diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c index c0c406d921..876b6a79e3 100644 --- a/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c @@ -3233,11 +3233,9 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt) const unsigned char *start; size_t outlen = 32, inlen; unsigned long alg_a; - int Ttag, Tclass; - long Tlen; - size_t sess_key_len; - const unsigned char *data; + unsigned int asn1id, asn1len; int ret = 0; + PACKET encdata; /* Get our certificate private key */ alg_a = s->s3->tmp.new_cipher->algorithm_auth; @@ -3279,22 +3277,42 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt) ERR_clear_error(); } /* Decrypt session key */ - sess_key_len = PACKET_remaining(pkt); - if (!PACKET_get_bytes(pkt, &data, sess_key_len)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST, - ERR_R_INTERNAL_ERROR); - goto err; - } - /* TODO(size_t): Convert this function */ - if (ASN1_get_object((const unsigned char **)&data, &Tlen, &Ttag, - &Tclass, (long)sess_key_len) != V_ASN1_CONSTRUCTED - || Ttag != V_ASN1_SEQUENCE || Tclass != V_ASN1_UNIVERSAL) { + 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; } - start = data; - inlen = Tlen; + 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, + 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, + SSL_R_DECRYPTION_FAILED); + goto err; + } + inlen = PACKET_remaining(&encdata); + start = PACKET_data(&encdata); + if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start, inlen) <= 0) { SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,