Rewrite TLSv1.2 key block handling.
authorjsing <jsing@openbsd.org>
Wed, 5 May 2021 10:05:27 +0000 (10:05 +0000)
committerjsing <jsing@openbsd.org>
Wed, 5 May 2021 10:05:27 +0000 (10:05 +0000)
For TLSv1.2 a single key block is generated, then partitioned into
individual secrets for use as IVs and keys. The previous implementation
splits this across two functions tls1_setup_key_block() and
tls1_change_cipher_state(), which means that the IV and key sizes have to
be known in multiple places.

This implementation generates and partitions the key block in a single
step, meaning that the secrets are then simply handed out when requested.

ok inoguchi@ tb@

lib/libssl/Makefile
lib/libssl/ssl_locl.h
lib/libssl/t1_enc.c
lib/libssl/tls12_key_schedule.c [new file with mode: 0644]
lib/libssl/tls12_record_layer.c

index d6730a5..6171194 100644 (file)
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.69 2021/04/25 13:15:22 jsing Exp $
+# $OpenBSD: Makefile,v 1.70 2021/05/05 10:05:27 jsing Exp $
 
 .include <bsd.own.mk>
 .ifndef NOMAN
@@ -67,6 +67,7 @@ SRCS= \
        ssl_versions.c \
        t1_enc.c \
        t1_lib.c \
+       tls12_key_schedule.c \
        tls12_lib.c \
        tls12_record_layer.c \
        tls13_buffer.c \
index 9dfa124..1f7e1fa 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssl_locl.h,v 1.341 2021/05/02 17:46:58 jsing Exp $ */
+/* $OpenBSD: ssl_locl.h,v 1.342 2021/05/05 10:05:27 jsing Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -431,12 +431,8 @@ typedef struct ssl_handshake_tls12_st {
        int cert_request;
        STACK_OF(X509_NAME) *ca_names;
 
-       /* Size of the MAC secret. */
-       int mac_secret_size;
-
        /* Record-layer key block for TLS 1.2 and earlier. */
-       unsigned char *key_block;
-       size_t key_block_len;
+       struct tls12_key_block *key_block;
 
        /* Transcript hash prior to sending certificate verify message. */
        uint8_t cert_verify[EVP_MAX_MD_SIZE];
@@ -522,6 +518,17 @@ typedef struct ssl_handshake_st {
        SSL_HANDSHAKE_TLS13 tls13;
 } SSL_HANDSHAKE;
 
+struct tls12_key_block;
+
+struct tls12_key_block *tls12_key_block_new(void);
+void tls12_key_block_free(struct tls12_key_block *kb);
+void tls12_key_block_client_write(struct tls12_key_block *kb, CBS *mac_key,
+    CBS *key, CBS *iv);
+void tls12_key_block_server_write(struct tls12_key_block *kb, CBS *mac_key,
+    CBS *key, CBS *iv);
+int tls12_key_block_generate(struct tls12_key_block *kb, SSL *s,
+    const EVP_AEAD *aead, const EVP_CIPHER *cipher, const EVP_MD *mac_hash);
+
 struct tls12_record_layer;
 
 struct tls12_record_layer *tls12_record_layer_new(void);
@@ -532,8 +539,6 @@ int tls12_record_layer_write_overhead(struct tls12_record_layer *rl,
     size_t *overhead);
 int tls12_record_layer_read_protected(struct tls12_record_layer *rl);
 int tls12_record_layer_write_protected(struct tls12_record_layer *rl);
