Restore ability to trust non-CA selfsigned EE cert
diff --git a/ChangeLog b/ChangeLog
index 097f0ff..886fe11 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -43,6 +43,9 @@
      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.)
+   * Restore ability to locally trust a self-signed cert that is not a proper
+     CA for use as an end entity certificate. (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 6f72661..03cdda8 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -1587,11 +1587,16 @@
 /*
  * Check if 'parent' is a suitable parent (signing CA) for 'child'.
  * Return 0 if yes, -1 if not.
+ *
+ * top means parent is a locally-trusted certificate
+ * bottom means child is the end entity cert
  */
 static int x509_crt_check_parent( const x509_crt *child,
                                   const x509_crt *parent,
-                                  int top )
+                                  int top, int bottom )
 {
+    int need_ca_bit;
+
     /* Parent must be the issuer */
     if( child->issuer_raw.len != parent->subject_raw.len ||
         memcmp( child->issuer_raw.p, parent->subject_raw.p,
@@ -1600,17 +1605,30 @@
         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 ) )
+    /* Parent must have the basicConstraints CA bit set as a general rule */
+    need_ca_bit = 1;
+
+    /* Exception: v1/v2 certificates that are locally trusted. */
+    if( top && parent->version < 3 )
+        need_ca_bit = 0;
+
+    /* Exception: self-signed end-entity certs that are locally trusted. */
+    if( top && bottom &&
+        child->raw.len == parent->raw.len &&
+        memcmp( child->raw.p, parent->raw.p, child->raw.len ) == 0 )
+    {
+        need_ca_bit = 0;
+    }
+
+    if( need_ca_bit && ! parent->ca_istrue )
+        return( -1 );
+
+#if defined(POLARSSL_X509_CHECK_KEY_USAGE)
+    if( need_ca_bit &&
+        x509_crt_check_key_usage( parent, KU_KEY_CERT_SIGN ) != 0 )
     {
         return( -1 );
     }
-
-#if defined(POLARSSL_X509_CHECK_KEY_USAGE)
-    if( x509_crt_check_key_usage( parent, KU_KEY_CERT_SIGN ) != 0 )
-        return( -1 );
 #endif
 
     return( 0 );
@@ -1651,7 +1669,7 @@
 
     for( /* trust_ca */ ; trust_ca != NULL; trust_ca = trust_ca->next )
     {
-        if( x509_crt_check_parent( child, trust_ca, 1 ) != 0 )
+        if( x509_crt_check_parent( child, trust_ca, 1, path_cnt == 0 ) != 0 )
             continue;
 
         /*
@@ -1778,7 +1796,8 @@
          grandparent != NULL;
          grandparent = grandparent->next )
     {
-        if( x509_crt_check_parent( parent, grandparent, 0 ) == 0 )
+        if( x509_crt_check_parent( parent, grandparent,
+                                   0, path_cnt == 0 ) == 0 )
             break;
     }
 
@@ -1880,7 +1899,7 @@
     /* Look for a parent upwards the chain */
     for( parent = crt->next; parent != NULL; parent = parent->next )
     {
-        if( x509_crt_check_parent( crt, parent, 0 ) == 0 )
+        if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 )
             break;
     }
 
diff --git a/tests/data_files/server5-selfsigned.crt b/tests/data_files/server5-selfsigned.crt
new file mode 100644
index 0000000..cb55647
--- /dev/null
+++ b/tests/data_files/server5-selfsigned.crt
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE-----
+MIIBzTCCAXKgAwIBAgIMU6LLSxJOrYN9qJSyMAoGCCqGSM49BAMCMEcxEzARBgNV
+BAMTCnNlbGZzaWduZWQxEDAOBgNVBAsTB3Rlc3RpbmcxETAPBgNVBAoTCFBvbGFy
+U1NMMQswCQYDVQQGEwJOTDAiGA8yMDE0MDYxOTExMzY0M1oYDzIwMjQwNjE4MTEz
+NjQzWjBHMRMwEQYDVQQDEwpzZWxmc2lnbmVkMRAwDgYDVQQLEwd0ZXN0aW5nMREw
+DwYDVQQKEwhQb2xhclNTTDELMAkGA1UEBhMCTkwwWTATBgcqhkjOPQIBBggqhkjO
+PQMBBwNCAAQ3zFbZdgkeWnI+x1kt/yBu7nz5BpF00K0UtfdoIllikk7lANgjEf/q
+L9I0XV0WvYqIwmt3DVXNiioO+gHItO3/o0AwPjAMBgNVHRMBAf8EAjAAMA8GA1Ud
+DwEB/wQFAwMHgAAwHQYDVR0OBBYEFLZtURgXjmWq8uzV8wHkbFLCNB1bMAoGCCqG
+SM49BAMCA0kAMEYCIQCf/bzFoge0pCOIrtHrABgc1+Cl9kjlsICpduXhdHUMOwIh
+AOJ+nBHfaEGyF4PRJvn/jMDeIaH1zisinVzC2v+JQOWq
+-----END CERTIFICATE-----
diff --git a/tests/data_files/server6-ss-child.crt b/tests/data_files/server6-ss-child.crt
new file mode 100644
index 0000000..3c6fd4d
--- /dev/null
+++ b/tests/data_files/server6-ss-child.crt
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB8jCCAZmgAwIBAgIMU6LLWCI5lHSn7HnsMAoGCCqGSM49BAMCMEcxEzARBgNV
+BAMTCnNlbGZzaWduZWQxEDAOBgNVBAsTB3Rlc3RpbmcxETAPBgNVBAoTCFBvbGFy
+U1NMMQswCQYDVQQGEwJOTDAiGA8yMDE0MDYxOTExMzY1NloYDzIwMjQwNjE4MTEz
+NjU2WjBNMRkwFwYDVQQDExBzZWxmc2lnbmVkLWNoaWxkMRAwDgYDVQQLEwd0ZXN0
+aW5nMREwDwYDVQQKEwhQb2xhclNTTDELMAkGA1UEBhMCTkwwWTATBgcqhkjOPQIB
+BggqhkjOPQMBBwNCAASBWTF2SST6Fa2roDFuDu0zEfqRJVXBsMGcA3I+mLotpHI3
+iR9DN40fjjrY8FfoL0/JAKT323MPssYElNFAOzjjo2EwXzAMBgNVHRMBAf8EAjAA
+MA8GA1UdDwEB/wQFAwMHgAAwHQYDVR0OBBYEFDxZrEo+LvwCNi/afcvLnHqyiZlT
+MB8GA1UdIwQYMBaAFLZtURgXjmWq8uzV8wHkbFLCNB1bMAoGCCqGSM49BAMCA0cA
+MEQCIAMlQ59/NW7S0hP1cu5OTD2zqT087bEmnIfOTBYfj8UFAiBBrrz2dipODVYx
+vvTsQmSCzjrm+JtQQoWa+cdnAG3w5g==
+-----END CERTIFICATE-----
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index 12019b0..a22741e 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -634,6 +634,14 @@
 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 Certificate verification #73 (selfsigned trusted without CA bit)
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECDSA_C:POLARSSL_SHA256_C
+x509_verify:"data_files/server5-selfsigned.crt":"data_files/server5-selfsigned.crt":"data_files/crl.pem":"NULL":0:0:"NULL"
+
+X509 Certificate verification #74 (signed by selfsigned trusted without CA bit)
+depends_on:POLARSSL_PEM_PARSE_C:POLARSSL_ECDSA_C:POLARSSL_SHA256_C
+x509_verify:"data_files/server6-ss-child.crt":"data_files/server5-selfsigned.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: