Error checking and size asserts added
This commit is contained in:
parent
a0efb6742d
commit
e649a86b1f
@ -25,6 +25,8 @@
|
|||||||
#define EAP_ENCRYPT_BLOBS 1
|
#define EAP_ENCRYPT_BLOBS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define _HOST_LOW_ENDIAN
|
||||||
|
|
||||||
#if !defined(RC_INVOKED) && !defined(MIDL_PASS)
|
#if !defined(RC_INVOKED) && !defined(MIDL_PASS)
|
||||||
|
|
||||||
#include <WinStd/Common.h>
|
#include <WinStd/Common.h>
|
||||||
|
@ -191,23 +191,31 @@ namespace eap
|
|||||||
///
|
///
|
||||||
/// Makes a TLS handshake
|
/// Makes a TLS handshake
|
||||||
///
|
///
|
||||||
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter 7.4. Handshake Protocol](https://tools.ietf.org/html/rfc5246#section-7.4)
|
/// \sa [The Transport Layer Security (TLS) Protocol Version 1.2 (Chapter A.1. Record Layer](https://tools.ietf.org/html/rfc5246#appendix-A.1)
|
||||||
///
|
///
|
||||||
/// \param[in] msg Handshake data contents
|
/// \param[in] msg Handshake data contents
|
||||||
/// \param[in] encrypt Should make an encrypted handshake message?
|
/// \param[in] encrypt Should make an encrypted handshake message?
|
||||||
|
/// \param[out] msg_h TLS handshake message
|
||||||
|
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
|
||||||
///
|
///
|
||||||
/// \returns TLS handshake message
|
/// \returns
|
||||||
|
/// - \c true if succeeded
|
||||||
|
/// - \c false otherwise. See \p ppEapError for details.
|
||||||
///
|
///
|
||||||
sanitizing_blob make_handshake(_In_ const sanitizing_blob &msg, _In_ bool encrypt);
|
bool make_handshake(_In_ const sanitizing_blob &msg, _In_ bool encrypt, _Out_ eap::sanitizing_blob &msg_h, _Out_ EAP_ERROR **ppEapError);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Encrypt block of data
|
/// Encrypt block of data
|
||||||
///
|
///
|
||||||
/// \param[in] msg TLS message to encrypt
|
/// \param[in] msg TLS message to encrypt
|
||||||
|
/// \param[out] msg_enc Encrypted \p msg
|
||||||
|
/// \param[out] ppEapError Pointer to error descriptor in case of failure. Free using `module::free_error_memory()`.
|
||||||
///
|
///
|
||||||
/// \returns Encrypted message
|
/// \returns
|
||||||
|
/// - \c true if succeeded
|
||||||
|
/// - \c false otherwise. See \p ppEapError for details.
|
||||||
///
|
///
|
||||||
std::vector<unsigned char> encrypt_message(_In_ const sanitizing_blob &msg);
|
bool encrypt_message(_In_ const sanitizing_blob &msg, _Out_ std::vector<unsigned char> &msg_enc, _Out_ EAP_ERROR **ppEapError);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum phase_t {
|
enum phase_t {
|
||||||
|
@ -296,7 +296,8 @@ bool eap::method_tls::process_request_packet(
|
|||||||
m_packet_res.m_id = m_packet_req.m_id;
|
m_packet_res.m_id = m_packet_req.m_id;
|
||||||
m_packet_res.m_flags = 0;
|
m_packet_res.m_flags = 0;
|
||||||
sanitizing_blob hello(make_client_hello());
|
sanitizing_blob hello(make_client_hello());
|
||||||
sanitizing_blob handshake(make_handshake(hello, false));
|
sanitizing_blob handshake;
|
||||||
|
if (!make_handshake(hello, false, handshake, ppEapError)) return false;
|
||||||
m_packet_res.m_data.assign(handshake.begin(), handshake.end());
|
m_packet_res.m_data.assign(handshake.begin(), handshake.end());
|
||||||
pEapOutput->fAllowNotifications = FALSE;
|
pEapOutput->fAllowNotifications = FALSE;
|
||||||
pEapOutput->action = EapPeerMethodResponseActionSend;
|
pEapOutput->action = EapPeerMethodResponseActionSend;
|
||||||
@ -309,6 +310,8 @@ bool eap::method_tls::process_request_packet(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case phase_server_hello:
|
||||||
|
|
||||||
default:
|
default:
|
||||||
*ppEapError = m_module.make_error(ERROR_NOT_SUPPORTED, _T(__FUNCTION__) _T(" Not supported."));
|
*ppEapError = m_module.make_error(ERROR_NOT_SUPPORTED, _T(__FUNCTION__) _T(" Not supported."));
|
||||||
return false;
|
return false;
|
||||||
@ -375,27 +378,28 @@ bool eap::method_tls::get_response_packet(
|
|||||||
|
|
||||||
eap::sanitizing_blob eap::method_tls::make_client_hello() const
|
eap::sanitizing_blob eap::method_tls::make_client_hello() const
|
||||||
{
|
{
|
||||||
unsigned long 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(tls_random_t) + // Client random
|
sizeof(tls_random_t) + // Client random
|
||||||
1 + // Session ID size
|
1 + // Session ID size
|
||||||
(unsigned long)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
|
||||||
unsigned long ssl_header = htonl(0x01000000 | size_data); // client_hello (0x01)
|
assert(size_data <= 0xffffff);
|
||||||
|
unsigned long ssl_header = htonl(0x01000000 | (unsigned long)size_data); // client_hello (0x01)
|
||||||
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
|
// SSL version
|
||||||
msg.push_back(0x03); // SSL major version
|
msg.push_back(3); // SSL major version
|
||||||
msg.push_back(0x01); // SSL minor version
|
msg.push_back(3); // SSL minor version
|
||||||
|
|
||||||
// Client random
|
// Client random
|
||||||
unsigned long time = htonl(m_random_client.time);
|
unsigned long time = htonl(m_random_client.time);
|
||||||
@ -403,6 +407,7 @@ eap::sanitizing_blob eap::method_tls::make_client_hello() const
|
|||||||
msg.insert(msg.end(), m_random_client.data, m_random_client.data + _countof(m_random_client.data)); // TODO: Check if byte order should be changed!
|
msg.insert(msg.end(), m_random_client.data, m_random_client.data + _countof(m_random_client.data)); // TODO: Check if byte order should be changed!
|
||||||
|
|
||||||
// Session ID
|
// Session ID
|
||||||
|
assert(m_session_id.size() <= 32);
|
||||||
msg.push_back((unsigned char)m_session_id.size());
|
msg.push_back((unsigned char)m_session_id.size());
|
||||||
msg.insert(msg.end(), m_session_id.begin(), m_session_id.end());
|
msg.insert(msg.end(), m_session_id.begin(), m_session_id.end());
|
||||||
|
|
||||||
@ -420,24 +425,29 @@ eap::sanitizing_blob eap::method_tls::make_client_hello() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
eap::sanitizing_blob eap::method_tls::make_handshake(_In_ const sanitizing_blob &msg, _In_ bool encrypt)
|
bool eap::method_tls::make_handshake(_In_ const sanitizing_blob &msg, _In_ bool encrypt, _Out_ eap::sanitizing_blob &msg_h, _Out_ EAP_ERROR **ppEapError)
|
||||||
{
|
{
|
||||||
const unsigned char *msg_ptr;
|
const unsigned char *msg_ptr;
|
||||||
unsigned short size_msg;
|
size_t size_msg;
|
||||||
vector<unsigned char> msg_enc;
|
vector<unsigned char> msg_enc;
|
||||||
|
|
||||||
if (encrypt) {
|
if (encrypt) {
|
||||||
// Create an unencrypted handshake first.
|
// Create an unencrypted handshake first.
|
||||||
msg_enc = encrypt_message(make_handshake(msg, false));
|
eap::sanitizing_blob msg_h_unenc;
|
||||||
size_msg = (unsigned short)msg_enc.size();
|
if (!make_handshake(msg, false, msg_h_unenc, ppEapError)) return false;
|
||||||
|
|
||||||
|
// Encrypt it.
|
||||||
|
if (!encrypt_message(msg_h_unenc, msg_enc, ppEapError)) return false;
|
||||||
|
|
||||||
|
size_msg = msg_enc.size();
|
||||||
msg_ptr = msg_enc.data();
|
msg_ptr = msg_enc.data();
|
||||||
} else {
|
} else {
|
||||||
size_msg = (unsigned short)msg.size();
|
size_msg = msg.size();
|
||||||
msg_ptr = msg.data();
|
msg_ptr = msg.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a handshake.
|
// Create a handshake.
|
||||||
sanitizing_blob msg_h;
|
msg_h.clear();
|
||||||
msg_h.reserve(
|
msg_h.reserve(
|
||||||
1 + // SSL record type
|
1 + // SSL record type
|
||||||
2 + // SSL version
|
2 + // SSL version
|
||||||
@ -445,44 +455,62 @@ 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(0x16); // handshake (0x16)
|
msg_h.push_back(22); // handshake (22)
|
||||||
|
|
||||||
// SSL version
|
// SSL version
|
||||||
msg_h.push_back(0x03); // SSL major version
|
msg_h.push_back(3); // SSL major version
|
||||||
msg_h.push_back(0x01); // SSL minor version
|
msg_h.push_back(3); // SSL minor version
|
||||||
|
|
||||||
// Message
|
// Message
|
||||||
unsigned short size_msg_n = htons(size_msg);
|
assert(size_msg <= 0xffff);
|
||||||
|
unsigned short size_msg_n = htons((unsigned short)size_msg);
|
||||||
msg_h.insert(msg_h.end(), (unsigned char*)&size_msg_n, (unsigned char*)(&size_msg_n + 1));
|
msg_h.insert(msg_h.end(), (unsigned char*)&size_msg_n, (unsigned char*)(&size_msg_n + 1));
|
||||||
msg_h.insert(msg_h.end(), msg_ptr, msg_ptr + size_msg);
|
msg_h.insert(msg_h.end(), msg_ptr, msg_ptr + size_msg);
|
||||||
|
|
||||||
return msg_h;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<unsigned char> eap::method_tls::encrypt_message(_In_ const sanitizing_blob &msg)
|
bool eap::method_tls::encrypt_message(_In_ const sanitizing_blob &msg, _Out_ std::vector<unsigned char> &msg_enc, _Out_ EAP_ERROR **ppEapError)
|
||||||
{
|
{
|
||||||
|
assert(ppEapError);
|
||||||
|
|
||||||
// Create a HMAC hash.
|
// Create a HMAC hash.
|
||||||
crypt_hash hash_hmac;
|
crypt_hash hash_hmac;
|
||||||
hash_hmac.create(m_cp, CALG_HMAC, m_key_hmac, 0);
|
if (!hash_hmac.create(m_cp, CALG_HMAC, m_key_hmac, 0)) {
|
||||||
|
*ppEapError = m_module.make_error(GetLastError(), _T(__FUNCTION__) _T(" Error creating HMAC hash."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
static const HMAC_INFO s_hmac_info = { CALG_SHA1 };
|
static const HMAC_INFO s_hmac_info = { CALG_SHA1 };
|
||||||
CryptSetHashParam(hash_hmac, HP_HMAC_INFO, (const BYTE*)&s_hmac_info, 0);
|
if (!CryptSetHashParam(hash_hmac, HP_HMAC_INFO, (const BYTE*)&s_hmac_info, 0)) {
|
||||||
|
*ppEapError = m_module.make_error(GetLastError(), _T(__FUNCTION__) _T(" Error setting hash parameter."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Hash sequence number.
|
// Hash sequence number.
|
||||||
unsigned __int64 seq_num = htonll(m_seq_num);
|
unsigned __int64 seq_num = htonll(m_seq_num);
|
||||||
CryptHashData(hash_hmac, (const BYTE*)&seq_num, sizeof(seq_num), 0);
|
if (!CryptHashData(hash_hmac, (const BYTE*)&seq_num, sizeof(seq_num), 0)) {
|
||||||
|
*ppEapError = m_module.make_error(GetLastError(), _T(__FUNCTION__) _T(" Error hashing data."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Hash data.
|
// Hash message.
|
||||||
CryptHashData(hash_hmac, msg.data(), (DWORD)msg.size(), 0);
|
if (!CryptHashData(hash_hmac, msg.data(), (DWORD)msg.size(), 0)) {
|
||||||
|
*ppEapError = m_module.make_error(GetLastError(), _T(__FUNCTION__) _T(" Error hashing data."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate hash.
|
// Calculate hash.
|
||||||
vector<unsigned char> hmac;
|
vector<unsigned char> hmac;
|
||||||
CryptGetHashParam(hash_hmac, HP_HASHVAL, hmac, 0);
|
if (!CryptGetHashParam(hash_hmac, HP_HASHVAL, hmac, 0)) {
|
||||||
|
*ppEapError = m_module.make_error(GetLastError(), _T(__FUNCTION__) _T(" Error finishing hash calculation."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long size =
|
size_t size =
|
||||||
(unsigned long)msg.size() - 5 + // TLS message without SSL header (SSL record type, SSL version, Message size)
|
msg.size() - 5 + // TLS message without SSL header (SSL record type, SSL version, Message size)
|
||||||
20 + // SHA-1
|
20 + // SHA-1
|
||||||
1; // Padding length
|
1; // Padding length
|
||||||
unsigned char padding = (8 - size) % 8;
|
unsigned char padding = (8 - size) % 8;
|
||||||
size += padding;
|
size += padding;
|
||||||
|
|
||||||
@ -491,19 +519,27 @@ std::vector<unsigned char> eap::method_tls::encrypt_message(_In_ const sanitizin
|
|||||||
enc.reserve(size);
|
enc.reserve(size);
|
||||||
enc.assign(msg.begin() + 5, msg.end());
|
enc.assign(msg.begin() + 5, msg.end());
|
||||||
|
|
||||||
// Append HMAC hash (in reversed byte order).
|
// Append HMAC hash.
|
||||||
|
#ifdef _HOST_LOW_ENDIAN
|
||||||
std::reverse(hmac.begin(), hmac.end());
|
std::reverse(hmac.begin(), hmac.end());
|
||||||
|
#endif
|
||||||
enc.insert(enc.end(), hmac.begin(), hmac.end());
|
enc.insert(enc.end(), hmac.begin(), hmac.end());
|
||||||
|
|
||||||
// Append padding.
|
// Append padding.
|
||||||
enc.insert(enc.end(), padding + 1, padding);
|
enc.insert(enc.end(), padding + 1, padding);
|
||||||
DWORD size2 = size;
|
|
||||||
CryptEncrypt(m_key_write, NULL, FALSE, 0, enc.data(), &size2, size);
|
// Encrypt.
|
||||||
|
assert(size < 0xffffffff);
|
||||||
|
DWORD size2 = (DWORD)size;
|
||||||
|
if (!CryptEncrypt(m_key_write, NULL, FALSE, 0, enc.data(), &size2, (DWORD)size)) {
|
||||||
|
*ppEapError = m_module.make_error(GetLastError(), _T(__FUNCTION__) _T(" Error encrypting message."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Increment sequence number.
|
// Increment sequence number.
|
||||||
m_seq_num++;
|
m_seq_num++;
|
||||||
|
|
||||||
// Move to regular vector, now the data is encrypted.
|
// Copy to output.
|
||||||
std::vector<unsigned char> enc2(std::move((std::vector<unsigned char>&)enc));
|
msg_enc.assign(enc.begin(), enc.end());
|
||||||
return enc2;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user