1 | /* |
2 | * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. |
3 | * |
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at |
7 | * https://www.openssl.org/source/license.html |
8 | */ |
9 | |
10 | #include <stddef.h> |
11 | #include "internal/cryptlib.h" |
12 | #include <openssl/asn1.h> |
13 | #include <openssl/asn1t.h> |
14 | #include <openssl/objects.h> |
15 | #include <openssl/buffer.h> |
16 | #include <openssl/err.h> |
17 | #include <openssl/x509v3.h> |
18 | #include "crypto/asn1.h" |
19 | #include "asn1_local.h" |
20 | |
21 | /* |
22 | * Print routines. |
23 | */ |
24 | |
25 | /* ASN1_PCTX routines */ |
26 | |
27 | static ASN1_PCTX default_pctx = { |
28 | ASN1_PCTX_FLAGS_SHOW_ABSENT, /* flags */ |
29 | 0, /* nm_flags */ |
30 | 0, /* cert_flags */ |
31 | 0, /* oid_flags */ |
32 | 0 /* str_flags */ |
33 | }; |
34 | |
35 | ASN1_PCTX *ASN1_PCTX_new(void) |
36 | { |
37 | ASN1_PCTX *ret; |
38 | |
39 | ret = OPENSSL_zalloc(sizeof(*ret)); |
40 | if (ret == NULL) { |
41 | ASN1err(ASN1_F_ASN1_PCTX_NEW, ERR_R_MALLOC_FAILURE); |
42 | return NULL; |
43 | } |
44 | return ret; |
45 | } |
46 | |
47 | void ASN1_PCTX_free(ASN1_PCTX *p) |
48 | { |
49 | OPENSSL_free(p); |
50 | } |
51 | |
52 | unsigned long ASN1_PCTX_get_flags(const ASN1_PCTX *p) |
53 | { |
54 | return p->flags; |
55 | } |
56 | |
57 | void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags) |
58 | { |
59 | p->flags = flags; |
60 | } |
61 | |
62 | unsigned long ASN1_PCTX_get_nm_flags(const ASN1_PCTX *p) |
63 | { |
64 | return p->nm_flags; |
65 | } |
66 | |
67 | void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags) |
68 | { |
69 | p->nm_flags = flags; |
70 | } |
71 | |
72 | unsigned long ASN1_PCTX_get_cert_flags(const ASN1_PCTX *p) |
73 | { |
74 | return p->cert_flags; |
75 | } |
76 | |
77 | void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags) |
78 | { |
79 | p->cert_flags = flags; |
80 | } |
81 | |
82 | unsigned long ASN1_PCTX_get_oid_flags(const ASN1_PCTX *p) |
83 | { |
84 | return p->oid_flags; |
85 | } |
86 | |
87 | void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags) |
88 | { |
89 | p->oid_flags = flags; |
90 | } |
91 | |
92 | unsigned long ASN1_PCTX_get_str_flags(const ASN1_PCTX *p) |
93 | { |
94 | return p->str_flags; |
95 | } |
96 | |
97 | void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags) |
98 | { |
99 | p->str_flags = flags; |
100 | } |
101 | |
102 | /* Main print routines */ |
103 | |
104 | static int asn1_item_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent, |
105 | const ASN1_ITEM *it, |
106 | const char *fname, const char *sname, |
107 | int nohdr, const ASN1_PCTX *pctx); |
108 | |
109 | static int asn1_template_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent, |
110 | const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx); |
111 | |
112 | static int asn1_primitive_print(BIO *out, const ASN1_VALUE **fld, |
113 | const ASN1_ITEM *it, int indent, |
114 | const char *fname, const char *sname, |
115 | const ASN1_PCTX *pctx); |
116 | |
117 | static int asn1_print_fsname(BIO *out, int indent, |
118 | const char *fname, const char *sname, |
119 | const ASN1_PCTX *pctx); |
120 | |
121 | int ASN1_item_print(BIO *out, const ASN1_VALUE *ifld, int indent, |
122 | const ASN1_ITEM *it, const ASN1_PCTX *pctx) |
123 | { |
124 | const char *sname; |
125 | if (pctx == NULL) |
126 | pctx = &default_pctx; |
127 | if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME) |
128 | sname = NULL; |
129 | else |
130 | sname = it->sname; |
131 | return asn1_item_print_ctx(out, &ifld, indent, it, NULL, sname, 0, pctx); |
132 | } |
133 | |
134 | static int asn1_item_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent, |
135 | const ASN1_ITEM *it, |
136 | const char *fname, const char *sname, |
137 | int nohdr, const ASN1_PCTX *pctx) |
138 | { |
139 | const ASN1_TEMPLATE *tt; |
140 | const ASN1_EXTERN_FUNCS *ef; |
141 | const ASN1_VALUE **tmpfld; |
142 | const ASN1_AUX *aux = it->funcs; |
143 | ASN1_aux_const_cb *asn1_cb = NULL; |
144 | ASN1_PRINT_ARG parg; |
145 | int i; |
146 | if (aux != NULL) { |
147 | parg.out = out; |
148 | parg.indent = indent; |
149 | parg.pctx = pctx; |
150 | asn1_cb = ((aux->flags & ASN1_AFLG_CONST_CB) != 0) ? aux->asn1_const_cb |
151 | : (ASN1_aux_const_cb *)aux->asn1_cb; /* backward compatibility */ |
152 | } |
153 | |
154 | if (((it->itype != ASN1_ITYPE_PRIMITIVE) |
155 | || (it->utype != V_ASN1_BOOLEAN)) && *fld == NULL) { |
156 | if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_ABSENT) { |
157 | if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx)) |
158 | return 0; |
159 | if (BIO_puts(out, "<ABSENT>\n" ) <= 0) |
160 | return 0; |
161 | } |
162 | return 1; |
163 | } |
164 | |
165 | switch (it->itype) { |
166 | case ASN1_ITYPE_PRIMITIVE: |
167 | if (it->templates) { |
168 | if (!asn1_template_print_ctx(out, fld, indent, |
169 | it->templates, pctx)) |
170 | return 0; |
171 | break; |
172 | } |
173 | /* fall through */ |
174 | case ASN1_ITYPE_MSTRING: |
175 | if (!asn1_primitive_print(out, fld, it, indent, fname, sname, pctx)) |
176 | return 0; |
177 | break; |
178 | |
179 | case ASN1_ITYPE_EXTERN: |
180 | if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx)) |
181 | return 0; |
182 | /* Use new style print routine if possible */ |
183 | ef = it->funcs; |
184 | if (ef && ef->asn1_ex_print) { |
185 | i = ef->asn1_ex_print(out, fld, indent, "" , pctx); |
186 | if (!i) |
187 | return 0; |
188 | if ((i == 2) && (BIO_puts(out, "\n" ) <= 0)) |
189 | return 0; |
190 | return 1; |
191 | } else if (sname && |
192 | BIO_printf(out, ":EXTERNAL TYPE %s\n" , sname) <= 0) |
193 | return 0; |
194 | break; |
195 | |
196 | case ASN1_ITYPE_CHOICE: |
197 | /* CHOICE type, get selector */ |
198 | i = asn1_get_choice_selector_const(fld, it); |
199 | /* This should never happen... */ |
200 | if ((i < 0) || (i >= it->tcount)) { |
201 | if (BIO_printf(out, "ERROR: selector [%d] invalid\n" , i) <= 0) |
202 | return 0; |
203 | return 1; |
204 | } |
205 | tt = it->templates + i; |
206 | tmpfld = asn1_get_const_field_ptr(fld, tt); |
207 | if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx)) |
208 | return 0; |
209 | break; |
210 | |
211 | case ASN1_ITYPE_SEQUENCE: |
212 | case ASN1_ITYPE_NDEF_SEQUENCE: |
213 | if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx)) |
214 | return 0; |
215 | if (fname || sname) { |
216 | if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) { |
217 | if (BIO_puts(out, " {\n" ) <= 0) |
218 | return 0; |
219 | } else { |
220 | if (BIO_puts(out, "\n" ) <= 0) |
221 | return 0; |
222 | } |
223 | } |
224 | |
225 | if (asn1_cb) { |
226 | i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg); |
227 | if (i == 0) |
228 | return 0; |
229 | if (i == 2) |
230 | return 1; |
231 | } |
232 | |
233 | /* Print each field entry */ |
234 | for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { |
235 | const ASN1_TEMPLATE *seqtt; |
236 | seqtt = asn1_do_adb(*fld, tt, 1); |
237 | if (!seqtt) |
238 | return 0; |
239 | tmpfld = asn1_get_const_field_ptr(fld, seqtt); |
240 | if (!asn1_template_print_ctx(out, tmpfld, |
241 | indent + 2, seqtt, pctx)) |
242 | return 0; |
243 | } |
244 | if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) { |
245 | if (BIO_printf(out, "%*s}\n" , indent, "" ) < 0) |
246 | return 0; |
247 | } |
248 | |
249 | if (asn1_cb) { |
250 | i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg); |
251 | if (i == 0) |
252 | return 0; |
253 | } |
254 | break; |
255 | |
256 | default: |
257 | BIO_printf(out, "Unprocessed type %d\n" , it->itype); |
258 | return 0; |
259 | } |
260 | |
261 | return 1; |
262 | } |
263 | |
264 | static int asn1_template_print_ctx(BIO *out, const ASN1_VALUE **fld, int indent, |
265 | const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx) |
266 | { |
267 | int i, flags; |
268 | const char *sname, *fname; |
269 | const ASN1_VALUE *tfld; |
270 | flags = tt->flags; |
271 | if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME) |
272 | sname = ASN1_ITEM_ptr(tt->item)->sname; |
273 | else |
274 | sname = NULL; |
275 | if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME) |
276 | fname = NULL; |
277 | else |
278 | fname = tt->field_name; |
279 | |
280 | /* |
281 | * If field is embedded then fld needs fixing so it is a pointer to |
282 | * a pointer to a field. |
283 | */ |
284 | if (flags & ASN1_TFLG_EMBED) { |
285 | tfld = (const ASN1_VALUE *)fld; |
286 | fld = &tfld; |
287 | } |
288 | |
289 | if (flags & ASN1_TFLG_SK_MASK) { |
290 | char *tname; |
291 | const ASN1_VALUE *skitem; |
292 | STACK_OF(const_ASN1_VALUE) *stack; |
293 | |
294 | /* SET OF, SEQUENCE OF */ |
295 | if (fname) { |
296 | if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF) { |
297 | if (flags & ASN1_TFLG_SET_OF) |
298 | tname = "SET" ; |
299 | else |
300 | tname = "SEQUENCE" ; |
301 | if (BIO_printf(out, "%*s%s OF %s {\n" , |
302 | indent, "" , tname, tt->field_name) <= 0) |
303 | return 0; |
304 | } else if (BIO_printf(out, "%*s%s:\n" , indent, "" , fname) <= 0) |
305 | return 0; |
306 | } |
307 | stack = (STACK_OF(const_ASN1_VALUE) *)*fld; |
308 | for (i = 0; i < sk_const_ASN1_VALUE_num(stack); i++) { |
309 | if ((i > 0) && (BIO_puts(out, "\n" ) <= 0)) |
310 | return 0; |
311 | |
312 | skitem = sk_const_ASN1_VALUE_value(stack, i); |
313 | if (!asn1_item_print_ctx(out, &skitem, indent + 2, |
314 | ASN1_ITEM_ptr(tt->item), NULL, NULL, 1, |
315 | pctx)) |
316 | return 0; |
317 | } |
318 | if (i == 0 && BIO_printf(out, "%*s<%s>\n" , indent + 2, "" , |
319 | stack == NULL ? "ABSENT" : "EMPTY" ) <= 0) |
320 | return 0; |
321 | if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) { |
322 | if (BIO_printf(out, "%*s}\n" , indent, "" ) <= 0) |
323 | return 0; |
324 | } |
325 | return 1; |
326 | } |
327 | return asn1_item_print_ctx(out, fld, indent, ASN1_ITEM_ptr(tt->item), |
328 | fname, sname, 0, pctx); |
329 | } |
330 | |
331 | static int asn1_print_fsname(BIO *out, int indent, |
332 | const char *fname, const char *sname, |
333 | const ASN1_PCTX *pctx) |
334 | { |
335 | static const char spaces[] = " " ; |
336 | static const int nspaces = sizeof(spaces) - 1; |
337 | |
338 | while (indent > nspaces) { |
339 | if (BIO_write(out, spaces, nspaces) != nspaces) |
340 | return 0; |
341 | indent -= nspaces; |
342 | } |
343 | if (BIO_write(out, spaces, indent) != indent) |
344 | return 0; |
345 | if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME) |
346 | sname = NULL; |
347 | if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME) |
348 | fname = NULL; |
349 | if (!sname && !fname) |
350 | return 1; |
351 | if (fname) { |
352 | if (BIO_puts(out, fname) <= 0) |
353 | return 0; |
354 | } |
355 | if (sname) { |
356 | if (fname) { |
357 | if (BIO_printf(out, " (%s)" , sname) <= 0) |
358 | return 0; |
359 | } else { |
360 | if (BIO_puts(out, sname) <= 0) |
361 | return 0; |
362 | } |
363 | } |
364 | if (BIO_write(out, ": " , 2) != 2) |
365 | return 0; |
366 | return 1; |
367 | } |
368 | |
369 | static int asn1_print_boolean(BIO *out, int boolval) |
370 | { |
371 | const char *str; |
372 | switch (boolval) { |
373 | case -1: |
374 | str = "BOOL ABSENT" ; |
375 | break; |
376 | |
377 | case 0: |
378 | str = "FALSE" ; |
379 | break; |
380 | |
381 | default: |
382 | str = "TRUE" ; |
383 | break; |
384 | |
385 | } |
386 | |
387 | if (BIO_puts(out, str) <= 0) |
388 | return 0; |
389 | return 1; |
390 | |
391 | } |
392 | |
393 | static int asn1_print_integer(BIO *out, const ASN1_INTEGER *str) |
394 | { |
395 | char *s; |
396 | int ret = 1; |
397 | s = i2s_ASN1_INTEGER(NULL, str); |
398 | if (s == NULL) |
399 | return 0; |
400 | if (BIO_puts(out, s) <= 0) |
401 | ret = 0; |
402 | OPENSSL_free(s); |
403 | return ret; |
404 | } |
405 | |
406 | static int asn1_print_oid(BIO *out, const ASN1_OBJECT *oid) |
407 | { |
408 | char objbuf[80]; |
409 | const char *ln; |
410 | ln = OBJ_nid2ln(OBJ_obj2nid(oid)); |
411 | if (!ln) |
412 | ln = "" ; |
413 | OBJ_obj2txt(objbuf, sizeof(objbuf), oid, 1); |
414 | if (BIO_printf(out, "%s (%s)" , ln, objbuf) <= 0) |
415 | return 0; |
416 | return 1; |
417 | } |
418 | |
419 | static int asn1_print_obstring(BIO *out, const ASN1_STRING *str, int indent) |
420 | { |
421 | if (str->type == V_ASN1_BIT_STRING) { |
422 | if (BIO_printf(out, " (%ld unused bits)\n" , str->flags & 0x7) <= 0) |
423 | return 0; |
424 | } else if (BIO_puts(out, "\n" ) <= 0) |
425 | return 0; |
426 | if ((str->length > 0) |
427 | && BIO_dump_indent(out, (const char *)str->data, str->length, |
428 | indent + 2) <= 0) |
429 | return 0; |
430 | return 1; |
431 | } |
432 | |
433 | static int asn1_primitive_print(BIO *out, const ASN1_VALUE **fld, |
434 | const ASN1_ITEM *it, int indent, |
435 | const char *fname, const char *sname, |
436 | const ASN1_PCTX *pctx) |
437 | { |
438 | long utype; |
439 | ASN1_STRING *str; |
440 | int ret = 1, needlf = 1; |
441 | const char *pname; |
442 | const ASN1_PRIMITIVE_FUNCS *pf; |
443 | pf = it->funcs; |
444 | if (!asn1_print_fsname(out, indent, fname, sname, pctx)) |
445 | return 0; |
446 | if (pf && pf->prim_print) |
447 | return pf->prim_print(out, fld, it, indent, pctx); |
448 | if (it->itype == ASN1_ITYPE_MSTRING) { |
449 | str = (ASN1_STRING *)*fld; |
450 | utype = str->type & ~V_ASN1_NEG; |
451 | } else { |
452 | utype = it->utype; |
453 | if (utype == V_ASN1_BOOLEAN) |
454 | str = NULL; |
455 | else |
456 | str = (ASN1_STRING *)*fld; |
457 | } |
458 | if (utype == V_ASN1_ANY) { |
459 | const ASN1_TYPE *atype = (const ASN1_TYPE *)*fld; |
460 | utype = atype->type; |
461 | fld = (const ASN1_VALUE **)&atype->value.asn1_value; /* actually is const */ |
462 | str = (ASN1_STRING *)*fld; |
463 | if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE) |
464 | pname = NULL; |
465 | else |
466 | pname = ASN1_tag2str(utype); |
467 | } else { |
468 | if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE) |
469 | pname = ASN1_tag2str(utype); |
470 | else |
471 | pname = NULL; |
472 | } |
473 | |
474 | if (utype == V_ASN1_NULL) { |
475 | if (BIO_puts(out, "NULL\n" ) <= 0) |
476 | return 0; |
477 | return 1; |
478 | } |
479 | |
480 | if (pname) { |
481 | if (BIO_puts(out, pname) <= 0) |
482 | return 0; |
483 | if (BIO_puts(out, ":" ) <= 0) |
484 | return 0; |
485 | } |
486 | |
487 | switch (utype) { |
488 | case V_ASN1_BOOLEAN: |
489 | { |
490 | int boolval = *(int *)fld; |
491 | if (boolval == -1) |
492 | boolval = it->size; |
493 | ret = asn1_print_boolean(out, boolval); |
494 | } |
495 | break; |
496 | |
497 | case V_ASN1_INTEGER: |
498 | case V_ASN1_ENUMERATED: |
499 | ret = asn1_print_integer(out, str); |
500 | break; |
501 | |
502 | case V_ASN1_UTCTIME: |
503 | ret = ASN1_UTCTIME_print(out, str); |
504 | break; |
505 | |
506 | case V_ASN1_GENERALIZEDTIME: |
507 | ret = ASN1_GENERALIZEDTIME_print(out, str); |
508 | break; |
509 | |
510 | case V_ASN1_OBJECT: |
511 | ret = asn1_print_oid(out, (const ASN1_OBJECT *)*fld); |
512 | break; |
513 | |
514 | case V_ASN1_OCTET_STRING: |
515 | case V_ASN1_BIT_STRING: |
516 | ret = asn1_print_obstring(out, str, indent); |
517 | needlf = 0; |
518 | break; |
519 | |
520 | case V_ASN1_SEQUENCE: |
521 | case V_ASN1_SET: |
522 | case V_ASN1_OTHER: |
523 | if (BIO_puts(out, "\n" ) <= 0) |
524 | return 0; |
525 | if (ASN1_parse_dump(out, str->data, str->length, indent, 0) <= 0) |
526 | ret = 0; |
527 | needlf = 0; |
528 | break; |
529 | |
530 | default: |
531 | ret = ASN1_STRING_print_ex(out, str, pctx->str_flags); |
532 | |
533 | } |
534 | if (!ret) |
535 | return 0; |
536 | if (needlf && BIO_puts(out, "\n" ) <= 0) |
537 | return 0; |
538 | return 1; |
539 | } |
540 | |