diff mbox

[7/8] bsc: Check for the rand and then generate a res

Message ID 1434362142-12650-7-git-send-email-holger@freyther.de
State Accepted
Headers show

Commit Message

Holger Freyther June 15, 2015, 9:55 a.m. UTC
From: Holger Hans Peter Freyther <holger@moiji-mobile.com>

Check if the NAT has sent 16 bytes of RAND and if a key
has been configured in the system and then generate a
result using milenage. The milenage res will be sent and
noth the four byte GSM SRES derivation.
---
 openbsc/include/openbsc/bsc_msc.h       |  2 +-
 openbsc/include/openbsc/osmo_msc_data.h |  3 ++
 openbsc/src/libbsc/bsc_msc.c            |  7 +++-
 openbsc/src/osmo-bsc/osmo_bsc_msc.c     | 58 ++++++++++++++++++++++++++++++---
 openbsc/src/osmo-bsc/osmo_bsc_vty.c     | 29 +++++++++++++++++
 openbsc/src/osmo-bsc_nat/bsc_nat.c      |  2 +-
 6 files changed, 94 insertions(+), 7 deletions(-)
diff mbox

Patch

diff --git a/openbsc/include/openbsc/bsc_msc.h b/openbsc/include/openbsc/bsc_msc.h
index 2eec163..39258d3 100644
--- a/openbsc/include/openbsc/bsc_msc.h
+++ b/openbsc/include/openbsc/bsc_msc.h
@@ -60,6 +60,6 @@  void bsc_msc_schedule_connect(struct bsc_msc_connection *);
 
 void bsc_msc_lost(struct bsc_msc_connection *);
 
-struct msgb *bsc_msc_id_get_resp(int fixed, const char *token);
+struct msgb *bsc_msc_id_get_resp(int fixed, const char *token, const uint8_t *res, int len);
 
 #endif
diff --git a/openbsc/include/openbsc/osmo_msc_data.h b/openbsc/include/openbsc/osmo_msc_data.h
index 2d863aa..ed38187 100644
--- a/openbsc/include/openbsc/osmo_msc_data.h
+++ b/openbsc/include/openbsc/osmo_msc_data.h
@@ -59,6 +59,9 @@  struct osmo_msc_data {
 
 	/* Connection data */
 	char *bsc_token;
+	uint8_t bsc_key[16];
+	uint8_t bsc_key_present;
+
 	int ping_timeout;
 	int pong_timeout;
 	struct osmo_timer_list ping_timer;
diff --git a/openbsc/src/libbsc/bsc_msc.c b/openbsc/src/libbsc/bsc_msc.c
index fc4530c..829ee2b 100644
--- a/openbsc/src/libbsc/bsc_msc.c
+++ b/openbsc/src/libbsc/bsc_msc.c
@@ -276,7 +276,7 @@  void bsc_msc_schedule_connect(struct bsc_msc_connection *con)
 	osmo_timer_schedule(&con->reconnect_timer, 5, 0);
 }
 
