diff options
author | jsing <> | 2022-05-19 19:45:18 +0000 |
---|---|---|
committer | jsing <> | 2022-05-19 19:45:18 +0000 |
commit | 618f8e60b522b47730139a704cf3dfe94d5b6f86 (patch) | |
tree | a6fd01f764071f690704f8b6f83e59a21f6f7a3b /src | |
parent | 94f8e2dd8817ff74b89e103a09ba4b9b884f75ec (diff) | |
download | openbsd-618f8e60b522b47730139a704cf3dfe94d5b6f86.tar.gz openbsd-618f8e60b522b47730139a704cf3dfe94d5b6f86.tar.bz2 openbsd-618f8e60b522b47730139a704cf3dfe94d5b6f86.zip |
Reorder functions within file.
Order functions by use, moving public API to the bottom and utility
functions to the top. This makes the code more logical/readable, plus we
can remove all except one of the static function prototypes.
No functional change.
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/libcrypto/asn1/tasn_dec.c | 1232 |
1 files changed, 608 insertions, 624 deletions
diff --git a/src/lib/libcrypto/asn1/tasn_dec.c b/src/lib/libcrypto/asn1/tasn_dec.c index 79cbd4c75b..7583019aaa 100644 --- a/src/lib/libcrypto/asn1/tasn_dec.c +++ b/src/lib/libcrypto/asn1/tasn_dec.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: tasn_dec.c,v 1.71 2022/05/19 19:31:39 jsing Exp $ */ | 1 | /* $OpenBSD: tasn_dec.c,v 1.72 2022/05/19 19:45:18 jsing Exp $ */ |
2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | 2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
3 | * project 2000. | 3 | * project 2000. |
4 | */ | 4 | */ |
@@ -69,62 +69,568 @@ | |||
69 | #include "asn1_locl.h" | 69 | #include "asn1_locl.h" |
70 | #include "bytestring.h" | 70 | #include "bytestring.h" |
71 | 71 | ||
72 | /* Constructed types with a recursive definition (such as can be found in PKCS7) | 72 | /* |
73 | * Constructed types with a recursive definition (such as can be found in PKCS7) | ||
73 | * could eventually exceed the stack given malicious input with excessive | 74 | * could eventually exceed the stack given malicious input with excessive |
74 | * recursion. Therefore we limit the stack depth. | 75 | * recursion. Therefore we limit the stack depth. |
75 | */ | 76 | */ |
76 | #define ASN1_MAX_CONSTRUCTED_NEST 30 | 77 | #define ASN1_MAX_CONSTRUCTED_NEST 30 |
77 | 78 | ||
78 | static int asn1_check_eoc(CBS *cbs); | 79 | #ifndef ASN1_MAX_STRING_NEST |
79 | static int asn1_find_end(CBS *cbs, size_t length, char indefinite); | 80 | /* |
80 | 81 | * This determines how many levels of recursion are permitted in ASN.1 string | |
81 | static int asn1_collect(CBB *cbb, CBS *cbs, char indefinite, int expected_tag, | 82 | * types. If it is not limited stack overflows can occur. If set to zero no |
82 | int expected_class, int depth); | 83 | * recursion is allowed at all. Although zero should be adequate examples exist |
84 | * that require a value of 1. So 5 should be more than enough. | ||
85 | */ | ||
86 | #define ASN1_MAX_STRING_NEST 5 | ||
87 | #endif | ||
83 | 88 | ||
84 | static int asn1_template_ex_d2i(ASN1_VALUE **pval, CBS *cbs, | 89 | static int asn1_template_ex_d2i(ASN1_VALUE **pval, CBS *cbs, |
85 | const ASN1_TEMPLATE *tt, char optional, int depth); | 90 | const ASN1_TEMPLATE *tt, char optional, int depth); |
86 | static int asn1_template_noexp_d2i(ASN1_VALUE **pval, CBS *cbs, | ||
87 | const ASN1_TEMPLATE *tt, char optional, int depth); | ||
88 | static int asn1_d2i_ex_mstring(ASN1_VALUE **pval, CBS *CBS, | ||
89 | const ASN1_ITEM *it, int tag_number, int tag_class, char optional); | ||
90 | static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, CBS *cbs, | ||
91 | const ASN1_ITEM *it, int tag_number, int tag_class, char optional); | ||
92 | static int asn1_ex_c2i(ASN1_VALUE **pval, CBS *content, int utype, | ||
93 | const ASN1_ITEM *it); | ||
94 | 91 | ||
95 | static int asn1_check_tag(CBS *cbs, size_t *out_len, int *out_tag, | 92 | static int |
96 | uint8_t *out_class, char *out_indefinite, char *out_constructed, | 93 | asn1_check_eoc(CBS *cbs) |
97 | int expected_tag, int expected_class, char optional); | 94 | { |
95 | uint16_t eoc; | ||
98 | 96 | ||
99 | ASN1_VALUE * | 97 | if (!CBS_peek_u16(cbs, &eoc)) |
100 | ASN1_item_d2i(ASN1_VALUE **pval, const unsigned char **in, long inlen, | 98 | return 0; |
99 | if (eoc != 0) | ||
100 | return 0; | ||
101 | |||
102 | return CBS_skip(cbs, 2); | ||
103 | } | ||
104 | |||
105 | static int | ||
106 | asn1_check_tag(CBS *cbs, size_t *out_len, int *out_tag, uint8_t *out_class, | ||
107 | char *out_indefinite, char *out_constructed, int expected_tag, | ||
108 | int expected_class, char optional) | ||
109 | { | ||
110 | int constructed, indefinite; | ||
111 | uint32_t tag_number; | ||
112 | uint8_t tag_class; | ||
113 | size_t length; | ||
114 | |||
115 | if (out_len != NULL) | ||
116 | *out_len = 0; | ||
117 | if (out_tag != NULL) | ||
118 | *out_tag = 0; | ||
119 | if (out_class != NULL) | ||
120 | *out_class = 0; | ||
121 | if (out_indefinite != NULL) | ||
122 | *out_indefinite = 0; | ||
123 | if (out_constructed != NULL) | ||
124 | *out_constructed = 0; | ||
125 | |||
126 | if (!asn1_get_identifier_cbs(cbs, 0, &tag_class, &constructed, | ||
127 | &tag_number)) { | ||
128 | ASN1error(ASN1_R_BAD_OBJECT_HEADER); | ||
129 | return 0; | ||
130 | } | ||
131 | if (expected_tag >= 0) { | ||
132 | if (expected_tag != tag_number || | ||
133 | expected_class != tag_class << 6) { | ||
134 | /* Indicate missing type if this is OPTIONAL. */ | ||
135 | if (optional) | ||
136 | return -1; | ||
137 | |||
138 | ASN1error(ASN1_R_WRONG_TAG); | ||
139 | return 0; | ||
140 | } | ||
141 | } | ||
142 | if (!asn1_get_length_cbs(cbs, 0, &indefinite, &length)) { | ||
143 | ASN1error(ASN1_R_BAD_OBJECT_HEADER); | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | /* Indefinite length can only be used with constructed encoding. */ | ||
148 | if (indefinite && !constructed) { | ||
149 | ASN1error(ASN1_R_BAD_OBJECT_HEADER); | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | if (!indefinite && CBS_len(cbs) < length) { | ||
154 | ASN1error(ASN1_R_TOO_LONG); | ||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | if (tag_number > INT_MAX) { | ||
159 | ASN1error(ASN1_R_TOO_LONG); | ||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | if (indefinite) | ||
164 | length = CBS_len(cbs); | ||
165 | |||
166 | if (out_len != NULL) | ||
167 | *out_len = length; | ||
168 | if (out_tag != NULL) | ||
169 | *out_tag = tag_number; | ||
170 | if (out_class != NULL) | ||
171 | *out_class = tag_class << 6; | ||
172 | if (out_indefinite != NULL && indefinite) | ||
173 | *out_indefinite = 1 << 0; | ||
174 | if (out_constructed != NULL && constructed) | ||
175 | *out_constructed = 1 << 5; | ||
176 | |||
177 | return 1; | ||
178 | } | ||
179 | |||
180 | /* Collect the contents from a constructed ASN.1 object. */ | ||
181 | static int | ||
182 | asn1_collect(CBB *cbb, CBS *cbs, char indefinite, int expected_tag, | ||
183 | int expected_class, int depth) | ||
184 | { | ||
185 | char constructed; | ||
186 | size_t length; | ||
187 | CBS content; | ||
188 | int need_eoc; | ||
189 | |||
190 | if (depth > ASN1_MAX_STRING_NEST) { | ||
191 | ASN1error(ASN1_R_NESTED_ASN1_STRING); | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | need_eoc = indefinite; | ||
196 | |||
197 | while (CBS_len(cbs) > 0) { | ||
198 | if (asn1_check_eoc(cbs)) { | ||
199 | if (!need_eoc) { | ||
200 | ASN1error(ASN1_R_UNEXPECTED_EOC); | ||
201 | return 0; | ||
202 | } | ||
203 | return 1; | ||
204 | } | ||
205 | if (!asn1_check_tag(cbs, &length, NULL, NULL, &indefinite, | ||
206 | &constructed, expected_tag, expected_class, 0)) { | ||
207 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | if (constructed) { | ||
212 | if (!asn1_collect(cbb, cbs, indefinite, expected_tag, | ||
213 | expected_class, depth + 1)) | ||
214 | return 0; | ||
215 | continue; | ||
216 | } | ||
217 | |||
218 | if (!CBS_get_bytes(cbs, &content, length)) { | ||
219 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
220 | return 0; | ||
221 | } | ||
222 | if (!CBB_add_bytes(cbb, CBS_data(&content), CBS_len(&content))) | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | if (need_eoc) { | ||
227 | ASN1error(ASN1_R_MISSING_EOC); | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | return 1; | ||
232 | } | ||
233 | |||
234 | /* Find the end of an ASN.1 object. */ | ||
235 | static int | ||
236 | asn1_find_end(CBS *cbs, size_t length, char indefinite) | ||
237 | { | ||
238 | size_t eoc_count; | ||
239 | |||
240 | if (!indefinite) { | ||
241 | if (!CBS_skip(cbs, length)) { | ||
242 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
243 | return 0; | ||
244 | } | ||
245 | return 1; | ||
246 | } | ||
247 | |||
248 | eoc_count = 1; | ||
249 | |||
250 | while (CBS_len(cbs) > 0) { | ||
251 | if (asn1_check_eoc(cbs)) { | ||
252 | if (--eoc_count == 0) | ||
253 | break; | ||
254 | continue; | ||
255 | } | ||
256 | if (!asn1_check_tag(cbs, &length, NULL, NULL, | ||
257 | &indefinite, NULL, -1, 0, 0)) { | ||
258 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
259 | return 0; | ||
260 | } | ||
261 | if (indefinite) { | ||
262 | eoc_count++; | ||
263 | continue; | ||
264 | } | ||
265 | if (!CBS_skip(cbs, length)) | ||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | if (eoc_count > 0) { | ||
270 | ASN1error(ASN1_R_MISSING_EOC); | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | return 1; | ||
275 | } | ||
276 | |||
277 | static int | ||
278 | asn1_ex_c2i_primitive(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it) | ||
279 | { | ||
280 | ASN1_STRING *stmp; | ||
281 | ASN1_INTEGER **tint; | ||
282 | ASN1_BOOLEAN *tbool; | ||
283 | uint8_t u8val; | ||
284 | int ret = 0; | ||
285 | |||
286 | if (it->funcs != NULL) | ||
287 | return 0; | ||
288 | |||
289 | if (CBS_len(content) > INT_MAX) | ||
290 | return 0; | ||
291 | |||
292 | switch (utype) { | ||
293 | case V_ASN1_OBJECT: | ||
294 | if (!c2i_ASN1_OBJECT_cbs((ASN1_OBJECT **)pval, content)) | ||
295 | goto err; | ||
296 | break; | ||
297 | |||
298 | case V_ASN1_NULL: | ||
299 | if (CBS_len(content) != 0) { | ||
300 | ASN1error(ASN1_R_NULL_IS_WRONG_LENGTH); | ||
301 | goto err; | ||
302 | } | ||
303 | *pval = (ASN1_VALUE *)1; | ||
304 | break; | ||
305 | |||
306 | case V_ASN1_BOOLEAN: | ||
307 | tbool = (ASN1_BOOLEAN *)pval; | ||
308 | if (CBS_len(content) != 1) { | ||
309 | ASN1error(ASN1_R_BOOLEAN_IS_WRONG_LENGTH); | ||
310 | goto err; | ||
311 | } | ||
312 | if (!CBS_get_u8(content, &u8val)) | ||
313 | goto err; | ||
314 | *tbool = u8val; | ||
315 | break; | ||
316 | |||
317 | case V_ASN1_BIT_STRING: | ||
318 | if (!c2i_ASN1_BIT_STRING_cbs((ASN1_BIT_STRING **)pval, content)) | ||
319 | goto err; | ||
320 | break; | ||
321 | |||
322 | case V_ASN1_INTEGER: | ||
323 | case V_ASN1_ENUMERATED: | ||
324 | tint = (ASN1_INTEGER **)pval; | ||
325 | if (!c2i_ASN1_INTEGER_cbs(tint, content)) | ||
326 | goto err; | ||
327 | /* Fixup type to match the expected form */ | ||
328 | (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); | ||
329 | break; | ||
330 | |||
331 | case V_ASN1_OCTET_STRING: | ||
332 | case V_ASN1_NUMERICSTRING: | ||
333 | case V_ASN1_PRINTABLESTRING: | ||
334 | case V_ASN1_T61STRING: | ||
335 | case V_ASN1_VIDEOTEXSTRING: | ||
336 | case V_ASN1_IA5STRING: | ||
337 | case V_ASN1_UTCTIME: | ||
338 | case V_ASN1_GENERALIZEDTIME: | ||
339 | case V_ASN1_GRAPHICSTRING: | ||
340 | case V_ASN1_VISIBLESTRING: | ||
341 | case V_ASN1_GENERALSTRING: | ||
342 | case V_ASN1_UNIVERSALSTRING: | ||
343 | case V_ASN1_BMPSTRING: | ||
344 | case V_ASN1_UTF8STRING: | ||
345 | case V_ASN1_OTHER: | ||
346 | case V_ASN1_SET: | ||
347 | case V_ASN1_SEQUENCE: | ||
348 | default: | ||
349 | if (utype == V_ASN1_BMPSTRING && (CBS_len(content) & 1)) { | ||
350 | ASN1error(ASN1_R_BMPSTRING_IS_WRONG_LENGTH); | ||
351 | goto err; | ||
352 | } | ||
353 | if (utype == V_ASN1_UNIVERSALSTRING && (CBS_len(content) & 3)) { | ||
354 | ASN1error(ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH); | ||
355 | goto err; | ||
356 | } | ||
357 | /* All based on ASN1_STRING and handled the same way. */ | ||
358 | if (*pval == NULL) { | ||
359 | if ((stmp = ASN1_STRING_type_new(utype)) == NULL) { | ||
360 | ASN1error(ERR_R_MALLOC_FAILURE); | ||
361 | goto err; | ||
362 | } | ||
363 | *pval = (ASN1_VALUE *)stmp; | ||
364 | } else { | ||
365 | stmp = (ASN1_STRING *)*pval; | ||
366 | stmp->type = utype; | ||
367 | } | ||
368 | if (!ASN1_STRING_set(stmp, CBS_data(content), CBS_len(content))) { | ||
369 | ASN1_STRING_free(stmp); | ||
370 | *pval = NULL; | ||
371 | goto err; | ||
372 | } | ||
373 | break; | ||
374 | } | ||
375 | |||
376 | ret = 1; | ||
377 | |||
378 | err: | ||
379 | return ret; | ||
380 | } | ||
381 | |||
382 | static int | ||
383 | asn1_ex_c2i_any(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it) | ||
384 | { | ||
385 | ASN1_TYPE *atype; | ||
386 | |||
387 | if (it->utype != V_ASN1_ANY || it->funcs != NULL) | ||
388 | return 0; | ||
389 | |||
390 | if (*pval != NULL) { | ||
391 | ASN1_TYPE_free((ASN1_TYPE *)*pval); | ||
392 | *pval = NULL; | ||
393 | } | ||
394 | |||
395 | if ((atype = ASN1_TYPE_new()) == NULL) | ||
396 | return 0; | ||
397 | |||
398 | if (!asn1_ex_c2i_primitive(&atype->value.asn1_value, content, utype, it)) { | ||
399 | ASN1_TYPE_free(atype); | ||
400 | return 0; | ||
401 | } | ||
402 | atype->type = utype; | ||
403 | |||
404 | /* Fix up value for ASN.1 NULL. */ | ||
405 | if (atype->type == V_ASN1_NULL) | ||
406 | atype->value.ptr = NULL; | ||
407 | |||
408 | *pval = (ASN1_VALUE *)atype; | ||
409 | |||
410 | return 1; | ||
411 | } | ||
412 | |||
413 | static int | ||
414 | asn1_ex_c2i(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it) | ||
415 | { | ||
416 | if (CBS_len(content) > INT_MAX) | ||
417 | return 0; | ||
418 | |||
419 | if (it->funcs != NULL) { | ||
420 | const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; | ||
421 | char free_content = 0; | ||
422 | |||
423 | if (pf->prim_c2i == NULL) | ||
424 | return 0; | ||
425 | |||
426 | return pf->prim_c2i(pval, CBS_data(content), CBS_len(content), | ||
427 | utype, &free_content, it); | ||
428 | } | ||
429 | |||
430 | if (it->utype == V_ASN1_ANY) | ||
431 | return asn1_ex_c2i_any(pval, content, utype, it); | ||
432 | |||
433 | return asn1_ex_c2i_primitive(pval, content, utype, it); | ||
434 | } | ||
435 | |||
436 | /* | ||
437 | * Decode ASN.1 content into a primitive type. There are three possible forms - | ||
438 | * a SEQUENCE/SET/OTHER that is stored verbatim (including the ASN.1 tag and | ||
439 | * length octets), constructed objects and non-constructed objects. In the | ||
440 | * first two cases indefinite length is permitted, which we may need to handle. | ||
441 | * When this function is called the *cbs should reference the start of the | ||
442 | * ASN.1 object (i.e. the tag/length header), while *cbs_object should | ||
443 | * reference the start of the object contents (i.e. after the tag/length | ||
444 | * header. Additionally, the *cbs_object offset should be relative to the | ||
445 | * ASN.1 object being parsed. On success the *cbs will point at the octet | ||
446 | * after the object. | ||
447 | */ | ||
448 | static int | ||
449 | asn1_d2i_ex_primitive_content(ASN1_VALUE **pval, CBS *cbs, CBS *cbs_object, | ||
450 | int utype, char constructed, char indefinite, size_t length, | ||
101 | const ASN1_ITEM *it) | 451 | const ASN1_ITEM *it) |
102 | { | 452 | { |
103 | ASN1_VALUE *ptmpval = NULL; | 453 | CBS cbs_content, cbs_initial; |
454 | uint8_t *data = NULL; | ||
455 | size_t data_len = 0; | ||
456 | CBB cbb; | ||
457 | int ret = 0; | ||
104 | 458 | ||
105 | if (pval == NULL) | 459 | memset(&cbb, 0, sizeof(cbb)); |
106 | pval = &ptmpval; | ||
107 | if (ASN1_item_ex_d2i(pval, in, inlen, it, -1, 0, 0, 0) <= 0) | ||
108 | return NULL; | ||
109 | 460 | ||
110 | return *pval; | 461 | CBS_dup(cbs, &cbs_initial); |
462 | CBS_init(&cbs_content, NULL, 0); | ||
463 | |||
464 | /* XXX - check primitive vs constructed based on utype. */ | ||
465 | |||
466 | /* SEQUENCE and SET must be constructed. */ | ||
467 | if ((utype == V_ASN1_SEQUENCE || utype == V_ASN1_SET) && !constructed) { | ||
468 | ASN1error(ASN1_R_TYPE_NOT_CONSTRUCTED); | ||
469 | goto err; | ||
470 | } | ||
471 | |||
472 | /* SEQUENCE, SET and "OTHER" are left in encoded form. */ | ||
473 | if (utype == V_ASN1_SEQUENCE || utype == V_ASN1_SET || | ||
474 | utype == V_ASN1_OTHER) { | ||
475 | if (!asn1_find_end(cbs_object, length, indefinite)) | ||
476 | goto err; | ||
477 | if (!CBS_get_bytes(&cbs_initial, &cbs_content, | ||
478 | CBS_offset(cbs_object))) | ||
479 | goto err; | ||
480 | } else if (constructed) { | ||
481 | /* | ||
482 | * Should really check the internal tags are correct but | ||
483 | * some things may get this wrong. The relevant specs | ||
484 | * say that constructed string types should be OCTET STRINGs | ||
485 | * internally irrespective of the type. So instead just check | ||
486 | * for UNIVERSAL class and ignore the tag. | ||
487 | */ | ||
488 | if (!CBB_init(&cbb, 0)) | ||
489 | goto err; | ||
490 | if (!asn1_collect(&cbb, cbs_object, indefinite, -1, | ||
491 | V_ASN1_UNIVERSAL, 0)) | ||
492 | goto err; | ||
493 | if (!CBB_finish(&cbb, &data, &data_len)) | ||
494 | goto err; | ||
495 | |||
496 | CBS_init(&cbs_content, data, data_len); | ||
497 | } else { | ||
498 | if (!CBS_get_bytes(cbs_object, &cbs_content, length)) | ||
499 | goto err; | ||
500 | } | ||
501 | |||
502 | if (!asn1_ex_c2i(pval, &cbs_content, utype, it)) | ||
503 | goto err; | ||
504 | |||
505 | if (!CBS_skip(cbs, CBS_offset(cbs_object))) | ||
506 | goto err; | ||
507 | |||
508 | ret = 1; | ||
509 | |||
510 | err: | ||
511 | CBB_cleanup(&cbb); | ||
512 | freezero(data, data_len); | ||
513 | |||
514 | return ret; | ||
111 | } | 515 | } |
112 | 516 | ||
113 | int | 517 | static int |
114 | ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, | 518 | asn1_d2i_ex_any(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, |
115 | const ASN1_TEMPLATE *tt) | 519 | int tag_number, int tag_class, char optional) |
116 | { | 520 | { |
117 | CBS cbs; | 521 | char constructed, indefinite; |
522 | unsigned char object_class; | ||
523 | int object_type; | ||
524 | CBS cbs_object; | ||
525 | size_t length; | ||
526 | |||
527 | CBS_init(&cbs_object, CBS_data(cbs), CBS_len(cbs)); | ||
528 | |||
529 | if (it->utype != V_ASN1_ANY) | ||
530 | return 0; | ||
531 | |||
532 | if (tag_number >= 0) { | ||
533 | ASN1error(ASN1_R_ILLEGAL_TAGGED_ANY); | ||
534 | return 0; | ||
535 | } | ||
536 | if (optional) { | ||
537 | ASN1error(ASN1_R_ILLEGAL_OPTIONAL_ANY); | ||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | /* Determine type from ASN.1 tag. */ | ||
542 | if (asn1_check_tag(&cbs_object, &length, &object_type, &object_class, | ||
543 | &indefinite, &constructed, -1, 0, 0) != 1) { | ||
544 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
545 | return 0; | ||
546 | } | ||
547 | if (object_class != V_ASN1_UNIVERSAL) | ||
548 | object_type = V_ASN1_OTHER; | ||
549 | |||
550 | return asn1_d2i_ex_primitive_content(pval, cbs, &cbs_object, object_type, | ||
551 | constructed, indefinite, length, it); | ||
552 | } | ||
553 | |||
554 | static int | ||
555 | asn1_d2i_ex_mstring(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, | ||
556 | int tag_number, int tag_class, char optional) | ||
557 | { | ||
558 | char constructed, indefinite; | ||
559 | unsigned char object_class; | ||
560 | int object_tag; | ||
561 | CBS cbs_object; | ||
562 | size_t length; | ||
563 | |||
564 | CBS_init(&cbs_object, CBS_data(cbs), CBS_len(cbs)); | ||
565 | |||
566 | /* | ||
567 | * It never makes sense for multi-strings to have implicit tagging, so | ||
568 | * if tag_number != -1, then this looks like an error in the template. | ||
569 | */ | ||
570 | if (tag_number != -1) { | ||
571 | ASN1error(ASN1_R_BAD_TEMPLATE); | ||
572 | return 0; | ||
573 | } | ||
574 | |||
575 | if (asn1_check_tag(&cbs_object, &length, &object_tag, &object_class, | ||
576 | &indefinite, &constructed, -1, 0, 1) != 1) { | ||
577 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
578 | return 0; | ||
579 | } | ||
580 | |||
581 | /* Class must be UNIVERSAL. */ | ||
582 | if (object_class != V_ASN1_UNIVERSAL) { | ||
583 | if (optional) | ||
584 | return -1; | ||
585 | ASN1error(ASN1_R_MSTRING_NOT_UNIVERSAL); | ||
586 | return 0; | ||
587 | } | ||
588 | /* Check tag matches bit map. */ | ||
589 | if ((ASN1_tag2bit(object_tag) & it->utype) == 0) { | ||
590 | if (optional) | ||
591 | return -1; | ||
592 | ASN1error(ASN1_R_MSTRING_WRONG_TAG); | ||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | return asn1_d2i_ex_primitive_content(pval, cbs, &cbs_object, | ||
597 | object_tag, constructed, indefinite, length, it); | ||
598 | } | ||
599 | |||
600 | static int | ||
601 | asn1_d2i_ex_primitive(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, | ||
602 | int tag_number, int tag_class, char optional) | ||
603 | { | ||
604 | CBS cbs_object; | ||
605 | char constructed, indefinite; | ||
606 | int utype = it->utype; | ||
607 | size_t length; | ||
118 | int ret; | 608 | int ret; |
119 | 609 | ||
120 | if (len < 0) | 610 | CBS_init(&cbs_object, CBS_data(cbs), CBS_len(cbs)); |
611 | |||
612 | if (it->itype == ASN1_ITYPE_MSTRING) | ||
121 | return 0; | 613 | return 0; |
122 | 614 | ||
123 | CBS_init(&cbs, *in, len); | 615 | if (it->utype == V_ASN1_ANY) |
124 | if ((ret = asn1_template_ex_d2i(pval, &cbs, tt, 0, 0)) == 1) | 616 | return asn1_d2i_ex_any(pval, cbs, it, tag_number, tag_class, optional); |
125 | *in = CBS_data(&cbs); | ||
126 | 617 | ||
127 | return ret; | 618 | if (tag_number == -1) { |
619 | tag_number = it->utype; | ||
620 | tag_class = V_ASN1_UNIVERSAL; | ||
621 | } | ||
622 | |||
623 | ret = asn1_check_tag(&cbs_object, &length, NULL, NULL, &indefinite, | ||
624 | &constructed, tag_number, tag_class, optional); | ||
625 | if (ret == -1) | ||
626 | return -1; | ||
627 | if (ret != 1) { | ||
628 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
629 | return 0; | ||
630 | } | ||
631 | |||
632 | return asn1_d2i_ex_primitive_content(pval, cbs, &cbs_object, utype, | ||
633 | constructed, indefinite, length, it); | ||
128 | } | 634 | } |
129 | 635 | ||
130 | static int | 636 | static int |
@@ -468,94 +974,6 @@ asn1_item_ex_d2i(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, | |||
468 | return 0; | 974 | return 0; |
469 | } | 975 | } |
470 | 976 | ||
471 | int | ||
472 | ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long inlen, | ||
473 | const ASN1_ITEM *it, int tag_number, int tag_class, char optional, | ||
474 | ASN1_TLC *ctx) | ||
475 | { | ||
476 | CBS cbs; | ||
477 | int ret; | ||
478 | |||
479 | if (inlen < 0) | ||
480 | return 0; | ||
481 | |||
482 | CBS_init(&cbs, *in, inlen); | ||
483 | |||
484 | if ((ret = asn1_item_ex_d2i(pval, &cbs, it, tag_number, tag_class, | ||
485 | optional, 0)) == 1) | ||
486 | *in = CBS_data(&cbs); | ||
487 | |||
488 | return ret; | ||
489 | } | ||
490 | |||
491 | static int | ||
492 | asn1_template_ex_d2i(ASN1_VALUE **pval, CBS *cbs, const ASN1_TEMPLATE *tt, | ||
493 | char optional, int depth) | ||
494 | { | ||
495 | CBS cbs_exp, cbs_exp_content; | ||
496 | char constructed, indefinite; | ||
497 | size_t length; | ||
498 | int ret; | ||
499 | |||
500 | if (pval == NULL) | ||
501 | return 0; | ||
502 | |||
503 | /* Check if EXPLICIT tag is expected. */ | ||
504 | if ((tt->flags & ASN1_TFLG_EXPTAG) == 0) | ||
505 | return asn1_template_noexp_d2i(pval, cbs, tt, optional, depth); | ||
506 | |||
507 | CBS_init(&cbs_exp, CBS_data(cbs), CBS_len(cbs)); | ||
508 | |||
509 | /* Read ASN.1 header for EXPLICIT tagged object. */ | ||
510 | ret = asn1_check_tag(&cbs_exp, &length, NULL, NULL, &indefinite, | ||
511 | &constructed, tt->tag, tt->flags & ASN1_TFLG_TAG_CLASS, optional); | ||
512 | if (ret == -1) | ||
513 | return -1; | ||
514 | if (ret != 1) { | ||
515 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
516 | return 0; | ||
517 | } | ||
518 | |||
519 | if (!constructed) { | ||
520 | ASN1error(ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); | ||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | if (indefinite) { | ||
525 | CBS_init(&cbs_exp_content, CBS_data(&cbs_exp), CBS_len(&cbs_exp)); | ||
526 | } else { | ||
527 | if (!CBS_get_bytes(&cbs_exp, &cbs_exp_content, length)) | ||
528 | goto err; | ||
529 | } | ||
530 | |||
531 | if ((ret = asn1_template_noexp_d2i(pval, &cbs_exp_content, tt, 0, | ||
532 | depth)) != 1) { | ||
533 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
534 | return 0; | ||
535 | } | ||
536 | |||
537 | if (indefinite) { | ||
538 | if (!asn1_check_eoc(&cbs_exp_content)) { | ||
539 | ASN1error(ASN1_R_MISSING_EOC); | ||
540 | goto err; | ||
541 | } | ||
542 | if (!CBS_skip(&cbs_exp, CBS_offset(&cbs_exp_content))) | ||
543 | goto err; | ||
544 | } else if (CBS_len(&cbs_exp_content) != 0) { | ||
545 | ASN1error(ASN1_R_SEQUENCE_LENGTH_MISMATCH); | ||
546 | goto err; | ||
547 | } | ||
548 | |||
549 | if (!CBS_skip(cbs, CBS_offset(&cbs_exp))) | ||
550 | goto err; | ||
551 | |||
552 | return 1; | ||
553 | |||
554 | err: | ||
555 | ASN1_template_free(pval, tt); | ||
556 | return 0; | ||
557 | } | ||
558 | |||
559 | static void | 977 | static void |
560 | asn1_template_stack_of_free(STACK_OF(ASN1_VALUE) *avals, const ASN1_TEMPLATE *tt) { | 978 | asn1_template_stack_of_free(STACK_OF(ASN1_VALUE) *avals, const ASN1_TEMPLATE *tt) { |
561 | ASN1_VALUE *aval; | 979 | ASN1_VALUE *aval; |
@@ -712,195 +1130,27 @@ asn1_template_noexp_d2i(ASN1_VALUE **pval, CBS *cbs, const ASN1_TEMPLATE *tt, | |||
712 | return 0; | 1130 | return 0; |
713 | } | 1131 | } |
714 | 1132 | ||
715 | /* | ||
716 | * Decode ASN.1 content into a primitive type. There are three possible forms - | ||
717 | * a SEQUENCE/SET/OTHER that is stored verbatim (including the ASN.1 tag and | ||
718 | * length octets), constructed objects and non-constructed objects. In the | ||
719 | * first two cases indefinite length is permitted, which we may need to handle. | ||
720 | * When this function is called the *cbs should reference the start of the | ||
721 | * ASN.1 object (i.e. the tag/length header), while *cbs_object should | ||
722 | * reference the start of the object contents (i.e. after the tag/length | ||
723 | * header. Additionally, the *cbs_object offset should be relative to the | ||
724 | * ASN.1 object being parsed. On success the *cbs will point at the octet | ||
725 | * after the object. | ||
726 | */ | ||
727 | static int | ||
728 | asn1_d2i_ex_primitive_content(ASN1_VALUE **pval, CBS *cbs, CBS *cbs_object, | ||
729 | int utype, char constructed, char indefinite, size_t length, | ||
730 | const ASN1_ITEM *it) | ||
731 | { | ||
732 | CBS cbs_content, cbs_initial; | ||
733 | uint8_t *data = NULL; | ||
734 | size_t data_len = 0; | ||
735 | CBB cbb; | ||
736 | int ret = 0; | ||
737 | |||
738 | memset(&cbb, 0, sizeof(cbb)); | ||
739 | |||
740 | CBS_dup(cbs, &cbs_initial); | ||
741 | CBS_init(&cbs_content, NULL, 0); | ||
742 | |||
743 | /* XXX - check primitive vs constructed based on utype. */ | ||
744 | |||
745 | /* SEQUENCE and SET must be constructed. */ | ||
746 | if ((utype == V_ASN1_SEQUENCE || utype == V_ASN1_SET) && !constructed) { | ||
747 | ASN1error(ASN1_R_TYPE_NOT_CONSTRUCTED); | ||
748 | goto err; | ||
749 | } | ||
750 | |||
751 | /* SEQUENCE, SET and "OTHER" are left in encoded form. */ | ||
752 | if (utype == V_ASN1_SEQUENCE || utype == V_ASN1_SET || | ||
753 | utype == V_ASN1_OTHER) { | ||
754 | if (!asn1_find_end(cbs_object, length, indefinite)) | ||
755 | goto err; | ||
756 | if (!CBS_get_bytes(&cbs_initial, &cbs_content, | ||
757 | CBS_offset(cbs_object))) | ||
758 | goto err; | ||
759 | } else if (constructed) { | ||
760 | /* | ||
761 | * Should really check the internal tags are correct but | ||
762 | * some things may get this wrong. The relevant specs | ||
763 | * say that constructed string types should be OCTET STRINGs | ||
764 | * internally irrespective of the type. So instead just check | ||
765 | * for UNIVERSAL class and ignore the tag. | ||
766 | */ | ||
767 | if (!CBB_init(&cbb, 0)) | ||
768 | goto err; | ||
769 | if (!asn1_collect(&cbb, cbs_object, indefinite, -1, | ||
770 | V_ASN1_UNIVERSAL, 0)) | ||
771 | goto err; | ||
772 | if (!CBB_finish(&cbb, &data, &data_len)) | ||
773 | goto err; | ||
774 | |||
775 | CBS_init(&cbs_content, data, data_len); | ||
776 | } else { | ||
777 | if (!CBS_get_bytes(cbs_object, &cbs_content, length)) | ||
778 | goto err; | ||
779 | } | ||
780 | |||
781 | if (!asn1_ex_c2i(pval, &cbs_content, utype, it)) | ||
782 | goto err; | ||
783 | |||
784 | if (!CBS_skip(cbs, CBS_offset(cbs_object))) | ||
785 | goto err; | ||
786 | |||
787 | ret = 1; | ||
788 | |||
789 | err: | ||
790 | CBB_cleanup(&cbb); | ||
791 | freezero(data, data_len); | ||
792 | |||
793 | return ret; | ||
794 | } | ||
795 | |||
796 | static int | ||
797 | asn1_d2i_ex_any(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, | ||
798 | int tag_number, int tag_class, char optional) | ||
799 | { | ||
800 | char constructed, indefinite; | ||
801 | unsigned char object_class; | ||
802 | int object_type; | ||
803 | CBS cbs_object; | ||
804 | size_t length; | ||
805 | |||
806 | CBS_init(&cbs_object, CBS_data(cbs), CBS_len(cbs)); | ||
807 | |||
808 | if (it->utype != V_ASN1_ANY) | ||
809 | return 0; | ||
810 | |||
811 | if (tag_number >= 0) { | ||
812 | ASN1error(ASN1_R_ILLEGAL_TAGGED_ANY); | ||
813 | return 0; | ||
814 | } | ||
815 | if (optional) { | ||
816 | ASN1error(ASN1_R_ILLEGAL_OPTIONAL_ANY); | ||
817 | return 0; | ||
818 | } | ||
819 | |||
820 | /* Determine type from ASN.1 tag. */ | ||
821 | if (asn1_check_tag(&cbs_object, &length, &object_type, &object_class, | ||
822 | &indefinite, &constructed, -1, 0, 0) != 1) { | ||
823 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
824 | return 0; | ||
825 | } | ||
826 | if (object_class != V_ASN1_UNIVERSAL) | ||
827 | object_type = V_ASN1_OTHER; | ||
828 | |||
829 | return asn1_d2i_ex_primitive_content(pval, cbs, &cbs_object, object_type, | ||
830 | constructed, indefinite, length, it); | ||
831 | } | ||
832 | |||
833 | static int | ||
834 | asn1_d2i_ex_mstring(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, | ||
835 | int tag_number, int tag_class, char optional) | ||
836 | { | ||
837 | char constructed, indefinite; | ||
838 | unsigned char object_class; | ||
839 | int object_tag; | ||
840 | CBS cbs_object; | ||
841 | size_t length; | ||
842 | |||
843 | CBS_init(&cbs_object, CBS_data(cbs), CBS_len(cbs)); | ||
844 | |||
845 | /* | ||
846 | * It never makes sense for multi-strings to have implicit tagging, so | ||
847 | * if tag_number != -1, then this looks like an error in the template. | ||
848 | */ | ||
849 | if (tag_number != -1) { | ||
850 | ASN1error(ASN1_R_BAD_TEMPLATE); | ||
851 | return 0; | ||
852 | } | ||
853 | |||
854 | if (asn1_check_tag(&cbs_object, &length, &object_tag, &object_class, | ||
855 | &indefinite, &constructed, -1, 0, 1) != 1) { | ||
856 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
857 | return 0; | ||
858 | } | ||
859 | |||
860 | /* Class must be UNIVERSAL. */ | ||
861 | if (object_class != V_ASN1_UNIVERSAL) { | ||
862 | if (optional) | ||
863 | return -1; | ||
864 | ASN1error(ASN1_R_MSTRING_NOT_UNIVERSAL); | ||
865 | return 0; | ||
866 | } | ||
867 | /* Check tag matches bit map. */ | ||
868 | if ((ASN1_tag2bit(object_tag) & it->utype) == 0) { | ||
869 | if (optional) | ||
870 | return -1; | ||
871 | ASN1error(ASN1_R_MSTRING_WRONG_TAG); | ||
872 | return 0; | ||
873 | } | ||
874 | |||
875 | return asn1_d2i_ex_primitive_content(pval, cbs, &cbs_object, | ||
876 | object_tag, constructed, indefinite, length, it); | ||
877 | } | ||
878 | |||
879 | static int | 1133 | static int |
880 | asn1_d2i_ex_primitive(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, | 1134 | asn1_template_ex_d2i(ASN1_VALUE **pval, CBS *cbs, const ASN1_TEMPLATE *tt, |
881 | int tag_number, int tag_class, char optional) | 1135 | char optional, int depth) |
882 | { | 1136 | { |
883 | CBS cbs_object; | 1137 | CBS cbs_exp, cbs_exp_content; |
884 | char constructed, indefinite; | 1138 | char constructed, indefinite; |
885 | int utype = it->utype; | ||
886 | size_t length; | 1139 | size_t length; |
887 | int ret; | 1140 | int ret; |
888 | 1141 | ||
889 | CBS_init(&cbs_object, CBS_data(cbs), CBS_len(cbs)); | 1142 | if (pval == NULL) |
890 | |||
891 | if (it->itype == ASN1_ITYPE_MSTRING) | ||
892 | return 0; | 1143 | return 0; |
893 | 1144 | ||
894 | if (it->utype == V_ASN1_ANY) | 1145 | /* Check if EXPLICIT tag is expected. */ |
895 | return asn1_d2i_ex_any(pval, cbs, it, tag_number, tag_class, optional); | 1146 | if ((tt->flags & ASN1_TFLG_EXPTAG) == 0) |
1147 | return asn1_template_noexp_d2i(pval, cbs, tt, optional, depth); | ||
896 | 1148 | ||
897 | if (tag_number == -1) { | 1149 | CBS_init(&cbs_exp, CBS_data(cbs), CBS_len(cbs)); |
898 | tag_number = it->utype; | ||
899 | tag_class = V_ASN1_UNIVERSAL; | ||
900 | } | ||
901 | 1150 | ||
902 | ret = asn1_check_tag(&cbs_object, &length, NULL, NULL, &indefinite, | 1151 | /* Read ASN.1 header for EXPLICIT tagged object. */ |
903 | &constructed, tag_number, tag_class, optional); | 1152 | ret = asn1_check_tag(&cbs_exp, &length, NULL, NULL, &indefinite, |
1153 | &constructed, tt->tag, tt->flags & ASN1_TFLG_TAG_CLASS, optional); | ||
904 | if (ret == -1) | 1154 | if (ret == -1) |
905 | return -1; | 1155 | return -1; |
906 | if (ret != 1) { | 1156 | if (ret != 1) { |
@@ -908,359 +1158,93 @@ asn1_d2i_ex_primitive(ASN1_VALUE **pval, CBS *cbs, const ASN1_ITEM *it, | |||
908 | return 0; | 1158 | return 0; |
909 | } | 1159 | } |
910 | 1160 | ||
911 | return asn1_d2i_ex_primitive_content(pval, cbs, &cbs_object, utype, | 1161 | if (!constructed) { |
912 | constructed, indefinite, length, it); | 1162 | ASN1error(ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); |
913 | } | ||
914 | |||
915 | static int | ||
916 | asn1_ex_c2i_primitive(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it) | ||
917 | { | ||
918 | ASN1_STRING *stmp; | ||
919 | ASN1_INTEGER **tint; | ||
920 | ASN1_BOOLEAN *tbool; | ||
921 | uint8_t u8val; | ||
922 | int ret = 0; | ||
923 | |||
924 | if (it->funcs != NULL) | ||
925 | return 0; | ||
926 | |||
927 | if (CBS_len(content) > INT_MAX) | ||
928 | return 0; | 1163 | return 0; |
1164 | } | ||
929 | 1165 | ||
930 | switch (utype) { | 1166 | if (indefinite) { |
931 | case V_ASN1_OBJECT: | 1167 | CBS_init(&cbs_exp_content, CBS_data(&cbs_exp), CBS_len(&cbs_exp)); |
932 | if (!c2i_ASN1_OBJECT_cbs((ASN1_OBJECT **)pval, content)) | 1168 | } else { |
933 | goto err; | 1169 | if (!CBS_get_bytes(&cbs_exp, &cbs_exp_content, length)) |
934 | break; | ||
935 | |||
936 | case V_ASN1_NULL: | ||
937 | if (CBS_len(content) != 0) { | ||
938 | ASN1error(ASN1_R_NULL_IS_WRONG_LENGTH); | ||
939 | goto err; | ||
940 | } | ||
941 | *pval = (ASN1_VALUE *)1; | ||
942 | break; | ||
943 | |||
944 | case V_ASN1_BOOLEAN: | ||
945 | tbool = (ASN1_BOOLEAN *)pval; | ||
946 | if (CBS_len(content) != 1) { | ||
947 | ASN1error(ASN1_R_BOOLEAN_IS_WRONG_LENGTH); | ||
948 | goto err; | ||
949 | } | ||
950 | if (!CBS_get_u8(content, &u8val)) | ||
951 | goto err; | ||
952 | *tbool = u8val; | ||
953 | break; | ||
954 | |||
955 | case V_ASN1_BIT_STRING: | ||
956 | if (!c2i_ASN1_BIT_STRING_cbs((ASN1_BIT_STRING **)pval, content)) | ||
957 | goto err; | ||
958 | break; | ||
959 | |||
960 | case V_ASN1_INTEGER: | ||
961 | case V_ASN1_ENUMERATED: | ||
962 | tint = (ASN1_INTEGER **)pval; | ||
963 | if (!c2i_ASN1_INTEGER_cbs(tint, content)) | ||
964 | goto err; | ||
965 | /* Fixup type to match the expected form */ | ||
966 | (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); | ||
967 | break; | ||
968 | |||
969 | case V_ASN1_OCTET_STRING: | ||
970 | case V_ASN1_NUMERICSTRING: | ||
971 | case V_ASN1_PRINTABLESTRING: | ||
972 | case V_ASN1_T61STRING: | ||
973 | case V_ASN1_VIDEOTEXSTRING: | ||
974 | case V_ASN1_IA5STRING: | ||
975 | case V_ASN1_UTCTIME: | ||
976 | case V_ASN1_GENERALIZEDTIME: | ||
977 | case V_ASN1_GRAPHICSTRING: | ||
978 | case V_ASN1_VISIBLESTRING: | ||
979 | case V_ASN1_GENERALSTRING: | ||
980 | case V_ASN1_UNIVERSALSTRING: | ||
981 | case V_ASN1_BMPSTRING: | ||
982 | case V_ASN1_UTF8STRING: | ||
983 | case V_ASN1_OTHER: | ||
984 | case V_ASN1_SET: | ||
985 | case V_ASN1_SEQUENCE: | ||
986 | default: | ||
987 | if (utype == V_ASN1_BMPSTRING && (CBS_len(content) & 1)) { | ||
988 | ASN1error(ASN1_R_BMPSTRING_IS_WRONG_LENGTH); | ||
989 | goto err; | ||
990 | } | ||
991 | if (utype == V_ASN1_UNIVERSALSTRING && (CBS_len(content) & 3)) { | ||
992 | ASN1error(ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH); | ||
993 | goto err; | ||
994 | } | ||
995 | /* All based on ASN1_STRING and handled the same way. */ | ||
996 | if (*pval == NULL) { | ||
997 | if ((stmp = ASN1_STRING_type_new(utype)) == NULL) { | ||
998 | ASN1error(ERR_R_MALLOC_FAILURE); | ||
999 | goto err; | ||
1000 | } | ||
1001 | *pval = (ASN1_VALUE *)stmp; | ||
1002 | } else { | ||
1003 | stmp = (ASN1_STRING *)*pval; | ||
1004 | stmp->type = utype; | ||
1005 | } | ||
1006 | if (!ASN1_STRING_set(stmp, CBS_data(content), CBS_len(content))) { | ||
1007 | ASN1_STRING_free(stmp); | ||
1008 | *pval = NULL; | ||
1009 | goto err; | 1170 | goto err; |
1010 | } | ||
1011 | break; | ||
1012 | } | 1171 | } |
1013 | 1172 | ||
1014 | ret = 1; | 1173 | if ((ret = asn1_template_noexp_d2i(pval, &cbs_exp_content, tt, 0, |
1015 | 1174 | depth)) != 1) { | |
1016 | err: | 1175 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
1017 | return ret; | ||
1018 | } | ||
1019 | |||
1020 | static int | ||
1021 | asn1_ex_c2i_any(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it) | ||
1022 | { | ||
1023 | ASN1_TYPE *atype; | ||
1024 | |||
1025 | if (it->utype != V_ASN1_ANY || it->funcs != NULL) | ||
1026 | return 0; | 1176 | return 0; |
1027 | |||
1028 | if (*pval != NULL) { | ||
1029 | ASN1_TYPE_free((ASN1_TYPE *)*pval); | ||
1030 | *pval = NULL; | ||
1031 | } | 1177 | } |
1032 | 1178 | ||
1033 | if ((atype = ASN1_TYPE_new()) == NULL) | 1179 | if (indefinite) { |
1034 | return 0; | 1180 | if (!asn1_check_eoc(&cbs_exp_content)) { |
1035 | 1181 | ASN1error(ASN1_R_MISSING_EOC); | |
1036 | if (!asn1_ex_c2i_primitive(&atype->value.asn1_value, content, utype, it)) { | 1182 | goto err; |
1037 | ASN1_TYPE_free(atype); | 1183 | } |
1038 | return 0; | 1184 | if (!CBS_skip(&cbs_exp, CBS_offset(&cbs_exp_content))) |
1185 | goto err; | ||
1186 | } else if (CBS_len(&cbs_exp_content) != 0) { | ||
1187 | ASN1error(ASN1_R_SEQUENCE_LENGTH_MISMATCH); | ||
1188 | goto err; | ||
1039 | } | 1189 | } |
1040 | atype->type = utype; | ||
1041 | |||
1042 | /* Fix up value for ASN.1 NULL. */ | ||
1043 | if (atype->type == V_ASN1_NULL) | ||
1044 | atype->value.ptr = NULL; | ||
1045 | 1190 | ||
1046 | *pval = (ASN1_VALUE *)atype; | 1191 | if (!CBS_skip(cbs, CBS_offset(&cbs_exp))) |
1192 | goto err; | ||
1047 | 1193 | ||
1048 | return 1; | 1194 | return 1; |
1049 | } | ||
1050 | 1195 | ||
1051 | static int | 1196 | err: |
1052 | asn1_ex_c2i(ASN1_VALUE **pval, CBS *content, int utype, const ASN1_ITEM *it) | 1197 | ASN1_template_free(pval, tt); |
1053 | { | 1198 | return 0; |
1054 | if (CBS_len(content) > INT_MAX) | ||
1055 | return 0; | ||
1056 | |||
1057 | if (it->funcs != NULL) { | ||
1058 | const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; | ||
1059 | char free_content = 0; | ||
1060 | |||
1061 | if (pf->prim_c2i == NULL) | ||
1062 | return 0; | ||
1063 | |||
1064 | return pf->prim_c2i(pval, CBS_data(content), CBS_len(content), | ||
1065 | utype, &free_content, it); | ||
1066 | } | ||
1067 | |||
1068 | if (it->utype == V_ASN1_ANY) | ||
1069 | return asn1_ex_c2i_any(pval, content, utype, it); | ||
1070 | |||
1071 | return asn1_ex_c2i_primitive(pval, content, utype, it); | ||
1072 | } | 1199 | } |
1073 | 1200 | ||
1074 | /* Find the end of an ASN.1 object. */ | 1201 | ASN1_VALUE * |
1075 | static int | 1202 | ASN1_item_d2i(ASN1_VALUE **pval, const unsigned char **in, long inlen, |
1076 | asn1_find_end(CBS *cbs, size_t length, char indefinite) | 1203 | const ASN1_ITEM *it) |
1077 | { | 1204 | { |
1078 | size_t eoc_count; | 1205 | ASN1_VALUE *ptmpval = NULL; |
1079 | |||
1080 | if (!indefinite) { | ||
1081 | if (!CBS_skip(cbs, length)) { | ||
1082 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
1083 | return 0; | ||
1084 | } | ||
1085 | return 1; | ||
1086 | } | ||
1087 | |||
1088 | eoc_count = 1; | ||
1089 | |||
1090 | while (CBS_len(cbs) > 0) { | ||
1091 | if (asn1_check_eoc(cbs)) { | ||
1092 | if (--eoc_count == 0) | ||
1093 | break; | ||
1094 | continue; | ||
1095 | } | ||
1096 | if (!asn1_check_tag(cbs, &length, NULL, NULL, | ||
1097 | &indefinite, NULL, -1, 0, 0)) { | ||
1098 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
1099 | return 0; | ||
1100 | } | ||
1101 | if (indefinite) { | ||
1102 | eoc_count++; | ||
1103 | continue; | ||
1104 | } | ||
1105 | if (!CBS_skip(cbs, length)) | ||
1106 | return 0; | ||
1107 | } | ||
1108 | 1206 | ||
1109 | if (eoc_count > 0) { | 1207 | if (pval == NULL) |
1110 | ASN1error(ASN1_R_MISSING_EOC); | 1208 | pval = &ptmpval; |
1111 | return 0; | 1209 | if (ASN1_item_ex_d2i(pval, in, inlen, it, -1, 0, 0, 0) <= 0) |
1112 | } | 1210 | return NULL; |
1113 | 1211 | ||
1114 | return 1; | 1212 | return *pval; |
1115 | } | 1213 | } |
1116 | 1214 | ||
1117 | #ifndef ASN1_MAX_STRING_NEST | 1215 | int |
1118 | /* This determines how many levels of recursion are permitted in ASN1 | 1216 | ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long inlen, |
1119 | * string types. If it is not limited stack overflows can occur. If set | 1217 | const ASN1_ITEM *it, int tag_number, int tag_class, char optional, |
1120 | * to zero no recursion is allowed at all. Although zero should be adequate | 1218 | ASN1_TLC *ctx) |
1121 | * examples exist that require a value of 1. So 5 should be more than enough. | ||
1122 | */ | ||
1123 | #define ASN1_MAX_STRING_NEST 5 | ||
1124 | #endif | ||
1125 | |||
1126 | /* Collect the contents from a constructed ASN.1 object. */ | ||
1127 | static int | ||
1128 | asn1_collect(CBB *cbb, CBS *cbs, char indefinite, int expected_tag, | ||
1129 | int expected_class, int depth) | ||
1130 | { | 1219 | { |
1131 | char constructed; | 1220 | CBS cbs; |
1132 | size_t length; | 1221 | int ret; |
1133 | CBS content; | ||
1134 | int need_eoc; | ||
1135 | |||
1136 | if (depth > ASN1_MAX_STRING_NEST) { | ||
1137 | ASN1error(ASN1_R_NESTED_ASN1_STRING); | ||
1138 | return 0; | ||
1139 | } | ||
1140 | |||
1141 | need_eoc = indefinite; | ||
1142 | |||
1143 | while (CBS_len(cbs) > 0) { | ||
1144 | if (asn1_check_eoc(cbs)) { | ||
1145 | if (!need_eoc) { | ||
1146 | ASN1error(ASN1_R_UNEXPECTED_EOC); | ||
1147 | return 0; | ||
1148 | } | ||
1149 | return 1; | ||
1150 | } | ||
1151 | if (!asn1_check_tag(cbs, &length, NULL, NULL, &indefinite, | ||
1152 | &constructed, expected_tag, expected_class, 0)) { | ||
1153 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
1154 | return 0; | ||
1155 | } | ||
1156 | |||
1157 | if (constructed) { | ||
1158 | if (!asn1_collect(cbb, cbs, indefinite, expected_tag, | ||
1159 | expected_class, depth + 1)) | ||
1160 | return 0; | ||
1161 | continue; | ||
1162 | } | ||
1163 | |||
1164 | if (!CBS_get_bytes(cbs, &content, length)) { | ||
1165 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | ||
1166 | return 0; | ||
1167 | } | ||
1168 | if (!CBB_add_bytes(cbb, CBS_data(&content), CBS_len(&content))) | ||
1169 | return 0; | ||
1170 | } | ||
1171 | 1222 | ||
1172 | if (need_eoc) { | 1223 | if (inlen < 0) |
1173 | ASN1error(ASN1_R_MISSING_EOC); | ||
1174 | return 0; | 1224 | return 0; |
1175 | } | ||
1176 | 1225 | ||
1177 | return 1; | 1226 | CBS_init(&cbs, *in, inlen); |
1178 | } | ||
1179 | |||
1180 | static int | ||
1181 | asn1_check_eoc(CBS *cbs) | ||
1182 | { | ||
1183 | uint16_t eoc; | ||
1184 | 1227 | ||
1185 | if (!CBS_peek_u16(cbs, &eoc)) | 1228 | if ((ret = asn1_item_ex_d2i(pval, &cbs, it, tag_number, tag_class, |
1186 | return 0; | 1229 | optional, 0)) == 1) |
1187 | if (eoc != 0) | 1230 | *in = CBS_data(&cbs); |
1188 | return 0; | ||
1189 | 1231 | ||
1190 | return CBS_skip(cbs, 2); | 1232 | return ret; |
1191 | } | 1233 | } |
1192 | 1234 | ||
1193 | static int | 1235 | int |
1194 | asn1_check_tag(CBS *cbs, size_t *out_len, int *out_tag, uint8_t *out_class, | 1236 | ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, |
1195 | char *out_indefinite, char *out_constructed, int expected_tag, | 1237 | const ASN1_TEMPLATE *tt) |
1196 | int expected_class, char optional) | ||
1197 | { | 1238 | { |
1198 | int constructed, indefinite; | 1239 | CBS cbs; |
1199 | uint32_t tag_number; | 1240 | int ret; |
1200 | uint8_t tag_class; | ||
1201 | size_t length; | ||
1202 | |||
1203 | if (out_len != NULL) | ||
1204 | *out_len = 0; | ||
1205 | if (out_tag != NULL) | ||
1206 | *out_tag = 0; | ||
1207 | if (out_class != NULL) | ||
1208 | *out_class = 0; | ||
1209 | if (out_indefinite != NULL) | ||
1210 | *out_indefinite = 0; | ||
1211 | if (out_constructed != NULL) | ||
1212 | *out_constructed = 0; | ||
1213 | |||
1214 | if (!asn1_get_identifier_cbs(cbs, 0, &tag_class, &constructed, | ||
1215 | &tag_number)) { | ||
1216 | ASN1error(ASN1_R_BAD_OBJECT_HEADER); | ||
1217 | return 0; | ||
1218 | } | ||
1219 | if (expected_tag >= 0) { | ||
1220 | if (expected_tag != tag_number || | ||
1221 | expected_class != tag_class << 6) { | ||
1222 | /* Indicate missing type if this is OPTIONAL. */ | ||
1223 | if (optional) | ||
1224 | return -1; | ||
1225 | |||
1226 | ASN1error(ASN1_R_WRONG_TAG); | ||
1227 | return 0; | ||
1228 | } | ||
1229 | } | ||
1230 | if (!asn1_get_length_cbs(cbs, 0, &indefinite, &length)) { | ||
1231 | ASN1error(ASN1_R_BAD_OBJECT_HEADER); | ||
1232 | return 0; | ||
1233 | } | ||
1234 | |||
1235 | /* Indefinite length can only be used with constructed encoding. */ | ||
1236 | if (indefinite && !constructed) { | ||
1237 | ASN1error(ASN1_R_BAD_OBJECT_HEADER); | ||
1238 | return 0; | ||
1239 | } | ||
1240 | |||
1241 | if (!indefinite && CBS_len(cbs) < length) { | ||
1242 | ASN1error(ASN1_R_TOO_LONG); | ||
1243 | return 0; | ||
1244 | } | ||
1245 | 1241 | ||
1246 | if (tag_number > INT_MAX) { | 1242 | if (len < 0) |
1247 | ASN1error(ASN1_R_TOO_LONG); | ||
1248 | return 0; | 1243 | return 0; |
1249 | } | ||
1250 | 1244 | ||
1251 | if (indefinite) | 1245 | CBS_init(&cbs, *in, len); |
1252 | length = CBS_len(cbs); | 1246 | if ((ret = asn1_template_ex_d2i(pval, &cbs, tt, 0, 0)) == 1) |
1253 | 1247 | *in = CBS_data(&cbs); | |
1254 | if (out_len != NULL) | ||
1255 | *out_len = length; | ||
1256 | if (out_tag != NULL) | ||
1257 | *out_tag = tag_number; | ||
1258 | if (out_class != NULL) | ||
1259 | *out_class = tag_class << 6; | ||
1260 | if (out_indefinite != NULL && indefinite) | ||
1261 | *out_indefinite = 1 << 0; | ||
1262 | if (out_constructed != NULL && constructed) | ||
1263 | *out_constructed = 1 << 5; | ||
1264 | 1248 | ||
1265 | return 1; | 1249 | return ret; |
1266 | } | 1250 | } |