diff options
-rw-r--r-- | doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod | 67 | ||||
-rw-r--r-- | include/openssl/ssl.h | 4 | ||||
-rw-r--r-- | include/openssl/tls1.h | 7 | ||||
-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 | ||||
-rw-r--r-- | test/bad_dtls_test.c | 34 | ||||
-rw-r--r-- | test/handshake_helper.c | 14 | ||||
-rw-r--r-- | test/sslapitest.c | 68 | ||||
-rw-r--r-- | util/libssl.num | 1 |
11 files changed, 375 insertions, 69 deletions
diff --git a/doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod b/doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod index 88e70c5fa2..ae812097c5 100644 --- a/doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod +++ b/doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod @@ -2,20 +2,31 @@ =head1 NAME -SSL_CTX_set_tlsext_ticket_key_cb - set a callback for session ticket processing +SSL_CTX_set_tlsext_ticket_key_evp_cb, +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 SSL_CTX_set_tlsext_ticket_key_evp_cb(SSL_CTX sslctx, + int (*cb)(SSL *s, unsigned char key_name[16], + unsigned char iv[EVP_MAX_IV_LENGTH], + EVP_CIPHER_CTX *ctx, EVP_MAC_CTX *hctx, int enc)); + +Deprecated since OpenSSL 3.0, can be hidden entirely by defining +B<OPENSSL_API_COMPAT> with a suitable version value, see +L<openssl_user_macros(7)>: + + int 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 function I<cb> for handling +SSL_CTX_set_tlsext_ticket_key_evp_cb() sets a callback function 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 @@ -38,7 +49,8 @@ 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 L<EVP_CIPHER_CTX_reset(3)> and L<HMAC_CTX_reset(3)> respectively. +initialised with L<EVP_CIPHER_CTX_reset(3)> and L<EVP_MAC_CTX_new(3)> +respectively. For new sessions tickets, when the client doesn't present a session ticket, or an attempted retrieval of the ticket failed, or a renew option was indicated, @@ -53,8 +65,9 @@ maximum IV length is B<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(3)>. The hmac context can be set using -L<HMAC_Init_ex(3)>. +set using L<EVP_EncryptInit_ex(3)>. The hmac context and digest can be set using +L<EVP_MAC_CTX_set_params(3)> with the B<OSSL_MAC_PARAM_KEY> and +B<OSSL_MAC_PARAM_DIGEST> parameters respectively. 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 retrieve a set @@ -62,8 +75,9 @@ 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 retrieved parameters and the initialization vector -I<iv>. using a function like L<EVP_DecryptInit_ex(3)>. The I<hctx> needs to be -set using L<HMAC_Init_ex(3)>. +I<iv>. using a function like L<EVP_DecryptInit_ex(3)>. The key material and +digest for I<hctx> need to be set using L<EVP_MAC_CTX_set_params(3)> with the +B<OSSL_MAC_PARAM_KEY> and B<OSSL_MAC_PARAM_DIGEST> parameters respectively. 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 @@ -102,6 +116,14 @@ This indicates an error. =back +The SSL_CTX_set_tlsext_ticket_key_cb() function is identical to +SSL_CTX_set_tlsext_ticket_key_evp_cb() except that it takes a deprecated +HMAC_CTX pointer instead of an EVP_MAC_CTX one. +Before this callback function is started I<hctx> will have been +initialised with L<EVP_MAC_CTX_new(3)> and the digest set with +L<EVP_MAC_CTX_set_params(3)>. +The I<hctx> key material can be set using L<HMAC_Init_ex(3)>. + =head1 NOTES Session resumption shortcuts the TLS so that the client certificate @@ -129,13 +151,15 @@ returns 0 to indicate the callback function was set. Reference Implementation: - SSL_CTX_set_tlsext_ticket_key_cb(SSL, ssl_tlsext_ticket_key_cb); + SSL_CTX_set_tlsext_ticket_key_evp_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) + EVP_MAC_CTX *hctx, int enc) { + OSSL_PARAM params[3]; + if (enc) { /* create new session */ if (RAND_bytes(iv, EVP_MAX_IV_LENGTH) <= 0) return -1; /* insufficient random */ @@ -155,7 +179,13 @@ Reference Implementation: 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); + + params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, + key->hmac_key, 16); + params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, + "sha256", 0); + params[2] = OSSL_PARAM_construct_end(); + EVP_MAC_CTX_set_params(hctx, params); return 1; @@ -165,7 +195,13 @@ Reference Implementation: if (key == NULL || key->expire < now()) return 0; - HMAC_Init_ex(&hctx, key->hmac_key, 16, EVP_sha256(), NULL); + params[0] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, + key->hmac_key, 16); + params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, + "sha256", 0); + params[2] = OSSL_PARAM_construct_end(); + EVP_MAC_CTX_set_params(hctx, params); + EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key->aes_key, iv); if (key->expire < now() - RENEW_TIME) { @@ -188,6 +224,13 @@ L<SSL_CTX_sess_number(3)>, L<SSL_CTX_sess_set_get_cb(3)>, L<SSL_CTX_set_session_id_context(3)>, +=head1 HISTORY + +The SSL_CTX_set_tlsext_ticket_key_cb() function was deprecated in OpenSSL 3.0. + +The SSL_CTX_set_tlsext_ticket_key_evp_cb() function was introduced in +OpenSSL 3.0. + =head1 COPYRIGHT Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved. diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 3b52f86412..c1b6b8e5dc 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -1269,7 +1269,9 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION) # 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 +# ifndef OPENSSL_NO_DEPRECATED_3_0 +# define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72 +# endif # define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB 75 # define SSL_CTRL_SET_SRP_VERIFY_PARAM_CB 76 # define SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB 77 diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h index 9a1683e0fd..9181e0d2c1 100644 --- a/include/openssl/tls1.h +++ b/include/openssl/tls1.h @@ -327,9 +327,14 @@ __owur int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain) # define SSL_CTX_get_tlsext_status_type(ssl) \ SSL_CTX_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE,0,NULL) -# define SSL_CTX_set_tlsext_ticket_key_cb(ssl, cb) \ +# ifndef OPENSSL_NO_DEPRECATED_3_0 +# 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 +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)); /* PSK ciphersuites from 4279 */ # define TLS1_CK_PSK_WITH_RC4_128_SHA 0x0300008A 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; +} + diff --git a/test/bad_dtls_test.c b/test/bad_dtls_test.c index 66b5e1d2ed..9716b52193 100644 --- a/test/bad_dtls_test.c +++ b/test/bad_dtls_test.c @@ -29,6 +29,8 @@ */ #include <string.h> +#include <openssl/core_names.h> +#include <openssl/params.h> #include <openssl/opensslconf.h> #include <openssl/bio.h> #include <openssl/crypto.h> @@ -278,11 +280,13 @@ static int send_record(BIO *rbio, unsigned char type, uint64_t seqnr, static unsigned char seq[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static unsigned char ver[2] = { 0x01, 0x00 }; /* DTLS1_BAD_VER */ unsigned char lenbytes[2]; - HMAC_CTX *ctx; + EVP_MAC *hmac; + EVP_MAC_CTX *ctx; EVP_CIPHER_CTX *enc_ctx; unsigned char iv[16]; unsigned char pad; unsigned char *enc; + OSSL_PARAM params[3]; seq[0] = (seqnr >> 40) & 0xff; seq[1] = (seqnr >> 32) & 0xff; @@ -300,18 +304,26 @@ static int send_record(BIO *rbio, unsigned char type, uint64_t seqnr, memcpy(enc, msg, len); /* Append HMAC to data */ - ctx = HMAC_CTX_new(); - HMAC_Init_ex(ctx, mac_key, 20, EVP_sha1(), NULL); - HMAC_Update(ctx, epoch, 2); - HMAC_Update(ctx, seq, 6); - HMAC_Update(ctx, &type, 1); - HMAC_Update(ctx, ver, 2); /* Version */ + hmac = EVP_MAC_fetch(NULL, "HMAC", NULL); + ctx = EVP_MAC_CTX_new(hmac); + EVP_MAC_free(hmac); + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, + "SHA1", 0); + params[1] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, + mac_key, 20); + params[2] = OSSL_PARAM_construct_end(); + EVP_MAC_CTX_set_params(ctx, params); + EVP_MAC_init(ctx); + EVP_MAC_update(ctx, epoch, 2); + EVP_MAC_update(ctx, seq, 6); + EVP_MAC_update(ctx, &type, 1); + EVP_MAC_update(ctx, ver, 2); /* Version */ lenbytes[0] = (unsigned char)(len >> 8); lenbytes[1] = (unsigned char)(len); - HMAC_Update(ctx, lenbytes, 2); /* Length */ - HMAC_Update(ctx, enc, len); /* Finally the data itself */ - HMAC_Final(ctx, enc + len, NULL); - HMAC_CTX_free(ctx); + EVP_MAC_update(ctx, lenbytes, 2); /* Length */ + EVP_MAC_update(ctx, enc, len); /* Finally the data itself */ + EVP_MAC_final(ctx, enc + len, NULL, SHA_DIGEST_LENGTH); + EVP_MAC_CTX_free(ctx); /* Append padding bytes */ len += SHA_DIGEST_LENGTH; diff --git a/test/handshake_helper.c b/test/handshake_helper.c index e8249a7ce2..86313c9e3c 100644 --- a/test/handshake_helper.c +++ b/test/handshake_helper.c @@ -317,8 +317,9 @@ static int verify_accept_cb(X509_STORE_CTX *ctx, void *arg) { return 1; } -static int broken_session_ticket_cb(SSL *s, unsigned char *key_name, unsigned char *iv, - EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc) +static int broken_session_ticket_cb(SSL *s, unsigned char *key_name, + unsigned char *iv, EVP_CIPHER_CTX *ctx, + EVP_MAC_CTX *hctx, int enc) { return 0; } @@ -326,7 +327,7 @@ static int broken_session_ticket_cb(SSL *s, unsigned char *key_name, unsigned ch static int do_not_call_session_ticket_cb(SSL *s, unsigned char *key_name, unsigned char *iv, EVP_CIPHER_CTX *ctx, - HMAC_CTX *hctx, int enc) + EVP_MAC_CTX *hctx, int enc) { HANDSHAKE_EX_DATA *ex_data = (HANDSHAKE_EX_DATA*)(SSL_get_ex_data(s, ex_data_idx)); @@ -585,11 +586,12 @@ static int configure_handshake_ctx(SSL_CTX *server_ctx, SSL_CTX *server2_ctx, * session (assigned via SNI), and should never be invoked */ if (server2_ctx != NULL) - SSL_CTX_set_tlsext_ticket_key_cb(server2_ctx, - do_not_call_session_ticket_cb); + SSL_CTX_set_tlsext_ticket_key_evp_cb(server2_ctx, + do_not_call_session_ticket_cb); if (extra->server.broken_session_ticket) { - SSL_CTX_set_tlsext_ticket_key_cb(server_ctx, broken_session_ticket_cb); + SSL_CTX_set_tlsext_ticket_key_evp_cb(server_ctx, + broken_session_ticket_cb); } #ifndef OPENSSL_NO_NEXTPROTONEG if (extra->server.npn_protocols != NULL) { diff --git a/test/sslapitest.c b/test/sslapitest.c index 4993f16f4c..cf0fd3f37d 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -7,6 +7,14 @@ * https://www.openssl.org/source/license.html */ +/* + * We need access to the deprecated low level HMAC APIs for legacy purposes + * when the deprecated calls are not hidden + */ +#ifndef OPENSSL_NO_DEPRECATED_3_0 +# define OPENSSL_SUPPRESS_DEPRECATED +#endif + #include <stdio.h> #include <string.h> @@ -19,6 +27,7 @@ #include <openssl/txt_db.h> #include <openssl/aes.h> #include <openssl/rand.h> +#include <openssl/core_names.h> #include "ssltestlib.h" #include "testutil.h" @@ -6077,6 +6086,7 @@ static SSL_TICKET_RETURN dec_tick_cb(SSL *s, SSL_SESSION *ss, } +#ifndef OPENSSL_NO_DEPRECATED_3_0 static int tick_key_cb(SSL *s, unsigned char key_name[16], unsigned char iv[EVP_MAX_IV_LENGTH], EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc) @@ -6094,6 +6104,32 @@ static int tick_key_cb(SSL *s, unsigned char key_name[16], return tick_key_renew ? 2 : 1; } +#endif + +static int tick_key_evp_cb(SSL *s, unsigned char key_name[16], + unsigned char iv[EVP_MAX_IV_LENGTH], + EVP_CIPHER_CTX *ctx, EVP_MAC_CTX *hctx, int enc) +{ + const unsigned char tick_aes_key[16] = "0123456789abcdef"; + unsigned char tick_hmac_key[16] = "0123456789abcdef"; + OSSL_PARAM params[3]; + + tick_key_cb_called = 1; + memset(iv, 0, AES_BLOCK_SIZE); + memset(key_name, 0, 16); + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, + "SHA256", 0); + params[1] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, + tick_hmac_key, + sizeof(tick_hmac_key)); + params[2] = OSSL_PARAM_construct_end(); + if (!EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, tick_aes_key, iv, enc) + || !EVP_MAC_CTX_set_params(hctx, params) + || !EVP_MAC_init(hctx)) + return -1; + + return tick_key_renew ? 2 : 1; +} /* * Test the various ticket callbacks @@ -6105,10 +6141,14 @@ static int tick_key_cb(SSL *s, unsigned char key_name[16], * Test 5: TLSv1.3, no ticket key callback, ticket, no renewal * Test 6: TLSv1.2, no ticket key callback, ticket, renewal * Test 7: TLSv1.3, no ticket key callback, ticket, renewal - * Test 8: TLSv1.2, ticket key callback, ticket, no renewal - * Test 9: TLSv1.3, ticket key callback, ticket, no renewal - * Test 10: TLSv1.2, ticket key callback, ticket, renewal - * Test 11: TLSv1.3, ticket key callback, ticket, renewal + * Test 8: TLSv1.2, old ticket key callback, ticket, no renewal + * Test 9: TLSv1.3, old ticket key callback, ticket, no renewal + * Test 10: TLSv1.2, old ticket key callback, ticket, renewal + * Test 11: TLSv1.3, old ticket key callback, ticket, renewal + * Test 12: TLSv1.2, ticket key callback, ticket, no renewal + * Test 13: TLSv1.3, ticket key callback, ticket, no renewal + * Test 14: TLSv1.2, ticket key callback, ticket, renewal + * Test 15: TLSv1.3, ticket key callback, ticket, renewal */ static int test_ticket_callbacks(int tst) { @@ -6125,11 +6165,15 @@ static int test_ticket_callbacks(int tst) if (tst % 2 == 1) return 1; #endif +#ifdef OPENSSL_NO_DEPRECATED_3_0 + if (tst >= 8 && tst <= 11) + return 1; +#endif gen_tick_called = dec_tick_called = tick_key_cb_called = 0; /* Which tests the ticket key callback should request renewal for */ - if (tst == 10 || tst == 11) + if (tst == 10 || tst == 11 || tst == 14 || tst == 15) tick_key_renew = 1; else tick_key_renew = 0; @@ -6179,9 +6223,15 @@ static int test_ticket_callbacks(int tst) NULL))) goto end; - if (tst >= 8 - && !TEST_true(SSL_CTX_set_tlsext_ticket_key_cb(sctx, tick_key_cb))) - goto end; + if (tst >= 12) { + if (!TEST_true(SSL_CTX_set_tlsext_ticket_key_evp_cb(sctx, tick_key_evp_cb))) + goto end; +#ifndef OPENSSL_NO_DEPRECATED_3_0 + } else if (tst >= 8) { + if (!TEST_true(SSL_CTX_set_tlsext_ticket_key_cb(sctx, tick_key_cb))) + goto end; +#endif + } if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)) @@ -7060,7 +7110,7 @@ int setup_tests(void) ADD_ALL_TESTS(test_info_callback, 6); ADD_ALL_TESTS(test_ssl_pending, 2); ADD_ALL_TESTS(test_ssl_get_shared_ciphers, OSSL_NELEM(shared_ciphers_data)); - ADD_ALL_TESTS(test_ticket_callbacks, 12); + ADD_ALL_TESTS(test_ticket_callbacks, 16); ADD_ALL_TESTS(test_shutdown, 7); ADD_ALL_TESTS(te |