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