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