test-asn1.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * Testing tool for ASN.1 routines
  3. * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "includes.h"
  15. #include "common.h"
  16. #include "tls/asn1.h"
  17. extern int wpa_debug_level;
  18. static const char * asn1_class_str(int class)
  19. {
  20. switch (class) {
  21. case ASN1_CLASS_UNIVERSAL:
  22. return "Universal";
  23. case ASN1_CLASS_APPLICATION:
  24. return "Application";
  25. case ASN1_CLASS_CONTEXT_SPECIFIC:
  26. return "Context-specific";
  27. case ASN1_CLASS_PRIVATE:
  28. return "Private";
  29. default:
  30. return "?";
  31. }
  32. }
  33. int asn1_parse(const u8 *buf, size_t len, int level)
  34. {
  35. const u8 *pos, *prev, *end;
  36. char prefix[10], str[100];
  37. int _level;
  38. struct asn1_hdr hdr;
  39. struct asn1_oid oid;
  40. u8 tmp;
  41. _level = level;
  42. if ((size_t) _level > sizeof(prefix) - 1)
  43. _level = sizeof(prefix) - 1;
  44. memset(prefix, ' ', _level);
  45. prefix[_level] = '\0';
  46. pos = buf;
  47. end = buf + len;
  48. while (pos < end) {
  49. if (asn1_get_next(pos, end - pos, &hdr) < 0)
  50. return -1;
  51. prev = pos;
  52. pos = hdr.payload;
  53. wpa_printf(MSG_MSGDUMP, "ASN.1:%s Class %d(%s) P/C %d(%s) "
  54. "Tag %u Length %u",
  55. prefix, hdr.class, asn1_class_str(hdr.class),
  56. hdr.constructed,
  57. hdr.constructed ? "Constructed" : "Primitive",
  58. hdr.tag, hdr.length);
  59. if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC &&
  60. hdr.constructed) {
  61. if (asn1_parse(pos, hdr.length, level + 1) < 0)
  62. return -1;
  63. pos += hdr.length;
  64. }
  65. if (hdr.class != ASN1_CLASS_UNIVERSAL)
  66. continue;
  67. switch (hdr.tag) {
  68. case ASN1_TAG_EOC:
  69. if (hdr.length) {
  70. wpa_printf(MSG_DEBUG, "ASN.1: Non-zero "
  71. "end-of-contents length (%u)",
  72. hdr.length);
  73. return -1;
  74. }
  75. wpa_printf(MSG_MSGDUMP, "ASN.1:%s EOC", prefix);
  76. break;
  77. case ASN1_TAG_BOOLEAN:
  78. if (hdr.length != 1) {
  79. wpa_printf(MSG_DEBUG, "ASN.1: Unexpected "
  80. "Boolean length (%u)", hdr.length);
  81. return -1;
  82. }
  83. tmp = *pos++;
  84. wpa_printf(MSG_MSGDUMP, "ASN.1:%s Boolean %s",
  85. prefix, tmp ? "TRUE" : "FALSE");
  86. break;
  87. case ASN1_TAG_INTEGER:
  88. wpa_hexdump(MSG_MSGDUMP, "ASN.1: INTEGER",
  89. pos, hdr.length);
  90. pos += hdr.length;
  91. break;
  92. case ASN1_TAG_BITSTRING:
  93. wpa_hexdump(MSG_MSGDUMP, "ASN.1: BitString",
  94. pos, hdr.length);
  95. pos += hdr.length;
  96. break;
  97. case ASN1_TAG_OCTETSTRING:
  98. wpa_hexdump(MSG_MSGDUMP, "ASN.1: OctetString",
  99. pos, hdr.length);
  100. pos += hdr.length;
  101. break;
  102. case ASN1_TAG_NULL:
  103. if (hdr.length) {
  104. wpa_printf(MSG_DEBUG, "ASN.1: Non-zero Null "
  105. "length (%u)", hdr.length);
  106. return -1;
  107. }
  108. wpa_printf(MSG_MSGDUMP, "ASN.1:%s Null", prefix);
  109. break;
  110. case ASN1_TAG_OID:
  111. if (asn1_get_oid(prev, end - prev, &oid, &prev) < 0) {
  112. wpa_printf(MSG_DEBUG, "ASN.1: Invalid OID");
  113. return -1;
  114. }
  115. asn1_oid_to_str(&oid, str, sizeof(str));
  116. wpa_printf(MSG_DEBUG, "ASN.1:%s OID %s", prefix, str);
  117. pos += hdr.length;
  118. break;
  119. case ANS1_TAG_RELATIVE_OID:
  120. wpa_hexdump(MSG_MSGDUMP, "ASN.1: Relative OID",
  121. pos, hdr.length);
  122. pos += hdr.length;
  123. break;
  124. case ASN1_TAG_SEQUENCE:
  125. wpa_printf(MSG_MSGDUMP, "ASN.1:%s SEQUENCE", prefix);
  126. if (asn1_parse(pos, hdr.length, level + 1) < 0)
  127. return -1;
  128. pos += hdr.length;
  129. break;
  130. case ASN1_TAG_SET:
  131. wpa_printf(MSG_MSGDUMP, "ASN.1:%s SET", prefix);
  132. if (asn1_parse(pos, hdr.length, level + 1) < 0)
  133. return -1;
  134. pos += hdr.length;
  135. break;
  136. case ASN1_TAG_PRINTABLESTRING:
  137. wpa_hexdump_ascii(MSG_MSGDUMP,
  138. "ASN.1: PrintableString",
  139. pos, hdr.length);
  140. pos += hdr.length;
  141. break;
  142. case ASN1_TAG_IA5STRING:
  143. wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: IA5String",
  144. pos, hdr.length);
  145. pos += hdr.length;
  146. break;
  147. case ASN1_TAG_UTCTIME:
  148. wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: UTCTIME",
  149. pos, hdr.length);
  150. pos += hdr.length;
  151. break;
  152. case ASN1_TAG_VISIBLESTRING:
  153. wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: VisibleString",
  154. pos, hdr.length);
  155. pos += hdr.length;
  156. break;
  157. default:
  158. wpa_printf(MSG_DEBUG, "ASN.1: Unknown tag %d",
  159. hdr.tag);
  160. return -1;
  161. }
  162. }
  163. return 0;
  164. }
  165. int main(int argc, char *argv[])
  166. {
  167. FILE *f;
  168. u8 buf[3000];
  169. size_t len;
  170. wpa_debug_level = 0;
  171. f = fopen(argv[1], "rb");
  172. if (f == NULL)
  173. return -1;
  174. len = fread(buf, 1, sizeof(buf), f);
  175. fclose(f);
  176. if (asn1_parse(buf, len, 0) < 0)
  177. printf("Failed to parse DER ASN.1\n");
  178. printf("\n\n");
  179. return 0;
  180. }