blob: a00ab2ce06329fdbab896490d5f937139b460fd9 [file] [log] [blame]
Harald Welte8bd9d5d2023-05-28 09:36:50 +02001
2#include <stdint.h>
3#include <osmocom/core/utils.h>
4#include "gsm/tuak/tuak.h"
5
6/* user-friendly test specification, uses hex-strings for all parameters for
7 * copy+pasting from the spec. */
8struct tuak_testspec {
9 const char *name;
10 struct {
11 const char *k;
12 const char *rand;
13 const char *sqn;
14 const char *amf;
15 const char *top;
16 unsigned int keccak_iterations;
17 } in;
18 struct {
19 const char *topc;
20 const char *f1;
21 const char *f1star;
22 const char *f2;
23 const char *f3;
24 const char *f4;
25 const char *f5;
26 const char *f5star;
27 } out;
28};
29
30static const struct tuak_testspec testspecs[] = {
31 {
32 .name = "TS 35.233 Section 6.3 Test Set 1",
33 .in = {
34 .k = "abababababababababababababababab",
35 .rand = "42424242424242424242424242424242",
36 .sqn = "111111111111",
37 .amf = "ffff",
38 .top = "5555555555555555555555555555555555555555555555555555555555555555",
39 .keccak_iterations = 1,
40 },
41 .out = {
42 .topc = "bd04d9530e87513c5d837ac2ad954623a8e2330c115305a73eb45d1f40cccbff",
43 .f1 = "f9a54e6aeaa8618d",
44 .f1star = "e94b4dc6c7297df3",
45 .f2 = "657acd64",
46 .f3 = "d71a1e5c6caffe986a26f783e5c78be1",
47 .f4 = "be849fa2564f869aecee6f62d4337e72",
48 .f5 = "719f1e9b9054",
49 .f5star = "e7af6b3d0e38",
50 },
51 }, {
52 .name = "TS 35.233 Section 6.4 Test Set 2",
53 .in = {
54 .k = "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0",
55 .rand = "0123456789abcdef0123456789abcdef",
56 .sqn = "0123456789ab",
57 .amf = "abcd",
58 .top = "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f",
59 .keccak_iterations = 1,
60 },
61 .out = {
62 .topc = "305425427e18c503c8a4b294ea72c95d0c36c6c6b29d0c65de5974d5977f8524",
63 .f1 = "c0b8c2d4148ec7aa5f1d78a97e4d1d58",
64 .f1star = "ef81af7290f7842c6ceafa537fa0745b",
65 .f2 = "e9d749dc4eea0035",
66 .f3 = "a4cb6f6529ab17f8337f27baa8234d47",
67 .f4 = "2274155ccf4199d5e2abcbf621907f90",
68 .f5 = "480a9345cc1e",
69 .f5star = "f84eb338848c",
70 },
71 }, {
72 .name = "TS 35.233 Section 6.5 Test Set 3",
73 .in = {
74 .k = "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0",
75 .rand = "0123456789abcdef0123456789abcdef",
76 .sqn = "0123456789ab",
77 .amf = "abcd",
78 .top = "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f",
79 .keccak_iterations = 1,
80 },
81 .out = {
82 .topc = "305425427e18c503c8a4b294ea72c95d0c36c6c6b29d0c65de5974d5977f8524",
83 .f1 = "d97b75a1776065271b1e212bc3b1bf173f438b21e6c64a55a96c372e085e5cc5",
84 .f1star = "427bbf07c6e3a86c54f8c5216499f3909a6fd4a164c9fe235b1550258111b821",
85 .f2 = "07021c73e7635c7d",
86 .f3 = "4d59ac796834eb85d11fa148a5058c3c",
87 .f4 = "126d47500136fdc5ddfd14f19ebf16749ce4b6435323fbb5715a3a796a6082bd",
88 .f5 = "1d6622c4e59a",
89 .f5star = "f84eb338848c",
90 },
91 }, {
92 .name = "TS 35.233 Section 6.6 Test Set 4",
93 .in = {
94 .k = "b8da837a50652d6ac7c97da14f6acc61",
95 .rand = "6887e55425a966bd86c9661a5fa72be8",
96 .sqn = "0dea2ee2c5af",
97 .amf = "df1e",
98 .top = "0952be13556c32ebc58195d9dd930493e12a9003669988ffde5fa1f0fe35cc01",
99 .keccak_iterations = 1,
100 },
101 .out = {
102 .topc = "2bc16eb657a68e1f446f08f57c0efb1d493527a2e652ce281eb6ca0e4487760a",
103 .f1 = "749214087958dd8f58bfcdf869d8ae3f",
104 .f1star = "619e865afe80e382aee13063f9dfb56d",
105 .f2 = "4041ce438e3e38e8aa96562eed83ac43",
106 .f3 = "3e3bc01bea0cd914c4c2c83ce2d92757",
107 .f4 = "666a8e6f577b1aa77b7fd53cebb8a3d6",
108 .f5 = "1f880d005119",
109 .f5star = "45e617d77fe5",
110 },
111 }, {
112 .name = "TS 35.233 Section 6.7 Test Set 5",
113 .in = {
114 .k = "1574ca56881d05c189c82880f789c9cd4244955f4426aa2b69c29f15770e5aa5",
115 .rand = "c570aac68cde651fb1e3088322498bef",
116 .sqn = "c89bb71f3a41",
117 .amf = "297d",
118 .top = "e59f6eb10ea406813f4991b0b9e02f181edf4c7e17b480f66d34da35ee88c95e",
119 .keccak_iterations = 1,
120 },
121 .out = {
122 .topc = "3c6052e41532a28a47aa3cbb89f223e8f3aaa976aecd48bc3e7d6165a55eff62",
123 .f1 = "d7340dad02b4cb01",
124 .f1star = "c6021e2e66accb15",
125 .f2 = "84d89b41db1867ffd4c7ba1d82163f4d526a20fbae5418fbb526940b1eeb905c",
126 .f3 = "d419676afe5ab58c1d8bee0d43523a4d2f52ef0b31a4676a0c334427a988fe65",
127 .f4 = "205533e505661b61d05cc0eac87818f4",
128 .f5 = "d7b3d2d4980a",
129 .f5star = "ca9655264986",
130 },
131 }, {
132 .name = "TS 35.233 Section 6.8 Test Set 6",
133 .in = {
134 .k = "1574ca56881d05c189c82880f789c9cd4244955f4426aa2b69c29f15770e5aa5",
135 .rand = "c570aac68cde651fb1e3088322498bef",
136 .sqn = "c89bb71f3a41",
137 .amf = "297d",
138 .top = "e59f6eb10ea406813f4991b0b9e02f181edf4c7e17b480f66d34da35ee88c95e",
139 .keccak_iterations = 2,
140 },
141 .out = {
142 .topc = "b04a66f26c62fcd6c82de22a179ab65506ecf47f56245cd149966cfa9cec7a51",
143 .f1 = "90d2289ed1ca1c3dbc2247bb480d431ac71d2e4a7677f6e997cfddb0cbad88b7",
144 .f1star = "427355dbac30e825063aba61b556e87583abac638e3ab01c4c884ad9d458dc2f",
145 .f2 = "d67e6e64590d22eecba7324afa4af4460c93f01b24506d6e12047d789a94c867",
146 .f3 = "ede57edfc57cdffe1aae75066a1b7479bbc3837438e88d37a801cccc9f972b89",
147 .f4 = "48ed9299126e5057402fe01f9201cf25249f9c5c0ed2afcf084755daff1d3999",
148 .f5 = "6aae8d18c448",
149 .f5star = "8c5f33b61f4e",
150 },
151 },
152};
153
154
155struct tuak_testset {
156 const char *name;
157 struct {
158 uint8_t k[32];
159 uint8_t k_len_bytes;
160 uint8_t rand[16];
161 uint8_t sqn[6];
162 uint8_t amf[2];
163 uint8_t top[32];
164 unsigned int keccak_iterations;
165 } in;
166 struct {
167 uint8_t topc[32];
168 uint8_t mac_a[32];
169 uint8_t mac_s[32];
170 uint8_t mac_len_bytes;
171
172 uint8_t res[32];
173 uint8_t res_len_bytes;
174
175 uint8_t ck[32];
176 uint8_t ck_len_bytes;
177 uint8_t ik[32];
178 uint8_t ik_len_bytes;
179 uint8_t ak[6];
180 uint8_t f5star[6];
181 } out;
182};
183
184static void expect_equal(const char *name, const uint8_t *actual, const uint8_t *expected, size_t len)
185{
186 if (!memcmp(actual, expected, len)) {
187 printf("\t%s: %s\r\n", name, osmo_hexdump_nospc(actual, len));
188 } else {
189 char buf[len*2+1];
190 printf("\t%s: %s != %s\r\n", name, osmo_hexdump_nospc(actual, len),
191 osmo_hexdump_buf(buf, sizeof(buf), expected, len, "", true));
192 }
193}
194
195static void execute_testset(const struct tuak_testset *tset)
196{
197 uint8_t topc[32];
198
199 printf("==> %s\n", tset->name);
200
201 tuak_set_keccak_iterations(tset->in.keccak_iterations);
202 tuak_opc_gen(topc, tset->in.k, tset->in.k_len_bytes, tset->in.top);
203 expect_equal("TOPc", topc, tset->out.topc, sizeof(topc));
204
205 if (tset->out.mac_len_bytes) {
206 uint8_t mac_a[32];
207 uint8_t mac_s[32];
208
209 tuak_f1(topc, tset->in.k, tset->in.k_len_bytes, tset->in.rand, tset->in.sqn, tset->in.amf,
210 mac_a, tset->out.mac_len_bytes, tset->in.keccak_iterations);
211 expect_equal("MAC_A", mac_a, tset->out.mac_a, tset->out.mac_len_bytes);
212
213 tuak_f1star(topc, tset->in.k, tset->in.k_len_bytes, tset->in.rand, tset->in.sqn, tset->in.amf,
214 mac_s, tset->out.mac_len_bytes, tset->in.keccak_iterations);
215 expect_equal("MAC_S", mac_s, tset->out.mac_s, tset->out.mac_len_bytes);
216 }
217
218 if (tset->out.ck_len_bytes || tset->out.ik_len_bytes || tset->out.res_len_bytes) {
219 uint8_t res[32];
220 uint8_t ck[32];
221 uint8_t ik[32];
222 uint8_t ak[6];
223
224 tuak_f2345(topc, tset->in.k, tset->in.k_len_bytes, tset->in.rand,
225 tset->out.res_len_bytes ? res : NULL, tset->out.res_len_bytes,
226 tset->out.ck_len_bytes ? ck : NULL, tset->out.ck_len_bytes,
227 tset->out.ik_len_bytes ? ik : NULL, tset->out.ik_len_bytes,
228 ak, tset->in.keccak_iterations);
229
230 if (tset->out.res_len_bytes)
231 expect_equal("RES", res, tset->out.res, tset->out.res_len_bytes);
232
233 if (tset->out.ck_len_bytes)
234 expect_equal("CK", ck, tset->out.ck, tset->out.ck_len_bytes);
235
236 if (tset->out.ik_len_bytes)
237 expect_equal("IK", ik, tset->out.ik, tset->out.ik_len_bytes);
238
239 expect_equal("AK", ak, tset->out.ak, 6);
240 }
241}
242
243/* convert string-testspec to binary-testset and execute it */
244static void execute_testspec(const struct tuak_testspec *tcase)
245{
246 struct tuak_testset _tset, *tset = &_tset;
247
248 tset->name = tcase->name;
249 tset->in.keccak_iterations = tcase->in.keccak_iterations;
250
251 osmo_hexparse(tcase->in.k, tset->in.k, sizeof(tset->in.k));
252 tset->in.k_len_bytes = strlen(tcase->in.k)/2;
253 OSMO_ASSERT(tset->in.k_len_bytes == 16 || tset->in.k_len_bytes == 32);
254
255 osmo_hexparse(tcase->in.rand, tset->in.rand, sizeof(tset->in.rand));
256 OSMO_ASSERT(strlen(tcase->in.rand)/2 == 16);
257
258 osmo_hexparse(tcase->in.sqn, tset->in.sqn, sizeof(tset->in.sqn));
259 OSMO_ASSERT(strlen(tcase->in.sqn)/2 == 6);
260
261 osmo_hexparse(tcase->in.amf, tset->in.amf, sizeof(tset->in.amf));
262 OSMO_ASSERT(strlen(tcase->in.amf)/2 == 2);
263
264 osmo_hexparse(tcase->in.top, tset->in.top, sizeof(tset->in.top));
265 OSMO_ASSERT(strlen(tcase->in.top)/2 == 32);
266
267 osmo_hexparse(tcase->out.topc, tset->out.topc, sizeof(tset->out.topc));
268 OSMO_ASSERT(strlen(tcase->out.topc)/2 == 32);
269
270 osmo_hexparse(tcase->out.f1, tset->out.mac_a, sizeof(tset->out.mac_a));
271 osmo_hexparse(tcase->out.f1star, tset->out.mac_s, sizeof(tset->out.mac_s));
272 OSMO_ASSERT(strlen(tcase->out.f1) == strlen(tcase->out.f1star));
273 tset->out.mac_len_bytes = strlen(tcase->out.f1)/2;
274 OSMO_ASSERT(tset->out.mac_len_bytes == 8 || tset->out.mac_len_bytes == 16 ||
275 tset->out.mac_len_bytes == 32);
276
277 osmo_hexparse(tcase->out.f2, tset->out.res, sizeof(tset->out.res));
278 tset->out.res_len_bytes = strlen(tcase->out.f2)/2;
279 OSMO_ASSERT(tset->out.res_len_bytes == 4 || tset->out.res_len_bytes == 8 ||
280 tset->out.res_len_bytes == 16 || tset->out.res_len_bytes == 32);
281
282 osmo_hexparse(tcase->out.f3, tset->out.ck, sizeof(tset->out.ck));
283 tset->out.ck_len_bytes = strlen(tcase->out.f3)/2;
284 OSMO_ASSERT(tset->out.ck_len_bytes == 16 || tset->out.ck_len_bytes == 32);
285
286 osmo_hexparse(tcase->out.f4, tset->out.ik, sizeof(tset->out.ik));
287 tset->out.ik_len_bytes = strlen(tcase->out.f4)/2;
288 OSMO_ASSERT(tset->out.ik_len_bytes == 16 || tset->out.ik_len_bytes == 32);
289
290 osmo_hexparse(tcase->out.f5, tset->out.ak, sizeof(tset->out.ak));
291 OSMO_ASSERT(strlen(tcase->out.f5)/2 == 6);
292
293 osmo_hexparse(tcase->out.f5star, tset->out.f5star, sizeof(tset->out.f5star));
294 OSMO_ASSERT(strlen(tcase->out.f5star)/2 == 6);
295
296 execute_testset(tset);
297}
298
299int main(int argc, char **argv)
300{
301#if 0
302 for (unsigned int i = 0; i < ARRAY_SIZE(testsets); i++)
303 execute_testset(&testsets[i]);
304#endif
305
306 for (unsigned int i = 0; i < ARRAY_SIZE(testspecs); i++)
307 execute_testspec(&testspecs[i]);
308
309}