1a8e1175bSopenharmony_ci/*
2a8e1175bSopenharmony_ci *  X.509 certificate writing
3a8e1175bSopenharmony_ci *
4a8e1175bSopenharmony_ci *  Copyright The Mbed TLS Contributors
5a8e1175bSopenharmony_ci *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6a8e1175bSopenharmony_ci */
7a8e1175bSopenharmony_ci/*
8a8e1175bSopenharmony_ci * References:
9a8e1175bSopenharmony_ci * - certificates: RFC 5280, updated by RFC 6818
10a8e1175bSopenharmony_ci * - CSRs: PKCS#10 v1.7 aka RFC 2986
11a8e1175bSopenharmony_ci * - attributes: PKCS#9 v2.0 aka RFC 2985
12a8e1175bSopenharmony_ci */
13a8e1175bSopenharmony_ci
14a8e1175bSopenharmony_ci#include "common.h"
15a8e1175bSopenharmony_ci
16a8e1175bSopenharmony_ci#if defined(MBEDTLS_X509_CRT_WRITE_C)
17a8e1175bSopenharmony_ci
18a8e1175bSopenharmony_ci#include "mbedtls/x509_crt.h"
19a8e1175bSopenharmony_ci#include "x509_internal.h"
20a8e1175bSopenharmony_ci#include "mbedtls/asn1write.h"
21a8e1175bSopenharmony_ci#include "mbedtls/error.h"
22a8e1175bSopenharmony_ci#include "mbedtls/oid.h"
23a8e1175bSopenharmony_ci#include "mbedtls/platform.h"
24a8e1175bSopenharmony_ci#include "mbedtls/platform_util.h"
25a8e1175bSopenharmony_ci#include "mbedtls/md.h"
26a8e1175bSopenharmony_ci
27a8e1175bSopenharmony_ci#include <string.h>
28a8e1175bSopenharmony_ci#include <stdint.h>
29a8e1175bSopenharmony_ci
30a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_WRITE_C)
31a8e1175bSopenharmony_ci#include "mbedtls/pem.h"
32a8e1175bSopenharmony_ci#endif /* MBEDTLS_PEM_WRITE_C */
33a8e1175bSopenharmony_ci
34a8e1175bSopenharmony_ci#if defined(MBEDTLS_USE_PSA_CRYPTO)
35a8e1175bSopenharmony_ci#include "psa/crypto.h"
36a8e1175bSopenharmony_ci#include "psa_util_internal.h"
37a8e1175bSopenharmony_ci#include "mbedtls/psa_util.h"
38a8e1175bSopenharmony_ci#endif /* MBEDTLS_USE_PSA_CRYPTO */
39a8e1175bSopenharmony_ci
40a8e1175bSopenharmony_civoid mbedtls_x509write_crt_init(mbedtls_x509write_cert *ctx)
41a8e1175bSopenharmony_ci{
42a8e1175bSopenharmony_ci    memset(ctx, 0, sizeof(mbedtls_x509write_cert));
43a8e1175bSopenharmony_ci
44a8e1175bSopenharmony_ci    ctx->version = MBEDTLS_X509_CRT_VERSION_3;
45a8e1175bSopenharmony_ci}
46a8e1175bSopenharmony_ci
47a8e1175bSopenharmony_civoid mbedtls_x509write_crt_free(mbedtls_x509write_cert *ctx)
48a8e1175bSopenharmony_ci{
49a8e1175bSopenharmony_ci    mbedtls_asn1_free_named_data_list(&ctx->subject);
50a8e1175bSopenharmony_ci    mbedtls_asn1_free_named_data_list(&ctx->issuer);
51a8e1175bSopenharmony_ci    mbedtls_asn1_free_named_data_list(&ctx->extensions);
52a8e1175bSopenharmony_ci
53a8e1175bSopenharmony_ci    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_x509write_cert));
54a8e1175bSopenharmony_ci}
55a8e1175bSopenharmony_ci
56a8e1175bSopenharmony_civoid mbedtls_x509write_crt_set_version(mbedtls_x509write_cert *ctx,
57a8e1175bSopenharmony_ci                                       int version)
58a8e1175bSopenharmony_ci{
59a8e1175bSopenharmony_ci    ctx->version = version;
60a8e1175bSopenharmony_ci}
61a8e1175bSopenharmony_ci
62a8e1175bSopenharmony_civoid mbedtls_x509write_crt_set_md_alg(mbedtls_x509write_cert *ctx,
63a8e1175bSopenharmony_ci                                      mbedtls_md_type_t md_alg)
64a8e1175bSopenharmony_ci{
65a8e1175bSopenharmony_ci    ctx->md_alg = md_alg;
66a8e1175bSopenharmony_ci}
67a8e1175bSopenharmony_ci
68a8e1175bSopenharmony_civoid mbedtls_x509write_crt_set_subject_key(mbedtls_x509write_cert *ctx,
69a8e1175bSopenharmony_ci                                           mbedtls_pk_context *key)
70a8e1175bSopenharmony_ci{
71a8e1175bSopenharmony_ci    ctx->subject_key = key;
72a8e1175bSopenharmony_ci}
73a8e1175bSopenharmony_ci
74a8e1175bSopenharmony_civoid mbedtls_x509write_crt_set_issuer_key(mbedtls_x509write_cert *ctx,
75a8e1175bSopenharmony_ci                                          mbedtls_pk_context *key)
76a8e1175bSopenharmony_ci{
77a8e1175bSopenharmony_ci    ctx->issuer_key = key;
78a8e1175bSopenharmony_ci}
79a8e1175bSopenharmony_ci
80a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_subject_name(mbedtls_x509write_cert *ctx,
81a8e1175bSopenharmony_ci                                           const char *subject_name)
82a8e1175bSopenharmony_ci{
83a8e1175bSopenharmony_ci    return mbedtls_x509_string_to_names(&ctx->subject, subject_name);
84a8e1175bSopenharmony_ci}
85a8e1175bSopenharmony_ci
86a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_issuer_name(mbedtls_x509write_cert *ctx,
87a8e1175bSopenharmony_ci                                          const char *issuer_name)
88a8e1175bSopenharmony_ci{
89a8e1175bSopenharmony_ci    return mbedtls_x509_string_to_names(&ctx->issuer, issuer_name);
90a8e1175bSopenharmony_ci}
91a8e1175bSopenharmony_ci
92a8e1175bSopenharmony_ci#if defined(MBEDTLS_BIGNUM_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)
93a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_serial(mbedtls_x509write_cert *ctx,
94a8e1175bSopenharmony_ci                                     const mbedtls_mpi *serial)
95a8e1175bSopenharmony_ci{
96a8e1175bSopenharmony_ci    int ret;
97a8e1175bSopenharmony_ci    size_t tmp_len;
98a8e1175bSopenharmony_ci
99a8e1175bSopenharmony_ci    /* Ensure that the MPI value fits into the buffer */
100a8e1175bSopenharmony_ci    tmp_len = mbedtls_mpi_size(serial);
101a8e1175bSopenharmony_ci    if (tmp_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) {
102a8e1175bSopenharmony_ci        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
103a8e1175bSopenharmony_ci    }
104a8e1175bSopenharmony_ci
105a8e1175bSopenharmony_ci    ctx->serial_len = tmp_len;
106a8e1175bSopenharmony_ci
107a8e1175bSopenharmony_ci    ret = mbedtls_mpi_write_binary(serial, ctx->serial, tmp_len);
108a8e1175bSopenharmony_ci    if (ret < 0) {
109a8e1175bSopenharmony_ci        return ret;
110a8e1175bSopenharmony_ci    }
111a8e1175bSopenharmony_ci
112a8e1175bSopenharmony_ci    return 0;
113a8e1175bSopenharmony_ci}
114a8e1175bSopenharmony_ci#endif // MBEDTLS_BIGNUM_C && !MBEDTLS_DEPRECATED_REMOVED
115a8e1175bSopenharmony_ci
116a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_serial_raw(mbedtls_x509write_cert *ctx,
117a8e1175bSopenharmony_ci                                         unsigned char *serial, size_t serial_len)
118a8e1175bSopenharmony_ci{
119a8e1175bSopenharmony_ci    if (serial_len > MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN) {
120a8e1175bSopenharmony_ci        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
121a8e1175bSopenharmony_ci    }
122a8e1175bSopenharmony_ci
123a8e1175bSopenharmony_ci    ctx->serial_len = serial_len;
124a8e1175bSopenharmony_ci    memcpy(ctx->serial, serial, serial_len);
125a8e1175bSopenharmony_ci
126a8e1175bSopenharmony_ci    return 0;
127a8e1175bSopenharmony_ci}
128a8e1175bSopenharmony_ci
129a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert *ctx,
130a8e1175bSopenharmony_ci                                       const char *not_before,
131a8e1175bSopenharmony_ci                                       const char *not_after)
132a8e1175bSopenharmony_ci{
133a8e1175bSopenharmony_ci    if (strlen(not_before) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ||
134a8e1175bSopenharmony_ci        strlen(not_after)  != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1) {
135a8e1175bSopenharmony_ci        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
136a8e1175bSopenharmony_ci    }
137a8e1175bSopenharmony_ci    strncpy(ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN);
138a8e1175bSopenharmony_ci    strncpy(ctx->not_after, not_after, MBEDTLS_X509_RFC5280_UTC_TIME_LEN);
139a8e1175bSopenharmony_ci    ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
140a8e1175bSopenharmony_ci    ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z';
141a8e1175bSopenharmony_ci
142a8e1175bSopenharmony_ci    return 0;
143a8e1175bSopenharmony_ci}
144a8e1175bSopenharmony_ci
145a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_subject_alternative_name(mbedtls_x509write_cert *ctx,
146a8e1175bSopenharmony_ci                                                       const mbedtls_x509_san_list *san_list)
147a8e1175bSopenharmony_ci{
148a8e1175bSopenharmony_ci    return mbedtls_x509_write_set_san_common(&ctx->extensions, san_list);
149a8e1175bSopenharmony_ci}
150a8e1175bSopenharmony_ci
151a8e1175bSopenharmony_ci
152a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_extension(mbedtls_x509write_cert *ctx,
153a8e1175bSopenharmony_ci                                        const char *oid, size_t oid_len,
154a8e1175bSopenharmony_ci                                        int critical,
155a8e1175bSopenharmony_ci                                        const unsigned char *val, size_t val_len)
156a8e1175bSopenharmony_ci{
157a8e1175bSopenharmony_ci    return mbedtls_x509_set_extension(&ctx->extensions, oid, oid_len,
158a8e1175bSopenharmony_ci                                      critical, val, val_len);
159a8e1175bSopenharmony_ci}
160a8e1175bSopenharmony_ci
161a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_basic_constraints(mbedtls_x509write_cert *ctx,
162a8e1175bSopenharmony_ci                                                int is_ca, int max_pathlen)
163a8e1175bSopenharmony_ci{
164a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
165a8e1175bSopenharmony_ci    unsigned char buf[9];
166a8e1175bSopenharmony_ci    unsigned char *c = buf + sizeof(buf);
167a8e1175bSopenharmony_ci    size_t len = 0;
168a8e1175bSopenharmony_ci
169a8e1175bSopenharmony_ci    memset(buf, 0, sizeof(buf));
170a8e1175bSopenharmony_ci
171a8e1175bSopenharmony_ci    if (is_ca && max_pathlen > 127) {
172a8e1175bSopenharmony_ci        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
173a8e1175bSopenharmony_ci    }
174a8e1175bSopenharmony_ci
175a8e1175bSopenharmony_ci    if (is_ca) {
176a8e1175bSopenharmony_ci        if (max_pathlen >= 0) {
177a8e1175bSopenharmony_ci            MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf,
178a8e1175bSopenharmony_ci                                                             max_pathlen));
179a8e1175bSopenharmony_ci        }
180a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_bool(&c, buf, 1));
181a8e1175bSopenharmony_ci    }
182a8e1175bSopenharmony_ci
183a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
184a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf,
185a8e1175bSopenharmony_ci                                                     MBEDTLS_ASN1_CONSTRUCTED |
186a8e1175bSopenharmony_ci                                                     MBEDTLS_ASN1_SEQUENCE));
187a8e1175bSopenharmony_ci
188a8e1175bSopenharmony_ci    return
189a8e1175bSopenharmony_ci        mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_BASIC_CONSTRAINTS,
190a8e1175bSopenharmony_ci                                            MBEDTLS_OID_SIZE(MBEDTLS_OID_BASIC_CONSTRAINTS),
191a8e1175bSopenharmony_ci                                            is_ca, buf + sizeof(buf) - len, len);
192a8e1175bSopenharmony_ci}
193a8e1175bSopenharmony_ci
194a8e1175bSopenharmony_ci#if defined(MBEDTLS_MD_CAN_SHA1)
195a8e1175bSopenharmony_cistatic int mbedtls_x509write_crt_set_key_identifier(mbedtls_x509write_cert *ctx,
196a8e1175bSopenharmony_ci                                                    int is_ca,
197a8e1175bSopenharmony_ci                                                    unsigned char tag)
198a8e1175bSopenharmony_ci{
199a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
200a8e1175bSopenharmony_ci    unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */
201a8e1175bSopenharmony_ci    unsigned char *c = buf + sizeof(buf);
202a8e1175bSopenharmony_ci    size_t len = 0;
203a8e1175bSopenharmony_ci#if defined(MBEDTLS_USE_PSA_CRYPTO)
204a8e1175bSopenharmony_ci    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
205a8e1175bSopenharmony_ci    size_t hash_length;
206a8e1175bSopenharmony_ci#endif /* MBEDTLS_USE_PSA_CRYPTO */
207a8e1175bSopenharmony_ci
208a8e1175bSopenharmony_ci    memset(buf, 0, sizeof(buf));
209a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len,
210a8e1175bSopenharmony_ci                         mbedtls_pk_write_pubkey(&c,
211a8e1175bSopenharmony_ci                                                 buf,
212a8e1175bSopenharmony_ci                                                 is_ca ?
213a8e1175bSopenharmony_ci                                                 ctx->issuer_key :
214a8e1175bSopenharmony_ci                                                 ctx->subject_key));
215a8e1175bSopenharmony_ci
216a8e1175bSopenharmony_ci
217a8e1175bSopenharmony_ci#if defined(MBEDTLS_USE_PSA_CRYPTO)
218a8e1175bSopenharmony_ci    status = psa_hash_compute(PSA_ALG_SHA_1,
219a8e1175bSopenharmony_ci                              buf + sizeof(buf) - len,
220a8e1175bSopenharmony_ci                              len,
221a8e1175bSopenharmony_ci                              buf + sizeof(buf) - 20,
222a8e1175bSopenharmony_ci                              20,
223a8e1175bSopenharmony_ci                              &hash_length);
224a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
225a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
226a8e1175bSopenharmony_ci    }
227a8e1175bSopenharmony_ci#else
228a8e1175bSopenharmony_ci    ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1),
229a8e1175bSopenharmony_ci                     buf + sizeof(buf) - len, len,
230a8e1175bSopenharmony_ci                     buf + sizeof(buf) - 20);
231a8e1175bSopenharmony_ci    if (ret != 0) {
232a8e1175bSopenharmony_ci        return ret;
233a8e1175bSopenharmony_ci    }
234a8e1175bSopenharmony_ci#endif /* MBEDTLS_USE_PSA_CRYPTO */
235a8e1175bSopenharmony_ci
236a8e1175bSopenharmony_ci    c = buf + sizeof(buf) - 20;
237a8e1175bSopenharmony_ci    len = 20;
238a8e1175bSopenharmony_ci
239a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
240a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, tag));
241a8e1175bSopenharmony_ci
242a8e1175bSopenharmony_ci    if (is_ca) { // writes AuthorityKeyIdentifier sequence
243a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
244a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len,
245a8e1175bSopenharmony_ci                             mbedtls_asn1_write_tag(&c,
246a8e1175bSopenharmony_ci                                                    buf,
247a8e1175bSopenharmony_ci                                                    MBEDTLS_ASN1_CONSTRUCTED |
248a8e1175bSopenharmony_ci                                                    MBEDTLS_ASN1_SEQUENCE));
249a8e1175bSopenharmony_ci    }
250a8e1175bSopenharmony_ci
251a8e1175bSopenharmony_ci    if (is_ca) {
252a8e1175bSopenharmony_ci        return mbedtls_x509write_crt_set_extension(ctx,
253a8e1175bSopenharmony_ci                                                   MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
254a8e1175bSopenharmony_ci                                                   MBEDTLS_OID_SIZE(
255a8e1175bSopenharmony_ci                                                       MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER),
256a8e1175bSopenharmony_ci                                                   0, buf + sizeof(buf) - len, len);
257a8e1175bSopenharmony_ci    } else {
258a8e1175bSopenharmony_ci        return mbedtls_x509write_crt_set_extension(ctx,
259a8e1175bSopenharmony_ci                                                   MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,
260a8e1175bSopenharmony_ci                                                   MBEDTLS_OID_SIZE(
261a8e1175bSopenharmony_ci                                                       MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER),
262a8e1175bSopenharmony_ci                                                   0, buf + sizeof(buf) - len, len);
263a8e1175bSopenharmony_ci    }
264a8e1175bSopenharmony_ci}
265a8e1175bSopenharmony_ci
266a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert *ctx)
267a8e1175bSopenharmony_ci{
268a8e1175bSopenharmony_ci    return mbedtls_x509write_crt_set_key_identifier(ctx,
269a8e1175bSopenharmony_ci                                                    0,
270a8e1175bSopenharmony_ci                                                    MBEDTLS_ASN1_OCTET_STRING);
271a8e1175bSopenharmony_ci}
272a8e1175bSopenharmony_ci
273a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *ctx)
274a8e1175bSopenharmony_ci{
275a8e1175bSopenharmony_ci    return mbedtls_x509write_crt_set_key_identifier(ctx,
276a8e1175bSopenharmony_ci                                                    1,
277a8e1175bSopenharmony_ci                                                    (MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0));
278a8e1175bSopenharmony_ci}
279a8e1175bSopenharmony_ci#endif /* MBEDTLS_MD_CAN_SHA1 */
280a8e1175bSopenharmony_ci
281a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_key_usage(mbedtls_x509write_cert *ctx,
282a8e1175bSopenharmony_ci                                        unsigned int key_usage)
283a8e1175bSopenharmony_ci{
284a8e1175bSopenharmony_ci    unsigned char buf[5] = { 0 }, ku[2] = { 0 };
285a8e1175bSopenharmony_ci    unsigned char *c;
286a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
287a8e1175bSopenharmony_ci    const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
288a8e1175bSopenharmony_ci                                      MBEDTLS_X509_KU_NON_REPUDIATION   |
289a8e1175bSopenharmony_ci                                      MBEDTLS_X509_KU_KEY_ENCIPHERMENT  |
290a8e1175bSopenharmony_ci                                      MBEDTLS_X509_KU_DATA_ENCIPHERMENT |
291a8e1175bSopenharmony_ci                                      MBEDTLS_X509_KU_KEY_AGREEMENT     |
292a8e1175bSopenharmony_ci                                      MBEDTLS_X509_KU_KEY_CERT_SIGN     |
293a8e1175bSopenharmony_ci                                      MBEDTLS_X509_KU_CRL_SIGN          |
294a8e1175bSopenharmony_ci                                      MBEDTLS_X509_KU_ENCIPHER_ONLY     |
295a8e1175bSopenharmony_ci                                      MBEDTLS_X509_KU_DECIPHER_ONLY;
296a8e1175bSopenharmony_ci
297a8e1175bSopenharmony_ci    /* Check that nothing other than the allowed flags is set */
298a8e1175bSopenharmony_ci    if ((key_usage & ~allowed_bits) != 0) {
299a8e1175bSopenharmony_ci        return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
300a8e1175bSopenharmony_ci    }
301a8e1175bSopenharmony_ci
302a8e1175bSopenharmony_ci    c = buf + 5;
303a8e1175bSopenharmony_ci    MBEDTLS_PUT_UINT16_LE(key_usage, ku, 0);
304a8e1175bSopenharmony_ci    ret = mbedtls_asn1_write_named_bitstring(&c, buf, ku, 9);
305a8e1175bSopenharmony_ci
306a8e1175bSopenharmony_ci    if (ret < 0) {
307a8e1175bSopenharmony_ci        return ret;
308a8e1175bSopenharmony_ci    } else if (ret < 3 || ret > 5) {
309a8e1175bSopenharmony_ci        return MBEDTLS_ERR_X509_INVALID_FORMAT;
310a8e1175bSopenharmony_ci    }
311a8e1175bSopenharmony_ci
312a8e1175bSopenharmony_ci    ret = mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_KEY_USAGE,
313a8e1175bSopenharmony_ci                                              MBEDTLS_OID_SIZE(MBEDTLS_OID_KEY_USAGE),
314a8e1175bSopenharmony_ci                                              1, c, (size_t) ret);
315a8e1175bSopenharmony_ci    if (ret != 0) {
316a8e1175bSopenharmony_ci        return ret;
317a8e1175bSopenharmony_ci    }
318a8e1175bSopenharmony_ci
319a8e1175bSopenharmony_ci    return 0;
320a8e1175bSopenharmony_ci}
321a8e1175bSopenharmony_ci
322a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_ext_key_usage(mbedtls_x509write_cert *ctx,
323a8e1175bSopenharmony_ci                                            const mbedtls_asn1_sequence *exts)
324a8e1175bSopenharmony_ci{
325a8e1175bSopenharmony_ci    unsigned char buf[256];
326a8e1175bSopenharmony_ci    unsigned char *c = buf + sizeof(buf);
327a8e1175bSopenharmony_ci    int ret;
328a8e1175bSopenharmony_ci    size_t len = 0;
329a8e1175bSopenharmony_ci    const mbedtls_asn1_sequence *last_ext = NULL;
330a8e1175bSopenharmony_ci    const mbedtls_asn1_sequence *ext;
331a8e1175bSopenharmony_ci
332a8e1175bSopenharmony_ci    memset(buf, 0, sizeof(buf));
333a8e1175bSopenharmony_ci
334a8e1175bSopenharmony_ci    /* We need at least one extension: SEQUENCE SIZE (1..MAX) OF KeyPurposeId */
335a8e1175bSopenharmony_ci    if (exts == NULL) {
336a8e1175bSopenharmony_ci        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
337a8e1175bSopenharmony_ci    }
338a8e1175bSopenharmony_ci
339a8e1175bSopenharmony_ci    /* Iterate over exts backwards, so we write them out in the requested order */
340a8e1175bSopenharmony_ci    while (last_ext != exts) {
341a8e1175bSopenharmony_ci        for (ext = exts; ext->next != last_ext; ext = ext->next) {
342a8e1175bSopenharmony_ci        }
343a8e1175bSopenharmony_ci        if (ext->buf.tag != MBEDTLS_ASN1_OID) {
344a8e1175bSopenharmony_ci            return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
345a8e1175bSopenharmony_ci        }
346a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf, ext->buf.p, ext->buf.len));
347a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, ext->buf.len));
348a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_OID));
349a8e1175bSopenharmony_ci        last_ext = ext;
350a8e1175bSopenharmony_ci    }
351a8e1175bSopenharmony_ci
352a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
353a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len,
354a8e1175bSopenharmony_ci                         mbedtls_asn1_write_tag(&c, buf,
355a8e1175bSopenharmony_ci                                                MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
356a8e1175bSopenharmony_ci
357a8e1175bSopenharmony_ci    return mbedtls_x509write_crt_set_extension(ctx,
358a8e1175bSopenharmony_ci                                               MBEDTLS_OID_EXTENDED_KEY_USAGE,
359a8e1175bSopenharmony_ci                                               MBEDTLS_OID_SIZE(MBEDTLS_OID_EXTENDED_KEY_USAGE),
360a8e1175bSopenharmony_ci                                               1, c, len);
361a8e1175bSopenharmony_ci}
362a8e1175bSopenharmony_ci
363a8e1175bSopenharmony_ciint mbedtls_x509write_crt_set_ns_cert_type(mbedtls_x509write_cert *ctx,
364a8e1175bSopenharmony_ci                                           unsigned char ns_cert_type)
365a8e1175bSopenharmony_ci{
366a8e1175bSopenharmony_ci    unsigned char buf[4] = { 0 };
367a8e1175bSopenharmony_ci    unsigned char *c;
368a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
369a8e1175bSopenharmony_ci
370a8e1175bSopenharmony_ci    c = buf + 4;
371a8e1175bSopenharmony_ci
372a8e1175bSopenharmony_ci    ret = mbedtls_asn1_write_named_bitstring(&c, buf, &ns_cert_type, 8);
373a8e1175bSopenharmony_ci    if (ret < 3 || ret > 4) {
374a8e1175bSopenharmony_ci        return ret;
375a8e1175bSopenharmony_ci    }
376a8e1175bSopenharmony_ci
377a8e1175bSopenharmony_ci    ret = mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_NS_CERT_TYPE,
378a8e1175bSopenharmony_ci                                              MBEDTLS_OID_SIZE(MBEDTLS_OID_NS_CERT_TYPE),
379a8e1175bSopenharmony_ci                                              0, c, (size_t) ret);
380a8e1175bSopenharmony_ci    if (ret != 0) {
381a8e1175bSopenharmony_ci        return ret;
382a8e1175bSopenharmony_ci    }
383a8e1175bSopenharmony_ci
384a8e1175bSopenharmony_ci    return 0;
385a8e1175bSopenharmony_ci}
386a8e1175bSopenharmony_ci
387a8e1175bSopenharmony_cistatic int x509_write_time(unsigned char **p, unsigned char *start,
388a8e1175bSopenharmony_ci                           const char *t, size_t size)
389a8e1175bSopenharmony_ci{
390a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
391a8e1175bSopenharmony_ci    size_t len = 0;
392a8e1175bSopenharmony_ci
393a8e1175bSopenharmony_ci    /*
394a8e1175bSopenharmony_ci     * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
395a8e1175bSopenharmony_ci     */
396a8e1175bSopenharmony_ci    if (t[0] < '2' || (t[0] == '2' && t[1] == '0' && t[2] < '5')) {
397a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
398a8e1175bSopenharmony_ci                                                                (const unsigned char *) t + 2,
399a8e1175bSopenharmony_ci                                                                size - 2));
400a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
401a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
402a8e1175bSopenharmony_ci                                                         MBEDTLS_ASN1_UTC_TIME));
403a8e1175bSopenharmony_ci    } else {
404a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
405a8e1175bSopenharmony_ci                                                                (const unsigned char *) t,
406a8e1175bSopenharmony_ci                                                                size));
407a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
408a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
409a8e1175bSopenharmony_ci                                                         MBEDTLS_ASN1_GENERALIZED_TIME));
410a8e1175bSopenharmony_ci    }
411a8e1175bSopenharmony_ci
412a8e1175bSopenharmony_ci    return (int) len;
413a8e1175bSopenharmony_ci}
414a8e1175bSopenharmony_ci
415a8e1175bSopenharmony_ciint mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx,
416a8e1175bSopenharmony_ci                              unsigned char *buf, size_t size,
417a8e1175bSopenharmony_ci                              int (*f_rng)(void *, unsigned char *, size_t),
418a8e1175bSopenharmony_ci                              void *p_rng)
419a8e1175bSopenharmony_ci{
420a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
421a8e1175bSopenharmony_ci    const char *sig_oid;
422a8e1175bSopenharmony_ci    size_t sig_oid_len = 0;
423a8e1175bSopenharmony_ci    unsigned char *c, *c2;
424a8e1175bSopenharmony_ci    unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE];
425a8e1175bSopenharmony_ci    size_t hash_length = 0;
426a8e1175bSopenharmony_ci    unsigned char hash[MBEDTLS_MD_MAX_SIZE];
427a8e1175bSopenharmony_ci#if defined(MBEDTLS_USE_PSA_CRYPTO)
428a8e1175bSopenharmony_ci    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
429a8e1175bSopenharmony_ci    psa_algorithm_t psa_algorithm;
430a8e1175bSopenharmony_ci#endif /* MBEDTLS_USE_PSA_CRYPTO */
431a8e1175bSopenharmony_ci
432a8e1175bSopenharmony_ci    size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
433a8e1175bSopenharmony_ci    size_t len = 0;
434a8e1175bSopenharmony_ci    mbedtls_pk_type_t pk_alg;
435a8e1175bSopenharmony_ci    int write_sig_null_par;
436a8e1175bSopenharmony_ci
437a8e1175bSopenharmony_ci    /*
438a8e1175bSopenharmony_ci     * Prepare data to be signed at the end of the target buffer
439a8e1175bSopenharmony_ci     */
440a8e1175bSopenharmony_ci    c = buf + size;
441a8e1175bSopenharmony_ci
442a8e1175bSopenharmony_ci    /* Signature algorithm needed in TBS, and later for actual signature */
443a8e1175bSopenharmony_ci
444a8e1175bSopenharmony_ci    /* There's no direct way of extracting a signature algorithm
445a8e1175bSopenharmony_ci     * (represented as an element of mbedtls_pk_type_t) from a PK instance. */
446a8e1175bSopenharmony_ci    if (mbedtls_pk_can_do(ctx->issuer_key, MBEDTLS_PK_RSA)) {
447a8e1175bSopenharmony_ci        pk_alg = MBEDTLS_PK_RSA;
448a8e1175bSopenharmony_ci    } else if (mbedtls_pk_can_do(ctx->issuer_key, MBEDTLS_PK_ECDSA)) {
449a8e1175bSopenharmony_ci        pk_alg = MBEDTLS_PK_ECDSA;
450a8e1175bSopenharmony_ci    } else {
451a8e1175bSopenharmony_ci        return MBEDTLS_ERR_X509_INVALID_ALG;
452a8e1175bSopenharmony_ci    }
453a8e1175bSopenharmony_ci
454a8e1175bSopenharmony_ci    if ((ret = mbedtls_oid_get_oid_by_sig_alg(pk_alg, ctx->md_alg,
455a8e1175bSopenharmony_ci                                              &sig_oid, &sig_oid_len)) != 0) {
456a8e1175bSopenharmony_ci        return ret;
457a8e1175bSopenharmony_ci    }
458a8e1175bSopenharmony_ci
459a8e1175bSopenharmony_ci    /*
460a8e1175bSopenharmony_ci     *  Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
461a8e1175bSopenharmony_ci     */
462a8e1175bSopenharmony_ci
463a8e1175bSopenharmony_ci    /* Only for v3 */
464a8e1175bSopenharmony_ci    if (ctx->version == MBEDTLS_X509_CRT_VERSION_3) {
465a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len,
466a8e1175bSopenharmony_ci                             mbedtls_x509_write_extensions(&c,
467a8e1175bSopenharmony_ci                                                           buf, ctx->extensions));
468a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
469a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len,
470a8e1175bSopenharmony_ci                             mbedtls_asn1_write_tag(&c, buf,
471a8e1175bSopenharmony_ci                                                    MBEDTLS_ASN1_CONSTRUCTED |
472a8e1175bSopenharmony_ci                                                    MBEDTLS_ASN1_SEQUENCE));
473a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
474a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len,
475a8e1175bSopenharmony_ci                             mbedtls_asn1_write_tag(&c, buf,
476a8e1175bSopenharmony_ci                                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC |
477a8e1175bSopenharmony_ci                                                    MBEDTLS_ASN1_CONSTRUCTED | 3));
478a8e1175bSopenharmony_ci    }
479a8e1175bSopenharmony_ci
480a8e1175bSopenharmony_ci    /*
481a8e1175bSopenharmony_ci     *  SubjectPublicKeyInfo
482a8e1175bSopenharmony_ci     */
483a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(pub_len,
484a8e1175bSopenharmony_ci                         mbedtls_pk_write_pubkey_der(ctx->subject_key,
485a8e1175bSopenharmony_ci                                                     buf, (size_t) (c - buf)));
486a8e1175bSopenharmony_ci    c -= pub_len;
487a8e1175bSopenharmony_ci    len += pub_len;
488a8e1175bSopenharmony_ci
489a8e1175bSopenharmony_ci    /*
490a8e1175bSopenharmony_ci     *  Subject  ::=  Name
491a8e1175bSopenharmony_ci     */
492a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len,
493a8e1175bSopenharmony_ci                         mbedtls_x509_write_names(&c, buf,
494a8e1175bSopenharmony_ci                                                  ctx->subject));
495a8e1175bSopenharmony_ci
496a8e1175bSopenharmony_ci    /*
497a8e1175bSopenharmony_ci     *  Validity ::= SEQUENCE {
498a8e1175bSopenharmony_ci     *       notBefore      Time,
499a8e1175bSopenharmony_ci     *       notAfter       Time }
500a8e1175bSopenharmony_ci     */
501a8e1175bSopenharmony_ci    sub_len = 0;
502a8e1175bSopenharmony_ci
503a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(sub_len,
504a8e1175bSopenharmony_ci                         x509_write_time(&c, buf, ctx->not_after,
505a8e1175bSopenharmony_ci                                         MBEDTLS_X509_RFC5280_UTC_TIME_LEN));
506a8e1175bSopenharmony_ci
507a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(sub_len,
508a8e1175bSopenharmony_ci                         x509_write_time(&c, buf, ctx->not_before,
509a8e1175bSopenharmony_ci                                         MBEDTLS_X509_RFC5280_UTC_TIME_LEN));
510a8e1175bSopenharmony_ci
511a8e1175bSopenharmony_ci    len += sub_len;
512a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, sub_len));
513a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len,
514a8e1175bSopenharmony_ci                         mbedtls_asn1_write_tag(&c, buf,
515a8e1175bSopenharmony_ci                                                MBEDTLS_ASN1_CONSTRUCTED |
516a8e1175bSopenharmony_ci                                                MBEDTLS_ASN1_SEQUENCE));
517a8e1175bSopenharmony_ci
518a8e1175bSopenharmony_ci    /*
519a8e1175bSopenharmony_ci     *  Issuer  ::=  Name
520a8e1175bSopenharmony_ci     */
521a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_x509_write_names(&c, buf,
522a8e1175bSopenharmony_ci                                                       ctx->issuer));
523a8e1175bSopenharmony_ci
524a8e1175bSopenharmony_ci    /*
525a8e1175bSopenharmony_ci     *  Signature   ::=  AlgorithmIdentifier
526a8e1175bSopenharmony_ci     */
527a8e1175bSopenharmony_ci    if (pk_alg == MBEDTLS_PK_ECDSA) {
528a8e1175bSopenharmony_ci        /*
529a8e1175bSopenharmony_ci         * The AlgorithmIdentifier's parameters field must be absent for DSA/ECDSA signature
530a8e1175bSopenharmony_ci         * algorithms, see https://www.rfc-editor.org/rfc/rfc5480#page-17 and
531a8e1175bSopenharmony_ci         * https://www.rfc-editor.org/rfc/rfc5758#section-3.
532a8e1175bSopenharmony_ci         */
533a8e1175bSopenharmony_ci        write_sig_null_par = 0;
534a8e1175bSopenharmony_ci    } else {
535a8e1175bSopenharmony_ci        write_sig_null_par = 1;
536a8e1175bSopenharmony_ci    }
537a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len,
538a8e1175bSopenharmony_ci                         mbedtls_asn1_write_algorithm_identifier_ext(&c, buf,
539a8e1175bSopenharmony_ci                                                                     sig_oid, strlen(sig_oid),
540a8e1175bSopenharmony_ci                                                                     0, write_sig_null_par));
541a8e1175bSopenharmony_ci
542a8e1175bSopenharmony_ci    /*
543a8e1175bSopenharmony_ci     *  Serial   ::=  INTEGER
544a8e1175bSopenharmony_ci     *
545a8e1175bSopenharmony_ci     * Written data is:
546a8e1175bSopenharmony_ci     * - "ctx->serial_len" bytes for the raw serial buffer
547a8e1175bSopenharmony_ci     *   - if MSb of "serial" is 1, then prepend an extra 0x00 byte
548a8e1175bSopenharmony_ci     * - 1 byte for the length
549a8e1175bSopenharmony_ci     * - 1 byte for the TAG
550a8e1175bSopenharmony_ci     */
551a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf,
552a8e1175bSopenharmony_ci                                                            ctx->serial, ctx->serial_len));
553a8e1175bSopenharmony_ci    if (*c & 0x80) {
554a8e1175bSopenharmony_ci        if (c - buf < 1) {
555a8e1175bSopenharmony_ci            return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
556a8e1175bSopenharmony_ci        }
557a8e1175bSopenharmony_ci        *(--c) = 0x0;
558a8e1175bSopenharmony_ci        len++;
559a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf,
560a8e1175bSopenharmony_ci                                                         ctx->serial_len + 1));
561a8e1175bSopenharmony_ci    } else {
562a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf,
563a8e1175bSopenharmony_ci                                                         ctx->serial_len));
564a8e1175bSopenharmony_ci    }
565a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf,
566a8e1175bSopenharmony_ci                                                     MBEDTLS_ASN1_INTEGER));
567a8e1175bSopenharmony_ci
568a8e1175bSopenharmony_ci    /*
569a8e1175bSopenharmony_ci     *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
570a8e1175bSopenharmony_ci     */
571a8e1175bSopenharmony_ci
572a8e1175bSopenharmony_ci    /* Can be omitted for v1 */
573a8e1175bSopenharmony_ci    if (ctx->version != MBEDTLS_X509_CRT_VERSION_1) {
574a8e1175bSopenharmony_ci        sub_len = 0;
575a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(sub_len,
576a8e1175bSopenharmony_ci                             mbedtls_asn1_write_int(&c, buf, ctx->version));
577a8e1175bSopenharmony_ci        len += sub_len;
578a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len,
579a8e1175bSopenharmony_ci                             mbedtls_asn1_write_len(&c, buf, sub_len));
580a8e1175bSopenharmony_ci        MBEDTLS_ASN1_CHK_ADD(len,
581a8e1175bSopenharmony_ci                             mbedtls_asn1_write_tag(&c, buf,
582a8e1175bSopenharmony_ci                                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC |
583a8e1175bSopenharmony_ci                                                    MBEDTLS_ASN1_CONSTRUCTED | 0));
584a8e1175bSopenharmony_ci    }
585a8e1175bSopenharmony_ci
586a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
587a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len,
588a8e1175bSopenharmony_ci                         mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
589a8e1175bSopenharmony_ci                                                MBEDTLS_ASN1_SEQUENCE));
590a8e1175bSopenharmony_ci
591a8e1175bSopenharmony_ci    /*
592a8e1175bSopenharmony_ci     * Make signature
593a8e1175bSopenharmony_ci     */
594a8e1175bSopenharmony_ci
595a8e1175bSopenharmony_ci    /* Compute hash of CRT. */
596a8e1175bSopenharmony_ci#if defined(MBEDTLS_USE_PSA_CRYPTO)
597a8e1175bSopenharmony_ci    psa_algorithm = mbedtls_md_psa_alg_from_type(ctx->md_alg);
598a8e1175bSopenharmony_ci
599a8e1175bSopenharmony_ci    status = psa_hash_compute(psa_algorithm,
600a8e1175bSopenharmony_ci                              c,
601a8e1175bSopenharmony_ci                              len,
602a8e1175bSopenharmony_ci                              hash,
603a8e1175bSopenharmony_ci                              sizeof(hash),
604a8e1175bSopenharmony_ci                              &hash_length);
605a8e1175bSopenharmony_ci    if (status != PSA_SUCCESS) {
606a8e1175bSopenharmony_ci        return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
607a8e1175bSopenharmony_ci    }
608a8e1175bSopenharmony_ci#else
609a8e1175bSopenharmony_ci    if ((ret = mbedtls_md(mbedtls_md_info_from_type(ctx->md_alg), c,
610a8e1175bSopenharmony_ci                          len, hash)) != 0) {
611a8e1175bSopenharmony_ci        return ret;
612a8e1175bSopenharmony_ci    }
613a8e1175bSopenharmony_ci#endif /* MBEDTLS_USE_PSA_CRYPTO */
614a8e1175bSopenharmony_ci
615a8e1175bSopenharmony_ci
616a8e1175bSopenharmony_ci    if ((ret = mbedtls_pk_sign(ctx->issuer_key, ctx->md_alg,
617a8e1175bSopenharmony_ci                               hash, hash_length, sig, sizeof(sig), &sig_len,
618a8e1175bSopenharmony_ci                               f_rng, p_rng)) != 0) {
619a8e1175bSopenharmony_ci        return ret;
620a8e1175bSopenharmony_ci    }
621a8e1175bSopenharmony_ci
622a8e1175bSopenharmony_ci    /* Move CRT to the front of the buffer to have space
623a8e1175bSopenharmony_ci     * for the signature. */
624a8e1175bSopenharmony_ci    memmove(buf, c, len);
625a8e1175bSopenharmony_ci    c = buf + len;
626a8e1175bSopenharmony_ci
627a8e1175bSopenharmony_ci    /* Add signature at the end of the buffer,
628a8e1175bSopenharmony_ci     * making sure that it doesn't underflow
629a8e1175bSopenharmony_ci     * into the CRT buffer. */
630a8e1175bSopenharmony_ci    c2 = buf + size;
631a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len, mbedtls_x509_write_sig(&c2, c,
632a8e1175bSopenharmony_ci                                                                 sig_oid, sig_oid_len,
633a8e1175bSopenharmony_ci                                                                 sig, sig_len, pk_alg));
634a8e1175bSopenharmony_ci
635a8e1175bSopenharmony_ci    /*
636a8e1175bSopenharmony_ci     * Memory layout after this step:
637a8e1175bSopenharmony_ci     *
638a8e1175bSopenharmony_ci     * buf       c=buf+len                c2            buf+size
639a8e1175bSopenharmony_ci     * [CRT0,...,CRTn, UNUSED, ..., UNUSED, SIG0, ..., SIGm]
640a8e1175bSopenharmony_ci     */
641a8e1175bSopenharmony_ci
642a8e1175bSopenharmony_ci    /* Move raw CRT to just before the signature. */
643a8e1175bSopenharmony_ci    c = c2 - len;
644a8e1175bSopenharmony_ci    memmove(c, buf, len);
645a8e1175bSopenharmony_ci
646a8e1175bSopenharmony_ci    len += sig_and_oid_len;
647a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
648a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf,
649a8e1175bSopenharmony_ci                                                     MBEDTLS_ASN1_CONSTRUCTED |
650a8e1175bSopenharmony_ci                                                     MBEDTLS_ASN1_SEQUENCE));
651a8e1175bSopenharmony_ci
652a8e1175bSopenharmony_ci    return (int) len;
653a8e1175bSopenharmony_ci}
654a8e1175bSopenharmony_ci
655a8e1175bSopenharmony_ci#define PEM_BEGIN_CRT           "-----BEGIN CERTIFICATE-----\n"
656a8e1175bSopenharmony_ci#define PEM_END_CRT             "-----END CERTIFICATE-----\n"
657a8e1175bSopenharmony_ci
658a8e1175bSopenharmony_ci#if defined(MBEDTLS_PEM_WRITE_C)
659a8e1175bSopenharmony_ciint mbedtls_x509write_crt_pem(mbedtls_x509write_cert *crt,
660a8e1175bSopenharmony_ci                              unsigned char *buf, size_t size,
661a8e1175bSopenharmony_ci                              int (*f_rng)(void *, unsigned char *, size_t),
662a8e1175bSopenharmony_ci                              void *p_rng)
663a8e1175bSopenharmony_ci{
664a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
665a8e1175bSopenharmony_ci    size_t olen;
666a8e1175bSopenharmony_ci
667a8e1175bSopenharmony_ci    if ((ret = mbedtls_x509write_crt_der(crt, buf, size,
668a8e1175bSopenharmony_ci                                         f_rng, p_rng)) < 0) {
669a8e1175bSopenharmony_ci        return ret;
670a8e1175bSopenharmony_ci    }
671a8e1175bSopenharmony_ci
672a8e1175bSopenharmony_ci    if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_CRT, PEM_END_CRT,
673a8e1175bSopenharmony_ci                                        buf + size - ret, ret,
674a8e1175bSopenharmony_ci                                        buf, size, &olen)) != 0) {
675a8e1175bSopenharmony_ci        return ret;
676a8e1175bSopenharmony_ci    }
677a8e1175bSopenharmony_ci
678a8e1175bSopenharmony_ci    return 0;
679a8e1175bSopenharmony_ci}
680a8e1175bSopenharmony_ci#endif /* MBEDTLS_PEM_WRITE_C */
681a8e1175bSopenharmony_ci
682a8e1175bSopenharmony_ci#endif /* MBEDTLS_X509_CRT_WRITE_C */
683