A5 support for RSL and 04.08 (not used yet)

This just adds the 04.08 and RSL bits for A5, but not the logic
for performing authentication.

The caller would first set lchan->encr and then call
gsm48_send_rr_ciph_mode(lchan), which encapsulates the 04.08
CIPHERING MODE COMMAND into a RSL ENCRYPTION COMMAND and sends it
to the BTS for execution + forwarding.
diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c
index 7be1a6b..88e58de 100644
--- a/openbsc/src/abis_rsl.c
+++ b/openbsc/src/abis_rsl.c
@@ -317,6 +317,16 @@
 		memset(out+len, 0x2b, MACBLOCK_SIZE-len);
 }
 
+/* Chapter 9.3.7: Encryption Information */
+static int build_encr_info(u_int8_t *out, struct gsm_lchan *lchan)
+{
+	*out++ = lchan->encr.alg_id & 0xff;
+	if (lchan->encr.key_len)
+		memcpy(out, lchan->encr.key, lchan->encr.key_len);
+	return lchan->encr.key_len + 1;
+}
+
+
 static const char *rsl_err_vals[0xff] = {
 	[RSL_ERR_RADIO_IF_FAIL] =	"Radio Interface Failure",
 	[RSL_ERR_RADIO_LINK_FAIL] =	"Radio Link Failure",
@@ -587,10 +597,14 @@
 		     (u_int8_t *) &cm);
 	msgb_tlv_put(msg, RSL_IE_CHAN_IDENT, 4,
 		     (u_int8_t *) &ci);
-#if 0
-	msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
-		     (u_int8_t *) &encr_info);
-#endif
+
+	if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
+		u_int8_t encr_info[MAX_A5_KEY_LEN+2];
+		rc = build_encr_info(encr_info, lchan);
+		if (rc > 0)
+			msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
+	}
+
 	msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power);
 	msgb_tv_put(msg, RSL_IE_MS_POWER, lchan->ms_power);
 	msgb_tv_put(msg, RSL_IE_TIMING_ADVANCE, ta);
@@ -621,10 +635,45 @@
 
 	msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
 		     (u_int8_t *) &cm);
-#if 0
-	msgb_tlv_put(msg, RSL_IE_ENCR_INFO, 1,
-		     (u_int8_t *) &encr_info);
-#endif
+
+	if (lchan->encr.alg_id > RSL_ENC_ALG_A5(0)) {
+		u_int8_t encr_info[MAX_A5_KEY_LEN+2];
+		rc = build_encr_info(encr_info, lchan);
+		if (rc > 0)
+			msgb_tlv_put(msg, RSL_IE_ENCR_INFO, rc, encr_info);
+	}
+
+	msg->trx = lchan->ts->trx;
+
+	return abis_rsl_sendmsg(msg);
+}
+
+/* Chapter 8.4.6: Send the encryption command with given L3 info */
+int rsl_encryption_cmd(struct msgb *msg)
+{
+	struct abis_rsl_dchan_hdr *dh;
+	struct gsm_lchan *lchan = msg->lchan;
+	u_int8_t chan_nr = lchan2chan_nr(lchan);
+	u_int8_t encr_info[MAX_A5_KEY_LEN+2];
+	u_int8_t l3_len = msg->tail - (u_int8_t *)msgb_l3(msg);
+	int rc;
+
+	/* First push the L3 IE tag and length */
+	msgb_tv16_push(msg, RSL_IE_L3_INFO, l3_len);
+
+	/* then the link identifier (SAPI0, main sign link) */
+	msgb_tv_push(msg, RSL_IE_LINK_IDENT, 0);
+
+	/* then encryption information */
+	rc = build_encr_info(encr_info, lchan);
+	if (rc <= 0)
+		return rc;
+	msgb_tlv_push(msg, RSL_IE_ENCR_INFO, rc, encr_info);
+
+	/* and finally the DCHAN header */
+	dh = (struct abis_rsl_dchan_hdr *) msgb_push(msg, sizeof(*dh));
+	init_dchan_hdr(dh, RSL_MT_ENCR_CMD);
+	dh->chan_nr = chan_nr;
 
 	msg->trx = lchan->ts->trx;
 
@@ -1082,6 +1131,7 @@
 	arfcn = lchan->ts->trx->arfcn;
 	subch = lchan->nr;
 	
+	lchan->encr.alg_id = RSL_ENC_ALG_A5(0);	/* no encryption */
 	lchan->ms_power = ms_pwr_ctl_lvl(bts->band, bts->ms_max_power);
 	lchan->bs_power = 0; /* 0dB reduction, output power = Pn */
 	lchan->rsl_cmode = RSL_CMOD_SPD_SIGN;