aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bts-sysmo/l1_if.c
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 /src/osmo-bts-sysmo/l1_if.c
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.
Diffstat (limited to 'src/osmo-bts-sysmo/l1_if.c')
-rw-r--r--src/osmo-bts-sysmo/l1_if.c52
1 files changed, 47 insertions, 5 deletions
diff --git a/src/osmo-bts-sysmo/l1_if.c b/src/osmo-bts-sysmo/l1_if.c
index 1c46ecfa..02d930e9 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 */