[PATCH] osmo-bsc[master]: Permit set of multiple different A5 ciphers

dexter gerrit-no-reply at lists.osmocom.org
Mon Feb 19 10:12:51 UTC 2018


Hello Harald Welte, Jenkins Builder,

I'd like you to reexamine a change.  Please visit

    https://gerrit.osmocom.org/6544

to look at the new patch set (#4).

Permit set of multiple different A5 ciphers

So far, the administrator had to pick one particular cipher which
would then be used throughout all subscribers/phones. This is a bit
impractical, as e.g. not all phones support A5/3.  Extend the VTY
command syntax in a backwards-compatible way to permit for multiple
ciphers.

The bit-mask of permitted ciphers from the MSC (sent in ASSIGNMENT
COMMAND) is intersected with the vty-configured mask a the BSC.
Finally, the best (highest) possible cipher is chosen.

Change-Id: I1d1c8131855bcab2392b4f27f6216bdb2fae10e0
Closes: OS#2461
---
M include/osmocom/bsc/gsm_data.h
M src/libbsc/bsc_vty.c
M src/libbsc/net_init.c
M src/osmo-bsc/osmo_bsc_bssap.c
4 files changed, 52 insertions(+), 21 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/44/6544/4

diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index 04dc696..77fda00 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -1191,7 +1191,8 @@
 	/* global parameters */
 	uint16_t country_code;
 	uint16_t network_code;
-	int a5_encryption;
+	/* bit-mask of permitted encryption algorithms. LSB=A5/0, MSB=A5/7 */
+	uint8_t a5_encryption_mask;
 	int neci;
 	struct handover_cfg *ho;
 
diff --git a/src/libbsc/bsc_vty.c b/src/libbsc/bsc_vty.c
index 64a92b2..3ce310a 100644
--- a/src/libbsc/bsc_vty.c
+++ b/src/libbsc/bsc_vty.c
@@ -1,5 +1,5 @@
 /* OpenBSC interface to quagga VTY */
-/* (C) 2009-2010 by Harald Welte <laforge at gnumonks.org>
+/* (C) 2009-2017 by Harald Welte <laforge at gnumonks.org>
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -192,13 +192,18 @@
 static void net_dump_vty(struct vty *vty, struct gsm_network *net)
 {
 	struct pchan_load pl;
+	int i;
 
 	vty_out(vty, "BSC is on Country Code %u, Network Code %u "
 		"and has %u BTS%s", net->country_code, net->network_code,
 		net->num_bts, VTY_NEWLINE);
 	vty_out(vty, "%s", VTY_NEWLINE);
-	vty_out(vty, "  Encryption: A5/%u%s", net->a5_encryption,
-		VTY_NEWLINE);
+	vty_out(vty, "  Encryption:");
+	for (i = 0; i < 8; i++) {
+		if (net->a5_encryption_mask & (1 << i))
+			vty_out(vty, " A5/%u", i);
+	}
+	vty_out(vty, "%s", VTY_NEWLINE);
 	vty_out(vty, "  NECI (TCH/H): %u%s", net->neci,
 		VTY_NEWLINE);
 	vty_out(vty, "  Use TCH for Paging any: %d%s", net->pag_any_tch,
@@ -917,11 +922,17 @@
 static int config_write_net(struct vty *vty)
 {
 	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+	int i;
 
 	vty_out(vty, "network%s", VTY_NEWLINE);
 	vty_out(vty, " network country code %u%s", gsmnet->country_code, VTY_NEWLINE);
 	vty_out(vty, " mobile network code %u%s", gsmnet->network_code, VTY_NEWLINE);
-	vty_out(vty, " encryption a5 %u%s", gsmnet->a5_encryption, VTY_NEWLINE);
+	vty_out(vty, " encryption a5");
+	for (i = 0; i < 8; i++) {
+		if (gsmnet->a5_encryption_mask & (1 << i))
+			vty_out(vty, " %u", i);
+	}
+	vty_out(vty, "%s", VTY_NEWLINE);
 	vty_out(vty, " neci %u%s", gsmnet->neci, VTY_NEWLINE);
 	vty_out(vty, " paging any use tch %d%s", gsmnet->pag_any_tch, VTY_NEWLINE);
 
@@ -4410,15 +4421,20 @@
 
 DEFUN(cfg_net_encryption,
       cfg_net_encryption_cmd,
-      "encryption a5 (0|1|2|3)",
-	"Encryption options\n"
-	"A5 encryption\n" "A5/0: No encryption\n"
-	"A5/1: Encryption\n" "A5/2: Export-grade Encryption\n"
-	"A5/3: 'New' Secure Encryption\n")
+      "encryption a5 <0-3> [<0-3>] [<0-3>] [<0-3>]",
+      "Encryption options\n"
+      "GSM A5 Air Interface Encryption\n"
+      "A5/n Algorithm Number\n"
+      "A5/n Algorithm Number\n"
+      "A5/n Algorithm Number\n"
+      "A5/n Algorithm Number\n")
 {
 	struct gsm_network *gsmnet = gsmnet_from_vty(vty);
+	unsigned int i;
 
-	gsmnet->a5_encryption = atoi(argv[0]);
+	gsmnet->a5_encryption_mask = 0;
+	for (i = 0; i < argc; i++)
+		gsmnet->a5_encryption_mask |= (1 << atoi(argv[i]));
 
 	return CMD_SUCCESS;
 }
diff --git a/src/libbsc/net_init.c b/src/libbsc/net_init.c
index 90f668f..d560b0c 100644
--- a/src/libbsc/net_init.c
+++ b/src/libbsc/net_init.c
@@ -50,6 +50,8 @@
 
 	net->country_code = country_code;
 	net->network_code = network_code;
+	/* Permit a compile-time default of A5/3 and A5/1 */
+	net->a5_encryption_mask = (1 << 3) | (1 << 1);
 
 	/* Use 30 min periodic update interval as sane default */
 	net->t3212 = 5;
diff --git a/src/osmo-bsc/osmo_bsc_bssap.c b/src/osmo-bsc/osmo_bsc_bssap.c
index 83c884c..a27610e 100644
--- a/src/osmo-bsc/osmo_bsc_bssap.c
+++ b/src/osmo-bsc/osmo_bsc_bssap.c
@@ -567,6 +567,19 @@
 	return 0;
 }
 
