Coverage Report

Created: 2026-01-22 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/connectedhomeip/src/credentials/GenerateChipX509Cert.cpp
Line
Count
Source
1
/*
2
 *
3
 *    Copyright (c) 2021-2022 Project CHIP Authors
4
 *    All rights reserved.
5
 *
6
 *    Licensed under the Apache License, Version 2.0 (the "License");
7
 *    you may not use this file except in compliance with the License.
8
 *    You may obtain a copy of the License at
9
 *
10
 *        http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 *    Unless required by applicable law or agreed to in writing, software
13
 *    distributed under the License is distributed on an "AS IS" BASIS,
14
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 *    See the License for the specific language governing permissions and
16
 *    limitations under the License.
17
 */
18
19
/**
20
 *    @file
21
 *      This file implements methods for generating CHIP X.509 certificate.
22
 *
23
 */
24
25
#include <algorithm>
26
#include <initializer_list>
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/support/CodeUtils.h>
36
#include <lib/support/DLLUtil.h>
37
#include <protocols/Protocols.h>
38
39
namespace chip {
40
namespace Credentials {
41
42
using namespace chip::ASN1;
43
using namespace chip::Crypto;
44
using namespace chip::Protocols;
45
46
namespace {
47
48
enum IsCACert
49
{
50
    kCACert,
51
    kNotCACert,
52
};
53
54
CHIP_ERROR EncodeSubjectPublicKeyInfo(const Crypto::P256PublicKey & pubkey, ASN1Writer & writer)
55
0
{
56
0
    CHIP_ERROR err = CHIP_NO_ERROR;
57
58
0
    ASN1_START_SEQUENCE
59
0
    {
60
0
        ASN1_START_SEQUENCE
61
0
        {
62
0
            ASN1_ENCODE_OBJECT_ID(kOID_PubKeyAlgo_ECPublicKey);
63
0
            ASN1_ENCODE_OBJECT_ID(kOID_EllipticCurve_prime256v1);
64
0
        }
65
0
        ASN1_END_SEQUENCE;
66
67
0
        ReturnErrorOnFailure(writer.PutBitString(0, pubkey, static_cast<uint8_t>(pubkey.Length())));
68
0
    }
69
0
    ASN1_END_SEQUENCE;
70
71
0
exit:
72
0
    return err;
73
0
}
74
75
CHIP_ERROR EncodeAuthorityKeyIdentifierExtension(const Crypto::P256PublicKey & pubkey, ASN1Writer & writer)
76
0
{
77
0
    CHIP_ERROR err = CHIP_NO_ERROR;
78
79
0
    ASN1_START_SEQUENCE
80
0
    {
81
0
        ASN1_ENCODE_OBJECT_ID(kOID_Extension_AuthorityKeyIdentifier);
82
83
0
        ASN1_START_OCTET_STRING_ENCAPSULATED
84
0
        {
85
0
            ASN1_START_SEQUENCE
86
0
            {
87
0
                uint8_t keyid[kSHA1_Hash_Length];
88
0
                ReturnErrorOnFailure(Crypto::Hash_SHA1(pubkey, pubkey.Length(), keyid));
89
90
0
                ReturnErrorOnFailure(
91
0
                    writer.PutOctetString(kASN1TagClass_ContextSpecific, 0, keyid, static_cast<uint8_t>(sizeof(keyid))));
92
0
            }
93
0
            ASN1_END_SEQUENCE;
94
0
        }
95
0
        ASN1_END_ENCAPSULATED;
96
0
    }
97
0
    ASN1_END_SEQUENCE;
98
99
0
exit:
100
0
    return err;
101
0
}
102
103
CHIP_ERROR EncodeSubjectKeyIdentifierExtension(const Crypto::P256PublicKey & pubkey, ASN1Writer & writer)
104
0
{
105
0
    CHIP_ERROR err = CHIP_NO_ERROR;
106
107
0
    ASN1_START_SEQUENCE
108
0
    {
109
0
        ASN1_ENCODE_OBJECT_ID(kOID_Extension_SubjectKeyIdentifier);
110
111
0
        ASN1_START_OCTET_STRING_ENCAPSULATED
112
0
        {
113
0
            uint8_t keyid[kSHA1_Hash_Length];
114
0
            ReturnErrorOnFailure(Crypto::Hash_SHA1(pubkey, pubkey.Length(), keyid));
115
116
0
            ReturnErrorOnFailure(writer.PutOctetString(keyid, static_cast<uint8_t>(sizeof(keyid))));
117
0
        }
118
0
        ASN1_END_ENCAPSULATED;
119
0
    }
120
0
    ASN1_END_SEQUENCE;
121
122
0
exit:
123
0
    return err;
124
0
}
125
126
CHIP_ERROR EncodeExtKeyUsageExtension(std::initializer_list<OID> keyPurposeOIDs, ASN1Writer & writer)
127
0
{
128
0
    CHIP_ERROR err = CHIP_NO_ERROR;
129
0
    ASN1_START_SEQUENCE
130
0
    {
131
0
        ASN1_ENCODE_OBJECT_ID(kOID_Extension_ExtendedKeyUsage);
132
133
        // ExtKeyUsage extension MUST be marked as critical.
134
0
        ASN1_ENCODE_BOOLEAN(true);
135
0
        ASN1_START_OCTET_STRING_ENCAPSULATED
136
0
        {
137
0
            ASN1_START_SEQUENCE
138
0
            {
139
0
                for (auto && oid : keyPurposeOIDs)
140
0
                {
141
0
                    ASN1_ENCODE_OBJECT_ID(oid);
142
0
                }
143
0
            }
144
0
            ASN1_END_SEQUENCE;
145
0
        }
146
0
        ASN1_END_ENCAPSULATED;
147
0
    }
148
0
    ASN1_END_SEQUENCE;
149
150
0
exit:
151
0
    return err;
152
0
}
153
154
CHIP_ERROR EncodeKeyUsageExtension(BitFlags<KeyUsageFlags> keyUsageFlags, ASN1Writer & writer)
155
0
{
156
0
    CHIP_ERROR err = CHIP_NO_ERROR;
157
0
    ASN1_START_SEQUENCE
158
0
    {
159
0
        ASN1_ENCODE_OBJECT_ID(kOID_Extension_KeyUsage);
160
161
        // KeyUsage extension MUST be marked as critical.
162
0
        ASN1_ENCODE_BOOLEAN(true);
163
0
        ASN1_START_OCTET_STRING_ENCAPSULATED
164
0
        {
165
0
            ASN1_ENCODE_BIT_STRING(keyUsageFlags.Raw());
166
0
        }
167
0
        ASN1_END_ENCAPSULATED;
168
0
    }
169
0
    ASN1_END_SEQUENCE;
170
171
0
exit:
172
0
    return err;
173
0
}
174
175
CHIP_ERROR EncodeIsCAExtension(IsCACert isCA, ASN1Writer & writer)
176
0
{
177
0
    CHIP_ERROR err = CHIP_NO_ERROR;
178
0
    ASN1_START_SEQUENCE
179
0
    {
180
0
        ASN1_ENCODE_OBJECT_ID(kOID_Extension_BasicConstraints);
181
182
        // BasicConstraints extension MUST be marked as critical.
183
0
        ASN1_ENCODE_BOOLEAN(true);
184
185
0
        ASN1_START_OCTET_STRING_ENCAPSULATED
186
0
        {
187
0
            ASN1_START_SEQUENCE
188
0
            {
189
                // cA BOOLEAN
190
0
                if (isCA == kCACert)
191
0
                {
192
                    // Encode the boolean only if isCA is true
193
0
                    ASN1_ENCODE_BOOLEAN(true);
194
0
                }
195
0
            }
196
0
            ASN1_END_SEQUENCE;
197
0
        }
198
0
        ASN1_END_ENCAPSULATED;
199
0
    }
200
0
    ASN1_END_SEQUENCE;
201
202
0
exit:
203
0
    return err;
204
0
}
205
206
CHIP_ERROR EncodeCASpecificExtensions(ASN1Writer & writer)
207
0
{
208
0
    ReturnErrorOnFailure(EncodeIsCAExtension(kCACert, writer));
209
0
    ReturnErrorOnFailure(
210
0
        EncodeKeyUsageExtension(BitFlags<KeyUsageFlags>(KeyUsageFlags::kKeyCertSign, KeyUsageFlags::kCRLSign), writer));
211
0
    return CHIP_NO_ERROR;
212
0
}
213
214
CHIP_ERROR EncodeNOCSpecificExtensions(ASN1Writer & writer)
215
0
{
216
0
    ReturnErrorOnFailure(EncodeIsCAExtension(kNotCACert, writer));
217
0
    ReturnErrorOnFailure(EncodeKeyUsageExtension(KeyUsageFlags::kDigitalSignature, writer));
218
0
    ReturnErrorOnFailure(EncodeExtKeyUsageExtension({ kOID_KeyPurpose_ClientAuth, kOID_KeyPurpose_ServerAuth }, writer));
219
0
    return CHIP_NO_ERROR;
220
0
}
221
222
CHIP_ERROR EncodeVendorIdVerificationSignerSpecificExtensions(ASN1Writer & writer)
223
0
{
224
0
    ReturnErrorOnFailure(EncodeIsCAExtension(kNotCACert, writer));
225
0
    ReturnErrorOnFailure(EncodeKeyUsageExtension(KeyUsageFlags::kDigitalSignature, writer));
226
0
    return CHIP_NO_ERROR;
227
0
}
228
229
CHIP_ERROR EncodeFutureExtension(const Optional<FutureExtension> & futureExt, ASN1Writer & writer)
230
0
{
231
0
    CHIP_ERROR err = CHIP_NO_ERROR;
232
233
0
    VerifyOrReturnError(futureExt.HasValue(), CHIP_NO_ERROR);
234
235
0
    ASN1_START_SEQUENCE
236
0
    {
237
0
        ReturnErrorOnFailure(writer.PutObjectId(futureExt.Value().OID.data(), static_cast<uint16_t>(futureExt.Value().OID.size())));
238
239
0
        ASN1_START_OCTET_STRING_ENCAPSULATED
240
0
        {
241
0
            ReturnErrorOnFailure(writer.PutOctetString(futureExt.Value().Extension.data(),
242
0
                                                       static_cast<uint16_t>(futureExt.Value().Extension.size())));
243
0
        }
244
0
        ASN1_END_ENCAPSULATED;
245
0
    }
246
0
    ASN1_END_SEQUENCE;
247
248
0
exit:
249
0
    return err;
250
0
}
251
252
CHIP_ERROR EncodeExtensions(CertType certType, const Crypto::P256PublicKey & SKI, const Crypto::P256PublicKey & AKI,
253
                            const Optional<FutureExtension> & futureExt, ASN1Writer & writer)
254
0
{
255
0
    CHIP_ERROR err = CHIP_NO_ERROR;
256
257
0
    ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 3)
258
0
    {
259
0
        ASN1_START_SEQUENCE
260
0
        {
261
0
            switch (certType)
262
0
            {
263
0
            case CertType::kICA:
264
0
            case CertType::kRoot: {
265
0
                ReturnErrorOnFailure(EncodeCASpecificExtensions(writer));
266
0
                break;
267
0
            }
268
0
            case CertType::kNode: {
269
0
                ReturnErrorOnFailure(EncodeNOCSpecificExtensions(writer));
270
0
                break;
271
0
            }
272
0
            case CertType::kVidVerificationSigner: {
273
0
                ReturnErrorOnFailure(EncodeVendorIdVerificationSignerSpecificExtensions(writer));
274
0
                break;
275
0
            }
276
0
            case CertType::kFirmwareSigning:
277
0
            case CertType::kNetworkIdentity: {
278
                // Nothing to encode extra for those.
279
0
                break;
280
0
            }
281
0
            default: {
282
                // Unknown/invalid certificate type should not happen.
283
0
                return CHIP_ERROR_INVALID_ARGUMENT;
284
0
            }
285
0
            }
286
0
            ReturnErrorOnFailure(EncodeSubjectKeyIdentifierExtension(SKI, writer));
287
288
0
            ReturnErrorOnFailure(EncodeAuthorityKeyIdentifierExtension(AKI, writer));
289
290
0
            ReturnErrorOnFailure(EncodeFutureExtension(futureExt, writer));
291
0
        }
292
0
        ASN1_END_SEQUENCE;
293
0
    }
294
0
    ASN1_END_CONSTRUCTED;
295
296
0
exit:
297
0
    return err;
298
0
}
299
300
CHIP_ERROR EncodeValidity(uint32_t validityStart, uint32_t validityEnd, ASN1Writer & writer)
301
0
{
302
0
    CHIP_ERROR err = CHIP_NO_ERROR;
303
0
    ASN1UniversalTime asn1Time;
304
305
0
    ASN1_START_SEQUENCE
306
0
    {
307
0
        ReturnErrorOnFailure(ChipEpochToASN1Time(validityStart, asn1Time));
308
0
        ASN1_ENCODE_TIME(asn1Time);
309
310
0
        ReturnErrorOnFailure(ChipEpochToASN1Time(validityEnd, asn1Time));
311
0
        ASN1_ENCODE_TIME(asn1Time);
312
0
    }
313
0
    ASN1_END_SEQUENCE;
314
315
0
exit:
316
0
    return err;
317
0
}
318
319
CHIP_ERROR EncodeChipECDSASignature(Crypto::P256ECDSASignature & signature, ASN1Writer & writer)
320
0
{
321
0
    CHIP_ERROR err = CHIP_NO_ERROR;
322
323
0
    ASN1_START_BIT_STRING_ENCAPSULATED
324
0
    {
325
        // Convert RAW signature to DER when generating X509 certs.
326
0
        P256ECDSASignatureSpan raw_sig(signature.Bytes());
327
0
        ReturnErrorOnFailure(ConvertECDSASignatureRawToDER(raw_sig, writer));
328
0
    }
329
0
    ASN1_END_ENCAPSULATED;
330
331
0
exit:
332
0
    return err;
333
0
}
334
335
CHIP_ERROR EncodeTBSCert(const X509CertRequestParams & requestParams, const Crypto::P256PublicKey & subjectPubkey,
336
                         const Crypto::P256PublicKey & issuerPubkey, ASN1Writer & writer)
337
0
{
338
0
    CHIP_ERROR err = CHIP_NO_ERROR;
339
0
    CertType certType;
340
341
0
    VerifyOrReturnError(requestParams.SerialNumber >= 0, CHIP_ERROR_INVALID_ARGUMENT);
342
0
    VerifyOrReturnError(requestParams.ValidityEnd == kNullCertTime || requestParams.ValidityEnd >= requestParams.ValidityStart,
343
0
                        CHIP_ERROR_INVALID_ARGUMENT);
344
345
0
    ReturnErrorOnFailure(requestParams.SubjectDN.GetCertType(certType));
346
347
0
    ASN1_START_SEQUENCE
348
0
    {
349
        // version [0] EXPLICIT Version DEFAULT v1
350
0
        ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
351
0
        {
352
            // Version ::= INTEGER { v1(0), v2(1), v3(2) }
353
0
            ASN1_ENCODE_INTEGER(2);
354
0
        }
355
0
        ASN1_END_CONSTRUCTED;
356
357
0
        ReturnErrorOnFailure(writer.PutInteger(requestParams.SerialNumber));
358
359
0
        ASN1_START_SEQUENCE
360
0
        {
361
0
            ASN1_ENCODE_OBJECT_ID(kOID_SigAlgo_ECDSAWithSHA256);
362
0
        }
363
0
        ASN1_END_SEQUENCE;
364
365
        // issuer Name
366
0
        ReturnErrorOnFailure(requestParams.IssuerDN.EncodeToASN1(writer));
367
368
        // validity Validity,
369
0
        ReturnErrorOnFailure(EncodeValidity(requestParams.ValidityStart, requestParams.ValidityEnd, writer));
370
371
        // subject Name
372
0
        ReturnErrorOnFailure(requestParams.SubjectDN.EncodeToASN1(writer));
373
374
0
        ReturnErrorOnFailure(EncodeSubjectPublicKeyInfo(subjectPubkey, writer));
375
376
        // certificate extensions
377
0
        ReturnErrorOnFailure(EncodeExtensions(certType, subjectPubkey, issuerPubkey, requestParams.FutureExt, writer));
378
0
    }
379
0
    ASN1_END_SEQUENCE;
380
381
0
exit:
382
0
    return err;
383
0
}
384
385
} // namespace
386
387
CHIP_ERROR EncodeNetworkIdentityTBSCert(const P256PublicKey & pubkey, ASN1Writer & writer)
388
0
{
389
0
    CHIP_ERROR err = CHIP_NO_ERROR;
390
0
    ChipDN issuerAndSubject;
391
0
    InitNetworkIdentitySubject(issuerAndSubject);
392
393
0
    ASN1_START_SEQUENCE
394
0
    {
395
        // version [0] EXPLICIT Version DEFAULT v1
396
0
        ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 0)
397
0
        {
398
0
            ASN1_ENCODE_INTEGER(2); // Version ::= INTEGER { v1(0), v2(1), v3(2) }
399
0
        }
400
0
        ASN1_END_CONSTRUCTED;
401
402
0
        ReturnErrorOnFailure(writer.PutInteger(kNetworkIdentitySerialNumber));
403
404
0
        ASN1_START_SEQUENCE
405
0
        {
406
0
            ASN1_ENCODE_OBJECT_ID(kOID_SigAlgo_ECDSAWithSHA256);
407
0
        }
408
0
        ASN1_END_SEQUENCE;
409
410
        // issuer Name
411
0
        ReturnErrorOnFailure(issuerAndSubject.EncodeToASN1(writer));
412
413
        // validity Validity,
414
0
        ReturnErrorOnFailure(EncodeValidity(kNetworkIdentityNotBeforeTime, kNetworkIdentityNotAfterTime, writer));
415
416
        // subject Name
417
0
        ReturnErrorOnFailure(issuerAndSubject.EncodeToASN1(writer));
418
419
0
        ReturnErrorOnFailure(EncodeSubjectPublicKeyInfo(pubkey, writer));
420
421
        // certificate extensions
422
0
        ASN1_START_CONSTRUCTED(kASN1TagClass_ContextSpecific, 3)
423
0
        {
424
0
            ASN1_START_SEQUENCE
425
0
            {
426
0
                TEMPORARY_RETURN_IGNORED EncodeIsCAExtension(kNotCACert, writer);
427
0
                TEMPORARY_RETURN_IGNORED EncodeKeyUsageExtension(KeyUsageFlags::kDigitalSignature, writer);
428
0
                TEMPORARY_RETURN_IGNORED EncodeExtKeyUsageExtension({ kOID_KeyPurpose_ClientAuth, kOID_KeyPurpose_ServerAuth },
429
0
                                                                    writer);
430
0
            }
431
0
            ASN1_END_SEQUENCE;
432
0
        }
433
0
        ASN1_END_CONSTRUCTED;
434
0
    }
435
0
    ASN1_END_SEQUENCE;
436
437
0
exit:
438
0
    return err;
439
0
}
440
441
CHIP_ERROR NewChipX509Cert(const X509CertRequestParams & requestParams, const Crypto::P256PublicKey & subjectPubkey,
442
                           const Crypto::P256Keypair & issuerKeypair, MutableByteSpan & x509Cert)
