diff --git a/doc/manuals/chapters/net.adoc b/doc/manuals/chapters/net.adoc index 4bf34a33f..6edb9ee3a 100644 --- a/doc/manuals/chapters/net.adoc +++ b/doc/manuals/chapters/net.adoc @@ -188,11 +188,22 @@ network While authentication is always required on 3G, ciphering is optional. -So far OsmoMSC lacks explicit configuration for ciphering on 3G. As an interim -solution, ciphering is enabled on 3G exactly when ciphering is enabled on 2G, -i.e. when any cipher other than A5/0 is enabled in the configuration. If only -A5/0 is configured, ciphering will be disabled on both 2G and 3G. The future -aim is to add comprehensive configuration for 3G ciphering that is independent -from the 2G setting. +So far OsmoMSC allows switching ciphering on 3G either on or off -- the default +behavior is to enable ciphering. (Individual choice of algorithms may be added +in the future.) + +Disable 3G ciphering: + +---- +network + encryption uea 0 +---- + +Enable 3G ciphering (default): + +---- +network + encryption uea 1 2 +---- OsmoMSC indicates UEA1 and UEA2 as permitted encryption algorithms on 3G. diff --git a/include/osmocom/msc/gsm_data.h b/include/osmocom/msc/gsm_data.h index e926b3f87..a90b732af 100644 --- a/include/osmocom/msc/gsm_data.h +++ b/include/osmocom/msc/gsm_data.h @@ -149,6 +149,11 @@ 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; + struct rate_ctr_group *msc_ctrs; struct osmo_stat_item_group *statg; diff --git a/src/libmsc/gsm_04_08.c b/src/libmsc/gsm_04_08.c index cd37cff05..086116fd5 100644 --- a/src/libmsc/gsm_04_08.c +++ b/src/libmsc/gsm_04_08.c @@ -375,7 +375,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, - net->a5_encryption_mask > 0x01, + is_utran ? net->uea_encryption : net->a5_encryption_mask > 0x01, lu->key_seq, osmo_gsm48_classmark1_is_r99(&lu->classmark1), is_utran, @@ -780,7 +780,7 @@ int gsm48_rx_mm_serv_req(struct msc_a *msc_a, struct msgb *msg) req->cm_service_type, mi-1, &msc_a->via_cell.lai, is_utran || net->authentication_required, - net->a5_encryption_mask > 0x01, + is_utran ? net->uea_encryption : net->a5_encryption_mask > 0x01, req->cipher_key_seq, osmo_gsm48_classmark2_is_r99(cm2, cm2_len), is_utran); @@ -1152,7 +1152,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_lv, &msc_a->via_cell.lai, is_utran || net->authentication_required, - net->a5_encryption_mask > 0x01, + is_utran ? net->uea_encryption : net->a5_encryption_mask > 0x01, pr->key_seq, osmo_gsm48_classmark2_is_r99(cm2, classmark2_len), is_utran); diff --git a/src/libmsc/msc_net_init.c b/src/libmsc/msc_net_init.c index 11920f377..91b6165bd 100644 --- a/src/libmsc/msc_net_init.c +++ b/src/libmsc/msc_net_init.c @@ -49,6 +49,7 @@ 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; /* Use 30 min periodic update interval as sane default */ net->t3212 = 5; diff --git a/src/libmsc/msc_vty.c b/src/libmsc/msc_vty.c index 5bf970163..4674e2e68 100644 --- a/src/libmsc/msc_vty.c +++ b/src/libmsc/msc_vty.c @@ -144,14 +144,13 @@ DEFUN(cfg_net_name_long, return CMD_SUCCESS; } +#define ENCRYPTION_STR "Encryption options\n" + DEFUN(cfg_net_encryption, cfg_net_encryption_cmd, "encryption a5 <0-3> [<0-3>] [<0-3>] [<0-3>]", - "Encryption options\n" - "GSM A5 Air Interface Encryption." - " NOTE: as long as OsmoMSC lacks distinct configuration for 3G encryption," - " 3G encryption is enabled exactly when any 2G encryption is enabled." - " Hence configuring only A5/0 here switches off 3G encryption.\n" + ENCRYPTION_STR + "GSM A5 Air Interface Encryption.\n" "A5/n Algorithm Number\n" "A5/n Algorithm Number\n" "A5/n Algorithm Number\n" @@ -166,6 +165,45 @@ 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" + "UEAn Algorithm Number\n" + "UEAn Algorithm Number\n" + "UEAn Algorithm Number\n" + ) +{ + unsigned int i; + uint8_t 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; + } + + return CMD_SUCCESS; +} + DEFUN(cfg_net_authentication, cfg_net_authentication_cmd, "authentication (optional|required)", @@ -308,6 +346,11 @@ static int config_write_net(struct vty *vty) vty_out(vty, " %u", i); } 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, " authentication %s%s", gsmnet->authentication_required ? "required" : "optional", VTY_NEWLINE); vty_out(vty, " rrlp mode %s%s", msc_rrlp_mode_name(gsmnet->rrlp.mode), @@ -1894,6 +1937,7 @@ void msc_vty_init(struct gsm_network *msc_network) install_element(GSMNET_NODE, &cfg_net_name_short_cmd); install_element(GSMNET_NODE, &cfg_net_name_long_cmd); install_element(GSMNET_NODE, &cfg_net_encryption_cmd); + install_element(GSMNET_NODE, &cfg_net_encryption_uea_cmd); install_element(GSMNET_NODE, &cfg_net_authentication_cmd); install_element(GSMNET_NODE, &cfg_net_rrlp_mode_cmd); install_element(GSMNET_NODE, &cfg_net_mm_info_cmd); diff --git a/tests/msc_vlr/msc_vlr_test_authen_reuse.c b/tests/msc_vlr/msc_vlr_test_authen_reuse.c index 62ea6c7b5..d73a5f8c5 100644 --- a/tests/msc_vlr/msc_vlr_test_authen_reuse.c +++ b/tests/msc_vlr/msc_vlr_test_authen_reuse.c @@ -266,8 +266,6 @@ static void _test_auth_reuse(enum osmo_rat_type via_ran, static void test_auth_use_twice_geran() { comment_start(); - /* A5/0 = no encryption */ - net->a5_encryption_mask = A5_0; _test_auth_reuse(OSMO_RAT_GERAN_A, 1, 1, true); comment_end(); } @@ -275,8 +273,6 @@ static void test_auth_use_twice_geran() static void test_auth_use_twice_utran() { comment_start(); - /* A5/0 + A5/3 = encryption enabled; so far the A5 setting also triggers UTRAN encryption */ - net->a5_encryption_mask = A5_0_3; _test_auth_reuse(OSMO_RAT_UTRAN_IU, 1, 1, true); comment_end(); } @@ -284,8 +280,6 @@ static void test_auth_use_twice_utran() static void test_auth_use_infinitely_geran() { comment_start(); - /* A5/0 = no encryption */ - net->a5_encryption_mask = A5_0; _test_auth_reuse(OSMO_RAT_GERAN_A, -1, 3, false); comment_end(); } @@ -293,8 +287,6 @@ static void test_auth_use_infinitely_geran() static void test_auth_use_infinitely_utran() { comment_start(); - /* A5/0 + A5/3 = encryption enabled; so far the A5 setting also triggers UTRAN encryption */ - net->a5_encryption_mask = A5_0_3; _test_auth_reuse(OSMO_RAT_UTRAN_IU, -1, 3, false); comment_end(); } @@ -302,8 +294,6 @@ static void test_auth_use_infinitely_utran() static void test_no_auth_reuse_geran() { comment_start(); - /* A5/0 = no encryption */ - net->a5_encryption_mask = A5_0; _test_auth_reuse(OSMO_RAT_GERAN_A, 0, 0, true); comment_end(); } @@ -311,8 +301,6 @@ static void test_no_auth_reuse_geran() static void test_no_auth_reuse_utran() { comment_start(); - /* A5/0 + A5/3 = encryption enabled; so far the A5 setting also triggers UTRAN encryption */ - net->a5_encryption_mask = A5_0_3; _test_auth_reuse(OSMO_RAT_UTRAN_IU, 0, 0, true); comment_end(); } diff --git a/tests/msc_vlr/msc_vlr_test_call.c b/tests/msc_vlr/msc_vlr_test_call.c index cec2f8da0..065af2555 100644 --- a/tests/msc_vlr/msc_vlr_test_call.c +++ b/tests/msc_vlr/msc_vlr_test_call.c @@ -46,7 +46,6 @@ static void standard_lu() struct vlr_subscr *vsub; net->authentication_required = true; - net->a5_encryption_mask = A5_0_3; net->vlr->cfg.assign_tmsi = true; rx_from_ran = OSMO_RAT_UTRAN_IU; diff --git a/tests/msc_vlr/msc_vlr_test_umts_authen.c b/tests/msc_vlr/msc_vlr_test_umts_authen.c index 1bf6cd217..761db55e2 100644 --- a/tests/msc_vlr/msc_vlr_test_umts_authen.c +++ b/tests/msc_vlr/msc_vlr_test_umts_authen.c @@ -49,6 +49,8 @@ static void _test_umts_authen(enum osmo_rat_type via_ran) "5079da1e1ee7416937485e9ea7c965373d1d6683c270383b3d0e" "d3d36ff71c949e83c22072799e9687c5ec32a81d96afcbf4b4fb" "0c7ac3e9e9b7db05"; + bool encryption = (via_ran == OSMO_RAT_GERAN_A && net->a5_encryption_mask > 0x1) + || (via_ran == OSMO_RAT_UTRAN_IU && net->uea_encryption); net->authentication_required = true; net->vlr->cfg.assign_tmsi = true; @@ -122,8 +124,7 @@ static void _test_umts_authen(enum osmo_rat_type via_ran) VERBOSE_ASSERT(auth_request_sent, == true, "%d"); VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d"); - if (net->a5_encryption_mask > 0x1) { - /* Encryption enabled */ + if (encryption) { if (via_ran == OSMO_RAT_GERAN_A) { btw("Test code not implemented"); OSMO_ASSERT(false); @@ -197,8 +198,7 @@ static void _test_umts_authen(enum osmo_rat_type via_ran) EXPECT_ACCEPTED(false); thwart_rx_non_initial_requests(); - if (net->a5_encryption_mask > 0x1) { - /* Encryption enabled */ + if (encryption) { if (via_ran == OSMO_RAT_GERAN_A) { btw("Test code not implemented"); OSMO_ASSERT(false); @@ -265,8 +265,7 @@ static void _test_umts_authen(enum osmo_rat_type via_ran) EXPECT_ACCEPTED(false); thwart_rx_non_initial_requests(); - if (net->a5_encryption_mask > 0x1) { - /* Encryption enabled */ + if (encryption) { if (via_ran == OSMO_RAT_GERAN_A) { btw("Test code not implemented"); OSMO_ASSERT(false); @@ -327,8 +326,6 @@ static void _test_umts_authen(enum osmo_rat_type via_ran) static void test_umts_authen_geran() { comment_start(); - /* A5/0 = no encryption */ - net->a5_encryption_mask = A5_0; _test_umts_authen(OSMO_RAT_GERAN_A); comment_end(); } @@ -336,8 +333,7 @@ static void test_umts_authen_geran() static void test_umts_authen_utran() { comment_start(); - /* A5/0 = no encryption; so far the A5 setting also triggers UTRAN encryption */ - net->a5_encryption_mask = A5_0; + net->uea_encryption = false; _test_umts_authen(OSMO_RAT_UTRAN_IU); comment_end(); } @@ -345,8 +341,7 @@ static void test_umts_authen_utran() static void test_umts_auth_ciph_utran() { comment_start(); - /* A5/0 + A5/3 = encryption enabled; so far the A5 setting also triggers UTRAN encryption */ - net->a5_encryption_mask = A5_0_3; + net->uea_encryption = true; _test_umts_authen(OSMO_RAT_UTRAN_IU); comment_end(); } @@ -365,6 +360,8 @@ 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); net->authentication_required = true; net->vlr->cfg.assign_tmsi = true; @@ -519,8 +516,7 @@ static void _test_umts_authen_resync(enum osmo_rat_type via_ran) VERBOSE_ASSERT(auth_request_sent, == true, "%d"); VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d"); - if (net->a5_encryption_mask > 0x1) { - /* Encryption enabled */ + if (encryption) { if (via_ran == OSMO_RAT_GERAN_A) { btw("Test code not implemented"); OSMO_ASSERT(false); @@ -585,8 +581,6 @@ static void _test_umts_authen_resync(enum osmo_rat_type via_ran) static void test_umts_authen_resync_geran() { comment_start(); - /* A5/0 = no encryption */ - net->a5_encryption_mask = A5_0; _test_umts_authen_resync(OSMO_RAT_GERAN_A); comment_end(); } @@ -594,8 +588,7 @@ static void test_umts_authen_resync_geran() static void test_umts_authen_resync_utran() { comment_start(); - /* A5/0 = no encryption; so far the A5 setting also triggers UTRAN encryption */ - net->a5_encryption_mask = A5_0; + net->uea_encryption = false; _test_umts_authen_resync(OSMO_RAT_UTRAN_IU); comment_end(); } @@ -603,8 +596,7 @@ static void test_umts_authen_resync_utran() static void test_umts_auth_ciph_resync_utran() { comment_start(); - /* A5/0 + A5/3 = encryption enabled; so far the A5 setting also triggers UTRAN encryption */ - net->a5_encryption_mask = A5_0_3; + net->uea_encryption = true; _test_umts_authen_resync(OSMO_RAT_UTRAN_IU); comment_end(); } @@ -698,8 +690,6 @@ static void _test_umts_authen_too_short_res(enum osmo_rat_type via_ran) static void test_umts_authen_too_short_res_geran() { comment_start(); - /* A5/0 = no encryption */ - net->a5_encryption_mask = A5_0; _test_umts_authen_too_short_res(OSMO_RAT_GERAN_A); comment_end(); } @@ -707,8 +697,6 @@ static void test_umts_authen_too_short_res_geran() static void test_umts_authen_too_short_res_utran() { comment_start(); - /* A5/0 + A5/3 = encryption enabled; so far the A5 setting also triggers UTRAN encryption */ - net->a5_encryption_mask = A5_0_3; _test_umts_authen_too_short_res(OSMO_RAT_UTRAN_IU); comment_end(); } @@ -802,8 +790,6 @@ static void _test_umts_authen_too_long_res(enum osmo_rat_type via_ran) static void test_umts_authen_too_long_res_geran() { comment_start(); - /* A5/0 = no encryption */ - net->a5_encryption_mask = A5_0; _test_umts_authen_too_long_res(OSMO_RAT_GERAN_A); comment_end(); } @@ -811,8 +797,6 @@ static void test_umts_authen_too_long_res_geran() static void test_umts_authen_too_long_res_utran() { comment_start(); - /* A5/0 + A5/3 = encryption enabled; so far the A5 setting also triggers UTRAN encryption */ - net->a5_encryption_mask = A5_0_3; _test_umts_authen_too_long_res(OSMO_RAT_UTRAN_IU); comment_end(); } @@ -911,8 +895,6 @@ static void _test_umts_authen_only_sres(enum osmo_rat_type via_ran) static void test_umts_authen_only_sres_geran() { comment_start(); - /* A5/0 = no encryption */ - net->a5_encryption_mask = A5_0; _test_umts_authen_only_sres(OSMO_RAT_GERAN_A); comment_end(); } @@ -920,8 +902,6 @@ static void test_umts_authen_only_sres_geran() static void test_umts_authen_only_sres_utran() { comment_start(); - /* A5/0 + A5/3 = encryption enabled; so far the A5 setting also triggers UTRAN encryption */ - net->a5_encryption_mask = A5_0_3; _test_umts_authen_only_sres(OSMO_RAT_UTRAN_IU); comment_end(); } diff --git a/tests/msc_vlr/msc_vlr_tests.h b/tests/msc_vlr/msc_vlr_tests.h index 4330ea869..9df9cf049 100644 --- a/tests/msc_vlr/msc_vlr_tests.h +++ b/tests/msc_vlr/msc_vlr_tests.h @@ -32,9 +32,6 @@ #include #include -#define A5_0 (1 << 0) -#define A5_0_3 ((1 << 0) | (1 << 3)) - extern bool _log_lines; #define _log(fmt, args...) do { \ if (_log_lines) \ diff --git a/tests/test_nodes.vty b/tests/test_nodes.vty index fb7b1c529..0ad390fc5 100644 --- a/tests/test_nodes.vty +++ b/tests/test_nodes.vty @@ -17,6 +17,7 @@ OsmoMSC(config-net)# list short name NAME long name NAME encryption a5 <0-3> [<0-3>] [<0-3>] [<0-3>] + encryption uea <0-2> [<0-2>] [<0-2>] authentication (optional|required) rrlp mode (none|ms-based|ms-preferred|ass-preferred) mm info (0|1) @@ -26,6 +27,21 @@ OsmoMSC(config-net)# list periodic location update <6-1530> no periodic location update +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'. + +OsmoMSC(config-net)# encryption uea ? + <0-2> UEAn Algorithm Number +OsmoMSC(config-net)# encryption uea 0 ? + [<0-2>] UEAn Algorithm Number +OsmoMSC(config-net)# encryption uea 0 1 ? + [<0-2>] UEAn Algorithm Number +OsmoMSC(config-net)# encryption uea 0 1 2 ? + + OsmoMSC(config-net)# exit OsmoMSC(config)# msc OsmoMSC(config-msc)# list @@ -130,6 +146,7 @@ network short name OsmoMSC long name OsmoMSC encryption a5 0 + encryption uea 1 2 authentication optional rrlp mode none mm info 1 @@ -157,3 +174,52 @@ sgs local-ip 0.0.0.0 vlr-name vlr.example.net end + +OsmoMSC# configure terminal +OsmoMSC(config)# network +OsmoMSC(config-net)# encryption uea 0 +OsmoMSC(config-net)# show running-config +... + encryption uea 0 +... + +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 +... + +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 +... + +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 +... + +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 +... + +OsmoMSC(config-net)# encryption uea 1 2 +OsmoMSC(config-net)# show running-config +... + encryption uea 1 2 +...