]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Move eap-fast PRF functions into the EAP-FAST module
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 20 Jan 2019 14:43:22 +0000 (21:43 +0700)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 20 Jan 2019 14:45:14 +0000 (21:45 +0700)
Many other cleanups

15 files changed:
src/lib/eap/all.mk
src/lib/eap/crypto.c [new file with mode: 0644]
src/lib/eap/mppe_keys.c [deleted file]
src/lib/eap/tls.c
src/lib/eap/tls.h
src/lib/tls/base-h
src/modules/rlm_eap/types/rlm_eap_fast/all.mk.in
src/modules/rlm_eap/types/rlm_eap_fast/eap_fast.c
src/modules/rlm_eap/types/rlm_eap_fast/eap_fast_crypto.c
src/modules/rlm_eap/types/rlm_eap_fast/eap_fast_crypto.h
src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c
src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c
src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c
src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c
src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c

index 451b644096c94ccd83eda320234a5fd4d50ad747..0e4f832f5e222cb75284533a4d3ad3231929c9b1 100644 (file)
@@ -5,7 +5,7 @@ SOURCES := \
        chbind.c
 
 ifneq (${OPENSSL_LIBS},)
-SOURCES                += tls.c mppe_keys.c
+SOURCES                += tls.c crypto.c
 endif
 
 TGT_PREREQS    := libfreeradius-radius.a libfreeradius-util.a
