blob: f8ff67a1e279533a40aa2eae962f75fcede92b07 [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 Hofmeyr00c06972017-01-31 01:19:27 +010024
25#include <osmocom/core/application.h>
26#include <osmocom/core/utils.h>
27#include <osmocom/core/logging.h>
28
Neels Hofmeyr8cde6622017-01-31 02:10:40 +010029#include <osmocom/crypt/auth.h>
Neels Hofmeyr00c06972017-01-31 01:19:27 +010030
Neels Hofmeyr8cde6622017-01-31 02:10:40 +010031#include "logging.h"
32#include "auc.h"
33
34#define comment_start() fprintf(stderr, "\n===== %s\n", __func__);
Neels Hofmeyr00c06972017-01-31 01:19:27 +010035#define comment_end() fprintf(stderr, "===== %s: SUCCESS\n\n", __func__);
36
Neels Hofmeyr8cde6622017-01-31 02:10:40 +010037#define VERBOSE_ASSERT(val, expect_op, fmt) \
38 do { \
39 fprintf(stderr, #val " == " fmt "\n", (val)); \
40 OSMO_ASSERT((val) expect_op); \
41 } while (0);
42
Neels Hofmeyr6b883f72017-01-31 16:40:28 +010043char *vec_str(const struct osmo_auth_vector *vec)
Neels Hofmeyr8cde6622017-01-31 02:10:40 +010044{
45 static char buf[1024];
46 char *pos = buf;
47 char *end = buf + sizeof(buf);
48
49#define append(what) \
50 if (pos >= end) \
51 return buf; \
52 pos += snprintf(pos, sizeof(buf) - (pos - buf), \
53 " " #what ": %s\n", \
54 osmo_hexdump_nospc((void*)&vec->what, sizeof(vec->what)))
55
56 append(rand);
57 append(autn);
58 append(ck);
59 append(ik);
60 append(res);
61 append(res_len);
62 append(kc);
63 append(sres);
64 append(auth_types);
65#undef append
66
67 return buf;
68}
69
70#define VEC_IS(vec, expect) do { \
Neels Hofmeyr6b883f72017-01-31 16:40:28 +010071 char *_is = vec_str(vec); \
Neels Hofmeyr8cde6622017-01-31 02:10:40 +010072 fprintf(stderr, "auth vector ==\n%s\n", _is); \
73 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) { \
80 while (a > _is && *(a-1) != '\n') a--; \
81 fprintf(stderr, "mismatch at %d:\n" \
Neels Hofmeyr6b883f72017-01-31 16:40:28 +010082 "%s", (int)(a - _is), a); \
Neels Hofmeyr8cde6622017-01-31 02:10:40 +010083 break; \
84 } \
85 } \
86 OSMO_ASSERT(false); \
87 } \
88 } while (0)
89
Neels Hofmeyr00c06972017-01-31 01:19:27 +010090uint8_t fake_rand[16] = { 0 };
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +010091bool fake_rand_fixed = true;
92
93void next_rand(const char *hexstr, bool fixed)
94{
95 osmo_hexparse(hexstr, fake_rand, sizeof(fake_rand));
96 fake_rand_fixed = fixed;
97}
Neels Hofmeyr00c06972017-01-31 01:19:27 +010098
99int rand_get(uint8_t *rand, unsigned int len)
100{
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +0100101 int i;
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100102 OSMO_ASSERT(len <= sizeof(fake_rand));
103 memcpy(rand, fake_rand, len);
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +0100104 if (!fake_rand_fixed) {
105 for (i = 0; i < len; i++)
106 fake_rand[i] += 0x11;
107 }
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100108 return len;
109}
110
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100111static void test_gen_vectors_2g_only(void)
112{
113 struct osmo_sub_auth_data aud2g;
114 struct osmo_sub_auth_data aud3g;
115 struct osmo_auth_vector vec;
116 int rc;
117
118 comment_start();
119
120 aud2g = (struct osmo_sub_auth_data){
121 .type = OSMO_AUTH_TYPE_GSM,
122 .algo = OSMO_AUTH_ALG_COMP128v1,
123 };
124
125 osmo_hexparse("EB215756028D60E3275E613320AEC880",
126 aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki));
127
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100128 aud3g = (struct osmo_sub_auth_data){ 0 };
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100129
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +0100130 next_rand("39fa2f4e3d523d8619a73b4f65c3e14d", true);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100131
132 vec = (struct osmo_auth_vector){ {0} };
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100133 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100134 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
135 VERBOSE_ASSERT(rc, == 1, "%d");
136
137 VEC_IS(&vec,
138 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
139 " autn: 00000000000000000000000000000000\n"
140 " ck: 00000000000000000000000000000000\n"
141 " ik: 00000000000000000000000000000000\n"
142 " res: 00000000000000000000000000000000\n"
143 " res_len: 00\n"
144 " kc: 241a5b16aeb8e400\n"
145 " sres: 429d5b27\n"
146 " auth_types: 01000000\n"
147 );
148
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100149 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100150
151 /* even though vec is not zero-initialized, it should produce the same
152 * result (regardless of the umts sequence nr) */
153 aud3g.u.umts.sqn = 123;
154 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
155 VERBOSE_ASSERT(rc, == 1, "%d");
156
157 VEC_IS(&vec,
158 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
159 " autn: 00000000000000000000000000000000\n"
160 " ck: 00000000000000000000000000000000\n"
161 " ik: 00000000000000000000000000000000\n"
162 " res: 00000000000000000000000000000000\n"
163 " res_len: 00\n"
164 " kc: 241a5b16aeb8e400\n"
165 " sres: 429d5b27\n"
166 " auth_types: 01000000\n"
167 );
168
169 comment_end();
170}
171
172static void test_gen_vectors_2g_plus_3g(void)
173{
174 struct osmo_sub_auth_data aud2g;
175 struct osmo_sub_auth_data aud3g;
176 struct osmo_auth_vector vec;
177 int rc;
178
179 comment_start();
180
181 aud2g = (struct osmo_sub_auth_data){
182 .type = OSMO_AUTH_TYPE_GSM,
183 .algo = OSMO_AUTH_ALG_COMP128v1,
184 };
185
186 osmo_hexparse("EB215756028D60E3275E613320AEC880",
187 aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki));
188
189 aud3g = (struct osmo_sub_auth_data){
190 .type = OSMO_AUTH_TYPE_UMTS,
191 .algo = OSMO_AUTH_ALG_MILENAGE,
192 };
193
194 osmo_hexparse("EB215756028D60E3275E613320AEC880",
195 aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
196 osmo_hexparse("FB2A3D1B360F599ABAB99DB8669F8308",
197 aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +0100198 next_rand("39fa2f4e3d523d8619a73b4f65c3e14d", true);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100199
200 vec = (struct osmo_auth_vector){ {0} };
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100201 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100202 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
203 VERBOSE_ASSERT(rc, == 1, "%d");
204
205 VEC_IS(&vec,
206 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
207 " autn: 8704f5ba55f30000d2ee44b22c8ea919\n"
208 " ck: f64735036e5871319c679f4742a75ea1\n"
209 " ik: 27497388b6cb044648f396aa155b95ef\n"
210 " res: e229c19e791f2e410000000000000000\n"
211 " res_len: 08\n"
212 " kc: 241a5b16aeb8e400\n"
213 " sres: 429d5b27\n"
214 " auth_types: 03000000\n"
215 );
216
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100217 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 1, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100218
219 /* even though vec is not zero-initialized, it should produce the same
220 * result with the same sequence nr */
221 aud3g.u.umts.sqn = 0;
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100222 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100223 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
224 VERBOSE_ASSERT(rc, == 1, "%d");
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100225 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 1, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100226
227 VEC_IS(&vec,
228 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
229 " autn: 8704f5ba55f30000d2ee44b22c8ea919\n"
230 " ck: f64735036e5871319c679f4742a75ea1\n"
231 " ik: 27497388b6cb044648f396aa155b95ef\n"
232 " res: e229c19e791f2e410000000000000000\n"
233 " res_len: 08\n"
234 " kc: 241a5b16aeb8e400\n"
235 " sres: 429d5b27\n"
236 " auth_types: 03000000\n"
237 );
238
239 comment_end();
240}
241
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100242void _test_gen_vectors_3g_only__expect_vecs__WRONG(struct osmo_auth_vector vecs[3])
243{
244 fprintf(stderr, "THERE IS A BUG AND THE TEST PASSES THE WRONG VECTORS UNTIL THAT IS FIXED\n");
245 fprintf(stderr, "The SQN should increment with each new vector.\n");
246 fprintf(stderr, "[0]: ");
247 VEC_IS(&vecs[0],
248 " rand: 897210a0f7de278f0b8213098e098a3f\n"
249 " autn: c6b9790dad4b00000cf322869ea6a481\n"
250 " ck: e9922bd036718ed9e40bd1d02c3b81a5\n"
251 " ik: f19c20ca863137f8892326d959ec5e01\n"
252 " res: 9af5a557902d2db80000000000000000\n"
253 " res_len: 08\n"
254 " kc: 7526fc13c5976685\n"
255 " sres: 0ad888ef\n"
256 " auth_types: 03000000\n"
257 );
258 fprintf(stderr, "[1]: ");
259 VEC_IS(&vecs[1],
260 " rand: 9a8321b108ef38a01c93241a9f1a9b50\n"
261 " autn: 79a5113eb0900000f7e138537aa0962b\n"
262 " ck: 3686f05df057d1899c66ae4eb18cf941\n"
263 " ik: 79f21ed53bcb47787de57d136ff803a5\n"
264 " res: 43023475cb29292c0000000000000000\n"
265 " res_len: 08\n"
266 " kc: aef73dd515e86c15\n"
267 " sres: 882b1d59\n"
268 " auth_types: 03000000\n"
269 );
270 fprintf(stderr, "[2]: ");
271 VEC_IS(&vecs[2],
272 " rand: ab9432c2190049b12da4352bb02bac61\n"
273 " autn: 24b018d46c390000d88e11730d0367ac\n"
274 " ck: d86c3191a36fc0602e48202ef2080964\n"
275 " ik: 648dab72016181406243420649e63dc9\n"
276 " res: 010cab11cc63a6e40000000000000000\n"
277 " res_len: 08\n"
278 " kc: f0eaf8cb19e0758d\n"
279 " sres: cd6f0df5\n"
280 " auth_types: 03000000\n"
281 );
282}
283
284void _test_gen_vectors_3g_only__expect_vecs(struct osmo_auth_vector vecs[3])
285{
286 fprintf(stderr, "[0]: ");
287 VEC_IS(&vecs[0],
288 " rand: 897210a0f7de278f0b8213098e098a3f\n"
289 " autn: c6b9790dad4b00000cf322869ea6a481\n"
290 " ck: e9922bd036718ed9e40bd1d02c3b81a5\n"
291 " ik: f19c20ca863137f8892326d959ec5e01\n"
292 " res: 9af5a557902d2db80000000000000000\n"
293 " res_len: 08\n"
294 " kc: 7526fc13c5976685\n"
295 " sres: 0ad888ef\n"
296 " auth_types: 03000000\n"
297 );
298 fprintf(stderr, "[1]: ");
299 VEC_IS(&vecs[1],
300 " rand: 9a8321b108ef38a01c93241a9f1a9b50\n"
301 " autn: 79a5113eb0910000be6020540503ffc5\n"
302 " ck: 3686f05df057d1899c66ae4eb18cf941\n"
303 " ik: 79f21ed53bcb47787de57d136ff803a5\n"
304 " res: 43023475cb29292c0000000000000000\n"
305 " res_len: 08\n"
306 " kc: aef73dd515e86c15\n"
307 " sres: 882b1d59\n"
308 " auth_types: 03000000\n"
309 );
310 fprintf(stderr, "[2]: ");
311 VEC_IS(&vecs[2],
312 " rand: ab9432c2190049b12da4352bb02bac61\n"
313 " autn: 24b018d46c3b00009c7e1b47f3a19b2b\n"
314 " ck: d86c3191a36fc0602e48202ef2080964\n"
315 " ik: 648dab72016181406243420649e63dc9\n"
316 " res: 010cab11cc63a6e40000000000000000\n"
317 " res_len: 08\n"
318 " kc: f0eaf8cb19e0758d\n"
319 " sres: cd6f0df5\n"
320 " auth_types: 03000000\n"
321 );
322}
323
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100324static void test_gen_vectors_3g_only(void)
325{
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100326 struct osmo_sub_auth_data aud2g;
327 struct osmo_sub_auth_data aud3g;
328 struct osmo_auth_vector vec;
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100329 struct osmo_auth_vector vecs[3];
Neels Hofmeyrec9036b2017-02-21 21:56:11 +0100330 uint8_t auts[14];
331 uint8_t rand_auts[16];
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100332 int rc;
333
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100334 comment_start();
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100335
336 aud2g = (struct osmo_sub_auth_data){ 0 };
337
338 aud3g = (struct osmo_sub_auth_data){
339 .type = OSMO_AUTH_TYPE_UMTS,
340 .algo = OSMO_AUTH_ALG_MILENAGE,
341 };
342
343 osmo_hexparse("EB215756028D60E3275E613320AEC880",
344 aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
345 osmo_hexparse("FB2A3D1B360F599ABAB99DB8669F8308",
346 aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +0100347 next_rand("39fa2f4e3d523d8619a73b4f65c3e14d", true);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100348
349 vec = (struct osmo_auth_vector){ {0} };
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100350 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"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");
353
354 VEC_IS(&vec,
355 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
356 " autn: 8704f5ba55f30000d2ee44b22c8ea919\n"
357 " ck: f64735036e5871319c679f4742a75ea1\n"
358 " ik: 27497388b6cb044648f396aa155b95ef\n"
359 " res: e229c19e791f2e410000000000000000\n"
360 " res_len: 08\n"
361 " kc: 059a4f668f6fbe39\n"
362 " sres: 9b36efdf\n"
363 " auth_types: 03000000\n"
364 );
365
366 /* Note: 3GPP TS 33.102 6.8.1.2: c3 function to get GSM auth is
367 * KC[0..7] == CK[0..7] ^ CK[8..15] ^ IK[0..7] ^ IK[8..15]
368 * In [16]: hex( 0xf64735036e587131
369 * ^ 0x9c679f4742a75ea1
370 * ^ 0x27497388b6cb0446
371 * ^ 0x48f396aa155b95ef)
372 * Out[16]: '0x59a4f668f6fbe39L'
373 * hence expecting kc: 059a4f668f6fbe39
374 */
375
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100376 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 1, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100377
378 /* even though vec is not zero-initialized, it should produce the same
379 * result with the same sequence nr */
380 aud3g.u.umts.sqn = 0;
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100381 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100382 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
383 VERBOSE_ASSERT(rc, == 1, "%d");
Neels Hofmeyr6b883f72017-01-31 16:40:28 +0100384 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 1, "%"PRIu64);
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100385
386 VEC_IS(&vec,
387 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
388 " autn: 8704f5ba55f30000d2ee44b22c8ea919\n"
389 " ck: f64735036e5871319c679f4742a75ea1\n"
390 " ik: 27497388b6cb044648f396aa155b95ef\n"
391 " res: e229c19e791f2e410000000000000000\n"
392 " res_len: 08\n"
393 " kc: 059a4f668f6fbe39\n"
394 " sres: 9b36efdf\n"
395 " auth_types: 03000000\n"
396 );
397
Neels Hofmeyrec9036b2017-02-21 21:56:11 +0100398
399 fprintf(stderr, "- test AUTS resync\n");
400 vec = (struct osmo_auth_vector){};
401 aud3g.u.umts.sqn = 0;
402 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
403
404 /* The AUTN sent was 8704f5ba55f30000d2ee44b22c8ea919
405 * with the first 6 bytes being SQN ^ AK.
406 * K = EB215756028D60E3275E613320AEC880
407 * OPC = FB2A3D1B360F599ABAB99DB8669F8308
408 * RAND = 39fa2f4e3d523d8619a73b4f65c3e14d
409 * --milenage-f5-->
410 * AK = 8704f5ba55f3
411 *
412 * The first six bytes are 8704f5ba55f3,
413 * and 8704f5ba55f3 ^ AK = 0.
414 * --> SQN = 0.
415 *
416 * Say the USIM doesn't like that, let's say it is at SQN 23.
417 * SQN_MS = 000000000017
418 *
419 * AUTS = Conc(SQN_MS) || MAC-S
420 * Conc(SQN_MS) = SQN_MS ⊕ f5*[K](RAND)
421 * MAC-S = f1*[K] (SQN MS || RAND || AMF)
422 *
423 * f5*--> Conc(SQN_MS) = 000000000017 ^ 979498b1f73a
424 * = 979498b1f72d
425 * AMF = 0000 (TS 33.102 v7.0.0, 6.3.3)
426 *
427 * MAC-S = f1*[K] (000000000017 || 39fa2f4e3d523d8619a73b4f65c3e14d || 0000)
428 * = 3e28c59fa2e72f9c
429 *
430 * AUTS = 979498b1f72d || 3e28c59fa2e72f9c
431 *
432 * verify valid AUTS resulting in SQN 23 with:
433 * osmo-auc-gen -3 -a milenage -k EB215756028D60E3275E613320AEC880 \
434 * -o FB2A3D1B360F599ABAB99DB8669F8308 \
435 * -r 39fa2f4e3d523d8619a73b4f65c3e14d \
436 * -A 979498b1f72d3e28c59fa2e72f9c
437 */
438
439 /* AUTS response by USIM */
440 osmo_hexparse("979498b1f72d3e28c59fa2e72f9c",
441 auts, sizeof(auts));
442 /* RAND sent to USIM, which AUTS was generated from */
443 osmo_hexparse("39fa2f4e3d523d8619a73b4f65c3e14d",
444 rand_auts, sizeof(rand_auts));
445 /* new RAND token for the next key */
Neels Hofmeyr3aa3c102017-02-21 22:48:35 +0100446 next_rand("897210a0f7de278f0b8213098e098a3f", true);
Neels Hofmeyrec9036b2017-02-21 21:56:11 +0100447 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, rand_auts, auts);
448 VERBOSE_ASSERT(rc, == 1, "%d");
449 /* The USIM's last sqn was 23, the calculated vector was 24, hence the
450 * next one stored should be 25. */
451 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 25, "%"PRIu64);
452
453 VEC_IS(&vec,
454 " rand: 897210a0f7de278f0b8213098e098a3f\n"
455 " autn: c6b9790dad4b00000cf322869ea6a481\n"
456 " ck: e9922bd036718ed9e40bd1d02c3b81a5\n"
457 " ik: f19c20ca863137f8892326d959ec5e01\n"
458 " res: 9af5a557902d2db80000000000000000\n"
459 " res_len: 08\n"
460 " kc: 7526fc13c5976685\n"
461 " sres: 0ad888ef\n"
462 " auth_types: 03000000\n"
463 );
464
Neels Hofmeyr428c9472017-02-21 22:50:59 +0100465
466 fprintf(stderr, "- verify N vectors with AUTS resync"
467 " == N vectors without AUTS\n"
468 "First just set rand and sqn = 24, and compute 3 vectors\n");
469 next_rand("897210a0f7de278f0b8213098e098a3f", false);
470 aud3g.u.umts.sqn = 24;
471 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 24, "%"PRIu64);
472
473 memset(vecs, 0, sizeof(vecs));
474 rc = auc_compute_vectors(vecs, 3, &aud2g, &aud3g, NULL, NULL);
475 VERBOSE_ASSERT(rc, == 3, "%d");
476 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 27, "%"PRIu64);
477
478 _test_gen_vectors_3g_only__expect_vecs(vecs);
479
480 fprintf(stderr, "Now reach sqn = 24 with AUTS and expect the same\n");
481 /* AUTS response by USIM */
482 osmo_hexparse("979498b1f72d3e28c59fa2e72f9c",
483 auts, sizeof(auts));
484 /* RAND sent to USIM, which AUTS was generated from */
485 osmo_hexparse("39fa2f4e3d523d8619a73b4f65c3e14d",
486 rand_auts, sizeof(rand_auts));
487 next_rand("897210a0f7de278f0b8213098e098a3f", false);
488 rc = auc_compute_vectors(vecs, 3, &aud2g, &aud3g, rand_auts, auts);
489
490 /* THIS IS WRONG AND WILL BE FIXED IN A SUBSEQUENT COMMIT:
491 should be _test_gen_vectors_3g_only__expect_vecs() instead */
492 _test_gen_vectors_3g_only__expect_vecs__WRONG(vecs);
493
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100494 comment_end();
495}
496
Neels Hofmeyr569d3222017-02-21 22:57:11 +0100497void test_gen_vectors_bad_args()
498{
499 struct osmo_auth_vector vec;
500 uint8_t auts[14];
501 uint8_t rand_auts[16];
502 int rc;
503 int i;
504
505 struct osmo_sub_auth_data aud2g = {
506 .type = OSMO_AUTH_TYPE_GSM,
507 .algo = OSMO_AUTH_ALG_COMP128v1,
508 };
509
510 struct osmo_sub_auth_data aud3g = {
511 .type = OSMO_AUTH_TYPE_UMTS,
512 .algo = OSMO_AUTH_ALG_MILENAGE,
513 };
514
515 struct osmo_sub_auth_data aud2g_noalg = {
516 .type = OSMO_AUTH_TYPE_GSM,
517 .algo = OSMO_AUTH_ALG_NONE,
518 };
519
520 struct osmo_sub_auth_data aud3g_noalg = {
521 .type = OSMO_AUTH_TYPE_UMTS,
522 .algo = OSMO_AUTH_ALG_NONE,
523 };
524
525 struct osmo_sub_auth_data aud_notype = {
526 .type = OSMO_AUTH_TYPE_NONE,
527 .algo = OSMO_AUTH_ALG_MILENAGE,
528 };
529
530 struct osmo_sub_auth_data no_aud = {
531 .type = OSMO_AUTH_TYPE_NONE,
532 .algo = OSMO_AUTH_ALG_NONE,
533 };
534
535 struct {
536 struct osmo_sub_auth_data *aud2g;
537 struct osmo_sub_auth_data *aud3g;
538 uint8_t *rand_auts;
539 uint8_t *auts;
540 const char *label;
541 } tests[] = {
542 { NULL, NULL, NULL, NULL, "no auth data (a)"},
543 { NULL, &aud3g_noalg, NULL, NULL, "no auth data (b)"},
544 { NULL, &aud_notype, NULL, NULL, "no auth data (c)"},
545 { NULL, &no_aud, NULL, NULL, "no auth data (d)"},
546 { &aud2g_noalg, NULL, NULL, NULL, "no auth data (e)"},
547 { &aud2g_noalg, &aud3g_noalg, NULL, NULL, "no auth data (f)"},
548 { &aud2g_noalg, &aud_notype, NULL, NULL, "no auth data (g)"},
549 { &aud2g_noalg, &no_aud, NULL, NULL, "no auth data (h)"},
550 { &aud_notype, NULL, NULL, NULL, "no auth data (i)"},
551 { &aud_notype, &aud3g_noalg, NULL, NULL, "no auth data (j)"},
552 { &aud_notype, &aud_notype, NULL, NULL, "no auth data (k)"},
553 { &aud_notype, &no_aud, NULL, NULL, "no auth data (l)"},
554 { &no_aud, NULL, NULL, NULL, "no auth data (m)"},
555 { &no_aud, &aud3g_noalg, NULL, NULL, "no auth data (n)"},
556 { &no_aud, &aud_notype, NULL, NULL, "no auth data (o)"},
557 { &no_aud, &no_aud, NULL, NULL, "no auth data (p)"},
558 { &aud3g, NULL, NULL, NULL, "wrong auth data type (a)"},
559 { &aud3g, &aud3g_noalg, NULL, NULL, "wrong auth data type (b)"},
560 { &aud3g, &aud_notype, NULL, NULL, "wrong auth data type (c)"},
561 { &aud3g, &no_aud, NULL, NULL, "wrong auth data type (d)"},
562 { NULL, &aud2g, NULL, NULL, "wrong auth data type (e)"},
563 { &aud3g_noalg, &aud2g, NULL, NULL, "wrong auth data type (f)"},
564 { &aud_notype, &aud2g, NULL, NULL, "wrong auth data type (g)"},
565 { &no_aud, &aud2g, NULL, NULL, "wrong auth data type (h)"},
566 { &aud3g, &aud2g, NULL, NULL, "wrong auth data type (i)"},
567 { &aud3g, &aud3g, NULL, NULL, "wrong auth data type (j)"},
568 { &aud2g, &aud2g, NULL, NULL, "wrong auth data type (k)"},
569 { &aud2g, NULL, rand_auts, auts, "AUTS for 2G-only (a)"},
570 { &aud2g, &aud3g_noalg, rand_auts, auts, "AUTS for 2G-only (b)"},
571 { &aud2g, &aud_notype, rand_auts, auts, "AUTS for 2G-only (c)"},
572 { &aud2g, &no_aud, rand_auts, auts, "AUTS for 2G-only (d)"},
573 { NULL, &aud3g, NULL, auts, "incomplete AUTS (a)"},
574 { NULL, &aud3g, rand_auts, NULL, "incomplete AUTS (b)"},
575 { &aud2g, &aud3g, NULL, auts, "incomplete AUTS (c)"},
576 { &aud2g, &aud3g, rand_auts, NULL, "incomplete AUTS (d)"},
577 };
578
579 comment_start();
580
581 for (i = 0; i < ARRAY_SIZE(tests); i++) {
582 fprintf(stderr, "\n- %s\n", tests[i].label);
583 rc = auc_compute_vectors(&vec, 1,
584 tests[i].aud2g,
585 tests[i].aud3g,
586 tests[i].rand_auts,
587 tests[i].auts);
588 VERBOSE_ASSERT(rc, < 0, "%d");
589 }
590
591 comment_end();
592}
593
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100594int main()
595{
596 printf("auc_3g_test.c\n");
597 osmo_init_logging(&hlr_log_info);
598 log_set_print_filename(osmo_stderr_target, 0);
599 log_set_print_timestamp(osmo_stderr_target, 0);
600 log_set_use_color(osmo_stderr_target, 0);
601 log_set_print_category(osmo_stderr_target, 1);
602
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100603 test_gen_vectors_2g_only();
604 test_gen_vectors_2g_plus_3g();
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100605 test_gen_vectors_3g_only();
Neels Hofmeyr569d3222017-02-21 22:57:11 +0100606 test_gen_vectors_bad_args();
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100607
608 printf("Done\n");
609 return 0;
610}