From 2935b8f4e5570a30caaf3e515c99c9386b8c06cb Mon Sep 17 00:00:00 2001 From: jsing Date: Sat, 27 Feb 2021 14:20:50 +0000 Subject: [PATCH] Move handling of cipher/hash based cipher suites into the new record layer. ok tb@ --- lib/libssl/d1_both.c | 17 ++-- lib/libssl/ssl_lib.c | 14 +-- lib/libssl/ssl_locl.h | 26 ++--- lib/libssl/t1_enc.c | 117 +++------------------- lib/libssl/tls12_record_layer.c | 167 +++++++++++++++++++++----------- 5 files changed, 141 insertions(+), 200 deletions(-) diff --git a/lib/libssl/d1_both.c b/lib/libssl/d1_both.c index 06a8585e10f..f4c1cb95b09 100644 --- a/lib/libssl/d1_both.c +++ b/lib/libssl/d1_both.c @@ -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); } } diff --git a/lib/libssl/ssl_lib.c b/lib/libssl/ssl_lib.c index 57d0f4b7791..e0a77d78201 100644 --- a/lib/libssl/ssl_lib.c +++ b/lib/libssl/ssl_lib.c @@ -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); } diff --git a/lib/libssl/ssl_locl.h b/lib/libssl/ssl_locl.h index 7ed3094c3ee..b2af8fd7c96 100644 --- a/lib/libssl/ssl_locl.h +++ b/lib/libssl/ssl_locl.h @@ -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; diff --git a/lib/libssl/t1_enc.c b/lib/libssl/t1_enc.c index 8f3e9649b06..05a5b1d9534 100644 --- a/lib/libssl/t1_enc.c +++ b/lib/libssl/t1_enc.c @@ -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); diff --git a/lib/libssl/tls12_record_layer.c b/lib/libssl/tls12_record_layer.c index f090e2d940a..b7e891d2687 100644 --- a/lib/libssl/tls12_record_layer.c +++ b/lib/libssl/tls12_record_layer.c @@ -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 * @@ -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); } -- 2.20.1