diff --git a/src/lib/eap/crypto.c b/src/lib/eap/crypto.c
new file mode 100644 (file)
index 0000000..1f45956
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ *   This program is 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.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * $Id$
+ * @file lib/eap/mppe_keys.c
+ * @brief MPPE key calculation API
+ *
+ * @author Henrik Eriksson <henriken@axis.com>
+ * @author Lars Viklund <larsv@axis.com>
+ *
+ * @copyright 2002  Axis Communications AB
+ * @copyright 2006  The FreeRADIUS server project
+ */
+
+RCSID("$Id$")
+USES_APPLE_DEPRECATED_API      /* OpenSSL API has been deprecated by Apple */
+
+#define __STDC_WANT_LIB_EXT1__ 1
+#include <string.h>
+
+#include <openssl/hmac.h>
+
+#include <freeradius-devel/util/sha1.h>
+#include <freeradius-devel/tls/base.h>
+
+#include "tls.h"
+#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)
+{
+       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 OPENSSL_VERSION_NUMBER >= 0x10001000L
+       if (SSL_export_keying_material(ssl, out, sizeof(out), prf_label, prf_label_len, NULL, 0, 0) != 1) /* Fallback */
+#endif
+
+       {
+               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;
+
+               (void) SSL_get_server_random(ssl, p, SSL3_RANDOM_SIZE);
+               seed_len += SSL3_RANDOM_SIZE;
+
+               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);
+       }
+
+       RDEBUG2("Adding session keys");
+       p = out;
+       eap_add_reply(request, attr_ms_mppe_recv_key, p, EAP_TLS_MPPE_KEY_LEN);
+       p += EAP_TLS_MPPE_KEY_LEN;
+       eap_add_reply(request, attr_ms_mppe_send_key, p, EAP_TLS_MPPE_KEY_LEN);
+
+       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 *s, uint8_t *buffer, uint8_t *scratch, size_t size, char const *prf_label)
+{
+       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 OPENSSL_VERSION_NUMBER >= 0x10001000L
+       if (SSL_export_keying_material(s, buffer, size, prf_label,
+                                      strlen(prf_label), NULL, 0, 0) == 1) return;
+
+#endif
+
+       len = strlen(prf_label);
+       if (len > 128) len = 128;
+
+       p = seed;
+       memcpy(p, prf_label, len);
+       p += len;
+
+       (void) SSL_get_client_random(s, p, SSL3_RANDOM_SIZE);
+       p += SSL3_RANDOM_SIZE;
+       (void) SSL_get_server_random(s, p, SSL3_RANDOM_SIZE);
+       p += SSL3_RANDOM_SIZE;
+
+       master_key_len = SSL_SESSION_get_master_key(SSL_get_session(s), master_key, sizeof(master_key));
+       eap_crypto_rfc4346_prf(buffer, size, scratch, master_key, master_key_len, seed, p - seed);
+}
+
+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_len)
+{
+       uint8_t         *buff = NULL, *p;
+
+       *out = NULL;
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+       if (!prf_label) goto random_based_session_id;
+
+       switch (SSL_SESSION_get_protocol_version(SSL_get_session(ssl))) {
+       case SSL2_VERSION:      /* Should never happen */
+       case SSL3_VERSION:      /* Should never happen */
+               return - 1;
+
+       case TLS1_VERSION:      /* No Method ID */
+       case TLS1_1_VERSION:    /* No Method ID */
+       case TLS1_2_VERSION:    /* No Method ID */
+#endif
+       random_based_session_id:
+               MEM(buff = p = talloc_array(ctx, uint8_t, sizeof(eap_type) + (2 * SSL3_RANDOM_SIZE)));
+               *p++ = eap_type;
+
+               SSL_get_client_random(ssl, p, SSL3_RANDOM_SIZE);
+               p += SSL3_RANDOM_SIZE;
+               SSL_get_server_random(ssl, p, SSL3_RANDOM_SIZE);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+               break;
+
+       /*
+        *      Session-Id = <EAP-Type> || Method-Id
+        *      Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id", "", 64)
+        */
+       case TLS1_3_VERSION:
+       default:
+       {
+               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_len, NULL, 0, 0);
+       }
+               break;
+       }
+#endif
+       *out = buff;
+
+       return 0;
+}
diff --git a/src/lib/eap/mppe_keys.c b/src/lib/eap/mppe_keys.c
deleted file mode 100644 (file)
index 03acfb8..0000000
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- *   This program is 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.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-/**
- * $Id$
- * @file lib/eap/mppe_keys.c
- * @brief MPPE key calculation API
- *
- * @author Henrik Eriksson <henriken@axis.com>
- * @author Lars Viklund <larsv@axis.com>
- *
- * @copyright 2002  Axis Communications AB
- * @copyright 2006  The FreeRADIUS server project
- */
-
-RCSID("$Id$")
-USES_APPLE_DEPRECATED_API      /* OpenSSL API has been deprecated by Apple */
-
-#define __STDC_WANT_LIB_EXT1__ 1
-#include <string.h>
-
-#include <openssl/hmac.h>
-
-#include <freeradius-devel/util/sha1.h>
-
-#include "tls.h"
-#include "base.h"
-#include "attrs.h"
-
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
-/*
- *     OpenSSL compatibility, to avoid ifdef's through the rest of the code.
- */
-size_t SSL_get_client_random(const SSL *s, unsigned char *out, size_t outlen)
-{
-       if (!outlen) return sizeof(s->s3->client_random);
-
-       if (outlen > sizeof(s->s3->client_random)) outlen = sizeof(s->s3->client_random);
-
-       memcpy(out, s->s3->client_random, outlen);
-       return outlen;
-}
-
-size_t SSL_get_server_random(const SSL *s, unsigned char *out, size_t outlen)
-{
-       if (!outlen) return sizeof(s->s3->server_random);
-
-       if (outlen > sizeof(s->s3->server_random)) outlen = sizeof(s->s3->server_random);
-
-       memcpy(out, s->s3->server_random, outlen);
-       return outlen;
-}
-
-static size_t SSL_SESSION_get_master_key(const SSL_SESSION *s, unsigned char *out, size_t outlen)
-{
-       if (!outlen) return s->master_key_length;
-
-       if (outlen > (size_t)s->master_key_length) outlen = (size_t)s->master_key_length;
-
-       memcpy(out, s->master_key, outlen);
-       return outlen;
-}
-#endif
-
-/*
- * TLS PRF from RFC 2246
- */
-static void P_hash(EVP_MD const *evp_md,
-                  unsigned char const *secret, unsigned int secret_len,
-                  unsigned char const *seed,  unsigned int seed_len,
-                  unsigned char *out, unsigned int out_len)
-{
-       HMAC_CTX *ctx_a, *ctx_out;
-       unsigned char a[HMAC_MAX_MD_CBLOCK];
-       unsigned int 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
-}
-
-/*  EAP-FAST Pseudo-Random Function (T-PRF): RFC 4851, Section 5.5 */
-void T_PRF(unsigned char const *secret, unsigned int secret_len,
-          char const *prf_label,
-          unsigned char const *seed, unsigned int seed_len,
-          unsigned char *out, unsigned int out_len)
-{
-       size_t prf_size = strlen(prf_label);
-       size_t pos;
-       uint8_t *buf;
-
-       if (prf_size > 128) prf_size = 128;
-       prf_size++;     /* include trailing zero */
-
-       buf = talloc_size(NULL, SHA1_DIGEST_LENGTH + prf_size + seed_len + 2 + 1);
-
-       memcpy(buf + SHA1_DIGEST_LENGTH, prf_label, prf_size);
-       if (seed) memcpy(buf + SHA1_DIGEST_LENGTH + prf_size, seed, seed_len);
-       *(uint16_t *)&buf[SHA1_DIGEST_LENGTH + prf_size + seed_len] = htons(out_len);
-       buf[SHA1_DIGEST_LENGTH + prf_size + seed_len + 2] = 1;
-
-       // T1 is just the seed
-       fr_hmac_sha1(buf, buf + SHA1_DIGEST_LENGTH, prf_size + seed_len + 2 + 1, secret, secret_len);
-
-#define MIN(a,b) (((a)>(b)) ? (b) : (a))
-       memcpy(out, buf, MIN(out_len, SHA1_DIGEST_LENGTH));
-
-       pos = SHA1_DIGEST_LENGTH;
-       while (pos < out_len) {
-               buf[SHA1_DIGEST_LENGTH + prf_size + seed_len + 2]++;
-
-               fr_hmac_sha1(buf, buf, SHA1_DIGEST_LENGTH + prf_size + seed_len + 2 + 1, secret, secret_len);
-               memcpy(&out[pos], buf, MIN(out_len - pos, SHA1_DIGEST_LENGTH));
-
-               if (out_len - pos <= SHA1_DIGEST_LENGTH)
-                       break;
-
-               pos += SHA1_DIGEST_LENGTH;
-       }
-
-       memset(buf, 0, SHA1_DIGEST_LENGTH + prf_size + seed_len + 2 + 1);
-       talloc_free(buf);
-}
-
-static void PRF(unsigned char const *secret, unsigned int secret_len,
-               unsigned char const *seed,  unsigned int seed_len,
-               unsigned char *out, unsigned char *buf, unsigned int out_len)
-{
-       unsigned int i;
-       unsigned int len = (secret_len + 1) / 2;
-       uint8_t const *s1 = secret;
-       uint8_t const *s2 = secret + (secret_len - len);
-
-       P_hash(EVP_md5(), s1, len, seed, seed_len, out, out_len);
-       P_hash(EVP_sha1(), s2, len, seed, seed_len, buf, out_len);
-
-       for (i=0; i < out_len; i++) {
-               out[i] ^= buf[i];
-       }
-}
-
-#define EAP_TLS_MPPE_KEY_LEN     32
-
-/** Generate keys according to RFC 2716 and add to the reply
- *
- */
-void eap_tls_gen_mppe_keys(REQUEST *request, SSL *s, char const *prf_label)
-{
-       uint8_t         out[4 * EAP_TLS_MPPE_KEY_LEN];
-       uint8_t         *p;
-       size_t          prf_size;
-       size_t          master_key_len;
-       uint8_t         seed[64 + (2 * SSL3_RANDOM_SIZE)];
-       uint8_t         buf[4 * EAP_TLS_MPPE_KEY_LEN];
-       uint8_t         master_key[SSL_MAX_MASTER_KEY_LENGTH];
-
-       prf_size = strlen(prf_label);
-
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
-       if (SSL_export_keying_material(s, out, sizeof(out), prf_label, prf_size, NULL, 0, 0) != 1) /* Fallback */
-#endif
-
-       {
-               p = seed;
-               memcpy(p, prf_label, prf_size);
-               p += prf_size;
-
-               (void) SSL_get_client_random(s, p, SSL3_RANDOM_SIZE);
-               p += SSL3_RANDOM_SIZE;
-               prf_size += SSL3_RANDOM_SIZE;
-
-               (void) SSL_get_server_random(s, p, SSL3_RANDOM_SIZE);
-               prf_size += SSL3_RANDOM_SIZE;
-
-               master_key_len = SSL_SESSION_get_master_key(SSL_get_session(s), master_key, sizeof(master_key));
-               PRF(master_key, master_key_len, seed, prf_size, out, buf, sizeof(out));
-       }
-
-       RDEBUG2("Adding session keys");
-       p = out;
-       eap_add_reply(request, attr_ms_mppe_recv_key, p, EAP_TLS_MPPE_KEY_LEN);
-       p += EAP_TLS_MPPE_KEY_LEN;
-       eap_add_reply(request, attr_ms_mppe_send_key, p, EAP_TLS_MPPE_KEY_LEN);
-
-       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_tls_gen_challenge(SSL *s, uint8_t *buffer, uint8_t *scratch, size_t size, char const *prf_label)
-{
-       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 OPENSSL_VERSION_NUMBER >= 0x10001000L
-       if (SSL_export_keying_material(s, buffer, size, prf_label,
-                                      strlen(prf_label), NULL, 0, 0) == 1) return;
-
-#endif
-
-       len = strlen(prf_label);
-       if (len > 128) len = 128;
-
-       p = seed;
-       memcpy(p, prf_label, len);
-       p += len;
-
-       (void) SSL_get_client_random(s, p, SSL3_RANDOM_SIZE);
-       p += SSL3_RANDOM_SIZE;
-       (void) SSL_get_server_random(s, p, SSL3_RANDOM_SIZE);
-       p += SSL3_RANDOM_SIZE;
-
-       master_key_len = SSL_SESSION_get_master_key(SSL_get_session(s), master_key, sizeof(master_key));
-       PRF(master_key, master_key_len, seed, p - seed, buffer, scratch, size);
-}
-
-
-/*
- *     Same as before, but for EAP-FAST the order of {server,client}_random is flipped
- */
-void eap_fast_tls_gen_challenge(SSL *s, uint8_t *buffer, uint8_t *scratch, size_t size, char const *prf_label)
-{
-       uint8_t *p;
-       size_t len, master_key_len;
-       uint8_t seed[128 + 2*SSL3_RANDOM_SIZE];
-       uint8_t master_key[SSL_MAX_MASTER_KEY_LENGTH];
-
-       len = strlen(prf_label);
-       if (len > 128) len = 128;
-
-       p = seed;
-       memcpy(p, prf_label, len);
-       p += len;
-       (void) SSL_get_server_random(s, p, SSL3_RANDOM_SIZE);
-       p += SSL3_RANDOM_SIZE;
-       (void) SSL_get_client_random(s, p, SSL3_RANDOM_SIZE);
-       p += SSL3_RANDOM_SIZE;
-
-       master_key_len = SSL_SESSION_get_master_key(SSL_get_session(s), master_key, sizeof(master_key));
-       PRF(master_key, master_key_len, seed, p - seed, buffer, scratch, size);
-}
-
-/*
- *     Actually generates EAP-Session-Id, which is an internal server
- *     attribute.  Not all systems want to send EAP-Key-Name
- */
-void eap_tls_gen_session_id(RADIUS_PACKET *packet, SSL *ssl, uint8_t eap_type)
-{
-       VALUE_PAIR      *vp;
-       uint8_t         *buff = NULL, *p;
-
-       vp = fr_pair_afrom_da(packet, attr_eap_session_id);
-       if (!vp) return;
-
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
-       if (eap_type != FR_EAP_TLS) goto random_based_session_id;
-
-       switch (SSL_SESSION_get_protocol_version(SSL_get_session(ssl))) {
-       case SSL2_VERSION:      /* Should never happen */
-       case SSL3_VERSION:      /* Should never happen */
-               return;
-
-       case TLS1_VERSION:      /* No Method ID */
-       case TLS1_1_VERSION:    /* No Method ID */
-       case TLS1_2_VERSION:    /* No Method ID */
-#endif
-       random_based_session_id:
-               MEM(buff = p = talloc_array(vp, uint8_t, sizeof(eap_type) + SSL3_RANDOM_SIZE + SSL3_RANDOM_SIZE));
-               *p++ = eap_type;
-
-               SSL_get_client_random(ssl, p, SSL3_RANDOM_SIZE);
-               p += SSL3_RANDOM_SIZE;
-               SSL_get_server_random(ssl, p, SSL3_RANDOM_SIZE);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
-               break;
-
-       /*
-        *      Session-Id = <EAP-Type> || Method-Id
-        *      Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id", "", 64)
-        */
-       case TLS1_3_VERSION:
-       default:
-       {
-               char const prf_label[] = "EXPORTER_EAP_TLS_Method-Id";
-
-               MEM(buff = p = talloc_array(vp, uint8_t, sizeof(eap_type) + 64));
-               *p++ = eap_type;
-               SSL_export_keying_material(ssl, p, 64, prf_label, sizeof(prf_label) - 1, NULL, 0, 0);
-       }
-               break;
-       }
-#endif
-
-       fr_pair_value_memsteal(vp, buff);
-       fr_pair_add(&packet->vps, vp);
-}
index 0aa7bf059d1dfc3fe6843b47fe63d626bfe3f012..16ae53da76b2453a99a46a220374b6ddc1effb99 100644 (file)
@@ -245,12 +245,20 @@ int eap_tls_start(eap_session_t *eap_session)
  * We add the MPPE keys here.  These are used by the NAS.  The supplicant
  * will derive the same keys separately.
  *
- * @param eap_session that completed successfully.
+ * @param[in] eap_session              that completed successfully.
+ * @param[in] keying_prf_label         PRF label to use for generating keying material.
+ *                                     If NULL, no MPPE keys will be generated.
+ * @param[in] keying_prf_label_len     Length of the keying PRF label.
+ * @param[in] sessid_prf_label         PRF label to use when generating the session ID.
+ *                                     If NULL, session ID will be based on client/server randoms.
+ * @param[in] sessid_prf_label_len     Length of the session ID PRF label.
  * @return
  *     - 0 on success.
  *     - -1 on failure.
  */
-int eap_tls_success(eap_session_t *eap_session, char const *prf_label)
+int eap_tls_success(eap_session_t *eap_session,
+                   char const *keying_prf_label, size_t keying_prf_label_len,
+                   char const *sessid_prf_label, size_t sessid_prf_label_len)
 {
        REQUEST                 *request = eap_session->request;
        eap_tls_session_t       *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
@@ -291,9 +299,27 @@ int eap_tls_success(eap_session_t *eap_session, char const *prf_label)
        /*
         *      Automatically generate MPPE keying material.
         */
-       if (prf_label) eap_tls_gen_mppe_keys(eap_session->request, tls_session->ssl, prf_label);
+       if (keying_prf_label) eap_crypto_mppe_keys(eap_session->request, tls_session->ssl,
+                                                  keying_prf_label, keying_prf_label_len);
 
-       eap_tls_gen_session_id(eap_session->request->reply, tls_session->ssl, eap_session->type);
+       /*
+        *      Add the TLS session ID to the request
+        */
+       {
+               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,
+                                          sessid_prf_label, sessid_prf_label_len) < 0) return -1;
+
+               MEM(pair_add_reply(&vp, attr_eap_session_id) >= 0);
+               fr_pair_value_memsteal(vp, session_id);
+
+               RINDENT();
+               RDEBUG2("&reply:%pP", vp);
+               REXDENT();
+       }
 
        return 0;
 }
