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 implements objects for modeling and working with
24 : * CHIP certificates.
25 : *
26 : */
27 :
28 : #include <stddef.h>
29 :
30 : #include <credentials/CHIPCert_Internal.h>
31 : #include <credentials/CHIPCertificateSet.h>
32 : #include <lib/asn1/ASN1.h>
33 : #include <lib/asn1/ASN1Macros.h>
34 : #include <lib/core/CHIPCore.h>
35 : #include <lib/core/CHIPSafeCasts.h>
36 : #include <lib/core/TLV.h>
37 : #include <lib/support/BytesToHex.h>
38 : #include <lib/support/CHIPMem.h>
39 : #include <lib/support/CodeUtils.h>
40 : #include <lib/support/SafeInt.h>
41 : #include <lib/support/ScopedBuffer.h>
42 : #include <lib/support/TimeUtils.h>
43 : #include <protocols/Protocols.h>
44 :
45 : namespace chip {
46 : namespace Credentials {
47 :
48 : using namespace chip::ASN1;
49 : using namespace chip::TLV;
50 : using namespace chip::Protocols;
51 : using namespace chip::Crypto;
52 :
53 931 : ChipCertificateSet::ChipCertificateSet()
54 : {
55 931 : mCerts = nullptr;
56 931 : mCertCount = 0;
57 931 : mMaxCerts = 0;
58 931 : mMemoryAllocInternal = false;
59 931 : }
60 :
61 931 : ChipCertificateSet::~ChipCertificateSet()
62 : {
63 931 : Release();
64 931 : }
65 :
66 863 : CHIP_ERROR ChipCertificateSet::Init(uint8_t maxCertsArraySize)
67 : {
68 863 : CHIP_ERROR err = CHIP_NO_ERROR;
69 :
70 863 : VerifyOrExit(maxCertsArraySize > 0, err = CHIP_ERROR_INVALID_ARGUMENT);
71 863 : mCerts = reinterpret_cast<ChipCertificateData *>(chip::Platform::MemoryAlloc(sizeof(ChipCertificateData) * maxCertsArraySize));
72 863 : VerifyOrExit(mCerts != nullptr, err = CHIP_ERROR_NO_MEMORY);
73 :
74 863 : mMaxCerts = maxCertsArraySize;
75 863 : mMemoryAllocInternal = true;
76 :
77 863 : Clear();
78 :
79 863 : exit:
80 863 : if (err != CHIP_NO_ERROR)
81 : {
82 0 : Release();
83 : }
84 :
85 863 : return err;
86 : }
87 :
88 126 : CHIP_ERROR ChipCertificateSet::Init(ChipCertificateData * certsArray, uint8_t certsArraySize)
89 : {
90 126 : CHIP_ERROR err = CHIP_NO_ERROR;
91 :
92 126 : VerifyOrExit(certsArray != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
93 126 : VerifyOrExit(certsArraySize > 0, err = CHIP_ERROR_INVALID_ARGUMENT);
94 :
95 126 : mCerts = certsArray;
96 126 : mMaxCerts = certsArraySize;
97 126 : mMemoryAllocInternal = false;
98 :
99 126 : Clear();
100 :
101 126 : exit:
102 126 : return err;
103 : }
104 :
105 997 : void ChipCertificateSet::Release()
106 : {
107 997 : if (mMemoryAllocInternal)
108 : {
109 870 : if (mCerts != nullptr)
110 : {
111 863 : Clear();
112 863 : chip::Platform::MemoryFree(mCerts);
113 863 : mCerts = nullptr;
114 : }
115 : }
116 997 : }
117 :
118 1904 : void ChipCertificateSet::Clear()
119 : {
120 7458 : for (int i = 0; i < mMaxCerts; i++)
121 : {
122 5554 : mCerts[i].Clear();
123 : }
124 :
125 1904 : mCertCount = 0;
126 1904 : }
127 :
128 2640 : CHIP_ERROR ChipCertificateSet::LoadCert(const ByteSpan chipCert, BitFlags<CertDecodeFlags> decodeFlags)
129 : {
130 2640 : TLVReader reader;
131 :
132 2640 : reader.Init(chipCert);
133 2640 : return LoadCert(reader, decodeFlags, chipCert);
134 : }
135 :
136 2640 : CHIP_ERROR ChipCertificateSet::LoadCert(TLVReader & reader, BitFlags<CertDecodeFlags> decodeFlags, ByteSpan chipCert)
137 : {
138 2640 : ChipCertificateData cert;
139 2640 : ReturnErrorOnFailure(DecodeChipCert(reader, cert, decodeFlags));
140 :
141 : // Verify the cert has both the Subject Key Id and Authority Key Id extensions present.
142 : // Only certs with both these extensions are supported for the purposes of certificate validation.
143 2557 : VerifyOrReturnError(cert.mCertFlags.HasAll(CertFlags::kExtPresent_SubjectKeyId, CertFlags::kExtPresent_AuthKeyId),
144 : CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
145 :
146 : // Verify the cert was signed with ECDSA-SHA256. This is the only signature algorithm currently supported.
147 2551 : VerifyOrReturnError(cert.mSigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256, CHIP_ERROR_UNSUPPORTED_SIGNATURE_TYPE);
148 :
149 : // Check if this cert matches any currently loaded certificates
150 4941 : for (uint32_t i = 0; i < mCertCount; i++)
151 : {
152 2392 : if (cert.IsEqual(mCerts[i]))
153 : {
154 : // This cert is already loaded. Let's skip adding this cert.
155 2 : return CHIP_NO_ERROR;
156 : }
157 : }
158 :
159 : // Verify we have room for the new certificate.
160 2549 : VerifyOrReturnError(mCertCount < mMaxCerts, CHIP_ERROR_NO_MEMORY);
161 :
162 2549 : new (&mCerts[mCertCount]) ChipCertificateData(cert);
163 2549 : mCertCount++;
164 :
165 2549 : return CHIP_NO_ERROR;
166 2640 : }
167 :
168 0 : CHIP_ERROR ChipCertificateSet::ReleaseLastCert()
169 : {
170 0 : ChipCertificateData * lastCert = (mCertCount > 0) ? &mCerts[mCertCount - 1] : nullptr;
171 0 : VerifyOrReturnError(lastCert != nullptr, CHIP_ERROR_INTERNAL);
172 :
173 0 : lastCert->~ChipCertificateData();
174 0 : --mCertCount;
175 :
176 0 : return CHIP_NO_ERROR;
177 : }
178 :
179 0 : const ChipCertificateData * ChipCertificateSet::FindCert(const CertificateKeyId & subjectKeyId) const
180 : {
181 0 : for (uint8_t i = 0; i < mCertCount; i++)
182 : {
183 0 : ChipCertificateData & cert = mCerts[i];
184 0 : if (cert.mSubjectKeyId.data_equal(subjectKeyId))
185 : {
186 0 : return &cert;
187 : }
188 : }
189 :
190 0 : return nullptr;
191 : }
192 :
193 134 : bool ChipCertificateSet::IsCertInTheSet(const ChipCertificateData * cert) const
194 : {
195 376 : for (uint8_t i = 0; i < mCertCount; i++)
196 : {
197 376 : if (cert == &mCerts[i])
198 : {
199 134 : return true;
200 : }
201 : }
202 :
203 0 : return false;
204 : }
205 :
206 134 : CHIP_ERROR ChipCertificateSet::ValidateCert(const ChipCertificateData * cert, ValidationContext & context)
207 : {
208 134 : VerifyOrReturnError(IsCertInTheSet(cert), CHIP_ERROR_INVALID_ARGUMENT);
209 :
210 134 : context.mTrustAnchor = nullptr;
211 :
212 134 : return ValidateCert(cert, context, 0);
213 : }
214 :
215 808 : CHIP_ERROR ChipCertificateSet::FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId,
216 : ValidationContext & context, const ChipCertificateData ** certData)
217 : {
218 808 : context.mTrustAnchor = nullptr;
219 :
220 808 : return FindValidCert(subjectDN, subjectKeyId, context, 0, certData);
221 : }
222 :
223 0 : CHIP_ERROR ChipCertificateSet::VerifySignature(const ChipCertificateData * cert, const ChipCertificateData * caCert)
224 : {
225 0 : VerifyOrReturnError((cert != nullptr) && (caCert != nullptr), CHIP_ERROR_INVALID_ARGUMENT);
226 0 : return VerifyCertSignature(*cert, *caCert);
227 : }
228 :
229 1674 : CHIP_ERROR VerifyCertSignature(const ChipCertificateData & cert, const ChipCertificateData & signer)
230 : {
231 1674 : VerifyOrReturnError(cert.mCertFlags.Has(CertFlags::kTBSHashPresent), CHIP_ERROR_INVALID_ARGUMENT);
232 1673 : VerifyOrReturnError(cert.mSigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256, CHIP_ERROR_UNSUPPORTED_SIGNATURE_TYPE);
233 :
234 : #ifdef ENABLE_HSM_ECDSA_VERIFY
235 : P256PublicKeyHSM signerPublicKey;
236 : #else
237 1673 : P256PublicKey signerPublicKey;
238 : #endif
239 1673 : P256ECDSASignature signature;
240 :
241 1673 : ReturnErrorOnFailure(signature.SetLength(cert.mSignature.size()));
242 1673 : memcpy(signature.Bytes(), cert.mSignature.data(), cert.mSignature.size());
243 :
244 1673 : memcpy(signerPublicKey, signer.mPublicKey.data(), signer.mPublicKey.size());
245 :
246 1673 : ReturnErrorOnFailure(
247 : signerPublicKey.ECDSA_validate_hash_signature(cert.mTBSHash, chip::Crypto::kSHA256_Hash_Length, signature));
248 :
249 1670 : return CHIP_NO_ERROR;
250 1673 : }
251 :
252 2615 : CHIP_ERROR ChipCertificateSet::ValidateCert(const ChipCertificateData * cert, ValidationContext & context, uint8_t depth)
253 : {
254 2615 : CHIP_ERROR err = CHIP_NO_ERROR;
255 2615 : const ChipCertificateData * caCert = nullptr;
256 : CertType certType;
257 :
258 2615 : err = cert->mSubjectDN.GetCertType(certType);
259 2615 : SuccessOrExit(err);
260 :
261 : // Certificate with future-extension marked as "critical" is not allowed.
262 2615 : VerifyOrExit(!cert->mCertFlags.Has(CertFlags::kExtPresent_FutureIsCritical), err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
263 :
264 : // If the depth is greater than 0 then the certificate is required to be a CA certificate...
265 2614 : if (depth > 0)
266 : {
267 : // Verify the isCA flag is present.
268 1673 : VerifyOrExit(cert->mCertFlags.Has(CertFlags::kIsCA), err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
269 :
270 : // Verify the key usage extension is present and contains the 'keyCertSign' flag.
271 1672 : VerifyOrExit(cert->mCertFlags.Has(CertFlags::kExtPresent_KeyUsage) && cert->mKeyUsageFlags.Has(KeyUsageFlags::kKeyCertSign),
272 : err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
273 :
274 : // Verify that the certificate type is set to Root or ICA.
275 1670 : VerifyOrExit(certType == CertType::kICA || certType == CertType::kRoot, err = CHIP_ERROR_WRONG_CERT_TYPE);
276 :
277 : // If a path length constraint was included, verify the cert depth vs. the specified constraint.
278 : //
279 : // From the RFC, the path length constraint "gives the maximum number of non-self-issued
280 : // intermediate certificates that may follow this certificate in a valid certification path.
281 : // (Note: The last certificate in the certification path is not an intermediate certificate,
282 : // and is not included in this limit...)"
283 : //
284 1670 : if (cert->mCertFlags.Has(CertFlags::kPathLenConstraintPresent))
285 : {
286 23 : VerifyOrExit((depth - 1) <= cert->mPathLenConstraint, err = CHIP_ERROR_CERT_PATH_LEN_CONSTRAINT_EXCEEDED);
287 : }
288 : }
289 :
290 : // Otherwise verify the desired certificate usages/purposes/type given in the validation context...
291 : else
292 : {
293 : // If a set of desired key usages has been specified, verify that the key usage extension exists
294 : // in the certificate and that the corresponding usages are supported.
295 941 : if (context.mRequiredKeyUsages.HasAny())
296 : {
297 923 : VerifyOrExit(cert->mCertFlags.Has(CertFlags::kExtPresent_KeyUsage) &&
298 : cert->mKeyUsageFlags.HasAll(context.mRequiredKeyUsages),
299 : err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
300 : }
301 :
302 : // If a set of desired key purposes has been specified, verify that the extended key usage extension
303 : // exists in the certificate and that the corresponding purposes are supported.
304 909 : if (context.mRequiredKeyPurposes.HasAny())
305 : {
306 905 : VerifyOrExit(cert->mCertFlags.Has(CertFlags::kExtPresent_ExtendedKeyUsage) &&
307 : cert->mKeyPurposeFlags.HasAll(context.mRequiredKeyPurposes),
308 : err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
309 : }
310 :
311 : // If a required certificate type has been specified, verify it against the current certificate's type.
312 893 : if (context.mRequiredCertType != CertType::kNotSpecified)
313 : {
314 2 : VerifyOrExit(certType == context.mRequiredCertType, err = CHIP_ERROR_WRONG_CERT_TYPE);
315 : }
316 : }
317 :
318 : // Verify NotBefore and NotAfter validity of the certificates.
319 : //
320 : // See also ASN1ToChipEpochTime().
321 : //
322 : // X.509/RFC5280 defines the special time 99991231235959Z to mean 'no
323 : // well-defined expiration date'. In CHIP TLV-encoded certificates, this
324 : // special value is represented as a CHIP Epoch time value of 0 sec
325 : // (2000-01-01 00:00:00 UTC).
326 : CertificateValidityResult validityResult;
327 2561 : if (context.mEffectiveTime.Is<CurrentChipEpochTime>())
328 : {
329 198 : if (context.mEffectiveTime.Get<CurrentChipEpochTime>().count() < cert->mNotBeforeTime)
330 : {
331 13 : ChipLogDetail(SecureChannel, "Certificate's mNotBeforeTime (%" PRIu32 ") is after current time (%" PRIu32 ")",
332 : cert->mNotBeforeTime, context.mEffectiveTime.Get<CurrentChipEpochTime>().count());
333 13 : validityResult = CertificateValidityResult::kNotYetValid;
334 : }
335 370 : else if (cert->mNotAfterTime != kNullCertTime &&
336 185 : context.mEffectiveTime.Get<CurrentChipEpochTime>().count() > cert->mNotAfterTime)
337 : {
338 13 : ChipLogDetail(SecureChannel, "Certificate's mNotAfterTime (%" PRIu32 ") is before current time (%" PRIu32 ")",
339 : cert->mNotAfterTime, context.mEffectiveTime.Get<CurrentChipEpochTime>().count());
340 13 : validityResult = CertificateValidityResult::kExpired;
341 : }
342 : else
343 : {
344 172 : validityResult = CertificateValidityResult::kValid;
345 : }
346 : }
347 2363 : else if (context.mEffectiveTime.Is<LastKnownGoodChipEpochTime>())
348 : {
349 : // Last Known Good Time may not be moved forward except at the time of
350 : // commissioning or firmware update, so we can't use it to validate
351 : // NotBefore. However, so long as firmware build times are properly
352 : // recorded and certificates loaded during commissioning are in fact
353 : // valid at the time of commissioning, observing a NotAfter that falls
354 : // before Last Known Good Time is a reliable indicator that the
355 : // certificate in question is expired. Check for this.
356 87 : if (cert->mNotAfterTime != 0 && context.mEffectiveTime.Get<LastKnownGoodChipEpochTime>().count() > cert->mNotAfterTime)
357 : {
358 19 : ChipLogDetail(SecureChannel, "Certificate's mNotAfterTime (%" PRIu32 ") is before last known good time (%" PRIu32 ")",
359 : cert->mNotAfterTime, context.mEffectiveTime.Get<LastKnownGoodChipEpochTime>().count());
360 19 : validityResult = CertificateValidityResult::kExpiredAtLastKnownGoodTime;
361 : }
362 : else
363 : {
364 68 : validityResult = CertificateValidityResult::kNotExpiredAtLastKnownGoodTime;
365 : }
366 : }
367 : else
368 : {
369 2276 : validityResult = CertificateValidityResult::kTimeUnknown;
370 : }
371 :
372 2561 : if (context.mValidityPolicy != nullptr)
373 : {
374 2372 : SuccessOrExit(err = context.mValidityPolicy->ApplyCertificateValidityPolicy(cert, depth, validityResult));
375 : }
376 : else
377 : {
378 189 : SuccessOrExit(err = CertificateValidityPolicy::ApplyDefaultPolicy(cert, depth, validityResult));
379 : }
380 :
381 : // If the certificate itself is trusted, then it is implicitly valid. Record this certificate as the trust
382 : // anchor and return success.
383 2528 : if (cert->mCertFlags.Has(CertFlags::kIsTrustAnchor))
384 : {
385 846 : context.mTrustAnchor = cert;
386 846 : ExitNow(err = CHIP_NO_ERROR);
387 : }
388 :
389 : // Otherwise we must validate the certificate by looking for a chain of valid certificates up to a trusted
390 : // certificate known as the 'trust anchor'.
391 :
392 : // Fail validation if the certificate is self-signed. Since we don't trust this certificate (see the check above) and
393 : // it has no path we can follow to a trust anchor, it can't be considered valid.
394 1682 : if (cert->mIssuerDN.IsEqual(cert->mSubjectDN) && cert->mAuthKeyId.data_equal(cert->mSubjectKeyId))
395 : {
396 2 : ExitNow(err = CHIP_ERROR_CERT_NOT_TRUSTED);
397 : }
398 :
399 : // Verify that the certificate depth is less than the total number of certificates. It is technically possible to create
400 : // a circular chain of certificates. Limiting the maximum depth of the certificate path prevents infinite
401 : // recursion in such a case.
402 1680 : VerifyOrExit(depth < mCertCount, err = CHIP_ERROR_CERT_PATH_TOO_LONG);
403 :
404 : // Search for a valid CA certificate that matches the Issuer DN and Authority Key Id of the current certificate.
405 : // Fail if no acceptable certificate is found.
406 1680 : err = FindValidCert(cert->mIssuerDN, cert->mAuthKeyId, context, static_cast<uint8_t>(depth + 1), &caCert);
407 1680 : if (err != CHIP_NO_ERROR)
408 : {
409 18 : ChipLogError(SecureChannel, "Failed to find valid cert during chain traversal: %" CHIP_ERROR_FORMAT, err.Format());
410 18 : ExitNow(err = CHIP_ERROR_CA_CERT_NOT_FOUND);
411 : }
412 :
413 : // Verify signature of the current certificate against public key of the CA certificate. If signature verification
414 : // succeeds, the current certificate is valid.
415 1662 : err = VerifyCertSignature(*cert, *caCert);
416 1662 : SuccessOrExit(err);
417 :
418 2615 : exit:
419 2615 : return err;
420 : }
421 :
422 2488 : CHIP_ERROR ChipCertificateSet::FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId,
423 : ValidationContext & context, uint8_t depth, const ChipCertificateData ** certData)
424 : {
425 : CHIP_ERROR err;
426 :
427 2488 : *certData = nullptr;
428 :
429 : // Default error if we don't find any matching cert.
430 2488 : err = (depth > 0) ? CHIP_ERROR_CA_CERT_NOT_FOUND : CHIP_ERROR_CERT_NOT_FOUND;
431 :
432 : // For each cert in the set...
433 4966 : for (uint8_t i = 0; i < mCertCount; i++)
434 : {
435 4932 : ChipCertificateData * candidateCert = &mCerts[i];
436 :
437 : // Skip the certificate if its subject DN and key id do not match the input criteria.
438 4932 : if (!candidateCert->mSubjectDN.IsEqual(subjectDN))
439 : {
440 2447 : continue;
441 : }
442 2485 : if (!candidateCert->mSubjectKeyId.data_equal(subjectKeyId))
443 : {
444 4 : continue;
445 : }
446 :
447 : // Attempt to validate the cert. If the cert is valid, return it to the caller. Otherwise,
448 : // save the returned error and continue searching. If there are no other matching certs this
449 : // will be the error returned to the caller.
450 2481 : err = ValidateCert(candidateCert, context, depth);
451 2481 : if (err == CHIP_NO_ERROR)
452 : {
453 2454 : *certData = candidateCert;
454 2454 : ExitNow();
455 : }
456 : }
457 :
458 34 : exit:
459 2488 : return err;
460 : }
461 :
462 3150 : ChipCertificateData::ChipCertificateData() {}
463 :
464 3150 : ChipCertificateData::~ChipCertificateData() {}
465 :
466 8603 : void ChipCertificateData::Clear()
467 : {
468 8603 : mSerialNumber = ByteSpan();
469 8603 : mSubjectDN.Clear();
470 8603 : mIssuerDN.Clear();
471 8603 : mSubjectKeyId = CertificateKeyId();
472 8603 : mAuthKeyId = CertificateKeyId();
473 8603 : mNotBeforeTime = 0;
474 8603 : mNotAfterTime = 0;
475 8603 : mPublicKey = P256PublicKeySpan();
476 8603 : mPubKeyCurveOID = 0;
477 8603 : mPubKeyAlgoOID = 0;
478 8603 : mSigAlgoOID = 0;
479 8603 : mPathLenConstraint = 0;
480 8603 : mCertFlags.ClearAll();
481 8603 : mKeyUsageFlags.ClearAll();
482 8603 : mKeyPurposeFlags.ClearAll();
483 8603 : mSignature = P256ECDSASignatureSpan();
484 :
485 8603 : memset(mTBSHash, 0, sizeof(mTBSHash));
486 8603 : }
487 :
488 2392 : bool ChipCertificateData::IsEqual(const ChipCertificateData & other) const
489 : {
490 : // TODO - Add an operator== on BitFlags class.
491 2398 : return mSubjectDN.IsEqual(other.mSubjectDN) && mIssuerDN.IsEqual(other.mIssuerDN) &&
492 6 : mSubjectKeyId.data_equal(other.mSubjectKeyId) && mAuthKeyId.data_equal(other.mAuthKeyId) &&
493 6 : (mNotBeforeTime == other.mNotBeforeTime) && (mNotAfterTime == other.mNotAfterTime) &&
494 6 : mPublicKey.data_equal(other.mPublicKey) && (mPubKeyCurveOID == other.mPubKeyCurveOID) &&
495 6 : (mPubKeyAlgoOID == other.mPubKeyAlgoOID) && (mSigAlgoOID == other.mSigAlgoOID) &&
496 7 : (mCertFlags.Raw() == other.mCertFlags.Raw()) && (mKeyUsageFlags.Raw() == other.mKeyUsageFlags.Raw()) &&
497 6 : (mKeyPurposeFlags.Raw() == other.mKeyPurposeFlags.Raw()) && (mPathLenConstraint == other.mPathLenConstraint) &&
498 2397 : mSignature.data_equal(other.mSignature) && (memcmp(mTBSHash, other.mTBSHash, sizeof(mTBSHash)) == 0);
499 : }
500 :
501 883 : void ValidationContext::Reset()
502 : {
503 883 : mEffectiveTime = EffectiveTime{};
504 883 : mTrustAnchor = nullptr;
505 883 : mValidityPolicy = nullptr;
506 883 : mRequiredKeyUsages.ClearAll();
507 883 : mRequiredKeyPurposes.ClearAll();
508 883 : mRequiredCertType = CertType::kNotSpecified;
509 883 : }
510 :
511 5996 : bool ChipRDN::IsEqual(const ChipRDN & other) const
512 : {
513 5996 : if (mAttrOID == kOID_Unknown || mAttrOID == kOID_NotSpecified || mAttrOID != other.mAttrOID ||
514 4196 : mAttrIsPrintableString != other.mAttrIsPrintableString)
515 : {
516 1800 : return false;
517 : }
518 :
519 4196 : if (IsChipDNAttr(mAttrOID))
520 : {
521 4182 : return mChipVal == other.mChipVal;
522 : }
523 :
524 14 : return mString.data_equal(other.mString);
525 : }
526 :
527 40788 : ChipDN::ChipDN()
528 : {
529 6798 : Clear();
530 6798 : }
531 :
532 7029 : ChipDN::~ChipDN() {}
533 :
534 24034 : void ChipDN::Clear()
535 : {
536 144204 : for (auto & dn : rdn)
537 : {
538 120170 : dn.Clear();
539 : }
540 24034 : }
541 :
542 44458 : uint8_t ChipDN::RDNCount() const
543 : {
544 : uint8_t count;
545 :
546 104923 : for (count = 0; count < CHIP_CONFIG_CERT_MAX_RDN_ATTRIBUTES; count++)
547 : {
548 104776 : if (rdn[count].IsEmpty())
549 : {
550 44311 : break;
551 : }
552 : }
553 :
554 44458 : return count;
555 : }
556 :
557 10358 : CHIP_ERROR ChipDN::AddAttribute(chip::ASN1::OID oid, uint64_t val)
558 : {
559 10358 : uint8_t rdnCount = RDNCount();
560 :
561 10358 : VerifyOrReturnError(rdnCount < CHIP_CONFIG_CERT_MAX_RDN_ATTRIBUTES, CHIP_ERROR_NO_MEMORY);
562 10358 : VerifyOrReturnError(IsChipDNAttr(oid), CHIP_ERROR_INVALID_ARGUMENT);
563 :
564 10358 : if (IsChip32bitDNAttr(oid))
565 : {
566 132 : VerifyOrReturnError(CanCastTo<uint32_t>(val), CHIP_ERROR_INVALID_ARGUMENT);
567 : }
568 :
569 10358 : rdn[rdnCount].mAttrOID = oid;
570 10358 : rdn[rdnCount].mChipVal = val;
571 10358 : rdn[rdnCount].mAttrIsPrintableString = false;
572 :
573 10358 : return CHIP_NO_ERROR;
574 : }
575 :
576 3 : CHIP_ERROR ChipDN::AddCATs(const chip::CATValues & cats)
577 : {
578 3 : VerifyOrReturnError(cats.AreValid(), CHIP_ERROR_INVALID_ARGUMENT);
579 :
580 12 : for (auto & cat : cats.values)
581 : {
582 9 : if (cat != kUndefinedCAT)
583 : {
584 1 : ReturnErrorOnFailure(AddAttribute_MatterCASEAuthTag(cat));
585 : }
586 : }
587 :
588 3 : return CHIP_NO_ERROR;
589 : }
590 :
591 152 : CHIP_ERROR ChipDN::AddAttribute(chip::ASN1::OID oid, CharSpan val, bool isPrintableString)
592 : {
593 152 : uint8_t rdnCount = RDNCount();
594 :
595 152 : VerifyOrReturnError(rdnCount < CHIP_CONFIG_CERT_MAX_RDN_ATTRIBUTES, CHIP_ERROR_NO_MEMORY);
596 151 : VerifyOrReturnError(!IsChipDNAttr(oid), CHIP_ERROR_INVALID_ARGUMENT);
597 151 : VerifyOrReturnError(oid != kOID_NotSpecified, CHIP_ERROR_INVALID_ARGUMENT);
598 :
599 151 : rdn[rdnCount].mAttrOID = oid;
600 151 : rdn[rdnCount].mString = val;
601 151 : rdn[rdnCount].mAttrIsPrintableString = isPrintableString;
602 :
603 151 : return CHIP_NO_ERROR;
604 : }
605 :
606 3134 : CHIP_ERROR ChipDN::GetCertType(CertType & certType) const
607 : {
608 3134 : CertType lCertType = CertType::kNotSpecified;
609 3134 : bool fabricIdPresent = false;
610 3134 : bool catsPresent = false;
611 3134 : uint8_t rdnCount = RDNCount();
612 :
613 3143 : if (rdnCount == 1 && rdn[0].mAttrOID == kOID_AttributeType_CommonName && !rdn[0].mAttrIsPrintableString &&
614 9 : rdn[0].mString.data_equal(kNetworkIdentityCN))
615 : {
616 9 : certType = CertType::kNetworkIdentity;
617 9 : return CHIP_NO_ERROR;
618 : }
619 :
620 3125 : certType = CertType::kNotSpecified;
621 :
622 8288 : for (uint8_t i = 0; i < rdnCount; i++)
623 : {
624 5175 : if (rdn[i].mAttrOID == kOID_AttributeType_MatterRCACId)
625 : {
626 1008 : VerifyOrReturnError(lCertType == CertType::kNotSpecified, CHIP_ERROR_WRONG_CERT_DN);
627 :
628 1006 : lCertType = CertType::kRoot;
629 : }
630 4167 : else if (rdn[i].mAttrOID == kOID_AttributeType_MatterICACId)
631 : {
632 985 : VerifyOrReturnError(lCertType == CertType::kNotSpecified, CHIP_ERROR_WRONG_CERT_DN);
633 :
634 983 : lCertType = CertType::kICA;
635 : }
636 3182 : else if (rdn[i].mAttrOID == kOID_AttributeType_MatterVidVerificationSignerId)
637 : {
638 9 : VerifyOrReturnError(lCertType == CertType::kNotSpecified, CHIP_ERROR_WRONG_CERT_DN);
639 :
640 9 : lCertType = CertType::kVidVerificationSigner;
641 : }
642 3173 : else if (rdn[i].mAttrOID == kOID_AttributeType_MatterNodeId)
643 : {
644 1115 : VerifyOrReturnError(lCertType == CertType::kNotSpecified, CHIP_ERROR_WRONG_CERT_DN);
645 1113 : VerifyOrReturnError(IsOperationalNodeId(rdn[i].mChipVal), CHIP_ERROR_WRONG_NODE_ID);
646 1113 : lCertType = CertType::kNode;
647 : }
648 2058 : else if (rdn[i].mAttrOID == kOID_AttributeType_MatterFirmwareSigningId)
649 : {
650 2 : VerifyOrReturnError(lCertType == CertType::kNotSpecified, CHIP_ERROR_WRONG_CERT_DN);
651 :
652 2 : lCertType = CertType::kFirmwareSigning;
653 : }
654 2056 : else if (rdn[i].mAttrOID == kOID_AttributeType_MatterFabricId)
655 : {
656 : // Only one fabricId attribute is allowed per DN.
657 1983 : VerifyOrReturnError(!fabricIdPresent, CHIP_ERROR_WRONG_CERT_DN);
658 1977 : VerifyOrReturnError(IsValidFabricId(rdn[i].mChipVal), CHIP_ERROR_WRONG_CERT_DN);
659 1977 : fabricIdPresent = true;
660 : }
661 73 : else if (rdn[i].mAttrOID == kOID_AttributeType_MatterCASEAuthTag)
662 : {
663 41 : VerifyOrReturnError(CanCastTo<CASEAuthTag>(rdn[i].mChipVal), CHIP_ERROR_WRONG_CERT_DN);
664 41 : VerifyOrReturnError(IsValidCASEAuthTag(static_cast<CASEAuthTag>(rdn[i].mChipVal)), CHIP_ERROR_WRONG_CERT_DN);
665 41 : catsPresent = true;
666 : }
667 : }
668 :
669 3113 : if (lCertType == CertType::kNode)
670 : {
671 1109 : VerifyOrReturnError(fabricIdPresent, CHIP_ERROR_WRONG_CERT_DN);
672 : }
673 : else
674 : {
675 2004 : VerifyOrReturnError(!catsPresent, CHIP_ERROR_WRONG_CERT_DN);
676 : }
677 :
678 3106 : if (lCertType == CertType::kVidVerificationSigner)
679 : {
680 9 : VerifyOrReturnError(!fabricIdPresent, CHIP_ERROR_WRONG_CERT_DN);
681 : // Lack of NodeID already checked since presence of NodeID will be detected as CertType::kNode.
682 : }
683 :
684 3106 : certType = lCertType;
685 :
686 3106 : return CHIP_NO_ERROR;
687 : }
688 :
689 13 : CHIP_ERROR ChipDN::GetCertChipId(uint64_t & chipId) const
690 : {
691 13 : uint8_t rdnCount = RDNCount();
692 13 : bool foundId = false;
693 :
694 13 : chipId = 0;
695 :
696 38 : for (uint8_t i = 0; i < rdnCount; i++)
697 : {
698 25 : switch (rdn[i].mAttrOID)
699 : {
700 12 : case kOID_AttributeType_MatterRCACId:
701 : case kOID_AttributeType_MatterICACId:
702 : case kOID_AttributeType_MatterNodeId:
703 : case kOID_AttributeType_MatterFirmwareSigningId:
704 : case kOID_AttributeType_MatterVidVerificationSignerId:
705 12 : VerifyOrReturnError(!foundId, CHIP_ERROR_WRONG_CERT_DN);
706 :
707 12 : chipId = rdn[i].mChipVal;
708 12 : foundId = true;
709 12 : break;
710 13 : default:
711 13 : break;
712 : }
713 : }
714 :
715 13 : VerifyOrReturnError(foundId, CHIP_ERROR_WRONG_CERT_DN);
716 12 : return CHIP_NO_ERROR;
717 : }
718 :
719 1 : CHIP_ERROR ChipDN::GetCertFabricId(uint64_t & fabricId) const
720 : {
721 1 : uint8_t rdnCount = RDNCount();
722 :
723 1 : fabricId = kUndefinedFabricId;
724 :
725 6 : for (uint8_t i = 0; i < rdnCount; i++)
726 : {
727 5 : switch (rdn[i].mAttrOID)
728 : {
729 1 : case kOID_AttributeType_MatterFabricId:
730 : // Ensure only one FabricID RDN present, since start value is kUndefinedFabricId, which is reserved and never seen.
731 1 : VerifyOrReturnError(fabricId == kUndefinedFabricId, CHIP_ERROR_WRONG_CERT_DN);
732 1 : VerifyOrReturnError(IsValidFabricId(rdn[i].mChipVal), CHIP_ERROR_WRONG_CERT_DN);
733 1 : fabricId = rdn[i].mChipVal;
734 1 : break;
735 4 : default:
736 4 : break;
737 : }
738 : }
739 :
740 1 : VerifyOrReturnError(IsValidFabricId(fabricId), CHIP_ERROR_WRONG_CERT_DN);
741 1 : return CHIP_NO_ERROR;
742 : }
743 :
744 308 : CHIP_ERROR ChipDN::EncodeToTLV(TLVWriter & writer, Tag tag) const
745 : {
746 : TLVType outerContainer;
747 308 : uint8_t rdnCount = RDNCount();
748 :
749 308 : ReturnErrorOnFailure(writer.StartContainer(tag, kTLVType_List, outerContainer));
750 :
751 803 : for (uint8_t i = 0; i < rdnCount; i++)
752 : {
753 : // Derive the TLV tag number from the enum value assigned to the attribute type OID. For attributes that can be
754 : // either UTF8String or PrintableString, use the high bit in the tag number to distinguish the two.
755 496 : uint8_t tlvTagNum = GetOIDEnum(rdn[i].mAttrOID);
756 496 : if (rdn[i].mAttrIsPrintableString)
757 : {
758 3 : tlvTagNum |= 0x80;
759 : }
760 :
761 496 : if (IsChipDNAttr(rdn[i].mAttrOID))
762 : {
763 469 : ReturnErrorOnFailure(writer.Put(ContextTag(tlvTagNum), rdn[i].mChipVal));
764 : }
765 : else
766 : {
767 27 : ReturnErrorOnFailure(writer.PutString(ContextTag(tlvTagNum), rdn[i].mString));
768 : }
769 : }
770 :
771 307 : return writer.EndContainer(outerContainer);
772 : }
773 :
774 5992 : CHIP_ERROR ChipDN::DecodeFromTLV(TLVReader & reader)
775 : {
776 : CHIP_ERROR err;
777 : TLVType outerContainer;
778 :
779 : static constexpr uint32_t kOID_AttributeIsPrintableString_Flag = 0x00000080;
780 : static constexpr uint32_t kOID_AttributeType_Mask = 0x0000007F;
781 :
782 5992 : VerifyOrReturnError(reader.GetType() == kTLVType_List, CHIP_ERROR_WRONG_TLV_TYPE);
783 :
784 : // Enter the List TLV element that represents the DN in TLV format.
785 5992 : ReturnErrorOnFailure(reader.EnterContainer(outerContainer));
786 :
787 : // Read the RDN attributes in the List.
788 15741 : while ((err = reader.Next()) == CHIP_NO_ERROR)
789 : {
790 : // Get the TLV tag, make sure it is a context tag and extract the context tag number.
791 9770 : Tag tlvTag = reader.GetTag();
792 9791 : VerifyOrReturnError(IsContextTag(tlvTag), CHIP_ERROR_INVALID_TLV_TAG);
793 9770 : uint32_t tlvTagNum = TagNumFromTag(tlvTag);
794 :
795 : // Derive the OID of the corresponding ASN.1 attribute from the TLV tag number.
796 : // The numeric value of the OID is encoded in the bottom 7 bits of the TLV tag number.
797 : // This eliminates the need for a translation table/switch statement but has the
798 : // effect of tying the two encodings together.
799 : //
800 : // NOTE: In the event that the computed OID value is not one that we recognize
801 : // (specifically, is not in the table of OIDs defined in ASN1OID.h) then the
802 : // macro call below that encodes the attribute's object id (ASN1_ENCODE_OBJECT_ID)
803 : // will fail for lack of the OID's encoded representation. Given this there's no
804 : // need to test the validity of the OID here.
805 : //
806 9770 : OID attrOID = GetOID(kOIDCategory_AttributeType, static_cast<uint8_t>(tlvTagNum & kOID_AttributeType_Mask));
807 :
808 9770 : bool attrIsPrintableString = (tlvTagNum & kOID_AttributeIsPrintableString_Flag) == kOID_AttributeIsPrintableString_Flag;
809 :
810 : // For 64-bit CHIP-defined DN attributes.
811 9770 : if (IsChip64bitDNAttr(attrOID))
812 : {
813 : uint64_t chipAttr;
814 9560 : VerifyOrReturnError(attrIsPrintableString == false, CHIP_ERROR_INVALID_TLV_TAG);
815 9549 : ReturnErrorOnFailure(reader.Get(chipAttr));
816 9549 : if (attrOID == chip::ASN1::kOID_AttributeType_MatterNodeId)
817 : {
818 1090 : VerifyOrReturnError(IsOperationalNodeId(chipAttr), CHIP_ERROR_WRONG_NODE_ID);
819 : }
820 8459 : else if (attrOID == chip::ASN1::kOID_AttributeType_MatterFabricId)
821 : {
822 3584 : VerifyOrReturnError(IsValidFabricId(chipAttr), CHIP_ERROR_INVALID_ARGUMENT);
823 : }
824 9538 : ReturnErrorOnFailure(AddAttribute(attrOID, chipAttr));
825 : }
826 : // For 32-bit CHIP-defined DN attributes.
827 221 : else if (IsChip32bitDNAttr(attrOID))
828 : {
829 : uint32_t chipAttr;
830 134 : VerifyOrReturnError(attrIsPrintableString == false, CHIP_ERROR_INVALID_TLV_TAG);
831 124 : ReturnErrorOnFailure(reader.Get(chipAttr));
832 124 : if (attrOID == chip::ASN1::kOID_AttributeType_MatterCASEAuthTag)
833 : {
834 124 : VerifyOrReturnError(IsValidCASEAuthTag(chipAttr), CHIP_ERROR_INVALID_ARGUMENT);
835 : }
836 114 : ReturnErrorOnFailure(AddAttribute(attrOID, chipAttr));
837 : }
838 : // Otherwise the attribute is one of the supported X.509 attributes
839 : else
840 : {
841 97 : CharSpan asn1Attr;
842 97 : ReturnErrorOnFailure(reader.Get(asn1Attr));
843 97 : ReturnErrorOnFailure(AddAttribute(attrOID, asn1Attr, attrIsPrintableString));
844 : }
845 : }
846 5971 : VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
847 5971 : ReturnErrorOnFailure(reader.ExitContainer(outerContainer));
848 :
849 5971 : return CHIP_NO_ERROR;
850 : }
851 :
852 6401 : CHIP_ERROR ChipDN::EncodeToASN1(ASN1Writer & writer) const
853 : {
854 6401 : CHIP_ERROR err = CHIP_NO_ERROR;
855 6401 : uint8_t rdnCount = RDNCount();
856 :
857 6401 : ASN1_START_SEQUENCE
858 : {
859 16780 : for (uint8_t i = 0; i < rdnCount; i++)
860 : {
861 10380 : ASN1_START_SET
862 : {
863 : char chipAttrStr[kChip64bitAttrUTF8Length];
864 10380 : CharSpan asn1Attr;
865 : uint8_t asn1Tag;
866 10380 : chip::ASN1::OID attrOID = rdn[i].mAttrOID;
867 :
868 10380 : if (IsChip64bitDNAttr(attrOID))
869 : {
870 10136 : ReturnErrorOnFailure(
871 : Encoding::Uint64ToHex(rdn[i].mChipVal, chipAttrStr, sizeof(chipAttrStr), Encoding::HexFlags::kUppercase));
872 10136 : asn1Attr = CharSpan(chipAttrStr, kChip64bitAttrUTF8Length);
873 10136 : asn1Tag = kASN1UniversalTag_UTF8String;
874 : }
875 244 : else if (IsChip32bitDNAttr(attrOID))
876 : {
877 121 : ReturnErrorOnFailure(Encoding::Uint32ToHex(static_cast<uint32_t>(rdn[i].mChipVal), chipAttrStr,
878 : sizeof(chipAttrStr), Encoding::HexFlags::kUppercase));
879 121 : asn1Attr = CharSpan(chipAttrStr, kChip32bitAttrUTF8Length);
880 121 : asn1Tag = kASN1UniversalTag_UTF8String;
881 : }
882 : else
883 : {
884 123 : asn1Attr = rdn[i].mString;
885 :
886 : // Determine the appropriate ASN.1 tag for the DN attribute.
887 : // - DomainComponent is always an IA5String.
888 : // - For all other ASN.1 defined attributes, bit 0x80 in the TLV tag value conveys whether the attribute
889 : // is a UTF8String or a PrintableString (in some cases the certificate generator has a choice).
890 123 : if (attrOID == kOID_AttributeType_DomainComponent)
891 : {
892 0 : asn1Tag = kASN1UniversalTag_IA5String;
893 : }
894 : else
895 : {
896 123 : asn1Tag = rdn[i].mAttrIsPrintableString ? kASN1UniversalTag_PrintableString : kASN1UniversalTag_UTF8String;
897 : }
898 : }
899 :
900 : // AttributeTypeAndValue ::= SEQUENCE
901 10380 : ASN1_START_SEQUENCE
902 : {
903 : // type AttributeType
904 : // AttributeType ::= OBJECT IDENTIFIER
905 10380 : ASN1_ENCODE_OBJECT_ID(attrOID);
906 :
907 10380 : VerifyOrReturnError(CanCastTo<uint16_t>(asn1Attr.size()), CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
908 :
909 : // value AttributeValue
910 : // AttributeValue ::= ANY -- DEFINED BY AttributeType
911 10380 : ReturnErrorOnFailure(writer.PutString(asn1Tag, asn1Attr.data(), static_cast<uint16_t>(asn1Attr.size())));
912 : }
913 10379 : ASN1_END_SEQUENCE;
914 : }
915 10379 : ASN1_END_SET;
916 : }
917 : }
918 6400 : ASN1_END_SEQUENCE;
919 :
920 6400 : exit:
921 6400 : return err;
922 : }
923 :
924 325 : CHIP_ERROR ChipDN::DecodeFromASN1(ASN1Reader & reader)
925 : {
926 : CHIP_ERROR err;
927 :
928 : // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
929 325 : ASN1_PARSE_ENTER_SEQUENCE
930 : {
931 844 : while ((err = reader.Next()) == CHIP_NO_ERROR)
932 : {
933 : // RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
934 526 : ASN1_ENTER_SET
935 : {
936 : // AttributeTypeAndValue ::= SEQUENCE
937 526 : ASN1_PARSE_ENTER_SEQUENCE
938 : {
939 : // type AttributeType
940 : // AttributeType ::= OBJECT IDENTIFIER
941 : OID attrOID;
942 526 : ASN1_PARSE_OBJECT_ID(attrOID);
943 533 : VerifyOrReturnError(GetOIDCategory(attrOID) == kOIDCategory_AttributeType, ASN1_ERROR_INVALID_ENCODING);
944 :
945 : // AttributeValue ::= ANY -- DEFINED BY AttributeType
946 526 : ASN1_PARSE_ANY;
947 :
948 526 : uint8_t attrTag = reader.GetTag();
949 :
950 : // Can only support UTF8String, PrintableString and IA5String.
951 526 : VerifyOrReturnError(reader.GetClass() == kASN1TagClass_Universal &&
952 : (attrTag == kASN1UniversalTag_PrintableString ||
953 : attrTag == kASN1UniversalTag_UTF8String || attrTag == kASN1UniversalTag_IA5String),
954 : ASN1_ERROR_UNSUPPORTED_ENCODING);
955 :
956 : // CHIP attributes must be UTF8Strings.
957 526 : if (IsChipDNAttr(attrOID))
958 : {
959 497 : VerifyOrReturnError(attrTag == kASN1UniversalTag_UTF8String, ASN1_ERROR_INVALID_ENCODING);
960 : }
961 :
962 : // If 64-bit CHIP attribute.
963 526 : if (IsChip64bitDNAttr(attrOID))
964 : {
965 : uint64_t chipAttr;
966 488 : VerifyOrReturnError(Encoding::UppercaseHexToUint64(reinterpret_cast<const char *>(reader.GetValue()),
967 : static_cast<size_t>(reader.GetValueLen()),
968 : chipAttr) == sizeof(uint64_t),
969 : ASN1_ERROR_INVALID_ENCODING);
970 :
971 484 : if (attrOID == chip::ASN1::kOID_AttributeType_MatterNodeId)
972 : {
973 67 : VerifyOrReturnError(IsOperationalNodeId(chipAttr), CHIP_ERROR_WRONG_NODE_ID);
974 : }
975 417 : else if (attrOID == chip::ASN1::kOID_AttributeType_MatterFabricId)
976 : {
977 165 : VerifyOrReturnError(IsValidFabricId(chipAttr), CHIP_ERROR_WRONG_CERT_DN);
978 : }
979 :
980 480 : ReturnErrorOnFailure(AddAttribute(attrOID, chipAttr));
981 : }
982 : // If 32-bit CHIP attribute.
983 42 : else if (IsChip32bitDNAttr(attrOID))
984 : {
985 : CASEAuthTag chipAttr;
986 16 : VerifyOrReturnError(Encoding::UppercaseHexToUint32(reinterpret_cast<const char *>(reader.GetValue()),
987 : reader.GetValueLen(), chipAttr) == sizeof(CASEAuthTag),
988 : ASN1_ERROR_INVALID_ENCODING);
989 :
990 13 : VerifyOrReturnError(IsValidCASEAuthTag(chipAttr), CHIP_ERROR_WRONG_CERT_DN);
991 :
992 10 : ReturnErrorOnFailure(AddAttribute(attrOID, chipAttr));
993 : }
994 : // Otherwise, it is a string.
995 : else
996 : {
997 29 : ReturnErrorOnFailure(AddAttribute(attrOID,
998 : CharSpan(Uint8::to_const_char(reader.GetValue()), reader.GetValueLen()),
999 : attrTag == kASN1UniversalTag_PrintableString));
1000 : }
1001 : }
1002 519 : ASN1_EXIT_SEQUENCE;
1003 :
1004 : // Only one AttributeTypeAndValue allowed per RDN.
1005 519 : err = reader.Next();
1006 519 : VerifyOrReturnError(err != CHIP_NO_ERROR, ASN1_ERROR_UNSUPPORTED_ENCODING);
1007 519 : VerifyOrReturnError(err == ASN1_END, err);
1008 : }
1009 519 : ASN1_EXIT_SET;
1010 : }
1011 : }
1012 318 : ASN1_EXIT_SEQUENCE;
1013 :
1014 318 : exit:
1015 318 : return err;
1016 : }
1017 :
1018 9067 : bool ChipDN::IsEqual(const ChipDN & other) const
1019 : {
1020 9067 : bool res = true;
1021 9067 : uint8_t rdnCount = RDNCount();
1022 :
1023 9067 : VerifyOrExit(rdnCount > 0, res = false);
1024 9067 : VerifyOrExit(rdnCount == other.RDNCount(), res = false);
1025 :
1026 8546 : for (uint8_t i = 0; i < rdnCount; i++)
1027 : {
1028 5996 : VerifyOrExit(rdn[i].IsEqual(other.rdn[i]), res = false);
1029 : }
1030 :
1031 2550 : exit:
1032 9067 : return res;
1033 : }
1034 :
1035 445 : DLL_EXPORT CHIP_ERROR ASN1ToChipEpochTime(const chip::ASN1::ASN1UniversalTime & asn1Time, uint32_t & epochTime)
1036 : {
1037 445 : CHIP_ERROR err = CHIP_NO_ERROR;
1038 : // X.509/RFC5280 defines the special time 99991231235959Z to mean 'no well-defined expiration date'.
1039 : // In CHIP certificate it is represented as a CHIP Epoch time value of 0 sec (2000-01-01 00:00:00 UTC).
1040 : //
1041 : // While it is not conventional to use this special value for NotBefore, for simplicity we convert all
1042 : // time values of 99991231235959Z to CHIP epoch zero seconds. ChipEpochToASN1Time performs the inverse
1043 : // translation for conversions in the other direction.
1044 : //
1045 : // If in a conversion from X509 to CHIP TLV format the input X509 certificate encloses 99991231235959Z
1046 : // for NotBefore, this will be converted to the CHIP Epoch time value of 0 and consuming code will
1047 : // handle this transparently, as logic considering a NotBefore time at the CHIP epoch will evaluate all
1048 : // possible unsigned offsets from the CHIP epoch as valid, which is equivalent to ignoring NotBefore.
1049 : //
1050 : // If in a conversion from X509 to CHIP TLV format the input X509 certificate encloses a NotBefore time
1051 : // at the CHIP epoch itself, 2000-01-01 00:00:00, a resultant conversion to CHIP TLV certificate format
1052 : // will appear to have an invalid TBS signature when the symmetric ChipEpochToASN1Time produces
1053 : // 99991231235959Z for NotBefore during signature validation.
1054 : //
1055 : // Thus such certificates, when passing through this code, will not appear valid. This should be
1056 : // immediately evident at commissioning time.
1057 445 : if ((asn1Time.Year == kX509NoWellDefinedExpirationDateYear) && (asn1Time.Month == kMonthsPerYear) &&
1058 4 : (asn1Time.Day == kMaxDaysPerMonth) && (asn1Time.Hour == kHoursPerDay - 1) && (asn1Time.Minute == kMinutesPerHour - 1) &&
1059 4 : (asn1Time.Second == kSecondsPerMinute - 1))
1060 : {
1061 4 : epochTime = kNullCertTime;
1062 : }
1063 : else
1064 : {
1065 441 : if (!CalendarToChipEpochTime(asn1Time.Year, asn1Time.Month, asn1Time.Day, asn1Time.Hour, asn1Time.Minute, asn1Time.Second,
1066 : epochTime))
1067 : {
1068 0 : ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
1069 : }
1070 : }
1071 :
1072 441 : exit:
1073 445 : return err;
1074 : }
1075 :
1076 6417 : DLL_EXPORT CHIP_ERROR ChipEpochToASN1Time(uint32_t epochTime, chip::ASN1::ASN1UniversalTime & asn1Time)
1077 : {
1078 : // X.509/RFC5280 defines the special time 99991231235959Z to mean 'no well-defined expiration date'.
1079 : // In CHIP certificate it is represented as a CHIP Epoch time value of 0 secs (2000-01-01 00:00:00 UTC).
1080 : //
1081 : // For simplicity and symmetry with ASN1ToChipEpochTime, this method makes this conversion for all
1082 : // times, which in consuming code can create a conversion from CHIP epoch 0 seconds to 99991231235959Z
1083 : // for NotBefore, which is not conventional.
1084 : //
1085 : // If an original X509 certificate encloses a NotBefore time that is the CHIP Epoch itself, 2000-01-01
1086 : // 00:00:00, the resultant X509 certificate in a conversion back from CHIP TLV format using this time
1087 : // conversion method will instead enclose the NotBefore time 99991231235959Z, which will invalidiate the
1088 : // TBS signature. Thus, certificates with this specific attribute are not usable with this code.
1089 : // Attempted installation of such certficates will fail during commissioning.
1090 6417 : if (epochTime == kNullCertTime)
1091 : {
1092 19 : asn1Time.Year = kX509NoWellDefinedExpirationDateYear;
1093 19 : asn1Time.Month = kMonthsPerYear;
1094 19 : asn1Time.Day = kMaxDaysPerMonth;
1095 19 : asn1Time.Hour = kHoursPerDay - 1;
1096 19 : asn1Time.Minute = kMinutesPerHour - 1;
1097 19 : asn1Time.Second = kSecondsPerMinute - 1;
1098 : }
1099 : else
1100 : {
1101 6398 : ChipEpochToCalendarTime(epochTime, asn1Time.Year, asn1Time.Month, asn1Time.Day, asn1Time.Hour, asn1Time.Minute,
1102 6398 : asn1Time.Second);
1103 : }
1104 :
1105 6417 : return CHIP_NO_ERROR;
1106 : }
1107 :
1108 52 : static CHIP_ERROR ValidateCertificateType(const ChipCertificateData & certData, CertType expectedType)
1109 : {
1110 : CertType certType;
1111 52 : ReturnErrorOnFailure(certData.mSubjectDN.GetCertType(certType));
1112 44 : VerifyOrReturnError(certType == expectedType, CHIP_ERROR_WRONG_CERT_TYPE);
1113 18 : return CHIP_NO_ERROR;
1114 : }
1115 :
1116 92 : CHIP_ERROR ValidateChipRCAC(const ByteSpan & rcac)
1117 : {
1118 92 : ChipCertificateSet certSet;
1119 92 : ChipCertificateData certData;
1120 92 : ValidationContext validContext;
1121 :
1122 : // Note that this function doesn't check RCAC NotBefore / NotAfter time validity.
1123 : // It is assumed that RCAC should be valid at the time of installation by definition.
1124 :
1125 92 : ReturnErrorOnFailure(certSet.Init(&certData, 1));
1126 :
1127 92 : ReturnErrorOnFailure(certSet.LoadCert(rcac, CertDecodeFlags::kGenerateTBSHash));
1128 :
1129 44 : ReturnErrorOnFailure(ValidateCertificateType(certData, CertType::kRoot));
1130 :
1131 10 : VerifyOrReturnError(certData.mSubjectDN.IsEqual(certData.mIssuerDN), CHIP_ERROR_WRONG_CERT_TYPE);
1132 :
1133 10 : VerifyOrReturnError(certData.mSubjectKeyId.data_equal(certData.mAuthKeyId), CHIP_ERROR_WRONG_CERT_TYPE);
1134 :
1135 9 : VerifyOrReturnError(certData.mCertFlags.Has(CertFlags::kIsCA), CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
1136 7 : if (certData.mCertFlags.Has(CertFlags::kPathLenConstraintPresent))
1137 : {
1138 1 : VerifyOrReturnError(certData.mPathLenConstraint <= 1, CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
1139 : }
1140 :
1141 7 : VerifyOrReturnError(certData.mKeyUsageFlags.Has(KeyUsageFlags::kKeyCertSign), CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
1142 :
1143 5 : return VerifyCertSignature(certData, certData);
1144 92 : }
1145 :
1146 240 : CHIP_ERROR ConvertIntegerDERToRaw(ByteSpan derInt, uint8_t * rawInt, const uint16_t rawIntLen)
1147 : {
1148 240 : VerifyOrReturnError(!derInt.empty(), CHIP_ERROR_INVALID_ARGUMENT);
1149 240 : VerifyOrReturnError(rawInt != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
1150 :
1151 240 : const uint8_t * derIntData = derInt.data();
1152 240 : size_t derIntLen = derInt.size();
1153 :
1154 : /* one leading zero is allowed for positive integer in ASN1 DER format */
1155 240 : if (*derIntData == 0)
1156 : {
1157 129 : derIntData++;
1158 129 : derIntLen--;
1159 : }
1160 :
1161 240 : VerifyOrReturnError(derIntLen <= rawIntLen, CHIP_ERROR_INVALID_ARGUMENT);
1162 :
1163 240 : if (derIntLen > 0)
1164 : {
1165 240 : VerifyOrReturnError(*derIntData != 0, CHIP_ERROR_INVALID_ARGUMENT);
1166 : }
1167 :
1168 240 : memset(rawInt, 0, (rawIntLen - derIntLen));
1169 240 : memcpy(rawInt + (rawIntLen - derIntLen), derIntData, derIntLen);
1170 :
1171 240 : return CHIP_NO_ERROR;
1172 : }
1173 :
1174 0 : CHIP_ERROR ConvertECDSASignatureRawToDER(P256ECDSASignatureSpan rawSig, MutableByteSpan & derSig)
1175 : {
1176 0 : VerifyOrReturnError(derSig.size() >= kMax_ECDSA_Signature_Length_Der, CHIP_ERROR_BUFFER_TOO_SMALL);
1177 :
1178 : ASN1Writer writer;
1179 0 : writer.Init(derSig);
1180 0 : ReturnErrorOnFailure(ConvertECDSASignatureRawToDER(rawSig, writer));
1181 0 : derSig.reduce_size(writer.GetLengthWritten());
1182 :
1183 0 : return CHIP_NO_ERROR;
1184 : }
1185 :
1186 125 : CHIP_ERROR ConvertECDSASignatureRawToDER(P256ECDSASignatureSpan rawSig, ASN1Writer & writer)
1187 : {
1188 125 : CHIP_ERROR err = CHIP_NO_ERROR;
1189 : uint8_t derInt[kP256_FE_Length + kEmitDerIntegerWithoutTagOverhead];
1190 :
1191 : // Ecdsa-Sig-Value ::= SEQUENCE
1192 125 : ASN1_START_SEQUENCE
1193 : {
1194 : // r INTEGER
1195 : {
1196 125 : MutableByteSpan derIntSpan(derInt, sizeof(derInt));
1197 125 : ReturnErrorOnFailure(ConvertIntegerRawToDerWithoutTag(P256IntegerSpan(rawSig.data()), derIntSpan));
1198 125 : ReturnErrorOnFailure(writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, derIntSpan.data(),
1199 : static_cast<uint16_t>(derIntSpan.size())));
1200 : }
1201 :
1202 : // s INTEGER
1203 : {
1204 125 : MutableByteSpan derIntSpan(derInt, sizeof(derInt));
1205 125 : ReturnErrorOnFailure(ConvertIntegerRawToDerWithoutTag(P256IntegerSpan(rawSig.data() + kP256_FE_Length), derIntSpan));
1206 125 : ReturnErrorOnFailure(writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, derIntSpan.data(),
1207 : static_cast<uint16_t>(derIntSpan.size())));
1208 : }
1209 : }
1210 125 : ASN1_END_SEQUENCE;
1211 :
1212 125 : exit:
1213 125 : return err;
1214 : }
1215 :
1216 1 : CHIP_ERROR ConvertECDSAKeypairRawToDER(const P256SerializedKeypair & rawKeypair, MutableByteSpan & outDerKeypair)
1217 : {
1218 1 : CHIP_ERROR err = CHIP_NO_ERROR;
1219 :
1220 : // The raw key pair contains the public key followed by the private key
1221 1 : VerifyOrReturnError(rawKeypair.Length() == kP256_PublicKey_Length + kP256_PrivateKey_Length, CHIP_ERROR_INVALID_ARGUMENT);
1222 1 : FixedByteSpan<kP256_PublicKey_Length> publicKey(rawKeypair.ConstBytes());
1223 1 : FixedByteSpan<kP256_PrivateKey_Length> privateKey(rawKeypair.ConstBytes() + kP256_PublicKey_Length);
1224 :
1225 : ASN1Writer writer;
1226 1 : writer.Init(outDerKeypair);
1227 :
1228 : // ECPrivateKey ::= SEQUENCE
1229 1 : ASN1_START_SEQUENCE
1230 : {
1231 : // version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1)
1232 1 : ASN1_ENCODE_INTEGER(1);
1233 :
1234 : // privateKey OCTET STRING
1235 1 : ASN1_ENCODE_OCTET_STRING(privateKey.data(), privateKey.size());
1236 :
1237 : // parameters [0] ECParameters {{ NamedCurve }} OPTIONAL
1238 1 : ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0);
1239 : {
1240 1 : ASN1_ENCODE_OBJECT_ID(kOID_EllipticCurve_prime256v1);
1241 : }
1242 1 : ASN1_END_CONSTRUCTED;
1243 :
1244 : // publicKey [1] BIT STRING OPTIONAL
1245 1 : ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 1);
1246 : {
1247 1 : ReturnErrorOnFailure(writer.PutBitString(0, publicKey.data(), publicKey.size()));
1248 : }
1249 1 : ASN1_END_CONSTRUCTED;
1250 : }
1251 1 : ASN1_END_SEQUENCE;
1252 :
1253 1 : outDerKeypair.reduce_size(writer.GetLengthWritten());
1254 1 : exit:
1255 1 : return err;
1256 : }
1257 :
1258 889 : CHIP_ERROR ExtractNodeIdFabricIdFromOpCert(const ChipCertificateData & opcert, NodeId * outNodeId, FabricId * outFabricId)
1259 : {
1260 : // Since we assume the cert is pre-validated, we are going to assume that
1261 : // its subject in fact has both a node id and a fabric id.
1262 889 : VerifyOrReturnError(outNodeId != nullptr && outFabricId != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
1263 889 : NodeId nodeId = 0;
1264 889 : FabricId fabricId = kUndefinedFabricId;
1265 889 : bool foundNodeId = false;
1266 889 : bool foundFabricId = false;
1267 :
1268 889 : const ChipDN & subjectDN = opcert.mSubjectDN;
1269 2711 : for (uint8_t i = 0; i < subjectDN.RDNCount(); ++i)
1270 : {
1271 1822 : const auto & rdn = subjectDN.rdn[i];
1272 1822 : if (rdn.mAttrOID == ASN1::kOID_AttributeType_MatterNodeId)
1273 : {
1274 889 : nodeId = rdn.mChipVal;
1275 889 : foundNodeId = true;
1276 : }
1277 933 : else if (rdn.mAttrOID == ASN1::kOID_AttributeType_MatterFabricId)
1278 : {
1279 889 : fabricId = rdn.mChipVal;
1280 889 : foundFabricId = true;
1281 : }
1282 : }
1283 889 : if (!foundNodeId || !foundFabricId)
1284 : {
1285 0 : return CHIP_ERROR_NOT_FOUND;
1286 : }
1287 :
1288 889 : *outNodeId = nodeId;
1289 889 : *outFabricId = fabricId;
1290 889 : return CHIP_NO_ERROR;
1291 : }
1292 :
1293 10 : CHIP_ERROR ExtractNodeIdFabricIdCompressedFabricIdFromOpCerts(ByteSpan rcac, ByteSpan noc, CompressedFabricId & compressedFabricId,
1294 : FabricId & fabricId, NodeId & nodeId)
1295 : {
1296 10 : Crypto::P256PublicKey rootPubKey;
1297 10 : Credentials::P256PublicKeySpan rootPubKeySpan;
1298 10 : ReturnErrorOnFailure(ExtractPublicKeyFromChipCert(rcac, rootPubKeySpan));
1299 10 : rootPubKey = Crypto::P256PublicKey(rootPubKeySpan);
1300 10 : ReturnErrorOnFailure(Credentials::ExtractNodeIdFabricIdFromOpCert(noc, &nodeId, &fabricId));
1301 10 : ReturnErrorOnFailure(GenerateCompressedFabricId(rootPubKey, fabricId, compressedFabricId));
1302 10 : return CHIP_NO_ERROR;
1303 10 : }
1304 :
1305 0 : CHIP_ERROR ExtractNodeIdCompressedFabricIdFromOpCerts(ByteSpan rcac, ByteSpan noc, CompressedFabricId & compressedFabricId,
1306 : NodeId & nodeId)
1307 : {
1308 : FabricId fabricId;
1309 0 : ReturnErrorOnFailure(ExtractNodeIdFabricIdCompressedFabricIdFromOpCerts(rcac, noc, compressedFabricId, fabricId, nodeId));
1310 0 : return CHIP_NO_ERROR;
1311 : }
1312 :
1313 1545 : CHIP_ERROR ExtractFabricIdFromCert(const ChipCertificateData & cert, FabricId * fabricId)
1314 : {
1315 1545 : const ChipDN & subjectDN = cert.mSubjectDN;
1316 3078 : for (uint8_t i = 0; i < subjectDN.RDNCount(); ++i)
1317 : {
1318 2274 : const auto & rdn = subjectDN.rdn[i];
1319 2274 : if (rdn.mAttrOID == ASN1::kOID_AttributeType_MatterFabricId)
1320 : {
1321 741 : *fabricId = rdn.mChipVal;
1322 741 : return CHIP_NO_ERROR;
1323 : }
1324 : }
1325 :
1326 804 : return CHIP_ERROR_NOT_FOUND;
1327 : }
1328 :
1329 33 : CHIP_ERROR ExtractCATsFromOpCert(const ByteSpan & opcert, CATValues & cats)
1330 : {
1331 33 : ChipCertificateSet certSet;
1332 33 : ChipCertificateData certData;
1333 :
1334 33 : ReturnErrorOnFailure(certSet.Init(&certData, 1));
1335 :
1336 33 : ReturnErrorOnFailure(certSet.LoadCert(opcert, BitFlags<CertDecodeFlags>()));
1337 :
1338 32 : return ExtractCATsFromOpCert(certData, cats);
1339 33 : }
1340 :
1341 43 : CHIP_ERROR ExtractCATsFromOpCert(const ChipCertificateData & opcert, CATValues & cats)
1342 : {
1343 43 : uint8_t catCount = 0;
1344 : CertType certType;
1345 :
1346 43 : ReturnErrorOnFailure(opcert.mSubjectDN.GetCertType(certType));
1347 43 : VerifyOrReturnError(certType == CertType::kNode, CHIP_ERROR_INVALID_ARGUMENT);
1348 :
1349 42 : const ChipDN & subjectDN = opcert.mSubjectDN;
1350 150 : for (uint8_t i = 0; i < subjectDN.RDNCount(); ++i)
1351 : {
1352 108 : const auto & rdn = subjectDN.rdn[i];
1353 108 : if (rdn.mAttrOID == ASN1::kOID_AttributeType_MatterCASEAuthTag)
1354 : {
1355 : // This error should never happen in practice because valid NOC cannot have more
1356 : // than kMaxSubjectCATAttributeCount CATs in its subject. The check that it is
1357 : // valid NOC was done above.
1358 18 : VerifyOrReturnError(catCount != cats.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
1359 18 : VerifyOrReturnError(CanCastTo<CASEAuthTag>(rdn.mChipVal), CHIP_ERROR_INVALID_ARGUMENT);
1360 18 : cats.values[catCount++] = static_cast<CASEAuthTag>(rdn.mChipVal);
1361 : }
1362 : }
1363 150 : for (size_t i = catCount; i < cats.size(); ++i)
1364 : {
1365 108 : cats.values[i] = kUndefinedCAT;
1366 : }
1367 :
1368 : // Make sure the set contained valid data, otherwise it's an invalid cert
1369 42 : VerifyOrReturnError(cats.AreValid(), CHIP_ERROR_WRONG_CERT_DN);
1370 :
1371 41 : return CHIP_NO_ERROR;
1372 : }
1373 :
1374 11 : CHIP_ERROR ExtractFabricIdFromCert(const ByteSpan & opcert, FabricId * fabricId)
1375 : {
1376 11 : ChipCertificateData certData;
1377 11 : ReturnErrorOnFailure(DecodeChipCert(opcert, certData));
1378 11 : return ExtractFabricIdFromCert(certData, fabricId);
1379 11 : }
1380 :
1381 106 : CHIP_ERROR ExtractNodeIdFabricIdFromOpCert(const ByteSpan & opcert, NodeId * nodeId, FabricId * fabricId)
1382 : {
1383 106 : ChipCertificateData certData;
1384 106 : ReturnErrorOnFailure(DecodeChipCert(opcert, certData));
1385 106 : return ExtractNodeIdFabricIdFromOpCert(certData, nodeId, fabricId);
1386 106 : }
1387 :
1388 103 : CHIP_ERROR ExtractPublicKeyFromChipCert(const ByteSpan & chipCert, P256PublicKeySpan & publicKey)
1389 : {
1390 103 : ChipCertificateData certData;
1391 103 : ReturnErrorOnFailure(DecodeChipCert(chipCert, certData));
1392 103 : publicKey = certData.mPublicKey;
1393 103 : return CHIP_NO_ERROR;
1394 103 : }
1395 :
1396 24 : CHIP_ERROR ExtractNotBeforeFromChipCert(const ByteSpan & chipCert, chip::System::Clock::Seconds32 & notBeforeChipEpochTime)
1397 : {
1398 24 : ChipCertificateData certData;
1399 24 : ReturnErrorOnFailure(DecodeChipCert(chipCert, certData));
1400 24 : notBeforeChipEpochTime = chip::System::Clock::Seconds32(certData.mNotBeforeTime);
1401 24 : return CHIP_NO_ERROR;
1402 24 : }
1403 :
1404 16 : CHIP_ERROR ExtractSKIDFromChipCert(const ByteSpan & chipCert, CertificateKeyId & skid)
1405 : {
1406 16 : ChipCertificateData certData;
1407 16 : ReturnErrorOnFailure(DecodeChipCert(chipCert, certData));
1408 16 : VerifyOrReturnError(certData.mCertFlags.Has(CertFlags::kExtPresent_AuthKeyId), CHIP_ERROR_NOT_FOUND);
1409 15 : skid = certData.mSubjectKeyId;
1410 15 : return CHIP_NO_ERROR;
1411 16 : }
1412 :
1413 41 : CHIP_ERROR ExtractSubjectDNFromChipCert(const ByteSpan & chipCert, ChipDN & dn)
1414 : {
1415 41 : ChipCertificateData certData;
1416 41 : ReturnErrorOnFailure(DecodeChipCert(chipCert, certData));
1417 41 : dn = certData.mSubjectDN;
1418 41 : return CHIP_NO_ERROR;
1419 41 : }
1420 :
1421 10 : CHIP_ERROR ExtractSubjectDNFromX509Cert(const ByteSpan & x509Cert, ChipDN & dn)
1422 : {
1423 : CHIP_ERROR err;
1424 : ASN1Reader reader;
1425 :
1426 10 : VerifyOrReturnError(CanCastTo<uint32_t>(x509Cert.size()), CHIP_ERROR_INVALID_ARGUMENT);
1427 :
1428 10 : reader.Init(x509Cert);
1429 :
1430 : // Certificate ::= SEQUENCE
1431 10 : ASN1_PARSE_ENTER_SEQUENCE
1432 : {
1433 : // tbsCertificate TBSCertificate,
1434 : // TBSCertificate ::= SEQUENCE
1435 10 : ASN1_PARSE_ENTER_SEQUENCE
1436 : {
1437 : // Skip version [0] EXPLICIT Version DEFAULT v1
1438 10 : ASN1_PARSE_ELEMENT(kASN1TagClass_ContextSpecific, 0);
1439 :
1440 : // Skip serialNumber CertificateSerialNumber
1441 10 : ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer);
1442 :
1443 : // Skip signature AlgorithmIdentifier
1444 10 : ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Sequence);
1445 :
1446 : // Skip issuer Name
1447 10 : ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Sequence);
1448 :
1449 : // Skip validity Validity,
1450 10 : ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Sequence);
1451 :
1452 : // Decode subject Name,
1453 10 : ReturnErrorOnFailure(dn.DecodeFromASN1(reader));
1454 : }
1455 10 : ASN1_SKIP_AND_EXIT_SEQUENCE;
1456 : }
1457 10 : ASN1_SKIP_AND_EXIT_SEQUENCE;
1458 :
1459 10 : exit:
1460 10 : return err;
1461 : }
1462 :
1463 189 : CHIP_ERROR CertificateValidityPolicy::ApplyDefaultPolicy(const ChipCertificateData * cert, uint8_t depth,
1464 : CertificateValidityResult result)
1465 : {
1466 189 : switch (result)
1467 : {
1468 183 : case CertificateValidityResult::kValid:
1469 : case CertificateValidityResult::kNotExpiredAtLastKnownGoodTime:
1470 : // By default, we do not enforce certificate validity based upon a Last
1471 : // Known Good Time source. However, implementations may always inject a
1472 : // policy that does enforce based upon this.
1473 : case CertificateValidityResult::kExpiredAtLastKnownGoodTime:
1474 : case CertificateValidityResult::kTimeUnknown:
1475 183 : return CHIP_NO_ERROR;
1476 :
1477 3 : case CertificateValidityResult::kNotYetValid:
1478 3 : return CHIP_ERROR_CERT_NOT_VALID_YET;
1479 :
1480 3 : case CertificateValidityResult::kExpired:
1481 3 : return CHIP_ERROR_CERT_EXPIRED;
1482 :
1483 0 : default:
1484 0 : return CHIP_ERROR_INTERNAL;
1485 : }
1486 : }
1487 :
1488 15 : void InitNetworkIdentitySubject(ChipDN & name)
1489 : {
1490 15 : name.Clear();
1491 15 : CHIP_ERROR err = name.AddAttribute_CommonName(kNetworkIdentityCN, /* not printable */ false);
1492 15 : VerifyOrDie(err == CHIP_NO_ERROR); // AddAttribute can't fail in this case
1493 15 : }
1494 :
1495 4 : static CHIP_ERROR CalculateKeyIdentifierSha256(const P256PublicKeySpan & publicKey, MutableCertificateKeyId outKeyId)
1496 : {
1497 : uint8_t hash[kSHA256_Hash_Length];
1498 : static_assert(outKeyId.size() <= sizeof(hash)); // truncating 32 bytes down to 20
1499 4 : ReturnErrorOnFailure(Hash_SHA256(publicKey.data(), publicKey.size(), hash));
1500 4 : memcpy(outKeyId.data(), hash, outKeyId.size());
1501 4 : return CHIP_NO_ERROR;
1502 : }
1503 :
1504 6 : static CHIP_ERROR ValidateChipNetworkIdentity(const ChipCertificateData & certData)
1505 : {
1506 6 : ReturnErrorOnFailure(ValidateCertificateType(certData, CertType::kNetworkIdentity));
1507 :
1508 6 : VerifyOrReturnError(certData.mSerialNumber.data_equal(kNetworkIdentitySerialNumberBytes), CHIP_ERROR_WRONG_CERT_TYPE);
1509 6 : VerifyOrReturnError(certData.mNotBeforeTime == kNetworkIdentityNotBeforeTime, CHIP_ERROR_WRONG_CERT_TYPE);
1510 6 : VerifyOrReturnError(certData.mNotAfterTime == kNetworkIdentityNotAfterTime, CHIP_ERROR_WRONG_CERT_TYPE);
1511 6 : VerifyOrReturnError(certData.mIssuerDN.IsEqual(certData.mSubjectDN), CHIP_ERROR_WRONG_CERT_TYPE);
1512 :
1513 6 : VerifyOrReturnError(certData.mCertFlags.Has(CertFlags::kExtPresent_BasicConstraints) &&
1514 : !certData.mCertFlags.Has(CertFlags::kIsCA),
1515 : CHIP_ERROR_WRONG_CERT_TYPE);
1516 6 : VerifyOrReturnError(certData.mCertFlags.Has(CertFlags::kExtPresent_KeyUsage) &&
1517 : certData.mKeyUsageFlags == kNetworkIdentityKeyUsage,
1518 : CHIP_ERROR_WRONG_CERT_TYPE);
1519 6 : VerifyOrReturnError(certData.mCertFlags.Has(CertFlags::kExtPresent_ExtendedKeyUsage) &&
1520 : certData.mKeyPurposeFlags == kNetworkIdentityKeyPurpose,
1521 : CHIP_ERROR_WRONG_CERT_TYPE);
1522 :
1523 6 : ReturnErrorOnFailure(VerifyCertSignature(certData, certData));
1524 6 : return CHIP_NO_ERROR;
1525 : }
1526 :
1527 4 : CHIP_ERROR ValidateChipNetworkIdentity(const ByteSpan & cert)
1528 : {
1529 4 : ChipCertificateData certData;
1530 4 : ReturnErrorOnFailure(DecodeChipCert(cert, certData, CertDecodeFlags::kGenerateTBSHash));
1531 4 : ReturnErrorOnFailure(ValidateChipNetworkIdentity(certData));
1532 4 : return CHIP_NO_ERROR;
1533 4 : }
1534 :
1535 2 : CHIP_ERROR ValidateChipNetworkIdentity(const ByteSpan & cert, MutableCertificateKeyId outKeyId)
1536 : {
1537 2 : ChipCertificateData certData;
1538 2 : ReturnErrorOnFailure(DecodeChipCert(cert, certData, CertDecodeFlags::kGenerateTBSHash));
1539 2 : ReturnErrorOnFailure(ValidateChipNetworkIdentity(certData));
1540 2 : ReturnErrorOnFailure(CalculateKeyIdentifierSha256(certData.mPublicKey, outKeyId));
1541 2 : return CHIP_NO_ERROR;
1542 2 : }
1543 :
1544 2 : CHIP_ERROR ExtractIdentifierFromChipNetworkIdentity(const ByteSpan & cert, MutableCertificateKeyId outKeyId)
1545 : {
1546 2 : ChipCertificateData certData;
1547 2 : ReturnErrorOnFailure(DecodeChipCert(cert, certData));
1548 2 : ReturnErrorOnFailure(ValidateCertificateType(certData, CertType::kNetworkIdentity));
1549 2 : ReturnErrorOnFailure(CalculateKeyIdentifierSha256(certData.mPublicKey, outKeyId));
1550 2 : return CHIP_NO_ERROR;
1551 2 : }
1552 :
1553 1 : static CHIP_ERROR GenerateNetworkIdentitySignature(const P256Keypair & keypair, P256ECDSASignature & signature)
1554 : {
1555 : // Create a buffer and writer to capture the TBS (to-be-signed) portion of the certificate.
1556 1 : chip::Platform::ScopedMemoryBuffer<uint8_t> asn1TBSBuf;
1557 1 : VerifyOrReturnError(asn1TBSBuf.Alloc(kNetworkIdentityTBSLength), CHIP_ERROR_NO_MEMORY);
1558 :
1559 : ASN1Writer writer;
1560 1 : writer.Init(asn1TBSBuf.Get(), kNetworkIdentityTBSLength);
1561 :
1562 : // Generate the TBSCertificate and sign it
1563 1 : ReturnErrorOnFailure(EncodeNetworkIdentityTBSCert(keypair.Pubkey(), writer));
1564 1 : ReturnErrorOnFailure(keypair.ECDSA_sign_msg(asn1TBSBuf.Get(), writer.GetLengthWritten(), signature));
1565 :
1566 1 : return CHIP_NO_ERROR;
1567 1 : }
1568 :
1569 1 : static CHIP_ERROR EncodeCompactIdentityCert(TLVWriter & writer, Tag tag, const P256PublicKeySpan & publicKey,
1570 : const P256ECDSASignatureSpan & signature)
1571 : {
1572 : TLVType containerType;
1573 1 : ReturnErrorOnFailure(writer.StartContainer(tag, kTLVType_Structure, containerType));
1574 1 : ReturnErrorOnFailure(writer.Put(ContextTag(kTag_EllipticCurvePublicKey), publicKey));
1575 1 : ReturnErrorOnFailure(writer.Put(ContextTag(kTag_ECDSASignature), signature));
1576 1 : ReturnErrorOnFailure(writer.EndContainer(containerType));
1577 1 : return CHIP_NO_ERROR;
1578 : }
1579 :
1580 1 : CHIP_ERROR NewChipNetworkIdentity(const Crypto::P256Keypair & keypair, MutableByteSpan & outCompactCert)
1581 : {
1582 1 : VerifyOrReturnError(!outCompactCert.empty(), CHIP_ERROR_INVALID_ARGUMENT);
1583 1 : VerifyOrReturnError(CanCastTo<uint32_t>(outCompactCert.size()), CHIP_ERROR_INVALID_ARGUMENT);
1584 :
1585 1 : Crypto::P256ECDSASignature signature;
1586 1 : ReturnErrorOnFailure(GenerateNetworkIdentitySignature(keypair, signature));
1587 :
1588 1 : TLVWriter writer;
1589 1 : writer.Init(outCompactCert);
1590 :
1591 1 : P256PublicKeySpan publicKeySpan(keypair.Pubkey().ConstBytes());
1592 1 : P256ECDSASignatureSpan signatureSpan(signature.ConstBytes());
1593 1 : ReturnErrorOnFailure(EncodeCompactIdentityCert(writer, AnonymousTag(), publicKeySpan, signatureSpan));
1594 :
1595 1 : outCompactCert.reduce_size(writer.GetLengthWritten());
1596 1 : return CHIP_NO_ERROR;
1597 1 : }
1598 :
1599 : } // namespace Credentials
1600 : } // namespace chip
|