• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Testing tool for ASN.1/X.509v3 routines
3  * Copyright (c) 2006, 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 
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 
asn1_class_str(int class)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 
asn1_parse(const u8 * buf,size_t len,int level)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 
main(int argc,char * argv[])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