From d62ee951a03f91a064d1bac51b75489af91e85b5 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 17 Apr 2021 17:47:53 -0500 Subject: [PATCH] Refactor OpenSSL usage into a platform-specific file to allow other crypto backends --- src/ControlStream.c | 119 +++++------------------ src/InputStream.c | 133 +++++--------------------- src/Limelight-internal.h | 1 + src/PlatformCrypto.c | 197 +++++++++++++++++++++++++++++++++++++++ src/PlatformCrypto.h | 35 +++++++ src/SimpleStun.c | 4 +- 6 files changed, 279 insertions(+), 210 deletions(-) create mode 100644 src/PlatformCrypto.c create mode 100644 src/PlatformCrypto.h diff --git a/src/ControlStream.c b/src/ControlStream.c index 05dddf3..30d2081 100644 --- a/src/ControlStream.c +++ b/src/ControlStream.c @@ -6,8 +6,6 @@ #include -#include - // NV control stream packet header for TCP typedef struct _NVCTL_TCP_PACKET_HEADER { unsigned short type; @@ -65,11 +63,8 @@ static int currentEnetSequenceNumber; static bool idrFrameRequired; static LINKED_BLOCKING_QUEUE invalidReferenceFrameTuples; -static EVP_CIPHER_CTX* cipherContext; - -#if OPENSSL_VERSION_NUMBER < 0x10100000L -#define EVP_CIPHER_CTX_reset(x) EVP_CIPHER_CTX_cleanup(x); EVP_CIPHER_CTX_init(x) -#endif +static PPLT_CRYPTO_CONTEXT encryptionCtx; +static PPLT_CRYPTO_CONTEXT decryptionCtx; #define CONN_IMMEDIATE_POOR_LOSS_RATE 30 #define CONN_CONSECUTIVE_POOR_LOSS_RATE 15 @@ -251,7 +246,8 @@ int initializeControlStream(void) { lastConnectionStatusUpdate = CONN_STATUS_OKAY; currentEnetSequenceNumber = 0; usePeriodicPing = APP_VERSION_AT_LEAST(7, 1, 415); - cipherContext = EVP_CIPHER_CTX_new(); + encryptionCtx = PltCreateCryptoContext(); + decryptionCtx = PltCreateCryptoContext(); return 0; } @@ -269,7 +265,8 @@ void freeFrameInvalidationList(PLINKED_BLOCKING_QUEUE_ENTRY entry) { // Cleans up control stream void destroyControlStream(void) { LC_ASSERT(stopping); - EVP_CIPHER_CTX_free(cipherContext); + PltDestroyCryptoContext(encryptionCtx); + PltDestroyCryptoContext(decryptionCtx); PltCloseEvent(&invalidateRefFramesEvent); freeFrameInvalidationList(LbqDestroyLinkedBlockingQueue(&invalidReferenceFrameTuples)); PltDeleteMutex(&enetMutex); @@ -390,57 +387,23 @@ static PNVCTL_TCP_PACKET_HEADER readNvctlPacketTcp(void) { } static bool encryptControlMessage(PNVCTL_ENCRYPTED_PACKET_HEADER encPacket, PNVCTL_ENET_PACKET_HEADER_V2 packet) { - bool ret = false; - int len; unsigned char iv[16]; + int encryptedSize = sizeof(*packet) + packet->payloadLength; // This is a truncating cast, but it's what Nvidia does, so we have to mimic it. memset(iv, 0, sizeof(iv)); iv[0] = (unsigned char)encPacket->seq; - if (EVP_EncryptInit_ex(cipherContext, EVP_aes_128_gcm(), NULL, NULL, NULL) != 1) { - goto gcm_cleanup; - } - - if (EVP_CIPHER_CTX_ctrl(cipherContext, EVP_CTRL_GCM_SET_IVLEN, 16, NULL) != 1) { - goto gcm_cleanup; - } - - if (EVP_EncryptInit_ex(cipherContext, NULL, NULL, - (const unsigned char*)StreamConfig.remoteInputAesKey, iv) != 1) { - goto gcm_cleanup; - } - - // Encrypt into the space after the encrypted header and GCM tag - int encryptedSize = sizeof(*packet) + packet->payloadLength; - if (EVP_EncryptUpdate(cipherContext, ((unsigned char*)(encPacket + 1)) + AES_GCM_TAG_LENGTH, - &encryptedSize, (const unsigned char*)packet, encryptedSize) != 1) { - goto gcm_cleanup; - } - - // GCM encryption won't ever fill ciphertext here but we have to call it anyway - if (EVP_EncryptFinal_ex(cipherContext, ((unsigned char*)(encPacket + 1)), &len) != 1) { - goto gcm_cleanup; - } - LC_ASSERT(len == 0); - - // Read the tag into the space after the encrypted header - if (EVP_CIPHER_CTX_ctrl(cipherContext, EVP_CTRL_GCM_GET_TAG, 16, (unsigned char*)(encPacket + 1)) != 1) { - ret = -1; - goto gcm_cleanup; - } - - ret = true; - -gcm_cleanup: - EVP_CIPHER_CTX_reset(cipherContext); - return ret; + return PltEncryptMessage(encryptionCtx, ALGORITHM_AES_GCM, + (unsigned char*)StreamConfig.remoteInputAesKey, sizeof(StreamConfig.remoteInputAesKey), + iv, sizeof(iv), + (unsigned char*)(encPacket + 1), AES_GCM_TAG_LENGTH, // Write tag into the space after the encrypted header + (unsigned char*)packet, encryptedSize, + ((unsigned char*)(encPacket + 1)) + AES_GCM_TAG_LENGTH, &encryptedSize); // Write ciphertext after the GCM tag } // Caller must free() *packet on success!!! static bool decryptControlMessageToV1(PNVCTL_ENCRYPTED_PACKET_HEADER encPacket, PNVCTL_ENET_PACKET_HEADER_V1* packet, int* packetLength) { - bool ret = false; - int len; unsigned char iv[16]; *packet = NULL; @@ -458,60 +421,28 @@ static bool decryptControlMessageToV1(PNVCTL_ENCRYPTED_PACKET_HEADER encPacket, memset(iv, 0, sizeof(iv)); iv[0] = (unsigned char)encPacket->seq; - if (EVP_DecryptInit_ex(cipherContext, EVP_aes_128_gcm(), NULL, NULL, NULL) != 1) { - goto gcm_cleanup; - } - - if (EVP_CIPHER_CTX_ctrl(cipherContext, EVP_CTRL_GCM_SET_IVLEN, 16, NULL) != 1) { - goto gcm_cleanup; - } - - if (EVP_DecryptInit_ex(cipherContext, NULL, NULL, - (const unsigned char*)StreamConfig.remoteInputAesKey, iv) != 1) { - goto gcm_cleanup; - } - int plaintextLength = encPacket->length - sizeof(encPacket->seq) - AES_GCM_TAG_LENGTH; *packet = malloc(plaintextLength); if (*packet == NULL) { - goto gcm_cleanup; + return false; } - // Decrypt into the packet we allocated - if (EVP_DecryptUpdate(cipherContext, (unsigned char*)*packet, &plaintextLength, - ((unsigned char*)(encPacket + 1)) + AES_GCM_TAG_LENGTH, plaintextLength) != 1) { - goto gcm_cleanup; + if (!PltDecryptMessage(decryptionCtx, ALGORITHM_AES_GCM, + (unsigned char*)StreamConfig.remoteInputAesKey, sizeof(StreamConfig.remoteInputAesKey), + iv, sizeof(iv), + (unsigned char*)(encPacket + 1), AES_GCM_TAG_LENGTH, // The tag is located right after the header + ((unsigned char*)(encPacket + 1)) + AES_GCM_TAG_LENGTH, plaintextLength, // The ciphertext is after the tag + (unsigned char*)*packet, &plaintextLength)) { + free(*packet); + return false; } - // Set the GCM tag before calling EVP_DecryptFinal_ex() - if (EVP_CIPHER_CTX_ctrl(cipherContext, EVP_CTRL_GCM_SET_TAG, 16, (unsigned char*)(encPacket + 1)) != 1) { - ret = -1; - goto gcm_cleanup; - } - - // GCM will never have additional plaintext here, but we need to call it to - // ensure that the GCM authentication tag is correct for this data. - if (EVP_DecryptFinal_ex(cipherContext, (unsigned char*)*packet, &len) != 1) { - goto gcm_cleanup; - } - LC_ASSERT(len == 0); - // Now we do an in-place V2 to V1 header conversion, so our existing parsing code doesn't have to change. // All we need to do is eliminate the new length field in V2 by shifting everything by 2 bytes. memmove(((unsigned char*)*packet) + 2, ((unsigned char*)*packet) + 4, plaintextLength - 4); *packetLength = plaintextLength - 2; - ret = true; - -gcm_cleanup: - EVP_CIPHER_CTX_reset(cipherContext); - - if (!ret && *packet) { - free(*packet); - *packet = NULL; - } - - return ret; + return true; } static bool sendMessageEnet(short ptype, short paylen, const void* payload) { @@ -760,16 +691,12 @@ static void controlReceiveThreadFunc(void* context) { continue; } - // We (ab)use this lock to protect the cryptoContext too - PltLockMutex(&enetMutex); ctlHdr = NULL; if (!decryptControlMessageToV1((PNVCTL_ENCRYPTED_PACKET_HEADER)event.packet->data, &ctlHdr, &packetLength)) { - PltUnlockMutex(&enetMutex); Limelog("Failed to decrypt control packet of size %d\n", event.packet->dataLength); enet_packet_destroy(event.packet); continue; } - PltUnlockMutex(&enetMutex); } else { // What do we do here??? diff --git a/src/InputStream.c b/src/InputStream.c index 6b0decd..f81f8e7 100644 --- a/src/InputStream.c +++ b/src/InputStream.c @@ -4,13 +4,10 @@ #include "LinkedBlockingQueue.h" #include "Input.h" -#include - static SOCKET inputSock = INVALID_SOCKET; static unsigned char currentAesIv[16]; static bool initialized; -static EVP_CIPHER_CTX* cipherContext; -static bool cipherInitialized; +static PPLT_CRYPTO_CONTEXT cryptoContext; static LINKED_BLOCKING_QUEUE packetQueue; static PLT_THREAD inputSendThread; @@ -18,8 +15,6 @@ static PLT_THREAD inputSendThread; #define MAX_INPUT_PACKET_SIZE 128 #define INPUT_STREAM_TIMEOUT_SEC 10 -#define ROUND_TO_PKCS7_PADDED_LEN(x) ((((x) + 15) / 16) * 16) - // Contains input stream packets typedef struct _PACKET_HOLDER { int packetLength; @@ -36,19 +31,13 @@ typedef struct _PACKET_HOLDER { LINKED_BLOCKING_QUEUE_ENTRY entry; } PACKET_HOLDER, *PPACKET_HOLDER; -#if OPENSSL_VERSION_NUMBER < 0x10100000L -#define EVP_CIPHER_CTX_reset(x) EVP_CIPHER_CTX_cleanup(x); EVP_CIPHER_CTX_init(x) -#endif - // Initializes the input stream int initializeInputStream(void) { memcpy(currentAesIv, StreamConfig.remoteInputAesIv, sizeof(currentAesIv)); - // Initialized on first packet - cipherInitialized = false; - LbqInitializeLinkedBlockingQueue(&packetQueue, 30); + cryptoContext = PltCreateCryptoContext(); return 0; } @@ -56,10 +45,7 @@ int initializeInputStream(void) { void destroyInputStream(void) { PLINKED_BLOCKING_QUEUE_ENTRY entry, nextEntry; - if (cipherInitialized) { - EVP_CIPHER_CTX_free(cipherContext); - cipherInitialized = false; - } + PltDestroyCryptoContext(cryptoContext); entry = LbqDestroyLinkedBlockingQueue(&packetQueue); @@ -73,113 +59,38 @@ void destroyInputStream(void) { } } -static int addPkcs7PaddingInPlace(unsigned char* plaintext, int plaintextLen) { - int i; - int paddedLength = ROUND_TO_PKCS7_PADDED_LEN(plaintextLen); - unsigned char paddingByte = (unsigned char)(16 - (plaintextLen % 16)); - - for (i = plaintextLen; i < paddedLength; i++) { - plaintext[i] = paddingByte; - } - - return paddedLength; -} - -static int encryptData(const unsigned char* plaintext, int plaintextLen, +static int encryptData(unsigned char* plaintext, int plaintextLen, unsigned char* ciphertext, int* ciphertextLen) { - int ret; - int len; - + // Starting in Gen 7, AES GCM is used for encryption if (AppVersionQuad[0] >= 7) { - if (!cipherInitialized) { - if ((cipherContext = EVP_CIPHER_CTX_new()) == NULL) { - return -1; - } - cipherInitialized = true; + if (!PltEncryptMessage(cryptoContext, ALGORITHM_AES_GCM, + (unsigned char*)StreamConfig.remoteInputAesKey, sizeof(StreamConfig.remoteInputAesKey), + currentAesIv, sizeof(currentAesIv), + ciphertext, 16, + plaintext, plaintextLen, + &ciphertext[16], ciphertextLen)) { + return -1; } - // Gen 7 servers use 128-bit AES GCM - if (EVP_EncryptInit_ex(cipherContext, EVP_aes_128_gcm(), NULL, NULL, NULL) != 1) { - ret = -1; - goto gcm_cleanup; - } - - // Gen 7 servers uses 16 byte IVs - if (EVP_CIPHER_CTX_ctrl(cipherContext, EVP_CTRL_GCM_SET_IVLEN, 16, NULL) != 1) { - ret = -1; - goto gcm_cleanup; - } - - // Initialize again but now provide our key and current IV - if (EVP_EncryptInit_ex(cipherContext, NULL, NULL, - (const unsigned char*)StreamConfig.remoteInputAesKey, currentAesIv) != 1) { - ret = -1; - goto gcm_cleanup; - } - - // Encrypt into the caller's buffer, leaving room for the auth tag to be prepended - if (EVP_EncryptUpdate(cipherContext, &ciphertext[16], ciphertextLen, plaintext, plaintextLen) != 1) { - ret = -1; - goto gcm_cleanup; - } - - // GCM encryption won't ever fill ciphertext here but we have to call it anyway - if (EVP_EncryptFinal_ex(cipherContext, ciphertext, &len) != 1) { - ret = -1; - goto gcm_cleanup; - } - LC_ASSERT(len == 0); - - // Read the tag into the caller's buffer - if (EVP_CIPHER_CTX_ctrl(cipherContext, EVP_CTRL_GCM_GET_TAG, 16, ciphertext) != 1) { - ret = -1; - goto gcm_cleanup; - } - // Increment the ciphertextLen to account for the tag *ciphertextLen += 16; - - ret = 0; - - gcm_cleanup: - EVP_CIPHER_CTX_reset(cipherContext); + return 0; } else { + // PKCS7 padding may need to be added in-place, so we must copy this into a buffer + // that can safely be modified. unsigned char paddedData[MAX_INPUT_PACKET_SIZE]; - int paddedLength; - - if (!cipherInitialized) { - if ((cipherContext = EVP_CIPHER_CTX_new()) == NULL) { - ret = -1; - goto cbc_cleanup; - } - cipherInitialized = true; - // Prior to Gen 7, 128-bit AES CBC is used for encryption - if (EVP_EncryptInit_ex(cipherContext, EVP_aes_128_cbc(), NULL, - (const unsigned char*)StreamConfig.remoteInputAesKey, currentAesIv) != 1) { - ret = -1; - goto cbc_cleanup; - } - } - - // Pad the data to the required block length memcpy(paddedData, plaintext, plaintextLen); - paddedLength = addPkcs7PaddingInPlace(paddedData, plaintextLen); - - if (EVP_EncryptUpdate(cipherContext, ciphertext, ciphertextLen, paddedData, paddedLength) != 1) { - ret = -1; - goto cbc_cleanup; - } - - ret = 0; - cbc_cleanup: - // Nothing to do - ; + // Prior to Gen 7, 128-bit AES CBC is used for encryption + return PltEncryptMessage(cryptoContext, ALGORITHM_AES_CBC, + (unsigned char*)StreamConfig.remoteInputAesKey, sizeof(StreamConfig.remoteInputAesKey), + currentAesIv, sizeof(currentAesIv), + NULL, 0, + paddedData, plaintextLen, + ciphertext, ciphertextLen) ? 0 : -1; } - - return ret; } // Input thread proc diff --git a/src/Limelight-internal.h b/src/Limelight-internal.h index 88b4d31..7a768f3 100644 --- a/src/Limelight-internal.h +++ b/src/Limelight-internal.h @@ -4,6 +4,7 @@ #include "Platform.h" #include "PlatformSockets.h" #include "PlatformThreads.h" +#include "PlatformCrypto.h" #include "Video.h" #include "RtpFecQueue.h" diff --git a/src/PlatformCrypto.c b/src/PlatformCrypto.c new file mode 100644 index 0000000..ef9095f --- /dev/null +++ b/src/PlatformCrypto.c @@ -0,0 +1,197 @@ +#include "Limelight-internal.h" + +#include +#include + +static int addPkcs7PaddingInPlace(unsigned char* plaintext, int plaintextLen) { + int paddedLength = ROUND_TO_PKCS7_PADDED_LEN(plaintextLen); + unsigned char paddingByte = (unsigned char)(16 - (plaintextLen % 16)); + + memset(&plaintext[plaintextLen], paddingByte, paddedLength - plaintextLen); + + return paddedLength; +} + +// For CBC modes, inputData buffer must be allocated with length rounded up to next multiple of 16 and inputData buffer may be modified! +bool PltEncryptMessage(PPLT_CRYPTO_CONTEXT ctx, int algorithm, + unsigned char* key, int keyLength, + unsigned char* iv, int ivLength, + unsigned char* tag, int tagLength, + unsigned char* inputData, int inputDataLength, + unsigned char* outputData, int* outputDataLength) { + bool ret = false; + const EVP_CIPHER* cipher; + + switch (algorithm) { + case ALGORITHM_AES_CBC: + LC_ASSERT(keyLength == 16); + LC_ASSERT(tag == NULL); + LC_ASSERT(tagLength == 0); + cipher = EVP_aes_128_cbc(); + break; + case ALGORITHM_AES_GCM: + LC_ASSERT(keyLength == 16); + LC_ASSERT(tag != NULL); + LC_ASSERT(tagLength > 0); + cipher = EVP_aes_128_gcm(); + break; + default: + LC_ASSERT(false); + return false; + } + + if (algorithm == ALGORITHM_AES_GCM) { + if (EVP_EncryptInit_ex(ctx->ctx, cipher, NULL, NULL, NULL) != 1) { + goto cleanup; + } + + if (EVP_CIPHER_CTX_ctrl(ctx->ctx, EVP_CTRL_GCM_SET_IVLEN, ivLength, NULL) != 1) { + goto cleanup; + } + + if (EVP_EncryptInit_ex(ctx->ctx, NULL, NULL, key, iv) != 1) { + goto cleanup; + } + } + else { + if (!ctx->initialized) { + if (EVP_EncryptInit_ex(ctx->ctx, cipher, NULL, key, iv) != 1) { + goto cleanup; + } + + ctx->initialized = true; + } + + inputDataLength = addPkcs7PaddingInPlace(inputData, inputDataLength); + } + + if (EVP_EncryptUpdate(ctx->ctx, outputData, outputDataLength, inputData, inputDataLength) != 1) { + goto cleanup; + } + + if (algorithm == ALGORITHM_AES_GCM) { + int len; + + // GCM encryption won't ever fill ciphertext here but we have to call it anyway + if (EVP_EncryptFinal_ex(ctx->ctx, outputData, &len) != 1) { + goto cleanup; + } + LC_ASSERT(len == 0); + + if (EVP_CIPHER_CTX_ctrl(ctx->ctx, EVP_CTRL_GCM_GET_TAG, tagLength, tag) != 1) { + goto cleanup; + } + } + + ret = true; + +cleanup: + if (algorithm == ALGORITHM_AES_GCM) { + EVP_CIPHER_CTX_reset(ctx->ctx); + } + return ret; +} + +bool PltDecryptMessage(PPLT_CRYPTO_CONTEXT ctx, int algorithm, + unsigned char* key, int keyLength, + unsigned char* iv, int ivLength, + unsigned char* tag, int tagLength, + unsigned char* inputData, int inputDataLength, + unsigned char* outputData, int* outputDataLength) { + bool ret = false; + const EVP_CIPHER* cipher; + + switch (algorithm) { + case ALGORITHM_AES_CBC: + LC_ASSERT(keyLength == 16); + LC_ASSERT(tag == NULL); + LC_ASSERT(tagLength == 0); + cipher = EVP_aes_128_cbc(); + break; + case ALGORITHM_AES_GCM: + LC_ASSERT(keyLength == 16); + LC_ASSERT(tag != NULL); + LC_ASSERT(tagLength > 0); + cipher = EVP_aes_128_gcm(); + break; + default: + LC_ASSERT(false); + return false; + } + + if (algorithm == ALGORITHM_AES_GCM) { + if (EVP_DecryptInit_ex(ctx->ctx, cipher, NULL, NULL, NULL) != 1) { + goto cleanup; + } + + if (EVP_CIPHER_CTX_ctrl(ctx->ctx, EVP_CTRL_GCM_SET_IVLEN, ivLength, NULL) != 1) { + goto cleanup; + } + + if (EVP_DecryptInit_ex(ctx->ctx, NULL, NULL, key, iv) != 1) { + goto cleanup; + } + } + else { + if (!ctx->initialized) { + if (EVP_DecryptInit_ex(ctx->ctx, cipher, NULL, key, iv) != 1) { + goto cleanup; + } + + ctx->initialized = true; + } + } + + if (EVP_DecryptUpdate(ctx->ctx, outputData, outputDataLength, inputData, inputDataLength) != 1) { + goto cleanup; + } + + if (algorithm == ALGORITHM_AES_GCM) { + int len; + + // Set the GCM tag before calling EVP_DecryptFinal_ex() + if (EVP_CIPHER_CTX_ctrl(ctx->ctx, EVP_CTRL_GCM_SET_TAG, tagLength, tag) != 1) { + goto cleanup; + } + + // GCM will never have additional plaintext here, but we need to call it to + // ensure that the GCM authentication tag is correct for this data. + if (EVP_DecryptFinal_ex(ctx->ctx, outputData, &len) != 1) { + goto cleanup; + } + LC_ASSERT(len == 0); + } + + ret = true; + +cleanup: + if (algorithm == ALGORITHM_AES_GCM) { + EVP_CIPHER_CTX_reset(ctx->ctx); + } + return ret; +} + +PPLT_CRYPTO_CONTEXT PltCreateCryptoContext(void) { + PPLT_CRYPTO_CONTEXT ctx = malloc(sizeof(*ctx)); + if (!ctx) { + return NULL; + } + + ctx->initialized = false; + ctx->ctx = EVP_CIPHER_CTX_new(); + if (!ctx->ctx) { + free(ctx); + return NULL; + } + + return ctx; +} + +void PltDestroyCryptoContext(PPLT_CRYPTO_CONTEXT ctx) { + EVP_CIPHER_CTX_free(ctx->ctx); + free(ctx); +} + +void PltGenerateRandomData(unsigned char* data, int length) { + RAND_bytes(data, length); +} diff --git a/src/PlatformCrypto.h b/src/PlatformCrypto.h new file mode 100644 index 0000000..6301823 --- /dev/null +++ b/src/PlatformCrypto.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +// Hide the real OpenSSL definition from other code +typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX; + +typedef struct _PLT_CRYPTO_CONTEXT { + bool initialized; // Used for CBC only + EVP_CIPHER_CTX* ctx; +} PLT_CRYPTO_CONTEXT, *PPLT_CRYPTO_CONTEXT; + +#define ROUND_TO_PKCS7_PADDED_LEN(x) ((((x) + 15) / 16) * 16) + +PPLT_CRYPTO_CONTEXT PltCreateCryptoContext(); +void PltDestroyCryptoContext(PPLT_CRYPTO_CONTEXT ctx); + +#define ALGORITHM_AES_CBC 1 +#define ALGORITHM_AES_GCM 2 + +bool PltEncryptMessage(PPLT_CRYPTO_CONTEXT ctx, int algorithm, + unsigned char* key, int keyLength, + unsigned char* iv, int ivLength, + unsigned char* tag, int tagLength, + unsigned char* inputData, int inputDataLength, + unsigned char* outputData, int* outputDataLength); + +bool PltDecryptMessage(PPLT_CRYPTO_CONTEXT ctx, int algorithm, + unsigned char* key, int keyLength, + unsigned char* iv, int ivLength, + unsigned char* tag, int tagLength, + unsigned char* inputData, int inputDataLength, + unsigned char* outputData, int* outputDataLength); + +void PltGenerateRandomData(unsigned char* data, int length); diff --git a/src/SimpleStun.c b/src/SimpleStun.c index 13bec29..2dd9197 100644 --- a/src/SimpleStun.c +++ b/src/SimpleStun.c @@ -1,7 +1,5 @@ #include "Limelight-internal.h" -#include - #define STUN_RECV_TIMEOUT_SEC 3 #define STUN_MESSAGE_BINDING_REQUEST 0x0001 @@ -85,7 +83,7 @@ int LiFindExternalAddressIP4(const char* stunServer, unsigned short stunPort, un reqMsg.messageType = htons(STUN_MESSAGE_BINDING_REQUEST); reqMsg.messageLength = 0; reqMsg.magicCookie = htonl(STUN_MESSAGE_COOKIE); - RAND_bytes(reqMsg.transactionId, sizeof(reqMsg.transactionId)); + PltGenerateRandomData(reqMsg.transactionId, sizeof(reqMsg.transactionId)); bytesRead = SOCKET_ERROR; for (i = 0; i < STUN_RECV_TIMEOUT_SEC * 1000 / UDP_RECV_POLL_TIMEOUT_MS && bytesRead <= 0; i++) {