Move handling of cipher/hash based cipher suites into the new record layer.
authorjsing <jsing@openbsd.org>
Sat, 27 Feb 2021 14:20:50 +0000 (14:20 +0000)
committerjsing <jsing@openbsd.org>
Sat, 27 Feb 2021 14:20:50 +0000 (14:20 +0000)
ok tb@

lib/libssl/d1_both.c
lib/libssl/ssl_lib.c
lib/libssl/ssl_locl.h
lib/libssl/t1_enc.c
lib/libssl/tls12_record_layer.c

index 06a8585..f4c1cb9 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: d1_both.c,v 1.67 2021/02/20 14:14:16 tb Exp $ */
+/* $OpenBSD: d1_both.c,v 1.68 2021/02/27 14:20:50 jsing Exp $ */
 /*
  * DTLS implementation written by Nagendra Modadugu
  * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
@@ -201,12 +201,6 @@ dtls1_hm_fragment_free(hm_fragment *frag)
        if (frag == NULL)
                return;
 
-       if (frag->msg_header.is_ccs) {
-               EVP_CIPHER_CTX_free(
-                   frag->msg_header.saved_retransmit_state.enc_write_ctx);
-               EVP_MD_CTX_free(
-                   frag->msg_header.saved_retransmit_state.write_hash);
-       }
        free(frag->fragment);
        free(frag->reassembly);
        free(frag);
@@ -977,8 +971,6 @@ dtls1_buffer_message(SSL *s, int is_ccs)
        frag->msg_header.is_ccs = is_ccs;
 
        /* save current state*/
-       frag->msg_header.saved_retransmit_state.enc_write_ctx = s->internal->enc_write_ctx;
-       frag->msg_header.saved_retransmit_state.write_hash = s->internal->write_hash;
        frag->msg_header.saved_retransmit_state.session = s->session;
        frag->msg_header.saved_retransmit_state.epoch = D1I(s)->w_epoch;
 
@@ -1078,11 +1070,16 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
 void
 dtls1_clear_record_buffer(SSL *s)
 {
+       hm_fragment *frag;
        pitem *item;
 
        for(item = pqueue_pop(s->d1->sent_messages); item != NULL;
            item = pqueue_pop(s->d1->sent_messages)) {
-               dtls1_hm_fragment_free((hm_fragment *)item->data);
+               frag = item->data;
+               if (frag->msg_header.is_ccs)
+                       tls12_record_layer_write_epoch_done(s->internal->rl,
+                           frag->msg_header.saved_retransmit_state.epoch);
+               dtls1_hm_fragment_free(frag);
                pitem_free(item);
        }
 }
