#include "base.h"
#include "attrs.h"
+/** Initialize the PRF label fields
+ *
+ */
+void eap_crypto_prf_label_init(eap_tls_prf_label_t *prf_label, eap_session_t *eap_session,
+ char const *keying_prf_label, size_t keying_prf_label_len)
+{
+#ifdef TLS1_3_VERSION
+ eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
+
+ if (eap_tls_session->tls_session->info.version == TLS1_3_VERSION) {
+ prf_label->keying_prf_label = "EXPORTER_EAP_TLS_Key_Material";
+ prf_label->keying_prf_label_len = sizeof("EXPORTER_EAP_TLS_Key_Material") -1;
+
+ prf_label->sessid_prf_label = "EXPORTER_EAP_TLS_Method-Id";
+ prf_label->sessid_prf_label_len = sizeof("EXPORTER_EAP_TLS_Method-Id") - 1;
+
+ prf_label->context[0] = eap_session->type;
+ prf_label->context_len = 1;
+ prf_label->use_context = 1;
+ return;
+ }
+#endif
+
+ prf_label->keying_prf_label = keying_prf_label;
+ prf_label->keying_prf_label_len = keying_prf_label_len;
+
+ prf_label->sessid_prf_label = NULL;
+ prf_label->sessid_prf_label_len = 0;
+
+ prf_label->context[0] = 0;
+ prf_label->context_len = 0;
+ prf_label->use_context = 0;
+}
+
+
#define EAP_TLS_MPPE_KEY_LEN 32
-/** Generate keys according to RFC 2716 and add to the reply
+/** Generate keys according to RFC 5216 and add to the reply
*
*/
-int eap_crypto_mppe_keys(request_t *request, SSL *ssl, char const *prf_label, size_t prf_label_len)
+int eap_crypto_mppe_keys(request_t *request, SSL *ssl, eap_tls_prf_label_t *prf_label)
{
uint8_t out[4 * EAP_TLS_MPPE_KEY_LEN];
uint8_t *p;
- if (SSL_export_keying_material(ssl, out, sizeof(out), prf_label, prf_label_len, NULL, 0, 0) != 1) {
+ if (!prf_label->keying_prf_label) return 0;
+
+ if (SSL_export_keying_material(ssl, out, sizeof(out),
+ prf_label->keying_prf_label,
+ prf_label->keying_prf_label_len,
+ prf_label->context,
+ prf_label->context_len,
+ prf_label->use_context) != 1) {
fr_tls_log_error(request, "Failed generating MPPE keys");
return -1;
}
RDEBUG3("Key Derivation Function input");
RINDENT();
- RDEBUG3("prf label : %pV", fr_box_strvalue_len(prf_label, prf_label_len));
+ RDEBUG3("prf label : %s", prf_label->keying_prf_label);
master_key_len = SSL_SESSION_get_master_key(SSL_get_session(ssl), master_key, sizeof(master_key));
RDEBUG3("master session key : %pH", fr_box_octets(master_key, master_key_len));
random_len = SSL_get_client_random(ssl, random, SSL3_RANDOM_SIZE);
#if OPENSSL_VERSION_NUMBER < 0x10101000L
UNUSED
#endif
- request_t *request, SSL *ssl,
- uint8_t **out, uint8_t eap_type,
-#if OPENSSL_VERSION_NUMBER < 0x10101000L
- UNUSED
-#endif
- char const *prf_label,
-#if OPENSSL_VERSION_NUMBER < 0x10101000L
- UNUSED
-#endif
- size_t prf_label_len)
+ request_t *request, SSL *ssl, eap_tls_prf_label_t *prf_label,
+ uint8_t **out, uint8_t eap_type)
{
uint8_t *buff = NULL, *p;
*out = NULL;
- if (!prf_label) goto random_based_session_id;
+ if (!prf_label->sessid_prf_label) goto random_based_session_id;
switch (SSL_SESSION_get_protocol_version(SSL_get_session(ssl))) {
case SSL2_VERSION: /* Should never happen */
break;
/*
- * Session-Id = <EAP-Type> || Method-Id
* Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id", "", 64)
+ * Session-Id = <EAP-Type> || Method-Id
*/
case TLS1_3_VERSION:
default:
{
MEM(buff = p = talloc_array(ctx, uint8_t, sizeof(eap_type) + 64));
*p++ = eap_type;
- if (SSL_export_keying_material(ssl, p, 64, prf_label, prf_label_len, NULL, 0, 0) != 1) {
+ if (SSL_export_keying_material(ssl, p, 64,
+ prf_label->sessid_prf_label,
+ prf_label->sessid_prf_label_len,
+ prf_label->context,
+ prf_label->context_len,
+ prf_label->use_context) != 1) {
fr_tls_log_error(request, "Failed generating TLS session ID");
return -1;
}
*
* @param[in] request The current subrequest.
* @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.
+ * @param[in] prf_label PRF label struct
* @return
* - 0 on success.
* - -1 on failure.
*/
-int eap_tls_success(request_t *request, 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)
+int eap_tls_success(request_t *request, eap_session_t *eap_session, eap_tls_prf_label_t *prf_label)
{
eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
fr_tls_session_t *tls_session = eap_tls_session->tls_session;
if (eap_tls_compose(request, eap_session, EAP_TLS_ESTABLISHED,
eap_tls_session->base_flags, NULL, 0, 0) < 0) return -1;
+ if (!prf_label) return 0;
+
/*
* Automatically generate MPPE keying material.
*/
- if (keying_prf_label) if (eap_crypto_mppe_keys(request->parent, tls_session->ssl,
- keying_prf_label, keying_prf_label_len) < 0) return -1;
+ if (eap_crypto_mppe_keys(request->parent, tls_session->ssl, prf_label) < 0) return -1;
/*
* Add the EAP session ID to the request
fr_pair_t *vp;
MEM(pair_append_reply(&vp, attr_eap_session_id) >= 0);
- if (eap_crypto_tls_session_id(vp, request, tls_session->ssl,
- &session_id, eap_session->type,
- sessid_prf_label, sessid_prf_label_len) < 0) {
+ if (eap_crypto_tls_session_id(vp, request, tls_session->ssl, prf_label,
+ &session_id, eap_session->type) < 0) {
pair_delete_reply(vp);
return -1;
}
size_t record_in_recvd_len; //!< How much of the record we've received so far.
} eap_tls_session_t;
+typedef struct {
+ char const *keying_prf_label; //!< PRF label to use for generating keying material.
+ //!< If NULL, no MPPE keys will be generated.
+ size_t keying_prf_label_len; //!< length of the keying PRF label.
+
+ char const *sessid_prf_label; //!< PRF label to use when generating the session ID.
+ //!< If NULL, session ID will be based on client/server randoms.
+ size_t sessid_prf_label_len; //!< Length of the session ID PRF label.
+
+ uint8_t context[1]; //!< for TLS 1.3 context, is the EAP Type code
+ size_t context_len; //!< length of the context
+
+ int use_context; //!< for SSL_export_keying_material().
+} eap_tls_prf_label_t;
+
extern fr_table_num_ordered_t const eap_tls_status_table[];
extern size_t eap_tls_status_table_len;
int eap_tls_start(request_t *request, eap_session_t *eap_session) CC_HINT(nonnull);
-int eap_tls_success(request_t *request, 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_success(request_t *request, eap_session_t *eap_session, eap_tls_prf_label_t *prf_label) CC_HINT(nonnull(1,2));
int eap_tls_fail(request_t *request, eap_session_t *eap_session) CC_HINT(nonnull);
fr_tls_record_t *record, size_t record_len, size_t frag_len);
/* MPPE key generation */
-int eap_crypto_mppe_keys(request_t *request, SSL *ssl,
- char const *prf_label, size_t prf_label_len) CC_HINT(nonnull);
+void eap_crypto_prf_label_init(eap_tls_prf_label_t *prf_label, eap_session_t *eap_session,
+ char const *keying_prf_label, size_t keying_prf_label_len);
+
+int eap_crypto_mppe_keys(request_t *request, SSL *ssl, eap_tls_prf_label_t *prf_label) CC_HINT(nonnull);
-int eap_crypto_tls_session_id(TALLOC_CTX *ctx, request_t *request, SSL *ssl, uint8_t **out,
- uint8_t eap_type, char const *prf_label, size_t prf_label_len);
+int eap_crypto_tls_session_id(TALLOC_CTX *ctx, request_t *request,
+ SSL *ssl, eap_tls_prf_label_t *prf_label, uint8_t **out,
+ uint8_t eap_type);
/* EAP-TLS framework */
eap_tls_session_t *eap_tls_session_init(request_t *request, eap_session_t *eap_session,
RETURN_MODULE_HANDLED;
/*
- * Success: Automatically return MPPE keys.
+ * Success.
*/
case FR_RADIUS_CODE_ACCESS_ACCEPT:
- if (eap_tls_success(request, eap_session, NULL, 0, NULL, 0) < 0) RETURN_MODULE_FAIL;
+ if (eap_tls_success(request, eap_session, NULL) < 0) RETURN_MODULE_FAIL;
+
+ /*
+ * @todo - generate MPPE keys, which have their own magical deriviation.
+ */
/*
* Write the session to the session cache
case RLM_MODULE_OK:
{
- static char keying_prf_label[] = "client EAP encryption";
+ eap_tls_prf_label_t prf_label;
+
+ eap_crypto_prf_label_init(&prf_label, eap_session,
+ "client EAP encryption",
+ sizeof("client EAP encryption") - 1);
/*
* Success: Automatically return MPPE keys.
*/
- if (eap_tls_success(request, eap_session,
- keying_prf_label, sizeof(keying_prf_label) - 1,
- NULL, 0) < 0) RETURN_MODULE_FAIL;
+ if (eap_tls_success(request, eap_session, &prf_label) > 0) RETURN_MODULE_FAIL;
*p_result = rcode;
/*
{ NULL }
};
-static unlang_action_t eap_tls_success_with_prf(rlm_rcode_t *p_result, request_t *request, eap_session_t *eap_session)
-{
-#if OPENSSL_VERSION_NUMBER >= 0x10101000L
- eap_tls_session_t *eap_tls_session = talloc_get_type_abort(eap_session->opaque, eap_tls_session_t);
- fr_tls_session_t *tls_session = eap_tls_session->tls_session;
-
- /*
- * Set the PRF label based on the TLS version negotiated
- * in the handshake.
- */
- switch (SSL_SESSION_get_protocol_version(SSL_get_session(tls_session->ssl))) {
- case SSL2_VERSION: /* Should never happen */
- case SSL3_VERSION: /* Should never happen */
- fr_assert(0);
- RETURN_MODULE_INVALID;
-
- case TLS1_VERSION:
- case TLS1_1_VERSION:
- case TLS1_2_VERSION:
-#endif
- {
- static char const keying_prf_label[] = "client EAP encryption";
-
- if (eap_tls_success(request, eap_session,
- keying_prf_label, sizeof(keying_prf_label) - 1,
- NULL, 0) < 0) RETURN_MODULE_FAIL;
- }
-#if OPENSSL_VERSION_NUMBER >= 0x10101000L
- break;
-
- case TLS1_3_VERSION:
- default:
- {
- 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(request, eap_session,
- keying_prf_label, sizeof(keying_prf_label) - 1,
- sessid_prf_label, sizeof(sessid_prf_label) - 1) < 0) RETURN_MODULE_FAIL;
- }
- break;
- }
-#endif
- RETURN_MODULE_OK;
-}
-
static unlang_action_t mod_handshake_resume(rlm_rcode_t *p_result, UNUSED module_ctx_t const *mctx,
request_t *request, void *rctx)
{
* it accepts the certificates, too.
*/
case EAP_TLS_ESTABLISHED:
- if (eap_tls_success_with_prf(p_result, request, eap_session) < 0) RETURN_MODULE_FAIL;
+ {
+ eap_tls_prf_label_t prf_label;
+
+ eap_crypto_prf_label_init(&prf_label, eap_session,
+ "client EAP encryption",
+ sizeof("client EAP encryption") - 1);
+
+ if (eap_tls_success(request, eap_session, &prf_label) < 0) RETURN_MODULE_FAIL;
/*
* Write the session to the session cache
* never completed.
*/
return fr_tls_cache_pending_push(request, tls_session);
-
+ }
/*
* The TLS code is still working on the TLS
fr_tls_session_t *tls_session = eap_tls_session->tls_session;
ttls_tunnel_t *tunnel = talloc_get_type_abort(tls_session->opaque, ttls_tunnel_t);
- static char keying_prf_label[] = "ttls keying material";
if ((eap_tls_session->state == EAP_TLS_INVALID) || (eap_tls_session->state == EAP_TLS_FAIL)) {
REDEBUG("[eap-tls process] = %s", fr_table_str_by_value(eap_tls_status_table, eap_tls_session->state, "<INVALID>"));
}
if (tunnel && tunnel->authenticated) {
+ eap_tls_prf_label_t prf_label;
+
do_keys:
+ eap_crypto_prf_label_init(&prf_label, eap_session,
+ "ttls keying material",
+ sizeof("ttls keying material") - 1);
/*
* Success: Automatically return MPPE keys.
*/
- if (eap_tls_success(request, eap_session,
- keying_prf_label, sizeof(keying_prf_label) - 1,
- NULL, 0) < 0) RETURN_MODULE_FAIL;
+ if (eap_tls_success(request, eap_session, &prf_label) < 0) RETURN_MODULE_FAIL;
*p_result = RLM_MODULE_OK;
/*
}
tls_session->opaque = ttls_alloc(tls_session, inst);
+
eap_session->process = mod_handshake_process;
RETURN_MODULE_OK;