Make Cast certificate verification enforce constraints specified in the trusted root certificate.
* Hardcode the 2 Chromecast root certificates. Previously we included their Subject+SPKI, now it includes the full certificates.
* Change the net::TrustStore to take full-blown certificates rather than (subjet, spki) tuples.
* During verification all checks are done on the root certificate except for signature and issuer check.
Review URL: https://codereview.chromium.org/1890193003
Cr-Commit-Position: refs/heads/master@{#388905}
diff --git a/extensions/common/cast/cast_cert_validator.cc b/extensions/common/cast/cast_cert_validator.cc
index 2211bb6..f80b1063d 100644
--- a/extensions/common/cast/cast_cert_validator.cc
+++ b/extensions/common/cast/cast_cert_validator.cc
@@ -9,6 +9,7 @@
#include <algorithm>
#include <utility>
+#include "base/memory/singleton.h"
#include "net/cert/internal/certificate_policies.h"
#include "net/cert/internal/extended_key_usage.h"
#include "net/cert/internal/parse_certificate.h"
@@ -30,121 +31,39 @@
// There are two trusted roots for Cast certificate chains:
//
-// (1) CN=Cast Root CA
-// (2) CN=Eureka Root CA
+// (1) CN=Cast Root CA (kCastRootCaDer)
+// (2) CN=Eureka Root CA (kEurekaRootCaDer)
//
-// Note that only the subject/spki are saved here, not the full certificate.
-// See the TODO in CreateCastTrustStore().
+// These constants are defined by the files included next:
-unsigned char kCastRootCaSubjectDer[119] = {
- 0x30, 0x75, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
- 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
- 0x0C, 0x0A, 0x43, 0x61, 0x6C, 0x69, 0x66, 0x6F, 0x72, 0x6E, 0x69, 0x61,
- 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x0D, 0x4D,
- 0x6F, 0x75, 0x6E, 0x74, 0x61, 0x69, 0x6E, 0x20, 0x56, 0x69, 0x65, 0x77,
- 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0A, 0x47,
- 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x0D, 0x30,
- 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x04, 0x43, 0x61, 0x73, 0x74,
- 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0C, 0x43,
- 0x61, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41,
+#include "extensions/common/cast/cast_root_ca_cert_der-inc.h"
+#include "extensions/common/cast/eureka_root_ca_der-inc.h"
+
+// Singleton for the Cast trust store.
+class CastTrustStore {
+ public:
+ static CastTrustStore* GetInstance() {
+ return base::Singleton<CastTrustStore,
+ base::LeakySingletonTraits<CastTrustStore>>::get();
+ }
+
+ static net::TrustStore& Get() { return GetInstance()->store_; }
+
+ private:
+ friend struct base::DefaultSingletonTraits<CastTrustStore>;
+
+ CastTrustStore() {
+ // Initialize the trust store with two root certificates.
+ CHECK(store_.AddTrustedCertificateWithoutCopying(kCastRootCaDer,
+ sizeof(kCastRootCaDer)));
+ CHECK(store_.AddTrustedCertificateWithoutCopying(kEurekaRootCaDer,
+ sizeof(kEurekaRootCaDer)));
+ }
+
+ net::TrustStore store_;
+ DISALLOW_COPY_AND_ASSIGN(CastTrustStore);
};
-unsigned char kCastRootCaSpkiDer[294] = {
- 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
- 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00,
- 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xBA, 0xD9, 0x65,
- 0x9D, 0xDA, 0x39, 0xD3, 0xC1, 0x77, 0xF6, 0xD4, 0xD0, 0xAE, 0x8F, 0x58,
- 0x08, 0x68, 0x39, 0x4A, 0x95, 0xED, 0x70, 0xCF, 0xFD, 0x79, 0x08, 0xA9,
- 0xAA, 0xE5, 0xE9, 0xB8, 0xA7, 0x2D, 0xA0, 0x67, 0x47, 0x8A, 0x9E, 0xC9,
- 0xCF, 0x70, 0xB3, 0x05, 0x87, 0x69, 0x11, 0xEC, 0x70, 0x98, 0x97, 0xC3,
- 0xE6, 0xC3, 0xC3, 0xEB, 0xBD, 0xC6, 0xB0, 0x3D, 0xFC, 0x4F, 0xC1, 0x5E,
- 0x38, 0x9F, 0xDA, 0xCF, 0x73, 0x30, 0x06, 0x5B, 0x79, 0x37, 0xC1, 0x5E,
- 0x8C, 0x87, 0x47, 0x94, 0x9A, 0x41, 0x92, 0x2A, 0xD6, 0x95, 0xC4, 0x71,
- 0x5C, 0x27, 0x5D, 0x08, 0xB1, 0x80, 0xC6, 0x92, 0xBD, 0x1B, 0xE3, 0x41,
- 0x97, 0xA1, 0xEC, 0x75, 0x9F, 0x55, 0x9E, 0x3E, 0x9F, 0x8F, 0x1C, 0xC7,
- 0x65, 0x64, 0x07, 0xD3, 0xB3, 0x96, 0xA1, 0x04, 0x9F, 0x91, 0xC4, 0xDE,
- 0x0A, 0x7B, 0x6C, 0xD9, 0xC8, 0xC0, 0x78, 0x31, 0xA0, 0x19, 0x42, 0xA9,
- 0xE8, 0x83, 0xE3, 0xCE, 0xFC, 0xF1, 0xCE, 0xC2, 0x2E, 0x24, 0x46, 0x95,
- 0x09, 0x19, 0xCA, 0xC0, 0x46, 0xB2, 0xE5, 0x01, 0xBA, 0xD7, 0x4F, 0xF3,
- 0xBF, 0xF6, 0x69, 0xAD, 0x99, 0x04, 0xFA, 0xA0, 0x07, 0x39, 0x0E, 0xE6,
- 0xDF, 0x51, 0x47, 0x07, 0xC0, 0xE4, 0xA9, 0x5C, 0x4B, 0x94, 0xC5, 0x2F,
- 0xB3, 0xA0, 0x30, 0x7F, 0xE7, 0x95, 0x6B, 0xB2, 0xAF, 0x32, 0x0D, 0xF1,
- 0x8C, 0xD5, 0x6D, 0xCB, 0x7B, 0x47, 0xA7, 0x08, 0xAB, 0xCB, 0x27, 0xA3,
- 0x4D, 0xCF, 0x4A, 0x5A, 0xF1, 0x05, 0xD1, 0xF8, 0x62, 0xC5, 0x10, 0x2A,
- 0x74, 0x69, 0xAA, 0xE6, 0x4B, 0x96, 0xFB, 0x9B, 0xD8, 0x63, 0xE4, 0x58,
- 0x66, 0xD3, 0xAD, 0x8A, 0x6E, 0xFF, 0x7B, 0x5E, 0xF9, 0xA5, 0x56, 0x1E,
- 0x2D, 0x82, 0x31, 0x5B, 0xF0, 0xE2, 0x24, 0xE6, 0x41, 0x4A, 0x1F, 0xAE,
- 0x13, 0x02, 0x03, 0x01, 0x00, 0x01,
-};
-
-unsigned char kEurekaRootCaSubjectDer[126] = {
- 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
- 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
- 0x0C, 0x0A, 0x43, 0x61, 0x6C, 0x69, 0x66, 0x6F, 0x72, 0x6E, 0x69, 0x61,
- 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x0D, 0x4D,
- 0x6F, 0x75, 0x6E, 0x74, 0x61, 0x69, 0x6E, 0x20, 0x56, 0x69, 0x65, 0x77,
- 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0A, 0x47,
- 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x12, 0x30,
- 0x10, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x09, 0x47, 0x6F, 0x6F, 0x67,
- 0x6C, 0x65, 0x20, 0x54, 0x56, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55,
- 0x04, 0x03, 0x0C, 0x0E, 0x45, 0x75, 0x72, 0x65, 0x6B, 0x61, 0x20, 0x52,
- 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41,
-};
-
-unsigned char kEurekaRootCaSpkiDer[294] = {
- 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
- 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00,
- 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xB9, 0x11, 0xD0,
- 0xEA, 0x12, 0xDC, 0x32, 0xE1, 0xDF, 0x5C, 0x33, 0x6B, 0x19, 0x73, 0x1D,
- 0x9D, 0x9E, 0xD0, 0x39, 0x76, 0xBF, 0xA5, 0x84, 0x09, 0xA6, 0xFD, 0x6E,
- 0x6D, 0xE9, 0xDC, 0x8F, 0x36, 0x4E, 0xE9, 0x88, 0x02, 0xBD, 0x9F, 0xF4,
- 0xE8, 0x44, 0xFD, 0x4C, 0xF5, 0x9A, 0x02, 0x56, 0x6A, 0x47, 0x2A, 0x63,
- 0x6C, 0x58, 0x45, 0xCC, 0x7C, 0x66, 0x24, 0xDC, 0x79, 0x79, 0xC3, 0x2A,
- 0xA4, 0xB2, 0x8B, 0xA0, 0xF7, 0xA2, 0xB5, 0xCD, 0x06, 0x7E, 0xDB, 0xBE,
- 0xEC, 0x0C, 0x86, 0xF2, 0x0D, 0x24, 0x60, 0x74, 0x84, 0xCA, 0x29, 0x23,
- 0x84, 0x02, 0xD8, 0xA7, 0xED, 0x3B, 0xF1, 0xEC, 0x26, 0x47, 0x54, 0xE3,
- 0xB1, 0x2D, 0xE6, 0x64, 0x0F, 0xF6, 0x72, 0xC5, 0xE9, 0x98, 0x52, 0x17,
- 0xC0, 0xFC, 0xF2, 0x2C, 0x20, 0xC8, 0x40, 0xF8, 0x47, 0xC9, 0x32, 0x9E,
- 0x3B, 0x97, 0xB1, 0x8B, 0xF5, 0x98, 0x24, 0x70, 0x63, 0x66, 0x19, 0xC1,
- 0x52, 0xE8, 0x04, 0x05, 0x3D, 0x5F, 0x8D, 0xBC, 0xD8, 0x4B, 0xAF, 0x77,
- 0x98, 0x6F, 0x1F, 0x78, 0xD1, 0xB6, 0x50, 0x27, 0x4D, 0xE4, 0xEC, 0x14,
- 0x69, 0x67, 0x1F, 0x58, 0xAF, 0xA9, 0xA0, 0x11, 0x26, 0x3C, 0x94, 0x32,
- 0x07, 0x7F, 0xD7, 0xE9, 0x69, 0x1F, 0xAE, 0x3F, 0x4F, 0x63, 0x8A, 0x8F,
- 0x89, 0xD6, 0xF2, 0x19, 0x78, 0x5C, 0x21, 0x8E, 0xB1, 0xB6, 0x57, 0xD8,
- 0xC0, 0xE1, 0xEE, 0x7D, 0x6E, 0xDD, 0xF1, 0x3A, 0x0A, 0x6A, 0xF1, 0xBA,
- 0xFF, 0xF9, 0x83, 0x2F, 0xDC, 0xB5, 0xA4, 0x20, 0x17, 0x63, 0x36, 0xEF,
- 0xC8, 0x62, 0x19, 0xCC, 0x56, 0xCE, 0xB2, 0xEA, 0x31, 0x89, 0x4B, 0x78,
- 0x58, 0xC1, 0xBF, 0x03, 0x13, 0x99, 0xE0, 0x12, 0xF2, 0x88, 0xAA, 0x9B,
- 0x94, 0xDA, 0xDD, 0x76, 0x79, 0x17, 0x1E, 0x34, 0xD1, 0x0A, 0xC4, 0x07,
- 0x45, 0x02, 0x03, 0x01, 0x00, 0x01,
-};
-
-// Helper function that creates and initializes a TrustAnchor struct given
-// arrays for the subject's DER and the SPKI's DER.
-template <size_t SubjectSize, size_t SpkiSize>
-net::TrustAnchor CreateTrustAnchor(const uint8_t (&subject)[SubjectSize],
- const uint8_t (&spki)[SpkiSize]) {
- net::TrustAnchor anchor;
- anchor.name = std::string(subject, subject + SubjectSize);
- anchor.spki = std::string(spki, spki + SpkiSize);
- return anchor;
-}
-
-// Creates a trust store with the two Cast roots.
-//
-// TODO(eroman): The root certificates themselves are not included in the trust
-// store (just their subject/SPKI). The problem with this approach is any
-// restrictions encoded in their (like path length, or policy) are not known
-// when verifying, and hence not enforced.
-net::TrustStore CreateCastTrustStore() {
- net::TrustStore store;
- store.anchors.push_back(
- CreateTrustAnchor(kEurekaRootCaSubjectDer, kEurekaRootCaSpkiDer));
- store.anchors.push_back(
- CreateTrustAnchor(kCastRootCaSubjectDer, kCastRootCaSpkiDer));
- return store;
-}
-
using ExtensionsMap = std::map<net::der::Input, net::ParsedExtension>;
// Helper that looks up an extension by OID given a map of extensions.
@@ -340,14 +259,6 @@
const base::Time::Exploded& time,
scoped_ptr<CertVerificationContext>* context,
CastDeviceCertPolicy* policy) {
- // Initialize the trust store used for verifying Cast
- // device certificates.
- //
- // Performance: This code is re-building a TrustStore object each
- // time a chain needs to be verified rather than caching it, to
- // avoid memory bloat.
- auto trust_store = CreateCastTrustStore();
-
// The underlying verification function expects a sequence of
// der::Input, so wrap the data in it (cheap).
std::vector<net::der::Input> input_chain;
@@ -359,7 +270,7 @@
// Do RFC 5280 compatible certificate verification using the two Cast
// trust anchors and Cast signature policy.
- if (!net::VerifyCertificateChain(input_chain, trust_store,
+ if (!net::VerifyCertificateChain(input_chain, CastTrustStore::Get(),
signature_policy.get(),
ConvertExplodedTime(time))) {
return false;
diff --git a/extensions/common/cast/cast_root_ca_cert_der-inc.h b/extensions/common/cast/cast_root_ca_cert_der-inc.h
new file mode 100644
index 0000000..3c6200b
--- /dev/null
+++ b/extensions/common/cast/cast_root_ca_cert_der-inc.h
@@ -0,0 +1,148 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Certificate:
+// Data:
+// Version: 3 (0x2)
+// Serial Number: 2 (0x2)
+// Signature Algorithm: sha1WithRSAEncryption
+// Issuer: C=US, ST=California, L=Mountain View, O=Google Inc,
+// OU=Cast, CN=Cast Root CA
+// Validity
+// Not Before: Apr 2 17:34:26 2014 GMT
+// Not After : Mar 28 17:34:26 2034 GMT
+// Subject: C=US, ST=California, L=Mountain View, O=Google Inc, OU=Cast,
+// CN=Cast Root CA
+// Subject Public Key Info:
+// Public Key Algorithm: rsaEncryption
+// Public-Key: (2048 bit)
+// Modulus:
+// 00:ba:d9:65:9d:da:39:d3:c1:77:f6:d4:d0:ae:8f:
+// 58:08:68:39:4a:95:ed:70:cf:fd:79:08:a9:aa:e5:
+// e9:b8:a7:2d:a0:67:47:8a:9e:c9:cf:70:b3:05:87:
+// 69:11:ec:70:98:97:c3:e6:c3:c3:eb:bd:c6:b0:3d:
+// fc:4f:c1:5e:38:9f:da:cf:73:30:06:5b:79:37:c1:
+// 5e:8c:87:47:94:9a:41:92:2a:d6:95:c4:71:5c:27:
+// 5d:08:b1:80:c6:92:bd:1b:e3:41:97:a1:ec:75:9f:
+// 55:9e:3e:9f:8f:1c:c7:65:64:07:d3:b3:96:a1:04:
+// 9f:91:c4:de:0a:7b:6c:d9:c8:c0:78:31:a0:19:42:
+// a9:e8:83:e3:ce:fc:f1:ce:c2:2e:24:46:95:09:19:
+// ca:c0:46:b2:e5:01:ba:d7:4f:f3:bf:f6:69:ad:99:
+// 04:fa:a0:07:39:0e:e6:df:51:47:07:c0:e4:a9:5c:
+// 4b:94:c5:2f:b3:a0:30:7f:e7:95:6b:b2:af:32:0d:
+// f1:8c:d5:6d:cb:7b:47:a7:08:ab:cb:27:a3:4d:cf:
+// 4a:5a:f1:05:d1:f8:62:c5:10:2a:74:69:aa:e6:4b:
+// 96:fb:9b:d8:63:e4:58:66:d3:ad:8a:6e:ff:7b:5e:
+// f9:a5:56:1e:2d:82:31:5b:f0:e2:24:e6:41:4a:1f:
+// ae:13
+// Exponent: 65537 (0x10001)
+// X509v3 extensions:
+// X509v3 Basic Constraints:
+// CA:TRUE, pathlen:2
+// X509v3 Subject Key Identifier:
+// 7C:9A:1E:7D:DF:79:54:BC:D7:CC:5E:CA:99:86:45:79:65:74:28:19
+// X509v3 Authority Key Identifier:
+// keyid:7C:9A:1E:7D:DF:79:54:BC:D7:CC:5E:CA:99:86:45:79:65:74
+// :28:19
+//
+// X509v3 Key Usage:
+// Certificate Sign, CRL Sign
+// Signature Algorithm: sha1WithRSAEncryption
+// 80:f4:5a:fb:3d:28:19:51:20:d7:d4:fb:12:97:4a:65:f2:58:
+// 35:92:77:30:6a:f1:d7:b6:51:1a:7f:9a:cd:c7:7b:03:42:ad:
+// 55:6a:00:af:f0:e1:06:c2:bd:6b:78:75:db:fe:41:11:53:4a:
+// 39:bb:9a:3a:c6:59:34:2f:2c:33:e3:b2:d6:5c:7f:dd:78:eb:
+// 71:5b:39:da:83:90:c5:31:e2:3f:23:ef:da:eb:2b:2d:77:5e:
+// de:c3:43:d2:c9:6b:59:82:ca:d5:ed:fa:a1:64:5b:cb:f1:0d:
+// 1a:62:e1:9c:e8:a7:18:70:f0:5f:17:96:f8:ed:86:db:ae:1d:
+// e0:cf:3e:5d:2e:ee:16:6d:95:2b:3c:fd:97:f3:05:5a:24:68:
+// 4d:39:b6:f8:e4:58:ba:f5:e0:26:78:51:c5:5b:5d:4e:09:e5:
+// 6c:47:8b:7a:5a:2e:89:53:e6:cc:36:5b:26:3c:f8:72:43:02:
+// 82:d2:2b:cd:f0:d3:a3:ec:13:3e:52:d5:83:3d:07:dc:1d:43:
+// 65:7a:33:02:01:a3:ce:b7:d6:60:51:3b:09:c2:23:8a:32:fe:
+// 98:19:60:62:93:85:cd:34:46:db:d5:23:0f:79:da:77:00:2a:
+// 02:6d:83:58:ce:03:77:35:e1:a3:20:93:c2:4a:a2:a4:46:1c:
+// 75:2c:1f:4d
+const unsigned char kCastRootCaDer[] = {
+ 0x30, 0x82, 0x03, 0xc5, 0x30, 0x82, 0x02, 0xad, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x01, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x75, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13,
+ 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c,
+ 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, 0x30, 0x14, 0x06,
+ 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61,
+ 0x69, 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77, 0x31, 0x13, 0x30, 0x11, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x20, 0x49, 0x6e, 0x63, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04,
+ 0x0b, 0x0c, 0x04, 0x43, 0x61, 0x73, 0x74, 0x31, 0x15, 0x30, 0x13, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0c, 0x43, 0x61, 0x73, 0x74, 0x20, 0x52,
+ 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34,
+ 0x30, 0x34, 0x30, 0x32, 0x31, 0x37, 0x33, 0x34, 0x32, 0x36, 0x5a, 0x17,
+ 0x0d, 0x33, 0x34, 0x30, 0x33, 0x32, 0x38, 0x31, 0x37, 0x33, 0x34, 0x32,
+ 0x36, 0x5a, 0x30, 0x75, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+ 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e,
+ 0x69, 0x61, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c,
+ 0x0d, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x56, 0x69,
+ 0x65, 0x77, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c,
+ 0x0a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31,
+ 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x43, 0x61,
+ 0x73, 0x74, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
+ 0x0c, 0x43, 0x61, 0x73, 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43,
+ 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f,
+ 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xba, 0xd9,
+ 0x65, 0x9d, 0xda, 0x39, 0xd3, 0xc1, 0x77, 0xf6, 0xd4, 0xd0, 0xae, 0x8f,
+ 0x58, 0x08, 0x68, 0x39, 0x4a, 0x95, 0xed, 0x70, 0xcf, 0xfd, 0x79, 0x08,
+ 0xa9, 0xaa, 0xe5, 0xe9, 0xb8, 0xa7, 0x2d, 0xa0, 0x67, 0x47, 0x8a, 0x9e,
+ 0xc9, 0xcf, 0x70, 0xb3, 0x05, 0x87, 0x69, 0x11, 0xec, 0x70, 0x98, 0x97,
+ 0xc3, 0xe6, 0xc3, 0xc3, 0xeb, 0xbd, 0xc6, 0xb0, 0x3d, 0xfc, 0x4f, 0xc1,
+ 0x5e, 0x38, 0x9f, 0xda, 0xcf, 0x73, 0x30, 0x06, 0x5b, 0x79, 0x37, 0xc1,
+ 0x5e, 0x8c, 0x87, 0x47, 0x94, 0x9a, 0x41, 0x92, 0x2a, 0xd6, 0x95, 0xc4,
+ 0x71, 0x5c, 0x27, 0x5d, 0x08, 0xb1, 0x80, 0xc6, 0x92, 0xbd, 0x1b, 0xe3,
+ 0x41, 0x97, 0xa1, 0xec, 0x75, 0x9f, 0x55, 0x9e, 0x3e, 0x9f, 0x8f, 0x1c,
+ 0xc7, 0x65, 0x64, 0x07, 0xd3, 0xb3, 0x96, 0xa1, 0x04, 0x9f, 0x91, 0xc4,
+ 0xde, 0x0a, 0x7b, 0x6c, 0xd9, 0xc8, 0xc0, 0x78, 0x31, 0xa0, 0x19, 0x42,
+ 0xa9, 0xe8, 0x83, 0xe3, 0xce, 0xfc, 0xf1, 0xce, 0xc2, 0x2e, 0x24, 0x46,
+ 0x95, 0x09, 0x19, 0xca, 0xc0, 0x46, 0xb2, 0xe5, 0x01, 0xba, 0xd7, 0x4f,
+ 0xf3, 0xbf, 0xf6, 0x69, 0xad, 0x99, 0x04, 0xfa, 0xa0, 0x07, 0x39, 0x0e,
+ 0xe6, 0xdf, 0x51, 0x47, 0x07, 0xc0, 0xe4, 0xa9, 0x5c, 0x4b, 0x94, 0xc5,
+ 0x2f, 0xb3, 0xa0, 0x30, 0x7f, 0xe7, 0x95, 0x6b, 0xb2, 0xaf, 0x32, 0x0d,
+ 0xf1, 0x8c, 0xd5, 0x6d, 0xcb, 0x7b, 0x47, 0xa7, 0x08, 0xab, 0xcb, 0x27,
+ 0xa3, 0x4d, 0xcf, 0x4a, 0x5a, 0xf1, 0x05, 0xd1, 0xf8, 0x62, 0xc5, 0x10,
+ 0x2a, 0x74, 0x69, 0xaa, 0xe6, 0x4b, 0x96, 0xfb, 0x9b, 0xd8, 0x63, 0xe4,
+ 0x58, 0x66, 0xd3, 0xad, 0x8a, 0x6e, 0xff, 0x7b, 0x5e, 0xf9, 0xa5, 0x56,
+ 0x1e, 0x2d, 0x82, 0x31, 0x5b, 0xf0, 0xe2, 0x24, 0xe6, 0x41, 0x4a, 0x1f,
+ 0xae, 0x13, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x60, 0x30, 0x5e, 0x30,
+ 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01,
+ 0xff, 0x02, 0x01, 0x02, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04,
+ 0x16, 0x04, 0x14, 0x7c, 0x9a, 0x1e, 0x7d, 0xdf, 0x79, 0x54, 0xbc, 0xd7,
+ 0xcc, 0x5e, 0xca, 0x99, 0x86, 0x45, 0x79, 0x65, 0x74, 0x28, 0x19, 0x30,
+ 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
+ 0x7c, 0x9a, 0x1e, 0x7d, 0xdf, 0x79, 0x54, 0xbc, 0xd7, 0xcc, 0x5e, 0xca,
+ 0x99, 0x86, 0x45, 0x79, 0x65, 0x74, 0x28, 0x19, 0x30, 0x0b, 0x06, 0x03,
+ 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
+ 0x03, 0x82, 0x01, 0x01, 0x00, 0x80, 0xf4, 0x5a, 0xfb, 0x3d, 0x28, 0x19,
+ 0x51, 0x20, 0xd7, 0xd4, 0xfb, 0x12, 0x97, 0x4a, 0x65, 0xf2, 0x58, 0x35,
+ 0x92, 0x77, 0x30, 0x6a, 0xf1, 0xd7, 0xb6, 0x51, 0x1a, 0x7f, 0x9a, 0xcd,
+ 0xc7, 0x7b, 0x03, 0x42, 0xad, 0x55, 0x6a, 0x00, 0xaf, 0xf0, 0xe1, 0x06,
+ 0xc2, 0xbd, 0x6b, 0x78, 0x75, 0xdb, 0xfe, 0x41, 0x11, 0x53, 0x4a, 0x39,
+ 0xbb, 0x9a, 0x3a, 0xc6, 0x59, 0x34, 0x2f, 0x2c, 0x33, 0xe3, 0xb2, 0xd6,
+ 0x5c, 0x7f, 0xdd, 0x78, 0xeb, 0x71, 0x5b, 0x39, 0xda, 0x83, 0x90, 0xc5,
+ 0x31, 0xe2, 0x3f, 0x23, 0xef, 0xda, 0xeb, 0x2b, 0x2d, 0x77, 0x5e, 0xde,
+ 0xc3, 0x43, 0xd2, 0xc9, 0x6b, 0x59, 0x82, 0xca, 0xd5, 0xed, 0xfa, 0xa1,
+ 0x64, 0x5b, 0xcb, 0xf1, 0x0d, 0x1a, 0x62, 0xe1, 0x9c, 0xe8, 0xa7, 0x18,
+ 0x70, 0xf0, 0x5f, 0x17, 0x96, 0xf8, 0xed, 0x86, 0xdb, 0xae, 0x1d, 0xe0,
+ 0xcf, 0x3e, 0x5d, 0x2e, 0xee, 0x16, 0x6d, 0x95, 0x2b, 0x3c, 0xfd, 0x97,
+ 0xf3, 0x05, 0x5a, 0x24, 0x68, 0x4d, 0x39, 0xb6, 0xf8, 0xe4, 0x58, 0xba,
+ 0xf5, 0xe0, 0x26, 0x78, 0x51, 0xc5, 0x5b, 0x5d, 0x4e, 0x09, 0xe5, 0x6c,
+ 0x47, 0x8b, 0x7a, 0x5a, 0x2e, 0x89, 0x53, 0xe6, 0xcc, 0x36, 0x5b, 0x26,
+ 0x3c, 0xf8, 0x72, 0x43, 0x02, 0x82, 0xd2, 0x2b, 0xcd, 0xf0, 0xd3, 0xa3,
+ 0xec, 0x13, 0x3e, 0x52, 0xd5, 0x83, 0x3d, 0x07, 0xdc, 0x1d, 0x43, 0x65,
+ 0x7a, 0x33, 0x02, 0x01, 0xa3, 0xce, 0xb7, 0xd6, 0x60, 0x51, 0x3b, 0x09,
+ 0xc2, 0x23, 0x8a, 0x32, 0xfe, 0x98, 0x19, 0x60, 0x62, 0x93, 0x85, 0xcd,
+ 0x34, 0x46, 0xdb, 0xd5, 0x23, 0x0f, 0x79, 0xda, 0x77, 0x00, 0x2a, 0x02,
+ 0x6d, 0x83, 0x58, 0xce, 0x03, 0x77, 0x35, 0xe1, 0xa3, 0x20, 0x93, 0xc2,
+ 0x4a, 0xa2, 0xa4, 0x46, 0x1c, 0x75, 0x2c, 0x1f, 0x4d};
diff --git a/extensions/common/cast/eureka_root_ca_der-inc.h b/extensions/common/cast/eureka_root_ca_der-inc.h
new file mode 100644
index 0000000..0ebd5e9
--- /dev/null
+++ b/extensions/common/cast/eureka_root_ca_der-inc.h
@@ -0,0 +1,146 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Certificate:
+// Data:
+// Version: 3 (0x2)
+// Serial Number: 1 (0x1)
+// Signature Algorithm: sha1WithRSAEncryption
+// Issuer: C=US, ST=California, L=Mountain View, O=Google Inc,
+// OU=Google TV, CN=Eureka Root CA
+// Validity
+// Not Before: Dec 17 22:39:33 2012 GMT
+// Not After : Dec 12 22:39:33 2032 GMT
+// Subject: C=US, ST=California, L=Mountain View, O=Google Inc,
+// OU=Google TV, CN=Eureka Root CA
+// Subject Public Key Info:
+// Public Key Algorithm: rsaEncryption
+// Public-Key: (2048 bit)
+// Modulus:
+// 00:b9:11:d0:ea:12:dc:32:e1:df:5c:33:6b:19:73:
+// 1d:9d:9e:d0:39:76:bf:a5:84:09:a6:fd:6e:6d:e9:
+// dc:8f:36:4e:e9:88:02:bd:9f:f4:e8:44:fd:4c:f5:
+// 9a:02:56:6a:47:2a:63:6c:58:45:cc:7c:66:24:dc:
+// 79:79:c3:2a:a4:b2:8b:a0:f7:a2:b5:cd:06:7e:db:
+// be:ec:0c:86:f2:0d:24:60:74:84:ca:29:23:84:02:
+// d8:a7:ed:3b:f1:ec:26:47:54:e3:b1:2d:e6:64:0f:
+// f6:72:c5:e9:98:52:17:c0:fc:f2:2c:20:c8:40:f8:
+// 47:c9:32:9e:3b:97:b1:8b:f5:98:24:70:63:66:19:
+// c1:52:e8:04:05:3d:5f:8d:bc:d8:4b:af:77:98:6f:
+// 1f:78:d1:b6:50:27:4d:e4:ec:14:69:67:1f:58:af:
+// a9:a0:11:26:3c:94:32:07:7f:d7:e9:69:1f:ae:3f:
+// 4f:63:8a:8f:89:d6:f2:19:78:5c:21:8e:b1:b6:57:
+// d8:c0:e1:ee:7d:6e:dd:f1:3a:0a:6a:f1:ba:ff:f9:
+// 83:2f:dc:b5:a4:20:17:63:36:ef:c8:62:19:cc:56:
+// ce:b2:ea:31:89:4b:78:58:c1:bf:03:13:99:e0:12:
+// f2:88:aa:9b:94:da:dd:76:79:17:1e:34:d1:0a:c4:
+// 07:45
+// Exponent: 65537 (0x10001)
+// X509v3 extensions:
+// X509v3 Subject Key Identifier:
+// 44:4E:2A:47:58:D8:B9:48:91:F6:4F:CE:74:A9:1D:32:9A:8D:8D:E9
+// X509v3 Authority Key Identifier:
+// keyid:44:4E:2A:47:58:D8:B9:48:91:F6:4F:CE:74:A9:1D:32:9A:8D
+// :8D:E9
+//
+// X509v3 Basic Constraints:
+// CA:TRUE
+// Signature Algorithm: sha1WithRSAEncryption
+// 3f:c8:26:a0:6e:5c:05:40:79:a1:98:a9:33:de:68:74:85:ee:
+// ae:b7:1c:33:59:b0:11:de:9f:f4:4f:d3:eb:51:09:7d:47:7e:
+// 6e:51:85:f4:54:cd:83:98:25:b1:ba:b0:57:ec:93:db:12:e2:
+// ec:51:49:7a:96:73:9b:c8:96:6d:85:8c:d3:e1:3c:fa:32:e2:
+// 58:0c:77:6d:87:0c:34:01:aa:30:a9:76:e0:c0:e7:db:5e:1b:
+// e9:10:30:a4:e0:09:49:26:b9:58:cd:5a:07:e5:50:75:de:9a:
+// 3b:f6:53:7e:b1:53:5e:45:27:4f:17:e3:08:33:b2:50:0a:bb:
+// f4:fc:25:97:29:de:41:75:30:fa:77:38:aa:65:8a:73:4f:ea:
+// 11:7b:eb:7c:17:60:27:0e:bc:3e:76:52:d8:8b:ed:1a:f8:eb:
+// 37:bb:11:fd:ae:70:17:0a:fe:e0:ad:06:b3:1f:69:8a:72:04:
+// c2:c0:33:0b:d6:2f:63:4c:33:11:14:b8:62:36:88:c5:03:65:
+// 01:19:a3:ef:00:bb:6f:0e:92:ff:34:1c:a1:d6:31:d0:5c:5e:
+// 9f:99:7d:c7:ca:bd:7c:72:0b:f4:5c:a5:7e:6e:04:a8:d2:99:
+// 2c:51:01:14:fe:a2:48:f0:7e:be:84:0d:b4:d3:e2:f3:0e:7d:
+// de:8b:f5:33
+const unsigned char kEurekaRootCaDer[] = {
+ 0x30, 0x82, 0x03, 0xc3, 0x30, 0x82, 0x02, 0xab, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x7c, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13,
+ 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43, 0x61, 0x6c,
+ 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, 0x30, 0x14, 0x06,
+ 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61,
+ 0x69, 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77, 0x31, 0x13, 0x30, 0x11, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+ 0x20, 0x49, 0x6e, 0x63, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04,
+ 0x0b, 0x0c, 0x09, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x54, 0x56,
+ 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0e, 0x45,
+ 0x75, 0x72, 0x65, 0x6b, 0x61, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43,
+ 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x32, 0x31, 0x32, 0x31, 0x37, 0x32,
+ 0x32, 0x33, 0x39, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x33, 0x32, 0x31, 0x32,
+ 0x31, 0x32, 0x32, 0x32, 0x33, 0x39, 0x33, 0x33, 0x5a, 0x30, 0x7c, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53,
+ 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x43,
+ 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, 0x30,
+ 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d, 0x6f, 0x75, 0x6e,
+ 0x74, 0x61, 0x69, 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77, 0x31, 0x13, 0x30,
+ 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03,
+ 0x55, 0x04, 0x0b, 0x0c, 0x09, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20,
+ 0x54, 0x56, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
+ 0x0e, 0x45, 0x75, 0x72, 0x65, 0x6b, 0x61, 0x20, 0x52, 0x6f, 0x6f, 0x74,
+ 0x20, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82,
+ 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00,
+ 0xb9, 0x11, 0xd0, 0xea, 0x12, 0xdc, 0x32, 0xe1, 0xdf, 0x5c, 0x33, 0x6b,
+ 0x19, 0x73, 0x1d, 0x9d, 0x9e, 0xd0, 0x39, 0x76, 0xbf, 0xa5, 0x84, 0x09,
+ 0xa6, 0xfd, 0x6e, 0x6d, 0xe9, 0xdc, 0x8f, 0x36, 0x4e, 0xe9, 0x88, 0x02,
+ 0xbd, 0x9f, 0xf4, 0xe8, 0x44, 0xfd, 0x4c, 0xf5, 0x9a, 0x02, 0x56, 0x6a,
+ 0x47, 0x2a, 0x63, 0x6c, 0x58, 0x45, 0xcc, 0x7c, 0x66, 0x24, 0xdc, 0x79,
+ 0x79, 0xc3, 0x2a, 0xa4, 0xb2, 0x8b, 0xa0, 0xf7, 0xa2, 0xb5, 0xcd, 0x06,
+ 0x7e, 0xdb, 0xbe, 0xec, 0x0c, 0x86, 0xf2, 0x0d, 0x24, 0x60, 0x74, 0x84,
+ 0xca, 0x29, 0x23, 0x84, 0x02, 0xd8, 0xa7, 0xed, 0x3b, 0xf1, 0xec, 0x26,
+ 0x47, 0x54, 0xe3, 0xb1, 0x2d, 0xe6, 0x64, 0x0f, 0xf6, 0x72, 0xc5, 0xe9,
+ 0x98, 0x52, 0x17, 0xc0, 0xfc, 0xf2, 0x2c, 0x20, 0xc8, 0x40, 0xf8, 0x47,
+ 0xc9, 0x32, 0x9e, 0x3b, 0x97, 0xb1, 0x8b, 0xf5, 0x98, 0x24, 0x70, 0x63,
+ 0x66, 0x19, 0xc1, 0x52, 0xe8, 0x04, 0x05, 0x3d, 0x5f, 0x8d, 0xbc, 0xd8,
+ 0x4b, 0xaf, 0x77, 0x98, 0x6f, 0x1f, 0x78, 0xd1, 0xb6, 0x50, 0x27, 0x4d,
+ 0xe4, 0xec, 0x14, 0x69, 0x67, 0x1f, 0x58, 0xaf, 0xa9, 0xa0, 0x11, 0x26,
+ 0x3c, 0x94, 0x32, 0x07, 0x7f, 0xd7, 0xe9, 0x69, 0x1f, 0xae, 0x3f, 0x4f,
+ 0x63, 0x8a, 0x8f, 0x89, 0xd6, 0xf2, 0x19, 0x78, 0x5c, 0x21, 0x8e, 0xb1,
+ 0xb6, 0x57, 0xd8, 0xc0, 0xe1, 0xee, 0x7d, 0x6e, 0xdd, 0xf1, 0x3a, 0x0a,
+ 0x6a, 0xf1, 0xba, 0xff, 0xf9, 0x83, 0x2f, 0xdc, 0xb5, 0xa4, 0x20, 0x17,
+ 0x63, 0x36, 0xef, 0xc8, 0x62, 0x19, 0xcc, 0x56, 0xce, 0xb2, 0xea, 0x31,
+ 0x89, 0x4b, 0x78, 0x58, 0xc1, 0xbf, 0x03, 0x13, 0x99, 0xe0, 0x12, 0xf2,
+ 0x88, 0xaa, 0x9b, 0x94, 0xda, 0xdd, 0x76, 0x79, 0x17, 0x1e, 0x34, 0xd1,
+ 0x0a, 0xc4, 0x07, 0x45, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30,
+ 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14,
+ 0x44, 0x4e, 0x2a, 0x47, 0x58, 0xd8, 0xb9, 0x48, 0x91, 0xf6, 0x4f, 0xce,
+ 0x74, 0xa9, 0x1d, 0x32, 0x9a, 0x8d, 0x8d, 0xe9, 0x30, 0x1f, 0x06, 0x03,
+ 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x44, 0x4e, 0x2a,
+ 0x47, 0x58, 0xd8, 0xb9, 0x48, 0x91, 0xf6, 0x4f, 0xce, 0x74, 0xa9, 0x1d,
+ 0x32, 0x9a, 0x8d, 0x8d, 0xe9, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+ 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82,
+ 0x01, 0x01, 0x00, 0x3f, 0xc8, 0x26, 0xa0, 0x6e, 0x5c, 0x05, 0x40, 0x79,
+ 0xa1, 0x98, 0xa9, 0x33, 0xde, 0x68, 0x74, 0x85, 0xee, 0xae, 0xb7, 0x1c,
+ 0x33, 0x59, 0xb0, 0x11, 0xde, 0x9f, 0xf4, 0x4f, 0xd3, 0xeb, 0x51, 0x09,
+ 0x7d, 0x47, 0x7e, 0x6e, 0x51, 0x85, 0xf4, 0x54, 0xcd, 0x83, 0x98, 0x25,
+ 0xb1, 0xba, 0xb0, 0x57, 0xec, 0x93, 0xdb, 0x12, 0xe2, 0xec, 0x51, 0x49,
+ 0x7a, 0x96, 0x73, 0x9b, 0xc8, 0x96, 0x6d, 0x85, 0x8c, 0xd3, 0xe1, 0x3c,
+ 0xfa, 0x32, 0xe2, 0x58, 0x0c, 0x77, 0x6d, 0x87, 0x0c, 0x34, 0x01, 0xaa,
+ 0x30, 0xa9, 0x76, 0xe0, 0xc0, 0xe7, 0xdb, 0x5e, 0x1b, 0xe9, 0x10, 0x30,
+ 0xa4, 0xe0, 0x09, 0x49, 0x26, 0xb9, 0x58, 0xcd, 0x5a, 0x07, 0xe5, 0x50,
+ 0x75, 0xde, 0x9a, 0x3b, 0xf6, 0x53, 0x7e, 0xb1, 0x53, 0x5e, 0x45, 0x27,
+ 0x4f, 0x17, 0xe3, 0x08, 0x33, 0xb2, 0x50, 0x0a, 0xbb, 0xf4, 0xfc, 0x25,
+ 0x97, 0x29, 0xde, 0x41, 0x75, 0x30, 0xfa, 0x77, 0x38, 0xaa, 0x65, 0x8a,
+ 0x73, 0x4f, 0xea, 0x11, 0x7b, 0xeb, 0x7c, 0x17, 0x60, 0x27, 0x0e, 0xbc,
+ 0x3e, 0x76, 0x52, 0xd8, 0x8b, 0xed, 0x1a, 0xf8, 0xeb, 0x37, 0xbb, 0x11,
+ 0xfd, 0xae, 0x70, 0x17, 0x0a, 0xfe, 0xe0, 0xad, 0x06, 0xb3, 0x1f, 0x69,
+ 0x8a, 0x72, 0x04, 0xc2, 0xc0, 0x33, 0x0b, 0xd6, 0x2f, 0x63, 0x4c, 0x33,
+ 0x11, 0x14, 0xb8, 0x62, 0x36, 0x88, 0xc5, 0x03, 0x65, 0x01, 0x19, 0xa3,
+ 0xef, 0x00, 0xbb, 0x6f, 0x0e, 0x92, 0xff, 0x34, 0x1c, 0xa1, 0xd6, 0x31,
+ 0xd0, 0x5c, 0x5e, 0x9f, 0x99, 0x7d, 0xc7, 0xca, 0xbd, 0x7c, 0x72, 0x0b,
+ 0xf4, 0x5c, 0xa5, 0x7e, 0x6e, 0x04, 0xa8, 0xd2, 0x99, 0x2c, 0x51, 0x01,
+ 0x14, 0xfe, 0xa2, 0x48, 0xf0, 0x7e, 0xbe, 0x84, 0x0d, 0xb4, 0xd3, 0xe2,
+ 0xf3, 0x0e, 0x7d, 0xde, 0x8b, 0xf5, 0x33};
diff --git a/extensions/extensions.gypi b/extensions/extensions.gypi
index d9b258a..1d18238 100644
--- a/extensions/extensions.gypi
+++ b/extensions/extensions.gypi
@@ -39,6 +39,8 @@
'common/api/sockets/sockets_manifest_permission.h',
'common/cast/cast_cert_validator.cc',
'common/cast/cast_cert_validator.h',
+ 'common/cast/cast_root_ca_cert_der-inc.h',
+ 'common/cast/eureka_root_ca_der-inc.h',
'common/common_manifest_handlers.cc',
'common/common_manifest_handlers.h',
'common/csp_validator.cc',
diff --git a/net/cert/internal/parse_certificate.cc b/net/cert/internal/parse_certificate.cc
index 74538080..738d91b 100644
--- a/net/cert/internal/parse_certificate.cc
+++ b/net/cert/internal/parse_certificate.cc
@@ -150,6 +150,10 @@
} // namespace
+ParsedCertificate::ParsedCertificate() {}
+
+ParsedCertificate::~ParsedCertificate() {}
+
ParsedTbsCertificate::ParsedTbsCertificate() {}
ParsedTbsCertificate::~ParsedTbsCertificate() {}
diff --git a/net/cert/internal/parse_certificate.h b/net/cert/internal/parse_certificate.h
index eca692dd..d48c07c 100644
--- a/net/cert/internal/parse_certificate.h
+++ b/net/cert/internal/parse_certificate.h
@@ -112,6 +112,9 @@
// ParsedCertificate is expected to be filled by ParseCertificate(), so
// subsequent field descriptions are in terms of what ParseCertificate() sets.
struct NET_EXPORT ParsedCertificate {
+ ParsedCertificate();
+ ~ParsedCertificate();
+
// Corresponds with "tbsCertificate" from RFC 5280:
// tbsCertificate TBSCertificate,
//
diff --git a/net/cert/internal/verify_certificate_chain.cc b/net/cert/internal/verify_certificate_chain.cc
index a6e0f4a8..506fb43 100644
--- a/net/cert/internal/verify_certificate_chain.cc
+++ b/net/cert/internal/verify_certificate_chain.cc
@@ -198,24 +198,6 @@
return NameMatches(cert.tbs.subject_tlv, cert.tbs.issuer_tlv);
}
-// Finds a trust anchor that matches |name| in |trust_store| or returns
-// nullptr. The returned pointer references data in |trust_store|.
-//
-// TODO(eroman): This implementation is linear in the size of the trust store,
-// and also presumes that all names are unique. In practice it is possible to
-// have multiple SPKIs with the same name. Also this mechanism of
-// searching is fairly primitive, and does not take advantage of other
-// properties like the authority key id.
-WARN_UNUSED_RESULT const TrustAnchor* FindTrustAnchorByName(
- const TrustStore& trust_store,
- const der::Input& name) {
- for (const auto& anchor : trust_store.anchors) {
- if (NameMatches(name, der::Input(&anchor.name)))
- return &anchor;
- }
- return nullptr;
-}
-
// Returns true if |cert| is valid at time |time|.
//
// The certificate's validity requirements are described by RFC 5280 section
@@ -273,9 +255,15 @@
// This function corresponds to RFC 5280 section 6.1.3's "Basic Certificate
// Processing" procedure.
+//
+// |skip_issuer_checks| controls whether the function will skip:
+// - Checking that |cert|'s signature using |working_spki|
+// - Checkinging that |cert|'s issuer matches |working_issuer_name|
+// This should be set to true only when verifying a trusted root certificate.
WARN_UNUSED_RESULT bool BasicCertificateProcessing(
const FullyParsedCert& cert,
bool is_target_cert,
+ bool skip_issuer_checks,
const SignaturePolicy* signature_policy,
const der::GeneralizedTime& time,
const der::Input& working_spki,
@@ -288,12 +276,14 @@
if (!VerifySignatureAlgorithmsMatch(cert))
return false;
- // Verify the digital signature using the previous certificate's (or trust
- // anchor's) key (RFC 5280 section 6.1.3 step a.1).
- if (!VerifySignedData(
- *cert.signature_algorithm, cert.cert.tbs_certificate_tlv,
- cert.cert.signature_value, working_spki, signature_policy)) {
- return false;
+ // Verify the digital signature using the previous certificate's key (RFC
+ // 5280 section 6.1.3 step a.1).
+ if (!skip_issuer_checks) {
+ if (!VerifySignedData(
+ *cert.signature_algorithm, cert.cert.tbs_certificate_tlv,
+ cert.cert.signature_value, working_spki, signature_policy)) {
+ return false;
+ }
}
// Check the time range for the certificate's validity, ensuring it is valid
@@ -304,10 +294,12 @@
// TODO(eroman): Check revocation (RFC 5280 section 6.1.3 step a.3)
- // Verify the certificate's issuer name matches the issuing certificate's (or
- // trust anchor's) subject name. (RFC 5280 section 6.1.3 step a.4)
- if (!NameMatches(cert.tbs.issuer_tlv, working_issuer_name))
- return false;
+ // Verify the certificate's issuer name matches the issuing certificate's
+ // subject name. (RFC 5280 section 6.1.3 step a.4)
+ if (!skip_issuer_checks) {
+ if (!NameMatches(cert.tbs.issuer_tlv, working_issuer_name))
+ return false;
+ }
// Name constraints (RFC 5280 section 6.1.3 step b & c)
// If certificate i is self-issued and it is not the final certificate in the
@@ -502,22 +494,123 @@
} // namespace
+TrustAnchor::TrustAnchor() {}
TrustAnchor::~TrustAnchor() {}
+std::unique_ptr<TrustAnchor> TrustAnchor::CreateFromCertificateData(
+ const uint8_t* data,
+ size_t length,
+ DataSource source) {
+ std::unique_ptr<TrustAnchor> result(new TrustAnchor);
+
+ switch (source) {
+ case DataSource::INTERNAL_COPY:
+ result->cert_data_.assign(data, data + length);
+ result->cert_ =
+ der::Input(result->cert_data_.data(), result->cert_data_.size());
+ break;
+ case DataSource::EXTERNAL_REFERENCE:
+ result->cert_ = der::Input(data, length);
+ break;
+ }
+
+ // Parse the certificate to get its name.
+ ParsedCertificate cert;
+ if (!ParseCertificate(result->cert(), &cert))
+ return nullptr;
+
+ ParsedTbsCertificate tbs;
+ if (!ParseTbsCertificate(cert.tbs_certificate_tlv, &tbs))
+ return nullptr;
+
+ result->name_ = tbs.subject_tlv;
+
+ // TODO(eroman): If adding a self-signed certificate, check that its
+ // signature is correct? This check will not otherwise be done during
+ // verification.
+
+ return result;
+}
+
+bool TrustAnchor::MatchesName(const der::Input& name) const {
+ return NameMatches(name, name_);
+}
+
TrustStore::TrustStore() {}
-TrustStore::TrustStore(const TrustStore& other) = default;
TrustStore::~TrustStore() {}
+void TrustStore::Clear() {
+ anchors_.clear();
+}
+
+bool TrustStore::AddTrustedCertificate(const uint8_t* data, size_t length) {
+ return AddTrustedCertificate(data, length,
+ TrustAnchor::DataSource::INTERNAL_COPY);
+}
+
+bool TrustStore::AddTrustedCertificate(const base::StringPiece& data) {
+ return AddTrustedCertificate(reinterpret_cast<const uint8_t*>(data.data()),
+ data.size());
+}
+
+bool TrustStore::AddTrustedCertificateWithoutCopying(const uint8_t* data,
+ size_t length) {
+ return AddTrustedCertificate(data, length,
+ TrustAnchor::DataSource::EXTERNAL_REFERENCE);
+}
+
+const TrustAnchor* TrustStore::FindTrustAnchorByName(
+ const der::Input& name) const {
+ for (const auto& anchor : anchors_) {
+ if (anchor->MatchesName(name)) {
+ return anchor.get();
+ }
+ }
+ return nullptr;
+}
+
+bool TrustStore::IsTrustedCertificate(const der::Input& cert_der) const {
+ for (const auto& anchor : anchors_) {
+ if (anchor->cert() == cert_der)
+ return true;
+ }
+ return false;
+}
+
+bool TrustStore::AddTrustedCertificate(const uint8_t* data,
+ size_t length,
+ TrustAnchor::DataSource source) {
+ auto anchor = TrustAnchor::CreateFromCertificateData(data, length, source);
+ if (!anchor)
+ return false;
+ anchors_.push_back(std::move(anchor));
+ return true;
+}
+
+// TODO(eroman): Move this into existing anonymous namespace.
+namespace {
+
// This implementation is structured to mimic the description of certificate
// path verification given by RFC 5280 section 6.1.
-bool VerifyCertificateChain(const std::vector<der::Input>& certs_der,
- const TrustStore& trust_store,
- const SignaturePolicy* signature_policy,
- const der::GeneralizedTime& time) {
+//
+// Unlike RFC 5280, the trust anchor is specified as the root certificate in
+// the chain. This root certificate is assumed to be trusted, and neither its
+// signature nor issuer name are verified. (It needn't be self-signed).
+bool VerifyCertificateChainAssumingTrustedRoot(
+ const std::vector<der::Input>& certs_der,
+ // The trust store is only used for assertions.
+ const TrustStore& trust_store,
+ const SignaturePolicy* signature_policy,
+ const der::GeneralizedTime& time) {
// An empty chain is necessarily invalid.
if (certs_der.empty())
return false;
+ // IMPORTANT: the assumption being made is that the root certificate in
+ // the given path is the trust anchor (and has already been verified as
+ // such).
+ DCHECK(trust_store.IsTrustedCertificate(certs_der.back()));
+
// Will contain a NameConstraints for each previous cert in the chain which
// had nameConstraints. This corresponds to the permitted_subtrees and
// excluded_subtrees state variables from RFC 5280.
@@ -536,18 +629,14 @@
// 5280 section 6.1.2:
//
// working_public_key: the public key used to verify the
- // signature of a certificate. The working_public_key is
- // initialized from the trusted public key provided in the trust
- // anchor information.
+ // signature of a certificate.
der::Input working_spki;
// |working_issuer_name| corresponds with the same named variable in RFC 5280
// section 6.1.2:
//
// working_issuer_name: the issuer distinguished name expected
- // in the next certificate in the chain. The
- // working_issuer_name is initialized to the trusted issuer name
- // provided in the trust anchor information.
+ // in the next certificate in the chain.
der::Input working_issuer_name;
// |max_path_length| corresponds with the same named variable in RFC 5280
@@ -565,39 +654,34 @@
//
// Note that |i| uses 0-based indexing whereas in RFC 5280 it is 1-based.
//
- // * i=0 : Certificate signed by a trust anchor.
+ // * i=0 : Trust anchor.
// * i=N-1 : Target certificate.
for (size_t i = 0; i < certs_der.size(); ++i) {
const size_t index_into_certs_der = certs_der.size() - i - 1;
+
+ // |is_target_cert| is true if the current certificate is the target
+ // certificate being verified. The target certificate isn't necessarily an
+ // end-entity certificate.
const bool is_target_cert = index_into_certs_der == 0;
+ // |is_trust_anchor| is true if the current certificate is the trust
+ // anchor. This certificate is implicitly trusted.
+ const bool is_trust_anchor = i == 0;
+
// Parse the current certificate into |cert|.
FullyParsedCert cert;
const der::Input& cert_der = certs_der[index_into_certs_der];
if (!FullyParseCertificate(cert_der, &cert))
return false;
- // When processing the first certificate, initialize |working_spki|
- // and |working_issuer_name| to the trust anchor per RFC 5280 section 6.1.2.
- // This is done inside the loop in order to have access to the parsed
- // certificate.
- if (i == 0) {
- const TrustAnchor* trust_anchor =
- FindTrustAnchorByName(trust_store, cert.tbs.issuer_tlv);
- if (!trust_anchor)
- return false;
- working_spki = der::Input(&trust_anchor->spki);
- working_issuer_name = der::Input(&trust_anchor->name);
- }
-
// Per RFC 5280 section 6.1:
// * Do basic processing for each certificate
// * If it is the last certificate in the path (target certificate)
// - Then run "Wrap up"
// - Otherwise run "Prepare for Next cert"
- if (!BasicCertificateProcessing(cert, is_target_cert, signature_policy,
- time, working_spki, working_issuer_name,
- name_constraints_list)) {
+ if (!BasicCertificateProcessing(
+ cert, is_target_cert, is_trust_anchor, signature_policy, time,
+ working_spki, working_issuer_name, name_constraints_list)) {
return false;
}
if (!is_target_cert) {
@@ -620,4 +704,60 @@
return true;
}
+// TODO(eroman): This function is a temporary hack in the absence of full
+// path building. It may insert 1 certificate at the root of the
+// chain to ensure that the path's root certificate is a trust anchor.
+//
+// Beyond this no other verification is done on the chain. The caller is
+// responsible for verifying the subsequent chain's correctness.
+WARN_UNUSED_RESULT bool BuildSimplePathToTrustAnchor(
+ const std::vector<der::Input>& certs_der,
+ const TrustStore& trust_store,
+ std::vector<der::Input>* certs_der_trusted_root) {
+ // Copy the input chain.
+ *certs_der_trusted_root = certs_der;
+
+ if (certs_der.empty())
+ return false;
+
+ // Check if the current root certificate is trusted. If it is then no
+ // extra work is needed.
+ if (trust_store.IsTrustedCertificate(certs_der_trusted_root->back()))
+ return true;
+
+ // Otherwise if it is not trusted, check whether its issuer is trusted. If
+ // so, make *that* trusted certificate the root. If the issuer is not in
+ // the trust store then give up and fail (this is not full path building).
+ ParsedCertificate cert;
+ ParsedTbsCertificate tbs;
+ if (!ParseCertificate(certs_der.back(), &cert) ||
+ !ParseTbsCertificate(cert.tbs_certificate_tlv, &tbs)) {
+ return false;
+ }
+
+ auto trust_anchor = trust_store.FindTrustAnchorByName(tbs.issuer_tlv);
+ if (!trust_anchor)
+ return false;
+ certs_der_trusted_root->push_back(trust_anchor->cert());
+ return true;
+}
+
+} // namespace
+
+bool VerifyCertificateChain(const std::vector<der::Input>& certs_der,
+ const TrustStore& trust_store,
+ const SignaturePolicy* signature_policy,
+ const der::GeneralizedTime& time) {
+ // Modify the certificate chain so that its root is a trusted certificate.
+ std::vector<der::Input> certs_der_trusted_root;
+ if (!BuildSimplePathToTrustAnchor(certs_der, trust_store,
+ &certs_der_trusted_root)) {
+ return false;
+ }
+
+ // Verify the chain.
+ return VerifyCertificateChainAssumingTrustedRoot(
+ certs_der_trusted_root, trust_store, signature_policy, time);
+}
+
} // namespace net
diff --git a/net/cert/internal/verify_certificate_chain.h b/net/cert/internal/verify_certificate_chain.h
index 0ef8cba..2b4a7ab 100644
--- a/net/cert/internal/verify_certificate_chain.h
+++ b/net/cert/internal/verify_certificate_chain.h
@@ -13,34 +13,107 @@
#include "base/compiler_specific.h"
#include "net/base/net_export.h"
+#include "net/cert/internal/parse_certificate.h"
+#include "net/der/input.h"
namespace net {
namespace der {
-class Input;
struct GeneralizedTime;
}
class SignaturePolicy;
-struct NET_EXPORT TrustAnchor {
+// Represents a trust anchor (i.e. a trusted root certificate).
+class NET_EXPORT TrustAnchor {
+ public:
+ // The certificate data for this trust anchor may either be owned internally
+ // (INTERNAL_COPY) or owned externally (EXTERNAL_REFERENCE). When it is
+ // owned internally the data is held by |cert_data_|
+ enum class DataSource {
+ INTERNAL_COPY,
+ EXTERNAL_REFERENCE,
+ };
+
+ TrustAnchor();
~TrustAnchor();
- // DER-encoded SubjectPublicKeyInfo for the trusted key.
- std::string spki;
+ // Creates a TrustAnchor given a DER-encoded certificate. Returns nullptr on
+ // failure. Failure will occur if the certificate data cannot be parsed to
+ // find a subject.
+ //
+ // The provided certificate data is either copied, or aliased, depending on
+ // the value of |source|. See the comments for DataSource for details.
+ static std::unique_ptr<TrustAnchor> CreateFromCertificateData(
+ const uint8_t* data,
+ size_t length,
+ DataSource source);
- // DER-encoded "Name" corresponding to the key.
- std::string name;
+ // Returns true if the trust anchor matches |name|. In other words, returns
+ // true if the certificate's subject matches |name|.
+ bool MatchesName(const der::Input& name) const;
+
+ // Returns the DER-encoded certificate data for this trust anchor.
+ const der::Input& cert() const { return cert_; }
+
+ private:
+ // The backing store for the certificate data. This is only applicable when
+ // the trust anchor was initialized using DataSource::INTERNAL_COPY.
+ std::vector<uint8_t> cert_data_;
+
+ // Note that the backing data for |cert_| and |name_| may come either form
+ // |cert_data_| or some external buffer (depending on how the anchor was
+ // created).
+
+ // Points to the raw certificate DER.
+ der::Input cert_;
+
+ // Points to the subject TLV for the certificate.
+ der::Input name_;
+
+ DISALLOW_COPY_AND_ASSIGN(TrustAnchor);
};
-// A very simple implementation of a TrustStore, which contains mappings from
-// names to trusted public keys.
-struct NET_EXPORT TrustStore {
+// A very simple implementation of a TrustStore, which contains a set of
+// trusted certificates.
+class NET_EXPORT TrustStore {
+ public:
TrustStore();
- TrustStore(const TrustStore& other);
~TrustStore();
- std::vector<TrustAnchor> anchors;
+ // Empties the trust store, resetting it to original state.
+ void Clear();
+
+ // Adds a trusted certificate to the store. The trust store makes a copy of
+ // the provided certificate data.
+ bool AddTrustedCertificate(const uint8_t* data,
+ size_t length) WARN_UNUSED_RESULT;
+ bool AddTrustedCertificate(const base::StringPiece& data) WARN_UNUSED_RESULT;
+
+ // This function is the same as AddTrustedCertificate() except the underlying
+ // data is not copied. The caller is responsible for ensuring that the data
+ // pointer remains alive and is not mutated for the lifetime of the
+ // TrustStore.
+ bool AddTrustedCertificateWithoutCopying(const uint8_t* data,
+ size_t length) WARN_UNUSED_RESULT;
+
+ // Returns the trust anchor that matches |name|, or nullptr if there is none.
+ // TODO(eroman): There may be multiple matches.
+ const TrustAnchor* FindTrustAnchorByName(const der::Input& name) const
+ WARN_UNUSED_RESULT;
+
+ // Returns true if |cert_der| matches a certificate in the TrustStore.
+ bool IsTrustedCertificate(const der::Input& cert_der) const
+ WARN_UNUSED_RESULT;
+
+ private:
+ bool AddTrustedCertificate(const uint8_t* data,
+ size_t length,
+ TrustAnchor::DataSource source) WARN_UNUSED_RESULT;
+
+ std::vector<std::unique_ptr<TrustAnchor>> anchors_;
+
+ DISALLOW_COPY_AND_ASSIGN(TrustStore);
};
// VerifyCertificateChain() verifies a certificate path (chain) based on the
diff --git a/net/cert/internal/verify_certificate_chain_pkits_unittest.cc b/net/cert/internal/verify_certificate_chain_pkits_unittest.cc
index 5993b9c1..60656370 100644
--- a/net/cert/internal/verify_certificate_chain_pkits_unittest.cc
+++ b/net/cert/internal/verify_certificate_chain_pkits_unittest.cc
@@ -43,18 +43,6 @@
namespace {
-// Adds the certificate |cert_der| as a trust anchor to |trust_store|.
-void AddCertificateToTrustStore(const std::string& cert_der,
- TrustStore* trust_store) {
- ParsedCertificate cert;
- ASSERT_TRUE(ParseCertificate(der::Input(&cert_der), &cert));
-
- ParsedTbsCertificate tbs;
- ASSERT_TRUE(ParseTbsCertificate(cert.tbs_certificate_tlv, &tbs));
- TrustAnchor anchor = {tbs.spki_tlv.AsString(), tbs.subject_tlv.AsString()};
- trust_store->anchors.push_back(anchor);
-}
-
class VerifyCertificateChainPkitsTestDelegate {
public:
static bool Verify(std::vector<std::string> cert_ders,
@@ -65,7 +53,7 @@
}
// First entry in the PKITS chain is the trust anchor.
TrustStore trust_store;
- AddCertificateToTrustStore(cert_ders[0], &trust_store);
+ EXPECT_TRUE(trust_store.AddTrustedCertificate(cert_ders[0]));
// PKITS lists chains from trust anchor to target, VerifyCertificateChain
// takes them starting with the target and not including the trust anchor.
diff --git a/net/cert/internal/verify_certificate_chain_unittest.cc b/net/cert/internal/verify_certificate_chain_unittest.cc
index b172a338..a4443ca 100644
--- a/net/cert/internal/verify_certificate_chain_unittest.cc
+++ b/net/cert/internal/verify_certificate_chain_unittest.cc
@@ -39,18 +39,6 @@
return file_data;
}
-// Adds the certificate |cert_der| as a trust anchor to |trust_store|.
-void AddCertificateToTrustStore(const std::string& cert_der,
- TrustStore* trust_store) {
- ParsedCertificate cert;
- ASSERT_TRUE(ParseCertificate(der::Input(&cert_der), &cert));
-
- ParsedTbsCertificate tbs;
- ASSERT_TRUE(ParseTbsCertificate(cert.tbs_certificate_tlv, &tbs));
- TrustAnchor anchor = {tbs.spki_tlv.AsString(), tbs.subject_tlv.AsString()};
- trust_store->anchors.push_back(anchor);
-}
-
// Reads a test case from |file_name|. Test cases are comprised of a
// certificate chain, trust store, a timestamp to validate at, and the
// expected result of verification.
@@ -60,7 +48,7 @@
der::GeneralizedTime* time,
bool* verify_result) {
chain->clear();
- *trust_store = TrustStore();
+ trust_store->Clear();
std::string file_data = ReadTestFileToString(file_name);
@@ -87,7 +75,7 @@
if (block_type == kCertificateHeader) {
chain->push_back(block_data);
} else if (block_type == kTrustedCertificateHeader) {
- AddCertificateToTrustStore(block_data, trust_store);
+ ASSERT_TRUE(trust_store->AddTrustedCertificate(block_data));
} else if (block_type == kTimeHeader) {
ASSERT_FALSE(has_time) << "Duplicate " << kTimeHeader;
has_time = true;
@@ -197,6 +185,10 @@
RunTest("expired-target-notBefore.pem");
}
+TEST(VerifyCertificateChainTest, ExpiredRoot) {
+ RunTest("expired-root.pem");
+}
+
TEST(VerifyCertificateChainTest, TargetNotEndEntity) {
RunTest("target-not-end-entity.pem");
}
@@ -221,6 +213,14 @@
RunTest("issuer-and-subject-not-byte-for-byte-equal-anchor.pem");
}
+TEST(VerifyCertificateChainTest, ViolatesPathlen1Root) {
+ RunTest("violates-pathlen-1-root.pem");
+}
+
+TEST(VerifyCertificateChainTest, NonSelfSignedRoot) {
+ RunTest("non-self-signed-root.pem");
+}
+
// Tests that verifying a chain with no certificates fails.
TEST(VerifyCertificateChainTest, EmptyChainIsInvalid) {
TrustStore trust_store;
diff --git a/net/data/verify_certificate_chain_unittest/expired-root.pem b/net/data/verify_certificate_chain_unittest/expired-root.pem
new file mode 100644
index 0000000..5e9ffcf
--- /dev/null
+++ b/net/data/verify_certificate_chain_unittest/expired-root.pem
@@ -0,0 +1,280 @@
+[Created by: generate-expired-root.py]
+
+Certificate chain with 1 intermediary, where the root certificate is expired
+(violates validity.notAfter). Verification is expected to fail.
+
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=Intermediary
+ Validity
+ Not Before: Jan 1 12:00:00 2015 GMT
+ Not After : Jan 1 12:00:00 2016 GMT
+ Subject: CN=Target
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c2:5a:d7:49:58:e0:e3:06:4c:d0:8d:83:ad:7a:
+ ff:86:7c:0e:00:26:64:44:8a:cb:38:bd:95:8e:b1:
+ 7f:7c:48:7f:02:ef:7d:f9:b4:76:76:eb:5a:1d:71:
+ 99:3a:c8:66:1a:c8:fb:24:d3:e8:9c:af:3b:5c:b5:
+ 10:f0:32:7c:46:87:9a:3f:f6:57:6a:45:5c:18:6e:
+ 92:54:54:16:4e:17:79:1c:a1:05:7c:21:3c:dc:89:
+ 23:5d:aa:f9:1e:a1:8c:9b:9f:d7:a0:f3:c3:23:f0:
+ f4:b5:12:ac:d3:57:cb:bb:f9:8e:0d:d8:e9:d5:bd:
+ 71:2b:3e:38:d1:fe:f0:17:cb:f0:ce:23:8f:8a:ee:
+ 56:4d:94:18:31:c3:1d:74:07:57:a4:f7:07:e8:b3:
+ a4:60:53:38:96:83:f7:59:cf:03:f9:38:3c:35:87:
+ 6a:71:92:8a:1b:4f:7e:f0:49:76:ba:65:42:87:fe:
+ b2:21:e1:17:d6:98:50:36:5a:7f:fe:8d:f6:bf:ab:
+ 46:63:fc:57:e8:57:c5:90:9b:27:07:30:fa:26:1d:
+ 13:eb:f2:e1:b0:99:f9:55:39:76:0f:ca:a4:31:85:
+ c6:62:df:53:cd:3e:df:bf:83:1d:a9:07:b1:a2:8a:
+ be:43:f2:05:1e:f9:ca:28:2e:81:39:fa:2c:74:c5:
+ 7c:b1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 14:B3:FA:87:AB:1D:54:2D:2B:B8:C4:5D:33:57:C5:52:F4:15:B8:20
+ X509v3 Authority Key Identifier:
+ keyid:ED:CC:99:FA:9D:D2:85:7E:0E:02:42:8E:72:48:C3:F4:29:4B:95:D2
+
+ Authority Information Access:
+ CA Issuers - URI:http://url-for-aia/Intermediary.cer
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://url-for-crl/Intermediary.crl
+
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ Signature Algorithm: sha256WithRSAEncryption
+ 42:13:4f:10:c0:69:c9:ad:88:94:2d:df:24:e6:47:6c:d3:07:
+ 33:75:77:ba:c8:40:f4:28:1f:7a:0a:49:14:93:5f:d7:6e:91:
+ 49:22:a3:cb:f0:52:f9:d6:22:90:ef:62:79:3d:cc:e5:2f:d0:
+ c9:c3:0e:b0:54:06:6c:31:7e:f3:9e:48:be:02:c8:f3:60:cb:
+ d7:5b:65:f6:82:41:fa:b4:19:34:e2:82:9c:0a:02:ee:ec:2a:
+ 53:6d:25:49:19:9a:ce:1a:6c:c4:49:e2:3b:08:fb:6f:05:00:
+ 65:d6:64:29:a9:c5:9f:83:27:af:49:a8:b8:14:de:e0:43:c6:
+ b4:c2:ad:49:55:d5:58:42:50:cb:20:54:df:1e:9b:0a:9d:d3:
+ a0:85:4d:a2:5c:cb:07:24:1c:f0:91:d2:89:54:d1:69:7a:68:
+ 05:6a:3c:80:00:e5:7d:6d:9a:0b:37:0d:d0:6b:5e:61:d4:04:
+ 37:73:41:ae:48:10:0a:3b:b1:d4:67:31:19:19:43:d2:22:f4:
+ 29:72:cd:8d:97:5b:f8:11:09:5b:32:07:56:fb:f4:d7:66:cc:
+ 72:e4:db:f6:1d:53:70:0e:bf:4c:c2:0f:61:07:a9:f3:1d:5f:
+ 03:f9:1e:9c:96:f6:49:1a:b8:51:1d:16:22:1a:f5:2b:ac:da:
+ ce:5a:a6:38
+-----BEGIN CERTIFICATE-----
+MIIDjTCCAnWgAwIBAgIBATANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAxJbnRl
+cm1lZGlhcnkwHhcNMTUwMTAxMTIwMDAwWhcNMTYwMTAxMTIwMDAwWjARMQ8wDQYD
+VQQDDAZUYXJnZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCWtdJ
+WODjBkzQjYOtev+GfA4AJmREiss4vZWOsX98SH8C7335tHZ261odcZk6yGYayPsk
+0+icrztctRDwMnxGh5o/9ldqRVwYbpJUVBZOF3kcoQV8ITzciSNdqvkeoYybn9eg
+88Mj8PS1EqzTV8u7+Y4N2OnVvXErPjjR/vAXy/DOI4+K7lZNlBgxwx10B1ek9wfo
+s6RgUziWg/dZzwP5ODw1h2pxkoobT37wSXa6ZUKH/rIh4RfWmFA2Wn/+jfa/q0Zj
+/FfoV8WQmycHMPomHRPr8uGwmflVOXYPyqQxhcZi31PNPt+/gx2pB7Giir5D8gUe
++cooLoE5+ix0xXyxAgMBAAGjgekwgeYwHQYDVR0OBBYEFBSz+oerHVQtK7jEXTNX
+xVL0FbggMB8GA1UdIwQYMBaAFO3Mmfqd0oV+DgJCjnJIw/QpS5XSMD8GCCsGAQUF
+BwEBBDMwMTAvBggrBgEFBQcwAoYjaHR0cDovL3VybC1mb3ItYWlhL0ludGVybWVk
+aWFyeS5jZXIwNAYDVR0fBC0wKzApoCegJYYjaHR0cDovL3VybC1mb3ItY3JsL0lu
+dGVybWVkaWFyeS5jcmwwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUF
+BwMBBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAQhNPEMBpya2IlC3fJOZH
+bNMHM3V3ushA9CgfegpJFJNf126RSSKjy/BS+dYikO9ieT3M5S/QycMOsFQGbDF+
+855IvgLI82DL11tl9oJB+rQZNOKCnAoC7uwqU20lSRmazhpsxEniOwj7bwUAZdZk
+KanFn4Mnr0mouBTe4EPGtMKtSVXVWEJQyyBU3x6bCp3ToIVNolzLByQc8JHSiVTR
+aXpoBWo8gADlfW2aCzcN0GteYdQEN3NBrkgQCjux1GcxGRlD0iL0KXLNjZdb+BEJ
+WzIHVvv012bMcuTb9h1TcA6/TMIPYQep8x1fA/kenJb2SRq4UR0WIhr1K6zazlqm
+OA==
+-----END CERTIFICATE-----
+
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=Root
+ Validity
+ Not Before: Jan 1 12:00:00 2015 GMT
+ Not After : Jan 1 12:00:00 2016 GMT
+ Subject: CN=Intermediary
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:b0:4e:34:a2:37:40:52:cd:58:5e:d8:18:40:f2:
+ 23:9e:a8:78:10:18:db:5b:87:a3:e2:e3:c8:a5:50:
+ b7:c3:1c:fa:e5:77:7f:93:b3:44:2a:90:60:39:81:
+ a4:c4:63:e0:3d:8a:d8:36:c8:5d:df:04:01:c1:f1:
+ b5:65:12:3d:f5:22:f9:f5:ff:c5:60:2a:48:39:90:
+ 69:df:08:9f:bc:07:6c:c6:ab:3f:e4:2d:05:b5:b3:
+ 11:9e:4d:5a:8d:3c:64:3f:1e:7d:df:05:1c:e2:e4:
+ b7:d9:42:36:cb:86:df:53:2a:ea:51:2b:53:f8:3a:
+ 07:5a:08:8b:df:fb:9d:2f:1f:94:a9:fb:07:93:87:
+ 20:ee:e6:ae:d9:a5:2e:1a:eb:d9:67:0e:ce:8f:7e:
+ 0b:be:3a:ca:b2:9c:40:38:54:5c:35:99:ac:07:12:
+ 3e:00:a3:39:07:76:e1:fa:df:7b:81:59:0b:a3:8e:
+ 4e:42:b7:1e:09:04:e2:0c:ea:eb:d5:c0:da:dd:6f:
+ f0:6e:6a:34:2a:38:ae:4f:b4:f3:4f:06:17:c3:83:
+ 0a:66:e8:c6:8a:54:71:86:0b:8b:39:3b:73:07:d2:
+ 0b:dc:4c:86:79:da:86:44:25:3d:dc:f1:38:eb:22:
+ ce:92:df:8b:9b:ff:47:eb:7a:28:0a:91:cd:ba:30:
+ 77:7d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ ED:CC:99:FA:9D:D2:85:7E:0E:02:42:8E:72:48:C3:F4:29:4B:95:D2
+ X509v3 Authority Key Identifier:
+ keyid:62:81:A1:85:84:13:F2:70:79:BD:48:5B:29:88:E0:F1:27:35:41:F7
+
+ Authority Information Access:
+ CA Issuers - URI:http://url-for-aia/Root.cer
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://url-for-crl/Root.crl
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha256WithRSAEncryption
+ 02:82:8b:cf:81:89:f2:15:d3:a7:a6:30:c8:2a:c8:32:c5:95:
+ 7c:18:60:2e:51:48:c5:26:47:b8:5e:49:17:b4:aa:87:f7:8b:
+ 22:73:2a:81:20:1d:1c:54:b7:7b:91:e1:48:40:7a:19:13:05:
+ 05:6e:e4:21:75:d7:a7:a0:54:bf:da:18:a1:52:08:95:0a:c5:
+ e0:36:f3:6d:ab:ed:21:69:e1:e7:4d:8f:85:85:22:ac:7b:b3:
+ 7f:3f:1a:7e:44:be:06:ee:0b:f5:89:53:e3:d1:fa:f7:51:00:
+ 7c:61:d2:5e:48:ab:4c:bb:47:03:a2:d4:6a:78:02:7e:33:5a:
+ b9:7c:14:12:5a:c2:bb:66:91:4f:21:cb:c0:b7:80:72:4b:28:
+ 6c:d9:7b:02:fa:04:26:f2:de:2a:54:7d:69:89:88:f3:b9:10:
+ ab:0a:07:fa:f8:7c:1e:bb:45:0f:4f:de:2e:36:3e:a4:63:b0:
+ 71:a1:be:2b:dd:0c:fa:0b:97:f0:ad:56:b0:dd:76:51:e7:45:
+ aa:a3:82:cd:77:5a:07:3a:e5:bc:fd:37:8f:52:ee:e0:de:ac:
+ 99:44:94:65:7d:b1:30:89:4d:12:da:73:29:06:a9:28:42:5d:
+ 1f:1a:a7:44:f3:77:5b:99:4a:ca:a6:dd:3a:cd:a1:16:76:11:
+ 16:44:34:c0
+-----BEGIN CERTIFICATE-----
+MIIDbTCCAlWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290
+MB4XDTE1MDEwMTEyMDAwMFoXDTE2MDEwMTEyMDAwMFowFzEVMBMGA1UEAwwMSW50
+ZXJtZWRpYXJ5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsE40ojdA
+Us1YXtgYQPIjnqh4EBjbW4ej4uPIpVC3wxz65Xd/k7NEKpBgOYGkxGPgPYrYNshd
+3wQBwfG1ZRI99SL59f/FYCpIOZBp3wifvAdsxqs/5C0FtbMRnk1ajTxkPx593wUc
+4uS32UI2y4bfUyrqUStT+DoHWgiL3/udLx+UqfsHk4cg7uau2aUuGuvZZw7Oj34L
+vjrKspxAOFRcNZmsBxI+AKM5B3bh+t97gVkLo45OQrceCQTiDOrr1cDa3W/wbmo0
+KjiuT7TzTwYXw4MKZujGilRxhguLOTtzB9IL3EyGedqGRCU93PE46yLOkt+Lm/9H
+63ooCpHNujB3fQIDAQABo4HLMIHIMB0GA1UdDgQWBBTtzJn6ndKFfg4CQo5ySMP0
+KUuV0jAfBgNVHSMEGDAWgBRigaGFhBPycHm9SFspiODxJzVB9zA3BggrBgEFBQcB
+AQQrMCkwJwYIKwYBBQUHMAKGG2h0dHA6Ly91cmwtZm9yLWFpYS9Sb290LmNlcjAs
+BgNVHR8EJTAjMCGgH6AdhhtodHRwOi8vdXJsLWZvci1jcmwvUm9vdC5jcmwwDgYD
+VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
+AAKCi8+BifIV06emMMgqyDLFlXwYYC5RSMUmR7heSRe0qof3iyJzKoEgHRxUt3uR
+4UhAehkTBQVu5CF116egVL/aGKFSCJUKxeA2822r7SFp4edNj4WFIqx7s38/Gn5E
+vgbuC/WJU+PR+vdRAHxh0l5Iq0y7RwOi1Gp4An4zWrl8FBJawrtmkU8hy8C3gHJL
+KGzZewL6BCby3ipUfWmJiPO5EKsKB/r4fB67RQ9P3i42PqRjsHGhvivdDPoLl/Ct
+VrDddlHnRaqjgs13Wgc65bz9N49S7uDerJlElGV9sTCJTRLacykGqShCXR8ap0Tz
+d1uZSsqm3TrNoRZ2ERZENMA=
+-----END CERTIFICATE-----
+
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=Root
+ Validity
+ Not Before: Jan 1 12:00:00 2015 GMT
+ Not After : Mar 1 12:00:00 2015 GMT
+ Subject: CN=Root
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:b5:79:69:47:50:a7:53:24:79:a6:6a:35:e8:33:
+ 74:57:45:da:2c:69:13:1f:76:f9:51:ce:b4:47:ad:
+ a3:c3:58:50:d1:5f:d6:34:5b:3a:62:f0:6c:ea:e7:
+ 86:c2:09:78:b3:53:0d:7f:45:cb:2b:8e:2e:1f:9b:
+ c0:7e:47:90:e3:7b:20:cc:01:ed:b6:c3:c6:40:69:
+ 74:2b:f1:db:a5:f8:f4:5b:fd:e9:84:db:1a:fc:4f:
+ 91:4b:e7:f5:2e:99:d0:c9:69:f5:48:5b:8b:19:ca:
+ dc:5c:0d:3d:15:25:56:77:86:b6:54:fc:d3:1d:8e:
+ f8:ea:f5:ec:de:30:38:93:28:37:7c:d4:b7:29:26:
+ 6f:2a:4a:56:c3:12:91:18:d6:77:cf:4f:31:4e:13:
+ b3:8f:ca:bc:7b:a7:7f:f1:af:db:77:80:51:8c:42:
+ 1c:27:37:18:ac:6c:45:8e:d5:21:25:16:09:fb:3b:
+ 0c:84:a8:60:ea:8a:03:65:94:f5:5c:d6:62:36:ae:
+ b4:de:a3:b1:ee:1b:85:12:8c:6e:ba:ee:14:94:b9:
+ c7:cb:a3:f1:d1:96:ed:81:79:71:27:d0:d8:26:b4:
+ 80:54:c8:07:a9:34:71:a2:a9:04:33:d6:58:02:59:
+ f9:14:97:5e:a9:2b:8c:41:2a:5c:3e:ac:30:b8:63:
+ 52:35
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 62:81:A1:85:84:13:F2:70:79:BD:48:5B:29:88:E0:F1:27:35:41:F7
+ X509v3 Authority Key Identifier:
+ keyid:62:81:A1:85:84:13:F2:70:79:BD:48:5B:29:88:E0:F1:27:35:41:F7
+
+ Authority Information Access:
+ CA Issuers - URI:http://url-for-aia/Root.cer
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://url-for-crl/Root.crl
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha256WithRSAEncryption
+ 47:20:58:cf:09:e0:8c:35:aa:91:d7:be:d1:6a:dc:06:11:ef:
+ 4a:b2:f1:94:41:3b:b4:00:d5:d3:be:cb:4b:ef:67:e0:1b:91:
+ 8b:c3:4f:42:92:9a:5b:8f:84:b1:8e:86:f8:9a:f8:aa:d2:66:
+ 34:76:e5:bb:6f:95:4c:f4:23:e4:71:53:6a:02:8d:e4:ad:7f:
+ c3:6c:77:a0:8d:00:80:c9:cf:e3:d0:96:e2:5a:1c:b6:66:96:
+ 0d:2a:43:58:66:c8:53:b8:7a:6e:c2:c4:2b:c6:54:33:40:b3:
+ f3:07:67:37:51:92:b2:7f:9a:e3:c1:79:36:4b:d8:9f:e9:6e:
+ 04:c6:49:19:51:fd:6f:21:86:09:9a:00:76:e0:5e:73:b0:57:
+ 00:25:c5:2a:12:b3:bd:9a:8b:1b:ff:46:90:47:20:76:2b:bf:
+ 8e:94:7d:1a:7c:56:f6:0a:03:7b:5a:42:97:76:77:2e:a5:0c:
+ 2e:a0:03:13:a8:39:79:82:a0:98:8c:da:bd:1e:7e:af:56:21:
+ 95:14:26:ef:06:07:d7:ec:42:6b:2f:b1:e6:f7:97:88:30:5f:
+ 79:50:99:92:b4:9e:20:d0:c2:95:8e:f7:61:64:99:c3:13:da:
+ 46:a1:63:73:0b:23:e8:d7:e7:97:36:82:2b:2a:12:8e:b8:a9:
+ 2d:3c:35:b3
+-----BEGIN TRUSTED_CERTIFICATE-----
+MIIDZTCCAk2gAwIBAgIBATANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290
+MB4XDTE1MDEwMTEyMDAwMFoXDTE1MDMwMTEyMDAwMFowDzENMAsGA1UEAwwEUm9v
+dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALV5aUdQp1MkeaZqNegz
+dFdF2ixpEx92+VHOtEeto8NYUNFf1jRbOmLwbOrnhsIJeLNTDX9FyyuOLh+bwH5H
+kON7IMwB7bbDxkBpdCvx26X49Fv96YTbGvxPkUvn9S6Z0Mlp9UhbixnK3FwNPRUl
+VneGtlT80x2O+Or17N4wOJMoN3zUtykmbypKVsMSkRjWd89PMU4Ts4/KvHunf/Gv
+23eAUYxCHCc3GKxsRY7VISUWCfs7DISoYOqKA2WU9VzWYjautN6jse4bhRKMbrru
+FJS5x8uj8dGW7YF5cSfQ2Ca0gFTIB6k0caKpBDPWWAJZ+RSXXqkrjEEqXD6sMLhj
+UjUCAwEAAaOByzCByDAdBgNVHQ4EFgQUYoGhhYQT8nB5vUhbKYjg8Sc1QfcwHwYD
+VR0jBBgwFoAUYoGhhYQT8nB5vUhbKYjg8Sc1QfcwNwYIKwYBBQUHAQEEKzApMCcG
+CCsGAQUFBzAChhtodHRwOi8vdXJsLWZvci1haWEvUm9vdC5jZXIwLAYDVR0fBCUw
+IzAhoB+gHYYbaHR0cDovL3VybC1mb3ItY3JsL1Jvb3QuY3JsMA4GA1UdDwEB/wQE
+AwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBHIFjPCeCM
+NaqR177RatwGEe9KsvGUQTu0ANXTvstL72fgG5GLw09Ckppbj4Sxjob4mviq0mY0
+duW7b5VM9CPkcVNqAo3krX/DbHegjQCAyc/j0JbiWhy2ZpYNKkNYZshTuHpuwsQr
+xlQzQLPzB2c3UZKyf5rjwXk2S9if6W4ExkkZUf1vIYYJmgB24F5zsFcAJcUqErO9
+mosb/0aQRyB2K7+OlH0afFb2CgN7WkKXdncupQwuoAMTqDl5gqCYjNq9Hn6vViGV
+FCbvBgfX7EJrL7Hm95eIMF95UJmStJ4g0MKVjvdhZJnDE9pGoWNzCyPo1+eXNoIr
+KhKOuKktPDWz
+-----END TRUSTED_CERTIFICATE-----
+
+-----BEGIN TIME-----
+MTUwMzAyMTIwMDAwWg==
+-----END TIME-----
+
+-----BEGIN VERIFY_RESULT-----
+RkFJTA==
+-----END VERIFY_RESULT-----
diff --git a/net/data/verify_certificate_chain_unittest/generate-expired-root.py b/net/data/verify_certificate_chain_unittest/generate-expired-root.py
new file mode 100755
index 0000000..83f7917
--- /dev/null
+++ b/net/data/verify_certificate_chain_unittest/generate-expired-root.py
@@ -0,0 +1,32 @@
+#!/usr/bin/python
+# Copyright (c) 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Certificate chain with 1 intermediary, where the root certificate is expired
+(violates validity.notAfter). Verification is expected to fail."""
+
+import common
+
+# Self-signed root certificate (part of trust store).
+root = common.create_self_signed_root_certificate('Root')
+root.set_validity_range(common.JANUARY_1_2015_UTC, common.MARCH_1_2015_UTC)
+
+# Intermediary certificate.
+intermediary = common.create_intermediary_certificate('Intermediary', root)
+intermediary.set_validity_range(common.JANUARY_1_2015_UTC,
+ common.JANUARY_1_2016_UTC)
+
+# Target certificate.
+target = common.create_end_entity_certificate('Target', intermediary)
+target.set_validity_range(common.JANUARY_1_2015_UTC, common.JANUARY_1_2016_UTC)
+
+chain = [target, intermediary]
+trusted = [root]
+
+# Both the target and intermediary are valid at this time, however the
+# root is not.
+time = common.MARCH_2_2015_UTC
+verify_result = False
+
+common.write_test_file(__doc__, chain, trusted, time, verify_result)
diff --git a/net/data/verify_certificate_chain_unittest/generate-non-self-signed-root.py b/net/data/verify_certificate_chain_unittest/generate-non-self-signed-root.py
new file mode 100755
index 0000000..355f61e
--- /dev/null
+++ b/net/data/verify_certificate_chain_unittest/generate-non-self-signed-root.py
@@ -0,0 +1,28 @@
+#!/usr/bin/python
+# Copyright (c) 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Certificate chain with 1 intermediary and a trusted root. The trusted root
+is NOT self signed, however its issuer is not included in the chain or root
+store. Verification is expected to succeed since the root is trusted."""
+
+import common
+
+shadow_root = common.create_self_signed_root_certificate('ShadowRoot')
+
+# Non-self-signed root (part of trust store).
+root = common.create_intermediary_certificate('Root', shadow_root)
+
+# Intermediary certificate.
+intermediary = common.create_intermediary_certificate('Intermediary', root)
+
+# Target certificate.
+target = common.create_end_entity_certificate('Target', intermediary)
+
+chain = [target, intermediary]
+trusted = [root]
+time = common.DEFAULT_TIME
+verify_result = True
+
+common.write_test_file(__doc__, chain, trusted, time, verify_result)
diff --git a/net/data/verify_certificate_chain_unittest/generate-violates-pathlen-1-root.py b/net/data/verify_certificate_chain_unittest/generate-violates-pathlen-1-root.py
new file mode 100755
index 0000000..bda9c25
--- /dev/null
+++ b/net/data/verify_certificate_chain_unittest/generate-violates-pathlen-1-root.py
@@ -0,0 +1,31 @@
+#!/usr/bin/python
+# Copyright (c) 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Certificate chain with 2 intermediaries and one end entity certificate. The
+root certificate has a pathlen:1 restriction so this is an invalid chain."""
+
+import common
+
+# Self-signed root certificate (part of trust store).
+root = common.create_self_signed_root_certificate('Root')
+root.get_extensions().set_property('basicConstraints',
+ 'critical,CA:true,pathlen:1')
+
+# Intermediary 1 (no pathlen restriction).
+intermediary1 = common.create_intermediary_certificate('Intermediary1', root)
+
+# Intermediary 2 (no pathlen restriction).
+intermediary2 = common.create_intermediary_certificate('Intermediary2',
+ intermediary1)
+
+# Target certificate.
+target = common.create_end_entity_certificate('Target', intermediary2)
+
+chain = [target, intermediary2, intermediary1]
+trusted = [root]
+time = common.DEFAULT_TIME
+verify_result = False
+
+common.write_test_file(__doc__, chain, trusted, time, verify_result)
diff --git a/net/data/verify_certificate_chain_unittest/non-self-signed-root.pem b/net/data/verify_certificate_chain_unittest/non-self-signed-root.pem
new file mode 100644
index 0000000..11dddad
--- /dev/null
+++ b/net/data/verify_certificate_chain_unittest/non-self-signed-root.pem
@@ -0,0 +1,281 @@
+[Created by: ./generate-non-self-signed-root.py]
+
+Certificate chain with 1 intermediary and a trusted root. The trusted root
+is NOT self signed, however its issuer is not included in the chain or root
+store. Verification is expected to succeed since the root is trusted.
+
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=Intermediary
+ Validity
+ Not Before: Jan 1 12:00:00 2015 GMT
+ Not After : Jan 1 12:00:00 2016 GMT
+ Subject: CN=Target
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c2:27:87:8d:77:16:37:79:6a:b5:5d:e7:ee:9f:
+ a4:5e:f6:f3:9e:a0:f9:9c:05:1a:5f:67:d8:72:c7:
+ 89:73:a5:21:d5:d6:df:39:0d:f7:e7:cb:1e:82:ec:
+ ae:15:ee:5a:bf:57:12:29:b2:44:8b:40:4b:d6:ea:
+ a5:34:05:34:5f:37:2e:32:c0:ed:6a:0c:21:ac:c5:
+ 16:80:61:96:e1:82:e3:15:62:34:23:0a:de:ca:ee:
+ 43:f8:3a:e7:42:5f:3a:79:f4:bc:cf:e7:da:c4:3a:
+ d6:d0:5f:bf:13:58:e7:69:0f:bc:38:7c:05:82:a9:
+ 92:b8:eb:f5:fb:2a:53:ef:5d:12:5e:dc:55:12:b1:
+ 66:67:3f:7c:00:89:b9:50:ea:9c:7f:90:48:02:40:
+ b3:f5:98:0d:73:ca:d8:f7:3d:0b:48:fe:99:12:90:
+ 92:37:93:34:5b:75:60:1c:16:c2:98:ec:2f:9a:f8:
+ e3:1f:8d:56:ea:c6:35:14:67:66:21:e5:83:69:59:
+ ce:c3:a6:f5:1e:94:e8:14:ce:73:83:52:af:ed:df:
+ 63:58:d2:45:07:87:18:ec:7c:11:85:c8:22:b8:ff:
+ b2:6d:05:2c:70:86:d1:5b:f9:8a:94:22:73:58:f1:
+ 9e:b2:4f:ea:50:7e:7c:db:2e:6a:ab:bc:b5:73:b5:
+ 49:3f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 0B:2F:1A:F2:F7:59:E8:BE:B9:20:D5:71:5F:D3:A1:CA:FB:88:4B:65
+ X509v3 Authority Key Identifier:
+ keyid:A5:03:4B:C2:60:A5:9F:86:00:2A:8E:36:33:89:B2:7B:17:24:C2:BC
+
+ Authority Information Access:
+ CA Issuers - URI:http://url-for-aia/Intermediary.cer
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://url-for-crl/Intermediary.crl
+
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ Signature Algorithm: sha256WithRSAEncryption
+ 12:45:9a:a3:e1:5b:0d:8f:1c:b7:39:60:63:7a:e0:fd:34:46:
+ 7e:44:1b:32:44:c7:7f:03:fb:94:68:a2:6b:a1:7f:06:c2:60:
+ 8d:be:65:fc:a3:45:f9:15:2c:17:16:25:98:03:a2:85:88:b6:
+ 4b:4d:86:26:ae:8a:0b:43:46:cd:cc:a3:28:5f:44:3c:92:8a:
+ ae:f3:de:02:93:1b:b7:a3:8e:6e:79:d5:a0:09:d2:c4:65:ff:
+ 1b:f5:80:16:66:20:c7:1d:0c:af:32:ff:ec:f6:a4:0f:53:79:
+ 41:0c:b6:57:9f:b9:1b:81:9c:56:29:3e:62:f6:f5:75:9f:97:
+ ff:0a:9f:5c:c8:58:f5:d0:e7:ad:c1:4b:ba:62:c1:a3:c6:59:
+ 9a:01:11:46:40:c1:54:b6:23:ae:33:58:f9:05:6b:f2:32:0d:
+ 09:2e:5f:ff:74:c5:7d:ce:c9:96:a5:8d:ba:4c:d7:49:3c:8b:
+ 13:73:36:05:12:56:bf:f8:ad:b5:7a:0a:82:ca:bc:b4:00:d2:
+ 9f:39:88:2b:b8:d0:c0:49:8a:f6:3a:e3:3e:3e:fe:b4:4e:20:
+ 1e:60:e8:cb:4d:18:80:94:26:47:bf:be:49:8a:2d:e2:41:4a:
+ cd:c3:7e:23:82:90:ba:43:a6:8b:7e:b3:57:f8:ec:59:3c:97:
+ 38:52:a0:0d
+-----BEGIN CERTIFICATE-----
+MIIDjTCCAnWgAwIBAgIBATANBgkqhkiG9w0BAQsFADAXMRUwEwYDVQQDDAxJbnRl
+cm1lZGlhcnkwHhcNMTUwMTAxMTIwMDAwWhcNMTYwMTAxMTIwMDAwWjARMQ8wDQYD
+VQQDDAZUYXJnZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCJ4eN
+dxY3eWq1Xefun6Re9vOeoPmcBRpfZ9hyx4lzpSHV1t85Dffnyx6C7K4V7lq/VxIp
+skSLQEvW6qU0BTRfNy4ywO1qDCGsxRaAYZbhguMVYjQjCt7K7kP4OudCXzp59LzP
+59rEOtbQX78TWOdpD7w4fAWCqZK46/X7KlPvXRJe3FUSsWZnP3wAiblQ6px/kEgC
+QLP1mA1zytj3PQtI/pkSkJI3kzRbdWAcFsKY7C+a+OMfjVbqxjUUZ2Yh5YNpWc7D
+pvUelOgUznODUq/t32NY0kUHhxjsfBGFyCK4/7JtBSxwhtFb+YqUInNY8Z6yT+pQ
+fnzbLmqrvLVztUk/AgMBAAGjgekwgeYwHQYDVR0OBBYEFAsvGvL3Wei+uSDVcV/T
+ocr7iEtlMB8GA1UdIwQYMBaAFKUDS8JgpZ+GACqONjOJsnsXJMK8MD8GCCsGAQUF
+BwEBBDMwMTAvBggrBgEFBQcwAoYjaHR0cDovL3VybC1mb3ItYWlhL0ludGVybWVk
+aWFyeS5jZXIwNAYDVR0fBC0wKzApoCegJYYjaHR0cDovL3VybC1mb3ItY3JsL0lu
+dGVybWVkaWFyeS5jcmwwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUF
+BwMBBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAEkWao+FbDY8ctzlgY3rg
+/TRGfkQbMkTHfwP7lGiia6F/BsJgjb5l/KNF+RUsFxYlmAOihYi2S02GJq6KC0NG
+zcyjKF9EPJKKrvPeApMbt6OObnnVoAnSxGX/G/WAFmYgxx0MrzL/7PakD1N5QQy2
+V5+5G4GcVik+Yvb1dZ+X/wqfXMhY9dDnrcFLumLBo8ZZmgERRkDBVLYjrjNY+QVr
+8jINCS5f/3TFfc7JlqWNukzXSTyLE3M2BRJWv/ittXoKgsq8tADSnzmIK7jQwEmK
+9jrjPj7+tE4gHmDoy00YgJQmR7++SYot4kFKzcN+I4KQukOmi36zV/jsWTyXOFKg
+DQ==
+-----END CERTIFICATE-----
+
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=Root
+ Validity
+ Not Before: Jan 1 12:00:00 2015 GMT
+ Not After : Jan 1 12:00:00 2016 GMT
+ Subject: CN=Intermediary
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:b0:65:a4:4b:a6:56:90:82:42:cf:e8:65:86:d1:
+ 96:7f:13:8d:b9:46:5a:16:ce:c2:fa:0d:52:ae:93:
+ 62:dc:72:05:a2:31:b7:29:88:77:31:c3:2e:3f:4d:
+ 17:16:08:3a:96:d2:49:1b:bf:0f:a0:56:ac:d2:5a:
+ b8:ff:e3:46:f1:56:83:c3:72:32:8a:7d:f6:55:a5:
+ 05:8a:68:ca:2e:9b:2a:80:63:4d:fd:46:f2:9f:c9:
+ 95:43:06:79:c4:88:78:b3:73:fb:05:0c:4f:57:75:
+ 9c:ef:eb:9f:b3:5e:65:b6:b3:b1:b7:8d:1c:c4:d9:
+ 03:76:72:4f:b8:4f:dc:36:19:4c:62:d8:0c:e4:c1:
+ 9b:9f:0c:3e:e2:54:69:f5:a6:53:a1:16:88:be:ee:
+ a8:3e:20:28:3d:a9:3c:12:41:cc:91:ca:b7:fc:d7:
+ 15:d3:1c:63:9e:7b:1d:c4:b4:08:65:2e:bc:b5:61:
+ b8:84:de:3b:69:05:9c:52:6e:60:d1:79:17:36:69:
+ 06:21:ed:43:07:bf:21:28:0a:6b:48:79:53:21:da:
+ 02:07:79:b6:30:4c:f2:6f:9f:30:55:a2:20:ae:cf:
+ 8c:ac:c6:b0:30:b0:01:80:83:ed:b0:5a:9b:92:35:
+ d9:7d:51:c5:f5:76:1e:c5:53:c1:33:71:41:35:40:
+ 55:d7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ A5:03:4B:C2:60:A5:9F:86:00:2A:8E:36:33:89:B2:7B:17:24:C2:BC
+ X509v3 Authority Key Identifier:
+ keyid:D4:83:FC:D5:EF:E0:C4:8E:32:6D:A2:30:65:12:B4:CD:3A:B2:95:88
+
+ Authority Information Access:
+ CA Issuers - URI:http://url-for-aia/Root.cer
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://url-for-crl/Root.crl
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha256WithRSAEncryption
+ 67:ed:d6:55:16:b2:0d:af:79:6e:53:48:70:4c:93:be:5e:ed:
+ 50:ea:d7:92:e4:7c:6c:78:05:0c:00:90:15:de:10:18:e5:cc:
+ 50:24:23:e6:3e:5f:b0:f4:6f:f9:74:44:db:38:d1:45:c5:84:
+ 59:58:cc:b6:f9:e9:1f:ed:41:e8:b9:aa:4b:d8:6e:88:76:d9:
+ 2f:44:bf:5d:4f:6e:72:8f:b8:35:d3:e6:a3:a2:ef:3d:e6:f3:
+ be:90:73:a8:80:ed:72:bb:ac:20:96:38:c6:3f:d1:fe:64:3e:
+ 1a:ce:21:65:cd:1f:28:54:4a:fb:44:dc:43:cc:b4:61:dd:58:
+ 83:1b:08:0c:31:f6:bc:bf:02:99:45:16:88:84:68:91:13:aa:
+ af:f6:6d:4e:8d:dd:26:1d:3a:35:ab:75:7e:f7:64:62:8c:b7:
+ 34:f9:5b:73:9b:e9:40:12:1c:f2:32:b9:e0:8c:86:fc:f2:b0:
+ 33:6d:56:f2:a0:f7:9c:ea:d7:45:41:8d:de:49:26:90:45:32:
+ 35:cf:e2:ce:43:b0:af:28:35:6a:0f:86:87:2b:57:eb:88:92:
+ 89:7a:9d:b5:f3:3c:46:11:56:2e:fc:73:32:56:a9:4b:c1:87:
+ f7:f8:46:d5:5d:ad:b2:e7:a2:88:5d:7d:b5:68:b4:ea:a7:1f:
+ 35:1d:f9:a6
+-----BEGIN CERTIFICATE-----
+MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290
+MB4XDTE1MDEwMTEyMDAwMFoXDTE2MDEwMTEyMDAwMFowFzEVMBMGA1UEAwwMSW50
+ZXJtZWRpYXJ5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsGWkS6ZW
+kIJCz+hlhtGWfxONuUZaFs7C+g1SrpNi3HIFojG3KYh3McMuP00XFgg6ltJJG78P
+oFas0lq4/+NG8VaDw3Iyin32VaUFimjKLpsqgGNN/Ubyn8mVQwZ5xIh4s3P7BQxP
+V3Wc7+ufs15ltrOxt40cxNkDdnJPuE/cNhlMYtgM5MGbnww+4lRp9aZToRaIvu6o
+PiAoPak8EkHMkcq3/NcV0xxjnnsdxLQIZS68tWG4hN47aQWcUm5g0XkXNmkGIe1D
+B78hKAprSHlTIdoCB3m2MEzyb58wVaIgrs+MrMawMLABgIPtsFqbkjXZfVHF9XYe
+xVPBM3FBNUBV1wIDAQABo4HLMIHIMB0GA1UdDgQWBBSlA0vCYKWfhgAqjjYzibJ7
+FyTCvDAfBgNVHSMEGDAWgBTUg/zV7+DEjjJtojBlErTNOrKViDA3BggrBgEFBQcB
+AQQrMCkwJwYIKwYBBQUHMAKGG2h0dHA6Ly91cmwtZm9yLWFpYS9Sb290LmNlcjAs
+BgNVHR8EJTAjMCGgH6AdhhtodHRwOi8vdXJsLWZvci1jcmwvUm9vdC5jcmwwDgYD
+VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
+AGft1lUWsg2veW5TSHBMk75e7VDq15LkfGx4BQwAkBXeEBjlzFAkI+Y+X7D0b/l0
+RNs40UXFhFlYzLb56R/tQei5qkvYboh22S9Ev11PbnKPuDXT5qOi7z3m876Qc6iA
+7XK7rCCWOMY/0f5kPhrOIWXNHyhUSvtE3EPMtGHdWIMbCAwx9ry/AplFFoiEaJET
+qq/2bU6N3SYdOjWrdX73ZGKMtzT5W3Ob6UASHPIyueCMhvzysDNtVvKg95zq10VB
+jd5JJpBFMjXP4s5DsK8oNWoPhocrV+uIkol6nbXzPEYRVi78czJWqUvBh/f4RtVd
+rbLnoohdfbVotOqnHzUd+aY=
+-----END CERTIFICATE-----
+
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=ShadowRoot
+ Validity
+ Not Before: Jan 1 12:00:00 2015 GMT
+ Not After : Jan 1 12:00:00 2016 GMT
+ Subject: CN=Root
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:a6:37:9c:ac:42:96:1c:fb:44:86:df:16:85:d2:
+ de:49:73:74:b8:5b:3e:8c:34:4b:42:57:7e:7a:9a:
+ fd:cf:7f:03:c7:39:22:02:3f:44:1b:62:4b:4a:1b:
+ 9b:d8:8e:7b:a5:b5:92:39:a1:03:bc:3c:1a:1f:5f:
+ 36:54:9d:b4:6d:98:c2:24:a9:fd:f7:6e:8e:41:18:
+ e1:9b:ae:ef:61:98:5f:91:53:f0:8a:8e:d4:18:cf:
+ 4f:dd:ff:75:01:16:10:f1:76:10:28:ba:70:96:8b:
+ b7:ac:df:17:68:61:03:56:77:e5:bd:04:58:d8:44:
+ d6:65:21:97:28:46:5d:a3:62:6d:3d:a1:03:6d:da:
+ f7:46:f5:76:5c:1a:cd:19:b4:25:cd:17:d7:0e:ac:
+ 6a:3c:d1:35:a0:20:cc:5e:62:7b:e1:11:d6:92:09:
+ 34:3e:1d:d7:d5:27:b9:3b:5b:42:1e:11:f4:1a:2f:
+ de:93:81:2f:6b:d1:9f:40:9f:d7:8e:7c:9b:37:7b:
+ d8:3f:ba:e3:00:d7:f7:3c:20:0e:81:b4:df:cc:46:
+ 3c:10:0d:04:8a:b5:ef:ba:e7:ec:7e:0b:98:a1:18:
+ fb:39:db:2c:76:ae:1b:91:94:22:f4:35:b0:1a:73:
+ 4d:7b:eb:c5:b3:80:80:74:90:79:b9:2f:fd:35:39:
+ 02:ad
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ D4:83:FC:D5:EF:E0:C4:8E:32:6D:A2:30:65:12:B4:CD:3A:B2:95:88
+ X509v3 Authority Key Identifier:
+ keyid:EE:5C:5F:80:3F:59:C4:A6:5B:70:C2:1C:BA:E4:5D:40:F9:E9:60:8D
+
+ Authority Information Access:
+ CA Issuers - URI:http://url-for-aia/ShadowRoot.cer
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://url-for-crl/ShadowRoot.crl
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha256WithRSAEncryption
+ 8c:2a:1f:ee:90:15:b8:41:8b:cc:b4:45:2b:6f:5b:9e:49:f7:
+ a1:9f:9e:2a:ce:8a:c3:ae:57:95:62:b5:f2:c9:a4:6a:57:49:
+ 39:00:32:c4:23:4c:b8:15:21:4a:8f:0a:83:98:d8:ba:83:dc:
+ da:88:4c:7e:60:21:1a:ed:75:6d:5e:5d:83:90:e0:71:23:13:
+ 4f:2d:94:c0:fb:91:7f:b6:59:41:d6:b3:3e:42:ef:31:02:23:
+ 18:a6:d2:9b:00:c6:8c:5a:3d:2c:cb:5e:dc:53:69:ac:71:b8:
+ 68:90:62:5a:ba:2f:1f:20:9d:77:f3:b0:aa:2e:52:61:a5:60:
+ 53:5b:5c:ab:c9:56:7e:01:4c:bf:26:ab:13:47:c1:28:72:13:
+ a5:d8:b8:4c:65:09:9f:7f:a1:67:93:fc:0d:71:a3:4c:1d:3f:
+ 95:9c:4a:28:8d:52:0d:48:fe:34:04:c2:d2:80:61:86:1c:e6:
+ 18:cd:bb:62:ca:d2:e6:76:a8:f3:14:e3:41:75:5d:3b:e7:5a:
+ 29:6c:6e:2c:bc:53:6f:39:e8:82:ab:73:d1:d5:b9:d3:f8:30:
+ 5c:d7:19:d3:49:11:25:7c:01:3a:2a:a6:7f:19:b3:08:bf:0f:
+ dc:4f:7b:fa:5b:20:b8:7e:eb:ea:8f:0a:56:c4:16:cd:e1:2b:
+ a2:bb:66:f0
+-----BEGIN TRUSTED_CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDDApTaGFk
+b3dSb290MB4XDTE1MDEwMTEyMDAwMFoXDTE2MDEwMTEyMDAwMFowDzENMAsGA1UE
+AwwEUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKY3nKxClhz7
+RIbfFoXS3klzdLhbPow0S0JXfnqa/c9/A8c5IgI/RBtiS0obm9iOe6W1kjmhA7w8
+Gh9fNlSdtG2YwiSp/fdujkEY4Zuu72GYX5FT8IqO1BjPT93/dQEWEPF2ECi6cJaL
+t6zfF2hhA1Z35b0EWNhE1mUhlyhGXaNibT2hA23a90b1dlwazRm0Jc0X1w6sajzR
+NaAgzF5ie+ER1pIJND4d19UnuTtbQh4R9Bov3pOBL2vRn0Cf1458mzd72D+64wDX
+9zwgDoG038xGPBANBIq177rn7H4LmKEY+znbLHauG5GUIvQ1sBpzTXvrxbOAgHSQ
+ebkv/TU5Aq0CAwEAAaOB1zCB1DAdBgNVHQ4EFgQU1IP81e/gxI4ybaIwZRK0zTqy
+lYgwHwYDVR0jBBgwFoAU7lxfgD9ZxKZbcMIcuuRdQPnpYI0wPQYIKwYBBQUHAQEE
+MTAvMC0GCCsGAQUFBzAChiFodHRwOi8vdXJsLWZvci1haWEvU2hhZG93Um9vdC5j
+ZXIwMgYDVR0fBCswKTAnoCWgI4YhaHR0cDovL3VybC1mb3ItY3JsL1NoYWRvd1Jv
+b3QuY3JsMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4IBAQCMKh/ukBW4QYvMtEUrb1ueSfehn54qzorDrleVYrXyyaRqV0k5
+ADLEI0y4FSFKjwqDmNi6g9zaiEx+YCEa7XVtXl2DkOBxIxNPLZTA+5F/tllB1rM+
+Qu8xAiMYptKbAMaMWj0sy17cU2mscbhokGJaui8fIJ1387CqLlJhpWBTW1yryVZ+
+AUy/JqsTR8EochOl2LhMZQmff6Fnk/wNcaNMHT+VnEoojVINSP40BMLSgGGGHOYY
+zbtiytLmdqjzFONBdV0751opbG4svFNvOeiCq3PR1bnT+DBc1xnTSRElfAE6KqZ/
+GbMIvw/cT3v6WyC4fuvqjwpWxBbN4Suiu2bw
+-----END TRUSTED_CERTIFICATE-----
+
+-----BEGIN TIME-----
+MTUwMzAyMTIwMDAwWg==
+-----END TIME-----
+
+-----BEGIN VERIFY_RESULT-----
+U1VDQ0VTUw==
+-----END VERIFY_RESULT-----
diff --git a/net/data/verify_certificate_chain_unittest/violates-pathlen-1-root.pem b/net/data/verify_certificate_chain_unittest/violates-pathlen-1-root.pem
new file mode 100644
index 0000000..c639e56
--- /dev/null
+++ b/net/data/verify_certificate_chain_unittest/violates-pathlen-1-root.pem
@@ -0,0 +1,369 @@
+[Created by: generate-violates-pathlen-1-root.py]
+
+Certificate chain with 2 intermediaries and one end entity certificate. The
+root certificate has a pathlen:1 restriction so this is an invalid chain.
+
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=Intermediary2
+ Validity
+ Not Before: Jan 1 12:00:00 2015 GMT
+ Not After : Jan 1 12:00:00 2016 GMT
+ Subject: CN=Target
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:bf:b8:e9:8b:9f:2a:8d:58:f0:93:6a:7a:d2:d4:
+ 29:ec:ce:35:c9:5e:c0:f7:27:2a:78:a3:76:53:25:
+ 54:09:43:e0:30:df:a1:f3:e2:a2:45:21:d7:b0:e6:
+ ff:d0:cc:81:eb:2b:78:9a:b6:85:97:87:d5:b2:9f:
+ 3b:f2:d7:55:3d:fe:0f:ba:20:39:a6:0d:c8:7c:ea:
+ 23:8a:63:38:8e:70:44:ff:d2:18:66:3e:ad:10:68:
+ ee:ec:21:f7:18:e4:7f:37:09:c6:e6:a8:d1:a2:4c:
+ 1f:e5:7a:69:04:13:df:09:5e:13:61:7c:15:09:9c:
+ 55:af:27:66:87:0e:bd:fc:2a:9d:7f:1c:73:b5:84:
+ c2:d6:2b:d9:5d:f6:19:52:58:bb:8c:8c:5f:a7:9c:
+ de:d7:8d:5f:ef:8f:f3:24:e1:0d:10:59:58:c6:72:
+ 8c:d7:fc:fe:bc:22:a7:58:4d:83:f2:48:4b:cd:55:
+ 36:45:28:e4:cf:93:75:78:0f:5e:35:c0:b7:52:e5:
+ e2:91:42:04:bb:9c:0c:cf:eb:89:66:5f:90:46:b2:
+ 76:b0:82:c4:af:34:fd:a6:fd:93:7f:54:ce:4f:be:
+ a4:32:8e:9c:3f:40:c9:6c:db:be:85:0c:e6:df:2b:
+ 7c:9b:ef:8b:7a:4b:15:dc:09:10:3b:b1:b7:e7:c7:
+ c1:21
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 11:74:6B:48:F5:42:3C:04:F3:A2:04:42:E5:F2:BC:1C:AD:AB:CB:E2
+ X509v3 Authority Key Identifier:
+ keyid:9A:80:A6:AF:E0:4A:48:D1:70:0A:10:7A:0D:74:57:B8:CE:48:5B:7D
+
+ Authority Information Access:
+ CA Issuers - URI:http://url-for-aia/Intermediary2.cer
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://url-for-crl/Intermediary2.crl
+
+ X509v3 Key Usage: critical
+ Digital Signature, Key Encipherment
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication, TLS Web Client Authentication
+ Signature Algorithm: sha256WithRSAEncryption
+ 6e:0e:da:63:ae:72:b5:ee:9b:ee:f6:34:18:30:e5:4c:9b:b7:
+ a8:21:ef:fe:fe:55:c9:27:4d:13:ab:32:be:89:76:93:b8:2a:
+ be:c2:3f:6d:f6:23:6d:ed:b2:4f:77:7e:b7:7c:f4:5a:a3:de:
+ 80:09:f6:c0:3b:87:34:2d:97:5c:1a:a0:0d:e4:9f:28:93:d4:
+ d6:38:ca:ea:c8:4e:ec:71:07:b8:c7:cb:c0:59:77:e5:99:80:
+ 34:7b:9f:77:8f:63:b0:d0:3d:ce:a9:c4:aa:ba:49:02:5e:31:
+ 84:a3:7f:8e:51:5c:06:a4:44:49:04:c4:27:7e:04:f7:13:18:
+ 61:67:d1:4d:23:b0:16:f2:47:79:bd:e5:40:52:77:06:73:8b:
+ 4b:c6:c4:5c:09:46:29:a3:36:b5:3c:75:6d:94:71:13:db:ff:
+ e8:62:e4:76:59:06:88:9d:c5:5b:d7:af:ae:16:72:80:60:6a:
+ 23:01:4d:fa:90:33:ad:01:38:47:d6:5d:91:28:9f:78:6f:ba:
+ da:62:5b:17:fa:9f:5a:6e:28:5f:59:96:de:64:a8:3b:b7:de:
+ fe:f7:b5:3c:79:e9:fe:15:b2:73:0f:65:5f:83:2e:6b:85:55:
+ 04:42:da:87:48:6b:7d:1c:a2:b0:e2:60:7f:c9:22:70:d1:a4:
+ 51:94:40:3c
+-----BEGIN CERTIFICATE-----
+MIIDkDCCAnigAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1JbnRl
+cm1lZGlhcnkyMB4XDTE1MDEwMTEyMDAwMFoXDTE2MDEwMTEyMDAwMFowETEPMA0G
+A1UEAwwGVGFyZ2V0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv7jp
+i58qjVjwk2p60tQp7M41yV7A9ycqeKN2UyVUCUPgMN+h8+KiRSHXsOb/0MyB6yt4
+mraFl4fVsp878tdVPf4PuiA5pg3IfOojimM4jnBE/9IYZj6tEGju7CH3GOR/NwnG
+5qjRokwf5XppBBPfCV4TYXwVCZxVrydmhw69/CqdfxxztYTC1ivZXfYZUli7jIxf
+p5ze141f74/zJOENEFlYxnKM1/z+vCKnWE2D8khLzVU2RSjkz5N1eA9eNcC3UuXi
+kUIEu5wMz+uJZl+QRrJ2sILErzT9pv2Tf1TOT76kMo6cP0DJbNu+hQzm3yt8m++L
+eksV3AkQO7G358fBIQIDAQABo4HrMIHoMB0GA1UdDgQWBBQRdGtI9UI8BPOiBELl
+8rwcravL4jAfBgNVHSMEGDAWgBSagKav4EpI0XAKEHoNdFe4zkhbfTBABggrBgEF
+BQcBAQQ0MDIwMAYIKwYBBQUHMAKGJGh0dHA6Ly91cmwtZm9yLWFpYS9JbnRlcm1l
+ZGlhcnkyLmNlcjA1BgNVHR8ELjAsMCqgKKAmhiRodHRwOi8vdXJsLWZvci1jcmwv
+SW50ZXJtZWRpYXJ5Mi5jcmwwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsG
+AQUFBwMBBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAbg7aY65yte6b7vY0
+GDDlTJu3qCHv/v5VySdNE6syvol2k7gqvsI/bfYjbe2yT3d+t3z0WqPegAn2wDuH
+NC2XXBqgDeSfKJPU1jjK6shO7HEHuMfLwFl35ZmANHufd49jsNA9zqnEqrpJAl4x
+hKN/jlFcBqRESQTEJ34E9xMYYWfRTSOwFvJHeb3lQFJ3BnOLS8bEXAlGKaM2tTx1
+bZRxE9v/6GLkdlkGiJ3FW9evrhZygGBqIwFN+pAzrQE4R9ZdkSifeG+62mJbF/qf
+Wm4oX1mW3mSoO7fe/ve1PHnp/hWycw9lX4Mua4VVBELah0hrfRyisOJgf8kicNGk
+UZRAPA==
+-----END CERTIFICATE-----
+
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=Intermediary1
+ Validity
+ Not Before: Jan 1 12:00:00 2015 GMT
+ Not After : Jan 1 12:00:00 2016 GMT
+ Subject: CN=Intermediary2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:9b:e8:f6:41:79:62:c9:06:fd:13:2c:f5:cc:07:
+ a9:dd:5c:1e:90:76:a5:71:fa:f3:5c:34:1f:c9:3a:
+ 33:77:05:a0:27:7b:6a:eb:8b:d8:de:25:65:6f:b6:
+ d6:e1:82:34:0a:7b:13:d3:85:37:7d:d9:70:04:43:
+ b3:e3:46:8b:60:e1:99:ba:28:5b:ef:c2:7e:b3:c4:
+ 20:6f:94:f2:47:79:66:ce:0f:5d:79:58:aa:f7:62:
+ 80:38:14:4a:17:34:59:86:39:1d:ed:38:b8:14:f4:
+ 10:0c:1f:2c:8e:49:e5:5d:fd:d2:0f:37:5c:b8:e5:
+ a9:86:07:0e:5e:27:ee:05:a0:ad:b5:b6:86:43:30:
+ 8b:0d:35:b5:86:cd:98:98:e8:d6:04:53:4e:2b:81:
+ be:d2:96:6f:cf:2f:72:2d:f5:6c:c8:ba:f5:42:7a:
+ f1:67:33:03:bb:cf:6d:67:03:f3:1a:3c:39:d9:cf:
+ 8f:ad:03:ca:2c:dc:e3:33:92:24:18:46:86:8e:dc:
+ 27:b8:76:57:3a:7d:a2:89:96:18:07:96:04:d9:75:
+ 8c:e6:1b:cf:1f:e9:6c:5d:8d:77:2f:4d:9d:00:bb:
+ 16:e9:c5:da:7d:5f:45:e8:3d:17:d8:72:a6:bf:68:
+ 1f:0a:a5:88:c1:74:45:53:b9:0c:d5:05:a5:ba:ed:
+ 55:73
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 9A:80:A6:AF:E0:4A:48:D1:70:0A:10:7A:0D:74:57:B8:CE:48:5B:7D
+ X509v3 Authority Key Identifier:
+ keyid:1D:4A:1C:48:70:30:B6:65:73:56:A7:6E:A0:48:35:81:6E:3B:95:8A
+
+ Authority Information Access:
+ CA Issuers - URI:http://url-for-aia/Intermediary1.cer
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://url-for-crl/Intermediary1.crl
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha256WithRSAEncryption
+ 47:1c:62:1b:7e:69:aa:b6:d8:6c:50:44:09:e8:15:b5:fe:ee:
+ 86:5c:69:6d:4c:7a:90:1f:2e:4f:e8:21:a3:44:38:d6:07:0b:
+ 43:cf:dd:13:64:64:42:a9:ae:62:f6:1b:ea:03:2e:3b:4f:ed:
+ 8a:45:8e:ec:09:d8:1a:67:eb:ef:c6:77:fc:cf:03:9f:b4:4a:
+ 59:76:4e:2b:b0:d3:41:5a:a0:8c:bb:1c:61:67:52:7d:48:2e:
+ 3f:c2:7d:a6:60:95:25:75:47:9c:1a:c3:1e:25:cd:e9:7d:2b:
+ 71:26:fc:97:f1:2e:c6:2f:d4:2a:bb:27:d4:76:7e:c9:bc:05:
+ 92:24:86:56:46:27:e0:14:af:d7:c6:72:d2:dc:be:93:2f:b3:
+ 44:d3:e1:4a:08:75:47:50:16:e6:50:36:61:e3:6f:b7:a6:40:
+ 1c:61:14:ae:66:20:93:0b:fb:6d:b1:a9:4d:d5:ec:8d:2b:d6:
+ 84:36:c4:61:70:e5:99:4f:7e:af:97:d2:42:91:11:a7:1f:0e:
+ 32:fc:09:37:44:a2:c9:bb:35:82:73:85:e5:90:b4:80:a7:4b:
+ 40:ce:cb:62:ca:e1:2b:36:f6:e7:bc:3a:67:71:6d:ab:4b:87:
+ cf:72:70:ad:ef:7a:85:ab:72:5d:c7:c1:ac:5e:b5:81:dc:ff:
+ 96:6f:08:02
+-----BEGIN CERTIFICATE-----
+MIIDiTCCAnGgAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1JbnRl
+cm1lZGlhcnkxMB4XDTE1MDEwMTEyMDAwMFoXDTE2MDEwMTEyMDAwMFowGDEWMBQG
+A1UEAwwNSW50ZXJtZWRpYXJ5MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAJvo9kF5YskG/RMs9cwHqd1cHpB2pXH681w0H8k6M3cFoCd7auuL2N4lZW+2
+1uGCNAp7E9OFN33ZcARDs+NGi2DhmbooW+/CfrPEIG+U8kd5Zs4PXXlYqvdigDgU
+Shc0WYY5He04uBT0EAwfLI5J5V390g83XLjlqYYHDl4n7gWgrbW2hkMwiw01tYbN
+mJjo1gRTTiuBvtKWb88vci31bMi69UJ68WczA7vPbWcD8xo8OdnPj60Dyizc4zOS
+JBhGho7cJ7h2Vzp9oomWGAeWBNl1jOYbzx/pbF2Ndy9NnQC7FunF2n1fReg9F9hy
+pr9oHwqliMF0RVO5DNUFpbrtVXMCAwEAAaOB3TCB2jAdBgNVHQ4EFgQUmoCmr+BK
+SNFwChB6DXRXuM5IW30wHwYDVR0jBBgwFoAUHUocSHAwtmVzVqduoEg1gW47lYow
+QAYIKwYBBQUHAQEENDAyMDAGCCsGAQUFBzAChiRodHRwOi8vdXJsLWZvci1haWEv
+SW50ZXJtZWRpYXJ5MS5jZXIwNQYDVR0fBC4wLDAqoCigJoYkaHR0cDovL3VybC1m
+b3ItY3JsL0ludGVybWVkaWFyeTEuY3JsMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB
+Af8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBHHGIbfmmqtthsUEQJ6BW1/u6G
+XGltTHqQHy5P6CGjRDjWBwtDz90TZGRCqa5i9hvqAy47T+2KRY7sCdgaZ+vvxnf8
+zwOftEpZdk4rsNNBWqCMuxxhZ1J9SC4/wn2mYJUldUecGsMeJc3pfStxJvyX8S7G
+L9QquyfUdn7JvAWSJIZWRifgFK/XxnLS3L6TL7NE0+FKCHVHUBbmUDZh42+3pkAc
+YRSuZiCTC/ttsalN1eyNK9aENsRhcOWZT36vl9JCkRGnHw4y/Ak3RKLJuzWCc4Xl
+kLSAp0tAzstiyuErNvbnvDpncW2rS4fPcnCt73qFq3Jdx8GsXrWB3P+WbwgC
+-----END CERTIFICATE-----
+
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=Root
+ Validity
+ Not Before: Jan 1 12:00:00 2015 GMT
+ Not After : Jan 1 12:00:00 2016 GMT
+ Subject: CN=Intermediary1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:b9:d1:e1:e9:55:23:09:13:95:52:d6:31:f6:16:
+ 49:28:4d:e9:02:bd:42:73:3b:f6:9a:d4:05:86:6e:
+ fd:c4:26:b1:59:d5:e1:be:64:f0:84:39:f0:d9:cf:
+ 0a:62:98:68:c6:7b:a1:6c:73:4c:79:5e:92:88:ba:
+ db:e2:16:f9:0a:5b:46:f7:ef:6b:77:4b:98:d9:40:
+ ca:1b:2d:7b:fa:9a:92:11:fe:85:6c:ef:2e:39:6f:
+ 2f:16:32:cc:45:c7:a7:bd:62:2a:d7:49:9d:c1:cc:
+ 0d:a8:b1:91:e0:f7:b8:e5:77:f4:0a:ef:01:de:e1:
+ 65:4c:e0:e6:29:3f:2d:3f:aa:0d:a4:38:69:90:5d:
+ 83:b4:e9:b0:04:c4:f4:a4:b9:5f:c0:a8:88:68:13:
+ 86:a1:9b:fe:24:d3:ef:cc:34:be:3d:bb:70:58:64:
+ 74:54:7d:c8:6a:a3:d3:37:9e:91:5c:fe:16:15:5f:
+ 00:45:2f:f9:81:3a:7f:ef:bb:03:60:b8:08:ce:9f:
+ 88:20:62:ba:4d:8a:18:8a:57:1d:ea:12:1e:62:d7:
+ eb:01:80:e6:a9:72:d2:2f:84:aa:16:20:e8:f8:47:
+ e1:4e:43:46:16:20:51:cd:20:39:a3:47:70:0f:9f:
+ 4e:e6:7b:fa:5d:c2:9e:67:ce:22:e1:e8:1c:89:bd:
+ a0:49
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 1D:4A:1C:48:70:30:B6:65:73:56:A7:6E:A0:48:35:81:6E:3B:95:8A
+ X509v3 Authority Key Identifier:
+ keyid:88:1C:D6:E6:0D:8F:83:DE:9D:9C:2E:3E:1E:E5:61:82:EA:2D:11:F6
+
+ Authority Information Access:
+ CA Issuers - URI:http://url-for-aia/Root.cer
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://url-for-crl/Root.crl
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha256WithRSAEncryption
+ 7c:45:39:85:85:2e:2a:47:1a:05:7c:45:0b:9d:1c:94:58:c9:
+ a6:ab:95:85:fb:64:da:a3:cf:96:98:80:8c:c4:fe:5d:10:db:
+ 94:df:6c:eb:15:45:d3:e8:d1:80:39:0e:b9:28:4a:b8:0c:aa:
+ 87:cc:4b:b2:14:4d:fe:2c:a6:36:5e:40:5c:10:49:e2:90:1d:
+ 46:ad:d1:b5:25:85:35:3d:99:da:0b:da:ad:f0:9d:94:50:6e:
+ b8:4c:1c:86:d6:68:cc:d9:7f:7e:b8:8d:0c:43:0c:e9:6a:05:
+ 00:0e:7d:00:88:62:70:4f:f9:a1:68:48:9f:c4:c7:cd:78:63:
+ c6:6c:ec:84:c3:09:65:64:14:27:f4:f9:df:a1:f4:bc:c1:43:
+ 88:88:ba:98:ba:14:66:8a:47:42:49:dc:9a:35:84:e0:8b:17:
+ 9e:5b:bd:8f:4f:b3:01:2e:61:3e:12:45:ab:63:38:77:b1:f2:
+ 21:57:04:49:53:e4:23:4b:58:81:23:42:9a:a5:fe:1c:08:7b:
+ d6:bf:7e:ec:9d:b1:15:b7:27:2a:f2:96:81:05:52:ad:97:92:
+ 71:20:34:33:99:77:a3:e9:92:e1:68:73:ea:31:eb:54:cb:f9:
+ 97:61:03:56:de:4c:35:c5:cd:d4:75:a7:e4:f2:5c:66:f5:5d:
+ 34:ab:8f:f8
+-----BEGIN CERTIFICATE-----
+MIIDbjCCAlagAwIBAgIBAjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290
+MB4XDTE1MDEwMTEyMDAwMFoXDTE2MDEwMTEyMDAwMFowGDEWMBQGA1UEAwwNSW50
+ZXJtZWRpYXJ5MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALnR4elV
+IwkTlVLWMfYWSShN6QK9QnM79prUBYZu/cQmsVnV4b5k8IQ58NnPCmKYaMZ7oWxz
+THlekoi62+IW+QpbRvfva3dLmNlAyhste/qakhH+hWzvLjlvLxYyzEXHp71iKtdJ
+ncHMDaixkeD3uOV39ArvAd7hZUzg5ik/LT+qDaQ4aZBdg7TpsATE9KS5X8CoiGgT
+hqGb/iTT78w0vj27cFhkdFR9yGqj0zeekVz+FhVfAEUv+YE6f++7A2C4CM6fiCBi
+uk2KGIpXHeoSHmLX6wGA5qly0i+EqhYg6PhH4U5DRhYgUc0gOaNHcA+fTuZ7+l3C
+nmfOIuHoHIm9oEkCAwEAAaOByzCByDAdBgNVHQ4EFgQUHUocSHAwtmVzVqduoEg1
+gW47lYowHwYDVR0jBBgwFoAUiBzW5g2Pg96dnC4+HuVhguotEfYwNwYIKwYBBQUH
+AQEEKzApMCcGCCsGAQUFBzAChhtodHRwOi8vdXJsLWZvci1haWEvUm9vdC5jZXIw
+LAYDVR0fBCUwIzAhoB+gHYYbaHR0cDovL3VybC1mb3ItY3JsL1Jvb3QuY3JsMA4G
+A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IB
+AQB8RTmFhS4qRxoFfEULnRyUWMmmq5WF+2Tao8+WmICMxP5dENuU32zrFUXT6NGA
+OQ65KEq4DKqHzEuyFE3+LKY2XkBcEEnikB1GrdG1JYU1PZnaC9qt8J2UUG64TByG
+1mjM2X9+uI0MQwzpagUADn0AiGJwT/mhaEifxMfNeGPGbOyEwwllZBQn9PnfofS8
+wUOIiLqYuhRmikdCSdyaNYTgixeeW72PT7MBLmE+EkWrYzh3sfIhVwRJU+QjS1iB
+I0Kapf4cCHvWv37snbEVtycq8paBBVKtl5JxIDQzmXej6ZLhaHPqMetUy/mXYQNW
+3kw1xc3Udafk8lxm9V00q4/4
+-----END CERTIFICATE-----
+
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN=Root
+ Validity
+ Not Before: Jan 1 12:00:00 2015 GMT
+ Not After : Jan 1 12:00:00 2016 GMT
+ Subject: CN=Root
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:a3:90:0c:56:93:34:da:26:53:6e:a9:d5:07:b9:
+ 83:30:70:85:69:ed:18:67:72:bb:1d:c4:06:ff:a8:
+ b8:00:75:fd:38:ac:f1:e2:4a:86:21:4d:01:77:fc:
+ f3:2d:90:94:7e:14:2c:8a:89:c2:cd:42:a5:ae:fe:
+ 7a:ca:9d:44:78:21:f6:ab:6d:d3:c8:8a:07:57:eb:
+ 22:10:cf:1e:44:f2:a4:23:e7:10:46:1e:d4:21:60:
+ 9c:01:72:ff:ca:20:c8:48:c4:ad:b0:17:28:f3:14:
+ af:49:65:52:52:58:9a:1b:68:1a:9d:77:e9:61:52:
+ 54:0b:81:e4:0b:c7:2d:b3:2d:aa:9e:16:1f:51:ec:
+ 7d:e7:2d:2c:e6:c4:88:81:3e:1b:e1:e7:1f:21:12:
+ 21:47:ec:14:a5:d9:ab:a2:2b:ac:1f:3c:b2:a5:c1:
+ 69:4e:55:88:66:e8:5a:4d:9d:08:27:1c:fe:cd:62:
+ b0:95:62:c4:4b:ff:12:11:4c:d8:10:66:a4:d0:29:
+ da:d5:79:b7:ee:19:d5:b9:33:92:c5:61:89:56:a8:
+ 4f:48:cf:9a:a0:3e:95:f0:1f:b7:c9:de:82:89:09:
+ b0:87:a5:c5:71:2c:71:3b:72:4a:0a:51:c4:c4:7d:
+ ac:84:c3:9b:60:3d:ff:0c:52:05:23:4d:57:57:06:
+ 60:17
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 88:1C:D6:E6:0D:8F:83:DE:9D:9C:2E:3E:1E:E5:61:82:EA:2D:11:F6
+ X509v3 Authority Key Identifier:
+ keyid:88:1C:D6:E6:0D:8F:83:DE:9D:9C:2E:3E:1E:E5:61:82:EA:2D:11:F6
+
+ Authority Information Access:
+ CA Issuers - URI:http://url-for-aia/Root.cer
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://url-for-crl/Root.crl
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:1
+ Signature Algorithm: sha256WithRSAEncryption
+ 2e:81:16:b6:af:49:9b:93:4d:84:34:9c:f0:43:ee:76:91:f5:
+ 88:9e:6b:cd:a8:95:f2:5e:10:19:f0:41:98:b2:ac:38:2a:ac:
+ 3e:4c:0f:49:0b:b9:fd:97:d3:c9:61:6c:8b:7d:26:06:1d:65:
+ 7e:e8:92:23:07:82:cc:3c:c9:c7:32:7b:2e:e2:3e:e8:42:52:
+ 29:9f:6d:8f:7d:34:57:37:7a:71:8f:f1:28:33:70:aa:59:88:
+ 12:95:74:82:60:d0:14:50:b5:d4:5a:ad:7c:03:85:ab:84:c9:
+ e5:bf:7a:4a:3e:1a:d0:44:0b:bc:e1:ae:3b:48:e9:00:1c:92:
+ 1b:b5:40:a4:e6:65:88:ec:3b:6e:ab:da:37:10:b7:6d:45:e5:
+ 70:89:eb:e4:21:68:2e:77:e6:de:25:e3:5d:7a:a0:f1:33:4c:
+ cc:e2:8b:a9:c8:fd:dc:0b:4b:9e:4c:5c:7c:86:0f:d4:ab:f9:
+ e0:c8:c0:82:76:38:55:d3:dc:4d:57:d0:ca:76:63:9f:92:5c:
+ ff:5f:1b:bd:b6:39:5e:0f:5f:93:0b:86:23:9e:08:d3:e4:11:
+ 02:5f:5f:bd:00:af:d3:22:c0:14:3a:f4:4b:8b:fb:be:5e:b7:
+ 1c:34:e1:20:69:5d:7c:d9:f5:86:28:ab:92:a6:31:6b:fe:1d:
+ 03:00:f0:89
+-----BEGIN TRUSTED_CERTIFICATE-----
+MIIDaDCCAlCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290
+MB4XDTE1MDEwMTEyMDAwMFoXDTE2MDEwMTEyMDAwMFowDzENMAsGA1UEAwwEUm9v
+dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKOQDFaTNNomU26p1Qe5
+gzBwhWntGGdyux3EBv+ouAB1/Tis8eJKhiFNAXf88y2QlH4ULIqJws1Cpa7+esqd
+RHgh9qtt08iKB1frIhDPHkTypCPnEEYe1CFgnAFy/8ogyEjErbAXKPMUr0llUlJY
+mhtoGp136WFSVAuB5AvHLbMtqp4WH1HsfectLObEiIE+G+HnHyESIUfsFKXZq6Ir
+rB88sqXBaU5ViGboWk2dCCcc/s1isJVixEv/EhFM2BBmpNAp2tV5t+4Z1bkzksVh
+iVaoT0jPmqA+lfAft8negokJsIelxXEscTtySgpRxMR9rITDm2A9/wxSBSNNV1cG
+YBcCAwEAAaOBzjCByzAdBgNVHQ4EFgQUiBzW5g2Pg96dnC4+HuVhguotEfYwHwYD
+VR0jBBgwFoAUiBzW5g2Pg96dnC4+HuVhguotEfYwNwYIKwYBBQUHAQEEKzApMCcG
+CCsGAQUFBzAChhtodHRwOi8vdXJsLWZvci1haWEvUm9vdC5jZXIwLAYDVR0fBCUw
+IzAhoB+gHYYbaHR0cDovL3VybC1mb3ItY3JsL1Jvb3QuY3JsMA4GA1UdDwEB/wQE
+AwIBBjASBgNVHRMBAf8ECDAGAQH/AgEBMA0GCSqGSIb3DQEBCwUAA4IBAQAugRa2
+r0mbk02ENJzwQ+52kfWInmvNqJXyXhAZ8EGYsqw4Kqw+TA9JC7n9l9PJYWyLfSYG
+HWV+6JIjB4LMPMnHMnsu4j7oQlIpn22PfTRXN3pxj/EoM3CqWYgSlXSCYNAUULXU
+Wq18A4WrhMnlv3pKPhrQRAu84a47SOkAHJIbtUCk5mWI7Dtuq9o3ELdtReVwievk
+IWgud+beJeNdeqDxM0zM4oupyP3cC0ueTFx8hg/Uq/ngyMCCdjhV09xNV9DKdmOf
+klz/Xxu9tjleD1+TC4YjngjT5BECX1+9AK/TIsAUOvRLi/u+XrccNOEgaV182fWG
+KKuSpjFr/h0DAPCJ
+-----END TRUSTED_CERTIFICATE-----
+
+-----BEGIN TIME-----
+MTUwMzAyMTIwMDAwWg==
+-----END TIME-----
+
+-----BEGIN VERIFY_RESULT-----
+RkFJTA==
+-----END VERIFY_RESULT-----
diff --git a/net/net.gypi b/net/net.gypi
index acf8306..18236aa 100644
--- a/net/net.gypi
+++ b/net/net.gypi
@@ -2407,6 +2407,7 @@
'data/verify_certificate_chain_unittest/basic-constraints-pathlen-0-self-issued.pem',
'data/verify_certificate_chain_unittest/common.py',
'data/verify_certificate_chain_unittest/expired-intermediary.pem',
+ 'data/verify_certificate_chain_unittest/expired-root.pem',
'data/verify_certificate_chain_unittest/expired-target-notBefore.pem',
'data/verify_certificate_chain_unittest/expired-target.pem',
'data/verify_certificate_chain_unittest/generate-all.sh',
@@ -2441,6 +2442,7 @@
'data/verify_certificate_chain_unittest/intermediary-unknown-non-critical-extension.pem',
'data/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal-anchor.pem',
'data/verify_certificate_chain_unittest/issuer-and-subject-not-byte-for-byte-equal.pem',
+ 'data/verify_certificate_chain_unittest/non-self-signed-root.pem',
'data/verify_certificate_chain_unittest/openssl_conf.py',
'data/verify_certificate_chain_unittest/target-and-intermediary.pem',
'data/verify_certificate_chain_unittest/target-has-keycertsign-but-not-ca.pem',
@@ -2453,6 +2455,7 @@
'data/verify_certificate_chain_unittest/target-wrong-signature.pem',
'data/verify_certificate_chain_unittest/unknown-root.pem',
'data/verify_certificate_chain_unittest/violates-basic-constraints-pathlen-0.pem',
+ 'data/verify_certificate_chain_unittest/violates-pathlen-1-root.pem',
'data/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap-dupe_attr.pem',
'data/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap-extra_attr.pem',
'data/verify_name_match_unittest/names/ascii-BMPSTRING-case_swap-extra_rdn.pem',