index 57d0f4b..e0a77d7 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssl_lib.c,v 1.249 2021/02/25 17:06:05 jsing Exp $ */
+/* $OpenBSD: ssl_lib.c,v 1.250 2021/02/27 14:20:50 jsing Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -2616,22 +2616,14 @@ ssl_clear_cipher_state(SSL *s)
 void
 ssl_clear_cipher_read_state(SSL *s)
 {
-       EVP_CIPHER_CTX_free(s->enc_read_ctx);
-       s->enc_read_ctx = NULL;
-       EVP_MD_CTX_free(s->read_hash);
-       s->read_hash = NULL;
-
        tls12_record_layer_clear_read_state(s->internal->rl);
+       tls12_record_layer_read_cipher_hash(s->internal->rl,
+           &s->enc_read_ctx, &s->read_hash);
 }
 
 void
 ssl_clear_cipher_write_state(SSL *s)
 {
-       EVP_CIPHER_CTX_free(s->internal->enc_write_ctx);
-       s->internal->enc_write_ctx = NULL;
-       EVP_MD_CTX_free(s->internal->write_hash);
-       s->internal->write_hash = NULL;
-
        tls12_record_layer_clear_write_state(s->internal->rl);
 }
 
index 7ed3094..b2af8fd 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssl_locl.h,v 1.323 2021/02/25 17:06:05 jsing Exp $ */
+/* $OpenBSD: ssl_locl.h,v 1.324 2021/02/27 14:20:50 jsing Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -483,6 +483,9 @@ int tls12_record_layer_read_protected(struct tls12_record_layer *rl);
 int tls12_record_layer_write_protected(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,
+    const EVP_CIPHER *cipher, const EVP_MD *handshake_hash,
+    const EVP_MD *mac_hash);
 void tls12_record_layer_set_version(struct tls12_record_layer *rl,
     uint16_t version);
 void tls12_record_layer_set_write_epoch(struct tls12_record_layer *rl,
@@ -494,16 +497,8 @@ void tls12_record_layer_write_epoch_done(struct tls12_record_layer *rl,
 void tls12_record_layer_clear_read_state(struct tls12_record_layer *rl);
 void tls12_record_layer_clear_write_state(struct tls12_record_layer *rl);
 void tls12_record_layer_reflect_seq_num(struct tls12_record_layer *rl);
-int tls12_record_layer_set_read_aead(struct tls12_record_layer *rl,
-    SSL_AEAD_CTX *aead_ctx);
-int tls12_record_layer_set_write_aead(struct tls12_record_layer *rl,
-    SSL_AEAD_CTX *aead_ctx);
-int tls12_record_layer_set_read_cipher_hash(struct tls12_record_layer *rl,
-    EVP_CIPHER_CTX *cipher_ctx, EVP_MD_CTX *hash_ctx, int stream_mac);
-int tls12_record_layer_set_write_cipher_hash(struct tls12_record_layer *rl,
-    EVP_CIPHER_CTX *cipher_ctx, EVP_MD_CTX *hash_ctx, int stream_mac);
-int tls12_record_layer_set_read_mac_key(struct tls12_record_layer *rl,
-    const uint8_t *mac_key, size_t mac_key_len);
+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);
@@ -774,9 +769,6 @@ typedef struct ssl_internal_st {
 
        STACK_OF(SSL_CIPHER) *cipher_list_tls13;
 
-       EVP_CIPHER_CTX *enc_write_ctx;          /* cryptographic state */
-       EVP_MD_CTX *write_hash;                 /* used for mac generation */
-
        struct tls12_record_layer *rl;
 
        /* session info */
