aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2017-12-23 19:30:32 +0100
committerHarald Welte <laforge@gnumonks.org>2018-01-28 00:09:42 +0000
commit7b222aa1062aae786c92ea649d945ae8d86bbba2 (patch)
treecd6429a67e8d31508ef7eb2b3201bf3524cd7208
parent71c51df07dfbc60cb41cb43385576a9d89c0c269 (diff)
Permit a set of multiple different A5 ciphers
So far, the administrator had to pick one particular cipher which would then be used throughout all subscribers/phones. This is a bit impractical, as e.g. not all phones support A5/3. Extend the VTY command syntax in a backwards-compatible way to permit for multiple ciphers. NOTE: Like the previous code, OsmoMSC does *not yet check* whether the configured cipher is compatible with the MS capabilities as reported in CLASSMARK! The network hence might choose an algorithm not supported by the phone. Fixing this is subject to another patch. Closes: OS#2460 Change-Id: I79a4e2892eb5fbecc3d84e11dceffb7149db264b
-rw-r--r--include/osmocom/msc/gsm_data.h3
-rw-r--r--src/libcommon-cs/common_cs.c2
-rw-r--r--src/libcommon-cs/common_cs_vty.c15
-rw-r--r--src/libmsc/gsm_04_08.c15
-rw-r--r--src/libmsc/msc_vty.c10
-rw-r--r--tests/msc_vlr/msc_vlr_test_gsm_ciph.c10
-rw-r--r--tests/msc_vlr/msc_vlr_test_gsm_ciph.err18
-rw-r--r--tests/msc_vlr/msc_vlr_tests.c6
8 files changed, 49 insertions, 30 deletions
diff --git a/include/osmocom/msc/gsm_data.h b/include/osmocom/msc/gsm_data.h
index e9871362b..27324d7b6 100644
--- a/include/osmocom/msc/gsm_data.h
+++ b/include/osmocom/msc/gsm_data.h
@@ -299,7 +299,8 @@ struct gsm_network {
regex_t authorized_regexp;
char *authorized_reg_str;
enum gsm48_reject_value reject_cause;
- int a5_encryption;
+ /* bit-mask of permitted encryption algorithms. LSB=A5/0, MSB=A5/7 */
+ uint8_t a5_encryption_mask;
bool authentication_required;
int neci;
int send_mm_info;
diff --git a/src/libcommon-cs/common_cs.c b/src/libcommon-cs/common_cs.c
index 41c456e7a..170b62a23 100644
--- a/src/libcommon-cs/common_cs.c
+++ b/src/libcommon-cs/common_cs.c
@@ -56,6 +56,8 @@ struct gsm_network *gsm_network_init(void *ctx,
net->country_code = country_code;
net->network_code = network_code;
+ /* Permit a compile-time default of A5/3 and A5/1 */
+ net->a5_encryption_mask = (1 << 3) | (1 << 1);
/* Use 30 min periodic update interval as sane default */
net->t3212 = 5;
diff --git a/src/libcommon-cs/common_cs_vty.c b/src/libcommon-cs/common_cs_vty.c
index 4754531b4..8c9f1275c 100644
--- a/src/libcommon-cs/common_cs_vty.c
+++ b/src/libcommon-cs/common_cs_vty.c
@@ -155,15 +155,20 @@ DEFUN(cfg_net_reject_cause,
DEFUN(cfg_net_encryption,
cfg_net_encryption_cmd,
- "encryption a5 (0|1|2|3)",
+ "encryption a5 <0-3> [<0-3>] [<0-3>] [<0-3>]",
"Encryption options\n"
- "A5 encryption\n" "A5/0: No encryption\n"
- "A5/1: Encryption\n" "A5/2: Export-grade Encryption\n"
- "A5/3: 'New' Secure Encryption\n")
+ "GSM A5 Air Interface Encryption\n"
+ "A5/n Algorithm Number\n"
+ "A5/n Algorithm Number\n"
+ "A5/n Algorithm Number\n"
+ "A5/n Algorithm Number\n")
{
struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+ unsigned int i;
- gsmnet->a5_encryption = atoi(argv[0]);
+ gsmnet->a5_encryption_mask = 0;
+ for (i = 0; i < argc; i++)
+ gsmnet->a5_encryption_mask |= (1 << atoi(argv[i]));
return CMD_SUCCESS;
}
diff --git a/src/libmsc/gsm_04_08.c b/src/libmsc/gsm_04_08.c
index c37aeb758..3574583a6 100644
--- a/src/libmsc/gsm_04_08.c
+++ b/src/libmsc/gsm_04_08.c
@@ -339,7 +339,7 @@ int mm_rx_loc_upd_req(struct gsm_subscriber_connection *conn, struct msgb *msg)
net->vlr, conn, vlr_lu_type, tmsi, imsi,
&old_lai, &new_lai,
is_utran || conn->network->authentication_required,
- is_utran || conn->network->a5_encryption,
+ is_utran || conn->network->a5_encryption_mask > 0x01,
classmark_is_r99(&conn->classmark),
is_utran,
net->vlr->cfg.assign_tmsi);
@@ -723,7 +723,7 @@ int gsm48_rx_mm_serv_req(struct gsm_subscriber_connection *conn, struct msgb *ms
net->vlr, conn,
VLR_PR_ARQ_T_CM_SERV_REQ, mi-1, &lai,
is_utran || conn->network->authentication_required,
- is_utran || conn->network->a5_encryption,
+ is_utran || conn->network->a5_encryption_mask > 0x01,
classmark_is_r99(&conn->classmark),
is_utran);
@@ -1127,7 +1127,7 @@ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct m
net->vlr, conn,
VLR_PR_ARQ_T_PAGING_RESP, mi_lv, &lai,
is_utran || conn->network->authentication_required,
- is_utran || conn->network->a5_encryption,
+ is_utran || conn->network->a5_encryption_mask > 0x01,
classmark_is_r99(&conn->classmark),
is_utran);
@@ -3447,10 +3447,15 @@ static int msc_vlr_set_ciph_mode(void *msc_conn_ref,
DEBUGP(DMM, "-> CIPHER MODE COMMAND %s\n",
vlr_subscr_name(conn->vsub));
{
+ struct gsm_network *net = conn->network;
struct gsm0808_encrypt_info ei;
+ int i, j = 0;
- ei.perm_algo[0] = vlr_ciph_to_gsm0808_alg_id(conn->network->a5_encryption);
- ei.perm_algo_len = 1;
+ for (i = 0; i < 8; i++) {
+ if (net->a5_encryption_mask & (1 << i))
+ ei.perm_algo[j++] = vlr_ciph_to_gsm0808_alg_id(i);
+ }
+ ei.perm_algo_len = j;
/* In case of UMTS AKA, the Kc for ciphering must be derived from the 3G auth
* tokens. tuple->vec.kc was calculated from the GSM algorithm and is not
diff --git a/src/libmsc/msc_vty.c b/src/libmsc/msc_vty.c
index 82608c642..faf17ec3c 100644
--- a/src/libmsc/msc_vty.c
+++ b/src/libmsc/msc_vty.c
@@ -1,7 +1,7 @@
/* MSC interface to quagga VTY */
/* (C) 2016 by sysmocom s.m.f.c. GmbH <info@sysmocom.de>
* Based on OpenBSC interface to quagga VTY (libmsc/vty_interface_layer3.c)
- * (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2009-2017 by Harald Welte <laforge@gnumonks.org>
* (C) 2009-2011 by Holger Hans Peter Freyther
* All Rights Reserved
*
@@ -160,6 +160,7 @@ static int config_write_msc(struct vty *vty)
static int config_write_net(struct vty *vty)
{
struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+ int i;
vty_out(vty, "network%s", VTY_NEWLINE);
vty_out(vty, " network country code %u%s", gsmnet->country_code, VTY_NEWLINE);
@@ -169,7 +170,12 @@ static int config_write_net(struct vty *vty)
vty_out(vty, " auth policy %s%s", gsm_auth_policy_name(gsmnet->auth_policy), VTY_NEWLINE);
vty_out(vty, " location updating reject cause %u%s",
gsmnet->reject_cause, VTY_NEWLINE);
- vty_out(vty, " encryption a5 %u%s", gsmnet->a5_encryption, VTY_NEWLINE);
+ vty_out(vty, " encryption a5");
+ for (i = 0; i < 8; i++) {
+ if (gsmnet->a5_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", rrlp_mode_name(gsmnet->rrlp.mode),
diff --git a/tests/msc_vlr/msc_vlr_test_gsm_ciph.c b/tests/msc_vlr/msc_vlr_test_gsm_ciph.c
index e0bd9673a..42e620a7b 100644
--- a/tests/msc_vlr/msc_vlr_test_gsm_ciph.c
+++ b/tests/msc_vlr/msc_vlr_test_gsm_ciph.c
@@ -31,7 +31,7 @@ void test_ciph()
comment_start();
/* implicit: net->authentication_required = true; */
- net->a5_encryption = VLR_CIPH_A5_1;
+ net->a5_encryption_mask = (1 << 1);
btw("Location Update request causes a GSUP Send Auth Info request to HLR");
lu_result_sent = RES_NONE;
@@ -243,7 +243,7 @@ void test_ciph_tmsi()
comment_start();
/* implicit: net->authentication_required = true; */
- net->a5_encryption = VLR_CIPH_A5_1;
+ net->a5_encryption_mask = (1 << 1);
net->vlr->cfg.assign_tmsi = true;
btw("Location Update request causes a GSUP Send Auth Info request to HLR");
@@ -482,7 +482,7 @@ void test_ciph_imei()
comment_start();
/* implicit: net->authentication_required = true; */
- net->a5_encryption = VLR_CIPH_A5_1;
+ net->a5_encryption_mask = (1 << 1);
net->vlr->cfg.check_imei_rqd = true;
btw("Location Update request causes a GSUP Send Auth Info request to HLR");
@@ -584,7 +584,7 @@ void test_ciph_imeisv()
comment_start();
/* implicit: net->authentication_required = true; */
- net->a5_encryption = VLR_CIPH_A5_1;
+ net->a5_encryption_mask = (1 << 1);
net->vlr->cfg.retrieve_imeisv_ciphered = true;
btw("Location Update request causes a GSUP Send Auth Info request to HLR");
@@ -682,7 +682,7 @@ void test_ciph_tmsi_imei()
comment_start();
/* implicit: net->authentication_required = true; */
- net->a5_encryption = VLR_CIPH_A5_1;
+ net->a5_encryption_mask = (1 << 1);
net->vlr->cfg.assign_tmsi = true;
net->vlr->cfg.check_imei_rqd = true;
diff --git a/tests/msc_vlr/msc_vlr_test_gsm_ciph.err b/tests/msc_vlr/msc_vlr_test_gsm_ciph.err
index 0e9d99613..cb9091cfc 100644
--- a/tests/msc_vlr/msc_vlr_test_gsm_ciph.err
+++ b/tests/msc_vlr/msc_vlr_test_gsm_ciph.err
@@ -62,7 +62,7 @@ DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode
-- sending Ciphering Mode Command for IMSI:901700000004620: cipher=VLR_CIPH_A5_1 kc=61855fb81fc2a800 retrieve_imeisv=0
+- sending Ciphering Mode Command for IMSI:901700000004620: ciphers=0x02 kc=61855fb81fc2a800 retrieve_imeisv=0
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_CIPH
DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
DREF IMSI:901700000004620: MSC conn use - dtap == 1 (0x4)
@@ -225,7 +225,7 @@ DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: Received E
DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: got VLR_AUTH_RES_PASSED
DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2()
DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: Set Ciphering Mode
-- sending Ciphering Mode Command for MSISDN:46071: cipher=VLR_CIPH_A5_1 kc=07fa7502e07e1c00 retrieve_imeisv=0
+- sending Ciphering Mode Command for MSISDN:46071: ciphers=0x02 kc=07fa7502e07e1c00 retrieve_imeisv=0
DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_WAIT_CIPH
DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
DREF MSISDN:46071: MSC conn use - dtap == 1 (0x4)
@@ -370,7 +370,7 @@ DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: Received E
DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: got VLR_AUTH_RES_PASSED
DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2()
DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: Set Ciphering Mode
-- sending Ciphering Mode Command for MSISDN:46071: cipher=VLR_CIPH_A5_1 kc=e2b234f807886400 retrieve_imeisv=0
+- sending Ciphering Mode Command for MSISDN:46071: ciphers=0x02 kc=e2b234f807886400 retrieve_imeisv=0
DVLR Process_Access_Request_VLR(901700000004620){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_WAIT_CIPH
DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
DREF MSISDN:46071: MSC conn use - dtap == 1 (0x4)
@@ -547,7 +547,7 @@ DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode
-- sending Ciphering Mode Command for IMSI:901700000004620: cipher=VLR_CIPH_A5_1 kc=61855fb81fc2a800 retrieve_imeisv=0
+- sending Ciphering Mode Command for IMSI:901700000004620: ciphers=0x02 kc=61855fb81fc2a800 retrieve_imeisv=0
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_CIPH
DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
DREF IMSI:901700000004620: MSC conn use - dtap == 1 (0x4)
@@ -747,7 +747,7 @@ DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: Received Event PR
DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: got VLR_AUTH_RES_PASSED
DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2()
DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: Set Ciphering Mode
-- sending Ciphering Mode Command for MSISDN:46071: cipher=VLR_CIPH_A5_1 kc=07fa7502e07e1c00 retrieve_imeisv=0
+- sending Ciphering Mode Command for MSISDN:46071: ciphers=0x02 kc=07fa7502e07e1c00 retrieve_imeisv=0
DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_WAIT_CIPH
DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
DREF MSISDN:46071: MSC conn use - dtap == 1 (0x4)
@@ -892,7 +892,7 @@ DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: Received Event PR
DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: got VLR_AUTH_RES_PASSED
DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: _proc_arq_vlr_node2()
DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: Set Ciphering Mode
-- sending Ciphering Mode Command for MSISDN:46071: cipher=VLR_CIPH_A5_1 kc=e2b234f807886400 retrieve_imeisv=0
+- sending Ciphering Mode Command for MSISDN:46071: ciphers=0x02 kc=e2b234f807886400 retrieve_imeisv=0
DVLR Process_Access_Request_VLR(50462976){PR_ARQ_S_WAIT_AUTH}: state_chg to PR_ARQ_S_WAIT_CIPH
DMM MSISDN:46071: bump: conn still being established (SUBSCR_CONN_S_NEW)
DREF MSISDN:46071: MSC conn use - dtap == 1 (0x4)
@@ -1069,7 +1069,7 @@ DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode
-- sending Ciphering Mode Command for IMSI:901700000004620: cipher=VLR_CIPH_A5_1 kc=61855fb81fc2a800 retrieve_imeisv=0
+- sending Ciphering Mode Command for IMSI:901700000004620: ciphers=0x02 kc=61855fb81fc2a800 retrieve_imeisv=0
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_CIPH
DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
DREF IMSI:901700000004620: MSC conn use - dtap == 1 (0x4)
@@ -1290,7 +1290,7 @@ DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode
-- sending Ciphering Mode Command for IMSI:901700000004620: cipher=VLR_CIPH_A5_1 kc=61855fb81fc2a800 retrieve_imeisv=1
+- sending Ciphering Mode Command for IMSI:901700000004620: ciphers=0x02 kc=61855fb81fc2a800 retrieve_imeisv=1
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_CIPH
DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
DREF IMSI:901700000004620: MSC conn use - dtap == 1 (0x4)
@@ -1500,7 +1500,7 @@ DVLR VLR_Authenticate(901700000004620){VLR_SUB_AS_AUTHENTICATED}: Deallocated
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Received Event VLR_ULA_E_AUTH_RES
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: vlr_loc_upd_post_auth()
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: Set Ciphering Mode
-- sending Ciphering Mode Command for IMSI:901700000004620: cipher=VLR_CIPH_A5_1 kc=61855fb81fc2a800 retrieve_imeisv=0
+- sending Ciphering Mode Command for IMSI:901700000004620: ciphers=0x02 kc=61855fb81fc2a800 retrieve_imeisv=0
DVLR vlr_lu_fsm(901700000004620){VLR_ULA_S_WAIT_AUTH}: state_chg to VLR_ULA_S_WAIT_CIPH
DMM IMSI:901700000004620: bump: conn still being established (SUBSCR_CONN_S_NEW)
DREF IMSI:901700000004620: MSC conn use - dtap == 1 (0x4)
diff --git a/tests/msc_vlr/msc_vlr_tests.c b/tests/msc_vlr/msc_vlr_tests.c
index b8553b64b..e4adfe078 100644
--- a/tests/msc_vlr/msc_vlr_tests.c
+++ b/tests/msc_vlr/msc_vlr_tests.c
@@ -333,7 +333,7 @@ void clear_vlr()
}
net->authentication_required = false;
- net->a5_encryption = VLR_CIPH_NONE;
+ net->a5_encryption_mask = (1 << 0);
net->vlr->cfg.check_imei_rqd = false;
net->vlr->cfg.assign_tmsi = false;
net->vlr->cfg.retrieve_imeisv_early = false;
@@ -670,10 +670,10 @@ static int fake_vlr_tx_ciph_mode_cmd(void *msc_conn_ref, bool umts_aka, bool ret
struct gsm_subscriber_connection *conn = msc_conn_ref;
switch (conn->via_ran) {
case RAN_GERAN_A:
- btw("sending Ciphering Mode Command for %s: cipher=%s kc=%s"
+ btw("sending Ciphering Mode Command for %s: ciphers=0x%02x kc=%s"
" retrieve_imeisv=%d",
vlr_subscr_name(conn->vsub),
- vlr_ciph_name(conn->network->a5_encryption),
+ conn->network->a5_encryption_mask,
osmo_hexdump_nospc(conn->vsub->last_tuple->vec.kc, 8),
retrieve_imeisv);
break;