Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(415)

Side by Side Diff: net/cert/ct_objects_extractor.cc

Issue 2816363002: Reimplement ct_objects_extractor.cc without legacy ASN.1 code (Closed)
Patch Set: appease MSVC Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | net/cert/ct_objects_extractor_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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(&copy, &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
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
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
OLDNEW
« no previous file with comments | « no previous file | net/cert/ct_objects_extractor_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698