[MERGED] libosmocore[master]: Add GEA3 & GEA4 ciphers

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

Harald Welte gerrit-no-reply at lists.osmocom.org
Mon Jul 11 19:15:24 UTC 2016


Harald Welte has submitted this change and it was merged.

Change subject: Add GEA3 & GEA4 ciphers
......................................................................


Add GEA3 & GEA4 ciphers

Corresponding test code include both official test vectors from the
specs and data from over-the-air tests.

This obsoletes libosmo-crypt-a53 as it was last missing piece
unimplemented in libosmogsm.

Change-Id: I939e4f6b91b4a7c591ef3761fe2d46ed1c2fb2d3
Related: OS#1582
---
M .gitignore
M include/Makefile.am
M include/osmocom/crypt/gprs_cipher.h
A include/osmocom/gsm/gea.h
M src/gsm/Makefile.am
A src/gsm/gea.c
A src/gsm/gprs_gea.c
M tests/Makefile.am
A tests/gea/gea_test.c
A tests/gea/gea_test.ok
M tests/testsuite.at
11 files changed, 225 insertions(+), 5 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/.gitignore b/.gitignore
index 9cdf853..5165364 100644
--- a/.gitignore
+++ b/.gitignore
@@ -62,6 +62,7 @@
 tests/utils/utils_test
 tests/stats/stats_test
 tests/kasumi/kasumi_test
+tests/gea/gea_test
 tests/sms/sms_test
 tests/timer/timer_test
 tests/msgfile/msgfile_test
diff --git a/include/Makefile.am b/include/Makefile.am
index 7aa9c27..479e665 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -131,7 +131,7 @@
 
 noinst_HEADERS = \
 	osmocom/core/timer_compat.h \
-	osmocom/gsm/kasumi.h
+	osmocom/gsm/kasumi.h osmocom/gsm/gea.h
 
 osmocom/core/bit%gen.h: osmocom/core/bitXXgen.h.tpl
 	$(AM_V_GEN)$(MKDIR_P) $(dir $@)
diff --git a/include/osmocom/crypt/gprs_cipher.h b/include/osmocom/crypt/gprs_cipher.h
index d242595..c302f10 100644
--- a/include/osmocom/crypt/gprs_cipher.h
+++ b/include/osmocom/crypt/gprs_cipher.h
@@ -3,6 +3,8 @@
 #include <osmocom/core/linuxlist.h>
 #include <osmocom/core/utils.h>
 
+#include <stdint.h>
+
 #define GSM0464_CIPH_MAX_BLOCK	1523
 
 /* 3GPP TS 24.008 § 10.5.5.3 */
diff --git a/include/osmocom/gsm/gea.h b/include/osmocom/gsm/gea.h
new file mode 100644
index 0000000..3051101
--- /dev/null
+++ b/include/osmocom/gsm/gea.h
@@ -0,0 +1,17 @@
+/*
+ * GEA3 header
+ *
+ * See gea.c for details
+ */
+
+#pragma once
+
+#include <osmocom/crypt/gprs_cipher.h>
+
+#include <stdint.h>
+
+int gea3(uint8_t *out, uint16_t len, uint8_t *kc, uint32_t iv,
+	 enum gprs_cipher_direction direct);
+
+int gea4(uint8_t *out, uint16_t len, uint8_t *kc, uint32_t iv,
+	 enum gprs_cipher_direction direct);
diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am
index 781f153..0f43f48 100644
--- a/src/gsm/Makefile.am
+++ b/src/gsm/Makefile.am
@@ -24,10 +24,10 @@
 			conv_tch_afs_6_7_gen.c conv_tch_afs_5_9_gen.c \
 			conv_tch_afs_5_15_gen.c conv_tch_afs_4_75_gen.c \
 			auth_core.c auth_comp128v1.c auth_comp128v23.c \
-			auth_milenage.c milenage/aes-encblock.c \
+			auth_milenage.c milenage/aes-encblock.c gea.c \
 			milenage/aes-internal.c milenage/aes-internal-enc.c \
 			milenage/milenage.c gan.c ipa.c gsm0341.c apn.c \
-			gsup.c
+			gsup.c gprs_gea.c
 libgsmint_la_LDFLAGS = -no-undefined
 libgsmint_la_LIBADD = ../libosmocore.la
 
