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 2049 : 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 2668 : 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
|