diff --git a/include/osmocom/msc/msc_a.h b/include/osmocom/msc/msc_a.h index ad41d731b..0bd72cbb1 100644 --- a/include/osmocom/msc/msc_a.h +++ b/include/osmocom/msc/msc_a.h @@ -181,6 +181,7 @@ void msc_a_pending_cm_service_req_add(struct msc_a *msc_a, enum osmo_cm_service_ unsigned int msc_a_pending_cm_service_req_count(struct msc_a *msc_a, enum osmo_cm_service_type type); void msc_a_pending_cm_service_req_del(struct msc_a *msc_a, enum osmo_cm_service_type type); bool msc_a_try_ciphering(const struct msc_a *msc_a); +bool msc_a_require_ciphering(const struct msc_a *msc_a); #define msc_a_ran_down(A,B,C) \ _msc_a_ran_down(A,B,C, __FILE__, __LINE__) diff --git a/include/osmocom/msc/vlr.h b/include/osmocom/msc/vlr.h index db9c72bff..8f2417ad1 100644 --- a/include/osmocom/msc/vlr.h +++ b/include/osmocom/msc/vlr.h @@ -300,6 +300,7 @@ vlr_loc_update(struct osmo_fsm_inst *parent, const struct osmo_location_area_id *new_lai, bool authentication_required, bool try_ciphering, + bool ciphering_required, uint8_t key_seq, bool is_r99, bool is_utran, bool assign_tmsi); @@ -464,6 +465,7 @@ vlr_proc_acc_req(struct osmo_fsm_inst *parent, const struct osmo_location_area_id *lai, bool authentication_required, bool try_ciphering, + bool ciphering_required, uint8_t key_seq, bool is_r99, bool is_utran); diff --git a/src/libmsc/gsm_04_08.c b/src/libmsc/gsm_04_08.c index 3c60b1f36..af20b389c 100644 --- a/src/libmsc/gsm_04_08.c +++ b/src/libmsc/gsm_04_08.c @@ -418,6 +418,7 @@ static int mm_rx_loc_upd_req(struct msc_a *msc_a, struct msgb *msg) &old_lai, &msc_a->via_cell.lai, is_utran || net->authentication_required, msc_a_try_ciphering(msc_a), + msc_a_require_ciphering(msc_a), lu->key_seq, osmo_gsm48_classmark1_is_r99(&lu->classmark1), is_utran, @@ -819,6 +820,7 @@ int gsm48_rx_mm_serv_req(struct msc_a *msc_a, struct msgb *msg) &mi, &msc_a->via_cell.lai, is_utran || net->authentication_required, msc_a_try_ciphering(msc_a), + msc_a_require_ciphering(msc_a), req->cipher_key_seq, osmo_gsm48_classmark2_is_r99(cm2, cm2_len), is_utran); @@ -945,6 +947,7 @@ static int gsm48_rx_cm_reest_req(struct msc_a *msc_a, struct msgb *msg) &mi, &msc_a->via_cell.lai, is_utran || net->authentication_required, msc_a_try_ciphering(msc_a), + msc_a_require_ciphering(msc_a), req->cipher_key_seq, osmo_gsm48_classmark2_is_r99(cm2, cm2_len), is_utran); @@ -1307,6 +1310,7 @@ static int gsm48_rx_rr_pag_resp(struct msc_a *msc_a, struct msgb *msg) VLR_PR_ARQ_T_PAGING_RESP, 0, &mi, &msc_a->via_cell.lai, is_utran || net->authentication_required, msc_a_try_ciphering(msc_a), + msc_a_require_ciphering(msc_a), 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 fad5b77eb..7ce70c93e 100644 --- a/src/libmsc/msc_a.c +++ b/src/libmsc/msc_a.c @@ -116,6 +116,18 @@ bool msc_a_try_ciphering(const struct msc_a *msc_a) return net->a5_encryption_mask > 0x1; } +bool msc_a_require_ciphering(const struct msc_a *msc_a) +{ + struct gsm_network *net = msc_a_net(msc_a); + bool is_utran = (msc_a->c.ran->type == OSMO_RAT_UTRAN_IU); + if (is_utran) + return net->uea_encryption_mask + && ((net->uea_encryption_mask & (1 << OSMO_UTRAN_UEA0)) == 0); + else + return net->a5_encryption_mask + && ((net->a5_encryption_mask & 0x1) == 0); +} + static void update_counters(struct osmo_fsm_inst *fi, bool conn_accepted) { struct msc_a *msc_a = fi->priv; diff --git a/src/libvlr/vlr_access_req_fsm.c b/src/libvlr/vlr_access_req_fsm.c index 5b8d9bb23..267220433 100644 --- a/src/libvlr/vlr_access_req_fsm.c +++ b/src/libvlr/vlr_access_req_fsm.c @@ -67,7 +67,12 @@ struct proc_arq_priv { uint32_t tmsi; struct osmo_location_area_id lai; bool authentication_required; + /* try_ciphering: true when any A5/n > 0 are enabled. Ciphering is allowed, always attempt to get Auth Info from + * the HLR. */ bool try_ciphering; + /* ciphering_required: true when A5/0 is disabled. If we cannot get Auth Info from the HLR, reject the + * subscriber. */ + bool ciphering_required; uint8_t key_seq; bool is_r99; bool is_utran; @@ -635,12 +640,16 @@ vlr_proc_acc_req(struct osmo_fsm_inst *parent, const struct osmo_location_area_id *lai, bool authentication_required, bool try_ciphering, + bool ciphering_required, uint8_t key_seq, bool is_r99, bool is_utran) { struct osmo_fsm_inst *fi; struct proc_arq_priv *par; + if (ciphering_required) + OSMO_ASSERT(try_ciphering); + fi = osmo_fsm_inst_alloc_child(&proc_arq_vlr_fsm, parent, parent_event_failure); if (!fi) @@ -658,6 +667,7 @@ vlr_proc_acc_req(struct osmo_fsm_inst *parent, par->parent_event_data = parent_event_data; par->authentication_required = authentication_required; par->try_ciphering = try_ciphering; + par->ciphering_required = ciphering_required; par->key_seq = key_seq; par->is_r99 = is_r99; par->is_utran = is_utran; diff --git a/src/libvlr/vlr_lu_fsm.c b/src/libvlr/vlr_lu_fsm.c index e2fc9466b..eaf3d36e9 100644 --- a/src/libvlr/vlr_lu_fsm.c +++ b/src/libvlr/vlr_lu_fsm.c @@ -676,7 +676,12 @@ struct lu_fsm_priv { struct osmo_location_area_id old_lai; struct osmo_location_area_id new_lai; bool authentication_required; + /* try_ciphering: true when any A5/n > 0 are enabled. Ciphering is allowed, always attempt to get Auth Info from + * the HLR. */ bool try_ciphering; + /* ciphering_required: true when A5/0 is disabled. If we cannot get Auth Info from the HLR, reject the + * subscriber. */ + bool ciphering_required; uint8_t key_seq; bool is_r99; bool is_utran; @@ -1476,6 +1481,7 @@ vlr_loc_update(struct osmo_fsm_inst *parent, const struct osmo_location_area_id *new_lai, bool authentication_required, bool try_ciphering, + bool ciphering_required, uint8_t key_seq, bool is_r99, bool is_utran, bool assign_tmsi) @@ -1483,6 +1489,9 @@ vlr_loc_update(struct osmo_fsm_inst *parent, struct osmo_fsm_inst *fi; struct lu_fsm_priv *lfp; + if (ciphering_required) + OSMO_ASSERT(try_ciphering); + fi = osmo_fsm_inst_alloc_child(&vlr_lu_fsm, parent, parent_event_failure); if (!fi) return NULL; @@ -1500,6 +1509,7 @@ vlr_loc_update(struct osmo_fsm_inst *parent, lfp->parent_event_data = parent_event_data; lfp->authentication_required = authentication_required; lfp->try_ciphering = try_ciphering; + lfp->ciphering_required = ciphering_required; lfp->key_seq = key_seq; lfp->is_r99 = is_r99; lfp->is_utran = is_utran;