Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2022 Project CHIP Authors
4 : * Copyright (c) 2013-2017 Nest Labs, Inc.
5 : * All rights reserved.
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : /**
21 : * @file
22 : * This file implements methods for converting a CHIP
23 : * TLV-encoded certificate to a standard X.509 certificate.
24 : *
25 : */
26 :
27 : #include <inttypes.h>
28 : #include <stddef.h>
29 :
30 : #include <credentials/CHIPCert_Internal.h>
31 : #include <lib/asn1/ASN1.h>
32 : #include <lib/asn1/ASN1Macros.h>
33 : #include <lib/core/CHIPCore.h>
34 : #include <lib/core/CHIPSafeCasts.h>
35 : #include <lib/core/TLV.h>
36 : #include <lib/support/CodeUtils.h>
37 : #include <lib/support/DLLUtil.h>
38 : #include <lib/support/SafeInt.h>
39 : #include <protocols/Protocols.h>
40 :
41 : namespace chip {
42 : namespace Credentials {
43 :
44 : using namespace chip::ASN1;
45 : using namespace chip::TLV;
46 : using namespace chip::Protocols;
47 : using namespace chip::Crypto;
48 :
49 5682 : static CHIP_ERROR DecodeConvertDN(TLVReader & reader, ASN1Writer & writer, ChipDN & dn)
50 : {
51 5682 : ReturnErrorOnFailure(dn.DecodeFromTLV(reader));
52 5661 : ReturnErrorOnFailure(dn.EncodeToASN1(writer));
53 5660 : return CHIP_NO_ERROR;
54 : }
55 :
56 2856 : static CHIP_ERROR DecodeConvertValidity(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
57 : {
58 : CHIP_ERROR err;
59 : ASN1UniversalTime asn1Time;
60 :
61 2856 : ASN1_START_SEQUENCE
62 : {
63 2856 : ReturnErrorOnFailure(reader.Next(ContextTag(kTag_NotBefore)));
64 2847 : ReturnErrorOnFailure(reader.Get(certData.mNotBeforeTime));
65 2847 : ReturnErrorOnFailure(ChipEpochToASN1Time(certData.mNotBeforeTime, asn1Time));
66 2847 : ASN1_ENCODE_TIME(asn1Time);
67 :
68 2847 : ReturnErrorOnFailure(reader.Next(ContextTag(kTag_NotAfter)));
69 2838 : ReturnErrorOnFailure(reader.Get(certData.mNotAfterTime));
70 2838 : ReturnErrorOnFailure(ChipEpochToASN1Time(certData.mNotAfterTime, asn1Time));
71 2838 : ASN1_ENCODE_TIME(asn1Time);
72 :
73 : // Perform this check if NotAfter value is different from Never-Expire value.
74 2838 : if (certData.mNotAfterTime != kNullCertTime)
75 : {
76 2826 : VerifyOrReturnError(certData.mNotBeforeTime < certData.mNotAfterTime, CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
77 : }
78 : }
79 2829 : ASN1_END_SEQUENCE;
80 :
81 2829 : exit:
82 2829 : return err;
83 : }
84 :
85 2804 : static CHIP_ERROR DecodeConvertSubjectPublicKeyInfo(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
86 : {
87 : CHIP_ERROR err;
88 : uint8_t pubKeyAlgoId, pubKeyCurveId;
89 :
90 2804 : ReturnErrorOnFailure(reader.Next(ContextTag(kTag_PublicKeyAlgorithm)));
91 2804 : ReturnErrorOnFailure(reader.Get(pubKeyAlgoId));
92 :
93 2804 : certData.mPubKeyAlgoOID = GetOID(kOIDCategory_PubKeyAlgo, pubKeyAlgoId);
94 2804 : VerifyOrReturnError(certData.mPubKeyAlgoOID == kOID_PubKeyAlgo_ECPublicKey, CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
95 :
96 2804 : ReturnErrorOnFailure(reader.Next(ContextTag(kTag_EllipticCurveIdentifier)));
97 2804 : ReturnErrorOnFailure(reader.Get(pubKeyCurveId));
98 :
99 2804 : certData.mPubKeyCurveOID = GetOID(kOIDCategory_EllipticCurve, pubKeyCurveId);
100 2804 : VerifyOrReturnError(certData.mPubKeyCurveOID == kOID_EllipticCurve_prime256v1, CHIP_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
101 :
102 : // subjectPublicKeyInfo SubjectPublicKeyInfo,
103 2795 : ASN1_START_SEQUENCE
104 : {
105 : // algorithm AlgorithmIdentifier,
106 : // AlgorithmIdentifier ::= SEQUENCE
107 2795 : ASN1_START_SEQUENCE
108 : {
109 : // algorithm OBJECT IDENTIFIER,
110 2795 : ASN1_ENCODE_OBJECT_ID(certData.mPubKeyAlgoOID);
111 :
112 : // EcpkParameters ::= CHOICE {
113 : // ecParameters ECParameters,
114 : // namedCurve OBJECT IDENTIFIER,
115 : // implicitlyCA NULL }
116 : //
117 : // (Only namedCurve supported).
118 : //
119 2794 : ASN1_ENCODE_OBJECT_ID(certData.mPubKeyCurveOID);
120 : }
121 2794 : ASN1_END_SEQUENCE;
122 :
123 2794 : ReturnErrorOnFailure(reader.Next(kTLVType_ByteString, ContextTag(kTag_EllipticCurvePublicKey)));
124 2794 : ReturnErrorOnFailure(reader.Get(certData.mPublicKey));
125 :
126 : static_assert(P256PublicKeySpan().size() <= UINT16_MAX, "Public key size doesn't fit in a uint16_t");
127 :
128 : // For EC certs, the subjectPublicKey BIT STRING contains the X9.62 encoded EC point.
129 2794 : ReturnErrorOnFailure(writer.PutBitString(0, certData.mPublicKey.data(), static_cast<uint16_t>(certData.mPublicKey.size())));
130 : }
131 2794 : ASN1_END_SEQUENCE;
132 :
133 2795 : exit:
134 2795 : return err;
135 : }
136 :
137 2759 : static CHIP_ERROR DecodeConvertAuthorityKeyIdentifierExtension(TLVReader & reader, ASN1Writer & writer,
138 : ChipCertificateData & certData)
139 : {
140 : CHIP_ERROR err;
141 :
142 2759 : certData.mCertFlags.Set(CertFlags::kExtPresent_AuthKeyId);
143 :
144 : // AuthorityKeyIdentifier extension MUST be marked as non-critical (default).
145 :
146 : // AuthorityKeyIdentifier ::= SEQUENCE
147 2759 : ASN1_START_SEQUENCE
148 : {
149 : // keyIdentifier [0] IMPLICIT KeyIdentifier
150 : // KeyIdentifier ::= OCTET STRING
151 2759 : ReturnErrorOnFailure(reader.Expect(kTLVType_ByteString, ContextTag(kTag_AuthorityKeyIdentifier)));
152 2759 : ReturnErrorOnFailure(reader.Get(certData.mAuthKeyId));
153 :
154 : static_assert(CertificateKeyId().size() <= UINT16_MAX, "Authority key id size doesn't fit in a uint16_t");
155 :
156 2750 : ReturnErrorOnFailure(writer.PutOctetString(kASN1TagClass_ContextSpecific, 0, certData.mAuthKeyId.data(),
157 : static_cast<uint16_t>(certData.mAuthKeyId.size())));
158 : }
159 2750 : ASN1_END_SEQUENCE;
160 :
161 2750 : exit:
162 2750 : return err;
163 : }
164 :
165 2769 : static CHIP_ERROR DecodeConvertSubjectKeyIdentifierExtension(TLVReader & reader, ASN1Writer & writer,
166 : ChipCertificateData & certData)
167 : {
168 2769 : certData.mCertFlags.Set(CertFlags::kExtPresent_SubjectKeyId);
169 :
170 : // SubjectKeyIdentifier extension MUST be marked as non-critical (default).
171 :
172 : // SubjectKeyIdentifier ::= KeyIdentifier
173 : // KeyIdentifier ::= OCTET STRING
174 2769 : ReturnErrorOnFailure(reader.Expect(kTLVType_ByteString, ContextTag(kTag_SubjectKeyIdentifier)));
175 2769 : ReturnErrorOnFailure(reader.Get(certData.mSubjectKeyId));
176 :
177 : static_assert(CertificateKeyId().size() <= UINT16_MAX, "Subject key id size doesn't fit in a uint16_t");
178 :
179 2760 : ReturnErrorOnFailure(
180 : writer.PutOctetString(certData.mSubjectKeyId.data(), static_cast<uint16_t>(certData.mSubjectKeyId.size())));
181 :
182 2759 : return CHIP_NO_ERROR;
183 : }
184 :
185 2781 : static CHIP_ERROR DecodeConvertKeyUsageExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
186 : {
187 : CHIP_ERROR err;
188 : uint16_t keyUsageBits;
189 :
190 2781 : certData.mCertFlags.Set(CertFlags::kExtPresent_KeyUsage);
191 :
192 : // KeyUsage ::= BIT STRING
193 2781 : ReturnErrorOnFailure(reader.Expect(ContextTag(kTag_KeyUsage)));
194 2781 : ReturnErrorOnFailure(reader.Get(keyUsageBits));
195 :
196 : {
197 2781 : BitFlags<KeyUsageFlags> keyUsageFlags(keyUsageBits);
198 2781 : VerifyOrReturnError(
199 : keyUsageFlags.HasOnly(KeyUsageFlags::kDigitalSignature, KeyUsageFlags::kNonRepudiation, KeyUsageFlags::kKeyEncipherment,
200 : KeyUsageFlags::kDataEncipherment, KeyUsageFlags::kKeyAgreement, KeyUsageFlags::kKeyCertSign,
201 : KeyUsageFlags::kCRLSign, KeyUsageFlags::kEncipherOnly, KeyUsageFlags::kEncipherOnly),
202 : CHIP_ERROR_UNSUPPORTED_CERT_FORMAT);
203 :
204 2781 : ASN1_ENCODE_BIT_STRING(keyUsageBits);
205 :
206 2781 : certData.mKeyUsageFlags = keyUsageFlags;
207 : }
208 :
209 2781 : exit:
210 2781 : return err;
211 : }
212 :
213 2790 : static CHIP_ERROR DecodeConvertBasicConstraintsExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
214 : {
215 : CHIP_ERROR err;
216 : TLVType outerContainer;
217 :
218 2790 : certData.mCertFlags.Set(CertFlags::kExtPresent_BasicConstraints);
219 :
220 : // BasicConstraints ::= SEQUENCE
221 2790 : ASN1_START_SEQUENCE
222 : {
223 2790 : ReturnErrorOnFailure(reader.Expect(kTLVType_Structure, ContextTag(kTag_BasicConstraints)));
224 2790 : ReturnErrorOnFailure(reader.EnterContainer(outerContainer));
225 :
226 : // cA BOOLEAN DEFAULT FALSE
227 : {
228 : bool isCA;
229 2790 : ReturnErrorOnFailure(reader.Next(ContextTag(kTag_BasicConstraints_IsCA)));
230 2781 : ReturnErrorOnFailure(reader.Get(isCA));
231 :
232 2781 : if (isCA)
233 : {
234 1753 : ASN1_ENCODE_BOOLEAN(true);
235 1753 : certData.mCertFlags.Set(CertFlags::kIsCA);
236 : }
237 :
238 2781 : err = reader.Next();
239 2781 : VerifyOrReturnError(err == CHIP_NO_ERROR || err == CHIP_END_OF_TLV, err);
240 : }
241 :
242 : // pathLenConstraint INTEGER (0..MAX) OPTIONAL
243 2781 : if (reader.GetTag() == ContextTag(kTag_BasicConstraints_PathLenConstraint))
244 : {
245 54 : ReturnErrorOnFailure(reader.Get(certData.mPathLenConstraint));
246 :
247 54 : ASN1_ENCODE_INTEGER(certData.mPathLenConstraint);
248 :
249 54 : certData.mCertFlags.Set(CertFlags::kPathLenConstraintPresent);
250 :
251 54 : err = reader.Next();
252 54 : VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
253 : }
254 :
255 2781 : ReturnErrorOnFailure(reader.VerifyEndOfContainer());
256 2781 : ReturnErrorOnFailure(reader.ExitContainer(outerContainer));
257 : }
258 2781 : ASN1_END_SEQUENCE;
259 :
260 2781 : exit:
261 2781 : return err;
262 : }
263 :
264 1028 : static CHIP_ERROR DecodeConvertExtendedKeyUsageExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
265 : {
266 : CHIP_ERROR err;
267 : TLVType outerContainer;
268 :
269 1028 : certData.mCertFlags.Set(CertFlags::kExtPresent_ExtendedKeyUsage);
270 :
271 : // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
272 1028 : ASN1_START_SEQUENCE
273 : {
274 1028 : ReturnErrorOnFailure(reader.Expect(kTLVType_Array, ContextTag(kTag_ExtendedKeyUsage)));
275 1028 : ReturnErrorOnFailure(reader.EnterContainer(outerContainer));
276 :
277 3080 : while ((err = reader.Next(AnonymousTag())) == CHIP_NO_ERROR)
278 : {
279 : uint8_t keyPurposeId;
280 2052 : ReturnErrorOnFailure(reader.Get(keyPurposeId));
281 :
282 : // KeyPurposeId ::= OBJECT IDENTIFIER
283 2052 : ASN1_ENCODE_OBJECT_ID(GetOID(kOIDCategory_KeyPurpose, keyPurposeId));
284 :
285 2052 : certData.mKeyPurposeFlags.Set(static_cast<KeyPurposeFlags>(0x01 << (keyPurposeId - 1)));
286 : }
287 1028 : VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
288 1028 : ReturnErrorOnFailure(reader.ExitContainer(outerContainer));
289 : }
290 1028 : ASN1_END_SEQUENCE;
291 :
292 1028 : exit:
293 1028 : return err;
294 : }
295 :
296 63 : static CHIP_ERROR DecodeConvertFutureExtension(TLVReader & tlvReader, ASN1Writer & writer, ChipCertificateData & certData)
297 : {
298 : CHIP_ERROR err;
299 63 : ByteSpan extensionSequence;
300 : ASN1Reader reader;
301 :
302 63 : ReturnErrorOnFailure(tlvReader.Expect(kTLVType_ByteString, ContextTag(kTag_FutureExtension)));
303 63 : ReturnErrorOnFailure(tlvReader.Get(extensionSequence));
304 :
305 63 : reader.Init(extensionSequence);
306 :
307 : // Extension ::= SEQUENCE
308 63 : ASN1_PARSE_ENTER_SEQUENCE
309 : {
310 : OID extensionOID;
311 63 : bool critical = false;
312 :
313 63 : ASN1_PARSE_OBJECT_ID(extensionOID);
314 :
315 63 : VerifyOrReturnError(extensionOID == kOID_Unknown, ASN1_ERROR_UNSUPPORTED_ENCODING);
316 :
317 : // critical BOOLEAN DEFAULT FALSE,
318 63 : ASN1_PARSE_ANY;
319 63 : if (reader.GetClass() == kASN1TagClass_Universal && reader.GetTag() == kASN1UniversalTag_Boolean)
320 : {
321 12 : ASN1_GET_BOOLEAN(critical);
322 :
323 12 : if (critical)
324 : {
325 12 : certData.mCertFlags.Set(CertFlags::kExtPresent_FutureIsCritical);
326 : }
327 :
328 12 : ASN1_PARSE_ANY;
329 : }
330 : }
331 63 : ASN1_EXIT_SEQUENCE;
332 :
333 63 : VerifyOrReturnError(CanCastTo<uint16_t>(extensionSequence.size()), ASN1_ERROR_INVALID_ENCODING);
334 :
335 : // FutureExtension SEQUENCE
336 63 : ReturnErrorOnFailure(writer.PutConstructedType(extensionSequence.data(), static_cast<uint16_t>(extensionSequence.size())));
337 :
338 63 : exit:
339 63 : return err;
340 : }
341 :
342 12193 : static CHIP_ERROR DecodeConvertExtension(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
343 : {
344 12193 : CHIP_ERROR err = CHIP_NO_ERROR;
345 : Tag tlvTag;
346 : uint32_t extensionTagNum;
347 :
348 12193 : tlvTag = reader.GetTag();
349 12193 : VerifyOrReturnError(IsContextTag(tlvTag), CHIP_ERROR_INVALID_TLV_TAG);
350 12192 : extensionTagNum = TagNumFromTag(tlvTag);
351 :
352 12192 : if (extensionTagNum == kTag_FutureExtension)
353 : {
354 63 : ReturnErrorOnFailure(DecodeConvertFutureExtension(reader, writer, certData));
355 : }
356 : else
357 : {
358 : // Extension ::= SEQUENCE
359 12129 : ASN1_START_SEQUENCE
360 : {
361 : // extnID OBJECT IDENTIFIER,
362 12129 : ASN1_ENCODE_OBJECT_ID(GetOID(kOIDCategory_Extension, static_cast<uint8_t>(extensionTagNum)));
363 :
364 : // BasicConstraints, KeyUsage and ExtKeyUsage extensions MUST be marked as critical.
365 12127 : if (extensionTagNum == kTag_KeyUsage || extensionTagNum == kTag_BasicConstraints ||
366 : extensionTagNum == kTag_ExtendedKeyUsage)
367 : {
368 6599 : ASN1_ENCODE_BOOLEAN(true);
369 : }
370 :
371 : // extnValue OCTET STRING
372 : // -- contains the DER encoding of an ASN.1 value
373 : // -- corresponding to the extension type identified
374 : // -- by extnID
375 12127 : ASN1_START_OCTET_STRING_ENCAPSULATED
376 : {
377 12127 : if (extensionTagNum == kTag_AuthorityKeyIdentifier)
378 : {
379 2759 : ReturnErrorOnFailure(DecodeConvertAuthorityKeyIdentifierExtension(reader, writer, certData));
380 : }
381 9368 : else if (extensionTagNum == kTag_SubjectKeyIdentifier)
382 : {
383 2769 : ReturnErrorOnFailure(DecodeConvertSubjectKeyIdentifierExtension(reader, writer, certData));
384 : }
385 6599 : else if (extensionTagNum == kTag_KeyUsage)
386 : {
387 2781 : ReturnErrorOnFailure(DecodeConvertKeyUsageExtension(reader, writer, certData));
388 : }
389 3818 : else if (extensionTagNum == kTag_BasicConstraints)
390 : {
391 2790 : ReturnErrorOnFailure(DecodeConvertBasicConstraintsExtension(reader, writer, certData));
392 : }
393 1028 : else if (extensionTagNum == kTag_ExtendedKeyUsage)
394 : {
395 1028 : ReturnErrorOnFailure(DecodeConvertExtendedKeyUsageExtension(reader, writer, certData));
396 : }
397 : else
398 : {
399 0 : return CHIP_ERROR_UNSUPPORTED_CERT_FORMAT;
400 : }
401 : }
402 12099 : ASN1_END_ENCAPSULATED;
403 : }
404 12099 : ASN1_END_SEQUENCE;
405 : }
406 :
407 12164 : exit:
408 12164 : return err;
409 : }
410 :
411 2794 : static CHIP_ERROR DecodeConvertExtensions(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
412 : {
413 : CHIP_ERROR err;
414 : TLVType outerContainer;
415 :
416 2794 : ReturnErrorOnFailure(reader.Next(kTLVType_List, ContextTag(kTag_Extensions)));
417 2794 : ReturnErrorOnFailure(reader.EnterContainer(outerContainer));
418 :
419 : // extensions [3] EXPLICIT Extensions OPTIONAL
420 2794 : ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 3)
421 : {
422 : // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
423 2794 : ASN1_START_SEQUENCE
424 : {
425 : // Read certificate extension in the List.
426 14956 : while ((err = reader.Next()) == CHIP_NO_ERROR)
427 : {
428 12193 : ReturnErrorOnFailure(DecodeConvertExtension(reader, writer, certData));
429 : }
430 2763 : VerifyOrReturnError(err == CHIP_END_OF_TLV, err);
431 : }
432 2763 : ASN1_END_SEQUENCE;
433 : }
434 2763 : ASN1_END_CONSTRUCTED;
435 :
436 2763 : ReturnErrorOnFailure(reader.ExitContainer(outerContainer));
437 :
438 2763 : exit:
439 2763 : return err;
440 : }
441 :
442 2767 : static CHIP_ERROR DecodeECDSASignature(TLVReader & reader, ChipCertificateData & certData)
443 : {
444 2767 : ReturnErrorOnFailure(reader.Next(kTLVType_ByteString, ContextTag(kTag_ECDSASignature)));
445 2767 : ReturnErrorOnFailure(reader.Get(certData.mSignature));
446 2767 : return CHIP_NO_ERROR;
447 : }
448 :
449 2767 : static CHIP_ERROR DecodeConvertECDSASignature(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
450 : {
451 2767 : CHIP_ERROR err = CHIP_NO_ERROR;
452 :
453 2767 : ReturnErrorOnFailure(DecodeECDSASignature(reader, certData));
454 :
455 : // Converting the signature is a bit of work, so explicitly check if we have a null writer
456 2767 : VerifyOrReturnError(!writer.IsNullWriter(), CHIP_NO_ERROR);
457 :
458 : // signatureValue BIT STRING
459 : // Per RFC3279, the ECDSA signature value is encoded in DER encapsulated in the signatureValue BIT STRING.
460 20 : ASN1_START_BIT_STRING_ENCAPSULATED
461 : {
462 20 : ReturnErrorOnFailure(ConvertECDSASignatureRawToDER(certData.mSignature, writer));
463 : }
464 20 : ASN1_END_ENCAPSULATED;
465 :
466 20 : exit:
467 20 : return err;
468 : }
469 :
470 : /**
471 : * @brief Decode and convert the To-Be-Signed (TBS) portion of the CHIP certificate
472 : * into X.509 DER encoded form.
473 : *
474 : * @param reader A TLVReader positioned at the beginning of the TBS portion
475 : * (certificate serial number) of the CHIP certificates.
476 : * @param writer A reference to the ASN1Writer to store DER encoded TBS portion of
477 : * the CHIP certificate.
478 : * @param certData Structure containing data extracted from the TBS portion of the
479 : * CHIP certificate.
480 : *
481 : * Note: The reader must be positioned on the SerialNumber element.
482 : *
483 : * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
484 : **/
485 2889 : static CHIP_ERROR DecodeConvertTBSCert(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
486 : {
487 : CHIP_ERROR err;
488 :
489 : // tbsCertificate TBSCertificate,
490 : // TBSCertificate ::= SEQUENCE
491 2889 : ASN1_START_SEQUENCE
492 : {
493 : // version [0] EXPLICIT Version DEFAULT v1
494 2889 : ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
495 : {
496 : // Version ::= INTEGER { v1(0), v2(1), v3(2) }
497 2889 : ASN1_ENCODE_INTEGER(2);
498 : }
499 2889 : ASN1_END_CONSTRUCTED;
500 :
501 : // serialNumber CertificateSerialNumber
502 : // CertificateSerialNumber ::= INTEGER
503 2889 : ReturnErrorOnFailure(reader.Expect(kTLVType_ByteString, ContextTag(kTag_SerialNumber)));
504 2880 : ReturnErrorOnFailure(reader.Get(certData.mSerialNumber));
505 2880 : ReturnErrorOnFailure(writer.PutValue(kASN1TagClass_Universal, kASN1UniversalTag_Integer, false,
506 : certData.mSerialNumber.data(), static_cast<uint16_t>(certData.mSerialNumber.size())));
507 :
508 : // signature AlgorithmIdentifier
509 : // AlgorithmIdentifier ::= SEQUENCE
510 2880 : ASN1_START_SEQUENCE
511 : {
512 : uint8_t sigAlgoId;
513 2880 : ReturnErrorOnFailure(reader.Next(ContextTag(kTag_SignatureAlgorithm)));
514 2880 : ReturnErrorOnFailure(reader.Get(sigAlgoId));
515 :
516 2880 : certData.mSigAlgoOID = GetOID(kOIDCategory_SigAlgo, sigAlgoId);
517 2880 : ASN1_ENCODE_OBJECT_ID(certData.mSigAlgoOID);
518 : }
519 2871 : ASN1_END_SEQUENCE;
520 :
521 : // issuer Name
522 2871 : ReturnErrorOnFailure(reader.Next(kTLVType_List, ContextTag(kTag_Issuer)));
523 2862 : ReturnErrorOnFailure(DecodeConvertDN(reader, writer, certData.mIssuerDN));
524 :
525 : // validity Validity,
526 2856 : ReturnErrorOnFailure(DecodeConvertValidity(reader, writer, certData));
527 :
528 : // subject Name
529 2829 : ReturnErrorOnFailure(reader.Next(kTLVType_List, ContextTag(kTag_Subject)));
530 2820 : ReturnErrorOnFailure(DecodeConvertDN(reader, writer, certData.mSubjectDN));
531 :
532 : // subjectPublicKeyInfo SubjectPublicKeyInfo,
533 2804 : ReturnErrorOnFailure(DecodeConvertSubjectPublicKeyInfo(reader, writer, certData));
534 :
535 : // certificate extensions
536 2794 : ReturnErrorOnFailure(DecodeConvertExtensions(reader, writer, certData));
537 : }
538 2763 : ASN1_END_SEQUENCE;
539 :
540 2772 : exit:
541 2772 : return err;
542 : }
543 :
544 : /**
545 : * Variant of DecodeConvertTBSCert that handles reading a compact-pdc-identity
546 : * where only the subject public key is actually encoded. All other values are
547 : * populated / written as the well-known values mandated by the specification.
548 : *
549 : * Note: The reader must be positioned on the EllipticCurvePublicKey element.
550 : */
551 5 : static CHIP_ERROR DecodeConvertTBSCertCompactIdentity(TLVReader & reader, ASN1Writer & writer, ChipCertificateData & certData)
552 : {
553 : // Decode the public key, everything else is rigid
554 5 : ReturnErrorOnFailure(reader.Expect(kTLVType_ByteString, ContextTag(kTag_EllipticCurvePublicKey)));
555 5 : ReturnErrorOnFailure(reader.Get(certData.mPublicKey));
556 :
557 : // Populate rigid ChipCertificateData fields
558 5 : certData.mSerialNumber = kNetworkIdentitySerialNumberBytes;
559 5 : certData.mSigAlgoOID = kOID_SigAlgo_ECDSAWithSHA256;
560 5 : InitNetworkIdentitySubject(certData.mIssuerDN);
561 5 : certData.mNotBeforeTime = kNetworkIdentityNotBeforeTime;
562 5 : certData.mNotAfterTime = kNetworkIdentityNotAfterTime;
563 5 : InitNetworkIdentitySubject(certData.mSubjectDN);
564 5 : certData.mPubKeyAlgoOID = kOID_PubKeyAlgo_ECPublicKey;
565 5 : certData.mPubKeyCurveOID = kOID_EllipticCurve_prime256v1;
566 5 : certData.mCertFlags.Set(CertFlags::kExtPresent_BasicConstraints);
567 5 : certData.mCertFlags.Set(CertFlags::kExtPresent_KeyUsage);
568 5 : certData.mKeyUsageFlags = kNetworkIdentityKeyUsage;
569 5 : certData.mCertFlags.Set(CertFlags::kExtPresent_ExtendedKeyUsage);
570 5 : certData.mKeyPurposeFlags = kNetworkIdentityKeyPurpose;
571 :
572 5 : if (!writer.IsNullWriter())
573 : {
574 4 : ReturnErrorOnFailure(EncodeNetworkIdentityTBSCert(certData.mPublicKey, writer));
575 : }
576 5 : return CHIP_NO_ERROR;
577 : }
578 :
579 : /**
580 : * Decode a CHIP TLV certificate and convert it to X.509 DER form.
581 : *
582 : * This helper function takes separate ASN1Writers for the whole Certificate
583 : * and the TBSCertificate, to allow the caller to control which part (if any)
584 : * to capture.
585 : *
586 : * If `writer` is NOT a null writer, then `tbsWriter` MUST be a reference
587 : * to the same writer, otherwise the overall Certificate written will not be
588 : * valid.
589 : */
590 2894 : static CHIP_ERROR DecodeConvertCert(TLVReader & reader, ASN1Writer & writer, ASN1Writer & tbsWriter, ChipCertificateData & certData)
591 : {
592 : CHIP_ERROR err;
593 : TLVType containerType;
594 :
595 2894 : if (reader.GetType() == kTLVType_NotSpecified)
596 : {
597 2894 : ReturnErrorOnFailure(reader.Next());
598 : }
599 2894 : ReturnErrorOnFailure(reader.Expect(kTLVType_Structure, AnonymousTag()));
600 2894 : ReturnErrorOnFailure(reader.EnterContainer(containerType));
601 :
602 : // Certificate ::= SEQUENCE
603 2894 : ASN1_START_SEQUENCE
604 : {
605 : // tbsCertificate TBSCertificate,
606 2894 : reader.Next();
607 2894 : if (reader.GetTag() == ContextTag(kTag_EllipticCurvePublicKey))
608 : {
609 : // If the struct starts with the ec-pub-key we're dealing with a
610 : // Network (Client) Identity in compact-pdc-identity format.
611 5 : DecodeConvertTBSCertCompactIdentity(reader, tbsWriter, certData);
612 : }
613 : else
614 : {
615 2889 : ReturnErrorOnFailure(DecodeConvertTBSCert(reader, tbsWriter, certData));
616 : }
617 :
618 : // signatureAlgorithm AlgorithmIdentifier
619 : // AlgorithmIdentifier ::= SEQUENCE
620 2768 : ASN1_START_SEQUENCE
621 : {
622 2768 : ASN1_ENCODE_OBJECT_ID(static_cast<OID>(certData.mSigAlgoOID));
623 : }
624 2767 : ASN1_END_SEQUENCE;
625 :
626 : // signatureValue BIT STRING
627 2767 : ReturnErrorOnFailure(DecodeConvertECDSASignature(reader, writer, certData));
628 : }
629 2767 : ASN1_END_SEQUENCE;
630 :
631 : // Verify no more elements in certificate.
632 2767 : ReturnErrorOnFailure(reader.VerifyEndOfContainer());
633 2767 : ReturnErrorOnFailure(reader.ExitContainer(containerType));
634 :
635 2768 : exit:
636 2768 : return err;
637 : }
638 :
639 64 : DLL_EXPORT CHIP_ERROR ConvertChipCertToX509Cert(const ByteSpan chipCert, MutableByteSpan & x509Cert)
640 : {
641 64 : TLVReader reader;
642 : ASN1Writer writer;
643 64 : ChipCertificateData certData;
644 :
645 64 : reader.Init(chipCert);
646 :
647 64 : writer.Init(x509Cert);
648 :
649 64 : certData.Clear();
650 :
651 64 : ReturnErrorOnFailure(DecodeConvertCert(reader, writer, writer, certData));
652 :
653 20 : x509Cert.reduce_size(writer.GetLengthWritten());
654 :
655 20 : return CHIP_NO_ERROR;
656 64 : }
657 :
658 313 : CHIP_ERROR DecodeChipCert(const ByteSpan chipCert, ChipCertificateData & certData, BitFlags<CertDecodeFlags> decodeFlags)
659 : {
660 313 : TLVReader reader;
661 :
662 313 : reader.Init(chipCert);
663 313 : return DecodeChipCert(reader, certData, decodeFlags);
664 : }
665 :
666 2830 : CHIP_ERROR DecodeChipCert(TLVReader & reader, ChipCertificateData & certData, BitFlags<CertDecodeFlags> decodeFlags)
667 : {
668 : ASN1Writer nullWriter;
669 2830 : nullWriter.InitNullWriter();
670 :
671 2830 : certData.Clear();
672 :
673 2830 : if (decodeFlags.Has(CertDecodeFlags::kGenerateTBSHash))
674 : {
675 : // Create a buffer and writer to capture the TBS (to-be-signed) portion of the certificate
676 : // when we decode (and convert) the certificate, so we can hash it to create the TBSHash.
677 1622 : chip::Platform::ScopedMemoryBuffer<uint8_t> asn1TBSBuf;
678 1622 : VerifyOrReturnError(asn1TBSBuf.Alloc(kMaxCHIPCertDecodeBufLength), CHIP_ERROR_NO_MEMORY);
679 : ASN1Writer tbsWriter;
680 1622 : tbsWriter.Init(asn1TBSBuf.Get(), kMaxCHIPCertDecodeBufLength);
681 :
682 1622 : ReturnErrorOnFailure(DecodeConvertCert(reader, nullWriter, tbsWriter, certData));
683 :
684 : // Hash the encoded TBS certificate. Only SHA256 is supported.
685 1580 : VerifyOrReturnError(certData.mSigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256, CHIP_ERROR_UNSUPPORTED_SIGNATURE_TYPE);
686 1580 : ReturnErrorOnFailure(Hash_SHA256(asn1TBSBuf.Get(), tbsWriter.GetLengthWritten(), certData.mTBSHash));
687 1580 : certData.mCertFlags.Set(CertFlags::kTBSHashPresent);
688 1622 : }
689 : else
690 : {
691 1208 : ReturnErrorOnFailure(DecodeConvertCert(reader, nullWriter, nullWriter, certData));
692 : }
693 :
694 : // If requested by the caller, mark the certificate as trusted.
695 2747 : if (decodeFlags.Has(CertDecodeFlags::kIsTrustAnchor))
696 : {
697 788 : certData.mCertFlags.Set(CertFlags::kIsTrustAnchor);
698 : }
699 :
700 2747 : return CHIP_NO_ERROR;
701 : }
702 :
703 0 : CHIP_ERROR DecodeChipDN(TLVReader & reader, ChipDN & dn)
704 : {
705 : ASN1Writer writer;
706 :
707 0 : writer.InitNullWriter();
708 :
709 0 : dn.Clear();
710 :
711 0 : return DecodeConvertDN(reader, writer, dn);
712 : }
713 :
714 : } // namespace Credentials
715 : } // namespace chip
|