diff options
| author | jsing <> | 2018-09-05 16:48:11 +0000 |
|---|---|---|
| committer | jsing <> | 2018-09-05 16:48:11 +0000 |
| commit | c67d138a999b0555285f0993584d8124abc2b926 (patch) | |
| tree | 7285548c994d450785c9af93c1936fef8e5ee489 | |
| parent | cbd19c03dd185d497c1db407d6c4f002cb4abc92 (diff) | |
| download | openbsd-c67d138a999b0555285f0993584d8124abc2b926.tar.gz openbsd-c67d138a999b0555285f0993584d8124abc2b926.tar.bz2 openbsd-c67d138a999b0555285f0993584d8124abc2b926.zip | |
Correctly clear the current cipher state, when changing cipher state.
When a renegotiation results in a change of cipher suite, the renegotation
would fail if it switched from AEAD to non-AEAD or vice versa. This is due
to the fact that the previous EVP_AEAD or EVP_CIPHER state remained,
resulting in incorrect logic that caused MAC failures.
Rename ssl_clear_cipher_ctx() to ssl_clear_cipher_state() and split it
into separate read/write components, then call these functions from the
appropriate places when a ChangeCipherSpec message is being processed.
Also, remove the separate ssl_clear_hash_ctx() calls and fold these into
the ssl_clear_cipher_{read,write}_state() functions.
Issue reported by Bernard Spil, who also tested this diff.
ok tb@
Diffstat (limited to '')
| -rw-r--r-- | src/lib/libssl/ssl_lib.c | 52 | ||||
| -rw-r--r-- | src/lib/libssl/ssl_locl.h | 7 | ||||
| -rw-r--r-- | src/lib/libssl/t1_enc.c | 19 |
3 files changed, 37 insertions, 41 deletions
diff --git a/src/lib/libssl/ssl_lib.c b/src/lib/libssl/ssl_lib.c index 938139e18e..44d11d4b16 100644 --- a/src/lib/libssl/ssl_lib.c +++ b/src/lib/libssl/ssl_lib.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: ssl_lib.c,v 1.187 2018/08/30 16:56:16 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_lib.c,v 1.188 2018/09/05 16:48:11 jsing Exp $ */ |
| 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| @@ -191,9 +191,7 @@ SSL_clear(SSL *s) | |||
| 191 | BUF_MEM_free(s->internal->init_buf); | 191 | BUF_MEM_free(s->internal->init_buf); |
| 192 | s->internal->init_buf = NULL; | 192 | s->internal->init_buf = NULL; |
| 193 | 193 | ||
| 194 | ssl_clear_cipher_ctx(s); | 194 | ssl_clear_cipher_state(s); |
| 195 | ssl_clear_hash_ctx(&s->read_hash); | ||
| 196 | ssl_clear_hash_ctx(&s->internal->write_hash); | ||
| 197 | 195 | ||
| 198 | s->internal->first_packet = 0; | 196 | s->internal->first_packet = 0; |
| 199 | 197 | ||
| @@ -534,9 +532,7 @@ SSL_free(SSL *s) | |||
| 534 | SSL_SESSION_free(s->session); | 532 | SSL_SESSION_free(s->session); |
| 535 | } | 533 | } |
| 536 | 534 | ||
| 537 | ssl_clear_cipher_ctx(s); | 535 | ssl_clear_cipher_state(s); |
| 538 | ssl_clear_hash_ctx(&s->read_hash); | ||
| 539 | ssl_clear_hash_ctx(&s->internal->write_hash); | ||
| 540 | 536 | ||
| 541 | ssl_cert_free(s->cert); | 537 | ssl_cert_free(s->cert); |
| 542 | 538 | ||
| @@ -2431,10 +2427,7 @@ SSL_set_accept_state(SSL *s) | |||
| 2431 | s->internal->shutdown = 0; | 2427 | s->internal->shutdown = 0; |
| 2432 | S3I(s)->hs.state = SSL_ST_ACCEPT|SSL_ST_BEFORE; | 2428 | S3I(s)->hs.state = SSL_ST_ACCEPT|SSL_ST_BEFORE; |
| 2433 | s->internal->handshake_func = s->method->internal->ssl_accept; | 2429 | s->internal->handshake_func = s->method->internal->ssl_accept; |
| 2434 | /* clear the current cipher */ | 2430 | ssl_clear_cipher_state(s); |
| 2435 | ssl_clear_cipher_ctx(s); | ||
| 2436 | ssl_clear_hash_ctx(&s->read_hash); | ||
| 2437 | ssl_clear_hash_ctx(&s->internal->write_hash); | ||
| 2438 | } | 2431 | } |
| 2439 | 2432 | ||
| 2440 | void | 2433 | void |
| @@ -2444,10 +2437,7 @@ SSL_set_connect_state(SSL *s) | |||
| 2444 | s->internal->shutdown = 0; | 2437 | s->internal->shutdown = 0; |
| 2445 | S3I(s)->hs.state = SSL_ST_CONNECT|SSL_ST_BEFORE; | 2438 | S3I(s)->hs.state = SSL_ST_CONNECT|SSL_ST_BEFORE; |
| 2446 | s->internal->handshake_func = s->method->internal->ssl_connect; | 2439 | s->internal->handshake_func = s->method->internal->ssl_connect; |
| 2447 | /* clear the current cipher */ | 2440 | ssl_clear_cipher_state(s); |
| 2448 | ssl_clear_cipher_ctx(s); | ||
| 2449 | ssl_clear_hash_ctx(&s->read_hash); | ||
| 2450 | ssl_clear_hash_ctx(&s->internal->write_hash); | ||
| 2451 | } | 2441 | } |
| 2452 | 2442 | ||
| 2453 | int | 2443 | int |
| @@ -2623,24 +2613,40 @@ SSL_dup(SSL *s) | |||
| 2623 | } | 2613 | } |
| 2624 | 2614 | ||
| 2625 | void | 2615 | void |
| 2626 | ssl_clear_cipher_ctx(SSL *s) | 2616 | ssl_clear_cipher_state(SSL *s) |
| 2617 | { | ||
| 2618 | ssl_clear_cipher_read_state(s); | ||
| 2619 | ssl_clear_cipher_write_state(s); | ||
| 2620 | } | ||
| 2621 | |||
| 2622 | void | ||
| 2623 | ssl_clear_cipher_read_state(SSL *s) | ||
| 2627 | { | 2624 | { |
| 2628 | EVP_CIPHER_CTX_free(s->enc_read_ctx); | 2625 | EVP_CIPHER_CTX_free(s->enc_read_ctx); |
| 2629 | s->enc_read_ctx = NULL; | 2626 | s->enc_read_ctx = NULL; |
| 2630 | EVP_CIPHER_CTX_free(s->internal->enc_write_ctx); | 2627 | EVP_MD_CTX_destroy(s->read_hash); |
| 2631 | s->internal->enc_write_ctx = NULL; | 2628 | s->read_hash = NULL; |
| 2632 | 2629 | ||
| 2633 | if (s->internal->aead_read_ctx != NULL) { | 2630 | if (s->internal->aead_read_ctx != NULL) { |
| 2634 | EVP_AEAD_CTX_cleanup(&s->internal->aead_read_ctx->ctx); | 2631 | EVP_AEAD_CTX_cleanup(&s->internal->aead_read_ctx->ctx); |
| 2635 | free(s->internal->aead_read_ctx); | 2632 | free(s->internal->aead_read_ctx); |
| 2636 | s->internal->aead_read_ctx = NULL; | 2633 | s->internal->aead_read_ctx = NULL; |
| 2637 | } | 2634 | } |
| 2635 | } | ||
| 2636 | |||
| 2637 | void | ||
| 2638 | ssl_clear_cipher_write_state(SSL *s) | ||
| 2639 | { | ||
| 2640 | EVP_CIPHER_CTX_free(s->internal->enc_write_ctx); | ||
| 2641 | s->internal->enc_write_ctx = NULL; | ||
| 2642 | EVP_MD_CTX_destroy(s->internal->write_hash); | ||
| 2643 | s->internal->write_hash = NULL; | ||
| 2644 | |||
| 2638 | if (s->internal->aead_write_ctx != NULL) { | 2645 | if (s->internal->aead_write_ctx != NULL) { |
| 2639 | EVP_AEAD_CTX_cleanup(&s->internal->aead_write_ctx->ctx); | 2646 | EVP_AEAD_CTX_cleanup(&s->internal->aead_write_ctx->ctx); |
| 2640 | free(s->internal->aead_write_ctx); | 2647 | free(s->internal->aead_write_ctx); |
| 2641 | s->internal->aead_write_ctx = NULL; | 2648 | s->internal->aead_write_ctx = NULL; |
| 2642 | } | 2649 | } |
| 2643 | |||
| 2644 | } | 2650 | } |
| 2645 | 2651 | ||
| 2646 | /* Fix this function so that it takes an optional type parameter */ | 2652 | /* Fix this function so that it takes an optional type parameter */ |
| @@ -3021,14 +3027,6 @@ SSL_set_msg_callback(SSL *ssl, void (*cb)(int write_p, int version, | |||
| 3021 | } | 3027 | } |
| 3022 | 3028 | ||
| 3023 | void | 3029 | void |
| 3024 | ssl_clear_hash_ctx(EVP_MD_CTX **hash) | ||
| 3025 | { | ||
| 3026 | if (*hash) | ||
| 3027 | EVP_MD_CTX_destroy(*hash); | ||
| 3028 | *hash = NULL; | ||
| 3029 | } | ||
| 3030 | |||
| 3031 | void | ||
| 3032 | SSL_set_debug(SSL *s, int debug) | 3030 | SSL_set_debug(SSL *s, int debug) |
| 3033 | { | 3031 | { |
| 3034 | s->internal->debug = debug; | 3032 | s->internal->debug = debug; |
diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h index b6d71492fd..a4e831577d 100644 --- a/src/lib/libssl/ssl_locl.h +++ b/src/lib/libssl/ssl_locl.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: ssl_locl.h,v 1.212 2018/08/30 16:56:16 jsing Exp $ */ | 1 | /* $OpenBSD: ssl_locl.h,v 1.213 2018/09/05 16:48:11 jsing Exp $ */ |
| 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| @@ -1039,7 +1039,9 @@ extern SSL3_ENC_METHOD TLSv1_enc_data; | |||
| 1039 | extern SSL3_ENC_METHOD TLSv1_1_enc_data; | 1039 | extern SSL3_ENC_METHOD TLSv1_1_enc_data; |
| 1040 | extern SSL3_ENC_METHOD TLSv1_2_enc_data; | 1040 | extern SSL3_ENC_METHOD TLSv1_2_enc_data; |
| 1041 | 1041 | ||
| 1042 | void ssl_clear_cipher_ctx(SSL *s); | 1042 | void ssl_clear_cipher_state(SSL *s); |
| 1043 | void ssl_clear_cipher_read_state(SSL *s); | ||
| 1044 | void ssl_clear_cipher_write_state(SSL *s); | ||
| 1043 | int ssl_clear_bad_session(SSL *s); | 1045 | int ssl_clear_bad_session(SSL *s); |
| 1044 | CERT *ssl_cert_new(void); | 1046 | CERT *ssl_cert_new(void); |
| 1045 | CERT *ssl_cert_dup(CERT *cert); | 1047 | CERT *ssl_cert_dup(CERT *cert); |
| @@ -1279,7 +1281,6 @@ int tls12_get_sigid(const EVP_PKEY *pk); | |||
| 1279 | int tls12_get_hashandsig(CBB *cbb, const EVP_PKEY *pk, const EVP_MD *md); | 1281 | int tls12_get_hashandsig(CBB *cbb, const EVP_PKEY *pk, const EVP_MD *md); |
| 1280 | const EVP_MD *tls12_get_hash(unsigned char hash_alg); | 1282 | const EVP_MD *tls12_get_hash(unsigned char hash_alg); |
| 1281 | 1283 | ||
| 1282 | void ssl_clear_hash_ctx(EVP_MD_CTX **hash); | ||
| 1283 | long ssl_get_algorithm2(SSL *s); | 1284 | long ssl_get_algorithm2(SSL *s); |
| 1284 | int tls1_process_sigalgs(SSL *s, CBS *cbs); | 1285 | int tls1_process_sigalgs(SSL *s, CBS *cbs); |
| 1285 | void tls12_get_req_sig_algs(SSL *s, unsigned char **sigalgs, | 1286 | void tls12_get_req_sig_algs(SSL *s, unsigned char **sigalgs, |
diff --git a/src/lib/libssl/t1_enc.c b/src/lib/libssl/t1_enc.c index 24fc8ede68..39f542215b 100644 --- a/src/lib/libssl/t1_enc.c +++ b/src/lib/libssl/t1_enc.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: t1_enc.c,v 1.110 2018/08/31 18:31:34 jsing Exp $ */ | 1 | /* $OpenBSD: t1_enc.c,v 1.111 2018/09/05 16:48:11 jsing Exp $ */ |
| 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| @@ -397,10 +397,13 @@ tls1_change_cipher_state_aead(SSL *s, char is_read, const unsigned char *key, | |||
| 397 | SSL_AEAD_CTX *aead_ctx; | 397 | SSL_AEAD_CTX *aead_ctx; |
| 398 | 398 | ||
| 399 | if (is_read) { | 399 | if (is_read) { |
| 400 | ssl_clear_cipher_read_state(s); | ||
| 400 | if (!tls1_aead_ctx_init(&s->internal->aead_read_ctx)) | 401 | if (!tls1_aead_ctx_init(&s->internal->aead_read_ctx)) |
| 401 | return 0; | 402 | return 0; |
| 402 | aead_ctx = s->internal->aead_read_ctx; | 403 | aead_ctx = s->internal->aead_read_ctx; |
| 403 | } else { | 404 | } else { |
| 405 | /* XXX - Need to correctly handle DTLS. */ | ||
| 406 | ssl_clear_cipher_write_state(s); | ||
| 404 | if (!tls1_aead_ctx_init(&s->internal->aead_write_ctx)) | 407 | if (!tls1_aead_ctx_init(&s->internal->aead_write_ctx)) |
| 405 | return 0; | 408 | return 0; |
| 406 | aead_ctx = s->internal->aead_write_ctx; | 409 | aead_ctx = s->internal->aead_write_ctx; |
| @@ -468,10 +471,7 @@ tls1_change_cipher_state_cipher(SSL *s, char is_read, | |||
| 468 | else | 471 | else |
| 469 | s->internal->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM; | 472 | s->internal->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM; |
| 470 | 473 | ||
| 471 | EVP_CIPHER_CTX_free(s->enc_read_ctx); | 474 | ssl_clear_cipher_read_state(s); |
| 472 | s->enc_read_ctx = NULL; | ||
| 473 | EVP_MD_CTX_destroy(s->read_hash); | ||
| 474 | s->read_hash = NULL; | ||
| 475 | 475 | ||
| 476 | if ((cipher_ctx = EVP_CIPHER_CTX_new()) == NULL) | 476 | if ((cipher_ctx = EVP_CIPHER_CTX_new()) == NULL) |
| 477 | goto err; | 477 | goto err; |
| @@ -492,12 +492,9 @@ tls1_change_cipher_state_cipher(SSL *s, char is_read, | |||
| 492 | * contexts that are used for DTLS - these are instead freed | 492 | * contexts that are used for DTLS - these are instead freed |
| 493 | * by DTLS when its frees a ChangeCipherSpec fragment. | 493 | * by DTLS when its frees a ChangeCipherSpec fragment. |
| 494 | */ | 494 | */ |
| 495 | if (!SSL_IS_DTLS(s)) { | 495 | if (!SSL_IS_DTLS(s)) |
| 496 | EVP_CIPHER_CTX_free(s->internal->enc_write_ctx); | 496 | ssl_clear_cipher_write_state(s); |
| 497 | s->internal->enc_write_ctx = NULL; | 497 | |
| 498 | EVP_MD_CTX_destroy(s->internal->write_hash); | ||
| 499 | s->internal->write_hash = NULL; | ||
| 500 | } | ||
| 501 | if ((cipher_ctx = EVP_CIPHER_CTX_new()) == NULL) | 498 | if ((cipher_ctx = EVP_CIPHER_CTX_new()) == NULL) |
| 502 | goto err; | 499 | goto err; |
| 503 | s->internal->enc_write_ctx = cipher_ctx; | 500 | s->internal->enc_write_ctx = cipher_ctx; |
