Matter SDK Coverage Report
Current view: top level - credentials - GenerateChipX509Cert.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 100.0 % 210 210
Test Date: 2025-01-17 19:00:11 Functions: 100.0 % 18 18

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2021-2022 Project CHIP Authors
       4              :  *    All rights reserved.
       5              :  *
       6              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7              :  *    you may not use this file except in compliance with the License.
       8              :  *    You may obtain a copy of the License at
       9              :  *
      10              :  *        http://www.apache.org/licenses/LICENSE-2.0
      11              :  *
      12              :  *    Unless required by applicable law or agreed to in writing, software
      13              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15              :  *    See the License for the specific language governing permissions and
      16              :  *    limitations under the License.
      17              :  */
      18              : 
      19              : /**
      20              :  *    @file
      21              :  *      This file implements methods for generating CHIP X.509 certificate.
      22              :  *
      23              :  */
      24              : 
      25              : #include <algorithm>
      26              : #include <initializer_list>
      27              : #include <inttypes.h>
      28              : #include <stddef.h>
      29              : 
      30              : #include <credentials/CHIPCert_Internal.h>
      31              : #include <lib/asn1/ASN1.h>
      32              : #include <lib/asn1/ASN1Macros.h>
      33              : #include <lib/core/CHIPCore.h>
      34              : #include <lib/core/CHIPSafeCasts.h>
      35              : #include <lib/support/CodeUtils.h>
      36              : #include <lib/support/DLLUtil.h>
      37              : #include <protocols/Protocols.h>
      38              : 
      39              : namespace chip {
      40              : namespace Credentials {
      41              : 
      42              : using namespace chip::ASN1;
      43              : using namespace chip::Crypto;
      44              : using namespace chip::Protocols;
      45              : 
      46              : namespace {
      47              : 
      48              : enum IsCACert
      49              : {
      50              :     kCACert,
      51              :     kNotCACert,
      52              : };
      53              : 
      54          147 : CHIP_ERROR EncodeSubjectPublicKeyInfo(const Crypto::P256PublicKey & pubkey, ASN1Writer & writer)
      55              : {
      56          147 :     CHIP_ERROR err = CHIP_NO_ERROR;
      57              : 
      58          147 :     ASN1_START_SEQUENCE
      59              :     {
      60          147 :         ASN1_START_SEQUENCE
      61              :         {
      62          147 :             ASN1_ENCODE_OBJECT_ID(kOID_PubKeyAlgo_ECPublicKey);
      63          147 :             ASN1_ENCODE_OBJECT_ID(kOID_EllipticCurve_prime256v1);
      64              :         }
      65          147 :         ASN1_END_SEQUENCE;
      66              : 
      67          147 :         ReturnErrorOnFailure(writer.PutBitString(0, pubkey, static_cast<uint8_t>(pubkey.Length())));
      68              :     }
      69          147 :     ASN1_END_SEQUENCE;
      70              : 
      71          147 : exit:
      72          147 :     return err;
      73              : }
      74              : 
      75          142 : CHIP_ERROR EncodeAuthorityKeyIdentifierExtension(const Crypto::P256PublicKey & pubkey, ASN1Writer & writer)
      76              : {
      77          142 :     CHIP_ERROR err = CHIP_NO_ERROR;
      78              : 
      79          142 :     ASN1_START_SEQUENCE
      80              :     {
      81          142 :         ASN1_ENCODE_OBJECT_ID(kOID_Extension_AuthorityKeyIdentifier);
      82              : 
      83          142 :         ASN1_START_OCTET_STRING_ENCAPSULATED
      84              :         {
      85          142 :             ASN1_START_SEQUENCE
      86              :             {
      87              :                 uint8_t keyid[kSHA1_Hash_Length];
      88          142 :                 ReturnErrorOnFailure(Crypto::Hash_SHA1(pubkey, pubkey.Length(), keyid));
      89              : 
      90          142 :                 ReturnErrorOnFailure(
      91              :                     writer.PutOctetString(kASN1TagClass_ContextSpecific, 0, keyid, static_cast<uint8_t>(sizeof(keyid))));
      92              :             }
      93          142 :             ASN1_END_SEQUENCE;
      94              :         }
      95          142 :         ASN1_END_ENCAPSULATED;
      96              :     }
      97          142 :     ASN1_END_SEQUENCE;
      98              : 
      99          142 : exit:
     100          142 :     return err;
     101              : }
     102              : 
     103          142 : CHIP_ERROR EncodeSubjectKeyIdentifierExtension(const Crypto::P256PublicKey & pubkey, ASN1Writer & writer)
     104              : {
     105          142 :     CHIP_ERROR err = CHIP_NO_ERROR;
     106              : 
     107          142 :     ASN1_START_SEQUENCE
     108              :     {
     109          142 :         ASN1_ENCODE_OBJECT_ID(kOID_Extension_SubjectKeyIdentifier);
     110              : 
     111          142 :         ASN1_START_OCTET_STRING_ENCAPSULATED
     112              :         {
     113              :             uint8_t keyid[kSHA1_Hash_Length];
     114          142 :             ReturnErrorOnFailure(Crypto::Hash_SHA1(pubkey, pubkey.Length(), keyid));
     115              : 
     116          142 :             ReturnErrorOnFailure(writer.PutOctetString(keyid, static_cast<uint8_t>(sizeof(keyid))));
     117              :         }
     118          142 :         ASN1_END_ENCAPSULATED;
     119              :     }
     120          142 :     ASN1_END_SEQUENCE;
     121              : 
     122          142 : exit:
     123          142 :     return err;
     124              : }
     125              : 
     126           65 : CHIP_ERROR EncodeExtKeyUsageExtension(std::initializer_list<OID> keyPurposeOIDs, ASN1Writer & writer)
     127              : {
     128           65 :     CHIP_ERROR err = CHIP_NO_ERROR;
     129           65 :     ASN1_START_SEQUENCE
     130              :     {
     131           65 :         ASN1_ENCODE_OBJECT_ID(kOID_Extension_ExtendedKeyUsage);
     132              : 
     133              :         // ExtKeyUsage extension MUST be marked as critical.
     134           65 :         ASN1_ENCODE_BOOLEAN(true);
     135           65 :         ASN1_START_OCTET_STRING_ENCAPSULATED
     136              :         {
     137           65 :             ASN1_START_SEQUENCE
     138              :             {
     139          195 :                 for (auto && oid : keyPurposeOIDs)
     140              :                 {
     141          130 :                     ASN1_ENCODE_OBJECT_ID(oid);
     142              :                 }
     143              :             }
     144           65 :             ASN1_END_SEQUENCE;
     145              :         }
     146           65 :         ASN1_END_ENCAPSULATED;
     147              :     }
     148           65 :     ASN1_END_SEQUENCE;
     149              : 
     150           65 : exit:
     151           65 :     return err;
     152              : }
     153              : 
     154          147 : CHIP_ERROR EncodeKeyUsageExtension(BitFlags<KeyUsageFlags> keyUsageFlags, ASN1Writer & writer)
     155              : {
     156          147 :     CHIP_ERROR err = CHIP_NO_ERROR;
     157          147 :     ASN1_START_SEQUENCE
     158              :     {
     159          147 :         ASN1_ENCODE_OBJECT_ID(kOID_Extension_KeyUsage);
     160              : 
     161              :         // KeyUsage extension MUST be marked as critical.
     162          147 :         ASN1_ENCODE_BOOLEAN(true);
     163          147 :         ASN1_START_OCTET_STRING_ENCAPSULATED
     164              :         {
     165          147 :             ASN1_ENCODE_BIT_STRING(keyUsageFlags.Raw());
     166              :         }
     167          147 :         ASN1_END_ENCAPSULATED;
     168              :     }
     169          147 :     ASN1_END_SEQUENCE;
     170              : 
     171          147 : exit:
     172          147 :     return err;
     173              : }
     174              : 
     175          147 : CHIP_ERROR EncodeIsCAExtension(IsCACert isCA, ASN1Writer & writer)
     176              : {
     177          147 :     CHIP_ERROR err = CHIP_NO_ERROR;
     178          147 :     ASN1_START_SEQUENCE
     179              :     {
     180          147 :         ASN1_ENCODE_OBJECT_ID(kOID_Extension_BasicConstraints);
     181              : 
     182              :         // BasicConstraints extension MUST be marked as critical.
     183          147 :         ASN1_ENCODE_BOOLEAN(true);
     184              : 
     185          147 :         ASN1_START_OCTET_STRING_ENCAPSULATED
     186              :         {
     187          147 :             ASN1_START_SEQUENCE
     188              :             {
     189              :                 // cA BOOLEAN
     190          147 :                 if (isCA == kCACert)
     191              :                 {
     192              :                     // Encode the boolean only if isCA is true
     193           82 :                     ASN1_ENCODE_BOOLEAN(true);
     194              :                 }
     195              :             }
     196          147 :             ASN1_END_SEQUENCE;
     197              :         }
     198          147 :         ASN1_END_ENCAPSULATED;
     199              :     }
     200          147 :     ASN1_END_SEQUENCE;
     201              : 
     202          147 : exit:
     203          147 :     return err;
     204              : }
     205              : 
     206           82 : CHIP_ERROR EncodeCASpecificExtensions(ASN1Writer & writer)
     207              : {
     208           82 :     ReturnErrorOnFailure(EncodeIsCAExtension(kCACert, writer));
     209           82 :     ReturnErrorOnFailure(
     210              :         EncodeKeyUsageExtension(BitFlags<KeyUsageFlags>(KeyUsageFlags::kKeyCertSign, KeyUsageFlags::kCRLSign), writer));
     211           82 :     return CHIP_NO_ERROR;
     212              : }
     213              : 
     214           60 : CHIP_ERROR EncodeNOCSpecificExtensions(ASN1Writer & writer)
     215              : {
     216           60 :     ReturnErrorOnFailure(EncodeIsCAExtension(kNotCACert, writer));
     217           60 :     ReturnErrorOnFailure(EncodeKeyUsageExtension(KeyUsageFlags::kDigitalSignature, writer));
     218           60 :     ReturnErrorOnFailure(EncodeExtKeyUsageExtension({ kOID_KeyPurpose_ClientAuth, kOID_KeyPurpose_ServerAuth }, writer));
     219           60 :     return CHIP_NO_ERROR;
     220              : }
     221              : 
     222          142 : CHIP_ERROR EncodeFutureExtension(const Optional<FutureExtension> & futureExt, ASN1Writer & writer)
     223              : {
     224          142 :     CHIP_ERROR err = CHIP_NO_ERROR;
     225              : 
     226          142 :     VerifyOrReturnError(futureExt.HasValue(), CHIP_NO_ERROR);
     227              : 
     228            6 :     ASN1_START_SEQUENCE
     229              :     {
     230            6 :         ReturnErrorOnFailure(writer.PutObjectId(futureExt.Value().OID.data(), static_cast<uint16_t>(futureExt.Value().OID.size())));
     231              : 
     232            6 :         ASN1_START_OCTET_STRING_ENCAPSULATED
     233              :         {
     234            6 :             ReturnErrorOnFailure(writer.PutOctetString(futureExt.Value().Extension.data(),
     235              :                                                        static_cast<uint16_t>(futureExt.Value().Extension.size())));
     236              :         }
     237            6 :         ASN1_END_ENCAPSULATED;
     238              :     }
     239            6 :     ASN1_END_SEQUENCE;
     240              : 
     241            6 : exit:
     242            6 :     return err;
     243              : }
     244              : 
     245          142 : CHIP_ERROR EncodeExtensions(bool isCA, const Crypto::P256PublicKey & SKI, const Crypto::P256PublicKey & AKI,
     246              :                             const Optional<FutureExtension> & futureExt, ASN1Writer & writer)
     247              : {
     248          142 :     CHIP_ERROR err = CHIP_NO_ERROR;
     249              : 
     250          142 :     ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 3)
     251              :     {
     252          142 :         ASN1_START_SEQUENCE
     253              :         {
     254          142 :             if (isCA)
     255              :             {
     256           82 :                 ReturnErrorOnFailure(EncodeCASpecificExtensions(writer));
     257              :             }
     258              :             else
     259              :             {
     260           60 :                 ReturnErrorOnFailure(EncodeNOCSpecificExtensions(writer));
     261              :             }
     262              : 
     263          142 :             ReturnErrorOnFailure(EncodeSubjectKeyIdentifierExtension(SKI, writer));
     264              : 
     265          142 :             ReturnErrorOnFailure(EncodeAuthorityKeyIdentifierExtension(AKI, writer));
     266              : 
     267          142 :             ReturnErrorOnFailure(EncodeFutureExtension(futureExt, writer));
     268              :         }
     269          142 :         ASN1_END_SEQUENCE;
     270              :     }
     271          142 :     ASN1_END_CONSTRUCTED;
     272              : 
     273          142 : exit:
     274          142 :     return err;
     275              : }
     276              : 
     277          147 : CHIP_ERROR EncodeValidity(uint32_t validityStart, uint32_t validityEnd, ASN1Writer & writer)
     278              : {
     279          147 :     CHIP_ERROR err = CHIP_NO_ERROR;
     280              :     ASN1UniversalTime asn1Time;
     281              : 
     282          147 :     ASN1_START_SEQUENCE
     283              :     {
     284          147 :         ReturnErrorOnFailure(ChipEpochToASN1Time(validityStart, asn1Time));
     285          147 :         ASN1_ENCODE_TIME(asn1Time);
     286              : 
     287          147 :         ReturnErrorOnFailure(ChipEpochToASN1Time(validityEnd, asn1Time));
     288          147 :         ASN1_ENCODE_TIME(asn1Time);
     289              :     }
     290          147 :     ASN1_END_SEQUENCE;
     291              : 
     292          147 : exit:
     293          147 :     return err;
     294              : }
     295              : 
     296           71 : CHIP_ERROR EncodeChipECDSASignature(Crypto::P256ECDSASignature & signature, ASN1Writer & writer)
     297              : {
     298           71 :     CHIP_ERROR err = CHIP_NO_ERROR;
     299              : 
     300           71 :     ASN1_START_BIT_STRING_ENCAPSULATED
     301              :     {
     302              :         // Convert RAW signature to DER when generating X509 certs.
     303           71 :         P256ECDSASignatureSpan raw_sig(signature.Bytes());
     304           71 :         ReturnErrorOnFailure(ConvertECDSASignatureRawToDER(raw_sig, writer));
     305              :     }
     306           71 :     ASN1_END_ENCAPSULATED;
     307              : 
     308           71 : exit:
     309           71 :     return err;
     310              : }
     311              : 
     312          144 : CHIP_ERROR EncodeTBSCert(const X509CertRequestParams & requestParams, const Crypto::P256PublicKey & subjectPubkey,
     313              :                          const Crypto::P256PublicKey & issuerPubkey, ASN1Writer & writer)
     314              : {
     315          144 :     CHIP_ERROR err = CHIP_NO_ERROR;
     316              :     CertType certType;
     317              :     bool isCA;
     318              : 
     319          144 :     VerifyOrReturnError(requestParams.SerialNumber >= 0, CHIP_ERROR_INVALID_ARGUMENT);
     320          142 :     VerifyOrReturnError(requestParams.ValidityEnd == kNullCertTime || requestParams.ValidityEnd >= requestParams.ValidityStart,
     321              :                         CHIP_ERROR_INVALID_ARGUMENT);
     322              : 
     323          142 :     ReturnErrorOnFailure(requestParams.SubjectDN.GetCertType(certType));
     324          142 :     isCA = (certType == CertType::kICA || certType == CertType::kRoot);
     325              : 
     326          142 :     ASN1_START_SEQUENCE
     327              :     {
     328              :         // version [0] EXPLICIT Version DEFAULT v1
     329          142 :         ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
     330              :         {
     331              :             // Version ::= INTEGER { v1(0), v2(1), v3(2) }
     332          142 :             ASN1_ENCODE_INTEGER(2);
     333              :         }
     334          142 :         ASN1_END_CONSTRUCTED;
     335              : 
     336          142 :         ReturnErrorOnFailure(writer.PutInteger(requestParams.SerialNumber));
     337              : 
     338          142 :         ASN1_START_SEQUENCE
     339              :         {
     340          142 :             ASN1_ENCODE_OBJECT_ID(kOID_SigAlgo_ECDSAWithSHA256);
     341              :         }
     342          142 :         ASN1_END_SEQUENCE;
     343              : 
     344              :         // issuer Name
     345          142 :         ReturnErrorOnFailure(requestParams.IssuerDN.EncodeToASN1(writer));
     346              : 
     347              :         // validity Validity,
     348          142 :         ReturnErrorOnFailure(EncodeValidity(requestParams.ValidityStart, requestParams.ValidityEnd, writer));
     349              : 
     350              :         // subject Name
     351          142 :         ReturnErrorOnFailure(requestParams.SubjectDN.EncodeToASN1(writer));
     352              : 
     353          142 :         ReturnErrorOnFailure(EncodeSubjectPublicKeyInfo(subjectPubkey, writer));
     354              : 
     355              :         // certificate extensions
     356          142 :         ReturnErrorOnFailure(EncodeExtensions(isCA, subjectPubkey, issuerPubkey, requestParams.FutureExt, writer));
     357              :     }
     358          142 :     ASN1_END_SEQUENCE;
     359              : 
     360          142 : exit:
     361          142 :     return err;
     362              : }
     363              : 
     364              : } // namespace
     365              : 
     366            5 : CHIP_ERROR EncodeNetworkIdentityTBSCert(const P256PublicKey & pubkey, ASN1Writer & writer)
     367              : {
     368            5 :     CHIP_ERROR err = CHIP_NO_ERROR;
     369            5 :     ChipDN issuerAndSubject;
     370            5 :     InitNetworkIdentitySubject(issuerAndSubject);
     371              : 
     372            5 :     ASN1_START_SEQUENCE
     373              :     {
     374              :         // version [0] EXPLICIT Version DEFAULT v1
     375            5 :         ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
     376              :         {
     377            5 :             ASN1_ENCODE_INTEGER(2); // Version ::= INTEGER { v1(0), v2(1), v3(2) }
     378              :         }
     379            5 :         ASN1_END_CONSTRUCTED;
     380              : 
     381            5 :         ReturnErrorOnFailure(writer.PutInteger(kNetworkIdentitySerialNumber));
     382              : 
     383            5 :         ASN1_START_SEQUENCE
     384              :         {
     385            5 :             ASN1_ENCODE_OBJECT_ID(kOID_SigAlgo_ECDSAWithSHA256);
     386              :         }
     387            5 :         ASN1_END_SEQUENCE;
     388              : 
     389              :         // issuer Name
     390            5 :         ReturnErrorOnFailure(issuerAndSubject.EncodeToASN1(writer));
     391              : 
     392              :         // validity Validity,
     393            5 :         ReturnErrorOnFailure(EncodeValidity(kNetworkIdentityNotBeforeTime, kNetworkIdentityNotAfterTime, writer));
     394              : 
     395              :         // subject Name
     396            5 :         ReturnErrorOnFailure(issuerAndSubject.EncodeToASN1(writer));
     397              : 
     398            5 :         ReturnErrorOnFailure(EncodeSubjectPublicKeyInfo(pubkey, writer));
     399              : 
     400              :         // certificate extensions
     401            5 :         ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 3)
     402              :         {
     403            5 :             ASN1_START_SEQUENCE
     404              :             {
     405            5 :                 EncodeIsCAExtension(kNotCACert, writer);
     406            5 :                 EncodeKeyUsageExtension(KeyUsageFlags::kDigitalSignature, writer);
     407            5 :                 EncodeExtKeyUsageExtension({ kOID_KeyPurpose_ClientAuth, kOID_KeyPurpose_ServerAuth }, writer);
     408              :             }
     409            5 :             ASN1_END_SEQUENCE;
     410              :         }
     411            5 :         ASN1_END_CONSTRUCTED;
     412              :     }
     413            5 :     ASN1_END_SEQUENCE;
     414              : 
     415            5 : exit:
     416            5 :     return err;
     417            5 : }
     418              : 
     419           73 : CHIP_ERROR NewChipX509Cert(const X509CertRequestParams & requestParams, const Crypto::P256PublicKey & subjectPubkey,
     420              :                            const Crypto::P256Keypair & issuerKeypair, MutableByteSpan & x509Cert)
     421              : {
     422           73 :     CHIP_ERROR err = CHIP_NO_ERROR;
     423              :     ASN1Writer writer;
     424           73 :     writer.Init(x509Cert);
     425              : 
     426           73 :     ReturnErrorOnFailure(EncodeTBSCert(requestParams, subjectPubkey, issuerKeypair.Pubkey(), writer));
     427              : 
     428           71 :     Crypto::P256ECDSASignature signature;
     429           71 :     ReturnErrorOnFailure(issuerKeypair.ECDSA_sign_msg(x509Cert.data(), writer.GetLengthWritten(), signature));
     430              : 
     431           71 :     writer.Init(x509Cert);
     432              : 
     433           71 :     ASN1_START_SEQUENCE
     434              :     {
     435           71 :         ReturnErrorOnFailure(EncodeTBSCert(requestParams, subjectPubkey, issuerKeypair.Pubkey(), writer));
     436              : 
     437           71 :         ASN1_START_SEQUENCE
     438              :         {
     439           71 :             ASN1_ENCODE_OBJECT_ID(kOID_SigAlgo_ECDSAWithSHA256);
     440              :         }
     441           71 :         ASN1_END_SEQUENCE;
     442              : 
     443           71 :         ReturnErrorOnFailure(EncodeChipECDSASignature(signature, writer));
     444              :     }
     445           71 :     ASN1_END_SEQUENCE;
     446              : 
     447           71 :     x509Cert.reduce_size(writer.GetLengthWritten());
     448              : 
     449           71 : exit:
     450           71 :     return err;
     451           71 : }
     452              : 
     453           25 : DLL_EXPORT CHIP_ERROR NewRootX509Cert(const X509CertRequestParams & requestParams, const Crypto::P256Keypair & issuerKeypair,
     454              :                                       MutableByteSpan & x509Cert)
     455              : {
     456              :     CertType certType;
     457              : 
     458           25 :     ReturnErrorOnFailure(requestParams.SubjectDN.GetCertType(certType));
     459           25 :     VerifyOrReturnError(certType == CertType::kRoot, CHIP_ERROR_INVALID_ARGUMENT);
     460           24 :     VerifyOrReturnError(requestParams.SubjectDN.IsEqual(requestParams.IssuerDN), CHIP_ERROR_INVALID_ARGUMENT);
     461              : 
     462           23 :     return NewChipX509Cert(requestParams, issuerKeypair.Pubkey(), issuerKeypair, x509Cert);
     463              : }
     464              : 
     465           21 : DLL_EXPORT CHIP_ERROR NewICAX509Cert(const X509CertRequestParams & requestParams, const Crypto::P256PublicKey & subjectPubkey,
     466              :                                      const Crypto::P256Keypair & issuerKeypair, MutableByteSpan & x509Cert)
     467              : {
     468              :     CertType certType;
     469              : 
     470           21 :     ReturnErrorOnFailure(requestParams.SubjectDN.GetCertType(certType));
     471           21 :     VerifyOrReturnError(certType == CertType::kICA, CHIP_ERROR_INVALID_ARGUMENT);
     472              : 
     473           20 :     ReturnErrorOnFailure(requestParams.IssuerDN.GetCertType(certType));
     474           20 :     VerifyOrReturnError(certType == CertType::kRoot, CHIP_ERROR_INVALID_ARGUMENT);
     475              : 
     476           20 :     return NewChipX509Cert(requestParams, subjectPubkey, issuerKeypair, x509Cert);
     477              : }
     478              : 
     479           33 : DLL_EXPORT CHIP_ERROR NewNodeOperationalX509Cert(const X509CertRequestParams & requestParams,
     480              :                                                  const Crypto::P256PublicKey & subjectPubkey,
     481              :                                                  const Crypto::P256Keypair & issuerKeypair, MutableByteSpan & x509Cert)
     482              : {
     483              :     CertType certType;
     484              : 
     485           33 :     ReturnErrorOnFailure(requestParams.SubjectDN.GetCertType(certType));
     486           32 :     VerifyOrReturnError(certType == CertType::kNode, CHIP_ERROR_INVALID_ARGUMENT);
     487              : 
     488           31 :     ReturnErrorOnFailure(requestParams.IssuerDN.GetCertType(certType));
     489           31 :     VerifyOrReturnError(certType == CertType::kICA || certType == CertType::kRoot, CHIP_ERROR_INVALID_ARGUMENT);
     490              : 
     491           30 :     return NewChipX509Cert(requestParams, subjectPubkey, issuerKeypair, x509Cert);
     492              : }
     493              : 
     494              : } // namespace Credentials
     495              : } // namespace chip
        

Generated by: LCOV version 2.0-1