| // Copyright 2019 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef NET_TEST_CERT_BUILDER_H_ |
| #define NET_TEST_CERT_BUILDER_H_ |
| |
| #include <map> |
| #include <string> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/rand_util.h" |
| #include "base/strings/string_piece_forward.h" |
| #include "net/base/ip_address.h" |
| #include "net/cert/pki/parse_certificate.h" |
| #include "net/cert/pki/signature_algorithm.h" |
| #include "net/cert/x509_certificate.h" |
| #include "third_party/boringssl/src/include/openssl/base.h" |
| #include "third_party/boringssl/src/include/openssl/bytestring.h" |
| #include "third_party/boringssl/src/include/openssl/evp.h" |
| #include "third_party/boringssl/src/include/openssl/pool.h" |
| |
| class GURL; |
| |
| namespace base { |
| class FilePath; |
| } |
| |
| namespace net { |
| |
| namespace der { |
| class Input; |
| } |
| |
| // CertBuilder is a helper class to dynamically create a test certificate. |
| // |
| // CertBuilder is initialized using an existing certificate, from which it |
| // copies most properties (see InitFromCert for details). |
| // |
| // The subject, serial number, and key for the final certificate are chosen |
| // randomly. Using a randomized subject and serial number is important to defeat |
| // certificate caching done by NSS, which otherwise can make test outcomes |
| // dependent on ordering. |
| class CertBuilder { |
| public: |
| // Initializes the CertBuilder, if |orig_cert| is non-null it will be used as |
| // a template. If |issuer| is null then the generated certificate will be |
| // self-signed. Otherwise, it will be signed using |issuer|. |
| CertBuilder(CRYPTO_BUFFER* orig_cert, CertBuilder* issuer); |
| ~CertBuilder(); |
| |
| // Initializes a CertBuilder using the certificate and private key from |
| // |cert_and_key_file| as a template. If |issuer| is null then the generated |
| // certificate will be self-signed. Otherwise, it will be signed using |
| // |issuer|. |
| static std::unique_ptr<CertBuilder> FromFile( |
| const base::FilePath& cert_and_key_file, |
| CertBuilder* issuer); |
| |
| // Initializes a CertBuilder that will return a certificate for the provided |
| // public key |spki_der|. It will be signed with the |issuer|, this builder |
| // will not have a private key, so it cannot produce self-signed certificates |
| // and |issuer| cannot be null. |
| static std::unique_ptr<CertBuilder> FromSubjectPublicKeyInfo( |
| base::span<const uint8_t> spki_der, |
| CertBuilder* issuer); |
| |
| // Creates a CertBuilder that will return a static |cert| and |key|. |
| // This may be passed as the |issuer| param of another CertBuilder to create |
| // a cert chain that ends in a pre-defined certificate. |
| static std::unique_ptr<CertBuilder> FromStaticCert(CRYPTO_BUFFER* cert, |
| EVP_PKEY* key); |
| // Like FromStaticCert, but loads the certificate and private key from the |
| // PEM file |cert_and_key_file|. |
| static std::unique_ptr<CertBuilder> FromStaticCertFile( |
| const base::FilePath& cert_and_key_file); |
| |
| // Creates a simple chain of CertBuilders with no AIA or CrlDistributionPoint |
| // extensions, and leaf having a subjectAltName of www.example.com. |
| // The chain is returned in leaf-first order. |
| static std::vector<std::unique_ptr<CertBuilder>> CreateSimpleChain( |
| size_t chain_length); |
| |
| // Creates a simple leaf->intermediate->root chain of CertBuilders with no AIA |
| // or CrlDistributionPoint extensions, and leaf having a subjectAltName of |
| // www.example.com. |
| static std::array<std::unique_ptr<CertBuilder>, 3> CreateSimpleChain3(); |
| |
| // Creates a simple leaf->root chain of CertBuilders with no AIA or |
| // CrlDistributionPoint extensions, and leaf having a subjectAltName of |
| // www.example.com. |
| static std::array<std::unique_ptr<CertBuilder>, 2> CreateSimpleChain2(); |
| |
| // Returns a compatible signature algorithm for |key|. |
| static absl::optional<SignatureAlgorithm> DefaultSignatureAlgorithmForKey( |
| EVP_PKEY* key); |
| |
| // Signs |tbs_data| with |key| using |signature_algorithm| appending the |
| // signature onto |out_signature| and returns true if successful. |
| static bool SignData(SignatureAlgorithm signature_algorithm, |
| base::StringPiece tbs_data, |
| EVP_PKEY* key, |
| CBB* out_signature); |
| |
| static bool SignDataWithDigest(const EVP_MD* digest, |
| base::StringPiece tbs_data, |
| EVP_PKEY* key, |
| CBB* out_signature); |
| |
| // Returns a DER encoded AlgorithmIdentifier TLV for |signature_algorithm| |
| // empty string on error. |
| static std::string SignatureAlgorithmToDer( |
| SignatureAlgorithm signature_algorithm); |
| |
| // Generates |num_bytes| random bytes, and then returns the hex encoding of |
| // those bytes. |
| static std::string MakeRandomHexString(size_t num_bytes); |
| |
| // Builds a DER encoded X.501 Name TLV containing a commonName of |
| // |common_name| with type |common_name_tag|. |
| static std::vector<uint8_t> BuildNameWithCommonNameOfType( |
| base::StringPiece common_name, |
| unsigned common_name_tag); |
| |
| // Set the version of the certificate. Note that only V3 certificates may |
| // contain extensions, so if |version| is |V1| or |V2| you may want to also |
| // call |ClearExtensions()| unless you intentionally want to generate an |
| // invalid certificate. |
| void SetCertificateVersion(CertificateVersion version); |
| |
| // Sets a value for the indicated X.509 (v3) extension. |
| void SetExtension(const der::Input& oid, |
| std::string value, |
| bool critical = false); |
| |
| // Removes an extension (if present). |
| void EraseExtension(const der::Input& oid); |
| |
| // Removes all extensions. |
| void ClearExtensions(); |
| |
| // Sets the basicConstraints extension. |path_len| may be negative to |
| // indicate the pathLenConstraint should be omitted. |
| void SetBasicConstraints(bool is_ca, int path_len); |
| |
| // Sets the nameConstraints extension. |permitted_dns_names| lists permitted |
| // dnsName subtrees. |excluded_dns_names| lists excluded dnsName subtrees. If |
| // both lists are empty the extension is removed. |
| void SetNameConstraintsDnsNames( |
| const std::vector<std::string>& permitted_dns_names, |
| const std::vector<std::string>& excluded_dns_names); |
| |
| // Sets an AIA extension with a single caIssuers access method. |
| void SetCaIssuersUrl(const GURL& url); |
| |
| // Sets an AIA extension with the specified caIssuers and OCSP urls. Either |
| // list can have 0 or more URLs. If both are empty, the AIA extension is |
| // removed. |
| void SetCaIssuersAndOCSPUrls(const std::vector<GURL>& ca_issuers_urls, |
| const std::vector<GURL>& ocsp_urls); |
| |
| // Sets a cRLDistributionPoints extension with a single DistributionPoint |
| // with |url| in distributionPoint.fullName. |
| void SetCrlDistributionPointUrl(const GURL& url); |
| |
| // Sets a cRLDistributionPoints extension with a single DistributionPoint |
| // with |urls| in distributionPoints.fullName. |
| void SetCrlDistributionPointUrls(const std::vector<GURL>& urls); |
| |
| // Sets the issuer bytes that will be encoded into the generated certificate. |
| // If this is not called, or |issuer_tlv| is empty, the subject field from |
| // the issuer CertBuilder will be used. |
| void SetIssuerTLV(base::span<const uint8_t> issuer_tlv); |
| |
| // Sets the subject to a Name with a single commonName attribute with |
| // the value |common_name| tagged as a UTF8String. |
| void SetSubjectCommonName(base::StringPiece common_name); |
| |
| // Sets the subject to |subject_tlv|. |
| void SetSubjectTLV(base::span<const uint8_t> subject_tlv); |
| |
| // Sets the SAN for the certificate to a single dNSName. |
| void SetSubjectAltName(base::StringPiece dns_name); |
| |
| // Sets the SAN for the certificate to the given dns names and ip addresses. |
| void SetSubjectAltNames(const std::vector<std::string>& dns_names, |
| const std::vector<IPAddress>& ip_addresses); |
| |
| // Sets the keyUsage extension. |usages| should contain the KeyUsageBit |
| // values of the usages to set, and must not be empty. |
| void SetKeyUsages(const std::vector<KeyUsageBit>& usages); |
| |
| // Sets the extendedKeyUsage extension. |usages| should contain the DER OIDs |
| // of the usage purposes to set, and must not be empty. |
| void SetExtendedKeyUsages(const std::vector<der::Input>& purpose_oids); |
| |
| // Sets the certificatePolicies extension with the specified policyIdentifier |
| // OIDs, which must be specified in dotted string notation (e.g. "1.2.3.4"). |
| // If |policy_oids| is empty, the extension will be removed. |
| void SetCertificatePolicies(const std::vector<std::string>& policy_oids); |
| |
| // Sets the policyMappings extension with the specified mappings, which are |
| // pairs of issuerDomainPolicy -> subjectDomainPolicy mappings in dotted |
| // string notation. |
| // If |policy_mappings| is empty, the extension will be removed. |
| void SetPolicyMappings( |
| const std::vector<std::pair<std::string, std::string>>& policy_mappings); |
| |
| // Sets the PolicyConstraints extension. If both |require_explicit_policy| |
| // and |inhibit_policy_mapping| are nullopt, the PolicyConstraints extension |
| // will removed. |
| void SetPolicyConstraints(absl::optional<uint64_t> require_explicit_policy, |
| absl::optional<uint64_t> inhibit_policy_mapping); |
| |
| // Sets the inhibitAnyPolicy extension. |
| void SetInhibitAnyPolicy(uint64_t skip_certs); |
| |
| void SetValidity(base::Time not_before, base::Time not_after); |
| |
| // Sets the Subject Key Identifier (SKI) extension to the specified string. |
| // By default, a unique SKI will be generated for each CertBuilder; however, |
| // this may be overridden to force multiple certificates to be considered |
| // during path building on systems that prioritize matching SKI to the |
| // Authority Key Identifier (AKI) extension, rather than using the |
| // Subject/Issuer name. Empty SKIs are not supported; use EraseExtension() |
| // for that. |
| void SetSubjectKeyIdentifier(const std::string& subject_key_identifier); |
| |
| // Sets the Authority Key Identifier (AKI) extension to the specified |
| // string. |
| // Note: Only the keyIdentifier option is supported, and the value |
| // is the raw identifier (i.e. without DER encoding). Empty strings will |
| // result in the extension, if present, being erased. This ensures that it |
| // is safe to use SetAuthorityKeyIdentifier() with the result of the |
| // issuing CertBuilder's (if any) GetSubjectKeyIdentifier() without |
| // introducing AKI/SKI chain building issues. |
| void SetAuthorityKeyIdentifier(const std::string& authority_key_identifier); |
| |
| // Sets the signature algorithm to use in generating the certificate's |
| // signature. The signature algorithm should be compatible with |
| // the type of |issuer_->GetKey()|. If this method is not called, and the |
| // CertBuilder was initialized from a template cert, the signature algorithm |
| // of that cert will be used, or if there was no template cert, a default |
| // algorithm will be used base on the signing key type. |
| void SetSignatureAlgorithm(SignatureAlgorithm signature_algorithm); |
| |
| // Sets both signature AlgorithmIdentifier TLVs to encode in the generated |
| // certificate. |
| // This only affects the bytes written to the output - it does not affect what |
| // algorithm is actually used to perform the signature. To set the signature |
| // algorithm used to generate the certificate's signature, use |
| // |SetSignatureAlgorithm|. If this method is not called, the signature |
| // algorithm written to the output will be chosen to match the signature |
| // algorithm used to sign the certificate. |
| void SetSignatureAlgorithmTLV(base::StringPiece signature_algorithm_tlv); |
| |
| // Set only the outer Certificate signatureAlgorithm TLV. See |
| // SetSignatureAlgorithmTLV comment for general notes. |
| void SetOuterSignatureAlgorithmTLV(base::StringPiece signature_algorithm_tlv); |
| |
| // Set only the tbsCertificate signature TLV. See SetSignatureAlgorithmTLV |
| // comment for general notes. |
| void SetTBSSignatureAlgorithmTLV(base::StringPiece signature_algorithm_tlv); |
| |
| void SetRandomSerialNumber(); |
| |
| // Sets the private key for the generated certificate to an EC key. If a key |
| // was already set, it will be replaced. |
| void GenerateECKey(); |
| |
| // Sets the private key for the generated certificate to a 2048-bit RSA key. |
| // RSA key generation is expensive, so this should not be used unless an RSA |
| // key is specifically needed. If a key was already set, it will be replaced. |
| void GenerateRSAKey(); |
| |
| // Loads the private key for the generated certificate from |key_file|. |
| bool UseKeyFromFile(const base::FilePath& key_file); |
| |
| // Returns the CertBuilder that issues this certificate. (Will be |this| if |
| // certificate is self-signed.) |
| CertBuilder* issuer() { return issuer_; } |
| |
| // Returns a CRYPTO_BUFFER to the generated certificate. |
| CRYPTO_BUFFER* GetCertBuffer(); |
| |
| bssl::UniquePtr<CRYPTO_BUFFER> DupCertBuffer(); |
| |
| // Returns the subject of the generated certificate. |
| const std::string& GetSubject(); |
| |
| // Returns the serial number for the generated certificate. |
| uint64_t GetSerialNumber(); |
| |
| // Returns the subject key identifier for the generated certificate. If |
| // none is present, a random value will be generated. |
| // Note: The returned value will be the contents of the OCTET |
| // STRING/KeyIdentifier, without DER encoding, ensuring it's suitable for |
| // SetSubjectKeyIdentifier(). |
| std::string GetSubjectKeyIdentifier(); |
| |
| // Parses and returns validity period for the generated certificate in |
| // |not_before| and |not_after|, returning true on success. |
| bool GetValidity(base::Time* not_before, base::Time* not_after) const; |
| |
| // Returns the key for the generated certificate. |
| EVP_PKEY* GetKey(); |
| |
| // Returns an X509Certificate for the generated certificate. |
| scoped_refptr<X509Certificate> GetX509Certificate(); |
| |
| // Returns an X509Certificate for the generated certificate, including |
| // intermediate certificates (not including the self-signed root). |
| scoped_refptr<X509Certificate> GetX509CertificateChain(); |
| |
| // Returns an X509Certificate for the generated certificate, including |
| // intermediate certificates and the self-signed root. |
| scoped_refptr<X509Certificate> GetX509CertificateFullChain(); |
| |
| // Returns a copy of the certificate's DER. |
| std::string GetDER(); |
| |
| // Returns a copy of the certificate as PEM encoded DER. |
| // Convenience method for debugging, to more easily log what cert is being |
| // created. |
| std::string GetPEM(); |
| |
| // Returns the full chain (including root) as PEM. |
| // Convenience method for debugging, to more easily log what certs are being |
| // created. |
| std::string GetPEMFullChain(); |
| |
| // Returns the private key as PEM. |
| // Convenience method for debugging, to more easily log what certs are being |
| // created. |
| std::string GetPrivateKeyPEM(); |
| |
| private: |
| // Initializes the CertBuilder, if |orig_cert| is non-null it will be used as |
| // a template. If |issuer| is null then the generated certificate will be |
| // self-signed. Otherwise, it will be signed using |issuer|. |
| // |unique_subject_key_identifier| controls whether an ephemeral SKI will |
| // be generated for this certificate. In general, any manipulation of the |
| // certificate at all should result in a new SKI, to avoid issues on |
| // Windows CryptoAPI, but generating a unique SKI can create issues for |
| // macOS Security.framework if |orig_cert| has already issued certificates |
| // (including self-signed certs). The only time this is safe is thus |
| // when used in conjunction with FromStaticCert() and re-using the |
| // same key, thus this constructor is private. |
| CertBuilder(CRYPTO_BUFFER* orig_cert, |
| CertBuilder* issuer, |
| bool unique_subject_key_identifier); |
| |
| // Marks the generated certificate DER as invalid, so it will need to |
| // be re-generated next time the DER is accessed. |
| void Invalidate(); |
| |
| // Generates a random Subject Key Identifier for the certificate. This is |
| // necessary for Windows, which otherwises uses SKI/AKI matching for lookups |
| // with greater precedence than subject/issuer name matching, and on newer |
| // versions of Windows, limits the number of lookups+signature failures that |
| // can be performed. Rather than deriving from |key_|, generating a unique |
| // value is useful for signalling this is a "unique" and otherwise |
| // independent CA. |
| void GenerateSubjectKeyIdentifier(); |
| |
| // Generates a random subject for the certificate, comprised of just a CN. |
| void GenerateSubject(); |
| |
| // Parses |cert| and copies the following properties: |
| // * All extensions (dropping any duplicates) |
| // * Signature algorithm (from Certificate) |
| // * Validity (expiration) |
| void InitFromCert(const der::Input& cert); |
| |
| // Assembles the CertBuilder into a TBSCertificate. |
| void BuildTBSCertificate(base::StringPiece signature_algorithm_tlv, |
| std::string* out); |
| |
| void GenerateCertificate(); |
| |
| struct ExtensionValue { |
| bool critical = false; |
| std::string value; |
| }; |
| |
| CertificateVersion version_ = CertificateVersion::V3; |
| std::string validity_tlv_; |
| absl::optional<std::string> issuer_tlv_; |
| std::string subject_tlv_; |
| absl::optional<SignatureAlgorithm> signature_algorithm_; |
| std::string outer_signature_algorithm_tlv_; |
| std::string tbs_signature_algorithm_tlv_; |
| uint64_t serial_number_ = 0; |
| int default_pkey_id_ = EVP_PKEY_EC; |
| |
| std::map<std::string, ExtensionValue> extensions_; |
| |
| bssl::UniquePtr<CRYPTO_BUFFER> cert_; |
| bssl::UniquePtr<EVP_PKEY> key_; |
| |
| raw_ptr<CertBuilder, DanglingUntriaged> issuer_ = nullptr; |
| }; |
| |
| } // namespace net |
| |
| #endif // NET_TEST_CERT_BUILDER_H_ |