aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2012-04-08 20:17:43 +0200
committerHarald Welte <laforge@gnumonks.org>2012-04-19 08:22:29 +0200
commitd9ab45d1aac21c761c461659e2179d1077b5b7a5 (patch)
tree9c923824c549de2609486d8e6cacb3258e21398f
parent51f9693ba634945f489523453c3bdfc07274b09d (diff)
Support for ciphering
When the RR CIPH MODE CMD is transmitted to the MS, we need to tell the L1 to enable decryption on RX. After the first received frame has been decrypted successfully, we will enable encryption also on transmit. This has been tested with A5/1 so far, but A5/2 and A5/3 should work exactly identical.
-rw-r--r--src/osmo-bts-sysmo/l1_if.c52
-rw-r--r--src/osmo-bts-sysmo/oml.c41
2 files changed, 88 insertions, 5 deletions
diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c
index 1c46ecf..02d930e 100644
--- a/src/osmo-bts-sysmo/l1_if.c
+++ b/src/osmo-bts-sysmo/l1_if.c
@@ -301,6 +301,37 @@ get_lapdm_chan_by_hl2(struct gsm_bts_trx *trx, uint32_t hLayer2)
return &lchan->lapdm_ch;
}
+enum lchan_ciph_state {
+ LCHAN_CIPH_NONE,
+ LCHAN_CIPH_RX_REQ,
+ LCHAN_CIPH_RX_CONF,
+ LCHAN_CIPH_TXRX_REQ,
+ LCHAN_CIPH_TXRX_CONF,
+};
+
+/* check if the message is a GSM48_MT_RR_CIPH_M_CMD, and if yes, enable
+ * uni-directional de-cryption on the uplink. We need this ugly layering
+ * violation as we have no way of passing down L3 metadata (RSL CIPHERING CMD)
+ * to this point in L1 */
+static int check_for_ciph_cmd(struct femtol1_hdl *fl1h,
+ struct msgb *msg, struct gsm_lchan *lchan)
+{
+ /* First byte (Address Field) of LAPDm header) */
+ if (msg->data[0] != 0x03)
+ return 0;
+ /* First byte (protocol discriminator) of RR */
+ if ((msg->data[3] & 0xF) != GSM48_PDISC_RR)
+ return 0;
+ /* 2nd byte (msg type) of RR */
+ if ((msg->data[4] & 0x3F) != GSM48_MT_RR_CIPH_M_CMD)
+ return 0;
+
+ lchan->ciph_state = LCHAN_CIPH_RX_REQ;
+ l1if_enable_ciphering(fl1h, lchan, 0);
+
+ return 1;
+}
+
static const uint8_t fill_frame[GSM_MACBLOCK_LEN] = {
0x01, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,
0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,
@@ -316,7 +347,6 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1,
struct msgb *resp_msg;
GsmL1_PhDataReq_t *data_req;
GsmL1_MsgUnitParam_t *msu_param;
- struct lapdm_channel *lc;
struct lapdm_entity *le;
struct gsm_lchan *lchan;
struct gsm_time g_time;
@@ -424,13 +454,15 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1,
break;
case GsmL1_Sapi_Sdcch:
/* resolve the L2 entity using rts_ind->hLayer2 */
- lc = get_lapdm_chan_by_hl2(trx, rts_ind->hLayer2);
- le = &lc->lapdm_dcch;
+ lchan = l1if_hLayer2_to_lchan(trx, rts_ind->hLayer2);
+ le = &lchan->lapdm_ch.lapdm_dcch;
rc = lapdm_phsap_dequeue_prim(le, &pp);
if (rc < 0)
memcpy(msu_param->u8Buffer, fill_frame, GSM_MACBLOCK_LEN);
else {
memcpy(msu_param->u8Buffer, pp.oph.msg->data, GSM_MACBLOCK_LEN);
+ /* check if it is a RR CIPH MODE CMD. if yes, enable RX ciphering */
+ check_for_ciph_cmd(fl1, pp.oph.msg, lchan);
msgb_free(pp.oph.msg);
}
break;
@@ -458,13 +490,15 @@ static int handle_ph_readytosend_ind(struct femtol1_hdl *fl1,
case GsmL1_Sapi_FacchF:
case GsmL1_Sapi_FacchH:
/* resolve the L2 entity using rts_ind->hLayer2 */
- lc = get_lapdm_chan_by_hl2(trx, rts_ind->hLayer2);
- le = &lc->lapdm_dcch;
+ lchan = l1if_hLayer2_to_lchan(trx, rts_ind->hLayer2);
+ le = &lchan->lapdm_ch.lapdm_dcch;
rc = lapdm_phsap_dequeue_prim(le, &pp);
if (rc < 0)
goto empty_frame;
else {
memcpy(msu_param->u8Buffer, pp.oph.msg->data, GSM_MACBLOCK_LEN);
+ /* check if it is a RR CIPH MODE CMD. if yes, enable RX ciphering */
+ check_for_ciph_cmd(fl1, pp.oph.msg, lchan);
msgb_free(pp.oph.msg);
}
break;
@@ -585,6 +619,14 @@ static int handle_ph_data_ind(struct femtol1_hdl *fl1, GsmL1_PhDataInd_t *data_i
case GsmL1_Sapi_Sdcch:
case GsmL1_Sapi_FacchF:
case GsmL1_Sapi_FacchH:
+ /* if this is the first valid message after enabling Rx
+ * decryption, we have to enable Tx encryption */
+ if (lchan->ciph_state == LCHAN_CIPH_RX_REQ ||
+ lchan->ciph_state == LCHAN_CIPH_RX_CONF) {
+ l1if_enable_ciphering(fl1, lchan, 1);
+ lchan->ciph_state = LCHAN_CIPH_TXRX_REQ;
+ }
+
/* SDCCH, SACCH and FACCH all go to LAPDm */
le = le_by_l1_sapi(&lchan->lapdm_ch, data_ind->sapi);
/* allocate and fill LAPDm primitive */
diff --git a/src/osmo-bts-sysmo/oml.c b/src/osmo-bts-sysmo/oml.c
index 3c26849..00c088c 100644
--- a/src/osmo-bts-sysmo/oml.c
+++ b/src/osmo-bts-sysmo/oml.c
@@ -18,6 +18,7 @@
*/
#include <stdint.h>
+#include <errno.h>
#include <osmocom/core/talloc.h>
#include <osmocom/core/utils.h>
@@ -775,6 +776,46 @@ static int tx_confreq_logchpar(struct gsm_lchan *lchan, uint8_t direction)
return l1if_req_compl(fl1h, msg, 0, chmod_modif_compl_cb, lchan);
}
+const enum GsmL1_CipherId_t rsl2l1_ciph[] = {
+ [0] = GsmL1_CipherId_A50,
+ [1] = GsmL1_CipherId_A50,
+ [2] = GsmL1_CipherId_A51,
+ [3] = GsmL1_CipherId_A52,
+ [4] = GsmL1_CipherId_A53,
+};
+
+int l1if_enable_ciphering(struct femtol1_hdl *fl1h,
+ struct gsm_lchan *lchan,
+ int dir_downlink)
+{
+ struct msgb *msg = l1p_msgb_alloc();
+ struct GsmL1_MphConfigReq_t *cfgr;
+
+ LOGP(DL1C, LOGL_DEBUG, "%s enable_ciphering(dir_downlink=%u)\n",
+ gsm_lchan_name(lchan), dir_downlink);
+
+ cfgr = prim_init(msgb_l1prim(msg), GsmL1_PrimId_MphConfigReq, fl1h);
+
+ cfgr->cfgParamId = GsmL1_ConfigParamId_SetCipheringParams;
+ cfgr->cfgParams.setCipheringParams.u8Tn = lchan->ts->nr;
+ cfgr->cfgParams.setCipheringParams.subCh = lchan_to_GsmL1_SubCh_t(lchan);
+
+ if (dir_downlink)
+ cfgr->cfgParams.setCipheringParams.dir = GsmL1_Dir_TxDownlink;
+ else
+ cfgr->cfgParams.setCipheringParams.dir = GsmL1_Dir_RxUplink;
+
+ if (lchan->encr.alg_id >= ARRAY_SIZE(rsl2l1_ciph))
+ return -EINVAL;
+ cfgr->cfgParams.setCipheringParams.cipherId = rsl2l1_ciph[lchan->encr.alg_id];
+
+ memcpy(cfgr->cfgParams.setCipheringParams.u8Kc,
+ lchan->encr.key, lchan->encr.key_len);
+
+ return l1if_req_compl(fl1h, msg, 0, chmod_modif_compl_cb, lchan);
+}
+
+
int bts_model_rsl_mode_modify(struct gsm_lchan *lchan)
{
/* channel mode, encryption and/or multirate have changed */