asn1_parse.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /*
  2. * Copyright 1995-2023 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. #include <stdio.h>
  10. #include "internal/cryptlib.h"
  11. #include <openssl/buffer.h>
  12. #include <openssl/objects.h>
  13. #include <openssl/asn1.h>
  14. #ifndef ASN1_PARSE_MAXDEPTH
  15. #define ASN1_PARSE_MAXDEPTH 128
  16. #endif
  17. static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
  18. int offset, int depth, int indent, int dump);
  19. static int asn1_print_info(BIO *bp, long offset, int depth, int hl, long len,
  20. int tag, int xclass, int constructed, int indent)
  21. {
  22. char str[128];
  23. const char *p;
  24. int pop_f_prefix = 0;
  25. long saved_indent = -1;
  26. int i = 0;
  27. BIO *bio = NULL;
  28. if (constructed & V_ASN1_CONSTRUCTED)
  29. p = "cons: ";
  30. else
  31. p = "prim: ";
  32. if (constructed != (V_ASN1_CONSTRUCTED | 1)) {
  33. if (BIO_snprintf(str, sizeof(str), "%5ld:d=%-2d hl=%ld l=%4ld %s",
  34. offset, depth, (long)hl, len, p) <= 0)
  35. goto err;
  36. } else {
  37. if (BIO_snprintf(str, sizeof(str), "%5ld:d=%-2d hl=%ld l=inf %s",
  38. offset, depth, (long)hl, p) <= 0)
  39. goto err;
  40. }
  41. if (bp != NULL) {
  42. if (BIO_set_prefix(bp, str) <= 0) {
  43. if ((bio = BIO_new(BIO_f_prefix())) == NULL
  44. || (bp = BIO_push(bio, bp)) == NULL)
  45. goto err;
  46. pop_f_prefix = 1;
  47. }
  48. saved_indent = BIO_get_indent(bp);
  49. if (BIO_set_prefix(bp, str) <= 0 || BIO_set_indent(bp, indent) <= 0)
  50. goto err;
  51. }
  52. /*
  53. * BIO_set_prefix made a copy of |str|, so we can safely use it for
  54. * something else, ASN.1 tag printout.
  55. */
  56. p = str;
  57. if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
  58. BIO_snprintf(str, sizeof(str), "priv [ %d ] ", tag);
  59. else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
  60. BIO_snprintf(str, sizeof(str), "cont [ %d ]", tag);
  61. else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
  62. BIO_snprintf(str, sizeof(str), "appl [ %d ]", tag);
  63. else if (tag > 30)
  64. BIO_snprintf(str, sizeof(str), "<ASN1 %d>", tag);
  65. else
  66. p = ASN1_tag2str(tag);
  67. i = (BIO_printf(bp, "%-18s", p) > 0);
  68. err:
  69. if (saved_indent >= 0)
  70. BIO_set_indent(bp, saved_indent);
  71. if (pop_f_prefix)
  72. BIO_pop(bp);
  73. BIO_free(bio);
  74. return i;
  75. }
  76. int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
  77. {
  78. return asn1_parse2(bp, &pp, len, 0, 0, indent, 0);
  79. }
  80. int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent,
  81. int dump)
  82. {
  83. return asn1_parse2(bp, &pp, len, 0, 0, indent, dump);
  84. }
  85. static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
  86. int offset, int depth, int indent, int dump)
  87. {
  88. const unsigned char *p, *ep, *tot, *op, *opp;
  89. long len;
  90. int tag, xclass, ret = 0;
  91. int nl, hl, j, r;
  92. ASN1_OBJECT *o = NULL;
  93. ASN1_OCTET_STRING *os = NULL;
  94. ASN1_INTEGER *ai = NULL;
  95. ASN1_ENUMERATED *ae = NULL;
  96. /* ASN1_BMPSTRING *bmp=NULL; */
  97. int dump_indent, dump_cont = 0;
  98. if (depth > ASN1_PARSE_MAXDEPTH) {
  99. BIO_puts(bp, "BAD RECURSION DEPTH\n");
  100. return 0;
  101. }
  102. dump_indent = 6; /* Because we know BIO_dump_indent() */
  103. p = *pp;
  104. tot = p + length;
  105. while (length > 0) {
  106. op = p;
  107. j = ASN1_get_object(&p, &len, &tag, &xclass, length);
  108. if (j & 0x80) {
  109. BIO_puts(bp, "Error in encoding\n");
  110. goto end;
  111. }
  112. hl = (p - op);
  113. length -= hl;
  114. /*
  115. * if j == 0x21 it is a constructed indefinite length object
  116. */
  117. if (!asn1_print_info(bp, (long)offset + (long)(op - *pp), depth,
  118. hl, len, tag, xclass, j, (indent) ? depth : 0))
  119. goto end;
  120. if (j & V_ASN1_CONSTRUCTED) {
  121. const unsigned char *sp = p;
  122. ep = p + len;
  123. if (BIO_write(bp, "\n", 1) <= 0)
  124. goto end;
  125. if (len > length) {
  126. BIO_printf(bp, "length is greater than %ld\n", length);
  127. goto end;
  128. }
  129. if ((j == 0x21) && (len == 0)) {
  130. for (;;) {
  131. r = asn1_parse2(bp, &p, (long)(tot - p),
  132. offset + (p - *pp), depth + 1,
  133. indent, dump);
  134. if (r == 0)
  135. goto end;
  136. if ((r == 2) || (p >= tot)) {
  137. len = p - sp;
  138. break;
  139. }
  140. }
  141. } else {
  142. long tmp = len;
  143. while (p < ep) {
  144. sp = p;
  145. r = asn1_parse2(bp, &p, tmp,
  146. offset + (p - *pp), depth + 1,
  147. indent, dump);
  148. if (r == 0)
  149. goto end;
  150. tmp -= p - sp;
  151. }
  152. }
  153. } else if (xclass != 0) {
  154. p += len;
  155. if (BIO_write(bp, "\n", 1) <= 0)
  156. goto end;
  157. } else {
  158. nl = 0;
  159. if ((tag == V_ASN1_PRINTABLESTRING) ||
  160. (tag == V_ASN1_T61STRING) ||
  161. (tag == V_ASN1_IA5STRING) ||
  162. (tag == V_ASN1_VISIBLESTRING) ||
  163. (tag == V_ASN1_NUMERICSTRING) ||
  164. (tag == V_ASN1_UTF8STRING) ||
  165. (tag == V_ASN1_UTCTIME) || (tag == V_ASN1_GENERALIZEDTIME)) {
  166. if (BIO_write(bp, ":", 1) <= 0)
  167. goto end;
  168. if ((len > 0) && BIO_write(bp, (const char *)p, (int)len)
  169. != (int)len)
  170. goto end;
  171. } else if (tag == V_ASN1_OBJECT) {
  172. opp = op;
  173. if (d2i_ASN1_OBJECT(&o, &opp, len + hl) != NULL) {
  174. if (BIO_write(bp, ":", 1) <= 0)
  175. goto end;
  176. i2a_ASN1_OBJECT(bp, o);
  177. } else {
  178. if (BIO_puts(bp, ":BAD OBJECT") <= 0)
  179. goto end;
  180. dump_cont = 1;
  181. }
  182. } else if (tag == V_ASN1_BOOLEAN) {
  183. if (len != 1) {
  184. if (BIO_puts(bp, ":BAD BOOLEAN") <= 0)
  185. goto end;
  186. dump_cont = 1;
  187. }
  188. if (len > 0)
  189. BIO_printf(bp, ":%u", p[0]);
  190. } else if (tag == V_ASN1_BMPSTRING) {
  191. /* do the BMP thang */
  192. } else if (tag == V_ASN1_OCTET_STRING) {
  193. int i, printable = 1;
  194. opp = op;
  195. os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl);
  196. if (os != NULL && os->length > 0) {
  197. opp = os->data;
  198. /*
  199. * testing whether the octet string is printable
  200. */
  201. for (i = 0; i < os->length; i++) {
  202. if (((opp[i] < ' ') &&
  203. (opp[i] != '\n') &&
  204. (opp[i] != '\r') &&
  205. (opp[i] != '\t')) || (opp[i] > '~')) {
  206. printable = 0;
  207. break;
  208. }
  209. }
  210. if (printable)
  211. /* printable string */
  212. {
  213. if (BIO_write(bp, ":", 1) <= 0)
  214. goto end;
  215. if (BIO_write(bp, (const char *)opp, os->length) <= 0)
  216. goto end;
  217. } else if (!dump)
  218. /*
  219. * not printable => print octet string as hex dump
  220. */
  221. {
  222. if (BIO_write(bp, "[HEX DUMP]:", 11) <= 0)
  223. goto end;
  224. for (i = 0; i < os->length; i++) {
  225. if (BIO_printf(bp, "%02X", opp[i]) <= 0)
  226. goto end;
  227. }
  228. } else
  229. /* print the normal dump */
  230. {
  231. if (!nl) {
  232. if (BIO_write(bp, "\n", 1) <= 0)
  233. goto end;
  234. }
  235. if (BIO_dump_indent(bp,
  236. (const char *)opp,
  237. ((dump == -1 || dump >
  238. os->
  239. length) ? os->length : dump),
  240. dump_indent) <= 0)
  241. goto end;
  242. nl = 1;
  243. }
  244. }
  245. ASN1_OCTET_STRING_free(os);
  246. os = NULL;
  247. } else if (tag == V_ASN1_INTEGER) {
  248. int i;
  249. opp = op;
  250. ai = d2i_ASN1_INTEGER(NULL, &opp, len + hl);
  251. if (ai != NULL) {
  252. if (BIO_write(bp, ":", 1) <= 0)
  253. goto end;
  254. if (ai->type == V_ASN1_NEG_INTEGER)
  255. if (BIO_write(bp, "-", 1) <= 0)
  256. goto end;
  257. for (i = 0; i < ai->length; i++) {
  258. if (BIO_printf(bp, "%02X", ai->data[i]) <= 0)
  259. goto end;
  260. }
  261. if (ai->length == 0) {
  262. if (BIO_write(bp, "00", 2) <= 0)
  263. goto end;
  264. }
  265. } else {
  266. if (BIO_puts(bp, ":BAD INTEGER") <= 0)
  267. goto end;
  268. dump_cont = 1;
  269. }
  270. ASN1_INTEGER_free(ai);
  271. ai = NULL;
  272. } else if (tag == V_ASN1_ENUMERATED) {
  273. int i;
  274. opp = op;
  275. ae = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl);
  276. if (ae != NULL) {
  277. if (BIO_write(bp, ":", 1) <= 0)
  278. goto end;
  279. if (ae->type == V_ASN1_NEG_ENUMERATED)
  280. if (BIO_write(bp, "-", 1) <= 0)
  281. goto end;
  282. for (i = 0; i < ae->length; i++) {
  283. if (BIO_printf(bp, "%02X", ae->data[i]) <= 0)
  284. goto end;
  285. }
  286. if (ae->length == 0) {
  287. if (BIO_write(bp, "00", 2) <= 0)
  288. goto end;
  289. }
  290. } else {
  291. if (BIO_puts(bp, ":BAD ENUMERATED") <= 0)
  292. goto end;
  293. dump_cont = 1;
  294. }
  295. ASN1_ENUMERATED_free(ae);
  296. ae = NULL;
  297. } else if (len > 0 && dump) {
  298. if (!nl) {
  299. if (BIO_write(bp, "\n", 1) <= 0)
  300. goto end;
  301. }
  302. if (BIO_dump_indent(bp, (const char *)p,
  303. ((dump == -1 || dump > len) ? len : dump),
  304. dump_indent) <= 0)
  305. goto end;
  306. nl = 1;
  307. }
  308. if (dump_cont) {
  309. int i;
  310. const unsigned char *tmp = op + hl;
  311. if (BIO_puts(bp, ":[") <= 0)
  312. goto end;
  313. for (i = 0; i < len; i++) {
  314. if (BIO_printf(bp, "%02X", tmp[i]) <= 0)
  315. goto end;
  316. }
  317. if (BIO_puts(bp, "]") <= 0)
  318. goto end;
  319. dump_cont = 0;
  320. }
  321. if (!nl) {
  322. if (BIO_write(bp, "\n", 1) <= 0)
  323. goto end;
  324. }
  325. p += len;
  326. if ((tag == V_ASN1_EOC) && (xclass == 0)) {
  327. ret = 2; /* End of sequence */
  328. goto end;
  329. }
  330. }
  331. length -= len;
  332. }
  333. ret = 1;
  334. end:
  335. ASN1_OBJECT_free(o);
  336. ASN1_OCTET_STRING_free(os);
  337. ASN1_INTEGER_free(ai);
  338. ASN1_ENUMERATED_free(ae);
  339. *pp = p;
  340. return ret;
  341. }
  342. const char *ASN1_tag2str(int tag)
  343. {
  344. static const char *const tag2str[] = {
  345. /* 0-4 */
  346. "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING",
  347. /* 5-9 */
  348. "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL",
  349. /* 10-13 */
  350. "ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>",
  351. /* 15-17 */
  352. "<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET",
  353. /* 18-20 */
  354. "NUMERICSTRING", "PRINTABLESTRING", "T61STRING",
  355. /* 21-24 */
  356. "VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME",
  357. /* 25-27 */
  358. "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING",
  359. /* 28-30 */
  360. "UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING"
  361. };
  362. if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
  363. tag &= ~0x100;
  364. if (tag < 0 || tag > 30)
  365. return "(unknown)";
  366. return tag2str[tag];
  367. }