3 * Copyright (c) 2020-2021 Project CHIP Authors
4 * Copyright (c) 2013-2017 Nest Labs, Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * This file implements methods for converting a CHIP
23 * TLV-encoded certificate to a standard X.509 certificate.
27 #ifndef __STDC_LIMIT_MACROS
28 #define __STDC_LIMIT_MACROS
34 #include <asn1/ASN1.h>
35 #include <asn1/ASN1Macros.h>
36 #include <core/CHIPCore.h>
37 #include <core/CHIPSafeCasts.h>
38 #include <core/CHIPTLV.h>
39 #include <credentials/CHIPCert.h>
40 #include <protocols/Protocols.h>
41 #include <support/CodeUtils.h>
42 #include <support/DLLUtil.h>
45 namespace Credentials {
47 using namespace chip::ASN1;
48 using namespace chip::TLV;
49 using namespace chip::Protocols;
51 inline bool IsCertificateExtensionTag(uint64_t tag)
53 if (IsContextTag(tag))
55 uint32_t tagNum = TagNumFromTag(tag);
56 return (tagNum >= kCertificateExtensionTagsStart && tagNum <= kCertificateExtensionTagsEnd);
62 static CHIP_ERROR DecodeConvertDN(TLVReader & reader, ASN1Writer & writer, ChipDN & dn)
65 TLVType outerContainer;
71 const uint8_t * asn1AttrVal;
72 uint32_t asn1AttrValLen;
73 uint8_t chipIdStr[17];
75 // Enter the List TLV element that represents the DN in TLV format.
76 err = reader.EnterContainer(outerContainer);
79 // Read the first TLV element in the List. This represents the first RDN in the original ASN.1 DN.
81 // NOTE: Although CHIP certificate encoding allows for DNs containing multiple RDNs, and/or multiple
82 // attributes per RDN, this implementation only supports DNs with a single RDN that contains exactly
88 // Get the TLV tag, make sure it is a context tag and extract the context tag number.
89 tlvTag = reader.GetTag();
90 VerifyOrExit(IsContextTag(tlvTag), err = CHIP_ERROR_INVALID_TLV_TAG);
91 tlvTagNum = TagNumFromTag(tlvTag);
93 // Get the element type.
94 elemType = reader.GetType();
96 // Derive the OID of the corresponding ASN.1 attribute from the TLV tag number.
97 // The numeric value of the OID is encoded in the bottom 7 bits of the TLV tag number.
98 // This eliminates the need for a translation table/switch statement but has the
99 // effect of tying the two encodings together.
101 // NOTE: In the event that the computed OID value is not one that we recognize
102 // (specifically, is not in the table of OIDs defined in ASN1OID.h) then the
103 // macro call below that encodes the attribute's object id (ASN1_ENCODE_OBJECT_ID)
104 // will fail for lack of the OID's encoded representation. Given this there's no
105 // need to test the validity of the OID here.
107 attrOID = GetOID(kOIDCategory_AttributeType, static_cast<uint8_t>(tlvTagNum & 0x7f));
109 // Save the attribute OID in the caller's DN structure.
110 dn.mAttrOID = attrOID;
112 // If the attribute is one of the CHIP-defined X.509 attributes that contains a CHIP id...
113 if (IsChipIdX509Attr(attrOID))
115 // Verify that the underlying TLV data type is unsigned integer.
116 VerifyOrExit(elemType == kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE);
118 // Read the value of the CHIP id.
120 err = reader.Get(chipId);
123 // Generate the string representation of the id that will appear in the ASN.1 attribute.
124 // For CHIP ids the string representation is *always* 16 uppercase hex characters.
125 snprintf(reinterpret_cast<char *>(chipIdStr), sizeof(chipIdStr), "%016" PRIX64, chipId);
126 asn1AttrVal = chipIdStr;
129 // The ASN.1 tag for CHIP id attributes is always UTF8String.
130 asn1Tag = kASN1UniversalTag_UTF8String;
132 // Save the CHIP id value in the caller's DN structure.
133 dn.mAttrValue.mChipId = chipId;
136 // Otherwise the attribute is either one of the supported X.509 attributes or a CHIP-defined
137 // attribute that is *not* a CHIP id...
140 // Verify that the underlying data type is UTF8 string.
141 VerifyOrExit(elemType == kTLVType_UTF8String, err = CHIP_ERROR_WRONG_TLV_TYPE);
143 // Get a pointer the underlying string data, plus its length.
144 err = reader.GetDataPtr(asn1AttrVal);
146 asn1AttrValLen = reader.GetLength();
148 // Determine the appropriate ASN.1 tag for the DN attribute.
149 // - CHIP-defined attributes are always UTF8Strings.
150 // - DomainComponent is always an IA5String.
151 // - For all other ASN.1 defined attributes, bit 0x80 in the TLV tag value conveys whether the attribute
152 // is a UTF8String or a PrintableString (in some cases the certificate generator has a choice).
153 if (IsChipX509Attr(attrOID))
155 asn1Tag = kASN1UniversalTag_UTF8String;
157 else if (attrOID == kOID_AttributeType_DomainComponent)
159 asn1Tag = kASN1UniversalTag_IA5String;
163 asn1Tag = (tlvTagNum & 0x80) ? kASN1UniversalTag_PrintableString : kASN1UniversalTag_UTF8String;
166 // Save the string value in the caller's DN structure.
167 dn.mAttrValue.mString.mValue = asn1AttrVal;
168 dn.mAttrValue.mString.mLen = asn1AttrValLen;
171 // Verify that there are no further elements in the DN.
172 err = reader.VerifyEndOfContainer();
175 err = reader.ExitContainer(outerContainer);
178 // Write the ASN.1 representation of the DN...
180 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
183 // RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
186 // AttributeTypeAndValue ::= SEQUENCE
189 // type AttributeType
190 // AttributeType ::= OBJECT IDENTIFIER
191 ASN1_ENCODE_OBJECT_ID(attrOID);
193 // value AttributeValue
194 // AttributeValue ::= ANY -- DEFINED BY AttributeType
195 err = writer.PutString(asn1Tag, Uint8::to_const_char(asn1AttrVal), static_cast<uint16_t>(asn1AttrValLen));
208 static CHIP_ERROR DecodeConvertValidity(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
211 ASN1UniversalTime asn1Time;
212 uint64_t chipEpochTime;
216 err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_NotBefore));
219 err = reader.Get(chipEpochTime);
222 VerifyOrExit(chipEpochTime <= UINT32_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
223 certData.mNotBeforeTime = static_cast<uint32_t>(chipEpochTime);
225 err = ChipEpochToASN1Time(static_cast<uint32_t>(chipEpochTime), asn1Time);
228 ASN1_ENCODE_TIME(asn1Time);
230 err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_NotAfter));
233 err = reader.Get(chipEpochTime);
236 VerifyOrExit(chipEpochTime <= UINT32_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
237 certData.mNotAfterTime = static_cast<uint32_t>(chipEpochTime);
239 err = ChipEpochToASN1Time(static_cast<uint32_t>(chipEpochTime), asn1Time);
242 ASN1_ENCODE_TIME(asn1Time);
250 static CHIP_ERROR DecodeConvertSubjectPublicKeyInfo(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
253 uint64_t pubKeyAlgoId, pubKeyCurveId;
256 err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_PublicKeyAlgorithm));
258 err = reader.Get(pubKeyAlgoId);
260 VerifyOrExit(pubKeyAlgoId <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
262 pubKeyAlgoOID = GetOID(kOIDCategory_PubKeyAlgo, static_cast<uint8_t>(pubKeyAlgoId));
263 certData.mPubKeyAlgoOID = pubKeyAlgoOID;
265 VerifyOrExit(pubKeyAlgoOID == kOID_PubKeyAlgo_ECPublicKey, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
267 err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_EllipticCurveIdentifier));
269 err = reader.Get(pubKeyCurveId);
271 VerifyOrExit(pubKeyCurveId <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
273 certData.mPubKeyCurveOID = GetOID(kOIDCategory_EllipticCurve, static_cast<uint8_t>(pubKeyCurveId));
275 // subjectPublicKeyInfo SubjectPublicKeyInfo,
278 // algorithm AlgorithmIdentifier,
279 // AlgorithmIdentifier ::= SEQUENCE
282 // algorithm OBJECT IDENTIFIER,
283 ASN1_ENCODE_OBJECT_ID(pubKeyAlgoOID);
285 // EcpkParameters ::= CHOICE {
286 // ecParameters ECParameters,
287 // namedCurve OBJECT IDENTIFIER,
288 // implicitlyCA NULL }
290 // (Only namedCurve supported).
292 ASN1_ENCODE_OBJECT_ID(certData.mPubKeyCurveOID);
296 err = reader.Next(kTLVType_ByteString, ContextTag(kTag_EllipticCurvePublicKey));
299 err = reader.GetDataPtr(certData.mPublicKey);
302 uint32_t len = reader.GetLength();
303 VerifyOrExit(len == chip::Crypto::kP256_PublicKey_Length, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
304 certData.mPublicKeyLen = static_cast<uint8_t>(len);
306 // For EC certs, the subjectPublicKey BIT STRING contains the X9.62 encoded EC point.
307 err = writer.PutBitString(0, certData.mPublicKey, certData.mPublicKeyLen);
316 static CHIP_ERROR DecodeConvertAuthorityKeyIdentifierExtension(TLVReader & reader, ASN1Writer & writer,
317 ChipCertificateData & certData)
322 certData.mCertFlags.Set(CertFlags::kExtPresent_AuthKeyId);
324 // AuthorityKeyIdentifier extension MUST be marked as non-critical (default).
326 // AuthorityKeyIdentifier ::= SEQUENCE
329 // keyIdentifier [0] IMPLICIT KeyIdentifier
330 // KeyIdentifier ::= OCTET STRING
331 VerifyOrExit(reader.GetType() == kTLVType_ByteString, err = CHIP_ERROR_WRONG_TLV_TYPE);
332 VerifyOrExit(reader.GetTag() == ContextTag(kTag_AuthorityKeyIdentifier), err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
334 err = reader.GetDataPtr(certData.mAuthKeyId.mId);
337 len = reader.GetLength();
338 VerifyOrExit(len == kKeyIdentifierLength, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
340 certData.mAuthKeyId.mLen = static_cast<uint8_t>(len);
342 err = writer.PutOctetString(kASN1TagClass_ContextSpecific, 0, certData.mAuthKeyId.mId, certData.mAuthKeyId.mLen);
351 static CHIP_ERROR DecodeConvertSubjectKeyIdentifierExtension(TLVReader & reader, ASN1Writer & writer,
352 ChipCertificateData & certData)
357 certData.mCertFlags.Set(CertFlags::kExtPresent_SubjectKeyId);
359 // SubjectKeyIdentifier extension MUST be marked as non-critical (default).
361 // SubjectKeyIdentifier ::= KeyIdentifier
362 // KeyIdentifier ::= OCTET STRING
363 VerifyOrExit(reader.GetType() == kTLVType_ByteString, err = CHIP_ERROR_WRONG_TLV_TYPE);
364 VerifyOrExit(reader.GetTag() == ContextTag(kTag_SubjectKeyIdentifier), err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
366 len = reader.GetLength();
367 VerifyOrExit(len == kKeyIdentifierLength, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
369 certData.mSubjectKeyId.mLen = static_cast<uint8_t>(len);
371 err = reader.GetDataPtr(certData.mSubjectKeyId.mId);
374 err = writer.PutOctetString(certData.mSubjectKeyId.mId, certData.mSubjectKeyId.mLen);
381 static CHIP_ERROR DecodeConvertKeyUsageExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
384 uint64_t keyUsageBits;
385 BitFlags<uint16_t, KeyUsageFlags> keyUsageFlags;
387 certData.mCertFlags.Set(CertFlags::kExtPresent_KeyUsage);
389 // KeyUsage ::= BIT STRING
390 VerifyOrExit(reader.GetTag() == ContextTag(kTag_KeyUsage), err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
391 VerifyOrExit(reader.GetType() == kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE);
393 err = reader.Get(keyUsageBits);
396 VerifyOrExit(keyUsageBits <= UINT16_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
398 keyUsageFlags.SetRaw(static_cast<uint16_t>(keyUsageBits));
399 VerifyOrExit(keyUsageFlags.HasOnly(KeyUsageFlags::kDigitalSignature, KeyUsageFlags::kNonRepudiation,
400 KeyUsageFlags::kKeyEncipherment, KeyUsageFlags::kDataEncipherment,
401 KeyUsageFlags::kKeyAgreement, KeyUsageFlags::kKeyCertSign, KeyUsageFlags::kCRLSign,
402 KeyUsageFlags::kEncipherOnly, KeyUsageFlags::kEncipherOnly),
403 err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
405 ASN1_ENCODE_BIT_STRING(static_cast<uint16_t>(keyUsageBits));
407 certData.mKeyUsageFlags = keyUsageFlags;
413 static CHIP_ERROR DecodeConvertBasicConstraintsExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
415 CHIP_ERROR err, nextRes;
416 TLVType outerContainer;
418 certData.mCertFlags.Set(CertFlags::kExtPresent_BasicConstraints);
420 // BasicConstraints ::= SEQUENCE
423 VerifyOrExit(reader.GetTag() == ContextTag(kTag_BasicConstraints), err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
424 VerifyOrExit(reader.GetType() == kTLVType_Structure, err = CHIP_ERROR_WRONG_TLV_TYPE);
426 err = reader.EnterContainer(outerContainer);
429 // cA BOOLEAN DEFAULT FALSE
433 err = reader.Next(kTLVType_Boolean, ContextTag(kTag_BasicConstraints_IsCA));
436 err = reader.Get(isCA);
441 ASN1_ENCODE_BOOLEAN(true);
442 certData.mCertFlags.Set(CertFlags::kIsCA);
445 nextRes = reader.Next();
446 VerifyOrExit(nextRes == CHIP_NO_ERROR || nextRes == CHIP_END_OF_TLV, err = nextRes);
449 // pathLenConstraint INTEGER (0..MAX) OPTIONAL
450 if (reader.GetTag() == ContextTag(kTag_BasicConstraints_PathLenConstraint))
452 uint64_t pathLenConstraint;
454 VerifyOrExit(reader.GetType() == kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE);
456 err = reader.Get(pathLenConstraint);
459 VerifyOrExit(pathLenConstraint <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
461 ASN1_ENCODE_INTEGER(static_cast<int64_t>(pathLenConstraint));
463 certData.mPathLenConstraint = static_cast<uint8_t>(pathLenConstraint);
465 certData.mCertFlags.Set(CertFlags::kPathLenConstraintPresent);
470 err = reader.VerifyEndOfContainer();
473 err = reader.ExitContainer(outerContainer);
482 static CHIP_ERROR DecodeConvertExtendedKeyUsageExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
484 CHIP_ERROR err, nextRes;
485 TLVType outerContainer;
487 certData.mCertFlags.Set(CertFlags::kExtPresent_ExtendedKeyUsage);
489 // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
492 VerifyOrExit(reader.GetTag() == ContextTag(kTag_ExtendedKeyUsage), err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
493 VerifyOrExit(reader.GetType() == kTLVType_Array, err = CHIP_ERROR_WRONG_TLV_TYPE);
495 err = reader.EnterContainer(outerContainer);
498 while ((nextRes = reader.Next(kTLVType_UnsignedInteger, AnonymousTag)) == CHIP_NO_ERROR)
500 uint64_t keyPurposeId;
503 err = reader.Get(keyPurposeId);
506 VerifyOrExit(keyPurposeId <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
508 keyPurposeOID = GetOID(kOIDCategory_KeyPurpose, static_cast<uint8_t>(keyPurposeId));
510 // KeyPurposeId ::= OBJECT IDENTIFIER
511 ASN1_ENCODE_OBJECT_ID(keyPurposeOID);
513 certData.mKeyPurposeFlags.Set(static_cast<KeyPurposeFlags>(0x01 << (keyPurposeId - 1)));
516 VerifyOrExit(nextRes == CHIP_END_OF_TLV, err = nextRes);
518 err = reader.ExitContainer(outerContainer);
527 static CHIP_ERROR DecodeConvertExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
530 uint64_t extensionTagNum = TagNumFromTag(reader.GetTag());
533 if (extensionTagNum == kTag_AuthorityKeyIdentifier)
535 extensionOID = kOID_Extension_AuthorityKeyIdentifier;
537 else if (extensionTagNum == kTag_SubjectKeyIdentifier)
539 extensionOID = kOID_Extension_SubjectKeyIdentifier;
541 else if (extensionTagNum == kTag_KeyUsage)
543 extensionOID = kOID_Extension_KeyUsage;
545 else if (extensionTagNum == kTag_BasicConstraints)
547 extensionOID = kOID_Extension_BasicConstraints;
549 else if (extensionTagNum == kTag_ExtendedKeyUsage)
551 extensionOID = kOID_Extension_ExtendedKeyUsage;
555 ExitNow(err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
558 // Extension ::= SEQUENCE
561 // extnID OBJECT IDENTIFIER,
562 ASN1_ENCODE_OBJECT_ID(extensionOID);
564 // BasicConstraints, KeyUsage and ExtKeyUsage extensions MUST be marked as critical.
565 if (extensionTagNum == kTag_KeyUsage || extensionTagNum == kTag_BasicConstraints ||
566 extensionTagNum == kTag_ExtendedKeyUsage)
568 ASN1_ENCODE_BOOLEAN(true);
571 // extnValue OCTET STRING
572 // -- contains the DER encoding of an ASN.1 value
573 // -- corresponding to the extension type identified
575 ASN1_START_OCTET_STRING_ENCAPSULATED
577 if (extensionTagNum == kTag_AuthorityKeyIdentifier)
579 err = DecodeConvertAuthorityKeyIdentifierExtension(reader, writer, certData);
581 else if (extensionTagNum == kTag_SubjectKeyIdentifier)
583 err = DecodeConvertSubjectKeyIdentifierExtension(reader, writer, certData);
585 else if (extensionTagNum == kTag_KeyUsage)
587 err = DecodeConvertKeyUsageExtension(reader, writer, certData);
589 else if (extensionTagNum == kTag_BasicConstraints)
591 err = DecodeConvertBasicConstraintsExtension(reader, writer, certData);
593 else if (extensionTagNum == kTag_ExtendedKeyUsage)
595 err = DecodeConvertExtendedKeyUsageExtension(reader, writer, certData);
599 err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT;
603 ASN1_END_ENCAPSULATED;
611 static CHIP_ERROR DecodeConvertExtensions(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
616 // extensions [3] EXPLICIT Extensions OPTIONAL
617 ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 3)
619 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
624 err = DecodeConvertExtension(reader, writer, certData);
627 // Break the loop if the next certificate element is NOT an extension.
630 tag = reader.GetTag();
631 if (!IsCertificateExtensionTag(tag))
639 ASN1_END_CONSTRUCTED;
645 CHIP_ERROR DecodeECDSASignature(TLVReader & reader, ChipCertificateData & certData)
648 TLVType containerType;
651 // Verify the tag and type
652 VerifyOrExit(reader.GetType() == kTLVType_Structure, err = CHIP_ERROR_WRONG_TLV_TYPE);
653 VerifyOrExit(reader.GetTag() == ContextTag(kTag_ECDSASignature), err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
655 err = reader.EnterContainer(containerType);
659 err = reader.Next(kTLVType_ByteString, ContextTag(kTag_ECDSASignature_r));
662 err = reader.GetDataPtr(certData.mSignature.R);
665 len = reader.GetLength();
666 VerifyOrExit(len <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
668 certData.mSignature.RLen = static_cast<uint8_t>(len);
671 err = reader.Next(kTLVType_ByteString, ContextTag(kTag_ECDSASignature_s));
674 err = reader.GetDataPtr(certData.mSignature.S);
677 len = reader.GetLength();
678 VerifyOrExit(len <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
680 certData.mSignature.SLen = static_cast<uint8_t>(len);
682 // Verify no more elements in the signature.
684 err = reader.VerifyEndOfContainer();
687 err = reader.ExitContainer(containerType);
694 static CHIP_ERROR DecodeConvertECDSASignature(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
698 err = DecodeECDSASignature(reader, certData);
701 // signatureValue BIT STRING
702 // Per RFC3279, the ECDSA signature value is encoded in DER encapsulated in the signatureValue BIT STRING.
703 ASN1_START_BIT_STRING_ENCAPSULATED
705 // Ecdsa-Sig-Value ::= SEQUENCE
709 err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, certData.mSignature.R,
710 certData.mSignature.RLen);
714 err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, certData.mSignature.S,
715 certData.mSignature.SLen);
720 ASN1_END_ENCAPSULATED;
727 * @brief Decode and convert the To-Be-Signed (TBS) portion of the CHIP certificate
728 * into X.509 DER encoded form.
730 * @param reader A TLVReader positioned at the beginning of the TBS portion
731 * (certificate serial number) of the CHIP certificates.
732 * @param writer A reference to the ASN1Writer to store DER encoded TBS portion of
733 * the CHIP certificate.
734 * @param certData Structure containing data extracted from the TBS portion of the
737 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
739 CHIP_ERROR DecodeConvertTBSCert(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
744 // tbsCertificate TBSCertificate,
745 // TBSCertificate ::= SEQUENCE
748 // version [0] EXPLICIT Version DEFAULT v1
749 ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
751 // Version ::= INTEGER { v1(0), v2(1), v3(2) }
752 ASN1_ENCODE_INTEGER(2);
754 ASN1_END_CONSTRUCTED;
756 err = reader.Next(kTLVType_ByteString, ContextTag(kTag_SerialNumber));
759 // serialNumber CertificateSerialNumber
760 // CertificateSerialNumber ::= INTEGER
761 err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, reader);
764 // signature AlgorithmIdentifier
765 // AlgorithmIdentifier ::= SEQUENCE
771 err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_SignatureAlgorithm));
774 err = reader.Get(sigAlgoId);
777 VerifyOrExit(sigAlgoId <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
779 sigAlgoOID = GetOID(kOIDCategory_SigAlgo, static_cast<uint8_t>(sigAlgoId));
780 ASN1_ENCODE_OBJECT_ID(sigAlgoOID);
782 certData.mSigAlgoOID = sigAlgoOID;
787 err = reader.Next(kTLVType_List, ContextTag(kTag_Issuer));
789 err = DecodeConvertDN(reader, writer, certData.mIssuerDN);
792 // validity Validity,
793 err = DecodeConvertValidity(reader, writer, certData);
797 err = reader.Next(kTLVType_List, ContextTag(kTag_Subject));
799 err = DecodeConvertDN(reader, writer, certData.mSubjectDN);
802 // subjectPublicKeyInfo SubjectPublicKeyInfo,
803 err = DecodeConvertSubjectPublicKeyInfo(reader, writer, certData);
806 // If the next element is a certificate extension...
809 tag = reader.GetTag();
810 if (IsCertificateExtensionTag(tag))
812 err = DecodeConvertExtensions(reader, writer, certData);
822 static CHIP_ERROR DecodeConvertCert(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
826 TLVType containerType;
828 if (reader.GetType() == kTLVType_NotSpecified)
833 VerifyOrExit(reader.GetType() == kTLVType_Structure, err = CHIP_ERROR_WRONG_TLV_TYPE);
834 tag = reader.GetTag();
835 VerifyOrExit(tag == ProfileTag(kProtocol_OpCredentials, kTag_ChipCertificate) || tag == AnonymousTag,
836 err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
838 err = reader.EnterContainer(containerType);
841 // Certificate ::= SEQUENCE
844 // tbsCertificate TBSCertificate,
845 err = DecodeConvertTBSCert(reader, writer, certData);
848 // signatureAlgorithm AlgorithmIdentifier
849 // AlgorithmIdentifier ::= SEQUENCE
850 ASN1_START_SEQUENCE { ASN1_ENCODE_OBJECT_ID(static_cast<OID>(certData.mSigAlgoOID)); }
853 // signatureValue BIT STRING
854 err = DecodeConvertECDSASignature(reader, writer, certData);
859 // Verify no more elements in certificate.
860 err = reader.VerifyEndOfContainer();
863 err = reader.ExitContainer(containerType);
870 DLL_EXPORT CHIP_ERROR ConvertChipCertToX509Cert(const uint8_t * chipCert, uint32_t chipCertLen, uint8_t * x509CertBuf,
871 uint32_t x509CertBufSize, uint32_t & x509CertLen)
876 ChipCertificateData certData;
878 reader.Init(chipCert, chipCertLen);
880 writer.Init(x509CertBuf, x509CertBufSize);
882 err = DecodeConvertCert(reader, writer, certData);
885 err = writer.Finalize();
888 x509CertLen = writer.GetLengthWritten();
894 CHIP_ERROR DecodeChipCert(const uint8_t * chipCert, uint32_t chipCertLen, ChipCertificateData & certData)
898 reader.Init(chipCert, chipCertLen);
900 return DecodeChipCert(reader, certData);
903 CHIP_ERROR DecodeChipCert(TLVReader & reader, ChipCertificateData & certData)
907 writer.InitNullWriter();
911 return DecodeConvertCert(reader, writer, certData);
914 CHIP_ERROR DecodeChipDN(TLVReader & reader, ChipDN & dn)
918 writer.InitNullWriter();
922 return DecodeConvertDN(reader, writer, dn);
925 } // namespace Credentials