diff options
Diffstat (limited to 'openbsc')
-rw-r--r-- | openbsc/include/openbsc/abis_rsl.h | 1 | ||||
-rw-r--r-- | openbsc/include/openbsc/gsm_04_08.h | 1 | ||||
-rw-r--r-- | openbsc/include/openbsc/gsm_data.h | 9 | ||||
-rw-r--r-- | openbsc/src/abis_rsl.c | 66 | ||||
-rw-r--r-- | openbsc/src/gsm_04_08.c | 27 |
5 files changed, 96 insertions, 8 deletions
diff --git a/openbsc/include/openbsc/abis_rsl.h b/openbsc/include/openbsc/abis_rsl.h index 6a454bf4e..8c5547d1d 100644 --- a/openbsc/include/openbsc/abis_rsl.h +++ b/openbsc/include/openbsc/abis_rsl.h @@ -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, diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index 6f367864f..99d774770 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -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); diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 4bdca2ab7..2658a79a4 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -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; diff --git a/openbsc/src/abis_rsl.c b/openbsc/src/abis_rsl.c index 7be1a6b32..88e58de1a 100644 --- a/openbsc/src/abis_rsl.c +++ b/openbsc/src/abis_rsl.c @@ -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; diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index eeabc0fce..30c2db39d 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -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) |