Branch data Line data Source code
1 : : /*
2 : : * Generic ASN.1 parsing
3 : : *
4 : : * Copyright The Mbed TLS Contributors
5 : : * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 : : */
7 : :
8 : : #include "common.h"
9 : :
10 : : #if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C) || \
11 : : defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
12 : :
13 : : #include "mbedtls/asn1.h"
14 : : #include "mbedtls/platform_util.h"
15 : : #include "mbedtls/error.h"
16 : :
17 : : #include <string.h>
18 : :
19 : : #if defined(MBEDTLS_BIGNUM_C)
20 : : #include "mbedtls/bignum.h"
21 : : #endif
22 : :
23 : : #include "mbedtls/platform.h"
24 : :
25 : : /*
26 : : * ASN.1 DER decoding routines
27 : : */
28 : 124 : int mbedtls_asn1_get_len(unsigned char **p,
29 : : const unsigned char *end,
30 : : size_t *len)
31 : : {
32 [ - + ]: 124 : if ((end - *p) < 1) {
33 : : return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
34 : : }
35 : :
36 [ + + ]: 124 : if ((**p & 0x80) == 0) {
37 : 116 : *len = *(*p)++;
38 : : } else {
39 : 8 : int n = (**p) & 0x7F;
40 [ + - ]: 8 : if (n == 0 || n > 4) {
41 : : return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
42 : : }
43 [ - + ]: 8 : if ((end - *p) <= n) {
44 : : return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
45 : : }
46 : 8 : *len = 0;
47 : 8 : (*p)++;
48 [ + + ]: 20 : while (n--) {
49 : 12 : *len = (*len << 8) | **p;
50 : 12 : (*p)++;
51 : : }
52 : : }
53 : :
54 [ - + ]: 124 : if (*len > (size_t) (end - *p)) {
55 : : return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
56 : : }
57 : :
58 : : return 0;
59 : : }
60 : :
61 : 92 : int mbedtls_asn1_get_tag(unsigned char **p,
62 : : const unsigned char *end,
63 : : size_t *len, int tag)
64 : : {
65 [ + - ]: 92 : if ((end - *p) < 1) {
66 : : return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
67 : : }
68 : :
69 [ + - ]: 92 : if (**p != tag) {
70 : : return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
71 : : }
72 : :
73 : 92 : (*p)++;
74 : :
75 : 92 : return mbedtls_asn1_get_len(p, end, len);
76 : : }
77 : : #endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */
78 : :
79 : : #if defined(MBEDTLS_ASN1_PARSE_C)
80 : 0 : int mbedtls_asn1_get_bool(unsigned char **p,
81 : : const unsigned char *end,
82 : : int *val)
83 : : {
84 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
85 : 0 : size_t len;
86 : :
87 [ # # ]: 0 : if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BOOLEAN)) != 0) {
88 : : return ret;
89 : : }
90 : :
91 [ # # ]: 0 : if (len != 1) {
92 : : return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
93 : : }
94 : :
95 : 0 : *val = (**p != 0) ? 1 : 0;
96 : 0 : (*p)++;
97 : :
98 : 0 : return 0;
99 : : }
100 : :
101 : 4 : static int asn1_get_tagged_int(unsigned char **p,
102 : : const unsigned char *end,
103 : : int tag, int *val)
104 : : {
105 : 4 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
106 : 4 : size_t len;
107 : :
108 [ + - ]: 4 : if ((ret = mbedtls_asn1_get_tag(p, end, &len, tag)) != 0) {
109 : : return ret;
110 : : }
111 : :
112 : : /*
113 : : * len==0 is malformed (0 must be represented as 020100 for INTEGER,
114 : : * or 0A0100 for ENUMERATED tags
115 : : */
116 [ - + ]: 4 : if (len == 0) {
117 : : return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
118 : : }
119 : : /* This is a cryptography library. Reject negative integers. */
120 [ - + ]: 4 : if ((**p & 0x80) != 0) {
121 : : return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
122 : : }
123 : :
124 : : /* Skip leading zeros. */
125 [ + - - + ]: 4 : while (len > 0 && **p == 0) {
126 : 0 : ++(*p);
127 : 0 : --len;
128 : : }
129 : :
130 : : /* Reject integers that don't fit in an int. This code assumes that
131 : : * the int type has no padding bit. */
132 [ - + ]: 4 : if (len > sizeof(int)) {
133 : : return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
134 : : }
135 [ - + - - ]: 4 : if (len == sizeof(int) && (**p & 0x80) != 0) {
136 : : return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
137 : : }
138 : :
139 : 4 : *val = 0;
140 [ + + ]: 8 : while (len-- > 0) {
141 : 4 : *val = (*val << 8) | **p;
142 : 4 : (*p)++;
143 : : }
144 : :
145 : : return 0;
146 : : }
147 : :
148 : 4 : int mbedtls_asn1_get_int(unsigned char **p,
149 : : const unsigned char *end,
150 : : int *val)
151 : : {
152 : 4 : return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_INTEGER, val);
153 : : }
154 : :
155 : 0 : int mbedtls_asn1_get_enum(unsigned char **p,
156 : : const unsigned char *end,
157 : : int *val)
158 : : {
159 : 0 : return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_ENUMERATED, val);
160 : : }
161 : :
162 : : #if defined(MBEDTLS_BIGNUM_C)
163 : 0 : int mbedtls_asn1_get_mpi(unsigned char **p,
164 : : const unsigned char *end,
165 : : mbedtls_mpi *X)
166 : : {
167 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
168 : 0 : size_t len;
169 : :
170 [ # # ]: 0 : if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
171 : : return ret;
172 : : }
173 : :
174 : 0 : ret = mbedtls_mpi_read_binary(X, *p, len);
175 : :
176 : 0 : *p += len;
177 : :
178 : 0 : return ret;
179 : : }
180 : : #endif /* MBEDTLS_BIGNUM_C */
181 : :
182 : 0 : int mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end,
183 : : mbedtls_asn1_bitstring *bs)
184 : : {
185 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
186 : :
187 : : /* Certificate type is a single byte bitstring */
188 [ # # ]: 0 : if ((ret = mbedtls_asn1_get_tag(p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
189 : : return ret;
190 : : }
191 : :
192 : : /* Check length, subtract one for actual bit string length */
193 [ # # ]: 0 : if (bs->len < 1) {
194 : : return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
195 : : }
196 : 0 : bs->len -= 1;
197 : :
198 : : /* Get number of unused bits, ensure unused bits <= 7 */
199 : 0 : bs->unused_bits = **p;
200 [ # # ]: 0 : if (bs->unused_bits > 7) {
201 : : return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
202 : : }
203 : 0 : (*p)++;
204 : :
205 : : /* Get actual bitstring */
206 : 0 : bs->p = *p;
207 : 0 : *p += bs->len;
208 : :
209 [ # # ]: 0 : if (*p != end) {
210 : 0 : return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
211 : : }
212 : :
213 : : return 0;
214 : : }
215 : :
216 : : /*
217 : : * Traverse an ASN.1 "SEQUENCE OF <tag>"
218 : : * and call a callback for each entry found.
219 : : */
220 : 4 : int mbedtls_asn1_traverse_sequence_of(
221 : : unsigned char **p,
222 : : const unsigned char *end,
223 : : unsigned char tag_must_mask, unsigned char tag_must_val,
224 : : unsigned char tag_may_mask, unsigned char tag_may_val,
225 : : int (*cb)(void *ctx, int tag,
226 : : unsigned char *start, size_t len),
227 : : void *ctx)
228 : : {
229 : 4 : int ret;
230 : 4 : size_t len;
231 : :
232 : : /* Get main sequence tag */
233 [ + - ]: 4 : if ((ret = mbedtls_asn1_get_tag(p, end, &len,
234 : : MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
235 : : return ret;
236 : : }
237 : :
238 [ + - ]: 4 : if (*p + len != end) {
239 : : return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
240 : : }
241 : :
242 [ + + ]: 12 : while (*p < end) {
243 : 8 : unsigned char const tag = *(*p)++;
244 : :
245 [ + - ]: 8 : if ((tag & tag_must_mask) != tag_must_val) {
246 : : return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
247 : : }
248 : :
249 [ - + ]: 8 : if ((ret = mbedtls_asn1_get_len(p, end, &len)) != 0) {
250 : 0 : return ret;
251 : : }
252 : :
253 [ + - ]: 8 : if ((tag & tag_may_mask) == tag_may_val) {
254 [ + - ]: 8 : if (cb != NULL) {
255 : 8 : ret = cb(ctx, tag, *p, len);
256 [ - + ]: 8 : if (ret != 0) {
257 : 0 : return ret;
258 : : }
259 : : }
260 : : }
261 : :
262 : 8 : *p += len;
263 : : }
264 : :
265 : : return 0;
266 : : }
267 : :
268 : : /*
269 : : * Get a bit string without unused bits
270 : : */
271 : 8 : int mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end,
272 : : size_t *len)
273 : : {
274 : 8 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
275 : :
276 [ + - ]: 8 : if ((ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
277 : : return ret;
278 : : }
279 : :
280 [ - + ]: 8 : if (*len == 0) {
281 : : return MBEDTLS_ERR_ASN1_INVALID_DATA;
282 : : }
283 : 8 : --(*len);
284 : :
285 [ - + ]: 8 : if (**p != 0) {
286 : : return MBEDTLS_ERR_ASN1_INVALID_DATA;
287 : : }
288 : 8 : ++(*p);
289 : :
290 : 8 : return 0;
291 : : }
292 : :
293 : 16 : void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq)
294 : : {
295 [ - + ]: 16 : while (seq != NULL) {
296 : 0 : mbedtls_asn1_sequence *next = seq->next;
297 : 0 : mbedtls_free(seq);
298 : 0 : seq = next;
299 : : }
300 : 16 : }
301 : :
302 : : typedef struct {
303 : : int tag;
304 : : mbedtls_asn1_sequence *cur;
305 : : } asn1_get_sequence_of_cb_ctx_t;
306 : :
307 : 0 : static int asn1_get_sequence_of_cb(void *ctx,
308 : : int tag,
309 : : unsigned char *start,
310 : : size_t len)
311 : : {
312 : 0 : asn1_get_sequence_of_cb_ctx_t *cb_ctx =
313 : : (asn1_get_sequence_of_cb_ctx_t *) ctx;
314 : 0 : mbedtls_asn1_sequence *cur =
315 : : cb_ctx->cur;
316 : :
317 [ # # ]: 0 : if (cur->buf.p != NULL) {
318 : 0 : cur->next =
319 : 0 : mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
320 : :
321 [ # # ]: 0 : if (cur->next == NULL) {
322 : : return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
323 : : }
324 : :
325 : : cur = cur->next;
326 : : }
327 : :
328 : 0 : cur->buf.p = start;
329 : 0 : cur->buf.len = len;
330 : 0 : cur->buf.tag = tag;
331 : :
332 : 0 : cb_ctx->cur = cur;
333 : 0 : return 0;
334 : : }
335 : :
336 : : /*
337 : : * Parses and splits an ASN.1 "SEQUENCE OF <tag>"
338 : : */
339 : 0 : int mbedtls_asn1_get_sequence_of(unsigned char **p,
340 : : const unsigned char *end,
341 : : mbedtls_asn1_sequence *cur,
342 : : int tag)
343 : : {
344 : 0 : asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur };
345 : 0 : memset(cur, 0, sizeof(mbedtls_asn1_sequence));
346 : 0 : return mbedtls_asn1_traverse_sequence_of(
347 : : p, end, 0xFF, tag, 0, 0,
348 : : asn1_get_sequence_of_cb, &cb_ctx);
349 : : }
350 : :
351 : 12 : int mbedtls_asn1_get_alg(unsigned char **p,
352 : : const unsigned char *end,
353 : : mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params)
354 : : {
355 : 12 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
356 : 12 : size_t len;
357 : :
358 [ + - ]: 12 : if ((ret = mbedtls_asn1_get_tag(p, end, &len,
359 : : MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
360 : : return ret;
361 : : }
362 : :
363 [ + - ]: 12 : if ((end - *p) < 1) {
364 : : return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
365 : : }
366 : :
367 : 12 : alg->tag = **p;
368 : 12 : end = *p + len;
369 : :
370 [ + - ]: 12 : if ((ret = mbedtls_asn1_get_tag(p, end, &alg->len, MBEDTLS_ASN1_OID)) != 0) {
371 : : return ret;
372 : : }
373 : :
374 : 12 : alg->p = *p;
375 : 12 : *p += alg->len;
376 : :
377 [ + + ]: 12 : if (*p == end) {
378 : 8 : mbedtls_platform_zeroize(params, sizeof(mbedtls_asn1_buf));
379 : 8 : return 0;
380 : : }
381 : :
382 : 4 : params->tag = **p;
383 : 4 : (*p)++;
384 : :
385 [ + - ]: 4 : if ((ret = mbedtls_asn1_get_len(p, end, ¶ms->len)) != 0) {
386 : : return ret;
387 : : }
388 : :
389 : 4 : params->p = *p;
390 : 4 : *p += params->len;
391 : :
392 [ + - ]: 4 : if (*p != end) {
393 : : return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
394 : : }
395 : :
396 : : return 0;
397 : : }
398 : :
399 : 0 : int mbedtls_asn1_get_alg_null(unsigned char **p,
400 : : const unsigned char *end,
401 : : mbedtls_asn1_buf *alg)
402 : : {
403 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
404 : 0 : mbedtls_asn1_buf params;
405 : :
406 : 0 : memset(¶ms, 0, sizeof(mbedtls_asn1_buf));
407 : :
408 [ # # ]: 0 : if ((ret = mbedtls_asn1_get_alg(p, end, alg, ¶ms)) != 0) {
409 : : return ret;
410 : : }
411 : :
412 [ # # # # ]: 0 : if ((params.tag != MBEDTLS_ASN1_NULL && params.tag != 0) || params.len != 0) {
413 : 0 : return MBEDTLS_ERR_ASN1_INVALID_DATA;
414 : : }
415 : :
416 : : return 0;
417 : : }
418 : :
419 : : #if !defined(MBEDTLS_DEPRECATED_REMOVED)
420 : 0 : void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *cur)
421 : : {
422 [ # # ]: 0 : if (cur == NULL) {
423 : : return;
424 : : }
425 : :
426 : 0 : mbedtls_free(cur->oid.p);
427 : 0 : mbedtls_free(cur->val.p);
428 : :
429 : 0 : mbedtls_platform_zeroize(cur, sizeof(mbedtls_asn1_named_data));
430 : : }
431 : : #endif /* MBEDTLS_DEPRECATED_REMOVED */
432 : :
433 : 0 : void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head)
434 : : {
435 : 0 : mbedtls_asn1_named_data *cur;
436 : :
437 [ # # ]: 0 : while ((cur = *head) != NULL) {
438 : 0 : *head = cur->next;
439 : 0 : mbedtls_free(cur->oid.p);
440 : 0 : mbedtls_free(cur->val.p);
441 : 0 : mbedtls_free(cur);
442 : : }
443 : 0 : }
444 : :
445 : 8 : void mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name)
446 : : {
447 [ - + ]: 8 : for (mbedtls_asn1_named_data *next; name != NULL; name = next) {
448 : 0 : next = name->next;
449 : 0 : mbedtls_free(name);
450 : : }
451 : 8 : }
452 : :
453 : 0 : const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data *list,
454 : : const char *oid, size_t len)
455 : : {
456 [ # # ]: 0 : while (list != NULL) {
457 [ # # ]: 0 : if (list->oid.len == len &&
458 [ # # ]: 0 : memcmp(list->oid.p, oid, len) == 0) {
459 : : break;
460 : : }
461 : :
462 : 0 : list = list->next;
463 : : }
464 : :
465 : 0 : return list;
466 : : }
467 : :
468 : : #endif /* MBEDTLS_ASN1_PARSE_C */
|