RFC4507 (including RFC4507bis) TLS stateless session resumption support

for OpenSSL.
This commit is contained in:
Dr. Stephen Henson
2007-08-11 23:18:29 +00:00
parent e45c100762
commit 6434abbfc6
19 changed files with 781 additions and 23 deletions

View File

@@ -158,6 +158,7 @@
#include <openssl/rand.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/x509.h>
#ifndef OPENSSL_NO_DH
#include <openssl/dh.h>
@@ -529,11 +530,26 @@ int ssl3_accept(SSL *s)
if (ret <= 0) goto end;
if (s->hit)
s->state=SSL_ST_OK;
#ifndef OPENSSL_NO_TLSEXT
else if (s->tlsext_ticket_expected)
s->state=SSL3_ST_SW_SESSION_TICKET_A;
#endif
else
s->state=SSL3_ST_SW_CHANGE_A;
s->init_num=0;
break;
#ifndef OPENSSL_NO_TLSEXT
case SSL3_ST_SW_SESSION_TICKET_A:
case SSL3_ST_SW_SESSION_TICKET_B:
ret=ssl3_send_newsession_ticket(s);
if (ret <= 0) goto end;
s->state=SSL3_ST_SW_CHANGE_A;
s->init_num=0;
break;
#endif
case SSL3_ST_SW_CHANGE_A:
case SSL3_ST_SW_CHANGE_B:
@@ -762,14 +778,14 @@ int ssl3_get_client_hello(SSL *s)
* might be written that become totally unsecure when compiled with
* an earlier library version)
*/
if (j == 0 || (s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)))
if ((s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)))
{
if (!ssl_get_new_session(s,1))
goto err;
}
else
{
i=ssl_get_prev_session(s,p,j);
i=ssl_get_prev_session(s, p, j, d + n);
if (i == 1)
{ /* previous session */
s->hit=1;
@@ -2714,3 +2730,90 @@ int ssl3_send_server_certificate(SSL *s)
/* SSL3_ST_SW_CERT_B */
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
}
#ifndef OPENSSLP_NO_TLSEXT
int ssl3_send_newsession_ticket(SSL *s)
{
if (s->state == SSL3_ST_SW_SESSION_TICKET_A)
{
unsigned char *p, *senc, *macstart;
int len, slen;
unsigned int hlen;
EVP_CIPHER_CTX ctx;
HMAC_CTX hctx;
/* get session encoding length */
slen = i2d_SSL_SESSION(s->session, NULL);
/* Some length values are 16 bits, so forget it if session is
* too long
*/
if (slen > 0xFF00)
return -1;
/* Grow buffer if need be: the length calculation is as
* follows 1 (size of message name) + 3 (message length
* bytes) + 4 (ticket lifetime hint) + 2 (ticket length) +
* 16 (key name) + max_iv_len (iv length) +
* session_length + max_enc_block_size (max encrypted session
* length) + max_md_size (HMAC).
*/
if (!BUF_MEM_grow(s->init_buf,
26 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH +
EVP_MAX_MD_SIZE + slen))
return -1;
senc = OPENSSL_malloc(slen);
if (!senc)
return -1;
p = senc;
i2d_SSL_SESSION(s->session, &p);
p=(unsigned char *)s->init_buf->data;
/* do the header */
*(p++)=SSL3_MT_NEWSESSION_TICKET;
/* Skip message length for now */
p += 3;
l2n(s->session->tlsext_tick_lifetime_hint, p);
/* Skip ticket length for now */
p += 2;
/* Output key name */
macstart = p;
memcpy(p, s->ctx->tlsext_tick_key_name, 16);
p += 16;
/* Generate and output IV */
RAND_pseudo_bytes(p, 16);
EVP_CIPHER_CTX_init(&ctx);
/* Encrypt session data */
EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
s->ctx->tlsext_tick_aes_key, p);
p += 16;
EVP_EncryptUpdate(&ctx, p, &len, senc, slen);
p += len;
EVP_EncryptFinal(&ctx, p, &len);
p += len;
EVP_CIPHER_CTX_cleanup(&ctx);
HMAC_CTX_init(&hctx);
HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16,
EVP_sha1(), NULL);
HMAC_Update(&hctx, macstart, p - macstart);
HMAC_Final(&hctx, p, &hlen);
HMAC_CTX_cleanup(&hctx);
p += hlen;
/* Now write out lengths: p points to end of data written */
/* Total length */
len = p - (unsigned char *)s->init_buf->data;
p=(unsigned char *)s->init_buf->data + 1;
l2n3(len - 4, p); /* Message length */
p += 4;
s2n(len - 10, p); /* Ticket length */
/* number of bytes to write */
s->init_num= len;
s->state=SSL3_ST_SW_SESSION_TICKET_B;
s->init_off=0;
OPENSSL_free(senc);
}
/* SSL3_ST_SW_SESSION_TICKET_B */
return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
}
#endif