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.
22 #if defined(MBEDTLS_ASN1_PARSE_C)
24 #include "mbedtls/asn1.h"
25 #include "mbedtls/platform_util.h"
26 #include "mbedtls/error.h"
30 #if defined(MBEDTLS_BIGNUM_C)
31 #include "mbedtls/bignum.h"
34 #if defined(MBEDTLS_PLATFORM_C)
35 #include "mbedtls/platform.h"
38 #define mbedtls_calloc calloc
39 #define mbedtls_free free
43 * ASN.1 DER decoding routines
45 int mbedtls_asn1_get_len(unsigned char **p
,
46 const unsigned char *end
,
49 return (MBEDTLS_ERR_ASN1_OUT_OF_DATA
);
51 if ((**p
& 0x80) == 0)
57 return (MBEDTLS_ERR_ASN1_OUT_OF_DATA
);
65 return (MBEDTLS_ERR_ASN1_OUT_OF_DATA
);
67 *len
= ((size_t)(*p
)[1] << 8) | (*p
)[2];
73 return (MBEDTLS_ERR_ASN1_OUT_OF_DATA
);
75 *len
= ((size_t)(*p
)[1] << 16) |
76 ((size_t)(*p
)[2] << 8) | (*p
)[3];
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];
90 return (MBEDTLS_ERR_ASN1_INVALID_LENGTH
);
94 if (*len
> (size_t)(end
- *p
))
95 return (MBEDTLS_ERR_ASN1_OUT_OF_DATA
);
100 int mbedtls_asn1_get_tag(unsigned char **p
,
101 const unsigned char *end
,
102 size_t *len
, int tag
) {
104 return (MBEDTLS_ERR_ASN1_OUT_OF_DATA
);
107 return (MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
);
111 return (mbedtls_asn1_get_len(p
, end
, len
));
114 int mbedtls_asn1_get_bool(unsigned char **p
,
115 const unsigned char *end
,
117 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
120 if ((ret
= mbedtls_asn1_get_tag(p
, end
, &len
, MBEDTLS_ASN1_BOOLEAN
)) != 0)
124 return (MBEDTLS_ERR_ASN1_INVALID_LENGTH
);
126 *val
= (**p
!= 0) ? 1 : 0;
132 static int asn1_get_tagged_int(unsigned char **p
,
133 const unsigned char *end
,
135 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
138 if ((ret
= mbedtls_asn1_get_tag(p
, end
, &len
, tag
)) != 0)
142 * len==0 is malformed (0 must be represented as 020100 for INTEGER,
143 * or 0A0100 for ENUMERATED tags
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) {
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
);
166 *val
= (*val
<< 8) | **p
;
173 int mbedtls_asn1_get_int(unsigned char **p
,
174 const unsigned char *end
,
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
,
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
,
189 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
192 if ((ret
= mbedtls_asn1_get_tag(p
, end
, &len
, MBEDTLS_ASN1_INTEGER
)) != 0)
195 ret
= mbedtls_mpi_read_binary(X
, *p
, len
);
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)
211 /* Check length, subtract one for actual bit string length */
213 return (MBEDTLS_ERR_ASN1_OUT_OF_DATA
);
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
);
222 /* Get actual bitstring */
227 return (MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
233 * Traverse an ASN.1 "SEQUENCE OF <tag>"
234 * and call a callback for each entry found.
236 int mbedtls_asn1_traverse_sequence_of(
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
),
247 /* Get main sequence tag */
248 if ((ret
= mbedtls_asn1_get_tag(p
, end
, &len
,
249 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
)) != 0) {
254 return (MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
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)
265 if ((tag
& tag_may_mask
) == tag_may_val
) {
267 ret
= cb(ctx
, tag
, *p
, len
);
280 * Get a bit string without unused bits
282 int mbedtls_asn1_get_bitstring_null(unsigned char **p
, const unsigned char *end
,
284 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
286 if ((ret
= mbedtls_asn1_get_tag(p
, end
, len
, MBEDTLS_ASN1_BIT_STRING
)) != 0)
290 return (MBEDTLS_ERR_ASN1_INVALID_DATA
);
294 return (MBEDTLS_ERR_ASN1_INVALID_DATA
);
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
));
311 mbedtls_asn1_sequence
*cur
;
312 } asn1_get_sequence_of_cb_ctx_t
;
314 static int asn1_get_sequence_of_cb(void *ctx
,
316 unsigned char *start
,
318 asn1_get_sequence_of_cb_ctx_t
*cb_ctx
=
319 (asn1_get_sequence_of_cb_ctx_t
*) ctx
;
320 mbedtls_asn1_sequence
*cur
=
323 if (cur
->buf
.p
!= NULL
) {
325 mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence
));
327 if (cur
->next
== NULL
)
328 return (MBEDTLS_ERR_ASN1_ALLOC_FAILED
);
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
,
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
;
361 if ((ret
= mbedtls_asn1_get_tag(p
, end
, &len
,
362 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
)) != 0)
366 return (MBEDTLS_ERR_ASN1_OUT_OF_DATA
);
371 if ((ret
= mbedtls_asn1_get_tag(p
, end
, &alg
->len
, MBEDTLS_ASN1_OID
)) != 0)
378 mbedtls_platform_zeroize(params
, sizeof(mbedtls_asn1_buf
));
385 if ((ret
= mbedtls_asn1_get_len(p
, end
, ¶ms
->len
)) != 0)
392 return (MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
);
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(¶ms
, 0, sizeof(mbedtls_asn1_buf
));
405 if ((ret
= mbedtls_asn1_get_alg(p
, end
, alg
, ¶ms
)) != 0)
408 if ((params
.tag
!= MBEDTLS_ASN1_NULL
&& params
.tag
!= 0) || params
.len
!= 0)
409 return (MBEDTLS_ERR_ASN1_INVALID_DATA
);
414 void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data
*cur
) {
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
) {
429 mbedtls_asn1_free_named_data(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) {
448 #endif /* MBEDTLS_ASN1_PARSE_C */