diff options
author | Sylvain Munaut <tnt@246tNt.com> | 2010-06-11 00:19:42 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2010-06-14 20:43:53 +0200 |
commit | e824d9c2a117cdfa83fa9614810321cc976048a2 (patch) | |
tree | 41a0bf5b8f4937599ac99b77232947cd4f0af120 /openbsc | |
parent | c593cf100abeae7c795ccb568be68384081b9824 (diff) |
auth: Add support for XOR test A3A8 algo (and vty commands)
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Diffstat (limited to 'openbsc')
-rw-r--r-- | openbsc/include/openbsc/gsm_data.h | 2 | ||||
-rw-r--r-- | openbsc/src/auth.c | 25 | ||||
-rw-r--r-- | openbsc/src/vty_interface_layer3.c | 39 |
3 files changed, 53 insertions, 13 deletions
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index f8bda6df5..119c02adc 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -211,6 +211,8 @@ struct neigh_meas_proc { }; #define MAX_A5_KEY_LEN (128/8) +#define A38_XOR_MIN_KEY_LEN 12 +#define A38_XOR_MAX_KEY_LEN 16 #define A38_COMP128_KEY_LEN 16 #define RSL_ENC_ALG_A5(x) (x+1) diff --git a/openbsc/src/auth.c b/openbsc/src/auth.c index 5a54da020..f57b668ef 100644 --- a/openbsc/src/auth.c +++ b/openbsc/src/auth.c @@ -31,6 +31,26 @@ static int +_use_xor(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple) +{ + int i, l = ainfo->a3a8_ki_len; + + if ((l > A38_XOR_MAX_KEY_LEN) || (l < A38_XOR_MIN_KEY_LEN)) { + DEBUGP(DMM, "Invalid XOR key (len=%d) %s", + ainfo->a3a8_ki_len, + hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len)); + return -1; + } + + for (i=0; i<4; i++) + atuple->sres[i] = atuple->rand[i] ^ ainfo->a3a8_ki[i]; + for (i=8; i<12; i++) + atuple->kc[i-4] = atuple->rand[i] ^ ainfo->a3a8_ki[i]; + + return 0; +} + +static int _use_comp128_v1(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple) { if (ainfo->a3a8_ki_len != A38_COMP128_KEY_LEN) { @@ -85,6 +105,11 @@ int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple, case AUTH_ALGO_NONE: return 0; + case AUTH_ALGO_XOR: + if (_use_xor(&ainfo, atuple)) + return 0; + break; + case AUTH_ALGO_COMP128v1: if (_use_comp128_v1(&ainfo, atuple)) return 0; diff --git a/openbsc/src/vty_interface_layer3.c b/openbsc/src/vty_interface_layer3.c index b5af0ab72..7c32c05b0 100644 --- a/openbsc/src/vty_interface_layer3.c +++ b/openbsc/src/vty_interface_layer3.c @@ -442,9 +442,10 @@ DEFUN(ena_subscr_extension, return CMD_SUCCESS; } -#define A3A8_ALG_TYPES "(none|comp128v1)" +#define A3A8_ALG_TYPES "(none|xor|comp128v1)" #define A3A8_ALG_HELP \ "Use No A3A8 algorithm\n" \ + "Use XOR algorithm\n" \ "Use COMP128v1 algorithm\n" DEFUN(ena_subscr_a3a8, @@ -457,9 +458,9 @@ DEFUN(ena_subscr_a3a8, struct gsm_subscriber *subscr = get_subscr_by_argv(gsmnet, argv[0], argv[1]); const char *alg_str = argv[2]; - const char *ki_str = argv[3]; + const char *ki_str = argc == 4 ? argv[3] : NULL; struct gsm_auth_info ainfo; - int rc; + int rc, minlen, maxlen; if (!subscr) { vty_out(vty, "%% No subscriber found for %s %s%s", @@ -468,23 +469,35 @@ DEFUN(ena_subscr_a3a8, } if (!strcasecmp(alg_str, "none")) { - /* Just erase */ - rc = db_sync_authinfo_for_subscr(NULL, subscr); + ainfo.auth_algo = AUTH_ALGO_NONE; + minlen = maxlen = 0; + } else if (!strcasecmp(alg_str, "xor")) { + ainfo.auth_algo = AUTH_ALGO_XOR; + minlen = A38_XOR_MIN_KEY_LEN; + maxlen = A38_XOR_MAX_KEY_LEN; } else if (!strcasecmp(alg_str, "comp128v1")) { - /* Parse hex string Ki */ - rc = hexparse(ki_str, ainfo.a3a8_ki, sizeof(ainfo.a3a8_ki)); - if (rc != 16) - return CMD_WARNING; - - /* Set the infos */ ainfo.auth_algo = AUTH_ALGO_COMP128v1; - ainfo.a3a8_ki_len = rc; - rc = db_sync_authinfo_for_subscr(&ainfo, subscr); + minlen = maxlen = A38_COMP128_KEY_LEN; } else { /* Unknown method */ return CMD_WARNING; } + if (ki_str) { + rc = hexparse(ki_str, ainfo.a3a8_ki, sizeof(ainfo.a3a8_ki)); + if ((rc > maxlen) || (rc < minlen)) + return CMD_WARNING; + ainfo.a3a8_ki_len = rc; + } else { + ainfo.a3a8_ki_len = 0; + if (minlen) + return CMD_WARNING; + } + + rc = db_sync_authinfo_for_subscr( + ainfo.auth_algo == AUTH_ALGO_NONE ? NULL : &ainfo, + subscr); + /* the last tuple probably invalid with the new auth settings */ db_sync_lastauthtuple_for_subscr(NULL, subscr); |