support the XOR algorithm for UMTS AKA

Test USIMs as specified by 3GPP use the XOR algorithm not only for 2G
but also for 3G.  libosmocore includes the XOR-3G support since v1.3.0,
but osmo-hlr somehow never made use of it.

Change-Id: I3a452af9c18cd90d00ab4766d6bd1679456bc1a2
Closes: OS#4924
This commit is contained in:
Harald Welte 2020-12-28 01:01:31 +01:00
parent dac855e5c8
commit 6e237d3a90
5 changed files with 121 additions and 1 deletions

View File

@ -264,11 +264,11 @@ int db_subscr_update_aud_by_id(struct db_context *dbc, int64_t subscr_id,
switch (aud->algo) {
case OSMO_AUTH_ALG_NONE:
case OSMO_AUTH_ALG_MILENAGE:
case OSMO_AUTH_ALG_XOR:
break;
case OSMO_AUTH_ALG_COMP128v1:
case OSMO_AUTH_ALG_COMP128v2:
case OSMO_AUTH_ALG_COMP128v3:
case OSMO_AUTH_ALG_XOR:
LOGP(DAUC, LOGL_ERROR, "Cannot update auth tokens:"
" auth algo not suited for 3G: %s\n",
osmo_auth_alg_name(aud->algo));

View File

@ -551,6 +551,55 @@ DEFUN(subscriber_aud3g,
return CMD_SUCCESS;
}
DEFUN(subscriber_aud3g_xor,
subscriber_aud3g_xor_cmd,
SUBSCR_UPDATE "aud3g xor k K"
" [ind-bitlen] [<0-28>]",
SUBSCR_UPDATE_HELP
"Set UMTS authentication data (3G, and 2G with UMTS AKA)\n"
"Use XOR algorithm\n"
"Set Encryption Key K\n" "K as 32 hexadecimal characters\n"
"Set IND bit length\n" "IND bit length value (default: 5)\n")
{
struct hlr_subscriber subscr;
int minlen = 0;
int maxlen = 0;
int rc;
const char *id_type = argv[0];
const char *id = argv[1];
const char *k = argv[2];
int ind_bitlen = argc > 4? atoi(argv[4]) : 5;
struct sub_auth_data_str aud3g = {
.type = OSMO_AUTH_TYPE_UMTS,
.u.umts = {
.k = k,
.opc_is_op = 0,
.opc = "00000000000000000000000000000000",
.ind_bitlen = ind_bitlen,
},
};
if (!auth_algo_parse("xor", &aud3g.algo, &minlen, &maxlen)) {
vty_out(vty, "%% Unknown auth algorithm: '%s'%s", "xor", VTY_NEWLINE);
return CMD_WARNING;
}
if (!is_hexkey_valid(vty, "K", aud3g.u.umts.k, minlen, maxlen))
return CMD_WARNING;
if (get_subscr_by_argv(vty, id_type, id, &subscr))
return CMD_WARNING;
rc = db_subscr_update_aud_by_id(g_hlr->dbc, subscr.id, &aud3g);
if (rc) {
vty_out(vty, "%% Error: cannot set 3G auth data for IMSI='%s'%s",
subscr.imsi, VTY_NEWLINE);
return CMD_WARNING;
}
return CMD_SUCCESS;
}
DEFUN(subscriber_imei,
subscriber_imei_cmd,
SUBSCR_UPDATE "imei (none|IMEI)",
@ -637,6 +686,7 @@ void hlr_vty_subscriber_init(void)
install_element(ENABLE_NODE, &subscriber_aud2g_cmd);
install_element(ENABLE_NODE, &subscriber_no_aud3g_cmd);
install_element(ENABLE_NODE, &subscriber_aud3g_cmd);
install_element(ENABLE_NODE, &subscriber_aud3g_xor_cmd);
install_element(ENABLE_NODE, &subscriber_imei_cmd);
install_element(ENABLE_NODE, &subscriber_nam_cmd);
}

View File

@ -454,6 +454,50 @@ static void test_gen_vectors_3g_only(void)
comment_end();
}
static void test_gen_vectors_3g_xor(void)
{
struct osmo_sub_auth_data aud2g;
struct osmo_sub_auth_data aud3g;
struct osmo_auth_vector vec;
int rc;
comment_start();
aud2g = (struct osmo_sub_auth_data){ 0 };
aud3g = (struct osmo_sub_auth_data){
.type = OSMO_AUTH_TYPE_UMTS,
.algo = OSMO_AUTH_ALG_XOR,
.u.umts.sqn = 0,
};
osmo_hexparse("000102030405060708090a0b0c0d0e0f",
aud3g.u.umts.k, sizeof(aud3g.u.umts.k));
osmo_hexparse("00000000000000000000000000000000",
aud3g.u.umts.opc, sizeof(aud3g.u.umts.opc));
next_rand("b5039c57e4a75051551d1a390a71ce48", true);
vec = (struct osmo_auth_vector){ {0} };
VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
rc = auc_compute_vectors(&vec, 1, &aud2g, &aud3g, NULL, NULL);
VERBOSE_ASSERT(rc, == 1, "%d");
VERBOSE_ASSERT(aud3g.u.umts.sqn, == 0, "%"PRIu64);
VEC_IS(&vec,
" rand: b5039c57e4a75051551d1a390a71ce48\n"
" autn: 54e0a256565d0000b5029e54e0a25656\n"
" ck: 029e54e0a256565d141032067cc047b5\n"
" ik: 9e54e0a256565d141032067cc047b502\n"
" res: b5029e54e0a256565d141032067cc047\n"
" res_len: 10\n"
" kc: 98e880384887f9fe\n"
" sres: 0ec81877\n"
" auth_types: 03000000\n"
);
comment_end();
}
void test_gen_vectors_bad_args()
{
struct osmo_auth_vector vec;
@ -622,6 +666,7 @@ int main(int argc, char **argv)
test_gen_vectors_2g_only();
test_gen_vectors_2g_plus_3g();
test_gen_vectors_3g_only();
test_gen_vectors_3g_xor();
test_gen_vectors_bad_args();
printf("Done\n");

View File

@ -217,6 +217,29 @@ DAUC vector [2]: auth_types = 0x3
===== test_gen_vectors_3g_only: SUCCESS
===== test_gen_vectors_3g_xor
aud3g.u.umts.sqn == 0
DAUC Computing 1 auth vector: 3G only (2G derived from 3G keys)
DAUC 3G: k = 000102030405060708090a0b0c0d0e0f
DAUC 3G: opc = 00000000000000000000000000000000
DAUC 3G: for sqn ind 0, previous sqn was 0
DAUC vector [0]: rand = b5039c57e4a75051551d1a390a71ce48
DAUC vector [0]: sqn = 0
DAUC vector [0]: autn = 54e0a256565d0000b5029e54e0a25656
DAUC vector [0]: ck = 029e54e0a256565d141032067cc047b5
DAUC vector [0]: ik = 9e54e0a256565d141032067cc047b502
DAUC vector [0]: res = b5029e54e0a256565d141032067cc047
DAUC vector [0]: res_len = 16
DAUC vector [0]: deriving 2G from 3G
DAUC vector [0]: kc = 98e880384887f9fe
DAUC vector [0]: sres = 0ec81877
DAUC vector [0]: auth_types = 0x3
rc == 1
aud3g.u.umts.sqn == 0
vector matches expectations
===== test_gen_vectors_3g_xor: SUCCESS
===== test_gen_vectors_bad_args
- no auth data (a)

View File

@ -11,6 +11,7 @@ OsmoHLR# list
subscriber (imsi|msisdn|id|imei) IDENT update aud2g (comp128v1|comp128v2|comp128v3|xor) ki KI
subscriber (imsi|msisdn|id|imei) IDENT update aud3g none
subscriber (imsi|msisdn|id|imei) IDENT update aud3g milenage k K (op|opc) OP_C [ind-bitlen] [<0-28>]
subscriber (imsi|msisdn|id|imei) IDENT update aud3g xor k K [ind-bitlen] [<0-28>]
subscriber (imsi|msisdn|id|imei) IDENT update imei (none|IMEI)
subscriber (imsi|msisdn|id|imei) IDENT update network-access-mode (none|cs|ps|cs+ps)
show mslookup services
@ -268,6 +269,7 @@ OsmoHLR# subscriber id 101 show
OsmoHLR# subscriber imsi 123456789023000 update aud3g ?
none Delete 3G authentication data
milenage Use Milenage algorithm
xor Use XOR algorithm
OsmoHLR# subscriber imsi 123456789023000 update aud3g milenage ?
k Set Encryption Key K