[PATCH] openbsc[master]: SGSN: encrypt/decrypt only necessary frames

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.org
Wed Jul 6 10:35:44 UTC 2016


Review at  https://gerrit.osmocom.org/470

SGSN: encrypt/decrypt only necessary frames

According to 3GPP TS 24.008 § 4.7.1.2 some GMM frames are not supposed
to be ciphered. Propagate information about the necessity for
encryption between MM <-> LLC to ensure only proper frames are
encrypted/decrypted/dropped.

Change-Id: I0358905e60d1b182f75caec81bfcc72bbbbb2aa1
Related: OS#1582
---
M openbsc/include/openbsc/gprs_gmm.h
M openbsc/include/openbsc/gprs_llc.h
M openbsc/src/gprs/gprs_gmm.c
M openbsc/src/gprs/gprs_llc.c
M openbsc/src/gprs/gprs_sndcp.c
M openbsc/tests/sgsn/sgsn_test.c
6 files changed, 50 insertions(+), 34 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/openbsc refs/changes/70/470/1

diff --git a/openbsc/include/openbsc/gprs_gmm.h b/openbsc/include/openbsc/gprs_gmm.h
index e0d8f77..58449cb 100644
--- a/openbsc/include/openbsc/gprs_gmm.h
+++ b/openbsc/include/openbsc/gprs_gmm.h
@@ -4,13 +4,16 @@
 #include <osmocom/core/msgb.h>
 #include <openbsc/gprs_sgsn.h>
 
+#include <stdbool.h>
+
 int gsm48_tx_gsm_deact_pdp_req(struct sgsn_pdp_ctx *pdp, uint8_t sm_cause);
 int gsm48_tx_gsm_act_pdp_rej(struct sgsn_mm_ctx *mm, uint8_t tid,
 			     uint8_t cause, uint8_t pco_len, uint8_t *pco_v);
 int gsm48_tx_gsm_act_pdp_acc(struct sgsn_pdp_ctx *pdp);
 int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp);
 
-int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme);
+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);
 void gsm0408_gprs_access_granted(struct sgsn_mm_ctx *mmctx);
diff --git a/openbsc/include/openbsc/gprs_llc.h b/openbsc/include/openbsc/gprs_llc.h
index c48beb8..73870af 100644
--- a/openbsc/include/openbsc/gprs_llc.h
+++ b/openbsc/include/openbsc/gprs_llc.h
@@ -2,6 +2,7 @@
 #define _GPRS_LLC_H
 
 #include <stdint.h>
+#include <stdbool.h>
 #include <openbsc/gprs_sgsn.h>
 
 /* Section 4.7 LLC Layer Structure */
@@ -211,7 +212,7 @@
 
 /* LL-UNITDATA.req */
 int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command,
-		   void *mmctx);
+		   struct sgsn_mm_ctx *mmctx, bool encryptable);
 
 /* Chapter 7.2.1.2 LLGMM-RESET.req */
 int gprs_llgmm_reset(struct gprs_llc_llme *llme);
diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c
index 3df4e4a..e531bef 100644
--- a/openbsc/src/gprs/gprs_gmm.c
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -26,7 +26,7 @@
 #include <string.h>
 #include <stdint.h>
 #include <errno.h>
-
+#include <stdbool.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netdb.h>
@@ -130,13 +130,13 @@
 
 /* Send a message through the underlying layer */
 static int gsm48_gmm_sendmsg(struct msgb *msg, int command,
-			     struct sgsn_mm_ctx *mm)
+			     struct sgsn_mm_ctx *mm, bool encryptable)
 {
 	if (mm)
 		rate_ctr_inc(&mm->ctrg->ctr[GMM_CTR_PKTS_SIG_OUT]);
 
 	/* caller needs to provide TLLI, BVCI and NSEI */
-	return gprs_llc_tx_ui(msg, GPRS_SAPI_GMM, command, mm);
+	return gprs_llc_tx_ui(msg, GPRS_SAPI_GMM, command, mm, encryptable);
 }
 
 /* copy identifiers from old message to new message, this
@@ -194,7 +194,7 @@
 	}
 	gh->data[0] = cause;
 
-	return gsm48_gmm_sendmsg(msg, 0, mmctx);
+	return gsm48_gmm_sendmsg(msg, 0, mmctx, true);
 }
 
 static int gsm48_tx_gmm_status(struct sgsn_mm_ctx *mmctx, uint8_t cause)
@@ -232,7 +232,7 @@
 
 	msgb_tv_put(msg, GSM48_IE_GMM_CAUSE, cause);
 
-	return gsm48_gmm_sendmsg(msg, 0, mmctx);
+	return gsm48_gmm_sendmsg(msg, 0, mmctx, true);
 }
 
 static int gsm48_tx_gmm_detach_req(struct sgsn_mm_ctx *mmctx,
@@ -328,7 +328,7 @@
 	/* Optional: MS-identity (combined attach) */
 	/* Optional: GMM cause (partial attach result for combined attach) */
 
