From 579a7103a1738df11009d75b7bf02559e711a1cb Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Mon, 16 Jun 2014 14:59:30 +0200 Subject: gsm: Add Kasumi cipher implementation Submitted-by: Max Signed-off-by: Sylvain Munaut --- .gitignore | 1 + include/Makefile.am | 4 +- include/osmocom/gsm/kasumi.h | 48 +++++++++++ src/gsm/Makefile.am | 2 +- src/gsm/kasumi.c | 186 +++++++++++++++++++++++++++++++++++++++++++ tests/Makefile.am | 8 +- tests/kasumi/kasumi_test.c | 136 +++++++++++++++++++++++++++++++ tests/kasumi/kasumi_test.ok | 10 +++ tests/testsuite.at | 6 ++ 9 files changed, 397 insertions(+), 4 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 3fa1bbcf..12990282 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/Makefile.am b/include/Makefile.am index 48ca7ea2..74396de0 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -108,7 +108,9 @@ nobase_include_HEADERS += \ osmocom/vty/vty.h endif -noinst_HEADERS = osmocom/core/timer_compat.h +noinst_HEADERS = \ + osmocom/core/timer_compat.h \ + osmocom/gsm/kasumi.h osmocom/core/bit%gen.h: osmocom/core/bitXXgen.h.tpl $(AM_V_GEN)$(MKDIR_P) $(dir $@) diff --git a/include/osmocom/gsm/kasumi.h b/include/osmocom/gsm/kasumi.h new file mode 100644 index 00000000..8ecf65f6 --- /dev/null +++ b/include/osmocom/gsm/kasumi.h @@ -0,0 +1,48 @@ +/* + * KASUMI header + * + * See kasumi.c for details + * The parameters are described in TS 135 202. + */ + +#pragma once + +#include + +/*! \brief Single iteration of KASUMI cipher + * \param[in] P Block, 64 bits to be processed in this round + * \param[in] KLi1 Expanded subkeys + * \param[in] KLi2 Expanded subkeys + * \param[in] KOi1 Expanded subkeys + * \param[in] KOi2 Expanded subkeys + * \param[in] KOi3 Expanded subkeys + * \param[in] KIi1 Expanded subkeys + * \param[in] KIi2 Expanded subkeys + * \param[in] KIi3 Expanded subkeys + * \returns processed block of 64 bits + */ +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); + +/*! \brief Implementation of the KGCORE algorithm (used by A5/3, A5/4, GEA3, GEA4 and ECSD) + * \param[in] CA + * \param[in] cb + * \param[in] cc + * \param[in] cd + * \param[in] ck 8-bytes long key + * \param[out] co cl-dependent + * \param[in] cl + */ +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 - see TS 135 202 for details + * \param[in] key (128 bits) as array of bytes + * \param[out] KLi1 Expanded subkeys + * \param[out] KLi2 Expanded subkeys + * \param[out] KOi1 Expanded subkeys + * \param[out] KOi2 Expanded subkeys + * \param[out] KOi3 Expanded subkeys + * \param[out] KIi1 Expanded subkeys + * \param[out] KIi2 Expanded subkeys + * \param[out] KIi3 Expanded subkeys + */ +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 46698cdc..94729c91 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 00000000..d5d78a74 --- /dev/null +++ b/src/gsm/kasumi.c @@ -0,0 +1,186 @@ +/* Kasumi cipher and KGcore functions */ + +/* (C) 2013 by Max + * + * 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 +#include +#include + +/* 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 ^= osmo_rol16(tmp, 1); + + tmp = R | KLi2[i]; + L ^= osmo_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 */ +} + +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] = osmo_rol16(osmo_load16be(key + i * 2), 1); + KLi2[i] = C[(i + 2) & 0x7]; + + KOi1[i] = osmo_rol16(osmo_load16be(key + ((2 * (i + 1)) & 0xE)), 5); + KOi2[i] = osmo_rol16(osmo_load16be(key + ((2 * (i + 5)) & 0xE)), 8); + KOi3[i] = osmo_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); + + /* i is a block counter */ + for (i = 0; i < cl / 64 + 1; i++) { + BLK = _kasumi(A ^ i ^ BLK, KLi1, KLi2, KOi1, KOi2, KOi3, KIi1, KIi2, KIi3); + osmo_store64be(BLK, co + (i * 8)); + } +} diff --git a/tests/Makefile.am b/tests/Makefile.am index c6216d50..ea4bf9ca 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,10 @@ 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 +kasumi_kasumi_test_LDFLAGS = -static + 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 +106,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 00000000..9101407d --- /dev/null +++ b/tests/kasumi/kasumi_test.c @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +/* 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 00000000..2c2af4c7 --- /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 9124f251..7ce2ee80 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 -- cgit v1.2.3