Merge remote-tracking branch 'restricted/IOTSSL-1366/mbedtls-1.3' into mbedtls-1.3-restricted
* restricted/IOTSSL-1366/mbedtls-1.3:
More length checks in RSA PKCS1v15 verify
More length checks in RSA PKCS1v15 verify
diff --git a/ChangeLog b/ChangeLog
index 8449329..944d695 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -8,6 +8,8 @@
https://arxiv.org/abs/1702.08719v2.
Found and fix proposed by Michael Schwarz, Samuel Weiser, Daniel Gruss,
Clémentine Maurice and Stefan Mangard.
+ * Tighten ASN.1 parsing of RSA PKCS#1 v1.5 signatures, to avoid a
+ potential Bleichenbacher-style attack.
Bugfix
* Fix insufficient support for signature-hash-algorithm extension,
diff --git a/library/rsa.c b/library/rsa.c
index 1cdf0d6..999c8b9 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -1472,7 +1472,7 @@
{
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;
@@ -1523,24 +1523,30 @@
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( asn1_len + 2 != len )
+ 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( 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 + 2 )
+ return( POLARSSL_ERR_RSA_VERIFY_FAILED );
oid.p = p;
p += oid.len;
@@ -1554,13 +1560,16 @@
/*
* 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( ( ret = asn1_get_tag( &p, end, &asn1_len, ASN1_OCTET_STRING ) ) != 0 )
+ if( p != p0 + 2 )
return( POLARSSL_ERR_RSA_VERIFY_FAILED );
- if( asn1_len != hashlen )
+ 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 );
if( memcmp( p, hash, hashlen ) != 0 )