Merge pull request #3615 from nfedera/openssl_1.1.0
Support for OpenSSL 1.1.0
This commit is contained in:
commit
f23487907e
@ -756,6 +756,7 @@ endif()
|
||||
|
||||
if(OPENSSL_FOUND)
|
||||
add_definitions("-DWITH_OPENSSL")
|
||||
message(STATUS "Using OpenSSL Version: ${OPENSSL_VERSION}")
|
||||
endif()
|
||||
|
||||
if(MBEDTLS_FOUND)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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})
|
||||
|
||||
|
@ -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;
|
||||
|
44
libfreerdp/crypto/opensslcompat.c
Normal file
44
libfreerdp/crypto/opensslcompat.c
Normal 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 */
|
65
libfreerdp/crypto/opensslcompat.h
Normal file
65
libfreerdp/crypto/opensslcompat.h
Normal 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 */
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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++)
|
||||
{
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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[])
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user