-	return gsm48_gmm_sendmsg(msg, 0, mm);
+	return gsm48_gmm_sendmsg(msg, 0, mm, true);
 }
 
 /* Chapter 9.4.5: Attach reject */
@@ -345,7 +345,7 @@
 	gh->msg_type = GSM48_MT_GMM_ATTACH_REJ;
 	gh->data[0] = gmm_cause;
 
-	return gsm48_gmm_sendmsg(msg, 0, NULL);
+	return gsm48_gmm_sendmsg(msg, 0, NULL, false);
 }
 static int gsm48_tx_gmm_att_rej_oldmsg(const struct msgb *old_msg,
 					uint8_t gmm_cause)
@@ -377,7 +377,7 @@
 	gh->msg_type = GSM48_MT_GMM_DETACH_ACK;
 	gh->data[0] = force_stby;
 
-	return gsm48_gmm_sendmsg(msg, 0, mm);
+	return gsm48_gmm_sendmsg(msg, 0, mm, true);
 }
 
 static int gsm48_tx_gmm_det_ack(struct sgsn_mm_ctx *mm, uint8_t force_stby)
@@ -413,7 +413,7 @@
 	/* 10.5.5.9 ID type 2 + identity type and 10.5.5.7 'force to standby' IE */
 	gh->data[0] = id_type & 0xf;
 
-	return gsm48_gmm_sendmsg(msg, 1, mm);
+	return gsm48_gmm_sendmsg(msg, 1, mm, false);
 }
 
 /* Section 9.4.9: Authentication and Ciphering Request */
@@ -454,7 +454,7 @@
 
 	/* FIXME: make sure we don't send any other messages to the MS */
 
-	return gsm48_gmm_sendmsg(msg, 1, mm);
+	return gsm48_gmm_sendmsg(msg, 1, mm, false);
 }
 
 /* Section 9.4.11: Authentication and Ciphering Reject */
@@ -471,7 +471,7 @@
 	gh->proto_discr = GSM48_PDISC_MM_GPRS;
 	gh->msg_type = GSM48_MT_GMM_AUTH_CIPH_REJ;
 
-	return gsm48_gmm_sendmsg(msg, 0, mm);
+	return gsm48_gmm_sendmsg(msg, 0, mm, false);
 }
 
 /* Section 9.4.10: Authentication and Ciphering Response */
@@ -1078,7 +1078,7 @@
 		    gprs_secs_to_tmr_floor(sgsn->cfg.timers.T3314));
 
 	/* Option: MS ID, ... */
-	return gsm48_gmm_sendmsg(msg, 0, mm);
+	return gsm48_gmm_sendmsg(msg, 0, mm, true);
 }
 
 /* Chapter 9.4.17: Routing area update reject */
@@ -1098,7 +1098,7 @@
 	gh->data[1] = 0; /* ? */
 
 	/* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */
