From: Alan T. DeKok Date: Mon, 21 Jun 2021 19:44:44 +0000 (-0400) Subject: move the various PRF labels into a struct X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=79c364fe273c6038d3af66685054d52be8d159be;p=thirdparty%2Ffreeradius-server.git move the various PRF labels into a struct in order to allow for TLS 1.3 --- diff --git a/src/lib/eap/crypto.c b/src/lib/eap/crypto.c index ea4240fbdf6..c813ec8088a 100644 --- a/src/lib/eap/crypto.c +++ b/src/lib/eap/crypto.c @@ -42,17 +42,59 @@ USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */ #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; } @@ -65,7 +107,7 @@ int eap_crypto_mppe_keys(request_t *request, SSL *ssl, char const *prf_label, si 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); @@ -91,22 +133,14 @@ int eap_crypto_tls_session_id(TALLOC_CTX *ctx, #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 */ @@ -127,15 +161,20 @@ int eap_crypto_tls_session_id(TALLOC_CTX *ctx, break; /* - * Session-Id = || Method-Id * Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id", "", 64) + * Session-Id = || 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; } diff --git a/src/lib/eap/tls.c b/src/lib/eap/tls.c index b9853ef7e96..b5ea1ede070 100644 --- a/src/lib/eap/tls.c +++ b/src/lib/eap/tls.c @@ -254,19 +254,12 @@ int eap_tls_start(request_t *request, eap_session_t *eap_session) * * @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; @@ -281,11 +274,12 @@ int eap_tls_success(request_t *request, eap_session_t *eap_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 @@ -295,9 +289,8 @@ int eap_tls_success(request_t *request, eap_session_t *eap_session, 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; } diff --git a/src/lib/eap/tls.h b/src/lib/eap/tls.h index d01e2354e6a..5d63710780e 100644 --- a/src/lib/eap/tls.h +++ b/src/lib/eap/tls.h @@ -151,6 +151,21 @@ typedef struct { 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; @@ -161,9 +176,7 @@ unlang_action_t eap_tls_process(request_t *request, eap_session_t *eap_session) 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); @@ -174,11 +187,14 @@ int eap_tls_compose(request_t *request, eap_session_t *eap_session, 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, diff --git a/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c b/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c index 1deac3f50b0..a65b3a01dca 100644 --- a/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c +++ b/src/modules/rlm_eap/types/rlm_eap_fast/rlm_eap_fast.c @@ -454,10 +454,14 @@ static unlang_action_t mod_handshake_resume(rlm_rcode_t *p_result, UNUSED module 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 diff --git a/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c b/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c index 438f44f3aef..12baf2bc704 100644 --- a/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c +++ b/src/modules/rlm_eap/types/rlm_eap_peap/rlm_eap_peap.c @@ -217,14 +217,16 @@ static unlang_action_t mod_handshake_resume(rlm_rcode_t *p_result, module_ctx_t 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; /* diff --git a/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c b/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c index 55c0000880b..2075ea21197 100644 --- a/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c +++ b/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c @@ -72,52 +72,6 @@ fr_dict_attr_autoload_t rlm_eap_tls_dict_attr[] = { { 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) { @@ -140,7 +94,14 @@ static unlang_action_t mod_handshake_resume(rlm_rcode_t *p_result, UNUSED module * 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 @@ -155,7 +116,7 @@ static unlang_action_t mod_handshake_resume(rlm_rcode_t *p_result, UNUSED module * never completed. */ return fr_tls_cache_pending_push(request, tls_session); - + } /* * The TLS code is still working on the TLS diff --git a/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c b/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c index ffd97ba78ad..ca8ff8ec83d 100644 --- a/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c +++ b/src/modules/rlm_eap/types/rlm_eap_ttls/rlm_eap_ttls.c @@ -138,7 +138,6 @@ static unlang_action_t mod_handshake_resume(rlm_rcode_t *p_result, UNUSED module 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, "")); @@ -161,13 +160,16 @@ static unlang_action_t mod_handshake_resume(rlm_rcode_t *p_result, UNUSED module } 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; /* @@ -319,6 +321,7 @@ static unlang_action_t mod_session_init(rlm_rcode_t *p_result, module_ctx_t cons } tls_session->opaque = ttls_alloc(tls_session, inst); + eap_session->process = mod_handshake_process; RETURN_MODULE_OK;