From 6de05fa058fa77122db63aa48b7a5ead9efb41b6 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 3 May 2017 18:32:21 +0200 Subject: [PATCH 1/2] More length checks in RSA PKCS1v15 verify Tighten ASN.1 parsing of RSA PKCS#1 v1.5 signatures, to avoid a potential Bleichenbacher-style attack. Backport to 1.3 --- ChangeLog | 6 ++++++ library/rsa.c | 13 +++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 509908177..f71e75082 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ mbed TLS ChangeLog (Sorted per branch, date) += mbed TLS 1.3.xx branch released xxxx-xx-xx + +Security + * Tighten ASN.1 parsing of RSA PKCS#1 v1.5 signatures, to avoid a + potential Bleichenbacher-style attack. + = mbed TLS 1.3.19 branch released 2017-03-08 Security diff --git a/library/rsa.c b/library/rsa.c index 79726c1b5..253adf565 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -1344,7 +1344,7 @@ int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx, { int ret; size_t len, siglen, asn1_len; - unsigned char *p, *end; + unsigned char *p, *p0, *end; unsigned char buf[POLARSSL_MPI_MAX_SIZE]; md_type_t msg_md_alg; const md_info_t *md_info; @@ -1397,23 +1397,27 @@ int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx, // Parse the ASN.1 structure inside the PKCS#1 v1.5 structure // + p0 = p; if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - if( asn1_len + 2 != len ) + if( p != p0 + 2 || asn1_len + 2 != len ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - if( asn1_len + 6 + hashlen != len ) + if( p != p0 + 4 || asn1_len + 6 + hashlen != len ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( ( ret = asn1_get_tag( &p, end, &oid.len, ASN1_OID ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + if( p != p0 + 6 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + oid.p = p; p += oid.len; @@ -1429,10 +1433,11 @@ int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx, if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_NULL ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + p0 = p; if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_OCTET_STRING ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - if( asn1_len != hashlen ) + if( p != p0 + 2 || asn1_len != hashlen ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); if( memcmp( p, hash, hashlen ) != 0 ) From 6e598a2065a6a69d002fe6b037445434862f5e07 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Thu, 4 May 2017 12:48:39 +0200 Subject: [PATCH 2/2] More length checks in RSA PKCS1v15 verify Added one check that I'd missed, and made the style more uniform. Backport to 1.3. --- library/rsa.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/library/rsa.c b/library/rsa.c index 253adf565..129d126cd 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -1395,27 +1395,29 @@ int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx, end = p + len; - // Parse the ASN.1 structure inside the PKCS#1 v1.5 structure - // + /* + * Parse the ASN.1 structure inside the PKCS#1 v1.5 structure. + * Insist on 2-byte length tags, to protect against variants of + * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification. + */ p0 = p; if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - if( p != p0 + 2 || asn1_len + 2 != len ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + p0 = p; if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - - if( p != p0 + 4 || asn1_len + 6 + hashlen != len ) + if( p != p0 + 2 || asn1_len + 6 + hashlen != len ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + p0 = p; if( ( ret = asn1_get_tag( &p, end, &oid.len, ASN1_OID ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - - if( p != p0 + 6 ) + if( p != p0 + 2 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); oid.p = p; @@ -1430,13 +1432,15 @@ int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx, /* * assume the algorithm parameters must be NULL */ + p0 = p; if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_NULL ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); + if( p != p0 + 2 ) + return( POLARSSL_ERR_RSA_VERIFY_FAILED ); p0 = p; if( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_OCTET_STRING ) ) != 0 ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - if( p != p0 + 2 || asn1_len != hashlen ) return( POLARSSL_ERR_RSA_VERIFY_FAILED );