OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/cert/ct_objects_extractor.h" | 5 #include "net/cert/ct_objects_extractor.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/sha1.h" | 10 #include "base/sha1.h" |
11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
12 #include "crypto/sha2.h" | 12 #include "crypto/sha2.h" |
13 #include "net/cert/asn1_util.h" | 13 #include "net/cert/asn1_util.h" |
14 #include "net/cert/signed_certificate_timestamp.h" | 14 #include "net/cert/signed_certificate_timestamp.h" |
15 #include "third_party/boringssl/src/include/openssl/bytestring.h" | 15 #include "third_party/boringssl/src/include/openssl/bytestring.h" |
16 #include "third_party/boringssl/src/include/openssl/obj.h" | 16 #include "third_party/boringssl/src/include/openssl/mem.h" |
17 #include "third_party/boringssl/src/include/openssl/x509.h" | |
18 | 17 |
19 namespace net { | 18 namespace net { |
20 | 19 |
21 namespace ct { | 20 namespace ct { |
22 | 21 |
23 namespace { | 22 namespace { |
24 | 23 |
25 // The wire form of the OID 1.3.6.1.4.1.11129.2.4.2. See Section 3.3 of | 24 // The wire form of the OID 1.3.6.1.4.1.11129.2.4.2. See Section 3.3 of |
26 // RFC6962. | 25 // RFC6962. |
27 const uint8_t kEmbeddedSCTOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, | 26 const uint8_t kEmbeddedSCTOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, |
28 0xD6, 0x79, 0x02, 0x04, 0x02}; | 27 0xD6, 0x79, 0x02, 0x04, 0x02}; |
29 | 28 |
30 // The wire form of the OID 1.3.6.1.4.1.11129.2.4.5 - OCSP SingleExtension for | 29 // The wire form of the OID 1.3.6.1.4.1.11129.2.4.5 - OCSP SingleExtension for |
31 // X.509v3 Certificate Transparency Signed Certificate Timestamp List, see | 30 // X.509v3 Certificate Transparency Signed Certificate Timestamp List, see |
32 // Section 3.3 of RFC6962. | 31 // Section 3.3 of RFC6962. |
33 const uint8_t kOCSPExtensionOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, | 32 const uint8_t kOCSPExtensionOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, |
34 0xD6, 0x79, 0x02, 0x04, 0x05}; | 33 0xD6, 0x79, 0x02, 0x04, 0x05}; |
35 | 34 |
| 35 // The wire form of the OID 1.3.6.1.5.5.7.48.1.1. See RFC 6960. |
| 36 const uint8_t kOCSPBasicResponseOid[] = {0x2b, 0x06, 0x01, 0x05, 0x05, |
| 37 0x07, 0x30, 0x01, 0x01}; |
| 38 |
| 39 // The wire form of the OID 1.3.14.3.2.26. |
| 40 const uint8_t kSHA1Oid[] = {0x2b, 0x0e, 0x03, 0x02, 0x1a}; |
| 41 |
| 42 // The wire form of the OID 2.16.840.1.101.3.4.2.1. |
| 43 const uint8_t kSHA256Oid[] = {0x60, 0x86, 0x48, 0x01, 0x65, |
| 44 0x03, 0x04, 0x02, 0x01}; |
| 45 |
36 bool StringEqualToCBS(const std::string& value1, const CBS* value2) { | 46 bool StringEqualToCBS(const std::string& value1, const CBS* value2) { |
37 if (CBS_len(value2) != value1.size()) | 47 if (CBS_len(value2) != value1.size()) |
38 return false; | 48 return false; |
39 return memcmp(value1.data(), CBS_data(value2), CBS_len(value2)) == 0; | 49 return memcmp(value1.data(), CBS_data(value2), CBS_len(value2)) == 0; |
40 } | 50 } |
41 | 51 |
42 bssl::UniquePtr<X509> OSCertHandleToOpenSSL( | 52 bool SkipElements(CBS* cbs, int count) { |
43 X509Certificate::OSCertHandle os_handle) { | 53 for (int i = 0; i < count; i++) { |
44 #if defined(USE_OPENSSL_CERTS) | 54 if (!CBS_get_any_asn1_element(cbs, nullptr, nullptr, nullptr)) |
45 return bssl::UniquePtr<X509>(X509Certificate::DupOSCertHandle(os_handle)); | 55 return false; |
46 #else | 56 } |
47 std::string der_encoded; | 57 return true; |
48 if (!X509Certificate::GetDEREncoded(os_handle, &der_encoded)) | 58 } |
49 return bssl::UniquePtr<X509>(); | 59 |
50 const uint8_t* bytes = reinterpret_cast<const uint8_t*>(der_encoded.data()); | 60 bool SkipOptionalElement(CBS* cbs, unsigned tag) { |
51 return bssl::UniquePtr<X509>(d2i_X509(NULL, &bytes, der_encoded.size())); | 61 CBS unused; |
52 #endif | 62 return !CBS_peek_asn1_tag(cbs, tag) || CBS_get_asn1(cbs, &unused, tag); |
| 63 } |
| 64 |
| 65 // Copies all the bytes in |outer| which are before |inner| to |out|. |inner| |
| 66 // must be a subset of |outer|. |
| 67 bool CopyBefore(const CBS& outer, const CBS& inner, CBB* out) { |
| 68 CHECK_LE(CBS_data(&outer), CBS_data(&inner)); |
| 69 CHECK_LE(CBS_data(&inner) + CBS_len(&inner), |
| 70 CBS_data(&outer) + CBS_len(&outer)); |
| 71 |
| 72 return !!CBB_add_bytes(out, CBS_data(&outer), |
| 73 CBS_data(&inner) - CBS_data(&outer)); |
| 74 } |
| 75 |
| 76 // Copies all the bytes in |outer| which are after |inner| to |out|. |inner| |
| 77 // must be a subset of |outer|. |
| 78 bool CopyAfter(const CBS& outer, const CBS& inner, CBB* out) { |
| 79 CHECK_LE(CBS_data(&outer), CBS_data(&inner)); |
| 80 CHECK_LE(CBS_data(&inner) + CBS_len(&inner), |
| 81 CBS_data(&outer) + CBS_len(&outer)); |
| 82 |
| 83 return !!CBB_add_bytes( |
| 84 out, CBS_data(&inner) + CBS_len(&inner), |
| 85 CBS_data(&outer) + CBS_len(&outer) - CBS_data(&inner) - CBS_len(&inner)); |
| 86 } |
| 87 |
| 88 // Skips |tbs_cert|, which must be a TBSCertificate body, to just before the |
| 89 // extensions element. |
| 90 bool SkipTBSCertificateToExtensions(CBS* tbs_cert) { |
| 91 constexpr unsigned kVersionTag = |
| 92 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0; |
| 93 constexpr unsigned kIssuerUniqueIDTag = |
| 94 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1; |
| 95 constexpr unsigned kSubjectUniqueIDTag = |
| 96 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 2; |
| 97 return SkipOptionalElement(tbs_cert, kVersionTag) && |
| 98 SkipElements(tbs_cert, |
| 99 6 /* serialNumber through subjectPublicKeyInfo */) && |
| 100 SkipOptionalElement(tbs_cert, kIssuerUniqueIDTag) && |
| 101 SkipOptionalElement(tbs_cert, kSubjectUniqueIDTag); |
| 102 } |
| 103 |
| 104 // Looks for the extension with the specified OID in |extensions|, which must |
| 105 // contain the contents of a SEQUENCE of X.509 extension structures. If found, |
| 106 // returns true and sets |*out| to the full extension element. |
| 107 bool FindExtensionElement(const CBS& extensions, |
| 108 const uint8_t* oid, |
| 109 size_t oid_len, |
| 110 CBS* out) { |
| 111 CBS extensions_copy = extensions; |
| 112 CBS result; |
| 113 CBS_init(&result, nullptr, 0); |
| 114 bool found = false; |
| 115 while (CBS_len(&extensions_copy) > 0) { |
| 116 CBS extension_element; |
| 117 if (!CBS_get_asn1_element(&extensions_copy, &extension_element, |
| 118 CBS_ASN1_SEQUENCE)) { |
| 119 return false; |
| 120 } |
| 121 |
| 122 CBS copy = extension_element; |
| 123 CBS extension, extension_oid; |
| 124 if (!CBS_get_asn1(©, &extension, CBS_ASN1_SEQUENCE) || |
| 125 !CBS_get_asn1(&extension, &extension_oid, CBS_ASN1_OBJECT)) { |
| 126 return false; |
| 127 } |
| 128 |
| 129 if (CBS_mem_equal(&extension_oid, oid, oid_len)) { |
| 130 if (found) |
| 131 return false; |
| 132 found = true; |
| 133 result = extension_element; |
| 134 } |
| 135 } |
| 136 if (!found) |
| 137 return false; |
| 138 |
| 139 *out = result; |
| 140 return true; |
53 } | 141 } |
54 | 142 |
55 // Finds the SignedCertificateTimestampList in an extension with OID |oid| in | 143 // Finds the SignedCertificateTimestampList in an extension with OID |oid| in |
56 // |x509_exts|. If found, returns true and sets |*out_sct_list| to the encoded | 144 // |x509_exts|. If found, returns true and sets |*out_sct_list| to the encoded |
57 // SCT list. |out_sct_list| may be NULL. | 145 // SCT list. |
58 bool GetSCTListFromX509_EXTENSIONS(const X509_EXTENSIONS* x509_exts, | 146 bool ParseSCTListFromExtensions(const CBS& extensions, |
59 const uint8_t* oid, | 147 const uint8_t* oid, |
60 size_t oid_len, | 148 size_t oid_len, |
61 std::string* out_sct_list) { | 149 std::string* out_sct_list) { |
62 for (size_t i = 0; i < sk_X509_EXTENSION_num(x509_exts); i++) { | 150 CBS extension_element, extension, extension_oid, value, sct_list; |
63 X509_EXTENSION* x509_ext = sk_X509_EXTENSION_value(x509_exts, i); | 151 if (!FindExtensionElement(extensions, oid, oid_len, &extension_element) || |
64 if (static_cast<size_t>(x509_ext->object->length) == oid_len && | 152 !CBS_get_asn1(&extension_element, &extension, CBS_ASN1_SEQUENCE) || |
65 memcmp(x509_ext->object->data, oid, oid_len) == 0) { | 153 !CBS_get_asn1(&extension, &extension_oid, CBS_ASN1_OBJECT) || |
66 // The SCT list is an OCTET STRING inside the extension. | 154 // Skip the optional critical element. |
67 CBS ext_value, sct_list; | 155 !SkipOptionalElement(&extension, CBS_ASN1_BOOLEAN) || |
68 CBS_init(&ext_value, x509_ext->value->data, x509_ext->value->length); | 156 // The extension value is stored in an OCTET STRING. |
69 if (!CBS_get_asn1(&ext_value, &sct_list, CBS_ASN1_OCTETSTRING) || | 157 !CBS_get_asn1(&extension, &value, CBS_ASN1_OCTETSTRING) || |
70 CBS_len(&ext_value) != 0) { | 158 CBS_len(&extension) != 0 || |
71 return false; | 159 // The extension value itself is an OCTET STRING containing the |
72 } | 160 // serialized SCT list. |
73 if (out_sct_list) { | 161 !CBS_get_asn1(&value, &sct_list, CBS_ASN1_OCTETSTRING) || |
74 *out_sct_list = | 162 CBS_len(&value) != 0) { |
75 std::string(reinterpret_cast<const char*>(CBS_data(&sct_list)), | 163 return false; |
76 CBS_len(&sct_list)); | |
77 } | |
78 return true; | |
79 } | |
80 } | 164 } |
81 return false; | 165 |
| 166 DCHECK(CBS_mem_equal(&extension_oid, oid, oid_len)); |
| 167 *out_sct_list = std::string( |
| 168 reinterpret_cast<const char*>(CBS_data(&sct_list)), CBS_len(&sct_list)); |
| 169 return true; |
82 } | 170 } |
83 | 171 |
84 // Finds the SingleResponse in |responses| which matches |issuer| and | 172 // Finds the SingleResponse in |responses| which matches |issuer| and |
85 // |cert_serial_number|. On success, returns true and sets | 173 // |cert_serial_number|. On success, returns true and sets |
86 // |*out_single_response| to the body of the SingleResponse starting at the | 174 // |*out_single_response| to the body of the SingleResponse starting at the |
87 // |certStatus| field. | 175 // |certStatus| field. |
88 bool FindMatchingSingleResponse(CBS* responses, | 176 bool FindMatchingSingleResponse(CBS* responses, |
89 X509Certificate::OSCertHandle issuer, | 177 X509Certificate::OSCertHandle issuer, |
90 const std::string& cert_serial_number, | 178 const std::string& cert_serial_number, |
91 CBS* out_single_response) { | 179 CBS* out_single_response) { |
92 std::string issuer_der; | 180 std::string issuer_der; |
93 if (!X509Certificate::GetDEREncoded(issuer, &issuer_der)) | 181 if (!X509Certificate::GetDEREncoded(issuer, &issuer_der)) |
94 return false; | 182 return false; |
95 | 183 |
96 base::StringPiece issuer_spki; | 184 base::StringPiece issuer_spki; |
97 if (!asn1::ExtractSPKIFromDERCert(issuer_der, &issuer_spki)) | 185 if (!asn1::ExtractSPKIFromDERCert(issuer_der, &issuer_spki)) |
98 return false; | 186 return false; |
99 | 187 |
100 // In OCSP, only the key itself is under hash. | 188 // In OCSP, only the key itself is under hash. |
101 base::StringPiece issuer_spk; | 189 base::StringPiece issuer_spk; |
102 if (!asn1::ExtractSubjectPublicKeyFromSPKI(issuer_spki, &issuer_spk)) | 190 if (!asn1::ExtractSubjectPublicKeyFromSPKI(issuer_spki, &issuer_spk)) |
103 return false; | 191 return false; |
104 | 192 |
105 // ExtractSubjectPublicKey... does not remove the initial octet encoding the | 193 // ExtractSubjectPublicKeyFromSPKI does not remove the initial octet encoding |
106 // number of unused bits in the ASN.1 BIT STRING so we do it here. For public | 194 // the number of unused bits in the ASN.1 BIT STRING so we do it here. For |
107 // keys, the bitstring is in practice always byte-aligned. | 195 // public keys, the bitstring is in practice always byte-aligned. |
108 if (issuer_spk.empty() || issuer_spk[0] != 0) | 196 if (issuer_spk.empty() || issuer_spk[0] != 0) |
109 return false; | 197 return false; |
110 issuer_spk.remove_prefix(1); | 198 issuer_spk.remove_prefix(1); |
111 | 199 |
112 // TODO(ekasper): add SHA-384 to crypto/sha2.h and here if it proves | 200 // TODO(ekasper): add SHA-384 to crypto/sha2.h and here if it proves |
113 // necessary. | 201 // necessary. |
114 // TODO(ekasper): only compute the hashes on demand. | 202 // TODO(ekasper): only compute the hashes on demand. |
115 std::string issuer_key_sha256_hash = crypto::SHA256HashString(issuer_spk); | 203 std::string issuer_key_sha256_hash = crypto::SHA256HashString(issuer_spk); |
116 std::string issuer_key_sha1_hash = | 204 std::string issuer_key_sha1_hash = |
117 base::SHA1HashString(issuer_spk.as_string()); | 205 base::SHA1HashString(issuer_spk.as_string()); |
(...skipping 14 matching lines...) Expand all Loading... |
132 CBS_len(&cert_id) != 0) { | 220 CBS_len(&cert_id) != 0) { |
133 return false; | 221 return false; |
134 } | 222 } |
135 | 223 |
136 // Check the serial number matches. | 224 // Check the serial number matches. |
137 if (!StringEqualToCBS(cert_serial_number, &serial_number)) | 225 if (!StringEqualToCBS(cert_serial_number, &serial_number)) |
138 continue; | 226 continue; |
139 | 227 |
140 // Check if the issuer_key_hash matches. | 228 // Check if the issuer_key_hash matches. |
141 // TODO(ekasper): also use the issuer name hash in matching. | 229 // TODO(ekasper): also use the issuer name hash in matching. |
142 switch (OBJ_cbs2nid(&hash)) { | 230 if (CBS_mem_equal(&hash, kSHA1Oid, sizeof(kSHA1Oid))) { |
143 case NID_sha1: | 231 if (StringEqualToCBS(issuer_key_sha1_hash, &issuer_key_hash)) { |
144 if (StringEqualToCBS(issuer_key_sha1_hash, &issuer_key_hash)) { | 232 *out_single_response = single_response; |
145 *out_single_response = single_response; | 233 return true; |
146 return true; | 234 } |
147 } | 235 } else if (CBS_mem_equal(&hash, kSHA256Oid, sizeof(kSHA256Oid))) { |
148 break; | 236 if (StringEqualToCBS(issuer_key_sha256_hash, &issuer_key_hash)) { |
149 case NID_sha256: | 237 *out_single_response = single_response; |
150 if (StringEqualToCBS(issuer_key_sha256_hash, &issuer_key_hash)) { | 238 return true; |
151 *out_single_response = single_response; | 239 } |
152 return true; | |
153 } | |
154 break; | |
155 } | 240 } |
156 } | 241 } |
157 | 242 |
158 return false; | 243 return false; |
159 } | 244 } |
160 | 245 |
161 } // namespace | 246 } // namespace |
162 | 247 |
163 bool ExtractEmbeddedSCTList(X509Certificate::OSCertHandle cert, | 248 bool ExtractEmbeddedSCTList(X509Certificate::OSCertHandle cert, |
164 std::string* sct_list) { | 249 std::string* sct_list) { |
165 bssl::UniquePtr<X509> x509(OSCertHandleToOpenSSL(cert)); | 250 std::string der; |
166 if (!x509) | 251 if (!X509Certificate::GetDEREncoded(cert, &der)) |
167 return false; | 252 return false; |
168 X509_EXTENSIONS* x509_exts = x509->cert_info->extensions; | 253 CBS cert_cbs; |
169 if (!x509_exts) | 254 CBS_init(&cert_cbs, reinterpret_cast<const uint8_t*>(der.data()), der.size()); |
| 255 CBS cert_body, tbs_cert, extensions_wrap, extensions; |
| 256 if (!CBS_get_asn1(&cert_cbs, &cert_body, CBS_ASN1_SEQUENCE) || |
| 257 CBS_len(&cert_cbs) != 0 || |
| 258 !CBS_get_asn1(&cert_body, &tbs_cert, CBS_ASN1_SEQUENCE) || |
| 259 !SkipTBSCertificateToExtensions(&tbs_cert) || |
| 260 // Extract the extensions list. |
| 261 !CBS_get_asn1(&tbs_cert, &extensions_wrap, |
| 262 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 3) || |
| 263 !CBS_get_asn1(&extensions_wrap, &extensions, CBS_ASN1_SEQUENCE) || |
| 264 CBS_len(&extensions_wrap) != 0 || CBS_len(&tbs_cert) != 0) { |
170 return false; | 265 return false; |
171 return GetSCTListFromX509_EXTENSIONS(x509->cert_info->extensions, | 266 } |
172 kEmbeddedSCTOid, sizeof(kEmbeddedSCTOid), | 267 |
173 sct_list); | 268 return ParseSCTListFromExtensions(extensions, kEmbeddedSCTOid, |
| 269 sizeof(kEmbeddedSCTOid), sct_list); |
174 } | 270 } |
175 | 271 |
176 bool GetPrecertSignedEntry(X509Certificate::OSCertHandle leaf, | 272 bool GetPrecertSignedEntry(X509Certificate::OSCertHandle leaf, |
177 X509Certificate::OSCertHandle issuer, | 273 X509Certificate::OSCertHandle issuer, |
178 SignedEntryData* result) { | 274 SignedEntryData* result) { |
179 result->Reset(); | 275 result->Reset(); |
180 | 276 |
181 bssl::UniquePtr<X509> leaf_x509(OSCertHandleToOpenSSL(leaf)); | 277 std::string leaf_der; |
182 if (!leaf_x509) | 278 if (!X509Certificate::GetDEREncoded(leaf, &leaf_der)) |
183 return false; | 279 return false; |
184 | 280 |
185 // XXX(rsleevi): This check may be overkill, since we should be able to | 281 // Parse the TBSCertificate. |
186 // generate precerts for certs without the extension. For now, just a sanity | 282 CBS cert_cbs; |
187 // check to match the reference implementation. | 283 CBS_init(&cert_cbs, reinterpret_cast<const uint8_t*>(leaf_der.data()), |
188 if (!leaf_x509->cert_info->extensions || | 284 leaf_der.size()); |
189 !GetSCTListFromX509_EXTENSIONS(leaf_x509->cert_info->extensions, | 285 CBS cert_body, tbs_cert; |
190 kEmbeddedSCTOid, sizeof(kEmbeddedSCTOid), | 286 if (!CBS_get_asn1(&cert_cbs, &cert_body, CBS_ASN1_SEQUENCE) || |
191 NULL)) { | 287 CBS_len(&cert_cbs) != 0 || |
| 288 !CBS_get_asn1(&cert_body, &tbs_cert, CBS_ASN1_SEQUENCE)) { |
192 return false; | 289 return false; |
193 } | 290 } |
194 | 291 |
195 // The Precertificate log entry is the final certificate's TBSCertificate | 292 CBS tbs_cert_copy = tbs_cert; |
196 // without the SCT extension (RFC6962, section 3.2). | 293 if (!SkipTBSCertificateToExtensions(&tbs_cert)) |
197 bssl::UniquePtr<X509> leaf_copy(X509_dup(leaf_x509.get())); | 294 return false; |
198 if (!leaf_copy || !leaf_copy->cert_info->extensions) { | 295 |
199 NOTREACHED(); | 296 // Start filling in a new TBSCertificate. Copy everything parsed or skipped |
| 297 // so far to the |new_tbs_cert|. |
| 298 bssl::ScopedCBB cbb; |
| 299 CBB new_tbs_cert; |
| 300 if (!CBB_init(cbb.get(), CBS_len(&tbs_cert_copy)) || |
| 301 !CBB_add_asn1(cbb.get(), &new_tbs_cert, CBS_ASN1_SEQUENCE) || |
| 302 !CopyBefore(tbs_cert_copy, tbs_cert, &new_tbs_cert)) { |
200 return false; | 303 return false; |
201 } | 304 } |
202 X509_EXTENSIONS* leaf_copy_exts = leaf_copy->cert_info->extensions; | 305 |
203 for (size_t i = 0; i < sk_X509_EXTENSION_num(leaf_copy_exts); i++) { | 306 // Parse the extensions list and find the SCT extension. |
204 X509_EXTENSION* ext = sk_X509_EXTENSION_value(leaf_copy_exts, i); | 307 // |
205 if (static_cast<size_t>(ext->object->length) == sizeof(kEmbeddedSCTOid) && | 308 // XXX(rsleevi): We could generate precerts for certs without the extension |
206 memcmp(ext->object->data, kEmbeddedSCTOid, sizeof(kEmbeddedSCTOid)) == | 309 // by leaving the TBSCertificate as-is. The reference implementation does not |
207 0) { | 310 // do this. |
208 X509_EXTENSION_free(sk_X509_EXTENSION_delete(leaf_copy_exts, i)); | 311 constexpr unsigned kExtensionsTag = |
209 X509_CINF_set_modified(leaf_copy->cert_info); | 312 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 3; |
210 break; | 313 CBS extensions_wrap, extensions, sct_extension; |
211 } | 314 if (!CBS_get_asn1(&tbs_cert, &extensions_wrap, kExtensionsTag) || |
| 315 !CBS_get_asn1(&extensions_wrap, &extensions, CBS_ASN1_SEQUENCE) || |
| 316 CBS_len(&extensions_wrap) != 0 || CBS_len(&tbs_cert) != 0 || |
| 317 !FindExtensionElement(extensions, kEmbeddedSCTOid, |
| 318 sizeof(kEmbeddedSCTOid), &sct_extension)) { |
| 319 return false; |
212 } | 320 } |
213 | 321 |
214 std::string to_be_signed; | 322 // Add extensions to the TBSCertificate. Copy all extensions except the |
215 int len = i2d_X509_CINF(leaf_copy->cert_info, NULL); | 323 // embedded SCT extension. |
216 if (len < 0) | 324 CBB new_extensions_wrap, new_extensions; |
| 325 if (!CBB_add_asn1(&new_tbs_cert, &new_extensions_wrap, kExtensionsTag) || |
| 326 !CBB_add_asn1(&new_extensions_wrap, &new_extensions, CBS_ASN1_SEQUENCE) || |
| 327 !CopyBefore(extensions, sct_extension, &new_extensions) || |
| 328 !CopyAfter(extensions, sct_extension, &new_extensions)) { |
217 return false; | 329 return false; |
218 uint8_t* ptr = | 330 } |
219 reinterpret_cast<uint8_t*>(base::WriteInto(&to_be_signed, len + 1)); | 331 |
220 if (i2d_X509_CINF(leaf_copy->cert_info, &ptr) < 0) | 332 uint8_t* new_tbs_cert_der; |
| 333 size_t new_tbs_cert_len; |
| 334 if (!CBB_finish(cbb.get(), &new_tbs_cert_der, &new_tbs_cert_len)) |
221 return false; | 335 return false; |
| 336 bssl::UniquePtr<uint8_t> scoped_new_tbs_cert_der(new_tbs_cert_der); |
222 | 337 |
223 // Extract the issuer's public key. | 338 // Extract the issuer's public key. |
224 std::string issuer_der; | 339 std::string issuer_der; |
225 if (!X509Certificate::GetDEREncoded(issuer, &issuer_der)) | 340 base::StringPiece issuer_key; |
| 341 if (!X509Certificate::GetDEREncoded(issuer, &issuer_der) || |
| 342 !asn1::ExtractSPKIFromDERCert(issuer_der, &issuer_key)) { |
226 return false; | 343 return false; |
227 base::StringPiece issuer_key; | 344 } |
228 if (!asn1::ExtractSPKIFromDERCert(issuer_der, &issuer_key)) | |
229 return false; | |
230 | 345 |
231 // Fill in the SignedEntryData. | 346 // Fill in the SignedEntryData. |
232 result->type = ct::SignedEntryData::LOG_ENTRY_TYPE_PRECERT; | 347 result->type = ct::SignedEntryData::LOG_ENTRY_TYPE_PRECERT; |
233 result->tbs_certificate.swap(to_be_signed); | 348 result->tbs_certificate.assign( |
| 349 reinterpret_cast<const char*>(new_tbs_cert_der), new_tbs_cert_len); |
234 crypto::SHA256HashString(issuer_key, result->issuer_key_hash.data, | 350 crypto::SHA256HashString(issuer_key, result->issuer_key_hash.data, |
235 sizeof(result->issuer_key_hash.data)); | 351 sizeof(result->issuer_key_hash.data)); |
236 | 352 |
237 return true; | 353 return true; |
238 } | 354 } |
239 | 355 |
240 bool GetX509SignedEntry(X509Certificate::OSCertHandle leaf, | 356 bool GetX509SignedEntry(X509Certificate::OSCertHandle leaf, |
241 SignedEntryData* result) { | 357 SignedEntryData* result) { |
242 DCHECK(leaf); | 358 DCHECK(leaf); |
243 | 359 |
(...skipping 13 matching lines...) Expand all Loading... |
257 std::string* sct_list) { | 373 std::string* sct_list) { |
258 // The input is an OCSPResponse. See RFC2560, section 4.2.1. The SCT list is | 374 // The input is an OCSPResponse. See RFC2560, section 4.2.1. The SCT list is |
259 // in the extensions field of the SingleResponse which matches the input | 375 // in the extensions field of the SingleResponse which matches the input |
260 // certificate. | 376 // certificate. |
261 CBS cbs; | 377 CBS cbs; |
262 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(ocsp_response.data()), | 378 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(ocsp_response.data()), |
263 ocsp_response.size()); | 379 ocsp_response.size()); |
264 | 380 |
265 // Parse down to the ResponseBytes. The ResponseBytes is optional, but if it's | 381 // Parse down to the ResponseBytes. The ResponseBytes is optional, but if it's |
266 // missing, this can't include an SCT list. | 382 // missing, this can't include an SCT list. |
267 CBS sequence, response_status, tagged_response_bytes, response_bytes; | 383 CBS sequence, tagged_response_bytes, response_bytes, response_type, response; |
268 CBS response_type, response; | |
269 if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE) || CBS_len(&cbs) != 0 || | 384 if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE) || CBS_len(&cbs) != 0 || |
270 !CBS_get_asn1(&sequence, &response_status, CBS_ASN1_ENUMERATED) || | 385 !SkipElements(&sequence, 1 /* responseStatus */) || |
271 !CBS_get_asn1(&sequence, &tagged_response_bytes, | 386 !CBS_get_asn1(&sequence, &tagged_response_bytes, |
272 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || | 387 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || |
273 CBS_len(&sequence) != 0 || | 388 CBS_len(&sequence) != 0 || |
274 !CBS_get_asn1(&tagged_response_bytes, &response_bytes, | 389 !CBS_get_asn1(&tagged_response_bytes, &response_bytes, |
275 CBS_ASN1_SEQUENCE) || | 390 CBS_ASN1_SEQUENCE) || |
276 CBS_len(&tagged_response_bytes) != 0 || | 391 CBS_len(&tagged_response_bytes) != 0 || |
277 !CBS_get_asn1(&response_bytes, &response_type, CBS_ASN1_OBJECT) || | 392 !CBS_get_asn1(&response_bytes, &response_type, CBS_ASN1_OBJECT) || |
278 !CBS_get_asn1(&response_bytes, &response, CBS_ASN1_OCTETSTRING) || | 393 !CBS_get_asn1(&response_bytes, &response, CBS_ASN1_OCTETSTRING) || |
279 CBS_len(&response_bytes) != 0) { | 394 CBS_len(&response_bytes) != 0) { |
280 return false; | 395 return false; |
281 } | 396 } |
282 | 397 |
283 // The only relevant ResponseType is id-pkix-ocsp-basic. | 398 // The only relevant ResponseType is id-pkix-ocsp-basic. |
284 if (OBJ_cbs2nid(&response_type) != NID_id_pkix_OCSP_basic) | 399 if (!CBS_mem_equal(&response_type, kOCSPBasicResponseOid, |
| 400 sizeof(kOCSPBasicResponseOid))) { |
285 return false; | 401 return false; |
| 402 } |
286 | 403 |
287 // Parse the ResponseData out of the BasicOCSPResponse. Ignore the rest. | 404 // Parse the ResponseData out of the BasicOCSPResponse. Ignore the rest. |
| 405 constexpr unsigned kVersionTag = |
| 406 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0; |
288 CBS basic_response, response_data, responses; | 407 CBS basic_response, response_data, responses; |
289 if (!CBS_get_asn1(&response, &basic_response, CBS_ASN1_SEQUENCE) || | 408 if (!CBS_get_asn1(&response, &basic_response, CBS_ASN1_SEQUENCE) || |
290 CBS_len(&response) != 0 || | 409 CBS_len(&response) != 0 || |
291 !CBS_get_asn1(&basic_response, &response_data, CBS_ASN1_SEQUENCE)) { | 410 !CBS_get_asn1(&basic_response, &response_data, CBS_ASN1_SEQUENCE)) { |
292 } | |
293 | |
294 // Skip the optional version. | |
295 const int kVersionTag = CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0; | |
296 if (CBS_len(&response_data) > 0 && | |
297 CBS_data(&response_data)[0] == kVersionTag && | |
298 !CBS_get_asn1(&response_data, NULL /* version */, kVersionTag)) { | |
299 return false; | 411 return false; |
300 } | 412 } |
301 | 413 |
302 // Extract the list of SingleResponses. | 414 // Extract the list of SingleResponses from the ResponseData. |
303 if (!CBS_get_any_asn1_element(&response_data, NULL /* responderID */, NULL, | 415 if (!SkipOptionalElement(&response_data, kVersionTag) || |
304 NULL) || | 416 !SkipElements(&response_data, 2 /* responderID, producedAt */) || |
305 !CBS_get_any_asn1_element(&response_data, NULL /* producedAt */, NULL, | |
306 NULL) || | |
307 !CBS_get_asn1(&response_data, &responses, CBS_ASN1_SEQUENCE)) { | 417 !CBS_get_asn1(&response_data, &responses, CBS_ASN1_SEQUENCE)) { |
308 return false; | 418 return false; |
309 } | 419 } |
310 | 420 |
311 CBS single_response; | 421 CBS single_response; |
312 if (!FindMatchingSingleResponse(&responses, issuer, cert_serial_number, | 422 if (!FindMatchingSingleResponse(&responses, issuer, cert_serial_number, |
313 &single_response)) { | 423 &single_response)) { |
314 return false; | 424 return false; |
315 } | 425 } |
316 | 426 |
317 // Skip the certStatus and thisUpdate fields. | 427 // Parse the extensions out of the SingleResponse. |
318 if (!CBS_get_any_asn1_element(&single_response, NULL /* certStatus */, NULL, | 428 constexpr unsigned kNextUpdateTag = |
319 NULL) || | 429 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0; |
320 !CBS_get_any_asn1_element(&single_response, NULL /* thisUpdate */, NULL, | 430 constexpr unsigned kSingleExtensionsTag = |
321 NULL)) { | 431 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1; |
| 432 CBS extensions_wrap, extensions; |
| 433 if (!SkipElements(&single_response, 2 /* certStatus, thisUpdate */) || |
| 434 !SkipOptionalElement(&single_response, kNextUpdateTag) || |
| 435 !CBS_get_asn1(&single_response, &extensions_wrap, kSingleExtensionsTag) || |
| 436 !CBS_get_asn1(&extensions_wrap, &extensions, CBS_ASN1_SEQUENCE) || |
| 437 CBS_len(&extensions_wrap) != 0) { |
322 return false; | 438 return false; |
323 } | 439 } |
324 | 440 |
325 const int kNextUpdateTag = | 441 return ParseSCTListFromExtensions(extensions, kOCSPExtensionOid, |
326 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0; | 442 sizeof(kOCSPExtensionOid), sct_list); |
327 const int kSingleExtensionsTag = | |
328 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1; | |
329 | |
330 // Skip the optional nextUpdate field. | |
331 if (CBS_len(&single_response) > 0 && | |
332 CBS_data(&single_response)[0] == kNextUpdateTag && | |
333 !CBS_get_asn1(&single_response, NULL /* nextUpdate */, kNextUpdateTag)) { | |
334 return false; | |
335 } | |
336 | |
337 CBS extensions; | |
338 if (!CBS_get_asn1(&single_response, &extensions, kSingleExtensionsTag)) | |
339 return false; | |
340 const uint8_t* ptr = CBS_data(&extensions); | |
341 bssl::UniquePtr<X509_EXTENSIONS> x509_exts( | |
342 d2i_X509_EXTENSIONS(NULL, &ptr, CBS_len(&extensions))); | |
343 if (!x509_exts || ptr != CBS_data(&extensions) + CBS_len(&extensions)) | |
344 return false; | |
345 | |
346 return GetSCTListFromX509_EXTENSIONS(x509_exts.get(), kOCSPExtensionOid, | |
347 sizeof(kOCSPExtensionOid), sct_list); | |
348 } | 443 } |
349 | 444 |
350 } // namespace ct | 445 } // namespace ct |
351 | 446 |
352 } // namespace net | 447 } // namespace net |
OLD | NEW |