[MERGED] openbsc[master]: SGSN: add preliminary support for GPRS encryption

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/.

Harald Welte gerrit-no-reply at lists.osmocom.org
Sat Jul 16 23:17:16 UTC 2016


Harald Welte has submitted this change and it was merged.

Change subject: SGSN: add preliminary support for GPRS encryption
......................................................................


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

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, 49 insertions(+), 31 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/openbsc/include/openbsc/gprs_gmm.h b/openbsc/include/openbsc/gprs_gmm.h
index e0d8f77..044978b 100644
--- a/openbsc/include/openbsc/gprs_gmm.h
+++ b/openbsc/include/openbsc/gprs_gmm.h
@@ -12,7 +12,8 @@
 
 int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme);
 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 f9a6dec..d7a480b 100644
--- a/openbsc/include/openbsc/gprs_llc.h
+++ b/openbsc/include/openbsc/gprs_llc.h
@@ -215,7 +215,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 9604084..723c914 100644
--- a/openbsc/include/openbsc/gprs_sgsn.h
+++ b/openbsc/include/openbsc/gprs_sgsn.h
@@ -357,9 +357,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 492c766..61edc65 100644
--- a/openbsc/src/gprs/gprs_gmm.c
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -418,9 +418,9 @@
 	return gsm48_gmm_sendmsg(msg, 1, mm);
 }
 
-/* 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;
@@ -437,9 +437,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: */
 	if (RAND_bytes(&rbyte, 1) != 1) {
 		LOGP(DMM, LOGL_NOTICE, "RAND_bytes failed for A&C ref, falling "
@@ -454,11 +456,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);
@@ -652,8 +654,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 &&
@@ -959,7 +960,15 @@
 		ctx->ms_radio_access_capa.len);
 	ctx->ms_network_capa.len = msnc_len;
 	memcpy(ctx->ms_network_capa.buf, msnc, msnc_len);
-
+	if (!gprs_ms_net_cap_gea_supported(ctx->ms_network_capa.buf, msnc_len,
+					   ctx->ciph_algo)) {
+		reject_cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
+		LOGMMCTXP(LOGL_NOTICE, ctx, "Rejecting ATTACH REQUEST with MI "
+			  "type %s because MS do not support required %s "
+			  "encryption\n", gsm48_mi_type_name(mi_type),
+			  get_value_string(gprs_cipher_names,ctx->ciph_algo));
+		goto rejected;
+	}
 #ifdef PTMSI_ALLOC
 	/* Allocate a new P-TMSI (+ P-TMSI signature) and update TLLI */
 	/* Don't change the P-TMSI if a P-TMSI re-assignment is under way */
@@ -1355,7 +1364,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);
@@ -1534,8 +1543,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 */
@@ -2094,7 +2102,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) {
@@ -2128,10 +2136,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 b271e21..bc856e9 100644
--- a/openbsc/src/gprs/gprs_llc.c
+++ b/openbsc/src/gprs/gprs_llc.c
@@ -22,6 +22,8 @@
 #include <errno.h>
 #include <stdint.h>
 
+#include <openssl/rand.h>
+
 #include <osmocom/core/msgb.h>
 #include <osmocom/core/linuxlist.h>
 #include <osmocom/core/timer.h>
@@ -598,7 +600,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;
 		}
@@ -769,13 +772,18 @@
 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];
+
+	if (RAND_bytes((uint8_t *) &llme->iov_ui, 4) != 1) {
+		LOGP(DLLC, LOGL_NOTICE, "RAND_bytes failed for LLC XID reset, "
+		     "falling back to rand()\n");
+		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;
@@ -787,15 +795,21 @@
 	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();
+
+	if (RAND_bytes((uint8_t *) &llme->iov_ui, 4) != 1) {
+		LOGP(DLLC, LOGL_NOTICE, "RAND_bytes failed for LLC XID reset, "
+		     "falling back to rand()\n");
+		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: merged
Gerrit-Change-Id: I8900b906693496e4e6b35be5a86937c58039ed9e
Gerrit-PatchSet: 9
Gerrit-Project: openbsc
Gerrit-Branch: master
Gerrit-Owner: Max <msuraev at sysmocom.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Holger Freyther <holger at freyther.de>
Gerrit-Reviewer: Jenkins Builder



More information about the gerrit-log mailing list