-	return gsm48_gmm_sendmsg(msg, 0, NULL);
+	return gsm48_gmm_sendmsg(msg, 0, NULL, false);
 }
 
 static void process_ms_ctx_status(struct sgsn_mm_ctx *mmctx,
@@ -1312,13 +1312,19 @@
 
 /* GPRS Mobility Management */
 static int gsm0408_rcv_gmm(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
-			   struct gprs_llc_llme *llme)
+			   struct gprs_llc_llme *llme, bool drop_cipherable)
 {
 	struct sgsn_signal_data sig_data;
 	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
 	int rc;
 
 	/* MMCTX can be NULL when called */
+	if (drop_cipherable && gsm48_hdr_gmm_cipherable(gh)) {
+		LOGP(DMM, LOGL_NOTICE, "Dropping cleartext GMM %s which is "
+		     "expected to be encrypted\n",
+		     get_value_string(gprs_mt_gmm_names, gh->msg_type));
+		return -EBADMSG;
+	}
 
 	if (llme && !mmctx &&
 	    gh->msg_type != GSM48_MT_GMM_ATTACH_REQ &&
@@ -1631,7 +1637,7 @@
 
 	/* Optional: Packet Flow Identifier */
 
-	return gsm48_gmm_sendmsg(msg, 0, pdp->mm);
+	return gsm48_gmm_sendmsg(msg, 0, pdp->mm, true);
 }
 
 /* Section 9.5.3: Activate PDP Context reject */
@@ -1654,7 +1660,7 @@
 	if (pco_len && pco_v)
 		msgb_tlv_put(msg, GSM48_IE_GSM_PROTO_CONF_OPT, pco_len, pco_v);
 
-	return gsm48_gmm_sendmsg(msg, 0, mm);
+	return gsm48_gmm_sendmsg(msg, 0, mm, true);
 }
 
 /* Section 9.5.8: Deactivate PDP Context Request */
@@ -1675,7 +1681,7 @@
 
 	msgb_v_put(msg, sm_cause);
 
-	return gsm48_gmm_sendmsg(msg, 0, mm);
+	return gsm48_gmm_sendmsg(msg, 0, mm, true);
 }
 int gsm48_tx_gsm_deact_pdp_req(struct sgsn_pdp_ctx *pdp, uint8_t sm_cause)
 {
@@ -1699,7 +1705,7 @@
 	gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
 	gh->msg_type = GSM48_MT_GSM_DEACT_PDP_ACK;
 
-	return gsm48_gmm_sendmsg(msg, 0, mm);
+	return gsm48_gmm_sendmsg(msg, 0, mm, true);
 }
 int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp)
 {
@@ -2147,7 +2153,8 @@
 }
 
 /* Main entry point for incoming 04.08 GPRS messages from Gb */
-int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme)
+int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
+			   bool drop_cipherable)
 {
 	struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
 	uint8_t pdisc = gsm48_hdr_pdisc(gh);
@@ -2167,7 +2174,7 @@
 
 	switch (pdisc) {
 	case GSM48_PDISC_MM_GPRS:
-		rc = gsm0408_rcv_gmm(mmctx, msg, llme);
+		rc = gsm0408_rcv_gmm(mmctx, msg, llme, drop_cipherable);
 		break;
 	case GSM48_PDISC_SM_GPRS:
 		rc = gsm0408_rcv_gsm(mmctx, msg, llme);
diff --git a/openbsc/src/gprs/gprs_llc.c b/openbsc/src/gprs/gprs_llc.c
index 11e8358..c8ae6ea 100644
--- a/openbsc/src/gprs/gprs_llc.c
+++ b/openbsc/src/gprs/gprs_llc.c
@@ -21,6 +21,7 @@
 
 #include <errno.h>
 #include <stdint.h>
+#include <stdbool.h>
 
 #include <osmocom/core/msgb.h>
 #include <osmocom/core/linuxlist.h>
@@ -344,9 +345,12 @@
 	return gprs_llc_tx_u(msg, lle->sapi, command, GPRS_LLC_U_XID, 1);
 }
 
-/* Transmit a UI frame over the given SAPI */
+/* Transmit a UI frame over the given SAPI:
+   'encryptable' indicates whether particular message can be encrypted according
+   to 3GPP TS 24.008 § 4.7.1.2
+ */
 int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command,
-		   void *mmctx)
+		   struct sgsn_mm_ctx *mmctx, bool encryptable)
 {
 	struct gprs_llc_lle *lle;
 	uint8_t *fcs, *llch;
@@ -407,7 +411,7 @@
 	fcs[2] = (fcs_calc >> 16) & 0xff;
 
 	/* encrypt information field + FCS, if needed! */
-	if (lle->llme->algo != GPRS_ALGO_GEA0) {
+	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];
@@ -565,6 +569,7 @@
 	struct gprs_llc_hdr *lh = (struct gprs_llc_hdr *) msgb_llch(msg);
 	struct gprs_llc_hdr_parsed llhp;
 	struct gprs_llc_lle *lle;
+	bool drop_cipherable = false;
 	int rc = 0;
 
 	/* Identifiers from DOWN: NSEI, BVCI, TLLI */
@@ -637,11 +642,9 @@
 		for (i = 0; i < crypt_len; i++)
 			*(llhp.data + i) ^= cipher_out[i];
 	} else {
-		if (lle->llme->algo != GPRS_ALGO_GEA0) {
-			LOGP(DLLC, LOGL_NOTICE, "unencrypted frame for LLC "
-				"that is supposed to be encrypted. Dropping.\n");
-			return 0;
-		}
+		if (lle->llme->algo != GPRS_ALGO_GEA0 &&
+		    lle->llme->cksn != GSM_KEY_SEQ_INVAL)
+			drop_cipherable = true;
 	}
 
 	/* We have to do the FCS check _after_ decryption */
@@ -666,7 +669,8 @@
 		switch (llhp.sapi) {
 		case GPRS_SAPI_GMM:
 			/* send LL_UNITDATA_IND to GMM */
-			rc = gsm0408_gprs_rcvmsg_gb(msg, lle->llme);
+			rc = gsm0408_gprs_rcvmsg_gb(msg, lle->llme,
+						    drop_cipherable);
 			break;
 		case GPRS_SAPI_SNDCP3:
 		case GPRS_SAPI_SNDCP5:
diff --git a/openbsc/src/gprs/gprs_sndcp.c b/openbsc/src/gprs/gprs_sndcp.c
index 46d779b..75f95c9 100644
--- a/openbsc/src/gprs/gprs_sndcp.c
+++ b/openbsc/src/gprs/gprs_sndcp.c
@@ -22,6 +22,7 @@
 
 #include <errno.h>
 #include <stdint.h>
+#include <stdbool.h>
 
 #include <osmocom/core/msgb.h>
 #include <osmocom/core/linuxlist.h>
@@ -417,7 +418,7 @@
 	/* set the MORE bit of the SNDCP header accordingly */
 	sch->more = more;
 
-	rc = gprs_llc_tx_ui(fmsg, lle->sapi, 0, fs->mmcontext);
+	rc = gprs_llc_tx_ui(fmsg, lle->sapi, 0, fs->mmcontext, true);
 	/* abort in case of error, do not advance frag_nr / next_byte */
 	if (rc < 0) {
 		msgb_free(fs->msg);
@@ -498,7 +499,7 @@
 	sch->type = 1;
 	sch->nsapi = nsapi;
 
-	return gprs_llc_tx_ui(msg, lle->sapi, 0, mmcontext);
+	return gprs_llc_tx_ui(msg, lle->sapi, 0, mmcontext, true);
 }
 
 /* Section 5.1.2.17 LL-UNITDATA.ind */
diff --git a/openbsc/tests/sgsn/sgsn_test.c b/openbsc/tests/sgsn/sgsn_test.c
index 59e422c..ef07976 100644
--- a/openbsc/tests/sgsn/sgsn_test.c
+++ b/openbsc/tests/sgsn/sgsn_test.c
@@ -196,7 +196,7 @@
 	msg = create_msg(data, data_len);
 	msgb_tlli(msg) = tlli;
 	bssgp_create_cell_id(msgb_bcid(msg), bssgp_raid, 0);
-	gsm0408_gprs_rcvmsg_gb(msg, llme);
+	gsm0408_gprs_rcvmsg_gb(msg, llme, false);
 	msgb_free(msg);
 }
 

-- 
To view, visit https://gerrit.osmocom.org/470
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0358905e60d1b182f75caec81bfcc72bbbbb2aa1
Gerrit-PatchSet: 1
Gerrit-Project: openbsc
Gerrit-Branch: master
Gerrit-Owner: Max <msuraev at sysmocom.de>



More information about the gerrit-log mailing list