blob: 9a2063bdc1d72f6eb554c58e32033f202e4ef48a [file] [log] [blame]
Neels Hofmeyrf06046b2015-10-12 11:57:35 +02001/* Test Osmocom Authentication Protocol */
2/*
3 * (C) 2015 by sysmocom s.f.m.c. GmbH
4 * All Rights Reserved
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 Affero 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 <osmocom/core/application.h>
22
23#include <openbsc/debug.h>
24
25#include <openbsc/oap.h>
26#include <openbsc/oap_messages.h>
27
28#include <stdio.h>
29
Neels Hofmeyr89ef3242015-10-12 11:57:36 +020030static void test_oap_api(void)
Neels Hofmeyrf06046b2015-10-12 11:57:35 +020031{
Neels Hofmeyr89ef3242015-10-12 11:57:36 +020032 printf("Testing OAP API\n - Config parsing\n");
33
34 struct oap_config _config;
35 struct oap_config *config = &_config;
36
37 struct oap_state _state;
38 struct oap_state *state = &_state;
39
40 memset(config, 0, sizeof(*config));
41 memset(state, 0, sizeof(*state));
42
43 OSMO_ASSERT(osmo_hexparse("0102030405060708090a0b0c0d0e0f10", config->secret_k, 16) == 16);
44 OSMO_ASSERT(osmo_hexparse("1112131415161718191a1b1c1d1e1f20", config->secret_opc, 16) == 16);
45
46 /* make sure filling with zeros means uninitialized */
47 OSMO_ASSERT(state->state == OAP_UNINITIALIZED);
48
49 /* invalid client_id and shared secret */
50 config->client_id = 0;
51 config->secret_k_present = 0;
52 config->secret_opc_present = 0;
53 OSMO_ASSERT( oap_init(config, state) == 0 );
54 OSMO_ASSERT(state->state == OAP_DISABLED);
55
56 /* reset state */
57 memset(state, 0, sizeof(*state));
58
59 /* only client_id is invalid */
60 config->client_id = 0;
61 config->secret_k_present = 1;
62 config->secret_opc_present = 1;
63 OSMO_ASSERT( oap_init(config, state) == 0 );
64 OSMO_ASSERT(state->state == OAP_DISABLED);
65
66 memset(state, 0, sizeof(*state));
67
68 /* valid id, but omitted shared_secret (1/2) */
69 config->client_id = 12345;
70 config->secret_k_present = 0;
71 config->secret_opc_present = 1;
72 OSMO_ASSERT( oap_init(config, state) == 0 );
73 OSMO_ASSERT(state->state == OAP_DISABLED);
74
75 memset(state, 0, sizeof(*state));
76
77 /* valid id, but omitted shared_secret (2/2) */
78 config->client_id = 12345;
79 config->secret_k_present = 1;
80 config->secret_opc_present = 0;
81 OSMO_ASSERT( oap_init(config, state) == 0 );
82 OSMO_ASSERT(state->state == OAP_DISABLED);
83
84 memset(state, 0, sizeof(*state));
85
86
87 /* mint configuration */
88 config->client_id = 12345;
89 config->secret_k_present = 1;
90 config->secret_opc_present = 1;
91 /*config->secret_* buffers are still set from the top */
92 OSMO_ASSERT( oap_init(config, state) == 0 );
93 OSMO_ASSERT(state->state == OAP_INITIALIZED);
94
95 printf(" - AUTN failures\n");
96
97 struct oap_message oap_rx;
98 struct oap_message oap_tx;
99 struct msgb *msg_rx;
100 struct msgb *msg_tx;
101
102 memset(&oap_rx, 0, sizeof(oap_rx));
103
104 /* Missing challenge data */
105 oap_rx.message_type = OAP_MSGT_CHALLENGE_REQUEST;
106 oap_rx.rand_present = 0;
107 oap_rx.autn_present = 0;
108 msg_rx = oap_encoded(&oap_rx);
109 OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -2);
110 msgb_free(msg_rx);
111 OSMO_ASSERT(!msg_tx);
112
113 /* AUTN missing */
114 osmo_hexparse("0102030405060708090a0b0c0d0e0f10",
115 oap_rx.rand, 16);
116 oap_rx.rand_present = 1;
117 msg_rx = oap_encoded(&oap_rx);
118 OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -2);
119 msgb_free(msg_rx);
120 OSMO_ASSERT(!msg_tx);
121
122 /* RAND missing */
123 oap_rx.rand_present = 0;
124 osmo_hexparse("cec4e3848a33000086781158ca40f136",
125 oap_rx.autn, 16);
126 oap_rx.autn_present = 1;
127 msg_rx = oap_encoded(&oap_rx);
128 OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -2);
129 msgb_free(msg_rx);
130 OSMO_ASSERT(!msg_tx);
131
132 /* wrong autn (by one bit) */
133 osmo_hexparse("0102030405060708090a0b0c0d0e0f10",
134 oap_rx.rand, 16);
135 osmo_hexparse("dec4e3848a33000086781158ca40f136",
136 oap_rx.autn, 16);
137 oap_rx.rand_present = 1;
138 oap_rx.autn_present = 1;
139 msg_rx = oap_encoded(&oap_rx);
140 OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -2);
141 msgb_free(msg_rx);
142 OSMO_ASSERT(!msg_tx);
143
144 /* all data correct */
145 osmo_hexparse("cec4e3848a33000086781158ca40f136",
146 oap_rx.autn, 16);
147 msg_rx = oap_encoded(&oap_rx);
148
149 /* but refuse to evaluate in uninitialized state */
150 OSMO_ASSERT(state->state == OAP_INITIALIZED);
151
152 state->state = OAP_UNINITIALIZED;
153 OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -1);
154 OSMO_ASSERT(!msg_tx);
155
156 state->state = OAP_DISABLED;
157 OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -1);
158 OSMO_ASSERT(!msg_tx);
159
160 state->state = OAP_INITIALIZED;
161
162 /* now everything is correct */
163 printf(" - AUTN success\n");
164 /* a successful return value here indicates correct autn */
165 OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == 0);
166 msgb_free(msg_rx);
167
168 /* Expect the challenge response in msg_tx */
169 OSMO_ASSERT(msg_tx);
170 OSMO_ASSERT(oap_decode(msg_tx->data, msg_tx->len, &oap_tx) == 0);
171 OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_CHALLENGE_RESULT);
172 OSMO_ASSERT(strcmp("e2d05b598c61d9ba",
173 osmo_hexdump_nospc(oap_tx.xres, sizeof(oap_tx.xres)))
174 == 0);
175 OSMO_ASSERT(state->state == OAP_SENT_CHALLENGE_RESULT);
176 msgb_free(msg_tx);
177 msg_tx = 0;
178
179 struct oap_state saved_state = _state;
180
181 printf(" - Registration failure\n");
182
183 memset(&oap_rx, 0, sizeof(oap_rx));
184 oap_rx.message_type = OAP_MSGT_REGISTER_ERROR;
185 oap_rx.cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
186 msg_rx = oap_encoded(&oap_rx);
187
188 /* Receive registration error for the first time. */
189 OSMO_ASSERT(state->registration_failures == 0);
190 OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == 0);
191 OSMO_ASSERT(state->registration_failures == 1);
192 OSMO_ASSERT(msg_tx);
193 OSMO_ASSERT(oap_decode(msg_tx->data, msg_tx->len, &oap_tx) == 0);
194 OSMO_ASSERT(oap_tx.message_type == OAP_MSGT_REGISTER_REQUEST);
195 OSMO_ASSERT(state->state == OAP_REQUESTED_CHALLENGE);
196 msgb_free(msg_tx);
197 msg_tx = 0;
198
199 /* Receive registration error for the Nth time. */
200 state->registration_failures = 999;
201 OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == -11);
202 OSMO_ASSERT(!msg_tx);
203 OSMO_ASSERT(state->state == OAP_INITIALIZED);
204 msgb_free(msg_tx);
205 msg_tx = 0;
206
207 msgb_free(msg_rx);
208
209 printf(" - Registration success\n");
210
211 _state = saved_state;
212 memset(&oap_rx, 0, sizeof(oap_rx));
213 oap_rx.message_type = OAP_MSGT_REGISTER_RESULT;
214 msg_rx = oap_encoded(&oap_rx);
215 OSMO_ASSERT(oap_handle(state, msg_rx, &msg_tx) == 0);
216 OSMO_ASSERT(!msg_tx);
217 OSMO_ASSERT(state->state == OAP_REGISTERED);
218 msgb_free(msg_rx);
Neels Hofmeyrf06046b2015-10-12 11:57:35 +0200219}
220
221static struct log_info_cat gprs_categories[] = {
222 [DGPRS] = {
223 .name = "DGPRS",
224 .description = "GPRS Packet Service",
225 .enabled = 1, .loglevel = LOGL_DEBUG,
226 },
227};
228
229static struct log_info info = {
230 .cat = gprs_categories,
231 .num_cat = ARRAY_SIZE(gprs_categories),
232};
233
234int main(int argc, char **argv)
235{
236 osmo_init_logging(&info);
237
Neels Hofmeyr89ef3242015-10-12 11:57:36 +0200238 test_oap_api();
Neels Hofmeyrf06046b2015-10-12 11:57:35 +0200239 printf("Done\n");
240
241 return 0;
242}
243