@@ -823,7 +849,7 @@ static eap_tls_status_t eap_tls_handshake(eap_session_t *eap_session)
                 *      Init is finished.  The rest is
                 *      application data.
                 */
-               tls_session->info.content_type = application_data;
+               tls_session->info.content_type = SSL3_RT_APPLICATION_DATA;
                return EAP_TLS_ESTABLISHED;
        }
 
index c7621f285620548cb3aa88a1d01b8029c2a0d2d7..74f73672c9274babfb5ac27f470b5b4ac8a13452 100644 (file)
@@ -157,7 +157,9 @@ eap_tls_status_t    eap_tls_process(eap_session_t *eap_session) CC_HINT(nonnull);
 
 int                    eap_tls_start(eap_session_t *eap_session) CC_HINT(nonnull);
 
-int                    eap_tls_success(eap_session_t *eap_session, char const *prf_label) CC_HINT(nonnull(1));
+int                    eap_tls_success(eap_session_t *eap_session,
+                                       char const *keying_prf_label, size_t keying_prf_label_len,
+                                       char const *sessid_prf_label, size_t sessid_prf_label_len) CC_HINT(nonnull(1));
 
 int                    eap_tls_fail(eap_session_t *eap_session) CC_HINT(nonnull);
 
@@ -167,19 +169,19 @@ 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 */
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
-size_t SSL_get_client_random(const SSL *ssl, unsigned char *out, size_t outlen);
-size_t SSL_get_server_random(const SSL *ssl, unsigned char *out, size_t outlen);
-#endif
 
