| |
| Bundle of old SSLeay documentation files [OBSOLETE!] |
| |
| *** WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! *** |
| |
| OBSOLETE means that nothing in this document should be trusted. This |
| document is provided mostly for historical purposes (it wasn't even up |
| to date at the time SSLeay 0.8.1 was released) and as inspiration. If |
| you copy some snippet of code from this document, please _check_ that |
| it really is correct from all points of view. For example, you can |
| check with the other documents in this directory tree, or by comparing |
| with relevant parts of the include files. |
| |
| People have done the mistake of trusting what's written here. Please |
| don't do that. |
| |
| *** WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! *** |
| |
| |
| ==== readme ======================================================== |
| |
| This is the old 0.6.6 docuementation. Most of the cipher stuff is still |
| relevent but I'm working (very slowly) on new documentation. |
| The current version can be found online at |
| |
| http://www.cryptsoft.com/ssleay/doc |
| |
| ==== API.doc ======================================================== |
| |
| SSL - SSLv2/v3/v23 etc. |
| |
| BIO - methods and how they plug together |
| |
| MEM - memory allocation callback |
| |
| CRYPTO - locking for threads |
| |
| EVP - Ciphers/Digests/signatures |
| |
| RSA - methods |
| |
| X509 - certificate retrieval |
| |
| X509 - validation |
| |
| X509 - X509v3 extensions |
| |
| Objects - adding object identifiers |
| |
| ASN.1 - parsing |
| |
| PEM - parsing |
| |
| ==== ssl/readme ===================================================== |
| |
| 22 Jun 1996 |
| This file belongs in ../apps, but I'll leave it here because it deals |
| with SSL :-) It is rather dated but it gives you an idea of how |
| things work. |
| === |
| |
| 17 Jul 1995 |
| I have been changing things quite a bit and have not fully updated |
| this file, so take what you read with a grain of salt |
| eric |
| === |
| The s_client and s_server programs can be used to test SSL capable |
| IP/port addresses and the verification of the X509 certificates in use |
| by these services. I strongly advise having a look at the code to get |
| an idea of how to use the authentication under SSLeay. Any feedback |
| on changes and improvements would be greatly accepted. |
| |
| This file will probably be gibberish unless you have read |
| rfc1421, rfc1422, rfc1423 and rfc1424 which describe PEM |
| authentication. |
| |
| A Brief outline (and examples) how to use them to do so. |
| |
| NOTE: |
| The environment variable SSL_CIPER is used to specify the prefered |
| cipher to use, play around with setting it's value to combinations of |
| RC4-MD5, EXP-RC4-MD5, CBC-DES-MD5, CBC3-DES-MD5, CFB-DES-NULL |
| in a : separated list. |
| |
| This directory contains 3 X509 certificates which can be used by these programs. |
| client.pem: a file containing a certificate and private key to be used |
| by s_client. |
| server.pem :a file containing a certificate and private key to be used |
| by s_server. |
| eay1024.pem:the certificate used to sign client.pem and server.pem. |
| This would be your CA's certificate. There is also a link |
| from the file a8556381.0 to eay1024.PEM. The value a8556381 |
| is returned by 'x509 -hash -noout <eay1024.pem' and is the |
| value used by X509 verification routines to 'find' this |
| certificte when search a directory for it. |
| [the above is not true any more, the CA cert is |
| ../certs/testca.pem which is signed by ../certs/mincomca.pem] |
| |
| When testing the s_server, you may get |
| bind: Address already in use |
| errors. These indicate the port is still being held by the unix |
| kernel and you are going to have to wait for it to let go of it. If |
| this is the case, remember to use the port commands on the s_server and |
| s_client to talk on an alternative port. |
| |
| ===== |
| s_client. |
| This program can be used to connect to any IP/hostname:port that is |
| talking SSL. Once connected, it will attempt to authenticate the |
| certificate it was passed and if everything works as expected, a 2 |
| directional channel will be open. Any text typed will be sent to the |
| other end. type Q<cr> to exit. Flags are as follows. |
| -host arg : Arg is the host or IP address to connect to. |
| -port arg : Arg is the port to connect to (https is 443). |
| -verify arg : Turn on authentication of the server certificate. |
| : Arg specifies the 'depth', this will covered below. |
| -cert arg : The optional certificate to use. This certificate |
| : will be returned to the server if the server |
| : requests it for client authentication. |
| -key arg : The private key that matches the certificate |
| : specified by the -cert option. If this is not |
| : specified (but -cert is), the -cert file will be |
| : searched for the Private key. Both files are |
| : assumed to be in PEM format. |
| -CApath arg : When to look for certificates when 'verifying' the |
| : certificate from the server. |
| -CAfile arg : A file containing certificates to be used for |
| : 'verifying' the server certificate. |
| -reconnect : Once a connection has been made, drop it and |
| : reconnect with same session-id. This is for testing :-). |
| |
| The '-verify n' parameter specifies not only to verify the servers |
| certificate but to also only take notice of 'n' levels. The best way |
| to explain is to show via examples. |
| Given |
| s_server -cert server.PEM is running. |
| |
| s_client |
| CONNECTED |
| depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server |
| issuer= /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA |
| verify error:num=1:unable to get issuer certificate |
| verify return:1 |
| CIPHER is CBC-DES-MD5 |
| What has happened is that the 'SSLeay demo server' certificate's |
| issuer ('CA') could not be found but because verify is not on, we |
| don't care and the connection has been made anyway. It is now 'up' |
| using CBC-DES-MD5 mode. This is an unauthenticate secure channel. |
| You may not be talking to the right person but the data going to them |
| is encrypted. |
| |
| s_client -verify 0 |
| CONNECTED |
| depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server |
| issuer= /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA |
| verify error:num=1:unable to get issuer certificate |
| verify return:1 |
| CIPHER is CBC-DES-MD5 |
| We are 'verifying' but only to depth 0, so since the 'SSLeay demo server' |
| certificate passed the date and checksum, we are happy to proceed. |
| |
| s_client -verify 1 |
| CONNECTED |
| depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server |
| issuer= /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA |
| verify error:num=1:unable to get issuer certificate |
| verify return:0 |
| ERROR |
| verify error:unable to get issuer certificate |
| In this case we failed to make the connection because we could not |
| authenticate the certificate because we could not find the |
| 'CA' certificate. |
| |
| s_client -verify 1 -CAfile eay1024.PEM |
| CONNECTED |
| depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server |
| verify return:1 |
| depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA |
| verify return:1 |
| CIPHER is CBC-DES-MD5 |
| We loaded the certificates from the file eay1024.PEM. Everything |
| checked out and so we made the connection. |
| |
| s_client -verify 1 -CApath . |
| CONNECTED |
| depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server |
| verify return:1 |
| depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA |
| verify return:1 |
| CIPHER is CBC-DES-MD5 |
| We looked in out local directory for issuer certificates and 'found' |
| a8556381.0 and so everything is ok. |
| |
| It is worth noting that 'CA' is a self certified certificate. If you |
| are passed one of these, it will fail to 'verify' at depth 0 because |
| we need to lookup the certifier of a certificate from some information |
| that we trust and keep locally. |
| |
| SSL_CIPHER=CBC3-DES-MD5:RC4-MD5 |
| export SSL_CIPHER |
| s_client -verify 10 -CApath . -reconnect |
| CONNECTED |
| depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server |
| verify return:1 |
| depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA |
| verify return:1 |
| drop the connection and reconnect with the same session id |
| CIPHER is CBC3-DES-MD5 |
| This has done a full connection and then re-estabished it with the |
| same session id but a new socket. No RSA stuff occures on the second |
| connection. Note that we said we would prefer to use CBC3-DES-MD5 |
| encryption and so, since the server supports it, we are. |
| |
| ===== |
| s_server |
| This program accepts SSL connections on a specified port |
| Once connected, it will estabish an SSL connection and optionaly |
| attempt to authenticate the client. A 2 directional channel will be |
| open. Any text typed will be sent to the other end. Type Q<cr> to exit. |
| Flags are as follows. |
| -port arg : Arg is the port to listen on. |
| -verify arg : Turn on authentication of the client if they have a |
| : certificate. Arg specifies the 'depth'. |
| -Verify arg : Turn on authentication of the client. If they don't |
| : have a valid certificate, drop the connection. |
| -cert arg : The certificate to use. This certificate |
| : will be passed to the client. If it is not |
| : specified, it will default to server.PEM |
| -key arg : The private key that matches the certificate |
| : specified by the -cert option. If this is not |
| : specified (but -cert is), the -cert file will be |
| : searched for the Private key. Both files are |
| : assumed to be in PEM format. Default is server.PEM |
| -CApath arg : When to look for certificates when 'verifying' the |
| : certificate from the client. |
| -CAfile arg : A file containing certificates to be used for |
| : 'verifying' the client certificate. |
| |
| For the following 'demo' I will specify the s_server command and |
| the s_client command and then list the output from the s_server. |
| s_server |
| s_client |
| CONNECTED |
| CIPHER is CBC-DES-MD5 |
| Everything up and running |
| |
| s_server -verify 0 |
| s_client |
| CONNECTED |
| CIPHER is CBC-DES-MD5 |
| Ok since no certificate was returned and we don't care. |
| |
| s_server -verify 0 |
| ./s_client -cert client.PEM |
| CONNECTED |
| depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo client |
| issuer= /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA |
| verify error:num=1:unable to get issuer certificate |
| verify return:1 |
| CIPHER is CBC-DES-MD5 |
| Ok since we were only verifying to level 0 |
| |
| s_server -verify 4 |
| s_client -cert client.PEM |
| CONNECTED |
| depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo client |
| issuer= /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA |
| verify error:num=1:unable to get issuer certificate |
| verify return:0 |
| ERROR |
| verify error:unable to get issuer certificate |
| Bad because we could not authenticate the returned certificate. |
| |
| s_server -verify 4 -CApath . |
| s_client -cert client.PEM |
| CONNECTED |
| depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo client |
| verify return:1 |
| depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA |
| verify return:1 |
| CIPHER is CBC-DES-MD5 |
| Ok because we could authenticate the returned certificate :-). |
| |
| s_server -Verify 0 -CApath . |
| s_client |
| CONNECTED |
| ERROR |
| SSL error:function is:REQUEST_CERTIFICATE |
| :error is :client end did not return a certificate |
| Error because no certificate returned. |
| |
| s_server -Verify 4 -CApath . |
| s_client -cert client.PEM |
| CONNECTED |
| depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo client |
| verify return:1 |
| depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA |
| verify return:1 |
| CIPHER is CBC-DES-MD5 |
| Full authentication of the client. |
| |
| So in summary to do full authentication of both ends |
| s_server -Verify 9 -CApath . |
| s_client -cert client.PEM -CApath . -verify 9 |
| From the server side |
| CONNECTED |
| depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo client |
| verify return:1 |
| depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA |
| verify return:1 |
| CIPHER is CBC-DES-MD5 |
| From the client side |
| CONNECTED |
| depth=0 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=SSLeay demo server |
| verify return:1 |
| depth=1 /C=AU/SOP=QLD/O=Mincom Pty. Ltd./OU=CS/CN=CA |
| verify return:1 |
| CIPHER is CBC-DES-MD5 |
| |
| For general probing of the 'internet https' servers for the |
| distribution area, run |
| s_client -host www.netscape.com -port 443 -verify 4 -CApath ../rsa/hash |
| Then enter |
| GET / |
| and you should be talking to the https server on that host. |
| |
| www.rsa.com was refusing to respond to connections on 443 when I was |
| testing. |
| |
| have fun :-). |
| |
| eric |
| |
| ==== a_verify.doc ======================================================== |
| |
| From eay@mincom.com Fri Oct 4 18:29:06 1996 |
| Received: by orb.mincom.oz.au id AA29080 |
| (5.65c/IDA-1.4.4 for eay); Fri, 4 Oct 1996 08:29:07 +1000 |
| Date: Fri, 4 Oct 1996 08:29:06 +1000 (EST) |
| From: Eric Young <eay@mincom.oz.au> |
| X-Sender: eay@orb |
| To: wplatzer <wplatzer@iaik.tu-graz.ac.at> |
| Cc: Eric Young <eay@mincom.oz.au>, SSL Mailing List <ssl-users@mincom.com> |
| Subject: Re: Netscape's Public Key |
| In-Reply-To: <19961003134837.NTM0049@iaik.tu-graz.ac.at> |
| Message-Id: <Pine.SOL.3.91.961004081346.8018K-100000@orb> |
| Mime-Version: 1.0 |
| Content-Type: TEXT/PLAIN; charset=US-ASCII |
| Status: RO |
| X-Status: |
| |
| On Thu, 3 Oct 1996, wplatzer wrote: |
| > I get Public Key from Netscape (Gold 3.0b4), but cannot do anything |
| > with it... It looks like (asn1parse): |
| > |
| > 0:d=0 hl=3 l=180 cons: SEQUENCE |
| > 3:d=1 hl=2 l= 96 cons: SEQUENCE |
| > 5:d=2 hl=2 l= 92 cons: SEQUENCE |
| > 7:d=3 hl=2 l= 13 cons: SEQUENCE |
| > 9:d=4 hl=2 l= 9 prim: OBJECT :rsaEncryption |
| > 20:d=4 hl=2 l= 0 prim: NULL |
| > 22:d=3 hl=2 l= 75 prim: BIT STRING |
| > 99:d=2 hl=2 l= 0 prim: IA5STRING : |
| > 101:d=1 hl=2 l= 13 cons: SEQUENCE |
| > 103:d=2 hl=2 l= 9 prim: OBJECT :md5withRSAEncryption |
| > 114:d=2 hl=2 l= 0 prim: NULL |
| > 116:d=1 hl=2 l= 65 prim: BIT STRING |
| > |
| > The first BIT STRING is the public key and the second BIT STRING is |
| > the signature. |
| > But a public key consists of the public exponent and the modulus. Are |
| > both numbers in the first BIT STRING? |
| > Is there a document simply describing this coding stuff (checking |
| > signature, get the public key, etc.)? |
| |
| Minimal in SSLeay. If you want to see what the modulus and exponent are, |
| try asn1parse -offset 25 -length 75 <key.pem |
| asn1parse will currently stuff up on the 'length 75' part (fixed in next |
| release) but it will print the stuff. If you are after more |
| documentation on ASN.1, have a look at www.rsa.com and get their PKCS |
| documents, most of my initial work on SSLeay was done using them. |
| |
| As for SSLeay, |
| util/crypto.num and util/ssl.num are lists of all exported functions in |
| the library (but not macros :-(. |
| |
| The ones for extracting public keys from certificates and certificate |
| requests are EVP_PKEY * X509_REQ_extract_key(X509_REQ *req); |
| EVP_PKEY * X509_extract_key(X509 *x509); |
| |
| To verify a signature on a signed ASN.1 object |
| int X509_verify(X509 *a,EVP_PKEY *key); |
| int X509_REQ_verify(X509_REQ *a,EVP_PKEY *key); |
| int X509_CRL_verify(X509_CRL *a,EVP_PKEY *key); |
| int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *a,EVP_PKEY *key); |
| |
| I should mention that EVP_PKEY can be used to hold a public or a private key, |
| since for things like RSA and DSS, a public key is just a subset of what |
| is stored for the private key. |
| |
| To sign any of the above structures |
| |
| int X509_sign(X509 *a,EVP_PKEY *key,EVP_MD *md); |
| int X509_REQ_sign(X509_REQ *a,EVP_PKEY *key,EVP_MD *md); |
| int X509_CRL_sign(X509_CRL *a,EVP_PKEY *key,EVP_MD *md); |
| int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *a,EVP_PKEY *key,EVP_MD *md); |
| |
| where md is the message digest to sign with. |
| |
| There are all defined in x509.h and all the _sign and _verify functions are |
| actually macros to the ASN1_sign() and ASN1_verify() functions. |
| These functions will put the correct algorithm identifiers in the correct |
| places in the structures. |
| |
| eric |
| -- |
| Eric Young | BOOL is tri-state according to Bill Gates. |
| AARNet: eay@mincom.oz.au | RTFM Win32 GetMessage(). |
| |
| ==== x509 ======================================================= |
| |
| X509_verify() |
| X509_sign() |
| |
| X509_get_version() |
| X509_get_serialNumber() |
| X509_get_issuer() |
| X509_get_subject() |
| X509_get_notBefore() |
| X509_get_notAfter() |
| X509_get_pubkey() |
| |
| X509_set_version() |
| X509_set_serialNumber() |
| X509_set_issuer() |
| X509_set_subject() |
| X509_set_notBefore() |
| X509_set_notAfter() |
| X509_set_pubkey() |
| |
| X509_get_extensions() |
| X509_set_extensions() |
| |
| X509_EXTENSIONS_clear() |
| X509_EXTENSIONS_retrieve() |
| X509_EXTENSIONS_add() |
| X509_EXTENSIONS_delete() |
| |
| ==== x509 attribute ================================================ |
| |
| PKCS7 |
| STACK of X509_ATTRIBUTES |
| ASN1_OBJECT |
| STACK of ASN1_TYPE |
| |
| So it is |
| |
| p7.xa[].obj |
| p7.xa[].data[] |
| |
| get_obj_by_nid(STACK , nid) |
| get_num_by_nid(STACK , nid) |
| get_data_by_nid(STACK , nid, index) |
| |
| X509_ATTRIBUTE *X509_ATTRIBUTE_new(void ); |
| void X509_ATTRIBUTE_free(X509_ATTRIBUTE *a); |
| |
| X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **ex, |
| int nid, STACK *value); |
| |
| X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **ex, |
| int nid, STACK *value); |
| |
| int X509_ATTRIBUTE_set_object(X509_ATTRIBUTE *ex,ASN1_OBJECT *obj); |
| int X509_ATTRIBUTE_add_data(X509_ATTRIBUTE *ex, int index, |
| ASN1_TYPE *value); |
| |
| ASN1_OBJECT * X509_ATTRIBUTE_get_object(X509_ATTRIBUTE *ex); |
| int X509_ATTRIBUTE_get_num(X509_ATTRIBUTE *ne); |
| ASN1_TYPE * X509_ATTRIBUTE_get_data(X509_ATTRIBUTE *ne,int index); |
| |
| ASN1_TYPE * X509_ATTRIBUTE_get_data_by_NID(X509_ATTRIBUTE *ne, |
| ASN1_OBJECT *obj); |
| |
| X509_ATTRIBUTE *PKCS7_get_s_att_by_NID(PKCS7 *p7,int nid); |
| X509_ATTRIBUTE *PKCS7_get_u_att_by_NID(PKCS7 *p7,int nid); |
| |
| ==== x509 v3 ======================================================== |
| |
| The 'new' system. |
| |
| The X509_EXTENSION_METHOD includes extensions and attributes and/or names. |
| Basically everthing that can be added to an X509 with an OID identifying it. |
| |
| It operates via 2 methods per object id. |
| int a2i_XXX(X509 *x,char *str,int len); |
| int i2a_XXX(BIO *bp,X509 *x); |
| |
| The a2i_XXX function will add the object with a value converted from the |
| string into the X509. Len can be -1 in which case the length is calculated |
| via strlen(str). Applications can always use direct knowledge to load and |
| unload the relevent objects themselves. |
| |
| i2a_XXX will print to the passed BIO, a text representation of the |
| relevet object. Use a memory BIO if you want it printed to a buffer :-). |
| |
| X509_add_by_NID(X509 *x,int nid,char *str,int len); |
| X509_add_by_OBJ(X509 *x,ASN1_OBJECT *obj,char *str,int len); |
| |
| X509_print_by_name(BIO *bp,X509 *x); |
| X509_print_by_NID(BIO *bp,X509 *x); |
| X509_print_by_OBJ(BIO *bp,X509 *x); |
| |
| ==== verify ======================================================== |
| |
| X509_verify_cert_chain( |
| CERT_STORE *cert_store, |
| STACK /* X509 */ *certs, |
| int *verify_result, |
| int (*verify_error_callback)() |
| char *argument_to_callback, /* SSL */ |
| |
| app_verify_callback( |
| char *app_verify_arg, /* from SSL_CTX */ |
| STACK /* X509 */ *certs, |
| int *verify_result, |
| int (*verify_error_callback)() |
| SSL *s, |
| |
| int X509_verify_cert( |
| CERT_STORE *cert_store, |
| X509 *x509, |
| int *verify_result, |
| int (*verify_error_callback)(), |
| char *arg, |
| |
| ==== apps.doc ======================================================== |
| |
| The applications |
| |
| Ok, where to begin.... |
| In the begining, when SSLeay was small (April 1995), there |
| were but few applications, they did happily cohabit in |
| the one bin directory. Then over time, they did multiply and grow, |
| and they started to look like microsoft software; 500k to print 'hello world'. |
| A new approach was needed. They were coalessed into one 'Monolithic' |
| application, ssleay. This one program is composed of many programs that |
| can all be compiled independantly. |
| |
| ssleay has 3 modes of operation. |
| 1) If the ssleay binary has the name of one of its component programs, it |
| executes that program and then exits. This can be achieved by using hard or |
| symbolic links, or failing that, just renaming the binary. |
| 2) If the first argument to ssleay is the name of one of the component |
| programs, that program runs that program and then exits. |
| 3) If there are no arguments, ssleay enters a 'command' mode. Each line is |
| interpreted as a program name plus arguments. After each 'program' is run, |
| ssleay returns to the comand line. |
| |
| dgst - message digests |
| enc - encryption and base64 encoding |
| |
| ans1parse - 'pulls' appart ASN.1 encoded objects like certificates. |
| |
| dh - Diffle-Hellman parameter manipulation. |
| rsa - RSA manipulations. |
| crl - Certificate revokion list manipulations |
| x509 - X509 cert fiddles, including signing. |
| pkcs7 - pkcs7 manipulation, only DER versions right now. |
| |
| genrsa - generate an RSA private key. |
| gendh - Generate a set of Diffle-Hellman parameters. |
| req - Generate a PKCS#10 object, a certificate request. |
| |
| s_client - SSL client program |
| s_server - SSL server program |
| s_time - A SSL protocol timing program |
| s_mult - Another SSL server, but it multiplexes |
| connections. |
| s_filter - under development |
| |
| errstr - Convert SSLeay error numbers to strings. |
| ca - Sign certificate requests, and generate |
| certificate revokion lists |
| crl2pkcs7 - put a crl and certifcates into a pkcs7 object. |
| speed - Benchmark the ciphers. |
| verify - Check certificates |
| hashdir - under development |
| |
| [ there a now a few more options, play with the program to see what they |
| are ] |
| |
| ==== asn1.doc ======================================================== |
| |
| The ASN.1 Routines. |
| |
| ASN.1 is a specification for how to encode structured 'data' in binary form. |
| The approach I have take to the manipulation of structures and their encoding |
| into ASN.1 is as follows. |
| |
| For each distinct structure there are 4 function of the following form |
| TYPE *TYPE_new(void); |
| void TYPE_free(TYPE *); |
| TYPE *d2i_TYPE(TYPE **a,unsigned char **pp,long length); |
| long i2d_TYPE(TYPE *a,unsigned char **pp); /* CHECK RETURN VALUE */ |
| |
| where TYPE is the type of the 'object'. The TYPE that have these functions |
| can be in one of 2 forms, either the internal C malloc()ed data structure |
| or in the DER (a variant of ASN.1 encoding) binary encoding which is just |
| an array of unsigned bytes. The 'i2d' functions converts from the internal |
| form to the DER form and the 'd2i' functions convert from the DER form to |
| the internal form. |
| |
| The 'new' function returns a malloc()ed version of the structure with all |
| substructures either created or left as NULL pointers. For 'optional' |
| fields, they are normally left as NULL to indicate no value. For variable |
| size sub structures (often 'SET OF' or 'SEQUENCE OF' in ASN.1 syntax) the |
| STACK data type is used to hold the values. Have a read of stack.doc |
| and have a look at the relevant header files to see what I mean. If there |
| is an error while malloc()ing the structure, NULL is returned. |
| |
| The 'free' function will free() all the sub components of a particular |
| structure. If any of those sub components have been 'removed', replace |
| them with NULL pointers, the 'free' functions are tolerant of NULL fields. |
| |
| The 'd2i' function copies a binary representation into a C structure. It |
| operates as follows. 'a' is a pointer to a pointer to |
| the structure to populate, 'pp' is a pointer to a pointer to where the DER |
| byte string is located and 'length' is the length of the '*pp' data. |
| If there are no errors, a pointer to the populated structure is returned. |
| If there is an error, NULL is returned. Errors can occur because of |
| malloc() failures but normally they will be due to syntax errors in the DER |
| encoded data being parsed. It is also an error if there was an |
| attempt to read more that 'length' bytes from '*p'. If |
| everything works correctly, the value in '*p' is updated |
| to point at the location just beyond where the DER |
| structure was read from. In this way, chained calls to 'd2i' type |
| functions can be made, with the pointer into the 'data' array being |
| 'walked' along the input byte array. |
| Depending on the value passed for 'a', different things will be done. If |
| 'a' is NULL, a new structure will be malloc()ed and returned. If '*a' is |
| NULL, a new structure will be malloc()ed and put into '*a' and returned. |
| If '*a' is not NULL, the structure in '*a' will be populated, or in the |
| case of an error, free()ed and then returned. |
| Having these semantics means that a structure |
| can call a 'd2i' function to populate a field and if the field is currently |
| NULL, the structure will be created. |
| |
| The 'i2d' function type is used to copy a C structure to a byte array. |
| The parameter 'a' is the structure to convert and '*p' is where to put it. |
| As for the 'd2i' type structure, 'p' is updated to point after the last |
| byte written. If p is NULL, no data is written. The function also returns |
| the number of bytes written. Where this becomes useful is that if the |
| function is called with a NULL 'p' value, the length is returned. This can |
| then be used to malloc() an array of bytes and then the same function can |
| be recalled passing the malloced array to be written to. e.g. |
| |
| int len; |
| unsigned char *bytes,*p; |
| len=i2d_X509(x,NULL); /* get the size of the ASN1 encoding of 'x' */ |
| if ((bytes=(unsigned char *)malloc(len)) == NULL) |
| goto err; |
| p=bytes; |
| i2d_X509(x,&p); |
| |
| Please note that a new variable, 'p' was passed to i2d_X509. After the |
| call to i2d_X509 p has been incremented by len bytes. |
| |
| Now the reason for this functional organisation is that it allows nested |
| structures to be built up by calling these functions as required. There |
| are various macros used to help write the general 'i2d', 'd2i', 'new' and |
| 'free' functions. They are discussed in another file and would only be |
| used by some-one wanting to add new structures to the library. As you |
| might be able to guess, the process of writing ASN.1 files can be a bit CPU |
| expensive for complex structures. I'm willing to live with this since the |
| simpler library code make my life easier and hopefully most programs using |
| these routines will have their execution profiles dominated by cipher or |
| message digest routines. |
| What follows is a list of 'TYPE' values and the corresponding ASN.1 |
| structure and where it is used. |
| |
| TYPE ASN.1 |
| ASN1_INTEGER INTEGER |
| ASN1_BIT_STRING BIT STRING |
| ASN1_OCTET_STRING OCTET STRING |
| ASN1_OBJECT OBJECT IDENTIFIER |
| ASN1_PRINTABLESTRING PrintableString |
| ASN1_T61STRING T61String |
| ASN1_IA5STRING IA5String |
| ASN1_UTCTIME UTCTime |
| ASN1_TYPE Any of the above mentioned types plus SEQUENCE and SET |
| |
| Most of the above mentioned types are actualled stored in the |
| ASN1_BIT_STRING type and macros are used to differentiate between them. |
| The 3 types used are |
| |
| typedef struct asn1_object_st |
| { |
| /* both null if a dynamic ASN1_OBJECT, one is |
| * defined if a 'static' ASN1_OBJECT */ |
| char *sn,*ln; |
| int nid; |
| int length; |
| unsigned char *data; |
| } ASN1_OBJECT; |
| This is used to store ASN1 OBJECTS. Read 'objects.doc' for details ono |
| routines to manipulate this structure. 'sn' and 'ln' are used to hold text |
| strings that represent the object (short name and long or lower case name). |
| These are used by the 'OBJ' library. 'nid' is a number used by the OBJ |
| library to uniquely identify objects. The ASN1 routines will populate the |
| 'length' and 'data' fields which will contain the bit string representing |
| the object. |
| |
| typedef struct asn1_bit_string_st |
| { |
| int length; |
| int type; |
| unsigned char *data; |
| } ASN1_BIT_STRING; |
| This structure is used to hold all the other base ASN1 types except for |
| ASN1_UTCTIME (which is really just a 'char *'). Length is the number of |
| bytes held in data and type is the ASN1 type of the object (there is a list |
| in asn1.h). |
| |
| typedef struct asn1_type_st |
| { |
| int type; |
| union { |
| char *ptr; |
| ASN1_INTEGER * integer; |
| ASN1_BIT_STRING * bit_string; |
| ASN1_OCTET_STRING * octet_string; |
| ASN1_OBJECT * object; |
| ASN1_PRINTABLESTRING * printablestring; |
| ASN1_T61STRING * t61string; |
| ASN1_IA5STRING * ia5string; |
| ASN1_UTCTIME * utctime; |
| ASN1_BIT_STRING * set; |
| ASN1_BIT_STRING * sequence; |
| } value; |
| } ASN1_TYPE; |
| This structure is used in a few places when 'any' type of object can be |
| expected. |
| |
| X509 Certificate |
| X509_CINF CertificateInfo |
| X509_ALGOR AlgorithmIdentifier |
| X509_NAME Name |
| X509_NAME_ENTRY A single sub component of the name. |
| X509_VAL Validity |
| X509_PUBKEY SubjectPublicKeyInfo |
| The above mentioned types are declared in x509.h. They are all quite |
| straight forward except for the X509_NAME/X509_NAME_ENTRY pair. |
| A X509_NAME is a STACK (see stack.doc) of X509_NAME_ENTRY's. |
| typedef struct X509_name_entry_st |
| { |
| ASN1_OBJECT *object; |
| ASN1_BIT_STRING *value; |
| int set; |
| int size; /* temp variable */ |
| } X509_NAME_ENTRY; |
| The size is a temporary variable used by i2d_NAME and set is the set number |
| for the particular NAME_ENTRY. A X509_NAME is encoded as a sequence of |
| sequence of sets. Normally each set contains only a single item. |
| Sometimes it contains more. Normally throughout this library there will be |
| only one item per set. The set field contains the 'set' that this entry is |
| a member of. So if you have just created a X509_NAME structure and |
| populated it with X509_NAME_ENTRYs, you should then traverse the X509_NAME |
| (which is just a STACK) and set the 'set/' field to incrementing numbers. |
| For more details on why this is done, read the ASN.1 spec for Distinguished |
| Names. |
| |
| X509_REQ CertificateRequest |
| X509_REQ_INFO CertificateRequestInfo |
| These are used to hold certificate requests. |
| |
| X509_CRL CertificateRevocationList |
| These are used to hold a certificate revocation list |
| |
| RSAPrivateKey PrivateKeyInfo |
| RSAPublicKey PublicKeyInfo |
| Both these 'function groups' operate on 'RSA' structures (see rsa.doc). |
| The difference is that the RSAPublicKey operations only manipulate the m |
| and e fields in the RSA structure. |
| |
| DSAPrivateKey DSS private key |
| DSAPublicKey DSS public key |
| Both these 'function groups' operate on 'DSS' structures (see dsa.doc). |
| The difference is that the RSAPublicKey operations only manipulate the |
| XXX fields in the DSA structure. |
| |
| DHparams DHParameter |
| This is used to hold the p and g value for The Diffie-Hellman operation. |
| The function deal with the 'DH' strucure (see dh.doc). |
| |
| Now all of these function types can be used with several other functions to give |
| quite useful set of general manipulation routines. Normally one would |
| not uses these functions directly but use them via macros. |
| |
| char *ASN1_dup(int (*i2d)(),char *(*d2i)(),char *x); |
| 'x' is the input structure case to a 'char *', 'i2d' is the 'i2d_TYPE' |
| function for the type that 'x' is and d2i is the 'd2i_TYPE' function for the |
| type that 'x' is. As is obvious from the parameters, this function |
| duplicates the strucutre by transforming it into the DER form and then |
| re-loading it into a new strucutre and returning the new strucutre. This |
| is obviously a bit cpu intensive but when faced with a complex dynamic |
| structure this is the simplest programming approach. There are macros for |
| duplicating the major data types but is simple to add extras. |
| |
| char *ASN1_d2i_fp(char *(*new)(),char *(*d2i)(),FILE *fp,unsigned char **x); |
| 'x' is a pointer to a pointer of the 'desired type'. new and d2i are the |
| corresponding 'TYPE_new' and 'd2i_TYPE' functions for the type and 'fp' is |
| an open file pointer to read from. This function reads from 'fp' as much |
| data as it can and then uses 'd2i' to parse the bytes to load and return |
| the parsed strucutre in 'x' (if it was non-NULL) and to actually return the |
| strucutre. The behavior of 'x' is as per all the other d2i functions. |
| |
| char *ASN1_d2i_bio(char *(*new)(),char *(*d2i)(),BIO *fp,unsigned char **x); |
| The 'BIO' is the new IO type being used in SSLeay (see bio.doc). This |
| function is the same as ASN1_d2i_fp() except for the BIO argument. |
| ASN1_d2i_fp() actually calls this function. |
| |
| int ASN1_i2d_fp(int (*i2d)(),FILE *out,unsigned char *x); |
| 'x' is converted to bytes by 'i2d' and then written to 'out'. ASN1_i2d_fp |
| and ASN1_d2i_fp are not really symetric since ASN1_i2d_fp will read all |
| available data from the file pointer before parsing a single item while |
| ASN1_i2d_fp can be used to write a sequence of data objects. To read a |
| series of objects from a file I would sugest loading the file into a buffer |
| and calling the relevent 'd2i' functions. |
| |
| char *ASN1_d2i_bio(char *(*new)(),char *(*d2i)(),BIO *fp,unsigned char **x); |
| This function is the same as ASN1_i2d_fp() except for the BIO argument. |
| ASN1_i2d_fp() actually calls this function. |
| |
| char * PEM_ASN1_read(char *(*d2i)(),char *name,FILE *fp,char **x,int (*cb)()); |
| This function will read the next PEM encoded (base64) object of the same |
| type as 'x' (loaded by the d2i function). 'name' is the name that is in |
| the '-----BEGIN name-----' that designates the start of that object type. |
| If the data is encrypted, 'cb' will be called to prompt for a password. If |
| it is NULL a default function will be used to prompt from the password. |
| 'x' is delt with as per the standard 'd2i' function interface. This |
| function can be used to read a series of objects from a file. While any |
| data type can be encrypted (see PEM_ASN1_write) only RSA private keys tend |
| to be encrypted. |
| |
| char * PEM_ASN1_read_bio(char *(*d2i)(),char *name,BIO *fp, |
| char **x,int (*cb)()); |
| Same as PEM_ASN1_read() except using a BIO. This is called by |
| PEM_ASN1_read(). |
| |
| int PEM_ASN1_write(int (*i2d)(),char *name,FILE *fp,char *x,EVP_CIPHER *enc, |
| unsigned char *kstr,int klen,int (*callback)()); |
| |
| int PEM_ASN1_write_bio(int (*i2d)(),char *name,BIO *fp, |
| char *x,EVP_CIPHER *enc,unsigned char *kstr,int klen, |
| int (*callback)()); |
| |
| int ASN1_sign(int (*i2d)(), X509_ALGOR *algor1, X509_ALGOR *algor2, |
| ASN1_BIT_STRING *signature, char *data, RSA *rsa, EVP_MD *type); |
| int ASN1_verify(int (*i2d)(), X509_ALGOR *algor1, |
| ASN1_BIT_STRING *signature,char *data, RSA *rsa); |
| |
| int ASN1_BIT_STRING_cmp(ASN1_BIT_STRING *a, ASN1_BIT_STRING *b); |
| ASN1_BIT_STRING *ASN1_BIT_STRING_type_new(int type ); |
| |
| int ASN1_UTCTIME_check(ASN1_UTCTIME *a); |
| void ASN1_UTCTIME_print(BIO *fp,ASN1_UTCTIME *a); |
| ASN1_UTCTIME *ASN1_UTCTIME_dup(ASN1_UTCTIME *a); |
| |
| ASN1_BIT_STRING *d2i_asn1_print_type(ASN1_BIT_STRING **a,unsigned char **pp, |
| long length,int type); |
| |
| int i2d_ASN1_SET(STACK *a, unsigned char **pp, |
| int (*func)(), int ex_tag, int ex_class); |
| STACK * d2i_ASN1_SET(STACK **a, unsigned char **pp, long length, |
| char *(*func)(), int ex_tag, int ex_class); |
| |
| int i2a_ASN1_OBJECT(BIO *bp,ASN1_OBJECT *object); |
| int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a); |
| int a2i_ASN1_INTEGER(BIO *bp,ASN1_INTEGER *bs,char *buf,int size); |
| |
| int ASN1_INTEGER_set(ASN1_INTEGER *a, long v); |
| long ASN1_INTEGER_get(ASN1_INTEGER *a); |
| ASN1_INTEGER *BN_to_ASN1_INTEGER(BIGNUM *bn, ASN1_INTEGER *ai); |
| BIGNUM *ASN1_INTEGER_to_BN(ASN1_INTEGER *ai,BIGNUM *bn); |
| |
| /* given a string, return the correct type. Max is the maximum number |
| * of bytes to parse. It stops parsing when 'max' bytes have been |
| * processed or a '\0' is hit */ |
| int ASN1_PRINTABLE_type(unsigned char *s,int max); |
| |
| void ASN1_parse(BIO *fp,unsigned char *pp,long len); |
| |
| int i2d_ASN1_bytes(ASN1_BIT_STRING *a, unsigned char **pp, int tag, int class); |
| ASN1_BIT_STRING *d2i_ASN1_bytes(ASN1_OCTET_STRING **a, unsigned char **pp, |
| long length, int Ptag, int Pclass); |
| |
| /* PARSING */ |
| int asn1_Finish(ASN1_CTX *c); |
| |
| /* SPECIALS */ |
| int ASN1_get_object(unsigned char **pp, long *plength, int *ptag, |
| int *pclass, long omax); |
| int ASN1_check_infinite_end(unsigned char **p,long len); |
| void ASN1_put_object(unsigned char **pp, int constructed, int length, |
| int tag, int class); |
| int ASN1_object_size(int constructed, int length, int tag); |
| |
| X509 * X509_get_cert(CERTIFICATE_CTX *ctx,X509_NAME * name,X509 *tmp_x509); |
| int X509_add_cert(CERTIFICATE_CTX *ctx,X509 *); |
| |
| char * X509_cert_verify_error_string(int n); |
| int X509_add_cert_file(CERTIFICATE_CTX *c,char *file, int type); |
| char * X509_gmtime (char *s, long adj); |
| int X509_add_cert_dir (CERTIFICATE_CTX *c,char *dir, int type); |
| int X509_load_verify_locations (CERTIFICATE_CTX *ctx, |
| char *file_env, char *dir_env); |
| int X509_set_default_verify_paths(CERTIFICATE_CTX *cts); |
| X509 * X509_new_D2i_X509(int len, unsigned char *p); |
| 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 ); |
| X509_REQ *X509_X509_TO_req(X509 *x, RSA *rsa); |
| int X509_cert_verify(CERTIFICATE_CTX *ctx,X509 *xs, int (*cb)()); |
| |
| CERTIFICATE_CTX *CERTIFICATE_CTX_new(); |
| void CERTIFICATE_CTX_free(CERTIFICATE_CTX *c); |
| |
| void X509_NAME_print(BIO *fp, X509_NAME *name, int obase); |
| int X509_print_fp(FILE *fp,X509 *x); |
| int X509_print(BIO *fp,X509 *x); |
| |
| X509_INFO * X509_INFO_new(void); |
| void X509_INFO_free(X509_INFO *a); |
| |
| char * X509_NAME_oneline(X509_NAME *a); |
| |
| #define X509_verify(x,rsa) |
| #define X509_REQ_verify(x,rsa) |
| #define X509_CRL_verify(x,rsa) |
| |
| #define X509_sign(x,rsa,md) |
| #define X509_REQ_sign(x,rsa,md) |
| #define X509_CRL_sign(x,rsa,md) |
| |
| #define X509_dup(x509) |
| #define d2i_X509_fp(fp,x509) |
| #define i2d_X509_fp(fp,x509) |
| #define d2i_X509_bio(bp,x509) |
| #define i2d_X509_bio(bp,x509) |
| |
| #define X509_CRL_dup(crl) |
| #define d2i_X509_CRL_fp(fp,crl) |
| #define i2d_X509_CRL_fp(fp,crl) |
| #define d2i_X509_CRL_bio(bp,crl) |
| #define i2d_X509_CRL_bio(bp,crl) |
| |
| #define X509_REQ_dup(req) |
| #define d2i_X509_REQ_fp(fp,req) |
| #define i2d_X509_REQ_fp(fp,req) |
| #define d2i_X509_REQ_bio(bp,req) |
| #define i2d_X509_REQ_bio(bp,req) |
| |
| #define RSAPrivateKey_dup(rsa) |
| #define d2i_RSAPrivateKey_fp(fp,rsa) |
| #define i2d_RSAPrivateKey_fp(fp,rsa) |
| #define d2i_RSAPrivateKey_bio(bp,rsa) |
| #define i2d_RSAPrivateKey_bio(bp,rsa) |
| |
| #define X509_NAME_dup(xn) |
| #define X509_NAME_ENTRY_dup(ne) |
| |
| void X509_REQ_print_fp(FILE *fp,X509_REQ *req); |
| void X509_REQ_print(BIO *fp,X509_REQ *req); |
| |
| RSA *X509_REQ_extract_key(X509_REQ *req); |
| RSA *X509_extract_key(X509 *x509); |
| |
| int X509_issuer_and_serial_cmp(X509 *a, X509 *b); |
| unsigned long X509_issuer_and_serial_hash(X509 *a); |
| |
| X509_NAME * X509_get_issuer_name(X509 *a); |
| int X509_issuer_name_cmp(X509 *a, X509 *b); |
| unsigned long X509_issuer_name_hash(X509 *a); |
| |
| X509_NAME * X509_get_subject_name(X509 *a); |
| int X509_subject_name_cmp(X509 *a,X509 *b); |
| unsigned long X509_subject_name_hash(X509 *x); |
| |
| int X509_NAME_cmp (X509_NAME *a, X509_NAME *b); |
| unsigned long X509_NAME_hash(X509_NAME *x); |
| |
| |
| ==== bio.doc ======================================================== |
| |
| BIO Routines |
| |
| This documentation is rather sparse, you are probably best |
| off looking at the code for specific details. |
| |
| The BIO library is a IO abstraction that was originally |
| inspired by the need to have callbacks to perform IO to FILE |
| pointers when using Windows 3.1 DLLs. There are two types |
| of BIO; a source/sink type and a filter type. |
| The source/sink methods are as follows: |
| - BIO_s_mem() memory buffer - a read/write byte array that |
| grows until memory runs out :-). |
| - BIO_s_file() FILE pointer - A wrapper around the normal |
| 'FILE *' commands, good for use with stdin/stdout. |
| - BIO_s_fd() File descriptor - A wrapper around file |
| descriptors, often used with pipes. |
| - BIO_s_socket() Socket - Used around sockets. It is |
| mostly in the Microsoft world that sockets are different |
| from file descriptors and there are all those ugly winsock |
| commands. |
| - BIO_s_null() Null - read nothing and write nothing.; a |
| useful endpoint for filter type BIO's specifically things |
| like the message digest BIO. |
| |
| The filter types are |
| - BIO_f_buffer() IO buffering - does output buffering into |
| larger chunks and performs input buffering to allow gets() |
| type functions. |
| - BIO_f_md() Message digest - a transparent filter that can |
| be asked to return a message digest for the data that has |
| passed through it. |
| - BIO_f_cipher() Encrypt or decrypt all data passing |
| through the filter. |
| - BIO_f_base64() Base64 decode on read and encode on write. |
| - BIO_f_ssl() A filter that performs SSL encryption on the |
| data sent through it. |
| |
| Base BIO functions. |
| The BIO library has a set of base functions that are |
| implemented for each particular type. Filter BIOs will |
| normally call the equivalent function on the source/sink BIO |
| that they are layered on top of after they have performed |
| some modification to the data stream. Multiple filter BIOs |
| can be 'push' into a stack of modifers, so to read from a |
| file, unbase64 it, then decrypt it, a BIO_f_cipher, |
| BIO_f_base64 and a BIO_s_file would probably be used. If a |
| sha-1 and md5 message digest needed to be generated, a stack |
| two BIO_f_md() BIOs and a BIO_s_null() BIO could be used. |
| The base functions are |
| - BIO *BIO_new(BIO_METHOD *type); Create a new BIO of type 'type'. |
| - int BIO_free(BIO *a); Free a BIO structure. Depending on |
| the configuration, this will free the underlying data |
| object for a source/sink BIO. |
| - int BIO_read(BIO *b, char *data, int len); Read upto 'len' |
| bytes into 'data'. |
| - int BIO_gets(BIO *bp,char *buf, int size); Depending on |
| the BIO, this can either be a 'get special' or a get one |
| line of data, as per fgets(); |
| - int BIO_write(BIO *b, char *data, int len); Write 'len' |
| bytes from 'data' to the 'b' BIO. |
| - int BIO_puts(BIO *bp,char *buf); Either a 'put special' or |
| a write null terminated string as per fputs(). |
| - long BIO_ctrl(BIO *bp,int cmd,long larg,char *parg); A |
| control function which is used to manipulate the BIO |
| structure and modify it's state and or report on it. This |
| function is just about never used directly, rather it |
| should be used in conjunction with BIO_METHOD specific |
| macros. |
| - BIO *BIO_push(BIO *new_top, BIO *old); new_top is apped to the |
| top of the 'old' BIO list. new_top should be a filter BIO. |
| All writes will go through 'new_top' first and last on read. |
| 'old' is returned. |
| - BIO *BIO_pop(BIO *bio); the new topmost BIO is returned, NULL if |
| there are no more. |
| |
| If a particular low level BIO method is not supported |
| (normally BIO_gets()), -2 will be returned if that method is |
| called. Otherwise the IO methods (read, write, gets, puts) |
| will return the number of bytes read or written, and 0 or -1 |
| for error (or end of input). For the -1 case, |
| BIO_should_retry(bio) can be called to determine if it was a |
| genuine error or a temporary problem. -2 will also be |
| returned if the BIO has not been initalised yet, in all |
| cases, the correct error codes are set (accessible via the |
| ERR library). |
| |
| |
| The following functions are convenience functions: |
| - int BIO_printf(BIO *bio, char * format, ..); printf but |
| to a BIO handle. |
| - long BIO_ctrl_int(BIO *bp,int cmd,long larg,int iarg); a |
| convenience function to allow a different argument types |
| to be passed to BIO_ctrl(). |
| - int BIO_dump(BIO *b,char *bytes,int len); output 'len' |
| bytes from 'bytes' in a hex dump debug format. |
| - long BIO_debug_callback(BIO *bio, int cmd, char *argp, int |
| argi, long argl, long ret) - a default debug BIO callback, |
| this is mentioned below. To use this one normally has to |
| use the BIO_set_callback_arg() function to assign an |
| output BIO for the callback to use. |
| - BIO *BIO_find_type(BIO *bio,int type); when there is a 'stack' |
| of BIOs, this function scan the list and returns the first |
| that is of type 'type', as listed in buffer.h under BIO_TYPE_XXX. |
| - void BIO_free_all(BIO *bio); Free the bio and all other BIOs |
| in the list. It walks the bio->next_bio list. |
| |
| |
| |
| Extra commands are normally implemented as macros calling BIO_ctrl(). |
| - BIO_number_read(BIO *bio) - the number of bytes processed |
| by BIO_read(bio,.). |
| - BIO_number_written(BIO *bio) - the number of bytes written |
| by BIO_write(bio,.). |
| - BIO_reset(BIO *bio) - 'reset' the BIO. |
| - BIO_eof(BIO *bio) - non zero if we are at the current end |
| of input. |
| - BIO_set_close(BIO *bio, int close_flag) - set the close flag. |
| - BIO_get_close(BIO *bio) - return the close flag. |
| BIO_pending(BIO *bio) - return the number of bytes waiting |
| to be read (normally buffered internally). |
| - BIO_flush(BIO *bio) - output any data waiting to be output. |
| - BIO_should_retry(BIO *io) - after a BIO_read/BIO_write |
| operation returns 0 or -1, a call to this function will |
| return non zero if you should retry the call later (this |
| is for non-blocking IO). |
| - BIO_should_read(BIO *io) - we should retry when data can |
| be read. |
| - BIO_should_write(BIO *io) - we should retry when data can |
| be written. |
| - BIO_method_name(BIO *io) - return a string for the method name. |
| - BIO_method_type(BIO *io) - return the unique ID of the BIO method. |
| - BIO_set_callback(BIO *io, long (*callback)(BIO *io, int |
| cmd, char *argp, int argi, long argl, long ret); - sets |
| the debug callback. |
| - BIO_get_callback(BIO *io) - return the assigned function |
| as mentioned above. |
| - BIO_set_callback_arg(BIO *io, char *arg) - assign some |
| data against the BIO. This is normally used by the debug |
| callback but could in reality be used for anything. To |
| get an idea of how all this works, have a look at the code |
| in the default debug callback mentioned above. The |
| callback can modify the return values. |
| |
| Details of the BIO_METHOD structure. |
| typedef struct bio_method_st |
| { |
| int type; |
| char *name; |
| int (*bwrite)(); |
| int (*bread)(); |
| int (*bputs)(); |
| int (*bgets)(); |
| long (*ctrl)(); |
| int (*create)(); |
| int (*destroy)(); |
| } BIO_METHOD; |
| |
| The 'type' is the numeric type of the BIO, these are listed in buffer.h; |
| 'Name' is a textual representation of the BIO 'type'. |
| The 7 function pointers point to the respective function |
| methods, some of which can be NULL if not implemented. |
| The BIO structure |
| typedef struct bio_st |
| { |
| BIO_METHOD *method; |
| long (*callback)(BIO * bio, int mode, char *argp, int |
| argi, long argl, long ret); |
| char *cb_arg; /* first argument for the callback */ |
| int init; |
| int shutdown; |
| int flags; /* extra storage */ |
| int num; |
| char *ptr; |
| struct bio_st *next_bio; /* used by filter BIOs */ |
| int references; |
| unsigned long num_read; |
| unsigned long num_write; |
| } BIO; |
| |
| - 'Method' is the BIO method. |
| - 'callback', when configured, is called before and after |
| each BIO method is called for that particular BIO. This |
| is intended primarily for debugging and of informational feedback. |
| - 'init' is 0 when the BIO can be used for operation. |
| Often, after a BIO is created, a number of operations may |
| need to be performed before it is available for use. An |
| example is for BIO_s_sock(). A socket needs to be |
| assigned to the BIO before it can be used. |
| - 'shutdown', this flag indicates if the underlying |
| communication primitive being used should be closed/freed |
| when the BIO is closed. |
| - 'flags' is used to hold extra state. It is primarily used |
| to hold information about why a non-blocking operation |
| failed and to record startup protocol information for the |
| SSL BIO. |
| - 'num' and 'ptr' are used to hold instance specific state |
| like file descriptors or local data structures. |
| - 'next_bio' is used by filter BIOs to hold the pointer of the |
| next BIO in the chain. written data is sent to this BIO and |
| data read is taken from it. |
| - 'references' is used to indicate the number of pointers to |
| this structure. This needs to be '1' before a call to |
| BIO_free() is made if the BIO_free() function is to |
| actually free() the structure, otherwise the reference |
| count is just decreased. The actual BIO subsystem does |
| not really use this functionality but it is useful when |
| used in more advanced applicaion. |
| - num_read and num_write are the total number of bytes |
| read/written via the 'read()' and 'write()' methods. |
| |
| BIO_ctrl operations. |
| The following is the list of standard commands passed as the |
| second parameter to BIO_ctrl() and should be supported by |
| all BIO as best as possible. Some are optional, some are |
| manditory, in any case, where is makes sense, a filter BIO |
| should pass such requests to underlying BIO's. |
| - BIO_CTRL_RESET - Reset the BIO back to an initial state. |
| - BIO_CTRL_EOF - return 0 if we are not at the end of input, |
| non 0 if we are. |
| - BIO_CTRL_INFO - BIO specific special command, normal |
| information return. |
| - BIO_CTRL_SET - set IO specific parameter. |
| - BIO_CTRL_GET - get IO specific parameter. |
| - BIO_CTRL_GET_CLOSE - Get the close on BIO_free() flag, one |
| of BIO_CLOSE or BIO_NOCLOSE. |
| - BIO_CTRL_SET_CLOSE - Set the close on BIO_free() flag. |
| - BIO_CTRL_PENDING - Return the number of bytes available |
| for instant reading |
| - BIO_CTRL_FLUSH - Output pending data, return number of bytes output. |
| - BIO_CTRL_SHOULD_RETRY - After an IO error (-1 returned) |
| should we 'retry' when IO is possible on the underlying IO object. |
| - BIO_CTRL_RETRY_TYPE - What kind of IO are we waiting on. |
| |
| The following command is a special BIO_s_file() specific option. |
| - BIO_CTRL_SET_FILENAME - specify a file to open for IO. |
| |
| The BIO_CTRL_RETRY_TYPE needs a little more explanation. |
| When performing non-blocking IO, or say reading on a memory |
| BIO, when no data is present (or cannot be written), |
| BIO_read() and/or BIO_write() will return -1. |
| BIO_should_retry(bio) will return true if this is due to an |
| IO condition rather than an actual error. In the case of |
| BIO_s_mem(), a read when there is no data will return -1 and |
| a should retry when there is more 'read' data. |
| The retry type is deduced from 2 macros |
| BIO_should_read(bio) and BIO_should_write(bio). |
| Now while it may appear obvious that a BIO_read() failure |
| should indicate that a retry should be performed when more |
| read data is available, this is often not true when using |
| things like an SSL BIO. During the SSL protocol startup |
| multiple reads and writes are performed, triggered by any |
| SSL_read or SSL_write. |
| So to write code that will transparently handle either a |
| socket or SSL BIO, |
| i=BIO_read(bio,..) |
| if (I == -1) |
| { |
| if (BIO_should_retry(bio)) |
| { |
| if (BIO_should_read(bio)) |
| { |
| /* call us again when BIO can be read */ |
| } |
| if (BIO_should_write(bio)) |
| { |
| /* call us again when BIO can be written */ |
| } |
| } |
| } |
| |
| At this point in time only read and write conditions can be |
| used but in the future I can see the situation for other |
| conditions, specifically with SSL there could be a condition |
| of a X509 certificate lookup taking place and so the non- |
| blocking BIO_read would require a retry when the certificate |
| lookup subsystem has finished it's lookup. This is all |
| makes more sense and is easy to use in a event loop type |
| setup. |
| When using the SSL BIO, either SSL_read() or SSL_write()s |
| can be called during the protocol startup and things will |
| still work correctly. |
| The nice aspect of the use of the BIO_should_retry() macro |
| is that all the errno codes that indicate a non-fatal error |
| are encapsulated in one place. The Windows specific error |
| codes and WSAGetLastError() calls are also hidden from the |
| application. |
| |
| Notes on each BIO method. |
| Normally buffer.h is just required but depending on the |
| BIO_METHOD, ssl.h or evp.h will also be required. |
| |
| BIO_METHOD *BIO_s_mem(void); |
| - BIO_set_mem_buf(BIO *bio, BUF_MEM *bm, int close_flag) - |
| set the underlying BUF_MEM structure for the BIO to use. |
| - BIO_get_mem_ptr(BIO *bio, char **pp) - if pp is not NULL, |
| set it to point to the memory array and return the number |
| of bytes available. |
| A read/write BIO. Any data written is appended to the |
| memory array and any read is read from the front. This BIO |
| can be used for read/write at the same time. BIO_gets() is |
| supported in the fgets() sense. |
| BIO_CTRL_INFO can be used to retrieve pointers to the memory |
| buffer and it's length. |
| |
| BIO_METHOD *BIO_s_file(void); |
| - BIO_set_fp(BIO *bio, FILE *fp, int close_flag) - set 'FILE *' to use. |
| - BIO_get_fp(BIO *bio, FILE **fp) - get the 'FILE *' in use. |
| - BIO_read_filename(BIO *bio, char *name) - read from file. |
| - BIO_write_filename(BIO *bio, char *name) - write to file. |
| - BIO_append_filename(BIO *bio, char *name) - append to file. |
| This BIO sits over the normal system fread()/fgets() type |
| functions. Gets() is supported. This BIO in theory could be |
| used for read and write but it is best to think of each BIO |
| of this type as either a read or a write BIO, not both. |
| |
| BIO_METHOD *BIO_s_socket(void); |
| BIO_METHOD *BIO_s_fd(void); |
| - BIO_sock_should_retry(int i) - the underlying function |
| used to determine if a call should be retried; the |
| argument is the '0' or '-1' returned by the previous BIO |
| operation. |
| - BIO_fd_should_retry(int i) - same as the |
| - BIO_sock_should_retry() except that it is different internally. |
| - BIO_set_fd(BIO *bio, int fd, int close_flag) - set the |
| file descriptor to use |
| - BIO_get_fd(BIO *bio, int *fd) - get the file descriptor. |
| These two methods are very similar. Gets() is not |
| supported, if you want this functionality, put a |
| BIO_f_buffer() onto it. This BIO is bi-directional if the |
| underlying file descriptor is. This is normally the case |
| for sockets but not the case for stdio descriptors. |
| |
| BIO_METHOD *BIO_s_null(void); |
| Read and write as much data as you like, it all disappears |
| into this BIO. |
| |
| BIO_METHOD *BIO_f_buffer(void); |
| - BIO_get_buffer_num_lines(BIO *bio) - return the number of |
| complete lines in the buffer. |
| - BIO_set_buffer_size(BIO *bio, long size) - set the size of |
| the buffers. |
| This type performs input and output buffering. It performs |
| both at the same time. The size of the buffer can be set |
| via the set buffer size option. Data buffered for output is |
| only written when the buffer fills. |
| |
| BIO_METHOD *BIO_f_ssl(void); |
| - BIO_set_ssl(BIO *bio, SSL *ssl, int close_flag) - the SSL |
| structure to use. |
| - BIO_get_ssl(BIO *bio, SSL **ssl) - get the SSL structure |
| in use. |
| The SSL bio is a little different from normal BIOs because |
| the underlying SSL structure is a little different. A SSL |
| structure performs IO via a read and write BIO. These can |
| be different and are normally set via the |
| SSL_set_rbio()/SSL_set_wbio() calls. The SSL_set_fd() calls |
| are just wrappers that create socket BIOs and then call |
| SSL_set_bio() where the read and write BIOs are the same. |
| The BIO_push() operation makes the SSLs IO BIOs the same, so |
| make sure the BIO pushed is capable of two directional |
| traffic. If it is not, you will have to install the BIOs |
| via the more conventional SSL_set_bio() call. BIO_pop() will retrieve |
| the 'SSL read' BIO. |
| |
| BIO_METHOD *BIO_f_md(void); |
| - BIO_set_md(BIO *bio, EVP_MD *md) - set the message digest |
| to use. |
| - BIO_get_md(BIO *bio, EVP_MD **mdp) - return the digest |
| method in use in mdp, return 0 if not set yet. |
| - BIO_reset() reinitializes the digest (EVP_DigestInit()) |
| and passes the reset to the underlying BIOs. |
| All data read or written via BIO_read() or BIO_write() to |
| this BIO will be added to the calculated digest. This |
| implies that this BIO is only one directional. If read and |
| write operations are performed, two separate BIO_f_md() BIOs |
| are reuqired to generate digests on both the input and the |
| output. BIO_gets(BIO *bio, char *md, int size) will place the |
| generated digest into 'md' and return the number of bytes. |
| The EVP_MAX_MD_SIZE should probably be used to size the 'md' |
| array. Reading the digest will also reset it. |
| |
| BIO_METHOD *BIO_f_cipher(void); |
| - BIO_reset() reinitializes the cipher. |
| - BIO_flush() should be called when the last bytes have been |
| output to flush the final block of block ciphers. |
| - BIO_get_cipher_status(BIO *b), when called after the last |
| read from a cipher BIO, returns non-zero if the data |
| decrypted correctly, otherwise, 0. |
| - BIO_set_cipher(BIO *b, EVP_CIPHER *c, unsigned char *key, |
| unsigned char *iv, int encrypt) This function is used to |
| setup a cipher BIO. The length of key and iv are |
| specified by the choice of EVP_CIPHER. Encrypt is 1 to |
| encrypt and 0 to decrypt. |
| |
| BIO_METHOD *BIO_f_base64(void); |
| - BIO_flush() should be called when the last bytes have been output. |
| This BIO base64 encodes when writing and base64 decodes when |
| reading. It will scan the input until a suitable begin line |
| is found. After reading data, BIO_reset() will reset the |
| BIO to start scanning again. Do not mix reading and writing |
| on the same base64 BIO. It is meant as a single stream BIO. |
| |
| Directions type |
| both BIO_s_mem() |
| one/both BIO_s_file() |
| both BIO_s_fd() |
| both BIO_s_socket() |
| both BIO_s_null() |
| both BIO_f_buffer() |
| one BIO_f_md() |
| one BIO_f_cipher() |
| one BIO_f_base64() |
| both BIO_f_ssl() |
| |
| It is easy to mix one and two directional BIOs, all one has |
| to do is to keep two separate BIO pointers for reading and |
| writing and be careful about usage of underlying BIOs. The |
| SSL bio by it's very nature has to be two directional but |
| the BIO_push() command will push the one BIO into the SSL |
| BIO for both reading and writing. |
| |
| The best example program to look at is apps/enc.c and/or perhaps apps/dgst.c. |
| |
| |
| ==== blowfish.doc ======================================================== |
| |
| The Blowfish library. |
| |
| Blowfish is a block cipher that operates on 64bit (8 byte) quantities. It |
| uses variable size key, but 128bit (16 byte) key would normally be considered |
| good. It can be used in all the modes that DES can be used. This |
| library implements the ecb, cbc, cfb64, ofb64 modes. |
| |
| Blowfish is quite a bit faster that DES, and much faster than IDEA or |
| RC2. It is one of the faster block ciphers. |
| |
| For all calls that have an 'input' and 'output' variables, they can be the |
| same. |
| |
| This library requires the inclusion of 'blowfish.h'. |
| |
| All of the encryption functions take what is called an BF_KEY as an |
| argument. An BF_KEY is an expanded form of the Blowfish key. |
| For all modes of the Blowfish algorithm, the BF_KEY used for |
| decryption is the same one that was used for encryption. |
| |
| The define BF_ENCRYPT is passed to specify encryption for the functions |
| that require an encryption/decryption flag. BF_DECRYPT is passed to |
| specify decryption. |
| |
| Please note that any of the encryption modes specified in my DES library |
| could be used with Blowfish. I have only implemented ecb, cbc, cfb64 and |
| ofb64 for the following reasons. |
| - ecb is the basic Blowfish encryption. |
| - cbc is the normal 'chaining' form for block ciphers. |
| - cfb64 can be used to encrypt single characters, therefore input and output |
| do not need to be a multiple of 8. |
| - ofb64 is similar to cfb64 but is more like a stream cipher, not as |
| secure (not cipher feedback) but it does not have an encrypt/decrypt mode. |
| - If you want triple Blowfish, thats 384 bits of key and you must be totally |
| obsessed with security. Still, if you want it, it is simple enough to |
| copy the function from the DES library and change the des_encrypt to |
| BF_encrypt; an exercise left for the paranoid reader :-). |
| |
| The functions are as follows: |
| |
| void BF_set_key( |
| BF_KEY *ks; |
| int len; |
| unsigned char *key; |
| BF_set_key converts an 'len' byte key into a BF_KEY. |
| A 'ks' is an expanded form of the 'key' which is used to |
| perform actual encryption. It can be regenerated from the Blowfish key |
| so it only needs to be kept when encryption or decryption is about |
| to occur. Don't save or pass around BF_KEY's since they |
| are CPU architecture dependent, 'key's are not. Blowfish is an |
| interesting cipher in that it can be used with a variable length |
| key. 'len' is the length of 'key' to be used as the key. |
| A 'len' of 16 is recomended by me, but blowfish can use upto |
| 72 bytes. As a warning, blowfish has a very very slow set_key |
| function, it actually runs BF_encrypt 521 times. |
| |
| void BF_encrypt(unsigned long *data, BF_KEY *key); |
| void BF_decrypt(unsigned long *data, BF_KEY *key); |
| These are the Blowfish encryption function that gets called by just |
| about every other Blowfish routine in the library. You should not |
| use this function except to implement 'modes' of Blowfish. |
| I say this because the |
| functions that call this routine do the conversion from 'char *' to |
| long, and this needs to be done to make sure 'non-aligned' memory |
| access do not occur. |
| Data is a pointer to 2 unsigned long's and key is the |
| BF_KEY to use. |
| |
| void BF_ecb_encrypt( |
| unsigned char *in, |
| unsigned char *out, |
| BF_KEY *key, |
| int encrypt); |
| This is the basic Electronic Code Book form of Blowfish (in DES this |
| mode is called Electronic Code Book so I'm going to use the term |
| for blowfish as well. |
| Input is encrypted into output using the key represented by |
| key. Depending on the encrypt, encryption or |
| decryption occurs. Input is 8 bytes long and output is 8 bytes. |
| |
| void BF_cbc_encrypt( |
| unsigned char *in, |
| unsigned char *out, |
| long length, |
| BF_KEY *ks, |
| unsigned char *ivec, |
| int encrypt); |
| This routine implements Blowfish in Cipher Block Chaining mode. |
| Input, which should be a multiple of 8 bytes is encrypted |
| (or decrypted) to output which will also be a multiple of 8 bytes. |
| The number of bytes is in length (and from what I've said above, |
| should be a multiple of 8). If length is not a multiple of 8, bad |
| things will probably happen. ivec is the initialisation vector. |
| This function updates iv after each call so that it can be passed to |
| the next call to BF_cbc_encrypt(). |
| |
| void BF_cfb64_encrypt( |
| unsigned char *in, |
| unsigned char *out, |
| long length, |
| BF_KEY *schedule, |
| unsigned char *ivec, |
| int *num, |
| int encrypt); |
| This is one of the more useful functions in this Blowfish library, it |
| implements CFB mode of Blowfish with 64bit feedback. |
| This allows you to encrypt an arbitrary number of bytes, |
| you do not require 8 byte padding. Each call to this |
| routine will encrypt the input bytes to output and then update ivec |
| and num. Num contains 'how far' we are though ivec. |
| 'Encrypt' is used to indicate encryption or decryption. |
| CFB64 mode operates by using the cipher to generate a stream |
| of bytes which is used to encrypt the plain text. |
| The cipher text is then encrypted to generate the next 64 bits to |
| be xored (incrementally) with the next 64 bits of plain |
| text. As can be seen from this, to encrypt or decrypt, |
| the same 'cipher stream' needs to be generated but the way the next |
| block of data is gathered for encryption is different for |
| encryption and decryption. |
| |
| void BF_ofb64_encrypt( |
| unsigned char *in, |
| unsigned char *out, |
| long length, |
| BF_KEY *schedule, |
| unsigned char *ivec, |
| int *num); |
| This functions implements OFB mode of Blowfish with 64bit feedback. |
| This allows you to encrypt an arbitrary number of bytes, |
| you do not require 8 byte padding. Each call to this |
| routine will encrypt the input bytes to output and then update ivec |
| and num. Num contains 'how far' we are though ivec. |
| This is in effect a stream cipher, there is no encryption or |
| decryption mode. |
| |
| For reading passwords, I suggest using des_read_pw_string() from my DES library. |
| To generate a password from a text string, I suggest using MD5 (or MD2) to |
| produce a 16 byte message digest that can then be passed directly to |
| BF_set_key(). |
| |
| ===== |
| For more information about the specific Blowfish modes in this library |
| (ecb, cbc, cfb and ofb), read the section entitled 'Modes of DES' from the |
| documentation on my DES library. What is said about DES is directly |
| applicable for Blowfish. |
| |
| |
| ==== bn.doc ======================================================== |
| |
| The Big Number library. |
| |
| #include "bn.h" when using this library. |
| |
| This big number library was written for use in implementing the RSA and DH |
| public key encryption algorithms. As such, features such as negative |
| numbers have not been extensively tested but they should work as expected. |
| This library uses dynamic memory allocation for storing its data structures |
| and so there are no limit on the size of the numbers manipulated by these |
| routines but there is always the requirement to check return codes from |
| functions just in case a memory allocation error has occurred. |
| |
| The basic object in this library is a BIGNUM. It is used to hold a single |
| large integer. This type should be considered opaque and fields should not |
| be modified or accessed directly. |
| typedef struct bignum_st |
| { |
| int top; /* Index of last used d. */ |
| BN_ULONG *d; /* Pointer to an array of 'BITS2' bit chunks. */ |
| int max; /* Size of the d array. */ |
| int neg; |
| } BIGNUM; |
| The big number is stored in a malloced array of BN_ULONG's. A BN_ULONG can |
| be either 16, 32 or 64 bits in size, depending on the 'number of bits' |
| specified in bn.h. |
| The 'd' field is this array. 'max' is the size of the 'd' array that has |
| been allocated. 'top' is the 'last' entry being used, so for a value of 4, |
| bn.d[0]=4 and bn.top=1. 'neg' is 1 if the number is negative. |
| When a BIGNUM is '0', the 'd' field can be NULL and top == 0. |
| |
| Various routines in this library require the use of 'temporary' BIGNUM |
| variables during their execution. Due to the use of dynamic memory |
| allocation to create BIGNUMs being rather expensive when used in |
| conjunction with repeated subroutine calls, the BN_CTX structure is |
| used. This structure contains BN_CTX BIGNUMs. BN_CTX |
| is the maximum number of temporary BIGNUMs any publicly exported |
| function will use. |
| |
| #define BN_CTX 12 |
| typedef struct bignum_ctx |
| { |
| int tos; /* top of stack */ |
| BIGNUM *bn[BN_CTX]; /* The variables */ |
| } BN_CTX; |
| |
| The functions that follow have been grouped according to function. Most |
| arithmetic functions return a result in the first argument, sometimes this |
| first argument can also be an input parameter, sometimes it cannot. These |
| restrictions are documented. |
| |
| extern BIGNUM *BN_value_one; |
| There is one variable defined by this library, a BIGNUM which contains the |
| number 1. This variable is useful for use in comparisons and assignment. |
| |
| Get Size functions. |
| |
| int BN_num_bits(BIGNUM *a); |
| This function returns the size of 'a' in bits. |
| |
| int BN_num_bytes(BIGNUM *a); |
| This function (macro) returns the size of 'a' in bytes. |
| For conversion of BIGNUMs to byte streams, this is the number of |
| bytes the output string will occupy. If the output byte |
| format specifies that the 'top' bit indicates if the number is |
| signed, so an extra '0' byte is required if the top bit on a |
| positive number is being written, it is upto the application to |
| make this adjustment. Like I said at the start, I don't |
| really support negative numbers :-). |
| |
| Creation/Destruction routines. |
| |
| BIGNUM *BN_new(); |
| Return a new BIGNUM object. The number initially has a value of 0. If |
| there is an error, NULL is returned. |
| |
| void BN_free(BIGNUM *a); |
| Free()s a BIGNUM. |
| |
| void BN_clear(BIGNUM *a); |
| Sets 'a' to a value of 0 and also zeros all unused allocated |
| memory. This function is used to clear a variable of 'sensitive' |
| data that was held in it. |
| |
| void BN_clear_free(BIGNUM *a); |
| This function zeros the memory used by 'a' and then free()'s it. |
| This function should be used to BN_free() BIGNUMS that have held |
| sensitive numeric values like RSA private key values. Both this |
| function and BN_clear tend to only be used by RSA and DH routines. |
| |
| BN_CTX *BN_CTX_new(void); |
| Returns a new BN_CTX. NULL on error. |
| |
| void BN_CTX_free(BN_CTX *c); |
| Free a BN_CTX structure. The BIGNUMs in 'c' are BN_clear_free()ed. |
| |
| BIGNUM *bn_expand(BIGNUM *b, int bits); |
| This is an internal function that should not normally be used. It |
| ensures that 'b' has enough room for a 'bits' bit number. It is |
| mostly used by the various BIGNUM routines. If there is an error, |
| NULL is returned. if not, 'b' is returned. |
| |
| BIGNUM *BN_copy(BIGNUM *to, BIGNUM *from); |
| The 'from' is copied into 'to'. NULL is returned if there is an |
| error, otherwise 'to' is returned. |
| |
| BIGNUM *BN_dup(BIGNUM *a); |
| A new BIGNUM is created and returned containing the value of 'a'. |
| NULL is returned on error. |
| |
| Comparison and Test Functions. |
| |
| int BN_is_zero(BIGNUM *a) |
| Return 1 if 'a' is zero, else 0. |
| |
| int BN_is_one(a) |
| Return 1 is 'a' is one, else 0. |
| |
| int BN_is_word(a,w) |
| Return 1 if 'a' == w, else 0. 'w' is a BN_ULONG. |
| |
| int BN_cmp(BIGNUM *a, BIGNUM *b); |
| Return -1 if 'a' is less than 'b', 0 if 'a' and 'b' are the same |
| and 1 is 'a' is greater than 'b'. This is a signed comparison. |
| |
| int BN_ucmp(BIGNUM *a, BIGNUM *b); |
| This function is the same as BN_cmp except that the comparison |
| ignores the sign of the numbers. |
| |
| Arithmetic Functions |
| For all of these functions, 0 is returned if there is an error and 1 is |
| returned for success. The return value should always be checked. eg. |
| if (!BN_add(r,a,b)) goto err; |
| Unless explicitly mentioned, the 'return' value can be one of the |
| 'parameters' to the function. |
| |
| int BN_add(BIGNUM *r, BIGNUM *a, BIGNUM *b); |
| Add 'a' and 'b' and return the result in 'r'. This is r=a+b. |
| |
| int BN_sub(BIGNUM *r, BIGNUM *a, BIGNUM *b); |
| Subtract 'a' from 'b' and put the result in 'r'. This is r=a-b. |
| |
| int BN_lshift(BIGNUM *r, BIGNUM *a, int n); |
| Shift 'a' left by 'n' bits. This is r=a*(2^n). |
| |
| int BN_lshift1(BIGNUM *r, BIGNUM *a); |
| Shift 'a' left by 1 bit. This form is more efficient than |
| BN_lshift(r,a,1). This is r=a*2. |
| |
| int BN_rshift(BIGNUM *r, BIGNUM *a, int n); |
| Shift 'a' right by 'n' bits. This is r=int(a/(2^n)). |
| |
| int BN_rshift1(BIGNUM *r, BIGNUM *a); |
| Shift 'a' right by 1 bit. This form is more efficient than |
| BN_rshift(r,a,1). This is r=int(a/2). |
| |
| int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b); |
| Multiply a by b and return the result in 'r'. 'r' must not be |
| either 'a' or 'b'. It has to be a different BIGNUM. |
| This is r=a*b. |
| |
| int BN_sqr(BIGNUM *r, BIGNUM *a, BN_CTX *ctx); |
| Multiply a by a and return the result in 'r'. 'r' must not be |
| 'a'. This function is alot faster than BN_mul(r,a,a). This is r=a*a. |
| |
| int BN_div(BIGNUM *dv, BIGNUM *rem, BIGNUM *m, BIGNUM *d, BN_CTX *ctx); |
| Divide 'm' by 'd' and return the result in 'dv' and the remainder |
| in 'rem'. Either of 'dv' or 'rem' can be NULL in which case that |
| value is not returned. 'ctx' needs to be passed as a source of |
| temporary BIGNUM variables. |
| This is dv=int(m/d), rem=m%d. |
| |
| int BN_mod(BIGNUM *rem, BIGNUM *m, BIGNUM *d, BN_CTX *ctx); |
| Find the remainder of 'm' divided by 'd' and return it in 'rem'. |
| 'ctx' holds the temporary BIGNUMs required by this function. |
| This function is more efficient than BN_div(NULL,rem,m,d,ctx); |
| This is rem=m%d. |
| |
| int BN_mod_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *m,BN_CTX *ctx); |
| Multiply 'a' by 'b' and return the remainder when divided by 'm'. |
| 'ctx' holds the temporary BIGNUMs required by this function. |
| This is r=(a*b)%m. |
| |
| int BN_mod_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m,BN_CTX *ctx); |
| Raise 'a' to the 'p' power and return the remainder when divided by |
| 'm'. 'ctx' holds the temporary BIGNUMs required by this function. |
| This is r=(a^p)%m. |
| |
| int BN_reciprocal(BIGNUM *r, BIGNUM *m, BN_CTX *ctx); |
| Return the reciprocal of 'm'. 'ctx' holds the temporary variables |
| required. This function returns -1 on error, otherwise it returns |
| the number of bits 'r' is shifted left to make 'r' into an integer. |
| This number of bits shifted is required in BN_mod_mul_reciprocal(). |
| This is r=(1/m)<<(BN_num_bits(m)+1). |
| |
| int BN_mod_mul_reciprocal(BIGNUM *r, BIGNUM *x, BIGNUM *y, BIGNUM *m, |
| BIGNUM *i, int nb, BN_CTX *ctx); |
| This function is used to perform an efficient BN_mod_mul() |
| operation. If one is going to repeatedly perform BN_mod_mul() with |
| the same modulus is worth calculating the reciprocal of the modulus |
| and then using this function. This operation uses the fact that |
| a/b == a*r where r is the reciprocal of b. On modern computers |
| multiplication is very fast and big number division is very slow. |
| 'x' is multiplied by 'y' and then divided by 'm' and the remainder |
| is returned. 'i' is the reciprocal of 'm' and 'nb' is the number |
| of bits as returned from BN_reciprocal(). Normal usage is as follows. |
| bn=BN_reciprocal(i,m); |
| for (...) |
| { BN_mod_mul_reciprocal(r,x,y,m,i,bn,ctx); } |
| This is r=(x*y)%m. Internally it is approximately |
| r=(x*y)-m*(x*y/m) or r=(x*y)-m*((x*y*i) >> bn) |
| This function is used in BN_mod_exp() and BN_is_prime(). |
| |
| Assignment Operations |
| |
| int BN_one(BIGNUM *a) |
| Set 'a' to hold the value one. |
| This is a=1. |
| |
| int BN_zero(BIGNUM *a) |
| Set 'a' to hold the value zero. |
| This is a=0. |
| |
| int BN_set_word(BIGNUM *a, unsigned long w); |
| Set 'a' to hold the value of 'w'. 'w' is an unsigned long. |
| This is a=w. |
| |
| unsigned long BN_get_word(BIGNUM *a); |
| Returns 'a' in an unsigned long. Not remarkably, often 'a' will |
| be bigger than a word, in which case 0xffffffffL is returned. |
| |
| Word Operations |
| These functions are much more efficient that the normal bignum arithmetic |
| operations. |
| |
| BN_ULONG BN_mod_word(BIGNUM *a, unsigned long w); |
| Return the remainder of 'a' divided by 'w'. |
| This is return(a%w). |
| |
| int BN_add_word(BIGNUM *a, unsigned long w); |
| Add 'w' to 'a'. This function does not take the sign of 'a' into |
| account. This is a+=w; |
| |
| Bit operations. |
| |
| int BN_is_bit_set(BIGNUM *a, int n); |
| This function return 1 if bit 'n' is set in 'a' else 0. |
| |
| int BN_set_bit(BIGNUM *a, int n); |
| This function sets bit 'n' to 1 in 'a'. |
| This is a&= ~(1<<n); |
| |
| int BN_clear_bit(BIGNUM *a, int n); |
| This function sets bit 'n' to zero in 'a'. Return 0 if less |
| than 'n' bits in 'a' else 1. This is a&= ~(1<<n); |
| |
| int BN_mask_bits(BIGNUM *a, int n); |
| Truncate 'a' to n bits long. This is a&= ~((~0)<<n) |
| |
| Format conversion routines. |
| |
| BIGNUM *BN_bin2bn(unsigned char *s, int len,BIGNUM *ret); |
| This function converts 'len' bytes in 's' into a BIGNUM which |
| is put in 'ret'. If ret is NULL, a new BIGNUM is created. |
| Either this new BIGNUM or ret is returned. The number is |
| assumed to be in bigendian form in 's'. By this I mean that |
| to 'ret' is created as follows for 'len' == 5. |
| ret = s[0]*2^32 + s[1]*2^24 + s[2]*2^16 + s[3]*2^8 + s[4]; |
| This function cannot be used to convert negative numbers. It |
| is always assumed the number is positive. The application |
| needs to diddle the 'neg' field of th BIGNUM its self. |
| The better solution would be to save the numbers in ASN.1 format |
| since this is a defined standard for storing big numbers. |
| Look at the functions |
| |
| ASN1_INTEGER *BN_to_ASN1_INTEGER(BIGNUM *bn, ASN1_INTEGER *ai); |
| BIGNUM *ASN1_INTEGER_to_BN(ASN1_INTEGER *ai,BIGNUM *bn); |
| int i2d_ASN1_INTEGER(ASN1_INTEGER *a,unsigned char **pp); |
| ASN1_INTEGER *d2i_ASN1_INTEGER(ASN1_INTEGER **a,unsigned char **pp, |
| long length; |
| |
| int BN_bn2bin(BIGNUM *a, unsigned char *to); |
| This function converts 'a' to a byte string which is put into |
| 'to'. The representation is big-endian in that the most |
| significant byte of 'a' is put into to[0]. This function |
| returns the number of bytes used to hold 'a'. BN_num_bytes(a) |
| would return the same value and can be used to determine how |
| large 'to' needs to be. If the number is negative, this |
| information is lost. Since this library was written to |
| manipulate large positive integers, the inability to save and |
| restore them is not considered to be a problem by me :-). |
| As for BN_bin2bn(), look at the ASN.1 integer encoding funtions |
| for SSLeay. They use BN_bin2bn() and BN_bn2bin() internally. |
| |
| char *BN_bn2ascii(BIGNUM *a); |
| This function returns a malloc()ed string that contains the |
| ascii hexadecimal encoding of 'a'. The number is in bigendian |
| format with a '-' in front if the number is negative. |
| |
| int BN_ascii2bn(BIGNUM **bn, char *a); |
| The inverse of BN_bn2ascii. The function returns the number of |
| characters from 'a' were processed in generating a the bignum. |
| error is inticated by 0 being returned. The number is a |
| hex digit string, optionally with a leading '-'. If *bn |
| is null, a BIGNUM is created and returned via that variable. |
| |
| int BN_print_fp(FILE *fp, BIGNUM *a); |
| 'a' is printed to file pointer 'fp'. It is in the same format |
| that is output from BN_bn2ascii(). 0 is returned on error, |
| 1 if things are ok. |
| |
| int BN_print(BIO *bp, BIGNUM *a); |
| Same as BN_print except that the output is done to the SSLeay libraries |
| BIO routines. BN_print_fp() actually calls this function. |
| |
| Miscellaneous Routines. |
| |
| int BN_rand(BIGNUM *rnd, int bits, int top, int bottom); |
| This function returns in 'rnd' a random BIGNUM that is bits |
| long. If bottom is 1, the number returned is odd. If top is set, |
| the top 2 bits of the number are set. This is useful because if |
| this is set, 2 'n; bit numbers multiplied together will return a 2n |
| bit number. If top was not set, they could produce a 2n-1 bit |
| number. |
| |
| BIGNUM *BN_mod_inverse(BIGNUM *a, BIGNUM *n,BN_CTX *ctx); |
| This function create a new BIGNUM and returns it. This number |
| is the inverse mod 'n' of 'a'. By this it is meant that the |
| returned value 'r' satisfies (a*r)%n == 1. This function is |
| used in the generation of RSA keys. 'ctx', as per usual, |
| is used to hold temporary variables that are required by the |
| function. NULL is returned on error. |
| |
| int BN_gcd(BIGNUM *r,BIGNUM *a,BIGNUM *b,BN_CTX *ctx); |
| 'r' has the greatest common divisor of 'a' and 'b'. 'ctx' is |
| used for temporary variables and 0 is returned on error. |
| |
| int BN_is_prime(BIGNUM *p,int nchecks,void (*callback)(),BN_CTX *ctx, |
| char *cb_arg); |
| This function is used to check if a BIGNUM ('p') is prime. |
| It performs this test by using the Miller-Rabin randomised |
| primality test. This is a probalistic test that requires a |
| number of rounds to ensure the number is prime to a high |
| degree of probability. Since this can take quite some time, a |
| callback function can be passed and it will be called each |
| time 'p' passes a round of the prime testing. 'callback' will |
| be called as follows, callback(1,n,cb_arg) where n is the number of |
| the round, just passed. As per usual 'ctx' contains temporary |
| variables used. If ctx is NULL, it does not matter, a local version |
| will be malloced. This parameter is present to save some mallocing |
| inside the function but probably could be removed. |
| 0 is returned on error. |
| 'ncheck' is the number of Miller-Rabin tests to run. It is |
| suggested to use the value 'BN_prime_checks' by default. |
| |
| BIGNUM *BN_generate_prime( |
| int bits, |
| int strong, |
| BIGNUM *a, |
| BIGNUM *rems, |
| void (*callback)()); |
| char *cb_arg |
| This function is used to generate prime numbers. It returns a |
| new BIGNUM that has a high probability of being a prime. |
| 'bits' is the number of bits that |
| are to be in the prime. If 'strong' is true, the returned prime |
| will also be a strong prime ((p-1)/2 is also prime). |
| While searching for the prime ('p'), we |
| can add the requirement that the prime fill the following |
| condition p%a == rem. This can be used to help search for |
| primes with specific features, which is required when looking |
| for primes suitable for use with certain 'g' values in the |
| Diffie-Hellman key exchange algorithm. If 'a' is NULL, |
| this condition is not checked. If rem is NULL, rem is assumed |
| to be 1. Since this search for a prime |
| can take quite some time, if callback is not NULL, it is called |
| in the following situations. |
| We have a suspected prime (from a quick sieve), |
| callback(0,sus_prime++,cb_arg). Each item to be passed to BN_is_prime(). |
| callback(1,round++,cb_arg). Each successful 'round' in BN_is_prime(). |
| callback(2,round,cb_arg). For each successful BN_is_prime() test. |
| |
| Hints |
| ----- |
| |
| DSA wants 64*32 to use word mont mul, but RSA wants to use full. |
| |
| ==== callback.doc ======================================================== |
| |
| Callback functions used in SSLeay. |
| |
| -------------------------- |
| The BIO library. |
| |
| Each BIO structure can have a callback defined against it. This callback is |
| called 2 times for each BIO 'function'. It is passed 6 parameters. |
| BIO_debug_callback() is an example callback which is defined in |
| crypto/buffer/bio_cb.c and is used in apps/dgst.c This is intended mostly |
| for debuging or to notify the application of IO. |
| |
| long BIO_debug_callback(BIO *bio,int cmd,char *argp,int argi,long argl, |
| long ret); |
| bio is the BIO being called, cmd is the type of BIO function being called. |
| Look at the BIO_CB_* defines in buffer.h. Argp and argi are the arguments |
| passed to BIO_read(), BIO_write, BIO_gets(), BIO_puts(). In the case of |
| BIO_ctrl(), argl is also defined. The first time the callback is called, |
| before the underlying function has been executed, 0 is passed as 'ret', and |
| if the return code from the callback is not > 0, the call is aborted |
| and the returned <= 0 value is returned. |
| The second time the callback is called, the 'cmd' value also has |
| BIO_CB_RETURN logically 'or'ed with it. The 'ret' value is the value returned |
| from the actuall function call and whatever the callback returns is returned |
| from the BIO function. |
| |
| BIO_set_callback(b,cb) can be used to set the callback function |
| (b is a BIO), and BIO_set_callback_arg(b,arg) can be used to |
| set the cb_arg argument in the BIO strucutre. This field is only intended |
| to be used by application, primarily in the callback function since it is |
| accessable since the BIO is passed. |
| |
| -------------------------- |
| The PEM library. |
| |
| The pem library only really uses one type of callback, |
| static int def_callback(char *buf, int num, int verify); |
| which is used to return a password string if required. |
| 'buf' is the buffer to put the string in. 'num' is the size of 'buf' |
| and 'verify' is used to indicate that the password should be checked. |
| This last flag is mostly used when reading a password for encryption. |
| |
| For all of these functions, a NULL callback will call the above mentioned |
| default callback. This default function does not work under Windows 3.1. |
| For other machines, it will use an application defined prompt string |
| (EVP_set_pw_prompt(), which defines a library wide prompt string) |
| if defined, otherwise it will use it's own PEM password prompt. |
| It will then call EVP_read_pw_string() to get a password from the console. |
| If your application wishes to use nice fancy windows to retrieve passwords, |
| replace this function. The callback should return the number of bytes read |
| into 'buf'. If the number of bytes <= 0, it is considered an error. |
| |
| Functions that take this callback are listed below. For the 'read' type |
| functions, the callback will only be required if the PEM data is encrypted. |
| |
| For the Write functions, normally a password can be passed in 'kstr', of |
| 'klen' bytes which will be used if the 'enc' cipher is not NULL. If |
| 'kstr' is NULL, the callback will be used to retrieve a password. |
| |
| int PEM_do_header (EVP_CIPHER_INFO *cipher, unsigned char *data,long *len, |
| int (*callback)()); |
| char *PEM_ASN1_read_bio(char *(*d2i)(),char *name,BIO *bp,char **x,int (*cb)()); |
| char *PEM_ASN1_read(char *(*d2i)(),char *name,FILE *fp,char **x,int (*cb)()); |
| int PEM_ASN1_write_bio(int (*i2d)(),char *name,BIO *bp,char *x, |
| EVP_CIPHER *enc,unsigned char *kstr,int klen,int (*callback)()); |
| int PEM_ASN1_write(int (*i2d)(),char *name,FILE *fp,char *x, |
| EVP_CIPHER *enc,unsigned char *kstr,int klen,int (*callback)()); |
| STACK *PEM_X509_INFO_read(FILE *fp, STACK *sk, int (*cb)()); |
| STACK *PEM_X509_INFO_read_bio(BIO *fp, STACK *sk, int (*cb)()); |
| |
| #define PEM_write_RSAPrivateKey(fp,x,enc,kstr,klen,cb) |
| #define PEM_write_DSAPrivateKey(fp,x,enc,kstr,klen,cb) |
| #define PEM_write_bio_RSAPrivateKey(bp,x,enc,kstr,klen,cb) |
| #define PEM_write_bio_DSAPrivateKey(bp,x,enc,kstr,klen,cb) |
| #define PEM_read_SSL_SESSION(fp,x,cb) |
| #define PEM_read_X509(fp,x,cb) |
| #define PEM_read_X509_REQ(fp,x,cb) |
| #define PEM_read_X509_CRL(fp,x,cb) |
| #define PEM_read_RSAPrivateKey(fp,x,cb) |
| #define PEM_read_DSAPrivateKey(fp,x,cb) |
| #define PEM_read_PrivateKey(fp,x,cb) |
| #define PEM_read_PKCS7(fp,x,cb) |
| #define PEM_read_DHparams(fp,x,cb) |
| #define PEM_read_bio_SSL_SESSION(bp,x,cb) |
| #define PEM_read_bio_X509(bp,x,cb) |
| #define PEM_read_bio_X509_REQ(bp,x,cb) |
| #define PEM_read_bio_X509_CRL(bp,x,cb) |
| #define PEM_read_bio_RSAPrivateKey(bp,x,cb) |
| #define PEM_read_bio_DSAPrivateKey(bp,x,cb) |
| #define PEM_read_bio_PrivateKey(bp,x,cb) |
| #define PEM_read_bio_PKCS7(bp,x,cb) |
| #define PEM_read_bio_DHparams(bp,x,cb) |
| int i2d_Netscape_RSA(RSA *a, unsigned char **pp, int (*cb)()); |
| RSA *d2i_Netscape_RSA(RSA **a, unsigned char **pp, long length, int (*cb)()); |
| |
| Now you will notice that macros like |
| #define PEM_write_X509(fp,x) \ |
| PEM_ASN1_write((int (*)())i2d_X509,PEM_STRING_X509,fp, \ |
| (char *)x, NULL,NULL,0,NULL) |
| Don't do encryption normally. If you want to PEM encrypt your X509 structure, |
| either just call PEM_ASN1_write directly or just define your own |
| macro variant. As you can see, this macro just sets all encryption related |
| parameters to NULL. |
| |
| |
| -------------------------- |
| The SSL library. |
| |
| #define SSL_set_info_callback(ssl,cb) |
| #define SSL_CTX_set_info_callback(ctx,cb) |
| void callback(SSL *ssl,int location,int ret) |
| This callback is called each time around the SSL_connect()/SSL_accept() |
| state machine. So it will be called each time the SSL protocol progresses. |
| It is mostly present for use when debugging. When SSL_connect() or |
| SSL_accept() return, the location flag is SSL_CB_ACCEPT_EXIT or |
| SSL_CB_CONNECT_EXIT and 'ret' is the value about to be returned. |
| Have a look at the SSL_CB_* defines in ssl.h. If an info callback is defined |
| against the SSL_CTX, it is called unless there is one set against the SSL. |
| Have a look at |
| void client_info_callback() in apps/s_client() for an example. |
| |
| Certificate verification. |
| void SSL_set_verify(SSL *s, int mode, int (*callback) ()); |
| void SSL_CTX_set_verify(SSL_CTX *ctx,int mode,int (*callback)()); |
| This callback is used to help verify client and server X509 certificates. |
| It is actually passed to X509_cert_verify(), along with the SSL structure |
| so you have to read about X509_cert_verify() :-). The SSL_CTX version is used |
| if the SSL version is not defined. X509_cert_verify() is the function used |
| by the SSL part of the library to verify certificates. This function is |
| nearly always defined by the application. |
| |
| void SSL_CTX_set_cert_verify_cb(SSL_CTX *ctx, int (*cb)(),char *arg); |
| int callback(char *arg,SSL *s,X509 *xs,STACK *cert_chain); |
| This call is used to replace the SSLeay certificate verification code. |
| The 'arg' is kept in the SSL_CTX and is passed to the callback. |
| If the callback returns 0, the certificate is rejected, otherwise it |
| is accepted. The callback is replacing the X509_cert_verify() call. |
| This feature is not often used, but if you wished to implement |
| some totally different certificate authentication system, this 'hook' is |
| vital. |
| |
| SSLeay keeps a cache of session-ids against each SSL_CTX. These callbacks can |
| be used to notify the application when a SSL_SESSION is added to the cache |
| or to retrieve a SSL_SESSION that is not in the cache from the application. |
| #define SSL_CTX_sess_set_get_cb(ctx,cb) |
| SSL_SESSION *callback(SSL *s,char *session_id,int session_id_len,int *copy); |
| If defined, this callback is called to return the SESSION_ID for the |
| session-id in 'session_id', of 'session_id_len' bytes. 'copy' is set to 1 |
| if the server is to 'take a copy' of the SSL_SESSION structure. It is 0 |
| if the SSL_SESSION is being 'passed in' so the SSLeay library is now |
| responsible for 'free()ing' the structure. Basically it is used to indicate |
| if the reference count on the SSL_SESSION structure needs to be incremented. |
| |
| #define SSL_CTX_sess_set_new_cb(ctx,cb) |
| int callback(SSL *s, SSL_SESSION *sess); |
| When a new connection is established, if the SSL_SESSION is going to be added |
| to the cache, this callback is called. Return 1 if a 'copy' is required, |
| otherwise, return 0. This return value just causes the reference count |
| to be incremented (on return of a 1), this means the application does |
| not need to worry about incrementing the refernece count (and the |
| locking that implies in a multi-threaded application). |
| |
| void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx,int (*cb)()); |
| This sets the SSL password reading function. |
| It is mostly used for windowing applications |
| and used by PEM_read_bio_X509() and PEM_read_bio_RSAPrivateKey() |
| calls inside the SSL library. The only reason this is present is because the |
| calls to PEM_* functions is hidden in the SSLeay library so you have to |
| pass in the callback some how. |
| |
| #define SSL_CTX_set_client_cert_cb(ctx,cb) |
| int callback(SSL *s,X509 **x509, EVP_PKEY **pkey); |
| Called when a client certificate is requested but there is not one set |
| against the SSL_CTX or the SSL. If the callback returns 1, x509 and |
| pkey need to point to valid data. The library will free these when |
| required so if the application wants to keep these around, increment |
| their reference counts. If 0 is returned, no client cert is |
| available. If -1 is returned, it is assumed that the callback needs |
| to be called again at a later point in time. SSL_connect will return |
| -1 and SSL_want_x509_lookup(ssl) returns true. Remember that |
| application data can be attached to an SSL structure via the |
| SSL_set_app_data(SSL *ssl,char *data) call. |
| |
| -------------------------- |
| The X509 library. |
| |
| int X509_cert_verify(CERTIFICATE_CTX *ctx,X509 *xs, int (*cb)(), |
| int *error,char *arg,STACK *cert_chain); |
| int verify_callback(int ok,X509 *xs,X509 *xi,int depth,int error,char *arg, |
| STACK *cert_chain); |
| |
| X509_cert_verify() is used to authenticate X509 certificates. The 'ctx' holds |
| the details of the various caches and files used to locate certificates. |
| 'xs' is the certificate to verify and 'cb' is the application callback (more |
| detail later). 'error' will be set to the error code and 'arg' is passed |
| to the 'cb' callback. Look at the VERIFY_* defines in crypto/x509/x509.h |
| |
| When ever X509_cert_verify() makes a 'negative' decision about a |
| certitificate, the callback is called. If everything checks out, the |
| callback is called with 'VERIFY_OK' or 'VERIFY_ROOT_OK' (for a self |
| signed cert that is not the passed certificate). |
| |
| The callback is passed the X509_cert_verify opinion of the certificate |
| in 'ok', the certificate in 'xs', the issuer certificate in 'xi', |
| the 'depth' of the certificate in the verification 'chain', the |
| VERIFY_* code in 'error' and the argument passed to X509_cert_verify() |
| in 'arg'. cert_chain is a list of extra certs to use if they are not |
| in the cache. |
| |
| The callback can be used to look at the error reason, and then return 0 |
| for an 'error' or '1' for ok. This will override the X509_cert_verify() |
| opinion of the certificates validity. Processing will continue depending on |
| the return value. If one just wishes to use the callback for informational |
| reason, just return the 'ok' parameter. |
| |
| -------------------------- |
| The BN and DH library. |
| |
| BIGNUM *BN_generate_prime(int bits,int strong,BIGNUM *add, |
| BIGNUM *rem,void (*callback)(int,int)); |
| int BN_is_prime(BIGNUM *p,int nchecks,void (*callback)(int,int), |
| |
| Read doc/bn.doc for the description of these 2. |
| |
| DH *DH_generate_parameters(int prime_len,int generator, |
| void (*callback)(int,int)); |
| Read doc/bn.doc for the description of the callback, since it is just passed |
| to BN_generate_prime(), except that it is also called as |
| callback(3,0) by this function. |
| |
| -------------------------- |
| The CRYPTO library. |
| |
| void CRYPTO_set_locking_callback(void (*func)(int mode,int type,char *file, |
| int line)); |
| void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount, |
| int type,char *file, int line)); |
| void CRYPTO_set_id_callback(unsigned long (*func)(void)); |
| |
| Read threads.doc for info on these ones. |
| |
| |
| ==== cipher.doc ======================================================== |
| |
| The Cipher subroutines. |
| |
| These routines require "evp.h" to be included. |
| |
| These functions are a higher level interface to the various cipher |
| routines found in this library. As such, they allow the same code to be |
| used to encrypt and decrypt via different ciphers with only a change |
| in an initial parameter. These routines also provide buffering for block |
| ciphers. |
| |
| These routines all take a pointer to the following structure to specify |
| which cipher to use. If you wish to use a new cipher with these routines, |
| you would probably be best off looking an how an existing cipher is |
| implemented and copying it. At this point in time, I'm not going to go |
| into many details. This structure should be considered opaque |
| |
| typedef struct pem_cipher_st |
| { |
| int type; |
| int block_size; |
| int key_len; |
| int iv_len; |
| void (*enc_init)(); /* init for encryption */ |
| void (*dec_init)(); /* init for decryption */ |
| void (*do_cipher)(); /* encrypt data */ |
| } EVP_CIPHER; |
| |
| The type field is the object NID of the cipher type |
| (read the section on Objects for an explanation of what a NID is). |
| The cipher block_size is how many bytes need to be passed |
| to the cipher at a time. Key_len is the |
| length of the key the cipher requires and iv_len is the length of the |
| initialisation vector required. enc_init is the function |
| called to initialise the ciphers context for encryption and dec_init is the |
| function to initialise for decryption (they need to be different, especially |
| for the IDEA cipher). |
| |
| One reason for specifying the Cipher via a pointer to a structure |
| is that if you only use des-cbc, only the des-cbc routines will |
| be included when you link the program. If you passed an integer |
| that specified which cipher to use, the routine that mapped that |
| integer to a set of cipher functions would cause all the ciphers |
| to be link into the code. This setup also allows new ciphers |
| to be added by the application (with some restrictions). |
| |
| The thirteen ciphers currently defined in this library are |
| |
| EVP_CIPHER *EVP_des_ecb(); /* DES in ecb mode, iv=0, block=8, key= 8 */ |
| EVP_CIPHER *EVP_des_ede(); /* DES in ecb ede mode, iv=0, block=8, key=16 */ |
| EVP_CIPHER *EVP_des_ede3(); /* DES in ecb ede mode, iv=0, block=8, key=24 */ |
| EVP_CIPHER *EVP_des_cfb(); /* DES in cfb mode, iv=8, block=1, key= 8 */ |
| EVP_CIPHER *EVP_des_ede_cfb(); /* DES in ede cfb mode, iv=8, block=1, key=16 */ |
| EVP_CIPHER *EVP_des_ede3_cfb();/* DES in ede cfb mode, iv=8, block=1, key=24 */ |
| EVP_CIPHER *EVP_des_ofb(); /* DES in ofb mode, iv=8, block=1, key= 8 */ |
| EVP_CIPHER *EVP_des_ede_ofb(); /* DES in ede ofb mode, iv=8, block=1, key=16 */ |
| EVP_CIPHER *EVP_des_ede3_ofb();/* DES in ede ofb mode, iv=8, block=1, key=24 */ |
| EVP_CIPHER *EVP_des_cbc(); /* DES in cbc mode, iv=8, block=8, key= 8 */ |
| EVP_CIPHER *EVP_des_ede_cbc(); /* DES in cbc ede mode, iv=8, block=8, key=16 */ |
| EVP_CIPHER *EVP_des_ede3_cbc();/* DES in cbc ede mode, iv=8, block=8, key=24 */ |
| EVP_CIPHER *EVP_desx_cbc(); /* DES in desx cbc mode,iv=8, block=8, key=24 */ |
| EVP_CIPHER *EVP_rc4(); /* RC4, iv=0, block=1, key=16 */ |
| EVP_CIPHER *EVP_idea_ecb(); /* IDEA in ecb mode, iv=0, block=8, key=16 */ |
| EVP_CIPHER *EVP_idea_cfb(); /* IDEA in cfb mode, iv=8, block=1, key=16 */ |
| EVP_CIPHER *EVP_idea_ofb(); /* IDEA in ofb mode, iv=8, block=1, key=16 */ |
| EVP_CIPHER *EVP_idea_cbc(); /* IDEA in cbc mode, iv=8, block=8, key=16 */ |
| EVP_CIPHER *EVP_rc2_ecb(); /* RC2 in ecb mode, iv=0, block=8, key=16 */ |
| EVP_CIPHER *EVP_rc2_cfb(); /* RC2 in cfb mode, iv=8, block=1, key=16 */ |
| EVP_CIPHER *EVP_rc2_ofb(); /* RC2 in ofb mode, iv=8, block=1, key=16 */ |
| EVP_CIPHER *EVP_rc2_cbc(); /* RC2 in cbc mode, iv=8, block=8, key=16 */ |
| EVP_CIPHER *EVP_bf_ecb(); /* Blowfish in ecb mode,iv=0, block=8, key=16 */ |
| EVP_CIPHER *EVP_bf_cfb(); /* Blowfish in cfb mode,iv=8, block=1, key=16 */ |
| EVP_CIPHER *EVP_bf_ofb(); /* Blowfish in ofb mode,iv=8, block=1, key=16 */ |
| EVP_CIPHER *EVP_bf_cbc(); /* Blowfish in cbc mode,iv=8, block=8, key=16 */ |
| |
| The meaning of the compound names is as follows. |
| des The base cipher is DES. |
| idea The base cipher is IDEA |
| rc4 The base cipher is RC4-128 |
| rc2 The base cipher is RC2-128 |
| ecb Electronic Code Book form of the cipher. |
| cbc Cipher Block Chaining form of the cipher. |
| cfb 64 bit Cipher Feedback form of the cipher. |
| ofb 64 bit Output Feedback form of the cipher. |
| ede The cipher is used in Encrypt, Decrypt, Encrypt mode. The first |
| and last keys are the same. |
| ede3 The cipher is used in Encrypt, Decrypt, Encrypt mode. |
| |
| All the Cipher routines take a EVP_CIPHER_CTX pointer as an argument. |
| The state of the cipher is kept in this structure. |
| |
| typedef struct EVP_CIPHER_Ctx_st |
| { |
| EVP_CIPHER *cipher; |
| int encrypt; /* encrypt or decrypt */ |
| int buf_len; /* number we have left */ |
| unsigned char buf[8]; |
| union { |
| .... /* cipher specific stuff */ |
| } c; |
| } EVP_CIPHER_CTX; |
| |
| Cipher is a pointer the the EVP_CIPHER for the current context. The encrypt |
| flag indicates encryption or decryption. buf_len is the number of bytes |
| currently being held in buf. |
| The 'c' union holds the cipher specify context. |
| |
| The following functions are to be used. |
| |
| int EVP_read_pw_string( |
| char *buf, |
| int len, |
| char *prompt, |
| int verify, |
| This function is the same as des_read_pw_string() (des.doc). |
| |
| void EVP_set_pw_prompt(char *prompt); |
| This function sets the 'default' prompt to use to use in |
| EVP_read_pw_string when the prompt parameter is NULL. If the |
| prompt parameter is NULL, this 'default prompt' feature is turned |
| off. Be warned, this is a global variable so weird things |
| will happen if it is used under Win16 and care must be taken |
| with a multi-threaded version of the library. |
| |
| char *EVP_get_pw_prompt(); |
| This returns a pointer to the default prompt string. NULL |
| if it is not set. |
| |
| int EVP_BytesToKey( |
| EVP_CIPHER *type, |
| EVP_MD *md, |
| unsigned char *salt, |
| unsigned char *data, |
| int datal, |
| int count, |
| unsigned char *key, |
| unsigned char *iv); |
| This function is used to generate a key and an initialisation vector |
| for a specified cipher from a key string and a salt. Type |
| specifies the cipher the 'key' is being generated for. Md is the |
| message digest algorithm to use to generate the key and iv. The salt |
| is an optional 8 byte object that is used to help seed the key |
| generator. |
| If the salt value is NULL, it is just not used. Datal is the |
| number of bytes to use from 'data' in the key generation. |
| This function returns the key size for the specified cipher, if |
| data is NULL, this value is returns and no other |
| computation is performed. Count is |
| the number of times to loop around the key generator. I would |
| suggest leaving it's value as 1. Key and iv are the structures to |
| place the returning iv and key in. If they are NULL, no value is |
| generated for that particular value. |
| The algorithm used is as follows |
| |
| /* M[] is an array of message digests |
| * MD() is the message digest function */ |
| M[0]=MD(data . salt); |
| for (i=1; i<count; i++) M[0]=MD(M[0]); |
| |
| i=1 |
| while (data still needed for key and iv) |
| { |
| M[i]=MD(M[i-1] . data . salt); |
| for (i=1; i<count; i++) M[i]=MD(M[i]); |
| i++; |
| } |
| |
| If the salt is NULL, it is not used. |
| The digests are concatenated together. |
| M = M[0] . M[1] . M[2] ....... |
| |
| For key= 8, iv=8 => key=M[0.. 8], iv=M[ 9 .. 16]. |
| For key=16, iv=0 => key=M[0..16]. |
| For key=16, iv=8 => key=M[0..16], iv=M[17 .. 24]. |
| For key=24, iv=8 => key=M[0..24], iv=M[25 .. 32]. |
| |
| This routine will produce DES-CBC keys and iv that are compatible |
| with the PKCS-5 standard when md2 or md5 are used. If md5 is |
| used, the salt is NULL and count is 1, this routine will produce |
| the password to key mapping normally used with RC4. |
| I have attempted to logically extend the PKCS-5 standard to |
| generate keys and iv for ciphers that require more than 16 bytes, |
| if anyone knows what the correct standard is, please inform me. |
| When using sha or sha1, things are a bit different under this scheme, |
| since sha produces a 20 byte digest. So for ciphers requiring |
| 24 bits of data, 20 will come from the first MD and 4 will |
| come from the second. |
| |
| I have considered having a separate function so this 'routine' |
| can be used without the requirement of passing a EVP_CIPHER *, |
| but I have decided to not bother. If you wish to use the |
| function without official EVP_CIPHER structures, just declare |
| a local one and set the key_len and iv_len fields to the |
| length you desire. |
| |
| The following routines perform encryption and decryption 'by parts'. By |
| this I mean that there are groups of 3 routines. An Init function that is |
| used to specify a cipher and initialise data structures. An Update routine |
| that does encryption/decryption, one 'chunk' at a time. And finally a |
| 'Final' function that finishes the encryption/decryption process. |
| All these functions take a EVP_CIPHER pointer to specify which cipher to |
| encrypt/decrypt with. They also take a EVP_CIPHER_CTX object as an |
| argument. This structure is used to hold the state information associated |
| with the operation in progress. |
| |
| void EVP_EncryptInit( |
| EVP_CIPHER_CTX *ctx, |
| EVP_CIPHER *type, |
| unsigned char *key, |
| unsigned char *iv); |
| This function initialise a EVP_CIPHER_CTX for encryption using the |
| cipher passed in the 'type' field. The cipher is initialised to use |
| 'key' as the key and 'iv' for the initialisation vector (if one is |
| required). If the type, key or iv is NULL, the value currently in the |
| EVP_CIPHER_CTX is reused. So to perform several decrypt |
| using the same cipher, key and iv, initialise with the cipher, |
| key and iv the first time and then for subsequent calls, |
| reuse 'ctx' but pass NULL for type, key and iv. You must make sure |
| to pass a key that is large enough for a particular cipher. I |
| would suggest using the EVP_BytesToKey() function. |
| |
| void EVP_EncryptUpdate( |
| EVP_CIPHER_CTX *ctx, |
| unsigned char *out, |
| int *outl, |
| unsigned char *in, |
| int inl); |
| This function takes 'inl' bytes from 'in' and outputs bytes |
| encrypted by the cipher 'ctx' was initialised with into 'out'. The |
| number of bytes written to 'out' is put into outl. If a particular |
| cipher encrypts in blocks, less or more bytes than input may be |
| output. Currently the largest block size used by supported ciphers |
| is 8 bytes, so 'out' should have room for 'inl+7' bytes. Normally |
| EVP_EncryptInit() is called once, followed by lots and lots of |
| calls to EVP_EncryptUpdate, followed by a single EVP_EncryptFinal |
| call. |
| |
| void EVP_EncryptFinal( |
| EVP_CIPHER_CTX *ctx, |
| unsigned char *out, |
| int *outl); |
| Because quite a large number of ciphers are block ciphers, there is |
| often an incomplete block to write out at the end of the |
| encryption. EVP_EncryptFinal() performs processing on this last |
| block. The last block in encoded in such a way that it is possible |
| to determine how many bytes in the last block are valid. For 8 byte |
| block size ciphers, if only 5 bytes in the last block are valid, the |
| last three bytes will be filled with the value 3. If only 2 were |
| valid, the other 6 would be filled with sixes. If all 8 bytes are |
| valid, a extra 8 bytes are appended to the cipher stream containing |
| nothing but 8 eights. These last bytes are output into 'out' and |
| the number of bytes written is put into 'outl' These last bytes |
| are output into 'out' and the number of bytes written is put into |
| 'outl'. This form of block cipher finalisation is compatible with |
| PKCS-5. Please remember that even if you are using ciphers like |
| RC4 that has no blocking and so the function will not write |
| anything into 'out', it would still be a good idea to pass a |
| variable for 'out' that can hold 8 bytes just in case the cipher is |
| changed some time in the future. It should also be remembered |
| that the EVP_CIPHER_CTX contains the password and so when one has |
| finished encryption with a particular EVP_CIPHER_CTX, it is good |
| practice to zero the structure |
| (ie. memset(ctx,0,sizeof(EVP_CIPHER_CTX)). |
| |
| void EVP_DecryptInit( |
| EVP_CIPHER_CTX *ctx, |
| EVP_CIPHER *type, |
| unsigned char *key, |
| unsigned char *iv); |
| This function is basically the same as EVP_EncryptInit() accept that |
| is prepares the EVP_CIPHER_CTX for decryption. |
| |
| void EVP_DecryptUpdate( |
| EVP_CIPHER_CTX *ctx, |
| unsigned char *out, |
| int *outl, |
| unsigned char *in, |
| int inl); |
| This function is basically the same as EVP_EncryptUpdate() |
| except that it performs decryption. There is one |
| fundamental difference though. 'out' can not be the same as |
| 'in' for any ciphers with a block size greater than 1 if more |
| than one call to EVP_DecryptUpdate() will be made. This |
| is because this routine can hold a 'partial' block between |
| calls. When a partial block is decrypted (due to more bytes |
| being passed via this function, they will be written to 'out' |
| overwriting the input bytes in 'in' that have not been read |
| yet. From this it should also be noted that 'out' should |
| be at least one 'block size' larger than 'inl'. This problem |
| only occurs on the second and subsequent call to |
| EVP_DecryptUpdate() when using a block cipher. |
| |
| int EVP_DecryptFinal( |
| EVP_CIPHER_CTX *ctx, |
| unsigned char *out, |
| int *outl); |
| This function is different to EVP_EncryptFinal in that it 'removes' |
| any padding bytes appended when the data was encrypted. Due to the |
| way in which 1 to 8 bytes may have been appended when encryption |
| using a block cipher, 'out' can end up with 0 to 7 bytes being put |
| into it. When decoding the padding bytes, it is possible to detect |
| an incorrect decryption. If the decryption appears to be wrong, 0 |
| is returned. If everything seems ok, 1 is returned. For ciphers |
| with a block size of 1 (RC4), this function would normally not |
| return any bytes and would always return 1. Just because this |
| function returns 1 does not mean the decryption was correct. It |
| would normally be wrong due to either the wrong key/iv or |
| corruption of the cipher data fed to EVP_DecryptUpdate(). |
| As for EVP_EncryptFinal, it is a good idea to zero the |
| EVP_CIPHER_CTX after use since the structure contains the key used |
| to decrypt the data. |
| |
| The following Cipher routines are convenience routines that call either |
| EVP_EncryptXxx or EVP_DecryptXxx depending on weather the EVP_CIPHER_CTX |
| was setup to encrypt or decrypt. |
| |
| void EVP_CipherInit( |
| EVP_CIPHER_CTX *ctx, |
| EVP_CIPHER *type, |
| unsigned char *key, |
| unsigned char *iv, |
| int enc); |
| This function take arguments that are the same as EVP_EncryptInit() |
| and EVP_DecryptInit() except for the extra 'enc' flag. If 1, the |
| EVP_CIPHER_CTX is setup for encryption, if 0, decryption. |
| |
| void EVP_CipherUpdate( |
| EVP_CIPHER_CTX *ctx, |
| unsigned char *out, |
| int *outl, |
| unsigned char *in, |
| int inl); |
| Again this function calls either EVP_EncryptUpdate() or |
| EVP_DecryptUpdate() depending on state in the 'ctx' structure. |
| As noted for EVP_DecryptUpdate(), when this routine is used |
| for decryption with block ciphers, 'out' should not be the |
| same as 'in'. |
| |
| int EVP_CipherFinal( |
| EVP_CIPHER_CTX *ctx, |
| unsigned char *outm, |
| int *outl); |
| This routine call EVP_EncryptFinal() or EVP_DecryptFinal() |
| depending on the state information in 'ctx'. 1 is always returned |
| if the mode is encryption, otherwise the return value is the return |
| value of EVP_DecryptFinal(). |
| |
| ==== cipher.m ======================================================== |
| |
| Date: Tue, 15 Oct 1996 08:16:14 +1000 (EST) |
| From: Eric Young <eay@mincom.com> |
| X-Sender: eay@orb |
| To: Roland Haring <rharing@tandem.cl> |
| Cc: ssl-users@mincom.com |
| Subject: Re: Symmetric encryption with ssleay |
| In-Reply-To: <m0vBpyq-00001aC@tandemnet.tandem.cl> |
| Message-Id: <Pine.SOL.3.91.961015075623.11394A-100000@orb> |
| Mime-Version: 1.0 |
| Content-Type: TEXT/PLAIN; charset=US-ASCII |
| Sender: ssl-lists-owner@mincom.com |
| Precedence: bulk |
| Status: RO |
| X-Status: |
| |
| On Fri, 11 Oct 1996, Roland Haring wrote: |
| > THE_POINT: |
| > Would somebody be so kind to give me the minimum basic |
| > calls I need to do to libcrypto.a to get some text encrypted |
| > and decrypted again? ...hopefully with code included to do |
| > base64 encryption and decryption ... e.g. that sign-it.c code |
| > posted some while ago was a big help :-) (please, do not point |
| > me to apps/enc.c where I suspect my Heissenbug to be hidden :-) |
| |
| Ok, the base64 encoding stuff in 'enc.c' does the wrong thing sometimes |
| when the data is less than a line long (this is for decoding). I'll dig |
| up the exact fix today and post it. I am taking longer on 0.6.5 than I |
| intended so I'll just post this patch. |
| |
| The documentation to read is in |
| doc/cipher.doc, |
| doc/encode.doc (very sparse :-). |
| and perhaps |
| doc/digest.doc, |
| |
| The basic calls to encrypt with say triple DES are |
| |
| Given |
| char key[EVP_MAX_KEY_LENGTH]; |
| char iv[EVP_MAX_IV_LENGTH]; |
| EVP_CIPHER_CTX ctx; |
| unsigned char out[512+8]; |
| int outl; |
| |
| /* optional generation of key/iv data from text password using md5 |
| * via an upward compatable verson of PKCS#5. */ |
| EVP_BytesToKey(EVP_des_ede3_cbc,EVP_md5,NULL,passwd,strlen(passwd), |
| key,iv); |
| |
| /* Initalise the EVP_CIPHER_CTX */ |
| EVP_EncryptInit(ctx,EVP_des_ede3_cbc,key,iv); |
| |
| while (....) |
| { |
| /* This is processing 512 bytes at a time, the bytes are being |
| * copied into 'out', outl bytes are output. 'out' should not be the |
| * same as 'in' for reasons mentioned in the documentation. */ |
| EVP_EncryptUpdate(ctx,out,&outl,in,512); |
| } |
| |
| /* Output the last 'block'. If the cipher is a block cipher, the last |
| * block is encoded in such a way so that a wrong decryption will normally be |
| * detected - again, one of the PKCS standards. */ |
| |
| EVP_EncryptFinal(ctx,out,&outl); |
| |
| To decrypt, use the EVP_DecryptXXXXX functions except that EVP_DecryptFinal() |
| will return 0 if the decryption fails (only detectable on block ciphers). |
| |
| You can also use |
| EVP_CipherInit() |
| EVP_CipherUpdate() |
| EVP_CipherFinal() |
| which does either encryption or decryption depending on an extra |
| parameter to EVP_CipherInit(). |
| |
| |
| To do the base64 encoding, |
| EVP_EncodeInit() |
| EVP_EncodeUpdate() |
| EVP_EncodeFinal() |
| |
| EVP_DecodeInit() |
| EVP_DecodeUpdate() |
| EVP_DecodeFinal() |
| |
| where the encoding is quite simple, but the decoding can be a bit more |
| fun (due to dud input). |
| |
| EVP_DecodeUpdate() returns -1 for an error on an input line, 0 if the |
| 'last line' was just processed, and 1 if more lines should be submitted. |
| |
| EVP_DecodeFinal() returns -1 for an error or 1 if things are ok. |
| |
| So the loop becomes |
| EVP_DecodeInit(....) |
| for (;;) |
| { |
| i=EVP_DecodeUpdate(....); |
| if (i < 0) goto err; |
| |
| /* process the data */ |
| |
| if (i == 0) break; |
| } |
| EVP_DecodeFinal(....); |
| /* process the data */ |
| |
| The problem in 'enc.c' is that I was stuff the processing up after the |
| EVP_DecodeFinal(...) when the for(..) loop was not being run (one line of |
| base64 data) and this was because 'enc.c' tries to scan over a file until |
| it hits the first valid base64 encoded line. |
| |
| hope this helps a bit. |
| eric |
| -- |
| Eric Young | BOOL is tri-state according to Bill Gates. |
| AARNet: eay@mincom.oz.au | RTFM Win32 GetMessage(). |
| |
| ==== conf.doc ======================================================== |
| |
| The CONF library. |
| |
| The CONF library is a simple set of routines that can be used to configure |
| programs. It is a superset of the genenv() function with some extra |
| structure. |
| |
| The library consists of 5 functions. |
| |
| LHASH *CONF_load(LHASH *config,char *file); |
| This function is called to load in a configuration file. Multiple |
| configuration files can be loaded, with each subsequent 'load' overwriting |
| any already defined 'variables'. If there is an error, NULL is returned. |
| If config is NULL, a new LHASH structure is created and returned, otherwise |
| the new data in the 'file' is loaded into the 'config' structure. |
| |
| void CONF_free(LHASH *config); |
| This function free()s the data in config. |
| |
| char *CONF_get_string(LHASH *config,char *section,char *name); |
| This function returns the string found in 'config' that corresponds to the |
| 'section' and 'name' specified. Classes and the naming system used will be |
| discussed later in this document. If the variable is not defined, an NULL |
| is returned. |
| |
| long CONF_get_long(LHASH *config,char *section, char *name); |
| This function is the same as CONF_get_string() except that it converts the |
| string to an long and returns it. If variable is not a number or the |
| variable does not exist, 0 is returned. This is a little problematic but I |
| don't know of a simple way around it. |
| |
| STACK *CONF_get_section(LHASH *config, char *section); |
| This function returns a 'stack' of CONF_VALUE items that are all the |
| items defined in a particular section. DO NOT free() any of the |
| variable returned. They will disappear when CONF_free() is called. |
| |
| The 'lookup' model. |
| The configuration file is divided into 'sections'. Each section is started by |
| a line of the form '[ section ]'. All subsequent variable definitions are |
| of this section. A variable definition is a simple alpha-numeric name |
| followed by an '=' and then the data. A section or variable name can be |
| described by a regular expression of the following form '[A-Za-z0-9_]+'. |
| The value of the variable is the text after the '=' until the end of the |
| line, stripped of leading and trailing white space. |
| At this point I should mention that a '#' is a comment character, \ is the |
| escape character, and all three types of quote can be used to stop any |
| special interpretation of the data. |
| Now when the data is being loaded, variable expansion can occur. This is |
| done by expanding any $NAME sequences into the value represented by the |
| variable NAME. If the variable is not in the current section, the different |
| section can be specified by using the $SECTION::NAME form. The ${NAME} form |
| also works and is very useful for expanding variables inside strings. |
| |
| When a variable is looked up, there are 2 special section. 'default', which |
| is the initial section, and 'ENV' which is the processes environment |
| variables (accessed via getenv()). When a variable is looked up, it is |
| first 'matched' with it's section (if one was specified), if this fails, the |
| 'default' section is matched. |
| If the 'lhash' variable passed was NULL, the environment is searched. |
| |
| Now why do we bother with sections? So we can have multiple programs using |
| the same configuration file, or multiple instances of the same program |
| using different variables. It also provides a nice mechanism to override |
| the processes environment variables (eg ENV::HOME=/tmp). If there is a |
| program specific variable missing, we can have default values. |
| Multiple configuration files can be loaded, with each new value clearing |
| any predefined values. A system config file can provide 'default' values, |
| and application/usr specific files can provide overriding values. |
| |
| Examples |
| |
| # This is a simple example |
| SSLEAY_HOME = /usr/local/ssl |
| ENV::PATH = $SSLEAY_HOME/bin:$PATH # override my path |
| |
| [X509] |
| cert_dir = $SSLEAY_HOME/certs # /usr/local/ssl/certs |
| |
| [SSL] |
| CIPHER = DES-EDE-MD5:RC4-MD5 |
| USER_CERT = $HOME/${USER}di'r 5' # /home/eay/eaydir 5 |
| USER_CERT = $HOME/\${USER}di\'r # /home/eay/${USER}di'r |
| USER_CERT = "$HOME/${US"ER}di\'r # $HOME/${USER}di'r |
| |
| TEST = 1234\ |
| 5678\ |
| 9ab # TEST=123456789ab |
| TTT = 1234\n\n # TTT=1234<nl><nl> |
| |
| |
| |
| ==== des.doc ======================================================== |
| |
| The DES library. |
| |
| Please note that this library was originally written to operate with |
| eBones, a version of Kerberos that had had encryption removed when it left |
| the USA and then put back in. As such there are some routines that I will |
| advise not using but they are still in the library for historical reasons. |
| For all calls that have an 'input' and 'output' variables, they can be the |
| same. |
| |
| This library requires the inclusion of 'des.h'. |
| |
| All of the encryption functions take what is called a des_key_schedule as an |
| argument. A des_key_schedule is an expanded form of the des key. |
| A des_key is 8 bytes of odd parity, the type used to hold the key is a |
| des_cblock. A des_cblock is an array of 8 bytes, often in this library |
| description I will refer to input bytes when the function specifies |
| des_cblock's as input or output, this just means that the variable should |
| be a multiple of 8 bytes. |
| |
| The define DES_ENCRYPT is passed to specify encryption, DES_DECRYPT to |
| specify decryption. The functions and global variable are as follows: |
| |
| int des_check_key; |
| DES keys are supposed to be odd parity. If this variable is set to |
| a non-zero value, des_set_key() will check that the key has odd |
| parity and is not one of the known weak DES keys. By default this |
| variable is turned off; |
| |
| void des_set_odd_parity( |
| des_cblock *key ); |
| This function takes a DES key (8 bytes) and sets the parity to odd. |
| |
| int des_is_weak_key( |
| des_cblock *key ); |
| This function returns a non-zero value if the DES key passed is a |
| weak, DES key. If it is a weak key, don't use it, try a different |
| one. If you are using 'random' keys, the chances of hitting a weak |
| key are 1/2^52 so it is probably not worth checking for them. |
| |
| int des_set_key( |
| des_cblock *key, |
| des_key_schedule schedule); |
| Des_set_key converts an 8 byte DES key into a des_key_schedule. |
| A des_key_schedule is an expanded form of the key which is used to |
| perform actual encryption. It can be regenerated from the DES key |
| so it only needs to be kept when encryption or decryption is about |
| to occur. Don't save or pass around des_key_schedule's since they |
| are CPU architecture dependent, DES keys are not. If des_check_key |
| is non zero, zero is returned if the key has the wrong parity or |
| the key is a weak key, else 1 is returned. |
| |
| int des_key_sched( |
| des_cblock *key, |
| des_key_schedule schedule); |
| An alternative name for des_set_key(). |
| |
| int des_rw_mode; /* defaults to DES_PCBC_MODE */ |
| This flag holds either DES_CBC_MODE or DES_PCBC_MODE (default). |
| This specifies the function to use in the enc_read() and enc_write() |
| functions. |
| |
| void des_encrypt( |
| unsigned long *data, |
| des_key_schedule ks, |
| int enc); |
| This is the DES encryption function that gets called by just about |
| every other DES routine in the library. You should not use this |
| function except to implement 'modes' of DES. I say this because the |
| functions that call this routine do the conversion from 'char *' to |
| long, and this needs to be done to make sure 'non-aligned' memory |
| access do not occur. The characters are loaded 'little endian', |
| have a look at my source code for more details on how I use this |
| function. |
| Data is a pointer to 2 unsigned long's and ks is the |
| des_key_schedule to use. enc, is non zero specifies encryption, |
| zero if decryption. |
| |
| void des_encrypt2( |
| unsigned long *data, |
| des_key_schedule ks, |
| int enc); |
| This functions is the same as des_encrypt() except that the DES |
| initial permutation (IP) and final permutation (FP) have been left |
| out. As for des_encrypt(), you should not use this function. |
| It is used by the routines in my library that implement triple DES. |
| IP() des_encrypt2() des_encrypt2() des_encrypt2() FP() is the same |
| as des_encrypt() des_encrypt() des_encrypt() except faster :-). |
| |
| void des_ecb_encrypt( |
| des_cblock *input, |
| des_cblock *output, |
| des_key_schedule ks, |
| int enc); |
| This is the basic Electronic Code Book form of DES, the most basic |
| form. Input is encrypted into output using the key represented by |
| ks. If enc is non zero (DES_ENCRYPT), encryption occurs, otherwise |
| decryption occurs. Input is 8 bytes long and output is 8 bytes. |
| (the des_cblock structure is 8 chars). |
| |
| void des_ecb3_encrypt( |
| des_cblock *input, |
| des_cblock *output, |
| des_key_schedule ks1, |
| des_key_schedule ks2, |
| des_key_schedule ks3, |
| int enc); |
| This is the 3 key EDE mode of ECB DES. What this means is that |
| the 8 bytes of input is encrypted with ks1, decrypted with ks2 and |
| then encrypted again with ks3, before being put into output; |
| C=E(ks3,D(ks2,E(ks1,M))). There is a macro, des_ecb2_encrypt() |
| that only takes 2 des_key_schedules that implements, |
| C=E(ks1,D(ks2,E(ks1,M))) in that the final encrypt is done with ks1. |
| |
| void des_cbc_encrypt( |
| des_cblock *input, |
| des_cblock *output, |
| long length, |
| des_key_schedule ks, |
| des_cblock *ivec, |
| int enc); |
| This routine implements DES in Cipher Block Chaining mode. |
| Input, which should be a multiple of 8 bytes is encrypted |
| (or decrypted) to output which will also be a multiple of 8 bytes. |
| The number of bytes is in length (and from what I've said above, |
| should be a multiple of 8). If length is not a multiple of 8, I'm |
| not being held responsible :-). ivec is the initialisation vector. |
| This function does not modify this variable. To correctly implement |
| cbc mode, you need to do one of 2 things; copy the last 8 bytes of |
| cipher text for use as the next ivec in your application, |
| or use des_ncbc_encrypt(). |
| Only this routine has this problem with updating the ivec, all |
| other routines that are implementing cbc mode update ivec. |
| |
| void des_ncbc_encrypt( |
| des_cblock *input, |
| des_cblock *output, |
| long length, |
| des_key_schedule sk, |
| des_cblock *ivec, |
| int enc); |
| For historical reasons, des_cbc_encrypt() did not update the |
| ivec with the value requires so that subsequent calls to |
| des_cbc_encrypt() would 'chain'. This was needed so that the same |
| 'length' values would not need to be used when decrypting. |
| des_ncbc_encrypt() does the right thing. It is the same as |
| des_cbc_encrypt accept that ivec is updates with the correct value |
| to pass in subsequent calls to des_ncbc_encrypt(). I advise using |
| des_ncbc_encrypt() instead of des_cbc_encrypt(); |
| |
| void des_xcbc_encrypt( |
| des_cblock *input, |
| des_cblock *output, |
| long length, |
| des_key_schedule sk, |
| des_cblock *ivec, |
| des_cblock *inw, |
| des_cblock *outw, |
| int enc); |
| This is RSA's DESX mode of DES. It uses inw and outw to |
| 'whiten' the encryption. inw and outw are secret (unlike the iv) |
| and are as such, part of the key. So the key is sort of 24 bytes. |
| This is much better than cbc des. |
| |
| void des_3cbc_encrypt( |
| des_cblock *input, |
| des_cblock *output, |
| long length, |
| des_key_schedule sk1, |
| des_key_schedule sk2, |
| des_cblock *ivec1, |
| des_cblock *ivec2, |
| int enc); |
| This function is flawed, do not use it. I have left it in the |
| library because it is used in my des(1) program and will function |
| correctly when used by des(1). If I removed the function, people |
| could end up unable to decrypt files. |
| This routine implements outer triple cbc encryption using 2 ks and |
| 2 ivec's. Use des_ede2_cbc_encrypt() instead. |
| |
| void des_ede3_cbc_encrypt( |
| des_cblock *input, |
| des_cblock *output, |
| long length, |
| des_key_schedule ks1, |
| des_key_schedule ks2, |
| des_key_schedule ks3, |
| des_cblock *ivec, |
| int enc); |
| This function implements outer triple CBC DES encryption with 3 |
| keys. What this means is that each 'DES' operation |
| inside the cbc mode is really an C=E(ks3,D(ks2,E(ks1,M))). |
| Again, this is cbc mode so an ivec is requires. |
| This mode is used by SSL. |
| There is also a des_ede2_cbc_encrypt() that only uses 2 |
| des_key_schedule's, the first being reused for the final |
| encryption. C=E(ks1,D(ks2,E(ks1,M))). This form of triple DES |
| is used by the RSAref library. |
| |
| void des_pcbc_encrypt( |
| des_cblock *input, |
| des_cblock *output, |
| long length, |
| des_key_schedule ks, |
| des_cblock *ivec, |
| int enc); |
| This is Propagating Cipher Block Chaining mode of DES. It is used |
| by Kerberos v4. It's parameters are the same as des_ncbc_encrypt(). |
| |
| void des_cfb_encrypt( |
| unsigned char *in, |
| unsigned char *out, |
| int numbits, |
| long length, |
| des_key_schedule ks, |
| des_cblock *ivec, |
| int enc); |
| Cipher Feedback Back mode of DES. This implementation 'feeds back' |
| in numbit blocks. The input (and output) is in multiples of numbits |
| bits. numbits should to be a multiple of 8 bits. Length is the |
| number of bytes input. If numbits is not a multiple of 8 bits, |
| the extra bits in the bytes will be considered padding. So if |
| numbits is 12, for each 2 input bytes, the 4 high bits of the |
| second byte will be ignored. So to encode 72 bits when using |
| a numbits of 12 take 12 bytes. To encode 72 bits when using |
| numbits of 9 will take 16 bytes. To encode 80 bits when using |
| numbits of 16 will take 10 bytes. etc, etc. This padding will |
| apply to both input and output. |
| |
| |
| void des_cfb64_encrypt( |
| unsigned char *in, |
| unsigned char *out, |
| long length, |
| des_key_schedule ks, |
| des_cblock *ivec, |
| int *num, |
| int enc); |
| This is one of the more useful functions in this DES library, it |
| implements CFB mode of DES with 64bit feedback. Why is this |
| useful you ask? Because this routine will allow you to encrypt an |
| arbitrary number of bytes, no 8 byte padding. Each call to this |
| routine will encrypt the input bytes to output and then update ivec |
| and num. num contains 'how far' we are though ivec. If this does |
| not make much sense, read more about cfb mode of DES :-). |
| |
| void des_ede3_cfb64_encrypt( |
| unsigned char *in, |
| unsigned char *out, |
| long length, |
| des_key_schedule ks1, |
| des_key_schedule ks2, |
| des_key_schedule ks3, |
| des_cblock *ivec, |
| int *num, |
| int enc); |
| Same as des_cfb64_encrypt() accept that the DES operation is |
| triple DES. As usual, there is a macro for |
| des_ede2_cfb64_encrypt() which reuses ks1. |
| |
| void des_ofb_encrypt( |
| unsigned char *in, |
| unsigned char *out, |
| int numbits, |
| long length, |
| des_key_schedule ks, |
| des_cblock *ivec); |
| This is a implementation of Output Feed Back mode of DES. It is |
| the same as des_cfb_encrypt() in that numbits is the size of the |
| units dealt with during input and output (in bits). |
| |
| void des_ofb64_encrypt( |
| unsigned char *in, |
| unsigned char *out, |
| long length, |
| des_key_schedule ks, |
| des_cblock *ivec, |
| int *num); |
| The same as des_cfb64_encrypt() except that it is Output Feed Back |
| mode. |
| |
| void des_ede3_ofb64_encrypt( |
| unsigned char *in, |
| unsigned char *out, |
| long length, |
| des_key_schedule ks1, |
| des_key_schedule ks2, |
| des_key_schedule ks3, |
| des_cblock *ivec, |
| int *num); |
| Same as des_ofb64_encrypt() accept that the DES operation is |
| triple DES. As usual, there is a macro for |
| des_ede2_ofb64_encrypt() which reuses ks1. |
| |
| int des_read_pw_string( |
| char *buf, |
| int length, |
| char *prompt, |
| int verify); |
| This routine is used to get a password from the terminal with echo |
| turned off. Buf is where the string will end up and length is the |
| size of buf. Prompt is a string presented to the 'user' and if |
| verify is set, the key is asked for twice and unless the 2 copies |
| match, an error is returned. A return code of -1 indicates a |
| system error, 1 failure due to use interaction, and 0 is success. |
| |
| unsigned long des_cbc_cksum( |
| des_cblock *input, |
| des_cblock *output, |
| long length, |
| des_key_schedule ks, |
| des_cblock *ivec); |
| This function produces an 8 byte checksum from input that it puts in |
| output and returns the last 4 bytes as a long. The checksum is |
| generated via cbc mode of DES in which only the last 8 byes are |
| kept. I would recommend not using this function but instead using |
| the EVP_Digest routines, or at least using MD5 or SHA. This |
| function is used by Kerberos v4 so that is why it stays in the |
| library. |
| |
| char *des_fcrypt( |
| const char *buf, |
| const char *salt |
| char *ret); |
| This is my fast version of the unix crypt(3) function. This version |
| takes only a small amount of space relative to other fast |
| crypt() implementations. This is different to the normal crypt |
| in that the third parameter is the buffer that the return value |
| is written into. It needs to be at least 14 bytes long. This |
| function is thread safe, unlike the normal crypt. |
| |
| char *crypt( |
| const char *buf, |
| const char *salt); |
| This function calls des_fcrypt() with a static array passed as the |
| third parameter. This emulates the normal non-thread safe semantics |
| of crypt(3). |
| |
| void des_string_to_key( |
| char *str, |
| des_cblock *key); |
| This function takes str and converts it into a DES key. I would |
| recommend using MD5 instead and use the first 8 bytes of output. |
| When I wrote the first version of these routines back in 1990, MD5 |
| did not exist but I feel these routines are still sound. This |
| routines is compatible with the one in MIT's libdes. |
| |
| void des_string_to_2keys( |
| char *str, |
| des_cblock *key1, |
| des_cblock *key2); |
| This function takes str and converts it into 2 DES keys. |
| I would recommend using MD5 and using the 16 bytes as the 2 keys. |
| I have nothing against these 2 'string_to_key' routines, it's just |
| that if you say that your encryption key is generated by using the |
| 16 bytes of an MD5 hash, every-one knows how you generated your |
| keys. |
| |
| int des_read_password( |
| des_cblock *key, |
| char *prompt, |
| int verify); |
| This routine combines des_read_pw_string() with des_string_to_key(). |
| |
| int des_read_2passwords( |
| des_cblock *key1, |
| des_cblock *key2, |
| char *prompt, |
| int verify); |
| This routine combines des_read_pw_string() with des_string_to_2key(). |
| |
| void des_random_seed( |
| des_cblock key); |
| This routine sets a starting point for des_random_key(). |
| |
| void des_random_key( |
| des_cblock ret); |
| This function return a random key. Make sure to 'seed' the random |
| number generator (with des_random_seed()) before using this function. |
| I personally now use a MD5 based random number system. |
| |
| int des_enc_read( |
| int fd, |
| char *buf, |
| int len, |
| des_key_schedule ks, |
| des_cblock *iv); |
| This function will write to a file descriptor the encrypted data |
| from buf. This data will be preceded by a 4 byte 'byte count' and |
| will be padded out to 8 bytes. The encryption is either CBC of |
| PCBC depending on the value of des_rw_mode. If it is DES_PCBC_MODE, |
| pcbc is used, if DES_CBC_MODE, cbc is used. The default is to use |
| DES_PCBC_MODE. |
| |
| int des_enc_write( |
| int fd, |
| char *buf, |
| int len, |
| des_key_schedule ks, |
| des_cblock *iv); |
| This routines read stuff written by des_enc_read() and decrypts it. |
| I have used these routines quite a lot but I don't believe they are |
| suitable for non-blocking io. If you are after a full |
| authentication/encryption over networks, have a look at SSL instead. |
| |
| unsigned long des_quad_cksum( |
| des_cblock *input, |
| des_cblock *output, |
| long length, |
| int out_count, |
| des_cblock *seed); |
| This is a function from Kerberos v4 that is not anything to do with |
| DES but was needed. It is a cksum that is quicker to generate than |
| des_cbc_cksum(); I personally would use MD5 routines now. |
| ===== |
| Modes of DES |
| Quite a bit of the following information has been taken from |
| AS 2805.5.2 |
| Australian Standard |
| Electronic funds transfer - Requirements for interfaces, |
| Part 5.2: Modes of operation for an n-bit block cipher algorithm |
| Appendix A |
| |
| There are several different modes in which DES can be used, they are |
| as follows. |
| |
| Electronic Codebook Mode (ECB) (des_ecb_encrypt()) |
| - 64 bits are enciphered at a time. |
| - The order of the blocks can be rearranged without detection. |
| - The same plaintext block always produces the same ciphertext block |
| (for the same key) making it vulnerable to a 'dictionary attack'. |
| - An error will only affect one ciphertext block. |
| |
| Cipher Block Chaining Mode (CBC) (des_cbc_encrypt()) |
| - a multiple of 64 bits are enciphered at a time. |
| - The CBC mode produces the same ciphertext whenever the same |
| plaintext is encrypted using the same key and starting variable. |
| - The chaining operation makes the ciphertext blocks dependent on the |
| current and all preceding plaintext blocks and therefore blocks can not |
| be rearranged. |
| - The use of different starting variables prevents the same plaintext |
| enciphering to the same ciphertext. |
| - An error will affect the current and the following ciphertext blocks. |
| |
| Cipher Feedback Mode (CFB) (des_cfb_encrypt()) |
| - a number of bits (j) <= 64 are enciphered at a time. |
| - The CFB mode produces the same ciphertext whenever the same |
| plaintext is encrypted using the same key and starting variable. |
| - The chaining operation makes the ciphertext variables dependent on the |
| current and all preceding variables and therefore j-bit variables are |
| chained together and can not be rearranged. |
| - The use of different starting variables prevents the same plaintext |
| enciphering to the same ciphertext. |
| - The strength of the CFB mode depends on the size of k (maximal if |
| j == k). In my implementation this is always the case. |
| - Selection of a small value for j will require more cycles through |
| the encipherment algorithm per unit of plaintext and thus cause |
| greater processing overheads. |
| - Only multiples of j bits can be enciphered. |
| - An error will affect the current and the following ciphertext variables. |
| |
| Output Feedback Mode (OFB) (des_ofb_encrypt()) |
| - a number of bits (j) <= 64 are enciphered at a time. |
| - The OFB mode produces the same ciphertext whenever the same |
| plaintext enciphered using the same key and starting variable. More |
| over, in the OFB mode the same key stream is produced when the same |
| key and start variable are used. Consequently, for security reasons |
| a specific start variable should be used only once for a given key. |
| - The absence of chaining makes the OFB more vulnerable to specific attacks. |
| - The use of different start variables values prevents the same |
| plaintext enciphering to the same ciphertext, by producing different |
| key streams. |
| - Selection of a small value for j will require more cycles through |
| the encipherment algorithm per unit of plaintext and thus cause |
| greater processing overheads. |
| - Only multiples of j bits can be enciphered. |
| - OFB mode of operation does not extend ciphertext errors in the |
| resultant plaintext output. Every bit error in the ciphertext causes |
| only one bit to be in error in the deciphered plaintext. |
| - OFB mode is not self-synchronising. If the two operation of |
| encipherment and decipherment get out of synchronism, the system needs |
| to be re-initialised. |
| - Each re-initialisation should use a value of the start variable |
| different from the start variable values used before with the same |
| key. The reason for this is that an identical bit stream would be |
| produced each time from the same parameters. This would be |
| susceptible to a ' known plaintext' attack. |
| |
| Triple ECB Mode (des_ecb3_encrypt()) |
| - Encrypt with key1, decrypt with key2 and encrypt with key3 again. |
| - As for ECB encryption but increases the key length to 168 bits. |
| There are theoretic attacks that can be used that make the effective |
| key length 112 bits, but this attack also requires 2^56 blocks of |
| memory, not very likely, even for the NSA. |
| - If both keys are the same it is equivalent to encrypting once with |
| just one key. |
| - If the first and last key are the same, the key length is 112 bits. |
| There are attacks that could reduce the key space to 55 bit's but it |
| requires 2^56 blocks of memory. |
| - If all 3 keys are the same, this is effectively the same as normal |
| ecb mode. |
| |
| Triple CBC Mode (des_ede3_cbc_encrypt()) |
| - Encrypt with key1, decrypt with key2 and then encrypt with key3. |
| - As for CBC encryption but increases the key length to 168 bits with |
| the same restrictions as for triple ecb mode. |
| |
| ==== digest.doc ======================================================== |
| |
| |
| The Message Digest subroutines. |
| |
| These routines require "evp.h" to be included. |
| |
| These functions are a higher level interface to the various message digest |
| routines found in this library. As such, they allow the same code to be |
| used to digest via different algorithms with only a change in an initial |
| parameter. They are basically just a front-end to the MD2, MD5, SHA |
| and SHA1 |
| routines. |
| |
| These routines all take a pointer to the following structure to specify |
| which message digest algorithm to use. |
| typedef struct evp_md_st |
| { |
| int type; |
| int pkey_type; |
| int md_size; |
| void (*init)(); |
| void (*update)(); |
| void (*final)(); |
| |
| int required_pkey_type; /*EVP_PKEY_xxx */ |
| int (*sign)(); |
| int (*verify)(); |
| } EVP_MD; |
| |
| If additional message digest algorithms are to be supported, a structure of |
| this type needs to be declared and populated and then the Digest routines |
| can be used with that algorithm. The type field is the object NID of the |
| digest type (read the section on Objects for an explanation). The pkey_type |
| is the Object type to use when the a message digest is generated by there |
| routines and then is to be signed with the pkey algorithm. Md_size is |
| the size of the message digest returned. Init, update |
| and final are the relevant functions to perform the message digest function |
| by parts. One reason for specifying the message digest to use via this |
| mechanism is that if you only use md5, only the md5 routines will |
| be included in you linked program. If you passed an integer |
| that specified which message digest to use, the routine that mapped that |
| integer to a set of message digest functions would cause all the message |
| digests functions to be link into the code. This setup also allows new |
| message digest functions to be added by the application. |
| |
| The six message digests defined in this library are |
| |
| EVP_MD *EVP_md2(void); /* RSA sign/verify */ |
| EVP_MD *EVP_md5(void); /* RSA sign/verify */ |
| EVP_MD *EVP_sha(void); /* RSA sign/verify */ |
| EVP_MD *EVP_sha1(void); /* RSA sign/verify */ |
| EVP_MD *EVP_dss(void); /* DSA sign/verify */ |
| EVP_MD *EVP_dss1(void); /* DSA sign/verify */ |
| |
| All the message digest routines take a EVP_MD_CTX pointer as an argument. |
| The state of the message digest is kept in this structure. |
| |
| typedef struct pem_md_ctx_st |
| { |
| EVP_MD *digest; |
| union { |
| unsigned char base[4]; /* this is used in my library as a |
| * 'pointer' to all union elements |
| * structures. */ |
| MD2_CTX md2; |
| MD5_CTX md5; |
| SHA_CTX sha; |
| } md; |
| } EVP_MD_CTX; |
| |
| The Digest functions are as follows. |
| |
| void EVP_DigestInit( |
| EVP_MD_CTX *ctx, |
| EVP_MD *type); |
| This function is used to initialise the EVP_MD_CTX. The message |
| digest that will associated with 'ctx' is specified by 'type'. |
| |
| void EVP_DigestUpdate( |
| EVP_MD_CTX *ctx, |
| unsigned char *data, |
| unsigned int cnt); |
| This function is used to pass more data to the message digest |
| function. 'cnt' bytes are digested from 'data'. |
| |
| void EVP_DigestFinal( |
| EVP_MD_CTX *ctx, |
| unsigned char *md, |
| unsigned int *len); |
| This function finishes the digestion and puts the message digest |
| into 'md'. The length of the message digest is put into len; |
| EVP_MAX_MD_SIZE is the size of the largest message digest that |
| can be returned from this function. Len can be NULL if the |
| size of the digest is not required. |
| |
| |
| ==== encode.doc ======================================================== |
| |
| |
| void EVP_EncodeInit(EVP_ENCODE_CTX *ctx); |
| void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx,unsigned char *out, |
| int *outl,unsigned char *in,int inl); |
| void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl); |
| int EVP_EncodeBlock(unsigned char *t, unsigned char *f, int n); |
| |
| void EVP_DecodeInit(EVP_ENCODE_CTX *ctx); |
| int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx,unsigned char *out,int *outl, |
| unsigned char *in, int inl); |
| int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned |
| char *out, int *outl); |
| int EVP_DecodeBlock(unsigned char *t, unsigned |
| char *f, int n); |
| |
| |
| ==== envelope.doc ======================================================== |
| |
| The following routines are use to create 'digital' envelopes. |
| By this I mean that they perform various 'higher' level cryptographic |
| functions. Have a read of 'cipher.doc' and 'digest.doc' since those |
| routines are used by these functions. |
| cipher.doc contains documentation about the cipher part of the |
| envelope library and digest.doc contatins the description of the |
| message digests supported. |
| |
| To 'sign' a document involves generating a message digest and then encrypting |
| the digest with an private key. |
| |
| #define EVP_SignInit(a,b) EVP_DigestInit(a,b) |
| #define EVP_SignUpdate(a,b,c) EVP_DigestUpdate(a,b,c) |
| Due to the fact this operation is basically just an extended message |
| digest, the first 2 functions are macro calls to Digest generating |
| functions. |
| |
| int EVP_SignFinal( |
| EVP_MD_CTX *ctx, |
| unsigned char *md, |
| unsigned int *s, |
| EVP_PKEY *pkey); |
| This finalisation function finishes the generation of the message |
| digest and then encrypts the digest (with the correct message digest |
| object identifier) with the EVP_PKEY private key. 'ctx' is the message digest |
| context. 'md' will end up containing the encrypted message digest. This |
| array needs to be EVP_PKEY_size(pkey) bytes long. 's' will actually |
| contain the exact length. 'pkey' of course is the private key. It is |
| one of EVP_PKEY_RSA or EVP_PKEY_DSA type. |
| If there is an error, 0 is returned, otherwise 1. |
| |
| Verify is used to check an signed message digest. |
| |
| #define EVP_VerifyInit(a,b) EVP_DigestInit(a,b) |
| #define EVP_VerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c) |
| Since the first step is to generate a message digest, the first 2 functions |
| are macros. |
| |
| int EVP_VerifyFinal( |
| EVP_MD_CTX *ctx, |
| unsigned char *md, |
| unsigned int s, |
| EVP_PKEY *pkey); |
| This function finishes the generation of the message digest and then |
| compares it with the supplied encrypted message digest. 'md' contains the |
| 's' bytes of encrypted message digest. 'pkey' is used to public key decrypt |
| the digest. It is then compared with the message digest just generated. |
| If they match, 1 is returned else 0. |
| |
| int EVP_SealInit(EVP_CIPHER_CTX *ctx, EVP_CIPHER *type, unsigned char **ek, |
| int *ekl, unsigned char *iv, EVP_PKEY **pubk, int npubk); |
| Must have at least one public key, error is 0. I should also mention that |
| the buffers pointed to by 'ek' need to be EVP_PKEY_size(pubk[n]) is size. |
| |
| #define EVP_SealUpdate(a,b,c,d,e) EVP_EncryptUpdate(a,b,c,d,e) |
| void EVP_SealFinal(EVP_CIPHER_CTX *ctx,unsigned char *out,int *outl); |
| |
| |
| int EVP_OpenInit(EVP_CIPHER_CTX *ctx,EVP_CIPHER *type,unsigned char *ek, |
| int ekl,unsigned char *iv,EVP_PKEY *priv); |
| 0 on failure |
| |
| #define EVP_OpenUpdate(a,b,c,d,e) EVP_DecryptUpdate(a,b,c,d,e) |
| |
| int EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); |
| Decrypt final return code |
| |
| |
| ==== error.doc ======================================================== |
| |
| The error routines. |
| |
| The 'error' system I've implemented is intended to server 2 purpose, to |
| record the reason why a command failed and to record where in the libraries |
| the failure occurred. It is more or less setup to record a 'trace' of which |
| library components were being traversed when the error occurred. |
| |
| When an error is recorded, it is done so a as single unsigned long which is |
| composed of three parts. The top byte is the 'library' number, the middle |
| 12 bytes is the function code, and the bottom 12 bits is the 'reason' code. |
| |
| Each 'library', or should a say, 'section' of the SSLeay library has a |
| different unique 'library' error number. Each function in the library has |
| a number that is unique for that library. Each 'library' also has a number |
| for each 'error reason' that is only unique for that 'library'. |
| |
| Due to the way these error routines record a 'error trace', there is an |
| array per thread that is used to store the error codes. |
| The various functions in this library are used to access |
| and manipulate this array. |
| |
| void ERR_put_error(int lib, int func,int reason); |
| This routine records an error in library 'lib', function 'func' |
| and reason 'reason'. As errors get 'put' into the buffer, they wrap |
| around and overwrite old errors if too many are written. It is assumed |
| that the last errors are the most important. |
| |
| unsigned long ERR_get_error(void ); |
| This function returns the last error added to the error buffer. |
| In effect it is popping the value off the buffer so repeated calls will |
| continue to return values until there are no more errors to return in which |
| case 0 is returned. |
| |
| unsigned long ERR_peek_error(void ); |
| This function returns the value of the last error added to the |
| error buffer but does not 'pop' it from the buffer. |
| |
| void ERR_clear_error(void ); |
| This function clears the error buffer, discarding all unread |
| errors. |
| |
| While the above described error system obviously produces lots of different |
| error number, a method for 'reporting' these errors in a human readable |
| form is required. To achieve this, each library has the option of |
| 'registering' error strings. |
| |
| typedef struct ERR_string_data_st |
| { |
| unsigned long error; |
| char *string; |
| } ERR_STRING_DATA; |
| |
| The 'ERR_STRING_DATA' contains an error code and the corresponding text |
| string. To add new function error strings for a library, the |
| ERR_STRING_DATA needs to be 'registered' with the library. |
| |
| void ERR_load_strings(unsigned long lib,ERR_STRING_DATA *err); |
| This function 'registers' the array of ERR_STRING_DATA pointed to by |
| 'err' as error text strings for the error library 'lib'. |
| |
| void ERR_free_strings(void); |
| This function free()s all the loaded error strings. |
| |
| char *ERR_error_string(unsigned long error,char *buf); |
| This function returns a text string that is a human readable |
| version of the error represented by 'error'. Buff should be at least 120 |
| bytes long and if it is NULL, the return value is a pointer to a static |
| variable that will contain the error string, otherwise 'buf' is returned. |
| If there is not a text string registered for a particular error, a text |
| string containing the error number is returned instead. |
| |
| void ERR_print_errors(BIO *bp); |
| void ERR_print_errors_fp(FILE *fp); |
| This function is a convenience routine that prints the error string |
| for each error until all errors have been accounted for. |
| |
| char *ERR_lib_error_string(unsigned long e); |
| char *ERR_func_error_string(unsigned long e); |
| char *ERR_reason_error_string(unsigned long e); |
| The above three functions return the 3 different components strings for the |
| error 'e'. ERR_error_string() uses these functions. |
| |
| void ERR_load_ERR_strings(void ); |
| This function 'registers' the error strings for the 'ERR' module. |
| |
| void ERR_load_crypto_strings(void ); |
| This function 'register' the error strings for just about every |
| library in the SSLeay package except for the SSL routines. There is no |
| need to ever register any error text strings and you will probably save in |
| program size. If on the other hand you do 'register' all errors, it is |
| quite easy to determine why a particular routine failed. |
| |
| As a final footnote as to why the error system is designed as it is. |
| 1) I did not want a single 'global' error code. |
| 2) I wanted to know which subroutine a failure occurred in. |
| 3) For Windows NT etc, it should be simple to replace the 'key' routines |
| with code to pass error codes back to the application. |
| 4) I wanted the option of meaningful error text strings. |
| |
| Late breaking news - the changes to support threads. |
| |
| Each 'thread' has an 'ERR_STATE' state associated with it. |
| ERR_STATE *ERR_get_state(void ) will return the 'state' for the calling |
| thread/process. |
| |
| ERR_remove_state(unsigned long pid); will 'free()' this state. If pid == 0 |
| the current 'thread/process' will have it's error state removed. |
| If you do not remove the error state of a thread, this could be considered a |
| form of memory leak, so just after 'reaping' a thread that has died, |
| call ERR_remove_state(pid). |
| |
| Have a read of thread.doc for more details for what is required for |
| multi-threading support. All the other error routines will |
| work correctly when using threads. |
| |
| |
| ==== idea.doc ======================================================== |
| |
| The IDEA library. |
| IDEA is a block cipher that operates on 64bit (8 byte) quantities. It |
| uses a 128bit (16 byte) key. It can be used in all the modes that DES can |
| be used. This library implements the ecb, cbc, cfb64 and ofb64 modes. |
| |
| For all calls that have an 'input' and 'output' variables, they can be the |
| same. |
| |
| This library requires the inclusion of 'idea.h'. |
| |
| All of the encryption functions take what is called an IDEA_KEY_SCHEDULE as an |
| argument. An IDEA_KEY_SCHEDULE is an expanded form of the idea key. |
| For all modes of the IDEA algorithm, the IDEA_KEY_SCHEDULE used for |
| decryption is different to the one used for encryption. |
| |
| The define IDEA_ENCRYPT is passed to specify encryption for the functions |
| that require an encryption/decryption flag. IDEA_DECRYPT is passed to |
| specify decryption. For some mode there is no encryption/decryption |
| flag since this is determined by the IDEA_KEY_SCHEDULE. |
| |
| So to encrypt you would do the following |
| idea_set_encrypt_key(key,encrypt_ks); |
| idea_ecb_encrypt(...,encrypt_ks); |
| idea_cbc_encrypt(....,encrypt_ks,...,IDEA_ENCRYPT); |
| |
| To Decrypt |
| idea_set_encrypt_key(key,encrypt_ks); |
| idea_set_decrypt_key(encrypt_ks,decrypt_ks); |
| idea_ecb_encrypt(...,decrypt_ks); |
| idea_cbc_encrypt(....,decrypt_ks,...,IDEA_DECRYPT); |
| |
| Please note that any of the encryption modes specified in my DES library |
| could be used with IDEA. I have only implemented ecb, cbc, cfb64 and |
| ofb64 for the following reasons. |
| - ecb is the basic IDEA encryption. |
| - cbc is the normal 'chaining' form for block ciphers. |
| - cfb64 can be used to encrypt single characters, therefore input and output |
| do not need to be a multiple of 8. |
| - ofb64 is similar to cfb64 but is more like a stream cipher, not as |
| secure (not cipher feedback) but it does not have an encrypt/decrypt mode. |
| - If you want triple IDEA, thats 384 bits of key and you must be totally |
| obsessed with security. Still, if you want it, it is simple enough to |
| copy the function from the DES library and change the des_encrypt to |
| idea_encrypt; an exercise left for the paranoid reader :-). |
| |
| The functions are as follows: |
| |
| void idea_set_encrypt_key( |
| unsigned char *key; |
| IDEA_KEY_SCHEDULE *ks); |
| idea_set_encrypt_key converts a 16 byte IDEA key into an |
| IDEA_KEY_SCHEDULE. The IDEA_KEY_SCHEDULE is an expanded form of |
| the key which can be used to perform IDEA encryption. |
| An IDEA_KEY_SCHEDULE is an expanded form of the key which is used to |
| perform actual encryption. It can be regenerated from the IDEA key |
| so it only needs to be kept when encryption is about |
| to occur. Don't save or pass around IDEA_KEY_SCHEDULE's since they |
| are CPU architecture dependent, IDEA keys are not. |
| |
| void idea_set_decrypt_key( |
| IDEA_KEY_SCHEDULE *encrypt_ks, |
| IDEA_KEY_SCHEDULE *decrypt_ks); |
| This functions converts an encryption IDEA_KEY_SCHEDULE into a |
| decryption IDEA_KEY_SCHEDULE. For all decryption, this conversion |
| of the key must be done. In some modes of IDEA, an |
| encryption/decryption flag is also required, this is because these |
| functions involve block chaining and the way this is done changes |
| depending on which of encryption of decryption is being done. |
| Please note that there is no quick way to generate the decryption |
| key schedule other than generating the encryption key schedule and |
| then converting it. |
| |
| void idea_encrypt( |
| unsigned long *data, |
| IDEA_KEY_SCHEDULE *ks); |
| This is the IDEA encryption function that gets called by just about |
| every other IDEA routine in the library. You should not use this |
| function except to implement 'modes' of IDEA. I say this because the |
| functions that call this routine do the conversion from 'char *' to |
| long, and this needs to be done to make sure 'non-aligned' memory |
| access do not occur. |
| Data is a pointer to 2 unsigned long's and ks is the |
| IDEA_KEY_SCHEDULE to use. Encryption or decryption depends on the |
| IDEA_KEY_SCHEDULE. |
| |
| void idea_ecb_encrypt( |
| unsigned char *input, |
| unsigned char *output, |
| IDEA_KEY_SCHEDULE *ks); |
| This is the basic Electronic Code Book form of IDEA (in DES this |
| mode is called Electronic Code Book so I'm going to use the term |
| for idea as well :-). |
| Input is encrypted into output using the key represented by |
| ks. Depending on the IDEA_KEY_SCHEDULE, encryption or |
| decryption occurs. Input is 8 bytes long and output is 8 bytes. |
| |
| void idea_cbc_encrypt( |
| unsigned char *input, |
| unsigned char *output, |
| long length, |
| IDEA_KEY_SCHEDULE *ks, |
| unsigned char *ivec, |
| int enc); |
| This routine implements IDEA in Cipher Block Chaining mode. |
| Input, which should be a multiple of 8 bytes is encrypted |
| (or decrypted) to output which will also be a multiple of 8 bytes. |
| The number of bytes is in length (and from what I've said above, |
| should be a multiple of 8). If length is not a multiple of 8, bad |
| things will probably happen. ivec is the initialisation vector. |
| This function updates iv after each call so that it can be passed to |
| the next call to idea_cbc_encrypt(). |
| |
| void idea_cfb64_encrypt( |
| unsigned char *in, |
| unsigned char *out, |
| long length, |
| des_key_schedule ks, |
| des_cblock *ivec, |
| int *num, |
| int enc); |
| This is one of the more useful functions in this IDEA library, it |
| implements CFB mode of IDEA with 64bit feedback. |
| This allows you to encrypt an arbitrary number of bytes, |
| you do not require 8 byte padding. Each call to this |
| routine will encrypt the input bytes to output and then update ivec |
| and num. Num contains 'how far' we are though ivec. |
| Enc is used to indicate encryption or decryption. |
| One very important thing to remember is that when decrypting, use |
| the encryption form of the key. |
| CFB64 mode operates by using the cipher to |
| generate a stream of bytes which is used to encrypt the plain text. |
| The cipher text is then encrypted to generate the next 64 bits to |
| be xored (incrementally) with the next 64 bits of plain |
| text. As can be seen from this, to encrypt or decrypt, |
| the same 'cipher stream' needs to be generated but the way the next |
| block of data is gathered for encryption is different for |
| encryption and decryption. What this means is that to encrypt |
| idea_set_encrypt_key(key,ks); |
| idea_cfb64_encrypt(...,ks,..,IDEA_ENCRYPT) |
| do decrypt |
| idea_set_encrypt_key(key,ks) |
| idea_cfb64_encrypt(...,ks,...,IDEA_DECRYPT) |
| Note: The same IDEA_KEY_SCHEDULE but different encryption flags. |
| For idea_cbc or idea_ecb, idea_set_decrypt_key() would need to be |
| used to generate the IDEA_KEY_SCHEDULE for decryption. |
| The reason I'm stressing this point is that I just wasted 3 hours |
| today trying to decrypt using this mode and the decryption form of |
| the key :-(. |
| |
| void idea_ofb64_encrypt( |
| unsigned char *in, |
| unsigned char *out, |
| long length, |
| des_key_schedule ks, |
| des_cblock *ivec, |
| int *num); |
| This functions implements OFB mode of IDEA with 64bit feedback. |
| This allows you to encrypt an arbitrary number of bytes, |
| you do not require 8 byte padding. Each call to this |
| routine will encrypt the input bytes to output and then update ivec |
| and num. Num contains 'how far' we are though ivec. |
| This is in effect a stream cipher, there is no encryption or |
| decryption mode. The same key and iv should be used to |
| encrypt and decrypt. |
| |
| For reading passwords, I suggest using des_read_pw_string() from my DES library. |
| To generate a password from a text string, I suggest using MD5 (or MD2) to |
| produce a 16 byte message digest that can then be passed directly to |
| idea_set_encrypt_key(). |
| |
| ===== |
| For more information about the specific IDEA modes in this library |
| (ecb, cbc, cfb and ofb), read the section entitled 'Modes of DES' from the |
| documentation on my DES library. What is said about DES is directly |
| applicable for IDEA. |
| |
| |
| ==== legal.doc ======================================================== |
| |
| From eay@mincom.com Thu Jun 27 00:25:45 1996 |
| Received: by orb.mincom.oz.au id AA15821 |
| (5.65c/IDA-1.4.4 for eay); Wed, 26 Jun 1996 14:25:45 +1000 |
| Date: Wed, 26 Jun 1996 14:25:45 +1000 (EST) |
| From: Eric Young <eay@mincom.oz.au> |
| X-Sender: eay@orb |
| To: Ken Toll <ktoll@ren.digitalage.com> |
| Cc: Eric Young <eay@mincom.oz.au>, ssl-talk@netscape.com |
| Subject: Re: Unidentified subject! |
| In-Reply-To: <9606261950.ZM28943@ren.digitalage.com> |
| Message-Id: <Pine.SOL.3.91.960626131156.28573K-100000@orb> |
| Mime-Version: 1.0 |
| Content-Type: TEXT/PLAIN; charset=US-ASCII |
| Status: O |
| X-Status: |
| |
| |
| This is a little off topic but since SSLeay is a free implementation of |
| the SSLv2 protocol, I feel it is worth responding on the topic of if it |
| is actually legal for Americans to use free cryptographic software. |
| |
| On Wed, 26 Jun 1996, Ken Toll wrote: |
| > Is the U.S the only country that SSLeay cannot be used commercially |
| > (because of RSAref) or is that going to be an issue with every country |
| > that a client/server application (non-web browser/server) is deployed |
| > and sold? |
| |
| >From what I understand, the software patents that apply to algorithms |
| like RSA and DH only apply in the USA. The IDEA algorithm I believe is |
| patened in europe (USA?), but considing how little it is used by other SSL |
| implementations, it quite easily be left out of the SSLeay build |
| (this can be done with a compile flag). |
| |
| Actually if the RSA patent did apply outside the USA, it could be rather |
| interesting since RSA is not alowed to let RSA toolkits outside of the USA |
| [1], and since these are the only forms that they will alow the algorithm |
| to be used in, it would mean that non-one outside of the USA could produce |
| public key software which would be a very strong statment for |
| international patent law to make :-). This logic is a little flawed but |
| it still points out some of the more interesting permutations of USA |
| patent law and ITAR restrictions. |
| |
| Inside the USA there is also the unresolved issue of RC4/RC2 which were |
| made public on sci.crypt in Sep 1994 (RC4) and Feb 1996 (RC2). I have |
| copies of the origional postings if people are interested. RSA I believe |
| claim that they were 'trade-secrets' and that some-one broke an NDA in |
| revealing them. Other claim they reverse engineered the algorithms from |
| compiled binaries. If the algorithms were reverse engineered, I believe |
| RSA had no legal leg to stand on. If an NDA was broken, I don't know. |
| Regardless, RSA, I believe, is willing to go to court over the issue so |
| licencing is probably the best idea, or at least talk to them. |
| If there are people who actually know more about this, pease let me know, I |
| don't want to vilify or spread miss-information if I can help it. |
| |
| If you are not producing a web browser, it is easy to build SSLeay with |
| RC2/RC4 removed. Since RC4 is the defacto standard cipher in |
| all web software (and it is damn fast) it is more or less required for |
| www use. For non www use of SSL, especially for an application where |
| interoperability with other vendors is not critical just leave it out. |
| |
| Removing IDEA, RC2 and RC4 would only leave DES and Triple DES but |
| they should be ok. Considing that Triple DES can encrypt at rates of |
| 410k/sec on a pentium 100, and 940k/sec on a P6/200, this is quite |
| reasonable performance. Single DES clocks in at 1160k/s and 2467k/s |
| respectivly is actually quite fast for those not so paranoid (56 bit key).[1] |
| |
| > Is it possible to get a certificate for commercial use outside of the U.S.? |
| yes. |
| |
| Thawte Consulting issues certificates (they are the people who sell the |
| Sioux httpd server and are based in South Africa) |
| Verisign will issue certificates for Sioux (sold from South Africa), so this |
| proves that they will issue certificate for OS use if they are |
| happy with the quality of the software. |
| |
| (The above mentioned companies just the ones that I know for sure are issuing |
| certificates outside the USA). |
| |
| There is always the point that if you are using SSL for an intra net, |
| SSLeay provides programs that can be used so you can issue your own |
| certificates. They need polishing but at least it is a good starting point. |
| |
| I am not doing anything outside Australian law by implementing these |
| algorithms (to the best of my knowedge). It is another example of how |
| the world legal system does not cope with the internet very well. |
| |
| I may start making shared libraries available (I have now got DLL's for |
| Windows). This will mean that distributions into the usa could be |
| shipped with a version with a reduced cipher set and the versions outside |
| could use the DLL/shared library with all the ciphers (and without RSAref). |
| |
| This could be completly hidden from the application, so this would not |
| even require a re-linking. |
| |
| This is the reverse of what people were talking about doing to get around |
| USA export regulations :-) |
| |
| eric |
| |
| [1]: The RSAref2.0 tookit is available on at least 3 ftp sites in Europe |
| and one in South Africa. |
| |
| [2]: Since I always get questions when I post benchmark numbers :-), |
| DES performace figures are in 1000's of bytes per second in cbc |
| mode using an 8192 byte buffer. The pentium 100 was running Windows NT |
| 3.51 DLLs and the 686/200 was running NextStep. |
| I quote pentium 100 benchmarks because it is basically the |
| 'entry level' computer that most people buy for personal use. |
| Windows 95 is the OS shipping on those boxes, so I'll give |
| NT numbers (the same Win32 runtime environment). The 686 |
| numbers are present as an indication of where we will be in a |
| few years. |
| -- |
| Eric Young | BOOL is tri-state according to Bill Gates. |
| AARNet: eay@mincom.oz.au | RTFM Win32 GetMessage(). |
| |
| |
| |
| ==== lhash.doc ======================================================== |
| |
| The LHASH library. |
| |
| I wrote this library in 1991 and have since forgotten why I called it lhash. |
| It implements a hash table from an article I read at the |
| time from 'Communications of the ACM'. What makes this hash |
| table different is that as the table fills, the hash table is |
| increased (or decreased) in size via realloc(). |
| When a 'resize' is done, instead of all hashes being redistributed over |
| twice as many 'buckets', one bucket is split. So when an 'expand' is done, |
| there is only a minimal cost to redistribute some values. Subsequent |
| inserts will cause more single 'bucket' redistributions but there will |
| never be a sudden large cost due to redistributing all the 'buckets'. |
| |
| The state for a particular hash table is kept in the LHASH structure. |
| The LHASH structure also records statistics about most aspects of accessing |
| the hash table. This is mostly a legacy of my writing this library for |
| the reasons of implementing what looked like a nice algorithm rather than |
| for a particular software product. |
| |
| Internal stuff you probably don't want to know about. |
| The decision to increase or decrease the hash table size is made depending |
| on the 'load' of the hash table. The load is the number of items in the |
| hash table divided by the size of the hash table. The default values are |
| as follows. If (hash->up_load < load) => expand. |
| if (hash->down_load > load) => contract. The 'up_load' has a default value of |
| 1 and 'down_load' has a default value of 2. These numbers can be modified |
| by the application by just playing with the 'up_load' and 'down_load' |
| variables. The 'load' is kept in a form which is multiplied by 256. So |
| hash->up_load=8*256; will cause a load of 8 to be set. |
| |
| If you are interested in performance the field to watch is |
| num_comp_calls. The hash library keeps track of the 'hash' value for |
| each item so when a lookup is done, the 'hashes' are compared, if |
| there is a match, then a full compare is done, and |
| hash->num_comp_calls is incremented. If num_comp_calls is not equal |
| to num_delete plus num_retrieve it means that your hash function is |
| generating hashes that are the same for different values. It is |
| probably worth changing your hash function if this is the case because |
| even if your hash table has 10 items in a 'bucked', it can be searched |
| with 10 'unsigned long' compares and 10 linked list traverses. This |
| will be much less expensive that 10 calls to you compare function. |
| |
| LHASH *lh_new( |
| unsigned long (*hash)(), |
| int (*cmp)()); |
| This function is used to create a new LHASH structure. It is passed |
| function pointers that are used to store and retrieve values passed |
| into the hash table. The 'hash' |
| function is a hashing function that will return a hashed value of |
| it's passed structure. 'cmp' is passed 2 parameters, it returns 0 |
| is they are equal, otherwise, non zero. |
| If there are any problems (usually malloc failures), NULL is |
| returned, otherwise a new LHASH structure is returned. The |
| hash value is normally truncated to a power of 2, so make sure |
| that your hash function returns well mixed low order bits. |
| |
| void lh_free( |
| LHASH *lh); |
| This function free()s a LHASH structure. If there is malloced |
| data in the hash table, it will not be freed. Consider using the |
| lh_doall function to deallocate any remaining entries in the hash |
| table. |
| |
| char *lh_insert( |
| LHASH *lh, |
| char *data); |
| This function inserts the data pointed to by data into the lh hash |
| table. If there is already and entry in the hash table entry, the |
| value being replaced is returned. A NULL is returned if the new |
| entry does not clash with an entry already in the table (the normal |
| case) or on a malloc() failure (perhaps I should change this....). |
| The 'char *data' is exactly what is passed to the hash and |
| comparison functions specified in lh_new(). |
| |
| char *lh_delete( |
| LHASH *lh, |
| char *data); |
| This routine deletes an entry from the hash table. The value being |
| deleted is returned. NULL is returned if there is no such value in |
| the hash table. |
| |
| char *lh_retrieve( |
| LHASH *lh, |
| char *data); |
| If 'data' is in the hash table it is returned, else NULL is |
| returned. The way these routines would normally be uses is that a |
| dummy structure would have key fields populated and then |
| ret=lh_retrieve(hash,&dummy);. Ret would now be a pointer to a fully |
| populated structure. |
| |
| void lh_doall( |
| LHASH *lh, |
| void (*func)(char *a)); |
| This function will, for every entry in the hash table, call function |
| 'func' with the data item as parameters. |
| This function can be quite useful when used as follows. |
| void cleanup(STUFF *a) |
| { STUFF_free(a); } |
| lh_doall(hash,cleanup); |
| lh_free(hash); |
| This can be used to free all the entries, lh_free() then |
| cleans up the 'buckets' that point to nothing. Be careful |
| when doing this. If you delete entries from the hash table, |
| in the call back function, the table may decrease in size, |
| moving item that you are |
| currently on down lower in the hash table. This could cause |
| some entries to be skipped. The best solution to this problem |
| is to set lh->down_load=0 before you start. This will stop |
| the hash table ever being decreased in size. |
| |
| void lh_doall_arg( |
| LHASH *lh; |
| void(*func)(char *a,char *arg)); |
| char *arg; |
| This function is the same as lh_doall except that the function |
| called will be passed 'arg' as the second argument. |
| |
| unsigned long lh_strhash( |
| char *c); |
| This function is a demo string hashing function. Since the LHASH |
| routines would normally be passed structures, this routine would |
| not normally be passed to lh_new(), rather it would be used in the |
| function passed to lh_new(). |
| |
| The next three routines print out various statistics about the state of the |
| passed hash table. These numbers are all kept in the lhash structure. |
| |
| void lh_stats( |
| LHASH *lh, |
| FILE *out); |
| This function prints out statistics on the size of the hash table, |
| how many entries are in it, and the number and result of calls to |
| the routines in this library. |
| |
| void lh_node_stats( |
| LHASH *lh, |
| FILE *out); |
| For each 'bucket' in the hash table, the number of entries is |
| printed. |
| |
| void lh_node_usage_stats( |
| LHASH *lh, |
| FILE *out); |
| This function prints out a short summary of the state of the hash |
| table. It prints what I call the 'load' and the 'actual load'. |
| The load is the average number of data items per 'bucket' in the |
| hash table. The 'actual load' is the average number of items per |
| 'bucket', but only for buckets which contain entries. So the |
| 'actual load' is the average number of searches that will need to |
| find an item in the hash table, while the 'load' is the average number |
| that will be done to record a miss. |
| |
| ==== md2.doc ======================================================== |
| |
| The MD2 library. |
| MD2 is a message digest algorithm that can be used to condense an arbitrary |
| length message down to a 16 byte hash. The functions all need to be passed |
| a MD2_CTX which is used to hold the MD2 context during multiple MD2_Update() |
| function calls. The normal method of use for this library is as follows |
| |
| MD2_Init(...); |
| MD2_Update(...); |
| ... |
| MD2_Update(...); |
| MD2_Final(...); |
| |
| This library requires the inclusion of 'md2.h'. |
| |
| The main negative about MD2 is that it is slow, especially when compared |
| to MD5. |
| |
| The functions are as follows: |
| |
| void MD2_Init( |
| MD2_CTX *c); |
| This function needs to be called to initiate a MD2_CTX structure for |
| use. |
| |
| void MD2_Update( |
| MD2_CTX *c; |
| unsigned char *data; |
| unsigned long len); |
| This updates the message digest context being generated with 'len' |
| bytes from the 'data' pointer. The number of bytes can be any |
| length. |
| |
| void MD2_Final( |
| unsigned char *md; |
| MD2_CTX *c; |
| This function is called when a message digest of the data digested |
| with MD2_Update() is wanted. The message digest is put in the 'md' |
| array and is MD2_DIGEST_LENGTH (16) bytes long. |
| |
| unsigned char *MD2( |
| unsigned long n; |
| unsigned char *d; |
| unsigned char *md; |
| This function performs a MD2_Init(), followed by a MD2_Update() |
| followed by a MD2_Final() (using a local MD2_CTX). |
| The resulting digest is put into 'md' if it is not NULL. |
| Regardless of the value of 'md', the message |
| digest is returned from the function. If 'md' was NULL, the message |
| digest returned is being stored in a static structure. |
| |
| ==== md5.doc ======================================================== |
| |
| The MD5 library. |
| MD5 is a message digest algorithm that can be used to condense an arbitrary |
| length message down to a 16 byte hash. The functions all need to be passed |
| a MD5_CTX which is used to hold the MD5 context during multiple MD5_Update() |
| function calls. This library also contains random number routines that are |
| based on MD5 |
| |
| The normal method of use for this library is as follows |
| |
| MD5_Init(...); |
| MD5_Update(...); |
| ... |
| MD5_Update(...); |
| MD5_Final(...); |
| |
| This library requires the inclusion of 'md5.h'. |
| |
| The functions are as follows: |
| |
| void MD5_Init( |
| MD5_CTX *c); |
| This function needs to be called to initiate a MD5_CTX structure for |
| use. |
| |
| void MD5_Update( |
| MD5_CTX *c; |
| unsigned char *data; |
| unsigned long len); |
| This updates the message digest context being generated with 'len' |
| bytes from the 'data' pointer. The number of bytes can be any |
| length. |
| |
| void MD5_Final( |
| unsigned char *md; |
| MD5_CTX *c; |
| This function is called when a message digest of the data digested |
| with MD5_Update() is wanted. The message digest is put in the 'md' |
| array and is MD5_DIGEST_LENGTH (16) bytes long. |
| |
| unsigned char *MD5( |
| unsigned char *d; |
| unsigned long n; |
| unsigned char *md; |
| This function performs a MD5_Init(), followed by a MD5_Update() |
| followed by a MD5_Final() (using a local MD5_CTX). |
| The resulting digest is put into 'md' if it is not NULL. |
| Regardless of the value of 'md', the message |
| digest is returned from the function. If 'md' was NULL, the message |
| digest returned is being stored in a static structure. |
| |
| |
| ==== memory.doc ======================================================== |
| |
| In the interests of debugging SSLeay, there is an option to compile |
| using some simple memory leak checking. |
| |
| All malloc(), free() and realloc() calls in SSLeay now go via |
| Malloc(), Free() and Realloc() (except those in crypto/lhash). |
| |
| If CRYPTO_MDEBUG is defined, these calls are #defined to |
| CRYPTO_malloc(), CRYPTO_free() and CRYPTO_realloc(). |
| If it is not defined, they are #defined to malloc(), free() and realloc(). |
| |
| the CRYPTO_malloc() routines by default just call the underlying library |
| functons. |
| |
| If CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON) is called, memory leak detection is |
| turned on. CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF) turns it off. |
| |
| When turned on, each Malloc() or Realloc() call is recored along with the file |
| and line number from where the call was made. (This is done using the |
| lhash library which always uses normal system malloc(3) routines). |
| |
| void CRYPTO_mem_leaks(BIO *b); |
| void CRYPTO_mem_leaks_fp(FILE *fp); |
| These both print out the list of memory that has not been free()ed. |
| This will probably be rather hard to read, but if you look for the 'top level' |
| structure allocation, this will often give an idea as to what is not being |
| free()ed. I don't expect people to use this stuff normally. |
| |
| ==== ca.1 ======================================================== |
| |
| From eay@orb.mincom.oz.au Thu Dec 28 23:56:45 1995 |
|