der_print_flexi.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
  2. /* SPDX-License-Identifier: Unlicense */
  3. /* DER flexi-decode a certificate */
  4. #include "tomcrypt_private.h"
  5. #include <wchar.h>
  6. #define ASN1_FMTSTRING_FMT "line: %d, type=%d, size=%lu, data=%p, self=%p, next=%p, prev=%p, parent=%p, child=%p"
  7. #define ASN1_FMTSTRING_VAL(l) __LINE__, (l)->type, (l)->size, (l)->data, (l), (l)->next, (l)->prev, (l)->parent, (l)->child
  8. static void* s_xmalloc(int l)
  9. {
  10. void *r = XCALLOC(1, l);
  11. #if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 3
  12. fprintf(stderr, "ALLOC %9d to %p\n", l, r);
  13. #endif
  14. if (!r) {
  15. fprintf(stderr, "Could not allocate %d bytes of memory\n", l);
  16. exit(EXIT_FAILURE);
  17. }
  18. return r;
  19. }
  20. #ifndef S_FREE
  21. static void s_free(void *p)
  22. {
  23. #if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 3
  24. fprintf(stderr, "FREE %p\n", p);
  25. #endif
  26. XFREE(p);
  27. }
  28. #endif
  29. static void s_der_print_flexi_i(const ltc_asn1_list* l, unsigned int level)
  30. {
  31. char *buf = NULL;
  32. const char *name = NULL;
  33. const char *text = NULL;
  34. ltc_asn1_list *ostring = NULL;
  35. unsigned int n;
  36. int slen;
  37. const wchar_t *wtmp;
  38. switch (l->type)
  39. {
  40. case LTC_ASN1_EOL:
  41. name = "EOL";
  42. slen = snprintf(NULL, 0, ASN1_FMTSTRING_FMT "\n", ASN1_FMTSTRING_VAL(l));
  43. buf = s_xmalloc(slen);
  44. snprintf(buf, slen, ASN1_FMTSTRING_FMT "\n", ASN1_FMTSTRING_VAL(l));
  45. text = buf;
  46. break;
  47. case LTC_ASN1_BOOLEAN:
  48. name = "BOOLEAN";
  49. {
  50. if (*(int*) l->data)
  51. text = "true";
  52. else
  53. text = "false";
  54. }
  55. break;
  56. case LTC_ASN1_INTEGER:
  57. name = "INTEGER";
  58. buf = s_xmalloc(((ltc_mp_get_digit_count(l->data) + 1) * ltc_mp.bits_per_digit) / 3);
  59. ltc_mp_toradix(l->data, buf, 10);
  60. text = buf;
  61. break;
  62. case LTC_ASN1_SHORT_INTEGER:
  63. name = "SHORT INTEGER";
  64. break;
  65. case LTC_ASN1_BIT_STRING:
  66. name = "BIT STRING";
  67. if (l->size <= 16) {
  68. int r;
  69. int sz = l->size + 1;
  70. char *s = buf = s_xmalloc(sz);
  71. for (n = 0; n < l->size; ++n) {
  72. r = snprintf(s, sz, "%c", ((unsigned char*) l->data)[n] ? '1' : '0');
  73. if (r < 0 || r >= sz) {
  74. fprintf(stderr, "%s boom\n", name);
  75. exit(EXIT_FAILURE);
  76. }
  77. s += r;
  78. sz -= r;
  79. }
  80. } else {
  81. slen = snprintf(NULL, 0, "Length %lu", l->size);
  82. buf = s_xmalloc(slen);
  83. snprintf(buf, slen, "Length %lu", l->size);
  84. }
  85. text = buf;
  86. break;
  87. case LTC_ASN1_OCTET_STRING:
  88. name = "OCTET STRING";
  89. {
  90. unsigned long ostring_l = l->size;
  91. /* sometimes there's another sequence in an octet string...
  92. * try to decode that... if it fails print out the octet string
  93. */
  94. if (der_decode_sequence_flexi(l->data, &ostring_l, &ostring) == CRYPT_OK) {
  95. text = "";
  96. } else {
  97. int r;
  98. int sz = l->size * 2 + 1;
  99. char *s = buf = s_xmalloc(sz);
  100. for (n = 0; n < l->size; ++n) {
  101. r = snprintf(s, sz, "%02X", ((unsigned char*) l->data)[n]);
  102. if (r < 0 || r >= sz) {
  103. fprintf(stderr, "%s boom\n", name);
  104. exit(EXIT_FAILURE);
  105. }
  106. s += r;
  107. sz -= r;
  108. }
  109. text = buf;
  110. }
  111. }
  112. break;
  113. case LTC_ASN1_NULL:
  114. name = "NULL";
  115. text = "";
  116. break;
  117. case LTC_ASN1_OBJECT_IDENTIFIER:
  118. name = "OBJECT IDENTIFIER";
  119. {
  120. unsigned long len = 0;
  121. if (pk_oid_num_to_str(l->data, l->size, buf, &len) != CRYPT_BUFFER_OVERFLOW) {
  122. fprintf(stderr, "%s WTF\n", name);
  123. exit(EXIT_FAILURE);
  124. }
  125. buf = s_xmalloc(len);
  126. if (pk_oid_num_to_str(l->data, l->size, buf, &len) != CRYPT_OK) {
  127. fprintf(stderr, "%s boom\n", name);
  128. exit(EXIT_FAILURE);
  129. }
  130. text = buf;
  131. }
  132. break;
  133. case LTC_ASN1_IA5_STRING:
  134. name = "IA5 STRING";
  135. text = l->data;
  136. break;
  137. case LTC_ASN1_PRINTABLE_STRING:
  138. name = "PRINTABLE STRING";
  139. text = l->data;
  140. break;
  141. case LTC_ASN1_UTF8_STRING:
  142. name = "UTF8 STRING";
  143. wtmp = l->data;
  144. slen = wcsrtombs(NULL, &wtmp, 0, NULL);
  145. if (slen != -1) {
  146. slen++;
  147. buf = s_xmalloc(slen);
  148. if (wcsrtombs(buf, &wtmp, slen, NULL) == (size_t)-1) {
  149. fprintf(stderr, "%s boom\n", name);
  150. exit(EXIT_FAILURE);
  151. }
  152. text = buf;
  153. }
  154. break;
  155. case LTC_ASN1_UTCTIME:
  156. name = "UTCTIME";
  157. {
  158. ltc_utctime *ut = l->data;
  159. slen = 32;
  160. buf = s_xmalloc(slen);
  161. snprintf(buf, slen, "%02d-%02d-%02d %02d:%02d:%02d %c%02d:%02d", ut->YY, ut->MM, ut->DD, ut->hh, ut->mm,
  162. ut->ss, ut->off_dir ? '-' : '+', ut->off_hh, ut->off_mm);
  163. text = buf;
  164. }
  165. break;
  166. case LTC_ASN1_GENERALIZEDTIME:
  167. name = "GENERALIZED TIME";
  168. {
  169. ltc_generalizedtime *gt = l->data;
  170. slen = 32;
  171. buf = s_xmalloc(slen);
  172. if (gt->fs)
  173. snprintf(buf, slen, "%04d-%02d-%02d %02d:%02d:%02d.%02dZ", gt->YYYY, gt->MM, gt->DD, gt->hh, gt->mm,
  174. gt->ss, gt->fs);
  175. else
  176. snprintf(buf, slen, "%04d-%02d-%02d %02d:%02d:%02dZ", gt->YYYY, gt->MM, gt->DD, gt->hh, gt->mm, gt->ss);
  177. text = buf;
  178. }
  179. break;
  180. case LTC_ASN1_CHOICE:
  181. name = "CHOICE";
  182. break;
  183. case LTC_ASN1_SEQUENCE:
  184. name = "SEQUENCE";
  185. text = "";
  186. break;
  187. case LTC_ASN1_SET:
  188. name = "SET";
  189. text = "";
  190. break;
  191. case LTC_ASN1_SETOF:
  192. name = "SETOF";
  193. text = "";
  194. break;
  195. case LTC_ASN1_RAW_BIT_STRING:
  196. name = "RAW BIT STRING";
  197. break;
  198. case LTC_ASN1_TELETEX_STRING:
  199. name = "TELETEX STRING";
  200. text = l->data;
  201. break;
  202. case LTC_ASN1_CUSTOM_TYPE:
  203. name = "NON STANDARD";
  204. {
  205. int r;
  206. int sz = 128;
  207. char *s = buf = s_xmalloc(sz);
  208. r = snprintf(s, sz, "[%s %s %llu]", der_asn1_class_to_string_map[l->klass],
  209. der_asn1_pc_to_string_map[l->pc], l->tag);
  210. if (r < 0 || r >= sz) {
  211. fprintf(stderr, "%s boom\n", name);
  212. exit(EXIT_FAILURE);
  213. }
  214. text = buf;
  215. }
  216. break;
  217. }
  218. for (n = 0; n < level; ++n) {
  219. fprintf(stderr, " ");
  220. }
  221. if (name) {
  222. if (text)
  223. fprintf(stderr, "%s %s\n", name, text);
  224. else
  225. fprintf(stderr, "%s <missing decoding>\n", name);
  226. } else
  227. fprintf(stderr, "WTF type=%i\n", l->type);
  228. if (buf) {
  229. s_free(buf);
  230. buf = NULL;
  231. }
  232. if (ostring) {
  233. s_der_print_flexi_i(ostring, level + 1);
  234. der_free_sequence_flexi(ostring);
  235. }
  236. if (l->child) s_der_print_flexi_i(l->child, level + 1);
  237. if (l->next) s_der_print_flexi_i(l->next, level);
  238. }
  239. #ifndef LTC_DER_PRINT_FLEXI_NO_MAIN
  240. static void s_der_print_flexi(const ltc_asn1_list* l)
  241. {
  242. fprintf(stderr, "\n\n");
  243. s_der_print_flexi_i(l, 0);
  244. fprintf(stderr, "\n\n");
  245. }
  246. #include <sys/mman.h>
  247. #include <sys/stat.h>
  248. #include <fcntl.h>
  249. #include <stdio.h>
  250. #include <stdlib.h>
  251. #include <unistd.h>
  252. static int fd;
  253. static ltc_asn1_list *l;
  254. static void print_err(const char *fmt, ...)
  255. {
  256. va_list args;
  257. va_start(args, fmt);
  258. vfprintf(stderr, fmt, args);
  259. va_end(args);
  260. }
  261. static void die_(int err, int line)
  262. {
  263. print_err("%3d: LTC sez %s\n", line, error_to_string(err));
  264. der_free_sequence_flexi(l);
  265. close(fd);
  266. exit(EXIT_FAILURE);
  267. }
  268. #define die(i) do { die_(i, __LINE__); } while(0)
  269. #define DIE(s, ...) do { print_err("%3d: " s "\n", __LINE__, ##__VA_ARGS__); exit(EXIT_FAILURE); } while(0)
  270. int main(int argc, char **argv)
  271. {
  272. void *addr;
  273. int err, argn = 1;
  274. struct stat sb;
  275. unsigned long len;
  276. if ((err = register_all_hashes()) != CRYPT_OK) {
  277. die(err);
  278. }
  279. if ((err = crypt_mp_init("ltm")) != CRYPT_OK) {
  280. die(err);
  281. }
  282. if (argc > argn) fd = open(argv[argn], O_RDONLY);
  283. else fd = STDIN_FILENO;
  284. if (fd == -1) DIE("open sez no");
  285. if (fstat(fd, &sb) == -1) DIE("fstat");
  286. addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  287. if (addr == MAP_FAILED) DIE("mmap");
  288. len = sb.st_size;
  289. if ((err = der_decode_sequence_flexi(addr, &len, &l)) != CRYPT_OK) {
  290. die(err);
  291. }
  292. s_der_print_flexi(l);
  293. der_free_sequence_flexi(l);
  294. close(fd);
  295. return 0;
  296. }
  297. #endif /* LTC_DER_PRINT_FLEXI_NO_MAIN */