123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "net/test/cert_builder.h"
- #include "base/files/file_path.h"
- #include "base/memory/ptr_util.h"
- #include "base/strings/string_number_conversions.h"
- #include "crypto/ec_private_key.h"
- #include "crypto/openssl_util.h"
- #include "crypto/rsa_private_key.h"
- #include "net/cert/asn1_util.h"
- #include "net/cert/pki/verify_signed_data.h"
- #include "net/cert/x509_util.h"
- #include "net/der/encode_values.h"
- #include "net/der/input.h"
- #include "net/der/parse_values.h"
- #include "net/der/parser.h"
- #include "net/test/cert_test_util.h"
- #include "net/test/test_data_directory.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- #include "third_party/boringssl/src/include/openssl/evp.h"
- #include "third_party/boringssl/src/include/openssl/mem.h"
- #include "url/gurl.h"
- namespace net {
- namespace {
- std::string MakeRandomHexString(size_t num_bytes) {
- std::vector<char> rand_bytes;
- rand_bytes.resize(num_bytes);
- base::RandBytes(rand_bytes.data(), rand_bytes.size());
- return base::HexEncode(rand_bytes.data(), rand_bytes.size());
- }
- std::string Sha256WithRSAEncryption() {
- const uint8_t kSha256WithRSAEncryption[] = {0x30, 0x0D, 0x06, 0x09, 0x2a,
- 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x0b, 0x05, 0x00};
- return std::string(std::begin(kSha256WithRSAEncryption),
- std::end(kSha256WithRSAEncryption));
- }
- std::string Sha1WithRSAEncryption() {
- const uint8_t kSha1WithRSAEncryption[] = {0x30, 0x0D, 0x06, 0x09, 0x2a,
- 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x05, 0x05, 0x00};
- return std::string(std::begin(kSha1WithRSAEncryption),
- std::end(kSha1WithRSAEncryption));
- }
- std::string Md5WithRSAEncryption() {
- const uint8_t kMd5WithRSAEncryption[] = {0x30, 0x0d, 0x06, 0x09, 0x2a,
- 0x86, 0x48, 0x86, 0xf7, 0x0d,
- 0x01, 0x01, 0x04, 0x05, 0x00};
- return std::string(std::begin(kMd5WithRSAEncryption),
- std::end(kMd5WithRSAEncryption));
- }
- std::string EcdsaWithSha256() {
- const uint8_t kDer[] = {0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86,
- 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02};
- return std::string(std::begin(kDer), std::end(kDer));
- }
- std::string EcdsaWithSha1() {
- const uint8_t kDer[] = {0x30, 0x09, 0x06, 0x07, 0x2a, 0x86,
- 0x48, 0xce, 0x3d, 0x04, 0x01};
- return std::string(std::begin(kDer), std::end(kDer));
- }
- // Adds bytes (specified as a StringPiece) to the given CBB.
- // The argument ordering follows the boringssl CBB_* api style.
- bool CBBAddBytes(CBB* cbb, base::StringPiece bytes) {
- return CBB_add_bytes(cbb, reinterpret_cast<const uint8_t*>(bytes.data()),
- bytes.size());
- }
- // Adds bytes (from fixed size array) to the given CBB.
- // The argument ordering follows the boringssl CBB_* api style.
- template <size_t N>
- bool CBBAddBytes(CBB* cbb, const uint8_t (&data)[N]) {
- return CBB_add_bytes(cbb, data, N);
- }
- // Finalizes the CBB to a std::string.
- std::string FinishCBB(CBB* cbb) {
- size_t cbb_len;
- uint8_t* cbb_bytes;
- if (!CBB_finish(cbb, &cbb_bytes, &cbb_len)) {
- ADD_FAILURE() << "CBB_finish() failed";
- return std::string();
- }
- bssl::UniquePtr<uint8_t> delete_bytes(cbb_bytes);
- return std::string(reinterpret_cast<char*>(cbb_bytes), cbb_len);
- }
- } // namespace
- CertBuilder::CertBuilder(CRYPTO_BUFFER* orig_cert, CertBuilder* issuer)
- : CertBuilder(orig_cert, issuer, /*unique_subject_key_identifier=*/true) {}
- // static
- std::unique_ptr<CertBuilder> CertBuilder::FromFile(
- const base::FilePath& cert_and_key_file,
- CertBuilder* issuer) {
- scoped_refptr<X509Certificate> cert = ImportCertFromFile(cert_and_key_file);
- if (!cert)
- return nullptr;
- bssl::UniquePtr<EVP_PKEY> private_key(
- LoadPrivateKeyFromFile(cert_and_key_file));
- if (!private_key)
- return nullptr;
- auto builder = base::WrapUnique(new CertBuilder(cert->cert_buffer(), issuer));
- builder->key_ = std::move(private_key);
- return builder;
- }
- // static
- std::unique_ptr<CertBuilder> CertBuilder::FromStaticCert(CRYPTO_BUFFER* cert,
- EVP_PKEY* key) {
- std::unique_ptr<CertBuilder> builder = base::WrapUnique(
- new CertBuilder(cert, nullptr, /*unique_subject_key_identifier=*/false));
- // |cert_|, |key_|, and |subject_tlv_| must be initialized for |builder| to
- // function as the |issuer| of another CertBuilder.
- builder->cert_ = bssl::UpRef(cert);
- builder->key_ = bssl::UpRef(key);
- base::StringPiece subject_tlv;
- CHECK(asn1::ExtractSubjectFromDERCert(
- x509_util::CryptoBufferAsStringPiece(cert), &subject_tlv));
- builder->subject_tlv_ = std::string(subject_tlv);
- return builder;
- }
- // static
- std::unique_ptr<CertBuilder> CertBuilder::FromStaticCertFile(
- const base::FilePath& cert_and_key_file) {
- scoped_refptr<X509Certificate> cert = ImportCertFromFile(cert_and_key_file);
- if (!cert)
- return nullptr;
- bssl::UniquePtr<EVP_PKEY> private_key(
- LoadPrivateKeyFromFile(cert_and_key_file));
- if (!private_key)
- return nullptr;
- return CertBuilder::FromStaticCert(cert->cert_buffer(), private_key.get());
- }
- // static
- std::unique_ptr<CertBuilder> CertBuilder::FromSubjectPublicKeyInfo(
- base::span<const uint8_t> spki_der,
- CertBuilder* issuer) {
- DCHECK(issuer);
- auto builder = std::make_unique<CertBuilder>(/*orig_cert=*/nullptr, issuer);
- CBS cbs;
- CBS_init(&cbs, spki_der.data(), spki_der.size());
- builder->key_ = bssl::UniquePtr<EVP_PKEY>(EVP_parse_public_key(&cbs));
- // Check that there was no error in `EVP_parse_public_key` and that it
- // consumed the entire public key.
- if (!builder->key_ || (CBS_len(&cbs) != 0))
- return nullptr;
- return builder;
- }
- CertBuilder::~CertBuilder() = default;
- // static
- void CertBuilder::CreateSimpleChain(
- std::unique_ptr<CertBuilder>* out_leaf,
- std::unique_ptr<CertBuilder>* out_intermediate,
- std::unique_ptr<CertBuilder>* out_root) {
- const char kHostname[] = "www.example.com";
- base::FilePath certs_dir =
- GetTestNetDataDirectory()
- .AppendASCII("verify_certificate_chain_unittest")
- .AppendASCII("target-and-intermediate");
- CertificateList orig_certs = CreateCertificateListFromFile(
- certs_dir, "chain.pem", X509Certificate::FORMAT_AUTO);
- ASSERT_EQ(3U, orig_certs.size());
- // Build slightly modified variants of |orig_certs|.
- *out_root =
- std::make_unique<CertBuilder>(orig_certs[2]->cert_buffer(), nullptr);
- (*out_root)->SetSignatureAlgorithm(SignatureAlgorithm::kEcdsaSha256);
- (*out_root)->GenerateECKey();
- *out_intermediate = std::make_unique<CertBuilder>(
- orig_certs[1]->cert_buffer(), out_root->get());
- (*out_intermediate)->EraseExtension(der::Input(kCrlDistributionPointsOid));
- (*out_intermediate)->EraseExtension(der::Input(kAuthorityInfoAccessOid));
- (*out_intermediate)->SetSignatureAlgorithm(SignatureAlgorithm::kEcdsaSha256);
- (*out_intermediate)->GenerateECKey();
- *out_leaf = std::make_unique<CertBuilder>(orig_certs[0]->cert_buffer(),
- out_intermediate->get());
- (*out_leaf)->SetSubjectAltName(kHostname);
- (*out_leaf)->EraseExtension(der::Input(kCrlDistributionPointsOid));
- (*out_leaf)->EraseExtension(der::Input(kAuthorityInfoAccessOid));
- (*out_leaf)->SetSignatureAlgorithm(SignatureAlgorithm::kEcdsaSha256);
- (*out_leaf)->GenerateECKey();
- }
- // static
- void CertBuilder::CreateSimpleChain(std::unique_ptr<CertBuilder>* out_leaf,
- std::unique_ptr<CertBuilder>* out_root) {
- const char kHostname[] = "www.example.com";
- base::FilePath certs_dir = GetTestCertsDirectory();
- auto orig_root = ImportCertFromFile(certs_dir, "root_ca_cert.pem");
- ASSERT_TRUE(orig_root);
- auto orig_leaf = ImportCertFromFile(certs_dir, "ok_cert.pem");
- ASSERT_TRUE(orig_leaf);
- // Build slightly modified variants of |orig_certs|.
- *out_root = std::make_unique<CertBuilder>(orig_root->cert_buffer(), nullptr);
- (*out_root)->SetSignatureAlgorithm(SignatureAlgorithm::kEcdsaSha256);
- (*out_root)->GenerateECKey();
- *out_leaf =
- std::make_unique<CertBuilder>(orig_leaf->cert_buffer(), out_root->get());
- (*out_leaf)->SetSubjectAltName(kHostname);
- (*out_leaf)->SetSignatureAlgorithm(SignatureAlgorithm::kEcdsaSha256);
- (*out_leaf)->GenerateECKey();
- }
- // static
- absl::optional<SignatureAlgorithm> CertBuilder::DefaultSignatureAlgorithmForKey(
- EVP_PKEY* key) {
- if (EVP_PKEY_id(key) == EVP_PKEY_RSA)
- return SignatureAlgorithm::kRsaPkcs1Sha256;
- if (EVP_PKEY_id(key) == EVP_PKEY_EC)
- return SignatureAlgorithm::kEcdsaSha256;
- return absl::nullopt;
- }
- // static
- bool CertBuilder::SignData(SignatureAlgorithm signature_algorithm,
- base::StringPiece tbs_data,
- EVP_PKEY* key,
- CBB* out_signature) {
- if (!key)
- return false;
- int expected_pkey_id = 1;
- const EVP_MD* digest;
- switch (signature_algorithm) {
- case SignatureAlgorithm::kRsaPkcs1Md5:
- expected_pkey_id = EVP_PKEY_RSA;
- digest = EVP_md5();
- break;
- case SignatureAlgorithm::kRsaPkcs1Sha1:
- expected_pkey_id = EVP_PKEY_RSA;
- digest = EVP_sha1();
- break;
- case SignatureAlgorithm::kRsaPkcs1Sha256:
- expected_pkey_id = EVP_PKEY_RSA;
- digest = EVP_sha256();
- break;
- case SignatureAlgorithm::kRsaPkcs1Sha384:
- expected_pkey_id = EVP_PKEY_RSA;
- digest = EVP_sha384();
- break;
- case SignatureAlgorithm::kRsaPkcs1Sha512:
- expected_pkey_id = EVP_PKEY_RSA;
- digest = EVP_sha512();
- break;
- case SignatureAlgorithm::kEcdsaSha1:
- expected_pkey_id = EVP_PKEY_EC;
- digest = EVP_sha1();
- break;
- case SignatureAlgorithm::kEcdsaSha256:
- expected_pkey_id = EVP_PKEY_EC;
- digest = EVP_sha256();
- break;
- case SignatureAlgorithm::kEcdsaSha384:
- expected_pkey_id = EVP_PKEY_EC;
- digest = EVP_sha384();
- break;
- case SignatureAlgorithm::kEcdsaSha512:
- expected_pkey_id = EVP_PKEY_EC;
- digest = EVP_sha512();
- break;
- case SignatureAlgorithm::kRsaPssSha256:
- case SignatureAlgorithm::kRsaPssSha384:
- case SignatureAlgorithm::kRsaPssSha512:
- case SignatureAlgorithm::kRsaPkcs1Md2:
- case SignatureAlgorithm::kRsaPkcs1Md4:
- case SignatureAlgorithm::kDsaSha1:
- case SignatureAlgorithm::kDsaSha256:
- // Unsupported algorithms.
- return false;
- }
- const uint8_t* tbs_bytes = reinterpret_cast<const uint8_t*>(tbs_data.data());
- bssl::ScopedEVP_MD_CTX ctx;
- uint8_t* sig_out;
- size_t sig_len;
- return expected_pkey_id == EVP_PKEY_id(key) &&
- EVP_DigestSignInit(ctx.get(), nullptr, digest, nullptr, key) &&
- EVP_DigestSign(ctx.get(), nullptr, &sig_len, tbs_bytes,
- tbs_data.size()) &&
- CBB_reserve(out_signature, &sig_out, sig_len) &&
- EVP_DigestSign(ctx.get(), sig_out, &sig_len, tbs_bytes,
- tbs_data.size()) &&
- CBB_did_write(out_signature, sig_len);
- }
- // static
- std::string CertBuilder::SignatureAlgorithmToDer(
- SignatureAlgorithm signature_algorithm) {
- switch (signature_algorithm) {
- case SignatureAlgorithm::kRsaPkcs1Md5:
- return Md5WithRSAEncryption();
- case SignatureAlgorithm::kRsaPkcs1Sha1:
- return Sha1WithRSAEncryption();
- case SignatureAlgorithm::kRsaPkcs1Sha256:
- return Sha256WithRSAEncryption();
- case SignatureAlgorithm::kEcdsaSha1:
- return EcdsaWithSha1();
- case SignatureAlgorithm::kEcdsaSha256:
- return EcdsaWithSha256();
- default:
- ADD_FAILURE();
- return std::string();
- }
- }
- void CertBuilder::SetExtension(const der::Input& oid,
- std::string value,
- bool critical) {
- auto& extension_value = extensions_[oid.AsString()];
- extension_value.critical = critical;
- extension_value.value = std::move(value);
- Invalidate();
- }
- void CertBuilder::EraseExtension(const der::Input& oid) {
- extensions_.erase(oid.AsString());
- Invalidate();
- }
- void CertBuilder::SetBasicConstraints(bool is_ca, int path_len) {
- // From RFC 5280:
- //
- // BasicConstraints ::= SEQUENCE {
- // cA BOOLEAN DEFAULT FALSE,
- // pathLenConstraint INTEGER (0..MAX) OPTIONAL }
- bssl::ScopedCBB cbb;
- CBB basic_constraints;
- ASSERT_TRUE(CBB_init(cbb.get(), 64));
- ASSERT_TRUE(CBB_add_asn1(cbb.get(), &basic_constraints, CBS_ASN1_SEQUENCE));
- if (is_ca)
- ASSERT_TRUE(CBB_add_asn1_bool(&basic_constraints, true));
- if (path_len >= 0)
- ASSERT_TRUE(CBB_add_asn1_uint64(&basic_constraints, path_len));
- SetExtension(der::Input(kBasicConstraintsOid), FinishCBB(cbb.get()),
- /*critical=*/true);
- }
- void CertBuilder::SetCaIssuersUrl(const GURL& url) {
- SetCaIssuersAndOCSPUrls({url}, {});
- }
- void CertBuilder::SetCaIssuersAndOCSPUrls(
- const std::vector<GURL>& ca_issuers_urls,
- const std::vector<GURL>& ocsp_urls) {
- std::vector<std::pair<der::Input, GURL>> entries;
- for (const auto& url : ca_issuers_urls)
- entries.emplace_back(der::Input(kAdCaIssuersOid), url);
- for (const auto& url : ocsp_urls)
- entries.emplace_back(der::Input(kAdOcspOid), url);
- ASSERT_GT(entries.size(), 0U);
- // From RFC 5280:
- //
- // AuthorityInfoAccessSyntax ::=
- // SEQUENCE SIZE (1..MAX) OF AccessDescription
- //
- // AccessDescription ::= SEQUENCE {
- // accessMethod OBJECT IDENTIFIER,
- // accessLocation GeneralName }
- bssl::ScopedCBB cbb;
- CBB aia;
- ASSERT_TRUE(CBB_init(cbb.get(), 64));
- ASSERT_TRUE(CBB_add_asn1(cbb.get(), &aia, CBS_ASN1_SEQUENCE));
- for (const auto& entry : entries) {
- CBB access_description, access_method, access_location;
- ASSERT_TRUE(CBB_add_asn1(&aia, &access_description, CBS_ASN1_SEQUENCE));
- ASSERT_TRUE(
- CBB_add_asn1(&access_description, &access_method, CBS_ASN1_OBJECT));
- ASSERT_TRUE(CBBAddBytes(&access_method, entry.first.AsStringPiece()));
- ASSERT_TRUE(CBB_add_asn1(&access_description, &access_location,
- CBS_ASN1_CONTEXT_SPECIFIC | 6));
- ASSERT_TRUE(CBBAddBytes(&access_location, entry.second.spec()));
- ASSERT_TRUE(CBB_flush(&aia));
- }
- SetExtension(der::Input(kAuthorityInfoAccessOid), FinishCBB(cbb.get()));
- }
- void CertBuilder::SetCrlDistributionPointUrl(const GURL& url) {
- SetCrlDistributionPointUrls({url});
- }
- void CertBuilder::SetCrlDistributionPointUrls(const std::vector<GURL>& urls) {
- bssl::ScopedCBB cbb;
- ASSERT_TRUE(CBB_init(cbb.get(), 64));
- CBB dps, dp, dp_name, dp_fullname;
- // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
- ASSERT_TRUE(CBB_add_asn1(cbb.get(), &dps, CBS_ASN1_SEQUENCE));
- // DistributionPoint ::= SEQUENCE {
- // distributionPoint [0] DistributionPointName OPTIONAL,
- // reasons [1] ReasonFlags OPTIONAL,
- // cRLIssuer [2] GeneralNames OPTIONAL }
- ASSERT_TRUE(CBB_add_asn1(&dps, &dp, CBS_ASN1_SEQUENCE));
- ASSERT_TRUE(CBB_add_asn1(
- &dp, &dp_name, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0));
- // DistributionPointName ::= CHOICE {
- // fullName [0] GeneralNames,
- // nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
- ASSERT_TRUE(
- CBB_add_asn1(&dp_name, &dp_fullname,
- CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0));
- // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
- // GeneralName ::= CHOICE {
- // uniformResourceIdentifier [6] IA5String,
- for (const auto& url : urls) {
- CBB dp_url;
- ASSERT_TRUE(
- CBB_add_asn1(&dp_fullname, &dp_url, CBS_ASN1_CONTEXT_SPECIFIC | 6));
- ASSERT_TRUE(CBBAddBytes(&dp_url, url.spec()));
- ASSERT_TRUE(CBB_flush(&dp_fullname));
- }
- SetExtension(der::Input(kCrlDistributionPointsOid), FinishCBB(cbb.get()));
- }
- void CertBuilder::SetSubjectCommonName(base::StringPiece common_name) {
- // See RFC 4519.
- static const uint8_t kCommonName[] = {0x55, 0x04, 0x03};
- // See RFC 5280, section 4.1.2.4.
- bssl::ScopedCBB cbb;
- CBB rdns, rdn, attr, type, value;
- ASSERT_TRUE(CBB_init(cbb.get(), 64));
- ASSERT_TRUE(CBB_add_asn1(cbb.get(), &rdns, CBS_ASN1_SEQUENCE));
- ASSERT_TRUE(CBB_add_asn1(&rdns, &rdn, CBS_ASN1_SET));
- ASSERT_TRUE(CBB_add_asn1(&rdn, &attr, CBS_ASN1_SEQUENCE));
- ASSERT_TRUE(CBB_add_asn1(&attr, &type, CBS_ASN1_OBJECT));
- ASSERT_TRUE(CBBAddBytes(&type, kCommonName));
- ASSERT_TRUE(CBB_add_asn1(&attr, &value, CBS_ASN1_UTF8STRING));
- ASSERT_TRUE(CBBAddBytes(&value, common_name));
- subject_tlv_ = FinishCBB(cbb.get());
- Invalidate();
- }
- void CertBuilder::SetSubject(base::span<const uint8_t> subject_tlv) {
- subject_tlv_.assign(subject_tlv.begin(), subject_tlv.end());
- Invalidate();
- }
- void CertBuilder::SetSubjectAltName(const std::string& dns_name) {
- SetSubjectAltNames({dns_name}, {});
- }
- void CertBuilder::SetSubjectAltNames(
- const std::vector<std::string>& dns_names,
- const std::vector<IPAddress>& ip_addresses) {
- // From RFC 5280:
- //
- // SubjectAltName ::= GeneralNames
- //
- // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
- //
- // GeneralName ::= CHOICE {
- // ...
- // dNSName [2] IA5String,
- // ...
- // iPAddress [7] OCTET STRING,
- // ... }
- ASSERT_GT(dns_names.size() + ip_addresses.size(), 0U);
- bssl::ScopedCBB cbb;
- CBB general_names;
- ASSERT_TRUE(CBB_init(cbb.get(), 64));
- ASSERT_TRUE(CBB_add_asn1(cbb.get(), &general_names, CBS_ASN1_SEQUENCE));
- if (!dns_names.empty()) {
- for (const auto& name : dns_names) {
- CBB general_name;
- ASSERT_TRUE(CBB_add_asn1(&general_names, &general_name,
- CBS_ASN1_CONTEXT_SPECIFIC | 2));
- ASSERT_TRUE(CBBAddBytes(&general_name, name));
- ASSERT_TRUE(CBB_flush(&general_names));
- }
- }
- if (!ip_addresses.empty()) {
- for (const auto& addr : ip_addresses) {
- CBB general_name;
- ASSERT_TRUE(CBB_add_asn1(&general_names, &general_name,
- CBS_ASN1_CONTEXT_SPECIFIC | 7));
- ASSERT_TRUE(
- CBB_add_bytes(&general_name, addr.bytes().data(), addr.size()));
- ASSERT_TRUE(CBB_flush(&general_names));
- }
- }
- SetExtension(der::Input(kSubjectAltNameOid), FinishCBB(cbb.get()));
- }
- void CertBuilder::SetKeyUsages(const std::vector<KeyUsageBit>& usages) {
- ASSERT_GT(usages.size(), 0U);
- int number_of_unused_bits = 0;
- std::vector<uint8_t> bytes;
- for (auto usage : usages) {
- int bit_index = static_cast<int>(usage);
- // Index of the byte that contains the bit.
- size_t byte_index = bit_index / 8;
- if (byte_index + 1 > bytes.size()) {
- bytes.resize(byte_index + 1);
- number_of_unused_bits = 8;
- }
- // Within a byte, bits are ordered from most significant to least
- // significant. Convert |bit_index| to an index within the |byte_index|
- // byte, measured from its least significant bit.
- uint8_t bit_index_in_byte = 7 - (bit_index - byte_index * 8);
- if (byte_index + 1 == bytes.size() &&
- bit_index_in_byte < number_of_unused_bits) {
- number_of_unused_bits = bit_index_in_byte;
- }
- bytes[byte_index] |= (1 << bit_index_in_byte);
- }
- // From RFC 5290:
- // KeyUsage ::= BIT STRING {...}
- bssl::ScopedCBB cbb;
- CBB ku_cbb;
- ASSERT_TRUE(CBB_init(cbb.get(), bytes.size() + 1));
- ASSERT_TRUE(CBB_add_asn1(cbb.get(), &ku_cbb, CBS_ASN1_BITSTRING));
- ASSERT_TRUE(CBB_add_u8(&ku_cbb, number_of_unused_bits));
- ASSERT_TRUE(CBB_add_bytes(&ku_cbb, bytes.data(), bytes.size()));
- SetExtension(der::Input(kKeyUsageOid), FinishCBB(cbb.get()));
- }
- void CertBuilder::SetExtendedKeyUsages(
- const std::vector<der::Input>& purpose_oids) {
- // From RFC 5280:
- // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
- // KeyPurposeId ::= OBJECT IDENTIFIER
- ASSERT_GT(purpose_oids.size(), 0U);
- bssl::ScopedCBB cbb;
- CBB eku;
- ASSERT_TRUE(CBB_init(cbb.get(), 64));
- ASSERT_TRUE(CBB_add_asn1(cbb.get(), &eku, CBS_ASN1_SEQUENCE));
- for (const auto& oid : purpose_oids) {
- CBB purpose_cbb;
- ASSERT_TRUE(CBB_add_asn1(&eku, &purpose_cbb, CBS_ASN1_OBJECT));
- ASSERT_TRUE(CBBAddBytes(&purpose_cbb, oid.AsStringPiece()));
- ASSERT_TRUE(CBB_flush(&eku));
- }
- SetExtension(der::Input(kExtKeyUsageOid), FinishCBB(cbb.get()));
- }
- void CertBuilder::SetCertificatePolicies(
- const std::vector<std::string>& policy_oids) {
- // From RFC 5280:
- // certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
- //
- // PolicyInformation ::= SEQUENCE {
- // policyIdentifier CertPolicyId,
- // policyQualifiers SEQUENCE SIZE (1..MAX) OF
- // PolicyQualifierInfo OPTIONAL }
- //
- // CertPolicyId ::= OBJECT IDENTIFIER
- bssl::ScopedCBB cbb;
- CBB certificate_policies;
- ASSERT_TRUE(CBB_init(cbb.get(), 64));
- ASSERT_TRUE(
- CBB_add_asn1(cbb.get(), &certificate_policies, CBS_ASN1_SEQUENCE));
- for (const auto& oid : policy_oids) {
- CBB policy_information, policy_identifier;
- ASSERT_TRUE(CBB_add_asn1(&certificate_policies, &policy_information,
- CBS_ASN1_SEQUENCE));
- ASSERT_TRUE(
- CBB_add_asn1(&policy_information, &policy_identifier, CBS_ASN1_OBJECT));
- ASSERT_TRUE(
- CBB_add_asn1_oid_from_text(&policy_identifier, oid.data(), oid.size()));
- ASSERT_TRUE(CBB_flush(&certificate_policies));
- }
- SetExtension(der::Input(kCertificatePoliciesOid), FinishCBB(cbb.get()));
- }
- void CertBuilder::SetValidity(base::Time not_before, base::Time not_after) {
- // From RFC 5280:
- // Validity ::= SEQUENCE {
- // notBefore Time,
- // notAfter Time }
- bssl::ScopedCBB cbb;
- CBB validity;
- ASSERT_TRUE(CBB_init(cbb.get(), 64));
- ASSERT_TRUE(CBB_add_asn1(cbb.get(), &validity, CBS_ASN1_SEQUENCE));
- ASSERT_TRUE(x509_util::CBBAddTime(&validity, not_before));
- ASSERT_TRUE(x509_util::CBBAddTime(&validity, not_after));
- validity_tlv_ = FinishCBB(cbb.get());
- Invalidate();
- }
- void CertBuilder::SetSubjectKeyIdentifier(
- const std::string& subject_key_identifier) {
- ASSERT_FALSE(subject_key_identifier.empty());
- // From RFC 5280:
- // KeyIdentifier ::= OCTET STRING
- // SubjectKeyIdentifier ::= KeyIdentifier
- bssl::ScopedCBB cbb;
- ASSERT_TRUE(CBB_init(cbb.get(), 32));
- ASSERT_TRUE(CBB_add_asn1_octet_string(
- cbb.get(),
- reinterpret_cast<const uint8_t*>(subject_key_identifier.data()),
- subject_key_identifier.size()));
- // Replace the existing SKI. Note it MUST be non-critical, per RFC 5280.
- SetExtension(der::Input(kSubjectKeyIdentifierOid), FinishCBB(cbb.get()),
- /*critical=*/false);
- }
- void CertBuilder::SetAuthorityKeyIdentifier(
- const std::string& authority_key_identifier) {
- // If an empty AKI is presented, simply erase the existing one. Creating
- // an empty AKI is technically valid, but there's no use case for this.
- // An empty AKI would an empty (ergo, non-unique) SKI on the issuer,
- // which would violate RFC 5280, so using the empty value as a placeholder
- // unless and until a use case emerges is fine.
- if (authority_key_identifier.empty()) {
- EraseExtension(der::Input(kAuthorityKeyIdentifierOid));
- return;
- }
- // From RFC 5280:
- //
- // AuthorityKeyIdentifier ::= SEQUENCE {
- // keyIdentifier [0] KeyIdentifier OPTIONAL,
- // authorityCertIssuer [1] GeneralNames OPTIONAL,
- // authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
- //
- // KeyIdentifier ::= OCTET STRING
- bssl::ScopedCBB cbb;
- CBB aki, aki_value;
- ASSERT_TRUE(CBB_init(cbb.get(), 32));
- ASSERT_TRUE(CBB_add_asn1(cbb.get(), &aki, CBS_ASN1_SEQUENCE));
- ASSERT_TRUE(CBB_add_asn1(&aki, &aki_value, CBS_ASN1_CONTEXT_SPECIFIC | 0));
- ASSERT_TRUE(CBBAddBytes(&aki_value, authority_key_identifier));
- ASSERT_TRUE(CBB_flush(&aki));
- SetExtension(der::Input(kAuthorityKeyIdentifierOid), FinishCBB(cbb.get()));
- }
- void CertBuilder::SetSignatureAlgorithm(
- SignatureAlgorithm signature_algorithm) {
- signature_algorithm_ = signature_algorithm;
- Invalidate();
- }
- void CertBuilder::SetRandomSerialNumber() {
- serial_number_ = base::RandUint64();
- Invalidate();
- }
- CRYPTO_BUFFER* CertBuilder::GetCertBuffer() {
- if (!cert_)
- GenerateCertificate();
- return cert_.get();
- }
- bssl::UniquePtr<CRYPTO_BUFFER> CertBuilder::DupCertBuffer() {
- return bssl::UpRef(GetCertBuffer());
- }
- const std::string& CertBuilder::GetSubject() {
- if (subject_tlv_.empty())
- GenerateSubject();
- return subject_tlv_;
- }
- uint64_t CertBuilder::GetSerialNumber() {
- if (!serial_number_)
- serial_number_ = base::RandUint64();
- return serial_number_;
- }
- std::string CertBuilder::GetSubjectKeyIdentifier() {
- std::string ski_oid = der::Input(kSubjectKeyIdentifierOid).AsString();
- if (extensions_.find(ski_oid) == extensions_.end()) {
- // If no SKI is present, this means that the certificate was either
- // created by FromStaticCert() and lacked one, or it was explicitly
- // deleted as an extension.
- return std::string();
- }
- auto& extension_value = extensions_[ski_oid];
- der::Input ski_value;
- if (!ParseSubjectKeyIdentifier(der::Input(&extension_value.value),
- &ski_value)) {
- return std::string();
- }
- return ski_value.AsString();
- }
- bool CertBuilder::GetValidity(base::Time* not_before,
- base::Time* not_after) const {
- der::GeneralizedTime not_before_generalized_time;
- der::GeneralizedTime not_after_generalized_time;
- if (!ParseValidity(der::Input(&validity_tlv_), ¬_before_generalized_time,
- ¬_after_generalized_time) ||
- !GeneralizedTimeToTime(not_before_generalized_time, not_before) ||
- !GeneralizedTimeToTime(not_after_generalized_time, not_after)) {
- return false;
- }
- return true;
- }
- EVP_PKEY* CertBuilder::GetKey() {
- if (!key_) {
- switch (default_pkey_id_) {
- case EVP_PKEY_RSA:
- GenerateRSAKey();
- break;
- case EVP_PKEY_EC:
- GenerateECKey();
- break;
- }
- }
- return key_.get();
- }
- scoped_refptr<X509Certificate> CertBuilder::GetX509Certificate() {
- return X509Certificate::CreateFromBuffer(DupCertBuffer(), {});
- }
- scoped_refptr<X509Certificate> CertBuilder::GetX509CertificateChain() {
- std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
- // Add intermediates, not including the self-signed root.
- for (CertBuilder* cert = issuer_; cert && cert != cert->issuer_;
- cert = cert->issuer_) {
- intermediates.push_back(cert->DupCertBuffer());
- }
- return X509Certificate::CreateFromBuffer(DupCertBuffer(),
- std::move(intermediates));
- }
- std::string CertBuilder::GetDER() {
- return std::string(x509_util::CryptoBufferAsStringPiece(GetCertBuffer()));
- }
- CertBuilder::CertBuilder(CRYPTO_BUFFER* orig_cert,
- CertBuilder* issuer,
- bool unique_subject_key_identifier)
- : issuer_(issuer) {
- if (!issuer_)
- issuer_ = this;
- crypto::EnsureOpenSSLInit();
- if (orig_cert)
- InitFromCert(der::Input(x509_util::CryptoBufferAsStringPiece(orig_cert)));
- if (unique_subject_key_identifier) {
- GenerateSubjectKeyIdentifier();
- SetAuthorityKeyIdentifier(issuer_->GetSubjectKeyIdentifier());
- }
- }
- void CertBuilder::Invalidate() {
- cert_.reset();
- }
- void CertBuilder::GenerateECKey() {
- auto private_key = crypto::ECPrivateKey::Create();
- key_ = bssl::UpRef(private_key->key());
- Invalidate();
- }
- void CertBuilder::GenerateRSAKey() {
- auto private_key = crypto::RSAPrivateKey::Create(2048);
- key_ = bssl::UpRef(private_key->key());
- Invalidate();
- }
- void CertBuilder::GenerateSubjectKeyIdentifier() {
- // 20 bytes are chosen here for no other reason than it's compatible with
- // systems that assume the SKI is SHA-1(SPKI), which RFC 5280 notes as one
- // mechanism for generating an SKI, while also noting that random/unique
- // SKIs are also fine.
- std::string random_ski = base::RandBytesAsString(20);
- SetSubjectKeyIdentifier(random_ski);
- }
- void CertBuilder::GenerateSubject() {
- ASSERT_TRUE(subject_tlv_.empty());
- // Use a random common name comprised of 12 bytes in hex.
- std::string common_name = MakeRandomHexString(12);
- SetSubjectCommonName(common_name);
- }
- void CertBuilder::InitFromCert(const der::Input& cert) {
- extensions_.clear();
- Invalidate();
- // From RFC 5280, section 4.1
- // Certificate ::= SEQUENCE {
- // tbsCertificate TBSCertificate,
- // signatureAlgorithm AlgorithmIdentifier,
- // signatureValue BIT STRING }
- // TBSCertificate ::= SEQUENCE {
- // version [0] EXPLICIT Version DEFAULT v1,
- // serialNumber CertificateSerialNumber,
- // signature AlgorithmIdentifier,
- // issuer Name,
- // validity Validity,
- // subject Name,
- // subjectPublicKeyInfo SubjectPublicKeyInfo,
- // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
- // -- If present, version MUST be v2 or v3
- // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
- // -- If present, version MUST be v2 or v3
- // extensions [3] EXPLICIT Extensions OPTIONAL
- // -- If present, version MUST be v3
- // }
- der::Parser parser(cert);
- der::Parser certificate;
- der::Parser tbs_certificate;
- ASSERT_TRUE(parser.ReadSequence(&certificate));
- ASSERT_TRUE(certificate.ReadSequence(&tbs_certificate));
- // version
- bool unused;
- ASSERT_TRUE(tbs_certificate.SkipOptionalTag(
- der::kTagConstructed | der::kTagContextSpecific | 0, &unused));
- // serialNumber
- ASSERT_TRUE(tbs_certificate.SkipTag(der::kInteger));
- // signature
- der::Input signature_algorithm_tlv;
- ASSERT_TRUE(tbs_certificate.ReadRawTLV(&signature_algorithm_tlv));
- auto signature_algorithm =
- ParseSignatureAlgorithm(signature_algorithm_tlv, nullptr);
- ASSERT_TRUE(signature_algorithm);
- signature_algorithm_ = *signature_algorithm;
- // issuer
- ASSERT_TRUE(tbs_certificate.SkipTag(der::kSequence));
- // validity
- der::Input validity_tlv;
- ASSERT_TRUE(tbs_certificate.ReadRawTLV(&validity_tlv));
- validity_tlv_ = validity_tlv.AsString();
- // subject
- ASSERT_TRUE(tbs_certificate.SkipTag(der::kSequence));
- // subjectPublicKeyInfo
- der::Input spki_tlv;
- ASSERT_TRUE(tbs_certificate.ReadRawTLV(&spki_tlv));
- bssl::UniquePtr<EVP_PKEY> public_key;
- ASSERT_TRUE(ParsePublicKey(spki_tlv, &public_key));
- default_pkey_id_ = EVP_PKEY_id(public_key.get());
- // issuerUniqueID
- ASSERT_TRUE(tbs_certificate.SkipOptionalTag(der::ContextSpecificPrimitive(1),
- &unused));
- // subjectUniqueID
- ASSERT_TRUE(tbs_certificate.SkipOptionalTag(der::ContextSpecificPrimitive(2),
- &unused));
- // extensions
- absl::optional<der::Input> extensions_tlv;
- ASSERT_TRUE(tbs_certificate.ReadOptionalTag(
- der::ContextSpecificConstructed(3), &extensions_tlv));
- if (extensions_tlv) {
- std::map<der::Input, ParsedExtension> parsed_extensions;
- ASSERT_TRUE(ParseExtensions(extensions_tlv.value(), &parsed_extensions));
- for (const auto& parsed_extension : parsed_extensions) {
- SetExtension(parsed_extension.second.oid,
- parsed_extension.second.value.AsString(),
- parsed_extension.second.critical);
- }
- }
- }
- void CertBuilder::BuildTBSCertificate(base::StringPiece signature_algorithm_tlv,
- std::string* out) {
- bssl::ScopedCBB cbb;
- CBB tbs_cert, version, extensions_context, extensions;
- ASSERT_TRUE(CBB_init(cbb.get(), 64));
- ASSERT_TRUE(CBB_add_asn1(cbb.get(), &tbs_cert, CBS_ASN1_SEQUENCE));
- ASSERT_TRUE(
- CBB_add_asn1(&tbs_cert, &version,
- CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0));
- // Always use v3 certificates.
- ASSERT_TRUE(CBB_add_asn1_uint64(&version, 2));
- ASSERT_TRUE(CBB_add_asn1_uint64(&tbs_cert, GetSerialNumber()));
- ASSERT_TRUE(CBBAddBytes(&tbs_cert, signature_algorithm_tlv));
- ASSERT_TRUE(CBBAddBytes(&tbs_cert, issuer_->GetSubject()));
- ASSERT_TRUE(CBBAddBytes(&tbs_cert, validity_tlv_));
- ASSERT_TRUE(CBBAddBytes(&tbs_cert, GetSubject()));
- ASSERT_TRUE(GetKey());
- ASSERT_TRUE(EVP_marshal_public_key(&tbs_cert, GetKey()));
- // Serialize all the extensions.
- if (!extensions_.empty()) {
- ASSERT_TRUE(
- CBB_add_asn1(&tbs_cert, &extensions_context,
- CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 3));
- ASSERT_TRUE(
- CBB_add_asn1(&extensions_context, &extensions, CBS_ASN1_SEQUENCE));
- // Extension ::= SEQUENCE {
- // extnID OBJECT IDENTIFIER,
- // critical BOOLEAN DEFAULT FALSE,
- // extnValue OCTET STRING
- // -- contains the DER encoding of an ASN.1 value
- // -- corresponding to the extension type identified
- // -- by extnID
- // }
- for (const auto& extension_it : extensions_) {
- CBB extension_seq, oid, extn_value;
- ASSERT_TRUE(CBB_add_asn1(&extensions, &extension_seq, CBS_ASN1_SEQUENCE));
- ASSERT_TRUE(CBB_add_asn1(&extension_seq, &oid, CBS_ASN1_OBJECT));
- ASSERT_TRUE(CBBAddBytes(&oid, extension_it.first));
- if (extension_it.second.critical) {
- ASSERT_TRUE(CBB_add_asn1_bool(&extension_seq, true));
- }
- ASSERT_TRUE(
- CBB_add_asn1(&extension_seq, &extn_value, CBS_ASN1_OCTETSTRING));
- ASSERT_TRUE(CBBAddBytes(&extn_value, extension_it.second.value));
- ASSERT_TRUE(CBB_flush(&extensions));
- }
- }
- *out = FinishCBB(cbb.get());
- }
- void CertBuilder::GenerateCertificate() {
- ASSERT_FALSE(cert_);
- absl::optional<SignatureAlgorithm> signature_algorithm = signature_algorithm_;
- if (!signature_algorithm)
- signature_algorithm = DefaultSignatureAlgorithmForKey(issuer_->GetKey());
- ASSERT_TRUE(signature_algorithm.has_value());
- std::string signature_algorithm_tlv =
- SignatureAlgorithmToDer(*signature_algorithm);
- ASSERT_FALSE(signature_algorithm_tlv.empty());
- std::string tbs_cert;
- BuildTBSCertificate(signature_algorithm_tlv, &tbs_cert);
- // Sign the TBSCertificate and write the entire certificate.
- bssl::ScopedCBB cbb;
- CBB cert, signature;
- ASSERT_TRUE(CBB_init(cbb.get(), tbs_cert.size()));
- ASSERT_TRUE(CBB_add_asn1(cbb.get(), &cert, CBS_ASN1_SEQUENCE));
- ASSERT_TRUE(CBBAddBytes(&cert, tbs_cert));
- ASSERT_TRUE(CBBAddBytes(&cert, signature_algorithm_tlv));
- ASSERT_TRUE(CBB_add_asn1(&cert, &signature, CBS_ASN1_BITSTRING));
- ASSERT_TRUE(CBB_add_u8(&signature, 0 /* no unused bits */));
- ASSERT_TRUE(
- SignData(*signature_algorithm, tbs_cert, issuer_->GetKey(), &signature));
- auto cert_der = FinishCBB(cbb.get());
- cert_ =
- x509_util::CreateCryptoBuffer(base::as_bytes(base::make_span(cert_der)));
- }
- } // namespace net
|