lists.osmocom.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

gerrit-log

Thread Start a new thread
Download
Threads by month
  • ----- 2026 -----
  • November
  • 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
gerrit-log@lists.osmocom.org

June 2023

  • 1 participants
  • 2480 discussions
[XL] Change in libosmocore[master]: libosmogsm: Add support for TUAK authentication algorithm
by laforge 02 Jun '23

02 Jun '23
laforge has submitted this change. ( https://gerrit.osmocom.org/c/libosmocore/+/33094 ) Change subject: libosmogsm: Add support for TUAK authentication algorithm ...................................................................... libosmogsm: Add support for TUAK authentication algorithm The TUAK algorithm is specified in 3GPP TS 35.231, 232 and 233 and intended as an alternative to MILENAGE. It's based around the cryptographic function of KeccakP1600, which is part of SHA-3. This patch adds support for TUAK to the libosmogsm authentication core API via 'struct osmo_auth_impl'. Unit tests covering the test cases from the 3GPP specification are added (and are all passing). Change-Id: Ib905b8d8bdf248e8299bf50666ee1bca8298433d --- A .checkpatch.conf M TODO-RELEASE M include/osmocom/crypt/auth.h M src/gsm/Makefile.am M src/gsm/auth_core.c A src/gsm/auth_tuak.c A src/gsm/tuak/KeccakP-1600-3gpp.c A src/gsm/tuak/KeccakP-1600-3gpp.h A src/gsm/tuak/tuak.c A src/gsm/tuak/tuak.h M tests/Makefile.am A tests/auth/tuak_test.c A tests/auth/tuak_test.ok 13 files changed, 1,205 insertions(+), 1 deletion(-) Approvals: Jenkins Builder: Verified fixeria: Looks good to me, approved diff --git a/.checkpatch.conf b/.checkpatch.conf new file mode 100644 index 0000000..46bf0eb --- /dev/null +++ b/.checkpatch.conf @@ -0,0 +1 @@ +--exclude ^src/gsm/tuak/KeccakP-1600-3gpp\.(c|h)$ diff --git a/TODO-RELEASE b/TODO-RELEASE index b239efa..acd1a61 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -16,3 +16,4 @@ libosmogsm ADD new osmo_sub_auth_data2 / osmo_auth_gen_vec2 / osmo_auth_gen_vec_auts2 libosmogsm MODIFY osmo_auth_impl callback function signature change. No known external users libosmogsm ADD osmo_auth_c2 +libosmogsm ADD OSMO_AUTH_ALG_TUAK diff --git a/include/osmocom/crypt/auth.h b/include/osmocom/crypt/auth.h index 0e9b502..f73a48b 100644 --- a/include/osmocom/crypt/auth.h +++ b/include/osmocom/crypt/auth.h @@ -33,6 +33,7 @@ OSMO_AUTH_ALG_XOR_3G, OSMO_AUTH_ALG_MILENAGE, OSMO_AUTH_ALG_XOR_2G, + OSMO_AUTH_ALG_TUAK, _OSMO_AUTH_ALG_NUM, }; /* Backwards-compatibility. We used to call XOR-3G just "XOR" which became ambiguous when diff --git a/src/gsm/Makefile.am b/src/gsm/Makefile.am index ca850d2..cbbdcc0 100644 --- a/src/gsm/Makefile.am +++ b/src/gsm/Makefile.am @@ -15,6 +15,8 @@ milenage/common.h milenage/crypto.h milenage/includes.h \ milenage/milenage.h +noinst_HEADERS += tuak/KeccakP-1600-3gpp.h tuak/tuak.h + noinst_LTLIBRARIES = libgsmint.la lib_LTLIBRARIES = libosmogsm.la @@ -30,6 +32,7 @@ auth_milenage.c milenage/aes-encblock.c gea.c \ milenage/aes-internal.c milenage/aes-internal-enc.c \ milenage/milenage.c gan.c ipa.c gsm0341.c apn.c \ + tuak/KeccakP-1600-3gpp.c tuak/tuak.c auth_tuak.c \ gsup.c gsup_sms.c gprs_gea.c gsm0503_conv.c oap.c gsm0808_utils.c \ gsm23003.c gsm23236.c mncc.c bts_features.c oap_client.c \ gsm29118.c gsm48_rest_octets.c cbsp.c gsm48049.c \ diff --git a/src/gsm/auth_core.c b/src/gsm/auth_core.c index ad5967d..6972cb7 100644 --- a/src/gsm/auth_core.c +++ b/src/gsm/auth_core.c @@ -328,6 +328,7 @@ { OSMO_AUTH_ALG_XOR_3G, "XOR-3G" }, { OSMO_AUTH_ALG_MILENAGE, "MILENAGE" }, { OSMO_AUTH_ALG_XOR_2G, "XOR-2G" }, + { OSMO_AUTH_ALG_TUAK, "TUAK" }, { 0, NULL } }; diff --git a/src/gsm/auth_tuak.c b/src/gsm/auth_tuak.c new file mode 100644 index 0000000..05fbf69 --- /dev/null +++ b/src/gsm/auth_tuak.c @@ -0,0 +1,207 @@ +/*! \file auth_tuak.c + * GSM/GPRS/3G authentication core infrastructure */ +/* + * (C) 2023 by Harald Welte <laforge(a)osmocom.org> + * + * All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ + * + * 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. + * + */ + +/* NOTE: TUAK offers a lot of size variability in terms of size of length of MAC_A, MAC_S, + * but this is not used within 3GPP. The different sizes of Kc and RES are handled via + * osmo_sub_auth_data2. */ + +#include <errno.h> +#include <osmocom/crypt/auth.h> +#include <osmocom/core/bits.h> +#include "tuak/tuak.h" + +/*! \addtogroup auth + * @{ + */ + +static const uint8_t *gen_opc_if_needed(const struct osmo_sub_auth_data2 *aud, uint8_t *gen_opc) +{ + int rc; + + /* Check if we only know OP and compute OPC if required */ + if (aud->type == OSMO_AUTH_TYPE_UMTS && aud->u.umts.opc_is_op) { + rc = tuak_opc_gen(gen_opc, aud->u.umts.k, aud->u.umts.k_len, aud->u.umts.opc); + if (rc < 0) + return NULL; + return gen_opc; + } + + return aud->u.umts.opc; +} + +static int tuak_gen_vec(struct osmo_auth_vector *vec, + struct osmo_sub_auth_data2 *aud, + const uint8_t *_rand) +{ + size_t res_len = vec->res_len; + uint64_t next_sqn; + uint8_t gen_opc[32]; + const uint8_t *opc; + uint8_t sqn[6]; + uint64_t ind_mask; + uint64_t seq_1; + + switch (vec->res_len) { + case 4: + case 8: + case 16: + break; + default: + return -EINVAL; + } + + OSMO_ASSERT(aud->algo == OSMO_AUTH_ALG_TUAK); + + if (aud->u.umts.k_len != 16 && aud->u.umts.k_len != 32) + return -EINVAL; + if (aud->u.umts.opc_len != 32) + return -EINVAL; + + opc = gen_opc_if_needed(aud, gen_opc); + if (!opc) + return -1; + + /* Determine next SQN, according to 3GPP TS 33.102: + * SQN consists of SEQ and a lower significant part of IND bits: + * + * |----------SEQ------------| + * |------------------------SQN-----------| + * |-----IND----| + * + * The IND part is used as "slots": e.g. a given HLR client will always + * get the same IND part, called ind here, with incrementing SEQ. In + * the USIM, each IND slot enforces that its SEQ are used in ascending + * order -- as long as that constraint is satisfied, the SQN may jump + * forwards and backwards. For example, for ind_bitlen == 5, asking the + * USIM for SQN = 32, 64, 33 is allowed, because 32 and 64 are + * SEQ || (ind == 0), and though 33 is below 64, it is ind == 1 and + * allowed. Not allowed would be 32, 96, 64, because 64 would go + * backwards after 96, both being ind == 0. + * + * From the last used SQN, we want to increment SEQ + 1, and then pick + * the matching IND part. + * + * IND size is suggested in TS 33.102 as 5 bits. SQN is 48 bits long. + * If ind_bitlen is passed too large here, the algorithms will break + * down. But at which point should we return an error? A sane limit + * seems to be ind_bitlen == 10, but to protect against failure, + * limiting ind_bitlen to 28 is enough, 28 being the number of bits + * suggested for the delta in 33.102, which is discussed to still + * require 2^15 > 32000 authentications to wrap the SQN back to the + * start. + * + * Note that if a caller with ind == 1 generates N vectors, the SQN + * stored after this will reflect SEQ + N. If then another caller with + * ind == 2 generates another N vectors, this will then use SEQ + N + * onwards and end up with SEQ + N + N. In other words, most of each + * SEQ's IND slots will remain unused. When looking at SQN being 48 + * bits wide, after dropping ind_bitlen (say 5) from it, we will still + * have a sequence range of 2^43 = 8.8e12, eight trillion sequences, + * which is large enough to not bother further. With the maximum + * ind_bitlen of 28 enforced below, we still get more than 1 million + * sequences, which is also sufficiently large. + * + * An ind_bitlen of zero may be passed from legacy callers that are not + * aware of the IND extension. For these, below algorithm works out as + * before, simply incrementing SQN by 1. + * + * This is also a mechanism for tools like the osmo-auc-gen to directly + * request a given SQN to be used. With ind_bitlen == 0 the caller can + * be sure that this code will increment SQN by exactly one before + * generating a tuple, thus a caller would simply pass + * { .ind_bitlen = 0, .ind = 0, .sqn = (desired_sqn - 1) } + */ + + if (aud->u.umts.ind_bitlen > OSMO_MILENAGE_IND_BITLEN_MAX) + return -2; + + seq_1 = 1LL << aud->u.umts.ind_bitlen; + ind_mask = ~(seq_1 - 1); + + /* the ind index must not affect the SEQ part */ + if (aud->u.umts.ind >= seq_1) + return -3; + + /* keep the incremented SQN local until gsm_milenage() succeeded. */ + next_sqn = ((aud->u.umts.sqn + seq_1) & ind_mask) + aud->u.umts.ind; + + osmo_store64be_ext(next_sqn, sqn, 6); + + tuak_generate(opc, aud->u.umts.amf, aud->u.umts.k, aud->u.umts.k_len, + sqn, _rand, vec->autn, vec->ik, vec->ck, vec->res, &res_len); + + /* generate the GSM Kc + SRES values using C2 + C3 functions */ + osmo_auth_c3(vec->kc, vec->ck, vec->ik); + osmo_auth_c2(vec->sres, vec->res, vec->res_len, 1); + + vec->auth_types = OSMO_AUTH_TYPE_UMTS | OSMO_AUTH_TYPE_GSM; + + /* for storage in the caller's AUC database */ + aud->u.umts.sqn = next_sqn; + + return 0; +} + +static int tuak_gen_vec_auts(struct osmo_auth_vector *vec, + struct osmo_sub_auth_data2 *aud, + const uint8_t *auts, const uint8_t *rand_auts, + const uint8_t *_rand) +{ + uint8_t sqn_out[6]; + uint8_t gen_opc[32]; + const uint8_t *opc; + int rc; + + OSMO_ASSERT(aud->algo == OSMO_AUTH_ALG_TUAK); + + if (aud->u.umts.k_len != 16 && aud->u.umts.k_len != 32) + return -EINVAL; + if (aud->u.umts.opc_len != 32) + return -EINVAL; + + opc = gen_opc_if_needed(aud, gen_opc); + + rc = tuak_auts(opc, aud->u.umts.k, sizeof(aud->u.umts.k), rand_auts, auts, sqn_out); + if (rc < 0) + return rc; + + aud->u.umts.sqn_ms = osmo_load64be_ext(sqn_out, 6) >> 16; + /* Update our "largest used SQN" from the USIM -- milenage_gen_vec() + * below will increment SQN. */ + aud->u.umts.sqn = aud->u.umts.sqn_ms; + + return tuak_gen_vec(vec, aud, _rand); +} + +static struct osmo_auth_impl tuak_alg = { + .algo = OSMO_AUTH_ALG_TUAK, + .name = "TUAK (libosmogsm built-in)", + .priority = 1000, + .gen_vec = &tuak_gen_vec, + .gen_vec_auts = &tuak_gen_vec_auts, +}; + +static __attribute__((constructor)) void on_dso_load_tuak(void) +{ + osmo_auth_register(&tuak_alg); +} + +/*! @} */ diff --git a/src/gsm/tuak/KeccakP-1600-3gpp.c b/src/gsm/tuak/KeccakP-1600-3gpp.c new file mode 100644 index 0000000..3f5e2ad --- /dev/null +++ b/src/gsm/tuak/KeccakP-1600-3gpp.c @@ -0,0 +1,176 @@ +/* ----------------------------------------------------------------------- + * code extracted from 3GPP TS 35.231, annex E for Keccak core functions + * https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.… + *-----------------------------------------------------------------------*/ + +/* This code may be freely used or adapted. +*/ + +#include "KeccakP-1600-3gpp.h" + + +const uint8_t Rho[25] = {0,1,62,28,27,36,44,6,55,20,3,10,43,25,39,41,45, + 15,21,8,18,2,61,56,14}; + +const uint8_t Pi[25] = {0,6,12,18,24,3,9,10,16,22,1,7,13,19,20,4,5,11,17, + 23,2,8,14,15,21}; + +const uint8_t Iota[24] = {1,146,218,112,155,33,241,89,138,136,57,42,187,203, + 217,83,82,192,26,106,241,208,33,120}; + +#define ROTATE64(value, n) \ +((((uint64_t)(value))<<(n)) | (((uint64_t)(value))>>(64-(n)))) + +/* --------------------------------------------------------------------- + 64-bit version of Keccak_f(1600) + --------------------------------------------------------------------- +*/ +void Keccak_f_64(uint64_t s[25]) +{ uint64_t t[5]; + uint8_t i, j, round; + + for(round=0; round<24; ++round) + { /* Theta function */ + for(i=0; i<5; ++i) + t[i] = s[i] ^ s[5+i] ^ s[10+i] ^ s[15+i] ^ s[20+i]; + for(i=0; i<5; ++i, s+=5) + { s[0] ^= t[4] ^ ROTATE64(t[1], 1); + s[1] ^= t[0] ^ ROTATE64(t[2], 1); + s[2] ^= t[1] ^ ROTATE64(t[3], 1); + s[3] ^= t[2] ^ ROTATE64(t[4], 1); + s[4] ^= t[3] ^ ROTATE64(t[0], 1); + } + s -= 25; + + /* Rho function */ + for(i=1; i<25; ++i) + s[i] = ROTATE64(s[i], Rho[i]); + + /* Pi function */ + for(t[1] = s[i=1]; (j=Pi[i]) > 1; s[i]=s[j], i=j); + s[i] = t[1]; + + /* Chi function */ + for(i=0; i<5; ++i, s += 5) + { t[0] = (~s[1]) & s[2]; + t[1] = (~s[2]) & s[3]; + t[2] = (~s[3]) & s[4]; + t[3] = (~s[4]) & s[0]; + t[4] = (~s[0]) & s[1]; + for(j=0; j<5; ++j) s[j] ^= t[j]; + } + s -= 25; + + /* Iota function */ + t[0] = Iota[round]; + *s ^= (t[0] | (t[0]<<11) | (t[0]<<26) | (t[0]<<57)) + & 0x800000008000808BULL; /* set & mask bits 0,1,3,7,15,31,63 */ + } +} + + +/* --------------------------------------------------------------------- + 8-bit version of Keccak_f(1600) + --------------------------------------------------------------------- +*/ +void Keccak_f_8(uint8_t s[200]) +{ uint8_t t[40], i, j, k, round; + + for(round=0; round<24; ++round) + { /* Theta function */ + for(i=0; i<40; ++i) + t[i]=s[i]^s[40+i]^s[80+i]^s[120+i]^s[160+i]; + for(i=0; i<200; i+=8) + for(j = (i+32)%40, k=0; k<8; ++k) + s[i+k] ^= t[j+k]; + for(i=0; i<40; t[i] = (t[i]<<1)|j, i+=8) + for(j = t[i+7]>>7, k=7; k; --k) + t[i+k] = (t[i+k]<<1)|(t[i+k-1]>>7); + for(i=0; i<200; i+=8) + for(j = (i+8)%40, k=0; k<8; ++k) + s[i+k] ^= t[j+k]; + + /* Rho function */ + for(i=8; i<200; i+=8) + { for(j = Rho[i>>3]>>3, k=0; k<8; ++k) /* j:=bytes to shift, s->t */ + t[(k+j)&7] = s[i+k]; + for(j = Rho[i>>3]&7, k=7; k; --k) /* j:=bits to shift, t->s */ + s[i+k] = (t[k]<<j) | (t[k-1]>>(8-j)); + s[i] = (t[0]<<j) | (t[7]>>(8-j)); + } + + /* Pi function */ + for(k=8; k<16; ++k) t[k] = s[k]; /* =memcpy(t+8, s+8, 8) */ + for(i=1; (j=Pi[i])>1; i=j) + for(k=0; k<8; ++k) /* =memcpy(s+(i<<3), s+(j<<3), 8) */ + s[(i<<3)|k] = s[(j<<3)|k]; + for(k=0; k<8; ++k) /* =memcpy(s+(i<<3), t+8, 8) */ + s[(i<<3)|k] = t[k+8]; + + /* Chi function */ + for(i=0; i<200; i+=40) + { for(j=0; j<40; ++j) + t[j]=(~s[i+(j+8)%40]) & s[i+(j+16)%40]; + for(j=0; j<40; ++j) s[i+j]^=t[j]; + } + + /* Iota function */ + k = Iota[round]; + s[0] ^= k & 0x8B; /* bits 0, 1, 3, 7 */ + s[1] ^= (k<<3)&0x80; /* bit 15 */ + s[3] ^= (k<<2)&0x80; /* bit 31 */ + s[7] ^= (k<<1)&0x80; /* bit 63 */ + + } +} + +/* --------------------------------------------------------------------- + 32-bit version of Keccak_f(1600) + --------------------------------------------------------------------- +*/ +void Keccak_f_32(uint32_t s[50]) +{ uint32_t t[10]; + uint8_t i, j, round, k; + + for(round=0; round<24; ++round) + { /* Theta function */ + for(i=0; i<10; ++i) + t[i] = s[i] ^ s[10+i] ^ s[20+i] ^ s[30+i] ^ s[40+i]; + for(i=0; i<5; ++i) + for(j=8, k=2; ; j%=10, k=(k+2)%10) + { *s++ ^= t[j++] ^ ((t[k]<<1)|(t[k+1]>>31)); + *s++ ^= t[j++] ^ ((t[k+1]<<1)|(t[k]>>31)); + if(j==8) break; + } + s -= 50; + + /* Rho function */ + for(i=2; i<50; i+=2) + { k = Rho[i>>1] & 0x1f; + t[0] = (s[i+1] << k) | (s[i] >> (32-k)); + t[1] = (s[i] << k) | (s[i+1] >> (32-k)); + k = Rho[i>>1] >> 5; + s[i] = t[1-k], s[i+1] = t[k]; + } + + /* Pi function */ + for(i=2, t[0]=s[2], t[1]=s[3]; (j=(Pi[i>>1]<<1))>2; i=j) + s[i]=s[j], s[i+1]=s[j+1]; + s[i]=t[0], s[i+1]=t[1]; + + /* Chi function */ + for(i=0; i<5; ++i, s+=10) + { for(j=0; j<10; ++j) + t[j] = (~s[(j+2)%10]) & s[(j+4)%10]; + for(j=0; j<10; ++j) + s[j] ^= t[j]; + } + s -= 50; + + /* Iota function */ + t[0] = Iota[round]; + s[0] ^= (t[0] | (t[0]<<11) | (t[0]<<26)) & 0x8000808B; + s[1] ^= (t[0]<<25) & 0x80000000; + } +} + diff --git a/src/gsm/tuak/KeccakP-1600-3gpp.h b/src/gsm/tuak/KeccakP-1600-3gpp.h new file mode 100644 index 0000000..a23cc46 --- /dev/null +++ b/src/gsm/tuak/KeccakP-1600-3gpp.h @@ -0,0 +1,25 @@ +/* ----------------------------------------------------------------------- + * code extracted from 3GPP TS 35.231, annex E for Keccak core functions + * https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.… + *-----------------------------------------------------------------------*/ + +/* this is the trick to make the code cross-platform + * at least, Win32 / Linux */ + +#if defined(_WIN32) || defined(__WIN32__) +# include <windows.h> +# define EXPORTIT __declspec(dllexport) +#else +# define EXPORTIT +#endif + +#include <stdint.h> + +/*------------------------------------------------------------------------ + * KeccakP-1600-3gpp.h + *------------------------------------------------------------------------*/ + +EXPORTIT void Keccak_f_8 (uint8_t s[200]); +EXPORTIT void Keccak_f_32(uint32_t s[50]); +EXPORTIT void Keccak_f_64(uint64_t s[25]); + diff --git a/src/gsm/tuak/tuak.c b/src/gsm/tuak/tuak.c new file mode 100644 index 0000000..c044a37 --- /dev/null +++ b/src/gsm/tuak/tuak.c @@ -0,0 +1,372 @@ +/* (C) 2023 by Harald Welte <laforge(a)osmocom.org> + * + * All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ + * + * 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. + */ + +#include <stdint.h> +#include <string.h> +#include <string.h> +#include <errno.h> + +#include <osmocom/core/utils.h> + +#include "KeccakP-1600-3gpp.h" + +/* TUAK authentication algorithm + * as proposed by 3GPP as an alternative to Milenage + * algorithm based on SHA-3 (more exactly its KeccakP-1600 permutation) + * see 3GPP TS 35.231, 232 and 233 */ + +static unsigned int g_keccak_iterations = 1; +static const char algoname[] = "TUAK1.0"; +const uint8_t zero16[16] = { 0, }; + +void tuak_set_keccak_iterations(unsigned int i) +{ + g_keccak_iterations = i; +} + +/* append data from 'input' to 'buf' at 'idx', reversing byte order */ +#define PUSH_DATA(buf, idx, input, nbytes) \ + for (int i = nbytes-1; i >= 0; i--) { \ + buf[idx++] = input[i]; \ + } + +/* like memcpy(), but reversing they order of bytes */ +void memcpy_reverse(uint8_t *dst, const uint8_t *src, size_t len) +{ + for (size_t i = 0; i < len; i++) + dst[i] = src[len-i-1]; +} + +static void tuak_core(uint8_t buf[200], const uint8_t *opc, uint8_t instance, const uint8_t *_rand, + const uint8_t *amf, const uint8_t *sqn, const uint8_t *k, uint8_t k_len_bytes, + unsigned int keccac_iterations) +{ + unsigned int idx = 0; + + PUSH_DATA(buf, idx, opc, 32); + buf[idx++] = instance; + PUSH_DATA(buf, idx, algoname, strlen(algoname)); /* without trailing NUL */ + PUSH_DATA(buf, idx, _rand, 16); + PUSH_DATA(buf, idx, amf, 2); + PUSH_DATA(buf, idx, sqn, 6); + PUSH_DATA(buf, idx, k, k_len_bytes); + memset(buf+idx, 0, 32-k_len_bytes); idx += 32-k_len_bytes; + buf[idx++] = 0x1f; + memset(buf+idx, 0, 38); idx += 38; + buf[idx++] = 0x80; + memset(buf+idx, 0, 64); idx += 64; + OSMO_ASSERT(idx == 200); + + for (unsigned int i = 0; i < keccac_iterations; i++) + Keccak_f_64((uint64_t *) buf); +} + +/** + * tuak_f1 - TUAK f1 algorithm + * @opc: OPc = 256-bit value derived from OP and K + * @k: K = 128-bit or 256-bit subscriber key + * @_rand: RAND = 128-bit random challenge + * @sqn: SQN = 48-bit sequence number + * @amf: AMF = 16-bit authentication management field + * @mac_a: Buffer for MAC-A = 64/128/256-bit network authentication code + * Returns: 0 on success, -1 on failure + */ +int tuak_f1(const uint8_t *opc, const uint8_t *k, uint8_t k_len_bytes, const uint8_t *_rand, + const uint8_t *sqn, const uint8_t *amf, uint8_t *mac_a, uint8_t mac_a_len_bytes, + unsigned int keccac_iterations) +{ + uint8_t buf[200]; + uint8_t instance = 0x00; + + switch (mac_a_len_bytes) { + case 8: + instance |= 0x08; + break; + case 16: + instance |= 0x10; + break; + case 32: + instance |= 0x20; + break; + default: + return -EINVAL; + } + + switch (k_len_bytes) { + case 16: + break; + case 32: + instance |= 0x01; + break; + default: + return -EINVAL; + } + + tuak_core(buf, opc, instance, _rand, amf, sqn, k, k_len_bytes, keccac_iterations); + + memcpy_reverse(mac_a, buf, mac_a_len_bytes); + + return 0; +} + +/** + * tuak_f1star - TUAK f1* algorithm + * @opc: OPc = 256-bit value derived from OP and K + * @k: K = 128-bit or 256-bit subscriber key + * @_rand: RAND = 128-bit random challenge + * @sqn: SQN = 48-bit sequence number + * @amf: AMF = 16-bit authentication management field + * @mac_s: Buffer for MAC-S = 64/128/256-bit resync authentication code + * Returns: 0 on success, -1 on failure + */ +int tuak_f1star(const uint8_t *opc, const uint8_t *k, uint8_t k_len_bytes, const uint8_t *_rand, + const uint8_t *sqn, const uint8_t *amf, uint8_t *mac_s, uint8_t mac_s_len_bytes, + unsigned int keccac_iterations) +{ + uint8_t buf[200]; + uint8_t instance = 0x80; + + switch (mac_s_len_bytes) { + case 8: + instance |= 0x08; + break; + case 16: + instance |= 0x10; + break; + case 32: + instance |= 0x20; + break; + default: + return -EINVAL; + } + + switch (k_len_bytes) { + case 16: + break; + case 32: + instance |= 0x01; + break; + default: + return -EINVAL; + } + + tuak_core(buf, opc, instance, _rand, amf, sqn, k, k_len_bytes, keccac_iterations); + + memcpy_reverse(mac_s, buf, mac_s_len_bytes); + + return 0; +} + +/** + * tuak_f2345 - TUAK f2, f3, f4, f5, algorithms + * @opc: OPc = 256-bit value derived from OP and K + * @k: K = 128/256-bit subscriber key + * @_rand: RAND = 128-bit random challenge + * @res: Buffer for RES = 32/64/128/256-bit signed response (f2), or %NULL + * @ck: Buffer for CK = 128/256-bit confidentiality key (f3), or %NULL + * @ik: Buffer for IK = 128/256-bit integrity key (f4), or %NULL + * @ak: Buffer for AK = 48-bit anonymity key (f5), or %NULL + * Returns: 0 on success, -1 on failure + */ +int tuak_f2345(const uint8_t *opc, const uint8_t *k, uint8_t k_len_bytes, + const uint8_t *_rand, uint8_t *res, uint8_t res_len_bytes, + uint8_t *ck, uint8_t ck_len_bytes, + uint8_t *ik, uint8_t ik_len_bytes, uint8_t *ak, unsigned int keccac_iterations) +{ + uint8_t buf[200]; + uint8_t instance = 0x40; + + switch (res_len_bytes) { + case 4: + break; + case 8: + instance |= 0x08; + break; + case 16: + instance |= 0x10; + break; + case 32: + instance |= 0x20; + break; + default: + return -EINVAL; + } + + switch (ck_len_bytes) { + case 16: + break; + case 32: + instance |= 0x04; + break; + default: + return -EINVAL; + } + + switch (ik_len_bytes) { + case 16: + break; + case 32: + instance |= 0x02; + break; + default: + return -EINVAL; + } + + switch (k_len_bytes) { + case 16: + break; + case 32: + instance |= 0x01; + break; + default: + return -EINVAL; + } + + tuak_core(buf, opc, instance, _rand, zero16, zero16, k, k_len_bytes, keccac_iterations); + + if (res) + memcpy_reverse(res, buf, res_len_bytes); + + if (ck) + memcpy_reverse(ck, buf + 32, ck_len_bytes); + + if (ik) + memcpy_reverse(ik, buf + 64, ik_len_bytes); + + if (ak) + memcpy_reverse(ak, buf + 96, 6); + + return 0; +} + +/** + * tuak_f5star - TUAK f5* algorithm + * @opc: OPc = 256-bit value derived from OP and K + * @k: K = 128/256-bit subscriber key + * @_rand: RAND = 128-bit random challenge + * @ak: Buffer for AK = 48-bit anonymity key (f5) + * Returns: 0 on success, -1 on failure + */ +int tuak_f5star(const uint8_t *opc, const uint8_t *k, uint8_t k_len_bytes, + const uint8_t *_rand, uint8_t *ak, unsigned int keccac_iterations) +{ + uint8_t buf[200]; + uint8_t instance = 0xc0; + + switch (k_len_bytes) { + case 16: + break; + case 32: + instance += 1; + break; + default: + return -EINVAL; + } + + tuak_core(buf, opc, instance, _rand, zero16, zero16, k, k_len_bytes, keccac_iterations); + + memcpy_reverse(ak, buf + 96, 6); + + return 0; +} + +/** + * tuak_generate - Generate AKA AUTN,IK,CK,RES + * @opc: OPc = 256-bit operator variant algorithm configuration field (encr.) + * @amf: AMF = 16-bit authentication management field + * @k: K = 128/256-bit subscriber key + * @sqn: SQN = 48-bit sequence number + * @_rand: RAND = 128-bit random challenge + * @autn: Buffer for AUTN = 128-bit authentication token + * @ik: Buffer for IK = 128/256-bit integrity key (f4), or %NULL + * @ck: Buffer for CK = 128/256-bit confidentiality key (f3), or %NULL + * @res: Buffer for RES = 32/64/128-bit signed response (f2), or %NULL + * @res_len: Max length for res; set to used length or 0 on failure + */ +void tuak_generate(const uint8_t *opc, const uint8_t *amf, const uint8_t *k, uint8_t k_len_bytes, + const uint8_t *sqn, const uint8_t *_rand, uint8_t *autn, uint8_t *ik, + uint8_t *ck, uint8_t *res, size_t *res_len) +{ + int i; + uint8_t mac_a[8], ak[6]; + + if (*res_len < 4) { + *res_len = 0; + return; + } + if (tuak_f1(opc, k, k_len_bytes, _rand, sqn, amf, mac_a, sizeof(mac_a), g_keccak_iterations) || + tuak_f2345(opc, k, k_len_bytes, _rand, res, *res_len, ck, 16, ik, 16, ak, g_keccak_iterations)) { + *res_len = 0; + return; + } + + /* AUTN = (SQN ^ AK) || AMF || MAC */ + for (i = 0; i < 6; i++) + autn[i] = sqn[i] ^ ak[i]; + memcpy(autn + 6, amf, 2); + memcpy(autn + 8, mac_a, 8); +} + + +/** + * tuak_auts - Milenage AUTS validation + * @opc: OPc = 256-bit operator variant algorithm configuration field (encr.) + * @k: K = 128/256-bit subscriber key + * @_rand: RAND = 128-bit random challenge + * @auts: AUTS = 112-bit authentication token from client + * @sqn: Buffer for SQN = 48-bit sequence number + * Returns: 0 = success (sqn filled), -1 on failure + */ +int tuak_auts(const uint8_t *opc, const uint8_t *k, uint8_t k_len_bytes, + const uint8_t *_rand, const uint8_t *auts, uint8_t *sqn) +{ + uint8_t amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */ + uint8_t ak[6], mac_s[8]; + int i; + + if (tuak_f5star(opc, k, k_len_bytes, _rand, ak, g_keccak_iterations)) + return -1; + for (i = 0; i < 6; i++) + sqn[i] = auts[i] ^ ak[i]; + if (tuak_f1star(opc, k, k_len_bytes, _rand, sqn, amf, mac_s, 8, g_keccak_iterations) || + memcmp(mac_s, auts + 6, 8) != 0) + return -1; + return 0; +} + +int tuak_opc_gen(uint8_t *opc, const uint8_t *k, uint8_t k_len_bytes, const uint8_t *op) +{ + uint8_t buf[200]; + uint8_t instance; + + switch (k_len_bytes) { + case 16: + instance = 0x00; + break; + case 32: + instance = 0x01; + break; + default: + return -EINVAL; + } + + tuak_core(buf, op, instance, zero16, zero16, zero16, k, k_len_bytes, g_keccak_iterations); + + memcpy_reverse(opc, buf, 32); + + return 0; +} diff --git a/src/gsm/tuak/tuak.h b/src/gsm/tuak/tuak.h new file mode 100644 index 0000000..1a80822 --- /dev/null +++ b/src/gsm/tuak/tuak.h @@ -0,0 +1,33 @@ +#pragma once +#include <stdint.h> + +/* low-level functions */ + +int tuak_f1(const uint8_t *opc, const uint8_t *k, uint8_t k_len_bytes, const uint8_t *_rand, + const uint8_t *sqn, const uint8_t *amf, uint8_t *mac_a, uint8_t mac_a_len_bytes, + unsigned int keccac_iterations); + +int tuak_f1star(const uint8_t *opc, const uint8_t *k, uint8_t k_len_bytes, const uint8_t *_rand, + const uint8_t *sqn, const uint8_t *amf, uint8_t *mac_s, uint8_t mac_s_len_bytes, + unsigned int keccac_iterations); + +int tuak_f2345(const uint8_t *opc, const uint8_t *k, uint8_t k_len_bytes, + const uint8_t *_rand, uint8_t *res, uint8_t res_len_bytes, + uint8_t *ck, uint8_t ck_len_bytes, + uint8_t *ik, uint8_t ik_len_bytes, uint8_t *ak, unsigned int keccac_iterations); + +int tuak_f5star(const uint8_t *opc, const uint8_t *k, uint8_t k_len_bytes, + const uint8_t *_rand, uint8_t *ak, unsigned int keccac_iterations); + +/* high-level API */ + +void tuak_set_keccak_iterations(unsigned int i); + +void tuak_generate(const uint8_t *opc, const uint8_t *amf, const uint8_t *k, uint8_t k_len_bytes, + const uint8_t *sqn, const uint8_t *_rand, uint8_t *autn, uint8_t *ik, + uint8_t *ck, uint8_t *res, size_t *res_len); + +int tuak_auts(const uint8_t *opc, const uint8_t *k, uint8_t k_len_bytes, + const uint8_t *_rand, const uint8_t *auts, uint8_t *sqn); + +int tuak_opc_gen(uint8_t *opc, const uint8_t *k, uint8_t k_len_bytes, const uint8_t *op); diff --git a/tests/Makefile.am b/tests/Makefile.am index c6027a9..8df9d56 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -10,7 +10,8 @@ check_PROGRAMS = timer/timer_test sms/sms_test ussd/ussd_test \ bits/bitrev_test a5/a5_test \ - conv/conv_test auth/milenage_test lapd/lapd_test \ + conv/conv_test auth/milenage_test auth/tuak_test \ + lapd/lapd_test \ gsm0808/gsm0808_test gsm0408/gsm0408_test \ gprs/gprs_test kasumi/kasumi_test gea/gea_test \ logging/logging_test codec/codec_test \ @@ -115,6 +116,10 @@ auth_milenage_test_SOURCES = auth/milenage_test.c auth_milenage_test_LDADD = $(top_builddir)/src/gsm/libosmogsm.la $(LDADD) +auth_tuak_test_SOURCES = auth/tuak_test.c +auth_tuak_test_LDADD = $(top_builddir)/src/gsm/libgsmint.la $(LDADD) +auth_tuak_test_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src + auth_xor2g_test_SOURCES = auth/xor2g_test.c auth_xor2g_test_LDADD = $(top_builddir)/src/gsm/libosmogsm.la $(LDADD) @@ -393,6 +398,7 @@ timer/timer_test.ok sms/sms_test.ok ussd/ussd_test.ok \ bits/bitrev_test.ok a5/a5_test.ok \ conv/conv_test.ok auth/milenage_test.ok ctrl/ctrl_test.ok \ + auth/tuak_test.ok \ auth/xor2g_test.ok \ lapd/lapd_test.ok \ gsm0408/gsm0408_test.ok gsm0408/gsm0408_test.err \ @@ -535,6 +541,8 @@ >$(srcdir)/ussd/ussd_test.ok auth/milenage_test \ >$(srcdir)/auth/milenage_test.ok + auth/tuak_test \ + >$(srcdir)/auth/tuak_test.ok comp128/comp128_test \ >$(srcdir)/comp128/comp128_test.ok lapd/lapd_test \ diff --git a/tests/auth/tuak_test.c b/tests/auth/tuak_test.c new file mode 100644 index 0000000..a00ab2c --- /dev/null +++ b/tests/auth/tuak_test.c @@ -0,0 +1,309 @@ + +#include <stdint.h> +#include <osmocom/core/utils.h> +#include "gsm/tuak/tuak.h" + +/* user-friendly test specification, uses hex-strings for all parameters for + * copy+pasting from the spec. */ +struct tuak_testspec { + const char *name; + struct { + const char *k; + const char *rand; + const char *sqn; + const char *amf; + const char *top; + unsigned int keccak_iterations; + } in; + struct { + const char *topc; + const char *f1; + const char *f1star; + const char *f2; + const char *f3; + const char *f4; + const char *f5; + const char *f5star; + } out; +}; + +static const struct tuak_testspec testspecs[] = { + { + .name = "TS 35.233 Section 6.3 Test Set 1", + .in = { + .k = "abababababababababababababababab", + .rand = "42424242424242424242424242424242", + .sqn = "111111111111", + .amf = "ffff", + .top = "5555555555555555555555555555555555555555555555555555555555555555", + .keccak_iterations = 1, + }, + .out = { + .topc = "bd04d9530e87513c5d837ac2ad954623a8e2330c115305a73eb45d1f40cccbff", + .f1 = "f9a54e6aeaa8618d", + .f1star = "e94b4dc6c7297df3", + .f2 = "657acd64", + .f3 = "d71a1e5c6caffe986a26f783e5c78be1", + .f4 = "be849fa2564f869aecee6f62d4337e72", + .f5 = "719f1e9b9054", + .f5star = "e7af6b3d0e38", + }, + }, { + .name = "TS 35.233 Section 6.4 Test Set 2", + .in = { + .k = "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0", + .rand = "0123456789abcdef0123456789abcdef", + .sqn = "0123456789ab", + .amf = "abcd", + .top = "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + .keccak_iterations = 1, + }, + .out = { + .topc = "305425427e18c503c8a4b294ea72c95d0c36c6c6b29d0c65de5974d5977f8524", + .f1 = "c0b8c2d4148ec7aa5f1d78a97e4d1d58", + .f1star = "ef81af7290f7842c6ceafa537fa0745b", + .f2 = "e9d749dc4eea0035", + .f3 = "a4cb6f6529ab17f8337f27baa8234d47", + .f4 = "2274155ccf4199d5e2abcbf621907f90", + .f5 = "480a9345cc1e", + .f5star = "f84eb338848c", + }, + }, { + .name = "TS 35.233 Section 6.5 Test Set 3", + .in = { + .k = "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0", + .rand = "0123456789abcdef0123456789abcdef", + .sqn = "0123456789ab", + .amf = "abcd", + .top = "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + .keccak_iterations = 1, + }, + .out = { + .topc = "305425427e18c503c8a4b294ea72c95d0c36c6c6b29d0c65de5974d5977f8524", + .f1 = "d97b75a1776065271b1e212bc3b1bf173f438b21e6c64a55a96c372e085e5cc5", + .f1star = "427bbf07c6e3a86c54f8c5216499f3909a6fd4a164c9fe235b1550258111b821", + .f2 = "07021c73e7635c7d", + .f3 = "4d59ac796834eb85d11fa148a5058c3c", + .f4 = "126d47500136fdc5ddfd14f19ebf16749ce4b6435323fbb5715a3a796a6082bd", + .f5 = "1d6622c4e59a", + .f5star = "f84eb338848c", + }, + }, { + .name = "TS 35.233 Section 6.6 Test Set 4", + .in = { + .k = "b8da837a50652d6ac7c97da14f6acc61", + .rand = "6887e55425a966bd86c9661a5fa72be8", + .sqn = "0dea2ee2c5af", + .amf = "df1e", + .top = "0952be13556c32ebc58195d9dd930493e12a9003669988ffde5fa1f0fe35cc01", + .keccak_iterations = 1, + }, + .out = { + .topc = "2bc16eb657a68e1f446f08f57c0efb1d493527a2e652ce281eb6ca0e4487760a", + .f1 = "749214087958dd8f58bfcdf869d8ae3f", + .f1star = "619e865afe80e382aee13063f9dfb56d", + .f2 = "4041ce438e3e38e8aa96562eed83ac43", + .f3 = "3e3bc01bea0cd914c4c2c83ce2d92757", + .f4 = "666a8e6f577b1aa77b7fd53cebb8a3d6", + .f5 = "1f880d005119", + .f5star = "45e617d77fe5", + }, + }, { + .name = "TS 35.233 Section 6.7 Test Set 5", + .in = { + .k = "1574ca56881d05c189c82880f789c9cd4244955f4426aa2b69c29f15770e5aa5", + .rand = "c570aac68cde651fb1e3088322498bef", + .sqn = "c89bb71f3a41", + .amf = "297d", + .top = "e59f6eb10ea406813f4991b0b9e02f181edf4c7e17b480f66d34da35ee88c95e", + .keccak_iterations = 1, + }, + .out = { + .topc = "3c6052e41532a28a47aa3cbb89f223e8f3aaa976aecd48bc3e7d6165a55eff62", + .f1 = "d7340dad02b4cb01", + .f1star = "c6021e2e66accb15", + .f2 = "84d89b41db1867ffd4c7ba1d82163f4d526a20fbae5418fbb526940b1eeb905c", + .f3 = "d419676afe5ab58c1d8bee0d43523a4d2f52ef0b31a4676a0c334427a988fe65", + .f4 = "205533e505661b61d05cc0eac87818f4", + .f5 = "d7b3d2d4980a", + .f5star = "ca9655264986", + }, + }, { + .name = "TS 35.233 Section 6.8 Test Set 6", + .in = { + .k = "1574ca56881d05c189c82880f789c9cd4244955f4426aa2b69c29f15770e5aa5", + .rand = "c570aac68cde651fb1e3088322498bef", + .sqn = "c89bb71f3a41", + .amf = "297d", + .top = "e59f6eb10ea406813f4991b0b9e02f181edf4c7e17b480f66d34da35ee88c95e", + .keccak_iterations = 2, + }, + .out = { + .topc = "b04a66f26c62fcd6c82de22a179ab65506ecf47f56245cd149966cfa9cec7a51", + .f1 = "90d2289ed1ca1c3dbc2247bb480d431ac71d2e4a7677f6e997cfddb0cbad88b7", + .f1star = "427355dbac30e825063aba61b556e87583abac638e3ab01c4c884ad9d458dc2f", + .f2 = "d67e6e64590d22eecba7324afa4af4460c93f01b24506d6e12047d789a94c867", + .f3 = "ede57edfc57cdffe1aae75066a1b7479bbc3837438e88d37a801cccc9f972b89", + .f4 = "48ed9299126e5057402fe01f9201cf25249f9c5c0ed2afcf084755daff1d3999", + .f5 = "6aae8d18c448", + .f5star = "8c5f33b61f4e", + }, + }, +}; + + +struct tuak_testset { + const char *name; + struct { + uint8_t k[32]; + uint8_t k_len_bytes; + uint8_t rand[16]; + uint8_t sqn[6]; + uint8_t amf[2]; + uint8_t top[32]; + unsigned int keccak_iterations; + } in; + struct { + uint8_t topc[32]; + uint8_t mac_a[32]; + uint8_t mac_s[32]; + uint8_t mac_len_bytes; + + uint8_t res[32]; + uint8_t res_len_bytes; + + uint8_t ck[32]; + uint8_t ck_len_bytes; + uint8_t ik[32]; + uint8_t ik_len_bytes; + uint8_t ak[6]; + uint8_t f5star[6]; + } out; +}; + +static void expect_equal(const char *name, const uint8_t *actual, const uint8_t *expected, size_t len) +{ + if (!memcmp(actual, expected, len)) { + printf("\t%s: %s\r\n", name, osmo_hexdump_nospc(actual, len)); + } else { + char buf[len*2+1]; + printf("\t%s: %s != %s\r\n", name, osmo_hexdump_nospc(actual, len), + osmo_hexdump_buf(buf, sizeof(buf), expected, len, "", true)); + } +} + +static void execute_testset(const struct tuak_testset *tset) +{ + uint8_t topc[32]; + + printf("==> %s\n", tset->name); + + tuak_set_keccak_iterations(tset->in.keccak_iterations); + tuak_opc_gen(topc, tset->in.k, tset->in.k_len_bytes, tset->in.top); + expect_equal("TOPc", topc, tset->out.topc, sizeof(topc)); + + if (tset->out.mac_len_bytes) { + uint8_t mac_a[32]; + uint8_t mac_s[32]; + + tuak_f1(topc, tset->in.k, tset->in.k_len_bytes, tset->in.rand, tset->in.sqn, tset->in.amf, + mac_a, tset->out.mac_len_bytes, tset->in.keccak_iterations); + expect_equal("MAC_A", mac_a, tset->out.mac_a, tset->out.mac_len_bytes); + + tuak_f1star(topc, tset->in.k, tset->in.k_len_bytes, tset->in.rand, tset->in.sqn, tset->in.amf, + mac_s, tset->out.mac_len_bytes, tset->in.keccak_iterations); + expect_equal("MAC_S", mac_s, tset->out.mac_s, tset->out.mac_len_bytes); + } + + if (tset->out.ck_len_bytes || tset->out.ik_len_bytes || tset->out.res_len_bytes) { + uint8_t res[32]; + uint8_t ck[32]; + uint8_t ik[32]; + uint8_t ak[6]; + + tuak_f2345(topc, tset->in.k, tset->in.k_len_bytes, tset->in.rand, + tset->out.res_len_bytes ? res : NULL, tset->out.res_len_bytes, + tset->out.ck_len_bytes ? ck : NULL, tset->out.ck_len_bytes, + tset->out.ik_len_bytes ? ik : NULL, tset->out.ik_len_bytes, + ak, tset->in.keccak_iterations); + + if (tset->out.res_len_bytes) + expect_equal("RES", res, tset->out.res, tset->out.res_len_bytes); + + if (tset->out.ck_len_bytes) + expect_equal("CK", ck, tset->out.ck, tset->out.ck_len_bytes); + + if (tset->out.ik_len_bytes) + expect_equal("IK", ik, tset->out.ik, tset->out.ik_len_bytes); + + expect_equal("AK", ak, tset->out.ak, 6); + } +} + +/* convert string-testspec to binary-testset and execute it */ +static void execute_testspec(const struct tuak_testspec *tcase) +{ + struct tuak_testset _tset, *tset = &_tset; + + tset->name = tcase->name; + tset->in.keccak_iterations = tcase->in.keccak_iterations; + + osmo_hexparse(tcase->in.k, tset->in.k, sizeof(tset->in.k)); + tset->in.k_len_bytes = strlen(tcase->in.k)/2; + OSMO_ASSERT(tset->in.k_len_bytes == 16 || tset->in.k_len_bytes == 32); + + osmo_hexparse(tcase->in.rand, tset->in.rand, sizeof(tset->in.rand)); + OSMO_ASSERT(strlen(tcase->in.rand)/2 == 16); + + osmo_hexparse(tcase->in.sqn, tset->in.sqn, sizeof(tset->in.sqn)); + OSMO_ASSERT(strlen(tcase->in.sqn)/2 == 6); + + osmo_hexparse(tcase->in.amf, tset->in.amf, sizeof(tset->in.amf)); + OSMO_ASSERT(strlen(tcase->in.amf)/2 == 2); + + osmo_hexparse(tcase->in.top, tset->in.top, sizeof(tset->in.top)); + OSMO_ASSERT(strlen(tcase->in.top)/2 == 32); + + osmo_hexparse(tcase->out.topc, tset->out.topc, sizeof(tset->out.topc)); + OSMO_ASSERT(strlen(tcase->out.topc)/2 == 32); + + osmo_hexparse(tcase->out.f1, tset->out.mac_a, sizeof(tset->out.mac_a)); + osmo_hexparse(tcase->out.f1star, tset->out.mac_s, sizeof(tset->out.mac_s)); + OSMO_ASSERT(strlen(tcase->out.f1) == strlen(tcase->out.f1star)); + tset->out.mac_len_bytes = strlen(tcase->out.f1)/2; + OSMO_ASSERT(tset->out.mac_len_bytes == 8 || tset->out.mac_len_bytes == 16 || + tset->out.mac_len_bytes == 32); + + osmo_hexparse(tcase->out.f2, tset->out.res, sizeof(tset->out.res)); + tset->out.res_len_bytes = strlen(tcase->out.f2)/2; + OSMO_ASSERT(tset->out.res_len_bytes == 4 || tset->out.res_len_bytes == 8 || + tset->out.res_len_bytes == 16 || tset->out.res_len_bytes == 32); + + osmo_hexparse(tcase->out.f3, tset->out.ck, sizeof(tset->out.ck)); + tset->out.ck_len_bytes = strlen(tcase->out.f3)/2; + OSMO_ASSERT(tset->out.ck_len_bytes == 16 || tset->out.ck_len_bytes == 32); + + osmo_hexparse(tcase->out.f4, tset->out.ik, sizeof(tset->out.ik)); + tset->out.ik_len_bytes = strlen(tcase->out.f4)/2; + OSMO_ASSERT(tset->out.ik_len_bytes == 16 || tset->out.ik_len_bytes == 32); + + osmo_hexparse(tcase->out.f5, tset->out.ak, sizeof(tset->out.ak)); + OSMO_ASSERT(strlen(tcase->out.f5)/2 == 6); + + osmo_hexparse(tcase->out.f5star, tset->out.f5star, sizeof(tset->out.f5star)); + OSMO_ASSERT(strlen(tcase->out.f5star)/2 == 6); + + execute_testset(tset); +} + +int main(int argc, char **argv) +{ +#if 0 + for (unsigned int i = 0; i < ARRAY_SIZE(testsets); i++) + execute_testset(&testsets[i]); +#endif + + for (unsigned int i = 0; i < ARRAY_SIZE(testspecs); i++) + execute_testspec(&testspecs[i]); + +} diff --git a/tests/auth/tuak_test.ok b/tests/auth/tuak_test.ok new file mode 100644 index 0000000..976fb59 --- /dev/null +++ b/tests/auth/tuak_test.ok @@ -0,0 +1,48 @@ +==> TS 35.233 Section 6.3 Test Set 1 + TOPc: bd04d9530e87513c5d837ac2ad954623a8e2330c115305a73eb45d1f40cccbff + MAC_A: f9a54e6aeaa8618d + MAC_S: e94b4dc6c7297df3 + RES: 657acd64 + CK: d71a1e5c6caffe986a26f783e5c78be1 + IK: be849fa2564f869aecee6f62d4337e72 + AK: 719f1e9b9054 +==> TS 35.233 Section 6.4 Test Set 2 + TOPc: 305425427e18c503c8a4b294ea72c95d0c36c6c6b29d0c65de5974d5977f8524 + MAC_A: c0b8c2d4148ec7aa5f1d78a97e4d1d58 + MAC_S: ef81af7290f7842c6ceafa537fa0745b + RES: e9d749dc4eea0035 + CK: a4cb6f6529ab17f8337f27baa8234d47 + IK: 2274155ccf4199d5e2abcbf621907f90 + AK: 480a9345cc1e +==> TS 35.233 Section 6.5 Test Set 3 + TOPc: 305425427e18c503c8a4b294ea72c95d0c36c6c6b29d0c65de5974d5977f8524 + MAC_A: d97b75a1776065271b1e212bc3b1bf173f438b21e6c64a55a96c372e085e5cc5 + MAC_S: 427bbf07c6e3a86c54f8c5216499f3909a6fd4a164c9fe235b1550258111b821 + RES: 07021c73e7635c7d + CK: 4d59ac796834eb85d11fa148a5058c3c + IK: 126d47500136fdc5ddfd14f19ebf16749ce4b6435323fbb5715a3a796a6082bd + AK: 1d6622c4e59a +==> TS 35.233 Section 6.6 Test Set 4 + TOPc: 2bc16eb657a68e1f446f08f57c0efb1d493527a2e652ce281eb6ca0e4487760a + MAC_A: 749214087958dd8f58bfcdf869d8ae3f + MAC_S: 619e865afe80e382aee13063f9dfb56d + RES: 4041ce438e3e38e8aa96562eed83ac43 + CK: 3e3bc01bea0cd914c4c2c83ce2d92757 + IK: 666a8e6f577b1aa77b7fd53cebb8a3d6 + AK: 1f880d005119 +==> TS 35.233 Section 6.7 Test Set 5 + TOPc: 3c6052e41532a28a47aa3cbb89f223e8f3aaa976aecd48bc3e7d6165a55eff62 + MAC_A: d7340dad02b4cb01 + MAC_S: c6021e2e66accb15 + RES: 84d89b41db1867ffd4c7ba1d82163f4d526a20fbae5418fbb526940b1eeb905c + CK: d419676afe5ab58c1d8bee0d43523a4d2f52ef0b31a4676a0c334427a988fe65 + IK: 205533e505661b61d05cc0eac87818f4 + AK: d7b3d2d4980a +==> TS 35.233 Section 6.8 Test Set 6 + TOPc: b04a66f26c62fcd6c82de22a179ab65506ecf47f56245cd149966cfa9cec7a51 + MAC_A: 90d2289ed1ca1c3dbc2247bb480d431ac71d2e4a7677f6e997cfddb0cbad88b7 + MAC_S: 427355dbac30e825063aba61b556e87583abac638e3ab01c4c884ad9d458dc2f + RES: d67e6e64590d22eecba7324afa4af4460c93f01b24506d6e12047d789a94c867 + CK: ede57edfc57cdffe1aae75066a1b7479bbc3837438e88d37a801cccc9f972b89 + IK: 48ed9299126e5057402fe01f9201cf25249f9c5c0ed2afcf084755daff1d3999 + AK: 6aae8d18c448 -- To view, visit https://gerrit.osmocom.org/c/libosmocore/+/33094 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Change-Id: Ib905b8d8bdf248e8299bf50666ee1bca8298433d Gerrit-Change-Number: 33094 Gerrit-PatchSet: 8 Gerrit-Owner: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: merged
1 0
0 0
[M] Change in osmo-hnbgw[master]: cnpool: select CN link from pool by NRI or round robin
by pespin 02 Jun '23

02 Jun '23
Attention is currently required from: neels. pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/33136 ) Change subject: cnpool: select CN link from pool by NRI or round robin ...................................................................... Patch Set 2: Code-Review+1 -- To view, visit https://gerrit.osmocom.org/c/osmo-hnbgw/+/33136 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-hnbgw Gerrit-Branch: master Gerrit-Change-Id: I66fba27cfbe6e2b27ee3443718846ecfbbd8a974 Gerrit-Change-Number: 33136 Gerrit-PatchSet: 2 Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-Attention: neels <nhofmeyr(a)sysmocom.de> Gerrit-Comment-Date: Fri, 02 Jun 2023 15:27:30 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[M] Change in osmo-hnbgw[master]: add rate_ctr infra; add rate_ctrs for cnpool
by pespin 02 Jun '23

02 Jun '23
Attention is currently required from: neels. pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/33134 ) Change subject: add rate_ctr infra; add rate_ctrs for cnpool ...................................................................... Patch Set 2: Code-Review+1 -- To view, visit https://gerrit.osmocom.org/c/osmo-hnbgw/+/33134 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-hnbgw Gerrit-Branch: master Gerrit-Change-Id: I0132d053223a38e5756cede74106019c47ddcd94 Gerrit-Change-Number: 33134 Gerrit-PatchSet: 2 Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-Attention: neels <nhofmeyr(a)sysmocom.de> Gerrit-Comment-Date: Fri, 02 Jun 2023 15:26:58 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[L] Change in osmo-hnbgw[master]: cnpool: extract Mobile Identity from RANAP payload
by pespin 02 Jun '23

02 Jun '23
Attention is currently required from: neels. pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/33133 ) Change subject: cnpool: extract Mobile Identity from RANAP payload ...................................................................... Patch Set 2: (3 comments) File src/osmo-hnbgw/hnbgw_l3.c: https://gerrit.osmocom.org/c/osmo-hnbgw/+/33133/comment/89867818_b87a25f5 PS2, Line 1: /* OsmoHNBGW implementation of CS and PS Level3 message decoding (NAS PDU */ missing ")" https://gerrit.osmocom.org/c/osmo-hnbgw/+/33133/comment/935c25e3_e7e73a17 PS2, Line 104: /* Old routing area identification 10.5.5.15. */ You can use gsm48_parse_ra() here, see gprs_gmm_rx_att_ack() in libosmo-gprs.git https://gerrit.osmocom.org/c/osmo-hnbgw/+/33133/comment/8028a26c_8a9fe744 PS2, Line 132: /* Old routing area identification 10.5.5.15 */ gsm48_parse_ra -- To view, visit https://gerrit.osmocom.org/c/osmo-hnbgw/+/33133 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-hnbgw Gerrit-Branch: master Gerrit-Change-Id: I373d665c9684b607207f68094188eab63209db51 Gerrit-Change-Number: 33133 Gerrit-PatchSet: 2 Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-CC: pespin <pespin(a)sysmocom.de> Gerrit-Attention: neels <nhofmeyr(a)sysmocom.de> Gerrit-Comment-Date: Fri, 02 Jun 2023 15:26:06 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Gerrit-MessageType: comment
1 0
0 0
[L] Change in osmo-hnbgw[master]: cnpool: make NRI mappings VTY configurable
by pespin 02 Jun '23

02 Jun '23
Attention is currently required from: neels. pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/33130 ) Change subject: cnpool: make NRI mappings VTY configurable ...................................................................... Patch Set 2: Code-Review+1 -- To view, visit https://gerrit.osmocom.org/c/osmo-hnbgw/+/33130 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-hnbgw Gerrit-Branch: master Gerrit-Change-Id: Ifb87e01e5971962e5cfe5e127871af4a67806de1 Gerrit-Change-Number: 33130 Gerrit-PatchSet: 2 Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-Attention: neels <nhofmeyr(a)sysmocom.de> Gerrit-Comment-Date: Fri, 02 Jun 2023 15:21:54 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[L] Change in osmo-hnbgw[master]: cnpool: add multiple 'msc' and 'sgsn' cfg (use only the first)
by pespin 02 Jun '23

02 Jun '23
Attention is currently required from: neels. pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/32324 ) Change subject: cnpool: add multiple 'msc' and 'sgsn' cfg (use only the first) ...................................................................... Patch Set 5: Code-Review+1 -- To view, visit https://gerrit.osmocom.org/c/osmo-hnbgw/+/32324 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-hnbgw Gerrit-Branch: master Gerrit-Change-Id: I5479eded786ec26062d49403a8be12967f113cdb Gerrit-Change-Number: 32324 Gerrit-PatchSet: 5 Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-Attention: neels <nhofmeyr(a)sysmocom.de> Gerrit-Comment-Date: Fri, 02 Jun 2023 15:20:24 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[S] Change in osmo-hnbgw[master]: cnpool prep: add SCCP_EV_USER_ABORT
by pespin 02 Jun '23

