mirror of https://github.com/FreeRDP/FreeRDP
[winpr,crypto] add internal rc4 replacement
RDP relies on RC4 for some operations, so we need these to successfully log on to windows machines. This is a replacement for use with SSL libraries that have already deprecated these.
This commit is contained in:
parent
06bd759c64
commit
0c7330720f
|
@ -64,6 +64,7 @@ option(WITH_DEBUG_SYMBOLS "Pack debug symbols to installer" OFF)
|
|||
option(WITH_NATIVE_SSPI "Use native SSPI modules" ${NATIVE_SSPI})
|
||||
option(WITH_SMARTCARD_INSPECT "Enable SmartCard API Inspector" OFF)
|
||||
option(WITH_DEBUG_MUTEX "Print mutex debug messages" ${DEFAULT_DEBUG_OPTION})
|
||||
option(WITH_INTERNAL_RC4 "Use compiled in rc4 functions instead of OpenSSL/MBedTLS" OFF)
|
||||
option(WITH_INTERNAL_MD4 "Use compiled in md4 hash functions instead of OpenSSL/MBedTLS" OFF)
|
||||
option(WITH_INTERNAL_MD5 "Use compiled in md5 hash functions instead of OpenSSL/MBedTLS" OFF)
|
||||
option(WITH_UNICODE_BUILTIN "Use built-in Unicode conversion (don't use system-provided libraries)" OFF)
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#cmakedefine WITH_EVENTFD_READ_WRITE
|
||||
|
||||
#cmakedefine WITH_NATIVE_SSPI
|
||||
#cmakedefine WITH_INTERNAL_RC4
|
||||
#cmakedefine WITH_INTERNAL_MD4
|
||||
#cmakedefine WITH_INTERNAL_MD5
|
||||
|
||||
|
|
|
@ -23,6 +23,10 @@ set(SRCS
|
|||
crypto.c
|
||||
crypto.h
|
||||
)
|
||||
if (WITH_INTERNAL_RC4)
|
||||
list(APPEND SRCS rc4.c rc4.h)
|
||||
endif()
|
||||
|
||||
if (WITH_INTERNAL_MD4)
|
||||
list(APPEND SRCS md4.c md4.h)
|
||||
endif()
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
#include "../log.h"
|
||||
#define TAG WINPR_TAG("crypto.cipher")
|
||||
|
||||
#if defined(WITH_INTERNAL_RC4)
|
||||
#include "rc4.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/rc4.h>
|
||||
|
@ -46,23 +50,21 @@
|
|||
|
||||
struct winpr_rc4_ctx_private_st
|
||||
{
|
||||
union
|
||||
{
|
||||
#if defined(WITH_INTERNAL_RC4)
|
||||
winpr_int_RC4_CTX* ictx;
|
||||
#else
|
||||
#if defined(WITH_OPENSSL)
|
||||
EVP_CIPHER_CTX* ctx;
|
||||
EVP_CIPHER_CTX* ctx;
|
||||
#endif
|
||||
#if defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C)
|
||||
mbedtls_arc4_context mctx;
|
||||
mbedtls_arc4_context* mctx;
|
||||
#endif
|
||||
#endif
|
||||
} u;
|
||||
};
|
||||
|
||||
static WINPR_RC4_CTX* winpr_RC4_New_Internal(const BYTE* key, size_t keylen, BOOL override_fips)
|
||||
{
|
||||
WINPR_RC4_CTX* ctx = NULL;
|
||||
#if defined(WITH_OPENSSL)
|
||||
const EVP_CIPHER* evp = NULL;
|
||||
#endif
|
||||
|
||||
if (!key || (keylen == 0))
|
||||
return NULL;
|
||||
|
@ -71,13 +73,19 @@ static WINPR_RC4_CTX* winpr_RC4_New_Internal(const BYTE* key, size_t keylen, BOO
|
|||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
#if defined(WITH_INTERNAL_RC4)
|
||||
WINPR_UNUSED(override_fips);
|
||||
ctx->ictx = winpr_int_rc4_new(key, keylen);
|
||||
if (!ctx->ictx)
|
||||
goto fail;
|
||||
#elif defined(WITH_OPENSSL)
|
||||
const EVP_CIPHER* evp = NULL;
|
||||
|
||||
if (keylen > INT_MAX)
|
||||
goto fail;
|
||||
|
||||
ctx->u.ctx = EVP_CIPHER_CTX_new();
|
||||
if (!ctx->u.ctx)
|
||||
ctx->ctx = EVP_CIPHER_CTX_new();
|
||||
if (!ctx->ctx)
|
||||
goto fail;
|
||||
|
||||
evp = EVP_rc4();
|
||||
|
@ -85,27 +93,29 @@ static WINPR_RC4_CTX* winpr_RC4_New_Internal(const BYTE* key, size_t keylen, BOO
|
|||
if (!evp)
|
||||
goto fail;
|
||||
|
||||
EVP_CIPHER_CTX_init(ctx->u.ctx);
|
||||
if (EVP_EncryptInit_ex(ctx->u.ctx, evp, NULL, NULL, NULL) != 1)
|
||||
EVP_CIPHER_CTX_init(ctx->ctx);
|
||||
if (EVP_EncryptInit_ex(ctx->ctx, evp, NULL, NULL, NULL) != 1)
|
||||
goto fail;
|
||||
|
||||
/* EVP_CIPH_FLAG_NON_FIPS_ALLOW does not exist before openssl 1.0.1 */
|
||||
#if !(OPENSSL_VERSION_NUMBER < 0x10001000L)
|
||||
|
||||
if (override_fips == TRUE)
|
||||
EVP_CIPHER_CTX_set_flags(ctx->u.ctx, EVP_CIPH_FLAG_NON_FIPS_ALLOW);
|
||||
EVP_CIPHER_CTX_set_flags(ctx->ctx, EVP_CIPH_FLAG_NON_FIPS_ALLOW);
|
||||
|
||||
#endif
|
||||
EVP_CIPHER_CTX_set_key_length(ctx->u.ctx, (int)keylen);
|
||||
if (EVP_EncryptInit_ex(ctx->u.ctx, NULL, NULL, key, NULL) != 1)
|
||||
EVP_CIPHER_CTX_set_key_length(ctx->ctx, (int)keylen);
|
||||
if (EVP_EncryptInit_ex(ctx->ctx, NULL, NULL, key, NULL) != 1)
|
||||
goto fail;
|
||||
|
||||
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C)
|
||||
|
||||
ctx->u.mctx = calloc(1, sizeof(mbedtls_arc4_context)) if (!ctx->u.mctx) goto fail;
|
||||
ctx->mctx = calloc(1, sizeof(mbedtls_arc4_context));
|
||||
if (!ctx->mctx)
|
||||
goto fail;
|
||||
|
||||
mbedtls_arc4_init(ctx->u.mctx);
|
||||
mbedtls_arc4_setup(ctx->u.mctx, key, (unsigned int)keylen);
|
||||
mbedtls_arc4_init(ctx->mctx);
|
||||
mbedtls_arc4_setup(ctx->mctx, key, (unsigned int)keylen);
|
||||
#endif
|
||||
return ctx;
|
||||
|
||||
|
@ -127,18 +137,23 @@ WINPR_RC4_CTX* winpr_RC4_New(const BYTE* key, size_t keylen)
|
|||
BOOL winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
#if defined(WITH_OPENSSL)
|
||||
WINPR_ASSERT(ctx->u.ctx);
|
||||
|
||||
#if defined(WITH_INTERNAL_RC4)
|
||||
return winpr_int_rc4_update(ctx->ictx, length, input, output);
|
||||
#elif defined(WITH_OPENSSL)
|
||||
WINPR_ASSERT(ctx->ctx);
|
||||
int outputLength;
|
||||
if (length > INT_MAX)
|
||||
return FALSE;
|
||||
|
||||
EVP_CipherUpdate(ctx->u.ctx, output, &outputLength, input, (int)length);
|
||||
WINPR_ASSERT(ctx);
|
||||
if (EVP_CipherUpdate(ctx->ctx, output, &outputLength, input, (int)length) != 1)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C)
|
||||
|
||||
WINPR_ASSERT(ctx->u.mctx);
|
||||
if (mbedtls_arc4_crypt(ctx->u.mctx, length, input, output) == 0)
|
||||
WINPR_ASSERT(ctx->mctx);
|
||||
if (mbedtls_arc4_crypt(ctx->mctx, length, input, output) == 0)
|
||||
return TRUE;
|
||||
|
||||
#endif
|
||||
|
@ -150,10 +165,12 @@ void winpr_RC4_Free(WINPR_RC4_CTX* ctx)
|
|||
if (!ctx)
|
||||
return;
|
||||
|
||||
#if defined(WITH_OPENSSL)
|
||||
EVP_CIPHER_CTX_free(ctx->u.ctx);
|
||||
#if defined(WITH_INTERNAL_RC4)
|
||||
winpr_int_rc4_free(ctx->ictx);
|
||||
#elif defined(WITH_OPENSSL)
|
||||
EVP_CIPHER_CTX_free(ctx->ctx);
|
||||
#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C)
|
||||
mbedtls_arc4_free(ctx->u.mctx);
|
||||
mbedtls_arc4_free(ctx->mctx);
|
||||
#endif
|
||||
free(ctx);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* RC4 implementation for RDP
|
||||
*
|
||||
* Copyright 2023 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2023 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 <winpr/assert.h>
|
||||
|
||||
#include "rc4.h"
|
||||
|
||||
#define CTX_SIZE 256
|
||||
|
||||
struct winpr_int_rc4_ctx
|
||||
{
|
||||
size_t i;
|
||||
size_t j;
|
||||
BYTE s[CTX_SIZE];
|
||||
BYTE t[CTX_SIZE];
|
||||
};
|
||||
|
||||
static void swap(BYTE* p1, BYTE* p2)
|
||||
{
|
||||
BYTE t = *p1;
|
||||
*p1 = *p2;
|
||||
*p2 = t;
|
||||
}
|
||||
|
||||
winpr_int_RC4_CTX* winpr_int_rc4_new(const BYTE* key, size_t keylength)
|
||||
{
|
||||
winpr_int_RC4_CTX* ctx = calloc(1, sizeof(winpr_int_RC4_CTX));
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
for (size_t i = 0; i < CTX_SIZE; i++)
|
||||
{
|
||||
ctx->s[i] = i;
|
||||
ctx->t[i] = key[i % keylength];
|
||||
}
|
||||
|
||||
size_t j = 0;
|
||||
for (size_t i = 0; i < CTX_SIZE; i++)
|
||||
{
|
||||
j = (j + ctx->s[i] + ctx->t[i]) % CTX_SIZE;
|
||||
swap(&ctx->s[i], &ctx->s[j]);
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void winpr_int_rc4_free(winpr_int_RC4_CTX* ctx)
|
||||
{
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
BOOL winpr_int_rc4_update(winpr_int_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
UINT32 t1 = ctx->i;
|
||||
UINT32 t2 = ctx->j;
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
t1 = (t1 + 1) % CTX_SIZE;
|
||||
t2 = (t2 + ctx->s[t1]) % CTX_SIZE;
|
||||
swap(&ctx->s[t1], &ctx->s[t2]);
|
||||
|
||||
const size_t idx = ((size_t)ctx->s[t1] + ctx->s[t2]) % CTX_SIZE;
|
||||
const BYTE val = ctx->s[idx];
|
||||
const BYTE out = *input++ ^ val;
|
||||
*output++ = out;
|
||||
}
|
||||
|
||||
ctx->i = t1;
|
||||
ctx->j = t2;
|
||||
return TRUE;
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* WinPR: Windows Portable Runtime
|
||||
* RC4 implementation for RDP
|
||||
*
|
||||
* Copyright 2023 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2023 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 WINPR_RC4_H
|
||||
#define WINPR_RC4_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
typedef struct winpr_int_rc4_ctx winpr_int_RC4_CTX;
|
||||
|
||||
winpr_int_RC4_CTX* winpr_int_rc4_new(const BYTE* key, size_t keylength);
|
||||
BOOL winpr_int_rc4_update(winpr_int_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output);
|
||||
void winpr_int_rc4_free(winpr_int_RC4_CTX* ctx);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue