973562bff1bcc97f907ed50e041f720128e48fb3
[strongswan.git] / src / libstrongswan / tests / suites / test_asn1_parser.c
1 /*
2 * Copyright (C) 2014 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "test_suite.h"
17
18 #include <asn1/asn1_parser.h>
19 #include <utils/chunk.h>
20
21 /*******************************************************************************
22 * utilities
23 */
24
25 typedef struct {
26 bool success;
27 int count;
28 chunk_t blob;
29 } asn1_test_t;
30
31 static void run_parser_test(const asn1Object_t *objects, int id,
32 asn1_test_t *test)
33 {
34 asn1_parser_t *parser;
35 chunk_t object;
36 int objectID, count = 0;
37 bool success;
38
39 parser = asn1_parser_create(objects, test->blob);
40 while (parser->iterate(parser, &objectID, &object))
41 {
42 if (objectID == id)
43 {
44 count++;
45 }
46 }
47 success = parser->success(parser);
48 parser->destroy(parser);
49
50 ck_assert(success == test->success && count == test->count);
51 }
52
53 /*******************************************************************************
54 * length
55 */
56
57 static const asn1Object_t octetStringObjects[] = {
58 { 0, "octetString", ASN1_OCTET_STRING, ASN1_BODY }, /* 0 */
59 { 0, "exit", ASN1_EOC, ASN1_EXIT }
60 };
61
62 asn1_test_t length_tests[] = {
63 { FALSE, 0, { NULL, 0 } },
64 { FALSE, 0, chunk_from_chars(0x04) },
65 { TRUE, 1, chunk_from_chars(0x04, 0x00) },
66 { TRUE, 1, chunk_from_chars(0x04, 0x01, 0xaa) },
67 { FALSE, 0, chunk_from_chars(0x04, 0x7f) },
68 { FALSE, 0, chunk_from_chars(0x04, 0x80) },
69 { FALSE, 0, chunk_from_chars(0x04, 0x81) },
70 { TRUE, 1, chunk_from_chars(0x04, 0x81, 0x00) },
71 { FALSE, 0, chunk_from_chars(0x04, 0x81, 0x01) },
72 { TRUE, 1, chunk_from_chars(0x04, 0x81, 0x01, 0xaa) },
73 { FALSE, 0, chunk_from_chars(0x04, 0x82, 0x00, 0x01) },
74 { TRUE, 1, chunk_from_chars(0x04, 0x82, 0x00, 0x01, 0xaa) },
75 { FALSE, 0, chunk_from_chars(0x04, 0x83, 0x00, 0x00, 0x01) },
76 { TRUE, 1, chunk_from_chars(0x04, 0x83, 0x00, 0x00, 0x01, 0xaa) },
77 { FALSE, 0, chunk_from_chars(0x04, 0x84, 0x00, 0x00, 0x00, 0x01) },
78 { TRUE, 1, chunk_from_chars(0x04, 0x84, 0x00, 0x00, 0x00, 0x01, 0xaa) },
79 };
80
81 START_TEST(test_asn1_parser_length)
82 {
83 run_parser_test(octetStringObjects, 0, &length_tests[_i]);
84 }
85 END_TEST
86
87 /*******************************************************************************
88 * loop
89 */
90
91 static const asn1Object_t loopObjects[] = {
92 { 0, "loopObjects", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
93 { 1, "octetString", ASN1_OCTET_STRING, ASN1_BODY }, /* 1 */
94 { 0, "end loop", ASN1_EOC, ASN1_END }, /* 2 */
95 { 0, "exit", ASN1_EOC, ASN1_EXIT }
96 };
97
98 asn1_test_t loop_tests[] = {
99 { TRUE, 0, chunk_from_chars(0x30, 0x00) },
100 { FALSE, 0, chunk_from_chars(0x30, 0x02, 0x04, 0x01) },
101 { TRUE, 1, chunk_from_chars(0x30, 0x03, 0x04, 0x01, 0xaa) },
102 { TRUE, 2, chunk_from_chars(0x30, 0x05, 0x04, 0x01, 0xaa, 0x04, 0x00) },
103 { FALSE, 1, chunk_from_chars(0x30, 0x05, 0x04, 0x01, 0xaa, 0x05, 0x00) },
104 { TRUE, 3, chunk_from_chars(0x30, 0x09, 0x04, 0x01, 0xaa, 0x04, 0x00,
105 0x04, 0x02, 0xbb, 0xcc) },
106 };
107
108 START_TEST(test_asn1_parser_loop)
109 {
110 run_parser_test(loopObjects, 1, &loop_tests[_i]);
111 }
112 END_TEST
113
114 /*******************************************************************************
115 * default
116 */
117
118 typedef struct {
119 int i1, i2, i3;
120 chunk_t blob;
121 } default_opt_test_t;
122
123 static const asn1Object_t defaultObjects[] = {
124 { 0, "defaultObjects", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
125 { 1, "explicit int1", ASN1_CONTEXT_C_1, ASN1_DEF }, /* 1 */
126 { 2, "int1", ASN1_INTEGER, ASN1_BODY }, /* 2 */
127 { 1, "int2", ASN1_INTEGER, ASN1_DEF|ASN1_BODY }, /* 3 */
128 { 1, "implicit int3", ASN1_CONTEXT_S_3, ASN1_DEF|ASN1_BODY }, /* 4 */
129 { 0, "exit", ASN1_EOC, ASN1_EXIT }
130 };
131
132 default_opt_test_t default_tests[] = {
133 { -1, -2, -3, chunk_from_chars(0x30, 0x00) },
134 { 1, -2, -3, chunk_from_chars(0x30, 0x05, 0xa1, 0x03, 0x02, 0x01, 0x01) },
135 { -1, 2, -3, chunk_from_chars(0x30, 0x03, 0x02, 0x01, 0x02) },
136 { -1, -2, 3, chunk_from_chars(0x30, 0x03, 0x83, 0x01, 0x03) },
137 { 1, 2, -3, chunk_from_chars(0x30, 0x08, 0xa1, 0x03, 0x02, 0x01, 0x01,
138 0x02, 0x01, 0x02) },
139 { 1, -2, 3, chunk_from_chars(0x30, 0x08, 0xa1, 0x03, 0x02, 0x01, 0x01,
140 0x83, 0x01, 0x03) },
141 { -1, 2, 3, chunk_from_chars(0x30, 0x06, 0x02, 0x01, 0x02,
142 0x83, 0x01, 0x03) },
143 { 1, 2, 3, chunk_from_chars(0x30, 0x0b, 0xa1, 0x03, 0x02, 0x01, 0x01,
144 0x02, 0x01, 0x02,
145 0x83, 0x01, 0x03) },
146 { 0, 0, 0, chunk_from_chars(0x30, 0x0b, 0xa1, 0x03, 0x04, 0x01, 0xaa,
147 0x02, 0x01, 0x02,
148 0x83, 0x01, 0x03) },
149 { 1, 0, 0, chunk_from_chars(0x30, 0x0b, 0xa1, 0x03, 0x02, 0x01, 0x01,
150 0x02, 0x05, 0x02,
151 0x83, 0x01, 0x03) },
152 { 1, 2, 0, chunk_from_chars(0x30, 0x0b, 0xa1, 0x03, 0x02, 0x01, 0x01,
153 0x02, 0x01, 0x02,
154 0x83, 0x02, 0x03) },
155 };
156
157 START_TEST(test_asn1_parser_default)
158 {
159 asn1_parser_t *parser;
160 chunk_t object;
161 int objectID, i1 = 0, i2 = 0, i3 = 0;
162 bool success;
163
164 parser = asn1_parser_create(defaultObjects, default_tests[_i].blob);
165 while (parser->iterate(parser, &objectID, &object))
166 {
167 switch (objectID)
168 {
169 case 2:
170 i1 = object.len ? *object.ptr : -1;
171 break;
172 case 3:
173 i2 = object.len ? *object.ptr : -2;
174 break;
175 case 4:
176 i3 = object.len ? *object.ptr : -3;
177 break;
178 default:
179 break;
180 }
181 }
182 success = parser->success(parser);
183 parser->destroy(parser);
184
185 ck_assert(success == (default_tests[_i].i1 &&
186 default_tests[_i].i2 &&
187 default_tests[_i].i3));
188
189 ck_assert(i1 == default_tests[_i].i1 &&
190 i2 == default_tests[_i].i2 &&
191 i3 == default_tests[_i].i3);
192 }
193 END_TEST
194
195 /*******************************************************************************
196 * option
197 */
198
199 static const asn1Object_t optionObjects[] = {
200 { 0, "optionalObjects", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
201 { 1, "sequence int1", ASN1_SEQUENCE, ASN1_OPT }, /* 1 */
202 { 2, "int1", ASN1_INTEGER, ASN1_OPT|ASN1_BODY }, /* 2 */
203 { 2, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
204 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 4 */
205 { 1, "int2", ASN1_INTEGER, ASN1_OPT|ASN1_BODY }, /* 5 */
206 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 6 */
207 { 1, "implicit int3", ASN1_CONTEXT_S_3, ASN1_OPT|ASN1_BODY }, /* 7 */
208 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 8 */
209 { 0, "exit", ASN1_EOC, ASN1_EXIT }
210 };
211
212 default_opt_test_t option_tests[] = {
213 { 0, 0, 0, chunk_from_chars(0x30, 0x00) },
214 { 1, 0, 0, chunk_from_chars(0x30, 0x05, 0x30, 0x03, 0x02, 0x01, 0x01) },
215 { 0, 2, 0, chunk_from_chars(0x30, 0x03, 0x02, 0x01, 0x02) },
216 { 0, 0, 3, chunk_from_chars(0x30, 0x03, 0x83, 0x01, 0x03) },
217 { 1, 2, 0, chunk_from_chars(0x30, 0x08, 0x30, 0x03, 0x02, 0x01, 0x01,
218 0x02, 0x01, 0x02) },
219 { 1, 0, 3, chunk_from_chars(0x30, 0x08, 0x30, 0x03, 0x02, 0x01, 0x01,
220 0x83, 0x01, 0x03) },
221 { 0, 2, 3, chunk_from_chars(0x30, 0x06, 0x02, 0x01, 0x02,
222 0x83, 0x01, 0x03) },
223 { 1, 2, 3, chunk_from_chars(0x30, 0x0b, 0x30, 0x03, 0x02, 0x01, 0x01,
224 0x02, 0x01, 0x02,
225 0x83, 0x01, 0x03) },
226 { 0, 2, 3, chunk_from_chars(0x30, 0x08, 0x30, 0x00,
227 0x02, 0x01, 0x02,
228 0x83, 0x01, 0x03) },
229 };
230
231 START_TEST(test_asn1_parser_option)
232 {
233 asn1_parser_t *parser;
234 chunk_t object;
235 int objectID, i1 = 0, i2 = 0, i3 = 0;
236 bool success;
237
238 parser = asn1_parser_create(optionObjects, option_tests[_i].blob);
239 while (parser->iterate(parser, &objectID, &object))
240 {
241 switch (objectID)
242 {
243 case 2:
244 i1 = *object.ptr;
245 break;
246 case 5:
247 i2 = *object.ptr;
248 break;
249 case 7:
250 i3 = *object.ptr;
251 break;
252 default:
253 break;
254 }
255 }
256 success = parser->success(parser);
257 parser->destroy(parser);
258
259 ck_assert(success);
260
261 ck_assert(i1 == option_tests[_i].i1 &&
262 i2 == option_tests[_i].i2 &&
263 i3 == option_tests[_i].i3);
264 }
265 END_TEST
266
267 Suite *asn1_parser_suite_create()
268 {
269 Suite *s;
270 TCase *tc;
271
272 s = suite_create("asn1_parser");
273
274 tc = tcase_create("length");
275 tcase_add_loop_test(tc, test_asn1_parser_length, 0, countof(length_tests));
276 suite_add_tcase(s, tc);
277
278 tc = tcase_create("loop");
279 tcase_add_loop_test(tc, test_asn1_parser_loop, 0, countof(loop_tests));
280 suite_add_tcase(s, tc);
281
282 tc = tcase_create("default");
283 tcase_add_loop_test(tc, test_asn1_parser_default, 0, countof(default_tests));
284 suite_add_tcase(s, tc);
285
286 tc = tcase_create("option");
287 tcase_add_loop_test(tc, test_asn1_parser_option, 0, countof(option_tests));
288 suite_add_tcase(s, tc);
289
290 return s;
291 }