-const EVP_AEAD *tls12_record_layer_aead(struct tls12_record_layer *rl);
-const EVP_CIPHER *tls12_record_layer_cipher(struct tls12_record_layer *rl);
 void tls12_record_layer_set_aead(struct tls12_record_layer *rl,
     const EVP_AEAD *aead);
 void tls12_record_layer_set_cipher_hash(struct tls12_record_layer *rl,
@@ -553,11 +558,9 @@ void tls12_record_layer_reflect_seq_num(struct tls12_record_layer *rl);
 void tls12_record_layer_read_cipher_hash(struct tls12_record_layer *rl,
     EVP_CIPHER_CTX **cipher, EVP_MD_CTX **hash);
 int tls12_record_layer_change_read_cipher_state(struct tls12_record_layer *rl,
-    const uint8_t *mac_key, size_t mac_key_len, const uint8_t *key,
-    size_t key_len, const uint8_t *iv, size_t iv_len);
+    CBS *mac_key, CBS *key, CBS *iv);
 int tls12_record_layer_change_write_cipher_state(struct tls12_record_layer *rl,
-    const uint8_t *mac_key, size_t mac_key_len, const uint8_t *key,
-    size_t key_len, const uint8_t *iv, size_t iv_len);
+    CBS *mac_key, CBS *key, CBS *iv);
 int tls12_record_layer_open_record(struct tls12_record_layer *rl,
     uint8_t *buf, size_t buf_len, uint8_t **out, size_t *out_len);
 int tls12_record_layer_seal_record(struct tls12_record_layer *rl,
@@ -1381,6 +1384,7 @@ void tls1_cleanup_key_block(SSL *s);
 int tls1_change_read_cipher_state(SSL *s);
 int tls1_change_write_cipher_state(SSL *s);
 int tls1_setup_key_block(SSL *s);
+int tls1_generate_key_block(SSL *s, uint8_t *key_block, size_t key_block_len);
 int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
     const char *label, size_t llen, const unsigned char *p, size_t plen,
     int use_context);
index e3cdcc1..5a626fb 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: t1_enc.c,v 1.142 2021/05/02 17:46:58 jsing Exp $ */
+/* $OpenBSD: t1_enc.c,v 1.143 2021/05/05 10:05:27 jsing Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
 void
 tls1_cleanup_key_block(SSL *s)
 {
-       freezero(S3I(s)->hs.tls12.key_block, S3I(s)->hs.tls12.key_block_len);
+       tls12_key_block_free(S3I(s)->hs.tls12.key_block);
        S3I(s)->hs.tls12.key_block = NULL;
-       S3I(s)->hs.tls12.key_block_len = 0;
 }
 
 /*
@@ -283,7 +282,7 @@ tls1_PRF(SSL *s, const unsigned char *secret, size_t secret_len,
        return (1);
 }
 
-static int
+int
 tls1_generate_key_block(SSL *s, uint8_t *key_block, size_t key_block_len)
 {
        return tls1_PRF(s,
@@ -297,62 +296,20 @@ tls1_generate_key_block(SSL *s, uint8_t *key_block, size_t key_block_len)
 static int
 tls1_change_cipher_state(SSL *s, int is_write)
 {
-       const unsigned char *client_write_mac_secret, *server_write_mac_secret;
-       const unsigned char *client_write_key, *server_write_key;
-       const unsigned char *client_write_iv, *server_write_iv;
-       const unsigned char *mac_secret, *key, *iv;
-       int mac_secret_size, key_len, iv_len;
-       unsigned char *key_block;
-       const EVP_CIPHER *cipher;
-       const EVP_AEAD *aead;
-
-       aead = tls12_record_layer_aead(s->internal->rl);
-       cipher = tls12_record_layer_cipher(s->internal->rl);
-
-       if (aead != NULL) {
-               key_len = EVP_AEAD_key_length(aead);
-               iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(S3I(s)->hs.cipher);
-       } else {
-               key_len = EVP_CIPHER_key_length(cipher);
-               iv_len = EVP_CIPHER_iv_length(cipher);
-       }
-
-       mac_secret_size = S3I(s)->hs.tls12.mac_secret_size;
-
-       key_block = S3I(s)->hs.tls12.key_block;
-       client_write_mac_secret = key_block;
-       key_block += mac_secret_size;
-       server_write_mac_secret = key_block;
-       key_block += mac_secret_size;
-       client_write_key = key_block;
-       key_block += key_len;
-       server_write_key = key_block;
-       key_block += key_len;
-       client_write_iv = key_block;
-       key_block += iv_len;
-       server_write_iv = key_block;
-       key_block += iv_len;
+       CBS mac_key, key, iv;
 
        /* Use client write keys on client write and server read. */
        if ((!s->server && is_write) || (s->server && !is_write)) {
-               mac_secret = client_write_mac_secret;
-               key = client_write_key;
-               iv = client_write_iv;
+               tls12_key_block_client_write(S3I(s)->hs.tls12.key_block,
+                   &mac_key, &key, &iv);
        } else {
-               mac_secret = server_write_mac_secret;
-               key = server_write_key;
-               iv = server_write_iv;
-       }
-
-       if (key_block - S3I(s)->hs.tls12.key_block !=
-           S3I(s)->hs.tls12.key_block_len) {
-               SSLerror(s, ERR_R_INTERNAL_ERROR);
-               goto err;
+               tls12_key_block_server_write(S3I(s)->hs.tls12.key_block,
+                   &mac_key, &key, &iv);
        }
 
        if (!is_write) {
                if (!tls12_record_layer_change_read_cipher_state(s->internal->rl,
-                   mac_secret, mac_secret_size, key, key_len, iv, iv_len))
+                   &mac_key, &key, &iv))
                        goto err;
                if (SSL_is_dtls(s))
                        dtls1_reset_read_seq_numbers(s);
