summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrsleevi <rsleevi@chromium.org>2015-11-13 13:14:37 -0800
committerCommit bot <commit-bot@chromium.org>2015-11-13 21:15:50 +0000
commit22241d9e94fbab2e6f111c8c994464ddc485b560 (patch)
tree5b358fa9511532e590e07dd34d5b70f6dcac9f49
parentadce66abd74fb2d6e22da36eee85b7e324f962ba (diff)
downloadchromium_src-22241d9e94fbab2e6f111c8c994464ddc485b560.zip
chromium_src-22241d9e94fbab2e6f111c8c994464ddc485b560.tar.gz
chromium_src-22241d9e94fbab2e6f111c8c994464ddc485b560.tar.bz2
Don't trust SHA-1 from publicly trusted CAs on/after 2016-1-1
The Baseline Requirements forbid any CAs from issuing new SHA-1 certificates after January 1, 2016. As such, reject any such certificates with a notBefore validity period on or later than that date, and which were issued by publicly trusted CAs. No user should ever see this error, and if they do, it's either a bug (which tests should cover) or because a CA is violating the Baseline Requirements and putting the Internet at risk. Enterprise-installed CAs are left untouched until the 2017-1-1 hard disabling of SHA-1. BUG=555395 Review URL: https://codereview.chromium.org/1441993002 Cr-Commit-Position: refs/heads/master@{#359641}
-rw-r--r--net/cert/cert_verify_proc.cc28
-rw-r--r--net/cert/cert_verify_proc_android.cc2
-rw-r--r--net/cert/cert_verify_proc_mac.cc5
-rw-r--r--net/cert/cert_verify_proc_nss.cc4
-rw-r--r--net/cert/cert_verify_proc_openssl.cc2
-rw-r--r--net/cert/cert_verify_proc_unittest.cc157
-rw-r--r--net/cert/cert_verify_proc_win.cc6
-rw-r--r--net/cert/cert_verify_result.cc1
-rw-r--r--net/cert/cert_verify_result.h1
-rw-r--r--net/data/ssl/certificates/README4
-rw-r--r--net/data/ssl/certificates/sha1_dec_2015.pem82
-rw-r--r--net/data/ssl/certificates/sha1_jan_2016.pem82
-rwxr-xr-xnet/data/ssl/scripts/generate-test-certs.sh26
13 files changed, 355 insertions, 45 deletions
diff --git a/net/cert/cert_verify_proc.cc b/net/cert/cert_verify_proc.cc
index bb379ff..0df2033 100644
--- a/net/cert/cert_verify_proc.cc
+++ b/net/cert/cert_verify_proc.cc
@@ -165,6 +165,18 @@ bool ExaminePublicKeys(const scoped_refptr<X509Certificate>& cert,
return weak_key;
}
+// Beginning with Ballot 118, ratified in the Baseline Requirements v1.2.1,
+// CAs MUST NOT issue SHA-1 certificates beginning on 1 January 2016.
+bool IsPastSHA1DeprecationDate(const X509Certificate& cert) {
+ const base::Time& start = cert.valid_start();
+ if (start.is_max() || start.is_null())
+ return true;
+ // 2016-01-01 00:00:00 UTC.
+ const base::Time kSHA1DeprecationDate =
+ base::Time::FromInternalValue(INT64_C(13096080000000000));
+ return start >= kSHA1DeprecationDate;
+}
+
} // namespace
// static
@@ -262,8 +274,19 @@ int CertVerifyProc::Verify(X509Certificate* cert,
rv = MapCertStatusToNetError(verify_result->cert_status);
}
+ if (verify_result->has_sha1)
+ verify_result->cert_status |= CERT_STATUS_SHA1_SIGNATURE_PRESENT;
+
// Flag certificates using weak signature algorithms.
- if (verify_result->has_md5) {
+ // The CA/Browser Forum Baseline Requirements (beginning with v1.2.1)
+ // prohibits SHA-1 certificates from being issued beginning on
+ // 1 January 2016. Ideally, all of SHA-1 in new certificates would be
+ // disabled on this date, but enterprises need more time to transition.
+ // As the risk is greatest for publicly trusted certificates, prevent
+ // those certificates from being trusted from that date forward.
+ if (verify_result->has_md5 ||
+ (verify_result->has_sha1_leaf && verify_result->is_issued_by_known_root &&
+ IsPastSHA1DeprecationDate(*cert))) {
verify_result->cert_status |= CERT_STATUS_WEAK_SIGNATURE_ALGORITHM;
// Avoid replacing a more serious error, such as an OS/library failure,
// by ensuring that if verification failed, it failed with a certificate
@@ -272,9 +295,6 @@ int CertVerifyProc::Verify(X509Certificate* cert,
rv = MapCertStatusToNetError(verify_result->cert_status);
}
- if (verify_result->has_sha1)
- verify_result->cert_status |= CERT_STATUS_SHA1_SIGNATURE_PRESENT;
-
// Flag certificates from publicly-trusted CAs that are issued to intranet
// hosts. While the CA/Browser Forum Baseline Requirements (v1.1) permit
// these to be issued until 1 November 2015, they represent a real risk for
diff --git a/net/cert/cert_verify_proc_android.cc b/net/cert/cert_verify_proc_android.cc
index d35f108..3825b20 100644
--- a/net/cert/cert_verify_proc_android.cc
+++ b/net/cert/cert_verify_proc_android.cc
@@ -101,6 +101,8 @@ bool VerifyFromAndroidTrustManager(const std::vector<std::string>& cert_bytes,
sig_alg == NID_dsaWithSHA1_2 || sig_alg == NID_sha1WithRSA ||
sig_alg == NID_ecdsa_with_SHA1) {
verify_result->has_sha1 = true;
+ if (i == 0)
+ verify_result->has_sha1_leaf = true;
}
}
diff --git a/net/cert/cert_verify_proc_mac.cc b/net/cert/cert_verify_proc_mac.cc
index 834b5cb..c4e0c41 100644
--- a/net/cert/cert_verify_proc_mac.cc
+++ b/net/cert/cert_verify_proc_mac.cc
@@ -192,6 +192,7 @@ void GetCertChainInfo(CFArrayRef cert_chain,
verify_result->has_md4 = false;
verify_result->has_md5 = false;
verify_result->has_sha1 = false;
+ verify_result->has_sha1_leaf = false;
SecCertificateRef verified_cert = NULL;
std::vector<SecCertificateRef> verified_chain;
@@ -252,8 +253,10 @@ void GetCertChainInfo(CFArrayRef cert_chain,
CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA_JDK) ||
CSSMOIDEqual(alg_oid, &CSSMOID_ECDSA_WithSHA1)) {
verify_result->has_sha1 = true;
- if (i == 0)
+ if (i == 0) {
+ verify_result->has_sha1_leaf = true;
*leaf_is_weak = true;
+ }
}
}
if (!verified_cert) {
diff --git a/net/cert/cert_verify_proc_nss.cc b/net/cert/cert_verify_proc_nss.cc
index 9ee65ee..b4443d5 100644
--- a/net/cert/cert_verify_proc_nss.cc
+++ b/net/cert/cert_verify_proc_nss.cc
@@ -165,7 +165,7 @@ void GetCertChainInfo(CERTCertList* cert_list,
CERTCertificate* verified_cert = NULL;
std::vector<CERTCertificate*> verified_chain;
- int i = 0;
+ size_t i = 0;
for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
!CERT_LIST_END(node, cert_list);
node = CERT_LIST_NEXT(node), ++i) {
@@ -215,6 +215,8 @@ void GetCertChainInfo(CERTCertList* cert_list,
case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
verify_result->has_sha1 = true;
+ if (i == 0)
+ verify_result->has_sha1_leaf = true;
break;
default:
break;
diff --git a/net/cert/cert_verify_proc_openssl.cc b/net/cert/cert_verify_proc_openssl.cc
index 286b21b..824a95c 100644
--- a/net/cert/cert_verify_proc_openssl.cc
+++ b/net/cert/cert_verify_proc_openssl.cc
@@ -125,6 +125,8 @@ void GetCertChainInfo(X509_STORE_CTX* store_ctx,
sig_alg == NID_dsaWithSHA1_2 || sig_alg == NID_sha1WithRSA ||
sig_alg == NID_ecdsa_with_SHA1) {
verify_result->has_sha1 = true;
+ if (i == 0)
+ verify_result->has_sha1_leaf = true;
}
}
}
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc
index 502cfb5..a3c1fd8 100644
--- a/net/cert/cert_verify_proc_unittest.cc
+++ b/net/cert/cert_verify_proc_unittest.cc
@@ -46,21 +46,18 @@ unsigned char paypal_null_fingerprint[] = {
0x1f, 0xe8, 0x1b, 0xd6, 0xab, 0x7b, 0xe8, 0xd7
};
-// Mock CertVerifyProc that will set |verify_result->is_issued_by_known_root|
-// for all certificates that are Verified.
-class WellKnownCaCertVerifyProc : public CertVerifyProc {
+// Mock CertVerifyProc that sets the CertVerifyResult to a given value for
+// all certificates that are Verify()'d
+class MockCertVerifyProc : public CertVerifyProc {
public:
- // Initialize a CertVerifyProc that will set
- // |verify_result->is_issued_by_known_root| to |is_well_known|.
- explicit WellKnownCaCertVerifyProc(bool is_well_known)
- : is_well_known_(is_well_known) {}
-
+ explicit MockCertVerifyProc(const CertVerifyResult& result)
+ : result_(result) {}
// CertVerifyProc implementation:
bool SupportsAdditionalTrustAnchors() const override { return false; }
bool SupportsOCSPStapling() const override { return false; }
protected:
- ~WellKnownCaCertVerifyProc() override {}
+ ~MockCertVerifyProc() override {}
private:
int VerifyInternal(X509Certificate* cert,
@@ -71,12 +68,12 @@ class WellKnownCaCertVerifyProc : public CertVerifyProc {
const CertificateList& additional_trust_anchors,
CertVerifyResult* verify_result) override;
- const bool is_well_known_;
+ const CertVerifyResult result_;
- DISALLOW_COPY_AND_ASSIGN(WellKnownCaCertVerifyProc);
+ DISALLOW_COPY_AND_ASSIGN(MockCertVerifyProc);
};
-int WellKnownCaCertVerifyProc::VerifyInternal(
+int MockCertVerifyProc::VerifyInternal(
X509Certificate* cert,
const std::string& hostname,
const std::string& ocsp_response,
@@ -84,7 +81,8 @@ int WellKnownCaCertVerifyProc::VerifyInternal(
CRLSet* crl_set,
const CertificateList& additional_trust_anchors,
CertVerifyResult* verify_result) {
- verify_result->is_issued_by_known_root = is_well_known_;
+ *verify_result = result_;
+ verify_result->verified_cert = cert;
return OK;
}
@@ -841,20 +839,102 @@ TEST_F(CertVerifyProcTest, IntranetHostsRejected) {
int error = 0;
// Intranet names for public CAs should be flagged:
- verify_proc_ = new WellKnownCaCertVerifyProc(true);
+ CertVerifyResult dummy_result;
+ dummy_result.is_issued_by_known_root = true;
+ verify_proc_ = new MockCertVerifyProc(dummy_result);
error =
Verify(cert.get(), "intranet", 0, NULL, empty_cert_list_, &verify_result);
EXPECT_EQ(OK, error);
EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_NON_UNIQUE_NAME);
// However, if the CA is not well known, these should not be flagged:
- verify_proc_ = new WellKnownCaCertVerifyProc(false);
+ dummy_result.Reset();
+ dummy_result.is_issued_by_known_root = false;
+ verify_proc_ = new MockCertVerifyProc(dummy_result);
error =
Verify(cert.get(), "intranet", 0, NULL, empty_cert_list_, &verify_result);
EXPECT_EQ(OK, error);
EXPECT_FALSE(verify_result.cert_status & CERT_STATUS_NON_UNIQUE_NAME);
}
+// Test that a SHA-1 certificate from a publicly trusted CA issued after
+// 1 January 2016 is rejected, but those issued before that date, or with
+// SHA-1 in the intermediate, is not rejected.
+TEST_F(CertVerifyProcTest, VerifyRejectsSHA1AfterDeprecation) {
+ CertVerifyResult dummy_result;
+ CertVerifyResult verify_result;
+ int error = 0;
+ scoped_refptr<X509Certificate> cert;
+
+ // Publicly trusted SHA-1 leaf certificates issued before 1 January 2016
+ // are accepted.
+ verify_result.Reset();
+ dummy_result.Reset();
+ dummy_result.is_issued_by_known_root = true;
+ dummy_result.has_sha1 = true;
+ dummy_result.has_sha1_leaf = true;
+ verify_proc_ = new MockCertVerifyProc(dummy_result);
+ cert = CreateCertificateChainFromFile(GetTestCertsDirectory(),
+ "sha1_dec_2015.pem",
+ X509Certificate::FORMAT_AUTO);
+ ASSERT_TRUE(cert);
+ error = Verify(cert.get(), "127.0.0.1", 0, NULL, empty_cert_list_,
+ &verify_result);
+ EXPECT_EQ(OK, error);
+ EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT);
+
+ // Publicly trusted SHA-1 leaf certificates issued on/after 1 January 2016
+ // are rejected.
+ verify_result.Reset();
+ dummy_result.Reset();
+ dummy_result.is_issued_by_known_root = true;
+ dummy_result.has_sha1 = true;
+ dummy_result.has_sha1_leaf = true;
+ verify_proc_ = new MockCertVerifyProc(dummy_result);
+ cert = CreateCertificateChainFromFile(GetTestCertsDirectory(),
+ "sha1_jan_2016.pem",
+ X509Certificate::FORMAT_AUTO);
+ ASSERT_TRUE(cert);
+ error = Verify(cert.get(), "127.0.0.1", 0, NULL, empty_cert_list_,
+ &verify_result);
+ EXPECT_EQ(ERR_CERT_WEAK_SIGNATURE_ALGORITHM, error);
+ EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM);
+
+ // Enterprise issued SHA-1 leaf certificates issued on/after 1 January 2016
+ // remain accepted until SHA-1 is disabled.
+ verify_result.Reset();
+ dummy_result.Reset();
+ dummy_result.is_issued_by_known_root = false;
+ dummy_result.has_sha1 = true;
+ dummy_result.has_sha1_leaf = true;
+ verify_proc_ = new MockCertVerifyProc(dummy_result);
+ cert = CreateCertificateChainFromFile(GetTestCertsDirectory(),
+ "sha1_jan_2016.pem",
+ X509Certificate::FORMAT_AUTO);
+ ASSERT_TRUE(cert);
+ error = Verify(cert.get(), "127.0.0.1", 0, NULL, empty_cert_list_,
+ &verify_result);
+ EXPECT_EQ(OK, error);
+ EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT);
+
+ // Publicly trusted SHA-1 intermediates issued on/after 1 January 2016 are,
+ // unfortunately, accepted. This can arise due to OS path building quirks.
+ verify_result.Reset();
+ dummy_result.Reset();
+ dummy_result.is_issued_by_known_root = true;
+ dummy_result.has_sha1 = true;
+ dummy_result.has_sha1_leaf = false;
+ verify_proc_ = new MockCertVerifyProc(dummy_result);
+ cert = CreateCertificateChainFromFile(GetTestCertsDirectory(),
+ "sha1_jan_2016.pem",
+ X509Certificate::FORMAT_AUTO);
+ ASSERT_TRUE(cert);
+ error = Verify(cert.get(), "127.0.0.1", 0, NULL, empty_cert_list_,
+ &verify_result);
+ EXPECT_EQ(OK, error);
+ EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT);
+}
+
// Test that the certificate returned in CertVerifyResult is able to reorder
// certificates that are not ordered from end-entity to root. While this is
// a protocol violation if sent during a TLS handshake, if multiple sources
@@ -1280,7 +1360,8 @@ enum ExpectedAlgorithms {
EXPECT_MD2 = 1 << 0,
EXPECT_MD4 = 1 << 1,
EXPECT_MD5 = 1 << 2,
- EXPECT_SHA1 = 1 << 3
+ EXPECT_SHA1 = 1 << 3,
+ EXPECT_SHA1_LEAF = 1 << 4,
};
struct WeakDigestTestData {
@@ -1348,6 +1429,8 @@ TEST_P(CertVerifyProcWeakDigestTest, Verify) {
EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD4), verify_result.has_md4);
EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD5), verify_result.has_md5);
EXPECT_EQ(!!(data.expected_algorithms & EXPECT_SHA1), verify_result.has_sha1);
+ EXPECT_EQ(!!(data.expected_algorithms & EXPECT_SHA1_LEAF),
+ verify_result.has_sha1_leaf);
EXPECT_FALSE(verify_result.is_issued_by_additional_trust_anchor);
@@ -1393,15 +1476,15 @@ TEST_P(CertVerifyProcWeakDigestTest, Verify) {
// The signature algorithm of the root CA should not matter.
const WeakDigestTestData kVerifyRootCATestData[] = {
- { "weak_digest_md5_root.pem", "weak_digest_sha1_intermediate.pem",
- "weak_digest_sha1_ee.pem", EXPECT_SHA1 },
+ {"weak_digest_md5_root.pem", "weak_digest_sha1_intermediate.pem",
+ "weak_digest_sha1_ee.pem", EXPECT_SHA1 | EXPECT_SHA1_LEAF},
#if defined(USE_OPENSSL_CERTS) || defined(OS_WIN)
- // MD4 is not supported by OS X / NSS
- { "weak_digest_md4_root.pem", "weak_digest_sha1_intermediate.pem",
- "weak_digest_sha1_ee.pem", EXPECT_SHA1 },
+ // MD4 is not supported by OS X / NSS
+ {"weak_digest_md4_root.pem", "weak_digest_sha1_intermediate.pem",
+ "weak_digest_sha1_ee.pem", EXPECT_SHA1 | EXPECT_SHA1_LEAF},
#endif
- { "weak_digest_md2_root.pem", "weak_digest_sha1_intermediate.pem",
- "weak_digest_sha1_ee.pem", EXPECT_SHA1 },
+ {"weak_digest_md2_root.pem", "weak_digest_sha1_intermediate.pem",
+ "weak_digest_sha1_ee.pem", EXPECT_SHA1 | EXPECT_SHA1_LEAF},
};
#if defined(OS_ANDROID)
#define MAYBE_VerifyRoot DISABLED_VerifyRoot
@@ -1414,15 +1497,15 @@ INSTANTIATE_TEST_CASE_P(MAYBE_VerifyRoot,
// The signature algorithm of intermediates should be properly detected.
const WeakDigestTestData kVerifyIntermediateCATestData[] = {
- { "weak_digest_sha1_root.pem", "weak_digest_md5_intermediate.pem",
- "weak_digest_sha1_ee.pem", EXPECT_MD5 | EXPECT_SHA1 },
+ {"weak_digest_sha1_root.pem", "weak_digest_md5_intermediate.pem",
+ "weak_digest_sha1_ee.pem", EXPECT_MD5 | EXPECT_SHA1 | EXPECT_SHA1_LEAF},
#if defined(USE_OPENSSL_CERTS) || defined(OS_WIN)
- // MD4 is not supported by OS X / NSS
- { "weak_digest_sha1_root.pem", "weak_digest_md4_intermediate.pem",
- "weak_digest_sha1_ee.pem", EXPECT_MD4 | EXPECT_SHA1 },
+ // MD4 is not supported by OS X / NSS
+ {"weak_digest_sha1_root.pem", "weak_digest_md4_intermediate.pem",
+ "weak_digest_sha1_ee.pem", EXPECT_MD4 | EXPECT_SHA1 | EXPECT_SHA1_LEAF},
#endif
- { "weak_digest_sha1_root.pem", "weak_digest_md2_intermediate.pem",
- "weak_digest_sha1_ee.pem", EXPECT_MD2 | EXPECT_SHA1 },
+ {"weak_digest_sha1_root.pem", "weak_digest_md2_intermediate.pem",
+ "weak_digest_sha1_ee.pem", EXPECT_MD2 | EXPECT_SHA1 | EXPECT_SHA1_LEAF},
};
// Disabled on NSS - MD4 is not supported, and MD2 and MD5 are disabled.
#if defined(USE_NSS_CERTS) || defined(OS_IOS) || defined(OS_ANDROID)
@@ -1461,15 +1544,15 @@ WRAPPED_INSTANTIATE_TEST_CASE_P(MAYBE_VerifyEndEntity,
// Incomplete chains should still report the status of the intermediate.
const WeakDigestTestData kVerifyIncompleteIntermediateTestData[] = {
- { NULL, "weak_digest_md5_intermediate.pem", "weak_digest_sha1_ee.pem",
- EXPECT_MD5 | EXPECT_SHA1 },
+ {NULL, "weak_digest_md5_intermediate.pem", "weak_digest_sha1_ee.pem",
+ EXPECT_MD5 | EXPECT_SHA1 | EXPECT_SHA1_LEAF},
#if defined(USE_OPENSSL_CERTS) || defined(OS_WIN)
- // MD4 is not supported by OS X / NSS
- { NULL, "weak_digest_md4_intermediate.pem", "weak_digest_sha1_ee.pem",
- EXPECT_MD4 | EXPECT_SHA1 },
+ // MD4 is not supported by OS X / NSS
+ {NULL, "weak_digest_md4_intermediate.pem", "weak_digest_sha1_ee.pem",
+ EXPECT_MD4 | EXPECT_SHA1 | EXPECT_SHA1_LEAF},
#endif
- { NULL, "weak_digest_md2_intermediate.pem", "weak_digest_sha1_ee.pem",
- EXPECT_MD2 | EXPECT_SHA1 },
+ {NULL, "weak_digest_md2_intermediate.pem", "weak_digest_sha1_ee.pem",
+ EXPECT_MD2 | EXPECT_SHA1 | EXPECT_SHA1_LEAF},
};
// Disabled on NSS - libpkix does not return constructed chains on error,
// preventing us from detecting/inspecting the verified chain.
diff --git a/net/cert/cert_verify_proc_win.cc b/net/cert/cert_verify_proc_win.cc
index 4eada6f..f67f823 100644
--- a/net/cert/cert_verify_proc_win.cc
+++ b/net/cert/cert_verify_proc_win.cc
@@ -295,7 +295,7 @@ void GetCertChainInfo(PCCERT_CHAIN_CONTEXT chain_context,
return;
PCERT_SIMPLE_CHAIN first_chain = chain_context->rgpChain[0];
- int num_elements = first_chain->cElement;
+ DWORD num_elements = first_chain->cElement;
PCERT_CHAIN_ELEMENT* element = first_chain->rgpElement;
PCCERT_CONTEXT verified_cert = NULL;
@@ -316,7 +316,7 @@ void GetCertChainInfo(PCCERT_CHAIN_CONTEXT chain_context,
num_elements -= 1;
}
- for (int i = 0; i < num_elements; ++i) {
+ for (DWORD i = 0; i < num_elements; ++i) {
PCCERT_CONTEXT cert = element[i]->pCertContext;
if (i == 0) {
verified_cert = cert;
@@ -341,6 +341,8 @@ void GetCertChainInfo(PCCERT_CHAIN_CONTEXT chain_context,
// id-dsa-with-sha1: 1.2.840.10040.4.3
// ecdsa-with-SHA1: 1.2.840.10045.4.1
verify_result->has_sha1 = true;
+ if (i == 0)
+ verify_result->has_sha1_leaf = true;
}
}
diff --git a/net/cert/cert_verify_result.cc b/net/cert/cert_verify_result.cc
index b2413e6..2a41893 100644
--- a/net/cert/cert_verify_result.cc
+++ b/net/cert/cert_verify_result.cc
@@ -22,6 +22,7 @@ void CertVerifyResult::Reset() {
has_md4 = false;
has_md5 = false;
has_sha1 = false;
+ has_sha1_leaf = false;
is_issued_by_known_root = false;
is_issued_by_additional_trust_anchor = false;
common_name_fallback_used = false;
diff --git a/net/cert/cert_verify_result.h b/net/cert/cert_verify_result.h
index 9e67325..104fc6e 100644
--- a/net/cert/cert_verify_result.h
+++ b/net/cert/cert_verify_result.h
@@ -48,6 +48,7 @@ class NET_EXPORT CertVerifyResult {
bool has_md4;
bool has_md5;
bool has_sha1;
+ bool has_sha1_leaf;
// If the certificate was successfully verified then this contains the
// hashes, in several hash algorithms, of the SubjectPublicKeyInfos of the
diff --git a/net/data/ssl/certificates/README b/net/data/ssl/certificates/README
index 6eed2be..305528d 100644
--- a/net/data/ssl/certificates/README
+++ b/net/data/ssl/certificates/README
@@ -158,6 +158,10 @@ unit tests.
- sha1_2016.pem
Used to test the handling of SHA1 certificates expiring in 2016.
+- sha1_dec_2015.pem
+- sha1_jan_2016.pem
+ Used to test enforcement of the Baseline Requirements' policies on SHA-1.
+
- 10_year_validity.pem
- 11_year_validity.pem
- 39_months_after_2015_04.pem
diff --git a/net/data/ssl/certificates/sha1_dec_2015.pem b/net/data/ssl/certificates/sha1_dec_2015.pem
new file mode 100644
index 0000000..b5047d2
--- /dev/null
+++ b/net/data/ssl/certificates/sha1_dec_2015.pem
@@ -0,0 +1,82 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 8 (0x8)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=Test Root CA
+ Validity
+ Not Before: Dec 31 23:59:59 2015 GMT
+ Not After : Dec 30 00:00:00 2016 GMT
+ Subject: C=US, ST=California, L=Mountain View, O=Test CA, CN=127.0.0.1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:da:6a:85:4f:e5:d7:73:82:af:a2:1e:85:49:d0:
+ a9:ef:65:b9:29:e3:1d:32:d0:33:10:0d:67:a8:7d:
+ 22:d1:99:c1:c9:ab:e5:3e:06:9b:63:62:81:60:26:
+ 9c:70:b4:92:65:95:46:b2:fd:ad:e5:19:b1:30:6d:
+ a5:00:7d:d8:4d:b3:e7:b6:a5:83:da:be:26:79:ee:
+ 58:0a:f8:dd:8a:ae:13:db:f7:9a:8a:2b:eb:9f:15:
+ 53:5d:ce:18:ac:03:f2:ed:30:f4:8c:af:d6:7e:76:
+ 97:aa:97:c4:24:a5:7e:28:dc:dc:22:ea:86:54:4f:
+ 15:bf:03:81:11:ea:f9:ca:17:db:5a:b8:f0:3d:1a:
+ a5:c9:96:1b:d3:ed:99:ba:7a:55:e3:fa:9e:61:54:
+ 61:75:16:79:22:10:e9:e6:5a:b5:6b:b5:9d:32:bb:
+ e8:10:de:66:d7:1a:59:6f:d7:42:bf:80:b5:b2:73:
+ b9:a1:0b:5d:fe:0f:a1:6c:fc:de:99:d2:b3:ae:13:
+ d6:7f:f3:a9:7e:c0:07:f1:e4:a2:27:1b:1f:6d:81:
+ 86:b4:0f:f7:2b:9a:3c:7b:76:dc:5d:3a:b0:9e:b7:
+ 64:5f:53:33:08:3a:51:77:df:d1:91:b5:54:b8:4e:
+ 7a:0c:29:d1:40:cb:47:a4:cc:3b:b4:6e:a2:4d:91:
+ 6b:75
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ 16:04:CF:CB:65:43:70:72:46:1E:83:5B:87:5E:10:CB:CB:69:B2:60
+ X509v3 Authority Key Identifier:
+ keyid:6C:29:1B:65:A9:3F:B8:19:9A:0F:FC:77:D6:95:55:2A:F2:4B:74:E6
+
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Subject Alternative Name:
+ IP Address:127.0.0.1
+ Signature Algorithm: sha256WithRSAEncryption
+ 58:b4:e7:31:15:4f:c4:70:1e:51:c6:ae:c3:47:3d:e8:17:92:
+ b9:8e:3b:76:c4:38:98:f7:c9:6e:be:0b:6a:2c:9d:fb:29:37:
+ e5:a7:4a:33:56:b5:2b:38:37:3e:65:8c:32:97:26:cf:47:94:
+ 1c:35:d1:8b:83:67:33:60:35:ed:8d:84:51:21:84:fe:15:4b:
+ 31:6d:6c:df:b2:24:ad:25:cd:f2:40:c5:bf:68:d8:62:db:ad:
+ d3:05:4b:71:0a:83:f5:12:d1:49:47:c5:44:a5:a5:08:1d:26:
+ 35:a2:2e:42:f1:06:4d:79:8a:54:95:51:54:a7:d3:aa:33:86:
+ ab:c7:5f:81:03:76:c1:c3:61:9a:9f:d9:a4:0c:6e:9f:31:40:
+ 0a:ee:b7:ae:e4:4a:17:aa:79:9c:17:1b:d4:49:65:52:57:f4:
+ 52:bb:e4:12:0e:b0:1a:65:c4:8d:e4:02:26:ff:43:42:87:53:
+ 7c:4b:10:7d:19:14:a9:c8:b7:9e:9a:e6:54:c1:f9:9e:2e:57:
+ 58:8e:37:3b:66:25:ce:1c:5c:7c:55:e1:0c:3a:dc:ac:46:48:
+ e2:d6:f5:c9:dd:36:c3:4f:75:df:06:af:e4:dc:21:fd:73:14:
+ 6d:51:1c:2d:b3:15:2e:1c:fb:b4:b9:b4:01:1f:82:ae:1d:20:
+ 3d:5f:25:98
+-----BEGIN CERTIFICATE-----
+MIIDczCCAlugAwIBAgIBCDANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAxUZXN0
+IFJvb3QgQ0EwHhcNMTUxMjMxMjM1OTU5WhcNMTYxMjMwMDAwMDAwWjBgMQswCQYD
+VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4g
+VmlldzEQMA4GA1UECgwHVGVzdCBDQTESMBAGA1UEAwwJMTI3LjAuMC4xMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2mqFT+XXc4Kvoh6FSdCp72W5KeMd
+MtAzEA1nqH0i0ZnByavlPgabY2KBYCaccLSSZZVGsv2t5RmxMG2lAH3YTbPntqWD
+2r4mee5YCvjdiq4T2/eaiivrnxVTXc4YrAPy7TD0jK/WfnaXqpfEJKV+KNzcIuqG
+VE8VvwOBEer5yhfbWrjwPRqlyZYb0+2ZunpV4/qeYVRhdRZ5IhDp5lq1a7WdMrvo
+EN5m1xpZb9dCv4C1snO5oQtd/g+hbPzemdKzrhPWf/OpfsAH8eSiJxsfbYGGtA/3
+K5o8e3bcXTqwnrdkX1MzCDpRd9/RkbVUuE56DCnRQMtHpMw7tG6iTZFrdQIDAQAB
+o4GAMH4wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUFgTPy2VDcHJGHoNbh14Qy8tp
+smAwHwYDVR0jBBgwFoAUbCkbZak/uBmaD/x31pVVKvJLdOYwHQYDVR0lBBYwFAYI
+KwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEQQIMAaHBH8AAAEwDQYJKoZIhvcNAQEL
+BQADggEBAFi05zEVT8RwHlHGrsNHPegXkrmOO3bEOJj3yW6+C2osnfspN+WnSjNW
+tSs4Nz5ljDKXJs9HlBw10YuDZzNgNe2NhFEhhP4VSzFtbN+yJK0lzfJAxb9o2GLb
+rdMFS3EKg/US0UlHxUSlpQgdJjWiLkLxBk15ilSVUVSn06ozhqvHX4EDdsHDYZqf
+2aQMbp8xQArut67kSheqeZwXG9RJZVJX9FK75BIOsBplxI3kAib/Q0KHU3xLEH0Z
+FKnIt56a5lTB+Z4uV1iONztmJc4cXHxV4Qw63KxGSOLW9cndNsNPdd8Gr+TcIf1z
+FG1RHC2zFS4c+7S5tAEfgq4dID1fJZg=
+-----END CERTIFICATE-----
diff --git a/net/data/ssl/certificates/sha1_jan_2016.pem b/net/data/ssl/certificates/sha1_jan_2016.pem
new file mode 100644
index 0000000..efb9b01
--- /dev/null
+++ b/net/data/ssl/certificates/sha1_jan_2016.pem
@@ -0,0 +1,82 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 9 (0x9)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=Test Root CA
+ Validity
+ Not Before: Jan 1 00:00:00 2016 GMT
+ Not After : Dec 30 00:00:00 2016 GMT
+ Subject: C=US, ST=California, L=Mountain View, O=Test CA, CN=127.0.0.1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:b6:93:55:29:0f:ea:d2:34:c0:71:6b:df:b4:f6:
+ 9f:12:72:65:e1:0c:ac:1a:7d:ab:3e:76:2e:64:5a:
+ 02:c7:bc:61:bd:1e:ed:f3:eb:30:76:bd:44:48:d0:
+ 15:fc:8b:f3:c5:bc:06:18:c2:8e:7b:99:a1:bc:f1:
+ 24:d4:17:05:39:51:bc:cc:1f:39:c7:0a:67:3b:76:
+ 8b:23:3f:9a:df:a9:21:70:71:17:40:c3:6f:b0:a2:
+ ea:7b:e3:64:94:08:cd:4b:66:a4:00:27:2f:af:8e:
+ ce:99:4c:c6:21:c6:4a:05:5e:08:17:41:3a:d4:31:
+ a0:bc:a0:0a:2e:a1:b2:ff:08:d9:11:a6:40:fc:f0:
+ 0f:3e:9c:31:de:32:4b:23:c2:b8:d4:a3:2c:81:84:
+ e7:64:c7:25:3b:e9:8e:aa:6c:7f:13:8a:66:35:2d:
+ a6:3c:07:95:7f:26:75:16:24:c0:92:6e:cf:f3:c3:
+ 19:f4:66:f9:23:4f:75:de:2f:a5:cd:1a:15:94:23:
+ 8c:68:bc:32:74:1d:21:fa:5f:c9:88:48:9a:08:c7:
+ 1e:9c:31:27:fb:8e:d7:01:72:6e:60:bb:b4:b6:f3:
+ d8:8b:6c:97:6c:ec:a0:42:b6:48:02:f1:f1:b7:15:
+ 0d:84:e5:96:64:9e:f4:59:a1:4f:df:cb:e6:58:51:
+ bf:d7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:FALSE
+ X509v3 Subject Key Identifier:
+ A6:36:4C:FB:11:3E:B2:79:D1:1F:94:96:A1:F0:14:03:01:BB:09:CE
+ X509v3 Authority Key Identifier:
+ keyid:6C:29:1B:65:A9:3F:B8:19:9A:0F:FC:77:D6:95:55:2A:F2:4B:74:E6
+
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ X509v3 Subject Alternative Name:
+ IP Address:127.0.0.1
+ Signature Algorithm: sha256WithRSAEncryption
+ 6c:76:f5:b4:56:92:77:34:99:32:47:05:9b:23:93:8e:82:29:
+ d9:cd:7f:e8:81:65:19:4a:db:6c:c7:c3:ef:7d:47:43:30:24:
+ 58:8a:9b:63:b6:88:d5:c4:57:09:89:79:ce:ac:4a:e2:bf:e5:
+ 87:1e:5d:e5:99:37:b6:af:96:7b:0c:a4:6c:ff:1c:65:eb:36:
+ cd:5f:74:53:e9:28:ef:72:e1:9f:b6:b5:aa:0f:8f:60:91:f7:
+ 79:62:85:d1:b2:19:84:26:9d:ff:e0:20:4c:71:7d:72:12:10:
+ 7e:83:4e:e1:c5:6a:a7:d2:5c:c2:c4:ac:33:e1:02:c5:74:d3:
+ 79:57:cd:8b:89:a2:17:b2:9a:97:83:ce:8a:b3:ae:50:e4:99:
+ d7:af:96:d2:d8:57:72:d3:22:67:17:52:7d:f0:4d:d3:48:95:
+ 5a:ef:8a:d4:1d:43:bd:3b:65:49:5b:70:da:7f:2e:8a:aa:e0:
+ b5:ed:6d:8f:d0:1d:7a:cc:ee:c7:47:dc:66:de:cf:b0:19:07:
+ 3f:44:d6:ce:db:1d:b1:1a:3e:54:60:16:93:df:85:76:62:9d:
+ 0e:fa:27:1c:bd:6f:fe:20:9b:34:4a:b6:f8:f9:52:c4:bb:22:
+ 92:01:69:8e:5b:da:0f:b9:f6:63:89:3f:f2:58:bc:59:9e:3d:
+ 58:c6:fe:db
+-----BEGIN CERTIFICATE-----
+MIIDczCCAlugAwIBAgIBCTANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAxUZXN0
+IFJvb3QgQ0EwHhcNMTYwMTAxMDAwMDAwWhcNMTYxMjMwMDAwMDAwWjBgMQswCQYD
+VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4g
+VmlldzEQMA4GA1UECgwHVGVzdCBDQTESMBAGA1UEAwwJMTI3LjAuMC4xMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtpNVKQ/q0jTAcWvftPafEnJl4Qys
+Gn2rPnYuZFoCx7xhvR7t8+swdr1ESNAV/IvzxbwGGMKOe5mhvPEk1BcFOVG8zB85
+xwpnO3aLIz+a36khcHEXQMNvsKLqe+NklAjNS2akACcvr47OmUzGIcZKBV4IF0E6
+1DGgvKAKLqGy/wjZEaZA/PAPPpwx3jJLI8K41KMsgYTnZMclO+mOqmx/E4pmNS2m
+PAeVfyZ1FiTAkm7P88MZ9Gb5I0913i+lzRoVlCOMaLwydB0h+l/JiEiaCMcenDEn
++47XAXJuYLu0tvPYi2yXbOygQrZIAvHxtxUNhOWWZJ70WaFP38vmWFG/1wIDAQAB
+o4GAMH4wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUpjZM+xE+snnRH5SWofAUAwG7
+Cc4wHwYDVR0jBBgwFoAUbCkbZak/uBmaD/x31pVVKvJLdOYwHQYDVR0lBBYwFAYI
+KwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEQQIMAaHBH8AAAEwDQYJKoZIhvcNAQEL
+BQADggEBAGx29bRWknc0mTJHBZsjk46CKdnNf+iBZRlK22zHw+99R0MwJFiKm2O2
+iNXEVwmJec6sSuK/5YceXeWZN7avlnsMpGz/HGXrNs1fdFPpKO9y4Z+2taoPj2CR
+93lihdGyGYQmnf/gIExxfXISEH6DTuHFaqfSXMLErDPhAsV003lXzYuJoheympeD
+zoqzrlDkmdevltLYV3LTImcXUn3wTdNIlVrvitQdQ707ZUlbcNp/Loqq4LXtbY/Q
+HXrM7sdH3Gbez7AZBz9E1s7bHbEaPlRgFpPfhXZinQ76Jxy9b/4gmzRKtvj5UsS7
+IpIBaY5b2g+59mOJP/JYvFmePVjG/ts=
+-----END CERTIFICATE-----
diff --git a/net/data/ssl/scripts/generate-test-certs.sh b/net/data/ssl/scripts/generate-test-certs.sh
index d777718..b2481ad 100755
--- a/net/data/ssl/scripts/generate-test-certs.sh
+++ b/net/data/ssl/scripts/generate-test-certs.sh
@@ -183,6 +183,32 @@ CA_COMMON_NAME="Test Root CA" \
-out ../certificates/sha1_2016.pem \
-config ca.cnf
+## SHA1 certificate issued the last second before the SHA-1 deprecation date.
+try openssl req -config ../scripts/ee.cnf -sha1 \
+ -newkey rsa:2048 -text -out out/sha1_dec_2015.req
+CA_COMMON_NAME="Test Root CA" \
+ try openssl ca \
+ -batch \
+ -extensions user_cert \
+ -startdate 151231235959Z \
+ -enddate 161230000000Z \
+ -in out/sha1_dec_2015.req \
+ -out ../certificates/sha1_dec_2015.pem \
+ -config ca.cnf
+
+## SHA1 certificate issued on the SHA-1 deprecation date.
+try openssl req -config ../scripts/ee.cnf -sha1 \
+ -newkey rsa:2048 -text -out out/sha1_jan_2016.req
+CA_COMMON_NAME="Test Root CA" \
+ try openssl ca \
+ -batch \
+ -extensions user_cert \
+ -startdate 160101000000Z \
+ -enddate 161230000000Z \
+ -in out/sha1_jan_2016.req \
+ -out ../certificates/sha1_jan_2016.pem \
+ -config ca.cnf
+
## Validity too long unit test support.
try openssl req -config ../scripts/ee.cnf \
-newkey rsa:2048 -text -out ../certificates/10_year_validity.req