1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/base/ev_root_ca_metadata.h" 6 7 #if defined(USE_NSS) 8 #include <cert.h> 9 #include <pkcs11n.h> 10 #include <secerr.h> 11 #include <secoid.h> 12 #elif defined(OS_WIN) 13 #include <stdlib.h> 14 #endif 15 16 #include "base/lazy_instance.h" 17 #include "base/logging.h" 18 19 namespace net { 20 21 // Raw metadata. 22 struct EVMetadata { 23 // The SHA-1 fingerprint of the root CA certificate, used as a unique 24 // identifier for a root CA certificate. 25 SHA1Fingerprint fingerprint; 26 27 // The EV policy OID of the root CA. 28 // Note: a root CA may have multiple EV policies. When that actually 29 // happens, we'll need to support that. 30 const char* policy_oid; 31 }; 32 33 static const EVMetadata ev_root_ca_metadata[] = { 34 // AddTrust External CA Root 35 // https://addtrustexternalcaroot-ev.comodoca.com 36 { { { 0x02, 0xfa, 0xf3, 0xe2, 0x91, 0x43, 0x54, 0x68, 0x60, 0x78, 37 0x57, 0x69, 0x4d, 0xf5, 0xe4, 0x5b, 0x68, 0x85, 0x18, 0x68 } }, 38 "1.3.6.1.4.1.6449.1.2.1.5.1" 39 }, 40 // AffirmTrust Commercial 41 // https://commercial.affirmtrust.com/ 42 { { { 0xf9, 0xb5, 0xb6, 0x32, 0x45, 0x5f, 0x9c, 0xbe, 0xec, 0x57, 43 0x5f, 0x80, 0xdc, 0xe9, 0x6e, 0x2c, 0xc7, 0xb2, 0x78, 0xb7 } }, 44 "1.3.6.1.4.1.34697.2.1" 45 }, 46 // AffirmTrust Networking 47 // https://networking.affirmtrust.com:4431 48 { { { 0x29, 0x36, 0x21, 0x02, 0x8b, 0x20, 0xed, 0x02, 0xf5, 0x66, 49 0xc5, 0x32, 0xd1, 0xd6, 0xed, 0x90, 0x9f, 0x45, 0x00, 0x2f } }, 50 "1.3.6.1.4.1.34697.2.2" 51 }, 52 // AffirmTrust Premium 53 // https://premium.affirmtrust.com:4432/ 54 { { { 0xd8, 0xa6, 0x33, 0x2c, 0xe0, 0x03, 0x6f, 0xb1, 0x85, 0xf6, 55 0x63, 0x4f, 0x7d, 0x6a, 0x06, 0x65, 0x26, 0x32, 0x28, 0x27 } }, 56 "1.3.6.1.4.1.34697.2.3" 57 }, 58 // AffirmTrust Premium ECC 59 // https://premiumecc.affirmtrust.com:4433/ 60 { { { 0xb8, 0x23, 0x6b, 0x00, 0x2f, 0x1d, 0x16, 0x86, 0x53, 0x01, 61 0x55, 0x6c, 0x11, 0xa4, 0x37, 0xca, 0xeb, 0xff, 0xc3, 0xbb } }, 62 "1.3.6.1.4.1.34697.2.4" 63 }, 64 // CertPlus Class 2 Primary CA (KEYNECTIS) 65 // https://www.keynectis.com/ 66 { { { 0x74, 0x20, 0x74, 0x41, 0x72, 0x9c, 0xdd, 0x92, 0xec, 0x79, 67 0x31, 0xd8, 0x23, 0x10, 0x8d, 0xc2, 0x81, 0x92, 0xe2, 0xbb } }, 68 "1.3.6.1.4.1.22234.2.5.2.3.1" 69 }, 70 // COMODO Certification Authority 71 // https://secure.comodo.com/ 72 { { { 0x66, 0x31, 0xbf, 0x9e, 0xf7, 0x4f, 0x9e, 0xb6, 0xc9, 0xd5, 73 0xa6, 0x0c, 0xba, 0x6a, 0xbe, 0xd1, 0xf7, 0xbd, 0xef, 0x7b } }, 74 "1.3.6.1.4.1.6449.1.2.1.5.1" 75 }, 76 // COMODO ECC Certification Authority 77 // https://comodoecccertificationauthority-ev.comodoca.com/ 78 { { { 0x9f, 0x74, 0x4e, 0x9f, 0x2b, 0x4d, 0xba, 0xec, 0x0f, 0x31, 79 0x2c, 0x50, 0xb6, 0x56, 0x3b, 0x8e, 0x2d, 0x93, 0xc3, 0x11 } }, 80 "1.3.6.1.4.1.6449.1.2.1.5.1" 81 }, 82 // Cybertrust Global Root 83 // https://evup.cybertrust.ne.jp/ctj-ev-upgrader/evseal.gif 84 { { { 0x5f, 0x43, 0xe5, 0xb1, 0xbf, 0xf8, 0x78, 0x8c, 0xac, 0x1c, 85 0xc7, 0xca, 0x4a, 0x9a, 0xc6, 0x22, 0x2b, 0xcc, 0x34, 0xc6 } }, 86 "1.3.6.1.4.1.6334.1.100.1" 87 }, 88 // DigiCert High Assurance EV Root CA 89 // https://www.digicert.com 90 { { { 0x5f, 0xb7, 0xee, 0x06, 0x33, 0xe2, 0x59, 0xdb, 0xad, 0x0c, 91 0x4c, 0x9a, 0xe6, 0xd3, 0x8f, 0x1a, 0x61, 0xc7, 0xdc, 0x25 } }, 92 "2.16.840.1.114412.2.1" 93 }, 94 // Entrust.net Secure Server Certification Authority 95 // https://www.entrust.net/ 96 { { { 0x99, 0xa6, 0x9b, 0xe6, 0x1a, 0xfe, 0x88, 0x6b, 0x4d, 0x2b, 97 0x82, 0x00, 0x7c, 0xb8, 0x54, 0xfc, 0x31, 0x7e, 0x15, 0x39 } }, 98 "2.16.840.1.114028.10.1.2" 99 }, 100 // Entrust Root Certification Authority 101 // https://www.entrust.net/ 102 { { { 0xb3, 0x1e, 0xb1, 0xb7, 0x40, 0xe3, 0x6c, 0x84, 0x02, 0xda, 103 0xdc, 0x37, 0xd4, 0x4d, 0xf5, 0xd4, 0x67, 0x49, 0x52, 0xf9 } }, 104 "2.16.840.1.114028.10.1.2" 105 }, 106 // Equifax Secure Certificate Authority (GeoTrust) 107 // https://www.geotrust.com/ 108 { { { 0xd2, 0x32, 0x09, 0xad, 0x23, 0xd3, 0x14, 0x23, 0x21, 0x74, 109 0xe4, 0x0d, 0x7f, 0x9d, 0x62, 0x13, 0x97, 0x86, 0x63, 0x3a } }, 110 "1.3.6.1.4.1.14370.1.6" 111 }, 112 // GeoTrust Primary Certification Authority 113 // https://www.geotrust.com/ 114 { { { 0x32, 0x3c, 0x11, 0x8e, 0x1b, 0xf7, 0xb8, 0xb6, 0x52, 0x54, 115 0xe2, 0xe2, 0x10, 0x0d, 0xd6, 0x02, 0x90, 0x37, 0xf0, 0x96 } }, 116 "1.3.6.1.4.1.14370.1.6" 117 }, 118 // GlobalSign 119 // https://www.globalsign.com/ 120 { { { 0x75, 0xe0, 0xab, 0xb6, 0x13, 0x85, 0x12, 0x27, 0x1c, 0x04, 121 0xf8, 0x5f, 0xdd, 0xde, 0x38, 0xe4, 0xb7, 0x24, 0x2e, 0xfe } }, 122 "1.3.6.1.4.1.4146.1.1" 123 }, 124 // GlobalSign Root CA 125 { { { 0xb1, 0xbc, 0x96, 0x8b, 0xd4, 0xf4, 0x9d, 0x62, 0x2a, 0xa8, 126 0x9a, 0x81, 0xf2, 0x15, 0x01, 0x52, 0xa4, 0x1d, 0x82, 0x9c } }, 127 "1.3.6.1.4.1.4146.1.1" 128 }, 129 // Go Daddy Class 2 Certification Authority 130 // https://www.godaddy.com/ 131 { { { 0x27, 0x96, 0xba, 0xe6, 0x3f, 0x18, 0x01, 0xe2, 0x77, 0x26, 132 0x1b, 0xa0, 0xd7, 0x77, 0x70, 0x02, 0x8f, 0x20, 0xee, 0xe4 } }, 133 "2.16.840.1.114413.1.7.23.3" 134 }, 135 // GTE CyberTrust Global Root 136 // https://www.cybertrust.ne.jp/ 137 { { { 0x97, 0x81, 0x79, 0x50, 0xd8, 0x1c, 0x96, 0x70, 0xcc, 0x34, 138 0xd8, 0x09, 0xcf, 0x79, 0x44, 0x31, 0x36, 0x7e, 0xf4, 0x74 } }, 139 "1.3.6.1.4.1.6334.1.100.1" 140 }, 141 // Network Solutions Certificate Authority 142 // https://www.networksolutions.com/website-packages/index.jsp 143 { { { 0x74, 0xf8, 0xa3, 0xc3, 0xef, 0xe7, 0xb3, 0x90, 0x06, 0x4b, 144 0x83, 0x90, 0x3c, 0x21, 0x64, 0x60, 0x20, 0xe5, 0xdf, 0xce } }, 145 "1.3.6.1.4.1.782.1.2.1.8.1" 146 }, 147 // QuoVadis Root CA 2 148 // https://www.quovadis.bm/ 149 { { { 0xca, 0x3a, 0xfb, 0xcf, 0x12, 0x40, 0x36, 0x4b, 0x44, 0xb2, 150 0x16, 0x20, 0x88, 0x80, 0x48, 0x39, 0x19, 0x93, 0x7c, 0xf7 } }, 151 "1.3.6.1.4.1.8024.0.2.100.1.2" 152 }, 153 // SecureTrust CA, SecureTrust Corporation 154 // https://www.securetrust.com 155 // https://www.trustwave.com/ 156 { { { 0x87, 0x82, 0xc6, 0xc3, 0x04, 0x35, 0x3b, 0xcf, 0xd2, 0x96, 157 0x92, 0xd2, 0x59, 0x3e, 0x7d, 0x44, 0xd9, 0x34, 0xff, 0x11 } }, 158 "2.16.840.1.114404.1.1.2.4.1" 159 }, 160 // Secure Global CA, SecureTrust Corporation 161 { { { 0x3a, 0x44, 0x73, 0x5a, 0xe5, 0x81, 0x90, 0x1f, 0x24, 0x86, 162 0x61, 0x46, 0x1e, 0x3b, 0x9c, 0xc4, 0x5f, 0xf5, 0x3a, 0x1b } }, 163 "2.16.840.1.114404.1.1.2.4.1" 164 }, 165 // Security Communication RootCA1 166 // https://www.secomtrust.net/contact/form.html 167 { { { 0x36, 0xb1, 0x2b, 0x49, 0xf9, 0x81, 0x9e, 0xd7, 0x4c, 0x9e, 168 0xbc, 0x38, 0x0f, 0xc6, 0x56, 0x8f, 0x5d, 0xac, 0xb2, 0xf7 } }, 169 "1.2.392.200091.100.721.1" 170 }, 171 // Security Communication EV RootCA1 172 // https://www.secomtrust.net/contact/form.html 173 { { { 0xfe, 0xb8, 0xc4, 0x32, 0xdc, 0xf9, 0x76, 0x9a, 0xce, 0xae, 174 0x3d, 0xd8, 0x90, 0x8f, 0xfd, 0x28, 0x86, 0x65, 0x64, 0x7d } }, 175 "1.2.392.200091.100.721.1" 176 }, 177 // StartCom Certification Authority 178 // https://www.startssl.com/ 179 { { { 0x3e, 0x2b, 0xf7, 0xf2, 0x03, 0x1b, 0x96, 0xf3, 0x8c, 0xe6, 180 0xc4, 0xd8, 0xa8, 0x5d, 0x3e, 0x2d, 0x58, 0x47, 0x6a, 0x0f } }, 181 "1.3.6.1.4.1.23223.1.1.1" 182 }, 183 // Starfield Class 2 Certification Authority 184 // https://www.starfieldtech.com/ 185 { { { 0xad, 0x7e, 0x1c, 0x28, 0xb0, 0x64, 0xef, 0x8f, 0x60, 0x03, 186 0x40, 0x20, 0x14, 0xc3, 0xd0, 0xe3, 0x37, 0x0e, 0xb5, 0x8a } }, 187 "2.16.840.1.114414.1.7.23.3" 188 }, 189 // SwissSign Gold CA - G2 190 // https://testevg2.swisssign.net/ 191 { { { 0xd8, 0xc5, 0x38, 0x8a, 0xb7, 0x30, 0x1b, 0x1b, 0x6e, 0xd4, 192 0x7a, 0xe6, 0x45, 0x25, 0x3a, 0x6f, 0x9f, 0x1a, 0x27, 0x61 } }, 193 "2.16.756.1.89.1.2.1.1" 194 }, 195 // Thawte Premium Server CA 196 // https://www.thawte.com/ 197 { { { 0x62, 0x7f, 0x8d, 0x78, 0x27, 0x65, 0x63, 0x99, 0xd2, 0x7d, 198 0x7f, 0x90, 0x44, 0xc9, 0xfe, 0xb3, 0xf3, 0x3e, 0xfa, 0x9a } }, 199 "2.16.840.1.113733.1.7.48.1" 200 }, 201 // thawte Primary Root CA 202 // https://www.thawte.com/ 203 { { { 0x91, 0xc6, 0xd6, 0xee, 0x3e, 0x8a, 0xc8, 0x63, 0x84, 0xe5, 204 0x48, 0xc2, 0x99, 0x29, 0x5c, 0x75, 0x6c, 0x81, 0x7b, 0x81 } }, 205 "2.16.840.1.113733.1.7.48.1" 206 }, 207 // UTN - DATACorp SGC 208 { { { 0x58, 0x11, 0x9f, 0x0e, 0x12, 0x82, 0x87, 0xea, 0x50, 0xfd, 209 0xd9, 0x87, 0x45, 0x6f, 0x4f, 0x78, 0xdc, 0xfa, 0xd6, 0xd4 } }, 210 "1.3.6.1.4.1.6449.1.2.1.5.1" 211 }, 212 // UTN-USERFirst-Hardware 213 { { { 0x04, 0x83, 0xed, 0x33, 0x99, 0xac, 0x36, 0x08, 0x05, 0x87, 214 0x22, 0xed, 0xbc, 0x5e, 0x46, 0x00, 0xe3, 0xbe, 0xf9, 0xd7 } }, 215 "1.3.6.1.4.1.6449.1.2.1.5.1" 216 }, 217 // ValiCert Class 2 Policy Validation Authority 218 // TODO(wtc): bug 1165107: this CA has another policy OID 219 // "2.16.840.1.114414.1.7.23.3". 220 { { { 0x31, 0x7a, 0x2a, 0xd0, 0x7f, 0x2b, 0x33, 0x5e, 0xf5, 0xa1, 221 0xc3, 0x4e, 0x4b, 0x57, 0xe8, 0xb7, 0xd8, 0xf1, 0xfc, 0xa6 } }, 222 "2.16.840.1.114413.1.7.23.3" 223 }, 224 // VeriSign Class 3 Public Primary Certification Authority 225 // https://www.verisign.com/ 226 { { { 0x74, 0x2c, 0x31, 0x92, 0xe6, 0x07, 0xe4, 0x24, 0xeb, 0x45, 227 0x49, 0x54, 0x2b, 0xe1, 0xbb, 0xc5, 0x3e, 0x61, 0x74, 0xe2 } }, 228 "2.16.840.1.113733.1.7.23.6" 229 }, 230 // VeriSign Class 3 Public Primary Certification Authority - G5 231 // https://www.verisign.com/ 232 { { { 0x4e, 0xb6, 0xd5, 0x78, 0x49, 0x9b, 0x1c, 0xcf, 0x5f, 0x58, 233 0x1e, 0xad, 0x56, 0xbe, 0x3d, 0x9b, 0x67, 0x44, 0xa5, 0xe5 } }, 234 "2.16.840.1.113733.1.7.23.6" 235 }, 236 // Wells Fargo WellsSecure Public Root Certificate Authority 237 // https://nerys.wellsfargo.com/test.html 238 { { { 0xe7, 0xb4, 0xf6, 0x9d, 0x61, 0xec, 0x90, 0x69, 0xdb, 0x7e, 239 0x90, 0xa7, 0x40, 0x1a, 0x3c, 0xf4, 0x7d, 0x4f, 0xe8, 0xee } }, 240 "2.16.840.1.114171.500.9" 241 }, 242 // XRamp Global Certification Authority 243 { { { 0xb8, 0x01, 0x86, 0xd1, 0xeb, 0x9c, 0x86, 0xa5, 0x41, 0x04, 244 0xcf, 0x30, 0x54, 0xf3, 0x4c, 0x52, 0xb7, 0xe5, 0x58, 0xc6 } }, 245 "2.16.840.1.114404.1.1.2.4.1" 246 } 247 }; 248 249 #if defined(OS_WIN) 250 // static 251 const EVRootCAMetadata::PolicyOID EVRootCAMetadata::policy_oids_[] = { 252 // The OIDs must be sorted in ascending order. 253 "1.2.392.200091.100.721.1", 254 "1.3.6.1.4.1.14370.1.6", 255 "1.3.6.1.4.1.22234.2.5.2.3.1", 256 "1.3.6.1.4.1.23223.1.1.1", 257 "1.3.6.1.4.1.34697.2.1", 258 "1.3.6.1.4.1.34697.2.2", 259 "1.3.6.1.4.1.34697.2.3", 260 "1.3.6.1.4.1.34697.2.4", 261 "1.3.6.1.4.1.4146.1.1", 262 "1.3.6.1.4.1.6334.1.100.1", 263 "1.3.6.1.4.1.6449.1.2.1.5.1", 264 "1.3.6.1.4.1.782.1.2.1.8.1", 265 "1.3.6.1.4.1.8024.0.2.100.1.2", 266 "2.16.756.1.89.1.2.1.1", 267 "2.16.840.1.113733.1.7.23.6", 268 "2.16.840.1.113733.1.7.48.1", 269 "2.16.840.1.114028.10.1.2", 270 "2.16.840.1.114171.500.9", 271 "2.16.840.1.114404.1.1.2.4.1", 272 "2.16.840.1.114412.2.1", 273 "2.16.840.1.114413.1.7.23.3", 274 "2.16.840.1.114414.1.7.23.3", 275 }; 276 #endif 277 278 static base::LazyInstance<EVRootCAMetadata, 279 base::LeakyLazyInstanceTraits<EVRootCAMetadata> > 280 g_ev_root_ca_metadata(base::LINKER_INITIALIZED); 281 282 // static 283 EVRootCAMetadata* EVRootCAMetadata::GetInstance() { 284 return g_ev_root_ca_metadata.Pointer(); 285 } 286 287 bool EVRootCAMetadata::GetPolicyOID( 288 const SHA1Fingerprint& fingerprint, 289 PolicyOID* policy_oid) const { 290 PolicyOidMap::const_iterator iter = ev_policy_.find(fingerprint); 291 if (iter == ev_policy_.end()) 292 return false; 293 *policy_oid = iter->second; 294 return true; 295 } 296 297 #if defined(OS_WIN) 298 static int PolicyOIDCmp(const void* keyval, const void* datum) { 299 const char* oid1 = reinterpret_cast<const char*>(keyval); 300 const char* const* oid2 = reinterpret_cast<const char* const*>(datum); 301 return strcmp(oid1, *oid2); 302 } 303 304 bool EVRootCAMetadata::IsEVPolicyOID(PolicyOID policy_oid) const { 305 return bsearch(policy_oid, &policy_oids_[0], num_policy_oids_, 306 sizeof(PolicyOID), PolicyOIDCmp) != NULL; 307 } 308 #else 309 bool EVRootCAMetadata::IsEVPolicyOID(PolicyOID policy_oid) const { 310 for (size_t i = 0; i < policy_oids_.size(); ++i) { 311 if (PolicyOIDsAreEqual(policy_oid, policy_oids_[i])) 312 return true; 313 } 314 return false; 315 } 316 #endif 317 318 bool EVRootCAMetadata::HasEVPolicyOID(const SHA1Fingerprint& fingerprint, 319 PolicyOID policy_oid) const { 320 PolicyOID ev_policy_oid; 321 if (!GetPolicyOID(fingerprint, &ev_policy_oid)) 322 return false; 323 return PolicyOIDsAreEqual(ev_policy_oid, policy_oid); 324 } 325 326 EVRootCAMetadata::EVRootCAMetadata() { 327 // Constructs the object from the raw metadata in ev_root_ca_metadata. 328 #if defined(USE_NSS) 329 for (size_t i = 0; i < arraysize(ev_root_ca_metadata); i++) { 330 const EVMetadata& metadata = ev_root_ca_metadata[i]; 331 PRUint8 buf[1024]; 332 SECItem oid_item; 333 oid_item.data = buf; 334 oid_item.len = sizeof(buf); 335 SECStatus status = SEC_StringToOID(NULL, &oid_item, metadata.policy_oid, 0); 336 if (status != SECSuccess) { 337 LOG(ERROR) << "Failed to convert to OID: " << metadata.policy_oid; 338 continue; 339 } 340 // Register the OID. 341 SECOidData od; 342 od.oid.len = oid_item.len; 343 od.oid.data = oid_item.data; 344 od.offset = SEC_OID_UNKNOWN; 345 od.desc = metadata.policy_oid; 346 od.mechanism = CKM_INVALID_MECHANISM; 347 od.supportedExtension = INVALID_CERT_EXTENSION; 348 SECOidTag policy = SECOID_AddEntry(&od); 349 DCHECK(policy != SEC_OID_UNKNOWN); 350 ev_policy_[metadata.fingerprint] = policy; 351 policy_oids_.push_back(policy); 352 } 353 #elif defined(OS_WIN) 354 num_policy_oids_ = arraysize(policy_oids_); 355 // Verify policy_oids_ is in ascending order. 356 for (int i = 0; i < num_policy_oids_ - 1; i++) 357 DCHECK(strcmp(policy_oids_[i], policy_oids_[i + 1]) < 0); 358 359 for (size_t i = 0; i < arraysize(ev_root_ca_metadata); i++) { 360 const EVMetadata& metadata = ev_root_ca_metadata[i]; 361 ev_policy_[metadata.fingerprint] = metadata.policy_oid; 362 // Verify policy_oids_ contains every EV policy OID. 363 DCHECK(IsEVPolicyOID(metadata.policy_oid)); 364 } 365 #else 366 for (size_t i = 0; i < arraysize(ev_root_ca_metadata); i++) { 367 const EVMetadata& metadata = ev_root_ca_metadata[i]; 368 ev_policy_[metadata.fingerprint] = metadata.policy_oid; 369 // Multiple root CA certs may use the same EV policy OID. Having 370 // duplicates in the policy_oids_ array does no harm, so we don't 371 // bother detecting duplicates. 372 policy_oids_.push_back(metadata.policy_oid); 373 } 374 #endif 375 } 376 377 EVRootCAMetadata::~EVRootCAMetadata() { 378 } 379 380 // static 381 bool EVRootCAMetadata::PolicyOIDsAreEqual(PolicyOID a, PolicyOID b) { 382 #if defined(USE_NSS) 383 return a == b; 384 #else 385 return !strcmp(a, b); 386 #endif 387 } 388 389 } // namespace net 390