File openssl-1_1-CVE-2021-3449-NULL_pointer_deref_in_signature_algorithms.patch of Package openssl-1_1.20905
Index: openssl-1.1.1d/ssl/s3_lib.c
===================================================================
--- openssl-1.1.1d.orig/ssl/s3_lib.c
+++ openssl-1.1.1d/ssl/s3_lib.c
@@ -4638,6 +4638,7 @@ int ssl_generate_master_secret(SSL *s, u
OPENSSL_clear_free(s->s3->tmp.psk, psklen);
s->s3->tmp.psk = NULL;
+ s->s3->tmp.psklen = 0;
if (!s->method->ssl3_enc->generate_master_secret(s,
s->session->master_key,pskpms, pskpmslen,
&s->session->master_key_length)) {
@@ -4667,8 +4668,10 @@ int ssl_generate_master_secret(SSL *s, u
else
OPENSSL_cleanse(pms, pmslen);
}
- if (s->server == 0)
+ if (s->server == 0) {
s->s3->tmp.pms = NULL;
+ s->s3->tmp.pmslen = 0;
+ }
return ret;
}
Index: openssl-1.1.1d/ssl/ssl_lib.c
===================================================================
--- openssl-1.1.1d.orig/ssl/ssl_lib.c
+++ openssl-1.1.1d/ssl/ssl_lib.c
@@ -779,8 +779,10 @@ SSL *SSL_new(SSL_CTX *ctx)
s->ext.ecpointformats =
OPENSSL_memdup(ctx->ext.ecpointformats,
ctx->ext.ecpointformats_len);
- if (!s->ext.ecpointformats)
+ if (!s->ext.ecpointformats) {
+ s->ext.ecpointformats_len = 0;
goto err;
+ }
s->ext.ecpointformats_len =
ctx->ext.ecpointformats_len;
}
@@ -789,8 +791,10 @@ SSL *SSL_new(SSL_CTX *ctx)
OPENSSL_memdup(ctx->ext.supportedgroups,
ctx->ext.supportedgroups_len
* sizeof(*ctx->ext.supportedgroups));
- if (!s->ext.supportedgroups)
+ if (!s->ext.supportedgroups) {
+ s->ext.supportedgroups_len = 0;
goto err;
+ }
s->ext.supportedgroups_len = ctx->ext.supportedgroups_len;
}
#endif
@@ -800,8 +804,10 @@ SSL *SSL_new(SSL_CTX *ctx)
if (s->ctx->ext.alpn) {
s->ext.alpn = OPENSSL_malloc(s->ctx->ext.alpn_len);
- if (s->ext.alpn == NULL)
+ if (s->ext.alpn == NULL) {
+ s->ext.alpn_len = 0;
goto err;
+ }
memcpy(s->ext.alpn, s->ctx->ext.alpn, s->ctx->ext.alpn_len);
s->ext.alpn_len = s->ctx->ext.alpn_len;
}
@@ -2778,6 +2784,7 @@ int SSL_CTX_set_alpn_protos(SSL_CTX *ctx
OPENSSL_free(ctx->ext.alpn);
ctx->ext.alpn = OPENSSL_memdup(protos, protos_len);
if (ctx->ext.alpn == NULL) {
+ ctx->ext.alpn_len = 0;
SSLerr(SSL_F_SSL_CTX_SET_ALPN_PROTOS, ERR_R_MALLOC_FAILURE);
return 1;
}
@@ -2797,6 +2804,7 @@ int SSL_set_alpn_protos(SSL *ssl, const
OPENSSL_free(ssl->ext.alpn);
ssl->ext.alpn = OPENSSL_memdup(protos, protos_len);
if (ssl->ext.alpn == NULL) {
+ ssl->ext.alpn_len = 0;
SSLerr(SSL_F_SSL_SET_ALPN_PROTOS, ERR_R_MALLOC_FAILURE);
return 1;
}
Index: openssl-1.1.1d/ssl/statem/extensions.c
===================================================================
--- openssl-1.1.1d.orig/ssl/statem/extensions.c
+++ openssl-1.1.1d/ssl/statem/extensions.c
@@ -1136,6 +1136,7 @@ static int init_sig_algs(SSL *s, unsigne
/* Clear any signature algorithms extension received */
OPENSSL_free(s->s3->tmp.peer_sigalgs);
s->s3->tmp.peer_sigalgs = NULL;
+ s->s3->tmp.peer_sigalgslen = 0;
return 1;
}
@@ -1145,6 +1146,7 @@ static int init_sig_algs_cert(SSL *s, un
/* Clear any signature algorithms extension received */
OPENSSL_free(s->s3->tmp.peer_cert_sigalgs);
s->s3->tmp.peer_cert_sigalgs = NULL;
+ s->s3->tmp.peer_cert_sigalgslen = 0;
return 1;
}
Index: openssl-1.1.1d/ssl/statem/extensions_clnt.c
===================================================================
--- openssl-1.1.1d.orig/ssl/statem/extensions_clnt.c
+++ openssl-1.1.1d/ssl/statem/extensions_clnt.c
@@ -816,6 +816,7 @@ EXT_RETURN tls_construct_ctos_early_data
OPENSSL_free(s->psksession_id);
s->psksession_id = OPENSSL_memdup(id, idlen);
if (s->psksession_id == NULL) {
+ s->psksession_id_len = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
@@ -1375,6 +1376,7 @@ int tls_parse_stoc_ec_pt_formats(SSL *s,
OPENSSL_free(s->ext.peer_ecpointformats);
s->ext.peer_ecpointformats = OPENSSL_malloc(ecpointformats_len);
if (s->ext.peer_ecpointformats == NULL) {
+ s->ext.peer_ecpointformats_len = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
return 0;
@@ -1492,8 +1494,13 @@ int tls_parse_stoc_sct(SSL *s, PACKET *p
s->ext.scts_len = (uint16_t)size;
if (size > 0) {
s->ext.scts = OPENSSL_malloc(size);
- if (s->ext.scts == NULL
- || !PACKET_copy_bytes(pkt, s->ext.scts, size)) {
+ if (s->ext.scts == NULL) {
+ s->ext.scts_len = 0;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SCT,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (!PACKET_copy_bytes(pkt, s->ext.scts, size)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SCT,
ERR_R_INTERNAL_ERROR);
return 0;
@@ -1592,6 +1599,7 @@ int tls_parse_stoc_npn(SSL *s, PACKET *p
OPENSSL_free(s->ext.npn);
s->ext.npn = OPENSSL_malloc(selected_len);
if (s->ext.npn == NULL) {
+ s->ext.npn_len = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_NPN,
ERR_R_INTERNAL_ERROR);
return 0;
@@ -1632,6 +1640,7 @@ int tls_parse_stoc_alpn(SSL *s, PACKET *
OPENSSL_free(s->s3->alpn_selected);
s->s3->alpn_selected = OPENSSL_malloc(len);
if (s->s3->alpn_selected == NULL) {
+ s->s3->alpn_selected_len = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
ERR_R_INTERNAL_ERROR);
return 0;
@@ -1663,6 +1672,7 @@ int tls_parse_stoc_alpn(SSL *s, PACKET *
s->session->ext.alpn_selected =
OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len);
if (s->session->ext.alpn_selected == NULL) {
+ s->session->ext.alpn_selected_len = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
ERR_R_INTERNAL_ERROR);
return 0;
Index: openssl-1.1.1d/ssl/statem/statem_clnt.c
===================================================================
--- openssl-1.1.1d.orig/ssl/statem/statem_clnt.c
+++ openssl-1.1.1d/ssl/statem/statem_clnt.c
@@ -2461,6 +2461,7 @@ MSG_PROCESS_RETURN tls_process_certifica
s->s3->tmp.ctype_len = 0;
OPENSSL_free(s->pha_context);
s->pha_context = NULL;
+ s->pha_context_len = 0;
if (!PACKET_get_length_prefixed_1(pkt, &reqctx) ||
!PACKET_memdup(&reqctx, &s->pha_context, &s->pha_context_len)) {
@@ -2770,16 +2771,17 @@ int tls_process_cert_status_body(SSL *s,
}
s->ext.ocsp.resp = OPENSSL_malloc(resplen);
if (s->ext.ocsp.resp == NULL) {
+ s->ext.ocsp.resp_len = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
ERR_R_MALLOC_FAILURE);
return 0;
}
+ s->ext.ocsp.resp_len = resplen;
if (!PACKET_copy_bytes(pkt, s->ext.ocsp.resp, resplen)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
SSL_R_LENGTH_MISMATCH);
return 0;
}
- s->ext.ocsp.resp_len = resplen;
return 1;
}
@@ -3349,9 +3351,11 @@ int tls_construct_client_key_exchange(SS
err:
OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
s->s3->tmp.pms = NULL;
+ s->s3->tmp.pmslen = 0;
#ifndef OPENSSL_NO_PSK
OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
s->s3->tmp.psk = NULL;
+ s->s3->tmp.psklen = 0;
#endif
return 0;
}
@@ -3426,6 +3430,7 @@ int tls_client_key_exchange_post_work(SS
err:
OPENSSL_clear_free(pms, pmslen);
s->s3->tmp.pms = NULL;
+ s->s3->tmp.pmslen = 0;
return 0;
}
Index: openssl-1.1.1d/ssl/statem/statem_srvr.c
===================================================================
--- openssl-1.1.1d.orig/ssl/statem/statem_srvr.c
+++ openssl-1.1.1d/ssl/statem/statem_srvr.c
@@ -2153,6 +2153,7 @@ int tls_handle_alpn(SSL *s)
OPENSSL_free(s->s3->alpn_selected);
s->s3->alpn_selected = OPENSSL_memdup(selected, selected_len);
if (s->s3->alpn_selected == NULL) {
+ s->s3->alpn_selected_len = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_HANDLE_ALPN,
ERR_R_INTERNAL_ERROR);
return 0;
@@ -2828,9 +2829,16 @@ int tls_construct_certificate_request(SS
if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
OPENSSL_free(s->pha_context);
s->pha_context_len = 32;
- if ((s->pha_context = OPENSSL_malloc(s->pha_context_len)) == NULL
- || RAND_bytes(s->pha_context, s->pha_context_len) <= 0
- || !WPACKET_sub_memcpy_u8(pkt, s->pha_context, s->pha_context_len)) {
+ if ((s->pha_context = OPENSSL_malloc(s->pha_context_len)) == NULL) {
+ s->pha_context_len = 0;
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ if (RAND_bytes(s->pha_context, s->pha_context_len) <= 0
+ || !WPACKET_sub_memcpy_u8(pkt, s->pha_context,
+ s->pha_context_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
ERR_R_INTERNAL_ERROR);
@@ -2944,6 +2952,7 @@ static int tls_process_cke_psk_preamble(
OPENSSL_cleanse(psk, psklen);
if (s->s3->tmp.psk == NULL) {
+ s->s3->tmp.psklen = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_MALLOC_FAILURE);
return 0;
@@ -3491,6 +3500,7 @@ MSG_PROCESS_RETURN tls_process_client_ke
#ifndef OPENSSL_NO_PSK
OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
s->s3->tmp.psk = NULL;
+ s->s3->tmp.psklen = 0;
#endif
return MSG_PROCESS_ERROR;
}
@@ -4100,6 +4110,7 @@ int tls_construct_new_session_ticket(SSL
s->session->ext.alpn_selected =
OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len);
if (s->session->ext.alpn_selected == NULL) {
+ s->session->ext.alpn_selected_len = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
ERR_R_MALLOC_FAILURE);
Index: openssl-1.1.1d/test/recipes/70-test_renegotiation.t
===================================================================
--- openssl-1.1.1d.orig/test/recipes/70-test_renegotiation.t
+++ openssl-1.1.1d/test/recipes/70-test_renegotiation.t
@@ -38,7 +38,7 @@ my $proxy = TLSProxy::Proxy->new(
$proxy->clientflags("-no_tls1_3");
$proxy->reneg(1);
$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
-plan tests => 3;
+plan tests => 4;
ok(TLSProxy::Message->success(), "Basic renegotiation");
#Test 2: Client does not send the Reneg SCSV. Reneg should fail
@@ -77,6 +77,20 @@ SKIP: {
"Check ClientHello version is the same");
}
+SKIP: {
+ skip "TLSv1.2 disabled", 1
+ if disabled("tls1_2");
+
+ #Test 4: Test for CVE-2021-3449. client_sig_algs instead of sig_algs in
+ # resumption ClientHello
+ $proxy->clear();
+ $proxy->filter(\&sigalgs_filter);
+ $proxy->clientflags("-tls1_2");
+ $proxy->reneg(1);
+ $proxy->start();
+ ok(TLSProxy::Message->fail(), "client_sig_algs instead of sig_algs");
+}
+
sub reneg_filter
{
my $proxy = shift;
@@ -95,4 +109,24 @@ sub reneg_filter
$message->repack();
}
}
+}
+
+sub sigalgs_filter
+{
+ my $proxy = shift;
+ my $cnt = 0;
+
+ # We're only interested in the second ClientHello message
+ foreach my $message (@{$proxy->message_list}) {
+ if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO) {
+ next if ($cnt++ == 0);
+
+ my $sigs = pack "C10", 0x00, 0x08,
+ # rsa_pkcs_sha{256,384,512,1}
+ 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x02, 0x01;
+ $message->set_extension(TLSProxy::Message::EXT_SIG_ALGS_CERT, $sigs);
+ $message->delete_extension(TLSProxy::Message::EXT_SIG_ALGS);
+ $message->repack();
+ }
+ }
}
Index: openssl-1.1.1d/util/perl/TLSProxy/Message.pm
===================================================================
--- openssl-1.1.1d.orig/util/perl/TLSProxy/Message.pm
+++ openssl-1.1.1d/util/perl/TLSProxy/Message.pm
@@ -448,7 +448,7 @@ sub ciphersuite
}
#Update all the underlying records with the modified data from this message
-#Note: Only supports re-encrypting for TLSv1.3
+#Note: Only supports TLSv1.3 and ETM encryption
sub repack
{
my $self = shift;
@@ -490,15 +490,38 @@ sub repack
# (If a length override is ever needed to construct invalid packets,
# use an explicit override field instead.)
$rec->decrypt_len(length($rec->decrypt_data));
- $rec->len($rec->len + length($msgdata) - $old_length);
- # Only support re-encryption for TLSv1.3.
- if (TLSProxy::Proxy->is_tls13() && $rec->encrypted()) {
- #Add content type (1 byte) and 16 tag bytes
- $rec->data($rec->decrypt_data
- .pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16));
+ # Only support re-encryption for TLSv1.3 and ETM.
+ if ($rec->encrypted()) {
+ if (TLSProxy::Proxy->is_tls13()) {
+ #Add content type (1 byte) and 16 tag bytes
+ $rec->data($rec->decrypt_data
+ .pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16));
+ } elsif ($rec->etm()) {
+ my $data = $rec->decrypt_data;
+ #Add padding
+ my $padval = length($data) % 16;
+ $padval = 15 - $padval;
+ for (0..$padval) {
+ $data .= pack("C", $padval);
+ }
+
+ #Add MAC. Assumed to be 20 bytes
+ foreach my $macval (0..19) {
+ $data .= pack("C", $macval);
+ }
+
+ if ($rec->version() >= TLSProxy::Record::VERS_TLS_1_1) {
+ #Explicit IV
+ $data = ("\0"x16).$data;
+ }
+ $rec->data($data);
+ } else {
+ die "Unsupported encryption: No ETM";
+ }
} else {
$rec->data($rec->decrypt_data);
}
+ $rec->len(length($rec->data));
#Update the fragment len in case we changed it above
${$self->message_frag_lens}[0] = length($msgdata)