text
[RRG-proxmark3.git] / common / mbedtls / asn1parse.c
blob98460e055dc6531e073235bd0c4031dadfc8294d
1 /*
2 * Generic ASN.1 parsing
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_PARSE_C)
24 #include "mbedtls/asn1.h"
25 #include "mbedtls/platform_util.h"
26 #include "mbedtls/error.h"
28 #include <string.h>
30 #if defined(MBEDTLS_BIGNUM_C)
31 #include "mbedtls/bignum.h"
32 #endif
34 #if defined(MBEDTLS_PLATFORM_C)
35 #include "mbedtls/platform.h"
36 #else
37 #include <stdlib.h>
38 #define mbedtls_calloc calloc
39 #define mbedtls_free free
40 #endif
43 * ASN.1 DER decoding routines
45 int mbedtls_asn1_get_len(unsigned char **p,
46 const unsigned char *end,
47 size_t *len) {
48 if ((end - *p) < 1)
49 return (MBEDTLS_ERR_ASN1_OUT_OF_DATA);
51 if ((**p & 0x80) == 0)
52 *len = *(*p)++;
53 else {
54 switch (**p & 0x7F) {
55 case 1:
56 if ((end - *p) < 2)
57 return (MBEDTLS_ERR_ASN1_OUT_OF_DATA);
59 *len = (*p)[1];
60 (*p) += 2;
61 break;
63 case 2:
64 if ((end - *p) < 3)
65 return (MBEDTLS_ERR_ASN1_OUT_OF_DATA);
67 *len = ((size_t)(*p)[1] << 8) | (*p)[2];
68 (*p) += 3;
69 break;
71 case 3:
72 if ((end - *p) < 4)
73 return (MBEDTLS_ERR_ASN1_OUT_OF_DATA);
75 *len = ((size_t)(*p)[1] << 16) |
76 ((size_t)(*p)[2] << 8) | (*p)[3];
77 (*p) += 4;
78 break;
80 case 4:
81 if ((end - *p) < 5)
82 return (MBEDTLS_ERR_ASN1_OUT_OF_DATA);
84 *len = ((size_t)(*p)[1] << 24) | ((size_t)(*p)[2] << 16) |
85 ((size_t)(*p)[3] << 8) | (*p)[4];
86 (*p) += 5;
87 break;
89 default:
90 return (MBEDTLS_ERR_ASN1_INVALID_LENGTH);
94 if (*len > (size_t)(end - *p))
95 return (MBEDTLS_ERR_ASN1_OUT_OF_DATA);
97 return (0);
100 int mbedtls_asn1_get_tag(unsigned char **p,
101 const unsigned char *end,
102 size_t *len, int tag) {
103 if ((end - *p) < 1)
104 return (MBEDTLS_ERR_ASN1_OUT_OF_DATA);
106 if (**p != tag)
107 return (MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
109 (*p)++;
111 return (mbedtls_asn1_get_len(p, end, len));
114 int mbedtls_asn1_get_bool(unsigned char **p,
115 const unsigned char *end,
116 int *val) {
117 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
118 size_t len;
120 if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BOOLEAN)) != 0)
121 return (ret);
123 if (len != 1)
124 return (MBEDTLS_ERR_ASN1_INVALID_LENGTH);
126 *val = (**p != 0) ? 1 : 0;
127 (*p)++;
129 return (0);
132 static int asn1_get_tagged_int(unsigned char **p,
133 const unsigned char *end,
134 int tag, int *val) {
135 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
136 size_t len;
138 if ((ret = mbedtls_asn1_get_tag(p, end, &len, tag)) != 0)
139 return (ret);
142 * len==0 is malformed (0 must be represented as 020100 for INTEGER,
143 * or 0A0100 for ENUMERATED tags
145 if (len == 0)
146 return (MBEDTLS_ERR_ASN1_INVALID_LENGTH);
147 /* This is a cryptography library. Reject negative integers. */
148 if ((**p & 0x80) != 0)
149 return (MBEDTLS_ERR_ASN1_INVALID_LENGTH);
151 /* Skip leading zeros. */
152 while (len > 0 && **p == 0) {
153 ++(*p);
154 --len;
157 /* Reject integers that don't fit in an int. This code assumes that
158 * the int type has no padding bit. */
159 if (len > sizeof(int))
160 return (MBEDTLS_ERR_ASN1_INVALID_LENGTH);
161 if (len == sizeof(int) && (**p & 0x80) != 0)
162 return (MBEDTLS_ERR_ASN1_INVALID_LENGTH);
164 *val = 0;
165 while (len-- > 0) {
166 *val = (*val << 8) | **p;
167 (*p)++;
170 return (0);
173 int mbedtls_asn1_get_int(unsigned char **p,
174 const unsigned char *end,
175 int *val) {
176 return (asn1_get_tagged_int(p, end, MBEDTLS_ASN1_INTEGER, val));
179 int mbedtls_asn1_get_enum(unsigned char **p,
180 const unsigned char *end,
181 int *val) {
182 return (asn1_get_tagged_int(p, end, MBEDTLS_ASN1_ENUMERATED, val));
185 #if defined(MBEDTLS_BIGNUM_C)
186 int mbedtls_asn1_get_mpi(unsigned char **p,
187 const unsigned char *end,
188 mbedtls_mpi *X) {
189 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
190 size_t len;
192 if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0)
193 return (ret);
195 ret = mbedtls_mpi_read_binary(X, *p, len);
197 *p += len;
199 return (ret);
201 #endif /* MBEDTLS_BIGNUM_C */
203 int mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end,
204 mbedtls_asn1_bitstring *bs) {
205 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
207 /* Certificate type is a single byte bitstring */
208 if ((ret = mbedtls_asn1_get_tag(p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING)) != 0)
209 return (ret);
211 /* Check length, subtract one for actual bit string length */
212 if (bs->len < 1)
213 return (MBEDTLS_ERR_ASN1_OUT_OF_DATA);
214 bs->len -= 1;
216 /* Get number of unused bits, ensure unused bits <= 7 */
217 bs->unused_bits = **p;
218 if (bs->unused_bits > 7)
219 return (MBEDTLS_ERR_ASN1_INVALID_LENGTH);
220 (*p)++;
222 /* Get actual bitstring */
223 bs->p = *p;
224 *p += bs->len;
226 if (*p != end)
227 return (MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
229 return (0);
233 * Traverse an ASN.1 "SEQUENCE OF <tag>"
234 * and call a callback for each entry found.
236 int mbedtls_asn1_traverse_sequence_of(
237 unsigned char **p,
238 const unsigned char *end,
239 unsigned char tag_must_mask, unsigned char tag_must_val,
240 unsigned char tag_may_mask, unsigned char tag_may_val,
241 int (*cb)(void *ctx, int tag,
242 unsigned char *start, size_t len),
243 void *ctx) {
244 int ret;
245 size_t len;
247 /* Get main sequence tag */
248 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
249 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
250 return (ret);
253 if (*p + len != end)
254 return (MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
256 while (*p < end) {
257 unsigned char const tag = *(*p)++;
259 if ((tag & tag_must_mask) != tag_must_val)
260 return (MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
262 if ((ret = mbedtls_asn1_get_len(p, end, &len)) != 0)
263 return (ret);
265 if ((tag & tag_may_mask) == tag_may_val) {
266 if (cb != NULL) {
267 ret = cb(ctx, tag, *p, len);
268 if (ret != 0)
269 return (ret);
273 *p += len;
276 return (0);
280 * Get a bit string without unused bits
282 int mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end,
283 size_t *len) {
284 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
286 if ((ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_BIT_STRING)) != 0)
287 return (ret);
289 if (*len == 0)
290 return (MBEDTLS_ERR_ASN1_INVALID_DATA);
291 --(*len);
293 if (**p != 0)
294 return (MBEDTLS_ERR_ASN1_INVALID_DATA);
295 ++(*p);
297 return (0);
300 void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq) {
301 while (seq != NULL) {
302 mbedtls_asn1_sequence *next = seq->next;
303 mbedtls_platform_zeroize(seq, sizeof(*seq));
304 mbedtls_free(seq);
305 seq = next;
309 typedef struct {
310 int tag;
311 mbedtls_asn1_sequence *cur;
312 } asn1_get_sequence_of_cb_ctx_t;
314 static int asn1_get_sequence_of_cb(void *ctx,
315 int tag,
316 unsigned char *start,
317 size_t len) {
318 asn1_get_sequence_of_cb_ctx_t *cb_ctx =
319 (asn1_get_sequence_of_cb_ctx_t *) ctx;
320 mbedtls_asn1_sequence *cur =
321 cb_ctx->cur;
323 if (cur->buf.p != NULL) {
324 cur->next =
325 mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
327 if (cur->next == NULL)
328 return (MBEDTLS_ERR_ASN1_ALLOC_FAILED);
330 cur = cur->next;
333 cur->buf.p = start;
334 cur->buf.len = len;
335 cur->buf.tag = tag;
337 cb_ctx->cur = cur;
338 return (0);
342 * Parses and splits an ASN.1 "SEQUENCE OF <tag>"
344 int mbedtls_asn1_get_sequence_of(unsigned char **p,
345 const unsigned char *end,
346 mbedtls_asn1_sequence *cur,
347 int tag) {
348 asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur };
349 memset(cur, 0, sizeof(mbedtls_asn1_sequence));
350 return (mbedtls_asn1_traverse_sequence_of(
351 p, end, 0xFF, tag, 0, 0,
352 asn1_get_sequence_of_cb, &cb_ctx));
355 int mbedtls_asn1_get_alg(unsigned char **p,
356 const unsigned char *end,
357 mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params) {
358 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
359 size_t len;
361 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
362 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0)
363 return (ret);
365 if ((end - *p) < 1)
366 return (MBEDTLS_ERR_ASN1_OUT_OF_DATA);
368 alg->tag = **p;
369 end = *p + len;
371 if ((ret = mbedtls_asn1_get_tag(p, end, &alg->len, MBEDTLS_ASN1_OID)) != 0)
372 return (ret);
374 alg->p = *p;
375 *p += alg->len;
377 if (*p == end) {
378 mbedtls_platform_zeroize(params, sizeof(mbedtls_asn1_buf));
379 return (0);
382 params->tag = **p;
383 (*p)++;
385 if ((ret = mbedtls_asn1_get_len(p, end, &params->len)) != 0)
386 return (ret);
388 params->p = *p;
389 *p += params->len;
391 if (*p != end)
392 return (MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
394 return (0);
397 int mbedtls_asn1_get_alg_null(unsigned char **p,
398 const unsigned char *end,
399 mbedtls_asn1_buf *alg) {
400 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
401 mbedtls_asn1_buf params;
403 memset(&params, 0, sizeof(mbedtls_asn1_buf));
405 if ((ret = mbedtls_asn1_get_alg(p, end, alg, &params)) != 0)
406 return (ret);
408 if ((params.tag != MBEDTLS_ASN1_NULL && params.tag != 0) || params.len != 0)
409 return (MBEDTLS_ERR_ASN1_INVALID_DATA);
411 return (0);
414 void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *cur) {
415 if (cur == NULL)
416 return;
418 mbedtls_free(cur->oid.p);
419 mbedtls_free(cur->val.p);
421 mbedtls_platform_zeroize(cur, sizeof(mbedtls_asn1_named_data));
424 void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head) {
425 mbedtls_asn1_named_data *cur;
427 while ((cur = *head) != NULL) {
428 *head = cur->next;
429 mbedtls_asn1_free_named_data(cur);
430 mbedtls_free(cur);
434 mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(mbedtls_asn1_named_data *list,
435 const char *oid, size_t len) {
436 while (list != NULL) {
437 if (list->oid.len == len &&
438 memcmp(list->oid.p, oid, len) == 0) {
439 break;
442 list = list->next;
445 return (list);
448 #endif /* MBEDTLS_ASN1_PARSE_C */