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