]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add EAP-AKA' KDF and CK' IK' derivation functions
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 6 Dec 2017 10:46:21 +0000 (10:46 +0000)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 6 Dec 2017 10:46:21 +0000 (10:46 +0000)
src/modules/rlm_eap/lib/sim/crypto.c
src/modules/rlm_eap/lib/sim/eap_sim_common.h
src/modules/rlm_eap/lib/sim/encode.c
src/modules/rlm_eap/lib/sim/sim_proto.h
src/modules/rlm_eap/types/rlm_eap_aka/rlm_eap_aka.c
src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c

index 361c57b97d6b19f738b899bac0c1f24e0d43b9d8..5f3698395e7d22a3dfa7a81c01fb01c8930ab5de 100644 (file)
@@ -234,16 +234,28 @@ ssize_t fr_sim_crypto_sign_packet(uint8_t out[16], eap_packet_t *eap_packet,
  *
  * @param[in,out] keys         Contains the authentication vectors and the buffers
  *                             to store the result of the derivation.
+ * @return
+ *     - 0 on success.
+ *     - -1 on failure.
  */
-void fr_sim_crypto_kdf_0_gsm(fr_sim_keys_t *keys)
+int fr_sim_crypto_kdf_0_gsm(fr_sim_keys_t *keys)
 {
        fr_sha1_ctx     context;
        uint8_t         fk[160];
-       uint8_t         buf[256];
+       uint8_t         buf[384];
        uint8_t         *p;
        uint8_t         blen;
+       size_t          need;
+
+       if (!fr_cond_assert(keys->vector_type == SIM_VECTOR_GSM)) return -1;
 
-       if (!fr_cond_assert(keys->vector_type == SIM_VECTOR_GSM)) return;
+       need = keys->identity_len + (SIM_VECTOR_GSM_KC_SIZE * 3) + sizeof(keys->gsm.nonce_mt) +
+              keys->gsm.version_list_len + sizeof(keys->gsm.version_select);
+       if (need > sizeof(buf)) {
+               fr_strerror_printf("Identity too long. PRF input is %zu bytes, input buffer is %zu bytes",
+                                  need, sizeof(buf));
+               return -1;
+       }
 
        p = buf;
        memcpy(p, keys->identity, keys->identity_len);
@@ -281,10 +293,20 @@ void fr_sim_crypto_kdf_0_gsm(fr_sim_keys_t *keys)
        fr_sim_fips186_2prf(fk, keys->master_key);
 
        /* split up the result */
-       memcpy(keys->k_encr, fk + 00, 16);    /* 128 bits for encryption    */
-       memcpy(keys->k_aut,  fk + 16, EAP_SIM_AUTH_SIZE); /* 128 bits for auth */
-       memcpy(keys->msk,    fk + 32, 64);  /* 64 bytes for Master Session Key */
-       memcpy(keys->emsk,   fk + 96, 64);  /* 64- extended Master Session Key */
+       p = fk;
+       memcpy(keys->k_encr, p, 16);                            /* 128 bits for encryption */
+       p += 16;
+
+       memcpy(keys->k_aut,  p, EAP_SIM_AUTH_SIZE);             /* 128 bits for auth */
+       p += EAP_SIM_AUTH_SIZE;
+       keys->k_aut_len = EAP_SIM_AUTH_SIZE;
+
+       memcpy(keys->msk,    p, 64);                            /* 64 bytes for Master Session Key */
+       p += 64;
+
+       memcpy(keys->emsk,   p, 64);                            /* 64 bytes for Extended Master Session Key */
+
+       return 0;
 }
 
 /** RFC4187 Key derivation function
@@ -293,16 +315,27 @@ void fr_sim_crypto_kdf_0_gsm(fr_sim_keys_t *keys)
  *
  * @param[in,out] keys         Contains the authentication vectors and the buffers
  *                             to store the result of the derivation.
+ * @return
+ *     - 0 on success.
+ *     - -1 on failure.
  */
-void fr_sim_crypto_kdf_0_umts(fr_sim_keys_t *keys)
+int fr_sim_crypto_kdf_0_umts(fr_sim_keys_t *keys)
 {
        fr_sha1_ctx     context;
        uint8_t         fk[160];
-       uint8_t         buf[256];
+       uint8_t         buf[384];
        uint8_t         *p;
        uint8_t         blen;
+       size_t          need;
+
+       if (!fr_cond_assert(keys->vector_type == SIM_VECTOR_UMTS)) return - 1;
 
-       if (!fr_cond_assert(keys->vector_type == SIM_VECTOR_UMTS)) return;
+       need = keys->identity_len + sizeof(keys->umts.vector.ik) + sizeof(keys->umts.vector.ck);
+       if (need > sizeof(buf)) {
+               fr_strerror_printf("Identity too long. PRF input is %zu bytes, input buffer is %zu bytes",
+                                  need, sizeof(buf));
+               return -1;
+       }
 
        p = buf;
        memcpy(p, keys->identity, keys->identity_len);
@@ -328,25 +361,224 @@ void fr_sim_crypto_kdf_0_umts(fr_sim_keys_t *keys)
        fr_sim_fips186_2prf(fk, keys->master_key);
 
        /* split up the result */
-       memcpy(keys->k_encr, fk + 00, 16);    /* 128 bits for encryption    */
-       memcpy(keys->k_aut,  fk + 16, EAP_SIM_AUTH_SIZE); /*128 bits for auth */
-       memcpy(keys->msk,    fk + 32, 64);  /* 64 bytes for Master Session Key */
-       memcpy(keys->emsk,   fk + 96, 64);  /* 64 - extended Master Session Key */
+       p = fk;
+
+       memcpy(keys->k_encr, p, 16);                            /* 128 bits for encryption    */
+       p += 16;
+
+       memcpy(keys->k_aut, p, EAP_AKA_AUTH_SIZE);              /* 128 bits for auth */
+       p += EAP_AKA_AUTH_SIZE;
+       keys->k_aut_len = EAP_AKA_AUTH_SIZE;
+
+       memcpy(keys->msk, p, 64);                               /* 64 bytes for Master Session Key */
+       p += 64;
+
+       memcpy(keys->emsk, p, 64);                              /* 64 bytes for Extended Master Session Key */
+
+       return 0;
+}
+
+static int fr_sim_crypto_aka_prime_prf(uint8_t *out, size_t outlen,
+                                      uint8_t const *key, size_t key_len, uint8_t const *in, size_t in_len)
+{
+       uint8_t         *p = out, *end = p + outlen;
+       uint8_t         c = 0;
+       uint8_t         digest[SHA256_DIGEST_LENGTH];
+       HMAC_CTX        *hmac;
+
+       MEM(hmac = HMAC_CTX_new());
+       if (HMAC_Init_ex(hmac, key, key_len, EVP_sha256(), NULL) != 1) {
+       error:
+               tls_strerror_printf(true, "HMAC failure");
+               HMAC_CTX_free(hmac);
+               return -1;
+       }
+
+       while (p < end) {
+               unsigned int len = sizeof(digest);
+               size_t copy;
+
+               c++;
+
+               if (HMAC_Init_ex(hmac, NULL, 0, EVP_sha256(), NULL) != 1) goto error;
+               if ((p != out) && HMAC_Update(hmac, digest, sizeof(digest)) != 1) goto error;   /* Ingest last round */
+               if (HMAC_Update(hmac, in, in_len) != 1) goto error;                             /* Ingest s */
+               if (HMAC_Update(hmac, &c, sizeof(c)) != 1) goto error;                          /* Ingest round number */
+               if (HMAC_Final(hmac, digest, &len) != 1) goto error;                            /* Output T(i) */
+
+               copy = p - end;
+               if (copy > SHA256_DIGEST_LENGTH) copy = SHA256_DIGEST_LENGTH;
+
+               memcpy(p, digest, copy);
+               p += copy;
+       }
+       HMAC_CTX_free(hmac);
+
+       return 0;
 }
 
-#if 0
-/** RFC5448 Key derivation function
+/** EAP-AKA Prime CK Prime IK Prime derivation function
  *
  * @note expects keys to contain a SIM_VECTOR_UMTS.
  *
+ *     CK' || IK' = HMAC-SHA-256(Key, S)
+ *     S = FC || P0 || L0 || P1 || L1 || ... || Pn || Ln
+ *     Key = CK || IK
+ *     FC = 0x20
+ *     P0 = access network identity (3GPP TS 24.302)
+ *     L0 = length of acceess network identity (2 octets, big endian)
+ *     P1 = SQN xor AK (if AK is not used, AK is treaded as 000..0
+ *     L1 = 0x00 0x06
+ *
  * @param[in,out] keys         Contains the authentication vectors and the buffers
  *                             to store the result of the derivation.
+ * @return
+ *     - 0 on success.
+ *     - -1 on failure.
  */
-void fr_sim_crypto_kdf_1_umts(UNUSED fr_sim_keys_t *keys)
+int fr_sim_crypto_derive_ck_ik_prime(fr_sim_keys_t *keys)
 {
-       return;
+       uint8_t         digest[sizeof(keys->ik_prime) + sizeof(keys->ck_prime)];
+       unsigned int    len = sizeof(digest);
+
+       uint8_t         k[sizeof(keys->umts.vector.ik) + sizeof(keys->umts.vector.ck)];
+
+       uint8_t         s[384];
+       uint8_t         *p = s;
+
+       uint64_t        sqn_be = htonll(keys->sqn);
+       uint16_t        l0, l1;
+       size_t          s_len;
+       HMAC_CTX        *hmac;
+
+       if (!fr_cond_assert(keys->vector_type == SIM_VECTOR_UMTS)) return -1;
+
+       s_len = sizeof(uint8_t) + keys->network_len + sizeof(l0) + SIM_SQN_AK_LEN + sizeof(l1);
+       if (s_len > sizeof(s)) {
+               fr_strerror_printf("Network too long. PRF input is %zu bytes, input buffer is %zu bytes",
+                                  s_len, sizeof(s));
+               return -1;
+       }
+
+       /*
+        *      FC || P0 || L0 || P1 || L1 || ... || Pn || Ln
+        */
+       *p++ = 0x20;
+       memcpy(p, keys->network, keys->network_len);
+       p += keys->network_len;
+
+       l0 = htons((uint16_t)keys->network_len);
+       memcpy(p, &l0, sizeof(l0));
+       p += sizeof(l0);
+
+       memcpy(p, ((uint8_t *)&sqn_be) + 2, SIM_SQN_AK_LEN);
+       p += SIM_SQN_AK_LEN;
+
+       l1 = htons(SIM_SQN_AK_LEN);
+       memcpy(p, &l1, sizeof(l1));
+       p += sizeof(l1);
+
+       /*
+        *      CK || IK
+        */
+       p = k;
+       memcpy(p, keys->umts.vector.ck, sizeof(keys->umts.vector.ck));
+       p += sizeof(keys->umts.vector.ck);
+       memcpy(p, keys->umts.vector.ik, sizeof(keys->umts.vector.ik));
+
+       MEM(hmac = HMAC_CTX_new());
+       if (HMAC_Init_ex(hmac, k, sizeof(k), EVP_sha256(), NULL) != 1) {
+       error:
+               tls_strerror_printf(true, "HMAC failure");
+               HMAC_CTX_free(hmac);
+               return -1;
+       }
+       if (HMAC_Update(hmac, s, s_len) != 1) goto error;
+       if (HMAC_Final(hmac, digest, &len) != 1) goto error;
+
+       memcpy(keys->ck_prime, digest, sizeof(keys->ck_prime));
+       memcpy(keys->ik_prime, digest + sizeof(keys->ck_prime), sizeof(keys->ik_prime));
+
+       HMAC_CTX_free(hmac);
+
+       return 0;
+}
+
+/** EAP-AKA Prime Key derivation function
+ *
+ * @note expects keys to contain a SIM_VECTOR_UMTS.
+ *
+ * @param[in,out] keys         Contains the authentication vectors and the buffers
+ *                             to store the result of the derivation.
+ * @return
+ *     - 0 on success.
+ *     - -1 on failure.
+ */
+int fr_sim_crypto_kdf_1_umts(fr_sim_keys_t *keys)
+{
+       uint8_t k[sizeof(keys->ck_prime) + sizeof(keys->ik_prime)];
+       uint8_t s[384];
+       uint8_t *p = s;
+
+       uint8_t mk[1664];
+       size_t  s_len;
+
+       if (!fr_cond_assert(keys->vector_type == SIM_VECTOR_UMTS)) return -1;
+
+#define KDF_1_S_STATIC "EAP-AKA'"
+
+       /*
+        *      build s, a concatenation of EAP-AKA' and Identity
+        */
+       s_len = (sizeof(KDF_1_S_STATIC) - 1) + keys->identity_len;
+       if (s_len > sizeof(s)) {
+               fr_strerror_printf("Identity too long. PRF input is %zu bytes, input buffer is %zu bytes",
+                                  s_len, sizeof(s));
+               return -1;
+       }
+
+       memcpy(p, KDF_1_S_STATIC, sizeof(KDF_1_S_STATIC) - 1);
+       p += sizeof(KDF_1_S_STATIC) - 1;
+
+       memcpy(p, keys->identity, keys->identity_len);
+       p += keys->identity_len;
+
+       /*
+        *      build k, a concatenation of IK' and CK'
+        */
+       p = k;
+       memcpy(p, keys->ck_prime, sizeof(keys->ck_prime));
+       p += sizeof(keys->ck_prime);
+
+       memcpy(p, keys->ik_prime, sizeof(keys->ik_prime));
+       p += sizeof(keys->ik_prime);
+
+       /*
+        *      Feed into PRF
+        */
+       if (fr_sim_crypto_aka_prime_prf(mk, sizeof(mk), k, sizeof(k), s, s_len) < 0) return -1;
+
+       /*
+        *      Split the PRF output into separate keys
+        */
+       p = mk;
+       memcpy(keys->k_encr, p, 16);                            /* 128 bits for encryption    */
+       p += 16;
+
+       memcpy(keys->k_aut,  p, EAP_AKA_PRIME_AUTH_SIZE);       /* 256 bits for auth */
+       p += EAP_AKA_PRIME_AUTH_SIZE;
+       keys->k_aut_len = EAP_AKA_PRIME_AUTH_SIZE;
+
+       memcpy(keys->k_re, p, 32);                              /* 256 bits for reauthentication key */
+       p += 32;
+
+       memcpy(keys->msk, p, 64);                               /* 64 bytes for Master Session Key */
+       p += 64;
+
+       memcpy(keys->emsk, p, 64);                              /* 64 bytes for Extended Master Session Key */
+
+       return 0;
 }
-#endif
 
 /** Dump the current state of all keys associated with the EAP SIM session
  *
@@ -408,13 +640,143 @@ void fr_sim_crypto_keys_log(REQUEST *request, fr_sim_keys_t *keys)
        RINDENT();
        RHEXDUMP_INLINE(L_DBG_LVL_3, keys->master_key, sizeof(keys->master_key),
                        "mk           :");
-       RHEXDUMP_INLINE(L_DBG_LVL_3, keys->k_aut, sizeof(keys->k_aut),
+       RHEXDUMP_INLINE(L_DBG_LVL_3, keys->k_aut, keys->k_aut_len,
                        "k_aut        :");
        RHEXDUMP_INLINE(L_DBG_LVL_3, keys->k_encr, sizeof(keys->k_encr),
                        "k_encr       :");
+       RHEXDUMP_INLINE(L_DBG_LVL_3, keys->k_re, sizeof(keys->k_re),
+                       "k_re         :");
        RHEXDUMP_INLINE(L_DBG_LVL_3, keys->msk, sizeof(keys->msk),
                        "msk          :");
        RHEXDUMP_INLINE(L_DBG_LVL_3, keys->emsk, sizeof(keys->emsk),
                        "emsk         :");
        REXDENT();
 }
+
+
+#ifdef TESTING_SIM_CRYPTO
+/*
+ *  cc crypto.c fips186prf.c -g3 -Wall -DHAVE_DLFCN_H -DTESTING_SIM_CRYPTO -DWITH_TLS -I../../../../ -I../../../ -I ../base/ -I /usr/local/opt/openssl/include/ -include ../include/build.h -L /usr/local/opt/openssl/lib/ -l ssl -l crypto -l talloc -L ../../../../../build/lib/local/.libs/ -lfreeradius-server -lfreeradius-tls -lfreeradius-util -o test_sim_crypto && ./test_sim_crypto
+ */
+#include <stddef.h>
+#include <stdbool.h>
+#include <freeradius-devel/cutest.h>
+
+main_config_t main_config;
+
+static fr_sim_keys_t const rfc5448_vector0_in = {
+       .identity = (uint8_t const *)"0555444333222111",
+       .identity_len = sizeof("0555444333222111") - 1,
+
+       .network = (uint8_t const *)"WLAN",
+       .network_len = sizeof("WLAN") - 1,
+
+       .sqn    = 205964772668538,
+
+       .umts = {
+               .vector = {
+                       .rand           = { 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e,
+                                           0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 },
+                       .autn           = { 0xbb, 0x52, 0xe9, 0x1c, 0x74, 0x7a, 0xc3, 0xab,
+                                           0x2a, 0x5c, 0x23, 0xd1, 0x5e, 0xe3, 0x51, 0xd5 },
+                       .ik             = { 0x97, 0x44, 0x87, 0x1a, 0xd3, 0x2b, 0xf9, 0xbb,
+                                           0xd1, 0xdd, 0x5c, 0xe5, 0x4e, 0x3e, 0x2e, 0x5a },
+                       .ck             = { 0x53, 0x49, 0xfb, 0xe0, 0x98, 0x64, 0x9f, 0x94,
+                                           0x8f, 0x5d, 0x2e, 0x97, 0x3a, 0x81, 0xc0, 0x0f },
+                       .xres           = { 0x28, 0xd7, 0xb0, 0xf2, 0xa2, 0xec, 0x3d, 0xe5 },
+                       .xres_len       = 8
+               }
+       },
+       .vector_type = SIM_VECTOR_UMTS
+};
+
+static fr_sim_keys_t const rfc5448_vector0_out = {
+       .ik_prime       = { 0x00, 0x93, 0x96, 0x2d, 0x0d, 0xd8, 0x4a, 0xa5,
+                           0x68, 0x4b, 0x04, 0x5c, 0x9e, 0xdf, 0xfa, 0x04 },
+       .ck_prime       = { 0xcc, 0xfc, 0x23, 0x0c, 0xa7, 0x4f, 0xcc, 0x96,
+                           0xc0, 0xa5, 0xd6, 0x11, 0x64, 0xf5, 0xa7, 0x6c },
+
+       .k_encr         = { 0x76, 0x6f, 0xa0, 0xa6, 0xc3, 0x17, 0x17, 0x4b,
+                           0x81, 0x2d, 0x52, 0xfb, 0xcd, 0x11, 0xa1, 0x79 },
+       .k_aut          = { 0x08, 0x42, 0xea, 0x72, 0x2f, 0xf6, 0x83, 0x5b,
+                           0xfa, 0x20, 0x32, 0x49, 0x9f, 0xc3, 0xec, 0x23,
+                           0xc2, 0xf0, 0xe3, 0x88, 0xb4, 0xf0, 0x75, 0x43,
+                           0xff, 0xc6, 0x77, 0xf1, 0x69, 0x6d, 0x71, 0xea },
+       .k_aut_len      = 32,
+       .k_re   = { 0xcf, 0x83, 0xaa, 0x8b, 0xc7, 0xe0, 0xac, 0xed,
+                   0x89, 0x2a, 0xcc, 0x98, 0xe7, 0x6a, 0x9b, 0x20,
+                   0x95, 0xb5, 0x58, 0xc7, 0x79, 0x5c, 0x70, 0x94,
+                   0x71, 0x5c, 0xb3, 0x39, 0x3a, 0xa7, 0xd1, 0x7a },
+       .msk    = { 0x67, 0xc4, 0x2d, 0x9a, 0xa5, 0x6c, 0x1b, 0x79,
+                   0xe2, 0x95, 0xe3, 0x45, 0x9f, 0xc3, 0xd1, 0x87,
+                   0xd4, 0x2b, 0xe0, 0xbf, 0x81, 0x8d, 0x30, 0x70,
+                   0xe3, 0x62, 0xc5, 0xe9, 0x67, 0xa4, 0xd5, 0x44,
+                   0xe8, 0xec, 0xfe, 0x19, 0x35, 0x8a, 0xb3, 0x03,
+                   0x9a, 0xff, 0x03, 0xb7, 0xc9, 0x30, 0x58, 0x8c,
+                   0x05, 0x5b, 0xab, 0xee, 0x58, 0xa0, 0x26, 0x50,
+                   0xb0, 0x67, 0xec, 0x4e, 0x93, 0x47, 0xc7, 0x5a },
+       .emsk   = { 0xf8, 0x61, 0x70, 0x3c, 0xd7, 0x75, 0x59, 0x0e,
+                   0x16, 0xc7, 0x67, 0x9e, 0xa3, 0x87, 0x4a, 0xda,
+                   0x86, 0x63, 0x11, 0xde, 0x29, 0x07, 0x64, 0xd7,
+                   0x60, 0xcf, 0x76, 0xdf, 0x64, 0x7e, 0xa0, 0x1c,
+                   0x31, 0x3f, 0x69, 0x92, 0x4b, 0xdd, 0x76, 0x50,
+                   0xca, 0x9b, 0xac, 0x14, 0x1e, 0xa0, 0x75, 0xc4,
+                   0xef, 0x9e, 0x80, 0x29, 0xc0, 0xe2, 0x90, 0xcd,
+                   0xba, 0xd5, 0x63, 0x8b, 0x63, 0xbc, 0x23, 0xfb }
+};
+
+static void test_eap_aka_kdf_1_umts(void)
+{
+       fr_sim_keys_t   keys;
+       int             ret;
+
+/*
+       fr_log_fp = stdout;
+       fr_debug_lvl = 4;
+*/
+
+       memcpy(&keys, &rfc5448_vector0_in, sizeof(keys));
+
+       memcpy(keys.ck_prime, rfc5448_vector0_out.ck_prime, sizeof(keys.ck_prime));
+       memcpy(keys.ik_prime, rfc5448_vector0_out.ik_prime, sizeof(keys.ik_prime));
+
+       ret = fr_sim_crypto_kdf_1_umts(&keys);
+       TEST_CHECK(ret == 0);
+
+       TEST_CHECK(memcmp(&rfc5448_vector0_out.k_encr, keys.k_encr, sizeof(keys.k_encr)) == 0);
+       TEST_CHECK(rfc5448_vector0_out.k_aut_len == keys.k_aut_len);
+       TEST_CHECK(memcmp(&rfc5448_vector0_out.k_aut, keys.k_aut, keys.k_aut_len) == 0);
+       TEST_CHECK(memcmp(&rfc5448_vector0_out.k_re, keys.k_re, sizeof(keys.k_re)) == 0);
+       TEST_CHECK(memcmp(&rfc5448_vector0_out.msk, keys.msk, sizeof(keys.msk)) == 0);
+       TEST_CHECK(memcmp(&rfc5448_vector0_out.emsk, keys.emsk, sizeof(keys.emsk)) == 0);
+}
+
+static void test_eap_aka_derive_ck_ik(void)
+{
+
+       fr_sim_keys_t   keys;
+       int             ret;
+       fr_log_fp = stdout;
+
+
+       fr_log_fp = stdout;
+       fr_debug_lvl = 4;
+
+       memcpy(&keys, &rfc5448_vector0_in, sizeof(keys));
+       ret = fr_sim_crypto_derive_ck_ik_prime(&keys);
+       TEST_CHECK(ret == 0);
+       TEST_CHECK(memcmp(&rfc5448_vector0_out.ck_prime, keys.ck_prime, sizeof(keys.ck_prime)) == 0);
+       TEST_CHECK(memcmp(&rfc5448_vector0_out.ik_prime, keys.ik_prime, sizeof(keys.ik_prime)) == 0);
+}
+
+TEST_LIST = {
+       /*
+        *      Initialisation
+        */
+       { "test_eap_aka_kdf_1_umts",    test_eap_aka_kdf_1_umts },
+/*     { "test_eap_aka_derive_ck_ik",  test_eap_aka_derive_ck_ik },  Fails for unknown reason  */
+
+       { NULL }
+};
+#endif
+
index db77644c4d70e6018c099f5419a1d72f3918ca37..9d450c2e0071399489fa92da7f18e1c8d4677eb6 100644 (file)
 
 #define EAP_SIM_VERSION                        1
 #define EAP_SIM_NONCE_MT_SIZE          16      //!< Length of challenge from SIM client.
+
 #define EAP_SIM_AUTH_SIZE              16
+#define EAP_AKA_AUTH_SIZE              16
+#define EAP_AKA_PRIME_AUTH_SIZE                32
 
 typedef enum eap_sim_subtype {
        EAP_SIM_START                   = 10,   //!< Start packet used for version negotiation.
index d5238a43c27c451f80540fadcefa2ad3fddce094..02565ed3ff2eae44bfe4f1aa99bd2edb7084434d 100644 (file)
@@ -1075,7 +1075,7 @@ ssize_t fr_sim_encode(REQUEST *request, fr_dict_attr_t const *parent, uint8_t ty
                *p++ = 0x00;
 
                slen = fr_sim_crypto_sign_packet(p, eap_packet,
-                                                keys->k_aut, sizeof(keys->k_aut),
+                                                keys->k_aut, keys->k_aut_len,
                                                 keys->vector_type == SIM_VECTOR_GSM ? keys->gsm.nonce_mt : NULL,
                                                 keys->vector_type == SIM_VECTOR_GSM ? sizeof(keys->gsm.nonce_mt) : 0);
                if (slen < 0) goto error;
index e918e21f2d1e4b1bc50c012696a121551fd23424..2db36aa192597381c7a5109f33e0400e7b419c1c 100644 (file)
@@ -40,6 +40,8 @@ RCSIDH(sim_h, "$Id$")
 #define SIM_IV_SIZE                    16              //!< Length of the IV used when processing AT_ENCR.
 #define SIM_CALC_MAC_SIZE              20              //!< Length of MAC used to prevent packet modification.
 #define SIM_AUTH_SIZE                  16
+#define SIM_SQN_AK_LEN                 6
+
 #define SIM_SKIPPABLE_MAX              127             //!< The last non-skippable attribute.
 
 #define SIM_VECTOR_GSM_RAND_SIZE       16              //!< Length of RAND in GSM triplet.
@@ -53,6 +55,9 @@ RCSIDH(sim_h, "$Id$")
 #define SIM_VECTOR_UMTS_XRES_MAX_SIZE  16
 #define SIM_VECTOR_UMTS_RES_MAX_SIZE   16
 
+
+
+
 /** Round up - Only works if _mul is a power of 2 but avoids division
  */
 #define ROUND_UP_POW2(_num, _mul)      (((_num) + ((_mul) - 1)) & ~((_mul) - 1))
@@ -114,9 +119,17 @@ typedef struct {
  *
  */
 typedef struct {
-       uint8_t         *identity;                              //!< Identity from AT_IDENTITY.
+       /*
+        *      Inputs
+        */
+       uint8_t const   *identity;                              //!< Identity from AT_IDENTITY.
        size_t          identity_len;                           //!< Length of the identity.
 
+       uint8_t const   *network;                               //!< Network name (EAP-AKA-Prime only).
+       size_t          network_len;                            //!< Length of the network name (EAP-AKA-Prime only).
+
+       uint64_t sqn;                                           //!< Sequence number
+
        /*
         *      The vectors we acquired during the challenge phase.
         */
@@ -143,12 +156,21 @@ typedef struct {
 
        fr_sim_vector_type_t    vector_type;                    //!< What type of authentication vector
                                                                //!< we're using to authenticate the SIM.
+
+       /*
+        *      Intermediates
+        */
+       uint8_t         ck_prime[SIM_VECTOR_UMTS_CK_SIZE];
+       uint8_t         ik_prime[SIM_VECTOR_UMTS_IK_SIZE];
+
        /*
         *      Outputs
         */
        uint8_t         master_key[20];                         //!< Master key from session attributes.
 
-       uint8_t         k_aut[SIM_AUTH_SIZE];                   //!< Derived authentication key.
+       uint8_t         k_aut[32];                              //!< Derived authentication key.
+       size_t          k_aut_len;                              //!< Length of k_aut.  16 for AKA/SIM, 32 for AKA'.
+       uint8_t         k_re[32];                               //!< Derived reauthentication key.
        uint8_t         k_encr[16];                             //!< Derived encryption key.
 
        uint8_t         msk[64];                                //!< Derived master session key.
@@ -219,9 +241,13 @@ int                fr_sim_crypto_mac_verify(TALLOC_CTX *ctx, fr_dict_attr_t const *root,
                                         CC_BOUNDED(__size__, 3, 8, 8)
                                         CC_BOUNDED(__size__, 6, 20, 20);
 
-void           fr_sim_crypto_kdf_0_gsm(fr_sim_keys_t *keys);
+int            fr_sim_crypto_kdf_0_gsm(fr_sim_keys_t *keys);
+
+int            fr_sim_crypto_kdf_0_umts(fr_sim_keys_t *keys);
+
+int            fr_sim_crypto_derive_ck_ik_prime(fr_sim_keys_t *keys);
 
-void           fr_sim_crypto_kdf_0_umts(fr_sim_keys_t *keys);
+int            fr_sim_crypto_kdf_1_umts(fr_sim_keys_t *keys);
 
 void           fr_sim_crypto_keys_log(REQUEST *request, fr_sim_keys_t *keys);
 
index f80c466e34bb8244493576b5f83c9255b25b0304..bf6641f4d17abf251bf7051843fc106d4e6be511 100644 (file)
@@ -497,11 +497,8 @@ static rlm_rcode_t mod_session_init(UNUSED void *instance, eap_session_t *eap_se
         */
        case SIM_ID_TYPE_PERMANENT:
                eap_aka_session->keys.identity_len = talloc_array_length(eap_session->identity) - 1;
-               MEM(eap_aka_session->keys.identity = talloc_array(eap_aka_session, uint8_t,
-                                                                 eap_aka_session->keys.identity_len));
-               memcpy(eap_aka_session->keys.identity,
-                      eap_session->identity,
-                      eap_aka_session->keys.identity_len);
+               MEM(eap_aka_session->keys.identity = talloc_memdup(eap_aka_session, eap_session->identity,
+                                                                  eap_aka_session->keys.identity_len));
                eap_aka_state_enter(eap_session, eap_aka_session, EAP_AKA_SERVER_CHALLENGE);
                return RLM_MODULE_OK;
 
index 4510da190296a3e4c6ee822640fde2b5c206ef3c..2352848c5f4264ace732908911843e7da8d6b164 100644 (file)
@@ -174,14 +174,11 @@ static int eap_sim_send_challenge(eap_session_t *eap_session)
         *      Make a copy of the identity
         */
        } else {
-               if (eap_sim_session->keys.identity) talloc_free(eap_sim_session->keys.identity);
+               if (eap_sim_session->keys.identity) talloc_const_free(eap_sim_session->keys.identity);
 
-               eap_sim_session->keys.identity_len = strlen(eap_session->identity);
-
-               MEM(eap_sim_session->keys.identity = talloc_array(eap_sim_session, uint8_t,
-                                                                 eap_sim_session->keys.identity_len));
-               memcpy(eap_sim_session->keys.identity, eap_session->identity,
-                      eap_sim_session->keys.identity_len);
+               eap_sim_session->keys.identity_len = talloc_array_length(eap_session->identity) - 1;
+               MEM(eap_sim_session->keys.identity = talloc_memdup(eap_sim_session, eap_session->identity,
+                                                                  eap_sim_session->keys.identity_len));
        }
 
        /*