From: Arran Cudbard-Bell Date: Mon, 29 Apr 2019 22:14:25 +0000 (-0400) Subject: Crypto functions should take REQUEST * not eap_session_t * X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=301abefbd75ecde814ea8150e7c7ae4e1993a159;p=thirdparty%2Ffreeradius-server.git Crypto functions should take REQUEST * not eap_session_t * --- diff --git a/src/lib/sim/base.h b/src/lib/sim/base.h index 77f05d12b89..eb79f3a357f 100644 --- a/src/lib/sim/base.h +++ b/src/lib/sim/base.h @@ -45,6 +45,10 @@ RCSIDH(sim_h, "$Id$") #define SIM_SQN_AK_SIZE 6 #define SIM_NONCE_S_SIZE 16 //!< Length of re-authentication nonce +#define SIM_KI_SIZE 16 //!< Length of secret data shared between SIM and AuC. +#define SIM_OP_SIZE 16 //!< Length of Operator Algorithm Configuration. +#define SIM_OPC_SIZE 16 //!< Length of modified Operator Algorithm Configuration. + #define SIM_MK_SIZE 20 //!< Master key size #define SIM_SKIPPABLE_MAX 127 //!< The last non-skippable attribute. @@ -66,7 +70,8 @@ RCSIDH(sim_h, "$Id$") typedef enum { SIM_VECTOR_NONE = 0, SIM_VECTOR_GSM, //!< Vector is GSM triplets. - SIM_VECTOR_UMTS //!< Vector is UMTS quintuplets. + SIM_VECTOR_UMTS, //!< Vector is UMTS quintuplets. + SIM_VECTOR_UMTS_REAUTH } fr_sim_vector_type_t; /** Where to get EAP-SIM vectors from @@ -76,7 +81,8 @@ typedef enum { SIM_VECTOR_SRC_TRIPLETS, //!< Source of triplets is EAP-SIM-* attributes. SIM_VECTOR_SRC_QUINTUPLETS, //!< Source of triplets is derived from EAP-AKA-* ///< quintuplets. - SIM_VECTOR_SRC_KI //!< Should generate triplets locally using a Ki. + SIM_VECTOR_SRC_KI, //!< Should generate triplets locally using a Ki. + SIM_VECTOR_SRC_REAUTH } fr_sim_vector_src_t; typedef struct { @@ -259,12 +265,12 @@ int fr_sim_crypto_kdf_0_gsm(fr_sim_keys_t *keys); int fr_sim_crypto_kdf_0_umts(fr_sim_keys_t *keys); -void fr_sim_crypto_keys_init_kdf_0_reauth(fr_sim_keys_t *keys, - uint8_t const master_key[static SIM_MK_SIZE], uint16_t counter); +int fr_sim_crypto_kdf_1_umts(fr_sim_keys_t *keys); -int fr_sim_crypto_kdf_0_reauth(fr_sim_keys_t *keys); +void fr_sim_crypto_keys_init_reauth(fr_sim_keys_t *keys, + uint8_t const master_key[static SIM_MK_SIZE], uint16_t counter); -int fr_sim_crypto_kdf_1_umts(fr_sim_keys_t *keys); +int fr_sim_crypto_kdf_0_reauth(fr_sim_keys_t *keys); int fr_sim_crypto_kdf_1_reauth(fr_sim_keys_t *keys); @@ -276,9 +282,17 @@ void fr_sim_crypto_keys_log(REQUEST *request, fr_sim_keys_t *keys); int fr_sim_vector_gsm_from_attrs(eap_session_t *eap_session, VALUE_PAIR *vps, int idx, fr_sim_keys_t *keys, fr_sim_vector_src_t *src); -int fr_sim_vector_umts_from_attrs(eap_session_t *eap_session, VALUE_PAIR *vps, +int fr_sim_vector_umts_from_attrs(REQUEST *request, VALUE_PAIR *vps, fr_sim_keys_t *keys, fr_sim_vector_src_t *src); +int fr_sim_vector_umts_reauth_from_attrs(REQUEST *request, VALUE_PAIR *vps, + fr_sim_keys_t *keys); + +void fr_sim_vector_umts_reauth_clear(fr_sim_keys_t *keys); + +int fr_sim_umts_resync_from_attrs(uint64_t *new_sqn, + REQUEST *request, VALUE_PAIR *auts_vp, fr_sim_keys_t *keys); + /* * fips186prf.c */ diff --git a/src/lib/sim/crypto.c b/src/lib/sim/crypto.c index fe2f6b99999..fc2c2163cbe 100644 --- a/src/lib/sim/crypto.c +++ b/src/lib/sim/crypto.c @@ -568,176 +568,6 @@ int fr_sim_crypto_kdf_0_umts(fr_sim_keys_t *keys) return 0; } -/** Initialise fr_sim_keys_t with EAP-SIM/EAP-AKA reauthentication data - * - * @param[out] keys structure to populate. - * @param[in] master_key from original authentication. - * @param[in] counter re-authentication counter. - */ -void fr_sim_crypto_keys_init_kdf_0_reauth(fr_sim_keys_t *keys, - uint8_t const master_key[static SIM_MK_SIZE], uint16_t counter) -{ - uint32_t nonce_s[4]; - - /* - * Copy in master key - */ - memcpy(keys->master_key, master_key, sizeof(keys->master_key)); - - keys->reauth.counter = counter; - - nonce_s[0] = fr_rand(); - nonce_s[1] = fr_rand(); - nonce_s[2] = fr_rand(); - nonce_s[3] = fr_rand(); - memcpy(keys->reauth.nonce_s, (uint8_t *)&nonce_s, sizeof(keys->reauth.nonce_s)); -} - -/** Key Derivation Function (Fast-Reauthentication) as described in RFC4186/7 (EAP-SIM/AKA) section 7 - * - @verbatim - XKEY' = SHA1(Identity|counter|NONCE_S| MK) - FK = PRF(XKEY') - MSK = FK[0..511] - EMSK = FK[512..1023] - @endverbatim - * - * Derives new MSK, EMSK, k_aut, k_encr - * - * Use #fr_sim_crypto_keys_init_kdf_0_reauth to populate the #fr_sim_keys_t structure. - * - * @note expects keys to contain a populated master_key, none_s and counter values. - * - * @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_0_reauth(fr_sim_keys_t *keys) -{ - EVP_MD_CTX *md_ctx; - uint8_t fk[160]; - uint8_t xkey_prime[SHA1_DIGEST_LENGTH]; - - uint8_t buf[384]; - uint8_t *p; - - size_t need; - unsigned int len = 0; - - if (keys->reauth.counter == 0) { - fr_strerror_printf("Re-authentication counter not initialised, must be >= 1"); - return -1; - } - - need = keys->identity_len + sizeof(uint16_t) + SIM_NONCE_S_SIZE + sizeof(keys->master_key); - 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; - } - - /* - * Re-derive k_aut and k_encr from the original Master Key - * These keys stay the same over multiple re-auth attempts. - */ - fr_sim_fips186_2prf(fk, keys->master_key); - - p = fk; - memcpy(keys->k_encr, p, 16); /* 128 bits for encryption */ - p += 16; - FR_PROTO_HEX_DUMP(keys->k_encr, sizeof(keys->k_encr), "K_encr"); - - memcpy(keys->k_aut, p, EAP_SIM_AUTH_SIZE); /* 128 bits for auth */ - - keys->k_aut_len = EAP_SIM_AUTH_SIZE; - FR_PROTO_HEX_DUMP(keys->k_aut, keys->k_aut_len, "K_aut"); - - /* - * Derive a new MSK and EMSK - * - * New PRF input is: - * XKEY' = SHA1(Identity|counter|NONCE_S| MK) - */ - - /* - * Identity - */ - p = buf; - memcpy(p, keys->identity, keys->identity_len); - p += keys->identity_len; - FR_PROTO_HEX_DUMP(keys->identity, keys->identity_len, "identity"); - - /* - * Counter - */ - *p++ = ((keys->reauth.counter & 0xff00) >> 8); - *p++ = (keys->reauth.counter & 0x00ff); - - /* - * nonce_s - */ - memcpy(p, keys->reauth.nonce_s, sizeof(keys->reauth.nonce_s)); - p += sizeof(keys->reauth.nonce_s); - - /* - * Master key - */ - memcpy(p, keys->master_key, sizeof(keys->master_key)); - p += sizeof(keys->master_key); - - FR_PROTO_HEX_DUMP(buf, p - buf, "Identity || counter || NONCE_S || MK"); - - /* - * Digest re-auth key with SHA1 - */ - md_ctx = EVP_MD_CTX_create(); - if (!md_ctx) { - tls_strerror_printf("Failed creating MD ctx"); - error: - EVP_MD_CTX_destroy(md_ctx); - return -1; - } - - if (EVP_DigestInit_ex(md_ctx, EVP_sha1(), NULL) != 1) { - tls_strerror_printf("Failed initialising digest"); - goto error; - } - - if (EVP_DigestUpdate(md_ctx, buf, p - buf) != 1) { - tls_strerror_printf("Failed digesting crypto data"); - goto error; - } - - if (EVP_DigestFinal_ex(md_ctx, xkey_prime, &len) != 1) { - tls_strerror_printf("Failed finalising digest"); - goto error; - } - - EVP_MD_CTX_destroy(md_ctx); - - FR_PROTO_HEX_DUMP(xkey_prime, sizeof(xkey_prime), "xkey'"); - - /* - * Expand XKEY' with PRF - */ - fr_sim_fips186_2prf(fk, xkey_prime); - - /* - * Split up the result - */ - p = fk; - memcpy(keys->msk, p, 64); /* 64 bytes for Master Session Key */ - p += 64; - FR_PROTO_HEX_DUMP(keys->msk, sizeof(keys->msk), "K_msk"); - - memcpy(keys->emsk, p, 64); /* 64 bytes for Extended Master Session Key */ - FR_PROTO_HEX_DUMP(keys->emsk, sizeof(keys->emsk), "K_emsk"); - - return 0; -} - /** Key Derivation Function (CK', IK') as specified in 3GPP.33.402 * @verbatim @@ -1023,6 +853,185 @@ int fr_sim_crypto_kdf_1_umts(fr_sim_keys_t *keys) return 0; } + +/** Initialise fr_sim_keys_t with EAP-SIM/EAP-AKA['] reauthentication data + * + * Generates a new nonce_s and copies the mk and counter values into the fr_sim_keys_t. + * + * @param[out] keys structure to populate. + * @param[in] master_key from original authentication. + * @param[in] counter re-authentication counter. + */ +void fr_sim_crypto_keys_init_reauth(fr_sim_keys_t *keys, + uint8_t const master_key[static SIM_MK_SIZE], uint16_t counter) +{ + uint32_t nonce_s[4]; + + /* + * Copy in master key + */ + memcpy(keys->master_key, master_key, sizeof(keys->master_key)); + + keys->reauth.counter = counter; + + nonce_s[0] = fr_rand(); + nonce_s[1] = fr_rand(); + nonce_s[2] = fr_rand(); + nonce_s[3] = fr_rand(); + memcpy(keys->reauth.nonce_s, (uint8_t *)&nonce_s, sizeof(keys->reauth.nonce_s)); +} + +/** Key Derivation Function (Fast-Reauthentication) as described in RFC4186/7 (EAP-SIM/AKA) section 7 + * + @verbatim + XKEY' = SHA1(Identity|counter|NONCE_S| MK) + FK = PRF(XKEY') + MSK = FK[0..511] + EMSK = FK[512..1023] + @endverbatim + * + * Derives new MSK, EMSK, k_aut, k_encr + * + * Use #fr_sim_crypto_keys_init_reauth to populate the #fr_sim_keys_t structure. + * + * @note expects keys to contain a populated master_key, none_s and counter values. + * + * @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_0_reauth(fr_sim_keys_t *keys) +{ + EVP_MD_CTX *md_ctx; + uint8_t fk[160]; + uint8_t xkey_prime[SHA1_DIGEST_LENGTH]; + + uint8_t buf[384]; + uint8_t *p; + + size_t need; + unsigned int len = 0; + + /* + * RFC 4187 Section 5.1 + * ... + * "On full authentication, both the server and + * the peer initialize the counter to one." + */ + if (keys->reauth.counter == 0) { + fr_strerror_printf("Re-authentication counter not initialised, must be >= 1"); + return -1; + } + + need = keys->identity_len + sizeof(uint16_t) + SIM_NONCE_S_SIZE + sizeof(keys->master_key); + 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; + } + + /* + * Re-derive k_aut and k_encr from the original Master Key + * These keys stay the same over multiple re-auth attempts. + */ + fr_sim_fips186_2prf(fk, keys->master_key); + + p = fk; + memcpy(keys->k_encr, p, 16); /* 128 bits for encryption */ + p += 16; + FR_PROTO_HEX_DUMP(keys->k_encr, sizeof(keys->k_encr), "K_encr"); + + memcpy(keys->k_aut, p, EAP_SIM_AUTH_SIZE); /* 128 bits for auth */ + + keys->k_aut_len = EAP_SIM_AUTH_SIZE; + FR_PROTO_HEX_DUMP(keys->k_aut, keys->k_aut_len, "K_aut"); + + /* + * Derive a new MSK and EMSK + * + * New PRF input is: + * XKEY' = SHA1(Identity|counter|NONCE_S| MK) + */ + + /* + * Identity + */ + p = buf; + memcpy(p, keys->identity, keys->identity_len); + p += keys->identity_len; + FR_PROTO_HEX_DUMP(keys->identity, keys->identity_len, "identity"); + + /* + * Counter + */ + *p++ = ((keys->reauth.counter & 0xff00) >> 8); + *p++ = (keys->reauth.counter & 0x00ff); + + /* + * nonce_s + */ + memcpy(p, keys->reauth.nonce_s, sizeof(keys->reauth.nonce_s)); + p += sizeof(keys->reauth.nonce_s); + + /* + * Master key + */ + memcpy(p, keys->master_key, sizeof(keys->master_key)); + p += sizeof(keys->master_key); + + FR_PROTO_HEX_DUMP(buf, p - buf, "Identity || counter || NONCE_S || MK"); + + /* + * Digest re-auth key with SHA1 + */ + md_ctx = EVP_MD_CTX_create(); + if (!md_ctx) { + tls_strerror_printf("Failed creating MD ctx"); + error: + EVP_MD_CTX_destroy(md_ctx); + return -1; + } + + if (EVP_DigestInit_ex(md_ctx, EVP_sha1(), NULL) != 1) { + tls_strerror_printf("Failed initialising digest"); + goto error; + } + + if (EVP_DigestUpdate(md_ctx, buf, p - buf) != 1) { + tls_strerror_printf("Failed digesting crypto data"); + goto error; + } + + if (EVP_DigestFinal_ex(md_ctx, xkey_prime, &len) != 1) { + tls_strerror_printf("Failed finalising digest"); + goto error; + } + + EVP_MD_CTX_destroy(md_ctx); + + FR_PROTO_HEX_DUMP(xkey_prime, sizeof(xkey_prime), "xkey'"); + + /* + * Expand XKEY' with PRF + */ + fr_sim_fips186_2prf(fk, xkey_prime); + + /* + * Split up the result + */ + p = fk; + memcpy(keys->msk, p, 64); /* 64 bytes for Master Session Key */ + p += 64; + FR_PROTO_HEX_DUMP(keys->msk, sizeof(keys->msk), "K_msk"); + + memcpy(keys->emsk, p, 64); /* 64 bytes for Extended Master Session Key */ + FR_PROTO_HEX_DUMP(keys->emsk, sizeof(keys->emsk), "K_emsk"); + + return 0; +} + /** Key Derivation Function (Fast-Reauthentication) as described in RFC 5448 (EAP-AKA') section 3.3 * @verbatim @@ -1152,6 +1161,12 @@ void fr_sim_crypto_keys_log(REQUEST *request, fr_sim_keys_t *keys) "IK' :"); break; + case SIM_VECTOR_UMTS_REAUTH: + RHEXDUMP_INLINE(L_DBG_LVL_3, keys->master_key, sizeof(keys->master_key), "mk :"); + RDEBUG3("counter : %u", keys->reauth.counter); + RHEXDUMP_INLINE(L_DBG_LVL_3, keys->reauth.nonce_s, sizeof(keys->reauth.nonce_s), "nonce_s :"); + break; + case SIM_VECTOR_NONE: break; } @@ -1159,8 +1174,16 @@ void fr_sim_crypto_keys_log(REQUEST *request, fr_sim_keys_t *keys) RDEBUG3("Derived keys"); RINDENT(); - RHEXDUMP_INLINE(L_DBG_LVL_3, keys->master_key, sizeof(keys->master_key), - "mk :"); + + switch (keys->vector_type) { + case SIM_VECTOR_UMTS_REAUTH: + break; + + default: + RHEXDUMP_INLINE(L_DBG_LVL_3, keys->master_key, sizeof(keys->master_key), + "mk :"); + break; + } 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), diff --git a/src/lib/sim/vector.c b/src/lib/sim/vector.c index b105a1b7c8e..bf8c9f87e1a 100644 --- a/src/lib/sim/vector.c +++ b/src/lib/sim/vector.c @@ -384,9 +384,8 @@ int fr_sim_vector_gsm_from_attrs(eap_session_t *eap_session, VALUE_PAIR *vps, return 0; } -static int vector_umts_from_ki(eap_session_t *eap_session, VALUE_PAIR *vps, fr_sim_keys_t *keys) +static int vector_umts_from_ki(REQUEST *request, VALUE_PAIR *vps, fr_sim_keys_t *keys) { - REQUEST *request = eap_session->request; VALUE_PAIR *ki_vp, *amf_vp, *sqn_vp, *version_vp; uint64_t sqn; @@ -492,10 +491,8 @@ static int vector_umts_from_ki(eap_session_t *eap_session, VALUE_PAIR *vps, fr_s /** Get one set of quintuplets from the request * */ -static int vector_umts_from_quintuplets(eap_session_t *eap_session, VALUE_PAIR *vps, fr_sim_keys_t *keys) +static int vector_umts_from_quintuplets(REQUEST *request, VALUE_PAIR *vps, fr_sim_keys_t *keys) { - REQUEST *request = eap_session->request; - VALUE_PAIR *rand_vp = NULL, *xres_vp = NULL, *ck_vp = NULL, *ik_vp = NULL; VALUE_PAIR *autn_vp = NULL, *sqn_vp = NULL, *ak_vp = NULL; @@ -644,7 +641,7 @@ static int vector_umts_from_quintuplets(eap_session_t *eap_session, VALUE_PAIR * * * Hunt for a source of UMTS quintuplets * - * @param eap_session The current eap_session. + * @param request The current request. * @param vps List to hunt for triplets in. * @param keys UMTS keys. * @param src Forces quintuplets to be retrieved from a particular src. @@ -654,10 +651,9 @@ static int vector_umts_from_quintuplets(eap_session_t *eap_session, VALUE_PAIR * * - 0 Vector was retrieved OK and written to the specified index. * - -1 Error retrieving vector from the specified src. */ -int fr_sim_vector_umts_from_attrs(eap_session_t *eap_session, VALUE_PAIR *vps, +int fr_sim_vector_umts_from_attrs(REQUEST *request, VALUE_PAIR *vps, fr_sim_keys_t *keys, fr_sim_vector_src_t *src) { - REQUEST *request = eap_session->request; int ret; rad_assert((keys->vector_type == SIM_VECTOR_NONE) || (keys->vector_type == SIM_VECTOR_UMTS)); @@ -665,7 +661,7 @@ int fr_sim_vector_umts_from_attrs(eap_session_t *eap_session, VALUE_PAIR *vps, switch (*src) { default: case SIM_VECTOR_SRC_KI: - ret = vector_umts_from_ki(eap_session, vps, keys); + ret = vector_umts_from_ki(request, vps, keys); if (ret == 0) { *src = SIM_VECTOR_SRC_KI; break; @@ -675,7 +671,7 @@ int fr_sim_vector_umts_from_attrs(eap_session_t *eap_session, VALUE_PAIR *vps, /* FALL-THROUGH */ case SIM_VECTOR_SRC_QUINTUPLETS: - ret = vector_umts_from_quintuplets(eap_session, vps, keys); + ret = vector_umts_from_quintuplets(request, vps, keys); if (ret == 0) { *src = SIM_VECTOR_SRC_QUINTUPLETS; break;; diff --git a/src/modules/rlm_eap/types/rlm_eap_aka/rlm_eap_aka.c b/src/modules/rlm_eap/types/rlm_eap_aka/rlm_eap_aka.c index 2c4394f09bf..54c05674b82 100644 --- a/src/modules/rlm_eap/types/rlm_eap_aka/rlm_eap_aka.c +++ b/src/modules/rlm_eap/types/rlm_eap_aka/rlm_eap_aka.c @@ -348,7 +348,7 @@ static int eap_aka_send_challenge(eap_session_t *eap_session) * Get vectors from attribute or generate * them using COMP128-* or Milenage. */ - if (fr_sim_vector_umts_from_attrs(eap_session, request->control, &eap_aka_session->keys, &src) != 0) { + if (fr_sim_vector_umts_from_attrs(request, request->control, &eap_aka_session->keys, &src) != 0) { REDEBUG("Failed retrieving UMTS vectors"); return RLM_MODULE_FAIL; } diff --git a/src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c b/src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c index e78a391117d..6dcd2c47635 100644 --- a/src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c +++ b/src/modules/rlm_eap/types/rlm_eap_sim/rlm_eap_sim.c @@ -410,7 +410,7 @@ static int eap_sim_send_reauthentication(eap_session_t *eap_session) /* * All set, calculate keys! */ - fr_sim_crypto_keys_init_kdf_0_reauth(&eap_sim_session->keys, mk->vp_octets, counter->vp_uint16); + fr_sim_crypto_keys_init_reauth(&eap_sim_session->keys, mk->vp_octets, counter->vp_uint16); fr_sim_crypto_kdf_0_reauth(&eap_sim_session->keys); if (RDEBUG_ENABLED3) fr_sim_crypto_keys_log(request, &eap_sim_session->keys);