-void                   T_PRF(unsigned char const *secret, unsigned int secret_len, char const *prf_label, unsigned char const *seed, unsigned int seed_len, unsigned char *out, unsigned int out_len) CC_HINT(nonnull(1,3,6));
+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_tls_gen_mppe_keys(REQUEST *request, SSL *s, char const *prf_label) CC_HINT(nonnull);
+void                   eap_crypto_mppe_keys(REQUEST *request, SSL *ssl,
+                                            char const *prf_label, size_t prf_label_len) CC_HINT(nonnull);
 
-void                   eap_tls_gen_challenge(SSL *ssl, uint8_t *buffer, uint8_t *scratch, size_t size, char const *prf_label) CC_HINT(nonnull);
-void                   eap_fast_tls_gen_challenge(SSL *ssl, uint8_t *buffer, uint8_t *scratch, size_t size, char const *prf_label) CC_HINT(nonnull);
+void                   eap_crypto_challenge(SSL *ssl, uint8_t *buffer, uint8_t *scratch, size_t size, char const *prf_label) CC_HINT(nonnull);
 
-void                   eap_tls_gen_session_id(RADIUS_PACKET *packet, SSL *s, uint8_t type) 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_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 f041d37d3da54610d158aaff9377f8be40f057d1..2efbe6fd6a9229ddd661a1dc6c5c29b92ca7c434 100644 (file)
@@ -341,63 +341,6 @@ struct fr_tls_conf_t {
 
 typedef struct fr_tls_conf_t fr_tls_conf_t;
 
-/*
- *     Following enums from rfc2246
- *
- *     Hmm... since we dpeend on OpenSSL, it would be smarter to
- *     use the OpenSSL names for these.
- */
-enum ContentType {
-       change_cipher_spec = 20,
-       alert = 21,
-       handshake = 22,
-       application_data = 23
-};
-
-enum AlertLevel {
-       warning = 1,
-       fatal = 2
-};
-
-enum AlertDescription {
-       close_notify = 0,
-       unexpected_message = 10,
-       bad_record_mac = 20,
-       decryption_failed = 21,
-       record_overflow = 22,
-       decompression_failure = 30,
-       handshake_failure = 40,
-       bad_certificate = 42,
-       unsupported_certificate = 43,
-       certificate_revoked = 44,
-       certificate_expired = 45,
-       certificate_unknown = 46,
-       illegal_parameter = 47,
-       unknown_ca = 48,
-       access_denied = 49,
-       decode_error = 50,
-       decrypt_error = 51,
-       export_restriction = 60,
-       protocol_version = 70,
-       insufficient_security = 71,
-       internal_error = 80,
-       user_canceled = 90,
-       no_renegotiation = 100
-};
-
-enum HandshakeType {
-       hello_request = 0,
-       client_hello = 1,
-       server_hello = 2,
-       certificate = 11,
-       server_key_exchange  = 12,
-       certificate_request = 13,
-       server_hello_done = 14,
-       certificate_verify = 15,
-       client_key_exchange = 16,
-       handshake_finished = 20
-};
-
 extern int fr_tls_ex_index_vps;
 extern int fr_tls_max_threads;
 
index e9b855f69e9e9e58dc95149a6e91facad8280902..e5af0c4802fd2dab76b4ba7cb6d8590639f51239 100644 (file)
@@ -8,4 +8,4 @@ SOURCES         := $(TARGETNAME).c eap_fast.c eap_fast_crypto.c
 
 SRC_INCDIRS    := ${top_srcdir}/src/modules/rlm_eap/ ${top_srcdir}/src/modules/rlm_eap/lib/base/
 
-TGT_PREREQS    := libfreeradius-radius.a libfreeradius-util.a libfreeradius-eap.a
+TGT_PREREQS    := libfreeradius-radius.a libfreeradius-util.a libfreeradius-tls.a libfreeradius-eap.a
index 78f37d4b322cbfc34e8736209746aa8438742190..dfb28d712018980f24e8b788a7a427b801b6a015 100644 (file)
@@ -1027,7 +1027,7 @@ FR_CODE eap_fast_process(eap_session_t *eap_session, tls_session_t *tls_session)
                }
 
                /*
-                * eap_tls_gen_mppe_keys() is unsuitable for EAP-FAST as Cisco decided
+                * eap_crypto_mppe_keys() is unsuitable for EAP-FAST as Cisco decided
                 * it would be a great idea to flip the recv/send keys around
                 */
                #define EAPTLS_MPPE_KEY_LEN 32
