Matter SDK Coverage Report
Current view: top level - credentials - CHIPCertFromX509.cpp (source / functions) Coverage Total Hit
Test: SHA:1560a87972ec2c7a76cec101927a563a6862bc2a Lines: 96.9 % 224 217
Test Date: 2025-03-30 07:08:27 Functions: 100.0 % 8 8

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020-2022 Project CHIP Authors
       4              :  *    Copyright (c) 2013-2017 Nest Labs, Inc.
       5              :  *    All rights reserved.
       6              :  *
       7              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       8              :  *    you may not use this file except in compliance with the License.
       9              :  *    You may obtain a copy of the License at
      10              :  *
      11              :  *        http://www.apache.org/licenses/LICENSE-2.0
      12              :  *
      13              :  *    Unless required by applicable law or agreed to in writing, software
      14              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      15              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      16              :  *    See the License for the specific language governing permissions and
      17              :  *    limitations under the License.
      18              :  */
      19              : 
      20              : /**
      21              :  *    @file
      22              :  *      This file implements methods for converting a standard X.509
      23              :  *      certificate to a CHIP TLV-encoded certificate.
      24              :  *
      25              :  */
      26              : 
      27              : #include <stddef.h>
      28              : 
      29              : #include <credentials/CHIPCert.h>
      30              : #include <lib/asn1/ASN1.h>
      31              : #include <lib/asn1/ASN1Macros.h>
      32              : #include <lib/core/CHIPCore.h>
      33              : #include <lib/core/CHIPSafeCasts.h>
      34              : #include <lib/core/Optional.h>
      35              : #include <lib/core/TLV.h>
      36              : #include <lib/support/BytesToHex.h>
      37              : #include <lib/support/CodeUtils.h>
      38              : #include <lib/support/SafeInt.h>
      39              : #include <protocols/Protocols.h>
      40              : 
      41              : namespace chip {
      42              : namespace Credentials {
      43              : 
      44              : using namespace chip::ASN1;
      45              : using namespace chip::TLV;
      46              : using namespace chip::Protocols;
      47              : using namespace chip::Crypto;
      48              : 
      49          263 : static CHIP_ERROR ConvertDistinguishedName(ASN1Reader & reader, TLVWriter & writer, Tag tag)
      50              : {
      51          263 :     ChipDN dn;
      52          263 :     ReturnErrorOnFailure(dn.DecodeFromASN1(reader));
      53          256 :     return dn.EncodeToTLV(writer, tag);
      54          263 : }
      55              : 
      56          135 : static CHIP_ERROR ConvertValidity(ASN1Reader & reader, TLVWriter & writer)
      57              : {
      58              :     CHIP_ERROR err;
      59              :     ASN1UniversalTime asn1Time;
      60              :     uint32_t chipEpochTimeNotBefore;
      61              :     uint32_t chipEpochTimeNotAfter;
      62              : 
      63          135 :     ASN1_PARSE_ENTER_SEQUENCE
      64              :     {
      65          135 :         ASN1_PARSE_TIME(asn1Time);
      66          132 :         ReturnErrorOnFailure(ASN1ToChipEpochTime(asn1Time, chipEpochTimeNotBefore));
      67              : 
      68          132 :         ASN1_PARSE_TIME(asn1Time);
      69          129 :         ReturnErrorOnFailure(ASN1ToChipEpochTime(asn1Time, chipEpochTimeNotAfter));
      70              : 
      71              :         // Perform this check if NotAfter value is different from Never-Expire value.
      72          129 :         if (chipEpochTimeNotAfter != kNullCertTime)
      73              :         {
      74          125 :             VerifyOrReturnError(chipEpochTimeNotBefore < chipEpochTimeNotAfter, ASN1_ERROR_INVALID_ENCODING);
      75              :         }
      76              : 
      77          126 :         ReturnErrorOnFailure(writer.Put(ContextTag(kTag_NotBefore), chipEpochTimeNotBefore));
      78          126 :         ReturnErrorOnFailure(writer.Put(ContextTag(kTag_NotAfter), chipEpochTimeNotAfter));
      79              :     }
      80          126 :     ASN1_EXIT_SEQUENCE;
      81              : 
      82          132 : exit:
      83          132 :     return err;
      84              : }
      85              : 
      86          120 : static CHIP_ERROR ConvertSubjectPublicKeyInfo(ASN1Reader & reader, TLVWriter & writer)
      87              : {
      88              :     CHIP_ERROR err;
      89              :     OID pubKeyAlgoOID, pubKeyCurveOID;
      90              : 
      91              :     // subjectPublicKeyInfo SubjectPublicKeyInfo,
      92          120 :     ASN1_PARSE_ENTER_SEQUENCE
      93              :     {
      94              :         // algorithm AlgorithmIdentifier,
      95              :         // AlgorithmIdentifier ::= SEQUENCE
      96          120 :         ASN1_PARSE_ENTER_SEQUENCE
      97              :         {
      98              :             // algorithm OBJECT IDENTIFIER,
      99          120 :             ASN1_PARSE_OBJECT_ID(pubKeyAlgoOID);
     100              : 
     101              :             // Verify that the algorithm type is supported.
     102          120 :             VerifyOrExit(pubKeyAlgoOID == kOID_PubKeyAlgo_ECPublicKey, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
     103              : 
     104          120 :             err = writer.Put(ContextTag(kTag_PublicKeyAlgorithm), GetOIDEnum(pubKeyAlgoOID));
     105          120 :             SuccessOrExit(err);
     106              : 
     107              :             // EcpkParameters ::= CHOICE {
     108              :             //     ecParameters  ECParameters,
     109              :             //     namedCurve    OBJECT IDENTIFIER,
     110              :             //     implicitlyCA  NULL }
     111          120 :             ASN1_PARSE_ANY;
     112              : 
     113              :             // ecParameters and implicitlyCA not supported.
     114          120 :             if (reader.GetClass() == kASN1TagClass_Universal && reader.GetTag() == kASN1UniversalTag_Sequence)
     115              :             {
     116            0 :                 ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
     117              :             }
     118          120 :             if (reader.GetClass() == kASN1TagClass_Universal && reader.GetTag() == kASN1UniversalTag_Null)
     119              :             {
     120            0 :                 ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
     121              :             }
     122              : 
     123          120 :             ASN1_VERIFY_TAG(kASN1TagClass_Universal, kASN1UniversalTag_ObjectId);
     124              : 
     125          120 :             ASN1_GET_OBJECT_ID(pubKeyCurveOID);
     126              : 
     127              :             // Verify the curve name is recognized.
     128          120 :             VerifyOrExit(GetOIDCategory(pubKeyCurveOID) == kOIDCategory_EllipticCurve, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
     129              : 
     130          117 :             err = writer.Put(ContextTag(kTag_EllipticCurveIdentifier), GetOIDEnum(pubKeyCurveOID));
     131          117 :             SuccessOrExit(err);
     132              :         }
     133          117 :         ASN1_EXIT_SEQUENCE;
     134              : 
     135              :         // subjectPublicKey BIT STRING
     136          117 :         ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_BitString);
     137              : 
     138              :         // Verify public key length.
     139          117 :         VerifyOrExit(reader.GetValueLen() > 0, err = ASN1_ERROR_INVALID_ENCODING);
     140              : 
     141              :         // The first byte is Unused Bit Count value, which should be zero.
     142          117 :         VerifyOrExit(reader.GetValue()[0] == 0, err = ASN1_ERROR_INVALID_ENCODING);
     143              : 
     144              :         // Copy the X9.62 encoded EC point into the CHIP certificate as a byte string.
     145              :         // Skip the first Unused Bit Count byte.
     146          117 :         err = writer.PutBytes(ContextTag(kTag_EllipticCurvePublicKey), reader.GetValue() + 1, reader.GetValueLen() - 1);
     147          117 :         SuccessOrExit(err);
     148              :     }
     149          117 :     ASN1_EXIT_SEQUENCE;
     150              : 
     151          120 : exit:
     152          120 :     return err;
     153              : }
     154              : 
     155          474 : static CHIP_ERROR ConvertExtension(ASN1Reader & reader, TLVWriter & writer)
     156              : {
     157              :     CHIP_ERROR err;
     158              :     TLVType outerContainer;
     159              :     OID extensionOID;
     160          474 :     bool critical = false;
     161              :     const uint8_t * extensionSequence;
     162              :     uint32_t extensionSequenceLen;
     163              : 
     164          474 :     err = reader.GetConstructedType(extensionSequence, extensionSequenceLen);
     165          474 :     SuccessOrExit(err);
     166              : 
     167              :     // Extension ::= SEQUENCE
     168          474 :     ASN1_ENTER_SEQUENCE
     169              :     {
     170              :         // extnID OBJECT IDENTIFIER,
     171          474 :         ASN1_PARSE_OBJECT_ID(extensionOID);
     172              : 
     173              :         // The kOID_Unknown will be interpreted and encoded as future-extension.
     174          474 :         if (extensionOID != kOID_Unknown)
     175              :         {
     176          466 :             VerifyOrExit(GetOIDCategory(extensionOID) == kOIDCategory_Extension, err = ASN1_ERROR_INVALID_ENCODING);
     177              :         }
     178              : 
     179              :         // critical BOOLEAN DEFAULT FALSE,
     180          474 :         ASN1_PARSE_ANY;
     181          474 :         if (reader.GetClass() == kASN1TagClass_Universal && reader.GetTag() == kASN1UniversalTag_Boolean)
     182              :         {
     183          260 :             ASN1_GET_BOOLEAN(critical);
     184              : 
     185          260 :             VerifyOrExit(critical, err = ASN1_ERROR_INVALID_ENCODING);
     186              : 
     187          260 :             ASN1_PARSE_ANY;
     188              :         }
     189              : 
     190              :         // extnValue OCTET STRING
     191              :         //           -- contains the DER encoding of an ASN.1 value
     192              :         //           -- corresponding to the extension type identified
     193              :         //           -- by extnID
     194          474 :         ASN1_ENTER_ENCAPSULATED(kASN1TagClass_Universal, kASN1UniversalTag_OctetString)
     195              :         {
     196          474 :             if (extensionOID == kOID_Extension_AuthorityKeyIdentifier)
     197              :             {
     198              :                 // This extension MUST be marked as non-critical.
     199           96 :                 VerifyOrExit(!critical, err = ASN1_ERROR_INVALID_ENCODING);
     200              : 
     201              :                 // AuthorityKeyIdentifier ::= SEQUENCE
     202           96 :                 ASN1_PARSE_ENTER_SEQUENCE
     203              :                 {
     204           96 :                     err = reader.Next();
     205           96 :                     SuccessOrExit(err);
     206              : 
     207              :                     // keyIdentifier [0] IMPLICIT KeyIdentifier,
     208              :                     // KeyIdentifier ::= OCTET STRING
     209           96 :                     VerifyOrExit(reader.GetClass() == kASN1TagClass_ContextSpecific && reader.GetTag() == 0,
     210              :                                  err = ASN1_ERROR_INVALID_ENCODING);
     211              : 
     212           96 :                     VerifyOrExit(reader.IsConstructed() == false, err = ASN1_ERROR_INVALID_ENCODING);
     213           96 :                     VerifyOrExit(reader.GetValueLen() == kKeyIdentifierLength, err = ASN1_ERROR_INVALID_ENCODING);
     214              : 
     215           93 :                     err = writer.PutBytes(ContextTag(kTag_AuthorityKeyIdentifier), reader.GetValue(), reader.GetValueLen());
     216           93 :                     SuccessOrExit(err);
     217              : 
     218           92 :                     err = reader.Next();
     219           92 :                     VerifyOrExit(err == ASN1_END, err = ASN1_ERROR_INVALID_ENCODING);
     220              :                 }
     221           92 :                 ASN1_EXIT_SEQUENCE;
     222              :             }
     223          378 :             else if (extensionOID == kOID_Extension_SubjectKeyIdentifier)
     224              :             {
     225              :                 // This extension MUST be marked as non-critical.
     226           99 :                 VerifyOrExit(!critical, err = ASN1_ERROR_INVALID_ENCODING);
     227              : 
     228              :                 // SubjectKeyIdentifier ::= KeyIdentifier
     229              :                 // KeyIdentifier ::= OCTET STRING
     230           99 :                 ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_OctetString);
     231              : 
     232           99 :                 VerifyOrExit(reader.GetValueLen() == kKeyIdentifierLength, err = ASN1_ERROR_INVALID_ENCODING);
     233              : 
     234           96 :                 err = writer.PutBytes(ContextTag(kTag_SubjectKeyIdentifier), reader.GetValue(), reader.GetValueLen());
     235           96 :                 SuccessOrExit(err);
     236              :             }
     237          279 :             else if (extensionOID == kOID_Extension_KeyUsage)
     238              :             {
     239              :                 // This extension MUST be marked as critical.
     240          107 :                 VerifyOrExit(critical, err = ASN1_ERROR_INVALID_ENCODING);
     241              : 
     242              :                 // KeyUsage ::= BIT STRING
     243          101 :                 ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_BitString);
     244              : 
     245              :                 uint32_t keyUsageBits;
     246          101 :                 err = reader.GetBitString(keyUsageBits);
     247          101 :                 SuccessOrExit(err);
     248          101 :                 VerifyOrExit(CanCastTo<uint16_t>(keyUsageBits), err = ASN1_ERROR_INVALID_ENCODING);
     249              : 
     250              :                 // Check that only supported flags are set.
     251          101 :                 BitFlags<KeyUsageFlags> keyUsageFlags(static_cast<uint16_t>(keyUsageBits));
     252          101 :                 VerifyOrExit(keyUsageFlags.HasOnly(
     253              :                                  KeyUsageFlags::kDigitalSignature, KeyUsageFlags::kNonRepudiation, KeyUsageFlags::kKeyEncipherment,
     254              :                                  KeyUsageFlags::kDataEncipherment, KeyUsageFlags::kKeyAgreement, KeyUsageFlags::kKeyCertSign,
     255              :                                  KeyUsageFlags::kCRLSign, KeyUsageFlags::kEncipherOnly, KeyUsageFlags::kEncipherOnly),
     256              :                              err = ASN1_ERROR_INVALID_ENCODING);
     257              : 
     258          101 :                 err = writer.Put(ContextTag(kTag_KeyUsage), keyUsageBits);
     259          101 :                 SuccessOrExit(err);
     260              :             }
     261          172 :             else if (extensionOID == kOID_Extension_BasicConstraints)
     262              :             {
     263              :                 // This extension MUST be marked as critical.
     264          117 :                 VerifyOrExit(critical, err = ASN1_ERROR_INVALID_ENCODING);
     265              : 
     266              :                 // BasicConstraints ::= SEQUENCE
     267          111 :                 ASN1_PARSE_ENTER_SEQUENCE
     268              :                 {
     269          111 :                     bool isCA                 = false;
     270          111 :                     int64_t pathLenConstraint = -1;
     271              : 
     272              :                     // cA BOOLEAN DEFAULT FALSE
     273          111 :                     err = reader.Next();
     274          173 :                     if (err == CHIP_NO_ERROR && reader.GetClass() == kASN1TagClass_Universal &&
     275           62 :                         reader.GetTag() == kASN1UniversalTag_Boolean)
     276              :                     {
     277           62 :                         ASN1_GET_BOOLEAN(isCA);
     278              : 
     279           58 :                         VerifyOrExit(isCA, err = ASN1_ERROR_INVALID_ENCODING);
     280              : 
     281           58 :                         err = reader.Next();
     282              :                     }
     283              : 
     284              :                     // pathLenConstraint INTEGER (0..MAX) OPTIONAL
     285          118 :                     if (err == CHIP_NO_ERROR && reader.GetClass() == kASN1TagClass_Universal &&
     286            7 :                         reader.GetTag() == kASN1UniversalTag_Integer)
     287              :                     {
     288            7 :                         ASN1_GET_INTEGER(pathLenConstraint);
     289              : 
     290            7 :                         VerifyOrExit(CanCastTo<uint8_t>(pathLenConstraint), err = ASN1_ERROR_INVALID_ENCODING);
     291              : 
     292              :                         // pathLenConstraint is present only when cA is TRUE
     293            7 :                         VerifyOrExit(isCA, err = ASN1_ERROR_INVALID_ENCODING);
     294              :                     }
     295              : 
     296          107 :                     err = writer.StartContainer(ContextTag(kTag_BasicConstraints), kTLVType_Structure, outerContainer);
     297          107 :                     SuccessOrExit(err);
     298              : 
     299              :                     // Set also when cA is FALSE
     300          107 :                     err = writer.PutBoolean(ContextTag(kTag_BasicConstraints_IsCA), isCA);
     301          107 :                     SuccessOrExit(err);
     302              : 
     303          107 :                     if (pathLenConstraint != -1)
     304              :                     {
     305            3 :                         err = writer.Put(ContextTag(kTag_BasicConstraints_PathLenConstraint),
     306              :                                          static_cast<uint8_t>(pathLenConstraint));
     307            3 :                         SuccessOrExit(err);
     308              :                     }
     309              : 
     310          107 :                     err = writer.EndContainer(outerContainer);
     311          107 :                     SuccessOrExit(err);
     312              :                 }
     313          107 :                 ASN1_EXIT_SEQUENCE;
     314              :             }
     315           55 :             else if (extensionOID == kOID_Extension_ExtendedKeyUsage)
     316              :             {
     317              :                 // This extension MUST be marked as critical.
     318           47 :                 VerifyOrExit(critical, err = ASN1_ERROR_INVALID_ENCODING);
     319              : 
     320           47 :                 err = writer.StartContainer(ContextTag(kTag_ExtendedKeyUsage), kTLVType_Array, outerContainer);
     321           47 :                 SuccessOrExit(err);
     322              : 
     323              :                 // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
     324           47 :                 ASN1_PARSE_ENTER_SEQUENCE
     325              :                 {
     326          140 :                     while ((err = reader.Next()) == CHIP_NO_ERROR)
     327              :                     {
     328              :                         // KeyPurposeId ::= OBJECT IDENTIFIER
     329              :                         OID keyPurposeOID;
     330           93 :                         ASN1_GET_OBJECT_ID(keyPurposeOID);
     331              : 
     332           93 :                         VerifyOrExit(keyPurposeOID != kOID_Unknown, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
     333           93 :                         VerifyOrExit(GetOIDCategory(keyPurposeOID) == kOIDCategory_KeyPurpose, err = ASN1_ERROR_INVALID_ENCODING);
     334              : 
     335           93 :                         err = writer.Put(AnonymousTag(), GetOIDEnum(keyPurposeOID));
     336           93 :                         SuccessOrExit(err);
     337              :                     }
     338           47 :                     if (err != ASN1_END)
     339              :                     {
     340            0 :                         SuccessOrExit(err);
     341              :                     }
     342              :                 }
     343           47 :                 ASN1_EXIT_SEQUENCE;
     344              : 
     345           47 :                 err = writer.EndContainer(outerContainer);
     346           47 :                 SuccessOrExit(err);
     347              :             }
     348              :             // Any other extension is treated as FutureExtension
     349              :             else
     350              :             {
     351            8 :                 err = writer.PutBytes(ContextTag(kTag_FutureExtension), extensionSequence, extensionSequenceLen);
     352            8 :                 SuccessOrExit(err);
     353              : 
     354            8 :                 ASN1_PARSE_ANY;
     355              :             }
     356              :         }
     357          451 :         ASN1_EXIT_ENCAPSULATED;
     358              :     }
     359          451 :     ASN1_EXIT_SEQUENCE;
     360              : 
     361          474 : exit:
     362          474 :     return err;
     363              : }
     364              : 
     365          117 : static CHIP_ERROR ConvertExtensions(ASN1Reader & reader, TLVWriter & writer)
     366              : {
     367              :     CHIP_ERROR err;
     368              :     TLVType containerType;
     369              : 
     370          117 :     err = writer.StartContainer(ContextTag(kTag_Extensions), kTLVType_List, containerType);
     371          117 :     SuccessOrExit(err);
     372              : 
     373              :     // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
     374          117 :     ASN1_PARSE_ENTER_SEQUENCE
     375              :     {
     376          568 :         while ((err = reader.Next()) == CHIP_NO_ERROR)
     377              :         {
     378          474 :             err = ConvertExtension(reader, writer);
     379          474 :             SuccessOrExit(err);
     380              :         }
     381              : 
     382           94 :         if (err != ASN1_END)
     383              :         {
     384            0 :             SuccessOrExit(err);
     385              :         }
     386              :     }
     387           94 :     ASN1_EXIT_SEQUENCE;
     388              : 
     389           94 :     err = writer.EndContainer(containerType);
     390           94 :     SuccessOrExit(err);
     391              : 
     392          117 : exit:
     393          117 :     return err;
     394              : }
     395              : 
     396           94 : CHIP_ERROR ConvertECDSASignatureDERToRaw(ASN1Reader & reader, TLVWriter & writer, Tag tag)
     397              : {
     398           94 :     CHIP_ERROR err = CHIP_NO_ERROR;
     399              :     uint8_t rawSig[kP256_ECDSA_Signature_Length_Raw];
     400              : 
     401              :     // Per RFC3279, the ECDSA signature value is encoded in DER encapsulated in the signatureValue BIT STRING.
     402           94 :     ASN1_ENTER_ENCAPSULATED(kASN1TagClass_Universal, kASN1UniversalTag_BitString)
     403              :     {
     404              :         // Ecdsa-Sig-Value ::= SEQUENCE
     405           94 :         ASN1_PARSE_ENTER_SEQUENCE
     406              :         {
     407              :             // r INTEGER
     408           94 :             ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer);
     409           94 :             ReturnErrorOnFailure(
     410              :                 ConvertIntegerDERToRaw(ByteSpan(reader.GetValue(), reader.GetValueLen()), rawSig, kP256_FE_Length));
     411              : 
     412              :             // s INTEGER
     413           94 :             ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer);
     414           94 :             ReturnErrorOnFailure(ConvertIntegerDERToRaw(ByteSpan(reader.GetValue(), reader.GetValueLen()), rawSig + kP256_FE_Length,
     415              :                                                         kP256_FE_Length));
     416              :         }
     417           94 :         ASN1_EXIT_SEQUENCE;
     418              :     }
     419           94 :     ASN1_EXIT_ENCAPSULATED;
     420              : 
     421           94 :     ReturnErrorOnFailure(writer.PutBytes(tag, rawSig, kP256_ECDSA_Signature_Length_Raw));
     422              : 
     423           93 : exit:
     424           93 :     return err;
     425              : }
     426              : 
     427          143 : static CHIP_ERROR ConvertCertificate(ASN1Reader & reader, TLVWriter & writer, Tag tag)
     428              : {
     429              :     CHIP_ERROR err;
     430              :     int64_t version;
     431              :     OID sigAlgoOID;
     432              :     TLVType containerType;
     433              : 
     434          143 :     err = writer.StartContainer(tag, kTLVType_Structure, containerType);
     435          143 :     SuccessOrExit(err);
     436              : 
     437              :     // Certificate ::= SEQUENCE
     438          143 :     ASN1_PARSE_ENTER_SEQUENCE
     439              :     {
     440              :         // tbsCertificate TBSCertificate,
     441              :         // TBSCertificate ::= SEQUENCE
     442          143 :         ASN1_PARSE_ENTER_SEQUENCE
     443              :         {
     444              :             // version [0] EXPLICIT Version DEFAULT v1
     445          143 :             ASN1_PARSE_ENTER_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
     446              :             {
     447              :                 // Version ::= INTEGER { v1(0), v2(1), v3(2) }
     448          143 :                 ASN1_PARSE_INTEGER(version);
     449              : 
     450              :                 // Verify that the X.509 certificate version is v3
     451          143 :                 VerifyOrExit(version == 2, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
     452              :             }
     453          140 :             ASN1_EXIT_CONSTRUCTED;
     454              : 
     455              :             // serialNumber CertificateSerialNumber
     456              :             // CertificateSerialNumber ::= INTEGER
     457          140 :             ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer);
     458          140 :             err = writer.PutBytes(ContextTag(kTag_SerialNumber), reader.GetValue(), reader.GetValueLen());
     459          140 :             SuccessOrExit(err);
     460              : 
     461              :             // signature AlgorithmIdentifier
     462              :             // AlgorithmIdentifier ::= SEQUENCE
     463          140 :             ASN1_PARSE_ENTER_SEQUENCE
     464              :             {
     465              :                 // algorithm OBJECT IDENTIFIER,
     466          140 :                 ASN1_PARSE_OBJECT_ID(sigAlgoOID);
     467              : 
     468          140 :                 VerifyOrExit(sigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
     469              : 
     470          137 :                 err = writer.Put(ContextTag(kTag_SignatureAlgorithm), GetOIDEnum(sigAlgoOID));
     471          137 :                 SuccessOrExit(err);
     472              :             }
     473          137 :             ASN1_EXIT_SEQUENCE;
     474              : 
     475              :             // issuer Name
     476          137 :             err = ConvertDistinguishedName(reader, writer, ContextTag(kTag_Issuer));
     477          137 :             SuccessOrExit(err);
     478              : 
     479              :             // validity Validity,
     480          135 :             err = ConvertValidity(reader, writer);
     481          135 :             SuccessOrExit(err);
     482              : 
     483              :             // subject Name,
     484          126 :             err = ConvertDistinguishedName(reader, writer, ContextTag(kTag_Subject));
     485          126 :             SuccessOrExit(err);
     486              : 
     487          120 :             err = ConvertSubjectPublicKeyInfo(reader, writer);
     488          120 :             SuccessOrExit(err);
     489              : 
     490          117 :             err = reader.Next();
     491              : 
     492              :             // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
     493              :             // Not supported.
     494          117 :             if (err == CHIP_NO_ERROR && reader.GetClass() == kASN1TagClass_ContextSpecific && reader.GetTag() == 1)
     495              :             {
     496            0 :                 ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
     497              :             }
     498              : 
     499              :             // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
     500              :             // Not supported.
     501          117 :             if (err == CHIP_NO_ERROR && reader.GetClass() == kASN1TagClass_ContextSpecific && reader.GetTag() == 2)
     502              :             {
     503            0 :                 ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
     504              :             }
     505              : 
     506              :             // extensions [3] EXPLICIT Extensions OPTIONAL
     507          117 :             if (err == CHIP_NO_ERROR && reader.GetClass() == kASN1TagClass_ContextSpecific && reader.GetTag() == 3)
     508              :             {
     509          117 :                 ASN1_ENTER_CONSTRUCTED(kASN1TagClass_ContextSpecific, 3)
     510              :                 {
     511          117 :                     err = ConvertExtensions(reader, writer);
     512          117 :                     SuccessOrExit(err);
     513              :                 }
     514           94 :                 ASN1_EXIT_CONSTRUCTED;
     515              : 
     516           94 :                 err = reader.Next();
     517              :             }
     518              : 
     519           94 :             if (err != ASN1_END)
     520              :             {
     521            0 :                 ExitNow();
     522              :             }
     523              :         }
     524           94 :         ASN1_EXIT_SEQUENCE;
     525              : 
     526              :         // signatureAlgorithm AlgorithmIdentifier
     527              :         // AlgorithmIdentifier ::= SEQUENCE
     528           94 :         ASN1_PARSE_ENTER_SEQUENCE
     529              :         {
     530              :             OID localSigAlgoOID;
     531              : 
     532              :             // algorithm OBJECT IDENTIFIER,
     533           94 :             ASN1_PARSE_OBJECT_ID(localSigAlgoOID);
     534              : 
     535              :             // Verify that the signatureAlgorithm is the same as the "signature" field in TBSCertificate.
     536           94 :             VerifyOrExit(localSigAlgoOID == sigAlgoOID, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
     537              :         }
     538           94 :         ASN1_EXIT_SEQUENCE;
     539              : 
     540              :         // signatureValue BIT STRING
     541           94 :         ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_BitString);
     542              : 
     543           94 :         ReturnErrorOnFailure(ConvertECDSASignatureDERToRaw(reader, writer, ContextTag(kTag_ECDSASignature)));
     544              :     }
     545           93 :     ASN1_EXIT_SEQUENCE;
     546              : 
     547           93 :     err = writer.EndContainer(containerType);
     548           93 :     SuccessOrExit(err);
     549              : 
     550          142 : exit:
     551          142 :     return err;
     552              : }
     553              : 
     554          143 : CHIP_ERROR ConvertX509CertToChipCert(const ByteSpan x509Cert, MutableByteSpan & chipCert)
     555              : {
     556              :     ASN1Reader reader;
     557          143 :     TLVWriter writer;
     558              : 
     559          143 :     VerifyOrReturnError(!x509Cert.empty(), CHIP_ERROR_INVALID_ARGUMENT);
     560          143 :     VerifyOrReturnError(CanCastTo<uint32_t>(x509Cert.size()), CHIP_ERROR_INVALID_ARGUMENT);
     561              : 
     562          143 :     reader.Init(x509Cert);
     563              : 
     564          143 :     writer.Init(chipCert);
     565              : 
     566          143 :     ReturnErrorOnFailure(ConvertCertificate(reader, writer, AnonymousTag()));
     567              : 
     568           93 :     ReturnErrorOnFailure(writer.Finalize());
     569              : 
     570           93 :     chipCert.reduce_size(writer.GetLengthWritten());
     571              : 
     572           93 :     return CHIP_NO_ERROR;
     573              : }
     574              : 
     575              : } // namespace Credentials
     576              : } // namespace chip
        

Generated by: LCOV version 2.0-1