#endif
/**
+ * 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;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+WINPR_API void winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, int md);
+WINPR_API void winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const BYTE* input, size_t ilen);
+WINPR_API void winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, BYTE* output);
+WINPR_API void winpr_Digest(int md, const BYTE* input, size_t ilen, BYTE* output);
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
* Random Number Generation
*/
}
#endif
+/**
+ * Key Generation
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int winpr_openssl_BytesToKey(int cipher, int md, const BYTE* salt, const BYTE* data, int datal, int count, BYTE* key, BYTE* iv);
+
+#ifdef __cplusplus
+}
+#endif
+
#endif /* WINPR_CRYPTO_H */
#endif
#ifdef WITH_MBEDTLS
+#include <mbedtls/md.h>
#include <mbedtls/aes.h>
#include <mbedtls/arc4.h>
#include <mbedtls/des.h>
* Generic Cipher API
*/
+#ifdef WITH_OPENSSL
+extern const EVP_MD* winpr_openssl_get_evp_md(int md);
+#endif
+
+#ifdef WITH_MBEDTLS
+extern mbedtls_md_type_t winpr_mbedtls_get_md_type(int md);
+#endif
+
#if defined(WITH_OPENSSL)
const EVP_CIPHER* winpr_openssl_get_evp_cipher(int cipher)
{
mbedtls_cipher_free((mbedtls_cipher_context_t*) ctx);
#endif
}
+
+/**
+ * Key Generation
+ */
+
+int winpr_openssl_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():
+ * https://www.openssl.org/docs/manmaster/crypto/EVP_BytesToKey.html
+ */
+
+#if defined(WITH_OPENSSL)
+ const EVP_MD* evp_md;
+ const EVP_CIPHER* evp_cipher;
+ evp_md = winpr_openssl_get_evp_md(md);
+ evp_cipher = winpr_openssl_get_evp_cipher(cipher);
+ return EVP_BytesToKey(evp_cipher, evp_md, salt, data, datal, count, key, iv);
+#elif defined(WITH_MBEDTLS)
+ int rv = 0;
+ BYTE md_buf[64];
+ int niv, nkey, addmd = 0;
+ unsigned int mds = 0, i;
+ mbedtls_md_context_t ctx;
+ const mbedtls_md_info_t* md_info;
+ mbedtls_cipher_type_t cipher_type;
+ const mbedtls_cipher_info_t* cipher_info;
+
+ mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md);
+ md_info = mbedtls_md_info_from_type(md_type);
+
+ cipher_type = winpr_mbedtls_get_cipher_type(cipher);
+ cipher_info = mbedtls_cipher_info_from_type(cipher_type);
+
+ nkey = cipher_info->key_bitlen / 8;
+ niv = cipher_info->iv_size;
+
+ if ((nkey > 64) || (niv > 64))
+ return 0;
+
+ if (!data)
+ return nkey;
+
+ mbedtls_md_init(&ctx);
+
+ while (1)
+ {
+ if (mbedtls_md_setup(&ctx, md_info, 0) != 0)
+ return 0;
+
+ if (mbedtls_md_starts(&ctx) != 0)
+ return 0;
+
+ if (addmd++)
+ {
+ if (mbedtls_md_update(&ctx, &(md_buf[0]), mds) != 0)
+ goto err;
+ }
+
+ if (mbedtls_md_update(&ctx, data, datal) != 0)
+ goto err;
+
+ if (salt)
+ {
+ if (mbedtls_md_update(&ctx, salt, 8) != 0)
+ goto err;
+ }
+
+ if (mbedtls_md_finish(&ctx, &(md_buf[0])) != 0)
+ goto err;
+
+ mds = mbedtls_md_get_size(md_info);
+
+ for (i = 1; i < (unsigned int) count; i++)
+ {
+ if (mbedtls_md_starts(&ctx) != 0)
+ goto err;
+ if (mbedtls_md_update(&ctx, &(md_buf[0]), mds) != 0)
+ goto err;
+ if (mbedtls_md_finish(&ctx, &(md_buf[0])) != 0)
+ goto err;
+ }
+
+ i = 0;
+
+ if (nkey)
+ {
+ while (1)
+ {
+ if (nkey == 0)
+ break;
+ if (i == mds)
+ break;
+ if (key)
+ *(key++) = md_buf[i];
+ nkey--;
+ i++;
+ }
+ }
+
+ if (niv && (i != mds))
+ {
+ while (1)
+ {
+ if (niv == 0)
+ break;
+ if (i == mds)
+ break;
+ if (iv)
+ *(iv++) = md_buf[i];
+ niv--;
+ i++;
+ }
+ }
+
+ if ((nkey == 0) && (niv == 0))
+ break;
+ }
+
+ rv = cipher_info->key_bitlen / 8;
+err:
+ mbedtls_md_free(&ctx);
+ SecureZeroMemory(&(md_buf[0]), EVP_MAX_MD_SIZE);
+ return rv;
+#endif
+
+ return 0;
+}
#include <winpr/crypto.h>
#include <winpr/collections.h>
-#ifdef WITH_OPENSSL
-#include <openssl/evp.h>
-#include <openssl/aes.h>
-#endif
-
static wListDictionary* g_ProtectedMemoryBlocks = NULL;
BOOL CryptProtectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags)
if (!g_ProtectedMemoryBlocks)
{
g_ProtectedMemoryBlocks = ListDictionary_New(TRUE);
+
if (!g_ProtectedMemoryBlocks)
return FALSE;
}
winpr_RAND(pMemBlock->salt, 8);
winpr_RAND(randomKey, sizeof(randomKey));
-#ifdef WITH_OPENSSL
- EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), pMemBlock->salt,
- randomKey, sizeof(randomKey), 4, pMemBlock->key, pMemBlock->iv);
-#endif
+ winpr_openssl_BytesToKey(WINPR_CIPHER_AES_256_CBC, WINPR_MD_SHA1,
+ pMemBlock->salt, randomKey, sizeof(randomKey), 4, pMemBlock->key, pMemBlock->iv);
SecureZeroMemory(randomKey, sizeof(randomKey));
* HMAC
*/
-#if defined(WITH_OPENSSL)
+#ifdef WITH_OPENSSL
const EVP_MD* winpr_openssl_get_evp_md(int md)
{
const EVP_MD* evp = NULL;
return evp;
}
-#elif defined(WITH_MBEDTLS)
+#endif
+
+#ifdef WITH_MBEDTLS
mbedtls_md_type_t winpr_mbedtls_get_md_type(int md)
{
mbedtls_md_type_t type = MBEDTLS_MD_NONE;
return 0;
}
+/**
+ * Generic Digest API
+ */
+
+void winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, int md)
+{
+#if defined(WITH_OPENSSL)
+ const EVP_MD* evp = winpr_openssl_get_evp_md(md);
+ EVP_MD_CTX_init((EVP_MD_CTX*) ctx);
+ EVP_DigestInit_ex((EVP_MD_CTX*) ctx, evp, NULL);
+#elif defined(WITH_MBEDTLS)
+ const mbedtls_md_info_t* md_info;
+ mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md);
+ md_info = mbedtls_md_info_from_type(md_type);
+ mbedtls_md_init((mbedtls_md_context_t*) ctx);
+ mbedtls_md_setup((mbedtls_md_context_t*) ctx, md_info, 0);
+ mbedtls_md_starts((mbedtls_md_context_t*) ctx);
+#endif
+}
+
+void winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const BYTE* input, size_t ilen)
+{
+#if defined(WITH_OPENSSL)
+ EVP_DigestUpdate((EVP_MD_CTX*) ctx, input, ilen);
+#elif defined(WITH_MBEDTLS)
+ mbedtls_md_update((mbedtls_md_context_t*) ctx, input, ilen);
+#endif
+}
+
+void winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, BYTE* output)
+{
+#if defined(WITH_OPENSSL)
+ EVP_DigestFinal_ex((EVP_MD_CTX*) ctx, output, NULL);
+#elif defined(WITH_MBEDTLS)
+ mbedtls_md_finish((mbedtls_md_context_t*) ctx, output);
+ mbedtls_md_free((mbedtls_md_context_t*) ctx);
+#endif
+}
+
+void winpr_Digest(int md, const BYTE* input, size_t ilen, BYTE* output)
+{
+ WINPR_DIGEST_CTX ctx;
+ winpr_Digest_Init(&ctx, md);
+ winpr_Digest_Update(&ctx, input, ilen);
+ winpr_Digest_Final(&ctx, output);
+}
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()
+BOOL test_crypto_cipher_rc4()
{
size_t len;
BYTE* text;
text = (BYTE*) calloc(1, len);
if (!text)
- return -1;
+ return FALSE;
winpr_RC4_Init(&ctx, TEST_RC4_KEY, strlen((char*) TEST_RC4_KEY));
winpr_RC4_Update(&ctx, len, (BYTE*) TEST_RC4_PLAINTEXT, text);
free(actual);
free(expected);
- return -1;
+ return FALSE;
}
- return 0;
+ return TRUE;
+}
+
+static const BYTE* TEST_RAND_DATA = (BYTE*)
+ "\x1F\xC2\xEE\x4C\xA3\x66\x80\xA2\xCE\xFE\x56\xB4\x9E\x08\x30\x96"
+ "\x33\x6A\xA9\x6D\x36\xFD\x3C\xB7\x83\x04\x4E\x5E\xDC\x22\xCD\xF3"
+ "\x48\xDF\x3A\x2A\x61\xF1\xA8\xFA\x1F\xC6\xC7\x1B\x81\xB4\xE1\x0E"
+ "\xCB\xA2\xEF\xA1\x12\x4A\x83\xE5\x1D\x72\x1D\x2D\x26\xA8\x6B\xC0";
+
+static const BYTE* TEST_CIPHER_KEY = (BYTE*)
+ "\x9D\x7C\xC0\xA1\x94\x3B\x07\x67\x2F\xD3\x83\x10\x51\x83\x38\x0E"
+ "\x1C\x74\x8C\x4E\x15\x79\xD6\xFF\xE2\xF0\x37\x7F\x8C\xD7\xD2\x13";
+
+static const BYTE* TEST_CIPHER_IV = (BYTE*)
+ "\xFE\xE3\x9F\xF0\xD1\x5E\x37\x0C\xAB\xAB\x9B\x04\xF3\xDB\x99\x15";
+
+BOOL test_crypto_cipher_key()
+{
+ int status;
+ BYTE key[32];
+ BYTE iv[16];
+ BYTE salt[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };
+
+ ZeroMemory(key, sizeof(key));
+ ZeroMemory(iv, sizeof(iv));
+
+ status = winpr_openssl_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))
+ {
+ char* akstr;
+ char* ekstr;
+ char* aivstr;
+ char* eivstr;
+
+ akstr = winpr_BinToHexString(key, 32, 0);
+ ekstr = winpr_BinToHexString(TEST_CIPHER_KEY, 32, 0);
+
+ aivstr = winpr_BinToHexString(iv, 16, 0);
+ eivstr = winpr_BinToHexString(TEST_CIPHER_IV, 16, 0);
+
+ fprintf(stderr, "Unexpected EVP_BytesToKey Key: Actual: %s, Expected: %s\n", akstr, ekstr);
+ fprintf(stderr, "Unexpected EVP_BytesToKey IV : Actual: %s, Expected: %s\n", aivstr, eivstr);
+
+ free(akstr);
+ free(ekstr);
+ free(aivstr);
+ free(eivstr);
+ }
+
+ return TRUE;
}
int TestCryptoCipher(int argc, char* argv[])
if (!test_crypto_cipher_rc4())
return -1;
+ if (!test_crypto_cipher_key())
+ return -1;
+
return 0;
}