@@ -360,7 +317,7 @@ tls1_change_cipher_state(SSL *s, int is_write)
                    &s->enc_read_ctx, &s->read_hash);
        } else {
                if (!tls12_record_layer_change_write_cipher_state(s->internal->rl,
-                   mac_secret, mac_secret_size, key, key_len, iv, iv_len))
+                   &mac_key, &key, &iv))
                        goto err;
                if (SSL_is_dtls(s))
                        dtls1_reset_write_seq_numbers(s);
@@ -386,17 +343,19 @@ tls1_change_write_cipher_state(SSL *s)
 int
 tls1_setup_key_block(SSL *s)
 {
-       unsigned char *key_block;
+       struct tls12_key_block *key_block;
        int mac_type = NID_undef, mac_secret_size = 0;
-       size_t key_block_len;
-       int key_len, iv_len;
        const EVP_CIPHER *cipher = NULL;
        const EVP_AEAD *aead = NULL;
        const EVP_MD *handshake_hash = NULL;
        const EVP_MD *mac_hash = NULL;
        int ret = 0;
 
-       if (S3I(s)->hs.tls12.key_block_len != 0)
+       /*
+        * XXX - callers should be changed so that they only call this
+        * function once.
+        */
+       if (S3I(s)->hs.tls12.key_block != NULL)
                return (1);
 
        if (s->session->cipher &&
@@ -405,41 +364,29 @@ tls1_setup_key_block(SSL *s)
                        SSLerror(s, SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
                        return (0);
                }
-               key_len = EVP_AEAD_key_length(aead);
-               iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(s->session->cipher);
        } else {
+               /* XXX - mac_type and mac_secret_size are now unused. */
                if (!ssl_cipher_get_evp(s->session, &cipher, &mac_hash,
                    &mac_type, &mac_secret_size)) {
                        SSLerror(s, SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
                        return (0);
                }
-               key_len = EVP_CIPHER_key_length(cipher);
-               iv_len = EVP_CIPHER_iv_length(cipher);
        }
 
        if (!ssl_get_handshake_evp_md(s, &handshake_hash))
                return (0);
 
-       S3I(s)->hs.tls12.mac_secret_size = mac_secret_size;
-
        tls12_record_layer_set_aead(s->internal->rl, aead);
        tls12_record_layer_set_cipher_hash(s->internal->rl, cipher,
            handshake_hash, mac_hash);
 
-       tls1_cleanup_key_block(s);
-
-       if ((key_block = reallocarray(NULL, mac_secret_size + key_len + iv_len,
-           2)) == NULL) {
-               SSLerror(s, ERR_R_MALLOC_FAILURE);
+       if ((key_block = tls12_key_block_new()) == NULL)
+               goto err;
+       if (!tls12_key_block_generate(key_block, s, aead, cipher, mac_hash))
                goto err;
-       }
-       key_block_len = (mac_secret_size + key_len + iv_len) * 2;
 
-       S3I(s)->hs.tls12.key_block_len = key_block_len;
        S3I(s)->hs.tls12.key_block = key_block;
-
-       if (!tls1_generate_key_block(s, key_block, key_block_len))
-               goto err;
+       key_block = NULL;
 
        if (!(s->internal->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) &&
            s->method->internal->version <= TLS1_VERSION) {
@@ -463,6 +410,8 @@ tls1_setup_key_block(SSL *s)
        ret = 1;
 
  err:
+       tls12_key_block_free(key_block);
+
        return (ret);
 }
 
diff --git a/lib/libssl/tls12_key_schedule.c b/lib/libssl/tls12_key_schedule.c
new file mode 100644 (file)
index 0000000..c206460
--- /dev/null
@@ -0,0 +1,175 @@
+/* $OpenBSD: tls12_key_schedule.c,v 1.1 2021/05/05 10:05:27 jsing Exp $ */
+/*
+ * Copyright (c) 2021 Joel Sing <jsing@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdlib.h>
+
+#include <openssl/evp.h>
+
+#include "bytestring.h"
+#include "ssl_locl.h"
+
+struct tls12_key_block {
+       CBS client_write_mac_key;
+       CBS server_write_mac_key;
+       CBS client_write_key;
+       CBS server_write_key;
+       CBS client_write_iv;
+       CBS server_write_iv;
+
+       uint8_t *key_block;
+       size_t key_block_len;
+};
+
+struct tls12_key_block *
+tls12_key_block_new(void)
+{
+       return calloc(1, sizeof(struct tls12_key_block));
+}
+
+static void
+tls12_key_block_clear(struct tls12_key_block *kb)
+{
+       CBS_init(&kb->client_write_mac_key, NULL, 0);
+       CBS_init(&kb->server_write_mac_key, NULL, 0);
+       CBS_init(&kb->client_write_key, NULL, 0);
+       CBS_init(&kb->server_write_key, NULL, 0);
+       CBS_init(&kb->client_write_iv, NULL, 0);
+       CBS_init(&kb->server_write_iv, NULL, 0);
+
+       freezero(kb->key_block, kb->key_block_len);
+       kb->key_block = NULL;
+       kb->key_block_len = 0;
+}
+
+void
+tls12_key_block_free(struct tls12_key_block *kb)
+{
+       if (kb == NULL)
+               return;
+
+       tls12_key_block_clear(kb);
+
+       freezero(kb, sizeof(struct tls12_key_block));
+}
+
+void
+tls12_key_block_client_write(struct tls12_key_block *kb, CBS *mac_key,
+    CBS *key, CBS *iv)
+{
+       CBS_dup(&kb->client_write_mac_key, mac_key);
+       CBS_dup(&kb->client_write_key, key);
+       CBS_dup(&kb->client_write_iv, iv);
+}
+
+void
+tls12_key_block_server_write(struct tls12_key_block *kb, CBS *mac_key,
+    CBS *key, CBS *iv)
+{
+       CBS_dup(&kb->server_write_mac_key, mac_key);
+       CBS_dup(&kb->server_write_key, key);
+       CBS_dup(&kb->server_write_iv, iv);
+}
+
+int
+tls12_key_block_generate(struct tls12_key_block *kb, SSL *s,
+    const EVP_AEAD *aead, const EVP_CIPHER *cipher, const EVP_MD *mac_hash)
+{
+       size_t mac_key_len = 0, key_len = 0, iv_len = 0;
+       uint8_t *key_block = NULL;
+       size_t key_block_len = 0;
+       CBS cbs;
+
+       /*
+        * Generate a TLSv1.2 key block and partition into individual secrets,
+        * as per RFC 5246 section 6.3.
+        */
+
+       tls12_key_block_clear(kb);
+
+       /* Must have AEAD or cipher/MAC pair. */
+       if (aead == NULL && (cipher == NULL || mac_hash == NULL))
+               goto err;
+
+       if (aead != NULL) {
+               key_len = EVP_AEAD_key_length(aead);
+
+               /* AEAD fixed nonce length. */
+               if (aead == EVP_aead_aes_128_gcm() ||
+                   aead == EVP_aead_aes_256_gcm())
+                       iv_len = 4;
+               else if (aead == EVP_aead_chacha20_poly1305())
+                       iv_len = 12;
+               else
+                       goto err;
+       } else if (cipher != NULL && mac_hash != NULL) {
+               /*
+                * A negative integer return value will be detected via the
+                * EVP_MAX_* checks against the size_t variables below.
+                */
+               mac_key_len = EVP_MD_size(mac_hash);
+               key_len = EVP_CIPHER_key_length(cipher);
+               iv_len = EVP_CIPHER_iv_length(cipher);
+
+               /* Special handling for GOST... */
+               if (EVP_MD_type(mac_hash) == NID_id_Gost28147_89_MAC)
+                       mac_key_len = 32;
+       }
+
+       if (mac_key_len > EVP_MAX_MD_SIZE)
+               goto err;
+       if (key_len > EVP_MAX_KEY_LENGTH)
+               goto err;
+       if (iv_len > EVP_MAX_IV_LENGTH)
+               goto err;
+
+       key_block_len = 2 * mac_key_len + 2 * key_len + 2 * iv_len;
+       if ((key_block = calloc(1, key_block_len)) == NULL)
+               goto err;
+
+       if (!tls1_generate_key_block(s, key_block, key_block_len))
+               goto err;
+
+       kb->key_block = key_block;
+       kb->key_block_len = key_block_len;
+       key_block = NULL;
+       key_block_len = 0;
+
+       /* Partition key block into individual secrets. */
+       CBS_init(&cbs, kb->key_block, kb->key_block_len);
+       if (!CBS_get_bytes(&cbs, &kb->client_write_mac_key, mac_key_len))
+               goto err;
+       if (!CBS_get_bytes(&cbs, &kb->server_write_mac_key, mac_key_len))
+               goto err;
+       if (!CBS_get_bytes(&cbs, &kb->client_write_key, key_len))
+               goto err;
+       if (!CBS_get_bytes(&cbs, &kb->server_write_key, key_len))
+               goto err;
+       if (!CBS_get_bytes(&cbs, &kb->client_write_iv, iv_len))
+               goto err;
+       if (!CBS_get_bytes(&cbs, &kb->server_write_iv, iv_len))
+               goto err;
+       if (CBS_len(&cbs) != 0)
+               goto err;
+
+       return 1;
+
+ err:
+       tls12_key_block_clear(kb);
+       freezero(key_block, key_block_len);
+
+       return 0;
+}
index 7e29f4e..b9a3320 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls12_record_layer.c,v 1.26 2021/04/19 17:26:39 jsing Exp $ */
+/* $OpenBSD: tls12_record_layer.c,v 1.27 2021/05/05 10:05:27 jsing Exp $ */
 /*
  * Copyright (c) 2020 Joel Sing <jsing@openbsd.org>
  *
@@ -254,18 +254,6 @@ tls12_record_layer_write_protected(struct tls12_record_layer *rl)
        return tls12_record_protection_engaged(rl->write);
 }
 
-const EVP_AEAD *
-tls12_record_layer_aead(struct tls12_record_layer *rl)
-{
-       return rl->aead;
-}
-
-const EVP_CIPHER *
-tls12_record_layer_cipher(struct tls12_record_layer *rl)
-{
-       return rl->cipher;
-}
-
 void
 tls12_record_layer_set_aead(struct tls12_record_layer *rl, const EVP_AEAD *aead)
 {
@@ -410,11 +398,10 @@ tls12_record_layer_set_mac_key(struct tls12_record_protection *rp,
 
 static int
 tls12_record_layer_ccs_aead(struct tls12_record_layer *rl,
-    struct tls12_record_protection *rp, int is_write, const uint8_t *mac_key,
-    size_t mac_key_len, const uint8_t *key, size_t key_len, const uint8_t *iv,
-    size_t iv_len)
+    struct tls12_record_protection *rp, int is_write, CBS *mac_key, CBS *key,
+    CBS *iv)
 {
-       size_t aead_nonce_len;
+       size_t aead_nonce_len, fixed_nonce_len;
 
        if (!tls12_record_protection_unused(rp))
                return 0;
@@ -431,11 +418,11 @@ tls12_record_layer_ccs_aead(struct tls12_record_layer *rl,
        if (rl->aead == EVP_aead_chacha20_poly1305())
                rp->aead_ctx->xor_fixed_nonce = 1;
 
-       if (iv_len > sizeof(rp->aead_ctx->fixed_nonce))
+       if (!CBS_write_bytes(iv, rp->aead_ctx->fixed_nonce,
+           sizeof(rp->aead_ctx->fixed_nonce), &fixed_nonce_len))
                return 0;
 
-       memcpy(rp->aead_ctx->fixed_nonce, iv, iv_len);
-       rp->aead_ctx->fixed_nonce_len = iv_len;
+       rp->aead_ctx->fixed_nonce_len = fixed_nonce_len;
        rp->aead_ctx->tag_len = EVP_AEAD_max_overhead(rl->aead);
        rp->aead_ctx->variable_nonce_len = 8;
 
@@ -454,8 +441,8 @@ tls12_record_layer_ccs_aead(struct tls12_record_layer *rl,
                        return 0;
        }
 
-       if (!EVP_AEAD_CTX_init(&rp->aead_ctx->ctx, rl->aead, key, key_len,
-           EVP_AEAD_DEFAULT_TAG_LENGTH, NULL))
+       if (!EVP_AEAD_CTX_init(&rp->aead_ctx->ctx, rl->aead, CBS_data(key),
+           CBS_len(key), EVP_AEAD_DEFAULT_TAG_LENGTH, NULL))
                return 0;
 
        return 1;
@@ -463,9 +450,8 @@ tls12_record_layer_ccs_aead(struct tls12_record_layer *rl,
 
 static int
 tls12_record_layer_ccs_cipher(struct tls12_record_layer *rl,
-    struct tls12_record_protection *rp, int is_write, const uint8_t *mac_key,
-    size_t mac_key_len, const uint8_t *key, size_t key_len, const uint8_t *iv,
-    size_t iv_len)
+    struct tls12_record_protection *rp, int is_write, CBS *mac_key, CBS *key,
+    CBS *iv)
 {
        EVP_PKEY *mac_pkey = NULL;
        int gost_param_nid;
@@ -478,23 +464,23 @@ tls12_record_layer_ccs_cipher(struct tls12_record_layer *rl,
        mac_type = EVP_PKEY_HMAC;
        rp->stream_mac = 0;
 
-       if (iv_len > INT_MAX || key_len > INT_MAX)
+       if (CBS_len(iv) > INT_MAX || CBS_len(key) > INT_MAX)
                goto err;
-       if (EVP_CIPHER_iv_length(rl->cipher) != iv_len)
+       if (EVP_CIPHER_iv_length(rl->cipher) != CBS_len(iv))
                goto err;
-       if (EVP_CIPHER_key_length(rl->cipher) != key_len)
+       if (EVP_CIPHER_key_length(rl->cipher) != CBS_len(key))
                goto err;
 
        /* Special handling for GOST... */
        if (EVP_MD_type(rl->mac_hash) == NID_id_Gost28147_89_MAC) {
-               if (mac_key_len != 32)
+               if (CBS_len(mac_key) != 32)
                        goto err;
                mac_type = EVP_PKEY_GOSTIMIT;
                rp->stream_mac = 1;
        } else {
-               if (mac_key_len > INT_MAX)
+               if (CBS_len(mac_key) > INT_MAX)
                        goto err;
-               if (EVP_MD_size(rl->mac_hash) != mac_key_len)
+               if (EVP_MD_size(rl->mac_hash) != CBS_len(mac_key))
                        goto err;
        }
 
@@ -503,15 +489,16 @@ tls12_record_layer_ccs_cipher(struct tls12_record_layer *rl,
        if ((rp->hash_ctx = EVP_MD_CTX_new()) == NULL)
                goto err;
 
-       if (!tls12_record_layer_set_mac_key(rp, mac_key, mac_key_len))
+       if (!tls12_record_layer_set_mac_key(rp, CBS_data(mac_key),
+           CBS_len(mac_key)))
                goto err;
 
-       if ((mac_pkey = EVP_PKEY_new_mac_key(mac_type, NULL, mac_key,
-           mac_key_len)) == NULL)
+       if ((mac_pkey = EVP_PKEY_new_mac_key(mac_type, NULL, CBS_data(mac_key),
+           CBS_len(mac_key))) == NULL)
                goto err;
 
-       if (!EVP_CipherInit_ex(rp->cipher_ctx, rl->cipher, NULL, key, iv,
-           is_write))
+       if (!EVP_CipherInit_ex(rp->cipher_ctx, rl->cipher, NULL, CBS_data(key),
+           CBS_data(iv), is_write))
                goto err;
 
        if (EVP_DigestSignInit(rp->hash_ctx, NULL, rl->mac_hash, NULL,
@@ -545,22 +532,20 @@ tls12_record_layer_ccs_cipher(struct tls12_record_layer *rl,
 
 static int
 tls12_record_layer_change_cipher_state(struct tls12_record_layer *rl,
-    struct tls12_record_protection *rp, int is_write, const uint8_t *mac_key,
-    size_t mac_key_len, const uint8_t *key, size_t key_len, const uint8_t *iv,
-    size_t iv_len)
+    struct tls12_record_protection *rp, int is_write, CBS *mac_key, CBS *key,
+    CBS *iv)
 {
        if (rl->aead != NULL)
                return tls12_record_layer_ccs_aead(rl, rp, is_write, mac_key,
-                   mac_key_len, key, key_len, iv, iv_len);
+                   key, iv);
 
        return tls12_record_layer_ccs_cipher(rl, rp, is_write, mac_key,
-           mac_key_len, key, key_len, iv, iv_len);
+           key, iv);
 }
 
 int
 tls12_record_layer_change_read_cipher_state(struct tls12_record_layer *rl,
-    const uint8_t *mac_key, size_t mac_key_len, const uint8_t *key,
-    size_t key_len, const uint8_t *iv, size_t iv_len)
+    CBS *mac_key, CBS *key, CBS *iv)
 {
        struct tls12_record_protection *read_new = NULL;
        int ret = 0;
@@ -571,7 +556,7 @@ tls12_record_layer_change_read_cipher_state(struct tls12_record_layer *rl,
        /* Read sequence number gets reset to zero. */
 
        if (!tls12_record_layer_change_cipher_state(rl, read_new, 0,
-           mac_key, mac_key_len, key, key_len, iv, iv_len))
+           mac_key, key, iv))
                goto err;
 
        tls12_record_protection_free(rl->read_current);
@@ -588,8 +573,7 @@ tls12_record_layer_change_read_cipher_state(struct tls12_record_layer *rl,
 
 int
 tls12_record_layer_change_write_cipher_state(struct tls12_record_layer *rl,
-    const uint8_t *mac_key, size_t mac_key_len, const uint8_t *key,
-    size_t key_len, const uint8_t *iv, size_t iv_len)
+    CBS *mac_key, CBS *key, CBS *iv)
 {
        struct tls12_record_protection *write_new;
        int ret = 0;
@@ -600,7 +584,7 @@ tls12_record_layer_change_write_cipher_state(struct tls12_record_layer *rl,
        /* Write sequence number gets reset to zero. */
 
        if (!tls12_record_layer_change_cipher_state(rl, write_new, 1,
-           mac_key, mac_key_len, key, key_len, iv, iv_len))
+           mac_key, key, iv))
                goto err;
 
        if (rl->dtls) {