From 5195b79eed1b8394e6c2bc0553e6ab30ec13a56b Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Tue, 4 Feb 2020 16:04:53 +0100 Subject: [PATCH] method_ttls: Reintroduce Signed-off-by: Simon Rozman --- lib/TLS/include/Method.h | 13 ++++++++ lib/TLS/src/Method.cpp | 67 ++++++++++++++++++--------------------- lib/TTLS/include/Method.h | 25 ++++++++++++++- lib/TTLS/src/Method.cpp | 53 +++++++++++++++++++++++++++++++ lib/TTLS/src/Module.cpp | 8 +++-- 5 files changed, 125 insertions(+), 41 deletions(-) diff --git a/lib/TLS/include/Method.h b/lib/TLS/include/Method.h index c1c8388..1495179 100644 --- a/lib/TLS/include/Method.h +++ b/lib/TLS/include/Method.h @@ -163,6 +163,19 @@ namespace eap _Inout_ EapPeerMethodResult *pResult); protected: + /// + /// Pushes keying material to the inner method. + /// + virtual void push_keying_material(); + + /// + /// Retrieves keying material. + /// + /// \param[out] recv_key Enc-RECV-Key, 32 bytes + /// \param[out] send_key Enc-SEND-Key, 32 bytes + /// + virtual void get_keying_material(_Out_ sanitizing_blob_xf<32> &recv_key, _Out_ sanitizing_blob_xf<32> &send_key); + /// /// Decrypts data and forwards it to the inner method. /// diff --git a/lib/TLS/src/Method.cpp b/lib/TLS/src/Method.cpp index 5a6f4a2..636c007 100644 --- a/lib/TLS/src/Method.cpp +++ b/lib/TLS/src/Method.cpp @@ -420,23 +420,7 @@ EapPeerMethodResponseAction eap::method_tls::process_request_packet( m_phase = phase_t::finished; m_cfg.m_last_status = config_method::status_t::auth_failed; // Blame protocol if we fail beyond this point. - - method_mschapv2_diameter *inner_mschapv2 = dynamic_cast(m_inner.get()); - if (inner_mschapv2) { - // Push EAP-TTLS keying material to inner MSCHAPv2 method. - static const DWORD key_id = 0x02; // EAP-TTLSv0 Challenge Data - static const SecPkgContext_EapPrfInfo prf_info = { 0, sizeof(key_id), (PBYTE)&key_id }; - if (FAILED(status = SetContextAttributes(m_sc_ctx, SECPKG_ATTR_EAP_PRF_INFO, (void*)&prf_info, sizeof(prf_info)))) - throw sec_runtime_error(status, __FUNCTION__ " Error setting TTLS PRF in Schannel."); - - SecPkgContext_EapKeyBlock key_block; - if (FAILED(status = QueryContextAttributes(m_sc_ctx, SECPKG_ATTR_EAP_KEY_BLOCK, &key_block))) - throw sec_runtime_error(status, __FUNCTION__ " Error generating PRF in Schannel."); - - inner_mschapv2->set_challenge_data(key_block.rgbKeys, key_block.rgbKeys[sizeof(challenge_mschapv2)]); - - SecureZeroMemory(&key_block, sizeof(key_block)); - } + push_keying_material(); // Piggyback initial inner response. decrypt_request_data(); @@ -542,32 +526,17 @@ void eap::method_tls::get_result( m_eap_attr.clear(); } - // Derive MSK keys. - DWORD key_id = - m_cfg.get_method_id() == eap_type_t::ttls ? 0x01 : // EAP-TTLSv0 Keying Material - 0x00; // PPP EAP TLS Key Data - const SecPkgContext_EapPrfInfo prf_info = { 0, sizeof(key_id), (PBYTE)&key_id }; - SECURITY_STATUS status = SetContextAttributes(m_sc_ctx, SECPKG_ATTR_EAP_PRF_INFO, (void*)&prf_info, sizeof(prf_info)); - if (FAILED(status)) - throw sec_runtime_error(status, __FUNCTION__ " Error setting PRF in Schannel."); - - SecPkgContext_EapKeyBlock key_block; - status = QueryContextAttributes(m_sc_ctx, SECPKG_ATTR_EAP_KEY_BLOCK, &key_block); - if (FAILED(status)) - throw sec_runtime_error(status, __FUNCTION__ " Error generating MSK in Schannel."); - const unsigned char *_key_block = key_block.rgbKeys; + // Make MSK keys. + sanitizing_blob_xf<32> recv, send; + get_keying_material(recv, send); // MSK: MPPE-Recv-Key - a.create_ms_mppe_key(16, _key_block, 32); + a.create_ms_mppe_key(16, recv.data, sizeof(recv.data)); m_eap_attr.push_back(std::move(a)); - _key_block += 32; // MSK: MPPE-Send-Key - a.create_ms_mppe_key(17, _key_block, 32); + a.create_ms_mppe_key(17, send.data, sizeof(send.data)); m_eap_attr.push_back(std::move(a)); - _key_block += 32; - - SecureZeroMemory(&key_block, sizeof(key_block)); // Append blank EAP attribute. m_eap_attr.push_back(eap_attr::blank); @@ -587,6 +556,30 @@ void eap::method_tls::get_result( } +void eap::method_tls::push_keying_material() +{ +} + + +void eap::method_tls::get_keying_material(_Out_ sanitizing_blob_xf<32> &recv_key, _Out_ sanitizing_blob_xf<32> &send_key) +{ + // Derive MSK keys. + DWORD key_id = 0x00; // PPP EAP TLS Key Data + const SecPkgContext_EapPrfInfo prf_info = { 0, sizeof(key_id), (PBYTE)&key_id }; + SECURITY_STATUS status = SetContextAttributes(m_sc_ctx, SECPKG_ATTR_EAP_PRF_INFO, (void*)&prf_info, sizeof(prf_info)); + if (FAILED(status)) + throw sec_runtime_error(status, __FUNCTION__ " Error setting PRF in Schannel."); + + SecPkgContext_EapKeyBlock key_block; + status = QueryContextAttributes(m_sc_ctx, SECPKG_ATTR_EAP_KEY_BLOCK, &key_block); + if (FAILED(status)) + throw sec_runtime_error(status, __FUNCTION__ " Error generating MSK in Schannel."); + memcpy(recv_key.data, key_block.rgbKeys , 32); + memcpy(send_key.data, key_block.rgbKeys + 32, 32); + SecureZeroMemory(&key_block, sizeof(key_block)); +} + + EapPeerMethodResponseAction eap::method_tls::decrypt_request_data() { if (!(m_sc_ctx.m_attrib & ISC_RET_CONFIDENTIALITY)) diff --git a/lib/TTLS/include/Method.h b/lib/TTLS/include/Method.h index fbac6ff..0c9ed7c 100644 --- a/lib/TTLS/include/Method.h +++ b/lib/TTLS/include/Method.h @@ -21,6 +21,7 @@ namespace eap { class method_eapmsg; + class method_ttls; } #pragma once @@ -29,7 +30,7 @@ namespace eap #include "Credentials.h" #include "TTLS.h" -#include "../../EAPBase/include/Method.h" +#include "../../TLS/include/Method.h" namespace eap @@ -88,5 +89,27 @@ namespace eap sanitizing_blob m_packet_res; ///< Response packet }; + + /// + /// EAP-TTLS method + /// + class method_ttls : public method_tls + { + public: + /// + /// Constructs an EAP-TTLS method + /// + /// \param[in] mod EAP module to use for global services + /// \param[in] cfg Method configuration + /// \param[in] cred User credentials + /// \param[in] inner Inner method + /// + method_ttls(_In_ module &mod, _In_ config_method_ttls &cfg, _In_ credentials_tls_tunnel &cred, _In_ method *inner); + + protected: + virtual void push_keying_material(); + virtual void get_keying_material(_Out_ sanitizing_blob_xf<32> &recv_key, _Out_ sanitizing_blob_xf<32> &send_key); + }; + /// @} } diff --git a/lib/TTLS/src/Method.cpp b/lib/TTLS/src/Method.cpp index e155624..b44ecb7 100644 --- a/lib/TTLS/src/Method.cpp +++ b/lib/TTLS/src/Method.cpp @@ -20,6 +20,8 @@ #include "StdAfx.h" +#pragma comment(lib, "Secur32.lib") + using namespace std; using namespace winstd; @@ -149,3 +151,54 @@ void eap::method_eapmsg::get_response_packet( packet.assign(m_packet_res.cbegin(), m_packet_res.cend()); } } + + +////////////////////////////////////////////////////////////////////// +// eap::method_ttls +////////////////////////////////////////////////////////////////////// + +eap::method_ttls::method_ttls(_In_ module &mod, _In_ config_method_ttls &cfg, _In_ credentials_tls_tunnel &cred, _In_ method *inner) : + method_tls(mod, cfg, cred, inner) +{ +} + + +void eap::method_ttls::push_keying_material() +{ + method_mschapv2_diameter *inner_mschapv2 = dynamic_cast(m_inner.get()); + if (inner_mschapv2) { + // Push EAP-TTLS keying material to inner MSCHAPv2 method. + SECURITY_STATUS status; + static const DWORD key_id = 0x02; // EAP-TTLSv0 Challenge Data + static const SecPkgContext_EapPrfInfo prf_info = { 0, sizeof(key_id), (PBYTE)&key_id }; + if (FAILED(status = SetContextAttributes(m_sc_ctx, SECPKG_ATTR_EAP_PRF_INFO, (void*)&prf_info, sizeof(prf_info)))) + throw sec_runtime_error(status, __FUNCTION__ " Error setting TTLS PRF in Schannel."); + + SecPkgContext_EapKeyBlock key_block; + if (FAILED(status = QueryContextAttributes(m_sc_ctx, SECPKG_ATTR_EAP_KEY_BLOCK, &key_block))) + throw sec_runtime_error(status, __FUNCTION__ " Error generating PRF in Schannel."); + + inner_mschapv2->set_challenge_data(key_block.rgbKeys, key_block.rgbKeys[sizeof(challenge_mschapv2)]); + + SecureZeroMemory(&key_block, sizeof(key_block)); + } +} + + +void eap::method_ttls::get_keying_material(_Out_ sanitizing_blob_xf<32> &recv_key, _Out_ sanitizing_blob_xf<32> &send_key) +{ + // Derive MSK keys. + DWORD key_id = 0x01; // EAP-TTLSv0 Keying Material + const SecPkgContext_EapPrfInfo prf_info = { 0, sizeof(key_id), (PBYTE)&key_id }; + SECURITY_STATUS status = SetContextAttributes(m_sc_ctx, SECPKG_ATTR_EAP_PRF_INFO, (void*)&prf_info, sizeof(prf_info)); + if (FAILED(status)) + throw sec_runtime_error(status, __FUNCTION__ " Error setting PRF in Schannel."); + + SecPkgContext_EapKeyBlock key_block; + status = QueryContextAttributes(m_sc_ctx, SECPKG_ATTR_EAP_KEY_BLOCK, &key_block); + if (FAILED(status)) + throw sec_runtime_error(status, __FUNCTION__ " Error generating MSK in Schannel."); + memcpy(recv_key.data, key_block.rgbKeys , 32); + memcpy(send_key.data, key_block.rgbKeys + 32, 32); + SecureZeroMemory(&key_block, sizeof(key_block)); +} diff --git a/lib/TTLS/src/Module.cpp b/lib/TTLS/src/Module.cpp index 1876648..51759e6 100644 --- a/lib/TTLS/src/Module.cpp +++ b/lib/TTLS/src/Module.cpp @@ -174,8 +174,10 @@ eap::config_method* eap::peer_ttls::make_config_method() eap::method* eap::peer_ttls::make_method(_In_ config_method_tls &cfg, _In_ credentials_tls &cred) { unique_ptr meth_inner; - auto cfg_inner = dynamic_cast(cfg).m_inner.get(); - auto cred_inner = dynamic_cast(cred).m_inner.get(); + auto &cfg_ttls = dynamic_cast(cfg); + auto cfg_inner = cfg_ttls.m_inner.get(); + auto &cred_tunnel = dynamic_cast(cred); + auto cred_inner = cred_tunnel.m_inner.get(); assert(cfg_inner); switch (cfg_inner->get_method_id()) { @@ -218,5 +220,5 @@ eap::method* eap::peer_ttls::make_method(_In_ config_method_tls &cfg, _In_ crede return new method_eap (*this, eap_type_t::ttls, cred, new method_defrag(*this, 0 /* Schannel supports retrieving keying material for EAP-TTLSv0 only. */, - new method_tls (*this, cfg, cred, meth_inner.release()))); + new method_ttls (*this, cfg_ttls, cred_tunnel, meth_inner.release()))); }