-struct msgb *bsc_msc_id_get_resp(int fixed, const char *token)
+struct msgb *bsc_msc_id_get_resp(int fixed, const char *token, const uint8_t *res, int len)
 {
 	struct msgb *msg;
 
@@ -302,6 +302,11 @@  struct msgb *bsc_msc_id_get_resp(int fixed, const char *token)
 		msgb_put_u8(msg, 0);
 		msgb_put_u8(msg, strlen(token) + 2);
 		msgb_tv_fixed_put(msg, IPAC_IDTAG_UNITNAME, strlen(token) + 1, (uint8_t *) token);
+		if (len > 0) {
+			msgb_put_u8(msg, 0);
+			msgb_put_u8(msg, len + 1);
+			msgb_tv_fixed_put(msg, 0x24, len, res);
+		}
 	} else {
 		msgb_l16tv_put(msg, strlen(token) + 1,
 			IPAC_IDTAG_UNITNAME, (uint8_t *) token);
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_msc.c b/openbsc/src/osmo-bsc/osmo_bsc_msc.c
index 5127ca8..773ee14 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_msc.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_msc.c
@@ -23,6 +23,7 @@ 
 #include <openbsc/bsc_nat.h>
 #include <osmocom/ctrl/control_cmd.h>
 #include <osmocom/ctrl/control_if.h>
+#include <osmocom/crypt/auth.h>
 #include <openbsc/debug.h>
 #include <openbsc/gsm_data.h>
 #include <openbsc/ipaccess.h>
@@ -44,7 +45,7 @@ 
 
 static void initialize_if_needed(struct bsc_msc_connection *conn);
 static void send_lacs(struct gsm_network *net, struct bsc_msc_connection *conn);
-static void send_id_get_response(struct osmo_msc_data *data, int fd);
+static void send_id_get_response(struct osmo_msc_data *data, int fd, struct msgb *inp);
 static void send_ping(struct osmo_msc_data *data);
 static void schedule_ping_pong(struct osmo_msc_data *data);
 
@@ -302,7 +303,7 @@  static int ipaccess_a_fd_cb(struct osmo_fd *bfd)
 		if (msg->l2h[0] == IPAC_MSGT_ID_ACK)
 			initialize_if_needed(data->msc_con);
 		else if (msg->l2h[0] == IPAC_MSGT_ID_GET) {
-			send_id_get_response(data, bfd->fd);
+			send_id_get_response(data, bfd->fd, msg);
 		} else if (msg->l2h[0] == IPAC_MSGT_PONG) {
 			osmo_timer_del(&data->pong_timer);
 		}
@@ -451,12 +452,61 @@  static void initialize_if_needed(struct bsc_msc_connection *conn)
 	}
 }
 
