1 /* 2 * Testing tool for ASN.1/X.509v3 routines 3 * Copyright (c) 2006, Jouni Malinen <j (at) 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 15 #include "includes.h" 16 17 #include "common.h" 18 #include "asn1.h" 19 #include "x509v3.h" 20 21 extern int wpa_debug_level; 22 23 24 static const char * asn1_class_str(int class) 25 { 26 switch (class) { 27 case ASN1_CLASS_UNIVERSAL: 28 return "Universal"; 29 case ASN1_CLASS_APPLICATION: 30 return "Application"; 31 case ASN1_CLASS_CONTEXT_SPECIFIC: 32 return "Context-specific"; 33 case ASN1_CLASS_PRIVATE: 34 return "Private"; 35 default: 36 return "?"; 37 } 38 } 39 40 41 int asn1_parse(const u8 *buf, size_t len, int level) 42 { 43 const u8 *pos, *prev, *end; 44 char prefix[10], str[100]; 45 int _level; 46 struct asn1_hdr hdr; 47 struct asn1_oid oid; 48 u8 tmp; 49 50 _level = level; 51 if ((size_t) _level > sizeof(prefix) - 1) 52 _level = sizeof(prefix) - 1; 53 memset(prefix, ' ', _level); 54 prefix[_level] = '\0'; 55 56 pos = buf; 57 end = buf + len; 58 59 while (pos < end) { 60 if (asn1_get_next(pos, end - pos, &hdr) < 0) 61 return -1; 62 63 prev = pos; 64 pos = hdr.payload; 65 66 wpa_printf(MSG_MSGDUMP, "ASN.1:%s Class %d(%s) P/C %d(%s) " 67 "Tag %u Length %u", 68 prefix, hdr.class, asn1_class_str(hdr.class), 69 hdr.constructed, 70 hdr.constructed ? "Constructed" : "Primitive", 71 hdr.tag, hdr.length); 72 73 if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC && 74 hdr.constructed) { 75 if (asn1_parse(pos, hdr.length, level + 1) < 0) 76 return -1; 77 pos += hdr.length; 78 } 79 80 if (hdr.class != ASN1_CLASS_UNIVERSAL) 81 continue; 82 83 switch (hdr.tag) { 84 case ASN1_TAG_EOC: 85 if (hdr.length) { 86 wpa_printf(MSG_DEBUG, "ASN.1: Non-zero " 87 "end-of-contents length (%u)", 88 hdr.length); 89 return -1; 90 } 91 wpa_printf(MSG_MSGDUMP, "ASN.1:%s EOC", prefix); 92 break; 93 case ASN1_TAG_BOOLEAN: 94 if (hdr.length != 1) { 95 wpa_printf(MSG_DEBUG, "ASN.1: Unexpected " 96 "Boolean length (%u)", hdr.length); 97 return -1; 98 } 99 tmp = *pos++; 100 wpa_printf(MSG_MSGDUMP, "ASN.1:%s Boolean %s", 101 prefix, tmp ? "TRUE" : "FALSE"); 102 break; 103 case ASN1_TAG_INTEGER: 104 wpa_hexdump(MSG_MSGDUMP, "ASN.1: INTEGER", 105 pos, hdr.length); 106 pos += hdr.length; 107 break; 108 case ASN1_TAG_BITSTRING: 109 wpa_hexdump(MSG_MSGDUMP, "ASN.1: BitString", 110 pos, hdr.length); 111 pos += hdr.length; 112 break; 113 case ASN1_TAG_OCTETSTRING: 114 wpa_hexdump(MSG_MSGDUMP, "ASN.1: OctetString", 115 pos, hdr.length); 116 pos += hdr.length; 117 break; 118 case ASN1_TAG_NULL: 119 if (hdr.length) { 120 wpa_printf(MSG_DEBUG, "ASN.1: Non-zero Null " 121 "length (%u)", hdr.length); 122 return -1; 123 } 124 wpa_printf(MSG_MSGDUMP, "ASN.1:%s Null", prefix); 125 break; 126 case ASN1_TAG_OID: 127 if (asn1_get_oid(prev, end - prev, &oid, &prev) < 0) { 128 wpa_printf(MSG_DEBUG, "ASN.1: Invalid OID"); 129 return -1; 130 } 131 asn1_oid_to_str(&oid, str, sizeof(str)); 132 wpa_printf(MSG_DEBUG, "ASN.1:%s OID %s", prefix, str); 133 pos += hdr.length; 134 break; 135 case ANS1_TAG_RELATIVE_OID: 136 wpa_hexdump(MSG_MSGDUMP, "ASN.1: Relative OID", 137 pos, hdr.length); 138 pos += hdr.length; 139 break; 140 case ASN1_TAG_SEQUENCE: 141 wpa_printf(MSG_MSGDUMP, "ASN.1:%s SEQUENCE", prefix); 142 if (asn1_parse(pos, hdr.length, level + 1) < 0) 143 return -1; 144 pos += hdr.length; 145 break; 146 case ASN1_TAG_SET: 147 wpa_printf(MSG_MSGDUMP, "ASN.1:%s SET", prefix); 148 if (asn1_parse(pos, hdr.length, level + 1) < 0) 149 return -1; 150 pos += hdr.length; 151 break; 152 case ASN1_TAG_PRINTABLESTRING: 153 wpa_hexdump_ascii(MSG_MSGDUMP, 154 "ASN.1: PrintableString", 155 pos, hdr.length); 156 pos += hdr.length; 157 break; 158 case ASN1_TAG_IA5STRING: 159 wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: IA5String", 160 pos, hdr.length); 161 pos += hdr.length; 162 break; 163 case ASN1_TAG_UTCTIME: 164 wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: UTCTIME", 165 pos, hdr.length); 166 pos += hdr.length; 167 break; 168 case ASN1_TAG_VISIBLESTRING: 169 wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: VisibleString", 170 pos, hdr.length); 171 pos += hdr.length; 172 break; 173 default: 174 wpa_printf(MSG_DEBUG, "ASN.1: Unknown tag %d", 175 hdr.tag); 176 return -1; 177 } 178 } 179 180 return 0; 181 } 182 183 184 int main(int argc, char *argv[]) 185 { 186 FILE *f; 187 u8 buf[3000]; 188 size_t len; 189 struct x509_certificate *cert; 190 191 wpa_debug_level = 0; 192 193 f = fopen(argv[1], "rb"); 194 if (f == NULL) 195 return -1; 196 len = fread(buf, 1, sizeof(buf), f); 197 fclose(f); 198 199 if (asn1_parse(buf, len, 0) < 0) 200 printf("Failed to parse DER ASN.1\n"); 201 202 printf("\n\n"); 203 204 cert = x509_certificate_parse(buf, len); 205 if (cert == NULL) 206 printf("Failed to parse X.509 certificate\n"); 207 x509_certificate_free(cert); 208 209 return 0; 210 } 211