blob: 7bccdf4ce1f2a726e4845ff1263083c03295c978 [file] [log] [blame]
[email protected]130686a2012-11-06 18:22:091// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]6e7845ae2013-03-29 21:48:115#include "net/cert/x509_util.h"
[email protected]130686a2012-11-06 18:22:096
Matt Muellera4193272017-12-07 00:23:347#include <string.h>
David Benjamin03c28a42018-05-11 23:12:078#include <map>
danakj3a4770d2016-04-16 03:09:299#include <memory>
10
David Benjaminf349dc4b2017-08-04 19:17:0011#include "base/lazy_instance.h"
Hans Wennborga65658a2020-04-21 08:09:4612#include "base/logging.h"
Keishi Hattori0e45c022021-11-27 09:25:5213#include "base/memory/raw_ptr.h"
Hans Wennborg725d0432020-06-18 13:54:1614#include "base/notreached.h"
Nina Satragno4cca617292019-12-19 17:00:5015#include "base/strings/string_split.h"
David Benjaminbdc94d72017-08-07 23:25:2116#include "base/strings/string_util.h"
[email protected]9da992db2013-06-28 05:40:4717#include "base/time/time.h"
David Benjaminf349dc4b2017-08-04 19:17:0018#include "build/build_config.h"
David Benjaminbdc94d72017-08-07 23:25:2119#include "crypto/openssl_util.h"
[email protected]d99b2fb42013-11-01 05:14:2920#include "crypto/rsa_private_key.h"
Ryan Sleevi3dabe0b2018-04-05 03:59:0121#include "crypto/sha2.h"
asanka5ffd5d72016-03-23 16:20:4922#include "net/base/hash_value.h"
Ryan Sleevi3dabe0b2018-04-05 03:59:0123#include "net/cert/asn1_util.h"
Eric Roman7b45a272017-08-02 03:21:4424#include "net/cert/internal/cert_errors.h"
jam8b3813b72016-09-06 20:25:4725#include "net/cert/internal/name_constraints.h"
asanka5ffd5d72016-03-23 16:20:4926#include "net/cert/internal/parse_certificate.h"
jam8b3813b72016-09-06 20:25:4727#include "net/cert/internal/parse_name.h"
asanka5ffd5d72016-03-23 16:20:4928#include "net/cert/internal/signature_algorithm.h"
[email protected]6e7845ae2013-03-29 21:48:1129#include "net/cert/x509_certificate.h"
David Benjaminbdc94d72017-08-07 23:25:2130#include "net/der/encode_values.h"
jam8b3813b72016-09-06 20:25:4731#include "net/der/input.h"
32#include "net/der/parse_values.h"
David Benjaminbdc94d72017-08-07 23:25:2133#include "third_party/boringssl/src/include/openssl/bytestring.h"
David Benjaminf349dc4b2017-08-04 19:17:0034#include "third_party/boringssl/src/include/openssl/digest.h"
David Benjaminbdc94d72017-08-07 23:25:2135#include "third_party/boringssl/src/include/openssl/evp.h"
36#include "third_party/boringssl/src/include/openssl/mem.h"
Matt Muellerc458af12021-11-11 19:33:1637#include "third_party/boringssl/src/include/openssl/pkcs7.h"
David Benjaminf349dc4b2017-08-04 19:17:0038#include "third_party/boringssl/src/include/openssl/pool.h"
39#include "third_party/boringssl/src/include/openssl/stack.h"
[email protected]130686a2012-11-06 18:22:0940
Tsuyoshi Horo4f516be2022-06-14 11:53:1341namespace net::x509_util {
David Benjaminf349dc4b2017-08-04 19:17:0042
jam8b3813b72016-09-06 20:25:4743namespace {
44
David Benjaminbdc94d72017-08-07 23:25:2145bool AddRSASignatureAlgorithm(CBB* cbb, DigestAlgorithm algorithm) {
David Benjaminbdc94d72017-08-07 23:25:2146 // See RFC 4055.
47 static const uint8_t kSHA256WithRSAEncryption[] = {
48 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b};
49
50 // An AlgorithmIdentifier is described in RFC 5280, 4.1.1.2.
51 CBB sequence, oid, params;
52 if (!CBB_add_asn1(cbb, &sequence, CBS_ASN1_SEQUENCE) ||
53 !CBB_add_asn1(&sequence, &oid, CBS_ASN1_OBJECT)) {
54 return false;
55 }
56
57 switch (algorithm) {
David Benjaminbdc94d72017-08-07 23:25:2158 case DIGEST_SHA256:
59 if (!CBB_add_bytes(&oid, kSHA256WithRSAEncryption,
60 sizeof(kSHA256WithRSAEncryption)))
61 return false;
62 break;
63 }
64
65 // All supported algorithms use null parameters.
66 if (!CBB_add_asn1(&sequence, &params, CBS_ASN1_NULL) || !CBB_flush(cbb)) {
67 return false;
68 }
69
70 return true;
71}
72
73const EVP_MD* ToEVP(DigestAlgorithm alg) {
74 switch (alg) {
David Benjaminbdc94d72017-08-07 23:25:2175 case DIGEST_SHA256:
76 return EVP_sha256();
77 }
78 return nullptr;
79}
80
Christine Franksf4373ad2022-02-17 19:21:3281class BufferPoolSingleton {
82 public:
83 BufferPoolSingleton() : pool_(CRYPTO_BUFFER_POOL_new()) {}
84 CRYPTO_BUFFER_POOL* pool() { return pool_; }
85
86 private:
87 // The singleton is leaky, so there is no need to use a smart pointer.
88 raw_ptr<CRYPTO_BUFFER_POOL> pool_;
89};
90
91base::LazyInstance<BufferPoolSingleton>::Leaky g_buffer_pool_singleton =
92 LAZY_INSTANCE_INITIALIZER;
93
94} // namespace
95
Nina Satragno4cca617292019-12-19 17:00:5096// Adds an X.509 Name with the specified distinguished name to |cbb|.
97bool AddName(CBB* cbb, base::StringPiece name) {
David Benjaminbdc94d72017-08-07 23:25:2198 // See RFC 4519.
99 static const uint8_t kCommonName[] = {0x55, 0x04, 0x03};
Nina Satragno4cca617292019-12-19 17:00:50100 static const uint8_t kCountryName[] = {0x55, 0x04, 0x06};
101 static const uint8_t kOrganizationName[] = {0x55, 0x04, 0x0a};
102 static const uint8_t kOrganizationalUnitName[] = {0x55, 0x04, 0x0b};
103
104 std::vector<std::string> attributes = SplitString(
105 name, /*separators=*/",", base::WhitespaceHandling::TRIM_WHITESPACE,
106 base::SplitResult::SPLIT_WANT_NONEMPTY);
107
108 if (attributes.size() == 0) {
109 LOG(ERROR) << "Missing DN or wrong format";
110 return false;
111 }
David Benjaminbdc94d72017-08-07 23:25:21112
113 // See RFC 5280, section 4.1.2.4.
Nina Satragno4cca617292019-12-19 17:00:50114 CBB rdns;
115 if (!CBB_add_asn1(cbb, &rdns, CBS_ASN1_SEQUENCE)) {
116 return false;
117 }
118
119 for (const std::string& attribute : attributes) {
120 std::vector<std::string> parts =
121 SplitString(attribute, /*separators=*/"=",
122 base::WhitespaceHandling::KEEP_WHITESPACE,
123 base::SplitResult::SPLIT_WANT_ALL);
124 if (parts.size() != 2) {
125 LOG(ERROR) << "Wrong DN format at " + attribute;
126 return false;
127 }
128
129 const std::string& type_string = parts[0];
130 const std::string& value_string = parts[1];
131 base::span<const uint8_t> type_bytes;
132 if (type_string == "CN") {
133 type_bytes = kCommonName;
134 } else if (type_string == "C") {
135 type_bytes = kCountryName;
136 } else if (type_string == "O") {
137 type_bytes = kOrganizationName;
138 } else if (type_string == "OU") {
139 type_bytes = kOrganizationalUnitName;
140 } else {
141 LOG(ERROR) << "Unrecognized type " + type_string;
142 return false;
143 }
144
145 CBB rdn, attr, type, value;
146 if (!CBB_add_asn1(&rdns, &rdn, CBS_ASN1_SET) ||
147 !CBB_add_asn1(&rdn, &attr, CBS_ASN1_SEQUENCE) ||
148 !CBB_add_asn1(&attr, &type, CBS_ASN1_OBJECT) ||
149 !CBB_add_bytes(&type, type_bytes.data(), type_bytes.size()) ||
Jeongwoo Park7f559082020-08-10 21:50:16150 !CBB_add_asn1(&attr, &value, type_string == "C" ?
151 CBS_ASN1_PRINTABLESTRING : CBS_ASN1_UTF8STRING) ||
Nina Satragno4cca617292019-12-19 17:00:50152 !CBB_add_bytes(&value,
153 reinterpret_cast<const uint8_t*>(value_string.data()),
154 value_string.size()) ||
155 !CBB_flush(&rdns)) {
156 return false;
157 }
158 }
159 if (!CBB_flush(cbb)) {
David Benjaminbdc94d72017-08-07 23:25:21160 return false;
161 }
162 return true;
163}
164
Matt Mueller0a8ada32020-05-08 19:24:14165bool CBBAddTime(CBB* cbb, base::Time time) {
David Benjaminbdc94d72017-08-07 23:25:21166 der::GeneralizedTime generalized_time;
167 if (!der::EncodeTimeAsGeneralizedTime(time, &generalized_time))
168 return false;
169
170 // Per RFC 5280, 4.1.2.5, times which fit in UTCTime must be encoded as
171 // UTCTime rather than GeneralizedTime.
172 CBB child;
173 uint8_t* out;
174 if (generalized_time.InUTCTimeRange()) {
175 return CBB_add_asn1(cbb, &child, CBS_ASN1_UTCTIME) &&
176 CBB_add_space(&child, &out, der::kUTCTimeLength) &&
177 der::EncodeUTCTime(generalized_time, out) && CBB_flush(cbb);
178 }
179
180 return CBB_add_asn1(cbb, &child, CBS_ASN1_GENERALIZEDTIME) &&
181 CBB_add_space(&child, &out, der::kGeneralizedTimeLength) &&
182 der::EncodeGeneralizedTime(generalized_time, out) && CBB_flush(cbb);
183}
184
David Benjaminf349dc4b2017-08-04 19:17:00185bool GetTLSServerEndPointChannelBinding(const X509Certificate& certificate,
186 std::string* token) {
187 static const char kChannelBindingPrefix[] = "tls-server-end-point:";
188
Matt Muellera4193272017-12-07 00:23:34189 base::StringPiece der_encoded_certificate =
190 x509_util::CryptoBufferAsStringPiece(certificate.cert_buffer());
David Benjaminf349dc4b2017-08-04 19:17:00191
192 der::Input tbs_certificate_tlv;
193 der::Input signature_algorithm_tlv;
194 der::BitString signature_value;
Matt Muellera4193272017-12-07 00:23:34195 if (!ParseCertificate(der::Input(der_encoded_certificate),
David Benjaminf349dc4b2017-08-04 19:17:00196 &tbs_certificate_tlv, &signature_algorithm_tlv,
197 &signature_value, nullptr))
198 return false;
199
200 std::unique_ptr<SignatureAlgorithm> signature_algorithm =
201 SignatureAlgorithm::Create(signature_algorithm_tlv, nullptr);
202 if (!signature_algorithm)
203 return false;
204
205 const EVP_MD* digest_evp_md = nullptr;
206 switch (signature_algorithm->digest()) {
207 case net::DigestAlgorithm::Md2:
208 case net::DigestAlgorithm::Md4:
209 // Shouldn't be reachable.
210 digest_evp_md = nullptr;
211 break;
212
213 // Per RFC 5929 section 4.1, MD5 and SHA1 map to SHA256.
214 case net::DigestAlgorithm::Md5:
215 case net::DigestAlgorithm::Sha1:
216 case net::DigestAlgorithm::Sha256:
217 digest_evp_md = EVP_sha256();
218 break;
219
220 case net::DigestAlgorithm::Sha384:
221 digest_evp_md = EVP_sha384();
222 break;
223
224 case net::DigestAlgorithm::Sha512:
225 digest_evp_md = EVP_sha512();
226 break;
227 }
228 if (!digest_evp_md)
229 return false;
230
231 uint8_t digest[EVP_MAX_MD_SIZE];
232 unsigned int out_size;
233 if (!EVP_Digest(der_encoded_certificate.data(),
234 der_encoded_certificate.size(), digest, &out_size,
235 digest_evp_md, nullptr))
236 return false;
237
238 token->assign(kChannelBindingPrefix);
239 token->append(digest, digest + out_size);
240 return true;
241}
[email protected]130686a2012-11-06 18:22:09242
[email protected]d99b2fb42013-11-01 05:14:29243// RSA keys created by CreateKeyAndSelfSignedCert will be of this length.
wtc69f8ea82015-06-04 00:08:13244static const uint16_t kRSAKeyLength = 1024;
[email protected]d99b2fb42013-11-01 05:14:29245
David Benjaminccfdc642017-09-15 16:38:20246// Certificates made by CreateKeyAndSelfSignedCert will be signed using this
247// digest algorithm.
[email protected]d99b2fb42013-11-01 05:14:29248static const DigestAlgorithm kSignatureDigestAlgorithm = DIGEST_SHA256;
249
[email protected]d99b2fb42013-11-01 05:14:29250bool CreateKeyAndSelfSignedCert(const std::string& subject,
wtc69f8ea82015-06-04 00:08:13251 uint32_t serial_number,
[email protected]d99b2fb42013-11-01 05:14:29252 base::Time not_valid_before,
253 base::Time not_valid_after,
danakj3a4770d2016-04-16 03:09:29254 std::unique_ptr<crypto::RSAPrivateKey>* key,
[email protected]d99b2fb42013-11-01 05:14:29255 std::string* der_cert) {
danakj3a4770d2016-04-16 03:09:29256 std::unique_ptr<crypto::RSAPrivateKey> new_key(
[email protected]d99b2fb42013-11-01 05:14:29257 crypto::RSAPrivateKey::Create(kRSAKeyLength));
Adam Langley0a4e4db2018-03-20 21:49:52258 if (!new_key)
[email protected]d99b2fb42013-11-01 05:14:29259 return false;
260
Adam Langley09d085792018-03-27 17:51:10261 bool success = CreateSelfSignedCert(new_key->key(), kSignatureDigestAlgorithm,
262 subject, serial_number, not_valid_before,
Adam Langley28254a42018-09-07 18:33:27263 not_valid_after, {}, der_cert);
[email protected]d99b2fb42013-11-01 05:14:29264 if (success)
inlinechan894515af2016-12-09 02:40:10265 *key = std::move(new_key);
[email protected]d99b2fb42013-11-01 05:14:29266
267 return success;
268}
269
Adam Langley28254a42018-09-07 18:33:27270Extension::Extension(base::span<const uint8_t> in_oid,
271 bool in_critical,
272 base::span<const uint8_t> in_contents)
273 : oid(in_oid), critical(in_critical), contents(in_contents) {}
274Extension::~Extension() {}
275Extension::Extension(const Extension&) = default;
276
Adam Langley0a4e4db2018-03-20 21:49:52277bool CreateSelfSignedCert(EVP_PKEY* key,
David Benjaminbdc94d72017-08-07 23:25:21278 DigestAlgorithm alg,
279 const std::string& subject,
280 uint32_t serial_number,
281 base::Time not_valid_before,
282 base::Time not_valid_after,
Adam Langley28254a42018-09-07 18:33:27283 const std::vector<Extension>& extension_specs,
David Benjaminbdc94d72017-08-07 23:25:21284 std::string* der_encoded) {
285 crypto::EnsureOpenSSLInit();
286 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
287
David Benjaminbdc94d72017-08-07 23:25:21288 // See RFC 5280, section 4.1. First, construct the TBSCertificate.
289 bssl::ScopedCBB cbb;
290 CBB tbs_cert, version, validity;
291 uint8_t* tbs_cert_bytes;
292 size_t tbs_cert_len;
293 if (!CBB_init(cbb.get(), 64) ||
294 !CBB_add_asn1(cbb.get(), &tbs_cert, CBS_ASN1_SEQUENCE) ||
295 !CBB_add_asn1(&tbs_cert, &version,
296 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
297 !CBB_add_asn1_uint64(&version, 2) ||
298 !CBB_add_asn1_uint64(&tbs_cert, serial_number) ||
Nina Satragno4cca617292019-12-19 17:00:50299 !AddRSASignatureAlgorithm(&tbs_cert, alg) || // signature
300 !AddName(&tbs_cert, subject) || // issuer
David Benjaminbdc94d72017-08-07 23:25:21301 !CBB_add_asn1(&tbs_cert, &validity, CBS_ASN1_SEQUENCE) ||
Matt Mueller0a8ada32020-05-08 19:24:14302 !CBBAddTime(&validity, not_valid_before) ||
303 !CBBAddTime(&validity, not_valid_after) ||
Nina Satragno4cca617292019-12-19 17:00:50304 !AddName(&tbs_cert, subject) || // subject
305 !EVP_marshal_public_key(&tbs_cert, key)) { // subjectPublicKeyInfo
David Benjaminbdc94d72017-08-07 23:25:21306 return false;
307 }
Adam Langley28254a42018-09-07 18:33:27308
309 if (!extension_specs.empty()) {
310 CBB outer_extensions, extensions;
311 if (!CBB_add_asn1(&tbs_cert, &outer_extensions,
312 3 | CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED) ||
313 !CBB_add_asn1(&outer_extensions, &extensions, CBS_ASN1_SEQUENCE)) {
314 return false;
315 }
316
317 for (const auto& extension_spec : extension_specs) {
318 CBB extension, oid, value;
319 if (!CBB_add_asn1(&extensions, &extension, CBS_ASN1_SEQUENCE) ||
320 !CBB_add_asn1(&extension, &oid, CBS_ASN1_OBJECT) ||
321 !CBB_add_bytes(&oid, extension_spec.oid.data(),
322 extension_spec.oid.size()) ||
323 (extension_spec.critical && !CBB_add_asn1_bool(&extension, 1)) ||
324 !CBB_add_asn1(&extension, &value, CBS_ASN1_OCTETSTRING) ||
325 !CBB_add_bytes(&value, extension_spec.contents.data(),
326 extension_spec.contents.size()) ||
327 !CBB_flush(&extensions)) {
328 return false;
329 }
330 }
331
332 if (!CBB_flush(&tbs_cert)) {
333 return false;
334 }
335 }
336
337 if (!CBB_finish(cbb.get(), &tbs_cert_bytes, &tbs_cert_len))
338 return false;
David Benjaminbdc94d72017-08-07 23:25:21339 bssl::UniquePtr<uint8_t> delete_tbs_cert_bytes(tbs_cert_bytes);
340
341 // Sign the TBSCertificate and write the entire certificate.
342 CBB cert, signature;
343 bssl::ScopedEVP_MD_CTX ctx;
344 uint8_t* sig_out;
345 size_t sig_len;
346 uint8_t* cert_bytes;
347 size_t cert_len;
348 if (!CBB_init(cbb.get(), tbs_cert_len) ||
349 !CBB_add_asn1(cbb.get(), &cert, CBS_ASN1_SEQUENCE) ||
350 !CBB_add_bytes(&cert, tbs_cert_bytes, tbs_cert_len) ||
351 !AddRSASignatureAlgorithm(&cert, alg) ||
352 !CBB_add_asn1(&cert, &signature, CBS_ASN1_BITSTRING) ||
353 !CBB_add_u8(&signature, 0 /* no unused bits */) ||
Adam Langley0a4e4db2018-03-20 21:49:52354 !EVP_DigestSignInit(ctx.get(), nullptr, ToEVP(alg), nullptr, key) ||
David Benjaminbdc94d72017-08-07 23:25:21355 // Compute the maximum signature length.
356 !EVP_DigestSign(ctx.get(), nullptr, &sig_len, tbs_cert_bytes,
357 tbs_cert_len) ||
358 !CBB_reserve(&signature, &sig_out, sig_len) ||
359 // Actually sign the TBSCertificate.
360 !EVP_DigestSign(ctx.get(), sig_out, &sig_len, tbs_cert_bytes,
361 tbs_cert_len) ||
362 !CBB_did_write(&signature, sig_len) ||
363 !CBB_finish(cbb.get(), &cert_bytes, &cert_len)) {
364 return false;
365 }
366 bssl::UniquePtr<uint8_t> delete_cert_bytes(cert_bytes);
367 der_encoded->assign(reinterpret_cast<char*>(cert_bytes), cert_len);
368 return true;
369}
370
David Benjaminf349dc4b2017-08-04 19:17:00371CRYPTO_BUFFER_POOL* GetBufferPool() {
372 return g_buffer_pool_singleton.Get().pool();
373}
374
Matt Muellere6dac722021-11-18 15:33:44375bssl::UniquePtr<CRYPTO_BUFFER> CreateCryptoBuffer(
376 base::span<const uint8_t> data) {
David Benjaminf349dc4b2017-08-04 19:17:00377 return bssl::UniquePtr<CRYPTO_BUFFER>(
Matt Muellere6dac722021-11-18 15:33:44378 CRYPTO_BUFFER_new(data.data(), data.size(), GetBufferPool()));
David Benjaminf349dc4b2017-08-04 19:17:00379}
380
381bssl::UniquePtr<CRYPTO_BUFFER> CreateCryptoBuffer(
382 const base::StringPiece& data) {
383 return bssl::UniquePtr<CRYPTO_BUFFER>(
384 CRYPTO_BUFFER_new(reinterpret_cast<const uint8_t*>(data.data()),
385 data.size(), GetBufferPool()));
386}
387
Matt Muellerf50e1162021-11-01 18:29:53388bssl::UniquePtr<CRYPTO_BUFFER> CreateCryptoBufferFromStaticDataUnsafe(
389 base::span<const uint8_t> data) {
390 return bssl::UniquePtr<CRYPTO_BUFFER>(
391 CRYPTO_BUFFER_new_from_static_data_unsafe(data.data(), data.size(),
392 GetBufferPool()));
393}
394
Matt Muellera4193272017-12-07 00:23:34395bool CryptoBufferEqual(const CRYPTO_BUFFER* a, const CRYPTO_BUFFER* b) {
396 DCHECK(a && b);
397 if (a == b)
398 return true;
399 return CRYPTO_BUFFER_len(a) == CRYPTO_BUFFER_len(b) &&
400 memcmp(CRYPTO_BUFFER_data(a), CRYPTO_BUFFER_data(b),
401 CRYPTO_BUFFER_len(a)) == 0;
402}
403
Matt Mueller0dc37d62017-11-16 04:29:46404base::StringPiece CryptoBufferAsStringPiece(const CRYPTO_BUFFER* buffer) {
405 return base::StringPiece(
406 reinterpret_cast<const char*>(CRYPTO_BUFFER_data(buffer)),
407 CRYPTO_BUFFER_len(buffer));
408}
409
David Benjamin316373d92021-11-04 20:43:25410base::span<const uint8_t> CryptoBufferAsSpan(const CRYPTO_BUFFER* buffer) {
411 return base::make_span(CRYPTO_BUFFER_data(buffer), CRYPTO_BUFFER_len(buffer));
412}
413
David Benjaminf349dc4b2017-08-04 19:17:00414scoped_refptr<X509Certificate> CreateX509CertificateFromBuffers(
David Benjaminc792c6962018-04-26 14:31:14415 const STACK_OF(CRYPTO_BUFFER) * buffers) {
David Benjaminf349dc4b2017-08-04 19:17:00416 if (sk_CRYPTO_BUFFER_num(buffers) == 0) {
417 NOTREACHED();
418 return nullptr;
419 }
420
Matt Muellera4193272017-12-07 00:23:34421 std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediate_chain;
422 for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(buffers); ++i) {
423 intermediate_chain.push_back(
David Benjamin4db85cf2018-07-10 16:10:04424 bssl::UpRef(sk_CRYPTO_BUFFER_value(buffers, i)));
Matt Muellera4193272017-12-07 00:23:34425 }
426 return X509Certificate::CreateFromBuffer(
David Benjamin4db85cf2018-07-10 16:10:04427 bssl::UpRef(sk_CRYPTO_BUFFER_value(buffers, 0)),
Matt Muellera4193272017-12-07 00:23:34428 std::move(intermediate_chain));
David Benjaminf349dc4b2017-08-04 19:17:00429}
430
Matt Muellerc458af12021-11-11 19:33:16431bool CreateCertBuffersFromPKCS7Bytes(
432 base::span<const uint8_t> data,
433 std::vector<bssl::UniquePtr<CRYPTO_BUFFER>>* handles) {
434 crypto::EnsureOpenSSLInit();
435 crypto::OpenSSLErrStackTracer err_cleaner(FROM_HERE);
436
437 CBS der_data;
438 CBS_init(&der_data, data.data(), data.size());
439 STACK_OF(CRYPTO_BUFFER)* certs = sk_CRYPTO_BUFFER_new_null();
440 bool success =
441 PKCS7_get_raw_certificates(certs, &der_data, x509_util::GetBufferPool());
442 if (success) {
443 for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(certs); ++i) {
444 handles->push_back(
445 bssl::UniquePtr<CRYPTO_BUFFER>(sk_CRYPTO_BUFFER_value(certs, i)));
446 }
447 }
448 // |handles| took ownership of the individual buffers, so only free the list
449 // itself.
450 sk_CRYPTO_BUFFER_free(certs);
451
452 return success;
453}
454
Matt Mueller31f64a72017-09-07 23:55:55455ParseCertificateOptions DefaultParseCertificateOptions() {
456 ParseCertificateOptions options;
457 options.allow_invalid_serial_numbers = true;
458 return options;
459}
460
Ryan Sleevi3dabe0b2018-04-05 03:59:01461bool CalculateSha256SpkiHash(const CRYPTO_BUFFER* buffer, HashValue* hash) {
462 base::StringPiece spki;
463 if (!asn1::ExtractSPKIFromDERCert(CryptoBufferAsStringPiece(buffer), &spki)) {
464 return false;
465 }
466 *hash = HashValue(HASH_VALUE_SHA256);
467 crypto::SHA256HashString(spki, hash->data(), hash->size());
468 return true;
469}
470
David Benjamin03c28a42018-05-11 23:12:07471bool SignatureVerifierInitWithCertificate(
472 crypto::SignatureVerifier* verifier,
473 crypto::SignatureVerifier::SignatureAlgorithm signature_algorithm,
474 base::span<const uint8_t> signature,
475 const CRYPTO_BUFFER* certificate) {
476 base::StringPiece cert_der =
477 x509_util::CryptoBufferAsStringPiece(certificate);
478
479 der::Input tbs_certificate_tlv;
480 der::Input signature_algorithm_tlv;
481 der::BitString signature_value;
482 ParsedTbsCertificate tbs;
483 if (!ParseCertificate(der::Input(cert_der), &tbs_certificate_tlv,
484 &signature_algorithm_tlv, &signature_value, nullptr) ||
485 !ParseTbsCertificate(tbs_certificate_tlv,
486 DefaultParseCertificateOptions(), &tbs, nullptr)) {
487 return false;
488 }
489
490 // The key usage extension, if present, must assert the digitalSignature bit.
Hubert Chao07189962022-05-06 15:44:52491 if (tbs.extensions_tlv) {
David Benjamin03c28a42018-05-11 23:12:07492 std::map<der::Input, ParsedExtension> extensions;
Hubert Chao07189962022-05-06 15:44:52493 if (!ParseExtensions(tbs.extensions_tlv.value(), &extensions)) {
David Benjamin03c28a42018-05-11 23:12:07494 return false;
495 }
496 ParsedExtension key_usage_ext;
Matt Muellerc16093c2022-02-11 19:45:27497 if (ConsumeExtension(der::Input(kKeyUsageOid), &extensions,
498 &key_usage_ext)) {
David Benjamin03c28a42018-05-11 23:12:07499 der::BitString key_usage;
500 if (!ParseKeyUsage(key_usage_ext.value, &key_usage) ||
501 !key_usage.AssertsBit(KEY_USAGE_BIT_DIGITAL_SIGNATURE)) {
502 return false;
503 }
504 }
505 }
506
507 return verifier->VerifyInit(
508 signature_algorithm, signature,
509 base::make_span(tbs.spki_tlv.UnsafeData(), tbs.spki_tlv.Length()));
510}
511
David Benjamin07a07d652020-02-26 22:26:59512bool HasSHA1Signature(const CRYPTO_BUFFER* cert_buffer) {
513 der::Input tbs_certificate_tlv;
514 der::Input signature_algorithm_tlv;
515 der::BitString signature_value;
516 if (!ParseCertificate(der::Input(CRYPTO_BUFFER_data(cert_buffer),
517 CRYPTO_BUFFER_len(cert_buffer)),
518 &tbs_certificate_tlv, &signature_algorithm_tlv,
519 &signature_value, /*out_errors=*/nullptr)) {
520 return false;
521 }
522
523 std::unique_ptr<SignatureAlgorithm> signature_algorithm =
524 SignatureAlgorithm::Create(signature_algorithm_tlv, /*errors=*/nullptr);
525 if (!signature_algorithm)
526 return false;
527
528 return signature_algorithm->digest() == net::DigestAlgorithm::Sha1;
529}
530
Tsuyoshi Horo4f516be2022-06-14 11:53:13531} // namespace net::x509_util