diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2016-01-25 11:39:07 +0100 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> | 2016-01-25 15:20:42 +0000 |
commit | 6c91641271e536ffaa88a1dff5127e42ee99a91e (patch) | |
tree | 703d9dd49602377ddc90cbf886aad37913f2496b /chromium/net/cert | |
parent | b145b7fafd36f0c260d6a768c81fc14e32578099 (diff) | |
download | qtwebengine-chromium-6c91641271e536ffaa88a1dff5127e42ee99a91e.tar.gz |
BASELINE: Update Chromium to 49.0.2623.23
Also adds missing printing sources.
Change-Id: I3726b8f0c7d6751c9fc846096c571fadca7108cd
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Diffstat (limited to 'chromium/net/cert')
105 files changed, 7865 insertions, 2689 deletions
diff --git a/chromium/net/cert/asn1_util.cc b/chromium/net/cert/asn1_util.cc index 4bc37a67757..315ca75e648 100644 --- a/chromium/net/cert/asn1_util.cc +++ b/chromium/net/cert/asn1_util.cc @@ -4,98 +4,20 @@ #include "net/cert/asn1_util.h" +#include "net/der/input.h" +#include "net/der/parser.h" + namespace net { namespace asn1 { -bool ParseElement(base::StringPiece* in, - unsigned tag_value, - base::StringPiece* out, - unsigned *out_header_len) { - const uint8_t* data = reinterpret_cast<const uint8_t*>(in->data()); - - // We don't support kAny and kOptional at the same time. - if ((tag_value & kAny) && (tag_value & kOptional)) - return false; - - if (in->empty() && (tag_value & kOptional)) { - if (out_header_len) - *out_header_len = 0; - if (out) - *out = base::StringPiece(); - return true; - } - - if (in->size() < 2) - return false; - - if (tag_value != kAny && - static_cast<unsigned char>(data[0]) != (tag_value & 0xff)) { - if (tag_value & kOptional) { - if (out_header_len) - *out_header_len = 0; - if (out) - *out = base::StringPiece(); - return true; - } - return false; - } - - size_t len = 0; - if ((data[1] & 0x80) == 0) { - // short form length - if (out_header_len) - *out_header_len = 2; - len = static_cast<size_t>(data[1]) + 2; - } else { - // long form length - const unsigned num_bytes = data[1] & 0x7f; - if (num_bytes == 0 || num_bytes > 2) - return false; - if (in->size() < 2 + num_bytes) - return false; - len = data[2]; - if (num_bytes == 2) { - if (len == 0) { - // the length encoding must be minimal. - return false; - } - len <<= 8; - len += data[3]; - } - if (len < 128) { - // the length should have been encoded in short form. This distinguishes - // DER from BER encoding. - return false; - } - if (out_header_len) - *out_header_len = 2 + num_bytes; - len += 2 + num_bytes; - } - - if (in->size() < len) - return false; - if (out) - *out = base::StringPiece(in->data(), len); - in->remove_prefix(len); - return true; -} +namespace { -bool GetElement(base::StringPiece* in, - unsigned tag_value, - base::StringPiece* out) { - unsigned header_len; - if (!ParseElement(in, tag_value, out, &header_len)) - return false; - if (out) - out->remove_prefix(header_len); - return true; -} - -// SeekToSPKI changes |cert| so that it points to a suffix of the -// TBSCertificate where the suffix begins at the start of the ASN.1 -// SubjectPublicKeyInfo value. -static bool SeekToSPKI(base::StringPiece* cert) { +// Parses input |in| which should point to the beginning of a Certificate, and +// sets |*tbs_certificate| ready to parse the SubjectPublicKeyInfo. If parsing +// fails, this function returns false and |*tbs_certificate| is left in an +// undefined state. +bool SeekToSPKI(der::Input in, der::Parser* tbs_certificate) { // From RFC 5280, section 4.1 // Certificate ::= SEQUENCE { // tbsCertificate TBSCertificate, @@ -110,50 +32,55 @@ static bool SeekToSPKI(base::StringPiece* cert) { // validity Validity, // subject Name, // subjectPublicKeyInfo SubjectPublicKeyInfo, + // ... } - base::StringPiece certificate; - if (!GetElement(cert, kSEQUENCE, &certificate)) + der::Parser parser(in); + der::Parser certificate; + if (!parser.ReadSequence(&certificate)) return false; // We don't allow junk after the certificate. - if (!cert->empty()) + if (parser.HasMore()) return false; - base::StringPiece tbs_certificate; - if (!GetElement(&certificate, kSEQUENCE, &tbs_certificate)) + if (!certificate.ReadSequence(tbs_certificate)) return false; - if (!GetElement(&tbs_certificate, - kOptional | kConstructed | kContextSpecific | 0, - NULL)) { + bool unused; + if (!tbs_certificate->SkipOptionalTag( + der::kTagConstructed | der::kTagContextSpecific | 0, &unused)) { return false; } // serialNumber - if (!GetElement(&tbs_certificate, kINTEGER, NULL)) + if (!tbs_certificate->SkipTag(der::kInteger)) return false; // signature - if (!GetElement(&tbs_certificate, kSEQUENCE, NULL)) + if (!tbs_certificate->SkipTag(der::kSequence)) return false; // issuer - if (!GetElement(&tbs_certificate, kSEQUENCE, NULL)) + if (!tbs_certificate->SkipTag(der::kSequence)) return false; // validity - if (!GetElement(&tbs_certificate, kSEQUENCE, NULL)) + if (!tbs_certificate->SkipTag(der::kSequence)) return false; // subject - if (!GetElement(&tbs_certificate, kSEQUENCE, NULL)) + if (!tbs_certificate->SkipTag(der::kSequence)) return false; - *cert = tbs_certificate; return true; } +} // namespace + bool ExtractSPKIFromDERCert(base::StringPiece cert, base::StringPiece* spki_out) { - if (!SeekToSPKI(&cert)) + der::Parser parser; + if (!SeekToSPKI(der::Input(cert), &parser)) return false; - if (!ParseElement(&cert, kSEQUENCE, spki_out, NULL)) + der::Input spki; + if (!parser.ReadRawTLV(&spki)) return false; + *spki_out = spki.AsStringPiece(); return true; } @@ -169,18 +96,20 @@ bool ExtractSubjectPublicKeyFromSPKI(base::StringPiece spki, // parameters ANY DEFINED BY algorithm OPTIONAL } // Step into SubjectPublicKeyInfo sequence. - base::StringPiece spki_contents; - if (!asn1::GetElement(&spki, asn1::kSEQUENCE, &spki_contents)) + der::Parser parser((der::Input(spki))); + der::Parser spki_parser; + if (!parser.ReadSequence(&spki_parser)) return false; // Step over algorithm field (a SEQUENCE). - base::StringPiece algorithm; - if (!asn1::GetElement(&spki_contents, asn1::kSEQUENCE, &algorithm)) + if (!spki_parser.SkipTag(der::kSequence)) return false; // Extract the subjectPublicKey field. - if (!asn1::GetElement(&spki_contents, asn1::kBITSTRING, spk_out)) + der::Input spk; + if (!spki_parser.ReadTag(der::kBitString, &spk)) return false; + *spk_out = spk.AsStringPiece(); return true; } @@ -190,7 +119,9 @@ bool ExtractCRLURLsFromDERCert(base::StringPiece cert, urls_out->clear(); std::vector<base::StringPiece> tmp_urls_out; - if (!SeekToSPKI(&cert)) + bool present; + der::Parser tbs_cert_parser; + if (!SeekToSPKI(der::Input(cert), &tbs_cert_parser)) return false; // From RFC 5280, section 4.1 @@ -199,63 +130,71 @@ bool ExtractCRLURLsFromDERCert(base::StringPiece cert, // subjectPublicKeyInfo SubjectPublicKeyInfo, // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, - // extensions [3] EXPLICIT Extensions OPTIONAL + // extensions [3] EXPLICIT Extensions OPTIONAL } // subjectPublicKeyInfo - if (!GetElement(&cert, kSEQUENCE, NULL)) + if (!tbs_cert_parser.SkipTag(der::kSequence)) return false; // issuerUniqueID - if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 1, NULL)) + if (!tbs_cert_parser.SkipOptionalTag( + der::kTagConstructed | der::kTagContextSpecific | 1, &present)) { return false; + } // subjectUniqueID - if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 2, NULL)) + if (!tbs_cert_parser.SkipOptionalTag( + der::kTagConstructed | der::kTagContextSpecific | 2, &present)) { return false; + } - base::StringPiece extensions_seq; - if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 3, - &extensions_seq)) { + der::Input extensions; + if (!tbs_cert_parser.ReadOptionalTag( + der::kTagConstructed | der::kTagContextSpecific | 3, &extensions, + &present)) { return false; } - if (extensions_seq.empty()) + if (!present) return true; // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension // Extension ::= SEQUENCE { // extnID OBJECT IDENTIFIER, // critical BOOLEAN DEFAULT FALSE, - // extnValue OCTET STRING + // extnValue OCTET STRING } - // |extensions_seq| was EXPLICITly tagged, so we still need to remove the + // |extensions| was EXPLICITly tagged, so we still need to remove the // ASN.1 SEQUENCE header. - base::StringPiece extensions; - if (!GetElement(&extensions_seq, kSEQUENCE, &extensions)) + der::Parser explicit_extensions_parser(extensions); + der::Parser extensions_parser; + if (!explicit_extensions_parser.ReadSequence(&extensions_parser)) return false; - while (extensions.size() > 0) { - base::StringPiece extension; - if (!GetElement(&extensions, kSEQUENCE, &extension)) + if (explicit_extensions_parser.HasMore()) + return false; + + while (extensions_parser.HasMore()) { + der::Parser extension_parser; + if (!extensions_parser.ReadSequence(&extension_parser)) return false; - base::StringPiece oid; - if (!GetElement(&extension, kOID, &oid)) + der::Input oid; + if (!extension_parser.ReadTag(der::kOid, &oid)) return false; // kCRLDistributionPointsOID is the DER encoding of the OID for the X.509 // CRL Distribution Points extension. static const uint8_t kCRLDistributionPointsOID[] = {0x55, 0x1d, 0x1f}; - if (oid.size() != sizeof(kCRLDistributionPointsOID) || - memcmp(oid.data(), kCRLDistributionPointsOID, oid.size()) != 0) { + if (!oid.Equals(der::Input(kCRLDistributionPointsOID))) continue; - } // critical - GetElement(&extension, kBOOLEAN, NULL); + if (!extension_parser.SkipOptionalTag(der::kBool, &present)) + return false; // extnValue - base::StringPiece extension_value; - if (!GetElement(&extension, kOCTETSTRING, &extension_value)) + der::Input extension_value; + if (!extension_parser.ReadTag(der::kOctetString, &extension_value)) return false; // RFC 5280, section 4.2.1.13. @@ -267,56 +206,80 @@ bool ExtractCRLURLsFromDERCert(base::StringPiece cert, // reasons [1] ReasonFlags OPTIONAL, // cRLIssuer [2] GeneralNames OPTIONAL } - base::StringPiece distribution_points; - if (!GetElement(&extension_value, kSEQUENCE, &distribution_points)) + der::Parser extension_value_parser(extension_value); + der::Parser distribution_points_parser; + if (!extension_value_parser.ReadSequence(&distribution_points_parser)) + return false; + if (extension_value_parser.HasMore()) return false; - while (distribution_points.size() > 0) { - base::StringPiece distrib_point; - if (!GetElement(&distribution_points, kSEQUENCE, &distrib_point)) + while (distribution_points_parser.HasMore()) { + der::Parser distrib_point_parser; + if (!distribution_points_parser.ReadSequence(&distrib_point_parser)) return false; - base::StringPiece name; - if (!GetElement(&distrib_point, kContextSpecific | kConstructed | 0, - &name)) { - // If it doesn't contain a name then we skip it. - continue; + der::Input name; + if (!distrib_point_parser.ReadOptionalTag( + der::kTagContextSpecific | der::kTagConstructed | 0, &name, + &present)) { + return false; } - - if (GetElement(&distrib_point, kContextSpecific | 1, NULL)) { - // If it contains a subset of reasons then we skip it. We aren't - // interested in subsets of CRLs and the RFC states that there MUST be - // a CRL that covers all reasons. + // If it doesn't contain a name then we skip it. + if (!present) continue; - } - if (GetElement(&distrib_point, - kContextSpecific | kConstructed | 2, NULL)) { - // If it contains a alternative issuer, then we skip it. + if (!distrib_point_parser.SkipOptionalTag(der::kTagContextSpecific | 1, + &present)) { + return false; + } + // If it contains a subset of reasons then we skip it. We aren't + // interested in subsets of CRLs and the RFC states that there MUST be + // a CRL that covers all reasons. + if (present) continue; + + if (!distrib_point_parser.SkipOptionalTag( + der::kTagContextSpecific | der::kTagConstructed | 2, &present)) { + return false; } + // If it contains a alternative issuer, then we skip it. + if (present) + continue; // DistributionPointName ::= CHOICE { // fullName [0] GeneralNames, // nameRelativeToCRLIssuer [1] RelativeDistinguishedName } - base::StringPiece general_names; - if (!GetElement(&name, - kContextSpecific | kConstructed | 0, &general_names)) { - continue; + der::Input general_names; + if (!der::Parser(name).ReadOptionalTag( + der::kTagContextSpecific | der::kTagConstructed | 0, + &general_names, &present)) { + return false; } + if (!present) + continue; // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName // GeneralName ::= CHOICE { // ... // uniformResourceIdentifier [6] IA5String, - // ... - while (general_names.size() > 0) { - base::StringPiece url; - if (GetElement(&general_names, kContextSpecific | 6, &url)) { - tmp_urls_out.push_back(url); + // ... } + der::Parser general_names_parser(general_names); + while (general_names_parser.HasMore()) { + der::Input url; + if (!general_names_parser.ReadOptionalTag(der::kTagContextSpecific | 6, + &url, &present)) { + return false; + } + if (present) { + // This does not validate that |url| is a valid IA5String. + tmp_urls_out.push_back(url.AsStringPiece()); } else { - if (!GetElement(&general_names, kAny, NULL)) + der::Tag unused_tag; + der::Input unused_value; + if (!general_names_parser.ReadTagAndValue(&unused_tag, + &unused_value)) { return false; + } } } } diff --git a/chromium/net/cert/asn1_util.h b/chromium/net/cert/asn1_util.h index fdd765d8ed8..23bc2d2cf90 100644 --- a/chromium/net/cert/asn1_util.h +++ b/chromium/net/cert/asn1_util.h @@ -14,50 +14,6 @@ namespace net { namespace asn1 { -// These are the DER encodings of the tag byte for ASN.1 objects. -static const unsigned kBOOLEAN = 0x01; -static const unsigned kINTEGER = 0x02; -static const unsigned kBITSTRING = 0x03; -static const unsigned kOCTETSTRING = 0x04; -static const unsigned kOID = 0x06; -static const unsigned kENUMERATED = 0x0A; -static const unsigned kSEQUENCE = 0x30; - -// These are flags that can be ORed with the above tag numbers. -static const unsigned kContextSpecific = 0x80; -static const unsigned kConstructed = 0x20; - -// kAny matches any tag value; -static const unsigned kAny = 0x10000; -// kOptional denotes an optional element. -static const unsigned kOptional = 0x20000; - -// ParseElement parses a DER encoded ASN1 element from |in|, requiring that -// it have the given |tag_value|. It returns true on success. The following -// limitations are imposed: -// 1) tag numbers > 31 are not permitted. -// 2) lengths > 65535 are not permitted. -// On successful return: -// |in| is advanced over the element -// |out| contains the element, including the tag and length bytes. -// |out_header_len| contains the length of the tag and length bytes in |out|. -// -// If |tag_value & kOptional| is true then *out_header_len can be zero after a -// true return value if the element was not found. -bool ParseElement(base::StringPiece* in, - unsigned tag_value, - base::StringPiece* out, - unsigned *out_header_len); - -// GetElement performs the same actions as ParseElement, except that the header -// bytes are not included in the output. -// -// If |tag_value & kOptional| is true then this function cannot distinguish -// between a missing optional element and an empty one. -NET_EXPORT_PRIVATE bool GetElement(base::StringPiece* in, - unsigned tag_value, - base::StringPiece* out); - // ExtractSPKIFromDERCert parses the DER encoded certificate in |cert| and // extracts the bytes of the SubjectPublicKeyInfo. On successful return, // |spki_out| is set to contain the SPKI, pointing into |cert|. diff --git a/chromium/net/cert/cert_database_nss.cc b/chromium/net/cert/cert_database_nss.cc index 49d27f2b07c..1ff8862e20d 100644 --- a/chromium/net/cert/cert_database_nss.cc +++ b/chromium/net/cert/cert_database_nss.cc @@ -8,6 +8,8 @@ #include <pk11pub.h> #include <secmod.h> +#include <vector> + #include "base/logging.h" #include "base/observer_list_threadsafe.h" #include "crypto/nss_util.h" @@ -15,6 +17,10 @@ #include "net/base/net_errors.h" #include "net/cert/x509_certificate.h" #include "net/cert/x509_util_nss.h" +#include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h" + +// PSM = Mozilla's Personal Security Manager. +namespace psm = mozilla_security_manager; namespace net { @@ -49,30 +55,9 @@ int CertDatabase::CheckUserCert(X509Certificate* cert_obj) { } int CertDatabase::AddUserCert(X509Certificate* cert_obj) { - CERTCertificate* cert = cert_obj->os_cert_handle(); - CK_OBJECT_HANDLE key; - crypto::ScopedPK11Slot slot(PK11_KeyForCertExists(cert, &key, NULL)); - if (!slot.get()) - return ERR_NO_PRIVATE_KEY_FOR_CERT; - - std::string nickname = x509_util::GetUniqueNicknameForSlot( - cert_obj->GetDefaultNickname(USER_CERT), - &cert->derSubject, - slot.get()); - - SECStatus rv; - { - crypto::AutoNSSWriteLock lock; - rv = PK11_ImportCert(slot.get(), cert, key, nickname.c_str(), PR_FALSE); - } - - if (rv != SECSuccess) { - LOG(ERROR) << "Couldn't import user certificate. " << PORT_GetError(); - return ERR_ADD_USER_CERT_FAILED; - } - - NotifyObserversOfCertAdded(cert_obj); - return OK; + CertificateList cert_list; + cert_list.push_back(cert_obj); + return psm::ImportUserCert(cert_list); } } // namespace net diff --git a/chromium/net/cert/cert_net_fetcher.h b/chromium/net/cert/cert_net_fetcher.h index 2d19e14a27e..afe878e2a03 100644 --- a/chromium/net/cert/cert_net_fetcher.h +++ b/chromium/net/cert/cert_net_fetcher.h @@ -5,9 +5,12 @@ #ifndef NET_CERT_CERT_NET_FETCHER_H_ #define NET_CERT_CERT_NET_FETCHER_H_ +#include <stdint.h> + #include <vector> #include "base/callback.h" +#include "base/macros.h" #include "net/base/net_errors.h" #include "net/base/net_export.h" diff --git a/chromium/net/cert/cert_verifier.cc b/chromium/net/cert/cert_verifier.cc index 3cd4a78a341..79bd0ef6bec 100644 --- a/chromium/net/cert/cert_verifier.cc +++ b/chromium/net/cert/cert_verifier.cc @@ -25,8 +25,7 @@ scoped_ptr<CertVerifier> CertVerifier::CreateDefault() { return scoped_ptr<CertVerifier>(); #else return make_scoped_ptr( - new MultiThreadedCertVerifier(CertVerifyProc::CreateDefault())) - .Pass(); + new MultiThreadedCertVerifier(CertVerifyProc::CreateDefault())); #endif } diff --git a/chromium/net/cert/cert_verify_proc.cc b/chromium/net/cert/cert_verify_proc.cc index bb379ff000c..bdb4b871b4d 100644 --- a/chromium/net/cert/cert_verify_proc.cc +++ b/chromium/net/cert/cert_verify_proc.cc @@ -9,6 +9,7 @@ #include "base/metrics/histogram.h" #include "base/metrics/histogram_macros.h" #include "base/sha1.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/time/time.h" #include "build/build_config.h" @@ -165,6 +166,18 @@ bool ExaminePublicKeys(const scoped_refptr<X509Certificate>& cert, return weak_key; } +// Beginning with Ballot 118, ratified in the Baseline Requirements v1.2.1, +// CAs MUST NOT issue SHA-1 certificates beginning on 1 January 2016. +bool IsPastSHA1DeprecationDate(const X509Certificate& cert) { + const base::Time& start = cert.valid_start(); + if (start.is_max() || start.is_null()) + return true; + // 2016-01-01 00:00:00 UTC. + const base::Time kSHA1DeprecationDate = + base::Time::FromInternalValue(INT64_C(13096080000000000)); + return start >= kSHA1DeprecationDate; +} + } // namespace // static @@ -262,8 +275,19 @@ int CertVerifyProc::Verify(X509Certificate* cert, rv = MapCertStatusToNetError(verify_result->cert_status); } + if (verify_result->has_sha1) + verify_result->cert_status |= CERT_STATUS_SHA1_SIGNATURE_PRESENT; + // Flag certificates using weak signature algorithms. - if (verify_result->has_md5) { + // The CA/Browser Forum Baseline Requirements (beginning with v1.2.1) + // prohibits SHA-1 certificates from being issued beginning on + // 1 January 2016. Ideally, all of SHA-1 in new certificates would be + // disabled on this date, but enterprises need more time to transition. + // As the risk is greatest for publicly trusted certificates, prevent + // those certificates from being trusted from that date forward. + if (verify_result->has_md5 || + (verify_result->has_sha1_leaf && verify_result->is_issued_by_known_root && + IsPastSHA1DeprecationDate(*cert))) { verify_result->cert_status |= CERT_STATUS_WEAK_SIGNATURE_ALGORITHM; // Avoid replacing a more serious error, such as an OS/library failure, // by ensuring that if verification failed, it failed with a certificate @@ -272,9 +296,6 @@ int CertVerifyProc::Verify(X509Certificate* cert, rv = MapCertStatusToNetError(verify_result->cert_status); } - if (verify_result->has_sha1) - verify_result->cert_status |= CERT_STATUS_SHA1_SIGNATURE_PRESENT; - // Flag certificates from publicly-trusted CAs that are issued to intranet // hosts. While the CA/Browser Forum Baseline Requirements (v1.1) permit // these to be issued until 1 November 2015, they represent a real risk for @@ -537,7 +558,8 @@ static bool CheckNameConstraints(const std::vector<std::string>& dns_names, if (i->size() <= (1 /* period before domain */ + domain_length)) continue; - const char* suffix = &dns_name[i->size() - domain_length - 1]; + std::string suffix = + base::ToLowerASCII(&(*i)[i->size() - domain_length - 1]); if (suffix[0] != '.') continue; if (memcmp(&suffix[1], domains[j], domain_length) != 0) @@ -601,41 +623,41 @@ bool CertVerifyProc::HasNameConstraintsViolation( }; static const PublicKeyDomainLimitation kLimits[] = { - // C=FR, ST=France, L=Paris, O=PM/SGDN, OU=DCSSI, - // CN=IGC/A/emailAddress=igca@sgdn.pm.gouv.fr - { - {0x79, 0x23, 0xd5, 0x8d, 0x0f, 0xe0, 0x3c, 0xe6, 0xab, 0xad, - 0xae, 0x27, 0x1a, 0x6d, 0x94, 0xf4, 0x14, 0xd1, 0xa8, 0x73}, - kDomainsANSSI, - }, - // C=IN, O=India PKI, CN=CCA India 2007 - // Expires: July 4th 2015. - { - {0xfe, 0xe3, 0x95, 0x21, 0x2d, 0x5f, 0xea, 0xfc, 0x7e, 0xdc, - 0xcf, 0x88, 0x3f, 0x1e, 0xc0, 0x58, 0x27, 0xd8, 0xb8, 0xe4}, - kDomainsIndiaCCA, - }, - // C=IN, O=India PKI, CN=CCA India 2011 - // Expires: March 11 2016. - { - {0xf1, 0x42, 0xf6, 0xa2, 0x7d, 0x29, 0x3e, 0xa8, 0xf9, 0x64, - 0x52, 0x56, 0xed, 0x07, 0xa8, 0x63, 0xf2, 0xdb, 0x1c, 0xdf}, - kDomainsIndiaCCA, - }, - // C=IN, O=India PKI, CN=CCA India 2014 - // Expires: March 5 2024. - { - {0x36, 0x8c, 0x4a, 0x1e, 0x2d, 0xb7, 0x81, 0xe8, 0x6b, 0xed, - 0x5a, 0x0a, 0x42, 0xb8, 0xc5, 0xcf, 0x6d, 0xb3, 0x57, 0xe1}, - kDomainsIndiaCCA, - }, - // Not a real certificate - just for testing. This is the SPKI hash of - // the keys used in net/data/ssl/certificates/name_constraint_*.crt. - { - {0x61, 0xec, 0x82, 0x8b, 0xdb, 0x5c, 0x78, 0x2a, 0x8f, 0xcc, - 0x4f, 0x0f, 0x14, 0xbb, 0x85, 0x31, 0x93, 0x9f, 0xf7, 0x3d}, - kDomainsTest, - }, + // C=FR, ST=France, L=Paris, O=PM/SGDN, OU=DCSSI, + // CN=IGC/A/emailAddress=igca@sgdn.pm.gouv.fr + { + {0x79, 0x23, 0xd5, 0x8d, 0x0f, 0xe0, 0x3c, 0xe6, 0xab, 0xad, 0xae, + 0x27, 0x1a, 0x6d, 0x94, 0xf4, 0x14, 0xd1, 0xa8, 0x73}, + kDomainsANSSI, + }, + // C=IN, O=India PKI, CN=CCA India 2007 + // Expires: July 4th 2015. + { + {0xfe, 0xe3, 0x95, 0x21, 0x2d, 0x5f, 0xea, 0xfc, 0x7e, 0xdc, 0xcf, + 0x88, 0x3f, 0x1e, 0xc0, 0x58, 0x27, 0xd8, 0xb8, 0xe4}, + kDomainsIndiaCCA, + }, + // C=IN, O=India PKI, CN=CCA India 2011 + // Expires: March 11 2016. + { + {0xf1, 0x42, 0xf6, 0xa2, 0x7d, 0x29, 0x3e, 0xa8, 0xf9, 0x64, 0x52, + 0x56, 0xed, 0x07, 0xa8, 0x63, 0xf2, 0xdb, 0x1c, 0xdf}, + kDomainsIndiaCCA, + }, + // C=IN, O=India PKI, CN=CCA India 2014 + // Expires: March 5 2024. + { + {0x36, 0x8c, 0x4a, 0x1e, 0x2d, 0xb7, 0x81, 0xe8, 0x6b, 0xed, 0x5a, + 0x0a, 0x42, 0xb8, 0xc5, 0xcf, 0x6d, 0xb3, 0x57, 0xe1}, + kDomainsIndiaCCA, + }, + // Not a real certificate - just for testing. This is the SPKI hash of + // the keys used in net/data/ssl/certificates/name_constraint_*.crt. + { + {0x48, 0x49, 0x4a, 0xc5, 0x5a, 0x3e, 0xcd, 0xc5, 0x62, 0x9f, 0xef, + 0x23, 0x14, 0xad, 0x05, 0xa9, 0x2a, 0x5c, 0x39, 0xc0}, + kDomainsTest, + }, }; for (unsigned i = 0; i < arraysize(kLimits); ++i) { diff --git a/chromium/net/cert/cert_verify_proc.h b/chromium/net/cert/cert_verify_proc.h index fdc1205b849..629fde8bf38 100644 --- a/chromium/net/cert/cert_verify_proc.h +++ b/chromium/net/cert/cert_verify_proc.h @@ -9,6 +9,7 @@ #include <vector> #include "base/gtest_prod_util.h" +#include "base/macros.h" #include "base/memory/ref_counted.h" #include "net/base/net_export.h" #include "net/cert/x509_cert_types.h" diff --git a/chromium/net/cert/cert_verify_proc_android.cc b/chromium/net/cert/cert_verify_proc_android.cc index d35f10863e0..3825b20a475 100644 --- a/chromium/net/cert/cert_verify_proc_android.cc +++ b/chromium/net/cert/cert_verify_proc_android.cc @@ -101,6 +101,8 @@ bool VerifyFromAndroidTrustManager(const std::vector<std::string>& cert_bytes, sig_alg == NID_dsaWithSHA1_2 || sig_alg == NID_sha1WithRSA || sig_alg == NID_ecdsa_with_SHA1) { verify_result->has_sha1 = true; + if (i == 0) + verify_result->has_sha1_leaf = true; } } diff --git a/chromium/net/cert/cert_verify_proc_mac.cc b/chromium/net/cert/cert_verify_proc_mac.cc index c0eb0683ffa..c4e0c41ba92 100644 --- a/chromium/net/cert/cert_verify_proc_mac.cc +++ b/chromium/net/cert/cert_verify_proc_mac.cc @@ -8,9 +8,11 @@ #include <CoreServices/CoreServices.h> #include <Security/Security.h> +#include <set> #include <string> #include <vector> +#include "base/lazy_instance.h" #include "base/logging.h" #include "base/mac/mac_logging.h" #include "base/mac/scoped_cftyperef.h" @@ -19,6 +21,7 @@ #include "base/synchronization/lock.h" #include "crypto/mac_security_services_lock.h" #include "crypto/sha2.h" +#include "net/base/hash_value.h" #include "net/base/net_errors.h" #include "net/cert/asn1_util.h" #include "net/cert/cert_status_flags.h" @@ -27,7 +30,6 @@ #include "net/cert/crl_set.h" #include "net/cert/test_root_certs.h" #include "net/cert/x509_certificate.h" -#include "net/cert/x509_certificate_known_roots_mac.h" #include "net/cert/x509_util_mac.h" // From 10.7.2 libsecurity_keychain-55035/lib/SecTrustPriv.h, for use with @@ -190,6 +192,7 @@ void GetCertChainInfo(CFArrayRef cert_chain, verify_result->has_md4 = false; verify_result->has_md5 = false; verify_result->has_sha1 = false; + verify_result->has_sha1_leaf = false; SecCertificateRef verified_cert = NULL; std::vector<SecCertificateRef> verified_chain; @@ -250,8 +253,10 @@ void GetCertChainInfo(CFArrayRef cert_chain, CSSMOIDEqual(alg_oid, &CSSMOID_SHA1WithDSA_JDK) || CSSMOIDEqual(alg_oid, &CSSMOID_ECDSA_WithSHA1)) { verify_result->has_sha1 = true; - if (i == 0) + if (i == 0) { + verify_result->has_sha1_leaf = true; *leaf_is_weak = true; + } } } if (!verified_cert) { @@ -353,20 +358,6 @@ bool CheckRevocationWithCRLSet(CFArrayRef chain, CRLSet* crl_set) { return true; } -// IsIssuedByKnownRoot returns true if the given chain is rooted at a root CA -// that we recognise as a standard root. -// static -bool IsIssuedByKnownRoot(CFArrayRef chain) { - int n = CFArrayGetCount(chain); - if (n < 1) - return false; - SecCertificateRef root_ref = reinterpret_cast<SecCertificateRef>( - const_cast<void*>(CFArrayGetValueAtIndex(chain, n - 1))); - SHA1HashValue hash = X509Certificate::CalculateFingerprint(root_ref); - return IsSHA1HashInSortedArray( - hash, &kKnownRootCertSHA1Hashes[0][0], sizeof(kKnownRootCertSHA1Hashes)); -} - // Builds and evaluates a SecTrustRef for the certificate chain contained // in |cert_array|, using the verification policies in |trust_policies|. On // success, returns OK, and updates |trust_ref|, |trust_result|, @@ -466,6 +457,59 @@ int BuildAndEvaluateSecTrustRef(CFArrayRef cert_array, return OK; } +// Helper class for managing the set of OS X Known Roots. This is only safe +// to initialize while the crypto::GetMacSecurityServicesLock() is held, due +// to calling into Security.framework functions; however, once initialized, +// it can be called at any time. +// In practice, due to lazy initialization, it's best to just always guard +// accesses with the lock. +class OSXKnownRootHelper { + public: + // IsIssuedByKnownRoot returns true if the given chain is rooted at a root CA + // that we recognise as a standard root. + bool IsIssuedByKnownRoot(CFArrayRef chain) { + // If there are no known roots, then an API failure occurred. For safety, + // assume that all certificates are issued by known roots. + if (known_roots_.empty()) + return true; + + CFIndex n = CFArrayGetCount(chain); + if (n < 1) + return false; + SecCertificateRef root_ref = reinterpret_cast<SecCertificateRef>( + const_cast<void*>(CFArrayGetValueAtIndex(chain, n - 1))); + SHA256HashValue hash = X509Certificate::CalculateFingerprint256(root_ref); + return known_roots_.find(hash) != known_roots_.end(); + } + + private: + friend struct base::DefaultLazyInstanceTraits<OSXKnownRootHelper>; + + OSXKnownRootHelper() { + CFArrayRef cert_array = NULL; + OSStatus rv = SecTrustSettingsCopyCertificates( + kSecTrustSettingsDomainSystem, &cert_array); + if (rv != noErr) { + LOG(ERROR) << "Unable to determine trusted roots; assuming all roots are " + << "trusted! Error " << rv; + return; + } + base::ScopedCFTypeRef<CFArrayRef> scoped_array(cert_array); + for (CFIndex i = 0, size = CFArrayGetCount(cert_array); i < size; ++i) { + SecCertificateRef cert = reinterpret_cast<SecCertificateRef>( + const_cast<void*>(CFArrayGetValueAtIndex(cert_array, i))); + known_roots_.insert(X509Certificate::CalculateFingerprint256(cert)); + } + } + + ~OSXKnownRootHelper() {} + + std::set<SHA256HashValue, SHA256HashValueLessThan> known_roots_; +}; + +base::LazyInstance<OSXKnownRootHelper>::Leaky g_known_roots = + LAZY_INSTANCE_INITIALIZER; + } // namespace CertVerifyProcMac::CertVerifyProcMac() {} @@ -743,7 +787,8 @@ int CertVerifyProcMac::VerifyInternal( verify_result->cert_status &= ~CERT_STATUS_NO_REVOCATION_MECHANISM; AppendPublicKeyHashes(completed_chain, &verify_result->public_key_hashes); - verify_result->is_issued_by_known_root = IsIssuedByKnownRoot(completed_chain); + verify_result->is_issued_by_known_root = + g_known_roots.Get().IsIssuedByKnownRoot(completed_chain); if (IsCertStatusError(verify_result->cert_status)) return MapCertStatusToNetError(verify_result->cert_status); diff --git a/chromium/net/cert/cert_verify_proc_nss.cc b/chromium/net/cert/cert_verify_proc_nss.cc index 9ee65ee4b34..ca8e8116f0e 100644 --- a/chromium/net/cert/cert_verify_proc_nss.cc +++ b/chromium/net/cert/cert_verify_proc_nss.cc @@ -15,6 +15,7 @@ #include <sslerr.h> #include "base/logging.h" +#include "base/macros.h" #include "build/build_config.h" #include "crypto/nss_util.h" #include "crypto/scoped_nss_types.h" @@ -165,7 +166,7 @@ void GetCertChainInfo(CERTCertList* cert_list, CERTCertificate* verified_cert = NULL; std::vector<CERTCertificate*> verified_chain; - int i = 0; + size_t i = 0; for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); !CERT_LIST_END(node, cert_list); node = CERT_LIST_NEXT(node), ++i) { @@ -215,6 +216,8 @@ void GetCertChainInfo(CERTCertList* cert_list, case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST: case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE: verify_result->has_sha1 = true; + if (i == 0) + verify_result->has_sha1_leaf = true; break; default: break; diff --git a/chromium/net/cert/cert_verify_proc_openssl.cc b/chromium/net/cert/cert_verify_proc_openssl.cc index 286b21b98bb..824a95cdc45 100644 --- a/chromium/net/cert/cert_verify_proc_openssl.cc +++ b/chromium/net/cert/cert_verify_proc_openssl.cc @@ -125,6 +125,8 @@ void GetCertChainInfo(X509_STORE_CTX* store_ctx, sig_alg == NID_dsaWithSHA1_2 || sig_alg == NID_sha1WithRSA || sig_alg == NID_ecdsa_with_SHA1) { verify_result->has_sha1 = true; + if (i == 0) + verify_result->has_sha1_leaf = true; } } } diff --git a/chromium/net/cert/cert_verify_proc_unittest.cc b/chromium/net/cert/cert_verify_proc_unittest.cc index 502cfb5bb71..bdeec339d02 100644 --- a/chromium/net/cert/cert_verify_proc_unittest.cc +++ b/chromium/net/cert/cert_verify_proc_unittest.cc @@ -10,6 +10,7 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/logging.h" +#include "base/macros.h" #include "base/sha1.h" #include "base/strings/string_number_conversions.h" #include "crypto/sha2.h" @@ -46,21 +47,18 @@ unsigned char paypal_null_fingerprint[] = { 0x1f, 0xe8, 0x1b, 0xd6, 0xab, 0x7b, 0xe8, 0xd7 }; -// Mock CertVerifyProc that will set |verify_result->is_issued_by_known_root| -// for all certificates that are Verified. -class WellKnownCaCertVerifyProc : public CertVerifyProc { +// Mock CertVerifyProc that sets the CertVerifyResult to a given value for +// all certificates that are Verify()'d +class MockCertVerifyProc : public CertVerifyProc { public: - // Initialize a CertVerifyProc that will set - // |verify_result->is_issued_by_known_root| to |is_well_known|. - explicit WellKnownCaCertVerifyProc(bool is_well_known) - : is_well_known_(is_well_known) {} - + explicit MockCertVerifyProc(const CertVerifyResult& result) + : result_(result) {} // CertVerifyProc implementation: bool SupportsAdditionalTrustAnchors() const override { return false; } bool SupportsOCSPStapling() const override { return false; } protected: - ~WellKnownCaCertVerifyProc() override {} + ~MockCertVerifyProc() override {} private: int VerifyInternal(X509Certificate* cert, @@ -71,12 +69,12 @@ class WellKnownCaCertVerifyProc : public CertVerifyProc { const CertificateList& additional_trust_anchors, CertVerifyResult* verify_result) override; - const bool is_well_known_; + const CertVerifyResult result_; - DISALLOW_COPY_AND_ASSIGN(WellKnownCaCertVerifyProc); + DISALLOW_COPY_AND_ASSIGN(MockCertVerifyProc); }; -int WellKnownCaCertVerifyProc::VerifyInternal( +int MockCertVerifyProc::VerifyInternal( X509Certificate* cert, const std::string& hostname, const std::string& ocsp_response, @@ -84,7 +82,8 @@ int WellKnownCaCertVerifyProc::VerifyInternal( CRLSet* crl_set, const CertificateList& additional_trust_anchors, CertVerifyResult* verify_result) { - verify_result->is_issued_by_known_root = is_well_known_; + *verify_result = result_; + verify_result->verified_cert = cert; return OK; } @@ -580,6 +579,11 @@ TEST_F(CertVerifyProcTest, NameConstraintsOk) { &verify_result); EXPECT_EQ(OK, error); EXPECT_EQ(0U, verify_result.cert_status); + + error = Verify(leaf.get(), "foo.test2.example.com", flags, NULL, + empty_cert_list_, &verify_result); + EXPECT_EQ(OK, error); + EXPECT_EQ(0U, verify_result.cert_status); } TEST_F(CertVerifyProcTest, NameConstraintsFailure) { @@ -841,20 +845,102 @@ TEST_F(CertVerifyProcTest, IntranetHostsRejected) { int error = 0; // Intranet names for public CAs should be flagged: - verify_proc_ = new WellKnownCaCertVerifyProc(true); + CertVerifyResult dummy_result; + dummy_result.is_issued_by_known_root = true; + verify_proc_ = new MockCertVerifyProc(dummy_result); error = Verify(cert.get(), "intranet", 0, NULL, empty_cert_list_, &verify_result); EXPECT_EQ(OK, error); EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_NON_UNIQUE_NAME); // However, if the CA is not well known, these should not be flagged: - verify_proc_ = new WellKnownCaCertVerifyProc(false); + dummy_result.Reset(); + dummy_result.is_issued_by_known_root = false; + verify_proc_ = new MockCertVerifyProc(dummy_result); error = Verify(cert.get(), "intranet", 0, NULL, empty_cert_list_, &verify_result); EXPECT_EQ(OK, error); EXPECT_FALSE(verify_result.cert_status & CERT_STATUS_NON_UNIQUE_NAME); } +// Test that a SHA-1 certificate from a publicly trusted CA issued after +// 1 January 2016 is rejected, but those issued before that date, or with +// SHA-1 in the intermediate, is not rejected. +TEST_F(CertVerifyProcTest, VerifyRejectsSHA1AfterDeprecation) { + CertVerifyResult dummy_result; + CertVerifyResult verify_result; + int error = 0; + scoped_refptr<X509Certificate> cert; + + // Publicly trusted SHA-1 leaf certificates issued before 1 January 2016 + // are accepted. + verify_result.Reset(); + dummy_result.Reset(); + dummy_result.is_issued_by_known_root = true; + dummy_result.has_sha1 = true; + dummy_result.has_sha1_leaf = true; + verify_proc_ = new MockCertVerifyProc(dummy_result); + cert = CreateCertificateChainFromFile(GetTestCertsDirectory(), + "sha1_dec_2015.pem", + X509Certificate::FORMAT_AUTO); + ASSERT_TRUE(cert); + error = Verify(cert.get(), "127.0.0.1", 0, NULL, empty_cert_list_, + &verify_result); + EXPECT_EQ(OK, error); + EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT); + + // Publicly trusted SHA-1 leaf certificates issued on/after 1 January 2016 + // are rejected. + verify_result.Reset(); + dummy_result.Reset(); + dummy_result.is_issued_by_known_root = true; + dummy_result.has_sha1 = true; + dummy_result.has_sha1_leaf = true; + verify_proc_ = new MockCertVerifyProc(dummy_result); + cert = CreateCertificateChainFromFile(GetTestCertsDirectory(), + "sha1_jan_2016.pem", + X509Certificate::FORMAT_AUTO); + ASSERT_TRUE(cert); + error = Verify(cert.get(), "127.0.0.1", 0, NULL, empty_cert_list_, + &verify_result); + EXPECT_EQ(ERR_CERT_WEAK_SIGNATURE_ALGORITHM, error); + EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM); + + // Enterprise issued SHA-1 leaf certificates issued on/after 1 January 2016 + // remain accepted until SHA-1 is disabled. + verify_result.Reset(); + dummy_result.Reset(); + dummy_result.is_issued_by_known_root = false; + dummy_result.has_sha1 = true; + dummy_result.has_sha1_leaf = true; + verify_proc_ = new MockCertVerifyProc(dummy_result); + cert = CreateCertificateChainFromFile(GetTestCertsDirectory(), + "sha1_jan_2016.pem", + X509Certificate::FORMAT_AUTO); + ASSERT_TRUE(cert); + error = Verify(cert.get(), "127.0.0.1", 0, NULL, empty_cert_list_, + &verify_result); + EXPECT_EQ(OK, error); + EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT); + + // Publicly trusted SHA-1 intermediates issued on/after 1 January 2016 are, + // unfortunately, accepted. This can arise due to OS path building quirks. + verify_result.Reset(); + dummy_result.Reset(); + dummy_result.is_issued_by_known_root = true; + dummy_result.has_sha1 = true; + dummy_result.has_sha1_leaf = false; + verify_proc_ = new MockCertVerifyProc(dummy_result); + cert = CreateCertificateChainFromFile(GetTestCertsDirectory(), + "sha1_jan_2016.pem", + X509Certificate::FORMAT_AUTO); + ASSERT_TRUE(cert); + error = Verify(cert.get(), "127.0.0.1", 0, NULL, empty_cert_list_, + &verify_result); + EXPECT_EQ(OK, error); + EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT); +} + // Test that the certificate returned in CertVerifyResult is able to reorder // certificates that are not ordered from end-entity to root. While this is // a protocol violation if sent during a TLS handshake, if multiple sources @@ -1280,7 +1366,8 @@ enum ExpectedAlgorithms { EXPECT_MD2 = 1 << 0, EXPECT_MD4 = 1 << 1, EXPECT_MD5 = 1 << 2, - EXPECT_SHA1 = 1 << 3 + EXPECT_SHA1 = 1 << 3, + EXPECT_SHA1_LEAF = 1 << 4, }; struct WeakDigestTestData { @@ -1348,6 +1435,8 @@ TEST_P(CertVerifyProcWeakDigestTest, Verify) { EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD4), verify_result.has_md4); EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD5), verify_result.has_md5); EXPECT_EQ(!!(data.expected_algorithms & EXPECT_SHA1), verify_result.has_sha1); + EXPECT_EQ(!!(data.expected_algorithms & EXPECT_SHA1_LEAF), + verify_result.has_sha1_leaf); EXPECT_FALSE(verify_result.is_issued_by_additional_trust_anchor); @@ -1393,15 +1482,15 @@ TEST_P(CertVerifyProcWeakDigestTest, Verify) { // The signature algorithm of the root CA should not matter. const WeakDigestTestData kVerifyRootCATestData[] = { - { "weak_digest_md5_root.pem", "weak_digest_sha1_intermediate.pem", - "weak_digest_sha1_ee.pem", EXPECT_SHA1 }, + {"weak_digest_md5_root.pem", "weak_digest_sha1_intermediate.pem", + "weak_digest_sha1_ee.pem", EXPECT_SHA1 | EXPECT_SHA1_LEAF}, #if defined(USE_OPENSSL_CERTS) || defined(OS_WIN) - // MD4 is not supported by OS X / NSS - { "weak_digest_md4_root.pem", "weak_digest_sha1_intermediate.pem", - "weak_digest_sha1_ee.pem", EXPECT_SHA1 }, + // MD4 is not supported by OS X / NSS + {"weak_digest_md4_root.pem", "weak_digest_sha1_intermediate.pem", + "weak_digest_sha1_ee.pem", EXPECT_SHA1 | EXPECT_SHA1_LEAF}, #endif - { "weak_digest_md2_root.pem", "weak_digest_sha1_intermediate.pem", - "weak_digest_sha1_ee.pem", EXPECT_SHA1 }, + {"weak_digest_md2_root.pem", "weak_digest_sha1_intermediate.pem", + "weak_digest_sha1_ee.pem", EXPECT_SHA1 | EXPECT_SHA1_LEAF}, }; #if defined(OS_ANDROID) #define MAYBE_VerifyRoot DISABLED_VerifyRoot @@ -1414,15 +1503,15 @@ INSTANTIATE_TEST_CASE_P(MAYBE_VerifyRoot, // The signature algorithm of intermediates should be properly detected. const WeakDigestTestData kVerifyIntermediateCATestData[] = { - { "weak_digest_sha1_root.pem", "weak_digest_md5_intermediate.pem", - "weak_digest_sha1_ee.pem", EXPECT_MD5 | EXPECT_SHA1 }, + {"weak_digest_sha1_root.pem", "weak_digest_md5_intermediate.pem", + "weak_digest_sha1_ee.pem", EXPECT_MD5 | EXPECT_SHA1 | EXPECT_SHA1_LEAF}, #if defined(USE_OPENSSL_CERTS) || defined(OS_WIN) - // MD4 is not supported by OS X / NSS - { "weak_digest_sha1_root.pem", "weak_digest_md4_intermediate.pem", - "weak_digest_sha1_ee.pem", EXPECT_MD4 | EXPECT_SHA1 }, + // MD4 is not supported by OS X / NSS + {"weak_digest_sha1_root.pem", "weak_digest_md4_intermediate.pem", + "weak_digest_sha1_ee.pem", EXPECT_MD4 | EXPECT_SHA1 | EXPECT_SHA1_LEAF}, #endif - { "weak_digest_sha1_root.pem", "weak_digest_md2_intermediate.pem", - "weak_digest_sha1_ee.pem", EXPECT_MD2 | EXPECT_SHA1 }, + {"weak_digest_sha1_root.pem", "weak_digest_md2_intermediate.pem", + "weak_digest_sha1_ee.pem", EXPECT_MD2 | EXPECT_SHA1 | EXPECT_SHA1_LEAF}, }; // Disabled on NSS - MD4 is not supported, and MD2 and MD5 are disabled. #if defined(USE_NSS_CERTS) || defined(OS_IOS) || defined(OS_ANDROID) @@ -1461,15 +1550,15 @@ WRAPPED_INSTANTIATE_TEST_CASE_P(MAYBE_VerifyEndEntity, // Incomplete chains should still report the status of the intermediate. const WeakDigestTestData kVerifyIncompleteIntermediateTestData[] = { - { NULL, "weak_digest_md5_intermediate.pem", "weak_digest_sha1_ee.pem", - EXPECT_MD5 | EXPECT_SHA1 }, + {NULL, "weak_digest_md5_intermediate.pem", "weak_digest_sha1_ee.pem", + EXPECT_MD5 | EXPECT_SHA1 | EXPECT_SHA1_LEAF}, #if defined(USE_OPENSSL_CERTS) || defined(OS_WIN) - // MD4 is not supported by OS X / NSS - { NULL, "weak_digest_md4_intermediate.pem", "weak_digest_sha1_ee.pem", - EXPECT_MD4 | EXPECT_SHA1 }, + // MD4 is not supported by OS X / NSS + {NULL, "weak_digest_md4_intermediate.pem", "weak_digest_sha1_ee.pem", + EXPECT_MD4 | EXPECT_SHA1 | EXPECT_SHA1_LEAF}, #endif - { NULL, "weak_digest_md2_intermediate.pem", "weak_digest_sha1_ee.pem", - EXPECT_MD2 | EXPECT_SHA1 }, + {NULL, "weak_digest_md2_intermediate.pem", "weak_digest_sha1_ee.pem", + EXPECT_MD2 | EXPECT_SHA1 | EXPECT_SHA1_LEAF}, }; // Disabled on NSS - libpkix does not return constructed chains on error, // preventing us from detecting/inspecting the verified chain. diff --git a/chromium/net/cert/cert_verify_proc_whitelist.cc b/chromium/net/cert/cert_verify_proc_whitelist.cc index 99623278590..c2437f8c4de 100644 --- a/chromium/net/cert/cert_verify_proc_whitelist.cc +++ b/chromium/net/cert/cert_verify_proc_whitelist.cc @@ -22,10 +22,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xa0, 0xa8, 0xbb, 0xa5, 0x0a, 0x72, 0xd4, 0xe1, 0x83, 0x9a, 0x94, 0xfb, 0x1a, 0x58, 0x5a, 0xd7, 0x2a, 0x7a, 0xac, 0x3c, 0x72, 0x56, 0x1f, 0xc0 }, - { 0x00, 0xc6, 0x81, 0x13, 0x16, 0xbd, 0x9c, 0x91, - 0x98, 0x6e, 0xa9, 0x7e, 0x2c, 0x30, 0xab, 0xef, - 0xa0, 0xd5, 0x68, 0x04, 0x89, 0x0d, 0x65, 0x8d, - 0xff, 0x08, 0x59, 0x11, 0x6e, 0xb4, 0xc2, 0x32 }, { 0x00, 0xde, 0xff, 0x68, 0x2e, 0x35, 0x10, 0x22, 0xcc, 0x3b, 0xbb, 0x4e, 0xb5, 0x88, 0x0a, 0x97, 0x27, 0x88, 0x0a, 0xf3, 0x52, 0xfb, 0xbe, 0x2f, @@ -78,10 +74,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x4d, 0x8e, 0x3b, 0xc9, 0xc8, 0x7c, 0x02, 0x4e, 0x4b, 0xb7, 0x0d, 0xc6, 0x30, 0x1b, 0xcd, 0xe3, 0x24, 0x12, 0xb4, 0xce, 0x8c, 0x0c, 0x14, 0x58 }, - { 0x03, 0xde, 0x42, 0xaf, 0x1f, 0x30, 0x9f, 0x95, - 0xf6, 0xc8, 0x91, 0x03, 0xea, 0x98, 0x7e, 0x84, - 0xd3, 0x18, 0x6b, 0x60, 0x65, 0xf9, 0x60, 0x7a, - 0x06, 0x6a, 0x30, 0x2b, 0x58, 0x05, 0xeb, 0x3b }, { 0x03, 0xe0, 0x6e, 0x0b, 0x7a, 0x2c, 0xba, 0xe4, 0xb6, 0x8b, 0xce, 0x5f, 0x83, 0xe7, 0xa9, 0x31, 0x6e, 0xd7, 0x82, 0x3e, 0x8d, 0x94, 0x85, 0x38, @@ -102,10 +94,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x55, 0xdf, 0xe2, 0x54, 0xc8, 0x20, 0xa0, 0x77, 0xff, 0x11, 0xca, 0xfc, 0x83, 0xb5, 0x0e, 0x0a, 0x13, 0xf1, 0x3d, 0x59, 0xd3, 0xca, 0x6c, 0xaf }, - { 0x04, 0x71, 0x57, 0x2c, 0x03, 0x03, 0x7d, 0xee, - 0x2b, 0x40, 0x09, 0x6e, 0xe8, 0xaa, 0x37, 0x82, - 0xc6, 0xfa, 0x81, 0x42, 0xcc, 0xa2, 0x68, 0x19, - 0x09, 0xda, 0xe8, 0xc4, 0x66, 0xd0, 0x58, 0x4e }, { 0x04, 0x80, 0x71, 0x3a, 0x76, 0x91, 0x7e, 0xb1, 0x7f, 0xb5, 0x4c, 0x93, 0xee, 0xd3, 0xfd, 0x8a, 0x98, 0x2b, 0xd9, 0x06, 0x9c, 0x69, 0xab, 0xea, @@ -254,10 +242,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x23, 0x4a, 0x86, 0xc7, 0x0d, 0x49, 0x8c, 0x62, 0x60, 0x7f, 0x37, 0x44, 0xea, 0x71, 0xf1, 0x83, 0x1d, 0xcf, 0xca, 0xf3, 0xaf, 0x15, 0x56, 0x9c }, - { 0x0f, 0x43, 0xfc, 0x12, 0x47, 0x01, 0xfe, 0x29, - 0xb7, 0x14, 0xf3, 0x05, 0xe2, 0x61, 0xb6, 0x32, - 0x04, 0x82, 0xc0, 0x09, 0x6f, 0xfe, 0xad, 0x35, - 0xe1, 0xf8, 0xe6, 0x32, 0xc6, 0x4d, 0x7b, 0x20 }, { 0x0f, 0x57, 0xed, 0x67, 0x2b, 0xac, 0x50, 0x14, 0x89, 0xe4, 0xf4, 0xab, 0x4b, 0x1d, 0xb1, 0x75, 0x81, 0xfe, 0xb8, 0x76, 0x0f, 0xfb, 0xc0, 0x8a, @@ -298,14 +282,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x5f, 0xdc, 0xac, 0x20, 0xa2, 0x36, 0xf8, 0x6e, 0x94, 0xe5, 0xee, 0x58, 0x59, 0xd8, 0xfd, 0x45, 0xe9, 0xe9, 0xc5, 0xa6, 0xc5, 0xc0, 0xa4, 0x13 }, - { 0x13, 0xbd, 0x07, 0x7b, 0x8a, 0x9f, 0x46, 0xff, - 0x8f, 0x2f, 0xfd, 0x23, 0x6e, 0x53, 0xa7, 0x2c, - 0x3b, 0x87, 0xf3, 0x4c, 0xc9, 0xdb, 0xb5, 0x81, - 0x7e, 0x4d, 0xba, 0x1b, 0xd3, 0xbc, 0x9e, 0x5f }, - { 0x13, 0xe0, 0x1b, 0xe5, 0x72, 0xdc, 0x11, 0xfa, - 0xc3, 0xb4, 0x7a, 0xe6, 0x8f, 0x92, 0xdc, 0x00, - 0xf1, 0x00, 0xbf, 0x77, 0x53, 0x7b, 0x89, 0x47, - 0xf4, 0xc1, 0x1c, 0x25, 0xa0, 0xb6, 0xf9, 0xf6 }, { 0x14, 0x21, 0x28, 0xa6, 0x65, 0x1c, 0xdc, 0x18, 0x70, 0xc2, 0x67, 0x5e, 0xc0, 0xb0, 0xef, 0x32, 0xb5, 0xd4, 0xc1, 0x55, 0x35, 0x8e, 0x7e, 0xd9, @@ -334,14 +310,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xbf, 0x2f, 0x83, 0xc2, 0x80, 0xd1, 0x24, 0x6d, 0xce, 0x02, 0xa6, 0x28, 0x31, 0x26, 0xc6, 0x17, 0xe4, 0x17, 0xd2, 0xb7, 0xea, 0xc1, 0x19, 0x24 }, - { 0x15, 0x75, 0x93, 0x18, 0x80, 0x19, 0x6d, 0xe8, - 0x0d, 0x97, 0xfe, 0xf1, 0x85, 0xd2, 0x7a, 0xf6, - 0xad, 0x6b, 0x5b, 0x04, 0x0d, 0x87, 0x6c, 0xdf, - 0x4a, 0x39, 0xb5, 0xb7, 0x8e, 0x96, 0xb7, 0xd5 }, - { 0x15, 0xb0, 0xd9, 0xbe, 0xd6, 0x2b, 0xd8, 0x96, - 0x11, 0x59, 0xfe, 0x7e, 0x88, 0x92, 0xf8, 0xe8, - 0xeb, 0xb0, 0xce, 0x81, 0xe6, 0x8d, 0xea, 0xdd, - 0x29, 0x0f, 0xdd, 0xce, 0xd0, 0x9d, 0xe7, 0xf1 }, { 0x15, 0xcf, 0x2f, 0x78, 0xe6, 0x79, 0x62, 0x2c, 0x06, 0x78, 0xdc, 0x5b, 0xa8, 0x03, 0x84, 0x7a, 0xbd, 0xb5, 0xea, 0x64, 0x31, 0x65, 0x3e, 0xc2, @@ -362,18 +330,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xfd, 0x9a, 0x79, 0xf2, 0xfb, 0xba, 0x9a, 0xca, 0x46, 0xce, 0xad, 0x95, 0x43, 0x05, 0xfe, 0xe5, 0xb1, 0x3b, 0x5d, 0x53, 0xdb, 0x7c, 0x1d, 0xb1 }, - { 0x17, 0x29, 0xb3, 0x34, 0x7a, 0x7d, 0x93, 0x73, - 0x17, 0xe3, 0xda, 0x5c, 0xc7, 0xf7, 0xb0, 0xd8, - 0xfd, 0x97, 0x72, 0x24, 0x7a, 0x57, 0x99, 0x93, - 0x9a, 0x44, 0xd3, 0xa9, 0x7a, 0x50, 0xb9, 0xd9 }, { 0x17, 0x3d, 0xe2, 0x60, 0xe2, 0x2d, 0x76, 0x9d, 0x2d, 0x54, 0x99, 0xc8, 0x22, 0x0d, 0x86, 0xed, 0xe3, 0x48, 0xda, 0x1e, 0x57, 0xc1, 0xe7, 0xc8, 0x15, 0x07, 0xfb, 0x3e, 0x6b, 0xd7, 0x3b, 0x7f }, - { 0x17, 0x46, 0x68, 0x4e, 0x66, 0x21, 0x77, 0x68, - 0x70, 0xde, 0x55, 0x65, 0xdf, 0xd3, 0x3a, 0x30, - 0x92, 0x77, 0x18, 0x59, 0x6c, 0x01, 0x30, 0xf8, - 0x77, 0x4b, 0xe9, 0x9c, 0xd2, 0xa2, 0x51, 0x06 }, { 0x17, 0x59, 0x7e, 0x00, 0x45, 0x6c, 0x38, 0x32, 0xe1, 0x85, 0x1c, 0x30, 0x0c, 0xd5, 0x52, 0xc2, 0xe7, 0x73, 0x35, 0x8c, 0xf0, 0xf6, 0x88, 0x58, @@ -442,10 +402,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x38, 0x5d, 0xe1, 0xde, 0x16, 0xb2, 0x22, 0x6e, 0x88, 0x3d, 0x9c, 0x34, 0x66, 0x3e, 0x1b, 0x64, 0xe8, 0x5b, 0x98, 0x0e, 0xaf, 0xf0, 0xb9, 0xd3 }, - { 0x1c, 0x74, 0xba, 0x75, 0xe5, 0x1b, 0x48, 0x29, - 0x54, 0xc3, 0x8b, 0xf4, 0xd5, 0x1e, 0xfc, 0x70, - 0xa0, 0xa0, 0x4d, 0x41, 0x3a, 0xc1, 0xff, 0x8e, - 0xb9, 0x90, 0x39, 0x9d, 0x1f, 0x1a, 0xa9, 0xc4 }, { 0x1c, 0x76, 0xbb, 0xca, 0x37, 0x71, 0x77, 0x5b, 0xb9, 0xb0, 0xc3, 0x33, 0x71, 0x70, 0x32, 0x69, 0x06, 0x16, 0x77, 0xca, 0x7b, 0x18, 0x99, 0xef, @@ -474,10 +430,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x85, 0xa7, 0x9b, 0xba, 0x45, 0xce, 0x76, 0x4b, 0x2d, 0xa8, 0x1f, 0x99, 0x1f, 0x5f, 0x01, 0xd9, 0xeb, 0x7e, 0x3c, 0x99, 0x9b, 0x78, 0x75, 0x0e }, - { 0x1f, 0x7d, 0x37, 0x52, 0x93, 0x22, 0x7d, 0x04, - 0x97, 0x5b, 0x78, 0x97, 0xdc, 0x17, 0x25, 0x39, - 0x64, 0xdc, 0xd7, 0xd0, 0x06, 0x7e, 0x84, 0xc6, - 0xd8, 0x47, 0x9d, 0xfa, 0x27, 0x6e, 0xbe, 0xd0 }, { 0x1f, 0xc7, 0xf8, 0x10, 0x4e, 0x27, 0xff, 0x2a, 0x45, 0x56, 0xf9, 0x1e, 0x05, 0x42, 0x17, 0xc5, 0x8f, 0x69, 0x3f, 0x70, 0x36, 0x25, 0x9e, 0x39, @@ -486,10 +438,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xcc, 0xd4, 0xe6, 0xad, 0xe1, 0xcb, 0x75, 0x13, 0x8d, 0xd6, 0xd9, 0x06, 0xfe, 0xf3, 0x49, 0xc0, 0xc9, 0x86, 0xa5, 0x1b, 0x29, 0xb9, 0xe5, 0x2d }, - { 0x20, 0x15, 0x60, 0x8b, 0x8e, 0x86, 0xba, 0x63, - 0x12, 0x01, 0xc2, 0x12, 0x20, 0x99, 0x57, 0xaf, - 0xcb, 0x6e, 0xdf, 0x27, 0x22, 0xc6, 0x1b, 0x00, - 0xe2, 0xfc, 0x92, 0x46, 0xa8, 0xd5, 0x20, 0x4e }, { 0x20, 0xf1, 0x85, 0xbc, 0x7f, 0xa7, 0x61, 0x16, 0x6e, 0xa3, 0xa9, 0x98, 0x8f, 0xb1, 0x0b, 0x24, 0xc7, 0x01, 0xef, 0xdd, 0xab, 0xe4, 0x74, 0x05, @@ -518,10 +466,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xf7, 0x8d, 0xa6, 0xc8, 0xb1, 0xd7, 0x2c, 0x3b, 0xa8, 0x31, 0x9a, 0x46, 0xf8, 0x19, 0x2d, 0x1e, 0x19, 0xb9, 0xe2, 0x9a, 0xba, 0x18, 0xee, 0x87 }, - { 0x22, 0x2e, 0xc2, 0x75, 0xe6, 0x8a, 0x31, 0x7d, - 0x60, 0x80, 0x67, 0x9d, 0xdf, 0x56, 0x78, 0x6a, - 0xbd, 0x2b, 0x11, 0xf2, 0x5a, 0x17, 0x15, 0x33, - 0xcf, 0xbd, 0x59, 0xee, 0x0d, 0xfa, 0x4e, 0xe4 }, { 0x22, 0x7a, 0x2b, 0xff, 0xab, 0xde, 0xe1, 0x8c, 0x2c, 0x54, 0xe6, 0xe9, 0xb5, 0x8a, 0xbd, 0xbf, 0x93, 0x07, 0xa4, 0x06, 0x2e, 0xda, 0x97, 0xd4, @@ -542,10 +486,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x16, 0x2a, 0x9c, 0xa0, 0x6e, 0x88, 0x01, 0xe1, 0x19, 0xbd, 0xff, 0x54, 0x35, 0x4a, 0x3f, 0x68, 0x43, 0xcf, 0x2a, 0x2f, 0xa6, 0x01, 0x75, 0x8e }, - { 0x23, 0xf0, 0xdd, 0xd8, 0x9b, 0x42, 0x82, 0xa6, - 0x7f, 0xd0, 0x57, 0x56, 0xfd, 0xc5, 0xd1, 0x8c, - 0x1e, 0x5d, 0xcc, 0xef, 0xcf, 0x42, 0x65, 0x06, - 0x6d, 0xfb, 0x4a, 0xbd, 0x30, 0xd9, 0xe9, 0x77 }, { 0x23, 0xf7, 0xe4, 0xa3, 0x5b, 0xcc, 0xe7, 0x40, 0x36, 0xd9, 0xc8, 0x6f, 0x7f, 0x61, 0x1d, 0x85, 0xf3, 0x7c, 0xb6, 0x2c, 0x43, 0x24, 0x7d, 0x13, @@ -570,10 +510,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x74, 0xe5, 0xe3, 0xd4, 0x3b, 0x27, 0xad, 0x66, 0x62, 0x0b, 0x90, 0xcb, 0x91, 0x62, 0xc4, 0x68, 0x5f, 0xa2, 0x6d, 0x85, 0xf5, 0xa4, 0x3a, 0xa0 }, - { 0x25, 0x8c, 0x68, 0x91, 0xf0, 0x89, 0xb5, 0x09, - 0x4b, 0xe3, 0x3d, 0x6c, 0x82, 0x21, 0x5e, 0x72, - 0x65, 0xac, 0xa9, 0x3f, 0x7c, 0x9b, 0x41, 0x45, - 0xd0, 0x8a, 0xff, 0x1f, 0x48, 0x30, 0x58, 0xaa }, { 0x26, 0x03, 0xcb, 0xdf, 0x69, 0x75, 0xe3, 0x68, 0x83, 0x7f, 0x95, 0x1a, 0x00, 0x49, 0xfd, 0xc3, 0xc4, 0xb2, 0x39, 0xf0, 0x82, 0xf6, 0xbf, 0x89, @@ -618,10 +554,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xe6, 0xa6, 0xa3, 0x5a, 0x9d, 0x40, 0x00, 0x0a, 0x31, 0x8d, 0x7d, 0xdf, 0x5f, 0x5a, 0x2f, 0x4d, 0x3d, 0x18, 0xbe, 0xba, 0xd3, 0x96, 0x91, 0xec }, - { 0x29, 0x7a, 0xc8, 0x25, 0xc1, 0x98, 0x06, 0xfb, - 0x88, 0x1f, 0xd9, 0x1c, 0x61, 0x2d, 0x6c, 0xc2, - 0x1b, 0x28, 0xe4, 0xa5, 0x72, 0xcf, 0xb7, 0x16, - 0x04, 0xe5, 0x54, 0x41, 0x4d, 0xfd, 0xea, 0xdc }, { 0x29, 0xa8, 0x28, 0x26, 0x64, 0x3d, 0x5a, 0x98, 0xc4, 0x7d, 0xf3, 0xa7, 0x8f, 0xbb, 0x84, 0x49, 0xb3, 0xe6, 0xd3, 0xcc, 0xe6, 0x2c, 0xf4, 0x57, @@ -630,18 +562,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x39, 0xa4, 0x04, 0xde, 0x35, 0xac, 0x84, 0xab, 0x81, 0xaf, 0xec, 0x36, 0x17, 0xe7, 0xe1, 0xbf, 0x34, 0x67, 0xd4, 0x19, 0x25, 0x5d, 0xd8, 0x17 }, - { 0x2a, 0x6b, 0x9f, 0x6f, 0xdc, 0x43, 0xbf, 0x65, - 0xe2, 0xa1, 0x0e, 0xde, 0x36, 0x64, 0xc8, 0x3f, - 0xcb, 0xec, 0x13, 0x9a, 0x6e, 0x6c, 0xc5, 0xc8, - 0x32, 0xd3, 0x27, 0x89, 0x5b, 0x52, 0x0e, 0xa2 }, { 0x2a, 0xa6, 0x47, 0x8c, 0xc7, 0x5d, 0x67, 0xa8, 0xca, 0x55, 0xb2, 0xe1, 0x63, 0xfd, 0xbb, 0xbc, 0x9d, 0x74, 0xb4, 0xe5, 0xf3, 0x7b, 0x7d, 0xbd, 0x13, 0xc9, 0x4e, 0x85, 0x8d, 0x40, 0xda, 0xd0 }, - { 0x2a, 0xc0, 0x65, 0xae, 0x39, 0x6b, 0x87, 0x54, - 0x9c, 0x3f, 0x09, 0xe5, 0x8f, 0x16, 0x4b, 0x24, - 0x2e, 0xc5, 0x9d, 0x13, 0x92, 0xb1, 0xb2, 0x50, - 0x14, 0xbf, 0x47, 0x94, 0xac, 0x13, 0x01, 0xb0 }, { 0x2b, 0xf1, 0xe3, 0xf0, 0x37, 0x5a, 0x9a, 0x21, 0xc0, 0x7a, 0x92, 0x18, 0x04, 0x2f, 0x18, 0x77, 0x3f, 0x43, 0xea, 0xb0, 0xf5, 0xc0, 0x00, 0x26, @@ -662,10 +586,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xc3, 0x73, 0x58, 0xcd, 0x5f, 0x71, 0xd1, 0x23, 0xbb, 0x19, 0x77, 0x28, 0x85, 0x87, 0xc7, 0x3f, 0x84, 0xb0, 0x8f, 0xf8, 0xaa, 0x01, 0x9a, 0x69 }, - { 0x2d, 0xb5, 0x36, 0x48, 0xa6, 0x14, 0x69, 0x57, - 0x01, 0xc7, 0xc5, 0x1e, 0x35, 0xff, 0x38, 0xd6, - 0x4f, 0x27, 0xa2, 0x7d, 0x55, 0xdf, 0xf4, 0xb1, - 0x4a, 0xc4, 0x50, 0xc7, 0x5e, 0xb1, 0x18, 0x6e }, { 0x2d, 0xd5, 0xe6, 0xd3, 0x73, 0x36, 0x34, 0x2f, 0x01, 0x1e, 0xb9, 0x7a, 0x2b, 0x77, 0x38, 0x9d, 0xe6, 0xd2, 0x23, 0x8d, 0x87, 0x69, 0x65, 0x08, @@ -674,10 +594,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xad, 0xe6, 0x7e, 0x9c, 0xa7, 0x05, 0xeb, 0xb4, 0xc2, 0xe9, 0x40, 0xae, 0x1b, 0x9d, 0x62, 0x35, 0x72, 0x18, 0x04, 0x58, 0x31, 0xe9, 0x8f, 0xde }, - { 0x2e, 0x43, 0x2a, 0x54, 0x5d, 0xfe, 0x2d, 0xa3, - 0xad, 0x00, 0xcc, 0x87, 0x89, 0x23, 0xa1, 0x85, - 0xd6, 0xa3, 0xf9, 0x67, 0x5c, 0x36, 0xdc, 0x3c, - 0xd3, 0x70, 0x2a, 0xef, 0xeb, 0x27, 0x0c, 0x85 }, { 0x2e, 0x5d, 0xd2, 0x55, 0x09, 0x6d, 0x64, 0x83, 0x10, 0x5c, 0xb6, 0x03, 0x6c, 0x59, 0x17, 0x57, 0xfd, 0x98, 0x49, 0x70, 0x66, 0x05, 0x3f, 0x83, @@ -690,10 +606,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x01, 0x7c, 0x6c, 0x79, 0x90, 0xe3, 0xf9, 0xa4, 0x0d, 0x46, 0x9f, 0x76, 0x50, 0x59, 0x81, 0xc8, 0x6f, 0x95, 0x55, 0x4f, 0x48, 0x7a, 0x52, 0x76 }, - { 0x2f, 0x79, 0xd6, 0xf6, 0xa3, 0x2f, 0x1b, 0xee, - 0x22, 0x37, 0xa0, 0x18, 0xe6, 0xae, 0xc4, 0xf4, - 0x9e, 0x2c, 0x5c, 0x3c, 0xdb, 0xb6, 0x99, 0xe1, - 0x6f, 0x8e, 0xf4, 0x14, 0xee, 0xff, 0x8d, 0xa3 }, { 0x2f, 0xef, 0xa7, 0xcb, 0x12, 0x6b, 0x81, 0xc9, 0x47, 0x4d, 0x3e, 0x2c, 0x9b, 0x97, 0x3a, 0x83, 0x69, 0xbb, 0x08, 0x43, 0x41, 0xd3, 0x82, 0xd3, @@ -718,10 +630,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x74, 0x2d, 0x6b, 0xe8, 0x40, 0x0a, 0xde, 0x51, 0xb2, 0x09, 0x83, 0xf6, 0x83, 0xa2, 0xaa, 0xee, 0xb2, 0x5f, 0x58, 0xdf, 0x98, 0x1b, 0xde, 0x0d }, - { 0x31, 0xed, 0x8a, 0x8c, 0xc6, 0xee, 0x5e, 0x88, - 0x4f, 0x21, 0x4f, 0x26, 0x7f, 0xe3, 0xa2, 0x27, - 0xd4, 0xe6, 0xed, 0x36, 0xa7, 0x7f, 0xa2, 0x24, - 0x6f, 0x0a, 0xd0, 0x77, 0x8a, 0x6b, 0x3f, 0x97 }, { 0x32, 0x36, 0x98, 0x50, 0x9d, 0x8f, 0x8b, 0xfb, 0xd4, 0xf9, 0x04, 0xbd, 0x1d, 0x84, 0x64, 0x12, 0xc5, 0x27, 0xb7, 0x70, 0x06, 0x2a, 0xad, 0xdf, @@ -742,10 +650,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xb9, 0xe6, 0x63, 0x0d, 0x9f, 0xe7, 0x1f, 0x17, 0xb6, 0xc2, 0x25, 0xa6, 0x5c, 0x76, 0x08, 0x15, 0xe4, 0x08, 0x74, 0x6c, 0x33, 0x1a, 0xb4, 0xf6 }, - { 0x33, 0xc9, 0x15, 0x03, 0xbc, 0x7e, 0xbe, 0x5a, - 0x5d, 0xd0, 0xcf, 0xbb, 0x37, 0x52, 0x64, 0xdd, - 0x5a, 0x31, 0x1e, 0x48, 0xf4, 0x26, 0x6b, 0x32, - 0x50, 0x8a, 0x02, 0x5d, 0x04, 0xfa, 0xdf, 0x38 }, { 0x33, 0xd1, 0x6c, 0xd9, 0xe8, 0x2e, 0xdf, 0xfd, 0x0b, 0x3a, 0xfb, 0x46, 0xa6, 0x84, 0xc5, 0xa0, 0xd1, 0x2f, 0x2b, 0x40, 0x58, 0x6d, 0x53, 0x2f, @@ -798,18 +702,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x44, 0xd6, 0xab, 0x39, 0xb7, 0xa8, 0x18, 0xf8, 0x17, 0x6e, 0x65, 0x20, 0xdc, 0x86, 0x3d, 0xce, 0x43, 0xb3, 0x98, 0xc3, 0x0b, 0x5e, 0xdb, 0x09 }, - { 0x37, 0x07, 0x9d, 0x98, 0x72, 0x7c, 0x42, 0xa4, - 0x1d, 0x66, 0x18, 0xfc, 0xcd, 0xc6, 0xff, 0xa1, - 0x5e, 0xd3, 0xb2, 0xfe, 0xc7, 0xac, 0x0a, 0x09, - 0x7b, 0x74, 0xc5, 0x72, 0xbb, 0xcd, 0xa8, 0xd7 }, { 0x37, 0x87, 0x37, 0xcd, 0x85, 0x19, 0xba, 0xc5, 0x32, 0x2f, 0xdb, 0x28, 0xf4, 0x4a, 0x43, 0xc5, 0x09, 0xa5, 0x44, 0x7a, 0xd2, 0x68, 0x3b, 0xa1, 0x90, 0x05, 0xe3, 0x1b, 0x0d, 0x54, 0x8c, 0x6d }, - { 0x37, 0x99, 0x0f, 0x5b, 0x5c, 0x71, 0x11, 0x89, - 0x98, 0xf9, 0xc8, 0xe1, 0x54, 0x65, 0x69, 0x16, - 0x1a, 0x82, 0xbb, 0xfb, 0x4b, 0x4f, 0xc4, 0xca, - 0xa3, 0xf4, 0xb7, 0xe7, 0x4a, 0xf5, 0x15, 0xfe }, { 0x37, 0xc9, 0x7a, 0x48, 0xf5, 0xee, 0x3e, 0x68, 0xcc, 0x24, 0xb5, 0x4e, 0x7c, 0x4d, 0x9f, 0x91, 0xc7, 0xd1, 0x8b, 0x8d, 0xb6, 0x1e, 0x04, 0xee, @@ -846,10 +742,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x82, 0xd5, 0x85, 0xd5, 0xe0, 0x82, 0xc4, 0xb3, 0xad, 0x03, 0xcd, 0xb6, 0xb5, 0x05, 0xca, 0x80, 0x47, 0x19, 0x88, 0xec, 0x4c, 0x58, 0x99, 0x9e }, - { 0x3a, 0xd4, 0x7c, 0xb3, 0x47, 0x3f, 0x59, 0x51, - 0x5b, 0xac, 0x6a, 0xfa, 0x30, 0x44, 0x8f, 0xb9, - 0x5d, 0x7f, 0x4b, 0xf1, 0x14, 0x48, 0x53, 0x87, - 0xd0, 0x4c, 0x50, 0x15, 0x19, 0xbb, 0x77, 0xc3 }, { 0x3a, 0xea, 0x2c, 0xef, 0xae, 0x63, 0x44, 0xff, 0xae, 0x67, 0x49, 0x4c, 0x68, 0x4e, 0x1e, 0xbf, 0x87, 0x95, 0x40, 0xb5, 0x3d, 0x40, 0xf5, 0x16, @@ -858,10 +750,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xca, 0x6c, 0x31, 0xb3, 0x78, 0x39, 0xc9, 0x50, 0x76, 0x63, 0x70, 0xd7, 0xf4, 0xb6, 0x4a, 0xd0, 0x18, 0x55, 0xca, 0xcf, 0xe3, 0x51, 0x2f, 0xc3 }, - { 0x3b, 0x4a, 0x9f, 0x55, 0x6c, 0xca, 0xc7, 0x0c, - 0xa1, 0xf3, 0x3a, 0xf6, 0xde, 0xcc, 0x66, 0xca, - 0xfd, 0x2d, 0x30, 0x1d, 0x49, 0x7b, 0x49, 0x0b, - 0x30, 0x80, 0x46, 0x35, 0xba, 0xd2, 0x56, 0x94 }, { 0x3b, 0x6e, 0x3b, 0xb7, 0x00, 0x04, 0xbd, 0x78, 0xc9, 0x69, 0xa7, 0xfb, 0xd5, 0x11, 0x33, 0xa2, 0xb3, 0xc4, 0xdf, 0xb6, 0xba, 0x38, 0x5d, 0xce, @@ -890,22 +778,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xf8, 0x91, 0x85, 0x31, 0xa7, 0x7c, 0xf9, 0xbf, 0x5c, 0xa1, 0x85, 0x0c, 0x82, 0x02, 0x69, 0xd7, 0xb2, 0xc8, 0xec, 0xd0, 0x54, 0x3a, 0x61, 0x65 }, - { 0x3e, 0x6f, 0x37, 0x53, 0xf1, 0xab, 0x10, 0x62, - 0x60, 0xdb, 0xef, 0xa6, 0x8e, 0xc5, 0x85, 0x01, - 0x29, 0x1d, 0x1e, 0xb4, 0x00, 0x28, 0x8f, 0x06, - 0xed, 0xf2, 0x9f, 0x8f, 0x8f, 0x66, 0xb0, 0x1a }, { 0x3e, 0x8e, 0x9b, 0xad, 0x8e, 0xd9, 0xb5, 0x72, 0x38, 0x2e, 0x59, 0x8d, 0x2d, 0x73, 0x67, 0xe1, 0xfd, 0x6a, 0xf6, 0x95, 0x25, 0x00, 0x9d, 0x67, 0xb4, 0xe8, 0xaf, 0x80, 0xd9, 0x15, 0x85, 0x49 }, - { 0x3e, 0xc1, 0xc3, 0x43, 0xc6, 0x60, 0x05, 0x10, - 0x57, 0x97, 0x47, 0xa7, 0x1a, 0xea, 0xb3, 0x04, - 0x1a, 0x71, 0x8e, 0x4f, 0xc6, 0xe2, 0x96, 0xfe, - 0xb7, 0x50, 0xa3, 0x12, 0x38, 0x72, 0x6e, 0xa5 }, - { 0x3e, 0xd6, 0x85, 0x47, 0x65, 0x07, 0x91, 0x35, - 0xaa, 0xee, 0xb7, 0xd8, 0xa3, 0x79, 0x17, 0xdc, - 0x71, 0x74, 0x5e, 0xa6, 0x0f, 0xa9, 0x62, 0x1b, - 0xaa, 0x30, 0x7f, 0xbe, 0x71, 0xa7, 0x3c, 0x43 }, { 0x3f, 0x27, 0xbd, 0xca, 0x9b, 0x0e, 0x42, 0xf3, 0xf6, 0xd0, 0x91, 0x2c, 0x92, 0xe2, 0xda, 0x65, 0xcb, 0x35, 0x8f, 0x0b, 0x8f, 0x80, 0x5b, 0xec, @@ -938,10 +814,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x65, 0xa7, 0x39, 0xa0, 0x0c, 0x85, 0xf3, 0x44, 0x58, 0x79, 0xd6, 0x5e, 0x1d, 0x42, 0x2e, 0xed, 0x07, 0x65, 0x5a, 0x8e, 0x3e, 0xc3, 0x18, 0xcf }, - { 0x41, 0x1e, 0x5a, 0x18, 0x2a, 0x48, 0x3c, 0x67, - 0x0f, 0x89, 0xac, 0xee, 0xa6, 0xda, 0xa1, 0xf9, - 0xa6, 0x22, 0x7e, 0xdf, 0x04, 0x9c, 0x05, 0xe3, - 0xc4, 0xcf, 0xf7, 0x28, 0x42, 0x45, 0x9a, 0xa2 }, { 0x41, 0x29, 0x6b, 0x9f, 0xaa, 0xd6, 0x41, 0x33, 0xfc, 0xcb, 0xa6, 0xba, 0x74, 0x54, 0x11, 0xec, 0xc9, 0x11, 0xfd, 0x8e, 0xd5, 0x41, 0x90, 0x0f, @@ -990,14 +862,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x4a, 0x58, 0x1f, 0x4f, 0x10, 0x91, 0xab, 0xef, 0x33, 0x2d, 0x8a, 0x7c, 0xef, 0x60, 0xe6, 0x8d, 0xaf, 0x84, 0x13, 0x23, 0x26, 0x12, 0x90, 0xf0 }, - { 0x44, 0xc2, 0x00, 0x2e, 0xea, 0xbe, 0x55, 0xaa, - 0x9b, 0xf9, 0x7c, 0xf3, 0xef, 0xd4, 0xfb, 0x06, - 0xec, 0xe5, 0x10, 0xb4, 0xab, 0xe9, 0xac, 0xb8, - 0x2c, 0x36, 0xef, 0x23, 0x5b, 0x9d, 0xc8, 0xa1 }, - { 0x45, 0x60, 0xdb, 0xdb, 0x1c, 0x43, 0x68, 0x50, - 0xef, 0xb0, 0x03, 0x1e, 0xf8, 0x2b, 0x9f, 0x70, - 0x88, 0x21, 0x9e, 0xce, 0xd2, 0x69, 0x56, 0x1f, - 0xb4, 0xd1, 0xb0, 0x18, 0x3c, 0x44, 0xc2, 0xb5 }, { 0x45, 0x63, 0xcf, 0x13, 0xc2, 0x49, 0x2c, 0xaa, 0x92, 0xf5, 0x5b, 0x17, 0x26, 0x3a, 0xdd, 0x72, 0x04, 0xa8, 0x0f, 0xe6, 0x24, 0x0c, 0x4d, 0x63, @@ -1010,10 +874,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xd5, 0xda, 0xfc, 0x05, 0xeb, 0x0c, 0x53, 0x65, 0x82, 0x3a, 0x91, 0xa9, 0x8b, 0x7d, 0xbe, 0x81, 0xab, 0x5f, 0x17, 0x8b, 0x2d, 0xa4, 0xad, 0x9e }, - { 0x45, 0xcc, 0x74, 0xa3, 0xdb, 0xcb, 0x59, 0xa1, - 0x35, 0x35, 0x39, 0xfa, 0x5b, 0x1a, 0xf9, 0x74, - 0x6b, 0xa5, 0xc7, 0xf0, 0xf1, 0x6f, 0x7c, 0xc1, - 0xf7, 0x0c, 0x71, 0x32, 0x38, 0x82, 0x7e, 0x37 }, { 0x46, 0x9b, 0xd8, 0x04, 0xe9, 0x98, 0xae, 0x27, 0x9a, 0xc3, 0xfe, 0x1b, 0x52, 0x88, 0x46, 0xe7, 0xae, 0xc7, 0x6c, 0x56, 0xb8, 0x0b, 0x40, 0xf3, @@ -1034,18 +894,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x8b, 0xf5, 0xdd, 0xa4, 0xc3, 0xe9, 0x9e, 0x7f, 0xa3, 0x10, 0x9b, 0x67, 0xbd, 0x0c, 0x9b, 0x1f, 0x40, 0x75, 0x96, 0x65, 0xb9, 0xec, 0x3f, 0xf2 }, - { 0x48, 0x09, 0x80, 0xfc, 0xeb, 0x50, 0xeb, 0x37, - 0x4c, 0x91, 0x6c, 0xb2, 0xa4, 0x3a, 0xfb, 0xd5, - 0x35, 0x21, 0x1a, 0xea, 0x9b, 0x12, 0xb7, 0xa4, - 0x5a, 0xaf, 0x90, 0xba, 0x9c, 0xa4, 0x70, 0x0f }, - { 0x48, 0x4b, 0x8b, 0xc1, 0xe6, 0xcb, 0xba, 0x3f, - 0x01, 0xf7, 0xa9, 0x34, 0x5a, 0x88, 0x4c, 0xf5, - 0xf1, 0x5d, 0x82, 0xda, 0x56, 0x98, 0xb6, 0xb3, - 0x71, 0xe4, 0xdc, 0x6b, 0xbd, 0x6c, 0x8a, 0xe8 }, - { 0x48, 0x5c, 0xf2, 0xb0, 0xa5, 0xe6, 0x9a, 0x0a, - 0x9a, 0xab, 0x03, 0xff, 0x82, 0xbd, 0x6b, 0x7b, - 0x2e, 0xdf, 0x8e, 0x1b, 0x54, 0x45, 0x8e, 0x14, - 0x2a, 0xeb, 0x88, 0xba, 0xa8, 0x84, 0x0e, 0x5b }, { 0x48, 0xc5, 0xd4, 0xff, 0x5d, 0x08, 0x4a, 0xc1, 0x95, 0xb1, 0xa6, 0xa2, 0x19, 0xf8, 0x1b, 0xbd, 0xf9, 0xd2, 0xe5, 0xc0, 0x70, 0xec, 0x97, 0xdf, @@ -1126,10 +974,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xa9, 0xaa, 0x3b, 0x7b, 0x02, 0x7d, 0x71, 0x4c, 0x0f, 0x76, 0x07, 0xc3, 0x56, 0x73, 0x3b, 0xa2, 0x21, 0xaa, 0xe4, 0x09, 0x47, 0xf7, 0xfa, 0xcb }, - { 0x4d, 0x25, 0x2e, 0x6e, 0x1a, 0x15, 0x9a, 0xc2, - 0x22, 0xb3, 0x2e, 0x9d, 0xd0, 0x31, 0x56, 0x7b, - 0x69, 0x31, 0x4b, 0xe8, 0xe8, 0x21, 0x1c, 0x1f, - 0xb3, 0xc8, 0xb5, 0x3c, 0x26, 0x0a, 0x74, 0xe5 }, { 0x4d, 0x54, 0x4d, 0x4e, 0x41, 0xc0, 0xfb, 0x15, 0x5f, 0x04, 0x7d, 0x7f, 0xb1, 0xef, 0x29, 0xd1, 0x1b, 0xdf, 0xec, 0xa9, 0xd4, 0x11, 0xaf, 0x8b, @@ -1142,18 +986,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x81, 0x79, 0x67, 0x53, 0xdd, 0x20, 0x20, 0xb1, 0x10, 0x54, 0x09, 0x32, 0xf7, 0x4f, 0x97, 0x41, 0xd9, 0x6c, 0x1d, 0xb9, 0x50, 0x5d, 0x5f, 0xf1 }, - { 0x4e, 0x33, 0x78, 0xec, 0x23, 0x7c, 0x01, 0xa3, - 0xcd, 0x85, 0x9e, 0x1d, 0xc9, 0x29, 0xd6, 0xa6, - 0xef, 0xb6, 0x36, 0x7a, 0x72, 0x58, 0x41, 0xcf, - 0x54, 0x13, 0x25, 0xc0, 0x61, 0xf8, 0xbf, 0xd4 }, { 0x4e, 0x48, 0xc1, 0x6c, 0x9d, 0x0d, 0xe5, 0xdd, 0x8c, 0x9c, 0x36, 0x37, 0x35, 0xdd, 0xfb, 0xc3, 0xdb, 0xd2, 0x6e, 0xa0, 0xae, 0xcd, 0xe1, 0xc7, 0x62, 0xbb, 0x56, 0xbb, 0x3f, 0xe4, 0xfa, 0x74 }, - { 0x4e, 0x6e, 0x0a, 0x27, 0x52, 0x69, 0x22, 0x88, - 0x98, 0x02, 0xb5, 0x98, 0x9e, 0xf0, 0x8a, 0xe1, - 0x67, 0x02, 0x62, 0x0e, 0x8d, 0x12, 0x90, 0xb9, - 0x36, 0x9e, 0xf0, 0x32, 0x9a, 0xdb, 0xa6, 0x8c }, { 0x4f, 0x19, 0xdd, 0x12, 0x92, 0x4c, 0xe0, 0xc1, 0x4f, 0x82, 0xc0, 0x56, 0xc7, 0xd4, 0x2b, 0xac, 0x43, 0xd0, 0x13, 0x3a, 0xaf, 0x89, 0xc1, 0xef, @@ -1234,10 +1070,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x08, 0x60, 0x96, 0x78, 0xc4, 0x3b, 0xdd, 0xab, 0x90, 0x28, 0xba, 0x6c, 0x17, 0x68, 0x4c, 0x51, 0x22, 0x42, 0x62, 0x43, 0xcb, 0x61, 0x2a, 0x29 }, - { 0x53, 0xed, 0x84, 0xe5, 0xc9, 0xad, 0x2b, 0xd1, - 0xcb, 0x2c, 0xc8, 0x36, 0x52, 0xea, 0x0c, 0xc3, - 0x71, 0xcd, 0x53, 0x4b, 0xd5, 0x97, 0xce, 0x7e, - 0x07, 0x37, 0xa0, 0xab, 0x10, 0x65, 0x73, 0xaa }, { 0x54, 0x41, 0xfb, 0xb0, 0x5d, 0x6d, 0x4a, 0xed, 0xe0, 0x3b, 0x48, 0x2f, 0x51, 0x95, 0x1c, 0x7e, 0xf0, 0x73, 0x45, 0x53, 0xce, 0xc7, 0x80, 0xfb, @@ -1262,10 +1094,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x58, 0x4d, 0x9e, 0x7b, 0x57, 0x92, 0xa4, 0x03, 0xc2, 0x1d, 0x39, 0xd6, 0xe1, 0xf5, 0xe8, 0xed, 0x37, 0xb9, 0x3f, 0xa6, 0x1d, 0x88, 0x35, 0x16 }, - { 0x56, 0x65, 0xc2, 0xe5, 0x64, 0x33, 0x29, 0x85, - 0xb8, 0xd2, 0xc4, 0xfb, 0x61, 0x14, 0x57, 0xd8, - 0xd5, 0x65, 0x9a, 0xe0, 0x05, 0x87, 0x4c, 0x6f, - 0x30, 0x34, 0xd2, 0x9f, 0x2a, 0x9a, 0x78, 0x32 }, { 0x56, 0x96, 0x18, 0xd5, 0x4e, 0x3c, 0x61, 0x1b, 0x79, 0x7e, 0xeb, 0x01, 0xdf, 0x9c, 0x1c, 0x5c, 0x14, 0x6d, 0x87, 0xb3, 0xb1, 0x29, 0xba, 0x42, @@ -1282,10 +1110,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x62, 0x9c, 0x3c, 0x7c, 0x78, 0xef, 0xbe, 0xf2, 0x75, 0x06, 0x56, 0x65, 0xb2, 0x41, 0x1c, 0x0e, 0x5f, 0xcf, 0xbc, 0x7e, 0xb4, 0xbe, 0x34, 0x0b }, - { 0x58, 0x36, 0x98, 0x46, 0xc0, 0x25, 0x15, 0x0e, - 0xcf, 0xb2, 0x2c, 0xce, 0xb8, 0xe4, 0xde, 0x9a, - 0xc3, 0xd0, 0x2d, 0x9e, 0x23, 0x6c, 0x02, 0xef, - 0xb5, 0x5f, 0x63, 0xeb, 0xaf, 0xea, 0xf7, 0x5b }, { 0x59, 0x43, 0x09, 0x51, 0x02, 0x8b, 0x87, 0x78, 0x01, 0x67, 0xc9, 0x56, 0x47, 0x9a, 0x81, 0x5f, 0x91, 0xbc, 0x6c, 0x00, 0xc2, 0xe5, 0x0c, 0x35, @@ -1378,10 +1202,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x79, 0x92, 0xc5, 0x8f, 0xac, 0x32, 0xe3, 0x0c, 0x01, 0x9e, 0xaf, 0x41, 0xe0, 0xb3, 0x85, 0x7e, 0xa9, 0x00, 0xa1, 0x61, 0x08, 0xeb, 0x34, 0xde }, - { 0x60, 0x28, 0x6b, 0x5f, 0xb1, 0xa4, 0x7f, 0x8c, - 0x79, 0x3e, 0xbe, 0x0a, 0x4f, 0x9e, 0xa0, 0xef, - 0xb6, 0xff, 0xf7, 0xd0, 0x1c, 0x79, 0x10, 0xef, - 0xf7, 0x4e, 0xd3, 0xb2, 0x88, 0xf4, 0xe6, 0x27 }, { 0x60, 0xca, 0x81, 0xe3, 0x5b, 0x9a, 0x6f, 0x07, 0xe1, 0x3c, 0x02, 0xae, 0x41, 0x15, 0xb0, 0x00, 0x54, 0x30, 0xcf, 0x46, 0x0e, 0xfc, 0x7d, 0xba, @@ -1406,18 +1226,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x4d, 0xf9, 0x1e, 0x31, 0x32, 0x2e, 0x57, 0x74, 0x69, 0x1e, 0x0c, 0x41, 0xfa, 0x0d, 0x2f, 0x25, 0x7a, 0xd7, 0xf9, 0xf0, 0x25, 0x98, 0x14, 0x45 }, - { 0x63, 0x65, 0xeb, 0x4e, 0x37, 0xea, 0x23, 0x8b, - 0xbc, 0x40, 0xa7, 0x65, 0x1e, 0xdd, 0x9a, 0x1c, - 0x65, 0xfc, 0x54, 0xe3, 0xb8, 0x8f, 0xa7, 0xa0, - 0x6d, 0x92, 0xc6, 0x13, 0xae, 0xde, 0xd6, 0x5d }, { 0x63, 0x6a, 0x25, 0xbd, 0xdb, 0xb6, 0x5e, 0x7c, 0xc0, 0xe6, 0x1f, 0x91, 0xca, 0xfe, 0xb1, 0xfe, 0x5d, 0xd2, 0x67, 0xac, 0x67, 0x32, 0x25, 0xcc, 0x81, 0x8e, 0xa0, 0x2b, 0x9c, 0xc9, 0x4b, 0xe2 }, - { 0x64, 0x87, 0xc9, 0x20, 0xb1, 0x30, 0x16, 0xf4, - 0xa0, 0xaa, 0xd3, 0x9f, 0xe1, 0x97, 0x8b, 0xec, - 0xe9, 0xf4, 0xfa, 0x13, 0xed, 0x0c, 0x42, 0x4d, - 0xaa, 0x41, 0x6b, 0xaa, 0x75, 0x89, 0x62, 0x01 }, { 0x64, 0xd4, 0x92, 0x41, 0x6e, 0xe0, 0x55, 0x57, 0x9c, 0x46, 0x3b, 0x21, 0x1a, 0xfe, 0xf7, 0x46, 0xc3, 0x30, 0xca, 0x05, 0xf4, 0x4d, 0x85, 0x90, @@ -1434,10 +1246,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x38, 0x07, 0x1a, 0xee, 0xde, 0xf8, 0xe1, 0x83, 0xe2, 0x37, 0x38, 0x46, 0x97, 0x26, 0xeb, 0x99, 0x68, 0x0c, 0xd2, 0x44, 0x72, 0x73, 0x6b, 0xec }, - { 0x66, 0x49, 0xe0, 0x34, 0xc6, 0x9d, 0x14, 0x24, - 0xd2, 0x8c, 0x42, 0x68, 0xba, 0x95, 0x1e, 0xe1, - 0xb4, 0x8a, 0xe1, 0x5f, 0xeb, 0xe7, 0xd6, 0xbe, - 0x9d, 0x75, 0xf6, 0xa4, 0xac, 0x7a, 0xc2, 0x53 }, { 0x66, 0x50, 0xb2, 0xea, 0x64, 0x4c, 0x3f, 0x4e, 0x8c, 0x9e, 0x3c, 0x46, 0xac, 0xea, 0xc4, 0x52, 0x33, 0xd8, 0x66, 0xe3, 0x98, 0xff, 0x90, 0xeb, @@ -1566,14 +1374,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x8c, 0xc5, 0x2a, 0x48, 0x0a, 0xc0, 0x6d, 0x69, 0x71, 0xc5, 0xa3, 0xda, 0x97, 0xcf, 0x3e, 0xf0, 0x1a, 0xf2, 0x9d, 0x74, 0x72, 0x62, 0x31, 0xe2 }, - { 0x6e, 0xb8, 0xa7, 0xba, 0x7f, 0xc2, 0x1c, 0x62, - 0x40, 0x3f, 0x63, 0x76, 0xbb, 0x10, 0x44, 0x82, - 0x48, 0x8d, 0xa9, 0xc1, 0x41, 0x4a, 0xe3, 0xab, - 0x06, 0xe0, 0x1e, 0xd7, 0x32, 0x42, 0xab, 0xd7 }, - { 0x6e, 0xeb, 0x39, 0xda, 0xd7, 0x3f, 0xc5, 0x99, - 0x72, 0x42, 0x17, 0xcf, 0xf0, 0x21, 0xd5, 0xac, - 0x4e, 0x7e, 0x2b, 0xf4, 0x76, 0xea, 0xf4, 0xfd, - 0x4d, 0x7b, 0xfb, 0x6e, 0x4f, 0x18, 0xc1, 0x73 }, { 0x6f, 0x3b, 0xb3, 0x4b, 0x5d, 0x32, 0x91, 0xdf, 0xb3, 0xe4, 0x12, 0x71, 0xa1, 0xd7, 0x30, 0xcd, 0xbc, 0xff, 0xc1, 0x0b, 0x68, 0x05, 0x9d, 0xcc, @@ -1622,10 +1422,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x0e, 0xdf, 0xa3, 0x41, 0x1f, 0xbc, 0x9b, 0xad, 0x31, 0x65, 0xbe, 0x66, 0x0f, 0x34, 0x0a, 0xa2, 0x30, 0x8a, 0x5a, 0x33, 0x23, 0xfa, 0xbf, 0xa7 }, - { 0x73, 0x46, 0x99, 0x89, 0x4a, 0xd4, 0xb5, 0xa8, - 0xa2, 0xdd, 0x9a, 0xb4, 0xfd, 0x5f, 0x63, 0x25, - 0x30, 0x3b, 0x49, 0x16, 0x4c, 0xa8, 0xd8, 0xe7, - 0xba, 0x99, 0x77, 0x81, 0x7e, 0x4a, 0xe2, 0x4f }, { 0x73, 0x9d, 0x17, 0x23, 0x23, 0xf2, 0xb2, 0x84, 0x07, 0x0a, 0xce, 0x43, 0x09, 0x8c, 0x8b, 0x21, 0xc4, 0x7a, 0x53, 0xf9, 0x98, 0x5f, 0x2f, 0xad, @@ -1646,10 +1442,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x00, 0xb4, 0x14, 0x73, 0xca, 0x44, 0xe6, 0x87, 0x96, 0x38, 0x74, 0x3d, 0x8f, 0xee, 0x66, 0xee, 0x71, 0x8c, 0x18, 0xd8, 0xf1, 0x12, 0x15, 0xd1 }, - { 0x75, 0xbb, 0x15, 0x25, 0x09, 0xb7, 0x19, 0x04, - 0xe4, 0x40, 0x0f, 0xb4, 0x23, 0xa5, 0x80, 0xaa, - 0xe1, 0xdd, 0xb7, 0x68, 0xf6, 0xfd, 0x36, 0xe6, - 0x30, 0x94, 0xeb, 0xe3, 0x92, 0x15, 0xf3, 0x90 }, { 0x75, 0xe9, 0xa1, 0x5d, 0x94, 0x88, 0x0c, 0x66, 0x14, 0x82, 0xcf, 0xc1, 0x96, 0x4c, 0xbc, 0xe2, 0xb1, 0xca, 0x7a, 0x9f, 0x81, 0xd4, 0x07, 0x30, @@ -1666,10 +1458,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x83, 0x98, 0x71, 0x0f, 0x02, 0x20, 0xfa, 0xf3, 0x30, 0x1d, 0x54, 0x49, 0x38, 0xfb, 0x24, 0x19, 0x2d, 0xec, 0x32, 0xf7, 0x44, 0xe4, 0x22, 0x10 }, - { 0x76, 0xcd, 0xf0, 0x78, 0xa8, 0x89, 0x1f, 0x1b, - 0x3d, 0x0a, 0xa7, 0x1d, 0x6e, 0x18, 0xd7, 0x6a, - 0x4d, 0x20, 0x7a, 0xaf, 0x84, 0xc6, 0x12, 0x95, - 0x0e, 0xdf, 0xcd, 0x92, 0x82, 0xa1, 0x11, 0x44 }, { 0x77, 0x95, 0x6b, 0x48, 0xcd, 0xd9, 0x15, 0x0b, 0xd8, 0x7d, 0x8d, 0x81, 0x50, 0x60, 0xac, 0x8c, 0x84, 0x81, 0x3a, 0x53, 0x87, 0x1a, 0x58, 0x6a, @@ -1682,10 +1470,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x7e, 0xd5, 0x33, 0xc9, 0x9c, 0xc8, 0x25, 0x08, 0xeb, 0xa6, 0xac, 0x3a, 0x0b, 0xe5, 0xbc, 0xbf, 0x7a, 0xc9, 0x94, 0x95, 0x2b, 0x6d, 0x35, 0x07 }, - { 0x77, 0xb9, 0x6a, 0x00, 0x77, 0x15, 0xa0, 0x8c, - 0x6a, 0x22, 0xdb, 0x14, 0xc7, 0xf4, 0xf1, 0xd7, - 0xf4, 0xa7, 0x41, 0xce, 0x47, 0x32, 0xec, 0xf8, - 0x3e, 0x74, 0xc1, 0xc9, 0x63, 0x22, 0x83, 0xcd }, { 0x77, 0xdd, 0xc8, 0x1b, 0xd2, 0x8b, 0x9d, 0x46, 0x1e, 0x7d, 0x3c, 0xd4, 0xa8, 0x12, 0x2a, 0xa9, 0x8a, 0x24, 0x60, 0xfb, 0xa0, 0x8f, 0x1b, 0x7b, @@ -1746,14 +1530,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xf8, 0xa9, 0xb4, 0xd9, 0x8e, 0xa2, 0x9a, 0xe4, 0xa5, 0xa4, 0x24, 0x72, 0xf5, 0x91, 0xca, 0x11, 0xfb, 0x5e, 0x11, 0x21, 0x06, 0x28, 0x63, 0x96 }, - { 0x7c, 0x63, 0xb8, 0x8e, 0x58, 0x19, 0x07, 0x0f, - 0xc1, 0x4a, 0xdb, 0x67, 0xd6, 0xda, 0xa1, 0x29, - 0x83, 0x14, 0x30, 0x4a, 0x9c, 0x05, 0x30, 0x18, - 0x02, 0x7d, 0xf8, 0x36, 0x91, 0x4d, 0x73, 0xd4 }, - { 0x7c, 0xa0, 0x86, 0x8b, 0xeb, 0xae, 0x8a, 0xca, - 0x9d, 0x0f, 0x75, 0x38, 0x65, 0xc3, 0x2a, 0x0d, - 0x2d, 0xd4, 0xf1, 0x48, 0x6e, 0x37, 0x34, 0xa6, - 0xa3, 0x71, 0x0e, 0xcc, 0x3e, 0x57, 0xf9, 0xed }, { 0x7c, 0xf9, 0x2f, 0x75, 0xbb, 0xe7, 0xa1, 0x4d, 0x86, 0x93, 0xf9, 0x93, 0xc3, 0xd1, 0xa6, 0x08, 0xdb, 0xe0, 0xd1, 0x8f, 0x80, 0x8e, 0x21, 0x2d, @@ -1766,10 +1542,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xdd, 0xd6, 0x03, 0xb1, 0x75, 0xc9, 0xb2, 0x05, 0xac, 0x0b, 0x55, 0x3a, 0x4b, 0xf5, 0xfb, 0x08, 0xc2, 0x46, 0xec, 0xf9, 0xc8, 0x49, 0xdb, 0x28 }, - { 0x7f, 0x86, 0xd3, 0xaa, 0x7e, 0xa7, 0x5c, 0x18, - 0x03, 0x9d, 0x6a, 0xf9, 0x9c, 0xef, 0x75, 0x04, - 0xce, 0x7b, 0x05, 0x05, 0x9b, 0xbf, 0xe7, 0x3f, - 0xcd, 0xec, 0xfc, 0x71, 0xb2, 0x53, 0x8d, 0x72 }, { 0x7f, 0x95, 0x9b, 0x06, 0x34, 0xda, 0x94, 0xfa, 0xca, 0xda, 0xb0, 0x21, 0xcf, 0x94, 0x20, 0x78, 0x16, 0x00, 0x36, 0x13, 0xef, 0x09, 0xeb, 0x54, @@ -1834,10 +1606,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x95, 0xe2, 0x5f, 0x91, 0xa5, 0xfb, 0x0f, 0x2a, 0xfc, 0xba, 0x7e, 0x09, 0xb2, 0x17, 0x27, 0xee, 0xd8, 0x13, 0x0c, 0xde, 0x8f, 0x08, 0x0f, 0xca }, - { 0x82, 0xd1, 0x9b, 0xd8, 0x0a, 0x88, 0x6b, 0x28, - 0x61, 0xc3, 0x09, 0x97, 0x4c, 0x1c, 0x99, 0x3d, - 0xbe, 0xc3, 0x7e, 0x30, 0x85, 0xc1, 0x47, 0xc4, - 0x1f, 0x23, 0xd9, 0xf1, 0x20, 0xd8, 0x9b, 0x68 }, { 0x82, 0xe1, 0xbd, 0xb3, 0xdc, 0x4f, 0x02, 0x36, 0x3a, 0x79, 0x6b, 0x60, 0xa8, 0x8e, 0x4e, 0x71, 0xbd, 0x33, 0xb0, 0xbe, 0x4c, 0xc5, 0xb8, 0x33, @@ -1866,10 +1634,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xcf, 0x81, 0xb7, 0xd5, 0xff, 0x51, 0xa7, 0xa5, 0x6a, 0x84, 0x78, 0x3a, 0x2d, 0xf7, 0x43, 0x61, 0xff, 0x2e, 0xee, 0x0f, 0x92, 0x12, 0xc1, 0x59 }, - { 0x84, 0x26, 0xbc, 0x06, 0xdb, 0xb5, 0x18, 0x71, - 0x34, 0x66, 0xc7, 0x6a, 0xea, 0x52, 0x1b, 0xce, - 0x39, 0xd3, 0x91, 0xa8, 0x89, 0xcb, 0xba, 0x9b, - 0x7b, 0x72, 0xdc, 0xda, 0x89, 0xf3, 0x46, 0x55 }, { 0x84, 0x7b, 0x5f, 0x1e, 0xeb, 0x2a, 0x44, 0x13, 0xc8, 0xfa, 0x37, 0x98, 0x21, 0x97, 0x37, 0xe1, 0x92, 0xba, 0x72, 0x72, 0xa1, 0x08, 0xb7, 0x17, @@ -1914,14 +1678,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xe8, 0x1c, 0x27, 0xd1, 0xca, 0xf2, 0x74, 0xb1, 0x7d, 0x72, 0x0d, 0xf8, 0x07, 0x8b, 0x6f, 0x2a, 0x5c, 0x3b, 0xb8, 0xd8, 0xdf, 0xf0, 0x55, 0x00 }, - { 0x87, 0xeb, 0xcb, 0xb0, 0x73, 0x7a, 0xe3, 0x27, - 0xc6, 0xbe, 0x9d, 0x3f, 0xa2, 0xc7, 0x5d, 0x1e, - 0xea, 0x0a, 0xe6, 0x6d, 0x20, 0xd3, 0x8a, 0xf6, - 0xed, 0x76, 0xe6, 0xb1, 0x49, 0x9c, 0x83, 0x1f }, - { 0x88, 0x51, 0x76, 0x78, 0x61, 0xc9, 0x72, 0x7d, - 0x92, 0x77, 0x63, 0x62, 0x78, 0xfb, 0x94, 0x1b, - 0x88, 0x85, 0xd9, 0x99, 0x02, 0x48, 0xbf, 0x91, - 0x45, 0x9e, 0x52, 0x7c, 0xe7, 0xf0, 0x6c, 0xf6 }, { 0x88, 0x76, 0x88, 0xdc, 0x6e, 0x9f, 0xe3, 0xdb, 0x05, 0x05, 0x7f, 0xc6, 0x38, 0xeb, 0x8b, 0x29, 0x4c, 0x3d, 0x8e, 0x0a, 0xae, 0x17, 0x51, 0xf7, @@ -2002,10 +1758,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x81, 0x0d, 0x6e, 0x19, 0xf5, 0xf8, 0x8e, 0xa2, 0xc6, 0x5d, 0xb7, 0xa2, 0xe8, 0xa5, 0x06, 0xf7, 0xdf, 0x99, 0x55, 0x81, 0x7d, 0xdd, 0xeb, 0xc8 }, - { 0x8d, 0x74, 0xc0, 0xd6, 0x6b, 0xb2, 0xee, 0xb2, - 0x6b, 0x9a, 0x55, 0x74, 0x38, 0x5d, 0xa7, 0xb4, - 0x14, 0x0a, 0xf0, 0x70, 0x47, 0xd2, 0xfe, 0x64, - 0x3d, 0x1d, 0x1a, 0xe5, 0xb1, 0x96, 0x90, 0x43 }, { 0x8d, 0x85, 0xda, 0x44, 0x6f, 0x5c, 0x79, 0x54, 0xbd, 0xf7, 0x6c, 0x09, 0x0c, 0xd2, 0x46, 0x68, 0xff, 0x23, 0x3c, 0xcd, 0xf6, 0x6b, 0x94, 0xda, @@ -2182,10 +1934,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x60, 0x71, 0xd3, 0x82, 0x18, 0x1a, 0xf6, 0xcb, 0x25, 0xbd, 0xc5, 0x87, 0x5e, 0x29, 0xf0, 0xf4, 0xd7, 0x19, 0xa9, 0xd3, 0x5b, 0x5b, 0xd6, 0xbf }, - { 0x99, 0xb1, 0x38, 0xbb, 0x53, 0xc5, 0x4d, 0x1c, - 0x7a, 0xc2, 0x9a, 0x57, 0x85, 0xc8, 0xb1, 0x9f, - 0xdd, 0xc3, 0x7d, 0x99, 0x4a, 0x3e, 0x6c, 0x31, - 0xf7, 0x50, 0xa1, 0xbf, 0xeb, 0xe9, 0xfe, 0xf9 }, { 0x99, 0xb4, 0x6c, 0x68, 0x90, 0x62, 0x37, 0x40, 0x23, 0xdb, 0x68, 0x19, 0xf8, 0x89, 0xd3, 0xc1, 0xbb, 0x8a, 0x83, 0x8c, 0x6b, 0x51, 0x7e, 0x32, @@ -2258,18 +2006,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xfe, 0x1f, 0xd8, 0xdf, 0x2d, 0x36, 0xdd, 0xef, 0x00, 0xc8, 0xfc, 0x7b, 0xf7, 0xb7, 0xfd, 0x7e, 0x8d, 0x45, 0x92, 0xab, 0xf3, 0xc4, 0x21, 0xde }, - { 0x9e, 0x85, 0xd4, 0xac, 0x8b, 0x36, 0x0e, 0x4d, - 0xb2, 0xed, 0x37, 0x34, 0x10, 0x16, 0xe3, 0x7b, - 0xd5, 0x5c, 0x2d, 0x59, 0x79, 0x5d, 0x0a, 0x7c, - 0x26, 0xa4, 0x4e, 0x7e, 0x80, 0x98, 0x3e, 0x75 }, { 0x9e, 0x98, 0xf7, 0xda, 0x04, 0x74, 0xd4, 0x86, 0x5a, 0xc7, 0x05, 0xd4, 0xd7, 0xab, 0xbe, 0xb7, 0x1a, 0xef, 0xba, 0x2c, 0xf2, 0xe0, 0x82, 0xf0, 0x5f, 0xed, 0x53, 0x62, 0x41, 0x4b, 0xd3, 0x93 }, - { 0x9e, 0xea, 0x28, 0xdf, 0x01, 0x4d, 0x91, 0x24, - 0x4f, 0xf9, 0x31, 0x4f, 0x43, 0x4a, 0x84, 0x7b, - 0x65, 0x89, 0xc1, 0xf2, 0x03, 0x58, 0x33, 0x9d, - 0x79, 0xfc, 0xa6, 0x76, 0x63, 0x2d, 0xff, 0xfe }, { 0x9f, 0x24, 0x5c, 0x0a, 0x0e, 0xc6, 0x3a, 0xaa, 0xcb, 0xf9, 0x69, 0xc6, 0xfc, 0x24, 0xa1, 0x07, 0x15, 0x83, 0xb7, 0x79, 0xa5, 0x8a, 0xb6, 0x23, @@ -2282,18 +2022,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xb6, 0x2f, 0xa6, 0xe3, 0x23, 0x95, 0xeb, 0xe8, 0x33, 0x34, 0x46, 0x00, 0x43, 0x6d, 0xac, 0xc9, 0xb5, 0x69, 0x21, 0x4e, 0xeb, 0x8c, 0x0a, 0xf0 }, - { 0x9f, 0xf9, 0x38, 0x40, 0xb0, 0x1f, 0x96, 0xb6, - 0xf3, 0xc3, 0x10, 0xa0, 0x21, 0x90, 0xad, 0xc3, - 0x3a, 0x15, 0x69, 0x39, 0x5b, 0xbc, 0xee, 0x11, - 0x6a, 0x15, 0xe1, 0x58, 0xa6, 0x2b, 0xa5, 0x0b }, { 0xa0, 0x05, 0x20, 0xb9, 0x68, 0xbf, 0xcb, 0x63, 0x40, 0x87, 0x9f, 0xa8, 0x43, 0x82, 0x0c, 0xec, 0x95, 0x45, 0x86, 0x0f, 0xe2, 0x9e, 0x2f, 0x8f, 0xee, 0x00, 0xb0, 0x0f, 0xf8, 0x43, 0x42, 0x74 }, - { 0xa0, 0x44, 0xf2, 0xc0, 0x41, 0xf4, 0x18, 0x5b, - 0xc0, 0xfe, 0x1a, 0xd3, 0xe0, 0xa3, 0xe0, 0xc2, - 0x7e, 0x24, 0xf4, 0x58, 0xdc, 0xb7, 0xd9, 0x07, - 0x39, 0xb6, 0x4a, 0x68, 0x94, 0x45, 0xd4, 0xb6 }, { 0xa0, 0x77, 0x42, 0xd5, 0xb2, 0x99, 0x96, 0x65, 0x06, 0x76, 0x2e, 0x02, 0xe4, 0x20, 0xf1, 0xa9, 0xc4, 0xab, 0x73, 0x29, 0xae, 0x29, 0x5f, 0x01, @@ -2306,10 +2038,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x37, 0x14, 0xd5, 0xb3, 0x44, 0x5d, 0x88, 0xbe, 0x81, 0xff, 0x5e, 0x1d, 0x16, 0x07, 0x3d, 0xc1, 0x16, 0x6b, 0xb5, 0x44, 0x8f, 0xf6, 0x52, 0xdf }, - { 0xa0, 0xc8, 0xa5, 0x3f, 0xd7, 0x58, 0x3e, 0x43, - 0x91, 0xbe, 0xb8, 0xd0, 0xfe, 0xd8, 0x43, 0x1f, - 0x61, 0xb8, 0x52, 0xc1, 0xbe, 0x43, 0xab, 0x91, - 0x61, 0x4b, 0xbb, 0xeb, 0x3b, 0x4f, 0x47, 0x4e }, { 0xa1, 0x50, 0x03, 0x2f, 0x4e, 0xf5, 0xd4, 0xfe, 0xb0, 0xae, 0x4a, 0xe1, 0xcd, 0x54, 0x35, 0xba, 0x04, 0xa9, 0xb6, 0xa0, 0xf9, 0x0e, 0x2f, 0x3c, @@ -2354,18 +2082,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x4f, 0xdc, 0x08, 0x15, 0xb8, 0x6e, 0xa3, 0x03, 0x34, 0x3c, 0xf8, 0xc1, 0x0f, 0x37, 0x27, 0x83, 0x27, 0x14, 0x86, 0xb9, 0xc9, 0x3b, 0x63, 0x67 }, - { 0xa5, 0xdb, 0xaf, 0x01, 0xd3, 0xd5, 0x79, 0xee, - 0x8a, 0x48, 0x8e, 0xe8, 0xd7, 0x44, 0x09, 0x58, - 0xf7, 0xbf, 0x97, 0xa2, 0xbc, 0xa8, 0xd9, 0x71, - 0xf6, 0xf8, 0x97, 0x10, 0xbc, 0x2d, 0x10, 0x6f }, { 0xa6, 0x21, 0xae, 0x36, 0x54, 0xac, 0xfd, 0x17, 0x23, 0x30, 0x70, 0xe9, 0xb1, 0x8d, 0xfd, 0x91, 0x6a, 0x55, 0x2e, 0x6a, 0x8b, 0x82, 0x42, 0xbd, 0x57, 0xbb, 0xcd, 0xf4, 0xe6, 0x5e, 0x99, 0x76 }, - { 0xa6, 0x26, 0x87, 0xde, 0x88, 0x0c, 0xf3, 0x35, - 0xae, 0x42, 0x4d, 0x4a, 0xde, 0x29, 0xc7, 0xec, - 0x33, 0xbf, 0xb9, 0xf8, 0x6e, 0xc7, 0xfc, 0xaf, - 0x61, 0x9d, 0x71, 0x7c, 0x86, 0xb8, 0xfb, 0xbc }, { 0xa6, 0x33, 0x5d, 0xf3, 0xab, 0xa5, 0xea, 0xdf, 0xbd, 0xc9, 0xc2, 0xdc, 0x9d, 0x6b, 0xe6, 0x0b, 0xb6, 0x2d, 0xf2, 0xfe, 0x24, 0xec, 0x7b, 0xa7, @@ -2402,10 +2122,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x32, 0xed, 0xb3, 0xc8, 0xd6, 0x8c, 0xe1, 0x35, 0x1a, 0x48, 0xb5, 0x6f, 0x70, 0x11, 0xbb, 0x99, 0x20, 0xcf, 0xca, 0x75, 0x7e, 0x57, 0xc6, 0xc4 }, - { 0xa7, 0x86, 0x18, 0xd8, 0xa7, 0xf0, 0x08, 0xaf, - 0xdc, 0x72, 0x44, 0x98, 0x2c, 0x11, 0x34, 0xc5, - 0xdc, 0x91, 0xec, 0x94, 0x25, 0xbf, 0xef, 0xc8, - 0xcc, 0x0a, 0xf8, 0xf8, 0xc7, 0x59, 0x61, 0xc2 }, { 0xa8, 0x53, 0xad, 0xc1, 0xc2, 0x18, 0x59, 0xaf, 0x7c, 0x46, 0x2b, 0x4a, 0xa0, 0xa5, 0x74, 0xca, 0x9f, 0xee, 0xfb, 0x18, 0x5a, 0x1f, 0xdb, 0xb6, @@ -2414,10 +2130,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x11, 0x6f, 0x6a, 0x8b, 0x01, 0xe2, 0x95, 0xcd, 0x60, 0x72, 0x69, 0x5a, 0xb1, 0x65, 0x4b, 0x7b, 0xf9, 0xc4, 0x7e, 0x06, 0x20, 0x25, 0x6f, 0x81 }, - { 0xa8, 0xc6, 0xb0, 0x72, 0x2a, 0x0d, 0x13, 0xdc, - 0x8b, 0x7f, 0xbb, 0x20, 0xbc, 0x66, 0xe6, 0x03, - 0x0e, 0x4b, 0xde, 0x99, 0xea, 0xca, 0x9c, 0x96, - 0x5d, 0x34, 0x65, 0xc9, 0xab, 0xff, 0x64, 0x11 }, { 0xa8, 0xdf, 0xf0, 0x6a, 0x17, 0x35, 0xb4, 0x6d, 0x17, 0xda, 0xeb, 0xc3, 0x43, 0x43, 0x18, 0x31, 0x3b, 0x2d, 0x9e, 0x7c, 0x3e, 0xf4, 0x8f, 0x28, @@ -2430,18 +2142,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x56, 0x21, 0x2d, 0xb3, 0xab, 0x34, 0x89, 0x6e, 0x91, 0x70, 0x93, 0x11, 0x3e, 0x47, 0xca, 0x35, 0x96, 0x2e, 0xac, 0xca, 0x9c, 0xb3, 0x86, 0xf0 }, - { 0xa9, 0x20, 0x6f, 0x6d, 0x45, 0x43, 0xed, 0x74, - 0x4a, 0x5f, 0x15, 0x4a, 0xcb, 0x44, 0x50, 0x89, - 0x6b, 0x62, 0x5d, 0x7e, 0x32, 0x33, 0x85, 0xa9, - 0xfd, 0x25, 0x63, 0x93, 0x2f, 0x9c, 0xcc, 0x1b }, - { 0xa9, 0x4c, 0xc9, 0xde, 0x55, 0x52, 0xa6, 0xd9, - 0x6f, 0xe4, 0x10, 0xbe, 0x03, 0x97, 0x6f, 0x6b, - 0x0d, 0x4d, 0xa0, 0x5d, 0x73, 0x7a, 0xd2, 0xa3, - 0x1e, 0x0b, 0xad, 0x90, 0x82, 0xa5, 0x77, 0xb1 }, - { 0xa9, 0x5c, 0x06, 0x3e, 0x9e, 0x35, 0x84, 0xe5, - 0x99, 0x88, 0xf0, 0x73, 0x86, 0x4c, 0x18, 0x76, - 0xb5, 0xdf, 0x9b, 0x44, 0xc6, 0x1b, 0x4a, 0x8b, - 0xe4, 0x83, 0xbe, 0x05, 0xcf, 0xd1, 0xa1, 0xa6 }, { 0xa9, 0x71, 0x2f, 0x85, 0xed, 0x2e, 0x25, 0xad, 0xa5, 0x7d, 0xc1, 0xf0, 0xf8, 0x6d, 0xe1, 0x07, 0xb5, 0xe2, 0xf0, 0x36, 0x09, 0x53, 0xf1, 0xed, @@ -2470,10 +2170,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xec, 0xce, 0x7f, 0x5e, 0x61, 0x59, 0x9a, 0xf5, 0x26, 0x69, 0xbf, 0x59, 0x50, 0x7f, 0x8e, 0xf1, 0x99, 0x13, 0xc4, 0x2e, 0xe1, 0x29, 0xda, 0xf0 }, - { 0xab, 0xa7, 0x8e, 0x90, 0xf3, 0x24, 0x17, 0xae, - 0xc2, 0x8e, 0xea, 0x30, 0x22, 0xa2, 0xe2, 0xb7, - 0x66, 0x1a, 0xc7, 0x23, 0xc8, 0x7e, 0x0d, 0xbc, - 0xe2, 0x33, 0xe2, 0x16, 0x8f, 0xcf, 0x91, 0xb3 }, { 0xab, 0xeb, 0x6a, 0xa0, 0xd1, 0xb0, 0xe0, 0x49, 0xd6, 0x9d, 0xf8, 0x3a, 0xdd, 0x19, 0xf7, 0x26, 0x8a, 0x38, 0xde, 0x6c, 0x00, 0x72, 0x60, 0x68, @@ -2486,10 +2182,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x5a, 0xd4, 0xa3, 0xba, 0x3d, 0x4b, 0x01, 0x84, 0x91, 0xf3, 0x66, 0x1a, 0x37, 0x9b, 0x3d, 0xfe, 0xdd, 0x6f, 0xd3, 0xc3, 0x2e, 0xfa, 0x84, 0x7d }, - { 0xac, 0x8c, 0x6f, 0x03, 0xe4, 0xba, 0xcf, 0x72, - 0x20, 0x25, 0xdb, 0x54, 0xd0, 0xfa, 0xae, 0x7d, - 0xbe, 0x51, 0x37, 0x97, 0x37, 0x39, 0x45, 0x05, - 0xf0, 0x86, 0xaa, 0x89, 0xe2, 0xd4, 0xf7, 0x3b }, { 0xac, 0x90, 0x98, 0xf6, 0x4f, 0xe1, 0x03, 0xc8, 0xc1, 0x40, 0x30, 0xdb, 0xce, 0xdd, 0x63, 0xd1, 0xd1, 0x7c, 0x33, 0x8e, 0xbd, 0x1d, 0x7d, 0xe5, @@ -2610,10 +2302,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xa0, 0x49, 0xfe, 0x83, 0xf3, 0xd2, 0x9b, 0x38, 0x5b, 0x90, 0xd3, 0xd0, 0x0b, 0xa8, 0x57, 0xd6, 0x2f, 0x19, 0x67, 0x81, 0xdd, 0xa3, 0xd1, 0x85 }, - { 0xb4, 0x2c, 0x64, 0xf0, 0x25, 0xdf, 0x8f, 0x37, - 0x0e, 0xb7, 0xa4, 0x69, 0x94, 0x2b, 0x97, 0xe2, - 0xf8, 0xb5, 0xf4, 0xbf, 0xac, 0xc4, 0xcf, 0x17, - 0xd2, 0xa0, 0x8f, 0xca, 0x57, 0xbb, 0xc4, 0x9b }, { 0xb4, 0xae, 0x2a, 0x6b, 0xfc, 0xa5, 0x31, 0xc9, 0x9c, 0x69, 0xb3, 0x5a, 0xfe, 0x67, 0x54, 0xfc, 0x49, 0x27, 0x5b, 0x6c, 0xca, 0xcd, 0xc8, 0x26, @@ -2666,14 +2354,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x4f, 0x2b, 0x81, 0xf7, 0xf7, 0x21, 0x06, 0x73, 0xe9, 0x73, 0x08, 0xaf, 0xf1, 0x24, 0x3f, 0x26, 0x99, 0x5a, 0x25, 0xfa, 0x23, 0x0c, 0xfe, 0x4c }, - { 0xb7, 0x45, 0x85, 0x05, 0xc5, 0x17, 0x90, 0x14, - 0x9c, 0x5e, 0x98, 0x00, 0xfd, 0x22, 0x74, 0x8a, - 0x1d, 0x44, 0x66, 0x5f, 0x68, 0x34, 0xba, 0x84, - 0x4e, 0x9a, 0x0c, 0x32, 0x31, 0x4a, 0x57, 0x21 }, - { 0xb7, 0x9f, 0xca, 0x4d, 0x47, 0x92, 0xec, 0x5e, - 0x5a, 0x74, 0x06, 0x59, 0x81, 0x3a, 0x0f, 0x46, - 0x08, 0xea, 0xf9, 0xba, 0x9c, 0xbb, 0xa8, 0xa0, - 0xf8, 0xda, 0xe1, 0xdd, 0xbb, 0xe6, 0x1e, 0x77 }, { 0xb7, 0xa2, 0xae, 0x06, 0x06, 0xaa, 0x2c, 0xfb, 0x27, 0x01, 0xb3, 0xb2, 0x77, 0xf4, 0xd7, 0x12, 0x54, 0x70, 0x48, 0x7e, 0xfd, 0x94, 0x05, 0x85, @@ -2694,10 +2374,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x62, 0xb6, 0x2f, 0x36, 0x50, 0xdb, 0x00, 0xa3, 0x45, 0xf4, 0x6a, 0x0e, 0x8e, 0x01, 0x1a, 0x20, 0x01, 0x3f, 0xd8, 0xed, 0xce, 0x25, 0x27, 0x0d }, - { 0xb9, 0xcc, 0x92, 0xf7, 0x8c, 0x2c, 0x19, 0x57, - 0xdb, 0xb6, 0xc4, 0xa5, 0xe4, 0x25, 0x44, 0x68, - 0xfb, 0xcd, 0x88, 0xb1, 0xfd, 0x9f, 0x98, 0xfa, - 0x6d, 0x76, 0x08, 0x70, 0x9e, 0xbe, 0x92, 0x8d }, { 0xba, 0x18, 0x2c, 0x1b, 0x75, 0xd8, 0xdf, 0xd1, 0x18, 0x92, 0xe4, 0x77, 0x59, 0x59, 0xad, 0x8a, 0x8c, 0x78, 0x2c, 0xef, 0x60, 0xec, 0xea, 0xbe, @@ -2714,10 +2390,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x51, 0x61, 0x13, 0x55, 0x2c, 0x17, 0xab, 0x77, 0x82, 0xa7, 0xeb, 0xba, 0xea, 0x0b, 0xe3, 0x9f, 0x58, 0x92, 0x84, 0x1f, 0x1f, 0x74, 0xd2, 0x98 }, - { 0xbb, 0x13, 0xdf, 0x73, 0xb6, 0xe8, 0x89, 0x77, - 0x7c, 0x4d, 0x85, 0xec, 0x93, 0xb8, 0x3e, 0xa8, - 0xbb, 0x95, 0x43, 0xf9, 0xfc, 0x08, 0xc2, 0xb3, - 0x1c, 0x02, 0xac, 0x72, 0xb3, 0x1a, 0x09, 0x0d }, { 0xbb, 0x5c, 0xb3, 0x78, 0xb7, 0xb9, 0x48, 0x7f, 0xa6, 0x1b, 0xc0, 0x91, 0x3d, 0xa1, 0xdf, 0x26, 0xa1, 0xcf, 0xef, 0xf7, 0x45, 0x2d, 0x9b, 0xa3, @@ -2734,14 +2406,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x8c, 0xa8, 0xbc, 0x2c, 0x62, 0xfb, 0xcc, 0x40, 0x17, 0xff, 0x24, 0x96, 0x98, 0xbe, 0xed, 0xfb, 0x1e, 0xf3, 0x6f, 0x37, 0x5f, 0xb3, 0x9f, 0x72 }, - { 0xbc, 0x1a, 0x3b, 0x83, 0x46, 0xa5, 0x18, 0x4e, - 0x8f, 0xe2, 0xa9, 0x36, 0xd6, 0xd9, 0xce, 0x2c, - 0xbe, 0x3a, 0x92, 0x05, 0x54, 0xe0, 0x60, 0xf9, - 0x07, 0x97, 0xf9, 0x8f, 0xee, 0x62, 0xa8, 0x52 }, - { 0xbc, 0x98, 0x39, 0xc8, 0xb9, 0x22, 0xf6, 0x54, - 0x57, 0x67, 0xa2, 0xba, 0x46, 0x5a, 0x5b, 0xea, - 0x9a, 0xa1, 0x84, 0x11, 0x52, 0x99, 0x4a, 0x6c, - 0xf4, 0x67, 0x83, 0xae, 0x49, 0x98, 0xaf, 0xcc }, { 0xbd, 0x2e, 0x2f, 0x37, 0xc9, 0x66, 0xc3, 0x86, 0xd9, 0x70, 0x44, 0xfd, 0xe3, 0xe3, 0xf9, 0x00, 0xfb, 0x1a, 0x0b, 0x04, 0x03, 0xb5, 0x81, 0x72, @@ -2750,10 +2414,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x2a, 0xa7, 0xa7, 0x5f, 0x77, 0x63, 0xa8, 0x38, 0xcf, 0x4b, 0xa1, 0x7f, 0xb3, 0x64, 0x72, 0xba, 0x12, 0x69, 0x8c, 0x45, 0xdf, 0x88, 0xe8, 0x46 }, - { 0xbe, 0x2e, 0x88, 0xc5, 0xee, 0x30, 0x7b, 0xa5, - 0x41, 0x73, 0xa6, 0x00, 0x2b, 0x99, 0x16, 0x92, - 0xc8, 0xbd, 0x1d, 0x40, 0x8a, 0x59, 0x2f, 0x70, - 0x7b, 0xb1, 0xaf, 0x56, 0xf5, 0xb9, 0xd7, 0x42 }, { 0xbe, 0x41, 0x0a, 0x51, 0xd3, 0x44, 0x17, 0x76, 0x91, 0xb3, 0x42, 0x64, 0x10, 0xa4, 0x41, 0xaf, 0xd1, 0xc9, 0x40, 0xb1, 0xb2, 0x7c, 0xf5, 0x29, @@ -2762,10 +2422,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xb6, 0x20, 0x4f, 0x20, 0x13, 0x1b, 0x01, 0xff, 0x28, 0xb7, 0xdd, 0xff, 0x36, 0x2e, 0x42, 0x9b, 0xfd, 0xf8, 0x8f, 0x36, 0x37, 0x58, 0x24, 0x51 }, - { 0xbe, 0xac, 0x00, 0x60, 0x68, 0x7e, 0xb2, 0x5a, - 0x9b, 0xed, 0x21, 0xa1, 0x99, 0x97, 0xaf, 0xff, - 0x67, 0x7c, 0x89, 0x61, 0xdc, 0x00, 0xe2, 0x3b, - 0x4c, 0x1e, 0x27, 0x7f, 0xf8, 0x58, 0xc0, 0x92 }, { 0xbe, 0xb9, 0x09, 0x0c, 0x92, 0xd1, 0x6b, 0xd0, 0x5a, 0xf3, 0x91, 0x5a, 0x39, 0xcc, 0x2a, 0xfa, 0x9f, 0x6a, 0x8a, 0x6f, 0xbe, 0xd4, 0xfe, 0x54, @@ -2814,10 +2470,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xf7, 0xbd, 0x38, 0x95, 0x54, 0x60, 0xc3, 0xfc, 0x43, 0x55, 0x0d, 0x97, 0x7f, 0x25, 0xe3, 0x43, 0xd4, 0x9c, 0xd4, 0xaf, 0xad, 0xf2, 0x09, 0x3c }, - { 0xc0, 0xd3, 0xdc, 0x9a, 0x2d, 0x13, 0x9d, 0x38, - 0xce, 0x02, 0xc0, 0x78, 0xf3, 0xc2, 0x92, 0x5d, - 0x89, 0x1d, 0x24, 0xe4, 0x36, 0x13, 0xcb, 0xee, - 0x3f, 0x18, 0xa2, 0xc8, 0x60, 0x98, 0x84, 0xb2 }, { 0xc0, 0xfe, 0xb7, 0x2a, 0x5f, 0x33, 0x16, 0x5c, 0x0d, 0xc7, 0xc4, 0x24, 0x7e, 0x23, 0xf3, 0x8c, 0xc6, 0x1f, 0x25, 0x24, 0x42, 0xb2, 0xf6, 0x13, @@ -2938,10 +2590,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x8a, 0x88, 0x16, 0x10, 0x63, 0x70, 0x86, 0xf8, 0x8d, 0x9a, 0x11, 0x5e, 0x00, 0x92, 0x46, 0xd2, 0x7f, 0x48, 0x9f, 0xa7, 0x18, 0x51, 0x88, 0xa8 }, - { 0xc7, 0xf8, 0x85, 0xe4, 0x1a, 0xa5, 0x3b, 0x8c, - 0xb8, 0xe4, 0xe5, 0x59, 0xc4, 0x04, 0x3a, 0x87, - 0xda, 0xfb, 0x78, 0x7a, 0x0d, 0x2b, 0x2e, 0xf1, - 0xbc, 0xc0, 0x55, 0x71, 0xb7, 0x5d, 0x4e, 0x29 }, { 0xc7, 0xff, 0x8e, 0xfd, 0xec, 0xdf, 0x00, 0xd1, 0xfc, 0x8d, 0x55, 0x2d, 0x2a, 0x70, 0x70, 0xe5, 0xe3, 0x3d, 0x42, 0xe5, 0x90, 0xf5, 0x86, 0xc6, @@ -2974,10 +2622,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xb6, 0x1b, 0x90, 0x92, 0xa9, 0xaa, 0x96, 0x81, 0x62, 0x36, 0x55, 0xa6, 0x6f, 0x4f, 0xcb, 0xc4, 0xd3, 0xa6, 0x7e, 0xfd, 0x56, 0x72, 0x48, 0x30 }, - { 0xc9, 0x7e, 0x4d, 0x81, 0xe7, 0x4e, 0x3d, 0x0a, - 0x5e, 0xe0, 0x9c, 0x6f, 0x76, 0x9b, 0x95, 0x7e, - 0x70, 0x04, 0xad, 0x2c, 0x9f, 0xc6, 0x66, 0x8a, - 0x69, 0xd6, 0xca, 0x29, 0xe0, 0x66, 0xe7, 0xfe }, { 0xca, 0x55, 0x6f, 0x82, 0xc9, 0x68, 0x4c, 0x9a, 0xf3, 0x55, 0x7d, 0x3e, 0x2d, 0x88, 0xaf, 0x92, 0xed, 0x25, 0x9c, 0x20, 0xff, 0xd1, 0xdd, 0xe9, @@ -3014,10 +2658,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x49, 0xc8, 0xb7, 0xa8, 0x14, 0x8f, 0x26, 0xd7, 0x71, 0x08, 0x3e, 0xc5, 0x18, 0xf9, 0xb6, 0x6f, 0xf5, 0x47, 0xf2, 0x82, 0x2d, 0x11, 0x93, 0x6d }, - { 0xcc, 0x4e, 0x09, 0x63, 0x13, 0xdf, 0xa0, 0xcc, - 0x24, 0x77, 0xa3, 0xa5, 0xb7, 0x9a, 0xef, 0x0a, - 0x45, 0x54, 0x58, 0x69, 0xa7, 0xf8, 0x8a, 0x29, - 0x14, 0x96, 0x06, 0x4b, 0x69, 0x76, 0xe1, 0x4d }, { 0xcc, 0x65, 0xcd, 0xc5, 0x33, 0x62, 0xd4, 0x21, 0x62, 0x7e, 0xae, 0xf5, 0xd0, 0xc8, 0xe4, 0xc4, 0xe2, 0x40, 0xad, 0xe0, 0xc9, 0xd4, 0x20, 0xbe, @@ -3054,10 +2694,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x85, 0xf5, 0xb6, 0x4e, 0x65, 0x22, 0x8d, 0x03, 0xfc, 0x77, 0x93, 0xd9, 0x49, 0x42, 0xf8, 0x8a, 0x1c, 0x72, 0xbb, 0x7b, 0x61, 0x14, 0x51, 0xd5 }, - { 0xcf, 0x03, 0x40, 0x17, 0x5b, 0x25, 0x03, 0xc8, - 0xfa, 0x5d, 0x52, 0xed, 0x42, 0x5b, 0xf3, 0x7e, - 0x69, 0xc1, 0x80, 0xe5, 0x75, 0xad, 0xc1, 0xa2, - 0x6a, 0x47, 0x81, 0x97, 0x71, 0xb6, 0x8f, 0x7d }, { 0xcf, 0x92, 0x77, 0xce, 0xea, 0x50, 0x1a, 0x49, 0x66, 0x04, 0x3e, 0xf2, 0xb0, 0xf8, 0x86, 0x2a, 0xc9, 0x00, 0x93, 0x89, 0x78, 0x08, 0x26, 0x22, @@ -3082,14 +2718,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xbb, 0x8b, 0xaf, 0x57, 0xf5, 0xc4, 0x5b, 0x69, 0x16, 0x8c, 0x3a, 0x6e, 0xe3, 0xfb, 0xcd, 0xf3, 0xec, 0x2a, 0x77, 0xe8, 0x7c, 0x7c, 0x50, 0x09 }, - { 0xd1, 0xfa, 0xd9, 0xa8, 0xe6, 0x2e, 0x06, 0xcf, - 0x9b, 0x40, 0x3a, 0xdf, 0x51, 0xed, 0x60, 0x75, - 0xec, 0xe7, 0x61, 0xa1, 0x0d, 0xd6, 0xa4, 0xd8, - 0xde, 0x08, 0x82, 0x2f, 0xbb, 0x08, 0x22, 0xfd }, - { 0xd2, 0x3f, 0xeb, 0x93, 0x47, 0x60, 0xb8, 0xdf, - 0x4e, 0xe6, 0xb0, 0xe8, 0xbb, 0x4f, 0x5d, 0x31, - 0x5d, 0x40, 0x5b, 0xf0, 0x56, 0x18, 0x2e, 0x5d, - 0x5f, 0x70, 0x20, 0x31, 0x94, 0x61, 0x8a, 0x05 }, { 0xd2, 0x56, 0x79, 0xcb, 0x58, 0x3b, 0xa0, 0x10, 0x8f, 0x74, 0x97, 0xe3, 0x21, 0xc6, 0x5c, 0x4d, 0xc2, 0xca, 0x0f, 0x28, 0x20, 0xc7, 0xfc, 0xdb, @@ -3102,18 +2730,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x4c, 0x2d, 0xfe, 0x94, 0xcb, 0x44, 0x50, 0x37, 0x1e, 0x72, 0x36, 0xbd, 0xbd, 0x1c, 0x81, 0x13, 0xff, 0x36, 0x0f, 0xa4, 0xa1, 0x58, 0x1e, 0xfc }, - { 0xd2, 0xd1, 0x84, 0xca, 0x5b, 0x97, 0xac, 0x7b, - 0xd3, 0x4e, 0x78, 0x42, 0x4c, 0xa0, 0xc2, 0xb3, - 0x9c, 0x35, 0x08, 0x52, 0xcc, 0xb1, 0x33, 0xe5, - 0xa1, 0x87, 0xf7, 0x61, 0x7d, 0x00, 0xb0, 0x2c }, { 0xd2, 0xe8, 0xa1, 0x23, 0x7a, 0x93, 0xf5, 0x78, 0xd1, 0xba, 0x8f, 0x09, 0xe4, 0xff, 0x10, 0x7b, 0x62, 0x35, 0x78, 0x85, 0x42, 0xaa, 0x61, 0x83, 0xd1, 0x76, 0xdb, 0xf1, 0xc8, 0x8d, 0xcf, 0xb6 }, - { 0xd3, 0x10, 0x0b, 0xc8, 0x42, 0x8b, 0xa2, 0x3a, - 0xe1, 0x3b, 0x41, 0xea, 0xa2, 0x95, 0xbf, 0xbf, - 0xd6, 0x97, 0xf5, 0x0b, 0x81, 0xca, 0xef, 0x6a, - 0x30, 0xa4, 0xd1, 0x99, 0x47, 0x1b, 0x9f, 0x32 }, { 0xd3, 0x22, 0xe0, 0xc4, 0x4e, 0xa7, 0x92, 0xc0, 0x00, 0x13, 0x01, 0xa6, 0x32, 0xa1, 0x1d, 0x50, 0x6e, 0xa9, 0x17, 0xde, 0xed, 0xca, 0x8e, 0xd0, @@ -3134,10 +2754,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x3b, 0xb9, 0x9f, 0x80, 0x68, 0xcf, 0xee, 0x86, 0xa4, 0xb9, 0xf0, 0x89, 0xe0, 0x2d, 0x0c, 0x6c, 0xb6, 0xd4, 0xa3, 0x94, 0x6c, 0x6b, 0x16, 0x7a }, - { 0xd5, 0x50, 0xb9, 0xa6, 0xd5, 0xc3, 0xf5, 0x25, - 0x7c, 0x99, 0xb9, 0x94, 0x43, 0x69, 0x88, 0x3d, - 0xa1, 0x1d, 0xbe, 0x23, 0xb9, 0x6e, 0x19, 0x34, - 0xed, 0xed, 0x52, 0x1b, 0x73, 0x55, 0xe4, 0x44 }, { 0xd5, 0x83, 0x94, 0x96, 0xcd, 0xc8, 0x5b, 0xe3, 0xd1, 0xf1, 0xac, 0x65, 0x2e, 0xfa, 0x92, 0xbe, 0xa3, 0xb0, 0x61, 0xc1, 0x3d, 0xad, 0x5a, 0x82, @@ -3154,10 +2770,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xaa, 0x7e, 0x87, 0x8e, 0x6a, 0x85, 0x09, 0x1b, 0xaa, 0x07, 0x8d, 0x26, 0x8b, 0xbd, 0xb4, 0x9f, 0x09, 0x67, 0x94, 0x08, 0x61, 0x2d, 0x1e, 0xfe }, - { 0xd6, 0x46, 0x08, 0xb1, 0x5f, 0x71, 0xfc, 0x3b, - 0x91, 0x90, 0xa2, 0x00, 0xee, 0x3c, 0xb5, 0xbc, - 0xd9, 0xfc, 0x5b, 0x99, 0xfb, 0x67, 0x74, 0x9d, - 0x18, 0x87, 0xd9, 0x17, 0xd8, 0x50, 0x01, 0x0b }, { 0xd6, 0x83, 0xd0, 0x6e, 0xb9, 0x28, 0x74, 0x43, 0xe5, 0x01, 0xec, 0xf7, 0x1d, 0xad, 0xa6, 0x80, 0x35, 0x88, 0x71, 0xd1, 0x2a, 0x53, 0xfb, 0xcc, @@ -3190,10 +2802,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x0b, 0x84, 0xd9, 0xa1, 0x7b, 0x1e, 0x90, 0x24, 0xf6, 0x27, 0xc1, 0xec, 0xc3, 0x5e, 0xc7, 0xe6, 0x71, 0xc1, 0x42, 0x92, 0xa7, 0xb8, 0x8b, 0x43 }, - { 0xd8, 0x55, 0x49, 0xfc, 0xd2, 0x4d, 0x36, 0xcb, - 0x3f, 0x7c, 0x18, 0x06, 0x3f, 0x97, 0x5a, 0x16, - 0x9f, 0xe3, 0xa1, 0xfb, 0x8d, 0x0a, 0x35, 0x9f, - 0xd3, 0x5c, 0x28, 0x7b, 0xb2, 0xaf, 0x50, 0xca }, { 0xd8, 0x7a, 0x9d, 0xf7, 0x19, 0x1e, 0x29, 0xc8, 0x04, 0x1e, 0x4c, 0x19, 0x3c, 0x03, 0xa8, 0xa7, 0x12, 0x5f, 0x16, 0x6e, 0xa6, 0xcb, 0x21, 0x1f, @@ -3218,10 +2826,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x4a, 0x3e, 0xd7, 0xfc, 0x55, 0x8c, 0x58, 0x45, 0x64, 0x51, 0x60, 0xda, 0xb3, 0x53, 0x85, 0xc1, 0x38, 0xbc, 0x89, 0x9c, 0x4d, 0xad, 0x8b, 0x36 }, - { 0xd9, 0xd0, 0xd9, 0x6e, 0xb3, 0x28, 0xe0, 0xc1, - 0x77, 0x8b, 0x56, 0xa9, 0x2f, 0x71, 0x24, 0x3b, - 0x6c, 0x0d, 0xb4, 0x5c, 0x62, 0x51, 0x32, 0xdd, - 0x82, 0xca, 0x11, 0xa0, 0x97, 0xe7, 0x91, 0xc6 }, { 0xd9, 0xe8, 0xcc, 0xda, 0x78, 0xfb, 0x8d, 0x5d, 0xbc, 0xe6, 0x94, 0x15, 0x57, 0x61, 0xf4, 0xd0, 0x2c, 0x30, 0xcc, 0x8d, 0x7a, 0xea, 0x0e, 0x11, @@ -3242,22 +2846,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xe5, 0x38, 0x9a, 0x26, 0x08, 0x1c, 0x99, 0x8b, 0x5f, 0xfa, 0x67, 0xdd, 0x45, 0x97, 0xf8, 0xca, 0x67, 0xef, 0x10, 0x6a, 0xd7, 0x5f, 0x34, 0x9f }, - { 0xdb, 0xa1, 0x23, 0x67, 0x1f, 0xed, 0x4b, 0x28, - 0x70, 0x33, 0xa4, 0xb0, 0x06, 0x8f, 0xc7, 0x14, - 0xa5, 0xfc, 0x9c, 0x02, 0x6e, 0xf5, 0x65, 0x0b, - 0x42, 0xde, 0x25, 0x85, 0x9a, 0x12, 0x6a, 0xd1 }, { 0xdb, 0xa2, 0x21, 0xc2, 0xab, 0x44, 0xb5, 0x2c, 0x0b, 0x83, 0x36, 0xc4, 0x69, 0xfa, 0xa8, 0x56, 0xd6, 0xc3, 0xec, 0xdc, 0x6c, 0x24, 0x6b, 0xe3, 0xca, 0xc7, 0xe0, 0xf6, 0x28, 0x4b, 0x5b, 0xda }, - { 0xdc, 0x3d, 0x81, 0xc3, 0x01, 0xbc, 0xde, 0xc5, - 0x38, 0xef, 0xc7, 0xfa, 0x6a, 0x4e, 0x5a, 0x13, - 0xe5, 0x17, 0xd2, 0xa4, 0x61, 0x22, 0x2d, 0xed, - 0x98, 0x3e, 0x75, 0x56, 0x4d, 0x0e, 0x68, 0x84 }, - { 0xdc, 0x42, 0x4a, 0x70, 0x87, 0x80, 0x95, 0x98, - 0x7a, 0x5b, 0xcd, 0x17, 0x1a, 0xa5, 0x13, 0x67, - 0x7b, 0xda, 0x56, 0xdf, 0x35, 0xb6, 0x81, 0xc7, - 0x07, 0x84, 0x0f, 0xdc, 0xea, 0xc5, 0xe4, 0x0f }, { 0xdc, 0x90, 0x90, 0x55, 0x0c, 0x93, 0x42, 0xe2, 0xfa, 0xe2, 0x42, 0x26, 0xa4, 0xf9, 0xb3, 0xf6, 0x93, 0xf4, 0xd1, 0x46, 0x52, 0x79, 0xc3, 0x7b, @@ -3274,10 +2866,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xf0, 0xfd, 0xdb, 0x6b, 0x37, 0xfe, 0x00, 0x28, 0xde, 0x8b, 0x7d, 0x3c, 0xe5, 0x79, 0x1b, 0x45, 0x0d, 0xd2, 0x83, 0xb2, 0x0a, 0xdb, 0x05, 0xd2 }, - { 0xde, 0x45, 0x46, 0xc0, 0x24, 0x51, 0xa5, 0xb5, - 0xad, 0x85, 0xea, 0x53, 0x2f, 0x09, 0x6f, 0xdf, - 0x1e, 0x2b, 0x41, 0x71, 0xd9, 0x6a, 0x1d, 0xc3, - 0x93, 0x6a, 0x19, 0x74, 0xf0, 0x58, 0xf0, 0xb2 }, { 0xde, 0x5c, 0x3d, 0x09, 0x58, 0xa6, 0x12, 0xbd, 0x6d, 0x48, 0x09, 0x15, 0x03, 0x3d, 0x97, 0x15, 0x58, 0xdf, 0x35, 0xce, 0xb1, 0xc9, 0x18, 0xe6, @@ -3314,26 +2902,14 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xc4, 0xba, 0x83, 0x99, 0xd4, 0xd8, 0xd5, 0xa0, 0xd1, 0x98, 0x57, 0x8f, 0x42, 0x99, 0xfd, 0xfd, 0xaf, 0xf7, 0x8c, 0x3f, 0x67, 0x71, 0xf3, 0x94 }, - { 0xe0, 0x65, 0x19, 0x10, 0x41, 0x74, 0x08, 0xbe, - 0x2b, 0x0c, 0xfd, 0x3d, 0x9e, 0xaa, 0xeb, 0xca, - 0x32, 0x1f, 0x61, 0x6d, 0xda, 0x48, 0xcb, 0x4f, - 0x09, 0x10, 0x9d, 0x67, 0x19, 0x45, 0xa1, 0x1c }, { 0xe0, 0x8b, 0x2c, 0xc2, 0x7a, 0xe8, 0xe2, 0xef, 0x1a, 0x33, 0x01, 0x7a, 0x9a, 0xc2, 0x5d, 0xda, 0xfb, 0x5e, 0xa1, 0x12, 0xc9, 0x56, 0xb0, 0x02, 0xfe, 0x6c, 0x79, 0x80, 0x14, 0xaa, 0x90, 0x65 }, - { 0xe0, 0xa0, 0x7b, 0x39, 0x6d, 0x25, 0x7f, 0xab, - 0xb4, 0xe3, 0x22, 0xd8, 0x79, 0x94, 0x88, 0x37, - 0x28, 0x7a, 0xaa, 0x99, 0xad, 0x14, 0xd7, 0x8d, - 0x3a, 0x2f, 0x9d, 0xfe, 0x5c, 0x97, 0x28, 0xbf }, { 0xe0, 0xa9, 0xd9, 0x63, 0x6e, 0xfa, 0x36, 0xa7, 0x72, 0xac, 0xb5, 0xd0, 0x22, 0xfc, 0xa9, 0x73, 0x71, 0xb4, 0x4f, 0x7b, 0x80, 0x4b, 0x03, 0x97, 0xfb, 0x6c, 0x37, 0x1a, 0x22, 0x5b, 0xda, 0x78 }, - { 0xe0, 0xbb, 0xef, 0x7e, 0xe4, 0x37, 0xb0, 0x59, - 0xe0, 0x3b, 0x52, 0x9b, 0xe6, 0xb4, 0x09, 0x6d, - 0x56, 0xc7, 0x4e, 0x90, 0x67, 0xb0, 0x5f, 0x87, - 0xaa, 0x6a, 0x5a, 0x61, 0x93, 0x40, 0xa7, 0xc3 }, { 0xe0, 0xdd, 0xe1, 0x29, 0xd2, 0x60, 0xc3, 0xda, 0xb6, 0x91, 0xd8, 0x1d, 0xab, 0xad, 0x73, 0x4c, 0x9a, 0xdc, 0x61, 0xd2, 0x0c, 0x1a, 0xe1, 0xb6, @@ -3374,10 +2950,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x7e, 0x1f, 0x45, 0x5b, 0x85, 0xc0, 0x6f, 0x0d, 0x80, 0x9e, 0x75, 0xa5, 0x5c, 0x6b, 0x05, 0x48, 0x16, 0xe0, 0x19, 0x89, 0x9a, 0x3a, 0x02, 0xff }, - { 0xe3, 0x1f, 0xa0, 0xbd, 0xe8, 0x58, 0x9e, 0xdd, - 0xda, 0x1c, 0x5d, 0x1a, 0xa9, 0xc5, 0x81, 0x86, - 0xc3, 0x14, 0x36, 0x85, 0x67, 0xbd, 0xf9, 0xdc, - 0xd5, 0x37, 0xaa, 0xe3, 0xcf, 0xf8, 0x77, 0x52 }, { 0xe3, 0xc8, 0xfc, 0x63, 0x7b, 0x7b, 0xb0, 0xcc, 0x67, 0x4a, 0x5a, 0x4c, 0x3b, 0x4d, 0x35, 0x62, 0xeb, 0x8a, 0xa0, 0x0d, 0x7a, 0xd2, 0xc8, 0xa9, @@ -3426,18 +2998,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xfa, 0x2b, 0xfb, 0x76, 0xc2, 0x2d, 0xfa, 0x71, 0xbc, 0x3d, 0xa4, 0x8f, 0x67, 0x1e, 0xf7, 0x7c, 0x00, 0xaa, 0x8e, 0x45, 0x9b, 0x7c, 0xc8, 0x2a }, - { 0xe8, 0x1a, 0x87, 0x45, 0xad, 0x86, 0xf6, 0x5f, - 0xa0, 0xd8, 0x51, 0xfc, 0xb7, 0x2e, 0x3e, 0xf5, - 0x4d, 0x51, 0xbc, 0x60, 0xb9, 0x68, 0x0c, 0xb2, - 0x5e, 0xb2, 0xf3, 0xac, 0x44, 0xea, 0xa7, 0xa4 }, { 0xe8, 0x21, 0x3c, 0x45, 0x51, 0x81, 0x61, 0xbc, 0x36, 0x37, 0x3d, 0xcd, 0x2d, 0x4b, 0x21, 0xb7, 0x6a, 0x7c, 0x06, 0x6d, 0xf5, 0x52, 0x6e, 0x88, 0x8b, 0x6e, 0xed, 0x09, 0xa9, 0xee, 0xd0, 0x62 }, - { 0xe8, 0x6e, 0xe6, 0x9d, 0x51, 0xbe, 0x64, 0xf8, - 0x28, 0xfc, 0x22, 0xcc, 0xe5, 0xbc, 0xc1, 0x1d, - 0x24, 0xa5, 0xf1, 0x77, 0xf9, 0xba, 0x99, 0x51, - 0x92, 0x71, 0xa4, 0xf3, 0x9f, 0x0c, 0x51, 0x7c }, { 0xe8, 0xa6, 0x09, 0xec, 0x44, 0xf9, 0x3c, 0x12, 0xe0, 0x81, 0xe5, 0x94, 0x3b, 0x5e, 0xa0, 0x48, 0x68, 0x14, 0x48, 0x33, 0x32, 0x5d, 0xaa, 0x64, @@ -3470,10 +3034,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x5a, 0x76, 0x07, 0x64, 0x3e, 0x15, 0x26, 0x0d, 0x1c, 0x93, 0xfd, 0x9b, 0xe0, 0xfa, 0xb1, 0x0b, 0x76, 0xdc, 0x96, 0x86, 0xf6, 0x54, 0xc6, 0xe5 }, - { 0xec, 0x01, 0x78, 0xd1, 0xca, 0x3b, 0x94, 0x52, - 0xaa, 0x5c, 0xd5, 0xd3, 0x75, 0x45, 0x6b, 0xab, - 0xf0, 0xdc, 0x0e, 0xd2, 0x29, 0x91, 0x5d, 0x1a, - 0x8f, 0x49, 0x6d, 0xf2, 0xa2, 0xa0, 0x98, 0x71 }, { 0xec, 0x27, 0x05, 0x63, 0xb0, 0x5a, 0x06, 0xe5, 0xaa, 0xa5, 0xe6, 0xd5, 0xbb, 0xcc, 0x17, 0xcd, 0x1c, 0xb5, 0xb2, 0xa9, 0x4d, 0x93, 0x84, 0x75, @@ -3534,10 +3094,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x51, 0x6b, 0xf6, 0x39, 0x5d, 0xbd, 0x29, 0x33, 0x7c, 0xfc, 0xb7, 0xd4, 0x26, 0x64, 0x10, 0xa1, 0xf5, 0xda, 0x08, 0x08, 0xe0, 0x96, 0xf4, 0x55 }, - { 0xef, 0x7e, 0x8c, 0xcd, 0x7b, 0xcf, 0xb7, 0x1d, - 0x2a, 0xa7, 0xbc, 0xdd, 0x8f, 0xd2, 0xd2, 0xd1, - 0x55, 0x77, 0x9d, 0xe8, 0x68, 0x43, 0x20, 0x44, - 0x35, 0x1e, 0x98, 0x02, 0xcc, 0xa2, 0x90, 0xaf }, { 0xef, 0xaf, 0xca, 0x84, 0x90, 0x30, 0x7b, 0x0f, 0x62, 0x2b, 0xf4, 0x3a, 0x0e, 0xb3, 0xc5, 0x1a, 0xcb, 0xdd, 0xde, 0xdc, 0x23, 0x92, 0xf1, 0x61, @@ -3554,10 +3110,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x8d, 0x77, 0x2e, 0xba, 0xfa, 0x5b, 0xf5, 0x32, 0x92, 0x47, 0x77, 0x88, 0xdc, 0x12, 0x80, 0x32, 0x76, 0xb0, 0x00, 0xc4, 0x41, 0x91, 0x03, 0xf0 }, - { 0xf0, 0x15, 0x95, 0xf5, 0xa4, 0x66, 0x88, 0x78, - 0xf6, 0xc7, 0x98, 0xa5, 0xd2, 0xf1, 0x35, 0x23, - 0xf3, 0xaf, 0xb2, 0x0e, 0xf7, 0x6f, 0xe5, 0x77, - 0x6f, 0xce, 0x47, 0xd3, 0x40, 0x9d, 0xf3, 0xc2 }, { 0xf0, 0x2f, 0x9d, 0xa4, 0x5d, 0x9e, 0xb9, 0x86, 0x19, 0x4e, 0x06, 0xf5, 0xe6, 0x18, 0x95, 0x45, 0x12, 0xc9, 0x02, 0x6e, 0x7c, 0xa7, 0xb5, 0x1e, @@ -3586,10 +3138,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x26, 0xaa, 0x5a, 0x6b, 0xf5, 0xc4, 0xde, 0x59, 0x1c, 0xf1, 0x65, 0x0f, 0xa8, 0x22, 0xf1, 0x34, 0xd9, 0x2d, 0x54, 0x8f, 0x15, 0x77, 0x73, 0xd6 }, - { 0xf2, 0x06, 0x59, 0x72, 0x49, 0x8d, 0x5e, 0x12, - 0x79, 0x8e, 0x1e, 0x1f, 0xf3, 0xe1, 0x1d, 0xe4, - 0x23, 0x3a, 0xbb, 0xbd, 0x30, 0x8a, 0x58, 0x07, - 0x60, 0x58, 0x48, 0x18, 0x6e, 0x44, 0x11, 0x7f }, { 0xf2, 0x54, 0x76, 0xf3, 0xab, 0x8e, 0x5e, 0x0b, 0x9b, 0xb6, 0x1d, 0x4c, 0xe4, 0x50, 0x7f, 0xa3, 0x52, 0x93, 0xc6, 0x64, 0x15, 0xd7, 0xd1, 0x91, @@ -3634,10 +3182,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xd3, 0xc5, 0x60, 0x17, 0x6f, 0x3d, 0x77, 0xfd, 0xc5, 0x1e, 0x5f, 0x57, 0xb5, 0xe4, 0x8a, 0xe7, 0xa4, 0xb9, 0x70, 0x0a, 0x11, 0xd4, 0x69, 0x3a }, - { 0xf6, 0x41, 0xe7, 0xe0, 0x1b, 0xf4, 0xf2, 0xb0, - 0xd0, 0xc4, 0x8b, 0xa6, 0x38, 0xa0, 0x2e, 0x26, - 0xbd, 0xdb, 0xd7, 0x7b, 0xc5, 0xe9, 0x72, 0x61, - 0x94, 0xdb, 0x1a, 0xea, 0x4f, 0x2f, 0xd7, 0x71 }, { 0xf6, 0x54, 0x6b, 0x2f, 0xfe, 0x2b, 0xae, 0xf7, 0x35, 0xe8, 0x25, 0x67, 0xa6, 0xe2, 0x36, 0x75, 0x03, 0x94, 0xc1, 0x19, 0x14, 0x09, 0x87, 0x0c, @@ -3698,10 +3242,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xad, 0x25, 0x74, 0x25, 0xaa, 0xe7, 0x20, 0x01, 0x40, 0x05, 0xb4, 0x15, 0x91, 0x2d, 0xbb, 0x8c, 0x0b, 0xc9, 0x99, 0xaf, 0x48, 0x48, 0xcf, 0xe5 }, - { 0xf9, 0x0e, 0x7c, 0x21, 0x81, 0xba, 0x53, 0x4d, - 0xcf, 0x5b, 0xb6, 0xdb, 0xf7, 0xf9, 0xad, 0xa3, - 0xff, 0x98, 0xde, 0x50, 0x0c, 0xbd, 0x42, 0x12, - 0xc0, 0xd1, 0xfa, 0x05, 0x82, 0x80, 0xfd, 0x57 }, { 0xf9, 0xa7, 0xdd, 0xd3, 0xff, 0x51, 0xaf, 0x30, 0x7f, 0x95, 0x4f, 0x7b, 0x44, 0xdb, 0xd2, 0x42, 0x83, 0xcf, 0x97, 0xb6, 0x25, 0xbe, 0x76, 0x6b, @@ -3714,10 +3254,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xa7, 0x9b, 0x05, 0x48, 0x67, 0x6c, 0x18, 0x48, 0x5a, 0xf1, 0x10, 0x4c, 0xca, 0x9b, 0xb6, 0xb8, 0xdd, 0x9b, 0x5a, 0x54, 0x3c, 0xb6, 0xc6, 0x2e }, - { 0xfa, 0xe4, 0x72, 0x1e, 0x39, 0x47, 0xa5, 0x0d, - 0xd0, 0x4d, 0x16, 0xac, 0xef, 0xf3, 0x55, 0xc0, - 0x87, 0xb7, 0xe2, 0x24, 0x6b, 0xe6, 0x0f, 0xbc, - 0x26, 0x2a, 0x53, 0x52, 0xad, 0xac, 0x18, 0x01 }, { 0xfb, 0x44, 0x15, 0x70, 0x4c, 0x1d, 0x61, 0x55, 0x10, 0x6d, 0x88, 0xf3, 0xb2, 0x0f, 0xec, 0x9f, 0x6e, 0x82, 0x0c, 0x82, 0x24, 0xfe, 0xe3, 0x5e, @@ -3750,10 +3286,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xd0, 0xa9, 0xdf, 0xcc, 0xe9, 0x03, 0x12, 0xc7, 0x52, 0xe1, 0xb5, 0x2e, 0xb6, 0x54, 0xc4, 0x2c, 0x36, 0x94, 0x4b, 0x90, 0x2a, 0x30, 0x41, 0x07 }, - { 0xfc, 0x55, 0x86, 0x91, 0xda, 0xff, 0xe1, 0xe3, - 0x53, 0x8d, 0x38, 0xa6, 0xd3, 0xa9, 0xe6, 0xe7, - 0xc9, 0x9d, 0x24, 0x0c, 0x86, 0x89, 0x66, 0x73, - 0x56, 0x27, 0x99, 0x72, 0xfb, 0x4f, 0x30, 0x85 }, { 0xfc, 0x56, 0xdb, 0xa1, 0xe7, 0xaf, 0xbd, 0xaa, 0x07, 0x33, 0xc6, 0x91, 0x1c, 0x5f, 0x1f, 0x18, 0x28, 0xcb, 0x12, 0x98, 0x31, 0x40, 0x1a, 0x3c, @@ -3832,14 +3364,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xaf, 0x3f, 0x5c, 0xf4, 0x22, 0x5a, 0x8e, 0xaf }, }; const uint8_t kCNNICEVWhitelist[][crypto::kSHA256Length] = { - { 0x0e, 0x56, 0x71, 0x6d, 0xd3, 0xc1, 0x83, 0xaa, - 0x5d, 0xe0, 0xd3, 0x96, 0x89, 0x88, 0x94, 0xf0, - 0x03, 0xaa, 0xff, 0x06, 0x2e, 0x15, 0x82, 0x33, - 0xef, 0xfb, 0x5b, 0xc9, 0xe8, 0x33, 0x71, 0x4b }, - { 0x0f, 0x07, 0xaa, 0xd7, 0xac, 0x55, 0x6f, 0x85, - 0x86, 0xcb, 0xf3, 0x47, 0x8f, 0x2e, 0xc0, 0xb5, - 0x29, 0xca, 0x46, 0x5b, 0x19, 0x3f, 0xc2, 0xa6, - 0xe1, 0x93, 0x28, 0x3a, 0xd8, 0xd7, 0xa5, 0x50 }, { 0x23, 0x86, 0x51, 0xab, 0x70, 0xb7, 0x11, 0xa0, 0x65, 0x55, 0x4e, 0x5d, 0x63, 0x6a, 0x34, 0x2c, 0x8a, 0x6b, 0xfe, 0x46, 0x0e, 0x4e, 0x7b, 0x4c, @@ -3852,18 +3376,10 @@ const uint8_t kCNNICEVWhitelist[][crypto::kSHA256Length] = { 0xaa, 0x33, 0x43, 0x60, 0xa6, 0x6a, 0xc3, 0xa7, 0x3f, 0xa8, 0xd8, 0xd3, 0x60, 0x0d, 0x89, 0x4e, 0xb0, 0xc7, 0xd2, 0x84, 0x23, 0xc6, 0x78, 0x57 }, - { 0x61, 0xa7, 0x62, 0xef, 0x47, 0xbc, 0xa4, 0xee, - 0x77, 0xa5, 0xc8, 0xaf, 0x03, 0x98, 0x9a, 0x9d, - 0xea, 0xca, 0x4d, 0x82, 0x8a, 0x53, 0xd9, 0x23, - 0xe7, 0x0b, 0xfb, 0xc7, 0x25, 0x4a, 0xc7, 0x70 }, { 0x63, 0x80, 0x65, 0xec, 0x95, 0xf1, 0xea, 0x81, 0xd9, 0x5b, 0xa4, 0xdb, 0x9e, 0xa9, 0xa2, 0xef, 0xe2, 0xd6, 0xcd, 0x78, 0x75, 0x88, 0x67, 0x04, 0x5c, 0x06, 0xb6, 0x48, 0xa5, 0xda, 0x89, 0xb2 }, - { 0x67, 0xc3, 0xc0, 0xa1, 0x60, 0xe9, 0x28, 0x5e, - 0x35, 0xa4, 0x22, 0xbb, 0x43, 0x4b, 0xff, 0xff, - 0xee, 0x28, 0x79, 0xc6, 0xc0, 0xa5, 0x69, 0x36, - 0x56, 0xe7, 0x73, 0xa6, 0xdd, 0x68, 0x5f, 0x0e }, { 0x80, 0xf3, 0xeb, 0x58, 0xea, 0x6a, 0xa2, 0x85, 0x11, 0xb0, 0x9b, 0x68, 0xf2, 0xde, 0xf9, 0xb4, 0xaf, 0xa9, 0x9c, 0x97, 0x44, 0xc0, 0xbe, 0x4e, @@ -3880,10 +3396,6 @@ const uint8_t kCNNICEVWhitelist[][crypto::kSHA256Length] = { 0xb2, 0x7c, 0x6a, 0x62, 0xe3, 0xc4, 0x23, 0x5b, 0xd8, 0x3c, 0xc5, 0xe0, 0x06, 0xe9, 0x2a, 0x55, 0xe4, 0xa9, 0x86, 0xe6, 0x30, 0x53, 0x57, 0xe3 }, - { 0xaf, 0xbb, 0x40, 0x3c, 0xad, 0x0d, 0x19, 0xcc, - 0x26, 0xae, 0x5b, 0x1e, 0x31, 0x0a, 0xc1, 0xae, - 0x79, 0x47, 0x1b, 0xad, 0x2b, 0xd7, 0x7b, 0xe4, - 0x0f, 0x12, 0x50, 0x4c, 0x42, 0xe5, 0x22, 0x0b }, { 0xb2, 0xba, 0x3b, 0x49, 0xb8, 0xe5, 0x84, 0x51, 0x81, 0x6b, 0x10, 0x83, 0x6c, 0x4f, 0x1c, 0xa6, 0xa3, 0x39, 0x37, 0xce, 0xb8, 0xf0, 0xc0, 0x4b, @@ -3908,10 +3420,6 @@ const uint8_t kCNNICEVWhitelist[][crypto::kSHA256Length] = { 0x23, 0xb9, 0xa9, 0x60, 0xb5, 0xe9, 0x67, 0x0c, 0xcc, 0x34, 0x6d, 0x89, 0x93, 0x8f, 0xfa, 0x5d, 0xf7, 0x98, 0x65, 0xe4, 0x13, 0xd6, 0x31, 0x54 }, - { 0xee, 0x3d, 0x0b, 0xc5, 0xa6, 0x5a, 0xf5, 0x8d, - 0x43, 0x2d, 0x08, 0x63, 0x7b, 0xe0, 0xb7, 0xba, - 0x49, 0xc2, 0x32, 0x61, 0x8d, 0xa9, 0xc8, 0x97, - 0x3f, 0x88, 0x56, 0x8c, 0x88, 0x89, 0xd1, 0xad }, { 0xf3, 0xcb, 0x8e, 0xa4, 0xe8, 0xf2, 0xa7, 0x00, 0x9c, 0x23, 0x3a, 0x64, 0x88, 0x71, 0xdb, 0x46, 0x04, 0xd5, 0x45, 0x4b, 0xc5, 0x55, 0x9e, 0x9b, diff --git a/chromium/net/cert/cert_verify_proc_whitelist.h b/chromium/net/cert/cert_verify_proc_whitelist.h index c4a5aae0c6a..47ce9831848 100644 --- a/chromium/net/cert/cert_verify_proc_whitelist.h +++ b/chromium/net/cert/cert_verify_proc_whitelist.h @@ -5,6 +5,7 @@ #ifndef NET_CERT_CERT_VERIFY_PROC_WHITELIST_H_ #define NET_CERT_CERT_VERIFY_PROC_WHITELIST_H_ +#include <stddef.h> #include <stdint.h> #include "crypto/sha2.h" diff --git a/chromium/net/cert/cert_verify_proc_win.cc b/chromium/net/cert/cert_verify_proc_win.cc index 4eada6f4b49..cb1db7d9b84 100644 --- a/chromium/net/cert/cert_verify_proc_win.cc +++ b/chromium/net/cert/cert_verify_proc_win.cc @@ -281,9 +281,9 @@ bool IsIssuedByKnownRoot(PCCERT_CHAIN_CONTEXT chain_context) { PCERT_CHAIN_ELEMENT* element = first_chain->rgpElement; PCCERT_CONTEXT cert = element[num_elements - 1]->pCertContext; - SHA1HashValue hash = X509Certificate::CalculateFingerprint(cert); - return IsSHA1HashInSortedArray( - hash, &kKnownRootCertSHA1Hashes[0][0], sizeof(kKnownRootCertSHA1Hashes)); + SHA256HashValue hash = X509Certificate::CalculateFingerprint256(cert); + return IsSHA256HashInSortedArray(hash, &kKnownRootCertSHA256Hashes[0][0], + sizeof(kKnownRootCertSHA256Hashes)); } // Saves some information about the certificate chain |chain_context| in @@ -295,7 +295,7 @@ void GetCertChainInfo(PCCERT_CHAIN_CONTEXT chain_context, return; PCERT_SIMPLE_CHAIN first_chain = chain_context->rgpChain[0]; - int num_elements = first_chain->cElement; + DWORD num_elements = first_chain->cElement; PCERT_CHAIN_ELEMENT* element = first_chain->rgpElement; PCCERT_CONTEXT verified_cert = NULL; @@ -316,7 +316,7 @@ void GetCertChainInfo(PCCERT_CHAIN_CONTEXT chain_context, num_elements -= 1; } - for (int i = 0; i < num_elements; ++i) { + for (DWORD i = 0; i < num_elements; ++i) { PCCERT_CONTEXT cert = element[i]->pCertContext; if (i == 0) { verified_cert = cert; @@ -341,6 +341,8 @@ void GetCertChainInfo(PCCERT_CHAIN_CONTEXT chain_context, // id-dsa-with-sha1: 1.2.840.10040.4.3 // ecdsa-with-SHA1: 1.2.840.10045.4.1 verify_result->has_sha1 = true; + if (i == 0) + verify_result->has_sha1_leaf = true; } } diff --git a/chromium/net/cert/cert_verify_result.cc b/chromium/net/cert/cert_verify_result.cc index b2413e6755d..2a418938e71 100644 --- a/chromium/net/cert/cert_verify_result.cc +++ b/chromium/net/cert/cert_verify_result.cc @@ -22,6 +22,7 @@ void CertVerifyResult::Reset() { has_md4 = false; has_md5 = false; has_sha1 = false; + has_sha1_leaf = false; is_issued_by_known_root = false; is_issued_by_additional_trust_anchor = false; common_name_fallback_used = false; diff --git a/chromium/net/cert/cert_verify_result.h b/chromium/net/cert/cert_verify_result.h index 9e673255293..104fc6eec46 100644 --- a/chromium/net/cert/cert_verify_result.h +++ b/chromium/net/cert/cert_verify_result.h @@ -48,6 +48,7 @@ class NET_EXPORT CertVerifyResult { bool has_md4; bool has_md5; bool has_sha1; + bool has_sha1_leaf; // If the certificate was successfully verified then this contains the // hashes, in several hash algorithms, of the SubjectPublicKeyInfos of the diff --git a/chromium/net/cert/crl_set.h b/chromium/net/cert/crl_set.h index f54e346b460..2a84d2ae17c 100644 --- a/chromium/net/cert/crl_set.h +++ b/chromium/net/cert/crl_set.h @@ -5,6 +5,9 @@ #ifndef NET_CERT_CRL_SET_H_ #define NET_CERT_CRL_SET_H_ +#include <stddef.h> +#include <stdint.h> + #include <string> #include <utility> #include <vector> diff --git a/chromium/net/cert/ct_known_logs.cc b/chromium/net/cert/ct_known_logs.cc index 381d4dd1013..eddeb55a8a9 100644 --- a/chromium/net/cert/ct_known_logs.cc +++ b/chromium/net/cert/ct_known_logs.cc @@ -4,28 +4,63 @@ #include "net/cert/ct_known_logs.h" -#include <string> +#include <algorithm> +#include "base/logging.h" #include "base/macros.h" -#include "base/strings/string_piece.h" +#include "crypto/sha2.h" #include "net/cert/ct_known_logs_static.h" + +#if !defined(OS_NACL) #include "net/cert/ct_log_verifier.h" +#endif namespace net { namespace ct { -std::vector<scoped_refptr<CTLogVerifier>> CreateLogVerifiersForKnownLogs() { - std::vector<scoped_refptr<CTLogVerifier>> verifiers; +namespace { + +int log_ids_compare(const char* log_id, const char* lookup_id) { + return strncmp(log_id, lookup_id, crypto::kSHA256Length) < 0; +} + +} // namespace + +#if !defined(OS_NACL) +std::vector<scoped_refptr<const CTLogVerifier>> +CreateLogVerifiersForKnownLogs() { + std::vector<scoped_refptr<const CTLogVerifier>> verifiers; for (size_t i = 0; i < arraysize(kCTLogList); ++i) { const CTLogInfo& log(kCTLogList[i]); base::StringPiece key(log.log_key, log.log_key_length); verifiers.push_back(CTLogVerifier::Create(key, log.log_name, log.log_url)); + // Make sure no null logs enter verifiers. Parsing of all known logs should + // succeed. + CHECK(verifiers.back().get()); } return verifiers; } +#endif + +bool IsLogOperatedByGoogle(base::StringPiece log_id) { + // No callers should provide a log_id that's not of the expected length + // (log IDs are SHA-256 hashes of the key and are always 32 bytes). + // Without this DCHECK (i.e. in production) this function would always + // return false. + DCHECK_EQ(log_id.size(), arraysize(kGoogleLogIDs[0]) - 1); + + auto p = std::lower_bound(kGoogleLogIDs, kGoogleLogIDs + kNumGoogleLogs, + log_id.data(), &log_ids_compare); + if ((p == kGoogleLogIDs + kNumGoogleLogs) || + log_id != base::StringPiece(*p, crypto::kSHA256Length)) { + return false; + } + + return true; +} } // namespace ct diff --git a/chromium/net/cert/ct_known_logs.h b/chromium/net/cert/ct_known_logs.h index e6bbfc15b85..48904c2cc54 100644 --- a/chromium/net/cert/ct_known_logs.h +++ b/chromium/net/cert/ct_known_logs.h @@ -8,6 +8,8 @@ #include <vector> #include "base/memory/ref_counted.h" +#include "base/strings/string_piece.h" +#include "build/build_config.h" #include "net/base/net_export.h" namespace net { @@ -16,10 +18,14 @@ class CTLogVerifier; namespace ct { +#if !defined(OS_NACL) // CreateLogVerifiersForKnownLogs returns a vector of CT logs for all the known // and trusted logs. -NET_EXPORT std::vector<scoped_refptr<CTLogVerifier>> +NET_EXPORT std::vector<scoped_refptr<const CTLogVerifier>> CreateLogVerifiersForKnownLogs(); +#endif + +NET_EXPORT bool IsLogOperatedByGoogle(base::StringPiece log_id); } // namespace ct diff --git a/chromium/net/cert/ct_known_logs_static.h b/chromium/net/cert/ct_known_logs_static.h index d67b9fd72e5..a1e30f1fc6d 100644 --- a/chromium/net/cert/ct_known_logs_static.h +++ b/chromium/net/cert/ct_known_logs_static.h @@ -6,6 +6,8 @@ #ifndef NET_CERT_CT_KNOWN_LOGS_STATIC_H_ #define NET_CERT_CT_KNOWN_LOGS_STATIC_H_ +#include <stddef.h> + struct CTLogInfo { const char* const log_key; const size_t log_key_length; @@ -101,4 +103,15 @@ const CTLogInfo kCTLogList[] = { const size_t kNumKnownCTLogs = 8; +// The list is sorted. +const char kGoogleLogIDs[][33] = { + "\x68\xf6\x98\xf8\x1f\x64\x82\xbe\x3a\x8c\xee\xb9\x28\x1d\x4c\xfc\x71" + "\x51\x5d\x67\x93\xd4\x44\xd1\x0a\x67\xac\xbb\x4f\x4f\xfb\xc4", + "\xa4\xb9\x09\x90\xb4\x18\x58\x14\x87\xbb\x13\xa2\xcc\x67\x70\x0a\x3c" + "\x35\x98\x04\xf9\x1b\xdf\xb8\xe3\x77\xcd\x0e\xc8\x0d\xdc\x10", + "\xee\x4b\xbd\xb7\x75\xce\x60\xba\xe1\x42\x69\x1f\xab\xe1\x9e\x66\xa3" + "\x0f\x7e\x5f\xb0\x72\xd8\x83\x00\xc4\x7b\x89\x7a\xa8\xfd\xcb"}; + +const size_t kNumGoogleLogs = 3; + #endif // NET_CERT_CT_KNOWN_LOGS_STATIC_H_ diff --git a/chromium/net/cert/ct_log_response_parser.cc b/chromium/net/cert/ct_log_response_parser.cc index 0069fc70848..628eef286be 100644 --- a/chromium/net/cert/ct_log_response_parser.cc +++ b/chromium/net/cert/ct_log_response_parser.cc @@ -7,6 +7,7 @@ #include "base/base64.h" #include "base/json/json_value_converter.h" #include "base/logging.h" +#include "base/memory/scoped_vector.h" #include "base/strings/string_piece.h" #include "base/time/time.h" #include "base/values.h" @@ -101,6 +102,33 @@ bool IsJsonSTHStructurallyValid(const JsonSignedTreeHead& sth) { return true; } +// Structure for making JSON decoding easier. The string fields +// are base64-encoded so will require further decoding. +struct JsonConsistencyProof { + ScopedVector<std::string> proof_nodes; + + static void RegisterJSONConverter( + base::JSONValueConverter<JsonConsistencyProof>* converter); +}; + +bool ConvertIndividualProofNode(const base::Value* value, std::string* result) { + std::string b64_encoded_node; + if (!value->GetAsString(&b64_encoded_node)) + return false; + + if (!ConvertSHA256RootHash(b64_encoded_node, result)) + return false; + + return true; +} + +void JsonConsistencyProof::RegisterJSONConverter( + base::JSONValueConverter<JsonConsistencyProof>* converter) { + converter->RegisterRepeatedCustomValue<std::string>( + "consistency", &JsonConsistencyProof::proof_nodes, + &ConvertIndividualProofNode); +} + } // namespace bool FillSignedTreeHead(const base::Value& json_signed_tree_head, @@ -127,6 +155,30 @@ bool FillSignedTreeHead(const base::Value& json_signed_tree_head, return true; } +bool FillConsistencyProof(const base::Value& json_consistency_proof, + std::vector<std::string>* consistency_proof) { + JsonConsistencyProof parsed_proof; + base::JSONValueConverter<JsonConsistencyProof> converter; + if (!converter.Convert(json_consistency_proof, &parsed_proof)) { + DVLOG(1) << "Invalid consistency proof."; + return false; + } + + const base::DictionaryValue* dict_value = NULL; + if (!json_consistency_proof.GetAsDictionary(&dict_value) || + !dict_value->HasKey("consistency")) { + DVLOG(1) << "Missing consistency field."; + return false; + } + + consistency_proof->reserve(parsed_proof.proof_nodes.size()); + for (std::string* proof_node : parsed_proof.proof_nodes) { + consistency_proof->push_back(*proof_node); + } + + return true; +} + } // namespace ct } // namespace net diff --git a/chromium/net/cert/ct_log_response_parser.h b/chromium/net/cert/ct_log_response_parser.h index b7a012bde05..403f8bfb050 100644 --- a/chromium/net/cert/ct_log_response_parser.h +++ b/chromium/net/cert/ct_log_response_parser.h @@ -5,6 +5,9 @@ #ifndef NET_CERT_CT_LOG_RESPONSE_PARSER_H_ #define NET_CERT_CT_LOG_RESPONSE_PARSER_H_ +#include <string> +#include <vector> + #include "base/strings/string_piece.h" #include "net/base/net_export.h" @@ -24,6 +27,10 @@ struct SignedTreeHead; NET_EXPORT bool FillSignedTreeHead(const base::Value& json_signed_tree_head, SignedTreeHead* signed_tree_head); +NET_EXPORT bool FillConsistencyProof( + const base::Value& json_signed_tree_head, + std::vector<std::string>* consistency_proof); + } // namespace ct } // namespace net diff --git a/chromium/net/cert/ct_log_response_parser_unittest.cc b/chromium/net/cert/ct_log_response_parser_unittest.cc index 9f02699d744..fad759019ac 100644 --- a/chromium/net/cert/ct_log_response_parser_unittest.cc +++ b/chromium/net/cert/ct_log_response_parser_unittest.cc @@ -23,7 +23,7 @@ namespace ct { namespace { scoped_ptr<base::Value> ParseJson(const std::string& json) { base::JSONReader json_reader; - return json_reader.Read(json).Pass(); + return json_reader.Read(json); } } @@ -33,7 +33,7 @@ TEST(CTLogResponseParserTest, ParsesValidJsonSTH) { EXPECT_TRUE(FillSignedTreeHead(*sample_sth_json.get(), &tree_head)); SignedTreeHead sample_sth; - GetSampleSignedTreeHead(&sample_sth); + ASSERT_TRUE(GetSampleSignedTreeHead(&sample_sth)); ASSERT_EQ(SignedTreeHead::V1, tree_head.version); ASSERT_EQ(sample_sth.timestamp, tree_head.timestamp); @@ -95,6 +95,53 @@ TEST(CTLogResponseParserTest, FailsToParseIncorrectLengthRootHash) { ASSERT_FALSE(FillSignedTreeHead(*too_short_hash_json.get(), &tree_head)); } +TEST(CTLogResponseParserTest, ParsesConsistencyProofSuccessfully) { + std::string first(32, 'a'); + std::string second(32, 'b'); + std::string third(32, 'c'); + + std::vector<std::string> raw_nodes; + raw_nodes.push_back(first); + raw_nodes.push_back(second); + raw_nodes.push_back(third); + scoped_ptr<base::Value> sample_consistency_proof = + ParseJson(CreateConsistencyProofJsonString(raw_nodes)); + + std::vector<std::string> output; + + ASSERT_TRUE(FillConsistencyProof(*sample_consistency_proof.get(), &output)); + + EXPECT_EQ(output[0], first); + EXPECT_EQ(output[1], second); + EXPECT_EQ(output[2], third); +} + +TEST(CTLogResponseParserTest, FailsOnInvalidProofJson) { + std::vector<std::string> output; + + scoped_ptr<base::Value> badly_encoded = + ParseJson(std::string("{\"consistency\": [\"notbase64\"]}")); + EXPECT_FALSE(FillConsistencyProof(*badly_encoded.get(), &output)); + + scoped_ptr<base::Value> not_a_string = + ParseJson(std::string("{\"consistency\": [42, 16]}")); + EXPECT_FALSE(FillConsistencyProof(*badly_encoded.get(), &output)); + + scoped_ptr<base::Value> missing_consistency = ParseJson(std::string("{}")); + EXPECT_FALSE(FillConsistencyProof(*missing_consistency.get(), &output)); + + scoped_ptr<base::Value> not_a_dict = ParseJson(std::string("[]")); + EXPECT_FALSE(FillConsistencyProof(*not_a_dict.get(), &output)); +} + +TEST(CTLogResponseParserTest, ParsesProofJsonWithExtraFields) { + std::vector<std::string> output; + + scoped_ptr<base::Value> badly_encoded = + ParseJson(std::string("{\"consistency\": [], \"somethingelse\": 3}")); + EXPECT_TRUE(FillConsistencyProof(*badly_encoded.get(), &output)); +} + } // namespace ct } // namespace net diff --git a/chromium/net/cert/ct_log_verifier.cc b/chromium/net/cert/ct_log_verifier.cc index 7dbde12c4b2..0f70678add0 100644 --- a/chromium/net/cert/ct_log_verifier.cc +++ b/chromium/net/cert/ct_log_verifier.cc @@ -4,14 +4,32 @@ #include "net/cert/ct_log_verifier.h" +#include <string.h> + #include "base/logging.h" +#include "net/cert/ct_log_verifier_util.h" #include "net/cert/ct_serialization.h" +#include "net/cert/merkle_consistency_proof.h" #include "net/cert/signed_tree_head.h" namespace net { +namespace { + +// The SHA-256 hash of the empty string. +const unsigned char kSHA256EmptyStringHash[ct::kSthRootHashLength] = { + 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, + 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, + 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; + +bool IsPowerOfTwo(uint64_t n) { + return n != 0 && (n & (n - 1)) == 0; +} + +} // namespace + // static -scoped_refptr<CTLogVerifier> CTLogVerifier::Create( +scoped_refptr<const CTLogVerifier> CTLogVerifier::Create( const base::StringPiece& public_key, const base::StringPiece& description, const base::StringPiece& url) { @@ -35,7 +53,7 @@ CTLogVerifier::CTLogVerifier(const base::StringPiece& description, } bool CTLogVerifier::Verify(const ct::LogEntry& entry, - const ct::SignedCertificateTimestamp& sct) { + const ct::SignedCertificateTimestamp& sct) const { if (sct.log_id != key_id()) { DVLOG(1) << "SCT is not signed by this log."; return false; @@ -60,7 +78,7 @@ bool CTLogVerifier::Verify(const ct::LogEntry& entry, } bool CTLogVerifier::VerifySignedTreeHead( - const ct::SignedTreeHead& signed_tree_head) { + const ct::SignedTreeHead& signed_tree_head) const { if (!SignatureParametersMatch(signed_tree_head.signature)) return false; @@ -68,13 +86,18 @@ bool CTLogVerifier::VerifySignedTreeHead( ct::EncodeTreeHeadSignature(signed_tree_head, &serialized_data); if (VerifySignature(serialized_data, signed_tree_head.signature.signature_data)) { + if (signed_tree_head.tree_size == 0) { + // Root hash must equate SHA256 hash of the empty string. + return (memcmp(signed_tree_head.sha256_root_hash, kSHA256EmptyStringHash, + ct::kSthRootHashLength) == 0); + } return true; } return false; } bool CTLogVerifier::SignatureParametersMatch( - const ct::DigitallySigned& signature) { + const ct::DigitallySigned& signature) const { if (!signature.SignatureParametersMatch(hash_algorithm_, signature_algorithm_)) { DVLOG(1) << "Mismatched hash or signature algorithm. Hash: " @@ -87,4 +110,114 @@ bool CTLogVerifier::SignatureParametersMatch( return true; } +bool CTLogVerifier::VerifyConsistencyProof( + const ct::MerkleConsistencyProof& proof, + const std::string& old_tree_hash, + const std::string& new_tree_hash) const { + // Proof does not originate from this log. + if (key_id_ != proof.log_id) + return false; + + // Cannot prove consistency from a tree of a certain size to a tree smaller + // than that - only the other way around. + if (proof.first_tree_size > proof.second_tree_size) + return false; + + // If the proof is between trees of the same size, then the 'proof' + // is really just a statement that the tree hasn't changed. If this + // is the case, there should be no proof nodes, and both the old + // and new hash should be equivalent. + if (proof.first_tree_size == proof.second_tree_size) + return proof.nodes.empty() && old_tree_hash == new_tree_hash; + + // It is possible to call this method to prove consistency between the + // initial state of a log (i.e. an empty tree) and a later root. In that + // case, the only valid proof is an empty proof. + if (proof.first_tree_size == 0) + return proof.nodes.empty(); + + // Implement the algorithm described in + // https://tools.ietf.org/html/draft-ietf-trans-rfc6962-bis-11#section-9.4.2 + // + // It maintains a pair of hashes |fr| and |sr|, initialized to the same + // value. Each node in |proof| will be hashed to the left of both |fr| and + // |sr| or to the right of only |sr|. The proof is then valid if |fr| is + // |old_tree_hash| and |sr| is |new_tree_hash|, proving that tree nodes which + // make up |old_tree_hash| are a prefix of |new_tree_hash|. + + // At this point, the algorithm's preconditions must be satisfied. + DCHECK_LT(0u, proof.first_tree_size); + DCHECK_LT(proof.first_tree_size, proof.second_tree_size); + + // 1. If "first" is an exact power of 2, then prepend "first_hash" to the + // "consistency_path" array. + base::StringPiece first_proof_node = old_tree_hash; + std::vector<std::string>::const_iterator iter = proof.nodes.begin(); + if (!IsPowerOfTwo(proof.first_tree_size)) { + if (iter == proof.nodes.end()) + return false; + first_proof_node = *iter; + ++iter; + } + // iter now points to the second node in the modified proof.nodes. + + // 2. Set "fn" to "first - 1" and "sn" to "second - 1". + uint64_t fn = proof.first_tree_size - 1; + uint64_t sn = proof.second_tree_size - 1; + + // 3. If "LSB(fn)" is set, then right-shift both "fn" and "sn" equally until + // "LSB(fn)" is not set. + while (fn & 1) { + fn >>= 1; + sn >>= 1; + } + + // 4. Set both "fr" and "sr" to the first value in the "consistency_path" + // array. + std::string fr = first_proof_node.as_string(); + std::string sr = first_proof_node.as_string(); + + // 5. For each subsequent value "c" in the "consistency_path" array: + for (; iter != proof.nodes.end(); ++iter) { + // The proof should end exactly when |sn| becomes zero. This check is + // missing from the draft specification. It and the additional check below + // ensure the proof is consistent with the tree sizes but is not necessary + // to ensure |old_tree_hash| is a prefix of |new_tree_hash|. + if (sn == 0) + return false; + // If "LSB(fn)" is set, or if "fn" is equal to "sn", then: + if ((fn & 1) || fn == sn) { + // 1. Set "fr" to "HASH(0x01 || c || fr)" + // Set "sr" to "HASH(0x01 || c || sr)" + fr = ct::internal::HashNodes(*iter, fr); + sr = ct::internal::HashNodes(*iter, sr); + + // 2. If "LSB(fn)" is not set, then right-shift both "fn" and "sn" equally + // until either "LSB(fn)" is set or "fn" is "0". + while (!(fn & 1) && fn != 0) { + fn >>= 1; + sn >>= 1; + } + } else { // Otherwise: + // Set "sr" to "HASH(0x01 || sr || c)" + sr = ct::internal::HashNodes(sr, *iter); + } + + // Finally, right-shift both "fn" and "sn" one time. + fn >>= 1; + sn >>= 1; + } + + // 6. After completing iterating through the "consistency_path" array as + // described above, verify that the "fr" calculated is equal to the + // "first_hash" supplied and that the "sr" calculated is equal to the + // "second_hash" supplied. + // + // The proof should also end exactly when |sn| becomes zero. This check is + // missing from the draft specification. It and the additional check above + // ensure the proof is consistent with the tree sizes but is not necessary to + // ensure |old_tree_hash| is a prefix of |new_tree_hash|. + return fr == old_tree_hash && sr == new_tree_hash && sn == 0; +} + } // namespace net diff --git a/chromium/net/cert/ct_log_verifier.h b/chromium/net/cert/ct_log_verifier.h index 0a9b3eff03d..9f50c1423a6 100644 --- a/chromium/net/cert/ct_log_verifier.h +++ b/chromium/net/cert/ct_log_verifier.h @@ -25,11 +25,18 @@ typedef struct SECKEYPublicKeyStr SECKEYPublicKey; namespace net { namespace ct { + struct SignedTreeHead; +struct MerkleConsistencyProof; + } // namespace ct -// Class for verifying Signed Certificate Timestamps (SCTs) provided by a -// specific log (whose identity is provided during construction). +// Class for verifying signatures of a single Certificate Transparency +// log, whose identity is provided during construction. +// Currently can verify Signed Certificate Timestamp (SCT) and Signed +// Tree Head (STH) signatures. +// Immutable: Does not hold any state beyond the log information it was +// initialized with. class NET_EXPORT CTLogVerifier : public base::RefCountedThreadSafe<CTLogVerifier> { public: @@ -37,7 +44,7 @@ class NET_EXPORT CTLogVerifier // using |public_key|, which is a DER-encoded SubjectPublicKeyInfo. // If |public_key| refers to an unsupported public key, returns NULL. // |description| is a textual description of the log. - static scoped_refptr<CTLogVerifier> Create( + static scoped_refptr<const CTLogVerifier> Create( const base::StringPiece& public_key, const base::StringPiece& description, const base::StringPiece& url); @@ -49,12 +56,21 @@ class NET_EXPORT CTLogVerifier // Returns the log's URL const GURL& url() const { return url_; } - // Verifies that |sct| contains a valid signature for |entry|. + // Verifies that |sct| is valid for |entry| and was signed by this log. bool Verify(const ct::LogEntry& entry, - const ct::SignedCertificateTimestamp& sct); + const ct::SignedCertificateTimestamp& sct) const; + + // Verifies that |signed_tree_head| is a valid Signed Tree Head (RFC 6962, + // Section 3.5) for this log. + bool VerifySignedTreeHead(const ct::SignedTreeHead& signed_tree_head) const; - // Returns true if the signature in |signed_tree_head| verifies. - bool VerifySignedTreeHead(const ct::SignedTreeHead& signed_tree_head); + // Verifies that |proof| is a valid consistency proof (RFC 6962, Section + // 2.1.2) for this log, and which proves that |old_tree_hash| has + // been fully incorporated into the Merkle tree represented by + // |new_tree_hash|. + bool VerifyConsistencyProof(const ct::MerkleConsistencyProof& proof, + const std::string& old_tree_hash, + const std::string& new_tree_hash) const; private: FRIEND_TEST_ALL_PREFIXES(CTLogVerifierTest, VerifySignature); @@ -70,11 +86,11 @@ class NET_EXPORT CTLogVerifier // that |signature| contains the raw signature data (eg: without any // DigitallySigned struct encoding). bool VerifySignature(const base::StringPiece& data_to_sign, - const base::StringPiece& signature); + const base::StringPiece& signature) const; // Returns true if the signature and hash algorithms in |signature| // match those of the log - bool SignatureParametersMatch(const ct::DigitallySigned& signature); + bool SignatureParametersMatch(const ct::DigitallySigned& signature) const; std::string key_id_; std::string description_; diff --git a/chromium/net/cert/ct_log_verifier_nss.cc b/chromium/net/cert/ct_log_verifier_nss.cc index 75a87d610f6..fec7dc832da 100644 --- a/chromium/net/cert/ct_log_verifier_nss.cc +++ b/chromium/net/cert/ct_log_verifier_nss.cc @@ -117,7 +117,7 @@ bool CTLogVerifier::Init(const base::StringPiece& public_key) { } bool CTLogVerifier::VerifySignature(const base::StringPiece& data_to_sign, - const base::StringPiece& signature) { + const base::StringPiece& signature) const { SECItem sig_data; sig_data.data = reinterpret_cast<unsigned char*>(const_cast<char*>( signature.data())); diff --git a/chromium/net/cert/ct_log_verifier_openssl.cc b/chromium/net/cert/ct_log_verifier_openssl.cc index af875a58738..5fe41fd7769 100644 --- a/chromium/net/cert/ct_log_verifier_openssl.cc +++ b/chromium/net/cert/ct_log_verifier_openssl.cc @@ -86,7 +86,7 @@ bool CTLogVerifier::Init(const base::StringPiece& public_key) { } bool CTLogVerifier::VerifySignature(const base::StringPiece& data_to_sign, - const base::StringPiece& signature) { + const base::StringPiece& signature) const { crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); const EVP_MD* hash_alg = GetEvpAlg(hash_algorithm_); diff --git a/chromium/net/cert/ct_log_verifier_unittest.cc b/chromium/net/cert/ct_log_verifier_unittest.cc index 4f0fdcccc7e..3ee926353af 100644 --- a/chromium/net/cert/ct_log_verifier_unittest.cc +++ b/chromium/net/cert/ct_log_verifier_unittest.cc @@ -4,9 +4,16 @@ #include "net/cert/ct_log_verifier.h" +#include <stdint.h> + #include <string> +#include "base/strings/string_number_conversions.h" #include "base/time/time.h" +#include "crypto/secure_hash.h" +#include "net/base/hash_value.h" +#include "net/cert/ct_log_verifier_util.h" +#include "net/cert/merkle_consistency_proof.h" #include "net/cert/signed_certificate_timestamp.h" #include "net/cert/signed_tree_head.h" #include "net/test/ct_test_util.h" @@ -14,20 +21,222 @@ namespace net { +namespace { + +// Calculate the power of two nearest to, but less than, |n|. +// |n| must be at least 2. +uint64_t CalculateNearestPowerOfTwo(uint64_t n) { + DCHECK_GT(n, 1u); + + uint64_t ret = UINT64_C(1) << 63; + while (ret >= n) + ret >>= 1; + + return ret; +} + +// The following structures, TestVector and ProofTestVector are used for +// definining test proofs later on. + +// A single hash node. +struct TestVector { + const char* const str; + size_t length_bytes; +}; + +// A single consistency proof. Contains the old and new tree sizes +// (snapshot1 and snapshot2), the length of the proof (proof_length) and +// at most 3 proof nodes (all test proofs will be for a tree of size 8). +struct ProofTestVector { + uint64_t snapshot1; + uint64_t snapshot2; + size_t proof_length; + TestVector proof[3]; +}; + +// All test data replicated from +// https://github.com/google/certificate-transparency/blob/c41b090ecc14ddd6b3531dc7e5ce36b21e253fdd/cpp/merkletree/merkle_tree_test.cc +// A hash of the empty string. +const TestVector kSHA256EmptyTreeHash = { + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", 32}; + +// Node hashes for a sample tree of size 8 (each element in this array is +// a node hash, not leaf data; order represents order of the nodes in the tree). +const TestVector kSHA256Roots[8] = { + {"6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", 32}, + {"fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125", 32}, + {"aeb6bcfe274b70a14fb067a5e5578264db0fa9b51af5e0ba159158f329e06e77", 32}, + {"d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7", 32}, + {"4e3bbb1f7b478dcfe71fb631631519a3bca12c9aefca1612bfce4c13a86264d4", 32}, + {"76e67dadbcdf1e10e1b74ddc608abd2f98dfb16fbce75277b5232a127f2087ef", 32}, + {"ddb89be403809e325750d3d263cd78929c2942b7942a34b77e122c9594a74c8c", 32}, + {"5dc9da79a70659a9ad559cb701ded9a2ab9d823aad2f4960cfe370eff4604328", 32}}; + +// A collection of consistency proofs between various sub-trees of the tree +// defined by |kSHA256Roots|. +const ProofTestVector kSHA256Proofs[4] = { + // Empty consistency proof between trees of the same size (1). + {1, 1, 0, {{"", 0}, {"", 0}, {"", 0}}}, + // Consistency proof between tree of size 1 and tree of size 8, with 3 + // nodes in the proof. + {1, + 8, + 3, + {{"96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7", 32}, + {"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 32}, + {"6b47aaf29ee3c2af9af889bc1fb9254dabd31177f16232dd6aab035ca39bf6e4", + 32}}}, + // Consistency proof between tree of size 6 and tree of size 8, with 3 + // nodes in the proof. + {6, + 8, + 3, + {{"0ebc5d3437fbe2db158b9f126a1d118e308181031d0a949f8dededebc558ef6a", 32}, + {"ca854ea128ed050b41b35ffc1b87b8eb2bde461e9e3b5596ece6b9d5975a0ae0", 32}, + {"d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7", + 32}}}, + // Consistency proof between tree of size 2 and tree of size 5, with 2 + // nodes in the proof. + {2, + 5, + 2, + {{"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 32}, + {"bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", 32}, + {"", 0}}}}; + +// Decodes a hexadecimal string into the binary data it represents. +std::string HexToBytes(const char* hex_data, size_t hex_data_length) { + std::vector<uint8_t> output; + std::string result; + std::string hex_data_input(hex_data, hex_data_length); + if (base::HexStringToBytes(hex_data, &output)) + result.assign(reinterpret_cast<const char*>(&output[0]), output.size()); + return result; +} + +std::string GetEmptyTreeHash() { + return HexToBytes(kSHA256EmptyTreeHash.str, + kSHA256EmptyTreeHash.length_bytes); +} + +// Creates a ct::MerkleConsistencyProof and returns the result of +// calling log->VerifyConsistencyProof with that proof and snapshots. +bool VerifyConsistencyProof(scoped_refptr<const CTLogVerifier> log, + uint64_t old_tree_size, + const std::string& old_tree_root, + uint64_t new_tree_size, + const std::string& new_tree_root, + const std::vector<std::string>& proof) { + return log->VerifyConsistencyProof( + ct::MerkleConsistencyProof(log->key_id(), proof, old_tree_size, + new_tree_size), + old_tree_root, new_tree_root); +} + class CTLogVerifierTest : public ::testing::Test { public: CTLogVerifierTest() {} void SetUp() override { log_ = CTLogVerifier::Create(ct::GetTestPublicKey(), "testlog", - "https://ct.example.com").Pass(); + "https://ct.example.com"); ASSERT_TRUE(log_); ASSERT_EQ(log_->key_id(), ct::GetTestPublicKeyId()); } + // Given a consistency proof between two snapshots of the tree, asserts that + // it verifies and no other combination of snapshots and proof nodes verifies. + void VerifierConsistencyCheck(int snapshot1, + int snapshot2, + const std::string& root1, + const std::string& root2, + const std::vector<std::string>& proof) { + // Verify the original consistency proof. + EXPECT_TRUE( + VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, root2, proof)) + << " " << snapshot1 << " " << snapshot2; + + if (proof.empty()) { + // For simplicity test only non-trivial proofs that have root1 != root2 + // snapshot1 != 0 and snapshot1 != snapshot2. + return; + } + + // Wrong snapshot index: The proof checking code should not accept + // as a valid proof a proof for a tree size different than the original + // size it was produced for. + // Test that this is not the case for off-by-one changes. + EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1 - 1, root1, snapshot2, + root2, proof)); + EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1 + 1, root1, snapshot2, + root2, proof)); + EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1 ^ 2, root1, snapshot2, + root2, proof)); + + // Test that the proof is not accepted for trees with wrong tree height. + EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2 * 2, + root2, proof)); + EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2 / 2, + root2, proof)); + + // Test that providing the wrong input root fails checking an + // otherwise-valid proof. + const std::string wrong_root("WrongRoot"); + EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, + wrong_root, proof)); + EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, wrong_root, snapshot2, + root2, proof)); + // Test that swapping roots fails checking an otherwise-valid proof (that + // the right root is used for each calculation). + EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root2, snapshot2, + root1, proof)); + + // Variations of wrong proofs, all of which should be rejected. + std::vector<std::string> wrong_proof; + // Empty proof. + EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, + root2, wrong_proof)); + + // Modify a single element in the proof. + for (size_t j = 0; j < proof.size(); ++j) { + wrong_proof = proof; + wrong_proof[j] = GetEmptyTreeHash(); + EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, + root2, wrong_proof)); + } + + // Add garbage at the end of the proof. + wrong_proof = proof; + wrong_proof.push_back(std::string()); + EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, + root2, wrong_proof)); + wrong_proof.pop_back(); + + wrong_proof.push_back(proof.back()); + EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, + root2, wrong_proof)); + wrong_proof.pop_back(); + + // Remove a node from the end. + wrong_proof.pop_back(); + EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, + root2, wrong_proof)); + + // Add garbage in the beginning of the proof. + wrong_proof.clear(); + wrong_proof.push_back(std::string()); + wrong_proof.insert(wrong_proof.end(), proof.begin(), proof.end()); + EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, + root2, wrong_proof)); + + wrong_proof[0] = proof[0]; + EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, + root2, wrong_proof)); + } + protected: - scoped_refptr<CTLogVerifier> log_; + scoped_refptr<const CTLogVerifier> log_; }; TEST_F(CTLogVerifierTest, VerifiesCertSCT) { @@ -77,17 +286,29 @@ TEST_F(CTLogVerifierTest, FailsInvalidLogID) { EXPECT_FALSE(log_->Verify(cert_entry, *cert_sct.get())); } -TEST_F(CTLogVerifierTest, SetsValidSTH) { +TEST_F(CTLogVerifierTest, VerifiesValidSTH) { ct::SignedTreeHead sth; - ct::GetSampleSignedTreeHead(&sth); - ASSERT_TRUE(log_->VerifySignedTreeHead(sth)); + ASSERT_TRUE(ct::GetSampleSignedTreeHead(&sth)); + EXPECT_TRUE(log_->VerifySignedTreeHead(sth)); } -TEST_F(CTLogVerifierTest, DoesNotSetInvalidSTH) { +TEST_F(CTLogVerifierTest, DoesNotVerifyInvalidSTH) { ct::SignedTreeHead sth; - ct::GetSampleSignedTreeHead(&sth); + ASSERT_TRUE(ct::GetSampleSignedTreeHead(&sth)); sth.sha256_root_hash[0] = '\x0'; - ASSERT_FALSE(log_->VerifySignedTreeHead(sth)); + EXPECT_FALSE(log_->VerifySignedTreeHead(sth)); +} + +TEST_F(CTLogVerifierTest, VerifiesValidEmptySTH) { + ct::SignedTreeHead sth; + ASSERT_TRUE(ct::GetSampleEmptySignedTreeHead(&sth)); + EXPECT_TRUE(log_->VerifySignedTreeHead(sth)); +} + +TEST_F(CTLogVerifierTest, DoesNotVerifyInvalidEmptySTH) { + ct::SignedTreeHead sth; + ASSERT_TRUE(ct::GetBadEmptySignedTreeHead(&sth)); + EXPECT_FALSE(log_->VerifySignedTreeHead(sth)); } // Test that excess data after the public key is rejected. @@ -95,9 +316,197 @@ TEST_F(CTLogVerifierTest, ExcessDataInPublicKey) { std::string key = ct::GetTestPublicKey(); key += "extra"; - scoped_refptr<CTLogVerifier> log = + scoped_refptr<const CTLogVerifier> log = CTLogVerifier::Create(key, "testlog", "https://ct.example.com"); EXPECT_FALSE(log); } +TEST_F(CTLogVerifierTest, VerifiesConsistencyProofEdgeCases_EmptyProof) { + std::vector<std::string> empty_proof; + std::string root1(GetEmptyTreeHash()), root2(GetEmptyTreeHash()); + + // Snapshots that are always consistent, because they are either + // from an empty tree to a non-empty one or for trees of the same + // size. + EXPECT_TRUE(VerifyConsistencyProof(log_, 0, root1, 0, root2, empty_proof)); + EXPECT_TRUE(VerifyConsistencyProof(log_, 0, root1, 1, root2, empty_proof)); + EXPECT_TRUE(VerifyConsistencyProof(log_, 1, root1, 1, root2, empty_proof)); + + // Invalid consistency proofs. + // Time travel to the past. + EXPECT_FALSE(VerifyConsistencyProof(log_, 1, root1, 0, root2, empty_proof)); + EXPECT_FALSE(VerifyConsistencyProof(log_, 2, root1, 1, root2, empty_proof)); + // Proof between two trees of different size can never be empty. + EXPECT_FALSE(VerifyConsistencyProof(log_, 1, root1, 2, root2, empty_proof)); +} + +TEST_F(CTLogVerifierTest, VerifiesConsistencyProofEdgeCases_MismatchingRoots) { + std::vector<std::string> empty_proof; + std::string root2; + const std::string empty_tree_hash(GetEmptyTreeHash()); + + // Roots don't match. + EXPECT_FALSE( + VerifyConsistencyProof(log_, 0, empty_tree_hash, 0, root2, empty_proof)); + EXPECT_FALSE( + VerifyConsistencyProof(log_, 1, empty_tree_hash, 1, root2, empty_proof)); +} + +TEST_F(CTLogVerifierTest, + VerifiesConsistencyProofEdgeCases_MatchingRootsNonEmptyProof) { + const std::string empty_tree_hash(GetEmptyTreeHash()); + + std::vector<std::string> proof; + proof.push_back(empty_tree_hash); + + // Roots match and the tree size is either the same or the old tree size is 0, + // but the proof is not empty (the verification code should not accept + // proofs with redundant nodes in this case). + proof.push_back(empty_tree_hash); + EXPECT_FALSE(VerifyConsistencyProof(log_, 0, empty_tree_hash, 0, + empty_tree_hash, proof)); + EXPECT_FALSE(VerifyConsistencyProof(log_, 0, empty_tree_hash, 1, + empty_tree_hash, proof)); + EXPECT_FALSE(VerifyConsistencyProof(log_, 1, empty_tree_hash, 1, + empty_tree_hash, proof)); +} + +TEST_F(CTLogVerifierTest, VerifiesValidConsistencyProofs) { + std::vector<std::string> proof; + std::string root1, root2; + + // Known good proofs. + for (size_t i = 0; i < arraysize(kSHA256Proofs); ++i) { + proof.clear(); + for (size_t j = 0; j < kSHA256Proofs[i].proof_length; ++j) { + const TestVector& v = kSHA256Proofs[i].proof[j]; + proof.push_back(HexToBytes(v.str, v.length_bytes)); + } + const uint64_t snapshot1 = kSHA256Proofs[i].snapshot1; + const uint64_t snapshot2 = kSHA256Proofs[i].snapshot2; + const TestVector& old_root = kSHA256Roots[snapshot1 - 1]; + const TestVector& new_root = kSHA256Roots[snapshot2 - 1]; + VerifierConsistencyCheck( + snapshot1, snapshot2, HexToBytes(old_root.str, old_root.length_bytes), + HexToBytes(new_root.str, new_root.length_bytes), proof); + } +} + +const char kLeafPrefix[] = {'\x00'}; + +// Reference implementation of RFC6962. +// This allows generation of arbitrary-sized Merkle trees and consistency +// proofs between them for testing the consistency proof validation +// code. +class TreeHasher { + public: + static std::string HashEmpty() { + return HexToBytes(kSHA256EmptyTreeHash.str, + kSHA256EmptyTreeHash.length_bytes); + } + + static std::string HashLeaf(const std::string& leaf) { + SHA256HashValue sha256; + memset(sha256.data, 0, sizeof(sha256.data)); + + scoped_ptr<crypto::SecureHash> hash( + crypto::SecureHash::Create(crypto::SecureHash::SHA256)); + hash->Update(kLeafPrefix, 1); + hash->Update(leaf.data(), leaf.size()); + hash->Finish(sha256.data, sizeof(sha256.data)); + + return std::string(reinterpret_cast<const char*>(sha256.data), + sizeof(sha256.data)); + } +}; + +// Reference implementation of Merkle hash, for cross-checking. +// Recursively calculates the hash of the root given the leaf data +// specified in |inputs|. +std::string ReferenceMerkleTreeHash(std::string* inputs, uint64_t input_size) { + if (!input_size) + return TreeHasher::HashEmpty(); + if (input_size == 1) + return TreeHasher::HashLeaf(inputs[0]); + + const uint64_t split = CalculateNearestPowerOfTwo(input_size); + + return ct::internal::HashNodes( + ReferenceMerkleTreeHash(&inputs[0], split), + ReferenceMerkleTreeHash(&inputs[split], input_size - split)); +} + +// Reference implementation of snapshot consistency. Returns a +// consistency proof between two snapshots of the tree designated +// by |inputs|. +// Call with have_root1 = true. +std::vector<std::string> ReferenceSnapshotConsistency(std::string* inputs, + uint64_t snapshot2, + uint64_t snapshot1, + bool have_root1) { + std::vector<std::string> proof; + if (snapshot1 == 0 || snapshot1 > snapshot2) + return proof; + if (snapshot1 == snapshot2) { + // Consistency proof for two equal subtrees is empty. + if (!have_root1) { + // Record the hash of this subtree unless it's the root for which + // the proof was originally requested. (This happens when the snapshot1 + // tree is balanced.) + proof.push_back(ReferenceMerkleTreeHash(inputs, snapshot1)); + } + return proof; + } + + // 0 < snapshot1 < snapshot2 + const uint64_t split = CalculateNearestPowerOfTwo(snapshot2); + + std::vector<std::string> subproof; + if (snapshot1 <= split) { + // Root of snapshot1 is in the left subtree of snapshot2. + // Prove that the left subtrees are consistent. + subproof = + ReferenceSnapshotConsistency(inputs, split, snapshot1, have_root1); + proof.insert(proof.end(), subproof.begin(), subproof.end()); + // Record the hash of the right subtree (only present in snapshot2). + proof.push_back(ReferenceMerkleTreeHash(&inputs[split], snapshot2 - split)); + } else { + // Snapshot1 root is at the same level as snapshot2 root. + // Prove that the right subtrees are consistent. The right subtree + // doesn't contain the root of snapshot1, so set have_root1 = false. + subproof = ReferenceSnapshotConsistency(&inputs[split], snapshot2 - split, + snapshot1 - split, false); + proof.insert(proof.end(), subproof.begin(), subproof.end()); + // Record the hash of the left subtree (equal in both trees). + proof.push_back(ReferenceMerkleTreeHash(&inputs[0], split)); + } + return proof; +} + +// "brute-force" test generating a tree of 256 entries, generating +// a consistency proof for each snapshot of each sub-tree up to that +// size and making sure it verifies. +TEST_F(CTLogVerifierTest, + VerifiesValidConsistencyProofsFromReferenceGenerator) { + std::vector<std::string> data; + for (int i = 0; i < 256; ++i) + data.push_back(std::string(1, i)); + + std::vector<std::string> proof; + std::string root1, root2; + // More tests with reference proof generator. + for (size_t tree_size = 1; tree_size <= data.size() / 2; ++tree_size) { + root2 = ReferenceMerkleTreeHash(data.data(), tree_size); + // Repeat for each snapshot in range. + for (size_t snapshot = 1; snapshot <= tree_size; ++snapshot) { + proof = + ReferenceSnapshotConsistency(data.data(), tree_size, snapshot, true); + root1 = ReferenceMerkleTreeHash(data.data(), snapshot); + VerifierConsistencyCheck(snapshot, tree_size, root1, root2, proof); + } + } +} + +} // namespace + } // namespace net diff --git a/chromium/net/cert/ct_log_verifier_util.cc b/chromium/net/cert/ct_log_verifier_util.cc new file mode 100644 index 00000000000..9e8097f5133 --- /dev/null +++ b/chromium/net/cert/ct_log_verifier_util.cc @@ -0,0 +1,36 @@ +// Copyright 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. + +#include "net/cert/ct_log_verifier_util.h" + +#include "base/memory/scoped_ptr.h" +#include "base/strings/string_util.h" +#include "crypto/secure_hash.h" +#include "crypto/sha2.h" + +namespace net { + +namespace ct { + +namespace internal { + +std::string HashNodes(const std::string& lh, const std::string& rh) { + scoped_ptr<crypto::SecureHash> hash( + crypto::SecureHash::Create(crypto::SecureHash::SHA256)); + + hash->Update("\01", 1); + hash->Update(lh.data(), lh.size()); + hash->Update(rh.data(), rh.size()); + + std::string result; + hash->Finish(base::WriteInto(&result, crypto::kSHA256Length + 1), + crypto::kSHA256Length); + return result; +} + +} // namespace internal + +} // namespace ct + +} // namespace net diff --git a/chromium/net/cert/ct_log_verifier_util.h b/chromium/net/cert/ct_log_verifier_util.h new file mode 100644 index 00000000000..9894afe59ea --- /dev/null +++ b/chromium/net/cert/ct_log_verifier_util.h @@ -0,0 +1,30 @@ +// Copyright 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. + +#ifndef NET_CERT_CT_LOG_VERIFIER_UTIL_H_ +#define NET_CERT_CT_LOG_VERIFIER_UTIL_H_ + +#include <stdint.h> + +#include <string> + +#include "net/base/net_export.h" + +namespace net { + +namespace ct { + +namespace internal { + +// Hash |lh| and |rh| to produce a node hash according to +// http://tools.ietf.org/html/rfc6962#section-2.1 +NET_EXPORT std::string HashNodes(const std::string& lh, const std::string& rh); + +} // namespace internal + +} // namespace ct + +} // namespace net + +#endif diff --git a/chromium/net/cert/ct_objects_extractor_nss.cc b/chromium/net/cert/ct_objects_extractor_nss.cc index b4c1da3dfe6..76a3be51d2e 100644 --- a/chromium/net/cert/ct_objects_extractor_nss.cc +++ b/chromium/net/cert/ct_objects_extractor_nss.cc @@ -10,12 +10,15 @@ #include <secoid.h> #include "base/lazy_instance.h" +#include "base/macros.h" #include "base/sha1.h" #include "crypto/scoped_nss_types.h" #include "crypto/sha2.h" #include "net/cert/asn1_util.h" #include "net/cert/scoped_nss_types.h" #include "net/cert/signed_certificate_timestamp.h" +#include "net/der/input.h" +#include "net/der/parser.h" namespace net { @@ -147,14 +150,13 @@ bool GetCertOctetStringExtension(CERTCertificate* cert, if (rv != SECSuccess) return false; - base::StringPiece raw_data(reinterpret_cast<char*>(extension.data), - extension.len); - base::StringPiece parsed_data; - if (!asn1::GetElement(&raw_data, asn1::kOCTETSTRING, &parsed_data) || - raw_data.size() > 0) { // Decoding failure or raw data left + der::Parser parser(der::Input(extension.data, extension.len)); + der::Input parsed_extension; + if (!parser.ReadTag(der::kOctetString, &parsed_extension) || + parser.HasMore()) { // Decoding failure or raw data left rv = SECFailure; } else { - parsed_data.CopyToString(extension_data); + *extension_data = parsed_extension.AsString(); } SECITEM_FreeItem(&extension, PR_FALSE); diff --git a/chromium/net/cert/ct_objects_extractor_unittest.cc b/chromium/net/cert/ct_objects_extractor_unittest.cc index 7640e5bdb0d..5bb59ba3db0 100644 --- a/chromium/net/cert/ct_objects_extractor_unittest.cc +++ b/chromium/net/cert/ct_objects_extractor_unittest.cc @@ -32,7 +32,7 @@ class CTObjectsExtractorTest : public ::testing::Test { der_test_cert.length()); log_ = CTLogVerifier::Create(ct::GetTestPublicKey(), "testlog", - "https://ct.example.com").Pass(); + "https://ct.example.com"); ASSERT_TRUE(log_); } @@ -52,7 +52,7 @@ class CTObjectsExtractorTest : public ::testing::Test { protected: CertificateList precert_chain_; scoped_refptr<X509Certificate> test_cert_; - scoped_refptr<CTLogVerifier> log_; + scoped_refptr<const CTLogVerifier> log_; }; // Test that an SCT can be extracted and the extracted SCT contains the diff --git a/chromium/net/cert/cert_policy_enforcer.cc b/chromium/net/cert/ct_policy_enforcer.cc index 070f8691ee6..d9c92421bf8 100644 --- a/chromium/net/cert/cert_policy_enforcer.cc +++ b/chromium/net/cert/ct_policy_enforcer.cc @@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/cert/cert_policy_enforcer.h" +#include "net/cert/ct_policy_enforcer.h" #include <algorithm> +#include <utility> #include "base/bind.h" #include "base/build_time.h" @@ -13,9 +14,11 @@ #include "base/metrics/histogram_macros.h" #include "base/numerics/safe_conversions.h" #include "base/strings/string_number_conversions.h" +#include "base/time/time.h" #include "base/values.h" #include "base/version.h" #include "net/cert/ct_ev_whitelist.h" +#include "net/cert/ct_known_logs.h" #include "net/cert/ct_verify_result.h" #include "net/cert/signed_certificate_timestamp.h" #include "net/cert/x509_certificate.h" @@ -43,6 +46,11 @@ bool IsBuildTimely() { #endif } +bool IsGoogleIssuedSCT( + const scoped_refptr<ct::SignedCertificateTimestamp>& sct) { + return ct::IsLogOperatedByGoogle(sct->log_id); +} + // Returns a rounded-down months difference of |start| and |end|, // together with an indication of whether the last month was // a full month, because the range starts specified in the policy @@ -75,12 +83,10 @@ void RoundedDownMonthDifference(const base::Time& start, bool HasRequiredNumberOfSCTs(const X509Certificate& cert, const ct::CTVerifyResult& ct_result) { - // TODO(eranm): Count the number of *independent* SCTs once the information - // about log operators is available, crbug.com/425174 size_t num_valid_scts = ct_result.verified_scts.size(); - size_t num_embedded_scts = + size_t num_embedded_scts = base::checked_cast<size_t>( std::count_if(ct_result.verified_scts.begin(), - ct_result.verified_scts.end(), IsEmbeddedSCT); + ct_result.verified_scts.end(), IsEmbeddedSCT)); size_t num_non_embedded_scts = num_valid_scts - num_embedded_scts; // If at least two valid SCTs were delivered by means other than embedding @@ -117,10 +123,22 @@ bool HasRequiredNumberOfSCTs(const X509Certificate& cert, return num_embedded_scts >= num_required_embedded_scts; } +// Returns true if |verified_scts| contains SCTs from at least one log that is +// operated by Google and at least one log that is not operated by Google. This +// is required for SCTs after July 1st, 2015, as documented at +// http://dev.chromium.org/Home/chromium-security/root-ca-policy/EVCTPlanMay2015edition.pdf +bool HasEnoughDiverseSCTs(const ct::SCTList& verified_scts) { + size_t num_google_issued_scts = base::checked_cast<size_t>(std::count_if( + verified_scts.begin(), verified_scts.end(), IsGoogleIssuedSCT)); + return (num_google_issued_scts > 0) && + (verified_scts.size() != num_google_issued_scts); +} + enum CTComplianceStatus { CT_NOT_COMPLIANT = 0, CT_IN_WHITELIST = 1, CT_ENOUGH_SCTS = 2, + CT_NOT_ENOUGH_DIVERSE_SCTS = 3, CT_COMPLIANCE_MAX, }; @@ -135,6 +153,9 @@ const char* ComplianceStatusToString(CTComplianceStatus status) { case CT_ENOUGH_SCTS: return "ENOUGH_SCTS"; break; + case CT_NOT_ENOUGH_DIVERSE_SCTS: + return "NOT_ENOUGH_DIVERSE_SCTS"; + break; case CT_COMPLIANCE_MAX: break; } @@ -203,7 +224,24 @@ scoped_ptr<base::Value> NetLogComplianceCheckResultCallback( details->whitelist_version.GetString()); } } - return dict.Pass(); + return std::move(dict); +} + +// Returns true if all SCTs in |verified_scts| were issued on, or after, the +// date specified in kDiverseSCTRequirementStartDate +bool AllSCTsPastDistinctSCTRequirementEnforcementDate( + const ct::SCTList& verified_scts) { + // The date when diverse SCTs requirement is effective from. + // 2015-07-01 00:00:00 UTC. + base::Time kDiverseSCTRequirementStartDate = + base::Time::FromInternalValue(13080182400000000); + + for (const auto& it : verified_scts) { + if (it->timestamp < kDiverseSCTRequirementStartDate) + return false; + } + + return true; } bool IsCertificateInWhitelist(const X509Certificate& cert, @@ -241,17 +279,24 @@ void CheckCTEVPolicyCompliance(X509Certificate* cert, return; } - if (HasRequiredNumberOfSCTs(*cert, ct_result)) { - result->status = CT_ENOUGH_SCTS; + if (!HasRequiredNumberOfSCTs(*cert, ct_result)) { + result->status = CT_NOT_COMPLIANT; + return; + } + + if (AllSCTsPastDistinctSCTRequirementEnforcementDate( + ct_result.verified_scts) && + !HasEnoughDiverseSCTs(ct_result.verified_scts)) { + result->status = CT_NOT_ENOUGH_DIVERSE_SCTS; return; } - result->status = CT_NOT_COMPLIANT; + result->status = CT_ENOUGH_SCTS; } } // namespace -bool CertPolicyEnforcer::DoesConformToCTEVPolicy( +bool CTPolicyEnforcer::DoesConformToCTEVPolicy( X509Certificate* cert, const ct::EVCertsWhitelist* ev_whitelist, const ct::CTVerifyResult& ct_result, diff --git a/chromium/net/cert/cert_policy_enforcer.h b/chromium/net/cert/ct_policy_enforcer.h index ea24dbd91f1..8c29da5ecb3 100644 --- a/chromium/net/cert/cert_policy_enforcer.h +++ b/chromium/net/cert/ct_policy_enforcer.h @@ -1,8 +1,8 @@ // Copyright 2014 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. -#ifndef NET_CERT_CERT_POLICY_ENFORCER_H -#define NET_CERT_CERT_POLICY_ENFORCER_H +#ifndef NET_CERT_CT_POLICY_ENFORCER_H +#define NET_CERT_CT_POLICY_ENFORCER_H #include <stddef.h> @@ -22,10 +22,10 @@ class X509Certificate; // Class for checking that a given certificate conforms to security-related // policies. -class NET_EXPORT CertPolicyEnforcer { +class NET_EXPORT CTPolicyEnforcer { public: - CertPolicyEnforcer() {} - virtual ~CertPolicyEnforcer() {} + CTPolicyEnforcer() {} + virtual ~CTPolicyEnforcer() {} // Returns true if the collection of SCTs for the given certificate // conforms with the CT/EV policy. Conformance details are logged to @@ -41,4 +41,4 @@ class NET_EXPORT CertPolicyEnforcer { } // namespace net -#endif // NET_CERT_CERT_POLICY_ENFORCER_H +#endif // NET_CERT_CT_POLICY_ENFORCER_H diff --git a/chromium/net/cert/cert_policy_enforcer_unittest.cc b/chromium/net/cert/ct_policy_enforcer_unittest.cc index bf706dd9b94..43552529333 100644 --- a/chromium/net/cert/cert_policy_enforcer_unittest.cc +++ b/chromium/net/cert/ct_policy_enforcer_unittest.cc @@ -2,12 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/cert/cert_policy_enforcer.h" +#include "net/cert/ct_policy_enforcer.h" #include <string> #include "base/memory/scoped_ptr.h" +#include "base/time/time.h" #include "base/version.h" +#include "crypto/sha2.h" #include "net/base/test_data_directory.h" #include "net/cert/ct_ev_whitelist.h" #include "net/cert/ct_verify_result.h" @@ -44,29 +46,72 @@ class DummyEVCertsWhitelist : public ct::EVCertsWhitelist { bool canned_contains_response_; }; -class CertPolicyEnforcerTest : public ::testing::Test { +const char kGoogleAviatorLogID[] = + "\x68\xf6\x98\xf8\x1f\x64\x82\xbe\x3a\x8c\xee\xb9\x28\x1d\x4c\xfc\x71\x51" + "\x5d\x67\x93\xd4\x44\xd1\x0a\x67\xac\xbb\x4f\x4f\xfb\xc4"; +static_assert(arraysize(kGoogleAviatorLogID) - 1 == crypto::kSHA256Length, + "Incorrect log ID length."); + +class CTPolicyEnforcerTest : public ::testing::Test { public: void SetUp() override { - policy_enforcer_.reset(new CertPolicyEnforcer); + policy_enforcer_.reset(new CTPolicyEnforcer); std::string der_test_cert(ct::GetDerEncodedX509Cert()); chain_ = X509Certificate::CreateFromBytes(der_test_cert.data(), der_test_cert.size()); ASSERT_TRUE(chain_.get()); + google_log_id_ = std::string(kGoogleAviatorLogID, crypto::kSHA256Length); + non_google_log_id_.assign(crypto::kSHA256Length, 'A'); } void FillResultWithSCTsOfOrigin( ct::SignedCertificateTimestamp::Origin desired_origin, - int num_scts, + size_t num_scts, + const std::vector<std::string>& desired_log_keys, + bool timestamp_past_enforcement_date, ct::CTVerifyResult* result) { - for (int i = 0; i < num_scts; ++i) { + for (size_t i = 0; i < num_scts; ++i) { scoped_refptr<ct::SignedCertificateTimestamp> sct( new ct::SignedCertificateTimestamp()); sct->origin = desired_origin; + if (i < desired_log_keys.size()) + sct->log_id = desired_log_keys[i]; + else + sct->log_id = non_google_log_id_; + + if (timestamp_past_enforcement_date) + sct->timestamp = + base::Time::FromUTCExploded({2015, 8, 0, 15, 0, 0, 0, 0}); + else + sct->timestamp = + base::Time::FromUTCExploded({2015, 6, 0, 15, 0, 0, 0, 0}); + result->verified_scts.push_back(sct); } } + void FillResultWithSCTsOfOrigin( + ct::SignedCertificateTimestamp::Origin desired_origin, + size_t num_scts, + ct::CTVerifyResult* result) { + std::vector<std::string> desired_log_ids; + desired_log_ids.push_back(google_log_id_); + FillResultWithSCTsOfOrigin(desired_origin, num_scts, desired_log_ids, true, + result); + } + + void FillResultWithRepeatedLogID(const std::string& desired_id, + size_t num_scts, + bool timestamp_past_enforcement_date, + ct::CTVerifyResult* result) { + std::vector<std::string> desired_log_ids(num_scts, desired_id); + + FillResultWithSCTsOfOrigin( + ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, num_scts, + desired_log_ids, timestamp_past_enforcement_date, result); + } + void CheckCertificateCompliesWithExactNumberOfEmbeddedSCTs( const base::Time& start, const base::Time& end, @@ -74,16 +119,17 @@ class CertPolicyEnforcerTest : public ::testing::Test { scoped_refptr<X509Certificate> cert( new X509Certificate("subject", "issuer", start, end)); ct::CTVerifyResult result; + for (size_t i = 0; i < required_scts - 1; ++i) { FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, - 1, &result); + 1, std::vector<std::string>(), false, &result); EXPECT_FALSE(policy_enforcer_->DoesConformToCTEVPolicy( cert.get(), nullptr, result, BoundNetLog())) << " for: " << (end - start).InDays() << " and " << required_scts << " scts=" << result.verified_scts.size() << " i=" << i; } FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 1, - &result); + std::vector<std::string>(), false, &result); EXPECT_TRUE(policy_enforcer_->DoesConformToCTEVPolicy( cert.get(), nullptr, result, BoundNetLog())) << " for: " << (end - start).InDays() << " and " << required_scts @@ -91,11 +137,39 @@ class CertPolicyEnforcerTest : public ::testing::Test { } protected: - scoped_ptr<CertPolicyEnforcer> policy_enforcer_; + scoped_ptr<CTPolicyEnforcer> policy_enforcer_; scoped_refptr<X509Certificate> chain_; + std::string google_log_id_; + std::string non_google_log_id_; }; -TEST_F(CertPolicyEnforcerTest, ConformsToCTEVPolicyWithNonEmbeddedSCTs) { +TEST_F(CTPolicyEnforcerTest, + DoesNotConformToCTEVPolicyNotEnoughDiverseSCTsAllGoogle) { + ct::CTVerifyResult result; + FillResultWithRepeatedLogID(google_log_id_, 2, true, &result); + + EXPECT_FALSE(policy_enforcer_->DoesConformToCTEVPolicy( + chain_.get(), nullptr, result, BoundNetLog())); +} + +TEST_F(CTPolicyEnforcerTest, + DoesNotConformToCTEVPolicyNotEnoughDiverseSCTsAllNonGoogle) { + ct::CTVerifyResult result; + FillResultWithRepeatedLogID(non_google_log_id_, 2, true, &result); + + EXPECT_FALSE(policy_enforcer_->DoesConformToCTEVPolicy( + chain_.get(), nullptr, result, BoundNetLog())); +} + +TEST_F(CTPolicyEnforcerTest, ConformsToCTEVPolicyIfSCTBeforeEnforcementDate) { + ct::CTVerifyResult result; + FillResultWithRepeatedLogID(non_google_log_id_, 2, false, &result); + + EXPECT_TRUE(policy_enforcer_->DoesConformToCTEVPolicy(chain_.get(), nullptr, + result, BoundNetLog())); +} + +TEST_F(CTPolicyEnforcerTest, ConformsToCTEVPolicyWithNonEmbeddedSCTs) { ct::CTVerifyResult result; FillResultWithSCTsOfOrigin( ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, 2, &result); @@ -104,7 +178,7 @@ TEST_F(CertPolicyEnforcerTest, ConformsToCTEVPolicyWithNonEmbeddedSCTs) { result, BoundNetLog())); } -TEST_F(CertPolicyEnforcerTest, ConformsToCTEVPolicyWithEmbeddedSCTs) { +TEST_F(CTPolicyEnforcerTest, ConformsToCTEVPolicyWithEmbeddedSCTs) { // This chain_ is valid for 10 years - over 121 months - so requires 5 SCTs. ct::CTVerifyResult result; FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 5, @@ -114,7 +188,7 @@ TEST_F(CertPolicyEnforcerTest, ConformsToCTEVPolicyWithEmbeddedSCTs) { result, BoundNetLog())); } -TEST_F(CertPolicyEnforcerTest, DoesNotConformToCTEVPolicyNotEnoughSCTs) { +TEST_F(CTPolicyEnforcerTest, DoesNotConformToCTEVPolicyNotEnoughSCTs) { scoped_refptr<ct::EVCertsWhitelist> non_including_whitelist( new DummyEVCertsWhitelist(true, false)); // This chain_ is valid for 10 years - over 121 months - so requires 5 SCTs. @@ -134,7 +208,7 @@ TEST_F(CertPolicyEnforcerTest, DoesNotConformToCTEVPolicyNotEnoughSCTs) { chain_.get(), whitelist.get(), result, BoundNetLog())); } -TEST_F(CertPolicyEnforcerTest, DoesNotConformToPolicyInvalidDates) { +TEST_F(CTPolicyEnforcerTest, DoesNotConformToPolicyInvalidDates) { scoped_refptr<X509Certificate> no_valid_dates_cert(new X509Certificate( "subject", "issuer", base::Time(), base::Time::Now())); ct::CTVerifyResult result; @@ -149,7 +223,7 @@ TEST_F(CertPolicyEnforcerTest, DoesNotConformToPolicyInvalidDates) { chain_.get(), whitelist.get(), result, BoundNetLog())); } -TEST_F(CertPolicyEnforcerTest, +TEST_F(CTPolicyEnforcerTest, ConformsToPolicyExactNumberOfSCTsForValidityPeriod) { // Test multiple validity periods const struct TestData { @@ -193,7 +267,7 @@ TEST_F(CertPolicyEnforcerTest, } } -TEST_F(CertPolicyEnforcerTest, ConformsToPolicyByEVWhitelistPresence) { +TEST_F(CTPolicyEnforcerTest, ConformsToPolicyByEVWhitelistPresence) { scoped_refptr<ct::EVCertsWhitelist> whitelist( new DummyEVCertsWhitelist(true, true)); @@ -204,7 +278,7 @@ TEST_F(CertPolicyEnforcerTest, ConformsToPolicyByEVWhitelistPresence) { chain_.get(), whitelist.get(), result, BoundNetLog())); } -TEST_F(CertPolicyEnforcerTest, IgnoresInvalidEVWhitelist) { +TEST_F(CTPolicyEnforcerTest, IgnoresInvalidEVWhitelist) { scoped_refptr<ct::EVCertsWhitelist> whitelist( new DummyEVCertsWhitelist(false, true)); @@ -215,7 +289,7 @@ TEST_F(CertPolicyEnforcerTest, IgnoresInvalidEVWhitelist) { chain_.get(), whitelist.get(), result, BoundNetLog())); } -TEST_F(CertPolicyEnforcerTest, IgnoresNullEVWhitelist) { +TEST_F(CTPolicyEnforcerTest, IgnoresNullEVWhitelist) { ct::CTVerifyResult result; FillResultWithSCTsOfOrigin(ct::SignedCertificateTimestamp::SCT_EMBEDDED, 1, &result); diff --git a/chromium/net/cert/ct_serialization.cc b/chromium/net/cert/ct_serialization.cc index 6ea3cedc20f..235d37e65ad 100644 --- a/chromium/net/cert/ct_serialization.cc +++ b/chromium/net/cert/ct_serialization.cc @@ -6,6 +6,8 @@ #include <stdint.h> +#include <limits> + #include "base/logging.h" namespace net { @@ -360,7 +362,7 @@ bool DecodeSignedCertificateTimestamp( return false; } - if (timestamp > static_cast<uint64_t>(kint64max)) { + if (timestamp > static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) { DVLOG(1) << "Timestamp value too big to cast to int64_t: " << timestamp; return false; } diff --git a/chromium/net/cert/ct_serialization_unittest.cc b/chromium/net/cert/ct_serialization_unittest.cc index 28ed04c7d18..74cc0e900d8 100644 --- a/chromium/net/cert/ct_serialization_unittest.cc +++ b/chromium/net/cert/ct_serialization_unittest.cc @@ -164,7 +164,7 @@ TEST_F(CtSerializationTest, FailsDecodingInvalidSignedCertificateTimestamp) { TEST_F(CtSerializationTest, EncodesValidSignedTreeHead) { ct::SignedTreeHead signed_tree_head; - GetSampleSignedTreeHead(&signed_tree_head); + ASSERT_TRUE(GetSampleSignedTreeHead(&signed_tree_head)); std::string encoded; ct::EncodeTreeHeadSignature(signed_tree_head, &encoded); diff --git a/chromium/net/cert/ct_signed_certificate_timestamp_log_param.cc b/chromium/net/cert/ct_signed_certificate_timestamp_log_param.cc index 01efa0ab7d5..042f59fa16b 100644 --- a/chromium/net/cert/ct_signed_certificate_timestamp_log_param.cc +++ b/chromium/net/cert/ct_signed_certificate_timestamp_log_param.cc @@ -6,6 +6,7 @@ #include <algorithm> #include <string> +#include <utility> #include "base/base64.h" #include "base/strings/string_number_conversions.h" @@ -139,7 +140,7 @@ scoped_ptr<base::Value> NetLogSignedCertificateTimestampCallback( dict->Set("unknown_logs_scts", SCTListToPrintableValues(ct_result->unknown_logs_scts)); - return dict.Pass(); + return std::move(dict); } scoped_ptr<base::Value> NetLogRawSignedCertificateTimestampCallback( @@ -154,7 +155,7 @@ scoped_ptr<base::Value> NetLogRawSignedCertificateTimestampCallback( SetBinaryData("scts_from_tls_extension", *sct_list_from_tls_extension, dict.get()); - return dict.Pass(); + return std::move(dict); } } // namespace net diff --git a/chromium/net/cert/ct_verifier.h b/chromium/net/cert/ct_verifier.h index 40631048ac3..46a811a7960 100644 --- a/chromium/net/cert/ct_verifier.h +++ b/chromium/net/cert/ct_verifier.h @@ -21,6 +21,7 @@ class CTLogVerifier; class X509Certificate; // Interface for verifying Signed Certificate Timestamps over a certificate. +// The only known (non-test) implementation currently is MultiLogCTVerifier. class NET_EXPORT CTVerifier { public: class NET_EXPORT Observer { @@ -30,6 +31,8 @@ class NET_EXPORT CTVerifier { // Signed Certificate Timestamp, |cert| is the certificate it applies to. // The certificate is needed to calculate the hash of the log entry, // necessary for checking inclusion in the log. + // Note: The observer (whose implementation is expected to exist outside + // net/) may store the observed |cert| and |sct|. virtual void OnSCTVerified(X509Certificate* cert, const ct::SignedCertificateTimestamp* sct) = 0; }; diff --git a/chromium/net/cert/ev_root_ca_metadata.cc b/chromium/net/cert/ev_root_ca_metadata.cc index 8dd55f4e8c4..a5ac6e2231e 100644 --- a/chromium/net/cert/ev_root_ca_metadata.cc +++ b/chromium/net/cert/ev_root_ca_metadata.cc @@ -443,11 +443,6 @@ static const EVMetadata ev_root_ca_metadata[] = { 0x6c, 0x51, 0xf7, 0x0e, 0xe9, 0x0d, 0xda, 0xb9, 0xad, 0x8e } }, {"1.3.6.1.4.1.6449.1.2.1.5.1", ""}, }, - // UTN - DATACorp SGC - { { { 0x58, 0x11, 0x9f, 0x0e, 0x12, 0x82, 0x87, 0xea, 0x50, 0xfd, - 0xd9, 0x87, 0x45, 0x6f, 0x4f, 0x78, 0xdc, 0xfa, 0xd6, 0xd4 } }, - {"1.3.6.1.4.1.6449.1.2.1.5.1", ""}, - }, // UTN-USERFirst-Hardware { { { 0x04, 0x83, 0xed, 0x33, 0x99, 0xac, 0x36, 0x08, 0x05, 0x87, 0x22, 0xed, 0xbc, 0x5e, 0x46, 0x00, 0xe3, 0xbe, 0xf9, 0xd7 } }, diff --git a/chromium/net/cert/ev_root_ca_metadata.h b/chromium/net/cert/ev_root_ca_metadata.h index 10227a2536c..508e188b132 100644 --- a/chromium/net/cert/ev_root_ca_metadata.h +++ b/chromium/net/cert/ev_root_ca_metadata.h @@ -16,6 +16,7 @@ #include <string> #include <vector> +#include "base/macros.h" #include "net/base/net_export.h" #include "net/cert/x509_certificate.h" diff --git a/chromium/net/cert/internal/certificate_policies.cc b/chromium/net/cert/internal/certificate_policies.cc new file mode 100644 index 00000000000..4ff3a3a6595 --- /dev/null +++ b/chromium/net/cert/internal/certificate_policies.cc @@ -0,0 +1,178 @@ +// Copyright 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. + +#include <algorithm> + +#include "net/cert/internal/certificate_policies.h" + +#include "net/der/input.h" +#include "net/der/parser.h" +#include "net/der/tag.h" + +namespace net { + +namespace { + +// -- policyQualifierIds for Internet policy qualifiers +// +// id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } +// id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } +// +// In dotted decimal form: 1.3.6.1.5.5.7.2.1 +const der::Input CpsPointerId() { + static const uint8_t cps_pointer_id[] = {0x2b, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x02, 0x01}; + return der::Input(cps_pointer_id); +} + +// id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } +// +// In dotted decimal form: 1.3.6.1.5.5.7.2.2 +const der::Input UserNoticeId() { + static const uint8_t user_notice_id[] = {0x2b, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x02, 0x02}; + return der::Input(user_notice_id); +} + +// Ignores the policyQualifiers, but does some minimal correctness checking. +// TODO(mattm): parse and return the policyQualifiers, since the cert viewer +// still needs to display them. +bool ParsePolicyQualifiers(const der::Input& policy_oid, + der::Parser* policy_qualifiers_sequence_parser) { + // If it is present, the policyQualifiers sequence should have at least 1 + // element. + if (!policy_qualifiers_sequence_parser->HasMore()) + return false; + while (policy_qualifiers_sequence_parser->HasMore()) { + der::Parser policy_information_parser; + if (!policy_qualifiers_sequence_parser->ReadSequence( + &policy_information_parser)) { + return false; + } + der::Input qualifier_oid; + if (!policy_information_parser.ReadTag(der::kOid, &qualifier_oid)) + return false; + // RFC 5280 section 4.2.1.4: When qualifiers are used with the special + // policy anyPolicy, they MUST be limited to the qualifiers identified in + // this section. + if (policy_oid.Equals(AnyPolicy()) && + !qualifier_oid.Equals(CpsPointerId()) && + !qualifier_oid.Equals(UserNoticeId())) { + return false; + } + der::Tag tag; + der::Input value; + if (!policy_information_parser.ReadTagAndValue(&tag, &value)) + return false; + // Should not have trailing data after qualifier. + if (policy_information_parser.HasMore()) + return false; + } + return true; +} + +} // namespace + +const der::Input AnyPolicy() { + // id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} + // + // id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } + // + // anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } + // + // In dotted decimal form: 2.5.29.32.0 + static const uint8_t any_policy[] = {0x55, 0x1D, 0x20, 0x00}; + return der::Input(any_policy); +} + +// RFC 5280 section 4.2.1.4. Certificate Policies: +// +// certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation +// +// PolicyInformation ::= SEQUENCE { +// policyIdentifier CertPolicyId, +// policyQualifiers SEQUENCE SIZE (1..MAX) OF +// PolicyQualifierInfo OPTIONAL } +// +// CertPolicyId ::= OBJECT IDENTIFIER +// +// PolicyQualifierInfo ::= SEQUENCE { +// policyQualifierId PolicyQualifierId, +// qualifier ANY DEFINED BY policyQualifierId } +// +// PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) +// +// Qualifier ::= CHOICE { +// cPSuri CPSuri, +// userNotice UserNotice } +// +// CPSuri ::= IA5String +// +// UserNotice ::= SEQUENCE { +// noticeRef NoticeReference OPTIONAL, +// explicitText DisplayText OPTIONAL } +// +// NoticeReference ::= SEQUENCE { +// organization DisplayText, +// noticeNumbers SEQUENCE OF INTEGER } +// +// DisplayText ::= CHOICE { +// ia5String IA5String (SIZE (1..200)), +// visibleString VisibleString (SIZE (1..200)), +// bmpString BMPString (SIZE (1..200)), +// utf8String UTF8String (SIZE (1..200)) } +bool ParseCertificatePoliciesExtension(const der::Input& extension_value, + std::vector<der::Input>* policies) { + der::Parser extension_parser(extension_value); + der::Parser policies_sequence_parser; + if (!extension_parser.ReadSequence(&policies_sequence_parser)) + return false; + // Should not have trailing data after certificatePolicies sequence. + if (extension_parser.HasMore()) + return false; + // The certificatePolicies sequence should have at least 1 element. + if (!policies_sequence_parser.HasMore()) + return false; + + policies->clear(); + + while (policies_sequence_parser.HasMore()) { + der::Parser policy_information_parser; + if (!policies_sequence_parser.ReadSequence(&policy_information_parser)) + return false; + der::Input policy_oid; + if (!policy_information_parser.ReadTag(der::kOid, &policy_oid)) + return false; + + // Build the |policies| vector in sorted order (sorted on DER encoded policy + // OID). Use a binary search to check whether a duplicate policy is present, + // and if not, where to insert the policy to maintain the sorted order. + std::vector<der::Input>::iterator i = + std::lower_bound(policies->begin(), policies->end(), policy_oid); + // RFC 5280 section 4.2.1.4: A certificate policy OID MUST NOT appear more + // than once in a certificate policies extension. + if (i != policies->end() && i->Equals(policy_oid)) + return false; + + policies->insert(i, policy_oid); + + if (!policy_information_parser.HasMore()) + continue; + + der::Parser policy_qualifiers_sequence_parser; + if (!policy_information_parser.ReadSequence( + &policy_qualifiers_sequence_parser)) { + return false; + } + // Should not have trailing data after policyQualifiers sequence. + if (policy_information_parser.HasMore()) + return false; + if (!ParsePolicyQualifiers(policy_oid, &policy_qualifiers_sequence_parser)) + return false; + } + + return true; +} + +} // namespace net diff --git a/chromium/net/cert/internal/certificate_policies.h b/chromium/net/cert/internal/certificate_policies.h new file mode 100644 index 00000000000..e2ac13fd4e0 --- /dev/null +++ b/chromium/net/cert/internal/certificate_policies.h @@ -0,0 +1,36 @@ +// Copyright 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. + +#ifndef NET_CERT_INTERNAL_CERTIFICATE_POLICIES_H_ +#define NET_CERT_INTERNAL_CERTIFICATE_POLICIES_H_ + +#include <vector> + +#include "net/base/net_export.h" + +namespace net { + +namespace der { +class Input; +} // namespace der + +// Returns the DER-encoded OID, without tag or length, of the anyPolicy +// certificate policy defined in RFC 5280 section 4.2.1.4. +NET_EXPORT const der::Input AnyPolicy(); + +// Parses a certificatePolicies extension and stores the policy OIDs in +// |*policies|, in sorted order. If policyQualifiers are present, +// they are ignored. (RFC 5280 section 4.2.1.4 says "optional qualifiers, which +// MAY be present, are not expected to change the definition of the policy.", +// furthermore policyQualifiers do not affect the success or failure of the +// section 6 Certification Path Validation algorithm.) +// +// The returned values is only valid as long as |extension_value| is. +NET_EXPORT bool ParseCertificatePoliciesExtension( + const der::Input& extension_value, + std::vector<der::Input>* policies); + +} // namespace net + +#endif // NET_CERT_INTERNAL_CERTIFICATE_POLICIES_H_ diff --git a/chromium/net/cert/internal/certificate_policies_unittest.cc b/chromium/net/cert/internal/certificate_policies_unittest.cc new file mode 100644 index 00000000000..71137cb1f3e --- /dev/null +++ b/chromium/net/cert/internal/certificate_policies_unittest.cc @@ -0,0 +1,150 @@ +// Copyright 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. + +#include "net/cert/internal/certificate_policies.h" + +#include "net/cert/internal/test_helpers.h" +#include "net/der/input.h" +#include "net/der/parser.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { +namespace { + +::testing::AssertionResult LoadTestData(const std::string& name, + std::string* result) { + std::string path = "net/data/certificate_policies_unittest/" + name; + + const PemBlockMapping mappings[] = { + {"CERTIFICATE POLICIES", result}, + }; + + return ReadTestDataFromPemFile(path, mappings); +} + +const uint8_t policy_1_2_3_der[] = {0x2A, 0x03}; +const uint8_t policy_1_2_4_der[] = {0x2A, 0x04}; + +} // namespace + +TEST(ParseCertificatePoliciesTest, InvalidEmpty) { + std::string der; + ASSERT_TRUE(LoadTestData("invalid-empty.pem", &der)); + std::vector<der::Input> policies; + EXPECT_FALSE(ParseCertificatePoliciesExtension(der::Input(&der), &policies)); +} + +TEST(ParseCertificatePoliciesTest, InvalidIdentifierNotOid) { + std::string der; + ASSERT_TRUE(LoadTestData("invalid-policy_identifier_not_oid.pem", &der)); + std::vector<der::Input> policies; + EXPECT_FALSE(ParseCertificatePoliciesExtension(der::Input(&der), &policies)); +} + +TEST(ParseCertificatePoliciesTest, AnyPolicy) { + std::string der; + ASSERT_TRUE(LoadTestData("anypolicy.pem", &der)); + std::vector<der::Input> policies; + EXPECT_TRUE(ParseCertificatePoliciesExtension(der::Input(&der), &policies)); + ASSERT_EQ(1U, policies.size()); + EXPECT_EQ(AnyPolicy(), policies[0]); +} + +TEST(ParseCertificatePoliciesTest, AnyPolicyWithQualifier) { + std::string der; + ASSERT_TRUE(LoadTestData("anypolicy_with_qualifier.pem", &der)); + std::vector<der::Input> policies; + EXPECT_TRUE(ParseCertificatePoliciesExtension(der::Input(&der), &policies)); + ASSERT_EQ(1U, policies.size()); + EXPECT_EQ(AnyPolicy(), policies[0]); +} + +TEST(ParseCertificatePoliciesTest, InvalidAnyPolicyWithCustomQualifier) { + std::string der; + ASSERT_TRUE( + LoadTestData("invalid-anypolicy_with_custom_qualifier.pem", &der)); + std::vector<der::Input> policies; + EXPECT_FALSE(ParseCertificatePoliciesExtension(der::Input(&der), &policies)); +} + +TEST(ParseCertificatePoliciesTest, OnePolicy) { + std::string der; + ASSERT_TRUE(LoadTestData("policy_1_2_3.pem", &der)); + std::vector<der::Input> policies; + EXPECT_TRUE(ParseCertificatePoliciesExtension(der::Input(&der), &policies)); + ASSERT_EQ(1U, policies.size()); + EXPECT_EQ(der::Input(policy_1_2_3_der), policies[0]); +} + +TEST(ParseCertificatePoliciesTest, OnePolicyWithQualifier) { + std::string der; + ASSERT_TRUE(LoadTestData("policy_1_2_3_with_qualifier.pem", &der)); + std::vector<der::Input> policies; + EXPECT_TRUE(ParseCertificatePoliciesExtension(der::Input(&der), &policies)); + ASSERT_EQ(1U, policies.size()); + EXPECT_EQ(der::Input(policy_1_2_3_der), policies[0]); +} + +TEST(ParseCertificatePoliciesTest, OnePolicyWithCustomQualifier) { + std::string der; + ASSERT_TRUE(LoadTestData("policy_1_2_3_with_custom_qualifier.pem", &der)); + std::vector<der::Input> policies; + EXPECT_TRUE(ParseCertificatePoliciesExtension(der::Input(&der), &policies)); + ASSERT_EQ(1U, policies.size()); + EXPECT_EQ(der::Input(policy_1_2_3_der), policies[0]); +} + +TEST(ParseCertificatePoliciesTest, InvalidPolicyWithDuplicatePolicyOid) { + std::string der; + ASSERT_TRUE(LoadTestData("invalid-policy_1_2_3_dupe.pem", &der)); + std::vector<der::Input> policies; + EXPECT_FALSE(ParseCertificatePoliciesExtension(der::Input(&der), &policies)); +} + +TEST(ParseCertificatePoliciesTest, InvalidPolicyWithEmptyQualifiersSequence) { + std::string der; + ASSERT_TRUE(LoadTestData( + "invalid-policy_1_2_3_with_empty_qualifiers_sequence.pem", &der)); + std::vector<der::Input> policies; + EXPECT_FALSE(ParseCertificatePoliciesExtension(der::Input(&der), &policies)); +} + +TEST(ParseCertificatePoliciesTest, InvalidPolicyInformationHasUnconsumedData) { + std::string der; + ASSERT_TRUE(LoadTestData( + "invalid-policy_1_2_3_policyinformation_unconsumed_data.pem", &der)); + std::vector<der::Input> policies; + EXPECT_FALSE(ParseCertificatePoliciesExtension(der::Input(&der), &policies)); +} + +TEST(ParseCertificatePoliciesTest, + InvalidPolicyQualifierInfoHasUnconsumedData) { + std::string der; + ASSERT_TRUE(LoadTestData( + "invalid-policy_1_2_3_policyqualifierinfo_unconsumed_data.pem", &der)); + std::vector<der::Input> policies; + EXPECT_FALSE(ParseCertificatePoliciesExtension(der::Input(&der), &policies)); +} + +TEST(ParseCertificatePoliciesTest, TwoPolicies) { + std::string der; + ASSERT_TRUE(LoadTestData("policy_1_2_3_and_1_2_4.pem", &der)); + std::vector<der::Input> policies; + EXPECT_TRUE(ParseCertificatePoliciesExtension(der::Input(&der), &policies)); + ASSERT_EQ(2U, policies.size()); + EXPECT_EQ(der::Input(policy_1_2_3_der), policies[0]); + EXPECT_EQ(der::Input(policy_1_2_4_der), policies[1]); +} + +TEST(ParseCertificatePoliciesTest, TwoPoliciesWithQualifiers) { + std::string der; + ASSERT_TRUE(LoadTestData("policy_1_2_3_and_1_2_4_with_qualifiers.pem", &der)); + std::vector<der::Input> policies; + EXPECT_TRUE(ParseCertificatePoliciesExtension(der::Input(&der), &policies)); + ASSERT_EQ(2U, policies.size()); + EXPECT_EQ(der::Input(policy_1_2_3_der), policies[0]); + EXPECT_EQ(der::Input(policy_1_2_4_der), policies[1]); +} + +} // namespace net diff --git a/chromium/net/cert/internal/name_constraints.cc b/chromium/net/cert/internal/name_constraints.cc new file mode 100644 index 00000000000..ade43a776ee --- /dev/null +++ b/chromium/net/cert/internal/name_constraints.cc @@ -0,0 +1,569 @@ +// Copyright 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. + +#include "net/cert/internal/name_constraints.h" + +#include <limits.h> + +#include "base/strings/string_util.h" +#include "net/cert/internal/verify_name_match.h" +#include "net/der/input.h" +#include "net/der/parser.h" +#include "net/der/tag.h" + +namespace net { + +namespace { + +// The name types of GeneralName that are fully supported in name constraints. +// +// (The other types will have the minimal checking described by RFC 5280 +// section 4.2.1.10: If a name constraints extension that is marked as critical +// imposes constraints on a particular name form, and an instance of +// that name form appears in the subject field or subjectAltName +// extension of a subsequent certificate, then the application MUST +// either process the constraint or reject the certificate.) +const int kSupportedNameTypes = GENERAL_NAME_DNS_NAME | + GENERAL_NAME_DIRECTORY_NAME | + GENERAL_NAME_IP_ADDRESS; + +// Controls wildcard handling of DNSNameMatches. +// If WildcardMatchType is WILDCARD_PARTIAL_MATCH "*.bar.com" is considered to +// match the constraint "foo.bar.com". If it is WILDCARD_FULL_MATCH, "*.bar.com" +// will match "bar.com" but not "foo.bar.com". +enum WildcardMatchType { WILDCARD_PARTIAL_MATCH, WILDCARD_FULL_MATCH }; + +// Returns true if |name| falls in the subtree defined by |dns_constraint|. +// RFC 5280 section 4.2.1.10: +// DNS name restrictions are expressed as host.example.com. Any DNS +// name that can be constructed by simply adding zero or more labels +// to the left-hand side of the name satisfies the name constraint. For +// example, www.host.example.com would satisfy the constraint but +// host1.example.com would not. +// +// |wildcard_matching| controls handling of wildcard names (|name| starts with +// "*."). Wildcard handling is not specified by RFC 5280, but certificate +// verification allows it, name constraints must check it similarly. +bool DNSNameMatches(base::StringPiece name, + base::StringPiece dns_constraint, + WildcardMatchType wildcard_matching) { + // Everything matches the empty DNS name constraint. + if (dns_constraint.empty()) + return true; + + // Normalize absolute DNS names by removing the trailing dot, if any. + if (!name.empty() && *name.rbegin() == '.') + name.remove_suffix(1); + if (!dns_constraint.empty() && *dns_constraint.rbegin() == '.') + dns_constraint.remove_suffix(1); + + // Wildcard partial-match handling ("*.bar.com" matching name constraint + // "foo.bar.com"). This only handles the case where the the dnsname and the + // constraint match after removing the leftmost label, otherwise it is handled + // by falling through to the check of whether the dnsname is fully within or + // fully outside of the constraint. + if (wildcard_matching == WILDCARD_PARTIAL_MATCH && name.size() > 2 && + name[0] == '*' && name[1] == '.') { + size_t dns_constraint_dot_pos = dns_constraint.find('.'); + if (dns_constraint_dot_pos != std::string::npos) { + base::StringPiece dns_constraint_domain( + dns_constraint.begin() + dns_constraint_dot_pos + 1, + dns_constraint.size() - dns_constraint_dot_pos - 1); + base::StringPiece wildcard_domain(name.begin() + 2, name.size() - 2); + if (base::EqualsCaseInsensitiveASCII(wildcard_domain, + dns_constraint_domain)) { + return true; + } + } + } + + if (!base::EndsWith(name, dns_constraint, + base::CompareCase::INSENSITIVE_ASCII)) { + return false; + } + // Exact match. + if (name.size() == dns_constraint.size()) + return true; + // Subtree match. + if (name.size() > dns_constraint.size() && + name[name.size() - dns_constraint.size() - 1] == '.') { + return true; + } + // Trailing text matches, but not in a subtree (e.g., "foobar.com" is not a + // match for "bar.com"). + return false; +} + +// Return true if the bitmask |mask| contains only zeros after the first +// |prefix_length| bits. +bool IsSuffixZero(const std::vector<uint8_t>& mask, unsigned prefix_length) { + size_t zero_bits = mask.size() * CHAR_BIT - prefix_length; + size_t zero_bytes = zero_bits / CHAR_BIT; + std::vector<uint8_t> zeros(zero_bytes, 0); + if (memcmp(zeros.data(), mask.data() + mask.size() - zero_bytes, zero_bytes)) + return false; + size_t leftover_bits = zero_bits % CHAR_BIT; + if (leftover_bits) { + uint8_t b = mask[mask.size() - zero_bytes - 1]; + for (size_t i = 0; i < leftover_bits; ++i) { + if (b & (1 << i)) + return false; + } + } + return true; +} + +// Controls handling of unsupported name types in ParseGeneralName. (Unsupported +// types are those not in kSupportedNameTypes.) +// RECORD_UNSUPPORTED causes unsupported types to be recorded in +// |present_name_types|. +// IGNORE_UNSUPPORTED causes unsupported types to not be recorded. +enum ParseGeneralNameUnsupportedTypeBehavior { + RECORD_UNSUPPORTED, + IGNORE_UNSUPPORTED, +}; + +// Controls parsing of iPAddress names in ParseGeneralName. +// IP_ADDRESS_ONLY parses the iPAddress names as a 4 or 16 byte IP address. +// IP_ADDRESS_AND_NETMASK parses the iPAddress names as 8 or 32 bytes containing +// an IP address followed by a netmask. +enum ParseGeneralNameIPAddressType { + IP_ADDRESS_ONLY, + IP_ADDRESS_AND_NETMASK, +}; + +// Parses a GeneralName value and adds it to |subtrees|. +WARN_UNUSED_RESULT bool ParseGeneralName( + const der::Input& input, + ParseGeneralNameUnsupportedTypeBehavior unsupported_type_behavior, + ParseGeneralNameIPAddressType ip_address_type, + NameConstraints::GeneralNames* subtrees) { + der::Parser parser(input); + der::Tag tag; + der::Input value; + if (!parser.ReadTagAndValue(&tag, &value)) + return false; + if (!der::IsContextSpecific(tag)) + return false; + GeneralNameTypes name_type = GENERAL_NAME_NONE; + // GeneralName ::= CHOICE { + switch (der::GetTagNumber(tag)) { + // otherName [0] OtherName, + case 0: + if (!der::IsConstructed(tag)) + return false; + name_type = GENERAL_NAME_OTHER_NAME; + break; + // rfc822Name [1] IA5String, + case 1: + if (der::IsConstructed(tag)) + return false; + name_type = GENERAL_NAME_RFC822_NAME; + break; + // dNSName [2] IA5String, + case 2: { + if (der::IsConstructed(tag)) + return false; + name_type = GENERAL_NAME_DNS_NAME; + const std::string s = value.AsString(); + if (!base::IsStringASCII(s)) + return false; + subtrees->dns_names.push_back(s); + break; + } + // x400Address [3] ORAddress, + case 3: + if (!der::IsConstructed(tag)) + return false; + name_type = GENERAL_NAME_X400_ADDRESS; + break; + // directoryName [4] Name, + case 4: + if (!der::IsConstructed(tag)) + return false; + name_type = GENERAL_NAME_DIRECTORY_NAME; + subtrees->directory_names.push_back(std::vector<uint8_t>( + value.UnsafeData(), value.UnsafeData() + value.Length())); + break; + // ediPartyName [5] EDIPartyName, + case 5: + if (!der::IsConstructed(tag)) + return false; + name_type = GENERAL_NAME_EDI_PARTY_NAME; + break; + // uniformResourceIdentifier [6] IA5String, + case 6: + if (der::IsConstructed(tag)) + return false; + name_type = GENERAL_NAME_UNIFORM_RESOURCE_IDENTIFIER; + break; + // iPAddress [7] OCTET STRING, + case 7: + if (der::IsConstructed(tag)) + return false; + name_type = GENERAL_NAME_IP_ADDRESS; + if (ip_address_type == IP_ADDRESS_ONLY) { + // RFC 5280 section 4.2.1.6: + // When the subjectAltName extension contains an iPAddress, the address + // MUST be stored in the octet string in "network byte order", as + // specified in [RFC791]. The least significant bit (LSB) of each octet + // is the LSB of the corresponding byte in the network address. For IP + // version 4, as specified in [RFC791], the octet string MUST contain + // exactly four octets. For IP version 6, as specified in [RFC2460], + // the octet string MUST contain exactly sixteen octets. + if ((value.Length() != kIPv4AddressSize && + value.Length() != kIPv6AddressSize)) { + return false; + } + subtrees->ip_addresses.push_back(std::vector<uint8_t>( + value.UnsafeData(), value.UnsafeData() + value.Length())); + } else { + DCHECK_EQ(ip_address_type, IP_ADDRESS_AND_NETMASK); + // RFC 5280 section 4.2.1.10: + // The syntax of iPAddress MUST be as described in Section 4.2.1.6 with + // the following additions specifically for name constraints. For IPv4 + // addresses, the iPAddress field of GeneralName MUST contain eight (8) + // octets, encoded in the style of RFC 4632 (CIDR) to represent an + // address range [RFC4632]. For IPv6 addresses, the iPAddress field + // MUST contain 32 octets similarly encoded. For example, a name + // constraint for "class C" subnet 192.0.2.0 is represented as the + // octets C0 00 02 00 FF FF FF 00, representing the CIDR notation + // 192.0.2.0/24 (mask 255.255.255.0). + if (value.Length() != kIPv4AddressSize * 2 && + value.Length() != kIPv6AddressSize * 2) { + return false; + } + const std::vector<uint8_t> mask(value.UnsafeData() + value.Length() / 2, + value.UnsafeData() + value.Length()); + const unsigned mask_prefix_length = MaskPrefixLength(mask); + if (!IsSuffixZero(mask, mask_prefix_length)) + return false; + subtrees->ip_address_ranges.push_back(std::make_pair( + std::vector<uint8_t>(value.UnsafeData(), + value.UnsafeData() + value.Length() / 2), + mask_prefix_length)); + } + break; + // registeredID [8] OBJECT IDENTIFIER } + case 8: + if (der::IsConstructed(tag)) + return false; + name_type = GENERAL_NAME_REGISTERED_ID; + break; + default: + return false; + } + DCHECK_NE(GENERAL_NAME_NONE, name_type); + if ((name_type & kSupportedNameTypes) || + unsupported_type_behavior == RECORD_UNSUPPORTED) { + subtrees->present_name_types |= name_type; + } + return true; +} + +// Parses a GeneralSubtrees |value| and store the contents in |subtrees|. +// The individual values stored into |subtrees| are not validated by this +// function. +// NOTE: |subtrees| will be modified regardless of the return. +WARN_UNUSED_RESULT bool ParseGeneralSubtrees( + const der::Input& value, + bool is_critical, + NameConstraints::GeneralNames* subtrees) { + // GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree + // + // GeneralSubtree ::= SEQUENCE { + // base GeneralName, + // minimum [0] BaseDistance DEFAULT 0, + // maximum [1] BaseDistance OPTIONAL } + // + // BaseDistance ::= INTEGER (0..MAX) + der::Parser sequence_parser(value); + // The GeneralSubtrees sequence should have at least 1 element. + if (!sequence_parser.HasMore()) + return false; + while (sequence_parser.HasMore()) { + der::Parser subtree_sequence; + if (!sequence_parser.ReadSequence(&subtree_sequence)) + return false; + + der::Input raw_general_name; + if (!subtree_sequence.ReadRawTLV(&raw_general_name)) + return false; + + if (!ParseGeneralName(raw_general_name, + is_critical ? RECORD_UNSUPPORTED : IGNORE_UNSUPPORTED, + IP_ADDRESS_AND_NETMASK, subtrees)) { + return false; + } + + // RFC 5280 section 4.2.1.10: + // Within this profile, the minimum and maximum fields are not used with any + // name forms, thus, the minimum MUST be zero, and maximum MUST be absent. + // However, if an application encounters a critical name constraints + // extension that specifies other values for minimum or maximum for a name + // form that appears in a subsequent certificate, the application MUST + // either process these fields or reject the certificate. + + // Note that technically failing here isn't required: rather only need to + // fail if a name of this type actually appears in a subsequent cert and + // this extension was marked critical. However the minimum and maximum + // fields appear uncommon enough that implementing that isn't useful. + if (subtree_sequence.HasMore()) + return false; + } + return true; +} + +} // namespace + +NameConstraints::GeneralNames::GeneralNames() {} + +NameConstraints::GeneralNames::~GeneralNames() {} + +NameConstraints::~NameConstraints() {} + +// static +scoped_ptr<NameConstraints> NameConstraints::CreateFromDer( + const der::Input& extension_value, + bool is_critical) { + scoped_ptr<NameConstraints> name_constraints(new NameConstraints()); + if (!name_constraints->Parse(extension_value, is_critical)) + return nullptr; + return name_constraints; +} + +bool NameConstraints::Parse(const der::Input& extension_value, + bool is_critical) { + der::Parser extension_parser(extension_value); + der::Parser sequence_parser; + + // NameConstraints ::= SEQUENCE { + // permittedSubtrees [0] GeneralSubtrees OPTIONAL, + // excludedSubtrees [1] GeneralSubtrees OPTIONAL } + if (!extension_parser.ReadSequence(&sequence_parser)) + return false; + if (extension_parser.HasMore()) + return false; + + bool had_permitted_subtrees = false; + der::Input permitted_subtrees_value; + if (!sequence_parser.ReadOptionalTag(der::ContextSpecificConstructed(0), + &permitted_subtrees_value, + &had_permitted_subtrees)) { + return false; + } + if (had_permitted_subtrees && + !ParseGeneralSubtrees(permitted_subtrees_value, is_critical, + &permitted_subtrees_)) { + return false; + } + + bool had_excluded_subtrees = false; + der::Input excluded_subtrees_value; + if (!sequence_parser.ReadOptionalTag(der::ContextSpecificConstructed(1), + &excluded_subtrees_value, + &had_excluded_subtrees)) { + return false; + } + if (had_excluded_subtrees && + !ParseGeneralSubtrees(excluded_subtrees_value, is_critical, + &excluded_subtrees_)) { + return false; + } + + // RFC 5280 section 4.2.1.10: + // Conforming CAs MUST NOT issue certificates where name constraints is an + // empty sequence. That is, either the permittedSubtrees field or the + // excludedSubtrees MUST be present. + if (!had_permitted_subtrees && !had_excluded_subtrees) + return false; + + if (sequence_parser.HasMore()) + return false; + + return true; +} + +bool NameConstraints::IsPermittedCert( + const der::Input& subject_rdn_sequence, + const der::Input& subject_alt_name_extnvalue_tlv) const { + // Subject Alternative Name handling: + // + // RFC 5280 section 4.2.1.6: + // id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } + // + // SubjectAltName ::= GeneralNames + // + // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + + GeneralNames san_names; + if (subject_alt_name_extnvalue_tlv.Length()) { + der::Parser extnvalue_parser(subject_alt_name_extnvalue_tlv); + der::Input subject_alt_name_tlv; + if (!extnvalue_parser.ReadTag(der::kOctetString, &subject_alt_name_tlv)) + return false; + + der::Parser subject_alt_name_parser(subject_alt_name_tlv); + der::Parser san_sequence_parser; + if (!subject_alt_name_parser.ReadSequence(&san_sequence_parser)) + return false; + // Should not have trailing data after subjectAltName sequence. + if (subject_alt_name_parser.HasMore()) + return false; + // The subjectAltName sequence should have at least 1 element. + if (!san_sequence_parser.HasMore()) + return false; + + while (san_sequence_parser.HasMore()) { + der::Input raw_general_name; + if (!san_sequence_parser.ReadRawTLV(&raw_general_name)) + return false; + + if (!ParseGeneralName(raw_general_name, RECORD_UNSUPPORTED, + IP_ADDRESS_ONLY, &san_names)) + return false; + } + + // Check unsupported name types: + // ConstrainedNameTypes for the unsupported types will only be true if that + // type of name was present in a name constraint that was marked critical. + // + // RFC 5280 section 4.2.1.10: + // If a name constraints extension that is marked as critical + // imposes constraints on a particular name form, and an instance of + // that name form appears in the subject field or subjectAltName + // extension of a subsequent certificate, then the application MUST + // either process the constraint or reject the certificate. + if (ConstrainedNameTypes() & san_names.present_name_types & + ~kSupportedNameTypes) { + return false; + } + + // Check supported name types: + for (const auto& dns_name : san_names.dns_names) { + if (!IsPermittedDNSName(dns_name)) + return false; + } + + for (const auto& directory_name : san_names.directory_names) { + if (!IsPermittedDirectoryName( + der::Input(directory_name.data(), directory_name.size()))) { + return false; + } + } + + for (const auto& ip_address : san_names.ip_addresses) { + if (!IsPermittedIP(ip_address)) + return false; + } + } + + // Subject handling: + + // RFC 5280 section 4.2.1.10: + // Legacy implementations exist where an electronic mail address is embedded + // in the subject distinguished name in an attribute of type emailAddress + // (Section 4.1.2.6). When constraints are imposed on the rfc822Name name + // form, but the certificate does not include a subject alternative name, the + // rfc822Name constraint MUST be applied to the attribute of type emailAddress + // in the subject distinguished name. + if (!subject_alt_name_extnvalue_tlv.Length() && + (ConstrainedNameTypes() & GENERAL_NAME_RFC822_NAME)) { + bool contained_email_address = false; + if (!NameContainsEmailAddress(subject_rdn_sequence, + &contained_email_address)) { + return false; + } + if (contained_email_address) + return false; + } + + // RFC 5280 4.1.2.6: + // If subject naming information is present only in the subjectAltName + // extension (e.g., a key bound only to an email address or URI), then the + // subject name MUST be an empty sequence and the subjectAltName extension + // MUST be critical. + // This code assumes that criticality condition is checked by the caller, and + // therefore only needs to avoid the IsPermittedDirectoryName check against an + // empty subject in such a case. + if (subject_alt_name_extnvalue_tlv.Length() && + subject_rdn_sequence.Length() == 0) { + return true; + } + + return IsPermittedDirectoryName(subject_rdn_sequence); +} + +bool NameConstraints::IsPermittedDNSName(const std::string& name) const { + // If there are no name constraints for DNS names, all names are accepted. + if (!(ConstrainedNameTypes() & GENERAL_NAME_DNS_NAME)) + return true; + + for (const std::string& excluded_name : excluded_subtrees_.dns_names) { + // When matching wildcard hosts against excluded subtrees, consider it a + // match if the constraint would match any expansion of the wildcard. Eg, + // *.bar.com should match a constraint of foo.bar.com. + if (DNSNameMatches(name, excluded_name, WILDCARD_PARTIAL_MATCH)) + return false; + } + for (const std::string& permitted_name : permitted_subtrees_.dns_names) { + // When matching wildcard hosts against permitted subtrees, consider it a + // match only if the constraint would match all expansions of the wildcard. + // Eg, *.bar.com should match a constraint of bar.com, but not foo.bar.com. + if (DNSNameMatches(name, permitted_name, WILDCARD_FULL_MATCH)) + return true; + } + + return false; +} + +bool NameConstraints::IsPermittedDirectoryName( + const der::Input& name_rdn_sequence) const { + // If there are no name constraints for directory names, all names are + // accepted. + if (!(ConstrainedNameTypes() & GENERAL_NAME_DIRECTORY_NAME)) + return true; + + for (const auto& excluded_name : excluded_subtrees_.directory_names) { + if (VerifyNameInSubtree( + name_rdn_sequence, + der::Input(excluded_name.data(), excluded_name.size()))) { + return false; + } + } + for (const auto& permitted_name : permitted_subtrees_.directory_names) { + if (VerifyNameInSubtree( + name_rdn_sequence, + der::Input(permitted_name.data(), permitted_name.size()))) { + return true; + } + } + + return false; +} + +bool NameConstraints::IsPermittedIP(const IPAddressNumber& ip) const { + // If there are no name constraints for IP Address names, all names are + // accepted. + if (!(ConstrainedNameTypes() & GENERAL_NAME_IP_ADDRESS)) + return true; + + for (const auto& excluded_ip : excluded_subtrees_.ip_address_ranges) { + if (IPNumberMatchesPrefix(ip, excluded_ip.first, excluded_ip.second)) + return false; + } + for (const auto& permitted_ip : permitted_subtrees_.ip_address_ranges) { + if (IPNumberMatchesPrefix(ip, permitted_ip.first, permitted_ip.second)) + return true; + } + + return false; +} + +int NameConstraints::ConstrainedNameTypes() const { + return (permitted_subtrees_.present_name_types | + excluded_subtrees_.present_name_types); +} + +} // namespace net diff --git a/chromium/net/cert/internal/name_constraints.h b/chromium/net/cert/internal/name_constraints.h new file mode 100644 index 00000000000..46cb0dade74 --- /dev/null +++ b/chromium/net/cert/internal/name_constraints.h @@ -0,0 +1,138 @@ +// Copyright 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. + +#ifndef NET_CERT_INTERNAL_NAME_CONSTRAINTS_H_ +#define NET_CERT_INTERNAL_NAME_CONSTRAINTS_H_ + +#include <stdint.h> + +#include <vector> + +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "net/base/ip_address_number.h" + +namespace net { + +namespace der { +class Input; +} // namespace der + +// Bitfield values for the GeneralName types defined in RFC 5280. The ordering +// and exact values are not important, but match the order from the RFC for +// convenience. +enum GeneralNameTypes { + GENERAL_NAME_NONE = 0, + GENERAL_NAME_OTHER_NAME = 1 << 0, + GENERAL_NAME_RFC822_NAME = 1 << 1, + GENERAL_NAME_DNS_NAME = 1 << 2, + GENERAL_NAME_X400_ADDRESS = 1 << 3, + GENERAL_NAME_DIRECTORY_NAME = 1 << 4, + GENERAL_NAME_EDI_PARTY_NAME = 1 << 5, + GENERAL_NAME_UNIFORM_RESOURCE_IDENTIFIER = 1 << 6, + GENERAL_NAME_IP_ADDRESS = 1 << 7, + GENERAL_NAME_REGISTERED_ID = 1 << 8, +}; + +// Parses a NameConstraints extension value and allows testing whether names are +// allowed under those constraints as defined by RFC 5280 section 4.2.1.10. +class NET_EXPORT NameConstraints { + public: + // Represents a GeneralNames structure. When processing GeneralNames, it is + // often necessary to know which types of names were present, and to check + // all the names of a certain type. Therefore, a bitfield of all the name + // types is kept, and the names are split into members for each type. Only + // name types that are handled by this code are stored (though all types are + // recorded in the bitfield.) + // TODO(mattm): This may need to be split out into a public class, since + // GeneralNames is used other places in a certificate also... + struct GeneralNames { + GeneralNames(); + ~GeneralNames(); + + // ASCII hostnames. + std::vector<std::string> dns_names; + + // DER-encoded Name values (not including the Sequence tag). + std::vector<std::vector<uint8_t>> directory_names; + + // iPAddresses as sequences of octets in network byte order. This will be + // populated if the GeneralNames represents a Subject Alternative Name. + std::vector<std::vector<uint8_t>> ip_addresses; + + // iPAddress ranges, as <IP, prefix length> pairs. This will be populated + // if the GeneralNames represents a Name Constraints. + std::vector<std::pair<std::vector<uint8_t>, unsigned>> ip_address_ranges; + + // Which name types were present, as a bitfield of GeneralNameTypes. + // Includes both the supported and unsupported types (although unsupported + // ones may not be recorded depending on the context, like non-critical name + // constraints.) + int present_name_types = GENERAL_NAME_NONE; + }; + + ~NameConstraints(); + + // Parses a DER-encoded NameConstraints extension and initializes this object. + // |extension_value| should be the extnValue from the extension (not including + // the OCTET STRING tag). |is_critical| should be true if the extension was + // marked critical. Returns nullptr if parsing the the extension failed. + // The object lifetime is not bound to the lifetime of |extension_value| data. + static scoped_ptr<NameConstraints> CreateFromDer( + const der::Input& extension_value, + bool is_critical); + + // Tests if a certificate is allowed by the name constraints. + // |subject_rdn_sequence| should be the DER-encoded value of the subject's + // RDNSequence (not including Sequence tag), and may be an empty ASN.1 + // sequence. |subject_alt_name_extnvalue_tlv| should be the extnValue of the + // subjectAltName extension (including the OCTET STRING tag & length), or + // empty if the cert did not have a subjectAltName extension. + // Note that this method does not check hostname or IP address in commonName, + // which is deprecated (crbug.com/308330). + bool IsPermittedCert(const der::Input& subject_rdn_sequence, + const der::Input& subject_alt_name_extnvalue_tlv) const; + + // Returns true if the ASCII hostname |name| is permitted. + // |name| may be a wildcard hostname (starts with "*."). Eg, "*.bar.com" + // would not be permitted if "bar.com" is permitted and "foo.bar.com" is + // excluded, while "*.baz.com" would only be permitted if "baz.com" is + // permitted. + bool IsPermittedDNSName(const std::string& name) const; + + // Returns true if the directoryName |name_rdn_sequence| is permitted. + // |name_rdn_sequence| should be the DER-encoded RDNSequence value (not + // including the Sequence tag.) + bool IsPermittedDirectoryName(const der::Input& name_rdn_sequence) const; + + // Returns true if the iPAddress |ip| is permitted. + bool IsPermittedIP(const IPAddressNumber& ip) const; + + // Returns a bitfield of GeneralNameTypes of all the types constrained by this + // NameConstraints. Name types that aren't supported will only be present if + // the name constraint they appeared in was marked critical. + // + // RFC 5280 section 4.2.1.10 says: + // Applications conforming to this profile MUST be able to process name + // constraints that are imposed on the directoryName name form and SHOULD be + // able to process name constraints that are imposed on the rfc822Name, + // uniformResourceIdentifier, dNSName, and iPAddress name forms. + // If a name constraints extension that is marked as critical + // imposes constraints on a particular name form, and an instance of + // that name form appears in the subject field or subjectAltName + // extension of a subsequent certificate, then the application MUST + // either process the constraint or reject the certificate. + int ConstrainedNameTypes() const; + + private: + bool Parse(const der::Input& extension_value, + bool is_critical) WARN_UNUSED_RESULT; + + GeneralNames permitted_subtrees_; + GeneralNames excluded_subtrees_; +}; + +} // namespace net + +#endif // NET_CERT_INTERNAL_NAME_CONSTRAINTS_H_ diff --git a/chromium/net/cert/internal/name_constraints_unittest.cc b/chromium/net/cert/internal/name_constraints_unittest.cc new file mode 100644 index 00000000000..8b550f7fc94 --- /dev/null +++ b/chromium/net/cert/internal/name_constraints_unittest.cc @@ -0,0 +1,1276 @@ +// Copyright 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. + +#include "net/cert/internal/name_constraints.h" + +#include "net/cert/internal/test_helpers.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { +namespace { + +::testing::AssertionResult LoadTestData(const char* token, + const std::string& basename, + std::string* result) { + std::string path = "net/data/name_constraints_unittest/" + basename; + + const PemBlockMapping mappings[] = { + {token, result}, + }; + + return ReadTestDataFromPemFile(path, mappings); +} + +::testing::AssertionResult LoadTestName(const std::string& basename, + std::string* result) { + return LoadTestData("NAME", basename, result); +} + +::testing::AssertionResult LoadTestNameConstraint(const std::string& basename, + std::string* result) { + return LoadTestData("NAME CONSTRAINTS", basename, result); +} + +::testing::AssertionResult LoadTestSubjectAltName(const std::string& basename, + std::string* result) { + return LoadTestData("SUBJECT ALTERNATIVE NAME", basename, result); +} + +} // namespace + +class ParseNameConstraints + : public ::testing::TestWithParam<::testing::tuple<bool>> { + public: + bool is_critical() const { return ::testing::get<0>(GetParam()); } +}; + +// Run the tests with the name constraints marked critical and non-critical. For +// supported name types, the results should be the same for both. +INSTANTIATE_TEST_CASE_P(InstantiationName, + ParseNameConstraints, + ::testing::Values(true, false)); + +TEST_P(ParseNameConstraints, DNSNames) { + std::string a; + ASSERT_TRUE(LoadTestNameConstraint("dnsname.pem", &a)); + + scoped_ptr<NameConstraints> name_constraints( + NameConstraints::CreateFromDer(der::Input(&a), is_critical())); + ASSERT_TRUE(name_constraints); + + EXPECT_TRUE(name_constraints->IsPermittedDNSName("permitted.example.com")); + EXPECT_TRUE(name_constraints->IsPermittedDNSName("permitted.example.com.")); + EXPECT_TRUE(name_constraints->IsPermittedDNSName("a.permitted.example.com")); + EXPECT_FALSE(name_constraints->IsPermittedDNSName("apermitted.example.com")); + EXPECT_FALSE(name_constraints->IsPermittedDNSName("apermitted.example.com.")); + EXPECT_TRUE( + name_constraints->IsPermittedDNSName("alsopermitted.example.com")); + EXPECT_FALSE( + name_constraints->IsPermittedDNSName("excluded.permitted.example.com")); + EXPECT_FALSE( + name_constraints->IsPermittedDNSName("a.excluded.permitted.example.com")); + EXPECT_FALSE(name_constraints->IsPermittedDNSName( + "stillnotpermitted.excluded.permitted.example.com")); + EXPECT_FALSE(name_constraints->IsPermittedDNSName( + "a.stillnotpermitted.excluded.permitted.example.com")); + EXPECT_FALSE( + name_constraints->IsPermittedDNSName("extraneousexclusion.example.com")); + EXPECT_FALSE(name_constraints->IsPermittedDNSName( + "a.extraneousexclusion.example.com")); + EXPECT_FALSE(name_constraints->IsPermittedDNSName("other.example.com")); + EXPECT_FALSE(name_constraints->IsPermittedDNSName("other.com")); + + // Wildcard names: + // Pattern could match excluded.permitted.example.com, thus should not be + // allowed. + EXPECT_FALSE(name_constraints->IsPermittedDNSName("*.permitted.example.com")); + // Entirely within excluded name, obviously not allowed. + EXPECT_FALSE( + name_constraints->IsPermittedDNSName("*.excluded.permitted.example.com")); + // Within permitted.example.com and cannot match any exclusion, thus these are + // allowed. + EXPECT_TRUE( + name_constraints->IsPermittedDNSName("*.foo.permitted.example.com")); + EXPECT_TRUE( + name_constraints->IsPermittedDNSName("*.alsopermitted.example.com")); + // Matches permitted.example2.com, but also matches other .example2.com names + // which are not in either permitted or excluded, so not allowed. + EXPECT_FALSE(name_constraints->IsPermittedDNSName("*.example2.com")); + // Partial wildcards are not supported, so these name are permitted even if + // it seems like they shouldn't be. It's fine, since certificate verification + // won't treat them as wildcard names either. + EXPECT_TRUE( + name_constraints->IsPermittedDNSName("*xcluded.permitted.example.com")); + EXPECT_TRUE( + name_constraints->IsPermittedDNSName("exclude*.permitted.example.com")); + EXPECT_TRUE( + name_constraints->IsPermittedDNSName("excl*ded.permitted.example.com")); + // Garbage wildcard data. + EXPECT_FALSE(name_constraints->IsPermittedDNSName("*.")); + EXPECT_FALSE(name_constraints->IsPermittedDNSName("*.*")); + EXPECT_FALSE(name_constraints->IsPermittedDNSName(".*")); + EXPECT_FALSE(name_constraints->IsPermittedDNSName("*")); + // Matches SAN with trailing dot. + EXPECT_TRUE(name_constraints->IsPermittedDNSName("permitted.example3.com")); + EXPECT_TRUE(name_constraints->IsPermittedDNSName("permitted.example3.com.")); + EXPECT_TRUE(name_constraints->IsPermittedDNSName("a.permitted.example3.com")); + EXPECT_TRUE( + name_constraints->IsPermittedDNSName("a.permitted.example3.com.")); + + EXPECT_EQ(GENERAL_NAME_DNS_NAME, name_constraints->ConstrainedNameTypes()); + + std::string san; + ASSERT_TRUE(LoadTestSubjectAltName("san-permitted.pem", &san)); + EXPECT_TRUE( + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); + + ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-dnsname.pem", &san)); + EXPECT_FALSE( + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); + + ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-directoryname.pem", &san)); + EXPECT_TRUE( + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); + + ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-ipaddress.pem", &san)); + EXPECT_TRUE( + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); +} + +TEST_P(ParseNameConstraints, + DNSNamesWithMultipleLevelsBetweenExcludedAndPermitted) { + std::string a; + ASSERT_TRUE(LoadTestNameConstraint("dnsname2.pem", &a)); + scoped_ptr<NameConstraints> name_constraints( + NameConstraints::CreateFromDer(der::Input(&a), is_critical())); + ASSERT_TRUE(name_constraints); + + // Matches permitted exactly. + EXPECT_TRUE(name_constraints->IsPermittedDNSName("com")); + // Contained within permitted and doesn't match excluded (foo.bar.com). + EXPECT_TRUE(name_constraints->IsPermittedDNSName("bar.com")); + EXPECT_TRUE(name_constraints->IsPermittedDNSName("baz.bar.com")); + // Matches excluded exactly. + EXPECT_FALSE(name_constraints->IsPermittedDNSName("foo.bar.com")); + // Contained within excluded. + EXPECT_FALSE(name_constraints->IsPermittedDNSName("baz.foo.bar.com")); + + // Cannot match anything within excluded. + EXPECT_TRUE(name_constraints->IsPermittedDNSName("*.baz.bar.com")); + // Wildcard hostnames only match a single label, so cannot match excluded + // which has two labels before .com. + EXPECT_TRUE(name_constraints->IsPermittedDNSName("*.com")); + + // Partial match of foo.bar.com. + EXPECT_FALSE(name_constraints->IsPermittedDNSName("*.bar.com")); + // All expansions of wildcard are within excluded. + EXPECT_FALSE(name_constraints->IsPermittedDNSName("*.foo.bar.com")); +} + +TEST_P(ParseNameConstraints, DNSNamesWithLeadingDot) { + std::string a; + ASSERT_TRUE( + LoadTestNameConstraint("dnsname-permitted_with_leading_dot.pem", &a)); + scoped_ptr<NameConstraints> name_constraints( + NameConstraints::CreateFromDer(der::Input(&a), is_critical())); + ASSERT_TRUE(name_constraints); + + // dNSName constraints should be specified as a host. A dNSName constraint + // with a leading "." doesn't make sense, though some certs include it + // (probably confusing it with the rules for uniformResourceIdentifier + // constraints). It should not match anything. + EXPECT_FALSE(name_constraints->IsPermittedDNSName("com")); + EXPECT_FALSE(name_constraints->IsPermittedDNSName("bar.com")); + EXPECT_FALSE(name_constraints->IsPermittedDNSName("foo.bar.com")); +} + +TEST_P(ParseNameConstraints, DNSNamesExcludeOnly) { + std::string a; + ASSERT_TRUE(LoadTestNameConstraint("dnsname-excluded.pem", &a)); + + scoped_ptr<NameConstraints> name_constraints( + NameConstraints::CreateFromDer(der::Input(&a), is_critical())); + ASSERT_TRUE(name_constraints); + + // Only "excluded.permitted.example.com" is excluded, but since no dNSNames + // are permitted, everything is excluded. + EXPECT_FALSE(name_constraints->IsPermittedDNSName("")); + EXPECT_FALSE(name_constraints->IsPermittedDNSName("foo.com")); + EXPECT_FALSE(name_constraints->IsPermittedDNSName("permitted.example.com")); + EXPECT_FALSE( + name_constraints->IsPermittedDNSName("excluded.permitted.example.com")); + EXPECT_FALSE( + name_constraints->IsPermittedDNSName("a.excluded.permitted.example.com")); +} + +TEST_P(ParseNameConstraints, DNSNamesExcludeAll) { + std::string a; + ASSERT_TRUE(LoadTestNameConstraint("dnsname-excludeall.pem", &a)); + + scoped_ptr<NameConstraints> name_constraints( + NameConstraints::CreateFromDer(der::Input(&a), is_critical())); + ASSERT_TRUE(name_constraints); + + // "permitted.example.com" is in the permitted section, but since "" is + // excluded, nothing is permitted. + EXPECT_FALSE(name_constraints->IsPermittedDNSName("")); + EXPECT_FALSE(name_constraints->IsPermittedDNSName("foo.com")); + EXPECT_FALSE(name_constraints->IsPermittedDNSName("permitted.example.com")); + EXPECT_FALSE( + name_constraints->IsPermittedDNSName("foo.permitted.example.com")); +} + +TEST_P(ParseNameConstraints, DNSNamesExcludeDot) { + std::string a; + ASSERT_TRUE(LoadTestNameConstraint("dnsname-exclude_dot.pem", &a)); + + scoped_ptr<NameConstraints> name_constraints( + NameConstraints::CreateFromDer(der::Input(&a), is_critical())); + ASSERT_TRUE(name_constraints); + + // "." is excluded, which should match nothing. + EXPECT_FALSE(name_constraints->IsPermittedDNSName("foo.com")); + EXPECT_TRUE(name_constraints->IsPermittedDNSName("permitted.example.com")); + EXPECT_TRUE( + name_constraints->IsPermittedDNSName("foo.permitted.example.com")); +} + +TEST_P(ParseNameConstraints, DNSNamesFailOnInvalidIA5String) { + std::string a; + ASSERT_TRUE(LoadTestNameConstraint("dnsname.pem", &a)); + + size_t replace_location = a.find("permitted.example2.com"); + ASSERT_NE(std::string::npos, replace_location); + a.replace(replace_location, 1, 1, -1); + + EXPECT_FALSE(NameConstraints::CreateFromDer(der::Input(&a), is_critical())); +} + +TEST_P(ParseNameConstraints, DirectoryNames) { + std::string constraints_der; + ASSERT_TRUE(LoadTestNameConstraint("directoryname.pem", &constraints_der)); + + std::string name_us; + ASSERT_TRUE(LoadTestName("name-us.pem", &name_us)); + std::string name_us_ca; + ASSERT_TRUE(LoadTestName("name-us-california.pem", &name_us_ca)); + std::string name_us_ca_mountain_view; + ASSERT_TRUE(LoadTestName("name-us-california-mountain_view.pem", + &name_us_ca_mountain_view)); + std::string name_us_az; + ASSERT_TRUE(LoadTestName("name-us-arizona.pem", &name_us_az)); + std::string name_jp; + ASSERT_TRUE(LoadTestName("name-jp.pem", &name_jp)); + std::string name_jp_tokyo; + ASSERT_TRUE(LoadTestName("name-jp-tokyo.pem", &name_jp_tokyo)); + std::string name_de; + ASSERT_TRUE(LoadTestName("name-de.pem", &name_de)); + std::string name_ca; + ASSERT_TRUE(LoadTestName("name-ca.pem", &name_ca)); + + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + // Not in any permitted subtree. + EXPECT_FALSE(name_constraints->IsPermittedDirectoryName( + SequenceValueFromString(&name_ca))); + // Within the permitted C=US subtree. + EXPECT_TRUE(name_constraints->IsPermittedDirectoryName( + SequenceValueFromString(&name_us))); + // Within the permitted C=US subtree. + EXPECT_TRUE(name_constraints->IsPermittedDirectoryName( + SequenceValueFromString(&name_us_az))); + // Within the permitted C=US subtree, however the excluded C=US,ST=California + // subtree takes priority. + EXPECT_FALSE(name_constraints->IsPermittedDirectoryName( + SequenceValueFromString(&name_us_ca))); + // Within the permitted C=US subtree as well as the permitted + // C=US,ST=California,L=Mountain View subtree, however the excluded + // C=US,ST=California subtree still takes priority. + EXPECT_FALSE(name_constraints->IsPermittedDirectoryName( + SequenceValueFromString(&name_us_ca_mountain_view))); + // Not in any permitted subtree, and also inside the extraneous excluded C=DE + // subtree. + EXPECT_FALSE(name_constraints->IsPermittedDirectoryName( + SequenceValueFromString(&name_de))); + // Not in any permitted subtree. + EXPECT_FALSE(name_constraints->IsPermittedDirectoryName( + SequenceValueFromString(&name_jp))); + // Within the permitted C=JP,ST=Tokyo subtree. + EXPECT_TRUE(name_constraints->IsPermittedDirectoryName( + SequenceValueFromString(&name_jp_tokyo))); + + EXPECT_EQ(GENERAL_NAME_DIRECTORY_NAME, + name_constraints->ConstrainedNameTypes()); + + // Within the permitted C=US subtree. + EXPECT_TRUE(name_constraints->IsPermittedCert( + SequenceValueFromString(&name_us), der::Input())); + // Within the permitted C=US subtree, however the excluded C=US,ST=California + // subtree takes priority. + EXPECT_FALSE(name_constraints->IsPermittedCert( + SequenceValueFromString(&name_us_ca), der::Input())); + + std::string san; + ASSERT_TRUE(LoadTestSubjectAltName("san-permitted.pem", &san)); + EXPECT_TRUE( + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); + + ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-dnsname.pem", &san)); + EXPECT_TRUE( + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); + + ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-directoryname.pem", &san)); + EXPECT_FALSE( + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); + + ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-ipaddress.pem", &san)); + EXPECT_TRUE( + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); +} + +TEST_P(ParseNameConstraints, DirectoryNamesExcludeOnly) { + std::string constraints_der; + ASSERT_TRUE( + LoadTestNameConstraint("directoryname-excluded.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + std::string name_empty; + ASSERT_TRUE(LoadTestName("name-empty.pem", &name_empty)); + std::string name_us; + ASSERT_TRUE(LoadTestName("name-us.pem", &name_us)); + std::string name_us_ca; + ASSERT_TRUE(LoadTestName("name-us-california.pem", &name_us_ca)); + std::string name_us_ca_mountain_view; + ASSERT_TRUE(LoadTestName("name-us-california-mountain_view.pem", + &name_us_ca_mountain_view)); + + // Only "C=US,ST=California" is excluded, but since no directoryNames are + // permitted, everything is excluded. + EXPECT_FALSE(name_constraints->IsPermittedDirectoryName( + SequenceValueFromString(&name_empty))); + EXPECT_FALSE(name_constraints->IsPermittedDirectoryName( + SequenceValueFromString(&name_us))); + EXPECT_FALSE(name_constraints->IsPermittedDirectoryName( + SequenceValueFromString(&name_us_ca))); + EXPECT_FALSE(name_constraints->IsPermittedDirectoryName( + SequenceValueFromString(&name_us_ca_mountain_view))); +} + +TEST_P(ParseNameConstraints, DirectoryNamesExcludeAll) { + std::string constraints_der; + ASSERT_TRUE( + LoadTestNameConstraint("directoryname-excluded.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + std::string name_empty; + ASSERT_TRUE(LoadTestName("name-empty.pem", &name_empty)); + std::string name_us; + ASSERT_TRUE(LoadTestName("name-us.pem", &name_us)); + std::string name_us_ca; + ASSERT_TRUE(LoadTestName("name-us-california.pem", &name_us_ca)); + std::string name_us_ca_mountain_view; + ASSERT_TRUE(LoadTestName("name-us-california-mountain_view.pem", + &name_us_ca_mountain_view)); + std::string name_jp; + ASSERT_TRUE(LoadTestName("name-jp.pem", &name_jp)); + + // "C=US" is in the permitted section, but since an empty + // directoryName is excluded, nothing is permitted. + EXPECT_FALSE(name_constraints->IsPermittedDirectoryName( + SequenceValueFromString(&name_empty))); + EXPECT_FALSE(name_constraints->IsPermittedDirectoryName( + SequenceValueFromString(&name_us))); + EXPECT_FALSE(name_constraints->IsPermittedDirectoryName( + SequenceValueFromString(&name_us_ca))); + EXPECT_FALSE(name_constraints->IsPermittedDirectoryName( + SequenceValueFromString(&name_jp))); +} + +TEST_P(ParseNameConstraints, IPAdresses) { + std::string a; + ASSERT_TRUE(LoadTestNameConstraint("ipaddress.pem", &a)); + + scoped_ptr<NameConstraints> name_constraints( + NameConstraints::CreateFromDer(der::Input(&a), is_critical())); + ASSERT_TRUE(name_constraints); + + // IPv4 tests: + { + // Not in any permitted range. + const uint8_t ip4[] = {192, 169, 0, 1}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + // Within the permitted 192.168.0.0/255.255.0.0 range. + const uint8_t ip4[] = {192, 168, 0, 1}; + EXPECT_TRUE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + // Within the permitted 192.168.0.0/255.255.0.0 range, however the + // excluded 192.168.5.0/255.255.255.0 takes priority. + const uint8_t ip4[] = {192, 168, 5, 1}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + // Within the permitted 192.168.0.0/255.255.0.0 range as well as the + // permitted 192.168.5.32/255.255.255.224 range, however the excluded + // 192.168.5.0/255.255.255.0 still takes priority. + const uint8_t ip4[] = {192, 168, 5, 33}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + // Not in any permitted range. (Just outside the + // 192.167.5.32/255.255.255.224 range.) + const uint8_t ip4[] = {192, 167, 5, 31}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + // Within the permitted 192.167.5.32/255.255.255.224 range. + const uint8_t ip4[] = {192, 167, 5, 32}; + EXPECT_TRUE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + // Within the permitted 192.167.5.32/255.255.255.224 range. + const uint8_t ip4[] = {192, 167, 5, 63}; + EXPECT_TRUE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + // Not in any permitted range. (Just outside the + // 192.167.5.32/255.255.255.224 range.) + const uint8_t ip4[] = {192, 167, 5, 64}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + // Not in any permitted range, and also inside the extraneous excluded + // 192.166.5.32/255.255.255.224 range. + const uint8_t ip4[] = {192, 166, 5, 32}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + + // IPv6 tests: + { + // Not in any permitted range. + const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 0, 0, 0, 1}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip6, ip6 + arraysize(ip6)))); + } + { + // Within the permitted + // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: range. + const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 0, 1}; + EXPECT_TRUE(name_constraints->IsPermittedIP( + IPAddressNumber(ip6, ip6 + arraysize(ip6)))); + } + { + // Within the permitted + // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: range, however + // the excluded + // 102:304:506:708:90a:b0c:500:0/ffff:ffff:ffff:ffff:ffff:ffff:ff00:0 takes + // priority. + const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 5, 0, 0, 1}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip6, ip6 + arraysize(ip6)))); + } + { + // Within the permitted + // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: range as well + // as the permitted + // 102:304:506:708:90a:b0c:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0, + // however the excluded + // 102:304:506:708:90a:b0c:500:0/ffff:ffff:ffff:ffff:ffff:ffff:ff00:0 takes + // priority. + const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 5, 33, 0, 1}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip6, ip6 + arraysize(ip6)))); + } + { + // Not in any permitted range. (Just outside the + // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 + // range.) + const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 11, 5, 31, 255, 255}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip6, ip6 + arraysize(ip6)))); + } + { + // Within the permitted + // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 range. + const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 5, 32, 0, 0}; + EXPECT_TRUE(name_constraints->IsPermittedIP( + IPAddressNumber(ip6, ip6 + arraysize(ip6)))); + } + { + // Within the permitted + // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 range. + const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 11, 5, 63, 255, 255}; + EXPECT_TRUE(name_constraints->IsPermittedIP( + IPAddressNumber(ip6, ip6 + arraysize(ip6)))); + } + { + // Not in any permitted range. (Just outside the + // 102:304:506:708:90a:b0b:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 + // range.) + const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 5, 64, 0, 0}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip6, ip6 + arraysize(ip6)))); + } + { + // Not in any permitted range, and also inside the extraneous excluded + // 102:304:506:708:90a:b0a:520:0/ffff:ffff:ffff:ffff:ffff:ffff:ff60:0 range. + const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 10, 5, 33, 0, 1}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip6, ip6 + arraysize(ip6)))); + } + + EXPECT_EQ(GENERAL_NAME_IP_ADDRESS, name_constraints->ConstrainedNameTypes()); + + std::string san; + ASSERT_TRUE(LoadTestSubjectAltName("san-permitted.pem", &san)); + EXPECT_TRUE( + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); + + ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-dnsname.pem", &san)); + EXPECT_TRUE( + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); + + ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-directoryname.pem", &san)); + EXPECT_TRUE( + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); + + ASSERT_TRUE(LoadTestSubjectAltName("san-excluded-ipaddress.pem", &san)); + EXPECT_FALSE( + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); +} + +TEST_P(ParseNameConstraints, IPAdressesExcludeOnly) { + std::string a; + ASSERT_TRUE(LoadTestNameConstraint("ipaddress-excluded.pem", &a)); + + scoped_ptr<NameConstraints> name_constraints( + NameConstraints::CreateFromDer(der::Input(&a), is_critical())); + ASSERT_TRUE(name_constraints); + + // Only 192.168.5.0/255.255.255.0 is excluded, but since no iPAddresses + // are permitted, everything is excluded. + { + const uint8_t ip4[] = {192, 168, 0, 1}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip4[] = {192, 168, 5, 1}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 0, 0, 0, 1}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip6, ip6 + arraysize(ip6)))); + } +} + +TEST_P(ParseNameConstraints, IPAdressesExcludeAll) { + std::string a; + ASSERT_TRUE(LoadTestNameConstraint("ipaddress-excludeall.pem", &a)); + + scoped_ptr<NameConstraints> name_constraints( + NameConstraints::CreateFromDer(der::Input(&a), is_critical())); + ASSERT_TRUE(name_constraints); + + // 192.168.0.0/255.255.0.0 and + // 102:304:506:708:90a:b0c::/ffff:ffff:ffff:ffff:ffff:ffff:: are permitted, + // but since 0.0.0.0/0 and ::/0 are excluded nothing is permitted. + { + const uint8_t ip4[] = {192, 168, 0, 1}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip4[] = {1, 1, 1, 1}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip6[] = {2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip6, ip6 + arraysize(ip6)))); + } + { + const uint8_t ip6[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 0, 0, 0, 1}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip6, ip6 + arraysize(ip6)))); + } +} + +TEST_P(ParseNameConstraints, IPAdressesNetmaskPermitSingleHost) { + std::string a; + ASSERT_TRUE(LoadTestNameConstraint("ipaddress-permit_singlehost.pem", &a)); + + scoped_ptr<NameConstraints> name_constraints( + NameConstraints::CreateFromDer(der::Input(&a), is_critical())); + ASSERT_TRUE(name_constraints); + + { + const uint8_t ip4[] = {0, 0, 0, 0}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip4[] = {192, 168, 1, 1}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip4[] = {192, 168, 1, 2}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip4[] = {192, 168, 1, 3}; + EXPECT_TRUE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip4[] = {192, 168, 1, 4}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip4[] = {255, 255, 255, 255}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } +} + +TEST_P(ParseNameConstraints, IPAdressesNetmaskPermitPrefixLen31) { + std::string a; + ASSERT_TRUE(LoadTestNameConstraint("ipaddress-permit_prefix31.pem", &a)); + + scoped_ptr<NameConstraints> name_constraints( + NameConstraints::CreateFromDer(der::Input(&a), is_critical())); + ASSERT_TRUE(name_constraints); + + { + const uint8_t ip4[] = {0, 0, 0, 0}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip4[] = {192, 168, 1, 1}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip4[] = {192, 168, 1, 2}; + EXPECT_TRUE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip4[] = {192, 168, 1, 3}; + EXPECT_TRUE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip4[] = {192, 168, 1, 4}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip4[] = {192, 168, 1, 5}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip4[] = {255, 255, 255, 255}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } +} + +TEST_P(ParseNameConstraints, IPAdressesNetmaskPermitPrefixLen1) { + std::string a; + ASSERT_TRUE(LoadTestNameConstraint("ipaddress-permit_prefix1.pem", &a)); + + scoped_ptr<NameConstraints> name_constraints( + NameConstraints::CreateFromDer(der::Input(&a), is_critical())); + ASSERT_TRUE(name_constraints); + + { + const uint8_t ip4[] = {0, 0, 0, 0}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip4[] = {0x7F, 0xFF, 0xFF, 0xFF}; + EXPECT_FALSE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip4[] = {0x80, 0, 0, 0}; + EXPECT_TRUE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip4[] = {0xFF, 0xFF, 0xFF, 0xFF}; + EXPECT_TRUE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } +} + +TEST_P(ParseNameConstraints, IPAdressesNetmaskPermitAll) { + std::string a; + ASSERT_TRUE(LoadTestNameConstraint("ipaddress-permit_all.pem", &a)); + + scoped_ptr<NameConstraints> name_constraints( + NameConstraints::CreateFromDer(der::Input(&a), is_critical())); + ASSERT_TRUE(name_constraints); + + { + const uint8_t ip4[] = {0, 0, 0, 0}; + EXPECT_TRUE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip4[] = {192, 168, 1, 1}; + EXPECT_TRUE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } + { + const uint8_t ip4[] = {255, 255, 255, 255}; + EXPECT_TRUE(name_constraints->IsPermittedIP( + IPAddressNumber(ip4, ip4 + arraysize(ip4)))); + } +} + +TEST_P(ParseNameConstraints, IPAdressesFailOnInvalidAddr) { + std::string a; + ASSERT_TRUE(LoadTestNameConstraint("ipaddress-invalid_addr.pem", &a)); + + EXPECT_FALSE(NameConstraints::CreateFromDer(der::Input(&a), is_critical())); +} + +TEST_P(ParseNameConstraints, IPAdressesFailOnInvalidMaskNotContiguous) { + std::string a; + ASSERT_TRUE(LoadTestNameConstraint( + "ipaddress-invalid_mask_not_contiguous_1.pem", &a)); + EXPECT_FALSE(NameConstraints::CreateFromDer(der::Input(&a), is_critical())); + + ASSERT_TRUE(LoadTestNameConstraint( + "ipaddress-invalid_mask_not_contiguous_2.pem", &a)); + EXPECT_FALSE(NameConstraints::CreateFromDer(der::Input(&a), is_critical())); + + ASSERT_TRUE(LoadTestNameConstraint( + "ipaddress-invalid_mask_not_contiguous_3.pem", &a)); + EXPECT_FALSE(NameConstraints::CreateFromDer(der::Input(&a), is_critical())); + + ASSERT_TRUE(LoadTestNameConstraint( + "ipaddress-invalid_mask_not_contiguous_4.pem", &a)); + EXPECT_FALSE(NameConstraints::CreateFromDer(der::Input(&a), is_critical())); +} + +TEST_P(ParseNameConstraints, OtherNamesInPermitted) { + std::string constraints_der; + ASSERT_TRUE( + LoadTestNameConstraint("othername-permitted.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + if (is_critical()) { + EXPECT_EQ(GENERAL_NAME_OTHER_NAME, + name_constraints->ConstrainedNameTypes()); + } else { + EXPECT_EQ(0, name_constraints->ConstrainedNameTypes()); + } + + std::string san; + ASSERT_TRUE(LoadTestSubjectAltName("san-othername.pem", &san)); + EXPECT_EQ(!is_critical(), + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); +} + +TEST_P(ParseNameConstraints, OtherNamesInExcluded) { + std::string constraints_der; + ASSERT_TRUE( + LoadTestNameConstraint("othername-excluded.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + if (is_critical()) { + EXPECT_EQ(GENERAL_NAME_OTHER_NAME, + name_constraints->ConstrainedNameTypes()); + } else { + EXPECT_EQ(0, name_constraints->ConstrainedNameTypes()); + } + + std::string san; + ASSERT_TRUE(LoadTestSubjectAltName("san-othername.pem", &san)); + EXPECT_EQ(!is_critical(), + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); +} + +TEST_P(ParseNameConstraints, Rfc822NamesInPermitted) { + std::string constraints_der; + ASSERT_TRUE( + LoadTestNameConstraint("rfc822name-permitted.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + if (is_critical()) { + EXPECT_EQ(GENERAL_NAME_RFC822_NAME, + name_constraints->ConstrainedNameTypes()); + } else { + EXPECT_EQ(0, name_constraints->ConstrainedNameTypes()); + } + + std::string san; + ASSERT_TRUE(LoadTestSubjectAltName("san-rfc822name.pem", &san)); + EXPECT_EQ(!is_critical(), + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); +} + +TEST_P(ParseNameConstraints, Rfc822NamesInExcluded) { + std::string constraints_der; + ASSERT_TRUE( + LoadTestNameConstraint("rfc822name-excluded.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + if (is_critical()) { + EXPECT_EQ(GENERAL_NAME_RFC822_NAME, + name_constraints->ConstrainedNameTypes()); + } else { + EXPECT_EQ(0, name_constraints->ConstrainedNameTypes()); + } + + std::string san; + ASSERT_TRUE(LoadTestSubjectAltName("san-rfc822name.pem", &san)); + EXPECT_EQ(!is_critical(), + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); +} + +TEST_P(ParseNameConstraints, X400AddresssInPermitted) { + std::string constraints_der; + ASSERT_TRUE( + LoadTestNameConstraint("x400address-permitted.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + if (is_critical()) { + EXPECT_EQ(GENERAL_NAME_X400_ADDRESS, + name_constraints->ConstrainedNameTypes()); + } else { + EXPECT_EQ(0, name_constraints->ConstrainedNameTypes()); + } + + std::string san; + ASSERT_TRUE(LoadTestSubjectAltName("san-x400address.pem", &san)); + EXPECT_EQ(!is_critical(), + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); +} + +TEST_P(ParseNameConstraints, X400AddresssInExcluded) { + std::string constraints_der; + ASSERT_TRUE( + LoadTestNameConstraint("x400address-excluded.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + if (is_critical()) { + EXPECT_EQ(GENERAL_NAME_X400_ADDRESS, + name_constraints->ConstrainedNameTypes()); + } else { + EXPECT_EQ(0, name_constraints->ConstrainedNameTypes()); + } + + std::string san; + ASSERT_TRUE(LoadTestSubjectAltName("san-x400address.pem", &san)); + EXPECT_EQ(!is_critical(), + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); +} + +TEST_P(ParseNameConstraints, EdiPartyNamesInPermitted) { + std::string constraints_der; + ASSERT_TRUE( + LoadTestNameConstraint("edipartyname-permitted.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + if (is_critical()) { + EXPECT_EQ(GENERAL_NAME_EDI_PARTY_NAME, + name_constraints->ConstrainedNameTypes()); + } else { + EXPECT_EQ(0, name_constraints->ConstrainedNameTypes()); + } + + std::string san; + ASSERT_TRUE(LoadTestSubjectAltName("san-edipartyname.pem", &san)); + EXPECT_EQ(!is_critical(), + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); +} + +TEST_P(ParseNameConstraints, EdiPartyNamesInExcluded) { + std::string constraints_der; + ASSERT_TRUE( + LoadTestNameConstraint("edipartyname-excluded.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + if (is_critical()) { + EXPECT_EQ(GENERAL_NAME_EDI_PARTY_NAME, + name_constraints->ConstrainedNameTypes()); + } else { + EXPECT_EQ(0, name_constraints->ConstrainedNameTypes()); + } + + std::string san; + ASSERT_TRUE(LoadTestSubjectAltName("san-edipartyname.pem", &san)); + EXPECT_EQ(!is_critical(), + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); +} + +TEST_P(ParseNameConstraints, URIsInPermitted) { + std::string constraints_der; + ASSERT_TRUE(LoadTestNameConstraint("uri-permitted.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + if (is_critical()) { + EXPECT_EQ(GENERAL_NAME_UNIFORM_RESOURCE_IDENTIFIER, + name_constraints->ConstrainedNameTypes()); + } else { + EXPECT_EQ(0, name_constraints->ConstrainedNameTypes()); + } + + std::string san; + ASSERT_TRUE(LoadTestSubjectAltName("san-uri.pem", &san)); + EXPECT_EQ(!is_critical(), + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); +} + +TEST_P(ParseNameConstraints, URIsInExcluded) { + std::string constraints_der; + ASSERT_TRUE(LoadTestNameConstraint("uri-excluded.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + if (is_critical()) { + EXPECT_EQ(GENERAL_NAME_UNIFORM_RESOURCE_IDENTIFIER, + name_constraints->ConstrainedNameTypes()); + } else { + EXPECT_EQ(0, name_constraints->ConstrainedNameTypes()); + } + + std::string san; + ASSERT_TRUE(LoadTestSubjectAltName("san-uri.pem", &san)); + EXPECT_EQ(!is_critical(), + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); +} + +TEST_P(ParseNameConstraints, RegisteredIDsInPermitted) { + std::string constraints_der; + ASSERT_TRUE( + LoadTestNameConstraint("registeredid-permitted.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + if (is_critical()) { + EXPECT_EQ(GENERAL_NAME_REGISTERED_ID, + name_constraints->ConstrainedNameTypes()); + } else { + EXPECT_EQ(0, name_constraints->ConstrainedNameTypes()); + } + + std::string san; + ASSERT_TRUE(LoadTestSubjectAltName("san-registeredid.pem", &san)); + EXPECT_EQ(!is_critical(), + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); +} + +TEST_P(ParseNameConstraints, RegisteredIDsInExcluded) { + std::string constraints_der; + ASSERT_TRUE( + LoadTestNameConstraint("registeredid-excluded.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + if (is_critical()) { + EXPECT_EQ(GENERAL_NAME_REGISTERED_ID, + name_constraints->ConstrainedNameTypes()); + } else { + EXPECT_EQ(0, name_constraints->ConstrainedNameTypes()); + } + + std::string san; + ASSERT_TRUE(LoadTestSubjectAltName("san-registeredid.pem", &san)); + EXPECT_EQ(!is_critical(), + name_constraints->IsPermittedCert(der::Input(), der::Input(&san))); +} + +TEST_P(ParseNameConstraints, + failsOnGeneralSubtreeWithMinimumZeroEncodedUnnecessarily) { + std::string constraints_der; + ASSERT_TRUE( + LoadTestNameConstraint("dnsname-with_min_0.pem", &constraints_der)); + // The value should not be in the DER encoding if it is the default. But this + // could be changed to allowed if there are buggy encoders out there that + // include it anyway. + EXPECT_FALSE(NameConstraints::CreateFromDer(der::Input(&constraints_der), + is_critical())); +} + +TEST_P(ParseNameConstraints, FailsOnGeneralSubtreeWithMinimum) { + std::string constraints_der; + ASSERT_TRUE( + LoadTestNameConstraint("dnsname-with_min_1.pem", &constraints_der)); + EXPECT_FALSE(NameConstraints::CreateFromDer(der::Input(&constraints_der), + is_critical())); +} + +TEST_P(ParseNameConstraints, + failsOnGeneralSubtreeWithMinimumZeroEncodedUnnecessarilyAndMaximum) { + std::string constraints_der; + ASSERT_TRUE(LoadTestNameConstraint("dnsname-with_min_0_and_max.pem", + &constraints_der)); + EXPECT_FALSE(NameConstraints::CreateFromDer(der::Input(&constraints_der), + is_critical())); +} + +TEST_P(ParseNameConstraints, FailsOnGeneralSubtreeWithMinimumAndMaximum) { + std::string constraints_der; + ASSERT_TRUE(LoadTestNameConstraint("dnsname-with_min_1_and_max.pem", + &constraints_der)); + EXPECT_FALSE(NameConstraints::CreateFromDer(der::Input(&constraints_der), + is_critical())); +} + +TEST_P(ParseNameConstraints, FailsOnGeneralSubtreeWithMaximum) { + std::string constraints_der; + ASSERT_TRUE(LoadTestNameConstraint("dnsname-with_max.pem", &constraints_der)); + EXPECT_FALSE(NameConstraints::CreateFromDer(der::Input(&constraints_der), + is_critical())); +} + +TEST_P(ParseNameConstraints, FailsOnEmptyExtensionValue) { + std::string constraints_der = ""; + EXPECT_FALSE(NameConstraints::CreateFromDer(der::Input(&constraints_der), + is_critical())); +} + +TEST_P(ParseNameConstraints, FailsOnNoPermittedAndExcluded) { + std::string constraints_der; + ASSERT_TRUE( + LoadTestNameConstraint("invalid-no_subtrees.pem", &constraints_der)); + EXPECT_FALSE(NameConstraints::CreateFromDer(der::Input(&constraints_der), + is_critical())); +} + +TEST_P(ParseNameConstraints, FailsOnEmptyPermitted) { + std::string constraints_der; + ASSERT_TRUE(LoadTestNameConstraint("invalid-empty_permitted_subtree.pem", + &constraints_der)); + EXPECT_FALSE(NameConstraints::CreateFromDer(der::Input(&constraints_der), + is_critical())); +} + +TEST_P(ParseNameConstraints, FailsOnEmptyExcluded) { + std::string constraints_der; + ASSERT_TRUE(LoadTestNameConstraint("invalid-empty_excluded_subtree.pem", + &constraints_der)); + EXPECT_FALSE(NameConstraints::CreateFromDer(der::Input(&constraints_der), + is_critical())); +} + +TEST_P(ParseNameConstraints, IsPermittedCertSubjectEmailAddressIsOk) { + std::string constraints_der; + ASSERT_TRUE(LoadTestNameConstraint("directoryname.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + std::string name_us_arizona_email; + ASSERT_TRUE( + LoadTestName("name-us-arizona-email.pem", &name_us_arizona_email)); + + // Name constraints don't contain rfc822Name, so emailAddress in subject is + // allowed regardless. + EXPECT_TRUE(name_constraints->IsPermittedCert( + SequenceValueFromString(&name_us_arizona_email), der::Input())); +} + +TEST_P(ParseNameConstraints, IsPermittedCertSubjectEmailAddressIsNotOk) { + std::string constraints_der; + ASSERT_TRUE( + LoadTestNameConstraint("rfc822name-permitted.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + std::string name_us_arizona_email; + ASSERT_TRUE( + LoadTestName("name-us-arizona-email.pem", &name_us_arizona_email)); + + // Name constraints contain rfc822Name, so emailAddress in subject is not + // allowed if the constraints were critical. + EXPECT_EQ(!is_critical(), + name_constraints->IsPermittedCert( + SequenceValueFromString(&name_us_arizona_email), der::Input())); +} + +// Hostname in commonName is not allowed (crbug.com/308330), so these are tests +// are not particularly interesting, just verifying that the commonName is +// ignored for dNSName constraints. +TEST_P(ParseNameConstraints, IsPermittedCertSubjectDnsNames) { + std::string constraints_der; + ASSERT_TRUE(LoadTestNameConstraint("directoryname_and_dnsname.pem", + &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + std::string name_us_az_foocom; + ASSERT_TRUE(LoadTestName("name-us-arizona-foo.com.pem", &name_us_az_foocom)); + // The subject is within permitted directoryName constraints, so permitted. + // (The commonName hostname is not within permitted dNSName constraints, so + // this would not be permitted if hostnames in commonName were checked.) + EXPECT_TRUE(name_constraints->IsPermittedCert( + SequenceValueFromString(&name_us_az_foocom), der::Input())); + + std::string name_us_az_permitted; + ASSERT_TRUE(LoadTestName("name-us-arizona-permitted.example.com.pem", + &name_us_az_permitted)); + // The subject is in permitted directoryName and the commonName is within + // permitted dNSName constraints, so this should be permitted regardless if + // hostnames in commonName are checked or not. + EXPECT_TRUE(name_constraints->IsPermittedCert( + SequenceValueFromString(&name_us_az_permitted), der::Input())); + + std::string name_us_ca_permitted; + ASSERT_TRUE(LoadTestName("name-us-california-permitted.example.com.pem", + &name_us_ca_permitted)); + // The subject is within the excluded C=US,ST=California directoryName, so + // this should not be allowed, regardless of checking the + // permitted.example.com in commonName. + EXPECT_FALSE(name_constraints->IsPermittedCert( + SequenceValueFromString(&name_us_ca_permitted), der::Input())); +} + +// IP addresses in commonName are not allowed (crbug.com/308330), so these are +// tests are not particularly interesting, just verifying that the commonName is +// ignored for iPAddress constraints. +TEST_P(ParseNameConstraints, IsPermittedCertSubjectIpAddresses) { + std::string constraints_der; + ASSERT_TRUE(LoadTestNameConstraint( + "directoryname_and_dnsname_and_ipaddress.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + std::string name_us_az_1_1_1_1; + ASSERT_TRUE(LoadTestName("name-us-arizona-1.1.1.1.pem", &name_us_az_1_1_1_1)); + // The subject is within permitted directoryName constraints, so permitted. + // (The commonName IP address is not within permitted iPAddresses constraints, + // so this would not be permitted if IP addresses in commonName were checked.) + EXPECT_TRUE(name_constraints->IsPermittedCert( + SequenceValueFromString(&name_us_az_1_1_1_1), der::Input())); + + std::string name_us_az_192_168_1_1; + ASSERT_TRUE( + LoadTestName("name-us-arizona-192.168.1.1.pem", &name_us_az_192_168_1_1)); + // The subject is in permitted directoryName and the commonName is within + // permitted iPAddress constraints, so this should be permitted regardless if + // IP addresses in commonName are checked or not. + EXPECT_TRUE(name_constraints->IsPermittedCert( + SequenceValueFromString(&name_us_az_192_168_1_1), der::Input())); + + std::string name_us_ca_192_168_1_1; + ASSERT_TRUE(LoadTestName("name-us-california-192.168.1.1.pem", + &name_us_ca_192_168_1_1)); + // The subject is within the excluded C=US,ST=California directoryName, so + // this should not be allowed, regardless of checking the + // IP address in commonName. + EXPECT_FALSE(name_constraints->IsPermittedCert( + SequenceValueFromString(&name_us_ca_192_168_1_1), der::Input())); + + std::string name_us_az_ipv6; + ASSERT_TRUE(LoadTestName("name-us-arizona-ipv6.pem", &name_us_az_ipv6)); + // The subject is within permitted directoryName constraints, so permitted. + // (The commonName is an ipv6 address which wasn't supported in the past, but + // since commonName checking is ignored entirely, this is permitted.) + EXPECT_TRUE(name_constraints->IsPermittedCert( + SequenceValueFromString(&name_us_az_ipv6), der::Input())); +} + +TEST_P(ParseNameConstraints, IsPermittedCertFailsOnEmptySubjectAltName) { + std::string constraints_der; + ASSERT_TRUE(LoadTestNameConstraint("dnsname.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + std::string name_us_az; + ASSERT_TRUE(LoadTestName("name-us-arizona.pem", &name_us_az)); + + // No constraints on directoryName type, so name_us_az should be allowed when + // subjectAltName is not present. + EXPECT_TRUE(name_constraints->IsPermittedCert( + SequenceValueFromString(&name_us_az), der::Input())); + + std::string san; + ASSERT_TRUE(LoadTestSubjectAltName("san-invalid-empty.pem", &san)); + // Should fail if subjectAltName is present but empty. + EXPECT_FALSE(name_constraints->IsPermittedCert( + SequenceValueFromString(&name_us_az), der::Input(&san))); +} + +TEST_P(ParseNameConstraints, IsPermittedCertFailsOnInvalidIpInSubjectAltName) { + std::string constraints_der; + ASSERT_TRUE(LoadTestNameConstraint("ipaddress.pem", &constraints_der)); + scoped_ptr<NameConstraints> name_constraints(NameConstraints::CreateFromDer( + der::Input(&constraints_der), is_critical())); + ASSERT_TRUE(name_constraints); + + std::string name_us_az_192_168_1_1; + ASSERT_TRUE( + LoadTestName("name-us-arizona-192.168.1.1.pem", &name_us_az_192_168_1_1)); + + // Without the invalid subjectAltName, it passes. + EXPECT_TRUE(name_constraints->IsPermittedCert( + SequenceValueFromString(&name_us_az_192_168_1_1), der::Input())); + + std::string san; + ASSERT_TRUE(LoadTestSubjectAltName("san-invalid-ipaddress.pem", &san)); + // Should fail if subjectAltName contains an invalid ip address. + EXPECT_FALSE(name_constraints->IsPermittedCert( + SequenceValueFromString(&name_us_az_192_168_1_1), der::Input(&san))); +} + +} // namespace net diff --git a/chromium/net/cert/internal/parse_certificate.cc b/chromium/net/cert/internal/parse_certificate.cc index 9535459bb8a..74222e8fde0 100644 --- a/chromium/net/cert/internal/parse_certificate.cc +++ b/chromium/net/cert/internal/parse_certificate.cc @@ -4,6 +4,8 @@ #include "net/cert/internal/parse_certificate.h" +#include <utility> + #include "net/der/input.h" #include "net/der/parse_values.h" #include "net/der/parser.h" @@ -172,6 +174,17 @@ bool ParseValidity(const der::Input& validity_tlv, return true; } +// Returns true if every bit in |bits| is zero (including empty). +WARN_UNUSED_RESULT bool BitStringIsAllZeros(const der::BitString& bits) { + // Note that it is OK to read from the unused bits, since BitString parsing + // guarantees they are all zero. + for (size_t i = 0; i < bits.bytes().Length(); ++i) { + if (bits.bytes().UnsafeData()[i] != 0) + return false; + } + return true; +} + } // namespace ParsedTbsCertificate::ParsedTbsCertificate() {} @@ -353,4 +366,238 @@ bool ParseTbsCertificate(const der::Input& tbs_tlv, ParsedTbsCertificate* out) { return true; } +// From RFC 5280: +// +// Extension ::= SEQUENCE { +// extnID OBJECT IDENTIFIER, +// critical BOOLEAN DEFAULT FALSE, +// extnValue OCTET STRING +// -- contains the DER encoding of an ASN.1 value +// -- corresponding to the extension type identified +// -- by extnID +// } +bool ParseExtension(const der::Input& extension_tlv, ParsedExtension* out) { + der::Parser parser(extension_tlv); + + // Extension ::= SEQUENCE { + der::Parser extension_parser; + if (!parser.ReadSequence(&extension_parser)) + return false; + + // extnID OBJECT IDENTIFIER, + if (!extension_parser.ReadTag(der::kOid, &out->oid)) + return false; + + // critical BOOLEAN DEFAULT FALSE, + out->critical = false; + bool has_critical; + der::Input critical; + if (!extension_parser.ReadOptionalTag(der::kBool, &critical, &has_critical)) + return false; + if (has_critical) { + if (!der::ParseBool(critical, &out->critical)) + return false; + if (!out->critical) + return false; // DER-encoding requires DEFAULT values be omitted. + } + + // extnValue OCTET STRING + if (!extension_parser.ReadTag(der::kOctetString, &out->value)) + return false; + + // The Extension type does not have an extension point (everything goes in + // extnValue). + if (extension_parser.HasMore()) + return false; + + // By definition the input was a single Extension sequence, so there shouldn't + // be unconsumed data. + if (parser.HasMore()) + return false; + + return true; +} + +der::Input KeyUsageOid() { + // From RFC 5280: + // + // id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } + // + // In dotted notation: 2.5.29.15 + static const uint8_t oid[] = {0x55, 0x1d, 0x0f}; + return der::Input(oid); +} + +der::Input SubjectAltNameOid() { + // From RFC 5280: + // + // id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } + // + // In dotted notation: 2.5.29.17 + static const uint8_t oid[] = {0x55, 0x1d, 0x11}; + return der::Input(oid); +} + +der::Input BasicConstraintsOid() { + // From RFC 5280: + // + // id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } + // + // In dotted notation: 2.5.29.19 + static const uint8_t oid[] = {0x55, 0x1d, 0x13}; + return der::Input(oid); +} + +der::Input NameConstraintsOid() { + // From RFC 5280: + // + // id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } + // + // In dotted notation: 2.5.29.30 + static const uint8_t oid[] = {0x55, 0x1d, 0x1e}; + return der::Input(oid); +} + +der::Input CertificatePoliciesOid() { + // From RFC 5280: + // + // id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } + // + // In dotted notation: 2.5.29.32 + static const uint8_t oid[] = {0x55, 0x1d, 0x20}; + return der::Input(oid); +} + +der::Input PolicyConstraintsOid() { + // From RFC 5280: + // + // id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } + // + // In dotted notation: 2.5.29.36 + static const uint8_t oid[] = {0x55, 0x1d, 0x24}; + return der::Input(oid); +} + +der::Input ExtKeyUsageOid() { + // From RFC 5280: + // + // id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } + // + // In dotted notation: 2.5.29.37 + static const uint8_t oid[] = {0x55, 0x1d, 0x25}; + return der::Input(oid); +} + +NET_EXPORT bool ParseExtensions( + const der::Input& extensions_tlv, + std::map<der::Input, ParsedExtension>* extensions) { + der::Parser parser(extensions_tlv); + + // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + der::Parser extensions_parser; + if (!parser.ReadSequence(&extensions_parser)) + return false; + + // The Extensions SEQUENCE must contains at least 1 element (otherwise it + // should have been omitted). + if (!extensions_parser.HasMore()) + return false; + + extensions->clear(); + + while (extensions_parser.HasMore()) { + ParsedExtension extension; + + der::Input extension_tlv; + if (!extensions_parser.ReadRawTLV(&extension_tlv)) + return false; + + if (!ParseExtension(extension_tlv, &extension)) + return false; + + bool is_duplicate = + !extensions->insert(std::make_pair(extension.oid, extension)).second; + + // RFC 5280 says that an extension should not appear more than once. + if (is_duplicate) + return false; + } + + // By definition the input was a single Extensions sequence, so there + // shouldn't be unconsumed data. + if (parser.HasMore()) + return false; + + return true; +} + +bool ParseBasicConstraints(const der::Input& basic_constraints_tlv, + ParsedBasicConstraints* out) { + der::Parser parser(basic_constraints_tlv); + + // BasicConstraints ::= SEQUENCE { + der::Parser sequence_parser; + if (!parser.ReadSequence(&sequence_parser)) + return false; + + // cA BOOLEAN DEFAULT FALSE, + out->is_ca = false; + bool has_ca; + der::Input ca; + if (!sequence_parser.ReadOptionalTag(der::kBool, &ca, &has_ca)) + return false; + if (has_ca) { + if (!der::ParseBool(ca, &out->is_ca)) + return false; + // TODO(eroman): Should reject if CA was set to false, since + // DER-encoding requires DEFAULT values be omitted. In + // practice however there are a lot of certificates that use + // the broken encoding. + } + + // pathLenConstraint INTEGER (0..MAX) OPTIONAL } + der::Input encoded_path_len; + if (!sequence_parser.ReadOptionalTag(der::kInteger, &encoded_path_len, + &out->has_path_len)) { + return false; + } + if (out->has_path_len) { + if (!der::ParseUint8(encoded_path_len, &out->path_len)) + return false; + } else { + // Default initialize to 0 as a precaution. + out->path_len = 0; + } + + // There shouldn't be any unconsumed data in the extension. + if (sequence_parser.HasMore()) + return false; + + // By definition the input was a single BasicConstraints sequence, so there + // shouldn't be unconsumed data. + if (parser.HasMore()) + return false; + + return true; +} + +bool ParseKeyUsage(const der::Input& key_usage_tlv, der::BitString* key_usage) { + der::Parser parser(key_usage_tlv); + if (!parser.ReadBitString(key_usage)) + return false; + + // By definition the input was a single BIT STRING. + if (parser.HasMore()) + return false; + + // RFC 5280 section 4.2.1.3: + // + // When the keyUsage extension appears in a certificate, at least + // one of the bits MUST be set to 1. + if (BitStringIsAllZeros(*key_usage)) + return false; + + return true; +} + } // namespace net diff --git a/chromium/net/cert/internal/parse_certificate.h b/chromium/net/cert/internal/parse_certificate.h index 0f6b0bb0773..e7a1670af1b 100644 --- a/chromium/net/cert/internal/parse_certificate.h +++ b/chromium/net/cert/internal/parse_certificate.h @@ -5,7 +5,10 @@ #ifndef NET_CERT_INTERNAL_PARSE_CERTIFICATE_H_ #define NET_CERT_INTERNAL_PARSE_CERTIFICATE_H_ -#include "base/basictypes.h" +#include <stdint.h> + +#include <map> + #include "base/compiler_specific.h" #include "net/base/net_export.h" #include "net/der/input.h" @@ -214,6 +217,157 @@ struct NET_EXPORT ParsedTbsCertificate { der::Input extensions_tlv; }; +// ParsedExtension represents a parsed "Extension" from RFC 5280. It contains +// der:Inputs which are not owned so the associated data must be kept alive. +// +// Extension ::= SEQUENCE { +// extnID OBJECT IDENTIFIER, +// critical BOOLEAN DEFAULT FALSE, +// extnValue OCTET STRING +// -- contains the DER encoding of an ASN.1 value +// -- corresponding to the extension type identified +// -- by extnID +// } +struct NET_EXPORT ParsedExtension { + der::Input oid; + // |value| will contain the contents of the OCTET STRING. For instance for + // basicConstraints it will be the TLV for a SEQUENCE. + der::Input value; + bool critical = false; +}; + +// Parses a DER-encoded "Extension" as specified by RFC 5280. Returns true on +// success and sets the results in |out|. +// +// Note that on success |out| aliases data from the input |extension_tlv|. +// Hence the fields of the ParsedExtension are only valid as long as +// |extension_tlv| remains valid. +// +// On failure |out| has an undefined state. Some of its fields may have been +// updated during parsing, whereas others may not have been changed. +NET_EXPORT bool ParseExtension(const der::Input& extension_tlv, + ParsedExtension* out) WARN_UNUSED_RESULT; + +// From RFC 5280: +// +// id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } +// +// In dotted notation: 2.5.29.15 +NET_EXPORT der::Input KeyUsageOid(); + +// From RFC 5280: +// +// id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } +// +// In dotted notation: 2.5.29.17 +NET_EXPORT der::Input SubjectAltNameOid(); + +// From RFC 5280: +// +// id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } +// +// In dotted notation: 2.5.29.19 +NET_EXPORT der::Input BasicConstraintsOid(); + +// From RFC 5280: +// +// id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } +// +// In dotted notation: 2.5.29.30 +NET_EXPORT der::Input NameConstraintsOid(); + +// From RFC 5280: +// +// id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } +// +// In dotted notation: 2.5.29.32 +NET_EXPORT der::Input CertificatePoliciesOid(); + +// From RFC 5280: +// +// id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } +// +// In dotted notation: 2.5.29.36 +NET_EXPORT der::Input PolicyConstraintsOid(); + +// From RFC 5280: +// +// id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } +// +// In dotted notation: 2.5.29.37 +NET_EXPORT der::Input ExtKeyUsageOid(); + +// Parses the Extensions sequence as defined by RFC 5280. Extensions are added +// to the map |extensions| keyed by the OID. Parsing guarantees that each OID +// is unique. Note that certificate verification must consume each extension +// marked as critical. +// +// Returns true on success and fills |extensions|. The output will reference +// bytes in |extensions_tlv|, so that data must be kept alive. +// On failure |extensions| may be partially written to and should not be used. +NET_EXPORT bool ParseExtensions( + const der::Input& extensions_tlv, + std::map<der::Input, ParsedExtension>* extensions) WARN_UNUSED_RESULT; + +struct ParsedBasicConstraints { + bool is_ca = false; + bool has_path_len = false; + uint8_t path_len = 0; +}; + +// Parses the BasicConstraints extension as defined by RFC 5280: +// +// BasicConstraints ::= SEQUENCE { +// cA BOOLEAN DEFAULT FALSE, +// pathLenConstraint INTEGER (0..MAX) OPTIONAL } +// +// The maximum allowed value of pathLenConstraints will be whatever can fit +// into a uint8_t. +NET_EXPORT bool ParseBasicConstraints(const der::Input& basic_constraints_tlv, + ParsedBasicConstraints* out) + WARN_UNUSED_RESULT; + +// KeyUsageBit contains the index for a particular key usage. The index is +// measured from the most significant bit of a bit string. +// +// From RFC 5280 section 4.2.1.3: +// +// KeyUsage ::= BIT STRING { +// digitalSignature (0), +// nonRepudiation (1), -- recent editions of X.509 have +// -- renamed this bit to contentCommitment +// keyEncipherment (2), +// dataEncipherment (3), +// keyAgreement (4), +// keyCertSign (5), +// cRLSign (6), +// encipherOnly (7), +// decipherOnly (8) } +enum KeyUsageBit { + KEY_USAGE_BIT_DIGITAL_SIGNATURE = 0, + KEY_USAGE_BIT_NON_REPUDIATION = 1, + KEY_USAGE_BIT_KEY_ENCIPHERMENT = 2, + KEY_USAGE_BIT_DATA_ENCIPHERMENT = 3, + KEY_USAGE_BIT_KEY_AGREEMENT = 4, + KEY_USAGE_BIT_KEY_CERT_SIGN = 5, + KEY_USAGE_BIT_CRL_SIGN = 6, + KEY_USAGE_BIT_ENCIPHER_ONLY = 7, + KEY_USAGE_BIT_DECIPHER_ONLY = 8, +}; + +// Parses the KeyUsage extension as defined by RFC 5280. Returns true on +// success, and |key_usage| will alias data in |key_usage_tlv|. On failure +// returns false, and |key_usage| may have been modified. +// +// In addition to validating that key_usage_tlv is a BIT STRING, this does +// additional KeyUsage specific validations such as requiring at least 1 bit to +// be set. +// +// To test if a particular key usage is set, call, e.g.: +// key_usage->AssertsBit(KEY_USAGE_BIT_DIGITAL_SIGNATURE); +NET_EXPORT bool ParseKeyUsage(const der::Input& key_usage_tlv, + der::BitString* key_usage) WARN_UNUSED_RESULT; + } // namespace net #endif // NET_CERT_INTERNAL_PARSE_CERTIFICATE_H_ diff --git a/chromium/net/cert/internal/parse_certificate_unittest.cc b/chromium/net/cert/internal/parse_certificate_unittest.cc index cf6da4afc82..eea4d4024be 100644 --- a/chromium/net/cert/internal/parse_certificate_unittest.cc +++ b/chromium/net/cert/internal/parse_certificate_unittest.cc @@ -46,16 +46,14 @@ void EnsureParsingCertificateSucceeds(const std::string& file_name) { // Parsing the certificate should succeed. ParsedCertificate parsed; - ASSERT_TRUE(ParseCertificate(InputFromString(&data), &parsed)); + ASSERT_TRUE(ParseCertificate(der::Input(&data), &parsed)); // Ensure that the ParsedCertificate matches expectations. EXPECT_EQ(0, parsed.signature_value.unused_bits()); - EXPECT_EQ(InputFromString(&expected_signature), - parsed.signature_value.bytes()); - EXPECT_EQ(InputFromString(&expected_signature_algorithm), + EXPECT_EQ(der::Input(&expected_signature), parsed.signature_value.bytes()); + EXPECT_EQ(der::Input(&expected_signature_algorithm), parsed.signature_algorithm_tlv); - EXPECT_EQ(InputFromString(&expected_tbs_certificate), - parsed.tbs_certificate_tlv); + EXPECT_EQ(der::Input(&expected_tbs_certificate), parsed.tbs_certificate_tlv); } // Loads certificate data from the PEM file |file_name| and verifies that the @@ -71,7 +69,7 @@ void EnsureParsingCertificateFails(const std::string& file_name) { // Parsing the Certificate should fail. ParsedCertificate parsed; - ASSERT_FALSE(ParseCertificate(InputFromString(&data), &parsed)); + ASSERT_FALSE(ParseCertificate(der::Input(&data), &parsed)); } // Tests parsing a Certificate. @@ -153,33 +151,33 @@ void EnsureParsingTbsSucceeds(const std::string& file_name, // Parsing the TBSCertificate should succeed. ParsedTbsCertificate parsed; - ASSERT_TRUE(ParseTbsCertificate(InputFromString(&data), &parsed)); + ASSERT_TRUE(ParseTbsCertificate(der::Input(&data), &parsed)); // Ensure that the ParsedTbsCertificate matches expectations. EXPECT_EQ(expected_version, parsed.version); - EXPECT_EQ(InputFromString(&expected_serial_number), parsed.serial_number); - EXPECT_EQ(InputFromString(&expected_signature_algorithm), + EXPECT_EQ(der::Input(&expected_serial_number), parsed.serial_number); + EXPECT_EQ(der::Input(&expected_signature_algorithm), parsed.signature_algorithm_tlv); - EXPECT_EQ(InputFromString(&expected_issuer), parsed.issuer_tlv); + EXPECT_EQ(der::Input(&expected_issuer), parsed.issuer_tlv); // In the test expectations PEM file, validity is described as a // textual string of the parsed value (rather than as DER). EXPECT_EQ(expected_validity_not_before, ToString(parsed.validity_not_before)); EXPECT_EQ(expected_validity_not_after, ToString(parsed.validity_not_after)); - EXPECT_EQ(InputFromString(&expected_subject), parsed.subject_tlv); - EXPECT_EQ(InputFromString(&expected_spki), parsed.spki_tlv); + EXPECT_EQ(der::Input(&expected_subject), parsed.subject_tlv); + EXPECT_EQ(der::Input(&expected_spki), parsed.spki_tlv); - EXPECT_EQ(InputFromString(&expected_issuer_unique_id), + EXPECT_EQ(der::Input(&expected_issuer_unique_id), parsed.issuer_unique_id.bytes()); EXPECT_EQ(!expected_issuer_unique_id.empty(), parsed.has_issuer_unique_id); - EXPECT_EQ(InputFromString(&expected_subject_unique_id), + EXPECT_EQ(der::Input(&expected_subject_unique_id), parsed.subject_unique_id.bytes()); EXPECT_EQ(!expected_subject_unique_id.empty(), parsed.has_subject_unique_id); - EXPECT_EQ(InputFromString(&expected_extensions), parsed.extensions_tlv); + EXPECT_EQ(der::Input(&expected_extensions), parsed.extensions_tlv); EXPECT_EQ(!expected_extensions.empty(), parsed.has_extensions); } @@ -196,7 +194,7 @@ void EnsureParsingTbsFails(const std::string& file_name) { // Parsing the TBSCertificate should fail. ParsedTbsCertificate parsed; - ASSERT_FALSE(ParseTbsCertificate(InputFromString(&data), &parsed)); + ASSERT_FALSE(ParseTbsCertificate(der::Input(&data), &parsed)); } // Tests parsing a TBSCertificate for v3 that contains no optional fields. @@ -326,6 +324,467 @@ TEST(ParseTbsCertificateTest, ValidityRelaxed) { EnsureParsingTbsFails("tbs_validity_relaxed.pem"); } +// Reads a PEM file containing a block "EXTENSION". This input will be +// passed to ParseExtension, and the results filled in |out|. +bool ParseExtensionFromFile(const std::string& file_name, + ParsedExtension* out, + std::string* data) { + const PemBlockMapping mappings[] = { + {"EXTENSION", data}, + }; + + EXPECT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name), mappings)); + return ParseExtension(der::Input(data), out); +} + +// Parses an Extension whose critical field is true (255). +TEST(ParseExtensionTest, Critical) { + std::string data; + ParsedExtension extension; + ASSERT_TRUE( + ParseExtensionFromFile("extension_critical.pem", &extension, &data)); + + EXPECT_TRUE(extension.critical); + + const uint8_t kExpectedOid[] = {0x55, 0x1d, 0x13}; + EXPECT_EQ(der::Input(kExpectedOid), extension.oid); + + const uint8_t kExpectedValue[] = {0x30, 0x00}; + EXPECT_EQ(der::Input(kExpectedValue), extension.value); +} + +// Parses an Extension whose critical field is false (omitted). +TEST(ParseExtensionTest, NotCritical) { + std::string data; + ParsedExtension extension; + ASSERT_TRUE( + ParseExtensionFromFile("extension_not_critical.pem", &extension, &data)); + + EXPECT_FALSE(extension.critical); + + const uint8_t kExpectedOid[] = {0x55, 0x1d, 0x13}; + EXPECT_EQ(der::Input(kExpectedOid), extension.oid); + + const uint8_t kExpectedValue[] = {0x30, 0x00}; + EXPECT_EQ(der::Input(kExpectedValue), extension.value); +} + +// Parses an Extension whose critical field is 0. This is in one sense FALSE, +// however because critical has DEFAULT of false this is in fact invalid +// DER-encoding. +TEST(ParseExtensionTest, Critical0) { + std::string data; + ParsedExtension extension; + ASSERT_FALSE( + ParseExtensionFromFile("extension_critical_0.pem", &extension, &data)); +} + +// Parses an Extension whose critical field is 3. Under DER-encoding BOOLEAN +// values must an octet of either all zero bits, or all 1 bits, so this is not +// valid. +TEST(ParseExtensionTest, Critical3) { + std::string data; + ParsedExtension extension; + ASSERT_FALSE( + ParseExtensionFromFile("extension_critical_3.pem", &extension, &data)); +} + +// Runs a test for extensions parsing. The input file is a PEM file which +// contains a DER-encoded Extensions sequence, as well as the expected value +// for each contained extension. +void EnsureParsingExtensionsSucceeds( + const std::string& file_name, + std::map<der::Input, ParsedExtension>* extensions, + std::string* data) { + const PemBlockMapping mappings[] = { + // Test Input. + {"EXTENSIONS", data}, + }; + + ASSERT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name), mappings)); + ASSERT_TRUE(ParseExtensions(der::Input(data), extensions)); +} + +// Runs a test that verifies extensions parsing fails. The input file is a PEM +// file which contains a DER-encoded Extensions sequence. +void EnsureParsingExtensionsFails(const std::string& file_name) { + std::string data; + + const PemBlockMapping mappings[] = { + {"EXTENSIONS", &data}, + }; + + std::map<der::Input, ParsedExtension> extensions; + ASSERT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name), mappings)); + ASSERT_FALSE(ParseExtensions(der::Input(&data), &extensions)); +} + +// Parses an Extensions that is an empty sequence. +TEST(ParseExtensionsTest, EmptySequence) { + EnsureParsingExtensionsFails("extensions_empty_sequence.pem"); +} + +// Parses an Extensions that is not a sequence. +TEST(ParseExtensionsTest, NotSequence) { + EnsureParsingExtensionsFails("extensions_not_sequence.pem"); +} + +// Parses an Extensions that has data after the sequence. +TEST(ParseExtensionsTest, DataAfterSequence) { + EnsureParsingExtensionsFails("extensions_data_after_sequence.pem"); +} + +// Parses an Extensions that contains duplicated key usages. +TEST(ParseExtensionsTest, DuplicateKeyUsage) { + EnsureParsingExtensionsFails("extensions_duplicate_key_usage.pem"); +} + +// Parses an Extensions that contains an unknown critical extension. +TEST(ParseExtensionsTest, UnknownCritical) { + std::string data; + std::map<der::Input, ParsedExtension> extensions; + EnsureParsingExtensionsSucceeds("extensions_unknown_critical.pem", + &extensions, &data); + + ASSERT_EQ(1u, extensions.size()); + // This OID corresponds with + // 1.2.840.113554.4.1.72585.0 (https://davidben.net/oid) + const uint8_t oid[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, + 0x04, 0x01, 0x84, 0xb7, 0x09, 0x00}; + + auto iter = extensions.find(der::Input(oid)); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_TRUE(iter->second.critical); + EXPECT_EQ(4u, iter->second.value.Length()); +} + +// Parses an Extensions that contains an unknown non-critical extension. +TEST(ParseExtensionsTest, UnknownNonCritical) { + std::string data; + std::map<der::Input, ParsedExtension> extensions; + EnsureParsingExtensionsSucceeds("extensions_unknown_non_critical.pem", + &extensions, &data); + + ASSERT_EQ(1u, extensions.size()); + // This OID corresponds with + // 1.2.840.113554.4.1.72585.0 (https://davidben.net/oid) + const uint8_t oid[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, + 0x04, 0x01, 0x84, 0xb7, 0x09, 0x00}; + + auto iter = extensions.find(der::Input(oid)); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_FALSE(iter->second.critical); + EXPECT_EQ(4u, iter->second.value.Length()); +} + +// Parses an Extensions that contains a basic constraints. +TEST(ParseExtensionsTest, BasicConstraints) { + std::string data; + std::map<der::Input, ParsedExtension> extensions; + EnsureParsingExtensionsSucceeds("extensions_basic_constraints.pem", + &extensions, &data); + + ASSERT_EQ(1u, extensions.size()); + + auto iter = extensions.find(BasicConstraintsOid()); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_TRUE(iter->second.critical); + EXPECT_EQ(2u, iter->second.value.Length()); +} + +// Parses an Extensions that contains an extended key usages. +TEST(ParseExtensionsTest, ExtendedKeyUsage) { + std::string data; + std::map<der::Input, ParsedExtension> extensions; + EnsureParsingExtensionsSucceeds("extensions_extended_key_usage.pem", + &extensions, &data); + + ASSERT_EQ(1u, extensions.size()); + + auto iter = extensions.find(ExtKeyUsageOid()); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_FALSE(iter->second.critical); + EXPECT_EQ(45u, iter->second.value.Length()); +} + +// Parses an Extensions that contains a key usage. +TEST(ParseExtensionsTest, KeyUsage) { + std::string data; + std::map<der::Input, ParsedExtension> extensions; + EnsureParsingExtensionsSucceeds("extensions_key_usage.pem", &extensions, + &data); + + ASSERT_EQ(1u, extensions.size()); + + auto iter = extensions.find(KeyUsageOid()); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_TRUE(iter->second.critical); + EXPECT_EQ(4u, iter->second.value.Length()); +} + +// Parses an Extensions that contains a policies extension. +TEST(ParseExtensionsTest, Policies) { + std::string data; + std::map<der::Input, ParsedExtension> extensions; + EnsureParsingExtensionsSucceeds("extensions_policies.pem", &extensions, + &data); + + ASSERT_EQ(1u, extensions.size()); + + auto iter = extensions.find(CertificatePoliciesOid()); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_FALSE(iter->second.critical); + EXPECT_EQ(95u, iter->second.value.Length()); +} + +// Parses an Extensions that contains a subjectaltname extension. +TEST(ParseExtensionsTest, SubjectAltName) { + std::string data; + std::map<der::Input, ParsedExtension> extensions; + EnsureParsingExtensionsSucceeds("extensions_subject_alt_name.pem", + &extensions, &data); + + ASSERT_EQ(1u, extensions.size()); + + auto iter = extensions.find(SubjectAltNameOid()); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_FALSE(iter->second.critical); + EXPECT_EQ(23u, iter->second.value.Length()); +} + +// Parses an Extensions that contains multiple extensions, sourced from a +// real-world certificate. +TEST(ParseExtensionsTest, Real) { + std::string data; + std::map<der::Input, ParsedExtension> extensions; + EnsureParsingExtensionsSucceeds("extensions_real.pem", &extensions, &data); + + ASSERT_EQ(7u, extensions.size()); + + auto iter = extensions.find(KeyUsageOid()); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_TRUE(iter->second.critical); + EXPECT_EQ(4u, iter->second.value.Length()); + + iter = extensions.find(BasicConstraintsOid()); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_TRUE(iter->second.critical); + EXPECT_EQ(8u, iter->second.value.Length()); + + iter = extensions.find(CertificatePoliciesOid()); + ASSERT_TRUE(iter != extensions.end()); + EXPECT_FALSE(iter->second.critical); + EXPECT_EQ(16u, iter->second.value.Length()); + + // TODO(eroman): Verify the other 4 extensions' values. +} + +// Reads a PEM file containing a block "BASIC CONSTRAINTS". This input will +// be passed to ParseExtension, and the results filled in |out|. +bool ParseBasicConstraintsFromFile(const std::string& file_name, + ParsedBasicConstraints* out) { + std::string data; + const PemBlockMapping mappings[] = { + {"BASIC CONSTRAINTS", &data}, + }; + + EXPECT_TRUE(ReadTestDataFromPemFile(GetFilePath(file_name), mappings)); + return ParseBasicConstraints(der::Input(&data), out); +} + +// Parses a BasicConstraints with no CA or pathlen. +TEST(ParseBasicConstraintsTest, NotCa) { + ParsedBasicConstraints constraints; + ASSERT_TRUE(ParseBasicConstraintsFromFile("basic_constraints_not_ca.pem", + &constraints)); + EXPECT_FALSE(constraints.is_ca); + EXPECT_FALSE(constraints.has_path_len); +} + +// Parses a BasicConstraints with CA but no pathlen. +TEST(ParseBasicConstraintsTest, CaNoPath) { + ParsedBasicConstraints constraints; + ASSERT_TRUE(ParseBasicConstraintsFromFile("basic_constraints_ca_no_path.pem", + &constraints)); + EXPECT_TRUE(constraints.is_ca); + EXPECT_FALSE(constraints.has_path_len); +} + +// Parses a BasicConstraints with CA and pathlen of 9. +TEST(ParseBasicConstraintsTest, CaPath9) { + ParsedBasicConstraints constraints; + ASSERT_TRUE(ParseBasicConstraintsFromFile("basic_constraints_ca_path_9.pem", + &constraints)); + EXPECT_TRUE(constraints.is_ca); + EXPECT_TRUE(constraints.has_path_len); + EXPECT_EQ(9u, constraints.path_len); +} + +// Parses a BasicConstraints with CA and pathlen of 255 (largest allowed size). +TEST(ParseBasicConstraintsTest, Pathlen255) { + ParsedBasicConstraints constraints; + ASSERT_TRUE(ParseBasicConstraintsFromFile("basic_constraints_pathlen_255.pem", + &constraints)); + EXPECT_TRUE(constraints.is_ca); + EXPECT_TRUE(constraints.has_path_len); + EXPECT_EQ(255, constraints.path_len); +} + +// Parses a BasicConstraints with CA and pathlen of 256 (too large). +TEST(ParseBasicConstraintsTest, Pathlen256) { + ParsedBasicConstraints constraints; + ASSERT_FALSE(ParseBasicConstraintsFromFile( + "basic_constraints_pathlen_256.pem", &constraints)); +} + +// Parses a BasicConstraints with CA and a negative pathlen. +TEST(ParseBasicConstraintsTest, NegativePath) { + ParsedBasicConstraints constraints; + ASSERT_FALSE(ParseBasicConstraintsFromFile( + "basic_constraints_negative_path.pem", &constraints)); +} + +// Parses a BasicConstraints with CA and pathlen that is very large (and +// couldn't fit in a 64-bit integer). +TEST(ParseBasicConstraintsTest, PathTooLarge) { + ParsedBasicConstraints constraints; + ASSERT_FALSE(ParseBasicConstraintsFromFile( + "basic_constraints_path_too_large.pem", &constraints)); +} + +// Parses a BasicConstraints with CA explicitly set to false. This violates +// DER-encoding rules, however is commonly used, so it is accepted. +TEST(ParseBasicConstraintsTest, CaFalse) { + ParsedBasicConstraints constraints; + ASSERT_TRUE(ParseBasicConstraintsFromFile("basic_constraints_ca_false.pem", + &constraints)); + EXPECT_FALSE(constraints.is_ca); + EXPECT_FALSE(constraints.has_path_len); +} + +// Parses a BasicConstraints with CA set to true and an unexpected NULL at +// the end. +TEST(ParseBasicConstraintsTest, UnconsumedData) { + ParsedBasicConstraints constraints; + ASSERT_FALSE(ParseBasicConstraintsFromFile( + "basic_constraints_unconsumed_data.pem", &constraints)); +} + +// Parses a BasicConstraints with CA omitted (false), but with a pathlen of 1. +// This is valid DER for the ASN.1, however is not valid when interpreting the +// BasicConstraints at a higher level. +TEST(ParseBasicConstraintsTest, PathLenButNotCa) { + ParsedBasicConstraints constraints; + ASSERT_TRUE(ParseBasicConstraintsFromFile( + "basic_constraints_pathlen_not_ca.pem", &constraints)); + EXPECT_FALSE(constraints.is_ca); + EXPECT_TRUE(constraints.has_path_len); + EXPECT_EQ(1u, constraints.path_len); +} + +// Parses a KeyUsage with a single 0 bit. +TEST(ParseKeyUsageTest, OneBitAllZeros) { + const uint8_t der[] = { + 0x03, 0x02, // BIT STRING + 0x07, // Number of unused bits + 0x00, // bits + }; + + der::BitString key_usage; + ASSERT_FALSE(ParseKeyUsage(der::Input(der), &key_usage)); +} + +// Parses a KeyUsage with 32 bits that are all 0. +TEST(ParseKeyUsageTest, 32BitsAllZeros) { + const uint8_t der[] = { + 0x03, 0x05, // BIT STRING + 0x00, // Number of unused bits + 0x00, 0x00, 0x00, 0x00, + }; + + der::BitString key_usage; + ASSERT_FALSE(ParseKeyUsage(der::Input(der), &key_usage)); +} + +// Parses a KeyUsage with 32 bits, one of which is 1 (but not in recognized +// set). +TEST(ParseKeyUsageTest, 32BitsOneSet) { + const uint8_t der[] = { + 0x03, 0x05, // BIT STRING + 0x00, // Number of unused bits + 0x00, 0x00, 0x00, 0x02, + }; + + der::BitString key_usage; + ASSERT_TRUE(ParseKeyUsage(der::Input(der), &key_usage)); + + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_DIGITAL_SIGNATURE)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_NON_REPUDIATION)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_KEY_ENCIPHERMENT)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_DATA_ENCIPHERMENT)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_KEY_AGREEMENT)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_CRL_SIGN)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_ENCIPHER_ONLY)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_DECIPHER_ONLY)); +} + +// Parses a KeyUsage containing bit string 101. +TEST(ParseKeyUsageTest, ThreeBits) { + const uint8_t der[] = { + 0x03, 0x02, // BIT STRING + 0x05, // Number of unused bits + 0xA0, // bits + }; + + der::BitString key_usage; + ASSERT_TRUE(ParseKeyUsage(der::Input(der), &key_usage)); + + EXPECT_TRUE(key_usage.AssertsBit(KEY_USAGE_BIT_DIGITAL_SIGNATURE)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_NON_REPUDIATION)); + EXPECT_TRUE(key_usage.AssertsBit(KEY_USAGE_BIT_KEY_ENCIPHERMENT)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_DATA_ENCIPHERMENT)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_KEY_AGREEMENT)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_CRL_SIGN)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_ENCIPHER_ONLY)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_DECIPHER_ONLY)); +} + +// Parses a KeyUsage containing DECIPHER_ONLY, which is the +// only bit that doesn't fit in the first byte. +TEST(ParseKeyUsageTest, DecipherOnly) { + const uint8_t der[] = { + 0x03, 0x03, // BIT STRING + 0x07, // Number of unused bits + 0x00, 0x80, // bits + }; + + der::BitString key_usage; + ASSERT_TRUE(ParseKeyUsage(der::Input(der), &key_usage)); + + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_DIGITAL_SIGNATURE)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_NON_REPUDIATION)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_KEY_ENCIPHERMENT)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_DATA_ENCIPHERMENT)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_KEY_AGREEMENT)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_CRL_SIGN)); + EXPECT_FALSE(key_usage.AssertsBit(KEY_USAGE_BIT_ENCIPHER_ONLY)); + EXPECT_TRUE(key_usage.AssertsBit(KEY_USAGE_BIT_DECIPHER_ONLY)); +} + +// Parses an empty KeyUsage. +TEST(ParseKeyUsageTest, Empty) { + const uint8_t der[] = { + 0x03, 0x01, // BIT STRING + 0x00, // Number of unused bits + }; + + der::BitString key_usage; + ASSERT_FALSE(ParseKeyUsage(der::Input(der), &key_usage)); +} + } // namespace } // namespace net diff --git a/chromium/net/cert/internal/signature_algorithm.cc b/chromium/net/cert/internal/signature_algorithm.cc index 468fa16c3a6..38158fce771 100644 --- a/chromium/net/cert/internal/signature_algorithm.cc +++ b/chromium/net/cert/internal/signature_algorithm.cc @@ -4,6 +4,8 @@ #include "net/cert/internal/signature_algorithm.h" +#include <utility> + #include "base/numerics/safe_math.h" #include "net/der/input.h" #include "net/der/parse_values.h" @@ -540,10 +542,6 @@ RsaPssParameters::RsaPssParameters(DigestAlgorithm mgf1_hash, : mgf1_hash_(mgf1_hash), salt_length_(salt_length) { } -bool RsaPssParameters::Equals(const RsaPssParameters* other) const { - return mgf1_hash_ == other->mgf1_hash_ && salt_length_ == other->salt_length_; -} - SignatureAlgorithm::~SignatureAlgorithm() { } @@ -611,34 +609,6 @@ scoped_ptr<SignatureAlgorithm> SignatureAlgorithm::CreateRsaPss( make_scoped_ptr(new RsaPssParameters(mgf1_hash, salt_length)))); } -bool SignatureAlgorithm::Equals(const SignatureAlgorithm& other) const { - if (algorithm_ != other.algorithm_) - return false; - - if (digest_ != other.digest_) - return false; - - // Check that the parameters are equal. - switch (algorithm_) { - case SignatureAlgorithmId::RsaPss: { - const RsaPssParameters* params1 = ParamsForRsaPss(); - const RsaPssParameters* params2 = other.ParamsForRsaPss(); - if (!params1 || !params2 || !params1->Equals(params2)) - return false; - break; - } - - // There shouldn't be any parameters. - case SignatureAlgorithmId::RsaPkcs1: - case SignatureAlgorithmId::Ecdsa: - if (params_ || other.params_) - return false; - break; - } - - return true; -} - const RsaPssParameters* SignatureAlgorithm::ParamsForRsaPss() const { if (algorithm_ == SignatureAlgorithmId::RsaPss) return static_cast<RsaPssParameters*>(params_.get()); @@ -649,7 +619,6 @@ SignatureAlgorithm::SignatureAlgorithm( SignatureAlgorithmId algorithm, DigestAlgorithm digest, scoped_ptr<SignatureAlgorithmParameters> params) - : algorithm_(algorithm), digest_(digest), params_(params.Pass()) { -} + : algorithm_(algorithm), digest_(digest), params_(std::move(params)) {} } // namespace net diff --git a/chromium/net/cert/internal/signature_algorithm.h b/chromium/net/cert/internal/signature_algorithm.h index 9ecf252d671..de35a297473 100644 --- a/chromium/net/cert/internal/signature_algorithm.h +++ b/chromium/net/cert/internal/signature_algorithm.h @@ -7,8 +7,8 @@ #include <stdint.h> -#include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "net/base/net_export.h" @@ -53,8 +53,6 @@ class NET_EXPORT RsaPssParameters : public SignatureAlgorithmParameters { public: RsaPssParameters(DigestAlgorithm mgf1_hash, uint32_t salt_length); - bool Equals(const RsaPssParameters* other) const; - DigestAlgorithm mgf1_hash() const { return mgf1_hash_; } uint32_t salt_length() const { return salt_length_; } @@ -84,10 +82,6 @@ class NET_EXPORT SignatureAlgorithm { DigestAlgorithm mgf1_hash, uint32_t salt_length); - // Returns true if |*this| is equivalent to |other|. This compares both the - // algorithm ID and each parameter for equality. - bool Equals(const SignatureAlgorithm& other) const WARN_UNUSED_RESULT; - // The following methods retrieve the parameters for the signature algorithm. // // The correct parameters should be chosen based on the algorithm ID. For diff --git a/chromium/net/cert/internal/signature_algorithm_unittest.cc b/chromium/net/cert/internal/signature_algorithm_unittest.cc index 8cc5517b3e9..32f5a0fc629 100644 --- a/chromium/net/cert/internal/signature_algorithm_unittest.cc +++ b/chromium/net/cert/internal/signature_algorithm_unittest.cc @@ -485,106 +485,6 @@ TEST(SignatureAlgorithmTest, ParseDerEcdsaWithSHA512NullParams) { ASSERT_FALSE(ParseDer(kData, &algorithm)); } -// Tests that two RSA algorithms with different digests are not equal. -TEST(SignatureAlgorithmTest, EqualsRsaWithDifferentDigest) { - scoped_ptr<SignatureAlgorithm> alg1 = - SignatureAlgorithm::CreateRsaPkcs1(DigestAlgorithm::Sha1); - - scoped_ptr<SignatureAlgorithm> alg2 = - SignatureAlgorithm::CreateRsaPkcs1(DigestAlgorithm::Sha256); - - ASSERT_FALSE(alg1->Equals(*alg2)); -} - -// Tests that two ECDSA algorithms with different digests are not equal. -TEST(SignatureAlgorithmTest, EqualsEcdsaWithDifferentDigest) { - scoped_ptr<SignatureAlgorithm> alg1 = - SignatureAlgorithm::CreateEcdsa(DigestAlgorithm::Sha1); - - scoped_ptr<SignatureAlgorithm> alg2 = - SignatureAlgorithm::CreateEcdsa(DigestAlgorithm::Sha256); - - ASSERT_FALSE(alg1->Equals(*alg2)); -} - -// Tests that an ECDSA algorithm is not equal to an RSA algorithm (even though -// digests match). -TEST(SignatureAlgorithmTest, EqualsEcdsaNotEqualRsa) { - scoped_ptr<SignatureAlgorithm> alg1 = - SignatureAlgorithm::CreateEcdsa(DigestAlgorithm::Sha256); - - scoped_ptr<SignatureAlgorithm> alg2 = - SignatureAlgorithm::CreateRsaPkcs1(DigestAlgorithm::Sha256); - - ASSERT_FALSE(alg1->Equals(*alg2)); -} - -// Tests that two identical ECDSA algorithms are equal - both use SHA-256. -TEST(SignatureAlgorithmTest, EqualsEcdsaMatch) { - scoped_ptr<SignatureAlgorithm> alg1 = - SignatureAlgorithm::CreateEcdsa(DigestAlgorithm::Sha256); - - scoped_ptr<SignatureAlgorithm> alg2 = - SignatureAlgorithm::CreateEcdsa(DigestAlgorithm::Sha256); - - ASSERT_TRUE(alg1->Equals(*alg2)); -} - -// Tests that two identical RSA algorithms are equal - both use SHA-512 -TEST(SignatureAlgorithmTest, EqualsRsaPkcs1Match) { - scoped_ptr<SignatureAlgorithm> alg1 = - SignatureAlgorithm::CreateRsaPkcs1(DigestAlgorithm::Sha512); - - scoped_ptr<SignatureAlgorithm> alg2 = - SignatureAlgorithm::CreateRsaPkcs1(DigestAlgorithm::Sha512); - - ASSERT_TRUE(alg1->Equals(*alg2)); -} - -// Tests that two RSASSA-PSS algorithms are equal. -TEST(SignatureAlgorithmTest, EqualsRsaPssMatch) { - scoped_ptr<SignatureAlgorithm> alg1 = SignatureAlgorithm::CreateRsaPss( - DigestAlgorithm::Sha256, DigestAlgorithm::Sha1, 21); - - scoped_ptr<SignatureAlgorithm> alg2 = SignatureAlgorithm::CreateRsaPss( - DigestAlgorithm::Sha256, DigestAlgorithm::Sha1, 21); - - ASSERT_TRUE(alg1->Equals(*alg2)); -} - -// Tests that two RSASSA-PSS algorithms with different hashes are not equal. -TEST(SignatureAlgorithmTest, EqualsRsaPssWithDifferentDigest) { - scoped_ptr<SignatureAlgorithm> alg1 = SignatureAlgorithm::CreateRsaPss( - DigestAlgorithm::Sha1, DigestAlgorithm::Sha1, 20); - - scoped_ptr<SignatureAlgorithm> alg2 = SignatureAlgorithm::CreateRsaPss( - DigestAlgorithm::Sha256, DigestAlgorithm::Sha1, 20); - - ASSERT_FALSE(alg1->Equals(*alg2)); -} - -// Tests that two RSASSA-PSS algorithms with different mask gens are not equal. -TEST(SignatureAlgorithmTest, EqualsRsaPssWithDifferentMaskGen) { - scoped_ptr<SignatureAlgorithm> alg1 = SignatureAlgorithm::CreateRsaPss( - DigestAlgorithm::Sha256, DigestAlgorithm::Sha1, 20); - - scoped_ptr<SignatureAlgorithm> alg2 = SignatureAlgorithm::CreateRsaPss( - DigestAlgorithm::Sha256, DigestAlgorithm::Sha256, 20); - - ASSERT_FALSE(alg1->Equals(*alg2)); -} - -// Tests that two RSASSA-PSS algorithms with different salts -TEST(SignatureAlgorithmTest, EqualsRsaPssWithDifferentSalt) { - scoped_ptr<SignatureAlgorithm> alg1 = SignatureAlgorithm::CreateRsaPss( - DigestAlgorithm::Sha1, DigestAlgorithm::Sha1, 20); - - scoped_ptr<SignatureAlgorithm> alg2 = SignatureAlgorithm::CreateRsaPss( - DigestAlgorithm::Sha1, DigestAlgorithm::Sha1, 16); - - ASSERT_FALSE(alg1->Equals(*alg2)); -} - // Tests that the parmeters returned for an ECDSA algorithm are null for // non-ECDSA algorithms. TEST(SignatureAlgorithmTest, ParamsAreNullForWrongTypeEcdsa) { diff --git a/chromium/net/cert/internal/signature_policy.h b/chromium/net/cert/internal/signature_policy.h index 72ff945ed2c..3acf17b9ea6 100644 --- a/chromium/net/cert/internal/signature_policy.h +++ b/chromium/net/cert/internal/signature_policy.h @@ -5,6 +5,8 @@ #ifndef NET_CERT_INTERNAL_SIGNATURE_POLICY_H_ #define NET_CERT_INTERNAL_SIGNATURE_POLICY_H_ +#include <stddef.h> + #include "base/compiler_specific.h" #include "net/base/net_export.h" #include "net/cert/internal/signature_algorithm.h" diff --git a/chromium/net/cert/internal/test_helpers.cc b/chromium/net/cert/internal/test_helpers.cc index 0b5363d8acc..4194ae3e6a4 100644 --- a/chromium/net/cert/internal/test_helpers.cc +++ b/chromium/net/cert/internal/test_helpers.cc @@ -9,6 +9,8 @@ #include "base/files/file_util.h" #include "base/path_service.h" #include "net/cert/pem_tokenizer.h" +#include "net/der/parser.h" +#include "testing/gtest/include/gtest/gtest.h" namespace net { @@ -30,8 +32,18 @@ bool operator==(const Input& a, const Input& b) { } // namespace der -der::Input InputFromString(const std::string* s) { - return der::Input(reinterpret_cast<const uint8_t*>(s->data()), s->size()); +der::Input SequenceValueFromString(const std::string* s) { + der::Parser parser((der::Input(s))); + der::Input data; + if (!parser.ReadTag(der::kSequence, &data)) { + ADD_FAILURE(); + return der::Input(); + } + if (parser.HasMore()) { + ADD_FAILURE(); + return der::Input(); + } + return data; } ::testing::AssertionResult ReadTestDataFromPemFile( diff --git a/chromium/net/cert/internal/test_helpers.h b/chromium/net/cert/internal/test_helpers.h index d10148191a4..a1b3d8045ee 100644 --- a/chromium/net/cert/internal/test_helpers.h +++ b/chromium/net/cert/internal/test_helpers.h @@ -5,6 +5,8 @@ #ifndef NET_CERT_INTERNAL_TEST_HELPERS_H_ #define NET_CERT_INTERNAL_TEST_HELPERS_H_ +#include <stddef.h> + #include <ostream> #include <string> #include <vector> @@ -23,15 +25,13 @@ bool operator==(const Input& a, const Input& b); } // namespace der -// Creates a der::Input from an std::string. The lifetimes are a bit subtle -// when using this function: +// Parses |s| as a DER SEQUENCE TLV and returns a der::Input corresponding to +// the value portion. On error returns an empty der::Input and adds a gtest +// failure. // // The returned der::Input() is only valid so long as the input string is alive // and is not mutated. -// -// Note that the input parameter has been made a pointer to prevent callers -// from accidentally passing an r-value. -der::Input InputFromString(const std::string* s); +der::Input SequenceValueFromString(const std::string* s); // Helper structure that maps a PEM block header (for instance "CERTIFICATE") to // the destination where the value for that block should be written. diff --git a/chromium/net/cert/internal/verify_certificate_chain.cc b/chromium/net/cert/internal/verify_certificate_chain.cc new file mode 100644 index 00000000000..524de925d3e --- /dev/null +++ b/chromium/net/cert/internal/verify_certificate_chain.cc @@ -0,0 +1,549 @@ +// Copyright 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. + +#include "net/cert/internal/verify_certificate_chain.h" + +#include "base/logging.h" +#include "net/cert/internal/parse_certificate.h" +#include "net/cert/internal/signature_algorithm.h" +#include "net/cert/internal/signature_policy.h" +#include "net/cert/internal/verify_name_match.h" +#include "net/cert/internal/verify_signed_data.h" +#include "net/der/input.h" +#include "net/der/parser.h" + +namespace net { + +namespace { + +// Map from OID to ParsedExtension. +using ExtensionsMap = std::map<der::Input, ParsedExtension>; + +// Describes all parsed properties of a certificate that are relevant for +// certificate verification. +struct FullyParsedCert { + ParsedCertificate cert; + ParsedTbsCertificate tbs; + + scoped_ptr<SignatureAlgorithm> signature_algorithm; + + // Standard extensions that were parsed. + bool has_basic_constraints = false; + ParsedBasicConstraints basic_constraints; + + bool has_key_usage = false; + der::BitString key_usage; + + // The remaining extensions (excludes the standard ones above). + ExtensionsMap unconsumed_extensions; +}; + +// Removes the extension with OID |oid| from |unconsumed_extensions| and fills +// |extension| with the matching extension value. If there was no extension +// matching |oid| then returns |false|. +WARN_UNUSED_RESULT bool ConsumeExtension(const der::Input& oid, + ExtensionsMap* unconsumed_extensions, + ParsedExtension* extension) { + auto it = unconsumed_extensions->find(oid); + if (it == unconsumed_extensions->end()) + return false; + + *extension = it->second; + unconsumed_extensions->erase(it); + return true; +} + +// Returns true if the certificate does not contain any unconsumed _critical_ +// extensions. +WARN_UNUSED_RESULT bool VerifyNoUnconsumedCriticalExtensions( + const FullyParsedCert& cert) { + for (const auto& entry : cert.unconsumed_extensions) { + if (entry.second.critical) + return false; + } + return true; +} + +// Parses an X.509 Certificate fully (including the TBSCertificate and +// standard extensions), saving all the properties to |out_|. +WARN_UNUSED_RESULT bool FullyParseCertificate(const der::Input& cert_tlv, + FullyParsedCert* out) { + // Parse the outer Certificate. + if (!ParseCertificate(cert_tlv, &out->cert)) + return false; + + // Parse the signature algorithm contained in the Certificate (there is + // another one in the TBSCertificate, which is checked later by + // VerifySignatureAlgorithmsMatch) + out->signature_algorithm = + SignatureAlgorithm::CreateFromDer(out->cert.signature_algorithm_tlv); + if (!out->signature_algorithm) + return false; + + // Parse the TBSCertificate. + if (!ParseTbsCertificate(out->cert.tbs_certificate_tlv, &out->tbs)) + return false; + + // Reset state relating to extensions (which may not get overwritten). This is + // just a precaution, since in practice |out| will already be default + // initialize. + out->has_basic_constraints = false; + out->has_key_usage = false; + out->unconsumed_extensions.clear(); + + // Parse the standard X.509 extensions and remove them from + // |unconsumed_extensions|. + if (out->tbs.has_extensions) { + // ParseExtensions() ensures there are no duplicates, and maps the (unique) + // OID to the extension value. + if (!ParseExtensions(out->tbs.extensions_tlv, &out->unconsumed_extensions)) + return false; + + ParsedExtension extension; + + // Basic constraints. + if (ConsumeExtension(BasicConstraintsOid(), &out->unconsumed_extensions, + &extension)) { + out->has_basic_constraints = true; + if (!ParseBasicConstraints(extension.value, &out->basic_constraints)) + return false; + } + + // KeyUsage. + if (ConsumeExtension(KeyUsageOid(), &out->unconsumed_extensions, + &extension)) { + out->has_key_usage = true; + if (!ParseKeyUsage(extension.value, &out->key_usage)) + return false; + } + } + + return true; +} + +WARN_UNUSED_RESULT bool GetSequenceValue(const der::Input& tlv, + der::Input* value) { + der::Parser parser(tlv); + return parser.ReadTag(der::kSequence, value) && !parser.HasMore(); +} + +// Returns true if |name1_tlv| matches |name2_tlv|. The two inputs must be +// tag-length-value for RFC 5280's Name. +WARN_UNUSED_RESULT bool NameMatches(const der::Input& name1_tlv, + const der::Input& name2_tlv) { + der::Input name1_value; + der::Input name2_value; + + // Assume that the Name is an RDNSequence. VerifyNameMatch() expects the + // value from a SEQUENCE, so strip off the tag. + if (!GetSequenceValue(name1_tlv, &name1_value) || + !GetSequenceValue(name2_tlv, &name2_value)) { + return false; + } + + return VerifyNameMatch(name1_value, name2_value); +} + +// Returns true if |cert| was self-issued. The definition of self-issuance +// comes from RFC 5280 section 6.1: +// +// A certificate is self-issued if the same DN appears in the subject +// and issuer fields (the two DNs are the same if they match according +// to the rules specified in Section 7.1). In general, the issuer and +// subject of the certificates that make up a path are different for +// each certificate. However, a CA may issue a certificate to itself to +// support key rollover or changes in certificate policies. These +// self-issued certificates are not counted when evaluating path length +// or name constraints. +WARN_UNUSED_RESULT bool IsSelfIssued(const FullyParsedCert& cert) { + 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 +// 4.1.2.5: +// +// The validity period for a certificate is the period of time from +// notBefore through notAfter, inclusive. +WARN_UNUSED_RESULT bool VerifyTimeValidity(const FullyParsedCert& cert, + const der::GeneralizedTime time) { + return !(time < cert.tbs.validity_not_before) && + !(cert.tbs.validity_not_after < time); +} + +// Returns true if |signature_algorithm_tlv| is a valid algorithm encoding for +// RSA with SHA1. +WARN_UNUSED_RESULT bool IsRsaWithSha1SignatureAlgorithm( + const der::Input& signature_algorithm_tlv) { + scoped_ptr<SignatureAlgorithm> algorithm = + SignatureAlgorithm::CreateFromDer(signature_algorithm_tlv); + + return algorithm && + algorithm->algorithm() == SignatureAlgorithmId::RsaPkcs1 && + algorithm->digest() == DigestAlgorithm::Sha1; +} + +// Returns true if |cert| has internally consistent signature algorithms. +// +// X.509 certificates contain two different signature algorithms: +// (1) The signatureAlgorithm field of Certificate +// (2) The signature field of TBSCertificate +// +// According to RFC 5280 section 4.1.1.2 and 4.1.2.3 these two fields must be +// equal: +// +// This field MUST contain the same algorithm identifier as the +// signature field in the sequence tbsCertificate (Section 4.1.2.3). +// +// The spec is not explicit about what "the same algorithm identifier" means. +// Our interpretation is that the two DER-encoded fields must be byte-for-byte +// identical. +// +// In practice however there are certificates which use different encodings for +// specifying RSA with SHA1 (different OIDs). This is special-cased for +// compatibility sake. +WARN_UNUSED_RESULT bool VerifySignatureAlgorithmsMatch( + const FullyParsedCert& cert) { + const der::Input& alg1_tlv = cert.cert.signature_algorithm_tlv; + const der::Input& alg2_tlv = cert.tbs.signature_algorithm_tlv; + + // Ensure that the two DER-encoded signature algorithms are byte-for-byte + // equal, but make a compatibility concession for RSA with SHA1. + return alg1_tlv.Equals(alg2_tlv) || + (IsRsaWithSha1SignatureAlgorithm(alg1_tlv) && + IsRsaWithSha1SignatureAlgorithm(alg2_tlv)); +} + +// This function corresponds to RFC 5280 section 6.1.3's "Basic Certificate +// Processing" procedure. +WARN_UNUSED_RESULT bool BasicCertificateProcessing( + const FullyParsedCert& cert, + const SignaturePolicy* signature_policy, + const der::GeneralizedTime& time, + const der::Input& working_spki, + const der::Input& working_issuer_name) { + // Check that the signature algorithms in Certificate vs TBSCertificate + // match. This isn't part of RFC 5280 section 6.1.3, but is mandated by + // sections 4.1.1.2 and 4.1.2.3. + 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; + } + + // Check the time range for the certificate's validity, ensuring it is valid + // at |time|. + // (RFC 5280 section 6.1.3 step a.2) + if (!VerifyTimeValidity(cert, time)) + return false; + + // 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; + + // TODO(eroman): Steps b-f are omitted, as policy/name constraints are not yet + // implemented. + + return true; +} + +// This function corresponds to RFC 5280 section 6.1.4's "Preparation for +// Certificate i+1" procedure. |cert| is expected to be an intermediary. +WARN_UNUSED_RESULT bool PrepareForNextCertificate( + const FullyParsedCert& cert, + size_t* max_path_length_ptr, + der::Input* working_spki, + der::Input* working_issuer_name) { + // TODO(eroman): Steps a-b are omitted, as policy/name constraints are not yet + // implemented. + + // From RFC 5280 section 6.1.4 step c: + // + // Assign the certificate subject name to working_issuer_name. + *working_issuer_name = cert.tbs.subject_tlv; + + // From RFC 5280 section 6.1.4 step d: + // + // Assign the certificate subjectPublicKey to working_public_key. + *working_spki = cert.tbs.spki_tlv; + + // Note that steps e and f are omitted as they are handled by + // the assignment to |working_spki| above. See the definition + // of |working_spki|. + + // TODO(eroman): Steps g-j are omitted as policy/name constraints are not yet + // implemented. + + // From RFC 5280 section 6.1.4 step k: + // + // If certificate i is a version 3 certificate, verify that the + // basicConstraints extension is present and that cA is set to + // TRUE. (If certificate i is a version 1 or version 2 + // certificate, then the application MUST either verify that + // certificate i is a CA certificate through out-of-band means + // or reject the certificate. Conforming implementations may + // choose to reject all version 1 and version 2 intermediate + // certificates.) + // + // This code implicitly rejects non version 3 intermediaries, since they + // can't contain a BasicConstraints extension. + if (!cert.has_basic_constraints || !cert.basic_constraints.is_ca) + return false; + + // From RFC 5280 section 6.1.4 step l: + // + // If the certificate was not self-issued, verify that + // max_path_length is greater than zero and decrement + // max_path_length by 1. + if (!IsSelfIssued(cert)) { + if (*max_path_length_ptr == 0) + return false; + --(*max_path_length_ptr); + } + + // From RFC 5280 section 6.1.4 step m: + // + // If pathLenConstraint is present in the certificate and is + // less than max_path_length, set max_path_length to the value + // of pathLenConstraint. + if (cert.basic_constraints.has_path_len && + cert.basic_constraints.path_len < *max_path_length_ptr) { + *max_path_length_ptr = cert.basic_constraints.path_len; + } + + // From RFC 5280 section 6.1.4 step n: + // + // If a key usage extension is present, verify that the + // keyCertSign bit is set. + if (cert.has_key_usage && + !cert.key_usage.AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)) { + return false; + } + + // From RFC 5280 section 6.1.4 step o: + // + // Recognize and process any other critical extension present in + // the certificate. Process any other recognized non-critical + // extension present in the certificate that is relevant to path + // processing. + if (!VerifyNoUnconsumedCriticalExtensions(cert)) + return false; + + return true; +} + +// Checks that if the target certificate has properties that only a CA should +// have (keyCertSign, CA=true, pathLenConstraint), then its other properties +// are consistent with being a CA. +// +// This follows from some requirements in RFC 5280 section 4.2.1.9. In +// particular: +// +// CAs MUST NOT include the pathLenConstraint field unless the cA +// boolean is asserted and the key usage extension asserts the +// keyCertSign bit. +// +// And: +// +// If the cA boolean is not asserted, then the keyCertSign bit in the key +// usage extension MUST NOT be asserted. +// +// TODO(eroman): Strictly speaking the first requirement is on CAs and not the +// certificate client, so could be skipped. +// +// TODO(eroman): I don't believe Firefox enforces the keyCertSign restriction +// for compatibility reasons. Investigate if we need to similarly relax this +// constraint. +WARN_UNUSED_RESULT bool VerifyTargetCertHasConsistentCaBits( + const FullyParsedCert& cert) { + // Check if the certificate contains any property specific to CAs. + bool has_ca_property = + (cert.has_basic_constraints && + (cert.basic_constraints.is_ca || cert.basic_constraints.has_path_len)) || + (cert.has_key_usage && + cert.key_usage.AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)); + + // If it "looks" like a CA because it has a CA-only property, then check that + // it sets ALL the properties expected of a CA. + if (has_ca_property) { + return cert.has_basic_constraints && cert.basic_constraints.is_ca && + (!cert.has_key_usage || + cert.key_usage.AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)); + } + + return true; +} + +// This function corresponds with RFC 5280 section 6.1.5's "Wrap-Up Procedure". +// It does processing for the final certificate (the target cert). +WARN_UNUSED_RESULT bool WrapUp(const FullyParsedCert& cert) { + // TODO(eroman): Steps a-c are omitted as policy/name constraints are not yet + // implemented. + + // Note step c-e are omitted the verification function does + // not output the working public key. + + // From RFC 5280 section 6.1.5 step f: + // + // Recognize and process any other critical extension present in + // the certificate n. Process any other recognized non-critical + // extension present in certificate n that is relevant to path + // processing. + // + // Note that this is duplicated by PrepareForNextCertificate() so as to + // directly match the procedures in RFC 5280's section 6.1. + if (!VerifyNoUnconsumedCriticalExtensions(cert)) + return false; + + // TODO(eroman): Step g is omitted, as policy constraints are not yet + // implemented. + + // The following check is NOT part of RFC 5280 6.1.5's "Wrap-Up Procedure", + // however is implied by RFC 5280 section 4.2.1.9. + if (!VerifyTargetCertHasConsistentCaBits(cert)) + return false; + + return true; +} + +} // namespace + +TrustAnchor::~TrustAnchor() {} + +TrustStore::TrustStore() {} +TrustStore::~TrustStore() {} + +// 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) { + // An empty chain is necessarily invalid. + if (certs_der.empty()) + return false; + + // |working_spki| is an amalgamation of 3 separate variables from RFC 5280: + // * working_public_key + // * working_public_key_algorithm + // * working_public_key_parameters + // + // They are combined for simplicity since the signature verification takes an + // SPKI, and the parameter inheritence is not applicable for the supported + // key types. + // + // An approximate explanation of |working_spki| is this description from RFC + // 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. + 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. + der::Input working_issuer_name; + + // |max_path_length| corresponds with the same named variable in RFC 5280 + // section 6.1.2: + // + // max_path_length: this integer is initialized to n, is + // decremented for each non-self-issued certificate in the path, + // and may be reduced to the value in the path length constraint + // field within the basic constraints extension of a CA + // certificate. + size_t max_path_length = certs_der.size(); + + // Iterate over all the certificates in the reverse direction: starting from + // the trust anchor and progressing towards the target certificate. + // + // Note that |i| uses 0-based indexing whereas in RFC 5280 it is 1-based. + // + // * i=0 : Certificate signed by a 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; + const bool is_target_cert = index_into_certs_der == 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, signature_policy, time, working_spki, + working_issuer_name)) { + return false; + } + if (!is_target_cert) { + if (!PrepareForNextCertificate(cert, &max_path_length, &working_spki, + &working_issuer_name)) { + return false; + } + } else { + if (!WrapUp(cert)) + return false; + } + } + + // TODO(eroman): RFC 5280 forbids duplicate certificates per section 6.1: + // + // A certificate MUST NOT appear more than once in a prospective + // certification path. + + return true; +} + +} // namespace net diff --git a/chromium/net/cert/internal/verify_certificate_chain.h b/chromium/net/cert/internal/verify_certificate_chain.h new file mode 100644 index 00000000000..8f7e21f8ad6 --- /dev/null +++ b/chromium/net/cert/internal/verify_certificate_chain.h @@ -0,0 +1,86 @@ +// Copyright 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. + +#ifndef NET_CERT_INTERNAL_VERIFY_CERTIFICATE_CHAIN_H_ +#define NET_CERT_INTERNAL_VERIFY_CERTIFICATE_CHAIN_H_ + +#include <stdint.h> + +#include <string> +#include <vector> + +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "net/base/net_export.h" + +namespace net { + +namespace der { +class Input; +struct GeneralizedTime; +} + +class SignaturePolicy; + +struct NET_EXPORT TrustAnchor { + ~TrustAnchor(); + + // DER-encoded SubjectPublicKeyInfo for the trusted key. + std::string spki; + + // DER-encoded "Name" corresponding to the key. + std::string name; +}; + +// A very simple implementation of a TrustStore, which contains mappings from +// names to trusted public keys. +struct NET_EXPORT TrustStore { + TrustStore(); + ~TrustStore(); + + std::vector<TrustAnchor> anchors; +}; + +// VerifyCertificateChain() verifies a certificate path (chain) based on the +// rules in RFC 5280. +// +// WARNING: This implementation is in progress, and is currently +// incomplete. DO NOT USE IT unless its limitations are acceptable for your use. +// +// --------- +// Inputs +// --------- +// +// cert_chain: +// A non-empty chain of N DER-encoded certificates, listed in the +// "forward" direction. +// +// * cert_chain[0] is the target certificate to verify. +// * cert_chain[i+1] holds the certificate that issued cert_chain[i]. +// * cert_chain[N-1] must have been issued by a trust anchor +// +// trust_store: +// Contains the set of trusted public keys (and their names). +// +// signature_policy: +// The policy to use when verifying signatures (what hash algorithms are +// allowed, what length keys, what named curves, etc). +// +// time: +// The UTC time to use for expiration checks. +// +// --------- +// Outputs +// --------- +// +// Returns true if the target certificate can be verified. +NET_EXPORT bool VerifyCertificateChain(const std::vector<der::Input>& certs_der, + const TrustStore& trust_store, + const SignaturePolicy* signature_policy, + const der::GeneralizedTime& time) + WARN_UNUSED_RESULT; + +} // namespace net + +#endif // NET_CERT_INTERNAL_VERIFY_CERTIFICATE_CHAIN_H_ diff --git a/chromium/net/cert/internal/verify_certificate_chain_unittest.cc b/chromium/net/cert/internal/verify_certificate_chain_unittest.cc new file mode 100644 index 00000000000..c997f5386ef --- /dev/null +++ b/chromium/net/cert/internal/verify_certificate_chain_unittest.cc @@ -0,0 +1,246 @@ +// Copyright 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. + +#include "net/cert/internal/verify_certificate_chain.h" + +#include "base/base_paths.h" +#include "base/files/file_util.h" +#include "base/path_service.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "net/cert/internal/parse_certificate.h" +#include "net/cert/internal/signature_policy.h" +#include "net/cert/internal/test_helpers.h" +#include "net/cert/pem_tokenizer.h" +#include "net/der/input.h" +#include "testing/gtest/include/gtest/gtest.h" + +// TODO(eroman): Because VerifySignedData() is only implemented for BoringSSL +// these tests also depend on BoringSSL. +#if defined(USE_OPENSSL) + +namespace net { + +namespace { + +// Reads a data file from the unit-test data. +std::string ReadTestFileToString(const std::string& file_name) { + // Compute the full path, relative to the src/ directory. + base::FilePath src_root; + PathService::Get(base::DIR_SOURCE_ROOT, &src_root); + base::FilePath filepath = src_root.AppendASCII( + std::string("net/data/verify_certificate_chain_unittest/") + file_name); + + // Read the full contents of the file. + std::string file_data; + if (!base::ReadFileToString(filepath, &file_data)) { + ADD_FAILURE() << "Couldn't read file: " << filepath.value(); + return std::string(); + } + + 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. +void ReadTestFromFile(const std::string& file_name, + std::vector<std::string>* chain, + TrustStore* trust_store, + der::GeneralizedTime* time, + bool* verify_result) { + chain->clear(); + *trust_store = TrustStore(); + + std::string file_data = ReadTestFileToString(file_name); + + std::vector<std::string> pem_headers; + + const char kCertificateHeader[] = "CERTIFICATE"; + const char kTrustedCertificateHeader[] = "TRUSTED_CERTIFICATE"; + const char kTimeHeader[] = "TIME"; + const char kResultHeader[] = "VERIFY_RESULT"; + + pem_headers.push_back(kCertificateHeader); + pem_headers.push_back(kTrustedCertificateHeader); + pem_headers.push_back(kTimeHeader); + pem_headers.push_back(kResultHeader); + + bool has_time = false; + bool has_result = false; + + PEMTokenizer pem_tokenizer(file_data, pem_headers); + while (pem_tokenizer.GetNext()) { + const std::string& block_type = pem_tokenizer.block_type(); + const std::string& block_data = pem_tokenizer.data(); + + if (block_type == kCertificateHeader) { + chain->push_back(block_data); + } else if (block_type == kTrustedCertificateHeader) { + AddCertificateToTrustStore(block_data, trust_store); + } else if (block_type == kTimeHeader) { + ASSERT_FALSE(has_time) << "Duplicate " << kTimeHeader; + has_time = true; + ASSERT_TRUE(der::ParseUTCTime(der::Input(&block_data), time)); + } else if (block_type == kResultHeader) { + ASSERT_FALSE(has_result) << "Duplicate " << kResultHeader; + ASSERT_TRUE(block_data == "SUCCESS" || block_data == "FAIL") + << "Unrecognized result: " << block_data; + has_result = true; + *verify_result = block_data == "SUCCESS"; + } + } + + ASSERT_TRUE(has_time); + ASSERT_TRUE(has_result); +} + +void RunTest(const char* file_name) { + std::vector<std::string> chain; + TrustStore trust_store; + der::GeneralizedTime time; + bool expected_result; + + ReadTestFromFile(file_name, &chain, &trust_store, &time, &expected_result); + + std::vector<der::Input> input_chain; + for (const auto& cert_str : chain) + input_chain.push_back(der::Input(&cert_str)); + + SimpleSignaturePolicy signature_policy(1024); + + bool result = + VerifyCertificateChain(input_chain, trust_store, &signature_policy, time); + + ASSERT_EQ(expected_result, result); +} + +TEST(VerifyCertificateChainTest, TargetAndIntermediary) { + RunTest("target-and-intermediary.pem"); +} + +TEST(VerifyCertificateChainTest, UnknownRoot) { + RunTest("unknown-root.pem"); +} + +TEST(VerifyCertificateChainTest, IntermediaryLacksBasicConstraints) { + RunTest("intermediary-lacks-basic-constraints.pem"); +} + +TEST(VerifyCertificateChainTest, IntermediaryBasicConstraintsCaFalse) { + RunTest("intermediary-basic-constraints-ca-false.pem"); +} + +TEST(VerifyCertificateChainTest, IntermediaryBasicConstraintsNotCritical) { + RunTest("intermediary-basic-constraints-not-critical.pem"); +} + +TEST(VerifyCertificateChainTest, IntermediaryLacksSigningKeyUsage) { + RunTest("intermediary-lacks-signing-key-usage.pem"); +} + +TEST(VerifyCertificateChainTest, IntermediaryUnknownCriticalExtension) { + RunTest("intermediary-unknown-critical-extension.pem"); +} + +TEST(VerifyCertificateChainTest, IntermediaryUnknownNonCriticalExtension) { + RunTest("intermediary-unknown-non-critical-extension.pem"); +} + +TEST(VerifyCertificateChainTest, ViolatesBasicConstraintsPathlen0) { + RunTest("violates-basic-constraints-pathlen-0.pem"); +} + +TEST(VerifyCertificateChainTest, BasicConstraintsPathlen0SelfIssued) { + RunTest("basic-constraints-pathlen-0-self-issued.pem"); +} + +TEST(VerifyCertificateChainTest, TargetSignedWithMd5) { + RunTest("target-signed-with-md5.pem"); +} + +TEST(VerifyCertificateChainTest, IntermediarySignedWithMd5) { + RunTest("intermediary-signed-with-md5.pem"); +} + +TEST(VerifyCertificateChainTest, TargetWrongSignature) { + RunTest("target-wrong-signature.pem"); +} + +TEST(VerifyCertificateChainTest, TargetSignedBy512bitRsa) { + RunTest("target-signed-by-512bit-rsa.pem"); +} + +TEST(VerifyCertificateChainTest, TargetSignedUsingEcdsa) { + RunTest("target-signed-using-ecdsa.pem"); +} + +TEST(VerifyCertificateChainTest, ExpiredIntermediary) { + RunTest("expired-intermediary.pem"); +} + +TEST(VerifyCertificateChainTest, ExpiredTarget) { + RunTest("expired-target.pem"); +} + +TEST(VerifyCertificateChainTest, ExpiredTargetNotBefore) { + RunTest("expired-target-notBefore.pem"); +} + +TEST(VerifyCertificateChainTest, TargetNotEndEntity) { + RunTest("target-not-end-entity.pem"); +} + +TEST(VerifyCertificateChainTest, TargetHasKeyCertSignButNotCa) { + RunTest("target-has-keycertsign-but-not-ca.pem"); +} + +TEST(VerifyCertificateChainTest, TargetHasPathlenButNotCa) { + RunTest("target-has-pathlen-but-not-ca.pem"); +} + +TEST(VerifyCertificateChainTest, TargetUnknownCriticalExtension) { + RunTest("target-unknown-critical-extension.pem"); +} + +TEST(VerifyCertificateChainTest, IssuerAndSubjectNotByteForByteEqual) { + RunTest("issuer-and-subject-not-byte-for-byte-equal.pem"); +} + +TEST(VerifyCertificateChainTest, IssuerAndSubjectNotByteForByteEqualAnchor) { + RunTest("issuer-and-subject-not-byte-for-byte-equal-anchor.pem"); +} + +// Tests that verifying a chain with no certificates fails. +TEST(VerifyCertificateChainTest, EmptyChainIsInvalid) { + TrustStore trust_store; + der::GeneralizedTime time; + std::vector<der::Input> chain; + SimpleSignaturePolicy signature_policy(2048); + + ASSERT_FALSE( + VerifyCertificateChain(chain, trust_store, &signature_policy, time)); +} + +// TODO(eroman): Add test that invalidate validity dates where the day or month +// ordinal not in range, like "March 39, 2016" are rejected. + +} // namespace + +} // namespace net + +#endif diff --git a/chromium/net/cert/internal/verify_name_match.cc b/chromium/net/cert/internal/verify_name_match.cc index 5b6cf4cbf2a..00d1fb5c113 100644 --- a/chromium/net/cert/internal/verify_name_match.cc +++ b/chromium/net/cert/internal/verify_name_match.cc @@ -6,7 +6,6 @@ #include <string.h> -#include "base/stl_util.h" #include "base/strings/string16.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversion_utils.h" @@ -22,6 +21,17 @@ namespace net { namespace { +// RFC 5280 section A.1: +// +// pkcs-9 OBJECT IDENTIFIER ::= +// { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } +// +// id-emailAddress AttributeType ::= { pkcs-9 1 } +// +// In dotted form: 1.2.840.113549.1.9.1 +const uint8_t kOidEmailAddress[] = {0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x09, 0x01}; + // Types of character set checking that NormalizeDirectoryString can perform. enum CharsetEnforcement { NO_ENFORCEMENT, @@ -202,7 +212,7 @@ WARN_UNUSED_RESULT bool NormalizeUniversalStringValue(const der::Input& in, std::vector<uint32_t> in_32bit(in.Length() / 4); if (in.Length()) - memcpy(vector_as_array(&in_32bit), in.UnsafeData(), in.Length()); + memcpy(in_32bit.data(), in.UnsafeData(), in.Length()); for (const uint32_t c : in_32bit) { // UniversalString is UCS-4 in big-endian order. uint32_t codepoint = base::NetToHost32(c); @@ -389,8 +399,16 @@ bool VerifyRdnMatch(der::Parser* a_parser, der::Parser* b_parser) { return true; } -} // namespace +enum NameMatchType { + EXACT_MATCH, + SUBTREE_MATCH, +}; +// Verify that |a| matches |b|. If |match_type| is EXACT_MATCH, returns true if +// they are an exact match as defined by RFC 5280 7.1. If |match_type| is +// SUBTREE_MATCH, returns true if |a| is within the subtree defined by |b| as +// defined by RFC 5280 7.1. +// // |a| and |b| are ASN.1 RDNSequence values (not including the Sequence tag), // defined in RFC 5280 section 4.1.2.4: // @@ -401,7 +419,9 @@ bool VerifyRdnMatch(der::Parser* a_parser, der::Parser* b_parser) { // // RelativeDistinguishedName ::= // SET SIZE (1..MAX) OF AttributeTypeAndValue -bool VerifyNameMatch(const der::Input& a, const der::Input& b) { +bool VerifyNameMatchInternal(const der::Input& a, + const der::Input& b, + NameMatchType match_type) { // Empty Names are allowed. RFC 5280 section 4.1.2.4 requires "The issuer // field MUST contain a non-empty distinguished name (DN)", while section // 4.1.2.6 allows for the Subject to be empty in certain cases. The caller is @@ -421,7 +441,12 @@ bool VerifyNameMatch(const der::Input& a, const der::Input& b) { return false; } } - if (a_rdn_sequence_counter.HasMore() || b_rdn_sequence_counter.HasMore()) + // If doing exact match and either of the sequences has more elements than the + // other, not a match. If doing a subtree match, the first Name may have more + // RDNs than the second. + if (b_rdn_sequence_counter.HasMore()) + return false; + if (match_type == EXACT_MATCH && a_rdn_sequence_counter.HasMore()) return false; // Same number of RDNs, now check if they match. @@ -440,4 +465,42 @@ bool VerifyNameMatch(const der::Input& a, const der::Input& b) { return true; } +} // namespace + +bool VerifyNameMatch(const der::Input& a_rdn_sequence, + const der::Input& b_rdn_sequence) { + return VerifyNameMatchInternal(a_rdn_sequence, b_rdn_sequence, EXACT_MATCH); +} + +bool VerifyNameInSubtree(const der::Input& name_rdn_sequence, + const der::Input& parent_rdn_sequence) { + return VerifyNameMatchInternal(name_rdn_sequence, parent_rdn_sequence, + SUBTREE_MATCH); +} + +bool NameContainsEmailAddress(const der::Input& name_rdn_sequence, + bool* contained_email_address) { + der::Parser rdn_sequence_parser(name_rdn_sequence); + + while (rdn_sequence_parser.HasMore()) { + der::Parser rdn_parser; + if (!rdn_sequence_parser.ReadConstructed(der::kSet, &rdn_parser)) + return false; + + std::vector<AttributeTypeAndValue> type_and_values; + if (!ReadRdn(&rdn_parser, &type_and_values)) + return false; + + for (const auto& type_and_value : type_and_values) { + if (type_and_value.type.Equals(der::Input(kOidEmailAddress))) { + *contained_email_address = true; + return true; + } + } + } + + *contained_email_address = false; + return true; +} + } // namespace net diff --git a/chromium/net/cert/internal/verify_name_match.h b/chromium/net/cert/internal/verify_name_match.h index 99d09f0e107..5cca36ad2db 100644 --- a/chromium/net/cert/internal/verify_name_match.h +++ b/chromium/net/cert/internal/verify_name_match.h @@ -5,6 +5,7 @@ #ifndef NET_CERT_INTERNAL_VERIFY_NAME_MATCH_H_ #define NET_CERT_INTERNAL_VERIFY_NAME_MATCH_H_ +#include "base/compiler_specific.h" #include "base/strings/string_piece.h" #include "net/base/net_export.h" @@ -14,13 +15,30 @@ namespace der { class Input; } // namespace der -// Compare DER-encoded X.501 Name values according to RFC 5280 rules. +// Compares DER-encoded X.501 Name values according to RFC 5280 rules. // |a_rdn_sequence| and |b_rdn_sequence| should be the DER-encoded RDNSequence // values (not including the Sequence tag). // Returns true if |a_rdn_sequence| and |b_rdn_sequence| match. NET_EXPORT bool VerifyNameMatch(const der::Input& a_rdn_sequence, const der::Input& b_rdn_sequence); +// Compares |name_rdn_sequence| and |parent_rdn_sequence| and return true if +// |name_rdn_sequence| is within the subtree defined by |parent_rdn_sequence| as +// defined by RFC 5280 section 7.1. |name_rdn_sequence| and +// |parent_rdn_sequence| should be the DER-encoded sequence values (not +// including the Sequence tag). +NET_EXPORT bool VerifyNameInSubtree(const der::Input& name_rdn_sequence, + const der::Input& parent_rdn_sequence); + +// Helper functions: + +// Checks if |name_rdn_sequence| contains an emailAddress attribute type. +// If the return value is true, |*contained_email_address| will be set to +// indicate whether an emailAddress attribute was present. +// Returns false if there was a parsing error. +bool NameContainsEmailAddress(const der::Input& name_rdn_sequence, + bool* contained_email_address) WARN_UNUSED_RESULT; + } // namespace net #endif // NET_CERT_INTERNAL_VERIFY_NAME_MATCH_H_ diff --git a/chromium/net/cert/internal/verify_name_match_unittest.cc b/chromium/net/cert/internal/verify_name_match_unittest.cc index d6dc3884dcb..2bdf82efb68 100644 --- a/chromium/net/cert/internal/verify_name_match_unittest.cc +++ b/chromium/net/cert/internal/verify_name_match_unittest.cc @@ -7,27 +7,11 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "net/cert/internal/test_helpers.h" -#include "net/der/input.h" -#include "net/der/parser.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { namespace { -der::Input SequenceValueFromString(const std::string* s) { - der::Parser parser(InputFromString(s)); - der::Input data; - if (!parser.ReadTag(der::kSequence, &data)) { - ADD_FAILURE(); - return der::Input(); - } - if (parser.HasMore()) { - ADD_FAILURE(); - return der::Input(); - } - return data; -} - // Loads test data from file. The filename is constructed from the parameters: // |prefix| describes the type of data being tested, e.g. "ascii", // "unicode_bmp", "unicode_supplementary", and "invalid". @@ -232,6 +216,58 @@ TEST_P(VerifyNameMatchDifferingTypesTest, NormalizableTypesAreEqual) { } } +TEST_P(VerifyNameMatchDifferingTypesTest, NormalizableTypesInSubtrees) { + std::string der_1; + ASSERT_TRUE(LoadTestData("ascii", value_type_1(), "unmangled", &der_1)); + std::string der_1_extra_rdn; + ASSERT_TRUE(LoadTestData("ascii", value_type_1(), "unmangled-extra_rdn", + &der_1_extra_rdn)); + std::string der_1_extra_attr; + ASSERT_TRUE(LoadTestData("ascii", value_type_1(), "unmangled-extra_attr", + &der_1_extra_attr)); + std::string der_2; + ASSERT_TRUE(LoadTestData("ascii", value_type_2(), "unmangled", &der_2)); + std::string der_2_extra_rdn; + ASSERT_TRUE(LoadTestData("ascii", value_type_2(), "unmangled-extra_rdn", + &der_2_extra_rdn)); + std::string der_2_extra_attr; + ASSERT_TRUE(LoadTestData("ascii", value_type_2(), "unmangled-extra_attr", + &der_2_extra_attr)); + + if (TypesAreComparable(value_type_1(), value_type_2())) { + EXPECT_TRUE(VerifyNameInSubtree(SequenceValueFromString(&der_1), + SequenceValueFromString(&der_2))); + EXPECT_TRUE(VerifyNameInSubtree(SequenceValueFromString(&der_2), + SequenceValueFromString(&der_1))); + EXPECT_TRUE(VerifyNameInSubtree(SequenceValueFromString(&der_1_extra_rdn), + SequenceValueFromString(&der_2))); + EXPECT_TRUE(VerifyNameInSubtree(SequenceValueFromString(&der_2_extra_rdn), + SequenceValueFromString(&der_1))); + } else { + EXPECT_FALSE(VerifyNameInSubtree(SequenceValueFromString(&der_1), + SequenceValueFromString(&der_2))); + EXPECT_FALSE(VerifyNameInSubtree(SequenceValueFromString(&der_2), + SequenceValueFromString(&der_1))); + EXPECT_FALSE(VerifyNameInSubtree(SequenceValueFromString(&der_1_extra_rdn), + SequenceValueFromString(&der_2))); + EXPECT_FALSE(VerifyNameInSubtree(SequenceValueFromString(&der_2_extra_rdn), + SequenceValueFromString(&der_1))); + } + + EXPECT_FALSE(VerifyNameInSubtree(SequenceValueFromString(&der_1), + SequenceValueFromString(&der_2_extra_rdn))); + EXPECT_FALSE(VerifyNameInSubtree(SequenceValueFromString(&der_2), + SequenceValueFromString(&der_1_extra_rdn))); + EXPECT_FALSE(VerifyNameInSubtree(SequenceValueFromString(&der_1_extra_attr), + SequenceValueFromString(&der_2))); + EXPECT_FALSE(VerifyNameInSubtree(SequenceValueFromString(&der_2_extra_attr), + SequenceValueFromString(&der_1))); + EXPECT_FALSE(VerifyNameInSubtree(SequenceValueFromString(&der_1), + SequenceValueFromString(&der_2_extra_attr))); + EXPECT_FALSE(VerifyNameInSubtree(SequenceValueFromString(&der_2), + SequenceValueFromString(&der_1_extra_attr))); +} + // Runs VerifyNameMatchDifferingTypesTest for all combinations of value types in // value_type1 and value_type_2. INSTANTIATE_TEST_CASE_P(InstantiationName, @@ -459,4 +495,36 @@ TEST(VerifyNameMatchRDNSorting, DuplicateTypes) { SequenceValueFromString(&a))); } +TEST(VerifyNameInSubtreeInvalidDataTest, FailOnEmptyRdn) { + std::string valid; + ASSERT_TRUE(LoadTestData("ascii", "PRINTABLESTRING", "unmangled", &valid)); + std::string invalid; + ASSERT_TRUE(LoadTestData("invalid", "RDN", "empty", &invalid)); + // For both |name| and |parent|, a RelativeDistinguishedName must have at + // least one AttributeTypeAndValue. + EXPECT_FALSE(VerifyNameInSubtree(SequenceValueFromString(&valid), + SequenceValueFromString(&invalid))); + EXPECT_FALSE(VerifyNameInSubtree(SequenceValueFromString(&invalid), + SequenceValueFromString(&valid))); + EXPECT_FALSE(VerifyNameInSubtree(SequenceValueFromString(&invalid), + SequenceValueFromString(&invalid))); +} + +TEST(VerifyNameInSubtreeTest, EmptyNameMatching) { + std::string empty; + ASSERT_TRUE(LoadTestData("valid", "Name", "empty", &empty)); + std::string non_empty; + ASSERT_TRUE( + LoadTestData("ascii", "PRINTABLESTRING", "unmangled", &non_empty)); + // Empty name is in the subtree defined by empty name. + EXPECT_TRUE(VerifyNameInSubtree(SequenceValueFromString(&empty), + SequenceValueFromString(&empty))); + // Any non-empty name is in the subtree defined by empty name. + EXPECT_TRUE(VerifyNameInSubtree(SequenceValueFromString(&non_empty), + SequenceValueFromString(&empty))); + // Empty name is not in the subtree defined by non-empty name. + EXPECT_FALSE(VerifyNameInSubtree(SequenceValueFromString(&empty), + SequenceValueFromString(&non_empty))); +} + } // namespace net diff --git a/chromium/net/cert/internal/verify_signed_data_unittest.cc b/chromium/net/cert/internal/verify_signed_data_unittest.cc index a718c779a51..d7e822869cd 100644 --- a/chromium/net/cert/internal/verify_signed_data_unittest.cc +++ b/chromium/net/cert/internal/verify_signed_data_unittest.cc @@ -61,21 +61,20 @@ void RunTestCaseUsingPolicy(VerifyResult expected_result, ASSERT_TRUE(ReadTestDataFromPemFile(path, mappings)); scoped_ptr<SignatureAlgorithm> signature_algorithm = - SignatureAlgorithm::CreateFromDer(InputFromString(&algorithm)); + SignatureAlgorithm::CreateFromDer(der::Input(&algorithm)); ASSERT_TRUE(signature_algorithm); der::BitString signature_value_bit_string; - der::Parser signature_value_parser(InputFromString(&signature_value)); + der::Parser signature_value_parser((der::Input(&signature_value))); ASSERT_TRUE(signature_value_parser.ReadBitString(&signature_value_bit_string)) << "The signature value is not a valid BIT STRING"; bool expected_result_bool = expected_result == SUCCESS; - EXPECT_EQ( - expected_result_bool, - VerifySignedData(*signature_algorithm, InputFromString(&signed_data), - signature_value_bit_string, InputFromString(&public_key), - policy)); + EXPECT_EQ(expected_result_bool, + VerifySignedData(*signature_algorithm, der::Input(&signed_data), + signature_value_bit_string, + der::Input(&public_key), policy)); } // RunTestCase() is the same as RunTestCaseUsingPolicy(), only it uses a diff --git a/chromium/net/cert/jwk_serializer_nss.cc b/chromium/net/cert/jwk_serializer_nss.cc index 1db65f705ba..441a98ff4f9 100644 --- a/chromium/net/cert/jwk_serializer_nss.cc +++ b/chromium/net/cert/jwk_serializer_nss.cc @@ -8,7 +8,7 @@ #include <keyhi.h> #include <nss.h> -#include "base/base64.h" +#include "base/base64url.h" #include "base/values.h" #include "crypto/nss_util.h" #include "crypto/scoped_nss_types.h" @@ -37,7 +37,7 @@ bool ConvertEcPrime256v1PublicKeyInfoToJwk( reinterpret_cast<char*>(spki->subjectPublicKey.data + 1), kPrime256v1PublicKeyLength / 2); std::string x_b64; - base::Base64Encode(x, &x_b64); + base::Base64UrlEncode(x, base::Base64UrlEncodePolicy::OMIT_PADDING, &x_b64); public_key_jwk->SetString("x", x_b64); base::StringPiece y( @@ -45,7 +45,7 @@ bool ConvertEcPrime256v1PublicKeyInfoToJwk( kPrime256v1PublicKeyLength / 2), kPrime256v1PublicKeyLength / 2); std::string y_b64; - base::Base64Encode(y, &y_b64); + base::Base64UrlEncode(y, base::Base64UrlEncodePolicy::OMIT_PADDING, &y_b64); public_key_jwk->SetString("y", y_b64); return true; } diff --git a/chromium/net/cert/jwk_serializer_openssl.cc b/chromium/net/cert/jwk_serializer_openssl.cc index 67683fbc56d..f5afd4fb734 100644 --- a/chromium/net/cert/jwk_serializer_openssl.cc +++ b/chromium/net/cert/jwk_serializer_openssl.cc @@ -10,7 +10,7 @@ #include <openssl/evp.h> #include <openssl/x509.h> -#include "base/base64.h" +#include "base/base64url.h" #include "base/logging.h" #include "base/strings/string_util.h" #include "base/values.h" @@ -74,11 +74,13 @@ bool ConvertEcKeyToJwk(EVP_PKEY* pkey, public_key_jwk->SetString("crv", curve_name); std::string x_b64; - base::Base64Encode(x_bytes, &x_b64); + base::Base64UrlEncode(x_bytes, base::Base64UrlEncodePolicy::OMIT_PADDING, + &x_b64); public_key_jwk->SetString("x", x_b64); std::string y_b64; - base::Base64Encode(y_bytes, &y_b64); + base::Base64UrlEncode(y_bytes, base::Base64UrlEncodePolicy::OMIT_PADDING, + &y_b64); public_key_jwk->SetString("y", y_b64); return true; diff --git a/chromium/net/cert/jwk_serializer_unittest.cc b/chromium/net/cert/jwk_serializer_unittest.cc index 6fa318f3637..ec974175c1c 100644 --- a/chromium/net/cert/jwk_serializer_unittest.cc +++ b/chromium/net/cert/jwk_serializer_unittest.cc @@ -4,12 +4,14 @@ #include "net/cert/jwk_serializer.h" -#include "base/base64.h" +#include "base/base64url.h" #include "base/values.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { +namespace { + // This is the ASN.1 prefix for a P-256 public key. Specifically it's: // SEQUENCE // SEQUENCE @@ -60,6 +62,15 @@ static const unsigned char kSpkiEcWithLeadingZero[] = { 0xc9, 0x1e, 0x31, 0x89, 0xe2, 0x62, 0xcb, 0x3f }; +// Section 2 of RFC 7515 defines that an URL-safe base64 encoding must be used +// with all trailing '=' characters omitted. Returns whether the |input| +// contains any of the forbidden base64 characters (+, -, =). +bool ContainsNonUrlSafeBase64Characters(base::StringPiece input) { + return input.find_first_of("+-=") != std::string::npos; +} + +} // namespace + TEST(JwkSerializerTest, ConvertSpkiFromDerToJwkEc) { base::StringPiece spki; base::DictionaryValue public_key_jwk; @@ -78,8 +89,11 @@ TEST(JwkSerializerTest, ConvertSpkiFromDerToJwkEc) { EXPECT_STREQ("P-256", string_value.c_str()); EXPECT_TRUE(public_key_jwk.GetString("x", &string_value)); + EXPECT_FALSE(ContainsNonUrlSafeBase64Characters(string_value)); std::string decoded_coordinate; - EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate)); + EXPECT_TRUE(base::Base64UrlDecode( + string_value, base::Base64UrlDecodePolicy::DISALLOW_PADDING, + &decoded_coordinate)); EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size()); EXPECT_EQ(0, memcmp(decoded_coordinate.data(), @@ -87,7 +101,10 @@ TEST(JwkSerializerTest, ConvertSpkiFromDerToJwkEc) { kEcCoordinateSize)); EXPECT_TRUE(public_key_jwk.GetString("y", &string_value)); - EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate)); + EXPECT_FALSE(ContainsNonUrlSafeBase64Characters(string_value)); + EXPECT_TRUE(base::Base64UrlDecode( + string_value, base::Base64UrlDecodePolicy::DISALLOW_PADDING, + &decoded_coordinate)); EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size()); EXPECT_EQ(0, memcmp(decoded_coordinate.data(), @@ -106,7 +123,10 @@ TEST(JwkSerializerTest, ConvertSpkiFromDerToJwkEc) { EXPECT_STREQ("P-256", string_value.c_str()); EXPECT_TRUE(public_key_jwk.GetString("x", &string_value)); - EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate)); + EXPECT_FALSE(ContainsNonUrlSafeBase64Characters(string_value)); + EXPECT_TRUE(base::Base64UrlDecode( + string_value, base::Base64UrlDecodePolicy::DISALLOW_PADDING, + &decoded_coordinate)); EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size()); EXPECT_EQ(0, memcmp(decoded_coordinate.data(), @@ -114,7 +134,10 @@ TEST(JwkSerializerTest, ConvertSpkiFromDerToJwkEc) { kEcCoordinateSize)); EXPECT_TRUE(public_key_jwk.GetString("y", &string_value)); - EXPECT_TRUE(base::Base64Decode(string_value, &decoded_coordinate)); + EXPECT_FALSE(ContainsNonUrlSafeBase64Characters(string_value)); + EXPECT_TRUE(base::Base64UrlDecode( + string_value, base::Base64UrlDecodePolicy::DISALLOW_PADDING, + &decoded_coordinate)); EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size()); EXPECT_EQ(0, memcmp( decoded_coordinate.data(), diff --git a/chromium/net/cert/merkle_consistency_proof.cc b/chromium/net/cert/merkle_consistency_proof.cc new file mode 100644 index 00000000000..02f2b181a3d --- /dev/null +++ b/chromium/net/cert/merkle_consistency_proof.cc @@ -0,0 +1,27 @@ +// Copyright 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. + +#include "net/cert/merkle_consistency_proof.h" + +namespace net { + +namespace ct { + +MerkleConsistencyProof::MerkleConsistencyProof() {} + +MerkleConsistencyProof::MerkleConsistencyProof( + const std::string& log_id, + const std::vector<std::string>& proof_nodes, + uint64_t old_size, + uint64_t new_size) + : log_id(log_id), + nodes(proof_nodes), + first_tree_size(old_size), + second_tree_size(new_size) {} + +MerkleConsistencyProof::~MerkleConsistencyProof() {} + +} // namespace ct + +} // namespace net diff --git a/chromium/net/cert/merkle_consistency_proof.h b/chromium/net/cert/merkle_consistency_proof.h new file mode 100644 index 00000000000..48a70dc5eaa --- /dev/null +++ b/chromium/net/cert/merkle_consistency_proof.h @@ -0,0 +1,45 @@ +// Copyright 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. + +#ifndef NET_CERT_MERKLE_CONSISTENCY_PROOF_H_ +#define NET_CERT_MERKLE_CONSISTENCY_PROOF_H_ + +#include <stdint.h> + +#include <string> +#include <vector> + +#include "net/base/net_export.h" + +namespace net { + +namespace ct { + +// Consistency proof between two STHs as defined in section 2.1.2. of RFC6962. +struct NET_EXPORT MerkleConsistencyProof { + MerkleConsistencyProof(); + MerkleConsistencyProof(const std::string& log_id, + const std::vector<std::string>& proof_nodes, + uint64_t old_size, + uint64_t new_size); + ~MerkleConsistencyProof(); + + // The origin of this proof. + std::string log_id; + + // Consistency proof nodes. + std::vector<std::string> nodes; + + // Size of the older tree. + uint64_t first_tree_size = 0; + + // Size of the newer tree. + uint64_t second_tree_size = 0; +}; + +} // namespace ct + +} // namespace net + +#endif // NET_CERT_MERKLE_CONSISTENCY_PROOF_H_ diff --git a/chromium/net/cert/multi_log_ct_verifier.cc b/chromium/net/cert/multi_log_ct_verifier.cc index 7e421b2980b..d3ff7375a9c 100644 --- a/chromium/net/cert/multi_log_ct_verifier.cc +++ b/chromium/net/cert/multi_log_ct_verifier.cc @@ -62,7 +62,7 @@ MultiLogCTVerifier::MultiLogCTVerifier() : observer_(nullptr) { MultiLogCTVerifier::~MultiLogCTVerifier() { } void MultiLogCTVerifier::AddLogs( - const std::vector<scoped_refptr<CTLogVerifier>>& log_verifiers) { + const std::vector<scoped_refptr<const CTLogVerifier>>& log_verifiers) { for (const auto& log_verifier : log_verifiers) { VLOG(1) << "Adding CT log: " << log_verifier->description(); logs_[log_verifier->key_id()] = log_verifier; diff --git a/chromium/net/cert/multi_log_ct_verifier.h b/chromium/net/cert/multi_log_ct_verifier.h index 4546606112d..0d8667e6e7e 100644 --- a/chromium/net/cert/multi_log_ct_verifier.h +++ b/chromium/net/cert/multi_log_ct_verifier.h @@ -8,6 +8,7 @@ #include <map> #include <string> +#include "base/macros.h" #include "base/memory/ref_counted.h" #include "net/base/net_export.h" #include "net/cert/ct_verifier.h" @@ -23,15 +24,14 @@ class CTLogVerifier; // A Certificate Transparency verifier that can verify Signed Certificate // Timestamps from multiple logs. -// There should be a global instance of this class and for all known logs, -// AddLog should be called with a CTLogVerifier (which is created from the -// log's public key). +// It must be initialized with a list of logs by calling AddLogs. class NET_EXPORT MultiLogCTVerifier : public CTVerifier { public: MultiLogCTVerifier(); ~MultiLogCTVerifier() override; - void AddLogs(const std::vector<scoped_refptr<CTLogVerifier>>& log_verifiers); + void AddLogs( + const std::vector<scoped_refptr<const CTLogVerifier>>& log_verifiers); // CTVerifier implementation: int Verify(X509Certificate* cert, @@ -61,7 +61,7 @@ class NET_EXPORT MultiLogCTVerifier : public CTVerifier { // Mapping from a log's ID to the verifier for this log. // A log's ID is the SHA-256 of the log's key, as defined in section 3.2. // of RFC6962. - std::map<std::string, scoped_refptr<CTLogVerifier>> logs_; + std::map<std::string, scoped_refptr<const CTLogVerifier>> logs_; Observer* observer_; diff --git a/chromium/net/cert/multi_log_ct_verifier_unittest.cc b/chromium/net/cert/multi_log_ct_verifier_unittest.cc index 492c21a06d4..d5d609a8ec4 100644 --- a/chromium/net/cert/multi_log_ct_verifier_unittest.cc +++ b/chromium/net/cert/multi_log_ct_verifier_unittest.cc @@ -50,7 +50,7 @@ class MockSCTObserver : public CTVerifier::Observer { class MultiLogCTVerifierTest : public ::testing::Test { public: void SetUp() override { - scoped_refptr<CTLogVerifier> log(CTLogVerifier::Create( + scoped_refptr<const CTLogVerifier> log(CTLogVerifier::Create( ct::GetTestPublicKey(), kLogDescription, "https://ct.example.com")); ASSERT_TRUE(log); log_verifiers_.push_back(log); @@ -206,7 +206,7 @@ class MultiLogCTVerifierTest : public ::testing::Test { scoped_ptr<MultiLogCTVerifier> verifier_; scoped_refptr<X509Certificate> chain_; scoped_refptr<X509Certificate> embedded_sct_chain_; - std::vector<scoped_refptr<CTLogVerifier>> log_verifiers_; + std::vector<scoped_refptr<const CTLogVerifier>> log_verifiers_; }; TEST_F(MultiLogCTVerifierTest, VerifiesEmbeddedSCT) { diff --git a/chromium/net/cert/multi_threaded_cert_verifier.cc b/chromium/net/cert/multi_threaded_cert_verifier.cc index aef8a75288d..23f1d874ec8 100644 --- a/chromium/net/cert/multi_threaded_cert_verifier.cc +++ b/chromium/net/cert/multi_threaded_cert_verifier.cc @@ -5,6 +5,7 @@ #include "net/cert/multi_threaded_cert_verifier.h" #include <algorithm> +#include <utility> #include "base/bind.h" #include "base/bind_helpers.h" @@ -106,9 +107,9 @@ scoped_ptr<base::Value> CertVerifyResultCallback( ++it) { hashes->AppendString(it->ToString()); } - results->Set("public_key_hashes", hashes.Pass()); + results->Set("public_key_hashes", std::move(hashes)); - return results.Pass(); + return std::move(results); } } // namespace @@ -329,7 +330,7 @@ class CertVerifierJob { net_log_.source().ToEventParametersCallback()); requests_.Append(request.get()); - return request.Pass(); + return request; } private: @@ -468,7 +469,7 @@ int MultiThreadedCertVerifier::Verify(X509Certificate* cert, scoped_ptr<CertVerifierRequest> request = job->CreateRequest(callback, verify_result, net_log); - *out_req = request.Pass(); + *out_req = std::move(request); return ERR_IO_PENDING; } @@ -483,7 +484,7 @@ MultiThreadedCertVerifier::RequestParams::RequestParams( const std::string& ocsp_response_arg, int flags_arg, const CertificateList& additional_trust_anchors) - : hostname(hostname_arg), flags(flags_arg) { + : hostname(hostname_arg), flags(flags_arg), start_time(base::Time::Now()) { hash_values.reserve(3 + additional_trust_anchors.size()); SHA1HashValue ocsp_hash; base::SHA1HashBytes( @@ -522,10 +523,34 @@ void MultiThreadedCertVerifier::SaveResultToCache(const RequestParams& key, const CachedResult& result) { DCHECK(CalledOnValidThread()); - base::Time now = base::Time::Now(); + // When caching, this uses the time that validation started as the + // beginning of the validity, rather than the time that it ended (aka + // base::Time::Now()), to account for the fact that during validation, + // the clock may have changed. + // + // If the clock has changed significantly, then this result will ideally + // be evicted and the next time the certificate is encountered, it will + // be revalidated. + // + // Because of this, it's possible for situations to arise where the + // clock was correct at the start of validation, changed to an + // incorrect time during validation (such as too far in the past or + // future), and then was reset to the correct time. If this happens, + // it's likely that the result will not be a valid/correct result, + // but will still be used from the cache because the clock was reset + // to the correct time after the (bad) validation result completed. + // + // However, this solution optimizes for the case where the clock is + // bad at the start of validation, and subsequently is corrected. In + // that situation, the result is also incorrect, but because the clock + // was corrected after validation, if the cache validity period was + // computed at the end of validation, it would continue to serve an + // invalid result for kTTLSecs. + const base::Time start_time = key.start_time; cache_.Put( - key, result, CacheValidityPeriod(now), - CacheValidityPeriod(now, now + base::TimeDelta::FromSeconds(kTTLSecs))); + key, result, CacheValidityPeriod(start_time), + CacheValidityPeriod(start_time, + start_time + base::TimeDelta::FromSeconds(kTTLSecs))); } scoped_ptr<CertVerifierJob> MultiThreadedCertVerifier::RemoveJob( diff --git a/chromium/net/cert/multi_threaded_cert_verifier.h b/chromium/net/cert/multi_threaded_cert_verifier.h index 96329702415..30234ff9bc2 100644 --- a/chromium/net/cert/multi_threaded_cert_verifier.h +++ b/chromium/net/cert/multi_threaded_cert_verifier.h @@ -5,7 +5,9 @@ #ifndef NET_CERT_MULTI_THREADED_CERT_VERIFIER_H_ #define NET_CERT_MULTI_THREADED_CERT_VERIFIER_H_ +#include <stddef.h> #include <stdint.h> + #include <set> #include <string> #include <vector> @@ -97,6 +99,10 @@ class NET_EXPORT_PRIVATE MultiThreadedCertVerifier std::string hostname; int flags; std::vector<SHA1HashValue> hash_values; + // The time when verification started. + // Note: This uses base::Time, rather than base::TimeTicks, to + // account for system clock changes. + base::Time start_time; }; // CachedResult contains the result of a certificate verification. diff --git a/chromium/net/cert/nss_cert_database.cc b/chromium/net/cert/nss_cert_database.cc index c9f013324a8..53ea7c79fc5 100644 --- a/chromium/net/cert/nss_cert_database.cc +++ b/chromium/net/cert/nss_cert_database.cc @@ -9,10 +9,12 @@ #include <keyhi.h> #include <pk11pub.h> #include <secmod.h> +#include <utility> #include "base/bind.h" #include "base/callback.h" #include "base/logging.h" +#include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/observer_list_threadsafe.h" #include "base/task_runner.h" @@ -80,8 +82,8 @@ NSSCertDatabase::ImportCertFailure::~ImportCertFailure() {} NSSCertDatabase::NSSCertDatabase(crypto::ScopedPK11Slot public_slot, crypto::ScopedPK11Slot private_slot) - : public_slot_(public_slot.Pass()), - private_slot_(private_slot.Pass()), + : public_slot_(std::move(public_slot)), + private_slot_(std::move(private_slot)), observer_list_(new base::ObserverListThreadSafe<Observer>), weak_factory_(this) { CHECK(public_slot_); @@ -227,6 +229,18 @@ X509Certificate* NSSCertDatabase::FindRootInList( return cert0; } +int NSSCertDatabase::ImportUserCert(const std::string& data) { + CertificateList certificates = + X509Certificate::CreateCertificateListFromBytes( + data.c_str(), data.size(), net::X509Certificate::FORMAT_AUTO); + int result = psm::ImportUserCert(certificates); + + if (result == OK) + NotifyObserversOfCertAdded(NULL); + + return result; +} + bool NSSCertDatabase::ImportCACerts(const CertificateList& certificates, TrustBits trust_bits, ImportCertFailureList* not_imported) { diff --git a/chromium/net/cert/nss_cert_database.h b/chromium/net/cert/nss_cert_database.h index 42447f95a73..ff96af029d4 100644 --- a/chromium/net/cert/nss_cert_database.h +++ b/chromium/net/cert/nss_cert_database.h @@ -6,6 +6,7 @@ #define NET_CERT_NSS_CERT_DATABASE_H_ #include <stdint.h> + #include <string> #include <vector> @@ -192,6 +193,11 @@ class NET_EXPORT NSSCertDatabase { // TODO(mattm): improve this to handle any order. X509Certificate* FindRootInList(const CertificateList& certificates) const; + // Import a user certificate. The private key for the user certificate must + // already be installed, otherwise we return ERR_NO_PRIVATE_KEY_FOR_CERT. + // Returns OK or a network error code. + int ImportUserCert(const std::string& data); + // Import CA certificates. // Tries to import all the certificates given. The root will be trusted // according to |trust_bits|. Any certificates that could not be imported diff --git a/chromium/net/cert/nss_cert_database_chromeos.cc b/chromium/net/cert/nss_cert_database_chromeos.cc index 63d969cd7ea..fda5307f4e3 100644 --- a/chromium/net/cert/nss_cert_database_chromeos.cc +++ b/chromium/net/cert/nss_cert_database_chromeos.cc @@ -6,8 +6,8 @@ #include <cert.h> #include <pk11pub.h> - #include <algorithm> +#include <utility> #include "base/bind.h" #include "base/callback.h" @@ -21,7 +21,7 @@ namespace net { NSSCertDatabaseChromeOS::NSSCertDatabaseChromeOS( crypto::ScopedPK11Slot public_slot, crypto::ScopedPK11Slot private_slot) - : NSSCertDatabase(public_slot.Pass(), private_slot.Pass()) { + : NSSCertDatabase(std::move(public_slot), std::move(private_slot)) { // By default, don't use a system slot. Only if explicitly set by // SetSystemSlot, the system slot will be used. profile_filter_.Init(GetPublicSlot(), @@ -33,7 +33,7 @@ NSSCertDatabaseChromeOS::~NSSCertDatabaseChromeOS() {} void NSSCertDatabaseChromeOS::SetSystemSlot( crypto::ScopedPK11Slot system_slot) { - system_slot_ = system_slot.Pass(); + system_slot_ = std::move(system_slot); profile_filter_.Init(GetPublicSlot(), GetPrivateSlot(), GetSystemSlot()); } @@ -42,7 +42,7 @@ void NSSCertDatabaseChromeOS::ListCertsSync(CertificateList* certs) { } void NSSCertDatabaseChromeOS::ListCerts( - const base::Callback<void(scoped_ptr<CertificateList> certs)>& callback) { + const NSSCertDatabase::ListCertsCallback& callback) { scoped_ptr<CertificateList> certs(new CertificateList()); // base::Pased will NULL out |certs|, so cache the underlying pointer here. diff --git a/chromium/net/cert/nss_cert_database_chromeos.h b/chromium/net/cert/nss_cert_database_chromeos.h index 930f9f23e28..4eb27a7fd48 100644 --- a/chromium/net/cert/nss_cert_database_chromeos.h +++ b/chromium/net/cert/nss_cert_database_chromeos.h @@ -6,6 +6,7 @@ #define NET_CERT_NSS_CERT_DATABASE_CHROMEOS_ #include "base/callback.h" +#include "base/macros.h" #include "base/memory/weak_ptr.h" #include "crypto/scoped_nss_types.h" #include "net/base/net_export.h" diff --git a/chromium/net/cert/nss_profile_filter_chromeos.cc b/chromium/net/cert/nss_profile_filter_chromeos.cc index 8e4167a6e9b..40502e350f2 100644 --- a/chromium/net/cert/nss_profile_filter_chromeos.cc +++ b/chromium/net/cert/nss_profile_filter_chromeos.cc @@ -4,6 +4,8 @@ #include "net/cert/nss_profile_filter_chromeos.h" +#include <utility> + #include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" #include "net/cert/x509_certificate.h" @@ -71,11 +73,11 @@ void NSSProfileFilterChromeOS::Init(crypto::ScopedPK11Slot public_slot, // not release its reference, and the receiving object won't free // its copy. if (public_slot_.get() != public_slot.get()) - public_slot_ = public_slot.Pass(); + public_slot_ = std::move(public_slot); if (private_slot_.get() != private_slot.get()) - private_slot_ = private_slot.Pass(); + private_slot_ = std::move(private_slot); if (system_slot_.get() != system_slot.get()) - system_slot_ = system_slot.Pass(); + system_slot_ = std::move(system_slot); } bool NSSProfileFilterChromeOS::IsModuleAllowed(PK11SlotInfo* slot) const { diff --git a/chromium/net/cert/nss_profile_filter_chromeos_unittest.cc b/chromium/net/cert/nss_profile_filter_chromeos_unittest.cc index d4051af1197..f0243d843da 100644 --- a/chromium/net/cert/nss_profile_filter_chromeos_unittest.cc +++ b/chromium/net/cert/nss_profile_filter_chromeos_unittest.cc @@ -7,6 +7,7 @@ #include <cert.h> #include <pk11pub.h> #include <secmod.h> +#include <utility> #include "crypto/nss_util_internal.h" #include "crypto/scoped_nss_types.h" @@ -75,8 +76,7 @@ class NSSProfileFilterChromeOSTest : public testing::Test { ASSERT_TRUE(private_slot_1.get()); profile_filter_1_.Init( crypto::GetPublicSlotForChromeOSUser(user_1_.username_hash()), - private_slot_1.Pass(), - get_system_slot()); + std::move(private_slot_1), get_system_slot()); profile_filter_1_copy_ = profile_filter_1_; @@ -86,7 +86,7 @@ class NSSProfileFilterChromeOSTest : public testing::Test { ASSERT_TRUE(private_slot_2.get()); profile_filter_2_.Init( crypto::GetPublicSlotForChromeOSUser(user_2_.username_hash()), - private_slot_2.Pass(), + std::move(private_slot_2), crypto::ScopedPK11Slot() /* no system slot */); certs_ = CreateCertificateListFromFile(GetTestCertsDirectory(), diff --git a/chromium/net/cert/pem_tokenizer.h b/chromium/net/cert/pem_tokenizer.h index bb41c446db7..808acbd34e8 100644 --- a/chromium/net/cert/pem_tokenizer.h +++ b/chromium/net/cert/pem_tokenizer.h @@ -5,9 +5,12 @@ #ifndef NET_CERT_PEM_TOKENIZER_H_ #define NET_CERT_PEM_TOKENIZER_H_ +#include <stddef.h> + #include <string> #include <vector> +#include "base/macros.h" #include "base/strings/string_piece.h" #include "net/base/net_export.h" diff --git a/chromium/net/cert/signed_certificate_timestamp.h b/chromium/net/cert/signed_certificate_timestamp.h index 671c250fdc8..02697dc7a1f 100644 --- a/chromium/net/cert/signed_certificate_timestamp.h +++ b/chromium/net/cert/signed_certificate_timestamp.h @@ -8,6 +8,7 @@ #include <string> #include <vector> +#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "net/base/hash_value.h" diff --git a/chromium/net/cert/signed_tree_head.h b/chromium/net/cert/signed_tree_head.h index fdbcdc48499..161373607b2 100644 --- a/chromium/net/cert/signed_tree_head.h +++ b/chromium/net/cert/signed_tree_head.h @@ -5,6 +5,8 @@ #ifndef NET_CERT_SIGNED_TREE_HEAD_H_ #define NET_CERT_SIGNED_TREE_HEAD_H_ +#include <stdint.h> + #include <string> #include <vector> diff --git a/chromium/net/cert/test_root_certs.h b/chromium/net/cert/test_root_certs.h index 32eb999ec81..a7d0fd212de 100644 --- a/chromium/net/cert/test_root_certs.h +++ b/chromium/net/cert/test_root_certs.h @@ -6,6 +6,7 @@ #define NET_CERT_TEST_ROOT_CERTS_H_ #include "base/lazy_instance.h" +#include "base/macros.h" #include "base/memory/ref_counted.h" #include "build/build_config.h" #include "net/base/net_export.h" diff --git a/chromium/net/cert/test_root_certs_nss.cc b/chromium/net/cert/test_root_certs_nss.cc index f7d855c54b1..bcd4add1e86 100644 --- a/chromium/net/cert/test_root_certs_nss.cc +++ b/chromium/net/cert/test_root_certs_nss.cc @@ -7,6 +7,7 @@ #include <cert.h> #include "base/logging.h" +#include "base/macros.h" #include "base/stl_util.h" #include "crypto/nss_util.h" #include "net/cert/x509_certificate.h" diff --git a/chromium/net/cert/test_root_certs_win.cc b/chromium/net/cert/test_root_certs_win.cc index a83ac047905..67bf1b09f75 100644 --- a/chromium/net/cert/test_root_certs_win.cc +++ b/chromium/net/cert/test_root_certs_win.cc @@ -100,8 +100,8 @@ BOOL WINAPI InterceptedOpenStoreW(LPCSTR store_provider, // If the high word is all zeroes, then |store_provider| is a numeric ID. // Otherwise, it's a pointer to a null-terminated ASCII string. See the // documentation for CryptGetOIDFunctionAddress for more information. - uint32_t store_as_uint = reinterpret_cast<uint32_t>(store_provider); - if (store_as_uint > 0xFFFF || store_provider != CERT_STORE_PROV_SYSTEM_W || + uintptr_t store_as_uintptr = reinterpret_cast<uintptr_t>(store_provider); + if (store_as_uintptr > 0xFFFF || store_provider != CERT_STORE_PROV_SYSTEM_W || !g_capi_injector.Get().original_function) return FALSE; @@ -148,7 +148,7 @@ bool TestRootCerts::Add(X509Certificate* certificate) { CERT_STORE_ADD_NEW, NULL); if (!ok) { // If the certificate is already added, return successfully. - return GetLastError() == CRYPT_E_EXISTS; + return GetLastError() == static_cast<DWORD>(CRYPT_E_EXISTS); } empty_ = false; diff --git a/chromium/net/cert/x509_cert_types.h b/chromium/net/cert/x509_cert_types.h index 4e9340a4c0d..d2a55fe4b54 100644 --- a/chromium/net/cert/x509_cert_types.h +++ b/chromium/net/cert/x509_cert_types.h @@ -5,6 +5,7 @@ #ifndef NET_CERT_X509_CERT_TYPES_H_ #define NET_CERT_X509_CERT_TYPES_H_ +#include <stddef.h> #include <string.h> #include <map> diff --git a/chromium/net/cert/x509_certificate.cc b/chromium/net/cert/x509_certificate.cc index dc3cd80c7fd..d925ce6b490 100644 --- a/chromium/net/cert/x509_certificate.cc +++ b/chromium/net/cert/x509_certificate.cc @@ -4,6 +4,7 @@ #include "net/cert/x509_certificate.h" +#include <limits.h> #include <stdlib.h> #include <algorithm> @@ -14,6 +15,7 @@ #include "base/base64.h" #include "base/lazy_instance.h" #include "base/logging.h" +#include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/memory/singleton.h" #include "base/metrics/histogram_macros.h" @@ -301,7 +303,7 @@ X509Certificate* X509Certificate::CreateFromDERCertChain( // static X509Certificate* X509Certificate::CreateFromBytes(const char* data, - int length) { + size_t length) { OSCertHandle cert_handle = CreateOSCertHandleFromBytes(data, length); if (!cert_handle) return NULL; @@ -399,7 +401,9 @@ X509Certificate* X509Certificate::CreateFromPickle( // static CertificateList X509Certificate::CreateCertificateListFromBytes( - const char* data, int length, int format) { + const char* data, + size_t length, + int format) { OSCertHandles certificates; // Check to see if it is in a PEM-encoded form. This check is performed diff --git a/chromium/net/cert/x509_certificate.h b/chromium/net/cert/x509_certificate.h index 3cd1ad77a4d..c22a0d50d24 100644 --- a/chromium/net/cert/x509_certificate.h +++ b/chromium/net/cert/x509_certificate.h @@ -5,12 +5,14 @@ #ifndef NET_CERT_X509_CERTIFICATE_H_ #define NET_CERT_X509_CERTIFICATE_H_ +#include <stddef.h> #include <string.h> #include <string> #include <vector> #include "base/gtest_prod_util.h" +#include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/strings/string_piece.h" #include "base/time/time.h" @@ -155,7 +157,7 @@ class NET_EXPORT X509Certificate // Returns NULL on failure. // // The returned pointer must be stored in a scoped_refptr<X509Certificate>. - static X509Certificate* CreateFromBytes(const char* data, int length); + static X509Certificate* CreateFromBytes(const char* data, size_t length); #if defined(USE_NSS_CERTS) // Create an X509Certificate from the DER-encoded representation. @@ -166,7 +168,7 @@ class NET_EXPORT X509Certificate // This function differs from CreateFromBytes in that it takes a // nickname that will be used when the certificate is imported into PKCS#11. static X509Certificate* CreateFromBytesWithNickname(const char* data, - int length, + size_t length, const char* nickname); // The default nickname of the certificate, based on the certificate type @@ -189,7 +191,7 @@ class NET_EXPORT X509Certificate // certificates may have been serialized as. If an error occurs, an empty // collection will be returned. static CertificateList CreateCertificateListFromBytes(const char* data, - int length, + size_t length, int format); // Appends a representation of this object to the given pickle. @@ -362,7 +364,7 @@ class NET_EXPORT X509Certificate // Creates an OS certificate handle from the DER-encoded representation. // Returns NULL on failure. static OSCertHandle CreateOSCertHandleFromBytes(const char* data, - int length); + size_t length); #if defined(USE_NSS_CERTS) // Creates an OS certificate handle from the DER-encoded representation. @@ -370,16 +372,15 @@ class NET_EXPORT X509Certificate // non-NULL. static OSCertHandle CreateOSCertHandleFromBytesWithNickname( const char* data, - int length, + size_t length, const char* nickname); #endif // Creates all possible OS certificate handles from |data| encoded in a // specific |format|. Returns an empty collection on failure. - static OSCertHandles CreateOSCertHandlesFromBytes( - const char* data, - int length, - Format format); + static OSCertHandles CreateOSCertHandlesFromBytes(const char* data, + size_t length, + Format format); // Duplicates (or adds a reference to) an OS certificate handle. static OSCertHandle DupOSCertHandle(OSCertHandle cert_handle); diff --git a/chromium/net/cert/x509_certificate_ios.cc b/chromium/net/cert/x509_certificate_ios.cc index 9c3b333724e..d458589872d 100644 --- a/chromium/net/cert/x509_certificate_ios.cc +++ b/chromium/net/cert/x509_certificate_ios.cc @@ -24,6 +24,7 @@ #include "base/logging.h" #include "base/mac/scoped_cftyperef.h" #include "base/memory/scoped_ptr.h" +#include "base/numerics/safe_conversions.h" #include "base/pickle.h" #include "base/time/time.h" #include "crypto/nss_util.h" @@ -131,18 +132,19 @@ bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, // static X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( - const char* data, int length) { + const char* data, + size_t length) { ScopedCFTypeRef<CFDataRef> cert_data(CFDataCreateWithBytesNoCopy( - kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(data), length, - kCFAllocatorNull)); + kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), + base::checked_cast<CFIndex>(length), kCFAllocatorNull)); if (!cert_data) - return NULL; + return nullptr; OSCertHandle cert_handle = SecCertificateCreateWithData(NULL, cert_data); if (!cert_handle) - return NULL; + return nullptr; if (!IsValidOSCertHandle(cert_handle)) { CFRelease(cert_handle); - return NULL; + return nullptr; } return cert_handle; } @@ -150,7 +152,7 @@ X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( // static X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( const char* data, - int length, + size_t length, Format format) { return x509_util::CreateOSCertHandlesFromBytes(data, length, format); } diff --git a/chromium/net/cert/x509_certificate_known_roots_mac.h b/chromium/net/cert/x509_certificate_known_roots_mac.h deleted file mode 100644 index fb5d0f5b9b6..00000000000 --- a/chromium/net/cert/x509_certificate_known_roots_mac.h +++ /dev/null @@ -1,560 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef NET_CERT_X509_CERTIFICATE_KNOWN_ROOTS_MAC_H_ -#define NET_CERT_X509_CERTIFICATE_KNOWN_ROOTS_MAC_H_ - -// This is the set of Apple trusted roots from OS X 10.6.0 to -// OS X 10.10.1, available at http://opensource.apple.com -// -// Note that these *are not* trust anchors for Chromium. They are only used to -// distinguish `real' root CAs from roots that were user-installed. -static uint8_t kKnownRootCertSHA1Hashes[][20] = { - {0x01, 0x68, 0x97, 0xe1, 0xa0, 0xb8, 0xf2, 0xc3, 0xb1, 0x34, - 0x66, 0x5c, 0x20, 0xa7, 0x27, 0xb7, 0xa1, 0x58, 0xe2, 0x8f}, - {0x02, 0x72, 0x68, 0x29, 0x3e, 0x5f, 0x5d, 0x17, 0xaa, 0xa4, - 0xb3, 0xc3, 0xe6, 0x36, 0x1e, 0x1f, 0x92, 0x57, 0x5e, 0xaa}, - {0x02, 0xfa, 0xf3, 0xe2, 0x91, 0x43, 0x54, 0x68, 0x60, 0x78, - 0x57, 0x69, 0x4d, 0xf5, 0xe4, 0x5b, 0x68, 0x85, 0x18, 0x68}, - {0x03, 0x9e, 0xed, 0xb8, 0x0b, 0xe7, 0xa0, 0x3c, 0x69, 0x53, - 0x89, 0x3b, 0x20, 0xd2, 0xd9, 0x32, 0x3a, 0x4c, 0x2a, 0xfd}, - {0x04, 0x83, 0xed, 0x33, 0x99, 0xac, 0x36, 0x08, 0x05, 0x87, - 0x22, 0xed, 0xbc, 0x5e, 0x46, 0x00, 0xe3, 0xbe, 0xf9, 0xd7}, - {0x05, 0x63, 0xb8, 0x63, 0x0d, 0x62, 0xd7, 0x5a, 0xbb, 0xc8, - 0xab, 0x1e, 0x4b, 0xdf, 0xb5, 0xa8, 0x99, 0xb2, 0x4d, 0x43}, - {0x06, 0x08, 0x3f, 0x59, 0x3f, 0x15, 0xa1, 0x04, 0xa0, 0x69, - 0xa4, 0x6b, 0xa9, 0x03, 0xd0, 0x06, 0xb7, 0x97, 0x09, 0x91}, - {0x07, 0x47, 0x22, 0x01, 0x99, 0xce, 0x74, 0xb9, 0x7c, 0xb0, - 0x3d, 0x79, 0xb2, 0x64, 0xa2, 0xc8, 0x55, 0xe9, 0x33, 0xff}, - {0x07, 0xe0, 0x32, 0xe0, 0x20, 0xb7, 0x2c, 0x3f, 0x19, 0x2f, - 0x06, 0x28, 0xa2, 0x59, 0x3a, 0x19, 0xa7, 0x0f, 0x06, 0x9e}, - {0x08, 0x64, 0x18, 0xe9, 0x06, 0xce, 0xe8, 0x9c, 0x23, 0x53, - 0xb6, 0xe2, 0x7f, 0xbd, 0x9e, 0x74, 0x39, 0xf7, 0x63, 0x16}, - {0x09, 0x3c, 0x61, 0xf3, 0x8b, 0x8b, 0xdc, 0x7d, 0x55, 0xdf, - 0x75, 0x38, 0x02, 0x05, 0x00, 0xe1, 0x25, 0xf5, 0xc8, 0x36}, - {0x0b, 0x77, 0xbe, 0xbb, 0xcb, 0x7a, 0xa2, 0x47, 0x05, 0xde, - 0xcc, 0x0f, 0xbd, 0x6a, 0x02, 0xfc, 0x7a, 0xbd, 0x9b, 0x52}, - {0x0b, 0x97, 0x2c, 0x9e, 0xa6, 0xe7, 0xcc, 0x58, 0xd9, 0x3b, - 0x20, 0xbf, 0x71, 0xec, 0x41, 0x2e, 0x72, 0x09, 0xfa, 0xbf}, - {0x0c, 0x08, 0xb8, 0x4a, 0x1f, 0x26, 0xf5, 0x05, 0x49, 0xda, - 0xab, 0x36, 0x33, 0x08, 0xd3, 0x56, 0x52, 0x68, 0xf1, 0x60}, - {0x10, 0x1d, 0xfa, 0x3f, 0xd5, 0x0b, 0xcb, 0xbb, 0x9b, 0xb5, - 0x60, 0x0c, 0x19, 0x55, 0xa4, 0x1a, 0xf4, 0x73, 0x3a, 0x04}, - {0x10, 0xf1, 0x93, 0xf3, 0x40, 0xac, 0x91, 0xd6, 0xde, 0x5f, - 0x1e, 0xdc, 0x00, 0x62, 0x47, 0xc4, 0xf2, 0x5d, 0x96, 0x71}, - {0x12, 0x1f, 0x9f, 0xac, 0x62, 0x9f, 0xf1, 0x33, 0x88, 0x7c, - 0x1b, 0x45, 0x64, 0x0c, 0x1a, 0x03, 0x4f, 0x03, 0xf2, 0x8f}, - {0x13, 0x2d, 0x0d, 0x45, 0x53, 0x4b, 0x69, 0x97, 0xcd, 0xb2, - 0xd5, 0xc3, 0x39, 0xe2, 0x55, 0x76, 0x60, 0x9b, 0x5c, 0xc6}, - {0x14, 0x69, 0x89, 0x89, 0xbf, 0xb2, 0x95, 0x09, 0x21, 0xa4, - 0x24, 0x52, 0x64, 0x6d, 0x37, 0xb5, 0x0a, 0xf0, 0x17, 0xe2}, - {0x17, 0xc0, 0xc5, 0x9a, 0xb5, 0xd8, 0xd5, 0x85, 0x20, 0x43, - 0xe8, 0xec, 0x69, 0x2c, 0x40, 0x9d, 0x80, 0x62, 0xaa, 0x53}, - {0x1b, 0x4b, 0x39, 0x61, 0x26, 0x27, 0x6b, 0x64, 0x91, 0xa2, - 0x68, 0x6d, 0xd7, 0x02, 0x43, 0x21, 0x2d, 0x1f, 0x1d, 0x96}, - {0x1b, 0x8e, 0xea, 0x57, 0x96, 0x29, 0x1a, 0xc9, 0x39, 0xea, - 0xb8, 0x0a, 0x81, 0x1a, 0x73, 0x73, 0xc0, 0x93, 0x79, 0x67}, - {0x1f, 0x24, 0xc6, 0x30, 0xcd, 0xa4, 0x18, 0xef, 0x20, 0x69, - 0xff, 0xad, 0x4f, 0xdd, 0x5f, 0x46, 0x3a, 0x1b, 0x69, 0xaa}, - {0x1f, 0x49, 0x14, 0xf7, 0xd8, 0x74, 0x95, 0x1d, 0xdd, 0xae, - 0x02, 0xc0, 0xbe, 0xfd, 0x3a, 0x2d, 0x82, 0x75, 0x51, 0x85}, - {0x20, 0x42, 0x85, 0xdc, 0xf7, 0xeb, 0x76, 0x41, 0x95, 0x57, - 0x8e, 0x13, 0x6b, 0xd4, 0xb7, 0xd1, 0xe9, 0x8e, 0x46, 0xa5}, - {0x20, 0x99, 0x00, 0xb6, 0x3d, 0x95, 0x57, 0x28, 0x14, 0x0c, - 0xd1, 0x36, 0x22, 0xd8, 0xc6, 0x87, 0xa4, 0xeb, 0x00, 0x85}, - {0x20, 0xce, 0xb1, 0xf0, 0xf5, 0x1c, 0x0e, 0x19, 0xa9, 0xf3, - 0x8d, 0xb1, 0xaa, 0x8e, 0x03, 0x8c, 0xaa, 0x7a, 0xc7, 0x01}, - {0x20, 0xd8, 0x06, 0x40, 0xdf, 0x9b, 0x25, 0xf5, 0x12, 0x25, - 0x3a, 0x11, 0xea, 0xf7, 0x59, 0x8a, 0xeb, 0x14, 0xb5, 0x47}, - {0x21, 0xfc, 0xbd, 0x8e, 0x7f, 0x6c, 0xaf, 0x05, 0x1b, 0xd1, - 0xb3, 0x43, 0xec, 0xa8, 0xe7, 0x61, 0x47, 0xf2, 0x0f, 0x8a}, - {0x22, 0xd5, 0xd8, 0xdf, 0x8f, 0x02, 0x31, 0xd1, 0x8d, 0xf7, - 0x9d, 0xb7, 0xcf, 0x8a, 0x2d, 0x64, 0xc9, 0x3f, 0x6c, 0x3a}, - {0x23, 0xe5, 0x94, 0x94, 0x51, 0x95, 0xf2, 0x41, 0x48, 0x03, - 0xb4, 0xd5, 0x64, 0xd2, 0xa3, 0xa3, 0xf5, 0xd8, 0x8b, 0x8c}, - {0x25, 0x01, 0x90, 0x19, 0xcf, 0xfb, 0xd9, 0x99, 0x1c, 0xb7, - 0x68, 0x25, 0x74, 0x8d, 0x94, 0x5f, 0x30, 0x93, 0x95, 0x42}, - {0x25, 0x3f, 0x77, 0x5b, 0x0e, 0x77, 0x97, 0xab, 0x64, 0x5f, - 0x15, 0x91, 0x55, 0x97, 0xc3, 0x9e, 0x26, 0x36, 0x31, 0xd1}, - {0x26, 0xa1, 0x6c, 0x23, 0x5a, 0x24, 0x72, 0x22, 0x9b, 0x23, - 0x62, 0x80, 0x25, 0xbc, 0x80, 0x97, 0xc8, 0x85, 0x24, 0xa1}, - {0x26, 0xca, 0xff, 0x09, 0xa7, 0xaf, 0xba, 0xe9, 0x68, 0x10, - 0xcf, 0xff, 0x82, 0x1a, 0x94, 0x32, 0x6d, 0x28, 0x45, 0xaa}, - {0x27, 0x0c, 0x50, 0x0c, 0xc6, 0xc8, 0x6e, 0xcb, 0x19, 0x80, - 0xbc, 0x13, 0x05, 0x43, 0x9e, 0xd2, 0x82, 0x48, 0x0b, 0xe3}, - {0x27, 0x3e, 0xe1, 0x24, 0x57, 0xfd, 0xc4, 0xf9, 0x0c, 0x55, - 0xe8, 0x2b, 0x56, 0x16, 0x7f, 0x62, 0xf5, 0x32, 0xe5, 0x47}, - {0x27, 0x96, 0xba, 0xe6, 0x3f, 0x18, 0x01, 0xe2, 0x77, 0x26, - 0x1b, 0xa0, 0xd7, 0x77, 0x70, 0x02, 0x8f, 0x20, 0xee, 0xe4}, - {0x29, 0x36, 0x21, 0x02, 0x8b, 0x20, 0xed, 0x02, 0xf5, 0x66, - 0xc5, 0x32, 0xd1, 0xd6, 0xed, 0x90, 0x9f, 0x45, 0x00, 0x2f}, - {0x29, 0x64, 0xb6, 0x86, 0x13, 0x5b, 0x5d, 0xfd, 0xdd, 0x32, - 0x53, 0xa8, 0x9b, 0xbc, 0x24, 0xd7, 0x4b, 0x08, 0xc6, 0x4d}, - {0x2a, 0xb6, 0x28, 0x48, 0x5e, 0x78, 0xfb, 0xf3, 0xad, 0x9e, - 0x79, 0x10, 0xdd, 0x6b, 0xdf, 0x99, 0x72, 0x2c, 0x96, 0xe5}, - {0x2a, 0xc8, 0xd5, 0x8b, 0x57, 0xce, 0xbf, 0x2f, 0x49, 0xaf, - 0xf2, 0xfc, 0x76, 0x8f, 0x51, 0x14, 0x62, 0x90, 0x7a, 0x41}, - {0x2b, 0x84, 0xbf, 0xbb, 0x34, 0xee, 0x2e, 0xf9, 0x49, 0xfe, - 0x1c, 0xbe, 0x30, 0xaa, 0x02, 0x64, 0x16, 0xeb, 0x22, 0x16}, - {0x2c, 0xeb, 0x05, 0x34, 0xad, 0x59, 0x27, 0x18, 0x0d, 0x34, - 0x8c, 0x5f, 0x0e, 0x05, 0x6d, 0x38, 0x2b, 0x50, 0x82, 0x87}, - {0x2d, 0xc7, 0xab, 0xf6, 0x7e, 0x9e, 0x63, 0x9a, 0x22, 0xdb, - 0xdf, 0x4e, 0xee, 0x9b, 0xc5, 0x2a, 0x48, 0xa2, 0xcc, 0x2d}, - {0x2d, 0xff, 0x63, 0x36, 0xe3, 0x3a, 0x48, 0x29, 0xaa, 0x00, - 0x9f, 0x01, 0xa1, 0x80, 0x1e, 0xe7, 0xeb, 0xa5, 0x82, 0xbb}, - {0x2e, 0x14, 0xda, 0xec, 0x28, 0xf0, 0xfa, 0x1e, 0x8e, 0x38, - 0x9a, 0x4e, 0xab, 0xeb, 0x26, 0xc0, 0x0a, 0xd3, 0x83, 0xc3}, - {0x2e, 0xf6, 0x4b, 0xba, 0x77, 0xdd, 0x37, 0x79, 0xe9, 0x1f, - 0xbd, 0x5a, 0x4e, 0xee, 0x63, 0x3c, 0x8a, 0x36, 0xa5, 0xb1}, - {0x2f, 0x17, 0x3f, 0x7d, 0xe9, 0x96, 0x67, 0xaf, 0xa5, 0x7a, - 0xf8, 0x0a, 0xa2, 0xd1, 0xb1, 0x2f, 0xac, 0x83, 0x03, 0x38}, - {0x2f, 0x78, 0x3d, 0x25, 0x52, 0x18, 0xa7, 0x4a, 0x65, 0x39, - 0x71, 0xb5, 0x2c, 0xa2, 0x9c, 0x45, 0x15, 0x6f, 0xe9, 0x19}, - {0x30, 0x77, 0x9e, 0x93, 0x15, 0x02, 0x2e, 0x94, 0x85, 0x6a, - 0x3f, 0xf8, 0xbc, 0xf8, 0x15, 0xb0, 0x82, 0xf9, 0xae, 0xfd}, - {0x31, 0x7a, 0x2a, 0xd0, 0x7f, 0x2b, 0x33, 0x5e, 0xf5, 0xa1, - 0xc3, 0x4e, 0x4b, 0x57, 0xe8, 0xb7, 0xd8, 0xf1, 0xfc, 0xa6}, - {0x31, 0xf1, 0xfd, 0x68, 0x22, 0x63, 0x20, 0xee, 0xc6, 0x3b, - 0x3f, 0x9d, 0xea, 0x4a, 0x3e, 0x53, 0x7c, 0x7c, 0x39, 0x17}, - {0x32, 0x3c, 0x11, 0x8e, 0x1b, 0xf7, 0xb8, 0xb6, 0x52, 0x54, - 0xe2, 0xe2, 0x10, 0x0d, 0xd6, 0x02, 0x90, 0x37, 0xf0, 0x96}, - {0x33, 0x9b, 0x6b, 0x14, 0x50, 0x24, 0x9b, 0x55, 0x7a, 0x01, - 0x87, 0x72, 0x84, 0xd9, 0xe0, 0x2f, 0xc3, 0xd2, 0xd8, 0xe9}, - {0x36, 0x79, 0xca, 0x35, 0x66, 0x87, 0x72, 0x30, 0x4d, 0x30, - 0xa5, 0xfb, 0x87, 0x3b, 0x0f, 0xa7, 0x7b, 0xb7, 0x0d, 0x54}, - {0x36, 0x7d, 0x4b, 0x3b, 0x4f, 0xcb, 0xbc, 0x0b, 0x76, 0x7b, - 0x2e, 0xc0, 0xcd, 0xb2, 0xa3, 0x6e, 0xab, 0x71, 0xa4, 0xeb}, - {0x36, 0x86, 0x35, 0x63, 0xfd, 0x51, 0x28, 0xc7, 0xbe, 0xa6, - 0xf0, 0x05, 0xcf, 0xe9, 0xb4, 0x36, 0x68, 0x08, 0x6c, 0xce}, - {0x36, 0xb1, 0x2b, 0x49, 0xf9, 0x81, 0x9e, 0xd7, 0x4c, 0x9e, - 0xbc, 0x38, 0x0f, 0xc6, 0x56, 0x8f, 0x5d, 0xac, 0xb2, 0xf7}, - {0x37, 0xf7, 0x6d, 0xe6, 0x07, 0x7c, 0x90, 0xc5, 0xb1, 0x3e, - 0x93, 0x1a, 0xb7, 0x41, 0x10, 0xb4, 0xf2, 0xe4, 0x9a, 0x27}, - {0x39, 0x21, 0xc1, 0x15, 0xc1, 0x5d, 0x0e, 0xca, 0x5c, 0xcb, - 0x5b, 0xc4, 0xf0, 0x7d, 0x21, 0xd8, 0x05, 0x0b, 0x56, 0x6a}, - {0x39, 0x4f, 0xf6, 0x85, 0x0b, 0x06, 0xbe, 0x52, 0xe5, 0x18, - 0x56, 0xcc, 0x10, 0xe1, 0x80, 0xe8, 0x82, 0xb3, 0x85, 0xcc}, - {0x3a, 0x32, 0xef, 0x7b, 0x9a, 0xb8, 0x36, 0xf8, 0x37, 0x18, - 0x1a, 0x4c, 0xef, 0xa3, 0x55, 0xc6, 0x46, 0x67, 0xac, 0xbf}, - {0x3a, 0x44, 0x73, 0x5a, 0xe5, 0x81, 0x90, 0x1f, 0x24, 0x86, - 0x61, 0x46, 0x1e, 0x3b, 0x9c, 0xc4, 0x5f, 0xf5, 0x3a, 0x1b}, - {0x3b, 0x16, 0x6c, 0x3b, 0x7d, 0xc4, 0xb7, 0x51, 0xc9, 0xfe, - 0x2a, 0xfa, 0xb9, 0x13, 0x56, 0x41, 0xe3, 0x88, 0xe1, 0x86}, - {0x3b, 0xc0, 0x38, 0x0b, 0x33, 0xc3, 0xf6, 0xa6, 0x0c, 0x86, - 0x15, 0x22, 0x93, 0xd9, 0xdf, 0xf5, 0x4b, 0x81, 0xc0, 0x04}, - {0x3b, 0xc4, 0x9f, 0x48, 0xf8, 0xf3, 0x73, 0xa0, 0x9c, 0x1e, - 0xbd, 0xf8, 0x5b, 0xb1, 0xc3, 0x65, 0xc7, 0xd8, 0x11, 0xb3}, - {0x3e, 0x2b, 0xf7, 0xf2, 0x03, 0x1b, 0x96, 0xf3, 0x8c, 0xe6, - 0xc4, 0xd8, 0xa8, 0x5d, 0x3e, 0x2d, 0x58, 0x47, 0x6a, 0x0f}, - {0x3e, 0x5d, 0x35, 0x8f, 0x28, 0x3a, 0x0f, 0x64, 0x7c, 0x1c, - 0x92, 0x7f, 0xfb, 0xaa, 0xd4, 0x85, 0x2d, 0x99, 0x72, 0x56}, - {0x3f, 0x01, 0x8e, 0x6f, 0xe3, 0x36, 0x09, 0x6a, 0x79, 0x1b, - 0x81, 0xe7, 0x69, 0xbe, 0x70, 0x1a, 0xaf, 0x21, 0xe3, 0x07}, - {0x40, 0x54, 0xda, 0x6f, 0x1c, 0x3f, 0x40, 0x74, 0xac, 0xed, - 0x0f, 0xec, 0xcd, 0xdb, 0x79, 0xd1, 0x53, 0xfb, 0x90, 0x1d}, - {0x40, 0x9d, 0x4b, 0xd9, 0x17, 0xb5, 0x5c, 0x27, 0xb6, 0x9b, - 0x64, 0xcb, 0x98, 0x22, 0x44, 0x0d, 0xcd, 0x09, 0xb8, 0x89}, - {0x40, 0xaa, 0x38, 0x73, 0x1b, 0xd1, 0x89, 0xf9, 0xcd, 0xb5, - 0xb9, 0xdc, 0x35, 0xe2, 0x13, 0x6f, 0x38, 0x77, 0x7a, 0xf4}, - {0x40, 0xb3, 0x31, 0xa0, 0xe9, 0xbf, 0xe8, 0x55, 0xbc, 0x39, - 0x93, 0xca, 0x70, 0x4f, 0x4e, 0xc2, 0x51, 0xd4, 0x1d, 0x8f}, - {0x40, 0xe7, 0x8c, 0x1d, 0x52, 0x3d, 0x1c, 0xd9, 0x95, 0x4f, - 0xac, 0x1a, 0x1a, 0xb3, 0xbd, 0x3c, 0xba, 0xa1, 0x5b, 0xfc}, - {0x42, 0xf8, 0x18, 0xe8, 0x33, 0x06, 0x3b, 0xf5, 0x16, 0xc6, - 0x61, 0x8c, 0x1e, 0x60, 0xfd, 0x0f, 0x35, 0xc4, 0x76, 0x21}, - {0x43, 0x13, 0xbb, 0x96, 0xf1, 0xd5, 0x86, 0x9b, 0xc1, 0x4e, - 0x6a, 0x92, 0xf6, 0xcf, 0xf6, 0x34, 0x69, 0x87, 0x82, 0x37}, - {0x43, 0xd9, 0xbc, 0xb5, 0x68, 0xe0, 0x39, 0xd0, 0x73, 0xa7, - 0x4a, 0x71, 0xd8, 0x51, 0x1f, 0x74, 0x76, 0x08, 0x9c, 0xc3}, - {0x43, 0xf9, 0xb1, 0x10, 0xd5, 0xba, 0xfd, 0x48, 0x22, 0x52, - 0x31, 0xb0, 0xd0, 0x08, 0x2b, 0x37, 0x2f, 0xef, 0x9a, 0x54}, - {0x47, 0xbe, 0xab, 0xc9, 0x22, 0xea, 0xe8, 0x0e, 0x78, 0x78, - 0x34, 0x62, 0xa7, 0x9f, 0x45, 0xc2, 0x54, 0xfd, 0xe6, 0x8b}, - {0x48, 0x12, 0xbd, 0x92, 0x3c, 0xa8, 0xc4, 0x39, 0x06, 0xe7, - 0x30, 0x6d, 0x27, 0x96, 0xe6, 0xa4, 0xcf, 0x22, 0x2e, 0x7d}, - {0x49, 0x0a, 0x75, 0x74, 0xde, 0x87, 0x0a, 0x47, 0xfe, 0x58, - 0xee, 0xf6, 0xc7, 0x6b, 0xeb, 0xc6, 0x0b, 0x12, 0x40, 0x99}, - {0x4a, 0x3f, 0x8d, 0x6b, 0xdc, 0x0e, 0x1e, 0xcf, 0xcd, 0x72, - 0xe3, 0x77, 0xde, 0xf2, 0xd7, 0xff, 0x92, 0xc1, 0x9b, 0xc7}, - {0x4a, 0x65, 0xd5, 0xf4, 0x1d, 0xef, 0x39, 0xb8, 0xb8, 0x90, - 0x4a, 0x4a, 0xd3, 0x64, 0x81, 0x33, 0xcf, 0xc7, 0xa1, 0xd1}, - {0x4a, 0xbd, 0xee, 0xec, 0x95, 0x0d, 0x35, 0x9c, 0x89, 0xae, - 0xc7, 0x52, 0xa1, 0x2c, 0x5b, 0x29, 0xf6, 0xd6, 0xaa, 0x0c}, - {0x4a, 0xd4, 0x4d, 0x4d, 0x81, 0x2e, 0x42, 0x23, 0x2f, 0xe0, - 0x38, 0x76, 0x4c, 0x7b, 0x0c, 0xeb, 0x46, 0x6e, 0xef, 0x96}, - {0x4c, 0xab, 0x31, 0xa1, 0x28, 0x34, 0x02, 0x52, 0xbc, 0xb4, - 0x67, 0xd6, 0x2a, 0x99, 0x63, 0x1b, 0x21, 0x77, 0x20, 0x50}, - {0x4d, 0x23, 0x78, 0xec, 0x91, 0x95, 0x39, 0xb5, 0x00, 0x7f, - 0x75, 0x8f, 0x03, 0x3b, 0x21, 0x1e, 0xc5, 0x4d, 0x8b, 0xcf}, - {0x4e, 0xb6, 0xd5, 0x78, 0x49, 0x9b, 0x1c, 0xcf, 0x5f, 0x58, - 0x1e, 0xad, 0x56, 0xbe, 0x3d, 0x9b, 0x67, 0x44, 0xa5, 0xe5}, - {0x4f, 0x99, 0xaa, 0x93, 0xfb, 0x2b, 0xd1, 0x37, 0x26, 0xa1, - 0x99, 0x4a, 0xce, 0x7f, 0xf0, 0x05, 0xf2, 0x93, 0x5d, 0x1e}, - {0x50, 0x30, 0x06, 0x09, 0x1d, 0x97, 0xd4, 0xf5, 0xae, 0x39, - 0xf7, 0xcb, 0xe7, 0x92, 0x7d, 0x7d, 0x65, 0x2d, 0x34, 0x31}, - {0x51, 0x7f, 0x61, 0x1e, 0x29, 0x91, 0x6b, 0x53, 0x82, 0xfb, - 0x72, 0xe7, 0x44, 0xd9, 0x8d, 0xc3, 0xcc, 0x53, 0x6d, 0x64}, - {0x51, 0xa4, 0x4c, 0x28, 0xf3, 0x13, 0xe3, 0xf9, 0xcb, 0x5e, - 0x7c, 0x0a, 0x1e, 0x0e, 0x0d, 0xd2, 0x84, 0x37, 0x58, 0xae}, - {0x51, 0xc3, 0x24, 0x7d, 0x60, 0xf3, 0x56, 0xc7, 0xca, 0x3b, - 0xaf, 0x4c, 0x3f, 0x42, 0x9d, 0xac, 0x93, 0xee, 0x7b, 0x74}, - {0x51, 0xc6, 0xe7, 0x08, 0x49, 0x06, 0x6e, 0xf3, 0x92, 0xd4, - 0x5c, 0xa0, 0x0d, 0x6d, 0xa3, 0x62, 0x8f, 0xc3, 0x52, 0x39}, - {0x51, 0xcc, 0xa0, 0x71, 0x0a, 0xf7, 0x73, 0x3d, 0x34, 0xac, - 0xdc, 0x19, 0x45, 0x09, 0x9f, 0x43, 0x5c, 0x7f, 0xc5, 0x9f}, - {0x55, 0xa6, 0x72, 0x3e, 0xcb, 0xf2, 0xec, 0xcd, 0xc3, 0x23, - 0x74, 0x70, 0x19, 0x9d, 0x2a, 0xbe, 0x11, 0xe3, 0x81, 0xd1}, - {0x56, 0x4b, 0x6f, 0x8c, 0x56, 0x38, 0xdc, 0x05, 0x5b, 0xba, - 0x2b, 0xa1, 0x39, 0x0f, 0x7e, 0x31, 0x95, 0x4a, 0x55, 0x50}, - {0x56, 0xe0, 0xfa, 0xc0, 0x3b, 0x8f, 0x18, 0x23, 0x55, 0x18, - 0xe5, 0xd3, 0x11, 0xca, 0xe8, 0xc2, 0x43, 0x31, 0xab, 0x66}, - {0x57, 0xf0, 0x3d, 0xce, 0xfb, 0x45, 0x69, 0x4c, 0x1c, 0x25, - 0xe6, 0xee, 0xa0, 0x2c, 0x43, 0xd7, 0x52, 0x38, 0xd3, 0xc4}, - {0x58, 0x0f, 0x80, 0x47, 0x92, 0xab, 0xc6, 0x3b, 0xbb, 0x80, - 0x15, 0x4d, 0x4d, 0xfd, 0xdd, 0x8b, 0x2e, 0xf2, 0x67, 0x4e}, - {0x58, 0x11, 0x9f, 0x0e, 0x12, 0x82, 0x87, 0xea, 0x50, 0xfd, - 0xd9, 0x87, 0x45, 0x6f, 0x4f, 0x78, 0xdc, 0xfa, 0xd6, 0xd4}, - {0x58, 0xd5, 0x2d, 0xb9, 0x33, 0x01, 0xa4, 0xfd, 0x29, 0x1a, - 0x8c, 0x96, 0x45, 0xa0, 0x8f, 0xee, 0x7f, 0x52, 0x92, 0x82}, - {0x58, 0xe8, 0xab, 0xb0, 0x36, 0x15, 0x33, 0xfb, 0x80, 0xf7, - 0x9b, 0x1b, 0x6d, 0x29, 0xd3, 0xff, 0x8d, 0x5f, 0x00, 0xf0}, - {0x59, 0x0d, 0x2d, 0x7d, 0x88, 0x4f, 0x40, 0x2e, 0x61, 0x7e, - 0xa5, 0x62, 0x32, 0x17, 0x65, 0xcf, 0x17, 0xd8, 0x94, 0xe9}, - {0x59, 0x22, 0xa1, 0xe1, 0x5a, 0xea, 0x16, 0x35, 0x21, 0xf8, - 0x98, 0x39, 0x6a, 0x46, 0x46, 0xb0, 0x44, 0x1b, 0x0f, 0xa9}, - {0x59, 0xaf, 0x82, 0x79, 0x91, 0x86, 0xc7, 0xb4, 0x75, 0x07, - 0xcb, 0xcf, 0x03, 0x57, 0x46, 0xeb, 0x04, 0xdd, 0xb7, 0x16}, - {0x5a, 0x4d, 0x0e, 0x8b, 0x5f, 0xdc, 0xfd, 0xf6, 0x4e, 0x72, - 0x99, 0xa3, 0x6c, 0x06, 0x0d, 0xb2, 0x22, 0xca, 0x78, 0xe4}, - {0x5c, 0xfb, 0x1f, 0x5d, 0xb7, 0x32, 0xe4, 0x08, 0x4c, 0x0d, - 0xd4, 0x97, 0x85, 0x74, 0xe0, 0xcb, 0xc0, 0x93, 0xbe, 0xb3}, - {0x5d, 0x98, 0x9c, 0xdb, 0x15, 0x96, 0x11, 0x36, 0x51, 0x65, - 0x64, 0x1b, 0x56, 0x0f, 0xdb, 0xea, 0x2a, 0xc2, 0x3e, 0xf1}, - {0x5d, 0xe8, 0x3e, 0xe8, 0x2a, 0xc5, 0x09, 0x0a, 0xea, 0x9d, - 0x6a, 0xc4, 0xe7, 0xa6, 0xe2, 0x13, 0xf9, 0x46, 0xe1, 0x79}, - {0x5f, 0x3a, 0xfc, 0x0a, 0x8b, 0x64, 0xf6, 0x86, 0x67, 0x34, - 0x74, 0xdf, 0x7e, 0xa9, 0xa2, 0xfe, 0xf9, 0xfa, 0x7a, 0x51}, - {0x5f, 0x3b, 0x8c, 0xf2, 0xf8, 0x10, 0xb3, 0x7d, 0x78, 0xb4, - 0xce, 0xec, 0x19, 0x19, 0xc3, 0x73, 0x34, 0xb9, 0xc7, 0x74}, - {0x5f, 0x4e, 0x1f, 0xcf, 0x31, 0xb7, 0x91, 0x3b, 0x85, 0x0b, - 0x54, 0xf6, 0xe5, 0xff, 0x50, 0x1a, 0x2b, 0x6f, 0xc6, 0xcf}, - {0x5f, 0xb7, 0xee, 0x06, 0x33, 0xe2, 0x59, 0xdb, 0xad, 0x0c, - 0x4c, 0x9a, 0xe6, 0xd3, 0x8f, 0x1a, 0x61, 0xc7, 0xdc, 0x25}, - {0x61, 0x1e, 0x5b, 0x66, 0x2c, 0x59, 0x3a, 0x08, 0xff, 0x58, - 0xd1, 0x4a, 0xe2, 0x24, 0x52, 0xd1, 0x98, 0xdf, 0x6c, 0x60}, - {0x61, 0x57, 0x3a, 0x11, 0xdf, 0x0e, 0xd8, 0x7e, 0xd5, 0x92, - 0x65, 0x22, 0xea, 0xd0, 0x56, 0xd7, 0x44, 0xb3, 0x23, 0x71}, - {0x61, 0xef, 0x43, 0xd7, 0x7f, 0xca, 0xd4, 0x61, 0x51, 0xbc, - 0x98, 0xe0, 0xc3, 0x59, 0x12, 0xaf, 0x9f, 0xeb, 0x63, 0x11}, - {0x62, 0x52, 0xdc, 0x40, 0xf7, 0x11, 0x43, 0xa2, 0x2f, 0xde, - 0x9e, 0xf7, 0x34, 0x8e, 0x06, 0x42, 0x51, 0xb1, 0x81, 0x18}, - {0x62, 0x7f, 0x8d, 0x78, 0x27, 0x65, 0x63, 0x99, 0xd2, 0x7d, - 0x7f, 0x90, 0x44, 0xc9, 0xfe, 0xb3, 0xf3, 0x3e, 0xfa, 0x9a}, - {0x66, 0x31, 0xbf, 0x9e, 0xf7, 0x4f, 0x9e, 0xb6, 0xc9, 0xd5, - 0xa6, 0x0c, 0xba, 0x6a, 0xbe, 0xd1, 0xf7, 0xbd, 0xef, 0x7b}, - {0x67, 0x24, 0x90, 0x2e, 0x48, 0x01, 0xb0, 0x22, 0x96, 0x40, - 0x10, 0x46, 0xb4, 0xb1, 0x67, 0x2c, 0xa9, 0x75, 0xfd, 0x2b}, - {0x67, 0x65, 0x0d, 0xf1, 0x7e, 0x8e, 0x7e, 0x5b, 0x82, 0x40, - 0xa4, 0xf4, 0x56, 0x4b, 0xcf, 0xe2, 0x3d, 0x69, 0xc6, 0xf0}, - {0x67, 0x82, 0xaa, 0xe0, 0xed, 0xee, 0xe2, 0x1a, 0x58, 0x39, - 0xd3, 0xc0, 0xcd, 0x14, 0x68, 0x0a, 0x4f, 0x60, 0x14, 0x2a}, - {0x67, 0x9a, 0x4f, 0x81, 0xfc, 0x70, 0x5d, 0xde, 0xc4, 0x19, - 0x77, 0x8d, 0xd2, 0xeb, 0xd8, 0x75, 0xf4, 0xc2, 0x42, 0xc6}, - {0x69, 0x69, 0x56, 0x2e, 0x40, 0x80, 0xf4, 0x24, 0xa1, 0xe7, - 0x19, 0x9f, 0x14, 0xba, 0xf3, 0xee, 0x58, 0xab, 0x6a, 0xbb}, - {0x69, 0xbd, 0x8c, 0xf4, 0x9c, 0xd3, 0x00, 0xfb, 0x59, 0x2e, - 0x17, 0x93, 0xca, 0x55, 0x6a, 0xf3, 0xec, 0xaa, 0x35, 0xfb}, - {0x6a, 0x84, 0xfe, 0x62, 0x7e, 0xcc, 0x49, 0xa1, 0xbe, 0x02, - 0xe9, 0x18, 0xfa, 0xc9, 0xe1, 0xf7, 0x32, 0x80, 0x3a, 0x62}, - {0x6b, 0x2f, 0x34, 0xad, 0x89, 0x58, 0xbe, 0x62, 0xfd, 0xb0, - 0x6b, 0x5c, 0xce, 0xbb, 0x9d, 0xd9, 0x4f, 0x4e, 0x39, 0xf3}, - {0x6b, 0x81, 0x44, 0x6a, 0x5c, 0xdd, 0xf4, 0x74, 0xa0, 0xf8, - 0x00, 0xff, 0xbe, 0x69, 0xfd, 0x0d, 0xb6, 0x28, 0x75, 0x16}, - {0x6e, 0x3a, 0x55, 0xa4, 0x19, 0x0c, 0x19, 0x5c, 0x93, 0x84, - 0x3c, 0xc0, 0xdb, 0x72, 0x2e, 0x31, 0x30, 0x61, 0xf0, 0xb1}, - {0x70, 0x17, 0x9b, 0x86, 0x8c, 0x00, 0xa4, 0xfa, 0x60, 0x91, - 0x52, 0x22, 0x3f, 0x9f, 0x3e, 0x32, 0xbd, 0xe0, 0x05, 0x62}, - {0x70, 0x43, 0x2d, 0xe4, 0x3c, 0x9d, 0x1e, 0x79, 0xc1, 0x13, - 0x25, 0x20, 0xbc, 0x58, 0x43, 0xf7, 0xbb, 0x7d, 0x92, 0x95}, - {0x74, 0x20, 0x74, 0x41, 0x72, 0x9c, 0xdd, 0x92, 0xec, 0x79, - 0x31, 0xd8, 0x23, 0x10, 0x8d, 0xc2, 0x81, 0x92, 0xe2, 0xbb}, - {0x74, 0x2c, 0x31, 0x92, 0xe6, 0x07, 0xe4, 0x24, 0xeb, 0x45, - 0x49, 0x54, 0x2b, 0xe1, 0xbb, 0xc5, 0x3e, 0x61, 0x74, 0xe2}, - {0x74, 0x54, 0x53, 0x5c, 0x24, 0xa3, 0xa7, 0x58, 0x20, 0x7e, - 0x3e, 0x3e, 0xd3, 0x24, 0xf8, 0x16, 0xfb, 0x21, 0x16, 0x49}, - {0x74, 0xa2, 0x66, 0xf0, 0x95, 0xa9, 0xa4, 0xeb, 0x95, 0x22, - 0x19, 0xd6, 0x05, 0xda, 0x93, 0x63, 0xf5, 0x14, 0xfa, 0xf9}, - {0x74, 0xf8, 0xa3, 0xc3, 0xef, 0xe7, 0xb3, 0x90, 0x06, 0x4b, - 0x83, 0x90, 0x3c, 0x21, 0x64, 0x60, 0x20, 0xe5, 0xdf, 0xce}, - {0x75, 0xe0, 0xab, 0xb6, 0x13, 0x85, 0x12, 0x27, 0x1c, 0x04, - 0xf8, 0x5f, 0xdd, 0xde, 0x38, 0xe4, 0xb7, 0x24, 0x2e, 0xfe}, - {0x76, 0xe2, 0x7e, 0xc1, 0x4f, 0xdb, 0x82, 0xc1, 0xc0, 0xa6, - 0x75, 0xb5, 0x05, 0xbe, 0x3d, 0x29, 0xb4, 0xed, 0xdb, 0xbb}, - {0x77, 0x47, 0x4f, 0xc6, 0x30, 0xe4, 0x0f, 0x4c, 0x47, 0x64, - 0x3f, 0x84, 0xba, 0xb8, 0xc6, 0x95, 0x4a, 0x8a, 0x41, 0xec}, - {0x78, 0x6a, 0x74, 0xac, 0x76, 0xab, 0x14, 0x7f, 0x9c, 0x6a, - 0x30, 0x50, 0xba, 0x9e, 0xa8, 0x7e, 0xfe, 0x9a, 0xce, 0x3c}, - {0x79, 0x98, 0xa3, 0x08, 0xe1, 0x4d, 0x65, 0x85, 0xe6, 0xc2, - 0x1e, 0x15, 0x3a, 0x71, 0x9f, 0xba, 0x5a, 0xd3, 0x4a, 0xd9}, - {0x7e, 0x04, 0xde, 0x89, 0x6a, 0x3e, 0x66, 0x6d, 0x00, 0xe6, - 0x87, 0xd3, 0x3f, 0xfa, 0xd9, 0x3b, 0xe8, 0x3d, 0x34, 0x9e}, - {0x7e, 0x78, 0x4a, 0x10, 0x1c, 0x82, 0x65, 0xcc, 0x2d, 0xe1, - 0xf1, 0x6d, 0x47, 0xb4, 0x40, 0xca, 0xd9, 0x0a, 0x19, 0x45}, - {0x7f, 0x8a, 0xb0, 0xcf, 0xd0, 0x51, 0x87, 0x6a, 0x66, 0xf3, - 0x36, 0x0f, 0x47, 0xc8, 0x8d, 0x8c, 0xd3, 0x35, 0xfc, 0x74}, - {0x80, 0x1d, 0x62, 0xd0, 0x7b, 0x44, 0x9d, 0x5c, 0x5c, 0x03, - 0x5c, 0x98, 0xea, 0x61, 0xfa, 0x44, 0x3c, 0x2a, 0x58, 0xfe}, - {0x80, 0x25, 0xef, 0xf4, 0x6e, 0x70, 0xc8, 0xd4, 0x72, 0x24, - 0x65, 0x84, 0xfe, 0x40, 0x3b, 0x8a, 0x8d, 0x6a, 0xdb, 0xf5}, - {0x82, 0x50, 0xbe, 0xd5, 0xa2, 0x14, 0x43, 0x3a, 0x66, 0x37, - 0x7c, 0xbc, 0x10, 0xef, 0x83, 0xf6, 0x69, 0xda, 0x3a, 0x67}, - {0x82, 0x68, 0x99, 0x3e, 0xda, 0xeb, 0xb1, 0xe4, 0xfb, 0x77, - 0x91, 0x0f, 0x12, 0xcb, 0xd6, 0xc6, 0x70, 0xf0, 0x7c, 0xea}, - {0x84, 0xf2, 0xe3, 0xdd, 0x83, 0x13, 0x3e, 0xa9, 0x1d, 0x19, - 0x52, 0x7f, 0x02, 0xd7, 0x29, 0xbf, 0xc1, 0x5f, 0xe6, 0x67}, - {0x85, 0x37, 0x1c, 0xa6, 0xe5, 0x50, 0x14, 0x3d, 0xce, 0x28, - 0x03, 0x47, 0x1b, 0xde, 0x3a, 0x09, 0xe8, 0xf8, 0x77, 0x0f}, - {0x85, 0xa4, 0x08, 0xc0, 0x9c, 0x19, 0x3e, 0x5d, 0x51, 0x58, - 0x7d, 0xcd, 0xd6, 0x13, 0x30, 0xfd, 0x8c, 0xde, 0x37, 0xbf}, - {0x85, 0xb5, 0xff, 0x67, 0x9b, 0x0c, 0x79, 0x96, 0x1f, 0xc8, - 0x6e, 0x44, 0x22, 0x00, 0x46, 0x13, 0xdb, 0x17, 0x92, 0x84}, - {0x86, 0xe8, 0x17, 0xc8, 0x1a, 0x5c, 0xa6, 0x72, 0xfe, 0x00, - 0x0f, 0x36, 0xf8, 0x78, 0xc1, 0x95, 0x18, 0xd6, 0xf8, 0x44}, - {0x87, 0x81, 0xc2, 0x5a, 0x96, 0xbd, 0xc2, 0xfb, 0x4c, 0x65, - 0x06, 0x4f, 0xf9, 0x39, 0x0b, 0x26, 0x04, 0x8a, 0x0e, 0x01}, - {0x87, 0x82, 0xc6, 0xc3, 0x04, 0x35, 0x3b, 0xcf, 0xd2, 0x96, - 0x92, 0xd2, 0x59, 0x3e, 0x7d, 0x44, 0xd9, 0x34, 0xff, 0x11}, - {0x87, 0x9f, 0x4b, 0xee, 0x05, 0xdf, 0x98, 0x58, 0x3b, 0xe3, - 0x60, 0xd6, 0x33, 0xe7, 0x0d, 0x3f, 0xfe, 0x98, 0x71, 0xaf}, - {0x89, 0xdf, 0x74, 0xfe, 0x5c, 0xf4, 0x0f, 0x4a, 0x80, 0xf9, - 0xe3, 0x37, 0x7d, 0x54, 0xda, 0x91, 0xe1, 0x01, 0x31, 0x8e}, - {0x8b, 0xaf, 0x4c, 0x9b, 0x1d, 0xf0, 0x2a, 0x92, 0xf7, 0xda, - 0x12, 0x8e, 0xb9, 0x1b, 0xac, 0xf4, 0x98, 0x60, 0x4b, 0x6f}, - {0x8c, 0x94, 0x1b, 0x34, 0xea, 0x1e, 0xa6, 0xed, 0x9a, 0xe2, - 0xbc, 0x54, 0xcf, 0x68, 0x72, 0x52, 0xb4, 0xc9, 0xb5, 0x61}, - {0x8c, 0x96, 0xba, 0xeb, 0xdd, 0x2b, 0x07, 0x07, 0x48, 0xee, - 0x30, 0x32, 0x66, 0xa0, 0xf3, 0x98, 0x6e, 0x7c, 0xae, 0x58}, - {0x8c, 0xc4, 0x30, 0x7b, 0xc6, 0x07, 0x55, 0xe7, 0xb2, 0x2d, - 0xd9, 0xf7, 0xfe, 0xa2, 0x45, 0x93, 0x6c, 0x7c, 0xf2, 0x88}, - {0x8c, 0xf4, 0x27, 0xfd, 0x79, 0x0c, 0x3a, 0xd1, 0x66, 0x06, - 0x8d, 0xe8, 0x1e, 0x57, 0xef, 0xbb, 0x93, 0x22, 0x72, 0xd4}, - {0x8d, 0x17, 0x84, 0xd5, 0x37, 0xf3, 0x03, 0x7d, 0xec, 0x70, - 0xfe, 0x57, 0x8b, 0x51, 0x9a, 0x99, 0xe6, 0x10, 0xd7, 0xb0}, - {0x8e, 0x1c, 0x74, 0xf8, 0xa6, 0x20, 0xb9, 0xe5, 0x8a, 0xf4, - 0x61, 0xfa, 0xec, 0x2b, 0x47, 0x56, 0x51, 0x1a, 0x52, 0xc6}, - {0x8e, 0x5b, 0xd5, 0x0d, 0x6a, 0xe6, 0x86, 0xd6, 0x52, 0x52, - 0xf8, 0x43, 0xa9, 0xd4, 0xb9, 0x6d, 0x19, 0x77, 0x30, 0xab}, - {0x90, 0x5f, 0x94, 0x2f, 0xd9, 0xf2, 0x8f, 0x67, 0x9b, 0x37, - 0x81, 0x80, 0xfd, 0x4f, 0x84, 0x63, 0x47, 0xf6, 0x45, 0xc1}, - {0x90, 0xae, 0xa2, 0x69, 0x85, 0xff, 0x14, 0x80, 0x4c, 0x43, - 0x49, 0x52, 0xec, 0xe9, 0x60, 0x84, 0x77, 0xaf, 0x55, 0x6f}, - {0x91, 0xc6, 0xd6, 0xee, 0x3e, 0x8a, 0xc8, 0x63, 0x84, 0xe5, - 0x48, 0xc2, 0x99, 0x29, 0x5c, 0x75, 0x6c, 0x81, 0x7b, 0x81}, - {0x92, 0x5a, 0x8f, 0x8d, 0x2c, 0x6d, 0x04, 0xe0, 0x66, 0x5f, - 0x59, 0x6a, 0xff, 0x22, 0xd8, 0x63, 0xe8, 0x25, 0x6f, 0x3f}, - {0x93, 0xe6, 0xab, 0x22, 0x03, 0x03, 0xb5, 0x23, 0x28, 0xdc, - 0xda, 0x56, 0x9e, 0xba, 0xe4, 0xd1, 0xd1, 0xcc, 0xfb, 0x65}, - {0x94, 0x32, 0xbd, 0x9a, 0xec, 0x1d, 0x75, 0xd1, 0x70, 0x5c, - 0x54, 0x3a, 0xa3, 0x4c, 0x4a, 0xf6, 0xa5, 0x26, 0xc1, 0x3d}, - {0x96, 0x56, 0xcd, 0x7b, 0x57, 0x96, 0x98, 0x95, 0xd0, 0xe1, - 0x41, 0x46, 0x68, 0x06, 0xfb, 0xb8, 0xc6, 0x11, 0x06, 0x87}, - {0x96, 0x83, 0x38, 0xf1, 0x13, 0xe3, 0x6a, 0x7b, 0xab, 0xdd, - 0x08, 0xf7, 0x77, 0x63, 0x91, 0xa6, 0x87, 0x36, 0x58, 0x2e}, - {0x96, 0xc9, 0x1b, 0x0b, 0x95, 0xb4, 0x10, 0x98, 0x42, 0xfa, - 0xd0, 0xd8, 0x22, 0x79, 0xfe, 0x60, 0xfa, 0xb9, 0x16, 0x83}, - {0x97, 0x81, 0x79, 0x50, 0xd8, 0x1c, 0x96, 0x70, 0xcc, 0x34, - 0xd8, 0x09, 0xcf, 0x79, 0x44, 0x31, 0x36, 0x7e, 0xf4, 0x74}, - {0x98, 0x45, 0xa4, 0x31, 0xd5, 0x19, 0x59, 0xca, 0xf2, 0x25, - 0x32, 0x2b, 0x4a, 0x4f, 0xe9, 0xf2, 0x23, 0xce, 0x6d, 0x15}, - {0x99, 0xa6, 0x9b, 0xe6, 0x1a, 0xfe, 0x88, 0x6b, 0x4d, 0x2b, - 0x82, 0x00, 0x7c, 0xb8, 0x54, 0xfc, 0x31, 0x7e, 0x15, 0x39}, - {0x9b, 0xaa, 0xe5, 0x9f, 0x56, 0xee, 0x21, 0xcb, 0x43, 0x5a, - 0xbe, 0x25, 0x93, 0xdf, 0xa7, 0xf0, 0x40, 0xd1, 0x1d, 0xcb}, - {0x9c, 0xbb, 0x48, 0x53, 0xf6, 0xa4, 0xf6, 0xd3, 0x52, 0xa4, - 0xe8, 0x32, 0x52, 0x55, 0x60, 0x13, 0xf5, 0xad, 0xaf, 0x65}, - {0x9d, 0x70, 0xbb, 0x01, 0xa5, 0xa4, 0xa0, 0x18, 0x11, 0x2e, - 0xf7, 0x1c, 0x01, 0xb9, 0x32, 0xc5, 0x34, 0xe7, 0x88, 0xa8}, - {0x9f, 0xad, 0x91, 0xa6, 0xce, 0x6a, 0xc6, 0xc5, 0x00, 0x47, - 0xc4, 0x4e, 0xc9, 0xd4, 0xa5, 0x0d, 0x92, 0xd8, 0x49, 0x79}, - {0xa0, 0xa1, 0xab, 0x90, 0xc9, 0xfc, 0x84, 0x7b, 0x3b, 0x12, - 0x61, 0xe8, 0x97, 0x7d, 0x5f, 0xd3, 0x22, 0x61, 0xd3, 0xcc}, - {0xa1, 0x4b, 0x48, 0xd9, 0x43, 0xee, 0x0a, 0x0e, 0x40, 0x90, - 0x4f, 0x3c, 0xe0, 0xa4, 0xc0, 0x91, 0x93, 0x51, 0x5d, 0x3f}, - {0xa1, 0xdb, 0x63, 0x93, 0x91, 0x6f, 0x17, 0xe4, 0x18, 0x55, - 0x09, 0x40, 0x04, 0x15, 0xc7, 0x02, 0x40, 0xb0, 0xae, 0x6b}, - {0xa2, 0x48, 0x41, 0xab, 0xd6, 0xa0, 0xca, 0x5c, 0xcd, 0x2a, - 0xa3, 0xb1, 0x90, 0x70, 0x1e, 0xd6, 0x4b, 0x39, 0xfe, 0x53}, - {0xa3, 0xf1, 0x33, 0x3f, 0xe2, 0x42, 0xbf, 0xcf, 0xc5, 0xd1, - 0x4e, 0x8f, 0x39, 0x42, 0x98, 0x40, 0x68, 0x10, 0xd1, 0xa0}, - {0xa6, 0x76, 0xdb, 0xf1, 0x92, 0x48, 0xf5, 0x2c, 0x57, 0x53, - 0xd0, 0xda, 0xc1, 0x4c, 0x53, 0xc4, 0x74, 0xa4, 0x83, 0x5e}, - {0xa6, 0x9a, 0x91, 0xfd, 0x05, 0x7f, 0x13, 0x6a, 0x42, 0x63, - 0x0b, 0xb1, 0x76, 0x0d, 0x2d, 0x51, 0x12, 0x0c, 0x16, 0x50}, - {0xa8, 0x98, 0x5d, 0x3a, 0x65, 0xe5, 0xe5, 0xc4, 0xb2, 0xd7, - 0xd6, 0x6d, 0x40, 0xc6, 0xdd, 0x2f, 0xb1, 0x9c, 0x54, 0x36}, - {0xaa, 0xdb, 0xbc, 0x22, 0x23, 0x8f, 0xc4, 0x01, 0xa1, 0x27, - 0xbb, 0x38, 0xdd, 0xf4, 0x1d, 0xdb, 0x08, 0x9e, 0xf0, 0x12}, - {0xac, 0xed, 0x5f, 0x65, 0x53, 0xfd, 0x25, 0xce, 0x01, 0x5f, - 0x1f, 0x7a, 0x48, 0x3b, 0x6a, 0x74, 0x9f, 0x61, 0x78, 0xc6}, - {0xad, 0x7e, 0x1c, 0x28, 0xb0, 0x64, 0xef, 0x8f, 0x60, 0x03, - 0x40, 0x20, 0x14, 0xc3, 0xd0, 0xe3, 0x37, 0x0e, 0xb5, 0x8a}, - {0xae, 0x3b, 0x31, 0xbf, 0x8f, 0xd8, 0x91, 0x07, 0x9c, 0xf1, - 0xdf, 0x34, 0xcb, 0xce, 0x6e, 0x70, 0xd3, 0x7f, 0xb5, 0xb0}, - {0xae, 0x50, 0x83, 0xed, 0x7c, 0xf4, 0x5c, 0xbc, 0x8f, 0x61, - 0xc6, 0x21, 0xfe, 0x68, 0x5d, 0x79, 0x42, 0x21, 0x15, 0x6e}, - {0xae, 0xc5, 0xfb, 0x3f, 0xc8, 0xe1, 0xbf, 0xc4, 0xe5, 0x4f, - 0x03, 0x07, 0x5a, 0x9a, 0xe8, 0x00, 0xb7, 0xf7, 0xb6, 0xfa}, - {0xb0, 0x91, 0xaa, 0x91, 0x38, 0x47, 0xf3, 0x13, 0xd7, 0x27, - 0xbc, 0xef, 0xc8, 0x17, 0x9f, 0x08, 0x6f, 0x3a, 0x8c, 0x0f}, - {0xb1, 0x2e, 0x13, 0x63, 0x45, 0x86, 0xa4, 0x6f, 0x1a, 0xb2, - 0x60, 0x68, 0x37, 0x58, 0x2d, 0xc4, 0xac, 0xfd, 0x94, 0x97}, - {0xb1, 0x72, 0xb1, 0xa5, 0x6d, 0x95, 0xf9, 0x1f, 0xe5, 0x02, - 0x87, 0xe1, 0x4d, 0x37, 0xea, 0x6a, 0x44, 0x63, 0x76, 0x8a}, - {0xb1, 0xbc, 0x96, 0x8b, 0xd4, 0xf4, 0x9d, 0x62, 0x2a, 0xa8, - 0x9a, 0x81, 0xf2, 0x15, 0x01, 0x52, 0xa4, 0x1d, 0x82, 0x9c}, - {0xb3, 0x1e, 0xb1, 0xb7, 0x40, 0xe3, 0x6c, 0x84, 0x02, 0xda, - 0xdc, 0x37, 0xd4, 0x4d, 0xf5, 0xd4, 0x67, 0x49, 0x52, 0xf9}, - {0xb3, 0xea, 0xc4, 0x47, 0x76, 0xc9, 0xc8, 0x1c, 0xea, 0xf2, - 0x9d, 0x95, 0xb6, 0xcc, 0xa0, 0x08, 0x1b, 0x67, 0xec, 0x9d}, - {0xb4, 0x35, 0xd4, 0xe1, 0x11, 0x9d, 0x1c, 0x66, 0x90, 0xa7, - 0x49, 0xeb, 0xb3, 0x94, 0xbd, 0x63, 0x7b, 0xa7, 0x82, 0xb7}, - {0xb4, 0x57, 0x12, 0x1e, 0x63, 0x45, 0xff, 0x93, 0x5d, 0x6b, - 0x1c, 0xa2, 0xdd, 0xf4, 0x52, 0x3c, 0xc6, 0xd0, 0xef, 0x6b}, - {0xb5, 0x1c, 0x06, 0x7c, 0xee, 0x2b, 0x0c, 0x3d, 0xf8, 0x55, - 0xab, 0x2d, 0x92, 0xf4, 0xfe, 0x39, 0xd4, 0xe7, 0x0f, 0x0e}, - {0xb5, 0x2c, 0xb0, 0x2f, 0xd5, 0x67, 0xe0, 0x35, 0x9f, 0xe8, - 0xfa, 0x4d, 0x4c, 0x41, 0x03, 0x79, 0x70, 0xfe, 0x01, 0xb0}, - {0xb5, 0x61, 0xeb, 0xea, 0xa4, 0xde, 0xe4, 0x25, 0x4b, 0x69, - 0x1a, 0x98, 0xa5, 0x57, 0x47, 0xc2, 0x34, 0xc7, 0xd9, 0x71}, - {0xb6, 0xca, 0x21, 0x5b, 0x83, 0x6c, 0x35, 0x10, 0x1d, 0xaf, - 0x74, 0x63, 0x90, 0x0a, 0x93, 0x68, 0x80, 0x76, 0x7a, 0xa6}, - {0xb8, 0x01, 0x86, 0xd1, 0xeb, 0x9c, 0x86, 0xa5, 0x41, 0x04, - 0xcf, 0x30, 0x54, 0xf3, 0x4c, 0x52, 0xb7, 0xe5, 0x58, 0xc6}, - {0xb8, 0x23, 0x6b, 0x00, 0x2f, 0x1d, 0x16, 0x86, 0x53, 0x01, - 0x55, 0x6c, 0x11, 0xa4, 0x37, 0xca, 0xeb, 0xff, 0xc3, 0xbb}, - {0xb8, 0x6e, 0x79, 0x16, 0x20, 0xf7, 0x59, 0xf1, 0x7b, 0x8d, - 0x25, 0xe3, 0x8c, 0xa8, 0xbe, 0x32, 0xe7, 0xd5, 0xea, 0xc2}, - {0xba, 0x29, 0x41, 0x60, 0x77, 0x98, 0x3f, 0xf4, 0xf3, 0xef, - 0xf2, 0x31, 0x05, 0x3b, 0x2e, 0xea, 0x6d, 0x4d, 0x45, 0xfd}, - {0xc0, 0x60, 0xed, 0x44, 0xcb, 0xd8, 0x81, 0xbd, 0x0e, 0xf8, - 0x6c, 0x0b, 0xa2, 0x87, 0xdd, 0xcf, 0x81, 0x67, 0x47, 0x8c}, - {0xc8, 0xec, 0x8c, 0x87, 0x92, 0x69, 0xcb, 0x4b, 0xab, 0x39, - 0xe9, 0x8d, 0x7e, 0x57, 0x67, 0xf3, 0x14, 0x95, 0x73, 0x9d}, - {0xc9, 0xa8, 0xb9, 0xe7, 0x55, 0x80, 0x5e, 0x58, 0xe3, 0x53, - 0x77, 0xa7, 0x25, 0xeb, 0xaf, 0xc3, 0x7b, 0x27, 0xcc, 0xd7}, - {0xca, 0x39, 0xd8, 0xea, 0x48, 0x22, 0x13, 0x7f, 0x33, 0x8d, - 0xca, 0x79, 0x56, 0x6e, 0xdd, 0xf0, 0x54, 0x7e, 0xce, 0xa7}, - {0xca, 0x3a, 0xfb, 0xcf, 0x12, 0x40, 0x36, 0x4b, 0x44, 0xb2, - 0x16, 0x20, 0x88, 0x80, 0x48, 0x39, 0x19, 0x93, 0x7c, 0xf7}, - {0xcb, 0x44, 0xa0, 0x97, 0x85, 0x7c, 0x45, 0xfa, 0x18, 0x7e, - 0xd9, 0x52, 0x08, 0x6c, 0xb9, 0x84, 0x1f, 0x2d, 0x51, 0xb5}, - {0xcb, 0x65, 0x82, 0x64, 0xea, 0x8c, 0xda, 0x18, 0x6e, 0x17, - 0x52, 0xfb, 0x52, 0xc3, 0x97, 0x36, 0x7e, 0xa3, 0x87, 0xbe}, - {0xcb, 0xa1, 0xc5, 0xf8, 0xb0, 0xe3, 0x5e, 0xb8, 0xb9, 0x45, - 0x12, 0xd3, 0xf9, 0x34, 0xa2, 0xe9, 0x06, 0x10, 0xd3, 0x36}, - {0xcc, 0xab, 0x0e, 0xa0, 0x4c, 0x23, 0x01, 0xd6, 0x69, 0x7b, - 0xdd, 0x37, 0x9f, 0xcd, 0x12, 0xeb, 0x24, 0xe3, 0x94, 0x9d}, - {0xce, 0x6a, 0x64, 0xa3, 0x09, 0xe4, 0x2f, 0xbb, 0xd9, 0x85, - 0x1c, 0x45, 0x3e, 0x64, 0x09, 0xea, 0xe8, 0x7d, 0x60, 0xf1}, - {0xcf, 0x9e, 0x87, 0x6d, 0xd3, 0xeb, 0xfc, 0x42, 0x26, 0x97, - 0xa3, 0xb5, 0xa3, 0x7a, 0xa0, 0x76, 0xa9, 0x06, 0x23, 0x48}, - {0xd1, 0xeb, 0x23, 0xa4, 0x6d, 0x17, 0xd6, 0x8f, 0xd9, 0x25, - 0x64, 0xc2, 0xf1, 0xf1, 0x60, 0x17, 0x64, 0xd8, 0xe3, 0x49}, - {0xd2, 0x32, 0x09, 0xad, 0x23, 0xd3, 0x14, 0x23, 0x21, 0x74, - 0xe4, 0x0d, 0x7f, 0x9d, 0x62, 0x13, 0x97, 0x86, 0x63, 0x3a}, - {0xd2, 0x44, 0x1a, 0xa8, 0xc2, 0x03, 0xae, 0xca, 0xa9, 0x6e, - 0x50, 0x1f, 0x12, 0x4d, 0x52, 0xb6, 0x8f, 0xe4, 0xc3, 0x75}, - {0xd3, 0xc0, 0x63, 0xf2, 0x19, 0xed, 0x07, 0x3e, 0x34, 0xad, - 0x5d, 0x75, 0x0b, 0x32, 0x76, 0x29, 0xff, 0xd5, 0x9a, 0xf2}, - {0xd3, 0xee, 0xfb, 0xcb, 0xbc, 0xf4, 0x98, 0x67, 0x83, 0x86, - 0x26, 0xe2, 0x3b, 0xb5, 0x9c, 0xa0, 0x1e, 0x30, 0x5d, 0xb7}, - {0xd4, 0x37, 0x19, 0xb5, 0x1b, 0x57, 0xca, 0x4b, 0xb8, 0x74, - 0x16, 0x7d, 0x47, 0x95, 0x23, 0x1d, 0x34, 0x34, 0xfd, 0xa8}, - {0xd4, 0xde, 0x20, 0xd0, 0x5e, 0x66, 0xfc, 0x53, 0xfe, 0x1a, - 0x50, 0x88, 0x2c, 0x78, 0xdb, 0x28, 0x52, 0xca, 0xe4, 0x74}, - {0xd6, 0x9b, 0x56, 0x11, 0x48, 0xf0, 0x1c, 0x77, 0xc5, 0x45, - 0x78, 0xc1, 0x09, 0x26, 0xdf, 0x5b, 0x85, 0x69, 0x76, 0xad}, - {0xd6, 0xda, 0xa8, 0x20, 0x8d, 0x09, 0xd2, 0x15, 0x4d, 0x24, - 0xb5, 0x2f, 0xcb, 0x34, 0x6e, 0xb2, 0x58, 0xb2, 0x8a, 0x58}, - {0xd8, 0xa6, 0x33, 0x2c, 0xe0, 0x03, 0x6f, 0xb1, 0x85, 0xf6, - 0x63, 0x4f, 0x7d, 0x6a, 0x06, 0x65, 0x26, 0x32, 0x28, 0x27}, - {0xd8, 0xc5, 0x38, 0x8a, 0xb7, 0x30, 0x1b, 0x1b, 0x6e, 0xd4, - 0x7a, 0xe6, 0x45, 0x25, 0x3a, 0x6f, 0x9f, 0x1a, 0x27, 0x61}, - {0xda, 0x40, 0x18, 0x8b, 0x91, 0x89, 0xa3, 0xed, 0xee, 0xae, - 0xda, 0x97, 0xfe, 0x2f, 0x9d, 0xf5, 0xb7, 0xd1, 0x8a, 0x41}, - {0xda, 0xc9, 0x02, 0x4f, 0x54, 0xd8, 0xf6, 0xdf, 0x94, 0x93, - 0x5f, 0xb1, 0x73, 0x26, 0x38, 0xca, 0x6a, 0xd7, 0x7c, 0x13}, - {0xda, 0xfa, 0xf7, 0xfa, 0x66, 0x84, 0xec, 0x06, 0x8f, 0x14, - 0x50, 0xbd, 0xc7, 0xc2, 0x81, 0xa5, 0xbc, 0xa9, 0x64, 0x57}, - {0xdd, 0xfb, 0x16, 0xcd, 0x49, 0x31, 0xc9, 0x73, 0xa2, 0x03, - 0x7d, 0x3f, 0xc8, 0x3a, 0x4d, 0x7d, 0x77, 0x5d, 0x05, 0xe4}, - {0xde, 0x28, 0xf4, 0xa4, 0xff, 0xe5, 0xb9, 0x2f, 0xa3, 0xc5, - 0x03, 0xd1, 0xa3, 0x49, 0xa7, 0xf9, 0x96, 0x2a, 0x82, 0x12}, - {0xde, 0x3f, 0x40, 0xbd, 0x50, 0x93, 0xd3, 0x9b, 0x6c, 0x60, - 0xf6, 0xda, 0xbc, 0x07, 0x62, 0x01, 0x00, 0x89, 0x76, 0xc9}, - {0xde, 0x99, 0x0c, 0xed, 0x99, 0xe0, 0x43, 0x1f, 0x60, 0xed, - 0xc3, 0x93, 0x7e, 0x7c, 0xd5, 0xbf, 0x0e, 0xd9, 0xe5, 0xfa}, - {0xdf, 0x3c, 0x24, 0xf9, 0xbf, 0xd6, 0x66, 0x76, 0x1b, 0x26, - 0x80, 0x73, 0xfe, 0x06, 0xd1, 0xcc, 0x8d, 0x4f, 0x82, 0xa4}, - {0xdf, 0x71, 0x7e, 0xaa, 0x4a, 0xd9, 0x4e, 0xc9, 0x55, 0x84, - 0x99, 0x60, 0x2d, 0x48, 0xde, 0x5f, 0xbc, 0xf0, 0x3a, 0x25}, - {0xdf, 0xdf, 0xac, 0x89, 0x47, 0xbd, 0xf7, 0x52, 0x64, 0xa9, - 0x23, 0x3a, 0xc1, 0x0e, 0xe3, 0xd1, 0x28, 0x33, 0xda, 0xcc}, - {0xe0, 0x5f, 0x7c, 0x22, 0x59, 0x8c, 0x12, 0x56, 0xa7, 0xb9, - 0x4d, 0x92, 0xd3, 0xd1, 0x94, 0x50, 0x8c, 0x8c, 0xba, 0x71}, - {0xe0, 0xab, 0x05, 0x94, 0x20, 0x72, 0x54, 0x93, 0x05, 0x60, - 0x62, 0x02, 0x36, 0x70, 0xf7, 0xcd, 0x2e, 0xfc, 0x66, 0x66}, - {0xe1, 0x2d, 0xfb, 0x4b, 0x41, 0xd7, 0xd9, 0xc3, 0x2b, 0x30, - 0x51, 0x4b, 0xac, 0x1d, 0x81, 0xd8, 0x38, 0x5e, 0x2d, 0x46}, - {0xe1, 0x9f, 0xe3, 0x0e, 0x8b, 0x84, 0x60, 0x9e, 0x80, 0x9b, - 0x17, 0x0d, 0x72, 0xa8, 0xc5, 0xba, 0x6e, 0x14, 0x09, 0xbd}, - {0xe1, 0xa4, 0x5b, 0x14, 0x1a, 0x21, 0xda, 0x1a, 0x79, 0xf4, - 0x1a, 0x42, 0xa9, 0x61, 0xd6, 0x69, 0xcd, 0x06, 0x34, 0xc1}, - {0xe3, 0x92, 0x51, 0x2f, 0x0a, 0xcf, 0xf5, 0x05, 0xdf, 0xf6, - 0xde, 0x06, 0x7f, 0x75, 0x37, 0xe1, 0x65, 0xea, 0x57, 0x4b}, - {0xe5, 0xdf, 0x74, 0x3c, 0xb6, 0x01, 0xc4, 0x9b, 0x98, 0x43, - 0xdc, 0xab, 0x8c, 0xe8, 0x6a, 0x81, 0x10, 0x9f, 0xe4, 0x8e}, - {0xe6, 0x18, 0x83, 0xae, 0x84, 0xca, 0xc1, 0xc1, 0xcd, 0x52, - 0xad, 0xe8, 0xe9, 0x25, 0x2b, 0x45, 0xa6, 0x4f, 0xb7, 0xe2}, - {0xe6, 0x19, 0xd2, 0x5b, 0x38, 0x0b, 0x7b, 0x13, 0xfd, 0xa3, - 0x3e, 0x8a, 0x58, 0xcd, 0x82, 0xd8, 0xa8, 0x8e, 0x05, 0x15}, - {0xe7, 0xa1, 0x90, 0x29, 0xd3, 0xd5, 0x52, 0xdc, 0x0d, 0x0f, - 0xc6, 0x92, 0xd3, 0xea, 0x88, 0x0d, 0x15, 0x2e, 0x1a, 0x6b}, - {0xe7, 0xb4, 0xf6, 0x9d, 0x61, 0xec, 0x90, 0x69, 0xdb, 0x7e, - 0x90, 0xa7, 0x40, 0x1a, 0x3c, 0xf4, 0x7d, 0x4f, 0xe8, 0xee}, - {0xee, 0xef, 0xaa, 0x0b, 0xcd, 0x11, 0xaf, 0x5c, 0x02, 0xfa, - 0x96, 0x20, 0x6a, 0xc5, 0xc6, 0x2b, 0xa7, 0x24, 0xd6, 0x0a}, - {0xf0, 0x0f, 0xc3, 0x7d, 0x6a, 0x1c, 0x92, 0x61, 0xfb, 0x6b, - 0xc1, 0xc2, 0x18, 0x49, 0x8c, 0x5a, 0xa4, 0xdc, 0x51, 0xfb}, - {0xf1, 0x7f, 0x6f, 0xb6, 0x31, 0xdc, 0x99, 0xe3, 0xa3, 0xc8, - 0x7f, 0xfe, 0x1c, 0xf1, 0x81, 0x10, 0x88, 0xd9, 0x60, 0x33}, - {0xf1, 0x8b, 0x53, 0x8d, 0x1b, 0xe9, 0x03, 0xb6, 0xa6, 0xf0, - 0x56, 0x43, 0x5b, 0x17, 0x15, 0x89, 0xca, 0xf3, 0x6b, 0xf2}, - {0xf3, 0x73, 0xb3, 0x87, 0x06, 0x5a, 0x28, 0x84, 0x8a, 0xf2, - 0xf3, 0x4a, 0xce, 0x19, 0x2b, 0xdd, 0xc7, 0x8e, 0x9c, 0xac}, - {0xf5, 0x17, 0xa2, 0x4f, 0x9a, 0x48, 0xc6, 0xc9, 0xf8, 0xa2, - 0x00, 0x26, 0x9f, 0xdc, 0x0f, 0x48, 0x2c, 0xab, 0x30, 0x89}, - {0xf7, 0x4d, 0xac, 0xb2, 0x14, 0x14, 0xdc, 0xba, 0xab, 0x0b, - 0x94, 0x7c, 0x8a, 0x25, 0x7c, 0x32, 0x5c, 0xa8, 0x85, 0x50}, - {0xf8, 0xa5, 0x4e, 0x03, 0xaa, 0xdc, 0x56, 0x92, 0xb8, 0x50, - 0x49, 0x6a, 0x4c, 0x46, 0x30, 0xff, 0xea, 0xa2, 0x9d, 0x83}, - {0xf9, 0xb5, 0xb6, 0x32, 0x45, 0x5f, 0x9c, 0xbe, 0xec, 0x57, - 0x5f, 0x80, 0xdc, 0xe9, 0x6e, 0x2c, 0xc7, 0xb2, 0x78, 0xb7}, - {0xf9, 0xcd, 0x0e, 0x2c, 0xda, 0x76, 0x24, 0xc1, 0x8f, 0xbd, - 0xf0, 0xf0, 0xab, 0xb6, 0x45, 0xb8, 0xf7, 0xfe, 0xd5, 0x7a}, - {0xfa, 0xa7, 0xd9, 0xfb, 0x31, 0xb7, 0x46, 0xf2, 0x00, 0xa8, - 0x5e, 0x65, 0x79, 0x76, 0x13, 0xd8, 0x16, 0xe0, 0x63, 0xb5}, - {0xfa, 0xb7, 0xee, 0x36, 0x97, 0x26, 0x62, 0xfb, 0x2d, 0xb0, - 0x2a, 0xf6, 0xbf, 0x03, 0xfd, 0xe8, 0x7c, 0x4b, 0x2f, 0x9b}, - {0xfc, 0x21, 0x9a, 0x76, 0x11, 0x2f, 0x76, 0xc1, 0xc5, 0x08, - 0x83, 0x3c, 0x9a, 0x2f, 0xa2, 0xba, 0x84, 0xac, 0x08, 0x7a}, - {0xfe, 0x45, 0x65, 0x9b, 0x79, 0x03, 0x5b, 0x98, 0xa1, 0x61, - 0xb5, 0x51, 0x2e, 0xac, 0xda, 0x58, 0x09, 0x48, 0x22, 0x4d}, - {0xfe, 0xb8, 0xc4, 0x32, 0xdc, 0xf9, 0x76, 0x9a, 0xce, 0xae, - 0x3d, 0xd8, 0x90, 0x8f, 0xfd, 0x28, 0x86, 0x65, 0x64, 0x7d}, - {0xff, 0xad, 0x0e, 0x26, 0xf0, 0x5b, 0xbc, 0xd8, 0x06, 0x3c, - 0xce, 0x1d, 0xfa, 0x60, 0x24, 0x5e, 0x14, 0x3d, 0x53, 0x80}, -}; - -#endif // NET_CERT_X509_CERTIFICATE_KNOWN_ROOTS_MAC_H_ diff --git a/chromium/net/cert/x509_certificate_known_roots_win.h b/chromium/net/cert/x509_certificate_known_roots_win.h index ce7dce86e86..f914ec865d7 100644 --- a/chromium/net/cert/x509_certificate_known_roots_win.h +++ b/chromium/net/cert/x509_certificate_known_roots_win.h @@ -5,8 +5,10 @@ #ifndef NET_CERT_X509_CERTIFICATE_KNOWN_ROOTS_WIN_H_ #define NET_CERT_X509_CERTIFICATE_KNOWN_ROOTS_WIN_H_ -// This is a union of Microsoft trust roots over time, from 29 April -// 2013 through 15 May 2015. +#include <stdint.h> + +// This is a union of Microsoft trust roots over time, from 01 January +// 2007 through 24 November 2015. // // Extracted from // http://www.download.windowsupdate.com/msdownload/update/v3/ @@ -14,829 +16,1878 @@ // // Note that these *are not* trust anchors for Chromium. They are only used to // distinguish `real' root CAs from roots that were user-installed. -static uint8_t kKnownRootCertSHA1Hashes[][20] = { - {0x00, 0x48, 0xf8, 0xd3, 0x7b, 0x15, 0x3f, 0x6e, 0xa2, 0x79, - 0x8c, 0x32, 0x3e, 0xf4, 0xf3, 0x18, 0xa5, 0x62, 0x4a, 0x9e}, - {0x00, 0xea, 0x52, 0x2c, 0x8a, 0x9c, 0x06, 0xaa, 0x3e, 0xcc, - 0xe0, 0xb4, 0xfa, 0x6c, 0xdc, 0x21, 0xd9, 0x2e, 0x80, 0x99}, - {0x01, 0x68, 0x97, 0xe1, 0xa0, 0xb8, 0xf2, 0xc3, 0xb1, 0x34, - 0x66, 0x5c, 0x20, 0xa7, 0x27, 0xb7, 0xa1, 0x58, 0xe2, 0x8f}, - {0x02, 0x72, 0x68, 0x29, 0x3e, 0x5f, 0x5d, 0x17, 0xaa, 0xa4, - 0xb3, 0xc3, 0xe6, 0x36, 0x1e, 0x1f, 0x92, 0x57, 0x5e, 0xaa}, - {0x02, 0xfa, 0xf3, 0xe2, 0x91, 0x43, 0x54, 0x68, 0x60, 0x78, - 0x57, 0x69, 0x4d, 0xf5, 0xe4, 0x5b, 0x68, 0x85, 0x18, 0x68}, - {0x03, 0x9e, 0xed, 0xb8, 0x0b, 0xe7, 0xa0, 0x3c, 0x69, 0x53, - 0x89, 0x3b, 0x20, 0xd2, 0xd9, 0x32, 0x3a, 0x4c, 0x2a, 0xfd}, - {0x04, 0x09, 0x56, 0x5b, 0x77, 0xda, 0x58, 0x2e, 0x64, 0x95, - 0xac, 0x00, 0x60, 0xa7, 0x23, 0x54, 0xe6, 0x4b, 0x01, 0x92}, - {0x04, 0x46, 0xc8, 0xbb, 0x9a, 0x69, 0x83, 0xc9, 0x5c, 0x8a, - 0x2e, 0x54, 0x64, 0x68, 0x7c, 0x11, 0x15, 0xaa, 0xb7, 0x4a}, - {0x04, 0x56, 0xf2, 0x3d, 0x1e, 0x9c, 0x43, 0xae, 0xcb, 0x0d, - 0x80, 0x7f, 0x1c, 0x06, 0x47, 0x55, 0x1a, 0x05, 0xf4, 0x56}, - {0x04, 0x83, 0xed, 0x33, 0x99, 0xac, 0x36, 0x08, 0x05, 0x87, - 0x22, 0xed, 0xbc, 0x5e, 0x46, 0x00, 0xe3, 0xbe, 0xf9, 0xd7}, - {0x04, 0x98, 0x11, 0x05, 0x6a, 0xfe, 0x9f, 0xd0, 0xf5, 0xbe, - 0x01, 0x68, 0x5a, 0xac, 0xe6, 0xa5, 0xd1, 0xc4, 0x45, 0x4c}, - {0x05, 0x60, 0xa2, 0xc7, 0x38, 0xff, 0x98, 0xd1, 0x17, 0x2a, - 0x94, 0xfe, 0x45, 0xfb, 0x8a, 0x47, 0xd6, 0x65, 0x37, 0x1e}, - {0x05, 0x63, 0xb8, 0x63, 0x0d, 0x62, 0xd7, 0x5a, 0xbb, 0xc8, - 0xab, 0x1e, 0x4b, 0xdf, 0xb5, 0xa8, 0x99, 0xb2, 0x4d, 0x43}, - {0x06, 0x08, 0x3f, 0x59, 0x3f, 0x15, 0xa1, 0x04, 0xa0, 0x69, - 0xa4, 0x6b, 0xa9, 0x03, 0xd0, 0x06, 0xb7, 0x97, 0x09, 0x91}, - {0x06, 0x14, 0x31, 0x51, 0xe0, 0x2b, 0x45, 0xdd, 0xba, 0xdd, - 0x5d, 0x8e, 0x56, 0x53, 0x0d, 0xaa, 0xe3, 0x28, 0xcf, 0x90}, - {0x07, 0x47, 0x22, 0x01, 0x99, 0xce, 0x74, 0xb9, 0x7c, 0xb0, - 0x3d, 0x79, 0xb2, 0x64, 0xa2, 0xc8, 0x55, 0xe9, 0x33, 0xff}, - {0x07, 0xe0, 0x32, 0xe0, 0x20, 0xb7, 0x2c, 0x3f, 0x19, 0x2f, - 0x06, 0x28, 0xa2, 0x59, 0x3a, 0x19, 0xa7, 0x0f, 0x06, 0x9e}, - {0x08, 0x64, 0x18, 0xe9, 0x06, 0xce, 0xe8, 0x9c, 0x23, 0x53, - 0xb6, 0xe2, 0x7f, 0xbd, 0x9e, 0x74, 0x39, 0xf7, 0x63, 0x16}, - {0x09, 0x3c, 0x61, 0xf3, 0x8b, 0x8b, 0xdc, 0x7d, 0x55, 0xdf, - 0x75, 0x38, 0x02, 0x05, 0x00, 0xe1, 0x25, 0xf5, 0xc8, 0x36}, - {0x0b, 0x71, 0x99, 0xa1, 0xc7, 0xf3, 0xad, 0xdf, 0x7b, 0xa7, - 0xea, 0xb8, 0xeb, 0x57, 0x4a, 0xe8, 0x0d, 0x60, 0xdd, 0xde}, - {0x0b, 0x77, 0xbe, 0xbb, 0xcb, 0x7a, 0xa2, 0x47, 0x05, 0xde, - 0xcc, 0x0f, 0xbd, 0x6a, 0x02, 0xfc, 0x7a, 0xbd, 0x9b, 0x52}, - {0x0b, 0x97, 0x2c, 0x9e, 0xa6, 0xe7, 0xcc, 0x58, 0xd9, 0x3b, - 0x20, 0xbf, 0x71, 0xec, 0x41, 0x2e, 0x72, 0x09, 0xfa, 0xbf}, - {0x0c, 0x62, 0x8f, 0x5c, 0x55, 0x70, 0xb1, 0xc9, 0x57, 0xfa, - 0xfd, 0x38, 0x3f, 0xb0, 0x3d, 0x7b, 0x7d, 0xd7, 0xb9, 0xc6}, - {0x0c, 0xfd, 0x83, 0xdb, 0xae, 0x44, 0xb9, 0xa0, 0xc8, 0xf6, - 0x76, 0xf3, 0xb5, 0x70, 0x65, 0x0b, 0x94, 0xb6, 0x9d, 0xbf}, - {0x10, 0x1d, 0xfa, 0x3f, 0xd5, 0x0b, 0xcb, 0xbb, 0x9b, 0xb5, - 0x60, 0x0c, 0x19, 0x55, 0xa4, 0x1a, 0xf4, 0x73, 0x3a, 0x04}, - {0x11, 0xc5, 0xb5, 0xf7, 0x55, 0x52, 0xb0, 0x11, 0x66, 0x9c, - 0x2e, 0x97, 0x17, 0xde, 0x6d, 0x9b, 0xff, 0x5f, 0xa8, 0x10}, - {0x11, 0xe1, 0x9b, 0xbc, 0x74, 0x7b, 0x1a, 0xed, 0x0d, 0xb8, - 0x33, 0xc9, 0x4c, 0xac, 0x6c, 0x3f, 0x85, 0xbd, 0xeb, 0xdb}, - {0x13, 0x2d, 0x0d, 0x45, 0x53, 0x4b, 0x69, 0x97, 0xcd, 0xb2, - 0xd5, 0xc3, 0x39, 0xe2, 0x55, 0x76, 0x60, 0x9b, 0x5c, 0xc6}, - {0x15, 0x03, 0x32, 0xa5, 0x8d, 0xc5, 0x91, 0xfc, 0x42, 0xd4, - 0xc8, 0x73, 0xff, 0x9f, 0x1f, 0x0f, 0x81, 0xd5, 0x97, 0xc9}, - {0x16, 0x32, 0x47, 0x8d, 0x89, 0xf9, 0x21, 0x3a, 0x92, 0x00, - 0x85, 0x63, 0xf5, 0xa4, 0xa7, 0xd3, 0x12, 0x40, 0x8a, 0xd6}, - {0x16, 0xd8, 0x66, 0x35, 0xaf, 0x13, 0x41, 0xcd, 0x34, 0x79, - 0x94, 0x45, 0xeb, 0x60, 0x3e, 0x27, 0x37, 0x02, 0x96, 0x5d}, - {0x18, 0xf7, 0xc1, 0xfc, 0xc3, 0x09, 0x02, 0x03, 0xfd, 0x5b, - 0xaa, 0x2f, 0x86, 0x1a, 0x75, 0x49, 0x76, 0xc8, 0xdd, 0x25}, - {0x1a, 0xc9, 0x2f, 0x09, 0xea, 0x89, 0xe2, 0x8b, 0x12, 0x6d, - 0xfa, 0xc5, 0x1e, 0x3a, 0xf7, 0xea, 0x90, 0x95, 0xa3, 0xee}, - {0x1b, 0x4b, 0x39, 0x61, 0x26, 0x27, 0x6b, 0x64, 0x91, 0xa2, - 0x68, 0x6d, 0xd7, 0x02, 0x43, 0x21, 0x2d, 0x1f, 0x1d, 0x96}, - {0x1b, 0x8e, 0xea, 0x57, 0x96, 0x29, 0x1a, 0xc9, 0x39, 0xea, - 0xb8, 0x0a, 0x81, 0x1a, 0x73, 0x73, 0xc0, 0x93, 0x79, 0x67}, - {0x1f, 0x24, 0xc6, 0x30, 0xcd, 0xa4, 0x18, 0xef, 0x20, 0x69, - 0xff, 0xad, 0x4f, 0xdd, 0x5f, 0x46, 0x3a, 0x1b, 0x69, 0xaa}, - {0x1f, 0x49, 0x14, 0xf7, 0xd8, 0x74, 0x95, 0x1d, 0xdd, 0xae, - 0x02, 0xc0, 0xbe, 0xfd, 0x3a, 0x2d, 0x82, 0x75, 0x51, 0x85}, - {0x20, 0x42, 0x85, 0xdc, 0xf7, 0xeb, 0x76, 0x41, 0x95, 0x57, - 0x8e, 0x13, 0x6b, 0xd4, 0xb7, 0xd1, 0xe9, 0x8e, 0x46, 0xa5}, - {0x20, 0x99, 0x00, 0xb6, 0x3d, 0x95, 0x57, 0x28, 0x14, 0x0c, - 0xd1, 0x36, 0x22, 0xd8, 0xc6, 0x87, 0xa4, 0xeb, 0x00, 0x85}, - {0x20, 0xcb, 0x59, 0x4f, 0xb4, 0xed, 0xd8, 0x95, 0x76, 0x3f, - 0xd5, 0x25, 0x4e, 0x95, 0x9a, 0x66, 0x74, 0xc6, 0xee, 0xb2}, - {0x20, 0xd8, 0x06, 0x40, 0xdf, 0x9b, 0x25, 0xf5, 0x12, 0x25, - 0x3a, 0x11, 0xea, 0xf7, 0x59, 0x8a, 0xeb, 0x14, 0xb5, 0x47}, - {0x21, 0x11, 0x65, 0xca, 0x37, 0x9f, 0xbb, 0x5e, 0xd8, 0x01, - 0xe3, 0x1c, 0x43, 0x0a, 0x62, 0xaa, 0xc1, 0x09, 0xbc, 0xb4}, - {0x21, 0x6b, 0x2a, 0x29, 0xe6, 0x2a, 0x00, 0xce, 0x82, 0x01, - 0x46, 0xd8, 0x24, 0x41, 0x41, 0xb9, 0x25, 0x11, 0xb2, 0x79}, - {0x21, 0xfc, 0xbd, 0x8e, 0x7f, 0x6c, 0xaf, 0x05, 0x1b, 0xd1, - 0xb3, 0x43, 0xec, 0xa8, 0xe7, 0x61, 0x47, 0xf2, 0x0f, 0x8a}, - {0x22, 0xd5, 0xd8, 0xdf, 0x8f, 0x02, 0x31, 0xd1, 0x8d, 0xf7, - 0x9d, 0xb7, 0xcf, 0x8a, 0x2d, 0x64, 0xc9, 0x3f, 0x6c, 0x3a}, - {0x23, 0x88, 0xc9, 0xd3, 0x71, 0xcc, 0x9e, 0x96, 0x3d, 0xff, - 0x7d, 0x3c, 0xa7, 0xce, 0xfc, 0xd6, 0x25, 0xec, 0x19, 0x0d}, - {0x23, 0xe5, 0x94, 0x94, 0x51, 0x95, 0xf2, 0x41, 0x48, 0x03, - 0xb4, 0xd5, 0x64, 0xd2, 0xa3, 0xa3, 0xf5, 0xd8, 0x8b, 0x8c}, - {0x23, 0xe8, 0x33, 0x23, 0x3e, 0x7d, 0x0c, 0xc9, 0x2b, 0x7c, - 0x42, 0x79, 0xac, 0x19, 0xc2, 0xf4, 0x74, 0xd6, 0x04, 0xca}, - {0x24, 0x5c, 0x97, 0xdf, 0x75, 0x14, 0xe7, 0xcf, 0x2d, 0xf8, - 0xbe, 0x72, 0xae, 0x95, 0x7b, 0x9e, 0x04, 0x74, 0x1e, 0x85}, - {0x24, 0xa4, 0x0a, 0x1f, 0x57, 0x36, 0x43, 0xa6, 0x7f, 0x0a, - 0x4b, 0x07, 0x49, 0xf6, 0xa2, 0x2b, 0xf2, 0x8a, 0xbb, 0x6b}, - {0x24, 0xba, 0x6d, 0x6c, 0x8a, 0x5b, 0x58, 0x37, 0xa4, 0x8d, - 0xb5, 0xfa, 0xe9, 0x19, 0xea, 0x67, 0x5c, 0x94, 0xd2, 0x17}, - {0x25, 0x01, 0x90, 0x19, 0xcf, 0xfb, 0xd9, 0x99, 0x1c, 0xb7, - 0x68, 0x25, 0x74, 0x8d, 0x94, 0x5f, 0x30, 0x93, 0x95, 0x42}, - {0x25, 0x3f, 0x77, 0x5b, 0x0e, 0x77, 0x97, 0xab, 0x64, 0x5f, - 0x15, 0x91, 0x55, 0x97, 0xc3, 0x9e, 0x26, 0x36, 0x31, 0xd1}, - {0x26, 0xa1, 0x6c, 0x23, 0x5a, 0x24, 0x72, 0x22, 0x9b, 0x23, - 0x62, 0x80, 0x25, 0xbc, 0x80, 0x97, 0xc8, 0x85, 0x24, 0xa1}, - {0x27, 0x3e, 0xe1, 0x24, 0x57, 0xfd, 0xc4, 0xf9, 0x0c, 0x55, - 0xe8, 0x2b, 0x56, 0x16, 0x7f, 0x62, 0xf5, 0x32, 0xe5, 0x47}, - {0x27, 0x96, 0xba, 0xe6, 0x3f, 0x18, 0x01, 0xe2, 0x77, 0x26, - 0x1b, 0xa0, 0xd7, 0x77, 0x70, 0x02, 0x8f, 0x20, 0xee, 0xe4}, - {0x28, 0x90, 0x3a, 0x63, 0x5b, 0x52, 0x80, 0xfa, 0xe6, 0x77, - 0x4c, 0x0b, 0x6d, 0xa7, 0xd6, 0xba, 0xa6, 0x4a, 0xf2, 0xe8}, - {0x29, 0x36, 0x21, 0x02, 0x8b, 0x20, 0xed, 0x02, 0xf5, 0x66, - 0xc5, 0x32, 0xd1, 0xd6, 0xed, 0x90, 0x9f, 0x45, 0x00, 0x2f}, - {0x29, 0x64, 0xb6, 0x86, 0x13, 0x5b, 0x5d, 0xfd, 0xdd, 0x32, - 0x53, 0xa8, 0x9b, 0xbc, 0x24, 0xd7, 0x4b, 0x08, 0xc6, 0x4d}, - {0x2a, 0xc8, 0xd5, 0x8b, 0x57, 0xce, 0xbf, 0x2f, 0x49, 0xaf, - 0xf2, 0xfc, 0x76, 0x8f, 0x51, 0x14, 0x62, 0x90, 0x7a, 0x41}, - {0x2b, 0x8f, 0x1b, 0x57, 0x33, 0x0d, 0xbb, 0xa2, 0xd0, 0x7a, - 0x6c, 0x51, 0xf7, 0x0e, 0xe9, 0x0d, 0xda, 0xb9, 0xad, 0x8e}, - {0x2b, 0xb1, 0xf5, 0x3e, 0x55, 0x0c, 0x1d, 0xc5, 0xf1, 0xd4, - 0xe6, 0xb7, 0x6a, 0x46, 0x4b, 0x55, 0x06, 0x02, 0xac, 0x21}, - {0x2e, 0x14, 0xda, 0xec, 0x28, 0xf0, 0xfa, 0x1e, 0x8e, 0x38, - 0x9a, 0x4e, 0xab, 0xeb, 0x26, 0xc0, 0x0a, 0xd3, 0x83, 0xc3}, - {0x2e, 0x66, 0xc9, 0x84, 0x11, 0x81, 0xc0, 0x8f, 0xb1, 0xdf, - 0xab, 0xd4, 0xff, 0x8d, 0x5c, 0xc7, 0x2b, 0xe0, 0x8f, 0x02}, - {0x30, 0x70, 0xf8, 0x83, 0x3e, 0x4a, 0xa6, 0x80, 0x3e, 0x09, - 0xa6, 0x46, 0xae, 0x3f, 0x7d, 0x8a, 0xe1, 0xfd, 0x16, 0x54}, - {0x30, 0x77, 0x9e, 0x93, 0x15, 0x02, 0x2e, 0x94, 0x85, 0x6a, - 0x3f, 0xf8, 0xbc, 0xf8, 0x15, 0xb0, 0x82, 0xf9, 0xae, 0xfd}, - {0x31, 0x7a, 0x2a, 0xd0, 0x7f, 0x2b, 0x33, 0x5e, 0xf5, 0xa1, - 0xc3, 0x4e, 0x4b, 0x57, 0xe8, 0xb7, 0xd8, 0xf1, 0xfc, 0xa6}, - {0x31, 0xe2, 0xc5, 0x2c, 0xe1, 0x08, 0x9b, 0xef, 0xfd, 0xda, - 0xdb, 0x26, 0xdd, 0x7c, 0x78, 0x2e, 0xbc, 0x40, 0x37, 0xbd}, - {0x31, 0xf1, 0xfd, 0x68, 0x22, 0x63, 0x20, 0xee, 0xc6, 0x3b, - 0x3f, 0x9d, 0xea, 0x4a, 0x3e, 0x53, 0x7c, 0x7c, 0x39, 0x17}, - {0x32, 0x3c, 0x11, 0x8e, 0x1b, 0xf7, 0xb8, 0xb6, 0x52, 0x54, - 0xe2, 0xe2, 0x10, 0x0d, 0xd6, 0x02, 0x90, 0x37, 0xf0, 0x96}, - {0x33, 0x5a, 0x7f, 0xf0, 0x09, 0x27, 0xcf, 0x2d, 0xf2, 0x78, - 0xe2, 0xc9, 0x19, 0x2f, 0x7a, 0x4d, 0x55, 0x34, 0xf8, 0x0c}, - {0x33, 0x9b, 0x6b, 0x14, 0x50, 0x24, 0x9b, 0x55, 0x7a, 0x01, - 0x87, 0x72, 0x84, 0xd9, 0xe0, 0x2f, 0xc3, 0xd2, 0xd8, 0xe9}, - {0x34, 0x2c, 0xd9, 0xd3, 0x06, 0x2d, 0xa4, 0x8c, 0x34, 0x69, - 0x65, 0x29, 0x7f, 0x08, 0x1e, 0xbc, 0x2e, 0xf6, 0x8f, 0xdc}, - {0x34, 0xd4, 0x99, 0x42, 0x6f, 0x9f, 0xc2, 0xbb, 0x27, 0xb0, - 0x75, 0xba, 0xb6, 0x82, 0xaa, 0xe5, 0xef, 0xfc, 0xba, 0x74}, - {0x36, 0x79, 0xca, 0x35, 0x66, 0x87, 0x72, 0x30, 0x4d, 0x30, - 0xa5, 0xfb, 0x87, 0x3b, 0x0f, 0xa7, 0x7b, 0xb7, 0x0d, 0x54}, - {0x36, 0x86, 0x35, 0x63, 0xfd, 0x51, 0x28, 0xc7, 0xbe, 0xa6, - 0xf0, 0x05, 0xcf, 0xe9, 0xb4, 0x36, 0x68, 0x08, 0x6c, 0xce}, - {0x36, 0xb1, 0x2b, 0x49, 0xf9, 0x81, 0x9e, 0xd7, 0x4c, 0x9e, - 0xbc, 0x38, 0x0f, 0xc6, 0x56, 0x8f, 0x5d, 0xac, 0xb2, 0xf7}, - {0x37, 0x9a, 0x19, 0x7b, 0x41, 0x85, 0x45, 0x35, 0x0c, 0xa6, - 0x03, 0x69, 0xf3, 0x3c, 0x2e, 0xaf, 0x47, 0x4f, 0x20, 0x79}, - {0x37, 0xf7, 0x6d, 0xe6, 0x07, 0x7c, 0x90, 0xc5, 0xb1, 0x3e, - 0x93, 0x1a, 0xb7, 0x41, 0x10, 0xb4, 0xf2, 0xe4, 0x9a, 0x27}, - {0x38, 0xdd, 0x76, 0x59, 0xc7, 0x35, 0x10, 0x0b, 0x00, 0xa2, - 0x37, 0xe4, 0x91, 0xb7, 0xbc, 0x0f, 0xfc, 0xd2, 0x31, 0x6c}, - {0x39, 0x13, 0x85, 0x3e, 0x45, 0xc4, 0x39, 0xa2, 0xda, 0x71, - 0x8c, 0xdf, 0xb6, 0xf3, 0xe0, 0x33, 0xe0, 0x4f, 0xee, 0x71}, - {0x39, 0x21, 0xc1, 0x15, 0xc1, 0x5d, 0x0e, 0xca, 0x5c, 0xcb, - 0x5b, 0xc4, 0xf0, 0x7d, 0x21, 0xd8, 0x05, 0x0b, 0x56, 0x6a}, - {0x39, 0x41, 0x0b, 0xc2, 0x30, 0x37, 0x48, 0x06, 0x60, 0x69, - 0xa7, 0x2a, 0x66, 0x4d, 0xe4, 0xc7, 0x43, 0x48, 0x12, 0x96}, - {0x39, 0x4f, 0xf6, 0x85, 0x0b, 0x06, 0xbe, 0x52, 0xe5, 0x18, - 0x56, 0xcc, 0x10, 0xe1, 0x80, 0xe8, 0x82, 0xb3, 0x85, 0xcc}, - {0x39, 0x8e, 0xbe, 0x9c, 0x0f, 0x46, 0xc0, 0x79, 0xc3, 0xc7, - 0xaf, 0xe0, 0x7a, 0x2f, 0xdd, 0x9f, 0xae, 0x5f, 0x8a, 0x5c}, - {0x3a, 0x44, 0x73, 0x5a, 0xe5, 0x81, 0x90, 0x1f, 0x24, 0x86, - 0x61, 0x46, 0x1e, 0x3b, 0x9c, 0xc4, 0x5f, 0xf5, 0x3a, 0x1b}, - {0x3b, 0x1e, 0xfd, 0x3a, 0x66, 0xea, 0x28, 0xb1, 0x66, 0x97, - 0x39, 0x47, 0x03, 0xa7, 0x2c, 0xa3, 0x40, 0xa0, 0x5b, 0xd5}, - {0x3b, 0xc0, 0x38, 0x0b, 0x33, 0xc3, 0xf6, 0xa6, 0x0c, 0x86, - 0x15, 0x22, 0x93, 0xd9, 0xdf, 0xf5, 0x4b, 0x81, 0xc0, 0x04}, - {0x3b, 0xc4, 0x9f, 0x48, 0xf8, 0xf3, 0x73, 0xa0, 0x9c, 0x1e, - 0xbd, 0xf8, 0x5b, 0xb1, 0xc3, 0x65, 0xc7, 0xd8, 0x11, 0xb3}, - {0x3c, 0x71, 0xd7, 0x0e, 0x35, 0xa5, 0xda, 0xa8, 0xb2, 0xe3, - 0x81, 0x2d, 0xc3, 0x67, 0x74, 0x17, 0xf5, 0x99, 0x0d, 0xf3}, - {0x3e, 0x2b, 0xf7, 0xf2, 0x03, 0x1b, 0x96, 0xf3, 0x8c, 0xe6, - 0xc4, 0xd8, 0xa8, 0x5d, 0x3e, 0x2d, 0x58, 0x47, 0x6a, 0x0f}, - {0x3e, 0x42, 0xa1, 0x87, 0x06, 0xbd, 0x0c, 0x9c, 0xcf, 0x59, - 0x47, 0x50, 0xd2, 0xe4, 0xd6, 0xab, 0x00, 0x48, 0xfd, 0xc4}, - {0x3e, 0x5d, 0x35, 0x8f, 0x28, 0x3a, 0x0f, 0x64, 0x7c, 0x1c, - 0x92, 0x7f, 0xfb, 0xaa, 0xd4, 0x85, 0x2d, 0x99, 0x72, 0x56}, - {0x3e, 0x84, 0xd3, 0xbc, 0xc5, 0x44, 0xc0, 0xf6, 0xfa, 0x19, - 0x43, 0x5c, 0x85, 0x1f, 0x3f, 0x2f, 0xcb, 0xa8, 0xe8, 0x14}, - {0x3e, 0xe2, 0x2a, 0xdc, 0x26, 0x7d, 0xde, 0x0e, 0xb0, 0x23, - 0x17, 0x45, 0xf6, 0xcf, 0x9d, 0x6e, 0xab, 0xd3, 0x3c, 0x19}, - {0x3f, 0x85, 0xf2, 0xbb, 0x4a, 0x62, 0xb0, 0xb5, 0x8b, 0xe1, - 0x61, 0x4a, 0xbb, 0x0d, 0x46, 0x31, 0xb4, 0xbe, 0xf8, 0xba}, - {0x40, 0x54, 0xda, 0x6f, 0x1c, 0x3f, 0x40, 0x74, 0xac, 0xed, - 0x0f, 0xec, 0xcd, 0xdb, 0x79, 0xd1, 0x53, 0xfb, 0x90, 0x1d}, - {0x40, 0x9d, 0x4b, 0xd9, 0x17, 0xb5, 0x5c, 0x27, 0xb6, 0x9b, - 0x64, 0xcb, 0x98, 0x22, 0x44, 0x0d, 0xcd, 0x09, 0xb8, 0x89}, - {0x40, 0xe7, 0x8c, 0x1d, 0x52, 0x3d, 0x1c, 0xd9, 0x95, 0x4f, - 0xac, 0x1a, 0x1a, 0xb3, 0xbd, 0x3c, 0xba, 0xa1, 0x5b, 0xfc}, - {0x42, 0xef, 0xdd, 0xe6, 0xbf, 0xf3, 0x5e, 0xd0, 0xba, 0xe6, - 0xac, 0xdd, 0x20, 0x4c, 0x50, 0xae, 0x86, 0xc4, 0xf4, 0xfa}, - {0x43, 0x13, 0xbb, 0x96, 0xf1, 0xd5, 0x86, 0x9b, 0xc1, 0x4e, - 0x6a, 0x92, 0xf6, 0xcf, 0xf6, 0x34, 0x69, 0x87, 0x82, 0x37}, - {0x43, 0x94, 0xce, 0x31, 0x26, 0xff, 0x1a, 0x22, 0x4c, 0xdd, - 0x4d, 0xee, 0xb4, 0xf4, 0xec, 0x1d, 0xa3, 0x68, 0xef, 0x6a}, - {0x43, 0xf9, 0xb1, 0x10, 0xd5, 0xba, 0xfd, 0x48, 0x22, 0x52, - 0x31, 0xb0, 0xd0, 0x08, 0x2b, 0x37, 0x2f, 0xef, 0x9a, 0x54}, - {0x44, 0x63, 0xc5, 0x31, 0xd7, 0xcc, 0xc1, 0x00, 0x67, 0x94, - 0x61, 0x2b, 0xb6, 0x56, 0xd3, 0xbf, 0x82, 0x57, 0x84, 0x6f}, - {0x47, 0xbe, 0xab, 0xc9, 0x22, 0xea, 0xe8, 0x0e, 0x78, 0x78, - 0x34, 0x62, 0xa7, 0x9f, 0x45, 0xc2, 0x54, 0xfd, 0xe6, 0x8b}, - {0x48, 0x12, 0xbd, 0x92, 0x3c, 0xa8, 0xc4, 0x39, 0x06, 0xe7, - 0x30, 0x6d, 0x27, 0x96, 0xe6, 0xa4, 0xcf, 0x22, 0x2e, 0x7d}, - {0x49, 0x0a, 0x75, 0x74, 0xde, 0x87, 0x0a, 0x47, 0xfe, 0x58, - 0xee, 0xf6, 0xc7, 0x6b, 0xeb, 0xc6, 0x0b, 0x12, 0x40, 0x99}, - {0x4a, 0x05, 0x8f, 0xdf, 0xd7, 0x61, 0xdb, 0x21, 0xb0, 0xc2, - 0xee, 0x48, 0x57, 0x9b, 0xe2, 0x7f, 0x42, 0xa4, 0xda, 0x1c}, - {0x4a, 0x3f, 0x8d, 0x6b, 0xdc, 0x0e, 0x1e, 0xcf, 0xcd, 0x72, - 0xe3, 0x77, 0xde, 0xf2, 0xd7, 0xff, 0x92, 0xc1, 0x9b, 0xc7}, - {0x4a, 0xbd, 0xee, 0xec, 0x95, 0x0d, 0x35, 0x9c, 0x89, 0xae, - 0xc7, 0x52, 0xa1, 0x2c, 0x5b, 0x29, 0xf6, 0xd6, 0xaa, 0x0c}, - {0x4b, 0x6b, 0xd2, 0xd3, 0x88, 0x4e, 0x46, 0xc8, 0x0c, 0xe2, - 0xb9, 0x62, 0xbc, 0x59, 0x8c, 0xd9, 0xd5, 0xd8, 0x40, 0x13}, - {0x4e, 0xb6, 0xd5, 0x78, 0x49, 0x9b, 0x1c, 0xcf, 0x5f, 0x58, - 0x1e, 0xad, 0x56, 0xbe, 0x3d, 0x9b, 0x67, 0x44, 0xa5, 0xe5}, - {0x4e, 0xfc, 0xed, 0x9c, 0x6b, 0xdd, 0x0c, 0x98, 0x5c, 0xa3, - 0xc7, 0xd2, 0x53, 0x06, 0x3c, 0x5b, 0xe6, 0xfc, 0x62, 0x0c}, - {0x4f, 0x55, 0x5c, 0xe2, 0x0d, 0xcd, 0x33, 0x64, 0xe0, 0xdc, - 0x7c, 0x41, 0xef, 0xdd, 0x40, 0xf5, 0x03, 0x56, 0xc1, 0x22}, - {0x4f, 0x65, 0x56, 0x63, 0x36, 0xdb, 0x65, 0x98, 0x58, 0x1d, - 0x58, 0x4a, 0x59, 0x6c, 0x87, 0x93, 0x4d, 0x5f, 0x2a, 0xb4}, - {0x4f, 0x99, 0xaa, 0x93, 0xfb, 0x2b, 0xd1, 0x37, 0x26, 0xa1, - 0x99, 0x4a, 0xce, 0x7f, 0xf0, 0x05, 0xf2, 0x93, 0x5d, 0x1e}, - {0x50, 0x30, 0x06, 0x09, 0x1d, 0x97, 0xd4, 0xf5, 0xae, 0x39, - 0xf7, 0xcb, 0xe7, 0x92, 0x7d, 0x7d, 0x65, 0x2d, 0x34, 0x31}, - {0x51, 0xa4, 0x4c, 0x28, 0xf3, 0x13, 0xe3, 0xf9, 0xcb, 0x5e, - 0x7c, 0x0a, 0x1e, 0x0e, 0x0d, 0xd2, 0x84, 0x37, 0x58, 0xae}, - {0x51, 0xc6, 0xe7, 0x08, 0x49, 0x06, 0x6e, 0xf3, 0x92, 0xd4, - 0x5c, 0xa0, 0x0d, 0x6d, 0xa3, 0x62, 0x8f, 0xc3, 0x52, 0x39}, - {0x52, 0x41, 0x2b, 0xd6, 0x7b, 0x5a, 0x6c, 0x69, 0x52, 0x82, - 0x38, 0x60, 0x26, 0xf0, 0xb0, 0x53, 0xdd, 0x40, 0x0e, 0xfc}, - {0x53, 0x5b, 0x00, 0x16, 0x72, 0xab, 0xbf, 0x7b, 0x6c, 0xc2, - 0x54, 0x05, 0xae, 0x4d, 0x24, 0xfe, 0x03, 0x3f, 0xd1, 0xcc}, - {0x54, 0xf9, 0xc1, 0x63, 0x75, 0x9f, 0x19, 0x04, 0x51, 0x21, - 0xa3, 0x19, 0xf6, 0x4c, 0x2d, 0x05, 0x55, 0xb7, 0xe0, 0x73}, - {0x55, 0xa6, 0x72, 0x3e, 0xcb, 0xf2, 0xec, 0xcd, 0xc3, 0x23, - 0x74, 0x70, 0x19, 0x9d, 0x2a, 0xbe, 0x11, 0xe3, 0x81, 0xd1}, - {0x55, 0xc8, 0x6f, 0x74, 0x14, 0xac, 0x8b, 0xdd, 0x68, 0x14, - 0xf4, 0xd8, 0x6a, 0xf1, 0x5f, 0x37, 0x10, 0xe1, 0x04, 0xd0}, - {0x56, 0xe0, 0xfa, 0xc0, 0x3b, 0x8f, 0x18, 0x23, 0x55, 0x18, - 0xe5, 0xd3, 0x11, 0xca, 0xe8, 0xc2, 0x43, 0x31, 0xab, 0x66}, - {0x58, 0x11, 0x9f, 0x0e, 0x12, 0x82, 0x87, 0xea, 0x50, 0xfd, - 0xd9, 0x87, 0x45, 0x6f, 0x4f, 0x78, 0xdc, 0xfa, 0xd6, 0xd4}, - {0x58, 0x5f, 0x78, 0x75, 0xbe, 0xe7, 0x43, 0x3e, 0xb0, 0x79, - 0xea, 0xab, 0x7d, 0x05, 0xbb, 0x0f, 0x7a, 0xf2, 0xbc, 0xcc}, - {0x58, 0xd5, 0x2d, 0xb9, 0x33, 0x01, 0xa4, 0xfd, 0x29, 0x1a, - 0x8c, 0x96, 0x45, 0xa0, 0x8f, 0xee, 0x7f, 0x52, 0x92, 0x82}, - {0x58, 0xe8, 0xab, 0xb0, 0x36, 0x15, 0x33, 0xfb, 0x80, 0xf7, - 0x9b, 0x1b, 0x6d, 0x29, 0xd3, 0xff, 0x8d, 0x5f, 0x00, 0xf0}, - {0x59, 0x0d, 0x2d, 0x7d, 0x88, 0x4f, 0x40, 0x2e, 0x61, 0x7e, - 0xa5, 0x62, 0x32, 0x17, 0x65, 0xcf, 0x17, 0xd8, 0x94, 0xe9}, - {0x59, 0x22, 0xa1, 0xe1, 0x5a, 0xea, 0x16, 0x35, 0x21, 0xf8, - 0x98, 0x39, 0x6a, 0x46, 0x46, 0xb0, 0x44, 0x1b, 0x0f, 0xa9}, - {0x59, 0xaf, 0x82, 0x79, 0x91, 0x86, 0xc7, 0xb4, 0x75, 0x07, - 0xcb, 0xcf, 0x03, 0x57, 0x46, 0xeb, 0x04, 0xdd, 0xb7, 0x16}, - {0x5a, 0x4d, 0x0e, 0x8b, 0x5f, 0xdc, 0xfd, 0xf6, 0x4e, 0x72, - 0x99, 0xa3, 0x6c, 0x06, 0x0d, 0xb2, 0x22, 0xca, 0x78, 0xe4}, - {0x5a, 0x5a, 0x4d, 0xaf, 0x78, 0x61, 0x26, 0x7c, 0x4b, 0x1f, - 0x1e, 0x67, 0x58, 0x6b, 0xae, 0x6e, 0xd4, 0xfe, 0xb9, 0x3f}, - {0x5b, 0xb5, 0x99, 0x20, 0xd1, 0x1b, 0x39, 0x14, 0x79, 0x46, - 0x3a, 0xdd, 0x51, 0x00, 0xdb, 0x1d, 0x52, 0xf4, 0x3a, 0xd4}, - {0x5d, 0x00, 0x38, 0x60, 0xf0, 0x02, 0xed, 0x82, 0x9d, 0xea, - 0xa4, 0x18, 0x68, 0xf7, 0x88, 0x18, 0x6d, 0x62, 0x12, 0x7f}, - {0x5d, 0x98, 0x9c, 0xdb, 0x15, 0x96, 0x11, 0x36, 0x51, 0x65, - 0x64, 0x1b, 0x56, 0x0f, 0xdb, 0xea, 0x2a, 0xc2, 0x3e, 0xf1}, - {0x5f, 0x3a, 0xfc, 0x0a, 0x8b, 0x64, 0xf6, 0x86, 0x67, 0x34, - 0x74, 0xdf, 0x7e, 0xa9, 0xa2, 0xfe, 0xf9, 0xfa, 0x7a, 0x51}, - {0x5f, 0x3b, 0x8c, 0xf2, 0xf8, 0x10, 0xb3, 0x7d, 0x78, 0xb4, - 0xce, 0xec, 0x19, 0x19, 0xc3, 0x73, 0x34, 0xb9, 0xc7, 0x74}, - {0x5f, 0x43, 0xe5, 0xb1, 0xbf, 0xf8, 0x78, 0x8c, 0xac, 0x1c, - 0xc7, 0xca, 0x4a, 0x9a, 0xc6, 0x22, 0x2b, 0xcc, 0x34, 0xc6}, - {0x5f, 0x4e, 0x1f, 0xcf, 0x31, 0xb7, 0x91, 0x3b, 0x85, 0x0b, - 0x54, 0xf6, 0xe5, 0xff, 0x50, 0x1a, 0x2b, 0x6f, 0xc6, 0xcf}, - {0x5f, 0xb7, 0xee, 0x06, 0x33, 0xe2, 0x59, 0xdb, 0xad, 0x0c, - 0x4c, 0x9a, 0xe6, 0xd3, 0x8f, 0x1a, 0x61, 0xc7, 0xdc, 0x25}, - {0x60, 0xd6, 0x89, 0x74, 0xb5, 0xc2, 0x65, 0x9e, 0x8a, 0x0f, - 0xc1, 0x88, 0x7c, 0x88, 0xd2, 0x46, 0x69, 0x1b, 0x18, 0x2c}, - {0x61, 0x57, 0x3a, 0x11, 0xdf, 0x0e, 0xd8, 0x7e, 0xd5, 0x92, - 0x65, 0x22, 0xea, 0xd0, 0x56, 0xd7, 0x44, 0xb3, 0x23, 0x71}, - {0x61, 0xef, 0x43, 0xd7, 0x7f, 0xca, 0xd4, 0x61, 0x51, 0xbc, - 0x98, 0xe0, 0xc3, 0x59, 0x12, 0xaf, 0x9f, 0xeb, 0x63, 0x11}, - {0x62, 0x52, 0xdc, 0x40, 0xf7, 0x11, 0x43, 0xa2, 0x2f, 0xde, - 0x9e, 0xf7, 0x34, 0x8e, 0x06, 0x42, 0x51, 0xb1, 0x81, 0x18}, - {0x62, 0x7f, 0x8d, 0x78, 0x27, 0x65, 0x63, 0x99, 0xd2, 0x7d, - 0x7f, 0x90, 0x44, 0xc9, 0xfe, 0xb3, 0xf3, 0x3e, 0xfa, 0x9a}, - {0x64, 0x90, 0x2a, 0xd7, 0x27, 0x7a, 0xf3, 0xe3, 0x2c, 0xd8, - 0xcc, 0x1d, 0xc7, 0x9d, 0xe1, 0xfd, 0x7f, 0x80, 0x69, 0xea}, - {0x67, 0x24, 0x89, 0x80, 0xde, 0x77, 0x5d, 0x2c, 0x9b, 0x04, - 0xe4, 0x03, 0x07, 0x94, 0x0b, 0xad, 0xb3, 0x51, 0xf3, 0x95}, - {0x67, 0x65, 0x0d, 0xf1, 0x7e, 0x8e, 0x7e, 0x5b, 0x82, 0x40, - 0xa4, 0xf4, 0x56, 0x4b, 0xcf, 0xe2, 0x3d, 0x69, 0xc6, 0xf0}, - {0x67, 0x82, 0xaa, 0xe0, 0xed, 0xee, 0xe2, 0x1a, 0x58, 0x39, - 0xd3, 0xc0, 0xcd, 0x14, 0x68, 0x0a, 0x4f, 0x60, 0x14, 0x2a}, - {0x67, 0x9a, 0x4f, 0x81, 0xfc, 0x70, 0x5d, 0xde, 0xc4, 0x19, - 0x77, 0x8d, 0xd2, 0xeb, 0xd8, 0x75, 0xf4, 0xc2, 0x42, 0xc6}, - {0x67, 0xeb, 0x33, 0x7b, 0x68, 0x4c, 0xeb, 0x0e, 0xc2, 0xb0, - 0x76, 0x0a, 0xb4, 0x88, 0x27, 0x8c, 0xdd, 0x95, 0x97, 0xdd}, - {0x68, 0x8b, 0x6e, 0xb8, 0x07, 0xe8, 0xed, 0xa5, 0xc7, 0xb1, - 0x7c, 0x43, 0x93, 0xd0, 0x79, 0x5f, 0x0f, 0xae, 0x15, 0x5f}, - {0x68, 0xed, 0x18, 0xb3, 0x09, 0xcd, 0x52, 0x91, 0xc0, 0xd3, - 0x35, 0x7c, 0x1d, 0x11, 0x41, 0xbf, 0x88, 0x38, 0x66, 0xb1}, - {0x69, 0x69, 0x56, 0x2e, 0x40, 0x80, 0xf4, 0x24, 0xa1, 0xe7, - 0x19, 0x9f, 0x14, 0xba, 0xf3, 0xee, 0x58, 0xab, 0x6a, 0xbb}, - {0x69, 0xbd, 0x8c, 0xf4, 0x9c, 0xd3, 0x00, 0xfb, 0x59, 0x2e, - 0x17, 0x93, 0xca, 0x55, 0x6a, 0xf3, 0xec, 0xaa, 0x35, 0xfb}, - {0x6a, 0x17, 0x45, 0x70, 0xa9, 0x16, 0xfb, 0xe8, 0x44, 0x53, - 0xee, 0xd3, 0xd0, 0x70, 0xa1, 0xd8, 0xda, 0x44, 0x28, 0x29}, - {0x6a, 0x6f, 0x2a, 0x8b, 0x6e, 0x26, 0x15, 0x08, 0x8d, 0xf5, - 0x9c, 0xd2, 0x4c, 0x40, 0x24, 0x18, 0xae, 0x42, 0xa3, 0xf1}, - {0x6a, 0xd2, 0x3b, 0x9d, 0xc4, 0x8e, 0x37, 0x5f, 0x85, 0x9a, - 0xd9, 0xca, 0xb5, 0x85, 0x32, 0x5c, 0x23, 0x89, 0x40, 0x71}, - {0x6b, 0x2f, 0x34, 0xad, 0x89, 0x58, 0xbe, 0x62, 0xfd, 0xb0, - 0x6b, 0x5c, 0xce, 0xbb, 0x9d, 0xd9, 0x4f, 0x4e, 0x39, 0xf3}, - {0x6b, 0x81, 0x44, 0x6a, 0x5c, 0xdd, 0xf4, 0x74, 0xa0, 0xf8, - 0x00, 0xff, 0xbe, 0x69, 0xfd, 0x0d, 0xb6, 0x28, 0x75, 0x16}, - {0x6d, 0xc5, 0xe5, 0x62, 0xa9, 0xfd, 0x64, 0xd4, 0xbb, 0x2f, - 0x63, 0x1c, 0xcd, 0x04, 0x1e, 0x9a, 0xa6, 0xff, 0x60, 0xf1}, - {0x6e, 0x3a, 0x55, 0xa4, 0x19, 0x0c, 0x19, 0x5c, 0x93, 0x84, - 0x3c, 0xc0, 0xdb, 0x72, 0x2e, 0x31, 0x30, 0x61, 0xf0, 0xb1}, - {0x6f, 0x38, 0x84, 0x56, 0x8e, 0x99, 0xc8, 0xc6, 0xac, 0x0e, - 0x5d, 0xde, 0x2d, 0xb2, 0x02, 0xdd, 0x00, 0x2e, 0x36, 0x63}, - {0x6f, 0x62, 0xde, 0xb8, 0x6c, 0x85, 0x58, 0x5a, 0xe4, 0x2e, - 0x47, 0x8d, 0xb4, 0xd7, 0x6d, 0xb3, 0x67, 0x58, 0x5a, 0xe6}, - {0x70, 0x17, 0x9b, 0x86, 0x8c, 0x00, 0xa4, 0xfa, 0x60, 0x91, - 0x52, 0x22, 0x3f, 0x9f, 0x3e, 0x32, 0xbd, 0xe0, 0x05, 0x62}, - {0x70, 0x30, 0xaa, 0xbf, 0x84, 0x32, 0xa8, 0x00, 0x66, 0x6c, - 0xcc, 0xc4, 0x2a, 0x88, 0x7e, 0x42, 0xb7, 0x55, 0x3e, 0x2b}, - {0x70, 0x5d, 0x2b, 0x45, 0x65, 0xc7, 0x04, 0x7a, 0x54, 0x06, - 0x94, 0xa7, 0x9a, 0xf7, 0xab, 0xb8, 0x42, 0xbd, 0xc1, 0x61}, - {0x71, 0x89, 0x9a, 0x67, 0xbf, 0x33, 0xaf, 0x31, 0xbe, 0xfd, - 0xc0, 0x71, 0xf8, 0xf7, 0x33, 0xb1, 0x83, 0x85, 0x63, 0x32}, - {0x72, 0x0f, 0xc1, 0x5d, 0xdc, 0x27, 0xd4, 0x56, 0xd0, 0x98, - 0xfa, 0xbf, 0x3c, 0xdd, 0x78, 0xd3, 0x1e, 0xf5, 0xa8, 0xda}, - {0x74, 0x20, 0x74, 0x41, 0x72, 0x9c, 0xdd, 0x92, 0xec, 0x79, - 0x31, 0xd8, 0x23, 0x10, 0x8d, 0xc2, 0x81, 0x92, 0xe2, 0xbb}, - {0x74, 0x2c, 0x31, 0x92, 0xe6, 0x07, 0xe4, 0x24, 0xeb, 0x45, - 0x49, 0x54, 0x2b, 0xe1, 0xbb, 0xc5, 0x3e, 0x61, 0x74, 0xe2}, - {0x74, 0x2c, 0xdf, 0x15, 0x94, 0x04, 0x9c, 0xbf, 0x17, 0xa2, - 0x04, 0x6c, 0xc6, 0x39, 0xbb, 0x38, 0x88, 0xe0, 0x2e, 0x33}, - {0x75, 0x02, 0x51, 0xb2, 0xc6, 0x32, 0x53, 0x6f, 0x9d, 0x91, - 0x72, 0x79, 0x54, 0x3c, 0x13, 0x7c, 0xd7, 0x21, 0xc6, 0xe0}, - {0x75, 0xe0, 0xab, 0xb6, 0x13, 0x85, 0x12, 0x27, 0x1c, 0x04, - 0xf8, 0x5f, 0xdd, 0xde, 0x38, 0xe4, 0xb7, 0x24, 0x2e, 0xfe}, - {0x76, 0x12, 0xed, 0x9e, 0x49, 0xb3, 0x65, 0xb4, 0xda, 0xd3, - 0x12, 0x0c, 0x01, 0xe6, 0x03, 0x74, 0x8d, 0xae, 0x8c, 0xf0}, - {0x76, 0x39, 0xc7, 0x18, 0x47, 0xe1, 0x51, 0xb5, 0xc7, 0xea, - 0x01, 0xc7, 0x58, 0xfb, 0xf1, 0x2a, 0xba, 0x29, 0x8f, 0x7a}, - {0x76, 0xb7, 0x60, 0x96, 0xdd, 0x14, 0x56, 0x29, 0xac, 0x75, - 0x85, 0xd3, 0x70, 0x63, 0xc1, 0xbc, 0x47, 0x86, 0x1c, 0x8b}, - {0x76, 0xe2, 0x7e, 0xc1, 0x4f, 0xdb, 0x82, 0xc1, 0xc0, 0xa6, - 0x75, 0xb5, 0x05, 0xbe, 0x3d, 0x29, 0xb4, 0xed, 0xdb, 0xbb}, - {0x77, 0x47, 0x4f, 0xc6, 0x30, 0xe4, 0x0f, 0x4c, 0x47, 0x64, - 0x3f, 0x84, 0xba, 0xb8, 0xc6, 0x95, 0x4a, 0x8a, 0x41, 0xec}, - {0x78, 0x6a, 0x74, 0xac, 0x76, 0xab, 0x14, 0x7f, 0x9c, 0x6a, - 0x30, 0x50, 0xba, 0x9e, 0xa8, 0x7e, 0xfe, 0x9a, 0xce, 0x3c}, - {0x78, 0xe9, 0xdd, 0x06, 0x50, 0x62, 0x4d, 0xb9, 0xcb, 0x36, - 0xb5, 0x07, 0x67, 0xf2, 0x09, 0xb8, 0x43, 0xbe, 0x15, 0xb3}, - {0x79, 0x98, 0xa3, 0x08, 0xe1, 0x4d, 0x65, 0x85, 0xe6, 0xc2, - 0x1e, 0x15, 0x3a, 0x71, 0x9f, 0xba, 0x5a, 0xd3, 0x4a, 0xd9}, - {0x7a, 0x1c, 0xdd, 0xe3, 0xd2, 0x19, 0x7e, 0x71, 0x37, 0x43, - 0x3d, 0x3f, 0x99, 0xc0, 0xb3, 0x69, 0xf7, 0x06, 0xc7, 0x49}, - {0x7a, 0x74, 0x41, 0x0f, 0xb0, 0xcd, 0x5c, 0x97, 0x2a, 0x36, - 0x4b, 0x71, 0xbf, 0x03, 0x1d, 0x88, 0xa6, 0x51, 0x0e, 0x9e}, - {0x7a, 0xc5, 0xff, 0xf8, 0xdc, 0xbc, 0x55, 0x83, 0x17, 0x68, - 0x77, 0x07, 0x3b, 0xf7, 0x51, 0x73, 0x5e, 0x9b, 0xd3, 0x58}, - {0x7e, 0x04, 0xde, 0x89, 0x6a, 0x3e, 0x66, 0x6d, 0x00, 0xe6, - 0x87, 0xd3, 0x3f, 0xfa, 0xd9, 0x3b, 0xe8, 0x3d, 0x34, 0x9e}, - {0x7e, 0x20, 0x69, 0x39, 0xcc, 0x5f, 0xa8, 0x83, 0x63, 0x5f, - 0x64, 0xc7, 0x50, 0xeb, 0xf5, 0xfd, 0xa9, 0xae, 0xe6, 0x53}, - {0x7e, 0x78, 0x4a, 0x10, 0x1c, 0x82, 0x65, 0xcc, 0x2d, 0xe1, - 0xf1, 0x6d, 0x47, 0xb4, 0x40, 0xca, 0xd9, 0x0a, 0x19, 0x45}, - {0x7e, 0xb1, 0xa0, 0x42, 0x9b, 0xe5, 0xf4, 0x28, 0xac, 0x2b, - 0x93, 0x97, 0x1d, 0x7c, 0x84, 0x48, 0xa5, 0x36, 0x07, 0x0c}, - {0x7f, 0x88, 0xcd, 0x72, 0x23, 0xf3, 0xc8, 0x13, 0x81, 0x8c, - 0x99, 0x46, 0x14, 0xa8, 0x9c, 0x99, 0xfa, 0x3b, 0x52, 0x47}, - {0x7f, 0x8a, 0x77, 0x83, 0x6b, 0xdc, 0x6d, 0x06, 0x8f, 0x8b, - 0x07, 0x37, 0xfc, 0xc5, 0x72, 0x54, 0x13, 0x06, 0x8c, 0xa4}, - {0x7f, 0x8a, 0xb0, 0xcf, 0xd0, 0x51, 0x87, 0x6a, 0x66, 0xf3, - 0x36, 0x0f, 0x47, 0xc8, 0x8d, 0x8c, 0xd3, 0x35, 0xfc, 0x74}, - {0x7f, 0xb9, 0xe2, 0xc9, 0x95, 0xc9, 0x7a, 0x93, 0x9f, 0x9e, - 0x81, 0xa0, 0x7a, 0xea, 0x9b, 0x4d, 0x70, 0x46, 0x34, 0x96}, - {0x7f, 0xbb, 0x6a, 0xcd, 0x7e, 0x0a, 0xb4, 0x38, 0xda, 0xaf, - 0x6f, 0xd5, 0x02, 0x10, 0xd0, 0x07, 0xc6, 0xc0, 0x82, 0x9c}, - {0x80, 0x25, 0xef, 0xf4, 0x6e, 0x70, 0xc8, 0xd4, 0x72, 0x24, - 0x65, 0x84, 0xfe, 0x40, 0x3b, 0x8a, 0x8d, 0x6a, 0xdb, 0xf5}, - {0x80, 0xbf, 0x3d, 0xe9, 0xa4, 0x1d, 0x76, 0x8d, 0x19, 0x4b, - 0x29, 0x3c, 0x85, 0x63, 0x2c, 0xdb, 0xc8, 0xea, 0x8c, 0xf7}, - {0x81, 0x96, 0x8b, 0x3a, 0xef, 0x1c, 0xdc, 0x70, 0xf5, 0xfa, - 0x32, 0x69, 0xc2, 0x92, 0xa3, 0x63, 0x5b, 0xd1, 0x23, 0xd3}, - {0x82, 0x50, 0xbe, 0xd5, 0xa2, 0x14, 0x43, 0x3a, 0x66, 0x37, - 0x7c, 0xbc, 0x10, 0xef, 0x83, 0xf6, 0x69, 0xda, 0x3a, 0x67}, - {0x83, 0x51, 0x50, 0x9b, 0x7d, 0xf8, 0xcf, 0xe8, 0x7b, 0xae, - 0x62, 0xae, 0xb9, 0xb0, 0x3a, 0x52, 0xf4, 0xe6, 0x2c, 0x79}, - {0x83, 0x8e, 0x30, 0xf7, 0x7f, 0xdd, 0x14, 0xaa, 0x38, 0x5e, - 0xd1, 0x45, 0x00, 0x9c, 0x0e, 0x22, 0x36, 0x49, 0x4f, 0xaa}, - {0x84, 0x42, 0x9d, 0x9f, 0xe2, 0xe7, 0x3a, 0x0d, 0xc8, 0xaa, - 0x0a, 0xe0, 0xa9, 0x02, 0xf2, 0x74, 0x99, 0x33, 0xfe, 0x02}, - {0x85, 0x37, 0x1c, 0xa6, 0xe5, 0x50, 0x14, 0x3d, 0xce, 0x28, - 0x03, 0x47, 0x1b, 0xde, 0x3a, 0x09, 0xe8, 0xf8, 0x77, 0x0f}, - {0x85, 0xa4, 0x08, 0xc0, 0x9c, 0x19, 0x3e, 0x5d, 0x51, 0x58, - 0x7d, 0xcd, 0xd6, 0x13, 0x30, 0xfd, 0x8c, 0xde, 0x37, 0xbf}, - {0x85, 0xb5, 0xff, 0x67, 0x9b, 0x0c, 0x79, 0x96, 0x1f, 0xc8, - 0x6e, 0x44, 0x22, 0x00, 0x46, 0x13, 0xdb, 0x17, 0x92, 0x84}, - {0x87, 0x81, 0xc2, 0x5a, 0x96, 0xbd, 0xc2, 0xfb, 0x4c, 0x65, - 0x06, 0x4f, 0xf9, 0x39, 0x0b, 0x26, 0x04, 0x8a, 0x0e, 0x01}, - {0x87, 0x82, 0xc6, 0xc3, 0x04, 0x35, 0x3b, 0xcf, 0xd2, 0x96, - 0x92, 0xd2, 0x59, 0x3e, 0x7d, 0x44, 0xd9, 0x34, 0xff, 0x11}, - {0x87, 0x9f, 0x4b, 0xee, 0x05, 0xdf, 0x98, 0x58, 0x3b, 0xe3, - 0x60, 0xd6, 0x33, 0xe7, 0x0d, 0x3f, 0xfe, 0x98, 0x71, 0xaf}, - {0x89, 0xc3, 0x2e, 0x6b, 0x52, 0x4e, 0x4d, 0x65, 0x38, 0x8b, - 0x9e, 0xce, 0xdc, 0x63, 0x71, 0x34, 0xed, 0x41, 0x93, 0xa3}, - {0x89, 0xdf, 0x74, 0xfe, 0x5c, 0xf4, 0x0f, 0x4a, 0x80, 0xf9, - 0xe3, 0x37, 0x7d, 0x54, 0xda, 0x91, 0xe1, 0x01, 0x31, 0x8e}, - {0x8a, 0x5c, 0x8c, 0xee, 0xa5, 0x03, 0xe6, 0x05, 0x56, 0xba, - 0xd8, 0x1b, 0xd4, 0xf6, 0xc9, 0xb0, 0xed, 0xe5, 0x2f, 0xe0}, - {0x8b, 0x1a, 0x11, 0x06, 0xb8, 0xe2, 0x6b, 0x23, 0x29, 0x80, - 0xfd, 0x65, 0x2e, 0x61, 0x81, 0x37, 0x64, 0x41, 0xfd, 0x11}, - {0x8b, 0xaf, 0x4c, 0x9b, 0x1d, 0xf0, 0x2a, 0x92, 0xf7, 0xda, - 0x12, 0x8e, 0xb9, 0x1b, 0xac, 0xf4, 0x98, 0x60, 0x4b, 0x6f}, - {0x8c, 0x96, 0xba, 0xeb, 0xdd, 0x2b, 0x07, 0x07, 0x48, 0xee, - 0x30, 0x32, 0x66, 0xa0, 0xf3, 0x98, 0x6e, 0x7c, 0xae, 0x58}, - {0x8c, 0xc4, 0x30, 0x7b, 0xc6, 0x07, 0x55, 0xe7, 0xb2, 0x2d, - 0xd9, 0xf7, 0xfe, 0xa2, 0x45, 0x93, 0x6c, 0x7c, 0xf2, 0x88}, - {0x8c, 0xf4, 0x27, 0xfd, 0x79, 0x0c, 0x3a, 0xd1, 0x66, 0x06, - 0x8d, 0xe8, 0x1e, 0x57, 0xef, 0xbb, 0x93, 0x22, 0x72, 0xd4}, - {0x8d, 0x08, 0xfc, 0x43, 0xc0, 0x77, 0x0c, 0xa8, 0x4f, 0x4d, - 0xcc, 0xb2, 0xd4, 0x1a, 0x5d, 0x95, 0x6d, 0x78, 0x6d, 0xc4}, - {0x8d, 0x17, 0x84, 0xd5, 0x37, 0xf3, 0x03, 0x7d, 0xec, 0x70, - 0xfe, 0x57, 0x8b, 0x51, 0x9a, 0x99, 0xe6, 0x10, 0xd7, 0xb0}, - {0x8e, 0x10, 0x32, 0xe9, 0x24, 0x59, 0x44, 0xf8, 0x47, 0x91, - 0x98, 0x3e, 0xc9, 0xe8, 0x29, 0xcb, 0x10, 0x59, 0xb4, 0xd3}, - {0x8e, 0x1c, 0x74, 0xf8, 0xa6, 0x20, 0xb9, 0xe5, 0x8a, 0xf4, - 0x61, 0xfa, 0xec, 0x2b, 0x47, 0x56, 0x51, 0x1a, 0x52, 0xc6}, - {0x8e, 0xb0, 0x3f, 0xc3, 0xcf, 0x7b, 0xb2, 0x92, 0x86, 0x62, - 0x68, 0xb7, 0x51, 0x22, 0x3d, 0xb5, 0x10, 0x34, 0x05, 0xcb}, - {0x8e, 0xfd, 0xca, 0xbc, 0x93, 0xe6, 0x1e, 0x92, 0x5d, 0x4d, - 0x1d, 0xed, 0x18, 0x1a, 0x43, 0x20, 0xa4, 0x67, 0xa1, 0x39}, - {0x8f, 0x43, 0x28, 0x8a, 0xd2, 0x72, 0xf3, 0x10, 0x3b, 0x6f, - 0xb1, 0x42, 0x84, 0x85, 0xea, 0x30, 0x14, 0xc0, 0xbc, 0xfe}, - {0x90, 0x5f, 0x94, 0x2f, 0xd9, 0xf2, 0x8f, 0x67, 0x9b, 0x37, - 0x81, 0x80, 0xfd, 0x4f, 0x84, 0x63, 0x47, 0xf6, 0x45, 0xc1}, - {0x90, 0x78, 0xc5, 0xa2, 0x8f, 0x9a, 0x43, 0x25, 0xc2, 0xa7, - 0xc7, 0x38, 0x13, 0xcd, 0xfe, 0x13, 0xc2, 0x0f, 0x93, 0x4e}, - {0x90, 0xae, 0xa2, 0x69, 0x85, 0xff, 0x14, 0x80, 0x4c, 0x43, - 0x49, 0x52, 0xec, 0xe9, 0x60, 0x84, 0x77, 0xaf, 0x55, 0x6f}, - {0x90, 0xde, 0xce, 0x77, 0xf8, 0xc8, 0x25, 0x34, 0x0e, 0x62, - 0xeb, 0xd6, 0x35, 0xe1, 0xbe, 0x20, 0xcf, 0x73, 0x27, 0xdd}, - {0x90, 0xde, 0xde, 0x9e, 0x4c, 0x4e, 0x9f, 0x6f, 0xd8, 0x86, - 0x17, 0x57, 0x9d, 0xd3, 0x91, 0xbc, 0x65, 0xa6, 0x89, 0x64}, - {0x91, 0x21, 0x98, 0xee, 0xf2, 0x3d, 0xca, 0xc4, 0x09, 0x39, - 0x31, 0x2f, 0xee, 0x97, 0xdd, 0x56, 0x0b, 0xae, 0x49, 0xb1}, - {0x91, 0x58, 0xc5, 0xef, 0x98, 0x73, 0x01, 0xa8, 0x90, 0x3c, - 0xfd, 0xab, 0x03, 0xd7, 0x2d, 0xa1, 0xd8, 0x89, 0x09, 0xc9}, - {0x91, 0xc6, 0xd6, 0xee, 0x3e, 0x8a, 0xc8, 0x63, 0x84, 0xe5, - 0x48, 0xc2, 0x99, 0x29, 0x5c, 0x75, 0x6c, 0x81, 0x7b, 0x81}, - {0x92, 0x5a, 0x8f, 0x8d, 0x2c, 0x6d, 0x04, 0xe0, 0x66, 0x5f, - 0x59, 0x6a, 0xff, 0x22, 0xd8, 0x63, 0xe8, 0x25, 0x6f, 0x3f}, - {0x93, 0x05, 0x7a, 0x88, 0x15, 0xc6, 0x4f, 0xce, 0x88, 0x2f, - 0xfa, 0x91, 0x16, 0x52, 0x28, 0x78, 0xbc, 0x53, 0x64, 0x17}, - {0x93, 0xe6, 0xab, 0x22, 0x03, 0x03, 0xb5, 0x23, 0x28, 0xdc, - 0xda, 0x56, 0x9e, 0xba, 0xe4, 0xd1, 0xd1, 0xcc, 0xfb, 0x65}, - {0x93, 0xf7, 0xf4, 0x8b, 0x12, 0x61, 0x94, 0x3f, 0x6a, 0x78, - 0x21, 0x0c, 0x52, 0xe6, 0x26, 0xdf, 0xbf, 0xbb, 0xe2, 0x60}, - {0x96, 0x56, 0xcd, 0x7b, 0x57, 0x96, 0x98, 0x95, 0xd0, 0xe1, - 0x41, 0x46, 0x68, 0x06, 0xfb, 0xb8, 0xc6, 0x11, 0x06, 0x87}, - {0x96, 0x83, 0x38, 0xf1, 0x13, 0xe3, 0x6a, 0x7b, 0xab, 0xdd, - 0x08, 0xf7, 0x77, 0x63, 0x91, 0xa6, 0x87, 0x36, 0x58, 0x2e}, - {0x96, 0x97, 0x4c, 0xd6, 0xb6, 0x63, 0xa7, 0x18, 0x45, 0x26, - 0xb1, 0xd6, 0x48, 0xad, 0x81, 0x5c, 0xf5, 0x1e, 0x80, 0x1a}, - {0x96, 0xc9, 0x1b, 0x0b, 0x95, 0xb4, 0x10, 0x98, 0x42, 0xfa, - 0xd0, 0xd8, 0x22, 0x79, 0xfe, 0x60, 0xfa, 0xb9, 0x16, 0x83}, - {0x97, 0x1d, 0x34, 0x86, 0xfc, 0x1e, 0x8e, 0x63, 0x15, 0xf7, - 0xc6, 0xf2, 0xe1, 0x29, 0x67, 0xc7, 0x24, 0x34, 0x22, 0x14}, - {0x97, 0x22, 0x6a, 0xae, 0x4a, 0x7a, 0x64, 0xa5, 0x9b, 0xd1, - 0x67, 0x87, 0xf2, 0x7f, 0x84, 0x1c, 0x0a, 0x00, 0x1f, 0xd0}, - {0x97, 0x81, 0x79, 0x50, 0xd8, 0x1c, 0x96, 0x70, 0xcc, 0x34, - 0xd8, 0x09, 0xcf, 0x79, 0x44, 0x31, 0x36, 0x7e, 0xf4, 0x74}, - {0x97, 0xe2, 0xe9, 0x96, 0x36, 0xa5, 0x47, 0x55, 0x4f, 0x83, - 0x8f, 0xba, 0x38, 0xb8, 0x2e, 0x74, 0xf8, 0x9a, 0x83, 0x0a}, - {0x99, 0x57, 0xc5, 0x3f, 0xc5, 0x9f, 0xb8, 0xe7, 0x39, 0xf7, - 0xa4, 0xb7, 0xa7, 0x0e, 0x9b, 0x8e, 0x65, 0x9f, 0x20, 0x8c}, - {0x99, 0xa6, 0x9b, 0xe6, 0x1a, 0xfe, 0x88, 0x6b, 0x4d, 0x2b, - 0x82, 0x00, 0x7c, 0xb8, 0x54, 0xfc, 0x31, 0x7e, 0x15, 0x39}, - {0x9b, 0xaa, 0xe5, 0x9f, 0x56, 0xee, 0x21, 0xcb, 0x43, 0x5a, - 0xbe, 0x25, 0x93, 0xdf, 0xa7, 0xf0, 0x40, 0xd1, 0x1d, 0xcb}, - {0x9c, 0x61, 0x5c, 0x4d, 0x4d, 0x85, 0x10, 0x3a, 0x53, 0x26, - 0xc2, 0x4d, 0xba, 0xea, 0xe4, 0xa2, 0xd2, 0xd5, 0xcc, 0x97}, - {0x9c, 0xbb, 0x48, 0x53, 0xf6, 0xa4, 0xf6, 0xd3, 0x52, 0xa4, - 0xe8, 0x32, 0x52, 0x55, 0x60, 0x13, 0xf5, 0xad, 0xaf, 0x65}, - {0x9c, 0xde, 0x26, 0xd0, 0x7b, 0xb6, 0x8d, 0xe3, 0x50, 0xc8, - 0x35, 0xe7, 0x95, 0x0e, 0xe8, 0x1c, 0xde, 0x97, 0x87, 0xf5}, - {0x9d, 0x70, 0xbb, 0x01, 0xa5, 0xa4, 0xa0, 0x18, 0x11, 0x2e, - 0xf7, 0x1c, 0x01, 0xb9, 0x32, 0xc5, 0x34, 0xe7, 0x88, 0xa8}, - {0x9e, 0xd1, 0x80, 0x28, 0xfb, 0x1e, 0x8a, 0x97, 0x01, 0x48, - 0x0a, 0x78, 0x90, 0xa5, 0x9a, 0xcd, 0x73, 0xdf, 0xf8, 0x71}, - {0x9f, 0x74, 0x4e, 0x9f, 0x2b, 0x4d, 0xba, 0xec, 0x0f, 0x31, - 0x2c, 0x50, 0xb6, 0x56, 0x3b, 0x8e, 0x2d, 0x93, 0xc3, 0x11}, - {0x9f, 0xad, 0x91, 0xa6, 0xce, 0x6a, 0xc6, 0xc5, 0x00, 0x47, - 0xc4, 0x4e, 0xc9, 0xd4, 0xa5, 0x0d, 0x92, 0xd8, 0x49, 0x79}, - {0x9f, 0xc7, 0x96, 0xe8, 0xf8, 0x52, 0x4f, 0x86, 0x3a, 0xe1, - 0x49, 0x6d, 0x38, 0x12, 0x42, 0x10, 0x5f, 0x1b, 0x78, 0xf5}, - {0xa0, 0x73, 0xe5, 0xc5, 0xbd, 0x43, 0x61, 0x0d, 0x86, 0x4c, - 0x21, 0x13, 0x0a, 0x85, 0x58, 0x57, 0xcc, 0x9c, 0xea, 0x46}, - {0xa0, 0xa1, 0xab, 0x90, 0xc9, 0xfc, 0x84, 0x7b, 0x3b, 0x12, - 0x61, 0xe8, 0x97, 0x7d, 0x5f, 0xd3, 0x22, 0x61, 0xd3, 0xcc}, - {0xa0, 0xf8, 0xdb, 0x3f, 0x0b, 0xf4, 0x17, 0x69, 0x3b, 0x28, - 0x2e, 0xb7, 0x4a, 0x6a, 0xd8, 0x6d, 0xf9, 0xd4, 0x48, 0xa3}, - {0xa1, 0x4b, 0x48, 0xd9, 0x43, 0xee, 0x0a, 0x0e, 0x40, 0x90, - 0x4f, 0x3c, 0xe0, 0xa4, 0xc0, 0x91, 0x93, 0x51, 0x5d, 0x3f}, - {0xa1, 0x58, 0x51, 0x87, 0x15, 0x65, 0x86, 0xce, 0xf9, 0xc4, - 0x54, 0xe2, 0x2a, 0xb1, 0x5c, 0x58, 0x74, 0x56, 0x07, 0xb4}, - {0xa1, 0xdb, 0x63, 0x93, 0x91, 0x6f, 0x17, 0xe4, 0x18, 0x55, - 0x09, 0x40, 0x04, 0x15, 0xc7, 0x02, 0x40, 0xb0, 0xae, 0x6b}, - {0xa1, 0xe7, 0xc6, 0x00, 0xaa, 0x41, 0x70, 0xe5, 0xb7, 0x4b, - 0xc9, 0x4f, 0x9b, 0x97, 0x03, 0xed, 0xc2, 0x61, 0xb4, 0xb9}, - {0xa3, 0x99, 0xf7, 0x6f, 0x0c, 0xbf, 0x4c, 0x9d, 0xa5, 0x5e, - 0x4a, 0xc2, 0x4e, 0x89, 0x60, 0x98, 0x4b, 0x29, 0x05, 0xb6}, - {0xa3, 0xe3, 0x1e, 0x20, 0xb2, 0xe4, 0x6a, 0x32, 0x85, 0x20, - 0x47, 0x2d, 0x0c, 0xde, 0x95, 0x23, 0xe7, 0x26, 0x0c, 0x6d}, - {0xa4, 0x34, 0x89, 0x15, 0x9a, 0x52, 0x0f, 0x0d, 0x93, 0xd0, - 0x32, 0xcc, 0xaf, 0x37, 0xe7, 0xfe, 0x20, 0xa8, 0xb4, 0x19}, - {0xa5, 0x9c, 0x9b, 0x10, 0xec, 0x73, 0x57, 0x51, 0x5a, 0xbb, - 0x66, 0x0c, 0x4d, 0x94, 0xf7, 0x3b, 0x9e, 0x6e, 0x92, 0x72}, - {0xa5, 0xec, 0x73, 0xd4, 0x8c, 0x34, 0xfc, 0xbe, 0xf1, 0x00, - 0x5a, 0xeb, 0x85, 0x84, 0x35, 0x24, 0xbb, 0xfa, 0xb7, 0x27}, - {0xa6, 0x9a, 0x91, 0xfd, 0x05, 0x7f, 0x13, 0x6a, 0x42, 0x63, - 0x0b, 0xb1, 0x76, 0x0d, 0x2d, 0x51, 0x12, 0x0c, 0x16, 0x50}, - {0xa7, 0xf8, 0x39, 0x0b, 0xa5, 0x77, 0x05, 0x09, 0x6f, 0xd3, - 0x69, 0x41, 0xd4, 0x2e, 0x71, 0x98, 0xc6, 0xd4, 0xd9, 0xd5}, - {0xa8, 0x98, 0x5d, 0x3a, 0x65, 0xe5, 0xe5, 0xc4, 0xb2, 0xd7, - 0xd6, 0x6d, 0x40, 0xc6, 0xdd, 0x2f, 0xb1, 0x9c, 0x54, 0x36}, - {0xa9, 0x62, 0x8f, 0x4b, 0x98, 0xa9, 0x1b, 0x48, 0x35, 0xba, - 0xd2, 0xc1, 0x46, 0x32, 0x86, 0xbb, 0x66, 0x64, 0x6a, 0x8c}, - {0xa9, 0x82, 0x2e, 0x6c, 0x69, 0x33, 0xc6, 0x3c, 0x14, 0x8c, - 0x2d, 0xca, 0xa4, 0x4a, 0x5c, 0xf1, 0xaa, 0xd2, 0xc4, 0x2e}, - {0xa9, 0xe9, 0x78, 0x08, 0x14, 0x37, 0x58, 0x88, 0xf2, 0x05, - 0x19, 0xb0, 0x6d, 0x2b, 0x0d, 0x2b, 0x60, 0x16, 0x90, 0x7d}, - {0xaa, 0xdb, 0xbc, 0x22, 0x23, 0x8f, 0xc4, 0x01, 0xa1, 0x27, - 0xbb, 0x38, 0xdd, 0xf4, 0x1d, 0xdb, 0x08, 0x9e, 0xf0, 0x12}, - {0xab, 0x16, 0xdd, 0x14, 0x4e, 0xcd, 0xc0, 0xfc, 0x4b, 0xaa, - 0xb6, 0x2e, 0xcf, 0x04, 0x08, 0x89, 0x6f, 0xde, 0x52, 0xb7}, - {0xab, 0x48, 0xf3, 0x33, 0xdb, 0x04, 0xab, 0xb9, 0xc0, 0x72, - 0xda, 0x5b, 0x0c, 0xc1, 0xd0, 0x57, 0xf0, 0x36, 0x9b, 0x46}, - {0xab, 0x9d, 0x58, 0xc0, 0x3f, 0x54, 0xb1, 0xda, 0xe3, 0xf7, - 0xc2, 0xd4, 0xc6, 0xc1, 0xec, 0x36, 0x94, 0x55, 0x9c, 0x37}, - {0xac, 0xed, 0x5f, 0x65, 0x53, 0xfd, 0x25, 0xce, 0x01, 0x5f, - 0x1f, 0x7a, 0x48, 0x3b, 0x6a, 0x74, 0x9f, 0x61, 0x78, 0xc6}, - {0xad, 0x7e, 0x1c, 0x28, 0xb0, 0x64, 0xef, 0x8f, 0x60, 0x03, - 0x40, 0x20, 0x14, 0xc3, 0xd0, 0xe3, 0x37, 0x0e, 0xb5, 0x8a}, - {0xae, 0x3b, 0x31, 0xbf, 0x8f, 0xd8, 0x91, 0x07, 0x9c, 0xf1, - 0xdf, 0x34, 0xcb, 0xce, 0x6e, 0x70, 0xd3, 0x7f, 0xb5, 0xb0}, - {0xae, 0x50, 0x83, 0xed, 0x7c, 0xf4, 0x5c, 0xbc, 0x8f, 0x61, - 0xc6, 0x21, 0xfe, 0x68, 0x5d, 0x79, 0x42, 0x21, 0x15, 0x6e}, - {0xae, 0xc5, 0xfb, 0x3f, 0xc8, 0xe1, 0xbf, 0xc4, 0xe5, 0x4f, - 0x03, 0x07, 0x5a, 0x9a, 0xe8, 0x00, 0xb7, 0xf7, 0xb6, 0xfa}, - {0xaf, 0xe5, 0xd2, 0x44, 0xa8, 0xd1, 0x19, 0x42, 0x30, 0xff, - 0x47, 0x9f, 0xe2, 0xf8, 0x97, 0xbb, 0xcd, 0x7a, 0x8c, 0xb4}, - {0xb0, 0x91, 0xaa, 0x91, 0x38, 0x47, 0xf3, 0x13, 0xd7, 0x27, - 0xbc, 0xef, 0xc8, 0x17, 0x9f, 0x08, 0x6f, 0x3a, 0x8c, 0x0f}, - {0xb1, 0x2e, 0x13, 0x63, 0x45, 0x86, 0xa4, 0x6f, 0x1a, 0xb2, - 0x60, 0x68, 0x37, 0x58, 0x2d, 0xc4, 0xac, 0xfd, 0x94, 0x97}, - {0xb1, 0x72, 0xb1, 0xa5, 0x6d, 0x95, 0xf9, 0x1f, 0xe5, 0x02, - 0x87, 0xe1, 0x4d, 0x37, 0xea, 0x6a, 0x44, 0x63, 0x76, 0x8a}, - {0xb1, 0x9d, 0xd0, 0x96, 0xdc, 0xd4, 0xe3, 0xe0, 0xfd, 0x67, - 0x68, 0x85, 0x50, 0x5a, 0x67, 0x2c, 0x43, 0x8d, 0x4e, 0x9c}, - {0xb1, 0xb2, 0x36, 0x4f, 0xd4, 0xd4, 0xf5, 0x2e, 0x89, 0xb2, - 0xd0, 0xfa, 0xf3, 0x3e, 0x4d, 0x62, 0xbd, 0x96, 0x99, 0x21}, - {0xb1, 0xbc, 0x96, 0x8b, 0xd4, 0xf4, 0x9d, 0x62, 0x2a, 0xa8, - 0x9a, 0x81, 0xf2, 0x15, 0x01, 0x52, 0xa4, 0x1d, 0x82, 0x9c}, - {0xb1, 0xea, 0xc3, 0xe5, 0xb8, 0x24, 0x76, 0xe9, 0xd5, 0x0b, - 0x1e, 0xc6, 0x7d, 0x2c, 0xc1, 0x1e, 0x12, 0xe0, 0xb4, 0x91}, - {0xb2, 0xbd, 0x90, 0x31, 0xaa, 0x6d, 0x0e, 0x14, 0xf4, 0xc5, - 0x7f, 0xd5, 0x48, 0x25, 0x8f, 0x37, 0xb1, 0xfb, 0x39, 0xe4}, - {0xb3, 0x1e, 0xb1, 0xb7, 0x40, 0xe3, 0x6c, 0x84, 0x02, 0xda, - 0xdc, 0x37, 0xd4, 0x4d, 0xf5, 0xd4, 0x67, 0x49, 0x52, 0xf9}, - {0xb3, 0x8f, 0xec, 0xec, 0x0b, 0x14, 0x8a, 0xa6, 0x86, 0xc3, - 0xd0, 0x0f, 0x01, 0xec, 0xc8, 0x84, 0x8e, 0x80, 0x85, 0xeb}, - {0xb3, 0xea, 0xc4, 0x47, 0x76, 0xc9, 0xc8, 0x1c, 0xea, 0xf2, - 0x9d, 0x95, 0xb6, 0xcc, 0xa0, 0x08, 0x1b, 0x67, 0xec, 0x9d}, - {0xb4, 0x2c, 0x86, 0xc9, 0x57, 0xfd, 0x39, 0x20, 0x0c, 0x45, - 0xbb, 0xe3, 0x76, 0xc0, 0x8c, 0xd0, 0xf4, 0xd5, 0x86, 0xdb}, - {0xb4, 0x35, 0xd4, 0xe1, 0x11, 0x9d, 0x1c, 0x66, 0x90, 0xa7, - 0x49, 0xeb, 0xb3, 0x94, 0xbd, 0x63, 0x7b, 0xa7, 0x82, 0xb7}, - {0xb5, 0x1c, 0x06, 0x7c, 0xee, 0x2b, 0x0c, 0x3d, 0xf8, 0x55, - 0xab, 0x2d, 0x92, 0xf4, 0xfe, 0x39, 0xd4, 0xe7, 0x0f, 0x0e}, - {0xb5, 0x61, 0xeb, 0xea, 0xa4, 0xde, 0xe4, 0x25, 0x4b, 0x69, - 0x1a, 0x98, 0xa5, 0x57, 0x47, 0xc2, 0x34, 0xc7, 0xd9, 0x71}, - {0xb7, 0x2f, 0xff, 0x92, 0xd2, 0xce, 0x43, 0xde, 0x0a, 0x8d, - 0x4c, 0x54, 0x8c, 0x50, 0x37, 0x26, 0xa8, 0x1e, 0x2b, 0x93}, - {0xb8, 0x01, 0x86, 0xd1, 0xeb, 0x9c, 0x86, 0xa5, 0x41, 0x04, - 0xcf, 0x30, 0x54, 0xf3, 0x4c, 0x52, 0xb7, 0xe5, 0x58, 0xc6}, - {0xb8, 0x23, 0x6b, 0x00, 0x2f, 0x1d, 0x16, 0x86, 0x53, 0x01, - 0x55, 0x6c, 0x11, 0xa4, 0x37, 0xca, 0xeb, 0xff, 0xc3, 0xbb}, - {0xb8, 0x65, 0x13, 0x0b, 0xed, 0xca, 0x38, 0xd2, 0x7f, 0x69, - 0x92, 0x94, 0x20, 0x77, 0x0b, 0xed, 0x86, 0xef, 0xbc, 0x10}, - {0xb9, 0x42, 0x94, 0xbf, 0x91, 0xea, 0x8f, 0xb6, 0x4b, 0xe6, - 0x10, 0x97, 0xc7, 0xfb, 0x00, 0x13, 0x59, 0xb6, 0x76, 0xcb}, - {0xb9, 0xcd, 0x0c, 0xf6, 0x98, 0x35, 0xea, 0xbf, 0x3f, 0x13, - 0x7f, 0x20, 0x49, 0xe4, 0xc9, 0x24, 0x87, 0x84, 0x77, 0xdb}, - {0xba, 0x29, 0x41, 0x60, 0x77, 0x98, 0x3f, 0xf4, 0xf3, 0xef, - 0xf2, 0x31, 0x05, 0x3b, 0x2e, 0xea, 0x6d, 0x4d, 0x45, 0xfd}, - {0xbc, 0x7b, 0x3c, 0x6f, 0xef, 0x26, 0xb9, 0xf7, 0xab, 0x10, - 0xd7, 0xa1, 0xf6, 0xb6, 0x7c, 0x5e, 0xd2, 0xa1, 0x2d, 0x3d}, - {0xbc, 0x92, 0x19, 0xdd, 0xc9, 0x8e, 0x14, 0xbf, 0x1a, 0x78, - 0x1f, 0x6e, 0x28, 0x0b, 0x04, 0xc2, 0x7f, 0x90, 0x27, 0x12}, - {0xbe, 0x1a, 0xf2, 0x85, 0xf7, 0x86, 0xcd, 0xdb, 0xc4, 0x30, - 0x38, 0x2e, 0xef, 0xf2, 0xa6, 0x6d, 0xfb, 0xcd, 0x5d, 0xd0}, - {0xbe, 0x36, 0xa4, 0x56, 0x2f, 0xb2, 0xee, 0x05, 0xdb, 0xb3, - 0xd3, 0x23, 0x23, 0xad, 0xf4, 0x45, 0x08, 0x4e, 0xd6, 0x56}, - {0xbe, 0xb5, 0xa9, 0x95, 0x74, 0x6b, 0x9e, 0xdf, 0x73, 0x8b, - 0x56, 0xe6, 0xdf, 0x43, 0x7a, 0x77, 0xbe, 0x10, 0x6b, 0x81}, - {0xbe, 0xd5, 0x25, 0xd1, 0xac, 0x63, 0xa7, 0xfc, 0x6a, 0x66, - 0x0b, 0xa7, 0xa8, 0x95, 0x81, 0x8d, 0x5e, 0x8d, 0xd5, 0x64}, - {0xc0, 0x9a, 0xb0, 0xc8, 0xad, 0x71, 0x14, 0x71, 0x4e, 0xd5, - 0xe2, 0x1a, 0x5a, 0x27, 0x6a, 0xdc, 0xd5, 0xe7, 0xef, 0xcb}, - {0xc0, 0xdb, 0x57, 0x81, 0x57, 0xe9, 0xee, 0x82, 0xb5, 0x91, - 0x7d, 0xf0, 0xdd, 0x6d, 0x82, 0xee, 0x90, 0x39, 0xc4, 0xe2}, - {0xc1, 0x82, 0x11, 0x32, 0x8a, 0x92, 0xb3, 0xb2, 0x38, 0x09, - 0xb9, 0xb5, 0xe2, 0x74, 0x0a, 0x07, 0xfb, 0x12, 0xeb, 0x5e}, - {0xc4, 0x18, 0xf6, 0x4d, 0x46, 0xd1, 0xdf, 0x00, 0x3d, 0x27, - 0x30, 0x13, 0x72, 0x43, 0xa9, 0x12, 0x11, 0xc6, 0x75, 0xfb}, - {0xc4, 0x67, 0x4d, 0xdc, 0x6c, 0xe2, 0x96, 0x7f, 0xf9, 0xc9, - 0x2e, 0x07, 0x2e, 0xf8, 0xe8, 0xa7, 0xfb, 0xd6, 0xa1, 0x31}, - {0xc7, 0x30, 0x26, 0xe3, 0x25, 0xfe, 0x21, 0x91, 0x6b, 0x55, - 0xc4, 0xb5, 0x3a, 0x56, 0xb1, 0x3d, 0xca, 0xf3, 0xd6, 0x25}, - {0xc7, 0xf7, 0xcb, 0xe2, 0x02, 0x36, 0x66, 0xf9, 0x86, 0x02, - 0x5d, 0x4a, 0x3e, 0x31, 0x3f, 0x29, 0xeb, 0x0c, 0x5b, 0x38}, - {0xc8, 0x60, 0xa3, 0x18, 0xfc, 0xf5, 0xb7, 0x13, 0x0b, 0x10, - 0x07, 0xad, 0x7f, 0x61, 0x4a, 0x40, 0xff, 0xff, 0x18, 0x5f}, - {0xc8, 0xec, 0x8c, 0x87, 0x92, 0x69, 0xcb, 0x4b, 0xab, 0x39, - 0xe9, 0x8d, 0x7e, 0x57, 0x67, 0xf3, 0x14, 0x95, 0x73, 0x9d}, - {0xc9, 0x32, 0x1d, 0xe6, 0xb5, 0xa8, 0x26, 0x66, 0xcf, 0x69, - 0x71, 0xa1, 0x8a, 0x56, 0xf2, 0xd3, 0xa8, 0x67, 0x56, 0x02}, - {0xc9, 0x3c, 0x34, 0xea, 0x90, 0xd9, 0x13, 0x0c, 0x0f, 0x03, - 0x00, 0x4b, 0x98, 0xbd, 0x8b, 0x35, 0x70, 0x91, 0x56, 0x11}, - {0xc9, 0xa8, 0xb9, 0xe7, 0x55, 0x80, 0x5e, 0x58, 0xe3, 0x53, - 0x77, 0xa7, 0x25, 0xeb, 0xaf, 0xc3, 0x7b, 0x27, 0xcc, 0xd7}, - {0xca, 0x3a, 0xfb, 0xcf, 0x12, 0x40, 0x36, 0x4b, 0x44, 0xb2, - 0x16, 0x20, 0x88, 0x80, 0x48, 0x39, 0x19, 0x93, 0x7c, 0xf7}, - {0xca, 0xbb, 0x51, 0x67, 0x24, 0x00, 0x58, 0x8e, 0x64, 0x19, - 0xf1, 0xd4, 0x08, 0x78, 0xd0, 0x40, 0x3a, 0xa2, 0x02, 0x64}, - {0xcb, 0x44, 0xa0, 0x97, 0x85, 0x7c, 0x45, 0xfa, 0x18, 0x7e, - 0xd9, 0x52, 0x08, 0x6c, 0xb9, 0x84, 0x1f, 0x2d, 0x51, 0xb5}, - {0xcb, 0x65, 0x82, 0x64, 0xea, 0x8c, 0xda, 0x18, 0x6e, 0x17, - 0x52, 0xfb, 0x52, 0xc3, 0x97, 0x36, 0x7e, 0xa3, 0x87, 0xbe}, - {0xcb, 0xa1, 0xc5, 0xf8, 0xb0, 0xe3, 0x5e, 0xb8, 0xb9, 0x45, - 0x12, 0xd3, 0xf9, 0x34, 0xa2, 0xe9, 0x06, 0x10, 0xd3, 0x36}, - {0xcc, 0x7e, 0xa2, 0x92, 0xaf, 0x87, 0x15, 0xd7, 0x4c, 0xa4, - 0xb4, 0x15, 0xf3, 0x20, 0x15, 0x4b, 0x24, 0xf5, 0x65, 0xfd}, - {0xcd, 0x78, 0x7a, 0x3d, 0x5c, 0xba, 0x82, 0x07, 0x08, 0x28, - 0x48, 0x36, 0x5e, 0x9a, 0xcd, 0xe9, 0x68, 0x33, 0x64, 0xd8}, - {0xcd, 0xd4, 0xee, 0xae, 0x60, 0x00, 0xac, 0x7f, 0x40, 0xc3, - 0x80, 0x2c, 0x17, 0x1e, 0x30, 0x14, 0x80, 0x30, 0xc0, 0x72}, - {0xce, 0x6a, 0x64, 0xa3, 0x09, 0xe4, 0x2f, 0xbb, 0xd9, 0x85, - 0x1c, 0x45, 0x3e, 0x64, 0x09, 0xea, 0xe8, 0x7d, 0x60, 0xf1}, - {0xce, 0xa9, 0x89, 0x0d, 0x85, 0xd8, 0x07, 0x53, 0xa6, 0x26, - 0x28, 0x6c, 0xda, 0xd7, 0x8c, 0xb5, 0x66, 0xd7, 0x0c, 0xf2}, - {0xcf, 0x9e, 0x87, 0x6d, 0xd3, 0xeb, 0xfc, 0x42, 0x26, 0x97, - 0xa3, 0xb5, 0xa3, 0x7a, 0xa0, 0x76, 0xa9, 0x06, 0x23, 0x48}, - {0xcf, 0xde, 0xfe, 0x10, 0x2f, 0xda, 0x05, 0xbb, 0xe4, 0xc7, - 0x8d, 0x2e, 0x44, 0x23, 0x58, 0x90, 0x05, 0xb2, 0x57, 0x1d}, - {0xcf, 0xe4, 0x31, 0x3d, 0xba, 0x05, 0xb8, 0xa7, 0xc3, 0x00, - 0x63, 0x99, 0x5a, 0x9e, 0xb7, 0xc2, 0x47, 0xad, 0x8f, 0xd5}, - {0xcf, 0xf3, 0x60, 0xf5, 0x24, 0xcb, 0x20, 0xf1, 0xfe, 0xad, - 0x89, 0x00, 0x6f, 0x7f, 0x58, 0x6a, 0x28, 0x5b, 0x2d, 0x5b}, - {0xcf, 0xf8, 0x10, 0xfb, 0x2c, 0x4f, 0xfc, 0x01, 0x56, 0xbf, - 0xe1, 0xe1, 0xfa, 0xbc, 0xb4, 0x18, 0xc6, 0x8d, 0x31, 0xc5}, - {0xd1, 0xcb, 0xca, 0x5d, 0xb2, 0xd5, 0x2a, 0x7f, 0x69, 0x3b, - 0x67, 0x4d, 0xe5, 0xf0, 0x5a, 0x1d, 0x0c, 0x95, 0x7d, 0xf0}, - {0xd1, 0xeb, 0x23, 0xa4, 0x6d, 0x17, 0xd6, 0x8f, 0xd9, 0x25, - 0x64, 0xc2, 0xf1, 0xf1, 0x60, 0x17, 0x64, 0xd8, 0xe3, 0x49}, - {0xd2, 0x32, 0x09, 0xad, 0x23, 0xd3, 0x14, 0x23, 0x21, 0x74, - 0xe4, 0x0d, 0x7f, 0x9d, 0x62, 0x13, 0x97, 0x86, 0x63, 0x3a}, - {0xd2, 0x44, 0x1a, 0xa8, 0xc2, 0x03, 0xae, 0xca, 0xa9, 0x6e, - 0x50, 0x1f, 0x12, 0x4d, 0x52, 0xb6, 0x8f, 0xe4, 0xc3, 0x75}, - {0xd2, 0x9f, 0x6c, 0x98, 0xbe, 0xfc, 0x6d, 0x98, 0x65, 0x21, - 0x54, 0x3e, 0xe8, 0xbe, 0x56, 0xce, 0xbc, 0x28, 0x8c, 0xf3}, - {0xd2, 0xed, 0xf8, 0x8b, 0x41, 0xb6, 0xfe, 0x01, 0x46, 0x1d, - 0x6e, 0x28, 0x34, 0xec, 0x7c, 0x8f, 0x6c, 0x77, 0x72, 0x1e}, - {0xd3, 0xc0, 0x63, 0xf2, 0x19, 0xed, 0x07, 0x3e, 0x34, 0xad, - 0x5d, 0x75, 0x0b, 0x32, 0x76, 0x29, 0xff, 0xd5, 0x9a, 0xf2}, - {0xd3, 0xee, 0xfb, 0xcb, 0xbc, 0xf4, 0x98, 0x67, 0x83, 0x86, - 0x26, 0xe2, 0x3b, 0xb5, 0x9c, 0xa0, 0x1e, 0x30, 0x5d, 0xb7}, - {0xd4, 0xde, 0x20, 0xd0, 0x5e, 0x66, 0xfc, 0x53, 0xfe, 0x1a, - 0x50, 0x88, 0x2c, 0x78, 0xdb, 0x28, 0x52, 0xca, 0xe4, 0x74}, - {0xd6, 0x9b, 0x56, 0x11, 0x48, 0xf0, 0x1c, 0x77, 0xc5, 0x45, - 0x78, 0xc1, 0x09, 0x26, 0xdf, 0x5b, 0x85, 0x69, 0x76, 0xad}, - {0xd6, 0xbf, 0x79, 0x94, 0xf4, 0x2b, 0xe5, 0xfa, 0x29, 0xda, - 0x0b, 0xd7, 0x58, 0x7b, 0x59, 0x1f, 0x47, 0xa4, 0x4f, 0x22}, - {0xd6, 0xda, 0xa8, 0x20, 0x8d, 0x09, 0xd2, 0x15, 0x4d, 0x24, - 0xb5, 0x2f, 0xcb, 0x34, 0x6e, 0xb2, 0x58, 0xb2, 0x8a, 0x58}, - {0xd8, 0xa6, 0x33, 0x2c, 0xe0, 0x03, 0x6f, 0xb1, 0x85, 0xf6, - 0x63, 0x4f, 0x7d, 0x6a, 0x06, 0x65, 0x26, 0x32, 0x28, 0x27}, - {0xd8, 0xc5, 0x38, 0x8a, 0xb7, 0x30, 0x1b, 0x1b, 0x6e, 0xd4, - 0x7a, 0xe6, 0x45, 0x25, 0x3a, 0x6f, 0x9f, 0x1a, 0x27, 0x61}, - {0xd8, 0xeb, 0x6b, 0x41, 0x51, 0x92, 0x59, 0xe0, 0xf3, 0xe7, - 0x85, 0x00, 0xc0, 0x3d, 0xb6, 0x88, 0x97, 0xc9, 0xee, 0xfc}, - {0xd9, 0x04, 0x08, 0x0a, 0x49, 0x29, 0xc8, 0x38, 0xe9, 0xf1, - 0x85, 0xec, 0xf7, 0xa2, 0x2d, 0xef, 0x99, 0x34, 0x24, 0x07}, - {0xda, 0x40, 0x18, 0x8b, 0x91, 0x89, 0xa3, 0xed, 0xee, 0xae, - 0xda, 0x97, 0xfe, 0x2f, 0x9d, 0xf5, 0xb7, 0xd1, 0x8a, 0x41}, - {0xda, 0x8b, 0x65, 0x67, 0xef, 0x3f, 0x6e, 0x1e, 0xa2, 0x6a, - 0xb1, 0x46, 0xe3, 0x6c, 0xcb, 0x57, 0x28, 0x04, 0x18, 0x46}, - {0xda, 0xc9, 0x02, 0x4f, 0x54, 0xd8, 0xf6, 0xdf, 0x94, 0x93, - 0x5f, 0xb1, 0x73, 0x26, 0x38, 0xca, 0x6a, 0xd7, 0x7c, 0x13}, - {0xda, 0xfa, 0xf7, 0xfa, 0x66, 0x84, 0xec, 0x06, 0x8f, 0x14, - 0x50, 0xbd, 0xc7, 0xc2, 0x81, 0xa5, 0xbc, 0xa9, 0x64, 0x57}, - {0xdb, 0x2b, 0x7b, 0x43, 0x4d, 0xfb, 0x7f, 0xc1, 0xcb, 0x59, - 0x26, 0xec, 0x5d, 0x95, 0x21, 0xfe, 0x35, 0x0f, 0xf2, 0x79}, - {0xdb, 0xac, 0x3c, 0x7a, 0xa4, 0x25, 0x4d, 0xa1, 0xaa, 0x5c, - 0xaa, 0xd6, 0x84, 0x68, 0xcb, 0x88, 0xee, 0xdd, 0xee, 0xa8}, - {0xdd, 0x83, 0xc5, 0x19, 0xd4, 0x34, 0x81, 0xfa, 0xd4, 0xc2, - 0x2c, 0x03, 0xd7, 0x02, 0xfe, 0x9f, 0x3b, 0x22, 0xf5, 0x17}, - {0xdd, 0xe1, 0xd2, 0xa9, 0x01, 0x80, 0x2e, 0x1d, 0x87, 0x5e, - 0x84, 0xb3, 0x80, 0x7e, 0x4b, 0xb1, 0xfd, 0x99, 0x41, 0x34}, - {0xdd, 0xfb, 0x16, 0xcd, 0x49, 0x31, 0xc9, 0x73, 0xa2, 0x03, - 0x7d, 0x3f, 0xc8, 0x3a, 0x4d, 0x7d, 0x77, 0x5d, 0x05, 0xe4}, - {0xde, 0x28, 0xf4, 0xa4, 0xff, 0xe5, 0xb9, 0x2f, 0xa3, 0xc5, - 0x03, 0xd1, 0xa3, 0x49, 0xa7, 0xf9, 0x96, 0x2a, 0x82, 0x12}, - {0xde, 0x3f, 0x40, 0xbd, 0x50, 0x93, 0xd3, 0x9b, 0x6c, 0x60, - 0xf6, 0xda, 0xbc, 0x07, 0x62, 0x01, 0x00, 0x89, 0x76, 0xc9}, - {0xde, 0x99, 0x0c, 0xed, 0x99, 0xe0, 0x43, 0x1f, 0x60, 0xed, - 0xc3, 0x93, 0x7e, 0x7c, 0xd5, 0xbf, 0x0e, 0xd9, 0xe5, 0xfa}, - {0xdf, 0x3c, 0x24, 0xf9, 0xbf, 0xd6, 0x66, 0x76, 0x1b, 0x26, - 0x80, 0x73, 0xfe, 0x06, 0xd1, 0xcc, 0x8d, 0x4f, 0x82, 0xa4}, - {0xdf, 0x64, 0x6d, 0xcb, 0x7b, 0x0f, 0xd3, 0xa9, 0x6a, 0xee, - 0x88, 0xc6, 0x4e, 0x2d, 0x67, 0x67, 0x11, 0xff, 0x9d, 0x5f}, - {0xdf, 0x71, 0x7e, 0xaa, 0x4a, 0xd9, 0x4e, 0xc9, 0x55, 0x84, - 0x99, 0x60, 0x2d, 0x48, 0xde, 0x5f, 0xbc, 0xf0, 0x3a, 0x25}, - {0xe0, 0x92, 0x5e, 0x18, 0xc7, 0x76, 0x5e, 0x22, 0xda, 0xbd, - 0x94, 0x27, 0x52, 0x9d, 0xa6, 0xaf, 0x4e, 0x06, 0x64, 0x28}, - {0xe0, 0x98, 0xec, 0xf3, 0x55, 0xc1, 0x99, 0x53, 0x27, 0x4d, - 0x84, 0x77, 0x2a, 0x1c, 0xec, 0x96, 0xdc, 0x33, 0x56, 0xca}, - {0xe0, 0xab, 0x05, 0x94, 0x20, 0x72, 0x54, 0x93, 0x05, 0x60, - 0x62, 0x02, 0x36, 0x70, 0xf7, 0xcd, 0x2e, 0xfc, 0x66, 0x66}, - {0xe0, 0xb4, 0x32, 0x2e, 0xb2, 0xf6, 0xa5, 0x68, 0xb6, 0x54, - 0x53, 0x84, 0x48, 0x18, 0x4a, 0x50, 0x36, 0x87, 0x43, 0x84}, - {0xe1, 0x2d, 0xfb, 0x4b, 0x41, 0xd7, 0xd9, 0xc3, 0x2b, 0x30, - 0x51, 0x4b, 0xac, 0x1d, 0x81, 0xd8, 0x38, 0x5e, 0x2d, 0x46}, - {0xe1, 0xa4, 0x5b, 0x14, 0x1a, 0x21, 0xda, 0x1a, 0x79, 0xf4, - 0x1a, 0x42, 0xa9, 0x61, 0xd6, 0x69, 0xcd, 0x06, 0x34, 0xc1}, - {0xe2, 0xb8, 0x29, 0x4b, 0x55, 0x84, 0xab, 0x6b, 0x58, 0xc2, - 0x90, 0x46, 0x6c, 0xac, 0x3f, 0xb8, 0x39, 0x8f, 0x84, 0x83}, - {0xe3, 0x92, 0x51, 0x2f, 0x0a, 0xcf, 0xf5, 0x05, 0xdf, 0xf6, - 0xde, 0x06, 0x7f, 0x75, 0x37, 0xe1, 0x65, 0xea, 0x57, 0x4b}, - {0xe3, 0xd7, 0x36, 0x06, 0x99, 0x6c, 0xdf, 0xef, 0x61, 0xfa, - 0x04, 0xc3, 0x35, 0xe9, 0x8e, 0xa9, 0x61, 0x04, 0x26, 0x4a}, - {0xe5, 0xdf, 0x74, 0x3c, 0xb6, 0x01, 0xc4, 0x9b, 0x98, 0x43, - 0xdc, 0xab, 0x8c, 0xe8, 0x6a, 0x81, 0x10, 0x9f, 0xe4, 0x8e}, - {0xe6, 0x19, 0xd2, 0x5b, 0x38, 0x0b, 0x7b, 0x13, 0xfd, 0xa3, - 0x3e, 0x8a, 0x58, 0xcd, 0x82, 0xd8, 0xa8, 0x8e, 0x05, 0x15}, - {0xe6, 0x21, 0xf3, 0x35, 0x43, 0x79, 0x05, 0x9a, 0x4b, 0x68, - 0x30, 0x9d, 0x8a, 0x2f, 0x74, 0x22, 0x15, 0x87, 0xec, 0x79}, - {0xe7, 0x07, 0x15, 0xf6, 0xf7, 0x28, 0x36, 0x5b, 0x51, 0x90, - 0xe2, 0x71, 0xde, 0xe4, 0xc6, 0x5e, 0xbe, 0xea, 0xca, 0xf3}, - {0xe7, 0xa1, 0x90, 0x29, 0xd3, 0xd5, 0x52, 0xdc, 0x0d, 0x0f, - 0xc6, 0x92, 0xd3, 0xea, 0x88, 0x0d, 0x15, 0x2e, 0x1a, 0x6b}, - {0xe7, 0xb4, 0xf6, 0x9d, 0x61, 0xec, 0x90, 0x69, 0xdb, 0x7e, - 0x90, 0xa7, 0x40, 0x1a, 0x3c, 0xf4, 0x7d, 0x4f, 0xe8, 0xee}, - {0xea, 0xbd, 0xa2, 0x40, 0x44, 0x0a, 0xbb, 0xd6, 0x94, 0x93, - 0x0a, 0x01, 0xd0, 0x97, 0x64, 0xc6, 0xc2, 0xd7, 0x79, 0x66}, - {0xec, 0x0c, 0x37, 0x16, 0xea, 0x9e, 0xdf, 0xad, 0xd3, 0x5d, - 0xfb, 0xd5, 0x56, 0x08, 0xe6, 0x0a, 0x05, 0xd3, 0xcb, 0xf3}, - {0xec, 0x93, 0xde, 0x08, 0x3c, 0x93, 0xd9, 0x33, 0xa9, 0x86, - 0xb3, 0xd5, 0xcd, 0xe2, 0x5a, 0xcb, 0x2f, 0xee, 0xcf, 0x8e}, - {0xed, 0x8d, 0xc8, 0x38, 0x6c, 0x48, 0x86, 0xae, 0xee, 0x07, - 0x91, 0x58, 0xaa, 0xc3, 0xbf, 0xe6, 0x58, 0xe3, 0x94, 0xb4}, - {0xed, 0xb3, 0xcb, 0x5f, 0xb4, 0x19, 0xa1, 0x85, 0x06, 0x62, - 0x67, 0xe5, 0x79, 0x15, 0x54, 0xe1, 0xe2, 0x8b, 0x63, 0x99}, - {0xee, 0x29, 0xd6, 0xea, 0x98, 0xe6, 0x32, 0xc6, 0xe5, 0x27, - 0xe0, 0x90, 0x6f, 0x02, 0x80, 0x68, 0x8b, 0xdf, 0x44, 0xdc}, - {0xee, 0x86, 0x93, 0x87, 0xff, 0xfd, 0x83, 0x49, 0xab, 0x5a, - 0xd1, 0x43, 0x22, 0x58, 0x87, 0x89, 0xa4, 0x57, 0xb0, 0x12}, - {0xf0, 0x0f, 0xc3, 0x7d, 0x6a, 0x1c, 0x92, 0x61, 0xfb, 0x6b, - 0xc1, 0xc2, 0x18, 0x49, 0x8c, 0x5a, 0xa4, 0xdc, 0x51, 0xfb}, - {0xf1, 0x38, 0xa3, 0x30, 0xa4, 0xea, 0x98, 0x6b, 0xeb, 0x52, - 0x0b, 0xb1, 0x10, 0x35, 0x87, 0x6e, 0xfb, 0x9d, 0x7f, 0x1c}, - {0xf1, 0x7f, 0x6f, 0xb6, 0x31, 0xdc, 0x99, 0xe3, 0xa3, 0xc8, - 0x7f, 0xfe, 0x1c, 0xf1, 0x81, 0x10, 0x88, 0xd9, 0x60, 0x33}, - {0xf1, 0x8b, 0x53, 0x8d, 0x1b, 0xe9, 0x03, 0xb6, 0xa6, 0xf0, - 0x56, 0x43, 0x5b, 0x17, 0x15, 0x89, 0xca, 0xf3, 0x6b, 0xf2}, - {0xf3, 0x73, 0xb3, 0x87, 0x06, 0x5a, 0x28, 0x84, 0x8a, 0xf2, - 0xf3, 0x4a, 0xce, 0x19, 0x2b, 0xdd, 0xc7, 0x8e, 0x9c, 0xac}, - {0xf4, 0x40, 0x95, 0xc2, 0x38, 0xac, 0x73, 0xfc, 0x4f, 0x77, - 0xbf, 0x8f, 0x98, 0xdf, 0x70, 0xf8, 0xf0, 0x91, 0xbc, 0x52}, - {0xf4, 0x8b, 0x11, 0xbf, 0xde, 0xab, 0xbe, 0x94, 0x54, 0x20, - 0x71, 0xe6, 0x41, 0xde, 0x6b, 0xbe, 0x88, 0x2b, 0x40, 0xb9}, - {0xf5, 0x17, 0xa2, 0x4f, 0x9a, 0x48, 0xc6, 0xc9, 0xf8, 0xa2, - 0x00, 0x26, 0x9f, 0xdc, 0x0f, 0x48, 0x2c, 0xab, 0x30, 0x89}, - {0xf5, 0xc2, 0x7c, 0xf5, 0xff, 0xf3, 0x02, 0x9a, 0xcf, 0x1a, - 0x1a, 0x4b, 0xec, 0x7e, 0xe1, 0x96, 0x4c, 0x77, 0xd7, 0x84}, - {0xf9, 0xb5, 0xb6, 0x32, 0x45, 0x5f, 0x9c, 0xbe, 0xec, 0x57, - 0x5f, 0x80, 0xdc, 0xe9, 0x6e, 0x2c, 0xc7, 0xb2, 0x78, 0xb7}, - {0xf9, 0xcd, 0x0e, 0x2c, 0xda, 0x76, 0x24, 0xc1, 0x8f, 0xbd, - 0xf0, 0xf0, 0xab, 0xb6, 0x45, 0xb8, 0xf7, 0xfe, 0xd5, 0x7a}, - {0xf9, 0xdd, 0x19, 0x26, 0x6b, 0x20, 0x43, 0xf1, 0xfe, 0x4b, - 0x3d, 0xcb, 0x01, 0x90, 0xaf, 0xf1, 0x1f, 0x31, 0xa6, 0x9d}, - {0xfa, 0x08, 0x82, 0x59, 0x5f, 0x9c, 0xa6, 0xa1, 0x1e, 0xcc, - 0xbe, 0xaf, 0x65, 0xc7, 0x64, 0xc0, 0xcc, 0xc3, 0x11, 0xd0}, - {0xfa, 0xa7, 0xd9, 0xfb, 0x31, 0xb7, 0x46, 0xf2, 0x00, 0xa8, - 0x5e, 0x65, 0x79, 0x76, 0x13, 0xd8, 0x16, 0xe0, 0x63, 0xb5}, - {0xfa, 0xaa, 0x27, 0xb8, 0xca, 0xf5, 0xfd, 0xf5, 0xcd, 0xa9, - 0x8a, 0xc3, 0x37, 0x85, 0x72, 0xe0, 0x4c, 0xe8, 0xf2, 0xe0}, - {0xfa, 0xb7, 0xee, 0x36, 0x97, 0x26, 0x62, 0xfb, 0x2d, 0xb0, - 0x2a, 0xf6, 0xbf, 0x03, 0xfd, 0xe8, 0x7c, 0x4b, 0x2f, 0x9b}, - {0xfd, 0x1e, 0xd1, 0xe2, 0x02, 0x1b, 0x0b, 0x9f, 0x73, 0xe8, - 0xeb, 0x75, 0xce, 0x23, 0x43, 0x6b, 0xbc, 0xc7, 0x46, 0xeb}, - {0xfe, 0x45, 0x65, 0x9b, 0x79, 0x03, 0x5b, 0x98, 0xa1, 0x61, - 0xb5, 0x51, 0x2e, 0xac, 0xda, 0x58, 0x09, 0x48, 0x22, 0x4d}, - {0xfe, 0xb8, 0xc4, 0x32, 0xdc, 0xf9, 0x76, 0x9a, 0xce, 0xae, - 0x3d, 0xd8, 0x90, 0x8f, 0xfd, 0x28, 0x86, 0x65, 0x64, 0x7d}, - {0xff, 0xb7, 0xe0, 0x8f, 0x66, 0xe1, 0xd0, 0xc2, 0x58, 0x2f, - 0x02, 0x45, 0xc4, 0x97, 0x02, 0x92, 0xa4, 0x6e, 0x88, 0x03}, +static uint8_t kKnownRootCertSHA256Hashes[][32] = { + // C=US, O=Network Solutions L.L.C., CN=Network Solutions Certificate + // Authority + {0x00, 0x16, 0x86, 0xCD, 0x18, 0x1F, 0x83, 0xA1, 0xB1, 0x21, 0x7D, 0x30, + 0x5B, 0x36, 0x5C, 0x41, 0xE3, 0x47, 0x0A, 0x78, 0xA1, 0xD3, 0x7B, 0x13, + 0x4A, 0x98, 0xCD, 0x54, 0x7B, 0x92, 0xDA, 0xB3}, + // C=SI, O=POSTA, OU=POSTArCA + {0x00, 0x7E, 0x45, 0x2F, 0xD5, 0xCF, 0x83, 0x89, 0x46, 0x69, 0x6D, 0xFE, + 0x37, 0xA2, 0xDB, 0x2E, 0xF3, 0x99, 0x14, 0x36, 0xD2, 0x7B, 0xCB, 0xAB, + 0x45, 0x92, 0x20, 0x53, 0xC1, 0x5A, 0x87, 0xA8}, + // C=ES, O=Agencia Notarial de Certificacion S.L. Unipersonal - CIF + // B83395988, CN=ANCERT Certificados Notariales + {0x00, 0xAB, 0x44, 0x4A, 0xBD, 0x6B, 0xDB, 0xA3, 0x3D, 0xA8, 0xDE, 0x56, + 0x9A, 0xC4, 0xEC, 0xDE, 0x32, 0x6D, 0x1B, 0xE1, 0xA6, 0x14, 0x42, 0xD5, + 0xEE, 0xC3, 0x97, 0x5A, 0x0C, 0x24, 0x3F, 0x04}, + // C=US, O=Entrust, Inc., OU=See www.entrust.net/legal-terms, OU=(c) 2012 + // Entrust, Inc. - for authorized use only, CN=Entrust Root Certification + // Authority - EC1 + {0x02, 0xED, 0x0E, 0xB2, 0x8C, 0x14, 0xDA, 0x45, 0x16, 0x5C, 0x56, 0x67, + 0x91, 0x70, 0x0D, 0x64, 0x51, 0xD7, 0xFB, 0x56, 0xF0, 0xB2, 0xAB, 0x1D, + 0x3B, 0x8E, 0xB0, 0x70, 0xE5, 0x6E, 0xDF, 0xF5}, + // C=US, O=Wells Fargo, OU=Wells Fargo Certification Authority, CN=Wells + // Fargo Root Certificate Authority + {0x03, 0x45, 0x8B, 0x6A, 0xBE, 0xEC, 0xC2, 0x14, 0x95, 0x3D, 0x97, 0x14, + 0x9A, 0xF4, 0x53, 0x91, 0x69, 0x1D, 0xE9, 0xF9, 0xCD, 0xCC, 0x26, 0x47, + 0x86, 0x3A, 0x3D, 0x67, 0xC9, 0x5C, 0x24, 0x3B}, + // C=US, O=AffirmTrust, CN=AffirmTrust Commercial + {0x03, 0x76, 0xAB, 0x1D, 0x54, 0xC5, 0xF9, 0x80, 0x3C, 0xE4, 0xB2, 0xE2, + 0x01, 0xA0, 0xEE, 0x7E, 0xEF, 0x7B, 0x57, 0xB6, 0x36, 0xE8, 0xA9, 0x3C, + 0x9B, 0x8D, 0x48, 0x60, 0xC9, 0x6F, 0x5F, 0xA7}, + // C=KR, O=Government of Korea, OU=GPKI, CN=Root CA + {0x03, 0x78, 0xB2, 0x02, 0xCC, 0xAB, 0xBA, 0x99, 0xA1, 0x2E, 0x56, 0x9A, + 0x11, 0xA0, 0x77, 0xDB, 0x1E, 0xDB, 0x39, 0x48, 0x20, 0x61, 0xC7, 0x5D, + 0x00, 0x73, 0x05, 0x9D, 0x9A, 0xB5, 0xB5, 0x13}, + // CN=ACEDICOM Root, OU=PKI, O=EDICOM, C=ES + {0x03, 0x95, 0x0F, 0xB4, 0x9A, 0x53, 0x1F, 0x3E, 0x19, 0x91, 0x94, 0x23, + 0x98, 0xDF, 0xA9, 0xE0, 0xEA, 0x32, 0xD7, 0xBA, 0x1C, 0xDD, 0x9B, 0xC8, + 0x5D, 0xB5, 0x7E, 0xD9, 0x40, 0x0B, 0x43, 0x4A}, + // C=ES, CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 + {0x04, 0x04, 0x80, 0x28, 0xBF, 0x1F, 0x28, 0x64, 0xD4, 0x8F, 0x9A, 0xD4, + 0xD8, 0x32, 0x94, 0x36, 0x6A, 0x82, 0x88, 0x56, 0x55, 0x3F, 0x3B, 0x14, + 0x30, 0x3F, 0x90, 0x14, 0x7F, 0x5D, 0x40, 0xEF}, + // C=us, O=U.S. Government, OU=FBCA, CN=Common Policy + {0x04, 0xAC, 0xFB, 0x3B, 0x24, 0x79, 0x3F, 0x30, 0x0F, 0x67, 0xEF, 0x87, + 0xE4, 0x4D, 0xD7, 0x2C, 0xB9, 0xB2, 0x8B, 0x20, 0x4F, 0x38, 0x9A, 0x7C, + 0xD5, 0xAE, 0x28, 0x78, 0x5C, 0x7D, 0x42, 0xCD}, + // C=LT, O=VI Registru Centras - I.k. 124110246, OU=Registru Centro + // Sertifikavimo Centras, CN=VI Registru Centras RCSC (RootCA) + {0x05, 0x36, 0x80, 0x1F, 0xBB, 0x44, 0x3B, 0x3E, 0x90, 0x5F, 0xD6, 0xD7, + 0x0D, 0x8C, 0x81, 0xEB, 0x88, 0x55, 0x1B, 0xE8, 0x06, 0x12, 0x99, 0x11, + 0x0D, 0x2B, 0x4F, 0x82, 0xE6, 0x4C, 0xAD, 0xE1}, + // C=BE, O=Certipost s.a./n.v., CN=Certipost E-Trust Primary Qualified CA + {0x05, 0x8A, 0x40, 0x32, 0x3E, 0xC8, 0xC4, 0x62, 0x62, 0xC3, 0x05, 0x2A, + 0x5D, 0x35, 0x7B, 0x91, 0xAC, 0x24, 0xD3, 0xDA, 0x26, 0x35, 0x1B, 0x3F, + 0xF4, 0x40, 0x7E, 0x99, 0xF7, 0xA4, 0xE9, 0xB4}, + // C=EU, L=Madrid (see current address at + // www.camerfirma.com/address)/serialNumber=A82743287, O=AC Camerfirma S.A., + // CN=Chambers of Commerce Root - 2008 + {0x06, 0x3E, 0x4A, 0xFA, 0xC4, 0x91, 0xDF, 0xD3, 0x32, 0xF3, 0x08, 0x9B, + 0x85, 0x42, 0xE9, 0x46, 0x17, 0xD8, 0x93, 0xD7, 0xFE, 0x94, 0x4E, 0x10, + 0xA7, 0x93, 0x7E, 0xE2, 0x9D, 0x96, 0x93, 0xC0}, + // O=Digital Signature Trust Co., CN=DST Root CA X3 + {0x06, 0x87, 0x26, 0x03, 0x31, 0xA7, 0x24, 0x03, 0xD9, 0x09, 0xF1, 0x05, + 0xE6, 0x9B, 0xCF, 0x0D, 0x32, 0xE1, 0xBD, 0x24, 0x93, 0xFF, 0xC6, 0xD9, + 0x20, 0x6D, 0x11, 0xBC, 0xD6, 0x77, 0x07, 0x39}, + // C=JP, O=LGPKI, OU=Application CA G2 + {0x06, 0xDB, 0x3A, 0xF2, 0xDB, 0x7B, 0xAE, 0xE0, 0x0C, 0x03, 0xB9, 0x57, + 0x82, 0x88, 0xBB, 0xDE, 0x54, 0x1D, 0x90, 0x6E, 0xB0, 0x06, 0x93, 0x27, + 0x41, 0x32, 0x95, 0xFF, 0xB4, 0x86, 0x00, 0x8E}, + // C=IE, O=An Post, OU=Post.Trust Ltd., CN=Post.Trust Root CA + {0x07, 0x45, 0x3D, 0x53, 0x79, 0x3B, 0xF4, 0x18, 0x19, 0xA5, 0x25, 0x1C, + 0x69, 0xF8, 0x8E, 0x2B, 0xB3, 0x44, 0xB5, 0x9C, 0xA8, 0x28, 0xB5, 0xA5, + 0x43, 0x78, 0x15, 0x99, 0xEA, 0xF3, 0xD6, 0x02}, + // C=IL, O=PersonalID Ltd., OU=Certificate Services, CN=PersonalID + // Trustworthy RootCA 2011 + {0x07, 0x5B, 0xFC, 0xCA, 0x2D, 0x55, 0xAE, 0x6E, 0x35, 0x74, 0x2C, 0x32, + 0xAF, 0xD0, 0xCA, 0x8E, 0xA4, 0xC9, 0x58, 0xFE, 0xEF, 0xC2, 0x32, 0x24, + 0x99, 0x95, 0x41, 0xC0, 0x33, 0xD6, 0x9C, 0x8D}, + // C=CN, O=CFCA GT CA + {0x07, 0x71, 0x92, 0x0C, 0x8C, 0xB8, 0x74, 0xD5, 0xC5, 0xA4, 0xDC, 0x0D, + 0x6A, 0x51, 0xA2, 0xD4, 0x95, 0xD3, 0x8C, 0x4D, 0xE2, 0xCD, 0x5B, 0x83, + 0xD2, 0xA0, 0x6F, 0xAA, 0x05, 0x19, 0x35, 0xF6}, + // C=US, O=Equifax, OU=Equifax Secure Certificate Authority + {0x08, 0x29, 0x7A, 0x40, 0x47, 0xDB, 0xA2, 0x36, 0x80, 0xC7, 0x31, 0xDB, + 0x6E, 0x31, 0x76, 0x53, 0xCA, 0x78, 0x48, 0xE1, 0xBE, 0xBD, 0x3A, 0x0B, + 0x01, 0x79, 0xA7, 0x07, 0xF9, 0x2C, 0xF1, 0x78}, + // C=US, O=AffirmTrust, CN=AffirmTrust Networking + {0x0A, 0x81, 0xEC, 0x5A, 0x92, 0x97, 0x77, 0xF1, 0x45, 0x90, 0x4A, 0xF3, + 0x8D, 0x5D, 0x50, 0x9F, 0x66, 0xB5, 0xE2, 0xC5, 0x8F, 0xCD, 0xB5, 0x31, + 0x05, 0x8B, 0x0E, 0x17, 0xF3, 0xF0, 0xB4, 0x1B}, + // C=HU, L=Budapest, O=NetLock Halozatbiztonsagi Kft., OU=Tanusitvanykiadok, + // CN=NetLock Expressz (Class C) Tanusitvanykiado + {0x0B, 0x5E, 0xED, 0x4E, 0x84, 0x64, 0x03, 0xCF, 0x55, 0xE0, 0x65, 0x84, + 0x84, 0x40, 0xED, 0x2A, 0x82, 0x75, 0x8B, 0xF5, 0xB9, 0xAA, 0x1F, 0x25, + 0x3D, 0x46, 0x13, 0xCF, 0xA0, 0x80, 0xFF, 0x3F}, + // C=LT, O=Skaitmeninio sertifikavimo centras, OU=Certification Authority, + // CN=SSC Root CA B + {0x0B, 0x9F, 0x26, 0xDF, 0xCA, 0x68, 0x4C, 0x2C, 0xFC, 0xE2, 0x3E, 0x4E, + 0x4D, 0xD5, 0x67, 0xC8, 0x86, 0xBA, 0x25, 0x9E, 0x1D, 0xB2, 0x67, 0xF9, + 0x80, 0x6F, 0x0C, 0x5A, 0x09, 0x97, 0x11, 0xF2}, + // C=EU, O=AC Camerfirma SA CIF A82743287, OU=http://www.chambersign.org, + // CN=Chambers of Commerce Root + {0x0C, 0x25, 0x8A, 0x12, 0xA5, 0x67, 0x4A, 0xEF, 0x25, 0xF2, 0x8B, 0xA7, + 0xDC, 0xFA, 0xEC, 0xEE, 0xA3, 0x48, 0xE5, 0x41, 0xE6, 0xF5, 0xCC, 0x4E, + 0xE6, 0x3B, 0x71, 0xB3, 0x61, 0x60, 0x6A, 0xC3}, + // C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO + // Certification Authority + {0x0C, 0x2C, 0xD6, 0x3D, 0xF7, 0x80, 0x6F, 0xA3, 0x99, 0xED, 0xE8, 0x09, + 0x11, 0x6B, 0x57, 0x5B, 0xF8, 0x79, 0x89, 0xF0, 0x65, 0x18, 0xF9, 0x80, + 0x8C, 0x86, 0x05, 0x03, 0x17, 0x8B, 0xAF, 0x66}, + // C=NL, O=DigiNotar, CN=DigiNotar Root CA/emailAddress=info@diginotar.nl + {0x0D, 0x13, 0x6E, 0x43, 0x9F, 0x0A, 0xB6, 0xE9, 0x7F, 0x3A, 0x02, 0xA5, + 0x40, 0xDA, 0x9F, 0x06, 0x41, 0xAA, 0x55, 0x4E, 0x1D, 0x66, 0xEA, 0x51, + 0xAE, 0x29, 0x20, 0xD5, 0x1B, 0x2F, 0x72, 0x17}, + // CN=Autoridad de Certificacion Raiz del Estado Venezolano, C=VE, + // L=Caracas, ST=Distrito Capital, O=Sistema Nacional de Certificacion + // Electronica, OU=Superintendencia de Servicios de Certificacion + // Electronica/emailAddress=acraiz@suscerte.gob.ve + {0x0E, 0x88, 0xEB, 0x6E, 0xA2, 0x56, 0xE1, 0x9E, 0xF8, 0xD3, 0xAB, 0xD6, + 0x1A, 0x24, 0xD3, 0x8D, 0xBA, 0xD6, 0x32, 0x81, 0x6D, 0xD9, 0x57, 0x29, + 0x44, 0x27, 0xE4, 0x72, 0x4D, 0x81, 0xA3, 0x86}, + // C=NO, O=Buypass AS-983163327, CN=Buypass Class 2 CA 1 + {0x0F, 0x4E, 0x9C, 0xDD, 0x26, 0x4B, 0x02, 0x55, 0x50, 0xD1, 0x70, 0x80, + 0x63, 0x40, 0x21, 0x4F, 0xE9, 0x44, 0x34, 0xC9, 0xB0, 0x2F, 0x69, 0x7E, + 0xC7, 0x10, 0xFC, 0x5F, 0xEA, 0xFB, 0x5E, 0x38}, + // C=FR, O=Certplus, CN=Class 2 Primary CA + {0x0F, 0x99, 0x3C, 0x8A, 0xEF, 0x97, 0xBA, 0xAF, 0x56, 0x87, 0x14, 0x0E, + 0xD5, 0x9A, 0xD1, 0x82, 0x1B, 0xB4, 0xAF, 0xAC, 0xF0, 0xAA, 0x9A, 0x58, + 0xB5, 0xD5, 0x7A, 0x33, 0x8A, 0x3A, 0xFB, 0xCB}, + // C=JP, O=Japanese Government, OU=GPKI, CN=ApplicationCA2 Root + {0x12, 0x6B, 0xF0, 0x1C, 0x10, 0x94, 0xD2, 0xF0, 0xCA, 0x2E, 0x35, 0x23, + 0x80, 0xB3, 0xC7, 0x24, 0x29, 0x45, 0x46, 0xCC, 0xC6, 0x55, 0x97, 0xBE, + 0xF7, 0xF1, 0x2D, 0x8A, 0x17, 0x1F, 0x19, 0x84}, + // C=si, O=state-institutions, OU=sigen-ca + {0x12, 0xD4, 0x80, 0xC1, 0xA3, 0xC6, 0x64, 0x78, 0x1B, 0x99, 0xD9, 0xDF, + 0x0E, 0x9F, 0xAF, 0x3F, 0x1C, 0xAC, 0xEE, 0x1B, 0x3C, 0x30, 0xC3, 0x12, + 0x3A, 0x33, 0x7A, 0x4A, 0x45, 0x4F, 0xFE, 0xD2}, + // C=EU, L=Madrid (see current address at + // www.camerfirma.com/address)/serialNumber=A82743287, O=AC Camerfirma S.A., + // CN=Global Chambersign Root - 2008 + {0x13, 0x63, 0x35, 0x43, 0x93, 0x34, 0xA7, 0x69, 0x80, 0x16, 0xA0, 0xD3, + 0x24, 0xDE, 0x72, 0x28, 0x4E, 0x07, 0x9D, 0x7B, 0x52, 0x20, 0xBB, 0x8F, + 0xBD, 0x74, 0x78, 0x16, 0xEE, 0xBE, 0xBA, 0xCA}, + // C=US, O=Starfield Technologies, Inc., OU=Starfield Class 2 Certification + // Authority + {0x14, 0x65, 0xFA, 0x20, 0x53, 0x97, 0xB8, 0x76, 0xFA, 0xA6, 0xF0, 0xA9, + 0x95, 0x8E, 0x55, 0x90, 0xE4, 0x0F, 0xCC, 0x7F, 0xAA, 0x4F, 0xB7, 0xC2, + 0xC8, 0x67, 0x75, 0x21, 0xFB, 0x5F, 0xB6, 0x58}, + // C=FR, O=Certplus, CN=Certplus Root CA G1 + {0x15, 0x2A, 0x40, 0x2B, 0xFC, 0xDF, 0x2C, 0xD5, 0x48, 0x05, 0x4D, 0x22, + 0x75, 0xB3, 0x9C, 0x7F, 0xCA, 0x3E, 0xC0, 0x97, 0x80, 0x78, 0xB0, 0xF0, + 0xEA, 0x76, 0xE5, 0x61, 0xA6, 0xC7, 0x43, 0x3E}, + // C=es, O=Servicio de Certificacion del Colegio de Registradores (SCR), + // OU=Certificado Propio, OU=Certificado Raiz, CN=Certificado de la Clave + // Principal/street=Principe de Vergara 72 28006 + // Madrid/emailAddress=scr@registradores.org + {0x15, 0x94, 0xCB, 0x5B, 0x82, 0x6C, 0x31, 0x5D, 0xE3, 0xBC, 0x93, 0x2C, + 0x56, 0x89, 0x5F, 0xF2, 0x3A, 0x3A, 0x98, 0x8B, 0x5D, 0xC1, 0xF0, 0x34, + 0xD2, 0x14, 0xDF, 0xD8, 0x58, 0xD8, 0x9E, 0xE8}, + // C=US, O=Network Solutions L.L.C., CN=Network Solutions Certificate + // Authority + {0x15, 0xF0, 0xBA, 0x00, 0xA3, 0xAC, 0x7A, 0xF3, 0xAC, 0x88, 0x4C, 0x07, + 0x2B, 0x10, 0x11, 0xA0, 0x77, 0xBD, 0x77, 0xC0, 0x97, 0xF4, 0x01, 0x64, + 0xB2, 0xF8, 0x59, 0x8A, 0xBD, 0x83, 0x86, 0x0C}, + // C=IE, O=Baltimore, OU=CyberTrust, CN=Baltimore CyberTrust Root + {0x16, 0xAF, 0x57, 0xA9, 0xF6, 0x76, 0xB0, 0xAB, 0x12, 0x60, 0x95, 0xAA, + 0x5E, 0xBA, 0xDE, 0xF2, 0x2A, 0xB3, 0x11, 0x19, 0xD6, 0x44, 0xAC, 0x95, + 0xCD, 0x4B, 0x93, 0xDB, 0xF3, 0xF2, 0x6A, 0xEB}, + // C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO + // ECC Certification Authority + {0x17, 0x93, 0x92, 0x7A, 0x06, 0x14, 0x54, 0x97, 0x89, 0xAD, 0xCE, 0x2F, + 0x8F, 0x34, 0xF7, 0xF0, 0xB6, 0x6D, 0x0F, 0x3A, 0xE3, 0xA3, 0xB8, 0x4D, + 0x21, 0xEC, 0x15, 0xDB, 0xBA, 0x4F, 0xAD, 0xC7}, + // OU=GlobalSign ECC Root CA - R5, O=GlobalSign, CN=GlobalSign + {0x17, 0x9F, 0xBC, 0x14, 0x8A, 0x3D, 0xD0, 0x0F, 0xD2, 0x4E, 0xA1, 0x34, + 0x58, 0xCC, 0x43, 0xBF, 0xA7, 0xF5, 0x9C, 0x81, 0x82, 0xD7, 0x83, 0xA5, + 0x13, 0xF6, 0xEB, 0xEC, 0x10, 0x0C, 0x89, 0x24}, + // C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 3 + {0x18, 0xF1, 0xFC, 0x7F, 0x20, 0x5D, 0xF8, 0xAD, 0xDD, 0xEB, 0x7F, 0xE0, + 0x07, 0xDD, 0x57, 0xE3, 0xAF, 0x37, 0x5A, 0x9C, 0x4D, 0x8D, 0x73, 0x54, + 0x6B, 0xF4, 0xF1, 0xFE, 0xD1, 0xE1, 0x8D, 0x35}, + // C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO + // Certification Authority + {0x1A, 0x0D, 0x20, 0x44, 0x5D, 0xE5, 0xBA, 0x18, 0x62, 0xD1, 0x9E, 0xF8, + 0x80, 0x85, 0x8C, 0xBC, 0xE5, 0x01, 0x02, 0xB3, 0x6E, 0x8F, 0x0A, 0x04, + 0x0C, 0x3C, 0x69, 0xE7, 0x45, 0x22, 0xFE, 0x6E}, + // C=ZA, ST=Western Cape, L=Somerset West, O=South African Post Office + // Limited, OU=SAPO Trust Centre, CN=SAPO Class 3 Root + // CA/emailAddress=pkiadmin@trustcentre.co.za + {0x1A, 0x25, 0x12, 0xCD, 0xA6, 0x74, 0x4A, 0xBE, 0xA1, 0x14, 0x32, 0xA2, + 0xFD, 0xC9, 0xF8, 0xC0, 0x88, 0xDB, 0x5A, 0x98, 0xC8, 0x9E, 0x13, 0x35, + 0x25, 0x74, 0xCD, 0xE4, 0xD9, 0xE8, 0x0C, 0xDD}, + // C=CN, O=China Internet Network Information Center, CN=China Internet + // Network Information Center EV Certificates Root + {0x1C, 0x01, 0xC6, 0xF4, 0xDB, 0xB2, 0xFE, 0xFC, 0x22, 0x55, 0x8B, 0x2B, + 0xCA, 0x32, 0x56, 0x3F, 0x49, 0x84, 0x4A, 0xCF, 0xC3, 0x2B, 0x7B, 0xE4, + 0xB0, 0xFF, 0x59, 0x9F, 0x9E, 0x8C, 0x7A, 0xF7}, + // C=TN, O=ANCE, OU=Certification & PKI, CN=Agence Nationale de + // Certification Electronique/emailAddress=ance@certification.tn + {0x1D, 0x4F, 0x05, 0x96, 0xFC, 0xA2, 0x61, 0x1D, 0x09, 0xF8, 0x4C, 0x78, + 0xF2, 0xEA, 0x56, 0x5E, 0xF2, 0xEA, 0xB9, 0xCF, 0xC2, 0x72, 0xA1, 0x71, + 0x8B, 0xD3, 0x36, 0xE6, 0xE0, 0xAE, 0x02, 0x1A}, + // C=FR, O=ANSSI, OU=0002 130007669, CN=IGC/A AC racine Etat francais + {0x1E, 0x1A, 0x69, 0x84, 0xB4, 0xE7, 0x6B, 0xD7, 0x09, 0xAE, 0xE3, 0xE9, + 0xC9, 0xCF, 0x31, 0x18, 0xEA, 0xC0, 0x96, 0xDA, 0xB9, 0xCC, 0x20, 0xDC, + 0x25, 0xFA, 0xAB, 0x67, 0x29, 0x7E, 0x96, 0x5A}, + // C=CH, O=SwissSign AG, CN=SwissSign Silver Root CA - G3 + {0x1E, 0x49, 0xAC, 0x5D, 0xC6, 0x9E, 0x86, 0xD0, 0x56, 0x5D, 0xA2, 0xC1, + 0x30, 0x5C, 0x41, 0x93, 0x30, 0xB0, 0xB7, 0x81, 0xBF, 0xEC, 0x50, 0xE5, + 0x4A, 0x1B, 0x35, 0xAF, 0x7F, 0xDD, 0xD5, 0x01}, + // C=ch, O=Swisscom, OU=Digital Certificate Services, CN=Swisscom Root CA 1 + {0x21, 0xDB, 0x20, 0x12, 0x36, 0x60, 0xBB, 0x2E, 0xD4, 0x18, 0x20, 0x5D, + 0xA1, 0x1E, 0xE7, 0xA8, 0x5A, 0x65, 0xE2, 0xBC, 0x6E, 0x55, 0xB5, 0xAF, + 0x7E, 0x78, 0x99, 0xC8, 0xA2, 0x66, 0xD9, 0x2E}, + // C=US, O=Cisco Systems, CN=Cisco RXC-R2 + {0x22, 0x9C, 0xCC, 0x19, 0x6D, 0x32, 0xC9, 0x84, 0x21, 0xCC, 0x11, 0x9E, + 0x78, 0x48, 0x6E, 0xEB, 0xEF, 0x60, 0x3A, 0xEC, 0xD5, 0x25, 0xC6, 0xB8, + 0x8B, 0x47, 0xAB, 0xB7, 0x40, 0x69, 0x2B, 0x96}, + // C=US, O=Digital Signature Trust Co., OU=DST-Entrust GTI CA + {0x22, 0xE0, 0xD1, 0x1D, 0xC9, 0x20, 0x7E, 0x16, 0xC9, 0x2B, 0x2E, 0xE1, + 0x8C, 0xFD, 0xB2, 0xC2, 0xE9, 0x40, 0x62, 0x68, 0x47, 0x92, 0x1F, 0xC5, + 0x28, 0xCE, 0xDD, 0x2F, 0x79, 0x32, 0xF7, 0x14}, + // C=ES, O=IZENPE S.A., CN=Izenpe.com + {0x23, 0x80, 0x42, 0x03, 0xCA, 0x45, 0xD8, 0xCD, 0xE7, 0x16, 0xB8, 0xC1, + 0x3B, 0xF3, 0xB4, 0x48, 0x45, 0x7F, 0xA0, 0x6C, 0xC1, 0x02, 0x50, 0x99, + 0x7F, 0xA0, 0x14, 0x58, 0x31, 0x7C, 0x41, 0xE5}, + // C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2008 VeriSign, + // Inc. - For authorized use only, CN=VeriSign Universal Root Certification + // Authority + {0x23, 0x99, 0x56, 0x11, 0x27, 0xA5, 0x71, 0x25, 0xDE, 0x8C, 0xEF, 0xEA, + 0x61, 0x0D, 0xDF, 0x2F, 0xA0, 0x78, 0xB5, 0xC8, 0x06, 0x7F, 0x4E, 0x82, + 0x82, 0x90, 0xBF, 0xB8, 0x60, 0xE8, 0x4B, 0x3C}, + // C=US, ST=Utah, L=Salt Lake City, O=Xcert EZ by DST, CN=Xcert EZ by + // DST/emailAddress=ca@digsigtrust.com + {0x26, 0x02, 0xD2, 0x1E, 0x81, 0x27, 0x7A, 0x83, 0xF6, 0x04, 0x81, 0x28, + 0xF6, 0x1D, 0x79, 0x4A, 0x06, 0xF4, 0x74, 0xE1, 0xF7, 0x5E, 0x49, 0x74, + 0x0A, 0x81, 0x7C, 0x26, 0x66, 0xF6, 0x22, 0x11}, + // CN=ComSign Global Root CA, O=ComSign Ltd., C=IL + {0x26, 0x05, 0x87, 0x5A, 0xFC, 0xC1, 0x76, 0xB2, 0xD6, 0x6D, 0xD6, 0x6A, + 0x99, 0x5D, 0x7F, 0x8D, 0x5E, 0xBB, 0x86, 0xCE, 0x12, 0x0D, 0x0E, 0x7E, + 0x9E, 0x7C, 0x6E, 0xF2, 0x94, 0xA2, 0x7D, 0x4C}, + // C=FR, O=OpenTrust, CN=OpenTrust Root CA G2 + {0x27, 0x99, 0x58, 0x29, 0xFE, 0x6A, 0x75, 0x15, 0xC1, 0xBF, 0xE8, 0x48, + 0xF9, 0xC4, 0x76, 0x1D, 0xB1, 0x6C, 0x22, 0x59, 0x29, 0x25, 0x7B, 0xF4, + 0x0D, 0x08, 0x94, 0xF2, 0x9E, 0xA8, 0xBA, 0xF2}, + // C=DE, O=TC TrustCenter GmbH, OU=TC TrustCenter Universal CA, CN=TC + // TrustCenter Universal CA II + {0x28, 0x34, 0x99, 0x1C, 0xF6, 0x77, 0x46, 0x6D, 0x22, 0xBA, 0xAC, 0x3B, + 0x00, 0x55, 0xE5, 0xB9, 0x11, 0xD9, 0xA9, 0xE5, 0x5F, 0x5B, 0x85, 0xBA, + 0x02, 0xDC, 0x56, 0x67, 0x82, 0xC3, 0x0E, 0x8A}, + // C=US, O=RSA Data Security, Inc., OU=Secure Server Certification Authority + {0x29, 0x30, 0xBD, 0x09, 0xA0, 0x71, 0x26, 0xBD, 0xC1, 0x72, 0x88, 0xD4, + 0xF2, 0xAD, 0x84, 0x64, 0x5E, 0xC9, 0x48, 0x60, 0x79, 0x07, 0xA9, 0x7B, + 0x5E, 0xD0, 0xB0, 0xB0, 0x58, 0x79, 0xEF, 0x69}, + // C=NL, O=DigiNotar, CN=DigiNotar Root CA G2/emailAddress=info@diginotar.nl + {0x29, 0x4F, 0x55, 0xEF, 0x3B, 0xD7, 0x24, 0x4C, 0x6F, 0xF8, 0xA6, 0x8A, + 0xB7, 0x97, 0xE9, 0x18, 0x6E, 0xC2, 0x75, 0x82, 0x75, 0x1A, 0x79, 0x15, + 0x15, 0xE3, 0x29, 0x2E, 0x48, 0x37, 0x2D, 0x61}, + // C=FR, O=Certinomis, OU=0002 433998903, CN=Certinomis - Root CA + {0x2A, 0x99, 0xF5, 0xBC, 0x11, 0x74, 0xB7, 0x3C, 0xBB, 0x1D, 0x62, 0x08, + 0x84, 0xE0, 0x1C, 0x34, 0xE5, 0x1C, 0xCB, 0x39, 0x78, 0xDA, 0x12, 0x5F, + 0x0E, 0x33, 0x26, 0x88, 0x83, 0xBF, 0x41, 0x58}, + // C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, Inc., + // CN=Starfield Root Certificate Authority - G2 + {0x2C, 0xE1, 0xCB, 0x0B, 0xF9, 0xD2, 0xF9, 0xE1, 0x02, 0x99, 0x3F, 0xBE, + 0x21, 0x51, 0x52, 0xC3, 0xB2, 0xDD, 0x0C, 0xAB, 0xDE, 0x1C, 0x68, 0xE5, + 0x31, 0x9B, 0x83, 0x91, 0x54, 0xDB, 0xB7, 0xF5}, + // C=JP, O=Japanese Government, OU=ApplicationCA + {0x2D, 0x47, 0x43, 0x7D, 0xE1, 0x79, 0x51, 0x21, 0x5A, 0x12, 0xF3, 0xC5, + 0x8E, 0x51, 0xC7, 0x29, 0xA5, 0x80, 0x26, 0xEF, 0x1F, 0xCC, 0x0A, 0x5F, + 0xB3, 0xD9, 0xDC, 0x01, 0x2F, 0x60, 0x0D, 0x19}, + // C=IN, O=India PKI, CN=CCA India 2011 + {0x2D, 0x66, 0xA7, 0x02, 0xAE, 0x81, 0xBA, 0x03, 0xAF, 0x8C, 0xFF, 0x55, + 0xAB, 0x31, 0x8A, 0xFA, 0x91, 0x90, 0x39, 0xD9, 0xF3, 0x1B, 0x4D, 0x64, + 0x38, 0x86, 0x80, 0xF8, 0x13, 0x11, 0xB6, 0x5A}, + // C=AT, ST=Austria, L=Vienna, O=ARGE DATEN - Austrian Society for Data + // Protection, OU=A-CERT Certification Service, CN=A-CERT + // ADVANCED/emailAddress=info@a-cert.at + {0x2D, 0xC6, 0x2C, 0x3F, 0x6C, 0x0C, 0xC9, 0x02, 0x0B, 0xBA, 0x77, 0xE1, + 0xC5, 0x11, 0x51, 0x10, 0x24, 0xB9, 0x43, 0xEE, 0x59, 0x88, 0x56, 0xDA, + 0x5A, 0x22, 0xE2, 0x22, 0xB7, 0x27, 0x7A, 0x20}, + // C=AT, O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH, + // OU=A-Trust-Root-05, CN=A-Trust-Root-05 + {0x2D, 0xDE, 0x9D, 0x0C, 0x0A, 0x90, 0xE7, 0xB3, 0x2B, 0x5A, 0xBC, 0x01, + 0xF4, 0x17, 0x99, 0xD4, 0x2E, 0x95, 0xA1, 0xE3, 0xC3, 0x1C, 0x3B, 0x39, + 0x37, 0x3B, 0xB8, 0x14, 0x1E, 0xA5, 0x44, 0x71}, + // C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE + // CyberTrust Root + {0x2D, 0xFC, 0xBA, 0xCA, 0xDF, 0x22, 0xA6, 0xFF, 0x10, 0x7A, 0x51, 0xFD, + 0x3E, 0x8B, 0x9E, 0x17, 0x85, 0x80, 0x28, 0x87, 0x9B, 0x13, 0xF7, 0xC3, + 0xB5, 0x7B, 0x3E, 0x1B, 0xD2, 0x31, 0x58, 0x09}, + // C=US, O=Equifax Secure, OU=Equifax Secure eBusiness CA-2 + {0x2F, 0x27, 0x4E, 0x48, 0xAB, 0xA4, 0xAC, 0x7B, 0x76, 0x59, 0x33, 0x10, + 0x17, 0x75, 0x50, 0x6D, 0xC3, 0x0E, 0xE3, 0x8E, 0xF6, 0xAC, 0xD5, 0xC0, + 0x49, 0x32, 0xCF, 0xE0, 0x41, 0x23, 0x42, 0x20}, + // C=DE, O=TC TrustCenter GmbH, OU=TC TrustCenter Universal CA, CN=TC + // TrustCenter Universal CA III + {0x30, 0x9B, 0x4A, 0x87, 0xF6, 0xCA, 0x56, 0xC9, 0x31, 0x69, 0xAA, 0xA9, + 0x9C, 0x6D, 0x98, 0x88, 0x54, 0xD7, 0x89, 0x2B, 0xD5, 0x43, 0x7E, 0x2D, + 0x07, 0xB2, 0x9C, 0xBE, 0xDA, 0x55, 0xD3, 0x5D}, + // C=US, O=IdenTrust, CN=IdenTrust Public Sector Root CA 1 + {0x30, 0xD0, 0x89, 0x5A, 0x9A, 0x44, 0x8A, 0x26, 0x20, 0x91, 0x63, 0x55, + 0x22, 0xD1, 0xF5, 0x20, 0x10, 0xB5, 0x86, 0x7A, 0xCA, 0xE1, 0x2C, 0x78, + 0xEF, 0x95, 0x8F, 0xD4, 0xF4, 0x38, 0x9F, 0x2F}, + // C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G3 + {0x31, 0xAD, 0x66, 0x48, 0xF8, 0x10, 0x41, 0x38, 0xC7, 0x38, 0xF3, 0x9E, + 0xA4, 0x32, 0x01, 0x33, 0x39, 0x3E, 0x3A, 0x18, 0xCC, 0x02, 0x29, 0x6E, + 0xF9, 0x7C, 0x2A, 0xC9, 0xEF, 0x67, 0x31, 0xD0}, + // C=BR, ST=Rio de Janeiro, L=Rio de Janeiro, O=Certisign Certificadora + // Digital Ltda., OU=Certisign Autoridade Certificadora AC3S + {0x31, 0xEA, 0xCE, 0x9B, 0x4C, 0x9C, 0x71, 0x73, 0x4A, 0x18, 0x56, 0x80, + 0xBC, 0x24, 0x86, 0x6C, 0xA6, 0xCB, 0xD8, 0x2B, 0x3C, 0xB6, 0x1B, 0xCC, + 0x87, 0x06, 0x26, 0x1B, 0x59, 0xCE, 0x10, 0x73}, + // C=DE, O=TC TrustCenter GmbH, OU=TC TrustCenter Class 4 CA, CN=TC + // TrustCenter Class 4 CA II + {0x32, 0x66, 0x96, 0x7E, 0x59, 0xCD, 0x68, 0x00, 0x8D, 0x9D, 0xD3, 0x20, + 0x81, 0x11, 0x85, 0xC7, 0x04, 0x20, 0x5E, 0x8D, 0x95, 0xFD, 0xD8, 0x4F, + 0x1C, 0x7B, 0x31, 0x1E, 0x67, 0x04, 0xFC, 0x32}, + // C=HU, L=Budapest, O=Microsec Ltd., OU=e-Szigno CA, CN=Microsec e-Szigno + // Root CA + {0x32, 0x7A, 0x3D, 0x76, 0x1A, 0xBA, 0xDE, 0xA0, 0x34, 0xEB, 0x99, 0x84, + 0x06, 0x27, 0x5C, 0xB1, 0xA4, 0x77, 0x6E, 0xFD, 0xAE, 0x2F, 0xDF, 0x6D, + 0x01, 0x68, 0xEA, 0x1C, 0x4F, 0x55, 0x67, 0xD0}, + // C=SA, O=National Center for Digital Certification, OU=Saudi National Root + // CA + {0x34, 0xBB, 0x34, 0xE1, 0x4F, 0xAE, 0xD0, 0xD3, 0x39, 0x2F, 0x2F, 0xC4, + 0x41, 0xC0, 0xEC, 0xD5, 0xFD, 0x88, 0xAD, 0x88, 0x11, 0x8D, 0xF2, 0xD1, + 0xBA, 0x76, 0xCD, 0xEC, 0x1E, 0xEA, 0x10, 0xB8}, + // CN=EBG Elektronik Sertifika Hizmet + // Sa\xC4\x9Flay\xC4\xB1c\xC4\xB1s\xC4\xB1, O=EBG Bili\xC5\x9Fim + // Teknolojileri ve Hizmetleri A.\xC5\x9E., C=TR + {0x35, 0xAE, 0x5B, 0xDD, 0xD8, 0xF7, 0xAE, 0x63, 0x5C, 0xFF, 0xBA, 0x56, + 0x82, 0xA8, 0xF0, 0x0B, 0x95, 0xF4, 0x84, 0x62, 0xC7, 0x10, 0x8E, 0xE9, + 0xA0, 0xE5, 0x29, 0x2B, 0x07, 0x4A, 0xAF, 0xB2}, + // C=ES, O=Agencia Notarial de Certificacion S.L. Unipersonal - CIF + // B83395988, CN=ANCERT Corporaciones de Derecho Publico + {0x36, 0x54, 0x4D, 0x2F, 0xCE, 0x03, 0xC6, 0xC7, 0x2B, 0x70, 0xEB, 0x1A, + 0x80, 0x64, 0x26, 0x4D, 0xC1, 0x51, 0x17, 0x68, 0xC2, 0xD8, 0xF7, 0x6A, + 0x8B, 0x9F, 0x1F, 0x2B, 0xBD, 0x15, 0x3B, 0x7D}, + // C=US, O=GeoTrust Inc., CN=GeoTrust Primary Certification Authority + {0x37, 0xD5, 0x10, 0x06, 0xC5, 0x12, 0xEA, 0xAB, 0x62, 0x64, 0x21, 0xF1, + 0xEC, 0x8C, 0x92, 0x01, 0x3F, 0xC5, 0xF8, 0x2A, 0xE9, 0x8E, 0xE5, 0x33, + 0xEB, 0x46, 0x19, 0xB8, 0xDE, 0xB4, 0xD0, 0x6C}, + // C=HU, L=Budapest, O=NetLock Halozatbiztonsagi Kft., OU=Tanusitvanykiadok, + // CN=NetLock Uzleti (Class B) Tanusitvanykiado + {0x39, 0xDF, 0x7B, 0x68, 0x2B, 0x7B, 0x93, 0x8F, 0x84, 0x71, 0x54, 0x81, + 0xCC, 0xDE, 0x8D, 0x60, 0xD8, 0xF2, 0x2E, 0xC5, 0x98, 0x87, 0x7D, 0x0A, + 0xAA, 0xC1, 0x2B, 0x59, 0x18, 0x2B, 0x03, 0x12}, + // C=IE, O=An Post, OU=Post.Trust Ltd., CN=Post.Trust Root CA + {0x39, 0xF6, 0x03, 0x3C, 0xA6, 0x64, 0xCE, 0xDB, 0x21, 0x67, 0x44, 0xD3, + 0xC6, 0xF2, 0xB2, 0xE8, 0xE3, 0xCE, 0xBD, 0x68, 0x69, 0xF7, 0xDF, 0xF4, + 0x7E, 0x0D, 0xB9, 0x1A, 0x79, 0xC4, 0x16, 0xF8}, + // C=CH, O=SwissSign AG, CN=SwissSign Platinum CA - G2 + {0x3B, 0x22, 0x2E, 0x56, 0x67, 0x11, 0xE9, 0x92, 0x30, 0x0D, 0xC0, 0xB1, + 0x5A, 0xB9, 0x47, 0x3D, 0xAF, 0xDE, 0xF8, 0xC8, 0x4D, 0x0C, 0xEF, 0x7D, + 0x33, 0x17, 0xB4, 0xC1, 0x82, 0x1D, 0x14, 0x36}, + // C=NL, O=Staat der Nederlanden, CN=Staat der Nederlanden Root CA - G3 + {0x3C, 0x4F, 0xB0, 0xB9, 0x5A, 0xB8, 0xB3, 0x00, 0x32, 0xF4, 0x32, 0xB8, + 0x6F, 0x53, 0x5F, 0xE1, 0x72, 0xC1, 0x85, 0xD0, 0xFD, 0x39, 0x86, 0x58, + 0x37, 0xCF, 0x36, 0x18, 0x7F, 0xA6, 0xF4, 0x28}, + // C=HU, L=Budapest, O=Microsec Ltd., CN=Microsec e-Szigno Root CA + // 2009/emailAddress=info@e-szigno.hu + {0x3C, 0x5F, 0x81, 0xFE, 0xA5, 0xFA, 0xB8, 0x2C, 0x64, 0xBF, 0xA2, 0xEA, + 0xEC, 0xAF, 0xCD, 0xE8, 0xE0, 0x77, 0xFC, 0x86, 0x20, 0xA7, 0xCA, 0xE5, + 0x37, 0x16, 0x3D, 0xF3, 0x6E, 0xDB, 0xF3, 0x78}, + // CN=ComSign Advanced Security CA + {0x3C, 0xCC, 0x3C, 0xCF, 0xE4, 0x54, 0x96, 0xD0, 0x7B, 0x62, 0x0D, 0xBF, + 0x13, 0x28, 0xE8, 0xA1, 0x49, 0x00, 0x18, 0xF4, 0x86, 0x33, 0xC8, 0xA2, + 0x8A, 0x99, 0x5C, 0xA6, 0x04, 0x08, 0xB0, 0xBE}, + // C=AT, O=A-Trust Ges. f\xFCr Sicherheitssysteme im elektr. Datenverkehr + // GmbH, OU=A-Trust-Qual-01, CN=A-Trust-Qual-01 + {0x3D, 0xEA, 0xE6, 0xAE, 0x97, 0x52, 0x84, 0xE0, 0xE6, 0xFA, 0x2E, 0xB7, + 0x6C, 0xE4, 0x6E, 0x12, 0x44, 0x18, 0x69, 0xA2, 0xA7, 0xD4, 0xE6, 0x7D, + 0xC7, 0xAB, 0x86, 0x64, 0xFE, 0xFD, 0xBB, 0xB0}, + // C=EE, O=AS Sertifitseerimiskeskus, CN=EE Certification Centre Root + // CA/emailAddress=pki@sk.ee + {0x3E, 0x84, 0xBA, 0x43, 0x42, 0x90, 0x85, 0x16, 0xE7, 0x75, 0x73, 0xC0, + 0x99, 0x2F, 0x09, 0x79, 0xCA, 0x08, 0x4E, 0x46, 0x85, 0x68, 0x1F, 0xF1, + 0x95, 0xCC, 0xBA, 0x8A, 0x22, 0x9B, 0x8A, 0x76}, + // C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root CA + {0x3E, 0x90, 0x99, 0xB5, 0x01, 0x5E, 0x8F, 0x48, 0x6C, 0x00, 0xBC, 0xEA, + 0x9D, 0x11, 0x1E, 0xE7, 0x21, 0xFA, 0xBA, 0x35, 0x5A, 0x89, 0xBC, 0xF1, + 0xDF, 0x69, 0x56, 0x1E, 0x3D, 0xC6, 0x32, 0x5C}, + // C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=Trusted + // Certificate Services + {0x3F, 0x06, 0xE5, 0x56, 0x81, 0xD4, 0x96, 0xF5, 0xBE, 0x16, 0x9E, 0xB5, + 0x38, 0x9F, 0x9F, 0x2B, 0x8F, 0xF6, 0x1E, 0x17, 0x08, 0xDF, 0x68, 0x81, + 0x72, 0x48, 0x49, 0xCD, 0x5D, 0x27, 0xCB, 0x69}, + // C=GB, O=Trustis Limited, OU=Trustis EVS Root CA + {0x3F, 0x9D, 0xA4, 0x74, 0x4E, 0xC9, 0x67, 0x6C, 0xD3, 0x8B, 0x53, 0x0E, + 0x50, 0x0A, 0x46, 0x3F, 0xBC, 0xB1, 0x81, 0x65, 0x97, 0x7F, 0xF0, 0xDA, + 0x6D, 0x59, 0x93, 0xC3, 0xFE, 0x5F, 0xAB, 0x7C}, + // C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, + // OU=Certification Services Division, CN=Thawte Premium Server + // CA/emailAddress=premium-server@thawte.com + {0x3F, 0x9F, 0x27, 0xD5, 0x83, 0x20, 0x4B, 0x9E, 0x09, 0xC8, 0xA3, 0xD2, + 0x06, 0x6C, 0x4B, 0x57, 0xD3, 0xA2, 0x47, 0x9C, 0x36, 0x93, 0x65, 0x08, + 0x80, 0x50, 0x56, 0x98, 0x10, 0x5D, 0xBC, 0xE9}, + // C=KR, O=Government of Korea, OU=GPKI, CN=GPKIRootCA1 + {0x40, 0x7C, 0x27, 0x6B, 0xEA, 0xD2, 0xE4, 0xAF, 0x06, 0x61, 0xEF, 0x66, + 0x97, 0x34, 0x1D, 0xEC, 0x0A, 0x1F, 0x94, 0x34, 0xE4, 0xEA, 0xFB, 0x2D, + 0x3D, 0x32, 0xA9, 0x05, 0x49, 0xD9, 0xDE, 0x4A}, + // C=NL, O=Digidentity B.V., CN=Digidentity L3 Root CA - G2 + {0x41, 0x7D, 0xCF, 0x31, 0x80, 0xF4, 0xED, 0x1A, 0x37, 0x47, 0xAC, 0xF1, + 0x17, 0x93, 0x16, 0xCD, 0x48, 0xCB, 0x05, 0xC5, 0x78, 0x84, 0x35, 0x16, + 0x8A, 0xED, 0x98, 0xC9, 0x8C, 0xDC, 0xB6, 0x15}, + // C=CH, O=WISeKey, OU=Copyright (c) 2005, OU=OISTE Foundation Endorsed, + // CN=OISTE WISeKey Global Root GA CA + {0x41, 0xC9, 0x23, 0x86, 0x6A, 0xB4, 0xCA, 0xD6, 0xB7, 0xAD, 0x57, 0x80, + 0x81, 0x58, 0x2E, 0x02, 0x07, 0x97, 0xA6, 0xCB, 0xDF, 0x4F, 0xFF, 0x78, + 0xCE, 0x83, 0x96, 0xB3, 0x89, 0x37, 0xD7, 0xF5}, + // C=US, O=SecureTrust Corporation, CN=Secure Global CA + {0x42, 0x00, 0xF5, 0x04, 0x3A, 0xC8, 0x59, 0x0E, 0xBB, 0x52, 0x7D, 0x20, + 0x9E, 0xD1, 0x50, 0x30, 0x29, 0xFB, 0xCB, 0xD4, 0x1C, 0xA1, 0xB5, 0x06, + 0xEC, 0x27, 0xF1, 0x5A, 0xDE, 0x7D, 0xAC, 0x69}, + // C=FR, O=KEYNECTIS, OU=ROOT, CN=KEYNECTIS ROOT CA + {0x42, 0x10, 0xF1, 0x99, 0x49, 0x9A, 0x9A, 0xC3, 0x3C, 0x8D, 0xE0, 0x2B, + 0xA6, 0xDB, 0xAA, 0x14, 0x40, 0x8B, 0xDD, 0x8A, 0x6E, 0x32, 0x46, 0x89, + 0xC1, 0x92, 0x2D, 0x06, 0x97, 0x15, 0xA3, 0x32}, + // C=FR, O=Certeurope, OU=0002 434202180, CN=Certeurope Root CA 2 + {0x42, 0x14, 0x3A, 0x51, 0x1A, 0x3A, 0xFC, 0xDD, 0x80, 0xD5, 0x55, 0xDE, + 0xBB, 0x41, 0x91, 0xEC, 0x6B, 0xB2, 0x85, 0xEE, 0x66, 0xE6, 0x2E, 0xC6, + 0x57, 0xED, 0x20, 0xAD, 0xF7, 0xD5, 0x5F, 0xAA}, + // C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA + {0x43, 0x48, 0xA0, 0xE9, 0x44, 0x4C, 0x78, 0xCB, 0x26, 0x5E, 0x05, 0x8D, + 0x5E, 0x89, 0x44, 0xB4, 0xD8, 0x4F, 0x96, 0x62, 0xBD, 0x26, 0xDB, 0x25, + 0x7F, 0x89, 0x34, 0xA4, 0x43, 0xC7, 0x01, 0x61}, + // C=US, O=Entrust, Inc., OU=See www.entrust.net/legal-terms, OU=(c) 2009 + // Entrust, Inc. - for authorized use only, CN=Entrust Root Certification + // Authority - G2 + {0x43, 0xDF, 0x57, 0x74, 0xB0, 0x3E, 0x7F, 0xEF, 0x5F, 0xE4, 0x0D, 0x93, + 0x1A, 0x7B, 0xED, 0xF1, 0xBB, 0x2E, 0x6B, 0x42, 0x73, 0x8C, 0x4E, 0x6D, + 0x38, 0x41, 0x10, 0x3D, 0x3A, 0xA7, 0xF3, 0x39}, + // CN=T\xC3\x9CRKTRUST Elektronik Sertifika Hizmet + // Sa\xC4\x9Flay\xC4\xB1c\xC4\xB1s\xC4\xB1, C=TR, L=ANKARA, O=(c) 2005 + // T\xC3\x9CRKTRUST Bilgi \xC4\xB0leti\xC5\x9Fim ve Bili\xC5\x9Fim + // G\xC3\xBCvenli\xC4\x9Fi Hizmetleri A.\xC5\x9E. + {0x44, 0x04, 0xE3, 0x3B, 0x5E, 0x14, 0x0D, 0xCF, 0x99, 0x80, 0x51, 0xFD, + 0xFC, 0x80, 0x28, 0xC7, 0xC8, 0x16, 0x15, 0xC5, 0xEE, 0x73, 0x7B, 0x11, + 0x1B, 0x58, 0x82, 0x33, 0xA9, 0xB5, 0x35, 0xA0}, + // C=US, O=VeriSign, Inc., OU=Class 4 Public Primary Certification Authority + // - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign + // Trust Network + {0x44, 0x64, 0x0A, 0x0A, 0x0E, 0x4D, 0x00, 0x0F, 0xBD, 0x57, 0x4D, 0x2B, + 0x8A, 0x07, 0xBD, 0xB4, 0xD1, 0xDF, 0xED, 0x3B, 0x45, 0xBA, 0xAB, 0xA7, + 0x6F, 0x78, 0x57, 0x78, 0xC7, 0x01, 0x19, 0x61}, + // C=GR, L=Athens, O=Hellenic Academic and Research Institutions Cert. + // Authority, CN=Hellenic Academic and Research Institutions ECC RootCA 2015 + {0x44, 0xB5, 0x45, 0xAA, 0x8A, 0x25, 0xE6, 0x5A, 0x73, 0xCA, 0x15, 0xDC, + 0x27, 0xFC, 0x36, 0xD2, 0x4C, 0x1C, 0xB9, 0x95, 0x3A, 0x06, 0x65, 0x39, + 0xB1, 0x15, 0x82, 0xDC, 0x48, 0x7B, 0x48, 0x33}, + // C=US, ST=Arizona, L=Scottsdale, O=GoDaddy.com, Inc., CN=Go Daddy Root + // Certificate Authority - G2 + {0x45, 0x14, 0x0B, 0x32, 0x47, 0xEB, 0x9C, 0xC8, 0xC5, 0xB4, 0xF0, 0xD7, + 0xB5, 0x30, 0x91, 0xF7, 0x32, 0x92, 0x08, 0x9E, 0x6E, 0x5A, 0x63, 0xE2, + 0x74, 0x9D, 0xD3, 0xAC, 0xA9, 0x19, 0x8E, 0xDA}, + // C=UY, O=ADMINISTRACION NACIONAL DE CORREOS, OU=SERVICIOS ELECTRONICOS, + // CN=Correo Uruguayo - Root CA + {0x46, 0x27, 0x32, 0x85, 0x61, 0x5D, 0x96, 0xE5, 0x2D, 0xA9, 0xFC, 0x2E, + 0xD8, 0xC0, 0x36, 0xF1, 0x0A, 0xF3, 0xD9, 0xF6, 0x28, 0x0F, 0x8D, 0x28, + 0x87, 0x06, 0xC5, 0x2B, 0x20, 0x11, 0xB4, 0xDA}, + // C=PT, O=SCEE, CN=ECRaizEstado + {0x48, 0x8E, 0x13, 0x4F, 0x30, 0xC5, 0xDB, 0x56, 0xB7, 0x64, 0x73, 0xE6, + 0x08, 0x08, 0x68, 0x42, 0xBF, 0x21, 0xAF, 0x8A, 0xB3, 0xCD, 0x7A, 0xC6, + 0x7E, 0xBD, 0xF1, 0x25, 0xD5, 0x31, 0x83, 0x4E}, + // C=PA, ST=Panama, L=Panama City, O=TrustCor Systems S. de R.L., + // OU=TrustCor Certificate Authority, CN=TrustCor RootCert CA-1 + {0x48, 0x8F, 0xCA, 0x18, 0x9E, 0xAA, 0xDF, 0x54, 0xA3, 0xF9, 0x20, 0xED, + 0x39, 0xE5, 0x87, 0x18, 0x3B, 0xA5, 0x12, 0x23, 0x29, 0x99, 0xFA, 0xE3, + 0xE4, 0xA2, 0x85, 0xFE, 0x98, 0xE2, 0x98, 0xD1}, + // C=DK, O=TDC Internet, OU=TDC Internet Root CA + {0x48, 0x98, 0xC6, 0x88, 0x8C, 0x0C, 0xFF, 0xB0, 0xD3, 0xE3, 0x1A, 0xCA, + 0x8A, 0x37, 0xD4, 0xE3, 0x51, 0x5F, 0xF7, 0x46, 0xD0, 0x26, 0x35, 0xD8, + 0x66, 0x46, 0xCF, 0xA0, 0xA3, 0x18, 0x5A, 0xE7}, + // C=TR, L=Ankara, O=T\xC3\x9CRKTRUST Bilgi \xC4\xB0leti\xC5\x9Fim ve + // Bili\xC5\x9Fim G\xC3\xBCvenli\xC4\x9Fi Hizmetleri A.\xC5\x9E., + // CN=T\xC3\x9CRKTRUST Elektronik Sertifika Hizmet + // Sa\xC4\x9Flay\xC4\xB1c\xC4\xB1s\xC4\xB1 H5 + {0x49, 0x35, 0x1B, 0x90, 0x34, 0x44, 0xC1, 0x85, 0xCC, 0xDC, 0x5C, 0x69, + 0x3D, 0x24, 0xD8, 0x55, 0x5C, 0xB2, 0x08, 0xD6, 0xA8, 0x14, 0x13, 0x07, + 0x69, 0x9F, 0x4A, 0xF0, 0x63, 0x19, 0x9D, 0x78}, + // C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., + // OU=National Retail Federation, CN=DST (NRF) + // RootCA/emailAddress=ca@digsigtrust.com + {0x49, 0xC8, 0x17, 0x5A, 0x98, 0x15, 0xE0, 0x8B, 0xEF, 0x12, 0x9A, 0x92, + 0x9D, 0xE1, 0xBA, 0xCA, 0xD0, 0x4E, 0x4D, 0xB6, 0x7A, 0x8C, 0x83, 0x92, + 0x93, 0x95, 0x3E, 0x50, 0x31, 0xC8, 0x1C, 0xA0}, + // C=DE, O=D-Trust GmbH, CN=D-TRUST Root Class 3 CA 2 2009 + {0x49, 0xE7, 0xA4, 0x42, 0xAC, 0xF0, 0xEA, 0x62, 0x87, 0x05, 0x00, 0x54, + 0xB5, 0x25, 0x64, 0xB6, 0x50, 0xE4, 0xF4, 0x9E, 0x42, 0xE3, 0x48, 0xD6, + 0xAA, 0x38, 0xE0, 0x39, 0xE9, 0x57, 0xB1, 0xC1}, + // C=US, O=Digital Signature Trust Co., CN=Baltimore EZ by + // DST/mail=ca@digsigtrust.com + {0x49, 0xF7, 0x4F, 0x82, 0x4F, 0x2E, 0x05, 0x9F, 0xE9, 0x9C, 0x98, 0xAF, + 0x32, 0x19, 0xEC, 0x0D, 0x9A, 0x00, 0x4D, 0x1B, 0x64, 0xDD, 0x2F, 0xD1, + 0x45, 0x26, 0x16, 0x31, 0x8A, 0xB8, 0x06, 0xC0}, + // C=US, O=thawte, Inc., OU=Certification Services Division, OU=(c) 2008 + // thawte, Inc. - For authorized use only, CN=thawte Primary Root CA - G3 + {0x4B, 0x03, 0xF4, 0x58, 0x07, 0xAD, 0x70, 0xF2, 0x1B, 0xFC, 0x2C, 0xAE, + 0x71, 0xC9, 0xFD, 0xE4, 0x60, 0x4C, 0x06, 0x4C, 0xF5, 0xFF, 0xB6, 0x86, + 0xBA, 0xE5, 0xDB, 0xAA, 0xD7, 0xFD, 0xD3, 0x4C}, + // C=CN, O=WoSign CA Limited, CN=Certification Authority of WoSign + {0x4B, 0x22, 0xD5, 0xA6, 0xAE, 0xC9, 0x9F, 0x3C, 0xDB, 0x79, 0xAA, 0x5E, + 0xC0, 0x68, 0x38, 0x47, 0x9C, 0xD5, 0xEC, 0xBA, 0x71, 0x64, 0xF7, 0xF2, + 0x2D, 0xC1, 0xD6, 0x5F, 0x63, 0xD8, 0x57, 0x08}, + // C=BR, O=Certisign Certificadora Digital Ltda., OU=Certisign - Autoridade + // Certificadora - AC4 + {0x4B, 0xDB, 0x74, 0x18, 0xBD, 0xF7, 0xFF, 0xE3, 0x3B, 0xA0, 0x88, 0x4A, + 0xFA, 0x7C, 0x0C, 0x61, 0xFD, 0x85, 0xA1, 0x53, 0x97, 0x2F, 0x65, 0xF7, + 0xD0, 0x1C, 0xB3, 0xEC, 0x7E, 0xB4, 0x07, 0x3C}, + // C=ES, O=Agencia Notarial de Certificacion S.L.U. - CIF B83395988, + // CN=ANCERT Certificados Notariales V2 + {0x4B, 0xE8, 0xB5, 0xA1, 0xC7, 0x6C, 0x6A, 0xEA, 0xD0, 0x61, 0x19, 0x18, + 0xFC, 0xCF, 0x9D, 0xBD, 0x39, 0x8B, 0x67, 0xFB, 0x12, 0x29, 0x47, 0x58, + 0xBD, 0xF9, 0x94, 0xD0, 0xF9, 0x68, 0x2F, 0x60}, + // C=NL, O=Staat der Nederlanden, CN=Staat der Nederlanden EV Root CA + {0x4D, 0x24, 0x91, 0x41, 0x4C, 0xFE, 0x95, 0x67, 0x46, 0xEC, 0x4C, 0xEF, + 0xA6, 0xCF, 0x6F, 0x72, 0xE2, 0x8A, 0x13, 0x29, 0x43, 0x2F, 0x9D, 0x8A, + 0x90, 0x7A, 0xC4, 0xCB, 0x5D, 0xAD, 0xC1, 0x5A}, + // C=ES, O=FNMT-RCM, OU=AC RAIZ FNMT-RCM + {0x4D, 0x9E, 0xBB, 0x28, 0x82, 0x5C, 0x96, 0x43, 0xAB, 0x15, 0xD5, 0x4E, + 0x5F, 0x96, 0x14, 0xF1, 0x3C, 0xB3, 0xE9, 0x5D, 0xE3, 0xCF, 0x4E, 0xAC, + 0x97, 0x13, 0x01, 0xF3, 0x20, 0xF9, 0x22, 0x6E}, + // C=AT, O=Telekom-Control-Kommission, CN=Telekom-Control-Kommission Top 1 + {0x4D, 0xBB, 0x01, 0x57, 0xA6, 0x91, 0xFA, 0x73, 0x82, 0x28, 0x9D, 0x65, + 0xC0, 0x33, 0x2D, 0xDB, 0x1D, 0xCB, 0x64, 0x0B, 0x40, 0xAD, 0x10, 0xF0, + 0x10, 0xA4, 0x3E, 0x20, 0xF3, 0xAF, 0xED, 0x1E}, + // C=AT, ST=Austria, L=Vienna, O=Arge Daten Oesterreichische Gesellschaft + // fuer Datenschutz/emailAddress=a-cert@argedaten.at + {0x4E, 0x74, 0x80, 0xAD, 0x70, 0x2A, 0x37, 0x9D, 0xC5, 0x89, 0xAD, 0xB4, + 0xFA, 0xA6, 0x25, 0xE6, 0xA5, 0x99, 0x3F, 0x87, 0xEF, 0x23, 0x75, 0xD5, + 0x43, 0x7F, 0xFE, 0x3B, 0x79, 0xBE, 0x4E, 0x96}, + // C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust + // ECC Certification Authority + {0x4F, 0xF4, 0x60, 0xD5, 0x4B, 0x9C, 0x86, 0xDA, 0xBF, 0xBC, 0xFC, 0x57, + 0x12, 0xE0, 0x40, 0x0D, 0x2B, 0xED, 0x3F, 0xBC, 0x4D, 0x4F, 0xBD, 0xAA, + 0x86, 0xE0, 0x6A, 0xDC, 0xD2, 0xA9, 0xAD, 0x7A}, + // CN=ComSign Secured CA, O=ComSign, C=IL + {0x50, 0x79, 0x41, 0xC7, 0x44, 0x60, 0xA0, 0xB4, 0x70, 0x86, 0x22, 0x0D, + 0x4E, 0x99, 0x32, 0x57, 0x2A, 0xB5, 0xD1, 0xB5, 0xBB, 0xCB, 0x89, 0x80, + 0xAB, 0x1C, 0xB1, 0x76, 0x51, 0xA8, 0x44, 0xD2}, + // C=JP, O=SECOM Trust Systems CO.,LTD., OU=Security Communication RootCA2 + {0x51, 0x3B, 0x2C, 0xEC, 0xB8, 0x10, 0xD4, 0xCD, 0xE5, 0xDD, 0x85, 0x39, + 0x1A, 0xDF, 0xC6, 0xC2, 0xDD, 0x60, 0xD8, 0x7B, 0xB7, 0x36, 0xD2, 0xB5, + 0x21, 0x48, 0x4A, 0xA4, 0x7A, 0x0E, 0xBE, 0xF6}, + // O=eSign Australia, OU=Public Secure Services, CN=eSign Imperito Primary + // Root CA + {0x52, 0x7A, 0x42, 0x26, 0x7D, 0xAE, 0xA8, 0xD8, 0xF5, 0x4E, 0x91, 0xD2, + 0x82, 0xD5, 0xC2, 0x5B, 0x61, 0x5B, 0xC0, 0xDC, 0x73, 0xDC, 0x63, 0xA5, + 0x8F, 0x91, 0x6C, 0x4E, 0xD5, 0xBF, 0x59, 0xAC}, + // C=US, O=GTE Corporation, CN=GTE CyberTrust Root + {0x52, 0x7B, 0x05, 0x05, 0x27, 0xDF, 0x52, 0x9C, 0x0F, 0x7A, 0xD0, 0x0C, + 0xEF, 0x1E, 0x7B, 0xA4, 0x21, 0x78, 0x81, 0x82, 0x61, 0x5C, 0x32, 0x6C, + 0x8B, 0x6D, 0x1A, 0x20, 0x61, 0xA0, 0xBD, 0x7C}, + // C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO + // RSA Certification Authority + {0x52, 0xF0, 0xE1, 0xC4, 0xE5, 0x8E, 0xC6, 0x29, 0x29, 0x1B, 0x60, 0x31, + 0x7F, 0x07, 0x46, 0x71, 0xB8, 0x5D, 0x7E, 0xA8, 0x0D, 0x5B, 0x07, 0x27, + 0x34, 0x63, 0x53, 0x4B, 0x32, 0xB4, 0x02, 0x34}, + // C=US, O=Symantec Corporation, OU=Symantec Trust Network, CN=Symantec + // Class 3 Public Primary Certification Authority - G4 + {0x53, 0xDF, 0xDF, 0xA4, 0xE2, 0x97, 0xFC, 0xFE, 0x07, 0x59, 0x4E, 0x8C, + 0x62, 0xD5, 0xB8, 0xAB, 0x06, 0xB3, 0x2C, 0x75, 0x49, 0xF3, 0x8A, 0x16, + 0x30, 0x94, 0xFD, 0x64, 0x29, 0xD5, 0xDA, 0x43}, + // C=JP, O=LGPKI, CN=Application CA G3 Root + {0x54, 0xB4, 0xFC, 0x43, 0xD4, 0x4A, 0xA4, 0xCA, 0x9F, 0xC0, 0x3C, 0xA7, + 0xE9, 0x94, 0x9F, 0xBA, 0xE2, 0x67, 0xA0, 0x64, 0xD0, 0x2D, 0xA2, 0x18, + 0x52, 0x41, 0x2A, 0x38, 0x1B, 0x5D, 0x15, 0x37}, + // C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Trusted Root G4 + {0x55, 0x2F, 0x7B, 0xDC, 0xF1, 0xA7, 0xAF, 0x9E, 0x6C, 0xE6, 0x72, 0x01, + 0x7F, 0x4F, 0x12, 0xAB, 0xF7, 0x72, 0x40, 0xC7, 0x8E, 0x76, 0x1A, 0xC2, + 0x03, 0xD1, 0xD9, 0xD2, 0x0A, 0xC8, 0x99, 0x88}, + // CN=Autoridad Certificadora Ra\xC3\xADz Nacional de Uruguay, O=AGESIC, + // C=UY + {0x55, 0x33, 0xA0, 0x40, 0x1F, 0x61, 0x2C, 0x68, 0x8E, 0xBC, 0xE5, 0xBF, + 0x53, 0xF2, 0xEC, 0x14, 0xA7, 0x34, 0xEB, 0x17, 0x8B, 0xFA, 0xE0, 0x0E, + 0x50, 0xE8, 0x5D, 0xAE, 0x67, 0x23, 0x07, 0x8A}, + // C=IT, L=Milan, O=Actalis S.p.A./03358520967, CN=Actalis Authentication + // Root CA + {0x55, 0x92, 0x60, 0x84, 0xEC, 0x96, 0x3A, 0x64, 0xB9, 0x6E, 0x2A, 0xBE, + 0x01, 0xCE, 0x0B, 0xA8, 0x6A, 0x64, 0xFB, 0xFE, 0xBC, 0xC7, 0xAA, 0xB5, + 0xAF, 0xC1, 0x55, 0xB3, 0x7F, 0xD7, 0x60, 0x66}, + // C=ES, O=Consejo General de la Abogacia NIF:Q-2863006I, CN=Autoridad de + // Certificacion de la Abogacia + {0x56, 0x07, 0xE2, 0x60, 0x16, 0x3F, 0x49, 0xC8, 0xEA, 0x41, 0x75, 0xA1, + 0xC0, 0xA5, 0x3B, 0x13, 0x19, 0x5C, 0xB7, 0xD0, 0x78, 0x45, 0x61, 0x1E, + 0x94, 0x3A, 0x2F, 0xF5, 0x07, 0x03, 0x68, 0x34}, + // C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, Inc., + // CN=Starfield Services Root Certificate Authority - G2 + {0x56, 0x8D, 0x69, 0x05, 0xA2, 0xC8, 0x87, 0x08, 0xA4, 0xB3, 0x02, 0x51, + 0x90, 0xED, 0xCF, 0xED, 0xB1, 0x97, 0x4A, 0x60, 0x6A, 0x13, 0xC6, 0xE5, + 0x29, 0x0F, 0xCB, 0x2A, 0xE6, 0x3E, 0xDA, 0xB5}, + // C=FR, O=OpenTrust, CN=OpenTrust Root CA G1 + {0x56, 0xC7, 0x71, 0x28, 0xD9, 0x8C, 0x18, 0xD9, 0x1B, 0x4C, 0xFD, 0xFF, + 0xBC, 0x25, 0xEE, 0x91, 0x03, 0xD4, 0x75, 0x8E, 0xA2, 0xAB, 0xAD, 0x82, + 0x6A, 0x90, 0xF3, 0x45, 0x7D, 0x46, 0x0E, 0xB4}, + // CN=T\xC3\x9CRKTRUST Elektronik \xC4\xB0\xC5\x9Flem Hizmetleri, C=TR, + // L=Ankara, O=T\xC3\x9CRKTRUST Bilgi \xC4\xB0leti\xC5\x9Fim ve + // Bili\xC5\x9Fim G\xC3\xBCvenli\xC4\x9Fi Hizmetleri A.\xC5\x9E. (c) + // Kas\xC4\xB1m 2005 + {0x56, 0xCE, 0x34, 0x7C, 0xC6, 0xDF, 0x4C, 0x35, 0x94, 0x3D, 0xFD, 0xEA, + 0xEE, 0x02, 0x3F, 0x97, 0x39, 0xA3, 0xF1, 0xCE, 0xDE, 0xEE, 0x0C, 0xD8, + 0x8D, 0xC2, 0x38, 0x6B, 0xC8, 0xA9, 0x1E, 0xAF}, + // L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 2 + // Policy Validation Authority, + // CN=http://www.valicert.com//emailAddress=info@valicert.com + {0x58, 0xD0, 0x17, 0x27, 0x9C, 0xD4, 0xDC, 0x63, 0xAB, 0xDD, 0xB1, 0x96, + 0xA6, 0xC9, 0x90, 0x6C, 0x30, 0xC4, 0xE0, 0x87, 0x83, 0xEA, 0xE8, 0xC1, + 0x60, 0x99, 0x54, 0xD6, 0x93, 0x55, 0x59, 0x6B}, + // C=TW, O=TAIWAN-CA, OU=Root CA, CN=TWCA Global Root CA + {0x59, 0x76, 0x90, 0x07, 0xF7, 0x68, 0x5D, 0x0F, 0xCD, 0x50, 0x87, 0x2F, + 0x9F, 0x95, 0xD5, 0x75, 0x5A, 0x5B, 0x2B, 0x45, 0x7D, 0x81, 0xF3, 0x69, + 0x2B, 0x61, 0x0A, 0x98, 0x67, 0x2F, 0x0E, 0x1B}, + // C=CH, O=SwissSign AG, CN=SwissSign Platinum Root CA - G3 + {0x59, 0xB3, 0x82, 0x9F, 0x1F, 0xF4, 0x43, 0x34, 0x49, 0x58, 0xFA, 0xE8, + 0xBF, 0xF6, 0x21, 0xB6, 0x84, 0xC8, 0x48, 0xCF, 0xBF, 0x7E, 0xAD, 0x6B, + 0x63, 0xA6, 0xCA, 0x50, 0xF2, 0x79, 0x4F, 0x89}, + // C=SI, O=Halcom, CN=Halcom CA FO + {0x5A, 0x1B, 0x5D, 0x6B, 0xC6, 0x55, 0x23, 0xB4, 0x0A, 0x6D, 0xEF, 0xFA, + 0x45, 0xB4, 0x8E, 0x42, 0x88, 0xAE, 0x8D, 0xD8, 0x6D, 0xD7, 0x0A, 0x5B, + 0x85, 0x8D, 0x4A, 0x5A, 0xFF, 0xC9, 0x4F, 0x71}, + // CN=AC1 RAIZ MTIN/serialNumber=S2819001E, OU=PRESTADOR DE SERVICIOS DE + // CERTIFICACION MTIN, OU=SUBDIRECCION GENERAL DE PROCESO DE DATOS, + // O=MINISTERIO DE TRABAJO E INMIGRACION, L=MADRID, C=ES + {0x5B, 0x1D, 0x9D, 0x24, 0xDE, 0x0A, 0xFE, 0xA8, 0xB3, 0x5B, 0xA0, 0x4A, + 0x1C, 0x3E, 0x25, 0xD0, 0x81, 0x2C, 0xDF, 0x7C, 0x46, 0x25, 0xDE, 0x0A, + 0x89, 0xAF, 0x9F, 0xE4, 0xBB, 0xD1, 0xBB, 0x15}, + // C=PL, O=Unizeto Technologies S.A., OU=Certum Certification Authority, + // CN=Certum Trusted Network CA + {0x5C, 0x58, 0x46, 0x8D, 0x55, 0xF5, 0x8E, 0x49, 0x7E, 0x74, 0x39, 0x82, + 0xD2, 0xB5, 0x00, 0x10, 0xB6, 0xD1, 0x65, 0x37, 0x4A, 0xCF, 0x83, 0xA7, + 0xD4, 0xA3, 0x2D, 0xB7, 0x68, 0xC4, 0x40, 0x8E}, + // C=CN, O=China Financial Certification Authority, CN=CFCA EV ROOT + {0x5C, 0xC3, 0xD7, 0x8E, 0x4E, 0x1D, 0x5E, 0x45, 0x54, 0x7A, 0x04, 0xE6, + 0x87, 0x3E, 0x64, 0xF9, 0x0C, 0xF9, 0x53, 0x6D, 0x1C, 0xCC, 0x2E, 0xF8, + 0x00, 0xF3, 0x55, 0xC4, 0xC5, 0xFD, 0x70, 0xFD}, + // C=US, O=IdenTrust, CN=IdenTrust Commercial Root CA 1 + {0x5D, 0x56, 0x49, 0x9B, 0xE4, 0xD2, 0xE0, 0x8B, 0xCF, 0xCA, 0xD0, 0x8A, + 0x3E, 0x38, 0x72, 0x3D, 0x50, 0x50, 0x3B, 0xDE, 0x70, 0x69, 0x48, 0xE4, + 0x2F, 0x55, 0x60, 0x30, 0x19, 0xE5, 0x28, 0xAE}, + // C=AT, L=Vienna, ST=Austria, O=ARGE DATEN - Austrian Society for Data + // Protection, OU=GLOBALTRUST Certification Service, + // CN=GLOBALTRUST/emailAddress=info@globaltrust.info + {0x5E, 0x35, 0x71, 0xF3, 0x3F, 0x45, 0xA7, 0xDF, 0x15, 0x37, 0xA6, 0x8B, + 0x5F, 0xFB, 0x9E, 0x03, 0x6A, 0xF9, 0xD2, 0xF5, 0xBC, 0x4C, 0x97, 0x17, + 0x13, 0x0D, 0xC4, 0x3D, 0x71, 0x75, 0xAA, 0xC7}, + // C=US, O=GeoTrust Inc., OU=(c) 2007 GeoTrust Inc. - For authorized use + // only, CN=GeoTrust Primary Certification Authority - G2 + {0x5E, 0xDB, 0x7A, 0xC4, 0x3B, 0x82, 0xA0, 0x6A, 0x87, 0x61, 0xE8, 0xD7, + 0xBE, 0x49, 0x79, 0xEB, 0xF2, 0x61, 0x1F, 0x7D, 0xD7, 0x9B, 0xF9, 0x1C, + 0x1C, 0x6B, 0x56, 0x6A, 0x21, 0x9E, 0xD7, 0x66}, + // C=US, O=Equifax Secure Inc., CN=Equifax Secure Global eBusiness CA-1 + {0x5F, 0x0B, 0x62, 0xEA, 0xB5, 0xE3, 0x53, 0xEA, 0x65, 0x21, 0x65, 0x16, + 0x58, 0xFB, 0xB6, 0x53, 0x59, 0xF4, 0x43, 0x28, 0x0A, 0x4A, 0xFB, 0xD1, + 0x04, 0xD7, 0x7D, 0x10, 0xF9, 0xF0, 0x4C, 0x07}, + // C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA1 + {0x5F, 0x96, 0x0E, 0xEB, 0xD7, 0x16, 0xDB, 0xCB, 0x4D, 0x8A, 0x78, 0xB9, + 0x96, 0xE6, 0x80, 0xEC, 0x25, 0x47, 0x44, 0x1E, 0x69, 0xB4, 0xE4, 0x4E, + 0x98, 0xA5, 0x95, 0x50, 0x2E, 0x28, 0xA0, 0x02}, + // C=PT, O=MULTICERT - Servi\xC3\xA7os de Certifica\xC3\xA7\xC3\xA3o + // Electr\xC3\xB3nica S.A., CN=MULTICERT Root Certification Authority 01 + {0x60, 0x4D, 0x32, 0xD0, 0x36, 0x89, 0x5A, 0xED, 0x3B, 0xFE, 0xFA, 0xEB, + 0x72, 0x7C, 0x00, 0x9E, 0xC0, 0xF2, 0xB3, 0xCD, 0xFA, 0x42, 0xA1, 0xC7, + 0x17, 0x30, 0xE6, 0xA7, 0x2C, 0x3B, 0xE9, 0xD4}, + // C=KR, O=Government of Korea, OU=GPKI, CN=GPKIRootCA + {0x60, 0x62, 0x23, 0xD9, 0xDB, 0x80, 0xDF, 0x39, 0x39, 0x60, 0x1E, 0x74, + 0xB7, 0xE8, 0x28, 0xE2, 0x80, 0x0C, 0xCE, 0x42, 0x73, 0xF7, 0x6F, 0x27, + 0x6A, 0xA6, 0x2D, 0xB0, 0xA8, 0xE3, 0xB6, 0xC1}, + // C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data + // Networks GmbH, OU=TC TrustCenter Class 1 + // CA/emailAddress=certificate@trustcenter.de + {0x61, 0x4F, 0xD1, 0x8D, 0xA1, 0x49, 0x05, 0x60, 0xCD, 0xAD, 0x11, 0x96, + 0xE2, 0x49, 0x2A, 0xB7, 0x06, 0x2E, 0xAB, 0x1A, 0x67, 0xB3, 0xA3, 0x0F, + 0x1D, 0x05, 0x85, 0xA7, 0xD6, 0xBA, 0x68, 0x24}, + // C=US, O=VeriSign, Inc., OU=Class 4 Public Primary Certification Authority + // - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign + // Trust Network + {0x61, 0xDC, 0x0C, 0x03, 0x91, 0x69, 0x4C, 0x65, 0x52, 0x00, 0xC1, 0x50, + 0x5E, 0xBC, 0xC9, 0xE4, 0xE2, 0x16, 0xBC, 0x31, 0xA5, 0xC5, 0x1A, 0x36, + 0x11, 0x28, 0x34, 0x23, 0xC1, 0xD8, 0x9E, 0x37}, + // C=ES, O=FNMT, OU=FNMT Clase 2 CA + {0x62, 0xB9, 0x26, 0x72, 0x66, 0x21, 0x28, 0x32, 0xA8, 0xE2, 0x2D, 0xAB, + 0x93, 0x3D, 0x91, 0xC7, 0x01, 0x12, 0x74, 0xAC, 0xF7, 0x17, 0x03, 0xF9, + 0xCC, 0x97, 0x83, 0x37, 0x51, 0xA6, 0xE9, 0x4F}, + // C=CH, O=SwissSign AG, CN=SwissSign Gold CA - G2 + {0x62, 0xDD, 0x0B, 0xE9, 0xB9, 0xF5, 0x0A, 0x16, 0x3E, 0xA0, 0xF8, 0xE7, + 0x5C, 0x05, 0x3B, 0x1E, 0xCA, 0x57, 0xEA, 0x55, 0xC8, 0x68, 0x8F, 0x64, + 0x7C, 0x68, 0x81, 0xF2, 0xC8, 0x35, 0x7B, 0x95}, + // C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits + // liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server + // Certification Authority + {0x62, 0xF2, 0x40, 0x27, 0x8C, 0x56, 0x4C, 0x4D, 0xD8, 0xBF, 0x7D, 0x9D, + 0x4F, 0x6F, 0x36, 0x6E, 0xA8, 0x94, 0xD2, 0x2F, 0x5F, 0x34, 0xD9, 0x89, + 0xA9, 0x83, 0xAC, 0xEC, 0x2F, 0xFF, 0xED, 0x50}, + // C=US, O=Digital Signature Trust Co., OU=DSTCA E1 + {0x63, 0x04, 0x19, 0xAE, 0xC4, 0x78, 0xCB, 0xB4, 0xBB, 0x80, 0x83, 0xDE, + 0x9D, 0x9C, 0xF2, 0x79, 0x75, 0x2F, 0x03, 0x9D, 0xEF, 0x16, 0xE4, 0x64, + 0x71, 0xB6, 0x79, 0xCA, 0x93, 0x00, 0x2D, 0xB0}, + // C=TW, O=TAIWAN-CA, OU=Root CA, CN=TWCA Root Certification Authority + {0x63, 0x2D, 0x80, 0xBB, 0x09, 0x6D, 0x20, 0x96, 0x77, 0xD1, 0x73, 0x4E, + 0x5B, 0x35, 0xEA, 0x9D, 0x30, 0x19, 0xB9, 0xC4, 0x4F, 0x8F, 0xCB, 0x26, + 0x40, 0xC8, 0x79, 0x03, 0x9A, 0xC9, 0x4E, 0xE8}, + // C=NL, O=Staat der Nederlanden, CN=Staat der Nederlanden Root CA - G2 + {0x66, 0x8C, 0x83, 0x94, 0x7D, 0xA6, 0x3B, 0x72, 0x4B, 0xEC, 0xE1, 0x74, + 0x3C, 0x31, 0xA0, 0xE6, 0xAE, 0xD0, 0xDB, 0x8E, 0xC5, 0xB3, 0x1B, 0xE3, + 0x77, 0xBB, 0x78, 0x4F, 0x91, 0xB6, 0x71, 0x6F}, + // O=eSign Australia, OU=Gatekeeper PKI, CN=Gatekeeper Root CA + {0x67, 0xEC, 0x20, 0x59, 0xFB, 0xF5, 0x2D, 0x2E, 0x6A, 0xB5, 0x1A, 0x5A, + 0x9B, 0x3F, 0xC2, 0xE1, 0xDC, 0xD6, 0x58, 0xA1, 0xEF, 0x3A, 0x8F, 0x31, + 0x10, 0x7B, 0xC9, 0x80, 0x28, 0xB4, 0x94, 0xA2}, + // C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority + {0x68, 0x72, 0x58, 0x62, 0x19, 0xC3, 0x49, 0xD8, 0x5A, 0xAA, 0x45, 0x86, + 0xA1, 0x44, 0x51, 0xF2, 0x45, 0x1A, 0xE3, 0xB6, 0x09, 0x2D, 0xBB, 0x1E, + 0xFF, 0xB0, 0x14, 0x7C, 0x33, 0xBF, 0x0F, 0xD4}, + // C=BR, O=ICP-Brasil, OU=Instituto Nacional de Tecnologia da Informacao - + // ITI, L=Brasilia, ST=DF, CN=Autoridade Certificadora Raiz Brasileira + {0x68, 0x7E, 0xA8, 0x90, 0x89, 0x30, 0x9D, 0x2C, 0xFE, 0x10, 0x7D, 0xB0, + 0x59, 0xFB, 0x10, 0xD6, 0x76, 0xF4, 0x5D, 0x32, 0x83, 0xAE, 0xE0, 0x56, + 0x90, 0x3E, 0xEA, 0x0C, 0xF3, 0xC1, 0x88, 0xF8}, + // C=SE, O=AddTrust AB, OU=AddTrust External TTP Network, CN=AddTrust + // External CA Root + {0x68, 0x7F, 0xA4, 0x51, 0x38, 0x22, 0x78, 0xFF, 0xF0, 0xC8, 0xB1, 0x1F, + 0x8D, 0x43, 0xD5, 0x76, 0x67, 0x1C, 0x6E, 0xB2, 0xBC, 0xEA, 0xB4, 0x13, + 0xFB, 0x83, 0xD9, 0x65, 0xD0, 0x6D, 0x2F, 0xF2}, + // C=US, O=Verizon Business, OU=OmniRoot, CN=Verizon Global Root CA + {0x68, 0xAD, 0x50, 0x90, 0x9B, 0x04, 0x36, 0x3C, 0x60, 0x5E, 0xF1, 0x35, + 0x81, 0xA9, 0x39, 0xFF, 0x2C, 0x96, 0x37, 0x2E, 0x3F, 0x12, 0x32, 0x5B, + 0x0A, 0x68, 0x61, 0xE1, 0xD5, 0x9F, 0x66, 0x03}, + // C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2007 VeriSign, + // Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary + // Certification Authority - G4 + {0x69, 0xDD, 0xD7, 0xEA, 0x90, 0xBB, 0x57, 0xC9, 0x3E, 0x13, 0x5D, 0xC8, + 0x5E, 0xA6, 0xFC, 0xD5, 0x48, 0x0B, 0x60, 0x32, 0x39, 0xBD, 0xC4, 0x54, + 0xFC, 0x75, 0x8B, 0x2A, 0x26, 0xCF, 0x7F, 0x79}, + // C=US, O=VISA, OU=Visa International Service Association, CN=Visa + // eCommerce Root + {0x69, 0xFA, 0xC9, 0xBD, 0x55, 0xFB, 0x0A, 0xC7, 0x8D, 0x53, 0xBB, 0xEE, + 0x5C, 0xF1, 0xD5, 0x97, 0x98, 0x9F, 0xD0, 0xAA, 0xAB, 0x20, 0xA2, 0x51, + 0x51, 0xBD, 0xF1, 0x73, 0x3E, 0xE7, 0xD1, 0x22}, + // C=AT, O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH, + // OU=A-Trust-Qual-03, CN=A-Trust-Qual-03 + {0x6B, 0xAF, 0x50, 0xAE, 0x34, 0x67, 0xEF, 0xF3, 0xC3, 0x5F, 0xEF, 0xDC, + 0x76, 0xA0, 0x2A, 0x97, 0xFA, 0xB6, 0x26, 0x77, 0x23, 0xED, 0xA9, 0x1E, + 0x99, 0xF1, 0xB3, 0xDC, 0x2B, 0x28, 0xF8, 0x2E}, + // C=HU, L=Budapest, O=NetLock Kft., + // OU=Tan\xC3\xBAs\xC3\xADtv\xC3\xA1nykiad\xC3\xB3k (Certification + // Services), CN=NetLock Arany (Class Gold) + // F\xC5\x91tan\xC3\xBAs\xC3\xADtv\xC3\xA1ny + {0x6C, 0x61, 0xDA, 0xC3, 0xA2, 0xDE, 0xF0, 0x31, 0x50, 0x6B, 0xE0, 0x36, + 0xD2, 0xA6, 0xFE, 0x40, 0x19, 0x94, 0xFB, 0xD1, 0x3D, 0xF9, 0xC8, 0xD4, + 0x66, 0x59, 0x92, 0x74, 0xC4, 0x46, 0xEC, 0x98}, + // C=FR, O=Certplus, CN=Certplus Root CA G2 + {0x6C, 0xC0, 0x50, 0x41, 0xE6, 0x44, 0x5E, 0x74, 0x69, 0x6C, 0x4C, 0xFB, + 0xC9, 0xF8, 0x0F, 0x54, 0x3B, 0x7E, 0xAB, 0xBB, 0x44, 0xB4, 0xCE, 0x6F, + 0x78, 0x7C, 0x6A, 0x99, 0x71, 0xC4, 0x2F, 0x17}, + // C=AU, O=GOV, OU=DoD, OU=PKI, OU=CAs, CN=ADOCA02 + {0x6C, 0xCF, 0xD3, 0x02, 0xFC, 0x44, 0xBF, 0x45, 0x99, 0x32, 0x9B, 0x97, + 0x50, 0x87, 0x8E, 0xA4, 0x4E, 0x7E, 0x85, 0x66, 0x56, 0x4B, 0xCB, 0xD5, + 0x86, 0x16, 0x97, 0x62, 0xDD, 0x10, 0xC7, 0x4E}, + // O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits + // liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Certification + // Authority (2048) + {0x6D, 0xC4, 0x71, 0x72, 0xE0, 0x1C, 0xBC, 0xB0, 0xBF, 0x62, 0x58, 0x0D, + 0x89, 0x5F, 0xE2, 0xB8, 0xAC, 0x9A, 0xD4, 0xF8, 0x73, 0x80, 0x1E, 0x0C, + 0x10, 0xB9, 0xC8, 0x37, 0xD2, 0x1E, 0xB1, 0x77}, + // C=ES, ST=Madrid, L=Madrid, O=IPS Certification Authority s.l. ipsCA, + // OU=ipsCA, CN=ipsCA Global CA Root/emailAddress=global01@ipsca.com + {0x6D, 0xEA, 0x86, 0xA1, 0xE6, 0x66, 0x20, 0xA0, 0x40, 0xC3, 0xC5, 0x94, + 0x3C, 0xB2, 0x15, 0xD2, 0xCA, 0x87, 0xFB, 0x6A, 0xC0, 0x9B, 0x59, 0x70, + 0x7E, 0x29, 0xD2, 0xFA, 0xCB, 0xD6, 0x6B, 0x4E}, + // C=us, O=U.S. Government, OU=FBCA, CN=Common Policy + {0x6E, 0x5E, 0x93, 0xAE, 0x86, 0x7F, 0xD3, 0xE3, 0xE7, 0x83, 0x04, 0xE0, + 0x54, 0xD1, 0xA6, 0xAE, 0xAE, 0xD0, 0x29, 0x5D, 0x58, 0xC0, 0xE3, 0xFC, + 0x4C, 0x9F, 0xFE, 0x31, 0x0A, 0x34, 0x88, 0xCC}, + // C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, + // OU=http://www.usertrust.com, CN=UTN-USERFirst-Hardware + {0x6E, 0xA5, 0x47, 0x41, 0xD0, 0x04, 0x66, 0x7E, 0xED, 0x1B, 0x48, 0x16, + 0x63, 0x4A, 0xA3, 0xA7, 0x9E, 0x6E, 0x4B, 0x96, 0x95, 0x0F, 0x82, 0x79, + 0xDA, 0xFC, 0x8D, 0x9B, 0xD8, 0x81, 0x21, 0x37}, + // C=CH, O=The Federal Authorities of the Swiss Confederation, OU=Services, + // OU=Certification Authorities, CN=Swiss Government Root CA I + {0x6E, 0xC6, 0x61, 0x4E, 0x9A, 0x8E, 0xFD, 0x47, 0xD6, 0x31, 0x8F, 0xFD, + 0xFD, 0x0B, 0xF6, 0x5B, 0x49, 0x3A, 0x14, 0x1F, 0x77, 0xC3, 0x8D, 0x0B, + 0x31, 0x9B, 0xE1, 0xBB, 0xBC, 0x05, 0x3D, 0xD2}, + // C=KR, O=KISA, OU=Korea Certification Authority Central, CN=KISA RootCA 1 + {0x6F, 0xDB, 0x3F, 0x76, 0xC8, 0xB8, 0x01, 0xA7, 0x53, 0x38, 0xD8, 0xA5, + 0x0A, 0x7C, 0x02, 0x87, 0x9F, 0x61, 0x98, 0xB5, 0x7E, 0x59, 0x4D, 0x31, + 0x8D, 0x38, 0x32, 0x90, 0x0F, 0xED, 0xCD, 0x79}, + // C=US, O=AffirmTrust, CN=AffirmTrust Premium + {0x70, 0xA7, 0x3F, 0x7F, 0x37, 0x6B, 0x60, 0x07, 0x42, 0x48, 0x90, 0x45, + 0x34, 0xB1, 0x14, 0x82, 0xD5, 0xBF, 0x0E, 0x69, 0x8E, 0xCC, 0x49, 0x8D, + 0xF5, 0x25, 0x77, 0xEB, 0xF2, 0xE9, 0x3B, 0x9A}, + // C=TW, O=Government Root Certification Authority + {0x70, 0xB9, 0x22, 0xBF, 0xDA, 0x0E, 0x3F, 0x4A, 0x34, 0x2E, 0x4E, 0xE2, + 0x2D, 0x57, 0x9A, 0xE5, 0x98, 0xD0, 0x71, 0xCC, 0x5E, 0xC9, 0xC3, 0x0F, + 0x12, 0x36, 0x80, 0x34, 0x03, 0x88, 0xAE, 0xA5}, + // C=PL, O=Telekomunikacja Polska S.A., OU=Signet Certification Authority, + // CN=Signet Root CA + {0x72, 0x86, 0xCE, 0x24, 0x9F, 0xE9, 0xE3, 0x2B, 0xD4, 0x75, 0x22, 0x57, + 0xC1, 0x7C, 0xD8, 0xF6, 0x99, 0x1A, 0x9C, 0x1E, 0x6F, 0x1A, 0x3C, 0xC7, + 0x33, 0x04, 0xED, 0x02, 0x3E, 0x6A, 0xE4, 0xEB}, + // C=NL, O=PTT Post, OU=KeyMail, CN=PTT Post Root CA/mail=ca@ptt-post.nl + {0x73, 0x0B, 0x61, 0x9E, 0xAA, 0x75, 0x98, 0x63, 0xC6, 0x53, 0x60, 0xB7, + 0x41, 0x2E, 0x14, 0x57, 0xEC, 0xA9, 0x68, 0x44, 0xEF, 0x2F, 0x16, 0xD9, + 0x1F, 0xCF, 0x2E, 0xFE, 0x46, 0xA6, 0x47, 0xE9}, + // C=TR, O=Elektronik Bilgi Guvenligi A.S., CN=E-GUVEN Kok Elektronik + // Sertifika Hizmet Saglayicisi S2 + {0x73, 0x2F, 0xF5, 0xBC, 0x47, 0x3C, 0x33, 0xEF, 0xAA, 0xD9, 0xB1, 0x87, + 0xFB, 0x45, 0x9A, 0x73, 0x2F, 0xFB, 0xEE, 0xA5, 0x9D, 0xF0, 0xFD, 0xFB, + 0x8E, 0x2F, 0xB5, 0xDE, 0xF4, 0x03, 0x2A, 0xFE}, + // C=ES, O=DIRECCION GENERAL DE LA POLICIA, OU=DNIE, CN=AC RAIZ DNIE + {0x73, 0x97, 0x10, 0xC5, 0x24, 0x5E, 0x33, 0xEC, 0x8A, 0x24, 0x3A, 0x1B, + 0x20, 0x04, 0x8F, 0xC9, 0xD5, 0xF4, 0x52, 0x85, 0x99, 0x21, 0x38, 0x45, + 0xC1, 0x64, 0xD0, 0x04, 0xB8, 0xB6, 0x67, 0xF9}, + // C=US, O=Entrust, Inc., OU=www.entrust.net/CPS is incorporated by + // reference, OU=(c) 2006 Entrust, Inc., CN=Entrust Root Certification + // Authority + {0x73, 0xC1, 0x76, 0x43, 0x4F, 0x1B, 0xC6, 0xD5, 0xAD, 0xF4, 0x5B, 0x0E, + 0x76, 0xE7, 0x27, 0x28, 0x7C, 0x8D, 0xE5, 0x76, 0x16, 0xC1, 0xE6, 0xE6, + 0x14, 0x1A, 0x2B, 0x2C, 0xBC, 0x7D, 0x8E, 0x4C}, + // C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert High Assurance EV + // Root CA + {0x74, 0x31, 0xE5, 0xF4, 0xC3, 0xC1, 0xCE, 0x46, 0x90, 0x77, 0x4F, 0x0B, + 0x61, 0xE0, 0x54, 0x40, 0x88, 0x3B, 0xA9, 0xA0, 0x1E, 0xD0, 0x0B, 0xA6, + 0xAB, 0xD7, 0x80, 0x6E, 0xD3, 0xB1, 0x18, 0xCF}, + // C=PA, ST=Panama, L=Panama City, O=TrustCor Systems S. de R.L., + // OU=TrustCor Certificate Authority, CN=TrustCor ECA-1 + {0x74, 0x4B, 0x11, 0x47, 0xB4, 0xA9, 0xA6, 0x9C, 0x32, 0x78, 0x5E, 0x9E, + 0x37, 0xC3, 0x32, 0x32, 0x41, 0xEF, 0x29, 0xF6, 0x3E, 0x76, 0xF1, 0x60, + 0x3D, 0x67, 0x61, 0xA7, 0x83, 0xD8, 0xA0, 0xFE}, + // C=si, O=state-institutions, OU=sigov-ca + {0x74, 0xCB, 0x3A, 0x4E, 0xA7, 0x91, 0xAF, 0xB0, 0xA2, 0xD1, 0xA0, 0xB1, + 0x33, 0x01, 0xB3, 0xBE, 0xE0, 0xE5, 0x0A, 0xD5, 0xC7, 0x9A, 0x1A, 0x6F, + 0x2C, 0x66, 0x3E, 0x6F, 0x4E, 0xE7, 0xA4, 0x84}, + // C=AT, O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH, + // OU=A-Trust-Qual-02, CN=A-Trust-Qual-02 + {0x75, 0xC9, 0xD4, 0x36, 0x1C, 0xB9, 0x6E, 0x99, 0x3A, 0xBD, 0x96, 0x20, + 0xCF, 0x04, 0x3B, 0xE9, 0x40, 0x7A, 0x46, 0x33, 0xF2, 0x02, 0xF0, 0xF4, + 0xC0, 0xE1, 0x78, 0x51, 0xCC, 0x60, 0x89, 0xCD}, + // C=TW, O=Government Root Certification Authority + {0x76, 0x00, 0x29, 0x5E, 0xEF, 0xE8, 0x5B, 0x9E, 0x1F, 0xD6, 0x24, 0xDB, + 0x76, 0x06, 0x2A, 0xAA, 0xAE, 0x59, 0x81, 0x8A, 0x54, 0xD2, 0x77, 0x4C, + 0xD4, 0xC0, 0xB2, 0xC0, 0x11, 0x31, 0xE1, 0xB3}, + // C=US, O=Digital Signature Trust, OU=DST ACES, CN=DST ACES CA X6 + {0x76, 0x7C, 0x95, 0x5A, 0x76, 0x41, 0x2C, 0x89, 0xAF, 0x68, 0x8E, 0x90, + 0xA1, 0xC7, 0x0F, 0x55, 0x6C, 0xFD, 0x6B, 0x60, 0x25, 0xDB, 0xEA, 0x10, + 0x41, 0x6D, 0x7E, 0xB6, 0x83, 0x1F, 0x8C, 0x40}, + // C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data + // Networks GmbH, OU=TC TrustCenter Class 3 + // CA/emailAddress=certificate@trustcenter.de + {0x76, 0xEF, 0x47, 0x62, 0xE5, 0x73, 0x20, 0x60, 0x06, 0xCB, 0xC3, 0x38, + 0xB1, 0x7C, 0xA4, 0xBC, 0x20, 0x05, 0x74, 0xA1, 0x19, 0x28, 0xD9, 0x0C, + 0x3E, 0xF3, 0x1C, 0x5E, 0x80, 0x3E, 0x6C, 0x6F}, + // L=Alvaro Obregon, ST=Distrito Federal, + // C=MX/postalCode=01030/street=Insurgentes Sur 1940, CN=Autoridad + // Certificadora Raiz de la Secretaria de Economia, OU=Direccion General de + // Normatividad Mercantil, O=Secretaria de + // Economia/emailAddress=acrse@economia.gob.mx + {0x77, 0xE0, 0x4C, 0x9A, 0x75, 0x1C, 0x73, 0xF2, 0x3E, 0x2A, 0x13, 0x36, + 0x11, 0x2E, 0xC8, 0xD5, 0x15, 0x3D, 0x38, 0x2A, 0x15, 0x2F, 0xED, 0x89, + 0xD7, 0x53, 0x2C, 0x31, 0x02, 0x77, 0x1F, 0x3C}, + // C=SG, O=Netrust Certificate Authority 1, OU=Netrust CA1 + {0x78, 0x1D, 0x64, 0xDF, 0xA7, 0x7B, 0x00, 0xF2, 0xC0, 0x06, 0x70, 0x0B, + 0x1F, 0xDA, 0x86, 0xBF, 0x68, 0xB8, 0x65, 0xA6, 0x03, 0xC7, 0xA6, 0x56, + 0xF9, 0x2E, 0x90, 0xC0, 0x42, 0xCA, 0x28, 0x73}, + // C=FI, O=Sonera, CN=Sonera Class2 CA + {0x79, 0x08, 0xB4, 0x03, 0x14, 0xC1, 0x38, 0x10, 0x0B, 0x51, 0x8D, 0x07, + 0x35, 0x80, 0x7F, 0xFB, 0xFC, 0xF8, 0x51, 0x8A, 0x00, 0x95, 0x33, 0x71, + 0x05, 0xBA, 0x38, 0x6B, 0x15, 0x3D, 0xD9, 0x27}, + // C=AT, O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH, + // OU=A-Trust-nQual-03, CN=A-Trust-nQual-03 + {0x79, 0x3C, 0xBF, 0x45, 0x59, 0xB9, 0xFD, 0xE3, 0x8A, 0xB2, 0x2D, 0xF1, + 0x68, 0x69, 0xF6, 0x98, 0x81, 0xAE, 0x14, 0xC4, 0xB0, 0x13, 0x9A, 0xC7, + 0x88, 0xA7, 0x8A, 0x1A, 0xFC, 0xCA, 0x02, 0xFB}, + // C=ZA, ST=Western Cape, L=Somerset West, O=South African Post Office + // Limited, OU=SAPO Trust Centre, CN=SAPO Class 3 Root + // CA/emailAddress=pkiadmin@trustcentre.co.za + {0x79, 0x6B, 0x93, 0xD0, 0xA3, 0xBA, 0x22, 0xE1, 0x91, 0xF2, 0x49, 0x5F, + 0x15, 0x0A, 0x5F, 0x9B, 0xFE, 0xE2, 0xCE, 0x15, 0x03, 0xDA, 0x21, 0x7B, + 0x74, 0xB8, 0xA9, 0x84, 0x68, 0x51, 0x10, 0xF1}, + // C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority + // - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign + // Trust Network + {0x79, 0x7E, 0x51, 0xF8, 0x83, 0xE8, 0x55, 0xD0, 0x21, 0xE5, 0xC7, 0x70, + 0x56, 0x66, 0x92, 0x99, 0x94, 0x07, 0x89, 0x55, 0x93, 0x23, 0x5D, 0xEF, + 0x52, 0xA0, 0x11, 0xF7, 0x16, 0xF8, 0xB6, 0xBF}, + // C=US, ST=MN, L=Minneapolis, O=Open Access Technology International Inc, + // CN=OATI WebCARES Root CA + {0x7A, 0x77, 0xC6, 0xC6, 0x1E, 0xEE, 0xB9, 0xAA, 0x65, 0xC4, 0xEA, 0x41, + 0x0D, 0x65, 0xD8, 0x95, 0xB2, 0x6A, 0x81, 0x12, 0x32, 0x83, 0x00, 0x9D, + 0xB1, 0x04, 0xB4, 0x8D, 0xE8, 0x0B, 0x24, 0x79}, + // C=CH, O=SwissSign AG, CN=SwissSign Gold Root CA - G3 + {0x7A, 0xF6, 0xEA, 0x9F, 0x75, 0x3A, 0x1E, 0x70, 0x9B, 0xD6, 0x4D, 0x0B, + 0xEB, 0x86, 0x7C, 0x11, 0xE8, 0xC2, 0x95, 0xA5, 0x6E, 0x24, 0xA6, 0xE0, + 0x47, 0x14, 0x59, 0xDC, 0xCD, 0xAA, 0x15, 0x58}, + // C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=DSTCA + // X1, CN=DST RootCA X1/emailAddress=ca@digsigtrust.com + {0x7B, 0x1A, 0x15, 0xD7, 0xE5, 0xE1, 0x30, 0xC5, 0x79, 0xE6, 0x8F, 0xCA, + 0x18, 0x92, 0x57, 0xF8, 0x37, 0xB5, 0xC1, 0x88, 0xF1, 0xB2, 0xB2, 0xA7, + 0x91, 0xE9, 0x67, 0xCC, 0x88, 0xCC, 0x65, 0x28}, + // C=AT, O=A-Trust, OU=A-Trust-nQual-01, CN=A-Trust-nQual-01 + {0x7B, 0x1F, 0x8D, 0x8E, 0xFF, 0x5D, 0x73, 0x49, 0xFE, 0xDB, 0x7E, 0xAE, + 0x89, 0xC2, 0x9A, 0xAC, 0xC4, 0x17, 0x04, 0xF1, 0x50, 0x3A, 0xE3, 0xC8, + 0xC2, 0xEB, 0xA1, 0x02, 0x25, 0xD0, 0xF5, 0x68}, + // C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root G2 + {0x7D, 0x05, 0xEB, 0xB6, 0x82, 0x33, 0x9F, 0x8C, 0x94, 0x51, 0xEE, 0x09, + 0x4E, 0xEB, 0xFE, 0xFA, 0x79, 0x53, 0xA1, 0x14, 0xED, 0xB2, 0xF4, 0x49, + 0x49, 0x45, 0x2F, 0xAB, 0x7D, 0x2F, 0xC1, 0x85}, + // C=ES, O=Colegio de Registradores de la Propiedad y Mercantiles de + // Espa\xC3\xB1a, OU=Certificado Propio, CN=Registradores de Espa\xC3\xB1a - + // CA Ra\xC3\xADz + {0x7D, 0x2B, 0xF3, 0x48, 0x9E, 0xBC, 0x9A, 0xD3, 0x44, 0x8B, 0x8B, 0x08, + 0x27, 0x71, 0x5A, 0x3C, 0xBF, 0xE3, 0xD5, 0x23, 0xE3, 0xB5, 0x6A, 0x9B, + 0x5F, 0xC1, 0xD2, 0xA2, 0xDA, 0x2F, 0x20, 0xFE}, + // C=US, O=America Online Inc., CN=America Online Root Certification + // Authority 2 + {0x7D, 0x3B, 0x46, 0x5A, 0x60, 0x14, 0xE5, 0x26, 0xC0, 0xAF, 0xFC, 0xEE, + 0x21, 0x27, 0xD2, 0x31, 0x17, 0x27, 0xAD, 0x81, 0x1C, 0x26, 0x84, 0x2D, + 0x00, 0x6A, 0xF3, 0x73, 0x06, 0xCC, 0x80, 0xBD}, + // C=FR, O=Certplus, CN=Class 1 Primary CA + {0x7D, 0x8C, 0xE8, 0x22, 0x22, 0x2B, 0x90, 0xC0, 0xB1, 0x43, 0x42, 0xC7, + 0xA8, 0x14, 0x5D, 0x1F, 0x24, 0x35, 0x1F, 0x4D, 0x1A, 0x1F, 0xE0, 0xED, + 0xFD, 0x31, 0x2E, 0xE7, 0x3F, 0xB0, 0x01, 0x49}, + // C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Assured ID Root G3 + {0x7E, 0x37, 0xCB, 0x8B, 0x4C, 0x47, 0x09, 0x0C, 0xAB, 0x36, 0x55, 0x1B, + 0xA6, 0xF4, 0x5D, 0xB8, 0x40, 0x68, 0x0F, 0xBA, 0x16, 0x6A, 0x95, 0x2D, + 0xB1, 0x00, 0x71, 0x7F, 0x43, 0x05, 0x3F, 0xC2}, + // C=HU, ST=Hungary, L=Budapest, O=NetLock Halozatbiztonsagi Kft., + // OU=Tanusitvanykiadok, CN=NetLock Kozjegyzoi (Class A) Tanusitvanykiado + {0x7F, 0x12, 0xCD, 0x5F, 0x7E, 0x5E, 0x29, 0x0E, 0xC7, 0xD8, 0x51, 0x79, + 0xD5, 0xB7, 0x2C, 0x20, 0xA5, 0xBE, 0x75, 0x08, 0xFF, 0xDB, 0x5B, 0xF8, + 0x1A, 0xB9, 0x68, 0x4A, 0x7F, 0xC9, 0xF6, 0x67}, + // C=ES, O=Agencia Notarial de Certificacion S.L. Unipersonal - CIF + // B83395988, CN=ANCERT Certificados CGN + {0x81, 0x77, 0xD1, 0xA8, 0x2B, 0xA5, 0x01, 0xAF, 0xDD, 0x1E, 0x94, 0x83, + 0xAD, 0x7D, 0xA9, 0x12, 0xEE, 0x1E, 0x9F, 0xCB, 0x2A, 0x5A, 0x06, 0x1F, + 0xA3, 0xC4, 0x79, 0xFA, 0x80, 0x4C, 0xE6, 0xBA}, + // C=TR, O=Elektronik Bilgi Guvenligi A.S., CN=E-GUVEN Kok Elektronik + // Sertifika Hizmet Saglayicisi S3 + {0x82, 0xD4, 0x2D, 0xB3, 0xD6, 0x57, 0xF1, 0x94, 0x4E, 0x65, 0xC1, 0x92, + 0xB1, 0xDD, 0x58, 0xDB, 0x8D, 0xF8, 0x41, 0x7B, 0x89, 0x16, 0x5B, 0x04, + 0x5F, 0x5C, 0x6A, 0x70, 0xC5, 0xF8, 0x93, 0x9E}, + // O=Cisco Systems, CN=Cisco Root CA 2048 + {0x83, 0x27, 0xBC, 0x8C, 0x9D, 0x69, 0x94, 0x7B, 0x3D, 0xE3, 0xC2, 0x75, + 0x11, 0x53, 0x72, 0x67, 0xF5, 0x9C, 0x21, 0xB9, 0xFA, 0x7B, 0x61, 0x3F, + 0xAF, 0xBC, 0xCD, 0x53, 0xB7, 0x02, 0x40, 0x00}, + // C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority + // - G2, OU=(c) 1998 VeriSign, Inc. - For authorized use only, OU=VeriSign + // Trust Network + {0x83, 0xCE, 0x3C, 0x12, 0x29, 0x68, 0x8A, 0x59, 0x3D, 0x48, 0x5F, 0x81, + 0x97, 0x3C, 0x0F, 0x91, 0x95, 0x43, 0x1E, 0xDA, 0x37, 0xCC, 0x5E, 0x36, + 0x43, 0x0E, 0x79, 0xC7, 0xA8, 0x88, 0x63, 0x8B}, + // C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft + // Root Certificate Authority 2011 + {0x84, 0x7D, 0xF6, 0xA7, 0x84, 0x97, 0x94, 0x3F, 0x27, 0xFC, 0x72, 0xEB, + 0x93, 0xF9, 0xA6, 0x37, 0x32, 0x0A, 0x02, 0xB5, 0x61, 0xD0, 0xA9, 0x1B, + 0x09, 0xE8, 0x7A, 0x78, 0x07, 0xED, 0x7C, 0x61}, + // C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 2 + {0x85, 0xA0, 0xDD, 0x7D, 0xD7, 0x20, 0xAD, 0xB7, 0xFF, 0x05, 0xF8, 0x3D, + 0x54, 0x2B, 0x20, 0x9D, 0xC7, 0xFF, 0x45, 0x28, 0xF7, 0xD6, 0x77, 0xB1, + 0x83, 0x89, 0xFE, 0xA5, 0xE5, 0xC4, 0x9E, 0x86}, + // C=BR, O=Certisign Certificadora Digital Ltda., OU=Certisign Autoridade + // Certificadora AC1S + {0x85, 0xE0, 0xDF, 0xAE, 0x3E, 0x55, 0xA8, 0x43, 0x19, 0x5F, 0x8B, 0x08, + 0xC8, 0x34, 0x90, 0x50, 0xE4, 0x68, 0x93, 0x72, 0xF6, 0xE1, 0x33, 0xAD, + 0x0D, 0x19, 0x9A, 0xF9, 0x6E, 0x95, 0xCC, 0x08}, + // C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, + // OU=http://www.usertrust.com, CN=UTN - DATACorp SGC + {0x85, 0xFB, 0x2F, 0x91, 0xDD, 0x12, 0x27, 0x5A, 0x01, 0x45, 0xB6, 0x36, + 0x53, 0x4F, 0x84, 0x02, 0x4A, 0xD6, 0x8B, 0x69, 0xB8, 0xEE, 0x88, 0x68, + 0x4F, 0xF7, 0x11, 0x37, 0x58, 0x05, 0xB3, 0x48}, + // C=AT, O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH, + // OU=A-Trust-nQual-03, CN=A-Trust-nQual-03 + {0x86, 0x88, 0xE5, 0x8F, 0x4C, 0x7A, 0x94, 0x5F, 0xAD, 0xCE, 0x7F, 0x62, + 0xBF, 0xEF, 0x52, 0x1B, 0x82, 0xDA, 0x7D, 0xC3, 0x8B, 0xFD, 0xB0, 0x16, + 0x34, 0x78, 0xA5, 0xFE, 0x42, 0xE5, 0x78, 0x70}, + // C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, + // OU=Certification Services Division, CN=Thawte Server + // CA/emailAddress=server-certs@thawte.com + {0x87, 0xC6, 0x78, 0xBF, 0xB8, 0xB2, 0x5F, 0x38, 0xF7, 0xE9, 0x7B, 0x33, + 0x69, 0x56, 0xBB, 0xCF, 0x14, 0x4B, 0xBA, 0xCA, 0xA5, 0x36, 0x47, 0xE6, + 0x1A, 0x23, 0x25, 0xBC, 0x10, 0x55, 0x31, 0x6B}, + // C=ES, O=Agencia Catalana de Certificacio (NIF Q-0801176-I), OU=Serveis + // Publics de Certificacio, OU=Vegeu https://www.catcert.net/verarrel (c)03, + // OU=Jerarquia Entitats de Certificacio Catalanes, CN=EC-ACC + {0x88, 0x49, 0x7F, 0x01, 0x60, 0x2F, 0x31, 0x54, 0x24, 0x6A, 0xE2, 0x8C, + 0x4D, 0x5A, 0xEF, 0x10, 0xF1, 0xD8, 0x7E, 0xBB, 0x76, 0x62, 0x6F, 0x4A, + 0xE0, 0xB7, 0xF9, 0x5B, 0xA7, 0x96, 0x87, 0x99}, + // DC=com, DC=microsoft, CN=Microsoft Root Certificate Authority + {0x88, 0x5D, 0xE6, 0x4C, 0x34, 0x0E, 0x3E, 0xA7, 0x06, 0x58, 0xF0, 0x1E, + 0x11, 0x45, 0xF9, 0x57, 0xFC, 0xDA, 0x27, 0xAA, 0xBE, 0xEA, 0x1A, 0xB9, + 0xFA, 0xA9, 0xFD, 0xB0, 0x10, 0x2D, 0x40, 0x77}, + // C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 3 G3 + {0x88, 0xEF, 0x81, 0xDE, 0x20, 0x2E, 0xB0, 0x18, 0x45, 0x2E, 0x43, 0xF8, + 0x64, 0x72, 0x5C, 0xEA, 0x5F, 0xBD, 0x1F, 0xC2, 0xD9, 0xD2, 0x05, 0x73, + 0x07, 0x09, 0xC5, 0xD8, 0xB8, 0x69, 0x0F, 0x46}, + // C=SI, O=ACNLB + {0x89, 0x4C, 0xE6, 0xDD, 0xB0, 0x12, 0xCB, 0x3F, 0x73, 0x69, 0x54, 0x66, + 0x8D, 0xE6, 0x3F, 0x43, 0x60, 0x80, 0xE9, 0x5F, 0x17, 0xB7, 0xA8, 0x1B, + 0xD9, 0x24, 0xEB, 0x21, 0xBE, 0xE9, 0xE4, 0x40}, + // C=US, O=U.S. Government, OU=FPKI, CN=Federal Common Policy CA + {0x89, 0x4E, 0xBC, 0x0B, 0x23, 0xDA, 0x2A, 0x50, 0xC0, 0x18, 0x6B, 0x7F, + 0x8F, 0x25, 0xEF, 0x1F, 0x6B, 0x29, 0x35, 0xAF, 0x32, 0xA9, 0x45, 0x84, + 0xEF, 0x80, 0xAA, 0xF8, 0x77, 0xA3, 0xA0, 0x6E}, + // C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 1 G3 + {0x8A, 0x86, 0x6F, 0xD1, 0xB2, 0x76, 0xB5, 0x7E, 0x57, 0x8E, 0x92, 0x1C, + 0x65, 0x82, 0x8A, 0x2B, 0xED, 0x58, 0xE9, 0xF2, 0xF2, 0x88, 0x05, 0x41, + 0x34, 0xB7, 0xF1, 0xF4, 0xBF, 0xC9, 0xCC, 0x74}, + // C=SI, O=Halcom, CN=Halcom Root CA + {0x8B, 0x3F, 0xDB, 0x15, 0x1A, 0xF7, 0x59, 0xC5, 0x66, 0x14, 0x3E, 0x07, + 0xC9, 0x50, 0xED, 0xE4, 0xF9, 0xE8, 0xC7, 0xCF, 0x80, 0x84, 0x53, 0xD3, + 0x3B, 0xCB, 0x78, 0xE5, 0x2A, 0x40, 0x0A, 0xF9}, + // C=CN, O=WoSign CA Limited, CN=CA WoSign ECC Root + {0x8B, 0x45, 0xDA, 0x1C, 0x06, 0xF7, 0x91, 0xEB, 0x0C, 0xAB, 0xF2, 0x6B, + 0xE5, 0x88, 0xF5, 0xFB, 0x23, 0x16, 0x5C, 0x2E, 0x61, 0x4B, 0xF8, 0x85, + 0x56, 0x2D, 0x0D, 0xCE, 0x50, 0xB2, 0x9B, 0x02}, + // C=ES, O=Generalitat Valenciana, OU=PKIGVA, CN=Root CA Generalitat + // Valenciana + {0x8C, 0x4E, 0xDF, 0xD0, 0x43, 0x48, 0xF3, 0x22, 0x96, 0x9E, 0x7E, 0x29, + 0xA4, 0xCD, 0x4D, 0xCA, 0x00, 0x46, 0x55, 0x06, 0x1C, 0x16, 0xE1, 0xB0, + 0x76, 0x42, 0x2E, 0xF3, 0x42, 0xAD, 0x63, 0x0E}, + // C=US, O=thawte, Inc., OU=Certification Services Division, OU=(c) 2006 + // thawte, Inc. - For authorized use only, CN=thawte Primary Root CA + {0x8D, 0x72, 0x2F, 0x81, 0xA9, 0xC1, 0x13, 0xC0, 0x79, 0x1D, 0xF1, 0x36, + 0xA2, 0x96, 0x6D, 0xB2, 0x6C, 0x95, 0x0A, 0x97, 0x1D, 0xB4, 0x6B, 0x41, + 0x99, 0xF4, 0xEA, 0x54, 0xB7, 0x8B, 0xFB, 0x9F}, + // C=DE, O=D-Trust GmbH, CN=D-TRUST Root Class 2 CA 2007 + {0x8D, 0xA7, 0x5F, 0x13, 0x27, 0x21, 0x7C, 0x88, 0x06, 0x0F, 0xD2, 0x52, + 0x9E, 0xFF, 0x28, 0x16, 0xE5, 0x0B, 0x0C, 0x74, 0x54, 0x1E, 0xA4, 0xEA, + 0x3D, 0xFC, 0xEE, 0x66, 0xA7, 0x1E, 0xFE, 0x09}, + // C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data + // Networks GmbH, OU=TC TrustCenter Class 4 + // CA/emailAddress=certificate@trustcenter.de + {0x8D, 0xBB, 0x5A, 0x7C, 0x06, 0xC2, 0x0E, 0xF6, 0x2D, 0xD9, 0x12, 0xA3, + 0x67, 0x40, 0x99, 0x2F, 0xF6, 0xE1, 0xE8, 0x58, 0x3D, 0x42, 0xED, 0xE2, + 0x57, 0xC3, 0xAF, 0xFD, 0x7C, 0x76, 0x93, 0x99}, + // C=TR, L=Ankara, O=T\xC3\x9CRKTRUST Bilgi \xC4\xB0leti\xC5\x9Fim ve + // Bili\xC5\x9Fim G\xC3\xBCvenli\xC4\x9Fi Hizmetleri A.\xC5\x9E., + // CN=T\xC3\x9CRKTRUST Elektronik Sertifika Hizmet + // Sa\xC4\x9Flay\xC4\xB1c\xC4\xB1s\xC4\xB1 H6 + {0x8D, 0xE7, 0x86, 0x55, 0xE1, 0xBE, 0x7F, 0x78, 0x47, 0x80, 0x0B, 0x93, + 0xF6, 0x94, 0xD2, 0x1D, 0x36, 0x8C, 0xC0, 0x6E, 0x03, 0x3E, 0x7F, 0xAB, + 0x04, 0xBB, 0x5E, 0xB9, 0x9D, 0xA6, 0xB7, 0x00}, + // C=HU, L=Budapest, O=Microsec Ltd., CN=Microsec e-Szigno Root CA + // 2009/emailAddress=info@e-szigno.hu + {0x8E, 0x8C, 0x6E, 0xBF, 0x77, 0xDC, 0x73, 0xDB, 0x3E, 0x38, 0xE9, 0x3F, + 0x48, 0x03, 0xE6, 0x2B, 0x6B, 0x59, 0x33, 0xBE, 0xB5, 0x1E, 0xE4, 0x15, + 0x2F, 0x68, 0xD7, 0xAA, 0x14, 0x42, 0x6B, 0x31}, + // CN=SG TRUST SERVICES RACINE, OU=0002 43525289500022, O=SG TRUST SERVICES, + // C=FR + {0x8F, 0x1E, 0xCD, 0xAF, 0x29, 0xBC, 0xD5, 0x6E, 0xDD, 0xD6, 0xB5, 0xD5, + 0x6A, 0x07, 0xFC, 0xAC, 0x2B, 0x74, 0xD4, 0xBC, 0xD1, 0x79, 0x17, 0x91, + 0x44, 0xA0, 0x36, 0x5C, 0x27, 0xDC, 0xF1, 0x4B}, + // C=US, O=Digital Signature Trust Co., OU=DSTCA E2 + {0x8F, 0x62, 0xD7, 0x73, 0x6F, 0x99, 0xDB, 0xD3, 0x3E, 0xE0, 0x0E, 0x10, + 0xC7, 0xE3, 0x29, 0x33, 0x9C, 0x98, 0x8A, 0x5B, 0x47, 0xEF, 0x25, 0xF4, + 0x08, 0x29, 0x3C, 0xF2, 0x42, 0x6B, 0x4D, 0x44}, + // C=US, O=First Data Digital Certificates Inc., CN=First Data Digital + // Certificates Inc. Certification Authority + {0x8F, 0x63, 0x3D, 0xF0, 0x19, 0x1A, 0x41, 0x7D, 0xCD, 0x4F, 0x63, 0x31, + 0xF0, 0xE9, 0x0E, 0xB9, 0x47, 0x15, 0x8C, 0x8A, 0x3E, 0xA5, 0x9B, 0xFE, + 0x81, 0x42, 0x00, 0x41, 0x31, 0x5E, 0xAC, 0x6C}, + // C=DE, ST=Hamburg, L=Hamburg, O=TC TrustCenter for Security in Data + // Networks GmbH, OU=TC TrustCenter Class 2 + // CA/emailAddress=certificate@trustcenter.de + {0x8F, 0x9E, 0x27, 0x51, 0xDC, 0xD5, 0x74, 0xE9, 0xBA, 0x90, 0xE7, 0x44, + 0xEA, 0x92, 0x58, 0x1F, 0xD0, 0xAF, 0x64, 0x0A, 0xE8, 0x6A, 0xC1, 0xCE, + 0x21, 0x98, 0xC9, 0x0F, 0x96, 0xB4, 0x48, 0x23}, + // C=KR, O=KISA, OU=Korea Certification Authority Central, CN=KISA RootCA 3 + {0x8F, 0xDD, 0x29, 0x8D, 0x1C, 0x93, 0xB2, 0x2B, 0xFC, 0x42, 0xAA, 0xB1, + 0xC3, 0xA1, 0x5F, 0x0D, 0x01, 0x83, 0x2C, 0xA0, 0xA1, 0xAE, 0xF2, 0x8D, + 0x56, 0x80, 0xF0, 0x6E, 0x6C, 0x7F, 0xD4, 0xEF}, + // C=BM, O=QuoVadis Limited, CN=QuoVadis Root CA 2 G3 + {0x8F, 0xE4, 0xFB, 0x0A, 0xF9, 0x3A, 0x4D, 0x0D, 0x67, 0xDB, 0x0B, 0xEB, + 0xB2, 0x3E, 0x37, 0xC7, 0x1B, 0xF3, 0x25, 0xDC, 0xBC, 0xDD, 0x24, 0x0E, + 0xA0, 0x4D, 0xAF, 0x58, 0xB4, 0x7E, 0x18, 0x40}, + // C=DE, O=D-Trust GmbH, CN=D-TRUST Root Class 3 CA 2007 + {0x90, 0xF3, 0xE0, 0x53, 0x96, 0x99, 0x5F, 0xF2, 0x09, 0x22, 0xC4, 0x45, + 0x92, 0xDB, 0x62, 0xD7, 0x84, 0x5E, 0x1B, 0xF6, 0x4A, 0xEF, 0x51, 0x2C, + 0xCA, 0x75, 0xBC, 0x66, 0x9C, 0xAA, 0x24, 0x79}, + // C=PA, ST=Panama, L=Panama City, O=TrustCor Systems S. de R.L., + // OU=TrustCor Certificate Authority, CN=TrustCor RootCert CA-2 + {0x91, 0x11, 0x24, 0x07, 0x47, 0xE1, 0xF6, 0x52, 0xF6, 0x6D, 0x1F, 0x71, + 0x2A, 0x11, 0xF6, 0x98, 0x96, 0x3B, 0x49, 0x17, 0x02, 0xE3, 0x12, 0xF7, + 0x51, 0x3D, 0xA3, 0xD0, 0xFC, 0x1E, 0x5A, 0x28}, + // C=DE, O=T-Systems Enterprise Services GmbH, OU=T-Systems Trust Center, + // CN=T-TeleSec GlobalRoot Class 2 + {0x91, 0xE2, 0xF5, 0x78, 0x8D, 0x58, 0x10, 0xEB, 0xA7, 0xBA, 0x58, 0x73, + 0x7D, 0xE1, 0x54, 0x8A, 0x8E, 0xCA, 0xCD, 0x01, 0x45, 0x98, 0xBC, 0x0B, + 0x14, 0x3E, 0x04, 0x1B, 0x17, 0x05, 0x25, 0x52}, + // C=SK, L=Bratislava, O=Disig a.s., CN=CA Disig + {0x92, 0xBF, 0x51, 0x19, 0xAB, 0xEC, 0xCA, 0xD0, 0xB1, 0x33, 0x2D, 0xC4, + 0xE1, 0xD0, 0x5F, 0xBA, 0x75, 0xB5, 0x67, 0x90, 0x44, 0xEE, 0x0C, 0xA2, + 0x6E, 0x93, 0x1F, 0x74, 0x4F, 0x2F, 0x33, 0xCF}, + // C=CN, O=UniTrust, CN=UCA Root + {0x93, 0xE6, 0x5E, 0xC7, 0x62, 0xF0, 0x55, 0xDC, 0x71, 0x8A, 0x33, 0x25, + 0x82, 0xC4, 0x1A, 0x04, 0x43, 0x0D, 0x72, 0xE3, 0xCB, 0x87, 0xE8, 0xB8, + 0x97, 0xB6, 0x75, 0x16, 0xF0, 0xD1, 0xAA, 0x39}, + // C=KR, O=KISA, OU=ROOTCA, CN=CertRSA01 + {0x95, 0x60, 0x57, 0x51, 0x7F, 0xF3, 0xBB, 0x35, 0x04, 0x93, 0x42, 0x28, + 0x8C, 0x1C, 0x9D, 0xCE, 0x85, 0x2D, 0xAC, 0xA6, 0x52, 0xB4, 0x65, 0xE9, + 0x74, 0x72, 0x53, 0xB5, 0xF9, 0x3B, 0x1F, 0x5E}, + // O=Cybertrust, Inc, CN=Cybertrust Global Root + {0x96, 0x0A, 0xDF, 0x00, 0x63, 0xE9, 0x63, 0x56, 0x75, 0x0C, 0x29, 0x65, + 0xDD, 0x0A, 0x08, 0x67, 0xDA, 0x0B, 0x9C, 0xBD, 0x6E, 0x77, 0x71, 0x4A, + 0xEA, 0xFB, 0x23, 0x49, 0xAB, 0x39, 0x3D, 0xA3}, + // CN=T\xC3\x9CRKTRUST Elektronik Sertifika Hizmet + // Sa\xC4\x9Flay\xC4\xB1c\xC4\xB1s\xC4\xB1, C=TR, L=Ankara, + // O=T\xC3\x9CRKTRUST Bilgi \xC4\xB0leti\xC5\x9Fim ve Bili\xC5\x9Fim + // G\xC3\xBCvenli\xC4\x9Fi Hizmetleri A.\xC5\x9E. (c) Aral\xC4\xB1k 2007 + {0x97, 0x8C, 0xD9, 0x66, 0xF2, 0xFA, 0xA0, 0x7B, 0xA7, 0xAA, 0x95, 0x00, + 0xD9, 0xC0, 0x2E, 0x9D, 0x77, 0xF2, 0xCD, 0xAD, 0xA6, 0xAD, 0x6B, 0xA7, + 0x4A, 0xF4, 0xB9, 0x1C, 0x66, 0x59, 0x3C, 0x50}, + // C=DE, O=Deutsche Telekom AG, OU=T-TeleSec Trust Center, CN=Deutsche + // Telekom Root CA 1 + {0x98, 0x06, 0xAB, 0x85, 0x09, 0xE2, 0xF3, 0x5E, 0x19, 0x2F, 0x27, 0x5F, + 0x0C, 0x30, 0x8B, 0x94, 0x09, 0xB4, 0x25, 0x12, 0xF9, 0x0C, 0x65, 0x95, + 0x98, 0xC2, 0x2B, 0xE6, 0x13, 0x96, 0x22, 0x72}, + // C=NO, O=Buypass AS-983163327, CN=Buypass Class 2 Root CA + {0x9A, 0x11, 0x40, 0x25, 0x19, 0x7C, 0x5B, 0xB9, 0x5D, 0x94, 0xE6, 0x3D, + 0x55, 0xCD, 0x43, 0x79, 0x08, 0x47, 0xB6, 0x46, 0xB2, 0x3C, 0xDF, 0x11, + 0xAD, 0xA4, 0xA0, 0x0E, 0xFF, 0x15, 0xFB, 0x48}, + // CN=ACCVRAIZ1, OU=PKIACCV, O=ACCV, C=ES + {0x9A, 0x6E, 0xC0, 0x12, 0xE1, 0xA7, 0xDA, 0x9D, 0xBE, 0x34, 0x19, 0x4D, + 0x47, 0x8A, 0xD7, 0xC0, 0xDB, 0x18, 0x22, 0xFB, 0x07, 0x1D, 0xF1, 0x29, + 0x81, 0x49, 0x6E, 0xD1, 0x04, 0x38, 0x41, 0x13}, + // C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 2006 VeriSign, + // Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary + // Certification Authority - G5 + {0x9A, 0xCF, 0xAB, 0x7E, 0x43, 0xC8, 0xD8, 0x80, 0xD0, 0x6B, 0x26, 0x2A, + 0x94, 0xDE, 0xEE, 0xE4, 0xB4, 0x65, 0x99, 0x89, 0xC3, 0xD0, 0xCA, 0xF1, + 0x9B, 0xAF, 0x64, 0x05, 0xE4, 0x1A, 0xB7, 0xDF}, + // C=SE, O=Swedish Social Insurance Agency, CN=Swedish Government Root + // Authority v2 + {0x9C, 0xEF, 0xB0, 0xCB, 0x7B, 0x74, 0xE6, 0x42, 0x93, 0x25, 0x32, 0x83, + 0x1E, 0x0D, 0xC8, 0xF4, 0xD6, 0x8A, 0xD4, 0x14, 0x26, 0x1F, 0xC3, 0xF4, + 0x74, 0xB7, 0x95, 0xE7, 0x2A, 0x16, 0x4E, 0x57}, + // C=EU, O=AC Camerfirma SA CIF A82743287, OU=http://www.chambersign.org, + // CN=Public Notary Root + {0x9D, 0xB9, 0x30, 0xA7, 0xBC, 0xED, 0x5A, 0x59, 0x9D, 0xA6, 0x73, 0xD0, + 0xBB, 0x12, 0xC4, 0xC6, 0xC7, 0xAB, 0x5B, 0x3F, 0x88, 0xF3, 0x9C, 0x24, + 0xEE, 0x20, 0xA2, 0x47, 0x16, 0xB3, 0x79, 0xDF}, + // C=US, O=Digital Signature Trust Co., OU=DST (ANX Network) CA + {0x9D, 0xF0, 0xEC, 0x44, 0xF5, 0x5B, 0x36, 0xD7, 0x9D, 0x4B, 0x53, 0xC2, + 0x08, 0xBE, 0xF8, 0xCB, 0x63, 0xD7, 0x8D, 0xCC, 0x8F, 0xCA, 0xFD, 0xE1, + 0x66, 0x23, 0x12, 0xF2, 0x12, 0x20, 0x4A, 0x37}, + // C=PL, O=Unizeto Technologies S.A., OU=Certum Certification Authority, + // CN=Certum Trusted Network CA 2 + {0x9F, 0x8B, 0x05, 0x13, 0x7F, 0x20, 0xAC, 0xDE, 0x9B, 0x99, 0x64, 0x10, + 0xF4, 0xD0, 0xBF, 0x79, 0x71, 0xA1, 0x00, 0x6D, 0xC9, 0x9E, 0x09, 0x4C, + 0x34, 0x6D, 0x27, 0x9B, 0x93, 0xCF, 0xF7, 0xAE}, + // C=US, O=GeoTrust Inc., CN=GeoTrust Universal CA 2 + {0xA0, 0x23, 0x4F, 0x3B, 0xC8, 0x52, 0x7C, 0xA5, 0x62, 0x8E, 0xEC, 0x81, + 0xAD, 0x5D, 0x69, 0x89, 0x5D, 0xA5, 0x68, 0x0D, 0xC9, 0x1D, 0x1C, 0xB8, + 0x47, 0x7F, 0x33, 0xF8, 0x78, 0xB9, 0x5B, 0x0B}, + // C=GR, L=Athens, O=Hellenic Academic and Research Institutions Cert. + // Authority, CN=Hellenic Academic and Research Institutions RootCA 2015 + {0xA0, 0x40, 0x92, 0x9A, 0x02, 0xCE, 0x53, 0xB4, 0xAC, 0xF4, 0xF2, 0xFF, + 0xC6, 0x98, 0x1C, 0xE4, 0x49, 0x6F, 0x75, 0x5E, 0x6D, 0x45, 0xFE, 0x0B, + 0x2A, 0x69, 0x2B, 0xCD, 0x52, 0x52, 0x3F, 0x36}, + // C=US, O=GeoTrust Inc., CN=GeoTrust Universal CA + {0xA0, 0x45, 0x9B, 0x9F, 0x63, 0xB2, 0x25, 0x59, 0xF5, 0xFA, 0x5D, 0x4C, + 0x6D, 0xB3, 0xF9, 0xF7, 0x2F, 0xF1, 0x93, 0x42, 0x03, 0x35, 0x78, 0xF0, + 0x73, 0xBF, 0x1D, 0x1B, 0x46, 0xCB, 0xB9, 0x12}, + // C=LU, O=LuxTrust s.a., CN=LuxTrust Global Root + {0xA1, 0xB2, 0xDB, 0xEB, 0x64, 0xE7, 0x06, 0xC6, 0x16, 0x9E, 0x3C, 0x41, + 0x18, 0xB2, 0x3B, 0xAA, 0x09, 0x01, 0x8A, 0x84, 0x27, 0x66, 0x6D, 0x8B, + 0xF0, 0xE2, 0x88, 0x91, 0xEC, 0x05, 0x19, 0x50}, + // C=CN, O=UniTrust, CN=UCA Global Root + {0xA1, 0xF0, 0x5C, 0xCB, 0x80, 0xC2, 0xD7, 0x10, 0xEC, 0x7D, 0x47, 0x9A, + 0xBD, 0xCB, 0xB8, 0x79, 0xE5, 0x8D, 0x7E, 0xDB, 0x71, 0x49, 0xFE, 0x78, + 0xA8, 0x78, 0x84, 0xE3, 0xD0, 0xBA, 0xD0, 0xF9}, + // C=JP, O=SECOM Trust Systems CO.,LTD., OU=Security Communication EV + // RootCA1 + {0xA2, 0x2D, 0xBA, 0x68, 0x1E, 0x97, 0x37, 0x6E, 0x2D, 0x39, 0x7D, 0x72, + 0x8A, 0xAE, 0x3A, 0x9B, 0x62, 0x96, 0xB9, 0xFD, 0xBA, 0x60, 0xBC, 0x2E, + 0x11, 0xF6, 0x47, 0xF2, 0xC6, 0x75, 0xFB, 0x37}, + // C=ch, O=admin, OU=Services, OU=Certification Authorities, + // CN=Admin-Root-CA + {0xA3, 0x1F, 0x09, 0x30, 0x53, 0xBD, 0x12, 0xC1, 0xF5, 0xC3, 0xC6, 0xEF, + 0xD4, 0x98, 0x02, 0x3F, 0xD2, 0x91, 0x4D, 0x77, 0x58, 0xD0, 0x5D, 0x69, + 0x8C, 0xE0, 0x84, 0xB5, 0x06, 0x26, 0xE0, 0xE5}, + // C=CH, O=The Federal Authorities of the Swiss Confederation, OU=Services, + // OU=Certification Authorities, CN=Swiss Government Root CA II + {0xA3, 0xD7, 0x43, 0x5A, 0x18, 0xC4, 0x6B, 0x23, 0xB6, 0xA4, 0xF8, 0x92, + 0x9C, 0xD5, 0x90, 0x50, 0xC9, 0x16, 0x8B, 0x03, 0xA7, 0xFA, 0xD5, 0x32, + 0x62, 0x6F, 0x29, 0x7C, 0xAC, 0x53, 0x56, 0xE4}, + // C=US, O=thawte, Inc., OU=(c) 2007 thawte, Inc. - For authorized use only, + // CN=thawte Primary Root CA - G2 + {0xA4, 0x31, 0x0D, 0x50, 0xAF, 0x18, 0xA6, 0x44, 0x71, 0x90, 0x37, 0x2A, + 0x86, 0xAF, 0xAF, 0x8B, 0x95, 0x1F, 0xFB, 0x43, 0x1D, 0x83, 0x7F, 0x1E, + 0x56, 0x88, 0xB4, 0x59, 0x71, 0xED, 0x15, 0x57}, + // C=BM, O=QuoVadis Limited, OU=Root Certification Authority, CN=QuoVadis + // Root Certification Authority + {0xA4, 0x5E, 0xDE, 0x3B, 0xBB, 0xF0, 0x9C, 0x8A, 0xE1, 0x5C, 0x72, 0xEF, + 0xC0, 0x72, 0x68, 0xD6, 0x93, 0xA2, 0x1C, 0x99, 0x6F, 0xD5, 0x1E, 0x67, + 0xCA, 0x07, 0x94, 0x60, 0xFD, 0x6D, 0x88, 0x73}, + // C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority + {0xA4, 0xB6, 0xB3, 0x99, 0x6F, 0xC2, 0xF3, 0x06, 0xB3, 0xFD, 0x86, 0x81, + 0xBD, 0x63, 0x41, 0x3D, 0x8C, 0x50, 0x09, 0xCC, 0x4F, 0xA3, 0x29, 0xC2, + 0xCC, 0xF0, 0xE2, 0xFA, 0x1B, 0x14, 0x03, 0x05}, + // C=US, O=GTE Corporation, OU=GTE CyberTrust Solutions, Inc., CN=GTE + // CyberTrust Global Root + {0xA5, 0x31, 0x25, 0x18, 0x8D, 0x21, 0x10, 0xAA, 0x96, 0x4B, 0x02, 0xC7, + 0xB7, 0xC6, 0xDA, 0x32, 0x03, 0x17, 0x08, 0x94, 0xE5, 0xFB, 0x71, 0xFF, + 0xFB, 0x66, 0x67, 0xD5, 0xE6, 0x81, 0x0A, 0x36}, + // C=US, O=Wells Fargo WellsSecure, OU=Wells Fargo Bank NA, CN=WellsSecure + // Public Root Certificate Authority + {0xA7, 0x12, 0x72, 0xAE, 0xAA, 0xA3, 0xCF, 0xE8, 0x72, 0x7F, 0x7F, 0xB3, + 0x9F, 0x0F, 0xB3, 0xD1, 0xE5, 0x42, 0x6E, 0x90, 0x60, 0xB0, 0x6E, 0xE6, + 0xF1, 0x3E, 0x9A, 0x3C, 0x58, 0x33, 0xCD, 0x43}, + // C=GR, O=Athens Exchange S.A., CN=ATHEX Root CA + {0xA7, 0x35, 0x63, 0xE8, 0x59, 0xCB, 0xCF, 0xA1, 0x73, 0xCF, 0x32, 0x85, + 0xDE, 0xBF, 0x25, 0x78, 0xED, 0xE1, 0x5D, 0x47, 0xA3, 0xBE, 0xE3, 0x85, + 0x86, 0x1A, 0xB7, 0xA4, 0xFB, 0x6D, 0x7B, 0x6E}, + // C=TN, O=ANCE, OU=ANCE WEB, CN=Agence Nationale de Certification + // Electronique/emailAddress=ance@certification.tn + {0xA7, 0x98, 0xA1, 0xC7, 0x0E, 0x9B, 0x6D, 0x50, 0xEA, 0xA5, 0x72, 0x4A, + 0x26, 0xFA, 0xC7, 0x99, 0x18, 0x48, 0xED, 0xC6, 0x1B, 0xF4, 0x8D, 0x79, + 0x81, 0x6B, 0xCA, 0xFB, 0x66, 0x97, 0x21, 0x28}, + // C=US, ST=DC, L=Washington, O=ABA.ECOM, INC., CN=ABA.ECOM Root + // CA/emailAddress=admin@digsigtrust.com + {0xA9, 0xA9, 0xCA, 0x22, 0x89, 0x0D, 0x69, 0x49, 0x19, 0xC0, 0x95, 0xBB, + 0x80, 0x64, 0xCB, 0xC4, 0xA5, 0x25, 0xA5, 0xDB, 0xFA, 0xF8, 0x01, 0xEC, + 0x93, 0x5D, 0xBC, 0xCC, 0x07, 0xC8, 0xBA, 0xEE}, + // C=my, O=TM, OU=TM Applied Business Certification Authority, CN=TM Applied + // Business Root Certificate + {0xA9, 0xC7, 0x7A, 0xF1, 0xBC, 0xDF, 0xAA, 0x37, 0x39, 0x44, 0x2B, 0x0B, + 0x27, 0x34, 0xC6, 0x8E, 0xAF, 0x2E, 0x98, 0x33, 0xF0, 0xD7, 0x66, 0xFB, + 0xCA, 0xA6, 0xF2, 0xAE, 0xB4, 0x2D, 0xEC, 0x02}, + // C=LV, O=VAS Latvijas Pasts - Vien.reg.Nr.40003052790, OU=Sertifikacijas + // pakalpojumi, CN=VAS Latvijas Pasts SSI(RCA) + {0xAA, 0xD9, 0xCE, 0xED, 0x5A, 0xA6, 0xB1, 0xCE, 0xA2, 0x85, 0x96, 0xA8, + 0xE4, 0xE1, 0xAB, 0xED, 0x93, 0x86, 0xD6, 0xEB, 0xC9, 0xD4, 0xAA, 0xD9, + 0xAC, 0xDE, 0x0F, 0xA3, 0x6B, 0xA0, 0x69, 0xD0}, + // C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, + // OU=Certification Services Division, CN=Thawte Premium Server + // CA/emailAddress=premium-server@thawte.com + {0xAB, 0x70, 0x36, 0x36, 0x5C, 0x71, 0x54, 0xAA, 0x29, 0xC2, 0xC2, 0x9F, + 0x5D, 0x41, 0x91, 0x16, 0x3B, 0x16, 0x2A, 0x22, 0x25, 0x01, 0x13, 0x57, + 0xD5, 0x6D, 0x07, 0xFF, 0xA7, 0xBC, 0x1F, 0x72}, + // C=CZ, O=\xC4\x8Cesk\xC3\xA1 po\xC5\xA1ta, s.p. [I\xC4\x8C 47114983], + // CN=PostSignum Root QCA 2 + {0xAD, 0x01, 0x6F, 0x95, 0x80, 0x50, 0xE0, 0xE7, 0xE4, 0x6F, 0xAE, 0x7D, + 0xCC, 0x50, 0x19, 0x7E, 0xD8, 0xE3, 0xFF, 0x0A, 0x4B, 0x26, 0x2E, 0x5D, + 0xDC, 0xDB, 0x3E, 0xDD, 0xDC, 0x7D, 0x65, 0x78}, + // C=US, O=Wells Fargo WellsSecure, OU=Wells Fargo Bank NA, CN=WellsSecure + // Public Root Certification Authority 01 G2 + {0xAD, 0x75, 0x39, 0xE5, 0xCD, 0xC9, 0x85, 0xFA, 0x95, 0x24, 0x40, 0x55, + 0xA9, 0x20, 0x2D, 0x63, 0x46, 0x0E, 0xC9, 0x21, 0x46, 0x7D, 0x03, 0x4C, + 0xFD, 0xBE, 0x87, 0xEC, 0x6D, 0x00, 0xFE, 0xDC}, + // C=AT, O=A-Trust, OU=A-Trust-nQual-01, CN=A-Trust-nQual-01 + {0xAE, 0x2F, 0xEC, 0x82, 0x91, 0x18, 0xA2, 0x45, 0x5A, 0xD6, 0xA4, 0x15, + 0xE7, 0x18, 0x23, 0xEB, 0x9B, 0x7B, 0x6E, 0x35, 0x78, 0xA5, 0x1A, 0xC8, + 0xA5, 0x14, 0x46, 0xEA, 0xDB, 0xB0, 0x97, 0x9C}, + // CN=ComSign CA, O=ComSign, C=IL + {0xAE, 0x44, 0x57, 0xB4, 0x0D, 0x9E, 0xDA, 0x96, 0x67, 0x7B, 0x0D, 0x3C, + 0x92, 0xD5, 0x7B, 0x51, 0x77, 0xAB, 0xD7, 0xAC, 0x10, 0x37, 0x95, 0x83, + 0x56, 0xD1, 0xE0, 0x94, 0x51, 0x8B, 0xE5, 0xF2}, + // C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA3 + {0xAE, 0x92, 0xE9, 0x00, 0x00, 0x54, 0x1A, 0x9E, 0xBC, 0x10, 0x1B, 0x70, + 0xB6, 0xC3, 0x3A, 0x62, 0xF5, 0xA5, 0x3A, 0x55, 0xBA, 0x81, 0x5E, 0x81, + 0xD3, 0x1A, 0xBD, 0xDF, 0x03, 0x50, 0x7F, 0x5D}, + // C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA2 + {0xAF, 0x6D, 0x08, 0xEE, 0xF3, 0xCA, 0xC4, 0xE1, 0x58, 0x4A, 0xBC, 0x63, + 0xC8, 0xA9, 0x47, 0x2A, 0xC5, 0x29, 0xAF, 0x99, 0xF3, 0xF7, 0x91, 0x31, + 0x9A, 0x43, 0x77, 0x60, 0x63, 0xF5, 0x8D, 0xCA}, + // L=Bogota AV Calle 26 N 68D-35, C=CO, O=Entidad de Certificacion Digital + // Abierta Certicamara S.A., CN=CERTICAMARA S.A. + {0xAF, 0x71, 0xA3, 0xBC, 0xA3, 0x22, 0xE5, 0x22, 0x4D, 0xF5, 0x46, 0x89, + 0x56, 0x96, 0xCE, 0x44, 0x9A, 0x8B, 0xD2, 0xBD, 0x13, 0x0F, 0x7A, 0x7A, + 0xE4, 0x57, 0x76, 0x7F, 0x5C, 0x23, 0xD8, 0xF8}, + // O=RSA Security Inc, OU=RSA Security 2048 V3 + {0xAF, 0x8B, 0x67, 0x62, 0xA1, 0xE5, 0x28, 0x22, 0x81, 0x61, 0xA9, 0x5D, + 0x5C, 0x55, 0x9E, 0xE2, 0x66, 0x27, 0x8F, 0x75, 0xD7, 0x9E, 0x83, 0x01, + 0x89, 0xA5, 0x03, 0x50, 0x6A, 0xBD, 0x6B, 0x4C}, + // C=IT, L=Milano, O=Actalis S.p.A./03358520967, CN=Actalis Authentication + // CA G1 + {0xAF, 0xE8, 0x0A, 0x97, 0xEA, 0x11, 0x15, 0x91, 0x90, 0xE9, 0x27, 0xE0, + 0x8E, 0xC2, 0xE6, 0x0C, 0x59, 0xA4, 0x05, 0x59, 0x48, 0x3A, 0x3F, 0xEE, + 0x83, 0x8A, 0x85, 0x32, 0x1B, 0x3A, 0xEA, 0xAD}, + // O=eSign Australia, OU=Public Secure Services, CN=Primary Utility Root CA + {0xB0, 0x4D, 0x70, 0x8F, 0x1A, 0xE0, 0x45, 0x62, 0x65, 0xDD, 0x1B, 0x66, + 0x90, 0x7A, 0x26, 0x91, 0xA2, 0x86, 0x80, 0xB8, 0x53, 0xE0, 0x31, 0xDF, + 0x3D, 0xF9, 0x08, 0x3A, 0xF7, 0x16, 0x14, 0xD7}, + // C=ES, O=IZENPE S.A. - CIF A-01337260-RMerc.Vitoria-Gasteiz T1055 F62 S8, + // L=Avda del Mediterraneo Etorbidea 3 - 01010 Vitoria-Gasteiz, + // CN=Izenpe.com/emailAddress=Info@izenpe.com + {0xB0, 0x87, 0x7A, 0xEE, 0x2D, 0x39, 0x27, 0x4D, 0xF8, 0x31, 0xF6, 0x6F, + 0xDE, 0xEB, 0x77, 0x17, 0x55, 0x7C, 0x25, 0x8F, 0xC9, 0xEB, 0x55, 0x23, + 0x1A, 0x9F, 0x8A, 0x64, 0x7A, 0x75, 0x43, 0x3F}, + // C=TR, L=Ankara, O=E-Tu\xC4\x9Fra EBG Bili\xC5\x9Fim Teknolojileri ve + // Hizmetleri A.\xC5\x9E., OU=E-Tugra Sertifikasyon Merkezi, CN=E-Tugra + // Certification Authority + {0xB0, 0xBF, 0xD5, 0x2B, 0xB0, 0xD7, 0xD9, 0xBD, 0x92, 0xBF, 0x5D, 0x4D, + 0xC1, 0x3D, 0xA2, 0x55, 0xC0, 0x2C, 0x54, 0x2F, 0x37, 0x83, 0x65, 0xEA, + 0x89, 0x39, 0x11, 0xF5, 0x5E, 0x55, 0xF2, 0x3C}, + // C=FR, O=NATIXIS, OU=0002 542044524, CN=CESAM + {0xB2, 0x25, 0x99, 0x96, 0xFF, 0xF7, 0x35, 0xAB, 0x35, 0x01, 0x4E, 0xF6, + 0x3F, 0x3D, 0x41, 0x31, 0x90, 0x07, 0x9D, 0xD0, 0x3A, 0x09, 0x62, 0x43, + 0x26, 0x35, 0xA8, 0x69, 0x5F, 0x99, 0x53, 0x05}, + // C=SE, O=Carelink, CN=SITHS CA v3 + {0xB2, 0xF3, 0xC4, 0x21, 0x6A, 0xF7, 0xAF, 0xF7, 0x24, 0x62, 0x46, 0x6D, + 0xC1, 0x3C, 0xD2, 0x81, 0x0D, 0xB8, 0xEE, 0xD8, 0x53, 0xEA, 0xBB, 0x9A, + 0x06, 0x3A, 0x60, 0x8E, 0xFC, 0x18, 0xFB, 0xE8}, + // C=US, O=Symantec Corporation, OU=Symantec Trust Network, CN=Symantec + // Class 3 Public Primary Certification Authority - G6 + {0xB3, 0x23, 0x96, 0x74, 0x64, 0x53, 0x44, 0x2F, 0x35, 0x3E, 0x61, 0x62, + 0x92, 0xBB, 0x20, 0xBB, 0xAA, 0x5D, 0x23, 0xB5, 0x46, 0x45, 0x0F, 0xDB, + 0x9C, 0x54, 0xB8, 0x38, 0x61, 0x67, 0xD5, 0x29}, + // C=au, O=SecureNet CA Class B + {0xB3, 0xC9, 0x62, 0xD3, 0x40, 0x19, 0xFB, 0x38, 0xAB, 0x9F, 0xE9, 0xC6, + 0x23, 0x99, 0x74, 0x2A, 0xB2, 0x6C, 0x43, 0xC2, 0xD1, 0x8C, 0xE3, 0xF2, + 0xB1, 0x3C, 0x14, 0x32, 0x1E, 0x52, 0x96, 0x4B}, + // x500UniqueIdentifier=SEC-830101-9V9, L=Alvaro Obregon, ST=Distrito + // Federal, C=MX/postalCode=01030/street=Insurgentes Sur 1940, CN=Autoridad + // Certificadora Raiz de la Secretaria de Economia, OU=Direccion General de + // Normatividad Mercantil, O=Secretaria de + // Economia/emailAddress=acrse@economia.gob.mx + {0xB4, 0x1D, 0x51, 0x6A, 0x53, 0x51, 0xD4, 0x2D, 0xEE, 0xA1, 0x91, 0xFA, + 0x6E, 0xDF, 0x2A, 0x67, 0xDE, 0xE2, 0xF3, 0x6D, 0xC9, 0x69, 0x01, 0x2C, + 0x76, 0x66, 0x9E, 0x61, 0x6B, 0x90, 0x0D, 0xDF}, + // C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, + // OU=Certification Services Division, CN=Thawte Server + // CA/emailAddress=server-certs@thawte.com + {0xB4, 0x41, 0x0B, 0x73, 0xE2, 0xE6, 0xEA, 0xCA, 0x47, 0xFB, 0xC4, 0x2F, + 0x8F, 0xA4, 0x01, 0x8A, 0xF4, 0x38, 0x1D, 0xC5, 0x4C, 0xFA, 0xA8, 0x44, + 0x50, 0x46, 0x1E, 0xED, 0x09, 0x45, 0x4D, 0xE9}, + // C=US, O=GeoTrust Inc., OU=(c) 2008 GeoTrust Inc. - For authorized use + // only, CN=GeoTrust Primary Certification Authority - G3 + {0xB4, 0x78, 0xB8, 0x12, 0x25, 0x0D, 0xF8, 0x78, 0x63, 0x5C, 0x2A, 0xA7, + 0xEC, 0x7D, 0x15, 0x5E, 0xAA, 0x62, 0x5E, 0xE8, 0x29, 0x16, 0xE2, 0xCD, + 0x29, 0x43, 0x61, 0x88, 0x6C, 0xD1, 0xFB, 0xD4}, + // C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, Inc., + // OU=http://certificates.starfieldtech.com/repository/, CN=Starfield + // Services Root Certificate Authority + {0xB5, 0xBD, 0x2C, 0xB7, 0x9C, 0xBD, 0x19, 0x07, 0x29, 0x8D, 0x6B, 0xDF, + 0x48, 0x42, 0xE5, 0x16, 0xD8, 0xC7, 0x8F, 0xA6, 0xFC, 0x96, 0xD2, 0x5F, + 0x71, 0xAF, 0x81, 0x4E, 0x16, 0xCC, 0x24, 0x5E}, + // C=DE, O=Deutsche Telekom AG, OU=T-TeleSec Trust Center, CN=Deutsche + // Telekom Root CA 2 + {0xB6, 0x19, 0x1A, 0x50, 0xD0, 0xC3, 0x97, 0x7F, 0x7D, 0xA9, 0x9B, 0xCD, + 0xAA, 0xC8, 0x6A, 0x22, 0x7D, 0xAE, 0xB9, 0x67, 0x9E, 0xC7, 0x0B, 0xA3, + 0xB0, 0xC9, 0xD9, 0x22, 0x71, 0xC1, 0x70, 0xD3}, + // C=ES, ST=Barcelona, L=Barcelona (see current address at + // https://www.anf.es/address/), O=ANF Autoridad de Certificaci\xC3\xB3n, + // OU=ANF Clase 1 CA/serialNumber=G63287510, CN=ANF Server CA + {0xB6, 0x44, 0xD9, 0x55, 0xFF, 0xF2, 0x9B, 0x74, 0xE3, 0xB5, 0x68, 0x7E, + 0x90, 0x8E, 0xE7, 0xC3, 0xC9, 0x19, 0x7B, 0xA3, 0x33, 0x6C, 0xC6, 0x32, + 0x85, 0x31, 0xF6, 0xC0, 0x57, 0xD6, 0x77, 0xFD}, + // C=NO, O=Buypass AS-983163327, CN=Buypass Class 3 CA 1 + {0xB7, 0xB1, 0x2B, 0x17, 0x1F, 0x82, 0x1D, 0xAA, 0x99, 0x0C, 0xD0, 0xFE, + 0x50, 0x87, 0xB1, 0x28, 0x44, 0x8B, 0xA8, 0xE5, 0x18, 0x4F, 0x84, 0xC5, + 0x1E, 0x02, 0xB5, 0xC8, 0xFB, 0x96, 0x2B, 0x24}, + // C=FR, O=OpenTrust, CN=OpenTrust Root CA G3 + {0xB7, 0xC3, 0x62, 0x31, 0x70, 0x6E, 0x81, 0x07, 0x8C, 0x36, 0x7C, 0xB8, + 0x96, 0x19, 0x8F, 0x1E, 0x32, 0x08, 0xDD, 0x92, 0x69, 0x49, 0xDD, 0x8F, + 0x57, 0x09, 0xA4, 0x10, 0xF7, 0x5B, 0x62, 0x92}, + // C=MO, O=Macao Post, CN=Macao Post eSignTrust Root Certification Authority + {0xB8, 0xBB, 0xE5, 0x23, 0xBF, 0xCA, 0x3B, 0x11, 0xD5, 0x0F, 0x73, 0xF7, + 0xF1, 0x0B, 0x3E, 0xC8, 0xEC, 0x95, 0x8A, 0xA1, 0xDC, 0x86, 0xF6, 0x6D, + 0x95, 0x41, 0x90, 0x7F, 0xF1, 0xA1, 0x10, 0xEF}, + // C=FR, ST=France, L=Paris, O=PM/SGDN, OU=DCSSI, + // CN=IGC/A/emailAddress=igca@sgdn.pm.gouv.fr + {0xB9, 0xBE, 0xA7, 0x86, 0x0A, 0x96, 0x2E, 0xA3, 0x61, 0x1D, 0xAB, 0x97, + 0xAB, 0x6D, 0xA3, 0xE2, 0x1C, 0x10, 0x68, 0xB9, 0x7D, 0x55, 0x57, 0x5E, + 0xD0, 0xE1, 0x12, 0x79, 0xC1, 0x1C, 0x89, 0x32}, + // C=GR, O=Hellenic Academic and Research Institutions Cert. Authority, + // CN=Hellenic Academic and Research Institutions RootCA 2011 + {0xBC, 0x10, 0x4F, 0x15, 0xA4, 0x8B, 0xE7, 0x09, 0xDC, 0xA5, 0x42, 0xA7, + 0xE1, 0xD4, 0xB9, 0xDF, 0x6F, 0x05, 0x45, 0x27, 0xE8, 0x02, 0xEA, 0xA9, + 0x2D, 0x59, 0x54, 0x44, 0x25, 0x8A, 0xFE, 0x71}, + // L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 3 + // Policy Validation Authority, + // CN=http://www.valicert.com//emailAddress=info@valicert.com + {0xBC, 0x23, 0xF9, 0x8A, 0x31, 0x3C, 0xB9, 0x2D, 0xE3, 0xBB, 0xFC, 0x3A, + 0x5A, 0x9F, 0x44, 0x61, 0xAC, 0x39, 0x49, 0x4C, 0x4A, 0xE1, 0x5A, 0x9E, + 0x9D, 0xF1, 0x31, 0xE9, 0x9B, 0x73, 0x01, 0x9A}, + // C=HK, O=Hongkong Post, CN=Hongkong Post Root CA + {0xBC, 0xDD, 0x8D, 0xF4, 0x27, 0x63, 0x66, 0xD7, 0xFF, 0x4B, 0x68, 0x8D, + 0xC8, 0x15, 0x00, 0xD8, 0xE9, 0x82, 0x52, 0xC0, 0x49, 0xC8, 0xFF, 0x1E, + 0x8C, 0x82, 0xF2, 0xBA, 0xEC, 0x9D, 0x5C, 0x16}, + // C=US, O=AffirmTrust, CN=AffirmTrust Premium ECC + {0xBD, 0x71, 0xFD, 0xF6, 0xDA, 0x97, 0xE4, 0xCF, 0x62, 0xD1, 0x64, 0x7A, + 0xDD, 0x25, 0x81, 0xB0, 0x7D, 0x79, 0xAD, 0xF8, 0x39, 0x7E, 0xB4, 0xEC, + 0xBA, 0x9C, 0x5E, 0x84, 0x88, 0x82, 0x14, 0x23}, + // C=CH, O=SwissSign AG, CN=SwissSign Silver CA - G2 + {0xBE, 0x6C, 0x4D, 0xA2, 0xBB, 0xB9, 0xBA, 0x59, 0xB6, 0xF3, 0x93, 0x97, + 0x68, 0x37, 0x42, 0x46, 0xC3, 0xC0, 0x05, 0x99, 0x3F, 0xA9, 0x8F, 0x02, + 0x0D, 0x1D, 0xED, 0xBE, 0xD4, 0x8A, 0x81, 0xD5}, + // OU=GlobalSign ECC Root CA - R4, O=GlobalSign, CN=GlobalSign + {0xBE, 0xC9, 0x49, 0x11, 0xC2, 0x95, 0x56, 0x76, 0xDB, 0x6C, 0x0A, 0x55, + 0x09, 0x86, 0xD7, 0x6E, 0x3B, 0xA0, 0x05, 0x66, 0x7C, 0x44, 0x2C, 0x97, + 0x62, 0xB4, 0xFB, 0xB7, 0x73, 0xDE, 0x22, 0x8C}, + // C=JP, O=Japan Certification Services, Inc., CN=SecureSign RootCA11 + {0xBF, 0x0F, 0xEE, 0xFB, 0x9E, 0x3A, 0x58, 0x1A, 0xD5, 0xF9, 0xE9, 0xDB, + 0x75, 0x89, 0x98, 0x57, 0x43, 0xD2, 0x61, 0x08, 0x5C, 0x4D, 0x31, 0x4F, + 0x6F, 0x5D, 0x72, 0x59, 0xAA, 0x42, 0x16, 0x12}, + // C=TW, O=TAIWAN-CA, OU=Root CA, CN=TWCA Root Certification Authority + {0xBF, 0xD8, 0x8F, 0xE1, 0x10, 0x1C, 0x41, 0xAE, 0x3E, 0x80, 0x1B, 0xF8, + 0xBE, 0x56, 0x35, 0x0E, 0xE9, 0xBA, 0xD1, 0xA6, 0xB9, 0xBD, 0x51, 0x5E, + 0xDC, 0x5C, 0x6D, 0x5B, 0x87, 0x11, 0xAC, 0x44}, + // C=CN, O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD., CN=GDCA TrustAUTH R5 + // ROOT + {0xBF, 0xFF, 0x8F, 0xD0, 0x44, 0x33, 0x48, 0x7D, 0x6A, 0x8A, 0xA6, 0x0C, + 0x1A, 0x29, 0x76, 0x7A, 0x9F, 0xC2, 0xBB, 0xB0, 0x5E, 0x42, 0x0F, 0x71, + 0x3A, 0x13, 0xB9, 0x92, 0x89, 0x1D, 0x38, 0x93}, + // C=TW, O=Chunghwa Telecom Co., Ltd., OU=ePKI Root Certification Authority + {0xC0, 0xA6, 0xF4, 0xDC, 0x63, 0xA2, 0x4B, 0xFD, 0xCF, 0x54, 0xEF, 0x2A, + 0x6A, 0x08, 0x2A, 0x0A, 0x72, 0xDE, 0x35, 0x80, 0x3E, 0x2F, 0xF5, 0xFF, + 0x52, 0x7A, 0xE5, 0xD8, 0x72, 0x06, 0xDF, 0xD5}, + // C=CL, ST=Region Metropolitana, L=Santiago, O=E-CERTCHILE, OU=Autoridad + // Certificadora/emailAddress=sclientes@ccs.cl, CN=E-CERT ROOT CA + {0xC1, 0x09, 0xE0, 0xD1, 0xB6, 0x40, 0x00, 0xB0, 0x1E, 0x89, 0x4B, 0xDA, + 0xA9, 0x55, 0xE1, 0xFF, 0x91, 0xB6, 0xD0, 0x84, 0xA8, 0x38, 0xD9, 0x0E, + 0x04, 0x4B, 0x9E, 0x3F, 0xCD, 0x2A, 0x8B, 0xFA}, + // C=FR, O=Certplus, CN=Class 3 Primary CA + {0xC1, 0xB1, 0x2F, 0x48, 0x00, 0x20, 0x33, 0x6E, 0x5B, 0x04, 0xF5, 0x20, + 0xBC, 0x19, 0xC2, 0xE2, 0xE1, 0x0A, 0xB4, 0x2C, 0x9D, 0x92, 0x35, 0xF0, + 0x5C, 0xBE, 0xC3, 0x3F, 0xFA, 0x4D, 0x4D, 0xEA}, + // C=GB, O=Trustis Limited, OU=Trustis FPS Root CA + {0xC1, 0xB4, 0x82, 0x99, 0xAB, 0xA5, 0x20, 0x8F, 0xE9, 0x63, 0x0A, 0xCE, + 0x55, 0xCA, 0x68, 0xA0, 0x3E, 0xDA, 0x5A, 0x51, 0x9C, 0x88, 0x02, 0xA0, + 0xD3, 0xA6, 0x73, 0xBE, 0x8F, 0x8E, 0x55, 0x7D}, + // C=ES, L=C/ Muntaner 244 Barcelona, CN=Autoridad de Certificacion + // Firmaprofesional CIF A62634068/emailAddress=ca@firmaprofesional.com + {0xC1, 0xCF, 0x0B, 0x52, 0x09, 0x64, 0x35, 0xE3, 0xF1, 0xB7, 0x1D, 0xAA, + 0xEC, 0x45, 0x5A, 0x23, 0x11, 0xC8, 0x40, 0x4F, 0x55, 0x83, 0xA9, 0xE2, + 0x13, 0xC6, 0x9D, 0x85, 0x7D, 0x94, 0x33, 0x05}, + // C=HU, L=Budapest, O=NISZ Nemzeti Infokommunik\xC3\xA1ci\xC3\xB3s + // Szolg\xC3\xA1ltat\xC3\xB3 Zrt., + // CN=F\xC5\x91tan\xC3\xBAs\xC3\xADtv\xC3\xA1nykiad\xC3\xB3 - + // Korm\xC3\xA1nyzati Hiteles\xC3\xADt\xC3\xA9s Szolg\xC3\xA1ltat\xC3\xB3 + {0xC2, 0x15, 0x73, 0x09, 0xD9, 0xAE, 0xE1, 0x7B, 0xF3, 0x4F, 0x4D, 0xF5, + 0xE8, 0x8D, 0xBA, 0xEB, 0xA5, 0x7E, 0x03, 0x61, 0xEB, 0x81, 0x4C, 0xBC, + 0x23, 0x9F, 0x4D, 0x54, 0xD3, 0x29, 0xA3, 0x8D}, + // C=CO, L=Carrera 9 16-21 Bogota, O=Certicamara S.A. Entidad de + // Certificacion, CN=Certificado Empresarial Clase-A + {0xC2, 0x95, 0x9D, 0xB8, 0x33, 0x9E, 0x8D, 0xBC, 0xF6, 0x40, 0x9C, 0xA9, + 0x2A, 0x66, 0xC4, 0x9F, 0xD2, 0xE3, 0x24, 0x94, 0x94, 0x0A, 0x90, 0x11, + 0x43, 0xBD, 0x7E, 0xB7, 0x28, 0x27, 0xDE, 0xC2}, + // C=LT, O=Skaitmeninio sertifikavimo centras, OU=CA ROOT Services, CN=SSC + // GDL CA Root B + {0xC3, 0x1E, 0xEF, 0x56, 0x82, 0xAB, 0xB5, 0x51, 0xEB, 0xC8, 0x28, 0xDE, + 0xD8, 0x40, 0x98, 0x51, 0x8A, 0x67, 0x68, 0x52, 0x6D, 0x15, 0x2E, 0xE1, + 0x64, 0xCF, 0xB9, 0x72, 0xA1, 0x42, 0x5D, 0x53}, + // C=IN, O=India PKI, CN=CCA India 2015 SPL + {0xC3, 0x4C, 0x5D, 0xF5, 0x30, 0x80, 0x07, 0x8F, 0xFE, 0x45, 0xB2, 0x1A, + 0x7F, 0x60, 0x04, 0x69, 0x91, 0x72, 0x04, 0xF4, 0xF0, 0x29, 0x3F, 0x1D, + 0x72, 0x09, 0x39, 0x3E, 0x52, 0x65, 0xC0, 0x4F}, + // C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification + // Authority + {0xC3, 0x84, 0x6B, 0xF2, 0x4B, 0x9E, 0x93, 0xCA, 0x64, 0x27, 0x4C, 0x0E, + 0xC6, 0x7C, 0x1E, 0xCC, 0x5E, 0x02, 0x4F, 0xFC, 0xAC, 0xD2, 0xD7, 0x40, + 0x19, 0x35, 0x0E, 0x81, 0xFE, 0x54, 0x6A, 0xE4}, + // C=US, ST=UT, L=Salt Lake City, O=The USERTRUST Network, + // OU=http://www.usertrust.com, CN=UTN-USERFirst-Network Applications + {0xC3, 0x8D, 0xCB, 0x38, 0x95, 0x93, 0x93, 0x35, 0x86, 0x91, 0xEA, 0x4D, + 0x4F, 0x3C, 0xE4, 0x95, 0xCE, 0x74, 0x89, 0x96, 0xE6, 0x4E, 0xD1, 0x89, + 0x1D, 0x89, 0x7A, 0x0F, 0xC4, 0xDD, 0x55, 0xC6}, + // CN=T\xC3\x9CRKTRUST Elektronik Sertifika Hizmet + // Sa\xC4\x9Flay\xC4\xB1c\xC4\xB1s\xC4\xB1, C=TR, L=Ankara, + // O=T\xC3\x9CRKTRUST Bilgi \xC4\xB0leti\xC5\x9Fim ve Bili\xC5\x9Fim + // G\xC3\xBCvenli\xC4\x9Fi Hizmetleri A.\xC5\x9E. (c) Kas\xC4\xB1m 2005 + {0xC4, 0x70, 0xCF, 0x54, 0x7E, 0x23, 0x02, 0xB9, 0x77, 0xFB, 0x29, 0xDD, + 0x71, 0xA8, 0x9A, 0x7B, 0x6C, 0x1F, 0x60, 0x77, 0x7B, 0x03, 0x29, 0xF5, + 0x60, 0x17, 0xF3, 0x28, 0xBF, 0x4F, 0x6B, 0xE6}, + // CN=T\xC3\x9CRKTRUST Elektronik \xC4\xB0\xC5\x9Flem Hizmetleri, C=TR, + // L=ANKARA, O=(c) 2005 T\xC3\x9CRKTRUST Bilgi \xC4\xB0leti\xC5\x9Fim ve + // Bili\xC5\x9Fim G\xC3\xBCvenli\xC4\x9Fi Hizmetleri A.\xC5\x9E. + {0xC4, 0x99, 0xF6, 0xCE, 0xCC, 0x5D, 0xA4, 0xD6, 0x1F, 0x14, 0xED, 0x04, + 0x05, 0x27, 0x0C, 0x52, 0x49, 0xD0, 0xE7, 0x96, 0x15, 0xB0, 0xDA, 0x42, + 0x65, 0x9E, 0xD2, 0xD7, 0xFF, 0xEF, 0x8A, 0x40}, + // C=US, O=VISA, OU=Visa International Service Association, CN=Visa + // Information Delivery Root CA + {0xC5, 0x7A, 0x3A, 0xCB, 0xE8, 0xC0, 0x6B, 0xA1, 0x98, 0x8A, 0x83, 0x48, + 0x5B, 0xF3, 0x26, 0xF2, 0x44, 0x87, 0x75, 0x37, 0x98, 0x49, 0xDE, 0x01, + 0xCA, 0x43, 0x57, 0x1A, 0xF3, 0x57, 0xE7, 0x4B}, + // C=IL, O=StartCom Ltd., OU=Secure Digital Certificate Signing, CN=StartCom + // Certification Authority + {0xC7, 0x66, 0xA9, 0xBE, 0xF2, 0xD4, 0x07, 0x1C, 0x86, 0x3A, 0x31, 0xAA, + 0x49, 0x20, 0xE8, 0x13, 0xB2, 0xD1, 0x98, 0x60, 0x8C, 0xB7, 0xB7, 0xCF, + 0xE2, 0x11, 0x43, 0xB8, 0x36, 0xDF, 0x09, 0xEA}, + // C=TN, CN=Tunisian Root Certificate Authority - TunRootCA2, O=National + // Digital Certification Agency + {0xC7, 0x95, 0xFF, 0x8F, 0xF2, 0x0C, 0x96, 0x66, 0x88, 0xF0, 0x64, 0xA1, + 0xE0, 0x91, 0x42, 0x1D, 0x31, 0x10, 0xA3, 0x45, 0x6C, 0x17, 0xEC, 0x24, + 0x04, 0xB9, 0x98, 0x73, 0x87, 0x41, 0xF6, 0x22}, + // C=IL, O=StartCom Ltd., CN=StartCom Certification Authority G2 + {0xC7, 0xBA, 0x65, 0x67, 0xDE, 0x93, 0xA7, 0x98, 0xAE, 0x1F, 0xAA, 0x79, + 0x1E, 0x71, 0x2D, 0x37, 0x8F, 0xAE, 0x1F, 0x93, 0xC4, 0x39, 0x7F, 0xEA, + 0x44, 0x1B, 0xB7, 0xCB, 0xE6, 0xFD, 0x59, 0x95}, + // C=US, O=GeoTrust Inc., CN=GeoTrust Global CA 2 + {0xCA, 0x2D, 0x82, 0xA0, 0x86, 0x77, 0x07, 0x2F, 0x8A, 0xB6, 0x76, 0x4F, + 0xF0, 0x35, 0x67, 0x6C, 0xFE, 0x3E, 0x5E, 0x32, 0x5E, 0x01, 0x21, 0x72, + 0xDF, 0x3F, 0x92, 0x09, 0x6D, 0xB7, 0x9B, 0x85}, + // OU=GlobalSign Root CA - R2, O=GlobalSign, CN=GlobalSign + {0xCA, 0x42, 0xDD, 0x41, 0x74, 0x5F, 0xD0, 0xB8, 0x1E, 0xB9, 0x02, 0x36, + 0x2C, 0xF9, 0xD8, 0xBF, 0x71, 0x9D, 0xA1, 0xBD, 0x1B, 0x1E, 0xFC, 0x94, + 0x6F, 0x5B, 0x4C, 0x99, 0xF4, 0x2C, 0x1B, 0x9E}, + // CN=Autoridad de Certificacion Raiz del Estado Venezolano, C=VE, + // L=Caracas, ST=Distrito Capital, O=Sistema Nacional de Certificacion + // Electronica, OU=Superintendencia de Servicios de Certificacion + // Electronica/emailAddress=acraiz@suscerte.gob.ve + {0xCA, 0x7A, 0x5E, 0x68, 0xC5, 0x3D, 0x2C, 0x51, 0xF7, 0x2F, 0x6B, 0x46, + 0x5D, 0x3E, 0xD7, 0x53, 0xF5, 0x90, 0x3E, 0xC7, 0x90, 0x1C, 0x8D, 0x0F, + 0x55, 0xD8, 0x68, 0x33, 0x7C, 0x81, 0x97, 0x5A}, + // C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root G2 + {0xCB, 0x3C, 0xCB, 0xB7, 0x60, 0x31, 0xE5, 0xE0, 0x13, 0x8F, 0x8D, 0xD3, + 0x9A, 0x23, 0xF9, 0xDE, 0x47, 0xFF, 0xC3, 0x5E, 0x43, 0xC1, 0x14, 0x4C, + 0xEA, 0x27, 0xD4, 0x6A, 0x5A, 0xB1, 0xCB, 0x5F}, + // OU=GlobalSign Root CA - R3, O=GlobalSign, CN=GlobalSign + {0xCB, 0xB5, 0x22, 0xD7, 0xB7, 0xF1, 0x27, 0xAD, 0x6A, 0x01, 0x13, 0x86, + 0x5B, 0xDF, 0x1C, 0xD4, 0x10, 0x2E, 0x7D, 0x07, 0x59, 0xAF, 0x63, 0x5A, + 0x7C, 0xF4, 0x72, 0x0D, 0xC9, 0x63, 0xC5, 0x3B}, + // C=BR, O=ICP-Brasil, OU=Instituto Nacional de Tecnologia da Informacao - + // ITI, CN=Autoridade Certificadora Raiz Brasileira v1 + {0xCB, 0xD8, 0xED, 0x38, 0xD4, 0xA2, 0xD6, 0x77, 0xD4, 0x53, 0xD7, 0x0D, + 0xD8, 0x89, 0x0A, 0xF4, 0xF6, 0x37, 0x4C, 0xBA, 0x62, 0x99, 0x94, 0x3F, + 0x1A, 0xB3, 0xA6, 0x93, 0x6C, 0x6F, 0xD7, 0x95}, + // C=FR, O=Certplus, CN=Class 3P Primary CA + {0xCC, 0xC8, 0x94, 0x89, 0x37, 0x1B, 0xAD, 0x11, 0x1C, 0x90, 0x61, 0x9B, + 0xEA, 0x24, 0x0A, 0x2E, 0x6D, 0xAD, 0xD9, 0x9F, 0x9F, 0x6E, 0x1D, 0x4D, + 0x41, 0xE5, 0x8E, 0xD6, 0xDE, 0x3D, 0x02, 0x85}, + // C=LV, OU=Sertifikacijas pakalpojumu dala, CN=E-ME SSI (RCA) + {0xCD, 0x0B, 0x3B, 0x2A, 0xA1, 0x74, 0xB5, 0x5F, 0x18, 0xC7, 0x50, 0x2F, + 0x3C, 0x3A, 0x76, 0xF2, 0x19, 0x81, 0x75, 0xCE, 0x45, 0x63, 0x73, 0x70, + 0xCF, 0x4F, 0x48, 0xB9, 0xC2, 0xCE, 0x4F, 0xBF}, + // DC=rs, DC=posta, DC=ca, CN=Configuration, CN=Services, CN=Public Key + // Services, CN=AIA, CN=Posta CA Root + {0xCD, 0x20, 0x12, 0x56, 0xFE, 0x5C, 0xED, 0x0B, 0xFF, 0xF8, 0xDF, 0x59, + 0x5F, 0xFF, 0x36, 0xB1, 0x41, 0x6D, 0x53, 0x13, 0xA9, 0x99, 0xF5, 0x32, + 0xEF, 0x4A, 0x99, 0x15, 0xDF, 0x96, 0xDE, 0xE0}, + // C=FR, O=Certplus, CN=Class 3TS Primary CA + {0xCE, 0x7D, 0xD0, 0x96, 0xC8, 0xFD, 0xE2, 0xBF, 0x5C, 0x43, 0x8E, 0xDB, + 0x57, 0x4B, 0xD6, 0x45, 0x43, 0x85, 0x33, 0x4E, 0xE8, 0xFF, 0x10, 0x6C, + 0x0F, 0x93, 0xD5, 0x05, 0x1B, 0xE6, 0xBA, 0xC3}, + // C=US, OU=www.xrampsecurity.com, O=XRamp Security Services Inc, CN=XRamp + // Global Certification Authority + {0xCE, 0xCD, 0xDC, 0x90, 0x50, 0x99, 0xD8, 0xDA, 0xDF, 0xC5, 0xB1, 0xD2, + 0x09, 0xB7, 0x37, 0xCB, 0xE2, 0xC1, 0x8C, 0xFB, 0x2C, 0x10, 0xC0, 0xFF, + 0x0B, 0xCF, 0x0D, 0x32, 0x86, 0xFC, 0x1A, 0xA2}, + // C=US, O=Equifax Secure Inc., CN=Equifax Secure eBusiness CA-1 + {0xCF, 0x56, 0xFF, 0x46, 0xA4, 0xA1, 0x86, 0x10, 0x9D, 0xD9, 0x65, 0x84, + 0xB5, 0xEE, 0xB5, 0x8A, 0x51, 0x0C, 0x42, 0x75, 0xB0, 0xE5, 0xF9, 0x4F, + 0x40, 0xBB, 0xAE, 0x86, 0x5E, 0x19, 0xF6, 0x73}, + // O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits + // liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Certification + // Authority (2048) + {0xD1, 0xC3, 0x39, 0xEA, 0x27, 0x84, 0xEB, 0x87, 0x0F, 0x93, 0x4F, 0xC5, + 0x63, 0x4E, 0x4A, 0xA9, 0xAD, 0x55, 0x05, 0x01, 0x64, 0x01, 0xF2, 0x64, + 0x65, 0xD3, 0x7A, 0x57, 0x46, 0x63, 0x35, 0x9F}, + // C=CZ, O=Prvn\xC3\xAD certifika\xC4\x8Dn\xC3\xAD autorita, a.s., CN=I.CA + // Root CA/RSA/serialNumber=NTRCZ-26439395 + {0xD3, 0xD6, 0x07, 0xA9, 0xFF, 0x24, 0xA1, 0x95, 0x23, 0xB6, 0xDA, 0x9D, + 0x2C, 0x64, 0x94, 0x46, 0xF8, 0x78, 0x8C, 0xB9, 0x6D, 0x9F, 0xD1, 0x30, + 0x97, 0x2E, 0x12, 0x0C, 0x13, 0x67, 0x77, 0x30}, + // C=NL, O=Staat der Nederlanden, CN=Staat der Nederlanden Root CA + {0xD4, 0x1D, 0x82, 0x9E, 0x8C, 0x16, 0x59, 0x82, 0x2A, 0xF9, 0x3F, 0xCE, + 0x62, 0xBF, 0xFC, 0xDE, 0x26, 0x4F, 0xC8, 0x4E, 0x8B, 0x95, 0x0C, 0x5F, + 0xF2, 0x75, 0xD0, 0x52, 0x35, 0x46, 0x95, 0xA3}, + // C=CN, O=WoSign CA Limited, CN=Certification Authority of WoSign G2 + {0xD4, 0x87, 0xA5, 0x6F, 0x83, 0xB0, 0x74, 0x82, 0xE8, 0x5E, 0x96, 0x33, + 0x94, 0xC1, 0xEC, 0xC2, 0xC9, 0xE5, 0x1D, 0x09, 0x03, 0xEE, 0x94, 0x6B, + 0x02, 0xC3, 0x01, 0x58, 0x1E, 0xD9, 0x9E, 0x16}, + // C=CN, O=WoSign CA Limited, CN=CA + // \xE6\xB2\x83\xE9\x80\x9A\xE6\xA0\xB9\xE8\xAF\x81\xE4\xB9\xA6 + {0xD6, 0xF0, 0x34, 0xBD, 0x94, 0xAA, 0x23, 0x3F, 0x02, 0x97, 0xEC, 0xA4, + 0x24, 0x5B, 0x28, 0x39, 0x73, 0xE4, 0x47, 0xAA, 0x59, 0x0F, 0x31, 0x0C, + 0x77, 0xF4, 0x8F, 0xDF, 0x83, 0x11, 0x22, 0x54}, + // C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=AAA + // Certificate Services + {0xD7, 0xA7, 0xA0, 0xFB, 0x5D, 0x7E, 0x27, 0x31, 0xD7, 0x71, 0xE9, 0x48, + 0x4E, 0xBC, 0xDE, 0xF7, 0x1D, 0x5F, 0x0C, 0x3E, 0x0A, 0x29, 0x48, 0x78, + 0x2B, 0xC8, 0x3E, 0xE0, 0xEA, 0x69, 0x9E, 0xF4}, + // C=DE, O=Deutscher Sparkassen Verlag GmbH, OU=S-TRUST Certification + // Services, CN=S-TRUST Universal Root CA + {0xD8, 0x0F, 0xEF, 0x91, 0x0A, 0xE3, 0xF1, 0x04, 0x72, 0x3B, 0x04, 0x5C, + 0xEC, 0x2D, 0x01, 0x9F, 0x44, 0x1C, 0xE6, 0x21, 0x3A, 0xDF, 0x15, 0x67, + 0x91, 0xE7, 0x0C, 0x17, 0x90, 0x11, 0x0A, 0x31}, + // C=PL, O=Unizeto Sp. z o.o., CN=Certum CA + {0xD8, 0xE0, 0xFE, 0xBC, 0x1D, 0xB2, 0xE3, 0x8D, 0x00, 0x94, 0x0F, 0x37, + 0xD2, 0x7D, 0x41, 0x34, 0x4D, 0x99, 0x3E, 0x73, 0x4B, 0x99, 0xD5, 0x65, + 0x6D, 0x97, 0x78, 0xD4, 0xD8, 0x14, 0x36, 0x24}, + // C=ch, O=Swisscom, OU=Digital Certificate Services, CN=Swisscom Root EV CA + // 2 + {0xD9, 0x5F, 0xEA, 0x3C, 0xA4, 0xEE, 0xDC, 0xE7, 0x4C, 0xD7, 0x6E, 0x75, + 0xFC, 0x6D, 0x1F, 0xF6, 0x2C, 0x44, 0x1F, 0x0F, 0xA8, 0xBC, 0x77, 0xF0, + 0x34, 0xB1, 0x9E, 0x5D, 0xB2, 0x58, 0x01, 0x5D}, + // O=TeliaSonera, CN=TeliaSonera Root CA v1 + {0xDD, 0x69, 0x36, 0xFE, 0x21, 0xF8, 0xF0, 0x77, 0xC1, 0x23, 0xA1, 0xA5, + 0x21, 0xC1, 0x22, 0x24, 0xF7, 0x22, 0x55, 0xB7, 0x3E, 0x03, 0xA7, 0x26, + 0x06, 0x93, 0xE8, 0xA2, 0x4B, 0x0F, 0xA3, 0x89}, + // C=BE, O=Certipost s.a./n.v., CN=Certipost E-Trust TOP Root CA + {0xDD, 0xFF, 0x53, 0xEC, 0xD7, 0x74, 0x3B, 0x60, 0xBB, 0x7B, 0x27, 0x95, + 0xFF, 0x57, 0x32, 0xFA, 0x78, 0x5F, 0x9A, 0x14, 0xDF, 0x11, 0x20, 0xFB, + 0x40, 0xA3, 0x8C, 0xF8, 0x4C, 0xA2, 0xA5, 0x66}, + // C=US, ST=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft + // Root Certificate Authority 2010 + {0xDF, 0x54, 0x5B, 0xF9, 0x19, 0xA2, 0x43, 0x9C, 0x36, 0x98, 0x3B, 0x54, + 0xCD, 0xFC, 0x90, 0x3D, 0xFA, 0x4F, 0x37, 0xD3, 0x99, 0x6D, 0x8D, 0x84, + 0xB4, 0xC3, 0x1E, 0xEC, 0x6F, 0x3C, 0x16, 0x3E}, + // C=ES, ST=Barcelona, L=Barcelona (see current address at + // http://www.anf.es/es/address-direccion.html ), O=ANF Autoridad de + // Certificacion, OU=ANF Clase 1 + // CA/emailAddress=info@anf.es/serialNumber=G63287510, CN=ANF Global Root CA + {0xE0, 0xE1, 0x7A, 0xEA, 0x06, 0xCF, 0x9C, 0xE1, 0x2A, 0xAE, 0x81, 0x90, + 0x34, 0x5A, 0x2C, 0x59, 0x72, 0x01, 0x30, 0xA7, 0xD8, 0xFF, 0x72, 0xF3, + 0x74, 0x5A, 0xD7, 0x5D, 0xBA, 0xA3, 0x65, 0xB6}, + // C=SK, L=Bratislava, O=Disig a.s., CN=CA Disig Root R2 + {0xE2, 0x3D, 0x4A, 0x03, 0x6D, 0x7B, 0x70, 0xE9, 0xF5, 0x95, 0xB1, 0x42, + 0x20, 0x79, 0xD2, 0xB9, 0x1E, 0xDF, 0xBB, 0x1F, 0xB6, 0x51, 0xA0, 0x63, + 0x3E, 0xAA, 0x8A, 0x9D, 0xC5, 0xF8, 0x07, 0x03}, + // C=CN, O=CNNIC, CN=CNNIC ROOT + {0xE2, 0x83, 0x93, 0x77, 0x3D, 0xA8, 0x45, 0xA6, 0x79, 0xF2, 0x08, 0x0C, + 0xC7, 0xFB, 0x44, 0xA3, 0xB7, 0xA1, 0xC3, 0x79, 0x2C, 0xB7, 0xEB, 0x77, + 0x29, 0xFD, 0xCB, 0x6A, 0x8D, 0x99, 0xAE, 0xA7}, + // C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, + // Inc. - For authorized use only, CN=VeriSign Class 4 Public Primary + // Certification Authority - G3 + {0xE3, 0x89, 0x36, 0x0D, 0x0F, 0xDB, 0xAE, 0xB3, 0xD2, 0x50, 0x58, 0x4B, + 0x47, 0x30, 0x31, 0x4E, 0x22, 0x2F, 0x39, 0xC1, 0x56, 0xA0, 0x20, 0x14, + 0x4E, 0x8D, 0x96, 0x05, 0x61, 0x79, 0x15, 0x06}, + // C=FR, O=Dhimyotis, CN=Certigna + {0xE3, 0xB6, 0xA2, 0xDB, 0x2E, 0xD7, 0xCE, 0x48, 0x84, 0x2F, 0x7A, 0xC5, + 0x32, 0x41, 0xC7, 0xB7, 0x1D, 0x54, 0x14, 0x4B, 0xFB, 0x40, 0xC1, 0x1F, + 0x3F, 0x1D, 0x0B, 0x42, 0xF5, 0xEE, 0xA1, 0x2D}, + // C=TR, L=Gebze - Kocaeli, O=T\xC3\xBCrkiye Bilimsel ve Teknolojik + // Ara\xC5\x9Ft\xC4\xB1rma Kurumu - T\xC3\x9CB\xC4\xB0TAK, OU=Ulusal + // Elektronik ve Kriptoloji Ara\xC5\x9Ft\xC4\xB1rma Enstit\xC3\xBCs\xC3\xBC + // - UEKAE, OU=Kamu Sertifikasyon Merkezi, CN=T\xC3\x9CB\xC4\xB0TAK UEKAE + // K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xC4\xB1c\xC4\xB1s\xC4\xB1 - + // S\xC3\xBCr\xC3\xBCm 3 + {0xE4, 0xC7, 0x34, 0x30, 0xD7, 0xA5, 0xB5, 0x09, 0x25, 0xDF, 0x43, 0x37, + 0x0A, 0x0D, 0x21, 0x6E, 0x9A, 0x79, 0xB9, 0xD6, 0xDB, 0x83, 0x73, 0xA0, + 0xC6, 0x9E, 0xB1, 0xCC, 0x31, 0xC7, 0xC5, 0x2A}, + // C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=DSTCA + // X2, CN=DST RootCA X2/emailAddress=ca@digsigtrust.com + {0xE5, 0x72, 0x10, 0xAB, 0x81, 0x2C, 0x8D, 0xF3, 0x08, 0x26, 0x7C, 0xB4, + 0x29, 0x1B, 0x98, 0xE9, 0x56, 0x59, 0x7C, 0xA3, 0x6E, 0xC2, 0xB9, 0x51, + 0x89, 0xEF, 0x17, 0x23, 0x39, 0x6B, 0xCA, 0xC8}, + // C=BR, O=Serasa S.A., OU=Serasa CA III, CN=Serasa Certificate Authority + // III + {0xE5, 0xBD, 0xA8, 0x20, 0xE5, 0xCE, 0x15, 0xBF, 0xD0, 0x7B, 0xA1, 0x1F, + 0xFB, 0x1C, 0x7C, 0x8A, 0x59, 0x10, 0xCE, 0x1B, 0x90, 0x17, 0x5C, 0x34, + 0x30, 0x8B, 0xC2, 0x50, 0x04, 0x53, 0xCC, 0xDC}, + // C=KR, O=Government of Korea, OU=GPKI, CN=Root CA + {0xE5, 0xC0, 0x1C, 0xB4, 0x09, 0x32, 0x79, 0xFA, 0xA1, 0x9F, 0xCF, 0xA2, + 0x4E, 0xA4, 0x3E, 0xB1, 0xB2, 0x6D, 0x07, 0xA6, 0x15, 0xAD, 0xF7, 0x24, + 0x01, 0x84, 0xA1, 0xE7, 0x16, 0xB7, 0x61, 0xC9}, + // C=TR, O=Elektronik Bilgi Guvenligi A.S., CN=e-Guven Kok Elektronik + // Sertifika Hizmet Saglayicisi + {0xE6, 0x09, 0x07, 0x84, 0x65, 0xA4, 0x19, 0x78, 0x0C, 0xB6, 0xAC, 0x4C, + 0x1C, 0x0B, 0xFB, 0x46, 0x53, 0xD9, 0xD9, 0xCC, 0x6E, 0xB3, 0x94, 0x6E, + 0xB7, 0xF3, 0xD6, 0x99, 0x97, 0xBA, 0xD5, 0x98}, + // C=DE, O=TC TrustCenter GmbH, OU=TC TrustCenter Class 2 CA, CN=TC + // TrustCenter Class 2 CA II + {0xE6, 0xB8, 0xF8, 0x76, 0x64, 0x85, 0xF8, 0x07, 0xAE, 0x7F, 0x8D, 0xAC, + 0x16, 0x70, 0x46, 0x1F, 0x07, 0xC0, 0xA1, 0x3E, 0xEF, 0x3A, 0x1F, 0xF7, + 0x17, 0x53, 0x8D, 0x7A, 0xBA, 0xD3, 0x91, 0xB4}, + // C=LT, O=Skaitmeninio sertifikavimo centras, OU=Certification Authority, + // CN=SSC Root CA C + {0xE6, 0xE4, 0xA9, 0x51, 0xEC, 0xBF, 0x7D, 0x8E, 0xDC, 0x01, 0xBC, 0x87, + 0x3F, 0x7B, 0x6F, 0xD3, 0x58, 0x68, 0xBD, 0xB1, 0x0E, 0xD7, 0x86, 0xF3, + 0xA1, 0xB1, 0xEE, 0x16, 0xD8, 0xCE, 0xC3, 0xE9}, + // C=JP, O=SECOM Trust.net, OU=Security Communication RootCA1 + {0xE7, 0x5E, 0x72, 0xED, 0x9F, 0x56, 0x0E, 0xEC, 0x6E, 0xB4, 0x80, 0x00, + 0x73, 0xA4, 0x3F, 0xC3, 0xAD, 0x19, 0x19, 0x5A, 0x39, 0x22, 0x82, 0x01, + 0x78, 0x95, 0x97, 0x4A, 0x99, 0x02, 0x6B, 0x6C}, + // C=US, O=VeriSign, Inc., OU=Class 3 Public Primary Certification Authority + {0xE7, 0x68, 0x56, 0x34, 0xEF, 0xAC, 0xF6, 0x9A, 0xCE, 0x93, 0x9A, 0x6B, + 0x25, 0x5B, 0x7B, 0x4F, 0xAB, 0xEF, 0x42, 0x93, 0x5B, 0x50, 0xA2, 0x65, + 0xAC, 0xB5, 0xCB, 0x60, 0x27, 0xE4, 0x4E, 0x70}, + // C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust + // RSA Certification Authority + {0xE7, 0x93, 0xC9, 0xB0, 0x2F, 0xD8, 0xAA, 0x13, 0xE2, 0x1C, 0x31, 0x22, + 0x8A, 0xCC, 0xB0, 0x81, 0x19, 0x64, 0x3B, 0x74, 0x9C, 0x89, 0x89, 0x64, + 0xB1, 0x74, 0x6D, 0x46, 0xC3, 0xD4, 0xCB, 0xD2}, + // C=us, ST=Utah, L=Salt Lake City, O=Digital Signature Trust Co., OU=United + // Parcel Service, CN=DST (UPS) RootCA/emailAddress=ca@digsigtrust.com + {0xE8, 0x73, 0xD4, 0x08, 0x2A, 0x7B, 0x46, 0x32, 0x93, 0x4F, 0x48, 0xA5, + 0xCC, 0x1E, 0xE5, 0x00, 0x93, 0x2F, 0x66, 0x1E, 0x56, 0xC3, 0x46, 0x7C, + 0x5C, 0x84, 0xD3, 0x14, 0x47, 0x47, 0x6B, 0x0C}, + // C=AT, O=A-Trust Ges. f\xFCr Sicherheitssysteme im elektr. Datenverkehr + // GmbH, OU=A-Trust-Qual-01, CN=A-Trust-Qual-01 + {0xE8, 0xA2, 0xF4, 0x41, 0x65, 0x76, 0x78, 0x97, 0x5F, 0x2B, 0x97, 0xD7, + 0x75, 0x71, 0x9C, 0x7D, 0x49, 0xD9, 0x22, 0x34, 0x55, 0x45, 0x40, 0xEC, + 0x14, 0xD9, 0x2E, 0x16, 0xFE, 0x27, 0xD2, 0xCB}, + // C=BR, O=Certisign Certificadora Digital Ltda., OU=Certisign - Autoridade + // Certificadora - AC2 + {0xE8, 0xB2, 0x8D, 0x2A, 0x3D, 0x81, 0xF6, 0x3B, 0x4E, 0x44, 0x67, 0xC2, + 0x19, 0x0A, 0x63, 0x1F, 0xC0, 0x62, 0x35, 0x3B, 0x5F, 0x2D, 0x25, 0x85, + 0x1D, 0xDA, 0x6B, 0x64, 0x4A, 0xC7, 0x8B, 0x3F}, + // C=DE, O=D-Trust GmbH, CN=D-TRUST Qualified Root CA 1 2007:PN + {0xE8, 0xC6, 0xAA, 0x6B, 0x5F, 0x58, 0xA8, 0xF2, 0xA6, 0x36, 0x5C, 0xF9, + 0x8E, 0x65, 0x69, 0x35, 0x63, 0xA3, 0x8B, 0x7B, 0x2F, 0x32, 0xCF, 0x1B, + 0xE0, 0x6F, 0x2D, 0x22, 0x29, 0xD4, 0xBF, 0x59}, + // C=BG, O=InfoNotary PLC, DC=root-ca, CN=InfoNotary CSP Root, OU=InfoNotary + // CSP Root/emailAddress=csp@infonotary.com + {0xEA, 0x7E, 0x31, 0x2E, 0xCE, 0x48, 0x7B, 0x4C, 0x0A, 0xA6, 0x3C, 0xC8, + 0x0A, 0xB9, 0xFC, 0xB3, 0x3C, 0x72, 0x05, 0x73, 0xF8, 0x94, 0x5F, 0x77, + 0x61, 0x74, 0x5F, 0xC6, 0x38, 0x63, 0xD3, 0x9D}, + // C=RO, O=certSIGN, OU=certSIGN ROOT CA + {0xEA, 0xA9, 0x62, 0xC4, 0xFA, 0x4A, 0x6B, 0xAF, 0xEB, 0xE4, 0x15, 0x19, + 0x6D, 0x35, 0x1C, 0xCD, 0x88, 0x8D, 0x4F, 0x53, 0xF3, 0xFA, 0x8A, 0xE6, + 0xD7, 0xC4, 0x66, 0xA9, 0x4E, 0x60, 0x42, 0xBB}, + // C=CH, O=admin, OU=Services, OU=Certification Authorities, + // CN=AdminCA-CD-T01 + {0xEA, 0xC0, 0x22, 0x0C, 0x5C, 0x9F, 0xEC, 0xC5, 0x12, 0x1D, 0x37, 0x20, + 0x87, 0x2D, 0x06, 0x70, 0x7B, 0x52, 0x66, 0xBE, 0x25, 0xD4, 0xEB, 0xB5, + 0x6A, 0xB8, 0x04, 0xBB, 0xBF, 0x85, 0xFE, 0x03}, + // C=US, O=VeriSign, Inc., OU=VeriSign Trust Network, OU=(c) 1999 VeriSign, + // Inc. - For authorized use only, CN=VeriSign Class 3 Public Primary + // Certification Authority - G3 + {0xEB, 0x04, 0xCF, 0x5E, 0xB1, 0xF3, 0x9A, 0xFA, 0x76, 0x2F, 0x2B, 0xB1, + 0x20, 0xF2, 0x96, 0xCB, 0xA5, 0x20, 0xC1, 0xB9, 0x7D, 0xB1, 0x58, 0x95, + 0x65, 0xB8, 0x1C, 0xB9, 0xA1, 0x7B, 0x72, 0x44}, + // C=HU, L=Budapest, O=NetLock Kft., + // OU=Tan\xC3\xBAs\xC3\xADtv\xC3\xA1nykiad\xC3\xB3k (Certification + // Services), CN=NetLock Platina (Class Platinum) + // F\xC5\x91tan\xC3\xBAs\xC3\xADtv\xC3\xA1ny + {0xEB, 0x7E, 0x05, 0xAA, 0x58, 0xE7, 0xBD, 0x32, 0x8A, 0x28, 0x2B, 0xF8, + 0x86, 0x70, 0x33, 0xF3, 0xC0, 0x35, 0x34, 0x2B, 0x51, 0x6E, 0xE8, 0x5C, + 0x01, 0x67, 0x3D, 0xFF, 0xFF, 0xBB, 0xFE, 0x58}, + // C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA + {0xEB, 0xD4, 0x10, 0x40, 0xE4, 0xBB, 0x3E, 0xC7, 0x42, 0xC9, 0xE3, 0x81, + 0xD3, 0x1E, 0xF2, 0xA4, 0x1A, 0x48, 0xB6, 0x68, 0x5C, 0x96, 0xE7, 0xCE, + 0xF3, 0xC1, 0xDF, 0x6C, 0xD4, 0x33, 0x1C, 0x99}, + // C=DE, O=TC TrustCenter GmbH, OU=TC TrustCenter Universal CA, CN=TC + // TrustCenter Universal CA I + {0xEB, 0xF3, 0xC0, 0x2A, 0x87, 0x89, 0xB1, 0xFB, 0x7D, 0x51, 0x19, 0x95, + 0xD6, 0x63, 0xB7, 0x29, 0x06, 0xD9, 0x13, 0xCE, 0x0D, 0x5E, 0x10, 0x56, + 0x8A, 0x8A, 0x77, 0xE2, 0x58, 0x61, 0x67, 0xE7}, + // emailAddress=pki@sk.ee, C=EE, O=AS Sertifitseerimiskeskus, CN=Juur-SK + {0xEC, 0xC3, 0xE9, 0xC3, 0x40, 0x75, 0x03, 0xBE, 0xE0, 0x91, 0xAA, 0x95, + 0x2F, 0x41, 0x34, 0x8F, 0xF8, 0x8B, 0xAA, 0x86, 0x3B, 0x22, 0x64, 0xBE, + 0xFA, 0xC8, 0x07, 0x90, 0x15, 0x74, 0xE9, 0x39}, + // C=NO, O=Buypass AS-983163327, CN=Buypass Class 3 Root CA + {0xED, 0xF7, 0xEB, 0xBC, 0xA2, 0x7A, 0x2A, 0x38, 0x4D, 0x38, 0x7B, 0x7D, + 0x40, 0x10, 0xC6, 0x66, 0xE2, 0xED, 0xB4, 0x84, 0x3E, 0x4C, 0x29, 0xB4, + 0xAE, 0x1D, 0x5B, 0x93, 0x32, 0xE6, 0xB2, 0x4D}, + // C=DE, O=D-Trust GmbH, CN=D-TRUST Root Class 3 CA 2 EV 2009 + {0xEE, 0xC5, 0x49, 0x6B, 0x98, 0x8C, 0xE9, 0x86, 0x25, 0xB9, 0x34, 0x09, + 0x2E, 0xEC, 0x29, 0x08, 0xBE, 0xD0, 0xB0, 0xF3, 0x16, 0xC2, 0xD4, 0x73, + 0x0C, 0x84, 0xEA, 0xF1, 0xF3, 0xD3, 0x48, 0x81}, + // C=ES, ST=Madrid, L=Madrid, O=IPS Certification Authority s.l. ipsCA, + // OU=ipsCA, CN=ipsCA Main CA Root/emailAddress=main01@ipsca.com + {0xEE, 0xFC, 0xA8, 0x88, 0xDB, 0x44, 0x2C, 0xEA, 0x1F, 0x03, 0xFA, 0xC5, + 0xDE, 0x5B, 0x1A, 0xF2, 0x10, 0xAE, 0x03, 0xF5, 0xE1, 0x65, 0x8D, 0xDB, + 0x88, 0x0C, 0x64, 0x5E, 0x78, 0x62, 0x45, 0x46}, + // C=EU, O=AC Camerfirma SA CIF A82743287, OU=http://www.chambersign.org, + // CN=Global Chambersign Root + {0xEF, 0x3C, 0xB4, 0x17, 0xFC, 0x8E, 0xBF, 0x6F, 0x97, 0x87, 0x6C, 0x9E, + 0x4E, 0xCE, 0x39, 0xDE, 0x1E, 0xA5, 0xFE, 0x64, 0x91, 0x41, 0xD1, 0x02, + 0x8B, 0x7D, 0x11, 0xC0, 0xB2, 0x29, 0x8C, 0xED}, + // C=BE, O=Certipost s.a./n.v., CN=Certipost E-Trust Primary Normalised CA + {0xF0, 0x03, 0x55, 0xEE, 0xF1, 0x01, 0xC7, 0xDF, 0x4E, 0x46, 0xCC, 0xE6, + 0x41, 0x7D, 0xFF, 0xCE, 0x3D, 0xB8, 0x2D, 0xBB, 0x13, 0x69, 0xC3, 0xB4, + 0x39, 0xC4, 0xE3, 0x3B, 0xEE, 0x44, 0x5C, 0x42}, + // C=FI, ST=Finland, O=Vaestorekisterikeskus CA, OU=Certification Authority + // Services, OU=Varmennepalvelut, CN=VRK Gov. Root CA + {0xF0, 0x08, 0x73, 0x3E, 0xC5, 0x00, 0xDC, 0x49, 0x87, 0x63, 0xCC, 0x92, + 0x64, 0xC6, 0xFC, 0xEA, 0x40, 0xEC, 0x22, 0x00, 0x0E, 0x92, 0x7D, 0x05, + 0x3C, 0xE9, 0xC9, 0x0B, 0xFA, 0x04, 0x6C, 0xB2}, + // C=ch, O=Swisscom, OU=Digital Certificate Services, CN=Swisscom Root CA 2 + {0xF0, 0x9B, 0x12, 0x2C, 0x71, 0x14, 0xF4, 0xA0, 0x9B, 0xD4, 0xEA, 0x4F, + 0x4A, 0x99, 0xD5, 0x58, 0xB4, 0x6E, 0x4C, 0x25, 0xCD, 0x81, 0x14, 0x0D, + 0x29, 0xC0, 0x56, 0x13, 0x91, 0x4C, 0x38, 0x41}, + // C=LT, O=Skaitmeninio sertifikavimo centras, OU=Certification Authority, + // CN=SSC Root CA A + {0xF1, 0xB1, 0x3F, 0x5C, 0x9A, 0x32, 0x64, 0x03, 0xB0, 0xF3, 0x1B, 0xBE, + 0x76, 0x99, 0xCD, 0x17, 0xC7, 0xD1, 0xC0, 0xB9, 0x81, 0x58, 0x6D, 0xD1, + 0xA7, 0xB2, 0x19, 0xC5, 0x25, 0x08, 0xFE, 0x99}, + // C=US, O=SecureTrust Corporation, CN=SecureTrust CA + {0xF1, 0xC1, 0xB5, 0x0A, 0xE5, 0xA2, 0x0D, 0xD8, 0x03, 0x0E, 0xC9, 0xF6, + 0xBC, 0x24, 0x82, 0x3D, 0xD3, 0x67, 0xB5, 0x25, 0x57, 0x59, 0xB4, 0xE7, + 0x1B, 0x61, 0xFC, 0xE9, 0xF7, 0x37, 0x5D, 0x73}, + // C=ES, ST=BARCELONA, L=BARCELONA, O=IPS Seguridad CA, OU=Certificaciones, + // CN=IPS SERVIDORES/emailAddress=ips@mail.ips.es + {0xF1, 0xF3, 0xCC, 0x20, 0x7A, 0x6D, 0x47, 0x94, 0x7B, 0x8C, 0xB9, 0xC3, + 0x04, 0x22, 0x22, 0x9D, 0xE0, 0xD7, 0x1F, 0xB8, 0x67, 0xE0, 0xB9, 0xA3, + 0xED, 0xA0, 0x8E, 0x0E, 0x17, 0x36, 0xBC, 0x28}, + // C=AT, O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH, + // OU=A-Trust-Qual-02, CN=A-Trust-Qual-02 + {0xF2, 0x86, 0x30, 0xBA, 0xBF, 0x25, 0x6E, 0x56, 0x7B, 0x58, 0x21, 0x06, + 0x9F, 0xCF, 0x13, 0x14, 0x8A, 0xB9, 0xA2, 0x3E, 0x28, 0xFC, 0x0D, 0x70, + 0x61, 0x5A, 0xAE, 0x6E, 0xD2, 0x84, 0xF4, 0xC8}, + // CN=Atos TrustedRoot 2011, O=Atos, C=DE + {0xF3, 0x56, 0xBE, 0xA2, 0x44, 0xB7, 0xA9, 0x1E, 0xB3, 0x5D, 0x53, 0xCA, + 0x9A, 0xD7, 0x86, 0x4A, 0xCE, 0x01, 0x8E, 0x2D, 0x35, 0xD5, 0xF8, 0xF9, + 0x6D, 0xDF, 0x68, 0xA6, 0xF4, 0x1A, 0xA4, 0x74}, + // C=IN, O=India PKI, CN=CCA India 2007 + {0xF3, 0x75, 0xE2, 0xF7, 0x7A, 0x10, 0x8B, 0xAC, 0xC4, 0x23, 0x48, 0x94, + 0xA9, 0xAF, 0x30, 0x8E, 0xDE, 0xCA, 0x1A, 0xCD, 0x8F, 0xBD, 0xE0, 0xE7, + 0xAA, 0xA9, 0x63, 0x4E, 0x9D, 0xAF, 0x7E, 0x1C}, + // OU=Copyright (c) 1997 Microsoft Corp., OU=Microsoft Corporation, + // CN=Microsoft Root Authority + {0xF3, 0x84, 0x06, 0xE5, 0x40, 0xD7, 0xA9, 0xD9, 0x0C, 0xB4, 0xA9, 0x47, + 0x92, 0x99, 0x64, 0x0F, 0xFB, 0x6D, 0xF9, 0xE2, 0x24, 0xEC, 0xC7, 0xA0, + 0x1C, 0x0D, 0x95, 0x58, 0xD8, 0xDA, 0xD7, 0x7D}, + // C=ES, O=Agencia Notarial de Certificacion S.L.U. - CIF B83395988, + // CN=ANCERT Certificados CGN V2 + {0xF4, 0x33, 0x6B, 0xC2, 0xAC, 0x75, 0x95, 0x0B, 0xEC, 0xCF, 0x1C, 0x1F, + 0x2F, 0x9D, 0xA6, 0xDD, 0xDA, 0xFD, 0x1F, 0x41, 0x16, 0x1C, 0xA7, 0x1F, + 0x59, 0xC7, 0x68, 0x89, 0xBD, 0x47, 0x40, 0x33}, + // L=ValiCert Validation Network, O=ValiCert, Inc., OU=ValiCert Class 1 + // Policy Validation Authority, + // CN=http://www.valicert.com//emailAddress=info@valicert.com + {0xF4, 0xC1, 0x49, 0x55, 0x1A, 0x30, 0x13, 0xA3, 0x5B, 0xC7, 0xBF, 0xFE, + 0x17, 0xA7, 0xF3, 0x44, 0x9B, 0xC1, 0xAB, 0x5B, 0x5A, 0x0A, 0xE7, 0x4B, + 0x06, 0xC2, 0x3B, 0x90, 0x00, 0x4C, 0x01, 0x04}, + // C=IT, O=SIA S.p.A., L=Milano, CN=SIA Secure Server CA + {0xF5, 0x63, 0xC5, 0xC3, 0xE5, 0x12, 0xE6, 0x3B, 0x97, 0xB5, 0x43, 0x8F, + 0x2B, 0xD4, 0xA9, 0xAE, 0x78, 0xA4, 0xF9, 0xEA, 0xD9, 0x2B, 0xCC, 0x34, + 0xFE, 0x97, 0x3B, 0xDC, 0x7C, 0x6D, 0x21, 0x48}, + // C=SE, O=Swedish Social Insurance Agency, CN=Swedish Government Root + // Authority v1 + {0xF6, 0x57, 0xA6, 0x33, 0xEE, 0xB9, 0xBC, 0x5D, 0x15, 0xA4, 0x61, 0x75, + 0x17, 0x49, 0xEA, 0x4B, 0x31, 0x67, 0x27, 0xDC, 0xF1, 0xA9, 0xF9, 0x86, + 0xB5, 0x45, 0x84, 0x45, 0xF6, 0x48, 0x5D, 0xDE}, + // C=UY, O=ADMINISTRACION NACIONAL DE CORREOS, OU=SERVICIOS ELECTRONICOS, + // CN=SERVICIOS DE CERTIFICACION - A.N.C./mail=correo_cert@correo.com.uy + {0xF7, 0x73, 0xBC, 0x65, 0x65, 0x9F, 0x1B, 0xC5, 0x90, 0x87, 0xBF, 0x21, + 0x4E, 0xEA, 0xD8, 0x64, 0x01, 0x0D, 0x58, 0x87, 0xCD, 0x2C, 0xD8, 0x4E, + 0x4F, 0x1B, 0xA7, 0x52, 0x3F, 0xE5, 0x56, 0x40}, + // C=SK, L=Bratislava, O=Disig a.s., CN=CA Disig Root R1 + {0xF9, 0x6F, 0x23, 0xF4, 0xC3, 0xE7, 0x9C, 0x07, 0x7A, 0x46, 0x98, 0x8D, + 0x5A, 0xF5, 0x90, 0x06, 0x76, 0xA0, 0xF0, 0x39, 0xCB, 0x64, 0x5D, 0xD1, + 0x75, 0x49, 0xB2, 0x16, 0xC8, 0x24, 0x40, 0xCE}, + // C=HK, O=Hongkong Post, CN=Hongkong Post Root CA 1 + {0xF9, 0xE6, 0x7D, 0x33, 0x6C, 0x51, 0x00, 0x2A, 0xC0, 0x54, 0xC6, 0x32, + 0x02, 0x2D, 0x66, 0xDD, 0xA2, 0xE7, 0xE3, 0xFF, 0xF1, 0x0A, 0xD0, 0x61, + 0xED, 0x31, 0xD8, 0xBB, 0xB4, 0x10, 0xCF, 0xB2}, + // C=PL, O=Krajowa Izba Rozliczeniowa S.A., CN=SZAFIR ROOT CA + {0xFA, 0xBC, 0xF5, 0x19, 0x7C, 0xDD, 0x7F, 0x45, 0x8A, 0xC3, 0x38, 0x32, + 0xD3, 0x28, 0x40, 0x21, 0xDB, 0x24, 0x25, 0xFD, 0x6B, 0xEA, 0x7A, 0x2E, + 0x69, 0xB7, 0x48, 0x6E, 0x8F, 0x51, 0xF9, 0xCC}, + // C=BR, O=ICP-Brasil, OU=Instituto Nacional de Tecnologia da Informacao - + // ITI, CN=Autoridade Certificadora Raiz Brasileira v2 + {0xFB, 0x47, 0xD9, 0x2A, 0x99, 0x09, 0xFD, 0x4F, 0xA9, 0xBE, 0xC0, 0x27, + 0x37, 0x54, 0x3E, 0x1F, 0x35, 0x14, 0xCE, 0xD7, 0x47, 0x40, 0x7A, 0x8D, + 0x9C, 0xFA, 0x39, 0x7B, 0x09, 0x15, 0x06, 0x7C}, + // C=IT, O=SIA S.p.A., L=Milano, CN=SIA Secure Client CA + {0xFC, 0x0A, 0x0F, 0xE2, 0x7C, 0x9D, 0xC1, 0x3C, 0x81, 0x23, 0x8A, 0x59, + 0x13, 0xA1, 0xDA, 0xF8, 0x18, 0x41, 0x68, 0xBE, 0xB7, 0xE5, 0xA4, 0x51, + 0x2A, 0x77, 0x1F, 0xD4, 0xF4, 0x53, 0x65, 0x1D}, + // C=SE, O=Inera AB, CN=SITHS Root CA v1 + {0xFC, 0x50, 0xB2, 0x6B, 0xDC, 0x4A, 0x8F, 0xDF, 0x13, 0x44, 0xCC, 0x80, + 0x15, 0x7A, 0xE1, 0x3A, 0xC6, 0x71, 0xE2, 0x70, 0x6F, 0xAC, 0xFC, 0x06, + 0x05, 0xFE, 0x34, 0xE2, 0x49, 0xEB, 0x72, 0xD6}, + // C=FR, O=Certinomis, OU=0002 433998903, CN=Certinomis - Autorit\xC3\xA9 + // Racine + {0xFC, 0xBF, 0xE2, 0x88, 0x62, 0x06, 0xF7, 0x2B, 0x27, 0x59, 0x3C, 0x8B, + 0x07, 0x02, 0x97, 0xE1, 0x2D, 0x76, 0x9E, 0xD1, 0x0E, 0xD7, 0x93, 0x07, + 0x05, 0xA8, 0x09, 0x8E, 0xFF, 0xC1, 0x4D, 0x17}, + // C=DE, O=T-Systems Enterprise Services GmbH, OU=T-Systems Trust Center, + // CN=T-TeleSec GlobalRoot Class 3 + {0xFD, 0x73, 0xDA, 0xD3, 0x1C, 0x64, 0x4F, 0xF1, 0xB4, 0x3B, 0xEF, 0x0C, + 0xCD, 0xDA, 0x96, 0x71, 0x0B, 0x9C, 0xD9, 0x87, 0x5E, 0xCA, 0x7E, 0x31, + 0x70, 0x7A, 0xF3, 0xE9, 0x6D, 0x52, 0x2B, 0xBD}, + // C=SI, O=Halcom, CN=Halcom CA PO 2 + {0xFE, 0x71, 0x14, 0xD0, 0x7A, 0x14, 0x77, 0x59, 0x89, 0x1F, 0xF3, 0x7B, + 0x4F, 0x53, 0xEB, 0x43, 0x56, 0x82, 0x96, 0xBC, 0x3B, 0xF8, 0x9B, 0xC1, + 0x2C, 0xAF, 0xB1, 0x86, 0x98, 0x5E, 0xF2, 0x8D}, + // C=US, O=GeoTrust Inc., CN=GeoTrust Global CA + {0xFF, 0x85, 0x6A, 0x2D, 0x25, 0x1D, 0xCD, 0x88, 0xD3, 0x66, 0x56, 0xF4, + 0x50, 0x12, 0x67, 0x98, 0xCF, 0xAB, 0xAA, 0xDE, 0x40, 0x79, 0x9C, 0x72, + 0x2D, 0xE4, 0xD2, 0xB5, 0xDB, 0x36, 0xA7, 0x3A}, + // C=BR, O=Serasa S.A., OU=Serasa CA II, CN=Serasa Certificate Authority II + {0xFF, 0xCE, 0xF2, 0x22, 0x4E, 0x29, 0xB0, 0xB3, 0x6E, 0xC8, 0x31, 0x4E, + 0x68, 0x68, 0x22, 0xF3, 0xAC, 0x0F, 0x1C, 0x5E, 0x0C, 0x2D, 0x5C, 0x0E, + 0xB2, 0x48, 0x4C, 0xE7, 0xE2, 0x54, 0x0F, 0xD0}, }; #endif // NET_CERT_X509_CERTIFICATE_KNOWN_ROOTS_WIN_H_ diff --git a/chromium/net/cert/x509_certificate_mac.cc b/chromium/net/cert/x509_certificate_mac.cc index 64457e4d7e1..e27576ab265 100644 --- a/chromium/net/cert/x509_certificate_mac.cc +++ b/chromium/net/cert/x509_certificate_mac.cc @@ -148,8 +148,8 @@ void AddCertificatesFromBytes(const char* data, size_t length, X509Certificate::OSCertHandles* output) { SecExternalFormat input_format = format; ScopedCFTypeRef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy( - kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), length, - kCFAllocatorNull)); + kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), + base::checked_cast<CFIndex>(length), kCFAllocatorNull)); CFArrayRef items = NULL; OSStatus status; @@ -298,7 +298,8 @@ bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, // static X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( - const char* data, int length) { + const char* data, + size_t length) { CSSM_DATA cert_data; cert_data.Data = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(data)); cert_data.Length = length; @@ -319,7 +320,9 @@ X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( // static X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( - const char* data, int length, Format format) { + const char* data, + size_t length, + Format format) { OSCertHandles results; switch (format) { diff --git a/chromium/net/cert/x509_certificate_net_log_param.cc b/chromium/net/cert/x509_certificate_net_log_param.cc index 72b1e919aa7..0a1bc8ed85b 100644 --- a/chromium/net/cert/x509_certificate_net_log_param.cc +++ b/chromium/net/cert/x509_certificate_net_log_param.cc @@ -5,6 +5,7 @@ #include "net/cert/x509_certificate_net_log_param.h" #include <string> +#include <utility> #include <vector> #include "base/values.h" @@ -21,8 +22,8 @@ scoped_ptr<base::Value> NetLogX509CertificateCallback( certificate->GetPEMEncodedChain(&encoded_chain); for (size_t i = 0; i < encoded_chain.size(); ++i) certs->Append(new base::StringValue(encoded_chain[i])); - dict->Set("certificates", certs.Pass()); - return dict.Pass(); + dict->Set("certificates", std::move(certs)); + return std::move(dict); } } // namespace net diff --git a/chromium/net/cert/x509_certificate_nss.cc b/chromium/net/cert/x509_certificate_nss.cc index f8646cb0369..1c5359198bc 100644 --- a/chromium/net/cert/x509_certificate_nss.cc +++ b/chromium/net/cert/x509_certificate_nss.cc @@ -16,6 +16,7 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" +#include "base/numerics/safe_conversions.h" #include "base/pickle.h" #include "base/strings/stringprintf.h" #include "base/time/time.h" @@ -41,7 +42,7 @@ void X509Certificate::Initialize() { // static X509Certificate* X509Certificate::CreateFromBytesWithNickname( const char* data, - int length, + size_t length, const char* nickname) { OSCertHandle cert_handle = CreateOSCertHandleFromBytesWithNickname(data, length, @@ -160,19 +161,16 @@ bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, // static X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( - const char* data, int length) { + const char* data, + size_t length) { return CreateOSCertHandleFromBytesWithNickname(data, length, NULL); } // static X509Certificate::OSCertHandle -X509Certificate::CreateOSCertHandleFromBytesWithNickname( - const char* data, - int length, - const char* nickname) { - if (length < 0) - return NULL; - +X509Certificate::CreateOSCertHandleFromBytesWithNickname(const char* data, + size_t length, + const char* nickname) { crypto::EnsureNSSInit(); if (!NSS_IsInitialized()) @@ -180,7 +178,7 @@ X509Certificate::CreateOSCertHandleFromBytesWithNickname( SECItem der_cert; der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data)); - der_cert.len = length; + der_cert.len = base::checked_cast<unsigned>(length); der_cert.type = siDERCertBuffer; // Parse into a certificate structure. @@ -192,7 +190,7 @@ X509Certificate::CreateOSCertHandleFromBytesWithNickname( // static X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( const char* data, - int length, + size_t length, Format format) { return x509_util::CreateOSCertHandlesFromBytes(data, length, format); } diff --git a/chromium/net/cert/x509_certificate_openssl.cc b/chromium/net/cert/x509_certificate_openssl.cc index 6e803619db7..ec31e6e371b 100644 --- a/chromium/net/cert/x509_certificate_openssl.cc +++ b/chromium/net/cert/x509_certificate_openssl.cc @@ -13,7 +13,9 @@ #include <openssl/ssl.h> #include <openssl/x509v3.h> +#include "base/macros.h" #include "base/memory/singleton.h" +#include "base/numerics/safe_conversions.h" #include "base/pickle.h" #include "base/sha1.h" #include "base/strings/string_number_conversions.h" @@ -38,7 +40,8 @@ using ScopedGENERAL_NAMES = crypto::ScopedOpenSSL<GENERAL_NAMES, GENERAL_NAMES_free>; void CreateOSCertHandlesFromPKCS7Bytes( - const char* data, int length, + const char* data, + size_t length, X509Certificate::OSCertHandles* handles) { crypto::EnsureOpenSSLInit(); crypto::OpenSSLErrStackTracer err_cleaner(FROM_HERE); @@ -260,24 +263,23 @@ SHA1HashValue X509Certificate::CalculateCAFingerprint( // static X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( - const char* data, int length) { - if (length < 0) - return NULL; + const char* data, + size_t length) { crypto::EnsureOpenSSLInit(); const unsigned char* d2i_data = reinterpret_cast<const unsigned char*>(data); // Don't cache this data for x509_util::GetDER as this wire format // may be not be identical from the i2d_X509 roundtrip. - X509* cert = d2i_X509(NULL, &d2i_data, length); + X509* cert = d2i_X509(NULL, &d2i_data, base::checked_cast<long>(length)); return cert; } // static X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( - const char* data, int length, Format format) { + const char* data, + size_t length, + Format format) { OSCertHandles results; - if (length < 0) - return results; switch (format) { case FORMAT_SINGLE_CERTIFICATE: { diff --git a/chromium/net/cert/x509_certificate_unittest.cc b/chromium/net/cert/x509_certificate_unittest.cc index ec9342ac852..362f7ff0991 100644 --- a/chromium/net/cert/x509_certificate_unittest.cc +++ b/chromium/net/cert/x509_certificate_unittest.cc @@ -1175,7 +1175,7 @@ const struct PublicKeyInfoTestData { // need to be renegerated with a larger key. See https://crbug.com/472291. {"large_key.pem", 0, X509Certificate::kPublicKeyTypeUnknown}, #else - {"large_key.pem", 4104, X509Certificate::kPublicKeyTypeRSA}, + {"large_key.pem", 8200, X509Certificate::kPublicKeyTypeRSA}, #endif }; diff --git a/chromium/net/cert/x509_certificate_win.cc b/chromium/net/cert/x509_certificate_win.cc index 808a2847f9b..d2077821b8c 100644 --- a/chromium/net/cert/x509_certificate_win.cc +++ b/chromium/net/cert/x509_certificate_win.cc @@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" +#include "base/numerics/safe_conversions.h" #include "base/pickle.h" #include "base/sha1.h" #include "base/strings/string_util.h" @@ -94,7 +95,7 @@ void AddCertsFromStore(HCERTSTORE store, X509Certificate::OSCertHandles ParsePKCS7(const char* data, size_t length) { X509Certificate::OSCertHandles results; CERT_BLOB data_blob; - data_blob.cbData = length; + data_blob.cbData = base::checked_cast<DWORD>(length); data_blob.pbData = reinterpret_cast<BYTE*>(const_cast<char*>(data)); HCERTSTORE out_store = NULL; @@ -250,18 +251,25 @@ bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, // static X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( - const char* data, int length) { - OSCertHandle cert_handle = NULL; + const char* data, + size_t length) { + if (!base::IsValueInRangeForNumericType<DWORD>(length)) + return nullptr; + OSCertHandle cert_handle = nullptr; if (!CertAddEncodedCertificateToStore( - NULL, X509_ASN_ENCODING, reinterpret_cast<const BYTE*>(data), - length, CERT_STORE_ADD_USE_EXISTING, &cert_handle)) - return NULL; + NULL, X509_ASN_ENCODING, reinterpret_cast<const BYTE*>(data), + base::checked_cast<DWORD>(length), CERT_STORE_ADD_USE_EXISTING, + &cert_handle)) { + return nullptr; + } return cert_handle; } X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( - const char* data, int length, Format format) { + const char* data, + size_t length, + Format format) { OSCertHandles results; switch (format) { case FORMAT_SINGLE_CERTIFICATE: { diff --git a/chromium/net/cert/x509_util.h b/chromium/net/cert/x509_util.h index a1c29689468..fb8c20f080d 100644 --- a/chromium/net/cert/x509_util.h +++ b/chromium/net/cert/x509_util.h @@ -6,6 +6,7 @@ #define NET_CERT_X509_UTIL_H_ #include <stdint.h> + #include <string> #include "base/memory/ref_counted.h" @@ -30,14 +31,6 @@ enum DigestAlgorithm { DIGEST_SHA256 }; -// Returns true if the times can be used to create an X.509 certificate. -// Certificates can accept dates from Jan 1st, 1 to Dec 31, 9999. A bug in NSS -// limited the range to 1950-9999 -// (https://bugzilla.mozilla.org/show_bug.cgi?id=786531). This function will -// return whether it is supported by the currently used crypto library. -NET_EXPORT_PRIVATE bool IsSupportedValidityRange(base::Time not_valid_before, - base::Time not_valid_after); - // Creates a public-private keypair and a self-signed certificate. // Subject, serial number and validity period are given as parameters. // The certificate is signed by the private key in |key|. The key length and diff --git a/chromium/net/cert/x509_util_android.cc b/chromium/net/cert/x509_util_android.cc index 2a91f4a2792..ee47845f57e 100644 --- a/chromium/net/cert/x509_util_android.cc +++ b/chromium/net/cert/x509_util_android.cc @@ -5,7 +5,7 @@ #include "net/cert/x509_util_android.h" #include "base/android/build_info.h" -#include "base/android/jni_android.h" +#include "base/android/context_utils.h" #include "base/metrics/histogram_macros.h" #include "jni/X509Util_jni.h" #include "net/cert/cert_database.h" @@ -27,16 +27,6 @@ void RecordCertVerifyCapabilitiesHistogram(JNIEnv* env, } } -ScopedJavaLocalRef<jobject> GetApplicationContext( - JNIEnv* env, - const JavaParamRef<jclass>& clazz) { - ScopedJavaLocalRef<jobject> r; - // Must use Reset to force creation of a new local ref, instead of trying to - // adopt the global-ref'ed jobject as a local ref as the constructor would. - r.Reset(env, base::android::GetApplicationContext()); - return r; -} - bool RegisterX509Util(JNIEnv* env) { return RegisterNativesImpl(env); } diff --git a/chromium/net/cert/x509_util_nss.cc b/chromium/net/cert/x509_util_nss.cc index fa6dc1c652a..2dbff2c76fc 100644 --- a/chromium/net/cert/x509_util_nss.cc +++ b/chromium/net/cert/x509_util_nss.cc @@ -180,19 +180,6 @@ bool CreateSelfSignedCert(crypto::RSAPrivateKey* key, return true; } -bool IsSupportedValidityRange(base::Time not_valid_before, - base::Time not_valid_after) { - CERTValidity* validity = CERT_CreateValidity( - crypto::BaseTimeToPRTime(not_valid_before), - crypto::BaseTimeToPRTime(not_valid_after)); - - if (!validity) - return false; - - CERT_DestroyValidity(validity); - return true; -} - } // namespace x509_util } // namespace net diff --git a/chromium/net/cert/x509_util_nss.h b/chromium/net/cert/x509_util_nss.h index bb9bed955cd..55e562effba 100644 --- a/chromium/net/cert/x509_util_nss.h +++ b/chromium/net/cert/x509_util_nss.h @@ -5,6 +5,8 @@ #ifndef NET_CERT_X509_UTIL_NSS_H_ #define NET_CERT_X509_UTIL_NSS_H_ +#include <stddef.h> + #include <string> #include <vector> @@ -47,7 +49,7 @@ void GetSubjectAltName(CERTCertificate* cert_handle, // |format|. Returns an empty collection on failure. X509Certificate::OSCertHandles CreateOSCertHandlesFromBytes( const char* data, - int length, + size_t length, X509Certificate::Format format); // Reads a single certificate from |pickle_iter| and returns a platform-specific diff --git a/chromium/net/cert/x509_util_nss_certs.cc b/chromium/net/cert/x509_util_nss_certs.cc index 78112b44f59..1ec360d31e6 100644 --- a/chromium/net/cert/x509_util_nss_certs.cc +++ b/chromium/net/cert/x509_util_nss_certs.cc @@ -16,6 +16,7 @@ #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/memory/singleton.h" +#include "base/numerics/safe_conversions.h" #include "base/pickle.h" #include "base/strings/stringprintf.h" #include "crypto/ec_private_key.h" @@ -201,11 +202,9 @@ void GetSubjectAltName(CERTCertificate* cert_handle, X509Certificate::OSCertHandles CreateOSCertHandlesFromBytes( const char* data, - int length, + size_t length, X509Certificate::Format format) { X509Certificate::OSCertHandles results; - if (length < 0) - return results; crypto::EnsureNSSInit(); @@ -224,8 +223,9 @@ X509Certificate::OSCertHandles CreateOSCertHandlesFromBytes( // Make a copy since CERT_DecodeCertPackage may modify it std::vector<char> data_copy(data, data + length); - SECStatus result = CERT_DecodeCertPackage(&data_copy[0], length, - CollectCertsCallback, &results); + SECStatus result = CERT_DecodeCertPackage( + data_copy.data(), base::checked_cast<int>(data_copy.size()), + CollectCertsCallback, &results); if (result != SECSuccess) results.clear(); break; diff --git a/chromium/net/cert/x509_util_openssl.cc b/chromium/net/cert/x509_util_openssl.cc index baf7d127613..c81a3a49b39 100644 --- a/chromium/net/cert/x509_util_openssl.cc +++ b/chromium/net/cert/x509_util_openssl.cc @@ -4,6 +4,7 @@ #include "net/cert/x509_util_openssl.h" +#include <limits.h> #include <openssl/asn1.h> #include <openssl/mem.h> @@ -11,6 +12,7 @@ #include "base/lazy_instance.h" #include "base/logging.h" +#include "base/macros.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "crypto/ec_private_key.h" @@ -197,39 +199,6 @@ base::LazyInstance<DERCacheInitSingleton>::Leaky g_der_cache_singleton = } // namespace -bool IsSupportedValidityRange(base::Time not_valid_before, - base::Time not_valid_after) { - if (not_valid_before > not_valid_after) - return false; - - // The validity field of a certificate can only encode years 1-9999. - - // Compute the base::Time values corresponding to Jan 1st,0001 and - // Jan 1st, 10000 respectively. Done by using the pre-computed numbers - // of days between these dates and the Unix epoch, i.e. Jan 1st, 1970, - // using the following Python script: - // - // from datetime import date as D - // print (D(1970,1,1)-D(1,1,1)) # -> 719162 days - // print (D(9999,12,31)-D(1970,1,1)) # -> 2932896 days - // - // Note: This ignores leap seconds, but should be enough in practice. - // - const int64_t kDaysFromYear0001ToUnixEpoch = 719162; - const int64_t kDaysFromUnixEpochToYear10000 = 2932896 + 1; - const base::Time kEpoch = base::Time::UnixEpoch(); - const base::Time kYear0001 = kEpoch - - base::TimeDelta::FromDays(kDaysFromYear0001ToUnixEpoch); - const base::Time kYear10000 = kEpoch + - base::TimeDelta::FromDays(kDaysFromUnixEpochToYear10000); - - if (not_valid_before < kYear0001 || not_valid_before >= kYear10000 || - not_valid_after < kYear0001 || not_valid_after >= kYear10000) - return false; - - return true; -} - bool CreateSelfSignedCert(crypto::RSAPrivateKey* key, DigestAlgorithm alg, const std::string& common_name, diff --git a/chromium/net/cert/x509_util_openssl_unittest.cc b/chromium/net/cert/x509_util_openssl_unittest.cc deleted file mode 100644 index 9eebff8a32e..00000000000 --- a/chromium/net/cert/x509_util_openssl_unittest.cc +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2012 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. - -#include "base/memory/scoped_ptr.h" -#include "crypto/ec_private_key.h" -#include "crypto/openssl_util.h" -#include "crypto/scoped_openssl_types.h" -#include "net/cert/x509_util.h" -#include "net/cert/x509_util_openssl.h" -#include "net/ssl/scoped_openssl_types.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace net { - -TEST(X509UtilOpenSSLTest, IsSupportedValidityRange) { - base::Time now = base::Time::Now(); - EXPECT_TRUE(x509_util::IsSupportedValidityRange(now, now)); - EXPECT_FALSE(x509_util::IsSupportedValidityRange( - now, now - base::TimeDelta::FromSeconds(1))); - - // See x509_util_openssl.cc to see how these were computed. - const int64_t kDaysFromYear0001ToUnixEpoch = 719162; - const int64_t kDaysFromUnixEpochToYear10000 = 2932896 + 1; - - // When computing too_old / too_late, add one day to account for - // possible leap seconds. - base::Time too_old = base::Time::UnixEpoch() - - base::TimeDelta::FromDays(kDaysFromYear0001ToUnixEpoch + 1); - - base::Time too_late = base::Time::UnixEpoch() + - base::TimeDelta::FromDays(kDaysFromUnixEpochToYear10000 + 1); - - EXPECT_FALSE(x509_util::IsSupportedValidityRange(too_old, too_old)); - EXPECT_FALSE(x509_util::IsSupportedValidityRange(too_old, now)); - - EXPECT_FALSE(x509_util::IsSupportedValidityRange(now, too_late)); - EXPECT_FALSE(x509_util::IsSupportedValidityRange(too_late, too_late)); -} - -} // namespace net |