@@ -902,8 +894,6 @@ typedef struct ssl3_state_internal_st {
        SSL_HANDSHAKE_TLS13 hs_tls13;
 
        struct  {
-               int new_mac_secret_size;
-
                unsigned char cert_verify_md[EVP_MAX_MD_SIZE];
 
                unsigned char finish_md[EVP_MAX_MD_SIZE];
@@ -931,8 +921,8 @@ typedef struct ssl3_state_internal_st {
 
                const EVP_CIPHER *new_sym_enc;
                const EVP_AEAD *new_aead;
-               const EVP_MD *new_hash;
-               int new_mac_pkey_type;
+               int new_mac_secret_size;
+
                int cert_request;
        } tmp;
 
index 8f3e964..05a5b1d 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: t1_enc.c,v 1.132 2021/02/03 15:14:44 tb Exp $ */
+/* $OpenBSD: t1_enc.c,v 1.133 2021/02/27 14:20:50 jsing Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -310,98 +310,6 @@ tls1_generate_key_block(SSL *s, uint8_t *key_block, size_t key_block_len)
            NULL, 0, NULL, 0, key_block, key_block_len);
 }
 
-/*
- * tls1_change_cipher_state_cipher performs the work needed to switch cipher
- * states when using EVP_CIPHER. The argument is_read is true iff this function
- * is being called due to reading, as opposed to writing, a ChangeCipherSpec
- * message.
- */
-static int
-tls1_change_cipher_state_cipher(SSL *s, char is_read,
-    const unsigned char *mac_secret, unsigned int mac_secret_size,
-    const unsigned char *key, unsigned int key_len, const unsigned char *iv,
-    unsigned int iv_len)
-{
-       EVP_CIPHER_CTX *cipher_ctx;
-       const EVP_CIPHER *cipher;
-       EVP_MD_CTX *mac_ctx;
-       EVP_PKEY *mac_key;
-       const EVP_MD *mac;
-       int stream_mac;
-       int mac_type;
-
-       cipher = S3I(s)->tmp.new_sym_enc;
-       mac = S3I(s)->tmp.new_hash;
-       mac_type = S3I(s)->tmp.new_mac_pkey_type;
-       stream_mac = S3I(s)->hs.new_cipher->algorithm2 & TLS1_STREAM_MAC;
-
-       if (is_read) {
-               ssl_clear_cipher_read_state(s);
-
-               if ((cipher_ctx = EVP_CIPHER_CTX_new()) == NULL)
-                       goto err;
-               s->enc_read_ctx = cipher_ctx;
-               if ((mac_ctx = EVP_MD_CTX_new()) == NULL)
-                       goto err;
-               s->read_hash = mac_ctx;
-
-               if (!tls12_record_layer_set_read_cipher_hash(s->internal->rl,
-                   cipher_ctx, mac_ctx, stream_mac))
-                       goto err;
-
-               if (!tls12_record_layer_set_read_mac_key(s->internal->rl,
-                   mac_secret, mac_secret_size))
-                       goto err;
-       } else {
-               /*
-                * DTLS fragments retain a pointer to the compression, cipher
-                * and hash contexts, so that it can restore state in order
-                * to perform retransmissions. As such, we cannot free write
-                * contexts that are used for DTLS - these are instead freed
-                * by DTLS when its frees a ChangeCipherSpec fragment.
-                */
-               if (!SSL_is_dtls(s))
-                       ssl_clear_cipher_write_state(s);
-
-               if ((cipher_ctx = EVP_CIPHER_CTX_new()) == NULL)
-                       goto err;
-               s->internal->enc_write_ctx = cipher_ctx;
-               if ((mac_ctx = EVP_MD_CTX_new()) == NULL)
-                       goto err;
-               s->internal->write_hash = mac_ctx;
-
-               if (!tls12_record_layer_set_write_cipher_hash(s->internal->rl,
-                   cipher_ctx, mac_ctx, stream_mac))
-                       goto err;
-       }
-
-       EVP_CipherInit_ex(cipher_ctx, cipher, NULL, key, iv, !is_read);
-
-       if ((mac_key = EVP_PKEY_new_mac_key(mac_type, NULL, mac_secret,
-           mac_secret_size)) == NULL)
-               goto err;
-       EVP_DigestSignInit(mac_ctx, NULL, mac, NULL, mac_key);
-       EVP_PKEY_free(mac_key);
-
-       if (S3I(s)->hs.new_cipher->algorithm_enc == SSL_eGOST2814789CNT) {
-               int nid;
-               if (S3I(s)->hs.new_cipher->algorithm2 & SSL_HANDSHAKE_MAC_GOST94)
-                       nid = NID_id_Gost28147_89_CryptoPro_A_ParamSet;
-               else
-                       nid = NID_id_tc26_gost_28147_param_Z;
-
-               EVP_CIPHER_CTX_ctrl(cipher_ctx, EVP_CTRL_GOST_SET_SBOX, nid, 0);
-               if (S3I(s)->hs.new_cipher->algorithm_mac == SSL_GOST89MAC)
-                       EVP_MD_CTX_ctrl(mac_ctx, EVP_MD_CTRL_GOST_SET_SBOX, nid, 0);
-       }
-
-       return (1);
-
-err:
-       SSLerrorx(ERR_R_MALLOC_FAILURE);
-       return (0);
-}
-
 int
 tls1_change_cipher_state(SSL *s, int which)
 {
@@ -476,17 +384,14 @@ tls1_change_cipher_state(SSL *s, int which)
                if (!tls12_record_layer_change_read_cipher_state(s->internal->rl,
                    mac_secret, mac_secret_size, key, key_len, iv, iv_len))
                        goto err;
+               tls12_record_layer_read_cipher_hash(s->internal->rl,
+                   &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))
                        goto err;
        }
-
-       if (aead != NULL)
-               return 1;
-
-       return tls1_change_cipher_state_cipher(s, is_read,
-           mac_secret, mac_secret_size, key, key_len, iv, iv_len);
+       return (1);
 
  err:
        return (0);
@@ -501,7 +406,8 @@ tls1_setup_key_block(SSL *s)
        int key_len, iv_len;
        const EVP_CIPHER *cipher = NULL;
        const EVP_AEAD *aead = NULL;
-       const EVP_MD *mac = NULL;
+       const EVP_MD *handshake_hash = NULL;
+       const EVP_MD *mac_hash = NULL;
        int ret = 0;
 
        if (S3I(s)->hs.key_block_len != 0)
@@ -516,8 +422,8 @@ tls1_setup_key_block(SSL *s)
                key_len = EVP_AEAD_key_length(aead);
                iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(s->session->cipher);
        } else {
-               if (!ssl_cipher_get_evp(s->session, &cipher, &mac, &mac_type,
-                   &mac_secret_size)) {
+               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);
                }
