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/.
Max gerrit-no-reply at lists.osmocom.orgHello Jenkins Builder,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/460
to look at the new patch set (#5).
SGSN: add preliminary support for GPRS encryption
It is already functional enough to allow testing with real
phones. However, note - there are several limitations in the current
implementation:
* only default value for IOV-UI is supported at the moment
* AUTN-based key material is not supported
FCS-related corrections were contributed by Dieter Spaar.
Related: OS#1582
Change-Id: I8900b906693496e4e6b35be5a86937c58039ed9e
---
M openbsc/include/openbsc/gprs_gmm.h
M openbsc/include/openbsc/gprs_llc.h
M openbsc/include/openbsc/gprs_sgsn.h
M openbsc/src/gprs/gprs_gmm.c
M openbsc/src/gprs/gprs_llc.c
M openbsc/src/gprs/gprs_sgsn.c
6 files changed, 41 insertions(+), 38 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/openbsc refs/changes/60/460/5
diff --git a/openbsc/include/openbsc/gprs_gmm.h b/openbsc/include/openbsc/gprs_gmm.h
index 58449cb..8a3ffea 100644
--- a/openbsc/include/openbsc/gprs_gmm.h
+++ b/openbsc/include/openbsc/gprs_gmm.h
@@ -15,7 +15,8 @@
int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
bool drop_cipherable);
int gsm0408_gprs_force_reattach(struct sgsn_mm_ctx *mmctx);
-int gsm0408_gprs_force_reattach_oldmsg(struct msgb *msg);
+int gsm0408_gprs_force_reattach_oldmsg(struct msgb *msg,
+ struct gprs_llc_llme *llme);
void gsm0408_gprs_access_granted(struct sgsn_mm_ctx *mmctx);
void gsm0408_gprs_access_denied(struct sgsn_mm_ctx *mmctx, int gmm_cause);
void gsm0408_gprs_access_cancelled(struct sgsn_mm_ctx *mmctx, int gmm_cause);
diff --git a/openbsc/include/openbsc/gprs_llc.h b/openbsc/include/openbsc/gprs_llc.h
index 73870af..8a44741 100644
--- a/openbsc/include/openbsc/gprs_llc.h
+++ b/openbsc/include/openbsc/gprs_llc.h
@@ -216,7 +216,8 @@
/* Chapter 7.2.1.2 LLGMM-RESET.req */
int gprs_llgmm_reset(struct gprs_llc_llme *llme);
-int gprs_llgmm_reset_oldmsg(struct msgb* oldmsg, uint8_t sapi);
+int gprs_llgmm_reset_oldmsg(struct msgb* oldmsg, uint8_t sapi,
+ struct gprs_llc_llme *llme);
/* 04.64 Chapter 7.2.1.1 LLGMM-ASSIGN */
int gprs_llgmm_assign(struct gprs_llc_llme *llme,
diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h
index 3f91fb6..ce7b04b 100644
--- a/openbsc/include/openbsc/gprs_sgsn.h
+++ b/openbsc/include/openbsc/gprs_sgsn.h
@@ -356,9 +356,6 @@
char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len);
-/* Force re-attachment based on msgb meta data */
-int sgsn_force_reattach_oldmsg(struct msgb *oldmsg);
-
/*
* ctrl interface related work
*/
diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c
index e531bef..64cf8d6 100644
--- a/openbsc/src/gprs/gprs_gmm.c
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -416,9 +416,9 @@
return gsm48_gmm_sendmsg(msg, 1, mm, false);
}
-/* Section 9.4.9: Authentication and Ciphering Request */
+/* 3GPP TS 24.008 Section 9.4.9: Authentication and Ciphering Request */
static int gsm48_tx_gmm_auth_ciph_req(struct sgsn_mm_ctx *mm, uint8_t *rnd,
- uint8_t key_seq, uint8_t algo)
+ uint8_t key_seq, bool force_standby)
{
struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 AUTH CIPH REQ");
struct gsm48_hdr *gh;
@@ -435,9 +435,11 @@
gh->msg_type = GSM48_MT_GMM_AUTH_CIPH_REQ;
acreq = (struct gsm48_auth_ciph_req *) msgb_put(msg, sizeof(*acreq));
- acreq->ciph_alg = algo & 0xf;
+ acreq->ciph_alg = mm->ciph_algo & 0xf;
+ /* § 10.5.5.10: */
acreq->imeisv_req = 0x1;
- acreq->force_stby = 0x0;
+ /* § 10.5.5.7: */
+ acreq->force_stby = force_standby;
/* 3GPP TS 24.008 § 10.5.5.19: */
acreq->ac_ref_nr = rand();
mm->auth_ref = acreq->ac_ref_nr;
@@ -447,11 +449,11 @@
m_rand = msgb_put(msg, 16+1);
m_rand[0] = GSM48_IE_GMM_AUTH_RAND;
memcpy(m_rand + 1, rnd, 16);
-
+ /* § 10.5.1.2: */
m_cksn = msgb_put(msg, 1);
m_cksn[0] = (GSM48_IE_GMM_CIPH_CKSN << 4) | (key_seq & 0x07);
}
-
+ /* FIXME: add AUTN for 3g auth according to 3GPP TS 24.008 § 10.5.3.1.1 */
/* FIXME: make sure we don't send any other messages to the MS */
return gsm48_gmm_sendmsg(msg, 1, mm, false);
@@ -645,8 +647,7 @@
mmctx_timer_start(ctx, 3360, sgsn->cfg.timers.T3360);
return gsm48_tx_gmm_auth_ciph_req(ctx, at->vec.rand,
- at->key_seq,
- GPRS_ALGO_GEA0);
+ at->key_seq, false);
}
if (ctx->auth_state == SGSN_AUTH_AUTHENTICATE && ctx->is_authenticated &&
@@ -1354,7 +1355,7 @@
}
/* Force the MS to re-attach */
- rc = sgsn_force_reattach_oldmsg(msg);
+ rc = gsm0408_gprs_force_reattach_oldmsg(msg, llme);
/* TLLI unassignment */
gprs_llgmm_unassign(llme);
@@ -1533,8 +1534,7 @@
}
at = &mm->auth_triplet;
- gsm48_tx_gmm_auth_ciph_req(mm, at->vec.rand, at->key_seq,
- GPRS_ALGO_GEA0);
+ gsm48_tx_gmm_auth_ciph_req(mm, at->vec.rand, at->key_seq, false);
osmo_timer_schedule(&mm->timer, sgsn->cfg.timers.T3360, 0);
break;
case 3370: /* waiting for IDENTITY RESPONSE */
@@ -2093,7 +2093,7 @@
if (gh->msg_type == GSM48_MT_GSM_STATUS)
return 0;
- return sgsn_force_reattach_oldmsg(msg);
+ return gsm0408_gprs_force_reattach_oldmsg(msg, llme);
}
switch (gh->msg_type) {
@@ -2127,10 +2127,11 @@
return rc;
}
-int gsm0408_gprs_force_reattach_oldmsg(struct msgb *msg)
+int gsm0408_gprs_force_reattach_oldmsg(struct msgb *msg,
+ struct gprs_llc_llme *llme)
{
int rc;
- gprs_llgmm_reset_oldmsg(msg, GPRS_SAPI_GMM);
+ gprs_llgmm_reset_oldmsg(msg, GPRS_SAPI_GMM, llme);
rc = gsm48_tx_gmm_detach_req_oldmsg(
msg, GPRS_DET_T_MT_REATT_REQ, GMM_CAUSE_IMPL_DETACHED);
diff --git a/openbsc/src/gprs/gprs_llc.c b/openbsc/src/gprs/gprs_llc.c
index c8ae6ea..7d7c843 100644
--- a/openbsc/src/gprs/gprs_llc.c
+++ b/openbsc/src/gprs/gprs_llc.c
@@ -412,7 +412,6 @@
/* encrypt information field + FCS, if needed! */
if (lle->llme->algo != GPRS_ALGO_GEA0 && encryptable) {
- uint32_t iov_ui = 0; /* FIXME: randomly select for TLLI */
uint16_t crypt_len = (fcs + 3) - (llch + 3);
uint8_t cipher_out[GSM0464_CIPH_MAX_BLOCK];
uint32_t iv;
@@ -420,7 +419,7 @@
uint8_t *kc = lle->llme->kc;
/* Compute the 'Input' Paraemeter */
- iv = gprs_cipher_gen_input_ui(iov_ui, sapi, nu, oc);
+ iv = gprs_cipher_gen_input_ui(lle->llme->iov_ui, sapi, nu, oc);
/* Compute the keystream that we need to XOR with the data */
rc = gprs_cipher_run(cipher_out, crypt_len, lle->llme->algo,
@@ -431,12 +430,16 @@
return rc;
}
+ /* Mark frame as encrypted and update FCS */
+ llch[2] |= 0x02;
+ fcs_calc = gprs_llc_fcs(llch, fcs - llch);
+ fcs[0] = fcs_calc & 0xff;
+ fcs[1] = (fcs_calc >> 8) & 0xff;
+ fcs[2] = (fcs_calc >> 16) & 0xff;
+
/* XOR the cipher output with the information field + FCS */
for (i = 0; i < crypt_len; i++)
*(llch + 3 + i) ^= cipher_out[i];
-
- /* Mark frame as encrypted */
- ctrl[1] |= 0x02;
}
/* Identifiers passed down: (BVCI, NSEI) */
@@ -603,7 +606,8 @@
case GPRS_SAPI_SNDCP9:
case GPRS_SAPI_SNDCP11:
/* Ask an upper layer for help. */
- return sgsn_force_reattach_oldmsg(msg);
+ return gsm0408_gprs_force_reattach_oldmsg(msg,
+ lle->llme);
default:
break;
}
@@ -615,7 +619,6 @@
/* decrypt information field + FCS, if needed! */
if (llhp.is_encrypted) {
- uint32_t iov_ui = 0; /* FIXME: randomly select for TLLI */
uint16_t crypt_len = llhp.data_len + 3;
uint8_t cipher_out[GSM0464_CIPH_MAX_BLOCK];
uint32_t iv;
@@ -628,7 +631,7 @@
return 0;
}
- iv = gprs_cipher_gen_input_ui(iov_ui, lle->sapi, llhp.seq_tx,
+ iv = gprs_cipher_gen_input_ui(lle->llme->iov_ui, lle->sapi, llhp.seq_tx,
lle->oc_ui_recv);
rc = gprs_cipher_run(cipher_out, crypt_len, lle->llme->algo,
kc, iv, GPRS_CIPH_MS2SGSN);
@@ -641,6 +644,10 @@
/* XOR the cipher output with the information field + FCS */
for (i = 0; i < crypt_len; i++)
*(llhp.data + i) ^= cipher_out[i];
+
+ llhp.fcs = *(llhp.data + crypt_len - 3);
+ llhp.fcs |= *(llhp.data + crypt_len - 2) << 8;
+ llhp.fcs |= *(llhp.data + crypt_len - 1) << 16;
} else {
if (lle->llme->algo != GPRS_ALGO_GEA0 &&
lle->llme->cksn != GSM_KEY_SEQ_INVAL)
@@ -773,13 +780,12 @@
int gprs_llgmm_reset(struct gprs_llc_llme *llme)
{
struct msgb *msg = msgb_alloc_headroom(4096, 1024, "LLC_XID");
- int random = rand();
struct gprs_llc_lle *lle = &llme->lle[1];
-
+ llme->iov_ui = rand();
/* First XID component must be RESET */
msgb_put_xid_par(msg, GPRS_LLC_XID_T_RESET, 0, NULL);
/* randomly select new IOV-UI */
- msgb_put_xid_par(msg, GPRS_LLC_XID_T_IOV_UI, 4, (uint8_t *) &random);
+ msgb_put_xid_par(msg, GPRS_LLC_XID_T_IOV_UI, 4, (uint8_t *) &llme->iov_ui);
/* Reset some of the LLC parameters. See GSM 04.64, 8.5.3.1 */
lle->vu_recv = 0;
@@ -791,15 +797,16 @@
return gprs_llc_tx_xid(lle, msg, 1);
}
-int gprs_llgmm_reset_oldmsg(struct msgb* oldmsg, uint8_t sapi)
+int gprs_llgmm_reset_oldmsg(struct msgb* oldmsg, uint8_t sapi,
+ struct gprs_llc_llme *llme)
{
struct msgb *msg = msgb_alloc_headroom(4096, 1024, "LLC_XID");
- int random = rand();
+ llme->iov_ui = rand();
/* First XID component must be RESET */
msgb_put_xid_par(msg, GPRS_LLC_XID_T_RESET, 0, NULL);
/* randomly select new IOV-UI */
- msgb_put_xid_par(msg, GPRS_LLC_XID_T_IOV_UI, 4, (uint8_t *) &random);
+ msgb_put_xid_par(msg, GPRS_LLC_XID_T_IOV_UI, 4, (uint8_t *) &llme->iov_ui);
/* FIXME: Start T200, wait for XID response */
diff --git a/openbsc/src/gprs/gprs_sgsn.c b/openbsc/src/gprs/gprs_sgsn.c
index 711887e..c2f2d5b 100644
--- a/openbsc/src/gprs/gprs_sgsn.c
+++ b/openbsc/src/gprs/gprs_sgsn.c
@@ -169,6 +169,7 @@
ctx->gb.tlli = tlli;
ctx->mm_state = GMM_DEREGISTERED;
ctx->auth_triplet.key_seq = GSM_KEY_SEQ_INVAL;
+ ctx->ciph_algo = sgsn->cfg.cipher;
ctx->ctrg = rate_ctr_group_alloc(ctx, &mmctx_ctrg_desc, tlli);
INIT_LLIST_HEAD(&ctx->pdp_list);
@@ -602,11 +603,6 @@
}
return num;
-}
-
-int sgsn_force_reattach_oldmsg(struct msgb *oldmsg)
-{
- return gsm0408_gprs_force_reattach_oldmsg(oldmsg);
}
void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx)
--
To view, visit https://gerrit.osmocom.org/460
To unsubscribe, visit https://gerrit.osmocom.org/settings
Gerrit-MessageType: newpatchset
Gerrit-Change-Id: I8900b906693496e4e6b35be5a86937c58039ed9e
Gerrit-PatchSet: 5
Gerrit-Project: openbsc
Gerrit-Branch: master
Gerrit-Owner: Max <msuraev at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder