[PATCH] openbsc[master]: SGSN: move cipher application to separate function

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 14:22:20 UTC 2016


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

SGSN: move cipher application to separate function

FCS-related corrections were contributed by Dieter Spaar.

Change-Id: Ied74fcd971edba793b5a0958eb66707e5fa94074
Related: OS#1582
---
M openbsc/src/gprs/gprs_llc.c
1 file changed, 53 insertions(+), 46 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/openbsc refs/changes/79/479/1

diff --git a/openbsc/src/gprs/gprs_llc.c b/openbsc/src/gprs/gprs_llc.c
index c8ae6ea..fb4f02e 100644
--- a/openbsc/src/gprs/gprs_llc.c
+++ b/openbsc/src/gprs/gprs_llc.c
@@ -345,6 +345,46 @@
 	return gprs_llc_tx_u(msg, lle->sapi, command, GPRS_LLC_U_XID, 1);
 }
 
+/* encrypt information field + FCS, if needed! */
+static bool apply_gea(struct gprs_llc_lle *lle, uint16_t crypt_len, uint16_t nu,
+		     uint32_t oc, uint8_t sapi, uint8_t *fcs, uint8_t *data)
+{
+	uint8_t cipher_out[GSM0464_CIPH_MAX_BLOCK];
+
+	if (lle->llme->algo == GPRS_ALGO_GEA0)
+		return false;
+
+	/* Compute the 'Input' Paraemeter */
+	uint32_t fcs_calc, iv = gprs_cipher_gen_input_ui(lle->llme->iov_ui, sapi,
+							 nu, oc);
+	/* Compute gamma that we need to XOR with the data */
+	int r = gprs_cipher_run(cipher_out, crypt_len, lle->llme->algo,
+				lle->llme->kc, iv,
+				fcs ? GPRS_CIPH_SGSN2MS : GPRS_CIPH_MS2SGSN);
+	if (r < 0) {
+		LOGP(DLLC, LOGL_ERROR, "Error producing %s gamma for UI "
+		     "frame: %d\n", get_value_string(gprs_cipher_names,
+						     lle->llme->algo), r);
+		return false;
+	}
+
+	if (fcs) {
+		/* Mark frame as encrypted and update FCS */
+		data[2] |= 0x02;
+		fcs_calc = gprs_llc_fcs(data, fcs - data);
+		fcs[0] = fcs_calc & 0xff;
+		fcs[1] = (fcs_calc >> 8) & 0xff;
+		fcs[2] = (fcs_calc >> 16) & 0xff;
+		data += 3;
+	}
+
+	/* XOR the cipher output with the data */
+	for (r = 0; r < crypt_len; r++)
+		*(data + r) ^= cipher_out[r];
+
+	return true;
+}
+
 /* 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
@@ -410,33 +450,11 @@
 	fcs[1] = (fcs_calc >> 8) & 0xff;
 	fcs[2] = (fcs_calc >> 16) & 0xff;
 
-	/* 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;
-		int rc, i;
-		uint8_t *kc = lle->llme->kc;
-
-		/* Compute the 'Input' Paraemeter */
-		iv = gprs_cipher_gen_input_ui(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,
-				     kc, iv, GPRS_CIPH_SGSN2MS);
-		if (rc < 0) {
-			LOGP(DLLC, LOGL_ERROR, "Error crypting UI frame: %d\n", rc);
+		if (!apply_gea(lle, fcs - llch, nu, oc, sapi, fcs, llch)) {
 			msgb_free(msg);
-			return rc;
+			return -EINVAL;
 		}
-
-		/* 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) */
@@ -615,32 +633,21 @@
 
 	/* 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;
-		uint8_t *kc = lle->llme->kc;
-		int rc, i;
+		if (lle->llme->algo != GPRS_ALGO_GEA0) {
+			if (!apply_gea(lle, llhp.data_len + 3, llhp.seq_tx,
+				       lle->oc_ui_recv, lle->sapi, NULL,
+				       llhp.data))
+				return -EINVAL;
 
-		if (lle->llme->algo == GPRS_ALGO_GEA0) {
+		llhp.fcs = *(llhp.data + llhp.data_len);
+		llhp.fcs |= *(llhp.data + llhp.data_len + 1) << 8;
+		llhp.fcs |= *(llhp.data + llhp.data_len + 2) << 16;
+
+		} else {
 			LOGP(DLLC, LOGL_NOTICE, "encrypted frame for LLC that "
-				"has no KC/Algo! Dropping.\n");
+			     "has no KC/Algo! Dropping.\n");
 			return 0;
 		}
-
-		iv = gprs_cipher_gen_input_ui(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);
-		if (rc < 0) {
-			LOGP(DLLC, LOGL_ERROR, "Error decrypting frame: %d\n",
-			     rc);
-			return rc;
-		}
-
-		/* XOR the cipher output with the information field + FCS */
-		for (i = 0; i < crypt_len; i++)
-			*(llhp.data + i) ^= cipher_out[i];
 	} else {
 		if (lle->llme->algo != GPRS_ALGO_GEA0 &&
 		    lle->llme->cksn != GSM_KEY_SEQ_INVAL)

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

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



More information about the gerrit-log mailing list