-static void send_id_get_response(struct osmo_msc_data *data, int fd)
+static int answer_challenge(struct osmo_msc_data *data, struct msgb *inp, struct osmo_auth_vector *vec)
+{
+	int ret;
+	struct tlv_parsed tvp;
+	const uint8_t *mrand;
+	uint8_t mrand_len;
+	struct osmo_sub_auth_data auth = {
+		.type		= OSMO_AUTH_TYPE_GSM,
+		.algo		= OSMO_AUTH_ALG_MILENAGE,
+	};
+
+	ret = ipa_ccm_idtag_parse_off(&tvp,
+				inp->l2h + 1,
+				msgb_l2len(inp) - 1, 1);
+	if (ret < 0) {
+		LOGP(DMSC, LOGL_ERROR, "ignoring IPA response "
+			"message with malformed TLVs: %s\n", osmo_hexdump(inp->l2h + 1,
+			msgb_l2len(inp) - 1));
+		return 0;
+	}
+
+	mrand = TLVP_VAL(&tvp, 0x23);
+	mrand_len = TLVP_LEN(&tvp, 0x23);
+	if (mrand_len != 16) {
+		LOGP(DMSC, LOGL_ERROR,
+			"RAND is not 16 bytes. Was %d\n",
+			mrand_len);
+		return 0;
+	}
+
+	/* copy the key */
+	memcpy(auth.u.umts.opc, data->bsc_key, 16);
+	memcpy(auth.u.umts.k, data->bsc_key, 16);
+	memset(auth.u.umts.amf, 0, 2);
+	auth.u.umts.sqn = 0;
+
+	/* generate the result */
+	memset(vec, 0, sizeof(*vec));
+	osmo_auth_gen_vec(vec, &auth, mrand);
+	return 1;
+}
+
+
+static void send_id_get_response(struct osmo_msc_data *data, int fd, struct msgb *inp)
 {
 	struct msc_signal_data sig;
 	struct msgb *msg;
+	struct osmo_auth_vector vec;
+	int valid = 0;
+
+	if (data->bsc_key_present)
+		valid = answer_challenge(data, inp, &vec);
 
-	msg = bsc_msc_id_get_resp(0, data->bsc_token);
+	msg = bsc_msc_id_get_resp(valid, data->bsc_token,
+			vec.res, valid ? vec.res_len : 0);
 	if (!msg)
 		return;
 	msc_queue_write(data->msc_con, msg, IPAC_PROTO_IPACCESS);
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_vty.c b/openbsc/src/osmo-bsc/osmo_bsc_vty.c
index 06ad77d..9a17cd0 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_vty.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_vty.c
@@ -107,6 +107,9 @@  static void write_msc(struct vty *vty, struct osmo_msc_data *msc)
 	vty_out(vty, "msc %d%s", msc->nr, VTY_NEWLINE);
 	if (msc->bsc_token)
 		vty_out(vty, " token %s%s", msc->bsc_token, VTY_NEWLINE);
+	if (msc->bsc_key_present)
+		vty_out(vty, " auth-key %s%s",
+			osmo_hexdump(msc->bsc_key, sizeof(msc->bsc_key)), VTY_NEWLINE);
 	if (msc->core_ncc != -1)
 		vty_out(vty, " core-mobile-network-code %d%s",
 			msc->core_ncc, VTY_NEWLINE);
@@ -231,6 +234,30 @@  DEFUN(cfg_net_bsc_token,
 	return CMD_SUCCESS;
 }
 
+DEFUN(cfg_net_bsc_key,
+      cfg_net_bsc_key_cmd,
+      "auth-key KEY",
+      "Authentication (secret) key configuration\n"
+      "Security key\n")
+{
+	struct osmo_msc_data *data = osmo_msc_data(vty);
+
+	osmo_hexparse(argv[0], data->bsc_key, sizeof(data->bsc_key));
+	data->bsc_key_present = 1;
+	return CMD_SUCCESS;
+}
+
+DEFUN(cfg_net_no_bsc_key, cfg_net_bsc_no_key_cmd,
+      "no auth-key",
+      NO_STR "Authentication (secret) key configuration\n")
+{
+	struct osmo_msc_data *data = osmo_msc_data(vty);
+
+	memset(data->bsc_key, 0, sizeof(data->bsc_key));
+	data->bsc_key_present = 0;
+	return CMD_SUCCESS;
+}
+
 DEFUN(cfg_net_bsc_ncc,
       cfg_net_bsc_ncc_cmd,
       "core-mobile-network-code <1-999>",
@@ -871,6 +898,8 @@  int bsc_vty_init_extra(void)
 	install_node(&msc_node, config_write_msc);
 	vty_install_default(MSC_NODE);
 	install_element(MSC_NODE, &cfg_net_bsc_token_cmd);
+	install_element(MSC_NODE, &cfg_net_bsc_key_cmd);
+	install_element(MSC_NODE, &cfg_net_bsc_no_key_cmd);
 	install_element(MSC_NODE, &cfg_net_bsc_ncc_cmd);
 	install_element(MSC_NODE, &cfg_net_bsc_mcc_cmd);
 	install_element(MSC_NODE, &cfg_net_bsc_lac_cmd);
diff --git a/openbsc/src/osmo-bsc_nat/bsc_nat.c b/openbsc/src/osmo-bsc_nat/bsc_nat.c
index 254ea42..9837709 100644
--- a/openbsc/src/osmo-bsc_nat/bsc_nat.c
+++ b/openbsc/src/osmo-bsc_nat/bsc_nat.c
@@ -394,7 +394,7 @@  static void initialize_msc_if_needed(struct bsc_msc_connection *msc_con)
 
 static void send_id_get_response(struct bsc_msc_connection *msc_con)
 {
-	struct msgb *msg = bsc_msc_id_get_resp(0, nat->token);
+	struct msgb *msg = bsc_msc_id_get_resp(0, nat->token, NULL, 0);
 	if (!msg)
 		return;