| /* |
| * |
| * 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 "CHIPCert.h" |
| #include "CertificateValidityPolicy.h" |
| #include <lib/support/Variant.h> |
| |
| namespace chip { |
| namespace Credentials { |
| |
| struct CurrentChipEpochTime : chip::System::Clock::Seconds32 |
| { |
| template <typename... Args> |
| CurrentChipEpochTime(Args &&... args) : chip::System::Clock::Seconds32(std::forward<Args>(args)...) |
| {} |
| }; |
| |
| struct LastKnownGoodChipEpochTime : chip::System::Clock::Seconds32 |
| { |
| template <typename... Args> |
| LastKnownGoodChipEpochTime(Args &&... args) : chip::System::Clock::Seconds32(std::forward<Args>(args)...) |
| {} |
| }; |
| |
| using EffectiveTime = Variant<CurrentChipEpochTime, LastKnownGoodChipEpochTime>; |
| |
| /** |
| * @struct ValidationContext |
| * |
| * @brief |
| * Context information used during certification validation. |
| */ |
| struct ValidationContext |
| { |
| EffectiveTime mEffectiveTime; /**< Current or last known good CHIP Epoch time. */ |
| const ChipCertificateData * mTrustAnchor; /**< Pointer to the Trust Anchor Certificate data structure. |
| This value is set during certificate validation process |
| to indicate to the caller the trust anchor of the |
| validated certificate. */ |
| BitFlags<KeyUsageFlags> mRequiredKeyUsages; /**< Key usage extensions that should be present in the |
| validated certificate. */ |
| BitFlags<KeyPurposeFlags> mRequiredKeyPurposes; /**< Extended Key usage extensions that should be present |
| in the validated certificate. */ |
| uint8_t mRequiredCertType; /**< Required certificate type. */ |
| |
| CertificateValidityPolicy * mValidityPolicy = |
| nullptr; /**< Optional application policy to apply for certificate validity period evaluation. */ |
| |
| void Reset(); |
| |
| template <typename T> |
| void SetEffectiveTime(chip::System::Clock::Seconds32 chipTime) |
| { |
| mEffectiveTime.Set<T>(chipTime); |
| } |
| |
| template <typename T> |
| CHIP_ERROR SetEffectiveTimeFromUnixTime(chip::System::Clock::Seconds32 unixTime) |
| { |
| uint32_t chipTime; |
| VerifyOrReturnError(UnixEpochToChipEpochTime(unixTime.count(), chipTime), CHIP_ERROR_INVALID_TIME); |
| SetEffectiveTime<T>(chip::System::Clock::Seconds32(chipTime)); |
| return CHIP_NO_ERROR; |
| } |
| |
| template <typename T> |
| CHIP_ERROR SetEffectiveTimeFromAsn1Time(const ASN1::ASN1UniversalTime & asn1Time) |
| { |
| uint32_t chipTime; |
| ReturnErrorOnFailure(ASN1ToChipEpochTime(asn1Time, chipTime)); |
| SetEffectiveTime<T>(chip::System::Clock::Seconds32(chipTime)); |
| return CHIP_NO_ERROR; |
| } |
| }; |
| |
| /** |
| * @class ChipCertificateSet |
| * |
| * @brief |
| * Collection of CHIP certificate data providing methods for |
| * certificate validation and signature verification. |
| */ |
| class DLL_EXPORT ChipCertificateSet |
| { |
| public: |
| ChipCertificateSet(); |
| ~ChipCertificateSet(); |
| |
| ChipCertificateSet & operator=(ChipCertificateSet && aOther) |
| { |
| mCerts = aOther.mCerts; |
| aOther.mCerts = nullptr; |
| mCertCount = aOther.mCertCount; |
| mMaxCerts = aOther.mMaxCerts; |
| mMemoryAllocInternal = aOther.mMemoryAllocInternal; |
| |
| return *this; |
| } |
| |
| /** |
| * @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. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR Init(uint8_t maxCertsArraySize); |
| |
| /** |
| * @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. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR Init(ChipCertificateData * certsArray, uint8_t certsArraySize); |
| |
| /** |
| * @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 decodeFlags Certificate decoding option flags. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR LoadCert(const ByteSpan chipCert, BitFlags<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. |
| * @param chipCert Buffer containing certificate encoded on CHIP format. It is required that this CHIP certificate |
| * in chipCert ByteSpan stays valid while the certificate data in the set is used. |
| * |
| * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise |
| **/ |
| CHIP_ERROR LoadCert(chip::TLV::TLVReader & reader, BitFlags<CertDecodeFlags> decodeFlags, ByteSpan chipCert = ByteSpan()); |
| |
| CHIP_ERROR ReleaseLastCert(); |
| |
| /** |
| * @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 certificate 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[in] subjectDN Subject distinguished name to use as certificate search parameter. |
| * @param[in] subjectKeyId Subject key identifier to use as certificate search parameter. |
| * @param[in] context Certificate validation context. |
| * @param[out] certData A slot to write a pointer to the CHIP certificate data 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, |
| const ChipCertificateData ** certData); |
| |
| /** |
| * @brief Verify CHIP certificate signature. |
| * |
| * @param cert Pointer to the CHIP certificate 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. We maintain the invariant that all |
| the slots at indices less than |
| mCertCount have been constructed and slots |
| at indices >= mCertCount have either never |
| had their constructor called, or have had |
| their destructor called since then. */ |
| uint8_t mMaxCerts; /**< Length of mCerts array. */ |
| bool mMemoryAllocInternal; /**< Indicates whether temporary memory buffers are allocated internally. */ |
| |
| /** |
| * @brief Find and validate CHIP certificate. |
| * |
| * @param[in] subjectDN Subject distinguished name to use as certificate search parameter. |
| * @param[in] subjectKeyId Subject key identifier to use as certificate search parameter. |
| * @param[in] context Certificate validation context. |
| * @param[in] depth Depth of the current certificate in the certificate validation chain. |
| * @param[out] certData A slot to write a pointer to the CHIP certificate data 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, |
| uint8_t depth, const ChipCertificateData ** certData); |
| |
| /** |
| * @brief Validate CHIP certificate. |
| * |
| * @param cert Pointer to the CHIP certificate to be validated. |
| * @param context Certificate validation context. |
| * @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, uint8_t depth); |
| }; |
| |
| } // namespace Credentials |
| } // namespace chip |