aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/bsc/gsm_data.h4
-rw-r--r--src/osmo-bsc/handover_fsm.c29
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);
}