diff --git a/include/osmocom/msc/gsm_data.h b/include/osmocom/msc/gsm_data.h index 72e33a61d..2a64c533b 100644 --- a/include/osmocom/msc/gsm_data.h +++ b/include/osmocom/msc/gsm_data.h @@ -155,10 +155,8 @@ struct gsm_network { bool authentication_required; int send_mm_info; - /* Whether to use encryption on UTRAN. - * TODO: we should offer a choice of UEA1 and/or UEA2, and probably replace this bool with a bit-mask of - * permitted Iu encryption algorithms. See also OS#4143 and the 'encryption uea' vty command. */ - bool uea_encryption; + /* bit-mask of permitted encryption algorithms. LSB=UEA0, MSB=UEA7 */ + uint8_t uea_encryption_mask; struct rate_ctr_group *msc_ctrs; struct osmo_stat_item_group *statg; diff --git a/include/osmocom/msc/ran_msg.h b/include/osmocom/msc/ran_msg.h index 816ef1f92..0714607af 100644 --- a/include/osmocom/msc/ran_msg.h +++ b/include/osmocom/msc/ran_msg.h @@ -103,7 +103,7 @@ struct ran_cipher_mode_command { struct geran_encr *chosen_key; } geran; struct { - bool uea_encryption; + uint8_t uea_encryption_mask; } utran; }; diff --git a/src/libmsc/gsm_04_08.c b/src/libmsc/gsm_04_08.c index 565e7adb7..fc1b2e204 100644 --- a/src/libmsc/gsm_04_08.c +++ b/src/libmsc/gsm_04_08.c @@ -414,7 +414,7 @@ static int mm_rx_loc_upd_req(struct msc_a *msc_a, struct msgb *msg) net->vlr, msc_a, vlr_lu_type, tmsi, imsi, &old_lai, &msc_a->via_cell.lai, is_utran || net->authentication_required, - is_utran ? net->uea_encryption : net->a5_encryption_mask > 0x01, + is_utran ? net->uea_encryption_mask > 0x01 : net->a5_encryption_mask > 0x01, lu->key_seq, osmo_gsm48_classmark1_is_r99(&lu->classmark1), is_utran, @@ -805,7 +805,7 @@ int gsm48_rx_mm_serv_req(struct msc_a *msc_a, struct msgb *msg) req->cm_service_type, &mi, &msc_a->via_cell.lai, is_utran || net->authentication_required, - is_utran ? net->uea_encryption : net->a5_encryption_mask > 0x01, + is_utran ? net->uea_encryption_mask > 0x01 : net->a5_encryption_mask > 0x01, req->cipher_key_seq, osmo_gsm48_classmark2_is_r99(cm2, cm2_len), is_utran); @@ -931,7 +931,7 @@ static int gsm48_rx_cm_reest_req(struct msc_a *msc_a, struct msgb *msg) VLR_PR_ARQ_T_CM_RE_ESTABLISH_REQ, 0, &mi, &msc_a->via_cell.lai, is_utran || net->authentication_required, - is_utran ? net->uea_encryption : net->a5_encryption_mask > 0x01, + is_utran ? net->uea_encryption_mask > 0x01 : net->a5_encryption_mask > 0x01, req->cipher_key_seq, osmo_gsm48_classmark2_is_r99(cm2, cm2_len), is_utran); @@ -1293,7 +1293,7 @@ static int gsm48_rx_rr_pag_resp(struct msc_a *msc_a, struct msgb *msg) net->vlr, msc_a, VLR_PR_ARQ_T_PAGING_RESP, 0, &mi, &msc_a->via_cell.lai, is_utran || net->authentication_required, - is_utran ? net->uea_encryption : net->a5_encryption_mask > 0x01, + is_utran ? net->uea_encryption_mask > 0x01 : net->a5_encryption_mask > 0x01, pr->key_seq, osmo_gsm48_classmark2_is_r99(cm2, classmark2_len), is_utran); diff --git a/src/libmsc/msc_a.c b/src/libmsc/msc_a.c index fe3af14e4..a79cf6aa9 100644 --- a/src/libmsc/msc_a.c +++ b/src/libmsc/msc_a.c @@ -349,8 +349,8 @@ static int msc_a_ran_enc_ciphering(struct msc_a *msc_a, bool umts_aka, bool retr .chosen_key = &msc_a->geran_encr, }, .utran = { - .uea_encryption = net->uea_encryption - } + .uea_encryption_mask = net->uea_encryption_mask, + }, }, }; diff --git a/src/libmsc/msc_net_init.c b/src/libmsc/msc_net_init.c index 9e3e8b34f..d53156b8a 100644 --- a/src/libmsc/msc_net_init.c +++ b/src/libmsc/msc_net_init.c @@ -67,7 +67,8 @@ struct gsm_network *gsm_network_init(void *ctx, mncc_recv_cb_t mncc_recv) /* Permit a compile-time default of A5/3 and A5/1 */ net->a5_encryption_mask = (1 << 3) | (1 << 1); - net->uea_encryption = true; + /* Permit a compile-time default of UEA2 and UEA1 */ + net->uea_encryption_mask = (1 << 2) | (1 << 1); net->mncc_guard_timeout = 180; net->ncss_guard_timeout = 30; diff --git a/src/libmsc/msc_vty.c b/src/libmsc/msc_vty.c index e4e093741..6be09d8ed 100644 --- a/src/libmsc/msc_vty.c +++ b/src/libmsc/msc_vty.c @@ -169,41 +169,21 @@ DEFUN(cfg_net_encryption, return CMD_SUCCESS; } -/* So far just a boolean switch, a future patch might add individual config for UEA1 and UEA2, see OS#4143 */ DEFUN(cfg_net_encryption_uea, cfg_net_encryption_uea_cmd, "encryption uea <0-2> [<0-2>] [<0-2>]", ENCRYPTION_STR - "UTRAN (3G) encryption algorithms to allow: 0 = UEA0 (no encryption), 1 = UEA1, 2 = UEA2." - " NOTE: the current implementation does not allow free choice of combining encryption algorithms yet." - " The only valid settings are either 'encryption uea 0' or 'encryption uea 1 2'.\n" + "UTRAN (3G) encryption algorithms to allow: 0 = UEA0 (no encryption), 1 = UEA1, 2 = UEA2.\n" "UEAn Algorithm Number\n" "UEAn Algorithm Number\n" "UEAn Algorithm Number\n" ) { unsigned int i; - uint8_t mask = 0; + gsmnet->uea_encryption_mask = 0; for (i = 0; i < argc; i++) - mask |= (1 << atoi(argv[i])); - - if (mask == (1 << 0)) { - /* UEA0. Disable encryption. */ - gsmnet->uea_encryption = false; - } else if (mask == ((1 << 1) | (1 << 2))) { - /* UEA1 and UEA2. Enable encryption. */ - gsmnet->uea_encryption = true; - } else { - vty_out(vty, - "%% Error: the current implementation does not allow free choice of combining%s" - "%% encryption algorithms yet. The only valid settings are either%s" - "%% encryption uea 0%s" - "%% or%s" - "%% encryption uea 1 2%s", - VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE); - return CMD_WARNING; - } + gsmnet->uea_encryption_mask |= (1 << atoi(argv[i])); return CMD_SUCCESS; } @@ -386,10 +366,12 @@ static int config_write_net(struct vty *vty) } vty_out(vty, "%s", VTY_NEWLINE); - if (!gsmnet->uea_encryption) - vty_out(vty, " encryption uea 0%s", VTY_NEWLINE); - else - vty_out(vty, " encryption uea 1 2%s", VTY_NEWLINE); + vty_out(vty, " encryption uea"); + for (i = 0; i < 8; i++) { + if (gsmnet->uea_encryption_mask & (1 << i)) + vty_out(vty, " %u", i); + } + vty_out(vty, "%s", VTY_NEWLINE); vty_out(vty, " authentication %s%s", gsmnet->authentication_required ? "required" : "optional", VTY_NEWLINE); vty_out(vty, " rrlp mode %s%s", msc_rrlp_mode_name(gsmnet->rrlp.mode), diff --git a/src/libmsc/ran_msg_iu.c b/src/libmsc/ran_msg_iu.c index 6120918d9..7b3dd1c01 100644 --- a/src/libmsc/ran_msg_iu.c +++ b/src/libmsc/ran_msg_iu.c @@ -367,9 +367,13 @@ static struct msgb *ran_iu_make_security_mode_command(struct osmo_fsm_inst *call const struct ran_cipher_mode_command *cm) { - LOG_RAN_IU_ENC(caller_fi, LOGL_DEBUG, "Tx RANAP SECURITY MODE COMMAND to RNC, ik %s\n", - osmo_hexdump_nospc(cm->vec->ik, 16)); - return ranap_new_msg_sec_mod_cmd(cm->vec->ik, cm->utran.uea_encryption ? cm->vec->ck : NULL, RANAP_KeyStatus_new); + LOG_RAN_IU_ENC(caller_fi, LOGL_DEBUG, "Tx RANAP SECURITY MODE COMMAND to RNC, IK=%s, CK=%s\n", + osmo_hexdump_nospc(cm->vec->ik, 16), + cm->utran.uea_encryption_mask > 0x01 ? osmo_hexdump_nospc(cm->vec->ck, 16) : "NONE"); + /* TODO: Do we need to check if the UE supports all of the algorithms and build an intersection like + * in the case of A5? */ + return ranap_new_msg_sec_mod_cmd2(cm->vec->ik, cm->utran.uea_encryption_mask > 0x01 ? cm->vec->ck : NULL, + RANAP_KeyStatus_new, 0x06, cm->utran.uea_encryption_mask); } diff --git a/tests/msc_vlr/msc_vlr_test_umts_authen.c b/tests/msc_vlr/msc_vlr_test_umts_authen.c index 46f8d98a1..e462ef4df 100644 --- a/tests/msc_vlr/msc_vlr_test_umts_authen.c +++ b/tests/msc_vlr/msc_vlr_test_umts_authen.c @@ -50,7 +50,7 @@ static void _test_umts_authen(enum osmo_rat_type via_ran) "d3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb" "0c7ac3e9e9b7db05"; bool encryption = (via_ran == OSMO_RAT_GERAN_A && net->a5_encryption_mask > 0x1) - || (via_ran == OSMO_RAT_UTRAN_IU && net->uea_encryption); + || (via_ran == OSMO_RAT_UTRAN_IU && net->uea_encryption_mask > 0x1); net->authentication_required = true; net->vlr->cfg.assign_tmsi = true; @@ -333,7 +333,7 @@ static void test_umts_authen_geran() static void test_umts_authen_utran() { comment_start(); - net->uea_encryption = false; + net->uea_encryption_mask = 0x01; _test_umts_authen(OSMO_RAT_UTRAN_IU); comment_end(); } @@ -341,7 +341,7 @@ static void test_umts_authen_utran() static void test_umts_auth_ciph_utran() { comment_start(); - net->uea_encryption = true; + net->uea_encryption_mask = 0x06; _test_umts_authen(OSMO_RAT_UTRAN_IU); comment_end(); } @@ -361,7 +361,7 @@ static void _test_umts_authen_resync(enum osmo_rat_type via_ran) struct vlr_subscr *vsub; const char *imsi = "901700000010650"; bool encryption = (via_ran == OSMO_RAT_GERAN_A && net->a5_encryption_mask > 0x1) - || (via_ran == OSMO_RAT_UTRAN_IU && net->uea_encryption); + || (via_ran == OSMO_RAT_UTRAN_IU && net->uea_encryption_mask > 0x1); net->authentication_required = true; net->vlr->cfg.assign_tmsi = true; @@ -588,7 +588,7 @@ static void test_umts_authen_resync_geran() static void test_umts_authen_resync_utran() { comment_start(); - net->uea_encryption = false; + net->uea_encryption_mask = 0x01; _test_umts_authen_resync(OSMO_RAT_UTRAN_IU); comment_end(); } @@ -596,7 +596,7 @@ static void test_umts_authen_resync_utran() static void test_umts_auth_ciph_resync_utran() { comment_start(); - net->uea_encryption = true; + net->uea_encryption_mask = 0x06; _test_umts_authen_resync(OSMO_RAT_UTRAN_IU); comment_end(); } diff --git a/tests/test_nodes.vty b/tests/test_nodes.vty index 315264fd1..14f15a200 100644 --- a/tests/test_nodes.vty +++ b/tests/test_nodes.vty @@ -31,7 +31,7 @@ OsmoMSC(config-net)# encryption? encryption Encryption options OsmoMSC(config-net)# encryption ? a5 GSM A5 Air Interface Encryption. - uea UTRAN (3G) encryption algorithms to allow: 0 = UEA0 (no encryption), 1 = UEA1, 2 = UEA2. NOTE: the current implementation does not allow free choice of combining encryption algorithms yet. The only valid settings are either 'encryption uea 0' or 'encryption uea 1 2'. + uea UTRAN (3G) encryption algorithms to allow: 0 = UEA0 (no encryption), 1 = UEA1, 2 = UEA2. OsmoMSC(config-net)# encryption uea ? <0-2> UEAn Algorithm Number @@ -189,38 +189,27 @@ OsmoMSC(config-net)# show running-config ... OsmoMSC(config-net)# encryption uea 1 -% Error: the current implementation does not allow free choice of combining -% encryption algorithms yet. The only valid settings are either -% encryption uea 0 -% or -% encryption uea 1 2 OsmoMSC(config-net)# show running-config ... - encryption uea 0 + encryption uea 1 ... OsmoMSC(config-net)# encryption uea 2 -% Error: the current implementation does not allow free choice of combining -... OsmoMSC(config-net)# show running-config ... - encryption uea 0 + encryption uea 2 ... OsmoMSC(config-net)# encryption uea 0 1 -% Error: the current implementation does not allow free choice of combining -... OsmoMSC(config-net)# show running-config ... - encryption uea 0 + encryption uea 0 1 ... OsmoMSC(config-net)# encryption uea 0 2 -% Error: the current implementation does not allow free choice of combining -... OsmoMSC(config-net)# show running-config ... - encryption uea 0 + encryption uea 0 2 ... OsmoMSC(config-net)# encryption uea 1 2