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
---
src/sim/Makefile.am | 4 +-
src/sim/reader_sap.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/sim/reader_sap.h | 162 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 346 insertions(+), 2 deletions(-)
create mode 100644 src/sim/reader_sap.c
create mode 100644 src/sim/reader_sap.h
diff --git a/src/sim/Makefile.am b/src/sim/Makefile.am
index fe64278..2fd353a 100644
--- a/src/sim/Makefile.am
+++ b/src/sim/Makefile.am
@@ -9,11 +9,11 @@ AM_LDFLAGS = $(COVERAGE_LDFLAGS)
if ENABLE_PCSC
# FIXME: only build the PC/SC dependent part conditional, but always build other parts
-noinst_HEADERS = sim_int.h gsm_int.h
+noinst_HEADERS = sim_int.h gsm_int.h reader_sap.h
lib_LTLIBRARIES = libosmosim.la
-libosmosim_la_SOURCES = core.c card_fs_sim.c card_fs_usim.c card_fs_uicc.c reader.c reader_pcsc.c
+libosmosim_la_SOURCES = core.c card_fs_sim.c card_fs_usim.c card_fs_uicc.c reader.c reader_pcsc.c reader_sap.c
libosmosim_la_LDFLAGS = -version-info $(LIBVERSION)
libosmosim_la_LIBADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(PCSC_LIBS)
diff --git a/src/sim/reader_sap.c b/src/sim/reader_sap.c
new file mode 100644
index 0000000..0a74809
--- /dev/null
+++ b/src/sim/reader_sap.c
@@ -0,0 +1,182 @@
+/* SAP card reader backend for libosmosim */
+/*
+ * (C) 2013 by Max <Max.Suraev(a)fairwaves.ru>
+ *
+ * code shamelessly ripped from Nico Golde's patches to osmocom-bb
+ *
+ * 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 <unistd.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+
+#include <osmocom/core/talloc.h>
+#include <osmocom/sim/sim.h>
+
+#include "sim_int.h"
+#include "reader_sap.h"
+
+static int osim_sap_send(struct osim_sap_entity *st, struct msgb *msg)
+{
+ if(st->sap_state == SAP_NOT_CONNECTED && !st->sap_state == SAP_CONNECTION_UNDER_NEGOTIATION)
+ sap_connect(st);
+
+ if (st->fd <= 0)
+ return -EINVAL;
+/* FIXME:
+ if (write_queue_enqueue(&ms->sap_wq, msg) != 0) {
+ LOGP(DSAP, LOGL_ERROR, "Failed to enqueue msg.\n");
+ msgb_free(msg);
+ return -1;
+ }
+*/
+ return 0;
+}
+
+static struct msgb *sap_create_msg(uint8_t id, uint8_t num_params, struct sap_param *params)
+{
+ struct msgb *msg;
+ uint8_t *msgp;
+ uint8_t i, plen, padding = 0;
+
+ msg = msgb_alloc(GSM_SAP_LENGTH, "osmosap");
+ if (!msg) {
+ fprintf(stderr, "Failed to allocate msg.\n");
+ return NULL;
+ }
+
+ /* BTSAP 5.1 */
+ msgb_put_u8(msg, id);
+ msgb_put_u8(msg, num_params);
+ msgb_put_u16(msg, 0);
+
+ for(i = 0; i < num_params; i++){
+ plen = params[i].len;
+ msgb_put_u8(msg, params[i].id);
+ msgb_put_u8(msg, 0);
+ msgb_put_u16(msg, plen);
+ if(plen % 4){
+ padding = 4 - (plen % 4);
+ }
+ msgp = msgb_put(msg, plen + padding);
+ memcpy(msgp, params[i].value, plen);
+
+ if(padding){
+ memset(msgp + plen, 0, padding);
+ }
+ }
+
+ return msg;
+}
+
+static void sap_connect(struct osim_sap_entity *st)
+{
+ uint8_t buffer[3];
+ struct msgb *msg;
+ uint16_t size = st->max_msg_size;
+ struct sap_param params[1];
+
+ params[0].id = SAP_MAX_MSG_SIZE;
+ params[0].len = 2;
+
+ if(st->sap_state != SAP_NOT_CONNECTED) {
+ fprintf(stderr, "Attempting to connect while there is an active connection already.\n");
+ return;
+ }
+
+ buffer[0] = (size >> 8) & 0xFF;
+ buffer[1] = size & 0xFF;
+ buffer[2] = 0;
+ params[0].value = buffer;
+
+ msg = sap_create_msg(SAP_CONNECT_REQ, 1, params);
+ if(!msg)
+ return;
+
+ osim_sap_send(st, msg);
+
+ st->sap_state = SAP_CONNECTION_UNDER_NEGOTIATION;
+}
+
+static struct osim_reader_hdl *sap_reader_open(int num, const char *id, void *ctx)
+{
+ struct osim_reader_hdl *rh;
+ ssize_t rc;
+ struct sockaddr_un local;
+ struct osim_sap_entity *st;
+
+ rh = talloc_zero(ctx, struct osim_reader_hdl);
+ st = rh->priv = talloc_zero(rh, struct osim_sap_entity);
+
+ st->fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (st->fd < 0) {
+ fprintf(stderr, "Failed to create unix domain socket: %d\n", st->fd);
+ return NULL;
+ }
+
+ local.sun_family = AF_UNIX;
+ strncpy(local.sun_path, id, sizeof(local.sun_path));
+ local.sun_path[sizeof(local.sun_path) - 1] = '\0';
+
+ rc = connect(st->fd, (struct sockaddr *) &local, sizeof(local));
+ if (rc < 0) {
+ fprintf(stderr, "Failed to connect to '%s'\n", local.sun_path);
+ close(st->fd);
+ return NULL;
+ }
+ st->socket_path = strdup(id);
+/* FIXME:
+ write_queue_init(&ms->sap_wq, 100);
+ ms->sap_wq.bfd.data = ms;
+ ms->sap_wq.bfd.when = BSC_FD_READ;
+ ms->sap_wq.read_cb = sap_read;
+ ms->sap_wq.write_cb = sap_write;
+
+ rc = bsc_register_fd(&ms->sap_wq.bfd);
+ if (rc != 0) {
+ fprintf(stderr, "Failed to register fd.\n");
+ return rc;
+ }
+*/
+ sap_connect(st);
+
+ return rh;
+}
+
+static struct osim_card_hdl *sap_card_open(struct osim_reader_hdl *rh)
+{
+
+}
+
+static int sap_transceive(struct osim_reader_hdl *rh, struct msgb *msg)
+{
+
+}
+
+const struct osim_reader_ops sap_reader_ops = {
+ .name = "SAP",
+ .reader_open = sap_reader_open,
+ .card_open = sap_card_open,
+ .transceive = sap_transceive,
+};
diff --git a/src/sim/reader_sap.h b/src/sim/reader_sap.h
new file mode 100644
index 0000000..a4161b1
--- /dev/null
+++ b/src/sim/reader_sap.h
@@ -0,0 +1,162 @@
+/* SAP card reader backend for libosmosim */
+/*
+ * (C) 2013 by Max <Max.Suraev(a)fairwaves.ru>
+ *
+ * code shamelessly ripped from Nico Golde's patches to osmocom-bb
+ *
+ * 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.
+ *
+ */
+
+#define GSM_SAP_LENGTH 300
+#define GSM_SAP_HEADROOM 32
+
+enum osim_sap_state {
+ SAP_NOT_CONNECTED,
+ SAP_IDLE,
+ SAP_CONNECTION_UNDER_NEGOTIATION,
+ SAP_PROCESSING_ATR_REQUEST,
+ SAP_PROCESSING_APDU_REQUEST
+};
+
+/* BTSAP 1.13 */
+enum osim_sap_msg_type {
+ SAP_CONNECT_REQ = 0x00,
+ SAP_CONNECT_RESP = 0x01,
+ SAP_DISCONNECT_REQ = 0x02,
+ SAP_DISCONNECT_RESP = 0x03,
+ SAP_DISCONNECT_IND = 0x04,
+ SAP_TRANSFER_APDU_REQ = 0x05,
+ SAP_TRANSFER_APDU_RESP = 0x06,
+ SAP_TRANSFER_ATR_REQ = 0x07,
+ SAP_TRANSFER_ATR_RESP = 0x08,
+ SAP_POWER_SIM_OFF_REQ = 0x09,
+ SAP_POWER_SIM_OFF_RESP = 0x0A,
+ SAP_POWER_SIM_ON_REQ = 0x0B,
+ SAP_POWER_SIM_ON_RESP = 0x0C,
+ SAP_RESET_SIM_REQ = 0x0D,
+ SAP_RESET_SIM_RESP = 0x0E,
+ SAP_TRANSFER_CARD_READER_STATUS_REQ = 0x0F,
+ SAP_TRANSFER_CARD_READER_STATUS_RESP = 0x10,
+ SAP_STATUS_IND = 0x11,
+ SAP_ERROR_RESP = 0x12,
+ SAP_SET_TRANSPORT_PROTOCOL_REQ = 0x13,
+ SAP_SET_TRANSPORT_PROTOCOL_RESP = 0x14
+};
+
+/* BTSAP 5.2 */
+enum osim_sap_param_type {
+ SAP_MAX_MSG_SIZE = 0x00,
+ SAP_CONNECTION_STATUS = 0x01,
+ SAP_RESULT_CODE = 0x02,
+ SAP_DISCONNECTION_TYPE = 0x03,
+ SAP_COMMAND_APDU = 0x04,
+ SAP_COMMAND_APDU_7816 = 0x10,
+ SAP_RESPONSE_APDU = 0x05,
+ SAP_ATR = 0x06,
+ SAP_CARD_READER_STATUS = 0x07,
+ SAP_STATUS_CHANGE = 0x08,
+ SAP_TRANSPORT_PROTOCOL = 0x09
+};
+
+struct sap_param {
+ uint8_t id;
+ uint16_t len;
+ uint8_t *value;
+};
+
+struct sap_msg {
+ uint8_t id;
+ uint8_t num_params;
+ struct sap_param *params;
+};
+
+struct osim_sap_entity {
+ int fd;
+ uint8_t sap_state;
+ uint16_t max_msg_size;
+ char * socket_path;
+};
+
+static const struct value_string sap_param_names[] = {
+ {SAP_MAX_MSG_SIZE, "MaxMsgSize"},
+ {SAP_CONNECTION_STATUS, "ConnectionStatus"},
+ {SAP_RESULT_CODE, "ResultCode"},
+ {SAP_DISCONNECTION_TYPE, "DisconnectionType"},
+ {SAP_COMMAND_APDU, "CommandAPDU"},
+ {SAP_COMMAND_APDU_7816, "CommandAPDU7816"},
+ {SAP_RESPONSE_APDU, "ResponseAPDU"},
+ {SAP_ATR, "ATR"},
+ {SAP_CARD_READER_STATUS, "CardReaderStatus"},
+ {SAP_STATUS_CHANGE, "StatusChange"},
+ {SAP_TRANSPORT_PROTOCOL, "TransportProtocol"}
+};
+
+static const struct value_string sap_msg_names[] = {
+ {SAP_CONNECT_REQ, "CONNECT_REQ"},
+ {SAP_CONNECT_RESP, "CONNECT_RESP"},
+ {SAP_DISCONNECT_REQ, "DISCONNECT_REQ"},
+ {SAP_DISCONNECT_RESP, "DISCONNECT_RESP"},
+ {SAP_DISCONNECT_IND, "DISCONNECT_IND"},
+ {SAP_TRANSFER_APDU_REQ, "TRANSFER_APDU_REQ"},
+ {SAP_TRANSFER_APDU_RESP, "TRANSFER_APDU_RESP"},
+ {SAP_TRANSFER_ATR_REQ, "TRANSFER_ATR_REQ"},
+ {SAP_TRANSFER_ATR_RESP, "TRANSFER_ATR_RESP"},
+ {SAP_POWER_SIM_OFF_REQ, "POWER_SIM_OFF_REQ"},
+ {SAP_POWER_SIM_OFF_RESP, "POWER_SIM_OFF_RESP"},
+ {SAP_POWER_SIM_ON_REQ, "POWER_SIM_ON_REQ"},
+ {SAP_POWER_SIM_ON_RESP, "POWER_SIM_ON_RESP"},
+ {SAP_RESET_SIM_REQ, "RESET_SIM_REQ"},
+ {SAP_RESET_SIM_RESP, "RESET_SIM_RESP"},
+ {SAP_TRANSFER_CARD_READER_STATUS_REQ, "TRANSFER_CARD_READER_STATUS_REQ"},
+ {SAP_TRANSFER_CARD_READER_STATUS_RESP, "TRANSFER_CARD_READER_STATUS_RESP"},
+ {SAP_STATUS_IND, "STATUS_IND"},
+ {SAP_ERROR_RESP, "ERROR_RESP"},
+ {SAP_SET_TRANSPORT_PROTOCOL_REQ, "SET_TRANSPORT_PROTOCOL_REQ"},
+ {SAP_SET_TRANSPORT_PROTOCOL_RESP, "SET_TRANSPORT_PROTOCOL_RESP"}
+};
+
+/* BTSAP table 5.18 */
+static const struct value_string sap_result_names[] = {
+ {0, "OK, request processed correctly"},
+ {1, "Error, no reason defined"},
+ {2, "Error, card not accessible"},
+ {3, "Error, card (already) powered off"},
+ {4, "Error, card removed"},
+ {5, "Error, card already powered on"},
+ {6, "Error, data not available"},
+ {7, "Error, not supported"}
+};
+
+static const struct value_string sap_status_change_names[] = {
+ {0, "Unknown Error"},
+ {1, "Card reset"},
+ {2, "Card not accessible"},
+ {3, "Card removed"},
+ {4, "Card inserted"},
+ {5, "Card recovered"},
+};
+
+static const struct value_string sap_status_names[] = {
+ {0, "OK, Server can fulfill requirements"},
+ {1, "Error, Server unable to establish connection"},
+ {2, "Error, Server does not support maximum message size"},
+ {3, "Error, maximum message size by Client is too small"},
+ {4, "OK, ongoing call"}
+};
+
+static void sap_connect(struct osim_sap_entity *st);
--
1.7.10.4
--------------030201080608040809010804--
1
0
Hello.
Attached is A5/3,4 GEA3,4 implementation which was described today at OsmoDevCon.
This is "from the scratch" implementation, tests using test vectors from relevant
3GPP standards are included.
There are couple of bits missing:
* gprs_auth API needs to be changed to use GEA4 with 128 bits key
* gea_test only checks algorithm correctness but not loading/using it via gprs_auth
plugin api
* osmo_a5_1 and osmo_a5_2 probably should be hidden from public api - the only way to
call them should be through osmo_a5() function
Please review and merge if possible.
--
best regards,
Max, http://fairwaves.ru
4
12
---
include/osmocom/gsm/gsm_utils.h | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/include/osmocom/gsm/gsm_utils.h b/include/osmocom/gsm/gsm_utils.h
index cdbac87..9c3ec19 100644
--- a/include/osmocom/gsm/gsm_utils.h
+++ b/include/osmocom/gsm/gsm_utils.h
@@ -26,6 +26,7 @@
#define GSM_UTILS_H
#include <stdint.h>
+#include <stdlib.h>
#define ADD_MODULO(sum, delta, modulo) do { \
if ((sum += delta) >= modulo) \
@@ -74,17 +75,36 @@ int rxlev2dbm(uint8_t rxlev);
uint8_t dbm2rxlev(int dbm);
/* According to GSM 04.08 Chapter 10.5.1.6 */
-static inline int ms_cm2_a5n_support(uint8_t *cm2, int n) {
+static inline int ms_cm2_a5n_support(uint8_t *cm2, unsigned n) {
switch (n) {
case 0: return 1;
case 1: return (cm2[0] & (1<<3)) ? 0 : 1;
case 2: return (cm2[2] & (1<<0)) ? 1 : 0;
case 3: return (cm2[2] & (1<<1)) ? 1 : 0;
default:
- return 0;
+ return (n > 7) ? 0 : -1;
}
}
+/* According to GSM 04.08 Chapter 10.5.1.7 */
+static inline int ms_cm3_a5n_support(uint8_t *cm3, unsigned n) {
+ switch (n) {
+ case 4: return (cm3[0] & (1<<0)) ? 1 : 0;
+ case 5: return (cm3[0] & (1<<1)) ? 1 : 0;
+ case 6: return (cm3[0] & (1<<2)) ? 1 : 0;
+ case 7: return (cm3[0] & (1<<3)) ? 1 : 0;
+ default:
+ return (n > 7) ? 0 : -1;
+ }
+}
+
+/* Either classmark could be NULL */
+static inline int ms_a5n_support(uint8_t *cm2, uint8_t *cm3, unsigned n) {
+ if ((NULL != cm3) && n > 3) return ms_cm3_a5n_support(cm3, n);
+ if ((NULL != cm2) && n < 4) return ms_cm2_a5n_support(cm2, n);
+ return 0;
+}
+
/* According to GSM 04.08 Chapter 10.5.2.29 */
static inline int rach_max_trans_val2raw(int val) { return (val >> 1) & 3; }
static inline int rach_max_trans_raw2val(int raw) {
--
1.7.10.4
--------------080107010001070606070100--
1
0
---
.gitignore | 5 ++++-
include/Makefile.am | 2 ++
src/gsm/Makefile.am | 4 ++--
src/gsm/libosmogsm.map | 7 +++++++
tests/Makefile.am | 11 +++++++++--
tests/testsuite.at | 12 ++++++++++++
6 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/.gitignore b/.gitignore
index 2ed0144..e522b0d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -40,6 +40,8 @@ debian/tmp/
debian/libosmocore*.substvars
debian/libosmocore/
debian/libosmocore.post*.debhelper
+debian/libosmocore-dbg/
+debian/libosmocore-utils/
.tarball-version
.version
@@ -53,7 +55,8 @@ tests/package.m4
tests/testsuite
tests/testsuite.dir/
tests/testsuite.log
-
+tests/kasumi/kasumi_test
+teste/gea/gea_test
tests/sms/sms_test
tests/timer/timer_test
tests/msgfile/msgfile_test
diff --git a/include/Makefile.am b/include/Makefile.am
index b94abec..83ff9f1 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -40,6 +40,8 @@ nobase_include_HEADERS = \
osmocom/gprs/protocol/gsm_08_16.h \
osmocom/gprs/protocol/gsm_08_18.h \
osmocom/gsm/a5.h \
+ osmocom/gsm/gea.h \
+ osmocom/gsm/kasumi.h \
osmocom/gsm/abis_nm.h \
osmocom/gsm/comp128.h \
osmocom/gsm/gan.h \
diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am
index 59d4234..e203429 100644
--- a/src/gsm/Makefile.am
+++ b/src/gsm/Makefile.am
@@ -11,11 +11,11 @@ noinst_HEADERS = milenage/aes.h milenage/aes_i.h milenage/aes_wrap.h \
lib_LTLIBRARIES = libosmogsm.la
-libosmogsm_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c gsm_utils.c \
+libosmogsm_la_SOURCES = a5.c kasumi.c rxlev_stat.c tlv_parser.c comp128.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 gea.c \
auth_core.c auth_comp128v1.c auth_milenage.c \
milenage/aes-encblock.c milenage/aes-internal.c \
milenage/aes-internal-enc.c milenage/milenage.c gan.c
diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map
index b2278f1..c5ee6f5 100644
--- a/src/gsm/libosmogsm.map
+++ b/src/gsm/libosmogsm.map
@@ -188,6 +188,13 @@ osmo_a5;
osmo_a5_1;
osmo_a5_2;
+_kasumi;
+_kasumi_key_expand;
+_kasumi_kgcore;
+
+osmo_gea3;
+osmo_gea4;
+
osmo_auth_alg_name;
osmo_auth_alg_parse;
osmo_auth_gen_vec;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index bc9b7de..a2de833 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -5,7 +5,8 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test \
conv/conv_test auth/milenage_test lapd/lapd_test \
gsm0808/gsm0808_test gsm0408/gsm0408_test \
gb/bssgp_fc_test logging/logging_test fr/fr_test \
- loggingrb/loggingrb_test strrb/strrb_test
+ loggingrb/loggingrb_test strrb/strrb_test \
+ kasumi/kasumi_test gea/gea_test
if ENABLE_MSGFILE
check_PROGRAMS += msgfile/msgfile_test
@@ -17,6 +18,12 @@ a5_a5_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/li
auth_milenage_test_SOURCES = auth/milenage_test.c
auth_milenage_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
+
+gea_gea_test_SOURCES = gea/gea_test.c
+gea_gea_test_LDADD = $(top_builddir)/src/libosmocore.la $(top_builddir)/src/gsm/libosmogsm.la
+
bits_bitrev_test_SOURCES = bits/bitrev_test.c
bits_bitrev_test_LDADD = $(top_builddir)/src/libosmocore.la
@@ -91,7 +98,7 @@ EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE) \
msgfile/msgfile_test.ok msgfile/msgconfig.cfg \
logging/logging_test.ok logging/logging_test.err \
fr/fr_test.ok loggingrb/logging_test.ok \
- loggingrb/logging_test.err strrb/strrb_test.ok
+ loggingrb/logging_test.err strrb/strrb_test.ok kasumi/kasumi_test.ok
DISTCLEANFILES = atconfig
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 684ec4f..5323096 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -28,6 +28,18 @@ cat $abs_srcdir/conv/conv_test.ok > expout
AT_CHECK([$abs_top_builddir/tests/conv/conv_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([gea])
+AT_KEYWORDS([gea])
+cat $abs_srcdir/gea/gea_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/gea/gea_test], [0], [expout])
+AT_CLEANUP
+
if ENABLE_MSGFILE
AT_SETUP([msgfile])
AT_KEYWORDS([msgfile])
--
1.7.10.4
--------------060001040407040305040404--
1
0
---
include/osmocom/gsm/a5.h | 3 +++
src/gsm/a5.c | 58 +++++++++++++++++++++++++++++++++++++++++--
tests/a5/a5_test.c | 62 ++++++++++++++++++++++++++++++++++------------
tests/a5/a5_test.ok | 24 ++++++++++++++++++
4 files changed, 129 insertions(+), 18 deletions(-)
diff --git a/include/osmocom/gsm/a5.h b/include/osmocom/gsm/a5.h
index 2f78a92..2089404 100644
--- a/include/osmocom/gsm/a5.h
+++ b/include/osmocom/gsm/a5.h
@@ -24,6 +24,7 @@
#define __OSMO_A5_H__
#include <stdint.h>
+#include <stdbool.h>
#include <osmocom/core/bits.h>
@@ -57,6 +58,8 @@ osmo_a5_fn_count(uint32_t fn)
int osmo_a5(int n, const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul);
void osmo_a5_1(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul);
void osmo_a5_2(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul);
+void osmo_a5_3(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul);
+void osmo_a5_4(const uint8_t *ck, uint32_t fn, ubit_t *dl, ubit_t *ul);
/*! @} */
diff --git a/src/gsm/a5.c b/src/gsm/a5.c
index de821e8..314473f 100644
--- a/src/gsm/a5.c
+++ b/src/gsm/a5.c
@@ -34,10 +34,14 @@
* \brief Osmocom GSM A5 ciphering algorithm implementation
*/
+#include <stdio.h>
#include <errno.h>
#include <string.h>
+#include <stdbool.h>
+#include <osmocom/core/bits.h>
#include <osmocom/gsm/a5.h>
+#include <osmocom/gsm/kasumi.h>
/*! \brief Main method to generate a A5/x cipher stream
* \param[in] n Which A5/x method to use
@@ -47,7 +51,7 @@
* \param[out] ul Pointer to array of ubits to return Uplink cipher stream
* \returns 0 for success, -ENOTSUP for invalid cipher selection.
*
- * Currently A5/[0-2] are supported.
+ * Currently A5/[0-4] are supported: -ENOTSUP returned in this case, 0 returned for supported ciphers.
* Either (or both) of dl/ul can be NULL if not needed.
*/
int
@@ -70,8 +74,15 @@ osmo_a5(int n, const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
osmo_a5_2(key, fn, dl, ul);
break;
+ case 3:
+ osmo_a5_3(key, fn, dl, ul);
+ break;
+ case 4:
+ osmo_a5_4(key, fn, dl, ul);
+ break;
+
default:
- /* a5/[3..7] not supported here/yet */
+ /* a5/[5..7] not supported here/yet */
return -ENOTSUP;
}
@@ -368,4 +379,47 @@ osmo_a5_2(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
}
}
+/* ------------------------------------------------------------------------ */
+/* A5/3 */
+/* ------------------------------------------------------------------------ */
+
+/*! \brief Generate a GSM A5/3 cipher stream
+ * \param[in] key 8 byte array for the key (as received from the SIM)
+ * \param[in] fn Frame number
+ * \param[out] dl Pointer to array of ubits to return Downlink cipher stream
+ * \param[out] ul Pointer to array of ubits to return Uplink cipher stream
+ *
+ * Either (or both) of dl/ul should be NULL if not needed.
+ *
+ * Implementation based on specifications from 3GPP TS 55.216, 3GPP TR 55.919 and ETSI TS 135 202
+ * with slight simplifications (CE hardcoded to 0).
+ */
+void
+osmo_a5_3(const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
+{
+ /* internal function require 128 bit key so we expand by concatenating supplied 64 bit key */
+ uint8_t ck[16];
+ memcpy(ck, key, 8);
+ memcpy(ck + 8, key, 8);
+
+ osmo_a5_4(ck, fn, dl, ul);
+}
+
+void
+osmo_a5_4(const uint8_t *ck, uint32_t fn, ubit_t *dl, ubit_t *ul)
+{
+ uint8_t i, gamma[32];
+
+ if (ul) {
+ _kasumi_kgcore(0xF, 0, fn, 0, ck, gamma, 228);
+ uint8_t uplink[15];
+ for(i = 0; i < 15; i++) uplink[i] = (gamma[i + 14] << 2) + (gamma[i + 15] >> 6);
+ osmo_pbit2ubit(ul, uplink, 114);
+ }
+ if (dl) {
+ _kasumi_kgcore(0xF, 0, fn, 0, ck, gamma, 114);
+ osmo_pbit2ubit(dl, gamma, 114);
+ }
+}
+
/*! @} */
diff --git a/tests/a5/a5_test.c b/tests/a5/a5_test.c
index 14436f1..c0ed658 100644
--- a/tests/a5/a5_test.c
+++ b/tests/a5/a5_test.c
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
+#include <stdbool.h>
#include <osmocom/core/bits.h>
#include <osmocom/core/utils.h>
@@ -36,25 +37,40 @@ static const uint8_t ul[] = {
0x80, 0xba, 0xab, 0xc0, 0x59, 0x26, 0x40,
};
-static const char *
-binstr(ubit_t *d, int n)
-{
- static char str[256];
- int i;
+inline bool print_a5(int n, int k, char * dir, ubit_t * out, char * block) {
+ uint8_t len = 114 / 8 + 1, buf[len], res[len];
+ printf("A5/%d - %s: %s => ", n, dir, osmo_ubit_dump(out, 114));
+ osmo_hexparse(block, res, len);
+ osmo_ubit2pbit(buf, out, 114);
+ if (0 != memcmp(buf, res, len)) {
+ printf("FAIL");
+ printf("\nGOT: [%d] %s", k, osmo_hexdump_nospc(buf, len));
+ printf("\nEXP: [%d] %s\n", k, osmo_hexdump_nospc(res, len));
+ return false;
+ }
+ printf("OK\n");
+ return true;
+}
- for (i=0; i<n; i++)
- str[i] = d[i] ? '1' : '0';
+inline bool test_a5(int n, char * kc, uint32_t count, char * block1, char * block2) {
+ ubit_t out[114];
+ int k = (n == 4) ? 16 : 8;
+ uint8_t key[k];
+ osmo_hexparse(kc, key, k);
- str[i] = '\0';
+ osmo_a5(n, key, count, out, NULL);
+ bool d = print_a5(n, k, "DL", out, block1);
- return str;
+ osmo_a5(n, key, count, NULL, out);
+ bool u = print_a5(n, k, "UL", out, block2);
+
+ return d & u;
}
int main(int argc, char **argv)
{
- ubit_t exp[114];
- ubit_t out[114];
- int n, i;
+ ubit_t exp[114], out[114];
+ int n, i;
for (n=0; n<3; n++) {
/* "Randomize" */
@@ -66,13 +82,13 @@ int main(int argc, char **argv)
osmo_a5(n, key, fn, out, NULL);
- printf("A5/%d - DL: %s", n, binstr(out, 114));
+ printf("A5/%d - DL: %s", n, osmo_ubit_dump(out, 114));
if (!memcmp(exp, out, 114))
printf(" => OK\n");
else {
printf(" => BAD\n");
- printf(" Expected: %s", binstr(out, 114));
+ printf(" Expected: %s", osmo_ubit_dump(out, 114));
fprintf(stderr, "[!] A5/%d DL failed", n);
exit(1);
}
@@ -82,17 +98,31 @@ int main(int argc, char **argv)
osmo_a5(n, key, fn, NULL, out);
- printf("A5/%d - UL: %s", n, binstr(out, 114));
+ printf("A5/%d - UL: %s", n, osmo_ubit_dump(out, 114));
if (!memcmp(exp, out, 114))
printf(" => OK\n");
else {
printf(" => BAD\n");
- printf(" Expected: %s", binstr(out, 114));
+ printf(" Expected: %s", osmo_ubit_dump(out, 114));
fprintf(stderr, "[!] A5/%d UL failed", n);
exit(1);
}
}
+// test vectors from 3GPP TS 55.217 and TS 55.218
+ test_a5(3, "2BD6459F82C5BC00", 0x24F20F, "889EEAAF9ED1BA1ABBD8436232E440", "5CA3406AA244CF69CF047AADA2DF40");
+ test_a5(3, "952C49104881FF48", 0x061272, "FB4D5FBCEE13A33389285686E9A5C0", "25090378E0540457C57E367662E440");
+ test_a5(3, "EFA8B2229E720C2A", 0x33FD3F, "0E4015755A336469C3DD8680E30340", "6F10669E2B4E18B042431A28E47F80");
+ test_a5(3, "952C49104881FF48", 0x061527, "AB7DB38A573A325DAA76E4CB800A40", "4C4B594FEA9D00FE8978B7B7BC1080");
+ test_a5(3, "3451F23A43BD2C87", 0x0E418C, "75F7C4C51560905DFBA05E46FB54C0", "192C95353CDF979E054186DF15BF00");
+ test_a5(3, "CAA2639BE82435CF", 0x2FF229, "301437E4D4D6565D4904C631606EC0", "F0A3B8795E264D3E1A82F684353DC0");
+ test_a5(3, "7AE67E87400B9FA6", 0x2F24E5, "F794290FEF643D2EA348A7796A2100", "CB6FA6C6B8A705AF9FEFE975818500");
+ test_a5(3, "58AF69935540698B", 0x05446B, "749CA4E6B691E5A598C461D5FE4740", "31C9E444CD04677ADAA8A082ADBC40");
+ test_a5(3, "017F81E5F236FE62", 0x156B26, "2A6976761E60CC4E8F9F52160276C0", "A544D8475F2C78C35614128F1179C0");
+ test_a5(3, "1ACA8B448B767B39", 0x0BC3B5, "A4F70DC5A2C9707F5FA1C60EB10640", "7780B597B328C1400B5C74823E8500");
+ test_a5(4, "3D43C388C9581E337FF1F97EB5C1F85E", 0x35D2CF, "A2FE3034B6B22CC4E33C7090BEC340", "170D7497432FF897B91BE8AECBA880");
+ test_a5(4, "A4496A64DF4F399F3B4506814A3E07A1", 0x212777, "89CDEE360DF9110281BCF57755A040", "33822C0C779598C9CBFC49183AF7C0");
+
return 0;
}
diff --git a/tests/a5/a5_test.ok b/tests/a5/a5_test.ok
index 4497e14..cefcdb6 100644
--- a/tests/a5/a5_test.ok
+++ b/tests/a5/a5_test.ok
@@ -4,3 +4,27 @@ A5/1 - DL: 110010111010001001010101011101100001011101011101001110110001110001111
A5/1 - UL: 110110010000001101011110000011110010101011101100000100111001101000000101110101001010100001111011101100010110010010 => OK
A5/2 - DL: 010001011001110010001000110000111000001010110111111111111011001110011000110100101111100101101110000011110001010010 => OK
A5/2 - UL: 111100000011101010101100110111101110001101011011010111100110010110000000101110101010101111000000010110010010011001 => OK
+A5/3 - DL: 100010001001111011101010101011111001111011010001101110100001101010111011110110000100001101100010001100101110010001 => OK
+A5/3 - UL: 010111001010001101000000011010101010001001000100110011110110100111001111000001000111101010101101101000101101111101 => OK
+A5/3 - DL: 111110110100110101011111101111001110111000010011101000110011001110001001001010000101011010000110111010011010010111 => OK
+A5/3 - UL: 001001010000100100000011011110001110000001010100000001000101011111000101011111100011011001110110011000101110010001 => OK
+A5/3 - DL: 000011100100000000010101011101010101101000110011011001000110100111000011110111011000011010000000111000110000001101 => OK
+A5/3 - UL: 011011110001000001100110100111100010101101001110000110001011000001000010010000110001101000101000111001000111111110 => OK
+A5/3 - DL: 101010110111110110110011100010100101011100111010001100100101110110101010011101101110010011001011100000000000101001 => OK
+A5/3 - UL: 010011000100101101011001010011111110101010011101000000001111111010001001011110001011011110110111101111000001000010 => OK
+A5/3 - DL: 011101011111011111000100110001010001010101100000100100000101110111111011101000000101111001000110111110110101010011 => OK
+A5/3 - UL: 000110010010110010010101001101010011110011011111100101111001111000000101010000011000011011011111000101011011111100 => OK
+A5/3 - DL: 001100000001010000110111111001001101010011010110010101100101110101001001000001001100011000110001011000000110111011 => OK
+A5/3 - UL: 111100001010001110111000011110010101111000100110010011010011111000011010100000101111011010000100001101010011110111 => OK
+A5/3 - DL: 111101111001010000101001000011111110111101100100001111010010111010100011010010001010011101111001011010100010000100 => OK
+A5/3 - UL: 110010110110111110100110110001101011100010100111000001011010111110011111111011111110100101110101100000011000010100 => OK
+A5/3 - DL: 011101001001110010100100111001101011011010010001111001011010010110011000110001000110000111010101111111100100011101 => OK
+A5/3 - UL: 001100011100100111100100010001001100110100000100011001110111101011011010101010001010000010000010101011011011110001 => OK
+A5/3 - DL: 001010100110100101110110011101100001111001100000110011000100111010001111100111110101001000010110000000100111011011 => OK
+A5/3 - UL: 101001010100010011011000010001110101111100101100011110001100001101010110000101000001001010001111000100010111100111 => OK
+A5/3 - DL: 101001001111011100001101110001011010001011001001011100000111111101011111101000011100011000001110101100010000011001 => OK
+A5/3 - UL: 011101111000000010110101100101111011001100101000110000010100000000001011010111000111010010000010001111101000010100 => OK
+A5/4 - DL: 101000101111111000110000001101001011011010110010001011001100010011100011001111000111000010010000101111101100001101 => OK
+A5/4 - UL: 000101110000110101110100100101110100001100101111111110001001011110111001000110111110100010101110110010111010100010 => OK
+A5/4 - DL: 100010011100110111101110001101100000110111111001000100010000001010000001101111001111010101110111010101011010000001 => OK
+A5/4 - UL: 001100111000001000101100000011000111011110010101100110001100100111001011111111000100100100011000001110101111011111 => OK
--
1.7.10.4
--------------060001040407040305040404
Content-Type: text/x-patch;
name="0005-Update-test-suite-and-build-infrastructure.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="0005-Update-test-suite-and-build-infrastructure.patch"
1
0
---
include/osmocom/gsm/kasumi.h | 36 ++++++++
src/gsm/kasumi.c | 193 ++++++++++++++++++++++++++++++++++++++++++
tests/kasumi/kasumi_test.c | 128 ++++++++++++++++++++++++++++
tests/kasumi/kasumi_test.ok | 10 +++
4 files changed, 367 insertions(+)
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/include/osmocom/gsm/kasumi.h b/include/osmocom/gsm/kasumi.h
new file mode 100644
index 0000000..8479968
--- /dev/null
+++ b/include/osmocom/gsm/kasumi.h
@@ -0,0 +1,36 @@
+/*
+ * KASUMI header
+ *
+ * See kasumi.c for details
+ */
+
+#ifndef __KASUMI_H__
+#define __KASUMI_H__
+
+#include <stdint.h>
+
+/*
+ * Single iteration of KASUMI cipher
+*/
+uint64_t _kasumi(uint64_t P, uint16_t *KLi1, uint16_t *KLi2, uint16_t *KOi1, uint16_t *KOi2, uint16_t *KOi3, uint16_t *KIi1, uint16_t *KIi2, uint16_t *KIi3);
+
+/*
+ * Implementation of the KGCORE algorithm (used by A5/3, A5/4, GEA3, GEA4 and ECSD)
+ *
+ * CA : uint8_t
+ * cb : uint8_t
+ * cc : uint32_t
+ * cd : uint8_t
+ * ck : uint8_t [8]
+ * co : uint8_t [output, cl-dependent]
+ * cl : uint16_t
+ */
+void _kasumi_kgcore(uint8_t CA, uint8_t cb, uint32_t cc, uint8_t cd, const uint8_t *ck, uint8_t *co, uint16_t cl);
+
+/*! \brief Expand key into set of subkeys
+ * \param[in] key (128 bits) as array of bytes
+ * \param[out] arrays of round-specific subkeys - see TS 135 202 for details
+ */
+void _kasumi_key_expand(const uint8_t *key, uint16_t *KLi1, uint16_t *KLi2, uint16_t *KOi1, uint16_t *KOi2, uint16_t *KOi3, uint16_t *KIi1, uint16_t *KIi2, uint16_t *KIi3);
+
+#endif /* __KASUMI_H__ */
diff --git a/src/gsm/kasumi.c b/src/gsm/kasumi.c
new file mode 100644
index 0000000..816c681
--- /dev/null
+++ b/src/gsm/kasumi.c
@@ -0,0 +1,193 @@
+/* Kasumi cipher and KGcore functions */
+
+/* (C) 2013 by Max <Max.Suraev(a)fairwaves.ru>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdint.h>
+#include <osmocom/core/bits.h>
+#include <osmocom/gsm/kasumi.h>
+
+static uint16_t
+_kasumi_FI(uint16_t I, uint16_t skey)
+{
+ static uint16_t S7[] = {
+ 54, 50, 62, 56, 22, 34, 94, 96, 38, 6, 63, 93, 2, 18, 123, 33,
+ 55, 113, 39, 114, 21, 67, 65, 12, 47, 73, 46, 27, 25, 111, 124, 81,
+ 53, 9, 121, 79, 52, 60, 58, 48, 101, 127, 40, 120, 104, 70, 71, 43,
+ 20, 122, 72, 61, 23, 109, 13, 100, 77, 1, 16, 7, 82, 10, 105, 98,
+ 117, 116, 76, 11, 89, 106, 0,125,118, 99, 86, 69, 30, 57, 126, 87,
+ 112, 51, 17, 5, 95, 14, 90, 84, 91, 8, 35,103, 32, 97, 28, 66,
+ 102, 31, 26, 45, 75, 4, 85, 92, 37, 74, 80, 49, 68, 29, 115, 44,
+ 64, 107, 108, 24, 110, 83, 36, 78, 42, 19, 15, 41, 88, 119, 59, 3
+ };
+ static uint16_t S9[] = {
+ 167, 239, 161, 379, 391, 334, 9, 338, 38, 226, 48, 358, 452, 385, 90, 397,
+ 183, 253, 147, 331, 415, 340, 51, 362, 306, 500, 262, 82, 216, 159, 356, 177,
+ 175, 241, 489, 37, 206, 17, 0, 333, 44, 254, 378, 58, 143, 220, 81, 400,
+ 95, 3, 315, 245, 54, 235, 218, 405, 472, 264, 172, 494, 371, 290, 399, 76,
+ 165, 197, 395, 121, 257, 480, 423, 212, 240, 28, 462, 176, 406, 507, 288, 223,
+ 501, 407, 249, 265, 89, 186, 221, 428,164, 74, 440, 196, 458, 421, 350, 163,
+ 232, 158, 134, 354, 13, 250, 491, 142,191, 69, 193, 425, 152, 227, 366, 135,
+ 344, 300, 276, 242, 437, 320, 113, 278, 11, 243, 87, 317, 36, 93, 496, 27,
+ 487, 446, 482, 41, 68, 156, 457, 131, 326, 403, 339, 20, 39, 115, 442, 124,
+ 475, 384, 508, 53, 112, 170, 479, 151, 126, 169, 73, 268, 279, 321, 168, 364,
+ 363, 292, 46, 499, 393, 327, 324, 24, 456, 267, 157, 460, 488, 426, 309, 229,
+ 439, 506, 208, 271, 349, 401, 434, 236, 16, 209, 359, 52, 56, 120, 199, 277,
+ 465, 416, 252, 287, 246, 6, 83, 305, 420, 345, 153,502, 65, 61, 244, 282,
+ 173, 222, 418, 67, 386, 368, 261, 101, 476, 291, 195,430, 49, 79, 166, 330,
+ 280, 383, 373, 128, 382, 408, 155, 495, 367, 388, 274, 107, 459, 417, 62, 454,
+ 132, 225, 203, 316, 234, 14, 301, 91, 503, 286, 424, 211, 347, 307, 140, 374,
+ 35, 103, 125, 427, 19, 214, 453, 146, 498, 314, 444, 230, 256, 329, 198, 285,
+ 50, 116, 78, 410, 10, 205, 510, 171, 231, 45, 139, 467, 29, 86, 505, 32,
+ 72, 26, 342, 150, 313, 490, 431, 238, 411, 325, 149, 473, 40, 119, 174, 355,
+ 185, 233, 389, 71, 448, 273, 372, 55, 110, 178, 322, 12, 469, 392, 369, 190,
+ 1, 109, 375, 137, 181, 88, 75, 308, 260, 484, 98, 272, 370, 275, 412, 111,
+ 336, 318, 4, 504, 492, 259, 304, 77, 337, 435, 21, 357, 303, 332, 483, 18,
+ 47, 85, 25, 497, 474, 289, 100, 269, 296, 478, 270, 106, 31, 104, 433, 84,
+ 414, 486, 394, 96, 99, 154, 511, 148, 413, 361, 409, 255, 162, 215, 302, 201,
+ 266, 351, 343, 144, 441, 365, 108, 298, 251, 34, 182, 509, 138, 210, 335, 133,
+ 311, 352, 328, 141, 396, 346, 123, 319, 450, 281, 429, 228, 443, 481, 92, 404,
+ 485, 422, 248, 297, 23, 213, 130, 466, 22, 217, 283, 70, 294, 360, 419, 127,
+ 312, 377, 7, 468, 194, 2, 117, 295, 463, 258, 224, 447, 247, 187, 80, 398,
+ 284, 353, 105, 390, 299, 471, 470, 184, 57, 200, 348, 63, 204, 188, 33, 451,
+ 97, 30, 310, 219, 94, 160, 129, 493, 64, 179, 263, 102, 189, 207, 114, 402,
+ 438, 477, 387, 122, 192, 42, 381, 5, 145, 118, 180, 449, 293, 323, 136, 380,
+ 43, 66, 60, 455, 341, 445, 202, 432, 8, 237, 15, 376, 436, 464, 59, 461
+ };
+ uint16_t L, R;
+
+ /* Split 16 bit input into two unequal halves: 9 and 7 bits, same for subkey */
+ L = I >> 7; /* take 9 bits */
+ R = I & 0x7F; /* take 7 bits */
+
+ L = S9[L] ^ R;
+ R = S7[R] ^ (L & 0x7F);
+
+ L ^= (skey & 0x1FF);
+ R ^= (skey >> 9);
+
+ L = S9[L] ^ R;
+ R = S7[R] ^ (L & 0x7F);
+
+ return (R << 9) + L;
+}
+
+static uint32_t
+_kasumi_FO(uint32_t I, uint16_t *KOi1, uint16_t *KOi2, uint16_t *KOi3, uint16_t *KIi1, uint16_t *KIi2, uint16_t *KIi3, unsigned i)
+{
+ uint16_t L = I >> 16, R = I; /* Split 32 bit input into Left and Right parts */
+
+ L ^= KOi1[i];
+ L = _kasumi_FI(L, KIi1[i]);
+ L ^= R;
+
+ R ^= KOi2[i];
+ R = _kasumi_FI(R, KIi2[i]);
+ R ^= L;
+
+ L ^= KOi3[i];
+ L = _kasumi_FI(L, KIi3[i]);
+ L ^= R;
+
+ return (((uint32_t)R) << 16) + L;
+}
+
+static uint32_t
+_kasumi_FL(uint32_t I, uint16_t *KLi1, uint16_t *KLi2, unsigned i)
+{
+ uint16_t L = I >> 16, R = I, tmp; /* Split 32 bit input into Left and Right parts */
+
+ tmp = L & KLi1[i];
+ R ^= rol16(tmp, 1);
+
+ tmp = R | KLi2[i];
+ L ^= rol16(tmp, 1);
+
+ return (((uint32_t)L) << 16) + R;
+}
+
+uint64_t
+_kasumi(uint64_t P, uint16_t *KLi1, uint16_t *KLi2, uint16_t *KOi1, uint16_t *KOi2, uint16_t *KOi3, uint16_t *KIi1, uint16_t *KIi2, uint16_t *KIi3)
+{
+ uint32_t i, L = P >> 32, R = P; /* Split 64 bit input into Left and Right parts */
+
+ for (i = 0; i < 8; i++)
+ {
+ R ^= _kasumi_FO(_kasumi_FL(L, KLi1, KLi2, i), KOi1, KOi2, KOi3, KIi1, KIi2, KIi3, i); /* odd round */
+ i++;
+ L ^= _kasumi_FL(_kasumi_FO(R, KOi1, KOi2, KOi3, KIi1, KIi2, KIi3, i), KLi1, KLi2, i); /* even round */
+ }
+ return (((uint64_t)L) << 32) + R; /* Concatenate Left and Right 32 bits into 64 bit ciphertext */
+}
+
+/*! \brief Expand key into set of subkeys
+ * \param[in] key (128 bits) as array of bytes
+ * \param[out] arrays of round-specific subkeys - see TS 135 202 for details
+ */
+void
+_kasumi_key_expand(const uint8_t *key, uint16_t *KLi1, uint16_t *KLi2, uint16_t *KOi1, uint16_t *KOi2, uint16_t *KOi3, uint16_t *KIi1, uint16_t *KIi2, uint16_t *KIi3)
+{
+ uint16_t i, C[] = { 0x0123, 0x4567, 0x89AB, 0xCDEF, 0xFEDC, 0xBA98, 0x7654, 0x3210 };
+
+ for (i = 0; i < 8; i++) /* Work with 16 bit subkeys and create prime subkeys */
+ {
+ C[i] ^= osmo_get2bytes(key + i * 2);
+ }
+ /* C[] now stores K-prime[] */
+ for (i = 0; i < 8; i++) /* Create round-specific subkeys */
+ {
+ KLi1[i] = rol16(osmo_get2bytes(key + i * 2), 1);
+ KLi2[i] = C[(i + 2) & 0x7];
+
+ KOi1[i] = rol16(osmo_get2bytes(key + ((2 * (i + 1)) & 0xE)), 5);
+ KOi2[i] = rol16(osmo_get2bytes(key + ((2 * (i + 5)) & 0xE)), 8);
+ KOi3[i] = rol16(osmo_get2bytes(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_64pack2pbit(BLK, co + (i * 8));
+ }
+}
diff --git a/tests/kasumi/kasumi_test.c b/tests/kasumi/kasumi_test.c
new file mode 100644
index 0000000..5504905
--- /dev/null
+++ b/tests/kasumi/kasumi_test.c
@@ -0,0 +1,128 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/gsm/kasumi.h> // for testing internal A5/3 functions
+
+
+inline int _compare_mem(uint8_t * x, uint8_t * y, size_t len) {
+ if (0 != memcmp(x, y, len)) {
+ printf ("X: %s\t", osmo_hexdump_nospc(x, len));
+ printf ("Y: %s\n", osmo_hexdump_nospc(y, len));
+ return 0;
+ }
+ return 1;
+}
+
+inline static void test_expansion(uint8_t * test_key, uint16_t * _KLi1, uint16_t * _KLi2, uint16_t * _KOi1, uint16_t * _KOi2, uint16_t * _KOi3, uint16_t * _KIi1, uint16_t * _KIi2, uint16_t * _KIi3, uint16_t * _KLi1_r, uint16_t * _KLi2_r, uint16_t * _KOi1_r, uint16_t * _KOi2_r, uint16_t * _KOi3_r, uint16_t * _KIi1_r, uint16_t * _KIi2_r, uint16_t * _KIi3_r)
+{
+ _kasumi_key_expand(test_key, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3);
+ int passed = 1;
+ passed = _compare_mem((uint8_t *)_KLi1, (uint8_t *)_KLi1_r, 16);
+ passed = _compare_mem((uint8_t *)_KLi2, (uint8_t *)_KLi2_r, 16);
+ passed = _compare_mem((uint8_t *)_KOi1, (uint8_t *)_KOi1_r, 16);
+ passed = _compare_mem((uint8_t *)_KOi2, (uint8_t *)_KOi2_r, 16);
+ passed = _compare_mem((uint8_t *)_KOi3, (uint8_t *)_KOi3_r, 16);
+ passed = _compare_mem((uint8_t *)_KIi1, (uint8_t *)_KIi1_r, 16);
+ passed = _compare_mem((uint8_t *)_KIi2, (uint8_t *)_KIi2_r, 16);
+ passed = _compare_mem((uint8_t *)_KIi3, (uint8_t *)_KIi3_r, 16);
+ if (passed) printf(" OK. "); else printf("FAILED!");
+}
+
+int main(int argc, char **argv)
+{
+ uint16_t _KLi1[8], _KLi2[8], _KOi1[8], _KOi2[8], _KOi3[8], _KIi1[8], _KIi2[8], _KIi3[8], _KLi1_r[8], _KLi2_r[8], _KOi1_r[8], _KOi2_r[8], _KOi3_r[8], _KIi1_r[8], _KIi2_r[8], _KIi3_r[8];
+
+ printf("testing KASUMI key expansion and encryption (ETSI TS 135 203):\n");
+ printf("KASUMI Test Set 1...");
+
+uint8_t _test_key1[] = {0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00, 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48};
+_KLi1_r[0] = 0x57AC; _KLi1_r[1] = 0x8B3E; _KLi1_r[2] = 0x058B; _KLi1_r[3] = 0x6601; _KLi1_r[4] = 0x2A59; _KLi1_r[5] = 0x9220; _KLi1_r[6] = 0x9102; _KLi1_r[7] = 0xFE91;
+_KLi2_r[0] = 0x0B6E; _KLi2_r[1] = 0x7EEF; _KLi2_r[2] = 0x6BF0; _KLi2_r[3] = 0xF388; _KLi2_r[4] = 0x3ED5; _KLi2_r[5] = 0xCD58; _KLi2_r[6] = 0x2AF5; _KLi2_r[7] = 0x00F8;
+_KOi1_r[0] = 0xB3E8; _KOi1_r[1] = 0x58B0; _KOi1_r[2] = 0x6016; _KOi1_r[3] = 0xA592; _KOi1_r[4] = 0x2209; _KOi1_r[5] = 0x1029; _KOi1_r[6] = 0xE91F; _KOi1_r[7] = 0x7AC5;
+_KOi2_r[0] = 0x1049; _KOi2_r[1] = 0x8148; _KOi2_r[2] = 0x48FF; _KOi2_r[3] = 0xD62B; _KOi2_r[4] = 0x9F45; _KOi2_r[5] = 0xC582; _KOi2_r[6] = 0x00B3; _KOi2_r[7] = 0x2C95;
+_KOi3_r[0] = 0x2910; _KOi3_r[1] = 0x1FE9; _KOi3_r[2] = 0xC57A; _KOi3_r[3] = 0xE8B3; _KOi3_r[4] = 0xB058; _KOi3_r[5] = 0x1660; _KOi3_r[6] = 0x92A5; _KOi3_r[7] = 0x0922;
+_KIi1_r[0] = 0x6BF0; _KIi1_r[1] = 0xF388; _KIi1_r[2] = 0x3ED5; _KIi1_r[3] = 0xCD58; _KIi1_r[4] = 0x2AF5; _KIi1_r[5] = 0x00F8; _KIi1_r[6] = 0x0B6E; _KIi1_r[7] = 0x7EEF;
+_KIi2_r[0] = 0x7EEF; _KIi2_r[1] = 0x6BF0; _KIi2_r[2] = 0xF388; _KIi2_r[3] = 0x3ED5; _KIi2_r[4] = 0xCD58; _KIi2_r[5] = 0x2AF5; _KIi2_r[6] = 0x00F8; _KIi2_r[7] = 0x0B6E;
+_KIi3_r[0] = 0xCD58; _KIi3_r[1] = 0x2AF5; _KIi3_r[2] = 0x00F8; _KIi3_r[3] = 0x0B6E; _KIi3_r[4] = 0x7EEF; _KIi3_r[5] = 0x6BF0; _KIi3_r[6] = 0xF388; _KIi3_r[7] = 0x3ED5;
+test_expansion(_test_key1, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3, _KLi1_r, _KLi2_r, _KOi1_r, _KOi2_r, _KOi3_r, _KIi1_r, _KIi2_r, _KIi3_r);
+
+if (0xDF1F9B251C0BF45F == _kasumi(0xEA024714AD5C4D84, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3))
+ printf("OK."); else printf("FAILED!");
+
+printf("\nKASUMI Test Set 2...");
+
+uint8_t _test_key2[] = {0x8C, 0xE3, 0x3E, 0x2C, 0xC3, 0xC0, 0xB5, 0xFC, 0x1F, 0x3D, 0xE8, 0xA6, 0xDC, 0x66, 0xB1, 0xF3};
+_KLi1_r[0] = 0x19C7; _KLi1_r[1] = 0x7C58; _KLi1_r[2] = 0x8781; _KLi1_r[3] = 0x6BF9; _KLi1_r[4] = 0x3E7A; _KLi1_r[5] = 0xD14D; _KLi1_r[6] = 0xB8CD; _KLi1_r[7] = 0x63E7;
+_KLi2_r[0] = 0x4A6B; _KLi2_r[1] = 0x7813; _KLi2_r[2] = 0xE1E1; _KLi2_r[3] = 0x523E; _KLi2_r[4] = 0xAA32; _KLi2_r[5] = 0x83E3; _KLi2_r[6] = 0x8DC0; _KLi2_r[7] = 0x7B4B;
+_KOi1_r[0] = 0xC587; _KOi1_r[1] = 0x7818; _KOi1_r[2] = 0xBF96; _KOi1_r[3] = 0xE7A3; _KOi1_r[4] = 0x14DD; _KOi1_r[5] = 0x8CDB; _KOi1_r[6] = 0x3E76; _KOi1_r[7] = 0x9C71;
+_KOi2_r[0] = 0xA6E8; _KOi2_r[1] = 0x66DC; _KOi2_r[2] = 0xF3B1; _KOi2_r[3] = 0xE38C; _KOi2_r[4] = 0x2C3E; _KOi2_r[5] = 0xC0C3; _KOi2_r[6] = 0xFCB5; _KOi2_r[7] = 0x3D1F;
+_KOi3_r[0] = 0xDB8C; _KOi3_r[1] = 0x763E; _KOi3_r[2] = 0x719C; _KOi3_r[3] = 0x87C5; _KOi3_r[4] = 0x1878; _KOi3_r[5] = 0x96BF; _KOi3_r[6] = 0xA3E7; _KOi3_r[7] = 0xDD14;
+_KIi1_r[0] = 0xE1E1; _KIi1_r[1] = 0x523E; _KIi1_r[2] = 0xAA32; _KIi1_r[3] = 0x83E3; _KIi1_r[4] = 0x8DC0; _KIi1_r[5] = 0x7B4B; _KIi1_r[6] = 0x4A6B; _KIi1_r[7] = 0x7813;
+_KIi2_r[0] = 0x7813; _KIi2_r[1] = 0xE1E1; _KIi2_r[2] = 0x523E; _KIi2_r[3] = 0xAA32; _KIi2_r[4] = 0x83E3; _KIi2_r[5] = 0x8DC0; _KIi2_r[6] = 0x7B4B; _KIi2_r[7] = 0x4A6B;
+_KIi3_r[0] = 0x83E3; _KIi3_r[1] = 0x8DC0; _KIi3_r[2] = 0x7B4B; _KIi3_r[3] = 0x4A6B; _KIi3_r[4] = 0x7813; _KIi3_r[5] = 0xE1E1; _KIi3_r[6] = 0x523E; _KIi3_r[7] = 0xAA32;
+test_expansion(_test_key2, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3, _KLi1_r, _KLi2_r, _KOi1_r, _KOi2_r, _KOi3_r, _KIi1_r, _KIi2_r, _KIi3_r);
+
+if (0xDE551988CEB2F9B7 == _kasumi(0xD3C5D592327FB11C, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3))
+ printf("OK."); else printf("FAILED!");
+
+printf("\nKASUMI Test Set 3...");
+
+uint8_t _test_key3[] = {0x40, 0x35, 0xC6, 0x68, 0x0A, 0xF8, 0xC6, 0xD1, 0xA8, 0xFF, 0x86, 0x67, 0xB1, 0x71, 0x40, 0x13};
+_KLi1_r[0] = 0x806A; _KLi1_r[1] = 0x8CD1; _KLi1_r[2] = 0x15F0; _KLi1_r[3] = 0x8DA3; _KLi1_r[4] = 0x51FF; _KLi1_r[5] = 0x0CCF; _KLi1_r[6] = 0x62E3; _KLi1_r[7] = 0x8026;
+_KLi2_r[0] = 0x8353; _KLi2_r[1] = 0x0B3E; _KLi2_r[2] = 0x5623; _KLi2_r[3] = 0x3CFF; _KLi2_r[4] = 0xC725; _KLi2_r[5] = 0x7203; _KLi2_r[6] = 0x4116; _KLi2_r[7] = 0x830F;
+_KOi1_r[0] = 0xCD18; _KOi1_r[1] = 0x5F01; _KOi1_r[2] = 0xDA38; _KOi1_r[3] = 0x1FF5; _KOi1_r[4] = 0xCCF0; _KOi1_r[5] = 0x2E36; _KOi1_r[6] = 0x0268; _KOi1_r[7] = 0x06A8;
+_KOi2_r[0] = 0x6786; _KOi2_r[1] = 0x71B1; _KOi2_r[2] = 0x1340; _KOi2_r[3] = 0x3540; _KOi2_r[4] = 0x68C6; _KOi2_r[5] = 0xF80A; _KOi2_r[6] = 0xD1C6; _KOi2_r[7] = 0xFFA8;
+_KOi3_r[0] = 0x362E; _KOi3_r[1] = 0x6802; _KOi3_r[2] = 0xA806; _KOi3_r[3] = 0x18CD; _KOi3_r[4] = 0x015F; _KOi3_r[5] = 0x38DA; _KOi3_r[6] = 0xF51F; _KOi3_r[7] = 0xF0CC;
+_KIi1_r[0] = 0x5623; _KIi1_r[1] = 0x3CFF; _KIi1_r[2] = 0xC725; _KIi1_r[3] = 0x7203; _KIi1_r[4] = 0x4116; _KIi1_r[5] = 0x830F; _KIi1_r[6] = 0x8353; _KIi1_r[7] = 0x0B3E;
+_KIi2_r[0] = 0x0B3E; _KIi2_r[1] = 0x5623; _KIi2_r[2] = 0x3CFF; _KIi2_r[3] = 0xC725; _KIi2_r[4] = 0x7203; _KIi2_r[5] = 0x4116; _KIi2_r[6] = 0x830F; _KIi2_r[7] = 0x8353;
+_KIi3_r[0] = 0x7203; _KIi3_r[1] = 0x4116; _KIi3_r[2] = 0x830F; _KIi3_r[3] = 0x8353; _KIi3_r[4] = 0x0B3E; _KIi3_r[5] = 0x5623; _KIi3_r[6] = 0x3CFF; _KIi3_r[7] = 0xC725;
+test_expansion(_test_key3, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3, _KLi1_r, _KLi2_r, _KOi1_r, _KOi2_r, _KOi3_r, _KIi1_r, _KIi2_r, _KIi3_r);
+
+if (0x4592B0E78690F71B == _kasumi(0x62A540981BA6F9B7, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3))
+ printf("OK."); else printf("FAILED!");
+
+printf("\nKASUMI Test Set 4...");
+uint8_t _test_key4[] = {0x3A, 0x3B, 0x39, 0xB5, 0xC3, 0xF2, 0x37, 0x6D, 0x69, 0xF7, 0xD5, 0x46, 0xE5, 0xF8, 0x5D, 0x43};
+uint64_t I4 = 0xCA49C1C75771AB0B, i;
+_kasumi_key_expand(_test_key4, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3);
+
+for (i = 0; i < 50; i++)
+ I4 = _kasumi(I4, _KLi1, _KLi2, _KOi1, _KOi2, _KOi3, _KIi1, _KIi2, _KIi3);
+
+if (0x738BAD4C4A690802 == I4) printf(" OK.\n"); else printf("FAILED!");
+
+
+uint8_t gamma[32];
+
+uint8_t _Key1[] = {0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xBC, 0x00, 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xBC, 0x00},
+_gamma1[] = {0x88, 0x9E, 0xEA, 0xAF, 0x9E, 0xD1, 0xBA, 0x1A, 0xBB, 0xD8, 0x43, 0x62, 0x32, 0xE4, 0x57, 0x28, 0xD0, 0x1A, 0xA8, 0x91, 0x33, 0xDA, 0x73, 0xC1, 0x1E, 0xAB, 0x68, 0xB7, 0xD8, 0x9B, 0xC8, 0x41};
+_kasumi_kgcore(0xF, 0, 0x0024F20F, 0, _Key1, gamma, 228);
+printf ("KGCORE Test Set 1: %d\n", _compare_mem(gamma, _gamma1, 32));
+
+uint8_t _Key2[] = {0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48, 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48},
+_gamma2[] = {0xFB, 0x4D, 0x5F, 0xBC, 0xEE, 0x13, 0xA3, 0x33, 0x89, 0x28, 0x56, 0x86, 0xE9, 0xA5, 0xC9, 0x42, 0x40, 0xDE, 0x38, 0x15, 0x01, 0x15, 0xF1, 0x5F, 0x8D, 0x9D, 0x98, 0xB9, 0x1A, 0x94, 0xB2, 0x96};
+_kasumi_kgcore(0xF, 0, 0x00061272, 0, _Key2, gamma, 228);
+printf ("KGCORE Test Set 2: %d\n", _compare_mem(gamma, _gamma2, 32));
+
+uint8_t _Key3[] = {0xEF, 0xA8, 0xB2, 0x22, 0x9E, 0x72, 0x0C, 0x2A, 0xEF, 0xA8, 0xB2, 0x22, 0x9E, 0x72, 0x0C, 0x2A},
+_gamma3[] = {0x0E, 0x40, 0x15, 0x75, 0x5A, 0x33, 0x64, 0x69, 0xC3, 0xDD, 0x86, 0x80, 0xE3, 0x03, 0x5B, 0xC4, 0x19, 0xA7, 0x8A, 0xD3, 0x86, 0x2C, 0x10, 0x90, 0xC6, 0x8A, 0x39, 0x1F, 0xE8, 0xA6, 0xAD, 0xEB};
+_kasumi_kgcore(0xF, 0, 0x0033FD3F, 0, _Key3, gamma, 228);
+printf ("KGCORE Test Set 3: %d\n", _compare_mem(gamma, _gamma3, 32));
+
+uint8_t _Key4[] = {0x5A, 0xCB, 0x1D, 0x64, 0x4C, 0x0D, 0x51, 0x20, 0x4E, 0xA5, 0x5A, 0xCB, 0x1D, 0x64, 0x4C, 0x0D},
+_gamma4[] = {0xE0, 0x95, 0x30, 0x6A, 0xD5, 0x08, 0x6E, 0x2E, 0xAC, 0x7F, 0x31, 0x07, 0xDE, 0x4F, 0xA2, 0x2D, 0xC1, 0xDF, 0xC9, 0x7D, 0x5B, 0xC5, 0x66, 0x1D, 0xD6, 0x09, 0x6F, 0x47, 0x6A, 0xED, 0xC6, 0x4B};
+_kasumi_kgcore(0xF, 0, 0x00156B26, 0, _Key4, gamma, 228);
+printf ("KGCORE Test Set 4: %d\n", _compare_mem(gamma, _gamma4, 32));
+
+uint8_t _Key5[] = {0xD3, 0xC5, 0xD5, 0x92, 0x32, 0x7F, 0xB1, 0x1C, 0x40, 0x35, 0xC6, 0x68, 0x0A, 0xF8, 0xC6, 0xD1},
+_gamma5[] = {0xDC, 0xE6, 0x43, 0x62, 0xAB, 0x5F, 0x89, 0xC1, 0x1E, 0xF0, 0xB3, 0x05, 0x16, 0x65, 0x70, 0xF4, 0x88, 0x9D, 0x55, 0x11, 0xE9, 0xE3, 0x57, 0x5D, 0x06, 0x2B, 0x5C, 0xED, 0x60, 0x39, 0x50, 0x6A};
+_kasumi_kgcore(0xF, 0, 0x000A59B4, 0, _Key5, gamma, 228);
+printf ("KGCORE Test Set 5: %d\n", _compare_mem(gamma, _gamma5, 32));
+
+ return 0;
+}
diff --git a/tests/kasumi/kasumi_test.ok b/tests/kasumi/kasumi_test.ok
new file mode 100644
index 0000000..2c2af4c
--- /dev/null
+++ b/tests/kasumi/kasumi_test.ok
@@ -0,0 +1,10 @@
+testing KASUMI key expansion and encryption (ETSI TS 135 203):
+KASUMI Test Set 1... OK. OK.
+KASUMI Test Set 2... OK. OK.
+KASUMI Test Set 3... OK. OK.
+KASUMI Test Set 4... OK.
+KGCORE Test Set 1: 1
+KGCORE Test Set 2: 1
+KGCORE Test Set 3: 1
+KGCORE Test Set 4: 1
+KGCORE Test Set 5: 1
--
1.7.10.4
--------------060001040407040305040404
Content-Type: text/x-patch;
name="0003-Add-GEA3-and-GEA4-ciphers.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="0003-Add-GEA3-and-GEA4-ciphers.patch"
=46rom da6079e295966d9de1bba344f926c8c9eb2af33f Mon Sep 17 00:00:00 2001
From: Max <Max.Suraev(a)fairwaves.ru>
Date: Sun, 7 Apr 2013 14:56:02 +0200
Subject: [PATCH 3/5] Add GEA3 and GEA4 ciphers.
---
include/osmocom/crypt/gprs_cipher.h | 1 +
include/osmocom/gsm/gea.h | 28 +++++
src/gsm/gea.c | 45 +++++++
src/gsm/gprs_gea.c | 39 ++++++
tests/gea/gea_test | 228 +++++++++++++++++++++++++++++=
++++++
tests/gea/gea_test.c | 54 +++++++++
tests/gea/gea_test.ok | 11 ++
7 files changed, 406 insertions(+)
create mode 100644 include/osmocom/gsm/gea.h
create mode 100644 src/gsm/gea.c
create mode 100644 src/gsm/gprs_gea.c
create mode 100755 tests/gea/gea_test
create mode 100644 tests/gea/gea_test.c
create mode 100644 tests/gea/gea_test.ok
diff --git a/include/osmocom/crypt/gprs_cipher.h b/include/osmocom/crypt/=
gprs_cipher.h
index 3051071..f6ca01a 100644
--- a/include/osmocom/crypt/gprs_cipher.h
+++ b/include/osmocom/crypt/gprs_cipher.h
@@ -10,6 +10,7 @@ enum gprs_ciph_algo {
GPRS_ALGO_GEA1,
GPRS_ALGO_GEA2,
GPRS_ALGO_GEA3,
+ GPRS_ALGO_GEA4,
_GPRS_ALGO_NUM
};
=20
diff --git a/include/osmocom/gsm/gea.h b/include/osmocom/gsm/gea.h
new file mode 100644
index 0000000..9ea7231
--- /dev/null
+++ b/include/osmocom/gsm/gea.h
@@ -0,0 +1,28 @@
+/*
+ * GEA3 header
+ *
+ * See gea.c for details
+ */
+
+#ifndef __GEA_H__
+#define __GEA_H__
+
+#include <stdint.h>
+
+#include <osmocom/crypt/gprs_cipher.h>
+
+/*
+ * Performs the GEA3 algorithm (used in GPRS)
+ * out : uint8_t []
+ * len : uint16_t
+ * kc : uint64_t
+ * iv : uint32_t
+ * direct: 0 or 1
+ */
+
+int osmo_gea3(uint8_t *out, uint16_t len, uint64_t kc, uint32_t iv, enum=
gprs_cipher_direction direct);
+
+int osmo_gea4(uint8_t *out, uint16_t len, uint8_t * kc, uint32_t iv, enu=
m gprs_cipher_direction direct);
+
+#endif /* __GEA_H__ */
+
diff --git a/src/gsm/gea.c b/src/gsm/gea.c
new file mode 100644
index 0000000..ac879a8
--- /dev/null
+++ b/src/gsm/gea.c
@@ -0,0 +1,45 @@
+/*
+ * gea.c
+ *
+ * Full reimplementation of GEA3
+ *
+ * Copyright (C) 2013 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 alo=
ng
+ * with this program; if not, write to the Free Software Foundation, Inc=
=2E,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <stdint.h>
+
+#include <osmocom/core/bits.h>
+#include <osmocom/crypt/gprs_cipher.h>
+#include <osmocom/gsm/kasumi.h>
+
+
+int osmo_gea4(uint8_t *out, uint16_t len, uint8_t * kc, uint32_t iv, enu=
m gprs_cipher_direction direction) {
+ _kasumi_kgcore(0xFF, 0, iv, direction, kc, out, len * 8);
+
+ return 0;
+}
+
+int osmo_gea3(uint8_t *out, uint16_t len, uint64_t kc, uint32_t iv, enum=
gprs_cipher_direction direction) {
+ uint8_t ck[16];
+ osmo_64pack2pbit(kc, ck);
+ osmo_64pack2pbit(kc, ck + 8);
+
+// _kasumi_kgcore(0xFF, 0, iv, direction, ck, out, len * 8);
+
+ return osmo_gea4(out, len, ck, iv, direction);
+}
diff --git a/src/gsm/gprs_gea.c b/src/gsm/gprs_gea.c
new file mode 100644
index 0000000..3e0fddd
--- /dev/null
+++ b/src/gsm/gprs_gea.c
@@ -0,0 +1,39 @@
+/*
+ * gprs_gea.c
+ *
+ * GEA3 plugin
+ *
+ * Copyright (C) 2013 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 alo=
ng
+ * with this program; if not, write to the Free Software Foundation, Inc=
=2E,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <stdint.h>
+
+#include <osmocom/crypt/gprs_cipher.h>
+#include <osmocom/gsm/gea.h>
+
+static struct gprs_cipher_impl gea3_impl =3D {
+ .algo =3D GPRS_ALGO_GEA3,
+ .name =3D "GEA3 (libosmogsm built-in)",
+ .priority =3D 1000,
+ .run =3D &osmo_gea3,
+};
+
+static void __attribute__((constructor)) osmo_crypt_a5_init(void)
+{
+ gprs_cipher_register(&gea3_impl);
+}
diff --git a/tests/gea/gea_test b/tests/gea/gea_test
new file mode 100755
index 0000000..aa1fb66
--- /dev/null
+++ b/tests/gea/gea_test
@@ -0,0 +1,228 @@
+#! /bin/bash
+
+# gea/gea_test - temporary wrapper script for .libs/gea_test
+# Generated by libtool (GNU libtool) 2.4.2 Debian-2.4.2-1ubuntu2
+#
+# The gea/gea_test program cannot be directly executed until all the lib=
tool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst=3D's/\([`"$\\]\)/\\\1/g'
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=3D:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'=3D'"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
+BIN_SH=3Dxpg4; export BIN_SH # for Tru64
+DUALCASE=3D1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=3D"(cd /home/god/source/libosmocore/tests; { test -z \"\$=
{LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=3D; export L=
IBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_=
PATH || { COMPILER_PATH=3D; export COMPILER_PATH; }; }; { test -z \"\${GC=
C_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=3D; ex=
port GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD=
_RUN_PATH || { LD_RUN_PATH=3D; export LD_RUN_PATH; }; }; { test -z \"\${L=
D_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=3D; e=
xport LD_LIBRARY_PATH; }; }; PATH=3D/home/god/bin:/sbin:/usr/local/sbin:/=
usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games; =
export PATH; gcc -Wall -I../include -g -O2 -o \$progdir/\$file gea_test.o=
../src/.libs/libosmocore.so ../src/gsm/.libs/libosmogsm.so -Wl,-rpath -=
Wl,/home/god/source/libosmocore/src/.libs -Wl,-rpath -Wl,/home/god/source=
/libosmocore/src/gsm/.libs)"
+
+# This environment variable determines our operation mode.
+if test "$libtool_install_magic" =3D "%%%MAGIC variable%%%"; then
+ # install mode needs the following variables:
+ generated_by_libtool_version=3D'2.4.2'
+ notinst_deplibs=3D' ../src/libosmocore.la ../src/gsm/libosmogsm.la'
+else
+ # When we are sourced in execute mode, $file and $ECHO are already set=
=2E
+ if test "$libtool_execute_magic" !=3D "%%%MAGIC variable%%%"; then
+ file=3D"$0"
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+ ECHO=3D"printf %s\\n"
+ fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ which is used only on
+# windows platforms, and (c) all begin with the string --lt-
+# (application programs are unlikely to have options which match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's ../libtool value, followed by no.
+lt_option_debug=3D
+func_parse_lt_options ()
+{
+ lt_script_arg0=3D$0
+ shift
+ for lt_opt
+ do
+ case "$lt_opt" in
+ --lt-debug) lt_option_debug=3D1 ;;
+ --lt-dump-script)
+ lt_dump_D=3D`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e =
's%/[^/]*$%%'`
+ test "X$lt_dump_D" =3D "X$lt_script_arg0" && lt_dump_D=3D.
+ lt_dump_F=3D`$ECHO "X$lt_script_arg0" | /bin/sed -e 's/^X//' -e =
's%^.*/%%'`
+ cat "$lt_dump_D/$lt_dump_F"
+ exit 0
+ ;;
+ --lt-*)
+ $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+
+ # Print the debug banner immediately:
+ if test -n "$lt_option_debug"; then
+ echo "gea_test:gea/gea_test:${LINENO}: libtool wrapper (GNU libtool)=
2.4.2 Debian-2.4.2-1ubuntu2" 1>&2
+ fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+ lt_dump_args_N=3D1;
+ for lt_arg
+ do
+ $ECHO "gea_test:gea/gea_test:${LINENO}: newargv[$lt_dump_args_N]: $l=
t_arg"
+ lt_dump_args_N=3D`expr $lt_dump_args_N + 1`
+ done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
+
+ if test -n "$lt_option_debug"; then
+ $ECHO "gea_test:gea/gea_test:${LINENO}: newargv[0]: $progdir/$pr=
ogram" 1>&2
+ func_lt_dump_args ${1+"$@"} 1>&2
+ fi
+ exec "$progdir/$program" ${1+"$@"}
+
+ $ECHO "$0: cannot exec $program $*" 1>&2
+ exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from $@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+ case " $* " in
+ *\ --lt-*)
+ for lt_wr_arg
+ do
+ case $lt_wr_arg in
+ --lt-*) ;;
+ *) set x "$@" "$lt_wr_arg"; shift;;
+ esac
+ shift
+ done ;;
+ esac
+ func_exec_program_core ${1+"$@"}
+}
+
+ # Parse options
+ func_parse_lt_options "$0" ${1+"$@"}
+
+ # Find the directory that this script lives in.
+ thisdir=3D`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'`
+ test "x$thisdir" =3D "x$file" && thisdir=3D.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=3D`ls -ld "$file" | /bin/sed -n 's/.*-> //p'`
+ while test -n "$file"; do
+ destdir=3D`$ECHO "$file" | /bin/sed 's%/[^/]*$%%'`
+
+ # If there was a directory component, then change thisdir.
+ if test "x$destdir" !=3D "x$file"; then
+ case "$destdir" in
+ [\\/]* | [A-Za-z]:[\\/]*) thisdir=3D"$destdir" ;;
+ *) thisdir=3D"$thisdir/$destdir" ;;
+ esac
+ fi
+
+ file=3D`$ECHO "$file" | /bin/sed 's%^.*/%%'`
+ file=3D`ls -ld "$thisdir/$file" | /bin/sed -n 's/.*-> //p'`
+ done
+
+ # Usually 'no', except on cygwin/mingw when embedded into
+ # the cwrapper.
+ WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=3Dno
+ if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" =3D "yes"; then
+ # special case for '.'
+ if test "$thisdir" =3D "."; then
+ thisdir=3D`pwd`
+ fi
+ # remove .libs from thisdir
+ case "$thisdir" in
+ *[\\/].libs ) thisdir=3D`$ECHO "$thisdir" | /bin/sed 's%[\\/][^\\/]*=
$%%'` ;;
+ .libs ) thisdir=3D. ;;
+ esac
+ fi
+
+ # Try to get the absolute directory name.
+ absdir=3D`cd "$thisdir" && pwd`
+ test -n "$absdir" && thisdir=3D"$absdir"
+
+ program=3Dlt-'gea_test'
+ progdir=3D"$thisdir/.libs"
+
+ if test ! -f "$progdir/$program" ||
+ { file=3D`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev=
/null | /bin/sed 1q`; \
+ test "X$file" !=3D "X$progdir/$program"; }; then
+
+ file=3D"$$-$program"
+
+ if test ! -d "$progdir"; then
+ mkdir "$progdir"
+ else
+ rm -f "$progdir/$file"
+ fi
+
+ # relink executable if necessary
+ if test -n "$relink_command"; then
+ if relink_command_output=3D`eval $relink_command 2>&1`; then :
+ else
+ printf %s\n "$relink_command_output" >&2
+ rm -f "$progdir/$file"
+ exit 1
+ fi
+ fi
+
+ mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null ||
+ { rm -f "$progdir/$program";
+ mv -f "$progdir/$file" "$progdir/$program"; }
+ rm -f "$progdir/$file"
+ fi
+
+ if test -f "$progdir/$program"; then
+ if test "$libtool_execute_magic" !=3D "%%%MAGIC variable%%%"; then
+ # Run the actual program with our arguments.
+ func_exec_program ${1+"$@"}
+ fi
+ else
+ # The program doesn't exist.
+ $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2
+ $ECHO "This script is just a wrapper for $program." 1>&2
+ $ECHO "See the libtool documentation for more information." 1>&2
+ exit 1
+ fi
+fi
diff --git a/tests/gea/gea_test.c b/tests/gea/gea_test.c
new file mode 100644
index 0000000..70a4d2a
--- /dev/null
+++ b/tests/gea/gea_test.c
@@ -0,0 +1,54 @@
+#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/crypt/gprs_cipher.h>
+#include <osmocom/gsm/gea.h>
+
+void print_check(char * res, uint8_t * out, uint16_t len) {
+ uint8_t buf[len];
+ osmo_hexparse(res, buf, len);
+ if (0 !=3D memcmp(buf, out, len)) {
+ printf("FAIL:\n");
+ printf("OUT: %s\n", osmo_hexdump_nospc(out, len));
+ printf("EXP: %s\n", osmo_hexdump_nospc(buf, len));
+ }
+ else printf("OK\n");
+}
+
+void test_gea3(uint64_t kc, uint32_t iv, int dir, uint16_t len, char * r=
es) {
+ printf("%d: %d -> 0x%X ", len, dir, iv);
+ uint8_t out[len];
+ osmo_gea3(out, len, kc, iv, dir);
+ print_check(res, out, len);
+}
+
+void test_gea4(char * kc, uint32_t iv, int dir, uint16_t len, char * res=
) {
+ printf("%d: %d -> 0x%X ", len, dir, iv);
+ uint8_t out[len], ck[256];
+ osmo_hexparse(kc, ck, len);
+ osmo_gea4(out, len, ck, iv, dir);
+ print_check(res, out, len);
+}
+
+int main(int argc, char **argv)
+{
+ printf("GEA3 support: %d\n", gprs_cipher_supported(GPRS_ALGO_GEA3));=
+ printf("GEA4 support: %d\n", gprs_cipher_supported(GPRS_ALGO_GEA4));=
+// test vectors according to 3GPP TS 55.217 and TS 55.218
+test_gea3(0x2BD6459F82C5BC00, 0x8E9421A3, 0, 59, "5F359709DE950D0105B17B=
6C90194280F880B48DCCDC2AFEED415DBEF4354EEBB21D073CCBBFB2D706BD7AFFD371FC9=
6E3970D143DCB2624054826");
+test_gea3(0x952C49104881FF48, 0x5064DB71, 0, 59, "FDC03D738C8E14FF0320E5=
9AAF75760799E9DA78DD8F888471C4AEAAC1849633A26CD84F459D265B83D7D9B9A0B1E54=
F4D75E331640DF19E0DB0E0");
+test_gea3(0xEFA8B2229E720C2A, 0x4BDBD5E5, 1, 59, "4718A2ADFC90590949DDAD=
AB406EC3B925F1AF1214673909DAAB96BB4C18B1374BB1E99445A81CC856E47C6E49E9DBB=
9873D0831B2175CA1E109BA");
+test_gea3(0x3451F23A43BD2C87, 0x893FE14F, 0, 59, "B46B1E284E3F8B63B86D9D=
F0915CFCEDDF2F061895BF9F82BF2593AE4847E94A4626C393CF8941CE15EA7812690D841=
5B88C5730FE1F5D410E16A2");
+test_gea3(0xCAA2639BE82435CF, 0x8FE17885, 1, 59, "9FEFAF155A26CF35603E72=
7CDAA87BA067FD84FF98A50B7FF0EC8E95A0FB70E79CB93DEE2B7E9AB59D050E126240157=
1F349C68229DDF0DECC4E85");
+test_gea3(0x1ACA8B448B767B39, 0x4F7BC3B5, 0, 59, "514F6C3A3B5A55CA190092=
F7BB6E80EF3EDB738FCDCE2FF90BB387DDE75BBC32A04A67B898A3DFB8198FFFC37D437CF=
69E7F9C13B51A868720E750");
+test_gea4("D3C5D592327FB11C4035C6680AF8C6D1", 0x0A3A59B4, 0, 51, "6E217C=
E41EBEFB5EC8094C15974290065E42BABC9AE35654A53085CE68DFA4426A2FF0AD4AF3341=
006A3F84B7613ACB4FBDC34");
+test_gea4("3D43C388C9581E337FF1F97EB5C1F85E", 0x48571AB9, 0, 59, "FC7314=
EF00A63ED0116F236C5D25C54EEC56A5B71F9F18B4D7941F84E422ACBDE5EEA9A20467900=
2D14F312F3DEE2A1AC917C3FBDC3696143C0F5D");
+test_gea4("A4496A64DF4F399F3B4506814A3E07A1", 0xEB04ADE2, 1, 59, "2AEB59=
70FB06B718027D048488AAF24FB3B74EA4A6B1242FF85B108FF816A303C72757D9AAD862B=
835D1D287DBC141D0A28D79D87BB137CD1198CD");
+
+ return 0;
+}
diff --git a/tests/gea/gea_test.ok b/tests/gea/gea_test.ok
new file mode 100644
index 0000000..15abd38
--- /dev/null
+++ b/tests/gea/gea_test.ok
@@ -0,0 +1,11 @@
+GEA3 support: 0
+GEA4 support: 0
+59: 0 -> 0x8E9421A3 OK
+59: 0 -> 0x5064DB71 OK
+59: 1 -> 0x4BDBD5E5 OK
+59: 0 -> 0x893FE14F OK
+59: 1 -> 0x8FE17885 OK
+59: 0 -> 0x4F7BC3B5 OK
+51: 0 -> 0xA3A59B4 OK
+59: 0 -> 0x48571AB9 OK
+59: 1 -> 0xEB04ADE2 OK
--=20
1.7.10.4
--------------060001040407040305040404
Content-Type: text/x-patch;
name="0004-Add-A5-3-and-A5-4-ciphers.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="0004-Add-A5-3-and-A5-4-ciphers.patch"
1
0
---
include/osmocom/core/bits.h | 14 +++++++++++++-
include/osmocom/gsm/gsm_utils.h | 16 ++++++++++++++++
src/bits.c | 33 +++++++++++++++++++++++++++++++++
tests/bits/bitrev_test.c | 18 ++++++++++++++++--
tests/bits/bitrev_test.ok | 1 +
5 files changed, 79 insertions(+), 3 deletions(-)
diff --git a/include/osmocom/core/bits.h b/include/osmocom/core/bits.h
index 4c68532..bf79445 100644
--- a/include/osmocom/core/bits.h
+++ b/include/osmocom/core/bits.h
@@ -2,7 +2,7 @@
#define _OSMO_BITS_H
#include <stdint.h>
-
+#include <stddef.h>
/*! \defgroup bits soft, unpacked and packed bits
* @{
*/
@@ -73,6 +73,18 @@ 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 */
+uint16_t rol16(uint16_t in, unsigned shift);
+
+/* return 2 bytes from a given array glued into single uint16_t */
+uint16_t osmo_get2bytes(const uint8_t *a);
+
+/* convert uint64_t into array of 8 bytes in out */
+void osmo_64pack2pbit(uint64_t in, pbit_t *out);
+
/*! @} */
#endif /* _OSMO_BITS_H */
diff --git a/include/osmocom/gsm/gsm_utils.h b/include/osmocom/gsm/gsm_utils.h
index cdbac87..f215c7b 100644
--- a/include/osmocom/gsm/gsm_utils.h
+++ b/include/osmocom/gsm/gsm_utils.h
@@ -85,6 +85,22 @@ static inline int ms_cm2_a5n_support(uint8_t *cm2, int n) {
}
}
+/* According to GSM 04.08 Chapter 10.5.1.7 */
+static inline int ms_cm3_a5n_support(uint8_t *cm3, int n) {
+ switch (n) {
+ case 4: return (cm3[0] & (1<<0)) ? 1 : 0;
+ case 5: return (cm3[0] & (1<<1)) ? 1 : 0;
+ case 6: return (cm3[0] & (1<<2)) ? 1 : 0;
+ case 7: return (cm3[0] & (1<<3)) ? 1 : 0;
+ default:
+ return 0;
+ }
+}
+
+static inline int ms_a5n_support(uint8_t *cm, int n) {
+ return ((n < 4) ? ms_cm2_a5n_support(cm, n) : ms_cm3_a5n_support(cm, n));
+}
+
/* According to GSM 04.08 Chapter 10.5.2.29 */
static inline int rach_max_trans_val2raw(int val) { return (val >> 1) & 3; }
static inline int rach_max_trans_raw2val(int raw) {
diff --git a/src/bits.c b/src/bits.c
index 6be6d7a..41c46df 100644
--- a/src/bits.c
+++ b/src/bits.c
@@ -211,4 +211,37 @@ void osmo_revbytebits_buf(uint8_t *buf, int len)
}
}
+void osmo_revbytes_buf(uint8_t *buf, size_t len)
+{
+ uint8_t *end = buf + len - 1, tmp;
+
+ while (buf < end) {
+ tmp = *buf;
+ *buf++ = *end;
+ *end-- = tmp;
+ }
+}
+
+/* left circular shift */
+uint16_t rol16(uint16_t in, unsigned shift)
+{
+ return (in << shift) | (in >> (16 - shift));
+}
+
+/* return 2 bytes from a given array glued into single uint16_t */
+uint16_t osmo_get2bytes(const uint8_t *a)
+{ /* UNSAFE! NO out-of-bounds access check. Do NOT use unless you know what you are doing! */
+ return (uint16_t)((((uint16_t)a[0]) << 8) + (uint16_t)a[1]);
+}
+
+/* convert uint64_t into array of 8 bytes in out */
+void osmo_64pack2pbit(uint64_t in, pbit_t *out)
+{
+ int i;
+ for (i = 7; i >=0; i--) {
+ out[i] = in & 0xFF;
+ in >>= 8;
+ }
+}
+
/*! @} */
diff --git a/tests/bits/bitrev_test.c b/tests/bits/bitrev_test.c
index 5eca990..938d261 100644
--- a/tests/bits/bitrev_test.c
+++ b/tests/bits/bitrev_test.c
@@ -1,4 +1,4 @@
-
+#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@@ -12,7 +12,7 @@ static const uint8_t exp_out[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x0
int main(int argc, char **argv)
{
- uint8_t out[ARRAY_SIZE(input)];
+ uint8_t out[ARRAY_SIZE(input)], test[8];
unsigned int offs;
for (offs = 0; offs < sizeof(out); offs++) {
@@ -32,5 +32,19 @@ int main(int argc, char **argv)
printf("\n");
}
+ printf("checking bit packer... ");
+ uint64_t _test = ((uint64_t)rand() << 32) + rand();
+ osmo_64pack2pbit(_test, test);
+ char s[18], *p;
+ snprintf(s, 17, "%.16" PRIx64, _test);
+ p = osmo_hexdump_nospc(test, 8);
+ if (0 != memcmp(s, p, 8)) {
+ printf ("%s\t", s);
+ printf ("%s\t", p);
+ printf("FAILED!\n");
+ return 2;
+ }
+ printf("OK\n");
+
return 0;
}
diff --git a/tests/bits/bitrev_test.ok b/tests/bits/bitrev_test.ok
index 47f402f..8a5fc6e 100644
--- a/tests/bits/bitrev_test.ok
+++ b/tests/bits/bitrev_test.ok
@@ -22,3 +22,4 @@ REVERSED: 02 01
INORDER: 80
REVERSED: 01
+checking bit packer... OK
--
1.7.10.4
--------------060001040407040305040404
Content-Type: text/x-patch;
name="0002-Add-KASUMI-implementation.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="0002-Add-KASUMI-implementation.patch"
1
0
Hackito Ergo Sum 2013 -- Call For Paper -- HES2013 CFP
** http://hackitoergosum.org **
2-4 May 2013 / Paris / France
11111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111
11111111111111111000000111111111111111111000000111111111111111111
11111111111111111000000111111111111111111000000111111111111111111
11111111111111111000000111111111111111111000000111111111111111111
11111111111111111000000111111111111111111000000111111111111111111
11111111111000000000000000000000000000000000000000000111111111111
11111111111000000000000000000000000000000000000000000111111111111
11111111111000000000000000000000000000000000000000000111111111111
11111111111000000000000000000000000000000000000000000111111111111
11111000000000000111111111111000000111111111111000000000000111111
11111000000000000111111111111000000111111111111000000000000111111
11111000000000000111111111111000000111111111111000000000000111111
11111000000000000111111111111000000111111111111000000000000111111
11111000000000000000000000000000000000000000000000000000000111111
11111000000000000000000000000000000000000000000000000000000111111
11111000000000000000000000000000000000000000000000000000000111111
11111000000000000000000000000000000000000000000000000000000111111
11111000000000000000000000000000000000000000000000000000000111111
11111000000000000000000000000000000000000000000000000000000111111
11111000000000000000000000000000000000000000000000000000000111111
11111000000111111000000111111000000111111000000111111000000111111
11111000000111111000000111111000000111111000000111111000000111111
11111000000111111000000111111000000111111000000111111000000111111
11111000000111111000000111111000000111111000000111111000000111111
11111111111000000111111000000111111000000111111000000111111111111
11111111111000000111111000000111111000000111111000000111111111111
11111111111000000111111000000111111000000111111000000111111111111
11111111111000000111111000000111111000000111111000000111111111111
11111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111
111111111111111111111111111111111111111111111
111111111111111111111111111111111111111111111 HES 2013
111111111111111111111111111111111111111111111 Paris, 2-4 May 2013
111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111
11111111111111111111111111111111111111111111111111111111111111111
--[ Synopsis:
Hackito Ergo Sum is an international conference focused on
security and hacking breakthroughs from many different
perspectives: corporate, hackers, industry, governments,
academics. Diversity and creativity in this domain are the key
words. HES2013 will have for its 4th edition some of the best
hacking talents in the world.
--[ Venue:
Hackito Ergo Sum 2013 will take place in Paris, France from the
2nd to the 4th of May, 2013, at Cite des sciences et de
l'industrie.
Address:
30 Avenue Corentin Cariou
75019 Paris
FRANCE
It is easily accessible via public transport with metro line 7,
at the Porte de la Villette, or by car using orbital motorway
(Multiverse level I / 61d8327deb882cf99).
Map and pictures are available here:
https://plus.google.com/110203164083435669962/about?gl=fr&hl=fr
--[ Introduction:
It's 2013 and we're alive! Awesome! Let's have a look at what
hacking future we have.
From the tectonic shift of forces from the West to the East, the
rise of military-powered attack software, and the evermore
sophisticated games of spooks, yesteryear's "cloak-and-dagger"
has come to the hacking world. This is a game of mapping
individuals and their influences at hacking conferences,
cancelling Visas of potential future-enemies in a the
foreshadowed "cyber-war", buying AND selling 0-days to identify
hidden networks of the underground, raising their filternet,
establishing red-button routers, identifying challenge winners
and profiling their hacking methodologies, and owning botnets for
sheer firepower.
We are in deep shit.
But hey, wait, that's FUN! No matter the forces that threaten our
liberties and trace our modems, we still have not and will not
loose our passion to tinker, to explore, to peal back the layers
of technological reality. We have not lost the Will to Hack.
For the rest of us, we're still all alike when we read media and
government propaganda: hackers intruding everything and waging
cyberwar, panic-spreading, FUD-driven definition of us as bad
guys, mafia, and evil-doers. All alike.
Our world is the world of hack, of the beauty of the baud and the
sheer madness of the screaming electron, (respect to Phrack and
The Mentor), and we won't change it for anything. Because it is
the most immense and yet most fragile human creation; it is our
world and we own it.
If a khaki-pants warmonger or a 3-piece suit master-of-the-world
wannabee wants to confiscate it from us, restrict our freedom,
ban our activities, turn the public opinion to follow their
agenda, well, they may try, they may block some of us, they may
even put some of us out of the circuit, but they can't replicate
our passion, our energy, our love of what we do, our insane
attention to the detail and effectiveness of our techniques.
Because in end, we're all alike. And we're damn ALIVE!
Now for the enlightened, our shared future is full of
opportunities, the humbling discoveries of others, and open
projects that inspire us to join and create together. Our futures
is limited only by our capability to collaborate in great
projects, and also to leave space for the others. TOR is kicking
and OONI roaring; TRAILS offers OS privacy and security for who
needs it; many conferences are being born everywhere; Frida IRE
is an amazing reversing tool; Qubes provides long sought-out
tough security; plenty of new tools are being released to reveal
unique weaknesses and failures. This furious creativity and
ecosystem gives birth to world-changing start-ups, vital
resources, must-have open source projects, and of course, one of
the most open and creative cultures. All this, against all odds,
exists and develops without bias nor prejudice. Just like it is.
So for Hackito Ergo Sum 2013, we want to see you exactly in the
same way: just like you are (ALERT: if you think about food here
you need to smash your TV and DNS bind youtube.com to
github.com) new or old school, skiddie or security professional,
n00b or l33t, to share and show diversity, and, most of all, to
LEARN. It is therefore our utmost pleasure to welcome you to this
4th edition of HES!
Since 2010, the goal of Hackito Ergo Sum has been to promote
security research, broaden public awareness, and create an open
forum so that communication between researchers, the security
industry, experts, and the public can happen.
Like every year, we offer the possibility to hackers, security
researchers, students, and academics to present their projects
and research.
During the three days of HES, research conferences, solutions
presentations, panels, debates, AND PARTIES will aim to share,
mix, and determine the future of IT security & hacking.
--[ Content of the Research Track:
We are expecting submissions in English only.
The format will be 45 minutes presentation + 10 minutes Q&A.
Please note that talks whose content will be judged too
commercial or biased toward a given vendor will be rejected.
We will have slots for AnonConf -- that is, speaking about topics
for which improved anonymity and freedom of speech is imperative.
(Write Anon in email, use PGP).
We will also consider new and first time presenters, so that
anyone can get his/her foot in the door. Don't be shy, just say
"It's one of my first conf submission", and we'll be kind.
For the research track, preference will be given to offensive,
innovative, and highly technical proposals.
As a suggestion, we would love to see things about:
* SIPRnet, NIPRnet & other defense networks funny stories
* LTE radio and signaling abuses and/or real life hacks
* 4G, Diameter & GRX/IPX hacks
* Exploit style stylography
* CTF Antiforensics: Detection of Intelligence gathering CTFs
* Government filternets (formerly known as Internet, R.I.P)
* x86/64 & Non-x86 exploitation
* New methods to detect software bugs (source or binary based)
* Funky Kernel land exploits
* Offensive forensics
* Current kernel buffer overflows exploit techniques for your
grandmother
* SAT solving your ROP gadgeting and chaining
* Real life hack automation (yeah, default passwords and reuse DO
work better than overflows in a kernel 3.x world)
* IOS vuln research & vulndev
* Identifying tainted 0-day sploits for government-sponsored grey
market tracing
* Mobile Botnets and Overlay networks-based C&C
* IPv6 & "Carrier Grade NATs" advances
* M2M Machine Type Communication
* Sound hacking: binaural, brown, ...
* UEFI malware writing
* Android, RIM, Bada, IOS Mobile applications & OS hacks
* TPM and Secure Boot kitting & knifing
* FPGA backdoors
* Automated Hardware reverse engineering
* Hardware security & lockpicking in 2013
We will also have a Zero Day Show, as last year, at the end of
the conference so that people can share (love/kindness) or show
(salivate/envy) their new babies to the world. Prepare! Zombie
Exploitocalyps incoming :)
We highly encourage any other presentation topic, especially the
one we may not even imagine.
If you want to share skills on a specific subject during a
workshop, feel free to contact us.
--[ Submissions:
[*] Requested information:
Submissions must contain the following information:
* Speakers name or alias
* Presentation Title
* Description
* Needs: Internet? Others?
* Demo (Y/N)
* Company (name) or Independent? (optional)
* Address (optional)
* Phone (optional)
* Email (optional)
* Biography (optional)
We highly encourage and will favor presentations with demos.
Specify if submission contains any of the following information:
* Tool
* Slides
* Whitepaper
[*] How to submit:
Submit your presentation and materials by sending an email to:
hes-cfp(a)lists.hackitoergosum.org
--[ Dates:
2013-02-04 Call for Paper
2013-03-31 Submission Deadline
2013-04-04 Acceptance notification
2013-04-07 Program announcement
2013-05-02 Start of conference
2013-05-04 End of conference
--[ Program Committee:
The following program committee will review the submissions:
- Tavis Ormandy (Google) @taviso
- Mark Dowd (AzimuthSecurity) @mdowd
- Alex Rice (Facebook)
- Barnaby Jack (IOactive) @barnaby_jack
- Charlie Miller @0xcharlie
- David Litchfield (V3rity Software) @dlitchfield
- Nico Waisman (Immunity) @nicowaisman
- Philippe Langlois (P1 Security) @philpraxis
- Laurent Gaffie @laurentgaffie
- Julien Tinnes (Google)
- Brad Spendler (aka spender) (Grsecurity)
- Silvio Cesare (Deakin University) @silviocesare
- Carlos Sarraute (Core security)
- Itzik Kotler (aka izik) @itzikkotler
- Jason A. Donenfeld (ZX2C4) @zx2c4
- Rodrigo Branco (Intel) @bsdaemon
- Tim Shelton (HAWK Network Defense) @redsandbl4ck
- Ilja Van Sprundel (IOActive)
- Raoul Chiesa (tstf)
- Dhillon Andrew Kannabhiran (HITB) @hackinthebox
- Philip Petterson (aka Rebel)
- The Grugq (COSEINC) @thegrugq
- Emmanuel Gadaix (TSTF) @gadaix
- Kugg (/tmp/lab)
- Harald Welte (gnumonks.org) @LaF0rge
- Van Hauser (THC)
- Fyodor Yarochkin @fygrave
- Gamma (THC, Teso) @GammaTHC
- Pipacs (Linux Kernel Page Exec Protection)
- Nico Golde (Qualcomm) @iamnion
--[ Fees:
Here is the list of prices for HES 2013:
* Corporate ticket: 480 EUR
* Security professionals: 160 EUR
* Non security professionals: 70 EUR
* Discount for students below 26: 50 EUR
* Discount for CVE/exploit publisher in 2012-2013: 50 EUR
* Volunteers (Must register, see below): 0 EUR
Corporate tickets are a great way to directly sponsor HES and
help us to continue to organize this event. Special privileges or
goodies may be offer with these tickets.
Buy your ticket online :
http://fr.amiando.com/NGBMIJM.html
--[ Sponsors:
We are looking for sponsors. Don't forget that sponsors are
essential for events like HES.
Entrance fees and sponsors fees are used to fund international
speakers travel costs and hosting facility. Please ask for the
HES2013 Sponsor Kit at
hes2013-orga(a)lists.hackitoergosum.org.
--[ Volunteers:
Volunteers who sign up before 2013-04-07 get free access and will
need to be present onsite two days before (2013-04-30) if no
further arrangement is made with the organization.
--[ Journalists:
Journalists are welcome, but are required to comply with simple
rules to ensure the mutual respect among adults we aim to bring
in Hackito. In particular, filming or taking pictures of
attendees without their prior agreement is absolutely prohibited.
"We shall respect privacy and people" is the only motto.
Register here: http://2013.hackitoergosum.org/press/
--[ Challenges
Of course, there will be an online challenge during the
conference, hosted and animated by Over The Wire. We will
announce the country of honor for that regard shortly.
We will also have a new Hacker & Vendors challenge:
-^-^-^- The Fuzzor -^-^-^-
This challenge will enable the ultimate test between offensive
and defensive people. If you think you can hack anything, you're
offensive. If you think your product is so secure it won't suffer
a hack, you're defensive. And we'll get the two groups to meet on
a neutral ground, in a never-done before fashion.
Hackers: Register to the conference and prepare your Hacking
tools.
Vendors: Prepare your software to be tested like never before.
We will give more details before the conference. This new
challenge will rock your underwear!
--[ Security Vacation Club - Hackito Tour
After Hackito Ergo Sum, we will need to rest from the intensity
of the conference.
That's why we're organizing a Hackito tour!
Beach, clubs, code, meeting great people and party. We will go
from Paris to Ibiza to Berlin and back to Paris. For the lucky
few, one sponsored Villa will host us in Ibiza. See you there.
--[ Anti-sexism and LGBTA Friendly:
This conference is open to any sex, any color, any genre, any
alienness, whatever it may be.
--[ Greetz:
We would like to thank the HES2013 Team, its reviewing committee
and all the volunteers for their time and dedication in making
this event a success.
We would also like to greet all the speakers of last year's
edition for the quality of their presentation and the great time
we shared in Paris: you are all most welcome back in Paris for
the 2013 edition.
Likewise, we'd like to thank last year's sponsors for their
unconditional support. Feel free to support us again for this
2013 edition.
Finally, we would like to thank all the people who participated
to last years edition: whatever different views of the world,
communication and exchange is probably what makes people human,
and that's why we make Hackito happen. See you all in May! Peace,
Love, Passion.
--[ Contact:
hes2013-orga(a)lists.hackitoergosum.org
Please submit via hes-cfp(a)lists.hackitoergosum.org
Hackito Ergo Sum 2013 conference - http://hackitoergosum.org
-- [ Social Media:
Keep in touch with the HES Organization via Twitter!
Website: http://2013.hackitoergosum.org
@hesconference on Twitter ! - https://twitter.com/hesconference
-[EOF]-
2
1
i have a motorola c118 and running osmocon in raspberry. Am using the
uart available in gpio pins. What are the ideal settings in terms of
baud rate to allow communication,as i can't get hello world
working.the cable is ok since when i short tx and rx,and use minicom
whatever i type on the keyboard appears on minicom.
Thanks
1
0
Hi All,
as I've just been made aware of by a business contact, there is a
NEWSDR'13 workshop which, among other things, has OsmocomBB and OpenBSC
on the list of topics:
http://ecewp.ece.wpi.edu/wordpress/sdr-boston/newsdr-13/call-for-papers/
Did anyone ever hear of this workshop? Did the organizers ever make
contact with us? I'm a bit surprised that somebody organizes a workshop
with "our" projects on the agenda without even sending the CfP to us.
Or maybe I just missed it?
In case somebody is submitting a paper there: Please make sure to
coordinate here in order to avoid different developers/contributors from
submitting similar/related topics.
Regards,
Harald
--
- Harald Welte <laforge(a)gnumonks.org> http://laforge.gnumonks.org/
============================================================================
"Privacy in residential applications is a desirable marketing option."
(ETSI EN 300 175-7 Ch. A6)
2
1