blob: cdbd0b7397bb2fbb460494c059157f3adc191816 [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 Hofmeyr2f758032019-11-20 00:37:07 +010032#include <osmocom/hlr/logging.h>
33#include <osmocom/hlr/auc.h>
Neels Hofmeyr8cde6622017-01-31 02:10:40 +010034
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,
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100197 .u.umts.sqn = 31,
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100198 };
199
200 osmo_hexparse("EB215756028D60E3275E613320AEC880",
201 aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
202 osmo_hexparse("FB2A3D1B360F599ABAB99DB8669F8308",
203 aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +0100204 next_rand("39fa2f4e3d523d8619a73b4f65c3e14d", true);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100205
206 vec = (struct osmo_auth_vector){ {0} };
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100207 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 31, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100208 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
209 VERBOSE_ASSERT(rc, == 1, "%d");
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100210 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 32, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100211
212 VEC_IS(&vec,
213 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
Neels Hofmeyrd846ae82017-03-15 00:37:29 +0100214 " autn: 8704f5ba55d30000541dde77ea5b1d8c\n"
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100215 " ck: f64735036e5871319c679f4742a75ea1\n"
216 " ik: 27497388b6cb044648f396aa155b95ef\n"
217 " res: e229c19e791f2e410000000000000000\n"
218 " res_len: 08\n"
219 " kc: 241a5b16aeb8e400\n"
220 " sres: 429d5b27\n"
221 " auth_types: 03000000\n"
222 );
223
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100224 /* even though vec is not zero-initialized, it should produce the same
225 * result with the same sequence nr */
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100226 aud3g.u.umts.sqn = 31;
227 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 31, "%"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 Hofmeyrea1052d2017-03-15 02:42:19 +0100230 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 32, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100231
232 VEC_IS(&vec,
233 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
Neels Hofmeyrd846ae82017-03-15 00:37:29 +0100234 " autn: 8704f5ba55d30000541dde77ea5b1d8c\n"
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100235 " 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,
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100304 .u.umts.sqn = 31,
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100305 };
306
307 osmo_hexparse("EB215756028D60E3275E613320AEC880",
308 aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
309 osmo_hexparse("FB2A3D1B360F599ABAB99DB8669F8308",
310 aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +0100311 next_rand("39fa2f4e3d523d8619a73b4f65c3e14d", true);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100312
313 vec = (struct osmo_auth_vector){ {0} };
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100314 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 31, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100315 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
316 VERBOSE_ASSERT(rc, == 1, "%d");
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100317 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 32, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100318
319 VEC_IS(&vec,
320 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
Neels Hofmeyrd846ae82017-03-15 00:37:29 +0100321 " autn: 8704f5ba55d30000541dde77ea5b1d8c\n"
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100322 " ck: f64735036e5871319c679f4742a75ea1\n"
323 " ik: 27497388b6cb044648f396aa155b95ef\n"
324 " res: e229c19e791f2e410000000000000000\n"
325 " res_len: 08\n"
326 " kc: 059a4f668f6fbe39\n"
327 " sres: 9b36efdf\n"
328 " auth_types: 03000000\n"
329 );
330
331 /* Note: 3GPP TS 33.102 6.8.1.2: c3 function to get GSM auth is
332 * KC[0..7] == CK[0..7] ^ CK[8..15] ^ IK[0..7] ^ IK[8..15]
333 * In [16]: hex( 0xf64735036e587131
334 * ^ 0x9c679f4742a75ea1
335 * ^ 0x27497388b6cb0446
336 * ^ 0x48f396aa155b95ef)
337 * Out[16]: '0x59a4f668f6fbe39L'
338 * hence expecting kc: 059a4f668f6fbe39
339 */
340
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100341 /* even though vec is not zero-initialized, it should produce the same
342 * result with the same sequence nr */
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100343 aud3g.u.umts.sqn = 31;
344 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 31, "%"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 Hofmeyrea1052d2017-03-15 02:42:19 +0100347 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 32, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100348
349 VEC_IS(&vec,
350 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
Neels Hofmeyrd846ae82017-03-15 00:37:29 +0100351 " autn: 8704f5ba55d30000541dde77ea5b1d8c\n"
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100352 " 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){};
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100364 aud3g.u.umts.sqn = 31;
365 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 31, "%"PRIu64);
Neels Hofmeyrec9036b2017-02-21 21:56:11 +0100366
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");
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100412 /* The USIM's last sqn was 23, the calculated vector was 24 */
413 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 24, "%"PRIu64);
Neels Hofmeyrec9036b2017-02-21 21:56:11 +0100414
415 VEC_IS(&vec,
416 " rand: 897210a0f7de278f0b8213098e098a3f\n"
417 " autn: c6b9790dad4b00000cf322869ea6a481\n"
418 " ck: e9922bd036718ed9e40bd1d02c3b81a5\n"
419 " ik: f19c20ca863137f8892326d959ec5e01\n"
420 " res: 9af5a557902d2db80000000000000000\n"
421 " res_len: 08\n"
422 " kc: 7526fc13c5976685\n"
423 " sres: 0ad888ef\n"
424 " auth_types: 03000000\n"
425 );
426
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100427
428 fprintf(stderr, "- verify N vectors with AUTS resync"
429 " == N vectors without AUTS\n"
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100430 "First just set rand and sqn = 23, and compute 3 vectors\n");
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100431 next_rand("897210a0f7de278f0b8213098e098a3f", false);
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100432 aud3g.u.umts.sqn = 23;
433 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 23, "%"PRIu64);
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100434
435 memset(vecs, 0, sizeof(vecs));
436 rc = auc_compute_vectors(vecs, 3, &aud2g, &aud3g, NULL, NULL);
437 VERBOSE_ASSERT(rc, == 3, "%d");
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100438 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 26, "%"PRIu64);
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100439
440 _test_gen_vectors_3g_only__expect_vecs(vecs);
441
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100442 fprintf(stderr, "Now reach sqn = 23 with AUTS and expect the same\n");
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100443 /* AUTS response by USIM */
444 osmo_hexparse("979498b1f72d3e28c59fa2e72f9c",
445 auts, sizeof(auts));
446 /* RAND sent to USIM, which AUTS was generated from */
447 osmo_hexparse("39fa2f4e3d523d8619a73b4f65c3e14d",
448 rand_auts, sizeof(rand_auts));
449 next_rand("897210a0f7de278f0b8213098e098a3f", false);
450 rc = auc_compute_vectors(vecs, 3, &aud2g, &aud3g, rand_auts, auts);
451
Neels Hofmeyrb5b11e32017-02-22 01:42:43 +0100452 _test_gen_vectors_3g_only__expect_vecs(vecs);
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100453
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100454 comment_end();
455}
456
Neels Hofmeyr569d3222017-02-21 22:57:11 +0100457void test_gen_vectors_bad_args()
458{
459 struct osmo_auth_vector vec;
460 uint8_t auts[14];
461 uint8_t rand_auts[16];
462 int rc;
463 int i;
464
465 struct osmo_sub_auth_data aud2g = {
466 .type = OSMO_AUTH_TYPE_GSM,
467 .algo = OSMO_AUTH_ALG_COMP128v1,
468 };
469
470 struct osmo_sub_auth_data aud3g = {
471 .type = OSMO_AUTH_TYPE_UMTS,
472 .algo = OSMO_AUTH_ALG_MILENAGE,
473 };
474
475 struct osmo_sub_auth_data aud2g_noalg = {
476 .type = OSMO_AUTH_TYPE_GSM,
477 .algo = OSMO_AUTH_ALG_NONE,
478 };
479
480 struct osmo_sub_auth_data aud3g_noalg = {
481 .type = OSMO_AUTH_TYPE_UMTS,
482 .algo = OSMO_AUTH_ALG_NONE,
483 };
484
485 struct osmo_sub_auth_data aud_notype = {
486 .type = OSMO_AUTH_TYPE_NONE,
487 .algo = OSMO_AUTH_ALG_MILENAGE,
488 };
489
490 struct osmo_sub_auth_data no_aud = {
491 .type = OSMO_AUTH_TYPE_NONE,
492 .algo = OSMO_AUTH_ALG_NONE,
493 };
494
495 struct {
496 struct osmo_sub_auth_data *aud2g;
497 struct osmo_sub_auth_data *aud3g;
498 uint8_t *rand_auts;
499 uint8_t *auts;
500 const char *label;
501 } tests[] = {
502 { NULL, NULL, NULL, NULL, "no auth data (a)"},
503 { NULL, &aud3g_noalg, NULL, NULL, "no auth data (b)"},
504 { NULL, &aud_notype, NULL, NULL, "no auth data (c)"},
505 { NULL, &no_aud, NULL, NULL, "no auth data (d)"},
506 { &aud2g_noalg, NULL, NULL, NULL, "no auth data (e)"},
507 { &aud2g_noalg, &aud3g_noalg, NULL, NULL, "no auth data (f)"},
508 { &aud2g_noalg, &aud_notype, NULL, NULL, "no auth data (g)"},
509 { &aud2g_noalg, &no_aud, NULL, NULL, "no auth data (h)"},
510 { &aud_notype, NULL, NULL, NULL, "no auth data (i)"},
511 { &aud_notype, &aud3g_noalg, NULL, NULL, "no auth data (j)"},
512 { &aud_notype, &aud_notype, NULL, NULL, "no auth data (k)"},
513 { &aud_notype, &no_aud, NULL, NULL, "no auth data (l)"},
514 { &no_aud, NULL, NULL, NULL, "no auth data (m)"},
515 { &no_aud, &aud3g_noalg, NULL, NULL, "no auth data (n)"},
516 { &no_aud, &aud_notype, NULL, NULL, "no auth data (o)"},
517 { &no_aud, &no_aud, NULL, NULL, "no auth data (p)"},
518 { &aud3g, NULL, NULL, NULL, "wrong auth data type (a)"},
519 { &aud3g, &aud3g_noalg, NULL, NULL, "wrong auth data type (b)"},
520 { &aud3g, &aud_notype, NULL, NULL, "wrong auth data type (c)"},
521 { &aud3g, &no_aud, NULL, NULL, "wrong auth data type (d)"},
522 { NULL, &aud2g, NULL, NULL, "wrong auth data type (e)"},
523 { &aud3g_noalg, &aud2g, NULL, NULL, "wrong auth data type (f)"},
524 { &aud_notype, &aud2g, NULL, NULL, "wrong auth data type (g)"},
525 { &no_aud, &aud2g, NULL, NULL, "wrong auth data type (h)"},
526 { &aud3g, &aud2g, NULL, NULL, "wrong auth data type (i)"},
527 { &aud3g, &aud3g, NULL, NULL, "wrong auth data type (j)"},
528 { &aud2g, &aud2g, NULL, NULL, "wrong auth data type (k)"},
529 { &aud2g, NULL, rand_auts, auts, "AUTS for 2G-only (a)"},
530 { &aud2g, &aud3g_noalg, rand_auts, auts, "AUTS for 2G-only (b)"},
531 { &aud2g, &aud_notype, rand_auts, auts, "AUTS for 2G-only (c)"},
532 { &aud2g, &no_aud, rand_auts, auts, "AUTS for 2G-only (d)"},
533 { NULL, &aud3g, NULL, auts, "incomplete AUTS (a)"},
534 { NULL, &aud3g, rand_auts, NULL, "incomplete AUTS (b)"},
535 { &aud2g, &aud3g, NULL, auts, "incomplete AUTS (c)"},
536 { &aud2g, &aud3g, rand_auts, NULL, "incomplete AUTS (d)"},
537 };
538
539 comment_start();
540
541 for (i = 0; i < ARRAY_SIZE(tests); i++) {
542 fprintf(stderr, "\n- %s\n", tests[i].label);
543 rc = auc_compute_vectors(&vec, 1,
544 tests[i].aud2g,
545 tests[i].aud3g,
546 tests[i].rand_auts,
547 tests[i].auts);
548 VERBOSE_ASSERT(rc, < 0, "%d");
549 }
550
551 comment_end();
552}
553
Neels Hofmeyr21380ae2017-02-21 21:53:38 +0100554static struct {
555 bool verbose;
556} cmdline_opts = {
557 .verbose = false,
558};
559
560static void print_help(const char *program)
561{
562 printf("Usage:\n"
563 " %s [-v] [N [N...]]\n"
564 "Options:\n"
565 " -h --help show this text.\n"
566 " -v --verbose print source file and line numbers\n",
567 program
568 );
569}
570
571static void handle_options(int argc, char **argv)
572{
573 while (1) {
574 int option_index = 0, c;
575 static struct option long_options[] = {
576 {"help", 0, 0, 'h'},
577 {"verbose", 1, 0, 'v'},
578 {0, 0, 0, 0}
579 };
580
581 c = getopt_long(argc, argv, "hv",
582 long_options, &option_index);
583 if (c == -1)
584 break;
585
586 switch (c) {
587 case 'h':
588 print_help(argv[0]);
589 exit(0);
590 case 'v':
591 cmdline_opts.verbose = true;
592 break;
593 default:
594 /* catch unknown options *as well as* missing arguments. */
595 fprintf(stderr, "Error in command line options. Exiting.\n");
596 exit(-1);
597 break;
598 }
599 }
600
601 if (optind < argc) {
602 fprintf(stderr, "too many args\n");
603 exit(-1);
604 }
605}
606
607int main(int argc, char **argv)
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100608{
609 printf("auc_3g_test.c\n");
Neels Hofmeyr21380ae2017-02-21 21:53:38 +0100610
611 handle_options(argc, argv);
612
Pau Espin Pedrol51530312018-04-17 15:07:06 +0200613 void *tall_ctx = talloc_named_const(NULL, 1, "auc_test");
614
615 osmo_init_logging2(tall_ctx, &hlr_log_info);
Neels Hofmeyr21380ae2017-02-21 21:53:38 +0100616 log_set_print_filename(osmo_stderr_target, cmdline_opts.verbose);
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100617 log_set_print_timestamp(osmo_stderr_target, 0);
618 log_set_use_color(osmo_stderr_target, 0);
619 log_set_print_category(osmo_stderr_target, 1);
Neels Hofmeyr6eb231e2017-10-27 03:35:45 +0200620 log_parse_category_mask(osmo_stderr_target, "DMAIN,1:DDB,1:DAUC,1");
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100621
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100622 test_gen_vectors_2g_only();
623 test_gen_vectors_2g_plus_3g();
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100624 test_gen_vectors_3g_only();
Neels Hofmeyr569d3222017-02-21 22:57:11 +0100625 test_gen_vectors_bad_args();
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100626
627 printf("Done\n");
628 return 0;
629}