Document Last updated 03-Jul-95. The documentation version number is 1.1.
The version of SSLeay at the time of writing was 0.4.2.
This documentation is Copyright Tim Hudson (tjh@mincom.oz.au). See the COPYRIGHT file for the usage and redistribution restrictions.
This document describes an implementation of the Secure Sockets Layer (SSL) protocol. This implementation will be refered to a SSLeay for simplicity.
This implementation was coded from scratch using only the publically available documentation of the various protocols by Eric Young eay@mincom.oz.au.
The initial prompting to tackle an SSL implementation, the alpha testing, SSL developer (i.e. Eric) hassling, and documentation was done by Tim Hudson tjh@mincom.oz.au.
This implementation has been used by Tim Hudson tjh@mincom.oz.au to add SSL support to the following:
Patch kits for each of these are stored in the same location (actually a separate directory) as this implementation of SSL. Also full source trees for most of these are available in the same location as people have had difficulty finding the same version of the source that I've patched.
The aims of the document are:
Refer to [1] for details of the SSL protocol. Refer to [2] for details of the location of this implementation.
The development and distribution of this code has nothing to do with Mincom Pty Ltd in any way whatsoever. Eric Young and Tim Hudson are currently employed by Mincom Pty Ltd.
The call interface is probably not the same as SSLREF but it shouldn't be too hard to put together a wrapper that makes this look the same. We would appreciate that anyone who does this emails the patch to us (or alternatively perhaps someone can put together a wrapper for SSLREF to make it look like this library).
This documentation is Copyright Tim Hudson (tjh@mincom.oz.au). See the COPYRIGHT file for the usage and redistribution restrictions.
Note: a nicely formatted postscript version of this document is included in the file SSLeay.doc-version.tar.gz in the same directory as the SSLeay source.
Note: the primary site for fetching the SSL applications code is ftp.psy.uq.oz.au, however I push the initial versions and other interesting stuff to ftp.bond.edu.au first as that is where I have best access.
The SSL Protocol is designed to provide privacy between two communicating applications (a client and a server). Second, the protocol is designed to authenticate the server, and optionally the client. SSL requires a reliable transport protocol (e.g. TCP) for data transmission and reception.
The advantage of the SSL Protocol is that it is "application protocol" independent. A "higher level" application protocol (e.g. HTTP, FTP, TELNET, etc.) can layer on top of the SSL Protocol transparently.
SSL is written in a portable manner with no major assumptions about the underlying environment (except for the fact that long must be at least 32 bits [this code works on 64 bit machines too])
It is intended that the following environments be supported:
SSL has been compiled and tested on the following platforms
See PORTING for the current list.
This implementation has triggered C compiler bugs on a number of platforms. We have worked around all those we have found so far at "normal" -O level optimisation. These bugs are documented with test programs in bugs/
The SSL interface itself is documented here ... the "best" approach is to read ssl/client.c and ssl/server.c to see what is done there (and perhaps also look at the patches done to SRA telnet). You will also need to read through the Certificates section.
All the keys and certificates used in SSL can be encoded via the following different mechanisms:
The corresponding C "constants" are:
The "prefered" encoding format is PEM.
Rather standard stuff here ... most functions return <=0 on error and set SSL_errno. If SSL_errno is set to SSL_R_ERRNO then you should check the system errno value as it contains the real details of the error. If you call SSL_error_string() then it returns SYSTEM_ERROR (lib4.0 returns SSL_ERRNO).
int SSL_errno char *SSL_error_string(int SSL_errno) char *SSL_error_func_string(int SSL_errno)
Note: you currently must include ssl_err.h to have access to the SSL_* error defines.
Note: the error interface (internally at least) is currently being totally reworked to make it more Windows NT and Windows DLL friendly so this stuff will change soon.
For the other libraries
int RSA_errno char *RSA_error_string(int RSA_errno); int X509_errno char *X509_error_string(int X509_errno); int PEM_errno char *PEM_error_string(int PEM_errno);
Note: you will have to include the appropriate header file to get access to the error defines for each of the above.
Before anything useful can be done on an SSL connection you must create and initialise the data structure that records SSL state. SSL_new() simply allocates the required SSL data structure and initialises all the right things.
SSL *SSL_new(void)
If you wish to remove all allocated memory for a given SSL connection
void SSL_free(SSL *s)
You must register a callback via PEM_set_getkey_callback() if you do not wish to be prompted for a password on /dev/tty when the pass phrase is required when loading the key file if it is stored in PEM format with encryption enabled. Note that this callback will be invoked prior to the call to SSL_use_RSAPrivateKey() returning.
int SSL_use_RSAPrivateKey(SSL *s, RSA *key)
See PEM_read_RSA() for the interface for loading.
int SSL_use_RSAPrivateKey_file(SSL *s, char *file,int type) int SSL_use_RSAPrivateKey_fp(SSL *s, FILE *fp,int type) int PEM_set_getkey_callback(int (*callback)(char *buf,int len))
callback is passed a buffer into which is can store the value of the key up to len bytes. The length of the key must be returned. On error return -1.
The server must have a certificate. The client can (and probably should) have a certificate.
int SSL_use_certificate(SSL *s, X509 *cert)
See PEM_read_X590() for the interface for loading.
int SSL_use_certificate_file(SSL *s, char *file, int type) int SSL_use_certificate_fp(SSL *s, FILE *fp, int type)
See the Certificate Verification Process section as that describes this function in more detail.
void SSL_set_verify(SSL *s,int mode, int (*callback)() )
To set the association between an SSL connection and the underlying file descriptor:
void SSL_set_fd(SSL *s, int fd)
By default, SSL does not read more data from the network than is requested. However if you are not using select() to determine the availability of data, you can get a significant throughput improvement by simply switch read-ahead on. See SSL_pending() for a mechanism for determining if there is more data available.
void SSL_set_read_ahead(SSL *s, int yes)
To find out the current setting of the read-ahead flag:
int SSL_get_read_ahead(SSL *s)
When using read-ahead mode you cannot rely on select() to determine if more data is available as SSL_read() may have already read data off the wire that has not been read by the caller (the caller will get this data returned in future calls to SSL_read()).
int SSL_pending(SSL *s)
To get the association between an SSL connection and the underlying file descriptor:
int SSL_get_fd(SSL *s)
int SSL_connect(SSL *s)
int SSL_accept(SSL *s)
int SSL_read(SSL *s,char *buf,int len)
int SSL_write(SSL *s,char *buf,int len)
Note: SSL_write() will not sent any data if len is less than or equal to 0.
int SSL_copy_session_id(SSL *to,SSL *from)
To make life easier in porting programs that use the stdio library interface tjh put the following together ... so you cannot blame eay for this one ;-)
void SSL_fprintf(SSL *s, char *format, ...)
int SSL_set_pref_cipher(SSL *s, char *str)
A colon separated list of cipher names as per the defines
The default preference sequence for cipher negotiation is:
It is probably a good idea to allow the user to override the setting of the preferred cipher via an environment variable. We have been standardising on using SSL_CIPHER for this purpose via the following:
SSL_set_pref_cipher(s,getenv("SSL_CIPHER"))
After a connection has been established (via SSL_connect()) you can find out which of the ciphers was actually negotiated.
char * SSL_get_cipher(SSL *s)
The values in rsa/location.h are accessible via the following functions.
char *X509_get_default_cert_area(void) char *X509_get_default_cert_dir(void) char *X509_get_default_cert_file(void) char *X509_get_default_cert_dir_env(void) char *X509_get_default_cert_file_env(void)
i.e. X509_get_default_cert_area() will return /usr/local/ssl by default.
The basic decision that has to be made is whether or not you are going to transparently layer SSL on top of an existing protocol/application or if you are going to dynamically negotiate SSL using whatever mechanisms already exist in the protocol that you are extending. The authors have talking the approach of doing both where the existing protocol supported such a negotiation model.
Both telnet and ftp have been extended in the past to support additional authentication models. See RFC1409 for TELNET and IETF ftpsec for FTP so it is only logical to use the existing mechanism for these particular programs.
/* create an SSL structure */ con=(SSL *)SSL_new(); - do normal socket(), [bind()] connect() /* give it a file descriptor to use */ SSL_set_fd(con,s); /* do connection */ SSL_connect(con); - then use SSL_read() and SSL_write() rather than read() and write() e.g. SSL_write(con,"bye\n",4); /* start reading and writting */
con=(SSL *)SSL_new(); - do normal socket(), bind(), listen(), accept() SSL_set_fd(con,s); /* specify private key */ SSL_use_RSAPrivateKey(con,"server.rsa"); /* specify certificate */ SSL_use_certificate(con,"server.cert"); SSL_accept(con); - then use SSL_read() and SSL_write() rather than read() and write() e.g. SSL_read(con,buf,1024); for the client example this will return the 4 bytes written "bye\n" (possibly in multiple packets)
In order to have a working implementation of SSL a number of components are required.
This implementation of SSL is structured as per:
des/ Eric Young's libdes DES library rsa/ RSA and X509 stuff md/ message digest things (md2, md5) rc4/ rc4 implementation lhash/ hashing library ssl/ SSL itself idea/ IDEA
There is a top level Makefile that has the usual targets of all, clean, tags, tar, and install. By default, this implementation expects to be installed in /usr/local/ssl.
Note: there are a number of compile options that define what is built into the library and which RSA routines are used - you should see the documentation (and the Makefile) for SSLeay for more details.
Note: the overheads in bytes per block for supported encryption modes are different and are indicated beside each mode in terms of the header and fixed SSL header and any padding required.
The following are currently supported:
RC4-MD5 2 + 16 + N EXP-RC4-MD5 2 + 16 + N CBC-DES-MD5 3 + 16 + ( (N+7) / 8 ) * 8 CBC-IDEA-MD5 3 + 16 + ( (N+7) / 8 ) * 8 CBC3-DES-MD5 3 + 16 + ( (N+7) / 8 ) * 8 CFB-DES-MD5 2 + N
Refer to SSL_set_pref_cipher() for details of the #defines that match the particular cipher.
The current timings for each of the machines we have had access to are listed in times/times along with the required support files to generate your own timing figures.
We really need to include details on the following:
However we do have figures for private key encryption and support files (including 512, 1024, 2048, 3072, and 4096 bit keys) are included in the times/ directory. The following is an indication of relative performance:
Times to do a private key encryption, done via the ../rsa/x509 -signkey test1024 <test.PEM LLONG stands for the LONGLONG variable being defined in rsa/bn.h 80486dx/50MHz Solaris 2.4 - gcc -O2 (gcc 2.6.3) Normal LLONG 512 0.77 0.52 1024 5.03 3.10 (4.86) 2048 37.81 22.11 3072 73.75 RS6000/??? AIX 3.2 - cc -O (LLONG generate bad code) Normal 512 0.48 1024 2.91 2048 20.92 Sparc 10 Solaris 2.3 - gcc -O2 (gcc 2.6.3) / cc -fast (SC3.0) gcc gccLLONG cc ccLLONG 512 0.60 0.43 0.24 0.33 (0.57) ( 0.22) 1024 4.25 2.89 1.52 2.15 (4.15) ( 1.45) 2048 31.95 21.74 10.86 15.95 (10.32) 3072 36.22 DGUX 8500/88110 gcc -O2 (gcc 2.5.7) Normal LLONG 512 0.20 0.25 ( 0.19) 1024 1.19 1.63 ( 1.11) 2048 8.43 11.86 ( 7.86) 3072 27.96 33.66 SGI challange IRIX 5.3 (200mhz MIPS R4400) cc -O2 Normal LLONG gcc gccLLONG 512 0.11 0.13 0.06 1024 0.72 0.88 0.32 2048 5.29 6.46 4.93 2.22 3072 17.76 21.68 7.27 4096 41.78 16.93 HP-UX 9000/887 HPUX 9.04 cc +O4 / gcc -O2 (gcc 2.5.7) cc gcc gccLLONG 512 0.44 0.14 0.09 1024 3.21 0.88 0.48
2048 24.45 6.30 3.17 3072 21.05 10.44 4096 24.17 DEC Alpha OSF1 V3.0 cc -O2 (64bit) (LLONG generates bad code) 64bit 32bit 512 0.05 0.16 1024 0.31 1.20 2048 2.18 8.85 3072 7.15 29.93 4096 16.78
For the exact details you need to refer to the file COPYRIGHT in the top-level directory.
Basically, this implementation of SSL is being distributed under a slightly modified version of the UCB license. Attribution is mandatory. Commercial usage is permitted.
The license and distribution terms for any publically available version or derivative of this code cannot be changed. i.e. this code cannot simply be copied and put under another distrubution license [including the GNU Public License.]
The reason behind this being stated in this direct manner is past experience in code simply being copied and the attribution removed from it and then being distributed as part of other packages. This implementation was a non-trivial and unpaid effort.
We would appreciate feedback on any use of this implementation in either, public domain, shareware or commercial software.
Free licenses for commercial products using this library would naturally be greatly appreciated; however there is no legal requirement to do so.
Donations of almost any form to the author(s) will naturally be gratefully accepted and may even result in you joining our Christmas card list ;-)
Given the amount of effort that has been put into this implementation by the authors, any extensions or bug fixes should be forwarded to ssl-bugs@mincom.oz.au.
The majordomo based mailing list for discussions of this implementation is ssl-users@mincom.oz.au and can be joined by sending email to ssl-users-request@mincom.oz.au which will forward instructions for using the majordomo varient factotum that manages these lists.
Both the server and the client can validate each other. The currently shipping Netscape client authenticates any server that it connects to by checking that the certificate offered has been either obtained from Netscape or RSA Data Security Inc.
The current list of certificates are available directly from Netscape and include:
In order for a server implementation based on this implementation (perhaps using the patches to NCSA httpd version 1.3) to work with the current Netscape client, all that should be required is a certificate signed by one of the above trusted list. If you do not have a certificate signed by one of the above then the current version of the Netscape browser will not work with the patched NCSA httpd server.
If you do have a signed key then the patches I've done to NCSA httpd 1.3 work with the current version of SSLeay according to reliable reports.
The authors have been unable to test this functionality as we do not have such a key.
The patches to NCSA Mosaic version 2.5, however mean that it will connect to Netscape servers (and naturally to the patched NCSA httpd) using https. This has been tested. Currently we do not bother to authenticate the server (in what we have released) as for our purposes this is not required during testing (one extra function call will enable this in the code however you will need to figure out how you are going to manage certificate issuing before you do this).
How do we secure the private key of the user? It must be encrypted as access to it is equivalent to access to the plaintext version of a password. Read the PEM and PGP FAQs for a clear discussion of this. Currently we encrypt the PEM format of the key with a pass phrase using DES.
How do we set things up so that servers and clients can cross-authenticate without ending up with servers and clients that will not communicate across logical security zones? This is one of the unresolved challenges for SSL and other proposed commercial Internet security protocols.
SSL is the answer to a number of problems. It should enable most applications to be adapted with little effort to be able to run across non-trusted networks in a secure manner.
A reference implementation (known as SSLREF) is available free of charge for non commercial use for US residents from Netscape. A commercial license for SSLREF is also available from Netscape.
This implementation enables those of us who are not blessed with being US residents to participate in the use of and development of SSL enabled applications. It should also end some of the apparent reluctance to adopt SSL now that it is more freely available.
The key attributes of SSL from the point of view of the authors of this distribution:
There are lots of things in common here that should be looked at
PEM and PGP style tools layered on top of this library are a logical step that is planned - and it is not all that much work; however both Eric and myself have been concentrating on other issues.
We intend to layer a kerberos-style security mechanism on top of this such that we can have secure machine to machine login without the requirement of a password exchange or requiring hosts to trust each other. This is a logical extension of the certificate management stuff. The basic outline is as follows:
It should be possible to implement an auto-pushed STREAMS module that provides transparent SSL support for all applications in any modern SVR4 based kernel. Implementation of this is left as an exercise for the reader :-)
Alternatively, for those environments that support pre-load libraries (e.g. SunOS 5.x), a wrapper to perform SSL is fairly straight forward to implement. The author of this document has already implemented SOCKS support in such a manner.
Certificate Handling Interface