xref: /aosp_15_r20/external/cronet/net/cert/ev_root_ca_metadata.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 The Chromium Authors
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/cert/ev_root_ca_metadata.h"
6 
7 #include <string_view>
8 
9 #include "base/containers/contains.h"
10 #include "base/lazy_instance.h"
11 #include "base/logging.h"
12 #include "build/build_config.h"
13 #include "third_party/boringssl/src/pki/input.h"
14 #if defined(PLATFORM_USES_CHROMIUM_EV_METADATA)
15 #include "third_party/boringssl/src/include/openssl/bytestring.h"
16 #include "third_party/boringssl/src/include/openssl/mem.h"
17 #endif
18 
19 namespace net {
20 
21 namespace {
22 #if defined(PLATFORM_USES_CHROMIUM_EV_METADATA)
23 // Raw metadata.
24 struct EVMetadata {
25   // kMaxOIDsPerCA is the number of OIDs that we can support per root CA. At
26   // least one CA has different EV policies for business vs government
27   // entities and, in the case of cross-signing, we might need to list another
28   // CA's policy OID under the cross-signing root.
29   static const size_t kMaxOIDsPerCA = 2;
30 
31   // The SHA-256 fingerprint of the root CA certificate, used as a unique
32   // identifier for a root CA certificate.
33   SHA256HashValue fingerprint;
34 
35   // The EV policy OIDs of the root CA.
36   const std::string_view policy_oids[kMaxOIDsPerCA];
37 };
38 
39 #include "net/data/ssl/chrome_root_store/chrome-ev-roots-inc.cc"
40 
41 #endif  // defined(PLATFORM_USES_CHROMIUM_EV_METADATA)
42 }  // namespace
43 
44 static base::LazyInstance<EVRootCAMetadata>::Leaky g_ev_root_ca_metadata =
45     LAZY_INSTANCE_INITIALIZER;
46 
47 // static
GetInstance()48 EVRootCAMetadata* EVRootCAMetadata::GetInstance() {
49   return g_ev_root_ca_metadata.Pointer();
50 }
51 
52 #if defined(PLATFORM_USES_CHROMIUM_EV_METADATA)
53 
54 namespace {
55 
OIDStringToDER(std::string_view policy)56 std::string OIDStringToDER(std::string_view policy) {
57   uint8_t* der;
58   size_t len;
59   bssl::ScopedCBB cbb;
60   if (!CBB_init(cbb.get(), 32) ||
61       !CBB_add_asn1_oid_from_text(cbb.get(), policy.data(), policy.size()) ||
62       !CBB_finish(cbb.get(), &der, &len)) {
63     return std::string();
64   }
65   bssl::UniquePtr<uint8_t> delete_der(der);
66   return std::string(reinterpret_cast<const char*>(der), len);
67 }
68 
69 }  // namespace
70 
IsEVPolicyOID(bssl::der::Input policy_oid) const71 bool EVRootCAMetadata::IsEVPolicyOID(bssl::der::Input policy_oid) const {
72   return policy_oids_.find(policy_oid.AsStringView()) != policy_oids_.end();
73 }
74 
HasEVPolicyOID(const SHA256HashValue & fingerprint,bssl::der::Input policy_oid) const75 bool EVRootCAMetadata::HasEVPolicyOID(const SHA256HashValue& fingerprint,
76                                       bssl::der::Input policy_oid) const {
77   PolicyOIDMap::const_iterator iter = ev_policy_.find(fingerprint);
78   if (iter == ev_policy_.end())
79     return false;
80   for (const std::string& ev_oid : iter->second) {
81     if (bssl::der::Input(ev_oid) == policy_oid) {
82       return true;
83     }
84   }
85   return false;
86 }
87 
AddEVCA(const SHA256HashValue & fingerprint,const char * policy)88 bool EVRootCAMetadata::AddEVCA(const SHA256HashValue& fingerprint,
89                                const char* policy) {
90   if (ev_policy_.find(fingerprint) != ev_policy_.end())
91     return false;
92 
93   std::string der_policy = OIDStringToDER(policy);
94   if (der_policy.empty())
95     return false;
96 
97   ev_policy_[fingerprint].push_back(der_policy);
98   policy_oids_.insert(der_policy);
99   return true;
100 }
101 
RemoveEVCA(const SHA256HashValue & fingerprint)102 bool EVRootCAMetadata::RemoveEVCA(const SHA256HashValue& fingerprint) {
103   PolicyOIDMap::iterator it = ev_policy_.find(fingerprint);
104   if (it == ev_policy_.end())
105     return false;
106   std::string oid = it->second[0];
107   ev_policy_.erase(it);
108   policy_oids_.erase(oid);
109   return true;
110 }
111 
112 #else
113 
114 // These are just stub functions for platforms where we don't use this EV
115 // metadata.
116 //
117 
IsEVPolicyOID(bssl::der::Input policy_oid) const118 bool EVRootCAMetadata::IsEVPolicyOID(bssl::der::Input policy_oid) const {
119   LOG(WARNING) << "Not implemented";
120   return false;
121 }
122 
HasEVPolicyOID(const SHA256HashValue & fingerprint,bssl::der::Input policy_oid) const123 bool EVRootCAMetadata::HasEVPolicyOID(const SHA256HashValue& fingerprint,
124                                       bssl::der::Input policy_oid) const {
125   LOG(WARNING) << "Not implemented";
126   return false;
127 }
128 
AddEVCA(const SHA256HashValue & fingerprint,const char * policy)129 bool EVRootCAMetadata::AddEVCA(const SHA256HashValue& fingerprint,
130                                const char* policy) {
131   LOG(WARNING) << "Not implemented";
132   return true;
133 }
134 
RemoveEVCA(const SHA256HashValue & fingerprint)135 bool EVRootCAMetadata::RemoveEVCA(const SHA256HashValue& fingerprint) {
136   LOG(WARNING) << "Not implemented";
137   return true;
138 }
139 
140 #endif
141 
EVRootCAMetadata()142 EVRootCAMetadata::EVRootCAMetadata() {
143 // Constructs the object from the raw metadata in kEvRootCaMetadata.
144 #if defined(PLATFORM_USES_CHROMIUM_EV_METADATA)
145   for (const auto& ev_root : kEvRootCaMetadata) {
146     for (const auto& policy : ev_root.policy_oids) {
147       if (policy.empty())
148         break;
149 
150       std::string policy_der = OIDStringToDER(policy);
151       if (policy_der.empty()) {
152         LOG(ERROR) << "Failed to decode OID: " << policy;
153         continue;
154       }
155 
156       ev_policy_[ev_root.fingerprint].push_back(policy_der);
157       policy_oids_.insert(policy_der);
158     }
159   }
160 #endif
161 }
162 
163 EVRootCAMetadata::~EVRootCAMetadata() = default;
164 
165 }  // namespace net
166