From 55d3c8d25a6bd5764dcafed8b899723b80fd5a92 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 1 Apr 2020 19:05:59 +0300 Subject: [PATCH 81/87] ssl: fix Finished message length for CTR-OMAC ciphersuites CTR-OMAC ciphersuites use 32-byte Finished messages. Generate them properly. Signed-off-by: Dmitry Baryshkov --- src/lib/libssl/ssl_both.c | 18 ++++++++++-------- src/lib/libssl/ssl_locl.h | 5 +++-- src/lib/libssl/ssl_pkt.c | 2 +- src/lib/libssl/t1_enc.c | 13 ++++++++++--- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/lib/libssl/ssl_both.c b/src/lib/libssl/ssl_both.c index 488a5ff7c..8c71e580f 100644 --- a/src/lib/libssl/ssl_both.c +++ b/src/lib/libssl/ssl_both.c @@ -175,9 +175,12 @@ ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen) md_len = TLS1_FINISH_MAC_LENGTH; OPENSSL_assert(md_len <= EVP_MAX_MD_SIZE); - if (tls1_final_finish_mac(s, sender, slen, - S3I(s)->tmp.finish_md) != md_len) + md_len = tls1_final_finish_mac(s, sender, slen, + S3I(s)->tmp.finish_md, sizeof(S3I(s)->tmp.finish_md)); + if (md_len == 0) { + SSLerror(s, ERR_R_INTERNAL_ERROR); return (0); + } S3I(s)->tmp.finish_md_len = md_len; /* Copy finished so we can use it for renegotiation checks. */ @@ -237,7 +240,7 @@ ssl3_take_mac(SSL *s) S3I(s)->tmp.peer_finish_md_len = tls1_final_finish_mac(s, sender, slen, - S3I(s)->tmp.peer_finish_md); + S3I(s)->tmp.peer_finish_md, sizeof(S3I(s)->tmp.peer_finish_md)); } int @@ -260,8 +263,6 @@ ssl3_get_finished(SSL *s, int a, int b) } S3I(s)->change_cipher_spec = 0; - md_len = TLS1_FINISH_MAC_LENGTH; - if (n < 0) { al = SSL_AD_DECODE_ERROR; SSLerror(s, SSL_R_BAD_DIGEST_LENGTH); @@ -270,14 +271,15 @@ ssl3_get_finished(SSL *s, int a, int b) CBS_init(&cbs, s->internal->init_msg, n); - if (S3I(s)->tmp.peer_finish_md_len != md_len || - CBS_len(&cbs) != md_len) { + md_len = S3I(s)->tmp.peer_finish_md_len; + + if (CBS_len(&cbs) != md_len) { al = SSL_AD_DECODE_ERROR; SSLerror(s, SSL_R_BAD_DIGEST_LENGTH); goto f_err; } - if (!CBS_mem_equal(&cbs, S3I(s)->tmp.peer_finish_md, CBS_len(&cbs))) { + if (!CBS_mem_equal(&cbs, S3I(s)->tmp.peer_finish_md, md_len)) { al = SSL_AD_DECRYPT_ERROR; SSLerror(s, SSL_R_DIGEST_CHECK_FAILED); goto f_err; diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h index 87eb05999..f522abf96 100644 --- a/src/lib/libssl/ssl_locl.h +++ b/src/lib/libssl/ssl_locl.h @@ -874,7 +874,8 @@ typedef struct ssl3_state_internal_st { /* actually only needs to be 16+20 */ unsigned char cert_verify_md[EVP_MAX_MD_SIZE*2]; - /* actually only need to be 16+20 for SSLv3 and 12 for TLS */ + /* actually only need to be 16+20 for SSLv3 and 12 for TLS + * 32 for GOST CTR-OMAC ciphersuites */ unsigned char finish_md[EVP_MAX_MD_SIZE*2]; int finish_md_len; unsigned char peer_finish_md[EVP_MAX_MD_SIZE*2]; @@ -1337,7 +1338,7 @@ void tls1_cleanup_key_block(SSL *s); int tls1_change_cipher_state(SSL *s, int which); int tls1_setup_key_block(SSL *s); int tls1_enc(SSL *s, int snd); -int tls1_final_finish_mac(SSL *s, const char *str, int slen, unsigned char *p); +int tls1_final_finish_mac(SSL *s, const char *str, int str_len, unsigned char *out, unsigned int outlen); int tls1_mac(SSL *ssl, unsigned char *md, int snd); int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p, int len); diff --git a/src/lib/libssl/ssl_pkt.c b/src/lib/libssl/ssl_pkt.c index 157dd9895..d4aebebe9 100644 --- a/src/lib/libssl/ssl_pkt.c +++ b/src/lib/libssl/ssl_pkt.c @@ -1388,7 +1388,7 @@ ssl3_do_change_cipher_spec(SSL *s) } i = tls1_final_finish_mac(s, sender, slen, - S3I(s)->tmp.peer_finish_md); + S3I(s)->tmp.peer_finish_md, sizeof(S3I(s)->tmp.peer_finish_md)); if (i == 0) { SSLerror(s, ERR_R_INTERNAL_ERROR); return 0; diff --git a/src/lib/libssl/t1_enc.c b/src/lib/libssl/t1_enc.c index a3814dd44..7e9422b51 100644 --- a/src/lib/libssl/t1_enc.c +++ b/src/lib/libssl/t1_enc.c @@ -926,23 +926,30 @@ tls1_enc(SSL *s, int send) } int -tls1_final_finish_mac(SSL *s, const char *str, int str_len, unsigned char *out) +tls1_final_finish_mac(SSL *s, const char *str, int str_len, unsigned char *out, unsigned int outlen) { unsigned char buf[EVP_MAX_MD_SIZE]; size_t hash_len; + int finished_len = TLS1_FINISH_MAC_LENGTH; if (str_len < 0) return 0; + if (S3I(s)->hs.new_cipher->algorithm_mkey == SSL_kGOST_KDF) + finished_len = 32; + + if (finished_len > outlen) + return 0; + if (!tls1_transcript_hash_value(s, buf, sizeof(buf), &hash_len)) return 0; if (!tls1_PRF(s, s->session->master_key, s->session->master_key_length, str, str_len, buf, hash_len, NULL, 0, NULL, 0, NULL, 0, - out, TLS1_FINISH_MAC_LENGTH)) + out, finished_len)) return 0; - return TLS1_FINISH_MAC_LENGTH; + return finished_len; } int -- 2.17.1