TLS work continues...
This commit is contained in:
parent
a8c306953a
commit
c7a41d891a
@ -1 +1 @@
|
|||||||
Subproject commit b0c4f3edf3b6da1bae21673758ae2a2679e6ea0c
|
Subproject commit 7a459c8c6c785bffb63a73219998a57f8d610de5
|
@ -82,6 +82,7 @@
|
|||||||
<ClInclude Include="..\include\Config.h" />
|
<ClInclude Include="..\include\Config.h" />
|
||||||
<ClInclude Include="..\include\Credentials.h" />
|
<ClInclude Include="..\include\Credentials.h" />
|
||||||
<ClInclude Include="..\include\Method.h" />
|
<ClInclude Include="..\include\Method.h" />
|
||||||
|
<ClInclude Include="..\include\TLS.h" />
|
||||||
<ClInclude Include="..\src\StdAfx.h" />
|
<ClInclude Include="..\src\StdAfx.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -94,6 +95,7 @@
|
|||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\src\Credentials.cpp" />
|
<ClCompile Include="..\src\Credentials.cpp" />
|
||||||
|
<ClCompile Include="..\src\TLS.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
@ -23,6 +23,9 @@
|
|||||||
<ClInclude Include="..\include\Method.h">
|
<ClInclude Include="..\include\Method.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\include\TLS.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\src\StdAfx.cpp">
|
<ClCompile Include="..\src\StdAfx.cpp">
|
||||||
@ -37,5 +40,8 @@
|
|||||||
<ClCompile Include="..\src\Method.cpp">
|
<ClCompile Include="..\src\Method.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\TLS.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -18,13 +18,13 @@
|
|||||||
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
|
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sal.h>
|
|
||||||
|
|
||||||
#include <WinStd/Common.h>
|
#include <WinStd/Common.h>
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <WinCrypt.h> // Must include after <Windows.h>
|
#include <WinCrypt.h> // Must include after <Windows.h>
|
||||||
|
|
||||||
|
#include <sal.h>
|
||||||
|
|
||||||
namespace eap
|
namespace eap
|
||||||
{
|
{
|
||||||
///
|
///
|
||||||
@ -41,6 +41,8 @@ namespace eap
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Credentials.h"
|
#include "Credentials.h"
|
||||||
|
#include "Method.h"
|
||||||
|
#include "TLS.h"
|
||||||
|
|
||||||
#include "../../EAPBase/include/Config.h"
|
#include "../../EAPBase/include/Config.h"
|
||||||
|
|
||||||
@ -166,5 +168,9 @@ namespace eap
|
|||||||
public:
|
public:
|
||||||
std::list<winstd::cert_context> m_trusted_root_ca; ///< Trusted root CAs
|
std::list<winstd::cert_context> m_trusted_root_ca; ///< Trusted root CAs
|
||||||
std::list<std::string> m_server_names; ///< Acceptable authenticating server names
|
std::list<std::string> m_server_names; ///< Acceptable authenticating server names
|
||||||
|
|
||||||
|
// Following members are used for session resumptions. They are not exported/imported to XML.
|
||||||
|
sanitizing_blob m_session_id; ///< TLS session ID
|
||||||
|
tls_master_secret m_master_secret; ///< TLS master secret
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -26,10 +26,12 @@ namespace eap
|
|||||||
class method_tls;
|
class method_tls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../include/Config.h"
|
#include "Config.h"
|
||||||
#include "../include/Credentials.h"
|
#include "Credentials.h"
|
||||||
|
#include "TLS.h"
|
||||||
|
|
||||||
#include "../../EAPBase/include/Method.h"
|
#include "../../EAPBase/include/Method.h"
|
||||||
|
|
||||||
@ -65,79 +67,6 @@ namespace eap
|
|||||||
flags_res_more_frag = 0x40, ///< More fragments
|
flags_res_more_frag = 0x40, ///< More fragments
|
||||||
};
|
};
|
||||||
|
|
||||||
///
|
|
||||||
/// TLS packet type
|
|
||||||
///
|
|
||||||
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter: A.1. Record Layer](https://tools.ietf.org/html/rfc5246#appendix-A.1)
|
|
||||||
///
|
|
||||||
enum message_type_t {
|
|
||||||
message_type_change_cipher_spec = 20,
|
|
||||||
message_type_alert = 21,
|
|
||||||
message_type_handshake = 22,
|
|
||||||
message_type_application_data = 23,
|
|
||||||
};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// TLS handshake type
|
|
||||||
///
|
|
||||||
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter: A.4. Handshake Protocol](https://tools.ietf.org/html/rfc5246#appendix-A.4)
|
|
||||||
///
|
|
||||||
enum handshake_type_t {
|
|
||||||
handshake_type_hello_request = 0,
|
|
||||||
handshake_type_client_hello = 1,
|
|
||||||
handshake_type_server_hello = 2,
|
|
||||||
handshake_type_certificate = 11,
|
|
||||||
handshake_type_server_key_exchange = 12,
|
|
||||||
handshake_type_certificate_request = 13,
|
|
||||||
handshake_type_server_hello_done = 14,
|
|
||||||
handshake_type_certificate_verify = 15,
|
|
||||||
handshake_type_client_key_exchange = 16,
|
|
||||||
handshake_type_finished = 20
|
|
||||||
};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// TLS alert level
|
|
||||||
///
|
|
||||||
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter: 7.2. Alert Protocol)](https://tools.ietf.org/html/rfc5246#section-7.2)
|
|
||||||
///
|
|
||||||
enum alert_level_t {
|
|
||||||
alert_level_warning = 1,
|
|
||||||
alert_level_fatal = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
///
|
|
||||||
/// TLS alert description
|
|
||||||
///
|
|
||||||
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter: 7.2. Alert Protocol)](https://tools.ietf.org/html/rfc5246#section-7.2)
|
|
||||||
///
|
|
||||||
enum alert_desc_t {
|
|
||||||
alert_desc_close_notify = 0,
|
|
||||||
alert_desc_unexpected_message = 10,
|
|
||||||
alert_desc_bad_record_mac = 20,
|
|
||||||
alert_desc_decryption_failed = 21, // reserved
|
|
||||||
alert_desc_record_overflow = 22,
|
|
||||||
alert_desc_decompression_failure = 30,
|
|
||||||
alert_desc_handshake_failure = 40,
|
|
||||||
alert_desc_no_certificate = 41, // reserved
|
|
||||||
alert_desc_bad_certificate = 42,
|
|
||||||
alert_desc_unsupported_certificate = 43,
|
|
||||||
alert_desc_certificate_revoked = 44,
|
|
||||||
alert_desc_certificate_expired = 45,
|
|
||||||
alert_desc_certificate_unknown = 46,
|
|
||||||
alert_desc_illegal_parameter = 47,
|
|
||||||
alert_desc_unknown_ca = 48,
|
|
||||||
alert_desc_access_denied = 49,
|
|
||||||
alert_desc_decode_error = 50,
|
|
||||||
alert_desc_decrypt_error = 51,
|
|
||||||
alert_desc_export_restriction = 60, // reserved
|
|
||||||
alert_desc_protocol_version = 70,
|
|
||||||
alert_desc_insufficient_security = 71,
|
|
||||||
alert_desc_internal_error = 80,
|
|
||||||
alert_desc_user_canceled = 90,
|
|
||||||
alert_desc_no_renegotiation = 100,
|
|
||||||
alert_desc_unsupported_extension = 110,
|
|
||||||
};
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// EAP-TLS packet (data)
|
/// EAP-TLS packet (data)
|
||||||
///
|
///
|
||||||
@ -193,56 +122,6 @@ namespace eap
|
|||||||
std::vector<unsigned char> m_data; ///< Packet data
|
std::vector<unsigned char> m_data; ///< Packet data
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(1)
|
|
||||||
///
|
|
||||||
/// TLS client/server random
|
|
||||||
///
|
|
||||||
struct random
|
|
||||||
{
|
|
||||||
__time32_t time; ///< Unix time-stamp
|
|
||||||
unsigned char data[28]; ///< Randomness
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Constructs a all-zero random
|
|
||||||
///
|
|
||||||
random();
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Copies a random
|
|
||||||
///
|
|
||||||
/// \param[in] other Random to copy from
|
|
||||||
///
|
|
||||||
random(_In_ const random &other);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Destructor
|
|
||||||
///
|
|
||||||
~random();
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Copies a random
|
|
||||||
///
|
|
||||||
/// \param[in] other Random to copy from
|
|
||||||
///
|
|
||||||
/// \returns Reference to this object
|
|
||||||
///
|
|
||||||
random& operator=(_In_ const random &other);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Empty the random
|
|
||||||
///
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Generate random
|
|
||||||
///
|
|
||||||
/// \param[in] cp Handle of the cryptographics provider
|
|
||||||
///
|
|
||||||
void reset(_In_ HCRYPTPROV cp);
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
#pragma pack(push)
|
#pragma pack(push)
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
///
|
///
|
||||||
@ -260,208 +139,6 @@ namespace eap
|
|||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(1)
|
|
||||||
///
|
|
||||||
/// Master secret
|
|
||||||
///
|
|
||||||
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (8.1. Computing the Master Secret)](https://tools.ietf.org/html/rfc5246#section-8.1)
|
|
||||||
///
|
|
||||||
struct master_secret
|
|
||||||
{
|
|
||||||
unsigned char data[48];
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Constructs a all-zero master secret
|
|
||||||
///
|
|
||||||
master_secret();
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Constructs a pre-master secret
|
|
||||||
///
|
|
||||||
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter 7.4.7.1. RSA-Encrypted Premaster Secret Message)](https://tools.ietf.org/html/rfc5246#section-7.4.7.1)
|
|
||||||
///
|
|
||||||
/// \param[in] cp Handle of the cryptographics provider
|
|
||||||
///
|
|
||||||
master_secret(_In_ HCRYPTPROV cp);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Copies a master secret
|
|
||||||
///
|
|
||||||
/// \param[in] other Random to copy from
|
|
||||||
///
|
|
||||||
master_secret(_In_ const master_secret &other);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Destructor
|
|
||||||
///
|
|
||||||
~master_secret();
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Copies a master secret
|
|
||||||
///
|
|
||||||
/// \param[in] other Random to copy from
|
|
||||||
///
|
|
||||||
/// \returns Reference to this object
|
|
||||||
///
|
|
||||||
master_secret& operator=(_In_ const master_secret &other);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Empty the master secret
|
|
||||||
///
|
|
||||||
void clear();
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Our own implementation of HMAC hashing
|
|
||||||
/// Microsoft's implementation ([MSDN](https://msdn.microsoft.com/en-us/library/windows/desktop/aa382379.aspx)) is flaky.
|
|
||||||
///
|
|
||||||
/// \sa [HMAC: Keyed-Hashing for Message Authentication](https://tools.ietf.org/html/rfc2104)
|
|
||||||
///
|
|
||||||
class hash_hmac
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef unsigned char padding_t[64];
|
|
||||||
|
|
||||||
public:
|
|
||||||
///
|
|
||||||
/// Construct new HMAC hashing object
|
|
||||||
///
|
|
||||||
/// \param[in] cp Handle of the cryptographics provider
|
|
||||||
/// \param[in] alg Hashing algorithm
|
|
||||||
/// \param[in] secret HMAC secret
|
|
||||||
/// \param[in] size_secret \p secret size
|
|
||||||
///
|
|
||||||
hash_hmac(
|
|
||||||
_In_ HCRYPTPROV cp,
|
|
||||||
_In_ ALG_ID alg,
|
|
||||||
_In_bytecount_(size_secret ) const void *secret,
|
|
||||||
_In_ size_t size_secret);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Construct new HMAC hashing object using already prepared inner padding
|
|
||||||
///
|
|
||||||
/// \param[in] cp Handle of the cryptographics provider
|
|
||||||
/// \param[in] alg Hashing algorithm
|
|
||||||
/// \param[in] padding HMAC secret XOR inner padding
|
|
||||||
///
|
|
||||||
hash_hmac(
|
|
||||||
_In_ HCRYPTPROV cp,
|
|
||||||
_In_ ALG_ID alg,
|
|
||||||
_In_ const padding_t padding);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Provides access to inner hash object to hash data at will.
|
|
||||||
///
|
|
||||||
/// \returns Inner hashing object handle
|
|
||||||
///
|
|
||||||
inline operator HCRYPTHASH()
|
|
||||||
{
|
|
||||||
return m_hash_inner;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Completes hashing and returns hashed data.
|
|
||||||
///
|
|
||||||
/// \param[out] val Calculated hash value
|
|
||||||
///
|
|
||||||
template<class _Ty, class _Ax>
|
|
||||||
inline void calculate(_Out_ std::vector<_Ty, _Ax> &val)
|
|
||||||
{
|
|
||||||
// Calculate inner hash.
|
|
||||||
if (!CryptGetHashParam(m_hash_inner, HP_HASHVAL, val, 0))
|
|
||||||
throw win_runtime_error(__FUNCTION__ " Error calculating inner hash.");
|
|
||||||
|
|
||||||
// Hash inner hash with outer hash.
|
|
||||||
if (!CryptHashData(m_hash_outer, (const BYTE*)val.data(), (DWORD)(val.size() * sizeof(_Ty)), 0))
|
|
||||||
throw win_runtime_error(__FUNCTION__ " Error hashing inner hash.");
|
|
||||||
|
|
||||||
// Calculate outer hash.
|
|
||||||
if (!CryptGetHashParam(m_hash_outer, HP_HASHVAL, val, 0))
|
|
||||||
throw win_runtime_error(__FUNCTION__ " Error calculating outer hash.");
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Helper method to pre-derive inner padding for frequent reuse
|
|
||||||
///
|
|
||||||
/// \param[in] cp Handle of the cryptographics provider
|
|
||||||
/// \param[in] alg Hashing algorithm
|
|
||||||
/// \param[in] secret HMAC secret
|
|
||||||
/// \param[in] size_secret \p secret size
|
|
||||||
/// \param[out] padding HMAC secret XOR inner padding
|
|
||||||
///
|
|
||||||
static void inner_padding(
|
|
||||||
_In_ HCRYPTPROV cp,
|
|
||||||
_In_ ALG_ID alg,
|
|
||||||
_In_bytecount_(size_secret ) const void *secret,
|
|
||||||
_In_ size_t size_secret,
|
|
||||||
_Out_ padding_t padding);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
winstd::crypt_hash m_hash_inner; ///< Inner hashing object
|
|
||||||
winstd::crypt_hash m_hash_outer; ///< Outer hashing object
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
///
|
|
||||||
/// TLS client connection state
|
|
||||||
///
|
|
||||||
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter 6.1. Connection States)](https://tools.ietf.org/html/rfc5246#section-6.1)
|
|
||||||
///
|
|
||||||
class conn_state
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
///
|
|
||||||
/// Constructs a connection state
|
|
||||||
///
|
|
||||||
conn_state();
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Copies a connection state
|
|
||||||
///
|
|
||||||
/// \param[in] other Connection state to copy from
|
|
||||||
///
|
|
||||||
conn_state(_In_ const conn_state &other);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Moves a connection state
|
|
||||||
///
|
|
||||||
/// \param[in] other Connection state to move from
|
|
||||||
///
|
|
||||||
conn_state(_Inout_ conn_state &&other);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Copies a connection state
|
|
||||||
///
|
|
||||||
/// \param[in] other Connection state to copy from
|
|
||||||
///
|
|
||||||
/// \returns Reference to this object
|
|
||||||
///
|
|
||||||
conn_state& operator=(_In_ const conn_state &other);
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Moves a connection state
|
|
||||||
///
|
|
||||||
/// \param[in] other Connection state to move from
|
|
||||||
///
|
|
||||||
/// \returns Reference to this object
|
|
||||||
///
|
|
||||||
conn_state& operator=(_Inout_ conn_state &&other);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const ALG_ID m_alg_prf; ///> Pseudo-random function algorithm
|
|
||||||
static const ALG_ID m_alg_encrypt; ///> Bulk encryption algorithm
|
|
||||||
static const size_t m_size_enc_key; ///> Encryption key size in bytes (has to comply with `m_alg_encrypt`)
|
|
||||||
static const size_t m_size_enc_iv; ///> Encryption initialization vector size in bytes (has to comply with `m_alg_encrypt`)
|
|
||||||
static const ALG_ID m_alg_mac; ///> Message authenticy check algorithm
|
|
||||||
static const size_t m_size_mac_key; ///> Message authenticy check algorithm key size (has to comply with `m_alg_mac`)
|
|
||||||
static const size_t m_size_mac_hash; ///> Message authenticy check algorithm result size (has to comply with `m_alg_mac`)
|
|
||||||
master_secret m_master_secret; ///< TLS master secret
|
|
||||||
random m_random_client; ///< Client random
|
|
||||||
random m_random_server; ///< Server random
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
///
|
///
|
||||||
/// Constructs an EAP method
|
/// Constructs an EAP method
|
||||||
@ -486,6 +163,11 @@ namespace eap
|
|||||||
///
|
///
|
||||||
method_tls(_Inout_ method_tls &&other);
|
method_tls(_Inout_ method_tls &&other);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Destructor
|
||||||
|
///
|
||||||
|
virtual ~method_tls();
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Copies an EAP method
|
/// Copies an EAP method
|
||||||
///
|
///
|
||||||
@ -594,7 +276,7 @@ namespace eap
|
|||||||
///
|
///
|
||||||
/// \returns Change cipher spec
|
/// \returns Change cipher spec
|
||||||
///
|
///
|
||||||
eap::sanitizing_blob make_finished();
|
eap::sanitizing_blob make_finished() const;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Makes a TLS handshake
|
/// Makes a TLS handshake
|
||||||
@ -633,6 +315,11 @@ namespace eap
|
|||||||
///
|
///
|
||||||
void derive_keys();
|
void derive_keys();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Generates master session key
|
||||||
|
///
|
||||||
|
void derive_msk();
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Processes messages in a TLS packet
|
/// Processes messages in a TLS packet
|
||||||
///
|
///
|
||||||
@ -684,7 +371,7 @@ namespace eap
|
|||||||
///
|
///
|
||||||
/// Verifies server's certificate if trusted by configuration
|
/// Verifies server's certificate if trusted by configuration
|
||||||
///
|
///
|
||||||
void verify_server_trust();
|
void verify_server_trust() const;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Encrypt TLS message
|
/// Encrypt TLS message
|
||||||
@ -698,18 +385,18 @@ namespace eap
|
|||||||
///
|
///
|
||||||
/// \param[inout] msg TLS message to decrypt
|
/// \param[inout] msg TLS message to decrypt
|
||||||
///
|
///
|
||||||
void decrypt_message(_Inout_ sanitizing_blob &msg);
|
void decrypt_message(_Inout_ sanitizing_blob &msg) const;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Calculates pseudo-random P_hash data defined in RFC 5246
|
/// 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.1 (Chapter 5: HMAC and the Pseudorandom Function)](https://tools.ietf.org/html/rfc4346#section-5)
|
||||||
///
|
///
|
||||||
/// \param[in] secret Hashing secret key
|
/// \param[in] secret Hashing secret key
|
||||||
/// \param[in] size_secret \p secret size
|
/// \param[in] size_secret \p secret size
|
||||||
/// \param[in] lblseed Concatenated label and seed
|
/// \param[in] seed Random seed
|
||||||
/// \param[in] size_lblseed \p lblseed size
|
/// \param[in] size_seed \p seed size
|
||||||
/// \param[in] size Number of bytes of pseudo-random data required
|
/// \param[in] size Number of bytes of pseudo-random data required
|
||||||
///
|
///
|
||||||
/// \returns Generated pseudo-random data (\p size bytes)
|
/// \returns Generated pseudo-random data (\p size bytes)
|
||||||
///
|
///
|
||||||
@ -718,7 +405,7 @@ namespace eap
|
|||||||
_In_ size_t size_secret,
|
_In_ size_t size_secret,
|
||||||
_In_bytecount_(size_seed) const void *seed,
|
_In_bytecount_(size_seed) const void *seed,
|
||||||
_In_ size_t size_seed,
|
_In_ size_t size_seed,
|
||||||
_In_ size_t size);
|
_In_ size_t size) const;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Creates a key
|
/// Creates a key
|
||||||
@ -778,13 +465,16 @@ namespace eap
|
|||||||
|
|
||||||
winstd::crypt_prov m_cp; ///< Cryptography provider
|
winstd::crypt_prov m_cp; ///< Cryptography provider
|
||||||
|
|
||||||
conn_state m_state; ///< Connection state
|
tls_conn_state m_state; ///< TLS connection state for fast reconnect
|
||||||
|
|
||||||
sanitizing_blob m_padding_hmac_client; ///< Padding (key) for client side HMAC calculation
|
sanitizing_blob m_padding_hmac_client; ///< Padding (key) for client side HMAC calculation
|
||||||
//sanitizing_blob m_padding_hmac_server; ///< Padding (key) for server side HMAC calculation
|
//sanitizing_blob m_padding_hmac_server; ///< Padding (key) for server side HMAC calculation
|
||||||
winstd::crypt_key m_key_client; ///< Key for encrypting messages
|
winstd::crypt_key m_key_client; ///< Key for encrypting messages
|
||||||
winstd::crypt_key m_key_server; ///< Key for decrypting messages
|
winstd::crypt_key m_key_server; ///< Key for decrypting messages
|
||||||
|
|
||||||
|
tls_random m_key_mppe_send; ///< MS-MPPE-Send-Key
|
||||||
|
tls_random m_key_mppe_recv; ///< MS-MPPE-Recv-Key
|
||||||
|
|
||||||
sanitizing_blob m_session_id; ///< TLS session ID
|
sanitizing_blob m_session_id; ///< TLS session ID
|
||||||
|
|
||||||
std::list<winstd::cert_context> m_server_cert_chain; ///< Server certificate chain
|
std::list<winstd::cert_context> m_server_cert_chain; ///< Server certificate chain
|
||||||
@ -798,5 +488,10 @@ namespace eap
|
|||||||
bool m_cipher_spec; ///< Did server specify cipher?
|
bool m_cipher_spec; ///< Did server specify cipher?
|
||||||
|
|
||||||
unsigned __int64 m_seq_num; ///< Sequence number for encryption
|
unsigned __int64 m_seq_num; ///< Sequence number for encryption
|
||||||
|
|
||||||
|
// The following members are required to avoid memory leakage in get_result()
|
||||||
|
EAP_ATTRIBUTES m_eap_attr_desc; ///< EAP Radius attributes descriptor
|
||||||
|
std::vector<winstd::eap_attr> m_eap_attr; ///< EAP Radius attributes
|
||||||
|
BYTE *m_blob_cfg; ///< Configuration BLOB
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
524
lib/TLS/include/TLS.h
Normal file
524
lib/TLS/include/TLS.h
Normal file
@ -0,0 +1,524 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015-2016 Amebis
|
||||||
|
Copyright 2016 GÉANT
|
||||||
|
|
||||||
|
This file is part of GÉANTLink.
|
||||||
|
|
||||||
|
GÉANTLink is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
GÉANTLink is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../EAPBase/include/EAP.h"
|
||||||
|
|
||||||
|
namespace eap
|
||||||
|
{
|
||||||
|
///
|
||||||
|
/// TLS packet type
|
||||||
|
///
|
||||||
|
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter: A.1. Record Layer](https://tools.ietf.org/html/rfc5246#appendix-A.1)
|
||||||
|
///
|
||||||
|
enum tls_message_type_t;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// TLS handshake type
|
||||||
|
///
|
||||||
|
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter: A.4. Handshake Protocol](https://tools.ietf.org/html/rfc5246#appendix-A.4)
|
||||||
|
///
|
||||||
|
enum tls_handshake_type_t;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// TLS alert level
|
||||||
|
///
|
||||||
|
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter: 7.2. Alert Protocol)](https://tools.ietf.org/html/rfc5246#section-7.2)
|
||||||
|
///
|
||||||
|
enum tls_alert_level_t;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// TLS alert description
|
||||||
|
///
|
||||||
|
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter: 7.2. Alert Protocol)](https://tools.ietf.org/html/rfc5246#section-7.2)
|
||||||
|
///
|
||||||
|
enum tls_alert_desc_t;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// TLS client/server tls_random
|
||||||
|
///
|
||||||
|
struct tls_random;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Master secret
|
||||||
|
///
|
||||||
|
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (8.1. Computing the Master Secret)](https://tools.ietf.org/html/rfc5246#section-8.1)
|
||||||
|
///
|
||||||
|
struct tls_master_secret;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// TLS client connection state
|
||||||
|
///
|
||||||
|
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter 6.1. Connection States)](https://tools.ietf.org/html/rfc5246#section-6.1)
|
||||||
|
///
|
||||||
|
struct tls_conn_state;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Our own implementation of HMAC hashing
|
||||||
|
/// Microsoft's implementation ([MSDN](https://msdn.microsoft.com/en-us/library/windows/desktop/aa382379.aspx)) is flaky.
|
||||||
|
///
|
||||||
|
/// \sa [HMAC: Keyed-Hashing for Message Authentication](https://tools.ietf.org/html/rfc2104)
|
||||||
|
///
|
||||||
|
class hash_hmac;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Packs a TLS tls_random
|
||||||
|
///
|
||||||
|
/// \param[inout] cursor Memory cursor
|
||||||
|
/// \param[in] val Variable with data to pack
|
||||||
|
///
|
||||||
|
inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const eap::tls_random &val);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns packed size of TLS tls_random
|
||||||
|
///
|
||||||
|
/// \param[in] val Data to pack
|
||||||
|
///
|
||||||
|
/// \returns Size of data when packed (in bytes)
|
||||||
|
///
|
||||||
|
inline size_t pksizeof(_In_ const eap::tls_random &val);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Unpacks a TLS tls_random
|
||||||
|
///
|
||||||
|
/// \param[inout] cursor Memory cursor
|
||||||
|
/// \param[out] val Variable to receive unpacked value
|
||||||
|
///
|
||||||
|
inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ eap::tls_random &val);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Packs a TLS master secret
|
||||||
|
///
|
||||||
|
/// \param[inout] cursor Memory cursor
|
||||||
|
/// \param[in] val Variable with data to pack
|
||||||
|
///
|
||||||
|
inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const eap::tls_master_secret &val);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns packed size of TLS master secret
|
||||||
|
///
|
||||||
|
/// \param[in] val Data to pack
|
||||||
|
///
|
||||||
|
/// \returns Size of data when packed (in bytes)
|
||||||
|
///
|
||||||
|
inline size_t pksizeof(_In_ const eap::tls_master_secret &val);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Unpacks a TLS master secret
|
||||||
|
///
|
||||||
|
/// \param[inout] cursor Memory cursor
|
||||||
|
/// \param[out] val Variable to receive unpacked value
|
||||||
|
///
|
||||||
|
inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ eap::tls_master_secret &val);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Packs a TLS connection state
|
||||||
|
///
|
||||||
|
/// \param[inout] cursor Memory cursor
|
||||||
|
/// \param[in] val Variable with data to pack
|
||||||
|
///
|
||||||
|
inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const eap::tls_conn_state &val);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns packed size of TLS connection state
|
||||||
|
///
|
||||||
|
/// \param[in] val Data to pack
|
||||||
|
///
|
||||||
|
/// \returns Size of data when packed (in bytes)
|
||||||
|
///
|
||||||
|
inline size_t pksizeof(_In_ const eap::tls_conn_state &val);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Unpacks a TLS connection state
|
||||||
|
///
|
||||||
|
/// \param[inout] cursor Memory cursor
|
||||||
|
/// \param[out] val Variable to receive unpacked value
|
||||||
|
///
|
||||||
|
inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ eap::tls_conn_state &val);
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
namespace eap
|
||||||
|
{
|
||||||
|
enum tls_message_type_t {
|
||||||
|
tls_message_type_change_cipher_spec = 20,
|
||||||
|
tls_message_type_alert = 21,
|
||||||
|
tls_message_type_handshake = 22,
|
||||||
|
tls_message_type_application_data = 23,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum tls_handshake_type_t {
|
||||||
|
tls_handshake_type_hello_request = 0,
|
||||||
|
tls_handshake_type_client_hello = 1,
|
||||||
|
tls_handshake_type_server_hello = 2,
|
||||||
|
tls_handshake_type_certificate = 11,
|
||||||
|
tls_handshake_type_server_key_exchange = 12,
|
||||||
|
tls_handshake_type_certificate_request = 13,
|
||||||
|
tls_handshake_type_server_hello_done = 14,
|
||||||
|
tls_handshake_type_certificate_verify = 15,
|
||||||
|
tls_handshake_type_client_key_exchange = 16,
|
||||||
|
tls_handshake_type_finished = 20
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum tls_alert_level_t {
|
||||||
|
tls_alert_level_warning = 1,
|
||||||
|
tls_alert_level_fatal = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
enum tls_alert_desc_t {
|
||||||
|
tls_alert_desc_close_notify = 0,
|
||||||
|
tls_alert_desc_unexpected_message = 10,
|
||||||
|
tls_alert_desc_bad_record_mac = 20,
|
||||||
|
tls_alert_desc_decryption_failed = 21, // reserved
|
||||||
|
tls_alert_desc_record_overflow = 22,
|
||||||
|
tls_alert_desc_decompression_failure = 30,
|
||||||
|
tls_alert_desc_handshake_failure = 40,
|
||||||
|
tls_alert_desc_no_certificate = 41, // reserved
|
||||||
|
tls_alert_desc_bad_certificate = 42,
|
||||||
|
tls_alert_desc_unsupported_certificate = 43,
|
||||||
|
tls_alert_desc_certificate_revoked = 44,
|
||||||
|
tls_alert_desc_certificate_expired = 45,
|
||||||
|
tls_alert_desc_certificate_unknown = 46,
|
||||||
|
tls_alert_desc_illegal_parameter = 47,
|
||||||
|
tls_alert_desc_unknown_ca = 48,
|
||||||
|
tls_alert_desc_access_denied = 49,
|
||||||
|
tls_alert_desc_decode_error = 50,
|
||||||
|
tls_alert_desc_decrypt_error = 51,
|
||||||
|
tls_alert_desc_export_restriction = 60, // reserved
|
||||||
|
tls_alert_desc_protocol_version = 70,
|
||||||
|
tls_alert_desc_insufficient_security = 71,
|
||||||
|
tls_alert_desc_internal_error = 80,
|
||||||
|
tls_alert_desc_user_canceled = 90,
|
||||||
|
tls_alert_desc_no_renegotiation = 100,
|
||||||
|
tls_alert_desc_unsupported_extension = 110,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack(push)
|
||||||
|
#pragma pack(1)
|
||||||
|
struct tls_random
|
||||||
|
{
|
||||||
|
unsigned char data[32]; ///< Randomness
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Constructs a all-zero tls_random
|
||||||
|
///
|
||||||
|
tls_random();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Copies a tls_random
|
||||||
|
///
|
||||||
|
/// \param[in] other Random to copy from
|
||||||
|
///
|
||||||
|
tls_random(_In_ const tls_random &other);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Destructor
|
||||||
|
///
|
||||||
|
~tls_random();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Copies a tls_random
|
||||||
|
///
|
||||||
|
/// \param[in] other Random to copy from
|
||||||
|
///
|
||||||
|
/// \returns Reference to this object
|
||||||
|
///
|
||||||
|
tls_random& operator=(_In_ const tls_random &other);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Empty the tls_random
|
||||||
|
///
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Generate tls_random
|
||||||
|
///
|
||||||
|
/// \param[in] cp Handle of the cryptographics provider
|
||||||
|
///
|
||||||
|
void reset(_In_ HCRYPTPROV cp);
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack(push)
|
||||||
|
#pragma pack(1)
|
||||||
|
struct tls_master_secret
|
||||||
|
{
|
||||||
|
unsigned char data[48];
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Constructs a all-zero master secret
|
||||||
|
///
|
||||||
|
tls_master_secret();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Constructs a pre-master secret
|
||||||
|
///
|
||||||
|
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter 7.4.7.1. RSA-Encrypted Premaster Secret Message)](https://tools.ietf.org/html/rfc5246#section-7.4.7.1)
|
||||||
|
///
|
||||||
|
/// \param[in] cp Handle of the cryptographics provider
|
||||||
|
///
|
||||||
|
tls_master_secret(_In_ HCRYPTPROV cp);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Copies a master secret
|
||||||
|
///
|
||||||
|
/// \param[in] other Random to copy from
|
||||||
|
///
|
||||||
|
tls_master_secret(_In_ const tls_master_secret &other);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Destructor
|
||||||
|
///
|
||||||
|
~tls_master_secret();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Copies a master secret
|
||||||
|
///
|
||||||
|
/// \param[in] other Random to copy from
|
||||||
|
///
|
||||||
|
/// \returns Reference to this object
|
||||||
|
///
|
||||||
|
tls_master_secret& operator=(_In_ const tls_master_secret &other);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Empty the master secret
|
||||||
|
///
|
||||||
|
void clear();
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
|
||||||
|
struct tls_conn_state
|
||||||
|
{
|
||||||
|
ALG_ID m_alg_prf; ///> Pseudo-tls_random function algorithm
|
||||||
|
ALG_ID m_alg_encrypt; ///> Bulk encryption algorithm
|
||||||
|
size_t m_size_enc_key; ///> Encryption key size in bytes (has to comply with `m_alg_encrypt`)
|
||||||
|
size_t m_size_enc_iv; ///> Encryption initialization vector size in bytes (has to comply with `m_alg_encrypt`)
|
||||||
|
ALG_ID m_alg_mac; ///> Message authenticy check algorithm
|
||||||
|
size_t m_size_mac_key; ///> Message authenticy check algorithm key size (has to comply with `m_alg_mac`)
|
||||||
|
size_t m_size_mac_hash; ///> Message authenticy check algorithm result size (has to comply with `m_alg_mac`)
|
||||||
|
tls_master_secret m_master_secret; ///< TLS master secret
|
||||||
|
tls_random m_random_client; ///< Client tls_random
|
||||||
|
tls_random m_random_server; ///< Server tls_random
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Constructs a connection state
|
||||||
|
///
|
||||||
|
tls_conn_state();
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Copies a connection state
|
||||||
|
///
|
||||||
|
/// \param[in] other Connection state to copy from
|
||||||
|
///
|
||||||
|
tls_conn_state(_In_ const tls_conn_state &other);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Moves a connection state
|
||||||
|
///
|
||||||
|
/// \param[in] other Connection state to move from
|
||||||
|
///
|
||||||
|
tls_conn_state(_Inout_ tls_conn_state &&other);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Copies a connection state
|
||||||
|
///
|
||||||
|
/// \param[in] other Connection state to copy from
|
||||||
|
///
|
||||||
|
/// \returns Reference to this object
|
||||||
|
///
|
||||||
|
tls_conn_state& operator=(_In_ const tls_conn_state &other);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Moves a connection state
|
||||||
|
///
|
||||||
|
/// \param[in] other Connection state to move from
|
||||||
|
///
|
||||||
|
/// \returns Reference to this object
|
||||||
|
///
|
||||||
|
tls_conn_state& operator=(_Inout_ tls_conn_state &&other);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class hash_hmac
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef unsigned char padding_t[64];
|
||||||
|
|
||||||
|
public:
|
||||||
|
///
|
||||||
|
/// Construct new HMAC hashing object
|
||||||
|
///
|
||||||
|
/// \param[in] cp Handle of the cryptographics provider
|
||||||
|
/// \param[in] alg Hashing algorithm
|
||||||
|
/// \param[in] secret HMAC secret
|
||||||
|
/// \param[in] size_secret \p secret size
|
||||||
|
///
|
||||||
|
hash_hmac(
|
||||||
|
_In_ HCRYPTPROV cp,
|
||||||
|
_In_ ALG_ID alg,
|
||||||
|
_In_bytecount_(size_secret ) const void *secret,
|
||||||
|
_In_ size_t size_secret);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Construct new HMAC hashing object using already prepared inner padding
|
||||||
|
///
|
||||||
|
/// \param[in] cp Handle of the cryptographics provider
|
||||||
|
/// \param[in] alg Hashing algorithm
|
||||||
|
/// \param[in] padding HMAC secret XOR inner padding
|
||||||
|
///
|
||||||
|
hash_hmac(
|
||||||
|
_In_ HCRYPTPROV cp,
|
||||||
|
_In_ ALG_ID alg,
|
||||||
|
_In_ const padding_t padding);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Provides access to inner hash object to hash data at will.
|
||||||
|
///
|
||||||
|
/// \returns Inner hashing object handle
|
||||||
|
///
|
||||||
|
inline operator HCRYPTHASH()
|
||||||
|
{
|
||||||
|
return m_hash_inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Completes hashing and returns hashed data.
|
||||||
|
///
|
||||||
|
/// \param[out] val Calculated hash value
|
||||||
|
///
|
||||||
|
template<class _Ty, class _Ax>
|
||||||
|
inline void calculate(_Out_ std::vector<_Ty, _Ax> &val)
|
||||||
|
{
|
||||||
|
// Calculate inner hash.
|
||||||
|
if (!CryptGetHashParam(m_hash_inner, HP_HASHVAL, val, 0))
|
||||||
|
throw win_runtime_error(__FUNCTION__ " Error calculating inner hash.");
|
||||||
|
|
||||||
|
// Hash inner hash with outer hash.
|
||||||
|
if (!CryptHashData(m_hash_outer, (const BYTE*)val.data(), (DWORD)(val.size() * sizeof(_Ty)), 0))
|
||||||
|
throw win_runtime_error(__FUNCTION__ " Error hashing inner hash.");
|
||||||
|
|
||||||
|
// Calculate outer hash.
|
||||||
|
if (!CryptGetHashParam(m_hash_outer, HP_HASHVAL, val, 0))
|
||||||
|
throw win_runtime_error(__FUNCTION__ " Error calculating outer hash.");
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Helper method to pre-derive inner padding for frequent reuse
|
||||||
|
///
|
||||||
|
/// \param[in] cp Handle of the cryptographics provider
|
||||||
|
/// \param[in] alg Hashing algorithm
|
||||||
|
/// \param[in] secret HMAC secret
|
||||||
|
/// \param[in] size_secret \p secret size
|
||||||
|
/// \param[out] padding HMAC secret XOR inner padding
|
||||||
|
///
|
||||||
|
static void inner_padding(
|
||||||
|
_In_ HCRYPTPROV cp,
|
||||||
|
_In_ ALG_ID alg,
|
||||||
|
_In_bytecount_(size_secret ) const void *secret,
|
||||||
|
_In_ size_t size_secret,
|
||||||
|
_Out_ padding_t padding);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
winstd::crypt_hash m_hash_inner; ///< Inner hashing object
|
||||||
|
winstd::crypt_hash m_hash_outer; ///< Outer hashing object
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const eap::tls_random &val)
|
||||||
|
{
|
||||||
|
eap::cursor_out::ptr_type ptr_end = cursor.ptr + sizeof(eap::tls_random);
|
||||||
|
assert(ptr_end <= cursor.ptr_end);
|
||||||
|
memcpy(cursor.ptr, val.data, sizeof(eap::tls_random));
|
||||||
|
cursor.ptr = ptr_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline size_t pksizeof(_In_ const eap::tls_random &val)
|
||||||
|
{
|
||||||
|
UNREFERENCED_PARAMETER(val);
|
||||||
|
return sizeof(eap::tls_random);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ eap::tls_random &val)
|
||||||
|
{
|
||||||
|
eap::cursor_in::ptr_type ptr_end = cursor.ptr + sizeof(eap::tls_random);
|
||||||
|
assert(ptr_end <= cursor.ptr_end);
|
||||||
|
memcpy(val.data, cursor.ptr, sizeof(eap::tls_random));
|
||||||
|
cursor.ptr = ptr_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const eap::tls_master_secret &val)
|
||||||
|
{
|
||||||
|
eap::cursor_out::ptr_type ptr_end = cursor.ptr + sizeof(eap::tls_master_secret);
|
||||||
|
assert(ptr_end <= cursor.ptr_end);
|
||||||
|
memcpy(cursor.ptr, val.data, sizeof(eap::tls_master_secret));
|
||||||
|
cursor.ptr = ptr_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline size_t pksizeof(_In_ const eap::tls_master_secret &val)
|
||||||
|
{
|
||||||
|
UNREFERENCED_PARAMETER(val);
|
||||||
|
return sizeof(eap::tls_master_secret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ eap::tls_master_secret &val)
|
||||||
|
{
|
||||||
|
eap::cursor_in::ptr_type ptr_end = cursor.ptr + sizeof(eap::tls_master_secret);
|
||||||
|
assert(ptr_end <= cursor.ptr_end);
|
||||||
|
memcpy(val.data, cursor.ptr, sizeof(eap::tls_master_secret));
|
||||||
|
cursor.ptr = ptr_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void operator<<(_Inout_ eap::cursor_out &cursor, _In_ const eap::tls_conn_state &val)
|
||||||
|
{
|
||||||
|
cursor << val.m_master_secret;
|
||||||
|
cursor << val.m_random_client;
|
||||||
|
cursor << val.m_random_server;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline size_t pksizeof(_In_ const eap::tls_conn_state &val)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
pksizeof(val.m_master_secret) +
|
||||||
|
pksizeof(val.m_random_client) +
|
||||||
|
pksizeof(val.m_random_server);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void operator>>(_Inout_ eap::cursor_in &cursor, _Out_ eap::tls_conn_state &val)
|
||||||
|
{
|
||||||
|
cursor >> val.m_master_secret;
|
||||||
|
cursor >> val.m_random_client;
|
||||||
|
cursor >> val.m_random_server;
|
||||||
|
}
|
@ -75,6 +75,8 @@ eap::config_method_tls::config_method_tls(_In_ module &mod) : config_method_with
|
|||||||
eap::config_method_tls::config_method_tls(_In_ const config_method_tls &other) :
|
eap::config_method_tls::config_method_tls(_In_ const config_method_tls &other) :
|
||||||
m_trusted_root_ca(other.m_trusted_root_ca),
|
m_trusted_root_ca(other.m_trusted_root_ca),
|
||||||
m_server_names(other.m_server_names),
|
m_server_names(other.m_server_names),
|
||||||
|
m_session_id(other.m_session_id),
|
||||||
|
m_master_secret(other.m_master_secret),
|
||||||
config_method_with_cred(other)
|
config_method_with_cred(other)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -83,6 +85,8 @@ eap::config_method_tls::config_method_tls(_In_ const config_method_tls &other) :
|
|||||||
eap::config_method_tls::config_method_tls(_Inout_ config_method_tls &&other) :
|
eap::config_method_tls::config_method_tls(_Inout_ config_method_tls &&other) :
|
||||||
m_trusted_root_ca(std::move(other.m_trusted_root_ca)),
|
m_trusted_root_ca(std::move(other.m_trusted_root_ca)),
|
||||||
m_server_names(std::move(other.m_server_names)),
|
m_server_names(std::move(other.m_server_names)),
|
||||||
|
m_session_id(std::move(other.m_session_id)),
|
||||||
|
m_master_secret(std::move(other.m_master_secret)),
|
||||||
config_method_with_cred(std::move(other))
|
config_method_with_cred(std::move(other))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -94,6 +98,8 @@ eap::config_method_tls& eap::config_method_tls::operator=(_In_ const config_meth
|
|||||||
(config_method_with_cred&)*this = other;
|
(config_method_with_cred&)*this = other;
|
||||||
m_trusted_root_ca = other.m_trusted_root_ca;
|
m_trusted_root_ca = other.m_trusted_root_ca;
|
||||||
m_server_names = other.m_server_names;
|
m_server_names = other.m_server_names;
|
||||||
|
m_session_id = other.m_session_id;
|
||||||
|
m_master_secret = other.m_master_secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
@ -106,6 +112,8 @@ eap::config_method_tls& eap::config_method_tls::operator=(_Inout_ config_method_
|
|||||||
(config_method_with_cred&&)*this = std::move(other);
|
(config_method_with_cred&&)*this = std::move(other);
|
||||||
m_trusted_root_ca = std::move(other.m_trusted_root_ca);
|
m_trusted_root_ca = std::move(other.m_trusted_root_ca);
|
||||||
m_server_names = std::move(other.m_server_names);
|
m_server_names = std::move(other.m_server_names);
|
||||||
|
m_session_id = std::move(other.m_session_id);
|
||||||
|
m_master_secret = std::move(other.m_master_secret);
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
@ -242,6 +250,8 @@ void eap::config_method_tls::operator<<(_Inout_ cursor_out &cursor) const
|
|||||||
config_method_with_cred::operator<<(cursor);
|
config_method_with_cred::operator<<(cursor);
|
||||||
cursor << m_trusted_root_ca;
|
cursor << m_trusted_root_ca;
|
||||||
cursor << m_server_names ;
|
cursor << m_server_names ;
|
||||||
|
cursor << m_session_id ;
|
||||||
|
cursor << m_master_secret ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -250,7 +260,9 @@ size_t eap::config_method_tls::get_pk_size() const
|
|||||||
return
|
return
|
||||||
config_method_with_cred::get_pk_size() +
|
config_method_with_cred::get_pk_size() +
|
||||||
pksizeof(m_trusted_root_ca) +
|
pksizeof(m_trusted_root_ca) +
|
||||||
pksizeof(m_server_names );
|
pksizeof(m_server_names ) +
|
||||||
|
pksizeof(m_session_id ) +
|
||||||
|
pksizeof(m_master_secret );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -259,6 +271,8 @@ void eap::config_method_tls::operator>>(_Inout_ cursor_in &cursor)
|
|||||||
config_method_with_cred::operator>>(cursor);
|
config_method_with_cred::operator>>(cursor);
|
||||||
cursor >> m_trusted_root_ca;
|
cursor >> m_trusted_root_ca;
|
||||||
cursor >> m_server_names ;
|
cursor >> m_server_names ;
|
||||||
|
cursor >> m_session_id ;
|
||||||
|
cursor >> m_master_secret ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,233 +89,6 @@ void eap::method_tls::packet::clear()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// eap::method_tls::random
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
eap::method_tls::random::random() :
|
|
||||||
time(0)
|
|
||||||
{
|
|
||||||
memset(data, 0, sizeof(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
eap::method_tls::random::random(_In_ const random &other) :
|
|
||||||
time(other.time)
|
|
||||||
{
|
|
||||||
memcpy(data, other.data, sizeof(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
eap::method_tls::random::~random()
|
|
||||||
{
|
|
||||||
SecureZeroMemory(data, sizeof(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
eap::method_tls::random& eap::method_tls::random::operator=(_In_ const random &other)
|
|
||||||
{
|
|
||||||
if (this != std::addressof(other)) {
|
|
||||||
time = other.time;
|
|
||||||
memcpy(data, other.data, sizeof(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void eap::method_tls::random::clear()
|
|
||||||
{
|
|
||||||
time = 0;
|
|
||||||
memset(data, 0, sizeof(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void eap::method_tls::random::reset(_In_ HCRYPTPROV cp)
|
|
||||||
{
|
|
||||||
_time32(&time);
|
|
||||||
if (!CryptGenRandom(cp, sizeof(data), data))
|
|
||||||
throw win_runtime_error(__FUNCTION__ " Error creating randomness.");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// eap::method_tls::master_secret
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
eap::method_tls::master_secret::master_secret()
|
|
||||||
{
|
|
||||||
memset(data, 0, sizeof(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
eap::method_tls::master_secret::master_secret(_In_ HCRYPTPROV cp)
|
|
||||||
{
|
|
||||||
data[0] = 3;
|
|
||||||
data[1] = 1;
|
|
||||||
|
|
||||||
if (!CryptGenRandom(cp, sizeof(data) - 2, data + 2))
|
|
||||||
throw win_runtime_error(__FUNCTION__ " Error creating PMS randomness.");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
eap::method_tls::master_secret::master_secret(_In_ const master_secret &other)
|
|
||||||
{
|
|
||||||
memcpy(data, other.data, sizeof(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
eap::method_tls::master_secret::~master_secret()
|
|
||||||
{
|
|
||||||
SecureZeroMemory(data, sizeof(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
eap::method_tls::master_secret& eap::method_tls::master_secret::operator=(_In_ const master_secret &other)
|
|
||||||
{
|
|
||||||
if (this != std::addressof(other))
|
|
||||||
memcpy(data, other.data, sizeof(data));
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void eap::method_tls::master_secret::clear()
|
|
||||||
{
|
|
||||||
memset(data, 0, sizeof(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// eap::method_tls::hash_hmac
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
eap::method_tls::hash_hmac::hash_hmac(
|
|
||||||
_In_ HCRYPTPROV cp,
|
|
||||||
_In_ ALG_ID alg,
|
|
||||||
_In_bytecount_(size_secret ) const void *secret,
|
|
||||||
_In_ size_t size_secret)
|
|
||||||
{
|
|
||||||
// Prepare padding.
|
|
||||||
sanitizing_blob padding(sizeof(padding_t));
|
|
||||||
inner_padding(cp, alg, secret, size_secret, padding.data());
|
|
||||||
|
|
||||||
// Continue with the other constructor.
|
|
||||||
this->hash_hmac::hash_hmac(cp, alg, padding.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
eap::method_tls::hash_hmac::hash_hmac(
|
|
||||||
_In_ HCRYPTPROV cp,
|
|
||||||
_In_ ALG_ID alg,
|
|
||||||
_In_ const padding_t padding)
|
|
||||||
{
|
|
||||||
// Create inner hash.
|
|
||||||
if (!m_hash_inner.create(cp, alg))
|
|
||||||
throw win_runtime_error(__FUNCTION__ " Error creating inner hash.");
|
|
||||||
|
|
||||||
// Initialize it with the inner padding.
|
|
||||||
if (!CryptHashData(m_hash_inner, padding, sizeof(padding_t), 0))
|
|
||||||
throw win_runtime_error(__FUNCTION__ " Error hashing secret XOR inner padding.");
|
|
||||||
|
|
||||||
// Convert inner padding to outer padding for final calculation.
|
|
||||||
padding_t padding_out;
|
|
||||||
for (size_t i = 0; i < sizeof(padding_t); i++)
|
|
||||||
padding_out[i] = padding[i] ^ (0x36 ^ 0x5c);
|
|
||||||
|
|
||||||
// Create outer hash.
|
|
||||||
if (!m_hash_outer.create(cp, alg))
|
|
||||||
throw win_runtime_error(__FUNCTION__ " Error creating outer hash.");
|
|
||||||
|
|
||||||
// Initialize it with the outer padding.
|
|
||||||
if (!CryptHashData(m_hash_outer, padding_out, sizeof(padding_t), 0))
|
|
||||||
throw win_runtime_error(__FUNCTION__ " Error hashing secret XOR inner padding.");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void eap::method_tls::hash_hmac::inner_padding(
|
|
||||||
_In_ HCRYPTPROV cp,
|
|
||||||
_In_ ALG_ID alg,
|
|
||||||
_In_bytecount_(size_secret ) const void *secret,
|
|
||||||
_In_ size_t size_secret,
|
|
||||||
_Out_ padding_t padding)
|
|
||||||
{
|
|
||||||
if (size_secret > sizeof(padding_t)) {
|
|
||||||
// If the secret is longer than padding, use secret's hash instead.
|
|
||||||
crypt_hash hash;
|
|
||||||
if (!hash.create(cp, alg))
|
|
||||||
throw win_runtime_error(__FUNCTION__ " Error creating hash.");
|
|
||||||
if (!CryptHashData(hash, (const BYTE*)secret, (DWORD)size_secret, 0))
|
|
||||||
throw win_runtime_error(__FUNCTION__ " Error hashing.");
|
|
||||||
DWORD size_hash = sizeof(padding_t);
|
|
||||||
if (!CryptGetHashParam(hash, HP_HASHVAL, padding, &size_hash, 0))
|
|
||||||
throw win_runtime_error(__FUNCTION__ " Error finishing hash.");
|
|
||||||
size_secret = size_hash;
|
|
||||||
} else
|
|
||||||
memcpy(padding, secret, size_secret);
|
|
||||||
for (size_t i = 0; i < size_secret; i++)
|
|
||||||
padding[i] ^= 0x36;
|
|
||||||
memset(padding + size_secret, 0x36, sizeof(padding_t) - size_secret);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// eap::method_tls::conn_state
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
eap::method_tls::conn_state::conn_state()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
eap::method_tls::conn_state::conn_state(_In_ const conn_state &other) :
|
|
||||||
m_master_secret(other.m_master_secret),
|
|
||||||
m_random_client(other.m_random_client),
|
|
||||||
m_random_server(other.m_random_server)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
eap::method_tls::conn_state::conn_state(_Inout_ conn_state &&other) :
|
|
||||||
m_master_secret(std::move(other.m_master_secret)),
|
|
||||||
m_random_client(std::move(other.m_random_client)),
|
|
||||||
m_random_server(std::move(other.m_random_server))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
eap::method_tls::conn_state& eap::method_tls::conn_state::operator=(_In_ const conn_state &other)
|
|
||||||
{
|
|
||||||
if (this != std::addressof(other)) {
|
|
||||||
m_master_secret = other.m_master_secret;
|
|
||||||
m_random_client = other.m_random_client;
|
|
||||||
m_random_server = other.m_random_server;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
eap::method_tls::conn_state& eap::method_tls::conn_state::operator=(_Inout_ conn_state &&other)
|
|
||||||
{
|
|
||||||
if (this != std::addressof(other)) {
|
|
||||||
m_master_secret = std::move(other.m_master_secret);
|
|
||||||
m_random_client = std::move(other.m_random_client);
|
|
||||||
m_random_server = std::move(other.m_random_server);
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const ALG_ID eap::method_tls::conn_state::m_alg_prf = CALG_TLS1PRF;
|
|
||||||
const ALG_ID eap::method_tls::conn_state::m_alg_encrypt = CALG_3DES;
|
|
||||||
const size_t eap::method_tls::conn_state::m_size_enc_key = 192/8; // 3DES 192bits
|
|
||||||
const size_t eap::method_tls::conn_state::m_size_enc_iv = 64/8; // 3DES 64bits
|
|
||||||
const ALG_ID eap::method_tls::conn_state::m_alg_mac = CALG_SHA1;
|
|
||||||
const size_t eap::method_tls::conn_state::m_size_mac_key = 160/8; // SHA-1
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// eap::method_tls
|
// eap::method_tls
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@ -329,6 +102,7 @@ eap::method_tls::method_tls(_In_ module &module, _In_ config_method_tls &cfg, _I
|
|||||||
m_server_finished(false),
|
m_server_finished(false),
|
||||||
m_cipher_spec(false),
|
m_cipher_spec(false),
|
||||||
m_seq_num(0),
|
m_seq_num(0),
|
||||||
|
m_blob_cfg(NULL),
|
||||||
method(module, cfg, cred)
|
method(module, cfg, cred)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -341,6 +115,12 @@ eap::method_tls::method_tls(_In_ const method_tls &other) :
|
|||||||
m_packet_req(other.m_packet_req),
|
m_packet_req(other.m_packet_req),
|
||||||
m_packet_res(other.m_packet_res),
|
m_packet_res(other.m_packet_res),
|
||||||
m_state(other.m_state),
|
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_send(other.m_key_mppe_send),
|
||||||
|
m_key_mppe_recv(other.m_key_mppe_recv),
|
||||||
m_session_id(other.m_session_id),
|
m_session_id(other.m_session_id),
|
||||||
m_server_cert_chain(other.m_server_cert_chain),
|
m_server_cert_chain(other.m_server_cert_chain),
|
||||||
m_hash_handshake_msgs_md5(other.m_hash_handshake_msgs_md5),
|
m_hash_handshake_msgs_md5(other.m_hash_handshake_msgs_md5),
|
||||||
@ -362,6 +142,12 @@ eap::method_tls::method_tls(_Inout_ method_tls &&other) :
|
|||||||
m_packet_req(std::move(other.m_packet_req)),
|
m_packet_req(std::move(other.m_packet_req)),
|
||||||
m_packet_res(std::move(other.m_packet_res)),
|
m_packet_res(std::move(other.m_packet_res)),
|
||||||
m_state(std::move(other.m_state)),
|
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_send(std::move(other.m_key_mppe_send)),
|
||||||
|
m_key_mppe_recv(std::move(other.m_key_mppe_recv)),
|
||||||
m_session_id(std::move(other.m_session_id)),
|
m_session_id(std::move(other.m_session_id)),
|
||||||
m_server_cert_chain(std::move(other.m_server_cert_chain)),
|
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_md5(std::move(other.m_hash_handshake_msgs_md5)),
|
||||||
@ -376,25 +162,38 @@ eap::method_tls::method_tls(_Inout_ method_tls &&other) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eap::method_tls::~method_tls()
|
||||||
|
{
|
||||||
|
if (m_blob_cfg)
|
||||||
|
m_module.free_memory(m_blob_cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
eap::method_tls& eap::method_tls::operator=(_In_ const method_tls &other)
|
eap::method_tls& eap::method_tls::operator=(_In_ const method_tls &other)
|
||||||
{
|
{
|
||||||
if (this != std::addressof(other)) {
|
if (this != std::addressof(other)) {
|
||||||
assert(std::addressof(m_cfg ) == std::addressof(other.m_cfg )); // Copy method with same configuration only!
|
assert(std::addressof(m_cfg ) == std::addressof(other.m_cfg )); // Copy method with same configuration only!
|
||||||
assert(std::addressof(m_cred) == std::addressof(other.m_cred)); // Copy method with same credentials only!
|
assert(std::addressof(m_cred) == std::addressof(other.m_cred)); // Copy method with same credentials only!
|
||||||
(method&)*this = other;
|
(method&)*this = other;
|
||||||
m_phase = other.m_phase;
|
m_phase = other.m_phase;
|
||||||
m_packet_req = other.m_packet_req;
|
m_packet_req = other.m_packet_req;
|
||||||
m_packet_res = other.m_packet_res;
|
m_packet_res = other.m_packet_res;
|
||||||
m_state = other.m_state;
|
m_state = other.m_state;
|
||||||
m_session_id = other.m_session_id;
|
m_padding_hmac_client = other.m_padding_hmac_client;
|
||||||
m_server_cert_chain = other.m_server_cert_chain;
|
//m_padding_hmac_server = other.m_padding_hmac_server;
|
||||||
m_hash_handshake_msgs_md5 = other.m_hash_handshake_msgs_md5;
|
m_key_client = other.m_key_client;
|
||||||
m_hash_handshake_msgs_sha1 = other.m_hash_handshake_msgs_sha1;
|
m_key_server = other.m_key_server;
|
||||||
m_send_client_cert = other.m_send_client_cert;
|
m_key_mppe_send = other.m_key_mppe_send;
|
||||||
m_server_hello_done = other.m_server_hello_done;
|
m_key_mppe_recv = other.m_key_mppe_recv;
|
||||||
m_server_finished = other.m_server_finished;
|
m_session_id = other.m_session_id;
|
||||||
m_cipher_spec = other.m_cipher_spec;
|
m_server_cert_chain = other.m_server_cert_chain;
|
||||||
m_seq_num = other.m_seq_num;
|
m_hash_handshake_msgs_md5 = other.m_hash_handshake_msgs_md5;
|
||||||
|
m_hash_handshake_msgs_sha1 = other.m_hash_handshake_msgs_sha1;
|
||||||
|
m_send_client_cert = other.m_send_client_cert;
|
||||||
|
m_server_hello_done = other.m_server_hello_done;
|
||||||
|
m_server_finished = other.m_server_finished;
|
||||||
|
m_cipher_spec = other.m_cipher_spec;
|
||||||
|
m_seq_num = other.m_seq_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
@ -406,20 +205,26 @@ eap::method_tls& eap::method_tls::operator=(_Inout_ method_tls &&other)
|
|||||||
if (this != std::addressof(other)) {
|
if (this != std::addressof(other)) {
|
||||||
assert(std::addressof(m_cfg ) == std::addressof(other.m_cfg )); // Move method with same configuration only!
|
assert(std::addressof(m_cfg ) == std::addressof(other.m_cfg )); // Move method with same configuration only!
|
||||||
assert(std::addressof(m_cred) == std::addressof(other.m_cred)); // Move method with same credentials only!
|
assert(std::addressof(m_cred) == std::addressof(other.m_cred)); // Move method with same credentials only!
|
||||||
(method&)*this = std::move(other);
|
(method&)*this = std::move(other);
|
||||||
m_phase = std::move(other.m_phase);
|
m_phase = std::move(other.m_phase);
|
||||||
m_packet_req = std::move(other.m_packet_req);
|
m_packet_req = std::move(other.m_packet_req);
|
||||||
m_packet_res = std::move(other.m_packet_res);
|
m_packet_res = std::move(other.m_packet_res);
|
||||||
m_state = std::move(other.m_state);
|
m_state = std::move(other.m_state);
|
||||||
m_session_id = std::move(other.m_session_id);
|
m_padding_hmac_client = std::move(other.m_padding_hmac_client);
|
||||||
m_server_cert_chain = std::move(other.m_server_cert_chain);
|
//m_padding_hmac_server = std::move(other.m_padding_hmac_server);
|
||||||
m_hash_handshake_msgs_md5 = std::move(other.m_hash_handshake_msgs_md5);
|
m_key_client = std::move(other.m_key_client);
|
||||||
m_hash_handshake_msgs_sha1 = std::move(other.m_hash_handshake_msgs_sha1);
|
m_key_server = std::move(other.m_key_server);
|
||||||
m_send_client_cert = std::move(other.m_send_client_cert);
|
m_key_mppe_send = std::move(other.m_key_mppe_send);
|
||||||
m_server_hello_done = std::move(other.m_server_hello_done);
|
m_key_mppe_recv = std::move(other.m_key_mppe_recv);
|
||||||
m_server_finished = std::move(other.m_server_finished);
|
m_session_id = std::move(other.m_session_id);
|
||||||
m_cipher_spec = std::move(other.m_cipher_spec);
|
m_server_cert_chain = std::move(other.m_server_cert_chain);
|
||||||
m_seq_num = std::move(other.m_seq_num);
|
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_send_client_cert = std::move(other.m_send_client_cert);
|
||||||
|
m_server_hello_done = std::move(other.m_server_hello_done);
|
||||||
|
m_server_finished = std::move(other.m_server_finished);
|
||||||
|
m_cipher_spec = std::move(other.m_cipher_spec);
|
||||||
|
m_seq_num = std::move(other.m_seq_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
@ -437,6 +242,9 @@ void eap::method_tls::begin_session(
|
|||||||
// Create cryptographics provider.
|
// Create cryptographics provider.
|
||||||
if (!m_cp.create(NULL, MS_ENHANCED_PROV, PROV_RSA_FULL))
|
if (!m_cp.create(NULL, MS_ENHANCED_PROV, PROV_RSA_FULL))
|
||||||
throw win_runtime_error(__FUNCTION__ " Error creating cryptographics provider.");
|
throw win_runtime_error(__FUNCTION__ " Error creating cryptographics provider.");
|
||||||
|
|
||||||
|
m_session_id = m_cfg.m_session_id;
|
||||||
|
m_state.m_master_secret = m_cfg.m_master_secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -530,15 +338,18 @@ void eap::method_tls::process_request_packet(
|
|||||||
|
|
||||||
m_phase = phase_client_hello;
|
m_phase = phase_client_hello;
|
||||||
m_packet_res.clear();
|
m_packet_res.clear();
|
||||||
|
|
||||||
|
m_state.m_random_client.reset(m_cp);
|
||||||
|
|
||||||
|
// Generate client randomness.
|
||||||
m_padding_hmac_client.clear();
|
m_padding_hmac_client.clear();
|
||||||
//m_padding_hmac_server.clear();
|
//m_padding_hmac_server.clear();
|
||||||
m_key_client.free();
|
m_key_client.free();
|
||||||
m_key_server.free();
|
m_key_server.free();
|
||||||
|
m_key_mppe_send.clear();
|
||||||
|
m_key_mppe_recv.clear();
|
||||||
|
|
||||||
// Generate client randomness.
|
|
||||||
m_state.m_random_client.reset(m_cp);
|
|
||||||
m_server_cert_chain.clear();
|
m_server_cert_chain.clear();
|
||||||
m_session_id.clear();
|
|
||||||
|
|
||||||
// Create MD5 hash object.
|
// Create MD5 hash object.
|
||||||
if (!m_hash_handshake_msgs_md5.create(m_cp, CALG_MD5))
|
if (!m_hash_handshake_msgs_md5.create(m_cp, CALG_MD5))
|
||||||
@ -612,7 +423,7 @@ void eap::method_tls::process_request_packet(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate pre-master secret and encrypt it. PMS will get sanitized in its destructor when going out-of-scope.
|
// Generate pre-master secret and encrypt it. PMS will get sanitized in its destructor when going out-of-scope.
|
||||||
master_secret pms(m_cp);
|
tls_master_secret pms(m_cp);
|
||||||
sanitizing_blob pms_enc((const unsigned char*)&pms, (const unsigned char*)(&pms + 1));
|
sanitizing_blob pms_enc((const unsigned char*)&pms, (const unsigned char*)(&pms + 1));
|
||||||
crypt_key key;
|
crypt_key key;
|
||||||
if (!key.import_public(m_cp, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &(m_server_cert_chain.front()->pCertInfo->SubjectPublicKeyInfo)))
|
if (!key.import_public(m_cp, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &(m_server_cert_chain.front()->pCertInfo->SubjectPublicKeyInfo)))
|
||||||
@ -621,12 +432,12 @@ void eap::method_tls::process_request_packet(
|
|||||||
throw win_runtime_error(__FUNCTION__ " Error encrypting PMS.");
|
throw win_runtime_error(__FUNCTION__ " Error encrypting PMS.");
|
||||||
|
|
||||||
// Derive master secret.
|
// Derive master secret.
|
||||||
sanitizing_blob lblseed;
|
sanitizing_blob seed;
|
||||||
const unsigned char s_label[] = "master secret";
|
static const unsigned char s_label[] = "master secret";
|
||||||
lblseed.assign(s_label, s_label + _countof(s_label) - 1);
|
seed.assign(s_label, s_label + _countof(s_label) - 1);
|
||||||
lblseed.insert(lblseed.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_client, (const unsigned char*)(&m_state.m_random_client + 1));
|
||||||
lblseed.insert(lblseed.end(), (const unsigned char*)&m_state.m_random_server, (const unsigned char*)(&m_state.m_random_server + 1));
|
seed.insert(seed.end(), (const unsigned char*)&m_state.m_random_server, (const unsigned char*)(&m_state.m_random_server + 1));
|
||||||
memcpy(&m_state.m_master_secret, prf(&pms, sizeof(pms), lblseed.data(), lblseed.size(), sizeof(master_secret)).data(), sizeof(master_secret));
|
memcpy(&m_state.m_master_secret, prf(&pms, sizeof(pms), seed.data(), seed.size(), sizeof(tls_master_secret)).data(), sizeof(tls_master_secret));
|
||||||
|
|
||||||
// Create client key exchange message, and append to packet.
|
// Create client key exchange message, and append to packet.
|
||||||
sanitizing_blob client_key_exchange(make_client_key_exchange(pms_enc));
|
sanitizing_blob client_key_exchange(make_client_key_exchange(pms_enc));
|
||||||
@ -751,10 +562,57 @@ void eap::method_tls::get_result(
|
|||||||
_In_ EapPeerMethodResultReason reason,
|
_In_ EapPeerMethodResultReason reason,
|
||||||
_Inout_ EapPeerMethodResult *ppResult)
|
_Inout_ EapPeerMethodResult *ppResult)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(reason);
|
assert(ppResult);
|
||||||
UNREFERENCED_PARAMETER(ppResult);
|
|
||||||
|
|
||||||
throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Not supported.");
|
switch (reason) {
|
||||||
|
case EapPeerMethodResultSuccess: {
|
||||||
|
if (m_phase < phase_change_chiper_spec)
|
||||||
|
throw invalid_argument(__FUNCTION__ " Premature success.");
|
||||||
|
|
||||||
|
// Derive MSK.
|
||||||
|
derive_msk();
|
||||||
|
|
||||||
|
// Fill array with RADIUS attributes.
|
||||||
|
eap_attr a;
|
||||||
|
m_eap_attr.clear();
|
||||||
|
a.create_ms_mppe_key(16, (LPCBYTE)&m_key_mppe_send, sizeof(tls_random));
|
||||||
|
m_eap_attr.push_back(std::move(a));
|
||||||
|
a.create_ms_mppe_key(17, (LPCBYTE)&m_key_mppe_recv, sizeof(tls_random));
|
||||||
|
m_eap_attr.push_back(std::move(a));
|
||||||
|
m_eap_attr.push_back(eap_attr::blank);
|
||||||
|
|
||||||
|
m_eap_attr_desc.dwNumberOfAttributes = (DWORD)m_eap_attr.size();
|
||||||
|
m_eap_attr_desc.pAttribs = m_eap_attr.data();
|
||||||
|
ppResult->pAttribArray = &m_eap_attr_desc;
|
||||||
|
|
||||||
|
ppResult->fIsSuccess = TRUE;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
case EapPeerMethodResultFailure:
|
||||||
|
// :(
|
||||||
|
m_cfg.m_session_id.clear();
|
||||||
|
m_cfg.m_master_secret.clear();
|
||||||
|
ppResult->fSaveConnectionData = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -763,20 +621,20 @@ eap::sanitizing_blob eap::method_tls::make_client_hello() const
|
|||||||
size_t size_data;
|
size_t size_data;
|
||||||
sanitizing_blob msg;
|
sanitizing_blob msg;
|
||||||
msg.reserve(
|
msg.reserve(
|
||||||
4 + // SSL header
|
4 + // SSL header
|
||||||
(size_data =
|
(size_data =
|
||||||
2 + // SSL version
|
2 + // SSL version
|
||||||
sizeof(random) + // Client random
|
sizeof(tls_random) + // Client random
|
||||||
1 + // Session ID size
|
1 + // Session ID size
|
||||||
m_session_id.size() + // Session ID
|
m_session_id.size() + // Session ID
|
||||||
2 + // Length of cypher suite list
|
2 + // Length of cypher suite list
|
||||||
2 + // Cyper suite list
|
2 + // Cyper suite list
|
||||||
1 + // Length of compression suite
|
1 + // Length of compression suite
|
||||||
1)); // Compression suite
|
1)); // Compression suite
|
||||||
|
|
||||||
// SSL header
|
// SSL header
|
||||||
assert(size_data <= 0xffffff);
|
assert(size_data <= 0xffffff);
|
||||||
unsigned int ssl_header = htonl(((unsigned int)handshake_type_client_hello << 24) | (unsigned int)size_data);
|
unsigned int ssl_header = htonl(((unsigned int)tls_handshake_type_client_hello << 24) | (unsigned int)size_data);
|
||||||
msg.insert(msg.end(), (unsigned char*)&ssl_header, (unsigned char*)(&ssl_header + 1));
|
msg.insert(msg.end(), (unsigned char*)&ssl_header, (unsigned char*)(&ssl_header + 1));
|
||||||
|
|
||||||
// SSL version: TLS 1.0
|
// SSL version: TLS 1.0
|
||||||
@ -829,7 +687,7 @@ eap::sanitizing_blob eap::method_tls::make_client_cert() const
|
|||||||
|
|
||||||
// SSL header
|
// SSL header
|
||||||
assert(size_data <= 0xffffff);
|
assert(size_data <= 0xffffff);
|
||||||
unsigned int ssl_header = htonl(((unsigned int)handshake_type_certificate << 24) | (unsigned int)size_data);
|
unsigned int ssl_header = htonl(((unsigned int)tls_handshake_type_certificate << 24) | (unsigned int)size_data);
|
||||||
msg.insert(msg.end(), (unsigned char*)&ssl_header, (unsigned char*)(&ssl_header + 1));
|
msg.insert(msg.end(), (unsigned char*)&ssl_header, (unsigned char*)(&ssl_header + 1));
|
||||||
|
|
||||||
// List size
|
// List size
|
||||||
@ -864,7 +722,7 @@ eap::sanitizing_blob eap::method_tls::make_client_key_exchange(_In_ const saniti
|
|||||||
|
|
||||||
// SSL header
|
// SSL header
|
||||||
assert(size_data <= 0xffffff);
|
assert(size_data <= 0xffffff);
|
||||||
unsigned int ssl_header = htonl(((unsigned int)handshake_type_client_key_exchange << 24) | (unsigned int)size_data);
|
unsigned int ssl_header = htonl(((unsigned int)tls_handshake_type_client_key_exchange << 24) | (unsigned int)size_data);
|
||||||
msg.insert(msg.end(), (unsigned char*)&ssl_header, (unsigned char*)(&ssl_header + 1));
|
msg.insert(msg.end(), (unsigned char*)&ssl_header, (unsigned char*)(&ssl_header + 1));
|
||||||
|
|
||||||
// Encrypted pre master secret size
|
// Encrypted pre master secret size
|
||||||
@ -882,18 +740,18 @@ eap::sanitizing_blob eap::method_tls::make_client_key_exchange(_In_ const saniti
|
|||||||
eap::sanitizing_blob eap::method_tls::make_change_chiper_spec()
|
eap::sanitizing_blob eap::method_tls::make_change_chiper_spec()
|
||||||
{
|
{
|
||||||
static const unsigned char s_msg_css[] = {
|
static const unsigned char s_msg_css[] = {
|
||||||
(unsigned char)message_type_change_cipher_spec, // SSL record type
|
(unsigned char)tls_message_type_change_cipher_spec, // SSL record type
|
||||||
3, // SSL major version
|
3, // SSL major version
|
||||||
1, // SSL minor version
|
1, // SSL minor version
|
||||||
0, // Message size (high-order byte)
|
0, // Message size (high-order byte)
|
||||||
1, // Message size (low-order byte)
|
1, // Message size (low-order byte)
|
||||||
1, // Message: change_cipher_spec is always "1"
|
1, // Message: change_cipher_spec is always "1"
|
||||||
};
|
};
|
||||||
return eap::sanitizing_blob(s_msg_css, s_msg_css + _countof(s_msg_css));
|
return eap::sanitizing_blob(s_msg_css, s_msg_css + _countof(s_msg_css));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
eap::sanitizing_blob eap::method_tls::make_finished()
|
eap::sanitizing_blob eap::method_tls::make_finished() const
|
||||||
{
|
{
|
||||||
sanitizing_blob msg;
|
sanitizing_blob msg;
|
||||||
msg.reserve(
|
msg.reserve(
|
||||||
@ -901,20 +759,22 @@ eap::sanitizing_blob eap::method_tls::make_finished()
|
|||||||
12); // verify_data is 12B
|
12); // verify_data is 12B
|
||||||
|
|
||||||
// SSL header
|
// SSL header
|
||||||
unsigned int ssl_header = htonl(((unsigned int)handshake_type_finished << 24) | 12);
|
unsigned int ssl_header = htonl(((unsigned int)tls_handshake_type_finished << 24) | 12);
|
||||||
msg.insert(msg.end(), (unsigned char*)&ssl_header, (unsigned char*)(&ssl_header + 1));
|
msg.insert(msg.end(), (unsigned char*)&ssl_header, (unsigned char*)(&ssl_header + 1));
|
||||||
|
|
||||||
// Create label + hash MD5 + hash SHA-1 seed.
|
// Create label + hash MD5 + hash SHA-1 seed.
|
||||||
sanitizing_blob lblseed, hash;
|
crypt_hash hash;
|
||||||
const unsigned char s_label[] = "client finished";
|
static const unsigned char s_label[] = "client finished";
|
||||||
lblseed.assign(s_label, s_label + _countof(s_label) - 1);
|
sanitizing_blob seed(s_label, s_label + _countof(s_label) - 1), hash_data;
|
||||||
if (!CryptGetHashParam(m_hash_handshake_msgs_md5, HP_HASHVAL, hash, 0))
|
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.");
|
throw win_runtime_error(__FUNCTION__ " Error finishing MD5 hash calculation.");
|
||||||
lblseed.insert(lblseed.end(), hash.begin(), hash.end());
|
seed.insert(seed.end(), hash_data.begin(), hash_data.end());
|
||||||
if (!CryptGetHashParam(m_hash_handshake_msgs_sha1, HP_HASHVAL, hash, 0))
|
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.");
|
throw win_runtime_error(__FUNCTION__ " Error finishing SHA-1 hash calculation.");
|
||||||
lblseed.insert(lblseed.end(), hash.begin(), hash.end());
|
seed.insert(seed.end(), hash_data.begin(), hash_data.end());
|
||||||
sanitizing_blob verify(prf(&m_state.m_master_secret, sizeof(master_secret), lblseed.data(), lblseed.size(), 12));
|
sanitizing_blob verify(prf(&m_state.m_master_secret, sizeof(tls_master_secret), seed.data(), seed.size(), 12));
|
||||||
msg.insert(msg.end(), verify.begin(), verify.end());
|
msg.insert(msg.end(), verify.begin(), verify.end());
|
||||||
|
|
||||||
return msg;
|
return msg;
|
||||||
@ -932,7 +792,7 @@ eap::sanitizing_blob eap::method_tls::make_handshake(_In_ const sanitizing_blob
|
|||||||
size_msg); // Message
|
size_msg); // Message
|
||||||
|
|
||||||
// SSL record type
|
// SSL record type
|
||||||
msg_h.push_back((unsigned char)message_type_handshake);
|
msg_h.push_back((unsigned char)tls_message_type_handshake);
|
||||||
|
|
||||||
// SSL version: TLS 1.0
|
// SSL version: TLS 1.0
|
||||||
msg_h.push_back(3); // SSL major version
|
msg_h.push_back(3); // SSL major version
|
||||||
@ -950,13 +810,13 @@ eap::sanitizing_blob eap::method_tls::make_handshake(_In_ const sanitizing_blob
|
|||||||
|
|
||||||
void eap::method_tls::derive_keys()
|
void eap::method_tls::derive_keys()
|
||||||
{
|
{
|
||||||
sanitizing_blob lblseed;
|
sanitizing_blob seed;
|
||||||
const unsigned char s_label[] = "key expansion";
|
static const unsigned char s_label[] = "key expansion";
|
||||||
lblseed.assign(s_label, s_label + _countof(s_label) - 1);
|
seed.assign(s_label, s_label + _countof(s_label) - 1);
|
||||||
lblseed.insert(lblseed.end(), (const unsigned char*)&m_state.m_random_server, (const unsigned char*)(&m_state.m_random_server + 1));
|
seed.insert(seed.end(), (const unsigned char*)&m_state.m_random_server, (const unsigned char*)(&m_state.m_random_server + 1));
|
||||||
lblseed.insert(lblseed.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_client, (const unsigned char*)(&m_state.m_random_client + 1));
|
||||||
|
|
||||||
sanitizing_blob key_block(prf(&m_state.m_master_secret, sizeof(master_secret), lblseed.data(), lblseed.size(),
|
sanitizing_blob key_block(prf(&m_state.m_master_secret, sizeof(tls_master_secret), seed.data(), seed.size(),
|
||||||
2*m_state.m_size_mac_key + // client_write_MAC_secret & server_write_MAC_secret (SHA1)
|
2*m_state.m_size_mac_key + // client_write_MAC_secret & server_write_MAC_secret (SHA1)
|
||||||
2*m_state.m_size_enc_key + // client_write_key & server_write_key
|
2*m_state.m_size_enc_key + // client_write_key & server_write_key
|
||||||
2*m_state.m_size_enc_iv )); // client_write_IV & server_write_IV
|
2*m_state.m_size_enc_iv )); // client_write_IV & server_write_IV
|
||||||
@ -992,6 +852,26 @@ void eap::method_tls::derive_keys()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void eap::method_tls::derive_msk()
|
||||||
|
{
|
||||||
|
sanitizing_blob seed;
|
||||||
|
static const unsigned char s_label[] = "ttls keying material";
|
||||||
|
seed.assign(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, sizeof(tls_master_secret), seed.data(), seed.size(), 2*sizeof(tls_random)));
|
||||||
|
const unsigned char *_key_block = key_block.data();
|
||||||
|
|
||||||
|
// MS-MPPE-Send-Key
|
||||||
|
memcpy(&m_key_mppe_send, _key_block, sizeof(tls_random));
|
||||||
|
_key_block += sizeof(tls_random);
|
||||||
|
|
||||||
|
// MS-MPPE-Recv-Key
|
||||||
|
memcpy(&m_key_mppe_recv, _key_block, sizeof(tls_random));
|
||||||
|
_key_block += sizeof(tls_random);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void eap::method_tls::process_packet(_In_bytecount_(size_pck) const void *_pck, _In_ size_t size_pck)
|
void eap::method_tls::process_packet(_In_bytecount_(size_pck) const void *_pck, _In_ size_t size_pck)
|
||||||
{
|
{
|
||||||
for (const unsigned char *pck = (const unsigned char*)_pck, *pck_end = pck + size_pck; pck < pck_end; ) {
|
for (const unsigned char *pck = (const unsigned char*)_pck, *pck_end = pck + size_pck; pck < pck_end; ) {
|
||||||
@ -1007,11 +887,11 @@ void eap::method_tls::process_packet(_In_bytecount_(size_pck) const void *_pck,
|
|||||||
if (hdr->version.major == 3 && hdr->version.minor == 1) {
|
if (hdr->version.major == 3 && hdr->version.minor == 1) {
|
||||||
// Process TLS 1.0 message.
|
// Process TLS 1.0 message.
|
||||||
switch (hdr->type) {
|
switch (hdr->type) {
|
||||||
case message_type_change_cipher_spec:
|
case tls_message_type_change_cipher_spec:
|
||||||
process_change_cipher_spec(msg, msg_end - msg);
|
process_change_cipher_spec(msg, msg_end - msg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case message_type_alert:
|
case tls_message_type_alert:
|
||||||
if (m_cipher_spec) {
|
if (m_cipher_spec) {
|
||||||
sanitizing_blob msg_dec(msg, msg_end);
|
sanitizing_blob msg_dec(msg, msg_end);
|
||||||
decrypt_message(msg_dec);
|
decrypt_message(msg_dec);
|
||||||
@ -1020,7 +900,7 @@ void eap::method_tls::process_packet(_In_bytecount_(size_pck) const void *_pck,
|
|||||||
process_alert(msg, msg_end - msg);
|
process_alert(msg, msg_end - msg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case message_type_handshake:
|
case tls_message_type_handshake:
|
||||||
if (m_cipher_spec) {
|
if (m_cipher_spec) {
|
||||||
sanitizing_blob msg_dec(msg, msg_end);
|
sanitizing_blob msg_dec(msg, msg_end);
|
||||||
decrypt_message(msg_dec);
|
decrypt_message(msg_dec);
|
||||||
@ -1029,7 +909,7 @@ void eap::method_tls::process_packet(_In_bytecount_(size_pck) const void *_pck,
|
|||||||
process_handshake(msg, msg_end - msg);
|
process_handshake(msg, msg_end - msg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case message_type_application_data:
|
case tls_message_type_application_data:
|
||||||
if (!m_cipher_spec)
|
if (!m_cipher_spec)
|
||||||
throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, __FUNCTION__ " Application data should be encrypted.");
|
throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, __FUNCTION__ " Application data should be encrypted.");
|
||||||
|
|
||||||
@ -1096,19 +976,20 @@ void eap::method_tls::process_handshake(_In_bytecount_(msg_size) const void *_ms
|
|||||||
// Process record.
|
// Process record.
|
||||||
unsigned char type = hdr >> 24;
|
unsigned char type = hdr >> 24;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case handshake_type_server_hello:
|
case tls_handshake_type_server_hello:
|
||||||
// TLS version
|
// TLS version
|
||||||
if (rec + 2 > rec_end)
|
if (rec + 2 > rec_end)
|
||||||
throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, __FUNCTION__ " Server SSL/TLS version missing or incomplete.");
|
throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, __FUNCTION__ " Server SSL/TLS version missing or incomplete.");
|
||||||
else if (rec[0] != 3 || rec[1] != 1)
|
else if (rec[0] != 3 || rec[1] != 1)
|
||||||
throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Unsupported SSL/TLS version.");
|
throw win_runtime_error(ERROR_NOT_SUPPORTED, __FUNCTION__ " Unsupported SSL/TLS version.");
|
||||||
|
m_state.m_alg_prf = CALG_TLS1PRF;
|
||||||
rec += 2;
|
rec += 2;
|
||||||
|
|
||||||
// Server random
|
// Server random
|
||||||
if (rec + sizeof(m_state.m_random_server) > rec_end)
|
if (rec + sizeof(m_state.m_random_server) > rec_end)
|
||||||
throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, __FUNCTION__ " Server random missing or incomplete.");
|
throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, __FUNCTION__ " Server random missing or incomplete.");
|
||||||
memcpy(&m_state.m_random_server, rec, sizeof(random));
|
memcpy(&m_state.m_random_server, rec, sizeof(tls_random));
|
||||||
rec += sizeof(random);
|
rec += sizeof(tls_random);
|
||||||
|
|
||||||
// Session ID
|
// Session ID
|
||||||
if (rec + 1 > rec_end || rec + 1 + rec[0] > rec_end)
|
if (rec + 1 > rec_end || rec + 1 + rec[0] > rec_end)
|
||||||
@ -1120,13 +1001,20 @@ void eap::method_tls::process_handshake(_In_bytecount_(msg_size) const void *_ms
|
|||||||
// Cipher
|
// Cipher
|
||||||
if (rec + 2 > rec_end)
|
if (rec + 2 > rec_end)
|
||||||
throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, __FUNCTION__ " Cipher or incomplete.");
|
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] == 0x0a) {
|
||||||
throw win_runtime_error(ERROR_NOT_SUPPORTED, string_printf(__FUNCTION__ " Other than requested cipher selected (expected 0x000a, received 0x%02x%02x).", rec[0], rec[1]));
|
// TLS_RSA_WITH_3DES_EDE_CBC_SHA
|
||||||
|
m_state.m_alg_encrypt = CALG_3DES;
|
||||||
|
m_state.m_size_enc_key = 192/8; // 3DES 192bits
|
||||||
|
m_state.m_size_enc_iv = 64/8; // 3DES 64bits
|
||||||
|
m_state.m_alg_mac = CALG_SHA1;
|
||||||
|
m_state.m_size_mac_key = 160/8; // SHA-1
|
||||||
|
} else
|
||||||
|
throw win_runtime_error(ERROR_NOT_SUPPORTED, string_printf(__FUNCTION__ " Other than requested cipher selected (received 0x%02x%02x).", rec[0], rec[1]));
|
||||||
|
|
||||||
m_module.log_event(&EAPMETHOD_TLS_SERVER_HELLO, event_data((unsigned int)eap_type_tls), event_data((unsigned int)m_session_id.size()), event_data(m_session_id.data(), (ULONG)m_session_id.size()), event_data::blank);
|
m_module.log_event(&EAPMETHOD_TLS_SERVER_HELLO, event_data((unsigned int)eap_type_tls), event_data((unsigned int)m_session_id.size()), event_data(m_session_id.data(), (ULONG)m_session_id.size()), event_data::blank);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case handshake_type_certificate: {
|
case tls_handshake_type_certificate: {
|
||||||
// Certificate list size
|
// Certificate list size
|
||||||
if (rec + 3 > rec_end)
|
if (rec + 3 > rec_end)
|
||||||
throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, __FUNCTION__ " Certificate list size missing or incomplete.");
|
throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, __FUNCTION__ " Certificate list size missing or incomplete.");
|
||||||
@ -1161,33 +1049,35 @@ void eap::method_tls::process_handshake(_In_bytecount_(msg_size) const void *_ms
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case handshake_type_certificate_request:
|
case tls_handshake_type_certificate_request:
|
||||||
m_send_client_cert = true;
|
m_send_client_cert = true;
|
||||||
m_module.log_event(&EAPMETHOD_TLS_CERTIFICATE_REQUEST, event_data((unsigned int)eap_type_tls), event_data::blank);
|
m_module.log_event(&EAPMETHOD_TLS_CERTIFICATE_REQUEST, event_data((unsigned int)eap_type_tls), event_data::blank);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case handshake_type_server_hello_done:
|
case tls_handshake_type_server_hello_done:
|
||||||
m_server_hello_done = true;
|
m_server_hello_done = true;
|
||||||
m_module.log_event(&EAPMETHOD_TLS_SERVER_HELLO_DONE, event_data((unsigned int)eap_type_tls), event_data::blank);
|
m_module.log_event(&EAPMETHOD_TLS_SERVER_HELLO_DONE, event_data((unsigned int)eap_type_tls), event_data::blank);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case handshake_type_finished: {
|
case tls_handshake_type_finished: {
|
||||||
// According to https://tools.ietf.org/html/rfc5246#section-7.4.9 all verify_data is 12B.
|
// According to https://tools.ietf.org/html/rfc5246#section-7.4.9 all verify_data is 12B.
|
||||||
if (rec_end - rec != 12)
|
if (rec_end - rec != 12)
|
||||||
throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, string_printf(__FUNCTION__ " Finished record size incorrect (expected 12B, received %uB).", rec_end - rec));
|
throw win_runtime_error(EAP_E_EAPHOST_METHOD_INVALID_PACKET, string_printf(__FUNCTION__ " Finished record size incorrect (expected 12B, received %uB).", rec_end - rec));
|
||||||
|
|
||||||
// Create label + hash MD5 + hash SHA-1 seed.
|
// Create label + hash MD5 + hash SHA-1 seed.
|
||||||
sanitizing_blob lblseed, hash;
|
crypt_hash hash;
|
||||||
const unsigned char s_label[] = "server finished";
|
static const unsigned char s_label[] = "server finished";
|
||||||
lblseed.assign(s_label, s_label + _countof(s_label) - 1);
|
sanitizing_blob seed(s_label, s_label + _countof(s_label) - 1), hash_data;
|
||||||
if (!CryptGetHashParam(m_hash_handshake_msgs_md5, HP_HASHVAL, hash, 0))
|
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.");
|
throw win_runtime_error(__FUNCTION__ " Error finishing MD5 hash calculation.");
|
||||||
lblseed.insert(lblseed.end(), hash.begin(), hash.end());
|
seed.insert(seed.end(), hash_data.begin(), hash_data.end());
|
||||||
if (!CryptGetHashParam(m_hash_handshake_msgs_sha1, HP_HASHVAL, hash, 0))
|
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.");
|
throw win_runtime_error(__FUNCTION__ " Error finishing SHA-1 hash calculation.");
|
||||||
lblseed.insert(lblseed.end(), hash.begin(), hash.end());
|
seed.insert(seed.end(), hash_data.begin(), hash_data.end());
|
||||||
|
|
||||||
if (memcmp(prf(&m_state.m_master_secret, sizeof(master_secret), lblseed.data(), lblseed.size(), 12).data(), rec, 12))
|
if (memcmp(prf(&m_state.m_master_secret, sizeof(tls_master_secret), seed.data(), seed.size(), 12).data(), rec, 12))
|
||||||
throw win_runtime_error(ERROR_ENCRYPTION_FAILED, __FUNCTION__ " Integrity check failed.");
|
throw win_runtime_error(ERROR_ENCRYPTION_FAILED, __FUNCTION__ " Integrity check failed.");
|
||||||
|
|
||||||
m_server_finished = true;
|
m_server_finished = true;
|
||||||
@ -1211,10 +1101,10 @@ void eap::method_tls::process_application_data(_In_bytecount_(msg_size) const vo
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void eap::method_tls::verify_server_trust()
|
void eap::method_tls::verify_server_trust() const
|
||||||
{
|
{
|
||||||
assert(!m_server_cert_chain.empty());
|
assert(!m_server_cert_chain.empty());
|
||||||
cert_context &cert = m_server_cert_chain.front();
|
const cert_context &cert = m_server_cert_chain.front();
|
||||||
|
|
||||||
if (!m_cfg.m_server_names.empty()) {
|
if (!m_cfg.m_server_names.empty()) {
|
||||||
// Check server name.
|
// Check server name.
|
||||||
@ -1357,17 +1247,24 @@ void eap::method_tls::encrypt_message(_Inout_ sanitizing_blob &msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void eap::method_tls::decrypt_message(_Inout_ sanitizing_blob &msg)
|
void eap::method_tls::decrypt_message(_Inout_ sanitizing_blob &msg) const
|
||||||
{
|
{
|
||||||
// Decrypt.
|
// Decrypt.
|
||||||
DWORD size = (DWORD)msg.size();
|
if (!CryptDecrypt(m_key_server, NULL, FALSE, 0, msg))
|
||||||
if (!CryptDecrypt(m_key_server, NULL, FALSE, 0, msg.data(), &size))
|
|
||||||
throw win_runtime_error(__FUNCTION__ " Error decrypting message.");
|
throw win_runtime_error(__FUNCTION__ " Error decrypting message.");
|
||||||
|
|
||||||
// TODO: Check padding!
|
size_t size = msg.size();
|
||||||
|
if (size) {
|
||||||
|
// Check padding.
|
||||||
|
unsigned char padding = msg.back();
|
||||||
|
size_t size_data = size - 1 - padding;
|
||||||
|
for (size_t i = size_data, i_end = size - 1; i < i_end; i++)
|
||||||
|
if (msg[i] != padding)
|
||||||
|
throw invalid_argument(__FUNCTION__ " Incorrect message padding.");
|
||||||
|
|
||||||
// Remove padding.
|
// Remove padding.
|
||||||
msg.resize(size - msg.back() - 1);
|
msg.resize(size_data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1376,12 +1273,11 @@ eap::sanitizing_blob eap::method_tls::prf(
|
|||||||
_In_ size_t size_secret,
|
_In_ size_t size_secret,
|
||||||
_In_bytecount_(size_seed) const void *seed,
|
_In_bytecount_(size_seed) const void *seed,
|
||||||
_In_ size_t size_seed,
|
_In_ size_t size_seed,
|
||||||
_In_ size_t size)
|
_In_ size_t size) const
|
||||||
{
|
{
|
||||||
sanitizing_blob data;
|
sanitizing_blob data;
|
||||||
data.reserve(size);
|
data.reserve(size);
|
||||||
|
|
||||||
#pragma warning(suppress: 4127) // Prepared for future expansion to TLS 1.2, where m_alg_prf will no longer be static const.
|
|
||||||
if (m_state.m_alg_prf == CALG_TLS1PRF) {
|
if (m_state.m_alg_prf == CALG_TLS1PRF) {
|
||||||
// Split secret in two halves.
|
// Split secret in two halves.
|
||||||
size_t
|
size_t
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "../include/Config.h"
|
#include "../include/Config.h"
|
||||||
#include "../include/Credentials.h"
|
#include "../include/Credentials.h"
|
||||||
#include "../include/Method.h"
|
#include "../include/Method.h"
|
||||||
|
#include "../include/TLS.h"
|
||||||
|
|
||||||
#include "../../EAPBase/include/EAPXML.h"
|
#include "../../EAPBase/include/EAPXML.h"
|
||||||
|
|
||||||
|
238
lib/TLS/src/TLS.cpp
Normal file
238
lib/TLS/src/TLS.cpp
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2015-2016 Amebis
|
||||||
|
Copyright 2016 GÉANT
|
||||||
|
|
||||||
|
This file is part of GÉANTLink.
|
||||||
|
|
||||||
|
GÉANTLink is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
GÉANTLink is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace winstd;
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// eap::tls_random
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
eap::tls_random::tls_random()
|
||||||
|
{
|
||||||
|
memset(data, 0, sizeof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eap::tls_random::tls_random(_In_ const tls_random &other)
|
||||||
|
{
|
||||||
|
memcpy(data, other.data, sizeof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eap::tls_random::~tls_random()
|
||||||
|
{
|
||||||
|
SecureZeroMemory(data, sizeof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eap::tls_random& eap::tls_random::operator=(_In_ const tls_random &other)
|
||||||
|
{
|
||||||
|
if (this != std::addressof(other))
|
||||||
|
memcpy(data, other.data, sizeof(data));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void eap::tls_random::clear()
|
||||||
|
{
|
||||||
|
memset(data, 0, sizeof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void eap::tls_random::reset(_In_ HCRYPTPROV cp)
|
||||||
|
{
|
||||||
|
_time32((__time32_t*)&time);
|
||||||
|
if (!CryptGenRandom(cp, sizeof(data) - sizeof(__time32_t), data + sizeof(__time32_t)))
|
||||||
|
throw win_runtime_error(__FUNCTION__ " Error creating randomness.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// eap::tls_master_secret
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
eap::tls_master_secret::tls_master_secret()
|
||||||
|
{
|
||||||
|
memset(data, 0, sizeof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eap::tls_master_secret::tls_master_secret(_In_ HCRYPTPROV cp)
|
||||||
|
{
|
||||||
|
data[0] = 3;
|
||||||
|
data[1] = 1;
|
||||||
|
|
||||||
|
if (!CryptGenRandom(cp, sizeof(data) - 2, data + 2))
|
||||||
|
throw win_runtime_error(__FUNCTION__ " Error creating PMS randomness.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eap::tls_master_secret::tls_master_secret(_In_ const tls_master_secret &other)
|
||||||
|
{
|
||||||
|
memcpy(data, other.data, sizeof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eap::tls_master_secret::~tls_master_secret()
|
||||||
|
{
|
||||||
|
SecureZeroMemory(data, sizeof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eap::tls_master_secret& eap::tls_master_secret::operator=(_In_ const tls_master_secret &other)
|
||||||
|
{
|
||||||
|
if (this != std::addressof(other))
|
||||||
|
memcpy(data, other.data, sizeof(data));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void eap::tls_master_secret::clear()
|
||||||
|
{
|
||||||
|
memset(data, 0, sizeof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// eap::tls_conn_state
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
eap::tls_conn_state::tls_conn_state()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eap::tls_conn_state::tls_conn_state(_In_ const tls_conn_state &other) :
|
||||||
|
m_master_secret(other.m_master_secret),
|
||||||
|
m_random_client(other.m_random_client),
|
||||||
|
m_random_server(other.m_random_server)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eap::tls_conn_state::tls_conn_state(_Inout_ tls_conn_state &&other) :
|
||||||
|
m_master_secret(std::move(other.m_master_secret)),
|
||||||
|
m_random_client(std::move(other.m_random_client)),
|
||||||
|
m_random_server(std::move(other.m_random_server))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eap::tls_conn_state& eap::tls_conn_state::operator=(_In_ const tls_conn_state &other)
|
||||||
|
{
|
||||||
|
if (this != std::addressof(other)) {
|
||||||
|
m_master_secret = other.m_master_secret;
|
||||||
|
m_random_client = other.m_random_client;
|
||||||
|
m_random_server = other.m_random_server;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eap::tls_conn_state& eap::tls_conn_state::operator=(_Inout_ tls_conn_state &&other)
|
||||||
|
{
|
||||||
|
if (this != std::addressof(other)) {
|
||||||
|
m_master_secret = std::move(other.m_master_secret);
|
||||||
|
m_random_client = std::move(other.m_random_client);
|
||||||
|
m_random_server = std::move(other.m_random_server);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// eap::hash_hmac
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
eap::hash_hmac::hash_hmac(
|
||||||
|
_In_ HCRYPTPROV cp,
|
||||||
|
_In_ ALG_ID alg,
|
||||||
|
_In_bytecount_(size_secret ) const void *secret,
|
||||||
|
_In_ size_t size_secret)
|
||||||
|
{
|
||||||
|
// Prepare padding.
|
||||||
|
sanitizing_blob padding(sizeof(padding_t));
|
||||||
|
inner_padding(cp, alg, secret, size_secret, padding.data());
|
||||||
|
|
||||||
|
// Continue with the other constructor.
|
||||||
|
this->hash_hmac::hash_hmac(cp, alg, padding.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eap::hash_hmac::hash_hmac(
|
||||||
|
_In_ HCRYPTPROV cp,
|
||||||
|
_In_ ALG_ID alg,
|
||||||
|
_In_ const padding_t padding)
|
||||||
|
{
|
||||||
|
// Create inner hash.
|
||||||
|
if (!m_hash_inner.create(cp, alg))
|
||||||
|
throw win_runtime_error(__FUNCTION__ " Error creating inner hash.");
|
||||||
|
|
||||||
|
// Initialize it with the inner padding.
|
||||||
|
if (!CryptHashData(m_hash_inner, padding, sizeof(padding_t), 0))
|
||||||
|
throw win_runtime_error(__FUNCTION__ " Error hashing secret XOR inner padding.");
|
||||||
|
|
||||||
|
// Convert inner padding to outer padding for final calculation.
|
||||||
|
padding_t padding_out;
|
||||||
|
for (size_t i = 0; i < sizeof(padding_t); i++)
|
||||||
|
padding_out[i] = padding[i] ^ (0x36 ^ 0x5c);
|
||||||
|
|
||||||
|
// Create outer hash.
|
||||||
|
if (!m_hash_outer.create(cp, alg))
|
||||||
|
throw win_runtime_error(__FUNCTION__ " Error creating outer hash.");
|
||||||
|
|
||||||
|
// Initialize it with the outer padding.
|
||||||
|
if (!CryptHashData(m_hash_outer, padding_out, sizeof(padding_t), 0))
|
||||||
|
throw win_runtime_error(__FUNCTION__ " Error hashing secret XOR inner padding.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void eap::hash_hmac::inner_padding(
|
||||||
|
_In_ HCRYPTPROV cp,
|
||||||
|
_In_ ALG_ID alg,
|
||||||
|
_In_bytecount_(size_secret ) const void *secret,
|
||||||
|
_In_ size_t size_secret,
|
||||||
|
_Out_ padding_t padding)
|
||||||
|
{
|
||||||
|
if (size_secret > sizeof(padding_t)) {
|
||||||
|
// If the secret is longer than padding, use secret's hash instead.
|
||||||
|
crypt_hash hash;
|
||||||
|
if (!hash.create(cp, alg))
|
||||||
|
throw win_runtime_error(__FUNCTION__ " Error creating hash.");
|
||||||
|
if (!CryptHashData(hash, (const BYTE*)secret, (DWORD)size_secret, 0))
|
||||||
|
throw win_runtime_error(__FUNCTION__ " Error hashing.");
|
||||||
|
DWORD size_hash = sizeof(padding_t);
|
||||||
|
if (!CryptGetHashParam(hash, HP_HASHVAL, padding, &size_hash, 0))
|
||||||
|
throw win_runtime_error(__FUNCTION__ " Error finishing hash.");
|
||||||
|
size_secret = size_hash;
|
||||||
|
} else
|
||||||
|
memcpy(padding, secret, size_secret);
|
||||||
|
for (size_t i = 0; i < size_secret; i++)
|
||||||
|
padding[i] ^= 0x36;
|
||||||
|
memset(padding + size_secret, 0x36, sizeof(padding_t) - size_secret);
|
||||||
|
}
|
@ -1 +1 @@
|
|||||||
Subproject commit dc2711590306e1c056e49a12f8b8a7c40ee337ea
|
Subproject commit 84e544c2f6dbf14f76b930b2672c3cc2b77bfc3f
|
Loading…
x
Reference in New Issue
Block a user