text
[RRG-proxmark3.git] / common / mbedtls / asn1write.c
blob6c2d266850bec87ba06d45e033e404a0c1a96954
1 /*
2 * ASN.1 buffer writing functionality
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 #include "common.h"
22 #if defined(MBEDTLS_ASN1_WRITE_C)
24 #include "mbedtls/asn1write.h"
25 #include "mbedtls/error.h"
27 #include <string.h>
29 #if defined(MBEDTLS_PLATFORM_C)
30 #include "mbedtls/platform.h"
31 #else
32 #include <stdlib.h>
33 #define mbedtls_calloc calloc
34 #define mbedtls_free free
35 #endif
37 int mbedtls_asn1_write_len(unsigned char **p, unsigned char *start, size_t len) {
38 if (len < 0x80) {
39 if (*p - start < 1)
40 return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL);
42 *--(*p) = (unsigned char) len;
43 return (1);
46 if (len <= 0xFF) {
47 if (*p - start < 2)
48 return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL);
50 *--(*p) = (unsigned char) len;
51 *--(*p) = 0x81;
52 return (2);
55 if (len <= 0xFFFF) {
56 if (*p - start < 3)
57 return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL);
59 *--(*p) = (len) & 0xFF;
60 *--(*p) = (len >> 8) & 0xFF;
61 *--(*p) = 0x82;
62 return (3);
65 if (len <= 0xFFFFFF) {
66 if (*p - start < 4)
67 return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL);
69 *--(*p) = (len) & 0xFF;
70 *--(*p) = (len >> 8) & 0xFF;
71 *--(*p) = (len >> 16) & 0xFF;
72 *--(*p) = 0x83;
73 return (4);
76 #if SIZE_MAX > 0xFFFFFFFF
77 if (len <= 0xFFFFFFFF)
78 #endif
80 if (*p - start < 5)
81 return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL);
83 *--(*p) = (len) & 0xFF;
84 *--(*p) = (len >> 8) & 0xFF;
85 *--(*p) = (len >> 16) & 0xFF;
86 *--(*p) = (len >> 24) & 0xFF;
87 *--(*p) = 0x84;
88 return (5);
91 #if SIZE_MAX > 0xFFFFFFFF
92 return (MBEDTLS_ERR_ASN1_INVALID_LENGTH);
93 #endif
96 int mbedtls_asn1_write_tag(unsigned char **p, unsigned char *start, unsigned char tag) {
97 if (*p - start < 1)
98 return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL);
100 *--(*p) = tag;
102 return (1);
105 int mbedtls_asn1_write_raw_buffer(unsigned char **p, unsigned char *start,
106 const unsigned char *buf, size_t size) {
107 size_t len = 0;
109 if (*p < start || (size_t)(*p - start) < size)
110 return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL);
112 len = size;
113 (*p) -= len;
114 memcpy(*p, buf, len);
116 return ((int) len);
119 #if defined(MBEDTLS_BIGNUM_C)
120 int mbedtls_asn1_write_mpi(unsigned char **p, unsigned char *start, const mbedtls_mpi *X) {
121 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
122 size_t len = 0;
124 // Write the MPI
126 len = mbedtls_mpi_size(X);
128 if (*p < start || (size_t)(*p - start) < len)
129 return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL);
131 (*p) -= len;
132 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(X, *p, len));
134 // DER format assumes 2s complement for numbers, so the leftmost bit
135 // should be 0 for positive numbers and 1 for negative numbers.
137 if (X->s == 1 && **p & 0x80) {
138 if (*p - start < 1)
139 return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL);
141 *--(*p) = 0x00;
142 len += 1;
145 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
146 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_INTEGER));
148 ret = (int) len;
150 cleanup:
151 return (ret);
153 #endif /* MBEDTLS_BIGNUM_C */
155 int mbedtls_asn1_write_null(unsigned char **p, unsigned char *start) {
156 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
157 size_t len = 0;
159 // Write NULL
161 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, 0));
162 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_NULL));
164 return ((int) len);
167 int mbedtls_asn1_write_oid(unsigned char **p, unsigned char *start,
168 const char *oid, size_t oid_len) {
169 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
170 size_t len = 0;
172 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
173 (const unsigned char *) oid, oid_len));
174 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
175 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OID));
177 return ((int) len);
180 int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, unsigned char *start,
181 const char *oid, size_t oid_len,
182 size_t par_len) {
183 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
184 size_t len = 0;
186 if (par_len == 0)
187 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_null(p, start));
188 else
189 len += par_len;
191 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
193 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
194 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
195 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
197 return ((int) len);
200 int mbedtls_asn1_write_bool(unsigned char **p, unsigned char *start, int boolean) {
201 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
202 size_t len = 0;
204 if (*p - start < 1)
205 return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL);
207 *--(*p) = (boolean) ? 255 : 0;
208 len++;
210 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
211 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_BOOLEAN));
213 return ((int) len);
216 static int asn1_write_tagged_int(unsigned char **p, unsigned char *start, int val, int tag) {
217 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
218 size_t len = 0;
220 do {
221 if (*p - start < 1)
222 return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL);
223 len += 1;
224 *--(*p) = val & 0xff;
225 val >>= 8;
226 } while (val > 0);
228 if (**p & 0x80) {
229 if (*p - start < 1)
230 return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL);
231 *--(*p) = 0x00;
232 len += 1;
235 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
236 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag));
238 return ((int) len);
241 int mbedtls_asn1_write_int(unsigned char **p, unsigned char *start, int val) {
242 return (asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_INTEGER));
245 int mbedtls_asn1_write_enum(unsigned char **p, unsigned char *start, int val) {
246 return (asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_ENUMERATED));
249 int mbedtls_asn1_write_tagged_string(unsigned char **p, unsigned char *start, int tag,
250 const char *text, size_t text_len) {
251 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
252 size_t len = 0;
254 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
255 (const unsigned char *) text, text_len));
257 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
258 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag));
260 return ((int) len);
263 int mbedtls_asn1_write_utf8_string(unsigned char **p, unsigned char *start,
264 const char *text, size_t text_len) {
265 return (mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len));
268 int mbedtls_asn1_write_printable_string(unsigned char **p, unsigned char *start,
269 const char *text, size_t text_len) {
270 return (mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len));
273 int mbedtls_asn1_write_ia5_string(unsigned char **p, unsigned char *start,
274 const char *text, size_t text_len) {
275 return (mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len));
278 int mbedtls_asn1_write_named_bitstring(unsigned char **p,
279 unsigned char *start,
280 const unsigned char *buf,
281 size_t bits) {
282 size_t unused_bits, byte_len;
283 const unsigned char *cur_byte;
284 unsigned char cur_byte_shifted;
285 unsigned char bit;
287 byte_len = (bits + 7) / 8;
288 unused_bits = (byte_len * 8) - bits;
291 * Named bitstrings require that trailing 0s are excluded in the encoding
292 * of the bitstring. Trailing 0s are considered part of the 'unused' bits
293 * when encoding this value in the first content octet
295 if (bits != 0) {
296 cur_byte = buf + byte_len - 1;
297 cur_byte_shifted = *cur_byte >> unused_bits;
299 for (; ;) {
300 bit = cur_byte_shifted & 0x1;
301 cur_byte_shifted >>= 1;
303 if (bit != 0)
304 break;
306 bits--;
307 if (bits == 0)
308 break;
310 if (bits % 8 == 0)
311 cur_byte_shifted = *--cur_byte;
315 return (mbedtls_asn1_write_bitstring(p, start, buf, bits));
318 int mbedtls_asn1_write_bitstring(unsigned char **p, unsigned char *start,
319 const unsigned char *buf, size_t bits) {
320 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
321 size_t len = 0;
322 size_t unused_bits, byte_len;
324 byte_len = (bits + 7) / 8;
325 unused_bits = (byte_len * 8) - bits;
327 if (*p < start || (size_t)(*p - start) < byte_len + 1)
328 return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL);
330 len = byte_len + 1;
332 /* Write the bitstring. Ensure the unused bits are zeroed */
333 if (byte_len > 0) {
334 byte_len--;
335 *--(*p) = buf[byte_len] & ~((0x1 << unused_bits) - 1);
336 (*p) -= byte_len;
337 memcpy(*p, buf, byte_len);
340 /* Write unused bits */
341 *--(*p) = (unsigned char)unused_bits;
343 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
344 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_BIT_STRING));
346 return ((int) len);
349 int mbedtls_asn1_write_octet_string(unsigned char **p, unsigned char *start,
350 const unsigned char *buf, size_t size) {
351 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
352 size_t len = 0;
354 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, buf, size));
356 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
357 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OCTET_STRING));
359 return ((int) len);
363 /* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(),
364 * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */
365 static mbedtls_asn1_named_data *asn1_find_named_data(
366 mbedtls_asn1_named_data *list,
367 const char *oid, size_t len) {
368 while (list != NULL) {
369 if (list->oid.len == len &&
370 memcmp(list->oid.p, oid, len) == 0) {
371 break;
374 list = list->next;
377 return (list);
380 mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(
381 mbedtls_asn1_named_data **head,
382 const char *oid, size_t oid_len,
383 const unsigned char *val,
384 size_t val_len) {
385 mbedtls_asn1_named_data *cur;
387 if ((cur = asn1_find_named_data(*head, oid, oid_len)) == NULL) {
388 // Add new entry if not present yet based on OID
390 cur = (mbedtls_asn1_named_data *)mbedtls_calloc(1,
391 sizeof(mbedtls_asn1_named_data));
392 if (cur == NULL)
393 return (NULL);
395 cur->oid.len = oid_len;
396 cur->oid.p = mbedtls_calloc(1, oid_len);
397 if (cur->oid.p == NULL) {
398 mbedtls_free(cur);
399 return (NULL);
402 memcpy(cur->oid.p, oid, oid_len);
404 cur->val.len = val_len;
405 if (val_len != 0) {
406 cur->val.p = mbedtls_calloc(1, val_len);
407 if (cur->val.p == NULL) {
408 mbedtls_free(cur->oid.p);
409 mbedtls_free(cur);
410 return (NULL);
414 cur->next = *head;
415 *head = cur;
416 } else if (val_len == 0) {
417 mbedtls_free(cur->val.p);
418 cur->val.p = NULL;
419 } else if (cur->val.len != val_len) {
421 * Enlarge existing value buffer if needed
422 * Preserve old data until the allocation succeeded, to leave list in
423 * a consistent state in case allocation fails.
425 void *p = mbedtls_calloc(1, val_len);
426 if (p == NULL)
427 return (NULL);
429 mbedtls_free(cur->val.p);
430 cur->val.p = p;
431 cur->val.len = val_len;
434 if (val != NULL)
435 memcpy(cur->val.p, val, val_len);
437 return (cur);
439 #endif /* MBEDTLS_ASN1_WRITE_C */