Add code to handle change of cipher state in the new TLSv1.2 record layer.
authorjsing <jsing@openbsd.org>
Tue, 19 Jan 2021 19:07:39 +0000 (19:07 +0000)
committerjsing <jsing@openbsd.org>
Tue, 19 Jan 2021 19:07:39 +0000 (19:07 +0000)
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
lib/libssl/d1_pkt.c
lib/libssl/ssl_locl.h
lib/libssl/t1_enc.c
lib/libssl/tls12_record_layer.c

index d6bf6df..8c4fec5 100644 (file)
@@ -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 ==
index 14ff822..bde13c9 100644 (file)
@@ -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));
index e0a4c49..5a3e3ff 100644 (file)
@@ -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,
index 6c376be..875aae3 100644 (file)
@@ -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);
 }
 
index affc537..83d71d1 100644 (file)
@@ -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 <jsing@openbsd.org>
  *
@@ -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)