443
0
{
444
0
    CHIP_ERROR err = CHIP_NO_ERROR;
445
0
    ASN1Writer writer;
446
0
    writer.Init(x509Cert);
447
448
0
    ReturnErrorOnFailure(EncodeTBSCert(requestParams, subjectPubkey, issuerKeypair.Pubkey(), writer));
449
450
0
    Crypto::P256ECDSASignature signature;
451
0
    ReturnErrorOnFailure(issuerKeypair.ECDSA_sign_msg(x509Cert.data(), writer.GetLengthWritten(), signature));
452
453
0
    writer.Init(x509Cert);
454
455
0
    ASN1_START_SEQUENCE
456
0
    {
457
0
        ReturnErrorOnFailure(EncodeTBSCert(requestParams, subjectPubkey, issuerKeypair.Pubkey(), writer));
458
459
0
        ASN1_START_SEQUENCE
460
0
        {
461
0
            ASN1_ENCODE_OBJECT_ID(kOID_SigAlgo_ECDSAWithSHA256);
462
0
        }
463
0
        ASN1_END_SEQUENCE;
464
465
0
        ReturnErrorOnFailure(EncodeChipECDSASignature(signature, writer));
466
0
    }
467
0
    ASN1_END_SEQUENCE;
468
469
0
    x509Cert.reduce_size(writer.GetLengthWritten());
470
471
0
exit:
472
0
    return err;
473
0
}
474
475
DLL_EXPORT CHIP_ERROR NewRootX509Cert(const X509CertRequestParams & requestParams, const Crypto::P256Keypair & issuerKeypair,
476
                                      MutableByteSpan & x509Cert)
