diff options
Diffstat (limited to 'ssl/statem/statem_srvr.c')
-rw-r--r-- | ssl/statem/statem_srvr.c | 91 |
1 files changed, 54 insertions, 37 deletions
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index 8cf9c40d15c0..14cb27e6db01 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -1,5 +1,5 @@ /* - * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved * Copyright 2005 Nokia. All rights reserved. * @@ -10,9 +10,9 @@ */ #include <stdio.h> -#include "../ssl_locl.h" -#include "statem_locl.h" -#include "internal/constant_time_locl.h" +#include "../ssl_local.h" +#include "statem_local.h" +#include "internal/constant_time.h" #include "internal/cryptlib.h" #include <openssl/buffer.h> #include <openssl/rand.h> @@ -23,9 +23,24 @@ #include <openssl/dh.h> #include <openssl/bn.h> #include <openssl/md5.h> +#include <openssl/asn1t.h> #define TICKET_NONCE_SIZE 8 +typedef struct { + ASN1_TYPE *kxBlob; + ASN1_TYPE *opaqueBlob; +} GOST_KX_MESSAGE; + +DECLARE_ASN1_FUNCTIONS(GOST_KX_MESSAGE) + +ASN1_SEQUENCE(GOST_KX_MESSAGE) = { + ASN1_SIMPLE(GOST_KX_MESSAGE, kxBlob, ASN1_ANY), + ASN1_OPT(GOST_KX_MESSAGE, opaqueBlob, ASN1_ANY), +} ASN1_SEQUENCE_END(GOST_KX_MESSAGE) + +IMPLEMENT_ASN1_FUNCTIONS(GOST_KX_MESSAGE) + static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt); /* @@ -728,7 +743,15 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst) case TLS_ST_SW_CHANGE: if (SSL_IS_TLS13(s)) break; - s->session->cipher = s->s3->tmp.new_cipher; + /* Writes to s->session are only safe for initial handshakes */ + if (s->session->cipher == NULL) { + s->session->cipher = s->s3->tmp.new_cipher; + } else if (s->session->cipher != s->s3->tmp.new_cipher) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, + SSL_F_OSSL_STATEM_SERVER_PRE_WORK, + ERR_R_INTERNAL_ERROR); + return WORK_ERROR; + } if (!s->method->ssl3_enc->setup_key_block(s)) { /* SSLfatal() already called */ return WORK_ERROR; @@ -932,9 +955,11 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst) } #endif if (SSL_IS_TLS13(s)) { + /* TLS 1.3 gets the secret size from the handshake md */ + size_t dummy; if (!s->method->ssl3_enc->generate_master_secret(s, s->master_secret, s->handshake_secret, 0, - &s->session->master_key_length) + &dummy) || !s->method->ssl3_enc->change_cipher_state(s, SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_WRITE)) /* SSLfatal() already called */ @@ -3320,9 +3345,9 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt) const unsigned char *start; size_t outlen = 32, inlen; unsigned long alg_a; - unsigned int asn1id, asn1len; + GOST_KX_MESSAGE *pKX = NULL; + const unsigned char *ptr; int ret = 0; - PACKET encdata; /* Get our certificate private key */ alg_a = s->s3->tmp.new_cipher->algorithm_auth; @@ -3363,42 +3388,33 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt) if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0) ERR_clear_error(); } - /* Decrypt session key */ - if (!PACKET_get_1(pkt, &asn1id) - || asn1id != (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED) - || !PACKET_peek_1(pkt, &asn1len)) { - SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, - SSL_R_DECRYPTION_FAILED); - goto err; + + ptr = PACKET_data(pkt); + /* Some implementations provide extra data in the opaqueBlob + * We have nothing to do with this blob so we just skip it */ + pKX = d2i_GOST_KX_MESSAGE(NULL, &ptr, PACKET_remaining(pkt)); + if (pKX == NULL + || pKX->kxBlob == NULL + || ASN1_TYPE_get(pKX->kxBlob) != V_ASN1_SEQUENCE) { + SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + SSL_R_DECRYPTION_FAILED); + goto err; } - if (asn1len == 0x81) { - /* - * Long form length. Should only be one byte of length. Anything else - * isn't supported. - * We did a successful peek before so this shouldn't fail - */ - if (!PACKET_forward(pkt, 1)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, - SSL_R_DECRYPTION_FAILED); - goto err; - } - } else if (asn1len >= 0x80) { - /* - * Indefinite length, or more than one long form length bytes. We don't - * support it - */ - SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + + if (!PACKET_forward(pkt, ptr - PACKET_data(pkt))) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, SSL_R_DECRYPTION_FAILED); goto err; - } /* else short form length */ + } - if (!PACKET_as_length_prefixed_1(pkt, &encdata)) { - SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, + if (PACKET_remaining(pkt) != 0) { + SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, SSL_R_DECRYPTION_FAILED); goto err; } - inlen = PACKET_remaining(&encdata); - start = PACKET_data(&encdata); + + inlen = pKX->kxBlob->value.sequence->length; + start = pKX->kxBlob->value.sequence->data; if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start, inlen) <= 0) { @@ -3420,6 +3436,7 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt) ret = 1; err: EVP_PKEY_CTX_free(pkey_ctx); + GOST_KX_MESSAGE_free(pKX); return ret; #else /* Should never happen */ |