blob: bfca39ff4e2287813ced2c0a37a59bea7934ca4b [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>
23
24#include <osmocom/core/application.h>
25#include <osmocom/core/utils.h>
26#include <osmocom/core/logging.h>
27
Neels Hofmeyr8cde6622017-01-31 02:10:40 +010028#include <osmocom/crypt/auth.h>
Neels Hofmeyr00c06972017-01-31 01:19:27 +010029
Neels Hofmeyr8cde6622017-01-31 02:10:40 +010030#include "logging.h"
31#include "auc.h"
32
33#define comment_start() fprintf(stderr, "\n===== %s\n", __func__);
Neels Hofmeyr00c06972017-01-31 01:19:27 +010034#define comment_end() fprintf(stderr, "===== %s: SUCCESS\n\n", __func__);
35
Neels Hofmeyr8cde6622017-01-31 02:10:40 +010036#define VERBOSE_ASSERT(val, expect_op, fmt) \
37 do { \
38 fprintf(stderr, #val " == " fmt "\n", (val)); \
39 OSMO_ASSERT((val) expect_op); \
40 } while (0);
41
42const char *vec_str(const struct osmo_auth_vector *vec)
43{
44 static char buf[1024];
45 char *pos = buf;
46 char *end = buf + sizeof(buf);
47
48#define append(what) \
49 if (pos >= end) \
50 return buf; \
51 pos += snprintf(pos, sizeof(buf) - (pos - buf), \
52 " " #what ": %s\n", \
53 osmo_hexdump_nospc((void*)&vec->what, sizeof(vec->what)))
54
55 append(rand);
56 append(autn);
57 append(ck);
58 append(ik);
59 append(res);
60 append(res_len);
61 append(kc);
62 append(sres);
63 append(auth_types);
64#undef append
65
66 return buf;
67}
68
69#define VEC_IS(vec, expect) do { \
70 const char *_is = vec_str(vec); \
71 fprintf(stderr, "auth vector ==\n%s\n", _is); \
72 if (strcmp(_is, expect)) { \
73 fprintf(stderr, "MISMATCH! expected ==\n%s\n", \
74 expect); \
75 char *a = _is; \
76 char *b = expect; \
77 for (; *a && *b; a++, b++) { \
78 if (*a != *b) { \
79 while (a > _is && *(a-1) != '\n') a--; \
80 fprintf(stderr, "mismatch at %d:\n" \
81 "%s", a - _is, a); \
82 break; \
83 } \
84 } \
85 OSMO_ASSERT(false); \
86 } \
87 } while (0)
88
Neels Hofmeyr00c06972017-01-31 01:19:27 +010089uint8_t fake_rand[16] = { 0 };
90
91int rand_get(uint8_t *rand, unsigned int len)
92{
93 OSMO_ASSERT(len <= sizeof(fake_rand));
94 memcpy(rand, fake_rand, len);
95 return len;
96}
97
Neels Hofmeyr8cde6622017-01-31 02:10:40 +010098static void test_gen_vectors_2g_only(void)
99{
100 struct osmo_sub_auth_data aud2g;
101 struct osmo_sub_auth_data aud3g;
102 struct osmo_auth_vector vec;
103 int rc;
104
105 comment_start();
106
107 aud2g = (struct osmo_sub_auth_data){
108 .type = OSMO_AUTH_TYPE_GSM,
109 .algo = OSMO_AUTH_ALG_COMP128v1,
110 };
111
112 osmo_hexparse("EB215756028D60E3275E613320AEC880",
113 aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki));
114
115 aud3g = (struct osmo_sub_auth_data){ {0} };
116
117 osmo_hexparse("39fa2f4e3d523d8619a73b4f65c3e14d",
118 fake_rand, sizeof(fake_rand));
119
120 vec = (struct osmo_auth_vector){ {0} };
121 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%d");
122 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
123 VERBOSE_ASSERT(rc, == 1, "%d");
124
125 VEC_IS(&vec,
126 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
127 " autn: 00000000000000000000000000000000\n"
128 " ck: 00000000000000000000000000000000\n"
129 " ik: 00000000000000000000000000000000\n"
130 " res: 00000000000000000000000000000000\n"
131 " res_len: 00\n"
132 " kc: 241a5b16aeb8e400\n"
133 " sres: 429d5b27\n"
134 " auth_types: 01000000\n"
135 );
136
137 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%d");
138
139 /* even though vec is not zero-initialized, it should produce the same
140 * result (regardless of the umts sequence nr) */
141 aud3g.u.umts.sqn = 123;
142 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
143 VERBOSE_ASSERT(rc, == 1, "%d");
144
145 VEC_IS(&vec,
146 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
147 " autn: 00000000000000000000000000000000\n"
148 " ck: 00000000000000000000000000000000\n"
149 " ik: 00000000000000000000000000000000\n"
150 " res: 00000000000000000000000000000000\n"
151 " res_len: 00\n"
152 " kc: 241a5b16aeb8e400\n"
153 " sres: 429d5b27\n"
154 " auth_types: 01000000\n"
155 );
156
157 comment_end();
158}
159
160static void test_gen_vectors_2g_plus_3g(void)
161{
162 struct osmo_sub_auth_data aud2g;
163 struct osmo_sub_auth_data aud3g;
164 struct osmo_auth_vector vec;
165 int rc;
166
167 comment_start();
168
169 aud2g = (struct osmo_sub_auth_data){
170 .type = OSMO_AUTH_TYPE_GSM,
171 .algo = OSMO_AUTH_ALG_COMP128v1,
172 };
173
174 osmo_hexparse("EB215756028D60E3275E613320AEC880",
175 aud2g.u.gsm.ki, sizeof(aud2g.u.gsm.ki));
176
177 aud3g = (struct osmo_sub_auth_data){
178 .type = OSMO_AUTH_TYPE_UMTS,
179 .algo = OSMO_AUTH_ALG_MILENAGE,
180 };
181
182 osmo_hexparse("EB215756028D60E3275E613320AEC880",
183 aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
184 osmo_hexparse("FB2A3D1B360F599ABAB99DB8669F8308",
185 aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
186
187 osmo_hexparse("39fa2f4e3d523d8619a73b4f65c3e14d",
188 fake_rand, sizeof(fake_rand));
189
190 vec = (struct osmo_auth_vector){ {0} };
191 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%d");
192 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
193 VERBOSE_ASSERT(rc, == 1, "%d");
194
195 VEC_IS(&vec,
196 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
197 " autn: 8704f5ba55f30000d2ee44b22c8ea919\n"
198 " ck: f64735036e5871319c679f4742a75ea1\n"
199 " ik: 27497388b6cb044648f396aa155b95ef\n"
200 " res: e229c19e791f2e410000000000000000\n"
201 " res_len: 08\n"
202 " kc: 241a5b16aeb8e400\n"
203 " sres: 429d5b27\n"
204 " auth_types: 03000000\n"
205 );
206
207 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 1, "%d");
208
209 /* even though vec is not zero-initialized, it should produce the same
210 * result with the same sequence nr */
211 aud3g.u.umts.sqn = 0;
212 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%d");
213 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
214 VERBOSE_ASSERT(rc, == 1, "%d");
215 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 1, "%d");
216
217 VEC_IS(&vec,
218 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
219 " autn: 8704f5ba55f30000d2ee44b22c8ea919\n"
220 " ck: f64735036e5871319c679f4742a75ea1\n"
221 " ik: 27497388b6cb044648f396aa155b95ef\n"
222 " res: e229c19e791f2e410000000000000000\n"
223 " res_len: 08\n"
224 " kc: 241a5b16aeb8e400\n"
225 " sres: 429d5b27\n"
226 " auth_types: 03000000\n"
227 );
228
229 comment_end();
230}
231
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100232static void test_gen_vectors_3g_only(void)
233{
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100234 struct osmo_sub_auth_data aud2g;
235 struct osmo_sub_auth_data aud3g;
236 struct osmo_auth_vector vec;
237 int rc;
238
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100239 comment_start();
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100240
241 aud2g = (struct osmo_sub_auth_data){ 0 };
242
243 aud3g = (struct osmo_sub_auth_data){
244 .type = OSMO_AUTH_TYPE_UMTS,
245 .algo = OSMO_AUTH_ALG_MILENAGE,
246 };
247
248 osmo_hexparse("EB215756028D60E3275E613320AEC880",
249 aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
250 osmo_hexparse("FB2A3D1B360F599ABAB99DB8669F8308",
251 aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
252
253 osmo_hexparse("39fa2f4e3d523d8619a73b4f65c3e14d",
254 fake_rand, sizeof(fake_rand));
255
256 vec = (struct osmo_auth_vector){ {0} };
257 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%d");
258 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
259 VERBOSE_ASSERT(rc, == 1, "%d");
260
261 VEC_IS(&vec,
262 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
263 " autn: 8704f5ba55f30000d2ee44b22c8ea919\n"
264 " ck: f64735036e5871319c679f4742a75ea1\n"
265 " ik: 27497388b6cb044648f396aa155b95ef\n"
266 " res: e229c19e791f2e410000000000000000\n"
267 " res_len: 08\n"
268 " kc: 059a4f668f6fbe39\n"
269 " sres: 9b36efdf\n"
270 " auth_types: 03000000\n"
271 );
272
273 /* Note: 3GPP TS 33.102 6.8.1.2: c3 function to get GSM auth is
274 * KC[0..7] == CK[0..7] ^ CK[8..15] ^ IK[0..7] ^ IK[8..15]
275 * In [16]: hex( 0xf64735036e587131
276 * ^ 0x9c679f4742a75ea1
277 * ^ 0x27497388b6cb0446
278 * ^ 0x48f396aa155b95ef)
279 * Out[16]: '0x59a4f668f6fbe39L'
280 * hence expecting kc: 059a4f668f6fbe39
281 */
282
283 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 1, "%d");
284
285 /* even though vec is not zero-initialized, it should produce the same
286 * result with the same sequence nr */
287 aud3g.u.umts.sqn = 0;
288 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%d");
289 rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
290 VERBOSE_ASSERT(rc, == 1, "%d");
291 VERBOSE_ASSERT(aud3g.u.umts.sqn, == 1, "%d");
292
293 VEC_IS(&vec,
294 " rand: 39fa2f4e3d523d8619a73b4f65c3e14d\n"
295 " autn: 8704f5ba55f30000d2ee44b22c8ea919\n"
296 " ck: f64735036e5871319c679f4742a75ea1\n"
297 " ik: 27497388b6cb044648f396aa155b95ef\n"
298 " res: e229c19e791f2e410000000000000000\n"
299 " res_len: 08\n"
300 " kc: 059a4f668f6fbe39\n"
301 " sres: 9b36efdf\n"
302 " auth_types: 03000000\n"
303 );
304
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100305 comment_end();
306}
307
308int main()
309{
310 printf("auc_3g_test.c\n");
311 osmo_init_logging(&hlr_log_info);
312 log_set_print_filename(osmo_stderr_target, 0);
313 log_set_print_timestamp(osmo_stderr_target, 0);
314 log_set_use_color(osmo_stderr_target, 0);
315 log_set_print_category(osmo_stderr_target, 1);
316
Neels Hofmeyr8cde6622017-01-31 02:10:40 +0100317 test_gen_vectors_2g_only();
318 test_gen_vectors_2g_plus_3g();
Neels Hofmeyr00c06972017-01-31 01:19:27 +0100319 test_gen_vectors_3g_only();
320
321 printf("Done\n");
322 return 0;
323}