index 8b260c238727a0bbefac05c4a5d633422b3ab83c..a5cb6528c5d90e13abc3511f1df1a9659696fd4d 100644 (file)
@@ -29,6 +29,8 @@ USES_APPLE_DEPRECATED_API     /* OpenSSL API has been deprecated by Apple */
 
 #include <stdio.h>
 #include <freeradius-devel/util/base.h>
+#include <freeradius-devel/tls/base.h>
+#include <freeradius-devel/eap/tls.h>
 
 #include <openssl/evp.h>
 #include <openssl/aes.h>
@@ -36,6 +38,49 @@ USES_APPLE_DEPRECATED_API    /* OpenSSL API has been deprecated by Apple */
 
 #include "eap_fast_crypto.h"
 
+/*  EAP-FAST Pseudo-Random Function (T-PRF): RFC 4851, Section 5.5 */
+void T_PRF(unsigned char const *secret, unsigned int secret_len,
+          char const *prf_label,
+          unsigned char const *seed, unsigned int seed_len,
+          unsigned char *out, unsigned int out_len)
+{
+       size_t prf_size = strlen(prf_label);
+       size_t pos;
+       uint8_t *buf;
+
+       if (prf_size > 128) prf_size = 128;
+       prf_size++;     /* include trailing zero */
+
+       buf = talloc_size(NULL, SHA1_DIGEST_LENGTH + prf_size + seed_len + 2 + 1);
+
+       memcpy(buf + SHA1_DIGEST_LENGTH, prf_label, prf_size);
+       if (seed) memcpy(buf + SHA1_DIGEST_LENGTH + prf_size, seed, seed_len);
+       *(uint16_t *)&buf[SHA1_DIGEST_LENGTH + prf_size + seed_len] = htons(out_len);
+       buf[SHA1_DIGEST_LENGTH + prf_size + seed_len + 2] = 1;
+
+       // T1 is just the seed
+       fr_hmac_sha1(buf, buf + SHA1_DIGEST_LENGTH, prf_size + seed_len + 2 + 1, secret, secret_len);
+
+#define MIN(a,b) (((a)>(b)) ? (b) : (a))
+       memcpy(out, buf, MIN(out_len, SHA1_DIGEST_LENGTH));
+
+       pos = SHA1_DIGEST_LENGTH;
+       while (pos < out_len) {
+               buf[SHA1_DIGEST_LENGTH + prf_size + seed_len + 2]++;
+
+               fr_hmac_sha1(buf, buf, SHA1_DIGEST_LENGTH + prf_size + seed_len + 2 + 1, secret, secret_len);
+               memcpy(&out[pos], buf, MIN(out_len - pos, SHA1_DIGEST_LENGTH));
+
+               if (out_len - pos <= SHA1_DIGEST_LENGTH)
+                       break;
+
+               pos += SHA1_DIGEST_LENGTH;
+       }
+
+       memset(buf, 0, SHA1_DIGEST_LENGTH + prf_size + seed_len + 2 + 1);
+       talloc_free(buf);
+}
+
 // http://stackoverflow.com/a/29838852
 static void NEVER_RETURNS handleErrors(void)
 {
@@ -171,3 +216,28 @@ int eap_fast_decrypt(uint8_t const *ciphertext, size_t ciphertext_len,
                return -1;
        }
 }
