blob: d08c9c617903680aa4db378f7d5f3f20505f9b9c [file] [log] [blame]
/*
*
* Copyright (c) 2020-2021 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 <string.h>
#include <asn1/ASN1.h>
#include <core/CHIPConfig.h>
#include <core/CHIPTLV.h>
#include <crypto/CHIPCryptoPAL.h>
#include <support/BitFlags.h>
#include <support/DLLUtil.h>
namespace chip {
namespace Credentials {
/** Data Element Tags for the CHIP Certificate
*/
enum
{
// ---- Top-level Protocol-Specific Tags ----
kTag_ChipCertificate = 1, /**< [ structure ] A CHIP certificate. */
kTag_ChipCertificateArray = 2, /**< [ array ] An array of CHIP certificates. */
// ---- 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_ECDSASignature = 10, /**< [ structure ] The ECDSA signature for the certificate. */
// ---- Tags identifying certificate extensions (tag numbers 128 - 255) ----
kCertificateExtensionTagsStart = 128,
kTag_BasicConstraints = 128, /**< [ structure ] Identifies whether the subject of the certificate is a CA. */
kTag_KeyUsage = 129, /**< [ structure ] Purpose of the key contained in the certificate. */
kTag_ExtendedKeyUsage = 130, /**< [ structure ] Purposes for which the certified public key may be used. */
kTag_SubjectKeyIdentifier = 131, /**< [ structure ] Information about the certificate's public key. */
kTag_AuthorityKeyIdentifier = 132, /**< [ structure ] Information about the public key used to sign the certificate. */
kCertificateExtensionTagsEnd = 255,
// ---- Context-specific Tags for ECDSASignature Structure ----
kTag_ECDSASignature_r = 1, /**< [ byte string ] ECDSA r value, in ASN.1 integer encoding. */
kTag_ECDSASignature_s = 2, /**< [ byte string ] ECDSA s value, in ASN.1 integer encoding. */
// ---- Context-specific Tags for AuthorityKeyIdentifier Structure ----
kTag_AuthorityKeyIdentifier_Critical = 1, /**< [ boolean ] True if the AuthorityKeyIdentifier extension is critical.
Otherwise absent. */
kTag_AuthorityKeyIdentifier_KeyIdentifier = 2, /**< [ byte string ] Unique identifier of the issuer's public key,
per RFC5280. */
// ---- Context-specific Tags for SubjectKeyIdentifier Structure ----
kTag_SubjectKeyIdentifier_Critical = 1, /**< [ boolean ] True if the SubjectKeyIdentifier extension is critical.
Otherwise absent. */
kTag_SubjectKeyIdentifier_KeyIdentifier = 2, /**< [ byte string ] Unique identifier for certificate's public key,
per RFC5280. */
// ---- Context-specific Tags for KeyUsage Structure ----
kTag_KeyUsage_Critical = 1, /**< [ boolean ] True if the KeyUsage extension is critical. Otherwise absent. */
kTag_KeyUsage_KeyUsage = 2, /**< [ unsigned int ] Integer containing key usage bits, per to RFC5280. */
// ---- Context-specific Tags for BasicConstraints Structure ----
kTag_BasicConstraints_Critical = 1, /**< [ boolean ] True if the BasicConstraints extension is critical.
Otherwise absent. */
kTag_BasicConstraints_IsCA = 2, /**< [ boolean ] True if the certificate can be used to verify certificate
signatures. */
kTag_BasicConstraints_PathLenConstraint = 3, /**< [ unsigned int ] Maximum number of subordinate intermediate certificates. */
// ---- Context-specific Tags for ExtendedKeyUsage Structure ----
kTag_ExtendedKeyUsage_Critical = 1, /**< [ boolean ] True if the ExtendedKeyUsage extension is critical. Otherwise absent. */
kTag_ExtendedKeyUsage_KeyPurposes = 2, /**< [ array ] Array of enumerated values giving the purposes for which the public key
can be used. */
};
/** 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. Developers can also extend the certificate type value
* range with application-specific types that described custom certificates or certificates
* with unique security properties.
*
* 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
{
kCertType_NotSpecified = 0x00, /**< The certificate's type has not been specified. */
kCertType_CA = 0x01, /**< A CHIP CA certificate. */
kCertType_Node = 0x02, /**< A CHIP node certificate. */
kCertType_FirmwareSigning = 0x03, /**< A CHIP firmware signing certificate. */
kCertType_AppDefinedBase = 0x7F, /**< Application-specific certificate types should have values >= this value. */
};
/** 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 extention is present in the certificate. */
kExtPresent_ExtendedKeyUsage = 0x0004, /**< Extended key usage extention is present in the certificate. */
kExtPresent_SubjectKeyId = 0x0008, /**< Subject key identifier extention is present in the certificate. */
kExtPresent_AuthKeyId = 0x0010, /**< Authority key identifier extention is present in the certificate. */
kPathLenConstraintPresent = 0x0020, /**< Path length constraint is present in the certificate. */
kIsCA = 0x0040, /**< Indicates that certificate is a CA certificate. */
kIsTrustAnchor = 0x0080, /**< Indicates that certificate is a trust anchor. */
kTBSHashPresent = 0x0100, /**< 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. */
};
/** CHIP Certificate Validate Flags
*
* Contains information specifying how a certificate should be validated.
*/
enum class CertValidateFlags : uint8_t
{
kIgnoreNotBefore = 0x01, /**< Indicate that a Not Before field should be ignored when doing certificate validation. This
flag applies to all certificates in the validation chain. */
kIgnoreNotAfter = 0x02, /**< Indicate that a Not After field should be ignored when doing certificate validation. This
flag applies to all certificates in the validation chain. */
};
enum
{
kNullCertTime = 0
};
/**
* @struct ChipDN
*
* @brief
* A data structure representing a Distinguished Name (DN) in a CHIP certificate.
*/
struct ChipDN
{
union
{
uint64_t mChipId; /**< CHIP specific DN attribute value. */
struct
{
const uint8_t * mValue; /**< Pointer to the DN attribute value. */
uint32_t mLen; /**< DN attribute length. */
} mString; /**< DN attribute structure when encoded as a string. */
} mAttrValue; /**< DN attribute value union: string or unsigned integer. */
chip::ASN1::OID mAttrOID; /**< DN attribute CHIP OID. */
bool IsEqual(const ChipDN & other) const;
bool IsEmpty() const { return mAttrOID == chip::ASN1::kOID_NotSpecified; }
void Clear() { mAttrOID = chip::ASN1::kOID_NotSpecified; }
};
/**
* @struct CertificateKeyId
*
* @brief
* A data structure representing a certificate key identifier.
*/
struct CertificateKeyId
{
const uint8_t * mId; /**< Pointer to the key identifier. Encoded as Octet String and represented as the ASN.1 DER Integer (X.690
standard). */
uint8_t mLen; /**< Key identifier length. */
bool IsEqual(const CertificateKeyId & other) const;
bool IsEmpty() const { return mId == nullptr; }
void Clear() { mId = nullptr; }
};
/**
* @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();
ChipDN mSubjectDN; /**< Certificate Subject DN. */
ChipDN mIssuerDN; /**< Certificate Issuer DN. */
CertificateKeyId mSubjectKeyId; /**< Certificate Subject public key identifier. */
CertificateKeyId mAuthKeyId; /**< Certificate Authority public key identifier. */
uint16_t mNotBeforeDate; /**< Certificate validity: Not Before field. */
uint16_t mNotAfterDate; /**< Certificate validity: Not After field. */
const uint8_t * mPublicKey; /**< Pointer to the certificate public key. */
uint8_t mPublicKeyLen; /**< Certificate public key length. */
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<uint16_t, CertFlags> mCertFlags; /**< Certificate data flags. */
BitFlags<uint16_t, KeyUsageFlags> mKeyUsageFlags; /**< Certificate key usage extensions flags. */
BitFlags<uint8_t, KeyPurposeFlags> mKeyPurposeFlags; /**< Certificate extended key usage extensions flags. */
uint8_t mPathLenConstraint; /**< Basic constraint: path length. */
uint8_t mCertType; /**< Certificate type. */
struct
{
const uint8_t * R; /**< Pointer to the R element of the signature, encoded as ASN.1 DER Integer. */
uint8_t RLen; /**< Length of R. */
const uint8_t * S; /**< Pointer to the S element of the signature, encoded as ASN.1 DER Integer. */
uint8_t SLen; /**< Length of R. */
} mSignature; /**< Certificate signature structure. */
uint8_t mTBSHash[chip::Crypto::kSHA256_Hash_Length]; /**< Certificate TBS hash. */
};
/**
* @struct ValidationContext
*
* @brief
* Context information used during certification validation.
*/
struct ValidationContext
{
uint32_t mEffectiveTime; /**< Current time in the CHIP Packed Certificate Time format. */
const ChipCertificateData * mTrustAnchor; /**< Pointer to the Trust Anchor Certificate data structure. */
const ChipCertificateData * mSigningCert; /**< Pointer to the Signing Certificate data structure. */
BitFlags<uint16_t, KeyUsageFlags> mRequiredKeyUsages; /**< Key usage extensions that should be present in the
validated certificate. */
BitFlags<uint8_t, KeyPurposeFlags> mRequiredKeyPurposes; /**< Extended Key usage extensions that should be present
in the validated certificate. */
BitFlags<uint8_t, CertValidateFlags> mValidateFlags; /**< Certificate validation flags, specifying how a certificate
should be validated. */
uint8_t mRequiredCertType; /**< Required certificate type. */
void Reset();
};
/**
* @class ChipCertificateSet
*
* @brief
* Collection of CHIP certificate data providing methods for
* certificate validation and signature verification.
*/
class DLL_EXPORT ChipCertificateSet
{
public:
ChipCertificateSet();
~ChipCertificateSet();
/**
* @brief Initialize ChipCertificateSet.
* This initialization method is used when all memory structures needed for operation are
* allocated internally using chip::Platform::MemoryAlloc() and freed with chip::Platform::MemoryFree().
*
* @param maxCertsArraySize Maximum number of CHIP certificates to be loaded to the set.
* @param decodeBufSize Size of the buffer that should be allocated to perform CHIP certificate decoding.
*
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR Init(uint8_t maxCertsArraySize, uint16_t decodeBufSize);
/**
* @brief Initialize ChipCertificateSet.
* This initialization method is used when all memory structures needed for operation are
* allocated externally and methods in this class don't need to deal with memory allocations.
*
* @param certsArray A pointer to the array of the ChipCertificateData structures.
* @param certsArraySize Number of ChipCertificateData entries in the array.
* @param decodeBuf Buffer to use for temporary storage of intermediate processing results.
* @param decodeBufSize Size of decoding buffer.
*
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR Init(ChipCertificateData * certsArray, uint8_t certsArraySize, uint8_t * decodeBuf, uint16_t decodeBufSize);
/**
* @brief Release resources allocated by this class.
**/
void Release();
/**
* @brief Clear certificate data loaded into this set.
**/
void Clear();
/**
* @brief Load CHIP certificate into set.
* It is required that the CHIP certificate in the chipCert buffer stays valid while
* the certificate data in the set is used.
* In case of an error the certificate set is left in the same state as prior to this call.
*
* @param chipCert Buffer containing certificate encoded in CHIP format.
* @param chipCertLen The length of the certificate buffer.
* @param decodeFlags Certificate decoding option flags.
*
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR LoadCert(const uint8_t * chipCert, uint32_t chipCertLen, BitFlags<uint8_t, CertDecodeFlags> decodeFlags);
/**
* @brief Load CHIP certificate into set.
* It is required that the CHIP certificate in the reader's underlying buffer stays valid while
* the certificate data in the set is used.
* In case of an error the certificate set is left in the same state as prior to this call.
*
* @param reader A TLVReader positioned at the CHIP certificate TLV structure.
* @param decodeFlags Certificate decoding option flags.
*
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR LoadCert(chip::TLV::TLVReader & reader, BitFlags<uint8_t, CertDecodeFlags> decodeFlags);
/**
* @brief Load CHIP certificates into set.
* It is required that the CHIP certificates in the chipCerts buffer stays valid while
* the certificates data in the set is used.
* In case of an error the certificate set is left in the same state as prior to this call.
*
* @param chipCerts Buffer containing array of certificates or a single certificate encoded in CHIP TLV form.
* @param chipCertsLen The length of the certificates buffer.
* @param decodeFlags Certificate decoding option flags.
*
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR LoadCerts(const uint8_t * chipCerts, uint32_t chipCertsLen, BitFlags<uint8_t, CertDecodeFlags> decodeFlags);
/**
* @brief Load CHIP certificates into set.
* It is required that the CHIP certificates in the reader's underlying buffer stays valid while
* the certificates data in the set is used.
* In case of an error the certificate set is left in the same state as prior to this call.
*
* @param reader A TLVReader positioned at the CHIP certificates TLV array
* or TLV structure for a single certificate.
* @param decodeFlags Certificate decoding option flags.
*
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR LoadCerts(chip::TLV::TLVReader & reader, BitFlags<uint8_t, CertDecodeFlags> decodeFlags);
/**
* @brief Add trusted anchor key to the certificate set.
* It is required that the public key and public key Id in the pubKey and pubKeyId buffers
* stay valid while the certificate set is used.
* In case of an error the certificate set is left in the same state as prior to this call.
*
* @param caId CA certificate CHIP identifier.
* @param curveOID Elliptic curve CHIP OID.
* @param pubKey Trusted public key.
* @param pubKeyLen The length of the trusted public key.
* @param pubKeyId Trusted public key identifier.
* @param pubKeyIdLen The length of the trusted public key identifier.
*
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR AddTrustedKey(uint64_t caId, chip::ASN1::OID curveOID, const uint8_t * pubKey, uint8_t pubKeyLen,
const uint8_t * pubKeyId, uint8_t pubKeyIdLen);
/**
* @brief Find certificate in the set.
*
* @param subjectKeyId Subject key identifier of the certificate to be found in the set.
*
* @return A pointer to the certificate data On success. Otherwise, NULL if no certificate found.
**/
const ChipCertificateData * FindCert(const CertificateKeyId & subjectKeyId) const;
/**
* @return A pointer to the set of certificate data entries.
**/
const ChipCertificateData * GetCertSet() const { return mCerts; }
/**
* @return A pointer to the last certificate data in the set. Returns NULL if certificate set is empty.
**/
const ChipCertificateData * GetLastCert() const { return (mCertCount > 0) ? &mCerts[mCertCount - 1] : nullptr; }
/**
* @return Number of certificates loaded into the set.
**/
uint8_t GetCertCount() const { return mCertCount; }
/**
* @brief Check whether certificate is in the set.
*
* @param cert Pointer to the ChipCertificateData structures.
*
* @return True if certificate is in the set, false otherwise.
**/
bool IsCertInTheSet(const ChipCertificateData * cert) const;
/**
* @brief Validate CHIP certificate.
*
* @param cert Pointer to the CHIP certificiate to be validated. The certificate is
* required to be in this set, otherwise this function returns error.
* @param context Certificate validation context.
*
* @return Returns a CHIP_ERROR on validation or other error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR ValidateCert(const ChipCertificateData * cert, ValidationContext & context);
/**
* @brief Find and validate CHIP certificate.
*
* @param subjectDN Subject distinguished name to use as certificate search parameter.
* @param subjectKeyId Subject key identifier to use as certificate search parameter.
* @param context Certificate validation context.
* @param cert A pointer to the valid CHIP certificate that matches search criteria.
*
* @return Returns a CHIP_ERROR on validation or other error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId, ValidationContext & context,
ChipCertificateData *& cert);
/**
* @brief Verify CHIP certificate signature.
*
* @param cert Pointer to the CHIP certificiate which signature should be validated.
* @param caCert Pointer to the CA certificate of the verified certificate.
*
* @return Returns a CHIP_ERROR on validation or other error, CHIP_NO_ERROR otherwise
**/
static CHIP_ERROR VerifySignature(const ChipCertificateData * cert, const ChipCertificateData * caCert);
private:
ChipCertificateData * mCerts; /**< Pointer to an array of certificate data. */
uint8_t mCertCount; /**< Number of certificates in mCerts array. */
uint8_t mMaxCerts; /**< Length of mCerts array. */
uint8_t * mDecodeBuf; /**< Certificate decode buffer. */
uint16_t mDecodeBufSize; /**< Certificate decode buffer size. */
bool mMemoryAllocInternal; /**< Indicates whether temporary memory buffers are allocated internally. */
/**
* @brief Find and validate CHIP certificate.
*
* @param subjectDN Subject distinguished name to use as certificate search parameter.
* @param subjectKeyId Subject key identifier to use as certificate search parameter.
* @param context Certificate validation context.
* @param validateFlags Certificate validation flags.
* @param depth Depth of the current certificate in the certificate validation chain.
* @param cert A pointer to the valid CHIP certificate that matches search criteria.
*
* @return Returns a CHIP_ERROR on validation or other error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId, ValidationContext & context,
BitFlags<uint8_t, CertValidateFlags> validateFlags, uint8_t depth, ChipCertificateData *& cert);
/**
* @brief Validate CHIP certificate.
*
* @param cert Pointer to the CHIP certificiate to be validated.
* @param context Certificate validation context.
* @param validateFlags Certificate validation flags.
* @param depth Depth of the current certificate in the certificate validation chain.
*
* @return Returns a CHIP_ERROR on validation or other error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR ValidateCert(const ChipCertificateData * cert, ValidationContext & context,
BitFlags<uint8_t, CertValidateFlags> validateFlags, uint8_t depth);
};
/**
* @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 chipCertLen The length of the 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 uint8_t * chipCert, uint32_t chipCertLen, ChipCertificateData & certData);
/**
* @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);
/**
* @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 Buffer containing X.509 DER encoded certificate.
* @param x509CertLen The length of the X.509 DER encoded certificate.
* @param chipCertBuf Buffer to store converted certificate in CHIP format.
* @param chipCertBufSize The size of the buffer to store converted certificate.
* @param chipCertLen The length of the converted certificate.
*
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR ConvertX509CertToChipCert(const uint8_t * x509Cert, uint32_t x509CertLen, uint8_t * chipCertBuf,
uint32_t chipCertBufSize, uint32_t & chipCertLen);
/**
* @brief Convert CHIP certificate to the standard X.509 DER encoded certificate.
*
* @param chipCert Buffer containing CHIP certificate.
* @param chipCertLen The length of the CHIP certificate.
* @param x509CertBuf Buffer to store converted certificate in X.509 DER format.
* @param x509CertBufSize The size of the buffer to store converted certificate.
* @param x509CertLen The length of the converted certificate.
*
* @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
**/
CHIP_ERROR ConvertChipCertToX509Cert(const uint8_t * chipCert, uint32_t chipCertLen, uint8_t * x509CertBuf,
uint32_t x509CertBufSize, uint32_t & x509CertLen);
/**
* Determine type of a CHIP certificate.
*
* This function performs an assessment of a certificate's type and sets cert.mCertType value
* based on the structure of its subject DN and the extensions present. Applications are free
* to override this assessment by setting cert.mCertType to another value, including an
* application-defined one.
*
* In general, applications will only trust a peer's certificate if it chains to a trusted
* root certificate. However, the type assigned to a certificate can influence the *nature*
* of this trust, e.g. to allow or disallow access to certain features. Because of this,
* changes to this algorithm can have VERY SIGNIFICANT and POTENTIALLY CATASTROPHIC effects
* on overall system security, and should not be made without a thorough understanding of
* the implications.
**/
CHIP_ERROR DetermineCertType(ChipCertificateData & cert);
/**
* @brief
* Convert a certificate date/time (in the form of an ASN.1 universal time structure) into a packed
* certificate date/time.
*
* @details
* Packed certificate date/times provide a compact representation for the time values within a certificate
* (notBefore and notAfter) that does not require full calendar math to interpret.
*
* A packed certificate date/time contains the fields of a calendar date/time--i.e. year, month, day, hour,
* minute, second--packed into an unsigned integer. The bit representation is organized such that
* ordinal comparisons of packed date/time values correspond to the natural ordering of the corresponding
* times. To reduce their size, packed certificate date/times are limited to representing times that are on
* or after 2020/01/01 00:00:00. When housed within a 32-bit unsigned integer, packed certificate
* date/times can represent times up to the year 2153.
*
* @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 time The calendar date/time to be converted.
* @param packedTime A reference to an integer that will receive packed date/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 packed certificate time value.
**/
CHIP_ERROR PackCertTime(const chip::ASN1::ASN1UniversalTime & time, uint32_t & packedTime);
/**
* @brief
* Unpack a packed certificate date/time into an ASN.1 universal time structure.
*
* @param packedTime A packed certificate time to be unpacked.
* @param time A reference to an ASN1UniversalTime structure to receive the unpacked date/time.
*
* @retval #CHIP_NO_ERROR If the input time was successfully unpacked.
*/
CHIP_ERROR UnpackCertTime(uint32_t packedTime, chip::ASN1::ASN1UniversalTime & time);
/**
* @brief
* Convert a packed certificate date/time to a packed certificate date.
*
* @details
* A packed certificate date contains the fields of a calendar date--year, month, day--packed into an
* unsigned integer. The bits are organized such that ordinal comparisons of packed date values
* correspond to the natural ordering of the corresponding dates. To reduce their size, packed
* certificate dates are limited to representing dates on or after 2020/01/01. When housed within
* a 16-bit unsigned integer, packed certificate dates can represent dates up to the year 2196.
*
* @param packedTime The packed certificate date/time to be converted.
*
* @return A corresponding packed certificate date.
**/
uint16_t PackedCertTimeToDate(uint32_t packedTime);
/**
* @brief
* Convert a packed certificate date to a corresponding packed certificate date/time, where
* the time portion of the value is set to 00:00:00.
*
* @param packedDate The packed certificate date to be converted.
*
* @return A corresponding packed certificate date/time.
**/
uint32_t PackedCertDateToTime(uint16_t packedDate);
/**
* @brief
* Convert the number of seconds since 1970-01-01 00:00:00 UTC to a packed certificate date/time.
*
* @param secondsSinceEpoch Number of seconds since 1970-01-01 00:00:00 UTC.
* Note: this value is compatible with *positive* values
* of the POSIX time_t value, up to the year 2105.
*
* @return A corresponding packed certificate date/time.
**/
uint32_t SecondsSinceEpochToPackedCertTime(uint32_t secondsSinceEpoch);
/**
* @return True if the OID represents a CHIP-defined X.509 distinguished named attribute.
**/
inline bool IsChipX509Attr(chip::ASN1::OID oid)
{
return (oid == chip::ASN1::kOID_AttributeType_ChipNodeId || oid == chip::ASN1::kOID_AttributeType_ChipCAId ||
oid == chip::ASN1::kOID_AttributeType_ChipSoftwarePublisherId || oid == chip::ASN1::kOID_AttributeType_ChipFabricId);
}
/**
* @return True if the OID represents a CHIP-defined X.509 distinguished named attribute
* that contains a 64-bit CHIP id.
**/
inline bool IsChipIdX509Attr(chip::ASN1::OID oid)
{
return (oid == chip::ASN1::kOID_AttributeType_ChipNodeId || oid == chip::ASN1::kOID_AttributeType_ChipCAId ||
oid == chip::ASN1::kOID_AttributeType_ChipSoftwarePublisherId);
}
} // namespace Credentials
} // namespace chip