blob: 6e38b5202fa11cb59648315a51d22f9f1c0764af [file] [log] [blame]
Neels Hofmeyr17518fe2017-06-20 04:35:06 +02001/*! \file osmo-auc-gen.c
2 * GSM/GPRS/3G authentication testing tool. */
3/*
4 * (C) 2010-2012 by Harald Welte <laforge@gnumonks.org>
Harald Welte915e0ef2011-12-07 02:38:42 +01005 *
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 */
23
24
25#include <stdlib.h>
26#include <stdio.h>
27#include <errno.h>
28#include <string.h>
Jan Engelhardta6d83932013-06-03 01:38:57 +020029#include <time.h>
Harald Welte915e0ef2011-12-07 02:38:42 +010030#include <getopt.h>
Harald Welteb53717f2012-08-02 08:42:59 +020031#include <unistd.h>
Holger Hans Peter Freythera652abc2013-07-14 09:11:47 +020032#include <inttypes.h>
33#include <time.h>
Harald Welte915e0ef2011-12-07 02:38:42 +010034
35#include <osmocom/crypt/auth.h>
36#include <osmocom/core/utils.h>
37
Harald Welte57799ed2012-06-27 15:06:19 +020038static void dump_triplets_dat(struct osmo_auth_vector *vec)
39{
40 if (vec->auth_types & OSMO_AUTH_TYPE_UMTS) {
41 fprintf(stderr, "triplets.dat doesn't support UMTS!\n");
42 return;
43 }
44 printf("imsi,");
45 printf("%s,", osmo_hexdump_nospc(vec->rand, sizeof(vec->rand)));
46 printf("%s,", osmo_hexdump_nospc(vec->sres, sizeof(vec->sres)));
47 printf("%s\n", osmo_hexdump_nospc(vec->kc, sizeof(vec->kc)));
48}
49
Harald Welte915e0ef2011-12-07 02:38:42 +010050static void dump_auth_vec(struct osmo_auth_vector *vec)
51{
Harald Welte4f511b62016-05-18 19:36:42 +020052 printf("RAND:\t%s\n", osmo_hexdump_nospc(vec->rand, sizeof(vec->rand)));
Harald Welte915e0ef2011-12-07 02:38:42 +010053
54 if (vec->auth_types & OSMO_AUTH_TYPE_UMTS) {
Harald Welte4f511b62016-05-18 19:36:42 +020055 printf("AUTN:\t%s\n", osmo_hexdump_nospc(vec->autn, sizeof(vec->autn)));
56 printf("IK:\t%s\n", osmo_hexdump_nospc(vec->ik, sizeof(vec->ik)));
57 printf("CK:\t%s\n", osmo_hexdump_nospc(vec->ck, sizeof(vec->ck)));
58 printf("RES:\t%s\n", osmo_hexdump_nospc(vec->res, vec->res_len));
Harald Welte915e0ef2011-12-07 02:38:42 +010059 }
60
61 if (vec->auth_types & OSMO_AUTH_TYPE_GSM) {
Harald Welte4f511b62016-05-18 19:36:42 +020062 printf("SRES:\t%s\n", osmo_hexdump_nospc(vec->sres, sizeof(vec->sres)));
63 printf("Kc:\t%s\n", osmo_hexdump_nospc(vec->kc, sizeof(vec->kc)));
Harald Welte915e0ef2011-12-07 02:38:42 +010064 }
65}
66
67static struct osmo_sub_auth_data test_aud = {
68 .type = OSMO_AUTH_TYPE_NONE,
69 .algo = OSMO_AUTH_ALG_NONE,
70};
71
Harald Welte5fb795e2012-03-21 08:51:48 +010072static void help()
73{
Neels Hofmeyr18d65be2017-02-03 18:36:32 +010074 int alg;
Harald Welte5fb795e2012-03-21 08:51:48 +010075 printf( "-2 --2g\tUse 2G (GSM) authentication\n"
76 "-3 --3g\tUse 3G (UMTS) authentication\n"
77 "-a --algorithm\tSpecify name of the algorithm\n"
78 "-k --key\tSpecify Ki / K\n"
79 "-o --opc\tSpecify OPC (only for 3G)\n"
Harald Weltea72e47b2012-03-21 09:03:16 +010080 "-O --op\tSpecify OP (only for 3G)\n"
Holger Hans Peter Freyther91ff17c2015-05-26 00:11:37 +080081 "-f --amf\tSpecify AMF (only for 3G)\n"
Harald Welte5fb795e2012-03-21 08:51:48 +010082 "-s --sqn\tSpecify SQN (only for 3G)\n"
Neels Hofmeyr3cb08272017-08-26 21:45:33 +020083 "-i --ind\tSpecify IND slot for new SQN after AUTS (only for 3G)\n"
Neels Hofmeyrb1af6ef2017-08-26 21:38:51 +020084 "-l --ind-len\tSpecify IND bit length (default=5) (only for 3G)\n"
Harald Weltecebf3f02012-03-22 16:45:23 +010085 "-A --auts\tSpecify AUTS (only for 3G)\n"
Harald Welte57799ed2012-06-27 15:06:19 +020086 "-r --rand\tSpecify random value\n"
87 "-I --ipsec\tOutput in triplets.dat format for strongswan\n");
Neels Hofmeyr18d65be2017-02-03 18:36:32 +010088
89 fprintf(stderr, "\nAvailable algorithms for option -a:\n");
90 for (alg = 1; alg < _OSMO_AUTH_ALG_NUM; alg++)
91 fprintf(stderr, " %s\n",
92 osmo_auth_alg_name(alg));
Harald Welte5fb795e2012-03-21 08:51:48 +010093}
94
Harald Welte915e0ef2011-12-07 02:38:42 +010095int main(int argc, char **argv)
96{
97 struct osmo_auth_vector _vec;
98 struct osmo_auth_vector *vec = &_vec;
Neels Hofmeyr8352d312017-02-02 20:05:14 +010099 uint8_t _rand[16], _auts[14];
Neels Hofmeyrd157bbb2017-08-26 22:08:36 +0200100 uint64_t sqn;
Neels Hofmeyr3cb08272017-08-26 21:45:33 +0200101 unsigned int ind;
Harald Welte915e0ef2011-12-07 02:38:42 +0100102 int rc, option_index;
103 int rand_is_set = 0;
Harald Weltecebf3f02012-03-22 16:45:23 +0100104 int auts_is_set = 0;
Neels Hofmeyrd157bbb2017-08-26 22:08:36 +0200105 int sqn_is_set = 0;
Neels Hofmeyr3cb08272017-08-26 21:45:33 +0200106 int ind_is_set = 0;
Harald Welte57799ed2012-06-27 15:06:19 +0200107 int fmt_triplets_dat = 0;
Harald Welte915e0ef2011-12-07 02:38:42 +0100108
Harald Weltebc6f56c2012-03-21 17:37:53 +0100109 printf("osmo-auc-gen (C) 2011-2012 by Harald Welte\n");
Harald Welte915e0ef2011-12-07 02:38:42 +0100110 printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
111
Harald Weltecebf3f02012-03-22 16:45:23 +0100112 memset(_auts, 0, sizeof(_auts));
113
Harald Welte915e0ef2011-12-07 02:38:42 +0100114 while (1) {
115 int c;
Harald Welte915e0ef2011-12-07 02:38:42 +0100116 static struct option long_options[] = {
117 { "2g", 0, 0, '2' },
118 { "3g", 0, 0, '3' },
119 { "algorithm", 1, 0, 'a' },
120 { "key", 1, 0, 'k' },
121 { "opc", 1, 0, 'o' },
Harald Weltea72e47b2012-03-21 09:03:16 +0100122 { "op", 1, 0, 'O' },
Harald Welte915e0ef2011-12-07 02:38:42 +0100123 { "amf", 1, 0, 'f' },
124 { "sqn", 1, 0, 's' },
Neels Hofmeyr3cb08272017-08-26 21:45:33 +0200125 { "ind", 1, 0, 'i' },
Neels Hofmeyrb1af6ef2017-08-26 21:38:51 +0200126 { "ind-len", 1, 0, 'l' },
Harald Welte915e0ef2011-12-07 02:38:42 +0100127 { "rand", 1, 0, 'r' },
Harald Weltecebf3f02012-03-22 16:45:23 +0100128 { "auts", 1, 0, 'A' },
Harald Welte5fb795e2012-03-21 08:51:48 +0100129 { "help", 0, 0, 'h' },
Harald Welte915e0ef2011-12-07 02:38:42 +0100130 { 0, 0, 0, 0 }
131 };
132
133 rc = 0;
134
Neels Hofmeyrb1af6ef2017-08-26 21:38:51 +0200135 c = getopt_long(argc, argv, "23a:k:o:f:s:i:l:r:hO:A:I", long_options,
Harald Welte915e0ef2011-12-07 02:38:42 +0100136 &option_index);
137
138 if (c == -1)
139 break;
140
141 switch (c) {
142 case '2':
143 test_aud.type = OSMO_AUTH_TYPE_GSM;
144 break;
145 case '3':
146 test_aud.type = OSMO_AUTH_TYPE_UMTS;
Neels Hofmeyr4315e012017-08-26 21:40:11 +0200147 test_aud.u.umts.ind_bitlen = 5;
Harald Welte915e0ef2011-12-07 02:38:42 +0100148 break;
149 case 'a':
150 rc = osmo_auth_alg_parse(optarg);
151 if (rc < 0)
152 break;
153 test_aud.algo = rc;
154 break;
155 case 'k':
156 switch (test_aud.type) {
157 case OSMO_AUTH_TYPE_GSM:
Harald Welteaae23622011-12-07 11:35:02 +0100158 rc = osmo_hexparse(optarg, test_aud.u.gsm.ki,
159 sizeof(test_aud.u.gsm.ki));
Harald Welte915e0ef2011-12-07 02:38:42 +0100160 break;
161 case OSMO_AUTH_TYPE_UMTS:
Harald Welteaae23622011-12-07 11:35:02 +0100162 rc = osmo_hexparse(optarg, test_aud.u.umts.k,
163 sizeof(test_aud.u.umts.k));
Harald Welte915e0ef2011-12-07 02:38:42 +0100164 break;
165 default:
166 fprintf(stderr, "please specify 2g/3g first!\n");
167 }
168 break;
169 case 'o':
170 if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
171 fprintf(stderr, "Only UMTS has OPC\n");
172 exit(2);
173 }
Harald Welteaae23622011-12-07 11:35:02 +0100174 rc = osmo_hexparse(optarg, test_aud.u.umts.opc,
175 sizeof(test_aud.u.umts.opc));
Harald Weltea72e47b2012-03-21 09:03:16 +0100176 test_aud.u.umts.opc_is_op = 0;
177 break;
178 case 'O':
179 if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
180 fprintf(stderr, "Only UMTS has OP\n");
181 exit(2);
182 }
183 rc = osmo_hexparse(optarg, test_aud.u.umts.opc,
184 sizeof(test_aud.u.umts.opc));
185 test_aud.u.umts.opc_is_op = 1;
Harald Welte915e0ef2011-12-07 02:38:42 +0100186 break;
Harald Weltecebf3f02012-03-22 16:45:23 +0100187 case 'A':
188 if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
189 fprintf(stderr, "Only UMTS has AUTS\n");
190 exit(2);
191 }
192 rc = osmo_hexparse(optarg, _auts, sizeof(_auts));
193 auts_is_set = 1;
194 break;
Harald Welte915e0ef2011-12-07 02:38:42 +0100195 case 'f':
196 if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
197 fprintf(stderr, "Only UMTS has AMF\n");
198 exit(2);
199 }
Harald Welteaae23622011-12-07 11:35:02 +0100200 rc = osmo_hexparse(optarg, test_aud.u.umts.amf,
201 sizeof(test_aud.u.umts.amf));
Harald Welte915e0ef2011-12-07 02:38:42 +0100202 break;
203 case 's':
204 if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
205 fprintf(stderr, "Only UMTS has SQN\n");
206 exit(2);
207 }
Neels Hofmeyrd157bbb2017-08-26 22:08:36 +0200208 sqn = strtoull(optarg, 0, 10);
209 sqn_is_set = 1;
Harald Welte915e0ef2011-12-07 02:38:42 +0100210 break;
Neels Hofmeyr3cb08272017-08-26 21:45:33 +0200211 case 'i':
212 if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
213 fprintf(stderr, "Only UMTS has IND\n");
214 exit(2);
215 }
216 ind = atoi(optarg);
217 ind_is_set = 1;
218 break;
Neels Hofmeyrb1af6ef2017-08-26 21:38:51 +0200219 case 'l':
220 if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
221 fprintf(stderr, "Only UMTS has IND bitlen\n");
222 exit(2);
223 }
224 test_aud.u.umts.ind_bitlen = atoi(optarg);
225 break;
Harald Welte915e0ef2011-12-07 02:38:42 +0100226 case 'r':
227 rc = osmo_hexparse(optarg, _rand, sizeof(_rand));
228 rand_is_set = 1;
229 break;
Harald Welte57799ed2012-06-27 15:06:19 +0200230 case 'I':
231 fmt_triplets_dat = 1;
232 break;
Harald Welte5fb795e2012-03-21 08:51:48 +0100233 case 'h':
234 help();
235 exit(0);
236 default:
237 help();
238 exit(1);
Harald Welte915e0ef2011-12-07 02:38:42 +0100239 }
240
241 if (rc < 0) {
Neels Hofmeyr18d65be2017-02-03 18:36:32 +0100242 help();
243 fprintf(stderr, "\nError parsing argument of option `%c'\n", c);
Harald Welte915e0ef2011-12-07 02:38:42 +0100244 exit(2);
245 }
246 }
247
248 if (!rand_is_set) {
Holger Hans Peter Freyther17aa6b22014-06-22 16:53:55 +0200249 int i;
Harald Welte915e0ef2011-12-07 02:38:42 +0100250 printf("WARNING: We're using really weak random numbers!\n\n");
251 srand(time(NULL));
Holger Hans Peter Freyther17aa6b22014-06-22 16:53:55 +0200252
253 for (i = 0; i < 4; ++i) {
254 uint32_t r;
255 r = rand();
256 memcpy(&_rand[i*4], &r, 4);
257 }
Harald Welte915e0ef2011-12-07 02:38:42 +0100258 }
259
Harald Welte5fb795e2012-03-21 08:51:48 +0100260 if (test_aud.type == OSMO_AUTH_TYPE_NONE ||
261 test_aud.algo == OSMO_AUTH_ALG_NONE) {
262 help();
Neels Hofmeyr18d65be2017-02-03 18:36:32 +0100263 fprintf(stderr, "\nError: you need to pass at least"
264 " -2 or -3, as well as an algorithm to use.\n");
Harald Welte5fb795e2012-03-21 08:51:48 +0100265 exit(2);
266 }
267
Harald Welte915e0ef2011-12-07 02:38:42 +0100268 memset(vec, 0, sizeof(*vec));
269
Neels Hofmeyrd157bbb2017-08-26 22:08:36 +0200270 if (test_aud.type == OSMO_AUTH_TYPE_UMTS) {
271 uint64_t seq_1 = 1LL << test_aud.u.umts.ind_bitlen;
272 uint64_t ind_mask = seq_1 - 1;
273
274 if (sqn_is_set) {
275 /* Before calculating the UMTS auth vector, osmo_auth_gen_vec() increments SEQ.
276 * To end up with the SQN passed in by the user, we need to pass in SEQ-1, and
277 * indicate which IND slot to target. */
278 test_aud.u.umts.sqn = sqn - seq_1;
279 test_aud.u.umts.ind = sqn & ind_mask;
280 }
Neels Hofmeyr3cb08272017-08-26 21:45:33 +0200281
282 if (sqn_is_set && ind_is_set) {
283 fprintf(stderr, "Requesting --sqn %"PRIu64" implies IND=%u,"
284 " so no further --ind argument is allowed.\n",
285 sqn, test_aud.u.umts.ind);
286 exit(2);
287 }
288
289 if (ind_is_set) {
290 if (ind >= (1 << test_aud.u.umts.ind_bitlen)) {
291 fprintf(stderr, "Requested --ind %u is too large for IND bitlen of %u\n",
292 ind, test_aud.u.umts.ind_bitlen);
293 exit(2);
294 }
295 test_aud.u.umts.ind = ind;
296 }
Neels Hofmeyrd157bbb2017-08-26 22:08:36 +0200297 }
298
Harald Weltecebf3f02012-03-22 16:45:23 +0100299 if (!auts_is_set)
300 rc = osmo_auth_gen_vec(vec, &test_aud, _rand);
301 else
302 rc = osmo_auth_gen_vec_auts(vec, &test_aud, _auts, _rand, _rand);
Harald Welte915e0ef2011-12-07 02:38:42 +0100303 if (rc < 0) {
Harald Weltecebf3f02012-03-22 16:45:23 +0100304 if (!auts_is_set)
305 fprintf(stderr, "error generating auth vector\n");
306 else
307 fprintf(stderr, "AUTS from MS seems incorrect\n");
Harald Welte915e0ef2011-12-07 02:38:42 +0100308 exit(1);
309 }
310
Harald Welte57799ed2012-06-27 15:06:19 +0200311 if (fmt_triplets_dat)
312 dump_triplets_dat(vec);
Neels Hofmeyr5fe3d1b2017-03-15 01:16:43 +0100313 else {
Harald Welte57799ed2012-06-27 15:06:19 +0200314 dump_auth_vec(vec);
Neels Hofmeyr5fe3d1b2017-03-15 01:16:43 +0100315 if (test_aud.type == OSMO_AUTH_TYPE_UMTS)
Neels Hofmeyr82c9a0e2017-03-13 17:36:17 +0100316 printf("SQN:\t%" PRIu64 "\n", test_aud.u.umts.sqn);
Neels Hofmeyr5fe3d1b2017-03-15 01:16:43 +0100317 }
Harald Welte915e0ef2011-12-07 02:38:42 +0100318
Harald Weltecebf3f02012-03-22 16:45:23 +0100319 exit(0);
Harald Welte915e0ef2011-12-07 02:38:42 +0100320}