diff options
-rw-r--r-- | include/osmocom/bsc/gsm_data.h | 4 | ||||
-rw-r--r-- | src/osmo-bsc/handover_fsm.c | 29 |
2 files changed, 33 insertions, 0 deletions
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h index ba28a6b1c..131a53e93 100644 --- a/include/osmocom/bsc/gsm_data.h +++ b/include/osmocom/bsc/gsm_data.h @@ -179,6 +179,10 @@ struct handover_in_req { struct gsm0808_speech_codec_list scl; struct gsm0808_encrypt_info ei; struct gsm_classmark classmark; + /* chosen_encr_alg reflects the encoded value as in RSL_ENC_ALG_A5(a5_numer): + * chosen_encr_alg == 1 means A5/0 i.e. no encryption, chosen_encr_alg == 4 means A5/3. + * chosen_encr_alg == 0 means no such IE was present. */ + uint8_t chosen_encr_alg; struct gsm0808_cell_id cell_id_serving; char cell_id_serving_name[64]; struct gsm0808_cell_id cell_id_target; diff --git a/src/osmo-bsc/handover_fsm.c b/src/osmo-bsc/handover_fsm.c index 9c86b7090..421c32efb 100644 --- a/src/osmo-bsc/handover_fsm.c +++ b/src/osmo-bsc/handover_fsm.c @@ -432,6 +432,17 @@ static bool parse_ho_request(struct gsm_subscriber_connection *conn, const struc "Missing mandatory IE: 3GPP mandates either Classmark Information 1 or 2" " in BSSMAP Handover Request, but neither are present. Will continue without.\n"); + if ((e = TLVP_GET(tp, GSM0808_IE_CHOSEN_ENCR_ALG))) { + req->chosen_encr_alg = e->val[0]; + if (req->chosen_encr_alg < 1 || req->chosen_encr_alg > 8) + LOG_HO(conn, LOGL_ERROR, "Chosen Encryption Algorithm (Serving) is invalid: %u\n", + req->chosen_encr_alg); + } + + LOG_HO(conn, LOGL_DEBUG, "Handover Request encryption info: chosen=A5/%u key=%s\n", + (req->chosen_encr_alg ? : 1) - 1, req->ei.key_len? + osmo_hexdump_nospc(req->ei.key, req->ei.key_len) : "none"); + if (TLVP_PRESENT(tp, GSM0808_IE_AOIP_TRASP_ADDR)) { int rc; unsigned int u; @@ -611,6 +622,24 @@ void handover_start_inter_bsc_in(struct gsm_subscriber_connection *conn, .msc_assigned_cic = req->msc_assigned_cic, }; + if (req->chosen_encr_alg) { + info.encr.alg_id = req->chosen_encr_alg; + if (info.encr.alg_id > 1 && !req->ei.key_len) { + ho_fail(HO_RESULT_ERROR, "Chosen Encryption Algorithm (Serving) reflects A5/%u" + " but there is no key (Encryption Information)", info.encr.alg_id - 1); + return; + } + } + + if (req->ei.key_len) { + if (req->ei.key_len > sizeof(info.encr.key)) { + ho_fail(HO_RESULT_ERROR, "Encryption Information IE key length is too large: %u\n", + req->ei.key_len); + } + memcpy(info.encr.key, req->ei.key, req->ei.key_len); + info.encr.key_len = req->ei.key_len; + } + lchan_activate(ho->new_lchan, &info); } |