From 5023f55208e9940d983d98fb548a5f2e6553a072 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Fri, 6 Feb 2015 16:26:08 +1100 Subject: [PATCH] Add Windows CNG (BCrypt) support to HCrypto EVP API --- doc/copyright.texi | 2 +- lib/hcrypto/Makefile.am | 1 + lib/hcrypto/NTMakefile | 10 + lib/hcrypto/dllmain.c | 49 -- lib/hcrypto/evp-cc.c | 12 +- lib/hcrypto/evp-hcrypto.c | 4 +- lib/hcrypto/evp-w32.c | 147 ++++++ lib/hcrypto/evp-w32.h | 100 ++++ lib/hcrypto/evp-wincng.c | 710 +++++++++++++++++++++++++++++ lib/hcrypto/evp-wincng.h | 97 ++++ lib/hcrypto/evp.c | 22 +- lib/hcrypto/libhcrypto-exports.def | 21 + lib/hcrypto/md2.c | 9 +- lib/hcrypto/md2.h | 6 +- lib/hcrypto/md4.c | 9 +- lib/hcrypto/md4.h | 6 +- lib/hcrypto/md5.c | 9 +- lib/hcrypto/md5.h | 6 +- lib/hcrypto/sha.c | 9 +- lib/hcrypto/sha.h | 24 +- lib/hcrypto/sha256.c | 9 +- lib/hcrypto/sha512.c | 18 +- lib/hcrypto/test_bulk.c | 283 ++++++++++++ lib/hcrypto/test_cipher.c | 44 +- lib/hcrypto/version-script.map | 1 + lib/heimdal/NTMakefile | 5 + lib/krb5/dll.c | 15 + windows/NTMakefile.w32 | 2 + 28 files changed, 1517 insertions(+), 113 deletions(-) delete mode 100644 lib/hcrypto/dllmain.c create mode 100644 lib/hcrypto/evp-w32.c create mode 100644 lib/hcrypto/evp-w32.h create mode 100644 lib/hcrypto/evp-wincng.c create mode 100644 lib/hcrypto/evp-wincng.h create mode 100644 lib/hcrypto/test_bulk.c diff --git a/doc/copyright.texi b/doc/copyright.texi index 490abbcce..84baec52a 100644 --- a/doc/copyright.texi +++ b/doc/copyright.texi @@ -443,7 +443,7 @@ Windows support @verbatim -Copyright (c) 2009, Secure Endpoints Inc. +Copyright (c) 2009-2015, Secure Endpoints Inc. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/lib/hcrypto/Makefile.am b/lib/hcrypto/Makefile.am index d47cf92f8..510e5350e 100644 --- a/lib/hcrypto/Makefile.am +++ b/lib/hcrypto/Makefile.am @@ -60,6 +60,7 @@ PROGRAM_TESTS = \ rc2test \ rctest \ test_bn \ + test_bulk \ test_cipher \ test_engine_dso \ test_hmac \ diff --git a/lib/hcrypto/NTMakefile b/lib/hcrypto/NTMakefile index eced950c6..c46325f1b 100644 --- a/lib/hcrypto/NTMakefile +++ b/lib/hcrypto/NTMakefile @@ -62,6 +62,8 @@ INCFILES= \ $(HCRYPTOINCLUDEDIR)\evp.h \ $(HCRYPTOINCLUDEDIR)\evp-hcrypto.h \ $(HCRYPTOINCLUDEDIR)\evp-cc.h \ + $(HCRYPTOINCLUDEDIR)\evp-wincng.h \ + $(HCRYPTOINCLUDEDIR)\evp-w32.h \ $(HCRYPTOINCLUDEDIR)\hmac.h \ $(HCRYPTOINCLUDEDIR)\md2.h \ $(HCRYPTOINCLUDEDIR)\md4.h \ @@ -103,6 +105,8 @@ libhcrypto_OBJs = \ $(OBJ)\evp.obj \ $(OBJ)\evp-hcrypto.obj \ $(OBJ)\evp-cc.obj \ + $(OBJ)\evp-wincng.obj \ + $(OBJ)\evp-w32.obj \ $(OBJ)\engine.obj \ $(OBJ)\hmac.obj \ $(OBJ)\md2.obj \ @@ -150,6 +154,7 @@ test-binaries: \ $(OBJ)\rc2test.exe \ $(OBJ)\rctest.exe \ $(OBJ)\test_bn.exe \ + $(OBJ)\test_bulk.exe \ $(OBJ)\test_cipher.exe \ $(OBJ)\test_engine_dso.exe \ $(OBJ)\test_hmac.exe \ @@ -184,6 +189,10 @@ $(OBJ)\test_bn.exe: $(OBJ)\test_bn.obj $(LIBHEIMDAL) $(LIBROKEN) $(EXECONLINK) $(EXEPREP_NODIST) +$(OBJ)\test_bulk.exe: $(OBJ)\test_bulk.obj $(TESTLIB) $(LIBHEIMDAL) $(LIBROKEN) $(LIBVERS) + $(EXECONLINK) + $(EXEPREP_NODIST) + $(OBJ)\test_cipher.exe: $(OBJ)\test_cipher.obj $(TESTLIB) $(LIBHEIMDAL) $(LIBROKEN) $(LIBVERS) $(EXECONLINK) $(EXEPREP_NODIST) @@ -231,6 +240,7 @@ test-run: rc2test.exe rctest.exe test_bn.exe + test_bulk.exe test_cipher.exe test_engine_dso.exe test_hmac.exe diff --git a/lib/hcrypto/dllmain.c b/lib/hcrypto/dllmain.c deleted file mode 100644 index b241c7380..000000000 --- a/lib/hcrypto/dllmain.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include - -#include - -BOOL WINAPI -DllMain (HANDLE hInst, - ULONG reason, - LPVOID lpReserved) -{ - switch(reason) { - case DLL_PROCESS_ATTACH: - case DLL_PROCESS_DETACH: - default: - return TRUE; - } -} diff --git a/lib/hcrypto/evp-cc.c b/lib/hcrypto/evp-cc.c index bd084a25e..8ba1ba7f5 100644 --- a/lib/hcrypto/evp-cc.c +++ b/lib/hcrypto/evp-cc.c @@ -148,9 +148,12 @@ init_cc_key(int encp, CCAlgorithm alg, CCOptions opts, const void *key, CCCryptorRelease(*ref); } - ret = CCCryptorCreate(op, alg, opts, key, keylen, iv, ref); - if (ret) - return 0; + if (key) { + ret = CCCryptorCreate(op, alg, opts, key, keylen, iv, ref); + if (ret) + return 0; + } + return 1; } @@ -375,7 +378,8 @@ cc_aes_cfb8_init(EVP_CIPHER_CTX *ctx, int encp) { struct cc_key *cc = ctx->cipher_data; - memcpy(ctx->iv, iv, ctx->cipher->iv_len); + if (iv) + memcpy(ctx->iv, iv, ctx->cipher->iv_len); return init_cc_key(1, kCCAlgorithmAES128, kCCOptionECBMode, key, ctx->cipher->key_len, NULL, &cc->href); } diff --git a/lib/hcrypto/evp-hcrypto.c b/lib/hcrypto/evp-hcrypto.c index bf37b42ed..387fe8d19 100644 --- a/lib/hcrypto/evp-hcrypto.c +++ b/lib/hcrypto/evp-hcrypto.c @@ -69,7 +69,7 @@ aes_init(EVP_CIPHER_CTX *ctx, int encp) { AES_KEY *k = ctx->cipher_data; - if (ctx->encrypt) + if (ctx->encrypt || EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB8_MODE) AES_set_encrypt_key(key, ctx->cipher->key_len * 8, k); else AES_set_decrypt_key(key, ctx->cipher->key_len * 8, k); @@ -83,7 +83,7 @@ aes_do_cipher(EVP_CIPHER_CTX *ctx, unsigned int size) { AES_KEY *k = ctx->cipher_data; - if (ctx->flags & EVP_CIPH_CFB8_MODE) + if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB8_MODE) AES_cfb8_encrypt(in, out, size, k, ctx->iv, ctx->encrypt); else AES_cbc_encrypt(in, out, size, k, ctx->iv, ctx->encrypt); diff --git a/lib/hcrypto/evp-w32.c b/lib/hcrypto/evp-w32.c new file mode 100644 index 000000000..a72af16a5 --- /dev/null +++ b/lib/hcrypto/evp-w32.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2015, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Windows fallback provider: decides whether to use hcrypto or + * wincng depending on whether bcrypt.dll is available (i.e. it + * is runtime compatible back to XP, but will use the native + * crypto APIs from Vista onwards). + */ + +#include "config.h" + +#include +#include + +#include +#include +#include + +#if NTDDI_VERSION >= NTDDI_VISTA + +#include + +static LONG wincng_available = -1; + +static __inline int +wincng_check_availability(void) +{ + if (wincng_available == -1) { + char szBCryptDllPath[MAX_PATH]; + UINT cbBCryptDllPath; + + cbBCryptDllPath = GetSystemDirectory(szBCryptDllPath, + sizeof(szBCryptDllPath)); + if (cbBCryptDllPath > 0 && + cbBCryptDllPath < sizeof(szBCryptDllPath) && + strncat_s(szBCryptDllPath, + sizeof(szBCryptDllPath), "\\bcrypt.dll", 11) == 0) { + HANDLE hBCryptDll = LoadLibrary(szBCryptDllPath); + + InterlockedCompareExchangeRelease(&wincng_available, + !!hBCryptDll, -1); + if (hBCryptDll) + FreeLibrary(hBCryptDll); + } + } + + return wincng_available == 1; +} + +BOOL WINAPI +_hc_w32crypto_DllMain(HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved) +{ + if (fdwReason == DLL_PROCESS_DETACH) { + /* + * Don't bother cleaning up on process exit, only on + * FreeLibrary() (in which case lpvReserved will be NULL). + */ + if (lpvReserved == NULL) + _hc_wincng_cleanup(); + } + + return TRUE; +} + +#define EVP_W32CRYPTO_PROVIDER(type, name) \ + \ + const type *hc_EVP_w32crypto_ ##name (void) \ + { \ + if (wincng_check_availability()) \ + return hc_EVP_wincng_ ##name (); \ + else \ + return hc_EVP_hcrypto_ ##name (); \ + } + +#else + +#define EVP_W32CRYPTO_PROVIDER(type, name) \ + EVP_W32CRYPTO_PROVIDER_CNG_UNAVAILABLE(type, name) + +#endif /* NTDDI_VERSION >= NTDDI_VISTA */ + +#define EVP_W32CRYPTO_PROVIDER_CNG_UNAVAILABLE(type, name) \ + \ + const type *hc_EVP_w32crypto_ ##name (void) \ + { \ + return hc_EVP_hcrypto_ ##name (); \ + } + +EVP_W32CRYPTO_PROVIDER(EVP_MD, md2) +EVP_W32CRYPTO_PROVIDER(EVP_MD, md4) +EVP_W32CRYPTO_PROVIDER(EVP_MD, md5) +EVP_W32CRYPTO_PROVIDER(EVP_MD, sha1) +EVP_W32CRYPTO_PROVIDER(EVP_MD, sha256) +EVP_W32CRYPTO_PROVIDER(EVP_MD, sha384) +EVP_W32CRYPTO_PROVIDER(EVP_MD, sha512) + +EVP_W32CRYPTO_PROVIDER(EVP_CIPHER, rc2_cbc) +EVP_W32CRYPTO_PROVIDER(EVP_CIPHER, rc2_40_cbc) +EVP_W32CRYPTO_PROVIDER(EVP_CIPHER, rc2_64_cbc) + +EVP_W32CRYPTO_PROVIDER(EVP_CIPHER, rc4) +EVP_W32CRYPTO_PROVIDER(EVP_CIPHER, rc4_40) + +EVP_W32CRYPTO_PROVIDER(EVP_CIPHER, des_cbc) +EVP_W32CRYPTO_PROVIDER(EVP_CIPHER, des_ede3_cbc) + +EVP_W32CRYPTO_PROVIDER(EVP_CIPHER, aes_128_cbc) +EVP_W32CRYPTO_PROVIDER(EVP_CIPHER, aes_192_cbc) +EVP_W32CRYPTO_PROVIDER(EVP_CIPHER, aes_256_cbc) + +EVP_W32CRYPTO_PROVIDER(EVP_CIPHER, aes_128_cfb8) +EVP_W32CRYPTO_PROVIDER(EVP_CIPHER, aes_192_cfb8) +EVP_W32CRYPTO_PROVIDER(EVP_CIPHER, aes_256_cfb8) + +EVP_W32CRYPTO_PROVIDER_CNG_UNAVAILABLE(EVP_CIPHER, camellia_128_cbc) +EVP_W32CRYPTO_PROVIDER_CNG_UNAVAILABLE(EVP_CIPHER, camellia_192_cbc) +EVP_W32CRYPTO_PROVIDER_CNG_UNAVAILABLE(EVP_CIPHER, camellia_256_cbc) diff --git a/lib/hcrypto/evp-w32.h b/lib/hcrypto/evp-w32.h new file mode 100644 index 000000000..89bfa4d0a --- /dev/null +++ b/lib/hcrypto/evp-w32.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2015, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef HEIM_EVP_W32_H +#define HEIM_EVP_W32_H 1 + +/* symbol renaming */ +#define EVP_w32crypto_md2() hc_EVP_w32crypto_md2() +#define EVP_w32crypto_md4() hc_EVP_w32crypto_md4() +#define EVP_w32crypto_md5() hc_EVP_w32crypto_md5() +#define EVP_w32crypto_sha1() hc_EVP_w32crypto_sha1() +#define EVP_w32crypto_sha256() hc_EVP_w32crypto_sha256() +#define EVP_w32crypto_sha384() hc_EVP_w32crypto_sha384() +#define EVP_w32crypto_sha512() hc_EVP_w32crypto_sha512() +#define EVP_w32crypto_des_cbc() hc_EVP_w32crypto_des_cbc() +#define EVP_w32crypto_des_ede3_cbc() hc_EVP_w32crypto_des_ede3_cbc() +#define EVP_w32crypto_aes_128_cbc() hc_EVP_w32crypto_aes_128_cbc() +#define EVP_w32crypto_aes_192_cbc() hc_EVP_w32crypto_aes_192_cbc() +#define EVP_w32crypto_aes_256_cbc() hc_EVP_w32crypto_aes_256_cbc() +#define EVP_w32crypto_aes_128_cfb8() hc_EVP_w32crypto_aes_128_cfb8() +#define EVP_w32crypto_aes_192_cfb8() hc_EVP_w32crypto_aes_192_cfb8() +#define EVP_w32crypto_aes_256_cfb8() hc_EVP_w32crypto_aes_256_cfb8() +#define EVP_w32crypto_rc4() hc_EVP_w32crypto_rc4() +#define EVP_w32crypto_rc4_40() hc_EVP_w32crypto_rc4_40() +#define EVP_w32crypto_rc2_40_cbc() hc_EVP_w32crypto_rc2_40_cbc() +#define EVP_w32crypto_rc2_64_cbc() hc_EVP_w32crypto_rc2_64_cbc() +#define EVP_w32crypto_rc2_cbc() hc_EVP_w32crypto_rc2_cbc() +#define EVP_w32crypto_camellia_128_cbc() hc_EVP_w32crypto_camellia_128_cbc() +#define EVP_w32crypto_camellia_192_cbc() hc_EVP_w32crypto_camellia_192_cbc() +#define EVP_w32crypto_camellia_256_cbc() hc_EVP_w32crypto_camellia_256_cbc() + +/* + * This provider dynamically selects between Windows CNG (if running + * on Vista or above) or the inbuilt provider (if running on XP). + */ + +HC_CPP_BEGIN + +const EVP_MD * hc_EVP_w32crypto_md2(void); +const EVP_MD * hc_EVP_w32crypto_md4(void); +const EVP_MD * hc_EVP_w32crypto_md5(void); +const EVP_MD * hc_EVP_w32crypto_sha1(void); +const EVP_MD * hc_EVP_w32crypto_sha256(void); +const EVP_MD * hc_EVP_w32crypto_sha384(void); +const EVP_MD * hc_EVP_w32crypto_sha512(void); + +const EVP_CIPHER * hc_EVP_w32crypto_des_cbc(void); +const EVP_CIPHER * hc_EVP_w32crypto_des_ede3_cbc(void); + +const EVP_CIPHER * hc_EVP_w32crypto_aes_128_cbc(void); +const EVP_CIPHER * hc_EVP_w32crypto_aes_192_cbc(void); +const EVP_CIPHER * hc_EVP_w32crypto_aes_256_cbc(void); + +const EVP_CIPHER * hc_EVP_w32crypto_aes_128_cfb8(void); +const EVP_CIPHER * hc_EVP_w32crypto_aes_192_cfb8(void); +const EVP_CIPHER * hc_EVP_w32crypto_aes_256_cfb8(void); + +const EVP_CIPHER * hc_EVP_w32crypto_rc4(void); +const EVP_CIPHER * hc_EVP_w32crypto_rc4_40(void); + +const EVP_CIPHER * hc_EVP_w32crypto_rc2_cbc(void); +const EVP_CIPHER * hc_EVP_w32crypto_rc2_40_cbc(void); +const EVP_CIPHER * hc_EVP_w32crypto_rc2_64_cbc(void); + +const EVP_CIPHER * hc_EVP_w32crypto_camellia_128_cbc(void); +const EVP_CIPHER * hc_EVP_w32crypto_camellia_192_cbc(void); +const EVP_CIPHER * hc_EVP_w32crypto_camellia_256_cbc(void); + +HC_CPP_END + +#endif /* HEIM_EVP_W32_H */ diff --git a/lib/hcrypto/evp-wincng.c b/lib/hcrypto/evp-wincng.c new file mode 100644 index 000000000..c5d444c3e --- /dev/null +++ b/lib/hcrypto/evp-wincng.c @@ -0,0 +1,710 @@ +/* + * Copyright (c) 2015, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Windows CNG provider */ + +#include "config.h" + +#include +#include + +#if NTDDI_VERSION >= NTDDI_VISTA + +#include +#include + +#include + +/* + * CNG cipher provider + */ + +struct wincng_key { + BCRYPT_KEY_HANDLE hKey; + UCHAR rgbKeyObject[1]; +}; + +#define WINCNG_KEY_OBJECT_SIZE(ctx) \ + ((ctx)->cipher->ctx_size - sizeof(struct wincng_key) + 1) + +static int +wincng_do_cipher(EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, + unsigned int size) +{ + struct wincng_key *cng = ctx->cipher_data; + NTSTATUS status; + ULONG cbResult; + + assert(EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_STREAM_CIPHER || + (size % ctx->cipher->block_size) == 0); + + if (ctx->encrypt) { + status = BCryptEncrypt(cng->hKey, + (PUCHAR)in, + size, + NULL, /* pPaddingInfo */ + ctx->cipher->iv_len ? ctx->iv : NULL, + ctx->cipher->iv_len, + out, + size, + &cbResult, + 0); + } else { + status = BCryptDecrypt(cng->hKey, + (PUCHAR)in, + size, + NULL, /* pPaddingInfo */ + ctx->cipher->iv_len ? ctx->iv : NULL, + ctx->cipher->iv_len, + out, + size, + &cbResult, + 0); + } + + return BCRYPT_SUCCESS(status) && cbResult == size; +} + +static int +wincng_cleanup(EVP_CIPHER_CTX *ctx) +{ + struct wincng_key *cng = ctx->cipher_data; + + if (cng->hKey) + BCryptDestroyKey(cng->hKey); + SecureZeroMemory(cng->rgbKeyObject, WINCNG_KEY_OBJECT_SIZE(ctx)); + + return 1; +} + +static int +wincng_cipher_algorithm_init(EVP_CIPHER *cipher, + LPWSTR pszAlgId) +{ + BCRYPT_ALG_HANDLE hAlgorithm = NULL; + NTSTATUS status; + LPCWSTR pszChainingMode; + ULONG cbKeyObject, cbChainingMode, cbData; + + if (cipher->app_data) + return 1; + + status = BCryptOpenAlgorithmProvider(&hAlgorithm, + pszAlgId, + NULL, + 0); + if (!BCRYPT_SUCCESS(status)) + return 0; + + status = BCryptGetProperty(hAlgorithm, + BCRYPT_OBJECT_LENGTH, + (PUCHAR)&cbKeyObject, + sizeof(ULONG), + &cbData, + 0); + if (!BCRYPT_SUCCESS(status)) { + BCryptCloseAlgorithmProvider(hAlgorithm, 0); + return 0; + } + + cipher->ctx_size = sizeof(struct wincng_key) + cbKeyObject - 1; + + switch (cipher->flags & EVP_CIPH_MODE) { + case EVP_CIPH_CBC_MODE: + pszChainingMode = BCRYPT_CHAIN_MODE_CBC; + cbChainingMode = sizeof(BCRYPT_CHAIN_MODE_CBC); + break; + case EVP_CIPH_CFB8_MODE: + pszChainingMode = BCRYPT_CHAIN_MODE_CFB; + cbChainingMode = sizeof(BCRYPT_CHAIN_MODE_CFB); + break; + default: + pszChainingMode = NULL; + cbChainingMode = 0; + break; + } + + if (cbChainingMode) { + status = BCryptSetProperty(hAlgorithm, + BCRYPT_CHAINING_MODE, + (PUCHAR)pszChainingMode, + cbChainingMode, + 0); + if (!BCRYPT_SUCCESS(status)) { + BCryptCloseAlgorithmProvider(hAlgorithm, 0); + return 0; + } + } + + if (wcscmp(pszAlgId, BCRYPT_RC2_ALGORITHM) == 0) { + ULONG cbEffectiveKeyLength = EVP_CIPHER_key_length(cipher) * 8; + + status = BCryptSetProperty(hAlgorithm, + BCRYPT_EFFECTIVE_KEY_LENGTH, + (PUCHAR)&cbEffectiveKeyLength, + sizeof(cbEffectiveKeyLength), + 0); + if (!BCRYPT_SUCCESS(status)) { + BCryptCloseAlgorithmProvider(hAlgorithm, 0); + return 0; + } + } + + InterlockedCompareExchangePointerRelease(&cipher->app_data, + hAlgorithm, NULL); + return 1; +} + +static int +wincng_key_init(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, + int encp) +{ + struct wincng_key *cng = ctx->cipher_data; + NTSTATUS status; + + assert(cng != NULL); + assert(ctx->cipher != NULL); + + if (ctx->cipher->app_data == NULL) + return 0; + + /* + * Note: ctx->key_len not EVP_CIPHER_CTX_key_length() for + * variable length key support. + */ + status = BCryptGenerateSymmetricKey(ctx->cipher->app_data, + &cng->hKey, + cng->rgbKeyObject, + WINCNG_KEY_OBJECT_SIZE(ctx), + (PUCHAR)key, + ctx->key_len, + 0); + + return BCRYPT_SUCCESS(status); +} + +#define WINCNG_CIPHER_ALGORITHM(name, alg_id, block_size, key_len, \ + iv_len, flags) \ + \ + static EVP_CIPHER \ + wincng_##name = { \ + 0, \ + block_size, \ + key_len, \ + iv_len, \ + flags, \ + wincng_key_init, \ + wincng_do_cipher, \ + wincng_cleanup, \ + 0, \ + NULL, \ + NULL, \ + NULL, \ + NULL \ + }; \ + \ + const EVP_CIPHER * \ + hc_EVP_wincng_##name(void) \ + { \ + wincng_cipher_algorithm_init(&wincng_##name, alg_id); \ + return wincng_##name.app_data ? &wincng_##name : NULL; \ + } + +#define WINCNG_CIPHER_ALGORITHM_CLEANUP(name) do { \ + if (wincng_##name.app_data) { \ + BCryptCloseAlgorithmProvider(wincng_##name.app_data, 0); \ + wincng_##name.app_data = NULL; \ + } \ + } while (0) + +#define WINCNG_CIPHER_ALGORITHM_UNAVAILABLE(name) \ + \ + const EVP_CIPHER * \ + hc_EVP_wincng_##name(void) \ + { \ + return NULL; \ + } + +/** + * The tripple DES cipher type (Windows CNG provider) + * + * @return the DES-EDE3-CBC EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +WINCNG_CIPHER_ALGORITHM(des_ede3_cbc, + BCRYPT_3DES_ALGORITHM, + 8, + 24, + 8, + EVP_CIPH_CBC_MODE); + +/** + * The DES cipher type (Windows CNG provider) + * + * @return the DES-CBC EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +WINCNG_CIPHER_ALGORITHM(des_cbc, + BCRYPT_DES_ALGORITHM, + 8, + 8, + 8, + EVP_CIPH_CBC_MODE); + +/** + * The AES-128 cipher type (Windows CNG provider) + * + * @return the AES-128-CBC EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +WINCNG_CIPHER_ALGORITHM(aes_128_cbc, + BCRYPT_AES_ALGORITHM, + 16, + 16, + 16, + EVP_CIPH_CBC_MODE); + +/** + * The AES-192 cipher type (Windows CNG provider) + * + * @return the AES-192-CBC EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +WINCNG_CIPHER_ALGORITHM(aes_192_cbc, + BCRYPT_AES_ALGORITHM, + 16, + 24, + 16, + EVP_CIPH_CBC_MODE); + +/** + * The AES-256 cipher type (Windows CNG provider) + * + * @return the AES-256-CBC EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +WINCNG_CIPHER_ALGORITHM(aes_256_cbc, + BCRYPT_AES_ALGORITHM, + 16, + 32, + 16, + EVP_CIPH_CBC_MODE); + +/** + * The AES-128 CFB8 cipher type (Windows CNG provider) + * + * @return the AES-128-CFB8 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +WINCNG_CIPHER_ALGORITHM(aes_128_cfb8, + BCRYPT_AES_ALGORITHM, + 16, + 16, + 16, + EVP_CIPH_CFB8_MODE); + +/** + * The AES-192 CFB8 cipher type (Windows CNG provider) + * + * @return the AES-192-CFB8 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +WINCNG_CIPHER_ALGORITHM(aes_192_cfb8, + BCRYPT_AES_ALGORITHM, + 16, + 24, + 16, + EVP_CIPH_CFB8_MODE); + +/** + * The AES-256 CFB8 cipher type (Windows CNG provider) + * + * @return the AES-256-CFB8 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +WINCNG_CIPHER_ALGORITHM(aes_256_cfb8, + BCRYPT_AES_ALGORITHM, + 16, + 32, + 16, + EVP_CIPH_CFB8_MODE); + +/** + * The RC2 cipher type - Windows CNG + * + * @return the RC2 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +WINCNG_CIPHER_ALGORITHM(rc2_cbc, + BCRYPT_RC2_ALGORITHM, + 8, + 16, + 8, + EVP_CIPH_CBC_MODE); + +/** + * The RC2-40 cipher type - Windows CNG + * + * @return the RC2-40 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +WINCNG_CIPHER_ALGORITHM(rc2_40_cbc, + BCRYPT_RC2_ALGORITHM, + 8, + 5, + 8, + EVP_CIPH_CBC_MODE); + +/** + * The RC2-64 cipher type - Windows CNG + * + * @return the RC2-64 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +WINCNG_CIPHER_ALGORITHM(rc2_64_cbc, + BCRYPT_RC2_ALGORITHM, + 8, + 8, + 8, + EVP_CIPH_CBC_MODE); + +/** + * The Camellia-128 cipher type - CommonCrypto + * + * @return the Camellia-128 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +WINCNG_CIPHER_ALGORITHM_UNAVAILABLE(camellia_128_cbc); + +/** + * The Camellia-198 cipher type - CommonCrypto + * + * @return the Camellia-198 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +WINCNG_CIPHER_ALGORITHM_UNAVAILABLE(camellia_192_cbc); + +/** + * The Camellia-256 cipher type - CommonCrypto + * + * @return the Camellia-256 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +WINCNG_CIPHER_ALGORITHM_UNAVAILABLE(camellia_256_cbc); + +/** + * The RC4 cipher type (Windows CNG provider) + * + * @return the RC4 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +WINCNG_CIPHER_ALGORITHM(rc4, + BCRYPT_RC4_ALGORITHM, + 1, + 16, + 0, + EVP_CIPH_STREAM_CIPHER | EVP_CIPH_VARIABLE_LENGTH); + +/** + * The RC4-40 cipher type (Windows CNG provider) + * + * @return the RC4 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +WINCNG_CIPHER_ALGORITHM(rc4_40, + BCRYPT_RC4_ALGORITHM, + 1, + 5, + 0, + EVP_CIPH_STREAM_CIPHER | EVP_CIPH_VARIABLE_LENGTH); + +static void +wincng_cipher_algorithm_cleanup(void) +{ + WINCNG_CIPHER_ALGORITHM_CLEANUP(des_ede3_cbc); + WINCNG_CIPHER_ALGORITHM_CLEANUP(des_cbc); + WINCNG_CIPHER_ALGORITHM_CLEANUP(aes_128_cbc); + WINCNG_CIPHER_ALGORITHM_CLEANUP(aes_192_cbc); + WINCNG_CIPHER_ALGORITHM_CLEANUP(aes_256_cbc); + WINCNG_CIPHER_ALGORITHM_CLEANUP(aes_128_cfb8); + WINCNG_CIPHER_ALGORITHM_CLEANUP(aes_192_cfb8); + WINCNG_CIPHER_ALGORITHM_CLEANUP(aes_256_cfb8); + WINCNG_CIPHER_ALGORITHM_CLEANUP(rc2_cbc); + WINCNG_CIPHER_ALGORITHM_CLEANUP(rc2_40_cbc); + WINCNG_CIPHER_ALGORITHM_CLEANUP(rc2_64_cbc); + WINCNG_CIPHER_ALGORITHM_CLEANUP(rc4); + WINCNG_CIPHER_ALGORITHM_CLEANUP(rc4_40); +} + +/* + * CNG digest provider + */ + +struct wincng_md_ctx { + BCRYPT_HASH_HANDLE hHash; + ULONG cbHashObject; + UCHAR rgbHashObject[1]; +}; + +static BCRYPT_ALG_HANDLE +wincng_md_algorithm_init(EVP_MD *md, + LPCWSTR pszAlgId) +{ + BCRYPT_ALG_HANDLE hAlgorithm; + NTSTATUS status; + ULONG cbHashObject, cbData; + ULONG cbHash = 0, cbBlock = 0; + + status = BCryptOpenAlgorithmProvider(&hAlgorithm, + pszAlgId, + NULL, + 0); + if (!BCRYPT_SUCCESS(status)) + return NULL; + + status = BCryptGetProperty(hAlgorithm, + BCRYPT_HASH_LENGTH, + (PUCHAR)&cbHash, + sizeof(ULONG), + &cbData, + 0); + if (!BCRYPT_SUCCESS(status)) { + BCryptCloseAlgorithmProvider(hAlgorithm, 0); + return NULL; + } + + status = BCryptGetProperty(hAlgorithm, + BCRYPT_HASH_BLOCK_LENGTH, + (PUCHAR)&cbBlock, + sizeof(ULONG), + &cbData, + 0); + if (!BCRYPT_SUCCESS(status)) { + BCryptCloseAlgorithmProvider(hAlgorithm, 0); + return NULL; + } + + status = BCryptGetProperty(hAlgorithm, + BCRYPT_OBJECT_LENGTH, + (PUCHAR)&cbHashObject, + sizeof(ULONG), + &cbData, + 0); + if (!BCRYPT_SUCCESS(status)) { + BCryptCloseAlgorithmProvider(hAlgorithm, 0); + return NULL; + } + + md->hash_size = cbHash; + md->block_size = cbBlock; + md->ctx_size = sizeof(struct wincng_md_ctx) + cbHashObject - 1; + + return hAlgorithm; +} + +static int +wincng_md_hash_init(BCRYPT_ALG_HANDLE hAlgorithm, + EVP_MD_CTX *ctx) +{ + struct wincng_md_ctx *cng = (struct wincng_md_ctx *)ctx; + NTSTATUS status; + ULONG cbData; + + status = BCryptGetProperty(hAlgorithm, + BCRYPT_OBJECT_LENGTH, + (PUCHAR)&cng->cbHashObject, + sizeof(ULONG), + &cbData, + 0); + if (!BCRYPT_SUCCESS(status)) + return 0; + + status = BCryptCreateHash(hAlgorithm, + &cng->hHash, + cng->rgbHashObject, + cng->cbHashObject, + NULL, + 0, + 0); + + return BCRYPT_SUCCESS(status); +} + +static int +wincng_md_update(EVP_MD_CTX *ctx, + const void *data, + size_t length) +{ + struct wincng_md_ctx *cng = (struct wincng_md_ctx *)ctx; + NTSTATUS status; + + status = BCryptHashData(cng->hHash, (PUCHAR)data, length, 0); + + return BCRYPT_SUCCESS(status); +} + +static int +wincng_md_final(void *digest, + EVP_MD_CTX *ctx) +{ + struct wincng_md_ctx *cng = (struct wincng_md_ctx *)ctx; + NTSTATUS status; + ULONG cbHash, cbData; + + status = BCryptGetProperty(cng->hHash, + BCRYPT_HASH_LENGTH, + (PUCHAR)&cbHash, + sizeof(DWORD), + &cbData, + 0); + if (!BCRYPT_SUCCESS(status)) + return 0; + + status = BCryptFinishHash(cng->hHash, + digest, + cbHash, + 0); + + return BCRYPT_SUCCESS(status); +} + +static int +wincng_md_cleanup(EVP_MD_CTX *ctx) +{ + struct wincng_md_ctx *cng = (struct wincng_md_ctx *)ctx; + + if (cng->hHash) + BCryptDestroyHash(cng->hHash); + SecureZeroMemory(cng->rgbHashObject, cng->cbHashObject); + + return 1; +} + +#define WINCNG_MD_ALGORITHM(name, alg_id) \ + \ + static BCRYPT_ALG_HANDLE wincng_hAlgorithm_##name; \ + \ + static int wincng_##name##_init(EVP_MD_CTX *ctx) \ + { \ + return wincng_md_hash_init(wincng_hAlgorithm_##name, ctx); \ + } \ + \ + const EVP_MD * \ + hc_EVP_wincng_##name(void) \ + { \ + static struct hc_evp_md name = { \ + 0, \ + 0, \ + 0, \ + wincng_##name##_init, \ + wincng_md_update, \ + wincng_md_final, \ + wincng_md_cleanup \ + }; \ + \ + if (wincng_hAlgorithm_##name == NULL) { \ + BCRYPT_ALG_HANDLE hAlgorithm = \ + wincng_md_algorithm_init(&name, alg_id); \ + InterlockedCompareExchangePointerRelease( \ + &wincng_hAlgorithm_##name, hAlgorithm, NULL); \ + } \ + return wincng_hAlgorithm_##name ? &name : NULL; \ + } + +#define WINCNG_MD_ALGORITHM_CLEANUP(name) do { \ + if (wincng_hAlgorithm_##name) { \ + BCryptCloseAlgorithmProvider(wincng_hAlgorithm_##name, 0); \ + wincng_hAlgorithm_##name = NULL; \ + } \ + } while (0) + +WINCNG_MD_ALGORITHM(md2, BCRYPT_MD2_ALGORITHM); +WINCNG_MD_ALGORITHM(md4, BCRYPT_MD4_ALGORITHM); +WINCNG_MD_ALGORITHM(md5, BCRYPT_MD5_ALGORITHM); +WINCNG_MD_ALGORITHM(sha1, BCRYPT_SHA1_ALGORITHM); +WINCNG_MD_ALGORITHM(sha256, BCRYPT_SHA256_ALGORITHM); +WINCNG_MD_ALGORITHM(sha384, BCRYPT_SHA384_ALGORITHM); +WINCNG_MD_ALGORITHM(sha512, BCRYPT_SHA512_ALGORITHM); + +static void +wincng_md_algorithm_cleanup(void) +{ + WINCNG_MD_ALGORITHM_CLEANUP(md2); + WINCNG_MD_ALGORITHM_CLEANUP(md4); + WINCNG_MD_ALGORITHM_CLEANUP(md5); + WINCNG_MD_ALGORITHM_CLEANUP(sha1); + WINCNG_MD_ALGORITHM_CLEANUP(sha256); + WINCNG_MD_ALGORITHM_CLEANUP(sha384); + WINCNG_MD_ALGORITHM_CLEANUP(sha512); +} + +void _hc_wincng_cleanup(void) +{ + wincng_md_algorithm_cleanup(); + wincng_cipher_algorithm_cleanup(); +} + +#endif /* NTDDI_VERSION >= NTDDI_VISTA */ diff --git a/lib/hcrypto/evp-wincng.h b/lib/hcrypto/evp-wincng.h new file mode 100644 index 000000000..ed7037a11 --- /dev/null +++ b/lib/hcrypto/evp-wincng.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2015, Secure Endpoints Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* $Id$ */ + +#ifndef HEIM_EVP_WINCNG_H +#define HEIM_EVP_WINCNG_H 1 + +/* symbol renaming */ +#define EVP_wincng_md2() EVP_wincng_md2() +#define EVP_wincng_md4() EVP_wincng_md4() +#define EVP_wincng_md5() EVP_wincng_md5() +#define EVP_wincng_sha1() EVP_wincng_sha1() +#define EVP_wincng_sha256() EVP_wincng_sha256() +#define EVP_wincng_sha384() EVP_wincng_sha384() +#define EVP_wincng_sha512() EVP_wincng_sha512() +#define EVP_wincng_des_cbc() EVP_wincng_des_cbc() +#define EVP_wincng_des_ede3_cbc() EVP_wincng_des_ede3_cbc() +#define EVP_wincng_aes_128_cbc() EVP_wincng_aes_128_cbc() +#define EVP_wincng_aes_192_cbc() EVP_wincng_aes_192_cbc() +#define EVP_wincng_aes_256_cbc() EVP_wincng_aes_256_cbc() +#define EVP_wincng_aes_128_cfb8() EVP_wincng_aes_128_cfb8() +#define EVP_wincng_aes_192_cfb8() EVP_wincng_aes_192_cfb8() +#define EVP_wincng_aes_256_cfb8() EVP_wincng_aes_256_cfb8() +#define EVP_wincng_rc4() EVP_wincng_rc4() +#define EVP_wincng_rc4_40() EVP_wincng_rc4_40() +#define EVP_wincng_rc2_40_cbc() EVP_wincng_rc2_40_cbc() +#define EVP_wincng_rc2_64_cbc() EVP_wincng_rc2_64_cbc() +#define EVP_wincng_rc2_cbc() EVP_wincng_rc2_cbc() +#define EVP_wincng_camellia_128_cbc() EVP_wincng_camellia_128_cbc() +#define EVP_wincng_camellia_192_cbc() EVP_wincng_camellia_192_cbc() +#define EVP_wincng_camellia_256_cbc() EVP_wincng_camellia_256_cbc() + +/* + * + */ + +HC_CPP_BEGIN + +const EVP_MD * hc_EVP_wincng_md2(void); +const EVP_MD * hc_EVP_wincng_md4(void); +const EVP_MD * hc_EVP_wincng_md5(void); +const EVP_MD * hc_EVP_wincng_sha1(void); +const EVP_MD * hc_EVP_wincng_sha256(void); +const EVP_MD * hc_EVP_wincng_sha384(void); +const EVP_MD * hc_EVP_wincng_sha512(void); + +const EVP_CIPHER * hc_EVP_wincng_rc2_cbc(void); +const EVP_CIPHER * hc_EVP_wincng_rc2_40_cbc(void); +const EVP_CIPHER * hc_EVP_wincng_rc2_64_cbc(void); + +const EVP_CIPHER * hc_EVP_wincng_rc4(void); +const EVP_CIPHER * hc_EVP_wincng_rc4_40(void); + +const EVP_CIPHER * hc_EVP_wincng_des_cbc(void); +const EVP_CIPHER * hc_EVP_wincng_des_ede3_cbc(void); + +const EVP_CIPHER * hc_EVP_wincng_aes_128_cbc(void); +const EVP_CIPHER * hc_EVP_wincng_aes_192_cbc(void); +const EVP_CIPHER * hc_EVP_wincng_aes_256_cbc(void); + +const EVP_CIPHER * hc_EVP_wincng_aes_128_cfb8(void); +const EVP_CIPHER * hc_EVP_wincng_aes_192_cfb8(void); +const EVP_CIPHER * hc_EVP_wincng_aes_256_cfb8(void); + +void _hc_wincng_cleanup(void); + +HC_CPP_END + +#endif /* HEIM_EVP_WINCNG_H */ diff --git a/lib/hcrypto/evp.c b/lib/hcrypto/evp.c index 75eefc493..c564353e4 100644 --- a/lib/hcrypto/evp.c +++ b/lib/hcrypto/evp.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -175,10 +176,13 @@ EVP_MD_CTX_destroy(EVP_MD_CTX *ctx) int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) HC_DEPRECATED { - if (ctx->md && ctx->md->cleanup) - (ctx->md->cleanup)(ctx); - else if (ctx->md) + if (ctx->md && ctx->md->cleanup) { + int ret = (ctx->md->cleanup)(ctx); + if (!ret) + return ret; + } else if (ctx->md) { memset(ctx->ptr, 0, ctx->md->ctx_size); + } ctx->md = NULL; ctx->engine = NULL; free(ctx->ptr); @@ -258,8 +262,7 @@ EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *md, ENGINE *engine) if (ctx->ptr == NULL) return 0; } - (ctx->md->init)(ctx->ptr); - return 1; + return (ctx->md->init)(ctx->ptr); } /** @@ -582,8 +585,11 @@ EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *c) int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c) { - if (c->cipher && c->cipher->cleanup) - c->cipher->cleanup(c); + if (c->cipher && c->cipher->cleanup) { + int ret = c->cipher->cleanup(c); + if (!ret) + return ret; + } if (c->cipher_data) { memset(c->cipher_data, 0, c->cipher->ctx_size); free(c->cipher_data); @@ -814,7 +820,7 @@ EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *c, ENGINE *engine, } if (key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) - ctx->cipher->init(ctx, key, iv, encp); + return ctx->cipher->init(ctx, key, iv, encp); return 1; } diff --git a/lib/hcrypto/libhcrypto-exports.def b/lib/hcrypto/libhcrypto-exports.def index a7208f931..6fc728614 100644 --- a/lib/hcrypto/libhcrypto-exports.def +++ b/lib/hcrypto/libhcrypto-exports.def @@ -175,6 +175,26 @@ EXPORTS ;! hc_EVP_cc_aes_192_cfb8 ;! hc_EVP_cc_aes_256_cfb8 + hc_EVP_w32crypto_md2 ;! + hc_EVP_w32crypto_md4 ;! + hc_EVP_w32crypto_md5 ;! + hc_EVP_w32crypto_sha1 ;! + hc_EVP_w32crypto_sha256 ;! + hc_EVP_w32crypto_sha384 ;! + hc_EVP_w32crypto_sha512 ;! + hc_EVP_w32crypto_des_ede3_cbc ;! + hc_EVP_w32crypto_aes_128_cbc ;! + hc_EVP_w32crypto_aes_192_cbc ;! + hc_EVP_w32crypto_aes_256_cbc ;! + hc_EVP_w32crypto_rc2_40_cbc ;! + hc_EVP_w32crypto_rc2_cbc ;! + hc_EVP_w32crypto_rc4 ;! + hc_EVP_w32crypto_rc4_40 ;! + + hc_EVP_w32crypto_aes_128_cfb8 ;! + hc_EVP_w32crypto_aes_192_cfb8 ;! + hc_EVP_w32crypto_aes_256_cfb8 ;! + hc_EVP_hcrypto_md2 hc_EVP_hcrypto_md4 hc_EVP_hcrypto_md5 @@ -284,6 +304,7 @@ EXPORTS hc_EVP_CIPHER_CTX_ctrl hc_EVP_CIPHER_CTX_rand_key hc_EVP_CIPHER_CTX_set_key_length + hc_EVP_hcrypto_rc2_cbc hc_EVP_hcrypto_rc2_40_cbc hc_EVP_hcrypto_camellia_128_cbc hc_EVP_CipherUpdate diff --git a/lib/hcrypto/md2.c b/lib/hcrypto/md2.c index b6517a631..58075765e 100644 --- a/lib/hcrypto/md2.c +++ b/lib/hcrypto/md2.c @@ -57,10 +57,11 @@ static const unsigned char subst[256] = { 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 }; -void +int MD2_Init (struct md2 *m) { memset(m, 0, sizeof(*m)); + return 1; } static void @@ -91,7 +92,7 @@ calc(struct md2 *m, const void *v) memset(x, 0, sizeof(x)); } -void +int MD2_Update (struct md2 *m, const void *v, size_t len) { size_t idx = m->len & 0xf; @@ -114,9 +115,10 @@ MD2_Update (struct md2 *m, const void *v, size_t len) } memcpy(m->data + idx, p, len); + return 1; } -void +int MD2_Final (void *res, struct md2 *m) { unsigned char pad[16]; @@ -131,4 +133,5 @@ MD2_Final (void *res, struct md2 *m) memcpy(res, m->state, MD2_DIGEST_LENGTH); memset(m, 0, sizeof(*m)); + return 1; } diff --git a/lib/hcrypto/md2.h b/lib/hcrypto/md2.h index af765060a..d82334eac 100644 --- a/lib/hcrypto/md2.h +++ b/lib/hcrypto/md2.h @@ -56,8 +56,8 @@ struct md2 { typedef struct md2 MD2_CTX; -void MD2_Init (struct md2 *m); -void MD2_Update (struct md2 *m, const void *p, size_t len); -void MD2_Final (void *res, struct md2 *m); +int MD2_Init (struct md2 *m); +int MD2_Update (struct md2 *m, const void *p, size_t len); +int MD2_Final (void *res, struct md2 *m); #endif /* HEIM_MD2_H */ diff --git a/lib/hcrypto/md4.c b/lib/hcrypto/md4.c index 1a9f77fed..7617d9af5 100644 --- a/lib/hcrypto/md4.c +++ b/lib/hcrypto/md4.c @@ -42,7 +42,7 @@ #define D m->counter[3] #define X data -void +int MD4_Init (struct md4 *m) { m->sz[0] = 0; @@ -51,6 +51,7 @@ MD4_Init (struct md4 *m) C = 0x98badcfe; B = 0xefcdab89; A = 0x67452301; + return 1; } #define F(x,y,z) CRAYFIX((x & y) | (~x & z)) @@ -170,7 +171,7 @@ struct x32{ unsigned int b:32; }; -void +int MD4_Update (struct md4 *m, const void *v, size_t len) { const unsigned char *p = v; @@ -203,9 +204,10 @@ MD4_Update (struct md4 *m, const void *v, size_t len) offset = 0; } } + return 1; } -void +int MD4_Final (void *res, struct md4 *m) { unsigned char zeros[72]; @@ -243,4 +245,5 @@ MD4_Final (void *res, struct md4 *m) r[i] = swap_uint32_t (m->counter[i]); } #endif + return 1; } diff --git a/lib/hcrypto/md4.h b/lib/hcrypto/md4.h index ce17d0f08..06575c5c3 100644 --- a/lib/hcrypto/md4.h +++ b/lib/hcrypto/md4.h @@ -55,8 +55,8 @@ struct md4 { typedef struct md4 MD4_CTX; -void MD4_Init (struct md4 *m); -void MD4_Update (struct md4 *m, const void *p, size_t len); -void MD4_Final (void *res, struct md4 *m); +int MD4_Init (struct md4 *m); +int MD4_Update (struct md4 *m, const void *p, size_t len); +int MD4_Final (void *res, struct md4 *m); #endif /* HEIM_MD4_H */ diff --git a/lib/hcrypto/md5.c b/lib/hcrypto/md5.c index aa0bab463..cf8219dcd 100644 --- a/lib/hcrypto/md5.c +++ b/lib/hcrypto/md5.c @@ -42,7 +42,7 @@ #define D m->counter[3] #define X data -void +int MD5_Init (struct md5 *m) { m->sz[0] = 0; @@ -51,6 +51,7 @@ MD5_Init (struct md5 *m) C = 0x98badcfe; B = 0xefcdab89; A = 0x67452301; + return 1; } #define F(x,y,z) CRAYFIX((x & y) | (~x & z)) @@ -194,7 +195,7 @@ struct x32{ unsigned int b:32; }; -void +int MD5_Update (struct md5 *m, const void *v, size_t len) { const unsigned char *p = v; @@ -227,9 +228,10 @@ MD5_Update (struct md5 *m, const void *v, size_t len) offset = 0; } } + return 1; } -void +int MD5_Final (void *res, struct md5 *m) { unsigned char zeros[72]; @@ -267,4 +269,5 @@ MD5_Final (void *res, struct md5 *m) r[i] = swap_uint32_t (m->counter[i]); } #endif + return 1; } diff --git a/lib/hcrypto/md5.h b/lib/hcrypto/md5.h index b2df6e56f..ab1ac3540 100644 --- a/lib/hcrypto/md5.h +++ b/lib/hcrypto/md5.h @@ -55,8 +55,8 @@ struct md5 { typedef struct md5 MD5_CTX; -void MD5_Init (struct md5 *m); -void MD5_Update (struct md5 *m, const void *p, size_t len); -void MD5_Final (void *res, struct md5 *m); /* uint32_t res[4] */ +int MD5_Init (struct md5 *m); +int MD5_Update (struct md5 *m, const void *p, size_t len); +int MD5_Final (void *res, struct md5 *m); /* uint32_t res[4] */ #endif /* HEIM_MD5_H */ diff --git a/lib/hcrypto/sha.c b/lib/hcrypto/sha.c index 9c8b39e24..0f8f53a33 100644 --- a/lib/hcrypto/sha.c +++ b/lib/hcrypto/sha.c @@ -43,7 +43,7 @@ #define E m->counter[4] #define X data -void +int SHA1_Init (struct sha *m) { m->sz[0] = 0; @@ -53,6 +53,7 @@ SHA1_Init (struct sha *m) C = 0x98badcfe; D = 0x10325476; E = 0xc3d2e1f0; + return 1; } @@ -220,7 +221,7 @@ struct x32{ unsigned int b:32; }; -void +int SHA1_Update (struct sha *m, const void *v, size_t len) { const unsigned char *p = v; @@ -253,9 +254,10 @@ SHA1_Update (struct sha *m, const void *v, size_t len) offset = 0; } } + return 1; } -void +int SHA1_Final (void *res, struct sha *m) { unsigned char zeros[72]; @@ -293,4 +295,5 @@ SHA1_Final (void *res, struct sha *m) r[i] = swap_uint32_t (m->counter[i]); } #endif + return 1; } diff --git a/lib/hcrypto/sha.h b/lib/hcrypto/sha.h index fbc1810b4..59d72408c 100644 --- a/lib/hcrypto/sha.h +++ b/lib/hcrypto/sha.h @@ -64,9 +64,9 @@ struct sha { typedef struct sha SHA_CTX; -void SHA1_Init (struct sha *m); -void SHA1_Update (struct sha *m, const void *v, size_t len); -void SHA1_Final (void *res, struct sha *m); +int SHA1_Init (struct sha *m); +int SHA1_Update (struct sha *m, const void *v, size_t len); +int SHA1_Final (void *res, struct sha *m); /* * SHA-2 256 @@ -82,9 +82,9 @@ struct hc_sha256state { typedef struct hc_sha256state SHA256_CTX; -void SHA256_Init (SHA256_CTX *); -void SHA256_Update (SHA256_CTX *, const void *, size_t); -void SHA256_Final (void *, SHA256_CTX *); +int SHA256_Init (SHA256_CTX *); +int SHA256_Update (SHA256_CTX *, const void *, size_t); +int SHA256_Final (void *, SHA256_CTX *); /* * SHA-2 512 @@ -100,16 +100,16 @@ struct hc_sha512state { typedef struct hc_sha512state SHA512_CTX; -void SHA512_Init (SHA512_CTX *); -void SHA512_Update (SHA512_CTX *, const void *, size_t); -void SHA512_Final (void *, SHA512_CTX *); +int SHA512_Init (SHA512_CTX *); +int SHA512_Update (SHA512_CTX *, const void *, size_t); +int SHA512_Final (void *, SHA512_CTX *); #define SHA384_DIGEST_LENGTH 48 typedef struct hc_sha512state SHA384_CTX; -void SHA384_Init (SHA384_CTX *); -void SHA384_Update (SHA384_CTX *, const void *, size_t); -void SHA384_Final (void *, SHA384_CTX *); +int SHA384_Init (SHA384_CTX *); +int SHA384_Update (SHA384_CTX *, const void *, size_t); +int SHA384_Final (void *, SHA384_CTX *); #endif /* HEIM_SHA_H */ diff --git a/lib/hcrypto/sha256.c b/lib/hcrypto/sha256.c index 108afdccc..221e832c2 100644 --- a/lib/hcrypto/sha256.c +++ b/lib/hcrypto/sha256.c @@ -74,7 +74,7 @@ static const uint32_t constant_256[64] = { 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; -void +int SHA256_Init (SHA256_CTX *m) { m->sz[0] = 0; @@ -87,6 +87,7 @@ SHA256_Init (SHA256_CTX *m) F = 0x9b05688c; G = 0x1f83d9ab; H = 0x5be0cd19; + return 1; } static void @@ -162,7 +163,7 @@ struct x32{ unsigned int b:32; }; -void +int SHA256_Update (SHA256_CTX *m, const void *v, size_t len) { const unsigned char *p = v; @@ -195,9 +196,10 @@ SHA256_Update (SHA256_CTX *m, const void *v, size_t len) offset = 0; } } + return 1; } -void +int SHA256_Final (void *res, SHA256_CTX *m) { unsigned char zeros[72]; @@ -226,4 +228,5 @@ SHA256_Final (void *res, SHA256_CTX *m) r[4*i] = (m->counter[i] >> 24) & 0xFF; } } + return 1; } diff --git a/lib/hcrypto/sha512.c b/lib/hcrypto/sha512.c index 4bea21666..bf079b39a 100644 --- a/lib/hcrypto/sha512.c +++ b/lib/hcrypto/sha512.c @@ -98,7 +98,7 @@ static const uint64_t constant_512[80] = { 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL }; -void +int SHA512_Init (SHA512_CTX *m) { m->sz[0] = 0; @@ -111,6 +111,7 @@ SHA512_Init (SHA512_CTX *m) F = 0x9b05688c2b3e6c1fULL; G = 0x1f83d9abfb41bd6bULL; H = 0x5be0cd19137e2179ULL; + return 1; } static void @@ -184,7 +185,7 @@ struct x64{ }; #endif -void +int SHA512_Update (SHA512_CTX *m, const void *v, size_t len) { const unsigned char *p = v; @@ -217,9 +218,10 @@ SHA512_Update (SHA512_CTX *m, const void *v, size_t len) offset = 0; } } + return 1; } -void +int SHA512_Final (void *res, SHA512_CTX *m) { unsigned char zeros[128 + 16]; @@ -261,9 +263,10 @@ SHA512_Final (void *res, SHA512_CTX *m) r[8*i] = (m->counter[i] >> 56) & 0xFF; } } + return 1; } -void +int SHA384_Init(SHA384_CTX *m) { m->sz[0] = 0; @@ -276,19 +279,22 @@ SHA384_Init(SHA384_CTX *m) F = 0x8eb44a8768581511ULL; G = 0xdb0c2e0d64f98fa7ULL; H = 0x47b5481dbefa4fa4ULL; + return 1; } -void +int SHA384_Update (SHA384_CTX *m, const void *v, size_t len) { SHA512_Update(m, v, len); + return 1; } -void +int SHA384_Final (void *res, SHA384_CTX *m) { unsigned char data[SHA512_DIGEST_LENGTH]; SHA512_Final(data, m); memcpy(res, data, SHA384_DIGEST_LENGTH); + return 1; } diff --git a/lib/hcrypto/test_bulk.c b/lib/hcrypto/test_bulk.c new file mode 100644 index 000000000..6e87ef06a --- /dev/null +++ b/lib/hcrypto/test_bulk.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 +#define STATS_START(M) \ + LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds; \ + LARGE_INTEGER Frequency; \ + \ + QueryPerformanceFrequency(&Frequency); \ + QueryPerformanceCounter(&StartingTime); + +#define STATS_END(M) \ + QueryPerformanceCounter(&EndingTime); \ + ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart; \ + ElapsedMicroseconds.QuadPart *= 1000000; \ + ElapsedMicroseconds.QuadPart /= Frequency.QuadPart; \ + \ + M += (ElapsedMicroseconds.QuadPart - M) / (i + 1); +#else +#define STATS_START(M) \ + struct timeval StartingTime, EndingTime; \ + \ + gettimeofday(&StartingTime, NULL); + +#define STATS_END(M) \ + gettimeofday(&EndingTime, NULL); \ + timevalsub(&EndingTime, &StartingTime); \ + M += (EndingTime.tv_sec * 1000000 + EndingTime.tv_usec - M) / (i + 1); +#endif + +static int version_flag; +static int help_flag; +static int len = 1; +static int loops = 20; +static char *provider = "hcrypto"; +static unsigned char *d; + +#ifdef __APPLE__ +#define PROVIDER_USAGE "hcrypto|cc" +#elif defined(WIN32) +#define PROVIDER_USAGE "hcrypto|w32crypto" +#else +#define PROVIDER_USAGE "hcrypto" +#endif + +static struct getargs args[] = { + { "provider", 0, arg_string, &provider, + "crypto provider", PROVIDER_USAGE }, + { "loops", 0, arg_integer, &loops, + "number of loops", "loops" }, + { "size", 0, arg_integer, &len, + "size (KB)", NULL }, + { "version", 0, arg_flag, &version_flag, + "print version", NULL }, + { "help", 0, arg_flag, &help_flag, + NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, + sizeof(args)/sizeof(*args), + NULL, + ""); + exit (ret); +} + +static int +test_bulk_cipher(const char *cname, const EVP_CIPHER *c) +{ + static unsigned char key[16]; + static unsigned char iv[16]; + int i; + int64_t M = 0; + + for (i = 0; i < loops; i++) { + EVP_CIPHER_CTX ectx; + EVP_CIPHER_CTX dctx; + + STATS_START(M) + + EVP_CIPHER_CTX_init(&ectx); + EVP_CIPHER_CTX_init(&dctx); + + if (EVP_CipherInit_ex(&ectx, c, NULL, NULL, NULL, 1) != 1) + errx(1, "can't init encrypt"); + if (EVP_CipherInit_ex(&dctx, c, NULL, NULL, NULL, 0) != 1) + errx(1, "can't init decrypt"); + + EVP_CIPHER_CTX_set_key_length(&ectx, sizeof(key)); + EVP_CIPHER_CTX_set_key_length(&dctx, sizeof(key)); + + if (EVP_CipherInit_ex(&ectx, NULL, NULL, key, iv, 1) != 1) + errx(1, "can't init encrypt"); + if (EVP_CipherInit_ex(&dctx, NULL, NULL, key, iv, 0) != 1) + errx(1, "can't init decrypt"); + + if (!EVP_Cipher(&ectx, d, d, len)) + errx(1, "can't encrypt"); + if (!EVP_Cipher(&dctx, d, d, len)) + errx(1, "can't decrypt"); + + EVP_CIPHER_CTX_cleanup(&ectx); + EVP_CIPHER_CTX_cleanup(&dctx); + + STATS_END(M); + + if (d[0] != 0x00 || d[len - 1] != ((len - 1) & 0xff)) + errx(1, "encrypt/decrypt inconsistent"); + } + + printf("%s: mean time %llu usec%s\n", cname, M, (M == 1) ? "" : "s"); + + return 0; +} + +static int +test_bulk_digest(const char *cname, const EVP_MD *md) +{ + char digest[EVP_MAX_MD_SIZE]; + int i; + unsigned int tmp = sizeof(digest); + int64_t M = 0; + + for (i = 0; i < loops; i++) { + STATS_START(M); + EVP_Digest(d, len, digest, &tmp, md, NULL); + STATS_END(M); + } + + printf("%s: mean time %llu usec%s\n", cname, M, (M == 1) ? "" : "s"); + + return 0; +} + +static void +test_bulk_provider_hcrypto(void) +{ + test_bulk_cipher("hcrypto_aes_256_cbc", EVP_hcrypto_aes_256_cbc()); +#if 0 + test_bulk_cipher("hcrypto_aes_256_cfb8", EVP_hcrypto_aes_256_cfb8()); +#endif + test_bulk_cipher("hcrypto_rc4", EVP_hcrypto_rc4()); + test_bulk_digest("hcrypto_md2", EVP_hcrypto_md2()); + test_bulk_digest("hcrypto_md4", EVP_hcrypto_md4()); + test_bulk_digest("hcrypto_md5", EVP_hcrypto_md5()); + test_bulk_digest("hcrypto_sha1", EVP_hcrypto_sha1()); + test_bulk_digest("hcrypto_sha256", EVP_hcrypto_sha256()); + test_bulk_digest("hcrypto_sha384", EVP_hcrypto_sha384()); + test_bulk_digest("hcrypto_sha512", EVP_hcrypto_sha512()); +} + +#ifdef __APPLE__ +static void +test_bulk_provider_cc(void) +{ + test_bulk_cipher("cc_aes_256_cbc", EVP_cc_aes_256_cbc()); +#if 0 + test_bulk_cipher("cc_aes_256_cfb8", EVP_cc_aes_256_cfb8()); +#endif + test_bulk_cipher("cc_rc4", EVP_cc_rc4()); + test_bulk_digest("cc_md2", EVP_cc_md2()); + test_bulk_digest("cc_md4", EVP_cc_md4()); + test_bulk_digest("cc_md5", EVP_cc_md5()); + test_bulk_digest("cc_sha1", EVP_cc_sha1()); + test_bulk_digest("cc_sha256", EVP_cc_sha256()); +} +#endif /* __APPLE__ */ + +#ifdef WIN32 +static void +test_bulk_provider_w32crypto(void) +{ + test_bulk_cipher("w32crypto_aes_256_cbc", EVP_w32crypto_aes_256_cbc()); +#if 0 + test_bulk_cipher("w32crypto_aes_256_cfb8", EVP_w32crypto_aes_256_cfb8()); +#endif + test_bulk_cipher("w32crypto_rc4", EVP_w32crypto_rc4()); + test_bulk_digest("w32crypto_md2", EVP_w32crypto_md2()); + test_bulk_digest("w32crypto_md4", EVP_w32crypto_md4()); + test_bulk_digest("w32crypto_md5", EVP_w32crypto_md5()); + test_bulk_digest("w32crypto_sha1", EVP_w32crypto_sha1()); + test_bulk_digest("w32crypto_sha256", EVP_w32crypto_sha256()); + test_bulk_digest("w32crypto_sha384", EVP_w32crypto_sha384()); + test_bulk_digest("w32crypto_sha512", EVP_w32crypto_sha512()); +} +#endif /* WIN32 */ + +int +main(int argc, char **argv) +{ + int ret = 0; + int idx = 0; + int i; + + setprogname(argv[0]); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &idx)) + usage(1); + + if (help_flag) + usage(0); + + if(version_flag) { + print_version(NULL); + exit(0); + } + + argc -= idx; + argv += idx; + + len *= 1024; + + d = emalloc(len); + for (i = 0; i < len; i++) + d[i] = i & 0xff; + + if (strcmp(provider, "hcrypto") == 0) + test_bulk_provider_hcrypto(); +#ifdef __APPLE__ + else if (strcmp(provider, "cc") == 0) + test_bulk_provider_cc(); +#endif +#ifdef WIN32 + else if (strcmp(provider, "w32crypto") == 0) + test_bulk_provider_w32crypto(); +#endif + else + usage(1); + + free(d); + + return ret; +} diff --git a/lib/hcrypto/test_cipher.c b/lib/hcrypto/test_cipher.c index 8075efb3e..6eb9f3fe5 100644 --- a/lib/hcrypto/test_cipher.c +++ b/lib/hcrypto/test_cipher.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -80,11 +81,25 @@ struct tests aes_cfb_tests[] = { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", - "\x66\xe9\x4b\xd4\xef\x8a\x2c\x3b\x88\x4c\xfa\x59\xca\x34\x2b\x2e", + "\x66\x16\xf9\x2e\x42\xa8\xf1\x1a\x91\x16\x68\x57\x8e\xc3\xaa\x0f", NULL } }; + +struct tests rc2_tests[] = { + { "rc2", + "\x88\xbc\xa9\x0e\x90\x87\x5a\x7f\x0f\x79\xc3\x84\x62\x7b\xaf\xb2", + 16, + "\x00\x00\x00\x00\x00\x00\x00\x00", + 8, + "\x00\x00\x00\x00\x00\x00\x00\x00", + "\x22\x69\x55\x2a\xb0\xf8\x5c\xa6", + NULL + } +}; + + struct tests rc2_40_tests[] = { { "rc2-40", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", @@ -264,7 +279,7 @@ test_cipher(int i, const EVP_CIPHER *c, struct tests *t) d = emalloc(t->datasize); if (!EVP_Cipher(&ectx, d, t->indata, t->datasize)) - return 1; + errx(1, "%s: %d EVP_Cipher encrypt failed", t->name, i); if (memcmp(d, t->outdata, t->datasize) != 0) { char *s, *s2; @@ -274,7 +289,7 @@ test_cipher(int i, const EVP_CIPHER *c, struct tests *t) } if (!EVP_Cipher(&dctx, d, d, t->datasize)) - return 1; + errx(1, "%s: %d EVP_Cipher decrypt failed", t->name, i); if (memcmp(d, t->indata, t->datasize) != 0) { char *s; @@ -338,7 +353,8 @@ main(int argc, char **argv) ret += test_cipher(i, EVP_hcrypto_aes_256_cbc(), &aes_tests[i]); for (i = 0; i < sizeof(aes_cfb_tests)/sizeof(aes_cfb_tests[0]); i++) ret += test_cipher(i, EVP_hcrypto_aes_128_cfb8(), &aes_cfb_tests[i]); - + for (i = 0; i < sizeof(rc2_tests)/sizeof(rc2_tests[0]); i++) + ret += test_cipher(i, EVP_hcrypto_rc2_cbc(), &rc2_tests[i]); for (i = 0; i < sizeof(rc2_40_tests)/sizeof(rc2_40_tests[0]); i++) ret += test_cipher(i, EVP_hcrypto_rc2_40_cbc(), &rc2_40_tests[i]); for (i = 0; i < sizeof(des_ede3_tests)/sizeof(des_ede3_tests[0]); i++) @@ -353,10 +369,8 @@ main(int argc, char **argv) #ifdef __APPLE__ for (i = 0; i < sizeof(aes_tests)/sizeof(aes_tests[0]); i++) ret += test_cipher(i, EVP_cc_aes_256_cbc(), &aes_tests[i]); -#if 0 for (i = 0; i < sizeof(aes_cfb_tests)/sizeof(aes_cfb_tests[0]); i++) ret += test_cipher(i, EVP_cc_aes_128_cfb8(), &aes_cfb_tests[i]); -#endif for (i = 0; i < sizeof(rc2_40_tests)/sizeof(rc2_40_tests[0]); i++) ret += test_cipher(i, EVP_cc_rc2_40_cbc(), &rc2_40_tests[i]); for (i = 0; i < sizeof(des_ede3_tests)/sizeof(des_ede3_tests[0]); i++) @@ -366,7 +380,23 @@ main(int argc, char **argv) &camellia128_tests[i]); for (i = 0; i < sizeof(rc4_tests)/sizeof(rc4_tests[0]); i++) ret += test_cipher(i, EVP_cc_rc4(), &rc4_tests[i]); -#endif +#endif /* __APPLE__ */ + + /* Windows CNG (if available) */ +#ifdef WIN32 + for (i = 0; i < sizeof(aes_tests)/sizeof(aes_tests[0]); i++) + ret += test_cipher(i, EVP_w32crypto_aes_256_cbc(), &aes_tests[i]); + for (i = 0; i < sizeof(aes_cfb_tests)/sizeof(aes_cfb_tests[0]); i++) + ret += test_cipher(i, EVP_w32crypto_aes_128_cfb8(), &aes_cfb_tests[i]); + for (i = 0; i < sizeof(rc2_tests)/sizeof(rc2_tests[0]); i++) + ret += test_cipher(i, EVP_w32crypto_rc2_cbc(), &rc2_tests[i]); + for (i = 0; i < sizeof(rc2_40_tests)/sizeof(rc2_40_tests[0]); i++) + ret += test_cipher(i, EVP_w32crypto_rc2_40_cbc(), &rc2_40_tests[i]); + for (i = 0; i < sizeof(des_ede3_tests)/sizeof(des_ede3_tests[0]); i++) + ret += test_cipher(i, EVP_w32crypto_des_ede3_cbc(), &des_ede3_tests[i]); + for (i = 0; i < sizeof(rc4_tests)/sizeof(rc4_tests[0]); i++) + ret += test_cipher(i, EVP_w32crypto_rc4(), &rc4_tests[i]); +#endif /* WIN32 */ return ret; } diff --git a/lib/hcrypto/version-script.map b/lib/hcrypto/version-script.map index 6985d1b9e..ec202133f 100644 --- a/lib/hcrypto/version-script.map +++ b/lib/hcrypto/version-script.map @@ -289,6 +289,7 @@ HEIMDAL_CRYPTO_1.0 { hc_EVP_CIPHER_CTX_ctrl; hc_EVP_CIPHER_CTX_rand_key; hc_EVP_CIPHER_CTX_set_key_length; + hc_EVP_hcrypto_rc2_cbc; hc_EVP_hcrypto_rc2_40_cbc; hc_EVP_hcrypto_camellia_128_cbc; hc_EVP_CipherUpdate; diff --git a/lib/heimdal/NTMakefile b/lib/heimdal/NTMakefile index 39ac7ade8..b206cd3a8 100644 --- a/lib/heimdal/NTMakefile +++ b/lib/heimdal/NTMakefile @@ -54,6 +54,11 @@ DLLSDKDEPS= \ dnsapi.lib \ shlwapi.lib +dlllflags=$(dlllflags) /DELAYLOAD:bcrypt.dll +DLLSDKDEPS=$(DLLSDKDEPS)\ + bcrypt.lib \ + delayimp.lib + DEF=$(OBJ)\heimdal.def RES=$(OBJ)\heimdal-version.res diff --git a/lib/krb5/dll.c b/lib/krb5/dll.c index d03df3d29..a47487816 100644 --- a/lib/krb5/dll.c +++ b/lib/krb5/dll.c @@ -33,10 +33,25 @@ HINSTANCE _krb5_hInstance = NULL; +#if NTDDI_VERSION >= NTDDI_VISTA +extern BOOL WINAPI +_hc_w32crypto_DllMain(HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved); +#endif + BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { +#if NTDDI_VERSION >= NTDDI_VISTA + BOOL ret; + + ret = _hc_w32crypto_DllMain(hinstDLL, fdwReason, lpvReserved); + if (!ret) + return ret; +#endif + switch (fdwReason) { case DLL_PROCESS_ATTACH: diff --git a/windows/NTMakefile.w32 b/windows/NTMakefile.w32 index c5a382313..48e6aed26 100644 --- a/windows/NTMakefile.w32 +++ b/windows/NTMakefile.w32 @@ -162,6 +162,8 @@ pthreadinc= -I$(PTHREAD_INC) cincdirs=$(cincdirs) -I$(INCDIR) -I$(INCDIR)\krb5 $(pthreadinc) cdefines=$(cdefines) -DHAVE_CONFIG_H +# Windows CNG provider +cdefines=$(cdefines) -DHCRYPTO_DEF_PROVIDER=w32crypto cdebug=$(cdebug) /Zi ldebug=$(ldebug) /DEBUG localcflags=$(localcflags) /Oy-