diff --git a/src/gsm/gea.c b/src/gsm/gea.c
new file mode 100644
index 0000000..b8f6768
--- /dev/null
+++ b/src/gsm/gea.c
@@ -0,0 +1,60 @@
+/*
+ * gea.c
+ *
+ * Implementation of GEA3 and GEA4
+ *
+ * Copyright (C) 2016 by Sysmocom s.f.m.c. GmbH
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <osmocom/core/bits.h>
+#include <osmocom/crypt/gprs_cipher.h>
+#include <osmocom/crypt/auth.h>
+#include <osmocom/gsm/kasumi.h>
+
+#include <stdint.h>
+#include <string.h>
+
+/*! \brief Performs the GEA4 algorithm as in 3GPP TS 55.226 V9.0.0
+ *  \param[in,out] out Buffer for gamma for encrypted/decrypted
+ *  \param[in] len Length of out, in bytes
+ *  \param[in] kc Buffer with the ciphering key
+ *  \param[in] iv Init vector
+ *  \param[in] direct Direction: 0 (MS -> SGSN) or 1 (SGSN -> MS)
+ */
+int gea4(uint8_t *out, uint16_t len, uint8_t *kc, uint32_t iv,
+	 enum gprs_cipher_direction direction)
+{
+	_kasumi_kgcore(0xFF, 0, iv, direction, kc, out, len * 8);
+	return 0;
+}
+
+/*! \brief Performs the GEA3 algorithm as in 3GPP TS 55.216 V6.2.0
+ *  \param[in,out] out Buffer for gamma for encrypted/decrypted
+ *  \param[in] len Length of out, in bytes
+ *  \param[in] kc Buffer with the ciphering key
+ *  \param[in] iv Init vector
+ *  \param[in] direct Direction: 0 (MS -> SGSN) or 1 (SGSN -> MS)
+ */
+int gea3(uint8_t *out, uint16_t len, uint8_t *kc, uint32_t iv,
+	 enum gprs_cipher_direction direction)
+{
+	uint8_t ck[gprs_cipher_key_length(GPRS_ALGO_GEA4)];
+	osmo_c4(ck, kc);
+	return gea4(out, len, ck, iv, direction);
+}
diff --git a/src/gsm/gprs_gea.c b/src/gsm/gprs_gea.c
new file mode 100644
index 0000000..8ff1648
--- /dev/null
+++ b/src/gsm/gprs_gea.c
@@ -0,0 +1,48 @@
+/*
+ * gprs_gea.c
+ *
+ * GEA 3 & 4 plugin
+ *
+ * Copyright (C) 2016 by Sysmocom s.f.m.c. GmbH
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <osmocom/crypt/gprs_cipher.h>
+#include <osmocom/gsm/gea.h>
+
+#include <stdint.h>
+
+static struct gprs_cipher_impl gea3_impl = {
+	.algo = GPRS_ALGO_GEA3,
+	.name = "GEA3 (libosmogsm built-in)",
+	.priority = 100,
+	.run = &gea3,
+};
+
+static struct gprs_cipher_impl gea4_impl = {
+	.algo = GPRS_ALGO_GEA4,
+	.name = "GEA4 (libosmogsm built-in)",
+	.priority = 100,
+	.run = &gea4,
+};
+
+static __attribute__((constructor)) void on_dso_load_gea(void)
+{
+	gprs_cipher_register(&gea3_impl);
+	gprs_cipher_register(&gea4_impl);
+}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 73b2d6a..9b85e6d 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -7,7 +7,7 @@
                  conv/conv_test auth/milenage_test lapd/lapd_test	\
                  gsm0808/gsm0808_test gsm0408/gsm0408_test		\
 		 gb/bssgp_fc_test gb/gprs_bssgp_test gb/gprs_ns_test	\
-		 gprs/gprs_test	kasumi/kasumi_test			\
+		 gprs/gprs_test	kasumi/kasumi_test gea/gea_test		\
 		 logging/logging_test fr/fr_test codec/codec_test	\
 		 loggingrb/loggingrb_test strrb/strrb_test              \
 		 vty/vty_test comp128/comp128_test utils/utils_test	\
@@ -36,6 +36,9 @@
 
 auth_milenage_test_SOURCES = auth/milenage_test.c
 auth_milenage_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la
+
+gea_gea_test_SOURCES = gea/gea_test.c
+gea_gea_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la
 
 bits_bitrev_test_SOURCES = bits/bitrev_test.c
 bits_bitrev_test_LDADD = $(top_builddir)/src/libosmocore.la
@@ -146,7 +149,7 @@
              lapd/lapd_test.ok gsm0408/gsm0408_test.ok			\
              gsm0808/gsm0808_test.ok gb/bssgp_fc_tests.err		\
              gb/bssgp_fc_tests.ok gb/bssgp_fc_tests.sh			\
-             gb/gprs_bssgp_test.ok gb/gprs_ns_test.ok			\
+             gb/gprs_bssgp_test.ok gb/gprs_ns_test.ok gea/gea_test.ok	\
              gprs/gprs_test.ok kasumi/kasumi_test.ok codec/codec_test.ok \
              msgfile/msgfile_test.ok msgfile/msgconfig.cfg		\
              logging/logging_test.ok logging/logging_test.err		\
diff --git a/tests/gea/gea_test.c b/tests/gea/gea_test.c
new file mode 100644
index 0000000..ebccaaf
--- /dev/null
+++ b/tests/gea/gea_test.c
@@ -0,0 +1,68 @@
+#include <osmocom/core/bits.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/crypt/gprs_cipher.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+
+static inline void print_check(char *res, uint8_t *out, uint16_t len)
+{
+    uint8_t buf[len];
+    osmo_hexparse(res, buf, len);
+    if (0 != memcmp(buf, out, len)) {
+	printf("FAIL:\n");
+	printf("OUT: %s\n", osmo_hexdump_nospc(out, len));
+	printf("EXP: %s\n", osmo_hexdump_nospc(buf, len));
+    } else
+	    printf("\n");
+}
+
+static inline void test_gea(bool v4, char *kc, uint32_t iv, int dir,
+			    uint16_t len, char *res)
+{
+    uint8_t out[len], ck[256];
+    printf("len %d, dir %d, INPUT 0x%X -> ", len, dir, iv);
+    osmo_hexparse(kc, ck, len);
+    int t = gprs_cipher_run(out, len, v4 ? GPRS_ALGO_GEA4 : GPRS_ALGO_GEA3, ck,
+			    iv, dir);
+    printf("%s ", t < 0 ? strerror(-t) : "OK");
+    print_check(res, out, len);
+}
+
+static inline void real_gea(uint32_t iov_ui, uint8_t sapi, uint32_t lfn,
+			    uint32_t oc, enum gprs_cipher_direction d, char *kc,
+			    uint16_t len, char *res)
+{
+	test_gea(false, kc, gprs_cipher_gen_input_ui(iov_ui, sapi, lfn, oc), d,
+		 len, res);
+}
+
+int main(int argc, char **argv)
+{
+    printf("GEA3 support: %d\n", gprs_cipher_supported(GPRS_ALGO_GEA3));
+    printf("GEA4 support: %d\n", gprs_cipher_supported(GPRS_ALGO_GEA4));
+
+    /* GEA3 test vectors according to 3GPP TS 55.217 V6.1.0 and 55.218 V6.1.0 */
+    test_gea(false, "2BD6459F82C5BC00", 0x8E9421A3, 0, 59, "5F359709DE950D0105B17B6C90194280F880B48DCCDC2AFEED415DBEF4354EEBB21D073CCBBFB2D706BD7AFFD371FC96E3970D143DCB2624054826");
+    test_gea(false, "952C49104881FF48", 0x5064DB71, 0, 59, "FDC03D738C8E14FF0320E59AAF75760799E9DA78DD8F888471C4AEAAC1849633A26CD84F459D265B83D7D9B9A0B1E54F4D75E331640DF19E0DB0E0");
+    test_gea(false, "EFA8B2229E720C2A", 0x4BDBD5E5, 1, 59, "4718A2ADFC90590949DDADAB406EC3B925F1AF1214673909DAAB96BB4C18B1374BB1E99445A81CC856E47C6E49E9DBB9873D0831B2175CA1E109BA");
+    test_gea(false, "3451F23A43BD2C87", 0x893FE14F, 0, 59, "B46B1E284E3F8B63B86D9DF0915CFCEDDF2F061895BF9F82BF2593AE4847E94A4626C393CF8941CE15EA7812690D8415B88C5730FE1F5D410E16A2");
+    test_gea(false, "CAA2639BE82435CF", 0x8FE17885, 1, 59, "9FEFAF155A26CF35603E727CDAA87BA067FD84FF98A50B7FF0EC8E95A0FB70E79CB93DEE2B7E9AB59D050E1262401571F349C68229DDF0DECC4E85");
+    test_gea(false, "1ACA8B448B767B39", 0x4F7BC3B5, 0, 59, "514F6C3A3B5A55CA190092F7BB6E80EF3EDB738FCDCE2FF90BB387DDE75BBC32A04A67B898A3DFB8198FFFC37D437CF69E7F9C13B51A868720E750");
+
+    /* GEA4 test vectors according to 3GPP TS 55.226 V9.0.0 */
+    test_gea(true, "D3C5D592327FB11C4035C6680AF8C6D1", 0x0A3A59B4, 0, 51, "6E217CE41EBEFB5EC8094C15974290065E42BABC9AE35654A53085CE68DFA4426A2FF0AD4AF3341006A3F84B7613ACB4FBDC34");
+    test_gea(true, "3D43C388C9581E337FF1F97EB5C1F85E", 0x48571AB9, 0, 59, "FC7314EF00A63ED0116F236C5D25C54EEC56A5B71F9F18B4D7941F84E422ACBDE5EEA9A204679002D14F312F3DEE2A1AC917C3FBDC3696143C0F5D");
+    test_gea(true, "A4496A64DF4F399F3B4506814A3E07A1", 0xEB04ADE2, 1, 59, "2AEB5970FB06B718027D048488AAF24FB3B74EA4A6B1242FF85B108FF816A303C72757D9AAD862B835D1D287DBC141D0A28D79D87BB137CD1198CD");
+
+    /* GEA3 test with real data */
+    real_gea(0, 3, 26, 0, GPRS_CIPH_SGSN2MS, "0c09c6ed723a8400", 199, "b08edbbb7f0532ccbd9fef6e1917fa6815e6d7fa4c9ee629f89299ef9a5541bb23f05875487113c5d5166b7fd0bd04215c60cf8dc404f6cbbfb137191e87f5250a311e34c583f7d8a35346e35f287722b6f234b95b67037ee0711b25fbf8ee3fcb354ee2ba1981e57ce3eeaa4f7401a6a8328994c25b359821e4e7ee242f7daf4e597e006b9cce0b9e86d97cd1ff83a021203b93e83457f64f9794d4388e9b7c509ca5ad278b10082fa20d7ac48aea4cb787c19fcbcea95d63bc17e840380adc86688bcf293f2e");
+    real_gea(0, 3, 25, 0, GPRS_CIPH_SGSN2MS, "0c09c6ed723a8400", 77, "91d2a1a85f6bb00429d76dcd1ca27f50c52e079ee9e990afc8635e25fa8c1007fac52e77035fd09821db893843c7a0666c4e69b5ecd3c9e4e7dc3405e4535115a650eebf698674e248ef13575c");
+    real_gea(0, 3, 20, 0, GPRS_CIPH_MS2SGSN, "bf4575e165fec400", 134, "c43845418e7fc4b3651bc9c3cc9af0163373126c0b31f85d192280e20c981f426dc4a0514a377f76da3d1672c6a0f463513608b3291bacd5d17bb44c8cc5383c3cc85de94e9c594e0fd61d4f2b74b452c1edf07eb04e0e67f352337cc0fd932936841fa41ee5ff0d8f3fad9625a9dec1f12726b74595a1c40d429926ba7e8461f3fa2ae2c0d3");
+    real_gea(0, 3, 21, 0, GPRS_CIPH_MS2SGSN, "bf4575e165fec400", 65, "7b4fc1922c183e6f61e8d2317216ed1d2497477d6f84947f8318df42621ad9affc0c42ba2fd63e06bce4720598d5ae919ca2996f2f1feaea2aa79827692471fd0a");
+
+    return 0;
+}
diff --git a/tests/gea/gea_test.ok b/tests/gea/gea_test.ok
new file mode 100644
index 0000000..c298752
--- /dev/null
+++ b/tests/gea/gea_test.ok
@@ -0,0 +1,15 @@
+GEA3 support: 1
+GEA4 support: 1
+len 59, dir 0, INPUT 0x8E9421A3 -> OK 
+len 59, dir 0, INPUT 0x5064DB71 -> OK 
+len 59, dir 1, INPUT 0x4BDBD5E5 -> OK 
+len 59, dir 0, INPUT 0x893FE14F -> OK 
+len 59, dir 1, INPUT 0x8FE17885 -> OK 
+len 59, dir 0, INPUT 0x4F7BC3B5 -> OK 
+len 51, dir 0, INPUT 0xA3A59B4 -> OK 
+len 59, dir 0, INPUT 0x48571AB9 -> OK 
+len 59, dir 1, INPUT 0xEB04ADE2 -> OK 
+len 199, dir 1, INPUT 0x9800001A -> OK 
+len 77, dir 1, INPUT 0x98000019 -> OK 
+len 134, dir 0, INPUT 0x98000014 -> OK 
+len 65, dir 0, INPUT 0x98000015 -> OK 
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 93373c1..0c7edf1 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -45,6 +45,12 @@
 AT_CHECK([$abs_top_builddir/tests/msgb/msgb_test], [0], [expout], [ignore])
 AT_CLEANUP
 
+AT_SETUP([gea])
+AT_KEYWORDS([gea])
+cat $abs_srcdir/gea/gea_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/gea/gea_test], [0], [expout])
+AT_CLEANUP
+
 if ENABLE_MSGFILE
 AT_SETUP([msgfile])
 AT_KEYWORDS([msgfile])

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I939e4f6b91b4a7c591ef3761fe2d46ed1c2fb2d3
Gerrit-PatchSet: 5
Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Owner: Max <msuraev at sysmocom.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder



More information about the gerrit-log mailing list