From c4eff165160b5e3cc1666521c687831a2869ae87 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= <mpg@elzevir.fr>
Date: Thu, 19 Jun 2014 12:18:08 +0200
Subject: [PATCH] Restore ability to use v1 CA if trusted locally

---
 ChangeLog                              |  2 ++
 library/x509_crt.c                     | 22 ++++++++++-----
 tests/data_files/server1-v1.crt        | 19 +++++++++++++
 tests/data_files/server2-v1-chain.crt  | 38 ++++++++++++++++++++++++++
 tests/data_files/server2-v1.crt        | 19 +++++++++++++
 tests/data_files/test-ca-v1.crt        | 19 +++++++++++++
 tests/suites/test_suite_x509parse.data | 12 ++++++++
 7 files changed, 124 insertions(+), 7 deletions(-)
 create mode 100644 tests/data_files/server1-v1.crt
 create mode 100644 tests/data_files/server2-v1-chain.crt
 create mode 100644 tests/data_files/server2-v1.crt
 create mode 100644 tests/data_files/test-ca-v1.crt

diff --git a/ChangeLog b/ChangeLog
index e554f8d61d..097f0ffd09 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -41,6 +41,8 @@ Bugfix
      rejected with CBC-based ciphersuites and TLS >= 1.1
    * Very large records using less padding could cause a buffer overread of up
      to 32 bytes with CBC-based ciphersuites and TLS >= 1.1
+   * Restore ability to use a v1 cert as a CA if trusted locally. (This had
+     been removed in 1.3.6.)
 
 = PolarSSL 1.3.7 released on 2014-05-02
 Features
