TLS work continues...
This commit is contained in:
@@ -18,13 +18,13 @@
|
||||
along with GÉANTLink. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <sal.h>
|
||||
|
||||
#include <WinStd/Common.h>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <WinCrypt.h> // Must include after <Windows.h>
|
||||
|
||||
#include <sal.h>
|
||||
|
||||
namespace eap
|
||||
{
|
||||
///
|
||||
@@ -41,6 +41,8 @@ namespace eap
|
||||
#pragma once
|
||||
|
||||
#include "Credentials.h"
|
||||
#include "Method.h"
|
||||
#include "TLS.h"
|
||||
|
||||
#include "../../EAPBase/include/Config.h"
|
||||
|
||||
@@ -166,5 +168,9 @@ namespace eap
|
||||
public:
|
||||
std::list<winstd::cert_context> m_trusted_root_ca; ///< Trusted root CAs
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../include/Config.h"
|
||||
#include "../include/Credentials.h"
|
||||
#include "Config.h"
|
||||
#include "Credentials.h"
|
||||
#include "TLS.h"
|
||||
|
||||
#include "../../EAPBase/include/Method.h"
|
||||
|
||||
@@ -65,79 +67,6 @@ namespace eap
|
||||
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)
|
||||
///
|
||||
@@ -193,56 +122,6 @@ namespace eap
|
||||
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(1)
|
||||
///
|
||||
@@ -260,208 +139,6 @@ namespace eap
|
||||
};
|
||||
#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:
|
||||
///
|
||||
/// Constructs an EAP method
|
||||
@@ -486,6 +163,11 @@ namespace eap
|
||||
///
|
||||
method_tls(_Inout_ method_tls &&other);
|
||||
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
virtual ~method_tls();
|
||||
|
||||
///
|
||||
/// Copies an EAP method
|
||||
///
|
||||
@@ -594,7 +276,7 @@ namespace eap
|
||||
///
|
||||
/// \returns Change cipher spec
|
||||
///
|
||||
eap::sanitizing_blob make_finished();
|
||||
eap::sanitizing_blob make_finished() const;
|
||||
|
||||
///
|
||||
/// Makes a TLS handshake
|
||||
@@ -633,6 +315,11 @@ namespace eap
|
||||
///
|
||||
void derive_keys();
|
||||
|
||||
///
|
||||
/// Generates master session key
|
||||
///
|
||||
void derive_msk();
|
||||
|
||||
///
|
||||
/// Processes messages in a TLS packet
|
||||
///
|
||||
@@ -684,7 +371,7 @@ namespace eap
|
||||
///
|
||||
/// Verifies server's certificate if trusted by configuration
|
||||
///
|
||||
void verify_server_trust();
|
||||
void verify_server_trust() const;
|
||||
|
||||
///
|
||||
/// Encrypt TLS message
|
||||
@@ -698,18 +385,18 @@ namespace eap
|
||||
///
|
||||
/// \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
|
||||
///
|
||||
/// \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] size_secret \p secret size
|
||||
/// \param[in] lblseed Concatenated label and seed
|
||||
/// \param[in] size_lblseed \p lblseed size
|
||||
/// \param[in] size Number of bytes of pseudo-random data required
|
||||
/// \param[in] secret Hashing secret key
|
||||
/// \param[in] size_secret \p secret size
|
||||
/// \param[in] seed Random seed
|
||||
/// \param[in] size_seed \p seed size
|
||||
/// \param[in] size Number of bytes of pseudo-random data required
|
||||
///
|
||||
/// \returns Generated pseudo-random data (\p size bytes)
|
||||
///
|
||||
@@ -718,7 +405,7 @@ namespace eap
|
||||
_In_ size_t size_secret,
|
||||
_In_bytecount_(size_seed) const void *seed,
|
||||
_In_ size_t size_seed,
|
||||
_In_ size_t size);
|
||||
_In_ size_t size) const;
|
||||
|
||||
///
|
||||
/// Creates a key
|
||||
@@ -778,13 +465,16 @@ namespace eap
|
||||
|
||||
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_server; ///< Padding (key) for server side HMAC calculation
|
||||
winstd::crypt_key m_key_client; ///< Key for encrypting 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
|
||||
|
||||
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?
|
||||
|
||||
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;
|
||||
}
|
Reference in New Issue
Block a user