Document Last updated 31-Jan-96. 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.
The new error handling stuff is (from the callers point of view) a much simplier interface:
void SSL_load_error_strings(void); unsigned long ERR_get_error(void); char *ERR_error_string(unsigned long error); void ERR_print_errors(FILE *fp);
So on application initialisation if you want non-numeric error string you simply call SSL_load_error_strings() and then use either of the two different interfaces for getting at the error information:
error_code=ERR_get_error(); string=ERR_error_string(error_code); OR ERR_print_errors(stderr);
All information that is likely to be of use on more than one SSL connection is now stored in a context structure. You specify the binding between an SSL connection and it's context when you call SSL_new(). The context can (and should) be shared between SSL connections.
SSL_CTX *SSL_CTX_new(void)
Before anything useful can be done on an SSL connection you must have created and initialise the context data structure for SSL state using SSL_CTX_new(). SSL_new() simply allocates the required SSL data structure and initialises all the right things.
SSL *SSL_new(SSL_CTX *ssl_ctx)
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"))
Once SSL_connect() has returned there are a number of functions that can be used to get hold of information about the server and the negotiated cipher.
Which of the ciphers was actually negotiated.
char *SSL_get_cipher(SSL *s)
To find out what ciphers are in common (and hence could have been negotiated)
char *SSL_get_shared_ciphers(SSL *s,char *buf,int bufsize)
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) char *X509_get_default_private_dir(void)
i.e. X509_get_default_cert_area() will return /usr/local/ssl by default.
These settings can also be changed by using the following environment variables:
SSL_CERT_DIR SSL_CERT_FILE
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:
Solaris 2.4 x86 - gcc 2.6.3 - gcc -O3 type 8 bytes 16 bytes 128 bytes 1024 bytes 8192 bytes md2 12.95k 18.19k 46.88k 60.92k 61.30k md5 226.03k 439.38k 1402.02k 2319.18k 2351.77k rc4 1040.14k 1116.69k 1205.12k 1212.14k 1196.87k cfb des 216.49k 221.09k 226.43k 226.79k 224.93k cbc des 233.05k 245.25k 256.75k 259.01k 249.32k ede3 des 90.06k 96.29k 98.77k 99.32k 99.30k cbc idea 165.36k 165.32k 171.28k 172.03k 171.01k rsa 512 bits 0.457s rsa 1024 bits 2.973s rsa 2048 bits 21.410s Solaris 2.3 sparc - gcc 2.5.7 - gcc -O3 -mv8 type 8 bytes 16 bytes 128 bytes 1024 bytes 8192 bytes md2 33.20k 44.80k 109.14k 133.83k 138.34k md5 514.25k 1039.74k 3234.35k 4966.93k 5238.34k rc4 2946.26k 3114.17k 2886.20k 3092.48k 3219.07k cfb des 665.60k 676.08k 687.70k 687.79k 680.30k cbc des 711.15k 740.48k 765.26k 760.15k 761.08k ede3 des 270.81k 280.86k 284.46k 285.94k 281.60k cbc idea 651.28k 657.08k 676.77k 674.86k 674.47k rsa 512 bits 0.101s rsa 1024 bits 0.585s rsa 2048 bits 4.237s Solaris 2.3 sparc - SC3.0 cc - cc -fast type 8 bytes 16 bytes 128 bytes 1024 bytes 8192 bytes md2 34.50k 46.64k 113.79k 139.29k 141.78k md5 479.50k 987.80k 3147.73k 4837.54k 5081.77k rc4 2366.90k 2677.52k 3041.88k 3107.74k 3003.73k cfb des 521.83k 537.12k 548.46k 542.61k 546.13k cbc des 555.03k 576.64k 603.85k 598.65k 600.75k ede3 des 202.03k 207.19k 211.22k 209.58k 210.26k cbc idea 581.17k 589.48k 603.56k 606.21k 604.78k md2 39.73k 54.04k 130.50k 162.47k 165.55k md5 478.68k 970.31k 3057.22k 4794.37k 5087.81k rc4 2615.54k 2733.65k 2891.73k 2922.70k 2795.73k cfb des 479.33k 495.55k 497.95k 498.94k 502.37k cbc des 509.65k 528.76k 547.06k 549.01k 553.51k ede3 des 180.58k 187.39k 190.84k 188.20k 187.67k cbc idea 561.00k 578.81k 591.07k 600.06k 598.10k HPUX 9 - cc - cc +O3 type 8 bytes 16 bytes 128 bytes 1024 bytes 8192 bytes md2 58.31k 76.77k 203.38k 232.73k 239.77k md5 380.53k 777.80k 2880.53k 4833.42k 5207.34k rc4 3455.43k 3742.07k 3775.95k 3827.38k 3841.96k cfb des 785.14k 808.87k 828.74k 812.76k 822.03k cbc des 842.67k 923.14k 996.71k 1026.41k 1015.70k ede3 des 370.38k 374.39k 400.43k 390.04k 390.92k cbc idea 286.95k 286.86k 297.07k 280.16k 301.51k HPUX 9 - gcc 2.7.0 - gcc -O3 -mpa-risc-1-1 (BAD) type 8 bytes 16 bytes 128 bytes 1024 bytes 8192 bytes md2 45.20k 61.45k 133.25k 181.69k 174.97k md5 395.22k 811.37k 3365.22k 5636.30k 6148.28k rc4 3407.66k 3768.79k 3701.22k 3663.92k 3808.96k cfb des 558.30k 588.51k 596.95k 601.76k 615.16k cbc des 627.24k 657.47k 714.88k 712.23k 724.22k ede3 des 248.47k 263.49k 274.00k 244.59k 261.69k cbc idea 583.64k 593.64k 624.32k 621.35k 628.35k DGUX - gcc 2.6.3 - gcc -O3 (BAD) type 8 bytes 16 bytes 128 bytes 1024 bytes 8192 bytes md2 18.39k 25.10k 60.63k 74.63k 76.46k md5 201.13k 400.35k 1710.60k 3260.01k 3667.54k rc4 1483.17k 1534.55k 1591.68k 1602.69k 1598.11k cfb des 507.36k 529.14k 552.97k 553.97k 553.30k cbc des 555.89k 619.98k 689.14k 695.98k 695.65k ede3 des 230.74k 243.56k 254.36k 255.83k 256.17k cbc idea 458.73k 488.09k 523.71k 528.79k 530.86k DEC Alpha - gcc 2.7.0 - gcc -O3 type 8 bytes 16 bytes 128 bytes 1024 bytes 8192 bytes md2 55.46k 75.96k 185.86k 228.01k 233.54k md5 407.02k 793.80k 3266.90k 5732.35k 6307.38k rc4 3379.32k 3513.16k 3637.21k 3653.63k 3604.48k cfb des 845.70k 887.00k 925.53k 930.82k 925.70k cbc des 888.97k 974.52k 1075.80k 1097.00k 1092.88k ede3 des 366.57k 386.89k 402.22k 404.48k 404.14k cbc idea 683.40k 697.03k 729.17k 733.87k 735.91k rsa 512 bits 0.048s rsa 1024 bits 0.279s rsa 2048 bits 1.900s IRIX 5.3 r4400 200mhz - gcc 2.6.3 - gcc -O2 type 8 bytes 16 bytes 128 bytes 1024 bytes 8192 bytes md2 64.57k 87.03k 213.49k 261.34k 267.61k md5 784.47k 1509.64k 5466.85k 8371.29k 8961.55k rc4 5257.28k 5541.73k 5827.62k 5854.10k 5864.34k cfb des 1298.87k 1333.31k 1366.11k 1373.47k 1363.50k cbc des 1421.39k 1492.68k 1572.82k 1583.90k 1577.72k ede3 des 558.68k 572.53k 583.90k 585.63k 582.79k cbc idea 1197.72k 1218.11k 1265.38k 1274.16k 1275.53k rsa 512 bits 0.053s rsa 1024 bits 0.300s rsa 2048 bits 2.074s
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