lynxis lazus submitted this change.
libvlr: allow to use the same key slot for multiple ciphering commands
An established security context can be used multiple times.
In difference to re-use of the same auth tuple, which is a serious security
flaw, re-using a security context is completely fine as long the context
is not used forever.
Change-Id: I5c628ef4b43f7c22f62d1405cbe1f717a7918548
---
M include/osmocom/vlr/vlr.h
M src/libmsc/msc_vty.c
M src/libvlr/vlr_access_req_fsm.c
M src/libvlr/vlr_auth_fsm.c
M src/libvlr/vlr_auth_fsm.h
M src/libvlr/vlr_lu_fsm.c
M tests/msc_vlr/msc_vlr_test_authen_reuse.c
M tests/msc_vlr/msc_vlr_tests.c
8 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/include/osmocom/vlr/vlr.h b/include/osmocom/vlr/vlr.h
index 9fe2642..eac99b0 100644
--- a/include/osmocom/vlr/vlr.h
+++ b/include/osmocom/vlr/vlr.h
@@ -83,6 +83,7 @@
struct vlr_auth_tuple {
int auth_use_count;
+ int ciph_use_count;
int key_seq;
struct osmo_auth_vector vec;
};
@@ -282,6 +283,8 @@
bool check_imei_rqd;
int auth_tuple_max_reuse_count;
bool auth_reuse_old_sets_on_error;
+ /* how often a security context / cksq is re-used before a new auth tuple is used */
+ int ciph_sec_ctx_max_reuse;
bool parq_retrieve_imsi;
bool is_ps;
uint8_t nri_bitlen;
diff --git a/src/libmsc/msc_vty.c b/src/libmsc/msc_vty.c
index ef5c91e..a5de12f 100644
--- a/src/libmsc/msc_vty.c
+++ b/src/libmsc/msc_vty.c
@@ -532,7 +532,9 @@
"Configure authentication tuple re-use\n"
"0 to use each auth tuple at most once (default), >0 to limit re-use, -1 to re-use infinitely (vulnerable!).\n")
{
- gsmnet->vlr->cfg.auth_tuple_max_reuse_count = atoi(argv[0]);
+ int count = atoi(argv[0]);
+ gsmnet->vlr->cfg.auth_tuple_max_reuse_count = count;
+ gsmnet->vlr->cfg.ciph_sec_ctx_max_reuse = count;
return CMD_SUCCESS;
}
diff --git a/src/libvlr/vlr_access_req_fsm.c b/src/libvlr/vlr_access_req_fsm.c
index b1a75fd..5d2b7f9 100644
--- a/src/libvlr/vlr_access_req_fsm.c
+++ b/src/libvlr/vlr_access_req_fsm.c
@@ -322,6 +322,11 @@
return;
}
+ if (!auth_ciph_sec_ctx_use(vsub, par->key_seq)) {
+ LOGPFSML(fi, LOGL_ERROR, "Cannot start ciphering, auth tuple not available, even when it should!\n");
+ proc_arq_fsm_done(fi, GSM48_REJECT_NETWORK_FAILURE);
+ }
+
if (vlr_set_ciph_mode(vsub->vlr, fi, par->msc_conn_ref,
vsub->sec_ctx,
vsub->vlr->cfg.retrieve_imeisv_ciphered)) {
@@ -341,7 +346,7 @@
* are defined in 3GPP TS 33.102 */
/* For now we use a default value passed in to vlr_lu_fsm(). */
return par->authentication_required ||
- (par->is_ciphering_to_be_attempted && !auth_try_reuse_tuple(par->vsub, par->key_seq));
+ (par->is_ciphering_to_be_attempted && !auth_ciph_sec_ctx_is_usable(par->vsub, par->key_seq));
}
/* after the IMSI is known */
@@ -458,6 +463,9 @@
switch (event) {
case PR_ARQ_E_AUTH_RES:
/* Node 2 */
+ OSMO_ASSERT(par->vsub);
+ OSMO_ASSERT(par->vsub->last_tuple);
+ par->key_seq = par->vsub->last_tuple->key_seq;
_proc_arq_vlr_node2(fi);
return;
diff --git a/src/libvlr/vlr_auth_fsm.c b/src/libvlr/vlr_auth_fsm.c
index 176ef22..192e390 100644
--- a/src/libvlr/vlr_auth_fsm.c
+++ b/src/libvlr/vlr_auth_fsm.c
@@ -681,6 +681,36 @@
return fi;
}
+bool auth_ciph_sec_ctx_is_usable(const struct vlr_subscr *vsub, uint8_t key_seq)
+{
+ int max_reuse_count = vsub->vlr->cfg.ciph_sec_ctx_max_reuse;
+ struct vlr_auth_tuple *at = vsub->last_tuple;
+
+ if (key_seq == 0x7) /* No key available */
+ return false;
+ if (!at)
+ return false;
+ if ((max_reuse_count >= 0) && (at->ciph_use_count > max_reuse_count))
+ return false;
+ if (at->key_seq != key_seq)
+ return false;
+
+ return true;
+}
+
+bool auth_ciph_sec_ctx_use(struct vlr_subscr *vsub, uint8_t key_seq)
+{
+ struct vlr_auth_tuple *at = vsub->last_tuple;
+
+ if (!auth_ciph_sec_ctx_is_usable(vsub, key_seq))
+ return false;
+
+ OSMO_ASSERT(at);
+ at->ciph_use_count++;
+
+ return true;
+}
+
bool auth_try_reuse_tuple(struct vlr_subscr *vsub, uint8_t key_seq)
{
int max_reuse_count = vsub->vlr->cfg.auth_tuple_max_reuse_count;
diff --git a/src/libvlr/vlr_auth_fsm.h b/src/libvlr/vlr_auth_fsm.h
index 1cb25b6..7a45a1a 100644
--- a/src/libvlr/vlr_auth_fsm.h
+++ b/src/libvlr/vlr_auth_fsm.h
@@ -40,3 +40,5 @@
void vlr_auth_fsm_init(bool is_ps);
void vlr_auth_fsm_set_log_subsys(int log_level);
bool auth_try_reuse_tuple(struct vlr_subscr *vsub, uint8_t key_seq);
+bool auth_ciph_sec_ctx_is_usable(const struct vlr_subscr *vsub, uint8_t key_seq);
+bool auth_ciph_sec_ctx_use(struct vlr_subscr *vsub, uint8_t key_seq);
diff --git a/src/libvlr/vlr_lu_fsm.c b/src/libvlr/vlr_lu_fsm.c
index f286450..d3aaf3a 100644
--- a/src/libvlr/vlr_lu_fsm.c
+++ b/src/libvlr/vlr_lu_fsm.c
@@ -964,6 +964,12 @@
return;
}
+ if (!auth_ciph_sec_ctx_use(vsub, vsub->last_tuple->key_seq)) {
+ LOGPFSML(fi, LOGL_ERROR, "Cannot start ciphering, auth tuple not available, even when it should!\n");
+ lu_fsm_failure(fi, GSM48_REJECT_NETWORK_FAILURE);
+ return;
+ }
+
if (vlr_set_ciph_mode(vsub->vlr, fi, lfp->msc_conn_ref,
vsub->sec_ctx,
vsub->vlr->cfg.retrieve_imeisv_ciphered)) {
diff --git a/tests/msc_vlr/msc_vlr_test_authen_reuse.c b/tests/msc_vlr/msc_vlr_test_authen_reuse.c
index a3be7b6..a75f4fc 100644
--- a/tests/msc_vlr/msc_vlr_test_authen_reuse.c
+++ b/tests/msc_vlr/msc_vlr_test_authen_reuse.c
@@ -38,6 +38,7 @@
net->authentication_required = true;
net->vlr->cfg.assign_tmsi = true;
net->vlr->cfg.auth_tuple_max_reuse_count = set_max_reuse_count;
+ net->vlr->cfg.ciph_sec_ctx_max_reuse = set_max_reuse_count;
net->vlr->cfg.auth_reuse_old_sets_on_error = false;
rx_from_ran = via_ran;
diff --git a/tests/msc_vlr/msc_vlr_tests.c b/tests/msc_vlr/msc_vlr_tests.c
index c609381..008edfe 100644
--- a/tests/msc_vlr/msc_vlr_tests.c
+++ b/tests/msc_vlr/msc_vlr_tests.c
@@ -679,6 +679,7 @@
net->vlr->cfg.retrieve_imeisv_early = false;
net->vlr->cfg.retrieve_imeisv_ciphered = false;
net->vlr->cfg.auth_tuple_max_reuse_count = 0;
+ net->vlr->cfg.ciph_sec_ctx_max_reuse = 0;
net->vlr->cfg.auth_reuse_old_sets_on_error = false;
rx_from_ran = OSMO_RAT_GERAN_A;
To view, visit change 43480. To unsubscribe, or for help writing mail filters, visit settings.