Apply Upstream code (2021-03-15)
[platform/upstream/connectedhomeip.git] / src / credentials / CHIPCertToX509.cpp
1 /*
2  *
3  *    Copyright (c) 2020-2021 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 CHIP
23  *      TLV-encoded certificate to a standard X.509 certificate.
24  *
25  */
26
27 #ifndef __STDC_LIMIT_MACROS
28 #define __STDC_LIMIT_MACROS
29 #endif
30
31 #include <inttypes.h>
32 #include <stddef.h>
33
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>
43
44 namespace chip {
45 namespace Credentials {
46
47 using namespace chip::ASN1;
48 using namespace chip::TLV;
49 using namespace chip::Protocols;
50
51 inline bool IsCertificateExtensionTag(uint64_t tag)
52 {
53     if (IsContextTag(tag))
54     {
55         uint32_t tagNum = TagNumFromTag(tag);
56         return (tagNum >= kCertificateExtensionTagsStart && tagNum <= kCertificateExtensionTagsEnd);
57     }
58
59     return false;
60 }
61
62 static CHIP_ERROR DecodeConvertDN(TLVReader & reader, ASN1Writer & writer, ChipDN & dn)
63 {
64     CHIP_ERROR err;
65     TLVType outerContainer;
66     TLVType elemType;
67     uint64_t tlvTag;
68     uint32_t tlvTagNum;
69     OID attrOID;
70     uint32_t asn1Tag;
71     const uint8_t * asn1AttrVal;
72     uint32_t asn1AttrValLen;
73     uint8_t chipIdStr[17];
74
75     // Enter the List TLV element that represents the DN in TLV format.
76     err = reader.EnterContainer(outerContainer);
77     SuccessOrExit(err);
78
79     // Read the first TLV element in the List.  This represents the first RDN in the original ASN.1 DN.
80     //
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
83     // one attribute.
84     //
85     err = reader.Next();
86     SuccessOrExit(err);
87
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);
92
93     // Get the element type.
94     elemType = reader.GetType();
95
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.
100     //
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.
106     //
107     attrOID = GetOID(kOIDCategory_AttributeType, static_cast<uint8_t>(tlvTagNum & 0x7f));
108
109     // Save the attribute OID in the caller's DN structure.
110     dn.mAttrOID = attrOID;
111
112     // If the attribute is one of the CHIP-defined X.509 attributes that contains a CHIP id...
113     if (IsChipIdX509Attr(attrOID))
114     {
115         // Verify that the underlying TLV data type is unsigned integer.
116         VerifyOrExit(elemType == kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE);
117
118         // Read the value of the CHIP id.
119         uint64_t chipId;
120         err = reader.Get(chipId);
121         SuccessOrExit(err);
122
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;
127         asn1AttrValLen = 16;
128
129         // The ASN.1 tag for CHIP id attributes is always UTF8String.
130         asn1Tag = kASN1UniversalTag_UTF8String;
131
132         // Save the CHIP id value in the caller's DN structure.
133         dn.mAttrValue.mChipId = chipId;
134     }
135
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...
138     else
139     {
140         // Verify that the underlying data type is UTF8 string.
141         VerifyOrExit(elemType == kTLVType_UTF8String, err = CHIP_ERROR_WRONG_TLV_TYPE);
142
143         // Get a pointer the underlying string data, plus its length.
144         err = reader.GetDataPtr(asn1AttrVal);
145         SuccessOrExit(err);
146         asn1AttrValLen = reader.GetLength();
147
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))
154         {
155             asn1Tag = kASN1UniversalTag_UTF8String;
156         }
157         else if (attrOID == kOID_AttributeType_DomainComponent)
158         {
159             asn1Tag = kASN1UniversalTag_IA5String;
160         }
161         else
162         {
163             asn1Tag = (tlvTagNum & 0x80) ? kASN1UniversalTag_PrintableString : kASN1UniversalTag_UTF8String;
164         }
165
166         // Save the string value in the caller's DN structure.
167         dn.mAttrValue.mString.mValue = asn1AttrVal;
168         dn.mAttrValue.mString.mLen   = asn1AttrValLen;
169     }
170
171     // Verify that there are no further elements in the DN.
172     err = reader.VerifyEndOfContainer();
173     SuccessOrExit(err);
174
175     err = reader.ExitContainer(outerContainer);
176     SuccessOrExit(err);
177
178     // Write the ASN.1 representation of the DN...
179
180     // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
181     ASN1_START_SEQUENCE
182     {
183         // RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
184         ASN1_START_SET
185         {
186             // AttributeTypeAndValue ::= SEQUENCE
187             ASN1_START_SEQUENCE
188             {
189                 // type AttributeType
190                 // AttributeType ::= OBJECT IDENTIFIER
191                 ASN1_ENCODE_OBJECT_ID(attrOID);
192
193                 // value AttributeValue
194                 // AttributeValue ::= ANY -- DEFINED BY AttributeType
195                 err = writer.PutString(asn1Tag, Uint8::to_const_char(asn1AttrVal), static_cast<uint16_t>(asn1AttrValLen));
196                 SuccessOrExit(err);
197             }
198             ASN1_END_SEQUENCE;
199         }
200         ASN1_END_SET;
201     }
202     ASN1_END_SEQUENCE;
203
204 exit:
205     return err;
206 }
207
208 static CHIP_ERROR DecodeConvertValidity(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
209 {
210     CHIP_ERROR err;
211     ASN1UniversalTime asn1Time;
212     uint64_t chipEpochTime;
213
214     ASN1_START_SEQUENCE
215     {
216         err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_NotBefore));
217         SuccessOrExit(err);
218
219         err = reader.Get(chipEpochTime);
220         SuccessOrExit(err);
221
222         VerifyOrExit(chipEpochTime <= UINT32_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
223         certData.mNotBeforeTime = static_cast<uint32_t>(chipEpochTime);
224
225         err = ChipEpochToASN1Time(static_cast<uint32_t>(chipEpochTime), asn1Time);
226         SuccessOrExit(err);
227
228         ASN1_ENCODE_TIME(asn1Time);
229
230         err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_NotAfter));
231         SuccessOrExit(err);
232
233         err = reader.Get(chipEpochTime);
234         SuccessOrExit(err);
235
236         VerifyOrExit(chipEpochTime <= UINT32_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
237         certData.mNotAfterTime = static_cast<uint32_t>(chipEpochTime);
238
239         err = ChipEpochToASN1Time(static_cast<uint32_t>(chipEpochTime), asn1Time);
240         SuccessOrExit(err);
241
242         ASN1_ENCODE_TIME(asn1Time);
243     }
244     ASN1_END_SEQUENCE;
245
246 exit:
247     return err;
248 }
249
250 static CHIP_ERROR DecodeConvertSubjectPublicKeyInfo(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
251 {
252     CHIP_ERROR err;
253     uint64_t pubKeyAlgoId, pubKeyCurveId;
254     OID pubKeyAlgoOID;
255
256     err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_PublicKeyAlgorithm));
257     SuccessOrExit(err);
258     err = reader.Get(pubKeyAlgoId);
259     SuccessOrExit(err);
260     VerifyOrExit(pubKeyAlgoId <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
261
262     pubKeyAlgoOID           = GetOID(kOIDCategory_PubKeyAlgo, static_cast<uint8_t>(pubKeyAlgoId));
263     certData.mPubKeyAlgoOID = pubKeyAlgoOID;
264
265     VerifyOrExit(pubKeyAlgoOID == kOID_PubKeyAlgo_ECPublicKey, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
266
267     err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_EllipticCurveIdentifier));
268     SuccessOrExit(err);
269     err = reader.Get(pubKeyCurveId);
270     SuccessOrExit(err);
271     VerifyOrExit(pubKeyCurveId <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
272
273     certData.mPubKeyCurveOID = GetOID(kOIDCategory_EllipticCurve, static_cast<uint8_t>(pubKeyCurveId));
274
275     // subjectPublicKeyInfo SubjectPublicKeyInfo,
276     ASN1_START_SEQUENCE
277     {
278         // algorithm AlgorithmIdentifier,
279         // AlgorithmIdentifier ::= SEQUENCE
280         ASN1_START_SEQUENCE
281         {
282             // algorithm OBJECT IDENTIFIER,
283             ASN1_ENCODE_OBJECT_ID(pubKeyAlgoOID);
284
285             // EcpkParameters ::= CHOICE {
286             //     ecParameters  ECParameters,
287             //     namedCurve    OBJECT IDENTIFIER,
288             //     implicitlyCA  NULL }
289             //
290             // (Only namedCurve supported).
291             //
292             ASN1_ENCODE_OBJECT_ID(certData.mPubKeyCurveOID);
293         }
294         ASN1_END_SEQUENCE;
295
296         err = reader.Next(kTLVType_ByteString, ContextTag(kTag_EllipticCurvePublicKey));
297         SuccessOrExit(err);
298
299         err = reader.GetDataPtr(certData.mPublicKey);
300         SuccessOrExit(err);
301
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);
305
306         // For EC certs, the subjectPublicKey BIT STRING contains the X9.62 encoded EC point.
307         err = writer.PutBitString(0, certData.mPublicKey, certData.mPublicKeyLen);
308         SuccessOrExit(err);
309     }
310     ASN1_END_SEQUENCE;
311
312 exit:
313     return err;
314 }
315
316 static CHIP_ERROR DecodeConvertAuthorityKeyIdentifierExtension(TLVReader & reader, ASN1Writer & writer,
317                                                                ChipCertificateData & certData)
318 {
319     CHIP_ERROR err;
320     uint32_t len;
321
322     certData.mCertFlags.Set(CertFlags::kExtPresent_AuthKeyId);
323
324     // AuthorityKeyIdentifier extension MUST be marked as non-critical (default).
325
326     // AuthorityKeyIdentifier ::= SEQUENCE
327     ASN1_START_SEQUENCE
328     {
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);
333
334         err = reader.GetDataPtr(certData.mAuthKeyId.mId);
335         SuccessOrExit(err);
336
337         len = reader.GetLength();
338         VerifyOrExit(len == kKeyIdentifierLength, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
339
340         certData.mAuthKeyId.mLen = static_cast<uint8_t>(len);
341
342         err = writer.PutOctetString(kASN1TagClass_ContextSpecific, 0, certData.mAuthKeyId.mId, certData.mAuthKeyId.mLen);
343         SuccessOrExit(err);
344     }
345     ASN1_END_SEQUENCE;
346
347 exit:
348     return err;
349 }
350
351 static CHIP_ERROR DecodeConvertSubjectKeyIdentifierExtension(TLVReader & reader, ASN1Writer & writer,
352                                                              ChipCertificateData & certData)
353 {
354     CHIP_ERROR err;
355     uint32_t len;
356
357     certData.mCertFlags.Set(CertFlags::kExtPresent_SubjectKeyId);
358
359     // SubjectKeyIdentifier extension MUST be marked as non-critical (default).
360
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);
365
366     len = reader.GetLength();
367     VerifyOrExit(len == kKeyIdentifierLength, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
368
369     certData.mSubjectKeyId.mLen = static_cast<uint8_t>(len);
370
371     err = reader.GetDataPtr(certData.mSubjectKeyId.mId);
372     SuccessOrExit(err);
373
374     err = writer.PutOctetString(certData.mSubjectKeyId.mId, certData.mSubjectKeyId.mLen);
375     SuccessOrExit(err);
376
377 exit:
378     return err;
379 }
380
381 static CHIP_ERROR DecodeConvertKeyUsageExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
382 {
383     CHIP_ERROR err;
384     uint64_t keyUsageBits;
385
386     certData.mCertFlags.Set(CertFlags::kExtPresent_KeyUsage);
387
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);
391
392     err = reader.Get(keyUsageBits);
393     SuccessOrExit(err);
394
395     VerifyOrExit(keyUsageBits <= UINT16_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
396
397     {
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);
404
405         ASN1_ENCODE_BIT_STRING(static_cast<uint16_t>(keyUsageBits));
406
407         certData.mKeyUsageFlags = keyUsageFlags;
408     }
409
410 exit:
411     return err;
412 }
413
414 static CHIP_ERROR DecodeConvertBasicConstraintsExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
415 {
416     CHIP_ERROR err, nextRes;
417     TLVType outerContainer;
418
419     certData.mCertFlags.Set(CertFlags::kExtPresent_BasicConstraints);
420
421     // BasicConstraints ::= SEQUENCE
422     ASN1_START_SEQUENCE
423     {
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);
426
427         err = reader.EnterContainer(outerContainer);
428         SuccessOrExit(err);
429
430         // cA BOOLEAN DEFAULT FALSE
431         {
432             bool isCA;
433
434             err = reader.Next(kTLVType_Boolean, ContextTag(kTag_BasicConstraints_IsCA));
435             SuccessOrExit(err);
436
437             err = reader.Get(isCA);
438             SuccessOrExit(err);
439
440             if (isCA)
441             {
442                 ASN1_ENCODE_BOOLEAN(true);
443                 certData.mCertFlags.Set(CertFlags::kIsCA);
444             }
445
446             nextRes = reader.Next();
447             VerifyOrExit(nextRes == CHIP_NO_ERROR || nextRes == CHIP_END_OF_TLV, err = nextRes);
448         }
449
450         // pathLenConstraint INTEGER (0..MAX) OPTIONAL
451         if (reader.GetTag() == ContextTag(kTag_BasicConstraints_PathLenConstraint))
452         {
453             uint64_t pathLenConstraint;
454
455             VerifyOrExit(reader.GetType() == kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE);
456
457             err = reader.Get(pathLenConstraint);
458             SuccessOrExit(err);
459
460             VerifyOrExit(pathLenConstraint <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
461
462             ASN1_ENCODE_INTEGER(static_cast<int64_t>(pathLenConstraint));
463
464             certData.mPathLenConstraint = static_cast<uint8_t>(pathLenConstraint);
465
466             certData.mCertFlags.Set(CertFlags::kPathLenConstraintPresent);
467
468             reader.Next();
469         }
470
471         err = reader.VerifyEndOfContainer();
472         SuccessOrExit(err);
473
474         err = reader.ExitContainer(outerContainer);
475         SuccessOrExit(err);
476     }
477     ASN1_END_SEQUENCE;
478
479 exit:
480     return err;
481 }
482
483 static CHIP_ERROR DecodeConvertExtendedKeyUsageExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
484 {
485     CHIP_ERROR err, nextRes;
486     TLVType outerContainer;
487
488     certData.mCertFlags.Set(CertFlags::kExtPresent_ExtendedKeyUsage);
489
490     // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
491     ASN1_START_SEQUENCE
492     {
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);
495
496         err = reader.EnterContainer(outerContainer);
497         SuccessOrExit(err);
498
499         while ((nextRes = reader.Next(kTLVType_UnsignedInteger, AnonymousTag)) == CHIP_NO_ERROR)
500         {
501             uint64_t keyPurposeId;
502             OID keyPurposeOID;
503
504             err = reader.Get(keyPurposeId);
505             SuccessOrExit(err);
506
507             VerifyOrExit(keyPurposeId <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
508
509             keyPurposeOID = GetOID(kOIDCategory_KeyPurpose, static_cast<uint8_t>(keyPurposeId));
510
511             // KeyPurposeId ::= OBJECT IDENTIFIER
512             ASN1_ENCODE_OBJECT_ID(keyPurposeOID);
513
514             certData.mKeyPurposeFlags.Set(static_cast<KeyPurposeFlags>(0x01 << (keyPurposeId - 1)));
515         }
516
517         VerifyOrExit(nextRes == CHIP_END_OF_TLV, err = nextRes);
518
519         err = reader.ExitContainer(outerContainer);
520         SuccessOrExit(err);
521     }
522     ASN1_END_SEQUENCE;
523
524 exit:
525     return err;
526 }
527
528 static CHIP_ERROR DecodeConvertExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
529 {
530     CHIP_ERROR err;
531     uint64_t extensionTagNum = TagNumFromTag(reader.GetTag());
532     OID extensionOID;
533
534     if (extensionTagNum == kTag_AuthorityKeyIdentifier)
535     {
536         extensionOID = kOID_Extension_AuthorityKeyIdentifier;
537     }
538     else if (extensionTagNum == kTag_SubjectKeyIdentifier)
539     {
540         extensionOID = kOID_Extension_SubjectKeyIdentifier;
541     }
542     else if (extensionTagNum == kTag_KeyUsage)
543     {
544         extensionOID = kOID_Extension_KeyUsage;
545     }
546     else if (extensionTagNum == kTag_BasicConstraints)
547     {
548         extensionOID = kOID_Extension_BasicConstraints;
549     }
550     else if (extensionTagNum == kTag_ExtendedKeyUsage)
551     {
552         extensionOID = kOID_Extension_ExtendedKeyUsage;
553     }
554     else
555     {
556         ExitNow(err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
557     }
558
559     // Extension ::= SEQUENCE
560     ASN1_START_SEQUENCE
561     {
562         // extnID OBJECT IDENTIFIER,
563         ASN1_ENCODE_OBJECT_ID(extensionOID);
564
565         // BasicConstraints, KeyUsage and ExtKeyUsage extensions MUST be marked as critical.
566         if (extensionTagNum == kTag_KeyUsage || extensionTagNum == kTag_BasicConstraints ||
567             extensionTagNum == kTag_ExtendedKeyUsage)
568         {
569             ASN1_ENCODE_BOOLEAN(true);
570         }
571
572         // extnValue OCTET STRING
573         //           -- contains the DER encoding of an ASN.1 value
574         //           -- corresponding to the extension type identified
575         //           -- by extnID
576         ASN1_START_OCTET_STRING_ENCAPSULATED
577         {
578             if (extensionTagNum == kTag_AuthorityKeyIdentifier)
579             {
580                 err = DecodeConvertAuthorityKeyIdentifierExtension(reader, writer, certData);
581             }
582             else if (extensionTagNum == kTag_SubjectKeyIdentifier)
583             {
584                 err = DecodeConvertSubjectKeyIdentifierExtension(reader, writer, certData);
585             }
586             else if (extensionTagNum == kTag_KeyUsage)
587             {
588                 err = DecodeConvertKeyUsageExtension(reader, writer, certData);
589             }
590             else if (extensionTagNum == kTag_BasicConstraints)
591             {
592                 err = DecodeConvertBasicConstraintsExtension(reader, writer, certData);
593             }
594             else if (extensionTagNum == kTag_ExtendedKeyUsage)
595             {
596                 err = DecodeConvertExtendedKeyUsageExtension(reader, writer, certData);
597             }
598             else
599             {
600                 err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT;
601             }
602             SuccessOrExit(err);
603         }
604         ASN1_END_ENCAPSULATED;
605     }
606     ASN1_END_SEQUENCE;
607
608 exit:
609     return err;
610 }
611
612 static CHIP_ERROR DecodeConvertExtensions(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
613 {
614     CHIP_ERROR err;
615     uint64_t tag;
616
617     // extensions [3] EXPLICIT Extensions OPTIONAL
618     ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 3)
619     {
620         // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
621         ASN1_START_SEQUENCE
622         {
623             while (true)
624             {
625                 err = DecodeConvertExtension(reader, writer, certData);
626                 SuccessOrExit(err);
627
628                 // Break the loop if the next certificate element is NOT an extension.
629                 err = reader.Next();
630                 SuccessOrExit(err);
631                 tag = reader.GetTag();
632                 if (!IsCertificateExtensionTag(tag))
633                 {
634                     break;
635                 }
636             }
637         }
638         ASN1_END_SEQUENCE;
639     }
640     ASN1_END_CONSTRUCTED;
641
642 exit:
643     return err;
644 }
645
646 CHIP_ERROR DecodeECDSASignature(TLVReader & reader, ChipCertificateData & certData)
647 {
648     CHIP_ERROR err;
649     TLVType containerType;
650     uint32_t len;
651
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);
655
656     err = reader.EnterContainer(containerType);
657     SuccessOrExit(err);
658
659     // r INTEGER
660     err = reader.Next(kTLVType_ByteString, ContextTag(kTag_ECDSASignature_r));
661     SuccessOrExit(err);
662
663     err = reader.GetDataPtr(certData.mSignature.R);
664     SuccessOrExit(err);
665
666     len = reader.GetLength();
667     VerifyOrExit(len <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
668
669     certData.mSignature.RLen = static_cast<uint8_t>(len);
670
671     // s INTEGER
672     err = reader.Next(kTLVType_ByteString, ContextTag(kTag_ECDSASignature_s));
673     SuccessOrExit(err);
674
675     err = reader.GetDataPtr(certData.mSignature.S);
676     SuccessOrExit(err);
677
678     len = reader.GetLength();
679     VerifyOrExit(len <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
680
681     certData.mSignature.SLen = static_cast<uint8_t>(len);
682
683     // Verify no more elements in the signature.
684     reader.Next();
685     err = reader.VerifyEndOfContainer();
686     SuccessOrExit(err);
687
688     err = reader.ExitContainer(containerType);
689     SuccessOrExit(err);
690
691 exit:
692     return err;
693 }
694
695 static CHIP_ERROR DecodeConvertECDSASignature(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
696 {
697     CHIP_ERROR err;
698
699     err = DecodeECDSASignature(reader, certData);
700     SuccessOrExit(err);
701
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
705     {
706         // Ecdsa-Sig-Value ::= SEQUENCE
707         ASN1_START_SEQUENCE
708         {
709             // r INTEGER
710             err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, certData.mSignature.R,
711                                   certData.mSignature.RLen);
712             SuccessOrExit(err);
713
714             // s INTEGER
715             err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, certData.mSignature.S,
716                                   certData.mSignature.SLen);
717             SuccessOrExit(err);
718         }
719         ASN1_END_SEQUENCE;
720     }
721     ASN1_END_ENCAPSULATED;
722
723 exit:
724     return err;
725 }
726
727 /**
728  * @brief Decode and convert the To-Be-Signed (TBS) portion of the CHIP certificate
729  *        into X.509 DER encoded form.
730  *
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
736  *                  CHIP certificate.
737  *
738  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
739  **/
740 CHIP_ERROR DecodeConvertTBSCert(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
741 {
742     CHIP_ERROR err;
743     uint64_t tag;
744
745     // tbsCertificate TBSCertificate,
746     // TBSCertificate ::= SEQUENCE
747     ASN1_START_SEQUENCE
748     {
749         // version [0] EXPLICIT Version DEFAULT v1
750         ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
751         {
752             // Version ::= INTEGER { v1(0), v2(1), v3(2) }
753             ASN1_ENCODE_INTEGER(2);
754         }
755         ASN1_END_CONSTRUCTED;
756
757         err = reader.Next(kTLVType_ByteString, ContextTag(kTag_SerialNumber));
758         SuccessOrExit(err);
759
760         // serialNumber CertificateSerialNumber
761         // CertificateSerialNumber ::= INTEGER
762         err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, reader);
763         SuccessOrExit(err);
764
765         // signature AlgorithmIdentifier
766         // AlgorithmIdentifier ::= SEQUENCE
767         ASN1_START_SEQUENCE
768         {
769             uint64_t sigAlgoId;
770             OID sigAlgoOID;
771
772             err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_SignatureAlgorithm));
773             SuccessOrExit(err);
774
775             err = reader.Get(sigAlgoId);
776             SuccessOrExit(err);
777
778             VerifyOrExit(sigAlgoId <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
779
780             sigAlgoOID = GetOID(kOIDCategory_SigAlgo, static_cast<uint8_t>(sigAlgoId));
781             ASN1_ENCODE_OBJECT_ID(sigAlgoOID);
782
783             certData.mSigAlgoOID = sigAlgoOID;
784         }
785         ASN1_END_SEQUENCE;
786
787         // issuer Name
788         err = reader.Next(kTLVType_List, ContextTag(kTag_Issuer));
789         SuccessOrExit(err);
790         err = DecodeConvertDN(reader, writer, certData.mIssuerDN);
791         SuccessOrExit(err);
792
793         // validity Validity,
794         err = DecodeConvertValidity(reader, writer, certData);
795         SuccessOrExit(err);
796
797         // subject Name
798         err = reader.Next(kTLVType_List, ContextTag(kTag_Subject));
799         SuccessOrExit(err);
800         err = DecodeConvertDN(reader, writer, certData.mSubjectDN);
801         SuccessOrExit(err);
802
803         // subjectPublicKeyInfo SubjectPublicKeyInfo,
804         err = DecodeConvertSubjectPublicKeyInfo(reader, writer, certData);
805         SuccessOrExit(err);
806
807         // If the next element is a certificate extension...
808         err = reader.Next();
809         SuccessOrExit(err);
810         tag = reader.GetTag();
811         if (IsCertificateExtensionTag(tag))
812         {
813             err = DecodeConvertExtensions(reader, writer, certData);
814             SuccessOrExit(err);
815         }
816     }
817     ASN1_END_SEQUENCE;
818
819 exit:
820     return err;
821 }
822
823 static CHIP_ERROR DecodeConvertCert(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
824 {
825     CHIP_ERROR err;
826     uint64_t tag;
827     TLVType containerType;
828
829     if (reader.GetType() == kTLVType_NotSpecified)
830     {
831         err = reader.Next();
832         SuccessOrExit(err);
833     }
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);
838
839     err = reader.EnterContainer(containerType);
840     SuccessOrExit(err);
841
842     // Certificate ::= SEQUENCE
843     ASN1_START_SEQUENCE
844     {
845         // tbsCertificate TBSCertificate,
846         err = DecodeConvertTBSCert(reader, writer, certData);
847         SuccessOrExit(err);
848
849         // signatureAlgorithm   AlgorithmIdentifier
850         // AlgorithmIdentifier ::= SEQUENCE
851         ASN1_START_SEQUENCE { ASN1_ENCODE_OBJECT_ID(static_cast<OID>(certData.mSigAlgoOID)); }
852         ASN1_END_SEQUENCE;
853
854         // signatureValue BIT STRING
855         err = DecodeConvertECDSASignature(reader, writer, certData);
856         SuccessOrExit(err);
857     }
858     ASN1_END_SEQUENCE;
859
860     // Verify no more elements in certificate.
861     err = reader.VerifyEndOfContainer();
862     SuccessOrExit(err);
863
864     err = reader.ExitContainer(containerType);
865     SuccessOrExit(err);
866
867 exit:
868     return err;
869 }
870
871 DLL_EXPORT CHIP_ERROR ConvertChipCertToX509Cert(const uint8_t * chipCert, uint32_t chipCertLen, uint8_t * x509CertBuf,
872                                                 uint32_t x509CertBufSize, uint32_t & x509CertLen)
873 {
874     CHIP_ERROR err;
875     TLVReader reader;
876     ASN1Writer writer;
877     ChipCertificateData certData;
878
879     reader.Init(chipCert, chipCertLen);
880
881     writer.Init(x509CertBuf, x509CertBufSize);
882
883     err = DecodeConvertCert(reader, writer, certData);
884     SuccessOrExit(err);
885
886     err = writer.Finalize();
887     SuccessOrExit(err);
888
889     x509CertLen = writer.GetLengthWritten();
890
891 exit:
892     return err;
893 }
894
895 CHIP_ERROR DecodeChipCert(const uint8_t * chipCert, uint32_t chipCertLen, ChipCertificateData & certData)
896 {
897     TLVReader reader;
898
899     reader.Init(chipCert, chipCertLen);
900
901     return DecodeChipCert(reader, certData);
902 }
903
904 CHIP_ERROR DecodeChipCert(TLVReader & reader, ChipCertificateData & certData)
905 {
906     ASN1Writer writer;
907
908     writer.InitNullWriter();
909
910     certData.Clear();
911
912     return DecodeConvertCert(reader, writer, certData);
913 }
914
915 CHIP_ERROR DecodeChipDN(TLVReader & reader, ChipDN & dn)
916 {
917     ASN1Writer writer;
918
919     writer.InitNullWriter();
920
921     dn.Clear();
922
923     return DecodeConvertDN(reader, writer, dn);
924 }
925
926 } // namespace Credentials
927 } // namespace chip