]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Start working on removing our implementation of the rfc4346 PRF
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 27 Jan 2019 15:09:52 +0000 (22:09 +0700)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 27 Jan 2019 15:09:52 +0000 (22:09 +0700)
We can just use OpenSSL's

src/lib/eap/crypto.c
src/lib/eap/tls.c
src/lib/eap/tls.h
src/modules/rlm_eap/types/rlm_eap_fast/eap_fast_crypto.c
src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c

index 3b810bed6e000ae22f8bb205d65fd3dd090c3ef8..3dd987a486f843bb16c54bfdd688c29d86fe3d2c 100644 (file)
@@ -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;
        }
index 0ce8ea6d525e3277617f07e824609de3aa797a21..441104f4613a2c0407b9c538c2376524134a8a01 100644 (file)
@@ -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);
index bec50cb5fc5781b8a844ece31833a485e420fb9c..7fca0e42ece95d75b135cdbf983fc52e6e4bcbd6 100644 (file)
@@ -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);
index a5cb6528c5d90e13abc3511f1df1a9659696fd4d..7dc19d46097653b183c9261cd93e4726bfffea29 100644 (file)
@@ -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
  */
index 2be2527dd7ca8ca7147465314b31f92db83a5b9f..241ee320deeb6ceb5a511d02bd9a3872a6dc4a19 100644 (file)
@@ -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");