]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
move the various PRF labels into a struct
authorAlan T. DeKok <aland@freeradius.org>
Mon, 21 Jun 2021 19:44:44 +0000 (15:44 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 21 Jun 2021 20:53:29 +0000 (16:53 -0400)
in order to allow for TLS 1.3

src/lib/eap/crypto.c
src/lib/eap/tls.c
src/lib/eap/tls.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

index ea4240fbdf6def448af0f8a021c72cf0cabe34f4..c813ec8088aae758285099a472db051bddfa263c 100644 (file)
@@ -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 = <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;
                }
index b9853ef7e9685ac8b77800734a3e14e6006b421b..b5ea1ede0707901122a5edf38e351c7d2dab5def 100644 (file)
@@ -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;
                }
index d01e2354e6a35691e3ba2c5dfa353f3728f71a95..5d63710780e3beabd8dcb6610f7c4a32fca5ef58 100644 (file)
@@ -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,
index 1deac3f50b00360941558f0f7be7a116389b2c29..a65b3a01dca94c843154fd5d16a105f188de237b 100644 (file)
@@ -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
index 438f44f3aef28d64d3d819e143b821b1f66392d2..12baf2bc70479aedef095ed21e3694436ffc875d 100644 (file)
@@ -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;
 
                /*
index 55c0000880bacacae7e9fb5970d25cfa5d7ceca4..2075ea211978301fb669ab7515c950dbee43d66e 100644 (file)
@@ -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
index ffd97ba78ad50fa3577b421c8ff59f8ca3beed9f..ca8ff8ec83dffca33eef5c27d45b0d8a6fb95208 100644 (file)
@@ -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, "<INVALID>"));
@@ -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;