TLS: use EVP for HMAC throughout libssl.
authorPauli <paul.dale@oracle.com>
Fri, 24 Jan 2020 00:41:38 +0000 (10:41 +1000)
committerPauli <paul.dale@oracle.com>
Wed, 29 Jan 2020 09:49:23 +0000 (19:49 +1000)
Backwards compatibility with the old ticket key call back is maintained.
This will be removed when the low level HMAC APIs are finally removed.

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10836)

doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod
include/openssl/ssl.h
include/openssl/tls1.h
ssl/s3_lib.c
ssl/ssl_local.h
ssl/statem/statem_srvr.c
ssl/t1_lib.c
test/bad_dtls_test.c
test/handshake_helper.c
test/sslapitest.c
util/libssl.num

index 88e70c5fa23591f308edcc014970cae4b94e1dac..ae812097c58228e48ab9839180b4836efce027c1 100644 (file)
@@ -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.
index 3b52f864125cb0765333631f6eb066d7cc167f98..c1b6b8e5dc959fcb7d94d9c1d2700f1cc34f0cab 100644 (file)
@@ -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
index 9a1683e0fd4d09f38477dff168a33cc8c5d7e533..9181e0d2c13707f0067b9fbdf70aa268f4daf4a5 100644 (file)
@@ -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
index 745bccc83639c994b0d64829a89f4ff190d1dbd9..a1a61cf3281b014cc767a5ebadc413df91e97345 100644 (file)
@@ -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;
index 43b0623a0b9d567b8a7543acacae67c935937fe1..680afa070a2ccbdc0090d64ce6ea619128dcfb45 100644 (file)
@@ -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 */
index 4a18ad416d340ddced44148d2107ded6f5496095..50eaf69da4f6c94652da390961947e46323a9c2f 100644 (file)
@@ -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;
 }
 
index 0504f6bba1dde341d9bc26c0ea2a102cc18c46ed..fa2d6e0154716e1ac7f7e1d0deeb87796e046608 100644 (file)
@@ -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;
+}
+
index 66b5e1d2eda8f21c8bd5ae7524eabef5f3fd2472..9716b521931b44a94754fccab2828607183f051a 100644 (file)
@@ -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;
index e8249a7ce2316f13d9f5427713cad11d83116cc6..86313c9e3cac79160052d5c5c176aa9a38e03b16 100644 (file)
@@ -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) {
index 4993f16f4cfb4d95dd8f19c76aa71d90919a2be1..cf0fd3f37d1124812725225424ee61d03a15d622 100644 (file)
@@ -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(test_cert_cb, 6);
     ADD_ALL_TESTS(test_client_cert_cb, 2);
index 29d8af6258fbaac4ab7ecc2e18b95412c6d4faf1..c2b162f3bd43f965f9c6cf393c43cab1ad635f28 100644 (file)
@@ -511,4 +511,5 @@ SSL_CTX_set_default_verify_store        ?   3_0_0   EXIST::FUNCTION:
 SSL_CTX_load_verify_file                ?      3_0_0   EXIST::FUNCTION:
 SSL_CTX_load_verify_dir                 ?      3_0_0   EXIST::FUNCTION:
 SSL_CTX_load_verify_store               ?      3_0_0   EXIST::FUNCTION:
+SSL_CTX_set_tlsext_ticket_key_evp_cb    ?      3_0_0   EXIST::FUNCTION:
 SSL_CTX_new_with_libctx                 ?      3_0_0   EXIST::FUNCTION: