blob: 61cf82f8d04db15ace3080bd696b53fbd8657d00 [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
Harald Weltebd94b412021-01-04 14:02:55 +0100116/* Subscriber with 2G-only (COMP128v1) authentication data */
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100117static void test_gen_vectors_2g_only(void)
118{
119 struct osmo_sub_auth_data aud2g;
120 struct osmo_sub_auth_data aud3g;
121 struct osmo_auth_vector vec;
122 int rc;
123
124 comment_start();
125
126 aud2g = (struct osmo_sub_auth_data){
127 .type = OSMO_AUTH_TYPE_GSM,
128 .algo = OSMO_AUTH_ALG_COMP128v1,
129 };
130
131 osmo_hexparse("EB215756028D60E3275E613320AEC880",
132 aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki));
133
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100134 aud3g = (struct osmo_sub_auth_data){ 0 };
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100135
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +0100136 next_rand("39fa2f4e3d523d8619a73b4f65c3e14d", true);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100137
138 vec = (struct osmo_auth_vector){ {0} };
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100139 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100140 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
141 VERBOSE_ASSERT(rc, == 1, "%d");
142
143 VEC_IS(&vec,
144 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
145 " autn: 00000000000000000000000000000000\n"
146 " ck: 00000000000000000000000000000000\n"
147 " ik: 00000000000000000000000000000000\n"
148 " res: 00000000000000000000000000000000\n"
149 " res_len: 00\n"
150 " kc: 241a5b16aeb8e400\n"
151 " sres: 429d5b27\n"
152 " auth_types: 01000000\n"
153 );
154
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100155 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100156
157 /* even though vec is not zero-initialized, it should produce the same
158 * result (regardless of the umts sequence nr) */
159 aud3g.u.umts.sqn = 123;
160 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
161 VERBOSE_ASSERT(rc, == 1, "%d");
162
163 VEC_IS(&vec,
164 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
165 " autn: 00000000000000000000000000000000\n"
166 " ck: 00000000000000000000000000000000\n"
167 " ik: 00000000000000000000000000000000\n"
168 " res: 00000000000000000000000000000000\n"
169 " res_len: 00\n"
170 " kc: 241a5b16aeb8e400\n"
171 " sres: 429d5b27\n"
172 " auth_types: 01000000\n"
173 );
174
175 comment_end();
176}
177
Harald Weltebd94b412021-01-04 14:02:55 +0100178/* Subscriber with separate 2G (COMP128v1) and 3G (MILENAGE) authentication data,
179 * reflects the default configuration of sysmoUSIM-SJS1 */
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100180static void test_gen_vectors_2g_plus_3g(void)
181{
182 struct osmo_sub_auth_data aud2g;
183 struct osmo_sub_auth_data aud3g;
184 struct osmo_auth_vector vec;
185 int rc;
186
187 comment_start();
188
189 aud2g = (struct osmo_sub_auth_data){
190 .type = OSMO_AUTH_TYPE_GSM,
191 .algo = OSMO_AUTH_ALG_COMP128v1,
192 };
193
194 osmo_hexparse("EB215756028D60E3275E613320AEC880",
195 aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki));
196
197 aud3g = (struct osmo_sub_auth_data){
198 .type = OSMO_AUTH_TYPE_UMTS,
199 .algo = OSMO_AUTH_ALG_MILENAGE,
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100200 .u.umts.sqn = 31,
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100201 };
202
203 osmo_hexparse("EB215756028D60E3275E613320AEC880",
204 aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
205 osmo_hexparse("FB2A3D1B360F599ABAB99DB8669F8308",
206 aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +0100207 next_rand("39fa2f4e3d523d8619a73b4f65c3e14d", true);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100208
209 vec = (struct osmo_auth_vector){ {0} };
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100210 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 31, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100211 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
212 VERBOSE_ASSERT(rc, == 1, "%d");
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100213 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 32, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100214
215 VEC_IS(&vec,
216 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
Neels Hofmeyrd846ae82017-03-15 00:37:29 +0100217 " autn: 8704f5ba55d30000541dde77ea5b1d8c\n"
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100218 " ck: f64735036e5871319c679f4742a75ea1\n"
219 " ik: 27497388b6cb044648f396aa155b95ef\n"
220 " res: e229c19e791f2e410000000000000000\n"
221 " res_len: 08\n"
222 " kc: 241a5b16aeb8e400\n"
223 " sres: 429d5b27\n"
224 " auth_types: 03000000\n"
225 );
226
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100227 /* even though vec is not zero-initialized, it should produce the same
228 * result with the same sequence nr */
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100229 aud3g.u.umts.sqn = 31;
230 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 31, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100231 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
232 VERBOSE_ASSERT(rc, == 1, "%d");
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100233 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 32, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100234
235 VEC_IS(&vec,
236 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
Neels Hofmeyrd846ae82017-03-15 00:37:29 +0100237 " autn: 8704f5ba55d30000541dde77ea5b1d8c\n"
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100238 " ck: f64735036e5871319c679f4742a75ea1\n"
239 " ik: 27497388b6cb044648f396aa155b95ef\n"
240 " res: e229c19e791f2e410000000000000000\n"
241 " res_len: 08\n"
242 " kc: 241a5b16aeb8e400\n"
243 " sres: 429d5b27\n"
244 " auth_types: 03000000\n"
245 );
246
247 comment_end();
248}
249
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100250void _test_gen_vectors_3g_only__expect_vecs(struct osmo_auth_vector vecs[3])
251{
252 fprintf(stderr, "[0]: ");
253 VEC_IS(&vecs[0],
254 " rand: 897210a0f7de278f0b8213098e098a3f\n"
255 " autn: c6b9790dad4b00000cf322869ea6a481\n"
256 " ck: e9922bd036718ed9e40bd1d02c3b81a5\n"
257 " ik: f19c20ca863137f8892326d959ec5e01\n"
258 " res: 9af5a557902d2db80000000000000000\n"
259 " res_len: 08\n"
260 " kc: 7526fc13c5976685\n"
261 " sres: 0ad888ef\n"
262 " auth_types: 03000000\n"
263 );
264 fprintf(stderr, "[1]: ");
265 VEC_IS(&vecs[1],
266 " rand: 9a8321b108ef38a01c93241a9f1a9b50\n"
267 " autn: 79a5113eb0910000be6020540503ffc5\n"
268 " ck: 3686f05df057d1899c66ae4eb18cf941\n"
269 " ik: 79f21ed53bcb47787de57d136ff803a5\n"
270 " res: 43023475cb29292c0000000000000000\n"
271 " res_len: 08\n"
272 " kc: aef73dd515e86c15\n"
273 " sres: 882b1d59\n"
274 " auth_types: 03000000\n"
275 );
276 fprintf(stderr, "[2]: ");
277 VEC_IS(&vecs[2],
278 " rand: ab9432c2190049b12da4352bb02bac61\n"
279 " autn: 24b018d46c3b00009c7e1b47f3a19b2b\n"
280 " ck: d86c3191a36fc0602e48202ef2080964\n"
281 " ik: 648dab72016181406243420649e63dc9\n"
282 " res: 010cab11cc63a6e40000000000000000\n"
283 " res_len: 08\n"
284 " kc: f0eaf8cb19e0758d\n"
285 " sres: cd6f0df5\n"
286 " auth_types: 03000000\n"
287 );
288}
289
Harald Weltebd94b412021-01-04 14:02:55 +0100290/* Subscriber with only 3G (MILENAGE) authentication data,
291 * reflects the default configuration of sysmoISIM-SJA2. Resulting
292 * tuples are suitable for both 2G and 3G authentication */
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100293static void test_gen_vectors_3g_only(void)
294{
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100295 struct osmo_sub_auth_data aud2g;
296 struct osmo_sub_auth_data aud3g;
297 struct osmo_auth_vector vec;
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100298 struct osmo_auth_vector vecs[3];
Neels Hofmeyrec9036b2017-02-21 21:56:11 +0100299 uint8_t auts[14];
300 uint8_t rand_auts[16];
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100301 int rc;
302
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100303 comment_start();
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100304
305 aud2g = (struct osmo_sub_auth_data){ 0 };
306
307 aud3g = (struct osmo_sub_auth_data){
308 .type = OSMO_AUTH_TYPE_UMTS,
309 .algo = OSMO_AUTH_ALG_MILENAGE,
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100310 .u.umts.sqn = 31,
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100311 };
312
313 osmo_hexparse("EB215756028D60E3275E613320AEC880",
314 aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
315 osmo_hexparse("FB2A3D1B360F599ABAB99DB8669F8308",
316 aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +0100317 next_rand("39fa2f4e3d523d8619a73b4f65c3e14d", true);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100318
319 vec = (struct osmo_auth_vector){ {0} };
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100320 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 31, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100321 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
322 VERBOSE_ASSERT(rc, == 1, "%d");
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100323 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 32, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100324
325 VEC_IS(&vec,
326 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
Neels Hofmeyrd846ae82017-03-15 00:37:29 +0100327 " autn: 8704f5ba55d30000541dde77ea5b1d8c\n"
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100328 " ck: f64735036e5871319c679f4742a75ea1\n"
329 " ik: 27497388b6cb044648f396aa155b95ef\n"
330 " res: e229c19e791f2e410000000000000000\n"
331 " res_len: 08\n"
332 " kc: 059a4f668f6fbe39\n"
333 " sres: 9b36efdf\n"
334 " auth_types: 03000000\n"
335 );
336
337 /* Note: 3GPP TS 33.102 6.8.1.2: c3 function to get GSM auth is
338 * KC[0..7] == CK[0..7] ^ CK[8..15] ^ IK[0..7] ^ IK[8..15]
339 * In [16]: hex( 0xf64735036e587131
340 * ^ 0x9c679f4742a75ea1
341 * ^ 0x27497388b6cb0446
342 * ^ 0x48f396aa155b95ef)
343 * Out[16]: '0x59a4f668f6fbe39L'
344 * hence expecting kc: 059a4f668f6fbe39
345 */
346
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100347 /* even though vec is not zero-initialized, it should produce the same
348 * result with the same sequence nr */
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100349 aud3g.u.umts.sqn = 31;
350 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 31, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100351 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
352 VERBOSE_ASSERT(rc, == 1, "%d");
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100353 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 32, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100354
355 VEC_IS(&vec,
356 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
Neels Hofmeyrd846ae82017-03-15 00:37:29 +0100357 " autn: 8704f5ba55d30000541dde77ea5b1d8c\n"
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100358 " ck: f64735036e5871319c679f4742a75ea1\n"
359 " ik: 27497388b6cb044648f396aa155b95ef\n"
360 " res: e229c19e791f2e410000000000000000\n"
361 " res_len: 08\n"
362 " kc: 059a4f668f6fbe39\n"
363 " sres: 9b36efdf\n"
364 " auth_types: 03000000\n"
365 );
366
Neels Hofmeyrec9036b2017-02-21 21:56:11 +0100367
368 fprintf(stderr, "- test AUTS resync\n");
369 vec = (struct osmo_auth_vector){};
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100370 aud3g.u.umts.sqn = 31;
371 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 31, "%"PRIu64);
Neels Hofmeyrec9036b2017-02-21 21:56:11 +0100372
373 /* The AUTN sent was 8704f5ba55f30000d2ee44b22c8ea919
374 * with the first 6 bytes being SQN ^ AK.
375 * K = EB215756028D60E3275E613320AEC880
376 * OPC = FB2A3D1B360F599ABAB99DB8669F8308
377 * RAND = 39fa2f4e3d523d8619a73b4f65c3e14d
378 * --milenage-f5-->
379 * AK = 8704f5ba55f3
380 *
381 * The first six bytes are 8704f5ba55f3,
382 * and 8704f5ba55f3 ^ AK = 0.
383 * --> SQN = 0.
384 *
385 * Say the USIM doesn't like that, let's say it is at SQN 23.
386 * SQN_MS = 000000000017
387 *
388 * AUTS = Conc(SQN_MS) || MAC-S
389 * Conc(SQN_MS) = SQN_MS ⊕ f5*[K](RAND)
390 * MAC-S = f1*[K] (SQN MS || RAND || AMF)
391 *
392 * f5*--> Conc(SQN_MS) = 000000000017 ^ 979498b1f73a
393 * = 979498b1f72d
394 * AMF = 0000 (TS 33.102 v7.0.0, 6.3.3)
395 *
396 * MAC-S = f1*[K] (000000000017 || 39fa2f4e3d523d8619a73b4f65c3e14d || 0000)
397 * = 3e28c59fa2e72f9c
398 *
399 * AUTS = 979498b1f72d || 3e28c59fa2e72f9c
400 *
401 * verify valid AUTS resulting in SQN 23 with:
402 * osmo-auc-gen -3 -a milenage -k EB215756028D60E3275E613320AEC880 \
403 * -o FB2A3D1B360F599ABAB99DB8669F8308 \
404 * -r 39fa2f4e3d523d8619a73b4f65c3e14d \
405 * -A 979498b1f72d3e28c59fa2e72f9c
406 */
407
408 /* AUTS response by USIM */
409 osmo_hexparse("979498b1f72d3e28c59fa2e72f9c",
410 auts, sizeof(auts));
411 /* RAND sent to USIM, which AUTS was generated from */
412 osmo_hexparse("39fa2f4e3d523d8619a73b4f65c3e14d",
413 rand_auts, sizeof(rand_auts));
414 /* new RAND token for the next key */
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +0100415 next_rand("897210a0f7de278f0b8213098e098a3f", true);
Neels Hofmeyrec9036b2017-02-21 21:56:11 +0100416 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, rand_auts, auts);
417 VERBOSE_ASSERT(rc, == 1, "%d");
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100418 /* The USIM's last sqn was 23, the calculated vector was 24 */
419 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 24, "%"PRIu64);
Neels Hofmeyrec9036b2017-02-21 21:56:11 +0100420
421 VEC_IS(&vec,
422 " rand: 897210a0f7de278f0b8213098e098a3f\n"
423 " autn: c6b9790dad4b00000cf322869ea6a481\n"
424 " ck: e9922bd036718ed9e40bd1d02c3b81a5\n"
425 " ik: f19c20ca863137f8892326d959ec5e01\n"
426 " res: 9af5a557902d2db80000000000000000\n"
427 " res_len: 08\n"
428 " kc: 7526fc13c5976685\n"
429 " sres: 0ad888ef\n"
430 " auth_types: 03000000\n"
431 );
432
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100433
434 fprintf(stderr, "- verify N vectors with AUTS resync"
435 " == N vectors without AUTS\n"
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100436 "First just set rand and sqn = 23, and compute 3 vectors\n");
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100437 next_rand("897210a0f7de278f0b8213098e098a3f", false);
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100438 aud3g.u.umts.sqn = 23;
439 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 23, "%"PRIu64);
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100440
441 memset(vecs, 0, sizeof(vecs));
442 rc = auc_compute_vectors(vecs, 3, &aud2g, &aud3g, NULL, NULL);
443 VERBOSE_ASSERT(rc, == 3, "%d");
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100444 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 26, "%"PRIu64);
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100445
446 _test_gen_vectors_3g_only__expect_vecs(vecs);
447
Neels Hofmeyrea1052d2017-03-15 02:42:19 +0100448 fprintf(stderr, "Now reach sqn = 23 with AUTS and expect the same\n");
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100449 /* AUTS response by USIM */
450 osmo_hexparse("979498b1f72d3e28c59fa2e72f9c",
451 auts, sizeof(auts));
452 /* RAND sent to USIM, which AUTS was generated from */
453 osmo_hexparse("39fa2f4e3d523d8619a73b4f65c3e14d",
454 rand_auts, sizeof(rand_auts));
455 next_rand("897210a0f7de278f0b8213098e098a3f", false);
456 rc = auc_compute_vectors(vecs, 3, &aud2g, &aud3g, rand_auts, auts);
457
Neels Hofmeyrb5b11e32017-02-22 01:42:43 +0100458 _test_gen_vectors_3g_only__expect_vecs(vecs);
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100459
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100460 comment_end();
461}
462
Harald Weltebd94b412021-01-04 14:02:55 +0100463/* Subscriber with only 3G (XOR) authentication data,
464 * reflects the default configuration of sysmoTSIM-SJAx as well
465 * as many "Test USIM" cards. Resulting tuples are suitable for both
466 * 2G and 3G authentication */
Harald Welte6e237d32020-12-28 01:01:31 +0100467static void test_gen_vectors_3g_xor(void)
468{
469 struct osmo_sub_auth_data aud2g;
470 struct osmo_sub_auth_data aud3g;
471 struct osmo_auth_vector vec;
472 int rc;
473
474 comment_start();
475
476 aud2g = (struct osmo_sub_auth_data){ 0 };
477
478 aud3g = (struct osmo_sub_auth_data){
479 .type = OSMO_AUTH_TYPE_UMTS,
480 .algo = OSMO_AUTH_ALG_XOR,
481 .u.umts.sqn = 0,
482 };
483
484 osmo_hexparse("000102030405060708090a0b0c0d0e0f",
485 aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
486 osmo_hexparse("00000000000000000000000000000000",
487 aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
488 next_rand("b5039c57e4a75051551d1a390a71ce48", true);
489
490 vec = (struct osmo_auth_vector){ {0} };
491 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
492 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
493 VERBOSE_ASSERT(rc, == 1, "%d");
494 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
495
496 VEC_IS(&vec,
497 " rand: b5039c57e4a75051551d1a390a71ce48\n"
498 " autn: 54e0a256565d0000b5029e54e0a25656\n"
499 " ck: 029e54e0a256565d141032067cc047b5\n"
500 " ik: 9e54e0a256565d141032067cc047b502\n"
501 " res: b5029e54e0a256565d141032067cc047\n"
502 " res_len: 10\n"
503 " kc: 98e880384887f9fe\n"
504 " sres: 0ec81877\n"
505 " auth_types: 03000000\n"
506 );
507
508 comment_end();
509}
510
Harald Weltebd94b412021-01-04 14:02:55 +0100511/* Test a variety of invalid authentication data combinations */
Harald Welte7a476532022-11-03 11:38:41 +0100512void test_gen_vectors_bad_args(void)
Neels Hofmeyr569d3222017-02-21 22:57:11 +0100513{
514 struct osmo_auth_vector vec;
515 uint8_t auts[14];
516 uint8_t rand_auts[16];
517 int rc;
518 int i;
519
520 struct osmo_sub_auth_data aud2g = {
521 .type = OSMO_AUTH_TYPE_GSM,
522 .algo = OSMO_AUTH_ALG_COMP128v1,
523 };
524
525 struct osmo_sub_auth_data aud3g = {
526 .type = OSMO_AUTH_TYPE_UMTS,
527 .algo = OSMO_AUTH_ALG_MILENAGE,
528 };
529
530 struct osmo_sub_auth_data aud2g_noalg = {
531 .type = OSMO_AUTH_TYPE_GSM,
532 .algo = OSMO_AUTH_ALG_NONE,
533 };
534
535 struct osmo_sub_auth_data aud3g_noalg = {
536 .type = OSMO_AUTH_TYPE_UMTS,
537 .algo = OSMO_AUTH_ALG_NONE,
538 };
539
540 struct osmo_sub_auth_data aud_notype = {
541 .type = OSMO_AUTH_TYPE_NONE,
542 .algo = OSMO_AUTH_ALG_MILENAGE,
543 };
544
545 struct osmo_sub_auth_data no_aud = {
546 .type = OSMO_AUTH_TYPE_NONE,
547 .algo = OSMO_AUTH_ALG_NONE,
548 };
549
550 struct {
551 struct osmo_sub_auth_data *aud2g;
552 struct osmo_sub_auth_data *aud3g;
553 uint8_t *rand_auts;
554 uint8_t *auts;
555 const char *label;
556 } tests[] = {
557 { NULL, NULL, NULL, NULL, "no auth data (a)"},
558 { NULL, &aud3g_noalg, NULL, NULL, "no auth data (b)"},
559 { NULL, &aud_notype, NULL, NULL, "no auth data (c)"},
560 { NULL, &no_aud, NULL, NULL, "no auth data (d)"},
561 { &aud2g_noalg, NULL, NULL, NULL, "no auth data (e)"},
562 { &aud2g_noalg, &aud3g_noalg, NULL, NULL, "no auth data (f)"},
563 { &aud2g_noalg, &aud_notype, NULL, NULL, "no auth data (g)"},
564 { &aud2g_noalg, &no_aud, NULL, NULL, "no auth data (h)"},
565 { &aud_notype, NULL, NULL, NULL, "no auth data (i)"},
566 { &aud_notype, &aud3g_noalg, NULL, NULL, "no auth data (j)"},
567 { &aud_notype, &aud_notype, NULL, NULL, "no auth data (k)"},
568 { &aud_notype, &no_aud, NULL, NULL, "no auth data (l)"},
569 { &no_aud, NULL, NULL, NULL, "no auth data (m)"},
570 { &no_aud, &aud3g_noalg, NULL, NULL, "no auth data (n)"},
571 { &no_aud, &aud_notype, NULL, NULL, "no auth data (o)"},
572 { &no_aud, &no_aud, NULL, NULL, "no auth data (p)"},
573 { &aud3g, NULL, NULL, NULL, "wrong auth data type (a)"},
574 { &aud3g, &aud3g_noalg, NULL, NULL, "wrong auth data type (b)"},
575 { &aud3g, &aud_notype, NULL, NULL, "wrong auth data type (c)"},
576 { &aud3g, &no_aud, NULL, NULL, "wrong auth data type (d)"},
577 { NULL, &aud2g, NULL, NULL, "wrong auth data type (e)"},
578 { &aud3g_noalg, &aud2g, NULL, NULL, "wrong auth data type (f)"},
579 { &aud_notype, &aud2g, NULL, NULL, "wrong auth data type (g)"},
580 { &no_aud, &aud2g, NULL, NULL, "wrong auth data type (h)"},
581 { &aud3g, &aud2g, NULL, NULL, "wrong auth data type (i)"},
582 { &aud3g, &aud3g, NULL, NULL, "wrong auth data type (j)"},
583 { &aud2g, &aud2g, NULL, NULL, "wrong auth data type (k)"},
584 { &aud2g, NULL, rand_auts, auts, "AUTS for 2G-only (a)"},
585 { &aud2g, &aud3g_noalg, rand_auts, auts, "AUTS for 2G-only (b)"},
586 { &aud2g, &aud_notype, rand_auts, auts, "AUTS for 2G-only (c)"},
587 { &aud2g, &no_aud, rand_auts, auts, "AUTS for 2G-only (d)"},
588 { NULL, &aud3g, NULL, auts, "incomplete AUTS (a)"},
589 { NULL, &aud3g, rand_auts, NULL, "incomplete AUTS (b)"},
590 { &aud2g, &aud3g, NULL, auts, "incomplete AUTS (c)"},
591 { &aud2g, &aud3g, rand_auts, NULL, "incomplete AUTS (d)"},
592 };
593
594 comment_start();
595
596 for (i = 0; i < ARRAY_SIZE(tests); i++) {
597 fprintf(stderr, "\n- %s\n", tests[i].label);
598 rc = auc_compute_vectors(&vec, 1,
599 tests[i].aud2g,
600 tests[i].aud3g,
601 tests[i].rand_auts,
602 tests[i].auts);
603 VERBOSE_ASSERT(rc, < 0, "%d");
604 }
605
606 comment_end();
607}
608
Neels Hofmeyr21380ae2017-02-21 21:53:38 +0100609static struct {
610 bool verbose;
611} cmdline_opts = {
612 .verbose = false,
613};
614
615static void print_help(const char *program)
616{
617 printf("Usage:\n"
618 " %s [-v] [N [N...]]\n"
619 "Options:\n"
620 " -h --help show this text.\n"
621 " -v --verbose print source file and line numbers\n",
622 program
623 );
624}
625
626static void handle_options(int argc, char **argv)
627{
628 while (1) {
629 int option_index = 0, c;
630 static struct option long_options[] = {
631 {"help", 0, 0, 'h'},
632 {"verbose", 1, 0, 'v'},
633 {0, 0, 0, 0}
634 };
635
636 c = getopt_long(argc, argv, "hv",
637 long_options, &option_index);
638 if (c == -1)
639 break;
640
641 switch (c) {
642 case 'h':
643 print_help(argv[0]);
644 exit(0);
645 case 'v':
646 cmdline_opts.verbose = true;
647 break;
648 default:
649 /* catch unknown options *as well as* missing arguments. */
650 fprintf(stderr, "Error in command line options. Exiting.\n");
651 exit(-1);
652 break;
653 }
654 }
655
656 if (optind < argc) {
657 fprintf(stderr, "too many args\n");
658 exit(-1);
659 }
660}
661
662int main(int argc, char **argv)
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100663{
664 printf("auc_3g_test.c\n");
Neels Hofmeyr21380ae2017-02-21 21:53:38 +0100665
666 handle_options(argc, argv);
667
Pau Espin Pedrol51530312018-04-17 15:07:06 +0200668 void *tall_ctx = talloc_named_const(NULL, 1, "auc_test");
669
670 osmo_init_logging2(tall_ctx, &hlr_log_info);
Pau Espin Pedrold6993ea2021-02-19 13:20:18 +0100671 log_set_print_filename2(osmo_stderr_target,
672 cmdline_opts.verbose ?
673 LOG_FILENAME_BASENAME :
674 LOG_FILENAME_NONE);
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100675 log_set_print_timestamp(osmo_stderr_target, 0);
676 log_set_use_color(osmo_stderr_target, 0);
Pau Espin Pedrold6993ea2021-02-19 13:20:18 +0100677 log_set_print_category_hex(osmo_stderr_target, 0);
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100678 log_set_print_category(osmo_stderr_target, 1);
Neels Hofmeyr6eb231e2017-10-27 03:35:45 +0200679 log_parse_category_mask(osmo_stderr_target, "DMAIN,1:DDB,1:DAUC,1");
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100680
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100681 test_gen_vectors_2g_only();
682 test_gen_vectors_2g_plus_3g();
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100683 test_gen_vectors_3g_only();
Harald Welte6e237d32020-12-28 01:01:31 +0100684 test_gen_vectors_3g_xor();
Neels Hofmeyr569d3222017-02-21 22:57:11 +0100685 test_gen_vectors_bad_args();
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100686
687 printf("Done\n");
688 return 0;
689}