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 )