From 5bff1d0fdfb66dacad16ae89c535f77e7de01290 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 8 Oct 2015 16:26:37 -0400 Subject: [PATCH] libwinpr-crypto: add rand and RC4 functions with OpenSSL/mbedtls --- winpr/include/winpr/crypto.h | 52 ++++++++++++++++++++ winpr/libwinpr/crypto/CMakeLists.txt | 2 + winpr/libwinpr/crypto/cipher.c | 70 +++++++++++++++++++++++++++ winpr/libwinpr/crypto/rand.c | 51 +++++++++++++++++++ winpr/libwinpr/crypto/test/CMakeLists.txt | 2 + winpr/libwinpr/crypto/test/TestCryptoCipher.c | 52 ++++++++++++++++++++ winpr/libwinpr/crypto/test/TestCryptoRand.c | 25 ++++++++++ 7 files changed, 254 insertions(+) create mode 100644 winpr/libwinpr/crypto/cipher.c create mode 100644 winpr/libwinpr/crypto/rand.c create mode 100644 winpr/libwinpr/crypto/test/TestCryptoCipher.c create mode 100644 winpr/libwinpr/crypto/test/TestCryptoRand.c diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index 0d37bc5..1ac44b0 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -802,5 +802,57 @@ WINPR_API int winpr_HMAC(int md, const BYTE* key, size_t keylen, const BYTE* inp } #endif +/** + * Random Number Generation + */ + +#ifdef __cplusplus +extern "C" { +#endif + +WINPR_API int winpr_RAND(BYTE* output, size_t len); + +#ifdef __cplusplus +} +#endif + +/** + * 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; + +#ifdef __cplusplus +extern "C" { +#endif + +WINPR_API void winpr_RC4_Init(WINPR_RC4_CTX* ctx, const BYTE* key, size_t keylen); +WINPR_API int winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output); +WINPR_API void winpr_RC4_Final(WINPR_RC4_CTX* ctx); + +#ifdef __cplusplus +} +#endif + #endif /* WINPR_CRYPTO_H */ diff --git a/winpr/libwinpr/crypto/CMakeLists.txt b/winpr/libwinpr/crypto/CMakeLists.txt index a14df8c..d584af7 100644 --- a/winpr/libwinpr/crypto/CMakeLists.txt +++ b/winpr/libwinpr/crypto/CMakeLists.txt @@ -17,6 +17,8 @@ winpr_module_add( hash.c + rand.c + cipher.c cert.c crypto.c crypto.h) diff --git a/winpr/libwinpr/crypto/cipher.c b/winpr/libwinpr/crypto/cipher.c new file mode 100644 index 0000000..ea77634 --- /dev/null +++ b/winpr/libwinpr/crypto/cipher.c @@ -0,0 +1,70 @@ +/** + * WinPR: Windows Portable Runtime + * + * Copyright 2015 Marc-Andre Moreau + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +#ifdef WITH_OPENSSL +#include +#include +#include +#endif + +#ifdef WITH_MBEDTLS +#include +#include +#include +#endif + +/** + * RC4 + */ + +void winpr_RC4_Init(WINPR_RC4_CTX* ctx, const BYTE* key, size_t keylen) +{ +#if defined(WITH_OPENSSL) + RC4_set_key((RC4_KEY*) ctx, keylen, key); +#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C) + mbedtls_arc4_init((mbedtls_arc4_context*) ctx); + mbedtls_arc4_setup((mbedtls_arc4_context*) ctx, key, keylen); +#endif +} + +int winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output) +{ +#if defined(WITH_OPENSSL) + RC4((RC4_KEY*) ctx, length, input, output); +#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C) + mbedtls_arc4_crypt((mbedtls_arc4_context*) ctx, length, input, output); +#endif + return 0; +} + +void winpr_RC4_Final(WINPR_RC4_CTX* ctx) +{ +#if defined(WITH_OPENSSL) + +#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C) + mbedtls_arc4_free((mbedtls_arc4_context*) ctx); +#endif +} diff --git a/winpr/libwinpr/crypto/rand.c b/winpr/libwinpr/crypto/rand.c new file mode 100644 index 0000000..0dc03ed --- /dev/null +++ b/winpr/libwinpr/crypto/rand.c @@ -0,0 +1,51 @@ +/** + * WinPR: Windows Portable Runtime + * + * Copyright 2015 Marc-Andre Moreau + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +#ifdef WITH_OPENSSL +#include +#endif + +#ifdef WITH_MBEDTLS +#include +#include +#include +#include +#endif + +#undef WITH_OPENSSL + +int winpr_RAND(BYTE* output, size_t len) +{ +#if defined(WITH_OPENSSL) + RAND_bytes(output, len); +#elif defined(WITH_MBEDTLS) && defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_state hs; + mbedtls_havege_init(&hs); + mbedtls_havege_random(&hs, output, len); + mbedtls_havege_free(&hs); +#endif + return 0; +} diff --git a/winpr/libwinpr/crypto/test/CMakeLists.txt b/winpr/libwinpr/crypto/test/CMakeLists.txt index 5646749..4fb9aa0 100644 --- a/winpr/libwinpr/crypto/test/CMakeLists.txt +++ b/winpr/libwinpr/crypto/test/CMakeLists.txt @@ -6,6 +6,8 @@ set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c) set(${MODULE_PREFIX}_TESTS TestCryptoHash.c + TestCryptoRand.c + TestCryptoCipher.c TestCryptoProtectData.c TestCryptoProtectMemory.c TestCryptoCertEnumCertificatesInStore.c) diff --git a/winpr/libwinpr/crypto/test/TestCryptoCipher.c b/winpr/libwinpr/crypto/test/TestCryptoCipher.c new file mode 100644 index 0000000..7504942 --- /dev/null +++ b/winpr/libwinpr/crypto/test/TestCryptoCipher.c @@ -0,0 +1,52 @@ + +#include +#include +#include + +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"; + +int test_crypto_cipher_rc4() +{ + size_t len; + BYTE* text; + WINPR_RC4_CTX ctx; + + len = strlen(TEST_RC4_PLAINTEXT); + + text = (BYTE*) calloc(1, len); + + if (!text) + return -1; + + winpr_RC4_Init(&ctx, TEST_RC4_KEY, strlen((char*) TEST_RC4_KEY)); + winpr_RC4_Update(&ctx, len, (BYTE*) TEST_RC4_PLAINTEXT, text); + winpr_RC4_Final(&ctx); + + if (memcmp(text, TEST_RC4_CIPHERTEXT, len) != 0) + { + char* actual; + char* expected; + + 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); + + free(actual); + free(expected); + + return -1; + } + + return 0; +} + +int TestCryptoCipher(int argc, char* argv[]) +{ + if (!test_crypto_cipher_rc4()) + return -1; + + return 0; +} diff --git a/winpr/libwinpr/crypto/test/TestCryptoRand.c b/winpr/libwinpr/crypto/test/TestCryptoRand.c new file mode 100644 index 0000000..60620f8 --- /dev/null +++ b/winpr/libwinpr/crypto/test/TestCryptoRand.c @@ -0,0 +1,25 @@ + +#include +#include +#include + +int TestCryptoRand(int argc, char* argv[]) +{ + char* str; + BYTE rnd[16]; + + ZeroMemory(rnd, sizeof(rnd)); + + winpr_RAND(rnd, sizeof(rnd)); + + str = winpr_BinToHexString(rnd, sizeof(rnd), FALSE); + //fprintf(stderr, "Rand: %s\n", str); + free(str); + + if (memcmp(rnd, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) == 0) + { + return -1; + } + + return 0; +} -- 2.7.4