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 2.1.x
diff --git a/library/rsa.c b/library/rsa.c
index e831875..520f1a2 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -1343,7 +1343,7 @@
{
int ret;
size_t len, siglen, asn1_len;
- unsigned char *p, *end;
+ unsigned char *p, *p0, *end;
unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
mbedtls_md_type_t msg_md_alg;
const mbedtls_md_info_t *md_info;
@@ -1396,23 +1396,27 @@
// Parse the ASN.1 structure inside the PKCS#1 v1.5 structure
//
+ p0 = p;
if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
- if( asn1_len + 2 != len )
+ if( p != p0 + 2 || asn1_len + 2 != len )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
- if( asn1_len + 6 + hashlen != len )
+ if( p != p0 + 4 || asn1_len + 6 + hashlen != len )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
if( ( ret = mbedtls_asn1_get_tag( &p, end, &oid.len, MBEDTLS_ASN1_OID ) ) != 0 )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
+ if( p != p0 + 6 )
+ return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
+
oid.p = p;
p += oid.len;
@@ -1428,10 +1432,11 @@
if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_NULL ) ) != 0 )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
+ p0 = p;
if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
- if( asn1_len != hashlen )
+ if( p != p0 + 2 || asn1_len != hashlen )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
if( memcmp( p, hash, hashlen ) != 0 )