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 | 3 +-
include/Makefile.am | 6 +
include/osmocom/core/bitXXgen.h.tpl | 86 ++++++++++++++
include/osmocom/core/bits.h | 45 +++++++-
include/osmocom/core/msgb.h | 23 ++--
tests/bits/bitrev_test.c | 218 +++++++++++++++++++++++++++++++++++-
tests/bits/bitrev_test.ok | 31 +++++
7 files changed, 399 insertions(+), 13 deletions(-)
create mode 100644 include/osmocom/core/bitXXgen.h.tpl
diff --git a/.gitignore b/.gitignore
index 71b27f2..3fa1bbc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,6 +55,7 @@ tests/testsuite
tests/testsuite.dir/
tests/testsuite.log
+tests/utils/utils_test
tests/sms/sms_test
tests/timer/timer_test
tests/msgfile/msgfile_test
@@ -89,7 +90,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/Makefile.am b/include/Makefile.am
index b035906..18011ff 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -2,6 +2,8 @@ nobase_include_HEADERS = \
osmocom/codec/codec.h \
osmocom/core/application.h \
osmocom/core/backtrace.h \
+ osmocom/core/bit32gen.h \
+ osmocom/core/bit64gen.h \
osmocom/core/bits.h \
osmocom/core/bitvec.h \
osmocom/core/conv.h \
@@ -107,6 +109,10 @@ endif
noinst_HEADERS = osmocom/core/timer_compat.h
+osmocom/core/bit%gen.h: osmocom/core/bitXXgen.h.tpl
+ $(AM_V_GEN)$(MKDIR_P) $(dir $@)
+ $(AM_V_GEN)sed -e's/XX/$*/g' $< > $@
+
osmocom/core/crc%gen.h: osmocom/core/crcXXgen.h.tpl
$(AM_V_GEN)$(MKDIR_P) $(dir $@)
$(AM_V_GEN)sed -e's/XX/$*/g' $< > $@
diff --git a/include/osmocom/core/bitXXgen.h.tpl b/include/osmocom/core/bitXXgen.h.tpl
new file mode 100644
index 0000000..1deffb9
--- /dev/null
+++ b/include/osmocom/core/bitXXgen.h.tpl
@@ -0,0 +1,86 @@
+/*
+ * 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++);
+}
+
+/* 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++);
+}
+
+
+/* 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..09d163d 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 (24 bits and above) 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/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/tests/bits/bitrev_test.c b/tests/bits/bitrev_test.c
index 5eca990..fc5a811 100644
--- a/tests/bits/bitrev_test.c
+++ b/tests/bits/bitrev_test.c
@@ -1,20 +1,192 @@
-
+#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
+#include <time.h>
+#include <stdbool.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/bits.h>
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 };
+static char s[18];
+
+enum END {LE, BE};
+
+const char * end2str(enum END e) {
+ if (e == LE) return "LE";
+ return "BE";
+}
+
+
+/* convenience wrappers */
+
+inline uint64_t load64(enum END e, const uint8_t *buf, unsigned nbytes) {
+ return (e == BE) ? osmo_load64be_ext(buf, nbytes) : osmo_load64le_ext(buf, nbytes);
+}
+
+inline uint32_t load32(enum END e, const uint8_t *buf, unsigned nbytes) {
+ return (e == BE) ? osmo_load32be_ext(buf, nbytes) : osmo_load32le_ext(buf, nbytes);
+}
+
+inline uint16_t load16(enum END e, const uint8_t *buf) {
+ return (e == BE) ? osmo_load16be(buf) : osmo_load16le(buf);
+}
+
+inline void store64(enum END e, uint64_t t, uint8_t *buf, unsigned nbytes) {
+ (e == BE) ? osmo_store64be_ext(t, buf, nbytes) : osmo_store64le_ext(t, buf, nbytes);
+}
+
+inline void store32(enum END e, uint64_t t, uint8_t *buf, unsigned nbytes) {
+ (e == BE) ? osmo_store32be_ext(t, buf, nbytes) : osmo_store32le_ext(t, buf, nbytes);
+}
+
+inline void store16(enum END e, uint64_t t, uint8_t *buf) {
+ (e == BE) ? osmo_store16be(t, buf) : osmo_store16le(t, buf);
+}
+
+
+/* helper functions */
+
+inline bool printcheck(bool chk, unsigned nbytes, enum END e, bool b)
+{
+ if (!chk) {
+ printf("%u %s FAILED", nbytes * 8, end2str(e));
+ return true;
+ }
+ printf("%u %s OK", nbytes * 8, end2str(e));
+ return b;
+}
+
+inline bool dumpcheck(const char *dump, const char *s, unsigned nbytes, bool chk, enum END e, bool b)
+{
+ bool x = printcheck(chk, nbytes, e, b);
+ if (!dump) return x;
+
+ int m = memcmp(s, dump, nbytes);
+ if (0 == m) {
+ printf(", storage OK");
+ return x;
+ }
+ printf(", [%d]", m);
+
+ return true;
+}
+
+
+/* printcheckXX(): load/store 'test' and check against 'expected' value, compare to 'dump' buffer if given and print if necessary */
+
+inline void printcheck64(enum END e, unsigned nbytes, uint64_t test, uint64_t expected, const char *dump, bool print)
+{
+ uint8_t buf[nbytes];
+
+ store64(e, test, buf, nbytes);
+
+ char *s = osmo_hexdump_nospc(buf, nbytes);
+ uint64_t result = load64(e, buf, nbytes);
+
+ print = dumpcheck(dump, s, nbytes, result == expected, e, print);
+
+ if (print)
+ printf(": buffer %s known buffer %s loaded %.16" PRIx64 " expected %.16" PRIx64, s, dump, result, expected);
+ printf("\n");
+}
+
+inline void printcheck32(enum END e, unsigned nbytes, uint32_t test, uint32_t expected, const char *dump, bool print)
+{
+ uint8_t buf[nbytes];
+
+ store32(e, test, buf, nbytes);
+
+ char *s = osmo_hexdump_nospc(buf, nbytes);
+ uint32_t result = load32(e, buf, nbytes);
+
+ print = dumpcheck(dump, s, nbytes, result == expected, e, print);
+
+ if (print)
+ printf(": buffer %s known buffer %s loaded %.8" PRIx32 " expected %.8" PRIx32, s, dump, result, expected);
+ printf("\n");
+}
+
+inline void printcheck16(enum END e, uint32_t test, uint32_t expected, const char *dump, bool print)
+{
+ uint8_t buf[2];
+
+ store16(e, test, buf);
+
+ char *s = osmo_hexdump_nospc(buf, 2);
+ uint16_t result = load16(e, buf);
+
+ print = dumpcheck(dump, s, 2, result == expected, e, print);
+
+ if (print)
+ printf(": buffer %s known buffer %s loaded %.4" PRIx16 " expected %.4" PRIx16, s, dump, result, expected);
+ printf("\n");
+}
+
+
+/* compute expected value - zero excessive bytes */
+
+inline uint64_t exp64(enum END e, unsigned nbytes, uint64_t value) {
+ uint8_t adj = 64 - nbytes * 8;
+ uint64_t v = value << adj;
+ return (e == LE) ? v >> adj : v;
+}
+
+inline uint32_t exp32(enum END e, unsigned nbytes, uint32_t value) {
+ uint8_t adj = 32 - nbytes * 8;
+ uint32_t v = value << adj;
+ return (e == LE) ? v >> adj : v;
+}
+
+
+/* run actual tests - if 'test' is 0 than generate random test value internally */
+
+inline void check64(uint64_t test, uint64_t expected, unsigned nbytes, enum END e)
+{
+ bool print = true;
+ if (0 == test && 0 == expected) {
+ test = ((uint64_t)rand() << 32) + rand();
+ expected = exp64(e, nbytes, test);
+ print = false;
+ }
+ snprintf(s, 17, "%.16" PRIx64, expected);
+ printcheck64(e, nbytes, test, expected, (BE == e) ? s : NULL, print);
+}
+
+inline void check32(uint32_t test, uint32_t expected, unsigned nbytes, enum END e)
+{
+ bool print = true;
+ if (0 == test && 0 == expected) {
+ test = rand();
+ expected = exp32(e, nbytes, test);
+ print = false;
+ }
+ snprintf(s, 17, "%.8" PRIx32, expected);
+ printcheck32(e, nbytes, test, expected, (BE == e) ? s : NULL, print);
+}
+
+inline void check16(uint16_t test, enum END e)
+{
+ bool print = true;
+ if (0 == test) {
+ test = (uint16_t)rand();
+ print = false;
+ }
+ snprintf(s, 17, "%.4" PRIx16, test);
+ printcheck16(e, test, test, (BE == e) ? s : NULL, print);
+}
+
int main(int argc, char **argv)
{
uint8_t out[ARRAY_SIZE(input)];
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 +204,49 @@ int main(int argc, char **argv)
printf("\n");
}
+ printf("checking byte packing...\n");
+
+ printf("running static tests...\n");
+
+ check64(0xDEADBEEFF00DCAFE, 0xDEADBEEFF00DCAFE, 8, BE);
+ check64(0xDEADBEEFF00DCAFE, 0xADBEEFF00DCAFE00, 7, BE);
+ check64(0xDEADBEEFF00DCAFE, 0xBEEFF00DCAFE0000, 6, BE);
+ check64(0xDEADBEEFF00DCAFE, 0xEFF00DCAFE000000, 5, BE);
+
+ check64(0xDEADBEEFF00DCAFE, 0xDEADBEEFF00DCAFE, 8, LE);
+ check64(0xDEADBEEFF00DCAFE, 0x00ADBEEFF00DCAFE, 7, LE);
+ check64(0xDEADBEEFF00DCAFE, 0x0000BEEFF00DCAFE, 6, LE);
+ check64(0xDEADBEEFF00DCAFE, 0x000000EFF00DCAFE, 5, LE);
+
+ check32(0xBABEFACE, 0xBABEFACE, 4, BE);
+ check32(0xBABEFACE, 0xBEFACE00, 3, BE);
+
+ check32(0xBABEFACE, 0xBABEFACE, 4, LE);
+ check32(0xBABEFACE, 0x00BEFACE, 3, LE);
+
+ check16(0xB00B, BE);
+ check16(0xB00B, LE);
+
+ printf("running random tests...\n");
+
+ check64(0, 0, 8, BE);
+ check64(0, 0, 7, BE);
+ check64(0, 0, 6, BE);
+ check64(0, 0, 5, BE);
+
+ check64(0, 0, 8, LE);
+ check64(0, 0, 7, LE);
+ check64(0, 0, 6, LE);
+ check64(0, 0, 5, LE);
+
+ check32(0, 0, 4, BE);
+ check32(0, 0, 3, BE);
+
+ check32(0, 0, 4, LE);
+ check32(0, 0, 3, LE);
+
+ check16(0, BE);
+ check16(0, LE);
+
return 0;
}
diff --git a/tests/bits/bitrev_test.ok b/tests/bits/bitrev_test.ok
index 47f402f..90cb295 100644
--- a/tests/bits/bitrev_test.ok
+++ b/tests/bits/bitrev_test.ok
@@ -22,3 +22,34 @@ REVERSED: 02 01
INORDER: 80
REVERSED: 01
+checking byte packing...
+running static tests...
+64 BE OK, storage OK: buffer deadbeeff00dcafe known buffer deadbeeff00dcafe loaded deadbeeff00dcafe expected deadbeeff00dcafe
+56 BE OK, storage OK: buffer adbeeff00dcafe known buffer adbeeff00dcafe00 loaded adbeeff00dcafe00 expected adbeeff00dcafe00
+48 BE OK, storage OK: buffer beeff00dcafe known buffer beeff00dcafe0000 loaded beeff00dcafe0000 expected beeff00dcafe0000
+40 BE OK, storage OK: buffer eff00dcafe known buffer eff00dcafe000000 loaded eff00dcafe000000 expected eff00dcafe000000
+64 LE OK: buffer feca0df0efbeadde known buffer (null) loaded deadbeeff00dcafe expected deadbeeff00dcafe
+56 LE OK: buffer feca0df0efbead known buffer (null) loaded 00adbeeff00dcafe expected 00adbeeff00dcafe
+48 LE OK: buffer feca0df0efbe known buffer (null) loaded 0000beeff00dcafe expected 0000beeff00dcafe
+40 LE OK: buffer feca0df0ef known buffer (null) loaded 000000eff00dcafe expected 000000eff00dcafe
+32 BE OK, storage OK: buffer babeface known buffer babeface loaded babeface expected babeface
+24 BE OK, storage OK: buffer beface known buffer beface00 loaded beface00 expected beface00
+32 LE OK: buffer cefabeba known buffer (null) loaded babeface expected babeface
+24 LE OK: buffer cefabe known buffer (null) loaded 00beface expected 00beface
+16 BE OK, storage OK: buffer b00b known buffer b00b loaded b00b expected b00b
+16 LE OK: buffer 0bb0 known buffer (null) loaded b00b expected b00b
+running random tests...
+64 BE OK, storage OK
+56 BE OK, storage OK
+48 BE OK, storage OK
+40 BE OK, storage OK
+64 LE OK
+56 LE OK
+48 LE OK
+40 LE OK
+32 BE OK, storage OK
+24 BE OK, storage OK
+32 LE OK
+24 LE OK
+16 BE OK, storage OK
+16 LE OK
--
1.8.3.2
--------------070304090402030003020005
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.
Attached is a trivial patch which breaks existing GPRS cipher API of libosmocore by
switching from fixed 64-bit length Kc to variable-length.
There are several justifications for that:
- compliance with ETSI TS 155.22 (GEA4 - 128 bits Kc) and all further versions
- similarity to existing auth api (osmocom/crypt/auth.h uses 128 bits as well)
- nobody uses this API anyway (except my other patches with GEA)
- patch breaks nothing within libosmocore (make check succeeds) and openbsc (uses
gea0 only)
That's why I think next libosmocore version should apply this patch and change unused
API before someone actually start using it and makes transition more difficult.
--
best regards,
Max, http://fairwaves.ru
2
7
---
.gitignore | 1 +
include/osmocom/gsm/kasumi.h | 34 ++++++++
src/gsm/Makefile.am | 2 +-
src/gsm/kasumi.c | 191 +++++++++++++++++++++++++++++++++++++++++++
src/gsm/libosmogsm.map | 4 +
tests/Makefile.am | 7 +-
tests/kasumi/kasumi_test.c | 136 ++++++++++++++++++++++++++++++
tests/kasumi/kasumi_test.ok | 10 +++
tests/testsuite.at | 6 ++
9 files changed, 388 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 3fa1bbc..1299028 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,6 +56,7 @@ 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..48573b7
--- /dev/null
+++ b/include/osmocom/gsm/kasumi.h
@@ -0,0 +1,34 @@
+/*
+ * KASUMI header
+ *
+ * See kasumi.c for details
+ * The parameters are described in TS 135 202.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+/*
+ * Single iteration of KASUMI cipher
+*/
+uint64_t _kasumi(uint64_t P, const uint16_t *KLi1, const uint16_t *KLi2, const uint16_t *KOi1, const uint16_t *KOi2, const uint16_t *KOi3, const uint16_t *KIi1, const uint16_t *KIi2, const 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);
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..c2dfa6f
--- /dev/null
+++ b/src/gsm/kasumi.c
@@ -0,0 +1,191 @@
+/* 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>
+
+/* See TS 135 202 for constants and full Kasumi spec. */
+inline static uint16_t kasumi_FI(uint16_t I, uint16_t skey)
+{
+ static const 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 const 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;
+}
+
+inline static uint32_t kasumi_FO(uint32_t I, const uint16_t *KOi1, const uint16_t *KOi2, const uint16_t *KOi3, const uint16_t *KIi1, const uint16_t *KIi2, const 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;
+}
+
+inline static uint32_t kasumi_FL(uint32_t I, const uint16_t *KLi1, const 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, const uint16_t *KLi1, const uint16_t *KLi2, const uint16_t *KOi1, const uint16_t *KOi2, const uint16_t *KOi3, const uint16_t *KIi1, const uint16_t *KIi2, const 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 };
+
+ /* Work with 16 bit subkeys and create prime subkeys */
+ for (i = 0; i < 8; i++)
+ C[i] ^= osmo_load16be(key + i * 2);
+ /* C[] now stores K-prime[] */
+
+ /* Create round-specific subkeys */
+ for (i = 0; i < 8; i++)
+ {
+ 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 9d15d66..3a4a643 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -196,6 +196,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..9101407
--- /dev/null
+++ b/tests/kasumi/kasumi_test.c
@@ -0,0 +1,136 @@
+#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>
+
+/* Test vectors are taken from TS 135 202 */
+
+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);
+ printf(passed ? " OK. " : "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
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 9124f25..7ce2ee8 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -9,6 +9,12 @@ cat $abs_srcdir/a5/a5_test.ok > expout
AT_CHECK([$abs_top_builddir/tests/a5/a5_test], [0], [expout])
AT_CLEANUP
+AT_SETUP([kasumi])
+AT_KEYWORDS([kasumi])
+cat $abs_srcdir/kasumi/kasumi_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/kasumi/kasumi_test], [0], [expout])
+AT_CLEANUP
+
AT_SETUP([bits])
AT_KEYWORDS([bits])
cat $abs_srcdir/bits/bitrev_test.ok > expout
--
1.8.3.2
--------------030704070502020202070204--
1
0
---
.gitignore | 3 +-
include/Makefile.am | 6 ++
include/osmocom/core/bitXXgen.h.tpl | 86 ++++++++++++++++++++++++++++
include/osmocom/core/bits.h | 45 ++++++++++++++-
include/osmocom/core/msgb.h | 23 ++++----
tests/bits/bitrev_test.c | 109 +++++++++++++++++++++++++++++++++++-
tests/bits/bitrev_test.ok | 22 ++++++++
7 files changed, 280 insertions(+), 14 deletions(-)
create mode 100644 include/osmocom/core/bitXXgen.h.tpl
diff --git a/.gitignore b/.gitignore
index 71b27f2..3fa1bbc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,6 +55,7 @@ tests/testsuite
tests/testsuite.dir/
tests/testsuite.log
+tests/utils/utils_test
tests/sms/sms_test
tests/timer/timer_test
tests/msgfile/msgfile_test
@@ -89,7 +90,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/Makefile.am b/include/Makefile.am
index b035906..18011ff 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -2,6 +2,8 @@ nobase_include_HEADERS = \
osmocom/codec/codec.h \
osmocom/core/application.h \
osmocom/core/backtrace.h \
+ osmocom/core/bit32gen.h \
+ osmocom/core/bit64gen.h \
osmocom/core/bits.h \
osmocom/core/bitvec.h \
osmocom/core/conv.h \
@@ -107,6 +109,10 @@ endif
noinst_HEADERS = osmocom/core/timer_compat.h
+osmocom/core/bit%gen.h: osmocom/core/bitXXgen.h.tpl
+ $(AM_V_GEN)$(MKDIR_P) $(dir $@)
+ $(AM_V_GEN)sed -e's/XX/$*/g' $< > $@
+
osmocom/core/crc%gen.h: osmocom/core/crcXXgen.h.tpl
$(AM_V_GEN)$(MKDIR_P) $(dir $@)
$(AM_V_GEN)sed -e's/XX/$*/g' $< > $@
diff --git a/include/osmocom/core/bitXXgen.h.tpl b/include/osmocom/core/bitXXgen.h.tpl
new file mode 100644
index 0000000..1deffb9
--- /dev/null
+++ b/include/osmocom/core/bitXXgen.h.tpl
@@ -0,0 +1,86 @@
+/*
+ * 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++);
+}
+
+/* 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++);
+}
+
+
+/* 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..09d163d 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 (24 bits and above) 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/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/tests/bits/bitrev_test.c b/tests/bits/bitrev_test.c
index 5eca990..fbf4b22 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,79 @@
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 };
+static char s[18], *p;
+
+static void check_ls_64(uint8_t bytes)
+{
+ /* calculate various adjustment constants (number of bits, bytes, octets etc.)
+ based on number of bytes in type we actually test */
+ uint8_t T[bytes], D = (8 - bytes), A = 8 * D, C = 2 * D;
+ /* zero exceeding bytes to avoid polluting test results */
+ uint64_t _test = ((uint64_t)rand() << 32) + rand(), a_test = (_test << A) >> A;
+
+ /* TEST 1: store and compare the result with snprintf serialization (big-endian) */
+ 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);
+
+ /* TEST 2: verify that store/load cycle does not change value (little-endian) */
+ 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);
+
+ /* TEST 3: verify that store/load cycle does not change value (big-endian) */
+ 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));
+}
+
+static void check_ls_32(uint8_t bytes)
+{
+ /* calculate various adjustment constants (number of bits, bytes, octets etc.)
+ based on number of bytes in type we actually test */
+ uint8_t T[bytes], D = (4 - bytes), A = 8 * D, C = 2 * D;
+ /* zero exceeding bytes to avoid polluting test results */
+ uint32_t _test = rand(), a_test = (_test << A) >> A;
+
+ /* TEST 1: store and compare the result with snprintf serialization (big-endian) */
+ 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);
+
+ /* TEST 2: verify that store/load cycle does not change value (little-endian) */
+ 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);
+
+ /* TEST 3: verify that store/load cycle does not change value (big-endian) */
+ 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 +101,41 @@ 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);
+
+ /* TEST 1: store and compare the result with snprintf serialization (big-endian) */
+ 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");
+
+ /* TEST 2: verify that store/load cycle does not change value (little-endian) */
+ 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);
+
+ /* TEST 3: verify that store/load cycle does not change value (big-endian) */
+ 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
--------------030704070502020202070204
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
---
.gitignore | 1 +
include/osmocom/gsm/kasumi.h | 33 ++++++++
src/gsm/Makefile.am | 2 +-
src/gsm/kasumi.c | 190 +++++++++++++++++++++++++++++++++++++++++++
src/gsm/libosmogsm.map | 4 +
tests/Makefile.am | 7 +-
tests/kasumi/kasumi_test.c | 130 +++++++++++++++++++++++++++++
tests/kasumi/kasumi_test.ok | 10 +++
tests/testsuite.at | 6 ++
9 files changed, 380 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 3fa1bbc..1299028 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,6 +56,7 @@ 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..d0d07c7
--- /dev/null
+++ b/include/osmocom/gsm/kasumi.h
@@ -0,0 +1,33 @@
+/*
+ * KASUMI header
+ *
+ * See kasumi.c for details
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+/*
+ * Single iteration of KASUMI cipher
+*/
+uint64_t _kasumi(uint64_t P, const uint16_t *KLi1, const uint16_t *KLi2, const uint16_t *KOi1, const uint16_t *KOi2, const uint16_t *KOi3, const uint16_t *KIi1, const uint16_t *KIi2, const 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);
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..dfecb4e
--- /dev/null
+++ b/src/gsm/kasumi.c
@@ -0,0 +1,190 @@
+/* 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>
+
+inline static uint16_t _kasumi_FI(uint16_t I, uint16_t skey)
+{
+ static const 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 const 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;
+}
+
+inline static uint32_t _kasumi_FO(uint32_t I, const uint16_t *KOi1, const uint16_t *KOi2, const uint16_t *KOi3, const uint16_t *KIi1, const uint16_t *KIi2, const 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;
+}
+
+inline static uint32_t _kasumi_FL(uint32_t I, const uint16_t *KLi1, const 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, const uint16_t *KLi1, const uint16_t *KLi2, const uint16_t *KOi1, const uint16_t *KOi2, const uint16_t *KOi3, const uint16_t *KIi1, const uint16_t *KIi2, const 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 };
+
+ /* Work with 16 bit subkeys and create prime subkeys */
+ for (i = 0; i < 8; i++)
+ C[i] ^= osmo_load16be(key + i * 2);
+ /* C[] now stores K-prime[] */
+
+ /* Create round-specific subkeys */
+ for (i = 0; i < 8; i++)
+ {
+ 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 9d15d66..3a4a643 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -196,6 +196,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..d8b3c70
--- /dev/null
+++ b/tests/kasumi/kasumi_test.c
@@ -0,0 +1,130 @@
+#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>
+
+
+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
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 9124f25..7ce2ee8 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -9,6 +9,12 @@ cat $abs_srcdir/a5/a5_test.ok > expout
AT_CHECK([$abs_top_builddir/tests/a5/a5_test], [0], [expout])
AT_CLEANUP
+AT_SETUP([kasumi])
+AT_KEYWORDS([kasumi])
+cat $abs_srcdir/kasumi/kasumi_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/kasumi/kasumi_test], [0], [expout])
+AT_CLEANUP
+
AT_SETUP([bits])
AT_KEYWORDS([bits])
cat $abs_srcdir/bits/bitrev_test.ok > expout
--
1.8.3.2
--------------020709010205080901010203--
1
0
---
.gitignore | 3 +-
include/Makefile.am | 6 ++
include/osmocom/core/bitXXgen.h.tpl | 86 +++++++++++++++++++++++++++++
include/osmocom/core/bits.h | 45 ++++++++++++++-
include/osmocom/core/msgb.h | 23 ++++----
tests/bits/bitrev_test.c | 107 ++++++++++++++++++++++++++++++++++--
tests/bits/bitrev_test.ok | 22 ++++++++
7 files changed, 276 insertions(+), 16 deletions(-)
create mode 100644 include/osmocom/core/bitXXgen.h.tpl
diff --git a/.gitignore b/.gitignore
index 71b27f2..3fa1bbc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,6 +55,7 @@ tests/testsuite
tests/testsuite.dir/
tests/testsuite.log
+tests/utils/utils_test
tests/sms/sms_test
tests/timer/timer_test
tests/msgfile/msgfile_test
@@ -89,7 +90,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/Makefile.am b/include/Makefile.am
index b035906..18011ff 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -2,6 +2,8 @@ nobase_include_HEADERS = \
osmocom/codec/codec.h \
osmocom/core/application.h \
osmocom/core/backtrace.h \
+ osmocom/core/bit32gen.h \
+ osmocom/core/bit64gen.h \
osmocom/core/bits.h \
osmocom/core/bitvec.h \
osmocom/core/conv.h \
@@ -107,6 +109,10 @@ endif
noinst_HEADERS = osmocom/core/timer_compat.h
+osmocom/core/bit%gen.h: osmocom/core/bitXXgen.h.tpl
+ $(AM_V_GEN)$(MKDIR_P) $(dir $@)
+ $(AM_V_GEN)sed -e's/XX/$*/g' $< > $@
+
osmocom/core/crc%gen.h: osmocom/core/crcXXgen.h.tpl
$(AM_V_GEN)$(MKDIR_P) $(dir $@)
$(AM_V_GEN)sed -e's/XX/$*/g' $< > $@
diff --git a/include/osmocom/core/bitXXgen.h.tpl b/include/osmocom/core/bitXXgen.h.tpl
new file mode 100644
index 0000000..1deffb9
--- /dev/null
+++ b/include/osmocom/core/bitXXgen.h.tpl
@@ -0,0 +1,86 @@
+/*
+ * 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++);
+}
+
+/* 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++);
+}
+
+
+/* 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..09d163d 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 (24 bits and above) 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/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/tests/bits/bitrev_test.c b/tests/bits/bitrev_test.c
index 5eca990..9d5882c 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,12 +11,75 @@
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 };
+static char s[18], *p;
+
+static void check_ls_64(uint8_t bytes)
+{
+ /* calculate various adjustment constants (number of bits, bytes, octets etc.)
+ based on number of bytes in type we actually test */
+ uint8_t T[bytes], D = (8 - bytes), A = 8 * D, C = 2 * D;
+ /* zero exceeding bytes to avoid polluting test results */
+ 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));
+}
+
+static void check_ls_32(uint8_t bytes)
+{
+ /* calculate various adjustment constants (number of bits, bytes, octets etc.)
+ based on number of bytes in type we actually test */
+ uint8_t T[bytes], D = (4 - bytes), A = 8 * D, C = 2 * D;
+ /* zero exceeding bytes to avoid polluting test results */
+ 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;
- for (offs = 0; offs < sizeof(out); offs++) {
+ srand(time(NULL));
+
+ for (offs = 0; offs < sizeof(out); offs++)
+ {
uint8_t *start = out + offs;
uint8_t len = sizeof(out) - offs;
@@ -24,7 +88,8 @@ int main(int argc, char **argv)
printf("INORDER: %s\n", osmo_hexdump(start, len));
osmo_revbytebits_buf(start, len);
printf("REVERSED: %s\n", osmo_hexdump(start, len));
- if (memcmp(start, exp_out + offs, len)) {
+ if (memcmp(start, exp_out + offs, len))
+ {
printf("EXPECTED: %s\n", osmo_hexdump(exp_out+offs, len));
fprintf(stderr, "REVERSED != EXPECTED!\n");
exit(1);
@@ -32,5 +97,39 @@ 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
--------------020709010205080901010203
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
Hi,
we are students at Munich university and we trying to get GEA3 running
on openbsc in nitb mode. GSM and GPRS are working, also authentication
(+ GSM A5/1 encryption) and libosmo-crypt-a53 is installed, but we
didn't get the plugin running (It's loaded, but we think it isn't
registered). In the IRC Channel we got the information that it's
actually not fully implemented and should ask here.
Has anyone got GEA3 working in openbsc with real phones?
Thanks for your time and help.
With best regards,
Alexander and Stoffl
(We use the SymoSIM-GR1 SIMs and nanoBTSs 165g)
2
2
Hello,
I'm new with Osmocom.
I have a question.
Can I make phone calls using IMSI instead traditional phone number? Is Osmocom have function to do this?
If not - is it somehow possible to call somebody using IMSI?
Thank you for the answer.
Regards
Sebastian
4
5
Hi all,
I have been experimenting for a while now with the EMI firmware. My goal is creating a controlled interference for an experiment.
My current setup is the following:
- one osmo phone with the EMI firmware transmitting on a single time slot
- one USRP2 at the receiving side
I use GNURadio for sampling and Matlab for post-processing.
My problem is that once I analyse the received bursts in Matlab I am not able to decode its content. I expect to see the same sequence repeated over time since Dummy Burst are being transmitted as detailed in the wiki. However, this is not the case.
After going through the code I am not sure how the transmitted sequence is generated, neither the cyphering sequence used.
Could you help me with these issues?
Thanks,
Enrique
1
0
Osmocom/GSM hacking local groups in places other than Germany
by msokolov@ivan.Harhan.ORG 25 Feb '14
by msokolov@ivan.Harhan.ORG 25 Feb '14
25 Feb '14
dexter <zero-kelvin(a)gmx.de> wrote:
> It's time Again!
> This is the announcement for the next Osmocom Berlin meeting.
> Tomorrow, 8pm @ CCC Berlin, Marienstr. 11, 10117 Berlin
Are there any Osmocom/GSM/etc hackers in California, USA, anywhere
around Los Angeles or San Diego? Perhaps we can have our own local
meetings too, like the Berliners do? If there is any interest, I
would be happy to host.
VLR,
SF
2
1