diff --git a/lib/TLS/include/Method.h b/lib/TLS/include/Method.h index 172901b..fc041dc 100644 --- a/lib/TLS/include/Method.h +++ b/lib/TLS/include/Method.h @@ -230,6 +230,9 @@ namespace eap /// @} protected: + /// \name Client handshake message generation + /// @{ + /// /// Makes a TLS client hello message /// @@ -277,18 +280,10 @@ namespace eap /// eap::sanitizing_blob make_finished() const; - /// - /// Makes a TLS message - /// - /// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter A.1. Record Layer)](https://tools.ietf.org/html/rfc5246#appendix-A.1) - /// - /// \param[in] type Message type - /// \param[in] data Message data contents - /// \param[in] encrypt Should \p data get encrypted? - /// - /// \returns TLS message message - /// - eap::sanitizing_blob make_message(_In_ tls_message_type_t type, _Inout_ sanitizing_blob &data, _In_ bool encrypt); + /// @} + + /// \name Client/Server handshake hashing + /// @{ /// /// Hashes handshake message for "finished" message validation. @@ -318,6 +313,26 @@ namespace eap hash_handshake(data.data(), data.size() * sizeof(_Ty)); } + /// @} + + /// + /// Makes a TLS message + /// + /// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter A.1. Record Layer)](https://tools.ietf.org/html/rfc5246#appendix-A.1) + /// + /// \param[in] type Message type + /// \param[in] data Message data contents + /// \param[in] encrypt Should \p data get encrypted? + /// + /// \returns TLS message message + /// + eap::sanitizing_blob make_message(_In_ tls_message_type_t type, _Inout_ sanitizing_blob &data, _In_ bool encrypt); + + /// @} + + /// \name Key derivation + /// @{ + /// /// Generates keys required by current connection state /// @@ -332,6 +347,11 @@ namespace eap /// virtual void derive_msk(); + /// @} + + /// \name Server message processing + /// @{ + /// /// Processes messages in a TLS packet /// @@ -380,22 +400,27 @@ namespace eap /// virtual void process_application_data(_In_bytecount_(msg_size) const void *msg, _In_ size_t msg_size); - /// - /// Processes a vendor-specific TLS message - /// - /// \note Please see `m_cipher_spec` member if the message data came encrypted. - /// - /// \param[in] type TLS message type - /// \param[in] msg TLS message data - /// \param[in] msg_size TLS message data size - /// - virtual void process_vendor_data(_In_ unsigned char type, _In_bytecount_(msg_size) const void *msg, _In_ size_t msg_size); + ///// + ///// Processes a vendor-specific TLS message + ///// + ///// \note Please see `m_cipher_spec` member if the message data came encrypted. + ///// + ///// \param[in] type TLS message type + ///// \param[in] msg TLS message data + ///// \param[in] msg_size TLS message data size + ///// + //virtual void process_vendor_data(_In_ unsigned char type, _In_bytecount_(msg_size) const void *msg, _In_ size_t msg_size); + + /// @} /// /// Verifies server's certificate if trusted by configuration /// void verify_server_trust() const; + /// \name Encryption + /// @{ + /// /// Encrypt TLS message /// @@ -412,6 +437,11 @@ namespace eap /// void decrypt_message(_In_ const message_header *hdr, _Inout_ sanitizing_blob &data); + /// @} + + /// \name Pseudo-random generation + /// @{ + /// /// Calculates pseudo-random P_hash data defined in RFC 5246 /// @@ -450,6 +480,8 @@ namespace eap return prf(secret, seed.data(), seed.size() * sizeof(_Ty), size); } + /// @} + /// /// Creates a key /// @@ -474,9 +506,7 @@ namespace eap enum phase_t { phase_unknown = -1, ///< Unknown state - phase_res_client_hello = 0, ///< Respond with client hello phase_req_server_hello, ///< Request and parse server hello. - phase_req_change_chiper_spec, ///< Request change cipher from server phase_finished, ///< Final state } m_phase; ///< Session phase diff --git a/lib/TLS/src/Method.cpp b/lib/TLS/src/Method.cpp index 1ba80f9..4986246 100644 --- a/lib/TLS/src/Method.cpp +++ b/lib/TLS/src/Method.cpp @@ -337,12 +337,15 @@ void eap::method_tls::process_request_packet( throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, string_printf(__FUNCTION__ " ACK expected, received %u-%u-%x.", m_packet_req.m_code, m_packet_req.m_id, m_packet_req.m_flags)); } + m_packet_res.m_code = EapCodeResponse; + m_packet_res.m_id = m_packet_req.m_id; + m_packet_res.m_flags = 0; + if (pReceivedPacket->Code == EapCodeRequest && (m_packet_req.m_flags & flags_req_start)) { - // This is the TLS start message: initialize method. + // This is the TLS start message: (re)initialize method. m_module.log_event(&EAPMETHOD_TLS_HANDSHAKE_START2, event_data((unsigned int)eap_type_tls), event_data::blank); - m_phase = phase_res_client_hello; - m_packet_res.clear(); + m_phase = phase_req_server_hello; m_state.m_random_client.reset(m_cp); @@ -371,37 +374,21 @@ void eap::method_tls::process_request_packet( m_seq_num_client = 0; m_seq_num_server = 0; - } - switch (m_phase) { - case phase_res_client_hello: { - // Build response packet. - m_packet_res.m_code = EapCodeResponse; - m_packet_res.m_id = m_packet_req.m_id; - m_packet_res.m_flags = 0; - sanitizing_blob hello(make_client_hello()); - hash_handshake(hello); - sanitizing_blob handshake(make_message(tls_message_type_handshake, hello, m_cipher_spec)); - m_packet_res.m_data.assign(handshake.begin(), handshake.end()); - - m_phase = phase_req_server_hello; - - pEapOutput->fAllowNotifications = FALSE; - pEapOutput->action = EapPeerMethodResponseActionSend; - break; - } + // Build client hello packet. + sanitizing_blob hello(make_client_hello()); + hash_handshake(hello); + sanitizing_blob handshake(make_message(tls_message_type_handshake, hello, m_cipher_spec)); + m_packet_res.m_data.assign(handshake.begin(), handshake.end()); + } else { + // Process the packet. + m_packet_res.m_data.clear(); + process_packet(m_packet_req.m_data.data(), m_packet_req.m_data.size()); + switch (m_phase) { case phase_req_server_hello: { - process_packet(m_packet_req.m_data.data(), m_packet_req.m_data.size()); - if (!m_server_hello_done) { // Reply with ACK packet and wait for the next packet. - m_packet_res.m_code = EapCodeResponse; - m_packet_res.m_id = pReceivedPacket->Id; - m_packet_res.m_flags = 0; - m_packet_res.m_data.clear(); - pEapOutput->fAllowNotifications = FALSE; - pEapOutput->action = EapPeerMethodResponseActionSend; break; } @@ -410,12 +397,6 @@ void eap::method_tls::process_request_packet( throw win_runtime_error(ERROR_ENCRYPTION_FAILED, __FUNCTION__ " Can not continue without server's certificate."); verify_server_trust(); - // Build response packet. - m_packet_res.m_code = EapCodeResponse; - m_packet_res.m_id = m_packet_req.m_id; - m_packet_res.m_flags = 0; - m_packet_res.m_data.clear(); - if (!m_server_finished || !m_cipher_spec) { // New session. @@ -456,9 +437,7 @@ void eap::method_tls::process_request_packet( // Setup encryption. derive_keys(); m_cipher_spec = true; - m_phase = phase_req_change_chiper_spec; - } else - m_phase = phase_finished; + } // Create finished message, and append to packet. sanitizing_blob finished(make_finished()); @@ -466,31 +445,23 @@ void eap::method_tls::process_request_packet( sanitizing_blob handshake(make_message(tls_message_type_handshake, finished, m_cipher_spec)); m_packet_res.m_data.insert(m_packet_res.m_data.end(), handshake.begin(), handshake.end()); - pEapOutput->fAllowNotifications = FALSE; - pEapOutput->action = EapPeerMethodResponseActionSend; + m_phase = phase_finished; break; } - case phase_req_change_chiper_spec: - process_packet(m_packet_req.m_data.data(), m_packet_req.m_data.size()); - - if (!m_cipher_spec || !m_server_finished) - throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, __FUNCTION__ " Server did not finish."); - - // TLS finished. Continue to the finished state (no-break case). - m_phase = phase_finished; - case phase_finished: - pEapOutput->fAllowNotifications = FALSE; - pEapOutput->action = EapPeerMethodResponseActionNone; break; default: throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Not supported."); + } } // Request packet was processed. Clear its data since we use the absence of data to detect first of fragmented message packages. m_packet_req.m_data.clear(); + + pEapOutput->fAllowNotifications = FALSE; + pEapOutput->action = EapPeerMethodResponseActionSend; } @@ -558,7 +529,7 @@ void eap::method_tls::get_result( switch (reason) { case EapPeerMethodResultSuccess: { - if (m_phase < phase_req_change_chiper_spec) + if (m_phase < phase_finished) throw invalid_argument(__FUNCTION__ " Premature success."); // Derive MSK. @@ -583,9 +554,7 @@ void eap::method_tls::get_result( // Update configuration with session resumption data and prepare BLOB. m_cfg.m_session_id = m_session_id; m_cfg.m_master_secret = m_state.m_master_secret; - ppResult->fSaveConnectionData = TRUE; - m_phase = phase_finished; break; } @@ -600,12 +569,11 @@ void eap::method_tls::get_result( throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Not supported."); } - if (ppResult->fSaveConnectionData) { - m_module.pack(m_cfg, &ppResult->pConnectionData, &ppResult->dwSizeofConnectionData); - if (m_blob_cfg) - m_module.free_memory(m_blob_cfg); - m_blob_cfg = ppResult->pConnectionData; - } + ppResult->fSaveConnectionData = TRUE; + m_module.pack(m_cfg, &ppResult->pConnectionData, &ppResult->dwSizeofConnectionData); + if (m_blob_cfg) + m_module.free_memory(m_blob_cfg); + m_blob_cfg = ppResult->pConnectionData; } @@ -940,13 +908,13 @@ void eap::method_tls::process_packet(_In_bytecount_(size_pck) const void *_pck, break; } - default: - if (m_cipher_spec) { - sanitizing_blob msg_dec(msg, msg_end); - decrypt_message(hdr, msg_dec); - process_vendor_data(hdr->type, msg_dec.data(), msg_dec.size()); - } else - process_vendor_data(hdr->type, msg, msg_end - msg); + //default: + // if (m_cipher_spec) { + // sanitizing_blob msg_dec(msg, msg_end); + // decrypt_message(hdr, msg_dec); + // process_vendor_data(hdr->type, msg_dec.data(), msg_dec.size()); + // } else + // process_vendor_data(hdr->type, msg, msg_end - msg); } } @@ -1140,12 +1108,12 @@ void eap::method_tls::process_application_data(_In_bytecount_(msg_size) const vo } -void eap::method_tls::process_vendor_data(_In_ unsigned char type, _In_bytecount_(msg_size) const void *msg, _In_ size_t msg_size) -{ - UNREFERENCED_PARAMETER(type); - UNREFERENCED_PARAMETER(msg); - UNREFERENCED_PARAMETER(msg_size); -} +//void eap::method_tls::process_vendor_data(_In_ unsigned char type, _In_bytecount_(msg_size) const void *msg, _In_ size_t msg_size) +//{ +// UNREFERENCED_PARAMETER(type); +// UNREFERENCED_PARAMETER(msg); +// UNREFERENCED_PARAMETER(msg_size); +//} void eap::method_tls::verify_server_trust() const @@ -1265,9 +1233,9 @@ void eap::method_tls::encrypt_message(_In_ const message_header *hdr, _Inout_ sa // Calculate padding. unsigned char size_padding = (unsigned char)((m_state.m_size_enc_block - size_data_enc) % m_state.m_size_enc_block); size_data_enc += size_padding; - data.reserve(size_data_enc); // Append HMAC hash and padding. + data.reserve(size_data_enc); data.insert(data.end(), hmac.begin(), hmac.end()); data.insert(data.end(), size_padding + 1, size_padding); diff --git a/lib/TTLS/src/Method.cpp b/lib/TTLS/src/Method.cpp index 87b6944..9228ec2 100644 --- a/lib/TTLS/src/Method.cpp +++ b/lib/TTLS/src/Method.cpp @@ -74,8 +74,6 @@ eap::method_ttls& eap::method_ttls::operator=(_Inout_ method_ttls &&other) } - - void eap::method_ttls::process_request_packet( _In_bytecount_(dwReceivedPacketSize) const EapPacket *pReceivedPacket, _In_ DWORD dwReceivedPacketSize,