02 Jun '23
Attention is currently required from: neels, laforge. pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/33128 ) Change subject: cnpool prep: add SCCP_EV_USER_ABORT ...................................................................... Patch Set 2: Code-Review+2 -- To view, visit https://gerrit.osmocom.org/c/osmo-hnbgw/+/33128 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-hnbgw Gerrit-Branch: master Gerrit-Change-Id: Idff8e09b5328c904b175e4d4df7d4044a34f4a20 Gerrit-Change-Number: 33128 Gerrit-PatchSet: 2 Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-Attention: neels <nhofmeyr(a)sysmocom.de> Gerrit-Attention: laforge <laforge(a)osmocom.org> Gerrit-Comment-Date: Fri, 02 Jun 2023 15:17:47 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[M] Change in osmo-hnbgw[master]: cnpool: split up context_map_find_or_create_by_rua_ctx_id()
by pespin 02 Jun '23

02 Jun '23
Attention is currently required from: neels. pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/33127 ) Change subject: cnpool: split up context_map_find_or_create_by_rua_ctx_id() ...................................................................... Patch Set 2: Code-Review+1 -- To view, visit https://gerrit.osmocom.org/c/osmo-hnbgw/+/33127 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-hnbgw Gerrit-Branch: master Gerrit-Change-Id: Ifc5242547260154eb5aecd3a9d9c2aac8419e8db Gerrit-Change-Number: 33127 Gerrit-PatchSet: 2 Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-Attention: neels <nhofmeyr(a)sysmocom.de> Gerrit-Comment-Date: Fri, 02 Jun 2023 15:15:23 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
[L] Change in osmo-hnbgw[master]: cnpool: add multiple 'msc' and 'sgsn' cfg (use only the first)
by neels 02 Jun '23