@@ -525,13 +431,16 @@ tls1_setup_key_block(SSL *s)
                iv_len = EVP_CIPHER_iv_length(cipher);
        }
 
+       if (!ssl_get_handshake_evp_md(s, &handshake_hash))
+               return (0);
+
        S3I(s)->tmp.new_aead = aead;
        S3I(s)->tmp.new_sym_enc = cipher;
-       S3I(s)->tmp.new_hash = mac;
-       S3I(s)->tmp.new_mac_pkey_type = mac_type;
        S3I(s)->tmp.new_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);
 
index f090e2d..b7e891d 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls12_record_layer.c,v 1.18 2021/02/27 13:38:35 jsing Exp $ */
+/* $OpenBSD: tls12_record_layer.c,v 1.19 2021/02/27 14:20:50 jsing Exp $ */
 /*
  * Copyright (c) 2020 Joel Sing <jsing@openbsd.org>
  *
@@ -33,10 +33,6 @@ struct tls12_record_protection {
        uint8_t *mac_key;
        size_t mac_key_len;
 
-       /*
-        * XXX - for now these are just pointers to externally managed
-        * structs/memory. These should eventually be owned by the record layer.
-        */
        EVP_CIPHER_CTX *cipher_ctx;
        EVP_MD_CTX *hash_ctx;
 };
@@ -58,6 +54,12 @@ tls12_record_protection_clear(struct tls12_record_protection *rp)
                rp->aead_ctx = NULL;
        }
 
+       EVP_CIPHER_CTX_free(rp->cipher_ctx);
+       rp->cipher_ctx = NULL;
+
+       EVP_MD_CTX_free(rp->hash_ctx);
+       rp->hash_ctx = NULL;
+
        freezero(rp->mac_key, rp->mac_key_len);
        rp->mac_key = NULL;
        rp->mac_key_len = 0;
@@ -149,6 +151,9 @@ struct tls12_record_layer {
        uint8_t alert_desc;
 
        const EVP_AEAD *aead;
+       const EVP_CIPHER *cipher;
+       const EVP_MD *handshake_hash;
+       const EVP_MD *mac_hash;
 
        /* Pointers to active record protection (memory is not owned). */
        struct tls12_record_protection *read;
@@ -246,6 +251,16 @@ tls12_record_layer_set_aead(struct tls12_record_layer *rl, const EVP_AEAD *aead)
        rl->aead = aead;
 }
 
