struct gsm_encr: store alg_id in human-readable format
I find it weird that we store the A5 algorithm ID in a format that is used on the wire: N + 1 (valid for both A-bis and A interfaces). What confused me even more is that in some functions we print it as if it was in a normal, human-readable format. And this is also why one can see weird constructions like: if (lchan->encr.alg_id > ALG_A5_NR_TO_RSL(0)) { ... } Let's ensure that our internal structures use the A5/N format: alg_id=0: A5/0 (0x01 on the A-bis/A interface) alg_id=1: A5/1 (0x02 on the A-bis/A interface) alg_id=2: A5/2 (0x03 on the A-bis/A interface) ... alg_id=7: A5/7 (0x08 on the A-bis/A interface) so that we can print and compare the value of alg_id without using additional arithmetics. Let's also rename 'alg_id' to 'alg_a5_n' as it most clearly indicates which representation it is storing. This is how the above code snippet would look like: if (lchan->encr.alg_a5_n > 0) { ... } Change-Id: Ieb50c9a352cfa5481aebac2379e0a461663543ec
This commit is contained in:
parent
eba0a02017
commit
7fb4817b78
|
@ -7,7 +7,7 @@
|
|||
struct gsm_subscriber_connection;
|
||||
|
||||
void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, uint8_t dlci, enum gsm0808_cause cause);
|
||||
void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, struct msgb *msg, uint8_t chosen_encr);
|
||||
void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, struct msgb *msg, uint8_t chosen_a5_n);
|
||||
int bsc_compl_l3(struct gsm_lchan *lchan, struct msgb *msg, uint16_t chosen_channel);
|
||||
void bsc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg);
|
||||
void bsc_cm_update(struct gsm_subscriber_connection *conn,
|
||||
|
|
|
@ -546,6 +546,7 @@ struct om2k_mo {
|
|||
* These macros convert from n to the other representations:
|
||||
*/
|
||||
#define ALG_A5_NR_TO_RSL(A5_N) ((A5_N) >= 0 ? (A5_N)+1 : 0)
|
||||
#define ALG_A5_NR_TO_BSSAP(A5_N) ALG_A5_NR_TO_RSL(A5_N)
|
||||
#define ALG_A5_NR_TO_PERM_ALG_BITS(A5_N) ((A5_N) >= 0 ? 1<<(A5_N) : 0)
|
||||
|
||||
/* Up to 16 SI2quater are multiplexed; each fits 3 EARFCNS, so the practical maximum is 3*16.
|
||||
|
@ -608,7 +609,7 @@ enum lchan_sapi_state {
|
|||
#define MAX_A5_KEY_LEN (128/8)
|
||||
|
||||
struct gsm_encr {
|
||||
uint8_t alg_id;
|
||||
uint8_t alg_a5_n; /* N: 0 (A5/0), 1 (A5/1), ... 7 (A5/7) */
|
||||
uint8_t key_len;
|
||||
uint8_t key[MAX_A5_KEY_LEN];
|
||||
bool kc128_present;
|
||||
|
|
|
@ -159,13 +159,13 @@ static void pad_macblock(uint8_t *out, const uint8_t *in, int len)
|
|||
* 'out' must provide room for 17 bytes. */
|
||||
static int build_encr_info(uint8_t *out, struct gsm_lchan *lchan)
|
||||
{
|
||||
*out++ = lchan->encr.alg_id & 0xff;
|
||||
switch (lchan->encr.alg_id) {
|
||||
out[0] = ALG_A5_NR_TO_RSL(lchan->encr.alg_a5_n);
|
||||
switch (out[0]) {
|
||||
case GSM0808_ALG_ID_A5_1:
|
||||
case GSM0808_ALG_ID_A5_2:
|
||||
case GSM0808_ALG_ID_A5_3:
|
||||
if (!lchan->encr.key_len) {
|
||||
LOG_LCHAN(lchan, LOGL_ERROR, "A5/%d encryption chosen, but missing Kc\n", lchan->encr.alg_id);
|
||||
LOG_LCHAN(lchan, LOGL_ERROR, "A5/%d encryption chosen, but missing Kc\n", lchan->encr.alg_a5_n);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* fall through */
|
||||
|
@ -177,7 +177,7 @@ static int build_encr_info(uint8_t *out, struct gsm_lchan *lchan)
|
|||
* even for A5/0. Currently our ttcn3 test suite does expect the key to be present also for A5/0, see
|
||||
* f_cipher_mode() in bsc/MSC_ConnectionHandler.ttcn. */
|
||||
if (lchan->encr.key_len)
|
||||
memcpy(out, lchan->encr.key, lchan->encr.key_len);
|
||||
memcpy(&out[1], lchan->encr.key, lchan->encr.key_len);
|
||||
return 1 + lchan->encr.key_len;
|
||||
|
||||
case GSM0808_ALG_ID_A5_4:
|
||||
|
@ -185,11 +185,11 @@ static int build_encr_info(uint8_t *out, struct gsm_lchan *lchan)
|
|||
LOG_LCHAN(lchan, LOGL_ERROR, "A5/4 encryption chosen, but missing Kc128\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(out, lchan->encr.kc128, sizeof(lchan->encr.kc128));
|
||||
memcpy(&out[1], lchan->encr.kc128, sizeof(lchan->encr.kc128));
|
||||
return 1 + sizeof(lchan->encr.kc128);
|
||||
|
||||
default:
|
||||
LOG_LCHAN(lchan, LOGL_ERROR, "A5/%d encryption not supported\n", lchan->encr.alg_id);
|
||||
LOG_LCHAN(lchan, LOGL_ERROR, "A5/%d encryption not supported\n", lchan->encr.alg_a5_n);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -660,7 +660,7 @@ int rsl_tx_chan_activ(struct gsm_lchan *lchan, uint8_t act_type, uint8_t ho_ref)
|
|||
msg->l3h = len + 1;
|
||||
*len = msgb_l3len(msg);
|
||||
|
||||
if (lchan->encr.alg_id > ALG_A5_NR_TO_RSL(0)) {
|
||||
if (lchan->encr.alg_a5_n > 0) {
|
||||
uint8_t encr_info[MAX_A5_KEY_LEN+2];
|
||||
rc = build_encr_info(encr_info, lchan);
|
||||
if (rc > 0)
|
||||
|
@ -764,7 +764,7 @@ int rsl_chan_mode_modify_req(struct gsm_lchan *lchan)
|
|||
msgb_tlv_put(msg, RSL_IE_CHAN_MODE, sizeof(cm),
|
||||
(uint8_t *) &cm);
|
||||
|
||||
if (lchan->encr.alg_id > ALG_A5_NR_TO_RSL(0)) {
|
||||
if (lchan->encr.alg_a5_n > 0) {
|
||||
uint8_t encr_info[MAX_A5_KEY_LEN+2];
|
||||
rc = build_encr_info(encr_info, lchan);
|
||||
if (rc > 0)
|
||||
|
|
|
@ -226,7 +226,7 @@ static void send_assignment_complete(struct gsm_subscriber_connection *conn)
|
|||
|
||||
resp = gsm0808_create_ass_compl2(lchan->abis_ip.ass_compl.rr_cause,
|
||||
chosen_channel,
|
||||
lchan->encr.alg_id, perm_spch,
|
||||
ALG_A5_NR_TO_BSSAP(lchan->encr.alg_a5_n), perm_spch,
|
||||
addr_local_p, sc_ptr, NULL, lcls_get_status(conn));
|
||||
|
||||
if (!resp) {
|
||||
|
|
|
@ -368,16 +368,14 @@ int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv)
|
|||
{
|
||||
struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 CIPH");
|
||||
struct gsm48_hdr *gh;
|
||||
uint8_t ciph_mod_set;
|
||||
uint8_t ciph_mod_set = 0x00;
|
||||
|
||||
msg->lchan = lchan;
|
||||
|
||||
DEBUGP(DRR, "TX CIPHERING MODE CMD\n");
|
||||
|
||||
if (lchan->encr.alg_id <= ALG_A5_NR_TO_RSL(0))
|
||||
ciph_mod_set = 0;
|
||||
else
|
||||
ciph_mod_set = (lchan->encr.alg_id-2)<<1 | 1;
|
||||
if (lchan->encr.alg_a5_n > 0)
|
||||
ciph_mod_set = (lchan->encr.alg_a5_n - 1) << 1 | 0x01;
|
||||
|
||||
gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
|
||||
gh->proto_discr = GSM48_PDISC_RR;
|
||||
|
@ -592,9 +590,8 @@ struct msgb *gsm48_make_ho_cmd(const struct gsm_lchan *new_lchan,
|
|||
* Shall be included in the case of inter-RAT handover. */
|
||||
if (ho_scope & HO_INTER_BSC_IN) {
|
||||
uint8_t cms = 0x00;
|
||||
/* This formula copied from gsm48_send_rr_ciph_mode() */
|
||||
if (new_lchan->encr.alg_id > ALG_A5_NR_TO_RSL(0))
|
||||
cms = (new_lchan->encr.alg_id - 2) << 1 | 1;
|
||||
if (new_lchan->encr.alg_a5_n > 0)
|
||||
cms = (new_lchan->encr.alg_a5_n - 1) << 1 | 1;
|
||||
/* T (4 bit) + V (4 bit), see 3GPP TS 44.018, 10.5.2.9 */
|
||||
msgb_v_put(msg, GSM48_IE_CIP_MODE_SET | (cms & 0x0f));
|
||||
}
|
||||
|
@ -1014,7 +1011,7 @@ static void dispatch_dtap(struct gsm_subscriber_connection *conn,
|
|||
osmo_fsm_inst_dispatch(conn->ho.fi, HO_EV_RR_HO_FAIL, msg);
|
||||
break;
|
||||
case GSM48_MT_RR_CIPH_M_COMPL:
|
||||
bsc_cipher_mode_compl(conn, msg, conn->lchan->encr.alg_id);
|
||||
bsc_cipher_mode_compl(conn, msg, conn->lchan->encr.alg_a5_n);
|
||||
break;
|
||||
case GSM48_MT_RR_ASS_COMPL:
|
||||
if (conn->assignment.fi)
|
||||
|
|
|
@ -85,7 +85,7 @@ void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn,
|
|||
}
|
||||
|
||||
/*! MS->MSC: Tell MSC that ciphering has been enabled. */
|
||||
void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, struct msgb *msg, uint8_t chosen_encr)
|
||||
void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, struct msgb *msg, uint8_t chosen_a5_n)
|
||||
{
|
||||
int rc;
|
||||
struct msgb *resp;
|
||||
|
@ -94,7 +94,7 @@ void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, struct msgb *
|
|||
return;
|
||||
|
||||
LOGP(DMSC, LOGL_DEBUG, "CIPHER MODE COMPLETE from MS, forwarding to MSC\n");
|
||||
resp = gsm0808_create_cipher_complete(msg, chosen_encr);
|
||||
resp = gsm0808_create_cipher_complete(msg, ALG_A5_NR_TO_BSSAP(chosen_a5_n));
|
||||
rate_ctr_inc(rate_ctr_group_get_ctr(conn->sccp.msc->msc_ctrs, MSC_CTR_BSSMAP_TX_DT1_CIPHER_COMPLETE));
|
||||
rc = osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_TX_SCCP, resp);
|
||||
if (rc != 0)
|
||||
|
|
|
@ -756,7 +756,7 @@ void handover_start_inter_bsc_in(struct gsm_subscriber_connection *conn,
|
|||
}
|
||||
|
||||
/* Put encryption info in the chan activation info */
|
||||
info.encr.alg_id = ALG_A5_NR_TO_RSL(chosen_a5_n);
|
||||
info.encr.alg_a5_n = chosen_a5_n;
|
||||
if (chosen_a5_n > 0) {
|
||||
if (req->ei.key_len > sizeof(info.encr.key)) {
|
||||
ho_fail(HO_RESULT_ERROR, "Encryption Information IE key length is too large: %u",
|
||||
|
@ -933,7 +933,7 @@ static void send_handover_performed(struct gsm_subscriber_connection *conn)
|
|||
ho_perf_params.chosen_channel_present = true;
|
||||
|
||||
/* Chosen Encryption Algorithm 3.2.2.44 */
|
||||
ho_perf_params.chosen_encr_alg = lchan->encr.alg_id;
|
||||
ho_perf_params.chosen_encr_alg = ALG_A5_NR_TO_BSSAP(lchan->encr.alg_a5_n);
|
||||
ho_perf_params.chosen_encr_alg_present = true;
|
||||
|
||||
if (ho->new_lchan->activate.info.requires_voice_stream) {
|
||||
|
|
|
@ -750,7 +750,7 @@ static void lchan_fsm_wait_ts_ready_onenter(struct osmo_fsm_inst *fi, uint32_t p
|
|||
: "none",
|
||||
gsm_lchant_name(lchan->type),
|
||||
gsm48_chan_mode_name(lchan->activate.ch_mode_rate.chan_mode),
|
||||
(lchan->activate.info.encr.alg_id ? : 1)-1,
|
||||
lchan->activate.info.encr.alg_a5_n,
|
||||
lchan->activate.info.encr.key_len ? osmo_hexdump_nospc(lchan->activate.info.encr.key,
|
||||
lchan->activate.info.encr.key_len) : "none");
|
||||
|
||||
|
|
|
@ -532,7 +532,7 @@ static int bssmap_handle_cipher_mode(struct gsm_subscriber_connection *conn,
|
|||
goto reject;
|
||||
}
|
||||
|
||||
conn->lchan->encr.alg_id = ALG_A5_NR_TO_RSL(chosen_cipher);
|
||||
conn->lchan->encr.alg_a5_n = chosen_cipher;
|
||||
if (enc_key_len) {
|
||||
conn->lchan->encr.key_len = enc_key_len;
|
||||
memcpy(conn->lchan->encr.key, enc_key, enc_key_len);
|
||||
|
@ -1436,7 +1436,7 @@ int bsc_tx_bssmap_ho_request_ack(struct gsm_subscriber_connection *conn, struct
|
|||
.l3_info_len = rr_ho_command->len,
|
||||
.chosen_channel_present = true,
|
||||
.chosen_channel = gsm0808_chosen_channel(new_lchan->type, new_lchan->current_ch_mode_rate.chan_mode),
|
||||
.chosen_encr_alg = new_lchan->encr.alg_id,
|
||||
.chosen_encr_alg = ALG_A5_NR_TO_BSSAP(new_lchan->encr.alg_a5_n),
|
||||
.chosen_speech_version = gsm0808_permitted_speech(new_lchan->type,
|
||||
new_lchan->current_ch_mode_rate.chan_mode),
|
||||
};
|
||||
|
@ -1506,7 +1506,7 @@ enum handover_result bsc_tx_bssmap_ho_complete(struct gsm_subscriber_connection
|
|||
|
||||
struct gsm0808_handover_complete params = {
|
||||
.chosen_encr_alg_present = true,
|
||||
.chosen_encr_alg = lchan->encr.alg_id,
|
||||
.chosen_encr_alg = ALG_A5_NR_TO_BSSAP(lchan->encr.alg_a5_n),
|
||||
|
||||
.chosen_channel_present = true,
|
||||
.chosen_channel = gsm0808_chosen_channel(lchan->type, lchan->current_ch_mode_rate.chan_mode),
|
||||
|
|
|
@ -1685,7 +1685,7 @@ void trau_send_frame() {}
|
|||
/* Stub */
|
||||
int osmo_bsc_sigtran_open_conn(struct gsm_subscriber_connection *conn, struct msgb *msg) { return 0; }
|
||||
void bsc_sapi_n_reject(struct gsm_subscriber_connection *conn, uint8_t dlci, enum gsm0808_cause cause) {}
|
||||
void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, struct msgb *msg, uint8_t chosen_encr) {}
|
||||
void bsc_cipher_mode_compl(struct gsm_subscriber_connection *conn, struct msgb *msg, uint8_t chosen_a5_n) {}
|
||||
int bsc_compl_l3(struct gsm_lchan *lchan, struct msgb *msg, uint16_t chosen_channel)
|
||||
{ return 0; }
|
||||
void bsc_dtap(struct gsm_subscriber_connection *conn, uint8_t link_id, struct msgb *msg) {}
|
||||
|
|
Loading…
Reference in New Issue