diff --git a/lib/TLS/include/Method.h b/lib/TLS/include/Method.h index c3d9ffe..3558552 100644 --- a/lib/TLS/include/Method.h +++ b/lib/TLS/include/Method.h @@ -297,8 +297,9 @@ namespace eap /// inline void hash_handshake(_In_count_(size) const void *data, _In_ size_t size) { - CryptHashData(m_hash_handshake_msgs_md5 , (const BYTE*)data, (DWORD)size, 0); - CryptHashData(m_hash_handshake_msgs_sha1, (const BYTE*)data, (DWORD)size, 0); + CryptHashData(m_hash_handshake_msgs_md5 , (const BYTE*)data, (DWORD)size, 0); + CryptHashData(m_hash_handshake_msgs_sha1 , (const BYTE*)data, (DWORD)size, 0); + CryptHashData(m_hash_handshake_msgs_sha256, (const BYTE*)data, (DWORD)size, 0); } /// @@ -450,6 +451,8 @@ namespace eap /// \sa [The Transport Layer Security (TLS) Protocol Version 1.1 (Chapter 5. HMAC and the Pseudorandom Function)](https://tools.ietf.org/html/rfc4346#section-5) /// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter 5. HMAC and the Pseudorandom Function)](https://tools.ietf.org/html/rfc5246#section-5) /// + /// \param[in] cp Handle of the cryptographics provider + /// \param[in] alg Hashing Algorithm to use (CALG_TLS1PRF = combination of MD5 and SHA-1, CALG_SHA_256...) /// \param[in] secret Hashing secret key /// \param[in] seed Random seed /// \param[in] size_seed \p seed size @@ -457,11 +460,60 @@ namespace eap /// /// \returns Generated pseudo-random data (\p size bytes) /// - sanitizing_blob prf( + static sanitizing_blob prf( + _In_ HCRYPTPROV cp, + _In_ ALG_ID alg, _In_ const tls_master_secret &secret, _In_bytecount_(size_seed) const void *seed, _In_ size_t size_seed, - _In_ size_t size) const; + _In_ size_t size); + + /// + /// Calculates pseudo-random P_hash data defined in RFC 5246 + /// + /// \sa [The Transport Layer Security (TLS) Protocol Version 1.1 (Chapter 5. HMAC and the Pseudorandom Function)](https://tools.ietf.org/html/rfc4346#section-5) + /// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter 5. HMAC and the Pseudorandom Function)](https://tools.ietf.org/html/rfc5246#section-5) + /// + /// \param[in] secret Hashing secret key + /// \param[in] seed Random seed + /// \param[in] size_seed \p seed size + /// \param[in] size Number of bytes of pseudo-random data required + /// + /// \returns Generated pseudo-random data (\p size bytes) + /// + inline sanitizing_blob prf( + _In_ const tls_master_secret &secret, + _In_bytecount_(size_seed) const void *seed, + _In_ size_t size_seed, + _In_ size_t size) const + { + return prf(m_cp, m_state.m_alg_prf, secret, seed, size_seed, size); + } + + /// + /// Calculates pseudo-random P_hash data defined in RFC 5246 + /// + /// \sa [The Transport Layer Security (TLS) Protocol Version 1.1 (Chapter 5. HMAC and the Pseudorandom Function)](https://tools.ietf.org/html/rfc4346#section-5) + /// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter 5. HMAC and the Pseudorandom Function)](https://tools.ietf.org/html/rfc5246#section-5) + /// + /// \param[in] cp Handle of the cryptographics provider + /// \param[in] alg Hashing Algorithm to use (CALG_TLS1PRF = combination of MD5 and SHA-1, CALG_SHA_256...) + /// \param[in] secret Hashing secret key + /// \param[in] seed Random seed + /// \param[in] size Number of bytes of pseudo-random data required + /// + /// \returns Generated pseudo-random data (\p size bytes) + /// + template + inline static sanitizing_blob prf( + _In_ HCRYPTPROV cp, + _In_ ALG_ID alg, + _In_ const tls_master_secret &secret, + _In_ const std::vector<_Ty, _Ax> &seed, + _In_ size_t size) + { + return prf(cp, alg, secret, seed.data(), seed.size() * sizeof(_Ty), size); + } /// /// Calculates pseudo-random P_hash data defined in RFC 5246 @@ -479,9 +531,9 @@ namespace eap inline sanitizing_blob prf( _In_ const tls_master_secret &secret, _In_ const std::vector<_Ty, _Ax> &seed, - _In_ size_t size) const + _In_ size_t size) const { - return prf(secret, seed.data(), seed.size() * sizeof(_Ty), size); + return prf(m_cp, m_state.m_alg_prf, secret, seed.data(), seed.size() * sizeof(_Ty), size); } /// @} @@ -530,6 +582,7 @@ namespace eap winstd::crypt_hash m_hash_handshake_msgs_md5; ///< Running MD5 hash of handshake messages sent winstd::crypt_hash m_hash_handshake_msgs_sha1; ///< Running SHA-1 hash of handshake messages sent + winstd::crypt_hash m_hash_handshake_msgs_sha256; ///< Running SHA-256 hash of handshake messages sent bool m_certificate_req; ///< Did server request client certificate? bool m_server_hello_done; ///< Is server hello done? diff --git a/lib/TLS/src/Method.cpp b/lib/TLS/src/Method.cpp index 9b52192..f67e767 100644 --- a/lib/TLS/src/Method.cpp +++ b/lib/TLS/src/Method.cpp @@ -107,7 +107,7 @@ eap::method_tls::method_tls(_In_ module &module, _In_ config_provider_list &cfg, #endif method(module, cfg, cred) { - m_tls_version = tls_version_1_1; + m_tls_version = tls_version_1_2; } @@ -126,6 +126,7 @@ eap::method_tls::method_tls(_In_ const method_tls &other) : m_server_cert_chain(other.m_server_cert_chain), m_hash_handshake_msgs_md5(other.m_hash_handshake_msgs_md5), m_hash_handshake_msgs_sha1(other.m_hash_handshake_msgs_sha1), + m_hash_handshake_msgs_sha256(other.m_hash_handshake_msgs_sha256), m_certificate_req(other.m_certificate_req), m_server_hello_done(other.m_server_hello_done), m_cipher_spec(other.m_cipher_spec), @@ -152,6 +153,7 @@ eap::method_tls::method_tls(_Inout_ method_tls &&other) : m_server_cert_chain(std::move(other.m_server_cert_chain)), m_hash_handshake_msgs_md5(std::move(other.m_hash_handshake_msgs_md5)), m_hash_handshake_msgs_sha1(std::move(other.m_hash_handshake_msgs_sha1)), + m_hash_handshake_msgs_sha256(std::move(other.m_hash_handshake_msgs_sha256)), m_certificate_req(std::move(other.m_certificate_req)), m_server_hello_done(std::move(other.m_server_hello_done)), m_cipher_spec(std::move(other.m_cipher_spec)), @@ -179,26 +181,27 @@ eap::method_tls& eap::method_tls::operator=(_In_ const method_tls &other) { if (this != std::addressof(other)) { assert(std::addressof(m_cred) == std::addressof(other.m_cred)); // Copy method with same credentials only! - (method&)*this = other; - m_packet_req = other.m_packet_req; - m_packet_res = other.m_packet_res; - m_state = other.m_state; - m_padding_hmac_client = other.m_padding_hmac_client; - m_padding_hmac_server = other.m_padding_hmac_server; - m_key_client = other.m_key_client; - m_key_server = other.m_key_server; - m_key_mppe_client = other.m_key_mppe_client; - m_key_mppe_server = other.m_key_mppe_server; - m_session_id = other.m_session_id; - m_server_cert_chain = other.m_server_cert_chain; - m_hash_handshake_msgs_md5 = other.m_hash_handshake_msgs_md5; - m_hash_handshake_msgs_sha1 = other.m_hash_handshake_msgs_sha1; - m_certificate_req = other.m_certificate_req; - m_server_hello_done = other.m_server_hello_done; - m_cipher_spec = other.m_cipher_spec; - m_server_finished = other.m_server_finished; - m_seq_num_client = other.m_seq_num_client; - m_seq_num_server = other.m_seq_num_server; + (method&)*this = other; + m_packet_req = other.m_packet_req; + m_packet_res = other.m_packet_res; + m_state = other.m_state; + m_padding_hmac_client = other.m_padding_hmac_client; + m_padding_hmac_server = other.m_padding_hmac_server; + m_key_client = other.m_key_client; + m_key_server = other.m_key_server; + m_key_mppe_client = other.m_key_mppe_client; + m_key_mppe_server = other.m_key_mppe_server; + m_session_id = other.m_session_id; + m_server_cert_chain = other.m_server_cert_chain; + m_hash_handshake_msgs_md5 = other.m_hash_handshake_msgs_md5; + m_hash_handshake_msgs_sha1 = other.m_hash_handshake_msgs_sha1; + m_hash_handshake_msgs_sha256 = other.m_hash_handshake_msgs_sha256; + m_certificate_req = other.m_certificate_req; + m_server_hello_done = other.m_server_hello_done; + m_cipher_spec = other.m_cipher_spec; + m_server_finished = other.m_server_finished; + m_seq_num_client = other.m_seq_num_client; + m_seq_num_server = other.m_seq_num_server; } return *this; @@ -209,26 +212,27 @@ eap::method_tls& eap::method_tls::operator=(_Inout_ method_tls &&other) { if (this != std::addressof(other)) { assert(std::addressof(m_cred) == std::addressof(other.m_cred)); // Move method with same credentials only! - (method&)*this = std::move(other); - m_packet_req = std::move(other.m_packet_req); - m_packet_res = std::move(other.m_packet_res); - m_state = std::move(other.m_state); - m_padding_hmac_client = std::move(other.m_padding_hmac_client); - m_padding_hmac_server = std::move(other.m_padding_hmac_server); - m_key_client = std::move(other.m_key_client); - m_key_server = std::move(other.m_key_server); - m_key_mppe_client = std::move(other.m_key_mppe_client); - m_key_mppe_server = std::move(other.m_key_mppe_server); - m_session_id = std::move(other.m_session_id); - m_server_cert_chain = std::move(other.m_server_cert_chain); - m_hash_handshake_msgs_md5 = std::move(other.m_hash_handshake_msgs_md5); - m_hash_handshake_msgs_sha1 = std::move(other.m_hash_handshake_msgs_sha1); - m_certificate_req = std::move(other.m_certificate_req); - m_server_hello_done = std::move(other.m_server_hello_done); - m_cipher_spec = std::move(other.m_cipher_spec); - m_server_finished = std::move(other.m_server_finished); - m_seq_num_client = std::move(other.m_seq_num_client); - m_seq_num_server = std::move(other.m_seq_num_server); + (method&)*this = std::move(other); + m_packet_req = std::move(other.m_packet_req); + m_packet_res = std::move(other.m_packet_res); + m_state = std::move(other.m_state); + m_padding_hmac_client = std::move(other.m_padding_hmac_client); + m_padding_hmac_server = std::move(other.m_padding_hmac_server); + m_key_client = std::move(other.m_key_client); + m_key_server = std::move(other.m_key_server); + m_key_mppe_client = std::move(other.m_key_mppe_client); + m_key_mppe_server = std::move(other.m_key_mppe_server); + m_session_id = std::move(other.m_session_id); + m_server_cert_chain = std::move(other.m_server_cert_chain); + m_hash_handshake_msgs_md5 = std::move(other.m_hash_handshake_msgs_md5); + m_hash_handshake_msgs_sha1 = std::move(other.m_hash_handshake_msgs_sha1); + m_hash_handshake_msgs_sha256 = std::move(other.m_hash_handshake_msgs_sha256); + m_certificate_req = std::move(other.m_certificate_req); + m_server_hello_done = std::move(other.m_server_hello_done); + m_cipher_spec = std::move(other.m_cipher_spec); + m_server_finished = std::move(other.m_server_finished); + m_seq_num_client = std::move(other.m_seq_num_client); + m_seq_num_server = std::move(other.m_seq_num_server); } return *this; @@ -244,7 +248,7 @@ void eap::method_tls::begin_session( method::begin_session(dwFlags, pAttributeArray, hTokenImpersonateUser, dwMaxSendPacketSize); // Create cryptographics provider. - if (!m_cp.create(NULL, MS_ENHANCED_PROV, PROV_RSA_FULL)) + if (!m_cp.create(NULL, NULL, PROV_RSA_AES)) throw win_runtime_error(__FUNCTION__ " Error creating cryptographics provider."); if (m_cfg.m_providers.empty() || m_cfg.m_providers.front().m_methods.empty()) @@ -371,6 +375,9 @@ void eap::method_tls::process_request_packet( if (!m_hash_handshake_msgs_sha1.create(m_cp, CALG_SHA1)) throw win_runtime_error(__FUNCTION__ " Error creating SHA-1 hashing object."); + if (!m_hash_handshake_msgs_sha256.create(m_cp, CALG_SHA_256)) + throw win_runtime_error(__FUNCTION__ " Error creating SHA-256 hashing object."); + m_certificate_req = false; m_server_hello_done = false; m_cipher_spec = false; @@ -606,7 +613,7 @@ eap::sanitizing_blob eap::method_tls::make_client_hello() const 1 + // Session ID size m_session_id.size() + // Session ID 2 + // Length of cypher suite list - 2 + // Cyper suite list + 4 + // Cyper suite list 1 + // Length of compression suite 1)); // Compression suite @@ -627,8 +634,10 @@ eap::sanitizing_blob eap::method_tls::make_client_hello() const msg.insert(msg.end(), m_session_id.begin(), m_session_id.end()); // Cypher suite list - msg.push_back(0x00); // Length of cypher suite is two (in network-byte-order). - msg.push_back(0x02); // --^ + msg.push_back(0x00); // Length of cypher suite is four bytes (in network-byte-order). + msg.push_back(0x04); // --^ + msg.push_back(0x00); // TLS_RSA_WITH_AES_128_CBC_SHA (0x00 0x2f) + msg.push_back(0x2f); // --^ msg.push_back(0x00); // TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x00 0x0a) msg.push_back(0x0a); // --^ @@ -746,14 +755,21 @@ eap::sanitizing_blob eap::method_tls::make_finished() const crypt_hash hash; static const unsigned char s_label[] = "client finished"; sanitizing_blob seed(s_label, s_label + _countof(s_label) - 1), hash_data; - hash = m_hash_handshake_msgs_md5; // duplicate - if (!CryptGetHashParam(hash, HP_HASHVAL, hash_data, 0)) - throw win_runtime_error(__FUNCTION__ " Error finishing MD5 hash calculation."); - seed.insert(seed.end(), hash_data.begin(), hash_data.end()); - hash = m_hash_handshake_msgs_sha1; // duplicate - if (!CryptGetHashParam(hash, HP_HASHVAL, hash_data, 0)) - throw win_runtime_error(__FUNCTION__ " Error finishing SHA-1 hash calculation."); - seed.insert(seed.end(), hash_data.begin(), hash_data.end()); + if (m_tls_version < tls_version_1_2) { + hash = m_hash_handshake_msgs_md5; // duplicate + if (!CryptGetHashParam(hash, HP_HASHVAL, hash_data, 0)) + throw win_runtime_error(__FUNCTION__ " Error finishing MD5 hash calculation."); + seed.insert(seed.end(), hash_data.begin(), hash_data.end()); + hash = m_hash_handshake_msgs_sha1; // duplicate + if (!CryptGetHashParam(hash, HP_HASHVAL, hash_data, 0)) + throw win_runtime_error(__FUNCTION__ " Error finishing SHA-1 hash calculation."); + seed.insert(seed.end(), hash_data.begin(), hash_data.end()); + } else { + hash = m_hash_handshake_msgs_sha256; // duplicate + if (!CryptGetHashParam(hash, HP_HASHVAL, hash_data, 0)) + throw win_runtime_error(__FUNCTION__ " Error finishing SHA-256 hash calculation."); + seed.insert(seed.end(), hash_data.begin(), hash_data.end()); + } sanitizing_blob verify(prf(m_state.m_master_secret, seed, 12)); msg.insert(msg.end(), verify.begin(), verify.end()); @@ -763,31 +779,29 @@ eap::sanitizing_blob eap::method_tls::make_finished() const eap::sanitizing_blob eap::method_tls::make_message(_In_ tls_message_type_t type, _Inout_ sanitizing_blob &data, _In_ bool encrypt) { - if (encrypt) { + if (encrypt) encrypt_message(type, data); - return make_message(type, data, false); - } else { - size_t size_data = data.size(); - assert(size_data <= 0xffff); - message_header hdr = { - type, // SSL record type - { - m_tls_version.major, // SSL major version - m_tls_version.minor, // SSL minor version - }, - { - // Data length (unencrypted, network byte order) - (unsigned char)((size_data >> 8) & 0xff), - (unsigned char)((size_data ) & 0xff), - } - }; - sanitizing_blob msg; - msg.reserve(sizeof(message_header) + size_data); - msg.assign((const unsigned char*)&hdr, (const unsigned char*)(&hdr + 1)); - msg.insert(msg.end(), data.begin(), data.end()); - return msg; - } + size_t size_data = data.size(); + assert(size_data <= 0xffff); + message_header hdr = { + type, // SSL record type + { + m_tls_version.major, // SSL major version + m_tls_version.minor, // SSL minor version + }, + { + // Data length (unencrypted, network byte order) + (unsigned char)((size_data >> 8) & 0xff), + (unsigned char)((size_data ) & 0xff), + } + }; + + sanitizing_blob msg; + msg.reserve(sizeof(message_header) + size_data); + msg.assign((const unsigned char*)&hdr, (const unsigned char*)(&hdr + 1)); + msg.insert(msg.end(), data.begin(), data.end()); + return msg; } @@ -983,7 +997,7 @@ void eap::method_tls::process_handshake(_In_bytecount_(msg_size) const void *_ms else if (*(tls_version*)rec < tls_version_1_0 || m_tls_version < *(tls_version*)rec) throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Unsupported SSL/TLS version."); m_tls_version = *(tls_version*)rec; - m_state.m_alg_prf = CALG_TLS1PRF; + m_state.m_alg_prf = m_tls_version < tls_version_1_2 ? CALG_TLS1PRF : CALG_SHA_256; rec += 2; // Server random @@ -1002,7 +1016,16 @@ void eap::method_tls::process_handshake(_In_bytecount_(msg_size) const void *_ms // Cipher if (rec + 2 > rec_end) throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, __FUNCTION__ " Cipher or incomplete."); - if (rec[0] == 0x00 || rec[1] == 0x0a) { + if (rec[0] == 0x00 || rec[1] == 0x2f) { + // TLS_RSA_WITH_AES_128_CBC_SHA + m_state.m_alg_encrypt = CALG_AES_128; + m_state.m_size_enc_key = 128/8; // AES-128 + m_state.m_size_enc_iv = 128/8; // AES-128 + m_state.m_size_enc_block = 128/8; // AES-128 + m_state.m_alg_mac = CALG_SHA1; + m_state.m_size_mac_key = 160/8; // SHA-1 + m_state.m_size_mac_hash = 160/8; // SHA-1 + } else if (rec[0] == 0x00 || rec[1] == 0x0a) { // TLS_RSA_WITH_3DES_EDE_CBC_SHA m_state.m_alg_encrypt = CALG_3DES; m_state.m_size_enc_key = 192/8; // 3DES 192bits @@ -1079,14 +1102,21 @@ void eap::method_tls::process_handshake(_In_bytecount_(msg_size) const void *_ms crypt_hash hash; static const unsigned char s_label[] = "server finished"; sanitizing_blob seed(s_label, s_label + _countof(s_label) - 1), hash_data; - hash = m_hash_handshake_msgs_md5; // duplicate - if (!CryptGetHashParam(hash, HP_HASHVAL, hash_data, 0)) - throw win_runtime_error(__FUNCTION__ " Error finishing MD5 hash calculation."); - seed.insert(seed.end(), hash_data.begin(), hash_data.end()); - hash = m_hash_handshake_msgs_sha1; // duplicate - if (!CryptGetHashParam(hash, HP_HASHVAL, hash_data, 0)) - throw win_runtime_error(__FUNCTION__ " Error finishing SHA-1 hash calculation."); - seed.insert(seed.end(), hash_data.begin(), hash_data.end()); + if (m_tls_version < tls_version_1_2) { + hash = m_hash_handshake_msgs_md5; // duplicate + if (!CryptGetHashParam(hash, HP_HASHVAL, hash_data, 0)) + throw win_runtime_error(__FUNCTION__ " Error finishing MD5 hash calculation."); + seed.insert(seed.end(), hash_data.begin(), hash_data.end()); + hash = m_hash_handshake_msgs_sha1; // duplicate + if (!CryptGetHashParam(hash, HP_HASHVAL, hash_data, 0)) + throw win_runtime_error(__FUNCTION__ " Error finishing SHA-1 hash calculation."); + seed.insert(seed.end(), hash_data.begin(), hash_data.end()); + } else { + hash = m_hash_handshake_msgs_sha256; // duplicate + if (!CryptGetHashParam(hash, HP_HASHVAL, hash_data, 0)) + throw win_runtime_error(__FUNCTION__ " Error finishing SHA-256 hash calculation."); + seed.insert(seed.end(), hash_data.begin(), hash_data.end()); + } if (memcmp(prf(m_state.m_master_secret, seed, 12).data(), rec, 12)) throw win_runtime_error(ERROR_ENCRYPTION_FAILED, __FUNCTION__ " Integrity check failed."); @@ -1344,15 +1374,17 @@ void eap::method_tls::decrypt_message(_In_ tls_message_type_t type, _Inout_ sani eap::sanitizing_blob eap::method_tls::prf( + _In_ HCRYPTPROV cp, + _In_ ALG_ID alg, _In_ const tls_master_secret &secret, _In_bytecount_(size_seed) const void *seed, _In_ size_t size_seed, - _In_ size_t size) const + _In_ size_t size) { sanitizing_blob data; data.reserve(size); - if (m_state.m_alg_prf == CALG_TLS1PRF) { + if (alg == CALG_TLS1PRF) { // Split secret in two halves. size_t size_S1 = (sizeof(tls_master_secret) + 1) / 2, @@ -1365,8 +1397,8 @@ eap::sanitizing_blob eap::method_tls::prf( sanitizing_blob hmac_padding1(sizeof(hash_hmac::padding_t)), hmac_padding2(sizeof(hash_hmac::padding_t)); - hash_hmac::inner_padding(m_cp, CALG_MD5 , S1, size_S1, hmac_padding1.data()); - hash_hmac::inner_padding(m_cp, CALG_SHA1, S2, size_S2, hmac_padding2.data()); + hash_hmac::inner_padding(cp, CALG_MD5 , S1, size_S1, hmac_padding1.data()); + hash_hmac::inner_padding(cp, CALG_SHA1, S2, size_S2, hmac_padding2.data()); // Prepare A for p_hash. sanitizing_blob @@ -1380,13 +1412,13 @@ eap::sanitizing_blob eap::method_tls::prf( for (size_t i = 0, off1 = 0, off2 = 0; i < size; ) { if (off1 >= hmac1.size()) { // Rehash A. - hash_hmac hash1(m_cp, CALG_MD5 , hmac_padding1.data()); + hash_hmac hash1(cp, CALG_MD5 , hmac_padding1.data()); if (!CryptHashData(hash1, A1.data(), (DWORD)A1.size(), 0)) throw win_runtime_error(__FUNCTION__ " Error hashing A1."); hash1.calculate(A1); // Hash A and seed. - hash_hmac hash2(m_cp, CALG_MD5 , hmac_padding1.data()); + hash_hmac hash2(cp, CALG_MD5 , hmac_padding1.data()); if (!CryptHashData(hash2, A1.data(), (DWORD)A1.size(), 0) || !CryptHashData(hash2, (const BYTE*)seed , (DWORD)size_seed, 0)) throw win_runtime_error(__FUNCTION__ " Error hashing seed,label or data."); @@ -1396,13 +1428,13 @@ eap::sanitizing_blob eap::method_tls::prf( if (off2 >= hmac2.size()) { // Rehash A. - hash_hmac hash1(m_cp, CALG_SHA1 , hmac_padding2.data()); + hash_hmac hash1(cp, CALG_SHA1 , hmac_padding2.data()); if (!CryptHashData(hash1, A2.data(), (DWORD)A2.size(), 0)) throw win_runtime_error(__FUNCTION__ " Error hashing A2."); hash1.calculate(A2); // Hash A and seed. - hash_hmac hash2(m_cp, CALG_SHA1 , hmac_padding2.data()); + hash_hmac hash2(cp, CALG_SHA1 , hmac_padding2.data()); if (!CryptHashData(hash2, A2.data(), (DWORD)A2.size(), 0) || !CryptHashData(hash2, (const BYTE*)seed , (DWORD)size_seed, 0)) throw win_runtime_error(__FUNCTION__ " Error hashing seed,label or data."); @@ -1418,7 +1450,7 @@ eap::sanitizing_blob eap::method_tls::prf( } else { // Precalculate HMAC padding for speed. sanitizing_blob hmac_padding(sizeof(hash_hmac::padding_t)); - hash_hmac::inner_padding(m_cp, m_state.m_alg_prf, &secret, sizeof(tls_master_secret), hmac_padding.data()); + hash_hmac::inner_padding(cp, alg, &secret, sizeof(tls_master_secret), hmac_padding.data()); // Prepare A for p_hash. sanitizing_blob A((unsigned char*)seed, (unsigned char*)seed + size_seed); @@ -1426,13 +1458,13 @@ eap::sanitizing_blob eap::method_tls::prf( sanitizing_blob hmac; for (size_t i = 0; i < size; ) { // Rehash A. - hash_hmac hash1(m_cp, m_state.m_alg_prf, hmac_padding.data()); + hash_hmac hash1(cp, alg, hmac_padding.data()); if (!CryptHashData(hash1, A.data(), (DWORD)A.size(), 0)) throw win_runtime_error(__FUNCTION__ " Error hashing A."); hash1.calculate(A); // Hash A and seed. - hash_hmac hash2(m_cp, m_state.m_alg_prf, hmac_padding.data()); + hash_hmac hash2(cp, alg, hmac_padding.data()); if (!CryptHashData(hash2, A.data(), (DWORD)A.size() , 0) || !CryptHashData(hash2, (const BYTE*)seed , (DWORD)size_seed, 0)) throw win_runtime_error(__FUNCTION__ " Error hashing seed,label or data."); @@ -1454,6 +1486,34 @@ HCRYPTKEY eap::method_tls::create_key( _In_bytecount_(size_secret) const void *secret, _In_ size_t size_secret) { +#if 0 + UNREFERENCED_PARAMETER(key); + assert(size_secret <= 0xffffffff); + + // Prepare exported key BLOB. + struct key_blob_prefix { + PUBLICKEYSTRUC header; + DWORD size; + } const prefix = { + { + PLAINTEXTKEYBLOB, + CUR_BLOB_VERSION, + 0, + alg, + }, + (DWORD)size_secret, + }; + sanitizing_blob key_blob; + key_blob.reserve(sizeof(key_blob_prefix) + size_secret); + key_blob.assign((const unsigned char*)&prefix, (const unsigned char*)(&prefix + 1)); + key_blob.insert(key_blob.end(), (const unsigned char*)secret, (const unsigned char*)secret + size_secret); + + // Import the key. + winstd::crypt_key key_out; + if (!key_out.import(m_cp, key_blob.data(), (DWORD)key_blob.size(), NULL, 0)) + throw winstd::win_runtime_error(__FUNCTION__ " Error importing key."); + return key_out.detach(); +#else if (size_secret > m_state.m_size_enc_key) throw invalid_argument(__FUNCTION__ " Secret too big to fit the key."); @@ -1518,4 +1578,5 @@ HCRYPTKEY eap::method_tls::create_key( if (!key_out.import(m_cp, key_blob.data(), (DWORD)key_blob.size(), key, 0)) throw winstd::win_runtime_error(__FUNCTION__ " Error importing key."); return key_out.detach(); +#endif } diff --git a/lib/TTLS/src/Method.cpp b/lib/TTLS/src/Method.cpp index c28b165..59295e6 100644 --- a/lib/TTLS/src/Method.cpp +++ b/lib/TTLS/src/Method.cpp @@ -155,11 +155,26 @@ void eap::method_ttls::get_result( void eap::method_ttls::derive_msk() { + // + // TLS versions 1.0 [RFC2246] and 1.1 [RFC4346] define the same PRF + // function, and any EAP-TTLSv0 implementation based on these versions + // of TLS must use the PRF defined therein. It is expected that future + // versions of or extensions to the TLS protocol will permit alternative + // PRF functions to be negotiated. If an alternative PRF function is + // specified for the underlying TLS version or has been negotiated + // during the TLS handshake negotiation, then that alternative PRF + // function must be used in EAP-TTLSv0 computations instead of the TLS + // 1.0/1.1 PRF. + // + // [Extensible Authentication Protocol Tunneled Transport Layer Security Authenticated Protocol Version 0 (EAP-TTLSv0) (Chapter 7.8. Use of TLS PRF)](https://tools.ietf.org/html/rfc5281#section-7.8) + // + // If we use PRF_SHA256() the key exchange fails. Therefore we use PRF of TLS 1.0/1.1. + // static const unsigned char s_label[] = "ttls keying material"; sanitizing_blob seed(s_label, s_label + _countof(s_label) - 1); seed.insert(seed.end(), (const unsigned char*)&m_state.m_random_client, (const unsigned char*)(&m_state.m_random_client + 1)); seed.insert(seed.end(), (const unsigned char*)&m_state.m_random_server, (const unsigned char*)(&m_state.m_random_server + 1)); - sanitizing_blob key_block(prf(m_state.m_master_secret, seed, 2*sizeof(tls_random))); + sanitizing_blob key_block(prf(m_cp, CALG_TLS1PRF, m_state.m_master_secret, seed, 2*sizeof(tls_random))); const unsigned char *_key_block = key_block.data(); // MSK: MPPE-Recv-Key diff --git a/lib/TTLS/src/Module.cpp b/lib/TTLS/src/Module.cpp index 27397b2..9912334 100644 --- a/lib/TTLS/src/Module.cpp +++ b/lib/TTLS/src/Module.cpp @@ -122,7 +122,7 @@ void eap::peer_ttls::get_identity( if (*pfInvokeUI) { if ((dwFlags & EAP_FLAG_MACHINE_AUTH) == 0) { // Per-user authentication - log_event(&EAPMETHOD_TRACE_EVT_CRED_INVOKE_UI2); + log_event(&EAPMETHOD_TRACE_EVT_CRED_INVOKE_UI2, event_data::blank); return; } else { // Per-machine authentication