blob: 6fa7cec77122cf6c6639f4bbfe4b4401071df11c [file] [log] [blame]
Harald Welte915e0ef2011-12-07 02:38:42 +01001/* GSM/GPRS/3G authentication testing tool */
2
Harald Weltebc6f56c2012-03-21 17:37:53 +01003/* (C) 2010-2012 by Harald Welte <laforge@gnumonks.org>
Harald Welte915e0ef2011-12-07 02:38:42 +01004 *
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <errno.h>
27#include <string.h>
Jan Engelhardta6d83932013-06-03 01:38:57 +020028#include <time.h>
Harald Welte915e0ef2011-12-07 02:38:42 +010029#include <getopt.h>
Harald Welteb53717f2012-08-02 08:42:59 +020030#include <unistd.h>
Holger Hans Peter Freythera652abc2013-07-14 09:11:47 +020031#include <inttypes.h>
32#include <time.h>
Harald Welte915e0ef2011-12-07 02:38:42 +010033
34#include <osmocom/crypt/auth.h>
35#include <osmocom/core/utils.h>
36
Harald Welte57799ed2012-06-27 15:06:19 +020037static void dump_triplets_dat(struct osmo_auth_vector *vec)
38{
39 if (vec->auth_types & OSMO_AUTH_TYPE_UMTS) {
40 fprintf(stderr, "triplets.dat doesn't support UMTS!\n");
41 return;
42 }
43 printf("imsi,");
44 printf("%s,", osmo_hexdump_nospc(vec->rand, sizeof(vec->rand)));
45 printf("%s,", osmo_hexdump_nospc(vec->sres, sizeof(vec->sres)));
46 printf("%s\n", osmo_hexdump_nospc(vec->kc, sizeof(vec->kc)));
47}
48
Harald Welte915e0ef2011-12-07 02:38:42 +010049static void dump_auth_vec(struct osmo_auth_vector *vec)
50{
Harald Welte4f511b62016-05-18 19:36:42 +020051 printf("RAND:\t%s\n", osmo_hexdump_nospc(vec->rand, sizeof(vec->rand)));
Harald Welte915e0ef2011-12-07 02:38:42 +010052
53 if (vec->auth_types & OSMO_AUTH_TYPE_UMTS) {
Harald Welte4f511b62016-05-18 19:36:42 +020054 printf("AUTN:\t%s\n", osmo_hexdump_nospc(vec->autn, sizeof(vec->autn)));
55 printf("IK:\t%s\n", osmo_hexdump_nospc(vec->ik, sizeof(vec->ik)));
56 printf("CK:\t%s\n", osmo_hexdump_nospc(vec->ck, sizeof(vec->ck)));
57 printf("RES:\t%s\n", osmo_hexdump_nospc(vec->res, vec->res_len));
Harald Welte915e0ef2011-12-07 02:38:42 +010058 }
59
60 if (vec->auth_types & OSMO_AUTH_TYPE_GSM) {
Harald Welte4f511b62016-05-18 19:36:42 +020061 printf("SRES:\t%s\n", osmo_hexdump_nospc(vec->sres, sizeof(vec->sres)));
62 printf("Kc:\t%s\n", osmo_hexdump_nospc(vec->kc, sizeof(vec->kc)));
Harald Welte915e0ef2011-12-07 02:38:42 +010063 }
64}
65
66static struct osmo_sub_auth_data test_aud = {
67 .type = OSMO_AUTH_TYPE_NONE,
68 .algo = OSMO_AUTH_ALG_NONE,
69};
70
Harald Welte5fb795e2012-03-21 08:51:48 +010071static void help()
72{
Neels Hofmeyr18d65be2017-02-03 18:36:32 +010073 int alg;
Harald Welte5fb795e2012-03-21 08:51:48 +010074 printf( "-2 --2g\tUse 2G (GSM) authentication\n"
75 "-3 --3g\tUse 3G (UMTS) authentication\n"
76 "-a --algorithm\tSpecify name of the algorithm\n"
77 "-k --key\tSpecify Ki / K\n"
78 "-o --opc\tSpecify OPC (only for 3G)\n"
Harald Weltea72e47b2012-03-21 09:03:16 +010079 "-O --op\tSpecify OP (only for 3G)\n"
Holger Hans Peter Freyther91ff17c2015-05-26 00:11:37 +080080 "-f --amf\tSpecify AMF (only for 3G)\n"
Harald Welte5fb795e2012-03-21 08:51:48 +010081 "-s --sqn\tSpecify SQN (only for 3G)\n"
Harald Weltecebf3f02012-03-22 16:45:23 +010082 "-A --auts\tSpecify AUTS (only for 3G)\n"
Harald Welte57799ed2012-06-27 15:06:19 +020083 "-r --rand\tSpecify random value\n"
84 "-I --ipsec\tOutput in triplets.dat format for strongswan\n");
Neels Hofmeyr18d65be2017-02-03 18:36:32 +010085
86 fprintf(stderr, "\nAvailable algorithms for option -a:\n");
87 for (alg = 1; alg < _OSMO_AUTH_ALG_NUM; alg++)
88 fprintf(stderr, " %s\n",
89 osmo_auth_alg_name(alg));
Harald Welte5fb795e2012-03-21 08:51:48 +010090}
91
Harald Welte915e0ef2011-12-07 02:38:42 +010092int main(int argc, char **argv)
93{
94 struct osmo_auth_vector _vec;
95 struct osmo_auth_vector *vec = &_vec;
Neels Hofmeyr8352d312017-02-02 20:05:14 +010096 uint8_t _rand[16], _auts[14];
Harald Welte915e0ef2011-12-07 02:38:42 +010097 int rc, option_index;
98 int rand_is_set = 0;
Harald Weltecebf3f02012-03-22 16:45:23 +010099 int auts_is_set = 0;
Harald Welte57799ed2012-06-27 15:06:19 +0200100 int fmt_triplets_dat = 0;
Harald Welte915e0ef2011-12-07 02:38:42 +0100101
Harald Weltebc6f56c2012-03-21 17:37:53 +0100102 printf("osmo-auc-gen (C) 2011-2012 by Harald Welte\n");
Harald Welte915e0ef2011-12-07 02:38:42 +0100103 printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
104
Harald Weltecebf3f02012-03-22 16:45:23 +0100105 memset(_auts, 0, sizeof(_auts));
106
Harald Welte915e0ef2011-12-07 02:38:42 +0100107 while (1) {
108 int c;
109 unsigned long ul;
110 static struct option long_options[] = {
111 { "2g", 0, 0, '2' },
112 { "3g", 0, 0, '3' },
113 { "algorithm", 1, 0, 'a' },
114 { "key", 1, 0, 'k' },
115 { "opc", 1, 0, 'o' },
Harald Weltea72e47b2012-03-21 09:03:16 +0100116 { "op", 1, 0, 'O' },
Harald Welte915e0ef2011-12-07 02:38:42 +0100117 { "amf", 1, 0, 'f' },
118 { "sqn", 1, 0, 's' },
119 { "rand", 1, 0, 'r' },
Harald Weltecebf3f02012-03-22 16:45:23 +0100120 { "auts", 1, 0, 'A' },
Harald Welte5fb795e2012-03-21 08:51:48 +0100121 { "help", 0, 0, 'h' },
Harald Welte915e0ef2011-12-07 02:38:42 +0100122 { 0, 0, 0, 0 }
123 };
124
125 rc = 0;
126
Harald Welte57799ed2012-06-27 15:06:19 +0200127 c = getopt_long(argc, argv, "23a:k:o:f:s:r:hO:A:I", long_options,
Harald Welte915e0ef2011-12-07 02:38:42 +0100128 &option_index);
129
130 if (c == -1)
131 break;
132
133 switch (c) {
134 case '2':
135 test_aud.type = OSMO_AUTH_TYPE_GSM;
136 break;
137 case '3':
138 test_aud.type = OSMO_AUTH_TYPE_UMTS;
139 break;
140 case 'a':
141 rc = osmo_auth_alg_parse(optarg);
142 if (rc < 0)
143 break;
144 test_aud.algo = rc;
145 break;
146 case 'k':
147 switch (test_aud.type) {
148 case OSMO_AUTH_TYPE_GSM:
Harald Welteaae23622011-12-07 11:35:02 +0100149 rc = osmo_hexparse(optarg, test_aud.u.gsm.ki,
150 sizeof(test_aud.u.gsm.ki));
Harald Welte915e0ef2011-12-07 02:38:42 +0100151 break;
152 case OSMO_AUTH_TYPE_UMTS:
Harald Welteaae23622011-12-07 11:35:02 +0100153 rc = osmo_hexparse(optarg, test_aud.u.umts.k,
154 sizeof(test_aud.u.umts.k));
Harald Welte915e0ef2011-12-07 02:38:42 +0100155 break;
156 default:
157 fprintf(stderr, "please specify 2g/3g first!\n");
158 }
159 break;
160 case 'o':
161 if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
162 fprintf(stderr, "Only UMTS has OPC\n");
163 exit(2);
164 }
Harald Welteaae23622011-12-07 11:35:02 +0100165 rc = osmo_hexparse(optarg, test_aud.u.umts.opc,
166 sizeof(test_aud.u.umts.opc));
Harald Weltea72e47b2012-03-21 09:03:16 +0100167 test_aud.u.umts.opc_is_op = 0;
168 break;
169 case 'O':
170 if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
171 fprintf(stderr, "Only UMTS has OP\n");
172 exit(2);
173 }
174 rc = osmo_hexparse(optarg, test_aud.u.umts.opc,
175 sizeof(test_aud.u.umts.opc));
176 test_aud.u.umts.opc_is_op = 1;
Harald Welte915e0ef2011-12-07 02:38:42 +0100177 break;
Harald Weltecebf3f02012-03-22 16:45:23 +0100178 case 'A':
179 if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
180 fprintf(stderr, "Only UMTS has AUTS\n");
181 exit(2);
182 }
183 rc = osmo_hexparse(optarg, _auts, sizeof(_auts));
184 auts_is_set = 1;
185 break;
Harald Welte915e0ef2011-12-07 02:38:42 +0100186 case 'f':
187 if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
188 fprintf(stderr, "Only UMTS has AMF\n");
189 exit(2);
190 }
Harald Welteaae23622011-12-07 11:35:02 +0100191 rc = osmo_hexparse(optarg, test_aud.u.umts.amf,
192 sizeof(test_aud.u.umts.amf));
Harald Welte915e0ef2011-12-07 02:38:42 +0100193 break;
194 case 's':
195 if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
196 fprintf(stderr, "Only UMTS has SQN\n");
197 exit(2);
198 }
199 ul = strtoul(optarg, 0, 10);
Harald Welteaae23622011-12-07 11:35:02 +0100200 test_aud.u.umts.sqn = ul;
Harald Welte915e0ef2011-12-07 02:38:42 +0100201 break;
202 case 'r':
203 rc = osmo_hexparse(optarg, _rand, sizeof(_rand));
204 rand_is_set = 1;
205 break;
Harald Welte57799ed2012-06-27 15:06:19 +0200206 case 'I':
207 fmt_triplets_dat = 1;
208 break;
Harald Welte5fb795e2012-03-21 08:51:48 +0100209 case 'h':
210 help();
211 exit(0);
212 default:
213 help();
214 exit(1);
Harald Welte915e0ef2011-12-07 02:38:42 +0100215 }
216
217 if (rc < 0) {
Neels Hofmeyr18d65be2017-02-03 18:36:32 +0100218 help();
219 fprintf(stderr, "\nError parsing argument of option `%c'\n", c);
Harald Welte915e0ef2011-12-07 02:38:42 +0100220 exit(2);
221 }
222 }
223
224 if (!rand_is_set) {
Holger Hans Peter Freyther17aa6b22014-06-22 16:53:55 +0200225 int i;
Harald Welte915e0ef2011-12-07 02:38:42 +0100226 printf("WARNING: We're using really weak random numbers!\n\n");
227 srand(time(NULL));
Holger Hans Peter Freyther17aa6b22014-06-22 16:53:55 +0200228
229 for (i = 0; i < 4; ++i) {
230 uint32_t r;
231 r = rand();
232 memcpy(&_rand[i*4], &r, 4);
233 }
Harald Welte915e0ef2011-12-07 02:38:42 +0100234 }
235
Harald Welte5fb795e2012-03-21 08:51:48 +0100236 if (test_aud.type == OSMO_AUTH_TYPE_NONE ||
237 test_aud.algo == OSMO_AUTH_ALG_NONE) {
238 help();
Neels Hofmeyr18d65be2017-02-03 18:36:32 +0100239 fprintf(stderr, "\nError: you need to pass at least"
240 " -2 or -3, as well as an algorithm to use.\n");
Harald Welte5fb795e2012-03-21 08:51:48 +0100241 exit(2);
242 }
243
Harald Welte915e0ef2011-12-07 02:38:42 +0100244 memset(vec, 0, sizeof(*vec));
245
Harald Weltecebf3f02012-03-22 16:45:23 +0100246 if (!auts_is_set)
247 rc = osmo_auth_gen_vec(vec, &test_aud, _rand);
248 else
249 rc = osmo_auth_gen_vec_auts(vec, &test_aud, _auts, _rand, _rand);
Harald Welte915e0ef2011-12-07 02:38:42 +0100250 if (rc < 0) {
Harald Weltecebf3f02012-03-22 16:45:23 +0100251 if (!auts_is_set)
252 fprintf(stderr, "error generating auth vector\n");
253 else
254 fprintf(stderr, "AUTS from MS seems incorrect\n");
Harald Welte915e0ef2011-12-07 02:38:42 +0100255 exit(1);
256 }
257
Harald Welte57799ed2012-06-27 15:06:19 +0200258 if (fmt_triplets_dat)
259 dump_triplets_dat(vec);
Neels Hofmeyr5fe3d1b2017-03-15 01:16:43 +0100260 else {
Harald Welte57799ed2012-06-27 15:06:19 +0200261 dump_auth_vec(vec);
Neels Hofmeyr5fe3d1b2017-03-15 01:16:43 +0100262 if (test_aud.type == OSMO_AUTH_TYPE_UMTS)
263 /* After generating, SQN is incremented, so -1 */
264 printf("SQN:\t%" PRIu64 "\n", test_aud.u.umts.sqn - 1);
265 }
Harald Welte915e0ef2011-12-07 02:38:42 +0100266
Neels Hofmeyr5fe3d1b2017-03-15 01:16:43 +0100267 /* After recovering SQN.MS from AUTS, milenage_gen_vec_auts() does
268 * aud->u.umts.sqn++, and after vector generation milenage_gen_vec()
269 * does another ++, so to show SQN.MS we need to -2 */
Harald Weltecebf3f02012-03-22 16:45:23 +0100270 if (auts_is_set)
Neels Hofmeyr5fe3d1b2017-03-15 01:16:43 +0100271 printf("AUTS success: SQN.MS = %" PRIu64 "\n",
272 test_aud.u.umts.sqn - 2);
Harald Welte915e0ef2011-12-07 02:38:42 +0100273
Harald Weltecebf3f02012-03-22 16:45:23 +0100274 exit(0);
Harald Welte915e0ef2011-12-07 02:38:42 +0100275}