| =pod |
| |
| =head1 NAME |
| |
| SSL_CTX_set_tlsext_ticket_key_cb - set a callback for session ticket processing |
| |
| =head1 SYNOPSIS |
| |
| #include <openssl/tls1.h> |
| |
| long SSL_CTX_set_tlsext_ticket_key_cb(SSL_CTX sslctx, |
| int (*cb)(SSL *s, unsigned char key_name[16], |
| unsigned char iv[EVP_MAX_IV_LENGTH], |
| EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc)); |
| |
| =head1 DESCRIPTION |
| |
| SSL_CTX_set_tlsext_ticket_key_cb() sets a callback fuction I<cb> for handling |
| session tickets for the ssl context I<sslctx>. Session tickets, defined in |
| RFC5077 provide an enhanced session resumption capability where the server |
| implementation is not required to maintain per session state. It only applies |
| to TLS and there is no SSLv3 implementation. |
| |
| The callback is available when the OpenSSL library was built without |
| I<OPENSSL_NO_TLSEXT> being defined. |
| |
| The callback function I<cb> will be called for every client instigated TLS |
| session when session ticket extension is presented in the TLS hello |
| message. It is the responsibility of this function to create or retrieve the |
| cryptographic parameters and to maintain their state. |
| |
| The OpenSSL library uses your callback function to help implement a common TLS |
| ticket construction state according to RFC5077 Section 4 such that per session |
| state is unnecessary and a small set of cryptographic variables needs to be |
| maintained by the callback function implementation. |
| |
| In order to reuse a session, a TLS client must send the a session ticket |
| extension to the server. The client can only send exactly one session ticket. |
| The server, through the callback function, either agrees to reuse the session |
| ticket information or it starts a full TLS handshake to create a new session |
| ticket. |
| |
| Before the callback function is started I<ctx> and I<hctx> have been |
| initialised with EVP_CIPHER_CTX_init and HMAC_CTX_init respectively. |
| |
| For new sessions tickets, when the client doesn't present a session ticket, or |
| an attempted retreival of the ticket failed, or a renew option was indicated, |
| the callback function will be called with I<enc> equal to 1. The OpenSSL |
| library expects that the function will set an arbitary I<name>, initialize |
| I<iv>, and set the cipher context I<ctx> and the hash context I<hctx>. |
| |
| The I<name> is 16 characters long and is used as a key identifier. |
| |
| The I<iv> length is the length of the IV of the corresponding cipher. The |
| maximum IV length is L<EVP_MAX_IV_LENGTH> bytes defined in B<evp.h>. |
| |
| The initialization vector I<iv> should be a random value. The cipher context |
| I<ctx> should use the initialisation vector I<iv>. The cipher context can be |
| set using L<EVP_EncryptInit_ex>. The hmac context can be set using L<HMAC_Init_ex>. |
| |
| When the client presents a session ticket, the callback function with be called |
| with I<enc> set to 0 indicating that the I<cb> function should retreive a set |
| of parameters. In this case I<name> and I<iv> have already been parsed out of |
| the session ticket. The OpenSSL library expects that the I<name> will be used |
| to retrieve a cryptographic parameters and that the cryptographic context |
| I<ctx> will be set with the retreived parameters and the initialization vector |
| I<iv>. using a function like L<EVP_DecryptInit_ex>. The I<hctx> needs to be set |
| using L<HMAC_Init_ex>. |
| |
| If the I<name> is still valid but a renewal of the ticket is required the |
| callback function should return 2. The library will call the callback again |
| with an arguement of enc equal to 1 to set the new ticket. |
| |
| The return value of the I<cb> function is used by OpenSSL to determine what |
| further processing will occur. The following return values have meaning: |
| |
| =over 4 |
| |
| =item Z<>2 |
| |
| This indicates that the I<ctx> and I<hctx> have been set and the session can |
| continue on those parameters. Additionally it indicates that the session |
| ticket is in a renewal period and should be replaced. The OpenSSL library will |
| call I<cb> again with an enc argument of 1 to set the new ticket (see RFC5077 |
| 3.3 paragraph 2). |
| |
| =item Z<>1 |
| |
| This indicates that the I<ctx> and I<hctx> have been set and the session can |
| continue on those parameters. |
| |
| =item Z<>0 |
| |
| This indicates that it was not possible to set/retrieve a session ticket and |
| the SSL/TLS session will continue by by negiotationing a set of cryptographic |
| parameters or using the alternate SSL/TLS resumption mechanism, session ids. |
| |
| If called with enc equal to 0 the library will call the I<cb> again to get |
| a new set of parameters. |
| |
| =item less than 0 |
| |
| This indicates an error. |
| |
| =back |
| |
| =head1 NOTES |
| |
| Session resumption shortcuts the TLS so that the client certificate |
| negiotation don't occur. It makes up for this by storing client certificate |
| an all other negotiated state information encrypted within the ticket. In a |
| resumed session the applications will have all this state information available |
| exactly as if a full negiotation had occured. |
| |
| If an attacker can obtain the key used to encrypt a session ticket, they can |
| obtain the master secret for any ticket using that key and decrypt any traffic |
| using that session: even if the ciphersuite supports forward secrecy. As |
| a result applications may wish to use multiple keys and avoid using long term |
| keys stored in files. |
| |
| Applications can use longer keys to maintain a consistent level of security. |
| For example if a ciphersuite uses 256 bit ciphers but only a 128 bit ticket key |
| the overall security is only 128 bits because breaking the ticket key will |
| enable an attacker to obtain the session keys. |
| |
| =head1 EXAMPLES |
| |
| Reference Implemention: |
| SSL_CTX_set_tlsext_ticket_key_cb(SSL,ssl_tlsext_ticket_key_cb); |
| .... |
| |
| static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16], unsigned char *iv, EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc) |
| { |
| if (enc) { /* create new session */ |
| if (RAND_bytes(iv, EVP_MAX_IV_LENGTH) ) { |
| return -1; /* insufficient random */ |
| } |
| |
| key = currentkey(); /* something that you need to implement */ |
| if ( !key ) { |
| /* current key doesn't exist or isn't valid */ |
| key = createkey(); /* something that you need to implement. |
| * createkey needs to initialise, a name, |
| * an aes_key, a hmac_key and optionally |
| * an expire time. */ |
| if ( !key ) { /* key couldn't be created */ |
| return 0; |
| } |
| } |
| memcpy(key_name, key->name, 16); |
| |
| EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key->aes_key, iv); |
| HMAC_Init_ex(&hctx, key->hmac_key, 16, EVP_sha256(), NULL); |
| |
| return 1; |
| |
| } else { /* retrieve session */ |
| key = findkey(name); |
| |
| if (!key || key->expire < now() ) { |
| return 0; |
| } |
| |
| HMAC_Init_ex(&hctx, key->hmac_key, 16, EVP_sha256(), NULL); |
| EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key->aes_key, iv ); |
| |
| if (key->expire < ( now() - RENEW_TIME ) ) { |
| /* return 2 - this session will get a new ticket even though the current is still valid */ |
| return 2; |
| } |
| return 1; |
| |
| } |
| } |
| |
| |
| |
| =head1 RETURN VALUES |
| |
| returns 0 to indicate the callback function was set. |
| |
| =head1 SEE ALSO |
| |
| L<ssl(3)|ssl(3)>, L<SSL_set_session(3)|SSL_set_session(3)>, |
| L<SSL_session_reused(3)|SSL_session_reused(3)>, |
| L<SSL_CTX_add_session(3)|SSL_CTX_add_session(3)>, |
| L<SSL_CTX_sess_number(3)|SSL_CTX_sess_number(3)>, |
| L<SSL_CTX_sess_set_get_cb(3)|SSL_CTX_sess_set_get_cb(3)>, |
| L<SSL_CTX_set_session_id_context(3)|SSL_CTX_set_session_id_context(3)>, |
| |
| =head1 HISTORY |
| |
| This function was introduced in OpenSSL 0.9.8h |
| |
| =cut |