02 Jun '23
neels has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/32324 ) Change subject: cnpool: add multiple 'msc' and 'sgsn' cfg (use only the first) ...................................................................... Set Ready For Review -- To view, visit https://gerrit.osmocom.org/c/osmo-hnbgw/+/32324 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-hnbgw Gerrit-Branch: master Gerrit-Change-Id: I5479eded786ec26062d49403a8be12967f113cdb Gerrit-Change-Number: 32324 Gerrit-PatchSet: 5 Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Comment-Date: Fri, 02 Jun 2023 15:13:29 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: No Gerrit-MessageType: comment
1 0
0 0
[M] Change in osmo-hnbgw[master]: cnpool: split up context_map_find_or_create_by_rua_ctx_id()
by neels 02 Jun '23

02 Jun '23
Attention is currently required from: neels. Hello Jenkins Builder, laforge, I'd like you to reexamine a change. Please visit https://gerrit.osmocom.org/c/osmo-hnbgw/+/33127 to look at the new patch set (#2). Change subject: cnpool: split up context_map_find_or_create_by_rua_ctx_id() ...................................................................... cnpool: split up context_map_find_or_create_by_rua_ctx_id() Have separate find, alloc, set_cnlink functions instead of all in one. For CN pooling, I need these operations to be separate: - we need to decode the RANAP and L3 PDU only if no existing context_map was found (see I373d665c9684b607207f68094188eab63209db51 ). - while decoding RANAP and L3 PDU, and while deciding which cnlink to use, I already want to use the logging context of LOG_MAP(). So I want to allocate a map first, and connect it to the selected cnlink later. Related: SYS#6412 Change-Id: Ifc5242547260154eb5aecd3a9d9c2aac8419e8db --- M include/osmocom/hnbgw/context_map.h M src/osmo-hnbgw/context_map.c M src/osmo-hnbgw/hnbgw_rua.c 3 files changed, 100 insertions(+), 39 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/27/33127/2 -- To view, visit https://gerrit.osmocom.org/c/osmo-hnbgw/+/33127 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-hnbgw Gerrit-Branch: master Gerrit-Change-Id: Ifc5242547260154eb5aecd3a9d9c2aac8419e8db Gerrit-Change-Number: 33127 Gerrit-PatchSet: 2 Gerrit-Owner: neels <nhofmeyr(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Attention: neels <nhofmeyr(a)sysmocom.de> Gerrit-MessageType: newpatchset
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • ...
  • 248
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.