blob: c0b8da424e64f3baa2687bc291da93a39011a969 [file] [log] [blame]
Neels Hofmeyr37984bd2016-03-30 11:22:24 +02001#include <stdbool.h>
2
3#include <osmocom/core/application.h>
4#include <osmocom/core/logging.h>
5
6#include <openbsc/debug.h>
7#include <openbsc/gsm_data.h>
8#include <openbsc/gsm_subscriber.h>
9#include <openbsc/auth.h>
10
Neels Hofmeyr4554a622016-03-30 11:22:25 +020011#define min(A,B) ((A)>(B)? (B) : (A))
12
13static char *auth_tuple_str(struct gsm_auth_tuple *atuple)
14{
15 static char buf[256];
16 char *pos = buf;
17 int len = sizeof(buf);
18 int l;
19
20#define print2buf(FMT, args...) do {\
21 l = snprintf(pos, len, FMT, ## args); \
22 pos += l;\
23 len -= l;\
24 } while (0)
25
26 print2buf("gsm_auth_tuple {\n");
27 print2buf(" .use_count = %d\n", atuple->use_count);
28 print2buf(" .key_seq = %d\n", atuple->key_seq);
29 print2buf(" .rand = %s\n", osmo_hexdump(atuple->rand, sizeof(atuple->rand)));
30 print2buf(" .sres = %s\n", osmo_hexdump(atuple->sres, sizeof(atuple->sres)));
31 print2buf(" .kc = %s\n", osmo_hexdump(atuple->kc, sizeof(atuple->kc)));
32 print2buf("}\n");
33#undef print2buf
34
35 return buf;
36}
37
38static bool auth_tuple_is(struct gsm_auth_tuple *atuple,
39 const char *expect_str)
40{
41 int l, l1, l2;
42 int i;
43 char *tuple_str = auth_tuple_str(atuple);
44 bool same = (strcmp(expect_str, tuple_str) == 0);
45 if (!same) {
46 l1 = strlen(expect_str);
47 l2 = strlen(tuple_str);
48 printf("Expected %d:\n%s\nGot %d:\n%s\n",
49 l1, expect_str, l2, tuple_str);
50 l = min(l1, l2);
51 for (i = 0; i < l; i++) {
52 if (expect_str[i] != tuple_str[i]) {
53 printf("Difference at pos %d"
54 " (%c 0x%0x != %c 0x%0x)\n",
55 i, expect_str[i], expect_str[i],
56 tuple_str[i], tuple_str[i]);
57 break;
58 }
59 }
60 }
61 return same;
62}
63
Neels Hofmeyr37984bd2016-03-30 11:22:24 +020064/* override, requires '-Wl,--wrap=db_get_authinfo_for_subscr' */
65int __real_db_get_authinfo_for_subscr(struct gsm_auth_info *ainfo,
66 struct gsm_subscriber *subscr);
67
68int test_get_authinfo_rc = 0;
69struct gsm_auth_info test_auth_info = {0};
70struct gsm_auth_info default_auth_info = {
71 .auth_algo = AUTH_ALGO_COMP128v1,
72 .a3a8_ki_len = 16,
73 .a3a8_ki = { 0 }
74};
75
76int __wrap_db_get_authinfo_for_subscr(struct gsm_auth_info *ainfo,
77 struct gsm_subscriber *subscr)
78{
79 *ainfo = test_auth_info;
80 printf("wrapped: db_get_authinfo_for_subscr(): rc = %d\n", test_get_authinfo_rc);
81 return test_get_authinfo_rc;
82}
83
84/* override, requires '-Wl,--wrap=db_get_lastauthtuple_for_subscr' */
85int __real_db_get_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple,
86 struct gsm_subscriber *subscr);
87
88int test_get_lastauthtuple_rc = 0;
89struct gsm_auth_tuple test_last_auth_tuple = { 0 };
90struct gsm_auth_tuple default_auth_tuple = { 0 };
91
92int __wrap_db_get_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple,
93 struct gsm_subscriber *subscr)
94{
95 *atuple = test_last_auth_tuple;
96 printf("wrapped: db_get_lastauthtuple_for_subscr(): rc = %d\n", test_get_lastauthtuple_rc);
97 return test_get_lastauthtuple_rc;
98}
99
100/* override, requires '-Wl,--wrap=db_sync_lastauthtuple_for_subscr' */
101int __real_db_sync_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple,
102 struct gsm_subscriber *subscr);
103int test_sync_lastauthtuple_rc = 0;
104int __wrap_db_sync_lastauthtuple_for_subscr(struct gsm_auth_tuple *atuple,
105 struct gsm_subscriber *subscr)
106{
107 test_last_auth_tuple = *atuple;
108 printf("wrapped: db_sync_lastauthtuple_for_subscr(): rc = %d\n", test_sync_lastauthtuple_rc);
109 return test_sync_lastauthtuple_rc;
110}
111
112int auth_get_tuple_for_subscr_verbose(struct gsm_auth_tuple *atuple,
113 struct gsm_subscriber *subscr,
114 int key_seq)
115{
116 int auth_action;
117 auth_action = auth_get_tuple_for_subscr(atuple, subscr, key_seq);
118 printf("auth_get_tuple_for_subscr(key_seq=%d) --> auth_action == %s\n",
119 key_seq, auth_action_str(auth_action));
120 return auth_action;
121}
122
123/* override libssl RAND_bytes() to get testable crypto results */
124int RAND_bytes(uint8_t *rand, int len)
125{
126 memset(rand, 23, len);
127 return 1;
128}
129
130static void test_error()
131{
132 int auth_action;
133
134 struct gsm_auth_tuple atuple = {0};
135 struct gsm_subscriber subscr = {0};
136 int key_seq = 0;
137
138 printf("\n* test_error()\n");
139
140 /* any error (except -ENOENT) */
141 test_get_authinfo_rc = -EIO;
142 auth_action = auth_get_tuple_for_subscr_verbose(&atuple, &subscr,
143 key_seq);
144 OSMO_ASSERT(auth_action == -1);
145}
146
147static void test_auth_not_avail()
148{
149 int auth_action;
150
151 struct gsm_auth_tuple atuple = {0};
152 struct gsm_subscriber subscr = {0};
153 int key_seq = 0;
154
155 printf("\n* test_auth_not_avail()\n");
156
157 /* no entry */
158 test_get_authinfo_rc = -ENOENT;
159 auth_action = auth_get_tuple_for_subscr_verbose(&atuple, &subscr,
160 key_seq);
161 OSMO_ASSERT(auth_action == AUTH_NOT_AVAIL);
162}
163
Neels Hofmeyr4554a622016-03-30 11:22:25 +0200164static void test_auth_then_ciph1()
165{
166 int auth_action;
167
168 struct gsm_auth_tuple atuple = {0};
169 struct gsm_subscriber subscr = {0};
170 int key_seq;
171
172 printf("\n* test_auth_then_ciph1()\n");
173
174 /* Ki entry, but no auth tuple negotiated yet */
175 test_auth_info = default_auth_info;
176 test_last_auth_tuple = default_auth_tuple;
177 test_get_authinfo_rc = 0;
178 test_get_lastauthtuple_rc = -ENOENT;
179 key_seq = 0;
180 auth_action = auth_get_tuple_for_subscr_verbose(&atuple, &subscr,
181 key_seq);
182 OSMO_ASSERT(auth_action == AUTH_DO_AUTH_THEN_CIPH);
183 OSMO_ASSERT(auth_tuple_is(&atuple,
184 "gsm_auth_tuple {\n"
185 " .use_count = 1\n"
186 " .key_seq = 1\n"
187 " .rand = 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 \n"
188 " .sres = a1 ab c6 90 \n"
189 " .kc = 0f 27 ed f3 ac 97 ac 00 \n"
190 "}\n"
191 ));
192}
193
194static void test_auth_then_ciph2()
195{
196 int auth_action;
197
198 struct gsm_auth_tuple atuple = {0};
199 struct gsm_subscriber subscr = {0};
200 int key_seq;
201
202 printf("\n* test_auth_then_ciph2()\n");
203
204 /* Ki entry, auth tuple negotiated, but invalid incoming key_seq */
205 test_auth_info = default_auth_info;
206 test_last_auth_tuple = default_auth_tuple;
207 test_last_auth_tuple.key_seq = 2;
208 test_get_authinfo_rc = 0;
209 test_get_lastauthtuple_rc = 0;
210 key_seq = GSM_KEY_SEQ_INVAL;
211 auth_action = auth_get_tuple_for_subscr_verbose(&atuple, &subscr,
212 key_seq);
213 OSMO_ASSERT(auth_action == AUTH_DO_AUTH_THEN_CIPH);
214 OSMO_ASSERT(auth_tuple_is(&atuple,
215 "gsm_auth_tuple {\n"
216 " .use_count = 1\n"
217 " .key_seq = 3\n"
218 " .rand = 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 \n"
219 " .sres = a1 ab c6 90 \n"
220 " .kc = 0f 27 ed f3 ac 97 ac 00 \n"
221 "}\n"
222 ));
223
224 /* Change the last saved key_seq, expect last_auth_tuple.key_seq + 1 */
225 test_auth_info = default_auth_info;
226 test_last_auth_tuple = default_auth_tuple;
227 test_last_auth_tuple.key_seq = 3;
228 test_get_authinfo_rc = 0;
229 test_get_lastauthtuple_rc = 0;
230 key_seq = GSM_KEY_SEQ_INVAL;
231 auth_action = auth_get_tuple_for_subscr_verbose(&atuple, &subscr,
232 key_seq);
233 OSMO_ASSERT(auth_action == AUTH_DO_AUTH_THEN_CIPH);
234 OSMO_ASSERT(auth_tuple_is(&atuple,
235 "gsm_auth_tuple {\n"
236 " .use_count = 1\n"
237 " .key_seq = 4\n"
238 " .rand = 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 \n"
239 " .sres = a1 ab c6 90 \n"
240 " .kc = 0f 27 ed f3 ac 97 ac 00 \n"
241 "}\n"
242 ));
243}
244
Neels Hofmeyr37984bd2016-03-30 11:22:24 +0200245int main(void)
246{
247 osmo_init_logging(&log_info);
248 log_set_log_level(osmo_stderr_target, LOGL_INFO);
249
250 test_error();
251 test_auth_not_avail();
Neels Hofmeyr4554a622016-03-30 11:22:25 +0200252 test_auth_then_ciph1();
253 test_auth_then_ciph2();
Neels Hofmeyr37984bd2016-03-30 11:22:24 +0200254 return 0;
255}