+
+/*
+ *     Same as before, but for EAP-FAST the order of {server,client}_random is flipped
+ */
+void eap_fast_tls_gen_challenge(SSL *s, uint8_t *buffer, uint8_t *scratch, size_t size, char const *prf_label)
+{
+       uint8_t         *p;
+       size_t          len, master_key_len;
+       uint8_t         seed[128 + (2 * SSL3_RANDOM_SIZE)];
+       uint8_t         master_key[SSL_MAX_MASTER_KEY_LENGTH];
+
+       len = strlen(prf_label);
+       if (len > 128) len = 128;
+
+       p = seed;
+       memcpy(p, prf_label, len);
+       p += len;
+       (void) SSL_get_server_random(s, p, SSL3_RANDOM_SIZE);
+       p += SSL3_RANDOM_SIZE;
+       (void) SSL_get_client_random(s, p, SSL3_RANDOM_SIZE);
+       p += SSL3_RANDOM_SIZE;
+
+       master_key_len = SSL_SESSION_get_master_key(SSL_get_session(s), master_key, sizeof(master_key));
+       eap_crypto_rfc4346_prf(buffer, size, scratch, master_key, master_key_len, seed, p - seed);
+}
index a8976211d2204534a53d2be8c5e36f1575b9930b..8daac4532e3d04f7b446eba2b4c853e8e48ee22b 100644 (file)
@@ -27,6 +27,8 @@
  */
 RCSIDH(eap_fast_crypto_h, "$Id$")
 