477
0
{
478
0
    CertType certType;
479
480
0
    ReturnErrorOnFailure(requestParams.SubjectDN.GetCertType(certType));
481
0
    VerifyOrReturnError(certType == CertType::kRoot, CHIP_ERROR_INVALID_ARGUMENT);
482
0
    VerifyOrReturnError(requestParams.SubjectDN.IsEqual(requestParams.IssuerDN), CHIP_ERROR_INVALID_ARGUMENT);
483
484
0
    return NewChipX509Cert(requestParams, issuerKeypair.Pubkey(), issuerKeypair, x509Cert);
485
0
}
486
487
DLL_EXPORT CHIP_ERROR NewICAX509Cert(const X509CertRequestParams & requestParams, const Crypto::P256PublicKey & subjectPubkey,
488
                                     const Crypto::P256Keypair & issuerKeypair, MutableByteSpan & x509Cert)
489
0
{
490
0
    CertType certType;
491
492
0
    ReturnErrorOnFailure(requestParams.SubjectDN.GetCertType(certType));
493
0
    VerifyOrReturnError(certType == CertType::kICA, CHIP_ERROR_INVALID_ARGUMENT);
494
495
0
    ReturnErrorOnFailure(requestParams.IssuerDN.GetCertType(certType));
496
0
    VerifyOrReturnError(certType == CertType::kRoot, CHIP_ERROR_INVALID_ARGUMENT);
497
498
0
    return NewChipX509Cert(requestParams, subjectPubkey, issuerKeypair, x509Cert);
499
0
}
500
501
CHIP_ERROR NewVidVerificationSignerX509Cert(const X509CertRequestParams & requestParams,
502
                                            const Crypto::P256PublicKey & subjectPubkey, const Crypto::P256Keypair & issuerKeypair,
503
                                            MutableByteSpan & x509Cert)
