Merge pull request #3904 from bjcollins/master

FIPS Mode support for xfreerdp
This commit is contained in:
akallabeth 2017-11-17 13:31:43 +01:00 committed by GitHub
commit b156b937fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 263 additions and 46 deletions

View File

@ -91,6 +91,7 @@ static COMMAND_LINE_ARGUMENT_A args[] =
{ "encryption-methods", COMMAND_LINE_VALUE_REQUIRED, "[40,][56,][128,][FIPS]", NULL, NULL, -1, NULL, "RDP standard security encryption methods" },
{ "f", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Fullscreen mode" },
{ "fast-path", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Enable fast-path input/output" },
{ "fipsmode", COMMAND_LINE_VALUE_BOOL, NULL, NULL, NULL, -1, NULL, "Enable FIPS mode" },
{ "fonts", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Enable smooth fonts (ClearType)" },
{ "frame-ack", COMMAND_LINE_VALUE_REQUIRED, "<number>", NULL, NULL, -1, NULL, "Number of frame acknowledgement" },
{ "from-stdin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Read credentials from stdin, do not use defaults." },
@ -2767,6 +2768,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
if (!(settings->ActionScript = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
CommandLineSwitchCase(arg, "fipsmode")
{
settings->FIPSMode = TRUE;
}
CommandLineSwitchDefault(arg)
{
}
@ -2822,6 +2827,17 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
settings->ColorDepth = 32;
}
/* FIPS Mode forces the following and overrides the following(by happening later */
/* in the command line processing): */
/* 1. Disables NLA Security since NLA in freerdp uses NTLM(no Kerberos support yet) which uses algorithms */
/* not allowed in FIPS for sensitive data. So, we disallow NLA when FIPS is required. */
/* 2. Forces the only supported RDP encryption method to be FIPS. */
if (settings->FIPSMode)
{
settings->NlaSecurity = FALSE;
settings->EncryptionMethods = ENCRYPTION_METHOD_FIPS;
}
arg = CommandLineFindArgumentA(args, "port");
if (arg->Flags & COMMAND_LINE_ARGUMENT_PRESENT)

View File

@ -606,6 +606,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_AllowedTlsCiphers 1101
#define FreeRDP_VmConnectMode 1102
#define FreeRDP_NtlmSamFile 1103
#define FreeRDP_FIPSMode 1104
#define FreeRDP_MstscCookieMode 1152
#define FreeRDP_CookieMaxLength 1153
#define FreeRDP_PreconnectionId 1154
@ -1018,7 +1019,8 @@ struct rdp_settings
ALIGN64 char* AllowedTlsCiphers; /* 1101 */
ALIGN64 BOOL VmConnectMode; /* 1102 */
ALIGN64 char* NtlmSamFile; /* 1103 */
UINT64 padding1152[1152 - 1104]; /* 1104 */
ALIGN64 BOOL FIPSMode; /* 1104 */
UINT64 padding1152[1152 - 1105]; /* 1105 */
/* Connection Cookie */
ALIGN64 BOOL MstscCookieMode; /* 1152 */

View File

@ -921,6 +921,9 @@ BOOL freerdp_get_param_bool(rdpSettings* settings, int id)
case FreeRDP_ExternalCertificateManagement:
return settings->ExternalCertificateManagement;
case FreeRDP_FIPSMode:
return settings->FIPSMode;
case FreeRDP_Workarea:
return settings->Workarea;
@ -1381,6 +1384,10 @@ int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param)
settings->ExternalCertificateManagement = param;
break;
case FreeRDP_FIPSMode:
settings->FIPSMode = param;
break;
case FreeRDP_Workarea:
settings->Workarea = param;
break;

View File

@ -408,8 +408,13 @@ static BOOL certificate_process_server_public_signature(rdpCertificate* certific
BYTE encsig[TSSK_KEY_LENGTH + 8];
BYTE md5hash[WINPR_MD5_DIGEST_LENGTH];
if (!winpr_Digest(WINPR_MD_MD5, sigdata, sigdatalen, md5hash, sizeof(md5hash)))
return FALSE;
/* Do not bother with validation of server proprietary certificate. The use of MD5 here is not allowed under FIPS. */
/* Since the validation is not protecting against anything since the private/public keys are well known and documented in */
/* MS-RDPBCGR section 5.3.3.1, we are not gaining any security by using MD5 for signature comparison. Rather then use MD5 */
/* here we just dont do the validation to avoid its use. Historically, freerdp has been ignoring a failed validation anyways. */
/*if (!winpr_Digest(WINPR_MD_MD5, sigdata, sigdatalen, md5hash, sizeof(md5hash)))
return FALSE;*/
Stream_Read(s, encsig, siglen);
/* Last 8 bytes shall be all zero. */
@ -424,15 +429,17 @@ static BOOL certificate_process_server_public_signature(rdpCertificate* certific
}
siglen -= 8;
// TODO: check the result of decrypt
crypto_rsa_public_decrypt(encsig, siglen, TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent, sig);
/* Verify signature. */
if (memcmp(md5hash, sig, sizeof(md5hash)) != 0)
/* Do not bother with validation of server proprietary certificate as described above. */
/*if (memcmp(md5hash, sig, sizeof(md5hash)) != 0)
{
WLog_ERR(TAG, "invalid signature");
//return FALSE;
}
}*/
/*
* Verify rest of decrypted data:

View File

@ -32,6 +32,7 @@
#include <winpr/crt.h>
#include <winpr/crypto.h>
#include <winpr/ssl.h>
#include <freerdp/log.h>
#include <freerdp/error.h>
@ -178,6 +179,13 @@ BOOL rdp_client_connect(rdpRdp* rdp)
BOOL status;
rdpSettings* settings = rdp->settings;
/* make sure SSL is initialize for earlier enough for crypto, by taking advantage of winpr SSL FIPS flag for openssl initialization */
DWORD flags = WINPR_SSL_INIT_DEFAULT;
if (settings->FIPSMode)
flags |= WINPR_SSL_INIT_ENABLE_FIPS;
winpr_InitializeSSL(flags);
nego_init(rdp->nego);
nego_set_target(rdp->nego, settings->ServerHostname, settings->ServerPort);

View File

@ -615,6 +615,7 @@ BOOL freerdp_context_new(freerdp* instance)
rdpRdp* rdp;
rdpContext* context;
BOOL ret = TRUE;
DWORD flags = WINPR_SSL_INIT_DEFAULT;
instance->context = (rdpContext*) calloc(1, instance->ContextSize);
if (!instance->context)
@ -930,7 +931,6 @@ freerdp* freerdp_new()
if (!instance)
return NULL;
winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
instance->ContextSize = sizeof(rdpContext);
instance->SendChannelData = freerdp_send_channel_data;
instance->ReceiveChannelData = freerdp_channels_data;

View File

@ -424,7 +424,10 @@ BOOL license_generate_hwid(rdpLicense* license)
ZeroMemory(macAddress, sizeof(macAddress));
ZeroMemory(license->HardwareId, HWID_LENGTH);
if (!winpr_Digest(WINPR_MD_MD5, macAddress, sizeof(macAddress), &license->HardwareId[HWID_PLATFORM_ID_LENGTH], WINPR_MD5_DIGEST_LENGTH))
/* Allow FIPS override for use of MD5 here, really this does not have to be MD5 as we are just taking a MD5 hash of the 6 bytes of 0's(macAddress) */
/* and filling in the Data1-Data4 fields of the CLIENT_HARDWARE_ID structure(from MS-RDPELE section 2.2.2.3.1). This is for RDP licensing packets */
/* which will already be encrypted under FIPS, so the use of MD5 here is not for sensitive data protection. */
if (!winpr_Digest_Allow_FIPS(WINPR_MD_MD5, macAddress, sizeof(macAddress), &license->HardwareId[HWID_PLATFORM_ID_LENGTH], WINPR_MD5_DIGEST_LENGTH))
return FALSE;
return TRUE;
@ -495,7 +498,10 @@ BOOL license_decrypt_platform_challenge(rdpLicense* license)
return FALSE;
license->PlatformChallenge->length = license->EncryptedPlatformChallenge->length;
if ((rc4 = winpr_RC4_New(license->LicensingEncryptionKey,
/* Allow FIPS override for use of RC4 here, this is only used for decrypting the MACData field of the */
/* Server Platform Challenge packet (from MS-RDPELE section 2.2.2.4). This is for RDP licensing packets */
/* which will already be encrypted under FIPS, so the use of RC4 here is not for sensitive data protection. */
if ((rc4 = winpr_RC4_New_Allow_FIPS(license->LicensingEncryptionKey,
LICENSING_ENCRYPTION_KEY_LENGTH)) == NULL)
{
free(license->PlatformChallenge->data);
@ -1089,7 +1095,10 @@ BOOL license_send_platform_challenge_response_packet(rdpLicense* license)
if (!status)
return FALSE;
rc4 = winpr_RC4_New(license->LicensingEncryptionKey,
/* Allow FIPS override for use of RC4 here, this is only used for encrypting the EncryptedHWID field of the */
/* Client Platform Challenge Response packet (from MS-RDPELE section 2.2.2.5). This is for RDP licensing packets */
/* which will already be encrypted under FIPS, so the use of RC4 here is not for sensitive data protection. */
rc4 = winpr_RC4_New_Allow_FIPS(license->LicensingEncryptionKey,
LICENSING_ENCRYPTION_KEY_LENGTH);
if (!rc4)
return FALSE;

View File

@ -153,7 +153,10 @@ static BOOL security_salted_hash(const BYTE* salt, const BYTE* input, int length
/* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1_Digest) */
if (!(md5 = winpr_Digest_New()))
goto out;
if (!winpr_Digest_Init(md5, WINPR_MD_MD5))
/* Allow FIPS override for use of MD5 here, this is used for creating hashes of the premaster_secret and master_secret */
/* used for RDP licensing as described in MS-RDPELE. This is for RDP licensing packets */
/* which will already be encrypted under FIPS, so the use of MD5 here is not for sensitive data protection. */
if (!winpr_Digest_Init_Allow_FIPS(md5, WINPR_MD_MD5))
goto out;
if (!winpr_Digest_Update(md5, salt, 48)) /* Salt (48 bytes) */
goto out;
@ -232,11 +235,38 @@ out:
return result;
}
BOOL security_md5_16_32_32_Allow_FIPS(const BYTE* in0, const BYTE* in1, const BYTE* in2, BYTE* output)
{
WINPR_DIGEST_CTX* md5 = NULL;
BOOL result = FALSE;
if (!(md5 = winpr_Digest_New()))
return FALSE;
if (!winpr_Digest_Init_Allow_FIPS(md5, WINPR_MD_MD5))
goto out;
if (!winpr_Digest_Update(md5, in0, 16))
goto out;
if (!winpr_Digest_Update(md5, in1, 32))
goto out;
if (!winpr_Digest_Update(md5, in2, 32))
goto out;
if (!winpr_Digest_Final(md5, output, WINPR_MD5_DIGEST_LENGTH))
goto out;
result = TRUE;
out:
winpr_Digest_Free(md5);
return result;
}
BOOL security_licensing_encryption_key(const BYTE* session_key_blob, const BYTE* client_random,
const BYTE* server_random, BYTE* output)
{
/* LicensingEncryptionKey = MD5(Second128Bits(SessionKeyBlob) + ClientRandom + ServerRandom)) */
return security_md5_16_32_32(&session_key_blob[16], client_random, server_random, output);
/* Allow FIPS use of MD5 here, this is just used for creating the licensing encryption key as described in MS-RDPELE. */
/* This is for RDP licensing packets which will already be encrypted under FIPS, so the use of MD5 here is not for
/* sensitive data protection. */
return security_md5_16_32_32_Allow_FIPS(&session_key_blob[16], client_random, server_random, output);
}
void security_UINT32_le(BYTE* output, UINT32 value)
@ -279,7 +309,10 @@ BOOL security_mac_data(const BYTE* mac_salt_key, const BYTE* data, UINT32 length
/* MacData = MD5(MacSaltKey + pad2 + SHA1_Digest) */
if (!(md5 = winpr_Digest_New()))
goto out;
if (!winpr_Digest_Init(md5, WINPR_MD_MD5))
/* Allow FIPS override for use of MD5 here, this is only used for creating the MACData field of the */
/* Client Platform Challenge Response packet (from MS-RDPELE section 2.2.2.5). This is for RDP licensing packets */
/* which will already be encrypted under FIPS, so the use of MD5 here is not for sensitive data protection. */
if (!winpr_Digest_Init_Allow_FIPS(md5, WINPR_MD_MD5))
goto out;
if (!winpr_Digest_Update(md5, mac_salt_key, 16)) /* MacSaltKey */
goto out;
@ -546,8 +579,11 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp)
}
else
{
status = security_md5_16_32_32(&session_key_blob[16], client_random, server_random, rdp->decrypt_key);
status &= security_md5_16_32_32(&session_key_blob[32], client_random, server_random, rdp->encrypt_key);
/* Allow FIPS use of MD5 here, this is just used for generation of the SessionKeyBlob as described in MS-RDPELE. */
/* This is for RDP licensing packets which will already be encrypted under FIPS, so the use of MD5 here is not */
/* for sensitive data protection. */
status = security_md5_16_32_32_Allow_FIPS(&session_key_blob[16], client_random, server_random, rdp->decrypt_key);
status &= security_md5_16_32_32_Allow_FIPS(&session_key_blob[32], client_random, server_random, rdp->encrypt_key);
}
if (!status)

View File

@ -333,6 +333,7 @@ rdpSettings* freerdp_settings_new(DWORD flags)
settings->ConnectionType = CONNECTION_TYPE_LAN;
settings->EncryptionMethods = ENCRYPTION_METHOD_NONE;
settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE;
settings->FIPSMode = FALSE;
settings->CompressionEnabled = TRUE;
settings->LogonNotify = TRUE;

View File

@ -1466,7 +1466,6 @@ rdpTls* tls_new(rdpSettings* settings)
if (!tls)
return NULL;
winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
tls->settings = settings;
if (!settings->ServerMode)

View File

@ -27,6 +27,7 @@
#include <signal.h>
#include <winpr/crt.h>
#include <winpr/ssl.h>
#include <winpr/synch.h>
#include <winpr/string.h>
#include <winpr/path.h>
@ -919,6 +920,7 @@ int main(int argc, char* argv[])
}
WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi());
winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
instance = freerdp_listener_new();
if (!instance)

View File

@ -665,10 +665,12 @@ extern "C" {
#endif
WINPR_API WINPR_DIGEST_CTX* winpr_Digest_New(void);
WINPR_API BOOL winpr_Digest_Init_Allow_FIPS(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md);
WINPR_API BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md);
WINPR_API BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const BYTE* input, size_t ilen);
WINPR_API BOOL winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, BYTE* output, size_t ilen);
WINPR_API void winpr_Digest_Free(WINPR_DIGEST_CTX* ctx);
WINPR_API BOOL winpr_Digest_Allow_FIPS(int md, const BYTE* input, size_t ilen, BYTE* output, size_t olen);
WINPR_API BOOL winpr_Digest(int md, const BYTE* input, size_t ilen, BYTE* output, size_t olen);
#ifdef __cplusplus
@ -700,6 +702,7 @@ typedef struct _winpr_rc4_ctx_private_st WINPR_RC4_CTX;
extern "C" {
#endif
WINPR_API WINPR_RC4_CTX* winpr_RC4_New_Allow_FIPS(const BYTE* key, size_t keylen);
WINPR_API WINPR_RC4_CTX* winpr_RC4_New(const BYTE* key, size_t keylen);
WINPR_API BOOL winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output);
WINPR_API void winpr_RC4_Free(WINPR_RC4_CTX* ctx);

View File

@ -26,6 +26,7 @@
#define WINPR_SSL_INIT_DEFAULT 0x00
#define WINPR_SSL_INIT_ALREADY_INITIALIZED 0x01
#define WINPR_SSL_INIT_ENABLE_LOCKING 0x2
#define WINPR_SSL_INIT_ENABLE_FIPS 0x4
#define WINPR_SSL_CLEANUP_GLOBAL 0x01
#define WINPR_SSL_CLEANUP_THREAD 0x02

View File

@ -43,17 +43,36 @@
* RC4
*/
WINPR_RC4_CTX* winpr_RC4_New(const BYTE* key, size_t keylen)
WINPR_RC4_CTX* winpr_RC4_New_Internal(const BYTE* key, size_t keylen, BOOL override_fips)
{
WINPR_RC4_CTX* ctx = NULL;
#if defined(WITH_OPENSSL)
EVP_CIPHER* evp = NULL;
#endif
if (!key || (keylen == 0))
return NULL;
#if defined(WITH_OPENSSL)
if (!(ctx = (WINPR_RC4_CTX*) calloc(1, sizeof(RC4_KEY))))
if (!(ctx = EVP_CIPHER_CTX_new()))
return NULL;
RC4_set_key((RC4_KEY*) ctx, keylen, key);
evp = EVP_rc4();
if (!evp)
return NULL;
EVP_CIPHER_CTX_init((EVP_CIPHER_CTX *) ctx);
EVP_EncryptInit_ex((EVP_CIPHER_CTX *) ctx, evp, NULL, NULL, NULL);
/* EVP_CIPH_FLAG_NON_FIPS_ALLOW does not exist before openssl 1.0.1 */
#if !(OPENSSL_VERSION_NUMBER < 0x10001000L)
if (override_fips == TRUE)
EVP_CIPHER_CTX_set_flags((EVP_CIPHER_CTX *) ctx, EVP_CIPH_FLAG_NON_FIPS_ALLOW);
#endif
EVP_CIPHER_CTX_set_key_length((EVP_CIPHER_CTX *) ctx, keylen);
EVP_EncryptInit_ex((EVP_CIPHER_CTX *) ctx, NULL, NULL, key, NULL);
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C)
if (!(ctx = (WINPR_RC4_CTX*) calloc(1, sizeof(mbedtls_arc4_context))))
@ -64,10 +83,21 @@ WINPR_RC4_CTX* winpr_RC4_New(const BYTE* key, size_t keylen)
return ctx;
}
WINPR_RC4_CTX* winpr_RC4_New_Allow_FIPS(const BYTE* key, size_t keylen)
{
return winpr_RC4_New_Internal(key, keylen, TRUE);
}
WINPR_RC4_CTX* winpr_RC4_New(const BYTE* key, size_t keylen)
{
return winpr_RC4_New_Internal(key, keylen, FALSE);
}
BOOL winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output)
{
#if defined(WITH_OPENSSL)
RC4((RC4_KEY*) ctx, length, input, output);
int outputLength;
EVP_CipherUpdate((EVP_CIPHER_CTX *) ctx, output, &outputLength, input, length);
return TRUE;
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C)
@ -83,9 +113,7 @@ void winpr_RC4_Free(WINPR_RC4_CTX* ctx)
return;
#if defined(WITH_OPENSSL)
memset(ctx, 0, sizeof(RC4_KEY));
free(ctx);
EVP_CIPHER_CTX_free((EVP_CIPHER_CTX *) ctx);
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C)
mbedtls_arc4_free((mbedtls_arc4_context*) ctx);
free(ctx);

View File

@ -143,29 +143,30 @@ mbedtls_md_type_t winpr_mbedtls_get_md_type(int md)
WINPR_HMAC_CTX* winpr_HMAC_New(void)
{
WINPR_HMAC_CTX* ctx = NULL;
#if defined(WITH_OPENSSL)
HMAC_CTX* hmac = NULL;
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
if (!(hmac = (HMAC_CTX*) calloc(1, sizeof(HMAC_CTX))))
return NULL;
HMAC_CTX_init(hmac);
#else
if (!(hmac = HMAC_CTX_new()))
return NULL;
#endif
ctx = (WINPR_HMAC_CTX*) hmac;
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* hmac;
if (!(hmac = (mbedtls_md_context_t*) calloc(1, sizeof(mbedtls_md_context_t))))
return NULL;
mbedtls_md_init(hmac);
ctx = (WINPR_HMAC_CTX*) hmac;
#endif
return ctx;
}
@ -182,10 +183,11 @@ BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const BYTE* key, siz
HMAC_Init_ex(hmac, key, keylen, evp, NULL); /* no return value on OpenSSL 0.9.x */
return TRUE;
#else
if (HMAC_Init_ex(hmac, key, keylen, evp, NULL) == 1)
return TRUE;
#endif
#endif
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* hmac = (mbedtls_md_context_t*) ctx;
mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md);
@ -204,8 +206,8 @@ BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const BYTE* key, siz
if (mbedtls_md_hmac_starts(hmac, key, keylen) == 0)
return TRUE;
#endif
#endif
return FALSE;
}
@ -213,21 +215,22 @@ BOOL winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const BYTE* input, size_t ilen)
{
#if defined(WITH_OPENSSL)
HMAC_CTX* hmac = (HMAC_CTX*) ctx;
#if (OPENSSL_VERSION_NUMBER < 0x10000000L)
HMAC_Update(hmac, input, ilen); /* no return value on OpenSSL 0.9.x */
return TRUE;
#else
if (HMAC_Update(hmac, input, ilen) == 1)
return TRUE;
#endif
#endif
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*) ctx;
if (mbedtls_md_hmac_update(mdctx, input, ilen) == 0)
return TRUE;
#endif
#endif
return FALSE;
}
@ -248,16 +251,18 @@ BOOL winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, BYTE* output, size_t olen)
HMAC_Final(hmac, output, NULL); /* no return value on OpenSSL 0.9.x */
return TRUE;
#else
if (HMAC_Final(hmac, output, NULL) == 1)
return TRUE;
#endif
#endif
#elif defined(WITH_MBEDTLS)
mdctx = (mbedtls_md_context_t*) ctx;
if (mbedtls_md_hmac_finish(mdctx, output) == 0)
return TRUE;
#endif
#endif
return FALSE;
}
@ -265,6 +270,7 @@ void winpr_HMAC_Free(WINPR_HMAC_CTX* ctx)
{
#if defined(WITH_OPENSSL)
HMAC_CTX* hmac = (HMAC_CTX*) ctx;
if (hmac)
{
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
@ -277,27 +283,31 @@ void winpr_HMAC_Free(WINPR_HMAC_CTX* ctx)
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* hmac = (mbedtls_md_context_t*) ctx;
if (hmac)
{
mbedtls_md_free(hmac);
free(hmac);
}
#endif
}
BOOL winpr_HMAC(WINPR_MD_TYPE md, const BYTE* key, size_t keylen,
const BYTE* input, size_t ilen, BYTE* output, size_t olen)
const BYTE* input, size_t ilen, BYTE* output, size_t olen)
{
BOOL result = FALSE;
WINPR_HMAC_CTX *ctx = winpr_HMAC_New();
WINPR_HMAC_CTX* ctx = winpr_HMAC_New();
if (!ctx)
return FALSE;
if (!winpr_HMAC_Init(ctx, md, key, keylen))
goto out;
if (!winpr_HMAC_Update(ctx, input, ilen))
goto out;
if (!winpr_HMAC_Final(ctx, output, olen))
goto out;
@ -314,7 +324,6 @@ out:
WINPR_DIGEST_CTX* winpr_Digest_New(void)
{
WINPR_DIGEST_CTX* ctx = NULL;
#if defined(WITH_OPENSSL)
EVP_MD_CTX* mdctx;
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
@ -323,23 +332,22 @@ WINPR_DIGEST_CTX* winpr_Digest_New(void)
mdctx = EVP_MD_CTX_new();
#endif
ctx = (WINPR_DIGEST_CTX*) mdctx;
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* mdctx;
mdctx = (mbedtls_md_context_t*) calloc(1, sizeof(mbedtls_md_context_t));
if (mdctx)
mbedtls_md_init(mdctx);
ctx = (WINPR_DIGEST_CTX*) mdctx;
#endif
return ctx;
}
BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
{
#if defined(WITH_OPENSSL)
BOOL winpr_Digest_Init_Internal(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md, const EVP_MD* evp)
{
EVP_MD_CTX* mdctx = (EVP_MD_CTX*) ctx;
const EVP_MD* evp = winpr_openssl_get_evp_md(md);
if (!mdctx || !evp)
return FALSE;
@ -347,7 +355,12 @@ BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
if (EVP_DigestInit_ex(mdctx, evp, NULL) != 1)
return FALSE;
return TRUE;
}
#elif defined(WITH_MBEDTLS)
BOOL winpr_Digest_Init_Internal(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
{
mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*) ctx;
mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md);
const mbedtls_md_info_t* md_info = mbedtls_md_info_from_type(md_type);
@ -365,21 +378,57 @@ BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
if (mbedtls_md_starts(mdctx) != 0)
return FALSE;
#endif
return TRUE;
}
#endif
BOOL winpr_Digest_Init_Allow_FIPS(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
{
#if defined(WITH_OPENSSL)
EVP_MD_CTX* mdctx = (EVP_MD_CTX*) ctx;
const EVP_MD* evp = winpr_openssl_get_evp_md(md);
/* Only MD5 is supported for FIPS allow override */
if (md != WINPR_MD_MD5)
return FALSE;
EVP_MD_CTX_set_flags(mdctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
return winpr_Digest_Init_Internal(ctx, md, evp);
#elif defined(WITH_MBEDTLS)
/* Only MD5 is supported for FIPS allow override */
if (md != WINPR_MD_MD5)
return FALSE;
return winpr_Digest_Init_Internal(ctx, md);
#endif
}
BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md)
{
#if defined(WITH_OPENSSL)
const EVP_MD* evp = winpr_openssl_get_evp_md(md);
return winpr_Digest_Init_Internal(ctx, md, evp);
#else
return winpr_Digest_Init_Internal(ctx, md);
#endif
}
BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const BYTE* input, size_t ilen)
{
#if defined(WITH_OPENSSL)
EVP_MD_CTX* mdctx = (EVP_MD_CTX*) ctx;
if (EVP_DigestUpdate(mdctx, input, ilen) != 1)
return FALSE;
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*) ctx;
if (mbedtls_md_update(mdctx, input, ilen) != 0)
return FALSE;
#endif
return TRUE;
}
@ -388,15 +437,17 @@ BOOL winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, BYTE* output, size_t olen)
{
#if defined(WITH_OPENSSL)
EVP_MD_CTX* mdctx = (EVP_MD_CTX*) ctx;
if (EVP_DigestFinal_ex(mdctx, output, NULL) == 1)
return TRUE;
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*) ctx;
if (mbedtls_md_finish(mdctx, output) == 0)
return TRUE;
#endif
#endif
return FALSE;
}
@ -404,6 +455,7 @@ void winpr_Digest_Free(WINPR_DIGEST_CTX* ctx)
{
#if defined(WITH_OPENSSL)
EVP_MD_CTX* mdctx = (EVP_MD_CTX*) ctx;
if (mdctx)
{
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER)
@ -415,26 +467,53 @@ void winpr_Digest_Free(WINPR_DIGEST_CTX* ctx)
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*) ctx;
if (mdctx)
{
mbedtls_md_free(mdctx);
free(mdctx);
}
#endif
}
BOOL winpr_Digest(int md, const BYTE* input, size_t ilen, BYTE* output, size_t olen)
BOOL winpr_Digest_Allow_FIPS(int md, const BYTE* input, size_t ilen, BYTE* output, size_t olen)
{
BOOL result = FALSE;
WINPR_DIGEST_CTX *ctx = winpr_Digest_New();
WINPR_DIGEST_CTX* ctx = winpr_Digest_New();
if (!ctx)
return FALSE;
if (!winpr_Digest_Init(ctx, md))
if (!winpr_Digest_Init_Allow_FIPS(ctx, md))
goto out;
if (!winpr_Digest_Update(ctx, input, ilen))
goto out;
if (!winpr_Digest_Final(ctx, output, olen))
goto out;
result = TRUE;
out:
winpr_Digest_Free(ctx);
return result;
}
BOOL winpr_Digest(int md, const BYTE* input, size_t ilen, BYTE* output, size_t olen)
{
BOOL result = FALSE;
WINPR_DIGEST_CTX* ctx = winpr_Digest_New();
if (!ctx)
return FALSE;
if (!winpr_Digest_Init(ctx, md))
goto out;
if (!winpr_Digest_Update(ctx, input, ilen))
goto out;
if (!winpr_Digest_Final(ctx, output, olen))
goto out;

View File

@ -276,6 +276,25 @@ static BOOL CALLBACK _winpr_openssl_initialize(PINIT_ONCE once, PVOID param, PVO
#endif
g_winpr_openssl_initialized_by_winpr = TRUE;
if (flags & WINPR_SSL_INIT_ENABLE_FIPS)
{
#if (OPENSSL_VERSION_NUMBER < 0x10001000L)
WLog_ERR(TAG, "Openssl fips mode ENable not available on openssl versions less than 1.0.1!");
#else
WLog_DBG(TAG, "Ensuring openssl fips mode is ENabled");
if (FIPS_mode() != 1)
{
if (FIPS_mode_set(1))
WLog_INFO(TAG, "Openssl fips mode ENabled!");
else
WLog_ERR(TAG, "Openssl fips mode ENable failed!");
}
#endif
}
return TRUE;
}