+void T_PRF(unsigned char const *secret, unsigned int secret_len, char const *prf_label, unsigned char const *seed, unsigned int seed_len, unsigned char *out, unsigned int out_len) CC_HINT(nonnull(1,3,6));
+
 int eap_fast_encrypt(uint8_t const *plaintext, size_t plaintext_len,
                     uint8_t const *aad, size_t aad_len,
                     uint8_t const *key, uint8_t *iv, unsigned char *ciphertext,
@@ -35,3 +37,5 @@ int eap_fast_encrypt(uint8_t const *plaintext, size_t plaintext_len,
 int eap_fast_decrypt(uint8_t const *ciphertext, size_t ciphertext_len,
                     uint8_t const *aad, size_t aad_len,
                     uint8_t const *tag, uint8_t const *key, uint8_t const *iv, uint8_t *plaintext);
+
+void eap_fast_tls_gen_challenge(SSL *ssl, uint8_t *buffer, uint8_t *scratch, size_t size, char const *prf_label) CC_HINT(nonnull);
index 9a721e3daa1fa04df3ea8766e46cafd875f8a14a..bfb2389c9bb89bcf8217e1ba6bcd4eec629e92c3 100644 (file)
@@ -542,7 +542,7 @@ static rlm_rcode_t mod_process(void *instance, eap_session_t *eap_session)
                 *      Success: Automatically return MPPE keys.
                 */
        case FR_CODE_ACCESS_ACCEPT:
-               if (eap_tls_success(eap_session, NULL) < 0) return RLM_MODULE_FAIL;
+               if (eap_tls_success(eap_session, NULL, 0, NULL, 0) < 0) return RLM_MODULE_FAIL;
                return RLM_MODULE_OK;
 
                /*
index 8a438fc3a9a6c7aab17047fb0b00a80d1b81f2b2..53234d36bd4c100f7a3eba379541975eb67b2f81 100644 (file)
@@ -218,10 +218,16 @@ static rlm_rcode_t mod_process(void *instance, eap_session_t *eap_session)
                break;
 
        case RLM_MODULE_OK:
+       {
+               static char keying_prf_label[] = "client EAP encryption";
+
                /*
                 *      Success: Automatically return MPPE keys.
                 */
-               if (eap_tls_success(eap_session, "client EAP encryption") < 0) return 0;
+               if (eap_tls_success(eap_session,
+                                   keying_prf_label, sizeof(keying_prf_label) - 1,
+                                   NULL, 0) < 0) return 0;
+       }
                break;
 
                /*
index 5105e3d04005e525cf3614f2cb4caac183659e58..9676d5896460c4ea50b7b78110efb4d0f4bf4617 100644 (file)
@@ -168,8 +168,6 @@ static rlm_rcode_t mod_process(void *instance, eap_session_t *eap_session)
         */
        case EAP_TLS_ESTABLISHED:
        {
-               char const *prf_label = NULL;
-
                if (inst->virtual_server) return eap_tls_virtual_server(inst, eap_session);
 
 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
@@ -187,18 +185,31 @@ static rlm_rcode_t mod_process(void *instance, eap_session_t *eap_session)
                case TLS1_1_VERSION:
                case TLS1_2_VERSION:
 #endif
-                       prf_label = "client EAP encryption";
+               {
+                       static char const keying_prf_label[] = "client EAP encryption";
+
+                       if (eap_tls_success(eap_session,
+                                           keying_prf_label, sizeof(keying_prf_label) - 1,
+                                           NULL, 0) < 0) return RLM_MODULE_FAIL;
+               }
 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
                        break;
 
                case TLS1_3_VERSION:
                default:
-                       prf_label = "EXPORTER_EAP_TLS_Key_Material";
+               {
+                       static char const keying_prf_label[] = "EXPORTER_EAP_TLS_Key_Material";
+                       static char const sessid_prf_label[] = "EXPORTER_EAP_TLS_Method-Id";
+
+                       if (eap_tls_success(eap_session,
+                                           keying_prf_label, sizeof(keying_prf_label) - 1,
+                                           sessid_prf_label, sizeof(sessid_prf_label) - 1) < 0) return RLM_MODULE_FAIL;
+               }
                        break;
 #endif
                }
 
-               if (eap_tls_success(eap_session, prf_label) < 0) return RLM_MODULE_FAIL;
+
        }
                return RLM_MODULE_OK;
 
