| /* |
| * |
| * Copyright (c) 2020-2022 Project CHIP Authors |
| * Copyright (c) 2019 Google LLC. |
| * Copyright (c) 2013-2017 Nest Labs, Inc. |
| * All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /** |
| * @file |
| * This file defines data types and objects for modeling and |
| * working with CHIP certificates. |
| * |
| */ |
| |
| #pragma once |
| |
| #include <cstdint> |
| #include <string.h> |
| |
| #include <crypto/CHIPCryptoPAL.h> |
| #include <lib/asn1/ASN1.h> |
| #include <lib/core/CASEAuthTag.h> |
| #include <lib/core/CHIPConfig.h> |
| #include <lib/core/DataModelTypes.h> |
| #include <lib/core/PeerId.h> |
| #include <lib/core/TLV.h> |
| #include <lib/support/BitFlags.h> |
| #include <lib/support/DLLUtil.h> |
| #include <lib/support/Span.h> |
| #include <system/SystemClock.h> |
| |
| namespace chip { |
| namespace Credentials { |
| |
| static constexpr uint32_t kKeyIdentifierLength = static_cast<uint32_t>(Crypto::kSubjectKeyIdentifierLength); |
| static constexpr uint32_t kChip32bitAttrUTF8Length = 8; |
| static constexpr uint32_t kChip64bitAttrUTF8Length = 16; |
| static constexpr uint16_t kX509NoWellDefinedExpirationDateYear = 9999; |
| |
| // As per specifications (6.4.5. Node Operational Credentials Certificates) |
| static constexpr uint32_t kMaxCHIPCertLength = 400; |
| static constexpr uint32_t kMaxDERCertLength = 600; |
| |
| // As per spec section 11.24 (Wi-Fi Authentication with Per-Device Credentials) |
| inline constexpr uint32_t kMaxCHIPCompactNetworkIdentityLength = 137; |
| |
| /** Data Element Tags for the CHIP Certificate |
| */ |
| enum |
| { |
| // ---- Context-specific Tags for ChipCertificate Structure ---- |
| kTag_SerialNumber = 1, /**< [ byte string ] Certificate serial number, in BER integer encoding. */ |
| kTag_SignatureAlgorithm = 2, /**< [ unsigned int ] Enumerated value identifying the certificate signature algorithm. */ |
| kTag_Issuer = 3, /**< [ list ] The issuer distinguished name of the certificate. */ |
| kTag_NotBefore = 4, /**< [ unsigned int ] Certificate validity period start (certificate date format). */ |
| kTag_NotAfter = 5, /**< [ unsigned int ] Certificate validity period end (certificate date format). */ |
| kTag_Subject = 6, /**< [ list ] The subject distinguished name of the certificate. */ |
| kTag_PublicKeyAlgorithm = 7, /**< [ unsigned int ] Identifies the algorithm with which the public key can be used. */ |
| kTag_EllipticCurveIdentifier = 8, /**< [ unsigned int ] For EC certs, identifies the elliptic curve used. */ |
| kTag_EllipticCurvePublicKey = 9, /**< [ byte string ] The elliptic curve public key, in X9.62 encoded format. */ |
| kTag_Extensions = 10, /**< [ list ] Certificate extensions. */ |
| kTag_ECDSASignature = 11, /**< [ byte string ] The ECDSA signature for the certificate. */ |
| |
| // ---- Context-specific Tags for certificate extensions ---- |
| kTag_BasicConstraints = 1, /**< [ structure ] Identifies whether the subject of the certificate is a CA. */ |
| kTag_KeyUsage = 2, /**< [ unsigned int ] Bits identifying key usage, per RFC5280. */ |
| kTag_ExtendedKeyUsage = 3, /**< [ array ] Enumerated values giving the purposes for which the public key can be used. */ |
| kTag_SubjectKeyIdentifier = 4, /**< [ byte string ] Identifier of the certificate's public key. */ |
| kTag_AuthorityKeyIdentifier = 5, /**< [ byte string ] Identifier of the public key used to sign the certificate. */ |
| kTag_FutureExtension = 6, /**< [ byte string ] Arbitrary extension. DER encoded SEQUENCE as in X.509 form. */ |
| |
| // ---- Context-specific Tags for BasicConstraints Structure ---- |
| kTag_BasicConstraints_IsCA = 1, /**< [ boolean ] True if the certificate can be used to verify certificate |
| signatures. */ |
| kTag_BasicConstraints_PathLenConstraint = 2, /**< [ unsigned int ] Maximum number of subordinate intermediate certificates. */ |
| }; |
| |
| /** Identifies the purpose or application of certificate |
| * |
| * A certificate type is a label that describes a certificate's purpose or application. |
| * Certificate types are not carried as attributes of the corresponding certificates, but |
| * rather are derived from the certificate's structure and/or the context in which it is used. |
| * The certificate type enumeration includes a set of pre-defined values describing commonly |
| * used certificate applications. |
| * |
| * Certificate types are primarily used in the implementation of access control policies, |
| * where access to application features is influenced by the type of certificate presented |
| * by a requester. |
| * |
| * @note Cert type is an API data type only; it should never be sent over-the-wire. |
| */ |
| enum class CertType : uint8_t |
| { |
| kNotSpecified = 0x00, /**< The certificate's type has not been specified. */ |
| kRoot = 0x01, /**< A CHIP Root certificate. */ |
| kICA = 0x02, /**< A CHIP Intermediate CA certificate. */ |
| kNode = 0x03, /**< A CHIP node certificate. */ |
| kFirmwareSigning = 0x04, /**< A CHIP firmware signing certificate. Note that CHIP doesn't |
| specify how firmware images are signed and implementation of |
| firmware image signing is manufacturer-specific. The CHIP |
| certificate format supports encoding of firmware signing |
| certificates if chosen by the manufacturer to use them. */ |
| kNetworkIdentity = 0x05, /**< A CHIP Network (Client) Identity. */ |
| }; |
| |
| /** X.509 Certificate Key Purpose Flags |
| * |
| * The flags order must match the enumeration order of corresponding kOID_KeyPurpose values. |
| */ |
| enum class KeyPurposeFlags : uint8_t |
| { |
| kServerAuth = 0x01, /**< Extended key usage is server authentication. */ |
| kClientAuth = 0x02, /**< Extended key usage is client authentication. */ |
| kCodeSigning = 0x04, /**< Extended key usage is code signing. */ |
| kEmailProtection = 0x08, /**< Extended key usage is email protection. */ |
| kTimeStamping = 0x10, /**< Extended key usage is time stamping. */ |
| kOCSPSigning = 0x20, /**< Extended key usage is OCSP signing. */ |
| }; |
| |
| /** X.509 Certificate Key Usage Flags |
| */ |
| enum class KeyUsageFlags : uint16_t |
| { |
| kDigitalSignature = 0x0001, /**< Key usage is digital signature. */ |
| kNonRepudiation = 0x0002, /**< Key usage is non-repudiation. */ |
| kKeyEncipherment = 0x0004, /**< Key usage is key encipherment. */ |
| kDataEncipherment = 0x0008, /**< Key usage is data encipherment. */ |
| kKeyAgreement = 0x0010, /**< Key usage is key agreement. */ |
| kKeyCertSign = 0x0020, /**< Key usage is key cert signing. */ |
| kCRLSign = 0x0040, /**< Key usage is CRL signing. */ |
| kEncipherOnly = 0x0080, /**< Key usage is encipher only. */ |
| kDecipherOnly = 0x0100, /**< Key usage is decipher only. */ |
| }; |
| |
| /** CHIP Certificate Flags |
| * |
| * Contains information about a certificate that has been loaded into a ChipCertificateData object. |
| */ |
| enum class CertFlags : uint16_t |
| { |
| kExtPresent_BasicConstraints = 0x0001, /**< Basic constraints extension is present in the certificate. */ |
| kExtPresent_KeyUsage = 0x0002, /**< Key usage extension is present in the certificate. */ |
| kExtPresent_ExtendedKeyUsage = 0x0004, /**< Extended key usage extension is present in the certificate. */ |
| kExtPresent_SubjectKeyId = 0x0008, /**< Subject key identifier extension is present in the certificate. */ |
| kExtPresent_AuthKeyId = 0x0010, /**< Authority key identifier extension is present in the certificate. */ |
| kExtPresent_FutureIsCritical = 0x0020, /**< Future extension marked as critical is present in the certificate. */ |
| kPathLenConstraintPresent = 0x0040, /**< Path length constraint is present in the certificate. */ |
| kIsCA = 0x0080, /**< Indicates that certificate is a CA certificate. */ |
| kIsTrustAnchor = 0x0100, /**< Indicates that certificate is a trust anchor. */ |
| kTBSHashPresent = 0x0200, /**< Indicates that TBS hash of the certificate was generated and stored. */ |
| }; |
| |
| /** CHIP Certificate Decode Flags |
| * |
| * Contains information specifying how a certificate should be decoded. |
| */ |
| enum class CertDecodeFlags : uint8_t |
| { |
| kGenerateTBSHash = 0x01, /**< Indicates that to-be-signed (TBS) hash of the certificate should be calculated when certificate is |
| loaded. The TBS hash is then used to validate certificate signature. Normally, all certificates |
| (except trust anchor) in the certificate validation chain require TBS hash. */ |
| kIsTrustAnchor = 0x02, /**< Indicates that the corresponding certificate is trust anchor. */ |
| }; |
| |
| enum |
| { |
| kNullCertTime = 0 |
| }; |
| |
| /** |
| * @struct ChipRDN |
| * |
| * @brief |
| * A data structure representing a Relative Distinguished Name (RDN) in a CHIP certificate. |
| */ |
| struct ChipRDN |
| { |
| CharSpan mString; /**< Attribute value when encoded as a string. */ |
| uint64_t mChipVal; /**< CHIP specific DN attribute value. */ |
| chip::ASN1::OID mAttrOID = chip::ASN1::kOID_NotSpecified; /**< DN attribute CHIP OID. */ |
| bool mAttrIsPrintableString; /**< Specifies if attribute is a printable string type. */ |
| |
| bool IsEqual(const ChipRDN & other) const; |
| bool IsEmpty() const { return mAttrOID == chip::ASN1::kOID_NotSpecified; } |
| void Clear() |
| { |
| mAttrOID = chip::ASN1::kOID_NotSpecified; |
| mAttrIsPrintableString = false; |
| mChipVal = 0; |
| mString = CharSpan{}; |
| } |
| }; |
| |
| /** |
| * @brief |
| * A data structure representing a Distinguished Name (DN) in a CHIP certificate. |
| */ |
| class ChipDN |
| { |
| public: |
| ChipDN(); |
| ~ChipDN(); |
| |
| void Clear(); |
| |
| /** |
| * @brief Add CHIP-specific attribute to the DN. |
| * |
| * @param oid CHIP-specific OID for DN attribute. |
| * @param val CHIP-specific DN attribute value. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR AddAttribute(chip::ASN1::OID oid, uint64_t val); |
| |
| /** |
| * @brief Add CASE Authenticated Tags (CATs) attributes to the DN. |
| * |
| * @param cats Array of CAT values. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR AddCATs(const chip::CATValues & cats); |
| |
| /** |
| * @brief Add string attribute to the DN. |
| * |
| * @param oid String OID for DN attribute. |
| * @param val A CharSpan object containing a pointer and length of the DN string attribute |
| * buffer. The value in the buffer should remain valid while the object is in use. |
| * @param isPrintableString Specifies if attribute ASN1 type is a printable string. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR AddAttribute(chip::ASN1::OID oid, CharSpan val, bool isPrintableString); |
| |
| inline CHIP_ERROR AddAttribute_CommonName(CharSpan val, bool isPrintableString) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_CommonName, val, isPrintableString); |
| } |
| inline CHIP_ERROR AddAttribute_Surname(CharSpan val, bool isPrintableString) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_Surname, val, isPrintableString); |
| } |
| inline CHIP_ERROR AddAttribute_SerialNumber(CharSpan val, bool isPrintableString) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_SerialNumber, val, isPrintableString); |
| } |
| inline CHIP_ERROR AddAttribute_CountryName(CharSpan val, bool isPrintableString) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_CountryName, val, isPrintableString); |
| } |
| inline CHIP_ERROR AddAttribute_LocalityName(CharSpan val, bool isPrintableString) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_LocalityName, val, isPrintableString); |
| } |
| inline CHIP_ERROR AddAttribute_StateOrProvinceName(CharSpan val, bool isPrintableString) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_StateOrProvinceName, val, isPrintableString); |
| } |
| inline CHIP_ERROR AddAttribute_OrganizationName(CharSpan val, bool isPrintableString) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_OrganizationName, val, isPrintableString); |
| } |
| inline CHIP_ERROR AddAttribute_OrganizationalUnitName(CharSpan val, bool isPrintableString) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_OrganizationalUnitName, val, isPrintableString); |
| } |
| inline CHIP_ERROR AddAttribute_Title(CharSpan val, bool isPrintableString) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_Title, val, isPrintableString); |
| } |
| inline CHIP_ERROR AddAttribute_Name(CharSpan val, bool isPrintableString) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_Name, val, isPrintableString); |
| } |
| inline CHIP_ERROR AddAttribute_GivenName(CharSpan val, bool isPrintableString) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_GivenName, val, isPrintableString); |
| } |
| inline CHIP_ERROR AddAttribute_Initials(CharSpan val, bool isPrintableString) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_Initials, val, isPrintableString); |
| } |
| inline CHIP_ERROR AddAttribute_GenerationQualifier(CharSpan val, bool isPrintableString) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_GenerationQualifier, val, isPrintableString); |
| } |
| inline CHIP_ERROR AddAttribute_DNQualifier(CharSpan val, bool isPrintableString) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_DNQualifier, val, isPrintableString); |
| } |
| inline CHIP_ERROR AddAttribute_Pseudonym(CharSpan val, bool isPrintableString) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_Pseudonym, val, isPrintableString); |
| } |
| inline CHIP_ERROR AddAttribute_DomainComponent(CharSpan val, bool isPrintableString) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_DomainComponent, val, isPrintableString); |
| } |
| inline CHIP_ERROR AddAttribute_MatterNodeId(uint64_t val) { return AddAttribute(ASN1::kOID_AttributeType_MatterNodeId, val); } |
| inline CHIP_ERROR AddAttribute_MatterFirmwareSigningId(uint64_t val) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_MatterFirmwareSigningId, val); |
| } |
| inline CHIP_ERROR AddAttribute_MatterICACId(uint64_t val) { return AddAttribute(ASN1::kOID_AttributeType_MatterICACId, val); } |
| inline CHIP_ERROR AddAttribute_MatterRCACId(uint64_t val) { return AddAttribute(ASN1::kOID_AttributeType_MatterRCACId, val); } |
| inline CHIP_ERROR AddAttribute_MatterFabricId(uint64_t val) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_MatterFabricId, val); |
| } |
| inline CHIP_ERROR AddAttribute_MatterCASEAuthTag(CASEAuthTag val) |
| { |
| return AddAttribute(ASN1::kOID_AttributeType_MatterCASEAuthTag, val); |
| } |
| |
| /** |
| * @brief Determine type of a CHIP certificate. |
| * This method performs an assessment of a certificate's type based on the structure |
| * of its subject DN. |
| * |
| * @param certType A reference to the certificate type value. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR GetCertType(CertType & certType) const; |
| |
| /** |
| * @brief Retrieve the ID of a CHIP certificate. |
| * |
| * @param certId A reference to the certificate ID value. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR GetCertChipId(uint64_t & certId) const; |
| |
| /** |
| * @brief Retrieve the Fabric ID of a CHIP certificate. |
| **/ |
| CHIP_ERROR GetCertFabricId(uint64_t & fabricId) const; |
| |
| /** |
| * @brief Encode ChipDN attributes in TLV form. |
| **/ |
| CHIP_ERROR EncodeToTLV(chip::TLV::TLVWriter & writer, TLV::Tag tag) const; |
| |
| /** |
| * @brief Decode ChipDN attributes from TLV encoded format. |
| * |
| * @param reader A TLVReader positioned at the ChipDN TLV list. |
| **/ |
| CHIP_ERROR DecodeFromTLV(chip::TLV::TLVReader & reader); |
| |
| /** |
| * @brief Encode ChipDN attributes in ASN1 form. |
| **/ |
| CHIP_ERROR EncodeToASN1(ASN1::ASN1Writer & writer) const; |
| |
| /** |
| * @brief Decode ChipDN attributes from ASN1 encoded format. |
| * |
| * @param reader A ASN1Reader positioned at the ChipDN ASN1 list. |
| **/ |
| CHIP_ERROR DecodeFromASN1(ASN1::ASN1Reader & reader); |
| |
| bool IsEqual(const ChipDN & other) const; |
| |
| /** |
| * @brief Determine if DN is empty (doesn't have DN attributes). |
| * |
| * @return true if DN is empty, false otherwise. |
| **/ |
| bool IsEmpty() const { return RDNCount() == 0; } |
| |
| static_assert((CHIP_CONFIG_CERT_MAX_RDN_ATTRIBUTES) >= 5, "Spec requires at least 5 RDN to be supported per Matter TLV cert"); |
| ChipRDN rdn[CHIP_CONFIG_CERT_MAX_RDN_ATTRIBUTES]; |
| |
| uint8_t RDNCount() const; |
| }; |
| |
| /** |
| * @brief A data structure for holding a certificate key identifier, without the ownership of it. |
| */ |
| using CertificateKeyId = FixedByteSpan<kKeyIdentifierLength>; |
| |
| /** |
| * @brief A mutable `CertificateKeyId`. |
| */ |
| using MutableCertificateKeyId = FixedSpan<uint8_t, kKeyIdentifierLength>; |
| |
| /** |
| * @brief A storage type for `CertificateKeyId` and `MutableCertificateKeyId`. |
| */ |
| using CertificateKeyIdStorage = std::array<uint8_t, kKeyIdentifierLength>; |
| |
| /** |
| * @brief A data structure for holding a P256 ECDSA signature, without the ownership of it. |
| */ |
| using P256ECDSASignatureSpan = FixedByteSpan<Crypto::kP256_ECDSA_Signature_Length_Raw>; |
| |
| /** |
| * @brief A data structure for holding a P256 Public Key, without the ownership of it. |
| */ |
| using P256PublicKeySpan = FixedByteSpan<Crypto::kP256_PublicKey_Length>; |
| |
| /** |
| * @brief A data structure for holding a P256 Integer, without the ownership of it. |
| */ |
| using P256IntegerSpan = FixedByteSpan<Crypto::kP256_FE_Length>; |
| |
| /** |
| * @struct ChipCertificateData |
| * |
| * @brief |
| * In-memory representation of data extracted from a CHIP certificate. |
| * |
| * Some of the fields in this structure are pointers to the fields in the original |
| * CHIP certificate. That CHIP certificate is stored in a separate buffer and it is |
| * required that data in that buffer remains valid while the corresponding |
| * ChipCertificateData structure is used. |
| */ |
| struct ChipCertificateData |
| { |
| ChipCertificateData(); |
| ~ChipCertificateData(); |
| |
| void Clear(); |
| bool IsEqual(const ChipCertificateData & other) const; |
| |
| ByteSpan mSerialNumber; /**< Certificate Serial Number. */ |
| ChipDN mSubjectDN; /**< Certificate Subject DN. */ |
| ChipDN mIssuerDN; /**< Certificate Issuer DN. */ |
| CertificateKeyId mSubjectKeyId; /**< Certificate Subject public key identifier. */ |
| CertificateKeyId mAuthKeyId; /**< Certificate Authority public key identifier. */ |
| uint32_t mNotBeforeTime; /**< Certificate validity: Not Before field. */ |
| uint32_t mNotAfterTime; /**< Certificate validity: Not After field. */ |
| P256PublicKeySpan mPublicKey; /**< Certificate public key. */ |
| uint16_t mPubKeyCurveOID; /**< Public key Elliptic Curve CHIP OID. */ |
| uint16_t mPubKeyAlgoOID; /**< Public key algorithm CHIP OID. */ |
| uint16_t mSigAlgoOID; /**< Certificate signature algorithm CHIP OID. */ |
| BitFlags<CertFlags> mCertFlags; /**< Certificate data flags. */ |
| BitFlags<KeyUsageFlags> mKeyUsageFlags; /**< Certificate key usage extensions flags. */ |
| BitFlags<KeyPurposeFlags> mKeyPurposeFlags; /**< Certificate extended key usage extensions flags. */ |
| uint8_t mPathLenConstraint; /**< Basic constraint: path length. */ |
| P256ECDSASignatureSpan mSignature; /**< Certificate signature. */ |
| |
| uint8_t mTBSHash[Crypto::kSHA256_Hash_Length]; /**< Certificate TBS hash. */ |
| }; |
| |
| /** |
| * @brief Decode CHIP certificate. |
| * It is required that the CHIP certificate in the chipCert buffer stays valid while |
| * the certData is used. |
| * |
| * @param chipCert Buffer containing CHIP certificate. |
| * @param certData Structure containing data extracted from the CHIP certificate. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR DecodeChipCert(const ByteSpan chipCert, ChipCertificateData & certData, BitFlags<CertDecodeFlags> decodeFlags = {}); |
| |
| /** |
| * @brief Decode CHIP certificate. |
| * It is required that the CHIP certificate in the reader's underlying buffer stays valid while |
| * the certData is used. |
| * |
| * @param reader A TLVReader positioned at the CHIP certificate TLV structure. |
| * @param certData Structure containing data extracted from the CHIP certificate. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR DecodeChipCert(chip::TLV::TLVReader & reader, ChipCertificateData & certData, |
| BitFlags<CertDecodeFlags> decodeFlags = {}); |
| |
| /** |
| * @brief Decode CHIP Distinguished Name (DN). |
| * It is required that the CHIP DN in the reader's underlying buffer stays valid while |
| * the dn structure is used. |
| * |
| * @param reader A TLVReader positioned at the CHIP DN TLV structure. |
| * @param dn Distinguished Name structure. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR DecodeChipDN(chip::TLV::TLVReader & reader, ChipDN & dn); |
| |
| /** |
| * @brief Convert standard X.509 certificate to CHIP certificate. |
| * |
| * @param x509Cert CHIP X.509 DER encoded certificate. |
| * @param chipCert Buffer to store converted certificate in CHIP format. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR ConvertX509CertToChipCert(const ByteSpan x509Cert, MutableByteSpan & chipCert); |
| |
| /** |
| * @brief Convert CHIP certificate to the standard X.509 DER encoded certificate. |
| * |
| * @param chipCert CHIP certificate in CHIP TLV encoding. |
| * @param x509Cert Buffer to store converted certificate in X.509 DER format. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR ConvertChipCertToX509Cert(const ByteSpan chipCert, MutableByteSpan & x509Cert); |
| |
| /** |
| * @brief Verifies the signature of a certificate. |
| * |
| * @param cert The certificate to be verified. |
| * @param signer The certificate containing the public key used to verify the signature. |
| * |
| * @return Returns a CHIP_ERROR on validation or other error, CHIP_NO_ERROR otherwise |
| * |
| * The certificate to be verified must have been decoded with TBS hash calculation enabled. |
| * |
| * Note that this function performs ONLY signature verification. No Subject and Issuer DN |
| * comparison, Key Usage extension checks or similar validation is performed. |
| **/ |
| CHIP_ERROR VerifyCertSignature(const ChipCertificateData & cert, const ChipCertificateData & signer); |
| |
| /** |
| * Validate CHIP Root CA Certificate (RCAC) in ByteSpan TLV-encoded form. |
| * This function performs RCAC parsing, checks SubjectDN validity, verifies that SubjectDN |
| * and IssuerDN are equal, verifies that SKID and AKID are equal, validates certificate signature. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| */ |
| CHIP_ERROR ValidateChipRCAC(const ByteSpan & rcac); |
| |
| /** |
| * Validates a Network (Client) Identity in TLV-encoded form. |
| * Accepts either a full certificate or the compact-pdc-identity format. |
| * |
| * This function parses the certificate, ensures the rigid fields have the values mandated by the |
| * specification, and validates the certificate signature. |
| * |
| * @param cert The network identity certificate to validate. |
| * |
| * @return CHIP_NO_ERROR on success, CHIP_ERROR_WRONG_CERT_TYPE if the certificate does |
| * not conform to the requirements for a Network Identity, CHIP_ERROR_INVALID_SIGNATURE |
| * if the certificate has an invalid signature, or another CHIP_ERROR. |
| * |
| * @see section 11.24 (Wi-Fi Authentication with Per-Device Credentials) of the Matter spec |
| */ |
| CHIP_ERROR ValidateChipNetworkIdentity(const ByteSpan & cert); |
| |
| /** |
| * Convenience variant of `ValidateChipNetworkIdentity` that, upon successful validation, also |
| * calculates the key identifier for the Network (Client) Identity. |
| * @see ValidateChipNetworkIdentity |
| * @see ExtractIdentifierFromChipNetworkIdentity |
| */ |
| CHIP_ERROR ValidateChipNetworkIdentity(const ByteSpan & cert, MutableCertificateKeyId outKeyId); |
| |
| struct FutureExtension |
| { |
| ByteSpan OID; |
| ByteSpan Extension; |
| }; |
| |
| struct X509CertRequestParams |
| { |
| int64_t SerialNumber; |
| uint32_t ValidityStart; |
| uint32_t ValidityEnd; |
| ChipDN SubjectDN; |
| ChipDN IssuerDN; |
| Optional<FutureExtension> FutureExt; |
| }; |
| |
| /** |
| * @brief Generate a new X.509 DER encoded Root CA certificate |
| * |
| * @param requestParams Certificate request parameters. |
| * @param issuerKeypair The certificate signing key |
| * @param x509Cert Buffer to store signed certificate in X.509 DER format. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR NewRootX509Cert(const X509CertRequestParams & requestParams, const Crypto::P256Keypair & issuerKeypair, |
| MutableByteSpan & x509Cert); |
| |
| /** |
| * @brief Generate a new X.509 DER encoded Intermediate CA certificate |
| * |
| * @param requestParams Certificate request parameters. |
| * @param subjectPubkey The public key of subject |
| * @param issuerKeypair The certificate signing key |
| * @param x509Cert Buffer to store signed certificate in X.509 DER format. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR NewICAX509Cert(const X509CertRequestParams & requestParams, const Crypto::P256PublicKey & subjectPubkey, |
| const Crypto::P256Keypair & issuerKeypair, MutableByteSpan & x509Cert); |
| |
| /** |
| * @brief Generate a new X.509 DER encoded Node operational certificate |
| * |
| * @param requestParams Certificate request parameters. |
| * @param subjectPubkey The public key of subject |
| * @param issuerKeypair The certificate signing key |
| * @param x509Cert Buffer to store signed certificate in X.509 DER format. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR NewNodeOperationalX509Cert(const X509CertRequestParams & requestParams, const Crypto::P256PublicKey & subjectPubkey, |
| const Crypto::P256Keypair & issuerKeypair, MutableByteSpan & x509Cert); |
| |
| /** |
| * @brief Generates a Network (Client) Identity certificate in TLV-encoded form. |
| * |
| * @param keypair The key pair underlying the identity. |
| * @param outCompactCert Buffer to store the signed certificate in compact-pdc-identity TLV format. |
| * Must be at least `kMaxCHIPCompactNetworkIdentityLength` bytes long. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR NewChipNetworkIdentity(const Crypto::P256Keypair & keypair, MutableByteSpan & outCompactCert); |
| |
| /** |
| * @brief |
| * Convert a certificate date/time (in the form of an ASN.1 universal time structure) into a CHIP Epoch time. |
| * |
| * @note |
| * This function makes no attempt to verify the correct range of the input time other than year. |
| * Therefore callers must make sure the supplied values are valid prior to invocation. |
| * |
| * @param asn1Time The calendar date/time to be converted. |
| * @param epochTime A reference to an integer that will receive CHIP Epoch time. |
| * |
| * @retval #CHIP_NO_ERROR If the input time was successfully converted. |
| * @retval #ASN1_ERROR_UNSUPPORTED_ENCODING If the input time contained a year value that could not |
| * be represented in a CHIP epoch UTC time value. |
| **/ |
| CHIP_ERROR ASN1ToChipEpochTime(const chip::ASN1::ASN1UniversalTime & asn1Time, uint32_t & epochTime); |
| |
| /** |
| * @brief |
| * Convert a CHIP epoch UTC time into an ASN.1 universal time structure. |
| * |
| * @param epochTime A CHIP epoch UTC time to be converted. |
| * @param asn1Time A reference to an ASN1UniversalTime structure to receive the date/time. |
| * |
| * @retval #CHIP_NO_ERROR If the input time was successfully converted. |
| */ |
| CHIP_ERROR ChipEpochToASN1Time(uint32_t epochTime, chip::ASN1::ASN1UniversalTime & asn1Time); |
| |
| /** |
| * @return True if the OID represents a CHIP-defined 64-bit distinguished named attribute. |
| **/ |
| inline bool IsChip64bitDNAttr(chip::ASN1::OID oid) |
| { |
| return (oid == chip::ASN1::kOID_AttributeType_MatterNodeId || oid == chip::ASN1::kOID_AttributeType_MatterFirmwareSigningId || |
| oid == chip::ASN1::kOID_AttributeType_MatterICACId || oid == chip::ASN1::kOID_AttributeType_MatterRCACId || |
| oid == chip::ASN1::kOID_AttributeType_MatterFabricId); |
| } |
| |
| /** |
| * @return True if the OID represents a CHIP-defined 32-bit distinguished named attribute. |
| **/ |
| inline bool IsChip32bitDNAttr(chip::ASN1::OID oid) |
| { |
| return (oid == chip::ASN1::kOID_AttributeType_MatterCASEAuthTag); |
| } |
| |
| /** |
| * @return True if the OID represents a CHIP-defined distinguished named attribute. |
| **/ |
| inline bool IsChipDNAttr(chip::ASN1::OID oid) |
| { |
| return (IsChip64bitDNAttr(oid) || IsChip32bitDNAttr(oid)); |
| } |
| |
| /** |
| * @brief Convert an ASN.1 DER encoded integer to a raw big-endian integer. |
| * |
| * @param derInt P256 integer in ASN.1 DER encoded form. |
| * @param rawInt Buffer to store converted raw integer. |
| * @param rawIntLen The length of the converted raw integer. |
| * |
| * @retval #CHIP_NO_ERROR If the integer value was successfully converted. |
| */ |
| CHIP_ERROR ConvertIntegerDERToRaw(ByteSpan derInt, uint8_t * rawInt, const uint16_t rawIntLen); |
| |
| /** |
| * @brief Convert a raw CHIP signature to an ASN.1 DER encoded signature structure. |
| * |
| * @param[in] rawSig P256 ECDSA signature in raw form. |
| * @param[in,out] derSig Output buffer to receive the converted ASN.1 DER encoded signature. |
| * `derSig` must be at least `kMax_ECDSA_Signature_Length_Der` bytes long. |
| * The `derSig` size will be set to the actual DER encoded signature length on success. |
| * |
| * @retval #CHIP_NO_ERROR If the signature value was successfully converted. |
| */ |
| CHIP_ERROR ConvertECDSASignatureRawToDER(P256ECDSASignatureSpan rawSig, MutableByteSpan & derSig); |
| |
| /** |
| * @brief Convert a raw CHIP ECDSA signature to an ASN.1 DER encoded signature structure. |
| * |
| * @param rawSig P256 ECDSA signature in raw form. |
| * @param writer A reference to the ASN1Writer to store ASN.1 DER encoded signature. |
| * |
| * @retval #CHIP_NO_ERROR If the signature value was successfully converted. |
| */ |
| CHIP_ERROR ConvertECDSASignatureRawToDER(P256ECDSASignatureSpan rawSig, ASN1::ASN1Writer & writer); |
| |
| /** |
| * @brief Convert an ASN.1 DER encoded ECDSA signature to a raw CHIP signature. |
| * |
| * @param reader A reference to the ASN1Reader positioned at the beginning of the |
| * DER encoded ECDSA signature. |
| * @param writer A reference to the TLVWriter to store TLV encoded ECDSA signature element. |
| * @param tag Tag to use for TLV encoded signature. |
| * |
| * @retval #CHIP_NO_ERROR If the signature value was successfully converted. |
| */ |
| CHIP_ERROR ConvertECDSASignatureDERToRaw(ASN1::ASN1Reader & reader, chip::TLV::TLVWriter & writer, uint64_t tag); |
| |
| /** |
| * Extract the Fabric ID from an operational certificate that has already been |
| * parsed. |
| * |
| * This function can be used to extract Fabric ID from an ICA certificate. |
| * These certificates may not contain a NodeID, so ExtractNodeIdFabricIdFromOpCert() |
| * cannot be used for such certificates. |
| * |
| * @return CHIP_ERROR_NOT_FOUND if the passed-in cert does not have RDN |
| * corresponding to FabricID. |
| */ |
| CHIP_ERROR ExtractFabricIdFromCert(const ChipCertificateData & cert, FabricId * fabricId); |
| |
| /** |
| * Extract Node ID and Fabric ID from an operational certificate that has already been |
| * parsed. |
| * |
| * @return CHIP_ERROR_NOT_FOUND if the passed-in cert does not have at |
| * least one NodeId RDN and one FabricId RDN in the Subject DN. No other |
| * validation (e.g. checkign that there is exactly one RDN of each type) is |
| * performed. |
| */ |
| CHIP_ERROR ExtractNodeIdFabricIdFromOpCert(const ChipCertificateData & opcert, NodeId * nodeId, FabricId * fabricId); |
| |
| /** |
| * Extract Node ID, Fabric ID and Compressed Fabric ID from an operational |
| * certificate and its associated root certificate. |
| * |
| * @return CHIP_ERROR on failure or CHIP_NO_ERROR otherwise. |
| */ |
| CHIP_ERROR ExtractNodeIdFabricIdCompressedFabricIdFromOpCerts(ByteSpan rcac, ByteSpan noc, CompressedFabricId & compressedFabricId, |
| FabricId & fabricId, NodeId & nodeId); |
| |
| /** |
| * Extract Node ID and Compressed Fabric ID from an operational certificate |
| * and its associated root certificate. |
| * |
| * @return CHIP_ERROR on failure or CHIP_NO_ERROR otherwise. |
| */ |
| CHIP_ERROR ExtractNodeIdCompressedFabricIdFromOpCerts(ByteSpan rcac, ByteSpan noc, CompressedFabricId & compressedFabricId, |
| NodeId & nodeId); |
| |
| /** |
| * Extract CASE Authenticated Tags from an operational certificate in ByteSpan TLV-encoded form. |
| * |
| * All values in the 'cats' struct will be set either to a valid CAT value or zero (undefined) value. |
| * |
| * @return CHIP_ERROR_INVALID_ARGUMENT if the passed-in cert is not NOC. |
| * @return CHIP_ERROR_BUFFER_TOO_SMALL if there are too many CATs in the NOC |
| */ |
| CHIP_ERROR ExtractCATsFromOpCert(const ByteSpan & opcert, CATValues & cats); |
| |
| /** |
| * Extract CASE Authenticated Tags from an operational certificate that has already been |
| * parsed. |
| * |
| * All values in the 'cats' struct will be set either to a valid CAT value or to the kUndefinedCAT value. |
| * |
| * @return CHIP_ERROR_INVALID_ARGUMENT if the passed-in cert is not NOC. |
| * @return CHIP_ERROR_BUFFER_TOO_SMALL if the passed-in CATs array is too small. |
| */ |
| CHIP_ERROR ExtractCATsFromOpCert(const ChipCertificateData & opcert, CATValues & cats); |
| |
| /** |
| * Extract Fabric ID from an operational certificate in ByteSpan TLV-encoded |
| * form. This does not perform any sort of validation on the certificate |
| * structure other than parsing it. |
| * |
| * Can return any error that can be returned from parsing the cert or from the |
| * ChipCertificateData* version of ExtractNodeIdFabricIdFromOpCert. |
| */ |
| CHIP_ERROR ExtractFabricIdFromCert(const ByteSpan & opcert, FabricId * fabricId); |
| |
| /** |
| * Extract Node ID and Fabric ID from an operational certificate in ByteSpan TLV-encoded |
| * form. This does not perform any sort of validation on the certificate |
| * structure other than parsing it. |
| * |
| * Can return any error that can be returned from parsing the cert or from the |
| * ChipCertificateData* version of ExtractNodeIdFabricIdFromOpCert. |
| */ |
| CHIP_ERROR ExtractNodeIdFabricIdFromOpCert(const ByteSpan & opcert, NodeId * nodeId, FabricId * fabricId); |
| |
| /** |
| * Extract Public Key from a chip certificate in ByteSpan TLV-encoded form. |
| * This does not perform any sort of validation on the certificate structure |
| * other than parsing it. |
| * |
| * Can return any error that can be returned from parsing the cert. |
| */ |
| CHIP_ERROR ExtractPublicKeyFromChipCert(const ByteSpan & chipCert, P256PublicKeySpan & publicKey); |
| |
| /** |
| * Extract Not Before Time from a chip certificate in ByteSpan TLV-encoded form. |
| * Output format is seconds referenced from the CHIP epoch. |
| * |
| * This does not perform any sort of validation on the certificate structure |
| * other than parsing it. |
| * |
| * @param chipCert CHIP certificate in TLV-encoded form |
| * @param notBeforeChipEpochTime (out) certificate NotBefore time as seconds from the CHIP epoch |
| * @return CHIP_NO_ERROR if certificate parsing was successful, else an appropriate CHIP_ERROR |
| */ |
| CHIP_ERROR ExtractNotBeforeFromChipCert(const ByteSpan & chipCert, chip::System::Clock::Seconds32 & notBeforeChipEpochTime); |
| |
| /** |
| * Extract Subject Key Identifier from a chip certificate in ByteSpan TLV-encoded form. |
| * This does not perform any sort of validation on the certificate structure |
| * other than parsing it. |
| * |
| * Can return any error that can be returned from parsing the cert. |
| */ |
| CHIP_ERROR ExtractSKIDFromChipCert(const ByteSpan & chipCert, CertificateKeyId & skid); |
| |
| /** |
| * Extract Subject Distinguished Name (DN) from a chip certificate in ByteSpan TLV-encoded form. |
| * It is required that the certificate in the chipCert buffer stays valid while the `dn` output is used. |
| * |
| * Can return any error that can be returned from parsing the cert. |
| */ |
| CHIP_ERROR ExtractSubjectDNFromChipCert(const ByteSpan & chipCert, ChipDN & dn); |
| |
| /** |
| * Extract Subject Distinguished Name (DN) from a chip certificate in ByteSpan X509 DER-encoded form. |
| * It is required that the certificate in the chipCert buffer stays valid while the `dn` output is used. |
| * |
| * Can return any error that can be returned from converting and parsing the cert. |
| */ |
| CHIP_ERROR ExtractSubjectDNFromX509Cert(const ByteSpan & x509Cert, ChipDN & dn); |
| |
| /** |
| * Extracts the key identifier from a Network (Client) Identity in TLV-encoded form. |
| * Does NOT perform full validation of the identity certificate. |
| * |
| * @return CHIP_NO_ERROR on success, CHIP_ERROR_WRONG_CERT_TYPE if the certificate is |
| * not a Network (Client) Identity, or another CHIP_ERROR if parsing fails. |
| */ |
| CHIP_ERROR ExtractIdentifierFromChipNetworkIdentity(const ByteSpan & cert, MutableCertificateKeyId outKeyId); |
| |
| } // namespace Credentials |
| } // namespace chip |