From a802a16adaa92c0a0d3b8521ebf2eaf7341efd30 Mon Sep 17 00:00:00 2001 From: jsing Date: Tue, 19 Jan 2021 19:07:39 +0000 Subject: [PATCH] Add code to handle change of cipher state in the new TLSv1.2 record layer. This provides the basic framework for handling change of cipher state in the new TLSv1.2 record layer, creating new record protection. In the DTLS case we retain the previous write record protection and can switch back to it when retransmitting. This will allow the record layer to start owning sequence numbers and encryption/decryption state. ok inoguchi@ tb@ --- lib/libssl/d1_both.c | 11 ++-- lib/libssl/d1_pkt.c | 4 +- lib/libssl/ssl_locl.h | 12 +++- lib/libssl/t1_enc.c | 20 +++++- lib/libssl/tls12_record_layer.c | 107 ++++++++++++++++++++++++++++++-- 5 files changed, 137 insertions(+), 17 deletions(-) diff --git a/lib/libssl/d1_both.c b/lib/libssl/d1_both.c index d6bf6dfd1b8..8c4fec589f6 100644 --- a/lib/libssl/d1_both.c +++ b/lib/libssl/d1_both.c @@ -1,4 +1,4 @@ -/* $OpenBSD: d1_both.c,v 1.64 2021/01/19 18:51:08 jsing Exp $ */ +/* $OpenBSD: d1_both.c,v 1.65 2021/01/19 19:07:39 jsing Exp $ */ /* * DTLS implementation written by Nagendra Modadugu * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. @@ -1055,9 +1055,8 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off, /* restore state in which the message was originally sent */ s->session = frag->msg_header.saved_retransmit_state.session; D1I(s)->w_epoch = frag->msg_header.saved_retransmit_state.epoch; - if (!tls12_record_layer_set_write_cipher_hash(s->internal->rl, - frag->msg_header.saved_retransmit_state.enc_write_ctx, - frag->msg_header.saved_retransmit_state.write_hash, 0)) + + if (!tls12_record_layer_use_write_epoch(s->internal->rl, D1I(s)->w_epoch)) return 0; if (frag->msg_header.saved_retransmit_state.epoch == @@ -1074,8 +1073,8 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off, /* restore current state */ s->session = saved_state.session; D1I(s)->w_epoch = saved_state.epoch; - if (!tls12_record_layer_set_write_cipher_hash(s->internal->rl, - s->internal->enc_write_ctx, s->internal->write_hash, 0)) + + if (!tls12_record_layer_use_write_epoch(s->internal->rl, D1I(s)->w_epoch)) return 0; if (frag->msg_header.saved_retransmit_state.epoch == diff --git a/lib/libssl/d1_pkt.c b/lib/libssl/d1_pkt.c index 14ff8221be6..bde13c99e5e 100644 --- a/lib/libssl/d1_pkt.c +++ b/lib/libssl/d1_pkt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: d1_pkt.c,v 1.89 2021/01/19 18:57:09 jsing Exp $ */ +/* $OpenBSD: d1_pkt.c,v 1.90 2021/01/19 19:07:39 jsing Exp $ */ /* * DTLS implementation written by Nagendra Modadugu * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. @@ -1105,7 +1105,6 @@ do_dtls1_write(SSL *s, int type, const unsigned char *buf, unsigned int len) goto err; tls12_record_layer_set_version(s->internal->rl, s->version); - tls12_record_layer_set_write_epoch(s->internal->rl, D1I(s)->w_epoch); if (!tls12_record_layer_seal_record(s->internal->rl, type, buf, len, &cbb)) goto err; @@ -1245,6 +1244,7 @@ dtls1_reset_seq_numbers(SSL *s, int rw) memset(S3I(s)->read_sequence, 0, sizeof(S3I(s)->read_sequence)); } else { D1I(s)->w_epoch++; + tls12_record_layer_set_write_epoch(s->internal->rl, D1I(s)->w_epoch); memcpy(D1I(s)->last_write_sequence, S3I(s)->write_sequence, sizeof(S3I(s)->write_sequence)); memset(S3I(s)->write_sequence, 0, sizeof(S3I(s)->write_sequence)); diff --git a/lib/libssl/ssl_locl.h b/lib/libssl/ssl_locl.h index e0a4c49ccb6..5a3e3ff7260 100644 --- a/lib/libssl/ssl_locl.h +++ b/lib/libssl/ssl_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_locl.h,v 1.314 2021/01/19 18:57:09 jsing Exp $ */ +/* $OpenBSD: ssl_locl.h,v 1.315 2021/01/19 19:07:39 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -485,6 +485,10 @@ 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, uint16_t epoch); +int tls12_record_layer_use_write_epoch(struct tls12_record_layer *rl, + uint16_t epoch); +void tls12_record_layer_write_epoch_done(struct tls12_record_layer *rl, + uint16_t epoch); 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_set_read_seq_num(struct tls12_record_layer *rl, @@ -501,6 +505,12 @@ 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); +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); +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); 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, diff --git a/lib/libssl/t1_enc.c b/lib/libssl/t1_enc.c index 6c376be2e02..875aae36b03 100644 --- a/lib/libssl/t1_enc.c +++ b/lib/libssl/t1_enc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: t1_enc.c,v 1.128 2021/01/07 15:32:59 jsing Exp $ */ +/* $OpenBSD: t1_enc.c,v 1.129 2021/01/19 19:07:39 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -562,7 +562,21 @@ tls1_change_cipher_state(SSL *s, int which) if (key_block - S3I(s)->hs.key_block != S3I(s)->hs.key_block_len) { SSLerror(s, ERR_R_INTERNAL_ERROR); - goto err2; + goto err; + } + + if (is_read) { + 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_set_read_seq_num(s->internal->rl, + S3I(s)->read_sequence); + } 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; + tls12_record_layer_set_write_seq_num(s->internal->rl, + S3I(s)->write_sequence); } if (aead != NULL) { @@ -573,7 +587,7 @@ tls1_change_cipher_state(SSL *s, int which) return tls1_change_cipher_state_cipher(s, is_read, mac_secret, mac_secret_size, key, key_len, iv, iv_len); -err2: + err: return (0); } diff --git a/lib/libssl/tls12_record_layer.c b/lib/libssl/tls12_record_layer.c index affc5375a2e..83d71d1c7a0 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.12 2021/01/19 18:57:09 jsing Exp $ */ +/* $OpenBSD: tls12_record_layer.c,v 1.13 2021/01/19 19:07:39 jsing Exp $ */ /* * Copyright (c) 2020 Joel Sing * @@ -132,8 +132,13 @@ struct tls12_record_layer { uint8_t alert_desc; + /* Pointers to active record protection (memory is not owned). */ struct tls12_record_protection *read; struct tls12_record_protection *write; + + struct tls12_record_protection *read_current; + struct tls12_record_protection *write_current; + struct tls12_record_protection *write_previous; }; struct tls12_record_layer * @@ -143,11 +148,14 @@ tls12_record_layer_new(void) if ((rl = calloc(1, sizeof(struct tls12_record_layer))) == NULL) goto err; - if ((rl->read = tls12_record_protection_new()) == NULL) + if ((rl->read_current = tls12_record_protection_new()) == NULL) goto err; - if ((rl->write = tls12_record_protection_new()) == NULL) + if ((rl->write_current = tls12_record_protection_new()) == NULL) goto err; + rl->read = rl->read_current; + rl->write = rl->write_current; + return rl; err: @@ -162,8 +170,9 @@ tls12_record_layer_free(struct tls12_record_layer *rl) if (rl == NULL) return; - tls12_record_protection_free(rl->read); - tls12_record_protection_free(rl->write); + tls12_record_protection_free(rl->read_current); + tls12_record_protection_free(rl->write_current); + tls12_record_protection_free(rl->write_previous); freezero(rl, sizeof(struct tls12_record_layer)); } @@ -226,6 +235,37 @@ tls12_record_layer_set_write_epoch(struct tls12_record_layer *rl, uint16_t epoch rl->write->epoch = epoch; } +int +tls12_record_layer_use_write_epoch(struct tls12_record_layer *rl, uint16_t epoch) +{ + if (rl->write->epoch == epoch) + return 1; + + if (rl->write_current->epoch == epoch) { + rl->write = rl->write_current; + return 1; + } + + if (rl->write_previous != NULL && rl->write_previous->epoch == epoch) { + rl->write = rl->write_previous; + return 1; + } + + return 0; +} + +void +tls12_record_layer_write_epoch_done(struct tls12_record_layer *rl, uint16_t epoch) +{ + if (rl->write_previous == NULL || rl->write_previous->epoch != epoch) + return; + + rl->write = rl->write_current; + + tls12_record_protection_free(rl->write_previous); + rl->write_previous = NULL; +} + static void tls12_record_layer_set_read_state(struct tls12_record_layer *rl, SSL_AEAD_CTX *aead_ctx, EVP_CIPHER_CTX *cipher_ctx, EVP_MD_CTX *hash_ctx, @@ -263,6 +303,9 @@ tls12_record_layer_clear_write_state(struct tls12_record_layer *rl) { tls12_record_layer_set_write_state(rl, NULL, NULL, NULL, 0); rl->write->seq_num = NULL; + + tls12_record_protection_free(rl->write_previous); + rl->write_previous = NULL; } void @@ -337,6 +380,60 @@ tls12_record_layer_set_read_mac_key(struct tls12_record_layer *rl, return 1; } +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) +{ + struct tls12_record_protection *read_new = NULL; + int ret = 0; + + if ((read_new = tls12_record_protection_new()) == NULL) + goto err; + + /* XXX - change cipher state. */ + + tls12_record_protection_free(rl->read_current); + rl->read = rl->read_current = read_new; + read_new = NULL; + + ret = 1; + + err: + tls12_record_protection_free(read_new); + + return ret; +} + +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) +{ + struct tls12_record_protection *write_new; + int ret = 0; + + if ((write_new = tls12_record_protection_new()) == NULL) + goto err; + + /* XXX - change cipher state. */ + + if (rl->dtls) { + tls12_record_protection_free(rl->write_previous); + rl->write_previous = rl->write_current; + rl->write_current = NULL; + } + tls12_record_protection_free(rl->write_current); + rl->write = rl->write_current = write_new; + write_new = NULL; + + ret = 1; + + err: + tls12_record_protection_free(write_new); + + return ret; +} static int tls12_record_layer_build_seq_num(struct tls12_record_layer *rl, CBB *cbb, uint16_t epoch, uint8_t *seq_num, size_t seq_num_len) -- 2.20.1