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.
This commit is contained in:
Harald Welte 2009-08-30 15:37:11 +09:00
parent 196d0528ff
commit 08d91a5b26
5 changed files with 96 additions and 8 deletions

View File

@ -499,6 +499,7 @@ int rsl_chan_activate(struct gsm_bts_trx *trx, u_int8_t chan_nr,
int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type,
u_int8_t ta);
int rsl_chan_mode_modify_req(struct gsm_lchan *ts);
int rsl_encryption_cmd(struct msgb *msg);
int rsl_paging_cmd(struct gsm_bts *bts, u_int8_t paging_group, u_int8_t len,
u_int8_t *ms_ident, u_int8_t chan_needed);
int rsl_paging_cmd_subscr(struct gsm_bts *bts, u_int8_t chan_needed,

View File

@ -713,6 +713,7 @@ int gsm48_generate_mid_from_imsi(u_int8_t *buf, const char* imsi);
int gsm48_mi_to_string(char *string, const int str_len, const u_int8_t *mi, const int mi_len);
int gsm48_send_rr_release(struct gsm_lchan *lchan);
int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan);
int gsm48_send_rr_app_info(struct gsm_lchan *lchan, u_int8_t apdu_id,
u_int8_t apdu_len, u_int8_t *apdu);

View File

@ -126,6 +126,9 @@ struct gsm_loc_updating_operation {
int waiting_for_imei : 1;
};
#define MAX_A5_KEY_LEN (128/8)
#define RSL_ENC_ALG_A5(x) (x+1)
struct gsm_lchan {
/* The TS that we're part of */
struct gsm_bts_trx_ts *ts;
@ -140,6 +143,12 @@ struct gsm_lchan {
/* Power levels for MS and BTS */
u_int8_t bs_power;
u_int8_t ms_power;
/* Encryption information */
struct {
u_int8_t alg_id;
u_int8_t key_len;
u_int8_t key[MAX_A5_KEY_LEN];
} encr;
/* To whom we are allocated at the moment */
struct gsm_subscriber *subscr;

View File

@ -317,6 +317,16 @@ static void pad_macblock(u_int8_t *out, const u_int8_t *in, int len)
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 @@ int rsl_chan_activate_lchan(struct gsm_lchan *lchan, u_int8_t act_type,
(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 @@ int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
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 @@ static int rsl_rx_chan_rqd(struct msgb *msg)
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;

View File

@ -1672,6 +1672,10 @@ static int gsm0408_rcv_rr(struct msgb *msg)
case GSM48_MT_RR_APP_INFO:
rc = gsm48_rx_rr_app_info(msg);
break;
case GSM48_MT_RR_CIPH_M_COMPL:
DEBUGP(DRR, "CIPHERING MODE COMPLETE\n");
/* FIXME: check for MI (if any) */
break;
default:
fprintf(stderr, "Unimplemented GSM 04.08 RR msg type 0x%02x\n",
gh->msg_type);
@ -1681,6 +1685,29 @@ static int gsm0408_rcv_rr(struct msgb *msg)
return rc;
}
/* Chapter 9.1.9: Ciphering Mode Command */
int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan)
{
struct msgb *msg = gsm48_msgb_alloc();
struct gsm48_hdr *gh;
u_int8_t ciph_mod_set;
msg->lchan = lchan;
DEBUGP(DRR, "TX CIPHERING MODE CMD\n");
if (lchan->encr.alg_id <= RSL_ENC_ALG_A5(0))
ciph_mod_set = 0;
else
ciph_mod_set = (lchan->encr.alg_id-1)<<1 | 1;
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
gh->proto_discr = GSM48_PDISC_RR;
gh->msg_type = GSM48_MT_RR_CIPH_M_CMD;
gh->data[0] = 0x10 | (ciph_mod_set & 0xf);
return rsl_encryption_cmd(msg);
}
int gsm48_send_rr_app_info(struct gsm_lchan *lchan, u_int8_t apdu_id,
u_int8_t apdu_len, u_int8_t *apdu)