Validate the choosen UTRAN encryption algorithm

RANAP Security Command can include an encryption IE. If it includes
it the RNC can still ignore it (e.g. unsupported encryption) and
return the Security Command Complete with an choosen encryption IE:
"no encryption".
Validate the encryption element and ensure the encryption is included in
the encryption mask.

Closes: OS#4144
Change-Id: Icfc135c8b8ae862defe7114db492af600c26407f
This commit is contained in:
Alexander Couzens 2021-10-19 17:09:11 +02:00
parent 505a94a610
commit 2aaff7513b
8 changed files with 52 additions and 18 deletions

View File

@ -216,6 +216,12 @@ struct ran_msg {
* alg_id == 1 means A5/0 i.e. no encryption, alg_id == 4 means A5/3.
* alg_id == 0 means no such IE was present. */
uint8_t alg_id;
/*! utran integrity protection. 0..15 */
int16_t utran_integrity;
/*! utran_integrity is in encoded format:
* utran_integrity == -1 means no such IE was present
* utran_integrity == 0 means no encryption. */
int16_t utran_encryption;
const char *imeisv;
const struct tlv_p_entry *l3_msg;
} cipher_mode_complete;

View File

@ -1404,6 +1404,7 @@ static int msc_a_up_ho(struct msc_a *msc_a, const struct msc_a_ran_dec_data *d,
int msc_a_ran_dec_from_msc_i(struct msc_a *msc_a, struct msc_a_ran_dec_data *d)
{
struct vlr_subscr *vsub = msc_a_vsub(msc_a);
struct gsm_network *net = msc_a_net(msc_a);
const struct ran_msg *msg = d->ran_dec;
int rc = -99;
@ -1459,7 +1460,25 @@ int msc_a_ran_dec_from_msc_i(struct msc_a *msc_a, struct msc_a_ran_dec_data *d)
msc_a->geran_encr.alg_id = msg->cipher_mode_complete.alg_id;
LOG_MSC_A(msc_a, LOGL_DEBUG, "Cipher Mode Complete: chosen encryption algorithm: A5/%u\n",
msc_a->geran_encr.alg_id - 1);
};
}
if (msc_a->c.ran->type == OSMO_RAT_UTRAN_IU) {
int16_t utran_encryption;
/* utran: ensure chosen ciphering mode is allowed
* If the IE is missing (utran_encryption == -1), parse it as no encryption */
utran_encryption = msg->cipher_mode_complete.utran_encryption;
if (utran_encryption == -1)
utran_encryption = 0;
if ((net->uea_encryption_mask & (1 << utran_encryption)) == 0) {
/* cipher disallowed */
LOG_MSC_A(msc_a, LOGL_ERROR, "Cipher Mode Complete: RNC chosen forbidden ciphering UEA%d\n",
msg->cipher_mode_complete.utran_encryption);
vlr_subscr_rx_ciph_res(vsub, VLR_CIPH_REJECT);
rc = 0;
break;
}
}
vlr_subscr_rx_ciph_res(vsub, VLR_CIPH_COMPL);
rc = 0;

View File

