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 <crypto/CHIPCryptoPAL.h>
34 : #include <lib/asn1/ASN1.h>
35 : #include <lib/core/CASEAuthTag.h>
36 : #include <lib/core/CHIPConfig.h>
37 : #include <lib/core/DataModelTypes.h>
38 : #include <lib/core/PeerId.h>
39 : #include <lib/core/TLV.h>
40 : #include <lib/support/BitFlags.h>
41 : #include <lib/support/DLLUtil.h>
42 : #include <lib/support/Span.h>
43 : #include <system/SystemClock.h>
44 :
45 : namespace chip {
46 : namespace Credentials {
47 :
48 : static constexpr uint32_t kKeyIdentifierLength = static_cast<uint32_t>(Crypto::kSubjectKeyIdentifierLength);
49 : static constexpr uint32_t kChip32bitAttrUTF8Length = 8;
50 : static constexpr uint32_t kChip64bitAttrUTF8Length = 16;
51 : static constexpr uint16_t kX509NoWellDefinedExpirationDateYear = 9999;
52 :
53 : // As per specifications (6.4.5. Node Operational Credentials Certificates)
54 : static constexpr uint32_t kMaxCHIPCertLength = 400;
55 : static constexpr uint32_t kMaxDERCertLength = 600;
56 :
57 : // As per spec section 11.24 (Wi-Fi Authentication with Per-Device Credentials)
58 : inline constexpr uint32_t kMaxCHIPCompactNetworkIdentityLength = 137;
59 :
60 : // Length of a ASN.1 DER encoded ECPrivateKey structure (RFC 5915) for a P256 key pair.
61 : inline constexpr uint32_t kP256ECPrivateKeyDERLength = 121;
62 :
63 : /** Data Element Tags for the CHIP Certificate
64 : */
65 : enum
66 : {
67 : // ---- Context-specific Tags for ChipCertificate Structure ----
68 : kTag_SerialNumber = 1, /**< [ byte string ] Certificate serial number, in BER integer encoding. */
69 : kTag_SignatureAlgorithm = 2, /**< [ unsigned int ] Enumerated value identifying the certificate signature algorithm. */
70 : kTag_Issuer = 3, /**< [ list ] The issuer distinguished name of the certificate. */
71 : kTag_NotBefore = 4, /**< [ unsigned int ] Certificate validity period start (certificate date format). */
72 : kTag_NotAfter = 5, /**< [ unsigned int ] Certificate validity period end (certificate date format). */
73 : kTag_Subject = 6, /**< [ list ] The subject distinguished name of the certificate. */
74 : kTag_PublicKeyAlgorithm = 7, /**< [ unsigned int ] Identifies the algorithm with which the public key can be used. */
75 : kTag_EllipticCurveIdentifier = 8, /**< [ unsigned int ] For EC certs, identifies the elliptic curve used. */
76 : kTag_EllipticCurvePublicKey = 9, /**< [ byte string ] The elliptic curve public key, in X9.62 encoded format. */
77 : kTag_Extensions = 10, /**< [ list ] Certificate extensions. */
78 : kTag_ECDSASignature = 11, /**< [ byte string ] The ECDSA signature for the certificate. */
79 :
80 : // ---- Context-specific Tags for certificate extensions ----
81 : kTag_BasicConstraints = 1, /**< [ structure ] Identifies whether the subject of the certificate is a CA. */
82 : kTag_KeyUsage = 2, /**< [ unsigned int ] Bits identifying key usage, per RFC5280. */
83 : kTag_ExtendedKeyUsage = 3, /**< [ array ] Enumerated values giving the purposes for which the public key can be used. */
84 : kTag_SubjectKeyIdentifier = 4, /**< [ byte string ] Identifier of the certificate's public key. */
85 : kTag_AuthorityKeyIdentifier = 5, /**< [ byte string ] Identifier of the public key used to sign the certificate. */
86 : kTag_FutureExtension = 6, /**< [ byte string ] Arbitrary extension. DER encoded SEQUENCE as in X.509 form. */
87 :
88 : // ---- Context-specific Tags for BasicConstraints Structure ----
89 : kTag_BasicConstraints_IsCA = 1, /**< [ boolean ] True if the certificate can be used to verify certificate
90 : signatures. */
91 : kTag_BasicConstraints_PathLenConstraint = 2, /**< [ unsigned int ] Maximum number of subordinate intermediate certificates. */
92 : };
93 :
94 : /** Identifies the purpose or application of certificate
95 : *
96 : * A certificate type is a label that describes a certificate's purpose or application.
97 : * Certificate types are not carried as attributes of the corresponding certificates, but
98 : * rather are derived from the certificate's structure and/or the context in which it is used.
99 : * The certificate type enumeration includes a set of pre-defined values describing commonly
100 : * used certificate applications.
101 : *
102 : * Certificate types are primarily used in the implementation of access control policies,
103 : * where access to application features is influenced by the type of certificate presented
104 : * by a requester.
105 : *
106 : * @note Cert type is an API data type only; it should never be sent over-the-wire.
107 : */
108 : enum class CertType : uint8_t
109 : {
110 : kNotSpecified = 0x00, /**< The certificate's type has not been specified. */
111 : kRoot = 0x01, /**< A CHIP Root certificate. */
112 : kICA = 0x02, /**< A CHIP Intermediate CA certificate. */
113 : kNode = 0x03, /**< A CHIP node certificate. */
114 : kFirmwareSigning = 0x04, /**< A CHIP firmware signing certificate. Note that CHIP doesn't
115 : specify how firmware images are signed and implementation of
116 : firmware image signing is manufacturer-specific. The CHIP
117 : certificate format supports encoding of firmware signing
118 : certificates if chosen by the manufacturer to use them. */
119 : kNetworkIdentity = 0x05, /**< A CHIP Network (Client) Identity. */
120 : };
121 :
122 : /** X.509 Certificate Key Purpose Flags
123 : *
124 : * The flags order must match the enumeration order of corresponding kOID_KeyPurpose values.
125 : */
126 : enum class KeyPurposeFlags : uint8_t
127 : {
128 : kServerAuth = 0x01, /**< Extended key usage is server authentication. */
129 : kClientAuth = 0x02, /**< Extended key usage is client authentication. */
130 : kCodeSigning = 0x04, /**< Extended key usage is code signing. */
131 : kEmailProtection = 0x08, /**< Extended key usage is email protection. */
132 : kTimeStamping = 0x10, /**< Extended key usage is time stamping. */
133 : kOCSPSigning = 0x20, /**< Extended key usage is OCSP signing. */
134 : };
135 :
136 : /** X.509 Certificate Key Usage Flags
137 : */
138 : enum class KeyUsageFlags : uint16_t
139 : {
140 : kDigitalSignature = 0x0001, /**< Key usage is digital signature. */
141 : kNonRepudiation = 0x0002, /**< Key usage is non-repudiation. */
142 : kKeyEncipherment = 0x0004, /**< Key usage is key encipherment. */
143 : kDataEncipherment = 0x0008, /**< Key usage is data encipherment. */
144 : kKeyAgreement = 0x0010, /**< Key usage is key agreement. */
145 : kKeyCertSign = 0x0020, /**< Key usage is key cert signing. */
146 : kCRLSign = 0x0040, /**< Key usage is CRL signing. */
147 : kEncipherOnly = 0x0080, /**< Key usage is encipher only. */
148 : kDecipherOnly = 0x0100, /**< Key usage is decipher only. */
149 : };
150 :
151 : /** CHIP Certificate Flags
152 : *
153 : * Contains information about a certificate that has been loaded into a ChipCertificateData object.
154 : */
155 : enum class CertFlags : uint16_t
156 : {
157 : kExtPresent_BasicConstraints = 0x0001, /**< Basic constraints extension is present in the certificate. */
158 : kExtPresent_KeyUsage = 0x0002, /**< Key usage extension is present in the certificate. */
159 : kExtPresent_ExtendedKeyUsage = 0x0004, /**< Extended key usage extension is present in the certificate. */
160 : kExtPresent_SubjectKeyId = 0x0008, /**< Subject key identifier extension is present in the certificate. */
161 : kExtPresent_AuthKeyId = 0x0010, /**< Authority key identifier extension is present in the certificate. */
162 : kExtPresent_FutureIsCritical = 0x0020, /**< Future extension marked as critical is present in the certificate. */
163 : kPathLenConstraintPresent = 0x0040, /**< Path length constraint is present in the certificate. */
164 : kIsCA = 0x0080, /**< Indicates that certificate is a CA certificate. */
165 : kIsTrustAnchor = 0x0100, /**< Indicates that certificate is a trust anchor. */
166 : kTBSHashPresent = 0x0200, /**< Indicates that TBS hash of the certificate was generated and stored. */
167 : };
168 :
169 : /** CHIP Certificate Decode Flags
170 : *
171 : * Contains information specifying how a certificate should be decoded.
172 : */
173 : enum class CertDecodeFlags : uint8_t
174 : {
175 : kGenerateTBSHash = 0x01, /**< Indicates that to-be-signed (TBS) hash of the certificate should be calculated when certificate is
176 : loaded. The TBS hash is then used to validate certificate signature. Normally, all certificates
177 : (except trust anchor) in the certificate validation chain require TBS hash. */
178 : kIsTrustAnchor = 0x02, /**< Indicates that the corresponding certificate is trust anchor. */
179 : };
180 :
181 : enum
182 : {
183 : kNullCertTime = 0
184 : };
185 :
186 : /**
187 : * @struct ChipRDN
188 : *
189 : * @brief
190 : * A data structure representing a Relative Distinguished Name (RDN) in a CHIP certificate.
191 : */
192 : struct ChipRDN
193 : {
194 : CharSpan mString; /**< Attribute value when encoded as a string. */
195 : uint64_t mChipVal; /**< CHIP specific DN attribute value. */
196 : chip::ASN1::OID mAttrOID = chip::ASN1::kOID_NotSpecified; /**< DN attribute CHIP OID. */
197 : bool mAttrIsPrintableString; /**< Specifies if attribute is a printable string type. */
198 :
199 : bool IsEqual(const ChipRDN & other) const;
200 90242 : bool IsEmpty() const { return mAttrOID == chip::ASN1::kOID_NotSpecified; }
201 104680 : void Clear()
202 : {
203 104680 : mAttrOID = chip::ASN1::kOID_NotSpecified;
204 104680 : mAttrIsPrintableString = false;
205 104680 : mChipVal = 0;
206 104680 : mString = CharSpan{};
207 104680 : }
208 : };
209 :
210 : /**
211 : * @brief
212 : * A data structure representing a Distinguished Name (DN) in a CHIP certificate.
213 : */
214 : class ChipDN
215 : {
216 : public:
217 : ChipDN();
218 : ~ChipDN();
219 :
220 : void Clear();
221 :
222 : /**
223 : * @brief Add CHIP-specific attribute to the DN.
224 : *
225 : * @param oid CHIP-specific OID for DN attribute.
226 : * @param val CHIP-specific DN attribute value.
227 : *
228 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
229 : **/
230 : CHIP_ERROR AddAttribute(chip::ASN1::OID oid, uint64_t val);
231 :
232 : /**
233 : * @brief Add CASE Authenticated Tags (CATs) attributes to the DN.
234 : *
235 : * @param cats Array of CAT values.
236 : *
237 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
238 : **/
239 : CHIP_ERROR AddCATs(const chip::CATValues & cats);
240 :
241 : /**
242 : * @brief Add string attribute to the DN.
243 : *
244 : * @param oid String OID for DN attribute.
245 : * @param val A CharSpan object containing a pointer and length of the DN string attribute
246 : * buffer. The value in the buffer should remain valid while the object is in use.
247 : * @param isPrintableString Specifies if attribute ASN1 type is a printable string.
248 : *
249 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
250 : **/
251 : CHIP_ERROR AddAttribute(chip::ASN1::OID oid, CharSpan val, bool isPrintableString);
252 :
253 0 : inline CHIP_ERROR AddAttribute_CommonName(CharSpan val, bool isPrintableString)
254 : {
255 0 : return AddAttribute(ASN1::kOID_AttributeType_CommonName, val, isPrintableString);
256 : }
257 : inline CHIP_ERROR AddAttribute_Surname(CharSpan val, bool isPrintableString)
258 : {
259 : return AddAttribute(ASN1::kOID_AttributeType_Surname, val, isPrintableString);
260 : }
261 : inline CHIP_ERROR AddAttribute_SerialNumber(CharSpan val, bool isPrintableString)
262 : {
263 : return AddAttribute(ASN1::kOID_AttributeType_SerialNumber, val, isPrintableString);
264 : }
265 : inline CHIP_ERROR AddAttribute_CountryName(CharSpan val, bool isPrintableString)
266 : {
267 : return AddAttribute(ASN1::kOID_AttributeType_CountryName, val, isPrintableString);
268 : }
269 : inline CHIP_ERROR AddAttribute_LocalityName(CharSpan val, bool isPrintableString)
270 : {
271 : return AddAttribute(ASN1::kOID_AttributeType_LocalityName, val, isPrintableString);
272 : }
273 : inline CHIP_ERROR AddAttribute_StateOrProvinceName(CharSpan val, bool isPrintableString)
274 : {
275 : return AddAttribute(ASN1::kOID_AttributeType_StateOrProvinceName, val, isPrintableString);
276 : }
277 : inline CHIP_ERROR AddAttribute_OrganizationName(CharSpan val, bool isPrintableString)
278 : {
279 : return AddAttribute(ASN1::kOID_AttributeType_OrganizationName, val, isPrintableString);
280 : }
281 : inline CHIP_ERROR AddAttribute_OrganizationalUnitName(CharSpan val, bool isPrintableString)
282 : {
283 : return AddAttribute(ASN1::kOID_AttributeType_OrganizationalUnitName, val, isPrintableString);
284 : }
285 : inline CHIP_ERROR AddAttribute_Title(CharSpan val, bool isPrintableString)
286 : {
287 : return AddAttribute(ASN1::kOID_AttributeType_Title, val, isPrintableString);
288 : }
289 : inline CHIP_ERROR AddAttribute_Name(CharSpan val, bool isPrintableString)
290 : {
291 : return AddAttribute(ASN1::kOID_AttributeType_Name, val, isPrintableString);
292 : }
293 : inline CHIP_ERROR AddAttribute_GivenName(CharSpan val, bool isPrintableString)
294 : {
295 : return AddAttribute(ASN1::kOID_AttributeType_GivenName, val, isPrintableString);
296 : }
297 : inline CHIP_ERROR AddAttribute_Initials(CharSpan val, bool isPrintableString)
298 : {
299 : return AddAttribute(ASN1::kOID_AttributeType_Initials, val, isPrintableString);
300 : }
301 : inline CHIP_ERROR AddAttribute_GenerationQualifier(CharSpan val, bool isPrintableString)
302 : {
303 : return AddAttribute(ASN1::kOID_AttributeType_GenerationQualifier, val, isPrintableString);
304 : }
305 : inline CHIP_ERROR AddAttribute_DNQualifier(CharSpan val, bool isPrintableString)
306 : {
307 : return AddAttribute(ASN1::kOID_AttributeType_DNQualifier, val, isPrintableString);
308 : }
309 : inline CHIP_ERROR AddAttribute_Pseudonym(CharSpan val, bool isPrintableString)
310 : {
311 : return AddAttribute(ASN1::kOID_AttributeType_Pseudonym, val, isPrintableString);
312 : }
313 : inline CHIP_ERROR AddAttribute_DomainComponent(CharSpan val, bool isPrintableString)
314 : {
315 : return AddAttribute(ASN1::kOID_AttributeType_DomainComponent, val, isPrintableString);
316 : }
317 0 : inline CHIP_ERROR AddAttribute_MatterNodeId(uint64_t val) { return AddAttribute(ASN1::kOID_AttributeType_MatterNodeId, val); }
318 : inline CHIP_ERROR AddAttribute_MatterFirmwareSigningId(uint64_t val)
319 : {
320 : return AddAttribute(ASN1::kOID_AttributeType_MatterFirmwareSigningId, val);
321 : }
322 0 : inline CHIP_ERROR AddAttribute_MatterICACId(uint64_t val) { return AddAttribute(ASN1::kOID_AttributeType_MatterICACId, val); }
323 0 : inline CHIP_ERROR AddAttribute_MatterRCACId(uint64_t val) { return AddAttribute(ASN1::kOID_AttributeType_MatterRCACId, val); }
324 0 : inline CHIP_ERROR AddAttribute_MatterFabricId(uint64_t val)
325 : {
326 0 : return AddAttribute(ASN1::kOID_AttributeType_MatterFabricId, val);
327 : }
328 0 : inline CHIP_ERROR AddAttribute_MatterCASEAuthTag(CASEAuthTag val)
329 : {
330 0 : return AddAttribute(ASN1::kOID_AttributeType_MatterCASEAuthTag, val);
331 : }
332 :
333 : /**
334 : * @brief Determine type of a CHIP certificate.
335 : * This method performs an assessment of a certificate's type based on the structure
336 : * of its subject DN.
337 : *
338 : * @param certType A reference to the certificate type value.
339 : *
340 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
341 : **/
342 : CHIP_ERROR GetCertType(CertType & certType) const;
343 :
344 : /**
345 : * @brief Retrieve the ID of a CHIP certificate.
346 : *
347 : * @param certId A reference to the certificate ID value.
348 : *
349 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
350 : **/
351 : CHIP_ERROR GetCertChipId(uint64_t & certId) const;
352 :
353 : /**
354 : * @brief Retrieve the Fabric ID of a CHIP certificate.
355 : **/
356 : CHIP_ERROR GetCertFabricId(uint64_t & fabricId) const;
357 :
358 : /**
359 : * @brief Encode ChipDN attributes in TLV form.
360 : **/
361 : CHIP_ERROR EncodeToTLV(chip::TLV::TLVWriter & writer, TLV::Tag tag) const;
362 :
363 : /**
364 : * @brief Decode ChipDN attributes from TLV encoded format.
365 : *
366 : * @param reader A TLVReader positioned at the ChipDN TLV list.
367 : **/
368 : CHIP_ERROR DecodeFromTLV(chip::TLV::TLVReader & reader);
369 :
370 : /**
371 : * @brief Encode ChipDN attributes in ASN1 form.
372 : **/
373 : CHIP_ERROR EncodeToASN1(ASN1::ASN1Writer & writer) const;
374 :
375 : /**
376 : * @brief Decode ChipDN attributes from ASN1 encoded format.
377 : *
378 : * @param reader A ASN1Reader positioned at the ChipDN ASN1 list.
379 : **/
380 : CHIP_ERROR DecodeFromASN1(ASN1::ASN1Reader & reader);
381 :
382 : bool IsEqual(const ChipDN & other) const;
383 :
384 : /**
385 : * @brief Determine if DN is empty (doesn't have DN attributes).
386 : *
387 : * @return true if DN is empty, false otherwise.
388 : **/
389 : bool IsEmpty() const { return RDNCount() == 0; }
390 :
391 : static_assert((CHIP_CONFIG_CERT_MAX_RDN_ATTRIBUTES) >= 5, "Spec requires at least 5 RDN to be supported per Matter TLV cert");
392 : ChipRDN rdn[CHIP_CONFIG_CERT_MAX_RDN_ATTRIBUTES];
393 :
394 : uint8_t RDNCount() const;
395 : };
396 :
397 : /**
398 : * @brief A data structure for holding a certificate key identifier, without the ownership of it.
399 : */
400 : using CertificateKeyId = FixedByteSpan<kKeyIdentifierLength>;
401 :
402 : /**
403 : * @brief A mutable `CertificateKeyId`.
404 : */
405 : using MutableCertificateKeyId = FixedSpan<uint8_t, kKeyIdentifierLength>;
406 :
407 : /**
408 : * @brief A storage type for `CertificateKeyId` and `MutableCertificateKeyId`.
409 : */
410 : using CertificateKeyIdStorage = std::array<uint8_t, kKeyIdentifierLength>;
411 :
412 : /**
413 : * @brief A data structure for holding a P256 ECDSA signature, without the ownership of it.
414 : */
415 : using P256ECDSASignatureSpan = FixedByteSpan<Crypto::kP256_ECDSA_Signature_Length_Raw>;
416 :
417 : /**
418 : * @brief A data structure for holding a P256 Public Key, without the ownership of it.
419 : */
420 : using P256PublicKeySpan = FixedByteSpan<Crypto::kP256_PublicKey_Length>;
421 :
422 : /**
423 : * @brief A data structure for holding a P256 Integer, without the ownership of it.
424 : */
425 : using P256IntegerSpan = FixedByteSpan<Crypto::kP256_FE_Length>;
426 :
427 : /**
428 : * @struct ChipCertificateData
429 : *
430 : * @brief
431 : * In-memory representation of data extracted from a CHIP certificate.
432 : *
433 : * Some of the fields in this structure are pointers to the fields in the original
434 : * CHIP certificate. That CHIP certificate is stored in a separate buffer and it is
435 : * required that data in that buffer remains valid while the corresponding
436 : * ChipCertificateData structure is used.
437 : */
438 : struct ChipCertificateData
439 : {
440 : ChipCertificateData();
441 : ~ChipCertificateData();
442 :
443 : void Clear();
444 : bool IsEqual(const ChipCertificateData & other) const;
445 :
446 : ByteSpan mSerialNumber; /**< Certificate Serial Number. */
447 : ChipDN mSubjectDN; /**< Certificate Subject DN. */
448 : ChipDN mIssuerDN; /**< Certificate Issuer DN. */
449 : CertificateKeyId mSubjectKeyId; /**< Certificate Subject public key identifier. */
450 : CertificateKeyId mAuthKeyId; /**< Certificate Authority public key identifier. */
451 : uint32_t mNotBeforeTime; /**< Certificate validity: Not Before field. */
452 : uint32_t mNotAfterTime; /**< Certificate validity: Not After field. */
453 : P256PublicKeySpan mPublicKey; /**< Certificate public key. */
454 : uint16_t mPubKeyCurveOID; /**< Public key Elliptic Curve CHIP OID. */
455 : uint16_t mPubKeyAlgoOID; /**< Public key algorithm CHIP OID. */
456 : uint16_t mSigAlgoOID; /**< Certificate signature algorithm CHIP OID. */
457 : BitFlags<CertFlags> mCertFlags; /**< Certificate data flags. */
458 : BitFlags<KeyUsageFlags> mKeyUsageFlags; /**< Certificate key usage extensions flags. */
459 : BitFlags<KeyPurposeFlags> mKeyPurposeFlags; /**< Certificate extended key usage extensions flags. */
460 : uint8_t mPathLenConstraint; /**< Basic constraint: path length. */
461 : P256ECDSASignatureSpan mSignature; /**< Certificate signature. */
462 :
463 : uint8_t mTBSHash[Crypto::kSHA256_Hash_Length]; /**< Certificate TBS hash. */
464 : };
465 :
466 : /**
467 : * @brief Decode CHIP certificate.
468 : * It is required that the CHIP certificate in the chipCert buffer stays valid while
469 : * the certData is used.
470 : *
471 : * @param chipCert Buffer containing CHIP certificate.
472 : * @param certData Structure containing data extracted from the CHIP certificate.
473 : *
474 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
475 : **/
476 : CHIP_ERROR DecodeChipCert(const ByteSpan chipCert, ChipCertificateData & certData, BitFlags<CertDecodeFlags> decodeFlags = {});
477 :
478 : /**
479 : * @brief Decode CHIP certificate.
480 : * It is required that the CHIP certificate in the reader's underlying buffer stays valid while
481 : * the certData is used.
482 : *
483 : * @param reader A TLVReader positioned at the CHIP certificate TLV structure.
484 : * @param certData Structure containing data extracted from the CHIP certificate.
485 : *
486 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
487 : **/
488 : CHIP_ERROR DecodeChipCert(chip::TLV::TLVReader & reader, ChipCertificateData & certData,
489 : BitFlags<CertDecodeFlags> decodeFlags = {});
490 :
491 : /**
492 : * @brief Decode CHIP Distinguished Name (DN).
493 : * It is required that the CHIP DN in the reader's underlying buffer stays valid while
494 : * the dn structure is used.
495 : *
496 : * @param reader A TLVReader positioned at the CHIP DN TLV structure.
497 : * @param dn Distinguished Name structure.
498 : *
499 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
500 : **/
501 : CHIP_ERROR DecodeChipDN(chip::TLV::TLVReader & reader, ChipDN & dn);
502 :
503 : /**
504 : * @brief Convert standard X.509 certificate to CHIP certificate.
505 : *
506 : * @param x509Cert CHIP X.509 DER encoded certificate.
507 : * @param chipCert Buffer to store converted certificate in CHIP format.
508 : *
509 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
510 : **/
511 : CHIP_ERROR ConvertX509CertToChipCert(const ByteSpan x509Cert, MutableByteSpan & chipCert);
512 :
513 : /**
514 : * @brief Convert CHIP certificate to the standard X.509 DER encoded certificate.
515 : *
516 : * @param chipCert CHIP certificate in CHIP TLV encoding.
517 : * @param x509Cert Buffer to store converted certificate in X.509 DER format.
518 : *
519 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
520 : **/
521 : CHIP_ERROR ConvertChipCertToX509Cert(const ByteSpan chipCert, MutableByteSpan & x509Cert);
522 :
523 : /**
524 : * @brief Verifies the signature of a certificate.
525 : *
526 : * @param cert The certificate to be verified.
527 : * @param signer The certificate containing the public key used to verify the signature.
528 : *
529 : * @return Returns a CHIP_ERROR on validation or other error, CHIP_NO_ERROR otherwise
530 : *
531 : * The certificate to be verified must have been decoded with TBS hash calculation enabled.
532 : *
533 : * Note that this function performs ONLY signature verification. No Subject and Issuer DN
534 : * comparison, Key Usage extension checks or similar validation is performed.
535 : **/
536 : CHIP_ERROR VerifyCertSignature(const ChipCertificateData & cert, const ChipCertificateData & signer);
537 :
538 : /**
539 : * Validate CHIP Root CA Certificate (RCAC) in ByteSpan TLV-encoded form.
540 : * This function performs RCAC parsing, checks SubjectDN validity, verifies that SubjectDN
541 : * and IssuerDN are equal, verifies that SKID and AKID are equal, validates certificate signature.
542 : *
543 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
544 : */
545 : CHIP_ERROR ValidateChipRCAC(const ByteSpan & rcac);
546 :
547 : /**
548 : * Validates a Network (Client) Identity in TLV-encoded form.
549 : * Accepts either a full certificate or the compact-pdc-identity format.
550 : *
551 : * This function parses the certificate, ensures the rigid fields have the values mandated by the
552 : * specification, and validates the certificate signature.
553 : *
554 : * @param cert The network identity certificate to validate.
555 : *
556 : * @return CHIP_NO_ERROR on success, CHIP_ERROR_WRONG_CERT_TYPE if the certificate does
557 : * not conform to the requirements for a Network Identity, CHIP_ERROR_INVALID_SIGNATURE
558 : * if the certificate has an invalid signature, or another CHIP_ERROR.
559 : *
560 : * @see section 11.24 (Wi-Fi Authentication with Per-Device Credentials) of the Matter spec
561 : */
562 : CHIP_ERROR ValidateChipNetworkIdentity(const ByteSpan & cert);
563 :
564 : /**
565 : * Convenience variant of `ValidateChipNetworkIdentity` that, upon successful validation, also
566 : * calculates the key identifier for the Network (Client) Identity.
567 : * @see ValidateChipNetworkIdentity
568 : * @see ExtractIdentifierFromChipNetworkIdentity
569 : */
570 : CHIP_ERROR ValidateChipNetworkIdentity(const ByteSpan & cert, MutableCertificateKeyId outKeyId);
571 :
572 : struct FutureExtension
573 : {
574 : ByteSpan OID;
575 : ByteSpan Extension;
576 : };
577 :
578 : struct X509CertRequestParams
579 : {
580 : int64_t SerialNumber;
581 : uint32_t ValidityStart;
582 : uint32_t ValidityEnd;
583 : ChipDN SubjectDN;
584 : ChipDN IssuerDN;
585 : Optional<FutureExtension> FutureExt;
586 : };
587 :
588 : /**
589 : * @brief Generate a new X.509 DER encoded Root CA certificate
590 : *
591 : * @param requestParams Certificate request parameters.
592 : * @param issuerKeypair The certificate signing key
593 : * @param x509Cert Buffer to store signed certificate in X.509 DER format.
594 : *
595 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
596 : **/
597 : CHIP_ERROR NewRootX509Cert(const X509CertRequestParams & requestParams, const Crypto::P256Keypair & issuerKeypair,
598 : MutableByteSpan & x509Cert);
599 :
600 : /**
601 : * @brief Generate a new X.509 DER encoded Intermediate CA certificate
602 : *
603 : * @param requestParams Certificate request parameters.
604 : * @param subjectPubkey The public key of subject
605 : * @param issuerKeypair The certificate signing key
606 : * @param x509Cert Buffer to store signed certificate in X.509 DER format.
607 : *
608 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
609 : **/
610 : CHIP_ERROR NewICAX509Cert(const X509CertRequestParams & requestParams, const Crypto::P256PublicKey & subjectPubkey,
611 : const Crypto::P256Keypair & issuerKeypair, MutableByteSpan & x509Cert);
612 :
613 : /**
614 : * @brief Generate a new X.509 DER encoded Node operational certificate
615 : *
616 : * @param requestParams Certificate request parameters.
617 : * @param subjectPubkey The public key of subject
618 : * @param issuerKeypair The certificate signing key
619 : * @param x509Cert Buffer to store signed certificate in X.509 DER format.
620 : *
621 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
622 : **/
623 : CHIP_ERROR NewNodeOperationalX509Cert(const X509CertRequestParams & requestParams, const Crypto::P256PublicKey & subjectPubkey,
624 : const Crypto::P256Keypair & issuerKeypair, MutableByteSpan & x509Cert);
625 :
626 : /**
627 : * @brief Generates a Network (Client) Identity certificate in TLV-encoded form.
628 : *
629 : * @param keypair The key pair underlying the identity.
630 : * @param outCompactCert Buffer to store the signed certificate in compact-pdc-identity TLV format.
631 : * Must be at least `kMaxCHIPCompactNetworkIdentityLength` bytes long.
632 : *
633 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
634 : **/
635 : CHIP_ERROR NewChipNetworkIdentity(const Crypto::P256Keypair & keypair, MutableByteSpan & outCompactCert);
636 :
637 : /**
638 : * @brief
639 : * Convert a certificate date/time (in the form of an ASN.1 universal time structure) into a CHIP Epoch time.
640 : *
641 : * @note
642 : * This function makes no attempt to verify the correct range of the input time other than year.
643 : * Therefore callers must make sure the supplied values are valid prior to invocation.
644 : *
645 : * @param asn1Time The calendar date/time to be converted.
646 : * @param epochTime A reference to an integer that will receive CHIP Epoch time.
647 : *
648 : * @retval #CHIP_NO_ERROR If the input time was successfully converted.
649 : * @retval #ASN1_ERROR_UNSUPPORTED_ENCODING If the input time contained a year value that could not
650 : * be represented in a CHIP epoch UTC time value.
651 : **/
652 : CHIP_ERROR ASN1ToChipEpochTime(const chip::ASN1::ASN1UniversalTime & asn1Time, uint32_t & epochTime);
653 :
654 : /**
655 : * @brief
656 : * Convert a CHIP epoch UTC time into an ASN.1 universal time structure.
657 : *
658 : * @param epochTime A CHIP epoch UTC time to be converted.
659 : * @param asn1Time A reference to an ASN1UniversalTime structure to receive the date/time.
660 : *
661 : * @retval #CHIP_NO_ERROR If the input time was successfully converted.
662 : */
663 : CHIP_ERROR ChipEpochToASN1Time(uint32_t epochTime, chip::ASN1::ASN1UniversalTime & asn1Time);
664 :
665 : /**
666 : * @return True if the OID represents a CHIP-defined 64-bit distinguished named attribute.
667 : **/
668 31510 : inline bool IsChip64bitDNAttr(chip::ASN1::OID oid)
669 : {
670 27656 : return (oid == chip::ASN1::kOID_AttributeType_MatterNodeId || oid == chip::ASN1::kOID_AttributeType_MatterFirmwareSigningId ||
671 59166 : oid == chip::ASN1::kOID_AttributeType_MatterICACId || oid == chip::ASN1::kOID_AttributeType_MatterRCACId ||
672 31510 : oid == chip::ASN1::kOID_AttributeType_MatterFabricId);
673 : }
674 :
675 : /**
676 : * @return True if the OID represents a CHIP-defined 32-bit distinguished named attribute.
677 : **/
678 9871 : inline bool IsChip32bitDNAttr(chip::ASN1::OID oid)
679 : {
680 9871 : return (oid == chip::ASN1::kOID_AttributeType_MatterCASEAuthTag);
681 : }
682 :
683 : /**
684 : * @return True if the OID represents a CHIP-defined distinguished named attribute.
685 : **/
686 13580 : inline bool IsChipDNAttr(chip::ASN1::OID oid)
687 : {
688 13580 : return (IsChip64bitDNAttr(oid) || IsChip32bitDNAttr(oid));
689 : }
690 :
691 : /**
692 : * @brief Convert an ASN.1 DER encoded integer to a raw big-endian integer.
693 : *
694 : * @param derInt P256 integer in ASN.1 DER encoded form.
695 : * @param rawInt Buffer to store converted raw integer.
696 : * @param rawIntLen The length of the converted raw integer.
697 : *
698 : * @retval #CHIP_NO_ERROR If the integer value was successfully converted.
699 : */
700 : CHIP_ERROR ConvertIntegerDERToRaw(ByteSpan derInt, uint8_t * rawInt, const uint16_t rawIntLen);
701 :
702 : /**
703 : * @brief Convert a raw CHIP signature to an ASN.1 DER encoded signature structure.
704 : *
705 : * @param[in] rawSig P256 ECDSA signature in raw form.
706 : * @param[in,out] derSig Output buffer to receive the converted ASN.1 DER encoded signature.
707 : * `derSig` must be at least `kMax_ECDSA_Signature_Length_Der` bytes long.
708 : * The `derSig` size will be set to the actual DER encoded signature length on success.
709 : *
710 : * @retval #CHIP_NO_ERROR If the signature value was successfully converted.
711 : */
712 : CHIP_ERROR ConvertECDSASignatureRawToDER(P256ECDSASignatureSpan rawSig, MutableByteSpan & derSig);
713 :
714 : /**
715 : * @brief Convert a raw CHIP ECDSA signature to an ASN.1 DER encoded signature structure.
716 : *
717 : * @param rawSig P256 ECDSA signature in raw form.
718 : * @param writer A reference to the ASN1Writer to store ASN.1 DER encoded signature.
719 : *
720 : * @retval #CHIP_NO_ERROR If the signature value was successfully converted.
721 : */
722 : CHIP_ERROR ConvertECDSASignatureRawToDER(P256ECDSASignatureSpan rawSig, ASN1::ASN1Writer & writer);
723 :
724 : /**
725 : * @brief Convert an ASN.1 DER encoded ECDSA signature to a raw CHIP signature.
726 : *
727 : * @param reader A reference to the ASN1Reader positioned at the beginning of the
728 : * DER encoded ECDSA signature.
729 : * @param writer A reference to the TLVWriter to store TLV encoded ECDSA signature element.
730 : * @param tag Tag to use for TLV encoded signature.
731 : *
732 : * @retval #CHIP_NO_ERROR If the signature value was successfully converted.
733 : */
734 : CHIP_ERROR ConvertECDSASignatureDERToRaw(ASN1::ASN1Reader & reader, chip::TLV::TLVWriter & writer, uint64_t tag);
735 :
736 : /**
737 : * @brief Convert a raw ECDSA P256 key pair to an ASN.1 DER encoded ECPrivateKey structure (RFC 5915).
738 : *
739 : * @param rawKeypair The raw P256 key pair.
740 : * @param outDerKeypair Output buffer to receive the ASN.1 DER encoded key pair.
741 : * Must have a capacity of at least `kP256ECPrivateKeyDERLength` bytes.
742 : *
743 : * @retval #CHIP_NO_ERROR If the key pair was successfully converted, or a CHIP_ERROR otherwise.
744 : */
745 : CHIP_ERROR ConvertECDSAKeypairRawToDER(const Crypto::P256SerializedKeypair & rawKeypair, MutableByteSpan & outDerKeypair);
746 :
747 : /**
748 : * Extract the Fabric ID from an operational certificate that has already been
749 : * parsed.
750 : *
751 : * This function can be used to extract Fabric ID from an ICA certificate.
752 : * These certificates may not contain a NodeID, so ExtractNodeIdFabricIdFromOpCert()
753 : * cannot be used for such certificates.
754 : *
755 : * @return CHIP_ERROR_NOT_FOUND if the passed-in cert does not have RDN
756 : * corresponding to FabricID.
757 : */
758 : CHIP_ERROR ExtractFabricIdFromCert(const ChipCertificateData & cert, FabricId * fabricId);
759 :
760 : /**
761 : * Extract Node ID and Fabric ID from an operational certificate that has already been
762 : * parsed.
763 : *
764 : * @return CHIP_ERROR_NOT_FOUND if the passed-in cert does not have at
765 : * least one NodeId RDN and one FabricId RDN in the Subject DN. No other
766 : * validation (e.g. checkign that there is exactly one RDN of each type) is
767 : * performed.
768 : */
769 : CHIP_ERROR ExtractNodeIdFabricIdFromOpCert(const ChipCertificateData & opcert, NodeId * nodeId, FabricId * fabricId);
770 :
771 : /**
772 : * Extract Node ID, Fabric ID and Compressed Fabric ID from an operational
773 : * certificate and its associated root certificate.
774 : *
775 : * @return CHIP_ERROR on failure or CHIP_NO_ERROR otherwise.
776 : */
777 : CHIP_ERROR ExtractNodeIdFabricIdCompressedFabricIdFromOpCerts(ByteSpan rcac, ByteSpan noc, CompressedFabricId & compressedFabricId,
778 : FabricId & fabricId, NodeId & nodeId);
779 :
780 : /**
781 : * Extract Node ID and Compressed Fabric ID from an operational certificate
782 : * and its associated root certificate.
783 : *
784 : * @return CHIP_ERROR on failure or CHIP_NO_ERROR otherwise.
785 : */
786 : CHIP_ERROR ExtractNodeIdCompressedFabricIdFromOpCerts(ByteSpan rcac, ByteSpan noc, CompressedFabricId & compressedFabricId,
787 : NodeId & nodeId);
788 :
789 : /**
790 : * Extract CASE Authenticated Tags from an operational certificate in ByteSpan TLV-encoded form.
791 : *
792 : * All values in the 'cats' struct will be set either to a valid CAT value or zero (undefined) value.
793 : *
794 : * @return CHIP_ERROR_INVALID_ARGUMENT if the passed-in cert is not NOC.
795 : * @return CHIP_ERROR_BUFFER_TOO_SMALL if there are too many CATs in the NOC
796 : */
797 : CHIP_ERROR ExtractCATsFromOpCert(const ByteSpan & opcert, CATValues & cats);
798 :
799 : /**
800 : * Extract CASE Authenticated Tags from an operational certificate that has already been
801 : * parsed.
802 : *
803 : * All values in the 'cats' struct will be set either to a valid CAT value or to the kUndefinedCAT value.
804 : *
805 : * @return CHIP_ERROR_INVALID_ARGUMENT if the passed-in cert is not NOC.
806 : * @return CHIP_ERROR_BUFFER_TOO_SMALL if the passed-in CATs array is too small.
807 : */
808 : CHIP_ERROR ExtractCATsFromOpCert(const ChipCertificateData & opcert, CATValues & cats);
809 :
810 : /**
811 : * Extract Fabric ID from an operational certificate in ByteSpan TLV-encoded
812 : * form. This does not perform any sort of validation on the certificate
813 : * structure other than parsing it.
814 : *
815 : * Can return any error that can be returned from parsing the cert or from the
816 : * ChipCertificateData* version of ExtractNodeIdFabricIdFromOpCert.
817 : */
818 : CHIP_ERROR ExtractFabricIdFromCert(const ByteSpan & opcert, FabricId * fabricId);
819 :
820 : /**
821 : * Extract Node ID and Fabric ID from an operational certificate in ByteSpan TLV-encoded
822 : * form. This does not perform any sort of validation on the certificate
823 : * structure other than parsing it.
824 : *
825 : * Can return any error that can be returned from parsing the cert or from the
826 : * ChipCertificateData* version of ExtractNodeIdFabricIdFromOpCert.
827 : */
828 : CHIP_ERROR ExtractNodeIdFabricIdFromOpCert(const ByteSpan & opcert, NodeId * nodeId, FabricId * fabricId);
829 :
830 : /**
831 : * Extract Public Key from a chip certificate in ByteSpan TLV-encoded form.
832 : * This does not perform any sort of validation on the certificate structure
833 : * other than parsing it.
834 : *
835 : * Can return any error that can be returned from parsing the cert.
836 : */
837 : CHIP_ERROR ExtractPublicKeyFromChipCert(const ByteSpan & chipCert, P256PublicKeySpan & publicKey);
838 :
839 : /**
840 : * Extract Not Before Time from a chip certificate in ByteSpan TLV-encoded form.
841 : * Output format is seconds referenced from the CHIP epoch.
842 : *
843 : * This does not perform any sort of validation on the certificate structure
844 : * other than parsing it.
845 : *
846 : * @param chipCert CHIP certificate in TLV-encoded form
847 : * @param notBeforeChipEpochTime (out) certificate NotBefore time as seconds from the CHIP epoch
848 : * @return CHIP_NO_ERROR if certificate parsing was successful, else an appropriate CHIP_ERROR
849 : */
850 : CHIP_ERROR ExtractNotBeforeFromChipCert(const ByteSpan & chipCert, chip::System::Clock::Seconds32 & notBeforeChipEpochTime);
851 :
852 : /**
853 : * Extract Subject Key Identifier from a chip certificate in ByteSpan TLV-encoded form.
854 : * This does not perform any sort of validation on the certificate structure
855 : * other than parsing it.
856 : *
857 : * Can return any error that can be returned from parsing the cert.
858 : */
859 : CHIP_ERROR ExtractSKIDFromChipCert(const ByteSpan & chipCert, CertificateKeyId & skid);
860 :
861 : /**
862 : * Extract Subject Distinguished Name (DN) from a chip certificate in ByteSpan TLV-encoded form.
863 : * It is required that the certificate in the chipCert buffer stays valid while the `dn` output is used.
864 : *
865 : * Can return any error that can be returned from parsing the cert.
866 : */
867 : CHIP_ERROR ExtractSubjectDNFromChipCert(const ByteSpan & chipCert, ChipDN & dn);
868 :
869 : /**
870 : * Extract Subject Distinguished Name (DN) from a chip certificate in ByteSpan X509 DER-encoded form.
871 : * It is required that the certificate in the chipCert buffer stays valid while the `dn` output is used.
872 : *
873 : * Can return any error that can be returned from converting and parsing the cert.
874 : */
875 : CHIP_ERROR ExtractSubjectDNFromX509Cert(const ByteSpan & x509Cert, ChipDN & dn);
876 :
877 : /**
878 : * Extracts the key identifier from a Network (Client) Identity in TLV-encoded form.
879 : * Does NOT perform full validation of the identity certificate.
880 : *
881 : * @return CHIP_NO_ERROR on success, CHIP_ERROR_WRONG_CERT_TYPE if the certificate is
882 : * not a Network (Client) Identity, or another CHIP_ERROR if parsing fails.
883 : */
884 : CHIP_ERROR ExtractIdentifierFromChipNetworkIdentity(const ByteSpan & cert, MutableCertificateKeyId outKeyId);
885 :
886 : } // namespace Credentials
887 : } // namespace chip
|