+/* select the best cipher permitted by the intersection of both masks */
+static int select_best_cipher(uint8_t msc_mask, uint8_t bsc_mask)
+{
+	uint8_t intersection = msc_mask & bsc_mask;
+	unsigned int i;
+
+	for (i = 7; i >= 0; i--) {
+		if (intersection & (1 << i))
+			return i;
+	}
+	return -1;
+}
+
 /*
  * GSM 08.08 § 3.1.9.1 and 3.2.1.21...
  * release our gsm_subscriber_connection and send message
@@ -626,8 +639,8 @@
 	int include_imeisv = 1;
 	const uint8_t *enc_key;
 	uint16_t enc_key_len;
-	uint8_t enc_bits_bsc;
 	uint8_t enc_bits_msc;
+	int chosen_cipher;
 
 	if (!conn) {
 		LOGP(DMSC, LOGL_ERROR, "No lchan/msc_data in cipher mode command.\n");
@@ -668,27 +681,26 @@
 	if (TLVP_PRESENT(&tp, GSM0808_IE_CIPHER_RESPONSE_MODE))
 		include_imeisv = TLVP_VAL(&tp, GSM0808_IE_CIPHER_RESPONSE_MODE)[0] & 0x1;
 
-	/* FIXME: match up the list of permitted ciphering algorithms received from the MSC with a list
-	 * of ciphering algorithms configured for this BSC (the config of more than one is TODO). Finally
-	 * pick one of the remaining options. */
-
 	/* Identical to the GSM0808_IE_ENCRYPTION_INFORMATION above:
 	 * a5_encryption == 0 --> 0x01
 	 * a5_encryption == 1 --> 0x02
 	 * a5_encryption == 2 --> 0x04 ... */
-	enc_bits_bsc = 1 << network->a5_encryption;
 	enc_bits_msc = data[0];
 
-	if (!(enc_bits_msc & enc_bits_bsc)) {
-		LOGP(DMSC, LOGL_ERROR, "MSC does not permit A5/%d (permitted algorithms mask: 0x%x)\n",
-		     network->a5_encryption, enc_bits_msc);
+	/* The bit-mask of permitted ciphers from the MSC (sent in ASSIGNMENT COMMAND) is intersected
+	 * with the vty-configured mask a the BSC.  Finally, the best (highest) possible cipher is
+	 * chosen. */
+	chosen_cipher = select_best_cipher(enc_bits_msc, network->a5_encryption_mask);
+	if (chosen_cipher < 0) {
+		LOGP(DMSC, LOGL_ERROR, "Reject: no overlapping A5 ciphers between BSC (0x%02x) "
+			"and MSC (0x%02x)\n", network->a5_encryption_mask, enc_bits_msc);
 		reject_cause = GSM0808_CAUSE_CIPHERING_ALGORITHM_NOT_SUPPORTED;
 		goto reject;
 	}
 
 	/* To complete the confusion, gsm0808_cipher_mode again expects the encryption as a number
 	 * from 0 to 7. */
-	if (gsm0808_cipher_mode(conn, network->a5_encryption, enc_key, enc_key_len,
+	if (gsm0808_cipher_mode(conn, chosen_cipher, enc_key, enc_key_len,
 				include_imeisv)) {
 		reject_cause = GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC;
 		goto reject;

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

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: I1d1c8131855bcab2392b4f27f6216bdb2fae10e0
Gerrit-PatchSet: 4
Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Owner: dexter <pmaier at sysmocom.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder


More information about the gerrit-log mailing list