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