2 * Copyright (C) 2016-2018 Tobias Brunner
3 * HSR Hochschule fuer Technik Rapperswil
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>.
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
16 #include "test_suite.h"
18 #include <crypto/proposal/proposal.h>
25 { PROTO_IKE
, "", NULL
},
26 { PROTO_IKE
, "sha256", NULL
},
27 { PROTO_IKE
, "sha256-modp3072", NULL
},
28 { PROTO_IKE
, "null-sha256-modp3072", "IKE:NULL/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072" },
29 { PROTO_IKE
, "aes128", NULL
},
30 { PROTO_IKE
, "aes128-sha256", NULL
},
31 { PROTO_IKE
, "aes128-sha256-modpnone", NULL
},
32 { PROTO_IKE
, "aes128-prfsha256", NULL
},
33 { PROTO_IKE
, "aes128-prfsha256-modp2048", NULL
},
34 { PROTO_IKE
, "aes128-sha256-modp3072", "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072" },
35 { PROTO_IKE
, "aes128-sha256-prfsha384-modp3072", "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_384/MODP_3072" },
36 { PROTO_IKE
, "aes128gcm16-modp3072", NULL
},
37 { PROTO_IKE
, "aes128gcm16-prfsha256-modp3072", "IKE:AES_GCM_16_128/PRF_HMAC_SHA2_256/MODP_3072" },
38 { PROTO_IKE
, "aes128gcm16-sha256-modp3072", "IKE:AES_GCM_16_128/PRF_HMAC_SHA2_256/MODP_3072" },
39 { PROTO_IKE
, "aes128gcm16-aes128-modp3072", NULL
},
40 { PROTO_IKE
, "aes128gcm16-aes128-sha256-modp3072", NULL
},
41 { PROTO_ESP
, "", NULL
},
42 { PROTO_ESP
, "sha256", NULL
},
43 { PROTO_ESP
, "aes128-sha256", "ESP:AES_CBC_128/HMAC_SHA2_256_128/NO_EXT_SEQ" },
44 { PROTO_ESP
, "aes128-sha256-esn", "ESP:AES_CBC_128/HMAC_SHA2_256_128/EXT_SEQ" },
45 { PROTO_ESP
, "aes128-sha256-noesn", "ESP:AES_CBC_128/HMAC_SHA2_256_128/NO_EXT_SEQ" },
46 { PROTO_ESP
, "aes128-sha256-esn-noesn", "ESP:AES_CBC_128/HMAC_SHA2_256_128/EXT_SEQ/NO_EXT_SEQ" },
47 { PROTO_ESP
, "aes128-sha256-prfsha256-modp3072", "ESP:AES_CBC_128/HMAC_SHA2_256_128/MODP_3072/NO_EXT_SEQ" },
48 { PROTO_ESP
, "aes128gcm16-aes128-sha256-modp3072", NULL
},
49 { PROTO_ESP
, "aes128gmac", "ESP:NULL_AES_GMAC_128/NO_EXT_SEQ" },
50 { PROTO_AH
, "", NULL
},
51 { PROTO_AH
, "aes128", NULL
},
52 { PROTO_AH
, "aes128-sha256", "AH:HMAC_SHA2_256_128/NO_EXT_SEQ" },
53 { PROTO_AH
, "sha256-sha1", "AH:HMAC_SHA2_256_128/HMAC_SHA1_96/NO_EXT_SEQ" },
54 { PROTO_AH
, "aes128gmac-sha256", "AH:AES_128_GMAC/HMAC_SHA2_256_128/NO_EXT_SEQ" },
55 { PROTO_AH
, "aes128gmac-sha256-prfsha256", "AH:AES_128_GMAC/HMAC_SHA2_256_128/NO_EXT_SEQ" },
56 { PROTO_AH
, "aes128gmac-aes256gmac-aes128-sha256", "AH:AES_128_GMAC/AES_256_GMAC/HMAC_SHA2_256_128/NO_EXT_SEQ" },
57 { PROTO_AH
, "sha256-esn", "AH:HMAC_SHA2_256_128/EXT_SEQ" },
58 { PROTO_AH
, "sha256-noesn", "AH:HMAC_SHA2_256_128/NO_EXT_SEQ" },
59 { PROTO_AH
, "sha256-esn-noesn", "AH:HMAC_SHA2_256_128/EXT_SEQ/NO_EXT_SEQ" },
62 static void assert_proposal_eq(proposal_t
*proposal
, char *expected
)
71 snprintf(str
, sizeof(str
), "%P", proposal
);
72 ck_assert_str_eq(expected
, str
);
75 START_TEST(test_create_from_string
)
79 proposal
= proposal_create_from_string(create_data
[_i
].proto
,
80 create_data
[_i
].proposal
);
81 assert_proposal_eq(proposal
, create_data
[_i
].expected
);
91 proposal_selection_flag_t flags
;
93 { PROTO_ESP
, "aes128", "aes128", "aes128" },
94 { PROTO_ESP
, "aes128", "aes256", NULL
},
95 { PROTO_ESP
, "aes128-aes256", "aes256-aes128", "aes128" },
96 { PROTO_ESP
, "aes256-aes128", "aes128-aes256", "aes256" },
97 { PROTO_ESP
, "aes128-aes256-sha1-sha256", "aes256-aes128-sha256-sha1", "aes128-sha1" },
98 { PROTO_ESP
, "aes256-aes128-sha256-sha1", "aes128-aes256-sha1-sha256", "aes256-sha256" },
99 { PROTO_ESP
, "aes128-sha256-modp3072", "aes128-sha256", NULL
},
100 { PROTO_ESP
, "aes128-sha256-modp3072", "aes128-sha256", "aes128-sha256", PROPOSAL_SKIP_DH
},
101 { PROTO_ESP
, "aes128-sha256", "aes128-sha256-modp3072", NULL
},
102 { PROTO_ESP
, "aes128-sha256", "aes128-sha256-modp3072", "aes128-sha256", PROPOSAL_SKIP_DH
},
103 { PROTO_ESP
, "aes128-sha256-modp3072", "aes128-sha256-modp3072", "aes128-sha256", PROPOSAL_SKIP_DH
},
104 { PROTO_ESP
, "aes128-sha256-modp3072", "aes128-sha256-ecp256", "aes128-sha256", PROPOSAL_SKIP_DH
},
105 { PROTO_ESP
, "aes128-sha256-modp3072", "aes128-sha256-modpnone", NULL
},
106 { PROTO_ESP
, "aes128-sha256-modpnone", "aes128-sha256-modp3072", NULL
},
107 { PROTO_ESP
, "aes128-sha256-modp3072-modpnone", "aes128-sha256", "aes128-sha256" },
108 { PROTO_ESP
, "aes128-sha256", "aes128-sha256-modp3072-modpnone", "aes128-sha256" },
109 { PROTO_ESP
, "aes128-sha256-modp3072-modpnone", "aes128-sha256-modpnone-modp3072", "aes128-sha256-modp3072" },
110 { PROTO_ESP
, "aes128-sha256-modpnone-modp3072", "aes128-sha256-modp3072-modpnone", "aes128-sha256" },
111 { PROTO_ESP
, "aes128-sha256-esn", "aes128-sha256-esn", "aes128-sha256-esn" },
112 { PROTO_ESP
, "aes128-sha256-noesn", "aes128-sha256-esn", NULL
},
113 { PROTO_ESP
, "aes128-sha256-noesn-esn", "aes128-sha256-esn", "aes128-sha256-esn" },
114 { PROTO_ESP
, "aes128-sha256-noesn-esn", "aes128-sha256", "aes128-sha256" },
115 { PROTO_ESP
, "aes128-sha256-esn-noesn", "aes128-sha256-noesn-esn", "aes128-sha256-esn" },
116 { PROTO_IKE
, "aes128-sha256-modp3072", "aes128-sha256-modp3072", "aes128-sha256-modp3072" },
117 { PROTO_IKE
, "aes128-sha256-modp3072", "aes128-sha256-modp3072-modpnone", "aes128-sha256-modp3072" },
118 { PROTO_IKE
, "aes128-sha256-modp3072-modpnone", "aes128-sha256-modp3072", "aes128-sha256-modp3072" },
121 START_TEST(test_select
)
123 proposal_t
*self
, *other
, *selected
, *expected
;
125 self
= proposal_create_from_string(select_data
[_i
].proto
,
126 select_data
[_i
].self
);
127 other
= proposal_create_from_string(select_data
[_i
].proto
,
128 select_data
[_i
].other
);
129 selected
= self
->select(self
, other
, select_data
[_i
].flags
);
130 if (select_data
[_i
].expected
)
132 expected
= proposal_create_from_string(select_data
[_i
].proto
,
133 select_data
[_i
].expected
);
135 ck_assert_msg(expected
->equals(expected
, selected
), "proposal %P does "
136 "not match expected %P", selected
, expected
);
137 expected
->destroy(expected
);
141 ck_assert(!selected
);
143 DESTROY_IF(selected
);
144 other
->destroy(other
);
149 START_TEST(test_select_spi
)
151 proposal_t
*self
, *other
, *selected
;
153 self
= proposal_create_from_string(PROTO_ESP
, "aes128-sha256-modp3072");
154 other
= proposal_create_from_string(PROTO_ESP
, "aes128-sha256-modp3072");
155 other
->set_spi(other
, 0x12345678);
157 selected
= self
->select(self
, other
, 0);
159 ck_assert_int_eq(selected
->get_spi(selected
), other
->get_spi(other
));
160 selected
->destroy(selected
);
162 selected
= self
->select(self
, other
, PROPOSAL_PREFER_SUPPLIED
);
164 ck_assert_int_eq(selected
->get_spi(selected
), self
->get_spi(self
));
165 selected
->destroy(selected
);
167 other
->destroy(other
);
172 START_TEST(test_matches
)
174 proposal_t
*self
, *other
;
176 self
= proposal_create_from_string(select_data
[_i
].proto
,
177 select_data
[_i
].self
);
178 other
= proposal_create_from_string(select_data
[_i
].proto
,
179 select_data
[_i
].other
);
180 if (select_data
[_i
].expected
)
182 ck_assert(self
->matches(self
, other
, select_data
[_i
].flags
));
183 ck_assert(other
->matches(other
, self
, select_data
[_i
].flags
));
184 ck_assert(self
->matches(self
, other
,
185 select_data
[_i
].flags
| PROPOSAL_PREFER_SUPPLIED
));
186 ck_assert(other
->matches(other
, self
,
187 select_data
[_i
].flags
| PROPOSAL_PREFER_SUPPLIED
));
191 ck_assert(!self
->matches(self
, other
, select_data
[_i
].flags
));
192 ck_assert(!other
->matches(other
, self
, select_data
[_i
].flags
));
193 ck_assert(!self
->matches(self
, other
,
194 select_data
[_i
].flags
| PROPOSAL_PREFER_SUPPLIED
));
195 ck_assert(!other
->matches(other
, self
,
196 select_data
[_i
].flags
| PROPOSAL_PREFER_SUPPLIED
));
198 other
->destroy(other
);
208 proposal_selection_flag_t flags
;
209 } select_proposal_data
[] = {
210 { PROTO_ESP
, {}, {}, NULL
},
211 { PROTO_ESP
, { "aes128" }, {}, NULL
},
212 { PROTO_ESP
, {}, { "aes128" }, NULL
},
213 { PROTO_ESP
, { "aes128" }, { "aes256" }, NULL
},
214 { PROTO_ESP
, { "aes128" }, { "aes128" }, "aes128" },
215 { PROTO_ESP
, { "aes128", "aes256" }, { "aes256", "aes128" }, "aes128" },
216 { PROTO_ESP
, { "aes128", "aes256" }, { "aes256", "aes128" }, "aes256",
217 PROPOSAL_PREFER_SUPPLIED
},
218 { PROTO_ESP
, { "aes128-modp1024", "aes256-modp1024" },
219 { "aes256-modp2048", "aes128-modp2048" }, NULL
},
220 { PROTO_ESP
, { "aes128-modp1024", "aes256-modp1024" },
221 { "aes256-modp2048", "aes128-modp2048" }, "aes128",
223 { PROTO_ESP
, { "aes128-modp1024", "aes256-modp1024" },
224 { "aes256-modp2048", "aes128-modp2048" }, "aes256",
225 PROPOSAL_PREFER_SUPPLIED
| PROPOSAL_SKIP_DH
},
228 START_TEST(test_select_proposal
)
230 linked_list_t
*self
, *other
;
231 proposal_t
*proposal
, *selected
, *expected
;
234 self
= linked_list_create();
235 other
= linked_list_create();
237 for (i
= 0; i
< countof(select_proposal_data
[_i
].self
); i
++)
239 if (!select_proposal_data
[_i
].self
[i
])
243 proposal
= proposal_create_from_string(select_proposal_data
[_i
].proto
,
244 select_proposal_data
[_i
].self
[i
]);
245 self
->insert_last(self
, proposal
);
247 for (i
= 0; i
< countof(select_proposal_data
[_i
].other
); i
++)
249 if (!select_proposal_data
[_i
].other
[i
])
253 proposal
= proposal_create_from_string(select_proposal_data
[_i
].proto
,
254 select_proposal_data
[_i
].other
[i
]);
255 other
->insert_last(other
, proposal
);
257 selected
= proposal_select(self
, other
, select_proposal_data
[_i
].flags
);
258 if (select_proposal_data
[_i
].expected
)
260 expected
= proposal_create_from_string(select_proposal_data
[_i
].proto
,
261 select_proposal_data
[_i
].expected
);
263 ck_assert_msg(expected
->equals(expected
, selected
), "proposal %P does "
264 "not match expected %P", selected
, expected
);
265 expected
->destroy(expected
);
269 ck_assert(!selected
);
271 DESTROY_IF(selected
);
272 other
->destroy_offset(other
, offsetof(proposal_t
, destroy
));
273 self
->destroy_offset(self
, offsetof(proposal_t
, destroy
));
277 START_TEST(test_promote_dh_group
)
279 proposal_t
*proposal
;
281 proposal
= proposal_create_from_string(PROTO_IKE
,
282 "aes128-sha256-modp3072-ecp256");
283 ck_assert(proposal
->promote_dh_group(proposal
, ECP_256_BIT
));
284 assert_proposal_eq(proposal
, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256/MODP_3072");
285 proposal
->destroy(proposal
);
289 START_TEST(test_promote_dh_group_already_front
)
291 proposal_t
*proposal
;
293 proposal
= proposal_create_from_string(PROTO_IKE
,
294 "aes128-sha256-modp3072-ecp256");
295 ck_assert(proposal
->promote_dh_group(proposal
, MODP_3072_BIT
));
296 assert_proposal_eq(proposal
, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072/ECP_256");
297 proposal
->destroy(proposal
);
301 START_TEST(test_promote_dh_group_not_contained
)
303 proposal_t
*proposal
;
305 proposal
= proposal_create_from_string(PROTO_IKE
,
306 "aes128-sha256-modp3072-ecp256");
308 ck_assert(!proposal
->promote_dh_group(proposal
, MODP_2048_BIT
));
309 assert_proposal_eq(proposal
, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/MODP_3072/ECP_256");
310 proposal
->destroy(proposal
);
314 START_TEST(test_unknown_transform_types_print
)
316 proposal_t
*proposal
;
318 proposal
= proposal_create(PROTO_IKE
, 0);
319 proposal
->add_algorithm(proposal
, 242, 42, 128);
320 assert_proposal_eq(proposal
, "IKE:UNKNOWN_242_42_128");
321 proposal
->destroy(proposal
);
323 proposal
= proposal_create_from_string(PROTO_IKE
,
324 "aes128-sha256-ecp256");
325 proposal
->add_algorithm(proposal
, 242, 42, 128);
326 proposal
->add_algorithm(proposal
, 243, 1, 0);
327 assert_proposal_eq(proposal
, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256/UNKNOWN_242_42_128/UNKNOWN_243_1");
328 proposal
->destroy(proposal
);
332 START_TEST(test_unknown_transform_types_equals
)
334 proposal_t
*self
, *other
;
336 self
= proposal_create_from_string(PROTO_IKE
, "aes128-sha256-ecp256");
337 other
= proposal_create_from_string(PROTO_IKE
, "aes128-sha256-ecp256");
338 other
->add_algorithm(other
, 242, 42, 0);
339 ck_assert(!self
->equals(self
, other
));
340 ck_assert(!other
->equals(other
, self
));
341 self
->add_algorithm(self
, 242, 42, 0);
342 ck_assert(self
->equals(self
, other
));
343 ck_assert(other
->equals(other
, self
));
344 other
->destroy(other
);
349 START_TEST(test_unknown_transform_types_select_fail
)
351 proposal_t
*self
, *other
, *selected
;
353 self
= proposal_create_from_string(PROTO_IKE
, "aes128-sha256-ecp256");
354 other
= proposal_create_from_string(PROTO_IKE
, "aes128-sha256-ecp256");
355 other
->add_algorithm(other
, 242, 42, 0);
357 selected
= self
->select(self
, other
, 0);
358 ck_assert(!selected
);
359 other
->destroy(other
);
364 START_TEST(test_unknown_transform_types_select_fail_subtype
)
366 proposal_t
*self
, *other
, *selected
;
368 self
= proposal_create_from_string(PROTO_IKE
, "aes128-sha256-ecp256");
369 self
->add_algorithm(self
, 242, 8, 0);
370 other
= proposal_create_from_string(PROTO_IKE
, "aes128-sha256-ecp256");
371 other
->add_algorithm(other
, 242, 42, 0);
373 selected
= self
->select(self
, other
, 0);
374 ck_assert(!selected
);
375 other
->destroy(other
);
380 START_TEST(test_unknown_transform_types_select_success
)
382 proposal_t
*self
, *other
, *selected
;
384 self
= proposal_create_from_string(PROTO_IKE
, "aes128-sha256-ecp256");
385 self
->add_algorithm(self
, 242, 42, 128);
386 other
= proposal_create_from_string(PROTO_IKE
, "aes128-sha256-ecp256");
387 other
->add_algorithm(other
, 242, 42, 128);
388 other
->add_algorithm(other
, 242, 1, 0);
390 selected
= self
->select(self
, other
, 0);
392 assert_proposal_eq(selected
, "IKE:AES_CBC_128/HMAC_SHA2_256_128/PRF_HMAC_SHA2_256/ECP_256/UNKNOWN_242_42_128");
393 selected
->destroy(selected
);
394 other
->destroy(other
);
399 START_TEST(test_chacha20_poly1305_key_length
)
401 proposal_t
*proposal
;
404 proposal
= proposal_create_from_string(PROTO_IKE
, "chacha20poly1305-prfsha256-ecp256");
405 proposal
->get_algorithm(proposal
, ENCRYPTION_ALGORITHM
, &alg
, &ks
);
406 ck_assert_int_eq(alg
, ENCR_CHACHA20_POLY1305
);
407 ck_assert_int_eq(ks
, 0);
408 assert_proposal_eq(proposal
, "IKE:CHACHA20_POLY1305/PRF_HMAC_SHA2_256/ECP_256");
409 proposal
->destroy(proposal
);
417 proposal_selection_flag_t flags
;
419 { PROTO_ESP
, "aes128", "aes128" },
420 { PROTO_ESP
, "aes128-serpent", "aes128-serpent" },
421 { PROTO_ESP
, "aes128-serpent", "aes128", PROPOSAL_SKIP_PRIVATE
},
422 { PROTO_ESP
, "aes128-sha256-modp3072", "aes128-sha256-modp3072" },
423 { PROTO_ESP
, "aes128-sha256-modp3072", "aes128-sha256", PROPOSAL_SKIP_DH
},
424 { PROTO_ESP
, "aes128-serpent-modp3072", "aes128-serpent",
426 { PROTO_ESP
, "aes128-serpent-modp3072", "aes128",
427 PROPOSAL_SKIP_PRIVATE
| PROPOSAL_SKIP_DH
},
430 START_TEST(test_clone
)
432 proposal_t
*orig
, *result
, *expected
;
434 orig
= proposal_create_from_string(clone_data
[_i
].proto
,
435 clone_data
[_i
].orig
);
436 orig
->set_spi(orig
, 0x12345678);
438 result
= orig
->clone(orig
, clone_data
[_i
].flags
);
440 expected
= proposal_create_from_string(clone_data
[_i
].proto
,
441 clone_data
[_i
].expected
);
442 ck_assert_msg(expected
->equals(expected
, result
), "proposal %P does "
443 "not match expected %P", result
, expected
);
444 ck_assert_int_eq(orig
->get_spi(orig
), result
->get_spi(result
));
446 expected
->destroy(expected
);
447 result
->destroy(result
);
452 Suite
*proposal_suite_create()
457 s
= suite_create("proposal");
459 tc
= tcase_create("create_from_string");
460 tcase_add_loop_test(tc
, test_create_from_string
, 0, countof(create_data
));
461 suite_add_tcase(s
, tc
);
463 tc
= tcase_create("select");
464 tcase_add_loop_test(tc
, test_select
, 0, countof(select_data
));
465 tcase_add_test(tc
, test_select_spi
);
466 suite_add_tcase(s
, tc
);
468 tc
= tcase_create("matches");
469 tcase_add_loop_test(tc
, test_matches
, 0, countof(select_data
));
470 suite_add_tcase(s
, tc
);
472 tc
= tcase_create("select_proposal");
473 tcase_add_loop_test(tc
, test_select_proposal
, 0,
474 countof(select_proposal_data
));
475 suite_add_tcase(s
, tc
);
477 tc
= tcase_create("promote_dh_group");
478 tcase_add_test(tc
, test_promote_dh_group
);
479 tcase_add_test(tc
, test_promote_dh_group_already_front
);
480 tcase_add_test(tc
, test_promote_dh_group_not_contained
);
481 suite_add_tcase(s
, tc
);
483 tc
= tcase_create("unknown transform types");
484 tcase_add_test(tc
, test_unknown_transform_types_print
);
485 tcase_add_test(tc
, test_unknown_transform_types_equals
);
486 tcase_add_test(tc
, test_unknown_transform_types_select_fail
);
487 tcase_add_test(tc
, test_unknown_transform_types_select_fail_subtype
);
488 tcase_add_test(tc
, test_unknown_transform_types_select_success
);
489 suite_add_tcase(s
, tc
);
491 tc
= tcase_create("chacha20/poly1305");
492 tcase_add_test(tc
, test_chacha20_poly1305_key_length
);
493 suite_add_tcase(s
, tc
);
495 tc
= tcase_create("clone");
496 tcase_add_loop_test(tc
, test_clone
, 0, countof(clone_data
));
497 suite_add_tcase(s
, tc
);