+void
+tls12_record_layer_set_cipher_hash(struct tls12_record_layer *rl,
+    const EVP_CIPHER *cipher, const EVP_MD *handshake_hash,
+    const EVP_MD *mac_hash)
+{
+       rl->cipher = cipher;
+       rl->handshake_hash = handshake_hash;
+       rl->mac_hash = mac_hash;
+}
+
 void
 tls12_record_layer_set_version(struct tls12_record_layer *rl, uint16_t version)
 {
@@ -290,35 +305,15 @@ tls12_record_layer_write_epoch_done(struct tls12_record_layer *rl, uint16_t epoc
        rl->write_previous = NULL;
 }
 
-static void
-tls12_record_layer_set_read_state(struct tls12_record_layer *rl,
-    EVP_CIPHER_CTX *cipher_ctx, EVP_MD_CTX *hash_ctx, int stream_mac)
-{
-       rl->read->cipher_ctx = cipher_ctx;
-       rl->read->hash_ctx = hash_ctx;
-       rl->read->stream_mac = stream_mac;
-}
-
-static void
-tls12_record_layer_set_write_state(struct tls12_record_layer *rl,
-    EVP_CIPHER_CTX *cipher_ctx, EVP_MD_CTX *hash_ctx, int stream_mac)
-{
-       rl->write->cipher_ctx = cipher_ctx;
-       rl->write->hash_ctx = hash_ctx;
-       rl->write->stream_mac = stream_mac;
-}
-
 void
 tls12_record_layer_clear_read_state(struct tls12_record_layer *rl)
 {
-       tls12_record_layer_set_read_state(rl, NULL, NULL, 0);
        tls12_record_protection_clear(rl->read);
 }
 
 void
 tls12_record_layer_clear_write_state(struct tls12_record_layer *rl)
 {
-       tls12_record_layer_set_write_state(rl, NULL, NULL, 0);
        tls12_record_protection_clear(rl->write);
 
        tls12_record_protection_free(rl->write_previous);
@@ -326,48 +321,36 @@ tls12_record_layer_clear_write_state(struct tls12_record_layer *rl)
 }
 
 void
-tls12_record_layer_reflect_seq_num(struct tls12_record_layer *rl)
-{
-       memcpy(rl->write->seq_num, rl->read->seq_num,
-           sizeof(rl->write->seq_num));
-}
-
-int
-tls12_record_layer_set_read_cipher_hash(struct tls12_record_layer *rl,
-    EVP_CIPHER_CTX *cipher_ctx, EVP_MD_CTX *hash_ctx, int stream_mac)
+tls12_record_layer_read_cipher_hash(struct tls12_record_layer *rl,
+    EVP_CIPHER_CTX **cipher, EVP_MD_CTX **hash)
 {
-       tls12_record_layer_set_read_state(rl, cipher_ctx, hash_ctx,
-           stream_mac);
-
-       return 1;
+       *cipher = rl->read->cipher_ctx;
+       *hash = rl->read->hash_ctx;
 }
 
-int
-tls12_record_layer_set_write_cipher_hash(struct tls12_record_layer *rl,
-    EVP_CIPHER_CTX *cipher_ctx, EVP_MD_CTX *hash_ctx, int stream_mac)
+void
+tls12_record_layer_reflect_seq_num(struct tls12_record_layer *rl)
 {
-       tls12_record_layer_set_write_state(rl, cipher_ctx, hash_ctx,
-           stream_mac);
-
-       return 1;
+       memcpy(rl->write->seq_num, rl->read->seq_num,
+           sizeof(rl->write->seq_num));
 }
 
-int
-tls12_record_layer_set_read_mac_key(struct tls12_record_layer *rl,
+static int
+tls12_record_layer_set_mac_key(struct tls12_record_protection *rp,
     const uint8_t *mac_key, size_t mac_key_len)
 {
-       freezero(rl->read->mac_key, rl->read->mac_key_len);
-       rl->read->mac_key = NULL;
-       rl->read->mac_key_len = 0;
+       freezero(rp->mac_key, rp->mac_key_len);
+       rp->mac_key = NULL;
+       rp->mac_key_len = 0;
 
        if (mac_key == NULL || mac_key_len == 0)
                return 1;
 
-       if ((rl->read->mac_key = calloc(1, mac_key_len)) == NULL)
+       if ((rp->mac_key = calloc(1, mac_key_len)) == NULL)
                return 0;
 
-       memcpy(rl->read->mac_key, mac_key, mac_key_len);
-       rl->read->mac_key_len = mac_key_len;
+       memcpy(rp->mac_key, mac_key, mac_key_len);
+       rp->mac_key_len = mac_key_len;
 
        return 1;
 }
@@ -420,6 +403,76 @@ tls12_record_layer_ccs_aead(struct tls12_record_layer *rl,
        return 1;
 }
 
+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)
+{
+       EVP_PKEY *mac_pkey = NULL;
+       int gost_param_nid;
+       int mac_type;
+       int ret = 0;
+
+       mac_type = EVP_PKEY_HMAC;
+       rp->stream_mac = 0;
+
+       /* Special handling for GOST... */
+       if (EVP_MD_type(rl->mac_hash) == NID_id_Gost28147_89_MAC) {
+               if (mac_key_len != 32)
+                       goto err;
+               mac_type = EVP_PKEY_GOSTIMIT;
+               rp->stream_mac = 1;
+       } else {
+               if (EVP_MD_size(rl->mac_hash) != mac_key_len)
+                       goto err;
+       }
+
+       if ((rp->cipher_ctx = EVP_CIPHER_CTX_new()) == NULL)
+               goto err;
+       if ((rp->hash_ctx = EVP_MD_CTX_new()) == NULL)
+               goto err;
+
+       if (!tls12_record_layer_set_mac_key(rp, mac_key, mac_key_len))
+               goto err;
+
+       if ((mac_pkey = EVP_PKEY_new_mac_key(mac_type, NULL, mac_key,
+           mac_key_len)) == NULL)
+               goto err;
+
+       if (!EVP_CipherInit_ex(rp->cipher_ctx, rl->cipher, NULL, key, iv,
+           is_write))
+               goto err;
+
+       if (EVP_DigestSignInit(rp->hash_ctx, NULL, rl->mac_hash, NULL,
+           mac_pkey) <= 0)
+               goto err;
+
+       /* More special handling for GOST... */
+       if (EVP_CIPHER_type(rl->cipher) == NID_gost89_cnt) {
+               gost_param_nid = NID_id_tc26_gost_28147_param_Z;
+               if (EVP_MD_type(rl->handshake_hash) == NID_id_GostR3411_94)
+                       gost_param_nid = NID_id_Gost28147_89_CryptoPro_A_ParamSet;
+
+               if (EVP_CIPHER_CTX_ctrl(rp->cipher_ctx, EVP_CTRL_GOST_SET_SBOX,
+                   gost_param_nid, 0) <= 0)
+                       goto err;
+
+               if (EVP_MD_type(rl->mac_hash) == NID_id_Gost28147_89_MAC) {
+                       if (EVP_MD_CTX_ctrl(rp->hash_ctx, EVP_MD_CTRL_GOST_SET_SBOX,
+                           gost_param_nid, 0) <= 0)
+                               goto err;
+               }
+       }
+
+       ret = 1;
+
+ err:
+       EVP_PKEY_free(mac_pkey);
+
+       return ret;
+}
+
 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,
@@ -433,11 +486,11 @@ tls12_record_layer_change_cipher_state(struct tls12_record_layer *rl,
        if (mac_key_len > INT_MAX || key_len > INT_MAX || iv_len > INT_MAX)
                return 0;
 
-       /* XXX - only aead for now. */
-       if (rl->aead == NULL)
-               return 1;
+       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);
 
-       return tls12_record_layer_ccs_aead(rl, rp, is_write, mac_key,
+       return tls12_record_layer_ccs_cipher(rl, rp, is_write, mac_key,
            mac_key_len, key, key_len, iv, iv_len);
 }