diff options
author | Holger Hans Peter Freyther <zecke@selfish.org> | 2009-11-14 18:32:17 +0100 |
---|---|---|
committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2009-11-20 17:35:46 +0100 |
commit | f8b9d844c1aa93366a828836e1923d32fd0f9d4f (patch) | |
tree | 7e9c9fbdce8d9ce95ea9dcca9dea206288a5b794 /openbsc/src/bssap.c | |
parent | 58ec07d580d1e3e93908e6383b5b1f969eba39cc (diff) |
[bssap] Pick the A5/0 vs A5/1 setting from the gsm_network
Follow the configuration of the gsm network. If the Cipher
Mode Request does not allow our preferred format we will
reject it. Otherwise send the cipher mode command to the
mobile station. This code is mostly untested.
Diffstat (limited to 'openbsc/src/bssap.c')
-rw-r--r-- | openbsc/src/bssap.c | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/openbsc/src/bssap.c b/openbsc/src/bssap.c index ffc549852..26ab998fa 100644 --- a/openbsc/src/bssap.c +++ b/openbsc/src/bssap.c @@ -56,6 +56,8 @@ static const struct tlv_definition bss_att_tlvdef = { [GSM0808_IE_CONFIG_EVO_INDI] = { TLV_TYPE_TV }, [GSM0808_IE_LSA_ACCESS_CTRL_SUPPR] = { TLV_TYPE_TV }, [GSM0808_IE_SERVICE_HANDOVER] = { TLV_TYPE_TV}, + [GSM0808_IE_ENCRYPTION_INFORMATION] = { TLV_TYPE_TLV }, + [GSM0808_IE_CIPHER_RESPONSE_MODE] = { TLV_TYPE_TV }, }, }; @@ -191,8 +193,13 @@ static int bssmap_handle_clear_command(struct sccp_connection *conn, static int bssmap_handle_cipher_mode(struct sccp_connection *conn, struct msgb *msg, unsigned int payload_length) { + u_int16_t len; + struct gsm_network *network = NULL; + const u_int8_t *data; + struct tlv_parsed tp; struct msgb *resp; int reject_cause = -1; + int include_imeisv = 1; /* HACK: Sending A5/0 to the MS */ if (!msg->lchan || !msg->lchan->msc_data) { @@ -207,10 +214,43 @@ static int bssmap_handle_cipher_mode(struct sccp_connection *conn, msg->lchan->msc_data->ciphering_handled = 1; - /* FIXME: parse the message. TLVP */ -#warning "Need to handle cipher mode properly" + tlv_parse(&tp, &bss_att_tlvdef, msg->l4h + 1, payload_length - 1, 0, 0); + if (!TLVP_PRESENT(&tp, GSM0808_IE_ENCRYPTION_INFORMATION)) { + DEBUGP(DMSC, "IE Encryption Information missing.\n"); + goto reject; + } + + /* + * check if our global setting is allowed + * - Currently we check for A5/0 and A5/1 + * - Copy the key if that is necessary + * - Otherwise reject + */ + len = TLVP_LEN(&tp, GSM0808_IE_ENCRYPTION_INFORMATION); + if (len < 1) { + DEBUGP(DMSC, "IE Encryption Information is too short.\n"); + goto reject; + } + + network = msg->lchan->ts->trx->bts->network; + data = TLVP_VAL(&tp, GSM0808_IE_ENCRYPTION_INFORMATION); + + if (network->a5_encryption == 0 && (data[0] & 0x1) == 0x1) { + msg->lchan->encr.alg_id = RSL_ENC_ALG_A5(0); + } else if (network->a5_encryption != 0 && (data[0] & 0x2) == 0x2) { + msg->lchan->encr.alg_id = RSL_ENC_ALG_A5(1); + msg->lchan->encr.key_len = len - 1; + memcpy(msg->lchan->encr.key, &data[1], len - 1); + } else { + DEBUGP(DMSC, "Can not select encryption...\n"); + goto reject; + } + + if (TLVP_PRESENT(&tp, GSM0808_IE_CIPHER_RESPONSE_MODE)) { + include_imeisv = TLVP_VAL(&tp, GSM0808_IE_CIPHER_RESPONSE_MODE)[0] & 0x1; + } - return gsm48_send_rr_ciph_mode(msg->lchan, 1); + return gsm48_send_rr_ciph_mode(msg->lchan, include_imeisv); reject: resp = bssmap_create_cipher_reject(reject_cause); |