@@ -8,6 +8,59 @@
#include <openbsc/gsm_subscriber.h>
#include <openbsc/auth.h>
+#define min(A,B) ((A)>(B)? (B) : (A))
+
+static char *auth_tuple_str(struct gsm_auth_tuple *atuple)
+{
+ static char buf[256];
+ char *pos = buf;
+ int len = sizeof(buf);
+ int l;
+
+#define print2buf(FMT, args...) do {\
+ l = snprintf(pos, len, FMT, ## args); \
+ pos += l;\
+ len -= l;\
+ } while (0)
+
+ print2buf("gsm_auth_tuple {\n");
+ print2buf(" .use_count = %d\n", atuple->use_count);
+ print2buf(" .key_seq = %d\n", atuple->key_seq);
+ print2buf(" .rand = %s\n", osmo_hexdump(atuple->rand, sizeof(atuple->rand)));
+ print2buf(" .sres = %s\n", osmo_hexdump(atuple->sres, sizeof(atuple->sres)));
+ print2buf(" .kc = %s\n", osmo_hexdump(atuple->kc, sizeof(atuple->kc)));
+ print2buf("}\n");
+#undef print2buf
+
+ return buf;
+}
+
+static bool auth_tuple_is(struct gsm_auth_tuple *atuple,
+ const char *expect_str)
+{
+ int l, l1, l2;
+ int i;
+ char *tuple_str = auth_tuple_str(atuple);
+ bool same = (strcmp(expect_str, tuple_str) == 0);
+ if (!same) {
+ l1 = strlen(expect_str);
+ l2 = strlen(tuple_str);
+ printf("Expected %d:\n%s\nGot %d:\n%s\n",
+ l1, expect_str, l2, tuple_str);
+ l = min(l1, l2);
+ for (i = 0; i < l; i++) {
+ if (expect_str[i] != tuple_str[i]) {
+ printf("Difference at pos %d"
+ " (%c 0x%0x != %c 0x%0x)\n",
+ i, expect_str[i], expect_str[i],
+ tuple_str[i], tuple_str[i]);
+ break;
+ }
+ }
+ }
+ return same;
+}
+
/* override, requires '-Wl,--wrap=db_get_authinfo_for_subscr' */
int __real_db_get_authinfo_for_subscr(struct gsm_auth_info *ainfo,
struct gsm_subscriber *subscr);
@@ -108,6 +161,87 @@ static void test_auth_not_avail()
OSMO_ASSERT(auth_action == AUTH_NOT_AVAIL);
}
+static void test_auth_then_ciph1()
+{
+ int auth_action;
+
+ struct gsm_auth_tuple atuple = {0};
+ struct gsm_subscriber subscr = {0};
+ int key_seq;
+
+ printf("\n* test_auth_then_ciph1()\n");
+
+ /* Ki entry, but no auth tuple negotiated yet */
+ test_auth_info = default_auth_info;
+ test_last_auth_tuple = default_auth_tuple;
+ test_get_authinfo_rc = 0;
+ test_get_lastauthtuple_rc = -ENOENT;
+ key_seq = 0;
+ auth_action = auth_get_tuple_for_subscr_verbose(&atuple, &subscr,
+ key_seq);
+ OSMO_ASSERT(auth_action == AUTH_DO_AUTH_THEN_CIPH);
+ OSMO_ASSERT(auth_tuple_is(&atuple,
+ "gsm_auth_tuple {\n"
+ " .use_count = 1\n"
+ " .key_seq = 1\n"
+ " .rand = 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 \n"
+ " .sres = a1 ab c6 90 \n"
+ " .kc = 0f 27 ed f3 ac 97 ac 00 \n"
+ "}\n"
+ ));
+}
+
+static void test_auth_then_ciph2()
+{
+ int auth_action;
+
+ struct gsm_auth_tuple atuple = {0};
+ struct gsm_subscriber subscr = {0};
+ int key_seq;
+
+ printf("\n* test_auth_then_ciph2()\n");
+
+ /* Ki entry, auth tuple negotiated, but invalid incoming key_seq */
+ test_auth_info = default_auth_info;
+ test_last_auth_tuple = default_auth_tuple;
+ test_last_auth_tuple.key_seq = 2;
+ test_get_authinfo_rc = 0;
+ test_get_lastauthtuple_rc = 0;
+ key_seq = GSM_KEY_SEQ_INVAL;
+ auth_action = auth_get_tuple_for_subscr_verbose(&atuple, &subscr,
+ key_seq);
+ OSMO_ASSERT(auth_action == AUTH_DO_AUTH_THEN_CIPH);
+ OSMO_ASSERT(auth_tuple_is(&atuple,
+ "gsm_auth_tuple {\n"
+ " .use_count = 1\n"
+ " .key_seq = 3\n"
+ " .rand = 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 \n"
+ " .sres = a1 ab c6 90 \n"
+ " .kc = 0f 27 ed f3 ac 97 ac 00 \n"
+ "}\n"
+ ));
+
+ /* Change the last saved key_seq, expect last_auth_tuple.key_seq + 1 */
+ test_auth_info = default_auth_info;
+ test_last_auth_tuple = default_auth_tuple;
+ test_last_auth_tuple.key_seq = 3;
+ test_get_authinfo_rc = 0;
+ test_get_lastauthtuple_rc = 0;
+ key_seq = GSM_KEY_SEQ_INVAL;
+ auth_action = auth_get_tuple_for_subscr_verbose(&atuple, &subscr,
+ key_seq);
+ OSMO_ASSERT(auth_action == AUTH_DO_AUTH_THEN_CIPH);
+ OSMO_ASSERT(auth_tuple_is(&atuple,
+ "gsm_auth_tuple {\n"
+ " .use_count = 1\n"
+ " .key_seq = 4\n"
+ " .rand = 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 \n"
+ " .sres = a1 ab c6 90 \n"
+ " .kc = 0f 27 ed f3 ac 97 ac 00 \n"
+ "}\n"
+ ));
+}
+
int main(void)
{
osmo_init_logging(&log_info);
@@ -115,5 +249,7 @@ int main(void)
test_error();
test_auth_not_avail();
+ test_auth_then_ciph1();
+ test_auth_then_ciph2();
return 0;
}
@@ -6,3 +6,19 @@ auth_get_tuple_for_subscr(key_seq=0) --> auth_action == (internal error)
* test_auth_not_avail()
wrapped: db_get_authinfo_for_subscr(): rc = -2
auth_get_tuple_for_subscr(key_seq=0) --> auth_action == AUTH_NOT_AVAIL
+
+* test_auth_then_ciph1()
+wrapped: db_get_authinfo_for_subscr(): rc = 0
+wrapped: db_get_lastauthtuple_for_subscr(): rc = -2
+wrapped: db_sync_lastauthtuple_for_subscr(): rc = 0
+auth_get_tuple_for_subscr(key_seq=0) --> auth_action == AUTH_DO_AUTH_THEN_CIPH
+
+* test_auth_then_ciph2()
+wrapped: db_get_authinfo_for_subscr(): rc = 0
+wrapped: db_get_lastauthtuple_for_subscr(): rc = 0
+wrapped: db_sync_lastauthtuple_for_subscr(): rc = 0
+auth_get_tuple_for_subscr(key_seq=7) --> auth_action == AUTH_DO_AUTH_THEN_CIPH
+wrapped: db_get_authinfo_for_subscr(): rc = 0
+wrapped: db_get_lastauthtuple_for_subscr(): rc = 0
+wrapped: db_sync_lastauthtuple_for_subscr(): rc = 0
+auth_get_tuple_for_subscr(key_seq=7) --> auth_action == AUTH_DO_AUTH_THEN_CIPH