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;
386 certData.mCertFlags.Set(CertFlags::kExtPresent_KeyUsage);
388 // KeyUsage ::= BIT STRING
389 VerifyOrExit(reader.GetTag() == ContextTag(kTag_KeyUsage), err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
390 VerifyOrExit(reader.GetType() == kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE);
392 err = reader.Get(keyUsageBits);
395 VerifyOrExit(keyUsageBits <= UINT16_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
398 BitFlags<KeyUsageFlags> keyUsageFlags(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;
414 static CHIP_ERROR DecodeConvertBasicConstraintsExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
416 CHIP_ERROR err, nextRes;
417 TLVType outerContainer;
419 certData.mCertFlags.Set(CertFlags::kExtPresent_BasicConstraints);
421 // BasicConstraints ::= SEQUENCE
424 VerifyOrExit(reader.GetTag() == ContextTag(kTag_BasicConstraints), err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
425 VerifyOrExit(reader.GetType() == kTLVType_Structure, err = CHIP_ERROR_WRONG_TLV_TYPE);
427 err = reader.EnterContainer(outerContainer);
430 // cA BOOLEAN DEFAULT FALSE
434 err = reader.Next(kTLVType_Boolean, ContextTag(kTag_BasicConstraints_IsCA));
437 err = reader.Get(isCA);
442 ASN1_ENCODE_BOOLEAN(true);
443 certData.mCertFlags.Set(CertFlags::kIsCA);
446 nextRes = reader.Next();
447 VerifyOrExit(nextRes == CHIP_NO_ERROR || nextRes == CHIP_END_OF_TLV, err = nextRes);
450 // pathLenConstraint INTEGER (0..MAX) OPTIONAL
451 if (reader.GetTag() == ContextTag(kTag_BasicConstraints_PathLenConstraint))
453 uint64_t pathLenConstraint;
455 VerifyOrExit(reader.GetType() == kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE);
457 err = reader.Get(pathLenConstraint);
460 VerifyOrExit(pathLenConstraint <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
462 ASN1_ENCODE_INTEGER(static_cast<int64_t>(pathLenConstraint));
464 certData.mPathLenConstraint = static_cast<uint8_t>(pathLenConstraint);
466 certData.mCertFlags.Set(CertFlags::kPathLenConstraintPresent);
471 err = reader.VerifyEndOfContainer();
474 err = reader.ExitContainer(outerContainer);
483 static CHIP_ERROR DecodeConvertExtendedKeyUsageExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
485 CHIP_ERROR err, nextRes;
486 TLVType outerContainer;
488 certData.mCertFlags.Set(CertFlags::kExtPresent_ExtendedKeyUsage);
490 // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
493 VerifyOrExit(reader.GetTag() == ContextTag(kTag_ExtendedKeyUsage), err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
494 VerifyOrExit(reader.GetType() == kTLVType_Array, err = CHIP_ERROR_WRONG_TLV_TYPE);
496 err = reader.EnterContainer(outerContainer);
499 while ((nextRes = reader.Next(kTLVType_UnsignedInteger, AnonymousTag)) == CHIP_NO_ERROR)
501 uint64_t keyPurposeId;
504 err = reader.Get(keyPurposeId);
507 VerifyOrExit(keyPurposeId <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
509 keyPurposeOID = GetOID(kOIDCategory_KeyPurpose, static_cast<uint8_t>(keyPurposeId));
511 // KeyPurposeId ::= OBJECT IDENTIFIER
512 ASN1_ENCODE_OBJECT_ID(keyPurposeOID);
514 certData.mKeyPurposeFlags.Set(static_cast<KeyPurposeFlags>(0x01 << (keyPurposeId - 1)));
517 VerifyOrExit(nextRes == CHIP_END_OF_TLV, err = nextRes);
519 err = reader.ExitContainer(outerContainer);
528 static CHIP_ERROR DecodeConvertExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
531 uint64_t extensionTagNum = TagNumFromTag(reader.GetTag());
534 if (extensionTagNum == kTag_AuthorityKeyIdentifier)
536 extensionOID = kOID_Extension_AuthorityKeyIdentifier;
538 else if (extensionTagNum == kTag_SubjectKeyIdentifier)
540 extensionOID = kOID_Extension_SubjectKeyIdentifier;
542 else if (extensionTagNum == kTag_KeyUsage)
544 extensionOID = kOID_Extension_KeyUsage;
546 else if (extensionTagNum == kTag_BasicConstraints)
548 extensionOID = kOID_Extension_BasicConstraints;
550 else if (extensionTagNum == kTag_ExtendedKeyUsage)
552 extensionOID = kOID_Extension_ExtendedKeyUsage;
556 ExitNow(err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
559 // Extension ::= SEQUENCE
562 // extnID OBJECT IDENTIFIER,
563 ASN1_ENCODE_OBJECT_ID(extensionOID);
565 // BasicConstraints, KeyUsage and ExtKeyUsage extensions MUST be marked as critical.
566 if (extensionTagNum == kTag_KeyUsage || extensionTagNum == kTag_BasicConstraints ||
567 extensionTagNum == kTag_ExtendedKeyUsage)
569 ASN1_ENCODE_BOOLEAN(true);
572 // extnValue OCTET STRING
573 // -- contains the DER encoding of an ASN.1 value
574 // -- corresponding to the extension type identified
576 ASN1_START_OCTET_STRING_ENCAPSULATED
578 if (extensionTagNum == kTag_AuthorityKeyIdentifier)
580 err = DecodeConvertAuthorityKeyIdentifierExtension(reader, writer, certData);
582 else if (extensionTagNum == kTag_SubjectKeyIdentifier)
584 err = DecodeConvertSubjectKeyIdentifierExtension(reader, writer, certData);
586 else if (extensionTagNum == kTag_KeyUsage)
588 err = DecodeConvertKeyUsageExtension(reader, writer, certData);
590 else if (extensionTagNum == kTag_BasicConstraints)
592 err = DecodeConvertBasicConstraintsExtension(reader, writer, certData);
594 else if (extensionTagNum == kTag_ExtendedKeyUsage)
596 err = DecodeConvertExtendedKeyUsageExtension(reader, writer, certData);
600 err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT;
604 ASN1_END_ENCAPSULATED;
612 static CHIP_ERROR DecodeConvertExtensions(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
617 // extensions [3] EXPLICIT Extensions OPTIONAL
618 ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 3)
620 // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
625 err = DecodeConvertExtension(reader, writer, certData);
628 // Break the loop if the next certificate element is NOT an extension.
631 tag = reader.GetTag();
632 if (!IsCertificateExtensionTag(tag))
640 ASN1_END_CONSTRUCTED;
646 CHIP_ERROR DecodeECDSASignature(TLVReader & reader, ChipCertificateData & certData)
649 TLVType containerType;
652 // Verify the tag and type
653 VerifyOrExit(reader.GetType() == kTLVType_Structure, err = CHIP_ERROR_WRONG_TLV_TYPE);
654 VerifyOrExit(reader.GetTag() == ContextTag(kTag_ECDSASignature), err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
656 err = reader.EnterContainer(containerType);
660 err = reader.Next(kTLVType_ByteString, ContextTag(kTag_ECDSASignature_r));
663 err = reader.GetDataPtr(certData.mSignature.R);
666 len = reader.GetLength();
667 VerifyOrExit(len <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
669 certData.mSignature.RLen = static_cast<uint8_t>(len);
672 err = reader.Next(kTLVType_ByteString, ContextTag(kTag_ECDSASignature_s));
675 err = reader.GetDataPtr(certData.mSignature.S);
678 len = reader.GetLength();
679 VerifyOrExit(len <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
681 certData.mSignature.SLen = static_cast<uint8_t>(len);
683 // Verify no more elements in the signature.
685 err = reader.VerifyEndOfContainer();
688 err = reader.ExitContainer(containerType);
695 static CHIP_ERROR DecodeConvertECDSASignature(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
699 err = DecodeECDSASignature(reader, certData);
702 // signatureValue BIT STRING
703 // Per RFC3279, the ECDSA signature value is encoded in DER encapsulated in the signatureValue BIT STRING.
704 ASN1_START_BIT_STRING_ENCAPSULATED
706 // Ecdsa-Sig-Value ::= SEQUENCE
710 err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, certData.mSignature.R,
711 certData.mSignature.RLen);
715 err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, certData.mSignature.S,
716 certData.mSignature.SLen);
721 ASN1_END_ENCAPSULATED;
728 * @brief Decode and convert the To-Be-Signed (TBS) portion of the CHIP certificate
729 * into X.509 DER encoded form.
731 * @param reader A TLVReader positioned at the beginning of the TBS portion
732 * (certificate serial number) of the CHIP certificates.
733 * @param writer A reference to the ASN1Writer to store DER encoded TBS portion of
734 * the CHIP certificate.
735 * @param certData Structure containing data extracted from the TBS portion of the
738 * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
740 CHIP_ERROR DecodeConvertTBSCert(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
745 // tbsCertificate TBSCertificate,
746 // TBSCertificate ::= SEQUENCE
749 // version [0] EXPLICIT Version DEFAULT v1
750 ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
752 // Version ::= INTEGER { v1(0), v2(1), v3(2) }
753 ASN1_ENCODE_INTEGER(2);
755 ASN1_END_CONSTRUCTED;
757 err = reader.Next(kTLVType_ByteString, ContextTag(kTag_SerialNumber));
760 // serialNumber CertificateSerialNumber
761 // CertificateSerialNumber ::= INTEGER
762 err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, reader);
765 // signature AlgorithmIdentifier
766 // AlgorithmIdentifier ::= SEQUENCE
772 err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_SignatureAlgorithm));
775 err = reader.Get(sigAlgoId);
778 VerifyOrExit(sigAlgoId <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
780 sigAlgoOID = GetOID(kOIDCategory_SigAlgo, static_cast<uint8_t>(sigAlgoId));
781 ASN1_ENCODE_OBJECT_ID(sigAlgoOID);
783 certData.mSigAlgoOID = sigAlgoOID;
788 err = reader.Next(kTLVType_List, ContextTag(kTag_Issuer));
790 err = DecodeConvertDN(reader, writer, certData.mIssuerDN);
793 // validity Validity,
794 err = DecodeConvertValidity(reader, writer, certData);
798 err = reader.Next(kTLVType_List, ContextTag(kTag_Subject));
800 err = DecodeConvertDN(reader, writer, certData.mSubjectDN);
803 // subjectPublicKeyInfo SubjectPublicKeyInfo,
804 err = DecodeConvertSubjectPublicKeyInfo(reader, writer, certData);
807 // If the next element is a certificate extension...
810 tag = reader.GetTag();
811 if (IsCertificateExtensionTag(tag))
813 err = DecodeConvertExtensions(reader, writer, certData);
823 static CHIP_ERROR DecodeConvertCert(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
827 TLVType containerType;
829 if (reader.GetType() == kTLVType_NotSpecified)
834 VerifyOrExit(reader.GetType() == kTLVType_Structure, err = CHIP_ERROR_WRONG_TLV_TYPE);
835 tag = reader.GetTag();
836 VerifyOrExit(tag == ProfileTag(kProtocol_OpCredentials, kTag_ChipCertificate) || tag == AnonymousTag,
837 err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
839 err = reader.EnterContainer(containerType);
842 // Certificate ::= SEQUENCE
845 // tbsCertificate TBSCertificate,
846 err = DecodeConvertTBSCert(reader, writer, certData);
849 // signatureAlgorithm AlgorithmIdentifier
850 // AlgorithmIdentifier ::= SEQUENCE
851 ASN1_START_SEQUENCE { ASN1_ENCODE_OBJECT_ID(static_cast<OID>(certData.mSigAlgoOID)); }
854 // signatureValue BIT STRING
855 err = DecodeConvertECDSASignature(reader, writer, certData);
860 // Verify no more elements in certificate.
861 err = reader.VerifyEndOfContainer();
864 err = reader.ExitContainer(containerType);
871 DLL_EXPORT CHIP_ERROR ConvertChipCertToX509Cert(const uint8_t * chipCert, uint32_t chipCertLen, uint8_t * x509CertBuf,
872 uint32_t x509CertBufSize, uint32_t & x509CertLen)
877 ChipCertificateData certData;
879 reader.Init(chipCert, chipCertLen);
881 writer.Init(x509CertBuf, x509CertBufSize);
883 err = DecodeConvertCert(reader, writer, certData);
886 err = writer.Finalize();
889 x509CertLen = writer.GetLengthWritten();
895 CHIP_ERROR DecodeChipCert(const uint8_t * chipCert, uint32_t chipCertLen, ChipCertificateData & certData)
899 reader.Init(chipCert, chipCertLen);
901 return DecodeChipCert(reader, certData);
904 CHIP_ERROR DecodeChipCert(TLVReader & reader, ChipCertificateData & certData)
908 writer.InitNullWriter();
912 return DecodeConvertCert(reader, writer, certData);
915 CHIP_ERROR DecodeChipDN(TLVReader & reader, ChipDN & dn)
919 writer.InitNullWriter();
923 return DecodeConvertDN(reader, writer, dn);
926 } // namespace Credentials