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