index 23df6fdbc8c73d063f24fc006ee2356c71841775..e99db55e0cdd49d424547bc9204361b852ee3024 100644 (file)
@@ -139,6 +139,7 @@ static rlm_rcode_t mod_process(void *arg, eap_session_t *eap_session)
        tls_session_t           *tls_session = eap_tls_session->tls_session;
        ttls_tunnel_t           *tunnel = NULL;
        REQUEST                 *request = eap_session->request;
+       static char             keying_prf_label[] = "ttls keying material";
 
        if (tls_session->opaque) tunnel = talloc_get_type_abort(tls_session->opaque, ttls_tunnel_t);
 
@@ -169,11 +170,14 @@ static rlm_rcode_t mod_process(void *arg, eap_session_t *eap_session)
                }
 
                if (tunnel && tunnel->authenticated) {
+
                do_keys:
                        /*
                         *      Success: Automatically return MPPE keys.
                         */
-                       if (eap_tls_success(eap_session, "ttls keying material") < 0) return RLM_MODULE_FAIL;
+                       if (eap_tls_success(eap_session,
+                                           keying_prf_label, sizeof(keying_prf_label) - 1,
+                                           NULL, 0) < 0) return RLM_MODULE_FAIL;
                        return RLM_MODULE_OK;
                } else {
                        eap_tls_request(eap_session);
index 33aec4c75513b2d7d71b295f4f1527504d2b0eae..e7ab359b8df03bdf8198458aaf463b24edc70213 100644 (file)
@@ -267,7 +267,7 @@ do_value:
                                goto error;
                        }
 
-                       eap_tls_gen_challenge(ssl, challenge, scratch,
+                       eap_crypto_challenge(ssl, challenge, scratch,
                                              sizeof(challenge), "ttls challenge");
 
                        if (memcmp(challenge, vp->vp_octets, vp->vp_length) != 0) {