bb6fe2ccbe47455ed57314ba4ee38db02656df1b
[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     BitFlags<uint16_t, KeyUsageFlags> keyUsageFlags;
386
387     certData.mCertFlags.Set(CertFlags::kExtPresent_KeyUsage);
388
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);
392
393     err = reader.Get(keyUsageBits);
394     SuccessOrExit(err);
395
396     VerifyOrExit(keyUsageBits <= UINT16_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
397
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);
404
405     ASN1_ENCODE_BIT_STRING(static_cast<uint16_t>(keyUsageBits));
406
407     certData.mKeyUsageFlags = keyUsageFlags;
408
409 exit:
410     return err;
411 }
412
413 static CHIP_ERROR DecodeConvertBasicConstraintsExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
414 {
415     CHIP_ERROR err, nextRes;
416     TLVType outerContainer;
417
418     certData.mCertFlags.Set(CertFlags::kExtPresent_BasicConstraints);
419
420     // BasicConstraints ::= SEQUENCE
421     ASN1_START_SEQUENCE
422     {
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);
425
426         err = reader.EnterContainer(outerContainer);
427         SuccessOrExit(err);
428
429         // cA BOOLEAN DEFAULT FALSE
430         {
431             bool isCA;
432
433             err = reader.Next(kTLVType_Boolean, ContextTag(kTag_BasicConstraints_IsCA));
434             SuccessOrExit(err);
435
436             err = reader.Get(isCA);
437             SuccessOrExit(err);
438
439             if (isCA)
440             {
441                 ASN1_ENCODE_BOOLEAN(true);
442                 certData.mCertFlags.Set(CertFlags::kIsCA);
443             }
444
445             nextRes = reader.Next();
446             VerifyOrExit(nextRes == CHIP_NO_ERROR || nextRes == CHIP_END_OF_TLV, err = nextRes);
447         }
448
449         // pathLenConstraint INTEGER (0..MAX) OPTIONAL
450         if (reader.GetTag() == ContextTag(kTag_BasicConstraints_PathLenConstraint))
451         {
452             uint64_t pathLenConstraint;
453
454             VerifyOrExit(reader.GetType() == kTLVType_UnsignedInteger, err = CHIP_ERROR_WRONG_TLV_TYPE);
455
456             err = reader.Get(pathLenConstraint);
457             SuccessOrExit(err);
458
459             VerifyOrExit(pathLenConstraint <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
460
461             ASN1_ENCODE_INTEGER(static_cast<int64_t>(pathLenConstraint));
462
463             certData.mPathLenConstraint = static_cast<uint8_t>(pathLenConstraint);
464
465             certData.mCertFlags.Set(CertFlags::kPathLenConstraintPresent);
466
467             reader.Next();
468         }
469
470         err = reader.VerifyEndOfContainer();
471         SuccessOrExit(err);
472
473         err = reader.ExitContainer(outerContainer);
474         SuccessOrExit(err);
475     }
476     ASN1_END_SEQUENCE;
477
478 exit:
479     return err;
480 }
481
482 static CHIP_ERROR DecodeConvertExtendedKeyUsageExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
483 {
484     CHIP_ERROR err, nextRes;
485     TLVType outerContainer;
486
487     certData.mCertFlags.Set(CertFlags::kExtPresent_ExtendedKeyUsage);
488
489     // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
490     ASN1_START_SEQUENCE
491     {
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);
494
495         err = reader.EnterContainer(outerContainer);
496         SuccessOrExit(err);
497
498         while ((nextRes = reader.Next(kTLVType_UnsignedInteger, AnonymousTag)) == CHIP_NO_ERROR)
499         {
500             uint64_t keyPurposeId;
501             OID keyPurposeOID;
502
503             err = reader.Get(keyPurposeId);
504             SuccessOrExit(err);
505
506             VerifyOrExit(keyPurposeId <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
507
508             keyPurposeOID = GetOID(kOIDCategory_KeyPurpose, static_cast<uint8_t>(keyPurposeId));
509
510             // KeyPurposeId ::= OBJECT IDENTIFIER
511             ASN1_ENCODE_OBJECT_ID(keyPurposeOID);
512
513             certData.mKeyPurposeFlags.Set(static_cast<KeyPurposeFlags>(0x01 << (keyPurposeId - 1)));
514         }
515
516         VerifyOrExit(nextRes == CHIP_END_OF_TLV, err = nextRes);
517
518         err = reader.ExitContainer(outerContainer);
519         SuccessOrExit(err);
520     }
521     ASN1_END_SEQUENCE;
522
523 exit:
524     return err;
525 }
526
527 static CHIP_ERROR DecodeConvertExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
528 {
529     CHIP_ERROR err;
530     uint64_t extensionTagNum = TagNumFromTag(reader.GetTag());
531     OID extensionOID;
532
533     if (extensionTagNum == kTag_AuthorityKeyIdentifier)
534     {
535         extensionOID = kOID_Extension_AuthorityKeyIdentifier;
536     }
537     else if (extensionTagNum == kTag_SubjectKeyIdentifier)
538     {
539         extensionOID = kOID_Extension_SubjectKeyIdentifier;
540     }
541     else if (extensionTagNum == kTag_KeyUsage)
542     {
543         extensionOID = kOID_Extension_KeyUsage;
544     }
545     else if (extensionTagNum == kTag_BasicConstraints)
546     {
547         extensionOID = kOID_Extension_BasicConstraints;
548     }
549     else if (extensionTagNum == kTag_ExtendedKeyUsage)
550     {
551         extensionOID = kOID_Extension_ExtendedKeyUsage;
552     }
553     else
554     {
555         ExitNow(err = CHIP_ERROR_UNEXPECTED_TLV_ELEMENT);
556     }
557
558     // Extension ::= SEQUENCE
559     ASN1_START_SEQUENCE
560     {
561         // extnID OBJECT IDENTIFIER,
562         ASN1_ENCODE_OBJECT_ID(extensionOID);
563
564         // BasicConstraints, KeyUsage and ExtKeyUsage extensions MUST be marked as critical.
565         if (extensionTagNum == kTag_KeyUsage || extensionTagNum == kTag_BasicConstraints ||
566             extensionTagNum == kTag_ExtendedKeyUsage)
567         {
568             ASN1_ENCODE_BOOLEAN(true);
569         }
570
571         // extnValue OCTET STRING
572         //           -- contains the DER encoding of an ASN.1 value
573         //           -- corresponding to the extension type identified
574         //           -- by extnID
575         ASN1_START_OCTET_STRING_ENCAPSULATED
576         {
577             if (extensionTagNum == kTag_AuthorityKeyIdentifier)
578             {
579                 err = DecodeConvertAuthorityKeyIdentifierExtension(reader, writer, certData);
580             }
581             else if (extensionTagNum == kTag_SubjectKeyIdentifier)
582             {
583                 err = DecodeConvertSubjectKeyIdentifierExtension(reader, writer, certData);
584             }
585             else if (extensionTagNum == kTag_KeyUsage)
586             {
587                 err = DecodeConvertKeyUsageExtension(reader, writer, certData);
588             }
589             else if (extensionTagNum == kTag_BasicConstraints)
590             {
591                 err = DecodeConvertBasicConstraintsExtension(reader, writer, certData);
592             }
593             else if (extensionTagNum == kTag_ExtendedKeyUsage)
594             {
595                 err = DecodeConvertExtendedKeyUsageExtension(reader, writer, certData);
596             }
597             else
598             {
599                 err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT;
600             }
601             SuccessOrExit(err);
602         }
603         ASN1_END_ENCAPSULATED;
604     }
605     ASN1_END_SEQUENCE;
606
607 exit:
608     return err;
609 }
610
611 static CHIP_ERROR DecodeConvertExtensions(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
612 {
613     CHIP_ERROR err;
614     uint64_t tag;
615
616     // extensions [3] EXPLICIT Extensions OPTIONAL
617     ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 3)
618     {
619         // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
620         ASN1_START_SEQUENCE
621         {
622             while (true)
623             {
624                 err = DecodeConvertExtension(reader, writer, certData);
625                 SuccessOrExit(err);
626
627                 // Break the loop if the next certificate element is NOT an extension.
628                 err = reader.Next();
629                 SuccessOrExit(err);
630                 tag = reader.GetTag();
631                 if (!IsCertificateExtensionTag(tag))
632                 {
633                     break;
634                 }
635             }
636         }
637         ASN1_END_SEQUENCE;
638     }
639     ASN1_END_CONSTRUCTED;
640
641 exit:
642     return err;
643 }
644
645 CHIP_ERROR DecodeECDSASignature(TLVReader & reader, ChipCertificateData & certData)
646 {
647     CHIP_ERROR err;
648     TLVType containerType;
649     uint32_t len;
650
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);
654
655     err = reader.EnterContainer(containerType);
656     SuccessOrExit(err);
657
658     // r INTEGER
659     err = reader.Next(kTLVType_ByteString, ContextTag(kTag_ECDSASignature_r));
660     SuccessOrExit(err);
661
662     err = reader.GetDataPtr(certData.mSignature.R);
663     SuccessOrExit(err);
664
665     len = reader.GetLength();
666     VerifyOrExit(len <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
667
668     certData.mSignature.RLen = static_cast<uint8_t>(len);
669
670     // s INTEGER
671     err = reader.Next(kTLVType_ByteString, ContextTag(kTag_ECDSASignature_s));
672     SuccessOrExit(err);
673
674     err = reader.GetDataPtr(certData.mSignature.S);
675     SuccessOrExit(err);
676
677     len = reader.GetLength();
678     VerifyOrExit(len <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
679
680     certData.mSignature.SLen = static_cast<uint8_t>(len);
681
682     // Verify no more elements in the signature.
683     reader.Next();
684     err = reader.VerifyEndOfContainer();
685     SuccessOrExit(err);
686
687     err = reader.ExitContainer(containerType);
688     SuccessOrExit(err);
689
690 exit:
691     return err;
692 }
693
694 static CHIP_ERROR DecodeConvertECDSASignature(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
695 {
696     CHIP_ERROR err;
697
698     err = DecodeECDSASignature(reader, certData);
699     SuccessOrExit(err);
700
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
704     {
705         // Ecdsa-Sig-Value ::= SEQUENCE
706         ASN1_START_SEQUENCE
707         {
708             // r INTEGER
709             err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, certData.mSignature.R,
710                                   certData.mSignature.RLen);
711             SuccessOrExit(err);
712
713             // s INTEGER
714             err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, certData.mSignature.S,
715                                   certData.mSignature.SLen);
716             SuccessOrExit(err);
717         }
718         ASN1_END_SEQUENCE;
719     }
720     ASN1_END_ENCAPSULATED;
721
722 exit:
723     return err;
724 }
725
726 /**
727  * @brief Decode and convert the To-Be-Signed (TBS) portion of the CHIP certificate
728  *        into X.509 DER encoded form.
729  *
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
735  *                  CHIP certificate.
736  *
737  * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
738  **/
739 CHIP_ERROR DecodeConvertTBSCert(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
740 {
741     CHIP_ERROR err;
742     uint64_t tag;
743
744     // tbsCertificate TBSCertificate,
745     // TBSCertificate ::= SEQUENCE
746     ASN1_START_SEQUENCE
747     {
748         // version [0] EXPLICIT Version DEFAULT v1
749         ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
750         {
751             // Version ::= INTEGER { v1(0), v2(1), v3(2) }
752             ASN1_ENCODE_INTEGER(2);
753         }
754         ASN1_END_CONSTRUCTED;
755
756         err = reader.Next(kTLVType_ByteString, ContextTag(kTag_SerialNumber));
757         SuccessOrExit(err);
758
759         // serialNumber CertificateSerialNumber
760         // CertificateSerialNumber ::= INTEGER
761         err = writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false, reader);
762         SuccessOrExit(err);
763
764         // signature AlgorithmIdentifier
765         // AlgorithmIdentifier ::= SEQUENCE
766         ASN1_START_SEQUENCE
767         {
768             uint64_t sigAlgoId;
769             OID sigAlgoOID;
770
771             err = reader.Next(kTLVType_UnsignedInteger, ContextTag(kTag_SignatureAlgorithm));
772             SuccessOrExit(err);
773
774             err = reader.Get(sigAlgoId);
775             SuccessOrExit(err);
776
777             VerifyOrExit(sigAlgoId <= UINT8_MAX, err = CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
778
779             sigAlgoOID = GetOID(kOIDCategory_SigAlgo, static_cast<uint8_t>(sigAlgoId));
780             ASN1_ENCODE_OBJECT_ID(sigAlgoOID);
781
782             certData.mSigAlgoOID = sigAlgoOID;
783         }
784         ASN1_END_SEQUENCE;
785
786         // issuer Name
787         err = reader.Next(kTLVType_List, ContextTag(kTag_Issuer));
788         SuccessOrExit(err);
789         err = DecodeConvertDN(reader, writer, certData.mIssuerDN);
790         SuccessOrExit(err);
791
792         // validity Validity,
793         err = DecodeConvertValidity(reader, writer, certData);
794         SuccessOrExit(err);
795
796         // subject Name
797         err = reader.Next(kTLVType_List, ContextTag(kTag_Subject));
798         SuccessOrExit(err);
799         err = DecodeConvertDN(reader, writer, certData.mSubjectDN);
800         SuccessOrExit(err);
801
802         // subjectPublicKeyInfo SubjectPublicKeyInfo,
803         err = DecodeConvertSubjectPublicKeyInfo(reader, writer, certData);
804         SuccessOrExit(err);
805
806         // If the next element is a certificate extension...
807         err = reader.Next();
808         SuccessOrExit(err);
809         tag = reader.GetTag();
810         if (IsCertificateExtensionTag(tag))
811         {
812             err = DecodeConvertExtensions(reader, writer, certData);
813             SuccessOrExit(err);
814         }
815     }
816     ASN1_END_SEQUENCE;
817
818 exit:
819     return err;
820 }
821
822 static CHIP_ERROR DecodeConvertCert(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
823 {
824     CHIP_ERROR err;
825     uint64_t tag;
826     TLVType containerType;
827
828     if (reader.GetType() == kTLVType_NotSpecified)
829     {
830         err = reader.Next();
831         SuccessOrExit(err);
832     }
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);
837
838     err = reader.EnterContainer(containerType);
839     SuccessOrExit(err);
840
841     // Certificate ::= SEQUENCE
842     ASN1_START_SEQUENCE
843     {
844         // tbsCertificate TBSCertificate,
845         err = DecodeConvertTBSCert(reader, writer, certData);
846         SuccessOrExit(err);
847
848         // signatureAlgorithm   AlgorithmIdentifier
849         // AlgorithmIdentifier ::= SEQUENCE
850         ASN1_START_SEQUENCE { ASN1_ENCODE_OBJECT_ID(static_cast<OID>(certData.mSigAlgoOID)); }
851         ASN1_END_SEQUENCE;
852
853         // signatureValue BIT STRING
854         err = DecodeConvertECDSASignature(reader, writer, certData);
855         SuccessOrExit(err);
856     }
857     ASN1_END_SEQUENCE;
858
859     // Verify no more elements in certificate.
860     err = reader.VerifyEndOfContainer();
861     SuccessOrExit(err);
862
863     err = reader.ExitContainer(containerType);
864     SuccessOrExit(err);
865
866 exit:
867     return err;
868 }
869
870 DLL_EXPORT CHIP_ERROR ConvertChipCertToX509Cert(const uint8_t * chipCert, uint32_t chipCertLen, uint8_t * x509CertBuf,
871                                                 uint32_t x509CertBufSize, uint32_t & x509CertLen)
872 {
873     CHIP_ERROR err;
874     TLVReader reader;
875     ASN1Writer writer;
876     ChipCertificateData certData;
877
878     reader.Init(chipCert, chipCertLen);
879
880     writer.Init(x509CertBuf, x509CertBufSize);
881
882     err = DecodeConvertCert(reader, writer, certData);
883     SuccessOrExit(err);
884
885     err = writer.Finalize();
886     SuccessOrExit(err);
887
888     x509CertLen = writer.GetLengthWritten();
889
890 exit:
891     return err;
892 }
893
894 CHIP_ERROR DecodeChipCert(const uint8_t * chipCert, uint32_t chipCertLen, ChipCertificateData & certData)
895 {
896     TLVReader reader;
897
898     reader.Init(chipCert, chipCertLen);
899
900     return DecodeChipCert(reader, certData);
901 }
902
903 CHIP_ERROR DecodeChipCert(TLVReader & reader, ChipCertificateData & certData)
904 {
905     ASN1Writer writer;
906
907     writer.InitNullWriter();
908
909     certData.Clear();
910
911     return DecodeConvertCert(reader, writer, certData);
912 }
913
914 CHIP_ERROR DecodeChipDN(TLVReader & reader, ChipDN & dn)
915 {
916     ASN1Writer writer;
917
918     writer.InitNullWriter();
919
920     dn.Clear();
921
922     return DecodeConvertDN(reader, writer, dn);
923 }
924
925 } // namespace Credentials
926 } // namespace chip