Matter SDK Coverage Report
Current view: top level - credentials - CHIPCertFromX509.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 96.9 % 224 217
Test Date: 2025-01-17 19:00:11 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          257 : static CHIP_ERROR ConvertDistinguishedName(ASN1Reader & reader, TLVWriter & writer, Tag tag)
      50              : {
      51          257 :     ChipDN dn;
      52          257 :     ReturnErrorOnFailure(dn.DecodeFromASN1(reader));
      53          250 :     return dn.EncodeToTLV(writer, tag);
      54          257 : }
      55              : 
      56          132 : 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          132 :     ASN1_PARSE_ENTER_SEQUENCE
      64              :     {
      65          132 :         ASN1_PARSE_TIME(asn1Time);
      66          129 :         ReturnErrorOnFailure(ASN1ToChipEpochTime(asn1Time, chipEpochTimeNotBefore));
      67              : 
      68          129 :         ASN1_PARSE_TIME(asn1Time);
      69          126 :         ReturnErrorOnFailure(ASN1ToChipEpochTime(asn1Time, chipEpochTimeNotAfter));
      70              : 
      71              :         // Perform this check if NotAfter value is different from Never-Expire value.
      72          126 :         if (chipEpochTimeNotAfter != kNullCertTime)
      73              :         {
      74          122 :             VerifyOrReturnError(chipEpochTimeNotBefore < chipEpochTimeNotAfter, ASN1_ERROR_INVALID_ENCODING);
      75              :         }
      76              : 
      77          123 :         ReturnErrorOnFailure(writer.Put(ContextTag(kTag_NotBefore), chipEpochTimeNotBefore));
      78          123 :         ReturnErrorOnFailure(writer.Put(ContextTag(kTag_NotAfter), chipEpochTimeNotAfter));
      79              :     }
      80          123 :     ASN1_EXIT_SEQUENCE;
      81              : 
      82          129 : exit:
      83          129 :     return err;
      84              : }
      85              : 
      86          117 : static CHIP_ERROR ConvertSubjectPublicKeyInfo(ASN1Reader & reader, TLVWriter & writer)
      87              : {
      88              :     CHIP_ERROR err;
      89              :     OID pubKeyAlgoOID, pubKeyCurveOID;
      90              : 
      91              :     // subjectPublicKeyInfo SubjectPublicKeyInfo,
      92          117 :     ASN1_PARSE_ENTER_SEQUENCE
      93              :     {
      94              :         // algorithm AlgorithmIdentifier,
      95              :         // AlgorithmIdentifier ::= SEQUENCE
      96          117 :         ASN1_PARSE_ENTER_SEQUENCE
      97              :         {
      98              :             // algorithm OBJECT IDENTIFIER,
      99          117 :             ASN1_PARSE_OBJECT_ID(pubKeyAlgoOID);
     100              : 
     101              :             // Verify that the algorithm type is supported.
     102          117 :             VerifyOrExit(pubKeyAlgoOID == kOID_PubKeyAlgo_ECPublicKey, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
     103              : 
     104          117 :             err = writer.Put(ContextTag(kTag_PublicKeyAlgorithm), GetOIDEnum(pubKeyAlgoOID));
     105          117 :             SuccessOrExit(err);
     106              : 
     107              :             // EcpkParameters ::= CHOICE {
     108              :             //     ecParameters  ECParameters,
     109              :             //     namedCurve    OBJECT IDENTIFIER,
     110              :             //     implicitlyCA  NULL }
     111          117 :             ASN1_PARSE_ANY;
     112              : 
     113              :             // ecParameters and implicitlyCA not supported.
     114          117 :             if (reader.GetClass() == kASN1TagClass_Universal && reader.GetTag() == kASN1UniversalTag_Sequence)
     115              :             {
     116            0 :                 ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
     117              :             }
     118          117 :             if (reader.GetClass() == kASN1TagClass_Universal && reader.GetTag() == kASN1UniversalTag_Null)
     119              :             {
     120            0 :                 ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
     121              :             }
     122              : 
     123          117 :             ASN1_VERIFY_TAG(kASN1TagClass_Universal, kASN1UniversalTag_ObjectId);
     124              : 
     125          117 :             ASN1_GET_OBJECT_ID(pubKeyCurveOID);
     126              : 
     127              :             // Verify the curve name is recognized.
     128          117 :             VerifyOrExit(GetOIDCategory(pubKeyCurveOID) == kOIDCategory_EllipticCurve, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
     129              : 
     130          114 :             err = writer.Put(ContextTag(kTag_EllipticCurveIdentifier), GetOIDEnum(pubKeyCurveOID));
     131          114 :             SuccessOrExit(err);
     132              :         }
     133          114 :         ASN1_EXIT_SEQUENCE;
     134              : 
     135              :         // subjectPublicKey BIT STRING
     136          114 :         ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_BitString);
     137              : 
     138              :         // Verify public key length.
     139          114 :         VerifyOrExit(reader.GetValueLen() > 0, err = ASN1_ERROR_INVALID_ENCODING);
     140              : 
     141              :         // The first byte is Unused Bit Count value, which should be zero.
     142          114 :         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          114 :         err = writer.PutBytes(ContextTag(kTag_EllipticCurvePublicKey), reader.GetValue() + 1, reader.GetValueLen() - 1);
     147          114 :         SuccessOrExit(err);
     148              :     }
     149          114 :     ASN1_EXIT_SEQUENCE;
     150              : 
     151          117 : exit:
     152          117 :     return err;
     153              : }
     154              : 
     155          461 : static CHIP_ERROR ConvertExtension(ASN1Reader & reader, TLVWriter & writer)
     156              : {
     157              :     CHIP_ERROR err;
     158              :     TLVType outerContainer;
     159              :     OID extensionOID;
     160          461 :     bool critical = false;
     161              :     const uint8_t * extensionSequence;
     162              :     uint32_t extensionSequenceLen;
     163              : 
     164          461 :     err = reader.GetConstructedType(extensionSequence, extensionSequenceLen);
     165          461 :     SuccessOrExit(err);
     166              : 
     167              :     // Extension ::= SEQUENCE
     168          461 :     ASN1_ENTER_SEQUENCE
     169              :     {
     170              :         // extnID OBJECT IDENTIFIER,
     171          461 :         ASN1_PARSE_OBJECT_ID(extensionOID);
     172              : 
     173              :         // The kOID_Unknown will be interpreted and encoded as future-extension.
     174          461 :         if (extensionOID != kOID_Unknown)
     175              :         {
     176          453 :             VerifyOrExit(GetOIDCategory(extensionOID) == kOIDCategory_Extension, err = ASN1_ERROR_INVALID_ENCODING);
     177              :         }
     178              : 
     179              :         // critical BOOLEAN DEFAULT FALSE,
     180          461 :         ASN1_PARSE_ANY;
     181          461 :         if (reader.GetClass() == kASN1TagClass_Universal && reader.GetTag() == kASN1UniversalTag_Boolean)
     182              :         {
     183          253 :             ASN1_GET_BOOLEAN(critical);
     184              : 
     185          253 :             VerifyOrExit(critical, err = ASN1_ERROR_INVALID_ENCODING);
     186              : 
     187          253 :             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          461 :         ASN1_ENTER_ENCAPSULATED(kASN1TagClass_Universal, kASN1UniversalTag_OctetString)
     195              :         {
     196          461 :             if (extensionOID == kOID_Extension_AuthorityKeyIdentifier)
     197              :             {
     198              :                 // This extension MUST be marked as non-critical.
     199           93 :                 VerifyOrExit(!critical, err = ASN1_ERROR_INVALID_ENCODING);
     200              : 
     201              :                 // AuthorityKeyIdentifier ::= SEQUENCE
     202           93 :                 ASN1_PARSE_ENTER_SEQUENCE
     203              :                 {
     204           93 :                     err = reader.Next();
     205           93 :                     SuccessOrExit(err);
     206              : 
     207              :                     // keyIdentifier [0] IMPLICIT KeyIdentifier,
     208              :                     // KeyIdentifier ::= OCTET STRING
     209           93 :                     VerifyOrExit(reader.GetClass() == kASN1TagClass_ContextSpecific && reader.GetTag() == 0,
     210              :                                  err = ASN1_ERROR_INVALID_ENCODING);
     211              : 
     212           93 :                     VerifyOrExit(reader.IsConstructed() == false, err = ASN1_ERROR_INVALID_ENCODING);
     213           93 :                     VerifyOrExit(reader.GetValueLen() == kKeyIdentifierLength, err = ASN1_ERROR_INVALID_ENCODING);
     214              : 
     215           90 :                     err = writer.PutBytes(ContextTag(kTag_AuthorityKeyIdentifier), reader.GetValue(), reader.GetValueLen());
     216           90 :                     SuccessOrExit(err);
     217              : 
     218           89 :                     err = reader.Next();
     219           89 :                     VerifyOrExit(err == ASN1_END, err = ASN1_ERROR_INVALID_ENCODING);
     220              :                 }
     221           89 :                 ASN1_EXIT_SEQUENCE;
     222              :             }
     223          368 :             else if (extensionOID == kOID_Extension_SubjectKeyIdentifier)
     224              :             {
     225              :                 // This extension MUST be marked as non-critical.
     226           96 :                 VerifyOrExit(!critical, err = ASN1_ERROR_INVALID_ENCODING);
     227              : 
     228              :                 // SubjectKeyIdentifier ::= KeyIdentifier
     229              :                 // KeyIdentifier ::= OCTET STRING
     230           96 :                 ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_OctetString);
     231              : 
     232           96 :                 VerifyOrExit(reader.GetValueLen() == kKeyIdentifierLength, err = ASN1_ERROR_INVALID_ENCODING);
     233              : 
     234           93 :                 err = writer.PutBytes(ContextTag(kTag_SubjectKeyIdentifier), reader.GetValue(), reader.GetValueLen());
     235           93 :                 SuccessOrExit(err);
     236              :             }
     237          272 :             else if (extensionOID == kOID_Extension_KeyUsage)
     238              :             {
     239              :                 // This extension MUST be marked as critical.
     240          104 :                 VerifyOrExit(critical, err = ASN1_ERROR_INVALID_ENCODING);
     241              : 
     242              :                 // KeyUsage ::= BIT STRING
     243           98 :                 ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_BitString);
     244              : 
     245              :                 uint32_t keyUsageBits;
     246           98 :                 err = reader.GetBitString(keyUsageBits);
     247           98 :                 SuccessOrExit(err);
     248           98 :                 VerifyOrExit(CanCastTo<uint16_t>(keyUsageBits), err = ASN1_ERROR_INVALID_ENCODING);
     249              : 
     250              :                 // Check that only supported flags are set.
     251           98 :                 BitFlags<KeyUsageFlags> keyUsageFlags(static_cast<uint16_t>(keyUsageBits));
     252           98 :                 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           98 :                 err = writer.Put(ContextTag(kTag_KeyUsage), keyUsageBits);
     259           98 :                 SuccessOrExit(err);
     260              :             }
     261          168 :             else if (extensionOID == kOID_Extension_BasicConstraints)
     262              :             {
     263              :                 // This extension MUST be marked as critical.
     264          114 :                 VerifyOrExit(critical, err = ASN1_ERROR_INVALID_ENCODING);
     265              : 
     266              :                 // BasicConstraints ::= SEQUENCE
     267          108 :                 ASN1_PARSE_ENTER_SEQUENCE
     268              :                 {
     269          108 :                     bool isCA                 = false;
     270          108 :                     int64_t pathLenConstraint = -1;
     271              : 
     272              :                     // cA BOOLEAN DEFAULT FALSE
     273          108 :                     err = reader.Next();
     274          168 :                     if (err == CHIP_NO_ERROR && reader.GetClass() == kASN1TagClass_Universal &&
     275           60 :                         reader.GetTag() == kASN1UniversalTag_Boolean)
     276              :                     {
     277           60 :                         ASN1_GET_BOOLEAN(isCA);
     278              : 
     279           56 :                         VerifyOrExit(isCA, err = ASN1_ERROR_INVALID_ENCODING);
     280              : 
     281           56 :                         err = reader.Next();
     282              :                     }
     283              : 
     284              :                     // pathLenConstraint INTEGER (0..MAX) OPTIONAL
     285          115 :                     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          104 :                     err = writer.StartContainer(ContextTag(kTag_BasicConstraints), kTLVType_Structure, outerContainer);
     297          104 :                     SuccessOrExit(err);
     298              : 
     299              :                     // Set also when cA is FALSE
     300          104 :                     err = writer.PutBoolean(ContextTag(kTag_BasicConstraints_IsCA), isCA);
     301          104 :                     SuccessOrExit(err);
     302              : 
     303          104 :                     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          104 :                     err = writer.EndContainer(outerContainer);
     311          104 :                     SuccessOrExit(err);
     312              :                 }
     313          104 :                 ASN1_EXIT_SEQUENCE;
     314              :             }
     315           54 :             else if (extensionOID == kOID_Extension_ExtendedKeyUsage)
     316              :             {
     317              :                 // This extension MUST be marked as critical.
     318           46 :                 VerifyOrExit(critical, err = ASN1_ERROR_INVALID_ENCODING);
     319              : 
     320           46 :                 err = writer.StartContainer(ContextTag(kTag_ExtendedKeyUsage), kTLVType_Array, outerContainer);
     321           46 :                 SuccessOrExit(err);
     322              : 
     323              :                 // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
     324           46 :                 ASN1_PARSE_ENTER_SEQUENCE
     325              :                 {
     326          137 :                     while ((err = reader.Next()) == CHIP_NO_ERROR)
     327              :                     {
     328              :                         // KeyPurposeId ::= OBJECT IDENTIFIER
     329              :                         OID keyPurposeOID;
     330           91 :                         ASN1_GET_OBJECT_ID(keyPurposeOID);
     331              : 
     332           91 :                         VerifyOrExit(keyPurposeOID != kOID_Unknown, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
     333           91 :                         VerifyOrExit(GetOIDCategory(keyPurposeOID) == kOIDCategory_KeyPurpose, err = ASN1_ERROR_INVALID_ENCODING);
     334              : 
     335           91 :                         err = writer.Put(AnonymousTag(), GetOIDEnum(keyPurposeOID));
     336           91 :                         SuccessOrExit(err);
     337              :                     }
     338           46 :                     if (err != ASN1_END)
     339              :                     {
     340            0 :                         SuccessOrExit(err);
     341              :                     }
     342              :                 }
     343           46 :                 ASN1_EXIT_SEQUENCE;
     344              : 
     345           46 :                 err = writer.EndContainer(outerContainer);
     346           46 :                 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          438 :         ASN1_EXIT_ENCAPSULATED;
     358              :     }
     359          438 :     ASN1_EXIT_SEQUENCE;
     360              : 
     361          461 : exit:
     362          461 :     return err;
     363              : }
     364              : 
     365          114 : static CHIP_ERROR ConvertExtensions(ASN1Reader & reader, TLVWriter & writer)
     366              : {
     367              :     CHIP_ERROR err;
     368              :     TLVType containerType;
     369              : 
     370          114 :     err = writer.StartContainer(ContextTag(kTag_Extensions), kTLVType_List, containerType);
     371          114 :     SuccessOrExit(err);
     372              : 
     373              :     // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
     374          114 :     ASN1_PARSE_ENTER_SEQUENCE
     375              :     {
     376          552 :         while ((err = reader.Next()) == CHIP_NO_ERROR)
     377              :         {
     378          461 :             err = ConvertExtension(reader, writer);
     379          461 :             SuccessOrExit(err);
     380              :         }
     381              : 
     382           91 :         if (err != ASN1_END)
     383              :         {
     384            0 :             SuccessOrExit(err);
     385              :         }
     386              :     }
     387           91 :     ASN1_EXIT_SEQUENCE;
     388              : 
     389           91 :     err = writer.EndContainer(containerType);
     390           91 :     SuccessOrExit(err);
     391              : 
     392          114 : exit:
     393          114 :     return err;
     394              : }
     395              : 
     396           91 : CHIP_ERROR ConvertECDSASignatureDERToRaw(ASN1Reader & reader, TLVWriter & writer, Tag tag)
     397              : {
     398           91 :     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           91 :     ASN1_ENTER_ENCAPSULATED(kASN1TagClass_Universal, kASN1UniversalTag_BitString)
     403              :     {
     404              :         // Ecdsa-Sig-Value ::= SEQUENCE
     405           91 :         ASN1_PARSE_ENTER_SEQUENCE
     406              :         {
     407              :             // r INTEGER
     408           91 :             ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer);
     409           91 :             ReturnErrorOnFailure(
     410              :                 ConvertIntegerDERToRaw(ByteSpan(reader.GetValue(), reader.GetValueLen()), rawSig, kP256_FE_Length));
     411              : 
     412              :             // s INTEGER
     413           91 :             ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer);
     414           91 :             ReturnErrorOnFailure(ConvertIntegerDERToRaw(ByteSpan(reader.GetValue(), reader.GetValueLen()), rawSig + kP256_FE_Length,
     415              :                                                         kP256_FE_Length));
     416              :         }
     417           91 :         ASN1_EXIT_SEQUENCE;
     418              :     }
     419           91 :     ASN1_EXIT_ENCAPSULATED;
     420              : 
     421           91 :     ReturnErrorOnFailure(writer.PutBytes(tag, rawSig, kP256_ECDSA_Signature_Length_Raw));
     422              : 
     423           90 : exit:
     424           90 :     return err;
     425              : }
     426              : 
     427          140 : 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          140 :     err = writer.StartContainer(tag, kTLVType_Structure, containerType);
     435          140 :     SuccessOrExit(err);
     436              : 
     437              :     // Certificate ::= SEQUENCE
     438          140 :     ASN1_PARSE_ENTER_SEQUENCE
     439              :     {
     440              :         // tbsCertificate TBSCertificate,
     441              :         // TBSCertificate ::= SEQUENCE
     442          140 :         ASN1_PARSE_ENTER_SEQUENCE
     443              :         {
     444              :             // version [0] EXPLICIT Version DEFAULT v1
     445          140 :             ASN1_PARSE_ENTER_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
     446              :             {
     447              :                 // Version ::= INTEGER { v1(0), v2(1), v3(2) }
     448          140 :                 ASN1_PARSE_INTEGER(version);
     449              : 
     450              :                 // Verify that the X.509 certificate version is v3
     451          140 :                 VerifyOrExit(version == 2, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
     452              :             }
     453          137 :             ASN1_EXIT_CONSTRUCTED;
     454              : 
     455              :             // serialNumber CertificateSerialNumber
     456              :             // CertificateSerialNumber ::= INTEGER
     457          137 :             ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer);
     458          137 :             err = writer.PutBytes(ContextTag(kTag_SerialNumber), reader.GetValue(), reader.GetValueLen());
     459          137 :             SuccessOrExit(err);
     460              : 
     461              :             // signature AlgorithmIdentifier
     462              :             // AlgorithmIdentifier ::= SEQUENCE
     463          137 :             ASN1_PARSE_ENTER_SEQUENCE
     464              :             {
     465              :                 // algorithm OBJECT IDENTIFIER,
     466          137 :                 ASN1_PARSE_OBJECT_ID(sigAlgoOID);
     467              : 
     468          137 :                 VerifyOrExit(sigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
     469              : 
     470          134 :                 err = writer.Put(ContextTag(kTag_SignatureAlgorithm), GetOIDEnum(sigAlgoOID));
     471          134 :                 SuccessOrExit(err);
     472              :             }
     473          134 :             ASN1_EXIT_SEQUENCE;
     474              : 
     475              :             // issuer Name
     476          134 :             err = ConvertDistinguishedName(reader, writer, ContextTag(kTag_Issuer));
     477          134 :             SuccessOrExit(err);
     478              : 
     479              :             // validity Validity,
     480          132 :             err = ConvertValidity(reader, writer);
     481          132 :             SuccessOrExit(err);
     482              : 
     483              :             // subject Name,
     484          123 :             err = ConvertDistinguishedName(reader, writer, ContextTag(kTag_Subject));
     485          123 :             SuccessOrExit(err);
     486              : 
     487          117 :             err = ConvertSubjectPublicKeyInfo(reader, writer);
     488          117 :             SuccessOrExit(err);
     489              : 
     490          114 :             err = reader.Next();
     491              : 
     492              :             // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
     493              :             // Not supported.
     494          114 :             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          114 :             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          114 :             if (err == CHIP_NO_ERROR && reader.GetClass() == kASN1TagClass_ContextSpecific && reader.GetTag() == 3)
     508              :             {
     509          114 :                 ASN1_ENTER_CONSTRUCTED(kASN1TagClass_ContextSpecific, 3)
     510              :                 {
     511          114 :                     err = ConvertExtensions(reader, writer);
     512          114 :                     SuccessOrExit(err);
     513              :                 }
     514           91 :                 ASN1_EXIT_CONSTRUCTED;
     515              : 
     516           91 :                 err = reader.Next();
     517              :             }
     518              : 
     519           91 :             if (err != ASN1_END)
     520              :             {
     521            0 :                 ExitNow();
     522              :             }
     523              :         }
     524           91 :         ASN1_EXIT_SEQUENCE;
     525              : 
     526              :         // signatureAlgorithm AlgorithmIdentifier
     527              :         // AlgorithmIdentifier ::= SEQUENCE
     528           91 :         ASN1_PARSE_ENTER_SEQUENCE
     529              :         {
     530              :             OID localSigAlgoOID;
     531              : 
     532              :             // algorithm OBJECT IDENTIFIER,
     533           91 :             ASN1_PARSE_OBJECT_ID(localSigAlgoOID);
     534              : 
     535              :             // Verify that the signatureAlgorithm is the same as the "signature" field in TBSCertificate.
     536           91 :             VerifyOrExit(localSigAlgoOID == sigAlgoOID, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
     537              :         }
     538           91 :         ASN1_EXIT_SEQUENCE;
     539              : 
     540              :         // signatureValue BIT STRING
     541           91 :         ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_BitString);
     542              : 
     543           91 :         ReturnErrorOnFailure(ConvertECDSASignatureDERToRaw(reader, writer, ContextTag(kTag_ECDSASignature)));
     544              :     }
     545           90 :     ASN1_EXIT_SEQUENCE;
     546              : 
     547           90 :     err = writer.EndContainer(containerType);
     548           90 :     SuccessOrExit(err);
     549              : 
     550          139 : exit:
     551          139 :     return err;
     552              : }
     553              : 
     554          140 : CHIP_ERROR ConvertX509CertToChipCert(const ByteSpan x509Cert, MutableByteSpan & chipCert)
     555              : {
     556              :     ASN1Reader reader;
     557          140 :     TLVWriter writer;
     558              : 
     559          140 :     VerifyOrReturnError(!x509Cert.empty(), CHIP_ERROR_INVALID_ARGUMENT);
     560          140 :     VerifyOrReturnError(CanCastTo<uint32_t>(x509Cert.size()), CHIP_ERROR_INVALID_ARGUMENT);
     561              : 
     562          140 :     reader.Init(x509Cert);
     563              : 
     564          140 :     writer.Init(chipCert);
     565              : 
     566          140 :     ReturnErrorOnFailure(ConvertCertificate(reader, writer, AnonymousTag()));
     567              : 
     568           90 :     ReturnErrorOnFailure(writer.Finalize());
     569              : 
     570           90 :     chipCert.reduce_size(writer.GetLengthWritten());
     571              : 
     572           90 :     return CHIP_NO_ERROR;
     573              : }
     574              : 
     575              : } // namespace Credentials
     576              : } // namespace chip
        

Generated by: LCOV version 2.0-1