diff options
Diffstat (limited to 'ssl')
-rw-r--r-- | ssl/s3_lib.c | 10 | ||||
-rw-r--r-- | ssl/ssl_local.h | 32 | ||||
-rw-r--r-- | ssl/statem/statem_srvr.c | 47 | ||||
-rw-r--r-- | ssl/t1_lib.c | 160 |
4 files changed, 220 insertions, 29 deletions
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index 745bccc836..a1a61cf328 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -4008,12 +4008,14 @@ long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void)) ctx->ext.status_cb = (int (*)(SSL *, void *))fp; break; +# ifndef OPENSSL_NO_DEPRECATED_3_0 case SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB: ctx->ext.ticket_key_cb = (int (*)(SSL *, unsigned char *, unsigned char *, EVP_CIPHER_CTX *, HMAC_CTX *, int))fp; break; +#endif #ifndef OPENSSL_NO_SRP case SSL_CTRL_SET_SRP_VERIFY_PARAM_CB: @@ -4042,6 +4044,14 @@ long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void)) return 1; } +int SSL_CTX_set_tlsext_ticket_key_evp_cb + (SSL_CTX *ctx, int (*fp)(SSL *, unsigned char *, unsigned char *, + EVP_CIPHER_CTX *, EVP_MAC_CTX *, int)) +{ + ctx->ext.ticket_key_evp_cb = fp; + return 1; +} + const SSL_CIPHER *ssl3_get_cipher_by_id(uint32_t id) { SSL_CIPHER c; diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h index 43b0623a0b..680afa070a 100644 --- a/ssl/ssl_local.h +++ b/ssl/ssl_local.h @@ -737,6 +737,32 @@ typedef struct ssl_ctx_ext_secure_st { unsigned char tick_aes_key[TLSEXT_TICK_KEY_LENGTH]; } SSL_CTX_EXT_SECURE; +/* + * Helper function for HMAC + * The structure should be considered opaque, it will change once the low + * level deprecated calls are removed. At that point it can be replaced + * by EVP_MAC_CTX and most of the functions converted to macros or inlined + * directly. + */ +typedef struct ssl_hmac_st { + EVP_MAC_CTX *ctx; +# ifndef OPENSSL_NO_DEPRECATED_3_0 + HMAC_CTX *old_ctx; +# endif +} SSL_HMAC; + +SSL_HMAC *ssl_hmac_new(const SSL_CTX *ctx); +void ssl_hmac_free(SSL_HMAC *ctx); +# ifndef OPENSSL_NO_DEPRECATED_3_0 +HMAC_CTX *ssl_hmac_get0_HMAC_CTX(SSL_HMAC *ctx); +# endif +EVP_MAC_CTX *ssl_hmac_get0_EVP_MAC_CTX(SSL_HMAC *ctx); +int ssl_hmac_init(SSL_HMAC *ctx, void *key, size_t len, char *md); +int ssl_hmac_update(SSL_HMAC *ctx, const unsigned char *data, size_t len); +int ssl_hmac_final(SSL_HMAC *ctx, unsigned char *md, size_t *len, + size_t max_size); +size_t ssl_hmac_size(const SSL_HMAC *ctx); + struct ssl_ctx_st { OPENSSL_CTX *libctx; @@ -936,10 +962,16 @@ struct ssl_ctx_st { /* RFC 4507 session ticket keys */ unsigned char tick_key_name[TLSEXT_KEYNAME_LENGTH]; SSL_CTX_EXT_SECURE *secure; +# ifndef OPENSSL_NO_DEPRECATED_3_0 /* Callback to support customisation of ticket key setting */ int (*ticket_key_cb) (SSL *ssl, unsigned char *name, unsigned char *iv, EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc); +#endif + int (*ticket_key_evp_cb) (SSL *ssl, + unsigned char *name, unsigned char *iv, + EVP_CIPHER_CTX *ectx, EVP_MAC_CTX *hctx, + int enc); /* certificate status request info */ /* Callback for status request */ diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 4a18ad416d..50eaf69da4 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -18,7 +18,6 @@ #include <openssl/rand.h> #include <openssl/objects.h> #include <openssl/evp.h> -#include <openssl/hmac.h> #include <openssl/x509.h> #include <openssl/dh.h> #include <openssl/bn.h> @@ -3779,12 +3778,12 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add, { unsigned char *senc = NULL; EVP_CIPHER_CTX *ctx = NULL; - HMAC_CTX *hctx = NULL; + SSL_HMAC *hctx = NULL; unsigned char *p, *encdata1, *encdata2, *macdata1, *macdata2; const unsigned char *const_p; int len, slen_full, slen, lenfinal; SSL_SESSION *sess; - unsigned int hlen; + size_t hlen; SSL_CTX *tctx = s->session_ctx; unsigned char iv[EVP_MAX_IV_LENGTH]; unsigned char key_name[TLSEXT_KEYNAME_LENGTH]; @@ -3810,7 +3809,7 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add, } ctx = EVP_CIPHER_CTX_new(); - hctx = HMAC_CTX_new(); + hctx = ssl_hmac_new(tctx); if (ctx == NULL || hctx == NULL) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, ERR_R_MALLOC_FAILURE); @@ -3856,10 +3855,24 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add, * Initialize HMAC and cipher contexts. If callback present it does * all the work otherwise use generated values from parent ctx. */ - if (tctx->ext.ticket_key_cb) { - /* if 0 is returned, write an empty ticket */ - int ret = tctx->ext.ticket_key_cb(s, key_name, iv, ctx, - hctx, 1); +#ifndef OPENSSL_NO_DEPRECATED_3_0 + if (tctx->ext.ticket_key_evp_cb != NULL || tctx->ext.ticket_key_cb != NULL) +#else + if (tctx->ext.ticket_key_evp_cb != NULL) +#endif + { + int ret = 0; + + if (tctx->ext.ticket_key_evp_cb != NULL) + ret = tctx->ext.ticket_key_evp_cb(s, key_name, iv, ctx, + ssl_hmac_get0_EVP_MAC_CTX(hctx), + 1); +#ifndef OPENSSL_NO_DEPRECATED_3_0 + else if (tctx->ext.ticket_key_cb != NULL) + /* if 0 is returned, write an empty ticket */ + ret = tctx->ext.ticket_key_cb(s, key_name, iv, ctx, + ssl_hmac_get0_HMAC_CTX(hctx), 1); +#endif if (ret == 0) { @@ -3873,7 +3886,7 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add, } OPENSSL_free(senc); EVP_CIPHER_CTX_free(ctx); - HMAC_CTX_free(hctx); + ssl_hmac_free(hctx); return 1; } if (ret < 0) { @@ -3889,9 +3902,9 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add, if (RAND_bytes_ex(s->ctx->libctx, iv, iv_len) <= 0 || !EVP_EncryptInit_ex(ctx, cipher, NULL, tctx->ext.secure->tick_aes_key, iv) - || !HMAC_Init_ex(hctx, tctx->ext.secure->tick_hmac_key, - sizeof(tctx->ext.secure->tick_hmac_key), - EVP_sha256(), NULL)) { + || !ssl_hmac_init(hctx, tctx->ext.secure->tick_hmac_key, + sizeof(tctx->ext.secure->tick_hmac_key), + "SHA256")) { SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET, ERR_R_INTERNAL_ERROR); goto err; @@ -3921,11 +3934,11 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add, || encdata1 + len != encdata2 || len + lenfinal > slen + EVP_MAX_BLOCK_LENGTH || !WPACKET_get_total_written(pkt, &macendoffset) - || !HMAC_Update(hctx, - (unsigned char *)s->init_buf->data + macoffset, - macendoffset - macoffset) + || !ssl_hmac_update(hctx, + (unsigned char *)s->init_buf->data + macoffset, + macendoffset - macoffset) || !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &macdata1) - || !HMAC_Final(hctx, macdata1, &hlen) + || !ssl_hmac_final(hctx, macdata1, &hlen, EVP_MAX_MD_SIZE) || hlen > EVP_MAX_MD_SIZE || !WPACKET_allocate_bytes(pkt, hlen, &macdata2) || macdata1 != macdata2) { @@ -3945,7 +3958,7 @@ static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add, err: OPENSSL_free(senc); EVP_CIPHER_CTX_free(ctx); - HMAC_CTX_free(hctx); + ssl_hmac_free(hctx); return ok; } diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 0504f6bba1..fa2d6e0154 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -7,11 +7,15 @@ * https://www.openssl.org/source/license.html */ +/* We need access to the deprecated low level HMAC APIs */ +#define OPENSSL_SUPPRESS_DEPRECATED + #include <stdio.h> #include <stdlib.h> #include <openssl/objects.h> #include <openssl/evp.h> #include <openssl/hmac.h> +#include <openssl/core_names.h> #include <openssl/ocsp.h> #include <openssl/conf.h> #include <openssl/x509v3.h> @@ -1417,7 +1421,7 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick, SSL_TICKET_STATUS ret = SSL_TICKET_FATAL_ERR_OTHER; size_t mlen; unsigned char tick_hmac[EVP_MAX_MD_SIZE]; - HMAC_CTX *hctx = NULL; + SSL_HMAC *hctx = NULL; EVP_CIPHER_CTX *ctx = NULL; SSL_CTX *tctx = s->session_ctx; @@ -1447,7 +1451,7 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick, } /* Initialize session ticket encryption and HMAC contexts */ - hctx = HMAC_CTX_new(); + hctx = ssl_hmac_new(tctx); if (hctx == NULL) { ret = SSL_TICKET_FATAL_ERR_MALLOC; goto end; @@ -1457,11 +1461,28 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick, ret = SSL_TICKET_FATAL_ERR_MALLOC; goto end; } - if (tctx->ext.ticket_key_cb) { +#ifndef OPENSSL_NO_DEPRECATED_3_0 + if (tctx->ext.ticket_key_evp_cb != NULL || tctx->ext.ticket_key_cb != NULL) +#else + if (tctx->ext.ticket_key_evp_cb != NULL) +#endif + { unsigned char *nctick = (unsigned char *)etick; - int rv = tctx->ext.ticket_key_cb(s, nctick, + int rv = 0; + + if (tctx->ext.ticket_key_evp_cb != NULL) + rv = tctx->ext.ticket_key_evp_cb(s, nctick, + nctick + TLSEXT_KEYNAME_LENGTH, + ctx, + ssl_hmac_get0_EVP_MAC_CTX(hctx), + 0); +#ifndef OPENSSL_NO_DEPRECATED_3_0 + else if (tctx->ext.ticket_key_cb != NULL) + /* if 0 is returned, write an empty ticket */ + rv = tctx->ext.ticket_key_cb(s, nctick, nctick + TLSEXT_KEYNAME_LENGTH, - ctx, hctx, 0); + ctx, ssl_hmac_get0_HMAC_CTX(hctx), 0); +#endif if (rv < 0) { ret = SSL_TICKET_FATAL_ERR_OTHER; goto end; @@ -1479,9 +1500,9 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick, ret = SSL_TICKET_NO_DECRYPT; goto end; } - if (HMAC_Init_ex(hctx, tctx->ext.secure->tick_hmac_key, - sizeof(tctx->ext.secure->tick_hmac_key), - EVP_sha256(), NULL) <= 0 + if (ssl_hmac_init(hctx, tctx->ext.secure->tick_hmac_key, + sizeof(tctx->ext.secure->tick_hmac_key), + "SHA256") <= 0 || EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, tctx->ext.secure->tick_aes_key, etick + TLSEXT_KEYNAME_LENGTH) <= 0) { @@ -1495,7 +1516,7 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick, * Attempt to process session ticket, first conduct sanity and integrity * checks on ticket. */ - mlen = HMAC_size(hctx); + mlen = ssl_hmac_size(hctx); if (mlen == 0) { ret = SSL_TICKET_FATAL_ERR_OTHER; goto end; @@ -1509,8 +1530,8 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick, } eticklen -= mlen; /* Check HMAC of encrypted ticket */ - if (HMAC_Update(hctx, etick, eticklen) <= 0 - || HMAC_Final(hctx, tick_hmac, NULL) <= 0) { + if (ssl_hmac_update(hctx, etick, eticklen) <= 0 + || ssl_hmac_final(hctx, tick_hmac, NULL, sizeof(tick_hmac)) <= 0) { ret = SSL_TICKET_FATAL_ERR_OTHER; goto end; } @@ -1573,7 +1594,7 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick, end: EVP_CIPHER_CTX_free(ctx); - HMAC_CTX_free(hctx); + ssl_hmac_free(hctx); /* * If set, the decrypt_ticket_cb() is called unless a fatal error was @@ -2979,3 +3000,118 @@ uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *session) { return session->ext.max_fragment_len_mode; } + +/* + * Helper functions for HMAC access with legacy support included. + */ +SSL_HMAC *ssl_hmac_new(const SSL_CTX *ctx) +{ + SSL_HMAC *ret = OPENSSL_zalloc(sizeof(*ret)); + EVP_MAC *mac = NULL; + + if (ret == NULL) + return NULL; +#ifndef OPENSSL_NO_DEPRECATED_3_0 + if (ctx->ext.ticket_key_evp_cb == NULL + && ctx->ext.ticket_key_cb != NULL) { + ret->old_ctx = HMAC_CTX_new(); + if (ret->old_ctx == NULL) + goto err; + return ret; + } +#endif + mac = EVP_MAC_fetch(ctx->libctx, "HMAC", NULL); + if (mac == NULL || (ret->ctx = EVP_MAC_CTX_new(mac)) == NULL) + goto err; + EVP_MAC_free(mac); + return ret; + err: + EVP_MAC_CTX_free(ret->ctx); + EVP_MAC_free(mac); + OPENSSL_free(ret); + return NULL; +} + +void ssl_hmac_free(SSL_HMAC *ctx) +{ + if (ctx != NULL) { + EVP_MAC_CTX_free(ctx->ctx); +#ifndef OPENSSL_NO_DEPRECATED_3_0 + HMAC_CTX_free(ctx->old_ctx); +#endif + OPENSSL_free(ctx); + } +} + +#ifndef OPENSSL_NO_DEPRECATED_3_0 +HMAC_CTX *ssl_hmac_get0_HMAC_CTX(SSL_HMAC *ctx) +{ + return ctx->old_ctx; +} +#endif + +EVP_MAC_CTX *ssl_hmac_get0_EVP_MAC_CTX(SSL_HMAC *ctx) +{ + return ctx->ctx; +} + +int ssl_hmac_init(SSL_HMAC *ctx, void *key, size_t len, char *md) +{ + OSSL_PARAM params[3], *p = params; + + if (ctx->ctx != NULL) { + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, md, 0); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, key, len); + *p = OSSL_PARAM_construct_end(); + if (EVP_MAC_CTX_set_params(ctx->ctx, params) && EVP_MAC_init(ctx->ctx)) + return 1; + } +#ifndef OPENSSL_NO_DEPRECATED_3_0 + if (ctx->old_ctx != NULL) + return HMAC_Init_ex(ctx->old_ctx, key, len, + EVP_get_digestbyname(md), NULL); +#endif + return 0; +} + +int ssl_hmac_update(SSL_HMAC *ctx, const unsigned char *data, size_t len) +{ + if (ctx->ctx != NULL) + return EVP_MAC_update(ctx->ctx, data, len); +#ifndef OPENSSL_NO_DEPRECATED_3_0 + if (ctx->old_ctx != NULL) + return HMAC_Update(ctx->old_ctx, data, len); +#endif + return 0; +} + +int ssl_hmac_final(SSL_HMAC *ctx, unsigned char *md, size_t *len, + size_t max_size) +{ + if (ctx->ctx != NULL) + return EVP_MAC_final(ctx->ctx, md, len, max_size); +#ifndef OPENSSL_NO_DEPRECATED_3_0 + if (ctx->old_ctx != NULL) { + unsigned int l; + + if (HMAC_Final(ctx->old_ctx, md, &l) > 0) { + if (len != NULL) + *len = l; + return 1; + } + } +#endif + return 0; +} + +size_t ssl_hmac_size(const SSL_HMAC *ctx) +{ + if (ctx->ctx != NULL) + return EVP_MAC_size(ctx->ctx); +#ifndef OPENSSL_NO_DEPRECATED_3_0 + if (ctx->old_ctx != NULL) + return HMAC_size(ctx->old_ctx); +#endif + return 0; +} + |