blob: e3502b2c8eefdc046f9285afdf564fecb2c77311 [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>
28#include <getopt.h>
29
30#include <osmocom/crypt/auth.h>
31#include <osmocom/core/utils.h>
32
33static void dump_auth_vec(struct osmo_auth_vector *vec)
34{
35 printf("RAND:\t%s\n", osmo_hexdump(vec->rand, sizeof(vec->rand)));
36
37 if (vec->auth_types & OSMO_AUTH_TYPE_UMTS) {
38 printf("AUTN:\t%s\n", osmo_hexdump(vec->autn, sizeof(vec->autn)));
39 printf("IK:\t%s\n", osmo_hexdump(vec->ik, sizeof(vec->ik)));
40 printf("CK:\t%s\n", osmo_hexdump(vec->ck, sizeof(vec->ck)));
41 printf("RES:\t%s\n", osmo_hexdump(vec->res, vec->res_len));
42 }
43
44 if (vec->auth_types & OSMO_AUTH_TYPE_GSM) {
45 printf("SRES:\t%s\n", osmo_hexdump(vec->sres, sizeof(vec->sres)));
46 printf("Kc:\t%s\n", osmo_hexdump(vec->kc, sizeof(vec->kc)));
47 }
48}
49
50static struct osmo_sub_auth_data test_aud = {
51 .type = OSMO_AUTH_TYPE_NONE,
52 .algo = OSMO_AUTH_ALG_NONE,
53};
54
Harald Welte5fb795e2012-03-21 08:51:48 +010055static void help()
56{
57 printf( "-2 --2g\tUse 2G (GSM) authentication\n"
58 "-3 --3g\tUse 3G (UMTS) authentication\n"
59 "-a --algorithm\tSpecify name of the algorithm\n"
60 "-k --key\tSpecify Ki / K\n"
61 "-o --opc\tSpecify OPC (only for 3G)\n"
Harald Weltea72e47b2012-03-21 09:03:16 +010062 "-O --op\tSpecify OP (only for 3G)\n"
Harald Welte5fb795e2012-03-21 08:51:48 +010063 "-a --amf\tSpecify AMF (only for 3G)\n"
64 "-s --sqn\tSpecify SQN (only for 3G)\n"
Harald Weltecebf3f02012-03-22 16:45:23 +010065 "-A --auts\tSpecify AUTS (only for 3G)\n"
Harald Welte5fb795e2012-03-21 08:51:48 +010066 "-r --rand\tSpecify random value\n");
67}
68
Harald Welte915e0ef2011-12-07 02:38:42 +010069int main(int argc, char **argv)
70{
71 struct osmo_auth_vector _vec;
72 struct osmo_auth_vector *vec = &_vec;
Harald Weltecebf3f02012-03-22 16:45:23 +010073 uint8_t _rand[16], _auts[16];
Harald Welte915e0ef2011-12-07 02:38:42 +010074 int rc, option_index;
75 int rand_is_set = 0;
Harald Weltecebf3f02012-03-22 16:45:23 +010076 int auts_is_set = 0;
Harald Welte915e0ef2011-12-07 02:38:42 +010077
Harald Weltebc6f56c2012-03-21 17:37:53 +010078 printf("osmo-auc-gen (C) 2011-2012 by Harald Welte\n");
Harald Welte915e0ef2011-12-07 02:38:42 +010079 printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
80
Harald Weltecebf3f02012-03-22 16:45:23 +010081 memset(_auts, 0, sizeof(_auts));
82
Harald Welte915e0ef2011-12-07 02:38:42 +010083 while (1) {
84 int c;
85 unsigned long ul;
86 static struct option long_options[] = {
87 { "2g", 0, 0, '2' },
88 { "3g", 0, 0, '3' },
89 { "algorithm", 1, 0, 'a' },
90 { "key", 1, 0, 'k' },
91 { "opc", 1, 0, 'o' },
Harald Weltea72e47b2012-03-21 09:03:16 +010092 { "op", 1, 0, 'O' },
Harald Welte915e0ef2011-12-07 02:38:42 +010093 { "amf", 1, 0, 'f' },
94 { "sqn", 1, 0, 's' },
95 { "rand", 1, 0, 'r' },
Harald Weltecebf3f02012-03-22 16:45:23 +010096 { "auts", 1, 0, 'A' },
Harald Welte5fb795e2012-03-21 08:51:48 +010097 { "help", 0, 0, 'h' },
Harald Welte915e0ef2011-12-07 02:38:42 +010098 { 0, 0, 0, 0 }
99 };
100
101 rc = 0;
102
Harald Weltecebf3f02012-03-22 16:45:23 +0100103 c = getopt_long(argc, argv, "23a:k:o:f:s:r:hO:A:", long_options,
Harald Welte915e0ef2011-12-07 02:38:42 +0100104 &option_index);
105
106 if (c == -1)
107 break;
108
109 switch (c) {
110 case '2':
111 test_aud.type = OSMO_AUTH_TYPE_GSM;
112 break;
113 case '3':
114 test_aud.type = OSMO_AUTH_TYPE_UMTS;
115 break;
116 case 'a':
117 rc = osmo_auth_alg_parse(optarg);
118 if (rc < 0)
119 break;
120 test_aud.algo = rc;
121 break;
122 case 'k':
123 switch (test_aud.type) {
124 case OSMO_AUTH_TYPE_GSM:
Harald Welteaae23622011-12-07 11:35:02 +0100125 rc = osmo_hexparse(optarg, test_aud.u.gsm.ki,
126 sizeof(test_aud.u.gsm.ki));
Harald Welte915e0ef2011-12-07 02:38:42 +0100127 break;
128 case OSMO_AUTH_TYPE_UMTS:
Harald Welteaae23622011-12-07 11:35:02 +0100129 rc = osmo_hexparse(optarg, test_aud.u.umts.k,
130 sizeof(test_aud.u.umts.k));
Harald Welte915e0ef2011-12-07 02:38:42 +0100131 break;
132 default:
133 fprintf(stderr, "please specify 2g/3g first!\n");
134 }
135 break;
136 case 'o':
137 if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
138 fprintf(stderr, "Only UMTS has OPC\n");
139 exit(2);
140 }
Harald Welteaae23622011-12-07 11:35:02 +0100141 rc = osmo_hexparse(optarg, test_aud.u.umts.opc,
142 sizeof(test_aud.u.umts.opc));
Harald Weltea72e47b2012-03-21 09:03:16 +0100143 test_aud.u.umts.opc_is_op = 0;
144 break;
145 case 'O':
146 if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
147 fprintf(stderr, "Only UMTS has OP\n");
148 exit(2);
149 }
150 rc = osmo_hexparse(optarg, test_aud.u.umts.opc,
151 sizeof(test_aud.u.umts.opc));
152 test_aud.u.umts.opc_is_op = 1;
Harald Welte915e0ef2011-12-07 02:38:42 +0100153 break;
Harald Weltecebf3f02012-03-22 16:45:23 +0100154 case 'A':
155 if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
156 fprintf(stderr, "Only UMTS has AUTS\n");
157 exit(2);
158 }
159 rc = osmo_hexparse(optarg, _auts, sizeof(_auts));
160 auts_is_set = 1;
161 break;
Harald Welte915e0ef2011-12-07 02:38:42 +0100162 case 'f':
163 if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
164 fprintf(stderr, "Only UMTS has AMF\n");
165 exit(2);
166 }
Harald Welteaae23622011-12-07 11:35:02 +0100167 rc = osmo_hexparse(optarg, test_aud.u.umts.amf,
168 sizeof(test_aud.u.umts.amf));
Harald Welte915e0ef2011-12-07 02:38:42 +0100169 break;
170 case 's':
171 if (test_aud.type != OSMO_AUTH_TYPE_UMTS) {
172 fprintf(stderr, "Only UMTS has SQN\n");
173 exit(2);
174 }
175 ul = strtoul(optarg, 0, 10);
Harald Welteaae23622011-12-07 11:35:02 +0100176 test_aud.u.umts.sqn = ul;
Harald Welte915e0ef2011-12-07 02:38:42 +0100177 break;
178 case 'r':
179 rc = osmo_hexparse(optarg, _rand, sizeof(_rand));
180 rand_is_set = 1;
181 break;
Harald Welte5fb795e2012-03-21 08:51:48 +0100182 case 'h':
183 help();
184 exit(0);
185 default:
186 help();
187 exit(1);
Harald Welte915e0ef2011-12-07 02:38:42 +0100188 }
189
190 if (rc < 0) {
191 fprintf(stderr, "Error parsing argument of option `%c'\n", c);
192 exit(2);
193 }
194 }
195
196 if (!rand_is_set) {
197 printf("WARNING: We're using really weak random numbers!\n\n");
198 srand(time(NULL));
199 *(uint32_t *)&_rand[0] = rand();
200 *(uint32_t *)(&_rand[4]) = rand();
201 *(uint32_t *)(&_rand[8]) = rand();
202 *(uint32_t *)(&_rand[12]) = rand();
203 }
204
Harald Welte5fb795e2012-03-21 08:51:48 +0100205 if (test_aud.type == OSMO_AUTH_TYPE_NONE ||
206 test_aud.algo == OSMO_AUTH_ALG_NONE) {
207 help();
208 exit(2);
209 }
210
Harald Welte915e0ef2011-12-07 02:38:42 +0100211 memset(vec, 0, sizeof(*vec));
212
Harald Weltecebf3f02012-03-22 16:45:23 +0100213 if (!auts_is_set)
214 rc = osmo_auth_gen_vec(vec, &test_aud, _rand);
215 else
216 rc = osmo_auth_gen_vec_auts(vec, &test_aud, _auts, _rand, _rand);
Harald Welte915e0ef2011-12-07 02:38:42 +0100217 if (rc < 0) {
Harald Weltecebf3f02012-03-22 16:45:23 +0100218 if (!auts_is_set)
219 fprintf(stderr, "error generating auth vector\n");
220 else
221 fprintf(stderr, "AUTS from MS seems incorrect\n");
Harald Welte915e0ef2011-12-07 02:38:42 +0100222 exit(1);
223 }
224
225 dump_auth_vec(vec);
Harald Welte915e0ef2011-12-07 02:38:42 +0100226
Harald Weltecebf3f02012-03-22 16:45:23 +0100227 if (auts_is_set)
Harald Welteaae23622011-12-07 11:35:02 +0100228 printf("AUTS success: SEQ.MS = %lu\n", test_aud.u.umts.sqn);
Harald Welte915e0ef2011-12-07 02:38:42 +0100229
Harald Weltecebf3f02012-03-22 16:45:23 +0100230 exit(0);
Harald Welte915e0ef2011-12-07 02:38:42 +0100231}