Change in libosmocore[master]: utils: osmo-aka-verify to verify UMTS AKA (SIM side)

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

laforge gerrit-no-reply at lists.osmocom.org
Sat Mar 20 11:00:27 UTC 2021


laforge has submitted this change. ( https://gerrit.osmocom.org/c/libosmocore/+/23404 )

Change subject: utils: osmo-aka-verify to verify UMTS AKA (SIM side)
......................................................................

utils: osmo-aka-verify to verify UMTS AKA (SIM side)

This new utility implements the UMTS AKA procedures of the SIM
side.  It can be used to manually verify the correctness of
authentication tuples received from the network.

Change-Id: I497747fbf09f633dcd7c592bd9af7fca9a820645
---
M debian/libosmocore-utils.install
M utils/Makefile.am
A utils/osmo-aka-verify.c
3 files changed, 247 insertions(+), 1 deletion(-)

Approvals:
  laforge: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/debian/libosmocore-utils.install b/debian/libosmocore-utils.install
index d23cc73..9501bec 100644
--- a/debian/libosmocore-utils.install
+++ b/debian/libosmocore-utils.install
@@ -1,3 +1,4 @@
 usr/bin/osmo-arfcn
 usr/bin/osmo-auc-gen
+usr/bin/osmo-aka-verify
 usr/bin/osmo-config-merge
diff --git a/utils/Makefile.am b/utils/Makefile.am
index 4e54a78..3f2b13f 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -8,12 +8,14 @@
 if ENABLE_UTILITIES
 EXTRA_DIST = conv_gen.py conv_codes_gsm.py
 
-bin_PROGRAMS += osmo-arfcn osmo-auc-gen osmo-config-merge
+bin_PROGRAMS += osmo-arfcn osmo-auc-gen osmo-config-merge osmo-aka-verify
 
 osmo_arfcn_SOURCES = osmo-arfcn.c
 
 osmo_auc_gen_SOURCES = osmo-auc-gen.c
 
+osmo_aka_verify_SOURCES = osmo-aka-verify.c
+
 osmo_config_merge_SOURCES = osmo-config-merge.c
 osmo_config_merge_LDADD = $(LDADD) $(TALLOC_LIBS)
 osmo_config_merge_CFLAGS = $(TALLOC_CFLAGS)
diff --git a/utils/osmo-aka-verify.c b/utils/osmo-aka-verify.c
new file mode 100644
index 0000000..5134d79
--- /dev/null
+++ b/utils/osmo-aka-verify.c
@@ -0,0 +1,243 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <getopt.h>
+
+#include <osmocom/core/utils.h>
+#include <osmocom/core/bit64gen.h>
+
+/* Utility program for implementing the SIM-side procedures of 3GPP Authentication and Key Agreement
+ * as specified by 3GPP TS 33.102 Section 6.3.3
+ *
+ * (C) 2021 by Harald Welte <laforge at gnumonks.org>
+ * Milenage library code used from libosmocore, which inherited it from wpa_supplicant
+ */
+
+/* FIXME: libosmogsm implements those, but doesn't declare them */
+int milenage_f1(const uint8_t *opc, const uint8_t *k, const uint8_t *_rand,
+		const uint8_t *sqn, const uint8_t *amf, uint8_t *mac_a, uint8_t *mac_s);
+int milenage_f2345(const uint8_t *opc, const uint8_t *k, const uint8_t *_rand,
+		   uint8_t *res, uint8_t *ck, uint8_t *ik, uint8_t *ak, uint8_t *akstar);
+
+static int milenage_check(const uint8_t *opc, const uint8_t *k, const uint8_t *sqn, const uint8_t *_rand,
+			  const uint8_t *autn, uint8_t *ik, uint8_t *ck, uint8_t *res, size_t *res_len,
+			  uint8_t *auts)
+{
+	int i;
+	uint8_t xmac[8], ak[6], rx_sqn_bin[6];
+	unsigned long long rx_sqn;
+	const uint8_t *amf;
+
+	printf("=== Static SIM parameters:\n");
+	printf("Milenage SIM K: %s\n", osmo_hexdump_nospc(k, 16));
+	printf("Milenage SIM OPc: %s\n", osmo_hexdump_nospc(opc, 16));
+	printf("Milenage SIM SQN: %s\n", osmo_hexdump_nospc(sqn, 6));
+	printf("\n");
+
+	printf("=== Authentication Tuple as received from Network:\n");
+	printf("Milenage Input RAND: %s\n", osmo_hexdump_nospc(_rand, 16));
+	printf("Milenage Input AUTN: %s\n", osmo_hexdump_nospc(autn, 16));
+	printf("\tAUTN(+)AK: %s\n", osmo_hexdump_nospc(autn, 6));
+	printf("\tAMF: %s\n", osmo_hexdump_nospc(autn+6, 2));
+	printf("\tMAC: %s\n", osmo_hexdump_nospc(autn+8, 8));
+	printf("\n");
+
+	if (milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL))
+		return -1;
+
+	*res_len = 8;
+	printf("Milenage f2-Computed RES: %s\n", osmo_hexdump_nospc(res, *res_len));
+	printf("Milenage f3-Computed CK: %s\n", osmo_hexdump_nospc(ck, 16));
+	printf("Milenage f4-Computed IK: %s\n", osmo_hexdump_nospc(ik, 16));
+	printf("Milenage f5-Computed AK: %s\n", osmo_hexdump_nospc(ak, 6));
+
+	/* AUTN = (SQN ^ AK) || AMF || MAC */
+	for (i = 0; i < 6; i++)
+		rx_sqn_bin[i] = autn[i] ^ ak[i];
+	rx_sqn = osmo_load64be_ext(rx_sqn_bin, 6);
+	printf("Milenage Computed SQN: %s (%llu)\n", osmo_hexdump_nospc(rx_sqn_bin, 6), rx_sqn);
+
+	if (memcmp(rx_sqn_bin, sqn, 6) <= 0) {
+		printf("Milenage: RX-SQN differs from SIM SQN: Re-Sync!\n");
+		uint8_t auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
+		if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
+			return -1;
+		printf("Milenage Computed AK*: %s", osmo_hexdump_nospc(ak, 6));
+		for (i = 0; i < 6; i++)
+			auts[i] = sqn[i] ^ ak[i];
+		if (milenage_f1(opc, k, _rand, sqn, auts_amf, NULL, auts + 6))
+			return -1;
+		printf("Milenage AUTS: %s\n", osmo_hexdump_nospc(auts, 14));
+		return -2;
+	}
+
+	amf = autn + 6;
+	if (milenage_f1(opc, k, _rand, rx_sqn_bin, amf, xmac, NULL))
+		return -1;
+
+	printf("Milenage f1-Computed XMAC: %s\n", osmo_hexdump_nospc(xmac, 8));
+
+	if (memcmp(xmac, autn + 8, 8) != 0) {
+		fprintf(stderr, "Milenage: MAC mismatch!\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static void help()
+{
+	printf( "Static SIM card parameters:\n"
+		"-k  --key\tSpecify Ki / K\n"
+		"-o  --opc\tSpecify OPC\n"
+		"-O  --op\tSpecify OP\n"
+		"-f  --amf\tSpecify AMF\n"
+		"-s  --sqn\tSpecify SQN\n"
+	        "\n"
+	        "Authentication Tuple by network:\n"
+		//"-i  --ind\tSpecify IND slot for new SQN after AUTS\n"
+		//"-l  --ind-len\tSpecify IND bit length (default=5)\n"
+		"-r  --rand\tSpecify RAND random value\n"
+		"-A  --autn\tSpecify AUTN authentication nonce\n"
+	      );
+}
+
+static uint8_t g_k[16];
+static uint8_t g_opc[16];
+static uint8_t g_rand[16];
+static uint8_t g_autn[16];
+static uint8_t g_amf[16];
+static unsigned long long g_sqn;
+
+
+static int handle_options(int argc, char **argv)
+{
+	int rc, option_index;
+	bool rand_is_set = false;
+	bool autn_is_set = false;
+	bool sqn_is_set = false;
+	bool k_is_set = false;
+	bool opc_is_set = false;
+	bool amf_is_set = false;
+	bool opc_is_op = false;
+
+	while (1) {
+		int c;
+		static struct option long_options[] = {
+			{ "key", 1, 0, 'k' },
+			{ "opc", 1, 0, 'o' },
+			{ "op", 1, 0, 'O' },
+			{ "amf", 1, 0, 'f' },
+			{ "sqn", 1, 0, 's' },
+			{ "rand", 1, 0, 'r' },
+			{ "autn", 1, 0, 'A' },
+			{ "help", 0, 0, 'h' },
+			{ 0, 0, 0, 0 }
+		};
+
+		rc = 0;
+
+		c = getopt_long(argc, argv, "k:o:O:f:s:r:A:h", long_options, &option_index);
+
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 'k':
+			rc = osmo_hexparse(optarg, g_k, sizeof(g_k));
+			k_is_set = true;
+			break;
+		case 'o':
+			rc = osmo_hexparse(optarg, g_opc, sizeof(g_opc));
+			opc_is_op = false;
+			opc_is_set = true;
+			break;
+		case 'O':
+			rc = osmo_hexparse(optarg, g_opc, sizeof(g_opc));
+			opc_is_op = true;
+			opc_is_set = true;
+			break;
+		case 'A':
+			rc = osmo_hexparse(optarg, g_autn, sizeof(g_autn));
+			autn_is_set = true;
+			break;
+		case 'f':
+			rc = osmo_hexparse(optarg, g_amf, sizeof(g_amf));
+			amf_is_set = true;
+			break;
+		case 's':
+			g_sqn = strtoull(optarg, 0, 10);
+			sqn_is_set = true;
+			break;
+		case 'r':
+			rc = osmo_hexparse(optarg, g_rand, sizeof(g_rand));
+			rand_is_set = true;
+			break;
+		case 'h':
+			help();
+			exit(0);
+		default:
+			help();
+			exit(1);
+		}
+
+		if (rc < 0) {
+			help();
+			fprintf(stderr, "\nError parsing argument of option `%c'\n", c);
+			exit(2);
+		}
+	}
+
+	if (!k_is_set || !opc_is_set || !autn_is_set || !rand_is_set) {
+		fprintf(stderr, "Error: K, OP[c], AUTN and RAND are mandatory arguments\n");
+		fprintf(stderr, "\n");
+		help();
+		exit(2);
+	}
+
+	if (!sqn_is_set)
+		printf("Warning: You may want to specify SQN\n");
+
+	if (!amf_is_set)
+		printf("Warning: You may want to specify AMF\n");
+
+	if (opc_is_op) {
+		/* FIXME */
+	}
+
+	return 0;
+}
+
+
+
+int main(int argc, char **argv)
+{
+	printf("osmo-aka-check (C) 2021 by Harald Welte\n");
+	printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
+
+	handle_options(argc, argv);
+
+	printf("\n");
+
+	uint8_t ck[16];
+	uint8_t ik[16];
+	uint8_t res[16];
+	size_t res_len;
+	uint8_t auts[14];
+	uint8_t sqn_bin[6];
+	int rc;
+
+	osmo_store64be_ext(g_sqn, sqn_bin, 6);
+
+	rc = milenage_check(g_opc, g_k, sqn_bin, g_rand, g_autn, ck, ik, res, &res_len, auts);
+
+	if (rc < 0) {
+		fprintf(stderr, "Authentication FAILED!\n");
+		exit(1);
+	} else {
+		printf("Authentication SUCCEEDED\n");
+		exit(0);
+	}
+}

-- 
To view, visit https://gerrit.osmocom.org/c/libosmocore/+/23404
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Change-Id: I497747fbf09f633dcd7c592bd9af7fca9a820645
Gerrit-Change-Number: 23404
Gerrit-PatchSet: 3
Gerrit-Owner: laforge <laforge at osmocom.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: pespin <pespin at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210320/f34acac8/attachment.htm>


More information about the gerrit-log mailing list