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