Home | History | Annotate | Download | only in base
      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