Merge pull request #3615 from nfedera/openssl_1.1.0

Support for OpenSSL 1.1.0
This commit is contained in:
akallabeth 2016-11-25 11:07:58 +01:00 committed by GitHub
commit f23487907e
31 changed files with 1347 additions and 1156 deletions

View File

@ -756,6 +756,7 @@ endif()
if(OPENSSL_FOUND)
add_definitions("-DWITH_OPENSSL")
message(STATUS "Using OpenSSL Version: ${OPENSSL_VERSION}")
endif()
if(MBEDTLS_FOUND)

View File

@ -28,7 +28,7 @@
#include <openssl/bn.h>
#include <openssl/x509v3.h>
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800f)
#if OPENSSL_VERSION_NUMBER >= 0x0090800f
#define D2I_X509_CONST const
#else
#define D2I_X509_CONST

View File

@ -77,7 +77,6 @@ int freerdp_assistance_crypt_derive_key_sha1(BYTE* hash, int hashLength, BYTE* k
BYTE* buffer;
BYTE pad1[64];
BYTE pad2[64];
WINPR_SHA1_CTX hashCtx;
memset(pad1, 0x36, 64);
memset(pad2, 0x5C, 64);
@ -93,18 +92,10 @@ int freerdp_assistance_crypt_derive_key_sha1(BYTE* hash, int hashLength, BYTE* k
if (!buffer)
goto fail;
if (!winpr_SHA1_Init(&hashCtx))
goto fail;
if (!winpr_SHA1_Update(&hashCtx, pad1, 64))
goto fail;
if (!winpr_SHA1_Final(&hashCtx, buffer, hashLength))
if (!winpr_Digest(WINPR_MD_SHA1, pad1, 64, buffer, hashLength))
goto fail;
if (!winpr_SHA1_Init(&hashCtx))
goto fail;
if (!winpr_SHA1_Update(&hashCtx, pad2, 64))
goto fail;
if (!winpr_SHA1_Final(&hashCtx, &buffer[hashLength], hashLength))
if (!winpr_Digest(WINPR_MD_SHA1, pad2, 64, &buffer[hashLength], hashLength))
goto fail;
CopyMemory(key, buffer, keyLength);
@ -550,7 +541,6 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas
{
BOOL rc;
int status;
WINPR_MD5_CTX md5Ctx;
int cbPasswordW;
int cbPassStubW;
int EncryptedSize;
@ -568,17 +558,7 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas
cbPasswordW = (status - 1) * 2;
if (!winpr_MD5_Init(&md5Ctx))
{
free (PasswordW);
return NULL;
}
if (!winpr_MD5_Update(&md5Ctx, (BYTE*)PasswordW, cbPasswordW))
{
free (PasswordW);
return NULL;
}
if (!winpr_MD5_Final(&md5Ctx, (BYTE*) PasswordHash, sizeof(PasswordHash)))
if (!winpr_Digest(WINPR_MD_MD5, (BYTE*)PasswordW, cbPasswordW, (BYTE*) PasswordHash, sizeof(PasswordHash)))
{
free (PasswordW);
return NULL;
@ -665,7 +645,6 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas
int freerdp_assistance_decrypt2(rdpAssistanceFile* file, const char* password)
{
int status;
WINPR_SHA1_CTX shaCtx;
int cbPasswordW;
int cchOutW = 0;
WCHAR* pbOutW = NULL;
@ -684,9 +663,7 @@ int freerdp_assistance_decrypt2(rdpAssistanceFile* file, const char* password)
cbPasswordW = (status - 1) * 2;
if (!winpr_SHA1_Init(&shaCtx) ||
!winpr_SHA1_Update(&shaCtx, (BYTE*)PasswordW, cbPasswordW) ||
!winpr_SHA1_Final(&shaCtx, PasswordHash, sizeof(PasswordHash)))
if (!winpr_Digest(WINPR_MD_SHA1, (BYTE*)PasswordW, cbPasswordW, PasswordHash, sizeof(PasswordHash)))
{
free (PasswordW);
return -1;

View File

@ -35,6 +35,7 @@
#include <openssl/rsa.h>
#include "certificate.h"
#include "../crypto/opensslcompat.h"
#define TAG "com.freerdp.core"
@ -399,16 +400,11 @@ static BOOL certificate_process_server_public_signature(rdpCertificate* certific
const BYTE* sigdata, int sigdatalen, wStream* s, UINT32 siglen)
{
int i, sum;
WINPR_MD5_CTX md5ctx;
BYTE sig[TSSK_KEY_LENGTH];
BYTE encsig[TSSK_KEY_LENGTH + 8];
BYTE md5hash[WINPR_MD5_DIGEST_LENGTH];
if (!winpr_MD5_Init(&md5ctx))
return FALSE;
if (!winpr_MD5_Update(&md5ctx, sigdata, sigdatalen))
return FALSE;
if (!winpr_MD5_Final(&md5ctx, md5hash, sizeof(md5hash)))
if (!winpr_Digest(WINPR_MD_MD5, sigdata, sigdatalen, md5hash, sizeof(md5hash)))
return FALSE;
Stream_Read(s, encsig, siglen);
@ -667,6 +663,9 @@ rdpRsaKey* key_new_from_content(const char *keycontent, const char *keyfile)
BIO* bio = NULL;
RSA* rsa = NULL;
rdpRsaKey* key = NULL;
const BIGNUM *rsa_e = NULL;
const BIGNUM *rsa_n = NULL;
const BIGNUM *rsa_d = NULL;
key = (rdpRsaKey*) calloc(1, sizeof(rdpRsaKey));
if (!key)
@ -700,30 +699,32 @@ rdpRsaKey* key_new_from_content(const char *keycontent, const char *keyfile)
goto out_free_rsa;
}
if (BN_num_bytes(rsa->e) > 4)
RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d);
if (BN_num_bytes(rsa_e) > 4)
{
WLog_ERR(TAG, "RSA public exponent too large in %s", keyfile);
goto out_free_rsa;
}
key->ModulusLength = BN_num_bytes(rsa->n);
key->ModulusLength = BN_num_bytes(rsa_n);
key->Modulus = (BYTE*) malloc(key->ModulusLength);
if (!key->Modulus)
goto out_free_rsa;
BN_bn2bin(rsa->n, key->Modulus);
BN_bn2bin(rsa_n, key->Modulus);
crypto_reverse(key->Modulus, key->ModulusLength);
key->PrivateExponentLength = BN_num_bytes(rsa->d);
key->PrivateExponentLength = BN_num_bytes(rsa_d);
key->PrivateExponent = (BYTE*) malloc(key->PrivateExponentLength);
if (!key->PrivateExponent)
goto out_free_modulus;
BN_bn2bin(rsa->d, key->PrivateExponent);
BN_bn2bin(rsa_d, key->PrivateExponent);
crypto_reverse(key->PrivateExponent, key->PrivateExponentLength);
memset(key->exponent, 0, sizeof(key->exponent));
BN_bn2bin(rsa->e, key->exponent + sizeof(key->exponent) - BN_num_bytes(rsa->e));
BN_bn2bin(rsa_e, key->exponent + sizeof(key->exponent) - BN_num_bytes(rsa_e));
crypto_reverse(key->exponent, sizeof(key->exponent));
RSA_free(rsa);
return key;

View File

@ -490,31 +490,25 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
if (settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
{
rdp->fips_encrypt = winpr_Cipher_New( WINPR_CIPHER_DES_EDE3_CBC,
WINPR_ENCRYPT,
rdp->fips_encrypt_key,
fips_ivec);
rdp->fips_encrypt = winpr_Cipher_New(WINPR_CIPHER_DES_EDE3_CBC,
WINPR_ENCRYPT,
rdp->fips_encrypt_key,
fips_ivec);
if (!rdp->fips_encrypt)
{
WLog_ERR(TAG, "unable to allocate des3 encrypt key");
goto end;
}
rdp->fips_decrypt = winpr_Cipher_New(WINPR_CIPHER_DES_EDE3_CBC,
WINPR_DECRYPT,
rdp->fips_decrypt_key,
fips_ivec);
WINPR_DECRYPT,
rdp->fips_decrypt_key,
fips_ivec);
if (!rdp->fips_decrypt)
{
WLog_ERR(TAG, "unable to allocate des3 decrypt key");
goto end;
}
rdp->fips_hmac = calloc(1, sizeof(WINPR_HMAC_CTX));
if (!rdp->fips_hmac)
{
WLog_ERR(TAG, "unable to allocate fips hmac");
goto end;
}
ret = TRUE;
goto end;
}
@ -636,12 +630,6 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s)
goto end;
}
rdp->fips_hmac = calloc(1, sizeof(WINPR_HMAC_CTX));
if (!rdp->fips_hmac)
{
WLog_ERR(TAG, "unable to allocate fips hmac");
goto end;
}
ret = TRUE;
goto end;
}

View File

@ -35,6 +35,7 @@
#include "rdg.h"
#include "../rdp.h"
#include "../../crypto/opensslcompat.h"
#define TAG FREERDP_TAG("core.gateway.rdg")
@ -1389,7 +1390,7 @@ long rdg_bio_callback(BIO* bio, int mode, const char* argp, int argi, long argl,
static int rdg_bio_write(BIO* bio, const char* buf, int num)
{
int status;
rdpRdg* rdg = (rdpRdg*) bio->ptr;
rdpRdg* rdg = (rdpRdg*) BIO_get_data(bio);
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
@ -1418,7 +1419,7 @@ static int rdg_bio_write(BIO* bio, const char* buf, int num)
static int rdg_bio_read(BIO* bio, char* buf, int size)
{
int status;
rdpRdg* rdg = (rdpRdg*) bio->ptr;
rdpRdg* rdg = (rdpRdg*) BIO_get_data(bio);
status = rdg_read_data_packet(rdg, (BYTE*) buf, size);
@ -1454,7 +1455,7 @@ static int rdg_bio_gets(BIO* bio, char* str, int size)
static long rdg_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
{
int status = 0;
rdpRdg* rdg = (rdpRdg*)bio->ptr;
rdpRdg* rdg = (rdpRdg*) BIO_get_data(bio);
rdpTls* tlsOut = rdg->tlsOut;
rdpTls* tlsIn = rdg->tlsIn;
@ -1516,10 +1517,8 @@ static long rdg_bio_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
static int rdg_bio_new(BIO* bio)
{
bio->init = 1;
bio->num = 0;
bio->ptr = NULL;
bio->flags = BIO_FLAGS_SHOULD_RETRY;
BIO_set_init(bio, 1);
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
return 1;
}
@ -1528,23 +1527,25 @@ static int rdg_bio_free(BIO* bio)
return 1;
}
static BIO_METHOD rdg_bio_methods =
{
BIO_TYPE_TSG,
"RDGateway",
rdg_bio_write,
rdg_bio_read,
rdg_bio_puts,
rdg_bio_gets,
rdg_bio_ctrl,
rdg_bio_new,
rdg_bio_free,
NULL,
};
BIO_METHOD* BIO_s_rdg(void)
{
return &rdg_bio_methods;
static BIO_METHOD* bio_methods = NULL;
if (bio_methods == NULL)
{
if (!(bio_methods = BIO_meth_new(BIO_TYPE_TSG, "RDGateway")))
return NULL;
BIO_meth_set_write(bio_methods, rdg_bio_write);
BIO_meth_set_read(bio_methods, rdg_bio_read);
BIO_meth_set_puts(bio_methods, rdg_bio_puts);
BIO_meth_set_gets(bio_methods, rdg_bio_gets);
BIO_meth_set_ctrl(bio_methods, rdg_bio_ctrl);
BIO_meth_set_create(bio_methods, rdg_bio_new);
BIO_meth_set_destroy(bio_methods, rdg_bio_free);
}
return bio_methods;
}
rdpRdg* rdg_new(rdpTransport* transport)
@ -1610,7 +1611,7 @@ rdpRdg* rdg_new(rdpTransport* transport)
if (!rdg->frontBio)
goto rdg_alloc_error;
rdg->frontBio->ptr = rdg;
BIO_set_data(rdg->frontBio, rdg);
rdg->readEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

View File

@ -35,6 +35,7 @@
#include "rpc_bind.h"
#include "rpc_client.h"
#include "tsg.h"
#include "../../crypto/opensslcompat.h"
#define TAG FREERDP_TAG("core.gateway.tsg")
@ -1770,7 +1771,7 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, int timeout)
if (!tsg->bio)
return FALSE;
tsg->bio->ptr = (void*) tsg;
BIO_set_data(tsg->bio, (void*) tsg);
return TRUE;
}
@ -1937,7 +1938,7 @@ long transport_bio_tsg_callback(BIO* bio, int mode, const char* argp, int argi,
static int transport_bio_tsg_write(BIO* bio, const char* buf, int num)
{
int status;
rdpTsg* tsg = (rdpTsg*) bio->ptr;
rdpTsg* tsg = (rdpTsg*) BIO_get_data(bio);
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
@ -1964,7 +1965,7 @@ static int transport_bio_tsg_write(BIO* bio, const char* buf, int num)
static int transport_bio_tsg_read(BIO* bio, char* buf, int size)
{
int status;
rdpTsg* tsg = (rdpTsg*) bio->ptr;
rdpTsg* tsg = (rdpTsg*) BIO_get_data(bio);
BIO_clear_flags(bio, BIO_FLAGS_READ);
@ -2001,7 +2002,7 @@ static int transport_bio_tsg_gets(BIO* bio, char* str, int size)
static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
{
int status = 0;
rdpTsg* tsg = (rdpTsg*) bio->ptr;
rdpTsg* tsg = (rdpTsg*) BIO_get_data(bio);
RpcVirtualConnection* connection = tsg->rpc->VirtualConnection;
RpcInChannel* inChannel = connection->DefaultInChannel;
RpcOutChannel* outChannel = connection->DefaultOutChannel;
@ -2064,10 +2065,8 @@ static long transport_bio_tsg_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
static int transport_bio_tsg_new(BIO* bio)
{
bio->init = 1;
bio->num = 0;
bio->ptr = NULL;
bio->flags = BIO_FLAGS_SHOULD_RETRY;
BIO_set_init(bio, 1);
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
return 1;
}
@ -2076,21 +2075,23 @@ static int transport_bio_tsg_free(BIO* bio)
return 1;
}
static BIO_METHOD transport_bio_tsg_methods =
{
BIO_TYPE_TSG,
"TSGateway",
transport_bio_tsg_write,
transport_bio_tsg_read,
transport_bio_tsg_puts,
transport_bio_tsg_gets,
transport_bio_tsg_ctrl,
transport_bio_tsg_new,
transport_bio_tsg_free,
NULL,
};
BIO_METHOD* BIO_s_tsg(void)
{
return &transport_bio_tsg_methods;
static BIO_METHOD* bio_methods = NULL;
if (bio_methods == NULL)
{
if (!(bio_methods = BIO_meth_new(BIO_TYPE_TSG, "TSGateway")))
return NULL;
BIO_meth_set_write(bio_methods, transport_bio_tsg_write);
BIO_meth_set_read(bio_methods, transport_bio_tsg_read);
BIO_meth_set_puts(bio_methods, transport_bio_tsg_puts);
BIO_meth_set_gets(bio_methods, transport_bio_tsg_gets);
BIO_meth_set_ctrl(bio_methods, transport_bio_tsg_ctrl);
BIO_meth_set_create(bio_methods, transport_bio_tsg_new);
BIO_meth_set_destroy(bio_methods, transport_bio_tsg_free);
}
return bio_methods;
}

View File

@ -1265,7 +1265,6 @@ const BYTE tssk_exponent[] =
BOOL gcc_write_server_security_data(wStream* s, rdpMcs* mcs)
{
WINPR_MD5_CTX md5;
BYTE* sigData;
int expLen, keyLen, sigDataLen;
BYTE encryptedSignature[TSSK_KEY_LENGTH];
@ -1474,13 +1473,7 @@ BOOL gcc_write_server_security_data(wStream* s, rdpMcs* mcs)
Stream_Write_UINT16(s, sizeof(encryptedSignature) + 8); /* wSignatureBlobLen */
memcpy(signature, initial_signature, sizeof(initial_signature));
if (!winpr_MD5_Init(&md5))
return FALSE;
if (!winpr_MD5_Update(&md5, sigData, sigDataLen))
return FALSE;
if (!winpr_MD5_Final(&md5, signature, sizeof(signature)))
if (!winpr_Digest(WINPR_MD_MD5, sigData, sigDataLen, signature, sizeof(signature)))
return FALSE;
crypto_rsa_private_encrypt(signature, sizeof(signature), TSSK_KEY_LENGTH,

View File

@ -45,7 +45,6 @@ static const char* const INFO_TYPE_LOGON_STRINGS[4] =
BOOL rdp_compute_client_auto_reconnect_cookie(rdpRdp* rdp)
{
WINPR_HMAC_CTX hmac;
BYTE ClientRandom[32];
BYTE AutoReconnectRandom[32];
ARC_SC_PRIVATE_PACKET* serverCookie;
@ -70,11 +69,7 @@ BOOL rdp_compute_client_auto_reconnect_cookie(rdpRdp* rdp)
/* SecurityVerifier = HMAC_MD5(AutoReconnectRandom, ClientRandom) */
if (!winpr_HMAC_Init(&hmac, WINPR_MD_MD5, AutoReconnectRandom, 16))
return FALSE;
if (!winpr_HMAC_Update(&hmac, ClientRandom, 32))
return FALSE;
if (!winpr_HMAC_Final(&hmac, clientCookie->securityVerifier, 16))
if (!winpr_HMAC(WINPR_MD_MD5, AutoReconnectRandom, 16, ClientRandom, 32, clientCookie->securityVerifier, 16))
return FALSE;
return TRUE;

View File

@ -385,17 +385,12 @@ BOOL license_generate_keys(rdpLicense* license)
BOOL license_generate_hwid(rdpLicense* license)
{
WINPR_MD5_CTX md5;
BYTE macAddress[6];
ZeroMemory(macAddress, sizeof(macAddress));
ZeroMemory(license->HardwareId, HWID_LENGTH);
if (!winpr_MD5_Init(&md5))
return FALSE;
if (!winpr_MD5_Update(&md5, macAddress, sizeof(macAddress)))
return FALSE;
if (!winpr_MD5_Final(&md5, &license->HardwareId[HWID_PLATFORM_ID_LENGTH], WINPR_MD5_DIGEST_LENGTH))
if (!winpr_Digest(WINPR_MD_MD5, macAddress, sizeof(macAddress), &license->HardwareId[HWID_PLATFORM_ID_LENGTH], WINPR_MD5_DIGEST_LENGTH))
return FALSE;
return TRUE;

View File

@ -80,7 +80,6 @@ struct rdp_nla
SecBuffer authInfo;
SecBuffer PublicKey;
SecBuffer tsCredentials;
WINPR_RC4_CTX rc4SealState;
LPTSTR ServicePrincipalName;
SEC_WINNT_AUTH_IDENTITY* identity;
PSecurityFunctionTable table;

View File

@ -1646,12 +1646,6 @@ void rdp_reset(rdpRdp* rdp)
rdp->fips_decrypt = NULL;
}
if (rdp->fips_hmac)
{
free(rdp->fips_hmac);
rdp->fips_hmac = NULL;
}
if (settings->ServerRandom)
{
free(settings->ServerRandom);
@ -1699,7 +1693,6 @@ void rdp_free(rdpRdp* rdp)
winpr_RC4_Free(rdp->rc4_encrypt_key);
winpr_Cipher_Free(rdp->fips_encrypt);
winpr_Cipher_Free(rdp->fips_decrypt);
free(rdp->fips_hmac);
freerdp_settings_free(rdp->settings);
freerdp_settings_free(rdp->settingsCopy);
transport_free(rdp->transport);

View File

@ -157,7 +157,6 @@ struct rdp_rdp
int encrypt_checksum_use_count;
WINPR_CIPHER_CTX* fips_encrypt;
WINPR_CIPHER_CTX* fips_decrypt;
WINPR_HMAC_CTX* fips_hmac;
UINT32 sec_flags;
BOOL do_crypt;
BOOL do_crypt_license;

View File

@ -127,36 +127,46 @@ fips_oddparity_table[256] =
static BOOL security_salted_hash(const BYTE* salt, const BYTE* input, int length,
const BYTE* salt1, const BYTE* salt2, BYTE* output)
{
WINPR_MD5_CTX md5;
WINPR_SHA1_CTX sha1;
WINPR_DIGEST_CTX* sha1 = NULL;
WINPR_DIGEST_CTX* md5 = NULL;
BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH];
BOOL result = FALSE;
/* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1(Input + Salt + Salt1 + Salt2)) */
/* SHA1_Digest = SHA1(Input + Salt + Salt1 + Salt2) */
if (!winpr_SHA1_Init(&sha1))
return FALSE;
if (!winpr_SHA1_Update(&sha1, input, length)) /* Input */
return FALSE;
if (!winpr_SHA1_Update(&sha1, salt, 48)) /* Salt (48 bytes) */
return FALSE;
if (!winpr_SHA1_Update(&sha1, salt1, 32)) /* Salt1 (32 bytes) */
return FALSE;
if (!winpr_SHA1_Update(&sha1, salt2, 32)) /* Salt2 (32 bytes) */
return FALSE;
if (!winpr_SHA1_Final(&sha1, sha1_digest, sizeof(sha1_digest)))
return FALSE;
if (!(sha1 = winpr_Digest_New()))
goto out;
if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1))
goto out;
if (!winpr_Digest_Update(sha1, input, length)) /* Input */
goto out;
if (!winpr_Digest_Update(sha1, salt, 48)) /* Salt (48 bytes) */
goto out;
if (!winpr_Digest_Update(sha1, salt1, 32)) /* Salt1 (32 bytes) */
goto out;
if (!winpr_Digest_Update(sha1, salt2, 32)) /* Salt2 (32 bytes) */
goto out;
if (!winpr_Digest_Final(sha1, sha1_digest, sizeof(sha1_digest)))
goto out;
/* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1_Digest) */
if (!winpr_MD5_Init(&md5))
return FALSE;
if (!winpr_MD5_Update(&md5, salt, 48)) /* Salt (48 bytes) */
return FALSE;
if (!winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */
return FALSE;
if (!winpr_MD5_Final(&md5, output, WINPR_MD5_DIGEST_LENGTH))
return FALSE;
return TRUE;
if (!(md5 = winpr_Digest_New()))
goto out;
if (!winpr_Digest_Init(md5, WINPR_MD_MD5))
goto out;
if (!winpr_Digest_Update(md5, salt, 48)) /* Salt (48 bytes) */
goto out;
if (!winpr_Digest_Update(md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */
goto out;
if (!winpr_Digest_Final(md5, output, WINPR_MD5_DIGEST_LENGTH))
goto out;
result = TRUE;
out:
winpr_Digest_Free(sha1);
winpr_Digest_Free(md5);
return result;
}
static BOOL security_premaster_hash(const char* input, int length, const BYTE* premaster_secret,
@ -200,19 +210,26 @@ void security_mac_salt_key(const BYTE* session_key_blob, const BYTE* client_rand
BOOL security_md5_16_32_32(const BYTE* in0, const BYTE* in1, const BYTE* in2, BYTE* output)
{
WINPR_MD5_CTX md5;
WINPR_DIGEST_CTX* md5 = NULL;
BOOL result = FALSE;
if (!winpr_MD5_Init(&md5))
if (!(md5 = winpr_Digest_New()))
return FALSE;
if (!winpr_MD5_Update(&md5, in0, 16))
return FALSE;
if (!winpr_MD5_Update(&md5, in1, 32))
return FALSE;
if (!winpr_MD5_Update(&md5, in2, 32))
return FALSE;
if (!winpr_MD5_Final(&md5, output, WINPR_MD5_DIGEST_LENGTH))
return FALSE;
return TRUE;
if (!winpr_Digest_Init(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,
@ -233,92 +250,112 @@ void security_UINT32_le(BYTE* output, UINT32 value)
BOOL security_mac_data(const BYTE* mac_salt_key, const BYTE* data, UINT32 length,
BYTE* output)
{
WINPR_MD5_CTX md5;
WINPR_SHA1_CTX sha1;
WINPR_DIGEST_CTX* sha1 = NULL;
WINPR_DIGEST_CTX* md5 = NULL;
BYTE length_le[4];
BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH];
BOOL result = FALSE;
/* MacData = MD5(MacSaltKey + pad2 + SHA1(MacSaltKey + pad1 + length + data)) */
security_UINT32_le(length_le, length); /* length must be little-endian */
/* SHA1_Digest = SHA1(MacSaltKey + pad1 + length + data) */
if (!winpr_SHA1_Init(&sha1))
return FALSE;
if (!winpr_SHA1_Update(&sha1, mac_salt_key, 16)) /* MacSaltKey */
return FALSE;
if (!winpr_SHA1_Update(&sha1, pad1, sizeof(pad1))) /* pad1 */
return FALSE;
if (!winpr_SHA1_Update(&sha1, length_le, sizeof(length_le))) /* length */
return FALSE;
if (!winpr_SHA1_Update(&sha1, data, length)) /* data */
return FALSE;
if (!winpr_SHA1_Final(&sha1, sha1_digest, sizeof(sha1_digest)))
return FALSE;
if (!(sha1 = winpr_Digest_New()))
goto out;
if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1))
goto out;
if (!winpr_Digest_Update(sha1, mac_salt_key, 16)) /* MacSaltKey */
goto out;
if (!winpr_Digest_Update(sha1, pad1, sizeof(pad1))) /* pad1 */
goto out;
if (!winpr_Digest_Update(sha1, length_le, sizeof(length_le))) /* length */
goto out;
if (!winpr_Digest_Update(sha1, data, length)) /* data */
goto out;
if (!winpr_Digest_Final(sha1, sha1_digest, sizeof(sha1_digest)))
goto out;
/* MacData = MD5(MacSaltKey + pad2 + SHA1_Digest) */
if (!winpr_MD5_Init(&md5))
return FALSE;
if (!winpr_MD5_Update(&md5, mac_salt_key, 16)) /* MacSaltKey */
return FALSE;
if (!winpr_MD5_Update(&md5, pad2, sizeof(pad2))) /* pad2 */
return FALSE;
if (!winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */
return FALSE;
if (!winpr_MD5_Final(&md5, output, WINPR_MD5_DIGEST_LENGTH))
return FALSE;
return TRUE;
if (!(md5 = winpr_Digest_New()))
goto out;
if (!winpr_Digest_Init(md5, WINPR_MD_MD5))
goto out;
if (!winpr_Digest_Update(md5, mac_salt_key, 16)) /* MacSaltKey */
goto out;
if (!winpr_Digest_Update(md5, pad2, sizeof(pad2))) /* pad2 */
goto out;
if (!winpr_Digest_Update(md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */
goto out;
if (!winpr_Digest_Final(md5, output, WINPR_MD5_DIGEST_LENGTH))
goto out;
result = TRUE;
out:
winpr_Digest_Free(sha1);
winpr_Digest_Free(md5);
return result;
}
BOOL security_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BYTE* output)
{
WINPR_MD5_CTX md5;
WINPR_SHA1_CTX sha1;
WINPR_DIGEST_CTX* sha1 = NULL;
WINPR_DIGEST_CTX* md5 = NULL;
BYTE length_le[4];
BYTE md5_digest[WINPR_MD5_DIGEST_LENGTH];
BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH];
BOOL result = FALSE;
security_UINT32_le(length_le, length); /* length must be little-endian */
/* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */
if (!winpr_SHA1_Init(&sha1))
return FALSE;
if (!winpr_SHA1_Update(&sha1, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */
return FALSE;
if (!winpr_SHA1_Update(&sha1, pad1, sizeof(pad1))) /* pad1 */
return FALSE;
if (!winpr_SHA1_Update(&sha1, length_le, sizeof(length_le))) /* length */
return FALSE;
if (!winpr_SHA1_Update(&sha1, data, length)) /* data */
return FALSE;
if (!winpr_SHA1_Final(&sha1, sha1_digest, sizeof(sha1_digest)))
return FALSE;
if (!(sha1 = winpr_Digest_New()))
goto out;
if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1))
goto out;
if (!winpr_Digest_Update(sha1, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */
goto out;
if (!winpr_Digest_Update(sha1, pad1, sizeof(pad1))) /* pad1 */
goto out;
if (!winpr_Digest_Update(sha1, length_le, sizeof(length_le))) /* length */
goto out;
if (!winpr_Digest_Update(sha1, data, length)) /* data */
goto out;
if (!winpr_Digest_Final(sha1, sha1_digest, sizeof(sha1_digest)))
goto out;
/* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */
if (!winpr_MD5_Init(&md5))
return FALSE;
if (!winpr_MD5_Update(&md5, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */
return FALSE;
if (!winpr_MD5_Update(&md5, pad2, sizeof(pad2))) /* pad2 */
return FALSE;
if (!winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */
return FALSE;
if (!winpr_MD5_Final(&md5, md5_digest, sizeof(md5_digest)))
return FALSE;
if (!(md5 = winpr_Digest_New()))
goto out;
if (!winpr_Digest_Init(md5, WINPR_MD_MD5))
goto out;
if (!winpr_Digest_Update(md5, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */
goto out;
if (!winpr_Digest_Update(md5, pad2, sizeof(pad2))) /* pad2 */
goto out;
if (!winpr_Digest_Update(md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */
goto out;
if (!winpr_Digest_Final(md5, md5_digest, sizeof(md5_digest)))
goto out;
memcpy(output, md5_digest, 8);
return TRUE;
result = TRUE;
out:
winpr_Digest_Free(sha1);
winpr_Digest_Free(md5);
return result;
}
BOOL security_salted_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length,
BOOL encryption, BYTE* output)
{
WINPR_MD5_CTX md5;
WINPR_SHA1_CTX sha1;
WINPR_DIGEST_CTX* sha1 = NULL;
WINPR_DIGEST_CTX* md5 = NULL;
BYTE length_le[4];
BYTE use_count_le[4];
BYTE md5_digest[WINPR_MD5_DIGEST_LENGTH];
BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH];
BOOL result = FALSE;
security_UINT32_le(length_le, length); /* length must be little-endian */
@ -336,35 +373,43 @@ BOOL security_salted_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length,
}
/* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */
if (!winpr_SHA1_Init(&sha1))
return FALSE;
if (!winpr_SHA1_Update(&sha1, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */
return FALSE;
if (!winpr_SHA1_Update(&sha1, pad1, sizeof(pad1))) /* pad1 */
return FALSE;
if (!winpr_SHA1_Update(&sha1, length_le, sizeof(length_le))) /* length */
return FALSE;
if (!winpr_SHA1_Update(&sha1, data, length)) /* data */
return FALSE;
if (!winpr_SHA1_Update(&sha1, use_count_le, sizeof(use_count_le))) /* encryptionCount */
return FALSE;
if (!winpr_SHA1_Final(&sha1, sha1_digest, sizeof(sha1_digest)))
return FALSE;
if (!(sha1 = winpr_Digest_New()))
goto out;
if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1))
goto out;
if (!winpr_Digest_Update(sha1, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */
goto out;
if (!winpr_Digest_Update(sha1, pad1, sizeof(pad1))) /* pad1 */
goto out;
if (!winpr_Digest_Update(sha1, length_le, sizeof(length_le))) /* length */
goto out;
if (!winpr_Digest_Update(sha1, data, length)) /* data */
goto out;
if (!winpr_Digest_Update(sha1, use_count_le, sizeof(use_count_le))) /* encryptionCount */
goto out;
if (!winpr_Digest_Final(sha1, sha1_digest, sizeof(sha1_digest)))
goto out;
/* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */
if (!winpr_MD5_Init(&md5))
return FALSE;
if (!winpr_MD5_Update(&md5, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */
return FALSE;
if (!winpr_MD5_Update(&md5, pad2, sizeof(pad2))) /* pad2 */
return FALSE;
if (!winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */
return FALSE;
if (!winpr_MD5_Final(&md5, md5_digest, sizeof(md5_digest)))
return FALSE;
if (!(md5 = winpr_Digest_New()))
goto out;
if (!winpr_Digest_Init(md5, WINPR_MD_MD5))
goto out;
if (!winpr_Digest_Update(md5, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */
goto out;
if (!winpr_Digest_Update(md5, pad2, sizeof(pad2))) /* pad2 */
goto out;
if (!winpr_Digest_Update(md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */
goto out;
if (!winpr_Digest_Final(md5, md5_digest, sizeof(md5_digest)))
goto out;
memcpy(output, md5_digest, 8);
return TRUE;
result = TRUE;
out:
winpr_Digest_Free(sha1);
winpr_Digest_Free(md5);
return result;
}
static BOOL security_A(BYTE* master_secret, const BYTE* client_random, BYTE* server_random,
@ -433,38 +478,43 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp)
if (settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
{
WINPR_SHA1_CTX sha1;
WINPR_DIGEST_CTX* sha1;
BYTE client_encrypt_key_t[WINPR_SHA1_DIGEST_LENGTH + 1];
BYTE client_decrypt_key_t[WINPR_SHA1_DIGEST_LENGTH + 1];
if (!winpr_SHA1_Init(&sha1))
if (!(sha1 = winpr_Digest_New()))
return FALSE;
if (!winpr_SHA1_Update(&sha1, client_random + 16, 16))
return FALSE;
if (!winpr_SHA1_Update(&sha1, server_random + 16, 16))
return FALSE;
if (!winpr_SHA1_Final(&sha1, client_encrypt_key_t, sizeof(client_encrypt_key_t)))
if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1) ||
!winpr_Digest_Update(sha1, client_random + 16, 16) ||
!winpr_Digest_Update(sha1, server_random + 16, 16) ||
!winpr_Digest_Final(sha1, client_encrypt_key_t, sizeof(client_encrypt_key_t)))
{
winpr_Digest_Free(sha1);
return FALSE;
}
client_encrypt_key_t[20] = client_encrypt_key_t[0];
if (!winpr_SHA1_Init(&sha1))
return FALSE;
if (!winpr_SHA1_Update(&sha1, client_random, 16))
return FALSE;
if (!winpr_SHA1_Update(&sha1, server_random, 16))
return FALSE;
if (!winpr_SHA1_Final(&sha1, client_decrypt_key_t, sizeof(client_decrypt_key_t)))
if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1) ||
!winpr_Digest_Update(sha1, client_random, 16) ||
!winpr_Digest_Update(sha1, server_random, 16) ||
!winpr_Digest_Final(sha1, client_decrypt_key_t, sizeof(client_decrypt_key_t)))
{
winpr_Digest_Free(sha1);
return FALSE;
}
client_decrypt_key_t[20] = client_decrypt_key_t[0];
if (!winpr_SHA1_Init(&sha1))
return FALSE;
if (!winpr_SHA1_Update(&sha1, client_decrypt_key_t, WINPR_SHA1_DIGEST_LENGTH))
return FALSE;
if (!winpr_SHA1_Update(&sha1, client_encrypt_key_t, WINPR_SHA1_DIGEST_LENGTH))
return FALSE;
if (!winpr_SHA1_Final(&sha1, rdp->fips_sign_key, WINPR_SHA1_DIGEST_LENGTH))
if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1) ||
!winpr_Digest_Update(sha1, client_decrypt_key_t, WINPR_SHA1_DIGEST_LENGTH) ||
!winpr_Digest_Update(sha1, client_encrypt_key_t, WINPR_SHA1_DIGEST_LENGTH) ||
!winpr_Digest_Final(sha1, rdp->fips_sign_key, WINPR_SHA1_DIGEST_LENGTH))
{
winpr_Digest_Free(sha1);
return FALSE;
}
winpr_Digest_Free(sha1);
if (rdp->settings->ServerMode)
{
@ -536,48 +586,56 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp)
BOOL security_key_update(BYTE* key, BYTE* update_key, int key_len, rdpRdp* rdp)
{
BYTE sha1h[WINPR_SHA1_DIGEST_LENGTH];
WINPR_MD5_CTX md5;
WINPR_SHA1_CTX sha1;
WINPR_RC4_CTX* rc4;
WINPR_DIGEST_CTX* sha1 = NULL;
WINPR_DIGEST_CTX* md5 = NULL;
WINPR_RC4_CTX* rc4 = NULL;
BOOL rc;
BYTE salt[] = { 0xD1, 0x26, 0x9E }; /* 40 bits: 3 bytes, 56 bits: 1 byte */
BOOL result = FALSE;
if (!winpr_SHA1_Init(&sha1))
return FALSE;
if (!winpr_SHA1_Update(&sha1, update_key, key_len))
return FALSE;
if (!winpr_SHA1_Update(&sha1, pad1, sizeof(pad1)))
return FALSE;
if (!winpr_SHA1_Update(&sha1, key, key_len))
return FALSE;
if (!winpr_SHA1_Final(&sha1, sha1h, sizeof(sha1h)))
return FALSE;
if (!(sha1 = winpr_Digest_New()))
goto out;
if (!winpr_Digest_Init(sha1, WINPR_MD_SHA1))
goto out;
if (!winpr_Digest_Update(sha1, update_key, key_len))
goto out;
if (!winpr_Digest_Update(sha1, pad1, sizeof(pad1)))
goto out;
if (!winpr_Digest_Update(sha1, key, key_len))
goto out;
if (!winpr_Digest_Final(sha1, sha1h, sizeof(sha1h)))
goto out;
if (!winpr_MD5_Init(&md5))
return FALSE;
if (!winpr_MD5_Update(&md5, update_key, key_len))
return FALSE;
if (!winpr_MD5_Update(&md5, pad2, sizeof(pad2)))
return FALSE;
if (!winpr_MD5_Update(&md5, sha1h, sizeof(sha1h)))
return FALSE;
if (!winpr_MD5_Final(&md5, key, WINPR_MD5_DIGEST_LENGTH))
return FALSE;
if (!(md5 = winpr_Digest_New()))
goto out;
if (!winpr_Digest_Init(md5, WINPR_MD_MD5))
goto out;
if (!winpr_Digest_Update(md5, update_key, key_len))
goto out;
if (!winpr_Digest_Update(md5, pad2, sizeof(pad2)))
goto out;
if (!winpr_Digest_Update(md5, sha1h, sizeof(sha1h)))
goto out;
if (!winpr_Digest_Final(md5, key, WINPR_MD5_DIGEST_LENGTH))
goto out;
if ((rc4 = winpr_RC4_New(key, key_len)) == NULL)
return FALSE;
rc = winpr_RC4_Update(rc4, key_len, key, key);
winpr_RC4_Free(rc4);
if (!rc)
return FALSE;
if (!(rc4 = winpr_RC4_New(key, key_len)))
goto out;
if (!winpr_RC4_Update(rc4, key_len, key, key))
goto out;
if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_40BIT)
memcpy(key, salt, 3);
else if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_56BIT)
memcpy(key, salt, 1);
return TRUE;
result = TRUE;
out:
winpr_Digest_Free(sha1);
winpr_Digest_Free(md5);
winpr_RC4_Free(rc4);
return result;
}
BOOL security_encrypt(BYTE* data, int length, rdpRdp* rdp)
@ -630,21 +688,27 @@ BOOL security_hmac_signature(const BYTE* data, int length, BYTE* output, rdpRdp*
{
BYTE buf[WINPR_SHA1_DIGEST_LENGTH];
BYTE use_count_le[4];
WINPR_HMAC_CTX* hmac;
BOOL result = FALSE;
security_UINT32_le(use_count_le, rdp->encrypt_use_count);
if (!winpr_HMAC_Init(rdp->fips_hmac, WINPR_MD_SHA1,
rdp->fips_sign_key, WINPR_SHA1_DIGEST_LENGTH))
return FALSE;
if (!winpr_HMAC_Update(rdp->fips_hmac, data, length))
return FALSE;
if (!winpr_HMAC_Update(rdp->fips_hmac, use_count_le, 4))
return FALSE;
if (!winpr_HMAC_Final(rdp->fips_hmac, buf, WINPR_SHA1_DIGEST_LENGTH))
if (!(hmac = winpr_HMAC_New()))
return FALSE;
if (!winpr_HMAC_Init(hmac, WINPR_MD_SHA1, rdp->fips_sign_key, WINPR_SHA1_DIGEST_LENGTH))
goto out;
if (!winpr_HMAC_Update(hmac, data, length))
goto out;
if (!winpr_HMAC_Update(hmac, use_count_le, 4))
goto out;
if (!winpr_HMAC_Final(hmac, buf, WINPR_SHA1_DIGEST_LENGTH))
goto out;
memmove(output, buf, 8);
return TRUE;
result = TRUE;
out:
winpr_HMAC_Free(hmac);
return result;
}
BOOL security_fips_encrypt(BYTE* data, int length, rdpRdp* rdp)
@ -670,23 +734,27 @@ BOOL security_fips_check_signature(const BYTE* data, int length, const BYTE* sig
{
BYTE buf[WINPR_SHA1_DIGEST_LENGTH];
BYTE use_count_le[4];
WINPR_HMAC_CTX* hmac;
BOOL result = FALSE;
security_UINT32_le(use_count_le, rdp->decrypt_use_count);
if (!winpr_HMAC_Init(rdp->fips_hmac, WINPR_MD_SHA1,
rdp->fips_sign_key, WINPR_SHA1_DIGEST_LENGTH))
return FALSE;
if (!winpr_HMAC_Update(rdp->fips_hmac, data, length))
return FALSE;
if (!winpr_HMAC_Update(rdp->fips_hmac, use_count_le, 4))
return FALSE;
if (!winpr_HMAC_Final(rdp->fips_hmac, buf, WINPR_SHA1_DIGEST_LENGTH))
if (!(hmac = winpr_HMAC_New()))
return FALSE;
if (!winpr_HMAC_Init(hmac, WINPR_MD_SHA1, rdp->fips_sign_key, WINPR_SHA1_DIGEST_LENGTH))
goto out;
if (!winpr_HMAC_Update(hmac, data, length))
goto out;
if (!winpr_HMAC_Update(hmac, use_count_le, 4))
goto out;
if (!winpr_HMAC_Final(hmac, buf, WINPR_SHA1_DIGEST_LENGTH))
goto out;
rdp->decrypt_use_count++;
if (memcmp(sig, buf, 8))
return FALSE;
return TRUE;
if (!memcmp(sig, buf, 8))
result = TRUE;
out:
winpr_HMAC_Free(hmac);
return result;
}

View File

@ -84,6 +84,7 @@
#include <winpr/stream.h>
#include "tcp.h"
#include "../crypto/opensslcompat.h"
#define TAG FREERDP_TAG("core")
@ -108,7 +109,7 @@ static int transport_bio_simple_write(BIO* bio, const char* buf, int size)
{
int error;
int status = 0;
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) BIO_get_data(bio);
if (!buf)
return 0;
@ -139,7 +140,7 @@ static int transport_bio_simple_read(BIO* bio, char* buf, int size)
{
int error;
int status = 0;
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) BIO_get_data(bio);
if (!buf)
return 0;
@ -189,7 +190,7 @@ static int transport_bio_simple_gets(BIO* bio, char* str, int size)
static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
{
int status = -1;
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) BIO_get_data(bio);
if (cmd == BIO_C_SET_SOCKET)
{
@ -199,7 +200,7 @@ static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
}
else if (cmd == BIO_C_GET_SOCKET)
{
if (!bio->init || !arg2)
if (!BIO_get_init(bio) || !arg2)
return 0;
*((ULONG_PTR*) arg2) = (ULONG_PTR) ptr->socket;
@ -208,7 +209,7 @@ static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
}
else if (cmd == BIO_C_GET_EVENT)
{
if (!bio->init || !arg2)
if (!BIO_get_init(bio) || !arg2)
return 0;
*((ULONG_PTR*) arg2) = (ULONG_PTR) ptr->hEvent;
@ -319,7 +320,7 @@ static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
break;
case BIO_C_GET_FD:
if (bio->init)
if (BIO_get_init(bio))
{
if (arg2)
*((int*) arg2) = (int) ptr->socket;
@ -328,11 +329,11 @@ static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
break;
case BIO_CTRL_GET_CLOSE:
status = bio->shutdown;
status = BIO_get_shutdown(bio);
break;
case BIO_CTRL_SET_CLOSE:
bio->shutdown = (int) arg1;
BIO_set_shutdown(bio, (int) arg1);
status = 1;
break;
@ -354,13 +355,13 @@ static long transport_bio_simple_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
static int transport_bio_simple_init(BIO* bio, SOCKET socket, int shutdown)
{
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) BIO_get_data(bio);
ptr->socket = socket;
bio->shutdown = shutdown;
bio->flags = BIO_FLAGS_SHOULD_RETRY;
bio->init = 1;
BIO_set_shutdown(bio, shutdown);
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
BIO_set_init(bio, 1);
ptr->hEvent = WSACreateEvent();
@ -379,11 +380,11 @@ static int transport_bio_simple_init(BIO* bio, SOCKET socket, int shutdown)
static int transport_bio_simple_uninit(BIO* bio)
{
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) bio->ptr;
WINPR_BIO_SIMPLE_SOCKET* ptr = (WINPR_BIO_SIMPLE_SOCKET*) BIO_get_data(bio);
if (bio->shutdown)
if (BIO_get_shutdown(bio))
{
if (bio->init)
if (BIO_get_init(bio))
{
_shutdown(ptr->socket, SD_BOTH);
closesocket(ptr->socket);
@ -397,8 +398,8 @@ static int transport_bio_simple_uninit(BIO* bio)
ptr->hEvent = NULL;
}
bio->init = 0;
bio->flags = 0;
BIO_set_init(bio, 0);
BIO_set_flags(bio, 0);
return 1;
}
@ -407,53 +408,57 @@ static int transport_bio_simple_new(BIO* bio)
{
WINPR_BIO_SIMPLE_SOCKET* ptr;
bio->init = 0;
bio->ptr = NULL;
bio->flags = BIO_FLAGS_SHOULD_RETRY;
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
ptr = (WINPR_BIO_SIMPLE_SOCKET*) calloc(1, sizeof(WINPR_BIO_SIMPLE_SOCKET));
if (!ptr)
return 0;
bio->ptr = ptr;
BIO_set_data(bio, ptr);
return 1;
}
static int transport_bio_simple_free(BIO* bio)
{
WINPR_BIO_SIMPLE_SOCKET* ptr;
if (!bio)
return 0;
transport_bio_simple_uninit(bio);
if (bio->ptr)
ptr = (WINPR_BIO_SIMPLE_SOCKET*) BIO_get_data(bio);
if (ptr)
{
free(bio->ptr);
bio->ptr = NULL;
BIO_set_data(bio, NULL);
free(ptr);
}
return 1;
}
static BIO_METHOD transport_bio_simple_socket_methods =
{
BIO_TYPE_SIMPLE,
"SimpleSocket",
transport_bio_simple_write,
transport_bio_simple_read,
transport_bio_simple_puts,
transport_bio_simple_gets,
transport_bio_simple_ctrl,
transport_bio_simple_new,
transport_bio_simple_free,
NULL,
};
BIO_METHOD* BIO_s_simple_socket(void)
{
return &transport_bio_simple_socket_methods;
static BIO_METHOD* bio_methods = NULL;
if (bio_methods == NULL)
{
if (!(bio_methods = BIO_meth_new(BIO_TYPE_SIMPLE, "SimpleSocket")))
return NULL;
BIO_meth_set_write(bio_methods, transport_bio_simple_write);
BIO_meth_set_read(bio_methods, transport_bio_simple_read);
BIO_meth_set_puts(bio_methods, transport_bio_simple_puts);
BIO_meth_set_gets(bio_methods, transport_bio_simple_gets);
BIO_meth_set_ctrl(bio_methods, transport_bio_simple_ctrl);
BIO_meth_set_create(bio_methods, transport_bio_simple_new);
BIO_meth_set_destroy(bio_methods, transport_bio_simple_free);
}
return bio_methods;
}
/* Buffered Socket BIO */
@ -479,7 +484,8 @@ static int transport_bio_buffered_write(BIO* bio, const char* buf, int num)
int nchunks;
int committedBytes;
DataChunk chunks[2];
WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) bio->ptr;
WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) BIO_get_data(bio);
BIO* next_bio = NULL;
ret = num;
ptr->writeBlocked = FALSE;
@ -496,23 +502,24 @@ static int transport_bio_buffered_write(BIO* bio, const char* buf, int num)
committedBytes = 0;
nchunks = ringbuffer_peek(&ptr->xmitBuffer, chunks, ringbuffer_used(&ptr->xmitBuffer));
next_bio = BIO_next(bio);
for (i = 0; i < nchunks; i++)
{
while (chunks[i].size)
{
status = BIO_write(bio->next_bio, chunks[i].data, chunks[i].size);
status = BIO_write(next_bio, chunks[i].data, chunks[i].size);
if (status <= 0)
{
if (!BIO_should_retry(bio->next_bio))
if (!BIO_should_retry(next_bio))
{
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
ret = -1; /* fatal error */
goto out;
}
if (BIO_should_write(bio->next_bio))
if (BIO_should_write(next_bio))
{
BIO_set_flags(bio, BIO_FLAGS_WRITE);
ptr->writeBlocked = TRUE;
@ -535,16 +542,17 @@ out:
static int transport_bio_buffered_read(BIO* bio, char* buf, int size)
{
int status;
WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) bio->ptr;
WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) BIO_get_data(bio);
BIO* next_bio = BIO_next(bio);
ptr->readBlocked = FALSE;
BIO_clear_flags(bio, BIO_FLAGS_READ);
status = BIO_read(bio->next_bio, buf, size);
status = BIO_read(next_bio, buf, size);
if (status <= 0)
{
if (!BIO_should_retry(bio->next_bio))
if (!BIO_should_retry(next_bio))
{
BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY);
goto out;
@ -552,7 +560,7 @@ static int transport_bio_buffered_read(BIO* bio, char* buf, int size)
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
if (BIO_should_read(bio->next_bio))
if (BIO_should_read(next_bio))
{
BIO_set_flags(bio, BIO_FLAGS_READ);
ptr->readBlocked = TRUE;
@ -577,7 +585,7 @@ static int transport_bio_buffered_gets(BIO* bio, char* str, int size)
static long transport_bio_buffered_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
{
int status = -1;
WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) bio->ptr;
WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) BIO_get_data(bio);
switch (cmd)
{
@ -605,7 +613,7 @@ static long transport_bio_buffered_ctrl(BIO* bio, int cmd, long arg1, void* arg2
break;
default:
status = BIO_ctrl(bio->next_bio, cmd, arg1, arg2);
status = BIO_ctrl(BIO_next(bio), cmd, arg1, arg2);
break;
}
@ -616,17 +624,15 @@ static int transport_bio_buffered_new(BIO* bio)
{
WINPR_BIO_BUFFERED_SOCKET* ptr;
bio->init = 1;
bio->num = 0;
bio->ptr = NULL;
bio->flags = BIO_FLAGS_SHOULD_RETRY;
BIO_set_init(bio, 1);
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
ptr = (WINPR_BIO_BUFFERED_SOCKET*) calloc(1, sizeof(WINPR_BIO_BUFFERED_SOCKET));
if (!ptr)
return -1;
bio->ptr = (void*) ptr;
BIO_set_data(bio, (void*) ptr);
if (!ringbuffer_init(&ptr->xmitBuffer, 0x10000))
return -1;
@ -636,12 +642,13 @@ static int transport_bio_buffered_new(BIO* bio)
static int transport_bio_buffered_free(BIO* bio)
{
WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) bio->ptr;
WINPR_BIO_BUFFERED_SOCKET* ptr = (WINPR_BIO_BUFFERED_SOCKET*) BIO_get_data(bio);
BIO* next_bio = BIO_next(bio);
if (bio->next_bio)
if (next_bio)
{
BIO_free(bio->next_bio);
bio->next_bio = NULL;
BIO_free(next_bio);
BIO_set_next(bio, NULL);
}
ringbuffer_destroy(&ptr->xmitBuffer);
@ -651,23 +658,25 @@ static int transport_bio_buffered_free(BIO* bio)
return 1;
}
static BIO_METHOD transport_bio_buffered_socket_methods =
{
BIO_TYPE_BUFFERED,
"BufferedSocket",
transport_bio_buffered_write,
transport_bio_buffered_read,
transport_bio_buffered_puts,
transport_bio_buffered_gets,
transport_bio_buffered_ctrl,
transport_bio_buffered_new,
transport_bio_buffered_free,
NULL,
};
BIO_METHOD* BIO_s_buffered_socket(void)
{
return &transport_bio_buffered_socket_methods;
static BIO_METHOD* bio_methods = NULL;
if (bio_methods == NULL)
{
if (!(bio_methods = BIO_meth_new(BIO_TYPE_BUFFERED, "BufferedSocket")))
return NULL;
BIO_meth_set_write(bio_methods, transport_bio_buffered_write);
BIO_meth_set_read(bio_methods, transport_bio_buffered_read);
BIO_meth_set_puts(bio_methods, transport_bio_buffered_puts);
BIO_meth_set_gets(bio_methods, transport_bio_buffered_gets);
BIO_meth_set_ctrl(bio_methods, transport_bio_buffered_ctrl);
BIO_meth_set_create(bio_methods, transport_bio_buffered_new);
BIO_meth_set_destroy(bio_methods, transport_bio_buffered_free);
}
return bio_methods;
}
char* freerdp_tcp_get_ip_address(int sockfd)

View File

@ -26,7 +26,8 @@ freerdp_module_add(
base64.c
certificate.c
crypto.c
tls.c)
tls.c
opensslcompat.c)
freerdp_include_directory_add(${OPENSSL_INCLUDE_DIR})

View File

@ -98,11 +98,12 @@ static int crypto_rsa_common(const BYTE* input, int length, UINT32 key_length, c
BYTE* input_reverse;
BYTE* modulus_reverse;
BYTE* exponent_reverse;
BIGNUM mod, exp, x, y;
BIGNUM *mod, *exp, *x, *y;
input_reverse = (BYTE*) malloc(2 * key_length + exponent_size);
if (!input_reverse)
return -1;
modulus_reverse = input_reverse + key_length;
exponent_reverse = modulus_reverse + key_length;
@ -113,32 +114,42 @@ static int crypto_rsa_common(const BYTE* input, int length, UINT32 key_length, c
memcpy(input_reverse, input, length);
crypto_reverse(input_reverse, length);
ctx = BN_CTX_new();
if (!ctx)
goto out_free_input_reverse;
BN_init(&mod);
BN_init(&exp);
BN_init(&x);
BN_init(&y);
if (!(ctx = BN_CTX_new()))
goto fail_bn_ctx;
BN_bin2bn(modulus_reverse, key_length, &mod);
BN_bin2bn(exponent_reverse, exponent_size, &exp);
BN_bin2bn(input_reverse, length, &x);
BN_mod_exp(&y, &x, &exp, &mod, ctx);
if (!(mod = BN_new()))
goto fail_bn_mod;
output_length = BN_bn2bin(&y, output);
if (!(exp = BN_new()))
goto fail_bn_exp;
if (!(x = BN_new()))
goto fail_bn_x;
if (!(y = BN_new()))
goto fail_bn_y;
BN_bin2bn(modulus_reverse, key_length, mod);
BN_bin2bn(exponent_reverse, exponent_size, exp);
BN_bin2bn(input_reverse, length, x);
BN_mod_exp(y, x, exp, mod, ctx);
output_length = BN_bn2bin(y, output);
crypto_reverse(output, output_length);
if (output_length < (int) key_length)
memset(output + output_length, 0, key_length - output_length);
BN_free(&y);
BN_clear_free(&x);
BN_free(&exp);
BN_free(&mod);
BN_free(y);
fail_bn_y:
BN_clear_free(x);
fail_bn_x:
BN_free(exp);
fail_bn_exp:
BN_free(mod);
fail_bn_mod:
BN_CTX_free(ctx);
out_free_input_reverse:
fail_bn_ctx:
free(input_reverse);
return output_length;

View File

@ -0,0 +1,44 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* OpenSSL Compatibility
*
* Copyright (C) 2016 Norbert Federa <norbert.federa@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "opensslcompat.h"
#if OPENSSL_VERSION_NUMBER < 0x10100000L
BIO_METHOD* BIO_meth_new(int type, const char* name)
{
BIO_METHOD* m;
if (!(m = calloc(1, sizeof(BIO_METHOD))))
return NULL;
m->type = type;
m->name = name;
return m;
}
void RSA_get0_key(const RSA* r, const BIGNUM** n, const BIGNUM** e, const BIGNUM** d)
{
if (n != NULL)
*n = r->n;
if (e != NULL)
*e = r->e;
if (d != NULL)
*d = r->d;
}
#endif /* OPENSSL < 1.1.0 */

View File

@ -0,0 +1,65 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* OpenSSL Compatibility
*
* Copyright (C) 2016 Norbert Federa <norbert.federa@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_CRYPTO_OPENSSLCOMPAT_H
#define FREERDP_CRYPTO_OPENSSLCOMPAT_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <freerdp/api.h>
#ifdef WITH_OPENSSL
#include <openssl/opensslv.h>
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#include <openssl/bio.h>
#include <openssl/rsa.h>
#include <openssl/bn.h>
#define BIO_get_data(b) (b)->ptr
#define BIO_set_data(b,v) (b)->ptr = v
#define BIO_get_init(b) (b)->init
#define BIO_set_init(b,v) (b)->init = v
#define BIO_get_next(b,v) (b)->next_bio
#define BIO_set_next(b,v) (b)->next_bio = v
#define BIO_get_shutdown(b) (b)->shutdown
#define BIO_set_shutdown(b,v) (b)->shutdown = v
#define BIO_get_retry_reason(b) (b)->retry_reason
#define BIO_set_retry_reason(b,v) (b)->retry_reason = v
#define BIO_meth_set_write(b,f) (b)->bwrite = (f)
#define BIO_meth_set_read(b,f) (b)->bread = (f)
#define BIO_meth_set_puts(b,f) (b)->bputs = (f)
#define BIO_meth_set_gets(b,f) (b)->bgets = (f)
#define BIO_meth_set_ctrl(b,f) (b)->ctrl = (f)
#define BIO_meth_set_create(b,f) (b)->create = (f)
#define BIO_meth_set_destroy(b,f) (b)->destroy = (f)
#define BIO_meth_set_callback_ctrl(b,f) (b)->callback_ctrl = (f)
BIO_METHOD* BIO_meth_new(int type, const char* name);
void RSA_get0_key(const RSA* r, const BIGNUM** n, const BIGNUM** e, const BIGNUM** d);
#endif /* OPENSSL < 1.1.0 */
#endif /* WITH_OPENSSL */
#endif /* FREERDP_CRYPTO_OPENSSLCOMPAT_H */

View File

@ -34,6 +34,7 @@
#include <freerdp/log.h>
#include <freerdp/crypto/tls.h>
#include "../core/tcp.h"
#include "opensslcompat.h"
#ifdef HAVE_POLL_H
#include <poll.h>
@ -45,6 +46,30 @@
#define TAG FREERDP_TAG("crypto")
/**
* Earlier Microsoft iOS RDP clients have sent a null or even double null
* terminated hostname in the SNI TLS extension.
* If the length indicator does not equal the hostname strlen OpenSSL
* will abort (see openssl:ssl/t1_lib.c).
* Here is a tcpdump segment of Microsoft Remote Desktop Client Version
* 8.1.7 running on an iPhone 4 with iOS 7.1.2 showing the transmitted
* SNI hostname TLV blob when connection to server "abcd":
* 00 name_type 0x00 (host_name)
* 00 06 length_in_bytes 0x0006
* 61 62 63 64 00 00 host_name "abcd\0\0"
*
* Currently the only (runtime) workaround is setting an openssl tls
* extension debug callback that sets the SSL context's servername_done
* to 1 which effectively disables the parsing of that extension type.
*
* Nowadays this workaround is not required anymore but still can be
* activated by adding the following define:
*
* #define MICROSOFT_IOS_SNI_BUG
*/
struct _BIO_RDP_TLS
{
SSL* ssl;
@ -62,7 +87,7 @@ static int bio_rdp_tls_write(BIO* bio, const char* buf, int size)
{
int error;
int status;
BIO_RDP_TLS* tls = (BIO_RDP_TLS*) bio->ptr;
BIO_RDP_TLS* tls = (BIO_RDP_TLS*) BIO_get_data(bio);
if (!buf || !tls)
return 0;
@ -91,12 +116,12 @@ static int bio_rdp_tls_write(BIO* bio, const char* buf, int size)
case SSL_ERROR_WANT_X509_LOOKUP:
BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
bio->retry_reason = BIO_RR_SSL_X509_LOOKUP;
BIO_set_retry_reason(bio, BIO_RR_SSL_X509_LOOKUP);
break;
case SSL_ERROR_WANT_CONNECT:
BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
bio->retry_reason = BIO_RR_CONNECT;
BIO_set_retry_reason(bio, BIO_RR_CONNECT);
break;
case SSL_ERROR_SYSCALL:
@ -116,7 +141,7 @@ static int bio_rdp_tls_read(BIO* bio, char* buf, int size)
{
int error;
int status;
BIO_RDP_TLS* tls = (BIO_RDP_TLS*) bio->ptr;
BIO_RDP_TLS* tls = (BIO_RDP_TLS*) BIO_get_data(bio);
if (!buf || !tls)
return 0;
@ -145,17 +170,17 @@ static int bio_rdp_tls_read(BIO* bio, char* buf, int size)
case SSL_ERROR_WANT_X509_LOOKUP:
BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
bio->retry_reason = BIO_RR_SSL_X509_LOOKUP;
BIO_set_retry_reason(bio, BIO_RR_SSL_X509_LOOKUP);
break;
case SSL_ERROR_WANT_ACCEPT:
BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
bio->retry_reason = BIO_RR_ACCEPT;
BIO_set_retry_reason(bio, BIO_RR_ACCEPT);
break;
case SSL_ERROR_WANT_CONNECT:
BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL);
bio->retry_reason = BIO_RR_CONNECT;
BIO_set_retry_reason(bio, BIO_RR_CONNECT);
break;
case SSL_ERROR_SSL:
@ -203,9 +228,12 @@ static int bio_rdp_tls_gets(BIO* bio, char* str, int size)
static long bio_rdp_tls_ctrl(BIO* bio, int cmd, long num, void* ptr)
{
BIO* rbio;
BIO* ssl_rbio;
BIO* ssl_wbio;
BIO* next_bio;
int status = -1;
BIO_RDP_TLS* tls = (BIO_RDP_TLS*) bio->ptr;
BIO_RDP_TLS* tls = (BIO_RDP_TLS*) BIO_get_data(bio);
if (!tls)
return 0;
@ -213,29 +241,33 @@ static long bio_rdp_tls_ctrl(BIO* bio, int cmd, long num, void* ptr)
if (!tls->ssl && (cmd != BIO_C_SET_SSL))
return 0;
next_bio = BIO_next(bio);
ssl_rbio = tls->ssl ? SSL_get_rbio(tls->ssl) : NULL;
ssl_wbio = tls->ssl ? SSL_get_wbio(tls->ssl) : NULL;
switch (cmd)
{
case BIO_CTRL_RESET:
SSL_shutdown(tls->ssl);
if (tls->ssl->handshake_func == tls->ssl->method->ssl_connect)
if (SSL_in_connect_init(tls->ssl))
SSL_set_connect_state(tls->ssl);
else if (tls->ssl->handshake_func == tls->ssl->method->ssl_accept)
else if (SSL_in_accept_init(tls->ssl))
SSL_set_accept_state(tls->ssl);
SSL_clear(tls->ssl);
if (bio->next_bio)
status = BIO_ctrl(bio->next_bio, cmd, num, ptr);
else if (tls->ssl->rbio)
status = BIO_ctrl(tls->ssl->rbio, cmd, num, ptr);
if (next_bio)
status = BIO_ctrl(next_bio, cmd, num, ptr);
else if (ssl_rbio)
status = BIO_ctrl(ssl_rbio, cmd, num, ptr);
else
status = 1;
break;
case BIO_C_GET_FD:
status = BIO_ctrl(tls->ssl->rbio, cmd, num, ptr);
status = BIO_ctrl(ssl_rbio, cmd, num, ptr);
break;
case BIO_CTRL_INFO:
@ -261,53 +293,67 @@ static long bio_rdp_tls_ctrl(BIO* bio, int cmd, long num, void* ptr)
break;
case BIO_CTRL_GET_CLOSE:
status = bio->shutdown;
status = BIO_get_shutdown(bio);
break;
case BIO_CTRL_SET_CLOSE:
bio->shutdown = (int) num;
BIO_set_shutdown(bio, (int) num);
status = 1;
break;
case BIO_CTRL_WPENDING:
status = BIO_ctrl(tls->ssl->wbio, cmd, num, ptr);
status = BIO_ctrl(ssl_wbio, cmd, num, ptr);
break;
case BIO_CTRL_PENDING:
status = SSL_pending(tls->ssl);
if (status == 0)
status = BIO_pending(tls->ssl->rbio);
status = BIO_pending(ssl_rbio);
break;
case BIO_CTRL_FLUSH:
BIO_clear_retry_flags(bio);
status = BIO_ctrl(tls->ssl->wbio, cmd, num, ptr);
status = BIO_ctrl(ssl_wbio, cmd, num, ptr);
BIO_copy_next_retry(bio);
status = 1;
break;
case BIO_CTRL_PUSH:
if (bio->next_bio && (bio->next_bio != tls->ssl->rbio))
if (next_bio && (next_bio != ssl_rbio))
{
SSL_set_bio(tls->ssl, bio->next_bio, bio->next_bio);
#if OPENSSL_VERSION_NUMBER < 0x10100000L
SSL_set_bio(tls->ssl, next_bio, next_bio);
CRYPTO_add(&(bio->next_bio->references), 1, CRYPTO_LOCK_BIO);
#else
/*
* We are going to pass ownership of next to the SSL object...but
* we don't own a reference to pass yet - so up ref
*/
BIO_up_ref(next_bio);
SSL_set_bio(tls->ssl, next_bio, next_bio);
#endif
}
status = 1;
break;
case BIO_CTRL_POP:
/* Only detach if we are the BIO explicitly being popped */
if (bio == ptr)
{
if (tls->ssl->rbio != tls->ssl->wbio)
BIO_free_all(tls->ssl->wbio);
if (ssl_rbio != ssl_wbio)
BIO_free_all(ssl_wbio);
if (bio->next_bio)
#if OPENSSL_VERSION_NUMBER < 0x10100000L
if (next_bio)
CRYPTO_add(&(bio->next_bio->references), -1, CRYPTO_LOCK_BIO);
tls->ssl->wbio = tls->ssl->rbio = NULL;
#else
/* OpenSSL 1.1: This will also clear the reference we obtained during push */
SSL_set_bio(tls->ssl, NULL, NULL);
#endif
}
status = 1;
@ -323,29 +369,36 @@ static long bio_rdp_tls_ctrl(BIO* bio, int cmd, long num, void* ptr)
break;
case BIO_C_SET_SSL:
bio->shutdown = (int) num;
BIO_set_shutdown(bio, (int) num);
if (ptr)
tls->ssl = (SSL*) ptr;
rbio = SSL_get_rbio(tls->ssl);
if (rbio)
{
if (bio->next_bio)
BIO_push(rbio, bio->next_bio);
bio->next_bio = rbio;
CRYPTO_add(&(rbio->references), 1, CRYPTO_LOCK_BIO);
tls->ssl = (SSL*) ptr;
ssl_rbio = SSL_get_rbio(tls->ssl);
ssl_wbio = SSL_get_wbio(tls->ssl);
}
bio->init = 1;
if (ssl_rbio)
{
if (next_bio)
BIO_push(ssl_rbio, next_bio);
BIO_set_next(bio, ssl_rbio);
#if OPENSSL_VERSION_NUMBER < 0x10100000L
CRYPTO_add(&(ssl_rbio->references), 1, CRYPTO_LOCK_BIO);
#else
BIO_up_ref(ssl_rbio);
#endif
}
BIO_set_init(bio, 1);
status = 1;
break;
case BIO_C_DO_STATE_MACHINE:
BIO_clear_flags(bio, BIO_FLAGS_READ | BIO_FLAGS_WRITE | BIO_FLAGS_IO_SPECIAL);
bio->retry_reason = 0;
BIO_set_retry_reason(bio, 0);
status = SSL_do_handshake(tls->ssl);
if (status <= 0)
@ -362,7 +415,7 @@ static long bio_rdp_tls_ctrl(BIO* bio, int cmd, long num, void* ptr)
case SSL_ERROR_WANT_CONNECT:
BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL | BIO_FLAGS_SHOULD_RETRY);
bio->retry_reason = bio->next_bio->retry_reason;
BIO_set_retry_reason(bio, BIO_get_retry_reason(next_bio));
break;
default:
@ -374,7 +427,7 @@ static long bio_rdp_tls_ctrl(BIO* bio, int cmd, long num, void* ptr)
break;
default:
status = BIO_ctrl(tls->ssl->rbio, cmd, num, ptr);
status = BIO_ctrl(ssl_rbio, cmd, num, ptr);
break;
}
@ -384,17 +437,16 @@ static long bio_rdp_tls_ctrl(BIO* bio, int cmd, long num, void* ptr)
static int bio_rdp_tls_new(BIO* bio)
{
BIO_RDP_TLS* tls;
bio->init = 0;
bio->num = 0;
bio->flags = BIO_FLAGS_SHOULD_RETRY;
bio->next_bio = NULL;
tls = calloc(1, sizeof(BIO_RDP_TLS));
if (!tls)
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
if (!(tls = calloc(1, sizeof(BIO_RDP_TLS))))
return 0;
bio->ptr = (void*) tls;
InitializeCriticalSectionAndSpinCount(&tls->lock, 4000);
BIO_set_data(bio, (void*) tls);
return 1;
}
@ -405,21 +457,20 @@ static int bio_rdp_tls_free(BIO* bio)
if (!bio)
return 0;
tls = (BIO_RDP_TLS*) bio->ptr;
tls = (BIO_RDP_TLS*) BIO_get_data(bio);
if (!tls)
return 0;
if (bio->shutdown)
if (BIO_get_shutdown(bio))
{
if (bio->init && tls->ssl)
if (BIO_get_init(bio) && tls->ssl)
{
SSL_shutdown(tls->ssl);
SSL_free(tls->ssl);
}
bio->init = 0;
bio->flags = 0;
BIO_set_init(bio, 0);
BIO_set_flags(bio, 0);
}
DeleteCriticalSection(&tls->lock);
@ -435,7 +486,7 @@ static long bio_rdp_tls_callback_ctrl(BIO* bio, int cmd, bio_info_cb* fp)
if (!bio)
return 0;
tls = (BIO_RDP_TLS*) bio->ptr;
tls = (BIO_RDP_TLS*) BIO_get_data(bio);
if (!tls)
return 0;
@ -448,7 +499,7 @@ static long bio_rdp_tls_callback_ctrl(BIO* bio, int cmd, bio_info_cb* fp)
break;
default:
status = BIO_callback_ctrl(tls->ssl->rbio, cmd, fp);
status = BIO_callback_ctrl(SSL_get_rbio(tls->ssl), cmd, fp);
break;
}
@ -457,23 +508,26 @@ static long bio_rdp_tls_callback_ctrl(BIO* bio, int cmd, bio_info_cb* fp)
#define BIO_TYPE_RDP_TLS 68
static BIO_METHOD bio_rdp_tls_methods =
{
BIO_TYPE_RDP_TLS,
"RdpTls",
bio_rdp_tls_write,
bio_rdp_tls_read,
bio_rdp_tls_puts,
bio_rdp_tls_gets,
bio_rdp_tls_ctrl,
bio_rdp_tls_new,
bio_rdp_tls_free,
bio_rdp_tls_callback_ctrl,
};
BIO_METHOD* BIO_s_rdp_tls(void)
{
return &bio_rdp_tls_methods;
static BIO_METHOD* bio_methods = NULL;
if (bio_methods == NULL)
{
if (!(bio_methods = BIO_meth_new(BIO_TYPE_RDP_TLS, "RdpTls")))
return NULL;
BIO_meth_set_write(bio_methods, bio_rdp_tls_write);
BIO_meth_set_read(bio_methods, bio_rdp_tls_read);
BIO_meth_set_puts(bio_methods, bio_rdp_tls_puts);
BIO_meth_set_gets(bio_methods, bio_rdp_tls_gets);
BIO_meth_set_ctrl(bio_methods, bio_rdp_tls_ctrl);
BIO_meth_set_create(bio_methods, bio_rdp_tls_new);
BIO_meth_set_destroy(bio_methods, bio_rdp_tls_free);
BIO_meth_set_callback_ctrl(bio_methods, bio_rdp_tls_callback_ctrl);
}
return bio_methods;
}
BIO* BIO_new_rdp_tls(SSL_CTX* ctx, int client)
@ -805,11 +859,10 @@ int tls_connect(rdpTls* tls, BIO* underlying)
return tls_do_handshake(tls, TRUE);
}
#ifndef OPENSSL_NO_TLSEXT
#if defined(MICROSOFT_IOS_SNI_BUG) && !defined(OPENSSL_NO_TLSEXT)
static void tls_openssl_tlsext_debug_callback(SSL* s, int client_server,
int type, unsigned char* data, int len, void* arg)
{
/* see code comment in tls_accept() below */
if (type == TLSEXT_TYPE_server_name)
{
WLog_DBG(TAG, "Client uses SNI (extension disabled)");
@ -949,23 +1002,7 @@ BOOL tls_accept(rdpTls* tls, BIO* underlying, rdpSettings* settings)
return FALSE;
}
#ifndef OPENSSL_NO_TLSEXT
/**
* The Microsoft iOS clients eventually send a null or even double null
* terminated hostname in the SNI TLS extension!
* If the length indicator does not equal the hostname strlen OpenSSL
* will abort (see openssl:ssl/t1_lib.c).
* Here is a tcpdump segment of Microsoft Remote Desktop Client Version
* 8.1.7 running on an iPhone 4 with iOS 7.1.2 showing the transmitted
* SNI hostname TLV blob when connection to server "abcd":
* 00 name_type 0x00 (host_name)
* 00 06 length_in_bytes 0x0006
* 61 62 63 64 00 00 host_name "abcd\0\0"
*
* Currently the only (runtime) workaround is setting an openssl tls
* extension debug callback that sets the SSL context's servername_done
* to 1 which effectively disables the parsing of that extension type.
*/
#if defined(MICROSOFT_IOS_SNI_BUG) && !defined(OPENSSL_NO_TLSEXT)
SSL_set_tlsext_debug_callback(tls->ssl, tls_openssl_tlsext_debug_callback);
#endif
return tls_do_handshake(tls, FALSE) > 0;
@ -979,6 +1016,12 @@ BOOL tls_send_alert(rdpTls* tls)
if (!tls->ssl)
return TRUE;
/**
* FIXME: The following code does not work on OpenSSL > 1.1.0 because the
* SSL struct is opaqe now
*/
#if OPENSSL_VERSION_NUMBER < 0x10100000L
if (tls->alertDescription != TLS_ALERT_DESCRIPTION_CLOSE_NOTIFY)
{
/**
@ -990,10 +1033,13 @@ BOOL tls_send_alert(rdpTls* tls)
* Manually sending a TLS alert is necessary in certain cases,
* like when server-side NLA results in an authentication failure.
*/
SSL_SESSION* ssl_session = SSL_get_session(tls->ssl);
SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(tls->ssl);
SSL_set_quiet_shutdown(tls->ssl, 1);
if ((tls->alertLevel == TLS_ALERT_LEVEL_FATAL) && (tls->ssl->session))
SSL_CTX_remove_session(tls->ssl->ctx, tls->ssl->session);
if ((tls->alertLevel == TLS_ALERT_LEVEL_FATAL) && (ssl_session))
SSL_CTX_remove_session(ssl_ctx, ssl_session);
tls->ssl->s3->alert_dispatch = 1;
tls->ssl->s3->send_alert[0] = tls->alertLevel;
@ -1002,6 +1048,7 @@ BOOL tls_send_alert(rdpTls* tls)
if (tls->ssl->s3->wbuf.left == 0)
tls->ssl->method->ssl_dispatch_alert(tls->ssl);
}
#endif
return TRUE;
}
@ -1015,7 +1062,7 @@ BIO* findBufferedBio(BIO* front)
if (BIO_method_type(ret) == BIO_TYPE_BUFFERED)
return ret;
ret = ret->next_bio;
ret = BIO_next(ret);
}
return ret;

View File

@ -614,134 +614,10 @@ BOOL CryptBinaryToStringA(CONST BYTE* pbBinary, DWORD cbBinary, DWORD dwFlags, L
* Custom Crypto API Abstraction Layer
*/
/**
* MD5 hashing
*/
struct _OPENSSL_MD5_CTX
{
UINT32 A, B, C, D;
UINT32 Nl, Nh;
UINT32 data[16];
UINT32 num;
};
typedef struct _OPENSSL_MD5_CTX OPENSSL_MD5_CTX;
struct _MBEDTLS_MD5_CTX
{
UINT32 total[2];
UINT32 state[4];
BYTE buffer[64];
};
typedef struct _MBEDTLS_MD5_CTX MBEDTLS_MD5_CTX;
union _WINPR_MD5_CTX
{
OPENSSL_MD5_CTX openssl;
MBEDTLS_MD5_CTX mbedtls;
};
typedef union _WINPR_MD5_CTX WINPR_MD5_CTX;
#define WINPR_MD5_DIGEST_LENGTH 16
#ifdef __cplusplus
extern "C" {
#endif
WINPR_API BOOL winpr_MD5_Init(WINPR_MD5_CTX* ctx);
WINPR_API BOOL winpr_MD5_Update(WINPR_MD5_CTX* ctx, const BYTE* input, size_t ilen);
WINPR_API BOOL winpr_MD5_Final(WINPR_MD5_CTX* ctx, BYTE* output, size_t ilen);
WINPR_API BOOL winpr_MD5(const BYTE* input, size_t ilen, BYTE* output, size_t olen);
#ifdef __cplusplus
}
#endif
/**
* MD4 hashing
*/
struct _OPENSSL_MD4_CTX
{
UINT32 A, B, C, D;
UINT32 Nl, Nh;
UINT32 data[16];
UINT32 num;
};
typedef struct _OPENSSL_MD4_CTX OPENSSL_MD4_CTX;
struct _MBEDTLS_MD4_CTX
{
UINT32 total[2];
UINT32 state[4];
BYTE buffer[64];
};
typedef struct _MBEDTLS_MD4_CTX MBEDTLS_MD4_CTX;
union _WINPR_MD4_CTX
{
OPENSSL_MD4_CTX openssl;
MBEDTLS_MD4_CTX mbedtls;
};
typedef union _WINPR_MD4_CTX WINPR_MD4_CTX;
#define WINPR_MD4_DIGEST_LENGTH 16
#define WINPR_MD5_DIGEST_LENGTH 16
#define WINPR_SHA1_DIGEST_LENGTH 20
#ifdef __cplusplus
extern "C" {
#endif
WINPR_API BOOL winpr_MD4_Init(WINPR_MD4_CTX* ctx);
WINPR_API BOOL winpr_MD4_Update(WINPR_MD4_CTX* ctx, const BYTE* input, size_t ilen);
WINPR_API BOOL winpr_MD4_Final(WINPR_MD4_CTX* ctx, BYTE* output, size_t ilen);
WINPR_API BOOL winpr_MD4(const BYTE* input, size_t ilen, BYTE* output, size_t olen);
#ifdef __cplusplus
}
#endif
/**
* SHA1 Hashing
*/
#define WINPR_SHA1_DIGEST_LENGTH 20
struct _OPENSSL_SHA1_CTX
{
UINT32 h0, h1, h2, h3, h4;
UINT32 Nl, Nh;
UINT32 data[16];
UINT32 num;
};
typedef struct _OPENSSL_SHA1_CTX OPENSSL_SHA1_CTX;
struct _MBEDTLS_SHA1_CTX
{
UINT32 total[2];
UINT32 state[5];
BYTE buffer[64];
};
typedef struct _MBEDTLS_SHA1_CTX MBEDTLS_SHA1_CTX;
union _WINPR_SHA1_CTX
{
OPENSSL_SHA1_CTX openssl;
MBEDTLS_SHA1_CTX mbedtls;
};
typedef union _WINPR_SHA1_CTX WINPR_SHA1_CTX;
#ifdef __cplusplus
extern "C" {
#endif
WINPR_API BOOL winpr_SHA1_Init(WINPR_SHA1_CTX* ctx);
WINPR_API BOOL winpr_SHA1_Update(WINPR_SHA1_CTX* ctx, const BYTE* input, size_t ilen);
WINPR_API BOOL winpr_SHA1_Final(WINPR_SHA1_CTX* ctx, BYTE* output, size_t ilen);
WINPR_API BOOL winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output, size_t olen);
#ifdef __cplusplus
}
#endif
/**
* HMAC
@ -760,50 +636,17 @@ typedef enum
WINPR_MD_RIPEMD160 = 9
} WINPR_MD_TYPE;
struct _OPENSSL_EVP_MD_CTX
{
const void* digest;
void* engine;
unsigned long flags;
void* md_data;
void* pctx;
void* update;
};
typedef struct _OPENSSL_EVP_MD_CTX OPENSSL_EVP_MD_CTX;
struct _OPENSSL_HMAC_CTX
{
const void* md;
OPENSSL_EVP_MD_CTX md_ctx;
OPENSSL_EVP_MD_CTX i_ctx;
OPENSSL_EVP_MD_CTX o_ctx;
unsigned int key_length;
unsigned char key[128];
};
typedef struct _OPENSSL_HMAC_CTX OPENSSL_HMAC_CTX;
struct _MBEDTLS_HMAC_CTX
{
const void* md_info;
void* md_ctx;
void* hmac_ctx;
};
typedef struct _MBEDTLS_HMAC_CTX MBEDTLS_HMAC_CTX;
union _WINPR_HMAC_CTX
{
OPENSSL_HMAC_CTX openssl;
MBEDTLS_HMAC_CTX mbedtls;
};
typedef union _WINPR_HMAC_CTX WINPR_HMAC_CTX;
typedef struct _winpr_hmac_ctx_private_st WINPR_HMAC_CTX;
#ifdef __cplusplus
extern "C" {
#endif
WINPR_API BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const BYTE* key, size_t keylen);
WINPR_API WINPR_HMAC_CTX* winpr_HMAC_New(void);
WINPR_API BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const BYTE* key, size_t keylen);
WINPR_API BOOL winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const BYTE* input, size_t ilen);
WINPR_API BOOL winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, BYTE* output, size_t ilen);
WINPR_API void winpr_HMAC_Free(WINPR_HMAC_CTX* ctx);
WINPR_API BOOL winpr_HMAC(WINPR_MD_TYPE md, const BYTE* key, size_t keylen,
const BYTE* input, size_t ilen, BYTE* output, size_t olen);
@ -815,41 +658,17 @@ WINPR_API BOOL winpr_HMAC(WINPR_MD_TYPE md, const BYTE* key, size_t keylen,
* Generic Digest API
*/
struct _OPENSSL_DIGEST_CTX
{
const void* digest;
void* engine;
unsigned long flags;
void* md_data;
void* pctx;
void* update;
BYTE winpr_pad[8];
};
typedef struct _OPENSSL_DIGEST_CTX OPENSSL_DIGEST_CTX;
struct _MBEDTLS_DIGEST_CTX
{
const void* md_info;
void* md_ctx;
void* hmac_ctx;
BYTE winpr_pad[8];
};
typedef struct _MBEDTLS_DIGEST_CTX MBEDTLS_DIGEST_CTX;
union _WINPR_DIGEST_CTX
{
OPENSSL_DIGEST_CTX openssl;
MBEDTLS_DIGEST_CTX mbedtls;
};
typedef union _WINPR_DIGEST_CTX WINPR_DIGEST_CTX;
typedef struct _winpr_digest_ctx_private_st WINPR_DIGEST_CTX;
#ifdef __cplusplus
extern "C" {
#endif
WINPR_API WINPR_DIGEST_CTX* winpr_Digest_New(void);
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(int md, const BYTE* input, size_t ilen, BYTE* output, size_t olen);
#ifdef __cplusplus
@ -875,27 +694,7 @@ WINPR_API int winpr_RAND_pseudo(BYTE* output, size_t len);
* RC4
*/
struct _OPENSSL_RC4_CTX
{
int x, y;
int data[256];
};
typedef struct _OPENSSL_RC4_CTX OPENSSL_RC4_CTX;
struct _MBEDTLS_RC4_CTX
{
int x;
int y;
BYTE m[256];
};
typedef struct _MBEDTLS_RC4_CTX MBEDTLS_RC4_CTX;
union _WINPR_RC4_CTX
{
OPENSSL_RC4_CTX openssl;
MBEDTLS_RC4_CTX mbedtls;
};
typedef union _WINPR_RC4_CTX WINPR_RC4_CTX;
typedef struct _winpr_rc4_ctx_private_st WINPR_RC4_CTX;
#ifdef __cplusplus
extern "C" {
@ -970,49 +769,7 @@ WINPR_API void winpr_RC4_Free(WINPR_RC4_CTX* ctx);
#define WINPR_CIPHER_CAMELLIA_192_CCM 47
#define WINPR_CIPHER_CAMELLIA_256_CCM 48
struct _OPENSSL_CIPHER_CTX
{
const void* cipher;
void* engine;
int encrypt;
int buf_len;
BYTE oiv[16];
BYTE iv[16];
BYTE buf[32];
int num;
void* app_data;
int key_len;
unsigned long flags;
void* cipher_data;
int final_used;
int block_mask;
BYTE final[32];
BYTE winpr_pad[32];
};
typedef struct _OPENSSL_CIPHER_CTX OPENSSL_CIPHER_CTX;
struct _MBEDTLS_CIPHER_CTX
{
const void* cipher_info;
int key_bitlen;
int operation;
void* add_padding;
int* get_padding;
BYTE unprocessed_data[16];
size_t unprocessed_len;
BYTE iv[16];
size_t iv_size;
void* cipher_ctx;
BYTE winpr_pad[32];
};
typedef struct _MBEDTLS_CIPHER_CTX MBEDTLS_CIPHER_CTX;
union _WINPR_CIPHER_CTX
{
OPENSSL_CIPHER_CTX openssl;
MBEDTLS_CIPHER_CTX mbedtls;
};
typedef union _WINPR_CIPHER_CTX WINPR_CIPHER_CTX;
typedef struct _winpr_cipher_ctx_private_st WINPR_CIPHER_CTX;
#ifdef __cplusplus
extern "C" {
@ -1035,7 +792,7 @@ WINPR_API void winpr_Cipher_Free(WINPR_CIPHER_CTX* ctx);
extern "C" {
#endif
WINPR_API int winpr_openssl_BytesToKey(int cipher, int md, const BYTE* salt, const BYTE* data, int datal, int count, BYTE* key, BYTE* iv);
WINPR_API int winpr_Cipher_BytesToKey(int cipher, int md, const BYTE* salt, const BYTE* data, int datal, int count, BYTE* key, BYTE* iv);
#ifdef __cplusplus
}

View File

@ -50,13 +50,14 @@ WINPR_RC4_CTX* winpr_RC4_New(const BYTE* key, size_t keylen)
if (!key || (keylen == 0))
return NULL;
ctx = calloc(1, sizeof(WINPR_RC4_CTX));
if (!ctx)
return NULL;
#if defined(WITH_OPENSSL)
if (!(ctx = (WINPR_RC4_CTX*) calloc(1, sizeof(RC4_KEY))))
return NULL;
RC4_set_key((RC4_KEY*) ctx, keylen, key);
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C)
if (!(ctx = (WINPR_RC4_CTX*) calloc(1, sizeof(mbedtls_arc4_context))))
return NULL;
mbedtls_arc4_init((mbedtls_arc4_context*) ctx);
mbedtls_arc4_setup((mbedtls_arc4_context*) ctx, key, (unsigned int) keylen);
#endif
@ -67,12 +68,13 @@ BOOL winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE
{
#if defined(WITH_OPENSSL)
RC4((RC4_KEY*) ctx, length, input, output);
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C)
if (mbedtls_arc4_crypt((mbedtls_arc4_context*) ctx, length, input, output) != 0)
return FALSE;
#endif
return TRUE;
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C)
if (mbedtls_arc4_crypt((mbedtls_arc4_context*) ctx, length, input, output) == 0)
return TRUE;
#endif
return FALSE;
}
void winpr_RC4_Free(WINPR_RC4_CTX* ctx)
@ -81,11 +83,13 @@ void winpr_RC4_Free(WINPR_RC4_CTX* ctx)
return;
#if defined(WITH_OPENSSL)
memset(ctx, 0, sizeof(RC4_KEY));
free(ctx);
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C)
mbedtls_arc4_free((mbedtls_arc4_context*) ctx);
#endif
free(ctx);
#endif
}
/**
@ -304,6 +308,7 @@ const EVP_CIPHER* winpr_openssl_get_evp_cipher(int cipher)
return evp;
}
#elif defined(WITH_MBEDTLS)
mbedtls_cipher_type_t winpr_mbedtls_get_cipher_type(int cipher)
{
@ -514,71 +519,72 @@ mbedtls_cipher_type_t winpr_mbedtls_get_cipher_type(int cipher)
WINPR_CIPHER_CTX* winpr_Cipher_New(int cipher, int op, const BYTE* key, const BYTE* iv)
{
WINPR_CIPHER_CTX* ctx;
WINPR_CIPHER_CTX* ctx = NULL;
#if defined(WITH_OPENSSL)
int operation;
const EVP_CIPHER* evp;
EVP_CIPHER_CTX* octx;
#elif defined(WITH_MBEDTLS)
int key_bitlen;
mbedtls_operation_t operation;
mbedtls_cipher_type_t cipher_type;
const mbedtls_cipher_info_t* cipher_info;
#endif
ctx = calloc(1, sizeof(WINPR_CIPHER_CTX));
if (!ctx)
if (!(evp = winpr_openssl_get_evp_cipher(cipher)))
return NULL;
#if defined(WITH_OPENSSL)
octx = (EVP_CIPHER_CTX*)ctx;
evp = winpr_openssl_get_evp_cipher(cipher);
if (!evp)
{
free (ctx);
if (!(octx = EVP_CIPHER_CTX_new()))
return NULL;
}
operation = (op == WINPR_ENCRYPT) ? 1 : 0;
EVP_CIPHER_CTX_init(octx);
if (EVP_CipherInit_ex(octx, evp, NULL, key, iv, operation) != 1)
{
EVP_CIPHER_CTX_cleanup(octx);
free (octx);
EVP_CIPHER_CTX_free(octx);
return NULL;
}
EVP_CIPHER_CTX_set_padding(octx, 0);
ctx = (WINPR_CIPHER_CTX*) octx;
#elif defined(WITH_MBEDTLS)
cipher_type = winpr_mbedtls_get_cipher_type(cipher);
cipher_info = mbedtls_cipher_info_from_type(cipher_type);
int key_bitlen;
mbedtls_operation_t operation;
mbedtls_cipher_context_t* mctx;
mbedtls_cipher_type_t cipher_type = winpr_mbedtls_get_cipher_type(cipher);
const mbedtls_cipher_info_t* cipher_info = mbedtls_cipher_info_from_type(cipher_type);
if (!cipher_info)
{
free (ctx);
return NULL;
}
if (!(mctx = (mbedtls_cipher_context_t*) calloc(1, sizeof(mbedtls_cipher_context_t))))
return NULL;
operation = (op == WINPR_ENCRYPT) ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT;
mbedtls_cipher_init((mbedtls_cipher_context_t*) ctx);
mbedtls_cipher_init(mctx);
if (mbedtls_cipher_setup((mbedtls_cipher_context_t*) ctx, cipher_info) != 0)
if (mbedtls_cipher_setup(mctx, cipher_info) != 0)
{
free (ctx);
free (mctx);
return NULL;
}
key_bitlen = mbedtls_cipher_get_key_bitlen((mbedtls_cipher_context_t*) ctx);
key_bitlen = mbedtls_cipher_get_key_bitlen(mctx);
if (mbedtls_cipher_setkey((mbedtls_cipher_context_t*) ctx, key, key_bitlen, operation) != 0)
if (mbedtls_cipher_setkey(mctx, key, key_bitlen, operation) != 0)
{
mbedtls_cipher_free((mbedtls_cipher_context_t*) ctx);
free (ctx);
mbedtls_cipher_free(mctx);
free (mctx);
return NULL;
}
if (mbedtls_cipher_set_padding_mode(mctx, MBEDTLS_PADDING_NONE) != 0)
{
mbedtls_cipher_free(mctx);
free (mctx);
return NULL;
}
ctx = (WINPR_CIPHER_CTX*) mctx;
#endif
return ctx;
}
@ -587,15 +593,18 @@ BOOL winpr_Cipher_Update(WINPR_CIPHER_CTX* ctx, const BYTE* input, size_t ilen,
#if defined(WITH_OPENSSL)
int outl = (int) *olen;
if (EVP_CipherUpdate((EVP_CIPHER_CTX*) ctx, output, &outl, input, ilen) != 1)
return FALSE;
if (EVP_CipherUpdate((EVP_CIPHER_CTX*) ctx, output, &outl, input, ilen) == 1)
{
*olen = (size_t) outl;
return TRUE;
}
*olen = (size_t) outl;
#elif defined(WITH_MBEDTLS)
if (mbedtls_cipher_update((mbedtls_cipher_context_t*) ctx, input, ilen, output, olen) != 0)
return FALSE;
if (mbedtls_cipher_update((mbedtls_cipher_context_t*) ctx, input, ilen, output, olen) == 0)
return TRUE;
#endif
return TRUE;
return FALSE;
}
BOOL winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, BYTE* output, size_t* olen)
@ -603,15 +612,18 @@ BOOL winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, BYTE* output, size_t* olen)
#if defined(WITH_OPENSSL)
int outl = (int) *olen;
if (EVP_CipherFinal_ex((EVP_CIPHER_CTX*) ctx, output, &outl) != 1)
return FALSE;
if (EVP_CipherFinal_ex((EVP_CIPHER_CTX*) ctx, output, &outl) == 1)
{
*olen = (size_t) outl;
return TRUE;
}
*olen = (size_t) outl;
#elif defined(WITH_MBEDTLS)
if (mbedtls_cipher_finish((mbedtls_cipher_context_t*) ctx, output, olen) != 0)
return FALSE;
if (mbedtls_cipher_finish((mbedtls_cipher_context_t*) ctx, output, olen) == 0)
return TRUE;
#endif
return TRUE;
return FALSE;
}
void winpr_Cipher_Free(WINPR_CIPHER_CTX* ctx)
@ -620,9 +632,10 @@ void winpr_Cipher_Free(WINPR_CIPHER_CTX* ctx)
return;
#if defined(WITH_OPENSSL)
EVP_CIPHER_CTX_cleanup((EVP_CIPHER_CTX*) ctx);
EVP_CIPHER_CTX_free((EVP_CIPHER_CTX*) ctx);
#elif defined(WITH_MBEDTLS)
mbedtls_cipher_free((mbedtls_cipher_context_t*) ctx);
free(ctx);
#endif
}
@ -631,7 +644,7 @@ void winpr_Cipher_Free(WINPR_CIPHER_CTX* ctx)
* Key Generation
*/
int winpr_openssl_BytesToKey(int cipher, int md, const BYTE* salt, const BYTE* data, int datal, int count, BYTE* key, BYTE* iv)
int winpr_Cipher_BytesToKey(int cipher, int md, const BYTE* salt, const BYTE* data, int datal, int count, BYTE* key, BYTE* iv)
{
/**
* Key and IV generation compatible with OpenSSL EVP_BytesToKey():
@ -671,13 +684,13 @@ int winpr_openssl_BytesToKey(int cipher, int md, const BYTE* salt, const BYTE* d
mbedtls_md_init(&ctx);
if (mbedtls_md_setup(&ctx, md_info, 0) != 0)
goto err;
while (1)
{
if (mbedtls_md_setup(&ctx, md_info, 0) != 0)
return 0;
if (mbedtls_md_starts(&ctx) != 0)
return 0;
goto err;
if (addmd++)
{

View File

@ -177,7 +177,7 @@ BOOL CryptProtectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags)
winpr_RAND(pMemBlock->salt, 8);
winpr_RAND(randomKey, sizeof(randomKey));
winpr_openssl_BytesToKey(WINPR_CIPHER_AES_256_CBC, WINPR_MD_SHA1,
winpr_Cipher_BytesToKey(WINPR_CIPHER_AES_256_CBC, WINPR_MD_SHA1,
pMemBlock->salt, randomKey, sizeof(randomKey), 4, pMemBlock->key, pMemBlock->iv);
SecureZeroMemory(randomKey, sizeof(randomKey));

View File

@ -39,172 +39,6 @@
#include <mbedtls/md.h>
#endif
/**
* MD5
*/
BOOL winpr_MD5_Init(WINPR_MD5_CTX* ctx)
{
#if defined(WITH_OPENSSL)
if (MD5_Init((MD5_CTX*) ctx) != 1)
return FALSE;
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD5_C)
mbedtls_md5_init((mbedtls_md5_context*) ctx);
mbedtls_md5_starts((mbedtls_md5_context*) ctx);
#endif
return TRUE;
}
BOOL winpr_MD5_Update(WINPR_MD5_CTX* ctx, const BYTE* input, size_t ilen)
{
#if defined(WITH_OPENSSL)
if (MD5_Update((MD5_CTX*) ctx, input, ilen) != 1)
return FALSE;
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD5_C)
mbedtls_md5_update((mbedtls_md5_context*) ctx, input, ilen);
#endif
return TRUE;
}
BOOL winpr_MD5_Final(WINPR_MD5_CTX* ctx, BYTE* output, size_t ilen)
{
if (ilen < WINPR_MD5_DIGEST_LENGTH)
return FALSE;
#if defined(WITH_OPENSSL)
if (MD5_Final(output, (MD5_CTX*) ctx) != 1)
return FALSE;
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD5_C)
mbedtls_md5_finish((mbedtls_md5_context*) ctx, output);
mbedtls_md5_free((mbedtls_md5_context*) ctx);
#endif
return TRUE;
}
BOOL winpr_MD5(const BYTE* input, size_t ilen, BYTE* output, size_t olen)
{
WINPR_MD5_CTX ctx;
if (!winpr_MD5_Init(&ctx))
return FALSE;
if (!winpr_MD5_Update(&ctx, input, ilen))
return FALSE;
return winpr_MD5_Final(&ctx, output, olen);
}
/**
* MD4
*/
BOOL winpr_MD4_Init(WINPR_MD4_CTX* ctx)
{
#if defined(WITH_OPENSSL)
if (MD4_Init((MD4_CTX*) ctx) != 1)
return FALSE;
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD4_C)
mbedtls_md4_init((mbedtls_md4_context*) ctx);
mbedtls_md4_starts((mbedtls_md4_context*) ctx);
#endif
return TRUE;
}
BOOL winpr_MD4_Update(WINPR_MD4_CTX* ctx, const BYTE* input, size_t ilen)
{
#if defined(WITH_OPENSSL)
if (MD4_Update((MD4_CTX*) ctx, input, ilen) != 1)
return FALSE;
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD4_C)
mbedtls_md4_update((mbedtls_md4_context*) ctx, input, ilen);
#endif
return TRUE;
}
BOOL winpr_MD4_Final(WINPR_MD4_CTX* ctx, BYTE* output, size_t olen)
{
if (olen < WINPR_MD4_DIGEST_LENGTH)
return FALSE;
#if defined(WITH_OPENSSL)
if (MD4_Final(output, (MD4_CTX*) ctx) != 1)
return FALSE;
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD4_C)
mbedtls_md4_finish((mbedtls_md4_context*) ctx, output);
mbedtls_md4_free((mbedtls_md4_context*) ctx);
#endif
return TRUE;
}
BOOL winpr_MD4(const BYTE* input, size_t ilen, BYTE* output, size_t olen)
{
WINPR_MD4_CTX ctx;
if (!winpr_MD4_Init(&ctx))
return FALSE;
if (!winpr_MD4_Update(&ctx, input, ilen))
return FALSE;
return winpr_MD4_Final(&ctx, output, olen);
}
/**
* SHA1
*/
BOOL winpr_SHA1_Init(WINPR_SHA1_CTX* ctx)
{
#if defined(WITH_OPENSSL)
if (SHA1_Init((SHA_CTX*) ctx) != 1)
return FALSE;
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_SHA1_C)
mbedtls_sha1_init((mbedtls_sha1_context*) ctx);
mbedtls_sha1_starts((mbedtls_sha1_context*) ctx);
#endif
return TRUE;
}
BOOL winpr_SHA1_Update(WINPR_SHA1_CTX* ctx, const BYTE* input, size_t ilen)
{
#if defined(WITH_OPENSSL)
if (SHA1_Update((SHA_CTX*) ctx, input, ilen) != 1)
return FALSE;
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_SHA1_C)
mbedtls_sha1_update((mbedtls_sha1_context*) ctx, input, ilen);
#endif
return TRUE;
}
BOOL winpr_SHA1_Final(WINPR_SHA1_CTX* ctx, BYTE* output, size_t olen)
{
if (olen < WINPR_SHA1_DIGEST_LENGTH)
return FALSE;
#if defined(WITH_OPENSSL)
if (SHA1_Final(output, (SHA_CTX*) ctx) != 1)
return FALSE;
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_SHA1_C)
mbedtls_sha1_finish((mbedtls_sha1_context*) ctx, output);
mbedtls_sha1_free((mbedtls_sha1_context*) ctx);
#endif
return TRUE;
}
BOOL winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output, size_t olen)
{
WINPR_SHA1_CTX ctx;
if (!winpr_SHA1_Init(&ctx))
return FALSE;
if (!winpr_SHA1_Update(&ctx, input, ilen))
return FALSE;
return winpr_SHA1_Final(&ctx, output, olen);
}
/**
* HMAC
@ -308,141 +142,239 @@ mbedtls_md_type_t winpr_mbedtls_get_md_type(int md)
}
#endif
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)
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;
}
BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const BYTE* key, size_t keylen)
{
#if defined(WITH_OPENSSL)
HMAC_CTX* hmac = (HMAC_CTX*) ctx;
const EVP_MD* evp = winpr_openssl_get_evp_md(md);
if (!evp)
if (!evp || !hmac)
return FALSE;
HMAC_CTX_init((HMAC_CTX*) ctx);
#if (OPENSSL_VERSION_NUMBER < 0x10000000L)
HMAC_Init_ex((HMAC_CTX*) ctx, key, keylen, evp, NULL);
HMAC_Init_ex(hmac, key, keylen, evp, NULL); /* no return value on OpenSSL 0.9.x */
return TRUE;
#else
if (HMAC_Init_ex((HMAC_CTX*) ctx, key, keylen, evp, NULL) != 1)
return FALSE;
if (HMAC_Init_ex(hmac, key, keylen, evp, NULL) == 1)
return TRUE;
#endif
#elif defined(WITH_MBEDTLS)
const mbedtls_md_info_t* md_info;
mbedtls_md_context_t* hmac = (mbedtls_md_context_t*) ctx;
mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md);
md_info = mbedtls_md_info_from_type(md_type);
const mbedtls_md_info_t* md_info = mbedtls_md_info_from_type(md_type);
if (!md_info)
if (!md_info || !hmac)
return FALSE;
mbedtls_md_init((mbedtls_md_context_t*) ctx);
if (hmac->md_info != md_info)
{
mbedtls_md_free(hmac); /* can be called at any time after mbedtls_md_init */
if (mbedtls_md_setup((mbedtls_md_context_t*) ctx, md_info, 1) != 0)
return FALSE;
if (mbedtls_md_setup(hmac, md_info, 1) != 0)
return FALSE;
}
if (mbedtls_md_hmac_starts((mbedtls_md_context_t*) ctx, key, keylen) != 0)
return FALSE;
if (mbedtls_md_hmac_starts(hmac, key, keylen) == 0)
return TRUE;
#endif
return TRUE;
return FALSE;
}
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_CTX*) ctx, input, ilen);
#else
if (HMAC_Update((HMAC_CTX*) ctx, input, ilen) != 1)
return FALSE;
#endif
#elif defined(WITH_MBEDTLS)
if (mbedtls_md_hmac_update((mbedtls_md_context_t*) ctx, input, ilen) != 0)
return FALSE;
#endif
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
#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
return FALSE;
}
BOOL winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, BYTE* output, size_t olen)
{
/* TODO
if (olen < ctx->digestLength)
if (!ctx)
return FALSE;
*/
#if defined(WITH_OPENSSL)
HMAC_CTX* hmac = (HMAC_CTX*) ctx;
#if (OPENSSL_VERSION_NUMBER < 0x10000000L)
HMAC_Final((HMAC_CTX*) ctx, output, NULL);
#else
if (HMAC_Final((HMAC_CTX*) ctx, output, NULL) != 1)
return FALSE;
#endif
HMAC_CTX_cleanup((HMAC_CTX*) ctx);
#elif defined(WITH_MBEDTLS)
if (mbedtls_md_hmac_finish((mbedtls_md_context_t*) ctx, output) != 0)
return FALSE;
mbedtls_md_free((mbedtls_md_context_t*) ctx);
#endif
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
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*) ctx;
if (mbedtls_md_hmac_finish(mdctx, output) == 0)
return TRUE;
#endif
return FALSE;
}
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)
HMAC_CTX_cleanup(hmac);
free(hmac);
#else
HMAC_CTX_free(hmac);
#endif
}
#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)
{
WINPR_HMAC_CTX ctx;
BOOL result = FALSE;
WINPR_HMAC_CTX *ctx = winpr_HMAC_New();
if (!winpr_HMAC_Init(&ctx, md, key, keylen))
if (!ctx)
return FALSE;
if (!winpr_HMAC_Update(&ctx, input, ilen))
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;
if (!winpr_HMAC_Final(&ctx, output, olen))
return FALSE;
return TRUE;
result = TRUE;
out:
winpr_HMAC_Free(ctx);
return result;
}
/**
* Generic Digest API
*/
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)
mdctx = EVP_MD_CTX_create();
#else
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)
EVP_MD_CTX* mdctx = (EVP_MD_CTX*) ctx;
const EVP_MD* evp = winpr_openssl_get_evp_md(md);
if (!evp)
if (!mdctx || !evp)
return FALSE;
EVP_MD_CTX_init((EVP_MD_CTX*) ctx);
if (EVP_DigestInit_ex((EVP_MD_CTX*) ctx, evp, NULL) != 1)
if (EVP_DigestInit_ex(mdctx, evp, NULL) != 1)
return FALSE;
#elif defined(WITH_MBEDTLS)
const mbedtls_md_info_t* md_info;
mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*) ctx;
mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md);
md_info = mbedtls_md_info_from_type(md_type);
const mbedtls_md_info_t* md_info = mbedtls_md_info_from_type(md_type);
if (!md_info)
return FALSE;
mbedtls_md_init((mbedtls_md_context_t*) ctx);
if (mdctx->md_info != md_info)
{
mbedtls_md_free(mdctx); /* can be called at any time after mbedtls_md_init */
if (mbedtls_md_setup((mbedtls_md_context_t*) ctx, md_info, 0) != 0)
return FALSE;
if (mbedtls_md_setup(mdctx, md_info, 0) != 0)
return FALSE;
}
if (mbedtls_md_starts((mbedtls_md_context_t*) ctx) != 0)
if (mbedtls_md_starts(mdctx) != 0)
return FALSE;
#endif
return TRUE;
}
BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const BYTE* input, size_t ilen)
{
#if defined(WITH_OPENSSL)
if (EVP_DigestUpdate((EVP_MD_CTX*) ctx, input, ilen) != 1)
EVP_MD_CTX* mdctx = (EVP_MD_CTX*) ctx;
if (EVP_DigestUpdate(mdctx, input, ilen) != 1)
return FALSE;
#elif defined(WITH_MBEDTLS)
if (mbedtls_md_update((mbedtls_md_context_t*) ctx, input, ilen) != 0)
mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*) ctx;
if (mbedtls_md_update(mdctx, input, ilen) != 0)
return FALSE;
#endif
return TRUE;
@ -450,31 +382,60 @@ BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const BYTE* input, size_t ilen)
BOOL winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, BYTE* output, size_t olen)
{
// TODO: output length check
#if defined(WITH_OPENSSL)
if (EVP_DigestFinal_ex((EVP_MD_CTX*) ctx, output, NULL) != 1)
return FALSE;
#elif defined(WITH_MBEDTLS)
if (mbedtls_md_finish((mbedtls_md_context_t*) ctx, output) != 0)
return FALSE;
EVP_MD_CTX* mdctx = (EVP_MD_CTX*) ctx;
if (EVP_DigestFinal_ex(mdctx, output, NULL) == 1)
return TRUE;
mbedtls_md_free((mbedtls_md_context_t*) ctx);
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*) ctx;
if (mbedtls_md_finish(mdctx, output) == 0)
return TRUE;
#endif
return FALSE;
}
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)
EVP_MD_CTX_destroy(mdctx);
#else
EVP_MD_CTX_free(mdctx);
#endif
}
#elif defined(WITH_MBEDTLS)
mbedtls_md_context_t* mdctx = (mbedtls_md_context_t*) ctx;
if (mdctx)
{
mbedtls_md_free(mdctx);
free(mdctx);
}
#endif
return TRUE;
}
BOOL winpr_Digest(int md, const BYTE* input, size_t ilen, BYTE* output, size_t olen)
{
WINPR_DIGEST_CTX ctx;
BOOL result = FALSE;
WINPR_DIGEST_CTX *ctx = winpr_Digest_New();
if (!winpr_Digest_Init(&ctx, md))
if (!ctx)
return FALSE;
if (!winpr_Digest_Update(&ctx, input, ilen))
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;
if (!winpr_Digest_Final(&ctx, output, olen))
return FALSE;
return TRUE;
result = TRUE;
out:
winpr_Digest_Free(ctx);
return result;
}

