baseband-devel
Threads by month
- ----- 2026 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 1 participants
- 2024 discussions
---
.gitignore | 2 +-
include/osmocom/core/bitXXgen.h.tpl | 100 ++++++++++++++++++++++++++++++++++++
include/osmocom/core/bits.h | 45 +++++++++++++++-
tests/bits/bitrev_test.c | 92 ++++++++++++++++++++++++++++++++-
tests/bits/bitrev_test.ok | 22 ++++++++
5 files changed, 257 insertions(+), 4 deletions(-)
create mode 100644 include/osmocom/core/bitXXgen.h.tpl
diff --git a/.gitignore b/.gitignore
index 71b27f2..c85d04d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -89,7 +89,7 @@ doc/html.tar
src/crc*gen.c
include/osmocom/core/crc*gen.h
-
+include/osmocom/core/bit*gen.h
# vi files
*.sw?
diff --git a/include/osmocom/core/bitXXgen.h.tpl b/include/osmocom/core/bitXXgen.h.tpl
new file mode 100644
index 0000000..5714251
--- /dev/null
+++ b/include/osmocom/core/bitXXgen.h.tpl
@@ -0,0 +1,100 @@
+/*
+ * bitXXgen.h
+ *
+ * Copyright (C) 2014 Max <max.suraev(a)fairwaves.ru>
+ *
+ * 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 2 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.
+ */
+
+
+/* Load unaligned n-byte integer (little-endian encoding) into uintXX_t */
+static inline uintXX_t osmo_loadXXle_ext(const uint8_t *p, uint8_t n)
+{
+ uint8_t i;
+ uintXX_t r = 0;
+ for(i = 0; i < n; r |= ((uintXX_t)p[i] << (8 * i)), i++);
+ return r;
+}
+
+/* Load unaligned n-byte integer (big-endian encoding) into uintXX_t */
+static inline uintXX_t osmo_loadXXbe_ext(const uint8_t *p, uint8_t n)
+{
+ uint8_t i;
+ uintXX_t r = 0;
+ for(i = 0; i < n; r |= ((uintXX_t)p[i] << (XX - 8* (1 + i))), i++);
+ return r;
+}
+
+
+/* Store unaligned n-byte integer (little-endian encoding) into uintXX_t */
+static inline void osmo_storeXXle_ext(uintXX_t x, uint8_t *p, uint8_t n)
+{
+
+
+ uint8_t i;
+ for(i = 0; i < n; p[i] = (x >> i * 8) & 0xFF, i++);
+/*
+
+ uint8_t i, adj = 8 * (8 - n);
+ uintXX_t y = (x << adj) >> adj;
+ for(i = 0; i < n; p[i] = (y >> i * 8) & 0xFF, i++);
+*/
+}
+
+/* Store unaligned n-byte integer (big-endian encoding) into uintXX_t */
+static inline void osmo_storeXXbe_ext(uintXX_t x, uint8_t *p, uint8_t n)
+{
+ uint8_t i;
+ for(i = 0; i < n; p[i] = (x >> ((n - 1 - i) * 8)) & 0xFF, i++);
+
+/*
+ uint8_t i, adj = 8 * (8 - n);
+ uintXX_t y = (x << adj) >> adj;
+ for(i = 0; i < n; p[i] = (y >> ((n - 1 - i) * 8)) & 0xFF, i++);
+*/
+}
+
+
+/* Convenience function for most-used cases */
+
+
+/* Load unaligned XX-bit integer (little-endian encoding) */
+static inline uintXX_t osmo_loadXXle(const uint8_t *p)
+{
+ return osmo_loadXXle_ext(p, XX / 8);
+}
+
+/* Load unaligned XX-bit integer (big-endian encoding) */
+static inline uintXX_t osmo_loadXXbe(const uint8_t *p)
+{
+ return osmo_loadXXbe_ext(p, XX / 8);
+}
+
+
+/* Store unaligned XX-bit integer (little-endian encoding) */
+static inline void osmo_storeXXle(uintXX_t x, uint8_t *p)
+{
+ return osmo_storeXXle_ext(x, p, XX / 8);
+}
+
+/* Store unaligned XX-bit integer (big-endian encoding) */
+static inline void osmo_storeXXbe(uintXX_t x, uint8_t *p)
+{
+ return osmo_storeXXbe_ext(x, p, XX / 8);
+}
+
+
diff --git a/include/osmocom/core/bits.h b/include/osmocom/core/bits.h
index 4c68532..c636d71 100644
--- a/include/osmocom/core/bits.h
+++ b/include/osmocom/core/bits.h
@@ -2,7 +2,9 @@
#define _OSMO_BITS_H
#include <stdint.h>
-
+#include <stddef.h>
+#include <osmocom/core/bit32gen.h>
+#include <osmocom/core/bit64gen.h>
/*! \defgroup bits soft, unpacked and packed bits
* @{
*/
@@ -15,6 +17,37 @@ typedef int8_t sbit_t; /*!< \brief soft bit (-127...127) */
typedef uint8_t ubit_t; /*!< \brief unpacked bit (0 or 1) */
typedef uint8_t pbit_t; /*!< \brief packed bis (8 bits in a byte) */
+/* Load unaligned 16-bit integer (little-endian encoding) */
+static inline uint16_t osmo_load16le(const uint8_t *p)
+{
+ return p[0] | (p[1] << 8);
+}
+
+/* Load unaligned 16-bit integer (big-endian encoding) */
+static inline uint16_t osmo_load16be(const uint8_t *p)
+{
+ return (p[0] << 8) | p[1];
+}
+
+/* Store unaligned 16-bit integer (little-endian encoding) */
+static inline void osmo_store16le(uint16_t a, uint8_t *p)
+{
+ p[0] = a & 0xFF;
+ p[1] = (a >> 8) & 0xFF;
+}
+
+/* Store unaligned 16-bit integer (big-endian encoding) */
+static inline void osmo_store16be(uint16_t a, uint8_t *p)
+{
+ p[0] = (a >> 8) & 0xFF;
+ p[1] = a & 0xFF;
+}
+
+/*
+ Less trivial LE/BE functions are autogenerated
+ see included bitXXgen.h files
+*/
+
/*
NOTE on the endianess of pbit_t:
Bits in a pbit_t are ordered MSB first, i.e. 0x80 is the first bit.
@@ -73,6 +106,16 @@ uint32_t osmo_revbytebits_8(uint8_t x);
/* \brief reverse the bits of each byte in a given buffer */
void osmo_revbytebits_buf(uint8_t *buf, int len);
+/* \brief reverse the order of the bytes in a given buffer */
+void osmo_revbytes_buf(uint8_t *buf, size_t len);
+
+/* \brief left circular shift */
+static inline uint16_t rol16(uint16_t in, unsigned shift)
+{
+ return (in << shift) | (in >> (16 - shift));
+}
+
+
/*! @} */
#endif /* _OSMO_BITS_H */
diff --git a/tests/bits/bitrev_test.c b/tests/bits/bitrev_test.c
index 5eca990..6cf340e 100644
--- a/tests/bits/bitrev_test.c
+++ b/tests/bits/bitrev_test.c
@@ -1,8 +1,9 @@
-
+#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
+#include <time.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/bits.h>
@@ -10,11 +11,66 @@
static const uint8_t input[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
static const uint8_t exp_out[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
+char s[18], *p;
+
+void check_ls_64(uint8_t bytes)
+{
+ uint8_t T[bytes], D = (8 - bytes), A = 8 * D, C = 2 * D;
+ uint64_t _test = ((uint64_t)rand() << 32) + rand(), a_test = (_test << A) >> A;
+
+ osmo_store64be_ext(_test, T, bytes);
+ snprintf(s, 17, "%.16" PRIx64, a_test);
+ p = osmo_hexdump_nospc(T, bytes);
+ if (0 != memcmp(s + C, p, bytes)) {
+ printf("%s\t%s\t%u BE store FAILED!\n", s + C, p, bytes * 8);
+ } else printf("%u BE store OK\n", bytes * 8);
+
+ osmo_store64le_ext(_test, T, bytes);
+ if (osmo_load64le_ext(T, bytes) == a_test)
+ printf("%u LE OK\n", bytes * 8);
+ else
+ printf("%u LE FAILED on %s- loaded %.16" PRIx64 " instead of %.16" PRIx64 "\n", bytes * 8, osmo_hexdump(T, bytes), osmo_load64le_ext(T, bytes), a_test);
+
+ osmo_store64be_ext(_test, T, bytes);
+ if (osmo_load64be_ext(T, bytes) == (a_test << A))
+ printf("%u BE OK\n", bytes * 8);
+ else
+ printf("%u BE FAILED on %s- loaded %.16" PRIx64 " instead of %.16" PRIx64 "\n", bytes * 8, osmo_hexdump(T, bytes), osmo_load64be_ext(T, bytes), (a_test << A));
+}
+
+void check_ls_32(uint8_t bytes)
+{
+ uint8_t T[bytes], D = (4 - bytes), A = 8 * D, C = 2 * D;
+ uint32_t _test = rand(), a_test = (_test << A) >> A;
+
+ osmo_store32be_ext(_test, T, bytes);
+ snprintf(s, 17, "%.8" PRIx32, a_test);
+ p = osmo_hexdump_nospc(T, bytes);
+ if (0 != memcmp(s + C, p, bytes)) {
+ printf("%s\t%s\t%u BE store FAILED on %" PRIx32 "\n", s + C, p, bytes * 8, _test);
+ } else printf("%u BE store OK\n", bytes * 8);
+
+ osmo_store32le_ext(_test, T, bytes);
+ if (osmo_load32le_ext(T, bytes) == a_test)
+ printf("%u LE OK\n", bytes * 8);
+ else
+ printf("%u LE FAILED on %s- loaded %.8" PRIx32 " instead of %.8" PRIx32 "\n", bytes * 8, osmo_hexdump(T, bytes), osmo_load32le_ext(T, bytes), a_test);
+
+ osmo_store32be_ext(_test, T, bytes);
+ if (osmo_load32be_ext(T, bytes) == (a_test << A))
+ printf("%u BE OK\n", bytes * 8);
+ else
+ printf("%u BE FAILED on %s- loaded %.8" PRIx32 " instead of %.8" PRIx32 "\n", bytes * 8, osmo_hexdump(T, bytes), osmo_load32be_ext(T, bytes), (a_test << A));
+}
+
int main(int argc, char **argv)
{
- uint8_t out[ARRAY_SIZE(input)];
+ uint8_t out[ARRAY_SIZE(input)], test[8];
unsigned int offs;
+
+ srand(time(NULL));
+
for (offs = 0; offs < sizeof(out); offs++) {
uint8_t *start = out + offs;
uint8_t len = sizeof(out) - offs;
@@ -32,5 +88,37 @@ int main(int argc, char **argv)
printf("\n");
}
+ printf("checking byte packing...\n");
+
+ check_ls_64(8);
+ check_ls_64(7);
+ check_ls_64(6);
+ check_ls_64(5);
+ check_ls_32(4);
+ check_ls_32(3);
+
+ uint16_t _test16 = (uint16_t)rand();
+ osmo_store16be(_test16, test);
+
+ snprintf(s, 17, "%.4" PRIx16, _test16);
+ p = osmo_hexdump_nospc(test, 2);
+ if (0 != memcmp(s, p, 2)) {
+ printf ("%s\t", s);
+ printf ("%s\t", p);
+ printf("16 BE FAILED on %" PRIx16 "\n");
+ } else printf("16 BE store OK\n");
+
+ osmo_store16le(_test16, test);
+ if (osmo_load16le(test) == _test16)
+ printf("16 LE OK\n");
+ else
+ printf("16 LE FAILED: %s, %.4" PRIx16 ", %.4" PRIx16 "\n", osmo_hexdump(test, 2), osmo_load16le(test), _test16);
+
+ osmo_store16be(_test16, test);
+ if (osmo_load16be(test) == _test16)
+ printf("16 BE OK\n");
+ else
+ printf("16 BE FAILED: %s, %.4" PRIx16 ", %.4" PRIx16 "\n", osmo_hexdump(test, 2), osmo_load16be(test), _test16);
+
return 0;
}
diff --git a/tests/bits/bitrev_test.ok b/tests/bits/bitrev_test.ok
index 47f402f..0cbc4db 100644
--- a/tests/bits/bitrev_test.ok
+++ b/tests/bits/bitrev_test.ok
@@ -22,3 +22,25 @@ REVERSED: 02 01
INORDER: 80
REVERSED: 01
+checking byte packing...
+64 BE store OK
+64 LE OK
+64 BE OK
+56 BE store OK
+56 LE OK
+56 BE OK
+48 BE store OK
+48 LE OK
+48 BE OK
+40 BE store OK
+40 LE OK
+40 BE OK
+32 BE store OK
+32 LE OK
+32 BE OK
+24 BE store OK
+24 LE OK
+24 BE OK
+16 BE store OK
+16 LE OK
+16 BE OK
--
1.8.3.2
--------------030008030204080305010405
Content-Type: text/x-patch;
name="0002-Add-Kasumi-cipher-implementation.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="0002-Add-Kasumi-cipher-implementation.patch"
1
0
---
include/osmocom/core/bits.h | 282 +++++++++++++++++++++++++++++++++++++++++++-
include/osmocom/core/msgb.h | 23 ++--
src/gsm/libosmogsm.map | 27 +++++
tests/bits/bitrev_test.c | 134 ++++++++++++++++++++-
tests/bits/bitrev_test.ok | 15 +++
5 files changed, 467 insertions(+), 14 deletions(-)
diff --git a/include/osmocom/core/bits.h b/include/osmocom/core/bits.h
index 4c68532..9a7674c 100644
--- a/include/osmocom/core/bits.h
+++ b/include/osmocom/core/bits.h
@@ -2,7 +2,7 @@
#define _OSMO_BITS_H
#include <stdint.h>
-
+#include <stddef.h>
/*! \defgroup bits soft, unpacked and packed bits
* @{
*/
@@ -15,6 +15,276 @@ typedef int8_t sbit_t; /*!< \brief soft bit (-127...127) */
typedef uint8_t ubit_t; /*!< \brief unpacked bit (0 or 1) */
typedef uint8_t pbit_t; /*!< \brief packed bis (8 bits in a byte) */
+/* Load unaligned 16-bit integer (little-endian encoding) */
+static inline uint16_t osmo_load16le(const uint8_t *p)
+{
+ return p[0] | (p[1] << 8);
+}
+
+/* Load unaligned 16-bit integer (big-endian encoding) */
+static inline uint16_t osmo_load16be(const uint8_t *p)
+{
+ return (p[0] << 8) | p[1];
+}
+
+/* Load unaligned 24-bit integer (little-endian encoding) */
+static inline uint32_t osmo_load24le(const uint8_t *p)
+{
+ return p[0] | (p[1] << 8) | (p[2] << 16);
+}
+
+/* Load unaligned 24-bit integer (big-endian encoding) */
+static inline uint32_t osmo_load24be(const uint8_t *p)
+{
+ return (p[0] << 16) | (p[1] << 8) | p[2];
+}
+
+/* Load unaligned 32-bit integer (little-endian encoding) */
+static inline uint32_t osmo_load32le(const uint8_t *p)
+{
+ return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+}
+
+/* Load unaligned 32-bit integer (big-endian encoding) */
+static inline uint32_t osmo_load32be(const uint8_t *p)
+{
+ return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+}
+
+/* Load unaligned 40-bit integer (little-endian encoding) */
+static inline uint64_t osmo_load40le(const uint8_t *p)
+{
+ return p[0] |
+ ((uint64_t)p[1] << 8) |
+ ((uint64_t)p[2] << 16) |
+ ((uint64_t)p[3] << 24) |
+ ((uint64_t)p[4] << 32);
+}
+
+/* Load unaligned 40-bit integer (big-endian encoding) */
+static inline uint64_t osmo_load40be(const uint8_t *p)
+{
+ return ((uint64_t)p[0] << 32) |
+ ((uint64_t)p[1] << 24) |
+ ((uint64_t)p[2] << 16) |
+ ((uint64_t)p[3] << 8) |
+ p[4];
+
+}
+
+/* Load unaligned 48-bit integer (little-endian encoding) */
+static inline uint64_t osmo_load48le(const uint8_t *p)
+{
+ return p[0] |
+ ((uint64_t)p[1] << 8) |
+ ((uint64_t)p[2] << 16) |
+ ((uint64_t)p[3] << 24) |
+ ((uint64_t)p[4] << 32) |
+ ((uint64_t)p[5] << 40);
+}
+
+/* Load unaligned 48-bit integer (big-endian encoding) */
+static inline uint64_t osmo_load48be(const uint8_t *p)
+{
+ return ((uint64_t)p[0] << 40) |
+ ((uint64_t)p[1] << 32) |
+ ((uint64_t)p[2] << 24) |
+ ((uint64_t)p[3] << 16) |
+ ((uint64_t)p[4] << 8) |
+ p[5];
+}
+
+/* Load unaligned 56-bit integer (little-endian encoding) */
+static inline uint64_t osmo_load56le(const uint8_t *p)
+{
+ return p[0] |
+ ((uint64_t)p[1] << 8) |
+ ((uint64_t)p[2] << 16) |
+ ((uint64_t)p[3] << 24) |
+ ((uint64_t)p[4] << 32) |
+ ((uint64_t)p[5] << 40) |
+ ((uint64_t)p[6] << 48);
+}
+
+/* Load unaligned 56-bit integer (big-endian encoding) */
+static inline uint64_t osmo_load56be(const uint8_t *p)
+{
+ return ((uint64_t)p[0] << 48) |
+ ((uint64_t)p[1] << 40) |
+ ((uint64_t)p[2] << 32) |
+ ((uint64_t)p[3] << 24) |
+ ((uint64_t)p[4] << 16) |
+ ((uint64_t)p[5] << 8) |
+ p[6];
+}
+
+/* Load unaligned 64-bit integer (little-endian encoding) */
+static inline uint64_t osmo_load64le(const uint8_t *p)
+{
+ return p[0] |
+ ((uint64_t)p[1] << 8) |
+ ((uint64_t)p[2] << 16) |
+ ((uint64_t)p[3] << 24) |
+ ((uint64_t)p[4] << 32) |
+ ((uint64_t)p[5] << 40) |
+ ((uint64_t)p[6] << 48) |
+ ((uint64_t)p[7] << 56);
+}
+
+/* Load unaligned 64-bit integer (big-endian encoding) */
+static inline uint64_t osmo_load64be(const uint8_t *p)
+{
+ return ((uint64_t)p[0] << 56) |
+ ((uint64_t)p[1] << 48) |
+ ((uint64_t)p[2] << 40) |
+ ((uint64_t)p[3] << 32) |
+ ((uint64_t)p[4] << 24) |
+ ((uint64_t)p[5] << 16) |
+ ((uint64_t)p[6] << 8) |
+ p[7];
+}
+
+/* Store unaligned 16-bit integer (little-endian encoding) */
+static inline void osmo_store16le(uint16_t a, uint8_t *p)
+{
+ p[0] = a & 0xFF;
+ p[1] = (a >> 8) & 0xFF;
+}
+
+/* Store unaligned 16-bit integer (big-endian encoding) */
+static inline void osmo_store16be(uint16_t a, uint8_t *p)
+{
+ p[0] = (a >> 8) & 0xFF;
+ p[1] = a & 0xFF;
+}
+
+/* Store unaligned 24-bit integer (little-endian encoding) */
+static inline void osmo_store24le(uint32_t a, uint8_t *p)
+{
+ p[0] = a & 0xFF;
+ p[1] = (a >> 8) & 0xFF;
+ p[2] = (a >> 16) & 0xFF;
+}
+
+/* Store unaligned 24-bit integer (big-endian encoding) */
+static inline void osmo_store24be(uint32_t a, uint8_t *p)
+{
+ p[0] = (a >> 16) & 0xFF;
+ p[1] = (a >> 8) & 0xFF;
+ p[2] = a & 0xFF;
+}
+
+/* Store unaligned 32-bit integer (little-endian encoding) */
+static inline void osmo_store32le(uint32_t a, uint8_t *p)
+{
+ p[0] = a & 0xFF;
+ p[1] = (a >> 8) & 0xFF;
+ p[2] = (a >> 16) & 0xFF;
+ p[3] = (a >> 24) & 0xFF;
+}
+
+/* Store unaligned 32-bit integer (big-endian encoding) */
+static inline void osmo_store32be(uint32_t a, uint8_t *p)
+{
+ p[0] = (a >> 24) & 0xFF;
+ p[1] = (a >> 16) & 0xFF;
+ p[2] = (a >> 8) & 0xFF;
+ p[3] = a & 0xFF;
+}
+
+/* Store unaligned 40-bit integer (little-endian encoding) */
+static inline void osmo_store40le(uint64_t a, uint8_t *p)
+{
+ p[0] = a & 0xFF;
+ p[1] = (a >> 8) & 0xFF;
+ p[2] = (a >> 16) & 0xFF;
+ p[3] = (a >> 24) & 0xFF;
+ p[4] = (a >> 32) & 0xFF;
+}
+
+/* Store unaligned 40-bit integer (big-endian encoding) */
+static inline void osmo_store40be(uint64_t a, uint8_t *p)
+{
+ p[0] = (a >> 32) & 0xFF;
+ p[1] = (a >> 24) & 0xFF;
+ p[2] = (a >> 16) & 0xFF;
+ p[3] = (a >> 8) & 0xFF;
+ p[4] = a & 0xFF;
+}
+
+/* Store unaligned 48-bit integer (little-endian encoding) */
+static inline void osmo_store48le(uint64_t a, uint8_t *p)
+{
+ p[0] = a & 0xFF;
+ p[1] = (a >> 8) & 0xFF;
+ p[2] = (a >> 16) & 0xFF;
+ p[3] = (a >> 24) & 0xFF;
+ p[4] = (a >> 32) & 0xFF;
+ p[5] = (a >> 40) & 0xFF;
+}
+
+/* Store unaligned 48-bit integer (big-endian encoding) */
+static inline void osmo_store48be(uint64_t a, uint8_t *p)
+{
+ p[0] = (a >> 40) & 0xFF;
+ p[1] = (a >> 32) & 0xFF;
+ p[2] = (a >> 24) & 0xFF;
+ p[3] = (a >> 16) & 0xFF;
+ p[4] = (a >> 8) & 0xFF;
+ p[5] = a & 0xFF;
+}
+
+/* Store unaligned 56-bit integer (little-endian encoding) */
+static inline void osmo_store56le(uint64_t a, uint8_t *p)
+{
+ p[0] = a & 0xFF;
+ p[1] = (a >> 8) & 0xFF;
+ p[2] = (a >> 16) & 0xFF;
+ p[3] = (a >> 24) & 0xFF;
+ p[4] = (a >> 32) & 0xFF;
+ p[5] = (a >> 40) & 0xFF;
+ p[6] = (a >> 48) & 0xFF;
+}
+
+/* Store unaligned 56-bit integer (big-endian encoding) */
+static inline void osmo_store56be(uint64_t a, uint8_t *p)
+{
+ p[0] = (a >> 48) & 0xFF;
+ p[1] = (a >> 40) & 0xFF;
+ p[2] = (a >> 32) & 0xFF;
+ p[3] = (a >> 24) & 0xFF;
+ p[4] = (a >> 16) & 0xFF;
+ p[5] = (a >> 8) & 0xFF;
+ p[6] = a & 0xFF;
+}
+
+/* Store unaligned 64-bit integer (little-endian encoding) */
+static inline void osmo_store64le(uint64_t a, uint8_t *p)
+{
+ p[0] = a & 0xFF;
+ p[1] = (a >> 8) & 0xFF;
+ p[2] = (a >> 16) & 0xFF;
+ p[3] = (a >> 24) & 0xFF;
+ p[4] = (a >> 32) & 0xFF;
+ p[5] = (a >> 40) & 0xFF;
+ p[6] = (a >> 48) & 0xFF;
+ p[7] = (a >> 56) & 0xFF;
+}
+
+/* Store unaligned 64-bit integer (big-endian encoding) */
+static inline void osmo_store64be(uint64_t a, uint8_t *p)
+{
+
+ p[0] = (a >> 56) & 0xFF;
+ p[1] = (a >> 48) & 0xFF;
+ p[2] = (a >> 40) & 0xFF;
+ p[3] = (a >> 32) & 0xFF;
+ p[4] = (a >> 24) & 0xFF;
+ p[5] = (a >> 16) & 0xFF;
+ p[6] = (a >> 8) & 0xFF;
+ p[7] = a & 0xFF;
+}
+
/*
NOTE on the endianess of pbit_t:
Bits in a pbit_t are ordered MSB first, i.e. 0x80 is the first bit.
@@ -73,6 +343,16 @@ uint32_t osmo_revbytebits_8(uint8_t x);
/* \brief reverse the bits of each byte in a given buffer */
void osmo_revbytebits_buf(uint8_t *buf, int len);
+/* \brief reverse the order of the bytes in a given buffer */
+void osmo_revbytes_buf(uint8_t *buf, size_t len);
+
+/* \brief left circular shift */
+static inline uint16_t rol16(uint16_t in, unsigned shift)
+{
+ return (in << shift) | (in >> (16 - shift));
+}
+
+
/*! @} */
#endif /* _OSMO_BITS_H */
diff --git a/include/osmocom/core/msgb.h b/include/osmocom/core/msgb.h
index fe2733b..72fdc24 100644
--- a/include/osmocom/core/msgb.h
+++ b/include/osmocom/core/msgb.h
@@ -23,6 +23,7 @@
#include <stdint.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/utils.h>
+#include <osmocom/core/bits.h>
/*! \defgroup msgb Message buffers
* @{
@@ -204,8 +205,7 @@ static inline void msgb_put_u8(struct msgb *msgb, uint8_t word)
static inline void msgb_put_u16(struct msgb *msgb, uint16_t word)
{
uint8_t *space = msgb_put(msgb, 2);
- space[0] = word >> 8 & 0xFF;
- space[1] = word & 0xFF;
+ osmo_store16be(word, space);
}
/*! \brief append a uint32 value to the end of the message
@@ -215,10 +215,7 @@ static inline void msgb_put_u16(struct msgb *msgb, uint16_t word)
static inline void msgb_put_u32(struct msgb *msgb, uint32_t word)
{
uint8_t *space = msgb_put(msgb, 4);
- space[0] = word >> 24 & 0xFF;
- space[1] = word >> 16 & 0xFF;
- space[2] = word >> 8 & 0xFF;
- space[3] = word & 0xFF;
+ osmo_store32be(word, space);
}
/*! \brief remove data from end of message
@@ -235,6 +232,7 @@ static inline unsigned char *msgb_get(struct msgb *msgb, unsigned int len)
msgb->len -= len;
return tmp;
}
+
/*! \brief remove uint8 from end of message
* \param[in] msgb message buffer
* \returns 8bit value taken from end of msgb
@@ -244,6 +242,7 @@ static inline uint8_t msgb_get_u8(struct msgb *msgb)
uint8_t *space = msgb_get(msgb, 1);
return space[0];
}
+
/*! \brief remove uint16 from end of message
* \param[in] msgb message buffer
* \returns 16bit value taken from end of msgb
@@ -251,8 +250,9 @@ static inline uint8_t msgb_get_u8(struct msgb *msgb)
static inline uint16_t msgb_get_u16(struct msgb *msgb)
{
uint8_t *space = msgb_get(msgb, 2);
- return space[0] << 8 | space[1];
+ return osmo_load16be(space);
}
+
/*! \brief remove uint32 from end of message
* \param[in] msgb message buffer
* \returns 32bit value taken from end of msgb
@@ -260,7 +260,7 @@ static inline uint16_t msgb_get_u16(struct msgb *msgb)
static inline uint32_t msgb_get_u32(struct msgb *msgb)
{
uint8_t *space = msgb_get(msgb, 4);
- return space[0] << 24 | space[1] << 16 | space[2] << 8 | space[3];
+ return osmo_load32be(space);
}
/*! \brief prepend (push) some data to start of message
@@ -284,6 +284,7 @@ static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int len)
msgb->len += len;
return msgb->data;
}
+
/*! \brief remove (pull) a header from the front of the message buffer
* \param[in] msgb message buffer
* \param[in] len number of octets to be pulled
@@ -308,6 +309,7 @@ static inline uint8_t msgb_pull_u8(struct msgb *msgb)
uint8_t *space = msgb_pull(msgb, 1) - 1;
return space[0];
}
+
/*! \brief remove uint16 from front of message
* \param[in] msgb message buffer
* \returns 16bit value taken from end of msgb
@@ -315,8 +317,9 @@ static inline uint8_t msgb_pull_u8(struct msgb *msgb)
static inline uint16_t msgb_pull_u16(struct msgb *msgb)
{
uint8_t *space = msgb_pull(msgb, 2) - 2;
- return space[0] << 8 | space[1];
+ return osmo_load16be(space);
}
+
/*! \brief remove uint32 from front of message
* \param[in] msgb message buffer
* \returns 32bit value taken from end of msgb
@@ -324,7 +327,7 @@ static inline uint16_t msgb_pull_u16(struct msgb *msgb)
static inline uint32_t msgb_pull_u32(struct msgb *msgb)
{
uint8_t *space = msgb_pull(msgb, 4) - 4;
- return space[0] << 24 | space[1] << 16 | space[2] << 8 | space[3];
+ return osmo_load32be(space);
}
/*! \brief Increase headroom of empty msgb, reducing the tailroom
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index 9d15d66..7551c4a 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -22,6 +22,29 @@ abis_nm_test_name;
osmo_sitype_strs;
+osmo_load16le;
+osmo_load16be;
+osmo_load24le;
+osmo_load24be;
+osmo_load32le;
+osmo_load32be;
+osmo_load64le;
+osmo_load64be;
+osmo_store16le;
+osmo_store16be;
+osmo_store24le;
+osmo_store24be;
+osmo_store32le;
+osmo_store32be;
+osmo_store40le;
+osmo_store40be;
+osmo_store48le;
+osmo_store48be;
+osmo_store56le;
+osmo_store56be;
+osmo_store64le;
+osmo_store64be;
+
comp128;
dbm2rxlev;
@@ -196,6 +219,10 @@ osmo_a5;
osmo_a5_1;
osmo_a5_2;
+_kasumi;
+_kasumi_key_expand;
+_kasumi_kgcore;
+
osmo_auth_alg_name;
osmo_auth_alg_parse;
osmo_auth_gen_vec;
diff --git a/tests/bits/bitrev_test.c b/tests/bits/bitrev_test.c
index 5eca990..f82dbf3 100644
--- a/tests/bits/bitrev_test.c
+++ b/tests/bits/bitrev_test.c
@@ -1,4 +1,4 @@
-
+#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@@ -12,9 +12,10 @@ static const uint8_t exp_out[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x0
int main(int argc, char **argv)
{
- uint8_t out[ARRAY_SIZE(input)];
+ uint8_t out[ARRAY_SIZE(input)], test[8];
unsigned int offs;
-
+ char s[18], *p;
+
for (offs = 0; offs < sizeof(out); offs++) {
uint8_t *start = out + offs;
uint8_t len = sizeof(out) - offs;
@@ -32,5 +33,132 @@ int main(int argc, char **argv)
printf("\n");
}
+ printf("checking byte packing...\n");
+
+ uint64_t _test64 = ((uint64_t)rand() << 32) + rand();
+ osmo_store64be(_test64, test);
+
+ snprintf(s, 17, "%.16" PRIx64, _test64);
+ p = osmo_hexdump_nospc(test, 8);
+ if (0 != memcmp(s, p, 8)) {
+ printf ("%s\t", s);
+ printf ("%s\t", p);
+ printf("64 BE FAILED!\n");
+ } else printf("64 BE OK\n");
+
+ osmo_store64le(_test64, test);
+ if (osmo_load64le(test) == _test64)
+ printf("64 LE OK\n");
+ else
+ printf("64 LE FAILED: %s, %.16" PRIx64 ", %.16" PRIx64 "\n", osmo_hexdump(test, 8), osmo_load64le(test), _test64);
+
+
+ uint64_t _test56 = ((((uint64_t)rand() << 32) + rand()) << 8) >> 8;
+ osmo_store56be(_test56, test);
+
+ snprintf(s, 17, "%.14" PRIx64, _test56);
+ p = osmo_hexdump_nospc(test, 7);
+ if (0 != memcmp(s, p, 7)) {
+ printf ("%s\t", s);
+ printf ("%s\t", p);
+ printf("56 BE FAILED!\n");
+ } else printf("56 BE OK\n");
+
+ osmo_store56le(_test56, test);
+ if (osmo_load56le(test) == _test56)
+ printf("56 LE OK\n");
+ else
+ printf("56 LE FAILED: %s, %.14" PRIx64 ", %.14" PRIx64 "\n", osmo_hexdump(test, 7), osmo_load56le(test), _test56);
+
+
+ uint64_t _test48 = ((((uint64_t)rand() << 32) + rand()) << 16) >> 16;
+ osmo_store48be(_test48, test);
+
+ snprintf(s, 17, "%.12" PRIx64, _test48);
+ p = osmo_hexdump_nospc(test, 6);
+ if (0 != memcmp(s, p, 6)) {
+ printf ("%s\t", s);
+ printf ("%s\t", p);
+ printf("48 BE FAILED!\n");
+ } else printf("48 BE OK\n");
+
+ osmo_store48le(_test48, test);
+ if (osmo_load48le(test) == _test48)
+ printf("48 LE OK\n");
+ else
+ printf("48 LE FAILED: %s, %.12" PRIx64 ", %.12" PRIx64 "\n", osmo_hexdump(test, 6), osmo_load48le(test), _test48);
+
+
+ uint64_t _test40 = ((((uint64_t)rand() << 32) + rand()) << 24) >> 24;
+ osmo_store40be(_test40, test);
+
+ snprintf(s, 17, "%.10" PRIx64, _test40);
+ p = osmo_hexdump_nospc(test, 5);
+ if (0 != memcmp(s, p, 5)) {
+ printf ("%s\t", s);
+ printf ("%s\t", p);
+ printf("40 BE FAILED!\n");
+ } else printf("40 BE OK\n");
+
+ osmo_store40le(_test40, test);
+ if (osmo_load40le(test) == _test40)
+ printf("40 LE OK\n");
+ else
+ printf("40 LE FAILED: %s, %.10" PRIx64 ", %.10" PRIx64 "\n", osmo_hexdump(test, 5), osmo_load40le(test), _test40);
+
+
+ uint32_t _test32 = (uint32_t)rand();
+ osmo_store32be(_test32, test);
+
+ snprintf(s, 17, "%.8" PRIx32, _test32);
+ p = osmo_hexdump_nospc(test, 4);
+ if (0 != memcmp(s, p, 4)) {
+ printf ("%s\t", s);
+ printf ("%s\t", p);
+ printf("32 BE FAILED!\n");
+ } else printf("32 BE OK\n");
+
+ osmo_store32le(_test32, test);
+ if (osmo_load32le(test) == _test32)
+ printf("32 LE OK\n");
+ else
+ printf("32 LE FAILED: %s, %.8" PRIx32 ", %.8" PRIx32 "\n", osmo_hexdump(test, 4), osmo_load32le(test), _test32);
+
+
+ uint32_t _test24 = ((uint32_t)rand() << 8) >> 8;
+ osmo_store24be(_test24, test);
+
+ snprintf(s, 17, "%.6" PRIx32, _test24);
+ p = osmo_hexdump_nospc(test, 3);
+ if (0 != memcmp(s, p, 3)) {
+ printf ("%s\t", s);
+ printf ("%s\t", p);
+ printf("24 BE FAILED!\n");
+ } else printf("24 BE OK\n");
+
+ osmo_store24le(_test24, test);
+ if (osmo_load24le(test) == _test24)
+ printf("24 LE OK\n");
+ else
+ printf("24 LE FAILED: %s, %.6" PRIx32 ", %.6" PRIx32 "\n", osmo_hexdump(test, 3), osmo_load24le(test), _test24);
+
+
+ uint16_t _test16 = (uint16_t)rand();
+ osmo_store16be(_test16, test);
+
+ snprintf(s, 17, "%.4" PRIx16, _test16);
+ p = osmo_hexdump_nospc(test, 2);
+ if (0 != memcmp(s, p, 2)) {
+ printf ("%s\t", s);
+ printf ("%s\t", p);
+ printf("16 BE FAILED!\n");
+ } else printf("16 BE OK\n");
+
+ osmo_store16le(_test16, test);
+ if (osmo_load16le(test) == _test16)
+ printf("16 LE OK\n");
+ else
+ printf("16 LE FAILED: %s, %.4" PRIx16 ", %.4" PRIx16 "\n", osmo_hexdump(test, 2), osmo_load16le(test), _test16);
+
return 0;
}
diff --git a/tests/bits/bitrev_test.ok b/tests/bits/bitrev_test.ok
index 47f402f..e319af2 100644
--- a/tests/bits/bitrev_test.ok
+++ b/tests/bits/bitrev_test.ok
@@ -22,3 +22,18 @@ REVERSED: 02 01
INORDER: 80
REVERSED: 01
+checking byte packing...
+64 BE OK
+64 LE OK
+56 BE OK
+56 LE OK
+48 BE OK
+48 LE OK
+40 BE OK
+40 LE OK
+32 BE OK
+32 LE OK
+24 BE OK
+24 LE OK
+16 BE OK
+16 LE OK
--
1.8.3.2
--------------040706090709050002010705
Content-Type: text/x-patch;
name="0002-Add-Kasumi-cipher-implementation.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="0002-Add-Kasumi-cipher-implementation.patch"
1
0
Dear all,
Time has come to fill out the "Talks/Discussions/Workshop / Hacking"
section of the wiki page.
If you have something you'd like to present, talk about or hack on,
add it there. A simple descriptive title along with an estimated
duration is enough.
I guess we'll collect those for 2/3 weeks and then start making the schedule.
Cheers,
Sylvain
1
0
---
.gitignore | 2 +
include/osmocom/gsm/kasumi.h | 36 ++++++++
src/gsm/Makefile.am | 2 +-
src/gsm/kasumi.c | 193 +++++++++++++++++++++++++++++++++++++++++++
src/gsm/libosmogsm.map | 4 +
tests/Makefile.am | 7 +-
tests/kasumi/kasumi_test.c | 128 ++++++++++++++++++++++++++++
tests/kasumi/kasumi_test.ok | 10 +++
8 files changed, 379 insertions(+), 3 deletions(-)
create mode 100644 include/osmocom/gsm/kasumi.h
create mode 100644 src/gsm/kasumi.c
create mode 100644 tests/kasumi/kasumi_test.c
create mode 100644 tests/kasumi/kasumi_test.ok
diff --git a/.gitignore b/.gitignore
index 71b27f2..6436310 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,6 +55,8 @@ tests/testsuite
tests/testsuite.dir/
tests/testsuite.log
+tests/utils/utils_test
+tests/kasumi/kasumi_test
tests/sms/sms_test
tests/timer/timer_test
tests/msgfile/msgfile_test
diff --git a/include/osmocom/gsm/kasumi.h b/include/osmocom/gsm/kasumi.h
new file mode 100644
index 0000000..8479968
--- /dev/null
+++ b/include/osmocom/gsm/kasumi.h
@@ -0,0 +1,36 @@
+/*
+ * KASUMI header
+ *
+ * See kasumi.c for details
+ */
+
+#ifndef __KASUMI_H__
+#define __KASUMI_H__
+
+#include <stdint.h>
+
+/*
+ * Single iteration of KASUMI cipher
+*/
+uint64_t _kasumi(uint64_t P, uint16_t *KLi1, uint16_t *KLi2, uint16_t *KOi1, uint16_t *KOi2, uint16_t *KOi3, uint16_t *KIi1, uint16_t *KIi2, uint16_t *KIi3);
+
+/*
+ * Implementation of the KGCORE algorithm (used by A5/3, A5/4, GEA3, GEA4 and ECSD)
+ *
+ * CA : uint8_t
+ * cb : uint8_t
+ * cc : uint32_t
+ * cd : uint8_t
+ * ck : uint8_t [8]
+ * co : uint8_t [output, cl-dependent]
+ * cl : uint16_t
+ */
+void _kasumi_kgcore(uint8_t CA, uint8_t cb, uint32_t cc, uint8_t cd, const uint8_t *ck, uint8_t *co, uint16_t cl);
+
+/*! \brief Expand key into set of subkeys
+ * \param[in] key (128 bits) as array of bytes
+ * \param[out] arrays of round-specific subkeys - see TS 135 202 for details
+ */
+void _kasumi_key_expand(const uint8_t *key, uint16_t *KLi1, uint16_t *KLi2, uint16_t *KOi1, uint16_t *KOi2, uint16_t *KOi3, uint16_t *KIi1, uint16_t *KIi2, uint16_t *KIi3);
+
+#endif /* __KASUMI_H__ */
diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am
index 3162a7f..8ccbaec 100644
--- a/src/gsm/Makefile.am
+++ b/src/gsm/Makefile.am
@@ -15,7 +15,7 @@ libosmogsm_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c comp128v23.c \
gsm_utils.c rsl.c gsm48.c gsm48_ie.c gsm0808.c sysinfo.c \
gprs_cipher_core.c gsm0480.c abis_nm.c gsm0502.c \
gsm0411_utils.c gsm0411_smc.c gsm0411_smr.c \
- lapd_core.c lapdm.c \
+ lapd_core.c lapdm.c kasumi.c \
auth_core.c auth_comp128v1.c auth_comp128v23.c \
auth_milenage.c milenage/aes-encblock.c \
milenage/aes-internal.c milenage/aes-internal-enc.c \
diff --git a/src/gsm/kasumi.c b/src/gsm/kasumi.c
new file mode 100644
index 0000000..9900e05
--- /dev/null
+++ b/src/gsm/kasumi.c
@@ -0,0 +1,193 @@
+/* Kasumi cipher and KGcore functions */
+
+/* (C) 2013 by Max <Max.Suraev(a)fairwaves.ru>
+ *
+ * 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 2 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 <stdint.h>
+#include <osmocom/core/bits.h>
+#include <osmocom/gsm/kasumi.h>
+
+static uint16_t
+_kasumi_FI(uint16_t I, uint16_t skey)
+{
+ static uint16_t S7[] = {
+ 54, 50, 62, 56, 22, 34, 94, 96, 38, 6, 63, 93, 2, 18, 123, 33,
+ 55, 113, 39, 114, 21, 67, 65, 12, 47, 73, 46, 27, 25, 111, 124, 81,
+ 53, 9, 121, 79, 52, 60, 58, 48, 101, 127, 40, 120, 104, 70, 71, 43,
+ 20, 122, 72, 61, 23, 109, 13, 100, 77, 1, 16, 7, 82, 10, 105, 98,
+ 117, 116, 76, 11, 89, 106, 0,125,118, 99, 86, 69, 30, 57, 126, 87,
+ 112, 51, 17, 5, 95, 14, 90, 84, 91, 8, 35,103, 32, 97, 28, 66,
+ 102, 31, 26, 45, 75, 4, 85, 92, 37, 74, 80, 49, 68, 29, 115, 44,
+ 64, 107, 108, 24, 110, 83, 36, 78, 42, 19, 15, 41, 88, 119, 59, 3
+ };
+ static uint16_t S9[] = {
+ 167, 239, 161, 379, 391, 334, 9, 338, 38, 226, 48, 358, 452, 385, 90, 397,
+ 183, 253, 147, 331, 415, 340, 51, 362, 306, 500, 262, 82, 216, 159, 356, 177,
+ 175, 241, 489, 37, 206, 17, 0, 333, 44, 254, 378, 58, 143, 220, 81, 400,
+ 95, 3, 315, 245, 54, 235, 218, 405, 472, 264, 172, 494, 371, 290, 399, 76,
+ 165, 197, 395, 121, 257, 480, 423, 212, 240, 28, 462, 176, 406, 507, 288, 223,
+ 501, 407, 249, 265, 89, 186, 221, 428,164, 74, 440, 196, 458, 421, 350, 163,
+ 232, 158, 134, 354, 13, 250, 491, 142,191, 69, 193, 425, 152, 227, 366, 135,
+ 344, 300, 276, 242, 437, 320, 113, 278, 11, 243, 87, 317, 36, 93, 496, 27,
+ 487, 446, 482, 41, 68, 156, 457, 131, 326, 403, 339, 20, 39, 115, 442, 124,
+ 475, 384, 508, 53, 112, 170, 479, 151, 126, 169, 73, 268, 279, 321, 168, 364,
+ 363, 292, 46, 499, 393, 327, 324, 24, 456, 267, 157, 460, 488, 426, 309, 229,
+ 439, 506, 208, 271, 349, 401, 434, 236, 16, 209, 359, 52, 56, 120, 199, 277,
+ 465, 416, 252, 287, 246, 6, 83, 305, 420, 345, 153,502, 65, 61, 244, 282,
+ 173, 222, 418, 67, 386, 368, 261, 101, 476, 291, 195,430, 49, 79, 166, 330,
+ 280, 383, 373, 128, 382, 408, 155, 495, 367, 388, 274, 107, 459, 417, 62, 454,
+ 132, 225, 203, 316, 234, 14, 301, 91, 503, 286, 424, 211, 347, 307, 140, 374,
+ 35, 103, 125, 427, 19, 214, 453, 146, 498, 314, 444, 230, 256, 329, 198, 285,
+ 50, 116, 78, 410, 10, 205, 510, 171, 231, 45, 139, 467, 29, 86, 505, 32,
+ 72, 26, 342, 150, 313, 490, 431, 238, 411, 325, 149, 473, 40, 119, 174, 355,
+ 185, 233, 389, 71, 448, 273, 372, 55, 110, 178, 322, 12, 469, 392, 369, 190,
+ 1, 109, 375, 137, 181, 88, 75, 308, 260, 484, 98, 272, 370, 275, 412, 111,
+ 336, 318, 4, 504, 492, 259, 304, 77, 337, 435, 21, 357, 303, 332, 483, 18,
+ 47, 85, 25, 497, 474, 289, 100, 269, 296, 478, 270, 106, 31, 104, 433, 84,
+ 414, 486, 394, 96, 99, 154, 511, 148, 413, 361, 409, 255, 162, 215, 302, 201,
+ 266, 351, 343, 144, 441, 365, 108, 298, 251, 34, 182, 509, 138, 210, 335, 133,
+ 311, 352, 328, 141, 396, 346, 123, 319, 450, 281, 429, 228, 443, 481, 92, 404,
+ 485, 422, 248, 297, 23, 213, 130, 466, 22, 217, 283, 70, 294, 360, 419, 127,
+ 312, 377, 7, 468, 194, 2, 117, 295, 463, 258, 224, 447, 247, 187, 80, 398,
+ 284, 353, 105, 390, 299, 471, 470, 184, 57, 200, 348, 63, 204, 188, 33, 451,
+ 97, 30, 310, 219, 94, 160, 129, 493, 64, 179, 263, 102, 189, 207, 114, 402,
+ 438, 477, 387, 122, 192, 42, 381, 5, 145, 118, 180, 449, 293, 323, 136, 380,
+ 43, 66, 60, 455, 341, 445, 202, 432, 8, 237, 15, 376, 436, 464, 59, 461
+ };
+ uint16_t L, R;
+
+ /* Split 16 bit input into two unequal halves: 9 and 7 bits, same for subkey */
+ L = I >> 7; /* take 9 bits */
+ R = I & 0x7F; /* take 7 bits */
+
+ L = S9[L] ^ R;
+ R = S7[R] ^ (L & 0x7F);
+
+ L ^= (skey & 0x1FF);
+ R ^= (skey >> 9);
+
+ L = S9[L] ^ R;
+ R = S7[R] ^ (L & 0x7F);
+
+ return (R << 9) + L;
+}
+
+static uint32_t
+_kasumi_FO(uint32_t I, uint16_t *KOi1, uint16_t *KOi2, uint16_t *KOi3, uint16_t *KIi1, uint16_t *KIi2, uint16_t *KIi3, unsigned i)
+{
+ uint16_t L = I >> 16, R = I; /* Split 32 bit input into Left and Right parts */
+
+ L ^= KOi1[i];
+ L = _kasumi_FI(L, KIi1[i]);
+ L ^= R;
+
+ R ^= KOi2[i];
+ R = _kasumi_FI(R, KIi2[i]);
+ R ^= L;
+
+ L ^= KOi3[i];
+ L = _kasumi_FI(L, KIi3[i]);
+ L ^= R;
+
+ return (((uint32_t)R) << 16) + L;
+}
+
+static uint32_t
+_kasumi_FL(uint32_t I, uint16_t *KLi1, uint16_t *KLi2, unsigned i)
+{
+ uint16_t L = I >> 16, R = I, tmp; /* Split 32 bit input into Left and Right parts */
+
+ tmp = L & KLi1[i];
+ R ^= rol16(tmp, 1);
+
+ tmp = R | KLi2[i];
+ L ^= rol16(tmp, 1);
+
+ return (((uint32_t)L) << 16) + R;
+}
+
+uint64_t
+_kasumi(uint64_t P, uint16_t *KLi1, uint16_t *KLi2, uint16_t *KOi1, uint16_t *KOi2, uint16_t *KOi3, uint16_t *KIi1, uint16_t *KIi2, uint16_t *KIi3)
+{
+ uint32_t i, L = P >> 32, R = P; /* Split 64 bit input into Left and Right parts */
+
+ for (i = 0; i < 8; i++)
+ {
+ R ^= _kasumi_FO(_kasumi_FL(L, KLi1, KLi2, i), KOi1, KOi2, KOi3, KIi1, KIi2, KIi3, i); /* odd round */
+ i++;
+ L ^= _kasumi_FL(_kasumi_FO(R, KOi1, KOi2, KOi3, KIi1, KIi2, KIi3, i), KLi1, KLi2, i); /* even round */
+ }
+ return (((uint64_t)L) << 32) + R; /* Concatenate Left and Right 32 bits into 64 bit ciphertext */
+}
+
+/*! \brief Expand key into set of subkeys
+ * \param[in] key (128 bits) as array of bytes
+ * \param[out] arrays of round-specific subkeys - see TS 135 202 for details
+ */
+void
+_kasumi_key_expand(const uint8_t *key, uint16_t *KLi1, uint16_t *KLi2, uint16_t *KOi1, uint16_t *KOi2, uint16_t *KOi3, uint16_t *KIi1, uint16_t *KIi2, uint16_t *KIi3)
+{
+ uint16_t i, C[] = { 0x0123, 0x4567, 0x89AB, 0xCDEF, 0xFEDC, 0xBA98, 0x7654, 0x3210 };
+
+ for (i = 0; i < 8; i++) /* Work with 16 bit subkeys and create prime subkeys */
+ {
+ C[i] ^= osmo_load16be(key + i * 2);
+ }
+ /* C[] now stores K-prime[] */
+ for (i = 0; i < 8; i++) /* Create round-specific subkeys */
+ {
+ KLi1[i] = rol16(osmo_load16be(key + i * 2), 1);
+ KLi2[i] = C[(i + 2) & 0x7];
+
+ KOi1[i] = rol16(osmo_load16be(key + ((2 * (i + 1)) & 0xE)), 5);
+ KOi2[i] = rol16(osmo_load16be(key + ((2 * (i + 5)) & 0xE)), 8);
+ KOi3[i] = rol16(osmo_load16be(key + ((2 * (i + 6)) & 0xE)), 13);
+
+ KIi1[i] = C[(i + 4) & 0x7];
+ KIi2[i] = C[(i + 3) & 0x7];
+ KIi3[i] = C[(i + 7) & 0x7];
+ }
+}
+
+void
+_kasumi_kgcore(uint8_t CA, uint8_t cb, uint32_t cc, uint8_t cd, const uint8_t *ck, uint8_t *co, uint16_t cl)
+{
+ uint16_t KLi1[8], KLi2[8], KOi1[8], KOi2[8], KOi3[8], KIi1[8], KIi2[8], KIi3[8], i;
+ uint64_t A = ((uint64_t)cc) << 32, BLK = 0, _ca = ((uint64_t)CA << 16) ;
+ A |= _ca;
+ _ca = (uint64_t)((cb << 3) | (cd << 2)) << 24;
+ A |= _ca;
+ /* Register loading complete: see TR 55.919 8.2 and TS 55.216 3.2 */
+
+ uint8_t ck_km[16];
+ for (i = 0; i < 16; i++) ck_km[i] = ck[i] ^ 0x55; /* Modified key established */
+
+ /* preliminary round with modified key */
+ _kasumi_key_expand(ck_km, KLi1, KLi2, KOi1, KOi2, KOi3, KIi1, KIi2, KIi3);
+ A = _kasumi(A, KLi1, KLi2, KOi1, KOi2, KOi3, KIi1, KIi2, KIi3);
+
+ /* Run Kasumi in OFB to obtain enough data for gamma. */
+ _kasumi_key_expand(ck, KLi1, KLi2, KOi1, KOi2, KOi3, KIi1, KIi2, KIi3);
+ for (i = 0; i < cl / 64 + 1; i++) /* i is a block counter */
+ {
+ BLK = _kasumi(A ^ i ^ BLK, KLi1, KLi2, KOi1, KOi2, KOi3, KIi1, KIi2, KIi3);
+ osmo_store64be(BLK, co + (i * 8));
+ }
+}
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index d54f940..7551c4a 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -219,6 +219,10 @@ osmo_a5;
osmo_a5_1;
osmo_a5_2;
+_kasumi;
+_kasumi_key_expand;
+_kasumi_kgcore;
+
osmo_auth_alg_name;
osmo_auth_alg_parse;
osmo_auth_gen_vec;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index c6216d5..ddc13dc 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -4,7 +4,7 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test \
smscb/smscb_test bits/bitrev_test a5/a5_test \
conv/conv_test auth/milenage_test lapd/lapd_test \
gsm0808/gsm0808_test gsm0408/gsm0408_test \
- gb/bssgp_fc_test gb/gprs_ns_test \
+ gb/bssgp_fc_test gb/gprs_ns_test kasumi/kasumi_test \
logging/logging_test fr/fr_test \
loggingrb/loggingrb_test strrb/strrb_test \
vty/vty_test comp128/comp128_test utils/utils_test
@@ -19,6 +19,9 @@ utils_utils_test_LDADD = $(top_builddir)/src/libosmocore.la
a5_a5_test_SOURCES = a5/a5_test.c
a5_a5_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la
+kasumi_kasumi_test_SOURCES = kasumi/kasumi_test.c
+kasumi_kasumi_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la
+
comp128_comp128_test_SOURCES = comp128/comp128_test.c
comp128_comp128_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la
@@ -102,7 +105,7 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \
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_ns_test.ok \
+ gb/gprs_ns_test.ok kasumi/kasumi_test.ok \
msgfile/msgfile_test.ok msgfile/msgconfig.cfg \
logging/logging_test.ok logging/logging_test.err \
fr/fr_test.ok loggingrb/logging_test.ok \
diff --git a/tests/kasumi/kasumi_test.c b/tests/kasumi/kasumi_test.c
new file mode 100644
index 0000000..5504905
--- /dev/null
+++ b/tests/kasumi/kasumi_test.c
@@ -0,0 +1,128 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/gsm/kasumi.h> // for testing internal A5/3 functions
+
+
+inline int _compare_mem(uint8_t * x, uint8_t * y, size_t len) {
+ if (0 != memcmp(x, y, len)) {
+ printf ("X: %s\t", osmo_hexdump_nospc(x, len));
+ printf ("Y: %s\n", osmo_hexdump_nospc(y, len));
+ return 0;
+ }
+ return 1;
+}
+
+inline static void test_expansion(uint8_t * test_key, uint16_t * _KLi1, uint16_t * _KLi2, uint16_t * _KOi1, uint16_t * _KOi2, uint16_t * _KOi3, uint16_t * _KIi1, uint16_t * _KIi2, uint16_t * _KIi3, uint16_t * _KLi1_r, uint16_t * _KLi2_r, uint16_t * _KOi1_r, uint16_t * _KOi2_r, uint16_t * _KOi3_r, uint16_t * _KIi1_r, uint16_t * _KIi2_r, uint16_t * _KIi3_r)
+{
+ _kasumi_key_expand(test_key, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3);
+ int passed = 1;
+ passed = _compare_mem((uint8_t *)_KLi1, (uint8_t *)_KLi1_r, 16);
+ passed = _compare_mem((uint8_t *)_KLi2, (uint8_t *)_KLi2_r, 16);
+ passed = _compare_mem((uint8_t *)_KOi1, (uint8_t *)_KOi1_r, 16);
+ passed = _compare_mem((uint8_t *)_KOi2, (uint8_t *)_KOi2_r, 16);
+ passed = _compare_mem((uint8_t *)_KOi3, (uint8_t *)_KOi3_r, 16);
+ passed = _compare_mem((uint8_t *)_KIi1, (uint8_t *)_KIi1_r, 16);
+ passed = _compare_mem((uint8_t *)_KIi2, (uint8_t *)_KIi2_r, 16);
+ passed = _compare_mem((uint8_t *)_KIi3, (uint8_t *)_KIi3_r, 16);
+ if (passed) printf(" OK. "); else printf("FAILED!");
+}
+
+int main(int argc, char **argv)
+{
+ uint16_t _KLi1[8], _KLi2[8], _KOi1[8], _KOi2[8], _KOi3[8], _KIi1[8], _KIi2[8], _KIi3[8], _KLi1_r[8], _KLi2_r[8], _KOi1_r[8], _KOi2_r[8], _KOi3_r[8], _KIi1_r[8], _KIi2_r[8], _KIi3_r[8];
+
+ printf("testing KASUMI key expansion and encryption (ETSI TS 135 203):\n");
+ printf("KASUMI Test Set 1...");
+
+uint8_t _test_key1[] = {0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00, 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48};
+_KLi1_r[0] = 0x57AC; _KLi1_r[1] = 0x8B3E; _KLi1_r[2] = 0x058B; _KLi1_r[3] = 0x6601; _KLi1_r[4] = 0x2A59; _KLi1_r[5] = 0x9220; _KLi1_r[6] = 0x9102; _KLi1_r[7] = 0xFE91;
+_KLi2_r[0] = 0x0B6E; _KLi2_r[1] = 0x7EEF; _KLi2_r[2] = 0x6BF0; _KLi2_r[3] = 0xF388; _KLi2_r[4] = 0x3ED5; _KLi2_r[5] = 0xCD58; _KLi2_r[6] = 0x2AF5; _KLi2_r[7] = 0x00F8;
+_KOi1_r[0] = 0xB3E8; _KOi1_r[1] = 0x58B0; _KOi1_r[2] = 0x6016; _KOi1_r[3] = 0xA592; _KOi1_r[4] = 0x2209; _KOi1_r[5] = 0x1029; _KOi1_r[6] = 0xE91F; _KOi1_r[7] = 0x7AC5;
+_KOi2_r[0] = 0x1049; _KOi2_r[1] = 0x8148; _KOi2_r[2] = 0x48FF; _KOi2_r[3] = 0xD62B; _KOi2_r[4] = 0x9F45; _KOi2_r[5] = 0xC582; _KOi2_r[6] = 0x00B3; _KOi2_r[7] = 0x2C95;
+_KOi3_r[0] = 0x2910; _KOi3_r[1] = 0x1FE9; _KOi3_r[2] = 0xC57A; _KOi3_r[3] = 0xE8B3; _KOi3_r[4] = 0xB058; _KOi3_r[5] = 0x1660; _KOi3_r[6] = 0x92A5; _KOi3_r[7] = 0x0922;
+_KIi1_r[0] = 0x6BF0; _KIi1_r[1] = 0xF388; _KIi1_r[2] = 0x3ED5; _KIi1_r[3] = 0xCD58; _KIi1_r[4] = 0x2AF5; _KIi1_r[5] = 0x00F8; _KIi1_r[6] = 0x0B6E; _KIi1_r[7] = 0x7EEF;
+_KIi2_r[0] = 0x7EEF; _KIi2_r[1] = 0x6BF0; _KIi2_r[2] = 0xF388; _KIi2_r[3] = 0x3ED5; _KIi2_r[4] = 0xCD58; _KIi2_r[5] = 0x2AF5; _KIi2_r[6] = 0x00F8; _KIi2_r[7] = 0x0B6E;
+_KIi3_r[0] = 0xCD58; _KIi3_r[1] = 0x2AF5; _KIi3_r[2] = 0x00F8; _KIi3_r[3] = 0x0B6E; _KIi3_r[4] = 0x7EEF; _KIi3_r[5] = 0x6BF0; _KIi3_r[6] = 0xF388; _KIi3_r[7] = 0x3ED5;
+test_expansion(_test_key1, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3, _KLi1_r, _KLi2_r, _KOi1_r, _KOi2_r, _KOi3_r, _KIi1_r, _KIi2_r, _KIi3_r);
+
+if (0xDF1F9B251C0BF45F == _kasumi(0xEA024714AD5C4D84, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3))
+ printf("OK."); else printf("FAILED!");
+
+printf("\nKASUMI Test Set 2...");
+
+uint8_t _test_key2[] = {0x8C, 0xE3, 0x3E, 0x2C, 0xC3, 0xC0, 0xB5, 0xFC, 0x1F, 0x3D, 0xE8, 0xA6, 0xDC, 0x66, 0xB1, 0xF3};
+_KLi1_r[0] = 0x19C7; _KLi1_r[1] = 0x7C58; _KLi1_r[2] = 0x8781; _KLi1_r[3] = 0x6BF9; _KLi1_r[4] = 0x3E7A; _KLi1_r[5] = 0xD14D; _KLi1_r[6] = 0xB8CD; _KLi1_r[7] = 0x63E7;
+_KLi2_r[0] = 0x4A6B; _KLi2_r[1] = 0x7813; _KLi2_r[2] = 0xE1E1; _KLi2_r[3] = 0x523E; _KLi2_r[4] = 0xAA32; _KLi2_r[5] = 0x83E3; _KLi2_r[6] = 0x8DC0; _KLi2_r[7] = 0x7B4B;
+_KOi1_r[0] = 0xC587; _KOi1_r[1] = 0x7818; _KOi1_r[2] = 0xBF96; _KOi1_r[3] = 0xE7A3; _KOi1_r[4] = 0x14DD; _KOi1_r[5] = 0x8CDB; _KOi1_r[6] = 0x3E76; _KOi1_r[7] = 0x9C71;
+_KOi2_r[0] = 0xA6E8; _KOi2_r[1] = 0x66DC; _KOi2_r[2] = 0xF3B1; _KOi2_r[3] = 0xE38C; _KOi2_r[4] = 0x2C3E; _KOi2_r[5] = 0xC0C3; _KOi2_r[6] = 0xFCB5; _KOi2_r[7] = 0x3D1F;
+_KOi3_r[0] = 0xDB8C; _KOi3_r[1] = 0x763E; _KOi3_r[2] = 0x719C; _KOi3_r[3] = 0x87C5; _KOi3_r[4] = 0x1878; _KOi3_r[5] = 0x96BF; _KOi3_r[6] = 0xA3E7; _KOi3_r[7] = 0xDD14;
+_KIi1_r[0] = 0xE1E1; _KIi1_r[1] = 0x523E; _KIi1_r[2] = 0xAA32; _KIi1_r[3] = 0x83E3; _KIi1_r[4] = 0x8DC0; _KIi1_r[5] = 0x7B4B; _KIi1_r[6] = 0x4A6B; _KIi1_r[7] = 0x7813;
+_KIi2_r[0] = 0x7813; _KIi2_r[1] = 0xE1E1; _KIi2_r[2] = 0x523E; _KIi2_r[3] = 0xAA32; _KIi2_r[4] = 0x83E3; _KIi2_r[5] = 0x8DC0; _KIi2_r[6] = 0x7B4B; _KIi2_r[7] = 0x4A6B;
+_KIi3_r[0] = 0x83E3; _KIi3_r[1] = 0x8DC0; _KIi3_r[2] = 0x7B4B; _KIi3_r[3] = 0x4A6B; _KIi3_r[4] = 0x7813; _KIi3_r[5] = 0xE1E1; _KIi3_r[6] = 0x523E; _KIi3_r[7] = 0xAA32;
+test_expansion(_test_key2, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3, _KLi1_r, _KLi2_r, _KOi1_r, _KOi2_r, _KOi3_r, _KIi1_r, _KIi2_r, _KIi3_r);
+
+if (0xDE551988CEB2F9B7 == _kasumi(0xD3C5D592327FB11C, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3))
+ printf("OK."); else printf("FAILED!");
+
+printf("\nKASUMI Test Set 3...");
+
+uint8_t _test_key3[] = {0x40, 0x35, 0xC6, 0x68, 0x0A, 0xF8, 0xC6, 0xD1, 0xA8, 0xFF, 0x86, 0x67, 0xB1, 0x71, 0x40, 0x13};
+_KLi1_r[0] = 0x806A; _KLi1_r[1] = 0x8CD1; _KLi1_r[2] = 0x15F0; _KLi1_r[3] = 0x8DA3; _KLi1_r[4] = 0x51FF; _KLi1_r[5] = 0x0CCF; _KLi1_r[6] = 0x62E3; _KLi1_r[7] = 0x8026;
+_KLi2_r[0] = 0x8353; _KLi2_r[1] = 0x0B3E; _KLi2_r[2] = 0x5623; _KLi2_r[3] = 0x3CFF; _KLi2_r[4] = 0xC725; _KLi2_r[5] = 0x7203; _KLi2_r[6] = 0x4116; _KLi2_r[7] = 0x830F;
+_KOi1_r[0] = 0xCD18; _KOi1_r[1] = 0x5F01; _KOi1_r[2] = 0xDA38; _KOi1_r[3] = 0x1FF5; _KOi1_r[4] = 0xCCF0; _KOi1_r[5] = 0x2E36; _KOi1_r[6] = 0x0268; _KOi1_r[7] = 0x06A8;
+_KOi2_r[0] = 0x6786; _KOi2_r[1] = 0x71B1; _KOi2_r[2] = 0x1340; _KOi2_r[3] = 0x3540; _KOi2_r[4] = 0x68C6; _KOi2_r[5] = 0xF80A; _KOi2_r[6] = 0xD1C6; _KOi2_r[7] = 0xFFA8;
+_KOi3_r[0] = 0x362E; _KOi3_r[1] = 0x6802; _KOi3_r[2] = 0xA806; _KOi3_r[3] = 0x18CD; _KOi3_r[4] = 0x015F; _KOi3_r[5] = 0x38DA; _KOi3_r[6] = 0xF51F; _KOi3_r[7] = 0xF0CC;
+_KIi1_r[0] = 0x5623; _KIi1_r[1] = 0x3CFF; _KIi1_r[2] = 0xC725; _KIi1_r[3] = 0x7203; _KIi1_r[4] = 0x4116; _KIi1_r[5] = 0x830F; _KIi1_r[6] = 0x8353; _KIi1_r[7] = 0x0B3E;
+_KIi2_r[0] = 0x0B3E; _KIi2_r[1] = 0x5623; _KIi2_r[2] = 0x3CFF; _KIi2_r[3] = 0xC725; _KIi2_r[4] = 0x7203; _KIi2_r[5] = 0x4116; _KIi2_r[6] = 0x830F; _KIi2_r[7] = 0x8353;
+_KIi3_r[0] = 0x7203; _KIi3_r[1] = 0x4116; _KIi3_r[2] = 0x830F; _KIi3_r[3] = 0x8353; _KIi3_r[4] = 0x0B3E; _KIi3_r[5] = 0x5623; _KIi3_r[6] = 0x3CFF; _KIi3_r[7] = 0xC725;
+test_expansion(_test_key3, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3, _KLi1_r, _KLi2_r, _KOi1_r, _KOi2_r, _KOi3_r, _KIi1_r, _KIi2_r, _KIi3_r);
+
+if (0x4592B0E78690F71B == _kasumi(0x62A540981BA6F9B7, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3))
+ printf("OK."); else printf("FAILED!");
+
+printf("\nKASUMI Test Set 4...");
+uint8_t _test_key4[] = {0x3A, 0x3B, 0x39, 0xB5, 0xC3, 0xF2, 0x37, 0x6D, 0x69, 0xF7, 0xD5, 0x46, 0xE5, 0xF8, 0x5D, 0x43};
+uint64_t I4 = 0xCA49C1C75771AB0B, i;
+_kasumi_key_expand(_test_key4, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3);
+
+for (i = 0; i < 50; i++)
+ I4 = _kasumi(I4, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3);
+
+if (0x738BAD4C4A690802 == I4) printf(" OK.\n"); else printf("FAILED!");
+
+
+uint8_t gamma[32];
+
+uint8_t _Key1[] = {0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xBC, 0x00, 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xBC, 0x00},
+_gamma1[] = {0x88, 0x9E, 0xEA, 0xAF, 0x9E, 0xD1, 0xBA, 0x1A, 0xBB, 0xD8, 0x43, 0x62, 0x32, 0xE4, 0x57, 0x28, 0xD0, 0x1A, 0xA8, 0x91, 0x33, 0xDA, 0x73, 0xC1, 0x1E, 0xAB, 0x68, 0xB7, 0xD8, 0x9B, 0xC8, 0x41};
+_kasumi_kgcore(0xF, 0, 0x0024F20F, 0, _Key1, gamma, 228);
+printf ("KGCORE Test Set 1: %d\n", _compare_mem(gamma, _gamma1, 32));
+
+uint8_t _Key2[] = {0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48, 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48},
+_gamma2[] = {0xFB, 0x4D, 0x5F, 0xBC, 0xEE, 0x13, 0xA3, 0x33, 0x89, 0x28, 0x56, 0x86, 0xE9, 0xA5, 0xC9, 0x42, 0x40, 0xDE, 0x38, 0x15, 0x01, 0x15, 0xF1, 0x5F, 0x8D, 0x9D, 0x98, 0xB9, 0x1A, 0x94, 0xB2, 0x96};
+_kasumi_kgcore(0xF, 0, 0x00061272, 0, _Key2, gamma, 228);
+printf ("KGCORE Test Set 2: %d\n", _compare_mem(gamma, _gamma2, 32));
+
+uint8_t _Key3[] = {0xEF, 0xA8, 0xB2, 0x22, 0x9E, 0x72, 0x0C, 0x2A, 0xEF, 0xA8, 0xB2, 0x22, 0x9E, 0x72, 0x0C, 0x2A},
+_gamma3[] = {0x0E, 0x40, 0x15, 0x75, 0x5A, 0x33, 0x64, 0x69, 0xC3, 0xDD, 0x86, 0x80, 0xE3, 0x03, 0x5B, 0xC4, 0x19, 0xA7, 0x8A, 0xD3, 0x86, 0x2C, 0x10, 0x90, 0xC6, 0x8A, 0x39, 0x1F, 0xE8, 0xA6, 0xAD, 0xEB};
+_kasumi_kgcore(0xF, 0, 0x0033FD3F, 0, _Key3, gamma, 228);
+printf ("KGCORE Test Set 3: %d\n", _compare_mem(gamma, _gamma3, 32));
+
+uint8_t _Key4[] = {0x5A, 0xCB, 0x1D, 0x64, 0x4C, 0x0D, 0x51, 0x20, 0x4E, 0xA5, 0x5A, 0xCB, 0x1D, 0x64, 0x4C, 0x0D},
+_gamma4[] = {0xE0, 0x95, 0x30, 0x6A, 0xD5, 0x08, 0x6E, 0x2E, 0xAC, 0x7F, 0x31, 0x07, 0xDE, 0x4F, 0xA2, 0x2D, 0xC1, 0xDF, 0xC9, 0x7D, 0x5B, 0xC5, 0x66, 0x1D, 0xD6, 0x09, 0x6F, 0x47, 0x6A, 0xED, 0xC6, 0x4B};
+_kasumi_kgcore(0xF, 0, 0x00156B26, 0, _Key4, gamma, 228);
+printf ("KGCORE Test Set 4: %d\n", _compare_mem(gamma, _gamma4, 32));
+
+uint8_t _Key5[] = {0xD3, 0xC5, 0xD5, 0x92, 0x32, 0x7F, 0xB1, 0x1C, 0x40, 0x35, 0xC6, 0x68, 0x0A, 0xF8, 0xC6, 0xD1},
+_gamma5[] = {0xDC, 0xE6, 0x43, 0x62, 0xAB, 0x5F, 0x89, 0xC1, 0x1E, 0xF0, 0xB3, 0x05, 0x16, 0x65, 0x70, 0xF4, 0x88, 0x9D, 0x55, 0x11, 0xE9, 0xE3, 0x57, 0x5D, 0x06, 0x2B, 0x5C, 0xED, 0x60, 0x39, 0x50, 0x6A};
+_kasumi_kgcore(0xF, 0, 0x000A59B4, 0, _Key5, gamma, 228);
+printf ("KGCORE Test Set 5: %d\n", _compare_mem(gamma, _gamma5, 32));
+
+ return 0;
+}
diff --git a/tests/kasumi/kasumi_test.ok b/tests/kasumi/kasumi_test.ok
new file mode 100644
index 0000000..2c2af4c
--- /dev/null
+++ b/tests/kasumi/kasumi_test.ok
@@ -0,0 +1,10 @@
+testing KASUMI key expansion and encryption (ETSI TS 135 203):
+KASUMI Test Set 1... OK. OK.
+KASUMI Test Set 2... OK. OK.
+KASUMI Test Set 3... OK. OK.
+KASUMI Test Set 4... OK.
+KGCORE Test Set 1: 1
+KGCORE Test Set 2: 1
+KGCORE Test Set 3: 1
+KGCORE Test Set 4: 1
+KGCORE Test Set 5: 1
--
1.8.3.2
--------------060209070104080702030101--
1
0
---
.gitignore | 2 +
include/osmocom/gsm/kasumi.h | 36 ++++++++
src/gsm/Makefile.am | 2 +-
src/gsm/kasumi.c | 193 +++++++++++++++++++++++++++++++++++++++++++
src/gsm/libosmogsm.map | 4 +
tests/Makefile.am | 7 +-
tests/kasumi/kasumi_test.c | 128 ++++++++++++++++++++++++++++
tests/kasumi/kasumi_test.ok | 10 +++
8 files changed, 379 insertions(+), 3 deletions(-)
create mode 100644 include/osmocom/gsm/kasumi.h
create mode 100644 src/gsm/kasumi.c
create mode 100644 tests/kasumi/kasumi_test.c
create mode 100644 tests/kasumi/kasumi_test.ok
diff --git a/.gitignore b/.gitignore
index 71b27f2..6436310 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,6 +55,8 @@ tests/testsuite
tests/testsuite.dir/
tests/testsuite.log
+tests/utils/utils_test
+tests/kasumi/kasumi_test
tests/sms/sms_test
tests/timer/timer_test
tests/msgfile/msgfile_test
diff --git a/include/osmocom/gsm/kasumi.h b/include/osmocom/gsm/kasumi.h
new file mode 100644
index 0000000..8479968
--- /dev/null
+++ b/include/osmocom/gsm/kasumi.h
@@ -0,0 +1,36 @@
+/*
+ * KASUMI header
+ *
+ * See kasumi.c for details
+ */
+
+#ifndef __KASUMI_H__
+#define __KASUMI_H__
+
+#include <stdint.h>
+
+/*
+ * Single iteration of KASUMI cipher
+*/
+uint64_t _kasumi(uint64_t P, uint16_t *KLi1, uint16_t *KLi2, uint16_t *KOi1, uint16_t *KOi2, uint16_t *KOi3, uint16_t *KIi1, uint16_t *KIi2, uint16_t *KIi3);
+
+/*
+ * Implementation of the KGCORE algorithm (used by A5/3, A5/4, GEA3, GEA4 and ECSD)
+ *
+ * CA : uint8_t
+ * cb : uint8_t
+ * cc : uint32_t
+ * cd : uint8_t
+ * ck : uint8_t [8]
+ * co : uint8_t [output, cl-dependent]
+ * cl : uint16_t
+ */
+void _kasumi_kgcore(uint8_t CA, uint8_t cb, uint32_t cc, uint8_t cd, const uint8_t *ck, uint8_t *co, uint16_t cl);
+
+/*! \brief Expand key into set of subkeys
+ * \param[in] key (128 bits) as array of bytes
+ * \param[out] arrays of round-specific subkeys - see TS 135 202 for details
+ */
+void _kasumi_key_expand(const uint8_t *key, uint16_t *KLi1, uint16_t *KLi2, uint16_t *KOi1, uint16_t *KOi2, uint16_t *KOi3, uint16_t *KIi1, uint16_t *KIi2, uint16_t *KIi3);
+
+#endif /* __KASUMI_H__ */
diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am
index 3162a7f..8ccbaec 100644
--- a/src/gsm/Makefile.am
+++ b/src/gsm/Makefile.am
@@ -15,7 +15,7 @@ libosmogsm_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c comp128v23.c \
gsm_utils.c rsl.c gsm48.c gsm48_ie.c gsm0808.c sysinfo.c \
gprs_cipher_core.c gsm0480.c abis_nm.c gsm0502.c \
gsm0411_utils.c gsm0411_smc.c gsm0411_smr.c \
- lapd_core.c lapdm.c \
+ lapd_core.c lapdm.c kasumi.c \
auth_core.c auth_comp128v1.c auth_comp128v23.c \
auth_milenage.c milenage/aes-encblock.c \
milenage/aes-internal.c milenage/aes-internal-enc.c \
diff --git a/src/gsm/kasumi.c b/src/gsm/kasumi.c
new file mode 100644
index 0000000..9900e05
--- /dev/null
+++ b/src/gsm/kasumi.c
@@ -0,0 +1,193 @@
+/* Kasumi cipher and KGcore functions */
+
+/* (C) 2013 by Max <Max.Suraev(a)fairwaves.ru>
+ *
+ * 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 2 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 <stdint.h>
+#include <osmocom/core/bits.h>
+#include <osmocom/gsm/kasumi.h>
+
+static uint16_t
+_kasumi_FI(uint16_t I, uint16_t skey)
+{
+ static uint16_t S7[] = {
+ 54, 50, 62, 56, 22, 34, 94, 96, 38, 6, 63, 93, 2, 18, 123, 33,
+ 55, 113, 39, 114, 21, 67, 65, 12, 47, 73, 46, 27, 25, 111, 124, 81,
+ 53, 9, 121, 79, 52, 60, 58, 48, 101, 127, 40, 120, 104, 70, 71, 43,
+ 20, 122, 72, 61, 23, 109, 13, 100, 77, 1, 16, 7, 82, 10, 105, 98,
+ 117, 116, 76, 11, 89, 106, 0,125,118, 99, 86, 69, 30, 57, 126, 87,
+ 112, 51, 17, 5, 95, 14, 90, 84, 91, 8, 35,103, 32, 97, 28, 66,
+ 102, 31, 26, 45, 75, 4, 85, 92, 37, 74, 80, 49, 68, 29, 115, 44,
+ 64, 107, 108, 24, 110, 83, 36, 78, 42, 19, 15, 41, 88, 119, 59, 3
+ };
+ static uint16_t S9[] = {
+ 167, 239, 161, 379, 391, 334, 9, 338, 38, 226, 48, 358, 452, 385, 90, 397,
+ 183, 253, 147, 331, 415, 340, 51, 362, 306, 500, 262, 82, 216, 159, 356, 177,
+ 175, 241, 489, 37, 206, 17, 0, 333, 44, 254, 378, 58, 143, 220, 81, 400,
+ 95, 3, 315, 245, 54, 235, 218, 405, 472, 264, 172, 494, 371, 290, 399, 76,
+ 165, 197, 395, 121, 257, 480, 423, 212, 240, 28, 462, 176, 406, 507, 288, 223,
+ 501, 407, 249, 265, 89, 186, 221, 428,164, 74, 440, 196, 458, 421, 350, 163,
+ 232, 158, 134, 354, 13, 250, 491, 142,191, 69, 193, 425, 152, 227, 366, 135,
+ 344, 300, 276, 242, 437, 320, 113, 278, 11, 243, 87, 317, 36, 93, 496, 27,
+ 487, 446, 482, 41, 68, 156, 457, 131, 326, 403, 339, 20, 39, 115, 442, 124,
+ 475, 384, 508, 53, 112, 170, 479, 151, 126, 169, 73, 268, 279, 321, 168, 364,
+ 363, 292, 46, 499, 393, 327, 324, 24, 456, 267, 157, 460, 488, 426, 309, 229,
+ 439, 506, 208, 271, 349, 401, 434, 236, 16, 209, 359, 52, 56, 120, 199, 277,
+ 465, 416, 252, 287, 246, 6, 83, 305, 420, 345, 153,502, 65, 61, 244, 282,
+ 173, 222, 418, 67, 386, 368, 261, 101, 476, 291, 195,430, 49, 79, 166, 330,
+ 280, 383, 373, 128, 382, 408, 155, 495, 367, 388, 274, 107, 459, 417, 62, 454,
+ 132, 225, 203, 316, 234, 14, 301, 91, 503, 286, 424, 211, 347, 307, 140, 374,
+ 35, 103, 125, 427, 19, 214, 453, 146, 498, 314, 444, 230, 256, 329, 198, 285,
+ 50, 116, 78, 410, 10, 205, 510, 171, 231, 45, 139, 467, 29, 86, 505, 32,
+ 72, 26, 342, 150, 313, 490, 431, 238, 411, 325, 149, 473, 40, 119, 174, 355,
+ 185, 233, 389, 71, 448, 273, 372, 55, 110, 178, 322, 12, 469, 392, 369, 190,
+ 1, 109, 375, 137, 181, 88, 75, 308, 260, 484, 98, 272, 370, 275, 412, 111,
+ 336, 318, 4, 504, 492, 259, 304, 77, 337, 435, 21, 357, 303, 332, 483, 18,
+ 47, 85, 25, 497, 474, 289, 100, 269, 296, 478, 270, 106, 31, 104, 433, 84,
+ 414, 486, 394, 96, 99, 154, 511, 148, 413, 361, 409, 255, 162, 215, 302, 201,
+ 266, 351, 343, 144, 441, 365, 108, 298, 251, 34, 182, 509, 138, 210, 335, 133,
+ 311, 352, 328, 141, 396, 346, 123, 319, 450, 281, 429, 228, 443, 481, 92, 404,
+ 485, 422, 248, 297, 23, 213, 130, 466, 22, 217, 283, 70, 294, 360, 419, 127,
+ 312, 377, 7, 468, 194, 2, 117, 295, 463, 258, 224, 447, 247, 187, 80, 398,
+ 284, 353, 105, 390, 299, 471, 470, 184, 57, 200, 348, 63, 204, 188, 33, 451,
+ 97, 30, 310, 219, 94, 160, 129, 493, 64, 179, 263, 102, 189, 207, 114, 402,
+ 438, 477, 387, 122, 192, 42, 381, 5, 145, 118, 180, 449, 293, 323, 136, 380,
+ 43, 66, 60, 455, 341, 445, 202, 432, 8, 237, 15, 376, 436, 464, 59, 461
+ };
+ uint16_t L, R;
+
+ /* Split 16 bit input into two unequal halves: 9 and 7 bits, same for subkey */
+ L = I >> 7; /* take 9 bits */
+ R = I & 0x7F; /* take 7 bits */
+
+ L = S9[L] ^ R;
+ R = S7[R] ^ (L & 0x7F);
+
+ L ^= (skey & 0x1FF);
+ R ^= (skey >> 9);
+
+ L = S9[L] ^ R;
+ R = S7[R] ^ (L & 0x7F);
+
+ return (R << 9) + L;
+}
+
+static uint32_t
+_kasumi_FO(uint32_t I, uint16_t *KOi1, uint16_t *KOi2, uint16_t *KOi3, uint16_t *KIi1, uint16_t *KIi2, uint16_t *KIi3, unsigned i)
+{
+ uint16_t L = I >> 16, R = I; /* Split 32 bit input into Left and Right parts */
+
+ L ^= KOi1[i];
+ L = _kasumi_FI(L, KIi1[i]);
+ L ^= R;
+
+ R ^= KOi2[i];
+ R = _kasumi_FI(R, KIi2[i]);
+ R ^= L;
+
+ L ^= KOi3[i];
+ L = _kasumi_FI(L, KIi3[i]);
+ L ^= R;
+
+ return (((uint32_t)R) << 16) + L;
+}
+
+static uint32_t
+_kasumi_FL(uint32_t I, uint16_t *KLi1, uint16_t *KLi2, unsigned i)
+{
+ uint16_t L = I >> 16, R = I, tmp; /* Split 32 bit input into Left and Right parts */
+
+ tmp = L & KLi1[i];
+ R ^= rol16(tmp, 1);
+
+ tmp = R | KLi2[i];
+ L ^= rol16(tmp, 1);
+
+ return (((uint32_t)L) << 16) + R;
+}
+
+uint64_t
+_kasumi(uint64_t P, uint16_t *KLi1, uint16_t *KLi2, uint16_t *KOi1, uint16_t *KOi2, uint16_t *KOi3, uint16_t *KIi1, uint16_t *KIi2, uint16_t *KIi3)
+{
+ uint32_t i, L = P >> 32, R = P; /* Split 64 bit input into Left and Right parts */
+
+ for (i = 0; i < 8; i++)
+ {
+ R ^= _kasumi_FO(_kasumi_FL(L, KLi1, KLi2, i), KOi1, KOi2, KOi3, KIi1, KIi2, KIi3, i); /* odd round */
+ i++;
+ L ^= _kasumi_FL(_kasumi_FO(R, KOi1, KOi2, KOi3, KIi1, KIi2, KIi3, i), KLi1, KLi2, i); /* even round */
+ }
+ return (((uint64_t)L) << 32) + R; /* Concatenate Left and Right 32 bits into 64 bit ciphertext */
+}
+
+/*! \brief Expand key into set of subkeys
+ * \param[in] key (128 bits) as array of bytes
+ * \param[out] arrays of round-specific subkeys - see TS 135 202 for details
+ */
+void
+_kasumi_key_expand(const uint8_t *key, uint16_t *KLi1, uint16_t *KLi2, uint16_t *KOi1, uint16_t *KOi2, uint16_t *KOi3, uint16_t *KIi1, uint16_t *KIi2, uint16_t *KIi3)
+{
+ uint16_t i, C[] = { 0x0123, 0x4567, 0x89AB, 0xCDEF, 0xFEDC, 0xBA98, 0x7654, 0x3210 };
+
+ for (i = 0; i < 8; i++) /* Work with 16 bit subkeys and create prime subkeys */
+ {
+ C[i] ^= osmo_load16be(key + i * 2);
+ }
+ /* C[] now stores K-prime[] */
+ for (i = 0; i < 8; i++) /* Create round-specific subkeys */
+ {
+ KLi1[i] = rol16(osmo_load16be(key + i * 2), 1);
+ KLi2[i] = C[(i + 2) & 0x7];
+
+ KOi1[i] = rol16(osmo_load16be(key + ((2 * (i + 1)) & 0xE)), 5);
+ KOi2[i] = rol16(osmo_load16be(key + ((2 * (i + 5)) & 0xE)), 8);
+ KOi3[i] = rol16(osmo_load16be(key + ((2 * (i + 6)) & 0xE)), 13);
+
+ KIi1[i] = C[(i + 4) & 0x7];
+ KIi2[i] = C[(i + 3) & 0x7];
+ KIi3[i] = C[(i + 7) & 0x7];
+ }
+}
+
+void
+_kasumi_kgcore(uint8_t CA, uint8_t cb, uint32_t cc, uint8_t cd, const uint8_t *ck, uint8_t *co, uint16_t cl)
+{
+ uint16_t KLi1[8], KLi2[8], KOi1[8], KOi2[8], KOi3[8], KIi1[8], KIi2[8], KIi3[8], i;
+ uint64_t A = ((uint64_t)cc) << 32, BLK = 0, _ca = ((uint64_t)CA << 16) ;
+ A |= _ca;
+ _ca = (uint64_t)((cb << 3) | (cd << 2)) << 24;
+ A |= _ca;
+ /* Register loading complete: see TR 55.919 8.2 and TS 55.216 3.2 */
+
+ uint8_t ck_km[16];
+ for (i = 0; i < 16; i++) ck_km[i] = ck[i] ^ 0x55; /* Modified key established */
+
+ /* preliminary round with modified key */
+ _kasumi_key_expand(ck_km, KLi1, KLi2, KOi1, KOi2, KOi3, KIi1, KIi2, KIi3);
+ A = _kasumi(A, KLi1, KLi2, KOi1, KOi2, KOi3, KIi1, KIi2, KIi3);
+
+ /* Run Kasumi in OFB to obtain enough data for gamma. */
+ _kasumi_key_expand(ck, KLi1, KLi2, KOi1, KOi2, KOi3, KIi1, KIi2, KIi3);
+ for (i = 0; i < cl / 64 + 1; i++) /* i is a block counter */
+ {
+ BLK = _kasumi(A ^ i ^ BLK, KLi1, KLi2, KOi1, KOi2, KOi3, KIi1, KIi2, KIi3);
+ osmo_store64be(BLK, co + (i * 8));
+ }
+}
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index d54f940..7551c4a 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -219,6 +219,10 @@ osmo_a5;
osmo_a5_1;
osmo_a5_2;
+_kasumi;
+_kasumi_key_expand;
+_kasumi_kgcore;
+
osmo_auth_alg_name;
osmo_auth_alg_parse;
osmo_auth_gen_vec;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index c6216d5..ddc13dc 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -4,7 +4,7 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test \
smscb/smscb_test bits/bitrev_test a5/a5_test \
conv/conv_test auth/milenage_test lapd/lapd_test \
gsm0808/gsm0808_test gsm0408/gsm0408_test \
- gb/bssgp_fc_test gb/gprs_ns_test \
+ gb/bssgp_fc_test gb/gprs_ns_test kasumi/kasumi_test \
logging/logging_test fr/fr_test \
loggingrb/loggingrb_test strrb/strrb_test \
vty/vty_test comp128/comp128_test utils/utils_test
@@ -19,6 +19,9 @@ utils_utils_test_LDADD = $(top_builddir)/src/libosmocore.la
a5_a5_test_SOURCES = a5/a5_test.c
a5_a5_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la
+kasumi_kasumi_test_SOURCES = kasumi/kasumi_test.c
+kasumi_kasumi_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la
+
comp128_comp128_test_SOURCES = comp128/comp128_test.c
comp128_comp128_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la
@@ -102,7 +105,7 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \
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_ns_test.ok \
+ gb/gprs_ns_test.ok kasumi/kasumi_test.ok \
msgfile/msgfile_test.ok msgfile/msgconfig.cfg \
logging/logging_test.ok logging/logging_test.err \
fr/fr_test.ok loggingrb/logging_test.ok \
diff --git a/tests/kasumi/kasumi_test.c b/tests/kasumi/kasumi_test.c
new file mode 100644
index 0000000..5504905
--- /dev/null
+++ b/tests/kasumi/kasumi_test.c
@@ -0,0 +1,128 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/gsm/kasumi.h> // for testing internal A5/3 functions
+
+
+inline int _compare_mem(uint8_t * x, uint8_t * y, size_t len) {
+ if (0 != memcmp(x, y, len)) {
+ printf ("X: %s\t", osmo_hexdump_nospc(x, len));
+ printf ("Y: %s\n", osmo_hexdump_nospc(y, len));
+ return 0;
+ }
+ return 1;
+}
+
+inline static void test_expansion(uint8_t * test_key, uint16_t * _KLi1, uint16_t * _KLi2, uint16_t * _KOi1, uint16_t * _KOi2, uint16_t * _KOi3, uint16_t * _KIi1, uint16_t * _KIi2, uint16_t * _KIi3, uint16_t * _KLi1_r, uint16_t * _KLi2_r, uint16_t * _KOi1_r, uint16_t * _KOi2_r, uint16_t * _KOi3_r, uint16_t * _KIi1_r, uint16_t * _KIi2_r, uint16_t * _KIi3_r)
+{
+ _kasumi_key_expand(test_key, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3);
+ int passed = 1;
+ passed = _compare_mem((uint8_t *)_KLi1, (uint8_t *)_KLi1_r, 16);
+ passed = _compare_mem((uint8_t *)_KLi2, (uint8_t *)_KLi2_r, 16);
+ passed = _compare_mem((uint8_t *)_KOi1, (uint8_t *)_KOi1_r, 16);
+ passed = _compare_mem((uint8_t *)_KOi2, (uint8_t *)_KOi2_r, 16);
+ passed = _compare_mem((uint8_t *)_KOi3, (uint8_t *)_KOi3_r, 16);
+ passed = _compare_mem((uint8_t *)_KIi1, (uint8_t *)_KIi1_r, 16);
+ passed = _compare_mem((uint8_t *)_KIi2, (uint8_t *)_KIi2_r, 16);
+ passed = _compare_mem((uint8_t *)_KIi3, (uint8_t *)_KIi3_r, 16);
+ if (passed) printf(" OK. "); else printf("FAILED!");
+}
+
+int main(int argc, char **argv)
+{
+ uint16_t _KLi1[8], _KLi2[8], _KOi1[8], _KOi2[8], _KOi3[8], _KIi1[8], _KIi2[8], _KIi3[8], _KLi1_r[8], _KLi2_r[8], _KOi1_r[8], _KOi2_r[8], _KOi3_r[8], _KIi1_r[8], _KIi2_r[8], _KIi3_r[8];
+
+ printf("testing KASUMI key expansion and encryption (ETSI TS 135 203):\n");
+ printf("KASUMI Test Set 1...");
+
+uint8_t _test_key1[] = {0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00, 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48};
+_KLi1_r[0] = 0x57AC; _KLi1_r[1] = 0x8B3E; _KLi1_r[2] = 0x058B; _KLi1_r[3] = 0x6601; _KLi1_r[4] = 0x2A59; _KLi1_r[5] = 0x9220; _KLi1_r[6] = 0x9102; _KLi1_r[7] = 0xFE91;
+_KLi2_r[0] = 0x0B6E; _KLi2_r[1] = 0x7EEF; _KLi2_r[2] = 0x6BF0; _KLi2_r[3] = 0xF388; _KLi2_r[4] = 0x3ED5; _KLi2_r[5] = 0xCD58; _KLi2_r[6] = 0x2AF5; _KLi2_r[7] = 0x00F8;
+_KOi1_r[0] = 0xB3E8; _KOi1_r[1] = 0x58B0; _KOi1_r[2] = 0x6016; _KOi1_r[3] = 0xA592; _KOi1_r[4] = 0x2209; _KOi1_r[5] = 0x1029; _KOi1_r[6] = 0xE91F; _KOi1_r[7] = 0x7AC5;
+_KOi2_r[0] = 0x1049; _KOi2_r[1] = 0x8148; _KOi2_r[2] = 0x48FF; _KOi2_r[3] = 0xD62B; _KOi2_r[4] = 0x9F45; _KOi2_r[5] = 0xC582; _KOi2_r[6] = 0x00B3; _KOi2_r[7] = 0x2C95;
+_KOi3_r[0] = 0x2910; _KOi3_r[1] = 0x1FE9; _KOi3_r[2] = 0xC57A; _KOi3_r[3] = 0xE8B3; _KOi3_r[4] = 0xB058; _KOi3_r[5] = 0x1660; _KOi3_r[6] = 0x92A5; _KOi3_r[7] = 0x0922;
+_KIi1_r[0] = 0x6BF0; _KIi1_r[1] = 0xF388; _KIi1_r[2] = 0x3ED5; _KIi1_r[3] = 0xCD58; _KIi1_r[4] = 0x2AF5; _KIi1_r[5] = 0x00F8; _KIi1_r[6] = 0x0B6E; _KIi1_r[7] = 0x7EEF;
+_KIi2_r[0] = 0x7EEF; _KIi2_r[1] = 0x6BF0; _KIi2_r[2] = 0xF388; _KIi2_r[3] = 0x3ED5; _KIi2_r[4] = 0xCD58; _KIi2_r[5] = 0x2AF5; _KIi2_r[6] = 0x00F8; _KIi2_r[7] = 0x0B6E;
+_KIi3_r[0] = 0xCD58; _KIi3_r[1] = 0x2AF5; _KIi3_r[2] = 0x00F8; _KIi3_r[3] = 0x0B6E; _KIi3_r[4] = 0x7EEF; _KIi3_r[5] = 0x6BF0; _KIi3_r[6] = 0xF388; _KIi3_r[7] = 0x3ED5;
+test_expansion(_test_key1, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3, _KLi1_r, _KLi2_r, _KOi1_r, _KOi2_r, _KOi3_r, _KIi1_r, _KIi2_r, _KIi3_r);
+
+if (0xDF1F9B251C0BF45F == _kasumi(0xEA024714AD5C4D84, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3))
+ printf("OK."); else printf("FAILED!");
+
+printf("\nKASUMI Test Set 2...");
+
+uint8_t _test_key2[] = {0x8C, 0xE3, 0x3E, 0x2C, 0xC3, 0xC0, 0xB5, 0xFC, 0x1F, 0x3D, 0xE8, 0xA6, 0xDC, 0x66, 0xB1, 0xF3};
+_KLi1_r[0] = 0x19C7; _KLi1_r[1] = 0x7C58; _KLi1_r[2] = 0x8781; _KLi1_r[3] = 0x6BF9; _KLi1_r[4] = 0x3E7A; _KLi1_r[5] = 0xD14D; _KLi1_r[6] = 0xB8CD; _KLi1_r[7] = 0x63E7;
+_KLi2_r[0] = 0x4A6B; _KLi2_r[1] = 0x7813; _KLi2_r[2] = 0xE1E1; _KLi2_r[3] = 0x523E; _KLi2_r[4] = 0xAA32; _KLi2_r[5] = 0x83E3; _KLi2_r[6] = 0x8DC0; _KLi2_r[7] = 0x7B4B;
+_KOi1_r[0] = 0xC587; _KOi1_r[1] = 0x7818; _KOi1_r[2] = 0xBF96; _KOi1_r[3] = 0xE7A3; _KOi1_r[4] = 0x14DD; _KOi1_r[5] = 0x8CDB; _KOi1_r[6] = 0x3E76; _KOi1_r[7] = 0x9C71;
+_KOi2_r[0] = 0xA6E8; _KOi2_r[1] = 0x66DC; _KOi2_r[2] = 0xF3B1; _KOi2_r[3] = 0xE38C; _KOi2_r[4] = 0x2C3E; _KOi2_r[5] = 0xC0C3; _KOi2_r[6] = 0xFCB5; _KOi2_r[7] = 0x3D1F;
+_KOi3_r[0] = 0xDB8C; _KOi3_r[1] = 0x763E; _KOi3_r[2] = 0x719C; _KOi3_r[3] = 0x87C5; _KOi3_r[4] = 0x1878; _KOi3_r[5] = 0x96BF; _KOi3_r[6] = 0xA3E7; _KOi3_r[7] = 0xDD14;
+_KIi1_r[0] = 0xE1E1; _KIi1_r[1] = 0x523E; _KIi1_r[2] = 0xAA32; _KIi1_r[3] = 0x83E3; _KIi1_r[4] = 0x8DC0; _KIi1_r[5] = 0x7B4B; _KIi1_r[6] = 0x4A6B; _KIi1_r[7] = 0x7813;
+_KIi2_r[0] = 0x7813; _KIi2_r[1] = 0xE1E1; _KIi2_r[2] = 0x523E; _KIi2_r[3] = 0xAA32; _KIi2_r[4] = 0x83E3; _KIi2_r[5] = 0x8DC0; _KIi2_r[6] = 0x7B4B; _KIi2_r[7] = 0x4A6B;
+_KIi3_r[0] = 0x83E3; _KIi3_r[1] = 0x8DC0; _KIi3_r[2] = 0x7B4B; _KIi3_r[3] = 0x4A6B; _KIi3_r[4] = 0x7813; _KIi3_r[5] = 0xE1E1; _KIi3_r[6] = 0x523E; _KIi3_r[7] = 0xAA32;
+test_expansion(_test_key2, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3, _KLi1_r, _KLi2_r, _KOi1_r, _KOi2_r, _KOi3_r, _KIi1_r, _KIi2_r, _KIi3_r);
+
+if (0xDE551988CEB2F9B7 == _kasumi(0xD3C5D592327FB11C, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3))
+ printf("OK."); else printf("FAILED!");
+
+printf("\nKASUMI Test Set 3...");
+
+uint8_t _test_key3[] = {0x40, 0x35, 0xC6, 0x68, 0x0A, 0xF8, 0xC6, 0xD1, 0xA8, 0xFF, 0x86, 0x67, 0xB1, 0x71, 0x40, 0x13};
+_KLi1_r[0] = 0x806A; _KLi1_r[1] = 0x8CD1; _KLi1_r[2] = 0x15F0; _KLi1_r[3] = 0x8DA3; _KLi1_r[4] = 0x51FF; _KLi1_r[5] = 0x0CCF; _KLi1_r[6] = 0x62E3; _KLi1_r[7] = 0x8026;
+_KLi2_r[0] = 0x8353; _KLi2_r[1] = 0x0B3E; _KLi2_r[2] = 0x5623; _KLi2_r[3] = 0x3CFF; _KLi2_r[4] = 0xC725; _KLi2_r[5] = 0x7203; _KLi2_r[6] = 0x4116; _KLi2_r[7] = 0x830F;
+_KOi1_r[0] = 0xCD18; _KOi1_r[1] = 0x5F01; _KOi1_r[2] = 0xDA38; _KOi1_r[3] = 0x1FF5; _KOi1_r[4] = 0xCCF0; _KOi1_r[5] = 0x2E36; _KOi1_r[6] = 0x0268; _KOi1_r[7] = 0x06A8;
+_KOi2_r[0] = 0x6786; _KOi2_r[1] = 0x71B1; _KOi2_r[2] = 0x1340; _KOi2_r[3] = 0x3540; _KOi2_r[4] = 0x68C6; _KOi2_r[5] = 0xF80A; _KOi2_r[6] = 0xD1C6; _KOi2_r[7] = 0xFFA8;
+_KOi3_r[0] = 0x362E; _KOi3_r[1] = 0x6802; _KOi3_r[2] = 0xA806; _KOi3_r[3] = 0x18CD; _KOi3_r[4] = 0x015F; _KOi3_r[5] = 0x38DA; _KOi3_r[6] = 0xF51F; _KOi3_r[7] = 0xF0CC;
+_KIi1_r[0] = 0x5623; _KIi1_r[1] = 0x3CFF; _KIi1_r[2] = 0xC725; _KIi1_r[3] = 0x7203; _KIi1_r[4] = 0x4116; _KIi1_r[5] = 0x830F; _KIi1_r[6] = 0x8353; _KIi1_r[7] = 0x0B3E;
+_KIi2_r[0] = 0x0B3E; _KIi2_r[1] = 0x5623; _KIi2_r[2] = 0x3CFF; _KIi2_r[3] = 0xC725; _KIi2_r[4] = 0x7203; _KIi2_r[5] = 0x4116; _KIi2_r[6] = 0x830F; _KIi2_r[7] = 0x8353;
+_KIi3_r[0] = 0x7203; _KIi3_r[1] = 0x4116; _KIi3_r[2] = 0x830F; _KIi3_r[3] = 0x8353; _KIi3_r[4] = 0x0B3E; _KIi3_r[5] = 0x5623; _KIi3_r[6] = 0x3CFF; _KIi3_r[7] = 0xC725;
+test_expansion(_test_key3, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3, _KLi1_r, _KLi2_r, _KOi1_r, _KOi2_r, _KOi3_r, _KIi1_r, _KIi2_r, _KIi3_r);
+
+if (0x4592B0E78690F71B == _kasumi(0x62A540981BA6F9B7, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3))
+ printf("OK."); else printf("FAILED!");
+
+printf("\nKASUMI Test Set 4...");
+uint8_t _test_key4[] = {0x3A, 0x3B, 0x39, 0xB5, 0xC3, 0xF2, 0x37, 0x6D, 0x69, 0xF7, 0xD5, 0x46, 0xE5, 0xF8, 0x5D, 0x43};
+uint64_t I4 = 0xCA49C1C75771AB0B, i;
+_kasumi_key_expand(_test_key4, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3);
+
+for (i = 0; i < 50; i++)
+ I4 = _kasumi(I4, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3);
+
+if (0x738BAD4C4A690802 == I4) printf(" OK.\n"); else printf("FAILED!");
+
+
+uint8_t gamma[32];
+
+uint8_t _Key1[] = {0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xBC, 0x00, 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xBC, 0x00},
+_gamma1[] = {0x88, 0x9E, 0xEA, 0xAF, 0x9E, 0xD1, 0xBA, 0x1A, 0xBB, 0xD8, 0x43, 0x62, 0x32, 0xE4, 0x57, 0x28, 0xD0, 0x1A, 0xA8, 0x91, 0x33, 0xDA, 0x73, 0xC1, 0x1E, 0xAB, 0x68, 0xB7, 0xD8, 0x9B, 0xC8, 0x41};
+_kasumi_kgcore(0xF, 0, 0x0024F20F, 0, _Key1, gamma, 228);
+printf ("KGCORE Test Set 1: %d\n", _compare_mem(gamma, _gamma1, 32));
+
+uint8_t _Key2[] = {0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48, 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48},
+_gamma2[] = {0xFB, 0x4D, 0x5F, 0xBC, 0xEE, 0x13, 0xA3, 0x33, 0x89, 0x28, 0x56, 0x86, 0xE9, 0xA5, 0xC9, 0x42, 0x40, 0xDE, 0x38, 0x15, 0x01, 0x15, 0xF1, 0x5F, 0x8D, 0x9D, 0x98, 0xB9, 0x1A, 0x94, 0xB2, 0x96};
+_kasumi_kgcore(0xF, 0, 0x00061272, 0, _Key2, gamma, 228);
+printf ("KGCORE Test Set 2: %d\n", _compare_mem(gamma, _gamma2, 32));
+
+uint8_t _Key3[] = {0xEF, 0xA8, 0xB2, 0x22, 0x9E, 0x72, 0x0C, 0x2A, 0xEF, 0xA8, 0xB2, 0x22, 0x9E, 0x72, 0x0C, 0x2A},
+_gamma3[] = {0x0E, 0x40, 0x15, 0x75, 0x5A, 0x33, 0x64, 0x69, 0xC3, 0xDD, 0x86, 0x80, 0xE3, 0x03, 0x5B, 0xC4, 0x19, 0xA7, 0x8A, 0xD3, 0x86, 0x2C, 0x10, 0x90, 0xC6, 0x8A, 0x39, 0x1F, 0xE8, 0xA6, 0xAD, 0xEB};
+_kasumi_kgcore(0xF, 0, 0x0033FD3F, 0, _Key3, gamma, 228);
+printf ("KGCORE Test Set 3: %d\n", _compare_mem(gamma, _gamma3, 32));
+
+uint8_t _Key4[] = {0x5A, 0xCB, 0x1D, 0x64, 0x4C, 0x0D, 0x51, 0x20, 0x4E, 0xA5, 0x5A, 0xCB, 0x1D, 0x64, 0x4C, 0x0D},
+_gamma4[] = {0xE0, 0x95, 0x30, 0x6A, 0xD5, 0x08, 0x6E, 0x2E, 0xAC, 0x7F, 0x31, 0x07, 0xDE, 0x4F, 0xA2, 0x2D, 0xC1, 0xDF, 0xC9, 0x7D, 0x5B, 0xC5, 0x66, 0x1D, 0xD6, 0x09, 0x6F, 0x47, 0x6A, 0xED, 0xC6, 0x4B};
+_kasumi_kgcore(0xF, 0, 0x00156B26, 0, _Key4, gamma, 228);
+printf ("KGCORE Test Set 4: %d\n", _compare_mem(gamma, _gamma4, 32));
+
+uint8_t _Key5[] = {0xD3, 0xC5, 0xD5, 0x92, 0x32, 0x7F, 0xB1, 0x1C, 0x40, 0x35, 0xC6, 0x68, 0x0A, 0xF8, 0xC6, 0xD1},
+_gamma5[] = {0xDC, 0xE6, 0x43, 0x62, 0xAB, 0x5F, 0x89, 0xC1, 0x1E, 0xF0, 0xB3, 0x05, 0x16, 0x65, 0x70, 0xF4, 0x88, 0x9D, 0x55, 0x11, 0xE9, 0xE3, 0x57, 0x5D, 0x06, 0x2B, 0x5C, 0xED, 0x60, 0x39, 0x50, 0x6A};
+_kasumi_kgcore(0xF, 0, 0x000A59B4, 0, _Key5, gamma, 228);
+printf ("KGCORE Test Set 5: %d\n", _compare_mem(gamma, _gamma5, 32));
+
+ return 0;
+}
diff --git a/tests/kasumi/kasumi_test.ok b/tests/kasumi/kasumi_test.ok
new file mode 100644
index 0000000..2c2af4c
--- /dev/null
+++ b/tests/kasumi/kasumi_test.ok
@@ -0,0 +1,10 @@
+testing KASUMI key expansion and encryption (ETSI TS 135 203):
+KASUMI Test Set 1... OK. OK.
+KASUMI Test Set 2... OK. OK.
+KASUMI Test Set 3... OK. OK.
+KASUMI Test Set 4... OK.
+KGCORE Test Set 1: 1
+KGCORE Test Set 2: 1
+KGCORE Test Set 3: 1
+KGCORE Test Set 4: 1
+KGCORE Test Set 5: 1
--
1.8.3.2
--------------040706090709050002010705--
1
0
---
include/osmocom/core/bits.h | 291 +++++++++++++++++++++++++++++++++++++++++++-
include/osmocom/core/msgb.h | 23 ++--
src/gsm/libosmogsm.map | 23 ++++
tests/bits/bitrev_test.c | 134 +++++++++++++++++++-
tests/bits/bitrev_test.ok | 15 +++
5 files changed, 472 insertions(+), 14 deletions(-)
diff --git a/include/osmocom/core/bits.h b/include/osmocom/core/bits.h
index 4c68532..fa4d900 100644
--- a/include/osmocom/core/bits.h
+++ b/include/osmocom/core/bits.h
@@ -2,7 +2,7 @@
#define _OSMO_BITS_H
#include <stdint.h>
-
+#include <stddef.h>
/*! \defgroup bits soft, unpacked and packed bits
* @{
*/
@@ -15,6 +15,285 @@ typedef int8_t sbit_t; /*!< \brief soft bit (-127...127) */
typedef uint8_t ubit_t; /*!< \brief unpacked bit (0 or 1) */
typedef uint8_t pbit_t; /*!< \brief packed bis (8 bits in a byte) */
+/* Load unaligned 16-bit integer (little-endian encoding) */
+static inline uint16_t osmo_load16le(const uint8_t *p)
+{
+ return ((uint16_t)p[0]) | ((uint16_t)p[1] << 8);
+}
+
+/* Load unaligned 16-bit integer (big-endian encoding) */
+static inline uint16_t osmo_load16be(const uint8_t *p)
+{
+ return ((uint16_t)p[0] << 8) | ((uint16_t)p[1]);
+}
+
+/* Load unaligned 24-bit integer (little-endian encoding) */
+static inline uint32_t osmo_load24le(const uint8_t *p)
+{
+ return ((uint32_t)p[0]) |
+ ((uint32_t)p[1] << 8) |
+ ((uint32_t)p[2] << 16);
+}
+
+/* Load unaligned 24-bit integer (big-endian encoding) */
+static inline uint32_t osmo_load24be(const uint8_t *p)
+{
+ return ((uint32_t)p[0] << 16) |
+ ((uint32_t)p[1] << 8) |
+ ((uint32_t)p[2]);
+}
+
+/* Load unaligned 32-bit integer (little-endian encoding) */
+static inline uint32_t osmo_load32le(const uint8_t *p)
+{
+ return ((uint32_t)p[0]) |
+ ((uint32_t)p[1] << 8) |
+ ((uint32_t)p[2] << 16) |
+ ((uint32_t)p[3] << 24);
+}
+
+/* Load unaligned 32-bit integer (big-endian encoding) */
+static inline uint32_t osmo_load32be(const uint8_t *p)
+{
+ return ((uint32_t)p[0] << 24) |
+ ((uint32_t)p[1] << 16) |
+ ((uint32_t)p[2] << 8) |
+ ((uint32_t)p[3]);
+}
+
+/* Load unaligned 40-bit integer (little-endian encoding) */
+static inline uint64_t osmo_load40le(const uint8_t *p)
+{
+ return ((uint64_t)p[0]) |
+ ((uint64_t)p[1] << 8) |
+ ((uint64_t)p[2] << 16) |
+ ((uint64_t)p[3] << 24) |
+ ((uint64_t)p[4] << 32);
+}
+
+/* Load unaligned 40-bit integer (big-endian encoding) */
+static inline uint64_t osmo_load40be(const uint8_t *p)
+{
+ return (((uint64_t)p[0]) << 32) |
+ ((uint64_t)p[1] << 24) |
+ ((uint64_t)p[2] << 16) |
+ ((uint64_t)p[3] << 8) |
+ ((uint64_t)p[4]);
+}
+
+/* Load unaligned 48-bit integer (little-endian encoding) */
+static inline uint64_t osmo_load48le(const uint8_t *p)
+{
+ return ((uint64_t)p[0]) |
+ ((uint64_t)p[1] << 8) |
+ ((uint64_t)p[2] << 16) |
+ ((uint64_t)p[3] << 24) |
+ ((uint64_t)p[4] << 32) |
+ ((uint64_t)p[5] << 40);
+}
+
+/* Load unaligned 48-bit integer (big-endian encoding) */
+static inline uint64_t osmo_load48be(const uint8_t *p)
+{
+ return (((uint64_t)p[0]) << 40) |
+ ((uint64_t)p[1] << 32) |
+ ((uint64_t)p[2] << 24) |
+ ((uint64_t)p[3] << 16) |
+ ((uint64_t)p[4] << 8) |
+ ((uint64_t)p[5]);
+}
+
+/* Load unaligned 56-bit integer (little-endian encoding) */
+static inline uint64_t osmo_load56le(const uint8_t *p)
+{
+ return ((uint64_t)p[0]) |
+ ((uint64_t)p[1] << 8) |
+ ((uint64_t)p[2] << 16) |
+ ((uint64_t)p[3] << 24) |
+ ((uint64_t)p[4] << 32) |
+ ((uint64_t)p[5] << 40) |
+ ((uint64_t)p[6] << 48);
+}
+
+/* Load unaligned 56-bit integer (big-endian encoding) */
+static inline uint64_t osmo_load56be(const uint8_t *p)
+{
+ return (((uint64_t)p[0]) << 48) |
+ ((uint64_t)p[1] << 40) |
+ ((uint64_t)p[2] << 32) |
+ ((uint64_t)p[3] << 24) |
+ ((uint64_t)p[4] << 16) |
+ ((uint64_t)p[5] << 8) |
+ ((uint64_t)p[6]);
+}
+
+/* Load unaligned 64-bit integer (little-endian encoding) */
+static inline uint64_t osmo_load64le(const uint8_t *p)
+{
+ return ((uint64_t)p[0]) |
+ ((uint64_t)p[1] << 8) |
+ ((uint64_t)p[2] << 16) |
+ ((uint64_t)p[3] << 24) |
+ ((uint64_t)p[4] << 32) |
+ ((uint64_t)p[5] << 40) |
+ ((uint64_t)p[6] << 48) |
+ ((uint64_t)p[7] << 56);
+}
+
+/* Load unaligned 64-bit integer (big-endian encoding) */
+static inline uint64_t osmo_load64be(const uint8_t *p)
+{
+ return (((uint64_t)p[0]) << 56) |
+ ((uint64_t)p[1] << 48) |
+ ((uint64_t)p[2] << 40) |
+ ((uint64_t)p[3] << 32) |
+ ((uint64_t)p[4] << 24) |
+ ((uint64_t)p[5] << 16) |
+ ((uint64_t)p[6] << 8) |
+ ((uint64_t)p[7]);
+}
+
+/* Store unaligned 16-bit integer (little-endian encoding) */
+static inline void osmo_store16le(uint16_t a, uint8_t *p)
+{
+ ((uint8_t *)p)[0] = (a) & 0xFF;
+ ((uint8_t *)p)[1] = (a >> 8) & 0xFF;
+}
+
+/* Store unaligned 16-bit integer (big-endian encoding) */
+static inline void osmo_store16be(uint16_t a, uint8_t *p)
+{
+ ((uint8_t *)p)[0] = (a >> 8) & 0xFF;
+ ((uint8_t *)p)[1] = (a) & 0xFF;
+}
+
+/* Store unaligned 24-bit integer (little-endian encoding) */
+static inline void osmo_store24le(uint32_t a, uint8_t *p)
+{
+ ((uint8_t *)p)[0] = a & 0xFF;
+ ((uint8_t *)p)[1] = (a >> 8) & 0xFF;
+ ((uint8_t *)p)[2] = (a >> 16) & 0xFF;
+}
+
+/* Store unaligned 24-bit integer (big-endian encoding) */
+static inline void osmo_store24be(uint32_t a, uint8_t *p)
+{
+ ((uint8_t *)p)[0] = (a >> 16) & 0xFF;
+ ((uint8_t *)p)[1] = (a >> 8) & 0xFF;
+ ((uint8_t *)p)[2] = a & 0xFF;
+}
+
+/* Store unaligned 32-bit integer (little-endian encoding) */
+static inline void osmo_store32le(uint32_t a, uint8_t *p)
+{
+ ((uint8_t *)p)[0] = a & 0xFF;
+ ((uint8_t *)p)[1] = (a >> 8) & 0xFF;
+ ((uint8_t *)p)[2] = (a >> 16) & 0xFF;
+ ((uint8_t *)p)[3] = (a >> 24) & 0xFF;
+}
+
+/* Store unaligned 32-bit integer (big-endian encoding) */
+static inline void osmo_store32be(uint32_t a, uint8_t *p)
+{
+ ((uint8_t *)p)[0] = (a >> 24) & 0xFF;
+ ((uint8_t *)p)[1] = (a >> 16) & 0xFF;
+ ((uint8_t *)p)[2] = (a >> 8) & 0xFF;
+ ((uint8_t *)p)[3] = a & 0xFF;
+}
+
+/* Store unaligned 40-bit integer (little-endian encoding) */
+static inline void osmo_store40le(uint64_t a, uint8_t *p)
+{
+ ((uint8_t *)p)[0] = a & 0xFF;
+ ((uint8_t *)p)[1] = (a >> 8) & 0xFF;
+ ((uint8_t *)p)[2] = (a >> 16) & 0xFF;
+ ((uint8_t *)p)[3] = (a >> 24) & 0xFF;
+ ((uint8_t *)p)[4] = (a >> 32) & 0xFF;
+}
+
+/* Store unaligned 40-bit integer (big-endian encoding) */
+static inline void osmo_store40be(uint64_t a, uint8_t *p)
+{
+ ((uint8_t *)p)[0] = (a >> 32) & 0xFF;
+ ((uint8_t *)p)[1] = (a >> 24) & 0xFF;
+ ((uint8_t *)p)[2] = (a >> 16) & 0xFF;
+ ((uint8_t *)p)[3] = (a >> 8) & 0xFF;
+ ((uint8_t *)p)[4] = a & 0xFF;
+}
+
+/* Store unaligned 48-bit integer (little-endian encoding) */
+static inline void osmo_store48le(uint64_t a, uint8_t *p)
+{
+ ((uint8_t *)p)[0] = a & 0xFF;
+ ((uint8_t *)p)[1] = (a >> 8) & 0xFF;
+ ((uint8_t *)p)[2] = (a >> 16) & 0xFF;
+ ((uint8_t *)p)[3] = (a >> 24) & 0xFF;
+ ((uint8_t *)p)[4] = (a >> 32) & 0xFF;
+ ((uint8_t *)p)[5] = (a >> 40) & 0xFF;
+}
+
+/* Store unaligned 48-bit integer (big-endian encoding) */
+static inline void osmo_store48be(uint64_t a, uint8_t *p)
+{
+ ((uint8_t *)p)[0] = (a >> 40) & 0xFF;
+ ((uint8_t *)p)[1] = (a >> 32) & 0xFF;
+ ((uint8_t *)p)[2] = (a >> 24) & 0xFF;
+ ((uint8_t *)p)[3] = (a >> 16) & 0xFF;
+ ((uint8_t *)p)[4] = (a >> 8) & 0xFF;
+ ((uint8_t *)p)[5] = a & 0xFF;
+}
+
+/* Store unaligned 56-bit integer (little-endian encoding) */
+static inline void osmo_store56le(uint64_t a, uint8_t *p)
+{
+ ((uint8_t *)p)[0] = a & 0xFF;
+ ((uint8_t *)p)[1] = (a >> 8) & 0xFF;
+ ((uint8_t *)p)[2] = (a >> 16) & 0xFF;
+ ((uint8_t *)p)[3] = (a >> 24) & 0xFF;
+ ((uint8_t *)p)[4] = (a >> 32) & 0xFF;
+ ((uint8_t *)p)[5] = (a >> 40) & 0xFF;
+ ((uint8_t *)p)[6] = (a >> 48) & 0xFF;
+}
+
+/* Store unaligned 56-bit integer (big-endian encoding) */
+static inline void osmo_store56be(uint64_t a, uint8_t *p)
+{
+ ((uint8_t *)p)[0] = (a >> 48) & 0xFF;
+ ((uint8_t *)p)[1] = (a >> 40) & 0xFF;
+ ((uint8_t *)p)[2] = (a >> 32) & 0xFF;
+ ((uint8_t *)p)[3] = (a >> 24) & 0xFF;
+ ((uint8_t *)p)[4] = (a >> 16) & 0xFF;
+ ((uint8_t *)p)[5] = (a >> 8) & 0xFF;
+ ((uint8_t *)p)[6] = a & 0xFF;
+}
+
+/* Store unaligned 64-bit integer (little-endian encoding) */
+static inline void osmo_store64le(uint64_t a, uint8_t *p)
+{
+ ((uint8_t *)p)[0] = a & 0xFF;
+ ((uint8_t *)p)[1] = (a >> 8) & 0xFF;
+ ((uint8_t *)p)[2] = (a >> 16) & 0xFF;
+ ((uint8_t *)p)[3] = (a >> 24) & 0xFF;
+ ((uint8_t *)p)[4] = (a >> 32) & 0xFF;
+ ((uint8_t *)p)[5] = (a >> 40) & 0xFF;
+ ((uint8_t *)p)[6] = (a >> 48) & 0xFF;
+ ((uint8_t *)p)[7] = (a >> 56) & 0xFF;
+}
+
+/* Store unaligned 64-bit integer (big-endian encoding) */
+static inline void osmo_store64be(uint64_t a, uint8_t *p)
+{
+
+ ((uint8_t *)p)[0] = (a >> 56) & 0xFF;
+ ((uint8_t *)p)[1] = (a >> 48) & 0xFF;
+ ((uint8_t *)p)[2] = (a >> 40) & 0xFF;
+ ((uint8_t *)p)[3] = (a >> 32) & 0xFF;
+ ((uint8_t *)p)[4] = (a >> 24) & 0xFF;
+ ((uint8_t *)p)[5] = (a >> 16) & 0xFF;
+ ((uint8_t *)p)[6] = (a >> 8) & 0xFF;
+ ((uint8_t *)p)[7] = a & 0xFF;
+}
+
/*
NOTE on the endianess of pbit_t:
Bits in a pbit_t are ordered MSB first, i.e. 0x80 is the first bit.
@@ -73,6 +352,16 @@ uint32_t osmo_revbytebits_8(uint8_t x);
/* \brief reverse the bits of each byte in a given buffer */
void osmo_revbytebits_buf(uint8_t *buf, int len);
+/* \brief reverse the order of the bytes in a given buffer */
+void osmo_revbytes_buf(uint8_t *buf, size_t len);
+
+/* \brief left circular shift */
+static inline uint16_t rol16(uint16_t in, unsigned shift)
+{
+ return (in << shift) | (in >> (16 - shift));
+}
+
+
/*! @} */
#endif /* _OSMO_BITS_H */
diff --git a/include/osmocom/core/msgb.h b/include/osmocom/core/msgb.h
index fe2733b..72fdc24 100644
--- a/include/osmocom/core/msgb.h
+++ b/include/osmocom/core/msgb.h
@@ -23,6 +23,7 @@
#include <stdint.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/utils.h>
+#include <osmocom/core/bits.h>
/*! \defgroup msgb Message buffers
* @{
@@ -204,8 +205,7 @@ static inline void msgb_put_u8(struct msgb *msgb, uint8_t word)
static inline void msgb_put_u16(struct msgb *msgb, uint16_t word)
{
uint8_t *space = msgb_put(msgb, 2);
- space[0] = word >> 8 & 0xFF;
- space[1] = word & 0xFF;
+ osmo_store16be(word, space);
}
/*! \brief append a uint32 value to the end of the message
@@ -215,10 +215,7 @@ static inline void msgb_put_u16(struct msgb *msgb, uint16_t word)
static inline void msgb_put_u32(struct msgb *msgb, uint32_t word)
{
uint8_t *space = msgb_put(msgb, 4);
- space[0] = word >> 24 & 0xFF;
- space[1] = word >> 16 & 0xFF;
- space[2] = word >> 8 & 0xFF;
- space[3] = word & 0xFF;
+ osmo_store32be(word, space);
}
/*! \brief remove data from end of message
@@ -235,6 +232,7 @@ static inline unsigned char *msgb_get(struct msgb *msgb, unsigned int len)
msgb->len -= len;
return tmp;
}
+
/*! \brief remove uint8 from end of message
* \param[in] msgb message buffer
* \returns 8bit value taken from end of msgb
@@ -244,6 +242,7 @@ static inline uint8_t msgb_get_u8(struct msgb *msgb)
uint8_t *space = msgb_get(msgb, 1);
return space[0];
}
+
/*! \brief remove uint16 from end of message
* \param[in] msgb message buffer
* \returns 16bit value taken from end of msgb
@@ -251,8 +250,9 @@ static inline uint8_t msgb_get_u8(struct msgb *msgb)
static inline uint16_t msgb_get_u16(struct msgb *msgb)
{
uint8_t *space = msgb_get(msgb, 2);
- return space[0] << 8 | space[1];
+ return osmo_load16be(space);
}
+
/*! \brief remove uint32 from end of message
* \param[in] msgb message buffer
* \returns 32bit value taken from end of msgb
@@ -260,7 +260,7 @@ static inline uint16_t msgb_get_u16(struct msgb *msgb)
static inline uint32_t msgb_get_u32(struct msgb *msgb)
{
uint8_t *space = msgb_get(msgb, 4);
- return space[0] << 24 | space[1] << 16 | space[2] << 8 | space[3];
+ return osmo_load32be(space);
}
/*! \brief prepend (push) some data to start of message
@@ -284,6 +284,7 @@ static inline unsigned char *msgb_push(struct msgb *msgb, unsigned int len)
msgb->len += len;
return msgb->data;
}
+
/*! \brief remove (pull) a header from the front of the message buffer
* \param[in] msgb message buffer
* \param[in] len number of octets to be pulled
@@ -308,6 +309,7 @@ static inline uint8_t msgb_pull_u8(struct msgb *msgb)
uint8_t *space = msgb_pull(msgb, 1) - 1;
return space[0];
}
+
/*! \brief remove uint16 from front of message
* \param[in] msgb message buffer
* \returns 16bit value taken from end of msgb
@@ -315,8 +317,9 @@ static inline uint8_t msgb_pull_u8(struct msgb *msgb)
static inline uint16_t msgb_pull_u16(struct msgb *msgb)
{
uint8_t *space = msgb_pull(msgb, 2) - 2;
- return space[0] << 8 | space[1];
+ return osmo_load16be(space);
}
+
/*! \brief remove uint32 from front of message
* \param[in] msgb message buffer
* \returns 32bit value taken from end of msgb
@@ -324,7 +327,7 @@ static inline uint16_t msgb_pull_u16(struct msgb *msgb)
static inline uint32_t msgb_pull_u32(struct msgb *msgb)
{
uint8_t *space = msgb_pull(msgb, 4) - 4;
- return space[0] << 24 | space[1] << 16 | space[2] << 8 | space[3];
+ return osmo_load32be(space);
}
/*! \brief Increase headroom of empty msgb, reducing the tailroom
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index 9d15d66..d54f940 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -22,6 +22,29 @@ abis_nm_test_name;
osmo_sitype_strs;
+osmo_load16le;
+osmo_load16be;
+osmo_load24le;
+osmo_load24be;
+osmo_load32le;
+osmo_load32be;
+osmo_load64le;
+osmo_load64be;
+osmo_store16le;
+osmo_store16be;
+osmo_store24le;
+osmo_store24be;
+osmo_store32le;
+osmo_store32be;
+osmo_store40le;
+osmo_store40be;
+osmo_store48le;
+osmo_store48be;
+osmo_store56le;
+osmo_store56be;
+osmo_store64le;
+osmo_store64be;
+
comp128;
dbm2rxlev;
diff --git a/tests/bits/bitrev_test.c b/tests/bits/bitrev_test.c
index 5eca990..f82dbf3 100644
--- a/tests/bits/bitrev_test.c
+++ b/tests/bits/bitrev_test.c
@@ -1,4 +1,4 @@
-
+#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@@ -12,9 +12,10 @@ static const uint8_t exp_out[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x0
int main(int argc, char **argv)
{
- uint8_t out[ARRAY_SIZE(input)];
+ uint8_t out[ARRAY_SIZE(input)], test[8];
unsigned int offs;
-
+ char s[18], *p;
+
for (offs = 0; offs < sizeof(out); offs++) {
uint8_t *start = out + offs;
uint8_t len = sizeof(out) - offs;
@@ -32,5 +33,132 @@ int main(int argc, char **argv)
printf("\n");
}
+ printf("checking byte packing...\n");
+
+ uint64_t _test64 = ((uint64_t)rand() << 32) + rand();
+ osmo_store64be(_test64, test);
+
+ snprintf(s, 17, "%.16" PRIx64, _test64);
+ p = osmo_hexdump_nospc(test, 8);
+ if (0 != memcmp(s, p, 8)) {
+ printf ("%s\t", s);
+ printf ("%s\t", p);
+ printf("64 BE FAILED!\n");
+ } else printf("64 BE OK\n");
+
+ osmo_store64le(_test64, test);
+ if (osmo_load64le(test) == _test64)
+ printf("64 LE OK\n");
+ else
+ printf("64 LE FAILED: %s, %.16" PRIx64 ", %.16" PRIx64 "\n", osmo_hexdump(test, 8), osmo_load64le(test), _test64);
+
+
+ uint64_t _test56 = ((((uint64_t)rand() << 32) + rand()) << 8) >> 8;
+ osmo_store56be(_test56, test);
+
+ snprintf(s, 17, "%.14" PRIx64, _test56);
+ p = osmo_hexdump_nospc(test, 7);
+ if (0 != memcmp(s, p, 7)) {
+ printf ("%s\t", s);
+ printf ("%s\t", p);
+ printf("56 BE FAILED!\n");
+ } else printf("56 BE OK\n");
+
+ osmo_store56le(_test56, test);
+ if (osmo_load56le(test) == _test56)
+ printf("56 LE OK\n");
+ else
+ printf("56 LE FAILED: %s, %.14" PRIx64 ", %.14" PRIx64 "\n", osmo_hexdump(test, 7), osmo_load56le(test), _test56);
+
+
+ uint64_t _test48 = ((((uint64_t)rand() << 32) + rand()) << 16) >> 16;
+ osmo_store48be(_test48, test);
+
+ snprintf(s, 17, "%.12" PRIx64, _test48);
+ p = osmo_hexdump_nospc(test, 6);
+ if (0 != memcmp(s, p, 6)) {
+ printf ("%s\t", s);
+ printf ("%s\t", p);
+ printf("48 BE FAILED!\n");
+ } else printf("48 BE OK\n");
+
+ osmo_store48le(_test48, test);
+ if (osmo_load48le(test) == _test48)
+ printf("48 LE OK\n");
+ else
+ printf("48 LE FAILED: %s, %.12" PRIx64 ", %.12" PRIx64 "\n", osmo_hexdump(test, 6), osmo_load48le(test), _test48);
+
+
+ uint64_t _test40 = ((((uint64_t)rand() << 32) + rand()) << 24) >> 24;
+ osmo_store40be(_test40, test);
+
+ snprintf(s, 17, "%.10" PRIx64, _test40);
+ p = osmo_hexdump_nospc(test, 5);
+ if (0 != memcmp(s, p, 5)) {
+ printf ("%s\t", s);
+ printf ("%s\t", p);
+ printf("40 BE FAILED!\n");
+ } else printf("40 BE OK\n");
+
+ osmo_store40le(_test40, test);
+ if (osmo_load40le(test) == _test40)
+ printf("40 LE OK\n");
+ else
+ printf("40 LE FAILED: %s, %.10" PRIx64 ", %.10" PRIx64 "\n", osmo_hexdump(test, 5), osmo_load40le(test), _test40);
+
+
+ uint32_t _test32 = (uint32_t)rand();
+ osmo_store32be(_test32, test);
+
+ snprintf(s, 17, "%.8" PRIx32, _test32);
+ p = osmo_hexdump_nospc(test, 4);
+ if (0 != memcmp(s, p, 4)) {
+ printf ("%s\t", s);
+ printf ("%s\t", p);
+ printf("32 BE FAILED!\n");
+ } else printf("32 BE OK\n");
+
+ osmo_store32le(_test32, test);
+ if (osmo_load32le(test) == _test32)
+ printf("32 LE OK\n");
+ else
+ printf("32 LE FAILED: %s, %.8" PRIx32 ", %.8" PRIx32 "\n", osmo_hexdump(test, 4), osmo_load32le(test), _test32);
+
+
+ uint32_t _test24 = ((uint32_t)rand() << 8) >> 8;
+ osmo_store24be(_test24, test);
+
+ snprintf(s, 17, "%.6" PRIx32, _test24);
+ p = osmo_hexdump_nospc(test, 3);
+ if (0 != memcmp(s, p, 3)) {
+ printf ("%s\t", s);
+ printf ("%s\t", p);
+ printf("24 BE FAILED!\n");
+ } else printf("24 BE OK\n");
+
+ osmo_store24le(_test24, test);
+ if (osmo_load24le(test) == _test24)
+ printf("24 LE OK\n");
+ else
+ printf("24 LE FAILED: %s, %.6" PRIx32 ", %.6" PRIx32 "\n", osmo_hexdump(test, 3), osmo_load24le(test), _test24);
+
+
+ uint16_t _test16 = (uint16_t)rand();
+ osmo_store16be(_test16, test);
+
+ snprintf(s, 17, "%.4" PRIx16, _test16);
+ p = osmo_hexdump_nospc(test, 2);
+ if (0 != memcmp(s, p, 2)) {
+ printf ("%s\t", s);
+ printf ("%s\t", p);
+ printf("16 BE FAILED!\n");
+ } else printf("16 BE OK\n");
+
+ osmo_store16le(_test16, test);
+ if (osmo_load16le(test) == _test16)
+ printf("16 LE OK\n");
+ else
+ printf("16 LE FAILED: %s, %.4" PRIx16 ", %.4" PRIx16 "\n", osmo_hexdump(test, 2), osmo_load16le(test), _test16);
+
return 0;
}
diff --git a/tests/bits/bitrev_test.ok b/tests/bits/bitrev_test.ok
index 47f402f..e319af2 100644
--- a/tests/bits/bitrev_test.ok
+++ b/tests/bits/bitrev_test.ok
@@ -22,3 +22,18 @@ REVERSED: 02 01
INORDER: 80
REVERSED: 01
+checking byte packing...
+64 BE OK
+64 LE OK
+56 BE OK
+56 LE OK
+48 BE OK
+48 LE OK
+40 BE OK
+40 LE OK
+32 BE OK
+32 LE OK
+24 BE OK
+24 LE OK
+16 BE OK
+16 LE OK
--
1.8.3.2
--------------060209070104080702030101
Content-Type: text/x-patch;
name="0002-Add-Kasumi-cipher-implementation.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="0002-Add-Kasumi-cipher-implementation.patch"
1
0
Hello dear osmocom team
first off, thanks for all the work you have
put into this project. Its great to have a starting
point for toying with this new/old technology. ;)
I got myself a C155 and have used osmocom-bb on it
to read some traffic with wireshark. So far everything
works nicely.
Now i wanted to communicate with a second phone and
have tried setting up a BTS following this guide
http://openbsc.osmocom.org/trac/wiki/network_from_scratch
(using a single phone)
My problem is that the phone doesnt transmit anything.
Yes i have enabled the transmitter flag in the Makefile. ;)
When i use osmocon to load the TRX into the phone and start the
osmocom-transceiver i get this debug output from osmocon.
...
Synchronize_TDMA
=>FB @ FNR 26585 fn_offset=2002505 qbits=4924
LOST 1910!
BTS MODE: 255 65535 {0,0,0,0,0,0,0,0} TX 0..7 RX 0..7
After taking a look at the code the values seem weird
and they come from the transceiver function l1ctl_tx_bts_mode()
like that.
/host/layer23/src/transceiver/l1ctl.c:120
As a test i got the phone to transmit something by
overwriting the values on the TRX side.
I havent gone further yet but wanted to ask if someone could
maybe point me to an obvious mistake i did before i
spend more hours on this issue.
A hint as to how i enable the different logging settings
would be great as well.
thanks,
best regards, Christian
1
1
Hi everyone,Now I am facing some unknown problem to me.
I am getting the following error messages
(1) on the terminal after uploading layer1:
Failed to write msg to the socket(2) failed to connect to '/tmp/osmocom_sap'
Failed during sap_open (), no SIM reader
<000c> l1ctl.c:118 FBSB RESP: result=255
<000f> sim.c:858 received APDU but no job, please fixShall anyone tell me where I am doing wrong?
What exactly is the problem. Because earlier when I run mobile application then it was working well.Thanks in advance.NeeteshSent from RediffmailNG on Android
From: "neetesh saxena"saxenaneetesh061(a)rediffmail.com
Sent:Wed, 22 Jan 2014 16:51:45 +0530
To: "baseband-devel " baseband-devel(a)lists.osmocom.org
Subject: Query regarding running osmoocomBB
Hi everyone,
>
>Here, i wish to know the answer of a basic question. When I uploaded the firmware onto the mobile phone (with ./osmocon command), I can start other application programs like CCCh program, mobile program in other terminals.
>
>My problem is when I am doing it I can see that the layer1 is uploaded onto the phone but I am not able to switch on my phone. When I again press the red button to start phone, it again starts getting uploaded layer1.
>
>When I terminate the command of uploading firmware and start my phone then I am not able to view of SIM details and it shows me "service is unavailable" or "administratively down".
>
>My question is we need to continue run the terminal with ./osmocon command (for uploading layer1) or i need to stop it after uploading layer1 once onto the phone. When to switched on my phone ?
>
>
>With regards
> Neetesh Saxena...
>
>
>
>Get your own FREE website, FREE domain & FREE mobile app with Company email. Know More >
1
0
neetesh saxena wrote:
> My question is we need to continue run the terminal with ./osmocon
> command (for uploading layer1)
Yes.
> or i need to stop it after uploading layer1 once onto the phone.
No.
> When to switched on my phone ?
If layer1 is successfully uploaded then the phone is already switched on.
Just start the layer23 (mobile, ccch_scan, etc..) program on the host.
//Peter
1
0
Hi everyone,
Here, i wish to know the answer of a basic question. When I uploaded the firmware onto the mobile phone (with ./osmocon command), I can start other application programs like CCCh program, mobile program in other terminals.
My problem is when I am doing it I can see that the layer1 is uploaded onto the phone but I am not able to switch on my phone. When I again press the red button to start phone, it again starts getting uploaded layer1.
When I terminate the command of uploading firmware and start my phone then I am not able to view of SIM details and it shows me "service is unavailable" or "administratively down".
My question is we need to continue run the terminal with ./osmocon command (for uploading layer1) or i need to stop it after uploading layer1 once onto the phone. When to switched on my phone ?
With regards
Neetesh Saxena...
1
0