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 GetPrecertLogEntry(X509Certificate::OSCertHandle leaf, | 272 bool GetPrecertLogEntry(X509Certificate::OSCertHandle leaf, |
177 X509Certificate::OSCertHandle issuer, | 273 X509Certificate::OSCertHandle issuer, |
178 LogEntry* result) { | 274 LogEntry* 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 CBS cert_cbs; |
185 // XXX(rsleevi): This check may be overkill, since we should be able to | 281 CBS_init(&cert_cbs, reinterpret_cast<const uint8_t*>(leaf_der.data()), |
186 // generate precerts for certs without the extension. For now, just a sanity | 282 leaf_der.size()); |
187 // check to match the reference implementation. | 283 CBS cert_body, tbs_cert; |
mattm
2017/04/18 03:07:56
Should this comment be retained?
davidben
2017/04/22 05:51:22
I'm not sure it's possible for it to matter, but I
| |
188 if (!leaf_x509->cert_info->extensions || | 284 if (!CBS_get_asn1(&cert_cbs, &cert_body, CBS_ASN1_SEQUENCE) || |
189 !GetSCTListFromX509_EXTENSIONS(leaf_x509->cert_info->extensions, | 285 CBS_len(&cert_cbs) != 0 || |
190 kEmbeddedSCTOid, sizeof(kEmbeddedSCTOid), | 286 !CBS_get_asn1(&cert_body, &tbs_cert, CBS_ASN1_SEQUENCE)) { |
191 NULL)) { | |
192 return false; | 287 return false; |
193 } | 288 } |
194 | 289 |
195 // The Precertificate log entry is the final certificate's TBSCertificate | 290 // Copy everything up to the extensions to the output. |
196 // without the SCT extension (RFC6962, section 3.2). | 291 CBS tbs_cert_copy = tbs_cert; |
197 bssl::UniquePtr<X509> leaf_copy(X509_dup(leaf_x509.get())); | 292 bssl::ScopedCBB cbb; |
198 if (!leaf_copy || !leaf_copy->cert_info->extensions) { | 293 CBB tbs_cert_cbb; |
mattm
2017/04/18 03:07:56
I found this function to be a bit hard to follow.
davidben
2017/04/22 05:51:22
The ones that end in _cbb are the ones being gener
| |
199 NOTREACHED(); | 294 if (!CBB_init(cbb.get(), CBS_len(&tbs_cert)) || |
295 !CBB_add_asn1(cbb.get(), &tbs_cert_cbb, CBS_ASN1_SEQUENCE) || | |
296 !SkipTBSCertificateToExtensions(&tbs_cert) || | |
297 !CopyBefore(tbs_cert_copy, tbs_cert, &tbs_cert_cbb)) { | |
200 return false; | 298 return false; |
201 } | 299 } |
202 X509_EXTENSIONS* leaf_copy_exts = leaf_copy->cert_info->extensions; | 300 |
203 for (size_t i = 0; i < sk_X509_EXTENSION_num(leaf_copy_exts); i++) { | 301 // Extract and mirror the extensions list. |
204 X509_EXTENSION* ext = sk_X509_EXTENSION_value(leaf_copy_exts, i); | 302 constexpr unsigned kExtensionsTag = |
205 if (static_cast<size_t>(ext->object->length) == sizeof(kEmbeddedSCTOid) && | 303 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 3; |
206 memcmp(ext->object->data, kEmbeddedSCTOid, sizeof(kEmbeddedSCTOid)) == | 304 CBS extensions_wrap, extensions; |
207 0) { | 305 CBB extensions_wrap_cbb, extensions_cbb; |
208 X509_EXTENSION_free(sk_X509_EXTENSION_delete(leaf_copy_exts, i)); | 306 if (!CBS_get_asn1(&tbs_cert, &extensions_wrap, kExtensionsTag) || |
209 X509_CINF_set_modified(leaf_copy->cert_info); | 307 !CBS_get_asn1(&extensions_wrap, &extensions, CBS_ASN1_SEQUENCE) || |
210 break; | 308 CBS_len(&extensions_wrap) != 0 || CBS_len(&tbs_cert) != 0 || |
211 } | 309 !CBB_add_asn1(&tbs_cert_cbb, &extensions_wrap_cbb, kExtensionsTag) || |
310 !CBB_add_asn1(&extensions_wrap_cbb, &extensions_cbb, CBS_ASN1_SEQUENCE)) { | |
311 return false; | |
212 } | 312 } |
213 | 313 |
214 std::string to_be_signed; | 314 // Copy all extensions except the embedded SCT extension. |
215 int len = i2d_X509_CINF(leaf_copy->cert_info, NULL); | 315 CBS sct_extension; |
216 if (len < 0) | 316 if (!FindExtensionElement(extensions, kEmbeddedSCTOid, |
317 sizeof(kEmbeddedSCTOid), &sct_extension) || | |
318 !CopyBefore(extensions, sct_extension, &extensions_cbb) || | |
319 !CopyAfter(extensions, sct_extension, &extensions_cbb)) { | |
217 return false; | 320 return false; |
218 uint8_t* ptr = | 321 } |
219 reinterpret_cast<uint8_t*>(base::WriteInto(&to_be_signed, len + 1)); | 322 |
220 if (i2d_X509_CINF(leaf_copy->cert_info, &ptr) < 0) | 323 uint8_t* new_tbs_cert; |
324 size_t new_tbs_cert_len; | |
325 if (!CBB_finish(cbb.get(), &new_tbs_cert, &new_tbs_cert_len)) | |
221 return false; | 326 return false; |
327 bssl::UniquePtr<uint8_t> scoped_new_tbs_cert(new_tbs_cert); | |
222 | 328 |
223 // Extract the issuer's public key. | 329 // Extract the issuer's public key. |
224 std::string issuer_der; | 330 std::string issuer_der; |
225 if (!X509Certificate::GetDEREncoded(issuer, &issuer_der)) | 331 if (!X509Certificate::GetDEREncoded(issuer, &issuer_der)) |
226 return false; | 332 return false; |
227 base::StringPiece issuer_key; | 333 base::StringPiece issuer_key; |
228 if (!asn1::ExtractSPKIFromDERCert(issuer_der, &issuer_key)) | 334 if (!asn1::ExtractSPKIFromDERCert(issuer_der, &issuer_key)) |
229 return false; | 335 return false; |
230 | 336 |
231 // Fill in the LogEntry. | 337 // Fill in the LogEntry. |
232 result->type = ct::LogEntry::LOG_ENTRY_TYPE_PRECERT; | 338 result->type = ct::LogEntry::LOG_ENTRY_TYPE_PRECERT; |
233 result->tbs_certificate.swap(to_be_signed); | 339 result->tbs_certificate.assign(reinterpret_cast<const char*>(new_tbs_cert), |
340 new_tbs_cert_len); | |
234 crypto::SHA256HashString(issuer_key, result->issuer_key_hash.data, | 341 crypto::SHA256HashString(issuer_key, result->issuer_key_hash.data, |
235 sizeof(result->issuer_key_hash.data)); | 342 sizeof(result->issuer_key_hash.data)); |
236 | 343 |
237 return true; | 344 return true; |
238 } | 345 } |
239 | 346 |
240 bool GetX509LogEntry(X509Certificate::OSCertHandle leaf, LogEntry* result) { | 347 bool GetX509LogEntry(X509Certificate::OSCertHandle leaf, LogEntry* result) { |
241 DCHECK(leaf); | 348 DCHECK(leaf); |
242 | 349 |
243 std::string encoded; | 350 std::string encoded; |
(...skipping 12 matching lines...) Expand all Loading... | |
256 std::string* sct_list) { | 363 std::string* sct_list) { |
257 // The input is an OCSPResponse. See RFC2560, section 4.2.1. The SCT list is | 364 // The input is an OCSPResponse. See RFC2560, section 4.2.1. The SCT list is |
258 // in the extensions field of the SingleResponse which matches the input | 365 // in the extensions field of the SingleResponse which matches the input |
259 // certificate. | 366 // certificate. |
260 CBS cbs; | 367 CBS cbs; |
261 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(ocsp_response.data()), | 368 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(ocsp_response.data()), |
262 ocsp_response.size()); | 369 ocsp_response.size()); |
263 | 370 |
264 // Parse down to the ResponseBytes. The ResponseBytes is optional, but if it's | 371 // Parse down to the ResponseBytes. The ResponseBytes is optional, but if it's |
265 // missing, this can't include an SCT list. | 372 // missing, this can't include an SCT list. |
266 CBS sequence, response_status, tagged_response_bytes, response_bytes; | 373 CBS sequence, tagged_response_bytes, response_bytes, response_type, response; |
267 CBS response_type, response; | |
268 if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE) || CBS_len(&cbs) != 0 || | 374 if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE) || CBS_len(&cbs) != 0 || |
269 !CBS_get_asn1(&sequence, &response_status, CBS_ASN1_ENUMERATED) || | 375 !SkipElements(&sequence, 1 /* responderStatus */) || |
mattm
2017/04/18 03:07:56
responseStatus
davidben
2017/04/22 05:51:22
Done.
| |
270 !CBS_get_asn1(&sequence, &tagged_response_bytes, | 376 !CBS_get_asn1(&sequence, &tagged_response_bytes, |
271 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || | 377 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || |
272 CBS_len(&sequence) != 0 || | 378 CBS_len(&sequence) != 0 || |
273 !CBS_get_asn1(&tagged_response_bytes, &response_bytes, | 379 !CBS_get_asn1(&tagged_response_bytes, &response_bytes, |
274 CBS_ASN1_SEQUENCE) || | 380 CBS_ASN1_SEQUENCE) || |
275 CBS_len(&tagged_response_bytes) != 0 || | 381 CBS_len(&tagged_response_bytes) != 0 || |
276 !CBS_get_asn1(&response_bytes, &response_type, CBS_ASN1_OBJECT) || | 382 !CBS_get_asn1(&response_bytes, &response_type, CBS_ASN1_OBJECT) || |
277 !CBS_get_asn1(&response_bytes, &response, CBS_ASN1_OCTETSTRING) || | 383 !CBS_get_asn1(&response_bytes, &response, CBS_ASN1_OCTETSTRING) || |
278 CBS_len(&response_bytes) != 0) { | 384 CBS_len(&response_bytes) != 0) { |
279 return false; | 385 return false; |
280 } | 386 } |
281 | 387 |
282 // The only relevant ResponseType is id-pkix-ocsp-basic. | 388 // The only relevant ResponseType is id-pkix-ocsp-basic. |
283 if (OBJ_cbs2nid(&response_type) != NID_id_pkix_OCSP_basic) | 389 if (!CBS_mem_equal(&response_type, kOCSPBasicResponseOid, |
390 sizeof(kOCSPBasicResponseOid))) { | |
284 return false; | 391 return false; |
392 } | |
285 | 393 |
286 // Parse the ResponseData out of the BasicOCSPResponse. Ignore the rest. | 394 // Parse the ResponseData out of the BasicOCSPResponse. Ignore the rest. |
395 constexpr unsigned kVersionTag = | |
396 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0; | |
287 CBS basic_response, response_data, responses; | 397 CBS basic_response, response_data, responses; |
288 if (!CBS_get_asn1(&response, &basic_response, CBS_ASN1_SEQUENCE) || | 398 if (!CBS_get_asn1(&response, &basic_response, CBS_ASN1_SEQUENCE) || |
289 CBS_len(&response) != 0 || | 399 CBS_len(&response) != 0 || |
290 !CBS_get_asn1(&basic_response, &response_data, CBS_ASN1_SEQUENCE)) { | 400 !CBS_get_asn1(&basic_response, &response_data, CBS_ASN1_SEQUENCE)) { |
291 } | |
292 | |
293 // Skip the optional version. | |
294 const int kVersionTag = CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0; | |
295 if (CBS_len(&response_data) > 0 && | |
296 CBS_data(&response_data)[0] == kVersionTag && | |
297 !CBS_get_asn1(&response_data, NULL /* version */, kVersionTag)) { | |
298 return false; | 401 return false; |
299 } | 402 } |
300 | 403 |
301 // Extract the list of SingleResponses. | 404 // Extract the list of SingleResponses from the ResponseData. |
302 if (!CBS_get_any_asn1_element(&response_data, NULL /* responderID */, NULL, | 405 if (!SkipOptionalElement(&response_data, kVersionTag) || |
303 NULL) || | 406 !SkipElements(&response_data, 2 /* responseID, producedAt */) || |
mattm
2017/04/18 03:07:56
responderID
davidben
2017/04/22 05:51:22
Done.
| |
304 !CBS_get_any_asn1_element(&response_data, NULL /* producedAt */, NULL, | |
305 NULL) || | |
306 !CBS_get_asn1(&response_data, &responses, CBS_ASN1_SEQUENCE)) { | 407 !CBS_get_asn1(&response_data, &responses, CBS_ASN1_SEQUENCE)) { |
307 return false; | 408 return false; |
308 } | 409 } |
309 | 410 |
310 CBS single_response; | 411 CBS single_response; |
311 if (!FindMatchingSingleResponse(&responses, issuer, cert_serial_number, | 412 if (!FindMatchingSingleResponse(&responses, issuer, cert_serial_number, |
312 &single_response)) { | 413 &single_response)) { |
313 return false; | 414 return false; |
314 } | 415 } |
315 | 416 |
316 // Skip the certStatus and thisUpdate fields. | 417 // Parse the extensions out of the SingleResponse. |
317 if (!CBS_get_any_asn1_element(&single_response, NULL /* certStatus */, NULL, | 418 constexpr unsigned kNextUpdateTag = |
318 NULL) || | 419 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0; |
319 !CBS_get_any_asn1_element(&single_response, NULL /* thisUpdate */, NULL, | 420 constexpr unsigned kSingleExtensionsTag = |
320 NULL)) { | 421 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1; |
422 CBS extensions_wrap, extensions; | |
423 if (!SkipElements(&single_response, 2 /* certStatus, thisUpdate */) || | |
424 !SkipOptionalElement(&single_response, kNextUpdateTag) || | |
425 !CBS_get_asn1(&single_response, &extensions_wrap, kSingleExtensionsTag) || | |
426 !CBS_get_asn1(&extensions_wrap, &extensions, CBS_ASN1_SEQUENCE) || | |
427 CBS_len(&extensions_wrap) != 0) { | |
321 return false; | 428 return false; |
322 } | 429 } |
323 | 430 |
324 const int kNextUpdateTag = | 431 return ParseSCTListFromExtensions(extensions, kOCSPExtensionOid, |
325 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0; | 432 sizeof(kOCSPExtensionOid), sct_list); |
326 const int kSingleExtensionsTag = | |
327 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1; | |
328 | |
329 // Skip the optional nextUpdate field. | |
330 if (CBS_len(&single_response) > 0 && | |
331 CBS_data(&single_response)[0] == kNextUpdateTag && | |
332 !CBS_get_asn1(&single_response, NULL /* nextUpdate */, kNextUpdateTag)) { | |
333 return false; | |
334 } | |
335 | |
336 CBS extensions; | |
337 if (!CBS_get_asn1(&single_response, &extensions, kSingleExtensionsTag)) | |
338 return false; | |
339 const uint8_t* ptr = CBS_data(&extensions); | |
340 bssl::UniquePtr<X509_EXTENSIONS> x509_exts( | |
341 d2i_X509_EXTENSIONS(NULL, &ptr, CBS_len(&extensions))); | |
342 if (!x509_exts || ptr != CBS_data(&extensions) + CBS_len(&extensions)) | |
343 return false; | |
344 | |
345 return GetSCTListFromX509_EXTENSIONS(x509_exts.get(), kOCSPExtensionOid, | |
346 sizeof(kOCSPExtensionOid), sct_list); | |
347 } | 433 } |
348 | 434 |
349 } // namespace ct | 435 } // namespace ct |
350 | 436 |
351 } // namespace net | 437 } // namespace net |
OLD | NEW |