View File

@ -3,6 +3,112 @@
#include <winpr/print.h>
#include <winpr/crypto.h>
static BOOL test_crypto_cipher_aes_128_cbc()
{
WINPR_CIPHER_CTX* ctx;
BOOL result = FALSE;
BYTE key[] = "0123456789abcdeF";
BYTE iv[] = "1234567887654321";
BYTE ibuf[1024];
BYTE obuf[1024];
size_t ilen;
size_t olen;
size_t xlen;
const char plaintext[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
/* encrypt */
if (!(ctx = winpr_Cipher_New(WINPR_CIPHER_AES_128_CBC, WINPR_ENCRYPT, key, iv)))
{
fprintf(stderr, "%s: winpr_Cipher_New (encrypt) failed\n", __FUNCTION__);
return FALSE;
}
memset(ibuf, 0, sizeof(ibuf));
memset(obuf, 0, sizeof(obuf));
ilen = strlen(plaintext) + 1;
memcpy(ibuf, plaintext, ilen);
ilen = ((ilen + 15) / 16) * 16;
olen = 0;
xlen = 0;
if (!winpr_Cipher_Update(ctx, ibuf, ilen, obuf, &olen))
{
fprintf(stderr, "%s: winpr_Cipher_New (encrypt) failed\n", __FUNCTION__);
goto out;
}
xlen += olen;
if (!winpr_Cipher_Final(ctx, obuf + xlen, &olen))
{
fprintf(stderr, "%s: winpr_Cipher_Final (encrypt) failed\n", __FUNCTION__);
goto out;
}
xlen += olen;
if (xlen != ilen)
{
fprintf(stderr, "%s: error, xlen (%u) != ilen (%u) (encrypt)\n", __FUNCTION__, (unsigned)xlen, (unsigned)ilen);
goto out;
}
winpr_Cipher_Free(ctx);
/* decrypt */
if (!(ctx = winpr_Cipher_New(WINPR_CIPHER_AES_128_CBC, WINPR_DECRYPT, key, iv)))
{
fprintf(stderr, "%s: winpr_Cipher_New (decrypt) failed\n", __FUNCTION__);
return FALSE;
}
memset(ibuf, 0, sizeof(ibuf));
memcpy(ibuf, obuf, xlen);
memset(obuf, 0, sizeof(obuf));
ilen = xlen;
olen = 0;
xlen = 0;
if (!winpr_Cipher_Update(ctx, ibuf, ilen, obuf, &olen))
{
fprintf(stderr, "%s: winpr_Cipher_New (decrypt) failed\n", __FUNCTION__);
goto out;
}
xlen += olen;
if (!winpr_Cipher_Final(ctx, obuf + xlen, &olen))
{
fprintf(stderr, "%s: winpr_Cipher_Final (decrypt) failed\n", __FUNCTION__);
goto out;
}
xlen += olen;
if (xlen != ilen)
{
fprintf(stderr, "%s: error, xlen (%u) != ilen (%u) (decrypt)\n", __FUNCTION__, (unsigned)xlen, (unsigned)ilen);
goto out;
}
if (strcmp((const char*) obuf, plaintext))
{
fprintf(stderr, "%s: error, decrypted data does not match plaintext\n", __FUNCTION__);
goto out;
}
result = TRUE;
out:
winpr_Cipher_Free(ctx);
return result;
}
static const BYTE* TEST_RC4_KEY = (BYTE*) "Key";
static const char* TEST_RC4_PLAINTEXT = "Plaintext";
static const BYTE* TEST_RC4_CIPHERTEXT = (BYTE*) "\xBB\xF3\x16\xE8\xD9\x40\xAF\x0A\xD3";
@ -16,17 +122,24 @@ static BOOL test_crypto_cipher_rc4()
len = strlen(TEST_RC4_PLAINTEXT);
text = (BYTE*) calloc(1, len);
if (!text)
if (!(text = (BYTE*) calloc(1, len)))
{
fprintf(stderr, "%s: failed to allocate text buffer (len=%u)\n", __FUNCTION__, (unsigned)len);
goto out;
}
if ((ctx = winpr_RC4_New(TEST_RC4_KEY, strlen((char*) TEST_RC4_KEY))) == NULL)
{
fprintf(stderr, "%s: winpr_RC4_New failed\n", __FUNCTION__);
goto out;
}
rc = winpr_RC4_Update(ctx, len, (BYTE*) TEST_RC4_PLAINTEXT, text);
winpr_RC4_Free(ctx);
if (!rc)
{
fprintf(stderr, "%s: winpr_RC4_Update failed\n", __FUNCTION__);
goto out;
}
if (memcmp(text, TEST_RC4_CIPHERTEXT, len) != 0)
{
@ -36,7 +149,7 @@ static BOOL test_crypto_cipher_rc4()
actual = winpr_BinToHexString(text, len, FALSE);
expected = winpr_BinToHexString(TEST_RC4_CIPHERTEXT, len, FALSE);
fprintf(stderr, "unexpected RC4 ciphertext: Actual: %s Expected: %s\n", actual, expected);
fprintf(stderr, "%s: unexpected RC4 ciphertext: Actual: %s Expected: %s\n", __FUNCTION__, actual, expected);
free(actual);
free(expected);
@ -73,7 +186,7 @@ static BOOL test_crypto_cipher_key()
ZeroMemory(key, sizeof(key));
ZeroMemory(iv, sizeof(iv));
status = winpr_openssl_BytesToKey(WINPR_CIPHER_AES_256_CBC, WINPR_MD_SHA1,
status = winpr_Cipher_BytesToKey(WINPR_CIPHER_AES_256_CBC, WINPR_MD_SHA1,
salt, TEST_RAND_DATA, 64, 4, key, iv);
if (status != 32 || memcmp(key, TEST_CIPHER_KEY, 32) || memcmp(iv, TEST_CIPHER_IV, 16))
@ -103,6 +216,9 @@ static BOOL test_crypto_cipher_key()
int TestCryptoCipher(int argc, char* argv[])
{
if (!test_crypto_cipher_aes_128_cbc())
return -1;
if (!test_crypto_cipher_rc4())
return -1;

View File

@ -8,16 +8,30 @@ static const BYTE* TEST_MD5_HASH = (BYTE*) "\x09\x8f\x6b\xcd\x46\x21\xd3\x73\xca
static BOOL test_crypto_hash_md5(void)
{
BOOL result = FALSE;
BYTE hash[WINPR_MD5_DIGEST_LENGTH];
WINPR_MD5_CTX ctx;
WINPR_DIGEST_CTX* ctx;
if (!winpr_MD5_Init(&ctx))
if (!(ctx = winpr_Digest_New()))
{
fprintf(stderr, "%s: winpr_Digest_New failed\n", __FUNCTION__);
return FALSE;
if (!winpr_MD5_Update(&ctx, (BYTE*) TEST_MD5_DATA, strlen(TEST_MD5_DATA)))
return FALSE;
if (!winpr_MD5_Final(&ctx, hash, sizeof(hash)))
return FALSE;
}
if (!winpr_Digest_Init(ctx, WINPR_MD_MD5))
{
fprintf(stderr, "%s: winpr_Digest_Init failed\n", __FUNCTION__);
goto out;
}
if (!winpr_Digest_Update(ctx, (BYTE*) TEST_MD5_DATA, strlen(TEST_MD5_DATA)))
{
fprintf(stderr, "%s: winpr_Digest_Update failed\n", __FUNCTION__);
goto out;
}
if (!winpr_Digest_Final(ctx, hash, sizeof(hash)))
{
fprintf(stderr, "%s: winpr_Digest_Final failed\n", __FUNCTION__);
goto out;
}
if (memcmp(hash, TEST_MD5_HASH, WINPR_MD5_DIGEST_LENGTH) != 0)
{
char* actual;
@ -31,10 +45,13 @@ static BOOL test_crypto_hash_md5(void)
free(actual);
free(expected);
return FALSE;
goto out;
}
return TRUE;
result = TRUE;
out:
winpr_Digest_Free(ctx);
return result;
}
static const char* TEST_MD4_DATA = "test";
@ -42,16 +59,30 @@ static const BYTE* TEST_MD4_HASH = (BYTE*) "\xdb\x34\x6d\x69\x1d\x7a\xcc\x4d\xc2
static BOOL test_crypto_hash_md4(void)
{
BOOL result = FALSE;
BYTE hash[WINPR_MD4_DIGEST_LENGTH];
WINPR_MD4_CTX ctx;
WINPR_DIGEST_CTX* ctx;
if (!winpr_MD4_Init(&ctx))
if (!(ctx = winpr_Digest_New()))
{
fprintf(stderr, "%s: winpr_Digest_New failed\n", __FUNCTION__);
return FALSE;
if (!winpr_MD4_Update(&ctx, (BYTE*) TEST_MD4_DATA, strlen(TEST_MD4_DATA)))
return FALSE;
if (!winpr_MD4_Final(&ctx, hash, sizeof(hash)))
return FALSE;
}
if (!winpr_Digest_Init(ctx, WINPR_MD_MD4))
{
fprintf(stderr, "%s: winpr_Digest_Init failed\n", __FUNCTION__);
goto out;
}
if (!winpr_Digest_Update(ctx, (BYTE*) TEST_MD4_DATA, strlen(TEST_MD4_DATA)))
{
fprintf(stderr, "%s: winpr_Digest_Update failed\n", __FUNCTION__);
goto out;
}
if (!winpr_Digest_Final(ctx, hash, sizeof(hash)))
{
fprintf(stderr, "%s: winpr_Digest_Final failed\n", __FUNCTION__);
goto out;
}
if (memcmp(hash, TEST_MD4_HASH, WINPR_MD4_DIGEST_LENGTH) != 0)
{
char* actual;
@ -65,10 +96,13 @@ static BOOL test_crypto_hash_md4(void)
free(actual);
free(expected);
return FALSE;
goto out;
}
return TRUE;
result = TRUE;
out:
winpr_Digest_Free(ctx);
return result;
}
static const char* TEST_SHA1_DATA = "test";
@ -76,15 +110,30 @@ static const BYTE* TEST_SHA1_HASH = (BYTE*) "\xa9\x4a\x8f\xe5\xcc\xb1\x9b\xa6\x1
static BOOL test_crypto_hash_sha1(void)
{
BOOL result = FALSE;
BYTE hash[WINPR_SHA1_DIGEST_LENGTH];
WINPR_SHA1_CTX ctx;
WINPR_DIGEST_CTX* ctx;
if (!winpr_SHA1_Init(&ctx))
return FALSE;
if (!winpr_SHA1_Update(&ctx, (BYTE*) TEST_SHA1_DATA, strlen(TEST_SHA1_DATA)))
return FALSE;
if (!winpr_SHA1_Final(&ctx, hash, sizeof(hash)))
if (!(ctx = winpr_Digest_New()))
{
fprintf(stderr, "%s: winpr_Digest_New failed\n", __FUNCTION__);
return FALSE;
}
if (!winpr_Digest_Init(ctx, WINPR_MD_SHA1))
{
fprintf(stderr, "%s: winpr_Digest_Init failed\n", __FUNCTION__);
goto out;
}
if (!winpr_Digest_Update(ctx, (BYTE*) TEST_SHA1_DATA, strlen(TEST_SHA1_DATA)))
{
fprintf(stderr, "%s: winpr_Digest_Update failed\n", __FUNCTION__);
goto out;
}
if (!winpr_Digest_Final(ctx, hash, sizeof(hash)))
{
fprintf(stderr, "%s: winpr_Digest_Final failed\n", __FUNCTION__);
goto out;
}
if (memcmp(hash, TEST_SHA1_HASH, WINPR_MD5_DIGEST_LENGTH) != 0)
{
@ -99,10 +148,13 @@ static BOOL test_crypto_hash_sha1(void)
free(actual);
free(expected);
return FALSE;
goto out;
}
return TRUE;
result = TRUE;
out:
winpr_Digest_Free(ctx);
return result;
}
static const char* TEST_HMAC_MD5_DATA = "Hi There";
@ -112,14 +164,30 @@ static const BYTE* TEST_HMAC_MD5_HASH = (BYTE*) "\x92\x94\x72\x7a\x36\x38\xbb\x1
static BOOL test_crypto_hash_hmac_md5(void)
{
BYTE hash[WINPR_MD5_DIGEST_LENGTH];
WINPR_HMAC_CTX ctx;
WINPR_HMAC_CTX* ctx;
BOOL result = FALSE;
if (!winpr_HMAC_Init(&ctx, WINPR_MD_MD5, TEST_HMAC_MD5_KEY, WINPR_MD5_DIGEST_LENGTH))
return FALSE;
if (!winpr_HMAC_Update(&ctx, (BYTE*) TEST_HMAC_MD5_DATA, strlen(TEST_HMAC_MD5_DATA)))
return FALSE;
if (!winpr_HMAC_Final(&ctx, hash, sizeof(hash)))
if (!(ctx = winpr_HMAC_New()))
{
fprintf(stderr, "%s: winpr_HMAC_New failed\n", __FUNCTION__);
return FALSE;
}
if (!winpr_HMAC_Init(ctx, WINPR_MD_MD5, TEST_HMAC_MD5_KEY, WINPR_MD5_DIGEST_LENGTH))
{
fprintf(stderr, "%s: winpr_HMAC_Init failed\n", __FUNCTION__);
goto out;
}
if (!winpr_HMAC_Update(ctx, (BYTE*) TEST_HMAC_MD5_DATA, strlen(TEST_HMAC_MD5_DATA)))
{
fprintf(stderr, "%s: winpr_HMAC_Update failed\n", __FUNCTION__);
goto out;
}
if (!winpr_HMAC_Final(ctx, hash, sizeof(hash)))
{
fprintf(stderr, "%s: winpr_HMAC_Final failed\n", __FUNCTION__);
goto out;
}
if (memcmp(hash, TEST_HMAC_MD5_HASH, WINPR_MD5_DIGEST_LENGTH) != 0)
{
@ -134,10 +202,13 @@ static BOOL test_crypto_hash_hmac_md5(void)
free(actual);
free(expected);
return FALSE;
goto out;
}
return TRUE;
result = TRUE;
out:
winpr_HMAC_Free(ctx);
return result;
}
static const char* TEST_HMAC_SHA1_DATA = "Hi There";
@ -147,14 +218,30 @@ static const BYTE* TEST_HMAC_SHA1_HASH = (BYTE*) "\xb6\x17\x31\x86\x55\x05\x72\x
static BOOL test_crypto_hash_hmac_sha1(void)
{
BYTE hash[WINPR_SHA1_DIGEST_LENGTH];
WINPR_HMAC_CTX ctx;
WINPR_HMAC_CTX* ctx;
BOOL result = FALSE;
if (!winpr_HMAC_Init(&ctx, WINPR_MD_SHA1, TEST_HMAC_SHA1_KEY, WINPR_SHA1_DIGEST_LENGTH))
return FALSE;
if (!winpr_HMAC_Update(&ctx, (BYTE*) TEST_HMAC_SHA1_DATA, strlen(TEST_HMAC_SHA1_DATA)))
return FALSE;
if (!winpr_HMAC_Final(&ctx, hash, sizeof(hash)))
if (!(ctx = winpr_HMAC_New()))
{
fprintf(stderr, "%s: winpr_HMAC_New failed\n", __FUNCTION__);
return FALSE;
}
if (!winpr_HMAC_Init(ctx, WINPR_MD_SHA1, TEST_HMAC_SHA1_KEY, WINPR_SHA1_DIGEST_LENGTH))
{
fprintf(stderr, "%s: winpr_HMAC_Init failed\n", __FUNCTION__);
goto out;
}
if (!winpr_HMAC_Update(ctx, (BYTE*) TEST_HMAC_SHA1_DATA, strlen(TEST_HMAC_SHA1_DATA)))
{
fprintf(stderr, "%s: winpr_HMAC_Update failed\n", __FUNCTION__);
goto out;
}
if (!winpr_HMAC_Final(ctx, hash, sizeof(hash)))
{
fprintf(stderr, "%s: winpr_HMAC_Final failed\n", __FUNCTION__);
goto out;
}
if (memcmp(hash, TEST_HMAC_SHA1_HASH, WINPR_SHA1_DIGEST_LENGTH) != 0)
{
@ -169,10 +256,13 @@ static BOOL test_crypto_hash_hmac_sha1(void)
free(actual);
free(expected);
return FALSE;
goto out;
}
return TRUE;
result = TRUE;
out:
winpr_HMAC_Free(ctx);
return result;
}
int TestCryptoHash(int argc, char* argv[])

View File

@ -913,7 +913,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP,
BYTE checksum[8];
BYTE* signature;
ULONG version = 1;
WINPR_HMAC_CTX hmac;
WINPR_HMAC_CTX* hmac;
NTLM_CONTEXT* context;
PSecBuffer data_buffer = NULL;
PSecBuffer signature_buffer = NULL;
@ -943,11 +943,21 @@ SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP,
CopyMemory(data, data_buffer->pvBuffer, length);
/* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,data) using the client signing key */
winpr_HMAC_Init(&hmac, WINPR_MD_MD5, context->SendSigningKey, WINPR_MD5_DIGEST_LENGTH);
Data_Write_UINT32(&value, SeqNo);
winpr_HMAC_Update(&hmac, (void*) &value, 4);
winpr_HMAC_Update(&hmac, (void*) data, length);
winpr_HMAC_Final(&hmac, digest, WINPR_MD5_DIGEST_LENGTH);
hmac = winpr_HMAC_New();
if (hmac && winpr_HMAC_Init(hmac, WINPR_MD_MD5, context->SendSigningKey, WINPR_MD5_DIGEST_LENGTH))
{
Data_Write_UINT32(&value, SeqNo);
winpr_HMAC_Update(hmac, (void*) &value, 4);
winpr_HMAC_Update(hmac, (void*) data, length);
winpr_HMAC_Final(hmac, digest, WINPR_MD5_DIGEST_LENGTH);
winpr_HMAC_Free(hmac);
}
else
{
winpr_HMAC_Free(hmac);
free(data);
return SEC_E_INSUFFICIENT_MEMORY;
}
/* Encrypt message using with RC4, result overwrites original buffer */
@ -988,7 +998,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD
BYTE digest[WINPR_MD5_DIGEST_LENGTH];
BYTE checksum[8];
UINT32 version = 1;
WINPR_HMAC_CTX hmac;
WINPR_HMAC_CTX* hmac;
NTLM_CONTEXT* context;
BYTE expected_signature[WINPR_MD5_DIGEST_LENGTH];
PSecBuffer data_buffer = NULL;
@ -1027,11 +1037,21 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD
CopyMemory(data_buffer->pvBuffer, data, length);
/* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,data) using the client signing key */
winpr_HMAC_Init(&hmac, WINPR_MD_MD5, context->RecvSigningKey, WINPR_MD5_DIGEST_LENGTH);
Data_Write_UINT32(&value, SeqNo);
winpr_HMAC_Update(&hmac, (void*) &value, 4);
winpr_HMAC_Update(&hmac, (void*) data_buffer->pvBuffer, data_buffer->cbBuffer);
winpr_HMAC_Final(&hmac, digest, WINPR_MD5_DIGEST_LENGTH);
hmac = winpr_HMAC_New();
if (hmac && winpr_HMAC_Init(hmac, WINPR_MD_MD5, context->RecvSigningKey, WINPR_MD5_DIGEST_LENGTH))
{
Data_Write_UINT32(&value, SeqNo);
winpr_HMAC_Update(hmac, (void*) &value, 4);
winpr_HMAC_Update(hmac, (void*) data_buffer->pvBuffer, data_buffer->cbBuffer);
winpr_HMAC_Final(hmac, digest, WINPR_MD5_DIGEST_LENGTH);
winpr_HMAC_Free(hmac);
}
else
{
winpr_HMAC_Free(hmac);
free(data);
return SEC_E_INSUFFICIENT_MEMORY;
}
#ifdef WITH_DEBUG_NTLM
WLog_DBG(TAG, "Encrypted Data Buffer (length = %d)", length);
winpr_HexDump(TAG, WLOG_DEBUG, data, length);

View File

@ -246,19 +246,19 @@ typedef struct gss_channel_bindings_struct {
} *gss_channel_bindings_t;
*/
static void ntlm_md5_update_uint32_be(WINPR_MD5_CTX* md5, UINT32 num)
static BOOL ntlm_md5_update_uint32_be(WINPR_DIGEST_CTX* md5, UINT32 num)
{
BYTE be32[4];
be32[0] = (num >> 0) & 0xFF;
be32[1] = (num >> 8) & 0xFF;
be32[2] = (num >> 16) & 0xFF;
be32[3] = (num >> 24) & 0xFF;
winpr_MD5_Update(md5, be32, 4);
return winpr_Digest_Update(md5, be32, 4);
}
void ntlm_compute_channel_bindings(NTLM_CONTEXT* context)
{
WINPR_MD5_CTX md5;
WINPR_DIGEST_CTX* md5;
BYTE* ChannelBindingToken;
UINT32 ChannelBindingTokenLength;
SEC_CHANNEL_BINDINGS* ChannelBindings;
@ -269,16 +269,33 @@ void ntlm_compute_channel_bindings(NTLM_CONTEXT* context)
if (!ChannelBindings)
return;
if (!(md5 = winpr_Digest_New()))
return;
if (!winpr_Digest_Init(md5, WINPR_MD_MD5))
goto out;
ChannelBindingTokenLength = context->Bindings.BindingsLength - sizeof(SEC_CHANNEL_BINDINGS);
ChannelBindingToken = &((BYTE*) ChannelBindings)[ChannelBindings->dwApplicationDataOffset];
winpr_MD5_Init(&md5);
ntlm_md5_update_uint32_be(&md5, ChannelBindings->dwInitiatorAddrType);
ntlm_md5_update_uint32_be(&md5, ChannelBindings->cbInitiatorLength);
ntlm_md5_update_uint32_be(&md5, ChannelBindings->dwAcceptorAddrType);
ntlm_md5_update_uint32_be(&md5, ChannelBindings->cbAcceptorLength);
ntlm_md5_update_uint32_be(&md5, ChannelBindings->cbApplicationDataLength);
winpr_MD5_Update(&md5, (void*) ChannelBindingToken, ChannelBindingTokenLength);
winpr_MD5_Final(&md5, context->ChannelBindingsHash, WINPR_MD5_DIGEST_LENGTH);
if (!ntlm_md5_update_uint32_be(md5, ChannelBindings->dwInitiatorAddrType))
goto out;
if (!ntlm_md5_update_uint32_be(md5, ChannelBindings->cbInitiatorLength))
goto out;
if (!ntlm_md5_update_uint32_be(md5, ChannelBindings->dwAcceptorAddrType))
goto out;
if (!ntlm_md5_update_uint32_be(md5, ChannelBindings->cbAcceptorLength))
goto out;
if (!ntlm_md5_update_uint32_be(md5, ChannelBindings->cbApplicationDataLength))
goto out;
if (!winpr_Digest_Update(md5, (void*) ChannelBindingToken, ChannelBindingTokenLength))
goto out;
if (!winpr_Digest_Final(md5, context->ChannelBindingsHash, WINPR_MD5_DIGEST_LENGTH))
goto out;
out:
winpr_Digest_Free(md5);
}
void ntlm_compute_single_host_data(NTLM_CONTEXT* context)

View File

@ -549,7 +549,6 @@ int ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic,
{
int length;
BYTE* value;
WINPR_MD5_CTX md5;
length = WINPR_MD5_DIGEST_LENGTH + sign_magic->cbBuffer;
value = (BYTE*) malloc(length);
@ -560,9 +559,12 @@ int ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic,
/* Concatenate ExportedSessionKey with sign magic */
CopyMemory(value, exported_session_key, WINPR_MD5_DIGEST_LENGTH);
CopyMemory(&value[WINPR_MD5_DIGEST_LENGTH], sign_magic->pvBuffer, sign_magic->cbBuffer);
winpr_MD5_Init(&md5);
winpr_MD5_Update(&md5, value, length);
winpr_MD5_Final(&md5, signing_key, WINPR_MD5_DIGEST_LENGTH);
if (!winpr_Digest(WINPR_MD_MD5, value, length, signing_key, WINPR_MD5_DIGEST_LENGTH))
{
free(value);
return -1;
}
free(value);
return 1;
}
@ -606,7 +608,6 @@ void ntlm_generate_server_signing_key(NTLM_CONTEXT* context)
int ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic, BYTE* sealing_key)
{
BYTE* p;
WINPR_MD5_CTX md5;
SecBuffer buffer;
if (!sspi_SecBufferAlloc(&buffer, WINPR_MD5_DIGEST_LENGTH + seal_magic->cbBuffer))
@ -616,9 +617,13 @@ int ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic,
/* Concatenate ExportedSessionKey with seal magic */
CopyMemory(p, exported_session_key, WINPR_MD5_DIGEST_LENGTH);
CopyMemory(&p[WINPR_MD5_DIGEST_LENGTH], seal_magic->pvBuffer, seal_magic->cbBuffer);
winpr_MD5_Init(&md5);
winpr_MD5_Update(&md5, buffer.pvBuffer, buffer.cbBuffer);
winpr_MD5_Final(&md5, sealing_key, WINPR_MD5_DIGEST_LENGTH);
if (!winpr_Digest(WINPR_MD_MD5, buffer.pvBuffer, buffer.cbBuffer, sealing_key, WINPR_MD5_DIGEST_LENGTH))
{
sspi_SecBufferFree(&buffer);
return -1;
}
sspi_SecBufferFree(&buffer);
return 1;
}
@ -680,15 +685,22 @@ void ntlm_init_rc4_seal_states(NTLM_CONTEXT* context)
void ntlm_compute_message_integrity_check(NTLM_CONTEXT* context)
{
WINPR_HMAC_CTX hmac;
/*
* Compute the HMAC-MD5 hash of ConcatenationOf(NEGOTIATE_MESSAGE,
* CHALLENGE_MESSAGE, AUTHENTICATE_MESSAGE) using the ExportedSessionKey
*/
winpr_HMAC_Init(&hmac, WINPR_MD_MD5, context->ExportedSessionKey, WINPR_MD5_DIGEST_LENGTH);
winpr_HMAC_Update(&hmac, (BYTE*) context->NegotiateMessage.pvBuffer, context->NegotiateMessage.cbBuffer);
winpr_HMAC_Update(&hmac, (BYTE*) context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer);
winpr_HMAC_Update(&hmac, (BYTE*) context->AuthenticateMessage.pvBuffer, context->AuthenticateMessage.cbBuffer);
winpr_HMAC_Final(&hmac, context->MessageIntegrityCheck, WINPR_MD5_DIGEST_LENGTH);
WINPR_HMAC_CTX* hmac = winpr_HMAC_New();
if (!hmac)
return;
if (winpr_HMAC_Init(hmac, WINPR_MD_MD5, context->ExportedSessionKey, WINPR_MD5_DIGEST_LENGTH))
{
winpr_HMAC_Update(hmac, (BYTE*) context->NegotiateMessage.pvBuffer, context->NegotiateMessage.cbBuffer);
winpr_HMAC_Update(hmac, (BYTE*) context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer);
winpr_HMAC_Update(hmac, (BYTE*) context->AuthenticateMessage.pvBuffer, context->AuthenticateMessage.cbBuffer);
winpr_HMAC_Final(hmac, context->MessageIntegrityCheck, WINPR_MD5_DIGEST_LENGTH);
}
winpr_HMAC_Free(hmac);
}

View File

@ -35,22 +35,20 @@
BYTE* NTOWFv1W(LPWSTR Password, UINT32 PasswordLength, BYTE* NtHash)
{
BOOL allocate = !NtHash;
WINPR_MD4_CTX md4;
if (!Password)
return NULL;
if (!winpr_MD4_Init(&md4))
return NULL;
if (!winpr_MD4_Update(&md4, (BYTE*) Password, (size_t) PasswordLength))
return NULL;
if (!NtHash && !(NtHash = malloc(WINPR_MD4_DIGEST_LENGTH)))
return NULL;
if (!winpr_MD4_Final(&md4, NtHash, WINPR_MD4_DIGEST_LENGTH))
if (!winpr_Digest(WINPR_MD_MD4, (BYTE*) Password, (size_t) PasswordLength, NtHash, WINPR_MD4_DIGEST_LENGTH))
{
if (allocate)
{
free(NtHash);
return NULL;
NtHash = NULL;
}
}
return NtHash;

View File

@ -35,9 +35,21 @@
#include "../log.h"
#define TAG WINPR_TAG("utils.ssl")
static BOOL g_winpr_openssl_initialized_by_winpr = FALSE;
/**
* Note from OpenSSL 1.1.0 "CHANGES":
* OpenSSL now uses a new threading API. It is no longer necessary to
* set locking callbacks to use OpenSSL in a multi-threaded environment.
*/
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
#define WINPR_OPENSSL_LOCKING_REQUIRED 1
static int g_winpr_openssl_num_locks = 0;
static HANDLE* g_winpr_openssl_locks = NULL;
static BOOL g_winpr_openssl_initialized_by_winpr = FALSE;
struct CRYPTO_dynlock_value
{
@ -220,6 +232,9 @@ static BOOL _winpr_openssl_cleanup_locking(void)
return TRUE;
}
#endif /* OpenSSL < 1.1.0 */
static BOOL CALLBACK _winpr_openssl_initialize(PINIT_ONCE once, PVOID param, PVOID* context)
{
DWORD flags = param ? *(PDWORD)param : WINPR_SSL_INIT_DEFAULT;
@ -229,6 +244,7 @@ static BOOL CALLBACK _winpr_openssl_initialize(PINIT_ONCE once, PVOID param, PVO
return TRUE;
}
#ifdef WINPR_OPENSSL_LOCKING_REQUIRED
if (flags & WINPR_SSL_INIT_ENABLE_LOCKING)
{
if (!_winpr_openssl_initialize_locking())
@ -236,7 +252,7 @@ static BOOL CALLBACK _winpr_openssl_initialize(PINIT_ONCE once, PVOID param, PVO
return FALSE;
}
}
#endif
/* SSL_load_error_strings() is void */
SSL_load_error_strings();
/* SSL_library_init() always returns "1" */
@ -265,13 +281,16 @@ BOOL winpr_CleanupSSL(DWORD flags)
}
g_winpr_openssl_initialized_by_winpr = FALSE;
#ifdef WINPR_OPENSSL_LOCKING_REQUIRED
_winpr_openssl_cleanup_locking();
#endif
CRYPTO_cleanup_all_ex_data();
ERR_free_strings();
EVP_cleanup();
flags |= WINPR_SSL_CLEANUP_THREAD;
}
#ifdef WINPR_OPENSSL_LOCKING_REQUIRED
if (flags & WINPR_SSL_CLEANUP_THREAD)
{
#if (OPENSSL_VERSION_NUMBER < 0x10000000L)
@ -280,7 +299,7 @@ BOOL winpr_CleanupSSL(DWORD flags)
ERR_remove_thread_state(NULL);
#endif
}
#endif
return TRUE;
}