[PATCH] osmocom-bb[master]: trxcon/scheduler: implement A5/X ciphering support

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Harald Welte gerrit-no-reply at lists.osmocom.org
Thu Feb 22 15:33:35 UTC 2018


Review at  https://gerrit.osmocom.org/6812

trxcon/scheduler: implement A5/X ciphering support

This change implements the A5/X ciphering support transparently
for the logical channel handlers. In other words, a DL burst is
deciphered before being passed to a handler, and an UL burst is
ciphered before being sent to transceiver.

The implementation mostly relays on the libosmocore's A5 API.

Change-Id: Ib53418d8c0f394fdece09cf5cc240887cb0bb5af
---
M src/host/trxcon/l1ctl.c
M src/host/trxcon/sched_trx.c
M src/host/trxcon/sched_trx.h
3 files changed, 125 insertions(+), 3 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/12/6812/1

diff --git a/src/host/trxcon/l1ctl.c b/src/host/trxcon/l1ctl.c
index a11e792..070ee56 100644
--- a/src/host/trxcon/l1ctl.c
+++ b/src/host/trxcon/l1ctl.c
@@ -731,6 +731,49 @@
 	return 0;
 }
 
+static int l1ctl_rx_crypto_req(struct l1ctl_link *l1l, struct msgb *msg)
+{
+	struct l1ctl_crypto_req *req;
+	struct l1ctl_info_ul *ul;
+	struct trx_ts *ts;
+	uint8_t tn;
+	int rc = 0;
+
+	ul = (struct l1ctl_info_ul *) msg->l1h;
+	req = (struct l1ctl_crypto_req *) ul->payload;
+
+	LOGP(DL1C, LOGL_NOTICE, "L1CTL_CRYPTO_REQ (algo=A5/%u, key_len=%u)\n",
+		req->algo, req->key_len);
+
+	/* Determine TS index */
+	tn = ul->chan_nr & 0x7;
+	if (tn > 7) {
+		LOGP(DL1C, LOGL_ERROR, "Incorrect TS index %u\n", tn);
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	/* Make sure that required TS is allocated and configured */
+	ts = l1l->trx->ts_list[tn];
+	if (ts == NULL || ts->mf_layout == NULL) {
+		LOGP(DL1C, LOGL_ERROR, "TS %u is not configured\n", tn);
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	/* Poke scheduler */
+	rc = sched_trx_start_ciphering(ts, req->algo, req->key, req->key_len);
+	if (rc) {
+		LOGP(DL1C, LOGL_ERROR, "Couldn't configure ciphering\n");
+		rc = -EINVAL;
+		goto exit;
+	}
+
+exit:
+	msgb_free(msg);
+	return rc;
+}
+
 int l1ctl_rx_cb(struct l1ctl_link *l1l, struct msgb *msg)
 {
 	struct l1ctl_hdr *l1h;
@@ -763,6 +806,8 @@
 		return l1ctl_rx_param_req(l1l, msg);
 	case L1CTL_TCH_MODE_REQ:
 		return l1ctl_rx_tch_mode_req(l1l, msg);
+	case L1CTL_CRYPTO_REQ:
+		return l1ctl_rx_crypto_req(l1l, msg);
 	default:
 		LOGP(DL1C, LOGL_ERROR, "Unknown MSG: %u\n", l1h->msg_type);
 		msgb_free(msg);
diff --git a/src/host/trxcon/sched_trx.c b/src/host/trxcon/sched_trx.c
index fba9ee4..120098b 100644
--- a/src/host/trxcon/sched_trx.c
+++ b/src/host/trxcon/sched_trx.c
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <talloc.h>
 
+#include <osmocom/gsm/a5.h>
 #include <osmocom/core/bits.h>
 #include <osmocom/core/msgb.h>
 #include <osmocom/core/logging.h>
@@ -292,6 +293,37 @@
 	return 0;
 }
 
+int sched_trx_start_ciphering(struct trx_ts *ts, uint8_t algo,
+	uint8_t *key, uint8_t key_len)
+{
+	struct trx_lchan_state *state;
+	size_t len;
+	int i;
+
+	/* Prevent NULL-pointer deference */
+	if (!ts)
+		return -EINVAL;
+
+	/* Make sure we can store this key */
+	if (key_len > MAX_A5_KEY_LEN)
+		return -ERANGE;
+
+	/* Iterate over all allocated logical channels */
+	len = talloc_array_length(ts->lchans);
+	for (i = 0; i < len; i++) {
+		/* Set key length and algorithm */
+		state = ts->lchans + i;
+		state->a5.key_len = key_len;
+		state->a5.algo = algo;
+
+		/* Copy requested key */
+		if (key_len)
+			memcpy(state->a5.key, key, key_len);
+	}
+
+	return 0;
+}
+
 struct trx_lchan_state *sched_trx_find_lchan(struct trx_ts *ts,
 	enum trx_lchan_type chan)
 {
@@ -396,6 +428,9 @@
 	talloc_free(lchan->rx_bursts);
 	talloc_free(lchan->tx_bursts);
 
+	/* Reset ciphering state */
+	memset(&lchan->a5, 0x00, sizeof(lchan->a5));
+
 	/* Forget the current prim */
 	sched_prim_drop(lchan);
 
@@ -456,6 +491,40 @@
 	return TRXC_IDLE;
 }
 
+static void sched_trx_a5_burst_dec(struct trx_lchan_state *lchan,
+	uint32_t fn, sbit_t *burst)
+{
+	ubit_t ks[114];
+	int i;
+
+	/* Generate keystream for a DL burst */
+	osmo_a5(lchan->a5.algo, lchan->a5.key, fn, ks, NULL);
+
+	/* Apply keystream over ciphertext */
+	for (i = 0; i < 57; i++) {
+		if (ks[i])
+			burst[i + 3] *= -1;
+		if (ks[i + 57])
+			burst[i + 88] *= -1;
+	}
+}
+
+static void sched_trx_a5_burst_enc(struct trx_lchan_state *lchan,
+	uint32_t fn, ubit_t *burst)
+{
+	ubit_t ks[114];
+	int i;
+
+	/* Generate keystream for an UL burst */
+	osmo_a5(lchan->a5.algo, lchan->a5.key, fn, NULL, ks);
+
+	/* Apply keystream over plaintext */
+	for (i = 0; i < 57; i++) {
+		burst[i + 3] ^= ks[i];
+		burst[i + 88] ^= ks[i + 57];
+	}
+}
+
 int sched_trx_handle_rx_burst(struct trx_instance *trx, uint8_t tn,
 	uint32_t burst_fn, sbit_t *bits, uint16_t nbits, int8_t rssi, float toa)
 {
@@ -512,9 +581,13 @@
 		if (!lchan->active)
 			goto next_frame;
 
-		/* Put burst to handler */
+		/* Reached current fn */
 		if (fn == burst_fn) {
-			/* TODO: decrypt if required */
+			/* Perform A5/X decryption if required */
+			if (lchan->a5.algo)
+				sched_trx_a5_burst_dec(lchan, fn, bits);
+
+			/* Put burst to handler */
 			handler(trx, ts, lchan, fn, bid, bits, rssi, toa);
 		}
 
@@ -538,7 +611,9 @@
 {
 	int rc;
 
-	/* TODO: perform A5/X burst encryption if required */
+	/* Perform A5/X burst encryption if required */
+	if (lchan->a5.algo)
+		sched_trx_a5_burst_enc(lchan, fn, bits);
 
 	/* Forward burst to transceiver */
 	rc = trx_if_tx_burst(trx, ts->index, fn, trx->tx_power, bits);
diff --git a/src/host/trxcon/sched_trx.h b/src/host/trxcon/sched_trx.h
index 54dbc85..504054a 100644
--- a/src/host/trxcon/sched_trx.h
+++ b/src/host/trxcon/sched_trx.h
@@ -253,6 +253,8 @@
 int sched_trx_reset_ts(struct trx_instance *trx, int tn);
 int sched_trx_configure_ts(struct trx_instance *trx, int tn,
 	enum gsm_phys_chan_config config);
+int sched_trx_start_ciphering(struct trx_ts *ts, uint8_t algo,
+	uint8_t *key, uint8_t key_len);
 
 /* Logical channel management functions */
 enum gsm_phys_chan_config sched_trx_chan_nr2pchan_config(uint8_t chan_nr);

-- 
To view, visit https://gerrit.osmocom.org/6812
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib53418d8c0f394fdece09cf5cc240887cb0bb5af
Gerrit-PatchSet: 1
Gerrit-Project: osmocom-bb
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <laforge at gnumonks.org>



More information about the gerrit-log mailing list