diff --git a/cf/crypto.m4 b/cf/crypto.m4 index 248b86ce5..a0b033ff0 100644 --- a/cf/crypto.m4 +++ b/cf/crypto.m4 @@ -135,6 +135,17 @@ if test "$crypto_lib" = "unknown"; then fi +AC_ARG_WITH(pkcs11-module, + AS_HELP_STRING([--with-pkcs11-module=path], + [use PKCS11 module in path]), + [pkcs11_module="$withval"], + []) + +if test "$pkcs11_module" != ""; then + AC_DEFINE_UNQUOTED(PKCS11_MODULE_PATH, "$pkcs11_module", [path to PKCS11 module]) + openssl=no +fi + if test "$openssl" = "yes"; then AC_DEFINE([HAVE_OPENSSL], 1, [define to use openssl's libcrypto]) fi diff --git a/lib/hcrypto/Makefile.am b/lib/hcrypto/Makefile.am index cc0e6c527..c24f72bfa 100644 --- a/lib/hcrypto/Makefile.am +++ b/lib/hcrypto/Makefile.am @@ -2,7 +2,8 @@ include $(top_srcdir)/Makefile.am.common -AM_CPPFLAGS += -I$(srcdir)/libtommath -DUSE_HCRYPTO_LTM=1 +AM_CPPFLAGS += -I$(top_srcdir)/lib/hx509 \ + -I$(srcdir)/libtommath -DUSE_HCRYPTO_LTM=1 lib_LTLIBRARIES = libhcrypto.la check_LTLIBRARIES = libhctest.la @@ -11,6 +12,7 @@ libhcrypto_la_LDFLAGS = -version-info 5:0:1 libhcrypto_la_LIBADD = \ $(top_builddir)/lib/asn1/libasn1.la \ $(LIB_dlopen) \ + $(LIB_heimbase) \ $(LIBADD_roken) hcryptoincludedir = $(includedir)/hcrypto @@ -29,6 +31,7 @@ hcryptoinclude_HEADERS = \ evp.h \ evp-hcrypto.h \ evp-cc.h \ + evp-pkcs11.h \ hmac.h \ md2.h \ md4.h \ @@ -114,6 +117,7 @@ libhcrypto_la_SOURCES = \ evp.h \ evp-hcrypto.c \ evp-cc.c \ + evp-pkcs11.c \ engine.c \ engine.h \ hash.h \ diff --git a/lib/hcrypto/NTMakefile b/lib/hcrypto/NTMakefile index 9939c8222..9d0fe74b1 100644 --- a/lib/hcrypto/NTMakefile +++ b/lib/hcrypto/NTMakefile @@ -33,10 +33,17 @@ SUBDIRS=libtommath RELDIR=lib\hcrypto -intcflags=-DKRB5 -DASN1_LIB -I$(HCRYPTOINCLUDEDIR) -DUSE_HCRYPTO_LTM=1 - !include ../../windows/NTMakefile.w32 +HCRYPTOINCLUDEDIR = $(INCDIR)\hcrypto + +HEIMBASEDIR = $(SRC)\lib\base + +HX509DIR = $(SRC)\lib\hx509 + +intcflags=-DKRB5 -DASN1_LIB -I$(HCRYPTOINCLUDEDIR) -DUSE_HCRYPTO_LTM=1 \ + -I$(HX509DIR) + # Do dependencies first all:: subdirs @@ -47,8 +54,6 @@ test:: test-subdirs # Include files -HCRYPTOINCLUDEDIR=$(INCDIR)\hcrypto - INCFILES= \ $(HCRYPTOINCLUDEDIR)\aes.h \ $(HCRYPTOINCLUDEDIR)\bn.h \ @@ -62,6 +67,7 @@ INCFILES= \ $(HCRYPTOINCLUDEDIR)\evp.h \ $(HCRYPTOINCLUDEDIR)\evp-hcrypto.h \ $(HCRYPTOINCLUDEDIR)\evp-cc.h \ + $(HCRYPTOINCLUDEDIR)\evp-pkcs11.h \ $(HCRYPTOINCLUDEDIR)\evp-wincng.h \ $(HCRYPTOINCLUDEDIR)\evp-w32.h \ $(HCRYPTOINCLUDEDIR)\hmac.h \ @@ -105,6 +111,7 @@ libhcrypto_OBJs = \ $(OBJ)\evp.obj \ $(OBJ)\evp-hcrypto.obj \ $(OBJ)\evp-cc.obj \ + $(OBJ)\evp-pkcs11.obj \ $(OBJ)\evp-wincng.obj \ $(OBJ)\evp-w32.obj \ $(OBJ)\engine.obj \ @@ -165,63 +172,63 @@ test-binaries: \ $(OBJ)\test_rand.exe \ $(OBJ)\test_crypto.sh -$(OBJ)\destest.exe: $(OBJ)\destest.obj $(TESTLIB) $(LIBROKEN) +$(OBJ)\destest.exe: $(OBJ)\destest.obj $(TESTLIB) $(LIBROKEN) $(LIBHEIMBASE) $(EXECONLINK) $(EXEPREP_NODIST) -$(OBJ)\example_evp_cipher.exe: $(OBJ)\example_evp_cipher.obj $(TESTLIB) $(LIBHEIMDAL) $(LIBROKEN) +$(OBJ)\example_evp_cipher.exe: $(OBJ)\example_evp_cipher.obj $(TESTLIB) $(LIBHEIMDAL) $(LIBROKEN) $(LIBHEIMBASE) $(EXECONLINK) $(EXEPREP_NODIST) -$(OBJ)\mdtest.exe: $(OBJ)\mdtest.obj $(LIBHEIMDAL) $(LIBROKEN) $(OBJ)\sha512.obj +$(OBJ)\mdtest.exe: $(OBJ)\mdtest.obj $(LIBHEIMDAL) $(LIBROKEN) $(LIBHEIMBASE) $(OBJ)\sha512.obj $(EXECONLINK) $(EXEPREP_NODIST) -$(OBJ)\rc2test.exe: $(OBJ)\rc2test.obj $(LIBHEIMDAL) $(LIBROKEN) +$(OBJ)\rc2test.exe: $(OBJ)\rc2test.obj $(LIBHEIMDAL) $(LIBROKEN) $(LIBHEIMBASE) $(EXECONLINK) $(EXEPREP_NODIST) -$(OBJ)\rctest.exe: $(OBJ)\rctest.obj $(LIBHEIMDAL) $(LIBROKEN) +$(OBJ)\rctest.exe: $(OBJ)\rctest.obj $(LIBHEIMDAL) $(LIBROKEN) $(LIBHEIMBASE) $(EXECONLINK) $(EXEPREP_NODIST) -$(OBJ)\test_bn.exe: $(OBJ)\test_bn.obj $(LIBHEIMDAL) $(LIBROKEN) +$(OBJ)\test_bn.exe: $(OBJ)\test_bn.obj $(LIBHEIMDAL) $(LIBROKEN) $(LIBHEIMBASE) $(EXECONLINK) $(EXEPREP_NODIST) -$(OBJ)\test_bulk.exe: $(OBJ)\test_bulk.obj $(TESTLIB) $(LIBHEIMDAL) $(LIBROKEN) $(LIBVERS) +$(OBJ)\test_bulk.exe: $(OBJ)\test_bulk.obj $(TESTLIB) $(LIBHEIMDAL) $(LIBROKEN) $(LIBHEIMBASE) $(LIBVERS) $(EXECONLINK) $(EXEPREP_NODIST) -$(OBJ)\test_cipher.exe: $(OBJ)\test_cipher.obj $(TESTLIB) $(LIBHEIMDAL) $(LIBROKEN) $(LIBVERS) +$(OBJ)\test_cipher.exe: $(OBJ)\test_cipher.obj $(TESTLIB) $(LIBHEIMDAL) $(LIBROKEN) $(LIBHEIMBASE) $(LIBVERS) $(EXECONLINK) $(EXEPREP_NODIST) -$(OBJ)\test_engine_dso.exe: $(OBJ)\test_engine_dso.obj $(LIBHEIMDAL) $(LIBROKEN) $(LIBVERS) +$(OBJ)\test_engine_dso.exe: $(OBJ)\test_engine_dso.obj $(LIBHEIMDAL) $(LIBROKEN) $(LIBHEIMBASE) $(LIBVERS) $(EXECONLINK) $(EXEPREP_NODIST) -$(OBJ)\test_hmac.exe: $(OBJ)\test_hmac.obj $(LIBHEIMDAL) $(LIBROKEN) +$(OBJ)\test_hmac.exe: $(OBJ)\test_hmac.obj $(LIBHEIMDAL) $(LIBROKEN) $(LIBHEIMBASE) $(EXECONLINK) $(EXEPREP_NODIST) -$(OBJ)\test_pkcs5.exe: $(OBJ)\test_pkcs5.obj $(LIBHEIMDAL) $(LIBROKEN) +$(OBJ)\test_pkcs5.exe: $(OBJ)\test_pkcs5.obj $(LIBHEIMDAL) $(LIBROKEN) $(LIBHEIMBASE) $(EXECONLINK) $(EXEPREP_NODIST) -$(OBJ)\test_pkcs12.exe: $(OBJ)\test_pkcs12.obj $(LIBHEIMDAL) $(LIBROKEN) +$(OBJ)\test_pkcs12.exe: $(OBJ)\test_pkcs12.obj $(LIBHEIMDAL) $(LIBROKEN) $(LIBHEIMBASE) $(EXECONLINK) $(EXEPREP_NODIST) -$(OBJ)\test_rsa.exe: $(OBJ)\test_rsa.obj $(LIBHEIMDAL) $(LIBROKEN) $(LIBVERS) +$(OBJ)\test_rsa.exe: $(OBJ)\test_rsa.obj $(LIBHEIMDAL) $(LIBROKEN) $(LIBHEIMBASE) $(LIBVERS) $(EXECONLINK) $(EXEPREP_NODIST) -$(OBJ)\test_dh.exe: $(OBJ)\test_dh.obj $(LIBHEIMDAL) $(LIBROKEN) $(LIBVERS) +$(OBJ)\test_dh.exe: $(OBJ)\test_dh.obj $(LIBHEIMDAL) $(LIBROKEN) $(LIBHEIMBASE) $(LIBVERS) $(EXECONLINK) $(EXEPREP_NODIST) -$(OBJ)\test_rand.exe: $(OBJ)\test_rand.obj $(LIBHEIMDAL) $(LIBROKEN) $(LIBVERS) +$(OBJ)\test_rand.exe: $(OBJ)\test_rand.obj $(LIBHEIMDAL) $(LIBROKEN) $(LIBHEIMBASE) $(LIBVERS) $(EXECONLINK) $(EXEPREP_NODIST) diff --git a/lib/hcrypto/evp-pkcs11.c b/lib/hcrypto/evp-pkcs11.c new file mode 100644 index 000000000..9d420f509 --- /dev/null +++ b/lib/hcrypto/evp-pkcs11.c @@ -0,0 +1,775 @@ +/* + * 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. + */ + +/* PKCS#11 provider */ + +#include "config.h" + +#include +#ifdef HAVE_DLFCN_H +#include +#ifndef RTLD_LAZY +#define RTLD_LAZY 0 +#endif +#ifndef RTLD_LOCAL +#define RTLD_LOCAL 0 +#endif +#ifndef RTLD_GROUP +#define RTLD_GROUP 0 +#endif +#ifndef RTLD_NODELETE +#define RTLD_NODELETE 0 +#endif +#else +#error PKCS11 support requires dlfcn.h +#endif + +#include +#include + +#include +#include +#include + +#include + +#if __sun && !defined(PKCS11_MODULE_PATH) +# if _LP64 +# define PKCS11_MODULE_PATH "/usr/lib/64/libpkcs11.so" +# else +# define PKCS11_MODULE_PATH "/usr/lib/libpkcs11.so" +# endif +#endif + +static CK_FUNCTION_LIST_PTR p11_module; + +static int +p11_cleanup(EVP_CIPHER_CTX *ctx); + +struct pkcs11_cipher_ctx { + CK_SESSION_HANDLE hSession; + CK_OBJECT_HANDLE hSecret; +}; + +struct pkcs11_md_ctx { + CK_SESSION_HANDLE hSession; +}; + +static void +p11_module_init_once(void *context) +{ + CK_RV rv; + CK_FUNCTION_LIST_PTR module; + CK_RV (*C_GetFunctionList_fn)(CK_FUNCTION_LIST_PTR_PTR); + void *handle = NULL; + + if (!issuid()) { + char *pkcs11ModulePath = getenv("PKCS11_MODULE_PATH"); + if (pkcs11ModulePath != NULL) { + handle = dlopen(pkcs11ModulePath, RTLD_LAZY | RTLD_LOCAL | + RTLD_GROUP | RTLD_NODELETE); + if (handle == NULL) + fprintf(stderr, "p11_module_init(%s): %s\n", pkcs11ModulePath, dlerror()); + } + } +#ifdef PKCS11_MODULE_PATH + if (handle == NULL) { + handle = dlopen(PKCS11_MODULE_PATH, RTLD_LAZY | RTLD_LOCAL | + RTLD_GROUP | RTLD_NODELETE); + if (handle == NULL) + fprintf(stderr, "p11_module_init(%s): %s\n", PKCS11_MODULE_PATH, dlerror()); + } +#endif + if (handle == NULL) { + rv = CKR_LIBRARY_LOAD_FAILED; + goto cleanup; + } + + C_GetFunctionList_fn = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR)) + dlsym(handle, "C_GetFunctionList"); + if (C_GetFunctionList_fn == NULL) { + rv = CKR_LIBRARY_LOAD_FAILED; + goto cleanup; + } + + rv = C_GetFunctionList_fn(&module); + if (rv != CKR_OK) + goto cleanup; + + rv = module->C_Initialize(NULL); + if (rv == CKR_CRYPTOKI_ALREADY_INITIALIZED) + rv = CKR_OK; + if (rv == CKR_OK) + *((CK_FUNCTION_LIST_PTR_PTR)context) = module; + +cleanup: + if (handle != NULL && p11_module == NULL) + dlclose(handle); + /* else leak handle */ +} + +static CK_RV +p11_module_init(void) +{ + static heim_base_once_t init_module = HEIM_BASE_ONCE_INIT; + + heim_base_once_f(&init_module, &p11_module, p11_module_init_once); + + return p11_module != NULL ? CKR_OK : CKR_LIBRARY_LOAD_FAILED; +} + +static CK_RV +p11_session_init(CK_MECHANISM_TYPE mechanismType, CK_SESSION_HANDLE_PTR phSession) +{ + CK_RV rv; + CK_ULONG i, ulSlotCount = 0; + CK_SLOT_ID_PTR pSlotList = NULL; + CK_MECHANISM_INFO info; + + if (phSession != NULL) + *phSession = CK_INVALID_HANDLE; + + rv = p11_module_init(); + if (rv != CKR_OK) + goto cleanup; + + assert(p11_module != NULL); + + rv = p11_module->C_GetSlotList(CK_FALSE, NULL, &ulSlotCount); + if (rv != CKR_OK) + goto cleanup; + + pSlotList = (CK_SLOT_ID_PTR)calloc(ulSlotCount, sizeof(CK_SLOT_ID)); + if (pSlotList == NULL) { + rv = CKR_HOST_MEMORY; + goto cleanup; + } + + rv = p11_module->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount); + if (rv != CKR_OK) + goto cleanup; + + /* + * Note that this approach of using the first slot that supports the desired + * mechanism may not always be what the user wants (for example it may prefer + * software to hardware crypto). We're going to assume that this code will be + * principally used on Solaris (which has a meta-slot provider that sorts by + * hardware first) or in situations where the user can configure the slots in + * order of provider preference. In the future we should make this configurable. + */ + for (i = 0; i < ulSlotCount; i++) { + rv = p11_module->C_GetMechanismInfo(pSlotList[i], mechanismType, &info); + if (rv == CKR_OK) + break; + } + + if (i == ulSlotCount) { + rv = CKR_MECHANISM_INVALID; + goto cleanup; + } + + if (phSession != NULL) { + rv = p11_module->C_OpenSession(pSlotList[i], CKF_SERIAL_SESSION, NULL, NULL, phSession); + if (rv != CKR_OK) + goto cleanup; + } + +cleanup: + free(pSlotList); + + return rv; +} + +static int +p11_mech_available_p(CK_MECHANISM_TYPE mechanismType) +{ + return p11_session_init(mechanismType, NULL) == CKR_OK; +} + +static CK_KEY_TYPE +p11_key_type_for_mech(CK_MECHANISM_TYPE mechanismType) +{ + CK_KEY_TYPE keyType = 0; + + switch (mechanismType) { + case CKM_RC2_CBC: + keyType = CKK_RC2; + break; + case CKM_RC4: + keyType = CKK_RC4; + break; + case CKM_DES_CBC: + keyType = CKK_DES; + break; + case CKM_DES3_CBC: + keyType = CKK_DES3; + break; + case CKM_AES_CBC: + case CKM_AES_CFB8: + keyType = CKK_AES; + break; + case CKM_CAMELLIA_CBC: + keyType = CKK_CAMELLIA; + break; + default: + assert(0 && "Unknown PKCS#11 mechanism type"); + break; + } + + return keyType; +} + +static int +p11_key_init(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, + int encp) +{ + CK_RV rv; + CK_BBOOL bFalse = CK_FALSE; + CK_BBOOL bTrue = CK_TRUE; + CK_MECHANISM_TYPE mechanismType = (CK_MECHANISM_TYPE)ctx->cipher->app_data; + CK_KEY_TYPE keyType = p11_key_type_for_mech(mechanismType); + CK_OBJECT_CLASS objectClass = CKO_SECRET_KEY; + CK_ATTRIBUTE_TYPE op = encp ? CKA_ENCRYPT : CKA_DECRYPT; + CK_ATTRIBUTE attributes[] = { + { CKA_EXTRACTABLE, &bFalse, sizeof(bFalse) }, + { CKA_CLASS, &objectClass, sizeof(objectClass) }, + { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, + { CKA_TOKEN, &bFalse, sizeof(bFalse) }, + { CKA_PRIVATE, &bFalse, sizeof(bFalse) }, + { CKA_SENSITIVE, &bTrue, sizeof(bTrue) }, + { CKA_VALUE, (void *)key, ctx->key_len }, + { op, &bTrue, sizeof(bTrue) } + }; + struct pkcs11_cipher_ctx *p11ctx = (struct pkcs11_cipher_ctx *)ctx->cipher_data; + + rv = p11_session_init(mechanismType, &p11ctx->hSession); + if (rv != CKR_OK) + goto cleanup; + + assert(p11_module != NULL); + + rv = p11_module->C_CreateObject(p11ctx->hSession, attributes, + sizeof(attributes) / sizeof(attributes[0]), + &p11ctx->hSecret); + if (rv != CKR_OK) + goto cleanup; + +cleanup: + if (rv != CKR_OK) + p11_cleanup(ctx); + + return rv == CKR_OK; +} + +static int +p11_do_cipher(EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, + unsigned int size) +{ + struct pkcs11_cipher_ctx *p11ctx = (struct pkcs11_cipher_ctx *)ctx->cipher_data; + CK_RV rv; + CK_ULONG ulCipherTextLen = size; + CK_MECHANISM_TYPE mechanismType = (CK_MECHANISM_TYPE)ctx->cipher->app_data; + CK_MECHANISM mechanism = { + mechanismType, + ctx->cipher->iv_len ? ctx->iv : NULL, + ctx->cipher->iv_len + }; + + assert(p11_module != NULL); + assert(EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_STREAM_CIPHER || + (size % ctx->cipher->block_size) == 0); + + /* We cannot use C_EncryptUpdate() as it may buffer the output. */ + if (ctx->encrypt) { + rv = p11_module->C_EncryptInit(p11ctx->hSession, &mechanism, p11ctx->hSecret); + if (rv == CKR_OK) + rv = p11_module->C_Encrypt(p11ctx->hSession, (unsigned char *)in, size, out, &ulCipherTextLen); + } else { + rv = p11_module->C_DecryptInit(p11ctx->hSession, &mechanism, p11ctx->hSecret); + if (rv == CKR_OK) + rv = p11_module->C_Decrypt(p11ctx->hSession, (unsigned char *)in, size, out, &ulCipherTextLen); + } + + return rv == CKR_OK; +} + +static int +p11_cleanup(EVP_CIPHER_CTX *ctx) +{ + struct pkcs11_cipher_ctx *p11ctx = (struct pkcs11_cipher_ctx *)ctx->cipher_data; + + assert(p11_module != NULL); + + if (p11ctx->hSecret != CK_INVALID_HANDLE) { + p11_module->C_DestroyObject(p11ctx->hSession, p11ctx->hSecret); + p11ctx->hSecret = CK_INVALID_HANDLE; + } + if (p11ctx->hSession != CK_INVALID_HANDLE) { + p11_module->C_CloseSession(p11ctx->hSession); + p11ctx->hSession = CK_INVALID_HANDLE; + } + + return 1; +} + +static int +p11_md_hash_init(CK_MECHANISM_TYPE mechanismType, EVP_MD_CTX *ctx) +{ + struct pkcs11_md_ctx *p11ctx = (struct pkcs11_md_ctx *)ctx; + CK_RV rv; + + rv = p11_session_init(mechanismType, &p11ctx->hSession); + if (rv == CKR_OK) { + CK_MECHANISM mechanism = { mechanismType, NULL, 0 }; + + assert(p11_module != NULL); + + rv = p11_module->C_DigestInit(p11ctx->hSession, &mechanism); + } + + return rv == CKR_OK; +} + +static int +p11_md_update(EVP_MD_CTX *ctx, const void *data, size_t length) +{ + struct pkcs11_md_ctx *p11ctx = (struct pkcs11_md_ctx *)ctx; + CK_RV rv; + + assert(p11_module != NULL); + + rv = p11_module->C_DigestUpdate(p11ctx->hSession, (unsigned char *)data, length); + + return rv == CKR_OK; +} + +static int +p11_md_final(void *digest, EVP_MD_CTX *ctx) +{ + struct pkcs11_md_ctx *p11ctx = (struct pkcs11_md_ctx *)ctx; + CK_RV rv; + CK_ULONG digestLen = 0; + + assert(p11_module != NULL); + + rv = p11_module->C_DigestFinal(p11ctx->hSession, NULL, &digestLen); + if (rv == CKR_OK) + rv = p11_module->C_DigestFinal(p11ctx->hSession, digest, &digestLen); + + return rv == CKR_OK; +} + +static int +p11_md_cleanup(EVP_MD_CTX *ctx) +{ + struct pkcs11_md_ctx *p11ctx = (struct pkcs11_md_ctx *)ctx; + CK_RV rv; + + assert(p11_module != NULL); + + rv = p11_module->C_CloseSession(p11ctx->hSession); + if (rv == CKR_OK) + p11ctx->hSession = CK_INVALID_HANDLE; + + return rv == CKR_OK; +} + +#define PKCS11_CIPHER_ALGORITHM(name, mechanismType, block_size, \ + key_len, iv_len, flags) \ + \ + static EVP_CIPHER \ + pkcs11_##name = { \ + 0, \ + block_size, \ + key_len, \ + iv_len, \ + flags, \ + p11_key_init, \ + p11_do_cipher, \ + p11_cleanup, \ + sizeof(struct pkcs11_cipher_ctx), \ + NULL, \ + NULL, \ + NULL, \ + (void *)mechanismType \ + }; \ + \ + const EVP_CIPHER * \ + hc_EVP_pkcs11_##name(void) \ + { \ + if (p11_mech_available_p(mechanismType)) \ + return &pkcs11_##name; \ + else \ + return NULL; \ + } \ + \ + static void \ + pkcs11_hcrypto_##name##_init_once(void *context) \ + { \ + const EVP_CIPHER *cipher; \ + \ + cipher = hc_EVP_pkcs11_ ##name(); \ + if (cipher == NULL) \ + cipher = hc_EVP_hcrypto_ ##name(); \ + \ + *((const EVP_CIPHER **)context) = cipher; \ + } \ + \ + const EVP_CIPHER * \ + hc_EVP_pkcs11_hcrypto_##name(void) \ + { \ + static const EVP_CIPHER *__cipher; \ + static heim_base_once_t __init = HEIM_BASE_ONCE_INIT; \ + \ + heim_base_once_f(&__init, &__cipher, \ + pkcs11_hcrypto_##name##_init_once); \ + \ + return __cipher; \ + } + +#define PKCS11_MD_ALGORITHM(name, mechanismType, hash_size, block_size) \ + \ + static int p11_##name##_init(EVP_MD_CTX *ctx) \ + { \ + return p11_md_hash_init(mechanismType, ctx); \ + } \ + \ + const EVP_MD * \ + hc_EVP_pkcs11_##name(void) \ + { \ + static struct hc_evp_md name = { \ + hash_size, \ + block_size, \ + sizeof(struct pkcs11_md_ctx), \ + p11_##name##_init, \ + p11_md_update, \ + p11_md_final, \ + p11_md_cleanup \ + }; \ + \ + if (p11_mech_available_p(mechanismType)) \ + return &name; \ + else \ + return NULL; \ + } \ + \ + static void \ + pkcs11_hcrypto_##name##_init_once(void *context) \ + { \ + const EVP_MD *md; \ + \ + md = hc_EVP_pkcs11_ ##name(); \ + if (md == NULL) \ + md = hc_EVP_hcrypto_ ##name(); \ + \ + *((const EVP_MD **)context) = md; \ + } \ + \ + const EVP_MD * \ + hc_EVP_pkcs11_hcrypto_##name(void) \ + { \ + static const EVP_MD *__md; \ + static heim_base_once_t __init = HEIM_BASE_ONCE_INIT; \ + \ + heim_base_once_f(&__init, &__md, \ + pkcs11_hcrypto_##name##_init_once); \ + \ + return __md; \ + } + +#define PKCS11_MD_ALGORITHM_UNAVAILABLE(name) \ + \ + const EVP_MD * \ + hc_EVP_pkcs11_##name(void) \ + { \ + return NULL; \ + } \ + \ + const EVP_MD * \ + hc_EVP_pkcs11_hcrypto_##name(void) \ + { \ + return hc_EVP_hcrypto_ ##name(); \ + } + +/** + * The triple DES cipher type (PKCS#11 provider) + * + * @return the DES-EDE3-CBC EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +PKCS11_CIPHER_ALGORITHM(des_ede3_cbc, + CKM_DES3_CBC, + 8, + 24, + 8, + EVP_CIPH_CBC_MODE) + +/** + * The DES cipher type (PKCS#11 provider) + * + * @return the DES-CBC EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +PKCS11_CIPHER_ALGORITHM(des_cbc, + CKM_DES_CBC, + 8, + 8, + 8, + EVP_CIPH_CBC_MODE) + +/** + * The AES-128 cipher type (PKCS#11 provider) + * + * @return the AES-128-CBC EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +PKCS11_CIPHER_ALGORITHM(aes_128_cbc, + CKM_AES_CBC, + 16, + 16, + 16, + EVP_CIPH_CBC_MODE) + +/** + * The AES-192 cipher type (PKCS#11 provider) + * + * @return the AES-192-CBC EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +PKCS11_CIPHER_ALGORITHM(aes_192_cbc, + CKM_AES_CBC, + 16, + 24, + 16, + EVP_CIPH_CBC_MODE) + +/** + * The AES-256 cipher type (PKCS#11 provider) + * + * @return the AES-256-CBC EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +PKCS11_CIPHER_ALGORITHM(aes_256_cbc, + CKM_AES_CBC, + 16, + 32, + 16, + EVP_CIPH_CBC_MODE) + +/** + * The AES-128 CFB8 cipher type (PKCS#11 provider) + * + * @return the AES-128-CFB8 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +PKCS11_CIPHER_ALGORITHM(aes_128_cfb8, + CKM_AES_CFB8, + 16, + 16, + 16, + EVP_CIPH_CFB8_MODE) + +/** + * The AES-192 CFB8 cipher type (PKCS#11 provider) + * + * @return the AES-192-CFB8 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +PKCS11_CIPHER_ALGORITHM(aes_192_cfb8, + CKM_AES_CFB8, + 16, + 24, + 16, + EVP_CIPH_CFB8_MODE) + +/** + * The AES-256 CFB8 cipher type (PKCS#11 provider) + * + * @return the AES-256-CFB8 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +PKCS11_CIPHER_ALGORITHM(aes_256_cfb8, + CKM_AES_CFB8, + 16, + 32, + 16, + EVP_CIPH_CFB8_MODE) + +/** + * The RC2 cipher type - PKCS#11 + * + * @return the RC2 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +PKCS11_CIPHER_ALGORITHM(rc2_cbc, + CKM_RC2_CBC, + 8, + 16, + 8, + EVP_CIPH_CBC_MODE) + +/** + * The RC2-40 cipher type - PKCS#11 + * + * @return the RC2-40 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +PKCS11_CIPHER_ALGORITHM(rc2_40_cbc, + CKM_RC2_CBC, + 8, + 5, + 8, + EVP_CIPH_CBC_MODE) + +/** + * The RC2-64 cipher type - PKCS#11 + * + * @return the RC2-64 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +PKCS11_CIPHER_ALGORITHM(rc2_64_cbc, + CKM_RC2_CBC, + 8, + 8, + 8, + EVP_CIPH_CBC_MODE) + +/** + * The Camellia-128 cipher type - PKCS#11 + * + * @return the Camellia-128 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +PKCS11_CIPHER_ALGORITHM(camellia_128_cbc, + CKM_CAMELLIA_CBC, + 16, + 16, + 16, + EVP_CIPH_CBC_MODE) + +/** + * The Camellia-198 cipher type - PKCS#11 + * + * @return the Camellia-198 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +PKCS11_CIPHER_ALGORITHM(camellia_192_cbc, + CKM_CAMELLIA_CBC, + 16, + 24, + 16, + EVP_CIPH_CBC_MODE) + +/** + * The Camellia-256 cipher type - PKCS#11 + * + * @return the Camellia-256 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +PKCS11_CIPHER_ALGORITHM(camellia_256_cbc, + CKM_CAMELLIA_CBC, + 16, + 32, + 16, + EVP_CIPH_CBC_MODE) + +/** + * The RC4 cipher type (PKCS#11 provider) + * + * @return the RC4 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +PKCS11_CIPHER_ALGORITHM(rc4, + CKM_RC4, + 1, + 16, + 0, + EVP_CIPH_STREAM_CIPHER | EVP_CIPH_VARIABLE_LENGTH) + +/** + * The RC4-40 cipher type (PKCS#11 provider) + * + * @return the RC4 EVP_CIPHER pointer. + * + * @ingroup hcrypto_evp + */ + +PKCS11_CIPHER_ALGORITHM(rc4_40, + CKM_RC4, + 1, + 5, + 0, + EVP_CIPH_STREAM_CIPHER | EVP_CIPH_VARIABLE_LENGTH) + +PKCS11_MD_ALGORITHM(md2, CKM_MD2, 16, 16) +#ifdef CKM_MD4 /* non-standard extension */ +PKCS11_MD_ALGORITHM(md4, CKM_MD4, 16, 16) +#else +PKCS11_MD_ALGORITHM_UNAVAILABLE(md4) +#endif +PKCS11_MD_ALGORITHM(md5, CKM_MD5, 16, 64) +PKCS11_MD_ALGORITHM(sha1, CKM_SHA_1, 20, 64) +PKCS11_MD_ALGORITHM(sha256, CKM_SHA256, 32, 64) +PKCS11_MD_ALGORITHM(sha384, CKM_SHA384, 48, 128) +PKCS11_MD_ALGORITHM(sha512, CKM_SHA512, 64, 128) diff --git a/lib/hcrypto/evp-pkcs11.h b/lib/hcrypto/evp-pkcs11.h new file mode 100644 index 000000000..6d8a21f52 --- /dev/null +++ b/lib/hcrypto/evp-pkcs11.h @@ -0,0 +1,157 @@ +/* + * 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_PKCS11_H +#define HEIM_EVP_PKCS11_H 1 + +/* symbol renaming */ + +#define EVP_pkcs11_md2() hc_EVP_pkcs11_md2() +#define EVP_pkcs11_md4() hc_EVP_pkcs11_md4() +#define EVP_pkcs11_md5() hc_EVP_pkcs11_md5() +#define EVP_pkcs11_sha1() hc_EVP_pkcs11_sha1() +#define EVP_pkcs11_sha256() hc_EVP_pkcs11_sha256() +#define EVP_pkcs11_sha384() hc_EVP_pkcs11_sha384() +#define EVP_pkcs11_sha512() hc_EVP_pkcs11_sha512() +#define EVP_pkcs11_des_cbc() hc_EVP_pkcs11_des_cbc() +#define EVP_pkcs11_des_ede3_cbc() hc_EVP_pkcs11_des_ede3_cbc() +#define EVP_pkcs11_aes_128_cbc() hc_EVP_pkcs11_aes_128_cbc() +#define EVP_pkcs11_aes_192_cbc() hc_EVP_pkcs11_aes_192_cbc() +#define EVP_pkcs11_aes_256_cbc() hc_EVP_pkcs11_aes_256_cbc() +#define EVP_pkcs11_aes_128_cfb8() hc_EVP_pkcs11_aes_128_cfb8() +#define EVP_pkcs11_aes_192_cfb8() hc_EVP_pkcs11_aes_192_cfb8() +#define EVP_pkcs11_aes_256_cfb8() hc_EVP_pkcs11_aes_256_cfb8() +#define EVP_pkcs11_rc4() hc_EVP_pkcs11_rc4() +#define EVP_pkcs11_rc4_40() hc_EVP_pkcs11_rc4_40() +#define EVP_pkcs11_rc2_40_cbc() hc_EVP_pkcs11_rc2_40_cbc() +#define EVP_pkcs11_rc2_64_cbc() hc_EVP_pkcs11_rc2_64_cbc() +#define EVP_pkcs11_rc2_cbc() hc_EVP_pkcs11_rc2_cbc() +#define EVP_pkcs11_camellia_128_cbc() hc_EVP_pkcs11_camellia_128_cbc() +#define EVP_pkcs11_camellia_192_cbc() hc_EVP_pkcs11_camellia_192_cbc() +#define EVP_pkcs11_camellia_256_cbc() hc_EVP_pkcs11_camellia_256_cbc() + +#define EVP_pkcs11_hcrypto_md2() hc_EVP_pkcs11_hcrypto_md2() +#define EVP_pkcs11_hcrypto_md4() hc_EVP_pkcs11_hcrypto_md4() +#define EVP_pkcs11_hcrypto_md5() hc_EVP_pkcs11_hcrypto_md5() +#define EVP_pkcs11_hcrypto_sha1() hc_EVP_pkcs11_hcrypto_sha1() +#define EVP_pkcs11_hcrypto_sha256() hc_EVP_pkcs11_hcrypto_sha256() +#define EVP_pkcs11_hcrypto_sha384() hc_EVP_pkcs11_hcrypto_sha384() +#define EVP_pkcs11_hcrypto_sha512() hc_EVP_pkcs11_hcrypto_sha512() +#define EVP_pkcs11_hcrypto_des_cbc() hc_EVP_pkcs11_hcrypto_des_cbc() +#define EVP_pkcs11_hcrypto_des_ede3_cbc() hc_EVP_pkcs11_hcrypto_des_ede3_cbc() +#define EVP_pkcs11_hcrypto_aes_128_cbc() hc_EVP_pkcs11_hcrypto_aes_128_cbc() +#define EVP_pkcs11_hcrypto_aes_192_cbc() hc_EVP_pkcs11_hcrypto_aes_192_cbc() +#define EVP_pkcs11_hcrypto_aes_256_cbc() hc_EVP_pkcs11_hcrypto_aes_256_cbc() +#define EVP_pkcs11_hcrypto_aes_128_cfb8() hc_EVP_pkcs11_hcrypto_aes_128_cfb8() +#define EVP_pkcs11_hcrypto_aes_192_cfb8() hc_EVP_pkcs11_hcrypto_aes_192_cfb8() +#define EVP_pkcs11_hcrypto_aes_256_cfb8() hc_EVP_pkcs11_hcrypto_aes_256_cfb8() +#define EVP_pkcs11_hcrypto_rc4() hc_EVP_pkcs11_hcrypto_rc4() +#define EVP_pkcs11_hcrypto_rc4_40() hc_EVP_pkcs11_hcrypto_rc4_40() +#define EVP_pkcs11_hcrypto_rc2_40_cbc() hc_EVP_pkcs11_hcrypto_rc2_40_cbc() +#define EVP_pkcs11_hcrypto_rc2_64_cbc() hc_EVP_pkcs11_hcrypto_rc2_64_cbc() +#define EVP_pkcs11_hcrypto_rc2_cbc() hc_EVP_pkcs11_hcrypto_rc2_cbc() +#define EVP_pkcs11_hcrypto_camellia_128_cbc() hc_EVP_pkcs11_hcrypto_camellia_128_cbc() +#define EVP_pkcs11_hcrypto_camellia_192_cbc() hc_EVP_pkcs11_hcrypto_camellia_192_cbc() +#define EVP_pkcs11_hcrypto_camellia_256_cbc() hc_EVP_pkcs11_hcrypto_camellia_256_cbc() + +HC_CPP_BEGIN + +/* + * Strict PKCS#11 implementations (these will return NULL if the underlying + * PKCS#11 implementation does not implement the cipher or hash). + */ +const EVP_MD * hc_EVP_pkcs11_md2(void); +const EVP_MD * hc_EVP_pkcs11_md4(void); +const EVP_MD * hc_EVP_pkcs11_md5(void); +const EVP_MD * hc_EVP_pkcs11_sha1(void); +const EVP_MD * hc_EVP_pkcs11_sha256(void); +const EVP_MD * hc_EVP_pkcs11_sha384(void); +const EVP_MD * hc_EVP_pkcs11_sha512(void); + +const EVP_CIPHER * hc_EVP_pkcs11_rc2_cbc(void); +const EVP_CIPHER * hc_EVP_pkcs11_rc2_40_cbc(void); +const EVP_CIPHER * hc_EVP_pkcs11_rc2_64_cbc(void); + +const EVP_CIPHER * hc_EVP_pkcs11_rc4(void); +const EVP_CIPHER * hc_EVP_pkcs11_rc4_40(void); + +const EVP_CIPHER * hc_EVP_pkcs11_des_cbc(void); +const EVP_CIPHER * hc_EVP_pkcs11_des_ede3_cbc(void); + +const EVP_CIPHER * hc_EVP_pkcs11_aes_128_cbc(void); +const EVP_CIPHER * hc_EVP_pkcs11_aes_192_cbc(void); +const EVP_CIPHER * hc_EVP_pkcs11_aes_256_cbc(void); + +const EVP_CIPHER * hc_EVP_pkcs11_aes_128_cfb8(void); +const EVP_CIPHER * hc_EVP_pkcs11_aes_192_cfb8(void); +const EVP_CIPHER * hc_EVP_pkcs11_aes_256_cfb8(void); + +const EVP_CIPHER * hc_EVP_pkcs11_camellia_128_cbc(void); +const EVP_CIPHER * hc_EVP_pkcs11_camellia_192_cbc(void); +const EVP_CIPHER * hc_EVP_pkcs11_camellia_256_cbc(void); + +/* + * PKCS#11 implementations with fallback to hcrypto. + */ +const EVP_MD * hc_EVP_pkcs11_hcrypto_md2(void); +const EVP_MD * hc_EVP_pkcs11_hcrypto_md4(void); +const EVP_MD * hc_EVP_pkcs11_hcrypto_md5(void); +const EVP_MD * hc_EVP_pkcs11_hcrypto_sha1(void); +const EVP_MD * hc_EVP_pkcs11_hcrypto_sha256(void); +const EVP_MD * hc_EVP_pkcs11_hcrypto_sha384(void); +const EVP_MD * hc_EVP_pkcs11_hcrypto_sha512(void); + +const EVP_CIPHER * hc_EVP_pkcs11_hcrypto_rc2_cbc(void); +const EVP_CIPHER * hc_EVP_pkcs11_hcrypto_rc2_40_cbc(void); +const EVP_CIPHER * hc_EVP_pkcs11_hcrypto_rc2_64_cbc(void); + +const EVP_CIPHER * hc_EVP_pkcs11_hcrypto_rc4(void); +const EVP_CIPHER * hc_EVP_pkcs11_hcrypto_rc4_40(void); + +const EVP_CIPHER * hc_EVP_pkcs11_hcrypto_des_cbc(void); +const EVP_CIPHER * hc_EVP_pkcs11_hcrypto_des_ede3_cbc(void); + +const EVP_CIPHER * hc_EVP_pkcs11_hcrypto_aes_128_cbc(void); +const EVP_CIPHER * hc_EVP_pkcs11_hcrypto_aes_192_cbc(void); +const EVP_CIPHER * hc_EVP_pkcs11_hcrypto_aes_256_cbc(void); + +const EVP_CIPHER * hc_EVP_pkcs11_hcrypto_aes_128_cfb8(void); +const EVP_CIPHER * hc_EVP_pkcs11_hcrypto_aes_192_cfb8(void); +const EVP_CIPHER * hc_EVP_pkcs11_hcrypto_aes_256_cfb8(void); + +const EVP_CIPHER * hc_EVP_pkcs11_hcrypto_camellia_128_cbc(void); +const EVP_CIPHER * hc_EVP_pkcs11_hcrypto_camellia_192_cbc(void); +const EVP_CIPHER * hc_EVP_pkcs11_hcrypto_camellia_256_cbc(void); + +HC_CPP_END + +#endif /* HEIM_EVP_PKCS11_H */ diff --git a/lib/hcrypto/evp.c b/lib/hcrypto/evp.c index cfabf377e..cb8ba7602 100644 --- a/lib/hcrypto/evp.c +++ b/lib/hcrypto/evp.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -55,6 +56,8 @@ #ifndef HCRYPTO_DEF_PROVIDER # ifdef __APPLE__ # define HCRYPTO_DEF_PROVIDER cc +# elif __sun +# define HCRYPTO_DEF_PROVIDER pkcs11_hcrypto # else # define HCRYPTO_DEF_PROVIDER hcrypto # endif @@ -1126,7 +1129,7 @@ EVP_des_cbc(void) } /** - * The tripple DES cipher type + * The triple DES cipher type * * @return the DES-EDE3-CBC EVP_CIPHER pointer. * diff --git a/lib/hcrypto/libhcrypto-exports.def b/lib/hcrypto/libhcrypto-exports.def index 5a029cfd4..0b3c9a774 100644 --- a/lib/hcrypto/libhcrypto-exports.def +++ b/lib/hcrypto/libhcrypto-exports.def @@ -177,6 +177,23 @@ EXPORTS ;! hc_EVP_cc_aes_192_cfb8 ;! hc_EVP_cc_aes_256_cfb8 + hc_EVP_pkcs11_md2 + hc_EVP_pkcs11_md4 + hc_EVP_pkcs11_md5 + hc_EVP_pkcs11_sha1 + hc_EVP_pkcs11_sha256 + hc_EVP_pkcs11_des_ede3_cbc + hc_EVP_pkcs11_aes_128_cbc + hc_EVP_pkcs11_aes_192_cbc + hc_EVP_pkcs11_aes_256_cbc + hc_EVP_pkcs11_aes_128_cfb8 + hc_EVP_pkcs11_aes_192_cfb8 + hc_EVP_pkcs11_aes_256_cfb8 + hc_EVP_pkcs11_rc2_40_cbc + hc_EVP_pkcs11_rc2_cbc + hc_EVP_pkcs11_rc4 + hc_EVP_pkcs11_rc4_40 + hc_EVP_w32crypto_md2 ;! hc_EVP_w32crypto_md4 ;! hc_EVP_w32crypto_md5 ;! diff --git a/lib/hcrypto/test_bulk.c b/lib/hcrypto/test_bulk.c index 089a1fdcb..14f468867 100644 --- a/lib/hcrypto/test_bulk.c +++ b/lib/hcrypto/test_bulk.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -87,6 +88,8 @@ static unsigned char *d; #define PROVIDER_USAGE "hcrypto|cc" #elif defined(WIN32) #define PROVIDER_USAGE "hcrypto|w32crypto" +#elif __sun || defined(PKCS11_MODULE_PATH) +#define PROVIDER_USAGE "hcrypto|pkcs11" #else #define PROVIDER_USAGE "hcrypto" #endif @@ -122,6 +125,11 @@ test_bulk_cipher(const char *cname, const EVP_CIPHER *c) int i; int64_t M = 0; + if (c == NULL) { + printf("%s not supported\n", cname); + return 0; + } + for (i = 0; i < loops; i++) { EVP_CIPHER_CTX ectx; EVP_CIPHER_CTX dctx; @@ -171,6 +179,11 @@ test_bulk_digest(const char *cname, const EVP_MD *md) unsigned int tmp = sizeof(digest); int64_t M = 0; + if (md == NULL) { + printf("%s not supported\n", cname); + return 0; + } + for (i = 0; i < loops; i++) { STATS_START(M); EVP_Digest(d, len, digest, &tmp, md, NULL); @@ -237,6 +250,20 @@ test_bulk_provider_w32crypto(void) } #endif /* WIN32 */ +#if __sun || defined(PKCS11_MODULE_PATH) +static void +test_bulk_provider_pkcs11(void) +{ + test_bulk_cipher("pkcs11_aes_256_cbc", EVP_pkcs11_aes_256_cbc()); + test_bulk_cipher("pkcs11_rc4", EVP_pkcs11_rc4()); + test_bulk_digest("pkcs11_md5", EVP_pkcs11_md5()); + test_bulk_digest("pkcs11_sha1", EVP_pkcs11_sha1()); + test_bulk_digest("pkcs11_sha256", EVP_pkcs11_sha256()); + test_bulk_digest("pkcs11_sha384", EVP_pkcs11_sha384()); + test_bulk_digest("pkcs11_sha512", EVP_pkcs11_sha512()); +} +#endif /* __sun || PKCS11_MODULE_PATH */ + int main(int argc, char **argv) { @@ -275,6 +302,10 @@ main(int argc, char **argv) #ifdef WIN32 else if (strcmp(provider, "w32crypto") == 0) test_bulk_provider_w32crypto(); +#endif +#if __sun || defined(PKCS11_MODULE_PATH) + else if (strcmp(provider, "pkcs11") == 0) + test_bulk_provider_pkcs11(); #endif else usage(1); diff --git a/lib/hcrypto/test_cipher.c b/lib/hcrypto/test_cipher.c index 6eb9f3fe5..e73570ed4 100644 --- a/lib/hcrypto/test_cipher.c +++ b/lib/hcrypto/test_cipher.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -398,5 +399,21 @@ main(int argc, char **argv) ret += test_cipher(i, EVP_w32crypto_rc4(), &rc4_tests[i]); #endif /* WIN32 */ + /* PKCS#11 */ +#if __sun || defined(PKCS11_MODULE_PATH) + for (i = 0; i < sizeof(aes_tests)/sizeof(aes_tests[0]); i++) + ret += test_cipher(i, EVP_pkcs11_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_pkcs11_aes_128_cfb8(), &aes_cfb_tests[i]); + for (i = 0; i < sizeof(rc2_tests)/sizeof(rc2_tests[0]); i++) + ret += test_cipher(i, EVP_pkcs11_rc2_cbc(), &rc2_tests[i]); + for (i = 0; i < sizeof(rc2_40_tests)/sizeof(rc2_40_tests[0]); i++) + ret += test_cipher(i, EVP_pkcs11_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_pkcs11_des_ede3_cbc(), &des_ede3_tests[i]); + for (i = 0; i < sizeof(rc4_tests)/sizeof(rc4_tests[0]); i++) + ret += test_cipher(i, EVP_pkcs11_rc4(), &rc4_tests[i]); +#endif /* PKCS11_MODULE_PATH */ + return ret; } diff --git a/lib/hcrypto/version-script.map b/lib/hcrypto/version-script.map index d83361b33..177e27981 100644 --- a/lib/hcrypto/version-script.map +++ b/lib/hcrypto/version-script.map @@ -201,6 +201,24 @@ HEIMDAL_CRYPTO_1.0 { hc_EVP_hcrypto_rc4; hc_EVP_hcrypto_rc4_40; + hc_EVP_pkcs11_md2; + hc_EVP_pkcs11_md4; + hc_EVP_pkcs11_md5; + hc_EVP_pkcs11_sha1; + hc_EVP_pkcs11_sha256; + hc_EVP_pkcs11_des_ede3_cbc; + hc_EVP_pkcs11_aes_128_cbc; + hc_EVP_pkcs11_aes_192_cbc; + hc_EVP_pkcs11_aes_256_cbc; + hc_EVP_pkcs11_aes_128_cfb8; + hc_EVP_pkcs11_aes_192_cfb8; + hc_EVP_pkcs11_aes_256_cfb8; + hc_EVP_pkcs11_rc2_40_cbc; + hc_EVP_pkcs11_rc2_64_cbc; + hc_EVP_pkcs11_rc2_cbc; + hc_EVP_pkcs11_rc4; + hc_EVP_pkcs11_rc4_40; + hc_EVP_hcrypto_aes_128_cts; hc_EVP_hcrypto_aes_192_cts; hc_EVP_hcrypto_aes_256_cts;