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 standard X.509
23 : * certificate to a CHIP TLV-encoded certificate.
24 : *
25 : */
26 :
27 : #include <stddef.h>
28 :
29 : #include <credentials/CHIPCert.h>
30 : #include <lib/asn1/ASN1.h>
31 : #include <lib/asn1/ASN1Macros.h>
32 : #include <lib/core/CHIPCore.h>
33 : #include <lib/core/CHIPSafeCasts.h>
34 : #include <lib/core/Optional.h>
35 : #include <lib/core/TLV.h>
36 : #include <lib/support/BytesToHex.h>
37 : #include <lib/support/CodeUtils.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 439 : static CHIP_ERROR ConvertDistinguishedName(ASN1Reader & reader, TLVWriter & writer, Tag tag)
50 : {
51 439 : ChipDN dn;
52 439 : ReturnErrorOnFailure(dn.DecodeFromASN1(reader));
53 432 : return dn.EncodeToTLV(writer, tag);
54 439 : }
55 :
56 223 : static CHIP_ERROR ConvertValidity(ASN1Reader & reader, TLVWriter & writer)
57 : {
58 : CHIP_ERROR err;
59 : ASN1UniversalTime asn1Time;
60 : uint32_t chipEpochTimeNotBefore;
61 : uint32_t chipEpochTimeNotAfter;
62 :
63 223 : ASN1_PARSE_ENTER_SEQUENCE
64 : {
65 223 : ASN1_PARSE_TIME(asn1Time);
66 220 : ReturnErrorOnFailure(ASN1ToChipEpochTime(asn1Time, chipEpochTimeNotBefore));
67 :
68 220 : ASN1_PARSE_TIME(asn1Time);
69 217 : ReturnErrorOnFailure(ASN1ToChipEpochTime(asn1Time, chipEpochTimeNotAfter));
70 :
71 : // Perform this check if NotAfter value is different from Never-Expire value.
72 217 : if (chipEpochTimeNotAfter != kNullCertTime)
73 : {
74 213 : VerifyOrReturnError(chipEpochTimeNotBefore < chipEpochTimeNotAfter, ASN1_ERROR_INVALID_ENCODING);
75 : }
76 :
77 214 : ReturnErrorOnFailure(writer.Put(ContextTag(kTag_NotBefore), chipEpochTimeNotBefore));
78 214 : ReturnErrorOnFailure(writer.Put(ContextTag(kTag_NotAfter), chipEpochTimeNotAfter));
79 : }
80 642 : ASN1_EXIT_SEQUENCE;
81 :
82 214 : exit:
83 220 : return err;
84 : }
85 :
86 208 : static CHIP_ERROR ConvertSubjectPublicKeyInfo(ASN1Reader & reader, TLVWriter & writer)
87 : {
88 : CHIP_ERROR err;
89 : OID pubKeyAlgoOID, pubKeyCurveOID;
90 :
91 : // subjectPublicKeyInfo SubjectPublicKeyInfo,
92 208 : ASN1_PARSE_ENTER_SEQUENCE
93 : {
94 : // algorithm AlgorithmIdentifier,
95 : // AlgorithmIdentifier ::= SEQUENCE
96 208 : ASN1_PARSE_ENTER_SEQUENCE
97 : {
98 : // algorithm OBJECT IDENTIFIER,
99 208 : ASN1_PARSE_OBJECT_ID(pubKeyAlgoOID);
100 :
101 : // Verify that the algorithm type is supported.
102 208 : VerifyOrExit(pubKeyAlgoOID == kOID_PubKeyAlgo_ECPublicKey, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
103 :
104 208 : err = writer.Put(ContextTag(kTag_PublicKeyAlgorithm), GetOIDEnum(pubKeyAlgoOID));
105 208 : SuccessOrExit(err);
106 :
107 : // EcpkParameters ::= CHOICE {
108 : // ecParameters ECParameters,
109 : // namedCurve OBJECT IDENTIFIER,
110 : // implicitlyCA NULL }
111 208 : ASN1_PARSE_ANY;
112 :
113 : // ecParameters and implicitlyCA not supported.
114 208 : if (reader.GetClass() == kASN1TagClass_Universal && reader.GetTag() == kASN1UniversalTag_Sequence)
115 : {
116 0 : ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
117 : }
118 208 : if (reader.GetClass() == kASN1TagClass_Universal && reader.GetTag() == kASN1UniversalTag_Null)
119 : {
120 0 : ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
121 : }
122 :
123 208 : ASN1_VERIFY_TAG(kASN1TagClass_Universal, kASN1UniversalTag_ObjectId);
124 :
125 208 : ASN1_GET_OBJECT_ID(pubKeyCurveOID);
126 :
127 : // Verify the curve name is recognized.
128 208 : VerifyOrExit(GetOIDCategory(pubKeyCurveOID) == kOIDCategory_EllipticCurve, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
129 :
130 205 : err = writer.Put(ContextTag(kTag_EllipticCurveIdentifier), GetOIDEnum(pubKeyCurveOID));
131 205 : SuccessOrExit(err);
132 : }
133 615 : ASN1_EXIT_SEQUENCE;
134 :
135 : // subjectPublicKey BIT STRING
136 205 : ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_BitString);
137 :
138 : // Verify public key length.
139 205 : VerifyOrExit(reader.GetValueLen() > 0, err = ASN1_ERROR_INVALID_ENCODING);
140 :
141 : // The first byte is Unused Bit Count value, which should be zero.
142 205 : VerifyOrExit(reader.GetValue()[0] == 0, err = ASN1_ERROR_INVALID_ENCODING);
143 :
144 : // Copy the X9.62 encoded EC point into the CHIP certificate as a byte string.
145 : // Skip the first Unused Bit Count byte.
146 205 : err = writer.PutBytes(ContextTag(kTag_EllipticCurvePublicKey), reader.GetValue() + 1, reader.GetValueLen() - 1);
147 205 : SuccessOrExit(err);
148 : }
149 615 : ASN1_EXIT_SEQUENCE;
150 :
151 205 : exit:
152 208 : return err;
153 : }
154 :
155 871 : static CHIP_ERROR ConvertExtension(ASN1Reader & reader, TLVWriter & writer)
156 : {
157 : CHIP_ERROR err;
158 : TLVType outerContainer;
159 : OID extensionOID;
160 871 : bool critical = false;
161 : const uint8_t * extensionSequence;
162 : uint32_t extensionSequenceLen;
163 :
164 871 : err = reader.GetConstructedType(extensionSequence, extensionSequenceLen);
165 871 : SuccessOrExit(err);
166 :
167 : // Extension ::= SEQUENCE
168 871 : ASN1_ENTER_SEQUENCE
169 : {
170 : // extnID OBJECT IDENTIFIER,
171 871 : ASN1_PARSE_OBJECT_ID(extensionOID);
172 :
173 : // The kOID_Unknown will be interpreted and encoded as future-extension.
174 871 : if (extensionOID != kOID_Unknown)
175 : {
176 859 : VerifyOrExit(GetOIDCategory(extensionOID) == kOIDCategory_Extension, err = ASN1_ERROR_INVALID_ENCODING);
177 : }
178 :
179 : // critical BOOLEAN DEFAULT FALSE,
180 871 : ASN1_PARSE_ANY;
181 871 : if (reader.GetClass() == kASN1TagClass_Universal && reader.GetTag() == kASN1UniversalTag_Boolean)
182 : {
183 477 : ASN1_GET_BOOLEAN(critical);
184 :
185 477 : VerifyOrExit(critical, err = ASN1_ERROR_INVALID_ENCODING);
186 :
187 477 : ASN1_PARSE_ANY;
188 : }
189 :
190 : // extnValue OCTET STRING
191 : // -- contains the DER encoding of an ASN.1 value
192 : // -- corresponding to the extension type identified
193 : // -- by extnID
194 871 : ASN1_ENTER_ENCAPSULATED(kASN1TagClass_Universal, kASN1UniversalTag_OctetString)
195 : {
196 871 : if (extensionOID == kOID_Extension_AuthorityKeyIdentifier)
197 : {
198 : // This extension MUST be marked as non-critical.
199 184 : VerifyOrExit(!critical, err = ASN1_ERROR_INVALID_ENCODING);
200 :
201 : // AuthorityKeyIdentifier ::= SEQUENCE
202 184 : ASN1_PARSE_ENTER_SEQUENCE
203 : {
204 184 : err = reader.Next();
205 184 : SuccessOrExit(err);
206 :
207 : // keyIdentifier [0] IMPLICIT KeyIdentifier,
208 : // KeyIdentifier ::= OCTET STRING
209 184 : VerifyOrExit(reader.GetClass() == kASN1TagClass_ContextSpecific && reader.GetTag() == 0,
210 : err = ASN1_ERROR_INVALID_ENCODING);
211 :
212 184 : VerifyOrExit(reader.IsConstructed() == false, err = ASN1_ERROR_INVALID_ENCODING);
213 184 : VerifyOrExit(reader.GetValueLen() == kKeyIdentifierLength, err = ASN1_ERROR_INVALID_ENCODING);
214 :
215 181 : err = writer.PutBytes(ContextTag(kTag_AuthorityKeyIdentifier), reader.GetValue(), reader.GetValueLen());
216 181 : SuccessOrExit(err);
217 :
218 180 : err = reader.Next();
219 360 : VerifyOrExit(err == ASN1_END, err = ASN1_ERROR_INVALID_ENCODING);
220 : }
221 540 : ASN1_EXIT_SEQUENCE;
222 : }
223 687 : else if (extensionOID == kOID_Extension_SubjectKeyIdentifier)
224 : {
225 : // This extension MUST be marked as non-critical.
226 187 : VerifyOrExit(!critical, err = ASN1_ERROR_INVALID_ENCODING);
227 :
228 : // SubjectKeyIdentifier ::= KeyIdentifier
229 : // KeyIdentifier ::= OCTET STRING
230 187 : ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_OctetString);
231 :
232 187 : VerifyOrExit(reader.GetValueLen() == kKeyIdentifierLength, err = ASN1_ERROR_INVALID_ENCODING);
233 :
234 184 : err = writer.PutBytes(ContextTag(kTag_SubjectKeyIdentifier), reader.GetValue(), reader.GetValueLen());
235 184 : SuccessOrExit(err);
236 : }
237 500 : else if (extensionOID == kOID_Extension_KeyUsage)
238 : {
239 : // This extension MUST be marked as critical.
240 195 : VerifyOrExit(critical, err = ASN1_ERROR_INVALID_ENCODING);
241 :
242 : // KeyUsage ::= BIT STRING
243 189 : ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_BitString);
244 :
245 : uint32_t keyUsageBits;
246 189 : err = reader.GetBitString(keyUsageBits);
247 189 : SuccessOrExit(err);
248 189 : VerifyOrExit(CanCastTo<uint16_t>(keyUsageBits), err = ASN1_ERROR_INVALID_ENCODING);
249 :
250 : // Check that only supported flags are set.
251 189 : BitFlags<KeyUsageFlags> keyUsageFlags(static_cast<uint16_t>(keyUsageBits));
252 189 : VerifyOrExit(keyUsageFlags.HasOnly(
253 : KeyUsageFlags::kDigitalSignature, KeyUsageFlags::kNonRepudiation, KeyUsageFlags::kKeyEncipherment,
254 : KeyUsageFlags::kDataEncipherment, KeyUsageFlags::kKeyAgreement, KeyUsageFlags::kKeyCertSign,
255 : KeyUsageFlags::kCRLSign, KeyUsageFlags::kEncipherOnly, KeyUsageFlags::kEncipherOnly),
256 : err = ASN1_ERROR_INVALID_ENCODING);
257 :
258 189 : err = writer.Put(ContextTag(kTag_KeyUsage), keyUsageBits);
259 189 : SuccessOrExit(err);
260 : }
261 305 : else if (extensionOID == kOID_Extension_BasicConstraints)
262 : {
263 : // This extension MUST be marked as critical.
264 205 : VerifyOrExit(critical, err = ASN1_ERROR_INVALID_ENCODING);
265 :
266 : // BasicConstraints ::= SEQUENCE
267 199 : ASN1_PARSE_ENTER_SEQUENCE
268 : {
269 199 : bool isCA = false;
270 199 : int64_t pathLenConstraint = -1;
271 :
272 : // cA BOOLEAN DEFAULT FALSE
273 199 : err = reader.Next();
274 505 : if (err == CHIP_NO_ERROR && reader.GetClass() == kASN1TagClass_Universal &&
275 107 : reader.GetTag() == kASN1UniversalTag_Boolean)
276 : {
277 107 : ASN1_GET_BOOLEAN(isCA);
278 :
279 103 : VerifyOrExit(isCA, err = ASN1_ERROR_INVALID_ENCODING);
280 :
281 103 : err = reader.Next();
282 : }
283 :
284 : // pathLenConstraint INTEGER (0..MAX) OPTIONAL
285 405 : if (err == CHIP_NO_ERROR && reader.GetClass() == kASN1TagClass_Universal &&
286 7 : reader.GetTag() == kASN1UniversalTag_Integer)
287 : {
288 7 : ASN1_GET_INTEGER(pathLenConstraint);
289 :
290 7 : VerifyOrExit(CanCastTo<uint8_t>(pathLenConstraint), err = ASN1_ERROR_INVALID_ENCODING);
291 :
292 : // pathLenConstraint is present only when cA is TRUE
293 7 : VerifyOrExit(isCA, err = ASN1_ERROR_INVALID_ENCODING);
294 : }
295 :
296 195 : err = writer.StartContainer(ContextTag(kTag_BasicConstraints), kTLVType_Structure, outerContainer);
297 195 : SuccessOrExit(err);
298 :
299 : // Set also when cA is FALSE
300 195 : err = writer.PutBoolean(ContextTag(kTag_BasicConstraints_IsCA), isCA);
301 195 : SuccessOrExit(err);
302 :
303 195 : if (pathLenConstraint != -1)
304 : {
305 3 : err = writer.Put(ContextTag(kTag_BasicConstraints_PathLenConstraint),
306 : static_cast<uint8_t>(pathLenConstraint));
307 3 : SuccessOrExit(err);
308 : }
309 :
310 195 : err = writer.EndContainer(outerContainer);
311 195 : SuccessOrExit(err);
312 : }
313 585 : ASN1_EXIT_SEQUENCE;
314 : }
315 100 : else if (extensionOID == kOID_Extension_ExtendedKeyUsage)
316 : {
317 : // This extension MUST be marked as critical.
318 88 : VerifyOrExit(critical, err = ASN1_ERROR_INVALID_ENCODING);
319 :
320 88 : err = writer.StartContainer(ContextTag(kTag_ExtendedKeyUsage), kTLVType_Array, outerContainer);
321 88 : SuccessOrExit(err);
322 :
323 : // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
324 88 : ASN1_PARSE_ENTER_SEQUENCE
325 : {
326 526 : while ((err = reader.Next()) == CHIP_NO_ERROR)
327 : {
328 : // KeyPurposeId ::= OBJECT IDENTIFIER
329 : OID keyPurposeOID;
330 175 : ASN1_GET_OBJECT_ID(keyPurposeOID);
331 :
332 175 : VerifyOrExit(keyPurposeOID != kOID_Unknown, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
333 175 : VerifyOrExit(GetOIDCategory(keyPurposeOID) == kOIDCategory_KeyPurpose, err = ASN1_ERROR_INVALID_ENCODING);
334 :
335 175 : err = writer.Put(AnonymousTag(), GetOIDEnum(keyPurposeOID));
336 175 : SuccessOrExit(err);
337 : }
338 176 : if (err != ASN1_END)
339 : {
340 0 : SuccessOrExit(err);
341 : }
342 : }
343 264 : ASN1_EXIT_SEQUENCE;
344 :
345 88 : err = writer.EndContainer(outerContainer);
346 88 : SuccessOrExit(err);
347 : }
348 : // Any other extension is treated as FutureExtension
349 : else
350 : {
351 12 : err = writer.PutBytes(ContextTag(kTag_FutureExtension), extensionSequence, extensionSequenceLen);
352 12 : SuccessOrExit(err);
353 :
354 12 : ASN1_PARSE_ANY;
355 : }
356 : }
357 2544 : ASN1_EXIT_ENCAPSULATED;
358 : }
359 2544 : ASN1_EXIT_SEQUENCE;
360 :
361 848 : exit:
362 871 : return err;
363 : }
364 :
365 205 : static CHIP_ERROR ConvertExtensions(ASN1Reader & reader, TLVWriter & writer)
366 : {
367 : CHIP_ERROR err;
368 : TLVType containerType;
369 :
370 205 : err = writer.StartContainer(ContextTag(kTag_Extensions), kTLVType_List, containerType);
371 205 : SuccessOrExit(err);
372 :
373 : // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
374 205 : ASN1_PARSE_ENTER_SEQUENCE
375 : {
376 2106 : while ((err = reader.Next()) == CHIP_NO_ERROR)
377 : {
378 871 : err = ConvertExtension(reader, writer);
379 871 : SuccessOrExit(err);
380 : }
381 :
382 364 : if (err != ASN1_END)
383 : {
384 0 : SuccessOrExit(err);
385 : }
386 : }
387 546 : ASN1_EXIT_SEQUENCE;
388 :
389 182 : err = writer.EndContainer(containerType);
390 182 : SuccessOrExit(err);
391 :
392 182 : exit:
393 205 : return err;
394 : }
395 :
396 182 : CHIP_ERROR ConvertECDSASignatureDERToRaw(ASN1Reader & reader, TLVWriter & writer, Tag tag)
397 : {
398 182 : CHIP_ERROR err = CHIP_NO_ERROR;
399 : uint8_t rawSig[kP256_ECDSA_Signature_Length_Raw];
400 :
401 : // Per RFC3279, the ECDSA signature value is encoded in DER encapsulated in the signatureValue BIT STRING.
402 182 : ASN1_ENTER_ENCAPSULATED(kASN1TagClass_Universal, kASN1UniversalTag_BitString)
403 : {
404 : // Ecdsa-Sig-Value ::= SEQUENCE
405 182 : ASN1_PARSE_ENTER_SEQUENCE
406 : {
407 : // r INTEGER
408 182 : ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer);
409 182 : ReturnErrorOnFailure(
410 : ConvertIntegerDERToRaw(ByteSpan(reader.GetValue(), reader.GetValueLen()), rawSig, kP256_FE_Length));
411 :
412 : // s INTEGER
413 182 : ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer);
414 182 : ReturnErrorOnFailure(ConvertIntegerDERToRaw(ByteSpan(reader.GetValue(), reader.GetValueLen()), rawSig + kP256_FE_Length,
415 : kP256_FE_Length));
416 : }
417 546 : ASN1_EXIT_SEQUENCE;
418 : }
419 546 : ASN1_EXIT_ENCAPSULATED;
420 :
421 182 : ReturnErrorOnFailure(writer.PutBytes(tag, rawSig, kP256_ECDSA_Signature_Length_Raw));
422 :
423 181 : exit:
424 181 : return err;
425 : }
426 :
427 231 : static CHIP_ERROR ConvertCertificate(ASN1Reader & reader, TLVWriter & writer, Tag tag)
428 : {
429 : CHIP_ERROR err;
430 : int64_t version;
431 : OID sigAlgoOID;
432 : TLVType containerType;
433 :
434 231 : err = writer.StartContainer(tag, kTLVType_Structure, containerType);
435 231 : SuccessOrExit(err);
436 :
437 : // Certificate ::= SEQUENCE
438 231 : ASN1_PARSE_ENTER_SEQUENCE
439 : {
440 : // tbsCertificate TBSCertificate,
441 : // TBSCertificate ::= SEQUENCE
442 231 : ASN1_PARSE_ENTER_SEQUENCE
443 : {
444 : // version [0] EXPLICIT Version DEFAULT v1
445 231 : ASN1_PARSE_ENTER_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
446 : {
447 : // Version ::= INTEGER { v1(0), v2(1), v3(2) }
448 231 : ASN1_PARSE_INTEGER(version);
449 :
450 : // Verify that the X.509 certificate version is v3
451 231 : VerifyOrExit(version == 2, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
452 : }
453 684 : ASN1_EXIT_CONSTRUCTED;
454 :
455 : // serialNumber CertificateSerialNumber
456 : // CertificateSerialNumber ::= INTEGER
457 228 : ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_Integer);
458 228 : err = writer.PutBytes(ContextTag(kTag_SerialNumber), reader.GetValue(), reader.GetValueLen());
459 228 : SuccessOrExit(err);
460 :
461 : // signature AlgorithmIdentifier
462 : // AlgorithmIdentifier ::= SEQUENCE
463 228 : ASN1_PARSE_ENTER_SEQUENCE
464 : {
465 : // algorithm OBJECT IDENTIFIER,
466 228 : ASN1_PARSE_OBJECT_ID(sigAlgoOID);
467 :
468 228 : VerifyOrExit(sigAlgoOID == kOID_SigAlgo_ECDSAWithSHA256, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
469 :
470 225 : err = writer.Put(ContextTag(kTag_SignatureAlgorithm), GetOIDEnum(sigAlgoOID));
471 225 : SuccessOrExit(err);
472 : }
473 675 : ASN1_EXIT_SEQUENCE;
474 :
475 : // issuer Name
476 225 : err = ConvertDistinguishedName(reader, writer, ContextTag(kTag_Issuer));
477 225 : SuccessOrExit(err);
478 :
479 : // validity Validity,
480 223 : err = ConvertValidity(reader, writer);
481 223 : SuccessOrExit(err);
482 :
483 : // subject Name,
484 214 : err = ConvertDistinguishedName(reader, writer, ContextTag(kTag_Subject));
485 214 : SuccessOrExit(err);
486 :
487 208 : err = ConvertSubjectPublicKeyInfo(reader, writer);
488 208 : SuccessOrExit(err);
489 :
490 205 : err = reader.Next();
491 :
492 : // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
493 : // Not supported.
494 410 : if (err == CHIP_NO_ERROR && reader.GetClass() == kASN1TagClass_ContextSpecific && reader.GetTag() == 1)
495 : {
496 0 : ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
497 : }
498 :
499 : // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
500 : // Not supported.
501 410 : if (err == CHIP_NO_ERROR && reader.GetClass() == kASN1TagClass_ContextSpecific && reader.GetTag() == 2)
502 : {
503 0 : ExitNow(err = ASN1_ERROR_UNSUPPORTED_ENCODING);
504 : }
505 :
506 : // extensions [3] EXPLICIT Extensions OPTIONAL
507 410 : if (err == CHIP_NO_ERROR && reader.GetClass() == kASN1TagClass_ContextSpecific && reader.GetTag() == 3)
508 : {
509 205 : ASN1_ENTER_CONSTRUCTED(kASN1TagClass_ContextSpecific, 3)
510 : {
511 205 : err = ConvertExtensions(reader, writer);
512 205 : SuccessOrExit(err);
513 : }
514 546 : ASN1_EXIT_CONSTRUCTED;
515 :
516 182 : err = reader.Next();
517 : }
518 :
519 364 : if (err != ASN1_END)
520 : {
521 0 : ExitNow();
522 : }
523 : }
524 546 : ASN1_EXIT_SEQUENCE;
525 :
526 : // signatureAlgorithm AlgorithmIdentifier
527 : // AlgorithmIdentifier ::= SEQUENCE
528 182 : ASN1_PARSE_ENTER_SEQUENCE
529 : {
530 : OID localSigAlgoOID;
531 :
532 : // algorithm OBJECT IDENTIFIER,
533 182 : ASN1_PARSE_OBJECT_ID(localSigAlgoOID);
534 :
535 : // Verify that the signatureAlgorithm is the same as the "signature" field in TBSCertificate.
536 182 : VerifyOrExit(localSigAlgoOID == sigAlgoOID, err = ASN1_ERROR_UNSUPPORTED_ENCODING);
537 : }
538 546 : ASN1_EXIT_SEQUENCE;
539 :
540 : // signatureValue BIT STRING
541 182 : ASN1_PARSE_ELEMENT(kASN1TagClass_Universal, kASN1UniversalTag_BitString);
542 :
543 182 : ReturnErrorOnFailure(ConvertECDSASignatureDERToRaw(reader, writer, ContextTag(kTag_ECDSASignature)));
544 : }
545 543 : ASN1_EXIT_SEQUENCE;
546 :
547 181 : err = writer.EndContainer(containerType);
548 181 : SuccessOrExit(err);
549 :
550 181 : exit:
551 230 : return err;
552 : }
553 :
554 235 : CHIP_ERROR ConvertX509CertToChipCert(const ByteSpan x509Cert, MutableByteSpan & chipCert)
555 : {
556 : ASN1Reader reader;
557 235 : TLVWriter writer;
558 :
559 235 : VerifyOrReturnError(!x509Cert.empty(), CHIP_ERROR_INVALID_ARGUMENT);
560 233 : VerifyOrReturnError(CanCastTo<uint32_t>(x509Cert.size()), CHIP_ERROR_INVALID_ARGUMENT);
561 :
562 231 : reader.Init(x509Cert);
563 :
564 231 : writer.Init(chipCert);
565 :
566 231 : ReturnErrorOnFailure(ConvertCertificate(reader, writer, AnonymousTag()));
567 :
568 181 : ReturnErrorOnFailure(writer.Finalize());
569 :
570 181 : chipCert.reduce_size(writer.GetLengthWritten());
571 :
572 181 : return CHIP_NO_ERROR;
573 : }
574 :
575 : } // namespace Credentials
576 : } // namespace chip
|