From: Arran Cudbard-Bell Date: Sun, 27 Jan 2019 15:09:52 +0000 (+0700) Subject: Start working on removing our implementation of the rfc4346 PRF X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=deff8b42676a75bbfa91c6d03598a4cacd7f31df;p=thirdparty%2Ffreeradius-server.git Start working on removing our implementation of the rfc4346 PRF We can just use OpenSSL's --- diff --git a/src/lib/eap/crypto.c b/src/lib/eap/crypto.c index 3b810bed6e0..3dd987a486f 100644 --- a/src/lib/eap/crypto.c +++ b/src/lib/eap/crypto.c @@ -42,108 +42,37 @@ USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */ #include "base.h" #include "attrs.h" -static void crypto_rfc4346_p_hash(uint8_t *out, size_t out_len, - EVP_MD const *evp_md, - uint8_t const *secret, size_t secret_len, - uint8_t const *seed, size_t seed_len) -{ - HMAC_CTX *ctx_a, *ctx_out; - uint8_t a[HMAC_MAX_MD_CBLOCK]; - size_t size; - - ctx_a = HMAC_CTX_new(); - ctx_out = HMAC_CTX_new(); -#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW - HMAC_CTX_set_flags(ctx_a, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); - HMAC_CTX_set_flags(ctx_out, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); -#endif - HMAC_Init_ex(ctx_a, secret, secret_len, evp_md, NULL); - HMAC_Init_ex(ctx_out, secret, secret_len, evp_md, NULL); - - size = HMAC_size(ctx_out); - - /* Calculate A(1) */ - HMAC_Update(ctx_a, seed, seed_len); - HMAC_Final(ctx_a, a, NULL); - - while (1) { - /* Calculate next part of output */ - HMAC_Update(ctx_out, a, size); - HMAC_Update(ctx_out, seed, seed_len); - - /* Check if last part */ - if (out_len < size) { - HMAC_Final(ctx_out, a, NULL); - memcpy(out, a, out_len); - break; - } - - /* Place digest in output buffer */ - HMAC_Final(ctx_out, out, NULL); - HMAC_Init_ex(ctx_out, NULL, 0, NULL, NULL); - out += size; - out_len -= size; - - /* Calculate next A(i) */ - HMAC_Init_ex(ctx_a, NULL, 0, NULL, NULL); - HMAC_Update(ctx_a, a, size); - HMAC_Final(ctx_a, a, NULL); - } - - HMAC_CTX_free(ctx_a); - HMAC_CTX_free(ctx_out); -#ifdef __STDC_LIB_EXT1__ - memset_s(a, 0, sizeof(a), sizeof(a)); -#else - memset(a, 0, sizeof(a)); -#endif -} - - -void eap_crypto_rfc4346_prf(uint8_t *out, size_t out_len, uint8_t *scratch, - uint8_t const *secret, size_t secret_len, - uint8_t const *seed, size_t seed_len) -{ - unsigned int i; - unsigned int len = (secret_len + 1) / 2; - uint8_t const *s1 = secret; - uint8_t const *s2 = secret + (secret_len - len); - - crypto_rfc4346_p_hash(out, out_len, EVP_md5(), s1, len, seed, seed_len); - crypto_rfc4346_p_hash(scratch, out_len, EVP_sha1(), s2, len, seed, seed_len); - - for (i = 0; i < out_len; i++) out[i] ^= scratch[i]; -} - #define EAP_TLS_MPPE_KEY_LEN 32 /** Generate keys according to RFC 2716 and add to the reply * */ -void eap_crypto_mppe_keys(REQUEST *request, SSL *ssl, char const *prf_label, size_t prf_label_len) +int eap_crypto_mppe_keys(REQUEST *request, SSL *ssl, char const *prf_label, size_t prf_label_len) { uint8_t out[4 * EAP_TLS_MPPE_KEY_LEN]; uint8_t *p; - size_t seed_len = prf_label_len; - size_t master_key_len; - uint8_t seed[64 + (2 * SSL3_RANDOM_SIZE)]; - uint8_t scratch[sizeof(out)]; - uint8_t master_key[SSL_MAX_MASTER_KEY_LENGTH]; if (SSL_export_keying_material(ssl, out, sizeof(out), prf_label, prf_label_len, NULL, 0, 0) != 1) { - p = seed; - memcpy(p, prf_label, seed_len); - p += seed_len; - - (void) SSL_get_client_random(ssl, p, SSL3_RANDOM_SIZE); - p += SSL3_RANDOM_SIZE; - seed_len += SSL3_RANDOM_SIZE; + tls_log_error(request, "Failed generating MPPE keys"); + return -1; + } - (void) SSL_get_server_random(ssl, p, SSL3_RANDOM_SIZE); - seed_len += SSL3_RANDOM_SIZE; + if (RDEBUG_ENABLED3) { + uint8_t random[SSL3_RANDOM_SIZE]; + size_t random_len; + uint8_t master_key[SSL_MAX_MASTER_KEY_LENGTH]; + size_t master_key_len; + RDEBUG3("Key Derivation Function input"); + RINDENT(); + RDEBUG3("prf label : %pV", fr_box_strvalue_len(prf_label, prf_label_len)); master_key_len = SSL_SESSION_get_master_key(SSL_get_session(ssl), master_key, sizeof(master_key)); - eap_crypto_rfc4346_prf(out, sizeof(out), scratch, master_key, master_key_len, seed, seed_len); + RDEBUG3("master session key : %pH", fr_box_octets(master_key, master_key_len)); + random_len = SSL_get_client_random(ssl, random, SSL3_RANDOM_SIZE); + RDEBUG3("client random : %pH", fr_box_octets(random, random_len)); + random_len = SSL_get_server_random(ssl, random, SSL3_RANDOM_SIZE); + RDEBUG3("server random : %pH", fr_box_octets(random, random_len)); + REXDENT(); } RDEBUG2("Adding session keys"); @@ -154,44 +83,16 @@ void eap_crypto_mppe_keys(REQUEST *request, SSL *ssl, char const *prf_label, siz eap_add_reply(request, attr_eap_msk, out, 64); eap_add_reply(request, attr_eap_emsk, out + 64, 64); -} - - -/* - * Generate the challenge using a PRF label. - * - * It's in the TLS module simply because it's only a few lines - * of code, and it needs access to the TLS PRF functions. - */ -void eap_crypto_challenge(SSL *ssl, uint8_t *buffer, uint8_t *scratch, size_t size, - char const *prf_label, size_t prf_label_len) -{ - uint8_t *p; - size_t len, master_key_len; - uint8_t master_key[SSL_MAX_MASTER_KEY_LENGTH]; - uint8_t seed[128 + (2 * SSL3_RANDOM_SIZE)]; - - if (SSL_export_keying_material(ssl, buffer, size, prf_label, - prf_label_len, NULL, 0, 0) == 1) return; - - len = prf_label_len; - if (len > 128) len = 128; - - p = seed; - memcpy(p, prf_label, len); - p += len; - - (void) SSL_get_client_random(ssl, p, SSL3_RANDOM_SIZE); - p += SSL3_RANDOM_SIZE; - (void) SSL_get_server_random(ssl, p, SSL3_RANDOM_SIZE); - p += SSL3_RANDOM_SIZE; - master_key_len = SSL_SESSION_get_master_key(SSL_get_session(ssl), master_key, sizeof(master_key)); - eap_crypto_rfc4346_prf(buffer, size, scratch, master_key, master_key_len, seed, p - seed); + return 0; } -int eap_crypto_tls_session_id(TALLOC_CTX *ctx, uint8_t **out, - SSL *ssl, uint8_t eap_type, +int eap_crypto_tls_session_id(TALLOC_CTX *ctx, +#if OPENSSL_VERSION_NUMBER < 0x10100000L + UNUSED +#endif + REQUEST *request, SSL *ssl, + uint8_t **out, uint8_t eap_type, #if OPENSSL_VERSION_NUMBER < 0x10100000L UNUSED #endif @@ -236,7 +137,10 @@ int eap_crypto_tls_session_id(TALLOC_CTX *ctx, uint8_t **out, { MEM(buff = p = talloc_array(ctx, uint8_t, sizeof(eap_type) + 64)); *p++ = eap_type; - SSL_export_keying_material(ssl, p, 64, prf_label, prf_label_len, NULL, 0, 0); + if (SSL_export_keying_material(ssl, p, 64, prf_label, prf_label_len, NULL, 0, 0) != 1) { + tls_log_error(request, "Failed generating TLS session ID"); + return -1; + } } break; } diff --git a/src/lib/eap/tls.c b/src/lib/eap/tls.c index 0ce8ea6d525..441104f4613 100644 --- a/src/lib/eap/tls.c +++ b/src/lib/eap/tls.c @@ -299,8 +299,8 @@ int eap_tls_success(eap_session_t *eap_session, /* * Automatically generate MPPE keying material. */ - if (keying_prf_label) eap_crypto_mppe_keys(eap_session->request, tls_session->ssl, - keying_prf_label, keying_prf_label_len); + if (keying_prf_label) if (eap_crypto_mppe_keys(eap_session->request, tls_session->ssl, + keying_prf_label, keying_prf_label_len) < 0) return -1; /* * Add the TLS session ID to the request @@ -309,8 +309,8 @@ int eap_tls_success(eap_session_t *eap_session, uint8_t *session_id; VALUE_PAIR *vp; - if (eap_crypto_tls_session_id(eap_session->request->reply, &session_id, - tls_session->ssl, eap_session->type, + if (eap_crypto_tls_session_id(eap_session->request->reply, request, tls_session->ssl, + &session_id, eap_session->type, sessid_prf_label, sessid_prf_label_len) < 0) return -1; MEM(pair_add_reply(&vp, attr_eap_session_id) >= 0); diff --git a/src/lib/eap/tls.h b/src/lib/eap/tls.h index bec50cb5fc5..7fca0e42ece 100644 --- a/src/lib/eap/tls.h +++ b/src/lib/eap/tls.h @@ -169,20 +169,11 @@ int eap_tls_compose(eap_session_t *eap_session, eap_tls_status_t status, uint8 tls_record_t *record, size_t record_len, size_t frag_len); /* MPPE key generation */ - -void eap_crypto_rfc4346_prf(uint8_t *out, size_t out_len, uint8_t *scratch, - uint8_t const *secret, size_t secret_len, - uint8_t const *seed, size_t seed_len); - -void eap_crypto_mppe_keys(REQUEST *request, SSL *ssl, - char const *prf_label, size_t prf_label_len) CC_HINT(nonnull); - -void eap_crypto_challenge(SSL *ssl, uint8_t *buffer, uint8_t *scratch, size_t size, +int eap_crypto_mppe_keys(REQUEST *request, SSL *ssl, char const *prf_label, size_t prf_label_len) CC_HINT(nonnull); -int eap_crypto_tls_session_id(TALLOC_CTX *ctx, uint8_t **out, - SSL *ssl, uint8_t eap_type, - char const *prf_label, size_t prf_label_len); +int eap_crypto_tls_session_id(TALLOC_CTX *ctx, REQUEST *request, SSL *ssl, uint8_t **out, + uint8_t eap_type, char const *prf_label, size_t prf_label_len); /* EAP-TLS framework */ eap_tls_session_t *eap_tls_session_init(eap_session_t *eap_session, fr_tls_conf_t *tls_conf, bool client_cert) CC_HINT(nonnull); diff --git a/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast_crypto.c b/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast_crypto.c index a5cb6528c5d..7dc19d46097 100644 --- a/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast_crypto.c +++ b/src/modules/rlm_eap/types/rlm_eap_fast/eap_fast_crypto.c @@ -217,6 +217,81 @@ int eap_fast_decrypt(uint8_t const *ciphertext, size_t ciphertext_len, } } + +static void crypto_rfc4346_p_hash(uint8_t *out, size_t out_len, + EVP_MD const *evp_md, + uint8_t const *secret, size_t secret_len, + uint8_t const *seed, size_t seed_len) +{ + HMAC_CTX *ctx_a, *ctx_out; + uint8_t a[HMAC_MAX_MD_CBLOCK]; + size_t size; + + ctx_a = HMAC_CTX_new(); + ctx_out = HMAC_CTX_new(); +#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW + HMAC_CTX_set_flags(ctx_a, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + HMAC_CTX_set_flags(ctx_out, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); +#endif + HMAC_Init_ex(ctx_a, secret, secret_len, evp_md, NULL); + HMAC_Init_ex(ctx_out, secret, secret_len, evp_md, NULL); + + size = HMAC_size(ctx_out); + + /* Calculate A(1) */ + HMAC_Update(ctx_a, seed, seed_len); + HMAC_Final(ctx_a, a, NULL); + + while (1) { + /* Calculate next part of output */ + HMAC_Update(ctx_out, a, size); + HMAC_Update(ctx_out, seed, seed_len); + + /* Check if last part */ + if (out_len < size) { + HMAC_Final(ctx_out, a, NULL); + memcpy(out, a, out_len); + break; + } + + /* Place digest in output buffer */ + HMAC_Final(ctx_out, out, NULL); + HMAC_Init_ex(ctx_out, NULL, 0, NULL, NULL); + out += size; + out_len -= size; + + /* Calculate next A(i) */ + HMAC_Init_ex(ctx_a, NULL, 0, NULL, NULL); + HMAC_Update(ctx_a, a, size); + HMAC_Final(ctx_a, a, NULL); + } + + HMAC_CTX_free(ctx_a); + HMAC_CTX_free(ctx_out); +#ifdef __STDC_LIB_EXT1__ + memset_s(a, 0, sizeof(a), sizeof(a)); +#else + memset(a, 0, sizeof(a)); +#endif +} + + +static void eap_crypto_rfc4346_prf(uint8_t *out, size_t out_len, uint8_t *scratch, + uint8_t const *secret, size_t secret_len, + uint8_t const *seed, size_t seed_len) +{ + unsigned int i; + unsigned int len = (secret_len + 1) / 2; + uint8_t const *s1 = secret; + uint8_t const *s2 = secret + (secret_len - len); + + crypto_rfc4346_p_hash(out, out_len, EVP_md5(), s1, len, seed, seed_len); + crypto_rfc4346_p_hash(scratch, out_len, EVP_sha1(), s2, len, seed, seed_len); + + for (i = 0; i < out_len; i++) out[i] ^= scratch[i]; +} + + /* * Same as before, but for EAP-FAST the order of {server,client}_random is flipped */ diff --git a/src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c b/src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c index 2be2527dd7c..241ee320dee 100644 --- a/src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c +++ b/src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c @@ -260,7 +260,6 @@ do_value: */ if ((vp->da == attr_chap_challenge) || (vp->da == attr_ms_chap_challenge)) { uint8_t challenge[16]; - uint8_t scratch[16]; char label[] = "ttls challenge"; if ((vp->vp_length < 8) || (vp->vp_length > 16)) { @@ -268,8 +267,11 @@ do_value: goto error; } - eap_crypto_challenge(ssl, challenge, scratch, - sizeof(challenge), label, sizeof(label) - 1); + if (SSL_export_keying_material(ssl, challenge, sizeof(challenge), + label, sizeof(label) - 1, NULL, 0, 0) != 1) { + tls_strerror_printf("Failed generating phase2 challenge"); + goto error; + } if (memcmp(challenge, vp->vp_octets, vp->vp_length) != 0) { fr_strerror_printf("Tunneled challenge is incorrect");