libwinpr-crypto: add rand and RC4 functions with OpenSSL/mbedtls
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Thu, 8 Oct 2015 20:26:37 +0000 (16:26 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Thu, 8 Oct 2015 20:26:37 +0000 (16:26 -0400)
winpr/include/winpr/crypto.h
winpr/libwinpr/crypto/CMakeLists.txt
winpr/libwinpr/crypto/cipher.c [new file with mode: 0644]
winpr/libwinpr/crypto/rand.c [new file with mode: 0644]
winpr/libwinpr/crypto/test/CMakeLists.txt
winpr/libwinpr/crypto/test/TestCryptoCipher.c [new file with mode: 0644]
winpr/libwinpr/crypto/test/TestCryptoRand.c [new file with mode: 0644]

index 0d37bc5..1ac44b0 100644 (file)
@@ -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 */
 
index a14df8c..d584af7 100644 (file)
@@ -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 (file)
index 0000000..ea77634
--- /dev/null
@@ -0,0 +1,70 @@
+/**
+ * WinPR: Windows Portable Runtime
+ *
+ * Copyright 2015 Marc-Andre Moreau <marcandre.moreau@gmail.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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <winpr/crt.h>
+
+#include <winpr/crypto.h>
+
+#ifdef WITH_OPENSSL
+#include <openssl/aes.h>
+#include <openssl/rc4.h>
+#include <openssl/des.h>
+#endif
+
+#ifdef WITH_MBEDTLS
+#include <mbedtls/aes.h>
+#include <mbedtls/arc4.h>
+#include <mbedtls/des.h>
+#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 (file)
index 0000000..0dc03ed
--- /dev/null
@@ -0,0 +1,51 @@
+/**
+ * WinPR: Windows Portable Runtime
+ *
+ * Copyright 2015 Marc-Andre Moreau <marcandre.moreau@gmail.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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <winpr/crt.h>
+
+#include <winpr/crypto.h>
+
+#ifdef WITH_OPENSSL
+#include <openssl/rand.h>
+#endif
+
+#ifdef WITH_MBEDTLS
+#include <mbedtls/md.h>
+#include <mbedtls/entropy.h>
+#include <mbedtls/havege.h>
+#include <mbedtls/hmac_drbg.h>
+#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;
+}
index 5646749..4fb9aa0 100644 (file)
@@ -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 (file)
index 0000000..7504942
--- /dev/null
@@ -0,0 +1,52 @@
+
+#include <winpr/crt.h>
+#include <winpr/print.h>
+#include <winpr/crypto.h>
+
+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 (file)
index 0000000..60620f8
--- /dev/null
@@ -0,0 +1,25 @@
+
+#include <winpr/crt.h>
+#include <winpr/print.h>
+#include <winpr/crypto.h>
+
+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;
+}