@ -211,12 +211,20 @@ success:
ranap_free_rab_setupormodifieditemies(&setup_ies);
}
static void ran_iu_decode_security_mode_complete(struct ran_dec *ran_iu_decode)
static void ran_iu_decode_security_mode_complete(struct ran_dec *ran_iu_decode, const RANAP_SecurityModeCompleteIEs_t *ies)
{
struct ran_msg ran_dec_msg = {
.msg_type = RAN_MSG_CIPHER_MODE_COMPLETE,
.msg_name = "RANAP SecurityModeControl successfulOutcome",
.cipher_mode_complete = {
.utran_integrity = ies->chosenIntegrityProtectionAlgorithm,
.utran_encryption = -1,
},
};
if (ies->presenceMask & SECURITYMODECOMPLETEIES_RANAP_CHOSENENCRYPTIONALGORITHM_PRESENT)
ran_dec_msg.cipher_mode_complete.utran_encryption = ies->chosenEncryptionAlgorithm;
ran_decoded(ran_iu_decode, &ran_dec_msg);
}
@ -272,7 +280,7 @@ static void ran_iu_decode_ranap_msg(void *_ran_dec, ranap_message *message)
case RANAP_ProcedureCode_id_SecurityModeControl:
switch (message->direction) {
case RANAP_RANAP_PDU_PR_successfulOutcome:
ran_iu_decode_security_mode_complete(ran_iu_decode);
ran_iu_decode_security_mode_complete(ran_iu_decode, &message->msg.securityModeCompleteIEs);
return;
case RANAP_RANAP_PDU_PR_unsuccessfulOutcome:
ran_iu_decode_security_mode_reject(ran_iu_decode);

View File

@ -99,7 +99,7 @@ static void _test_auth_reuse(enum osmo_rat_type via_ran,
btw("MS sends SecurityModeControl acceptance, VLR accepts and sends GSUP LU Req to HLR");
gsup_expect_tx("04010809710000000156f0" CN_DOMAIN VLR_TO_HLR);
ms_sends_security_mode_complete();
ms_sends_security_mode_complete(1);
VERBOSE_ASSERT(gsup_tx_confirmed, == true, "%d");
VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
}
@ -170,7 +170,7 @@ static void _test_auth_reuse(enum osmo_rat_type via_ran,
VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
btw("MS sends SecurityModeControl acceptance, VLR accepts; above Ciphering is an implicit CM Service Accept");
ms_sends_security_mode_complete();
ms_sends_security_mode_complete(1);
VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
}
@ -239,7 +239,7 @@ static void _test_auth_reuse(enum osmo_rat_type via_ran,
VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
btw("MS sends SecurityModeControl acceptance, VLR accepts; above Ciphering is an implicit CM Service Accept");
ms_sends_security_mode_complete();
ms_sends_security_mode_complete(1);
VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
}

View File

@ -128,7 +128,7 @@ static void lu_utran_tmsi()
btw("MS sends SecurityModeControl acceptance, VLR accepts and sends GSUP LU Req to HLR");
gsup_expect_tx("04010809710000000156f0" CN_DOMAIN VLR_TO_HLR);
ms_sends_security_mode_complete();
ms_sends_security_mode_complete(1);
VERBOSE_ASSERT(gsup_tx_confirmed, == true, "%d");
VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
@ -197,7 +197,7 @@ static void test_call_mo()
VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
btw("MS sends SecurityModeControl acceptance, VLR accepts; above Ciphering is an implicit CM Service Accept");
ms_sends_security_mode_complete();
ms_sends_security_mode_complete(1);
VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
BTW("a call is initiated");
@ -317,7 +317,7 @@ static void test_call_mt()
btw("MS sends SecurityModeControl acceptance, VLR accepts, sends CC Setup");
dtap_expect_tx("0305" /* CC: Setup */);
ms_sends_security_mode_complete();
ms_sends_security_mode_complete(1);
btw("MS confirms call, we create a RAN-side RTP and forward MNCC_CALL_CONF_IND");
expect_crcx(RTP_TO_RAN);
@ -420,7 +420,7 @@ static void test_call_mt2()
btw("MS sends SecurityModeControl acceptance, VLR accepts, sends CC Setup");
dtap_expect_tx("0305" /* CC: Setup */);
ms_sends_security_mode_complete();
ms_sends_security_mode_complete(1);
btw("MS confirms call, we create a RAN-side RTP and forward MNCC_CALL_CONF_IND");
expect_crcx(RTP_TO_RAN);
@ -509,7 +509,7 @@ static void test_call_mo_to_unknown()
VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
btw("MS sends SecurityModeControl acceptance, VLR accepts; above Ciphering is an implicit CM Service Accept");
ms_sends_security_mode_complete();
ms_sends_security_mode_complete(1);
VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
BTW("a call is initiated");
@ -605,7 +605,7 @@ static void test_call_mo_to_unknown_timeout()
VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
btw("MS sends SecurityModeControl acceptance, VLR accepts; above Ciphering is an implicit CM Service Accept");
ms_sends_security_mode_complete();
ms_sends_security_mode_complete(1);
VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
BTW("a call is initiated");

View File

@ -138,7 +138,7 @@ static void _test_umts_authen(enum osmo_rat_type via_ran)
btw("MS sends SecurityModeControl acceptance, VLR accepts and sends GSUP LU Req to HLR");
gsup_expect_tx("04010809710000000156f0" CN_DOMAIN VLR_TO_HLR);
ms_sends_security_mode_complete();
ms_sends_security_mode_complete(1);
VERBOSE_ASSERT(gsup_tx_confirmed, == true, "%d");
VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
}
@ -211,7 +211,7 @@ static void _test_umts_authen(enum osmo_rat_type via_ran)
VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
btw("MS sends SecurityModeControl acceptance, VLR accepts; above Ciphering is an implicit CM Service Accept");
ms_sends_security_mode_complete();
ms_sends_security_mode_complete(1);
VERBOSE_ASSERT(cm_service_result_sent, == RES_NONE, "%d");
}
} else {
@ -278,7 +278,7 @@ static void _test_umts_authen(enum osmo_rat_type via_ran)
btw("MS sends SecurityModeControl acceptance, VLR accepts and sends SMS");
dtap_expect_tx(sms);
ms_sends_security_mode_complete();
ms_sends_security_mode_complete(1);
}
} else {
/* Encryption disabled */
@ -530,7 +530,7 @@ static void _test_umts_authen_resync(enum osmo_rat_type via_ran)
btw("MS sends SecurityModeControl acceptance, VLR accepts and sends GSUP LU Req to HLR");
gsup_expect_tx("04010809710000000156f0" CN_DOMAIN VLR_TO_HLR);
ms_sends_security_mode_complete();
ms_sends_security_mode_complete(1);
VERBOSE_ASSERT(gsup_tx_confirmed, == true, "%d");
VERBOSE_ASSERT(lu_result_sent, == RES_NONE, "%d");
}

View File

@ -986,12 +986,13 @@ void ms_sends_ciphering_mode_complete(const char *inner_ran_msg)
g_msub = NULL;
}
void ms_sends_security_mode_complete()
void ms_sends_security_mode_complete(uint8_t utran_encryption)
{
struct ran_msg ran_dec;
ran_dec = (struct ran_msg){
.msg_type = RAN_MSG_CIPHER_MODE_COMPLETE,
.cipher_mode_complete.utran_encryption = utran_encryption,
};
fake_msc_a_ran_dec(&ran_dec);

View File

@ -184,7 +184,7 @@ void paging_expect_tmsi(uint32_t tmsi);
void ms_sends_msg(const char *hex);
void ms_sends_classmark_update(const struct osmo_gsm48_classmark *classmark);
void ms_sends_ciphering_mode_complete(const char *inner_nas_msg);
void ms_sends_security_mode_complete();
void ms_sends_security_mode_complete(uint8_t utran_encryption);
void ms_sends_assignment_complete(enum mgcp_codecs assigned_codec);
void gsup_rx(const char *rx_hex, const char *expect_tx_hex);
void send_sms(struct vlr_subscr *receiver,