// Copyright 2015 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BSSL_PKI_PARSE_CERTIFICATE_H_ #define BSSL_PKI_PARSE_CERTIFICATE_H_ #include #include #include #include #include #include #include "general_names.h" #include "input.h" #include "parse_values.h" namespace bssl { namespace der { class Parser; } class CertErrors; struct ParsedTbsCertificate; // Returns true if the given serial number (CertificateSerialNumber in RFC 5280) // is valid: // // CertificateSerialNumber ::= INTEGER // // The input to this function is the (unverified) value octets of the INTEGER. // This function will verify that: // // * The octets are a valid DER-encoding of an INTEGER (for instance, minimal // encoding length). // // * No more than 20 octets are used. // // Note that it DOES NOT reject non-positive values (zero or negative). // // For reference, here is what RFC 5280 section 4.1.2.2 says: // // Given the uniqueness requirements above, serial numbers can be // expected to contain long integers. Certificate users MUST be able to // handle serialNumber values up to 20 octets. Conforming CAs MUST NOT // use serialNumber values longer than 20 octets. // // Note: Non-conforming CAs may issue certificates with serial numbers // that are negative or zero. Certificate users SHOULD be prepared to // gracefully handle such certificates. // // |errors| must be a non-null destination for any errors/warnings. If // |warnings_only| is set to true, then what would ordinarily be errors are // instead added as warnings. [[nodiscard]] OPENSSL_EXPORT bool VerifySerialNumber(der::Input value, bool warnings_only, CertErrors *errors); // Consumes a "Time" value (as defined by RFC 5280) from |parser|. On success // writes the result to |*out| and returns true. On failure no guarantees are // made about the state of |parser|. // // From RFC 5280: // // Time ::= CHOICE { // utcTime UTCTime, // generalTime GeneralizedTime } [[nodiscard]] OPENSSL_EXPORT bool ReadUTCOrGeneralizedTime( der::Parser *parser, der::GeneralizedTime *out); // Parses a DER-encoded "Validity" as specified by RFC 5280. Returns true on // success and sets the results in |not_before| and |not_after|: // // Validity ::= SEQUENCE { // notBefore Time, // notAfter Time } // // Note that upon success it is NOT guaranteed that |*not_before <= *not_after|. [[nodiscard]] OPENSSL_EXPORT bool ParseValidity( der::Input validity_tlv, der::GeneralizedTime *not_before, der::GeneralizedTime *not_after); struct OPENSSL_EXPORT ParseCertificateOptions { // If set to true, then parsing will skip checks on the certificate's serial // number. The only requirement will be that the serial number is an INTEGER, // however it is not required to be a valid DER-encoding (i.e. minimal // encoding), nor is it required to be constrained to any particular length. bool allow_invalid_serial_numbers = false; }; // Parses a DER-encoded "Certificate" as specified by RFC 5280. Returns true on // success and sets the results in the |out_*| parameters. On both the failure // and success case, if |out_errors| was non-null it may contain extra error // information. // // Note that on success the out parameters alias data from the input // |certificate_tlv|. Hence the output values are only valid as long as // |certificate_tlv| remains valid. // // On failure the out parameters have an undefined state, except for // out_errors. Some of them may have been updated during parsing, whereas // others may not have been changed. // // The out parameters represent each field of the Certificate SEQUENCE: // Certificate ::= SEQUENCE { // // The |out_tbs_certificate_tlv| parameter corresponds with "tbsCertificate" // from RFC 5280: // tbsCertificate TBSCertificate, // // This contains the full (unverified) Tag-Length-Value for a SEQUENCE. No // guarantees are made regarding the value of this SEQUENCE. // This can be further parsed using ParseTbsCertificate(). // // The |out_signature_algorithm_tlv| parameter corresponds with // "signatureAlgorithm" from RFC 5280: // signatureAlgorithm AlgorithmIdentifier, // // This contains the full (unverified) Tag-Length-Value for a SEQUENCE. No // guarantees are made regarding the value of this SEQUENCE. // This can be further parsed using SignatureValue::Create(). // // The |out_signature_value| parameter corresponds with "signatureValue" from // RFC 5280: // signatureValue BIT STRING } // // Parsing guarantees that this is a valid BIT STRING. [[nodiscard]] OPENSSL_EXPORT bool ParseCertificate( der::Input certificate_tlv, der::Input *out_tbs_certificate_tlv, der::Input *out_signature_algorithm_tlv, der::BitString *out_signature_value, CertErrors *out_errors); // Parses a DER-encoded "TBSCertificate" as specified by RFC 5280. Returns true // on success and sets the results in |out|. Certain invalid inputs may // be accepted based on the provided |options|. // // If |errors| was non-null then any warnings/errors that occur during parsing // are added to it. // // Note that on success |out| aliases data from the input |tbs_tlv|. // Hence the fields of the ParsedTbsCertificate are only valid as long as // |tbs_tlv| remains valid. // // On failure |out| has an undefined state. Some of its fields may have been // updated during parsing, whereas others may not have been changed. // // Refer to the per-field documentation of ParsedTbsCertificate for details on // what validity checks parsing performs. // // 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 // } [[nodiscard]] OPENSSL_EXPORT bool ParseTbsCertificate( der::Input tbs_tlv, const ParseCertificateOptions &options, ParsedTbsCertificate *out, CertErrors *errors); // Represents a "Version" from RFC 5280: // Version ::= INTEGER { v1(0), v2(1), v3(2) } enum class CertificateVersion { V1, V2, V3, }; // ParsedTbsCertificate contains pointers to the main fields of a DER-encoded // RFC 5280 "TBSCertificate". // // ParsedTbsCertificate is expected to be filled by ParseTbsCertificate(), so // subsequent field descriptions are in terms of what ParseTbsCertificate() // sets. struct OPENSSL_EXPORT ParsedTbsCertificate { ParsedTbsCertificate(); ParsedTbsCertificate(ParsedTbsCertificate &&other); ParsedTbsCertificate &operator=(ParsedTbsCertificate &&other) = default; ~ParsedTbsCertificate(); // Corresponds with "version" from RFC 5280: // version [0] EXPLICIT Version DEFAULT v1, // // Parsing guarantees that the version is one of v1, v2, or v3. CertificateVersion version = CertificateVersion::V1; // Corresponds with "serialNumber" from RFC 5280: // serialNumber CertificateSerialNumber, // // This field specifically contains the content bytes of the INTEGER. So for // instance if the serial number was 1000 then this would contain bytes // {0x03, 0xE8}. // // The serial number may or may not be a valid DER-encoded INTEGER: // // If the option |allow_invalid_serial_numbers=true| was used during // parsing, then nothing further can be assumed about these bytes. // // Otherwise if |allow_invalid_serial_numbers=false| then in addition // to being a valid DER-encoded INTEGER, parsing guarantees that // the serial number is at most 20 bytes long. Parsing does NOT guarantee // that the integer is positive (might be zero or negative). der::Input serial_number; // Corresponds with "signatureAlgorithm" from RFC 5280: // signatureAlgorithm AlgorithmIdentifier, // // This contains the full (unverified) Tag-Length-Value for a SEQUENCE. No // guarantees are made regarding the value of this SEQUENCE. // // This can be further parsed using SignatureValue::Create(). der::Input signature_algorithm_tlv; // Corresponds with "issuer" from RFC 5280: // issuer Name, // // This contains the full (unverified) Tag-Length-Value for a SEQUENCE. No // guarantees are made regarding the value of this SEQUENCE. der::Input issuer_tlv; // Corresponds with "validity" from RFC 5280: // validity Validity, // // Where Validity is defined as: // // Validity ::= SEQUENCE { // notBefore Time, // notAfter Time } // // Parsing guarantees that notBefore (validity_not_before) and notAfter // (validity_not_after) are valid DER-encoded dates, however it DOES NOT // gurantee anything about their values. For instance notAfter could be // before notBefore, or the dates could indicate an expired certificate. // Consumers are responsible for testing expiration. der::GeneralizedTime validity_not_before; der::GeneralizedTime validity_not_after; // Corresponds with "subject" from RFC 5280: // subject Name, // // This contains the full (unverified) Tag-Length-Value for a SEQUENCE. No // guarantees are made regarding the value of this SEQUENCE. der::Input subject_tlv; // Corresponds with "subjectPublicKeyInfo" from RFC 5280: // subjectPublicKeyInfo SubjectPublicKeyInfo, // // This contains the full (unverified) Tag-Length-Value for a SEQUENCE. No // guarantees are made regarding the value of this SEQUENCE. der::Input spki_tlv; // Corresponds with "issuerUniqueID" from RFC 5280: // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, // -- If present, version MUST be v2 or v3 // // Parsing guarantees that if issuer_unique_id is present it is a valid BIT // STRING, and that the version is either v2 or v3 std::optional issuer_unique_id; // Corresponds with "subjectUniqueID" from RFC 5280: // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, // -- If present, version MUST be v2 or v3 // // Parsing guarantees that if subject_unique_id is present it is a valid BIT // STRING, and that the version is either v2 or v3 std::optional subject_unique_id; // Corresponds with "extensions" from RFC 5280: // extensions [3] EXPLICIT Extensions OPTIONAL // -- If present, version MUST be v3 // // // This contains the full (unverified) Tag-Length-Value for a SEQUENCE. No // guarantees are made regarding the value of this SEQUENCE. (Note that the // EXPLICIT outer tag is stripped.) // // Parsing guarantees that if extensions is present the version is v3. std::optional extensions_tlv; }; // ParsedExtension represents a parsed "Extension" from RFC 5280. It contains // der:Inputs which are not owned so the associated data must be kept alive. // // 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 // } struct OPENSSL_EXPORT ParsedExtension { der::Input oid; // |value| will contain the contents of the OCTET STRING. For instance for // basicConstraints it will be the TLV for a SEQUENCE. der::Input value; bool critical = false; }; // Parses a DER-encoded "Extension" as specified by RFC 5280. Returns true on // success and sets the results in |out|. // // Note that on success |out| aliases data from the input |extension_tlv|. // Hence the fields of the ParsedExtension are only valid as long as // |extension_tlv| remains valid. // // On failure |out| has an undefined state. Some of its fields may have been // updated during parsing, whereas others may not have been changed. [[nodiscard]] OPENSSL_EXPORT bool ParseExtension(der::Input extension_tlv, ParsedExtension *out); // From RFC 5280: // // id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } // // In dotted notation: 2.5.29.14 inline constexpr uint8_t kSubjectKeyIdentifierOid[] = {0x55, 0x1d, 0x0e}; // From RFC 5280: // // id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } // // In dotted notation: 2.5.29.15 inline constexpr uint8_t kKeyUsageOid[] = {0x55, 0x1d, 0x0f}; // From RFC 5280: // // id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } // // In dotted notation: 2.5.29.17 inline constexpr uint8_t kSubjectAltNameOid[] = {0x55, 0x1d, 0x11}; // From RFC 5280: // // id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } // // In dotted notation: 2.5.29.19 inline constexpr uint8_t kBasicConstraintsOid[] = {0x55, 0x1d, 0x13}; // From RFC 5280: // // id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } // // In dotted notation: 2.5.29.30 inline constexpr uint8_t kNameConstraintsOid[] = {0x55, 0x1d, 0x1e}; // From RFC 5280: // // id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } // // In dotted notation: 2.5.29.32 inline constexpr uint8_t kCertificatePoliciesOid[] = {0x55, 0x1d, 0x20}; // From RFC 5280: // // id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } // // In dotted notation: 2.5.29.35 inline constexpr uint8_t kAuthorityKeyIdentifierOid[] = {0x55, 0x1d, 0x23}; // From RFC 5280: // // id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } // // In dotted notation: 2.5.29.36 inline constexpr uint8_t kPolicyConstraintsOid[] = {0x55, 0x1d, 0x24}; // From RFC 5280: // // id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } // // In dotted notation: 2.5.29.37 inline constexpr uint8_t kExtKeyUsageOid[] = {0x55, 0x1d, 0x25}; // From RFC 5280: // // id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 } // // In dotted notation: 1.3.6.1.5.5.7.1.1 inline constexpr uint8_t kAuthorityInfoAccessOid[] = {0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01}; // From RFC 5280: // // id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 } // // In dotted notation: 1.3.6.1.5.5.7.48.2 inline constexpr uint8_t kAdCaIssuersOid[] = {0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02}; // From RFC 5280: // // id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 } // // In dotted notation: 1.3.6.1.5.5.7.48.1 inline constexpr uint8_t kAdOcspOid[] = {0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01}; // From RFC 5280: // // id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } // // In dotted notation: 2.5.29.31 inline constexpr uint8_t kCrlDistributionPointsOid[] = {0x55, 0x1d, 0x1f}; // From RFC 6962: // // critical poison extension. // // In dotted notation 1.3.6.1.4.1.11129.2.4.3 inline constexpr uint8_t kCtPoisonOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, 0xD6, 0x79, 0x02, 0x04, 0x03}; // From // https://learn.microsoft.com/en-us/windows/win32/seccertenroll/supported-extensions#msapplicationpolicies // // OID: XCN_OID_APPLICATION_CERT_POLICIES (1.3.6.1.4.1.311.21.10) inline constexpr uint8_t kMSApplicationPoliciesOid[] = { 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x0a}; // Parses the Extensions sequence as defined by RFC 5280. Extensions are added // to the map |extensions| keyed by the OID. Parsing guarantees that each OID // is unique. Note that certificate verification must consume each extension // marked as critical. // // Returns true on success and fills |extensions|. The output will reference // bytes in |extensions_tlv|, so that data must be kept alive. // On failure |extensions| may be partially written to and should not be used. [[nodiscard]] OPENSSL_EXPORT bool ParseExtensions( der::Input extensions_tlv, std::map *extensions); // Removes the extension with OID |oid| from |unconsumed_extensions| and fills // |extension| with the matching extension value. If there was no extension // matching |oid| then returns |false|. [[nodiscard]] OPENSSL_EXPORT bool ConsumeExtension( der::Input oid, std::map *unconsumed_extensions, ParsedExtension *extension); struct ParsedBasicConstraints { bool is_ca = false; bool has_path_len = false; uint8_t path_len = 0; }; // Parses the BasicConstraints extension as defined by RFC 5280: // // BasicConstraints ::= SEQUENCE { // cA BOOLEAN DEFAULT FALSE, // pathLenConstraint INTEGER (0..MAX) OPTIONAL } // // The maximum allowed value of pathLenConstraints will be whatever can fit // into a uint8_t. [[nodiscard]] OPENSSL_EXPORT bool ParseBasicConstraints( der::Input basic_constraints_tlv, ParsedBasicConstraints *out); // KeyUsageBit contains the index for a particular key usage. The index is // measured from the most significant bit of a bit string. // // From RFC 5280 section 4.2.1.3: // // KeyUsage ::= BIT STRING { // digitalSignature (0), // nonRepudiation (1), -- recent editions of X.509 have // -- renamed this bit to contentCommitment // keyEncipherment (2), // dataEncipherment (3), // keyAgreement (4), // keyCertSign (5), // cRLSign (6), // encipherOnly (7), // decipherOnly (8) } enum KeyUsageBit { KEY_USAGE_BIT_DIGITAL_SIGNATURE = 0, KEY_USAGE_BIT_NON_REPUDIATION = 1, KEY_USAGE_BIT_KEY_ENCIPHERMENT = 2, KEY_USAGE_BIT_DATA_ENCIPHERMENT = 3, KEY_USAGE_BIT_KEY_AGREEMENT = 4, KEY_USAGE_BIT_KEY_CERT_SIGN = 5, KEY_USAGE_BIT_CRL_SIGN = 6, KEY_USAGE_BIT_ENCIPHER_ONLY = 7, KEY_USAGE_BIT_DECIPHER_ONLY = 8, }; // Parses the KeyUsage extension as defined by RFC 5280. Returns true on // success, and |key_usage| will alias data in |key_usage_tlv|. On failure // returns false, and |key_usage| may have been modified. // // In addition to validating that key_usage_tlv is a BIT STRING, this does // additional KeyUsage specific validations such as requiring at least 1 bit to // be set. // // To test if a particular key usage is set, call, e.g.: // key_usage->AssertsBit(KEY_USAGE_BIT_DIGITAL_SIGNATURE); [[nodiscard]] OPENSSL_EXPORT bool ParseKeyUsage(der::Input key_usage_tlv, der::BitString *key_usage); struct AuthorityInfoAccessDescription { // The accessMethod DER OID value. der::Input access_method_oid; // The accessLocation DER TLV. der::Input access_location; }; // Parses the Authority Information Access extension defined by RFC 5280. // Returns true on success, and |out_access_descriptions| will alias data // in |authority_info_access_tlv|.On failure returns false, and // out_access_descriptions may have been partially filled. // // No validation is performed on the contents of the // AuthorityInfoAccessDescription fields. [[nodiscard]] OPENSSL_EXPORT bool ParseAuthorityInfoAccess( der::Input authority_info_access_tlv, std::vector *out_access_descriptions); // Parses the Authority Information Access extension defined by RFC 5280, // extracting the caIssuers URIs and OCSP URIs. // // Returns true on success, and |out_ca_issuers_uris| and |out_ocsp_uris| will // alias data in |authority_info_access_tlv|. On failure returns false, and // |out_ca_issuers_uris| and |out_ocsp_uris| may have been partially filled. // // |out_ca_issuers_uris| is filled with the accessLocations of type // uniformResourceIdentifier for the accessMethod id-ad-caIssuers. // |out_ocsp_uris| is filled with the accessLocations of type // uniformResourceIdentifier for the accessMethod id-ad-ocsp. // // The values in |out_ca_issuers_uris| and |out_ocsp_uris| are checked to be // IA5String (ASCII strings), but no other validation is performed on them. // // accessMethods other than id-ad-caIssuers and id-ad-ocsp are silently ignored. // accessLocation types other than uniformResourceIdentifier are silently // ignored. [[nodiscard]] OPENSSL_EXPORT bool ParseAuthorityInfoAccessURIs( der::Input authority_info_access_tlv, std::vector *out_ca_issuers_uris, std::vector *out_ocsp_uris); // ParsedDistributionPoint represents a parsed DistributionPoint from RFC 5280. // // DistributionPoint ::= SEQUENCE { // distributionPoint [0] DistributionPointName OPTIONAL, // reasons [1] ReasonFlags OPTIONAL, // cRLIssuer [2] GeneralNames OPTIONAL } struct OPENSSL_EXPORT ParsedDistributionPoint { ParsedDistributionPoint(); ParsedDistributionPoint(ParsedDistributionPoint &&other); ~ParsedDistributionPoint(); // The parsed fullName, if distributionPoint was present and was a fullName. std::unique_ptr distribution_point_fullname; // If present, the DER encoded value of the nameRelativeToCRLIssuer field. // This should be a RelativeDistinguishedName, but the parser does not // validate it. std::optional distribution_point_name_relative_to_crl_issuer; // If present, the DER encoded value of the reasons field. This should be a // ReasonFlags bitString, but the parser does not validate it. std::optional reasons; // If present, the DER encoded value of the cRLIssuer field. This should be a // GeneralNames, but the parser does not validate it. std::optional crl_issuer; }; // Parses the value of a CRL Distribution Points extension (sequence of // DistributionPoint). Return true on success, and fills |distribution_points| // with values that reference data in |distribution_points_tlv|. [[nodiscard]] OPENSSL_EXPORT bool ParseCrlDistributionPoints( der::Input distribution_points_tlv, std::vector *distribution_points); // Represents the AuthorityKeyIdentifier extension defined by RFC 5280 section // 4.2.1.1. // // AuthorityKeyIdentifier ::= SEQUENCE { // keyIdentifier [0] KeyIdentifier OPTIONAL, // authorityCertIssuer [1] GeneralNames OPTIONAL, // authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } // // KeyIdentifier ::= OCTET STRING struct OPENSSL_EXPORT ParsedAuthorityKeyIdentifier { ParsedAuthorityKeyIdentifier(); ~ParsedAuthorityKeyIdentifier(); ParsedAuthorityKeyIdentifier(ParsedAuthorityKeyIdentifier &&other); ParsedAuthorityKeyIdentifier &operator=(ParsedAuthorityKeyIdentifier &&other); // The keyIdentifier, which is an OCTET STRING. std::optional key_identifier; // The authorityCertIssuer, which should be a GeneralNames, but this is not // enforced by ParseAuthorityKeyIdentifier. std::optional authority_cert_issuer; // The DER authorityCertSerialNumber, which should be a // CertificateSerialNumber (an INTEGER) but this is not enforced by // ParseAuthorityKeyIdentifier. std::optional authority_cert_serial_number; }; // Parses the value of an authorityKeyIdentifier extension. Returns true on // success and fills |authority_key_identifier| with values that reference data // in |extension_value|. On failure the state of |authority_key_identifier| is // not guaranteed. [[nodiscard]] OPENSSL_EXPORT bool ParseAuthorityKeyIdentifier( der::Input extension_value, ParsedAuthorityKeyIdentifier *authority_key_identifier); // Parses the value of a subjectKeyIdentifier extension. Returns true on // success and |subject_key_identifier| references data in |extension_value|. // On failure the state of |subject_key_identifier| is not guaranteed. [[nodiscard]] OPENSSL_EXPORT bool ParseSubjectKeyIdentifier( der::Input extension_value, der::Input *subject_key_identifier); } // namespace bssl #endif // BSSL_PKI_PARSE_CERTIFICATE_H_