Apply Upstream code (2021-03-15)
[platform/upstream/connectedhomeip.git] / src / credentials / CHIPCert.cpp
1 /*
2  *
3  *    Copyright (c) 2020-2021 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 <asn1/ASN1.h>
35 #include <asn1/ASN1Macros.h>
36 #include <core/CHIPCore.h>
37 #include <core/CHIPSafeCasts.h>
38 #include <core/CHIPTLV.h>
39 #include <credentials/CHIPCert.h>
40 #include <protocols/Protocols.h>
41 #include <support/CHIPMem.h>
42 #include <support/CodeUtils.h>
43 #include <support/TimeUtils.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 extern CHIP_ERROR DecodeConvertTBSCert(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData);
54 extern CHIP_ERROR DecodeECDSASignature(TLVReader & reader, ChipCertificateData & certData);
55
56 ChipCertificateSet::ChipCertificateSet()
57 {
58     mCerts               = nullptr;
59     mCertCount           = 0;
60     mMaxCerts            = 0;
61     mDecodeBuf           = nullptr;
62     mDecodeBufSize       = 0;
63     mMemoryAllocInternal = false;
64 }
65
66 ChipCertificateSet::~ChipCertificateSet()
67 {
68     Release();
69 }
70
71 CHIP_ERROR ChipCertificateSet::Init(uint8_t maxCertsArraySize, uint16_t decodeBufSize)
72 {
73     CHIP_ERROR err = CHIP_NO_ERROR;
74
75     VerifyOrExit(maxCertsArraySize > 0, err = CHIP_ERROR_INVALID_ARGUMENT);
76     mCerts = reinterpret_cast<ChipCertificateData *>(chip::Platform::MemoryAlloc(sizeof(ChipCertificateData) * maxCertsArraySize));
77     VerifyOrExit(mCerts != nullptr, err = CHIP_ERROR_NO_MEMORY);
78
79     VerifyOrExit(decodeBufSize > 0, err = CHIP_ERROR_INVALID_ARGUMENT);
80     mDecodeBuf = reinterpret_cast<uint8_t *>(chip::Platform::MemoryAlloc(decodeBufSize));
81     VerifyOrExit(mDecodeBuf != nullptr, err = CHIP_ERROR_NO_MEMORY);
82
83     mCertCount           = 0;
84     mMaxCerts            = maxCertsArraySize;
85     mDecodeBufSize       = decodeBufSize;
86     mMemoryAllocInternal = true;
87
88 exit:
89     if (err != CHIP_NO_ERROR)
90     {
91         Release();
92     }
93
94     return err;
95 }
96
97 CHIP_ERROR ChipCertificateSet::Init(ChipCertificateData * certsArray, uint8_t certsArraySize, uint8_t * decodeBuf,
98                                     uint16_t decodeBufSize)
99 {
100     CHIP_ERROR err = CHIP_NO_ERROR;
101
102     VerifyOrExit(certsArray != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
103     VerifyOrExit(certsArraySize > 0, err = CHIP_ERROR_INVALID_ARGUMENT);
104     VerifyOrExit(decodeBuf != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
105     VerifyOrExit(decodeBufSize > 0, err = CHIP_ERROR_INVALID_ARGUMENT);
106
107     mCertCount           = 0;
108     mCerts               = certsArray;
109     mMaxCerts            = certsArraySize;
110     mDecodeBuf           = decodeBuf;
111     mDecodeBufSize       = decodeBufSize;
112     mMemoryAllocInternal = false;
113
114 exit:
115     return err;
116 }
117
118 void ChipCertificateSet::Release()
119 {
120     if (mMemoryAllocInternal)
121     {
122         if (mCerts != nullptr)
123         {
124             Clear();
125             chip::Platform::MemoryFree(mCerts);
126             mCerts = nullptr;
127         }
128         if (mDecodeBuf != nullptr)
129         {
130             chip::Platform::MemoryFree(mDecodeBuf);
131             mDecodeBuf = nullptr;
132         }
133     }
134 }
135
136 void ChipCertificateSet::Clear()
137 {
138     for (int i = 0; i < mCertCount; i++)
139     {
140         mCerts[i].~ChipCertificateData();
141     }
142
143     mCertCount = 0;
144 }
145
146 CHIP_ERROR ChipCertificateSet::LoadCert(const uint8_t * chipCert, uint32_t chipCertLen, BitFlags<CertDecodeFlags> decodeFlags)
147 {
148     CHIP_ERROR err;
149     TLVReader reader;
150
151     reader.Init(chipCert, chipCertLen);
152     reader.ImplicitProfileId = kProtocol_OpCredentials;
153
154     err = reader.Next(kTLVType_Structure, ProfileTag(kProtocol_OpCredentials, kTag_ChipCertificate));
155     SuccessOrExit(err);
156
157     err = LoadCert(reader, decodeFlags);
158
159 exit:
160     return err;
161 }
162
163 CHIP_ERROR ChipCertificateSet::LoadCert(TLVReader & reader, BitFlags<CertDecodeFlags> decodeFlags)
164 {
165     CHIP_ERROR err;
166     ASN1Writer writer; // ASN1Writer is used to encode TBS portion of the certificate for the purpose of signature
167                        // validation, which should be performed on the TBS data encoded in ASN.1 DER form.
168     ChipCertificateData * cert = nullptr;
169
170     // Must be positioned on the structure element representing the certificate.
171     VerifyOrExit(reader.GetType() == kTLVType_Structure, err = CHIP_ERROR_INVALID_ARGUMENT);
172
173     // Verify we have room for the new certificate.
174     VerifyOrExit(mCertCount < mMaxCerts, err = CHIP_ERROR_NO_MEMORY);
175
176     cert = new (&mCerts[mCertCount]) ChipCertificateData();
177
178     {
179         TLVType containerType;
180
181         // Enter the certificate structure...
182         err = reader.EnterContainer(containerType);
183         SuccessOrExit(err);
184
185         // Initialize an ASN1Writer and convert the TBS (to-be-signed) portion of the certificate to ASN.1 DER
186         // encoding.  At the same time, parse various components within the certificate and set the corresponding
187         // fields in the CertificateData object.
188         writer.Init(mDecodeBuf, mDecodeBufSize);
189         err = DecodeConvertTBSCert(reader, writer, *cert);
190         SuccessOrExit(err);
191
192         // Verify the cert has both the Subject Key Id and Authority Key Id extensions present.
193         // Only certs with both these extensions are supported for the purposes of certificate validation.
194         VerifyOrExit(cert->mCertFlags.HasAll(CertFlags::kExtPresent_SubjectKeyId, CertFlags::kExtPresent_AuthKeyId),
195                      err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
196
197         // Verify the cert was signed with ECDSA-SHA256. This is the only signature algorithm currently supported.
198         VerifyOrExit(cert->mSigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256, err = CHIP_ERROR_UNSUPPORTED_SIGNATURE_TYPE);
199
200         // If requested, generate the hash of the TBS portion of the certificate...
201         if (decodeFlags.Has(CertDecodeFlags::kGenerateTBSHash))
202         {
203             // Finish writing the ASN.1 DER encoding of the TBS certificate.
204             err = writer.Finalize();
205             SuccessOrExit(err);
206
207             // Generate a SHA hash of the encoded TBS certificate.
208             chip::Crypto::Hash_SHA256(mDecodeBuf, writer.GetLengthWritten(), cert->mTBSHash);
209
210             cert->mCertFlags.Set(CertFlags::kTBSHashPresent);
211         }
212
213         // Decode the certificate's signature...
214         err = DecodeECDSASignature(reader, *cert);
215         SuccessOrExit(err);
216
217         // Verify no more elements in the certificate.
218         err = reader.VerifyEndOfContainer();
219         SuccessOrExit(err);
220
221         err = reader.ExitContainer(containerType);
222         SuccessOrExit(err);
223     }
224
225     // If requested by the caller, mark the certificate as trusted.
226     if (decodeFlags.Has(CertDecodeFlags::kIsTrustAnchor))
227     {
228         cert->mCertFlags.Set(CertFlags::kIsTrustAnchor);
229     }
230
231     // Assign a default type for the certificate based on its subject and attributes.
232     err = DetermineCertType(*cert);
233     SuccessOrExit(err);
234
235     mCertCount++;
236
237 exit:
238     if (err != CHIP_NO_ERROR)
239     {
240         if (cert != nullptr)
241         {
242             cert->~ChipCertificateData();
243         }
244     }
245
246     return err;
247 }
248
249 CHIP_ERROR ChipCertificateSet::LoadCerts(const uint8_t * chipCerts, uint32_t chipCertsLen, BitFlags<CertDecodeFlags> decodeFlags)
250 {
251     CHIP_ERROR err;
252     TLVReader reader;
253     TLVType type;
254     uint64_t tag;
255
256     reader.Init(chipCerts, chipCertsLen);
257     reader.ImplicitProfileId = kProtocol_OpCredentials;
258
259     err = reader.Next();
260     SuccessOrExit(err);
261
262     type = reader.GetType();
263     tag  = reader.GetTag();
264
265     VerifyOrExit((type == kTLVType_Structure && tag == ProfileTag(kProtocol_OpCredentials, kTag_ChipCertificate)) ||
266                      (type == kTLVType_Array && tag == ProfileTag(kProtocol_OpCredentials, kTag_ChipCertificateArray)),
267                  err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
268
269     err = LoadCerts(reader, decodeFlags);
270
271 exit:
272     return err;
273 }
274
275 CHIP_ERROR ChipCertificateSet::LoadCerts(TLVReader & reader, BitFlags<CertDecodeFlags> decodeFlags)
276 {
277     CHIP_ERROR err;
278     uint8_t initialCertCount = mCertCount;
279
280     // If positioned on a structure, we assume that structure is a single certificate.
281     if (reader.GetType() == kTLVType_Structure)
282     {
283         err = LoadCert(reader, decodeFlags);
284         SuccessOrExit(err);
285     }
286
287     // Other we expect to be positioned on an Array that contains a sequence of
288     // zero or more certificates...
289     else
290     {
291         TLVType containerType;
292
293         err = reader.EnterContainer(containerType);
294         SuccessOrExit(err);
295
296         while ((err = reader.Next()) == CHIP_NO_ERROR)
297         {
298             VerifyOrExit(reader.GetTag() == AnonymousTag, err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
299
300             err = LoadCert(reader, decodeFlags);
301             SuccessOrExit(err);
302         }
303         if (err != CHIP_END_OF_TLV)
304         {
305             ExitNow();
306         }
307
308         err = reader.ExitContainer(containerType);
309         SuccessOrExit(err);
310     }
311
312 exit:
313     if (err != CHIP_NO_ERROR)
314     {
315         for (uint8_t i = initialCertCount; i < mCertCount; i++)
316         {
317             mCerts[i].~ChipCertificateData();
318         }
319         mCertCount = initialCertCount;
320     }
321
322     return err;
323 }
324
325 CHIP_ERROR ChipCertificateSet::AddTrustedKey(uint64_t caId, OID curveOID, const uint8_t * pubKey, uint8_t pubKeyLen,
326                                              const uint8_t * pubKeyId, uint8_t pubKeyIdLen)
327 {
328     CHIP_ERROR err = CHIP_NO_ERROR;
329     ChipCertificateData * cert;
330
331     // Verify we have room for the new certificate.
332     VerifyOrExit(mCertCount < mMaxCerts, err = CHIP_ERROR_NO_MEMORY);
333
334     cert = new (&mCerts[mCertCount]) ChipCertificateData();
335
336     cert->mSubjectDN.mAttrOID           = kOID_AttributeType_ChipCAId;
337     cert->mSubjectDN.mAttrValue.mChipId = caId;
338     cert->mIssuerDN                     = cert->mSubjectDN;
339     cert->mPubKeyCurveOID               = curveOID;
340     cert->mPublicKey                    = pubKey;
341     cert->mPublicKeyLen                 = pubKeyLen;
342     cert->mSubjectKeyId.mId             = pubKeyId;
343     cert->mSubjectKeyId.mLen            = pubKeyIdLen;
344     cert->mAuthKeyId                    = cert->mSubjectKeyId;
345     cert->mCertType                     = kCertType_CA;
346
347     cert->mCertFlags.Set(CertFlags::kExtPresent_BasicConstraints);
348     cert->mCertFlags.Set(CertFlags::kExtPresent_KeyUsage);
349     cert->mCertFlags.Set(CertFlags::kExtPresent_SubjectKeyId);
350     cert->mCertFlags.Set(CertFlags::kExtPresent_AuthKeyId);
351     cert->mCertFlags.Set(CertFlags::kIsCA);
352     cert->mCertFlags.Set(CertFlags::kIsTrustAnchor);
353
354     cert->mKeyUsageFlags.Set(KeyUsageFlags::kKeyCertSign);
355
356     mCertCount++;
357
358 exit:
359     return err;
360 }
361
362 const ChipCertificateData * ChipCertificateSet::FindCert(const CertificateKeyId & subjectKeyId) const
363 {
364     for (uint8_t i = 0; i < mCertCount; i++)
365     {
366         ChipCertificateData & cert = mCerts[i];
367         if (cert.mSubjectKeyId.IsEqual(subjectKeyId))
368         {
369             return &cert;
370         }
371     }
372
373     return nullptr;
374 }
375
376 bool ChipCertificateSet::IsCertInTheSet(const ChipCertificateData * cert) const
377 {
378     for (uint8_t i = 0; i < mCertCount; i++)
379     {
380         if (cert == &mCerts[i])
381         {
382             return true;
383         }
384     }
385
386     return false;
387 }
388
389 CHIP_ERROR ChipCertificateSet::ValidateCert(const ChipCertificateData * cert, ValidationContext & context)
390 {
391     CHIP_ERROR err;
392
393     VerifyOrExit(IsCertInTheSet(cert), err = CHIP_ERROR_INVALID_ARGUMENT);
394
395     context.mTrustAnchor = nullptr;
396
397     err = ValidateCert(cert, context, context.mValidateFlags, 0);
398
399 exit:
400     return err;
401 }
402
403 CHIP_ERROR ChipCertificateSet::FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId,
404                                              ValidationContext & context, ChipCertificateData *& cert)
405 {
406     CHIP_ERROR err;
407
408     context.mTrustAnchor = nullptr;
409
410     err = FindValidCert(subjectDN, subjectKeyId, context, context.mValidateFlags, 0, cert);
411     SuccessOrExit(err);
412
413 exit:
414     return err;
415 }
416
417 CHIP_ERROR ChipCertificateSet::VerifySignature(const ChipCertificateData * cert, const ChipCertificateData * caCert)
418 {
419     static constexpr size_t kMaxBytesForDeferredLenList = sizeof(uint8_t *) + // size of a single pointer in the deferred list
420         4 + // extra memory allocated for the deferred length field (kLengthFieldReserveSize - 1)
421         3;  // the deferred length list is alligned to 32bit boundary
422
423     CHIP_ERROR err;
424     P256PublicKey caPublicKey;
425     P256ECDSASignature signature;
426     uint8_t tmpBuf[signature.Capacity() + kMaxBytesForDeferredLenList];
427     ASN1Writer writer;
428
429     writer.Init(tmpBuf, static_cast<uint32_t>(sizeof(tmpBuf)));
430
431     // Ecdsa-Sig-Value ::= SEQUENCE
432     ASN1_START_SEQUENCE
433     {
434         // r INTEGER
435         err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, cert->mSignature.R, cert->mSignature.RLen);
436         SuccessOrExit(err);
437
438         // s INTEGER
439         err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, cert->mSignature.S, cert->mSignature.SLen);
440         SuccessOrExit(err);
441     }
442     ASN1_END_SEQUENCE;
443
444     err = writer.Finalize();
445     SuccessOrExit(err);
446
447     VerifyOrExit(writer.GetLengthWritten() <= signature.Capacity(), err = CHIP_ERROR_BUFFER_TOO_SMALL);
448
449     memcpy(signature, tmpBuf, writer.GetLengthWritten());
450     err = signature.SetLength(writer.GetLengthWritten());
451     SuccessOrExit(err);
452
453     memcpy(caPublicKey, caCert->mPublicKey, caCert->mPublicKeyLen);
454
455     err = caPublicKey.ECDSA_validate_hash_signature(cert->mTBSHash, chip::Crypto::kSHA256_Hash_Length, signature);
456     SuccessOrExit(err);
457
458 exit:
459     return err;
460 }
461
462 CHIP_ERROR ChipCertificateSet::ValidateCert(const ChipCertificateData * cert, ValidationContext & context,
463                                             BitFlags<CertValidateFlags> validateFlags, uint8_t depth)
464 {
465     CHIP_ERROR err               = CHIP_NO_ERROR;
466     ChipCertificateData * caCert = nullptr;
467
468     // If the depth is greater than 0 then the certificate is required to be a CA certificate...
469     if (depth > 0)
470     {
471         // Verify the isCA flag is present.
472         VerifyOrExit(cert->mCertFlags.Has(CertFlags::kIsCA), err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
473
474         // Verify the key usage extension is present and contains the 'keyCertSign' flag.
475         VerifyOrExit(cert->mCertFlags.Has(CertFlags::kExtPresent_KeyUsage) && cert->mKeyUsageFlags.Has(KeyUsageFlags::kKeyCertSign),
476                      err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
477
478         // Verify that the certificate type is set to "CA".
479         VerifyOrExit(cert->mCertType == kCertType_CA, err = CHIP_ERROR_WRONG_CERT_TYPE);
480
481         // If a path length constraint was included, verify the cert depth vs. the specified constraint.
482         //
483         // From the RFC, the path length constraint "gives the maximum number of non-self-issued
484         // intermediate certificates that may follow this certificate in a valid certification path.
485         // (Note: The last certificate in the certification path is not an intermediate certificate,
486         // and is not included in this limit...)"
487         //
488         if (cert->mCertFlags.Has(CertFlags::kPathLenConstraintPresent))
489         {
490             VerifyOrExit((depth - 1) <= cert->mPathLenConstraint, err = CHIP_ERROR_CERT_PATH_LEN_CONSTRAINT_EXCEEDED);
491         }
492     }
493
494     // Otherwise verify the desired certificate usages/purposes/type given in the validation context...
495     else
496     {
497         // If a set of desired key usages has been specified, verify that the key usage extension exists
498         // in the certificate and that the corresponding usages are supported.
499         if (context.mRequiredKeyUsages.HasAny())
500         {
501             VerifyOrExit(cert->mCertFlags.Has(CertFlags::kExtPresent_KeyUsage) &&
502                              cert->mKeyUsageFlags.HasAll(context.mRequiredKeyUsages),
503                          err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
504         }
505
506         // If a set of desired key purposes has been specified, verify that the extended key usage extension
507         // exists in the certificate and that the corresponding purposes are supported.
508         if (context.mRequiredKeyPurposes.HasAny())
509         {
510             VerifyOrExit(cert->mCertFlags.Has(CertFlags::kExtPresent_ExtendedKeyUsage) &&
511                              cert->mKeyPurposeFlags.HasAll(context.mRequiredKeyPurposes),
512                          err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
513         }
514
515         // If a required certificate type has been specified, verify it against the current certificate's type.
516         if (context.mRequiredCertType != kCertType_NotSpecified)
517         {
518             VerifyOrExit(cert->mCertType == context.mRequiredCertType, err = CHIP_ERROR_WRONG_CERT_TYPE);
519         }
520     }
521
522     // Verify the validity time of the certificate, if requested.
523     if (cert->mNotBeforeTime != 0 && !validateFlags.Has(CertValidateFlags::kIgnoreNotBefore))
524     {
525         VerifyOrExit(context.mEffectiveTime >= cert->mNotBeforeTime, err = CHIP_ERROR_CERT_NOT_VALID_YET);
526     }
527     if (cert->mNotAfterTime != 0 && !validateFlags.Has(CertValidateFlags::kIgnoreNotAfter))
528     {
529         VerifyOrExit(context.mEffectiveTime <= cert->mNotAfterTime, err = CHIP_ERROR_CERT_EXPIRED);
530     }
531
532     // If the certificate itself is trusted, then it is implicitly valid.  Record this certificate as the trust
533     // anchor and return success.
534     if (cert->mCertFlags.Has(CertFlags::kIsTrustAnchor))
535     {
536         context.mTrustAnchor = cert;
537         ExitNow(err = CHIP_NO_ERROR);
538     }
539
540     // Otherwise we must validate the certificate by looking for a chain of valid certificates up to a trusted
541     // certificate known as the 'trust anchor'.
542
543     // Fail validation if the certificate is self-signed. Since we don't trust this certificate (see the check above) and
544     // it has no path we can follow to a trust anchor, it can't be considered valid.
545     if (cert->mIssuerDN.IsEqual(cert->mSubjectDN) && cert->mAuthKeyId.IsEqual(cert->mSubjectKeyId))
546     {
547         ExitNow(err = CHIP_ERROR_CERT_NOT_TRUSTED);
548     }
549
550     // Verify that the certificate depth is less than the total number of certificates. It is technically possible to create
551     // a circular chain of certificates.  Limiting the maximum depth of the certificate path prevents infinite
552     // recursion in such a case.
553     VerifyOrExit(depth < mCertCount, err = CHIP_ERROR_CERT_PATH_TOO_LONG);
554
555     // Verify that a hash of the 'to-be-signed' portion of the certificate has been computed. We will need this to
556     // verify the cert's signature below.
557     VerifyOrExit(cert->mCertFlags.Has(CertFlags::kTBSHashPresent), err = CHIP_ERROR_INVALID_ARGUMENT);
558
559     // Search for a valid CA certificate that matches the Issuer DN and Authority Key Id of the current certificate.
560     // Fail if no acceptable certificate is found.
561     err = FindValidCert(cert->mIssuerDN, cert->mAuthKeyId, context, validateFlags, static_cast<uint8_t>(depth + 1), caCert);
562     if (err != CHIP_NO_ERROR)
563     {
564         ExitNow(err = CHIP_ERROR_CA_CERT_NOT_FOUND);
565     }
566
567     // Verify signature of the current certificate against public key of the CA certificate. If signature verification
568     // succeeds, the current certificate is valid.
569     err = VerifySignature(cert, caCert);
570     SuccessOrExit(err);
571
572 exit:
573     return err;
574 }
575
576 CHIP_ERROR ChipCertificateSet::FindValidCert(const ChipDN & subjectDN, const CertificateKeyId & subjectKeyId,
577                                              ValidationContext & context, BitFlags<CertValidateFlags> validateFlags, uint8_t depth,
578                                              ChipCertificateData *& cert)
579 {
580     CHIP_ERROR err;
581
582     // Default error if we don't find any matching cert.
583     err = (depth > 0) ? CHIP_ERROR_CA_CERT_NOT_FOUND : CHIP_ERROR_CERT_NOT_FOUND;
584
585     // Fail immediately if neither of the input criteria are specified.
586     if (subjectDN.IsEmpty() && subjectKeyId.IsEmpty())
587     {
588         ExitNow();
589     }
590
591     // For each cert in the set...
592     for (uint8_t i = 0; i < mCertCount; i++)
593     {
594         ChipCertificateData * candidateCert = &mCerts[i];
595
596         // Skip the certificate if its subject DN and key id do not match the input criteria.
597         if (!subjectDN.IsEmpty() && !candidateCert->mSubjectDN.IsEqual(subjectDN))
598         {
599             continue;
600         }
601         if (!subjectKeyId.IsEmpty() && !candidateCert->mSubjectKeyId.IsEqual(subjectKeyId))
602         {
603             continue;
604         }
605
606         // Attempt to validate the cert.  If the cert is valid, return it to the caller. Otherwise,
607         // save the returned error and continue searching.  If there are no other matching certs this
608         // will be the error returned to the caller.
609         err = ValidateCert(candidateCert, context, validateFlags, depth);
610         if (err == CHIP_NO_ERROR)
611         {
612             cert = candidateCert;
613             ExitNow();
614         }
615     }
616
617     cert = nullptr;
618
619 exit:
620     return err;
621 }
622
623 ChipCertificateData::ChipCertificateData()
624 {
625     Clear();
626 }
627
628 ChipCertificateData::~ChipCertificateData()
629 {
630     Clear();
631 }
632
633 void ChipCertificateData::Clear()
634 {
635     mSubjectDN.Clear();
636     mIssuerDN.Clear();
637     mSubjectKeyId.Clear();
638     mAuthKeyId.Clear();
639     mNotBeforeTime  = 0;
640     mNotAfterTime   = 0;
641     mPublicKey      = nullptr;
642     mPublicKeyLen   = 0;
643     mPubKeyCurveOID = 0;
644     mPubKeyAlgoOID  = 0;
645     mSigAlgoOID     = 0;
646     mCertFlags.ClearAll();
647     mKeyUsageFlags.ClearAll();
648     mKeyPurposeFlags.ClearAll();
649     mPathLenConstraint = 0;
650     mCertType          = kCertType_NotSpecified;
651     mSignature.R       = nullptr;
652     mSignature.RLen    = 0;
653     mSignature.S       = nullptr;
654     mSignature.SLen    = 0;
655     memset(mTBSHash, 0, sizeof(mTBSHash));
656 }
657
658 void ValidationContext::Reset()
659 {
660     mEffectiveTime = 0;
661     mTrustAnchor   = nullptr;
662     mSigningCert   = nullptr;
663     mRequiredKeyUsages.ClearAll();
664     mRequiredKeyPurposes.ClearAll();
665     mValidateFlags.ClearAll();
666     mRequiredCertType = kCertType_NotSpecified;
667 }
668
669 CHIP_ERROR DetermineCertType(ChipCertificateData & cert)
670 {
671     CHIP_ERROR err = CHIP_NO_ERROR;
672
673     // If the certificate subject contains a ChipCAId attribute...
674     if (cert.mSubjectDN.mAttrOID == kOID_AttributeType_ChipCAId)
675     {
676         // Verify the BasicConstraints isCA flag is true.
677         VerifyOrExit(cert.mCertFlags.Has(CertFlags::kIsCA), err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
678
679         // Verify the key usage extension is present and contains the 'keyCertSign' flag.
680         VerifyOrExit(cert.mCertFlags.Has(CertFlags::kExtPresent_KeyUsage) && cert.mKeyUsageFlags.Has(KeyUsageFlags::kKeyCertSign),
681                      err = CHIP_ERROR_CERT_USAGE_NOT_ALLOWED);
682
683         // Set the certificate type to CA.
684         cert.mCertType = kCertType_CA;
685     }
686
687     // If the certificate subject contains a ChipNodeId attribute set the certificate type to Node.
688     else if (cert.mSubjectDN.mAttrOID == kOID_AttributeType_ChipNodeId)
689     {
690         cert.mCertType = kCertType_Node;
691     }
692
693     // If the certificate subject contains a ChipSoftwarePublisherId attribute set the certificate type to FirmwareSigning.
694     else if (cert.mSubjectDN.mAttrOID == kOID_AttributeType_ChipSoftwarePublisherId)
695     {
696         cert.mCertType = kCertType_FirmwareSigning;
697     }
698
699     else
700     {
701         err = CHIP_ERROR_WRONG_CERT_TYPE;
702     }
703
704 exit:
705     return err;
706 }
707
708 bool ChipDN::IsEqual(const ChipDN & other) const
709 {
710     if (mAttrOID == kOID_Unknown || mAttrOID == kOID_NotSpecified || mAttrOID != other.mAttrOID)
711     {
712         return false;
713     }
714
715     if (IsChipIdX509Attr(mAttrOID))
716     {
717         return mAttrValue.mChipId == other.mAttrValue.mChipId;
718     }
719     else
720     {
721         return (mAttrValue.mString.mLen == other.mAttrValue.mString.mLen &&
722                 memcmp(mAttrValue.mString.mValue, other.mAttrValue.mString.mValue, mAttrValue.mString.mLen) == 0);
723     }
724 }
725
726 bool CertificateKeyId::IsEqual(const CertificateKeyId & other) const
727 {
728     return mId != nullptr && other.mId != nullptr && mLen == other.mLen && memcmp(mId, other.mId, mLen) == 0;
729 }
730
731 DLL_EXPORT CHIP_ERROR ASN1ToChipEpochTime(const chip::ASN1::ASN1UniversalTime & asn1Time, uint32_t & epochTime)
732 {
733     CHIP_ERROR err = CHIP_NO_ERROR;
734
735     // X.509/RFC5280 defines the special time 99991231235959Z to mean 'no well-defined expiration date'.
736     // In CHIP certificate it is represented as a CHIP Epoch UTC time value of 0 sec (2020-01-01 00:00:00 UTC).
737     if ((asn1Time.Year == kX509NoWellDefinedExpirationDateYear) && (asn1Time.Month == kMonthsPerYear) &&
738         (asn1Time.Day == kMaxDaysPerMonth) && (asn1Time.Hour == kHoursPerDay - 1) && (asn1Time.Minute == kMinutesPerHour - 1) &&
739         (asn1Time.Second == kSecondsPerMinute - 1))
740     {
741         epochTime = kNullCertTime;
742     }
743     else
744     {
745         if (!CalendarToChipEpochTime(asn1Time.Year, asn1Time.Month, asn1Time.Day, asn1Time.Hour, asn1Time.Minute, asn1Time.Second,
746                                      epochTime))
747         {
748             ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
749         }
750     }
751
752 exit:
753     return err;
754 }
755
756 DLL_EXPORT CHIP_ERROR ChipEpochToASN1Time(uint32_t epochTime, chip::ASN1::ASN1UniversalTime & asn1Time)
757 {
758     // X.509/RFC5280 defines the special time 99991231235959Z to mean 'no well-defined expiration date'.
759     // In CHIP certificate it is represented as a CHIP Epoch time value of 0 secs (2020-01-01 00:00:00 UTC).
760     if (epochTime == kNullCertTime)
761     {
762         asn1Time.Year   = kX509NoWellDefinedExpirationDateYear;
763         asn1Time.Month  = kMonthsPerYear;
764         asn1Time.Day    = kMaxDaysPerMonth;
765         asn1Time.Hour   = kHoursPerDay - 1;
766         asn1Time.Minute = kMinutesPerHour - 1;
767         asn1Time.Second = kSecondsPerMinute - 1;
768     }
769     else
770     {
771         ChipEpochToCalendarTime(epochTime, asn1Time.Year, asn1Time.Month, asn1Time.Day, asn1Time.Hour, asn1Time.Minute,
772                                 asn1Time.Second);
773     }
774
775     return CHIP_NO_ERROR;
776 }
777
778 } // namespace Credentials
779 } // namespace chip