blob: 16c87f7b5b3cb01b397524162f1dfdc74fe32cee [file] [log] [blame]
Neels Hofmeyr00c06972017-01-31 01:19:27 +01001/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
2 * All Rights Reserved
3 *
4 * Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#include <stdio.h>
22#include <string.h>
Neels Hofmeyr6b883f72017-01-31 16:40:28 +010023#include <inttypes.h>
Neels Hofmeyr21380ae2017-02-21 21:53:38 +010024#include <getopt.h>
Neels Hofmeyr00c06972017-01-31 01:19:27 +010025
26#include <osmocom/core/application.h>
27#include <osmocom/core/utils.h>
28#include <osmocom/core/logging.h>
29
Neels Hofmeyr8cde6622017-01-31 02:10:40 +010030#include <osmocom/crypt/auth.h>
Neels Hofmeyr00c06972017-01-31 01:19:27 +010031
Neels Hofmeyr8cde6622017-01-31 02:10:40 +010032#include "logging.h"
33#include "auc.h"
34
35#define comment_start() fprintf(stderr, "\n===== %s\n", __func__);
Neels Hofmeyr00c06972017-01-31 01:19:27 +010036#define comment_end() fprintf(stderr, "===== %s: SUCCESS\n\n", __func__);
37
Neels Hofmeyr8cde6622017-01-31 02:10:40 +010038#define VERBOSE_ASSERT(val, expect_op, fmt) \
39 do { \
40 fprintf(stderr, #val " == " fmt "\n", (val)); \
41 OSMO_ASSERT((val) expect_op); \
42 } while (0);
43
Neels Hofmeyr6b883f72017-01-31 16:40:28 +010044char *vec_str(const struct osmo_auth_vector *vec)
Neels Hofmeyr8cde6622017-01-31 02:10:40 +010045{
46 static char buf[1024];
47 char *pos = buf;
48 char *end = buf + sizeof(buf);
49
50#define append(what) \
51 if (pos >= end) \
52 return buf; \
53 pos += snprintf(pos, sizeof(buf) - (pos - buf), \
54 " " #what ": %s\n", \
55 osmo_hexdump_nospc((void*)&vec->what, sizeof(vec->what)))
56
57 append(rand);
58 append(autn);
59 append(ck);
60 append(ik);
61 append(res);
62 append(res_len);
63 append(kc);
64 append(sres);
65 append(auth_types);
66#undef append
67
68 return buf;
69}
70
71#define VEC_IS(vec, expect) do { \
Neels Hofmeyr6b883f72017-01-31 16:40:28 +010072 char *_is = vec_str(vec); \
Neels Hofmeyr8cde6622017-01-31 02:10:40 +010073 if (strcmp(_is, expect)) { \
74 fprintf(stderr, "MISMATCH! expected ==\n%s\n", \
75 expect); \
76 char *a = _is; \
77 char *b = expect; \
78 for (; *a && *b; a++, b++) { \
79 if (*a != *b) { \
Neels Hofmeyr21380ae2017-02-21 21:53:38 +010080 fprintf(stderr, "mismatch at %d:\n", \
81 (int)(a - _is)); \
82 while (a > _is && *(a-1) != '\n') { \
83 fprintf(stderr, " "); \
84 a--; \
85 } \
86 fprintf(stderr, "v\n%s", a); \
Neels Hofmeyr8cde6622017-01-31 02:10:40 +010087 break; \
88 } \
89 } \
90 OSMO_ASSERT(false); \
Neels Hofmeyr8d97d342017-02-21 22:46:35 +010091 } else \
92 fprintf(stderr, "vector matches expectations\n"); \
Neels Hofmeyr8cde6622017-01-31 02:10:40 +010093 } while (0)
94
Neels Hofmeyr00c06972017-01-31 01:19:27 +010095uint8_t fake_rand[16] = { 0 };
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +010096bool fake_rand_fixed = true;
97
98void next_rand(const char *hexstr, bool fixed)
99{
100 osmo_hexparse(hexstr, fake_rand, sizeof(fake_rand));
101 fake_rand_fixed = fixed;
102}
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100103
104int rand_get(uint8_t *rand, unsigned int len)
105{
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +0100106 int i;
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100107 OSMO_ASSERT(len <= sizeof(fake_rand));
108 memcpy(rand, fake_rand, len);
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +0100109 if (!fake_rand_fixed) {
110 for (i = 0; i < len; i++)
111 fake_rand[i] += 0x11;
112 }
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100113 return len;
114}
115
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100116static void test_gen_vectors_2g_only(void)
117{
118 struct osmo_sub_auth_data aud2g;
119 struct osmo_sub_auth_data aud3g;
120 struct osmo_auth_vector vec;
121 int rc;
122
123 comment_start();
124
125 aud2g = (struct osmo_sub_auth_data){
126 .type = OSMO_AUTH_TYPE_GSM,
127 .algo = OSMO_AUTH_ALG_COMP128v1,
128 };
129
130 osmo_hexparse("EB215756028D60E3275E613320AEC880",
131 aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki));
132
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100133 aud3g = (struct osmo_sub_auth_data){ 0 };
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100134
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +0100135 next_rand("39fa2f4e3d523d8619a73b4f65c3e14d", true);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100136
137 vec = (struct osmo_auth_vector){ {0} };
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100138 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100139 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
140 VERBOSE_ASSERT(rc, == 1, "%d");
141
142 VEC_IS(&vec,
143 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
144 " autn: 00000000000000000000000000000000\n"
145 " ck: 00000000000000000000000000000000\n"
146 " ik: 00000000000000000000000000000000\n"
147 " res: 00000000000000000000000000000000\n"
148 " res_len: 00\n"
149 " kc: 241a5b16aeb8e400\n"
150 " sres: 429d5b27\n"
151 " auth_types: 01000000\n"
152 );
153
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100154 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100155
156 /* even though vec is not zero-initialized, it should produce the same
157 * result (regardless of the umts sequence nr) */
158 aud3g.u.umts.sqn = 123;
159 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
160 VERBOSE_ASSERT(rc, == 1, "%d");
161
162 VEC_IS(&vec,
163 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
164 " autn: 00000000000000000000000000000000\n"
165 " ck: 00000000000000000000000000000000\n"
166 " ik: 00000000000000000000000000000000\n"
167 " res: 00000000000000000000000000000000\n"
168 " res_len: 00\n"
169 " kc: 241a5b16aeb8e400\n"
170 " sres: 429d5b27\n"
171 " auth_types: 01000000\n"
172 );
173
174 comment_end();
175}
176
177static void test_gen_vectors_2g_plus_3g(void)
178{
179 struct osmo_sub_auth_data aud2g;
180 struct osmo_sub_auth_data aud3g;
181 struct osmo_auth_vector vec;
182 int rc;
183
184 comment_start();
185
186 aud2g = (struct osmo_sub_auth_data){
187 .type = OSMO_AUTH_TYPE_GSM,
188 .algo = OSMO_AUTH_ALG_COMP128v1,
189 };
190
191 osmo_hexparse("EB215756028D60E3275E613320AEC880",
192 aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki));
193
194 aud3g = (struct osmo_sub_auth_data){
195 .type = OSMO_AUTH_TYPE_UMTS,
196 .algo = OSMO_AUTH_ALG_MILENAGE,
197 };
198
199 osmo_hexparse("EB215756028D60E3275E613320AEC880",
200 aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
201 osmo_hexparse("FB2A3D1B360F599ABAB99DB8669F8308",
202 aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +0100203 next_rand("39fa2f4e3d523d8619a73b4f65c3e14d", true);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100204
205 vec = (struct osmo_auth_vector){ {0} };
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100206 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100207 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
208 VERBOSE_ASSERT(rc, == 1, "%d");
209
210 VEC_IS(&vec,
211 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
212 " autn: 8704f5ba55f30000d2ee44b22c8ea919\n"
213 " ck: f64735036e5871319c679f4742a75ea1\n"
214 " ik: 27497388b6cb044648f396aa155b95ef\n"
215 " res: e229c19e791f2e410000000000000000\n"
216 " res_len: 08\n"
217 " kc: 241a5b16aeb8e400\n"
218 " sres: 429d5b27\n"
219 " auth_types: 03000000\n"
220 );
221
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100222 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 1, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100223
224 /* even though vec is not zero-initialized, it should produce the same
225 * result with the same sequence nr */
226 aud3g.u.umts.sqn = 0;
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100227 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100228 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
229 VERBOSE_ASSERT(rc, == 1, "%d");
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100230 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 1, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100231
232 VEC_IS(&vec,
233 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
234 " autn: 8704f5ba55f30000d2ee44b22c8ea919\n"
235 " ck: f64735036e5871319c679f4742a75ea1\n"
236 " ik: 27497388b6cb044648f396aa155b95ef\n"
237 " res: e229c19e791f2e410000000000000000\n"
238 " res_len: 08\n"
239 " kc: 241a5b16aeb8e400\n"
240 " sres: 429d5b27\n"
241 " auth_types: 03000000\n"
242 );
243
244 comment_end();
245}
246
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100247void _test_gen_vectors_3g_only__expect_vecs(struct osmo_auth_vector vecs[3])
248{
249 fprintf(stderr, "[0]: ");
250 VEC_IS(&vecs[0],
251 " rand: 897210a0f7de278f0b8213098e098a3f\n"
252 " autn: c6b9790dad4b00000cf322869ea6a481\n"
253 " ck: e9922bd036718ed9e40bd1d02c3b81a5\n"
254 " ik: f19c20ca863137f8892326d959ec5e01\n"
255 " res: 9af5a557902d2db80000000000000000\n"
256 " res_len: 08\n"
257 " kc: 7526fc13c5976685\n"
258 " sres: 0ad888ef\n"
259 " auth_types: 03000000\n"
260 );
261 fprintf(stderr, "[1]: ");
262 VEC_IS(&vecs[1],
263 " rand: 9a8321b108ef38a01c93241a9f1a9b50\n"
264 " autn: 79a5113eb0910000be6020540503ffc5\n"
265 " ck: 3686f05df057d1899c66ae4eb18cf941\n"
266 " ik: 79f21ed53bcb47787de57d136ff803a5\n"
267 " res: 43023475cb29292c0000000000000000\n"
268 " res_len: 08\n"
269 " kc: aef73dd515e86c15\n"
270 " sres: 882b1d59\n"
271 " auth_types: 03000000\n"
272 );
273 fprintf(stderr, "[2]: ");
274 VEC_IS(&vecs[2],
275 " rand: ab9432c2190049b12da4352bb02bac61\n"
276 " autn: 24b018d46c3b00009c7e1b47f3a19b2b\n"
277 " ck: d86c3191a36fc0602e48202ef2080964\n"
278 " ik: 648dab72016181406243420649e63dc9\n"
279 " res: 010cab11cc63a6e40000000000000000\n"
280 " res_len: 08\n"
281 " kc: f0eaf8cb19e0758d\n"
282 " sres: cd6f0df5\n"
283 " auth_types: 03000000\n"
284 );
285}
286
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100287static void test_gen_vectors_3g_only(void)
288{
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100289 struct osmo_sub_auth_data aud2g;
290 struct osmo_sub_auth_data aud3g;
291 struct osmo_auth_vector vec;
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100292 struct osmo_auth_vector vecs[3];
Neels Hofmeyrec9036b2017-02-21 21:56:11 +0100293 uint8_t auts[14];
294 uint8_t rand_auts[16];
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100295 int rc;
296
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100297 comment_start();
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100298
299 aud2g = (struct osmo_sub_auth_data){ 0 };
300
301 aud3g = (struct osmo_sub_auth_data){
302 .type = OSMO_AUTH_TYPE_UMTS,
303 .algo = OSMO_AUTH_ALG_MILENAGE,
304 };
305
306 osmo_hexparse("EB215756028D60E3275E613320AEC880",
307 aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
308 osmo_hexparse("FB2A3D1B360F599ABAB99DB8669F8308",
309 aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +0100310 next_rand("39fa2f4e3d523d8619a73b4f65c3e14d", true);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100311
312 vec = (struct osmo_auth_vector){ {0} };
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100313 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100314 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
315 VERBOSE_ASSERT(rc, == 1, "%d");
316
317 VEC_IS(&vec,
318 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
319 " autn: 8704f5ba55f30000d2ee44b22c8ea919\n"
320 " ck: f64735036e5871319c679f4742a75ea1\n"
321 " ik: 27497388b6cb044648f396aa155b95ef\n"
322 " res: e229c19e791f2e410000000000000000\n"
323 " res_len: 08\n"
324 " kc: 059a4f668f6fbe39\n"
325 " sres: 9b36efdf\n"
326 " auth_types: 03000000\n"
327 );
328
329 /* Note: 3GPP TS 33.102 6.8.1.2: c3 function to get GSM auth is
330 * KC[0..7] == CK[0..7] ^ CK[8..15] ^ IK[0..7] ^ IK[8..15]
331 * In [16]: hex( 0xf64735036e587131
332 * ^ 0x9c679f4742a75ea1
333 * ^ 0x27497388b6cb0446
334 * ^ 0x48f396aa155b95ef)
335 * Out[16]: '0x59a4f668f6fbe39L'
336 * hence expecting kc: 059a4f668f6fbe39
337 */
338
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100339 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 1, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100340
341 /* even though vec is not zero-initialized, it should produce the same
342 * result with the same sequence nr */
343 aud3g.u.umts.sqn = 0;
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100344 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100345 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
346 VERBOSE_ASSERT(rc, == 1, "%d");
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100347 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 1, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100348
349 VEC_IS(&vec,
350 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
351 " autn: 8704f5ba55f30000d2ee44b22c8ea919\n"
352 " ck: f64735036e5871319c679f4742a75ea1\n"
353 " ik: 27497388b6cb044648f396aa155b95ef\n"
354 " res: e229c19e791f2e410000000000000000\n"
355 " res_len: 08\n"
356 " kc: 059a4f668f6fbe39\n"
357 " sres: 9b36efdf\n"
358 " auth_types: 03000000\n"
359 );
360
Neels Hofmeyrec9036b2017-02-21 21:56:11 +0100361
362 fprintf(stderr, "- test AUTS resync\n");
363 vec = (struct osmo_auth_vector){};
364 aud3g.u.umts.sqn = 0;
365 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
366
367 /* The AUTN sent was 8704f5ba55f30000d2ee44b22c8ea919
368 * with the first 6 bytes being SQN ^ AK.
369 * K = EB215756028D60E3275E613320AEC880
370 * OPC = FB2A3D1B360F599ABAB99DB8669F8308
371 * RAND = 39fa2f4e3d523d8619a73b4f65c3e14d
372 * --milenage-f5-->
373 * AK = 8704f5ba55f3
374 *
375 * The first six bytes are 8704f5ba55f3,
376 * and 8704f5ba55f3 ^ AK = 0.
377 * --> SQN = 0.
378 *
379 * Say the USIM doesn't like that, let's say it is at SQN 23.
380 * SQN_MS = 000000000017
381 *
382 * AUTS = Conc(SQN_MS) || MAC-S
383 * Conc(SQN_MS) = SQN_MS ⊕ f5*[K](RAND)
384 * MAC-S = f1*[K] (SQN MS || RAND || AMF)
385 *
386 * f5*--> Conc(SQN_MS) = 000000000017 ^ 979498b1f73a
387 * = 979498b1f72d
388 * AMF = 0000 (TS 33.102 v7.0.0, 6.3.3)
389 *
390 * MAC-S = f1*[K] (000000000017 || 39fa2f4e3d523d8619a73b4f65c3e14d || 0000)
391 * = 3e28c59fa2e72f9c
392 *
393 * AUTS = 979498b1f72d || 3e28c59fa2e72f9c
394 *
395 * verify valid AUTS resulting in SQN 23 with:
396 * osmo-auc-gen -3 -a milenage -k EB215756028D60E3275E613320AEC880 \
397 * -o FB2A3D1B360F599ABAB99DB8669F8308 \
398 * -r 39fa2f4e3d523d8619a73b4f65c3e14d \
399 * -A 979498b1f72d3e28c59fa2e72f9c
400 */
401
402 /* AUTS response by USIM */
403 osmo_hexparse("979498b1f72d3e28c59fa2e72f9c",
404 auts, sizeof(auts));
405 /* RAND sent to USIM, which AUTS was generated from */
406 osmo_hexparse("39fa2f4e3d523d8619a73b4f65c3e14d",
407 rand_auts, sizeof(rand_auts));
408 /* new RAND token for the next key */
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +0100409 next_rand("897210a0f7de278f0b8213098e098a3f", true);
Neels Hofmeyrec9036b2017-02-21 21:56:11 +0100410 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, rand_auts, auts);
411 VERBOSE_ASSERT(rc, == 1, "%d");
412 /* The USIM's last sqn was 23, the calculated vector was 24, hence the
413 * next one stored should be 25. */
414 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 25, "%"PRIu64);
415
416 VEC_IS(&vec,
417 " rand: 897210a0f7de278f0b8213098e098a3f\n"
418 " autn: c6b9790dad4b00000cf322869ea6a481\n"
419 " ck: e9922bd036718ed9e40bd1d02c3b81a5\n"
420 " ik: f19c20ca863137f8892326d959ec5e01\n"
421 " res: 9af5a557902d2db80000000000000000\n"
422 " res_len: 08\n"
423 " kc: 7526fc13c5976685\n"
424 " sres: 0ad888ef\n"
425 " auth_types: 03000000\n"
426 );
427
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100428
429 fprintf(stderr, "- verify N vectors with AUTS resync"
430 " == N vectors without AUTS\n"
431 "First just set rand and sqn = 24, and compute 3 vectors\n");
432 next_rand("897210a0f7de278f0b8213098e098a3f", false);
433 aud3g.u.umts.sqn = 24;
434 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 24, "%"PRIu64);
435
436 memset(vecs, 0, sizeof(vecs));
437 rc = auc_compute_vectors(vecs, 3, &aud2g, &aud3g, NULL, NULL);
438 VERBOSE_ASSERT(rc, == 3, "%d");
439 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 27, "%"PRIu64);
440
441 _test_gen_vectors_3g_only__expect_vecs(vecs);
442
443 fprintf(stderr, "Now reach sqn = 24 with AUTS and expect the same\n");
444 /* AUTS response by USIM */
445 osmo_hexparse("979498b1f72d3e28c59fa2e72f9c",
446 auts, sizeof(auts));
447 /* RAND sent to USIM, which AUTS was generated from */
448 osmo_hexparse("39fa2f4e3d523d8619a73b4f65c3e14d",
449 rand_auts, sizeof(rand_auts));
450 next_rand("897210a0f7de278f0b8213098e098a3f", false);
451 rc = auc_compute_vectors(vecs, 3, &aud2g, &aud3g, rand_auts, auts);
452
Neels Hofmeyrb5b11e32017-02-22 01:42:43 +0100453 _test_gen_vectors_3g_only__expect_vecs(vecs);
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100454
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100455 comment_end();
456}
457
Neels Hofmeyr569d3222017-02-21 22:57:11 +0100458void test_gen_vectors_bad_args()
459{
460 struct osmo_auth_vector vec;
461 uint8_t auts[14];
462 uint8_t rand_auts[16];
463 int rc;
464 int i;
465
466 struct osmo_sub_auth_data aud2g = {
467 .type = OSMO_AUTH_TYPE_GSM,
468 .algo = OSMO_AUTH_ALG_COMP128v1,
469 };
470
471 struct osmo_sub_auth_data aud3g = {
472 .type = OSMO_AUTH_TYPE_UMTS,
473 .algo = OSMO_AUTH_ALG_MILENAGE,
474 };
475
476 struct osmo_sub_auth_data aud2g_noalg = {
477 .type = OSMO_AUTH_TYPE_GSM,
478 .algo = OSMO_AUTH_ALG_NONE,
479 };
480
481 struct osmo_sub_auth_data aud3g_noalg = {
482 .type = OSMO_AUTH_TYPE_UMTS,
483 .algo = OSMO_AUTH_ALG_NONE,
484 };
485
486 struct osmo_sub_auth_data aud_notype = {
487 .type = OSMO_AUTH_TYPE_NONE,
488 .algo = OSMO_AUTH_ALG_MILENAGE,
489 };
490
491 struct osmo_sub_auth_data no_aud = {
492 .type = OSMO_AUTH_TYPE_NONE,
493 .algo = OSMO_AUTH_ALG_NONE,
494 };
495
496 struct {
497 struct osmo_sub_auth_data *aud2g;
498 struct osmo_sub_auth_data *aud3g;
499 uint8_t *rand_auts;
500 uint8_t *auts;
501 const char *label;
502 } tests[] = {
503 { NULL, NULL, NULL, NULL, "no auth data (a)"},
504 { NULL, &aud3g_noalg, NULL, NULL, "no auth data (b)"},
505 { NULL, &aud_notype, NULL, NULL, "no auth data (c)"},
506 { NULL, &no_aud, NULL, NULL, "no auth data (d)"},
507 { &aud2g_noalg, NULL, NULL, NULL, "no auth data (e)"},
508 { &aud2g_noalg, &aud3g_noalg, NULL, NULL, "no auth data (f)"},
509 { &aud2g_noalg, &aud_notype, NULL, NULL, "no auth data (g)"},
510 { &aud2g_noalg, &no_aud, NULL, NULL, "no auth data (h)"},
511 { &aud_notype, NULL, NULL, NULL, "no auth data (i)"},
512 { &aud_notype, &aud3g_noalg, NULL, NULL, "no auth data (j)"},
513 { &aud_notype, &aud_notype, NULL, NULL, "no auth data (k)"},
514 { &aud_notype, &no_aud, NULL, NULL, "no auth data (l)"},
515 { &no_aud, NULL, NULL, NULL, "no auth data (m)"},
516 { &no_aud, &aud3g_noalg, NULL, NULL, "no auth data (n)"},
517 { &no_aud, &aud_notype, NULL, NULL, "no auth data (o)"},
518 { &no_aud, &no_aud, NULL, NULL, "no auth data (p)"},
519 { &aud3g, NULL, NULL, NULL, "wrong auth data type (a)"},
520 { &aud3g, &aud3g_noalg, NULL, NULL, "wrong auth data type (b)"},
521 { &aud3g, &aud_notype, NULL, NULL, "wrong auth data type (c)"},
522 { &aud3g, &no_aud, NULL, NULL, "wrong auth data type (d)"},
523 { NULL, &aud2g, NULL, NULL, "wrong auth data type (e)"},
524 { &aud3g_noalg, &aud2g, NULL, NULL, "wrong auth data type (f)"},
525 { &aud_notype, &aud2g, NULL, NULL, "wrong auth data type (g)"},
526 { &no_aud, &aud2g, NULL, NULL, "wrong auth data type (h)"},
527 { &aud3g, &aud2g, NULL, NULL, "wrong auth data type (i)"},
528 { &aud3g, &aud3g, NULL, NULL, "wrong auth data type (j)"},
529 { &aud2g, &aud2g, NULL, NULL, "wrong auth data type (k)"},
530 { &aud2g, NULL, rand_auts, auts, "AUTS for 2G-only (a)"},
531 { &aud2g, &aud3g_noalg, rand_auts, auts, "AUTS for 2G-only (b)"},
532 { &aud2g, &aud_notype, rand_auts, auts, "AUTS for 2G-only (c)"},
533 { &aud2g, &no_aud, rand_auts, auts, "AUTS for 2G-only (d)"},
534 { NULL, &aud3g, NULL, auts, "incomplete AUTS (a)"},
535 { NULL, &aud3g, rand_auts, NULL, "incomplete AUTS (b)"},
536 { &aud2g, &aud3g, NULL, auts, "incomplete AUTS (c)"},
537 { &aud2g, &aud3g, rand_auts, NULL, "incomplete AUTS (d)"},
538 };
539
540 comment_start();
541
542 for (i = 0; i < ARRAY_SIZE(tests); i++) {
543 fprintf(stderr, "\n- %s\n", tests[i].label);
544 rc = auc_compute_vectors(&vec, 1,
545 tests[i].aud2g,
546 tests[i].aud3g,
547 tests[i].rand_auts,
548 tests[i].auts);
549 VERBOSE_ASSERT(rc, < 0, "%d");
550 }
551
552 comment_end();
553}
554
Neels Hofmeyr21380ae2017-02-21 21:53:38 +0100555static struct {
556 bool verbose;
557} cmdline_opts = {
558 .verbose = false,
559};
560
561static void print_help(const char *program)
562{
563 printf("Usage:\n"
564 " %s [-v] [N [N...]]\n"
565 "Options:\n"
566 " -h --help show this text.\n"
567 " -v --verbose print source file and line numbers\n",
568 program
569 );
570}
571
572static void handle_options(int argc, char **argv)
573{
574 while (1) {
575 int option_index = 0, c;
576 static struct option long_options[] = {
577 {"help", 0, 0, 'h'},
578 {"verbose", 1, 0, 'v'},
579 {0, 0, 0, 0}
580 };
581
582 c = getopt_long(argc, argv, "hv",
583 long_options, &option_index);
584 if (c == -1)
585 break;
586
587 switch (c) {
588 case 'h':
589 print_help(argv[0]);
590 exit(0);
591 case 'v':
592 cmdline_opts.verbose = true;
593 break;
594 default:
595 /* catch unknown options *as well as* missing arguments. */
596 fprintf(stderr, "Error in command line options. Exiting.\n");
597 exit(-1);
598 break;
599 }
600 }
601
602 if (optind < argc) {
603 fprintf(stderr, "too many args\n");
604 exit(-1);
605 }
606}
607
608int main(int argc, char **argv)
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100609{
610 printf("auc_3g_test.c\n");
Neels Hofmeyr21380ae2017-02-21 21:53:38 +0100611
612 handle_options(argc, argv);
613
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100614 osmo_init_logging(&hlr_log_info);
Neels Hofmeyr21380ae2017-02-21 21:53:38 +0100615 log_set_print_filename(osmo_stderr_target, cmdline_opts.verbose);
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100616 log_set_print_timestamp(osmo_stderr_target, 0);
617 log_set_use_color(osmo_stderr_target, 0);
618 log_set_print_category(osmo_stderr_target, 1);
619
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100620 test_gen_vectors_2g_only();
621 test_gen_vectors_2g_plus_3g();
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100622 test_gen_vectors_3g_only();
Neels Hofmeyr569d3222017-02-21 22:57:11 +0100623 test_gen_vectors_bad_args();
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100624
625 printf("Done\n");
626 return 0;
627}