Line data Source code
1 : /* 2 : * 3 : * Copyright (c) 2020-2022 Project CHIP Authors 4 : * Copyright (c) 2019 Google LLC. 5 : * Copyright (c) 2013-2017 Nest Labs, Inc. 6 : * All rights reserved. 7 : * 8 : * Licensed under the Apache License, Version 2.0 (the "License"); 9 : * you may not use this file except in compliance with the License. 10 : * You may obtain a copy of the License at 11 : * 12 : * http://www.apache.org/licenses/LICENSE-2.0 13 : * 14 : * Unless required by applicable law or agreed to in writing, software 15 : * distributed under the License is distributed on an "AS IS" BASIS, 16 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 : * See the License for the specific language governing permissions and 18 : * limitations under the License. 19 : */ 20 : 21 : /** 22 : * @file 23 : * This file defines data types and objects for modeling and 24 : * working with CHIP certificates. 25 : * 26 : */ 27 : 28 : #pragma once 29 : 30 : #include <cstdint> 31 : #include <string.h> 32 : 33 : #include "CHIPCert.h" 34 : #include "CertificateValidityPolicy.h" 35 : #include <lib/support/Variant.h> 36 : 37 : namespace chip { 38 : namespace Credentials { 39 : 40 : struct CurrentChipEpochTime : chip::System::Clock::Seconds32 41 : { 42 : template <typename... Args> 43 14 : CurrentChipEpochTime(Args &&... args) : chip::System::Clock::Seconds32(std::forward<Args>(args)...) 44 14 : {} 45 : }; 46 : 47 : struct LastKnownGoodChipEpochTime : chip::System::Clock::Seconds32 48 : { 49 : template <typename... Args> 50 0 : LastKnownGoodChipEpochTime(Args &&... args) : chip::System::Clock::Seconds32(std::forward<Args>(args)...) 51 0 : {} 52 : }; 53 : 54 : using EffectiveTime = Variant<CurrentChipEpochTime, LastKnownGoodChipEpochTime>; 55 : 56 : /** 57 : * @struct ValidationContext 58 : * 59 : * @brief 60 : * Context information used during certification validation. 61 : */ 62 : struct ValidationContext 63 : { 64 : EffectiveTime mEffectiveTime; /**< Current or last known good CHIP Epoch time. */ 65 : const ChipCertificateData * mTrustAnchor; /**< Pointer to the Trust Anchor Certificate data structure. 66 : This value is set during certificate validation process 67 : to indicate to the caller the trust anchor of the 68 : validated certificate. */ 69 : BitFlags<KeyUsageFlags> mRequiredKeyUsages; /**< Key usage extensions that should be present in the 70 : validated certificate. */ 71 : BitFlags<KeyPurposeFlags> mRequiredKeyPurposes; /**< Extended Key usage extensions that should be present 72 : in the validated certificate. */ 73 : CertType mRequiredCertType; /**< Required certificate type. */ 74 : 75 : CertificateValidityPolicy * mValidityPolicy = 76 : nullptr; /**< Optional application policy to apply for certificate validity period evaluation. */ 77 : 78 : void Reset(); 79 : 80 : template <typename T> 81 14 : void SetEffectiveTime(chip::System::Clock::Seconds32 chipTime) 82 : { 83 14 : mEffectiveTime.Set<T>(chipTime); 84 14 : } 85 : 86 : template <typename T> 87 14 : CHIP_ERROR SetEffectiveTimeFromUnixTime(chip::System::Clock::Seconds32 unixTime) 88 : { 89 : uint32_t chipTime; 90 14 : VerifyOrReturnError(UnixEpochToChipEpochTime(unixTime.count(), chipTime), CHIP_ERROR_INVALID_TIME); 91 14 : SetEffectiveTime<T>(chip::System::Clock::Seconds32(chipTime)); 92 14 : return CHIP_NO_ERROR; 93 : } 94 : 95 : template <typename T> 96 : CHIP_ERROR SetEffectiveTimeFromAsn1Time(const ASN1::ASN1UniversalTime & asn1Time) 97 : { 98 : uint32_t chipTime; 99 : ReturnErrorOnFailure(ASN1ToChipEpochTime(asn1Time, chipTime)); 100 : SetEffectiveTime<T>(chip::System::Clock::Seconds32(chipTime)); 101 : return CHIP_NO_ERROR; 102 : } 103 : }; 104 : 105 : /** 106 : * @class ChipCertificateSet 107 : * 108 : * @brief 109 : * Collection of CHIP certificate data providing methods for 110 : * certificate validation and signature verification. 111 : */ 112 : class DLL_EXPORT ChipCertificateSet 113 : { 114 : public: 115 : ChipCertificateSet(); 116 : ~ChipCertificateSet(); 117 : 118 : ChipCertificateSet & operator=(ChipCertificateSet && aOther) 119 : { 120 : mCerts = aOther.mCerts; 121 : aOther.mCerts = nullptr; 122 : mCertCount = aOther.mCertCount; 123 : mMaxCerts = aOther.mMaxCerts; 124 : mMemoryAllocInternal = aOther.mMemoryAllocInternal; 125 : 126 : return *this; 127 : } 128 : 129 : /** 130 : * @brief Initialize ChipCertificateSet. 131 : * This initialization method is used when all memory structures needed for operation are 132 : * allocated internally using chip::Platform::MemoryAlloc() and freed with chip::Platform::MemoryFree(). 133 : * 134 : * @param maxCertsArraySize Maximum number of CHIP certificates to be loaded to the set. 135 : * 136 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise 137 : **/ 138 : CHIP_ERROR Init(uint8_t maxCertsArraySize); 139 : 140 : /** 141 : * @brief Initialize ChipCertificateSet. 142 : * This initialization method is used when all memory structures needed for operation are 143 : * allocated externally and methods in this class don't need to deal with memory allocations. 144 : * 145 : * @param certsArray A pointer to the array of the ChipCertificateData structures. 146 : * @param certsArraySize Number of ChipCertificateData entries in the array. 147 : * 148 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise 149 : **/ 150 : CHIP_ERROR Init(ChipCertificateData * certsArray, uint8_t certsArraySize); 151 : 152 : /** 153 : * @brief Release resources allocated by this class. 154 : **/ 155 : void Release(); 156 : 157 : /** 158 : * @brief Clear certificate data loaded into this set. 159 : **/ 160 : void Clear(); 161 : 162 : /** 163 : * @brief Load CHIP certificate into set. 164 : * It is required that the CHIP certificate in the chipCert buffer stays valid while 165 : * the certificate data in the set is used. 166 : * In case of an error the certificate set is left in the same state as prior to this call. 167 : * 168 : * @param chipCert Buffer containing certificate encoded in CHIP format. 169 : * @param decodeFlags Certificate decoding option flags. 170 : * 171 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise 172 : **/ 173 : CHIP_ERROR LoadCert(const ByteSpan chipCert, BitFlags<CertDecodeFlags> decodeFlags); 174 : 175 : /** 176 : * @brief Load CHIP certificate into set. 177 : * It is required that the CHIP certificate in the reader's underlying buffer stays valid while 178 : * the certificate data in the set is used. 179 : * In case of an error the certificate set is left in the same state as prior to this call. 180 : * 181 : * @param reader A TLVReader positioned at the CHIP certificate TLV structure. 182 : * @param decodeFlags Certificate decoding option flags. 183 : * @param chipCert Buffer containing certificate encoded on CHIP format. It is required that this CHIP certificate 184 : * in chipCert ByteSpan stays valid while the certificate data in the set is used. 185 : * 186 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise 187 : **/ 188 : CHIP_ERROR LoadCert(chip::TLV::TLVReader & reader, BitFlags<CertDecodeFlags> decodeFlags, ByteSpan chipCert = ByteSpan()); 189 : 190 : CHIP_ERROR ReleaseLastCert(); 191 : 192 : /** 193 : * @brief Find certificate in the set. 194 : * 195 : * @param subjectKeyId Subject key identifier of the certificate to be found in the set. 196 : * 197 : * @return A pointer to the certificate data On success. Otherwise, NULL if no certificate found. 198 : **/ 199 : const ChipCertificateData * FindCert(const CertificateKeyId & subjectKeyId) const; 200 : 201 : /** 202 : * @return A pointer to the set of certificate data entries. 203 : **/ 204 1833 : const ChipCertificateData * GetCertSet() const { return mCerts; } 205 : 206 : /** 207 : * @return A pointer to the last certificate data in the set. Returns NULL if certificate set is empty. 208 : **/ 209 2380 : const ChipCertificateData * GetLastCert() const { return (mCertCount > 0) ? &mCerts[mCertCount - 1] : nullptr; } 210 : 211 : /** 212 : * @return Number of certificates loaded into the set. 213 : **/ 214 : uint8_t GetCertCount() const { return mCertCount; } 215 : 216 : /** 217 : * @brief Check whether certificate is in the set. 218 : * 219 : * @param cert Pointer to the ChipCertificateData structures. 220 : * 221 : * @return True if certificate is in the set, false otherwise. 222 : **/ 223 : bool IsCertInTheSet(const ChipCertificateData * cert) const; 224 : 225 : /** 226 : * @brief Validate CHIP certificate. 227 : * 228 : * @param cert Pointer to the CHIP certificate to be validated. The certificate is 229 : * required to be in this set, otherwise this function returns error. 230 : * @param context Certificate validation context. 231 : * 232 : * @return Returns a CHIP_ERROR on validation or other error, CHIP_NO_ERROR otherwise 233 : **/ 234 : CHIP_ERROR ValidateCert(const ChipCertificateData * cert, ValidationContext & context); 235 : 236 : /** 237 : * @brief Find and validate CHIP certificate. 238 : * 239 : * @param[in] subjectDN Subject distinguished name to use as certificate search parameter. 240 : * @param[in] subjectKeyId Subject key identifier to use as certificate search parameter. 241 : * @param[in] context Certificate validation context. 242 : * @param[out] certData A slot to write a pointer to the CHIP certificate data that matches search criteria. 243 : * 244 : * @return Returns a CHIP_ERROR on validation or other error, CHIP_NO_ERROR otherwise 245 : **/ 246 : CHIP_ERROR FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId, ValidationContext & context, 247 : const ChipCertificateData ** certData); 248 : 249 : // Deprecated, use the equivalent free function VerifyCertSignature() 250 : static CHIP_ERROR VerifySignature(const ChipCertificateData * cert, const ChipCertificateData * caCert); 251 : 252 : private: 253 : ChipCertificateData * mCerts; /**< Pointer to an array of certificate data. */ 254 : uint8_t mCertCount; /**< Number of certificates in mCerts 255 : array. We maintain the invariant that all 256 : the slots at indices less than 257 : mCertCount have been constructed and slots 258 : at indices >= mCertCount have either never 259 : had their constructor called, or have had 260 : their destructor called since then. */ 261 : uint8_t mMaxCerts; /**< Length of mCerts array. */ 262 : bool mMemoryAllocInternal; /**< Indicates whether temporary memory buffers are allocated internally. */ 263 : 264 : /** 265 : * @brief Find and validate CHIP certificate. 266 : * 267 : * @param[in] subjectDN Subject distinguished name to use as certificate search parameter. 268 : * @param[in] subjectKeyId Subject key identifier to use as certificate search parameter. 269 : * @param[in] context Certificate validation context. 270 : * @param[in] depth Depth of the current certificate in the certificate validation chain. 271 : * @param[out] certData A slot to write a pointer to the CHIP certificate data that matches search criteria. 272 : * 273 : * @return Returns a CHIP_ERROR on validation or other error, CHIP_NO_ERROR otherwise 274 : **/ 275 : CHIP_ERROR FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId, ValidationContext & context, 276 : uint8_t depth, const ChipCertificateData ** certData); 277 : 278 : /** 279 : * @brief Validate CHIP certificate. 280 : * 281 : * @param cert Pointer to the CHIP certificate to be validated. 282 : * @param context Certificate validation context. 283 : * @param depth Depth of the current certificate in the certificate validation chain. 284 : * 285 : * @return Returns a CHIP_ERROR on validation or other error, CHIP_NO_ERROR otherwise 286 : **/ 287 : CHIP_ERROR ValidateCert(const ChipCertificateData * cert, ValidationContext & context, uint8_t depth); 288 : }; 289 : 290 : } // namespace Credentials 291 : } // namespace chip