diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2008-04-30 16:11:33 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2008-04-30 16:11:33 +0000 |
commit | db533c96e35ccdb8f97f0e5e98ab9db9c4938ca1 (patch) | |
tree | c1f1d11c3ad840a17626e453cec54c5e10cf970d /ssl | |
parent | 8831eb7624992ded000310586c99cf6f226a6e19 (diff) |
TLS ticket key setting callback: this allows and application to set
its own TLS ticket keys.
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/s3_lib.c | 7 | ||||
-rw-r--r-- | ssl/s3_srvr.c | 40 | ||||
-rw-r--r-- | ssl/ssl.h | 10 | ||||
-rw-r--r-- | ssl/t1_lib.c | 52 | ||||
-rw-r--r-- | ssl/tls1.h | 3 |
5 files changed, 82 insertions, 30 deletions
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 06e454c96b..bdbcd44f27 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -2255,6 +2255,13 @@ long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void)) ctx->tlsext_status_cb=(int (*)(SSL *,void *))fp; break; + case SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB: + ctx->tlsext_ticket_key_cb=(int (*)(SSL *,unsigned char *, + unsigned char *, + EVP_CIPHER_CTX *, + HMAC_CTX *, int))fp; + break; + #endif default: return(0); diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index c031a0f763..903522ab59 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -2703,6 +2703,8 @@ int ssl3_send_newsession_ticket(SSL *s) unsigned int hlen; EVP_CIPHER_CTX ctx; HMAC_CTX hctx; + unsigned char iv[EVP_MAX_IV_LENGTH]; + unsigned char key_name[16]; /* get session encoding length */ slen = i2d_SSL_SESSION(s->session, NULL); @@ -2733,29 +2735,47 @@ int ssl3_send_newsession_ticket(SSL *s) *(p++)=SSL3_MT_NEWSESSION_TICKET; /* Skip message length for now */ p += 3; + EVP_CIPHER_CTX_init(&ctx); + HMAC_CTX_init(&hctx); + /* Initialize HMAC and cipher contexts. If callback present + * it does all the work otherwise use generated values + * from parent ctx. + */ + if (s->ctx->tlsext_ticket_key_cb) + { + if (s->ctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx, + &hctx, 1) < 0) + { + OPENSSL_free(senc); + return -1; + } + } + else + { + RAND_pseudo_bytes(iv, 16); + EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, + s->ctx->tlsext_tick_aes_key, iv); + HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16, + tlsext_tick_md(), NULL); + memcpy(key_name, s->ctx->tlsext_tick_key_name, 16); + } 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); + memcpy(p, key_name, 16); p += 16; - /* Generate and output IV */ - RAND_pseudo_bytes(p, 16); - EVP_CIPHER_CTX_init(&ctx); + /* output IV */ + memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx)); + p += EVP_CIPHER_CTX_iv_length(&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, - tlsext_tick_md(), NULL); HMAC_Update(&hctx, macstart, p - macstart); HMAC_Final(&hctx, p, &hlen); HMAC_CTX_cleanup(&hctx); @@ -187,6 +187,7 @@ #include <openssl/buffer.h> #endif #include <openssl/pem.h> +#include <openssl/hmac.h> #include <openssl/kssl.h> #include <openssl/safestack.h> @@ -767,7 +768,12 @@ struct ssl_ctx_st unsigned char tlsext_tick_key_name[16]; unsigned char tlsext_tick_hmac_key[16]; unsigned char tlsext_tick_aes_key[16]; - + /* Callback to support customisation of ticket key setting */ + int (*tlsext_ticket_key_cb)(SSL *ssl, + unsigned char *name, unsigned char *iv, + EVP_CIPHER_CTX *ectx, + HMAC_CTX *hctx, int enc); + /* certificate status request info */ /* Callback for status request */ int (*tlsext_status_cb)(SSL *ssl, void *arg); @@ -1252,6 +1258,8 @@ size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count); #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS 69 #define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP 70 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP 71 + +#define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72 #endif #define SSL_session_reused(ssl) \ diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 8ff1734dab..93a4caa48e 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -788,39 +788,53 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, SSL_SESSION *sess; unsigned char *sdec; const unsigned char *p; - int slen, mlen; + int slen, mlen, renew_ticket = 0; unsigned char tick_hmac[EVP_MAX_MD_SIZE]; HMAC_CTX hctx; EVP_CIPHER_CTX ctx; + /* Need at least keyname + iv + some encrypted data */ + if (eticklen < 48) + goto tickerr; + /* Initialize session ticket encryption and HMAC contexts */ + HMAC_CTX_init(&hctx); + EVP_CIPHER_CTX_init(&ctx); + if (s->ctx->tlsext_ticket_key_cb) + { + unsigned char *nctick = (unsigned char *)etick; + int rv = s->ctx->tlsext_ticket_key_cb(s, nctick, nctick + 16, + &ctx, &hctx, 0); + if (rv < 0) + return -1; + if (rv == 0) + goto tickerr; + if (rv == 2) + renew_ticket = 1; + } + else + { + /* Check key name matches */ + if (memcmp(etick, s->ctx->tlsext_tick_key_name, 16)) + goto tickerr; + HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16, + tlsext_tick_md(), NULL); + EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, + s->ctx->tlsext_tick_aes_key, etick + 16); + } /* Attempt to process session ticket, first conduct sanity and * integrity checks on ticket. */ - mlen = EVP_MD_size(tlsext_tick_md()); + mlen = HMAC_size(&hctx); eticklen -= mlen; - /* Need at least keyname + iv + some encrypted data */ - if (eticklen < 48) - goto tickerr; - /* Check key name matches */ - if (memcmp(etick, s->ctx->tlsext_tick_key_name, 16)) - goto tickerr; /* Check HMAC of encrypted ticket */ - HMAC_CTX_init(&hctx); - HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16, - tlsext_tick_md(), NULL); HMAC_Update(&hctx, etick, eticklen); HMAC_Final(&hctx, tick_hmac, NULL); HMAC_CTX_cleanup(&hctx); if (memcmp(tick_hmac, etick + eticklen, mlen)) goto tickerr; - /* Set p to start of IV */ - p = etick + 16; - EVP_CIPHER_CTX_init(&ctx); /* Attempt to decrypt session data */ - EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, - s->ctx->tlsext_tick_aes_key, p); /* Move p after IV to start of encrypted ticket, update length */ - p += 16; - eticklen -= 32; + p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx); + eticklen -= 16 + EVP_CIPHER_CTX_iv_length(&ctx); sdec = OPENSSL_malloc(eticklen); if (!sdec) { @@ -847,7 +861,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, memcpy(sess->session_id, sess_id, sesslen); sess->session_id_length = sesslen; *psess = sess; - s->tlsext_ticket_expected = 0; + s->tlsext_ticket_expected = renew_ticket; return 1; } /* If session decrypt failure indicate a cache miss and set state to diff --git a/ssl/tls1.h b/ssl/tls1.h index 7c3b6a8a85..2d1d293e1a 100644 --- a/ssl/tls1.h +++ b/ssl/tls1.h @@ -179,6 +179,9 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB,(void (*)(void))cb) #define SSL_CTX_set_tlsext_status_arg(ssl, arg) \ SSL_CTX_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG,0, (void *)arg) +#define SSL_CTX_set_tlsext_ticket_key_cb(ssl, cb) \ +SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb) + #endif /* Additional TLS ciphersuites from draft-ietf-tls-56-bit-ciphersuites-00.txt |