1a8e1175bSopenharmony_ci/*
2a8e1175bSopenharmony_ci * ASN.1 buffer writing functionality
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#include "common.h"
9a8e1175bSopenharmony_ci
10a8e1175bSopenharmony_ci#if defined(MBEDTLS_ASN1_WRITE_C) || defined(MBEDTLS_X509_USE_C) || \
11a8e1175bSopenharmony_ci    defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
12a8e1175bSopenharmony_ci
13a8e1175bSopenharmony_ci#include "mbedtls/asn1write.h"
14a8e1175bSopenharmony_ci#include "mbedtls/error.h"
15a8e1175bSopenharmony_ci
16a8e1175bSopenharmony_ci#include <string.h>
17a8e1175bSopenharmony_ci
18a8e1175bSopenharmony_ci#include "mbedtls/platform.h"
19a8e1175bSopenharmony_ci
20a8e1175bSopenharmony_ci#if defined(MBEDTLS_ASN1_PARSE_C)
21a8e1175bSopenharmony_ci#include "mbedtls/asn1.h"
22a8e1175bSopenharmony_ci#endif
23a8e1175bSopenharmony_ci
24a8e1175bSopenharmony_ciint mbedtls_asn1_write_len(unsigned char **p, const unsigned char *start, size_t len)
25a8e1175bSopenharmony_ci{
26a8e1175bSopenharmony_ci#if SIZE_MAX > 0xFFFFFFFF
27a8e1175bSopenharmony_ci    if (len > 0xFFFFFFFF) {
28a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
29a8e1175bSopenharmony_ci    }
30a8e1175bSopenharmony_ci#endif
31a8e1175bSopenharmony_ci
32a8e1175bSopenharmony_ci    int required = 1;
33a8e1175bSopenharmony_ci
34a8e1175bSopenharmony_ci    if (len >= 0x80) {
35a8e1175bSopenharmony_ci        for (size_t l = len; l != 0; l >>= 8) {
36a8e1175bSopenharmony_ci            required++;
37a8e1175bSopenharmony_ci        }
38a8e1175bSopenharmony_ci    }
39a8e1175bSopenharmony_ci
40a8e1175bSopenharmony_ci    if (required > (*p - start)) {
41a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
42a8e1175bSopenharmony_ci    }
43a8e1175bSopenharmony_ci
44a8e1175bSopenharmony_ci    do {
45a8e1175bSopenharmony_ci        *--(*p) = MBEDTLS_BYTE_0(len);
46a8e1175bSopenharmony_ci        len >>= 8;
47a8e1175bSopenharmony_ci    } while (len);
48a8e1175bSopenharmony_ci
49a8e1175bSopenharmony_ci    if (required > 1) {
50a8e1175bSopenharmony_ci        *--(*p) = (unsigned char) (0x80 + required - 1);
51a8e1175bSopenharmony_ci    }
52a8e1175bSopenharmony_ci
53a8e1175bSopenharmony_ci    return required;
54a8e1175bSopenharmony_ci}
55a8e1175bSopenharmony_ci
56a8e1175bSopenharmony_ciint mbedtls_asn1_write_tag(unsigned char **p, const unsigned char *start, unsigned char tag)
57a8e1175bSopenharmony_ci{
58a8e1175bSopenharmony_ci    if (*p - start < 1) {
59a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
60a8e1175bSopenharmony_ci    }
61a8e1175bSopenharmony_ci
62a8e1175bSopenharmony_ci    *--(*p) = tag;
63a8e1175bSopenharmony_ci
64a8e1175bSopenharmony_ci    return 1;
65a8e1175bSopenharmony_ci}
66a8e1175bSopenharmony_ci#endif /* MBEDTLS_ASN1_WRITE_C || MBEDTLS_X509_USE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */
67a8e1175bSopenharmony_ci
68a8e1175bSopenharmony_ci#if defined(MBEDTLS_ASN1_WRITE_C)
69a8e1175bSopenharmony_cistatic int mbedtls_asn1_write_len_and_tag(unsigned char **p,
70a8e1175bSopenharmony_ci                                          const unsigned char *start,
71a8e1175bSopenharmony_ci                                          size_t len,
72a8e1175bSopenharmony_ci                                          unsigned char tag)
73a8e1175bSopenharmony_ci{
74a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
75a8e1175bSopenharmony_ci
76a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
77a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag));
78a8e1175bSopenharmony_ci
79a8e1175bSopenharmony_ci    return (int) len;
80a8e1175bSopenharmony_ci}
81a8e1175bSopenharmony_ci
82a8e1175bSopenharmony_ciint mbedtls_asn1_write_raw_buffer(unsigned char **p, const unsigned char *start,
83a8e1175bSopenharmony_ci                                  const unsigned char *buf, size_t size)
84a8e1175bSopenharmony_ci{
85a8e1175bSopenharmony_ci    size_t len = 0;
86a8e1175bSopenharmony_ci
87a8e1175bSopenharmony_ci    if (*p < start || (size_t) (*p - start) < size) {
88a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
89a8e1175bSopenharmony_ci    }
90a8e1175bSopenharmony_ci
91a8e1175bSopenharmony_ci    len = size;
92a8e1175bSopenharmony_ci    (*p) -= len;
93a8e1175bSopenharmony_ci    memcpy(*p, buf, len);
94a8e1175bSopenharmony_ci
95a8e1175bSopenharmony_ci    return (int) len;
96a8e1175bSopenharmony_ci}
97a8e1175bSopenharmony_ci
98a8e1175bSopenharmony_ci#if defined(MBEDTLS_BIGNUM_C)
99a8e1175bSopenharmony_ciint mbedtls_asn1_write_mpi(unsigned char **p, const unsigned char *start, const mbedtls_mpi *X)
100a8e1175bSopenharmony_ci{
101a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
102a8e1175bSopenharmony_ci    size_t len = 0;
103a8e1175bSopenharmony_ci
104a8e1175bSopenharmony_ci    // Write the MPI
105a8e1175bSopenharmony_ci    //
106a8e1175bSopenharmony_ci    len = mbedtls_mpi_size(X);
107a8e1175bSopenharmony_ci
108a8e1175bSopenharmony_ci    /* DER represents 0 with a sign bit (0=nonnegative) and 7 value bits, not
109a8e1175bSopenharmony_ci     * as 0 digits. We need to end up with 020100, not with 0200. */
110a8e1175bSopenharmony_ci    if (len == 0) {
111a8e1175bSopenharmony_ci        len = 1;
112a8e1175bSopenharmony_ci    }
113a8e1175bSopenharmony_ci
114a8e1175bSopenharmony_ci    if (*p < start || (size_t) (*p - start) < len) {
115a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
116a8e1175bSopenharmony_ci    }
117a8e1175bSopenharmony_ci
118a8e1175bSopenharmony_ci    (*p) -= len;
119a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(X, *p, len));
120a8e1175bSopenharmony_ci
121a8e1175bSopenharmony_ci    // DER format assumes 2s complement for numbers, so the leftmost bit
122a8e1175bSopenharmony_ci    // should be 0 for positive numbers and 1 for negative numbers.
123a8e1175bSopenharmony_ci    //
124a8e1175bSopenharmony_ci    if (X->s == 1 && **p & 0x80) {
125a8e1175bSopenharmony_ci        if (*p - start < 1) {
126a8e1175bSopenharmony_ci            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
127a8e1175bSopenharmony_ci        }
128a8e1175bSopenharmony_ci
129a8e1175bSopenharmony_ci        *--(*p) = 0x00;
130a8e1175bSopenharmony_ci        len += 1;
131a8e1175bSopenharmony_ci    }
132a8e1175bSopenharmony_ci
133a8e1175bSopenharmony_ci    ret = mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_INTEGER);
134a8e1175bSopenharmony_ci
135a8e1175bSopenharmony_cicleanup:
136a8e1175bSopenharmony_ci    return ret;
137a8e1175bSopenharmony_ci}
138a8e1175bSopenharmony_ci#endif /* MBEDTLS_BIGNUM_C */
139a8e1175bSopenharmony_ci
140a8e1175bSopenharmony_ciint mbedtls_asn1_write_null(unsigned char **p, const unsigned char *start)
141a8e1175bSopenharmony_ci{
142a8e1175bSopenharmony_ci    // Write NULL
143a8e1175bSopenharmony_ci    //
144a8e1175bSopenharmony_ci    return mbedtls_asn1_write_len_and_tag(p, start, 0, MBEDTLS_ASN1_NULL);
145a8e1175bSopenharmony_ci}
146a8e1175bSopenharmony_ci
147a8e1175bSopenharmony_ciint mbedtls_asn1_write_oid(unsigned char **p, const unsigned char *start,
148a8e1175bSopenharmony_ci                           const char *oid, size_t oid_len)
149a8e1175bSopenharmony_ci{
150a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
151a8e1175bSopenharmony_ci    size_t len = 0;
152a8e1175bSopenharmony_ci
153a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
154a8e1175bSopenharmony_ci                                                            (const unsigned char *) oid, oid_len));
155a8e1175bSopenharmony_ci    return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_OID);
156a8e1175bSopenharmony_ci}
157a8e1175bSopenharmony_ci
158a8e1175bSopenharmony_ciint mbedtls_asn1_write_algorithm_identifier(unsigned char **p, const unsigned char *start,
159a8e1175bSopenharmony_ci                                            const char *oid, size_t oid_len,
160a8e1175bSopenharmony_ci                                            size_t par_len)
161a8e1175bSopenharmony_ci{
162a8e1175bSopenharmony_ci    return mbedtls_asn1_write_algorithm_identifier_ext(p, start, oid, oid_len, par_len, 1);
163a8e1175bSopenharmony_ci}
164a8e1175bSopenharmony_ci
165a8e1175bSopenharmony_ciint mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p, const unsigned char *start,
166a8e1175bSopenharmony_ci                                                const char *oid, size_t oid_len,
167a8e1175bSopenharmony_ci                                                size_t par_len, int has_par)
168a8e1175bSopenharmony_ci{
169a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
170a8e1175bSopenharmony_ci    size_t len = 0;
171a8e1175bSopenharmony_ci
172a8e1175bSopenharmony_ci    if (has_par) {
173a8e1175bSopenharmony_ci        if (par_len == 0) {
174a8e1175bSopenharmony_ci            MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_null(p, start));
175a8e1175bSopenharmony_ci        } else {
176a8e1175bSopenharmony_ci            len += par_len;
177a8e1175bSopenharmony_ci        }
178a8e1175bSopenharmony_ci    }
179a8e1175bSopenharmony_ci
180a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
181a8e1175bSopenharmony_ci
182a8e1175bSopenharmony_ci    return mbedtls_asn1_write_len_and_tag(p, start, len,
183a8e1175bSopenharmony_ci                                          MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
184a8e1175bSopenharmony_ci}
185a8e1175bSopenharmony_ci
186a8e1175bSopenharmony_ciint mbedtls_asn1_write_bool(unsigned char **p, const unsigned char *start, int boolean)
187a8e1175bSopenharmony_ci{
188a8e1175bSopenharmony_ci    size_t len = 0;
189a8e1175bSopenharmony_ci
190a8e1175bSopenharmony_ci    if (*p - start < 1) {
191a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
192a8e1175bSopenharmony_ci    }
193a8e1175bSopenharmony_ci
194a8e1175bSopenharmony_ci    *--(*p) = (boolean) ? 255 : 0;
195a8e1175bSopenharmony_ci    len++;
196a8e1175bSopenharmony_ci
197a8e1175bSopenharmony_ci    return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_BOOLEAN);
198a8e1175bSopenharmony_ci}
199a8e1175bSopenharmony_ci
200a8e1175bSopenharmony_cistatic int asn1_write_tagged_int(unsigned char **p, const unsigned char *start, int val, int tag)
201a8e1175bSopenharmony_ci{
202a8e1175bSopenharmony_ci    size_t len = 0;
203a8e1175bSopenharmony_ci
204a8e1175bSopenharmony_ci    do {
205a8e1175bSopenharmony_ci        if (*p - start < 1) {
206a8e1175bSopenharmony_ci            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
207a8e1175bSopenharmony_ci        }
208a8e1175bSopenharmony_ci        len += 1;
209a8e1175bSopenharmony_ci        *--(*p) = val & 0xff;
210a8e1175bSopenharmony_ci        val >>= 8;
211a8e1175bSopenharmony_ci    } while (val > 0);
212a8e1175bSopenharmony_ci
213a8e1175bSopenharmony_ci    if (**p & 0x80) {
214a8e1175bSopenharmony_ci        if (*p - start < 1) {
215a8e1175bSopenharmony_ci            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
216a8e1175bSopenharmony_ci        }
217a8e1175bSopenharmony_ci        *--(*p) = 0x00;
218a8e1175bSopenharmony_ci        len += 1;
219a8e1175bSopenharmony_ci    }
220a8e1175bSopenharmony_ci
221a8e1175bSopenharmony_ci    return mbedtls_asn1_write_len_and_tag(p, start, len, tag);
222a8e1175bSopenharmony_ci}
223a8e1175bSopenharmony_ci
224a8e1175bSopenharmony_ciint mbedtls_asn1_write_int(unsigned char **p, const unsigned char *start, int val)
225a8e1175bSopenharmony_ci{
226a8e1175bSopenharmony_ci    return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_INTEGER);
227a8e1175bSopenharmony_ci}
228a8e1175bSopenharmony_ci
229a8e1175bSopenharmony_ciint mbedtls_asn1_write_enum(unsigned char **p, const unsigned char *start, int val)
230a8e1175bSopenharmony_ci{
231a8e1175bSopenharmony_ci    return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_ENUMERATED);
232a8e1175bSopenharmony_ci}
233a8e1175bSopenharmony_ci
234a8e1175bSopenharmony_ciint mbedtls_asn1_write_tagged_string(unsigned char **p, const unsigned char *start, int tag,
235a8e1175bSopenharmony_ci                                     const char *text, size_t text_len)
236a8e1175bSopenharmony_ci{
237a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
238a8e1175bSopenharmony_ci    size_t len = 0;
239a8e1175bSopenharmony_ci
240a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
241a8e1175bSopenharmony_ci                                                            (const unsigned char *) text,
242a8e1175bSopenharmony_ci                                                            text_len));
243a8e1175bSopenharmony_ci
244a8e1175bSopenharmony_ci    return mbedtls_asn1_write_len_and_tag(p, start, len, tag);
245a8e1175bSopenharmony_ci}
246a8e1175bSopenharmony_ci
247a8e1175bSopenharmony_ciint mbedtls_asn1_write_utf8_string(unsigned char **p, const unsigned char *start,
248a8e1175bSopenharmony_ci                                   const char *text, size_t text_len)
249a8e1175bSopenharmony_ci{
250a8e1175bSopenharmony_ci    return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len);
251a8e1175bSopenharmony_ci}
252a8e1175bSopenharmony_ci
253a8e1175bSopenharmony_ciint mbedtls_asn1_write_printable_string(unsigned char **p, const unsigned char *start,
254a8e1175bSopenharmony_ci                                        const char *text, size_t text_len)
255a8e1175bSopenharmony_ci{
256a8e1175bSopenharmony_ci    return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text,
257a8e1175bSopenharmony_ci                                            text_len);
258a8e1175bSopenharmony_ci}
259a8e1175bSopenharmony_ci
260a8e1175bSopenharmony_ciint mbedtls_asn1_write_ia5_string(unsigned char **p, const unsigned char *start,
261a8e1175bSopenharmony_ci                                  const char *text, size_t text_len)
262a8e1175bSopenharmony_ci{
263a8e1175bSopenharmony_ci    return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len);
264a8e1175bSopenharmony_ci}
265a8e1175bSopenharmony_ci
266a8e1175bSopenharmony_ciint mbedtls_asn1_write_named_bitstring(unsigned char **p,
267a8e1175bSopenharmony_ci                                       const unsigned char *start,
268a8e1175bSopenharmony_ci                                       const unsigned char *buf,
269a8e1175bSopenharmony_ci                                       size_t bits)
270a8e1175bSopenharmony_ci{
271a8e1175bSopenharmony_ci    size_t unused_bits, byte_len;
272a8e1175bSopenharmony_ci    const unsigned char *cur_byte;
273a8e1175bSopenharmony_ci    unsigned char cur_byte_shifted;
274a8e1175bSopenharmony_ci    unsigned char bit;
275a8e1175bSopenharmony_ci
276a8e1175bSopenharmony_ci    byte_len = (bits + 7) / 8;
277a8e1175bSopenharmony_ci    unused_bits = (byte_len * 8) - bits;
278a8e1175bSopenharmony_ci
279a8e1175bSopenharmony_ci    /*
280a8e1175bSopenharmony_ci     * Named bitstrings require that trailing 0s are excluded in the encoding
281a8e1175bSopenharmony_ci     * of the bitstring. Trailing 0s are considered part of the 'unused' bits
282a8e1175bSopenharmony_ci     * when encoding this value in the first content octet
283a8e1175bSopenharmony_ci     */
284a8e1175bSopenharmony_ci    if (bits != 0) {
285a8e1175bSopenharmony_ci        cur_byte = buf + byte_len - 1;
286a8e1175bSopenharmony_ci        cur_byte_shifted = *cur_byte >> unused_bits;
287a8e1175bSopenharmony_ci
288a8e1175bSopenharmony_ci        for (;;) {
289a8e1175bSopenharmony_ci            bit = cur_byte_shifted & 0x1;
290a8e1175bSopenharmony_ci            cur_byte_shifted >>= 1;
291a8e1175bSopenharmony_ci
292a8e1175bSopenharmony_ci            if (bit != 0) {
293a8e1175bSopenharmony_ci                break;
294a8e1175bSopenharmony_ci            }
295a8e1175bSopenharmony_ci
296a8e1175bSopenharmony_ci            bits--;
297a8e1175bSopenharmony_ci            if (bits == 0) {
298a8e1175bSopenharmony_ci                break;
299a8e1175bSopenharmony_ci            }
300a8e1175bSopenharmony_ci
301a8e1175bSopenharmony_ci            if (bits % 8 == 0) {
302a8e1175bSopenharmony_ci                cur_byte_shifted = *--cur_byte;
303a8e1175bSopenharmony_ci            }
304a8e1175bSopenharmony_ci        }
305a8e1175bSopenharmony_ci    }
306a8e1175bSopenharmony_ci
307a8e1175bSopenharmony_ci    return mbedtls_asn1_write_bitstring(p, start, buf, bits);
308a8e1175bSopenharmony_ci}
309a8e1175bSopenharmony_ci
310a8e1175bSopenharmony_ciint mbedtls_asn1_write_bitstring(unsigned char **p, const unsigned char *start,
311a8e1175bSopenharmony_ci                                 const unsigned char *buf, size_t bits)
312a8e1175bSopenharmony_ci{
313a8e1175bSopenharmony_ci    size_t len = 0;
314a8e1175bSopenharmony_ci    size_t unused_bits, byte_len;
315a8e1175bSopenharmony_ci
316a8e1175bSopenharmony_ci    byte_len = (bits + 7) / 8;
317a8e1175bSopenharmony_ci    unused_bits = (byte_len * 8) - bits;
318a8e1175bSopenharmony_ci
319a8e1175bSopenharmony_ci    if (*p < start || (size_t) (*p - start) < byte_len + 1) {
320a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
321a8e1175bSopenharmony_ci    }
322a8e1175bSopenharmony_ci
323a8e1175bSopenharmony_ci    len = byte_len + 1;
324a8e1175bSopenharmony_ci
325a8e1175bSopenharmony_ci    /* Write the bitstring. Ensure the unused bits are zeroed */
326a8e1175bSopenharmony_ci    if (byte_len > 0) {
327a8e1175bSopenharmony_ci        byte_len--;
328a8e1175bSopenharmony_ci        *--(*p) = buf[byte_len] & ~((0x1 << unused_bits) - 1);
329a8e1175bSopenharmony_ci        (*p) -= byte_len;
330a8e1175bSopenharmony_ci        memcpy(*p, buf, byte_len);
331a8e1175bSopenharmony_ci    }
332a8e1175bSopenharmony_ci
333a8e1175bSopenharmony_ci    /* Write unused bits */
334a8e1175bSopenharmony_ci    *--(*p) = (unsigned char) unused_bits;
335a8e1175bSopenharmony_ci
336a8e1175bSopenharmony_ci    return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_BIT_STRING);
337a8e1175bSopenharmony_ci}
338a8e1175bSopenharmony_ci
339a8e1175bSopenharmony_ciint mbedtls_asn1_write_octet_string(unsigned char **p, const unsigned char *start,
340a8e1175bSopenharmony_ci                                    const unsigned char *buf, size_t size)
341a8e1175bSopenharmony_ci{
342a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
343a8e1175bSopenharmony_ci    size_t len = 0;
344a8e1175bSopenharmony_ci
345a8e1175bSopenharmony_ci    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, buf, size));
346a8e1175bSopenharmony_ci
347a8e1175bSopenharmony_ci    return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_OCTET_STRING);
348a8e1175bSopenharmony_ci}
349a8e1175bSopenharmony_ci
350a8e1175bSopenharmony_ci
351a8e1175bSopenharmony_ci#if !defined(MBEDTLS_ASN1_PARSE_C)
352a8e1175bSopenharmony_ci/* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(),
353a8e1175bSopenharmony_ci * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */
354a8e1175bSopenharmony_cistatic mbedtls_asn1_named_data *asn1_find_named_data(
355a8e1175bSopenharmony_ci    mbedtls_asn1_named_data *list,
356a8e1175bSopenharmony_ci    const char *oid, size_t len)
357a8e1175bSopenharmony_ci{
358a8e1175bSopenharmony_ci    while (list != NULL) {
359a8e1175bSopenharmony_ci        if (list->oid.len == len &&
360a8e1175bSopenharmony_ci            memcmp(list->oid.p, oid, len) == 0) {
361a8e1175bSopenharmony_ci            break;
362a8e1175bSopenharmony_ci        }
363a8e1175bSopenharmony_ci
364a8e1175bSopenharmony_ci        list = list->next;
365a8e1175bSopenharmony_ci    }
366a8e1175bSopenharmony_ci
367a8e1175bSopenharmony_ci    return list;
368a8e1175bSopenharmony_ci}
369a8e1175bSopenharmony_ci#else
370a8e1175bSopenharmony_ci#define asn1_find_named_data(list, oid, len) \
371a8e1175bSopenharmony_ci    ((mbedtls_asn1_named_data *) mbedtls_asn1_find_named_data(list, oid, len))
372a8e1175bSopenharmony_ci#endif
373a8e1175bSopenharmony_ci
374a8e1175bSopenharmony_cimbedtls_asn1_named_data *mbedtls_asn1_store_named_data(
375a8e1175bSopenharmony_ci    mbedtls_asn1_named_data **head,
376a8e1175bSopenharmony_ci    const char *oid, size_t oid_len,
377a8e1175bSopenharmony_ci    const unsigned char *val,
378a8e1175bSopenharmony_ci    size_t val_len)
379a8e1175bSopenharmony_ci{
380a8e1175bSopenharmony_ci    mbedtls_asn1_named_data *cur;
381a8e1175bSopenharmony_ci
382a8e1175bSopenharmony_ci    if ((cur = asn1_find_named_data(*head, oid, oid_len)) == NULL) {
383a8e1175bSopenharmony_ci        // Add new entry if not present yet based on OID
384a8e1175bSopenharmony_ci        //
385a8e1175bSopenharmony_ci        cur = (mbedtls_asn1_named_data *) mbedtls_calloc(1,
386a8e1175bSopenharmony_ci                                                         sizeof(mbedtls_asn1_named_data));
387a8e1175bSopenharmony_ci        if (cur == NULL) {
388a8e1175bSopenharmony_ci            return NULL;
389a8e1175bSopenharmony_ci        }
390a8e1175bSopenharmony_ci
391a8e1175bSopenharmony_ci        cur->oid.len = oid_len;
392a8e1175bSopenharmony_ci        cur->oid.p = mbedtls_calloc(1, oid_len);
393a8e1175bSopenharmony_ci        if (cur->oid.p == NULL) {
394a8e1175bSopenharmony_ci            mbedtls_free(cur);
395a8e1175bSopenharmony_ci            return NULL;
396a8e1175bSopenharmony_ci        }
397a8e1175bSopenharmony_ci
398a8e1175bSopenharmony_ci        memcpy(cur->oid.p, oid, oid_len);
399a8e1175bSopenharmony_ci
400a8e1175bSopenharmony_ci        cur->val.len = val_len;
401a8e1175bSopenharmony_ci        if (val_len != 0) {
402a8e1175bSopenharmony_ci            cur->val.p = mbedtls_calloc(1, val_len);
403a8e1175bSopenharmony_ci            if (cur->val.p == NULL) {
404a8e1175bSopenharmony_ci                mbedtls_free(cur->oid.p);
405a8e1175bSopenharmony_ci                mbedtls_free(cur);
406a8e1175bSopenharmony_ci                return NULL;
407a8e1175bSopenharmony_ci            }
408a8e1175bSopenharmony_ci        }
409a8e1175bSopenharmony_ci
410a8e1175bSopenharmony_ci        cur->next = *head;
411a8e1175bSopenharmony_ci        *head = cur;
412a8e1175bSopenharmony_ci    } else if (val_len == 0) {
413a8e1175bSopenharmony_ci        mbedtls_free(cur->val.p);
414a8e1175bSopenharmony_ci        cur->val.p = NULL;
415a8e1175bSopenharmony_ci    } else if (cur->val.len != val_len) {
416a8e1175bSopenharmony_ci        /*
417a8e1175bSopenharmony_ci         * Enlarge existing value buffer if needed
418a8e1175bSopenharmony_ci         * Preserve old data until the allocation succeeded, to leave list in
419a8e1175bSopenharmony_ci         * a consistent state in case allocation fails.
420a8e1175bSopenharmony_ci         */
421a8e1175bSopenharmony_ci        void *p = mbedtls_calloc(1, val_len);
422a8e1175bSopenharmony_ci        if (p == NULL) {
423a8e1175bSopenharmony_ci            return NULL;
424a8e1175bSopenharmony_ci        }
425a8e1175bSopenharmony_ci
426a8e1175bSopenharmony_ci        mbedtls_free(cur->val.p);
427a8e1175bSopenharmony_ci        cur->val.p = p;
428a8e1175bSopenharmony_ci        cur->val.len = val_len;
429a8e1175bSopenharmony_ci    }
430a8e1175bSopenharmony_ci
431a8e1175bSopenharmony_ci    if (val != NULL && val_len != 0) {
432a8e1175bSopenharmony_ci        memcpy(cur->val.p, val, val_len);
433a8e1175bSopenharmony_ci    }
434a8e1175bSopenharmony_ci
435a8e1175bSopenharmony_ci    return cur;
436a8e1175bSopenharmony_ci}
437a8e1175bSopenharmony_ci#endif /* MBEDTLS_ASN1_WRITE_C */
438