504
0
{
505
0
    CertType certType;
506
507
0
    ReturnErrorOnFailure(requestParams.SubjectDN.GetCertType(certType));
508
0
    VerifyOrReturnError(certType == CertType::kVidVerificationSigner, CHIP_ERROR_INVALID_ARGUMENT);
509
510
0
    ReturnErrorOnFailure(requestParams.IssuerDN.GetCertType(certType));
511
0
    VerifyOrReturnError((certType == CertType::kICA) || (certType == CertType::kRoot), CHIP_ERROR_INVALID_ARGUMENT);
512
513
0
    return NewChipX509Cert(requestParams, subjectPubkey, issuerKeypair, x509Cert);
514
0
}
515
516
DLL_EXPORT CHIP_ERROR NewNodeOperationalX509Cert(const X509CertRequestParams & requestParams,
517
                                                 const Crypto::P256PublicKey & subjectPubkey,
518
                                                 const Crypto::P256Keypair & issuerKeypair, MutableByteSpan & x509Cert)
519
0
{
520
0
    CertType certType;
521
522
0
    ReturnErrorOnFailure(requestParams.SubjectDN.GetCertType(certType));
523
0
    VerifyOrReturnError(certType == CertType::kNode, CHIP_ERROR_INVALID_ARGUMENT);
524
525
0
    ReturnErrorOnFailure(requestParams.IssuerDN.GetCertType(certType));
526
0
    VerifyOrReturnError(certType == CertType::kICA || certType == CertType::kRoot, CHIP_ERROR_INVALID_ARGUMENT);
527
528
0
    return NewChipX509Cert(requestParams, subjectPubkey, issuerKeypair, x509Cert);
529
0
}
530
531
} // namespace Credentials
532
} // namespace chip