diff --git a/library/x509_crt.c b/library/x509_crt.c
index c5f7f70ffd..6f72661301 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1589,17 +1589,25 @@ static int x509_wildcard_verify( const char *cn, x509_buf *name )
  * Return 0 if yes, -1 if not.
  */
 static int x509_crt_check_parent( const x509_crt *child,
-                                  const x509_crt *parent )
+                                  const x509_crt *parent,
+                                  int top )
 {
-    if( parent->version == 0 ||
-        parent->ca_istrue == 0 ||
-        child->issuer_raw.len != parent->subject_raw.len ||
+    /* Parent must be the issuer */
+    if( child->issuer_raw.len != parent->subject_raw.len ||
         memcmp( child->issuer_raw.p, parent->subject_raw.p,
                 child->issuer_raw.len ) != 0 )
     {
         return( -1 );
     }
 
+    /* Parent must have the basicConstraints CA bit set.
+     * Exception: v1/v2 certificates that are locally trusted. */
+    if( parent->ca_istrue == 0 &&
+        ! ( top && parent->version < 3 ) )
+    {
+        return( -1 );
+    }
+
 #if defined(POLARSSL_X509_CHECK_KEY_USAGE)
     if( x509_crt_check_key_usage( parent, KU_KEY_CERT_SIGN ) != 0 )
         return( -1 );
@@ -1643,7 +1651,7 @@ static int x509_crt_verify_top(
 
     for( /* trust_ca */ ; trust_ca != NULL; trust_ca = trust_ca->next )
     {
-        if( x509_crt_check_parent( child, trust_ca ) != 0 )
+        if( x509_crt_check_parent( child, trust_ca, 1 ) != 0 )
             continue;
 
         /*
@@ -1770,7 +1778,7 @@ static int x509_crt_verify_child(
          grandparent != NULL;
          grandparent = grandparent->next )
     {
-        if( x509_crt_check_parent( parent, grandparent ) == 0 )
+        if( x509_crt_check_parent( parent, grandparent, 0 ) == 0 )
             break;
     }
 
@@ -1872,7 +1880,7 @@ int x509_crt_verify( x509_crt *crt,
     /* Look for a parent upwards the chain */
     for( parent = crt->next; parent != NULL; parent = parent->next )
     {
-        if( x509_crt_check_parent( crt, parent ) == 0 )
+        if( x509_crt_check_parent( crt, parent, 0 ) == 0 )
             break;
     }
 
diff --git a/tests/data_files/server1-v1.crt b/tests/data_files/server1-v1.crt
new file mode 100644
index 0000000000..47f1fff1cd
--- /dev/null
+++ b/tests/data_files/server1-v1.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDITCCAgkCDFOitscEzU2OvIALwTANBgkqhkiG9w0BAQsFADBQMRwwGgYDVQQD
+ExNQb2xhclNTTCBUZXN0IENBIHYxMRAwDgYDVQQLEwd0ZXN0aW5nMREwDwYDVQQK
+EwhQb2xhclNTTDELMAkGA1UEBhMCTkwwIhgPMjAxNDA2MTkxMDA5MTFaGA8yMDI0
+MDYxODEwMDkxMVowTjEaMBgGA1UEAxMRc2VydmVyMS9pbnQtY2EtdjExEDAOBgNV
+BAsTB3Rlc3RpbmcxETAPBgNVBAoTCFBvbGFyU1NMMQswCQYDVQQGEwJOTDCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkCHz1AatVVU4v9Nu6CZS4VYV6J
+v7joRZDb7ogWUtPxQ1BHlhJZZIdr/SvgRvlzvt3PkuGRW+1moG+JKXlFgNCDatVB
+Q3dfOXwJBEeCsFc5cO2j7BUZHqgzCEfBBUKp/UzDtN/dBh9NEFFAZ3MTD0D4bYEl
+XwqxU8YwfhU5rPla7n+SnqYFW+cTl4W1I5LZ1CQG1QkliXUH3aYajz8JGb6tZSxk
+65Wb3P5BXhem2mxbacwCuhQsFiScStzN0PdSZ3PxLaAj/X70McotcMqJCwTbLqZP
+cG6ezr1YieJTWZ5uWpJl4og/DJQZo93l6J2VE+0p26twEtxaymsXq1KCVLECAwEA
+ATANBgkqhkiG9w0BAQsFAAOCAQEAPJl3fbVeTJ6gVAvCoLYM8JY5U7ZhrCCdBghw
+WuZBS/TWwf4WLP0G/ZtTyTOENcT0gWHf0/VnXtNPw2/yBjWsLtTXxN2XQlEVf3j/
+WcQxWgSESYdx/sT/uTW6qihuONPWkTQizmx7OG6vBuGx3g54s9/oeJKXOraNqud3
+G4KBrytOazliMfoKO2hnzaeydpaDtb2tZX8apN/6KqQpTAcXsWrZRW9XEHWq2sNz
+IR1nIE1F/9gnqi9Xy0HQprteLRUvM4tEQ35m4H20eS5Y9gJlE/DqXmMQ7aiU8DgP
+krj+Z18pcrssO+Etv0BOiPjmU9TWWpDMj34ef7U/OH5qJxkSrA==
+-----END CERTIFICATE-----
diff --git a/tests/data_files/server2-v1-chain.crt b/tests/data_files/server2-v1-chain.crt
new file mode 100644
index 0000000000..84bb6b2b93
--- /dev/null
+++ b/tests/data_files/server2-v1-chain.crt
@@ -0,0 +1,38 @@
+-----BEGIN CERTIFICATE-----
+MIIDFTCCAf0CDFOittkjXbxFc/m3bDANBgkqhkiG9w0BAQsFADBOMRowGAYDVQQD
+ExFzZXJ2ZXIxL2ludC1jYS12MTEQMA4GA1UECxMHdGVzdGluZzERMA8GA1UEChMI
+UG9sYXJTU0wxCzAJBgNVBAYTAk5MMCIYDzIwMTQwNjE5MTAwOTI5WhgPMjAyNDA2
+MTgxMDA5MjlaMEQxEDAOBgNVBAMTB3NlcnZlcjIxEDAOBgNVBAsTB3Rlc3Rpbmcx
+ETAPBgNVBAoTCFBvbGFyU1NMMQswCQYDVQQGEwJOTDCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTNowCI
+p+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKzNtSj
++uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kMtQCQ
+4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8PhYva
+i0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjyaHT4P
+6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAATANBgkqhkiG9w0B
+AQsFAAOCAQEAivCCMBfC5YNeozwp8vAWpiRUakhtO8ysvCfQsZD4tWLlSkrjoUtG
+3RNd9gDVDGb852GswtNMKHJC1AeZuXdh3eBoDBNTXnR/9UkHgWNBy5f+JH2irYrc
+ps5ofpYJZe7K6xQjl+RLc8nfUUaVfS3dJnyLr9k5kg4in48p+hEF6oXDBu2zdufF
+53k/U98FTvFkVisEDFzLXyKX0fAZxfMk4qnEoBflH4fEXfkuuaBUVdoGGIMRLNAW
+GIyRxr+zj+OJL+ZjjAkY4JqtEuUuLjODn//DHI/MkqE0LANOvbb4akpgZsyvSSO3
+o38d1wQHw5+bO+YDqdfIdQXguU5mtS1xAw==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDITCCAgkCDFOitscEzU2OvIALwTANBgkqhkiG9w0BAQsFADBQMRwwGgYDVQQD
+ExNQb2xhclNTTCBUZXN0IENBIHYxMRAwDgYDVQQLEwd0ZXN0aW5nMREwDwYDVQQK
+EwhQb2xhclNTTDELMAkGA1UEBhMCTkwwIhgPMjAxNDA2MTkxMDA5MTFaGA8yMDI0
+MDYxODEwMDkxMVowTjEaMBgGA1UEAxMRc2VydmVyMS9pbnQtY2EtdjExEDAOBgNV
+BAsTB3Rlc3RpbmcxETAPBgNVBAoTCFBvbGFyU1NMMQswCQYDVQQGEwJOTDCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkCHz1AatVVU4v9Nu6CZS4VYV6J
+v7joRZDb7ogWUtPxQ1BHlhJZZIdr/SvgRvlzvt3PkuGRW+1moG+JKXlFgNCDatVB
+Q3dfOXwJBEeCsFc5cO2j7BUZHqgzCEfBBUKp/UzDtN/dBh9NEFFAZ3MTD0D4bYEl
+XwqxU8YwfhU5rPla7n+SnqYFW+cTl4W1I5LZ1CQG1QkliXUH3aYajz8JGb6tZSxk
+65Wb3P5BXhem2mxbacwCuhQsFiScStzN0PdSZ3PxLaAj/X70McotcMqJCwTbLqZP
+cG6ezr1YieJTWZ5uWpJl4og/DJQZo93l6J2VE+0p26twEtxaymsXq1KCVLECAwEA
+ATANBgkqhkiG9w0BAQsFAAOCAQEAPJl3fbVeTJ6gVAvCoLYM8JY5U7ZhrCCdBghw
+WuZBS/TWwf4WLP0G/ZtTyTOENcT0gWHf0/VnXtNPw2/yBjWsLtTXxN2XQlEVf3j/
+WcQxWgSESYdx/sT/uTW6qihuONPWkTQizmx7OG6vBuGx3g54s9/oeJKXOraNqud3
+G4KBrytOazliMfoKO2hnzaeydpaDtb2tZX8apN/6KqQpTAcXsWrZRW9XEHWq2sNz
+IR1nIE1F/9gnqi9Xy0HQprteLRUvM4tEQ35m4H20eS5Y9gJlE/DqXmMQ7aiU8DgP
+krj+Z18pcrssO+Etv0BOiPjmU9TWWpDMj34ef7U/OH5qJxkSrA==
+-----END CERTIFICATE-----
diff --git a/tests/data_files/server2-v1.crt b/tests/data_files/server2-v1.crt
new file mode 100644
index 0000000000..7ef7968f59
--- /dev/null
+++ b/tests/data_files/server2-v1.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDFTCCAf0CDFOittkjXbxFc/m3bDANBgkqhkiG9w0BAQsFADBOMRowGAYDVQQD
+ExFzZXJ2ZXIxL2ludC1jYS12MTEQMA4GA1UECxMHdGVzdGluZzERMA8GA1UEChMI
+UG9sYXJTU0wxCzAJBgNVBAYTAk5MMCIYDzIwMTQwNjE5MTAwOTI5WhgPMjAyNDA2
+MTgxMDA5MjlaMEQxEDAOBgNVBAMTB3NlcnZlcjIxEDAOBgNVBAsTB3Rlc3Rpbmcx
+ETAPBgNVBAoTCFBvbGFyU1NMMQswCQYDVQQGEwJOTDCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTNowCI
+p+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKzNtSj
++uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kMtQCQ
+4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8PhYva
+i0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjyaHT4P
+6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAATANBgkqhkiG9w0B
+AQsFAAOCAQEAivCCMBfC5YNeozwp8vAWpiRUakhtO8ysvCfQsZD4tWLlSkrjoUtG
+3RNd9gDVDGb852GswtNMKHJC1AeZuXdh3eBoDBNTXnR/9UkHgWNBy5f+JH2irYrc
+ps5ofpYJZe7K6xQjl+RLc8nfUUaVfS3dJnyLr9k5kg4in48p+hEF6oXDBu2zdufF
+53k/U98FTvFkVisEDFzLXyKX0fAZxfMk4qnEoBflH4fEXfkuuaBUVdoGGIMRLNAW
+GIyRxr+zj+OJL+ZjjAkY4JqtEuUuLjODn//DHI/MkqE0LANOvbb4akpgZsyvSSO3
+o38d1wQHw5+bO+YDqdfIdQXguU5mtS1xAw==
+-----END CERTIFICATE-----
diff --git a/tests/data_files/test-ca-v1.crt b/tests/data_files/test-ca-v1.crt
new file mode 100644
index 0000000000..e5a3b1cde4
--- /dev/null
+++ b/tests/data_files/test-ca-v1.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDIzCCAgsCDFOito4FQA5VXJOV5TANBgkqhkiG9w0BAQsFADBQMRwwGgYDVQQD
+ExNQb2xhclNTTCBUZXN0IENBIHYxMRAwDgYDVQQLEwd0ZXN0aW5nMREwDwYDVQQK
+EwhQb2xhclNTTDELMAkGA1UEBhMCTkwwIhgPMjAxNDA2MTkxMDA4MTRaGA8yMDI0
+MDYxODEwMDgxNFowUDEcMBoGA1UEAxMTUG9sYXJTU0wgVGVzdCBDQSB2MTEQMA4G
+A1UECxMHdGVzdGluZzERMA8GA1UEChMIUG9sYXJTU0wxCzAJBgNVBAYTAk5MMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwN83/Be74JadP4beljJ9RKUW
+oM0h8ZnU7OrLfBhYCJSl7JvFi98aHpk4mYcee8CNOd84XXB4B9Oe2ZPouXJRxc6j
+MFKp8udAcBTLRKJyC8LlQPk+5aYOs/nsSmPAuCkAdJxXO6ilBJBx8b2D2T/WpeI8
+Ko/vJ2DDxp/LuuxgfbfmhDK+T/tYJiIDW9S01fv145YucMDkLr38Lu7iQVXANC59
+JHJpy0exFECDfWf0hvYxq/F5pLK1LhL5hBfwYm8nPhNYsVQNIZpzN6Ewz2+S3Pbp
+/KzbLijRfgJLI6AV8jhlZAnqDG6OGxegccizm8mr6cPyz4eWj4ACMp6ZWG+i1QID
+AQABMA0GCSqGSIb3DQEBCwUAA4IBAQBoXC5AlXI5azyOPvmNse2qHhO7BrXOEjH+
+9g5P/VsrVADhsUGv6x0A2oLoWXtOjGDIWWH53BWHkCUCu4T5D5C6+I47rXWl4pAr
+J+h+tQVZo6J0AJxfPse/NnrjsboUSWhunmo/iTrU6S4KJBguIKP6T1DZoD/8EYgU
+x+fXDmvRO+MTesWDiY+p+FHEzsu3b9EBtG9dUiR/zzXi/ktFCfrgstKGSuW6+j7m
+lcduTxsogi6Uc3tWKtn6qpSGR0uBoCz6emFO7Smmy/tIyVA88lH0+3UnxOvu4TAK
+uvjYkOcZqhprDiMfhxBB7pxbfiviEANTbgSfCtZewSNz2RUJ9ocy
+-----END CERTIFICATE-----
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index 54ef202bf1..12019b0dc3 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -622,6 +622,18 @@ X509 Certificate verification #69 (RSASSA-PSS, wrong mgf_hash)
 depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_X509_RSASSA_PSS_SUPPORT:POLARSSL_SHA256_C
 x509_verify:"data_files/server9-bad-mgfhash.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_NOT_TRUSTED:"NULL"
 
+X509 Certificate verification #70 (v1 trusted CA)
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15:POLARSSL_SHA256_C
+x509_verify:"data_files/server1-v1.crt":"data_files/test-ca-v1.crt":"data_files/crl.pem":"NULL":0:0:"NULL"
+
+X509 Certificate verification #71 (v1 trusted CA, other)
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15:POLARSSL_SHA256_C
+x509_verify:"data_files/server2-v1.crt":"data_files/server1-v1.crt":"data_files/crl.pem":"NULL":0:0:"NULL"
+
+X509 Certificate verification #72 (v1 chain)
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15:POLARSSL_SHA256_C
+x509_verify:"data_files/server2-v1-chain.crt":"data_files/test-ca-v1.crt":"data_files/crl.pem":"NULL":POLARSSL_ERR_X509_CERT_VERIFY_FAILED:BADCERT_NOT_TRUSTED:"NULL"
+
 X509 Parse Selftest
 depends_on:POLARSSL_SHA1_C:POLARSSL_PEM_PARSE_C:POLARSSL_CERTS_C
 x509_selftest: