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