# HG changeset patch # User Mike Sullivan # Date 1386643322 28800 # Node ID 314c74b881bce45f48d6d41a32d286eea89e13c3 # Parent 2d3ec080d6a3fc5ac23f88d86755d141c7bad368 backout 15801760 - not yet time diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/README --- a/components/openssl/README Mon Dec 09 15:11:31 2013 -0800 +++ b/components/openssl/README Mon Dec 09 18:42:02 2013 -0800 @@ -25,10 +25,10 @@ Build Layout --- -OpenSSL build is run four times. Once for regular dynamic 1.0.1 non-fips, once -for static 1.0.1 bits to link with standalone wanboot binary, once for 1.0.1 -fips-140, and once for 1.0.1 FIPS-140 canister (in the openssl-fips component) -needed to build 1.0.1 FIPS-140 certified libraries. All builds apart from +OpenSSL build is run four times. Once for regular dynamic 1.0.0 non-fips, once +for static 1.0.0 bits to link with standalone wanboot binary, once for 0.9.8 +fips-140, and once for 0.9.8 FIPS-140 canister (in the openssl-fips component) +needed to build 0.9.8 FIPS-140 certified libraries. All builds apart from static libraries for wanboot are done for 32 and 64 bits. So, in total, OpenSSL is built seven times. OpenSSL for wanboot is only build on sparc. @@ -135,16 +135,23 @@ The fips Build --- -FIPS-140 certified libraries for Solaris private use. Since OpenSSL 1.0.1 is -now FIPS-140 certified, we can ship only 1.0.1 with S12 and S11.2 and make -it a public interface. (To be done next) +FIPS-140 certified libraries for Solaris private use. We wait for OpenSSL 1.0.0 +to be FIPS-140 certified in which time we can ship only 1.0.0 with S11 and make +it a public interface. Patches --- -All the patches from 1.0.1 (non-fips) are used in 1.0.1(fips) as well aside from -14-manpage_openssl.patch which is not needed since we do not deliver 1.0.1(fips) man -pages. Once we make fips version public, we should deliver man page. +All the patches from 1.0.0 are used in 0.9.8 as well aside from +14-manpage_openssl.patch which is not needed since we do not deliver 0.9.8 man +pages. Additional patches: + +01-7009105.patch +Fixing a bug introduces in 0.9.8q and fixed in 0.9.8r. + +sparc-01-ccwrap.patch +Workaround so that fingerprinting the canister during runtime and comparing it +with the saved fingerprint works correctly. The wanboot Build ---- diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/Makefile Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,191 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +# +export PARFAIT_BUILD=no + +include ../../../make-rules/shared-macros.mk + +PATH=$(SPRO_VROOT)/bin:/usr/bin:/usr/gnu/bin:/usr/perl5/bin + +COMPONENT_NAME = openssl-fips-140 +# Note that this is the OpenSSL version that is used to build FIPS-140 certified +# libraries. However, we use the FIPS canister version for the IPS package. +COMPONENT_VERSION = 0.9.8y +IPS_COMPONENT_VERSION = 1.2 +COMPONENT_PROJECT_URL= http://www.openssl.org/ +COMPONENT_SRC_NAME = openssl +COMPONENT_SRC = $(COMPONENT_SRC_NAME)-$(COMPONENT_VERSION) +COMPONENT_ARCHIVE = $(COMPONENT_SRC).tar.gz +COMPONENT_ARCHIVE_HASH= \ + sha256:bbecf13495e612936e3a9860c29c0701413564b7a964bf771a3575eaa867cee3 +COMPONENT_ARCHIVE_URL = $(COMPONENT_PROJECT_URL)source/$(COMPONENT_ARCHIVE) +COMPONENT_BUGDB= utility/openssl + +# Apply the patch on SPARC only. Must put this before including prep.mk as +# mentioned in there. +PATCH_sparc = patches/sparc-01-ccwrap.patch +EXTRA_PATCHES = $(PATCH_$(MACH)) +# Note that the SPARC patch above does not fit this pattern. That is intentional +# and a reason why we can add it to the EXTRA_PATCHES variable so that we use it +# only on SPARC. +PATCH_PATTERN = [0-9][0-9]*.patch + +include $(WS_TOP)/make-rules/prep.mk +include $(WS_TOP)/make-rules/configure.mk +include $(WS_TOP)/make-rules/ips.mk +include $(WS_TOP)/make-rules/lint-libraries.mk + +# OpenSSL does not use autoconf but its own configure system. +CONFIGURE_SCRIPT = $(SOURCE_DIR)/Configure + +# Used in the configure options below. +PKCS11_LIB32 = /usr/lib/libpkcs11.so.1 +PKCS11_LIB64 = /usr/lib/64/libpkcs11.so.1 +ENGINESDIR_32 = /lib/openssl/engines +ENGINESDIR_64 = /lib/openssl/engines/64 + +# Built openssl/openssl-fips component is used when building FIPS-140 libraries. +# What we do here follows the OpenSSL FIPS-140 User Guide instructions. +FIPS_BUILD_DIR_32 = $(shell echo $(BUILD_DIR_32) | \ + sed -e 's/openssl-0.9.8-fips-140/openssl-fips/g' ) +FIPS_BUILD_DIR_64 = $(shell echo $(BUILD_DIR_64) | \ + sed -e 's/openssl-0.9.8-fips-140/openssl-fips/g' ) + +CONFIGURE_OPTIONS = -DSOLARIS_OPENSSL -DNO_WINDOWS_BRAINDEATH +CONFIGURE_OPTIONS += --openssldir=/etc/openssl +CONFIGURE_OPTIONS += --prefix=/usr +# We use OpenSSL install code for installing only manual pages and we do that +# for 32-bit version only. +CONFIGURE_OPTIONS += --install_prefix=$(PROTO_DIR) +CONFIGURE_OPTIONS += no-ec +CONFIGURE_OPTIONS += no-ecdh +CONFIGURE_OPTIONS += no-ecdsa +CONFIGURE_OPTIONS += no-rc3 +CONFIGURE_OPTIONS += no-rc5 +CONFIGURE_OPTIONS += no-mdc2 +CONFIGURE_OPTIONS += no-idea +CONFIGURE_OPTIONS += no-hw_4758_cca +CONFIGURE_OPTIONS += no-hw_aep +CONFIGURE_OPTIONS += no-hw_atalla +CONFIGURE_OPTIONS += no-hw_chil +CONFIGURE_OPTIONS += no-hw_gmp +CONFIGURE_OPTIONS += no-hw_ncipher +CONFIGURE_OPTIONS += no-hw_nuron +CONFIGURE_OPTIONS += no-hw_padlock +CONFIGURE_OPTIONS += no-hw_sureware +CONFIGURE_OPTIONS += no-hw_ubsec +CONFIGURE_OPTIONS += no-hw_cswift +CONFIGURE_OPTIONS += threads +CONFIGURE_OPTIONS += shared +CONFIGURE_OPTIONS += fips --with-fipslibdir="$(FIPS_BUILD_DIR_$(BITS))/fips" + +# We define our own compiler and linker option sets for Solaris. See Configure +# for more information. +CONFIGURE_OPTIONS32_i386 = solaris-x86-cc-sunw +CONFIGURE_OPTIONS32_sparc = solaris-sparcv8-cc-sunw +CONFIGURE_OPTIONS64_i386 = solaris64-x86_64-cc-sunw +CONFIGURE_OPTIONS64_sparc = solaris64-sparcv9-cc-sunw + +# Some additional options needed for our engines. +CONFIGURE_OPTIONS += --pk11-libname=$(PKCS11_LIB$(BITS)) +CONFIGURE_OPTIONS += --enginesdir=$(ENGINESDIR_$(BITS)) +CONFIGURE_OPTIONS += $(CONFIGURE_OPTIONS$(BITS)_$(MACH)) + +# OpenSSL has its own configure system which must be run from the fully +# populated source code directory. However, the Userland configuration phase is +# run from the build directory. The easiest way to workaround it is to copy all +# the source files there. +COMPONENT_PRE_CONFIGURE_ACTION = \ + ( $(CLONEY) $(SOURCE_DIR) $(BUILD_DIR)/$(MACH$(BITS)); ) + +# We deliver only one opensslconf.h file which must be suitable for both 32 and +# 64 bits. Depending on the configuration option, OpenSSL's Configure script +# creates opensslconf.h for either 32 or 64 bits. A patch makes the resulting +# header file usable on both architectures. The patch was generated against the +# opensslconf.h version from the 32 bit build. +COMPONENT_POST_CONFIGURE_ACTION = \ + ( [ $(BITS) -eq 32 ] && $(GPATCH) -p1 $(@D)/crypto/opensslconf.h \ + patches-post-config/opensslconf.patch; cd $(@D); $(MAKE) depend; ) + +ASLR_MODE = $(ASLR_NOT_APPLICABLE) + +# We must make sure that openssl-fips component is built before this 0.9.8 +# component since in order to build FIPS-140 certified libraries, the canister +# is needed. Note that we must unset BITS that would override the same variable +# used in openssl-fips' Makefile, and we would end up up with both canisters +# built in 64 (or 32) bits. +$(COMPONENT_DIR)/../openssl-fips/build/$(MACH32)/.installed \ +$(COMPONENT_DIR)/../openssl-fips/build/$(MACH64)/.installed: + ( unset BITS; \ + $(MAKE) -C $(COMPONENT_DIR)/../openssl-fips install; ) + +# download, clean, and clobber should all propogate to the fips bits +download clobber clean:: + (cd ../openssl-fips ; $(GMAKE) $@) + +# We do not ship our engines as patches since it would be more difficult to +# update the files which have been under continuous development. We rather copy +# the files to the right directories and let OpenSSL makefiles build it. +COMPONENT_PRE_BUILD_ACTION = \ + ( $(LN) -fs $(COMPONENT_DIR)/engines/pkcs11/* $(@D)/crypto/engine; ) + +# OpenSSL does not install into /$(MACH64) for 64-bit install so no such +# directory is created and Userland install code would fail when installing lint +# libraries. +COMPONENT_PRE_INSTALL_ACTION = ( $(MKDIR) $(PROTO_DIR)/usr/lib/$(MACH64); ) + +# For ccwrap on SPARC. This is to workaround a problem with the cc compiler on +# SPARC. We must modify PATH so that the wrapper can be found when run from +# fips/fipsld. +COMPONENT_BUILD_ENV += PATH=$(COMPONENT_DIR):$(PATH) +COMPONENT_INSTALL_ENV += PATH=$(COMPONENT_DIR):$(PATH) + +$(SOURCE_DIR)/.prep: $(COMPONENT_DIR)/../openssl-fips/build/$(MACH32)/.installed \ + $(COMPONENT_DIR)/../openssl-fips/build/$(MACH64)/.installed + +# We need ccwrap for building the libraries. +$(BUILD_32_and_64): ccwrap +build: $(BUILD_32_and_64) + +CLOBBER_PATHS += ccwrap + +# We follow what we do for install in openssl/openssl-1.0.0 component. Please +# see the comment in Makefile in there for more information. +install: $(INSTALL_32_and_64) + +# We need to modify the default lint flags to include patched opensslconf.h from +# the build directory. If we do not do that, lint will complain about md2.h +# which is not enabled by default but it is in our opensslconf.h. +LFLAGS_32 := -I$(BUILD_DIR_32)/include $(LINT_FLAGS) +LFLAGS_64 := -I$(BUILD_DIR_64)/include $(LINT_FLAGS) + +# Set modified lint flags for our lint library targets. +$(BUILD_DIR_32)/llib-lcrypto.ln: LINT_FLAGS=$(LFLAGS_32) +$(BUILD_DIR_32)/llib-lssl.ln: LINT_FLAGS=$(LFLAGS_32) +$(BUILD_DIR_64)/llib-lcrypto.ln: LINT_FLAGS=$(LFLAGS_64) +$(BUILD_DIR_64)/llib-lssl.ln: LINT_FLAGS=$(LFLAGS_64) + +test: $(NO_TESTS) + +BUILD_PKG_DEPENDENCIES = $(BUILD_TOOLS) + +include $(WS_TOP)/make-rules/depend.mk diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/ccwrap.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/ccwrap.sh Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,42 @@ +#!/bin/sh +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. +# + +# Very simple cc wrapper whose only purpose is to ensure that cc behaves as +# desired when linking the fipscanister.o object. Currently that means removing +# "-g" and adding "-W2,-Rfully_unroll" from/to the compiler options. +# +# This wrapper is called from fipsld. See fips/fipsld and +# patches/sparc-01-ccwrap.patch for more information. + +CC_CMD="" +while [ $# -ne 0 ]; do + if [ "$1" != "-g" ]; then + CC_CMD="$CC_CMD '$1'" + fi + shift; +done + +eval $CC_CMD -W2,-Rfully_unroll diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/engines/pkcs11/hw_pk11.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/engines/pkcs11/hw_pk11.c Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,3774 @@ +/* + * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. + * + */ + +/* crypto/engine/hw_pk11.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_RSA +#include +#endif +#ifndef OPENSSL_NO_DSA +#include +#endif +#ifndef OPENSSL_NO_DH +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 + +/* label for debug messages printed on stderr */ +#define PK11_DBG "PKCS#11 ENGINE DEBUG" +/* prints a lot of debug messages on stderr about slot selection process */ +#undef DEBUG_SLOT_SELECTION +/* + * Solaris specific code. See comment at check_hw_mechanisms() for more + * information. + */ +#if defined(__SVR4) && defined(__sun) +#define SOLARIS_HW_SLOT_SELECTION +#endif + +#ifdef DEBUG_SLOT_SELECTION +#define DEBUG_SLOT_SEL(...) fprintf(stderr, __VA_ARGS__) +#else +#define DEBUG_SLOT_SEL(...) +#endif + +/* + * AES counter mode is not supported in the OpenSSL EVP API yet and neither + * there are official OIDs for mechanisms based on this mode. With our changes, + * an application can define its own EVP calls for AES counter mode and then + * it can make use of hardware acceleration through this engine. However, it's + * better if we keep AES CTR support code under ifdef's. + */ +#define SOLARIS_AES_CTR + +#include +#include +#include "hw_pk11.h" +#include "hw_pk11_uri.h" + +#define PK11_ENGINE_LIB_NAME "PKCS#11 engine" +#include "hw_pk11_err.c" + +#ifdef SOLARIS_AES_CTR +/* + * NIDs for AES counter mode that will be defined during the engine + * initialization. + */ +int NID_aes_128_ctr = NID_undef; +int NID_aes_192_ctr = NID_undef; +int NID_aes_256_ctr = NID_undef; +#endif /* SOLARIS_AES_CTR */ + +/* + * We use this lock to prevent multiple C_Login()s, guard getpassphrase(), + * uri_struct manipulation, and static token info. All of that is used by the + * RSA keys by reference feature. + */ +pthread_mutex_t *uri_lock; + +#ifdef SOLARIS_HW_SLOT_SELECTION +/* + * Tables for symmetric ciphers and digest mechs found in the pkcs11_kernel + * library. See comment at check_hw_mechanisms() for more information. + */ +int *hw_cnids; +int *hw_dnids; +#endif /* SOLARIS_HW_SLOT_SELECTION */ + +/* PKCS#11 session caches and their locks for all operation types */ +static PK11_CACHE session_cache[OP_MAX]; + +/* + * We cache the flags so that we do not have to run C_GetTokenInfo() again when + * logging into the token. + */ +CK_FLAGS pubkey_token_flags; + +/* + * As stated in v2.20, 11.7 Object Management Function, in section for + * C_FindObjectsInit(), at most one search operation may be active at a given + * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be + * grouped together to form one atomic search operation. This is already + * ensured by the property of unique PKCS#11 session handle used for each + * PK11_SESSION object. + * + * This is however not the biggest concern - maintaining consistency of the + * underlying object store is more important. The same section of the spec also + * says that one thread can be in the middle of a search operation while another + * thread destroys the object matching the search template which would result in + * invalid handle returned from the search operation. + * + * Hence, the following locks are used for both protection of the object stores. + * They are also used for active list protection. + */ +pthread_mutex_t *find_lock[OP_MAX] = { NULL }; + +/* + * lists of asymmetric key handles which are active (referenced by at least one + * PK11_SESSION structure, either held by a thread or present in free_session + * list) for given algorithm type + */ +PK11_active *active_list[OP_MAX] = { NULL }; + +/* + * Create all secret key objects in a global session so that they are available + * to use for other sessions. These other sessions may be opened or closed + * without losing the secret key objects. + */ +static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE; + +/* Index for the supported ciphers */ +enum pk11_cipher_id + { + PK11_DES_CBC, + PK11_DES3_CBC, + PK11_DES_ECB, + PK11_DES3_ECB, + PK11_RC4, + PK11_AES_128_CBC, + PK11_AES_192_CBC, + PK11_AES_256_CBC, + PK11_AES_128_ECB, + PK11_AES_192_ECB, + PK11_AES_256_ECB, + PK11_BLOWFISH_CBC, +#ifdef SOLARIS_AES_CTR + PK11_AES_128_CTR, + PK11_AES_192_CTR, + PK11_AES_256_CTR, +#endif /* SOLARIS_AES_CTR */ + PK11_CIPHER_MAX + }; + +/* Index for the supported digests */ +enum pk11_digest_id + { + PK11_MD5, + PK11_SHA1, + PK11_SHA224, + PK11_SHA256, + PK11_SHA384, + PK11_SHA512, + PK11_DIGEST_MAX + }; + +typedef struct PK11_CIPHER_st + { + enum pk11_cipher_id id; + int nid; + int iv_len; + int min_key_len; + int max_key_len; + CK_KEY_TYPE key_type; + CK_MECHANISM_TYPE mech_type; + } PK11_CIPHER; + +typedef struct PK11_DIGEST_st + { + enum pk11_digest_id id; + int nid; + CK_MECHANISM_TYPE mech_type; + } PK11_DIGEST; + +/* ENGINE level stuff */ +static int pk11_init(ENGINE *e); +static int pk11_library_init(ENGINE *e); +static int pk11_finish(ENGINE *e); +static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); +static int pk11_destroy(ENGINE *e); + +/* RAND stuff */ +static void pk11_rand_seed(const void *buf, int num); +static void pk11_rand_add(const void *buf, int num, double add_entropy); +static void pk11_rand_cleanup(void); +static int pk11_rand_bytes(unsigned char *buf, int num); +static int pk11_rand_status(void); + +/* These functions are also used in other files */ +PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); +void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); + +/* active list manipulation functions used in this file */ +extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type); +extern void pk11_free_active_list(PK11_OPTYPE type); + +#ifndef OPENSSL_NO_RSA +int pk11_destroy_rsa_key_objects(PK11_SESSION *session); +int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +#endif +#ifndef OPENSSL_NO_DSA +int pk11_destroy_dsa_key_objects(PK11_SESSION *session); +int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +#endif +#ifndef OPENSSL_NO_DH +int pk11_destroy_dh_key_objects(PK11_SESSION *session); +int pk11_destroy_dh_object(PK11_SESSION *session, CK_BBOOL uselock); +#endif + +/* Local helper functions */ +static int pk11_free_all_sessions(void); +static int pk11_free_session_list(PK11_OPTYPE optype); +static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype); +static int pk11_destroy_cipher_key_objects(PK11_SESSION *session); +static int pk11_destroy_object(CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE oh, + CK_BBOOL persistent); +static const char *get_PK11_LIBNAME(void); +static void free_PK11_LIBNAME(void); +static long set_PK11_LIBNAME(const char *name); + +/* Symmetric cipher and digest support functions */ +static int cipher_nid_to_pk11(int nid); +#ifdef SOLARIS_AES_CTR +static int pk11_add_NID(char *sn, char *ln); +static int pk11_add_aes_ctr_NIDs(void); +#endif /* SOLARIS_AES_CTR */ +static int pk11_usable_ciphers(const int **nids); +static int pk11_usable_digests(const int **nids); +static int pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +static int pk11_cipher_final(PK11_SESSION *sp); +static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl); +static int pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx); +static int pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid); +static int pk11_engine_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid); +static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp); +static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key, + int key_len); +static int md_nid_to_pk11(int nid); +static int pk11_digest_init(EVP_MD_CTX *ctx); +static int pk11_digest_update(EVP_MD_CTX *ctx, const void *data, + size_t count); +static int pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md); +static int pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from); +static int pk11_digest_cleanup(EVP_MD_CTX *ctx); + +static int pk11_choose_slots(int *any_slot_found); +static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_cipher, + int *local_cipher_nids); +static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_digest, + int *local_digest_nids); +static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR, int slot_id, + int *current_slot_n_cipher, int *local_cipher_nids, + PK11_CIPHER *cipher); +static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id, + int *current_slot_n_digest, int *local_digest_nids, + PK11_DIGEST *digest); + +static int pk11_init_all_locks(void); +static void pk11_free_all_locks(void); + +#ifdef SOLARIS_HW_SLOT_SELECTION +static int check_hw_mechanisms(void); +static int nid_in_table(int nid, int *nid_table); +#endif /* SOLARIS_HW_SLOT_SELECTION */ + +#define TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type) \ + { \ + if (uselock) \ + LOCK_OBJSTORE(alg_type); \ + if (pk11_active_delete(obj_hdl, alg_type) == 1) \ + { \ + retval = pk11_destroy_object(sp->session, obj_hdl, \ + sp->persistent); \ + } \ + if (uselock) \ + UNLOCK_OBJSTORE(alg_type); \ + } + +static int cipher_nids[PK11_CIPHER_MAX]; +static int digest_nids[PK11_DIGEST_MAX]; +static int cipher_count = 0; +static int digest_count = 0; +static CK_BBOOL pk11_have_rsa = CK_FALSE; +static CK_BBOOL pk11_have_dsa = CK_FALSE; +static CK_BBOOL pk11_have_dh = CK_FALSE; +static CK_BBOOL pk11_have_random = CK_FALSE; + +/* + * Static list of ciphers. + * Note, that ciphers array is indexed by member PK11_CIPHER.id, + * thus ciphers[i].id == i + * Rows must be kept in sync with enum pk11_cipher_id. + */ +static PK11_CIPHER ciphers[] = + { + { PK11_DES_CBC, NID_des_cbc, 8, 8, 8, + CKK_DES, CKM_DES_CBC, }, + { PK11_DES3_CBC, NID_des_ede3_cbc, 8, 24, 24, + CKK_DES3, CKM_DES3_CBC, }, + { PK11_DES_ECB, NID_des_ecb, 0, 8, 8, + CKK_DES, CKM_DES_ECB, }, + { PK11_DES3_ECB, NID_des_ede3_ecb, 0, 24, 24, + CKK_DES3, CKM_DES3_ECB, }, + { PK11_RC4, NID_rc4, 0, 16, 256, + CKK_RC4, CKM_RC4, }, + { PK11_AES_128_CBC, NID_aes_128_cbc, 16, 16, 16, + CKK_AES, CKM_AES_CBC, }, + { PK11_AES_192_CBC, NID_aes_192_cbc, 16, 24, 24, + CKK_AES, CKM_AES_CBC, }, + { PK11_AES_256_CBC, NID_aes_256_cbc, 16, 32, 32, + CKK_AES, CKM_AES_CBC, }, + { PK11_AES_128_ECB, NID_aes_128_ecb, 0, 16, 16, + CKK_AES, CKM_AES_ECB, }, + { PK11_AES_192_ECB, NID_aes_192_ecb, 0, 24, 24, + CKK_AES, CKM_AES_ECB, }, + { PK11_AES_256_ECB, NID_aes_256_ecb, 0, 32, 32, + CKK_AES, CKM_AES_ECB, }, + { PK11_BLOWFISH_CBC, NID_bf_cbc, 8, 16, 16, + CKK_BLOWFISH, CKM_BLOWFISH_CBC, }, +#ifdef SOLARIS_AES_CTR + /* we don't know the correct NIDs until the engine is initialized */ + { PK11_AES_128_CTR, NID_undef, 16, 16, 16, + CKK_AES, CKM_AES_CTR, }, + { PK11_AES_192_CTR, NID_undef, 16, 24, 24, + CKK_AES, CKM_AES_CTR, }, + { PK11_AES_256_CTR, NID_undef, 16, 32, 32, + CKK_AES, CKM_AES_CTR, }, +#endif /* SOLARIS_AES_CTR */ + }; + +/* + * Static list of digests. + * Note, that digests array is indexed by member PK11_DIGEST.id, + * thus digests[i].id == i + * Rows must be kept in sync with enum pk11_digest_id. + */ +static PK11_DIGEST digests[] = + { + {PK11_MD5, NID_md5, CKM_MD5, }, + {PK11_SHA1, NID_sha1, CKM_SHA_1, }, + {PK11_SHA224, NID_sha224, CKM_SHA224, }, + {PK11_SHA256, NID_sha256, CKM_SHA256, }, + {PK11_SHA384, NID_sha384, CKM_SHA384, }, + {PK11_SHA512, NID_sha512, CKM_SHA512, }, + {0, NID_undef, 0xFFFF, }, + }; + +/* + * Structure to be used for the cipher_data/md_data in + * EVP_CIPHER_CTX/EVP_MD_CTX structures in order to use the same pk11 + * session in multiple cipher_update calls + */ +typedef struct PK11_CIPHER_STATE_st + { + PK11_SESSION *sp; + } PK11_CIPHER_STATE; + + +/* + * libcrypto EVP stuff - this is how we get wired to EVP so the engine gets + * called when libcrypto requests a cipher NID. + * + * Note how the PK11_CIPHER_STATE is used here. + */ + +/* DES CBC EVP */ +static const EVP_CIPHER pk11_des_cbc = + { + NID_des_cbc, + 8, 8, 8, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +/* 3DES CBC EVP */ +static const EVP_CIPHER pk11_3des_cbc = + { + NID_des_ede3_cbc, + 8, 24, 8, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +/* + * ECB modes don't use an Initial Vector so that's why set_asn1_parameters and + * get_asn1_parameters fields are set to NULL. + */ +static const EVP_CIPHER pk11_des_ecb = + { + NID_des_ecb, + 8, 8, 8, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_CIPHER pk11_3des_ecb = + { + NID_des_ede3_ecb, + 8, 24, 8, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + + +static const EVP_CIPHER pk11_aes_128_cbc = + { + NID_aes_128_cbc, + 16, 16, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_aes_192_cbc = + { + NID_aes_192_cbc, + 16, 24, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_aes_256_cbc = + { + NID_aes_256_cbc, + 16, 32, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +/* + * ECB modes don't use IV so that's why set_asn1_parameters and + * get_asn1_parameters are set to NULL. + */ +static const EVP_CIPHER pk11_aes_128_ecb = + { + NID_aes_128_ecb, + 16, 16, 0, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_CIPHER pk11_aes_192_ecb = + { + NID_aes_192_ecb, + 16, 24, 0, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_CIPHER pk11_aes_256_ecb = + { + NID_aes_256_ecb, + 16, 32, 0, + EVP_CIPH_ECB_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +#ifdef SOLARIS_AES_CTR +/* + * NID_undef's will be changed to the AES counter mode NIDs as soon they are + * created in pk11_library_init(). Note that the need to change these structures + * is the reason why we don't define them with the const keyword. + */ +static EVP_CIPHER pk11_aes_128_ctr = + { + NID_undef, + 16, 16, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static EVP_CIPHER pk11_aes_192_ctr = + { + NID_undef, + 16, 24, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static EVP_CIPHER pk11_aes_256_ctr = + { + NID_undef, + 16, 32, 16, + EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; +#endif /* SOLARIS_AES_CTR */ + +static const EVP_CIPHER pk11_bf_cbc = + { + NID_bf_cbc, + 8, 16, 8, + EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CBC_MODE, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + EVP_CIPHER_set_asn1_iv, + EVP_CIPHER_get_asn1_iv, + NULL + }; + +static const EVP_CIPHER pk11_rc4 = + { + NID_rc4, + 1, 16, 0, + EVP_CIPH_VARIABLE_LENGTH, + pk11_cipher_init, + pk11_cipher_do_cipher, + pk11_cipher_cleanup, + sizeof (PK11_CIPHER_STATE), + NULL, + NULL, + NULL + }; + +static const EVP_MD pk11_md5 = + { + NID_md5, + NID_md5WithRSAEncryption, + MD5_DIGEST_LENGTH, + 0, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + MD5_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha1 = + { + NID_sha1, + NID_sha1WithRSAEncryption, + SHA_DIGEST_LENGTH, + 0, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + SHA_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha224 = + { + NID_sha224, + NID_sha224WithRSAEncryption, + SHA224_DIGEST_LENGTH, + 0, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + /* SHA-224 uses the same cblock size as SHA-256 */ + SHA256_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha256 = + { + NID_sha256, + NID_sha256WithRSAEncryption, + SHA256_DIGEST_LENGTH, + 0, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + SHA256_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha384 = + { + NID_sha384, + NID_sha384WithRSAEncryption, + SHA384_DIGEST_LENGTH, + 0, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + /* SHA-384 uses the same cblock size as SHA-512 */ + SHA512_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +static const EVP_MD pk11_sha512 = + { + NID_sha512, + NID_sha512WithRSAEncryption, + SHA512_DIGEST_LENGTH, + 0, + pk11_digest_init, + pk11_digest_update, + pk11_digest_final, + pk11_digest_copy, + pk11_digest_cleanup, + EVP_PKEY_RSA_method, + SHA512_CBLOCK, + sizeof (PK11_CIPHER_STATE), + }; + +/* + * Initialization function. Sets up various PKCS#11 library components. + * The definitions for control commands specific to this engine + */ +#define PK11_CMD_SO_PATH ENGINE_CMD_BASE +static const ENGINE_CMD_DEFN pk11_cmd_defns[] = + { + { + PK11_CMD_SO_PATH, + "SO_PATH", + "Specifies the path to the 'pkcs#11' shared library", + ENGINE_CMD_FLAG_STRING + }, + {0, NULL, NULL, 0} + }; + + +static RAND_METHOD pk11_random = + { + pk11_rand_seed, + pk11_rand_bytes, + pk11_rand_cleanup, + pk11_rand_add, + pk11_rand_bytes, + pk11_rand_status + }; + + +/* Constants used when creating the ENGINE */ +static const char *engine_pk11_id = "pkcs11"; +static const char *engine_pk11_name = "PKCS #11 engine support"; + +CK_FUNCTION_LIST_PTR pFuncList = NULL; +static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList"; + +/* + * This is a static string constant for the DSO file name and the function + * symbol names to bind to. We set it in the Configure script based on whether + * this is 32 or 64 bit build. + */ +static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION; + +static CK_BBOOL pk11_true = CK_TRUE; +static CK_BBOOL pk11_false = CK_FALSE; +/* Needed in hw_pk11_pub.c as well so that's why it is not static. */ +CK_SLOT_ID pubkey_SLOTID = 0; +static CK_SLOT_ID rand_SLOTID = 0; +static CK_SLOT_ID SLOTID = 0; +static CK_BBOOL pk11_library_initialized = CK_FALSE; +static CK_BBOOL pk11_atfork_initialized = CK_FALSE; +static int pk11_pid = 0; + +static DSO *pk11_dso = NULL; + +/* allocate and initialize all locks used by the engine itself */ +static int pk11_init_all_locks(void) + { + int type; + +#ifndef OPENSSL_NO_RSA + find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_RSA] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_RSA], NULL); +#endif /* OPENSSL_NO_RSA */ + + if ((uri_lock = OPENSSL_malloc(sizeof (pthread_mutex_t))) == NULL) + goto malloc_err; + (void) pthread_mutex_init(uri_lock, NULL); + +#ifndef OPENSSL_NO_DSA + find_lock[OP_DSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_DSA] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_DSA], NULL); +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_DH + find_lock[OP_DH] = OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (find_lock[OP_DH] == NULL) + goto malloc_err; + (void) pthread_mutex_init(find_lock[OP_DH], NULL); +#endif /* OPENSSL_NO_DH */ + + for (type = 0; type < OP_MAX; type++) + { + session_cache[type].lock = + OPENSSL_malloc(sizeof (pthread_mutex_t)); + if (session_cache[type].lock == NULL) + goto malloc_err; + (void) pthread_mutex_init(session_cache[type].lock, NULL); + } + + return (1); + +malloc_err: + pk11_free_all_locks(); + PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE); + return (0); + } + +static void pk11_free_all_locks(void) + { + int type; + +#ifndef OPENSSL_NO_RSA + if (find_lock[OP_RSA] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_RSA]); + OPENSSL_free(find_lock[OP_RSA]); + find_lock[OP_RSA] = NULL; + } +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + if (find_lock[OP_DSA] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_DSA]); + OPENSSL_free(find_lock[OP_DSA]); + find_lock[OP_DSA] = NULL; + } +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + if (find_lock[OP_DH] != NULL) + { + (void) pthread_mutex_destroy(find_lock[OP_DH]); + OPENSSL_free(find_lock[OP_DH]); + find_lock[OP_DH] = NULL; + } +#endif /* OPENSSL_NO_DH */ + + for (type = 0; type < OP_MAX; type++) + { + if (session_cache[type].lock != NULL) + { + (void) pthread_mutex_destroy(session_cache[type].lock); + OPENSSL_free(session_cache[type].lock); + session_cache[type].lock = NULL; + } + } + } + +/* + * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support. + */ +static int bind_pk11(ENGINE *e) + { +#ifndef OPENSSL_NO_RSA + const RSA_METHOD *rsa = NULL; + RSA_METHOD *pk11_rsa = PK11_RSA(); +#endif /* OPENSSL_NO_RSA */ + if (!pk11_library_initialized) + if (!pk11_library_init(e)) + return (0); + + if (!ENGINE_set_id(e, engine_pk11_id) || + !ENGINE_set_name(e, engine_pk11_name) || + !ENGINE_set_ciphers(e, pk11_engine_ciphers) || + !ENGINE_set_digests(e, pk11_engine_digests)) + return (0); +#ifndef OPENSSL_NO_RSA + if (pk11_have_rsa == CK_TRUE) + { + if (!ENGINE_set_RSA(e, PK11_RSA()) || + !ENGINE_set_load_privkey_function(e, pk11_load_privkey) || + !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey)) + return (0); + DEBUG_SLOT_SEL("%s: registered RSA\n", PK11_DBG); + } +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + if (pk11_have_dsa == CK_TRUE) + { + if (!ENGINE_set_DSA(e, PK11_DSA())) + return (0); + DEBUG_SLOT_SEL("%s: registered DSA\n", PK11_DBG); + } +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + if (pk11_have_dh == CK_TRUE) + { + if (!ENGINE_set_DH(e, PK11_DH())) + return (0); + DEBUG_SLOT_SEL("%s: registered DH\n", PK11_DBG); + } +#endif /* OPENSSL_NO_DH */ + if (pk11_have_random) + { + if (!ENGINE_set_RAND(e, &pk11_random)) + return (0); + DEBUG_SLOT_SEL("%s: registered random\n", PK11_DBG); + } + if (!ENGINE_set_init_function(e, pk11_init) || + !ENGINE_set_destroy_function(e, pk11_destroy) || + !ENGINE_set_finish_function(e, pk11_finish) || + !ENGINE_set_ctrl_function(e, pk11_ctrl) || + !ENGINE_set_cmd_defns(e, pk11_cmd_defns)) + return (0); + +/* + * Apache calls OpenSSL function RSA_blinding_on() once during startup + * which in turn calls bn_mod_exp. Since we do not implement bn_mod_exp + * here, we wire it back to the OpenSSL software implementation. + * Since it is used only once, performance is not a concern. + */ +#ifndef OPENSSL_NO_RSA + rsa = RSA_PKCS1_SSLeay(); + pk11_rsa->rsa_mod_exp = rsa->rsa_mod_exp; + pk11_rsa->bn_mod_exp = rsa->bn_mod_exp; +#endif /* OPENSSL_NO_RSA */ + + /* Ensure the pk11 error handling is set up */ + ERR_load_pk11_strings(); + + return (1); + } + +/* Dynamic engine support is disabled at a higher level for Solaris */ +#ifdef ENGINE_DYNAMIC_SUPPORT +static int bind_helper(ENGINE *e, const char *id) + { + if (id && (strcmp(id, engine_pk11_id) != 0)) + return (0); + + if (!bind_pk11(e)) + return (0); + + return (1); + } + +IMPLEMENT_DYNAMIC_CHECK_FN() +IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) + +#else +static ENGINE *engine_pk11(void) + { + ENGINE *ret = ENGINE_new(); + + if (!ret) + return (NULL); + + if (!bind_pk11(ret)) + { + ENGINE_free(ret); + return (NULL); + } + + return (ret); + } + +void +ENGINE_load_pk11(void) + { + ENGINE *e_pk11 = NULL; + + /* + * Do not use dynamic PKCS#11 library on Solaris due to + * security reasons. We will link it in statically. + */ + /* Attempt to load PKCS#11 library */ + if (!pk11_dso) + pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0); + + if (pk11_dso == NULL) + { + PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE); + return; + } + + e_pk11 = engine_pk11(); + if (!e_pk11) + { + DSO_free(pk11_dso); + pk11_dso = NULL; + return; + } + + /* + * At this point, the pk11 shared library is either dynamically + * loaded or statically linked in. So, initialize the pk11 + * library before calling ENGINE_set_default since the latter + * needs cipher and digest algorithm information + */ + if (!pk11_library_init(e_pk11)) + { + DSO_free(pk11_dso); + pk11_dso = NULL; + ENGINE_free(e_pk11); + return; + } + + ENGINE_add(e_pk11); + + ENGINE_free(e_pk11); + ERR_clear_error(); + } +#endif /* ENGINE_DYNAMIC_SUPPORT */ + +/* + * These are the static string constants for the DSO file name and + * the function symbol names to bind to. + */ +static const char *PK11_LIBNAME = NULL; + +static const char *get_PK11_LIBNAME(void) + { + if (PK11_LIBNAME) + return (PK11_LIBNAME); + + return (def_PK11_LIBNAME); + } + +static void free_PK11_LIBNAME(void) + { + if (PK11_LIBNAME) + OPENSSL_free((void*)PK11_LIBNAME); + + PK11_LIBNAME = NULL; + } + +static long set_PK11_LIBNAME(const char *name) + { + free_PK11_LIBNAME(); + + return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0); + } + +/* acquire all engine specific mutexes before fork */ +static void pk11_fork_prepare(void) + { + int i; + + if (!pk11_library_initialized) + return; + + LOCK_OBJSTORE(OP_RSA); + LOCK_OBJSTORE(OP_DSA); + LOCK_OBJSTORE(OP_DH); + (void) pthread_mutex_lock(uri_lock); + for (i = 0; i < OP_MAX; i++) + { + (void) pthread_mutex_lock(session_cache[i].lock); + } + } + +/* release all engine specific mutexes */ +static void pk11_fork_parent(void) + { + int i; + + if (!pk11_library_initialized) + return; + + for (i = OP_MAX - 1; i >= 0; i--) + { + (void) pthread_mutex_unlock(session_cache[i].lock); + } + UNLOCK_OBJSTORE(OP_DH); + UNLOCK_OBJSTORE(OP_DSA); + UNLOCK_OBJSTORE(OP_RSA); + (void) pthread_mutex_unlock(uri_lock); + } + +/* + * same situation as in parent - we need to unlock all locks to make them + * accessible to all threads. + */ +static void pk11_fork_child(void) + { + int i; + + if (!pk11_library_initialized) + return; + + for (i = OP_MAX - 1; i >= 0; i--) + { + (void) pthread_mutex_unlock(session_cache[i].lock); + } + UNLOCK_OBJSTORE(OP_DH); + UNLOCK_OBJSTORE(OP_DSA); + UNLOCK_OBJSTORE(OP_RSA); + (void) pthread_mutex_unlock(uri_lock); + } + +/* Initialization function for the pk11 engine */ +static int pk11_init(ENGINE *e) + { + return (pk11_library_init(e)); + } + +/* + * Initialization function. Sets up various PKCS#11 library components. + * It selects a slot based on predefined critiera. In the process, it also + * count how many ciphers and digests to support. Since the cipher and + * digest information is needed when setting default engine, this function + * needs to be called before calling ENGINE_set_default. + */ +/* ARGSUSED */ +static int pk11_library_init(ENGINE *e) + { + CK_C_GetFunctionList p; + CK_RV rv = CKR_OK; + CK_INFO info; + CK_ULONG ul_state_len; + int any_slot_found; + int i; + + /* + * pk11_library_initialized is set to 0 in pk11_finish() which is called + * from ENGINE_finish(). However, if there is still at least one + * existing functional reference to the engine (see engine(3) for more + * information), pk11_finish() is skipped. For example, this can happen + * if an application forgets to clear one cipher context. In case of a + * fork() when the application is finishing the engine so that it can be + * reinitialized in the child, forgotten functional reference causes + * pk11_library_initialized to stay 1. In that case we need the PID + * check so that we properly initialize the engine again. + */ + if (pk11_library_initialized) + { + if (pk11_pid == getpid()) + { + return (1); + } + else + { + global_session = CK_INVALID_HANDLE; + /* + * free the locks first to prevent memory leak in case + * the application calls fork() without finishing the + * engine first. + */ + pk11_free_all_locks(); + } + } + + if (pk11_dso == NULL) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); + goto err; + } + +#ifdef SOLARIS_AES_CTR + /* + * We must do this before we start working with slots since we need all + * NIDs there. + */ + if (pk11_add_aes_ctr_NIDs() == 0) + goto err; +#endif /* SOLARIS_AES_CTR */ + +#ifdef SOLARIS_HW_SLOT_SELECTION + if (check_hw_mechanisms() == 0) + goto err; +#endif /* SOLARIS_HW_SLOT_SELECTION */ + + /* get the C_GetFunctionList function from the loaded library */ + p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso, + PK11_GET_FUNCTION_LIST); + if (!p) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); + goto err; + } + + /* get the full function list from the loaded library */ + rv = p(&pFuncList); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv); + goto err; + } + + rv = pFuncList->C_Initialize(NULL_PTR); + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv); + goto err; + } + + rv = pFuncList->C_GetInfo(&info); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv); + goto err; + } + + if (pk11_choose_slots(&any_slot_found) == 0) + goto err; + + /* + * The library we use, set in def_PK11_LIBNAME, may not offer any + * slot(s). In that case, we must not proceed but we must not return an + * error. The reason is that applications that try to set up the PKCS#11 + * engine don't exit on error during the engine initialization just + * because no slot was present. + */ + if (any_slot_found == 0) + return (1); + + if (global_session == CK_INVALID_HANDLE) + { + /* Open the global_session for the new process */ + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &global_session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_LIBRARY_INIT, + PK11_R_OPENSESSION, rv); + goto err; + } + } + + /* + * Disable digest if C_GetOperationState is not supported since + * this function is required by OpenSSL digest copy function + */ + if (pFuncList->C_GetOperationState(global_session, NULL, &ul_state_len) + == CKR_FUNCTION_NOT_SUPPORTED) + { + DEBUG_SLOT_SEL("%s: C_GetOperationState() not supported, " + "setting digest_count to 0\n", PK11_DBG); + digest_count = 0; + } + + pk11_library_initialized = CK_TRUE; + pk11_pid = getpid(); + /* + * if initialization of the locks fails pk11_init_all_locks() + * will do the cleanup. + */ + if (!pk11_init_all_locks()) + goto err; + for (i = 0; i < OP_MAX; i++) + session_cache[i].head = NULL; + /* + * initialize active lists. We only use active lists + * for asymmetric ciphers. + */ + for (i = 0; i < OP_MAX; i++) + active_list[i] = NULL; + + if (!pk11_atfork_initialized) + { + if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent, + pk11_fork_child) != 0) + { + PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED); + goto err; + } + pk11_atfork_initialized = CK_TRUE; + } + + return (1); + +err: + return (0); + } + +/* Destructor (complements the "ENGINE_pk11()" constructor) */ +/* ARGSUSED */ +static int pk11_destroy(ENGINE *e) + { + free_PK11_LIBNAME(); + ERR_unload_pk11_strings(); + return (1); + } + +/* + * Termination function to clean up the session, the token, and the pk11 + * library. + */ +/* ARGSUSED */ +static int pk11_finish(ENGINE *e) + { + int i; + + if (pk11_dso == NULL) + { + PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED); + goto err; + } + + OPENSSL_assert(pFuncList != NULL); + + if (pk11_free_all_sessions() == 0) + goto err; + + /* free all active lists */ + for (i = 0; i < OP_MAX; i++) + pk11_free_active_list(i); + + pFuncList->C_CloseSession(global_session); + global_session = CK_INVALID_HANDLE; + + /* + * Since we are part of a library (libcrypto.so), calling this function + * may have side-effects. + */ +#if 0 + pFuncList->C_Finalize(NULL); +#endif +#ifdef SOLARIS_AES_CTR + { + ASN1_OBJECT *ob = NULL; + if (NID_aes_128_ctr != NID_undef) + { + ob = OBJ_nid2obj(NID_aes_128_ctr); + if (ob != NULL) + ASN1_OBJECT_free(ob); + } + if (NID_aes_192_ctr != NID_undef) + { + ob = OBJ_nid2obj(NID_aes_192_ctr); + if (ob != NULL) + ASN1_OBJECT_free(ob); + } + if (NID_aes_256_ctr != NID_undef) + { + ob = OBJ_nid2obj(NID_aes_256_ctr); + if (ob != NULL) + ASN1_OBJECT_free(ob); + } + } +#endif + + if (!DSO_free(pk11_dso)) + { + PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE); + goto err; + } + pk11_dso = NULL; + pFuncList = NULL; + pk11_library_initialized = CK_FALSE; + pk11_pid = 0; + /* + * There is no way how to unregister atfork handlers (other than + * unloading the library) so we just free the locks. For this reason + * the atfork handlers check if the engine is initialized and bail out + * immediately if not. This is necessary in case a process finishes + * the engine before calling fork(). + */ + pk11_free_all_locks(); + + return (1); + +err: + return (0); + } + +/* Standard engine interface function to set the dynamic library path */ +/* ARGSUSED */ +static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) + { + int initialized = ((pk11_dso == NULL) ? 0 : 1); + + switch (cmd) + { + case PK11_CMD_SO_PATH: + if (p == NULL) + { + PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); + return (0); + } + + if (initialized) + { + PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED); + return (0); + } + + return (set_PK11_LIBNAME((const char *)p)); + default: + break; + } + + PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED); + + return (0); + } + + +/* Required function by the engine random interface. It does nothing here */ +static void pk11_rand_cleanup(void) + { + return; + } + +/* ARGSUSED */ +static void pk11_rand_add(const void *buf, int num, double add) + { + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RAND)) == NULL) + return; + + /* + * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since + * the calling functions do not care anyway + */ + pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num); + pk11_return_session(sp, OP_RAND); + + return; + } + +static void pk11_rand_seed(const void *buf, int num) + { + pk11_rand_add(buf, num, 0); + } + +static int pk11_rand_bytes(unsigned char *buf, int num) + { + CK_RV rv; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RAND)) == NULL) + return (0); + + rv = pFuncList->C_GenerateRandom(sp->session, buf, num); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv); + pk11_return_session(sp, OP_RAND); + return (0); + } + + pk11_return_session(sp, OP_RAND); + return (1); + } + +/* Required function by the engine random interface. It does nothing here */ +static int pk11_rand_status(void) + { + return (1); + } + +/* Free all BIGNUM structures from PK11_SESSION. */ +static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype) + { + switch (optype) + { +#ifndef OPENSSL_NO_RSA + case OP_RSA: + if (sp->opdata_rsa_n_num != NULL) + { + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + } + if (sp->opdata_rsa_e_num != NULL) + { + BN_free(sp->opdata_rsa_e_num); + sp->opdata_rsa_e_num = NULL; + } + if (sp->opdata_rsa_d_num != NULL) + { + BN_free(sp->opdata_rsa_d_num); + sp->opdata_rsa_d_num = NULL; + } + break; +#endif +#ifndef OPENSSL_NO_DSA + case OP_DSA: + if (sp->opdata_dsa_pub_num != NULL) + { + BN_free(sp->opdata_dsa_pub_num); + sp->opdata_dsa_pub_num = NULL; + } + if (sp->opdata_dsa_priv_num != NULL) + { + BN_free(sp->opdata_dsa_priv_num); + sp->opdata_dsa_priv_num = NULL; + } + break; +#endif +#ifndef OPENSSL_NO_DH + case OP_DH: + if (sp->opdata_dh_priv_num != NULL) + { + BN_free(sp->opdata_dh_priv_num); + sp->opdata_dh_priv_num = NULL; + } + break; +#endif + default: + break; + } + } + +/* + * Get new PK11_SESSION structure ready for use. Every process must have + * its own freelist of PK11_SESSION structures so handle fork() here + * by destroying the old and creating new freelist. + * The returned PK11_SESSION structure is disconnected from the freelist. + */ +PK11_SESSION * +pk11_get_session(PK11_OPTYPE optype) + { + PK11_SESSION *sp = NULL, *sp1, *freelist; + pthread_mutex_t *freelist_lock; + static pid_t pid = 0; + pid_t new_pid; + CK_RV rv; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: + freelist_lock = session_cache[optype].lock; + break; + default: + PK11err(PK11_F_GET_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return (NULL); + } + (void) pthread_mutex_lock(freelist_lock); + + /* + * Will use it to find out if we forked. We cannot use the PID field in + * the session structure because we could get a newly allocated session + * here, with no PID information. + */ + if (pid == 0) + pid = getpid(); + + freelist = session_cache[optype].head; + sp = freelist; + + /* + * If the free list is empty, allocate new uninitialized (filled + * with zeroes) PK11_SESSION structure otherwise return first + * structure from the freelist. + */ + if (sp == NULL) + { + if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL) + { + PK11err(PK11_F_GET_SESSION, + PK11_R_MALLOC_FAILURE); + goto err; + } + (void) memset(sp, 0, sizeof (PK11_SESSION)); + + /* + * It is a new session so it will look like a cache miss to the + * code below. So, we must not try to to destroy its members so + * mark them as unused. + */ + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + } + else + freelist = sp->next; + + /* + * Check whether we have forked. In that case, we must get rid of all + * inherited sessions and start allocating new ones. + */ + if (pid != (new_pid = getpid())) + { + pid = new_pid; + + /* + * We are a new process and thus need to free any inherited + * PK11_SESSION objects aside from the first session (sp) which + * is the only PK11_SESSION structure we will reuse (for the + * head of the list). + */ + while ((sp1 = freelist) != NULL) + { + freelist = sp1->next; + /* + * NOTE: we do not want to call pk11_free_all_sessions() + * here because it would close underlying PKCS#11 + * sessions and destroy all objects. + */ + pk11_free_nums(sp1, optype); + OPENSSL_free(sp1); + } + + /* we have to free the active list as well. */ + pk11_free_active_list(optype); + + /* Initialize the process */ + rv = pFuncList->C_Initialize(NULL_PTR); + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE, + rv); + OPENSSL_free(sp); + sp = NULL; + goto err; + } + + /* + * Choose slot here since the slot table is different on this + * process. If we are here then we must have found at least one + * usable slot before so we don't need to check any_slot_found. + * See pk11_library_init()'s usage of this function for more + * information. + */ +#ifdef SOLARIS_HW_SLOT_SELECTION + if (check_hw_mechanisms() == 0) + goto err; +#endif /* SOLARIS_HW_SLOT_SELECTION */ + if (pk11_choose_slots(NULL) == 0) + goto err; + + /* Open the global_session for the new process */ + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &global_session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION, + rv); + OPENSSL_free(sp); + sp = NULL; + goto err; + } + + /* + * It is an inherited session from our parent so it needs + * re-initialization. + */ + if (pk11_setup_session(sp, optype) == 0) + { + OPENSSL_free(sp); + sp = NULL; + goto err; + } + if (pk11_token_relogin(sp->session) == 0) + { + /* + * We will keep the session in the cache list and let + * the caller cope with the situation. + */ + freelist = sp; + sp = NULL; + goto err; + } + } + + if (sp->pid == 0) + { + /* It is a new session and needs initialization. */ + if (pk11_setup_session(sp, optype) == 0) + { + OPENSSL_free(sp); + sp = NULL; + } + } + + /* set new head for the list of PK11_SESSION objects */ + session_cache[optype].head = freelist; + +err: + if (sp != NULL) + sp->next = NULL; + + (void) pthread_mutex_unlock(freelist_lock); + + return (sp); + } + + +void +pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype) + { + pthread_mutex_t *freelist_lock; + PK11_SESSION *freelist; + + /* + * If this is a session from the parent it will be taken care of and + * freed in pk11_get_session() as part of the post-fork clean up the + * next time we will ask for a new session. + */ + if (sp == NULL || sp->pid != getpid()) + return; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: + freelist_lock = session_cache[optype].lock; + break; + default: + PK11err(PK11_F_RETURN_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return; + } + + (void) pthread_mutex_lock(freelist_lock); + freelist = session_cache[optype].head; + sp->next = freelist; + session_cache[optype].head = sp; + (void) pthread_mutex_unlock(freelist_lock); + } + + +/* Destroy all objects. This function is called when the engine is finished */ +static int pk11_free_all_sessions() + { + int ret = 1; + int type; + +#ifndef OPENSSL_NO_RSA + (void) pk11_destroy_rsa_key_objects(NULL); +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + (void) pk11_destroy_dsa_key_objects(NULL); +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + (void) pk11_destroy_dh_key_objects(NULL); +#endif /* OPENSSL_NO_DH */ + (void) pk11_destroy_cipher_key_objects(NULL); + + /* + * We try to release as much as we can but any error means that we will + * return 0 on exit. + */ + for (type = 0; type < OP_MAX; type++) + { + if (pk11_free_session_list(type) == 0) + ret = 0; + } + + return (ret); + } + +/* + * Destroy session structures from the linked list specified. Free as many + * sessions as possible but any failure in C_CloseSession() means that we + * return an error on return. + */ +static int pk11_free_session_list(PK11_OPTYPE optype) + { + CK_RV rv; + PK11_SESSION *sp = NULL; + PK11_SESSION *freelist = NULL; + pid_t mypid = getpid(); + pthread_mutex_t *freelist_lock; + int ret = 1; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + case OP_RAND: + case OP_DIGEST: + case OP_CIPHER: + freelist_lock = session_cache[optype].lock; + break; + default: + PK11err(PK11_F_FREE_ALL_SESSIONS, + PK11_R_INVALID_OPERATION_TYPE); + return (0); + } + + (void) pthread_mutex_lock(freelist_lock); + freelist = session_cache[optype].head; + while ((sp = freelist) != NULL) + { + if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid) + { + rv = pFuncList->C_CloseSession(sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_FREE_ALL_SESSIONS, + PK11_R_CLOSESESSION, rv); + ret = 0; + } + } + freelist = sp->next; + pk11_free_nums(sp, optype); + OPENSSL_free(sp); + } + + (void) pthread_mutex_unlock(freelist_lock); + return (ret); + } + + +static int +pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype) + { + CK_RV rv; + CK_SLOT_ID myslot; + + switch (optype) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + myslot = pubkey_SLOTID; + break; + case OP_RAND: + myslot = rand_SLOTID; + break; + case OP_DIGEST: + case OP_CIPHER: + myslot = SLOTID; + break; + default: + PK11err(PK11_F_SETUP_SESSION, + PK11_R_INVALID_OPERATION_TYPE); + return (0); + } + + sp->session = CK_INVALID_HANDLE; + DEBUG_SLOT_SEL("%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype); + rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + if (rv == CKR_CRYPTOKI_NOT_INITIALIZED) + { + /* + * We are probably a child process so force the + * reinitialize of the session + */ + pk11_library_initialized = CK_FALSE; + if (!pk11_library_init(NULL)) + return (0); + rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + } + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv); + return (0); + } + + sp->pid = getpid(); + + switch (optype) + { +#ifndef OPENSSL_NO_RSA + case OP_RSA: + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub = NULL; + sp->opdata_rsa_n_num = NULL; + sp->opdata_rsa_e_num = NULL; + sp->opdata_rsa_priv = NULL; + sp->opdata_rsa_d_num = NULL; + break; +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + case OP_DSA: + sp->opdata_dsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_dsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_dsa_pub = NULL; + sp->opdata_dsa_pub_num = NULL; + sp->opdata_dsa_priv = NULL; + sp->opdata_dsa_priv_num = NULL; + break; +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + case OP_DH: + sp->opdata_dh_key = CK_INVALID_HANDLE; + sp->opdata_dh = NULL; + sp->opdata_dh_priv_num = NULL; + break; +#endif /* OPENSSL_NO_DH */ + case OP_CIPHER: + sp->opdata_cipher_key = CK_INVALID_HANDLE; + sp->opdata_encrypt = -1; + break; + } + + /* + * We always initialize the session as containing a non-persistent + * object. The key load functions set it to persistent if that is so. + */ + sp->persistent = CK_FALSE; + return (1); + } + +#ifndef OPENSSL_NO_RSA +/* + * Destroy all non-NULL RSA parameters. For the RSA keys by reference code, + * public components 'n'/'e' are the key components we use to check for the + * cache hit even for the private keys. So, no matter whether we are destroying + * a public or a private key, we always free what we can. + */ +static void +destroy_all_rsa_params(PK11_SESSION *sp) + { + if (sp->opdata_rsa_n_num != NULL) + { + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + } + if (sp->opdata_rsa_e_num != NULL) + { + BN_free(sp->opdata_rsa_e_num); + sp->opdata_rsa_e_num = NULL; + } + if (sp->opdata_rsa_d_num != NULL) + { + BN_free(sp->opdata_rsa_d_num); + sp->opdata_rsa_d_num = NULL; + } + } + +/* Destroy RSA public key from single session. */ +int +pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_rsa_pub_key, + ret, uselock, OP_RSA); + sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_rsa_pub = NULL; + destroy_all_rsa_params(sp); + } + + return (ret); + } + +/* Destroy RSA private key from single session. */ +int +pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_rsa_priv_key, + ret, uselock, OP_RSA); + sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_rsa_priv = NULL; + destroy_all_rsa_params(sp); + } + + return (ret); + } + +/* + * Destroy RSA key object wrapper. If session is NULL, try to destroy all + * objects in the free list. + */ +int +pk11_destroy_rsa_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = CK_TRUE; + + if (session != NULL) + local_free_session = session; + else + { + (void) pthread_mutex_lock(session_cache[OP_RSA].lock); + local_free_session = session_cache[OP_RSA].head; + uselock = CK_FALSE; + } + + /* + * go through the list of sessions and delete key objects + */ + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_rsa_object_pub(sp, uselock) == 0) + { + ret = 0; + continue; + } + if (pk11_destroy_rsa_object_priv(sp, uselock) == 0) + { + ret = 0; + continue; + } + } + + if (session == NULL) + (void) pthread_mutex_unlock(session_cache[OP_RSA].lock); + + return (ret); + } +#endif /* OPENSSL_NO_RSA */ + +#ifndef OPENSSL_NO_DSA +/* Destroy DSA public key from single session. */ +int +pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_dsa_pub_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_dsa_pub_key, + ret, uselock, OP_DSA); + sp->opdata_dsa_pub_key = CK_INVALID_HANDLE; + sp->opdata_dsa_pub = NULL; + if (sp->opdata_dsa_pub_num != NULL) + { + BN_free(sp->opdata_dsa_pub_num); + sp->opdata_dsa_pub_num = NULL; + } + } + + return (ret); + } + +/* Destroy DSA private key from single session. */ +int +pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_dsa_priv_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_dsa_priv_key, + ret, uselock, OP_DSA); + sp->opdata_dsa_priv_key = CK_INVALID_HANDLE; + sp->opdata_dsa_priv = NULL; + if (sp->opdata_dsa_priv_num != NULL) + { + BN_free(sp->opdata_dsa_priv_num); + sp->opdata_dsa_priv_num = NULL; + } + } + + return (ret); + } + +/* + * Destroy DSA key object wrapper. If session is NULL, try to destroy all + * objects in the free list. + */ +int +pk11_destroy_dsa_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = CK_TRUE; + + if (session != NULL) + local_free_session = session; + else + { + (void) pthread_mutex_lock(session_cache[OP_DSA].lock); + local_free_session = session_cache[OP_DSA].head; + uselock = CK_FALSE; + } + + /* + * go through the list of sessions and delete key objects + */ + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_dsa_object_pub(sp, uselock) == 0) + { + ret = 0; + continue; + } + if (pk11_destroy_dsa_object_priv(sp, uselock) == 0) + { + ret = 0; + continue; + } + } + + if (session == NULL) + (void) pthread_mutex_unlock(session_cache[OP_DSA].lock); + + return (ret); + } +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_DH +/* Destroy DH key from single session. */ +int +pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock) + { + int ret = 0; + + if (sp->opdata_dh_key != CK_INVALID_HANDLE) + { + TRY_OBJ_DESTROY(sp, sp->opdata_dh_key, + ret, uselock, OP_DH); + sp->opdata_dh_key = CK_INVALID_HANDLE; + sp->opdata_dh = NULL; + if (sp->opdata_dh_priv_num != NULL) + { + BN_free(sp->opdata_dh_priv_num); + sp->opdata_dh_priv_num = NULL; + } + } + + return (ret); + } + +/* + * Destroy DH key object wrapper. + * + * arg0: pointer to PKCS#11 engine session structure + * if session is NULL, try to destroy all objects in the free list + */ +int +pk11_destroy_dh_key_objects(PK11_SESSION *session) + { + int ret = 1; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + CK_BBOOL uselock = CK_TRUE; + + if (session != NULL) + local_free_session = session; + else + { + (void) pthread_mutex_lock(session_cache[OP_DH].lock); + local_free_session = session_cache[OP_DH].head; + uselock = CK_FALSE; + } + + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + /* + * Do not terminate list traversal if one of the + * destroy operations fails. + */ + if (pk11_destroy_dh_object(sp, uselock) == 0) + { + ret = 0; + continue; + } + } +err: + if (session == NULL) + (void) pthread_mutex_unlock(session_cache[OP_DH].lock); + + return (ret); + } +#endif /* OPENSSL_NO_DH */ + +static int +pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh, + CK_BBOOL persistent) + { + CK_RV rv; + + /* + * We never try to destroy persistent objects which are the objects + * stored in the keystore. Also, we always use read-only sessions so + * C_DestroyObject() would be returning CKR_SESSION_READ_ONLY here. + */ + if (persistent == CK_TRUE) + return (1); + + rv = pFuncList->C_DestroyObject(session, oh); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT, + rv); + return (0); + } + + return (1); + } + + +/* Symmetric ciphers and digests support functions */ + +static int +cipher_nid_to_pk11(int nid) + { + int i; + + for (i = 0; i < PK11_CIPHER_MAX; i++) + if (ciphers[i].nid == nid) + return (ciphers[i].id); + return (-1); + } + +static int +pk11_usable_ciphers(const int **nids) + { + if (cipher_count > 0) + *nids = cipher_nids; + else + *nids = NULL; + return (cipher_count); + } + +static int +pk11_usable_digests(const int **nids) + { + if (digest_count > 0) + *nids = digest_nids; + else + *nids = NULL; + return (digest_count); + } + +/* + * Init context for encryption or decryption using a symmetric key. + */ +static int pk11_init_symmetric(EVP_CIPHER_CTX *ctx, PK11_CIPHER *pcipher, + PK11_SESSION *sp, CK_MECHANISM_PTR pmech) + { + CK_RV rv; +#ifdef SOLARIS_AES_CTR + CK_AES_CTR_PARAMS ctr_params; +#endif /* SOLARIS_AES_CTR */ + + /* + * We expect pmech->mechanism to be already set and + * pParameter/ulParameterLen initialized to NULL/0 before + * pk11_init_symmetric() is called. + */ + OPENSSL_assert(pmech->mechanism != NULL); + OPENSSL_assert(pmech->pParameter == NULL); + OPENSSL_assert(pmech->ulParameterLen == 0); + +#ifdef SOLARIS_AES_CTR + if (ctx->cipher->nid == NID_aes_128_ctr || + ctx->cipher->nid == NID_aes_192_ctr || + ctx->cipher->nid == NID_aes_256_ctr) + { + pmech->pParameter = (void *)(&ctr_params); + pmech->ulParameterLen = sizeof (ctr_params); + /* + * For now, we are limited to the fixed length of the counter, + * it covers the whole counter block. That's what RFC 4344 + * needs. For more information on internal structure of the + * counter block, see RFC 3686. If needed in the future, we can + * add code so that the counter length can be set via + * ENGINE_ctrl() function. + */ + ctr_params.ulCounterBits = AES_BLOCK_SIZE * 8; + OPENSSL_assert(pcipher->iv_len == AES_BLOCK_SIZE); + (void) memcpy(ctr_params.cb, ctx->iv, AES_BLOCK_SIZE); + } + else +#endif /* SOLARIS_AES_CTR */ + { + if (pcipher->iv_len > 0) + { + pmech->pParameter = (void *)ctx->iv; + pmech->ulParameterLen = pcipher->iv_len; + } + } + + /* if we get here, the encryption needs to be reinitialized */ + if (ctx->encrypt) + rv = pFuncList->C_EncryptInit(sp->session, pmech, + sp->opdata_cipher_key); + else + rv = pFuncList->C_DecryptInit(sp->session, pmech, + sp->opdata_cipher_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_INIT, ctx->encrypt ? + PK11_R_ENCRYPTINIT : PK11_R_DECRYPTINIT, rv); + pk11_return_session(sp, OP_CIPHER); + return (0); + } + + return (1); + } + +/* ARGSUSED */ +static int +pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) + { + CK_MECHANISM mech; + int index; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; + PK11_SESSION *sp; + PK11_CIPHER *p_ciph_table_row; + + state->sp = NULL; + + index = cipher_nid_to_pk11(ctx->cipher->nid); + if (index < 0 || index >= PK11_CIPHER_MAX) + return (0); + + p_ciph_table_row = &ciphers[index]; + /* + * iv_len in the ctx->cipher structure is the maximum IV length for the + * current cipher and it must be less or equal to the IV length in our + * ciphers table. The key length must be in the allowed interval. From + * all cipher modes that the PKCS#11 engine supports only RC4 allows a + * key length to be in some range, all other NIDs have a precise key + * length. Every application can define its own EVP functions so this + * code serves as a sanity check. + * + * Note that the reason why the IV length in ctx->cipher might be + * greater than the actual length is that OpenSSL uses BLOCK_CIPHER_defs + * macro to define functions that return EVP structures for all DES + * modes. So, even ECB modes get 8 byte IV. + */ + if (ctx->cipher->iv_len < p_ciph_table_row->iv_len || + ctx->key_len < p_ciph_table_row->min_key_len || + ctx->key_len > p_ciph_table_row->max_key_len) + { + PK11err(PK11_F_CIPHER_INIT, PK11_R_KEY_OR_IV_LEN_PROBLEM); + return (0); + } + + if ((sp = pk11_get_session(OP_CIPHER)) == NULL) + return (0); + + /* if applicable, the mechanism parameter is used for IV */ + mech.mechanism = p_ciph_table_row->mech_type; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + /* The key object is destroyed here if it is not the current key. */ + (void) check_new_cipher_key(sp, key, ctx->key_len); + + /* + * If the key is the same and the encryption is also the same, then + * just reuse it. However, we must not forget to reinitialize the + * context that was finalized in pk11_cipher_cleanup(). + */ + if (sp->opdata_cipher_key != CK_INVALID_HANDLE && + sp->opdata_encrypt == ctx->encrypt) + { + state->sp = sp; + if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0) + return (0); + + return (1); + } + + /* + * Check if the key has been invalidated. If so, a new key object + * needs to be created. + */ + if (sp->opdata_cipher_key == CK_INVALID_HANDLE) + { + sp->opdata_cipher_key = pk11_get_cipher_key( + ctx, key, p_ciph_table_row->key_type, sp); + } + + if (sp->opdata_encrypt != ctx->encrypt && sp->opdata_encrypt != -1) + { + /* + * The previous encryption/decryption is different. Need to + * terminate the previous * active encryption/decryption here. + */ + if (!pk11_cipher_final(sp)) + { + pk11_return_session(sp, OP_CIPHER); + return (0); + } + } + + if (sp->opdata_cipher_key == CK_INVALID_HANDLE) + { + pk11_return_session(sp, OP_CIPHER); + return (0); + } + + /* now initialize the context with a new key */ + if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0) + return (0); + + sp->opdata_encrypt = ctx->encrypt; + state->sp = sp; + + return (1); + } + +/* + * When reusing the same key in an encryption/decryption session for a + * decryption/encryption session, we need to close the active session + * and recreate a new one. Note that the key is in the global session so + * that it needs not be recreated. + * + * It is more appropriate to use C_En/DecryptFinish here. At the time of this + * development, these two functions in the PKCS#11 libraries used return + * unexpected errors when passing in 0 length output. It may be a good + * idea to try them again if performance is a problem here and fix + * C_En/DecryptFinial if there are bugs there causing the problem. + */ +static int +pk11_cipher_final(PK11_SESSION *sp) + { + CK_RV rv; + + rv = pFuncList->C_CloseSession(sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_CLOSESESSION, rv); + return (0); + } + + rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, + NULL_PTR, NULL_PTR, &sp->session); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_OPENSESSION, rv); + return (0); + } + + return (1); + } + +/* + * An engine interface function. The calling function allocates sufficient + * memory for the output buffer "out" to hold the results. + */ +static int +pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, unsigned int inl) + { + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; + PK11_SESSION *sp; + CK_RV rv; + unsigned long outl = inl; + + if (state == NULL || state->sp == NULL) + return (0); + + sp = (PK11_SESSION *) state->sp; + + if (!inl) + return (1); + + /* RC4 is the only stream cipher we support */ + if (ctx->cipher->nid != NID_rc4 && (inl % ctx->cipher->block_size) != 0) + return (0); + + if (ctx->encrypt) + { + rv = pFuncList->C_EncryptUpdate(sp->session, + (unsigned char *)in, inl, out, &outl); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_DO_CIPHER, + PK11_R_ENCRYPTUPDATE, rv); + return (0); + } + } + else + { + rv = pFuncList->C_DecryptUpdate(sp->session, + (unsigned char *)in, inl, out, &outl); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_DO_CIPHER, + PK11_R_DECRYPTUPDATE, rv); + return (0); + } + } + + /* + * For DES_CBC, DES3_CBC, AES_CBC, and RC4, the output size is always + * the same size of input. + * The application has guaranteed to call the block ciphers with + * correctly aligned buffers. + */ + if (inl != outl) + return (0); + + return (1); + } + +/* + * Return the session to the pool. Calling C_EncryptFinal() and C_DecryptFinal() + * here is the right thing because in EVP_DecryptFinal_ex(), engine's + * do_cipher() is not even called, and in EVP_EncryptFinal_ex() it is called but + * the engine can't find out that it's the finalizing call. We wouldn't + * necessarily have to finalize the context here since reinitializing it with + * C_(Encrypt|Decrypt)Init() should be fine but for the sake of correctness, + * let's do it. Some implementations might leak memory if the previously used + * context is initialized without finalizing it first. + */ +static int +pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx) + { + CK_RV rv; + CK_ULONG len = EVP_MAX_BLOCK_LENGTH; + CK_BYTE buf[EVP_MAX_BLOCK_LENGTH]; + PK11_CIPHER_STATE *state = ctx->cipher_data; + + if (state != NULL && state->sp != NULL) + { + /* + * We are not interested in the data here, we just need to get + * rid of the context. + */ + if (ctx->encrypt) + rv = pFuncList->C_EncryptFinal( + state->sp->session, buf, &len); + else + rv = pFuncList->C_DecryptFinal( + state->sp->session, buf, &len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CIPHER_CLEANUP, ctx->encrypt ? + PK11_R_ENCRYPTFINAL : PK11_R_DECRYPTFINAL, rv); + pk11_return_session(state->sp, OP_CIPHER); + return (0); + } + + pk11_return_session(state->sp, OP_CIPHER); + state->sp = NULL; + } + + return (1); + } + +/* + * Registered by the ENGINE when used to find out how to deal with + * a particular NID in the ENGINE. This says what we'll do at the + * top level - note, that list is restricted by what we answer with + */ +/* ARGSUSED */ +static int +pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, + const int **nids, int nid) + { + if (!cipher) + return (pk11_usable_ciphers(nids)); + + switch (nid) + { + case NID_des_ede3_cbc: + *cipher = &pk11_3des_cbc; + break; + case NID_des_cbc: + *cipher = &pk11_des_cbc; + break; + case NID_des_ede3_ecb: + *cipher = &pk11_3des_ecb; + break; + case NID_des_ecb: + *cipher = &pk11_des_ecb; + break; + case NID_aes_128_cbc: + *cipher = &pk11_aes_128_cbc; + break; + case NID_aes_192_cbc: + *cipher = &pk11_aes_192_cbc; + break; + case NID_aes_256_cbc: + *cipher = &pk11_aes_256_cbc; + break; + case NID_aes_128_ecb: + *cipher = &pk11_aes_128_ecb; + break; + case NID_aes_192_ecb: + *cipher = &pk11_aes_192_ecb; + break; + case NID_aes_256_ecb: + *cipher = &pk11_aes_256_ecb; + break; + case NID_bf_cbc: + *cipher = &pk11_bf_cbc; + break; + case NID_rc4: + *cipher = &pk11_rc4; + break; + default: +#ifdef SOLARIS_AES_CTR + /* + * These can't be in separated cases because the NIDs + * here are not constants. + */ + if (nid == NID_aes_128_ctr) + *cipher = &pk11_aes_128_ctr; + else if (nid == NID_aes_192_ctr) + *cipher = &pk11_aes_192_ctr; + else if (nid == NID_aes_256_ctr) + *cipher = &pk11_aes_256_ctr; + else +#endif /* SOLARIS_AES_CTR */ + *cipher = NULL; + break; + } + return (*cipher != NULL); + } + +/* ARGSUSED */ +static int +pk11_engine_digests(ENGINE *e, const EVP_MD **digest, + const int **nids, int nid) + { + if (!digest) + return (pk11_usable_digests(nids)); + + switch (nid) + { + case NID_md5: + *digest = &pk11_md5; + break; + case NID_sha1: + *digest = &pk11_sha1; + break; + case NID_sha224: + *digest = &pk11_sha224; + break; + case NID_sha256: + *digest = &pk11_sha256; + break; + case NID_sha384: + *digest = &pk11_sha384; + break; + case NID_sha512: + *digest = &pk11_sha512; + break; + default: + *digest = NULL; + break; + } + return (*digest != NULL); + } + + +/* Create a secret key object in a PKCS#11 session */ +static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, + const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_OBJECT_CLASS obj_key = CKO_SECRET_KEY; + CK_ULONG ul_key_attr_count = 6; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void*) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void*) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &pk11_false, sizeof (pk11_false)}, + {CKA_ENCRYPT, &pk11_true, sizeof (pk11_true)}, + {CKA_DECRYPT, &pk11_true, sizeof (pk11_true)}, + {CKA_VALUE, (void*) NULL, 0}, + }; + + /* + * Create secret key object in global_session. All other sessions + * can use the key handles. Here is why: + * OpenSSL will call EncryptInit and EncryptUpdate using a secret key. + * It may then call DecryptInit and DecryptUpdate using the same key. + * To use the same key object, we need to call EncryptFinal with + * a 0 length message. Currently, this does not work for 3DES + * mechanism. To get around this problem, we close the session and + * then create a new session to use the same key object. When a session + * is closed, all the object handles will be invalid. Thus, create key + * objects in a global session, an individual session may be closed to + * terminate the active operation. + */ + CK_SESSION_HANDLE session = global_session; + a_key_template[0].pValue = &obj_key; + a_key_template[1].pValue = &key_type; + a_key_template[5].pValue = (void *) key; + a_key_template[5].ulValueLen = (unsigned long) ctx->key_len; + + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_CIPHER_KEY, PK11_R_CREATEOBJECT, + rv); + goto err; + } + + /* + * Save the key information used in this session. + * The max can be saved is PK11_KEY_LEN_MAX. + */ + sp->opdata_key_len = ctx->key_len > PK11_KEY_LEN_MAX ? + PK11_KEY_LEN_MAX : ctx->key_len; + (void) memcpy(sp->opdata_key, key, sp->opdata_key_len); +err: + + return (h_key); + } + +static int +md_nid_to_pk11(int nid) + { + int i; + + for (i = 0; i < PK11_DIGEST_MAX; i++) + if (digests[i].nid == nid) + return (digests[i].id); + return (-1); + } + +static int +pk11_digest_init(EVP_MD_CTX *ctx) + { + CK_RV rv; + CK_MECHANISM mech; + int index; + PK11_SESSION *sp; + PK11_DIGEST *pdp; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; + + state->sp = NULL; + + index = md_nid_to_pk11(ctx->digest->type); + if (index < 0 || index >= PK11_DIGEST_MAX) + return (0); + + pdp = &digests[index]; + if ((sp = pk11_get_session(OP_DIGEST)) == NULL) + return (0); + + /* at present, no parameter is needed for supported digests */ + mech.mechanism = pdp->mech_type; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + rv = pFuncList->C_DigestInit(sp->session, &mech); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_INIT, PK11_R_DIGESTINIT, rv); + pk11_return_session(sp, OP_DIGEST); + return (0); + } + + state->sp = sp; + + return (1); + } + +static int +pk11_digest_update(EVP_MD_CTX *ctx, const void *data, size_t count) + { + CK_RV rv; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; + + /* 0 length message will cause a failure in C_DigestFinal */ + if (count == 0) + return (1); + + if (state == NULL || state->sp == NULL) + return (0); + + rv = pFuncList->C_DigestUpdate(state->sp->session, (CK_BYTE *) data, + count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_UPDATE, PK11_R_DIGESTUPDATE, rv); + pk11_return_session(state->sp, OP_DIGEST); + state->sp = NULL; + return (0); + } + + return (1); + } + +static int +pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md) + { + CK_RV rv; + unsigned long len; + PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; + len = ctx->digest->md_size; + + if (state == NULL || state->sp == NULL) + return (0); + + rv = pFuncList->C_DigestFinal(state->sp->session, md, &len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_FINAL, PK11_R_DIGESTFINAL, rv); + pk11_return_session(state->sp, OP_DIGEST); + state->sp = NULL; + return (0); + } + + if (ctx->digest->md_size != len) + return (0); + + /* + * Final is called and digest is returned, so return the session + * to the pool + */ + pk11_return_session(state->sp, OP_DIGEST); + state->sp = NULL; + + return (1); + } + +static int +pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) + { + CK_RV rv; + int ret = 0; + PK11_CIPHER_STATE *state, *state_to; + CK_BYTE_PTR pstate = NULL; + CK_ULONG ul_state_len; + + /* The copy-from state */ + state = (PK11_CIPHER_STATE *) from->md_data; + if (state == NULL || state->sp == NULL) + goto err; + + /* Initialize the copy-to state */ + if (!pk11_digest_init(to)) + goto err; + state_to = (PK11_CIPHER_STATE *) to->md_data; + + /* Get the size of the operation state of the copy-from session */ + rv = pFuncList->C_GetOperationState(state->sp->session, NULL, + &ul_state_len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE, + rv); + goto err; + } + if (ul_state_len == 0) + { + goto err; + } + + pstate = OPENSSL_malloc(ul_state_len); + if (pstate == NULL) + { + PK11err(PK11_F_DIGEST_COPY, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* Get the operation state of the copy-from session */ + rv = pFuncList->C_GetOperationState(state->sp->session, pstate, + &ul_state_len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE, + rv); + goto err; + } + + /* Set the operation state of the copy-to session */ + rv = pFuncList->C_SetOperationState(state_to->sp->session, pstate, + ul_state_len, 0, 0); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DIGEST_COPY, + PK11_R_SET_OPERATION_STATE, rv); + goto err; + } + + ret = 1; +err: + if (pstate != NULL) + OPENSSL_free(pstate); + + return (ret); + } + +/* Return any pending session state to the pool */ +static int +pk11_digest_cleanup(EVP_MD_CTX *ctx) + { + PK11_CIPHER_STATE *state = ctx->md_data; + unsigned char buf[EVP_MAX_MD_SIZE]; + + if (state != NULL && state->sp != NULL) + { + /* + * If state->sp is not NULL then pk11_digest_final() has not + * been called yet. We must call it now to free any memory + * that might have been allocated in the token when + * pk11_digest_init() was called. pk11_digest_final() + * will return the session to the cache. + */ + if (!pk11_digest_final(ctx, buf)) + return (0); + } + + return (1); + } + +/* + * Check if the new key is the same as the key object in the session. If the key + * is the same, no need to create a new key object. Otherwise, the old key + * object needs to be destroyed and a new one will be created. Return 1 for + * cache hit, 0 for cache miss. Note that we must check the key length first + * otherwise we could end up reusing a different, longer key with the same + * prefix. + */ +static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key, + int key_len) + { + if (sp->opdata_key_len != key_len || + memcmp(sp->opdata_key, key, key_len) != 0) + { + (void) pk11_destroy_cipher_key_objects(sp); + return (0); + } + return (1); + } + +/* Destroy one or more secret key objects. */ +static int pk11_destroy_cipher_key_objects(PK11_SESSION *session) + { + int ret = 0; + PK11_SESSION *sp = NULL; + PK11_SESSION *local_free_session; + + if (session != NULL) + local_free_session = session; + else + { + (void) pthread_mutex_lock(session_cache[OP_CIPHER].lock); + local_free_session = session_cache[OP_CIPHER].head; + } + + while ((sp = local_free_session) != NULL) + { + local_free_session = sp->next; + + if (sp->opdata_cipher_key != CK_INVALID_HANDLE) + { + /* + * The secret key object is created in the + * global_session. See pk11_get_cipher_key(). + */ + if (pk11_destroy_object(global_session, + sp->opdata_cipher_key, CK_FALSE) == 0) + goto err; + sp->opdata_cipher_key = CK_INVALID_HANDLE; + } + } + ret = 1; +err: + + if (session == NULL) + (void) pthread_mutex_unlock(session_cache[OP_CIPHER].lock); + + return (ret); + } + + +/* + * Public key mechanisms optionally supported + * + * CKM_RSA_X_509 + * CKM_RSA_PKCS + * CKM_DSA + * + * The first slot that supports at least one of those mechanisms is chosen as a + * public key slot. + * + * Symmetric ciphers optionally supported + * + * CKM_DES3_CBC + * CKM_DES_CBC + * CKM_AES_CBC + * CKM_DES3_ECB + * CKM_DES_ECB + * CKM_AES_ECB + * CKM_AES_CTR + * CKM_RC4 + * CKM_BLOWFISH_CBC + * + * Digests optionally supported + * + * CKM_MD5 + * CKM_SHA_1 + * CKM_SHA224 + * CKM_SHA256 + * CKM_SHA384 + * CKM_SHA512 + * + * The output of this function is a set of global variables indicating which + * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of + * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global + * variables carry information about which slot was chosen for (a) public key + * mechanisms, (b) random operations, and (c) symmetric ciphers and digests. + */ +static int +pk11_choose_slots(int *any_slot_found) + { + CK_SLOT_ID_PTR pSlotList = NULL_PTR; + CK_ULONG ulSlotCount = 0; + CK_MECHANISM_INFO mech_info; + CK_TOKEN_INFO token_info; + int i; + CK_RV rv; + CK_SLOT_ID best_pubkey_slot_sofar; +#ifdef DEBUG_SLOT_SELECTION + CK_SLOT_ID best_cd_slot_sofar; +#endif + int slot_n_cipher = -1; + int slot_n_digest = -1; + CK_SLOT_ID current_slot = 0; + int current_slot_n_cipher = 0; + int current_slot_n_digest = 0; + int best_number_of_mechs = 0; + int current_number_of_mechs = 0; + int local_cipher_nids[PK11_CIPHER_MAX]; + int local_digest_nids[PK11_DIGEST_MAX]; + + /* let's initialize the output parameter */ + if (any_slot_found != NULL) + *any_slot_found = 0; + + /* Get slot list for memory allocation */ + rv = pFuncList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); + return (0); + } + + /* it's not an error if we didn't find any providers */ + if (ulSlotCount == 0) + { + DEBUG_SLOT_SEL("%s: no crypto providers found\n", PK11_DBG); + return (1); + } + + pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); + + if (pSlotList == NULL) + { + PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE); + return (0); + } + + /* Get the slot list for processing */ + rv = pFuncList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); + OPENSSL_free(pSlotList); + return (0); + } + + DEBUG_SLOT_SEL("%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME); + DEBUG_SLOT_SEL("%s: number of slots: %d\n", PK11_DBG, ulSlotCount); + + pubkey_SLOTID = pSlotList[0]; + for (i = 0; i < ulSlotCount; i++) + { + CK_BBOOL slot_has_rsa = CK_FALSE; + CK_BBOOL slot_has_dsa = CK_FALSE; + CK_BBOOL slot_has_dh = CK_FALSE; + current_slot = pSlotList[i]; + + DEBUG_SLOT_SEL("%s: == checking slot: %d ==\n", PK11_DBG, + current_slot); + rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); + if (rv != CKR_OK) + continue; + + DEBUG_SLOT_SEL("%s: token label: %.32s\n", PK11_DBG, + token_info.label); + + DEBUG_SLOT_SEL("%s: checking rand slots\n", PK11_DBG); + + if (((token_info.flags & CKF_RNG) != 0) && !pk11_have_random) + { + DEBUG_SLOT_SEL( + "%s: this token has CKF_RNG flag\n", PK11_DBG); + pk11_have_random = CK_TRUE; + rand_SLOTID = current_slot; + } + + DEBUG_SLOT_SEL("%s: checking pubkey slots\n", PK11_DBG); + current_number_of_mechs = 0; + +#ifndef OPENSSL_NO_RSA + /* + * Check if this slot is capable of signing and + * verifying with CKM_RSA_PKCS. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS, + &mech_info); + + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && + (mech_info.flags & CKF_VERIFY))) + { + /* + * Check if this slot is capable of encryption, + * decryption, sign, and verify with CKM_RSA_X_509. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, + CKM_RSA_X_509, &mech_info); + + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && + (mech_info.flags & CKF_VERIFY) && + (mech_info.flags & CKF_ENCRYPT) && + (mech_info.flags & CKF_VERIFY_RECOVER) && + (mech_info.flags & CKF_DECRYPT))) + { + slot_has_rsa = CK_TRUE; + current_number_of_mechs++; + } + } +#endif /* OPENSSL_NO_RSA */ + +#ifndef OPENSSL_NO_DSA + /* + * Check if this slot is capable of signing and + * verifying with CKM_DSA. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA, + &mech_info); + if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && + (mech_info.flags & CKF_VERIFY))) + { + slot_has_dsa = CK_TRUE; + current_number_of_mechs++; + } + +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_DH + /* + * Check if this slot is capable of DH key generataion and + * derivation. + */ + rv = pFuncList->C_GetMechanismInfo(current_slot, + CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info); + + if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR)) + { + rv = pFuncList->C_GetMechanismInfo(current_slot, + CKM_DH_PKCS_DERIVE, &mech_info); + if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE)) + { + slot_has_dh = CK_TRUE; + current_number_of_mechs++; + } + } +#endif /* OPENSSL_NO_DH */ + + if (current_number_of_mechs > best_number_of_mechs) + { + best_pubkey_slot_sofar = current_slot; + pk11_have_rsa = slot_has_rsa; + pk11_have_dsa = slot_has_dsa; + pk11_have_dh = slot_has_dh; + best_number_of_mechs = current_number_of_mechs; + /* + * Cache the flags for later use. We might need those if + * RSA keys by reference feature is used. + */ + pubkey_token_flags = token_info.flags; + DEBUG_SLOT_SEL("%s: pubkey flags changed to " + "%lu.\n", PK11_DBG, pubkey_token_flags); + } + + DEBUG_SLOT_SEL("%s: checking cipher/digest\n", PK11_DBG); + + current_slot_n_cipher = 0; + current_slot_n_digest = 0; + (void) memset(local_cipher_nids, 0, sizeof (local_cipher_nids)); + (void) memset(local_digest_nids, 0, sizeof (local_digest_nids)); + + pk11_find_symmetric_ciphers(pFuncList, current_slot, + ¤t_slot_n_cipher, local_cipher_nids); + + pk11_find_digests(pFuncList, current_slot, + ¤t_slot_n_digest, local_digest_nids); + + DEBUG_SLOT_SEL("%s: current_slot_n_cipher %d\n", PK11_DBG, + current_slot_n_cipher); + DEBUG_SLOT_SEL("%s: current_slot_n_digest %d\n", PK11_DBG, + current_slot_n_digest); + + /* + * If the current slot supports more ciphers/digests than + * the previous best one we change the current best to this one, + * otherwise leave it where it is. + */ + if ((current_slot_n_cipher + current_slot_n_digest) > + (slot_n_cipher + slot_n_digest)) + { + DEBUG_SLOT_SEL("%s: changing best slot to %d\n", + PK11_DBG, current_slot); + SLOTID = current_slot; +#ifdef DEBUG_SLOT_SELECTION + best_cd_slot_sofar = current_slot; +#endif + cipher_count = slot_n_cipher = current_slot_n_cipher; + digest_count = slot_n_digest = current_slot_n_digest; + (void) memcpy(cipher_nids, local_cipher_nids, + sizeof (local_cipher_nids)); + (void) memcpy(digest_nids, local_digest_nids, + sizeof (local_digest_nids)); + } + + DEBUG_SLOT_SEL("%s: best cipher/digest slot so far: %d\n", + PK11_DBG, best_cd_slot_sofar); + } + + if (best_number_of_mechs == 0) + { + DEBUG_SLOT_SEL("%s: no rsa/dsa/dh\n", PK11_DBG); + } + else + { + pubkey_SLOTID = best_pubkey_slot_sofar; + } + + DEBUG_SLOT_SEL("%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID); + DEBUG_SLOT_SEL("%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID); + DEBUG_SLOT_SEL("%s: chosen cipher/digest slot: %d\n", PK11_DBG, SLOTID); + DEBUG_SLOT_SEL("%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa); + DEBUG_SLOT_SEL("%s: pk11_have_dsa %d\n", PK11_DBG, pk11_have_dsa); + DEBUG_SLOT_SEL("%s: pk11_have_dh %d\n", PK11_DBG, pk11_have_dh); + DEBUG_SLOT_SEL("%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random); + DEBUG_SLOT_SEL("%s: cipher_count %d\n", PK11_DBG, cipher_count); + DEBUG_SLOT_SEL("%s: digest_count %d\n", PK11_DBG, digest_count); + + if (pSlotList != NULL) + OPENSSL_free(pSlotList); + +#ifdef SOLARIS_HW_SLOT_SELECTION + OPENSSL_free(hw_cnids); + OPENSSL_free(hw_dnids); +#endif /* SOLARIS_HW_SLOT_SELECTION */ + + if (any_slot_found != NULL) + *any_slot_found = 1; + return (1); + } + +static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR pflist, + int slot_id, int *current_slot_n_cipher, int *local_cipher_nids, + PK11_CIPHER *cipher) + { + static CK_MECHANISM_INFO mech_info; + static CK_RV rv; + static CK_MECHANISM_TYPE last_checked_mech = (CK_MECHANISM_TYPE)-1; + + DEBUG_SLOT_SEL("%s: checking mech: %x", PK11_DBG, cipher->mech_type); + if (cipher->mech_type != last_checked_mech) + { + rv = pflist->C_GetMechanismInfo(slot_id, cipher->mech_type, + &mech_info); + } + + last_checked_mech = cipher->mech_type; + + if (rv != CKR_OK) + { + DEBUG_SLOT_SEL(" not found\n"); + return; + } + + if ((mech_info.flags & CKF_ENCRYPT) && + (mech_info.flags & CKF_DECRYPT)) + { + if (mech_info.ulMinKeySize > cipher->min_key_len || + mech_info.ulMaxKeySize < cipher->max_key_len) + { + DEBUG_SLOT_SEL(" engine key size range <%i-%i> does not" + " match mech range <%lu-%lu>\n", + cipher->min_key_len, cipher->max_key_len, + mech_info.ulMinKeySize, mech_info.ulMaxKeySize); + return; + } +#ifdef SOLARIS_HW_SLOT_SELECTION + if (nid_in_table(cipher->nid, hw_cnids)) +#endif /* SOLARIS_HW_SLOT_SELECTION */ + { + DEBUG_SLOT_SEL(" usable\n"); + local_cipher_nids[(*current_slot_n_cipher)++] = + cipher->nid; + } +#ifdef SOLARIS_HW_SLOT_SELECTION + else + { + DEBUG_SLOT_SEL( + " rejected, software implementation only\n"); + } +#endif /* SOLARIS_HW_SLOT_SELECTION */ + } + else + { + DEBUG_SLOT_SEL(" unusable\n"); + } + + return; + } + +static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id, + int *current_slot_n_digest, int *local_digest_nids, PK11_DIGEST *digest) + { + CK_MECHANISM_INFO mech_info; + CK_RV rv; + + DEBUG_SLOT_SEL("%s: checking mech: %x", PK11_DBG, digest->mech_type); + rv = pflist->C_GetMechanismInfo(slot_id, digest->mech_type, &mech_info); + + if (rv != CKR_OK) + { + DEBUG_SLOT_SEL(" not found\n"); + return; + } + + if (mech_info.flags & CKF_DIGEST) + { +#ifdef SOLARIS_HW_SLOT_SELECTION + if (nid_in_table(digest->nid, hw_dnids)) +#endif /* SOLARIS_HW_SLOT_SELECTION */ + { + DEBUG_SLOT_SEL(" usable\n"); + local_digest_nids[(*current_slot_n_digest)++] = + digest->nid; + } +#ifdef SOLARIS_HW_SLOT_SELECTION + else + { + DEBUG_SLOT_SEL( + " rejected, software implementation only\n"); + } +#endif /* SOLARIS_HW_SLOT_SELECTION */ + } + else + { + DEBUG_SLOT_SEL(" unusable\n"); + } + + return; + } + +#ifdef SOLARIS_AES_CTR +/* create a new NID when we have no OID for that mechanism */ +static int pk11_add_NID(char *sn, char *ln) + { + ASN1_OBJECT *o; + int nid; + + if ((o = ASN1_OBJECT_create(OBJ_new_nid(1), (unsigned char *)"", + 1, sn, ln)) == NULL) + { + return (0); + } + + /* will return NID_undef on error */ + nid = OBJ_add_object(o); + ASN1_OBJECT_free(o); + + return (nid); + } + +/* + * Create new NIDs for AES counter mode. OpenSSL doesn't support them now so we + * have to help ourselves here. + */ +static int pk11_add_aes_ctr_NIDs(void) + { + /* are we already set? */ + if (NID_aes_256_ctr != NID_undef) + return (1); + + /* + * There are no official names for AES counter modes yet so we just + * follow the format of those that exist. + */ + if ((NID_aes_128_ctr = pk11_add_NID("AES-128-CTR", "aes-128-ctr")) == + NID_undef) + goto err; + ciphers[PK11_AES_128_CTR].nid = pk11_aes_128_ctr.nid = NID_aes_128_ctr; + if ((NID_aes_192_ctr = pk11_add_NID("AES-192-CTR", "aes-192-ctr")) == + NID_undef) + goto err; + ciphers[PK11_AES_192_CTR].nid = pk11_aes_192_ctr.nid = NID_aes_192_ctr; + if ((NID_aes_256_ctr = pk11_add_NID("AES-256-CTR", "aes-256-ctr")) == + NID_undef) + goto err; + ciphers[PK11_AES_256_CTR].nid = pk11_aes_256_ctr.nid = NID_aes_256_ctr; + return (1); + +err: + PK11err(PK11_F_ADD_AES_CTR_NIDS, PK11_R_ADD_NID_FAILED); + return (0); + } +#endif /* SOLARIS_AES_CTR */ + +/* Find what symmetric ciphers this slot supports. */ +static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_cipher, int *local_cipher_nids) + { + int i; + + for (i = 0; i < PK11_CIPHER_MAX; ++i) + { + pk11_get_symmetric_cipher(pflist, current_slot, + current_slot_n_cipher, local_cipher_nids, &ciphers[i]); + } + } + +/* Find what digest algorithms this slot supports. */ +static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist, + CK_SLOT_ID current_slot, int *current_slot_n_digest, int *local_digest_nids) + { + int i; + + for (i = 0; i < PK11_DIGEST_MAX; ++i) + { + pk11_get_digest(pflist, current_slot, current_slot_n_digest, + local_digest_nids, &digests[i]); + } + } + +#ifdef SOLARIS_HW_SLOT_SELECTION +/* + * It would be great if we could use pkcs11_kernel directly since this library + * offers hardware slots only. That's the easiest way to achieve the situation + * where we use the hardware accelerators when present and OpenSSL native code + * otherwise. That presumes the fact that OpenSSL native code is faster than the + * code in the soft token. It's a logical assumption - Crypto Framework has some + * inherent overhead so going there for the software implementation of a + * mechanism should be logically slower in contrast to the OpenSSL native code, + * presuming that both implementations are of similar speed. For example, the + * soft token for AES is roughly three times slower than OpenSSL for 64 byte + * blocks and still 20% slower for 8KB blocks. So, if we want to ship products + * that use the PKCS#11 engine by default, we must somehow avoid that regression + * on machines without hardware acceleration. That's why switching to the + * pkcs11_kernel library seems like a very good idea. + * + * The problem is that OpenSSL built with SunStudio is roughly 2x slower for + * asymmetric operations (RSA/DSA/DH) than the soft token built with the same + * compiler. That means that if we switched to pkcs11_kernel from the libpkcs11 + * library, we would have had a performance regression on machines without + * hardware acceleration for asymmetric operations for all applications that use + * the PKCS#11 engine. There is one such application - Apache web server since + * it's shipped configured to use the PKCS#11 engine by default. Having said + * that, we can't switch to the pkcs11_kernel library now and have to come with + * a solution that, on non-accelerated machines, uses the OpenSSL native code + * for all symmetric ciphers and digests while it uses the soft token for + * asymmetric operations. + * + * This is the idea: dlopen() pkcs11_kernel directly and find out what + * mechanisms are there. We don't care about duplications (more slots can + * support the same mechanism), we just want to know what mechanisms can be + * possibly supported in hardware on that particular machine. As said before, + * pkcs11_kernel will show you hardware providers only. + * + * Then, we rely on the fact that since we use libpkcs11 library we will find + * the metaslot. When we go through the metaslot's mechanisms for symmetric + * ciphers and digests, we check that any found mechanism is in the table + * created using the pkcs11_kernel library. So, as a result we have two arrays + * of mechanisms that were advertised as supported in hardware which was the + * goal of that whole exercise. Thus, we can use libpkcs11 but avoid soft token + * code for symmetric ciphers and digests. See pk11_choose_slots() for more + * information. + * + * This is Solaris specific code, if SOLARIS_HW_SLOT_SELECTION is not defined + * the code won't be used. + */ +#if defined(__sparcv9) || defined(__x86_64) || defined(__amd64) +static const char pkcs11_kernel[] = "/usr/lib/security/64/pkcs11_kernel.so.1"; +#else +static const char pkcs11_kernel[] = "/usr/lib/security/pkcs11_kernel.so.1"; +#endif + +/* + * Check hardware capabilities of the machines. The output are two lists, + * hw_cnids and hw_dnids, that contain hardware mechanisms found in all hardware + * providers together. They are not sorted and may contain duplicate mechanisms. + */ +static int check_hw_mechanisms(void) + { + int i; + CK_RV rv; + void *handle; + CK_C_GetFunctionList p; + CK_TOKEN_INFO token_info; + CK_ULONG ulSlotCount = 0; + int n_cipher = 0, n_digest = 0; + CK_FUNCTION_LIST_PTR pflist = NULL; + CK_SLOT_ID_PTR pSlotList = NULL_PTR; + int *tmp_hw_cnids = NULL, *tmp_hw_dnids = NULL; + int hw_ctable_size, hw_dtable_size; + + DEBUG_SLOT_SEL("%s: SOLARIS_HW_SLOT_SELECTION code running\n", + PK11_DBG); + /* + * Use RTLD_GROUP to limit the pkcs11_kernel provider to its own + * symbols, which prevents it from mistakenly accessing C_* functions + * from the top-level PKCS#11 library. + */ + if ((handle = dlopen(pkcs11_kernel, RTLD_LAZY | RTLD_GROUP)) == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); + goto err; + } + + if ((p = (CK_C_GetFunctionList)dlsym(handle, + PK11_GET_FUNCTION_LIST)) == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); + goto err; + } + + /* get the full function list from the loaded library */ + if (p(&pflist) != CKR_OK) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); + goto err; + } + + rv = pflist->C_Initialize(NULL_PTR); + if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) + { + PK11err_add_data(PK11_F_CHECK_HW_MECHANISMS, + PK11_R_INITIALIZE, rv); + goto err; + } + + if (pflist->C_GetSlotList(0, NULL_PTR, &ulSlotCount) != CKR_OK) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); + goto err; + } + + /* no slots, set the hw mechanism tables as empty */ + if (ulSlotCount == 0) + { + DEBUG_SLOT_SEL("%s: no hardware mechanisms found\n", PK11_DBG); + hw_cnids = OPENSSL_malloc(sizeof (int)); + hw_dnids = OPENSSL_malloc(sizeof (int)); + if (hw_cnids == NULL || hw_dnids == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, + PK11_R_MALLOC_FAILURE); + return (0); + } + /* this means empty tables */ + hw_cnids[0] = NID_undef; + hw_dnids[0] = NID_undef; + return (1); + } + + pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); + if (pSlotList == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* Get the slot list for processing */ + if (pflist->C_GetSlotList(0, pSlotList, &ulSlotCount) != CKR_OK) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); + goto err; + } + + /* + * We don't care about duplicate mechanisms in multiple slots and also + * reserve one slot for the terminal NID_undef which we use to stop the + * search. + */ + hw_ctable_size = ulSlotCount * PK11_CIPHER_MAX + 1; + hw_dtable_size = ulSlotCount * PK11_DIGEST_MAX + 1; + tmp_hw_cnids = OPENSSL_malloc(hw_ctable_size * sizeof (int)); + tmp_hw_dnids = OPENSSL_malloc(hw_dtable_size * sizeof (int)); + if (tmp_hw_cnids == NULL || tmp_hw_dnids == NULL) + { + PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* + * Do not use memset since we should not rely on the fact that NID_undef + * is zero now. + */ + for (i = 0; i < hw_ctable_size; ++i) + tmp_hw_cnids[i] = NID_undef; + for (i = 0; i < hw_dtable_size; ++i) + tmp_hw_dnids[i] = NID_undef; + + DEBUG_SLOT_SEL("%s: provider: %s\n", PK11_DBG, pkcs11_kernel); + DEBUG_SLOT_SEL("%s: found %d hardware slots\n", PK11_DBG, ulSlotCount); + DEBUG_SLOT_SEL("%s: now looking for mechs supported in hw\n", + PK11_DBG); + + for (i = 0; i < ulSlotCount; i++) + { + if (pflist->C_GetTokenInfo(pSlotList[i], &token_info) != CKR_OK) + continue; + + DEBUG_SLOT_SEL("%s: token label: %.32s\n", PK11_DBG, + token_info.label); + + /* + * We are filling the hw mech tables here. Global tables are + * still NULL so all mechanisms are put into tmp tables. + */ + pk11_find_symmetric_ciphers(pflist, pSlotList[i], + &n_cipher, tmp_hw_cnids); + pk11_find_digests(pflist, pSlotList[i], + &n_digest, tmp_hw_dnids); + } + + /* + * Since we are part of a library (libcrypto.so), calling this function + * may have side-effects. Also, C_Finalize() is triggered by + * dlclose(3C). + */ +#if 0 + pflist->C_Finalize(NULL); +#endif + OPENSSL_free(pSlotList); + (void) dlclose(handle); + hw_cnids = tmp_hw_cnids; + hw_dnids = tmp_hw_dnids; + + DEBUG_SLOT_SEL("%s: hw mechs check complete\n", PK11_DBG); + return (1); + +err: + if (pSlotList != NULL) + OPENSSL_free(pSlotList); + if (tmp_hw_cnids != NULL) + OPENSSL_free(tmp_hw_cnids); + if (tmp_hw_dnids != NULL) + OPENSSL_free(tmp_hw_dnids); + + return (0); + } + +/* + * Check presence of a NID in the table of NIDs. The table may be NULL (i.e., + * non-existent). + */ +static int nid_in_table(int nid, int *nid_table) + { + int i = 0; + + /* + * a special case. NULL means that we are initializing a new + * table. + */ + if (nid_table == NULL) + return (1); + + /* + * the table is never full, there is always at least one + * NID_undef. + */ + while (nid_table[i] != NID_undef) + { + if (nid_table[i++] == nid) + { + DEBUG_SLOT_SEL(" (NID %d in hw table, idx %d)", nid, i); + return (1); + } + } + + return (0); + } +#endif /* SOLARIS_HW_SLOT_SELECTION */ + +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/engines/pkcs11/hw_pk11.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/engines/pkcs11/hw_pk11.h Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. + * + */ + +/* crypto/engine/hw_pk11.h */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HW_PK11_H +#define HW_PK11_H + +#include "hw_pk11_err.h" + +/* max byte length of a symetric key we support */ +#define PK11_KEY_LEN_MAX 32 + +/* + * This structure encapsulates all reusable information for a PKCS#11 + * session. A list of these objects is created on behalf of the + * calling application using an on-demand method. Each operation + * type (see PK11_OPTYPE below) has its own per-process list. + * Each of the lists is basically a cache for faster PKCS#11 object + * access to avoid expensive C_Find{,Init,Final}Object() calls. + * + * When a new request comes in, an object will be taken from the list + * (if there is one) or a new one is created to handle the request + * (if the list is empty). See pk11_get_session() on how it is done. + */ +typedef struct PK11_st_SESSION + { + struct PK11_st_SESSION *next; + CK_SESSION_HANDLE session; /* PK11 session handle */ + pid_t pid; /* Current process ID */ + CK_BBOOL persistent; /* is that a keystore object? */ + union + { +#ifndef OPENSSL_NO_RSA + struct + { + CK_OBJECT_HANDLE rsa_pub_key; /* pub handle */ + CK_OBJECT_HANDLE rsa_priv_key; /* priv handle */ + RSA *rsa_pub; /* pub key addr */ + BIGNUM *rsa_n_num; /* pub modulus */ + BIGNUM *rsa_e_num; /* pub exponent */ + RSA *rsa_priv; /* priv key addr */ + BIGNUM *rsa_d_num; /* priv exponent */ + } u_RSA; +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA + struct + { + CK_OBJECT_HANDLE dsa_pub_key; /* pub handle */ + CK_OBJECT_HANDLE dsa_priv_key; /* priv handle */ + DSA *dsa_pub; /* pub key addr */ + BIGNUM *dsa_pub_num; /* pub key */ + DSA *dsa_priv; /* priv key addr */ + BIGNUM *dsa_priv_num; /* priv key */ + } u_DSA; +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH + struct + { + CK_OBJECT_HANDLE dh_key; /* key handle */ + DH *dh; /* dh key addr */ + BIGNUM *dh_priv_num; /* priv dh key */ + } u_DH; +#endif /* OPENSSL_NO_DH */ + struct + { + CK_OBJECT_HANDLE cipher_key; /* key handle */ + unsigned char key[PK11_KEY_LEN_MAX]; + int key_len; /* priv key len */ + int encrypt; /* 1/0 enc/decr */ + } u_cipher; + } opdata_u; + } PK11_SESSION; + +#define opdata_rsa_pub_key opdata_u.u_RSA.rsa_pub_key +#define opdata_rsa_priv_key opdata_u.u_RSA.rsa_priv_key +#define opdata_rsa_pub opdata_u.u_RSA.rsa_pub +#define opdata_rsa_priv opdata_u.u_RSA.rsa_priv +#define opdata_rsa_n_num opdata_u.u_RSA.rsa_n_num +#define opdata_rsa_e_num opdata_u.u_RSA.rsa_e_num +#define opdata_rsa_d_num opdata_u.u_RSA.rsa_d_num +#define opdata_dsa_pub_key opdata_u.u_DSA.dsa_pub_key +#define opdata_dsa_priv_key opdata_u.u_DSA.dsa_priv_key +#define opdata_dsa_pub opdata_u.u_DSA.dsa_pub +#define opdata_dsa_pub_num opdata_u.u_DSA.dsa_pub_num +#define opdata_dsa_priv opdata_u.u_DSA.dsa_priv +#define opdata_dsa_priv_num opdata_u.u_DSA.dsa_priv_num +#define opdata_dh_key opdata_u.u_DH.dh_key +#define opdata_dh opdata_u.u_DH.dh +#define opdata_dh_priv_num opdata_u.u_DH.dh_priv_num +#define opdata_cipher_key opdata_u.u_cipher.cipher_key +#define opdata_key opdata_u.u_cipher.key +#define opdata_key_len opdata_u.u_cipher.key_len +#define opdata_encrypt opdata_u.u_cipher.encrypt + +/* + * We have 3 different groups of operation types: + * 1) asymmetric operations + * 2) random operations + * 3) symmetric and digest operations + * + * This division into groups stems from the fact that it's common that hardware + * providers may support operations from one group only. For example, hardware + * providers on UltraSPARC T2, n2rng(7d), ncp(7d), and n2cp(7d), each support + * only a single group of operations. + * + * For every group a different slot can be chosen. That means that we must have + * at least 3 different lists of cached PKCS#11 sessions since sessions from + * different groups may be initialized in different slots. + * + * To provide locking granularity in multithreaded environment, the groups are + * further splitted into types with each type having a separate session cache. + */ +typedef enum PK11_OPTYPE_ENUM + { + OP_RAND, + OP_RSA, + OP_DSA, + OP_DH, + OP_CIPHER, + OP_DIGEST, + OP_MAX + } PK11_OPTYPE; + +/* + * This structure contains the heads of the lists forming the object caches + * and locks associated with the lists. + */ +typedef struct PK11_st_CACHE + { + PK11_SESSION *head; + pthread_mutex_t *lock; + } PK11_CACHE; + +/* structure for tracking handles of asymmetric key objects */ +typedef struct PK11_active_st + { + CK_OBJECT_HANDLE h; + unsigned int refcnt; + struct PK11_active_st *prev; + struct PK11_active_st *next; + } PK11_active; + +extern pthread_mutex_t *find_lock[]; +extern PK11_active *active_list[]; +/* + * These variables are specific for the RSA keys by reference code. See + * hw_pk11_pub.c for explanation. + */ +extern char *passphrasedialog; +extern CK_FLAGS pubkey_token_flags; + +#define LOCK_OBJSTORE(alg_type) \ + (void) pthread_mutex_lock(find_lock[alg_type]) +#define UNLOCK_OBJSTORE(alg_type) \ + (void) pthread_mutex_unlock(find_lock[alg_type]) + +extern PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); +extern void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); + +#ifndef OPENSSL_NO_RSA +extern int pk11_destroy_rsa_key_objects(PK11_SESSION *session); +extern int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +extern int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +extern EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data); +extern EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file, + UI_METHOD *ui_method, void *callback_data); +extern RSA_METHOD *PK11_RSA(void); +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA +extern int pk11_destroy_dsa_key_objects(PK11_SESSION *session); +extern int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); +extern int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); +extern DSA_METHOD *PK11_DSA(void); +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH +extern int pk11_destroy_dh_key_objects(PK11_SESSION *session); +extern int pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock); +extern DH_METHOD *PK11_DH(void); +#endif /* OPENSSL_NO_DH */ + +extern CK_FUNCTION_LIST_PTR pFuncList; + +#endif /* HW_PK11_H */ diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/engines/pkcs11/hw_pk11_err.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/engines/pkcs11/hw_pk11_err.c Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. + * + */ + +/* crypto/engine/hw_pk11_err.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include "hw_pk11_err.h" + +/* BEGIN ERROR CODES */ +#ifndef OPENSSL_NO_ERR +static ERR_STRING_DATA pk11_str_functs[]= +{ +{ ERR_PACK(0, PK11_F_INIT, 0), "PK11_INIT"}, +{ ERR_PACK(0, PK11_F_FINISH, 0), "PK11_FINISH"}, +{ ERR_PACK(0, PK11_F_DESTROY, 0), "PK11_DESTROY"}, +{ ERR_PACK(0, PK11_F_CTRL, 0), "PK11_CTRL"}, +{ ERR_PACK(0, PK11_F_RSA_INIT, 0), "PK11_RSA_INIT"}, +{ ERR_PACK(0, PK11_F_RSA_FINISH, 0), "PK11_RSA_FINISH"}, +{ ERR_PACK(0, PK11_F_GET_PUB_RSA_KEY, 0), "PK11_GET_PUB_RSA_KEY"}, +{ ERR_PACK(0, PK11_F_GET_PRIV_RSA_KEY, 0), "PK11_GET_PRIV_RSA_KEY"}, +{ ERR_PACK(0, PK11_F_RSA_GEN_KEY, 0), "PK11_RSA_GEN_KEY"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_ENC, 0), "PK11_RSA_PUB_ENC"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC, 0), "PK11_RSA_PRIV_ENC"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_DEC, 0), "PK11_RSA_PUB_DEC"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC, 0), "PK11_RSA_PRIV_DEC"}, +{ ERR_PACK(0, PK11_F_RSA_SIGN, 0), "PK11_RSA_SIGN"}, +{ ERR_PACK(0, PK11_F_RSA_VERIFY, 0), "PK11_RSA_VERIFY"}, +{ ERR_PACK(0, PK11_F_RAND_ADD, 0), "PK11_RAND_ADD"}, +{ ERR_PACK(0, PK11_F_RAND_BYTES, 0), "PK11_RAND_BYTES"}, +{ ERR_PACK(0, PK11_F_GET_SESSION, 0), "PK11_GET_SESSION"}, +{ ERR_PACK(0, PK11_F_FREE_SESSION, 0), "PK11_FREE_SESSION"}, +{ ERR_PACK(0, PK11_F_LOAD_PUBKEY, 0), "PK11_LOAD_PUBKEY"}, +{ ERR_PACK(0, PK11_F_LOAD_PRIVKEY, 0), "PK11_LOAD_PRIV_KEY"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_ENC_LOW, 0), "PK11_RSA_PUB_ENC_LOW"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC_LOW, 0), "PK11_RSA_PRIV_ENC_LOW"}, +{ ERR_PACK(0, PK11_F_RSA_PUB_DEC_LOW, 0), "PK11_RSA_PUB_DEC_LOW"}, +{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC_LOW, 0), "PK11_RSA_PRIV_DEC_LOW"}, +{ ERR_PACK(0, PK11_F_DSA_SIGN, 0), "PK11_DSA_SIGN"}, +{ ERR_PACK(0, PK11_F_DSA_VERIFY, 0), "PK11_DSA_VERIFY"}, +{ ERR_PACK(0, PK11_F_DSA_INIT, 0), "PK11_DSA_INIT"}, +{ ERR_PACK(0, PK11_F_DSA_FINISH, 0), "PK11_DSA_FINISH"}, +{ ERR_PACK(0, PK11_F_GET_PUB_DSA_KEY, 0), "PK11_GET_PUB_DSA_KEY"}, +{ ERR_PACK(0, PK11_F_GET_PRIV_DSA_KEY, 0), "PK11_GET_PRIV_DSA_KEY"}, +{ ERR_PACK(0, PK11_F_DH_INIT, 0), "PK11_DH_INIT"}, +{ ERR_PACK(0, PK11_F_DH_FINISH, 0), "PK11_DH_FINISH"}, +{ ERR_PACK(0, PK11_F_MOD_EXP_DH, 0), "PK11_MOD_EXP_DH"}, +{ ERR_PACK(0, PK11_F_GET_DH_KEY, 0), "PK11_GET_DH_KEY"}, +{ ERR_PACK(0, PK11_F_FREE_ALL_SESSIONS, 0), "PK11_FREE_ALL_SESSIONS"}, +{ ERR_PACK(0, PK11_F_SETUP_SESSION, 0), "PK11_SETUP_SESSION"}, +{ ERR_PACK(0, PK11_F_DESTROY_OBJECT, 0), "PK11_DESTROY_OBJECT"}, +{ ERR_PACK(0, PK11_F_CIPHER_INIT, 0), "PK11_CIPHER_INIT"}, +{ ERR_PACK(0, PK11_F_CIPHER_DO_CIPHER, 0), "PK11_CIPHER_DO_CIPHER"}, +{ ERR_PACK(0, PK11_F_GET_CIPHER_KEY, 0), "PK11_GET_CIPHER_KEY"}, +{ ERR_PACK(0, PK11_F_DIGEST_INIT, 0), "PK11_DIGEST_INIT"}, +{ ERR_PACK(0, PK11_F_DIGEST_UPDATE, 0), "PK11_DIGEST_UPDATE"}, +{ ERR_PACK(0, PK11_F_DIGEST_FINAL, 0), "PK11_DIGEST_FINAL"}, +{ ERR_PACK(0, PK11_F_CHOOSE_SLOT, 0), "PK11_CHOOSE_SLOT"}, +{ ERR_PACK(0, PK11_F_CIPHER_FINAL, 0), "PK11_CIPHER_FINAL"}, +{ ERR_PACK(0, PK11_F_LIBRARY_INIT, 0), "PK11_LIBRARY_INIT"}, +{ ERR_PACK(0, PK11_F_LOAD, 0), "ENGINE_LOAD_PK11"}, +{ ERR_PACK(0, PK11_F_DH_GEN_KEY, 0), "PK11_DH_GEN_KEY"}, +{ ERR_PACK(0, PK11_F_DH_COMP_KEY, 0), "PK11_DH_COMP_KEY"}, +{ ERR_PACK(0, PK11_F_DIGEST_COPY, 0), "PK11_DIGEST_COPY"}, +{ ERR_PACK(0, PK11_F_CIPHER_CLEANUP, 0), "PK11_CIPHER_CLEANUP"}, +{ ERR_PACK(0, PK11_F_ACTIVE_ADD, 0), "PK11_ACTIVE_ADD"}, +{ ERR_PACK(0, PK11_F_ACTIVE_DELETE, 0), "PK11_ACTIVE_DELETE"}, +{ ERR_PACK(0, PK11_F_CHECK_HW_MECHANISMS, 0), "PK11_CHECK_HW_MECHANISMS"}, +{ ERR_PACK(0, PK11_F_INIT_SYMMETRIC, 0), "PK11_INIT_SYMMETRIC"}, +{ ERR_PACK(0, PK11_F_ADD_AES_CTR_NIDS, 0), "PK11_ADD_AES_CTR_NIDS"}, +{ ERR_PACK(0, PK11_F_INIT_ALL_LOCKS, 0), "PK11_INIT_ALL_LOCKS"}, +{ ERR_PACK(0, PK11_F_RETURN_SESSION, 0), "PK11_RETURN_SESSION"}, +{ ERR_PACK(0, PK11_F_GET_PIN, 0), "PK11_GET_PIN"}, +{ ERR_PACK(0, PK11_F_FIND_ONE_OBJECT, 0), "PK11_FIND_ONE_OBJECT"}, +{ ERR_PACK(0, PK11_F_CHECK_TOKEN_ATTRS, 0), "PK11_CHECK_TOKEN_ATTRS"}, +{ ERR_PACK(0, PK11_F_CACHE_PIN, 0), "PK11_CACHE_PIN"}, +{ ERR_PACK(0, PK11_F_MLOCK_PIN_IN_MEMORY, 0), "PK11_MLOCK_PIN_IN_MEMORY"}, +{ ERR_PACK(0, PK11_F_TOKEN_LOGIN, 0), "PK11_TOKEN_LOGIN"}, +{ ERR_PACK(0, PK11_F_TOKEN_RELOGIN, 0), "PK11_TOKEN_RELOGIN"}, +{ ERR_PACK(0, PK11_F_RUN_ASKPASS, 0), "PK11_F_RUN_ASKPASS"}, +{ 0, NULL} +}; + +static ERR_STRING_DATA pk11_str_reasons[]= +{ +{ PK11_R_ALREADY_LOADED, "PKCS#11 DSO already loaded"}, +{ PK11_R_DSO_FAILURE, "unable to load PKCS#11 DSO"}, +{ PK11_R_NOT_LOADED, "PKCS#11 DSO not loaded"}, +{ PK11_R_PASSED_NULL_PARAMETER, "null parameter passed"}, +{ PK11_R_COMMAND_NOT_IMPLEMENTED, "command not implemented"}, +{ PK11_R_INITIALIZE, "C_Initialize failed"}, +{ PK11_R_FINALIZE, "C_Finalize failed"}, +{ PK11_R_GETINFO, "C_GetInfo faile"}, +{ PK11_R_GETSLOTLIST, "C_GetSlotList failed"}, +{ PK11_R_NO_MODULUS_OR_NO_EXPONENT, "no modulus or no exponent"}, +{ PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID, "attr sensitive or invalid"}, +{ PK11_R_GETATTRIBUTVALUE, "C_GetAttributeValue failed"}, +{ PK11_R_NO_MODULUS, "no modulus"}, +{ PK11_R_NO_EXPONENT, "no exponent"}, +{ PK11_R_FINDOBJECTSINIT, "C_FindObjectsInit failed"}, +{ PK11_R_FINDOBJECTS, "C_FindObjects failed"}, +{ PK11_R_FINDOBJECTSFINAL, "C_FindObjectsFinal failed"}, +{ PK11_R_CREATEOBJECT, "C_CreateObject failed"}, +{ PK11_R_DESTROYOBJECT, "C_DestroyObject failed"}, +{ PK11_R_OPENSESSION, "C_OpenSession failed"}, +{ PK11_R_CLOSESESSION, "C_CloseSession failed"}, +{ PK11_R_ENCRYPTINIT, "C_EncryptInit failed"}, +{ PK11_R_ENCRYPT, "C_Encrypt failed"}, +{ PK11_R_SIGNINIT, "C_SignInit failed"}, +{ PK11_R_SIGN, "C_Sign failed"}, +{ PK11_R_DECRYPTINIT, "C_DecryptInit failed"}, +{ PK11_R_DECRYPT, "C_Decrypt failed"}, +{ PK11_R_VERIFYINIT, "C_VerifyRecover failed"}, +{ PK11_R_VERIFY, "C_Verify failed"}, +{ PK11_R_VERIFYRECOVERINIT, "C_VerifyRecoverInit failed"}, +{ PK11_R_VERIFYRECOVER, "C_VerifyRecover failed"}, +{ PK11_R_GEN_KEY, "C_GenerateKeyPair failed"}, +{ PK11_R_SEEDRANDOM, "C_SeedRandom failed"}, +{ PK11_R_GENERATERANDOM, "C_GenerateRandom failed"}, +{ PK11_R_INVALID_MESSAGE_LENGTH, "invalid message length"}, +{ PK11_R_UNKNOWN_ALGORITHM_TYPE, "unknown algorithm type"}, +{ PK11_R_UNKNOWN_ASN1_OBJECT_ID, "unknown asn1 onject id"}, +{ PK11_R_UNKNOWN_PADDING_TYPE, "unknown padding type"}, +{ PK11_R_PADDING_CHECK_FAILED, "padding check failed"}, +{ PK11_R_DIGEST_TOO_BIG, "digest too big"}, +{ PK11_R_MALLOC_FAILURE, "malloc failure"}, +{ PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED, "ctl command not implemented"}, +{ PK11_R_DATA_GREATER_THAN_MOD_LEN, "data is bigger than mod"}, +{ PK11_R_DATA_TOO_LARGE_FOR_MODULUS, "data is too larger for mod"}, +{ PK11_R_MISSING_KEY_COMPONENT, "a dsa component is missing"}, +{ PK11_R_INVALID_SIGNATURE_LENGTH, "invalid signature length"}, +{ PK11_R_INVALID_DSA_SIGNATURE_R, "missing r in dsa verify"}, +{ PK11_R_INVALID_DSA_SIGNATURE_S, "missing s in dsa verify"}, +{ PK11_R_INCONSISTENT_KEY, "inconsistent key type"}, +{ PK11_R_ENCRYPTUPDATE, "C_EncryptUpdate failed"}, +{ PK11_R_DECRYPTUPDATE, "C_DecryptUpdate failed"}, +{ PK11_R_DIGESTINIT, "C_DigestInit failed"}, +{ PK11_R_DIGESTUPDATE, "C_DigestUpdate failed"}, +{ PK11_R_DIGESTFINAL, "C_DigestFinal failed"}, +{ PK11_R_ENCRYPTFINAL, "C_EncryptFinal failed"}, +{ PK11_R_DECRYPTFINAL, "C_DecryptFinal failed"}, +{ PK11_R_NO_PRNG_SUPPORT, "Slot does not support PRNG"}, +{ PK11_R_GETTOKENINFO, "C_GetTokenInfo failed"}, +{ PK11_R_DERIVEKEY, "C_DeriveKey failed"}, +{ PK11_R_GET_OPERATION_STATE, "C_GetOperationState failed"}, +{ PK11_R_SET_OPERATION_STATE, "C_SetOperationState failed"}, +{ PK11_R_INVALID_HANDLE, "invalid PKCS#11 object handle"}, +{ PK11_R_KEY_OR_IV_LEN_PROBLEM, "IV or key length incorrect"}, +{ PK11_R_INVALID_OPERATION_TYPE, "invalid operation type"}, +{ PK11_R_ADD_NID_FAILED, "failed to add NID" }, +{ PK11_R_ATFORK_FAILED, "atfork failed" }, +{ PK11_R_TOKEN_LOGIN_FAILED, "C_Login failed on token" }, +{ PK11_R_MORE_THAN_ONE_OBJECT_FOUND, "more than one object found" }, +{ PK11_R_INVALID_PKCS11_URI, "pkcs11 URI provided is invalid" }, +{ PK11_R_COULD_NOT_READ_PIN, "could not read PIN from terminal" }, +{ PK11_R_PIN_NOT_READ_FROM_COMMAND, "PIN not read from external command" }, +{ PK11_R_COULD_NOT_OPEN_COMMAND, "could not popen dialog command" }, +{ PK11_R_PIPE_FAILED, "pipe failed" }, +{ PK11_R_BAD_PASSPHRASE_SPEC, "bad passphrasedialog specification" }, +{ PK11_R_TOKEN_NOT_INITIALIZED, "token not initialized" }, +{ PK11_R_TOKEN_PIN_NOT_SET, "token PIN required but not set" }, +{ PK11_R_TOKEN_PIN_NOT_PROVIDED, "token PIN required but not provided" }, +{ PK11_R_MISSING_OBJECT_LABEL, "missing mandatory 'object' keyword" }, +{ PK11_R_TOKEN_ATTRS_DO_NOT_MATCH, "token attrs provided do not match" }, +{ PK11_R_PRIV_KEY_NOT_FOUND, "private key not found in keystore" }, +{ PK11_R_NO_OBJECT_FOUND, "specified object not found" }, +{ PK11_R_PIN_CACHING_POLICY_INVALID, "PIN set but caching policy invalid" }, +{ PK11_R_SYSCONF_FAILED, "sysconf failed" }, +{ PK11_R_MMAP_FAILED, "mmap failed" }, +{ PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING, "PROC_LOCK_MEMORY privilege missing" }, +{ PK11_R_MLOCK_FAILED, "mlock failed" }, +{ PK11_R_FORK_FAILED, "fork failed" }, +{ 0, NULL} +}; +#endif /* OPENSSL_NO_ERR */ + +static int pk11_lib_error_code = 0; +static int pk11_error_init = 1; + +#ifdef PK11_ENGINE_LIB_NAME +static ERR_STRING_DATA pk11_engine_lib_name[] = +{ +{0, PK11_ENGINE_LIB_NAME}, +{0, NULL} +}; +#endif + +static void +ERR_load_pk11_strings(void) + { + if (pk11_lib_error_code == 0) + pk11_lib_error_code = ERR_get_next_error_library(); + + if (pk11_error_init) + { + pk11_error_init = 0; +#ifndef OPENSSL_NO_ERR + ERR_load_strings(pk11_lib_error_code, pk11_str_functs); + ERR_load_strings(pk11_lib_error_code, pk11_str_reasons); +#endif + +#ifdef PK11_ENGINE_LIB_NAME + pk11_engine_lib_name->error = + ERR_PACK(pk11_lib_error_code, 0, 0); + ERR_load_strings(0, pk11_engine_lib_name); +#endif + } + } + +static void +ERR_unload_pk11_strings(void) + { + if (pk11_error_init == 0) + { +#ifndef OPENSSL_NO_ERR + ERR_unload_strings(pk11_lib_error_code, pk11_str_functs); + ERR_unload_strings(pk11_lib_error_code, pk11_str_reasons); +#endif + +#ifdef PK11_ENGINE_LIB_NAME + ERR_unload_strings(0, pk11_engine_lib_name); +#endif + + pk11_error_init = 1; + } + } + +void +ERR_pk11_error(int function, int reason, char *file, int line) + { + if (pk11_lib_error_code == 0) + pk11_lib_error_code = ERR_get_next_error_library(); + ERR_PUT_error(pk11_lib_error_code, function, reason, file, line); + } + +void +PK11err_add_data(int function, int reason, CK_RV rv) + { + char tmp_buf[20]; + + PK11err(function, reason); + (void) snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); + ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); + } diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/engines/pkcs11/hw_pk11_err.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/engines/pkcs11/hw_pk11_err.h Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. + * + */ + +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HW_PK11_ERR_H +#define HW_PK11_ERR_H + +void ERR_pk11_error(int function, int reason, char *file, int line); +void PK11err_add_data(int function, int reason, CK_RV rv); +#define PK11err(f, r) ERR_pk11_error((f), (r), __FILE__, __LINE__) + +/* Error codes for the PK11 functions. */ + +/* Function codes. */ + +#define PK11_F_INIT 100 +#define PK11_F_FINISH 101 +#define PK11_F_DESTROY 102 +#define PK11_F_CTRL 103 +#define PK11_F_RSA_INIT 104 +#define PK11_F_RSA_FINISH 105 +#define PK11_F_GET_PUB_RSA_KEY 106 +#define PK11_F_GET_PRIV_RSA_KEY 107 +#define PK11_F_RSA_GEN_KEY 108 +#define PK11_F_RSA_PUB_ENC 109 +#define PK11_F_RSA_PRIV_ENC 110 +#define PK11_F_RSA_PUB_DEC 111 +#define PK11_F_RSA_PRIV_DEC 112 +#define PK11_F_RSA_SIGN 113 +#define PK11_F_RSA_VERIFY 114 +#define PK11_F_RAND_ADD 115 +#define PK11_F_RAND_BYTES 116 +#define PK11_F_GET_SESSION 117 +#define PK11_F_FREE_SESSION 118 +#define PK11_F_LOAD_PUBKEY 119 +#define PK11_F_LOAD_PRIVKEY 120 +#define PK11_F_RSA_PUB_ENC_LOW 121 +#define PK11_F_RSA_PRIV_ENC_LOW 122 +#define PK11_F_RSA_PUB_DEC_LOW 123 +#define PK11_F_RSA_PRIV_DEC_LOW 124 +#define PK11_F_DSA_SIGN 125 +#define PK11_F_DSA_VERIFY 126 +#define PK11_F_DSA_INIT 127 +#define PK11_F_DSA_FINISH 128 +#define PK11_F_GET_PUB_DSA_KEY 129 +#define PK11_F_GET_PRIV_DSA_KEY 130 +#define PK11_F_DH_INIT 131 +#define PK11_F_DH_FINISH 132 +#define PK11_F_MOD_EXP_DH 133 +#define PK11_F_GET_DH_KEY 134 +#define PK11_F_FREE_ALL_SESSIONS 135 +#define PK11_F_SETUP_SESSION 136 +#define PK11_F_DESTROY_OBJECT 137 +#define PK11_F_CIPHER_INIT 138 +#define PK11_F_CIPHER_DO_CIPHER 139 +#define PK11_F_GET_CIPHER_KEY 140 +#define PK11_F_DIGEST_INIT 141 +#define PK11_F_DIGEST_UPDATE 142 +#define PK11_F_DIGEST_FINAL 143 +#define PK11_F_CHOOSE_SLOT 144 +#define PK11_F_CIPHER_FINAL 145 +#define PK11_F_LIBRARY_INIT 146 +#define PK11_F_LOAD 147 +#define PK11_F_DH_GEN_KEY 148 +#define PK11_F_DH_COMP_KEY 149 +#define PK11_F_DIGEST_COPY 150 +#define PK11_F_CIPHER_CLEANUP 151 +#define PK11_F_ACTIVE_ADD 152 +#define PK11_F_ACTIVE_DELETE 153 +#define PK11_F_CHECK_HW_MECHANISMS 154 +#define PK11_F_INIT_SYMMETRIC 155 +#define PK11_F_ADD_AES_CTR_NIDS 156 +#define PK11_F_INIT_ALL_LOCKS 157 +#define PK11_F_RETURN_SESSION 158 +#define PK11_F_GET_PIN 159 +#define PK11_F_FIND_ONE_OBJECT 160 +#define PK11_F_CHECK_TOKEN_ATTRS 161 +#define PK11_F_CACHE_PIN 162 +#define PK11_F_MLOCK_PIN_IN_MEMORY 163 +#define PK11_F_TOKEN_LOGIN 164 +#define PK11_F_TOKEN_RELOGIN 165 +#define PK11_F_RUN_ASKPASS 166 + +/* Reason codes. */ +#define PK11_R_ALREADY_LOADED 100 +#define PK11_R_DSO_FAILURE 101 +#define PK11_R_NOT_LOADED 102 +#define PK11_R_PASSED_NULL_PARAMETER 103 +#define PK11_R_COMMAND_NOT_IMPLEMENTED 104 +#define PK11_R_INITIALIZE 105 +#define PK11_R_FINALIZE 106 +#define PK11_R_GETINFO 107 +#define PK11_R_GETSLOTLIST 108 +#define PK11_R_NO_MODULUS_OR_NO_EXPONENT 109 +#define PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID 110 +#define PK11_R_GETATTRIBUTVALUE 111 +#define PK11_R_NO_MODULUS 112 +#define PK11_R_NO_EXPONENT 113 +#define PK11_R_FINDOBJECTSINIT 114 +#define PK11_R_FINDOBJECTS 115 +#define PK11_R_FINDOBJECTSFINAL 116 +#define PK11_R_CREATEOBJECT 118 +#define PK11_R_DESTROYOBJECT 119 +#define PK11_R_OPENSESSION 120 +#define PK11_R_CLOSESESSION 121 +#define PK11_R_ENCRYPTINIT 122 +#define PK11_R_ENCRYPT 123 +#define PK11_R_SIGNINIT 124 +#define PK11_R_SIGN 125 +#define PK11_R_DECRYPTINIT 126 +#define PK11_R_DECRYPT 127 +#define PK11_R_VERIFYINIT 128 +#define PK11_R_VERIFY 129 +#define PK11_R_VERIFYRECOVERINIT 130 +#define PK11_R_VERIFYRECOVER 131 +#define PK11_R_GEN_KEY 132 +#define PK11_R_SEEDRANDOM 133 +#define PK11_R_GENERATERANDOM 134 +#define PK11_R_INVALID_MESSAGE_LENGTH 135 +#define PK11_R_UNKNOWN_ALGORITHM_TYPE 136 +#define PK11_R_UNKNOWN_ASN1_OBJECT_ID 137 +#define PK11_R_UNKNOWN_PADDING_TYPE 138 +#define PK11_R_PADDING_CHECK_FAILED 139 +#define PK11_R_DIGEST_TOO_BIG 140 +#define PK11_R_MALLOC_FAILURE 141 +#define PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED 142 +#define PK11_R_DATA_GREATER_THAN_MOD_LEN 143 +#define PK11_R_DATA_TOO_LARGE_FOR_MODULUS 144 +#define PK11_R_MISSING_KEY_COMPONENT 145 +#define PK11_R_INVALID_SIGNATURE_LENGTH 146 +#define PK11_R_INVALID_DSA_SIGNATURE_R 147 +#define PK11_R_INVALID_DSA_SIGNATURE_S 148 +#define PK11_R_INCONSISTENT_KEY 149 +#define PK11_R_ENCRYPTUPDATE 150 +#define PK11_R_DECRYPTUPDATE 151 +#define PK11_R_DIGESTINIT 152 +#define PK11_R_DIGESTUPDATE 153 +#define PK11_R_DIGESTFINAL 154 +#define PK11_R_ENCRYPTFINAL 155 +#define PK11_R_DECRYPTFINAL 156 +#define PK11_R_NO_PRNG_SUPPORT 157 +#define PK11_R_GETTOKENINFO 158 +#define PK11_R_DERIVEKEY 159 +#define PK11_R_GET_OPERATION_STATE 160 +#define PK11_R_SET_OPERATION_STATE 161 +#define PK11_R_INVALID_HANDLE 162 +#define PK11_R_KEY_OR_IV_LEN_PROBLEM 163 +#define PK11_R_INVALID_OPERATION_TYPE 164 +#define PK11_R_ADD_NID_FAILED 165 +#define PK11_R_ATFORK_FAILED 166 +#define PK11_R_TOKEN_LOGIN_FAILED 167 +#define PK11_R_MORE_THAN_ONE_OBJECT_FOUND 168 +#define PK11_R_INVALID_PKCS11_URI 169 +#define PK11_R_COULD_NOT_READ_PIN 170 +#define PK11_R_COULD_NOT_OPEN_COMMAND 171 +#define PK11_R_PIPE_FAILED 172 +#define PK11_R_PIN_NOT_READ_FROM_COMMAND 173 +#define PK11_R_BAD_PASSPHRASE_SPEC 174 +#define PK11_R_TOKEN_NOT_INITIALIZED 175 +#define PK11_R_TOKEN_PIN_NOT_SET 176 +#define PK11_R_TOKEN_PIN_NOT_PROVIDED 177 +#define PK11_R_MISSING_OBJECT_LABEL 178 +#define PK11_R_TOKEN_ATTRS_DO_NOT_MATCH 179 +#define PK11_R_PRIV_KEY_NOT_FOUND 180 +#define PK11_R_NO_OBJECT_FOUND 181 +#define PK11_R_PIN_CACHING_POLICY_INVALID 182 +#define PK11_R_SYSCONF_FAILED 183 +#define PK11_R_MMAP_FAILED 183 +#define PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING 184 +#define PK11_R_MLOCK_FAILED 185 +#define PK11_R_FORK_FAILED 186 + +#endif /* HW_PK11_ERR_H */ diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/engines/pkcs11/hw_pk11_pub.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/engines/pkcs11/hw_pk11_pub.c Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,3239 @@ +/* + * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. + * + */ + +/* crypto/engine/hw_pk11_pub.c */ +/* + * This product includes software developed by the OpenSSL Project for + * use in the OpenSSL Toolkit (http://www.openssl.org/). + * + * This project also referenced hw_pkcs11-0.9.7b.patch written by + * Afchine Madjlessi. + */ +/* + * ==================================================================== + * Copyright (c) 2000-2001 The OpenSSL Project. 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#ifndef OPENSSL_NO_RSA +#include +#endif /* OPENSSL_NO_RSA */ +#ifndef OPENSSL_NO_DSA +#include +#endif /* OPENSSL_NO_DSA */ +#ifndef OPENSSL_NO_DH +#include +#endif /* OPENSSL_NO_DH */ +#include +#include +#include +#include +#include +#include + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 + +#include +#include +#include "hw_pk11.h" +#include "hw_pk11_uri.h" + +static CK_BBOOL pk11_login_done = CK_FALSE; +extern CK_SLOT_ID pubkey_SLOTID; + +/* + * During the reinitialization after a detected fork we will try to login to the + * token using the passphrasedialog keyword that we inherit from the parent. + */ +char *passphrasedialog; + +#ifndef OPENSSL_NO_RSA +/* RSA stuff */ +static int pk11_RSA_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_private_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_public_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding); +static int pk11_RSA_init(RSA *rsa); +static int pk11_RSA_finish(RSA *rsa); +static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa); +static int pk11_RSA_verify(int dtype, const unsigned char *m, + unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, + const RSA *rsa); +EVP_PKEY *pk11_load_privkey(ENGINE*, const char *privkey_id, + UI_METHOD *ui_method, void *callback_data); +EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_id, + UI_METHOD *ui_method, void *callback_data); + +static int pk11_RSA_public_encrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); +static int pk11_RSA_private_encrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); +static int pk11_RSA_public_decrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); +static int pk11_RSA_private_decrypt_low(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa); + +static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, PK11_SESSION *sp); +static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, PK11_SESSION *sp); + +static int pk11_check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa); +static int pk11_check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa); +#endif + +/* DSA stuff */ +#ifndef OPENSSL_NO_DSA +static int pk11_DSA_init(DSA *dsa); +static int pk11_DSA_finish(DSA *dsa); +static DSA_SIG *pk11_dsa_do_sign(const unsigned char *dgst, int dlen, + DSA *dsa); +static int pk11_dsa_do_verify(const unsigned char *dgst, int dgst_len, + DSA_SIG *sig, DSA *dsa); + +static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa, DSA **key_ptr, + BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session); +static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa, DSA **key_ptr, + BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session); + +static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa); +static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa); +#endif + +/* DH stuff */ +#ifndef OPENSSL_NO_DH +static int pk11_DH_init(DH *dh); +static int pk11_DH_finish(DH *dh); +static int pk11_DH_generate_key(DH *dh); +static int pk11_DH_compute_key(unsigned char *key, + const BIGNUM *pub_key, DH *dh); + +static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, DH **key_ptr, + BIGNUM **priv_key, CK_SESSION_HANDLE session); + +static int check_new_dh_key(PK11_SESSION *sp, DH *dh); +#endif + +static int find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, + CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey); +static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue, + CK_ULONG *ulValueLen); +static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn); + +/* Read mode string to be used for fopen() */ +#if SOLARIS_OPENSSL +static char *read_mode_flags = "rF"; +#else +static char *read_mode_flags = "r"; +#endif + +/* + * Increment existing or create a new reference for an asymmetric key PKCS#11 + * object handle in the active object list. If the operation fails, unlock (if + * locked), set error variable and jump to the specified label. We use this list + * so that we can track how many references to the PKCS#11 objects are used from + * all our sessions structures. If we are replacing an object reference in the + * session structure and the ref count for the reference being replaced gets to + * 0 we know that we can safely free the object itself via C_ObjectDestroy(). + * See also TRY_OBJ_DESTROY. + */ +#define KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label) \ + { \ + if (pk11_active_add(key_handle, alg_type) < 0) \ + { \ + var = CK_TRUE; \ + if (unlock) \ + UNLOCK_OBJSTORE(alg_type); \ + goto label; \ + } \ + } + +/* + * Find active list entry according to object handle and return pointer to the + * entry otherwise return NULL. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry; + + for (entry = active_list[type]; entry != NULL; entry = entry->next) + if (entry->h == h) + return (entry); + + return (NULL); + } + +/* + * Search for an entry in the active list using PKCS#11 object handle as a + * search key and return refcnt of the found/created entry or -1 in case of + * failure. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +int +pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry = NULL; + + if (h == CK_INVALID_HANDLE) + { + PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE); + return (-1); + } + + /* search for entry in the active list */ + if ((entry = pk11_active_find(h, type)) != NULL) + entry->refcnt++; + else + { + /* not found, create new entry and add it to the list */ + entry = OPENSSL_malloc(sizeof (PK11_active)); + if (entry == NULL) + { + PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE); + return (-1); + } + entry->h = h; + entry->refcnt = 1; + entry->prev = NULL; + entry->next = NULL; + /* connect the newly created entry to the list */ + if (active_list[type] == NULL) + active_list[type] = entry; + else /* make the entry first in the list */ + { + entry->next = active_list[type]; + active_list[type]->prev = entry; + active_list[type] = entry; + } + } + + return (entry->refcnt); + } + +/* + * Remove active list entry from the list and free it. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +void +pk11_active_remove(PK11_active *entry, PK11_OPTYPE type) + { + PK11_active *prev_entry; + + /* remove the entry from the list and free it */ + if ((prev_entry = entry->prev) != NULL) + { + prev_entry->next = entry->next; + if (entry->next != NULL) + entry->next->prev = prev_entry; + } + else + { + active_list[type] = entry->next; + /* we were the first but not the only one */ + if (entry->next != NULL) + entry->next->prev = NULL; + } + + /* sanitization */ + entry->h = CK_INVALID_HANDLE; + entry->prev = NULL; + entry->next = NULL; + OPENSSL_free(entry); + } + +/* Free all entries from the active list. */ +void +pk11_free_active_list(PK11_OPTYPE type) + { + PK11_active *entry; + + /* only for asymmetric types since only they have C_Find* locks. */ + switch (type) + { + case OP_RSA: + case OP_DSA: + case OP_DH: + break; + default: + return; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(type); + while ((entry = active_list[type]) != NULL) + pk11_active_remove(entry, type); + UNLOCK_OBJSTORE(type); + } + +/* + * Search for active list entry associated with given PKCS#11 object handle, + * decrement its refcnt and if it drops to 0, disconnect the entry and free it. + * + * Return 1 if the PKCS#11 object associated with the entry has no references, + * return 0 if there is at least one reference, -1 on error. + * + * This function presumes it is called with lock protecting the active list + * held. + */ +int +pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type) + { + PK11_active *entry = NULL; + + if ((entry = pk11_active_find(h, type)) == NULL) + { + PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE); + return (-1); + } + + OPENSSL_assert(entry->refcnt > 0); + entry->refcnt--; + if (entry->refcnt == 0) + { + pk11_active_remove(entry, type); + return (1); + } + + return (0); + } + +#ifndef OPENSSL_NO_RSA +/* Our internal RSA_METHOD that we provide pointers to */ +static RSA_METHOD pk11_rsa = + { + "PKCS#11 RSA method", + pk11_RSA_public_encrypt, /* rsa_pub_encrypt */ + pk11_RSA_public_decrypt, /* rsa_pub_decrypt */ + pk11_RSA_private_encrypt, /* rsa_priv_encrypt */ + pk11_RSA_private_decrypt, /* rsa_priv_decrypt */ + NULL, /* rsa_mod_exp */ + NULL, /* bn_mod_exp */ + pk11_RSA_init, /* init */ + pk11_RSA_finish, /* finish */ + RSA_FLAG_SIGN_VER, /* flags */ + NULL, /* app_data */ + pk11_RSA_sign, /* rsa_sign */ + pk11_RSA_verify /* rsa_verify */ + }; + +RSA_METHOD * +PK11_RSA(void) + { + return (&pk11_rsa); + } +#endif + +#ifndef OPENSSL_NO_DSA +/* Our internal DSA_METHOD that we provide pointers to */ +static DSA_METHOD pk11_dsa = + { + "PKCS#11 DSA method", + pk11_dsa_do_sign, /* dsa_do_sign */ + NULL, /* dsa_sign_setup */ + pk11_dsa_do_verify, /* dsa_do_verify */ + NULL, /* dsa_mod_exp */ + NULL, /* bn_mod_exp */ + pk11_DSA_init, /* init */ + pk11_DSA_finish, /* finish */ + 0, /* flags */ + NULL /* app_data */ + }; + +DSA_METHOD * +PK11_DSA(void) + { + return (&pk11_dsa); + } +#endif + +#ifndef OPENSSL_NO_DH +/* + * PKCS #11 V2.20, section 11.2 specifies that the number of bytes needed for + * output buffer may somewhat exceed the precise number of bytes needed, but + * should not exceed it by a large amount. That may be caused, for example, by + * rounding it up to multiple of X in the underlying bignum library. 8 should be + * enough. + */ +#define DH_BUF_RESERVE 8 + +/* Our internal DH_METHOD that we provide pointers to */ +static DH_METHOD pk11_dh = + { + "PKCS#11 DH method", + pk11_DH_generate_key, /* generate_key */ + pk11_DH_compute_key, /* compute_key */ + NULL, /* bn_mod_exp */ + pk11_DH_init, /* init */ + pk11_DH_finish, /* finish */ + 0, /* flags */ + NULL, /* app_data */ + NULL /* generate_params */ + }; + +DH_METHOD * +PK11_DH(void) + { + return (&pk11_dh); + } +#endif + +/* Size of an SSL signature: MD5+SHA1 */ +#define SSL_SIG_LENGTH 36 + +/* Lengths of DSA data and signature */ +#define DSA_DATA_LEN 20 +#define DSA_SIGNATURE_LEN 40 + +static CK_BBOOL pk11_true = CK_TRUE; +static CK_BBOOL pk11_false = CK_FALSE; + +#ifndef OPENSSL_NO_RSA +/* + * Similiar to OpenSSL to take advantage of the paddings. The goal is to + * support all paddings in this engine although PK11 library does not + * support all the paddings used in OpenSSL. + * The input errors should have been checked in the padding functions. + */ +static int pk11_RSA_public_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + int i, num = 0, r = -1; + unsigned char *buf = NULL; + + num = BN_num_bytes(rsa->n); + if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL) + { + PK11err(PK11_F_RSA_PUB_ENC, PK11_R_MALLOC_FAILURE); + goto err; + } + + switch (padding) + { + case RSA_PKCS1_PADDING: + i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen); + break; +#ifndef OPENSSL_NO_SHA + case RSA_PKCS1_OAEP_PADDING: + i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0); + break; +#endif + case RSA_SSLV23_PADDING: + i = RSA_padding_add_SSLv23(buf, num, from, flen); + break; + case RSA_NO_PADDING: + i = RSA_padding_add_none(buf, num, from, flen); + break; + default: + PK11err(PK11_F_RSA_PUB_ENC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (i <= 0) goto err; + + /* PK11 functions are called here */ + r = pk11_RSA_public_encrypt_low(num, buf, to, rsa); +err: + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + + +/* + * Similar to Openssl to take advantage of the paddings. The input errors + * should be catched in the padding functions + */ +static int pk11_RSA_private_encrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + int i, num = 0, r = -1; + unsigned char *buf = NULL; + + num = BN_num_bytes(rsa->n); + if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL) + { + PK11err(PK11_F_RSA_PRIV_ENC, PK11_R_MALLOC_FAILURE); + goto err; + } + + switch (padding) + { + case RSA_PKCS1_PADDING: + i = RSA_padding_add_PKCS1_type_1(buf, num, from, flen); + break; + case RSA_NO_PADDING: + i = RSA_padding_add_none(buf, num, from, flen); + break; + case RSA_SSLV23_PADDING: + default: + PK11err(PK11_F_RSA_PRIV_ENC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (i <= 0) goto err; + + /* PK11 functions are called here */ + r = pk11_RSA_private_encrypt_low(num, buf, to, rsa); +err: + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + +/* Similar to OpenSSL code. Input errors are also checked here */ +static int pk11_RSA_private_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + BIGNUM f; + int j, num = 0, r = -1; + unsigned char *p; + unsigned char *buf = NULL; + + BN_init(&f); + + num = BN_num_bytes(rsa->n); + + if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL) + { + PK11err(PK11_F_RSA_PRIV_DEC, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* + * This check was for equality but PGP does evil things + * and chops off the top '0' bytes + */ + if (flen > num) + { + PK11err(PK11_F_RSA_PRIV_DEC, + PK11_R_DATA_GREATER_THAN_MOD_LEN); + goto err; + } + + /* make data into a big number */ + if (BN_bin2bn(from, (int)flen, &f) == NULL) + goto err; + + if (BN_ucmp(&f, rsa->n) >= 0) + { + PK11err(PK11_F_RSA_PRIV_DEC, + PK11_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + /* PK11 functions are called here */ + r = pk11_RSA_private_decrypt_low(flen, from, buf, rsa); + + /* + * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning. + * Needs to skip these 0's paddings here. + */ + for (j = 0; j < r; j++) + if (buf[j] != 0) + break; + + p = buf + j; + j = r - j; /* j is only used with no-padding mode */ + + switch (padding) + { + case RSA_PKCS1_PADDING: + r = RSA_padding_check_PKCS1_type_2(to, num, p, j, num); + break; +#ifndef OPENSSL_NO_SHA + case RSA_PKCS1_OAEP_PADDING: + r = RSA_padding_check_PKCS1_OAEP(to, num, p, j, num, NULL, 0); + break; +#endif + case RSA_SSLV23_PADDING: + r = RSA_padding_check_SSLv23(to, num, p, j, num); + break; + case RSA_NO_PADDING: + r = RSA_padding_check_none(to, num, p, j, num); + break; + default: + PK11err(PK11_F_RSA_PRIV_DEC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (r < 0) + PK11err(PK11_F_RSA_PRIV_DEC, PK11_R_PADDING_CHECK_FAILED); + +err: + BN_clear_free(&f); + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + +/* Similar to OpenSSL code. Input errors are also checked here */ +static int pk11_RSA_public_decrypt(int flen, const unsigned char *from, + unsigned char *to, RSA *rsa, int padding) + { + BIGNUM f; + int i, num = 0, r = -1; + unsigned char *p; + unsigned char *buf = NULL; + + BN_init(&f); + num = BN_num_bytes(rsa->n); + buf = (unsigned char *)OPENSSL_malloc(num); + if (buf == NULL) + { + PK11err(PK11_F_RSA_PUB_DEC, PK11_R_MALLOC_FAILURE); + goto err; + } + + /* + * This check was for equality but PGP does evil things + * and chops off the top '0' bytes + */ + if (flen > num) + { + PK11err(PK11_F_RSA_PUB_DEC, PK11_R_DATA_GREATER_THAN_MOD_LEN); + goto err; + } + + if (BN_bin2bn(from, flen, &f) == NULL) + goto err; + + if (BN_ucmp(&f, rsa->n) >= 0) + { + PK11err(PK11_F_RSA_PUB_DEC, + PK11_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + /* PK11 functions are called here */ + r = pk11_RSA_public_decrypt_low(flen, from, buf, rsa); + + /* + * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning. + * Needs to skip these 0's here + */ + for (i = 0; i < r; i++) + if (buf[i] != 0) + break; + + p = buf + i; + i = r - i; /* i is only used with no-padding mode */ + + switch (padding) + { + case RSA_PKCS1_PADDING: + r = RSA_padding_check_PKCS1_type_1(to, num, p, i, num); + break; + case RSA_NO_PADDING: + r = RSA_padding_check_none(to, num, p, i, num); + break; + default: + PK11err(PK11_F_RSA_PUB_DEC, PK11_R_UNKNOWN_PADDING_TYPE); + goto err; + } + if (r < 0) + PK11err(PK11_F_RSA_PUB_DEC, PK11_R_PADDING_CHECK_FAILED); + +err: + BN_clear_free(&f); + if (buf != NULL) + { + OPENSSL_cleanse(buf, num); + OPENSSL_free(buf); + } + return (r); + } + +/* + * This function implements RSA public encryption using C_EncryptInit and + * C_Encrypt pk11 interfaces. Note that the CKM_RSA_X_509 is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_public_encrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG bytes_encrypted = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) pk11_check_new_rsa_key_pub(sp, rsa); + + h_pub_key = sp->opdata_rsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, sp); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_EncryptInit(sp->session, p_mech, + h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW, + PK11_R_ENCRYPTINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_Encrypt(sp->session, + (unsigned char *)from, flen, to, &bytes_encrypted); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW, + PK11_R_ENCRYPT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + retval = bytes_encrypted; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + + +/* + * This function implements RSA private encryption using C_SignInit and + * C_Sign pk11 APIs. Note that CKM_RSA_X_509 is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_private_encrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG ul_sig_len = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) pk11_check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, sp); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, + h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW, + PK11_R_SIGNINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_Sign(sp->session, + (unsigned char *)from, flen, to, &ul_sig_len); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW, PK11_R_SIGN, + rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + retval = ul_sig_len; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + + +/* + * This function implements RSA private decryption using C_DecryptInit and + * C_Decrypt pk11 APIs. Note that CKM_RSA_X_509 mechanism is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_private_decrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG bytes_decrypted = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) pk11_check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, sp); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DecryptInit(sp->session, p_mech, + h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW, + PK11_R_DECRYPTINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_Decrypt(sp->session, + (unsigned char *)from, flen, to, &bytes_decrypted); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW, + PK11_R_DECRYPT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + retval = bytes_decrypted; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + + +/* + * This function implements RSA public decryption using C_VerifyRecoverInit + * and C_VerifyRecover pk11 APIs. Note that CKM_RSA_X_509 is used here. + * The calling function allocated sufficient memory in "to" to store results. + */ +static int pk11_RSA_public_decrypt_low(int flen, + const unsigned char *from, unsigned char *to, RSA *rsa) + { + CK_ULONG bytes_decrypted = flen; + int retval = -1; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + PK11_SESSION *sp; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (-1); + + (void) pk11_check_new_rsa_key_pub(sp, rsa); + + h_pub_key = sp->opdata_rsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, sp); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_VerifyRecoverInit(sp->session, + p_mech, h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW, + PK11_R_VERIFYRECOVERINIT, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + + rv = pFuncList->C_VerifyRecover(sp->session, + (unsigned char *)from, flen, to, &bytes_decrypted); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW, + PK11_R_VERIFYRECOVER, rv); + pk11_return_session(sp, OP_RSA); + return (-1); + } + retval = bytes_decrypted; + } + + pk11_return_session(sp, OP_RSA); + return (retval); + } + +static int pk11_RSA_init(RSA *rsa) + { + /* + * This flag in the RSA_METHOD enables the new rsa_sign, + * rsa_verify functions. See rsa.h for details. + */ + rsa->flags |= RSA_FLAG_SIGN_VER; + + return (1); + } + +static int pk11_RSA_finish(RSA *rsa) + { + /* + * Since we are overloading OpenSSL's native RSA_eay_finish() we need + * to do the same as in the original function, i.e. to free bignum + * structures. + */ + if (rsa->_method_mod_n != NULL) + BN_MONT_CTX_free(rsa->_method_mod_n); + if (rsa->_method_mod_p != NULL) + BN_MONT_CTX_free(rsa->_method_mod_p); + if (rsa->_method_mod_q != NULL) + BN_MONT_CTX_free(rsa->_method_mod_q); + + return (1); + } + +/* + * Standard engine interface function. Majority codes here are from + * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11. + * See more details in rsa/rsa_sign.c + */ +static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, + unsigned char *sigret, unsigned int *siglen, const RSA *rsa) + { + X509_SIG sig; + ASN1_TYPE parameter; + int i, j; + unsigned char *p, *s = NULL; + X509_ALGOR algor; + ASN1_OCTET_STRING digest; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_priv_key; + PK11_SESSION *sp = NULL; + int ret = 0; + unsigned long ulsiglen; + + /* Encode the digest */ + /* Special case: SSL signature, just check the length */ + if (type == NID_md5_sha1) + { + if (m_len != SSL_SIG_LENGTH) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_INVALID_MESSAGE_LENGTH); + goto err; + } + i = SSL_SIG_LENGTH; + s = (unsigned char *)m; + } + else + { + sig.algor = &algor; + sig.algor->algorithm = OBJ_nid2obj(type); + if (sig.algor->algorithm == NULL) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_UNKNOWN_ALGORITHM_TYPE); + goto err; + } + if (sig.algor->algorithm->length == 0) + { + PK11err(PK11_F_RSA_SIGN, + PK11_R_UNKNOWN_ASN1_OBJECT_ID); + goto err; + } + parameter.type = V_ASN1_NULL; + parameter.value.ptr = NULL; + sig.algor->parameter = ¶meter; + + sig.digest = &digest; + sig.digest->data = (unsigned char *)m; + sig.digest->length = m_len; + + i = i2d_X509_SIG(&sig, NULL); + } + + j = RSA_size(rsa); + if ((i - RSA_PKCS1_PADDING) > j) + { + PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG); + goto err; + } + + if (type != NID_md5_sha1) + { + s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1)); + if (s == NULL) + { + PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE); + goto err; + } + p = s; + (void) i2d_X509_SIG(&sig, &p); + } + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + goto err; + + (void) pk11_check_new_rsa_key_priv(sp, rsa); + + h_priv_key = sp->opdata_rsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key((RSA *)rsa, sp); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv); + goto err; + } + + ulsiglen = j; + rv = pFuncList->C_Sign(sp->session, s, i, sigret, + (CK_ULONG_PTR) &ulsiglen); + *siglen = ulsiglen; + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv); + goto err; + } + ret = 1; + } + +err: + if (type != NID_md5_sha1) + { + (void) memset(s, 0, (unsigned int)(j + 1)); + OPENSSL_free(s); + } + + pk11_return_session(sp, OP_RSA); + return (ret); + } + +static int pk11_RSA_verify(int type, const unsigned char *m, + unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, + const RSA *rsa) + { + X509_SIG sig; + ASN1_TYPE parameter; + int i, j; + unsigned char *p, *s = NULL; + X509_ALGOR algor; + ASN1_OCTET_STRING digest; + CK_RV rv; + CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0}; + CK_MECHANISM *p_mech = &mech_rsa; + CK_OBJECT_HANDLE h_pub_key; + PK11_SESSION *sp = NULL; + int ret = 0; + + /* Encode the digest */ + /* Special case: SSL signature, just check the length */ + if (type == NID_md5_sha1) + { + if (m_len != SSL_SIG_LENGTH) + { + PK11err(PK11_F_RSA_VERIFY, + PK11_R_INVALID_MESSAGE_LENGTH); + goto err; + } + i = SSL_SIG_LENGTH; + s = (unsigned char *)m; + } + else + { + sig.algor = &algor; + sig.algor->algorithm = OBJ_nid2obj(type); + if (sig.algor->algorithm == NULL) + { + PK11err(PK11_F_RSA_VERIFY, + PK11_R_UNKNOWN_ALGORITHM_TYPE); + goto err; + } + if (sig.algor->algorithm->length == 0) + { + PK11err(PK11_F_RSA_VERIFY, + PK11_R_UNKNOWN_ASN1_OBJECT_ID); + goto err; + } + parameter.type = V_ASN1_NULL; + parameter.value.ptr = NULL; + sig.algor->parameter = ¶meter; + sig.digest = &digest; + sig.digest->data = (unsigned char *)m; + sig.digest->length = m_len; + i = i2d_X509_SIG(&sig, NULL); + } + + j = RSA_size(rsa); + if ((i - RSA_PKCS1_PADDING) > j) + { + PK11err(PK11_F_RSA_VERIFY, PK11_R_DIGEST_TOO_BIG); + goto err; + } + + if (type != NID_md5_sha1) + { + s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1)); + if (s == NULL) + { + PK11err(PK11_F_RSA_VERIFY, PK11_R_MALLOC_FAILURE); + goto err; + } + p = s; + (void) i2d_X509_SIG(&sig, &p); + } + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + goto err; + + (void) pk11_check_new_rsa_key_pub(sp, rsa); + + h_pub_key = sp->opdata_rsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key((RSA *)rsa, sp); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_VerifyInit(sp->session, p_mech, + h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFYINIT, + rv); + goto err; + } + rv = pFuncList->C_Verify(sp->session, s, i, sigbuf, + (CK_ULONG)siglen); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFY, rv); + goto err; + } + ret = 1; + } + +err: + if (type != NID_md5_sha1) + { + (void) memset(s, 0, (unsigned int)siglen); + OPENSSL_free(s); + } + + pk11_return_session(sp, OP_RSA); + return (ret); + } + +#define MAXATTR 1024 +/* + * Load RSA private key from a file or get its PKCS#11 handle if stored in the + * PKCS#11 token. + */ +/* ARGSUSED */ +EVP_PKEY *pk11_load_privkey(ENGINE* e, const char *privkey_id, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey = NULL; + FILE *privkey; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + RSA *rsa = NULL; + PK11_SESSION *sp; + /* Anything else below is needed for the key by reference extension. */ + const char *file; + int ret; + pkcs11_uri uri_struct; + CK_RV rv; + CK_BBOOL is_token = CK_TRUE; + CK_BBOOL rollback = CK_FALSE; + CK_BYTE attr_data[8][MAXATTR]; + CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY; + CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ + + /* We look for private keys only. */ + CK_ATTRIBUTE search_templ[] = + { + {CKA_TOKEN, &is_token, sizeof (is_token)}, + {CKA_CLASS, &key_class, sizeof (key_class)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * These public attributes are needed to initialize the OpenSSL RSA + * structure with something we can use to look up the key. Note that we + * never ask for private components. + */ + CK_ATTRIBUTE get_templ[] = + { + {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ + {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ + }; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (NULL); + + /* + * The next function will decide whether we are going to access keys in + * the token or read them from plain files. It all depends on what is in + * the 'privkey_id' parameter. + */ + ret = pk11_process_pkcs11_uri(privkey_id, &uri_struct, &file); + + if (ret == 0) + goto err; + + /* We will try to access a key from a PKCS#11 token. */ + if (ret == 1) + { + if (pk11_check_token_attrs(&uri_struct) == 0) + goto err; + + search_templ[2].pValue = uri_struct.object; + search_templ[2].ulValueLen = strlen(search_templ[2].pValue); + + if (pk11_token_login(sp->session, &pk11_login_done, + &uri_struct, CK_TRUE) == 0) + goto err; + + /* + * Now let's try to find the key in the token. It is a failure + * if we can't find it. + */ + if (find_one_object(OP_RSA, sp->session, search_templ, 3, + &ks_key) == 0) + goto err; + + /* + * Free the structure now. Note that we use uri_struct's field + * directly in the template so we cannot free it until the find + * is done. + */ + pk11_free_pkcs11_uri(&uri_struct, 0); + + /* + * We might have a cache hit which we could confirm according to + * the 'n'/'e' params, RSA public pointer as NULL, and non-NULL + * RSA private pointer. However, it is easier just to recreate + * everything. We expect the keys to be loaded once and used + * many times. We do not check the return value because even in + * case of failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() reports + * the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_rsa_object_priv(sp, CK_TRUE); + + sp->opdata_rsa_priv_key = ks_key; + /* This object shall not be deleted on a cache miss. */ + sp->persistent = CK_TRUE; + + if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL) + goto err; + + if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, + get_templ, 2)) != CKR_OK) + { + PK11err_add_data(PK11_F_LOAD_PRIVKEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + /* + * Cache the RSA private structure pointer. We do not use it now + * for key-by-ref keys but let's do it for consistency reasons. + */ + sp->opdata_rsa_priv = rsa; + + /* + * We do not use pk11_get_private_rsa_key() here so we must take + * care of handle management ourselves. + */ + KEY_HANDLE_REFHOLD(ks_key, OP_RSA, CK_FALSE, rollback, err); + + /* + * Those are the sensitive components we do not want to export + * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp). + */ + attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); + attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); + /* + * Must have 'n'/'e' components in the session structure as + * well. They serve as a public look-up key for the private key + * in the keystore. + */ + attr_to_BN(&get_templ[0], attr_data[0], &sp->opdata_rsa_n_num); + attr_to_BN(&get_templ[1], attr_data[1], &sp->opdata_rsa_e_num); + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_set1_RSA(pkey, rsa) == 0) + goto err; + } + else + if ((privkey = fopen(file, read_mode_flags)) != NULL) + { + pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL); + (void) fclose(privkey); + if (pkey != NULL) + { + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa != NULL) + { + (void) pk11_check_new_rsa_key_priv(sp, + rsa); + + h_priv_key = sp->opdata_rsa_priv_key = + pk11_get_private_rsa_key(rsa, sp); + if (h_priv_key == CK_INVALID_HANDLE) + goto err; + } + else + goto err; + } + } + + pk11_return_session(sp, OP_RSA); + return (pkey); +err: + if (rsa != NULL) + RSA_free(rsa); + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + return (pkey); + } + +/* Load RSA public key from a file or load it from the PKCS#11 token. */ +/* ARGSUSED */ +EVP_PKEY *pk11_load_pubkey(ENGINE* e, const char *pubkey_id, + UI_METHOD *ui_method, void *callback_data) + { + EVP_PKEY *pkey = NULL; + FILE *pubkey; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + RSA *rsa = NULL; + PK11_SESSION *sp; + /* everything else below needed for key by reference extension */ + int ret; + const char *file; + pkcs11_uri uri_struct; + CK_RV rv; + CK_BBOOL is_token = CK_TRUE; + CK_BYTE attr_data[2][MAXATTR]; + CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY; + CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ + + CK_ATTRIBUTE search_templ[] = + { + {CKA_TOKEN, &is_token, sizeof (is_token)}, + {CKA_CLASS, &key_class, sizeof (key_class)}, + {CKA_LABEL, NULL, 0} + }; + + /* + * These public attributes are needed to initialize OpenSSL RSA + * structure with something we can use to look up the key. + */ + CK_ATTRIBUTE get_templ[] = + { + {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ + {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ + }; + + if ((sp = pk11_get_session(OP_RSA)) == NULL) + return (NULL); + + ret = pk11_process_pkcs11_uri(pubkey_id, &uri_struct, &file); + + if (ret == 0) + goto err; + + if (ret == 1) + { + if (pk11_check_token_attrs(&uri_struct) == 0) + goto err; + + search_templ[2].pValue = uri_struct.object; + search_templ[2].ulValueLen = strlen(search_templ[2].pValue); + + if (pk11_token_login(sp->session, &pk11_login_done, + &uri_struct, CK_FALSE) == 0) + goto err; + + if (find_one_object(OP_RSA, sp->session, search_templ, 3, + &ks_key) == 0) + { + goto err; + } + + /* + * Free the structure now. Note that we use uri_struct's field + * directly in the template so we can't free until find is done. + */ + pk11_free_pkcs11_uri(&uri_struct, 0); + /* + * We load a new public key so we will create a new RSA + * structure. No cache hit is possible. + */ + (void) pk11_destroy_rsa_object_pub(sp, CK_TRUE); + sp->opdata_rsa_pub_key = ks_key; + + if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL) + goto err; + + if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, + get_templ, 2)) != CKR_OK) + { + PK11err_add_data(PK11_F_LOAD_PUBKEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + /* + * Cache the RSA public structure pointer. + */ + sp->opdata_rsa_pub = rsa; + + /* + * These are the sensitive components we do not want to export + * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp). + */ + attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); + attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); + + if ((pkey = EVP_PKEY_new()) == NULL) + goto err; + + if (EVP_PKEY_set1_RSA(pkey, rsa) == 0) + goto err; + + /* + * Create a session object from it so that when calling + * pk11_get_public_rsa_key() the next time, we can find it. The + * reason why we do that is that we cannot tell from the RSA + * structure (OpenSSL RSA structure does not have any room for + * additional data used by the engine, for example) if it bears + * a public key stored in the keystore or not so it's better if + * we always have a session key. Note that this is different + * from what we do for the private keystore objects but in that + * case, we can tell from the RSA structure that the keystore + * object is in play - the 'd' component is NULL in that case. + */ + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, sp); + if (h_pub_key == CK_INVALID_HANDLE) + goto err; + } + else + if ((pubkey = fopen(file, read_mode_flags)) != NULL) + { + pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL); + (void) fclose(pubkey); + if (pkey != NULL) + { + rsa = EVP_PKEY_get1_RSA(pkey); + if (rsa != NULL) + { + /* + * This will always destroy the RSA + * object since we have a new RSA + * structure here. + */ + (void) pk11_check_new_rsa_key_pub(sp, + rsa); + + h_pub_key = sp->opdata_rsa_pub_key = + pk11_get_public_rsa_key(rsa, sp); + if (h_pub_key == CK_INVALID_HANDLE) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + } + else + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + } + } + + pk11_return_session(sp, OP_RSA); + return (pkey); +err: + if (rsa != NULL) + RSA_free(rsa); + if (pkey != NULL) + { + EVP_PKEY_free(pkey); + pkey = NULL; + } + return (pkey); + } + +/* + * Get a public key object in a session from a given rsa structure. If the + * PKCS#11 session object already exists it is found, reused, and + * the counter in the active object list incremented. If not found, a new + * session object is created and put also onto the active object list. + * + * We use the session field from sp, and we cache rsa->(n|e) in + * opdata_rsa_(n|e|d)_num, respectively. + */ +static CK_OBJECT_HANDLE +pk11_get_public_rsa_key(RSA* rsa, PK11_SESSION *sp) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_ULONG found; + CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY; + CK_KEY_TYPE k_type = CKK_RSA; + CK_ULONG ul_key_attr_count = 7; + CK_BBOOL rollback = CK_FALSE; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &pk11_false, sizeof (pk11_false)}, + {CKA_ENCRYPT, &pk11_true, sizeof (pk11_true)}, + {CKA_VERIFY_RECOVER, &pk11_true, sizeof (pk11_true)}, + {CKA_MODULUS, (void *)NULL, 0}, + {CKA_PUBLIC_EXPONENT, (void *)NULL, 0} + }; + + int i; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + a_key_template[5].ulValueLen = BN_num_bytes(rsa->n); + a_key_template[5].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)a_key_template[5].ulValueLen); + if (a_key_template[5].pValue == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(rsa->n, a_key_template[5].pValue); + + a_key_template[6].ulValueLen = BN_num_bytes(rsa->e); + a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)a_key_template[6].ulValueLen); + if (a_key_template[6].pValue == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(rsa->e, a_key_template[6].pValue); + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + rv = pFuncList->C_FindObjectsInit(sp->session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(sp->session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(sp->session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(sp->session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if ((sp->opdata_rsa_n_num = BN_dup(rsa->n)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = CK_TRUE; + goto err; + } + + if ((sp->opdata_rsa_e_num = BN_dup(rsa->e)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + rollback = CK_TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_RSA, CK_FALSE, rollback, err); + sp->opdata_rsa_pub = rsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(sp->session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_RSA); + +malloc_err: + for (i = 5; i <= 6; i++) + { + if (a_key_template[i].pValue != NULL) + { + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Function similar to pk11_get_public_rsa_key(). In addition to 'n' and 'e' + * components, it also caches 'd' if present. Note that if RSA keys by reference + * are used, 'd' is never extracted from the token in which case it would be + * NULL here. + */ +static CK_OBJECT_HANDLE +pk11_get_private_rsa_key(RSA* rsa, PK11_SESSION *sp) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + int i; + CK_ULONG found; + CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY; + CK_KEY_TYPE k_type = CKK_RSA; + CK_ULONG ul_key_attr_count = 14; + CK_BBOOL rollback = CK_FALSE; + + /* + * Both CKA_TOKEN and CKA_SENSITIVE have to be CK_FALSE for session keys + */ + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &pk11_false, sizeof (pk11_false)}, + {CKA_SENSITIVE, &pk11_false, sizeof (pk11_false)}, + {CKA_DECRYPT, &pk11_true, sizeof (pk11_true)}, + {CKA_SIGN, &pk11_true, sizeof (pk11_true)}, + {CKA_MODULUS, (void *)NULL, 0}, + {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}, + {CKA_PRIVATE_EXPONENT, (void *)NULL, 0}, + {CKA_PRIME_1, (void *)NULL, 0}, + {CKA_PRIME_2, (void *)NULL, 0}, + {CKA_EXPONENT_1, (void *)NULL, 0}, + {CKA_EXPONENT_2, (void *)NULL, 0}, + {CKA_COEFFICIENT, (void *)NULL, 0}, + }; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + /* Put the private key components into the template */ + if (init_template_value(rsa->n, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(rsa->e, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0 || + init_template_value(rsa->d, &a_key_template[8].pValue, + &a_key_template[8].ulValueLen) == 0 || + init_template_value(rsa->p, &a_key_template[9].pValue, + &a_key_template[9].ulValueLen) == 0 || + init_template_value(rsa->q, &a_key_template[10].pValue, + &a_key_template[10].ulValueLen) == 0 || + init_template_value(rsa->dmp1, &a_key_template[11].pValue, + &a_key_template[11].ulValueLen) == 0 || + init_template_value(rsa->dmq1, &a_key_template[12].pValue, + &a_key_template[12].ulValueLen) == 0 || + init_template_value(rsa->iqmp, &a_key_template[13].pValue, + &a_key_template[13].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_RSA); + + /* + * We are getting the private key but the private 'd' component is NULL. + * That means this is key by reference RSA key. In that case, we can + * use only public components for searching for the private key handle. + */ + if (rsa->d == NULL) + { + ul_key_attr_count = 8; + /* + * We will perform the search in the token, not in the existing + * session keys. + */ + a_key_template[2].pValue = &pk11_true; + } + + rv = pFuncList->C_FindObjectsInit(sp->session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(sp->session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(sp->session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + /* + * We have an RSA structure with 'n'/'e' components only so we + * tried to find the private key in the keystore. If it was + * really a token key we have a problem. Note that for other key + * types we just create a new session key using the private + * components from the RSA structure. + */ + if (rsa->d == NULL) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_PRIV_KEY_NOT_FOUND); + goto err; + } + + rv = pFuncList->C_CreateObject(sp->session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + /* + * When RSA keys by reference code is used, we never extract private + * components from the keystore. In that case 'd' was set to NULL and we + * expect the application to properly cope with that. It is documented + * in openssl(5). In general, if keys by reference are used we expect it + * to be used exclusively using the high level API and then there is no + * problem. If the application expects the private components to be read + * from the keystore then that is not a supported way of usage. + */ + if (rsa->d != NULL) + { + if ((sp->opdata_rsa_d_num = BN_dup(rsa->d)) == NULL) + { + PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = CK_TRUE; + goto err; + } + } + else + sp->opdata_rsa_d_num = NULL; + + /* + * For the key by reference code, we need public components as well + * since 'd' component is always NULL. For that reason, we always cache + * 'n'/'e' components as well. + */ + if ((sp->opdata_rsa_n_num = BN_dup(rsa->n)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + sp->opdata_rsa_n_num = NULL; + rollback = CK_TRUE; + goto err; + } + if ((sp->opdata_rsa_e_num = BN_dup(rsa->e)) == NULL) + { + PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); + BN_free(sp->opdata_rsa_n_num); + sp->opdata_rsa_n_num = NULL; + rollback = CK_TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_RSA, CK_FALSE, rollback, err); + sp->opdata_rsa_priv = rsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(sp->session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_RSA); + +malloc_err: + /* + * 6 to 13 entries in the key template are key components. + * They need to be freed upon exit or error. + */ + for (i = 6; i <= 13; i++) + { + if (a_key_template[i].pValue != NULL) + { + (void) memset(a_key_template[i].pValue, 0, + a_key_template[i].ulValueLen); + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss. Objects are cleaned only if we have a full cache miss, + * meaning that it's a different RSA key pair. Return 1 for cache hit, 0 for + * cache miss. + */ +static int +pk11_check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa) + { + /* + * Provide protection against RSA structure reuse by making the + * check for cache hit stronger. Only public components of RSA + * key matter here so it is sufficient to compare them with values + * cached in PK11_SESSION structure. + * + * We must check the handle as well since with key by reference, public + * components 'n'/'e' are cached in private keys as well. That means we + * could have a cache hit in a private key when looking for a public + * key. That would not work, you cannot have one PKCS#11 object for + * both data signing and verifying. + */ + if (sp->opdata_rsa_pub == rsa && + BN_cmp(sp->opdata_rsa_n_num, rsa->n) == 0 && + BN_cmp(sp->opdata_rsa_e_num, rsa->e) == 0) + { + if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE) + return (1); + else + /* + * No public key object yet but we have the right RSA + * structure with potentially existing private key + * object. We can just create a public object and move + * on with this session structure. + */ + return (0); + } + + /* + * A different RSA key pair was using this session structure previously + * or it's an empty structure. Destroy what we can. + */ + (void) pk11_destroy_rsa_object_pub(sp, CK_TRUE); + (void) pk11_destroy_rsa_object_priv(sp, CK_TRUE); + return (0); + } + +/* + * Check for cache miss. Objects are cleaned only if we have a full cache miss, + * meaning that it's a different RSA key pair. Return 1 for cache hit, 0 for + * cache miss. + */ +static int +pk11_check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa) + { + /* + * Provide protection against RSA structure reuse by making the + * check for cache hit stronger. Comparing public exponent of RSA + * key with value cached in PK11_SESSION structure should + * be sufficient. Note that we want to compare the public component + * since with the keys by reference mechanism, private components are + * not in the RSA structure. Also, see pk11_check_new_rsa_key_pub() + * about why we compare the handle as well. + */ + if (sp->opdata_rsa_priv == rsa && + BN_cmp(sp->opdata_rsa_n_num, rsa->n) == 0 && + BN_cmp(sp->opdata_rsa_e_num, rsa->e) == 0) + { + if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE) + return (1); + else + /* + * No private key object yet but we have the right RSA + * structure with potentially existing public key + * object. We can just create a private object and move + * on with this session structure. + */ + return (0); + } + + /* + * A different RSA key pair was using this session structure previously + * or it's an empty structure. Destroy what we can. + */ + (void) pk11_destroy_rsa_object_priv(sp, CK_TRUE); + (void) pk11_destroy_rsa_object_pub(sp, CK_TRUE); + return (0); + } +#endif + +#ifndef OPENSSL_NO_DSA +/* The DSA function implementation */ +/* ARGSUSED */ +static int pk11_DSA_init(DSA *dsa) + { + return (1); + } + +/* ARGSUSED */ +static int pk11_DSA_finish(DSA *dsa) + { + return (1); + } + + +static DSA_SIG * +pk11_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) + { + BIGNUM *r = NULL, *s = NULL; + int i; + DSA_SIG *dsa_sig = NULL; + + CK_RV rv; + CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0}; + CK_MECHANISM *p_mech = &Mechanism_dsa; + CK_OBJECT_HANDLE h_priv_key; + + /* + * The signature is the concatenation of r and s, + * each is 20 bytes long + */ + unsigned char sigret[DSA_SIGNATURE_LEN]; + unsigned long siglen = DSA_SIGNATURE_LEN; + unsigned int siglen2 = DSA_SIGNATURE_LEN / 2; + + PK11_SESSION *sp = NULL; + + if ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL)) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MISSING_KEY_COMPONENT); + goto ret; + } + + i = BN_num_bytes(dsa->q); /* should be 20 */ + if (dlen > i) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_INVALID_SIGNATURE_LENGTH); + goto ret; + } + + if ((sp = pk11_get_session(OP_DSA)) == NULL) + goto ret; + + (void) check_new_dsa_key_priv(sp, dsa); + + h_priv_key = sp->opdata_dsa_priv_key; + if (h_priv_key == CK_INVALID_HANDLE) + h_priv_key = sp->opdata_dsa_priv_key = + pk11_get_private_dsa_key((DSA *)dsa, + &sp->opdata_dsa_priv, + &sp->opdata_dsa_priv_num, sp->session); + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGNINIT, rv); + goto ret; + } + + (void) memset(sigret, 0, siglen); + rv = pFuncList->C_Sign(sp->session, + (unsigned char *) dgst, dlen, sigret, + (CK_ULONG_PTR) &siglen); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGN, rv); + goto ret; + } + } + + + if ((s = BN_new()) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + if ((r = BN_new()) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + if ((dsa_sig = DSA_SIG_new()) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + if (BN_bin2bn(sigret, siglen2, r) == NULL || + BN_bin2bn(&sigret[siglen2], siglen2, s) == NULL) + { + PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); + goto ret; + } + + dsa_sig->r = r; + dsa_sig->s = s; + +ret: + if (dsa_sig == NULL) + { + if (r != NULL) + BN_free(r); + if (s != NULL) + BN_free(s); + } + + pk11_return_session(sp, OP_DSA); + return (dsa_sig); + } + +static int +pk11_dsa_do_verify(const unsigned char *dgst, int dlen, DSA_SIG *sig, + DSA *dsa) + { + int i; + CK_RV rv; + int retval = 0; + CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0}; + CK_MECHANISM *p_mech = &Mechanism_dsa; + CK_OBJECT_HANDLE h_pub_key; + + unsigned char sigbuf[DSA_SIGNATURE_LEN]; + unsigned long siglen = DSA_SIGNATURE_LEN; + unsigned long siglen2 = DSA_SIGNATURE_LEN/2; + + PK11_SESSION *sp = NULL; + + if (BN_is_zero(sig->r) || sig->r->neg || BN_ucmp(sig->r, dsa->q) >= 0) + { + PK11err(PK11_F_DSA_VERIFY, + PK11_R_INVALID_DSA_SIGNATURE_R); + goto ret; + } + + if (BN_is_zero(sig->s) || sig->s->neg || BN_ucmp(sig->s, dsa->q) >= 0) + { + PK11err(PK11_F_DSA_VERIFY, + PK11_R_INVALID_DSA_SIGNATURE_S); + goto ret; + } + + i = BN_num_bytes(dsa->q); /* should be 20 */ + + if (dlen > i) + { + PK11err(PK11_F_DSA_VERIFY, + PK11_R_INVALID_SIGNATURE_LENGTH); + goto ret; + } + + if ((sp = pk11_get_session(OP_DSA)) == NULL) + goto ret; + + (void) check_new_dsa_key_pub(sp, dsa); + + h_pub_key = sp->opdata_dsa_pub_key; + if (h_pub_key == CK_INVALID_HANDLE) + h_pub_key = sp->opdata_dsa_pub_key = + pk11_get_public_dsa_key((DSA *)dsa, &sp->opdata_dsa_pub, + &sp->opdata_dsa_pub_num, sp->session); + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_VerifyInit(sp->session, p_mech, + h_pub_key); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFYINIT, + rv); + goto ret; + } + + /* + * The representation of each of the two big numbers could + * be shorter than DSA_SIGNATURE_LEN/2 bytes so we need + * to act accordingly and shift if necessary. + */ + (void) memset(sigbuf, 0, siglen); + BN_bn2bin(sig->r, sigbuf + siglen2 - BN_num_bytes(sig->r)); + BN_bn2bin(sig->s, &sigbuf[siglen2] + siglen2 - + BN_num_bytes(sig->s)); + + rv = pFuncList->C_Verify(sp->session, + (unsigned char *) dgst, dlen, sigbuf, (CK_ULONG)siglen); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFY, rv); + goto ret; + } + } + + retval = 1; +ret: + + pk11_return_session(sp, OP_DSA); + return (retval); + } + + +/* + * Create a public key object in a session from a given dsa structure. + * The *dsa_pub_num pointer is non-NULL for DSA public keys. + */ +static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa, + DSA **key_ptr, BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_ULONG found; + CK_KEY_TYPE k_type = CKK_DSA; + CK_ULONG ul_key_attr_count = 8; + CK_BBOOL rollback = CK_FALSE; + int i; + + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &pk11_false, sizeof (pk11_false)}, + {CKA_VERIFY, &pk11_true, sizeof (pk11_true)}, + {CKA_PRIME, (void *)NULL, 0}, /* p */ + {CKA_SUBPRIME, (void *)NULL, 0}, /* q */ + {CKA_BASE, (void *)NULL, 0}, /* g */ + {CKA_VALUE, (void *)NULL, 0} /* pub_key - y */ + }; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + if (init_template_value(dsa->p, &a_key_template[4].pValue, + &a_key_template[4].ulValueLen) == 0 || + init_template_value(dsa->q, &a_key_template[5].pValue, + &a_key_template[5].ulValueLen) == 0 || + init_template_value(dsa->g, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(dsa->pub_key, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_DSA); + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if (dsa_pub_num != NULL) + if ((*dsa_pub_num = BN_dup(dsa->pub_key)) == NULL) + { + PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = CK_TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_DSA, CK_FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = dsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_DSA); + +malloc_err: + for (i = 4; i <= 7; i++) + { + if (a_key_template[i].pValue != NULL) + { + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Create a private key object in the session from a given dsa structure + * The *dsa_priv_num pointer is non-NULL for DSA private keys. + */ +static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa, + DSA **key_ptr, BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY; + int i; + CK_ULONG found; + CK_KEY_TYPE k_type = CKK_DSA; + CK_ULONG ul_key_attr_count = 9; + CK_BBOOL rollback = CK_FALSE; + + /* + * Both CKA_TOKEN and CKA_SENSITIVE have to be CK_FALSE for session keys + */ + CK_ATTRIBUTE a_key_template[] = + { + {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, + {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, + {CKA_TOKEN, &pk11_false, sizeof (pk11_false)}, + {CKA_SENSITIVE, &pk11_false, sizeof (pk11_false)}, + {CKA_SIGN, &pk11_true, sizeof (pk11_true)}, + {CKA_PRIME, (void *)NULL, 0}, /* p */ + {CKA_SUBPRIME, (void *)NULL, 0}, /* q */ + {CKA_BASE, (void *)NULL, 0}, /* g */ + {CKA_VALUE, (void *)NULL, 0} /* priv_key - x */ + }; + + a_key_template[0].pValue = &o_key; + a_key_template[1].pValue = &k_type; + + /* Put the private key components into the template */ + if (init_template_value(dsa->p, &a_key_template[5].pValue, + &a_key_template[5].ulValueLen) == 0 || + init_template_value(dsa->q, &a_key_template[6].pValue, + &a_key_template[6].ulValueLen) == 0 || + init_template_value(dsa->g, &a_key_template[7].pValue, + &a_key_template[7].ulValueLen) == 0 || + init_template_value(dsa->priv_key, &a_key_template[8].pValue, + &a_key_template[8].ulValueLen) == 0) + { + PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_DSA); + rv = pFuncList->C_FindObjectsInit(session, a_key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_FINDOBJECTSFINAL, rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + a_key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, + PK11_R_CREATEOBJECT, rv); + goto err; + } + } + + if (dsa_priv_num != NULL) + if ((*dsa_priv_num = BN_dup(dsa->priv_key)) == NULL) + { + PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE); + rollback = CK_TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_DSA, CK_FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = dsa; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_DSA); + +malloc_err: + /* + * 5 to 8 entries in the key template are key components. + * They need to be freed apon exit or error. + */ + for (i = 5; i <= 8; i++) + { + if (a_key_template[i].pValue != NULL) + { + (void) memset(a_key_template[i].pValue, 0, + a_key_template[i].ulValueLen); + OPENSSL_free(a_key_template[i].pValue); + a_key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa) + { + /* + * Provide protection against DSA structure reuse by making the + * check for cache hit stronger. Only public key component of DSA + * key matters here so it is sufficient to compare it with value + * cached in PK11_SESSION structure. + */ + if ((sp->opdata_dsa_pub != dsa) || + (BN_cmp(sp->opdata_dsa_pub_num, dsa->pub_key) != 0)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_dsa_object_pub(sp, CK_TRUE); + return (0); + } + return (1); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + */ +static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa) + { + /* + * Provide protection against DSA structure reuse by making the + * check for cache hit stronger. Only private key component of DSA + * key matters here so it is sufficient to compare it with value + * cached in PK11_SESSION structure. + */ + if ((sp->opdata_dsa_priv != dsa) || + (BN_cmp(sp->opdata_dsa_priv_num, dsa->priv_key) != 0)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_dsa_object_priv(sp, CK_TRUE); + return (0); + } + return (1); + } +#endif + + +#ifndef OPENSSL_NO_DH +/* The DH function implementation */ +/* ARGSUSED */ +static int pk11_DH_init(DH *dh) + { + return (1); + } + +/* ARGSUSED */ +static int pk11_DH_finish(DH *dh) + { + return (1); + } + +/* + * Generate DH key-pair. + * + * Warning: Unlike OpenSSL's DH_generate_key(3) we ignore dh->priv_key + * and override it even if it is set. OpenSSL does not touch dh->priv_key + * if set and just computes dh->pub_key. It looks like PKCS#11 standard + * is not capable of providing this functionality. This could be a problem + * for applications relying on OpenSSL's semantics. + */ +static int pk11_DH_generate_key(DH *dh) + { + CK_ULONG i; + CK_RV rv, rv1; + int reuse_mem_len = 0, ret = 0; + PK11_SESSION *sp = NULL; + CK_BYTE_PTR reuse_mem; + + CK_MECHANISM mechanism = {CKM_DH_PKCS_KEY_PAIR_GEN, NULL_PTR, 0}; + CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; + + CK_ULONG ul_pub_key_attr_count = 3; + CK_ATTRIBUTE pub_key_template[] = + { + {CKA_PRIVATE, &pk11_false, sizeof (pk11_false)}, + {CKA_PRIME, (void *)NULL, 0}, + {CKA_BASE, (void *)NULL, 0} + }; + + CK_ULONG ul_priv_key_attr_count = 3; + CK_ATTRIBUTE priv_key_template[] = + { + {CKA_PRIVATE, &pk11_false, sizeof (pk11_false)}, + {CKA_SENSITIVE, &pk11_false, sizeof (pk11_false)}, + {CKA_DERIVE, &pk11_true, sizeof (pk11_true)} + }; + + CK_ULONG pub_key_attr_result_count = 1; + CK_ATTRIBUTE pub_key_result[] = + { + {CKA_VALUE, (void *)NULL, 0} + }; + + CK_ULONG priv_key_attr_result_count = 1; + CK_ATTRIBUTE priv_key_result[] = + { + {CKA_VALUE, (void *)NULL, 0} + }; + + pub_key_template[1].ulValueLen = BN_num_bytes(dh->p); + if (pub_key_template[1].ulValueLen > 0) + { + /* + * We must not increase ulValueLen by DH_BUF_RESERVE since that + * could cause the same rounding problem. See definition of + * DH_BUF_RESERVE above. + */ + pub_key_template[1].pValue = + OPENSSL_malloc(pub_key_template[1].ulValueLen + + DH_BUF_RESERVE); + if (pub_key_template[1].pValue == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + + i = BN_bn2bin(dh->p, pub_key_template[1].pValue); + } + else + goto err; + + pub_key_template[2].ulValueLen = BN_num_bytes(dh->g); + if (pub_key_template[2].ulValueLen > 0) + { + pub_key_template[2].pValue = + OPENSSL_malloc(pub_key_template[2].ulValueLen + + DH_BUF_RESERVE); + if (pub_key_template[2].pValue == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + + i = BN_bn2bin(dh->g, pub_key_template[2].pValue); + } + else + goto err; + + /* + * Note: we are only using PK11_SESSION structure for getting + * a session handle. The objects created in this function are + * destroyed before return and thus not cached. + */ + if ((sp = pk11_get_session(OP_DH)) == NULL) + goto err; + + rv = pFuncList->C_GenerateKeyPair(sp->session, + &mechanism, + pub_key_template, + ul_pub_key_attr_count, + priv_key_template, + ul_priv_key_attr_count, + &h_pub_key, + &h_priv_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, PK11_R_GEN_KEY, rv); + goto err; + } + + /* + * Reuse the larger memory allocated. We know the larger memory + * should be sufficient for reuse. + */ + if (pub_key_template[1].ulValueLen > pub_key_template[2].ulValueLen) + { + reuse_mem = pub_key_template[1].pValue; + reuse_mem_len = pub_key_template[1].ulValueLen + DH_BUF_RESERVE; + } + else + { + reuse_mem = pub_key_template[2].pValue; + reuse_mem_len = pub_key_template[2].ulValueLen + DH_BUF_RESERVE; + } + + rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key, + pub_key_result, pub_key_attr_result_count); + rv1 = pFuncList->C_GetAttributeValue(sp->session, h_priv_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK || rv1 != CKR_OK) + { + rv = (rv != CKR_OK) ? rv : rv1; + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + if (((CK_LONG) pub_key_result[0].ulValueLen) <= 0 || + ((CK_LONG) priv_key_result[0].ulValueLen) <= 0) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_GETATTRIBUTVALUE); + goto err; + } + + /* Reuse the memory allocated */ + pub_key_result[0].pValue = reuse_mem; + pub_key_result[0].ulValueLen = reuse_mem_len; + + rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key, + pub_key_result, pub_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + if (pub_key_result[0].type == CKA_VALUE) + { + if (dh->pub_key == NULL) + if ((dh->pub_key = BN_new()) == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, + PK11_R_MALLOC_FAILURE); + goto err; + } + dh->pub_key = BN_bin2bn(pub_key_result[0].pValue, + pub_key_result[0].ulValueLen, dh->pub_key); + if (dh->pub_key == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + } + + /* Reuse the memory allocated */ + priv_key_result[0].pValue = reuse_mem; + priv_key_result[0].ulValueLen = reuse_mem_len; + + rv = pFuncList->C_GetAttributeValue(sp->session, h_priv_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_GETATTRIBUTVALUE, rv); + goto err; + } + + if (priv_key_result[0].type == CKA_VALUE) + { + if (dh->priv_key == NULL) + if ((dh->priv_key = BN_new()) == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, + PK11_R_MALLOC_FAILURE); + goto err; + } + dh->priv_key = BN_bin2bn(priv_key_result[0].pValue, + priv_key_result[0].ulValueLen, dh->priv_key); + if (dh->priv_key == NULL) + { + PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + } + + ret = 1; + +err: + + if (h_pub_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DestroyObject(sp->session, h_pub_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_DESTROYOBJECT, rv); + } + } + + if (h_priv_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DestroyObject(sp->session, h_priv_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_GEN_KEY, + PK11_R_DESTROYOBJECT, rv); + } + } + + for (i = 1; i <= 2; i++) + { + if (pub_key_template[i].pValue != NULL) + { + OPENSSL_free(pub_key_template[i].pValue); + pub_key_template[i].pValue = NULL; + } + } + + pk11_return_session(sp, OP_DH); + return (ret); + } + +static int pk11_DH_compute_key(unsigned char *key, const BIGNUM *pub_key, + DH *dh) + { + int i; + CK_MECHANISM mechanism = {CKM_DH_PKCS_DERIVE, NULL_PTR, 0}; + CK_OBJECT_CLASS key_class = CKO_SECRET_KEY; + CK_KEY_TYPE key_type = CKK_GENERIC_SECRET; + CK_OBJECT_HANDLE h_derived_key = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + + CK_ULONG ul_priv_key_attr_count = 2; + CK_ATTRIBUTE priv_key_template[] = + { + {CKA_CLASS, (void*) NULL, sizeof (key_class)}, + {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)}, + }; + + CK_ULONG priv_key_attr_result_count = 1; + CK_ATTRIBUTE priv_key_result[] = + { + {CKA_VALUE, (void *)NULL, 0} + }; + + CK_RV rv; + int ret = -1; + PK11_SESSION *sp = NULL; + + if (dh->priv_key == NULL) + goto err; + + priv_key_template[0].pValue = &key_class; + priv_key_template[1].pValue = &key_type; + + if ((sp = pk11_get_session(OP_DH)) == NULL) + goto err; + + mechanism.ulParameterLen = BN_num_bytes(pub_key); + mechanism.pParameter = OPENSSL_malloc(mechanism.ulParameterLen); + if (mechanism.pParameter == NULL) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + BN_bn2bin(pub_key, mechanism.pParameter); + + (void) check_new_dh_key(sp, dh); + + h_key = sp->opdata_dh_key; + if (h_key == CK_INVALID_HANDLE) + h_key = sp->opdata_dh_key = + pk11_get_dh_key((DH*) dh, &sp->opdata_dh, + &sp->opdata_dh_priv_num, sp->session); + + if (h_key == CK_INVALID_HANDLE) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_CREATEOBJECT); + goto err; + } + + rv = pFuncList->C_DeriveKey(sp->session, + &mechanism, + h_key, + priv_key_template, + ul_priv_key_attr_count, + &h_derived_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_DERIVEKEY, rv); + goto err; + } + + rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE, + rv); + goto err; + } + + if (((CK_LONG) priv_key_result[0].ulValueLen) <= 0) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE); + goto err; + } + priv_key_result[0].pValue = + OPENSSL_malloc(priv_key_result[0].ulValueLen); + if (!priv_key_result[0].pValue) + { + PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE); + goto err; + } + + rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key, + priv_key_result, priv_key_attr_result_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE, + rv); + goto err; + } + + /* + * OpenSSL allocates the output buffer 'key' which is the same + * length of the public key. It is long enough for the derived key + */ + if (priv_key_result[0].type == CKA_VALUE) + { + /* + * CKM_DH_PKCS_DERIVE mechanism is not supposed to strip + * leading zeros from a computed shared secret. However, + * OpenSSL always did it so we must do the same here. The + * vagueness of the spec regarding leading zero bytes was + * finally cleared with TLS 1.1 (RFC 4346) saying that leading + * zeros are stripped before the computed data is used as the + * pre-master secret. + */ + for (i = 0; i < priv_key_result[0].ulValueLen; ++i) + { + if (((char *)priv_key_result[0].pValue)[i] != 0) + break; + } + + (void) memcpy(key, ((char *)priv_key_result[0].pValue) + i, + priv_key_result[0].ulValueLen - i); + ret = priv_key_result[0].ulValueLen - i; + } + +err: + + if (h_derived_key != CK_INVALID_HANDLE) + { + rv = pFuncList->C_DestroyObject(sp->session, h_derived_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_DH_COMP_KEY, + PK11_R_DESTROYOBJECT, rv); + } + } + if (priv_key_result[0].pValue) + { + OPENSSL_free(priv_key_result[0].pValue); + priv_key_result[0].pValue = NULL; + } + + if (mechanism.pParameter) + { + OPENSSL_free(mechanism.pParameter); + mechanism.pParameter = NULL; + } + + pk11_return_session(sp, OP_DH); + return (ret); + } + + +static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, + DH **key_ptr, BIGNUM **dh_priv_num, CK_SESSION_HANDLE session) + { + CK_RV rv; + CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; + CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; + CK_KEY_TYPE key_type = CKK_DH; + CK_ULONG found; + CK_BBOOL rollback = CK_FALSE; + int i; + + CK_ULONG ul_key_attr_count = 7; + CK_ATTRIBUTE key_template[] = + { + {CKA_CLASS, (void*) NULL, sizeof (class)}, + {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)}, + {CKA_DERIVE, &pk11_true, sizeof (pk11_true)}, + {CKA_PRIVATE, &pk11_false, sizeof (pk11_false)}, + {CKA_PRIME, (void *) NULL, 0}, + {CKA_BASE, (void *) NULL, 0}, + {CKA_VALUE, (void *) NULL, 0}, + }; + + key_template[0].pValue = &class; + key_template[1].pValue = &key_type; + + key_template[4].ulValueLen = BN_num_bytes(dh->p); + key_template[4].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)key_template[4].ulValueLen); + if (key_template[4].pValue == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(dh->p, key_template[4].pValue); + + key_template[5].ulValueLen = BN_num_bytes(dh->g); + key_template[5].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)key_template[5].ulValueLen); + if (key_template[5].pValue == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(dh->g, key_template[5].pValue); + + key_template[6].ulValueLen = BN_num_bytes(dh->priv_key); + key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc( + (size_t)key_template[6].ulValueLen); + if (key_template[6].pValue == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + goto malloc_err; + } + + BN_bn2bin(dh->priv_key, key_template[6].pValue); + + /* see find_lock array definition for more info on object locking */ + LOCK_OBJSTORE(OP_DH); + rv = pFuncList->C_FindObjectsInit(session, key_template, + ul_key_attr_count); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTS, rv); + goto err; + } + + rv = pFuncList->C_FindObjectsFinal(session); + + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSFINAL, + rv); + goto err; + } + + if (found == 0) + { + rv = pFuncList->C_CreateObject(session, + key_template, ul_key_attr_count, &h_key); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_CREATEOBJECT, + rv); + goto err; + } + } + + if (dh_priv_num != NULL) + if ((*dh_priv_num = BN_dup(dh->priv_key)) == NULL) + { + PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); + rollback = CK_TRUE; + goto err; + } + + /* LINTED: E_CONSTANT_CONDITION */ + KEY_HANDLE_REFHOLD(h_key, OP_DH, CK_FALSE, rollback, err); + if (key_ptr != NULL) + *key_ptr = dh; + +err: + if (rollback) + { + /* + * We do not care about the return value from C_DestroyObject() + * since we are doing rollback. + */ + if (found == 0) + (void) pFuncList->C_DestroyObject(session, h_key); + h_key = CK_INVALID_HANDLE; + } + + UNLOCK_OBJSTORE(OP_DH); + +malloc_err: + for (i = 4; i <= 6; i++) + { + if (key_template[i].pValue != NULL) + { + OPENSSL_free(key_template[i].pValue); + key_template[i].pValue = NULL; + } + } + + return (h_key); + } + +/* + * Check for cache miss and clean the object pointer and handle + * in such case. Return 1 for cache hit, 0 for cache miss. + * + * Note: we rely on pk11_destroy_dh_key_objects() to set sp->opdata_dh + * to CK_INVALID_HANDLE even when it fails to destroy the object. + */ +static int check_new_dh_key(PK11_SESSION *sp, DH *dh) + { + /* + * Provide protection against DH structure reuse by making the + * check for cache hit stronger. Private key component of DH key + * is unique so it is sufficient to compare it with value cached + * in PK11_SESSION structure. + */ + if ((sp->opdata_dh != dh) || + (BN_cmp(sp->opdata_dh_priv_num, dh->priv_key) != 0)) + { + /* + * We do not check the return value because even in case of + * failure the sp structure will have both key pointer + * and object handle cleaned and pk11_destroy_object() + * reports the failure to the OpenSSL error message buffer. + */ + (void) pk11_destroy_dh_object(sp, CK_TRUE); + return (0); + } + return (1); + } +#endif + +/* + * Local function to simplify key template population + * Return 0 -- error, 1 -- no error + */ +static int +init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value, + CK_ULONG *ul_value_len) + { + CK_ULONG len; + + /* + * This function can be used on non-initialized BIGNUMs. It is easier to + * check that here than individually in the callers. + */ + if (bn != NULL) + len = BN_num_bytes(bn); + + if (bn == NULL || len == 0) + return (1); + + *ul_value_len = len; + *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len); + if (*p_value == NULL) + return (0); + + BN_bn2bin(bn, *p_value); + + return (1); + } + +static void +attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn) + { + if (attr->ulValueLen > 0) + *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL); + } + +/* + * Find one object in the token. It is an error if we can not find the object or + * if we find more objects based on the template we got. + * + * Returns: + * 1 OK + * 0 no object or more than 1 object found + */ +static int +find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, + CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey) + { + CK_RV rv; + CK_ULONG objcnt; + + LOCK_OBJSTORE(op); + if ((rv = pFuncList->C_FindObjectsInit(s, ptempl, nattr)) != CKR_OK) + { + PK11err_add_data(PK11_F_FIND_ONE_OBJECT, + PK11_R_FINDOBJECTSINIT, rv); + goto err; + } + + rv = pFuncList->C_FindObjects(s, pkey, 1, &objcnt); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_FIND_ONE_OBJECT, PK11_R_FINDOBJECTS, + rv); + goto err; + } + + if (objcnt > 1) + { + PK11err(PK11_F_FIND_ONE_OBJECT, + PK11_R_MORE_THAN_ONE_OBJECT_FOUND); + goto err; + } + else + if (objcnt == 0) + { + PK11err(PK11_F_FIND_ONE_OBJECT, PK11_R_NO_OBJECT_FOUND); + goto err; + } + + (void) pFuncList->C_FindObjectsFinal(s); + UNLOCK_OBJSTORE(op); + return (1); +err: + UNLOCK_OBJSTORE(op); + return (0); + } + +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/engines/pkcs11/hw_pk11_uri.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/engines/pkcs11/hw_pk11_uri.c Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,870 @@ +/* + * Copyright (c) 2004, 2011, Oracle and/or its affiliates. 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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 + +#ifndef OPENSSL_NO_HW +#ifndef OPENSSL_NO_HW_PK11 + +#include +#include +#include "hw_pk11.h" +#include "hw_pk11_uri.h" + +/* + * The keystore used is always from the pubkey slot so we need to know which one + * was selected so that we can get the information needed for the URI + * processing. + */ +extern CK_SLOT_ID pubkey_SLOTID; +extern CK_FUNCTION_LIST_PTR pFuncList; + +/* + * Cached PIN so that child can use it during the re-login. Note that we do not + * cache the PIN by default. + */ +static char *token_pin; + +static int mlock_pin_in_memory(char *pin); +static char *run_askpass(char *dialog); + +/* + * Get the PIN. Either run the command and use its standard output as a PIN to + * fill in the PKCS11 URI structure, or read the PIN from the terminal. Using + * the external command is of higher precedence. The memory for PIN is allocated + * in this function and the PIN is always NULL terminated. The caller must take + * care of freeing the memory used for the PIN. The maximum PIN length accepted + * is PK11_MAX_PIN_LEN. + * + * The function is used also during the re-initialization of the engine after + * the fork. + * + * The function must not be called under the protection of the mutex "uri_lock" + * because the lock is acquired in the prefork function. + * + * Returns: + * 0 in case of troubles (and sets "*pin" to NULL) + * 1 if we got the PIN + */ +#define EXEC_SPEC "exec:" +#define BUILTIN_SPEC "builtin" +int +pk11_get_pin(char *dialog, char **pin) + { + /* Initialize as an error. */ + *pin = NULL; + + if (strcmp(dialog, BUILTIN_SPEC) == 0) + { + /* The getpassphrase() function is not MT safe. */ + (void) pthread_mutex_lock(uri_lock); + /* Note that OpenSSL is not localized at all. */ + *pin = getpassphrase("Enter token PIN: "); + if (*pin == NULL) + { + PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN); + (void) pthread_mutex_unlock(uri_lock); + goto err; + } + else + { + char *pw; + + /* + * getpassphrase() uses an internal buffer to hold the + * entered password. Note that it terminates the buffer + * with '\0'. + */ + if ((pw = strdup(*pin)) == NULL) + { + PK11err(PK11_F_GET_PIN, PK11_R_MALLOC_FAILURE); + (void) pthread_mutex_unlock(uri_lock); + goto err; + } + /* Zero the internal buffer to get rid of the PIN. */ + memset(*pin, 0, strlen(*pin)); + *pin = pw; + (void) pthread_mutex_unlock(uri_lock); + } + } + else + { + /* + * This is the "exec:" case. We will get the PIN from the output + * of an external command. + */ + if (strncmp(dialog, EXEC_SPEC, strlen(EXEC_SPEC)) == 0) + { + dialog += strlen(EXEC_SPEC); + if ((*pin = run_askpass(dialog)) == NULL) + goto err; + } + else + { + /* + * Invalid specification in the passphrasedialog + * keyword. + */ + PK11err(PK11_F_GET_PIN, PK11_R_BAD_PASSPHRASE_SPEC); + goto err; + } + } + + return (1); +err: + return (0); + } + +/* + * Process the PKCS#11 URI and get the PIN. It uses information from the + * passphrasedialog keyword to get the PIN. If passphrasedialog is not present + * it is not considered an error since it depends on the token attributes + * whether C_Login() is required. The function expects an allocated 'uri_struct' + * structure. + * + * Returns: + * 0 if URI is not valid at all, or if we could not get the PIN + * 1 if all is OK + * 2 if the URI is not the PKCS#11 URI. In that case, put the string + * pointer to the filename to "*file". Note that the pointer just points + * inside of the "uristr", possibly skipping the file:// prefix if present. + */ +int +pk11_process_pkcs11_uri(const char *uristr, pkcs11_uri *uri_struct, + const char **file) + { + char *uristr2, *l1, *l2, *tok, *name; + + /* Check the "file://" case. */ + if (strncmp(uristr, FILE_URI_PREFIX, strlen(FILE_URI_PREFIX)) == 0) + { + *file = uristr + strlen(FILE_URI_PREFIX); + return (2); + } + + /* This is the "pkcs11:" case. */ + if (strncmp(uristr, PK11_URI_PREFIX, strlen(PK11_URI_PREFIX)) != 0) + { + /* Not PKCS#11 URI at all, could be a filename. */ + *file = (const char *)uristr; + return (2); + } + else + { + /* Dup the string and skip over the pkcs11: prefix then. */ + uristr2 = strdup(uristr + strlen(PK11_URI_PREFIX)); + if (uristr2 == NULL) + { + PK11err(PK11_F_CHECK_TOKEN_ATTRS, + PK11_R_MALLOC_FAILURE); + goto err; + } + } + + /* Initialize the structure. */ + memset(uri_struct, 0, sizeof (*uri_struct)); + + /* + * Using strtok_r() would silently skip over multiple semicolons. We + * must check that before moving on. We must also avoid ';' as the first + * and the last character in the URI. + */ + if (strstr(uristr2, ";;") != NULL || uristr2[0] == ';' || + (strlen(uristr2) > 0 && uristr2[strlen(uristr2) - 1] == ';')) + goto bad_uri; + + tok = strtok_r(uristr2, ";", &l1); + for (; tok != NULL; tok = strtok_r(NULL, ";", &l1)) + { + /* "tok" is not empty so there will be something in "name". */ + name = strtok_r(tok, "=", &l2); + /* Check whether there is '=' at all. */ + if (l2 == NULL) + goto bad_uri; + + /* + * Fill out the URI structure. We do not accept duplicit + * attributes. + */ + if (strcmp(name, PK11_TOKEN) == 0) + if (uri_struct->token == NULL) + { + if ((uri_struct->token = strdup(l2)) == NULL) + goto no_mem; + } + else + goto bad_uri; + else if (strcmp(name, PK11_MANUF) == 0) + if (uri_struct->manuf == NULL) + { + if ((uri_struct->manuf = strdup(l2)) == NULL) + goto no_mem; + } + else + goto bad_uri; + else if (strcmp(name, PK11_SERIAL) == 0) + if (uri_struct->serial == NULL) + { + if ((uri_struct->serial = strdup(l2)) == NULL) + goto no_mem; + } + else + goto bad_uri; + else if (strcmp(name, PK11_MODEL) == 0) + if (uri_struct->model == NULL) + { + if ((uri_struct->model = strdup(l2)) == NULL) + goto no_mem; + } + else + goto bad_uri; + else if (strcmp(name, PK11_OBJECT) == 0) + if (uri_struct->object == NULL) + { + if ((uri_struct->object = strdup(l2)) == NULL) + goto no_mem; + } + else + goto bad_uri; + else if (strcmp(name, PK11_OBJECTTYPE) == 0) + if (uri_struct->objecttype == NULL) + { + uri_struct->objecttype = strdup(l2); + if (uri_struct->objecttype == NULL) + goto no_mem; + } + else + goto bad_uri; + else if (strcmp(name, PK11_ASKPASS) == 0) + if (uri_struct->askpass == NULL) + { + if ((uri_struct->askpass = strdup(l2)) == NULL) + goto no_mem; + } + else + goto bad_uri; + else + goto bad_uri; + } + + /* The "object" token is mandatory in the PKCS#11 URI. */ + if (uri_struct->object == NULL) + { + PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MISSING_OBJECT_LABEL); + goto err; + } + + free(uristr2); + return (1); +bad_uri: + PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_INVALID_PKCS11_URI); + if (uristr2 != NULL) + free(uristr2); + return (0); +no_mem: + PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE); +err: + pk11_free_pkcs11_uri(uri_struct, CK_FALSE); + if (uristr2 != NULL) + free(uristr2); + return (0); + } + +/* + * Free the PKCS11 URI structure and anything that might be inside. + */ +void +pk11_free_pkcs11_uri(pkcs11_uri *uri_struct, CK_BBOOL free_uri_itself) + { + if (uri_struct->token != NULL) + free(uri_struct->token); + if (uri_struct->manuf != NULL) + free(uri_struct->manuf); + if (uri_struct->serial != NULL) + free(uri_struct->serial); + if (uri_struct->model != NULL) + free(uri_struct->model); + if (uri_struct->object != NULL) + free(uri_struct->object); + if (uri_struct->objecttype != NULL) + free(uri_struct->objecttype); + if (uri_struct->askpass != NULL) + free(uri_struct->askpass); + + if (free_uri_itself == CK_TRUE) + OPENSSL_free(uri_struct); + } + +/* + * While our keystore is always the one used by the pubkey slot (which is + * usually the Metaslot) we must make sure that those URI attributes that + * specify the keystore match the real attributes of our slot keystore. Note + * that one can use the METASLOT_OBJECTSTORE_TOKEN environment variable to + * change the Metaslot's keystore from the softtoken to something else (see + * libpkcs11(3LIB)). The user might want to use such attributes in the PKCS#11 + * URI to make sure that the intended keystore is used. + * + * Returns: + * 1 on success + * 0 on failure + */ +int +pk11_check_token_attrs(pkcs11_uri *uri_struct) + { + CK_RV rv; + static CK_TOKEN_INFO_PTR token_info = NULL; + + (void) pthread_mutex_lock(uri_lock); + if (token_info == NULL) + { + token_info = OPENSSL_malloc(sizeof (CK_TOKEN_INFO)); + if (token_info == NULL) + { + PK11err(PK11_F_CHECK_TOKEN_ATTRS, + PK11_R_MALLOC_FAILURE); + goto err; + } + + rv = pFuncList->C_GetTokenInfo(pubkey_SLOTID, token_info); + if (rv != CKR_OK) + { + PK11err_add_data(PK11_F_CHECK_TOKEN_ATTRS, + PK11_R_GETTOKENINFO, rv); + goto err; + } + } + + if (uri_struct->token != NULL) + if (strncmp(uri_struct->token, (char *)token_info->label, + strlen(uri_struct->token) > 32 ? 32 : + strlen(uri_struct->token)) != 0) + { + goto urierr; + } + + if (uri_struct->manuf != NULL) + if (strncmp(uri_struct->manuf, + (char *)token_info->manufacturerID, + strlen(uri_struct->manuf) > 32 ? 32 : + strlen(uri_struct->manuf)) != 0) + goto urierr; + + if (uri_struct->model != NULL) + if (strncmp(uri_struct->model, (char *)token_info->model, + strlen(uri_struct->model) > 16 ? 16 : + strlen(uri_struct->model)) != 0) + goto urierr; + + if (uri_struct->serial != NULL) + if (strncmp(uri_struct->serial, + (char *)token_info->serialNumber, + strlen(uri_struct->serial) > 16 ? 16 : + strlen(uri_struct->serial)) != 0) + goto urierr; + + (void) pthread_mutex_unlock(uri_lock); + return (1); + +urierr: + PK11err(PK11_F_CHECK_TOKEN_ATTRS, PK11_R_TOKEN_ATTRS_DO_NOT_MATCH); + /* Correct error already set above for the "err" label. */ +err: + (void) pthread_mutex_unlock(uri_lock); + return (0); + } + +/* + * Return the process PIN caching policy. We initialize it just once so if the + * process change OPENSSL_PKCS11_PIN_CACHING_POLICY during the operation it will + * not have any affect on the policy. + * + * We assume that the "uri_lock" mutex is already locked. + * + * Returns the caching policy number. + */ +int +pk11_get_pin_caching_policy(void) + { + char *value = NULL; + static int policy = POLICY_NOT_INITIALIZED; + + if (policy != POLICY_NOT_INITIALIZED) + return (policy); + + value = getenv("OPENSSL_PKCS11_PIN_CACHING_POLICY"); + + if (value == NULL || strcmp(value, "none") == 0) + { + policy = POLICY_NONE; + goto done; + } + + if (strcmp(value, "memory") == 0) + { + policy = POLICY_MEMORY; + goto done; + } + + if (strcmp(value, "mlocked-memory") == 0) + { + policy = POLICY_MLOCKED_MEMORY; + goto done; + } + + return (POLICY_WRONG_VALUE); +done: + return (policy); + } + +/* + * Cache the PIN in memory once. We already know that we have either "memory" or + * "mlocked-memory" keyword correctly set. + * + * Returns: + * 1 on success + * 0 on failure + */ +int +pk11_cache_pin(char *pin) + { + (void) pthread_mutex_lock(uri_lock); + /* We set the PIN only once since all URIs must have it the same. */ + if (token_pin != NULL) + goto ok; + + if (pk11_get_pin_caching_policy() == POLICY_MEMORY) + if ((token_pin = strdup(pin)) == NULL) + { + PK11err(PK11_F_CACHE_PIN, PK11_R_MALLOC_FAILURE); + goto err; + } + else + if (pk11_get_pin_caching_policy() == POLICY_MLOCKED_MEMORY) + { + if (mlock_pin_in_memory(pin) == 0) + goto err; + } + +ok: + (void) pthread_mutex_unlock(uri_lock); + return (1); +err: + (void) pthread_mutex_unlock(uri_lock); + return (0); + } + +/* + * Cache the PIN in mlock(3C)ed memory. If mlock(3C) fails we will not resort to + * the normal memory caching. + * + * Note that this function must be called under the protection of the "uri_lock" + * mutex. + * + * Returns: + * 1 on success + * 0 on failure + */ +static int +mlock_pin_in_memory(char *pin) + { + void *addr = NULL; + long pagesize = 0; + + /* mlock(3C) locks pages so we need one whole page for the PIN. */ + if ((pagesize = sysconf(_SC_PAGESIZE)) == -1) + { + PK11err(PK11_F_MLOCK_PIN_IN_MEMORY, PK11_R_SYSCONF_FAILED); + goto err; + } + + /* This will ensure we have a page aligned pointer... */ + if ((addr = mmap(0, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0)) == MAP_FAILED) + { + PK11err(PK11_F_MLOCK_PIN_IN_MEMORY, PK11_R_MMAP_FAILED); + goto err; + } + + /* ...because "addr" must be page aligned here. */ + if (mlock(addr, pagesize) == -1) + { + /* + * Missing the PRIV_PROC_LOCK_MEMORY privilege might be a common + * problem so distinguish this situation from other issues. + */ + if (errno == EPERM) + PK11err(PK11_F_MLOCK_PIN_IN_MEMORY, + PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING); + else + PK11err(PK11_F_MLOCK_PIN_IN_MEMORY, + PK11_R_MLOCK_FAILED); + + /* + * We already have a problem here so there is no need to check + * that we could unmap the page. The PIN is not there yet + * anyway. + */ + (void) munmap(addr, pagesize); + goto err; + } + + /* Copy the PIN to the mlocked memory. */ + token_pin = (char *)addr; + strlcpy(token_pin, pin, PK11_MAX_PIN_LEN + 1); + return (1); +err: + return (0); + } + +/* + * Log in to the keystore if we are supposed to do that at all. Take care of + * reading and caching the PIN etc. Log in only once even when called from + * multiple threads. + * + * Returns: + * 1 on success + * 0 on failure + */ +int +pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, + pkcs11_uri *uri_struct, CK_BBOOL is_private) + { + CK_RV rv; + + if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_NOT_INITIALIZED); + goto err; + } + + /* + * If login is required or needed but the PIN has not been even + * initialized we can bail out right now. Note that we are supposed to + * always log in if we are going to access private keys. However, we may + * need to log in even for accessing public keys in case that the + * CKF_LOGIN_REQUIRED flag is set. + */ + if ((pubkey_token_flags & CKF_LOGIN_REQUIRED || + is_private == CK_TRUE) && ~pubkey_token_flags & + CKF_USER_PIN_INITIALIZED) + { + PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET); + goto err; + } + + /* + * Note on locking: it is possible that more than one thread gets into + * pk11_get_pin() so we must deal with that. We cannot avoid it since we + * cannot guard fork() in there with a lock because we could end up in + * a dead lock in the child. Why? Remember we are in a multithreaded + * environment so we must lock all mutexes in the prefork function to + * avoid a situation in which a thread that did not call fork() held a + * lock, making future unlocking impossible. We lock right before + * C_Login(). + */ + if (pubkey_token_flags & CKF_LOGIN_REQUIRED || is_private == CK_TRUE) + { + if (*login_done == CK_FALSE && + uri_struct->askpass == NULL) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_PIN_NOT_PROVIDED); + goto err; + } + + if (*login_done == CK_FALSE && + uri_struct->askpass != NULL) + { + if (pk11_get_pin(uri_struct->askpass, + &uri_struct->pin) == 0) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_PIN_NOT_PROVIDED); + goto err; + } + } + + /* + * Note that what we are logging into is the keystore from + * pubkey_SLOTID because we work with OP_RSA session type here. + * That also means that we can work with only one keystore in + * the engine. + * + * We must make sure we do not try to login more than once. + * Also, see the comment above on locking strategy. + */ + (void) pthread_mutex_lock(uri_lock); + if (*login_done == CK_FALSE) + { + if ((rv = pFuncList->C_Login(session, + CKU_USER, (CK_UTF8CHAR*)uri_struct->pin, + strlen(uri_struct->pin))) != CKR_OK) + { + PK11err_add_data(PK11_F_TOKEN_LOGIN, + PK11_R_TOKEN_LOGIN_FAILED, rv); + goto err_locked; + } + + *login_done = CK_TRUE; + + /* + * Cache the passphrasedialog for possible child (which + * would need to relogin). + */ + if (passphrasedialog == NULL && + uri_struct->askpass != NULL) + { + passphrasedialog = + strdup(uri_struct->askpass); + + if (passphrasedialog == NULL) + { + PK11err_add_data(PK11_F_TOKEN_LOGIN, + PK11_R_MALLOC_FAILURE, rv); + goto err_locked; + } + } + + /* + * Check the PIN caching policy. Note that user might + * have provided a PIN even when no PIN was required - + * in that case we always remove the PIN from memory. + */ + if (pk11_get_pin_caching_policy() == + POLICY_WRONG_VALUE) + { + PK11err(PK11_F_TOKEN_LOGIN, + PK11_R_PIN_CACHING_POLICY_INVALID); + goto err_locked; + } + + if (pk11_get_pin_caching_policy() != POLICY_NONE) + if (pk11_cache_pin(uri_struct->pin) == 0) + goto err_locked; + } + (void) pthread_mutex_unlock(uri_lock); + } + else + { + /* + * If token does not require login we take it as the + * login was done. + */ + *login_done = CK_TRUE; + } + + /* + * If we raced at pk11_get_pin() we must make sure that all threads that + * called pk11_get_pin() will erase the PIN from memory, not just the + * one that called C_Login(). Note that if we were supposed to cache the + * PIN it was already cached by now so filling "uri_struct.pin" with + * zero bytes is always OK since pk11_cache_pin() makes a copy of it. + */ + if (uri_struct->pin != NULL) + memset(uri_struct->pin, 0, strlen(uri_struct->pin)); + + return (1); + +err_locked: + (void) pthread_mutex_unlock(uri_lock); +err: + /* Always get rid of the PIN. */ + if (uri_struct->pin != NULL) + memset(uri_struct->pin, 0, strlen(uri_struct->pin)); + return (0); + } + +/* + * Log in to the keystore in the child if we were logged in in the parent. There + * are similarities in the code with pk11_token_login() but still it is quite + * different so we need a separate function for this. + * + * Note that this function is called under the locked session mutex when fork is + * detected. That means that C_Login() will be called from the child just once. + * + * Returns: + * 1 on success + * 0 on failure + */ +int +pk11_token_relogin(CK_SESSION_HANDLE session) + { + CK_RV rv; + + /* + * We are in the child so check if we should login to the token again. + * Note that it is enough to log in to the token through one session + * only, all already open and all future sessions can access the token + * then. + */ + if (passphrasedialog != NULL) + { + char *pin = NULL; + + /* If we cached the PIN then use it. */ + if (token_pin != NULL) + pin = token_pin; + else if (pk11_get_pin(passphrasedialog, &pin) == 0) + goto err; + + (void) pthread_mutex_lock(uri_lock); + if ((rv = pFuncList->C_Login(session, CKU_USER, + (CK_UTF8CHAR_PTR)pin, strlen(pin))) != CKR_OK) + { + PK11err_add_data(PK11_F_TOKEN_RELOGIN, + PK11_R_TOKEN_LOGIN_FAILED, rv); + (void) pthread_mutex_unlock(uri_lock); + goto err; + } + (void) pthread_mutex_unlock(uri_lock); + + /* Forget the PIN now if we did not cache it before. */ + if (pin != token_pin) + { + memset(pin, 0, strlen(pin)); + OPENSSL_free(pin); + } + } + + return (1); +err: + return (0); + } + +/* + * This function forks and runs an external command. It would be nice if we + * could use popen(3C)/pclose(3C) for that but unfortunately we need to be able + * to get rid of the PIN from the memory. With p(open|close) function calls we + * cannot control the stdio's memory used for buffering and our tests showed + * that the PIN really stays there even after pclose(). + * + * Returns: + * allocated buffer on success + * NULL on failure + */ +static char * +run_askpass(char *dialog) + { + pid_t pid; + int n, p[2]; + char *buf = NULL; + + if (pipe(p) == -1) + { + PK11err(PK11_F_RUN_ASKPASS, PK11_R_PIPE_FAILED); + return (NULL); + } + + switch (pid = fork()) + { + case -1: + PK11err(PK11_F_RUN_ASKPASS, PK11_R_FORK_FAILED); + return (NULL); + /* child */ + case 0: + /* + * This should make sure that dup2() will not fail on + * file descriptor shortage. + */ + close(p[0]); + (void) dup2(p[1], 1); + close(p[1]); + /* + * Note that we cannot use PK11err() here since we are + * in the child. However, parent will get read() error + * so do not worry. + */ + (void) execl(dialog, basename(dialog), NULL); + exit(1); + /* parent */ + default: + /* +1 is for the terminating '\0' */ + buf = (char *)OPENSSL_malloc(PK11_MAX_PIN_LEN + 1); + if (buf == NULL) + { + PK11err(PK11_F_RUN_ASKPASS, + PK11_R_MALLOC_FAILURE); + return (NULL); + } + + close(p[1]); + n = read(p[0], buf, PK11_MAX_PIN_LEN); + if (n == -1 || n == 0) + { + PK11err(PK11_F_RUN_ASKPASS, + PK11_R_PIN_NOT_READ_FROM_COMMAND); + OPENSSL_free(buf); + return (NULL); + } + buf[n] = '\0'; + + (void) waitpid(pid, NULL, 0); + } + + return (buf); + } + +#endif /* OPENSSL_NO_HW_PK11 */ +#endif /* OPENSSL_NO_HW */ diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/engines/pkcs11/hw_pk11_uri.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/engines/pkcs11/hw_pk11_uri.h Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2004, 2013, Oracle and/or its affiliates. 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + */ + +#ifndef HW_PK11_URI_H +#define HW_PK11_URI_H + +#include + +/* PKCS#11 URI related prefixes and attributes. */ +#define PK11_URI_PREFIX "pkcs11:" +#define FILE_URI_PREFIX "file://" +#define PK11_TOKEN "token" +#define PK11_MANUF "manuf" +#define PK11_SERIAL "serial" +#define PK11_MODEL "model" +#define PK11_OBJECT "object" +#define PK11_OBJECTTYPE "objecttype" +#define PK11_ASKPASS "passphrasedialog" + +/* PIN caching policy. */ +#define POLICY_NOT_INITIALIZED 0 +#define POLICY_NONE 1 +#define POLICY_MEMORY 2 +#define POLICY_MLOCKED_MEMORY 3 +#define POLICY_WRONG_VALUE 4 + +/* + * That's what getpassphrase(3c) supports. + */ +#define PK11_MAX_PIN_LEN 256 + +/* Add new attributes of the PKCS#11 URI here. */ +typedef struct pkcs11_uri_struct + { + char *object; /* object label, the only mandatory info */ + char *objecttype; /* (private|public|cert), currently unused */ + char *token; /* token label */ + char *manuf; /* manufacturer label */ + char *serial; /* serial number label */ + char *model; /* model label */ + char *askpass; /* full path to the command to get the PIN */ + /* Not part of the PKCS11 URI itself. */ + char *pin; /* token PIN */ + } pkcs11_uri; + +/* For URI processing. */ +extern pthread_mutex_t *uri_lock; + +int pk11_get_pin(char *dialog, char **pin); +int pk11_get_pin_caching_policy(void); +int pk11_process_pkcs11_uri(const char *uristr, pkcs11_uri *uri_struct, + const char **file); +int pk11_check_token_attrs(pkcs11_uri *uri_struct); +void pk11_free_pkcs11_uri(pkcs11_uri *uri_struct, CK_BBOOL free_uri_itself); +int pk11_cache_pin(char *pin); +int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, + pkcs11_uri *uri_struct, CK_BBOOL is_private); +int pk11_token_relogin(CK_SESSION_HANDLE session); + +#endif /* HW_PK11_URI_H */ diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/llib-lcrypto --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/llib-lcrypto Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,68 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + */ + +/* LINTLIBRARY */ +/* PROTOLIB1 */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/llib-lssl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/llib-lssl Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,32 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + */ + +/* LINTLIBRARY */ +/* PROTOLIB1 */ + +#include +#include +#include +#include diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/openssl-0.9.8-fips-140.license --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/openssl-0.9.8-fips-140.license Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,127 @@ + + LICENSE ISSUES + ============== + + The OpenSSL toolkit stays under a dual license, i.e. both the conditions of + the OpenSSL License and the original SSLeay license apply to the toolkit. + See below for the actual license texts. Actually both licenses are BSD-style + Open Source licenses. In case of any license issues related to OpenSSL + please contact openssl-core@openssl.org. + + OpenSSL License + --------------- + +/* ==================================================================== + * Copyright (c) 1998-2008 The OpenSSL Project. 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. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + + Original SSLeay License + ----------------------- + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * 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 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/openssl-0.9.8-fips-140.p5m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/openssl-0.9.8-fips-140.p5m Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,133 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +# + + default mangler.man.stability uncommitted> +set name=pkg.fmri \ + value=pkg:/library/security/openssl/openssl-fips-140@$(IPS_COMPONENT_VERSION),$(BUILD_VERSION) +set name=pkg.human-version value=$(COMPONENT_VERSION) +set name=pkg.summary value="FIPS 140-2 Capable OpenSSL libraries" +set name=com.oracle.info.description value="the FIPS 140-2 Capable OpenSSL libraries" +set name=com.oracle.info.tpno value=13019 +set name=info.classification \ + value="org.opensolaris.category.2008:System/Security" +set name=info.source-url value=$(COMPONENT_ARCHIVE_URL) +set name=info.upstream-url value=$(COMPONENT_PROJECT_URL) +set name=org.opensolaris.arc-caseid \ + value=PSARC/2009/507 +set name=org.opensolaris.consolidation value=$(CONSOLIDATION) +# Basic directories and a configuration file. +file etc/openssl/openssl.cnf path=etc/openssl/fips-140/openssl.cnf group=sys mode=0644 preserve=true +link path=lib/openssl/fips-140/64 target=$(MACH64) +# 32 bit libraries, lint libraries, and engines. +file $(MACH32)/libcrypto.so.0.9.8 path=lib/openssl/fips-140/libcrypto.so.0.9.8 +link path=lib/openssl/fips-140/libcrypto.so target=libcrypto.so.0.9.8 +file $(MACH32)/libssl.so.0.9.8 path=lib/openssl/fips-140/libssl.so.0.9.8 +link path=lib/openssl/fips-140/libssl.so target=libssl.so.0.9.8 +file llib-lcrypto path=lib/openssl/fips-140/llib-lcrypto +file $(MACH32)/llib-lcrypto.ln path=lib/openssl/fips-140/llib-lcrypto.ln +file llib-lssl path=lib/openssl/fips-140/llib-lssl +file $(MACH32)/llib-lssl.ln path=lib/openssl/fips-140/llib-lssl.ln +# 64 bit libraries, lint libraries, and engines. +file $(MACH64)/libcrypto.so.0.9.8 path=lib/openssl/fips-140/$(MACH64)/libcrypto.so.0.9.8 +link path=lib/openssl/fips-140/$(MACH64)/libcrypto.so target=libcrypto.so.0.9.8 +file $(MACH64)/libssl.so.0.9.8 path=lib/openssl/fips-140/$(MACH64)/libssl.so.0.9.8 +link path=lib/openssl/fips-140/$(MACH64)/libssl.so target=libssl.so.0.9.8 +file llib-lcrypto path=lib/openssl/fips-140/$(MACH64)/llib-lcrypto +file $(MACH64)/llib-lcrypto.ln path=lib/openssl/fips-140/$(MACH64)/llib-lcrypto.ln +file llib-lssl path=lib/openssl/fips-140/$(MACH64)/llib-lssl +file $(MACH64)/llib-lssl.ln path=lib/openssl/fips-140/$(MACH64)/llib-lssl.ln +# Header files. +# +# Take header files from the 32-bit build. This build has the patched +# opensslconf.h (64-bit build does not). We cannot take header files from the +# proto area since it could contain headers installed for the 64-bit build. + \ + set action.hash $(MACH32)/include/openssl/%<1> > +file path=usr/include/openssl/fips-140/openssl/aes.h +file path=usr/include/openssl/fips-140/openssl/asn1.h +file path=usr/include/openssl/fips-140/openssl/asn1_mac.h +file path=usr/include/openssl/fips-140/openssl/asn1t.h +file path=usr/include/openssl/fips-140/openssl/bio.h +file path=usr/include/openssl/fips-140/openssl/blowfish.h +file path=usr/include/openssl/fips-140/openssl/bn.h +file path=usr/include/openssl/fips-140/openssl/buffer.h +file path=usr/include/openssl/fips-140/openssl/cast.h +file path=usr/include/openssl/fips-140/openssl/comp.h +file path=usr/include/openssl/fips-140/openssl/conf.h +file path=usr/include/openssl/fips-140/openssl/conf_api.h +file path=usr/include/openssl/fips-140/openssl/crypto.h +file path=usr/include/openssl/fips-140/openssl/des.h +file path=usr/include/openssl/fips-140/openssl/des_old.h +file path=usr/include/openssl/fips-140/openssl/dh.h +file path=usr/include/openssl/fips-140/openssl/dsa.h +file path=usr/include/openssl/fips-140/openssl/dso.h +file path=usr/include/openssl/fips-140/openssl/dtls1.h +file path=usr/include/openssl/fips-140/openssl/e_os2.h +file path=usr/include/openssl/fips-140/openssl/ebcdic.h +file path=usr/include/openssl/fips-140/openssl/engine.h +file path=usr/include/openssl/fips-140/openssl/err.h +file path=usr/include/openssl/fips-140/openssl/evp.h +file path=usr/include/openssl/fips-140/openssl/fips.h +file path=usr/include/openssl/fips-140/openssl/fips_rand.h +file path=usr/include/openssl/fips-140/openssl/hmac.h +file path=usr/include/openssl/fips-140/openssl/krb5_asn.h +file path=usr/include/openssl/fips-140/openssl/kssl.h +file path=usr/include/openssl/fips-140/openssl/lhash.h +file path=usr/include/openssl/fips-140/openssl/md2.h +file path=usr/include/openssl/fips-140/openssl/md4.h +file path=usr/include/openssl/fips-140/openssl/md5.h +file path=usr/include/openssl/fips-140/openssl/obj_mac.h +file path=usr/include/openssl/fips-140/openssl/objects.h +file path=usr/include/openssl/fips-140/openssl/ocsp.h +file path=usr/include/openssl/fips-140/openssl/opensslconf.h +file path=usr/include/openssl/fips-140/openssl/opensslv.h +file path=usr/include/openssl/fips-140/openssl/ossl_typ.h +file path=usr/include/openssl/fips-140/openssl/pem.h +file path=usr/include/openssl/fips-140/openssl/pem2.h +file path=usr/include/openssl/fips-140/openssl/pkcs12.h +file path=usr/include/openssl/fips-140/openssl/pkcs7.h +file path=usr/include/openssl/fips-140/openssl/pq_compat.h +file path=usr/include/openssl/fips-140/openssl/pqueue.h +file path=usr/include/openssl/fips-140/openssl/rand.h +file path=usr/include/openssl/fips-140/openssl/rc2.h +file path=usr/include/openssl/fips-140/openssl/rc4.h +file path=usr/include/openssl/fips-140/openssl/ripemd.h +file path=usr/include/openssl/fips-140/openssl/rsa.h +file path=usr/include/openssl/fips-140/openssl/safestack.h +file path=usr/include/openssl/fips-140/openssl/sha.h +file path=usr/include/openssl/fips-140/openssl/ssl.h +file path=usr/include/openssl/fips-140/openssl/ssl2.h +file path=usr/include/openssl/fips-140/openssl/ssl23.h +file path=usr/include/openssl/fips-140/openssl/ssl3.h +file path=usr/include/openssl/fips-140/openssl/stack.h +file path=usr/include/openssl/fips-140/openssl/store.h +file path=usr/include/openssl/fips-140/openssl/symhacks.h +file path=usr/include/openssl/fips-140/openssl/tls1.h +file path=usr/include/openssl/fips-140/openssl/tmdiff.h +file path=usr/include/openssl/fips-140/openssl/txt_db.h +file path=usr/include/openssl/fips-140/openssl/ui.h +file path=usr/include/openssl/fips-140/openssl/ui_compat.h +file path=usr/include/openssl/fips-140/openssl/x509.h +file path=usr/include/openssl/fips-140/openssl/x509_vfy.h +file path=usr/include/openssl/fips-140/openssl/x509v3.h +license openssl-0.9.8-fips-140.license license="OpenSSL, SSLeay" diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/patches-post-config/opensslconf.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/patches-post-config/opensslconf.patch Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,69 @@ +--- /tmp/opensslconf.h Thu Mar 10 06:46:57 2011 ++++ /tmp/opensslconf.h.new Thu Mar 10 06:47:41 2011 +@@ -2,6 +2,12 @@ + /* WARNING: Generated automatically from opensslconf.h.in by Configure. */ + + /* OpenSSL was configured with the following options: */ ++#if defined(__sparcv9) ++#ifndef OPENSSL_SYSNAME_ULTRASPARC ++# define OPENSSL_SYSNAME_ULTRASPARC ++#endif ++#endif ++ + #ifndef OPENSSL_DOING_MAKEDEPEND + + +@@ -205,10 +211,14 @@ + + #if !(defined(VMS) || defined(__VMS)) /* VMS uses logical names instead */ + #if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) ++#if defined(__sparcv9) || defined(__x86_64) ++#define ENGINESDIR "/lib/openssl/engines/64" ++#else + #define ENGINESDIR "/lib/openssl/engines" +-#define OPENSSLDIR "/etc/openssl" + #endif ++#define OPENSSLDIR "/etc/openssl/fips-140" + #endif ++#endif + + #undef OPENSSL_UNISTD + #define OPENSSL_UNISTD +@@ -252,13 +262,21 @@ + /* If this is set to 'unsigned int' on a DEC Alpha, this gives about a + * %20 speed up (longs are 8 bytes, int's are 4). */ + #ifndef DES_LONG ++#if defined(__sparcv9) || defined(__x86_64) ++#define DES_LONG unsigned int ++#else + #define DES_LONG unsigned long + #endif + #endif ++#endif + + #if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) + #define CONFIG_HEADER_BN_H ++#if defined(__sparcv9) || defined(__x86_64) ++#undef BN_LLONG ++#else + #define BN_LLONG ++#endif + + /* Should we define BN_DIV2W here? */ + +@@ -266,9 +284,14 @@ + /* The prime number generation stuff may not work when + * EIGHT_BIT but I don't care since I've only used this mode + * for debuging the bignum libraries */ ++#if defined(__sparcv9) || defined(__x86_64) ++#define SIXTY_FOUR_BIT_LONG ++#undef THIRTY_TWO_BIT ++#else + #undef SIXTY_FOUR_BIT_LONG +-#undef SIXTY_FOUR_BIT + #define THIRTY_TWO_BIT ++#endif ++#undef SIXTY_FOUR_BIT + #undef SIXTEEN_BIT + #undef EIGHT_BIT + #endif diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/patches/08-6193522.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/patches/08-6193522.patch Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,54 @@ +diff -ruN openssl-0.9.8a/apps/CA.pl.in openssl-0.9.8a/apps/CA.pl.in +--- openssl-0.9.8a/apps/CA.pl.in 2005-07-04 23:44:22.000000000 +0200 ++++ openssl-0.9.8a/apps/CA.pl.in 2009-04-21 16:08:45.354925289 +0200 +@@ -53,7 +53,7 @@ + $X509="$openssl x509"; + $PKCS12="$openssl pkcs12"; + +-$CATOP="./demoCA"; ++$CATOP="/etc/openssl"; + $CAKEY="cakey.pem"; + $CAREQ="careq.pem"; + $CACERT="cacert.pem"; +diff -ruN openssl-0.9.8a/apps/openssl.cnf openssl-0.9.8a/apps/openssl.cnf +--- openssl-0.9.8a/apps/openssl.cnf 2005-09-16 14:20:24.000000000 +0200 ++++ openssl-0.9.8a/apps/openssl.cnf 2009-04-21 16:07:13.910980196 +0200 +@@ -34,7 +34,7 @@ + #################################################################### + [ CA_default ] + +-dir = ./demoCA # Where everything is kept ++dir = /etc/openssl # Where everything is kept + certs = $dir/certs # Where the issued certs are kept + crl_dir = $dir/crl # Where the issued crl are kept + database = $dir/index.txt # database index file. +@@ -44,7 +44,7 @@ + + certificate = $dir/cacert.pem # The CA certificate + serial = $dir/serial # The current serial number +-crlnumber = $dir/crlnumber # the current crl number ++#crlnumber = $dir/crlnumber # the current crl number + # must be commented out to leave a V1 CRL + crl = $dir/crl.pem # The current CRL + private_key = $dir/private/cakey.pem# The private key +@@ -122,17 +122,17 @@ + + [ req_distinguished_name ] + countryName = Country Name (2 letter code) +-countryName_default = AU ++#countryName_default = US + countryName_min = 2 + countryName_max = 2 + + stateOrProvinceName = State or Province Name (full name) +-stateOrProvinceName_default = Some-State ++#stateOrProvinceName_default = Some-State + + localityName = Locality Name (eg, city) + + 0.organizationName = Organization Name (eg, company) +-0.organizationName_default = Internet Widgits Pty Ltd ++#0.organizationName_default = Unconfigured OpenSSL Installation + + # we can do this but it is not needed normally :-) + #1.organizationName = Second Organization Name (eg, company) diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/patches/11-6546806.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/patches/11-6546806.patch Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,12 @@ +diff -ruN openssl-0.9.8a/doc/crypto/hmac.pod openssl-0.9.8a/doc/crypto/hmac.pod +--- openssl-0.9.8a/doc/crypto/hmac.pod 2002-07-18 20:54:45.000000000 +0200 ++++ openssl-0.9.8a/doc/crypto/hmac.pod 2009-04-10 11:09:46.449071541 +0200 +@@ -2,7 +2,7 @@ + + =head1 NAME + +-HMAC, HMAC_Init, HMAC_Update, HMAC_Final, HMAC_cleanup - HMAC message ++HMAC, HMAC_CTX_init, HMAC_Init, HMAC_Init_ex, HMAC_Update, HMAC_Final, HMAC_CTX_cleanup, HMAC_cleanup - HMAC message + authentication code + + =head1 SYNOPSIS diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/patches/15-pkcs11_engine-0.9.8a.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/patches/15-pkcs11_engine-0.9.8a.patch Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,131 @@ +diff -ruN ../a/openssl-0.9.8o/Configure openssl-0.9.8o/Configure +--- ../a/openssl-0.9.8o/Configure 2010-05-20 10:36:23.000000000 -0700 ++++ openssl-0.9.8o/Configure 2010-09-22 18:32:18.922795700 -0700 +@@ -12,7 +12,7 @@ + + # see INSTALL for instructions. + +-my $usage="Usage: Configure [no- ...] [enable- ...] [experimental- ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [enable-montasm] [no-asm] [no-dso] [no-krb5] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n"; ++my $usage="Usage: Configure --pk11-libname=PK11_LIB_LOCATION [no- ...] [enable- ...] [experimental- ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [enable-montasm] [no-asm] [no-dso] [no-krb5] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n"; + + # Options: + # +@@ -21,6 +21,9 @@ + # --prefix prefix for the OpenSSL include, lib and bin directories + # (Default: the OPENSSLDIR directory) + # ++# --pk11-libname PKCS#11 library name. ++# (Default: none) ++# + # --install_prefix Additional prefix for package builders (empty by + # default). This needn't be set in advance, you can + # just as well use "make INSTALL_PREFIX=/whatever install". +@@ -587,6 +590,9 @@ + my $idx_ranlib = $idx++; + my $idx_arflags = $idx++; + ++# PKCS#11 engine patch ++my $pk11_libname=""; ++ + my $prefix=""; + my $libdir=""; + my $openssldir=""; +@@ -825,6 +831,10 @@ + { + $flags.=$_." "; + } ++ elsif (/^--pk11-libname=(.*)$/) ++ { ++ $pk11_libname=$1; ++ } + elsif (/^--prefix=(.*)$/) + { + $prefix=$1; +@@ -960,6 +970,13 @@ + exit 0; + } + ++if (! $pk11_libname) ++ { ++ print STDERR "You must set --pk11-libname for PKCS#11 library.\n"; ++ print STDERR "See README.pkcs11 for more information.\n"; ++ exit 1; ++ } ++ + if ($target =~ m/^CygWin32(-.*)$/) { + $target = "Cygwin".$1; + } +@@ -1126,6 +1143,8 @@ + if ($flags ne "") { $cflags="$flags$cflags"; } + else { $no_user_cflags=1; } + ++$cflags="-DPK11_LIB_LOCATION=\"$pk11_libname\" $cflags"; ++ + # Kerberos settings. The flavor must be provided from outside, either through + # the script "config" or manually. + if (!$no_krb5) +@@ -1489,6 +1508,7 @@ + s/^VERSION=.*/VERSION=$version/; + s/^MAJOR=.*/MAJOR=$major/; + s/^MINOR=.*/MINOR=$minor/; ++ s/^PK11_LIB_LOCATION=.*/PK11_LIB_LOCATION=$pk11_libname/; + s/^SHLIB_VERSION_NUMBER=.*/SHLIB_VERSION_NUMBER=$shlib_version_number/; + s/^SHLIB_VERSION_HISTORY=.*/SHLIB_VERSION_HISTORY=$shlib_version_history/; + s/^SHLIB_MAJOR=.*/SHLIB_MAJOR=$shlib_major/; +diff -ruN ../a/openssl-0.9.8o/Makefile.org openssl-0.9.8o/Makefile.org +--- ../a/openssl-0.9.8o/Makefile.org 2010-01-27 08:06:36.000000000 -0800 ++++ openssl-0.9.8o/Makefile.org 2010-09-22 18:32:19.152576100 -0700 +@@ -26,6 +26,9 @@ + INSTALL_PREFIX= + INSTALLTOP=/usr/local/ssl + ++# You must set this through --pk11-libname configure option. ++PK11_LIB_LOCATION= ++ + # Do not edit this manually. Use Configure --openssldir=DIR do change this! + OPENSSLDIR=/usr/local/ssl + +diff -ruN ../a/openssl-0.9.8o/crypto/engine/Makefile openssl-0.9.8o/crypto/engine/Makefile +--- ../a/openssl-0.9.8o/crypto/engine/Makefile 2009-09-27 07:04:32.000000000 -0700 ++++ openssl-0.9.8o/crypto/engine/Makefile 2010-09-22 18:32:19.109972600 -0700 +@@ -21,12 +21,14 @@ + eng_table.c eng_pkey.c eng_fat.c eng_all.c \ + tb_rsa.c tb_dsa.c tb_ecdsa.c tb_dh.c tb_ecdh.c tb_rand.c tb_store.c \ + tb_cipher.c tb_digest.c \ +- eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c eng_padlock.c ++ eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c eng_padlock.c \ ++ hw_pk11.c hw_pk11_pub.c hw_pk11_uri.c + LIBOBJ= eng_err.o eng_lib.o eng_list.o eng_init.o eng_ctrl.o \ + eng_table.o eng_pkey.o eng_fat.o eng_all.o \ + tb_rsa.o tb_dsa.o tb_ecdsa.o tb_dh.o tb_ecdh.o tb_rand.o tb_store.o \ + tb_cipher.o tb_digest.o \ +- eng_openssl.o eng_cnf.o eng_dyn.o eng_cryptodev.o eng_padlock.o ++ eng_openssl.o eng_cnf.o eng_dyn.o eng_cryptodev.o eng_padlock.o \ ++ hw_pk11.o hw_pk11_pub.o hw_pk11_uri.o + + SRC= $(LIBSRC) + +diff -ruN ../a/openssl-0.9.8o/crypto/engine/eng_all.c openssl-0.9.8o/crypto/engine/eng_all.c +--- ../a/openssl-0.9.8o/crypto/engine/eng_all.c 2010-02-28 16:30:11.000000000 -0800 ++++ openssl-0.9.8o/crypto/engine/eng_all.c 2010-09-22 18:33:15.326949000 -0700 +@@ -72,6 +72,9 @@ + ENGINE_load_padlock(); + #endif + ENGINE_load_dynamic(); ++#ifndef OPENSSL_NO_HW_PKCS11 ++ ENGINE_load_pk11(); ++#endif + #ifndef OPENSSL_NO_STATIC_ENGINE + #ifndef OPENSSL_NO_HW + #ifndef OPENSSL_NO_HW_4758_CCA +diff -ruN ../a/openssl-0.9.8o/crypto/engine/engine.h openssl-0.9.8o/crypto/engine/engine.h +--- ../a/openssl-0.9.8o/crypto/engine/engine.h 2010-02-09 06:18:15.000000000 -0800 ++++ openssl-0.9.8o/crypto/engine/engine.h 2010-09-22 18:32:19.063758100 -0700 +@@ -337,6 +337,7 @@ + void ENGINE_load_ubsec(void); + #endif + void ENGINE_load_cryptodev(void); ++void ENGINE_load_pk11(void); + void ENGINE_load_padlock(void); + void ENGINE_load_builtin_engines(void); + #ifdef OPENSSL_SYS_WIN32 diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/patches/18-compiler_opts.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/patches/18-compiler_opts.patch Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,28 @@ +diff -ruN openssl-0.9.8k/Configure openssl-0.9.8k/Configure +--- openssl-0.9.8k/Configure 2009-02-16 09:44:22.000000000 +0100 ++++ openssl-0.9.8k/Configure 2009-06-25 16:19:22.897811727 +0200 +@@ -130,6 +130,11 @@ + my $x86_64_asm="x86_64cpuid.o:x86_64-gcc.o x86_64-mont.o::aes-x86_64.o::md5-x86_64.o:sha1-x86_64.o sha256-x86_64.o sha512-x86_64.o::rc4-x86_64.o::"; + my $ia64_asm=":bn-ia64.o::aes_core.o aes_cbc.o aes-ia64.o:::sha1-ia64.o sha256-ia64.o sha512-ia64.o::rc4-ia64.o rc4_skey.o::"; + ++# ASM without "rx86-elf.o rc4_skey.o". The current RC4 asm assumes RC4_INT. Solaris/OpenSolaris uses RC4_CHAR. ++# Changing to RC4_INT would break ABI compatibility. ++my $x86_elf_asm_sunw="x86cpuid-elf.o:bn86-elf.o co86-elf.o MAYBE-MO86-elf.o:dx86-elf.o yx86-elf.o:ax86-elf.o:bx86-elf.o:mx86-elf.o:sx86-elf.o s512sse2-elf.o:cx86-elf.o::rm86-elf.o:r586-elf.o"; ++my $x86_64_asm_sunw="x86_64cpuid.o:x86_64-gcc.o x86_64-mont.o::aes-x86_64.o::md5-x86_64.o:sha1-x86_64.o sha256-x86_64.o sha512-x86_64.o::::"; ++ + my $no_asm="::::::::::"; + + # As for $BSDthreads. Idea is to maintain "collective" set of flags, +@@ -235,6 +240,12 @@ + #"sunos-cc", "cc:-O4 -DNOPROTO -DNOCONST::(unknown):SUNOS::DES_UNROLL:${no_asm}::", + "sunos-gcc","gcc:-O3 -mv8 -Dssize_t=int::(unknown):SUNOS::BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL DES_PTR DES_RISC1:${no_asm}::", + ++#### Solaris configs, used for OpenSSL as delivered by OpenSolaris ++"solaris-x86-cc-sunw","cc:-m32 -xO3 -xspace -g -Xa::-D_REENTRANT::-lsocket -lnsl -lc -R /lib/openssl/fips-140:BN_LLONG RC4_CHAR RC4_CHUNK DES_PTR DES_UNROLL BF_PTR:${x86_elf_asm_sunw}:dlfcn:solaris-shared:-KPIC:-m32 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign -M/usr/lib/ld/map.noexdata:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"solaris64-x86_64-cc-sunw","cc:-xO3 -m64 -g -xstrconst -Xa -DL_ENDIAN::-D_REENTRANT::-lsocket -lnsl -lc -R /lib/openssl/fips-140/64:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK BF_PTR DES_PTR DES_INT DES_UNROLL:${x86_64_asm_sunw}:dlfcn:solaris-shared:-KPIC:-m64 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign -M/usr/lib/ld/map.noexdata:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"solaris-sparcv8-cc-sunw","cc:-m32 -Qoption cg -xregs=no%appl -xO5 -g -xstrconst -xdepend -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT::-lsocket -lnsl -lc -R /lib/openssl/fips-140:BN_LLONG RC4_CHAR RC4_CHUNK DES_PTR DES_RISC1 DES_UNROLL BF_PTR::sparcv8plus.o::::::::::dlfcn:solaris-shared:-KPIC:-m32 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", ++"solaris64-sparcv9-cc-sunw","cc:-m64 -Qoption cg -xregs=no%appl -xO5 -g -xstrconst -xdepend -xspace -Xa -DB_ENDIAN::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -lc -R /lib/openssl/fips-140/64:SIXTY_FOUR_BIT_LONG RC4_CHAR RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL BF_PTR::::::::::::dlfcn:solaris-shared:-KPIC:-m64 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):/usr/ccs/bin/ar rs", ++ + #### IRIX 5.x configs + # -mips2 flag is added by ./config when appropriate. + "irix-gcc","gcc:-O3 -DTERMIOS -DB_ENDIAN::(unknown):::BN_LLONG MD2_CHAR RC4_INDEX RC4_CHAR RC4_CHUNK DES_UNROLL DES_RISC2 DES_PTR BF_PTR:${no_asm}:dlfcn:irix-shared:::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/patches/20-remove_rpath.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/patches/20-remove_rpath.patch Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,12 @@ +diff -ruN openssl-0.9.8a/Makefile.shared openssl-0.9.8a/Makefile.shared +--- openssl-0.9.8a/Makefile.shared 2005-06-23 22:47:54.000000000 +0200 ++++ openssl-0.9.8a/Makefile.shared 2009-05-20 00:35:52.611961155 +0200 +@@ -340,7 +340,7 @@ + @ if ${DETECT_GNU_LD}; then \ + $(DO_GNU_APP); \ + else \ +- LDFLAGS="$(CFLAGS) -R $(LIBRPATH)"; \ ++ LDFLAGS="$(CFLAGS)"; \ + fi; \ + $(LINK_APP) + diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/patches/23-noexstack.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/patches/23-noexstack.patch Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,21 @@ +diff -ruN openssl-0.9.8k/Makefile.shared openssl-0.9.8k/Makefile.shared +--- openssl-0.9.8k/Makefile.shared 2008-09-17 17:56:40.000000000 +0200 ++++ openssl-0.9.8k/Makefile.shared 2009-05-25 22:26:49.611468992 +0200 +@@ -347,12 +347,17 @@ + SHAREDFLAGS="$(CFLAGS) $(SHARED_LDFLAGS) -h $$SHLIB$$SHLIB_SOVER$$SHLIB_SUFFIX -Wl,-Bsymbolic"; \ + fi; \ + $(LINK_SO_A) ++# Make sure the apps have non-executable stacks and data (x86/x64 only). + link_app.solaris: + @ if ${DETECT_GNU_LD}; then \ + $(DO_GNU_APP); \ + else \ + LDFLAGS="$(CFLAGS)"; \ + fi; \ ++ if expr $(PLATFORM) : '.*x86.*' > /dev/null; then \ ++ LDFLAGS="$${LDFLAGS} -M/usr/lib/ld/map.noexdata"; \ ++ fi; \ ++ LDFLAGS="$${LDFLAGS} -M/usr/lib/ld/map.noexstk -M/usr/lib/ld/map.pagealign"; \ + $(LINK_APP) + + # OpenServer 5 native compilers used diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/patches/25-fips_rand.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/patches/25-fips_rand.patch Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,12 @@ +diff -ruN a/openssl-0.9.8k/fips/rand/fips_rand.h b/openssl-0.9.8k/fips/rand/fips_rand.h +--- openssl-0.9.8k/fips/rand/fips_rand.h 2008-09-16 12:12:18.000000000 +0200 ++++ openssl-0.9.8k/fips/rand/fips_rand.h 2009-09-29 17:42:41.969816617 +0200 +@@ -50,7 +50,7 @@ + #ifndef HEADER_FIPS_RAND_H + #define HEADER_FIPS_RAND_H + +-#include "des.h" ++#include + + #ifdef OPENSSL_FIPS + diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/patches/26-openssl_fips.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/patches/26-openssl_fips.patch Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,92 @@ +--- openssl-0.9.8m/apps/openssl.c Thu Oct 15 19:28:02 2009 ++++ openssl-0.9.8m/apps/openssl.c Fri Feb 26 16:12:30 2010 +@@ -130,6 +130,9 @@ + #include "s_apps.h" + #include + ++/* Solaris OpenSSL */ ++#include ++ + /* The LHASH callbacks ("hash" & "cmp") have been replaced by functions with the + * base prototypes (we cast each variable inside the function to the required + * type of "FUNCTION*"). This removes the necessity for macro-generated wrapper +@@ -151,9 +154,10 @@ + #endif + + ++static int *modes; ++ + static void lock_dbg_cb(int mode, int type, const char *file, int line) + { +- static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */ + const char *errstr = NULL; + int rw; + +@@ -164,7 +168,7 @@ + goto err; + } + +- if (type < 0 || type >= CRYPTO_NUM_LOCKS) ++ if (type < 0 || type >= CRYPTO_num_locks()) + { + errstr = "type out of bounds"; + goto err; +@@ -235,19 +239,29 @@ + + in_FIPS_mode = 0; + ++/* ++ * Solaris OpenSSL ++ * Add a further check for the FIPS_mode_set() symbol before calling to ++ * allow openssl(1openssl) to be run against both fips and non-fips libraries. ++ */ + if(getenv("OPENSSL_FIPS")) { +-#ifdef OPENSSL_FIPS +- if (!FIPS_mode_set(1)) { ++ ++ int (*FIPS_mode_set)(int); ++ FIPS_mode_set = (int (*)(int)) dlsym(RTLD_NEXT, "FIPS_mode_set"); ++ ++ if (FIPS_mode_set != NULL) { ++ if (!(*FIPS_mode_set)(1)) { + ERR_load_crypto_strings(); + ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE)); + EXIT(1); + } + in_FIPS_mode = 1; +-#else +- fprintf(stderr, "FIPS mode not supported.\n"); ++ } else { ++ fprintf(stderr, "Failed to enable FIPS mode. " ++ "For more information about running in FIPS mode see openssl(5).\n"); + EXIT(1); +-#endif + } ++ } + + if (bio_err == NULL) + if ((bio_err=BIO_new(BIO_s_file())) != NULL) +@@ -272,6 +286,14 @@ + if (getenv("OPENSSL_DEBUG_LOCKING") != NULL) + #endif + { ++ modes = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (int)); ++ if (modes == NULL) { ++ ERR_load_crypto_strings(); ++ BIO_printf(bio_err,"Memory allocation failure\n"); ++ ERR_print_errors(bio_err); ++ EXIT(1); ++ } ++ memset(modes, 0, CRYPTO_num_locks() * sizeof (int)); + CRYPTO_set_locking_callback(lock_dbg_cb); + } + +@@ -379,6 +401,8 @@ + BIO_free(bio_err); + bio_err=NULL; + } ++ ++ if (modes != NULL) OPENSSL_free(modes); + OPENSSL_EXIT(ret); + } + diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/patches/27-6978791.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/patches/27-6978791.patch Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,13 @@ +diff -ruN ../openssl-0.9.8o/Makefile.shared ./Makefile.shared +--- ../openssl-0.9.8o/Makefile.shared 2010-08-23 12:35:50.222830608 +0200 ++++ ./Makefile.shared 2010-08-23 12:36:35.672746275 +0200 +@@ -345,6 +345,9 @@ + ALLSYMSFLAGS="$${MINUSZ}allextract"; \ + NOALLSYMSFLAGS="$${MINUSZ}defaultextract"; \ + SHAREDFLAGS="$(CFLAGS) $(SHARED_LDFLAGS) -h $$SHLIB$$SHLIB_SOVER$$SHLIB_SUFFIX -Wl,-Bsymbolic"; \ ++ if [ $(LIBNAME) = "ssl" ]; then \ ++ SHAREDFLAGS="$$SHAREDFLAGS $${MINUSZ}nodelete"; \ ++ fi; \ + fi; \ + $(LINK_SO_A) + # Make sure the apps have non-executable stacks and data (x86/x64 only). diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/patches/28-enginesdir.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/patches/28-enginesdir.patch Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,59 @@ +--- openssl-0.9.8n/Configure 2010-04-19 17:45:39.421625300 -0700 ++++ openssl-0.9.8n/Configure.new 2010-06-18 15:18:52.437417100 -0700 +@@ -20,6 +20,8 @@ + # --prefix option is given; /usr/local/ssl otherwise) + # --prefix prefix for the OpenSSL include, lib and bin directories + # (Default: the OPENSSLDIR directory) ++# --enginesdir engines shared library location ++# (Default: $prefix/lib/engines) + # + # --pk11-libname PKCS#11 library name. + # (Default: none) +@@ -607,6 +609,7 @@ + my $prefix=""; + my $libdir=""; + my $openssldir=""; ++my $enginesdir=""; + my $exe_ext=""; + my $install_prefix= "$ENV{'INSTALL_PREFIX'}"; + my $cross_compile_prefix=""; +@@ -858,6 +861,10 @@ + { + $openssldir=$1; + } ++ elsif (/^--enginesdir=(.*)$/) ++ { ++ $enginesdir=$1; ++ } + elsif (/^--install.prefix=(.*)$/) + { + $install_prefix=$1; +@@ -1125,8 +1132,16 @@ + } + $prefix=$openssldir if $prefix eq ""; + ++if ($enginesdir eq "") ++ { ++ $enginesdir = "$prefix/lib/engines"; ++ } ++ + $libdir="lib" if $libdir eq ""; + ++ ++ ++ + $default_ranlib= &which("ranlib") or $default_ranlib="true"; + $perl=$ENV{'PERL'} or $perl=&which("perl5") or $perl=&which("perl") + or $perl="perl"; +@@ -1724,10 +1739,7 @@ + } + elsif (/^#define\s+ENGINESDIR/) + { +- # $foo is to become "$prefix/lib$multilib/engines"; +- # as Makefile.org and engines/Makefile are adapted for +- # $multilib suffix. +- my $foo = "$prefix/lib/engines"; ++ my $foo = $enginesdir; + $foo =~ s/\\/\\\\/g; + print OUT "#define ENGINESDIR \"$foo\"\n"; + } diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/patches/sparc-01-ccwrap.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/patches/sparc-01-ccwrap.patch Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,54 @@ +diff -ruN ../a/openssl-0.9.8k/fips/fipsld openssl-0.9.8k/fips/fipsld +--- ../a/openssl-0.9.8k/fips/fipsld 2008-09-16 12:12:10.000000000 +0200 ++++ openssl-0.9.8k/fips/fipsld 2009-10-06 16:45:34.379991933 +0200 +@@ -12,6 +12,14 @@ + + #set -x + ++# Solaris OpenSSL: ++# Wrap the calls to cc to remove the "-g" option when compiling ++# (SPARC only). If "-g" is used on SPARC to build libcrypto.so ++# the fingerprint will be incorrectly generated as "-g" promotes ++# static symbols to globals which then interacts with the linker to ++# produce a changed text section. ++CCWRAP=ccwrap ++ + CC=${FIPSLD_CC:-${CC}} + [ -n "${CC}" ] || { echo '$CC is not defined'; exit 1; } + +@@ -112,7 +120,7 @@ + fi + + /bin/rm -f "${TARGET}" +- ${CC} ${CANISTER_O_CMD:+"${CANISTER_O_CMD}"} \ ++ ${CCWRAP} ${CC} ${CANISTER_O_CMD:+"${CANISTER_O_CMD}"} \ + "${PREMAIN_C}" \ + ${_WL_PREMAIN} "$@" + +@@ -124,7 +132,7 @@ + fi + + # recompile with signature... +- ${CC} ${CANISTER_O_CMD:+"${CANISTER_O_CMD}"} \ ++ ${CCWRAP} ${CC} ${CANISTER_O_CMD:+"${CANISTER_O_CMD}"} \ + -DHMAC_SHA1_SIG=\"${SIG}\" "${PREMAIN_C}" \ + ${_WL_PREMAIN} "$@" + ;; +@@ -151,7 +159,7 @@ + { echo "${PREMAIN_C} fingerprint mismatch"; exit 1; } + + /bin/rm -f "${TARGET}" +- ${CC} ${CANISTER_O_CMD:+"${CANISTER_O_CMD}"} \ ++ ${CCWRAP} ${CC} ${CANISTER_O_CMD:+"${CANISTER_O_CMD}"} \ + "${PREMAIN_C}" \ + ${_WL_PREMAIN} "$@" + +@@ -163,7 +171,7 @@ + fi + + # recompile with signature... +- ${CC} ${CANISTER_O_CMD:+"${CANISTER_O_CMD}"} \ ++ ${CCWRAP} ${CC} ${CANISTER_O_CMD:+"${CANISTER_O_CMD}"} \ + -DHMAC_SHA1_SIG=\"${SIG}\" "${PREMAIN_C}" \ + ${_WL_PREMAIN} "$@" + ;; diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-0.9.8-fips-140/resolve.deps --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/openssl/openssl-0.9.8-fips-140/resolve.deps Mon Dec 09 18:42:02 2013 -0800 @@ -0,0 +1,1 @@ +system/library diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/Makefile --- a/components/openssl/openssl-1.0.1-fips-140/Makefile Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,193 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. -# -export PARFAIT_BUILD=no - -include ../../../make-rules/shared-macros.mk - -PATH=$(SPRO_VROOT)/bin:/usr/bin:/usr/gnu/bin:/usr/perl5/bin - -COMPONENT_NAME = openssl-fips-140 -# Note that this is the OpenSSL version that is used to build FIPS-140 certified -# libraries. However, we use the FIPS canister version for the IPS package. -COMPONENT_VERSION = 1.0.1e -IPS_COMPONENT_VERSION = 2.0.5 -COMPONENT_PROJECT_URL= http://www.openssl.org/ -COMPONENT_SRC_NAME = openssl -COMPONENT_SRC = $(COMPONENT_SRC_NAME)-$(COMPONENT_VERSION) -COMPONENT_ARCHIVE = $(COMPONENT_SRC).tar.gz -COMPONENT_ARCHIVE_HASH= \ - sha256:f74f15e8c8ff11aa3d5bb5f276d202ec18d7246e95f961db76054199c69c1ae3 -COMPONENT_ARCHIVE_URL = $(COMPONENT_PROJECT_URL)source/$(COMPONENT_ARCHIVE) -COMPONENT_BUGDB= utility/openssl - -# OpenSSL FIPS 2.0.5 directory -OPENSSL_FIPS_DIR = $(COMPONENT_DIR)/../openssl-fips - -# Note that the SPARC patch above does not fit this pattern. That is intentional -# and a reason why we can add it to the EXTRA_PATCHES variable so that we use it -# only on SPARC. -PATCH_PATTERN = [0-9][0-9]*.patch - -include $(WS_TOP)/make-rules/prep.mk -include $(WS_TOP)/make-rules/configure.mk -include $(WS_TOP)/make-rules/ips.mk -include $(WS_TOP)/make-rules/lint-libraries.mk - -# OpenSSL does not use autoconf but its own configure system. -CONFIGURE_SCRIPT = $(SOURCE_DIR)/Configure - -# Used in the configure options below. -PKCS11_LIB32 = /usr/lib/libpkcs11.so.1 -PKCS11_LIB64 = /usr/lib/64/libpkcs11.so.1 -ENGINESDIR_32 = /lib/openssl/engines -ENGINESDIR_64 = /lib/openssl/engines/64 - -# Built openssl/openssl-fips component is used when building FIPS-140 libraries. -# What we do here follows the OpenSSL FIPS-140 User Guide instructions. -FIPS_BUILD_DIR_32 = $(shell echo $(BUILD_DIR_32) | \ - sed -e 's/openssl-1.0.1-fips-140/openssl-fips/g' ) -FIPS_BUILD_DIR_64 = $(shell echo $(BUILD_DIR_64) | \ - sed -e 's/openssl-1.0.1-fips-140/openssl-fips/g' ) - -CONFIGURE_OPTIONS = -DSOLARIS_OPENSSL -DNO_WINDOWS_BRAINDEATH -CONFIGURE_OPTIONS += --openssldir=/etc/openssl -CONFIGURE_OPTIONS += --prefix=/usr -# We use OpenSSL install code for installing only manual pages and we do that -# for 32-bit version only. -CONFIGURE_OPTIONS += --install_prefix=$(PROTO_DIR) -CONFIGURE_OPTIONS += no-ec2m -CONFIGURE_OPTIONS += no-rc3 -CONFIGURE_OPTIONS += no-rc5 -CONFIGURE_OPTIONS += no-mdc2 -CONFIGURE_OPTIONS += no-idea -CONFIGURE_OPTIONS += no-hw_4758_cca -CONFIGURE_OPTIONS += no-hw_aep -CONFIGURE_OPTIONS += no-hw_atalla -CONFIGURE_OPTIONS += no-hw_chil -CONFIGURE_OPTIONS += no-hw_gmp -CONFIGURE_OPTIONS += no-hw_ncipher -CONFIGURE_OPTIONS += no-hw_nuron -CONFIGURE_OPTIONS += no-hw_padlock -CONFIGURE_OPTIONS += no-hw_sureware -CONFIGURE_OPTIONS += no-hw_ubsec -CONFIGURE_OPTIONS += no-hw_cswift -CONFIGURE_OPTIONS += threads -CONFIGURE_OPTIONS += shared -CONFIGURE_OPTIONS += fips --with-fipslibdir="$(FIPS_BUILD_DIR_$(BITS))/fips/" -CONFIGURE_OPTIONS += --with-fipsdir="$(BUILD_DIR_$(BITS))" - -# MD2 is not enabled by default in OpensSSL but some software we have in -# Userland needs it. One example is nmap. -CONFIGURE_OPTIONS += enable-md2 -CONFIGURE_OPTIONS += no-seed - -# We define our own compiler and linker option sets for Solaris. See Configure -# for more information. -CONFIGURE_OPTIONS32_i386 = solaris-x86-cc-sunw -CONFIGURE_OPTIONS32_sparc = solaris-sparcv8-cc-sunw -CONFIGURE_OPTIONS64_i386 = solaris64-x86_64-cc-sunw -CONFIGURE_OPTIONS64_sparc = solaris64-sparcv9-cc-sunw - -# Some additional options needed for our engines. -CONFIGURE_OPTIONS += --pk11-libname=$(PKCS11_LIB$(BITS)) -CONFIGURE_OPTIONS += --enginesdir=$(ENGINESDIR_$(BITS)) -CONFIGURE_OPTIONS += $(CONFIGURE_OPTIONS$(BITS)_$(MACH)) - -# OpenSSL has its own configure system which must be run from the fully -# populated source code directory. However, the Userland configuration phase is -# run from the build directory. The easiest way to workaround it is to copy all -# the source files there. -COMPONENT_PRE_CONFIGURE_ACTION = \ - ( $(CLONEY) $(SOURCE_DIR) $(BUILD_DIR)/$(MACH$(BITS)); ) - -# We deliver only one opensslconf.h file which must be suitable for both 32 and -# 64 bits. Depending on the configuration option, OpenSSL's Configure script -# creates opensslconf.h for either 32 or 64 bits. A patch makes the resulting -# header file usable on both architectures. The patch was generated against the -# opensslconf.h version from the 32 bit build. -COMPONENT_POST_CONFIGURE_ACTION = \ - ( [ $(BITS) -eq 32 ] && $(GPATCH) -p1 $(@D)/crypto/opensslconf.h \ - patches-post-config/opensslconf.patch; cd $(@D); $(MAKE) depend; ) - -ASLR_MODE = $(ASLR_NOT_APPLICABLE) - -# We must make sure that openssl-fips component is built before this 1.0.1 -# component since in order to build FIPS-140 certified libraries, the canister -# is needed. Note that we must unset BITS that would override the same variable -# used in openssl-fips' Makefile, and we would end up up with both canisters -# built in 64 (or 32) bits. -$(COMPONENT_DIR)/../openssl-fips/build/$(MACH32)/.installed \ -$(COMPONENT_DIR)/../openssl-fips/build/$(MACH64)/.installed: - ( unset BITS; \ - $(MAKE) -C $(COMPONENT_DIR)/../openssl-fips install; ) - -# download, clean, and clobber should all propogate to the fips bits -download clobber clean:: - (cd ../openssl-fips ; $(GMAKE) $@) - -# We do not ship our engines as patches since it would be more difficult to -# update the files which have been under continuous development. We rather copy -# the files to the right directories and let OpenSSL makefiles build it. -# We also copy some FIPS specific header files needed to build FIPS version -# of OpenSSL from FIPS module (openssl-fips-ecp-2.0.5). -COMPONENT_PRE_BUILD_ACTION = \ - ( $(LN) -fs $(COMPONENT_DIR)/engines/pkcs11/* $(@D)/crypto/engine; \ - $(MKDIR) $(@D)/bin; \ - $(LN) -fs $(OPENSSL_FIPS_DIR)/openssl-fips-ecp-2.0.5/fips/fips.h $(@D)/include/openssl; \ - $(LN) -fs $(OPENSSL_FIPS_DIR)/openssl-fips-ecp-2.0.5/fips/fipssyms.h $(@D)/include/openssl; \ - $(LN) -fs $(OPENSSL_FIPS_DIR)/openssl-fips-ecp-2.0.5/fips/rand/fips_rand.h $(@D)/include/openssl; \ - $(LN) -fs $(OPENSSL_FIPS_DIR)/openssl-fips-ecp-2.0.5/fips/fipsld $(@D)/bin/; \ - $(LN) -fs $(OPENSSL_FIPS_DIR)/build/$(MACH$(BITS))/fips/fips_standalone_sha1 $(@D)/bin/; \ - $(LN) -fs $(COMPONENT_DIR)/build/$(MACH$(BITS))/fips_premain_dso $(@D)/bin/;) - -# OpenSSL does not install into /$(MACH64) for 64-bit install so no such -# directory is created and Userland install code would fail when installing lint -# libraries. -COMPONENT_PRE_INSTALL_ACTION = ( $(MKDIR) $(PROTO_DIR)/usr/lib/$(MACH64); ) - -$(SOURCE_DIR)/.prep: $(COMPONENT_DIR)/../openssl-fips/build/$(MACH32)/.installed \ - $(COMPONENT_DIR)/../openssl-fips/build/$(MACH64)/.installed - -build: $(BUILD_32_and_64) - -# We follow what we do for install in openssl/openssl-1.0.0 component. Please -# see the comment in Makefile in there for more information. -install: $(INSTALL_32_and_64) - -# We need to modify the default lint flags to include patched opensslconf.h from -# the build directory. If we do not do that, lint will complain about md2.h -# which is not enabled by default but it is in our opensslconf.h. -LFLAGS_32 := -I$(BUILD_DIR_32)/include $(LINT_FLAGS) -LFLAGS_64 := -I$(BUILD_DIR_64)/include $(LINT_FLAGS) - -# Set modified lint flags for our lint library targets. -$(BUILD_DIR_32)/llib-lcrypto.ln: LINT_FLAGS=$(LFLAGS_32) -$(BUILD_DIR_32)/llib-lssl.ln: LINT_FLAGS=$(LFLAGS_32) -$(BUILD_DIR_64)/llib-lcrypto.ln: LINT_FLAGS=$(LFLAGS_64) -$(BUILD_DIR_64)/llib-lssl.ln: LINT_FLAGS=$(LFLAGS_64) - -test: $(NO_TESTS) - -BUILD_PKG_DEPENDENCIES = $(BUILD_TOOLS) - -include $(WS_TOP)/make-rules/depend.mk diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/engines/pkcs11/hw_pk11.c --- a/components/openssl/openssl-1.0.1-fips-140/engines/pkcs11/hw_pk11.c Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3643 +0,0 @@ -/* - * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. - */ - -/* crypto/engine/hw_pk11.c */ -/* - * This product includes software developed by the OpenSSL Project for - * use in the OpenSSL Toolkit (http://www.openssl.org/). - * - * This project also referenced hw_pkcs11-0.9.7b.patch written by - * Afchine Madjlessi. - */ -/* - * ==================================================================== - * Copyright (c) 2000-2001 The OpenSSL Project. 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. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED 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 OpenSSL PROJECT OR - * ITS 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. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef OPENSSL_NO_RSA -#include -#endif -#ifndef OPENSSL_NO_DSA -#include -#endif -#ifndef OPENSSL_NO_DH -#include -#endif -#include -#include -#include -#include -#include -#include -#include - -#ifndef OPENSSL_NO_HW -#ifndef OPENSSL_NO_HW_PK11 - -/* label for debug messages printed on stderr */ -#define PK11_DBG "PKCS#11 ENGINE DEBUG" -/* prints a lot of debug messages on stderr about slot selection process */ -#undef DEBUG_SLOT_SELECTION -/* - * Solaris specific code. See comment at check_hw_mechanisms() for more - * information. - */ -#if defined(__SVR4) && defined(__sun) -#define SOLARIS_HW_SLOT_SELECTION -#endif - -#ifdef DEBUG_SLOT_SELECTION -#define DEBUG_SLOT_SEL(...) fprintf(stderr, __VA_ARGS__) -#else -#define DEBUG_SLOT_SEL(...) -#endif - -#include -#include -#include "hw_pk11.h" -#include "hw_pk11_uri.h" - -#define PK11_ENGINE_LIB_NAME "PKCS#11 engine" -#include "hw_pk11_err.c" - -/* - * We use this lock to prevent multiple C_Login()s, guard getpassphrase(), - * uri_struct manipulation, and static token info. All of that is used by the - * RSA keys by reference feature. - */ -pthread_mutex_t *uri_lock; - -#ifdef SOLARIS_HW_SLOT_SELECTION -/* - * Tables for symmetric ciphers and digest mechs found in the pkcs11_kernel - * library. See comment at check_hw_mechanisms() for more information. - */ -int *hw_cnids; -int *hw_dnids; -#endif /* SOLARIS_HW_SLOT_SELECTION */ - -/* PKCS#11 session caches and their locks for all operation types */ -static PK11_CACHE session_cache[OP_MAX]; - -/* - * We cache the flags so that we do not have to run C_GetTokenInfo() again when - * logging into the token. - */ -CK_FLAGS pubkey_token_flags; - -/* - * As stated in v2.20, 11.7 Object Management Function, in section for - * C_FindObjectsInit(), at most one search operation may be active at a given - * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be - * grouped together to form one atomic search operation. This is already - * ensured by the property of unique PKCS#11 session handle used for each - * PK11_SESSION object. - * - * This is however not the biggest concern - maintaining consistency of the - * underlying object store is more important. The same section of the spec also - * says that one thread can be in the middle of a search operation while another - * thread destroys the object matching the search template which would result in - * invalid handle returned from the search operation. - * - * Hence, the following locks are used for both protection of the object stores. - * They are also used for active list protection. - */ -pthread_mutex_t *find_lock[OP_MAX] = { NULL }; - -/* - * lists of asymmetric key handles which are active (referenced by at least one - * PK11_SESSION structure, either held by a thread or present in free_session - * list) for given algorithm type - */ -PK11_active *active_list[OP_MAX] = { NULL }; - -/* - * Create all secret key objects in a global session so that they are available - * to use for other sessions. These other sessions may be opened or closed - * without losing the secret key objects. - */ -static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE; - -/* Index for the supported ciphers */ -enum pk11_cipher_id - { - PK11_DES_CBC, - PK11_DES3_CBC, - PK11_DES_ECB, - PK11_DES3_ECB, - PK11_RC4, - PK11_AES_128_CBC, - PK11_AES_192_CBC, - PK11_AES_256_CBC, - PK11_AES_128_ECB, - PK11_AES_192_ECB, - PK11_AES_256_ECB, - PK11_BLOWFISH_CBC, - PK11_AES_128_CTR, - PK11_AES_192_CTR, - PK11_AES_256_CTR, - PK11_CIPHER_MAX - }; - -/* Index for the supported digests */ -enum pk11_digest_id - { - PK11_MD5, - PK11_SHA1, - PK11_SHA224, - PK11_SHA256, - PK11_SHA384, - PK11_SHA512, - PK11_DIGEST_MAX - }; - -typedef struct PK11_CIPHER_st - { - enum pk11_cipher_id id; - int nid; - int iv_len; - int min_key_len; - int max_key_len; - CK_KEY_TYPE key_type; - CK_MECHANISM_TYPE mech_type; - } PK11_CIPHER; - -typedef struct PK11_DIGEST_st - { - enum pk11_digest_id id; - int nid; - CK_MECHANISM_TYPE mech_type; - } PK11_DIGEST; - -/* ENGINE level stuff */ -static int pk11_init(ENGINE *e); -static int pk11_library_init(ENGINE *e); -static int pk11_finish(ENGINE *e); -static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); -static int pk11_destroy(ENGINE *e); - -/* RAND stuff */ -static void pk11_rand_seed(const void *buf, int num); -static void pk11_rand_add(const void *buf, int num, double add_entropy); -static void pk11_rand_cleanup(void); -static int pk11_rand_bytes(unsigned char *buf, int num); -static int pk11_rand_status(void); - -/* These functions are also used in other files */ -PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); -void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); - -/* active list manipulation functions used in this file */ -extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type); -extern void pk11_free_active_list(PK11_OPTYPE type); - -#ifndef OPENSSL_NO_RSA -int pk11_destroy_rsa_key_objects(PK11_SESSION *session); -int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); -int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); -#endif -#ifndef OPENSSL_NO_DSA -int pk11_destroy_dsa_key_objects(PK11_SESSION *session); -int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); -int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); -#endif -#ifndef OPENSSL_NO_DH -int pk11_destroy_dh_key_objects(PK11_SESSION *session); -int pk11_destroy_dh_object(PK11_SESSION *session, CK_BBOOL uselock); -#endif - -/* Local helper functions */ -static int pk11_free_all_sessions(void); -static int pk11_free_session_list(PK11_OPTYPE optype); -static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype); -static int pk11_destroy_cipher_key_objects(PK11_SESSION *session); -static int pk11_destroy_object(CK_SESSION_HANDLE handle, CK_OBJECT_HANDLE oh, - CK_BBOOL persistent); -static const char *get_PK11_LIBNAME(void); -static void free_PK11_LIBNAME(void); -static long set_PK11_LIBNAME(const char *name); - -/* Symmetric cipher and digest support functions */ -static int cipher_nid_to_pk11(int nid); -static int pk11_usable_ciphers(const int **nids); -static int pk11_usable_digests(const int **nids); -static int pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, - const unsigned char *iv, int enc); -static int pk11_cipher_final(PK11_SESSION *sp); -static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, unsigned int inl); -static int pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx); -static int pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, - const int **nids, int nid); -static int pk11_engine_digests(ENGINE *e, const EVP_MD **digest, - const int **nids, int nid); -static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, - const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp); -static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key, - int key_len); -static int md_nid_to_pk11(int nid); -static int pk11_digest_init(EVP_MD_CTX *ctx); -static int pk11_digest_update(EVP_MD_CTX *ctx, const void *data, - size_t count); -static int pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md); -static int pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from); -static int pk11_digest_cleanup(EVP_MD_CTX *ctx); - -static int pk11_choose_slots(int *any_slot_found); -static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist, - CK_SLOT_ID current_slot, int *current_slot_n_cipher, - int *local_cipher_nids); -static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist, - CK_SLOT_ID current_slot, int *current_slot_n_digest, - int *local_digest_nids); -static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR, int slot_id, - int *current_slot_n_cipher, int *local_cipher_nids, - PK11_CIPHER *cipher); -static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id, - int *current_slot_n_digest, int *local_digest_nids, - PK11_DIGEST *digest); - -static int pk11_init_all_locks(void); -static void pk11_free_all_locks(void); - -#ifdef SOLARIS_HW_SLOT_SELECTION -static int check_hw_mechanisms(void); -static int nid_in_table(int nid, int *nid_table); -#endif /* SOLARIS_HW_SLOT_SELECTION */ - -#define TRY_OBJ_DESTROY(sp, obj_hdl, retval, uselock, alg_type) \ - { \ - if (uselock) \ - LOCK_OBJSTORE(alg_type); \ - if (pk11_active_delete(obj_hdl, alg_type) == 1) \ - { \ - retval = pk11_destroy_object(sp->session, obj_hdl, \ - sp->persistent); \ - } \ - if (uselock) \ - UNLOCK_OBJSTORE(alg_type); \ - } - -static int cipher_nids[PK11_CIPHER_MAX]; -static int digest_nids[PK11_DIGEST_MAX]; -static int cipher_count = 0; -static int digest_count = 0; -static CK_BBOOL pk11_have_rsa = CK_FALSE; -static CK_BBOOL pk11_have_dsa = CK_FALSE; -static CK_BBOOL pk11_have_dh = CK_FALSE; -static CK_BBOOL pk11_have_random = CK_FALSE; - -/* - * Static list of ciphers. - * Note, that ciphers array is indexed by member PK11_CIPHER.id, - * thus ciphers[i].id == i - * Rows must be kept in sync with enum pk11_cipher_id. - */ -static PK11_CIPHER ciphers[] = - { - { PK11_DES_CBC, NID_des_cbc, 8, 8, 8, - CKK_DES, CKM_DES_CBC, }, - { PK11_DES3_CBC, NID_des_ede3_cbc, 8, 24, 24, - CKK_DES3, CKM_DES3_CBC, }, - { PK11_DES_ECB, NID_des_ecb, 0, 8, 8, - CKK_DES, CKM_DES_ECB, }, - { PK11_DES3_ECB, NID_des_ede3_ecb, 0, 24, 24, - CKK_DES3, CKM_DES3_ECB, }, - { PK11_RC4, NID_rc4, 0, 16, 256, - CKK_RC4, CKM_RC4, }, - { PK11_AES_128_CBC, NID_aes_128_cbc, 16, 16, 16, - CKK_AES, CKM_AES_CBC, }, - { PK11_AES_192_CBC, NID_aes_192_cbc, 16, 24, 24, - CKK_AES, CKM_AES_CBC, }, - { PK11_AES_256_CBC, NID_aes_256_cbc, 16, 32, 32, - CKK_AES, CKM_AES_CBC, }, - { PK11_AES_128_ECB, NID_aes_128_ecb, 0, 16, 16, - CKK_AES, CKM_AES_ECB, }, - { PK11_AES_192_ECB, NID_aes_192_ecb, 0, 24, 24, - CKK_AES, CKM_AES_ECB, }, - { PK11_AES_256_ECB, NID_aes_256_ecb, 0, 32, 32, - CKK_AES, CKM_AES_ECB, }, - { PK11_BLOWFISH_CBC, NID_bf_cbc, 8, 16, 16, - CKK_BLOWFISH, CKM_BLOWFISH_CBC, }, - { PK11_AES_128_CTR, NID_aes_128_ctr, 16, 16, 16, - CKK_AES, CKM_AES_CTR, }, - { PK11_AES_192_CTR, NID_aes_192_ctr, 16, 24, 24, - CKK_AES, CKM_AES_CTR, }, - { PK11_AES_256_CTR, NID_aes_256_ctr, 16, 32, 32, - CKK_AES, CKM_AES_CTR, }, - }; - -/* - * Static list of digests. - * Note, that digests array is indexed by member PK11_DIGEST.id, - * thus digests[i].id == i - * Rows must be kept in sync with enum pk11_digest_id. - */ -static PK11_DIGEST digests[] = - { - {PK11_MD5, NID_md5, CKM_MD5, }, - {PK11_SHA1, NID_sha1, CKM_SHA_1, }, - {PK11_SHA224, NID_sha224, CKM_SHA224, }, - {PK11_SHA256, NID_sha256, CKM_SHA256, }, - {PK11_SHA384, NID_sha384, CKM_SHA384, }, - {PK11_SHA512, NID_sha512, CKM_SHA512, }, - {0, NID_undef, 0xFFFF, }, - }; - -/* - * Structure to be used for the cipher_data/md_data in - * EVP_CIPHER_CTX/EVP_MD_CTX structures in order to use the same pk11 - * session in multiple cipher_update calls - */ -typedef struct PK11_CIPHER_STATE_st - { - PK11_SESSION *sp; - } PK11_CIPHER_STATE; - - -/* - * libcrypto EVP stuff - this is how we get wired to EVP so the engine gets - * called when libcrypto requests a cipher NID. - * - * Note how the PK11_CIPHER_STATE is used here. - */ - -/* DES CBC EVP */ -static const EVP_CIPHER pk11_des_cbc = - { - NID_des_cbc, - 8, 8, 8, - EVP_CIPH_CBC_MODE, - pk11_cipher_init, - pk11_cipher_do_cipher, - pk11_cipher_cleanup, - sizeof (PK11_CIPHER_STATE), - EVP_CIPHER_set_asn1_iv, - EVP_CIPHER_get_asn1_iv, - NULL - }; - -/* 3DES CBC EVP */ -static const EVP_CIPHER pk11_3des_cbc = - { - NID_des_ede3_cbc, - 8, 24, 8, - EVP_CIPH_CBC_MODE, - pk11_cipher_init, - pk11_cipher_do_cipher, - pk11_cipher_cleanup, - sizeof (PK11_CIPHER_STATE), - EVP_CIPHER_set_asn1_iv, - EVP_CIPHER_get_asn1_iv, - NULL - }; - -/* - * ECB modes don't use an Initial Vector so that's why set_asn1_parameters and - * get_asn1_parameters fields are set to NULL. - */ -static const EVP_CIPHER pk11_des_ecb = - { - NID_des_ecb, - 8, 8, 8, - EVP_CIPH_ECB_MODE, - pk11_cipher_init, - pk11_cipher_do_cipher, - pk11_cipher_cleanup, - sizeof (PK11_CIPHER_STATE), - NULL, - NULL, - NULL - }; - -static const EVP_CIPHER pk11_3des_ecb = - { - NID_des_ede3_ecb, - 8, 24, 8, - EVP_CIPH_ECB_MODE, - pk11_cipher_init, - pk11_cipher_do_cipher, - pk11_cipher_cleanup, - sizeof (PK11_CIPHER_STATE), - NULL, - NULL, - NULL - }; - - -static const EVP_CIPHER pk11_aes_128_cbc = - { - NID_aes_128_cbc, - 16, 16, 16, - EVP_CIPH_CBC_MODE, - pk11_cipher_init, - pk11_cipher_do_cipher, - pk11_cipher_cleanup, - sizeof (PK11_CIPHER_STATE), - EVP_CIPHER_set_asn1_iv, - EVP_CIPHER_get_asn1_iv, - NULL - }; - -static const EVP_CIPHER pk11_aes_192_cbc = - { - NID_aes_192_cbc, - 16, 24, 16, - EVP_CIPH_CBC_MODE, - pk11_cipher_init, - pk11_cipher_do_cipher, - pk11_cipher_cleanup, - sizeof (PK11_CIPHER_STATE), - EVP_CIPHER_set_asn1_iv, - EVP_CIPHER_get_asn1_iv, - NULL - }; - -static const EVP_CIPHER pk11_aes_256_cbc = - { - NID_aes_256_cbc, - 16, 32, 16, - EVP_CIPH_CBC_MODE, - pk11_cipher_init, - pk11_cipher_do_cipher, - pk11_cipher_cleanup, - sizeof (PK11_CIPHER_STATE), - EVP_CIPHER_set_asn1_iv, - EVP_CIPHER_get_asn1_iv, - NULL - }; - -/* - * ECB modes don't use IV so that's why set_asn1_parameters and - * get_asn1_parameters are set to NULL. - */ -static const EVP_CIPHER pk11_aes_128_ecb = - { - NID_aes_128_ecb, - 16, 16, 0, - EVP_CIPH_ECB_MODE, - pk11_cipher_init, - pk11_cipher_do_cipher, - pk11_cipher_cleanup, - sizeof (PK11_CIPHER_STATE), - NULL, - NULL, - NULL - }; - -static const EVP_CIPHER pk11_aes_192_ecb = - { - NID_aes_192_ecb, - 16, 24, 0, - EVP_CIPH_ECB_MODE, - pk11_cipher_init, - pk11_cipher_do_cipher, - pk11_cipher_cleanup, - sizeof (PK11_CIPHER_STATE), - NULL, - NULL, - NULL - }; - -static const EVP_CIPHER pk11_aes_256_ecb = - { - NID_aes_256_ecb, - 16, 32, 0, - EVP_CIPH_ECB_MODE, - pk11_cipher_init, - pk11_cipher_do_cipher, - pk11_cipher_cleanup, - sizeof (PK11_CIPHER_STATE), - NULL, - NULL, - NULL - }; - -static EVP_CIPHER pk11_aes_128_ctr = - { - NID_aes_128_ctr, - 16, 16, 16, - EVP_CIPH_CTR_MODE, - pk11_cipher_init, - pk11_cipher_do_cipher, - pk11_cipher_cleanup, - sizeof (PK11_CIPHER_STATE), - EVP_CIPHER_set_asn1_iv, - EVP_CIPHER_get_asn1_iv, - NULL - }; - -static EVP_CIPHER pk11_aes_192_ctr = - { - NID_aes_192_ctr, - 16, 24, 16, - EVP_CIPH_CTR_MODE, - pk11_cipher_init, - pk11_cipher_do_cipher, - pk11_cipher_cleanup, - sizeof (PK11_CIPHER_STATE), - EVP_CIPHER_set_asn1_iv, - EVP_CIPHER_get_asn1_iv, - NULL - }; - -static EVP_CIPHER pk11_aes_256_ctr = - { - NID_aes_256_ctr, - 16, 32, 16, - EVP_CIPH_CTR_MODE, - pk11_cipher_init, - pk11_cipher_do_cipher, - pk11_cipher_cleanup, - sizeof (PK11_CIPHER_STATE), - EVP_CIPHER_set_asn1_iv, - EVP_CIPHER_get_asn1_iv, - NULL - }; - -static const EVP_CIPHER pk11_bf_cbc = - { - NID_bf_cbc, - 8, 16, 8, - EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CBC_MODE, - pk11_cipher_init, - pk11_cipher_do_cipher, - pk11_cipher_cleanup, - sizeof (PK11_CIPHER_STATE), - EVP_CIPHER_set_asn1_iv, - EVP_CIPHER_get_asn1_iv, - NULL - }; - -static const EVP_CIPHER pk11_rc4 = - { - NID_rc4, - 1, 16, 0, - EVP_CIPH_VARIABLE_LENGTH, - pk11_cipher_init, - pk11_cipher_do_cipher, - pk11_cipher_cleanup, - sizeof (PK11_CIPHER_STATE), - NULL, - NULL, - NULL - }; - -static const EVP_MD pk11_md5 = - { - NID_md5, - NID_md5WithRSAEncryption, - MD5_DIGEST_LENGTH, - 0, - pk11_digest_init, - pk11_digest_update, - pk11_digest_final, - pk11_digest_copy, - pk11_digest_cleanup, - EVP_PKEY_RSA_method, - MD5_CBLOCK, - sizeof (PK11_CIPHER_STATE), - }; - -static const EVP_MD pk11_sha1 = - { - NID_sha1, - NID_sha1WithRSAEncryption, - SHA_DIGEST_LENGTH, - EVP_MD_FLAG_FIPS, - pk11_digest_init, - pk11_digest_update, - pk11_digest_final, - pk11_digest_copy, - pk11_digest_cleanup, - EVP_PKEY_RSA_method, - SHA_CBLOCK, - sizeof (PK11_CIPHER_STATE), - }; - -static const EVP_MD pk11_sha224 = - { - NID_sha224, - NID_sha224WithRSAEncryption, - SHA224_DIGEST_LENGTH, - EVP_MD_FLAG_FIPS, - pk11_digest_init, - pk11_digest_update, - pk11_digest_final, - pk11_digest_copy, - pk11_digest_cleanup, - EVP_PKEY_RSA_method, - /* SHA-224 uses the same cblock size as SHA-256 */ - SHA256_CBLOCK, - sizeof (PK11_CIPHER_STATE), - }; - -static const EVP_MD pk11_sha256 = - { - NID_sha256, - NID_sha256WithRSAEncryption, - SHA256_DIGEST_LENGTH, - EVP_MD_FLAG_FIPS, - pk11_digest_init, - pk11_digest_update, - pk11_digest_final, - pk11_digest_copy, - pk11_digest_cleanup, - EVP_PKEY_RSA_method, - SHA256_CBLOCK, - sizeof (PK11_CIPHER_STATE), - }; - -static const EVP_MD pk11_sha384 = - { - NID_sha384, - NID_sha384WithRSAEncryption, - SHA384_DIGEST_LENGTH, - EVP_MD_FLAG_FIPS, - pk11_digest_init, - pk11_digest_update, - pk11_digest_final, - pk11_digest_copy, - pk11_digest_cleanup, - EVP_PKEY_RSA_method, - /* SHA-384 uses the same cblock size as SHA-512 */ - SHA512_CBLOCK, - sizeof (PK11_CIPHER_STATE), - }; - -static const EVP_MD pk11_sha512 = - { - NID_sha512, - NID_sha512WithRSAEncryption, - SHA512_DIGEST_LENGTH, - EVP_MD_FLAG_FIPS, - pk11_digest_init, - pk11_digest_update, - pk11_digest_final, - pk11_digest_copy, - pk11_digest_cleanup, - EVP_PKEY_RSA_method, - SHA512_CBLOCK, - sizeof (PK11_CIPHER_STATE), - }; - -/* - * Initialization function. Sets up various PKCS#11 library components. - * The definitions for control commands specific to this engine - */ -#define PK11_CMD_SO_PATH ENGINE_CMD_BASE -static const ENGINE_CMD_DEFN pk11_cmd_defns[] = - { - { - PK11_CMD_SO_PATH, - "SO_PATH", - "Specifies the path to the 'pkcs#11' shared library", - ENGINE_CMD_FLAG_STRING - }, - {0, NULL, NULL, 0} - }; - - -static RAND_METHOD pk11_random = - { - pk11_rand_seed, - pk11_rand_bytes, - pk11_rand_cleanup, - pk11_rand_add, - pk11_rand_bytes, - pk11_rand_status - }; - - -/* Constants used when creating the ENGINE */ -static const char *engine_pk11_id = "pkcs11"; -static const char *engine_pk11_name = "PKCS #11 engine support"; - -CK_FUNCTION_LIST_PTR pFuncList = NULL; -static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList"; - -/* - * This is a static string constant for the DSO file name and the function - * symbol names to bind to. We set it in the Configure script based on whether - * this is 32 or 64 bit build. - */ -static const char def_PK11_LIBNAME[] = PK11_LIB_LOCATION; - -static CK_BBOOL pk11_true = CK_TRUE; -static CK_BBOOL pk11_false = CK_FALSE; -/* Needed in hw_pk11_pub.c as well so that's why it is not static. */ -CK_SLOT_ID pubkey_SLOTID = 0; -static CK_SLOT_ID rand_SLOTID = 0; -static CK_SLOT_ID SLOTID = 0; -static CK_BBOOL pk11_library_initialized = CK_FALSE; -static CK_BBOOL pk11_atfork_initialized = CK_FALSE; -static int pk11_pid = 0; - -static DSO *pk11_dso = NULL; - -/* allocate and initialize all locks used by the engine itself */ -static int pk11_init_all_locks(void) - { - int type; - -#ifndef OPENSSL_NO_RSA - find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); - if (find_lock[OP_RSA] == NULL) - goto malloc_err; - (void) pthread_mutex_init(find_lock[OP_RSA], NULL); -#endif /* OPENSSL_NO_RSA */ - - if ((uri_lock = OPENSSL_malloc(sizeof (pthread_mutex_t))) == NULL) - goto malloc_err; - (void) pthread_mutex_init(uri_lock, NULL); - -#ifndef OPENSSL_NO_DSA - find_lock[OP_DSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); - if (find_lock[OP_DSA] == NULL) - goto malloc_err; - (void) pthread_mutex_init(find_lock[OP_DSA], NULL); -#endif /* OPENSSL_NO_DSA */ - -#ifndef OPENSSL_NO_DH - find_lock[OP_DH] = OPENSSL_malloc(sizeof (pthread_mutex_t)); - if (find_lock[OP_DH] == NULL) - goto malloc_err; - (void) pthread_mutex_init(find_lock[OP_DH], NULL); -#endif /* OPENSSL_NO_DH */ - - for (type = 0; type < OP_MAX; type++) - { - session_cache[type].lock = - OPENSSL_malloc(sizeof (pthread_mutex_t)); - if (session_cache[type].lock == NULL) - goto malloc_err; - (void) pthread_mutex_init(session_cache[type].lock, NULL); - } - - return (1); - -malloc_err: - pk11_free_all_locks(); - PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE); - return (0); - } - -static void pk11_free_all_locks(void) - { - int type; - -#ifndef OPENSSL_NO_RSA - if (find_lock[OP_RSA] != NULL) - { - (void) pthread_mutex_destroy(find_lock[OP_RSA]); - OPENSSL_free(find_lock[OP_RSA]); - find_lock[OP_RSA] = NULL; - } -#endif /* OPENSSL_NO_RSA */ -#ifndef OPENSSL_NO_DSA - if (find_lock[OP_DSA] != NULL) - { - (void) pthread_mutex_destroy(find_lock[OP_DSA]); - OPENSSL_free(find_lock[OP_DSA]); - find_lock[OP_DSA] = NULL; - } -#endif /* OPENSSL_NO_DSA */ -#ifndef OPENSSL_NO_DH - if (find_lock[OP_DH] != NULL) - { - (void) pthread_mutex_destroy(find_lock[OP_DH]); - OPENSSL_free(find_lock[OP_DH]); - find_lock[OP_DH] = NULL; - } -#endif /* OPENSSL_NO_DH */ - - for (type = 0; type < OP_MAX; type++) - { - if (session_cache[type].lock != NULL) - { - (void) pthread_mutex_destroy(session_cache[type].lock); - OPENSSL_free(session_cache[type].lock); - session_cache[type].lock = NULL; - } - } - } - -/* - * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support. - */ -static int bind_pk11(ENGINE *e) - { -#ifndef OPENSSL_NO_RSA - const RSA_METHOD *rsa = NULL; - RSA_METHOD *pk11_rsa = PK11_RSA(); -#endif /* OPENSSL_NO_RSA */ - if (!pk11_library_initialized) - if (!pk11_library_init(e)) - return (0); - - if (!ENGINE_set_id(e, engine_pk11_id) || - !ENGINE_set_name(e, engine_pk11_name) || - !ENGINE_set_ciphers(e, pk11_engine_ciphers) || - !ENGINE_set_digests(e, pk11_engine_digests)) - return (0); -#ifndef OPENSSL_NO_RSA - if (pk11_have_rsa == CK_TRUE) - { - if (!ENGINE_set_RSA(e, PK11_RSA()) || - !ENGINE_set_load_privkey_function(e, pk11_load_privkey) || - !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey)) - return (0); - DEBUG_SLOT_SEL("%s: registered RSA\n", PK11_DBG); - } -#endif /* OPENSSL_NO_RSA */ -#ifndef OPENSSL_NO_DSA - if (pk11_have_dsa == CK_TRUE) - { - if (!ENGINE_set_DSA(e, PK11_DSA())) - return (0); - DEBUG_SLOT_SEL("%s: registered DSA\n", PK11_DBG); - } -#endif /* OPENSSL_NO_DSA */ -#ifndef OPENSSL_NO_DH - if (pk11_have_dh == CK_TRUE) - { - if (!ENGINE_set_DH(e, PK11_DH())) - return (0); - DEBUG_SLOT_SEL("%s: registered DH\n", PK11_DBG); - } -#endif /* OPENSSL_NO_DH */ - if (pk11_have_random) - { - if (!ENGINE_set_RAND(e, &pk11_random)) - return (0); - DEBUG_SLOT_SEL("%s: registered random\n", PK11_DBG); - } - if (!ENGINE_set_init_function(e, pk11_init) || - !ENGINE_set_destroy_function(e, pk11_destroy) || - !ENGINE_set_finish_function(e, pk11_finish) || - !ENGINE_set_ctrl_function(e, pk11_ctrl) || - !ENGINE_set_cmd_defns(e, pk11_cmd_defns)) - return (0); - -/* - * Apache calls OpenSSL function RSA_blinding_on() once during startup - * which in turn calls bn_mod_exp. Since we do not implement bn_mod_exp - * here, we wire it back to the OpenSSL software implementation. - * Since it is used only once, performance is not a concern. - */ -#ifndef OPENSSL_NO_RSA - rsa = RSA_PKCS1_SSLeay(); - pk11_rsa->rsa_mod_exp = rsa->rsa_mod_exp; - pk11_rsa->bn_mod_exp = rsa->bn_mod_exp; -#endif /* OPENSSL_NO_RSA */ - - /* Ensure the pk11 error handling is set up */ - ERR_load_pk11_strings(); - - return (1); - } - -/* Dynamic engine support is disabled at a higher level for Solaris */ -#ifdef ENGINE_DYNAMIC_SUPPORT -static int bind_helper(ENGINE *e, const char *id) - { - if (id && (strcmp(id, engine_pk11_id) != 0)) - return (0); - - if (!bind_pk11(e)) - return (0); - - return (1); - } - -IMPLEMENT_DYNAMIC_CHECK_FN() -IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) - -#else -static ENGINE *engine_pk11(void) - { - ENGINE *ret = ENGINE_new(); - - if (!ret) - return (NULL); - - if (!bind_pk11(ret)) - { - ENGINE_free(ret); - return (NULL); - } - - return (ret); - } - -void -ENGINE_load_pk11(void) - { - ENGINE *e_pk11 = NULL; - - /* - * Do not use dynamic PKCS#11 library on Solaris due to - * security reasons. We will link it in statically. - */ - /* Attempt to load PKCS#11 library */ - if (!pk11_dso) - pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0); - - if (pk11_dso == NULL) - { - PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE); - return; - } - - e_pk11 = engine_pk11(); - if (!e_pk11) - { - DSO_free(pk11_dso); - pk11_dso = NULL; - return; - } - - /* - * At this point, the pk11 shared library is either dynamically - * loaded or statically linked in. So, initialize the pk11 - * library before calling ENGINE_set_default since the latter - * needs cipher and digest algorithm information - */ - if (!pk11_library_init(e_pk11)) - { - DSO_free(pk11_dso); - pk11_dso = NULL; - ENGINE_free(e_pk11); - return; - } - - ENGINE_add(e_pk11); - - ENGINE_free(e_pk11); - ERR_clear_error(); - } -#endif /* ENGINE_DYNAMIC_SUPPORT */ - -/* - * These are the static string constants for the DSO file name and - * the function symbol names to bind to. - */ -static const char *PK11_LIBNAME = NULL; - -static const char *get_PK11_LIBNAME(void) - { - if (PK11_LIBNAME) - return (PK11_LIBNAME); - - return (def_PK11_LIBNAME); - } - -static void free_PK11_LIBNAME(void) - { - if (PK11_LIBNAME) - OPENSSL_free((void*)PK11_LIBNAME); - - PK11_LIBNAME = NULL; - } - -static long set_PK11_LIBNAME(const char *name) - { - free_PK11_LIBNAME(); - - return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0); - } - -/* acquire all engine specific mutexes before fork */ -static void pk11_fork_prepare(void) - { - int i; - - if (!pk11_library_initialized) - return; - - LOCK_OBJSTORE(OP_RSA); - LOCK_OBJSTORE(OP_DSA); - LOCK_OBJSTORE(OP_DH); - (void) pthread_mutex_lock(uri_lock); - for (i = 0; i < OP_MAX; i++) - { - (void) pthread_mutex_lock(session_cache[i].lock); - } - } - -/* release all engine specific mutexes */ -static void pk11_fork_parent(void) - { - int i; - - if (!pk11_library_initialized) - return; - - for (i = OP_MAX - 1; i >= 0; i--) - { - (void) pthread_mutex_unlock(session_cache[i].lock); - } - UNLOCK_OBJSTORE(OP_DH); - UNLOCK_OBJSTORE(OP_DSA); - UNLOCK_OBJSTORE(OP_RSA); - (void) pthread_mutex_unlock(uri_lock); - } - -/* - * same situation as in parent - we need to unlock all locks to make them - * accessible to all threads. - */ -static void pk11_fork_child(void) - { - int i; - - if (!pk11_library_initialized) - return; - - for (i = OP_MAX - 1; i >= 0; i--) - { - (void) pthread_mutex_unlock(session_cache[i].lock); - } - UNLOCK_OBJSTORE(OP_DH); - UNLOCK_OBJSTORE(OP_DSA); - UNLOCK_OBJSTORE(OP_RSA); - (void) pthread_mutex_unlock(uri_lock); - } - -/* Initialization function for the pk11 engine */ -static int pk11_init(ENGINE *e) - { - return (pk11_library_init(e)); - } - -/* - * Initialization function. Sets up various PKCS#11 library components. - * It selects a slot based on predefined critiera. In the process, it also - * count how many ciphers and digests to support. Since the cipher and - * digest information is needed when setting default engine, this function - * needs to be called before calling ENGINE_set_default. - */ -/* ARGSUSED */ -static int pk11_library_init(ENGINE *e) - { - CK_C_GetFunctionList p; - CK_RV rv = CKR_OK; - CK_INFO info; - CK_ULONG ul_state_len; - int any_slot_found; - int i; - - /* - * pk11_library_initialized is set to 0 in pk11_finish() which is called - * from ENGINE_finish(). However, if there is still at least one - * existing functional reference to the engine (see engine(3) for more - * information), pk11_finish() is skipped. For example, this can happen - * if an application forgets to clear one cipher context. In case of a - * fork() when the application is finishing the engine so that it can be - * reinitialized in the child, forgotten functional reference causes - * pk11_library_initialized to stay 1. In that case we need the PID - * check so that we properly initialize the engine again. - */ - if (pk11_library_initialized) - { - if (pk11_pid == getpid()) - { - return (1); - } - else - { - global_session = CK_INVALID_HANDLE; - /* - * free the locks first to prevent memory leak in case - * the application calls fork() without finishing the - * engine first. - */ - pk11_free_all_locks(); - } - } - - if (pk11_dso == NULL) - { - PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE); - goto err; - } - -#ifdef SOLARIS_HW_SLOT_SELECTION - if (check_hw_mechanisms() == 0) - goto err; -#endif /* SOLARIS_HW_SLOT_SELECTION */ - - /* get the C_GetFunctionList function from the loaded library */ - p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso, - PK11_GET_FUNCTION_LIST); - if (!p) - { - PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); - goto err; - } - - /* get the full function list from the loaded library */ - rv = p(&pFuncList); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv); - goto err; - } - - rv = pFuncList->C_Initialize(NULL_PTR); - if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) - { - PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv); - goto err; - } - - rv = pFuncList->C_GetInfo(&info); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv); - goto err; - } - - if (pk11_choose_slots(&any_slot_found) == 0) - goto err; - - /* - * The library we use, set in def_PK11_LIBNAME, may not offer any - * slot(s). In that case, we must not proceed but we must not return an - * error. The reason is that applications that try to set up the PKCS#11 - * engine don't exit on error during the engine initialization just - * because no slot was present. - */ - if (any_slot_found == 0) - return (1); - - if (global_session == CK_INVALID_HANDLE) - { - /* Open the global_session for the new process */ - rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, - NULL_PTR, NULL_PTR, &global_session); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_LIBRARY_INIT, - PK11_R_OPENSESSION, rv); - goto err; - } - } - - /* - * Disable digest if C_GetOperationState is not supported since - * this function is required by OpenSSL digest copy function - */ - if (pFuncList->C_GetOperationState(global_session, NULL, &ul_state_len) - == CKR_FUNCTION_NOT_SUPPORTED) - { - DEBUG_SLOT_SEL("%s: C_GetOperationState() not supported, " - "setting digest_count to 0\n", PK11_DBG); - digest_count = 0; - } - - pk11_library_initialized = CK_TRUE; - pk11_pid = getpid(); - /* - * if initialization of the locks fails pk11_init_all_locks() - * will do the cleanup. - */ - if (!pk11_init_all_locks()) - goto err; - for (i = 0; i < OP_MAX; i++) - session_cache[i].head = NULL; - /* - * initialize active lists. We only use active lists - * for asymmetric ciphers. - */ - for (i = 0; i < OP_MAX; i++) - active_list[i] = NULL; - - if (!pk11_atfork_initialized) - { - if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent, - pk11_fork_child) != 0) - { - PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED); - goto err; - } - pk11_atfork_initialized = CK_TRUE; - } - - return (1); - -err: - return (0); - } - -/* Destructor (complements the "ENGINE_pk11()" constructor) */ -/* ARGSUSED */ -static int pk11_destroy(ENGINE *e) - { - free_PK11_LIBNAME(); - ERR_unload_pk11_strings(); - return (1); - } - -/* - * Termination function to clean up the session, the token, and the pk11 - * library. - */ -/* ARGSUSED */ -static int pk11_finish(ENGINE *e) - { - int i; - - if (pk11_dso == NULL) - { - PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED); - goto err; - } - - OPENSSL_assert(pFuncList != NULL); - - if (pk11_free_all_sessions() == 0) - goto err; - - /* free all active lists */ - for (i = 0; i < OP_MAX; i++) - pk11_free_active_list(i); - - pFuncList->C_CloseSession(global_session); - global_session = CK_INVALID_HANDLE; - - /* - * Since we are part of a library (libcrypto.so), calling this function - * may have side-effects. - */ -#if 0 - pFuncList->C_Finalize(NULL); -#endif - if (!DSO_free(pk11_dso)) - { - PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE); - goto err; - } - pk11_dso = NULL; - pFuncList = NULL; - pk11_library_initialized = CK_FALSE; - pk11_pid = 0; - /* - * There is no way how to unregister atfork handlers (other than - * unloading the library) so we just free the locks. For this reason - * the atfork handlers check if the engine is initialized and bail out - * immediately if not. This is necessary in case a process finishes - * the engine before calling fork(). - */ - pk11_free_all_locks(); - - return (1); - -err: - return (0); - } - -/* Standard engine interface function to set the dynamic library path */ -/* ARGSUSED */ -static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) - { - int initialized = ((pk11_dso == NULL) ? 0 : 1); - - switch (cmd) - { - case PK11_CMD_SO_PATH: - if (p == NULL) - { - PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); - return (0); - } - - if (initialized) - { - PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED); - return (0); - } - - return (set_PK11_LIBNAME((const char *)p)); - default: - break; - } - - PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED); - - return (0); - } - - -/* Required function by the engine random interface. It does nothing here */ -static void pk11_rand_cleanup(void) - { - return; - } - -/* ARGSUSED */ -static void pk11_rand_add(const void *buf, int num, double add) - { - PK11_SESSION *sp; - - if ((sp = pk11_get_session(OP_RAND)) == NULL) - return; - - /* - * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since - * the calling functions do not care anyway - */ - pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num); - pk11_return_session(sp, OP_RAND); - - return; - } - -static void pk11_rand_seed(const void *buf, int num) - { - pk11_rand_add(buf, num, 0); - } - -static int pk11_rand_bytes(unsigned char *buf, int num) - { - CK_RV rv; - PK11_SESSION *sp; - - if ((sp = pk11_get_session(OP_RAND)) == NULL) - return (0); - - rv = pFuncList->C_GenerateRandom(sp->session, buf, num); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv); - pk11_return_session(sp, OP_RAND); - return (0); - } - - pk11_return_session(sp, OP_RAND); - return (1); - } - -/* Required function by the engine random interface. It does nothing here */ -static int pk11_rand_status(void) - { - return (1); - } - -/* Free all BIGNUM structures from PK11_SESSION. */ -static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype) - { - switch (optype) - { -#ifndef OPENSSL_NO_RSA - case OP_RSA: - if (sp->opdata_rsa_n_num != NULL) - { - BN_free(sp->opdata_rsa_n_num); - sp->opdata_rsa_n_num = NULL; - } - if (sp->opdata_rsa_e_num != NULL) - { - BN_free(sp->opdata_rsa_e_num); - sp->opdata_rsa_e_num = NULL; - } - if (sp->opdata_rsa_d_num != NULL) - { - BN_free(sp->opdata_rsa_d_num); - sp->opdata_rsa_d_num = NULL; - } - break; -#endif -#ifndef OPENSSL_NO_DSA - case OP_DSA: - if (sp->opdata_dsa_pub_num != NULL) - { - BN_free(sp->opdata_dsa_pub_num); - sp->opdata_dsa_pub_num = NULL; - } - if (sp->opdata_dsa_priv_num != NULL) - { - BN_free(sp->opdata_dsa_priv_num); - sp->opdata_dsa_priv_num = NULL; - } - break; -#endif -#ifndef OPENSSL_NO_DH - case OP_DH: - if (sp->opdata_dh_priv_num != NULL) - { - BN_free(sp->opdata_dh_priv_num); - sp->opdata_dh_priv_num = NULL; - } - break; -#endif - default: - break; - } - } - -/* - * Get new PK11_SESSION structure ready for use. Every process must have - * its own freelist of PK11_SESSION structures so handle fork() here - * by destroying the old and creating new freelist. - * The returned PK11_SESSION structure is disconnected from the freelist. - */ -PK11_SESSION * -pk11_get_session(PK11_OPTYPE optype) - { - PK11_SESSION *sp = NULL, *sp1, *freelist; - pthread_mutex_t *freelist_lock; - static pid_t pid = 0; - pid_t new_pid; - CK_RV rv; - - switch (optype) - { - case OP_RSA: - case OP_DSA: - case OP_DH: - case OP_RAND: - case OP_DIGEST: - case OP_CIPHER: - freelist_lock = session_cache[optype].lock; - break; - default: - PK11err(PK11_F_GET_SESSION, - PK11_R_INVALID_OPERATION_TYPE); - return (NULL); - } - (void) pthread_mutex_lock(freelist_lock); - - /* - * Will use it to find out if we forked. We cannot use the PID field in - * the session structure because we could get a newly allocated session - * here, with no PID information. - */ - if (pid == 0) - pid = getpid(); - - freelist = session_cache[optype].head; - sp = freelist; - - /* - * If the free list is empty, allocate new uninitialized (filled - * with zeroes) PK11_SESSION structure otherwise return first - * structure from the freelist. - */ - if (sp == NULL) - { - if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL) - { - PK11err(PK11_F_GET_SESSION, - PK11_R_MALLOC_FAILURE); - goto err; - } - (void) memset(sp, 0, sizeof (PK11_SESSION)); - - /* - * It is a new session so it will look like a cache miss to the - * code below. So, we must not try to to destroy its members so - * mark them as unused. - */ - sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; - sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; - } - else - freelist = sp->next; - - /* - * Check whether we have forked. In that case, we must get rid of all - * inherited sessions and start allocating new ones. - */ - if (pid != (new_pid = getpid())) - { - pid = new_pid; - - /* - * We are a new process and thus need to free any inherited - * PK11_SESSION objects aside from the first session (sp) which - * is the only PK11_SESSION structure we will reuse (for the - * head of the list). - */ - while ((sp1 = freelist) != NULL) - { - freelist = sp1->next; - /* - * NOTE: we do not want to call pk11_free_all_sessions() - * here because it would close underlying PKCS#11 - * sessions and destroy all objects. - */ - pk11_free_nums(sp1, optype); - OPENSSL_free(sp1); - } - - /* we have to free the active list as well. */ - pk11_free_active_list(optype); - - /* Initialize the process */ - rv = pFuncList->C_Initialize(NULL_PTR); - if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) - { - PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE, - rv); - OPENSSL_free(sp); - sp = NULL; - goto err; - } - - /* - * Choose slot here since the slot table is different on this - * process. If we are here then we must have found at least one - * usable slot before so we don't need to check any_slot_found. - * See pk11_library_init()'s usage of this function for more - * information. - */ -#ifdef SOLARIS_HW_SLOT_SELECTION - if (check_hw_mechanisms() == 0) - goto err; -#endif /* SOLARIS_HW_SLOT_SELECTION */ - if (pk11_choose_slots(NULL) == 0) - goto err; - - /* Open the global_session for the new process */ - rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, - NULL_PTR, NULL_PTR, &global_session); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION, - rv); - OPENSSL_free(sp); - sp = NULL; - goto err; - } - - /* - * It is an inherited session from our parent so it needs - * re-initialization. - */ - if (pk11_setup_session(sp, optype) == 0) - { - OPENSSL_free(sp); - sp = NULL; - goto err; - } - if (pk11_token_relogin(sp->session) == 0) - { - /* - * We will keep the session in the cache list and let - * the caller cope with the situation. - */ - freelist = sp; - sp = NULL; - goto err; - } - } - - if (sp->pid == 0) - { - /* It is a new session and needs initialization. */ - if (pk11_setup_session(sp, optype) == 0) - { - OPENSSL_free(sp); - sp = NULL; - } - } - - /* set new head for the list of PK11_SESSION objects */ - session_cache[optype].head = freelist; - -err: - if (sp != NULL) - sp->next = NULL; - - (void) pthread_mutex_unlock(freelist_lock); - - return (sp); - } - - -void -pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype) - { - pthread_mutex_t *freelist_lock; - PK11_SESSION *freelist; - - /* - * If this is a session from the parent it will be taken care of and - * freed in pk11_get_session() as part of the post-fork clean up the - * next time we will ask for a new session. - */ - if (sp == NULL || sp->pid != getpid()) - return; - - switch (optype) - { - case OP_RSA: - case OP_DSA: - case OP_DH: - case OP_RAND: - case OP_DIGEST: - case OP_CIPHER: - freelist_lock = session_cache[optype].lock; - break; - default: - PK11err(PK11_F_RETURN_SESSION, - PK11_R_INVALID_OPERATION_TYPE); - return; - } - - (void) pthread_mutex_lock(freelist_lock); - freelist = session_cache[optype].head; - sp->next = freelist; - session_cache[optype].head = sp; - (void) pthread_mutex_unlock(freelist_lock); - } - - -/* Destroy all objects. This function is called when the engine is finished */ -static int pk11_free_all_sessions() - { - int ret = 1; - int type; - -#ifndef OPENSSL_NO_RSA - (void) pk11_destroy_rsa_key_objects(NULL); -#endif /* OPENSSL_NO_RSA */ -#ifndef OPENSSL_NO_DSA - (void) pk11_destroy_dsa_key_objects(NULL); -#endif /* OPENSSL_NO_DSA */ -#ifndef OPENSSL_NO_DH - (void) pk11_destroy_dh_key_objects(NULL); -#endif /* OPENSSL_NO_DH */ - (void) pk11_destroy_cipher_key_objects(NULL); - - /* - * We try to release as much as we can but any error means that we will - * return 0 on exit. - */ - for (type = 0; type < OP_MAX; type++) - { - if (pk11_free_session_list(type) == 0) - ret = 0; - } - - return (ret); - } - -/* - * Destroy session structures from the linked list specified. Free as many - * sessions as possible but any failure in C_CloseSession() means that we - * return an error on return. - */ -static int pk11_free_session_list(PK11_OPTYPE optype) - { - CK_RV rv; - PK11_SESSION *sp = NULL; - PK11_SESSION *freelist = NULL; - pid_t mypid = getpid(); - pthread_mutex_t *freelist_lock; - int ret = 1; - - switch (optype) - { - case OP_RSA: - case OP_DSA: - case OP_DH: - case OP_RAND: - case OP_DIGEST: - case OP_CIPHER: - freelist_lock = session_cache[optype].lock; - break; - default: - PK11err(PK11_F_FREE_ALL_SESSIONS, - PK11_R_INVALID_OPERATION_TYPE); - return (0); - } - - (void) pthread_mutex_lock(freelist_lock); - freelist = session_cache[optype].head; - while ((sp = freelist) != NULL) - { - if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid) - { - rv = pFuncList->C_CloseSession(sp->session); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_FREE_ALL_SESSIONS, - PK11_R_CLOSESESSION, rv); - ret = 0; - } - } - freelist = sp->next; - pk11_free_nums(sp, optype); - OPENSSL_free(sp); - } - - (void) pthread_mutex_unlock(freelist_lock); - return (ret); - } - - -static int -pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype) - { - CK_RV rv; - CK_SLOT_ID myslot; - - switch (optype) - { - case OP_RSA: - case OP_DSA: - case OP_DH: - myslot = pubkey_SLOTID; - break; - case OP_RAND: - myslot = rand_SLOTID; - break; - case OP_DIGEST: - case OP_CIPHER: - myslot = SLOTID; - break; - default: - PK11err(PK11_F_SETUP_SESSION, - PK11_R_INVALID_OPERATION_TYPE); - return (0); - } - - sp->session = CK_INVALID_HANDLE; - DEBUG_SLOT_SEL("%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype); - rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, - NULL_PTR, NULL_PTR, &sp->session); - if (rv == CKR_CRYPTOKI_NOT_INITIALIZED) - { - /* - * We are probably a child process so force the - * reinitialize of the session - */ - pk11_library_initialized = CK_FALSE; - if (!pk11_library_init(NULL)) - return (0); - rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, - NULL_PTR, NULL_PTR, &sp->session); - } - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv); - return (0); - } - - sp->pid = getpid(); - - switch (optype) - { -#ifndef OPENSSL_NO_RSA - case OP_RSA: - sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; - sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; - sp->opdata_rsa_pub = NULL; - sp->opdata_rsa_n_num = NULL; - sp->opdata_rsa_e_num = NULL; - sp->opdata_rsa_priv = NULL; - sp->opdata_rsa_d_num = NULL; - break; -#endif /* OPENSSL_NO_RSA */ -#ifndef OPENSSL_NO_DSA - case OP_DSA: - sp->opdata_dsa_pub_key = CK_INVALID_HANDLE; - sp->opdata_dsa_priv_key = CK_INVALID_HANDLE; - sp->opdata_dsa_pub = NULL; - sp->opdata_dsa_pub_num = NULL; - sp->opdata_dsa_priv = NULL; - sp->opdata_dsa_priv_num = NULL; - break; -#endif /* OPENSSL_NO_DSA */ -#ifndef OPENSSL_NO_DH - case OP_DH: - sp->opdata_dh_key = CK_INVALID_HANDLE; - sp->opdata_dh = NULL; - sp->opdata_dh_priv_num = NULL; - break; -#endif /* OPENSSL_NO_DH */ - case OP_CIPHER: - sp->opdata_cipher_key = CK_INVALID_HANDLE; - sp->opdata_encrypt = -1; - break; - } - - /* - * We always initialize the session as containing a non-persistent - * object. The key load functions set it to persistent if that is so. - */ - sp->persistent = CK_FALSE; - return (1); - } - -#ifndef OPENSSL_NO_RSA -/* - * Destroy all non-NULL RSA parameters. For the RSA keys by reference code, - * public components 'n'/'e' are the key components we use to check for the - * cache hit even for the private keys. So, no matter whether we are destroying - * a public or a private key, we always free what we can. - */ -static void -destroy_all_rsa_params(PK11_SESSION *sp) - { - if (sp->opdata_rsa_n_num != NULL) - { - BN_free(sp->opdata_rsa_n_num); - sp->opdata_rsa_n_num = NULL; - } - if (sp->opdata_rsa_e_num != NULL) - { - BN_free(sp->opdata_rsa_e_num); - sp->opdata_rsa_e_num = NULL; - } - if (sp->opdata_rsa_d_num != NULL) - { - BN_free(sp->opdata_rsa_d_num); - sp->opdata_rsa_d_num = NULL; - } - } - -/* Destroy RSA public key from single session. */ -int -pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) - { - int ret = 0; - - if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE) - { - TRY_OBJ_DESTROY(sp, sp->opdata_rsa_pub_key, - ret, uselock, OP_RSA); - sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; - sp->opdata_rsa_pub = NULL; - destroy_all_rsa_params(sp); - } - - return (ret); - } - -/* Destroy RSA private key from single session. */ -int -pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) - { - int ret = 0; - - if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE) - { - TRY_OBJ_DESTROY(sp, sp->opdata_rsa_priv_key, - ret, uselock, OP_RSA); - sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; - sp->opdata_rsa_priv = NULL; - destroy_all_rsa_params(sp); - } - - return (ret); - } - -/* - * Destroy RSA key object wrapper. If session is NULL, try to destroy all - * objects in the free list. - */ -int -pk11_destroy_rsa_key_objects(PK11_SESSION *session) - { - int ret = 1; - PK11_SESSION *sp = NULL; - PK11_SESSION *local_free_session; - CK_BBOOL uselock = CK_TRUE; - - if (session != NULL) - local_free_session = session; - else - { - (void) pthread_mutex_lock(session_cache[OP_RSA].lock); - local_free_session = session_cache[OP_RSA].head; - uselock = CK_FALSE; - } - - /* - * go through the list of sessions and delete key objects - */ - while ((sp = local_free_session) != NULL) - { - local_free_session = sp->next; - - /* - * Do not terminate list traversal if one of the - * destroy operations fails. - */ - if (pk11_destroy_rsa_object_pub(sp, uselock) == 0) - { - ret = 0; - continue; - } - if (pk11_destroy_rsa_object_priv(sp, uselock) == 0) - { - ret = 0; - continue; - } - } - - if (session == NULL) - (void) pthread_mutex_unlock(session_cache[OP_RSA].lock); - - return (ret); - } -#endif /* OPENSSL_NO_RSA */ - -#ifndef OPENSSL_NO_DSA -/* Destroy DSA public key from single session. */ -int -pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) - { - int ret = 0; - - if (sp->opdata_dsa_pub_key != CK_INVALID_HANDLE) - { - TRY_OBJ_DESTROY(sp, sp->opdata_dsa_pub_key, - ret, uselock, OP_DSA); - sp->opdata_dsa_pub_key = CK_INVALID_HANDLE; - sp->opdata_dsa_pub = NULL; - if (sp->opdata_dsa_pub_num != NULL) - { - BN_free(sp->opdata_dsa_pub_num); - sp->opdata_dsa_pub_num = NULL; - } - } - - return (ret); - } - -/* Destroy DSA private key from single session. */ -int -pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) - { - int ret = 0; - - if (sp->opdata_dsa_priv_key != CK_INVALID_HANDLE) - { - TRY_OBJ_DESTROY(sp, sp->opdata_dsa_priv_key, - ret, uselock, OP_DSA); - sp->opdata_dsa_priv_key = CK_INVALID_HANDLE; - sp->opdata_dsa_priv = NULL; - if (sp->opdata_dsa_priv_num != NULL) - { - BN_free(sp->opdata_dsa_priv_num); - sp->opdata_dsa_priv_num = NULL; - } - } - - return (ret); - } - -/* - * Destroy DSA key object wrapper. If session is NULL, try to destroy all - * objects in the free list. - */ -int -pk11_destroy_dsa_key_objects(PK11_SESSION *session) - { - int ret = 1; - PK11_SESSION *sp = NULL; - PK11_SESSION *local_free_session; - CK_BBOOL uselock = CK_TRUE; - - if (session != NULL) - local_free_session = session; - else - { - (void) pthread_mutex_lock(session_cache[OP_DSA].lock); - local_free_session = session_cache[OP_DSA].head; - uselock = CK_FALSE; - } - - /* - * go through the list of sessions and delete key objects - */ - while ((sp = local_free_session) != NULL) - { - local_free_session = sp->next; - - /* - * Do not terminate list traversal if one of the - * destroy operations fails. - */ - if (pk11_destroy_dsa_object_pub(sp, uselock) == 0) - { - ret = 0; - continue; - } - if (pk11_destroy_dsa_object_priv(sp, uselock) == 0) - { - ret = 0; - continue; - } - } - - if (session == NULL) - (void) pthread_mutex_unlock(session_cache[OP_DSA].lock); - - return (ret); - } -#endif /* OPENSSL_NO_DSA */ - -#ifndef OPENSSL_NO_DH -/* Destroy DH key from single session. */ -int -pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock) - { - int ret = 0; - - if (sp->opdata_dh_key != CK_INVALID_HANDLE) - { - TRY_OBJ_DESTROY(sp, sp->opdata_dh_key, - ret, uselock, OP_DH); - sp->opdata_dh_key = CK_INVALID_HANDLE; - sp->opdata_dh = NULL; - if (sp->opdata_dh_priv_num != NULL) - { - BN_free(sp->opdata_dh_priv_num); - sp->opdata_dh_priv_num = NULL; - } - } - - return (ret); - } - -/* - * Destroy DH key object wrapper. - * - * arg0: pointer to PKCS#11 engine session structure - * if session is NULL, try to destroy all objects in the free list - */ -int -pk11_destroy_dh_key_objects(PK11_SESSION *session) - { - int ret = 1; - PK11_SESSION *sp = NULL; - PK11_SESSION *local_free_session; - CK_BBOOL uselock = CK_TRUE; - - if (session != NULL) - local_free_session = session; - else - { - (void) pthread_mutex_lock(session_cache[OP_DH].lock); - local_free_session = session_cache[OP_DH].head; - uselock = CK_FALSE; - } - - while ((sp = local_free_session) != NULL) - { - local_free_session = sp->next; - - /* - * Do not terminate list traversal if one of the - * destroy operations fails. - */ - if (pk11_destroy_dh_object(sp, uselock) == 0) - { - ret = 0; - continue; - } - } -err: - if (session == NULL) - (void) pthread_mutex_unlock(session_cache[OP_DH].lock); - - return (ret); - } -#endif /* OPENSSL_NO_DH */ - -static int -pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh, - CK_BBOOL persistent) - { - CK_RV rv; - - /* - * We never try to destroy persistent objects which are the objects - * stored in the keystore. Also, we always use read-only sessions so - * C_DestroyObject() would be returning CKR_SESSION_READ_ONLY here. - */ - if (persistent == CK_TRUE) - return (1); - - rv = pFuncList->C_DestroyObject(session, oh); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT, - rv); - return (0); - } - - return (1); - } - - -/* Symmetric ciphers and digests support functions */ - -static int -cipher_nid_to_pk11(int nid) - { - int i; - - for (i = 0; i < PK11_CIPHER_MAX; i++) - if (ciphers[i].nid == nid) - return (ciphers[i].id); - return (-1); - } - -static int -pk11_usable_ciphers(const int **nids) - { - if (cipher_count > 0) - *nids = cipher_nids; - else - *nids = NULL; - return (cipher_count); - } - -static int -pk11_usable_digests(const int **nids) - { - if (digest_count > 0) - *nids = digest_nids; - else - *nids = NULL; - return (digest_count); - } - -/* - * Init context for encryption or decryption using a symmetric key. - */ -static int pk11_init_symmetric(EVP_CIPHER_CTX *ctx, PK11_CIPHER *pcipher, - PK11_SESSION *sp, CK_MECHANISM_PTR pmech) - { - CK_RV rv; - CK_AES_CTR_PARAMS ctr_params; - - /* - * We expect pmech->mechanism to be already set and - * pParameter/ulParameterLen initialized to NULL/0 before - * pk11_init_symmetric() is called. - */ - OPENSSL_assert(pmech->mechanism != NULL); - OPENSSL_assert(pmech->pParameter == NULL); - OPENSSL_assert(pmech->ulParameterLen == 0); - - if (ctx->cipher->nid == NID_aes_128_ctr || - ctx->cipher->nid == NID_aes_192_ctr || - ctx->cipher->nid == NID_aes_256_ctr) - { - pmech->pParameter = (void *)(&ctr_params); - pmech->ulParameterLen = sizeof (ctr_params); - /* - * For now, we are limited to the fixed length of the counter, - * it covers the whole counter block. That's what RFC 4344 - * needs. For more information on internal structure of the - * counter block, see RFC 3686. If needed in the future, we can - * add code so that the counter length can be set via - * ENGINE_ctrl() function. - */ - ctr_params.ulCounterBits = AES_BLOCK_SIZE * 8; - OPENSSL_assert(pcipher->iv_len == AES_BLOCK_SIZE); - (void) memcpy(ctr_params.cb, ctx->iv, AES_BLOCK_SIZE); - } - else - { - if (pcipher->iv_len > 0) - { - pmech->pParameter = (void *)ctx->iv; - pmech->ulParameterLen = pcipher->iv_len; - } - } - - /* if we get here, the encryption needs to be reinitialized */ - if (ctx->encrypt) - rv = pFuncList->C_EncryptInit(sp->session, pmech, - sp->opdata_cipher_key); - else - rv = pFuncList->C_DecryptInit(sp->session, pmech, - sp->opdata_cipher_key); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_CIPHER_INIT, ctx->encrypt ? - PK11_R_ENCRYPTINIT : PK11_R_DECRYPTINIT, rv); - pk11_return_session(sp, OP_CIPHER); - return (0); - } - - return (1); - } - -/* ARGSUSED */ -static int -pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, - const unsigned char *iv, int enc) - { - CK_MECHANISM mech; - int index; - PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; - PK11_SESSION *sp; - PK11_CIPHER *p_ciph_table_row; - - state->sp = NULL; - - index = cipher_nid_to_pk11(ctx->cipher->nid); - if (index < 0 || index >= PK11_CIPHER_MAX) - return (0); - - p_ciph_table_row = &ciphers[index]; - /* - * iv_len in the ctx->cipher structure is the maximum IV length for the - * current cipher and it must be less or equal to the IV length in our - * ciphers table. The key length must be in the allowed interval. From - * all cipher modes that the PKCS#11 engine supports only RC4 allows a - * key length to be in some range, all other NIDs have a precise key - * length. Every application can define its own EVP functions so this - * code serves as a sanity check. - * - * Note that the reason why the IV length in ctx->cipher might be - * greater than the actual length is that OpenSSL uses BLOCK_CIPHER_defs - * macro to define functions that return EVP structures for all DES - * modes. So, even ECB modes get 8 byte IV. - */ - if (ctx->cipher->iv_len < p_ciph_table_row->iv_len || - ctx->key_len < p_ciph_table_row->min_key_len || - ctx->key_len > p_ciph_table_row->max_key_len) - { - PK11err(PK11_F_CIPHER_INIT, PK11_R_KEY_OR_IV_LEN_PROBLEM); - return (0); - } - - if ((sp = pk11_get_session(OP_CIPHER)) == NULL) - return (0); - - /* if applicable, the mechanism parameter is used for IV */ - mech.mechanism = p_ciph_table_row->mech_type; - mech.pParameter = NULL; - mech.ulParameterLen = 0; - - /* The key object is destroyed here if it is not the current key. */ - (void) check_new_cipher_key(sp, key, ctx->key_len); - - /* - * If the key is the same and the encryption is also the same, then - * just reuse it. However, we must not forget to reinitialize the - * context that was finalized in pk11_cipher_cleanup(). - */ - if (sp->opdata_cipher_key != CK_INVALID_HANDLE && - sp->opdata_encrypt == ctx->encrypt) - { - state->sp = sp; - if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0) - return (0); - - return (1); - } - - /* - * Check if the key has been invalidated. If so, a new key object - * needs to be created. - */ - if (sp->opdata_cipher_key == CK_INVALID_HANDLE) - { - sp->opdata_cipher_key = pk11_get_cipher_key( - ctx, key, p_ciph_table_row->key_type, sp); - } - - if (sp->opdata_encrypt != ctx->encrypt && sp->opdata_encrypt != -1) - { - /* - * The previous encryption/decryption is different. Need to - * terminate the previous * active encryption/decryption here. - */ - if (!pk11_cipher_final(sp)) - { - pk11_return_session(sp, OP_CIPHER); - return (0); - } - } - - if (sp->opdata_cipher_key == CK_INVALID_HANDLE) - { - pk11_return_session(sp, OP_CIPHER); - return (0); - } - - /* now initialize the context with a new key */ - if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0) - return (0); - - sp->opdata_encrypt = ctx->encrypt; - state->sp = sp; - - return (1); - } - -/* - * When reusing the same key in an encryption/decryption session for a - * decryption/encryption session, we need to close the active session - * and recreate a new one. Note that the key is in the global session so - * that it needs not be recreated. - * - * It is more appropriate to use C_En/DecryptFinish here. At the time of this - * development, these two functions in the PKCS#11 libraries used return - * unexpected errors when passing in 0 length output. It may be a good - * idea to try them again if performance is a problem here and fix - * C_En/DecryptFinial if there are bugs there causing the problem. - */ -static int -pk11_cipher_final(PK11_SESSION *sp) - { - CK_RV rv; - - rv = pFuncList->C_CloseSession(sp->session); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_CLOSESESSION, rv); - return (0); - } - - rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, - NULL_PTR, NULL_PTR, &sp->session); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_OPENSESSION, rv); - return (0); - } - - return (1); - } - -/* - * An engine interface function. The calling function allocates sufficient - * memory for the output buffer "out" to hold the results. - */ -static int -pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, - const unsigned char *in, unsigned int inl) - { - PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; - PK11_SESSION *sp; - CK_RV rv; - unsigned long outl = inl; - - if (state == NULL || state->sp == NULL) - return (0); - - sp = (PK11_SESSION *) state->sp; - - if (!inl) - return (1); - - /* RC4 is the only stream cipher we support */ - if (ctx->cipher->nid != NID_rc4 && (inl % ctx->cipher->block_size) != 0) - return (0); - - if (ctx->encrypt) - { - rv = pFuncList->C_EncryptUpdate(sp->session, - (unsigned char *)in, inl, out, &outl); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_CIPHER_DO_CIPHER, - PK11_R_ENCRYPTUPDATE, rv); - return (0); - } - } - else - { - rv = pFuncList->C_DecryptUpdate(sp->session, - (unsigned char *)in, inl, out, &outl); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_CIPHER_DO_CIPHER, - PK11_R_DECRYPTUPDATE, rv); - return (0); - } - } - - /* - * For DES_CBC, DES3_CBC, AES_CBC, and RC4, the output size is always - * the same size of input. - * The application has guaranteed to call the block ciphers with - * correctly aligned buffers. - */ - if (inl != outl) - return (0); - - return (1); - } - -/* - * Return the session to the pool. Calling C_EncryptFinal() and C_DecryptFinal() - * here is the right thing because in EVP_DecryptFinal_ex(), engine's - * do_cipher() is not even called, and in EVP_EncryptFinal_ex() it is called but - * the engine can't find out that it's the finalizing call. We wouldn't - * necessarily have to finalize the context here since reinitializing it with - * C_(Encrypt|Decrypt)Init() should be fine but for the sake of correctness, - * let's do it. Some implementations might leak memory if the previously used - * context is initialized without finalizing it first. - */ -static int -pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx) - { - CK_RV rv; - CK_ULONG len = EVP_MAX_BLOCK_LENGTH; - CK_BYTE buf[EVP_MAX_BLOCK_LENGTH]; - PK11_CIPHER_STATE *state = ctx->cipher_data; - - if (state != NULL && state->sp != NULL) - { - /* - * We are not interested in the data here, we just need to get - * rid of the context. - */ - if (ctx->encrypt) - rv = pFuncList->C_EncryptFinal( - state->sp->session, buf, &len); - else - rv = pFuncList->C_DecryptFinal( - state->sp->session, buf, &len); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_CIPHER_CLEANUP, ctx->encrypt ? - PK11_R_ENCRYPTFINAL : PK11_R_DECRYPTFINAL, rv); - pk11_return_session(state->sp, OP_CIPHER); - return (0); - } - - pk11_return_session(state->sp, OP_CIPHER); - state->sp = NULL; - } - - return (1); - } - -/* - * Registered by the ENGINE when used to find out how to deal with - * a particular NID in the ENGINE. This says what we'll do at the - * top level - note, that list is restricted by what we answer with - */ -/* ARGSUSED */ -static int -pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, - const int **nids, int nid) - { - if (!cipher) - return (pk11_usable_ciphers(nids)); - - switch (nid) - { - case NID_des_ede3_cbc: - *cipher = &pk11_3des_cbc; - break; - case NID_des_cbc: - *cipher = &pk11_des_cbc; - break; - case NID_des_ede3_ecb: - *cipher = &pk11_3des_ecb; - break; - case NID_des_ecb: - *cipher = &pk11_des_ecb; - break; - case NID_aes_128_cbc: - *cipher = &pk11_aes_128_cbc; - break; - case NID_aes_192_cbc: - *cipher = &pk11_aes_192_cbc; - break; - case NID_aes_256_cbc: - *cipher = &pk11_aes_256_cbc; - break; - case NID_aes_128_ecb: - *cipher = &pk11_aes_128_ecb; - break; - case NID_aes_192_ecb: - *cipher = &pk11_aes_192_ecb; - break; - case NID_aes_256_ecb: - *cipher = &pk11_aes_256_ecb; - break; - case NID_aes_128_ctr: - *cipher = &pk11_aes_128_ctr; - break; - case NID_aes_192_ctr: - *cipher = &pk11_aes_192_ctr; - break; - case NID_aes_256_ctr: - *cipher = &pk11_aes_256_ctr; - break; - case NID_bf_cbc: - *cipher = &pk11_bf_cbc; - break; - case NID_rc4: - *cipher = &pk11_rc4; - break; - default: - *cipher = NULL; - break; - } - return (*cipher != NULL); - } - -/* ARGSUSED */ -static int -pk11_engine_digests(ENGINE *e, const EVP_MD **digest, - const int **nids, int nid) - { - if (!digest) - return (pk11_usable_digests(nids)); - - switch (nid) - { - case NID_md5: - *digest = &pk11_md5; - break; - case NID_sha1: - *digest = &pk11_sha1; - break; - case NID_sha224: - *digest = &pk11_sha224; - break; - case NID_sha256: - *digest = &pk11_sha256; - break; - case NID_sha384: - *digest = &pk11_sha384; - break; - case NID_sha512: - *digest = &pk11_sha512; - break; - default: - *digest = NULL; - break; - } - return (*digest != NULL); - } - - -/* Create a secret key object in a PKCS#11 session */ -static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, - const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp) - { - CK_RV rv; - CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; - CK_OBJECT_CLASS obj_key = CKO_SECRET_KEY; - CK_ULONG ul_key_attr_count = 6; - - CK_ATTRIBUTE a_key_template[] = - { - {CKA_CLASS, (void*) NULL, sizeof (CK_OBJECT_CLASS)}, - {CKA_KEY_TYPE, (void*) NULL, sizeof (CK_KEY_TYPE)}, - {CKA_TOKEN, &pk11_false, sizeof (pk11_false)}, - {CKA_ENCRYPT, &pk11_true, sizeof (pk11_true)}, - {CKA_DECRYPT, &pk11_true, sizeof (pk11_true)}, - {CKA_VALUE, (void*) NULL, 0}, - }; - - /* - * Create secret key object in global_session. All other sessions - * can use the key handles. Here is why: - * OpenSSL will call EncryptInit and EncryptUpdate using a secret key. - * It may then call DecryptInit and DecryptUpdate using the same key. - * To use the same key object, we need to call EncryptFinal with - * a 0 length message. Currently, this does not work for 3DES - * mechanism. To get around this problem, we close the session and - * then create a new session to use the same key object. When a session - * is closed, all the object handles will be invalid. Thus, create key - * objects in a global session, an individual session may be closed to - * terminate the active operation. - */ - CK_SESSION_HANDLE session = global_session; - a_key_template[0].pValue = &obj_key; - a_key_template[1].pValue = &key_type; - a_key_template[5].pValue = (void *) key; - a_key_template[5].ulValueLen = (unsigned long) ctx->key_len; - - rv = pFuncList->C_CreateObject(session, - a_key_template, ul_key_attr_count, &h_key); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_CIPHER_KEY, PK11_R_CREATEOBJECT, - rv); - goto err; - } - - /* - * Save the key information used in this session. - * The max can be saved is PK11_KEY_LEN_MAX. - */ - sp->opdata_key_len = ctx->key_len > PK11_KEY_LEN_MAX ? - PK11_KEY_LEN_MAX : ctx->key_len; - (void) memcpy(sp->opdata_key, key, sp->opdata_key_len); -err: - - return (h_key); - } - -static int -md_nid_to_pk11(int nid) - { - int i; - - for (i = 0; i < PK11_DIGEST_MAX; i++) - if (digests[i].nid == nid) - return (digests[i].id); - return (-1); - } - -static int -pk11_digest_init(EVP_MD_CTX *ctx) - { - CK_RV rv; - CK_MECHANISM mech; - int index; - PK11_SESSION *sp; - PK11_DIGEST *pdp; - PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; - - state->sp = NULL; - - index = md_nid_to_pk11(ctx->digest->type); - if (index < 0 || index >= PK11_DIGEST_MAX) - return (0); - - pdp = &digests[index]; - if ((sp = pk11_get_session(OP_DIGEST)) == NULL) - return (0); - - /* at present, no parameter is needed for supported digests */ - mech.mechanism = pdp->mech_type; - mech.pParameter = NULL; - mech.ulParameterLen = 0; - - rv = pFuncList->C_DigestInit(sp->session, &mech); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DIGEST_INIT, PK11_R_DIGESTINIT, rv); - pk11_return_session(sp, OP_DIGEST); - return (0); - } - - state->sp = sp; - - return (1); - } - -static int -pk11_digest_update(EVP_MD_CTX *ctx, const void *data, size_t count) - { - CK_RV rv; - PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; - - /* 0 length message will cause a failure in C_DigestFinal */ - if (count == 0) - return (1); - - if (state == NULL || state->sp == NULL) - return (0); - - rv = pFuncList->C_DigestUpdate(state->sp->session, (CK_BYTE *) data, - count); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DIGEST_UPDATE, PK11_R_DIGESTUPDATE, rv); - pk11_return_session(state->sp, OP_DIGEST); - state->sp = NULL; - return (0); - } - - return (1); - } - -static int -pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md) - { - CK_RV rv; - unsigned long len; - PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; - len = ctx->digest->md_size; - - if (state == NULL || state->sp == NULL) - return (0); - - rv = pFuncList->C_DigestFinal(state->sp->session, md, &len); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DIGEST_FINAL, PK11_R_DIGESTFINAL, rv); - pk11_return_session(state->sp, OP_DIGEST); - state->sp = NULL; - return (0); - } - - if (ctx->digest->md_size != len) - return (0); - - /* - * Final is called and digest is returned, so return the session - * to the pool - */ - pk11_return_session(state->sp, OP_DIGEST); - state->sp = NULL; - - return (1); - } - -static int -pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) - { - CK_RV rv; - int ret = 0; - PK11_CIPHER_STATE *state, *state_to; - CK_BYTE_PTR pstate = NULL; - CK_ULONG ul_state_len; - - /* The copy-from state */ - state = (PK11_CIPHER_STATE *) from->md_data; - if (state == NULL || state->sp == NULL) - goto err; - - /* Initialize the copy-to state */ - if (!pk11_digest_init(to)) - goto err; - state_to = (PK11_CIPHER_STATE *) to->md_data; - - /* Get the size of the operation state of the copy-from session */ - rv = pFuncList->C_GetOperationState(state->sp->session, NULL, - &ul_state_len); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE, - rv); - goto err; - } - if (ul_state_len == 0) - { - goto err; - } - - pstate = OPENSSL_malloc(ul_state_len); - if (pstate == NULL) - { - PK11err(PK11_F_DIGEST_COPY, PK11_R_MALLOC_FAILURE); - goto err; - } - - /* Get the operation state of the copy-from session */ - rv = pFuncList->C_GetOperationState(state->sp->session, pstate, - &ul_state_len); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE, - rv); - goto err; - } - - /* Set the operation state of the copy-to session */ - rv = pFuncList->C_SetOperationState(state_to->sp->session, pstate, - ul_state_len, 0, 0); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DIGEST_COPY, - PK11_R_SET_OPERATION_STATE, rv); - goto err; - } - - ret = 1; -err: - if (pstate != NULL) - OPENSSL_free(pstate); - - return (ret); - } - -/* Return any pending session state to the pool */ -static int -pk11_digest_cleanup(EVP_MD_CTX *ctx) - { - PK11_CIPHER_STATE *state = ctx->md_data; - unsigned char buf[EVP_MAX_MD_SIZE]; - - if (state != NULL && state->sp != NULL) - { - /* - * If state->sp is not NULL then pk11_digest_final() has not - * been called yet. We must call it now to free any memory - * that might have been allocated in the token when - * pk11_digest_init() was called. pk11_digest_final() - * will return the session to the cache. - */ - if (!pk11_digest_final(ctx, buf)) - return (0); - } - - return (1); - } - -/* - * Check if the new key is the same as the key object in the session. If the key - * is the same, no need to create a new key object. Otherwise, the old key - * object needs to be destroyed and a new one will be created. Return 1 for - * cache hit, 0 for cache miss. Note that we must check the key length first - * otherwise we could end up reusing a different, longer key with the same - * prefix. - */ -static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key, - int key_len) - { - if (sp->opdata_key_len != key_len || - memcmp(sp->opdata_key, key, key_len) != 0) - { - (void) pk11_destroy_cipher_key_objects(sp); - return (0); - } - return (1); - } - -/* Destroy one or more secret key objects. */ -static int pk11_destroy_cipher_key_objects(PK11_SESSION *session) - { - int ret = 0; - PK11_SESSION *sp = NULL; - PK11_SESSION *local_free_session; - - if (session != NULL) - local_free_session = session; - else - { - (void) pthread_mutex_lock(session_cache[OP_CIPHER].lock); - local_free_session = session_cache[OP_CIPHER].head; - } - - while ((sp = local_free_session) != NULL) - { - local_free_session = sp->next; - - if (sp->opdata_cipher_key != CK_INVALID_HANDLE) - { - /* - * The secret key object is created in the - * global_session. See pk11_get_cipher_key(). - */ - if (pk11_destroy_object(global_session, - sp->opdata_cipher_key, CK_FALSE) == 0) - goto err; - sp->opdata_cipher_key = CK_INVALID_HANDLE; - } - } - ret = 1; -err: - - if (session == NULL) - (void) pthread_mutex_unlock(session_cache[OP_CIPHER].lock); - - return (ret); - } - - -/* - * Public key mechanisms optionally supported - * - * CKM_RSA_X_509 - * CKM_RSA_PKCS - * CKM_DSA - * - * The first slot that supports at least one of those mechanisms is chosen as a - * public key slot. - * - * Symmetric ciphers optionally supported - * - * CKM_DES3_CBC - * CKM_DES_CBC - * CKM_AES_CBC - * CKM_DES3_ECB - * CKM_DES_ECB - * CKM_AES_ECB - * CKM_AES_CTR - * CKM_RC4 - * CKM_BLOWFISH_CBC - * - * Digests optionally supported - * - * CKM_MD5 - * CKM_SHA_1 - * CKM_SHA224 - * CKM_SHA256 - * CKM_SHA384 - * CKM_SHA512 - * - * The output of this function is a set of global variables indicating which - * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of - * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global - * variables carry information about which slot was chosen for (a) public key - * mechanisms, (b) random operations, and (c) symmetric ciphers and digests. - */ -static int -pk11_choose_slots(int *any_slot_found) - { - CK_SLOT_ID_PTR pSlotList = NULL_PTR; - CK_ULONG ulSlotCount = 0; - CK_MECHANISM_INFO mech_info; - CK_TOKEN_INFO token_info; - int i; - CK_RV rv; - CK_SLOT_ID best_pubkey_slot_sofar; -#ifdef DEBUG_SLOT_SELECTION - CK_SLOT_ID best_cd_slot_sofar; -#endif - int slot_n_cipher = -1; - int slot_n_digest = -1; - CK_SLOT_ID current_slot = 0; - int current_slot_n_cipher = 0; - int current_slot_n_digest = 0; - int best_number_of_mechs = 0; - int current_number_of_mechs = 0; - int local_cipher_nids[PK11_CIPHER_MAX]; - int local_digest_nids[PK11_DIGEST_MAX]; - - /* let's initialize the output parameter */ - if (any_slot_found != NULL) - *any_slot_found = 0; - - /* Get slot list for memory allocation */ - rv = pFuncList->C_GetSlotList(CK_FALSE, NULL_PTR, &ulSlotCount); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); - return (0); - } - - /* it's not an error if we didn't find any providers */ - if (ulSlotCount == 0) - { - DEBUG_SLOT_SEL("%s: no crypto providers found\n", PK11_DBG); - return (1); - } - - pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); - - if (pSlotList == NULL) - { - PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE); - return (0); - } - - /* Get the slot list for processing */ - rv = pFuncList->C_GetSlotList(CK_FALSE, pSlotList, &ulSlotCount); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); - OPENSSL_free(pSlotList); - return (0); - } - - DEBUG_SLOT_SEL("%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME); - DEBUG_SLOT_SEL("%s: number of slots: %d\n", PK11_DBG, ulSlotCount); - - pubkey_SLOTID = pSlotList[0]; - for (i = 0; i < ulSlotCount; i++) - { - CK_BBOOL slot_has_rsa = CK_FALSE; - CK_BBOOL slot_has_dsa = CK_FALSE; - CK_BBOOL slot_has_dh = CK_FALSE; - current_slot = pSlotList[i]; - - DEBUG_SLOT_SEL("%s: == checking slot: %d ==\n", PK11_DBG, - current_slot); - rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); - if (rv != CKR_OK) - continue; - - DEBUG_SLOT_SEL("%s: token label: %.32s\n", PK11_DBG, - token_info.label); - - DEBUG_SLOT_SEL("%s: checking rand slots\n", PK11_DBG); - - if (((token_info.flags & CKF_RNG) != 0) && !pk11_have_random) - { - DEBUG_SLOT_SEL( - "%s: this token has CKF_RNG flag\n", PK11_DBG); - pk11_have_random = CK_TRUE; - rand_SLOTID = current_slot; - } - - DEBUG_SLOT_SEL("%s: checking pubkey slots\n", PK11_DBG); - current_number_of_mechs = 0; - -#ifndef OPENSSL_NO_RSA - /* - * Check if this slot is capable of signing and - * verifying with CKM_RSA_PKCS. - */ - rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS, - &mech_info); - - if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && - (mech_info.flags & CKF_VERIFY))) - { - /* - * Check if this slot is capable of encryption, - * decryption, sign, and verify with CKM_RSA_X_509. - */ - rv = pFuncList->C_GetMechanismInfo(current_slot, - CKM_RSA_X_509, &mech_info); - - if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && - (mech_info.flags & CKF_VERIFY) && - (mech_info.flags & CKF_ENCRYPT) && - (mech_info.flags & CKF_VERIFY_RECOVER) && - (mech_info.flags & CKF_DECRYPT))) - { - slot_has_rsa = CK_TRUE; - current_number_of_mechs++; - } - } -#endif /* OPENSSL_NO_RSA */ - -#ifndef OPENSSL_NO_DSA - /* - * Check if this slot is capable of signing and - * verifying with CKM_DSA. - */ - rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA, - &mech_info); - if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && - (mech_info.flags & CKF_VERIFY))) - { - slot_has_dsa = CK_TRUE; - current_number_of_mechs++; - } - -#endif /* OPENSSL_NO_DSA */ - -#ifndef OPENSSL_NO_DH - /* - * Check if this slot is capable of DH key generataion and - * derivation. - */ - rv = pFuncList->C_GetMechanismInfo(current_slot, - CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info); - - if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR)) - { - rv = pFuncList->C_GetMechanismInfo(current_slot, - CKM_DH_PKCS_DERIVE, &mech_info); - if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE)) - { - slot_has_dh = CK_TRUE; - current_number_of_mechs++; - } - } -#endif /* OPENSSL_NO_DH */ - - if (current_number_of_mechs > best_number_of_mechs) - { - best_pubkey_slot_sofar = current_slot; - pk11_have_rsa = slot_has_rsa; - pk11_have_dsa = slot_has_dsa; - pk11_have_dh = slot_has_dh; - best_number_of_mechs = current_number_of_mechs; - /* - * Cache the flags for later use. We might need those if - * RSA keys by reference feature is used. - */ - pubkey_token_flags = token_info.flags; - DEBUG_SLOT_SEL("%s: pubkey flags changed to " - "%lu.\n", PK11_DBG, pubkey_token_flags); - } - - DEBUG_SLOT_SEL("%s: checking cipher/digest\n", PK11_DBG); - - current_slot_n_cipher = 0; - current_slot_n_digest = 0; - (void) memset(local_cipher_nids, 0, sizeof (local_cipher_nids)); - (void) memset(local_digest_nids, 0, sizeof (local_digest_nids)); - - pk11_find_symmetric_ciphers(pFuncList, current_slot, - ¤t_slot_n_cipher, local_cipher_nids); - - pk11_find_digests(pFuncList, current_slot, - ¤t_slot_n_digest, local_digest_nids); - - DEBUG_SLOT_SEL("%s: current_slot_n_cipher %d\n", PK11_DBG, - current_slot_n_cipher); - DEBUG_SLOT_SEL("%s: current_slot_n_digest %d\n", PK11_DBG, - current_slot_n_digest); - - /* - * If the current slot supports more ciphers/digests than - * the previous best one we change the current best to this one, - * otherwise leave it where it is. - */ - if ((current_slot_n_cipher + current_slot_n_digest) > - (slot_n_cipher + slot_n_digest)) - { - DEBUG_SLOT_SEL("%s: changing best slot to %d\n", - PK11_DBG, current_slot); - SLOTID = current_slot; -#ifdef DEBUG_SLOT_SELECTION - best_cd_slot_sofar = current_slot; -#endif - cipher_count = slot_n_cipher = current_slot_n_cipher; - digest_count = slot_n_digest = current_slot_n_digest; - (void) memcpy(cipher_nids, local_cipher_nids, - sizeof (local_cipher_nids)); - (void) memcpy(digest_nids, local_digest_nids, - sizeof (local_digest_nids)); - } - - DEBUG_SLOT_SEL("%s: best cipher/digest slot so far: %d\n", - PK11_DBG, best_cd_slot_sofar); - } - - if (best_number_of_mechs == 0) - { - DEBUG_SLOT_SEL("%s: no rsa/dsa/dh\n", PK11_DBG); - } - else - { - pubkey_SLOTID = best_pubkey_slot_sofar; - } - - DEBUG_SLOT_SEL("%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID); - DEBUG_SLOT_SEL("%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID); - DEBUG_SLOT_SEL("%s: chosen cipher/digest slot: %d\n", PK11_DBG, SLOTID); - DEBUG_SLOT_SEL("%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa); - DEBUG_SLOT_SEL("%s: pk11_have_dsa %d\n", PK11_DBG, pk11_have_dsa); - DEBUG_SLOT_SEL("%s: pk11_have_dh %d\n", PK11_DBG, pk11_have_dh); - DEBUG_SLOT_SEL("%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random); - DEBUG_SLOT_SEL("%s: cipher_count %d\n", PK11_DBG, cipher_count); - DEBUG_SLOT_SEL("%s: digest_count %d\n", PK11_DBG, digest_count); - - if (pSlotList != NULL) - OPENSSL_free(pSlotList); - -#ifdef SOLARIS_HW_SLOT_SELECTION - OPENSSL_free(hw_cnids); - OPENSSL_free(hw_dnids); -#endif /* SOLARIS_HW_SLOT_SELECTION */ - - if (any_slot_found != NULL) - *any_slot_found = 1; - return (1); - } - -static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR pflist, - int slot_id, int *current_slot_n_cipher, int *local_cipher_nids, - PK11_CIPHER *cipher) - { - static CK_MECHANISM_INFO mech_info; - static CK_RV rv; - static CK_MECHANISM_TYPE last_checked_mech = (CK_MECHANISM_TYPE)-1; - - DEBUG_SLOT_SEL("%s: checking mech: %x", PK11_DBG, cipher->mech_type); - if (cipher->mech_type != last_checked_mech) - { - rv = pflist->C_GetMechanismInfo(slot_id, cipher->mech_type, - &mech_info); - } - - last_checked_mech = cipher->mech_type; - - if (rv != CKR_OK) - { - DEBUG_SLOT_SEL(" not found\n"); - return; - } - - if ((mech_info.flags & CKF_ENCRYPT) && - (mech_info.flags & CKF_DECRYPT)) - { - if (mech_info.ulMinKeySize > cipher->min_key_len || - mech_info.ulMaxKeySize < cipher->max_key_len) - { - DEBUG_SLOT_SEL(" engine key size range <%i-%i> does not" - " match mech range <%lu-%lu>\n", - cipher->min_key_len, cipher->max_key_len, - mech_info.ulMinKeySize, mech_info.ulMaxKeySize); - return; - } -#ifdef SOLARIS_HW_SLOT_SELECTION - if (nid_in_table(cipher->nid, hw_cnids)) -#endif /* SOLARIS_HW_SLOT_SELECTION */ - { - DEBUG_SLOT_SEL(" usable\n"); - local_cipher_nids[(*current_slot_n_cipher)++] = - cipher->nid; - } -#ifdef SOLARIS_HW_SLOT_SELECTION - else - { - DEBUG_SLOT_SEL( - " rejected, software implementation only\n"); - } -#endif /* SOLARIS_HW_SLOT_SELECTION */ - } - else - { - DEBUG_SLOT_SEL(" unusable\n"); - } - - return; - } - -static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id, - int *current_slot_n_digest, int *local_digest_nids, PK11_DIGEST *digest) - { - CK_MECHANISM_INFO mech_info; - CK_RV rv; - - DEBUG_SLOT_SEL("%s: checking mech: %x", PK11_DBG, digest->mech_type); - rv = pflist->C_GetMechanismInfo(slot_id, digest->mech_type, &mech_info); - - if (rv != CKR_OK) - { - DEBUG_SLOT_SEL(" not found\n"); - return; - } - - if (mech_info.flags & CKF_DIGEST) - { -#ifdef SOLARIS_HW_SLOT_SELECTION - if (nid_in_table(digest->nid, hw_dnids)) -#endif /* SOLARIS_HW_SLOT_SELECTION */ - { - DEBUG_SLOT_SEL(" usable\n"); - local_digest_nids[(*current_slot_n_digest)++] = - digest->nid; - } -#ifdef SOLARIS_HW_SLOT_SELECTION - else - { - DEBUG_SLOT_SEL( - " rejected, software implementation only\n"); - } -#endif /* SOLARIS_HW_SLOT_SELECTION */ - } - else - { - DEBUG_SLOT_SEL(" unusable\n"); - } - - return; - } - -/* Find what symmetric ciphers this slot supports. */ -static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist, - CK_SLOT_ID current_slot, int *current_slot_n_cipher, int *local_cipher_nids) - { - int i; - - for (i = 0; i < PK11_CIPHER_MAX; ++i) - { - pk11_get_symmetric_cipher(pflist, current_slot, - current_slot_n_cipher, local_cipher_nids, &ciphers[i]); - } - } - -/* Find what digest algorithms this slot supports. */ -static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist, - CK_SLOT_ID current_slot, int *current_slot_n_digest, int *local_digest_nids) - { - int i; - - for (i = 0; i < PK11_DIGEST_MAX; ++i) - { - pk11_get_digest(pflist, current_slot, current_slot_n_digest, - local_digest_nids, &digests[i]); - } - } - -#ifdef SOLARIS_HW_SLOT_SELECTION -/* - * It would be great if we could use pkcs11_kernel directly since this library - * offers hardware slots only. That's the easiest way to achieve the situation - * where we use the hardware accelerators when present and OpenSSL native code - * otherwise. That presumes the fact that OpenSSL native code is faster than the - * code in the soft token. It's a logical assumption - Crypto Framework has some - * inherent overhead so going there for the software implementation of a - * mechanism should be logically slower in contrast to the OpenSSL native code, - * presuming that both implementations are of similar speed. For example, the - * soft token for AES is roughly three times slower than OpenSSL for 64 byte - * blocks and still 20% slower for 8KB blocks. So, if we want to ship products - * that use the PKCS#11 engine by default, we must somehow avoid that regression - * on machines without hardware acceleration. That's why switching to the - * pkcs11_kernel library seems like a very good idea. - * - * The problem is that OpenSSL built with SunStudio is roughly 2x slower for - * asymmetric operations (RSA/DSA/DH) than the soft token built with the same - * compiler. That means that if we switched to pkcs11_kernel from the libpkcs11 - * library, we would have had a performance regression on machines without - * hardware acceleration for asymmetric operations for all applications that use - * the PKCS#11 engine. There is one such application - Apache web server since - * it's shipped configured to use the PKCS#11 engine by default. Having said - * that, we can't switch to the pkcs11_kernel library now and have to come with - * a solution that, on non-accelerated machines, uses the OpenSSL native code - * for all symmetric ciphers and digests while it uses the soft token for - * asymmetric operations. - * - * This is the idea: dlopen() pkcs11_kernel directly and find out what - * mechanisms are there. We don't care about duplications (more slots can - * support the same mechanism), we just want to know what mechanisms can be - * possibly supported in hardware on that particular machine. As said before, - * pkcs11_kernel will show you hardware providers only. - * - * Then, we rely on the fact that since we use libpkcs11 library we will find - * the metaslot. When we go through the metaslot's mechanisms for symmetric - * ciphers and digests, we check that any found mechanism is in the table - * created using the pkcs11_kernel library. So, as a result we have two arrays - * of mechanisms that were advertised as supported in hardware which was the - * goal of that whole exercise. Thus, we can use libpkcs11 but avoid soft token - * code for symmetric ciphers and digests. See pk11_choose_slots() for more - * information. - * - * This is Solaris specific code, if SOLARIS_HW_SLOT_SELECTION is not defined - * the code won't be used. - */ -#if defined(__sparcv9) || defined(__x86_64) || defined(__amd64) -static const char pkcs11_kernel[] = "/usr/lib/security/64/pkcs11_kernel.so.1"; -#else -static const char pkcs11_kernel[] = "/usr/lib/security/pkcs11_kernel.so.1"; -#endif - -/* - * Check hardware capabilities of the machines. The output are two lists, - * hw_cnids and hw_dnids, that contain hardware mechanisms found in all hardware - * providers together. They are not sorted and may contain duplicate mechanisms. - */ -static int check_hw_mechanisms(void) - { - int i; - CK_RV rv; - void *handle; - CK_C_GetFunctionList p; - CK_TOKEN_INFO token_info; - CK_ULONG ulSlotCount = 0; - int n_cipher = 0, n_digest = 0; - CK_FUNCTION_LIST_PTR pflist = NULL; - CK_SLOT_ID_PTR pSlotList = NULL_PTR; - int *tmp_hw_cnids = NULL, *tmp_hw_dnids = NULL; - int hw_ctable_size, hw_dtable_size; - - DEBUG_SLOT_SEL("%s: SOLARIS_HW_SLOT_SELECTION code running\n", - PK11_DBG); - /* - * Use RTLD_GROUP to limit the pkcs11_kernel provider to its own - * symbols, which prevents it from mistakenly accessing C_* functions - * from the top-level PKCS#11 library. - */ - if ((handle = dlopen(pkcs11_kernel, RTLD_LAZY | RTLD_GROUP)) == NULL) - { - PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); - goto err; - } - - if ((p = (CK_C_GetFunctionList)dlsym(handle, - PK11_GET_FUNCTION_LIST)) == NULL) - { - PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); - goto err; - } - - /* get the full function list from the loaded library */ - if (p(&pflist) != CKR_OK) - { - PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); - goto err; - } - - rv = pflist->C_Initialize(NULL_PTR); - if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) - { - PK11err_add_data(PK11_F_CHECK_HW_MECHANISMS, - PK11_R_INITIALIZE, rv); - goto err; - } - - if (pflist->C_GetSlotList(0, NULL_PTR, &ulSlotCount) != CKR_OK) - { - PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); - goto err; - } - - /* no slots, set the hw mechanism tables as empty */ - if (ulSlotCount == 0) - { - DEBUG_SLOT_SEL("%s: no hardware mechanisms found\n", PK11_DBG); - hw_cnids = OPENSSL_malloc(sizeof (int)); - hw_dnids = OPENSSL_malloc(sizeof (int)); - if (hw_cnids == NULL || hw_dnids == NULL) - { - PK11err(PK11_F_CHECK_HW_MECHANISMS, - PK11_R_MALLOC_FAILURE); - return (0); - } - /* this means empty tables */ - hw_cnids[0] = NID_undef; - hw_dnids[0] = NID_undef; - return (1); - } - - pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); - if (pSlotList == NULL) - { - PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); - goto err; - } - - /* Get the slot list for processing */ - if (pflist->C_GetSlotList(0, pSlotList, &ulSlotCount) != CKR_OK) - { - PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); - goto err; - } - - /* - * We don't care about duplicate mechanisms in multiple slots and also - * reserve one slot for the terminal NID_undef which we use to stop the - * search. - */ - hw_ctable_size = ulSlotCount * PK11_CIPHER_MAX + 1; - hw_dtable_size = ulSlotCount * PK11_DIGEST_MAX + 1; - tmp_hw_cnids = OPENSSL_malloc(hw_ctable_size * sizeof (int)); - tmp_hw_dnids = OPENSSL_malloc(hw_dtable_size * sizeof (int)); - if (tmp_hw_cnids == NULL || tmp_hw_dnids == NULL) - { - PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); - goto err; - } - - /* - * Do not use memset since we should not rely on the fact that NID_undef - * is zero now. - */ - for (i = 0; i < hw_ctable_size; ++i) - tmp_hw_cnids[i] = NID_undef; - for (i = 0; i < hw_dtable_size; ++i) - tmp_hw_dnids[i] = NID_undef; - - DEBUG_SLOT_SEL("%s: provider: %s\n", PK11_DBG, pkcs11_kernel); - DEBUG_SLOT_SEL("%s: found %d hardware slots\n", PK11_DBG, ulSlotCount); - DEBUG_SLOT_SEL("%s: now looking for mechs supported in hw\n", - PK11_DBG); - - for (i = 0; i < ulSlotCount; i++) - { - if (pflist->C_GetTokenInfo(pSlotList[i], &token_info) != CKR_OK) - continue; - - DEBUG_SLOT_SEL("%s: token label: %.32s\n", PK11_DBG, - token_info.label); - - /* - * We are filling the hw mech tables here. Global tables are - * still NULL so all mechanisms are put into tmp tables. - */ - pk11_find_symmetric_ciphers(pflist, pSlotList[i], - &n_cipher, tmp_hw_cnids); - pk11_find_digests(pflist, pSlotList[i], - &n_digest, tmp_hw_dnids); - } - - /* - * Since we are part of a library (libcrypto.so), calling this function - * may have side-effects. Also, C_Finalize() is triggered by - * dlclose(3C). - */ -#if 0 - pflist->C_Finalize(NULL); -#endif - OPENSSL_free(pSlotList); - (void) dlclose(handle); - hw_cnids = tmp_hw_cnids; - hw_dnids = tmp_hw_dnids; - - DEBUG_SLOT_SEL("%s: hw mechs check complete\n", PK11_DBG); - return (1); - -err: - if (pSlotList != NULL) - OPENSSL_free(pSlotList); - if (tmp_hw_cnids != NULL) - OPENSSL_free(tmp_hw_cnids); - if (tmp_hw_dnids != NULL) - OPENSSL_free(tmp_hw_dnids); - - return (0); - } - -/* - * Check presence of a NID in the table of NIDs. The table may be NULL (i.e., - * non-existent). - */ -static int nid_in_table(int nid, int *nid_table) - { - int i = 0; - - /* - * a special case. NULL means that we are initializing a new - * table. - */ - if (nid_table == NULL) - return (1); - - /* - * the table is never full, there is always at least one - * NID_undef. - */ - while (nid_table[i] != NID_undef) - { - if (nid_table[i++] == nid) - { - DEBUG_SLOT_SEL(" (NID %d in hw table, idx %d)", nid, i); - return (1); - } - } - - return (0); - } -#endif /* SOLARIS_HW_SLOT_SELECTION */ - -#endif /* OPENSSL_NO_HW_PK11 */ -#endif /* OPENSSL_NO_HW */ diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/engines/pkcs11/hw_pk11.h --- a/components/openssl/openssl-1.0.1-fips-140/engines/pkcs11/hw_pk11.h Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,248 +0,0 @@ -/* - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. - * - */ - -/* crypto/engine/hw_pk11.h */ -/* - * This product includes software developed by the OpenSSL Project for - * use in the OpenSSL Toolkit (http://www.openssl.org/). - * - * This project also referenced hw_pkcs11-0.9.7b.patch written by - * Afchine Madjlessi. - */ -/* - * ==================================================================== - * Copyright (c) 2000-2001 The OpenSSL Project. 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. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED 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 OpenSSL PROJECT OR - * ITS 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. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ - -#ifndef HW_PK11_H -#define HW_PK11_H - -#include "hw_pk11_err.h" - -/* max byte length of a symetric key we support */ -#define PK11_KEY_LEN_MAX 32 - -/* - * This structure encapsulates all reusable information for a PKCS#11 - * session. A list of these objects is created on behalf of the - * calling application using an on-demand method. Each operation - * type (see PK11_OPTYPE below) has its own per-process list. - * Each of the lists is basically a cache for faster PKCS#11 object - * access to avoid expensive C_Find{,Init,Final}Object() calls. - * - * When a new request comes in, an object will be taken from the list - * (if there is one) or a new one is created to handle the request - * (if the list is empty). See pk11_get_session() on how it is done. - */ -typedef struct PK11_st_SESSION - { - struct PK11_st_SESSION *next; - CK_SESSION_HANDLE session; /* PK11 session handle */ - pid_t pid; /* Current process ID */ - CK_BBOOL persistent; /* is that a keystore object? */ - union - { -#ifndef OPENSSL_NO_RSA - struct - { - CK_OBJECT_HANDLE rsa_pub_key; /* pub handle */ - CK_OBJECT_HANDLE rsa_priv_key; /* priv handle */ - RSA *rsa_pub; /* pub key addr */ - BIGNUM *rsa_n_num; /* pub modulus */ - BIGNUM *rsa_e_num; /* pub exponent */ - RSA *rsa_priv; /* priv key addr */ - BIGNUM *rsa_d_num; /* priv exponent */ - } u_RSA; -#endif /* OPENSSL_NO_RSA */ -#ifndef OPENSSL_NO_DSA - struct - { - CK_OBJECT_HANDLE dsa_pub_key; /* pub handle */ - CK_OBJECT_HANDLE dsa_priv_key; /* priv handle */ - DSA *dsa_pub; /* pub key addr */ - BIGNUM *dsa_pub_num; /* pub key */ - DSA *dsa_priv; /* priv key addr */ - BIGNUM *dsa_priv_num; /* priv key */ - } u_DSA; -#endif /* OPENSSL_NO_DSA */ -#ifndef OPENSSL_NO_DH - struct - { - CK_OBJECT_HANDLE dh_key; /* key handle */ - DH *dh; /* dh key addr */ - BIGNUM *dh_priv_num; /* priv dh key */ - } u_DH; -#endif /* OPENSSL_NO_DH */ - struct - { - CK_OBJECT_HANDLE cipher_key; /* key handle */ - unsigned char key[PK11_KEY_LEN_MAX]; - int key_len; /* priv key len */ - int encrypt; /* 1/0 enc/decr */ - } u_cipher; - } opdata_u; - } PK11_SESSION; - -#define opdata_rsa_pub_key opdata_u.u_RSA.rsa_pub_key -#define opdata_rsa_priv_key opdata_u.u_RSA.rsa_priv_key -#define opdata_rsa_pub opdata_u.u_RSA.rsa_pub -#define opdata_rsa_priv opdata_u.u_RSA.rsa_priv -#define opdata_rsa_n_num opdata_u.u_RSA.rsa_n_num -#define opdata_rsa_e_num opdata_u.u_RSA.rsa_e_num -#define opdata_rsa_d_num opdata_u.u_RSA.rsa_d_num -#define opdata_dsa_pub_key opdata_u.u_DSA.dsa_pub_key -#define opdata_dsa_priv_key opdata_u.u_DSA.dsa_priv_key -#define opdata_dsa_pub opdata_u.u_DSA.dsa_pub -#define opdata_dsa_pub_num opdata_u.u_DSA.dsa_pub_num -#define opdata_dsa_priv opdata_u.u_DSA.dsa_priv -#define opdata_dsa_priv_num opdata_u.u_DSA.dsa_priv_num -#define opdata_dh_key opdata_u.u_DH.dh_key -#define opdata_dh opdata_u.u_DH.dh -#define opdata_dh_priv_num opdata_u.u_DH.dh_priv_num -#define opdata_cipher_key opdata_u.u_cipher.cipher_key -#define opdata_key opdata_u.u_cipher.key -#define opdata_key_len opdata_u.u_cipher.key_len -#define opdata_encrypt opdata_u.u_cipher.encrypt - -/* - * We have 3 different groups of operation types: - * 1) asymmetric operations - * 2) random operations - * 3) symmetric and digest operations - * - * This division into groups stems from the fact that it's common that hardware - * providers may support operations from one group only. For example, hardware - * providers on UltraSPARC T2, n2rng(7d), ncp(7d), and n2cp(7d), each support - * only a single group of operations. - * - * For every group a different slot can be chosen. That means that we must have - * at least 3 different lists of cached PKCS#11 sessions since sessions from - * different groups may be initialized in different slots. - * - * To provide locking granularity in multithreaded environment, the groups are - * further splitted into types with each type having a separate session cache. - */ -typedef enum PK11_OPTYPE_ENUM - { - OP_RAND, - OP_RSA, - OP_DSA, - OP_DH, - OP_CIPHER, - OP_DIGEST, - OP_MAX - } PK11_OPTYPE; - -/* - * This structure contains the heads of the lists forming the object caches - * and locks associated with the lists. - */ -typedef struct PK11_st_CACHE - { - PK11_SESSION *head; - pthread_mutex_t *lock; - } PK11_CACHE; - -/* structure for tracking handles of asymmetric key objects */ -typedef struct PK11_active_st - { - CK_OBJECT_HANDLE h; - unsigned int refcnt; - struct PK11_active_st *prev; - struct PK11_active_st *next; - } PK11_active; - -extern pthread_mutex_t *find_lock[]; -extern PK11_active *active_list[]; -/* - * These variables are specific for the RSA keys by reference code. See - * hw_pk11_pub.c for explanation. - */ -extern char *passphrasedialog; -extern CK_FLAGS pubkey_token_flags; - -#define LOCK_OBJSTORE(alg_type) \ - (void) pthread_mutex_lock(find_lock[alg_type]) -#define UNLOCK_OBJSTORE(alg_type) \ - (void) pthread_mutex_unlock(find_lock[alg_type]) - -extern PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); -extern void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); - -#ifndef OPENSSL_NO_RSA -extern int pk11_destroy_rsa_key_objects(PK11_SESSION *session); -extern int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); -extern int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); -extern EVP_PKEY *pk11_load_privkey(ENGINE *e, const char *pubkey_file, - UI_METHOD *ui_method, void *callback_data); -extern EVP_PKEY *pk11_load_pubkey(ENGINE *e, const char *pubkey_file, - UI_METHOD *ui_method, void *callback_data); -extern RSA_METHOD *PK11_RSA(void); -#endif /* OPENSSL_NO_RSA */ -#ifndef OPENSSL_NO_DSA -extern int pk11_destroy_dsa_key_objects(PK11_SESSION *session); -extern int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); -extern int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); -extern DSA_METHOD *PK11_DSA(void); -#endif /* OPENSSL_NO_DSA */ -#ifndef OPENSSL_NO_DH -extern int pk11_destroy_dh_key_objects(PK11_SESSION *session); -extern int pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock); -extern DH_METHOD *PK11_DH(void); -#endif /* OPENSSL_NO_DH */ - -extern CK_FUNCTION_LIST_PTR pFuncList; - -#endif /* HW_PK11_H */ diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/engines/pkcs11/hw_pk11_err.c --- a/components/openssl/openssl-1.0.1-fips-140/engines/pkcs11/hw_pk11_err.c Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,307 +0,0 @@ -/* - * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. - * - */ - -/* crypto/engine/hw_pk11_err.c */ -/* - * This product includes software developed by the OpenSSL Project for - * use in the OpenSSL Toolkit (http://www.openssl.org/). - * - * This project also referenced hw_pkcs11-0.9.7b.patch written by - * Afchine Madjlessi. - */ -/* - * ==================================================================== - * Copyright (c) 2000-2001 The OpenSSL Project. 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. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED 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 OpenSSL PROJECT OR - * ITS 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. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ - -#include -#include -#include "hw_pk11_err.h" - -/* BEGIN ERROR CODES */ -#ifndef OPENSSL_NO_ERR -static ERR_STRING_DATA pk11_str_functs[]= -{ -{ ERR_PACK(0, PK11_F_INIT, 0), "PK11_INIT"}, -{ ERR_PACK(0, PK11_F_FINISH, 0), "PK11_FINISH"}, -{ ERR_PACK(0, PK11_F_DESTROY, 0), "PK11_DESTROY"}, -{ ERR_PACK(0, PK11_F_CTRL, 0), "PK11_CTRL"}, -{ ERR_PACK(0, PK11_F_RSA_INIT, 0), "PK11_RSA_INIT"}, -{ ERR_PACK(0, PK11_F_RSA_FINISH, 0), "PK11_RSA_FINISH"}, -{ ERR_PACK(0, PK11_F_GET_PUB_RSA_KEY, 0), "PK11_GET_PUB_RSA_KEY"}, -{ ERR_PACK(0, PK11_F_GET_PRIV_RSA_KEY, 0), "PK11_GET_PRIV_RSA_KEY"}, -{ ERR_PACK(0, PK11_F_RSA_GEN_KEY, 0), "PK11_RSA_GEN_KEY"}, -{ ERR_PACK(0, PK11_F_RSA_PUB_ENC, 0), "PK11_RSA_PUB_ENC"}, -{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC, 0), "PK11_RSA_PRIV_ENC"}, -{ ERR_PACK(0, PK11_F_RSA_PUB_DEC, 0), "PK11_RSA_PUB_DEC"}, -{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC, 0), "PK11_RSA_PRIV_DEC"}, -{ ERR_PACK(0, PK11_F_RSA_SIGN, 0), "PK11_RSA_SIGN"}, -{ ERR_PACK(0, PK11_F_RSA_VERIFY, 0), "PK11_RSA_VERIFY"}, -{ ERR_PACK(0, PK11_F_RAND_ADD, 0), "PK11_RAND_ADD"}, -{ ERR_PACK(0, PK11_F_RAND_BYTES, 0), "PK11_RAND_BYTES"}, -{ ERR_PACK(0, PK11_F_GET_SESSION, 0), "PK11_GET_SESSION"}, -{ ERR_PACK(0, PK11_F_FREE_SESSION, 0), "PK11_FREE_SESSION"}, -{ ERR_PACK(0, PK11_F_LOAD_PUBKEY, 0), "PK11_LOAD_PUBKEY"}, -{ ERR_PACK(0, PK11_F_LOAD_PRIVKEY, 0), "PK11_LOAD_PRIV_KEY"}, -{ ERR_PACK(0, PK11_F_RSA_PUB_ENC_LOW, 0), "PK11_RSA_PUB_ENC_LOW"}, -{ ERR_PACK(0, PK11_F_RSA_PRIV_ENC_LOW, 0), "PK11_RSA_PRIV_ENC_LOW"}, -{ ERR_PACK(0, PK11_F_RSA_PUB_DEC_LOW, 0), "PK11_RSA_PUB_DEC_LOW"}, -{ ERR_PACK(0, PK11_F_RSA_PRIV_DEC_LOW, 0), "PK11_RSA_PRIV_DEC_LOW"}, -{ ERR_PACK(0, PK11_F_DSA_SIGN, 0), "PK11_DSA_SIGN"}, -{ ERR_PACK(0, PK11_F_DSA_VERIFY, 0), "PK11_DSA_VERIFY"}, -{ ERR_PACK(0, PK11_F_DSA_INIT, 0), "PK11_DSA_INIT"}, -{ ERR_PACK(0, PK11_F_DSA_FINISH, 0), "PK11_DSA_FINISH"}, -{ ERR_PACK(0, PK11_F_GET_PUB_DSA_KEY, 0), "PK11_GET_PUB_DSA_KEY"}, -{ ERR_PACK(0, PK11_F_GET_PRIV_DSA_KEY, 0), "PK11_GET_PRIV_DSA_KEY"}, -{ ERR_PACK(0, PK11_F_DH_INIT, 0), "PK11_DH_INIT"}, -{ ERR_PACK(0, PK11_F_DH_FINISH, 0), "PK11_DH_FINISH"}, -{ ERR_PACK(0, PK11_F_MOD_EXP_DH, 0), "PK11_MOD_EXP_DH"}, -{ ERR_PACK(0, PK11_F_GET_DH_KEY, 0), "PK11_GET_DH_KEY"}, -{ ERR_PACK(0, PK11_F_FREE_ALL_SESSIONS, 0), "PK11_FREE_ALL_SESSIONS"}, -{ ERR_PACK(0, PK11_F_SETUP_SESSION, 0), "PK11_SETUP_SESSION"}, -{ ERR_PACK(0, PK11_F_DESTROY_OBJECT, 0), "PK11_DESTROY_OBJECT"}, -{ ERR_PACK(0, PK11_F_CIPHER_INIT, 0), "PK11_CIPHER_INIT"}, -{ ERR_PACK(0, PK11_F_CIPHER_DO_CIPHER, 0), "PK11_CIPHER_DO_CIPHER"}, -{ ERR_PACK(0, PK11_F_GET_CIPHER_KEY, 0), "PK11_GET_CIPHER_KEY"}, -{ ERR_PACK(0, PK11_F_DIGEST_INIT, 0), "PK11_DIGEST_INIT"}, -{ ERR_PACK(0, PK11_F_DIGEST_UPDATE, 0), "PK11_DIGEST_UPDATE"}, -{ ERR_PACK(0, PK11_F_DIGEST_FINAL, 0), "PK11_DIGEST_FINAL"}, -{ ERR_PACK(0, PK11_F_CHOOSE_SLOT, 0), "PK11_CHOOSE_SLOT"}, -{ ERR_PACK(0, PK11_F_CIPHER_FINAL, 0), "PK11_CIPHER_FINAL"}, -{ ERR_PACK(0, PK11_F_LIBRARY_INIT, 0), "PK11_LIBRARY_INIT"}, -{ ERR_PACK(0, PK11_F_LOAD, 0), "ENGINE_LOAD_PK11"}, -{ ERR_PACK(0, PK11_F_DH_GEN_KEY, 0), "PK11_DH_GEN_KEY"}, -{ ERR_PACK(0, PK11_F_DH_COMP_KEY, 0), "PK11_DH_COMP_KEY"}, -{ ERR_PACK(0, PK11_F_DIGEST_COPY, 0), "PK11_DIGEST_COPY"}, -{ ERR_PACK(0, PK11_F_CIPHER_CLEANUP, 0), "PK11_CIPHER_CLEANUP"}, -{ ERR_PACK(0, PK11_F_ACTIVE_ADD, 0), "PK11_ACTIVE_ADD"}, -{ ERR_PACK(0, PK11_F_ACTIVE_DELETE, 0), "PK11_ACTIVE_DELETE"}, -{ ERR_PACK(0, PK11_F_CHECK_HW_MECHANISMS, 0), "PK11_CHECK_HW_MECHANISMS"}, -{ ERR_PACK(0, PK11_F_INIT_SYMMETRIC, 0), "PK11_INIT_SYMMETRIC"}, -{ ERR_PACK(0, PK11_F_ADD_AES_CTR_NIDS, 0), "PK11_ADD_AES_CTR_NIDS"}, -{ ERR_PACK(0, PK11_F_INIT_ALL_LOCKS, 0), "PK11_INIT_ALL_LOCKS"}, -{ ERR_PACK(0, PK11_F_RETURN_SESSION, 0), "PK11_RETURN_SESSION"}, -{ ERR_PACK(0, PK11_F_GET_PIN, 0), "PK11_GET_PIN"}, -{ ERR_PACK(0, PK11_F_FIND_ONE_OBJECT, 0), "PK11_FIND_ONE_OBJECT"}, -{ ERR_PACK(0, PK11_F_CHECK_TOKEN_ATTRS, 0), "PK11_CHECK_TOKEN_ATTRS"}, -{ ERR_PACK(0, PK11_F_CACHE_PIN, 0), "PK11_CACHE_PIN"}, -{ ERR_PACK(0, PK11_F_MLOCK_PIN_IN_MEMORY, 0), "PK11_MLOCK_PIN_IN_MEMORY"}, -{ ERR_PACK(0, PK11_F_TOKEN_LOGIN, 0), "PK11_TOKEN_LOGIN"}, -{ ERR_PACK(0, PK11_F_TOKEN_RELOGIN, 0), "PK11_TOKEN_RELOGIN"}, -{ ERR_PACK(0, PK11_F_RUN_ASKPASS, 0), "PK11_F_RUN_ASKPASS"}, -{ 0, NULL} -}; - -static ERR_STRING_DATA pk11_str_reasons[]= -{ -{ PK11_R_ALREADY_LOADED, "PKCS#11 DSO already loaded"}, -{ PK11_R_DSO_FAILURE, "unable to load PKCS#11 DSO"}, -{ PK11_R_NOT_LOADED, "PKCS#11 DSO not loaded"}, -{ PK11_R_PASSED_NULL_PARAMETER, "null parameter passed"}, -{ PK11_R_COMMAND_NOT_IMPLEMENTED, "command not implemented"}, -{ PK11_R_INITIALIZE, "C_Initialize failed"}, -{ PK11_R_FINALIZE, "C_Finalize failed"}, -{ PK11_R_GETINFO, "C_GetInfo faile"}, -{ PK11_R_GETSLOTLIST, "C_GetSlotList failed"}, -{ PK11_R_NO_MODULUS_OR_NO_EXPONENT, "no modulus or no exponent"}, -{ PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID, "attr sensitive or invalid"}, -{ PK11_R_GETATTRIBUTVALUE, "C_GetAttributeValue failed"}, -{ PK11_R_NO_MODULUS, "no modulus"}, -{ PK11_R_NO_EXPONENT, "no exponent"}, -{ PK11_R_FINDOBJECTSINIT, "C_FindObjectsInit failed"}, -{ PK11_R_FINDOBJECTS, "C_FindObjects failed"}, -{ PK11_R_FINDOBJECTSFINAL, "C_FindObjectsFinal failed"}, -{ PK11_R_CREATEOBJECT, "C_CreateObject failed"}, -{ PK11_R_DESTROYOBJECT, "C_DestroyObject failed"}, -{ PK11_R_OPENSESSION, "C_OpenSession failed"}, -{ PK11_R_CLOSESESSION, "C_CloseSession failed"}, -{ PK11_R_ENCRYPTINIT, "C_EncryptInit failed"}, -{ PK11_R_ENCRYPT, "C_Encrypt failed"}, -{ PK11_R_SIGNINIT, "C_SignInit failed"}, -{ PK11_R_SIGN, "C_Sign failed"}, -{ PK11_R_DECRYPTINIT, "C_DecryptInit failed"}, -{ PK11_R_DECRYPT, "C_Decrypt failed"}, -{ PK11_R_VERIFYINIT, "C_VerifyRecover failed"}, -{ PK11_R_VERIFY, "C_Verify failed"}, -{ PK11_R_VERIFYRECOVERINIT, "C_VerifyRecoverInit failed"}, -{ PK11_R_VERIFYRECOVER, "C_VerifyRecover failed"}, -{ PK11_R_GEN_KEY, "C_GenerateKeyPair failed"}, -{ PK11_R_SEEDRANDOM, "C_SeedRandom failed"}, -{ PK11_R_GENERATERANDOM, "C_GenerateRandom failed"}, -{ PK11_R_INVALID_MESSAGE_LENGTH, "invalid message length"}, -{ PK11_R_UNKNOWN_ALGORITHM_TYPE, "unknown algorithm type"}, -{ PK11_R_UNKNOWN_ASN1_OBJECT_ID, "unknown asn1 onject id"}, -{ PK11_R_UNKNOWN_PADDING_TYPE, "unknown padding type"}, -{ PK11_R_PADDING_CHECK_FAILED, "padding check failed"}, -{ PK11_R_DIGEST_TOO_BIG, "digest too big"}, -{ PK11_R_MALLOC_FAILURE, "malloc failure"}, -{ PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED, "ctl command not implemented"}, -{ PK11_R_DATA_GREATER_THAN_MOD_LEN, "data is bigger than mod"}, -{ PK11_R_DATA_TOO_LARGE_FOR_MODULUS, "data is too larger for mod"}, -{ PK11_R_MISSING_KEY_COMPONENT, "a dsa component is missing"}, -{ PK11_R_INVALID_SIGNATURE_LENGTH, "invalid signature length"}, -{ PK11_R_INVALID_DSA_SIGNATURE_R, "missing r in dsa verify"}, -{ PK11_R_INVALID_DSA_SIGNATURE_S, "missing s in dsa verify"}, -{ PK11_R_INCONSISTENT_KEY, "inconsistent key type"}, -{ PK11_R_ENCRYPTUPDATE, "C_EncryptUpdate failed"}, -{ PK11_R_DECRYPTUPDATE, "C_DecryptUpdate failed"}, -{ PK11_R_DIGESTINIT, "C_DigestInit failed"}, -{ PK11_R_DIGESTUPDATE, "C_DigestUpdate failed"}, -{ PK11_R_DIGESTFINAL, "C_DigestFinal failed"}, -{ PK11_R_ENCRYPTFINAL, "C_EncryptFinal failed"}, -{ PK11_R_DECRYPTFINAL, "C_DecryptFinal failed"}, -{ PK11_R_NO_PRNG_SUPPORT, "Slot does not support PRNG"}, -{ PK11_R_GETTOKENINFO, "C_GetTokenInfo failed"}, -{ PK11_R_DERIVEKEY, "C_DeriveKey failed"}, -{ PK11_R_GET_OPERATION_STATE, "C_GetOperationState failed"}, -{ PK11_R_SET_OPERATION_STATE, "C_SetOperationState failed"}, -{ PK11_R_INVALID_HANDLE, "invalid PKCS#11 object handle"}, -{ PK11_R_KEY_OR_IV_LEN_PROBLEM, "IV or key length incorrect"}, -{ PK11_R_INVALID_OPERATION_TYPE, "invalid operation type"}, -{ PK11_R_ADD_NID_FAILED, "failed to add NID" }, -{ PK11_R_ATFORK_FAILED, "atfork failed" }, -{ PK11_R_TOKEN_LOGIN_FAILED, "C_Login failed on token" }, -{ PK11_R_MORE_THAN_ONE_OBJECT_FOUND, "more than one object found" }, -{ PK11_R_INVALID_PKCS11_URI, "pkcs11 URI provided is invalid" }, -{ PK11_R_COULD_NOT_READ_PIN, "could not read PIN from terminal" }, -{ PK11_R_PIN_NOT_READ_FROM_COMMAND, "PIN not read from external command" }, -{ PK11_R_COULD_NOT_OPEN_COMMAND, "could not popen dialog command" }, -{ PK11_R_PIPE_FAILED, "pipe failed" }, -{ PK11_R_BAD_PASSPHRASE_SPEC, "bad passphrasedialog specification" }, -{ PK11_R_TOKEN_NOT_INITIALIZED, "token not initialized" }, -{ PK11_R_TOKEN_PIN_NOT_SET, "token PIN required but not set" }, -{ PK11_R_TOKEN_PIN_NOT_PROVIDED, "token PIN required but not provided" }, -{ PK11_R_MISSING_OBJECT_LABEL, "missing mandatory 'object' keyword" }, -{ PK11_R_TOKEN_ATTRS_DO_NOT_MATCH, "token attrs provided do not match" }, -{ PK11_R_PRIV_KEY_NOT_FOUND, "private key not found in keystore" }, -{ PK11_R_NO_OBJECT_FOUND, "specified object not found" }, -{ PK11_R_PIN_CACHING_POLICY_INVALID, "PIN set but caching policy invalid" }, -{ PK11_R_SYSCONF_FAILED, "sysconf failed" }, -{ PK11_R_MMAP_FAILED, "mmap failed" }, -{ PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING, "PROC_LOCK_MEMORY privilege missing" }, -{ PK11_R_MLOCK_FAILED, "mlock failed" }, -{ PK11_R_FORK_FAILED, "fork failed" }, -{ 0, NULL} -}; -#endif /* OPENSSL_NO_ERR */ - -static int pk11_lib_error_code = 0; -static int pk11_error_init = 1; - -#ifdef PK11_ENGINE_LIB_NAME -static ERR_STRING_DATA pk11_engine_lib_name[] = -{ -{0, PK11_ENGINE_LIB_NAME}, -{0, NULL} -}; -#endif - -static void -ERR_load_pk11_strings(void) - { - if (pk11_lib_error_code == 0) - pk11_lib_error_code = ERR_get_next_error_library(); - - if (pk11_error_init) - { - pk11_error_init = 0; -#ifndef OPENSSL_NO_ERR - ERR_load_strings(pk11_lib_error_code, pk11_str_functs); - ERR_load_strings(pk11_lib_error_code, pk11_str_reasons); -#endif - -#ifdef PK11_ENGINE_LIB_NAME - pk11_engine_lib_name->error = - ERR_PACK(pk11_lib_error_code, 0, 0); - ERR_load_strings(0, pk11_engine_lib_name); -#endif - } - } - -static void -ERR_unload_pk11_strings(void) - { - if (pk11_error_init == 0) - { -#ifndef OPENSSL_NO_ERR - ERR_unload_strings(pk11_lib_error_code, pk11_str_functs); - ERR_unload_strings(pk11_lib_error_code, pk11_str_reasons); -#endif - -#ifdef PK11_ENGINE_LIB_NAME - ERR_unload_strings(0, pk11_engine_lib_name); -#endif - - pk11_error_init = 1; - } - } - -void -ERR_pk11_error(int function, int reason, char *file, int line) - { - if (pk11_lib_error_code == 0) - pk11_lib_error_code = ERR_get_next_error_library(); - ERR_PUT_error(pk11_lib_error_code, function, reason, file, line); - } - -void -PK11err_add_data(int function, int reason, CK_RV rv) - { - char tmp_buf[20]; - - PK11err(function, reason); - (void) snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); - ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); - } diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/engines/pkcs11/hw_pk11_err.h --- a/components/openssl/openssl-1.0.1-fips-140/engines/pkcs11/hw_pk11_err.h Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. - * - */ - -/* - * This product includes software developed by the OpenSSL Project for - * use in the OpenSSL Toolkit (http://www.openssl.org/). - * - * This project also referenced hw_pkcs11-0.9.7b.patch written by - * Afchine Madjlessi. - */ -/* - * ==================================================================== - * Copyright (c) 2000-2001 The OpenSSL Project. 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. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED 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 OpenSSL PROJECT OR - * ITS 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. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ - -#ifndef HW_PK11_ERR_H -#define HW_PK11_ERR_H - -void ERR_pk11_error(int function, int reason, char *file, int line); -void PK11err_add_data(int function, int reason, CK_RV rv); -#define PK11err(f, r) ERR_pk11_error((f), (r), __FILE__, __LINE__) - -/* Error codes for the PK11 functions. */ - -/* Function codes. */ - -#define PK11_F_INIT 100 -#define PK11_F_FINISH 101 -#define PK11_F_DESTROY 102 -#define PK11_F_CTRL 103 -#define PK11_F_RSA_INIT 104 -#define PK11_F_RSA_FINISH 105 -#define PK11_F_GET_PUB_RSA_KEY 106 -#define PK11_F_GET_PRIV_RSA_KEY 107 -#define PK11_F_RSA_GEN_KEY 108 -#define PK11_F_RSA_PUB_ENC 109 -#define PK11_F_RSA_PRIV_ENC 110 -#define PK11_F_RSA_PUB_DEC 111 -#define PK11_F_RSA_PRIV_DEC 112 -#define PK11_F_RSA_SIGN 113 -#define PK11_F_RSA_VERIFY 114 -#define PK11_F_RAND_ADD 115 -#define PK11_F_RAND_BYTES 116 -#define PK11_F_GET_SESSION 117 -#define PK11_F_FREE_SESSION 118 -#define PK11_F_LOAD_PUBKEY 119 -#define PK11_F_LOAD_PRIVKEY 120 -#define PK11_F_RSA_PUB_ENC_LOW 121 -#define PK11_F_RSA_PRIV_ENC_LOW 122 -#define PK11_F_RSA_PUB_DEC_LOW 123 -#define PK11_F_RSA_PRIV_DEC_LOW 124 -#define PK11_F_DSA_SIGN 125 -#define PK11_F_DSA_VERIFY 126 -#define PK11_F_DSA_INIT 127 -#define PK11_F_DSA_FINISH 128 -#define PK11_F_GET_PUB_DSA_KEY 129 -#define PK11_F_GET_PRIV_DSA_KEY 130 -#define PK11_F_DH_INIT 131 -#define PK11_F_DH_FINISH 132 -#define PK11_F_MOD_EXP_DH 133 -#define PK11_F_GET_DH_KEY 134 -#define PK11_F_FREE_ALL_SESSIONS 135 -#define PK11_F_SETUP_SESSION 136 -#define PK11_F_DESTROY_OBJECT 137 -#define PK11_F_CIPHER_INIT 138 -#define PK11_F_CIPHER_DO_CIPHER 139 -#define PK11_F_GET_CIPHER_KEY 140 -#define PK11_F_DIGEST_INIT 141 -#define PK11_F_DIGEST_UPDATE 142 -#define PK11_F_DIGEST_FINAL 143 -#define PK11_F_CHOOSE_SLOT 144 -#define PK11_F_CIPHER_FINAL 145 -#define PK11_F_LIBRARY_INIT 146 -#define PK11_F_LOAD 147 -#define PK11_F_DH_GEN_KEY 148 -#define PK11_F_DH_COMP_KEY 149 -#define PK11_F_DIGEST_COPY 150 -#define PK11_F_CIPHER_CLEANUP 151 -#define PK11_F_ACTIVE_ADD 152 -#define PK11_F_ACTIVE_DELETE 153 -#define PK11_F_CHECK_HW_MECHANISMS 154 -#define PK11_F_INIT_SYMMETRIC 155 -#define PK11_F_ADD_AES_CTR_NIDS 156 -#define PK11_F_INIT_ALL_LOCKS 157 -#define PK11_F_RETURN_SESSION 158 -#define PK11_F_GET_PIN 159 -#define PK11_F_FIND_ONE_OBJECT 160 -#define PK11_F_CHECK_TOKEN_ATTRS 161 -#define PK11_F_CACHE_PIN 162 -#define PK11_F_MLOCK_PIN_IN_MEMORY 163 -#define PK11_F_TOKEN_LOGIN 164 -#define PK11_F_TOKEN_RELOGIN 165 -#define PK11_F_RUN_ASKPASS 166 - -/* Reason codes. */ -#define PK11_R_ALREADY_LOADED 100 -#define PK11_R_DSO_FAILURE 101 -#define PK11_R_NOT_LOADED 102 -#define PK11_R_PASSED_NULL_PARAMETER 103 -#define PK11_R_COMMAND_NOT_IMPLEMENTED 104 -#define PK11_R_INITIALIZE 105 -#define PK11_R_FINALIZE 106 -#define PK11_R_GETINFO 107 -#define PK11_R_GETSLOTLIST 108 -#define PK11_R_NO_MODULUS_OR_NO_EXPONENT 109 -#define PK11_R_ATTRIBUT_SENSITIVE_OR_INVALID 110 -#define PK11_R_GETATTRIBUTVALUE 111 -#define PK11_R_NO_MODULUS 112 -#define PK11_R_NO_EXPONENT 113 -#define PK11_R_FINDOBJECTSINIT 114 -#define PK11_R_FINDOBJECTS 115 -#define PK11_R_FINDOBJECTSFINAL 116 -#define PK11_R_CREATEOBJECT 118 -#define PK11_R_DESTROYOBJECT 119 -#define PK11_R_OPENSESSION 120 -#define PK11_R_CLOSESESSION 121 -#define PK11_R_ENCRYPTINIT 122 -#define PK11_R_ENCRYPT 123 -#define PK11_R_SIGNINIT 124 -#define PK11_R_SIGN 125 -#define PK11_R_DECRYPTINIT 126 -#define PK11_R_DECRYPT 127 -#define PK11_R_VERIFYINIT 128 -#define PK11_R_VERIFY 129 -#define PK11_R_VERIFYRECOVERINIT 130 -#define PK11_R_VERIFYRECOVER 131 -#define PK11_R_GEN_KEY 132 -#define PK11_R_SEEDRANDOM 133 -#define PK11_R_GENERATERANDOM 134 -#define PK11_R_INVALID_MESSAGE_LENGTH 135 -#define PK11_R_UNKNOWN_ALGORITHM_TYPE 136 -#define PK11_R_UNKNOWN_ASN1_OBJECT_ID 137 -#define PK11_R_UNKNOWN_PADDING_TYPE 138 -#define PK11_R_PADDING_CHECK_FAILED 139 -#define PK11_R_DIGEST_TOO_BIG 140 -#define PK11_R_MALLOC_FAILURE 141 -#define PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED 142 -#define PK11_R_DATA_GREATER_THAN_MOD_LEN 143 -#define PK11_R_DATA_TOO_LARGE_FOR_MODULUS 144 -#define PK11_R_MISSING_KEY_COMPONENT 145 -#define PK11_R_INVALID_SIGNATURE_LENGTH 146 -#define PK11_R_INVALID_DSA_SIGNATURE_R 147 -#define PK11_R_INVALID_DSA_SIGNATURE_S 148 -#define PK11_R_INCONSISTENT_KEY 149 -#define PK11_R_ENCRYPTUPDATE 150 -#define PK11_R_DECRYPTUPDATE 151 -#define PK11_R_DIGESTINIT 152 -#define PK11_R_DIGESTUPDATE 153 -#define PK11_R_DIGESTFINAL 154 -#define PK11_R_ENCRYPTFINAL 155 -#define PK11_R_DECRYPTFINAL 156 -#define PK11_R_NO_PRNG_SUPPORT 157 -#define PK11_R_GETTOKENINFO 158 -#define PK11_R_DERIVEKEY 159 -#define PK11_R_GET_OPERATION_STATE 160 -#define PK11_R_SET_OPERATION_STATE 161 -#define PK11_R_INVALID_HANDLE 162 -#define PK11_R_KEY_OR_IV_LEN_PROBLEM 163 -#define PK11_R_INVALID_OPERATION_TYPE 164 -#define PK11_R_ADD_NID_FAILED 165 -#define PK11_R_ATFORK_FAILED 166 -#define PK11_R_TOKEN_LOGIN_FAILED 167 -#define PK11_R_MORE_THAN_ONE_OBJECT_FOUND 168 -#define PK11_R_INVALID_PKCS11_URI 169 -#define PK11_R_COULD_NOT_READ_PIN 170 -#define PK11_R_COULD_NOT_OPEN_COMMAND 171 -#define PK11_R_PIPE_FAILED 172 -#define PK11_R_PIN_NOT_READ_FROM_COMMAND 173 -#define PK11_R_BAD_PASSPHRASE_SPEC 174 -#define PK11_R_TOKEN_NOT_INITIALIZED 175 -#define PK11_R_TOKEN_PIN_NOT_SET 176 -#define PK11_R_TOKEN_PIN_NOT_PROVIDED 177 -#define PK11_R_MISSING_OBJECT_LABEL 178 -#define PK11_R_TOKEN_ATTRS_DO_NOT_MATCH 179 -#define PK11_R_PRIV_KEY_NOT_FOUND 180 -#define PK11_R_NO_OBJECT_FOUND 181 -#define PK11_R_PIN_CACHING_POLICY_INVALID 182 -#define PK11_R_SYSCONF_FAILED 183 -#define PK11_R_MMAP_FAILED 183 -#define PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING 184 -#define PK11_R_MLOCK_FAILED 185 -#define PK11_R_FORK_FAILED 186 - -#endif /* HW_PK11_ERR_H */ diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/engines/pkcs11/hw_pk11_pub.c --- a/components/openssl/openssl-1.0.1-fips-140/engines/pkcs11/hw_pk11_pub.c Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3239 +0,0 @@ -/* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. - * - */ - -/* crypto/engine/hw_pk11_pub.c */ -/* - * This product includes software developed by the OpenSSL Project for - * use in the OpenSSL Toolkit (http://www.openssl.org/). - * - * This project also referenced hw_pkcs11-0.9.7b.patch written by - * Afchine Madjlessi. - */ -/* - * ==================================================================== - * Copyright (c) 2000-2001 The OpenSSL Project. 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. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED 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 OpenSSL PROJECT OR - * ITS 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. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#ifndef OPENSSL_NO_RSA -#include -#endif /* OPENSSL_NO_RSA */ -#ifndef OPENSSL_NO_DSA -#include -#endif /* OPENSSL_NO_DSA */ -#ifndef OPENSSL_NO_DH -#include -#endif /* OPENSSL_NO_DH */ -#include -#include -#include -#include -#include -#include - -#ifndef OPENSSL_NO_HW -#ifndef OPENSSL_NO_HW_PK11 - -#include -#include -#include "hw_pk11.h" -#include "hw_pk11_uri.h" - -static CK_BBOOL pk11_login_done = CK_FALSE; -extern CK_SLOT_ID pubkey_SLOTID; - -/* - * During the reinitialization after a detected fork we will try to login to the - * token using the passphrasedialog keyword that we inherit from the parent. - */ -char *passphrasedialog; - -#ifndef OPENSSL_NO_RSA -/* RSA stuff */ -static int pk11_RSA_public_encrypt(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding); -static int pk11_RSA_private_encrypt(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding); -static int pk11_RSA_public_decrypt(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding); -static int pk11_RSA_private_decrypt(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding); -static int pk11_RSA_init(RSA *rsa); -static int pk11_RSA_finish(RSA *rsa); -static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, - unsigned char *sigret, unsigned int *siglen, const RSA *rsa); -static int pk11_RSA_verify(int dtype, const unsigned char *m, - unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, - const RSA *rsa); -EVP_PKEY *pk11_load_privkey(ENGINE*, const char *privkey_id, - UI_METHOD *ui_method, void *callback_data); -EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_id, - UI_METHOD *ui_method, void *callback_data); - -static int pk11_RSA_public_encrypt_low(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa); -static int pk11_RSA_private_encrypt_low(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa); -static int pk11_RSA_public_decrypt_low(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa); -static int pk11_RSA_private_decrypt_low(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa); - -static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, PK11_SESSION *sp); -static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, PK11_SESSION *sp); - -static int pk11_check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa); -static int pk11_check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa); -#endif - -/* DSA stuff */ -#ifndef OPENSSL_NO_DSA -static int pk11_DSA_init(DSA *dsa); -static int pk11_DSA_finish(DSA *dsa); -static DSA_SIG *pk11_dsa_do_sign(const unsigned char *dgst, int dlen, - DSA *dsa); -static int pk11_dsa_do_verify(const unsigned char *dgst, int dgst_len, - DSA_SIG *sig, DSA *dsa); - -static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa, DSA **key_ptr, - BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session); -static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa, DSA **key_ptr, - BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session); - -static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa); -static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa); -#endif - -/* DH stuff */ -#ifndef OPENSSL_NO_DH -static int pk11_DH_init(DH *dh); -static int pk11_DH_finish(DH *dh); -static int pk11_DH_generate_key(DH *dh); -static int pk11_DH_compute_key(unsigned char *key, - const BIGNUM *pub_key, DH *dh); - -static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, DH **key_ptr, - BIGNUM **priv_key, CK_SESSION_HANDLE session); - -static int check_new_dh_key(PK11_SESSION *sp, DH *dh); -#endif - -static int find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, - CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey); -static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue, - CK_ULONG *ulValueLen); -static void attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn); - -/* Read mode string to be used for fopen() */ -#if SOLARIS_OPENSSL -static char *read_mode_flags = "rF"; -#else -static char *read_mode_flags = "r"; -#endif - -/* - * Increment existing or create a new reference for an asymmetric key PKCS#11 - * object handle in the active object list. If the operation fails, unlock (if - * locked), set error variable and jump to the specified label. We use this list - * so that we can track how many references to the PKCS#11 objects are used from - * all our sessions structures. If we are replacing an object reference in the - * session structure and the ref count for the reference being replaced gets to - * 0 we know that we can safely free the object itself via C_ObjectDestroy(). - * See also TRY_OBJ_DESTROY. - */ -#define KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label) \ - { \ - if (pk11_active_add(key_handle, alg_type) < 0) \ - { \ - var = CK_TRUE; \ - if (unlock) \ - UNLOCK_OBJSTORE(alg_type); \ - goto label; \ - } \ - } - -/* - * Find active list entry according to object handle and return pointer to the - * entry otherwise return NULL. - * - * This function presumes it is called with lock protecting the active list - * held. - */ -static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type) - { - PK11_active *entry; - - for (entry = active_list[type]; entry != NULL; entry = entry->next) - if (entry->h == h) - return (entry); - - return (NULL); - } - -/* - * Search for an entry in the active list using PKCS#11 object handle as a - * search key and return refcnt of the found/created entry or -1 in case of - * failure. - * - * This function presumes it is called with lock protecting the active list - * held. - */ -int -pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type) - { - PK11_active *entry = NULL; - - if (h == CK_INVALID_HANDLE) - { - PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE); - return (-1); - } - - /* search for entry in the active list */ - if ((entry = pk11_active_find(h, type)) != NULL) - entry->refcnt++; - else - { - /* not found, create new entry and add it to the list */ - entry = OPENSSL_malloc(sizeof (PK11_active)); - if (entry == NULL) - { - PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE); - return (-1); - } - entry->h = h; - entry->refcnt = 1; - entry->prev = NULL; - entry->next = NULL; - /* connect the newly created entry to the list */ - if (active_list[type] == NULL) - active_list[type] = entry; - else /* make the entry first in the list */ - { - entry->next = active_list[type]; - active_list[type]->prev = entry; - active_list[type] = entry; - } - } - - return (entry->refcnt); - } - -/* - * Remove active list entry from the list and free it. - * - * This function presumes it is called with lock protecting the active list - * held. - */ -void -pk11_active_remove(PK11_active *entry, PK11_OPTYPE type) - { - PK11_active *prev_entry; - - /* remove the entry from the list and free it */ - if ((prev_entry = entry->prev) != NULL) - { - prev_entry->next = entry->next; - if (entry->next != NULL) - entry->next->prev = prev_entry; - } - else - { - active_list[type] = entry->next; - /* we were the first but not the only one */ - if (entry->next != NULL) - entry->next->prev = NULL; - } - - /* sanitization */ - entry->h = CK_INVALID_HANDLE; - entry->prev = NULL; - entry->next = NULL; - OPENSSL_free(entry); - } - -/* Free all entries from the active list. */ -void -pk11_free_active_list(PK11_OPTYPE type) - { - PK11_active *entry; - - /* only for asymmetric types since only they have C_Find* locks. */ - switch (type) - { - case OP_RSA: - case OP_DSA: - case OP_DH: - break; - default: - return; - } - - /* see find_lock array definition for more info on object locking */ - LOCK_OBJSTORE(type); - while ((entry = active_list[type]) != NULL) - pk11_active_remove(entry, type); - UNLOCK_OBJSTORE(type); - } - -/* - * Search for active list entry associated with given PKCS#11 object handle, - * decrement its refcnt and if it drops to 0, disconnect the entry and free it. - * - * Return 1 if the PKCS#11 object associated with the entry has no references, - * return 0 if there is at least one reference, -1 on error. - * - * This function presumes it is called with lock protecting the active list - * held. - */ -int -pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type) - { - PK11_active *entry = NULL; - - if ((entry = pk11_active_find(h, type)) == NULL) - { - PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE); - return (-1); - } - - OPENSSL_assert(entry->refcnt > 0); - entry->refcnt--; - if (entry->refcnt == 0) - { - pk11_active_remove(entry, type); - return (1); - } - - return (0); - } - -#ifndef OPENSSL_NO_RSA -/* Our internal RSA_METHOD that we provide pointers to */ -static RSA_METHOD pk11_rsa = - { - "PKCS#11 RSA method", - pk11_RSA_public_encrypt, /* rsa_pub_encrypt */ - pk11_RSA_public_decrypt, /* rsa_pub_decrypt */ - pk11_RSA_private_encrypt, /* rsa_priv_encrypt */ - pk11_RSA_private_decrypt, /* rsa_priv_decrypt */ - NULL, /* rsa_mod_exp */ - NULL, /* bn_mod_exp */ - pk11_RSA_init, /* init */ - pk11_RSA_finish, /* finish */ - RSA_FLAG_SIGN_VER, /* flags */ - NULL, /* app_data */ - pk11_RSA_sign, /* rsa_sign */ - pk11_RSA_verify /* rsa_verify */ - }; - -RSA_METHOD * -PK11_RSA(void) - { - return (&pk11_rsa); - } -#endif - -#ifndef OPENSSL_NO_DSA -/* Our internal DSA_METHOD that we provide pointers to */ -static DSA_METHOD pk11_dsa = - { - "PKCS#11 DSA method", - pk11_dsa_do_sign, /* dsa_do_sign */ - NULL, /* dsa_sign_setup */ - pk11_dsa_do_verify, /* dsa_do_verify */ - NULL, /* dsa_mod_exp */ - NULL, /* bn_mod_exp */ - pk11_DSA_init, /* init */ - pk11_DSA_finish, /* finish */ - 0, /* flags */ - NULL /* app_data */ - }; - -DSA_METHOD * -PK11_DSA(void) - { - return (&pk11_dsa); - } -#endif - -#ifndef OPENSSL_NO_DH -/* - * PKCS #11 V2.20, section 11.2 specifies that the number of bytes needed for - * output buffer may somewhat exceed the precise number of bytes needed, but - * should not exceed it by a large amount. That may be caused, for example, by - * rounding it up to multiple of X in the underlying bignum library. 8 should be - * enough. - */ -#define DH_BUF_RESERVE 8 - -/* Our internal DH_METHOD that we provide pointers to */ -static DH_METHOD pk11_dh = - { - "PKCS#11 DH method", - pk11_DH_generate_key, /* generate_key */ - pk11_DH_compute_key, /* compute_key */ - NULL, /* bn_mod_exp */ - pk11_DH_init, /* init */ - pk11_DH_finish, /* finish */ - 0, /* flags */ - NULL, /* app_data */ - NULL /* generate_params */ - }; - -DH_METHOD * -PK11_DH(void) - { - return (&pk11_dh); - } -#endif - -/* Size of an SSL signature: MD5+SHA1 */ -#define SSL_SIG_LENGTH 36 - -/* Lengths of DSA data and signature */ -#define DSA_DATA_LEN 20 -#define DSA_SIGNATURE_LEN 40 - -static CK_BBOOL pk11_true = CK_TRUE; -static CK_BBOOL pk11_false = CK_FALSE; - -#ifndef OPENSSL_NO_RSA -/* - * Similiar to OpenSSL to take advantage of the paddings. The goal is to - * support all paddings in this engine although PK11 library does not - * support all the paddings used in OpenSSL. - * The input errors should have been checked in the padding functions. - */ -static int pk11_RSA_public_encrypt(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding) - { - int i, num = 0, r = -1; - unsigned char *buf = NULL; - - num = BN_num_bytes(rsa->n); - if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL) - { - PK11err(PK11_F_RSA_PUB_ENC, PK11_R_MALLOC_FAILURE); - goto err; - } - - switch (padding) - { - case RSA_PKCS1_PADDING: - i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen); - break; -#ifndef OPENSSL_NO_SHA - case RSA_PKCS1_OAEP_PADDING: - i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0); - break; -#endif - case RSA_SSLV23_PADDING: - i = RSA_padding_add_SSLv23(buf, num, from, flen); - break; - case RSA_NO_PADDING: - i = RSA_padding_add_none(buf, num, from, flen); - break; - default: - PK11err(PK11_F_RSA_PUB_ENC, PK11_R_UNKNOWN_PADDING_TYPE); - goto err; - } - if (i <= 0) goto err; - - /* PK11 functions are called here */ - r = pk11_RSA_public_encrypt_low(num, buf, to, rsa); -err: - if (buf != NULL) - { - OPENSSL_cleanse(buf, num); - OPENSSL_free(buf); - } - return (r); - } - - -/* - * Similar to Openssl to take advantage of the paddings. The input errors - * should be catched in the padding functions - */ -static int pk11_RSA_private_encrypt(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding) - { - int i, num = 0, r = -1; - unsigned char *buf = NULL; - - num = BN_num_bytes(rsa->n); - if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL) - { - PK11err(PK11_F_RSA_PRIV_ENC, PK11_R_MALLOC_FAILURE); - goto err; - } - - switch (padding) - { - case RSA_PKCS1_PADDING: - i = RSA_padding_add_PKCS1_type_1(buf, num, from, flen); - break; - case RSA_NO_PADDING: - i = RSA_padding_add_none(buf, num, from, flen); - break; - case RSA_SSLV23_PADDING: - default: - PK11err(PK11_F_RSA_PRIV_ENC, PK11_R_UNKNOWN_PADDING_TYPE); - goto err; - } - if (i <= 0) goto err; - - /* PK11 functions are called here */ - r = pk11_RSA_private_encrypt_low(num, buf, to, rsa); -err: - if (buf != NULL) - { - OPENSSL_cleanse(buf, num); - OPENSSL_free(buf); - } - return (r); - } - -/* Similar to OpenSSL code. Input errors are also checked here */ -static int pk11_RSA_private_decrypt(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding) - { - BIGNUM f; - int j, num = 0, r = -1; - unsigned char *p; - unsigned char *buf = NULL; - - BN_init(&f); - - num = BN_num_bytes(rsa->n); - - if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL) - { - PK11err(PK11_F_RSA_PRIV_DEC, PK11_R_MALLOC_FAILURE); - goto err; - } - - /* - * This check was for equality but PGP does evil things - * and chops off the top '0' bytes - */ - if (flen > num) - { - PK11err(PK11_F_RSA_PRIV_DEC, - PK11_R_DATA_GREATER_THAN_MOD_LEN); - goto err; - } - - /* make data into a big number */ - if (BN_bin2bn(from, (int)flen, &f) == NULL) - goto err; - - if (BN_ucmp(&f, rsa->n) >= 0) - { - PK11err(PK11_F_RSA_PRIV_DEC, - PK11_R_DATA_TOO_LARGE_FOR_MODULUS); - goto err; - } - - /* PK11 functions are called here */ - r = pk11_RSA_private_decrypt_low(flen, from, buf, rsa); - - /* - * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning. - * Needs to skip these 0's paddings here. - */ - for (j = 0; j < r; j++) - if (buf[j] != 0) - break; - - p = buf + j; - j = r - j; /* j is only used with no-padding mode */ - - switch (padding) - { - case RSA_PKCS1_PADDING: - r = RSA_padding_check_PKCS1_type_2(to, num, p, j, num); - break; -#ifndef OPENSSL_NO_SHA - case RSA_PKCS1_OAEP_PADDING: - r = RSA_padding_check_PKCS1_OAEP(to, num, p, j, num, NULL, 0); - break; -#endif - case RSA_SSLV23_PADDING: - r = RSA_padding_check_SSLv23(to, num, p, j, num); - break; - case RSA_NO_PADDING: - r = RSA_padding_check_none(to, num, p, j, num); - break; - default: - PK11err(PK11_F_RSA_PRIV_DEC, PK11_R_UNKNOWN_PADDING_TYPE); - goto err; - } - if (r < 0) - PK11err(PK11_F_RSA_PRIV_DEC, PK11_R_PADDING_CHECK_FAILED); - -err: - BN_clear_free(&f); - if (buf != NULL) - { - OPENSSL_cleanse(buf, num); - OPENSSL_free(buf); - } - return (r); - } - -/* Similar to OpenSSL code. Input errors are also checked here */ -static int pk11_RSA_public_decrypt(int flen, const unsigned char *from, - unsigned char *to, RSA *rsa, int padding) - { - BIGNUM f; - int i, num = 0, r = -1; - unsigned char *p; - unsigned char *buf = NULL; - - BN_init(&f); - num = BN_num_bytes(rsa->n); - buf = (unsigned char *)OPENSSL_malloc(num); - if (buf == NULL) - { - PK11err(PK11_F_RSA_PUB_DEC, PK11_R_MALLOC_FAILURE); - goto err; - } - - /* - * This check was for equality but PGP does evil things - * and chops off the top '0' bytes - */ - if (flen > num) - { - PK11err(PK11_F_RSA_PUB_DEC, PK11_R_DATA_GREATER_THAN_MOD_LEN); - goto err; - } - - if (BN_bin2bn(from, flen, &f) == NULL) - goto err; - - if (BN_ucmp(&f, rsa->n) >= 0) - { - PK11err(PK11_F_RSA_PUB_DEC, - PK11_R_DATA_TOO_LARGE_FOR_MODULUS); - goto err; - } - - /* PK11 functions are called here */ - r = pk11_RSA_public_decrypt_low(flen, from, buf, rsa); - - /* - * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning. - * Needs to skip these 0's here - */ - for (i = 0; i < r; i++) - if (buf[i] != 0) - break; - - p = buf + i; - i = r - i; /* i is only used with no-padding mode */ - - switch (padding) - { - case RSA_PKCS1_PADDING: - r = RSA_padding_check_PKCS1_type_1(to, num, p, i, num); - break; - case RSA_NO_PADDING: - r = RSA_padding_check_none(to, num, p, i, num); - break; - default: - PK11err(PK11_F_RSA_PUB_DEC, PK11_R_UNKNOWN_PADDING_TYPE); - goto err; - } - if (r < 0) - PK11err(PK11_F_RSA_PUB_DEC, PK11_R_PADDING_CHECK_FAILED); - -err: - BN_clear_free(&f); - if (buf != NULL) - { - OPENSSL_cleanse(buf, num); - OPENSSL_free(buf); - } - return (r); - } - -/* - * This function implements RSA public encryption using C_EncryptInit and - * C_Encrypt pk11 interfaces. Note that the CKM_RSA_X_509 is used here. - * The calling function allocated sufficient memory in "to" to store results. - */ -static int pk11_RSA_public_encrypt_low(int flen, - const unsigned char *from, unsigned char *to, RSA *rsa) - { - CK_ULONG bytes_encrypted = flen; - int retval = -1; - CK_RV rv; - CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; - CK_MECHANISM *p_mech = &mech_rsa; - CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; - PK11_SESSION *sp; - - if ((sp = pk11_get_session(OP_RSA)) == NULL) - return (-1); - - (void) pk11_check_new_rsa_key_pub(sp, rsa); - - h_pub_key = sp->opdata_rsa_pub_key; - if (h_pub_key == CK_INVALID_HANDLE) - h_pub_key = sp->opdata_rsa_pub_key = - pk11_get_public_rsa_key(rsa, sp); - - if (h_pub_key != CK_INVALID_HANDLE) - { - rv = pFuncList->C_EncryptInit(sp->session, p_mech, - h_pub_key); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW, - PK11_R_ENCRYPTINIT, rv); - pk11_return_session(sp, OP_RSA); - return (-1); - } - - rv = pFuncList->C_Encrypt(sp->session, - (unsigned char *)from, flen, to, &bytes_encrypted); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW, - PK11_R_ENCRYPT, rv); - pk11_return_session(sp, OP_RSA); - return (-1); - } - retval = bytes_encrypted; - } - - pk11_return_session(sp, OP_RSA); - return (retval); - } - - -/* - * This function implements RSA private encryption using C_SignInit and - * C_Sign pk11 APIs. Note that CKM_RSA_X_509 is used here. - * The calling function allocated sufficient memory in "to" to store results. - */ -static int pk11_RSA_private_encrypt_low(int flen, - const unsigned char *from, unsigned char *to, RSA *rsa) - { - CK_ULONG ul_sig_len = flen; - int retval = -1; - CK_RV rv; - CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; - CK_MECHANISM *p_mech = &mech_rsa; - CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; - PK11_SESSION *sp; - - if ((sp = pk11_get_session(OP_RSA)) == NULL) - return (-1); - - (void) pk11_check_new_rsa_key_priv(sp, rsa); - - h_priv_key = sp->opdata_rsa_priv_key; - if (h_priv_key == CK_INVALID_HANDLE) - h_priv_key = sp->opdata_rsa_priv_key = - pk11_get_private_rsa_key(rsa, sp); - - if (h_priv_key != CK_INVALID_HANDLE) - { - rv = pFuncList->C_SignInit(sp->session, p_mech, - h_priv_key); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW, - PK11_R_SIGNINIT, rv); - pk11_return_session(sp, OP_RSA); - return (-1); - } - - rv = pFuncList->C_Sign(sp->session, - (unsigned char *)from, flen, to, &ul_sig_len); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW, PK11_R_SIGN, - rv); - pk11_return_session(sp, OP_RSA); - return (-1); - } - - retval = ul_sig_len; - } - - pk11_return_session(sp, OP_RSA); - return (retval); - } - - -/* - * This function implements RSA private decryption using C_DecryptInit and - * C_Decrypt pk11 APIs. Note that CKM_RSA_X_509 mechanism is used here. - * The calling function allocated sufficient memory in "to" to store results. - */ -static int pk11_RSA_private_decrypt_low(int flen, - const unsigned char *from, unsigned char *to, RSA *rsa) - { - CK_ULONG bytes_decrypted = flen; - int retval = -1; - CK_RV rv; - CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; - CK_MECHANISM *p_mech = &mech_rsa; - CK_OBJECT_HANDLE h_priv_key; - PK11_SESSION *sp; - - if ((sp = pk11_get_session(OP_RSA)) == NULL) - return (-1); - - (void) pk11_check_new_rsa_key_priv(sp, rsa); - - h_priv_key = sp->opdata_rsa_priv_key; - if (h_priv_key == CK_INVALID_HANDLE) - h_priv_key = sp->opdata_rsa_priv_key = - pk11_get_private_rsa_key(rsa, sp); - - if (h_priv_key != CK_INVALID_HANDLE) - { - rv = pFuncList->C_DecryptInit(sp->session, p_mech, - h_priv_key); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW, - PK11_R_DECRYPTINIT, rv); - pk11_return_session(sp, OP_RSA); - return (-1); - } - - rv = pFuncList->C_Decrypt(sp->session, - (unsigned char *)from, flen, to, &bytes_decrypted); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW, - PK11_R_DECRYPT, rv); - pk11_return_session(sp, OP_RSA); - return (-1); - } - retval = bytes_decrypted; - } - - pk11_return_session(sp, OP_RSA); - return (retval); - } - - -/* - * This function implements RSA public decryption using C_VerifyRecoverInit - * and C_VerifyRecover pk11 APIs. Note that CKM_RSA_X_509 is used here. - * The calling function allocated sufficient memory in "to" to store results. - */ -static int pk11_RSA_public_decrypt_low(int flen, - const unsigned char *from, unsigned char *to, RSA *rsa) - { - CK_ULONG bytes_decrypted = flen; - int retval = -1; - CK_RV rv; - CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0}; - CK_MECHANISM *p_mech = &mech_rsa; - CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; - PK11_SESSION *sp; - - if ((sp = pk11_get_session(OP_RSA)) == NULL) - return (-1); - - (void) pk11_check_new_rsa_key_pub(sp, rsa); - - h_pub_key = sp->opdata_rsa_pub_key; - if (h_pub_key == CK_INVALID_HANDLE) - h_pub_key = sp->opdata_rsa_pub_key = - pk11_get_public_rsa_key(rsa, sp); - - if (h_pub_key != CK_INVALID_HANDLE) - { - rv = pFuncList->C_VerifyRecoverInit(sp->session, - p_mech, h_pub_key); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW, - PK11_R_VERIFYRECOVERINIT, rv); - pk11_return_session(sp, OP_RSA); - return (-1); - } - - rv = pFuncList->C_VerifyRecover(sp->session, - (unsigned char *)from, flen, to, &bytes_decrypted); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW, - PK11_R_VERIFYRECOVER, rv); - pk11_return_session(sp, OP_RSA); - return (-1); - } - retval = bytes_decrypted; - } - - pk11_return_session(sp, OP_RSA); - return (retval); - } - -static int pk11_RSA_init(RSA *rsa) - { - /* - * This flag in the RSA_METHOD enables the new rsa_sign, - * rsa_verify functions. See rsa.h for details. - */ - rsa->flags |= RSA_FLAG_SIGN_VER; - - return (1); - } - -static int pk11_RSA_finish(RSA *rsa) - { - /* - * Since we are overloading OpenSSL's native RSA_eay_finish() we need - * to do the same as in the original function, i.e. to free bignum - * structures. - */ - if (rsa->_method_mod_n != NULL) - BN_MONT_CTX_free(rsa->_method_mod_n); - if (rsa->_method_mod_p != NULL) - BN_MONT_CTX_free(rsa->_method_mod_p); - if (rsa->_method_mod_q != NULL) - BN_MONT_CTX_free(rsa->_method_mod_q); - - return (1); - } - -/* - * Standard engine interface function. Majority codes here are from - * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11. - * See more details in rsa/rsa_sign.c - */ -static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len, - unsigned char *sigret, unsigned int *siglen, const RSA *rsa) - { - X509_SIG sig; - ASN1_TYPE parameter; - int i, j; - unsigned char *p, *s = NULL; - X509_ALGOR algor; - ASN1_OCTET_STRING digest; - CK_RV rv; - CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0}; - CK_MECHANISM *p_mech = &mech_rsa; - CK_OBJECT_HANDLE h_priv_key; - PK11_SESSION *sp = NULL; - int ret = 0; - unsigned long ulsiglen; - - /* Encode the digest */ - /* Special case: SSL signature, just check the length */ - if (type == NID_md5_sha1) - { - if (m_len != SSL_SIG_LENGTH) - { - PK11err(PK11_F_RSA_SIGN, - PK11_R_INVALID_MESSAGE_LENGTH); - goto err; - } - i = SSL_SIG_LENGTH; - s = (unsigned char *)m; - } - else - { - sig.algor = &algor; - sig.algor->algorithm = OBJ_nid2obj(type); - if (sig.algor->algorithm == NULL) - { - PK11err(PK11_F_RSA_SIGN, - PK11_R_UNKNOWN_ALGORITHM_TYPE); - goto err; - } - if (sig.algor->algorithm->length == 0) - { - PK11err(PK11_F_RSA_SIGN, - PK11_R_UNKNOWN_ASN1_OBJECT_ID); - goto err; - } - parameter.type = V_ASN1_NULL; - parameter.value.ptr = NULL; - sig.algor->parameter = ¶meter; - - sig.digest = &digest; - sig.digest->data = (unsigned char *)m; - sig.digest->length = m_len; - - i = i2d_X509_SIG(&sig, NULL); - } - - j = RSA_size(rsa); - if ((i - RSA_PKCS1_PADDING) > j) - { - PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG); - goto err; - } - - if (type != NID_md5_sha1) - { - s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1)); - if (s == NULL) - { - PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE); - goto err; - } - p = s; - (void) i2d_X509_SIG(&sig, &p); - } - - if ((sp = pk11_get_session(OP_RSA)) == NULL) - goto err; - - (void) pk11_check_new_rsa_key_priv(sp, rsa); - - h_priv_key = sp->opdata_rsa_priv_key; - if (h_priv_key == CK_INVALID_HANDLE) - h_priv_key = sp->opdata_rsa_priv_key = - pk11_get_private_rsa_key((RSA *)rsa, sp); - - if (h_priv_key != CK_INVALID_HANDLE) - { - rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv); - goto err; - } - - ulsiglen = j; - rv = pFuncList->C_Sign(sp->session, s, i, sigret, - (CK_ULONG_PTR) &ulsiglen); - *siglen = ulsiglen; - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv); - goto err; - } - ret = 1; - } - -err: - if (type != NID_md5_sha1) - { - (void) memset(s, 0, (unsigned int)(j + 1)); - OPENSSL_free(s); - } - - pk11_return_session(sp, OP_RSA); - return (ret); - } - -static int pk11_RSA_verify(int type, const unsigned char *m, - unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, - const RSA *rsa) - { - X509_SIG sig; - ASN1_TYPE parameter; - int i, j; - unsigned char *p, *s = NULL; - X509_ALGOR algor; - ASN1_OCTET_STRING digest; - CK_RV rv; - CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0}; - CK_MECHANISM *p_mech = &mech_rsa; - CK_OBJECT_HANDLE h_pub_key; - PK11_SESSION *sp = NULL; - int ret = 0; - - /* Encode the digest */ - /* Special case: SSL signature, just check the length */ - if (type == NID_md5_sha1) - { - if (m_len != SSL_SIG_LENGTH) - { - PK11err(PK11_F_RSA_VERIFY, - PK11_R_INVALID_MESSAGE_LENGTH); - goto err; - } - i = SSL_SIG_LENGTH; - s = (unsigned char *)m; - } - else - { - sig.algor = &algor; - sig.algor->algorithm = OBJ_nid2obj(type); - if (sig.algor->algorithm == NULL) - { - PK11err(PK11_F_RSA_VERIFY, - PK11_R_UNKNOWN_ALGORITHM_TYPE); - goto err; - } - if (sig.algor->algorithm->length == 0) - { - PK11err(PK11_F_RSA_VERIFY, - PK11_R_UNKNOWN_ASN1_OBJECT_ID); - goto err; - } - parameter.type = V_ASN1_NULL; - parameter.value.ptr = NULL; - sig.algor->parameter = ¶meter; - sig.digest = &digest; - sig.digest->data = (unsigned char *)m; - sig.digest->length = m_len; - i = i2d_X509_SIG(&sig, NULL); - } - - j = RSA_size(rsa); - if ((i - RSA_PKCS1_PADDING) > j) - { - PK11err(PK11_F_RSA_VERIFY, PK11_R_DIGEST_TOO_BIG); - goto err; - } - - if (type != NID_md5_sha1) - { - s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1)); - if (s == NULL) - { - PK11err(PK11_F_RSA_VERIFY, PK11_R_MALLOC_FAILURE); - goto err; - } - p = s; - (void) i2d_X509_SIG(&sig, &p); - } - - if ((sp = pk11_get_session(OP_RSA)) == NULL) - goto err; - - (void) pk11_check_new_rsa_key_pub(sp, rsa); - - h_pub_key = sp->opdata_rsa_pub_key; - if (h_pub_key == CK_INVALID_HANDLE) - h_pub_key = sp->opdata_rsa_pub_key = - pk11_get_public_rsa_key((RSA *)rsa, sp); - - if (h_pub_key != CK_INVALID_HANDLE) - { - rv = pFuncList->C_VerifyInit(sp->session, p_mech, - h_pub_key); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFYINIT, - rv); - goto err; - } - rv = pFuncList->C_Verify(sp->session, s, i, sigbuf, - (CK_ULONG)siglen); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFY, rv); - goto err; - } - ret = 1; - } - -err: - if (type != NID_md5_sha1) - { - (void) memset(s, 0, (unsigned int)siglen); - OPENSSL_free(s); - } - - pk11_return_session(sp, OP_RSA); - return (ret); - } - -#define MAXATTR 1024 -/* - * Load RSA private key from a file or get its PKCS#11 handle if stored in the - * PKCS#11 token. - */ -/* ARGSUSED */ -EVP_PKEY *pk11_load_privkey(ENGINE* e, const char *privkey_id, - UI_METHOD *ui_method, void *callback_data) - { - EVP_PKEY *pkey = NULL; - FILE *privkey; - CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; - RSA *rsa = NULL; - PK11_SESSION *sp; - /* Anything else below is needed for the key by reference extension. */ - const char *file; - int ret; - pkcs11_uri uri_struct; - CK_RV rv; - CK_BBOOL is_token = CK_TRUE; - CK_BBOOL rollback = CK_FALSE; - CK_BYTE attr_data[8][MAXATTR]; - CK_OBJECT_CLASS key_class = CKO_PRIVATE_KEY; - CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ - - /* We look for private keys only. */ - CK_ATTRIBUTE search_templ[] = - { - {CKA_TOKEN, &is_token, sizeof (is_token)}, - {CKA_CLASS, &key_class, sizeof (key_class)}, - {CKA_LABEL, NULL, 0} - }; - - /* - * These public attributes are needed to initialize the OpenSSL RSA - * structure with something we can use to look up the key. Note that we - * never ask for private components. - */ - CK_ATTRIBUTE get_templ[] = - { - {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ - {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ - }; - - if ((sp = pk11_get_session(OP_RSA)) == NULL) - return (NULL); - - /* - * The next function will decide whether we are going to access keys in - * the token or read them from plain files. It all depends on what is in - * the 'privkey_id' parameter. - */ - ret = pk11_process_pkcs11_uri(privkey_id, &uri_struct, &file); - - if (ret == 0) - goto err; - - /* We will try to access a key from a PKCS#11 token. */ - if (ret == 1) - { - if (pk11_check_token_attrs(&uri_struct) == 0) - goto err; - - search_templ[2].pValue = uri_struct.object; - search_templ[2].ulValueLen = strlen(search_templ[2].pValue); - - if (pk11_token_login(sp->session, &pk11_login_done, - &uri_struct, CK_TRUE) == 0) - goto err; - - /* - * Now let's try to find the key in the token. It is a failure - * if we can't find it. - */ - if (find_one_object(OP_RSA, sp->session, search_templ, 3, - &ks_key) == 0) - goto err; - - /* - * Free the structure now. Note that we use uri_struct's field - * directly in the template so we cannot free it until the find - * is done. - */ - pk11_free_pkcs11_uri(&uri_struct, 0); - - /* - * We might have a cache hit which we could confirm according to - * the 'n'/'e' params, RSA public pointer as NULL, and non-NULL - * RSA private pointer. However, it is easier just to recreate - * everything. We expect the keys to be loaded once and used - * many times. We do not check the return value because even in - * case of failure the sp structure will have both key pointer - * and object handle cleaned and pk11_destroy_object() reports - * the failure to the OpenSSL error message buffer. - */ - (void) pk11_destroy_rsa_object_priv(sp, CK_TRUE); - - sp->opdata_rsa_priv_key = ks_key; - /* This object shall not be deleted on a cache miss. */ - sp->persistent = CK_TRUE; - - if ((rsa = sp->opdata_rsa_priv = RSA_new_method(e)) == NULL) - goto err; - - if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, - get_templ, 2)) != CKR_OK) - { - PK11err_add_data(PK11_F_LOAD_PRIVKEY, - PK11_R_GETATTRIBUTVALUE, rv); - goto err; - } - - /* - * Cache the RSA private structure pointer. We do not use it now - * for key-by-ref keys but let's do it for consistency reasons. - */ - sp->opdata_rsa_priv = rsa; - - /* - * We do not use pk11_get_private_rsa_key() here so we must take - * care of handle management ourselves. - */ - KEY_HANDLE_REFHOLD(ks_key, OP_RSA, CK_FALSE, rollback, err); - - /* - * Those are the sensitive components we do not want to export - * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp). - */ - attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); - attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); - /* - * Must have 'n'/'e' components in the session structure as - * well. They serve as a public look-up key for the private key - * in the keystore. - */ - attr_to_BN(&get_templ[0], attr_data[0], &sp->opdata_rsa_n_num); - attr_to_BN(&get_templ[1], attr_data[1], &sp->opdata_rsa_e_num); - - if ((pkey = EVP_PKEY_new()) == NULL) - goto err; - - if (EVP_PKEY_set1_RSA(pkey, rsa) == 0) - goto err; - } - else - if ((privkey = fopen(file, read_mode_flags)) != NULL) - { - pkey = PEM_read_PrivateKey(privkey, NULL, NULL, NULL); - (void) fclose(privkey); - if (pkey != NULL) - { - rsa = EVP_PKEY_get1_RSA(pkey); - if (rsa != NULL) - { - (void) pk11_check_new_rsa_key_priv(sp, - rsa); - - h_priv_key = sp->opdata_rsa_priv_key = - pk11_get_private_rsa_key(rsa, sp); - if (h_priv_key == CK_INVALID_HANDLE) - goto err; - } - else - goto err; - } - } - - pk11_return_session(sp, OP_RSA); - return (pkey); -err: - if (rsa != NULL) - RSA_free(rsa); - if (pkey != NULL) - { - EVP_PKEY_free(pkey); - pkey = NULL; - } - return (pkey); - } - -/* Load RSA public key from a file or load it from the PKCS#11 token. */ -/* ARGSUSED */ -EVP_PKEY *pk11_load_pubkey(ENGINE* e, const char *pubkey_id, - UI_METHOD *ui_method, void *callback_data) - { - EVP_PKEY *pkey = NULL; - FILE *pubkey; - CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; - RSA *rsa = NULL; - PK11_SESSION *sp; - /* everything else below needed for key by reference extension */ - int ret; - const char *file; - pkcs11_uri uri_struct; - CK_RV rv; - CK_BBOOL is_token = CK_TRUE; - CK_BYTE attr_data[2][MAXATTR]; - CK_OBJECT_CLASS key_class = CKO_PUBLIC_KEY; - CK_OBJECT_HANDLE ks_key = CK_INVALID_HANDLE; /* key in keystore */ - - CK_ATTRIBUTE search_templ[] = - { - {CKA_TOKEN, &is_token, sizeof (is_token)}, - {CKA_CLASS, &key_class, sizeof (key_class)}, - {CKA_LABEL, NULL, 0} - }; - - /* - * These public attributes are needed to initialize OpenSSL RSA - * structure with something we can use to look up the key. - */ - CK_ATTRIBUTE get_templ[] = - { - {CKA_MODULUS, (void *)attr_data[0], MAXATTR}, /* n */ - {CKA_PUBLIC_EXPONENT, (void *)attr_data[1], MAXATTR}, /* e */ - }; - - if ((sp = pk11_get_session(OP_RSA)) == NULL) - return (NULL); - - ret = pk11_process_pkcs11_uri(pubkey_id, &uri_struct, &file); - - if (ret == 0) - goto err; - - if (ret == 1) - { - if (pk11_check_token_attrs(&uri_struct) == 0) - goto err; - - search_templ[2].pValue = uri_struct.object; - search_templ[2].ulValueLen = strlen(search_templ[2].pValue); - - if (pk11_token_login(sp->session, &pk11_login_done, - &uri_struct, CK_FALSE) == 0) - goto err; - - if (find_one_object(OP_RSA, sp->session, search_templ, 3, - &ks_key) == 0) - { - goto err; - } - - /* - * Free the structure now. Note that we use uri_struct's field - * directly in the template so we can't free until find is done. - */ - pk11_free_pkcs11_uri(&uri_struct, 0); - /* - * We load a new public key so we will create a new RSA - * structure. No cache hit is possible. - */ - (void) pk11_destroy_rsa_object_pub(sp, CK_TRUE); - sp->opdata_rsa_pub_key = ks_key; - - if ((rsa = sp->opdata_rsa_pub = RSA_new_method(e)) == NULL) - goto err; - - if ((rv = pFuncList->C_GetAttributeValue(sp->session, ks_key, - get_templ, 2)) != CKR_OK) - { - PK11err_add_data(PK11_F_LOAD_PUBKEY, - PK11_R_GETATTRIBUTVALUE, rv); - goto err; - } - - /* - * Cache the RSA public structure pointer. - */ - sp->opdata_rsa_pub = rsa; - - /* - * These are the sensitive components we do not want to export - * from the token at all: rsa->(d|p|q|dmp1|dmq1|iqmp). - */ - attr_to_BN(&get_templ[0], attr_data[0], &rsa->n); - attr_to_BN(&get_templ[1], attr_data[1], &rsa->e); - - if ((pkey = EVP_PKEY_new()) == NULL) - goto err; - - if (EVP_PKEY_set1_RSA(pkey, rsa) == 0) - goto err; - - /* - * Create a session object from it so that when calling - * pk11_get_public_rsa_key() the next time, we can find it. The - * reason why we do that is that we cannot tell from the RSA - * structure (OpenSSL RSA structure does not have any room for - * additional data used by the engine, for example) if it bears - * a public key stored in the keystore or not so it's better if - * we always have a session key. Note that this is different - * from what we do for the private keystore objects but in that - * case, we can tell from the RSA structure that the keystore - * object is in play - the 'd' component is NULL in that case. - */ - h_pub_key = sp->opdata_rsa_pub_key = - pk11_get_public_rsa_key(rsa, sp); - if (h_pub_key == CK_INVALID_HANDLE) - goto err; - } - else - if ((pubkey = fopen(file, read_mode_flags)) != NULL) - { - pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL); - (void) fclose(pubkey); - if (pkey != NULL) - { - rsa = EVP_PKEY_get1_RSA(pkey); - if (rsa != NULL) - { - /* - * This will always destroy the RSA - * object since we have a new RSA - * structure here. - */ - (void) pk11_check_new_rsa_key_pub(sp, - rsa); - - h_pub_key = sp->opdata_rsa_pub_key = - pk11_get_public_rsa_key(rsa, sp); - if (h_pub_key == CK_INVALID_HANDLE) - { - EVP_PKEY_free(pkey); - pkey = NULL; - } - } - else - { - EVP_PKEY_free(pkey); - pkey = NULL; - } - } - } - - pk11_return_session(sp, OP_RSA); - return (pkey); -err: - if (rsa != NULL) - RSA_free(rsa); - if (pkey != NULL) - { - EVP_PKEY_free(pkey); - pkey = NULL; - } - return (pkey); - } - -/* - * Get a public key object in a session from a given rsa structure. If the - * PKCS#11 session object already exists it is found, reused, and - * the counter in the active object list incremented. If not found, a new - * session object is created and put also onto the active object list. - * - * We use the session field from sp, and we cache rsa->(n|e) in - * opdata_rsa_(n|e|d)_num, respectively. - */ -static CK_OBJECT_HANDLE -pk11_get_public_rsa_key(RSA* rsa, PK11_SESSION *sp) - { - CK_RV rv; - CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; - CK_ULONG found; - CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY; - CK_KEY_TYPE k_type = CKK_RSA; - CK_ULONG ul_key_attr_count = 7; - CK_BBOOL rollback = CK_FALSE; - - CK_ATTRIBUTE a_key_template[] = - { - {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, - {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, - {CKA_TOKEN, &pk11_false, sizeof (pk11_false)}, - {CKA_ENCRYPT, &pk11_true, sizeof (pk11_true)}, - {CKA_VERIFY_RECOVER, &pk11_true, sizeof (pk11_true)}, - {CKA_MODULUS, (void *)NULL, 0}, - {CKA_PUBLIC_EXPONENT, (void *)NULL, 0} - }; - - int i; - - a_key_template[0].pValue = &o_key; - a_key_template[1].pValue = &k_type; - - a_key_template[5].ulValueLen = BN_num_bytes(rsa->n); - a_key_template[5].pValue = (CK_VOID_PTR)OPENSSL_malloc( - (size_t)a_key_template[5].ulValueLen); - if (a_key_template[5].pValue == NULL) - { - PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); - goto malloc_err; - } - - BN_bn2bin(rsa->n, a_key_template[5].pValue); - - a_key_template[6].ulValueLen = BN_num_bytes(rsa->e); - a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc( - (size_t)a_key_template[6].ulValueLen); - if (a_key_template[6].pValue == NULL) - { - PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); - goto malloc_err; - } - - BN_bn2bin(rsa->e, a_key_template[6].pValue); - - /* see find_lock array definition for more info on object locking */ - LOCK_OBJSTORE(OP_RSA); - - rv = pFuncList->C_FindObjectsInit(sp->session, a_key_template, - ul_key_attr_count); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, - PK11_R_FINDOBJECTSINIT, rv); - goto err; - } - - rv = pFuncList->C_FindObjects(sp->session, &h_key, 1, &found); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, - PK11_R_FINDOBJECTS, rv); - goto err; - } - - rv = pFuncList->C_FindObjectsFinal(sp->session); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, - PK11_R_FINDOBJECTSFINAL, rv); - goto err; - } - - if (found == 0) - { - rv = pFuncList->C_CreateObject(sp->session, - a_key_template, ul_key_attr_count, &h_key); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, - PK11_R_CREATEOBJECT, rv); - goto err; - } - } - - if ((sp->opdata_rsa_n_num = BN_dup(rsa->n)) == NULL) - { - PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); - rollback = CK_TRUE; - goto err; - } - - if ((sp->opdata_rsa_e_num = BN_dup(rsa->e)) == NULL) - { - PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); - BN_free(sp->opdata_rsa_n_num); - sp->opdata_rsa_n_num = NULL; - rollback = CK_TRUE; - goto err; - } - - /* LINTED: E_CONSTANT_CONDITION */ - KEY_HANDLE_REFHOLD(h_key, OP_RSA, CK_FALSE, rollback, err); - sp->opdata_rsa_pub = rsa; - -err: - if (rollback) - { - /* - * We do not care about the return value from C_DestroyObject() - * since we are doing rollback. - */ - if (found == 0) - (void) pFuncList->C_DestroyObject(sp->session, h_key); - h_key = CK_INVALID_HANDLE; - } - - UNLOCK_OBJSTORE(OP_RSA); - -malloc_err: - for (i = 5; i <= 6; i++) - { - if (a_key_template[i].pValue != NULL) - { - OPENSSL_free(a_key_template[i].pValue); - a_key_template[i].pValue = NULL; - } - } - - return (h_key); - } - -/* - * Function similar to pk11_get_public_rsa_key(). In addition to 'n' and 'e' - * components, it also caches 'd' if present. Note that if RSA keys by reference - * are used, 'd' is never extracted from the token in which case it would be - * NULL here. - */ -static CK_OBJECT_HANDLE -pk11_get_private_rsa_key(RSA* rsa, PK11_SESSION *sp) - { - CK_RV rv; - CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; - int i; - CK_ULONG found; - CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY; - CK_KEY_TYPE k_type = CKK_RSA; - CK_ULONG ul_key_attr_count = 14; - CK_BBOOL rollback = CK_FALSE; - - /* - * Both CKA_TOKEN and CKA_SENSITIVE have to be CK_FALSE for session keys - */ - CK_ATTRIBUTE a_key_template[] = - { - {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, - {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, - {CKA_TOKEN, &pk11_false, sizeof (pk11_false)}, - {CKA_SENSITIVE, &pk11_false, sizeof (pk11_false)}, - {CKA_DECRYPT, &pk11_true, sizeof (pk11_true)}, - {CKA_SIGN, &pk11_true, sizeof (pk11_true)}, - {CKA_MODULUS, (void *)NULL, 0}, - {CKA_PUBLIC_EXPONENT, (void *)NULL, 0}, - {CKA_PRIVATE_EXPONENT, (void *)NULL, 0}, - {CKA_PRIME_1, (void *)NULL, 0}, - {CKA_PRIME_2, (void *)NULL, 0}, - {CKA_EXPONENT_1, (void *)NULL, 0}, - {CKA_EXPONENT_2, (void *)NULL, 0}, - {CKA_COEFFICIENT, (void *)NULL, 0}, - }; - - a_key_template[0].pValue = &o_key; - a_key_template[1].pValue = &k_type; - - /* Put the private key components into the template */ - if (init_template_value(rsa->n, &a_key_template[6].pValue, - &a_key_template[6].ulValueLen) == 0 || - init_template_value(rsa->e, &a_key_template[7].pValue, - &a_key_template[7].ulValueLen) == 0 || - init_template_value(rsa->d, &a_key_template[8].pValue, - &a_key_template[8].ulValueLen) == 0 || - init_template_value(rsa->p, &a_key_template[9].pValue, - &a_key_template[9].ulValueLen) == 0 || - init_template_value(rsa->q, &a_key_template[10].pValue, - &a_key_template[10].ulValueLen) == 0 || - init_template_value(rsa->dmp1, &a_key_template[11].pValue, - &a_key_template[11].ulValueLen) == 0 || - init_template_value(rsa->dmq1, &a_key_template[12].pValue, - &a_key_template[12].ulValueLen) == 0 || - init_template_value(rsa->iqmp, &a_key_template[13].pValue, - &a_key_template[13].ulValueLen) == 0) - { - PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); - goto malloc_err; - } - - /* see find_lock array definition for more info on object locking */ - LOCK_OBJSTORE(OP_RSA); - - /* - * We are getting the private key but the private 'd' component is NULL. - * That means this is key by reference RSA key. In that case, we can - * use only public components for searching for the private key handle. - */ - if (rsa->d == NULL) - { - ul_key_attr_count = 8; - /* - * We will perform the search in the token, not in the existing - * session keys. - */ - a_key_template[2].pValue = &pk11_true; - } - - rv = pFuncList->C_FindObjectsInit(sp->session, a_key_template, - ul_key_attr_count); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, - PK11_R_FINDOBJECTSINIT, rv); - goto err; - } - - rv = pFuncList->C_FindObjects(sp->session, &h_key, 1, &found); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, - PK11_R_FINDOBJECTS, rv); - goto err; - } - - rv = pFuncList->C_FindObjectsFinal(sp->session); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, - PK11_R_FINDOBJECTSFINAL, rv); - goto err; - } - - if (found == 0) - { - /* - * We have an RSA structure with 'n'/'e' components only so we - * tried to find the private key in the keystore. If it was - * really a token key we have a problem. Note that for other key - * types we just create a new session key using the private - * components from the RSA structure. - */ - if (rsa->d == NULL) - { - PK11err(PK11_F_GET_PRIV_RSA_KEY, - PK11_R_PRIV_KEY_NOT_FOUND); - goto err; - } - - rv = pFuncList->C_CreateObject(sp->session, - a_key_template, ul_key_attr_count, &h_key); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY, - PK11_R_CREATEOBJECT, rv); - goto err; - } - } - - /* - * When RSA keys by reference code is used, we never extract private - * components from the keystore. In that case 'd' was set to NULL and we - * expect the application to properly cope with that. It is documented - * in openssl(5). In general, if keys by reference are used we expect it - * to be used exclusively using the high level API and then there is no - * problem. If the application expects the private components to be read - * from the keystore then that is not a supported way of usage. - */ - if (rsa->d != NULL) - { - if ((sp->opdata_rsa_d_num = BN_dup(rsa->d)) == NULL) - { - PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE); - rollback = CK_TRUE; - goto err; - } - } - else - sp->opdata_rsa_d_num = NULL; - - /* - * For the key by reference code, we need public components as well - * since 'd' component is always NULL. For that reason, we always cache - * 'n'/'e' components as well. - */ - if ((sp->opdata_rsa_n_num = BN_dup(rsa->n)) == NULL) - { - PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); - sp->opdata_rsa_n_num = NULL; - rollback = CK_TRUE; - goto err; - } - if ((sp->opdata_rsa_e_num = BN_dup(rsa->e)) == NULL) - { - PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE); - BN_free(sp->opdata_rsa_n_num); - sp->opdata_rsa_n_num = NULL; - rollback = CK_TRUE; - goto err; - } - - /* LINTED: E_CONSTANT_CONDITION */ - KEY_HANDLE_REFHOLD(h_key, OP_RSA, CK_FALSE, rollback, err); - sp->opdata_rsa_priv = rsa; - -err: - if (rollback) - { - /* - * We do not care about the return value from C_DestroyObject() - * since we are doing rollback. - */ - if (found == 0) - (void) pFuncList->C_DestroyObject(sp->session, h_key); - h_key = CK_INVALID_HANDLE; - } - - UNLOCK_OBJSTORE(OP_RSA); - -malloc_err: - /* - * 6 to 13 entries in the key template are key components. - * They need to be freed upon exit or error. - */ - for (i = 6; i <= 13; i++) - { - if (a_key_template[i].pValue != NULL) - { - (void) memset(a_key_template[i].pValue, 0, - a_key_template[i].ulValueLen); - OPENSSL_free(a_key_template[i].pValue); - a_key_template[i].pValue = NULL; - } - } - - return (h_key); - } - -/* - * Check for cache miss. Objects are cleaned only if we have a full cache miss, - * meaning that it's a different RSA key pair. Return 1 for cache hit, 0 for - * cache miss. - */ -static int -pk11_check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa) - { - /* - * Provide protection against RSA structure reuse by making the - * check for cache hit stronger. Only public components of RSA - * key matter here so it is sufficient to compare them with values - * cached in PK11_SESSION structure. - * - * We must check the handle as well since with key by reference, public - * components 'n'/'e' are cached in private keys as well. That means we - * could have a cache hit in a private key when looking for a public - * key. That would not work, you cannot have one PKCS#11 object for - * both data signing and verifying. - */ - if (sp->opdata_rsa_pub == rsa && - BN_cmp(sp->opdata_rsa_n_num, rsa->n) == 0 && - BN_cmp(sp->opdata_rsa_e_num, rsa->e) == 0) - { - if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE) - return (1); - else - /* - * No public key object yet but we have the right RSA - * structure with potentially existing private key - * object. We can just create a public object and move - * on with this session structure. - */ - return (0); - } - - /* - * A different RSA key pair was using this session structure previously - * or it's an empty structure. Destroy what we can. - */ - (void) pk11_destroy_rsa_object_pub(sp, CK_TRUE); - (void) pk11_destroy_rsa_object_priv(sp, CK_TRUE); - return (0); - } - -/* - * Check for cache miss. Objects are cleaned only if we have a full cache miss, - * meaning that it's a different RSA key pair. Return 1 for cache hit, 0 for - * cache miss. - */ -static int -pk11_check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa) - { - /* - * Provide protection against RSA structure reuse by making the - * check for cache hit stronger. Comparing public exponent of RSA - * key with value cached in PK11_SESSION structure should - * be sufficient. Note that we want to compare the public component - * since with the keys by reference mechanism, private components are - * not in the RSA structure. Also, see pk11_check_new_rsa_key_pub() - * about why we compare the handle as well. - */ - if (sp->opdata_rsa_priv == rsa && - BN_cmp(sp->opdata_rsa_n_num, rsa->n) == 0 && - BN_cmp(sp->opdata_rsa_e_num, rsa->e) == 0) - { - if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE) - return (1); - else - /* - * No private key object yet but we have the right RSA - * structure with potentially existing public key - * object. We can just create a private object and move - * on with this session structure. - */ - return (0); - } - - /* - * A different RSA key pair was using this session structure previously - * or it's an empty structure. Destroy what we can. - */ - (void) pk11_destroy_rsa_object_priv(sp, CK_TRUE); - (void) pk11_destroy_rsa_object_pub(sp, CK_TRUE); - return (0); - } -#endif - -#ifndef OPENSSL_NO_DSA -/* The DSA function implementation */ -/* ARGSUSED */ -static int pk11_DSA_init(DSA *dsa) - { - return (1); - } - -/* ARGSUSED */ -static int pk11_DSA_finish(DSA *dsa) - { - return (1); - } - - -static DSA_SIG * -pk11_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) - { - BIGNUM *r = NULL, *s = NULL; - int i; - DSA_SIG *dsa_sig = NULL; - - CK_RV rv; - CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0}; - CK_MECHANISM *p_mech = &Mechanism_dsa; - CK_OBJECT_HANDLE h_priv_key; - - /* - * The signature is the concatenation of r and s, - * each is 20 bytes long - */ - unsigned char sigret[DSA_SIGNATURE_LEN]; - unsigned long siglen = DSA_SIGNATURE_LEN; - unsigned int siglen2 = DSA_SIGNATURE_LEN / 2; - - PK11_SESSION *sp = NULL; - - if ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL)) - { - PK11err(PK11_F_DSA_SIGN, PK11_R_MISSING_KEY_COMPONENT); - goto ret; - } - - i = BN_num_bytes(dsa->q); /* should be 20 */ - if (dlen > i) - { - PK11err(PK11_F_DSA_SIGN, PK11_R_INVALID_SIGNATURE_LENGTH); - goto ret; - } - - if ((sp = pk11_get_session(OP_DSA)) == NULL) - goto ret; - - (void) check_new_dsa_key_priv(sp, dsa); - - h_priv_key = sp->opdata_dsa_priv_key; - if (h_priv_key == CK_INVALID_HANDLE) - h_priv_key = sp->opdata_dsa_priv_key = - pk11_get_private_dsa_key((DSA *)dsa, - &sp->opdata_dsa_priv, - &sp->opdata_dsa_priv_num, sp->session); - - if (h_priv_key != CK_INVALID_HANDLE) - { - rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGNINIT, rv); - goto ret; - } - - (void) memset(sigret, 0, siglen); - rv = pFuncList->C_Sign(sp->session, - (unsigned char *) dgst, dlen, sigret, - (CK_ULONG_PTR) &siglen); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGN, rv); - goto ret; - } - } - - - if ((s = BN_new()) == NULL) - { - PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); - goto ret; - } - - if ((r = BN_new()) == NULL) - { - PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); - goto ret; - } - - if ((dsa_sig = DSA_SIG_new()) == NULL) - { - PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); - goto ret; - } - - if (BN_bin2bn(sigret, siglen2, r) == NULL || - BN_bin2bn(&sigret[siglen2], siglen2, s) == NULL) - { - PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE); - goto ret; - } - - dsa_sig->r = r; - dsa_sig->s = s; - -ret: - if (dsa_sig == NULL) - { - if (r != NULL) - BN_free(r); - if (s != NULL) - BN_free(s); - } - - pk11_return_session(sp, OP_DSA); - return (dsa_sig); - } - -static int -pk11_dsa_do_verify(const unsigned char *dgst, int dlen, DSA_SIG *sig, - DSA *dsa) - { - int i; - CK_RV rv; - int retval = 0; - CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0}; - CK_MECHANISM *p_mech = &Mechanism_dsa; - CK_OBJECT_HANDLE h_pub_key; - - unsigned char sigbuf[DSA_SIGNATURE_LEN]; - unsigned long siglen = DSA_SIGNATURE_LEN; - unsigned long siglen2 = DSA_SIGNATURE_LEN/2; - - PK11_SESSION *sp = NULL; - - if (BN_is_zero(sig->r) || sig->r->neg || BN_ucmp(sig->r, dsa->q) >= 0) - { - PK11err(PK11_F_DSA_VERIFY, - PK11_R_INVALID_DSA_SIGNATURE_R); - goto ret; - } - - if (BN_is_zero(sig->s) || sig->s->neg || BN_ucmp(sig->s, dsa->q) >= 0) - { - PK11err(PK11_F_DSA_VERIFY, - PK11_R_INVALID_DSA_SIGNATURE_S); - goto ret; - } - - i = BN_num_bytes(dsa->q); /* should be 20 */ - - if (dlen > i) - { - PK11err(PK11_F_DSA_VERIFY, - PK11_R_INVALID_SIGNATURE_LENGTH); - goto ret; - } - - if ((sp = pk11_get_session(OP_DSA)) == NULL) - goto ret; - - (void) check_new_dsa_key_pub(sp, dsa); - - h_pub_key = sp->opdata_dsa_pub_key; - if (h_pub_key == CK_INVALID_HANDLE) - h_pub_key = sp->opdata_dsa_pub_key = - pk11_get_public_dsa_key((DSA *)dsa, &sp->opdata_dsa_pub, - &sp->opdata_dsa_pub_num, sp->session); - - if (h_pub_key != CK_INVALID_HANDLE) - { - rv = pFuncList->C_VerifyInit(sp->session, p_mech, - h_pub_key); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFYINIT, - rv); - goto ret; - } - - /* - * The representation of each of the two big numbers could - * be shorter than DSA_SIGNATURE_LEN/2 bytes so we need - * to act accordingly and shift if necessary. - */ - (void) memset(sigbuf, 0, siglen); - BN_bn2bin(sig->r, sigbuf + siglen2 - BN_num_bytes(sig->r)); - BN_bn2bin(sig->s, &sigbuf[siglen2] + siglen2 - - BN_num_bytes(sig->s)); - - rv = pFuncList->C_Verify(sp->session, - (unsigned char *) dgst, dlen, sigbuf, (CK_ULONG)siglen); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFY, rv); - goto ret; - } - } - - retval = 1; -ret: - - pk11_return_session(sp, OP_DSA); - return (retval); - } - - -/* - * Create a public key object in a session from a given dsa structure. - * The *dsa_pub_num pointer is non-NULL for DSA public keys. - */ -static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa, - DSA **key_ptr, BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session) - { - CK_RV rv; - CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY; - CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; - CK_ULONG found; - CK_KEY_TYPE k_type = CKK_DSA; - CK_ULONG ul_key_attr_count = 8; - CK_BBOOL rollback = CK_FALSE; - int i; - - CK_ATTRIBUTE a_key_template[] = - { - {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, - {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, - {CKA_TOKEN, &pk11_false, sizeof (pk11_false)}, - {CKA_VERIFY, &pk11_true, sizeof (pk11_true)}, - {CKA_PRIME, (void *)NULL, 0}, /* p */ - {CKA_SUBPRIME, (void *)NULL, 0}, /* q */ - {CKA_BASE, (void *)NULL, 0}, /* g */ - {CKA_VALUE, (void *)NULL, 0} /* pub_key - y */ - }; - - a_key_template[0].pValue = &o_key; - a_key_template[1].pValue = &k_type; - - if (init_template_value(dsa->p, &a_key_template[4].pValue, - &a_key_template[4].ulValueLen) == 0 || - init_template_value(dsa->q, &a_key_template[5].pValue, - &a_key_template[5].ulValueLen) == 0 || - init_template_value(dsa->g, &a_key_template[6].pValue, - &a_key_template[6].ulValueLen) == 0 || - init_template_value(dsa->pub_key, &a_key_template[7].pValue, - &a_key_template[7].ulValueLen) == 0) - { - PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE); - goto malloc_err; - } - - /* see find_lock array definition for more info on object locking */ - LOCK_OBJSTORE(OP_DSA); - rv = pFuncList->C_FindObjectsInit(session, a_key_template, - ul_key_attr_count); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, - PK11_R_FINDOBJECTSINIT, rv); - goto err; - } - - rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, - PK11_R_FINDOBJECTS, rv); - goto err; - } - - rv = pFuncList->C_FindObjectsFinal(session); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, - PK11_R_FINDOBJECTSFINAL, rv); - goto err; - } - - if (found == 0) - { - rv = pFuncList->C_CreateObject(session, - a_key_template, ul_key_attr_count, &h_key); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, - PK11_R_CREATEOBJECT, rv); - goto err; - } - } - - if (dsa_pub_num != NULL) - if ((*dsa_pub_num = BN_dup(dsa->pub_key)) == NULL) - { - PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE); - rollback = CK_TRUE; - goto err; - } - - /* LINTED: E_CONSTANT_CONDITION */ - KEY_HANDLE_REFHOLD(h_key, OP_DSA, CK_FALSE, rollback, err); - if (key_ptr != NULL) - *key_ptr = dsa; - -err: - if (rollback) - { - /* - * We do not care about the return value from C_DestroyObject() - * since we are doing rollback. - */ - if (found == 0) - (void) pFuncList->C_DestroyObject(session, h_key); - h_key = CK_INVALID_HANDLE; - } - - UNLOCK_OBJSTORE(OP_DSA); - -malloc_err: - for (i = 4; i <= 7; i++) - { - if (a_key_template[i].pValue != NULL) - { - OPENSSL_free(a_key_template[i].pValue); - a_key_template[i].pValue = NULL; - } - } - - return (h_key); - } - -/* - * Create a private key object in the session from a given dsa structure - * The *dsa_priv_num pointer is non-NULL for DSA private keys. - */ -static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa, - DSA **key_ptr, BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session) - { - CK_RV rv; - CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; - CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY; - int i; - CK_ULONG found; - CK_KEY_TYPE k_type = CKK_DSA; - CK_ULONG ul_key_attr_count = 9; - CK_BBOOL rollback = CK_FALSE; - - /* - * Both CKA_TOKEN and CKA_SENSITIVE have to be CK_FALSE for session keys - */ - CK_ATTRIBUTE a_key_template[] = - { - {CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)}, - {CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)}, - {CKA_TOKEN, &pk11_false, sizeof (pk11_false)}, - {CKA_SENSITIVE, &pk11_false, sizeof (pk11_false)}, - {CKA_SIGN, &pk11_true, sizeof (pk11_true)}, - {CKA_PRIME, (void *)NULL, 0}, /* p */ - {CKA_SUBPRIME, (void *)NULL, 0}, /* q */ - {CKA_BASE, (void *)NULL, 0}, /* g */ - {CKA_VALUE, (void *)NULL, 0} /* priv_key - x */ - }; - - a_key_template[0].pValue = &o_key; - a_key_template[1].pValue = &k_type; - - /* Put the private key components into the template */ - if (init_template_value(dsa->p, &a_key_template[5].pValue, - &a_key_template[5].ulValueLen) == 0 || - init_template_value(dsa->q, &a_key_template[6].pValue, - &a_key_template[6].ulValueLen) == 0 || - init_template_value(dsa->g, &a_key_template[7].pValue, - &a_key_template[7].ulValueLen) == 0 || - init_template_value(dsa->priv_key, &a_key_template[8].pValue, - &a_key_template[8].ulValueLen) == 0) - { - PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE); - goto malloc_err; - } - - /* see find_lock array definition for more info on object locking */ - LOCK_OBJSTORE(OP_DSA); - rv = pFuncList->C_FindObjectsInit(session, a_key_template, - ul_key_attr_count); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, - PK11_R_FINDOBJECTSINIT, rv); - goto err; - } - - rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, - PK11_R_FINDOBJECTS, rv); - goto err; - } - - rv = pFuncList->C_FindObjectsFinal(session); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, - PK11_R_FINDOBJECTSFINAL, rv); - goto err; - } - - if (found == 0) - { - rv = pFuncList->C_CreateObject(session, - a_key_template, ul_key_attr_count, &h_key); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY, - PK11_R_CREATEOBJECT, rv); - goto err; - } - } - - if (dsa_priv_num != NULL) - if ((*dsa_priv_num = BN_dup(dsa->priv_key)) == NULL) - { - PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE); - rollback = CK_TRUE; - goto err; - } - - /* LINTED: E_CONSTANT_CONDITION */ - KEY_HANDLE_REFHOLD(h_key, OP_DSA, CK_FALSE, rollback, err); - if (key_ptr != NULL) - *key_ptr = dsa; - -err: - if (rollback) - { - /* - * We do not care about the return value from C_DestroyObject() - * since we are doing rollback. - */ - if (found == 0) - (void) pFuncList->C_DestroyObject(session, h_key); - h_key = CK_INVALID_HANDLE; - } - - UNLOCK_OBJSTORE(OP_DSA); - -malloc_err: - /* - * 5 to 8 entries in the key template are key components. - * They need to be freed apon exit or error. - */ - for (i = 5; i <= 8; i++) - { - if (a_key_template[i].pValue != NULL) - { - (void) memset(a_key_template[i].pValue, 0, - a_key_template[i].ulValueLen); - OPENSSL_free(a_key_template[i].pValue); - a_key_template[i].pValue = NULL; - } - } - - return (h_key); - } - -/* - * Check for cache miss and clean the object pointer and handle - * in such case. Return 1 for cache hit, 0 for cache miss. - */ -static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa) - { - /* - * Provide protection against DSA structure reuse by making the - * check for cache hit stronger. Only public key component of DSA - * key matters here so it is sufficient to compare it with value - * cached in PK11_SESSION structure. - */ - if ((sp->opdata_dsa_pub != dsa) || - (BN_cmp(sp->opdata_dsa_pub_num, dsa->pub_key) != 0)) - { - /* - * We do not check the return value because even in case of - * failure the sp structure will have both key pointer - * and object handle cleaned and pk11_destroy_object() - * reports the failure to the OpenSSL error message buffer. - */ - (void) pk11_destroy_dsa_object_pub(sp, CK_TRUE); - return (0); - } - return (1); - } - -/* - * Check for cache miss and clean the object pointer and handle - * in such case. Return 1 for cache hit, 0 for cache miss. - */ -static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa) - { - /* - * Provide protection against DSA structure reuse by making the - * check for cache hit stronger. Only private key component of DSA - * key matters here so it is sufficient to compare it with value - * cached in PK11_SESSION structure. - */ - if ((sp->opdata_dsa_priv != dsa) || - (BN_cmp(sp->opdata_dsa_priv_num, dsa->priv_key) != 0)) - { - /* - * We do not check the return value because even in case of - * failure the sp structure will have both key pointer - * and object handle cleaned and pk11_destroy_object() - * reports the failure to the OpenSSL error message buffer. - */ - (void) pk11_destroy_dsa_object_priv(sp, CK_TRUE); - return (0); - } - return (1); - } -#endif - - -#ifndef OPENSSL_NO_DH -/* The DH function implementation */ -/* ARGSUSED */ -static int pk11_DH_init(DH *dh) - { - return (1); - } - -/* ARGSUSED */ -static int pk11_DH_finish(DH *dh) - { - return (1); - } - -/* - * Generate DH key-pair. - * - * Warning: Unlike OpenSSL's DH_generate_key(3) we ignore dh->priv_key - * and override it even if it is set. OpenSSL does not touch dh->priv_key - * if set and just computes dh->pub_key. It looks like PKCS#11 standard - * is not capable of providing this functionality. This could be a problem - * for applications relying on OpenSSL's semantics. - */ -static int pk11_DH_generate_key(DH *dh) - { - CK_ULONG i; - CK_RV rv, rv1; - int reuse_mem_len = 0, ret = 0; - PK11_SESSION *sp = NULL; - CK_BYTE_PTR reuse_mem; - - CK_MECHANISM mechanism = {CKM_DH_PKCS_KEY_PAIR_GEN, NULL_PTR, 0}; - CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE; - CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE; - - CK_ULONG ul_pub_key_attr_count = 3; - CK_ATTRIBUTE pub_key_template[] = - { - {CKA_PRIVATE, &pk11_false, sizeof (pk11_false)}, - {CKA_PRIME, (void *)NULL, 0}, - {CKA_BASE, (void *)NULL, 0} - }; - - CK_ULONG ul_priv_key_attr_count = 3; - CK_ATTRIBUTE priv_key_template[] = - { - {CKA_PRIVATE, &pk11_false, sizeof (pk11_false)}, - {CKA_SENSITIVE, &pk11_false, sizeof (pk11_false)}, - {CKA_DERIVE, &pk11_true, sizeof (pk11_true)} - }; - - CK_ULONG pub_key_attr_result_count = 1; - CK_ATTRIBUTE pub_key_result[] = - { - {CKA_VALUE, (void *)NULL, 0} - }; - - CK_ULONG priv_key_attr_result_count = 1; - CK_ATTRIBUTE priv_key_result[] = - { - {CKA_VALUE, (void *)NULL, 0} - }; - - pub_key_template[1].ulValueLen = BN_num_bytes(dh->p); - if (pub_key_template[1].ulValueLen > 0) - { - /* - * We must not increase ulValueLen by DH_BUF_RESERVE since that - * could cause the same rounding problem. See definition of - * DH_BUF_RESERVE above. - */ - pub_key_template[1].pValue = - OPENSSL_malloc(pub_key_template[1].ulValueLen + - DH_BUF_RESERVE); - if (pub_key_template[1].pValue == NULL) - { - PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); - goto err; - } - - i = BN_bn2bin(dh->p, pub_key_template[1].pValue); - } - else - goto err; - - pub_key_template[2].ulValueLen = BN_num_bytes(dh->g); - if (pub_key_template[2].ulValueLen > 0) - { - pub_key_template[2].pValue = - OPENSSL_malloc(pub_key_template[2].ulValueLen + - DH_BUF_RESERVE); - if (pub_key_template[2].pValue == NULL) - { - PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); - goto err; - } - - i = BN_bn2bin(dh->g, pub_key_template[2].pValue); - } - else - goto err; - - /* - * Note: we are only using PK11_SESSION structure for getting - * a session handle. The objects created in this function are - * destroyed before return and thus not cached. - */ - if ((sp = pk11_get_session(OP_DH)) == NULL) - goto err; - - rv = pFuncList->C_GenerateKeyPair(sp->session, - &mechanism, - pub_key_template, - ul_pub_key_attr_count, - priv_key_template, - ul_priv_key_attr_count, - &h_pub_key, - &h_priv_key); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DH_GEN_KEY, PK11_R_GEN_KEY, rv); - goto err; - } - - /* - * Reuse the larger memory allocated. We know the larger memory - * should be sufficient for reuse. - */ - if (pub_key_template[1].ulValueLen > pub_key_template[2].ulValueLen) - { - reuse_mem = pub_key_template[1].pValue; - reuse_mem_len = pub_key_template[1].ulValueLen + DH_BUF_RESERVE; - } - else - { - reuse_mem = pub_key_template[2].pValue; - reuse_mem_len = pub_key_template[2].ulValueLen + DH_BUF_RESERVE; - } - - rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key, - pub_key_result, pub_key_attr_result_count); - rv1 = pFuncList->C_GetAttributeValue(sp->session, h_priv_key, - priv_key_result, priv_key_attr_result_count); - - if (rv != CKR_OK || rv1 != CKR_OK) - { - rv = (rv != CKR_OK) ? rv : rv1; - PK11err_add_data(PK11_F_DH_GEN_KEY, - PK11_R_GETATTRIBUTVALUE, rv); - goto err; - } - - if (((CK_LONG) pub_key_result[0].ulValueLen) <= 0 || - ((CK_LONG) priv_key_result[0].ulValueLen) <= 0) - { - PK11err(PK11_F_DH_GEN_KEY, PK11_R_GETATTRIBUTVALUE); - goto err; - } - - /* Reuse the memory allocated */ - pub_key_result[0].pValue = reuse_mem; - pub_key_result[0].ulValueLen = reuse_mem_len; - - rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key, - pub_key_result, pub_key_attr_result_count); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DH_GEN_KEY, - PK11_R_GETATTRIBUTVALUE, rv); - goto err; - } - - if (pub_key_result[0].type == CKA_VALUE) - { - if (dh->pub_key == NULL) - if ((dh->pub_key = BN_new()) == NULL) - { - PK11err(PK11_F_DH_GEN_KEY, - PK11_R_MALLOC_FAILURE); - goto err; - } - dh->pub_key = BN_bin2bn(pub_key_result[0].pValue, - pub_key_result[0].ulValueLen, dh->pub_key); - if (dh->pub_key == NULL) - { - PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); - goto err; - } - } - - /* Reuse the memory allocated */ - priv_key_result[0].pValue = reuse_mem; - priv_key_result[0].ulValueLen = reuse_mem_len; - - rv = pFuncList->C_GetAttributeValue(sp->session, h_priv_key, - priv_key_result, priv_key_attr_result_count); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DH_GEN_KEY, - PK11_R_GETATTRIBUTVALUE, rv); - goto err; - } - - if (priv_key_result[0].type == CKA_VALUE) - { - if (dh->priv_key == NULL) - if ((dh->priv_key = BN_new()) == NULL) - { - PK11err(PK11_F_DH_GEN_KEY, - PK11_R_MALLOC_FAILURE); - goto err; - } - dh->priv_key = BN_bin2bn(priv_key_result[0].pValue, - priv_key_result[0].ulValueLen, dh->priv_key); - if (dh->priv_key == NULL) - { - PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE); - goto err; - } - } - - ret = 1; - -err: - - if (h_pub_key != CK_INVALID_HANDLE) - { - rv = pFuncList->C_DestroyObject(sp->session, h_pub_key); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DH_GEN_KEY, - PK11_R_DESTROYOBJECT, rv); - } - } - - if (h_priv_key != CK_INVALID_HANDLE) - { - rv = pFuncList->C_DestroyObject(sp->session, h_priv_key); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DH_GEN_KEY, - PK11_R_DESTROYOBJECT, rv); - } - } - - for (i = 1; i <= 2; i++) - { - if (pub_key_template[i].pValue != NULL) - { - OPENSSL_free(pub_key_template[i].pValue); - pub_key_template[i].pValue = NULL; - } - } - - pk11_return_session(sp, OP_DH); - return (ret); - } - -static int pk11_DH_compute_key(unsigned char *key, const BIGNUM *pub_key, - DH *dh) - { - int i; - CK_MECHANISM mechanism = {CKM_DH_PKCS_DERIVE, NULL_PTR, 0}; - CK_OBJECT_CLASS key_class = CKO_SECRET_KEY; - CK_KEY_TYPE key_type = CKK_GENERIC_SECRET; - CK_OBJECT_HANDLE h_derived_key = CK_INVALID_HANDLE; - CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; - - CK_ULONG ul_priv_key_attr_count = 2; - CK_ATTRIBUTE priv_key_template[] = - { - {CKA_CLASS, (void*) NULL, sizeof (key_class)}, - {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)}, - }; - - CK_ULONG priv_key_attr_result_count = 1; - CK_ATTRIBUTE priv_key_result[] = - { - {CKA_VALUE, (void *)NULL, 0} - }; - - CK_RV rv; - int ret = -1; - PK11_SESSION *sp = NULL; - - if (dh->priv_key == NULL) - goto err; - - priv_key_template[0].pValue = &key_class; - priv_key_template[1].pValue = &key_type; - - if ((sp = pk11_get_session(OP_DH)) == NULL) - goto err; - - mechanism.ulParameterLen = BN_num_bytes(pub_key); - mechanism.pParameter = OPENSSL_malloc(mechanism.ulParameterLen); - if (mechanism.pParameter == NULL) - { - PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE); - goto err; - } - BN_bn2bin(pub_key, mechanism.pParameter); - - (void) check_new_dh_key(sp, dh); - - h_key = sp->opdata_dh_key; - if (h_key == CK_INVALID_HANDLE) - h_key = sp->opdata_dh_key = - pk11_get_dh_key((DH*) dh, &sp->opdata_dh, - &sp->opdata_dh_priv_num, sp->session); - - if (h_key == CK_INVALID_HANDLE) - { - PK11err(PK11_F_DH_COMP_KEY, PK11_R_CREATEOBJECT); - goto err; - } - - rv = pFuncList->C_DeriveKey(sp->session, - &mechanism, - h_key, - priv_key_template, - ul_priv_key_attr_count, - &h_derived_key); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_DERIVEKEY, rv); - goto err; - } - - rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key, - priv_key_result, priv_key_attr_result_count); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE, - rv); - goto err; - } - - if (((CK_LONG) priv_key_result[0].ulValueLen) <= 0) - { - PK11err(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE); - goto err; - } - priv_key_result[0].pValue = - OPENSSL_malloc(priv_key_result[0].ulValueLen); - if (!priv_key_result[0].pValue) - { - PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE); - goto err; - } - - rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key, - priv_key_result, priv_key_attr_result_count); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE, - rv); - goto err; - } - - /* - * OpenSSL allocates the output buffer 'key' which is the same - * length of the public key. It is long enough for the derived key - */ - if (priv_key_result[0].type == CKA_VALUE) - { - /* - * CKM_DH_PKCS_DERIVE mechanism is not supposed to strip - * leading zeros from a computed shared secret. However, - * OpenSSL always did it so we must do the same here. The - * vagueness of the spec regarding leading zero bytes was - * finally cleared with TLS 1.1 (RFC 4346) saying that leading - * zeros are stripped before the computed data is used as the - * pre-master secret. - */ - for (i = 0; i < priv_key_result[0].ulValueLen; ++i) - { - if (((char *)priv_key_result[0].pValue)[i] != 0) - break; - } - - (void) memcpy(key, ((char *)priv_key_result[0].pValue) + i, - priv_key_result[0].ulValueLen - i); - ret = priv_key_result[0].ulValueLen - i; - } - -err: - - if (h_derived_key != CK_INVALID_HANDLE) - { - rv = pFuncList->C_DestroyObject(sp->session, h_derived_key); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_DH_COMP_KEY, - PK11_R_DESTROYOBJECT, rv); - } - } - if (priv_key_result[0].pValue) - { - OPENSSL_free(priv_key_result[0].pValue); - priv_key_result[0].pValue = NULL; - } - - if (mechanism.pParameter) - { - OPENSSL_free(mechanism.pParameter); - mechanism.pParameter = NULL; - } - - pk11_return_session(sp, OP_DH); - return (ret); - } - - -static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, - DH **key_ptr, BIGNUM **dh_priv_num, CK_SESSION_HANDLE session) - { - CK_RV rv; - CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; - CK_OBJECT_CLASS class = CKO_PRIVATE_KEY; - CK_KEY_TYPE key_type = CKK_DH; - CK_ULONG found; - CK_BBOOL rollback = CK_FALSE; - int i; - - CK_ULONG ul_key_attr_count = 7; - CK_ATTRIBUTE key_template[] = - { - {CKA_CLASS, (void*) NULL, sizeof (class)}, - {CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)}, - {CKA_DERIVE, &pk11_true, sizeof (pk11_true)}, - {CKA_PRIVATE, &pk11_false, sizeof (pk11_false)}, - {CKA_PRIME, (void *) NULL, 0}, - {CKA_BASE, (void *) NULL, 0}, - {CKA_VALUE, (void *) NULL, 0}, - }; - - key_template[0].pValue = &class; - key_template[1].pValue = &key_type; - - key_template[4].ulValueLen = BN_num_bytes(dh->p); - key_template[4].pValue = (CK_VOID_PTR)OPENSSL_malloc( - (size_t)key_template[4].ulValueLen); - if (key_template[4].pValue == NULL) - { - PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); - goto malloc_err; - } - - BN_bn2bin(dh->p, key_template[4].pValue); - - key_template[5].ulValueLen = BN_num_bytes(dh->g); - key_template[5].pValue = (CK_VOID_PTR)OPENSSL_malloc( - (size_t)key_template[5].ulValueLen); - if (key_template[5].pValue == NULL) - { - PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); - goto malloc_err; - } - - BN_bn2bin(dh->g, key_template[5].pValue); - - key_template[6].ulValueLen = BN_num_bytes(dh->priv_key); - key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc( - (size_t)key_template[6].ulValueLen); - if (key_template[6].pValue == NULL) - { - PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); - goto malloc_err; - } - - BN_bn2bin(dh->priv_key, key_template[6].pValue); - - /* see find_lock array definition for more info on object locking */ - LOCK_OBJSTORE(OP_DH); - rv = pFuncList->C_FindObjectsInit(session, key_template, - ul_key_attr_count); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSINIT, rv); - goto err; - } - - rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTS, rv); - goto err; - } - - rv = pFuncList->C_FindObjectsFinal(session); - - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSFINAL, - rv); - goto err; - } - - if (found == 0) - { - rv = pFuncList->C_CreateObject(session, - key_template, ul_key_attr_count, &h_key); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_CREATEOBJECT, - rv); - goto err; - } - } - - if (dh_priv_num != NULL) - if ((*dh_priv_num = BN_dup(dh->priv_key)) == NULL) - { - PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE); - rollback = CK_TRUE; - goto err; - } - - /* LINTED: E_CONSTANT_CONDITION */ - KEY_HANDLE_REFHOLD(h_key, OP_DH, CK_FALSE, rollback, err); - if (key_ptr != NULL) - *key_ptr = dh; - -err: - if (rollback) - { - /* - * We do not care about the return value from C_DestroyObject() - * since we are doing rollback. - */ - if (found == 0) - (void) pFuncList->C_DestroyObject(session, h_key); - h_key = CK_INVALID_HANDLE; - } - - UNLOCK_OBJSTORE(OP_DH); - -malloc_err: - for (i = 4; i <= 6; i++) - { - if (key_template[i].pValue != NULL) - { - OPENSSL_free(key_template[i].pValue); - key_template[i].pValue = NULL; - } - } - - return (h_key); - } - -/* - * Check for cache miss and clean the object pointer and handle - * in such case. Return 1 for cache hit, 0 for cache miss. - * - * Note: we rely on pk11_destroy_dh_key_objects() to set sp->opdata_dh - * to CK_INVALID_HANDLE even when it fails to destroy the object. - */ -static int check_new_dh_key(PK11_SESSION *sp, DH *dh) - { - /* - * Provide protection against DH structure reuse by making the - * check for cache hit stronger. Private key component of DH key - * is unique so it is sufficient to compare it with value cached - * in PK11_SESSION structure. - */ - if ((sp->opdata_dh != dh) || - (BN_cmp(sp->opdata_dh_priv_num, dh->priv_key) != 0)) - { - /* - * We do not check the return value because even in case of - * failure the sp structure will have both key pointer - * and object handle cleaned and pk11_destroy_object() - * reports the failure to the OpenSSL error message buffer. - */ - (void) pk11_destroy_dh_object(sp, CK_TRUE); - return (0); - } - return (1); - } -#endif - -/* - * Local function to simplify key template population - * Return 0 -- error, 1 -- no error - */ -static int -init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value, - CK_ULONG *ul_value_len) - { - CK_ULONG len; - - /* - * This function can be used on non-initialized BIGNUMs. It is easier to - * check that here than individually in the callers. - */ - if (bn != NULL) - len = BN_num_bytes(bn); - - if (bn == NULL || len == 0) - return (1); - - *ul_value_len = len; - *p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len); - if (*p_value == NULL) - return (0); - - BN_bn2bin(bn, *p_value); - - return (1); - } - -static void -attr_to_BN(CK_ATTRIBUTE_PTR attr, CK_BYTE attr_data[], BIGNUM **bn) - { - if (attr->ulValueLen > 0) - *bn = BN_bin2bn(attr_data, attr->ulValueLen, NULL); - } - -/* - * Find one object in the token. It is an error if we can not find the object or - * if we find more objects based on the template we got. - * - * Returns: - * 1 OK - * 0 no object or more than 1 object found - */ -static int -find_one_object(PK11_OPTYPE op, CK_SESSION_HANDLE s, - CK_ATTRIBUTE_PTR ptempl, CK_ULONG nattr, CK_OBJECT_HANDLE_PTR pkey) - { - CK_RV rv; - CK_ULONG objcnt; - - LOCK_OBJSTORE(op); - if ((rv = pFuncList->C_FindObjectsInit(s, ptempl, nattr)) != CKR_OK) - { - PK11err_add_data(PK11_F_FIND_ONE_OBJECT, - PK11_R_FINDOBJECTSINIT, rv); - goto err; - } - - rv = pFuncList->C_FindObjects(s, pkey, 1, &objcnt); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_FIND_ONE_OBJECT, PK11_R_FINDOBJECTS, - rv); - goto err; - } - - if (objcnt > 1) - { - PK11err(PK11_F_FIND_ONE_OBJECT, - PK11_R_MORE_THAN_ONE_OBJECT_FOUND); - goto err; - } - else - if (objcnt == 0) - { - PK11err(PK11_F_FIND_ONE_OBJECT, PK11_R_NO_OBJECT_FOUND); - goto err; - } - - (void) pFuncList->C_FindObjectsFinal(s); - UNLOCK_OBJSTORE(op); - return (1); -err: - UNLOCK_OBJSTORE(op); - return (0); - } - -#endif /* OPENSSL_NO_HW_PK11 */ -#endif /* OPENSSL_NO_HW */ diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/engines/pkcs11/hw_pk11_uri.c --- a/components/openssl/openssl-1.0.1-fips-140/engines/pkcs11/hw_pk11_uri.c Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,870 +0,0 @@ -/* - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. 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. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED 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 OpenSSL PROJECT OR - * ITS 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 - -#ifndef OPENSSL_NO_HW -#ifndef OPENSSL_NO_HW_PK11 - -#include -#include -#include "hw_pk11.h" -#include "hw_pk11_uri.h" - -/* - * The keystore used is always from the pubkey slot so we need to know which one - * was selected so that we can get the information needed for the URI - * processing. - */ -extern CK_SLOT_ID pubkey_SLOTID; -extern CK_FUNCTION_LIST_PTR pFuncList; - -/* - * Cached PIN so that child can use it during the re-login. Note that we do not - * cache the PIN by default. - */ -static char *token_pin; - -static int mlock_pin_in_memory(char *pin); -static char *run_askpass(char *dialog); - -/* - * Get the PIN. Either run the command and use its standard output as a PIN to - * fill in the PKCS11 URI structure, or read the PIN from the terminal. Using - * the external command is of higher precedence. The memory for PIN is allocated - * in this function and the PIN is always NULL terminated. The caller must take - * care of freeing the memory used for the PIN. The maximum PIN length accepted - * is PK11_MAX_PIN_LEN. - * - * The function is used also during the re-initialization of the engine after - * the fork. - * - * The function must not be called under the protection of the mutex "uri_lock" - * because the lock is acquired in the prefork function. - * - * Returns: - * 0 in case of troubles (and sets "*pin" to NULL) - * 1 if we got the PIN - */ -#define EXEC_SPEC "exec:" -#define BUILTIN_SPEC "builtin" -int -pk11_get_pin(char *dialog, char **pin) - { - /* Initialize as an error. */ - *pin = NULL; - - if (strcmp(dialog, BUILTIN_SPEC) == 0) - { - /* The getpassphrase() function is not MT safe. */ - (void) pthread_mutex_lock(uri_lock); - /* Note that OpenSSL is not localized at all. */ - *pin = getpassphrase("Enter token PIN: "); - if (*pin == NULL) - { - PK11err(PK11_F_GET_PIN, PK11_R_COULD_NOT_READ_PIN); - (void) pthread_mutex_unlock(uri_lock); - goto err; - } - else - { - char *pw; - - /* - * getpassphrase() uses an internal buffer to hold the - * entered password. Note that it terminates the buffer - * with '\0'. - */ - if ((pw = strdup(*pin)) == NULL) - { - PK11err(PK11_F_GET_PIN, PK11_R_MALLOC_FAILURE); - (void) pthread_mutex_unlock(uri_lock); - goto err; - } - /* Zero the internal buffer to get rid of the PIN. */ - memset(*pin, 0, strlen(*pin)); - *pin = pw; - (void) pthread_mutex_unlock(uri_lock); - } - } - else - { - /* - * This is the "exec:" case. We will get the PIN from the output - * of an external command. - */ - if (strncmp(dialog, EXEC_SPEC, strlen(EXEC_SPEC)) == 0) - { - dialog += strlen(EXEC_SPEC); - if ((*pin = run_askpass(dialog)) == NULL) - goto err; - } - else - { - /* - * Invalid specification in the passphrasedialog - * keyword. - */ - PK11err(PK11_F_GET_PIN, PK11_R_BAD_PASSPHRASE_SPEC); - goto err; - } - } - - return (1); -err: - return (0); - } - -/* - * Process the PKCS#11 URI and get the PIN. It uses information from the - * passphrasedialog keyword to get the PIN. If passphrasedialog is not present - * it is not considered an error since it depends on the token attributes - * whether C_Login() is required. The function expects an allocated 'uri_struct' - * structure. - * - * Returns: - * 0 if URI is not valid at all, or if we could not get the PIN - * 1 if all is OK - * 2 if the URI is not the PKCS#11 URI. In that case, put the string - * pointer to the filename to "*file". Note that the pointer just points - * inside of the "uristr", possibly skipping the file:// prefix if present. - */ -int -pk11_process_pkcs11_uri(const char *uristr, pkcs11_uri *uri_struct, - const char **file) - { - char *uristr2, *l1, *l2, *tok, *name; - - /* Check the "file://" case. */ - if (strncmp(uristr, FILE_URI_PREFIX, strlen(FILE_URI_PREFIX)) == 0) - { - *file = uristr + strlen(FILE_URI_PREFIX); - return (2); - } - - /* This is the "pkcs11:" case. */ - if (strncmp(uristr, PK11_URI_PREFIX, strlen(PK11_URI_PREFIX)) != 0) - { - /* Not PKCS#11 URI at all, could be a filename. */ - *file = (const char *)uristr; - return (2); - } - else - { - /* Dup the string and skip over the pkcs11: prefix then. */ - uristr2 = strdup(uristr + strlen(PK11_URI_PREFIX)); - if (uristr2 == NULL) - { - PK11err(PK11_F_CHECK_TOKEN_ATTRS, - PK11_R_MALLOC_FAILURE); - goto err; - } - } - - /* Initialize the structure. */ - memset(uri_struct, 0, sizeof (*uri_struct)); - - /* - * Using strtok_r() would silently skip over multiple semicolons. We - * must check that before moving on. We must also avoid ';' as the first - * and the last character in the URI. - */ - if (strstr(uristr2, ";;") != NULL || uristr2[0] == ';' || - (strlen(uristr2) > 0 && uristr2[strlen(uristr2) - 1] == ';')) - goto bad_uri; - - tok = strtok_r(uristr2, ";", &l1); - for (; tok != NULL; tok = strtok_r(NULL, ";", &l1)) - { - /* "tok" is not empty so there will be something in "name". */ - name = strtok_r(tok, "=", &l2); - /* Check whether there is '=' at all. */ - if (l2 == NULL) - goto bad_uri; - - /* - * Fill out the URI structure. We do not accept duplicit - * attributes. - */ - if (strcmp(name, PK11_TOKEN) == 0) - if (uri_struct->token == NULL) - { - if ((uri_struct->token = strdup(l2)) == NULL) - goto no_mem; - } - else - goto bad_uri; - else if (strcmp(name, PK11_MANUF) == 0) - if (uri_struct->manuf == NULL) - { - if ((uri_struct->manuf = strdup(l2)) == NULL) - goto no_mem; - } - else - goto bad_uri; - else if (strcmp(name, PK11_SERIAL) == 0) - if (uri_struct->serial == NULL) - { - if ((uri_struct->serial = strdup(l2)) == NULL) - goto no_mem; - } - else - goto bad_uri; - else if (strcmp(name, PK11_MODEL) == 0) - if (uri_struct->model == NULL) - { - if ((uri_struct->model = strdup(l2)) == NULL) - goto no_mem; - } - else - goto bad_uri; - else if (strcmp(name, PK11_OBJECT) == 0) - if (uri_struct->object == NULL) - { - if ((uri_struct->object = strdup(l2)) == NULL) - goto no_mem; - } - else - goto bad_uri; - else if (strcmp(name, PK11_OBJECTTYPE) == 0) - if (uri_struct->objecttype == NULL) - { - uri_struct->objecttype = strdup(l2); - if (uri_struct->objecttype == NULL) - goto no_mem; - } - else - goto bad_uri; - else if (strcmp(name, PK11_ASKPASS) == 0) - if (uri_struct->askpass == NULL) - { - if ((uri_struct->askpass = strdup(l2)) == NULL) - goto no_mem; - } - else - goto bad_uri; - else - goto bad_uri; - } - - /* The "object" token is mandatory in the PKCS#11 URI. */ - if (uri_struct->object == NULL) - { - PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MISSING_OBJECT_LABEL); - goto err; - } - - free(uristr2); - return (1); -bad_uri: - PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_INVALID_PKCS11_URI); - if (uristr2 != NULL) - free(uristr2); - return (0); -no_mem: - PK11err(PK11_F_LOAD_PRIVKEY, PK11_R_MALLOC_FAILURE); -err: - pk11_free_pkcs11_uri(uri_struct, CK_FALSE); - if (uristr2 != NULL) - free(uristr2); - return (0); - } - -/* - * Free the PKCS11 URI structure and anything that might be inside. - */ -void -pk11_free_pkcs11_uri(pkcs11_uri *uri_struct, CK_BBOOL free_uri_itself) - { - if (uri_struct->token != NULL) - free(uri_struct->token); - if (uri_struct->manuf != NULL) - free(uri_struct->manuf); - if (uri_struct->serial != NULL) - free(uri_struct->serial); - if (uri_struct->model != NULL) - free(uri_struct->model); - if (uri_struct->object != NULL) - free(uri_struct->object); - if (uri_struct->objecttype != NULL) - free(uri_struct->objecttype); - if (uri_struct->askpass != NULL) - free(uri_struct->askpass); - - if (free_uri_itself == CK_TRUE) - OPENSSL_free(uri_struct); - } - -/* - * While our keystore is always the one used by the pubkey slot (which is - * usually the Metaslot) we must make sure that those URI attributes that - * specify the keystore match the real attributes of our slot keystore. Note - * that one can use the METASLOT_OBJECTSTORE_TOKEN environment variable to - * change the Metaslot's keystore from the softtoken to something else (see - * libpkcs11(3LIB)). The user might want to use such attributes in the PKCS#11 - * URI to make sure that the intended keystore is used. - * - * Returns: - * 1 on success - * 0 on failure - */ -int -pk11_check_token_attrs(pkcs11_uri *uri_struct) - { - CK_RV rv; - static CK_TOKEN_INFO_PTR token_info = NULL; - - (void) pthread_mutex_lock(uri_lock); - if (token_info == NULL) - { - token_info = OPENSSL_malloc(sizeof (CK_TOKEN_INFO)); - if (token_info == NULL) - { - PK11err(PK11_F_CHECK_TOKEN_ATTRS, - PK11_R_MALLOC_FAILURE); - goto err; - } - - rv = pFuncList->C_GetTokenInfo(pubkey_SLOTID, token_info); - if (rv != CKR_OK) - { - PK11err_add_data(PK11_F_CHECK_TOKEN_ATTRS, - PK11_R_GETTOKENINFO, rv); - goto err; - } - } - - if (uri_struct->token != NULL) - if (strncmp(uri_struct->token, (char *)token_info->label, - strlen(uri_struct->token) > 32 ? 32 : - strlen(uri_struct->token)) != 0) - { - goto urierr; - } - - if (uri_struct->manuf != NULL) - if (strncmp(uri_struct->manuf, - (char *)token_info->manufacturerID, - strlen(uri_struct->manuf) > 32 ? 32 : - strlen(uri_struct->manuf)) != 0) - goto urierr; - - if (uri_struct->model != NULL) - if (strncmp(uri_struct->model, (char *)token_info->model, - strlen(uri_struct->model) > 16 ? 16 : - strlen(uri_struct->model)) != 0) - goto urierr; - - if (uri_struct->serial != NULL) - if (strncmp(uri_struct->serial, - (char *)token_info->serialNumber, - strlen(uri_struct->serial) > 16 ? 16 : - strlen(uri_struct->serial)) != 0) - goto urierr; - - (void) pthread_mutex_unlock(uri_lock); - return (1); - -urierr: - PK11err(PK11_F_CHECK_TOKEN_ATTRS, PK11_R_TOKEN_ATTRS_DO_NOT_MATCH); - /* Correct error already set above for the "err" label. */ -err: - (void) pthread_mutex_unlock(uri_lock); - return (0); - } - -/* - * Return the process PIN caching policy. We initialize it just once so if the - * process change OPENSSL_PKCS11_PIN_CACHING_POLICY during the operation it will - * not have any affect on the policy. - * - * We assume that the "uri_lock" mutex is already locked. - * - * Returns the caching policy number. - */ -int -pk11_get_pin_caching_policy(void) - { - char *value = NULL; - static int policy = POLICY_NOT_INITIALIZED; - - if (policy != POLICY_NOT_INITIALIZED) - return (policy); - - value = getenv("OPENSSL_PKCS11_PIN_CACHING_POLICY"); - - if (value == NULL || strcmp(value, "none") == 0) - { - policy = POLICY_NONE; - goto done; - } - - if (strcmp(value, "memory") == 0) - { - policy = POLICY_MEMORY; - goto done; - } - - if (strcmp(value, "mlocked-memory") == 0) - { - policy = POLICY_MLOCKED_MEMORY; - goto done; - } - - return (POLICY_WRONG_VALUE); -done: - return (policy); - } - -/* - * Cache the PIN in memory once. We already know that we have either "memory" or - * "mlocked-memory" keyword correctly set. - * - * Returns: - * 1 on success - * 0 on failure - */ -int -pk11_cache_pin(char *pin) - { - (void) pthread_mutex_lock(uri_lock); - /* We set the PIN only once since all URIs must have it the same. */ - if (token_pin != NULL) - goto ok; - - if (pk11_get_pin_caching_policy() == POLICY_MEMORY) - if ((token_pin = strdup(pin)) == NULL) - { - PK11err(PK11_F_CACHE_PIN, PK11_R_MALLOC_FAILURE); - goto err; - } - else - if (pk11_get_pin_caching_policy() == POLICY_MLOCKED_MEMORY) - { - if (mlock_pin_in_memory(pin) == 0) - goto err; - } - -ok: - (void) pthread_mutex_unlock(uri_lock); - return (1); -err: - (void) pthread_mutex_unlock(uri_lock); - return (0); - } - -/* - * Cache the PIN in mlock(3C)ed memory. If mlock(3C) fails we will not resort to - * the normal memory caching. - * - * Note that this function must be called under the protection of the "uri_lock" - * mutex. - * - * Returns: - * 1 on success - * 0 on failure - */ -static int -mlock_pin_in_memory(char *pin) - { - void *addr = NULL; - long pagesize = 0; - - /* mlock(3C) locks pages so we need one whole page for the PIN. */ - if ((pagesize = sysconf(_SC_PAGESIZE)) == -1) - { - PK11err(PK11_F_MLOCK_PIN_IN_MEMORY, PK11_R_SYSCONF_FAILED); - goto err; - } - - /* This will ensure we have a page aligned pointer... */ - if ((addr = mmap(0, pagesize, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, -1, 0)) == MAP_FAILED) - { - PK11err(PK11_F_MLOCK_PIN_IN_MEMORY, PK11_R_MMAP_FAILED); - goto err; - } - - /* ...because "addr" must be page aligned here. */ - if (mlock(addr, pagesize) == -1) - { - /* - * Missing the PRIV_PROC_LOCK_MEMORY privilege might be a common - * problem so distinguish this situation from other issues. - */ - if (errno == EPERM) - PK11err(PK11_F_MLOCK_PIN_IN_MEMORY, - PK11_R_PRIV_PROC_LOCK_MEMORY_MISSING); - else - PK11err(PK11_F_MLOCK_PIN_IN_MEMORY, - PK11_R_MLOCK_FAILED); - - /* - * We already have a problem here so there is no need to check - * that we could unmap the page. The PIN is not there yet - * anyway. - */ - (void) munmap(addr, pagesize); - goto err; - } - - /* Copy the PIN to the mlocked memory. */ - token_pin = (char *)addr; - strlcpy(token_pin, pin, PK11_MAX_PIN_LEN + 1); - return (1); -err: - return (0); - } - -/* - * Log in to the keystore if we are supposed to do that at all. Take care of - * reading and caching the PIN etc. Log in only once even when called from - * multiple threads. - * - * Returns: - * 1 on success - * 0 on failure - */ -int -pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, - pkcs11_uri *uri_struct, CK_BBOOL is_private) - { - CK_RV rv; - - if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0) - { - PK11err(PK11_F_TOKEN_LOGIN, - PK11_R_TOKEN_NOT_INITIALIZED); - goto err; - } - - /* - * If login is required or needed but the PIN has not been even - * initialized we can bail out right now. Note that we are supposed to - * always log in if we are going to access private keys. However, we may - * need to log in even for accessing public keys in case that the - * CKF_LOGIN_REQUIRED flag is set. - */ - if ((pubkey_token_flags & CKF_LOGIN_REQUIRED || - is_private == CK_TRUE) && ~pubkey_token_flags & - CKF_USER_PIN_INITIALIZED) - { - PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET); - goto err; - } - - /* - * Note on locking: it is possible that more than one thread gets into - * pk11_get_pin() so we must deal with that. We cannot avoid it since we - * cannot guard fork() in there with a lock because we could end up in - * a dead lock in the child. Why? Remember we are in a multithreaded - * environment so we must lock all mutexes in the prefork function to - * avoid a situation in which a thread that did not call fork() held a - * lock, making future unlocking impossible. We lock right before - * C_Login(). - */ - if (pubkey_token_flags & CKF_LOGIN_REQUIRED || is_private == CK_TRUE) - { - if (*login_done == CK_FALSE && - uri_struct->askpass == NULL) - { - PK11err(PK11_F_TOKEN_LOGIN, - PK11_R_TOKEN_PIN_NOT_PROVIDED); - goto err; - } - - if (*login_done == CK_FALSE && - uri_struct->askpass != NULL) - { - if (pk11_get_pin(uri_struct->askpass, - &uri_struct->pin) == 0) - { - PK11err(PK11_F_TOKEN_LOGIN, - PK11_R_TOKEN_PIN_NOT_PROVIDED); - goto err; - } - } - - /* - * Note that what we are logging into is the keystore from - * pubkey_SLOTID because we work with OP_RSA session type here. - * That also means that we can work with only one keystore in - * the engine. - * - * We must make sure we do not try to login more than once. - * Also, see the comment above on locking strategy. - */ - (void) pthread_mutex_lock(uri_lock); - if (*login_done == CK_FALSE) - { - if ((rv = pFuncList->C_Login(session, - CKU_USER, (CK_UTF8CHAR*)uri_struct->pin, - strlen(uri_struct->pin))) != CKR_OK) - { - PK11err_add_data(PK11_F_TOKEN_LOGIN, - PK11_R_TOKEN_LOGIN_FAILED, rv); - goto err_locked; - } - - *login_done = CK_TRUE; - - /* - * Cache the passphrasedialog for possible child (which - * would need to relogin). - */ - if (passphrasedialog == NULL && - uri_struct->askpass != NULL) - { - passphrasedialog = - strdup(uri_struct->askpass); - - if (passphrasedialog == NULL) - { - PK11err_add_data(PK11_F_TOKEN_LOGIN, - PK11_R_MALLOC_FAILURE, rv); - goto err_locked; - } - } - - /* - * Check the PIN caching policy. Note that user might - * have provided a PIN even when no PIN was required - - * in that case we always remove the PIN from memory. - */ - if (pk11_get_pin_caching_policy() == - POLICY_WRONG_VALUE) - { - PK11err(PK11_F_TOKEN_LOGIN, - PK11_R_PIN_CACHING_POLICY_INVALID); - goto err_locked; - } - - if (pk11_get_pin_caching_policy() != POLICY_NONE) - if (pk11_cache_pin(uri_struct->pin) == 0) - goto err_locked; - } - (void) pthread_mutex_unlock(uri_lock); - } - else - { - /* - * If token does not require login we take it as the - * login was done. - */ - *login_done = CK_TRUE; - } - - /* - * If we raced at pk11_get_pin() we must make sure that all threads that - * called pk11_get_pin() will erase the PIN from memory, not just the - * one that called C_Login(). Note that if we were supposed to cache the - * PIN it was already cached by now so filling "uri_struct.pin" with - * zero bytes is always OK since pk11_cache_pin() makes a copy of it. - */ - if (uri_struct->pin != NULL) - memset(uri_struct->pin, 0, strlen(uri_struct->pin)); - - return (1); - -err_locked: - (void) pthread_mutex_unlock(uri_lock); -err: - /* Always get rid of the PIN. */ - if (uri_struct->pin != NULL) - memset(uri_struct->pin, 0, strlen(uri_struct->pin)); - return (0); - } - -/* - * Log in to the keystore in the child if we were logged in in the parent. There - * are similarities in the code with pk11_token_login() but still it is quite - * different so we need a separate function for this. - * - * Note that this function is called under the locked session mutex when fork is - * detected. That means that C_Login() will be called from the child just once. - * - * Returns: - * 1 on success - * 0 on failure - */ -int -pk11_token_relogin(CK_SESSION_HANDLE session) - { - CK_RV rv; - - /* - * We are in the child so check if we should login to the token again. - * Note that it is enough to log in to the token through one session - * only, all already open and all future sessions can access the token - * then. - */ - if (passphrasedialog != NULL) - { - char *pin = NULL; - - /* If we cached the PIN then use it. */ - if (token_pin != NULL) - pin = token_pin; - else if (pk11_get_pin(passphrasedialog, &pin) == 0) - goto err; - - (void) pthread_mutex_lock(uri_lock); - if ((rv = pFuncList->C_Login(session, CKU_USER, - (CK_UTF8CHAR_PTR)pin, strlen(pin))) != CKR_OK) - { - PK11err_add_data(PK11_F_TOKEN_RELOGIN, - PK11_R_TOKEN_LOGIN_FAILED, rv); - (void) pthread_mutex_unlock(uri_lock); - goto err; - } - (void) pthread_mutex_unlock(uri_lock); - - /* Forget the PIN now if we did not cache it before. */ - if (pin != token_pin) - { - memset(pin, 0, strlen(pin)); - OPENSSL_free(pin); - } - } - - return (1); -err: - return (0); - } - -/* - * This function forks and runs an external command. It would be nice if we - * could use popen(3C)/pclose(3C) for that but unfortunately we need to be able - * to get rid of the PIN from the memory. With p(open|close) function calls we - * cannot control the stdio's memory used for buffering and our tests showed - * that the PIN really stays there even after pclose(). - * - * Returns: - * allocated buffer on success - * NULL on failure - */ -static char * -run_askpass(char *dialog) - { - pid_t pid; - int n, p[2]; - char *buf = NULL; - - if (pipe(p) == -1) - { - PK11err(PK11_F_RUN_ASKPASS, PK11_R_PIPE_FAILED); - return (NULL); - } - - switch (pid = fork()) - { - case -1: - PK11err(PK11_F_RUN_ASKPASS, PK11_R_FORK_FAILED); - return (NULL); - /* child */ - case 0: - /* - * This should make sure that dup2() will not fail on - * file descriptor shortage. - */ - close(p[0]); - (void) dup2(p[1], 1); - close(p[1]); - /* - * Note that we cannot use PK11err() here since we are - * in the child. However, parent will get read() error - * so do not worry. - */ - (void) execl(dialog, basename(dialog), NULL); - exit(1); - /* parent */ - default: - /* +1 is for the terminating '\0' */ - buf = (char *)OPENSSL_malloc(PK11_MAX_PIN_LEN + 1); - if (buf == NULL) - { - PK11err(PK11_F_RUN_ASKPASS, - PK11_R_MALLOC_FAILURE); - return (NULL); - } - - close(p[1]); - n = read(p[0], buf, PK11_MAX_PIN_LEN); - if (n == -1 || n == 0) - { - PK11err(PK11_F_RUN_ASKPASS, - PK11_R_PIN_NOT_READ_FROM_COMMAND); - OPENSSL_free(buf); - return (NULL); - } - buf[n] = '\0'; - - (void) waitpid(pid, NULL, 0); - } - - return (buf); - } - -#endif /* OPENSSL_NO_HW_PK11 */ -#endif /* OPENSSL_NO_HW */ diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/engines/pkcs11/hw_pk11_uri.h --- a/components/openssl/openssl-1.0.1-fips-140/engines/pkcs11/hw_pk11_uri.h Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2004, 2013, Oracle and/or its affiliates. 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. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED 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 OpenSSL PROJECT OR - * ITS 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. - */ - -#ifndef HW_PK11_URI_H -#define HW_PK11_URI_H - -#include - -/* PKCS#11 URI related prefixes and attributes. */ -#define PK11_URI_PREFIX "pkcs11:" -#define FILE_URI_PREFIX "file://" -#define PK11_TOKEN "token" -#define PK11_MANUF "manuf" -#define PK11_SERIAL "serial" -#define PK11_MODEL "model" -#define PK11_OBJECT "object" -#define PK11_OBJECTTYPE "objecttype" -#define PK11_ASKPASS "passphrasedialog" - -/* PIN caching policy. */ -#define POLICY_NOT_INITIALIZED 0 -#define POLICY_NONE 1 -#define POLICY_MEMORY 2 -#define POLICY_MLOCKED_MEMORY 3 -#define POLICY_WRONG_VALUE 4 - -/* - * That's what getpassphrase(3c) supports. - */ -#define PK11_MAX_PIN_LEN 256 - -/* Add new attributes of the PKCS#11 URI here. */ -typedef struct pkcs11_uri_struct - { - char *object; /* object label, the only mandatory info */ - char *objecttype; /* (private|public|cert), currently unused */ - char *token; /* token label */ - char *manuf; /* manufacturer label */ - char *serial; /* serial number label */ - char *model; /* model label */ - char *askpass; /* full path to the command to get the PIN */ - /* Not part of the PKCS11 URI itself. */ - char *pin; /* token PIN */ - } pkcs11_uri; - -/* For URI processing. */ -extern pthread_mutex_t *uri_lock; - -int pk11_get_pin(char *dialog, char **pin); -int pk11_get_pin_caching_policy(void); -int pk11_process_pkcs11_uri(const char *uristr, pkcs11_uri *uri_struct, - const char **file); -int pk11_check_token_attrs(pkcs11_uri *uri_struct); -void pk11_free_pkcs11_uri(pkcs11_uri *uri_struct, CK_BBOOL free_uri_itself); -int pk11_cache_pin(char *pin); -int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, - pkcs11_uri *uri_struct, CK_BBOOL is_private); -int pk11_token_relogin(CK_SESSION_HANDLE session); - -#endif /* HW_PK11_URI_H */ diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/llib-lcrypto --- a/components/openssl/openssl-1.0.1-fips-140/llib-lcrypto Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. - */ - -/* LINTLIBRARY */ -/* PROTOLIB1 */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/llib-lssl --- a/components/openssl/openssl-1.0.1-fips-140/llib-lssl Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - */ - -/* LINTLIBRARY */ -/* PROTOLIB1 */ - -#include -#include -#include -#include diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/openssl-1.0.1-fips-140.license --- a/components/openssl/openssl-1.0.1-fips-140/openssl-1.0.1-fips-140.license Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ - - LICENSE ISSUES - ============== - - The OpenSSL toolkit stays under a dual license, i.e. both the conditions of - the OpenSSL License and the original SSLeay license apply to the toolkit. - See below for the actual license texts. Actually both licenses are BSD-style - Open Source licenses. In case of any license issues related to OpenSSL - please contact openssl-core@openssl.org. - - OpenSSL License - --------------- - -/* ==================================================================== - * Copyright (c) 1998-2008 The OpenSSL Project. 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. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * openssl-core@openssl.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.openssl.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED 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 OpenSSL PROJECT OR - * ITS 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. - * ==================================================================== - * - * This product includes cryptographic software written by Eric Young - * (eay@cryptsoft.com). This product includes software written by Tim - * Hudson (tjh@cryptsoft.com). - * - */ - - Original SSLeay License - ----------------------- - -/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) - * All rights reserved. - * - * This package is an SSL implementation written - * by Eric Young (eay@cryptsoft.com). - * The implementation was written so as to conform with Netscapes SSL. - * - * This library is free for commercial and non-commercial use as long as - * the following conditions are aheared to. The following conditions - * apply to all code found in this distribution, be it the RC4, RSA, - * lhash, DES, etc., code; not just the SSL code. The SSL documentation - * included with this distribution is covered by the same copyright terms - * except that the holder is Tim Hudson (tjh@cryptsoft.com). - * - * Copyright remains Eric Young's, and as such any Copyright notices in - * the code are not to be removed. - * If this package is used in a product, Eric Young should be given attribution - * as the author of the parts of the library used. - * This can be in the form of a textual message at program startup or - * in documentation (online or textual) provided with the package. - * - * 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 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * "This product includes cryptographic software written by - * Eric Young (eay@cryptsoft.com)" - * The word 'cryptographic' can be left out if the rouines from the library - * being used are not cryptographic related :-). - * 4. If you include any Windows specific code (or a derivative thereof) from - * the apps directory (application code) you must include an acknowledgement: - * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" - * - * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. - * - * The licence and distribution terms for any publically available version or - * derivative of this code cannot be changed. i.e. this code cannot simply be - * copied and put under another distribution licence - * [including the GNU Public Licence.] - */ - diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/openssl-1.0.1-fips-140.p5m --- a/components/openssl/openssl-1.0.1-fips-140/openssl-1.0.1-fips-140.p5m Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. -# - - default mangler.man.stability uncommitted> -set name=pkg.fmri \ - value=pkg:/library/security/openssl/openssl-fips-140@$(IPS_COMPONENT_VERSION),$(BUILD_VERSION) -set name=pkg.human-version value=$(COMPONENT_VERSION) -set name=pkg.summary value="FIPS 140-2 Capable OpenSSL libraries" -set name=com.oracle.info.description value="the FIPS 140-2 Capable OpenSSL libraries" -set name=com.oracle.info.tpno value=13019 -set name=info.classification \ - value="org.opensolaris.category.2008:System/Security" -set name=info.source-url value=$(COMPONENT_ARCHIVE_URL) -set name=info.upstream-url value=$(COMPONENT_PROJECT_URL) -set name=org.opensolaris.arc-caseid \ - value=PSARC/2009/507 -set name=org.opensolaris.consolidation value=$(CONSOLIDATION) -# Basic directories and a configuration file. -file etc/openssl/openssl.cnf path=etc/openssl/fips-140/openssl.cnf group=sys mode=0644 preserve=true -link path=lib/openssl/fips-140/64 target=$(MACH64) -# 32 bit libraries, lint libraries, and engines. -file $(MACH32)/libcrypto.so.1.0.0 path=lib/openssl/fips-140/libcrypto.so.1.0.0 -link path=lib/openssl/fips-140/libcrypto.so target=libcrypto.so.1.0.0 -file $(MACH32)/libssl.so.1.0.0 path=lib/openssl/fips-140/libssl.so.1.0.0 -link path=lib/openssl/fips-140/libssl.so target=libssl.so.1.0.0 -file llib-lcrypto path=lib/openssl/fips-140/llib-lcrypto -file $(MACH32)/llib-lcrypto.ln path=lib/openssl/fips-140/llib-lcrypto.ln -file llib-lssl path=lib/openssl/fips-140/llib-lssl -file $(MACH32)/llib-lssl.ln path=lib/openssl/fips-140/llib-lssl.ln -# 64 bit libraries, lint libraries, and engines. -file $(MACH64)/libcrypto.so.1.0.0 path=lib/openssl/fips-140/$(MACH64)/libcrypto.so.1.0.0 -link path=lib/openssl/fips-140/$(MACH64)/libcrypto.so target=libcrypto.so.1.0.0 -file $(MACH64)/libssl.so.1.0.0 path=lib/openssl/fips-140/$(MACH64)/libssl.so.1.0.0 -link path=lib/openssl/fips-140/$(MACH64)/libssl.so target=libssl.so.1.0.0 -file llib-lcrypto path=lib/openssl/fips-140/$(MACH64)/llib-lcrypto -file $(MACH64)/llib-lcrypto.ln path=lib/openssl/fips-140/$(MACH64)/llib-lcrypto.ln -file llib-lssl path=lib/openssl/fips-140/$(MACH64)/llib-lssl -file $(MACH64)/llib-lssl.ln path=lib/openssl/fips-140/$(MACH64)/llib-lssl.ln -# Header files. -# -# Take header files from the 32-bit build. This build has the patched -# opensslconf.h (64-bit build does not). We cannot take header files from the -# proto area since it could contain headers installed for the 64-bit build. - \ - set action.hash $(MACH32)/include/openssl/%<1> > -file path=usr/include/openssl/fips-140/openssl/aes.h -file path=usr/include/openssl/fips-140/openssl/asn1.h -file path=usr/include/openssl/fips-140/openssl/asn1_mac.h -file path=usr/include/openssl/fips-140/openssl/asn1t.h -file path=usr/include/openssl/fips-140/openssl/bio.h -file path=usr/include/openssl/fips-140/openssl/blowfish.h -file path=usr/include/openssl/fips-140/openssl/bn.h -file path=usr/include/openssl/fips-140/openssl/buffer.h -file path=usr/include/openssl/fips-140/openssl/cast.h -file path=usr/include/openssl/fips-140/openssl/cmac.h -file path=usr/include/openssl/fips-140/openssl/cms.h -file path=usr/include/openssl/fips-140/openssl/comp.h -file path=usr/include/openssl/fips-140/openssl/conf.h -file path=usr/include/openssl/fips-140/openssl/conf_api.h -file path=usr/include/openssl/fips-140/openssl/crypto.h -file path=usr/include/openssl/fips-140/openssl/des.h -file path=usr/include/openssl/fips-140/openssl/des_old.h -file path=usr/include/openssl/fips-140/openssl/dh.h -file path=usr/include/openssl/fips-140/openssl/dsa.h -file path=usr/include/openssl/fips-140/openssl/dso.h -file path=usr/include/openssl/fips-140/openssl/dtls1.h -file path=usr/include/openssl/fips-140/openssl/e_os2.h -file path=usr/include/openssl/fips-140/openssl/ebcdic.h -file path=usr/include/openssl/fips-140/openssl/ec.h -file path=usr/include/openssl/fips-140/openssl/ecdh.h -file path=usr/include/openssl/fips-140/openssl/ecdsa.h -file path=usr/include/openssl/fips-140/openssl/engine.h -file path=usr/include/openssl/fips-140/openssl/err.h -file path=usr/include/openssl/fips-140/openssl/evp.h -file path=usr/include/openssl/fips-140/openssl/fips.h -file path=usr/include/openssl/fips-140/openssl/fips_rand.h -file path=usr/include/openssl/fips-140/openssl/hmac.h -file path=usr/include/openssl/fips-140/openssl/krb5_asn.h -file path=usr/include/openssl/fips-140/openssl/kssl.h -file path=usr/include/openssl/fips-140/openssl/lhash.h -file path=usr/include/openssl/fips-140/openssl/md2.h -file path=usr/include/openssl/fips-140/openssl/md4.h -file path=usr/include/openssl/fips-140/openssl/md5.h -file path=usr/include/openssl/fips-140/openssl/modes.h -file path=usr/include/openssl/fips-140/openssl/obj_mac.h -file path=usr/include/openssl/fips-140/openssl/objects.h -file path=usr/include/openssl/fips-140/openssl/ocsp.h -file path=usr/include/openssl/fips-140/openssl/opensslconf.h -file path=usr/include/openssl/fips-140/openssl/opensslv.h -file path=usr/include/openssl/fips-140/openssl/ossl_typ.h -file path=usr/include/openssl/fips-140/openssl/pem.h -file path=usr/include/openssl/fips-140/openssl/pem2.h -file path=usr/include/openssl/fips-140/openssl/pkcs12.h -file path=usr/include/openssl/fips-140/openssl/pkcs7.h -file path=usr/include/openssl/fips-140/openssl/pqueue.h -file path=usr/include/openssl/fips-140/openssl/rand.h -file path=usr/include/openssl/fips-140/openssl/rc2.h -file path=usr/include/openssl/fips-140/openssl/rc4.h -file path=usr/include/openssl/fips-140/openssl/ripemd.h -file path=usr/include/openssl/fips-140/openssl/rsa.h -file path=usr/include/openssl/fips-140/openssl/safestack.h -file path=usr/include/openssl/fips-140/openssl/sha.h -file path=usr/include/openssl/fips-140/openssl/srp.h -file path=usr/include/openssl/fips-140/openssl/srtp.h -file path=usr/include/openssl/fips-140/openssl/ssl.h -file path=usr/include/openssl/fips-140/openssl/ssl2.h -file path=usr/include/openssl/fips-140/openssl/ssl23.h -file path=usr/include/openssl/fips-140/openssl/ssl3.h -file path=usr/include/openssl/fips-140/openssl/stack.h -file path=usr/include/openssl/fips-140/openssl/symhacks.h -file path=usr/include/openssl/fips-140/openssl/tls1.h -file path=usr/include/openssl/fips-140/openssl/ts.h -file path=usr/include/openssl/fips-140/openssl/txt_db.h -file path=usr/include/openssl/fips-140/openssl/ui.h -file path=usr/include/openssl/fips-140/openssl/ui_compat.h -file path=usr/include/openssl/fips-140/openssl/whrlpool.h -file path=usr/include/openssl/fips-140/openssl/x509.h -file path=usr/include/openssl/fips-140/openssl/x509_vfy.h -file path=usr/include/openssl/fips-140/openssl/x509v3.h -license openssl-1.0.1-fips-140.license license="OpenSSL, SSLeay" diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/patches-post-config/opensslconf.patch --- a/components/openssl/openssl-1.0.1-fips-140/patches-post-config/opensslconf.patch Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ ---- /tmp/opensslconf.h Thu Mar 10 06:46:57 2011 -+++ /tmp/opensslconf.h.new Thu Mar 10 06:47:41 2011 -@@ -2,9 +2,12 @@ - /* WARNING: Generated automatically from opensslconf.h.in by Configure. */ - - /* OpenSSL was configured with the following options: */ -+#if defined(__sparcv9) - #ifndef OPENSSL_SYSNAME_ULTRASPARC - # define OPENSSL_SYSNAME_ULTRASPARC - #endif -+#endif -+ - #ifndef OPENSSL_DOING_MAKEDEPEND - - -@@ -185,10 +188,14 @@ - - #if !(defined(VMS) || defined(__VMS)) /* VMS uses logical names instead */ - #if defined(HEADER_CRYPTLIB_H) && !defined(OPENSSLDIR) -+#if defined(__sparcv9) || defined(__x86_64) -+#define ENGINESDIR "/lib/openssl/engines/64" -+#else - #define ENGINESDIR "/lib/openssl/engines" --#define OPENSSLDIR "/etc/openssl" - #endif -+#define OPENSSLDIR "/etc/openssl/fips-140" - #endif -+#endif - - #undef OPENSSL_UNISTD - #define OPENSSL_UNISTD -@@ -232,21 +239,34 @@ - /* If this is set to 'unsigned int' on a DEC Alpha, this gives about a - * %20 speed up (longs are 8 bytes, int's are 4). */ - #ifndef DES_LONG -+#if defined(__sparcv9) || defined(__x86_64) -+#define DES_LONG unsigned int -+#else - #define DES_LONG unsigned long - #endif - #endif -+#endif - - #if defined(HEADER_BN_H) && !defined(CONFIG_HEADER_BN_H) - #define CONFIG_HEADER_BN_H -+#if defined(__sparcv9) || defined(__x86_64) -+#undef BN_LLONG -+#else - #define BN_LLONG -+#endif - - /* Should we define BN_DIV2W here? */ - - /* Only one for the following should be defined */ -+#if defined(__sparcv9) || defined(__x86_64) -+#define SIXTY_FOUR_BIT_LONG -+#undef THIRTY_TWO_BIT -+#else - #undef SIXTY_FOUR_BIT_LONG --#undef SIXTY_FOUR_BIT - #define THIRTY_TWO_BIT - #endif -+#undef SIXTY_FOUR_BIT -+ #endif - - #if defined(HEADER_RC4_LOCL_H) && !defined(CONFIG_HEADER_RC4_LOCL_H) - #define CONFIG_HEADER_RC4_LOCL_H diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/patches/08-6193522.patch --- a/components/openssl/openssl-1.0.1-fips-140/patches/08-6193522.patch Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -diff -ruN openssl-0.9.8a/apps/CA.pl.in openssl-0.9.8a/apps/CA.pl.in ---- openssl-0.9.8a/apps/CA.pl.in 2005-07-04 23:44:22.000000000 +0200 -+++ openssl-0.9.8a/apps/CA.pl.in 2009-04-21 16:08:45.354925289 +0200 -@@ -53,7 +53,7 @@ - $X509="$openssl x509"; - $PKCS12="$openssl pkcs12"; - --$CATOP="./demoCA"; -+$CATOP="/etc/openssl"; - $CAKEY="cakey.pem"; - $CAREQ="careq.pem"; - $CACERT="cacert.pem"; -diff -ruN openssl-0.9.8a/apps/openssl.cnf openssl-0.9.8a/apps/openssl.cnf ---- openssl-0.9.8a/apps/openssl.cnf 2005-09-16 14:20:24.000000000 +0200 -+++ openssl-0.9.8a/apps/openssl.cnf 2009-04-21 16:07:13.910980196 +0200 -@@ -39,7 +39,7 @@ - #################################################################### - [ CA_default ] - --dir = ./demoCA # Where everything is kept -+dir = /etc/openssl # Where everything is kept - certs = $dir/certs # Where the issued certs are kept - crl_dir = $dir/crl # Where the issued crl are kept - database = $dir/index.txt # database index file. -@@ -49,7 +49,7 @@ - - certificate = $dir/cacert.pem # The CA certificate - serial = $dir/serial # The current serial number --crlnumber = $dir/crlnumber # the current crl number -+#crlnumber = $dir/crlnumber # the current crl number - # must be commented out to leave a V1 CRL - crl = $dir/crl.pem # The current CRL - private_key = $dir/private/cakey.pem# The private key -@@ -126,17 +126,17 @@ - - [ req_distinguished_name ] - countryName = Country Name (2 letter code) --countryName_default = AU -+#countryName_default = US - countryName_min = 2 - countryName_max = 2 - - stateOrProvinceName = State or Province Name (full name) --stateOrProvinceName_default = Some-State -+#stateOrProvinceName_default = Some-State - - localityName = Locality Name (eg, city) - - 0.organizationName = Organization Name (eg, company) --0.organizationName_default = Internet Widgits Pty Ltd -+#0.organizationName_default = Unconfigured OpenSSL Installation - - # we can do this but it is not needed normally :-) - #1.organizationName = Second Organization Name (eg, company) diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/patches/11-6546806.patch --- a/components/openssl/openssl-1.0.1-fips-140/patches/11-6546806.patch Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -diff -ruN openssl-0.9.8a/doc/crypto/hmac.pod openssl-0.9.8a/doc/crypto/hmac.pod ---- openssl-0.9.8a/doc/crypto/hmac.pod 2002-07-18 20:54:45.000000000 +0200 -+++ openssl-0.9.8a/doc/crypto/hmac.pod 2009-04-10 11:09:46.449071541 +0200 -@@ -2,7 +2,7 @@ - - =head1 NAME - --HMAC, HMAC_Init, HMAC_Update, HMAC_Final, HMAC_cleanup - HMAC message -+HMAC, HMAC_CTX_init, HMAC_Init, HMAC_Init_ex, HMAC_Update, HMAC_Final, HMAC_CTX_cleanup, HMAC_cleanup - HMAC message - authentication code - - =head1 SYNOPSIS diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/patches/15-pkcs11_engine-0.9.8a.patch --- a/components/openssl/openssl-1.0.1-fips-140/patches/15-pkcs11_engine-0.9.8a.patch Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,125 +0,0 @@ ---- /tmp/Configure Fri Feb 11 14:40:39 2011 -+++ openssl-1.0.0d/Configure Fri Feb 11 14:41:36 2011 -@@ -10,7 +10,7 @@ - - # see INSTALL for instructions. - --my $usage="Usage: Configure [no- ...] [enable- ...] [experimental- ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n"; -+my $usage="Usage: Configure --pk11-libname=PK11_LIB_LOCATION [no- ...] [enable- ...] [experimental- ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-krb5] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--test-sanity] os/compiler[:flags]\n"; - - # Options: - # -@@ -19,6 +19,9 @@ - # --prefix prefix for the OpenSSL include, lib and bin directories - # (Default: the OPENSSLDIR directory) - # -+# --pk11-libname PKCS#11 library name. -+# (Default: none) -+# - # --install_prefix Additional prefix for package builders (empty by - # default). This needn't be set in advance, you can - # just as well use "make INSTALL_PREFIX=/whatever install". -@@ -657,6 +661,9 @@ - my $idx_arflags = $idx++; - my $idx_multilib = $idx++; - -+# PKCS#11 engine patch -+my $pk11_libname=""; -+ - my $prefix=""; - my $libdir=""; - my $openssldir=""; -@@ -876,6 +879,10 @@ - $_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei; - $flags.=$_." "; - } -+ elsif (/^--pk11-libname=(.*)$/) -+ { -+ $pk11_libname=$1; -+ } - elsif (/^--prefix=(.*)$/) - { - $prefix=$1; -@@ -1043,6 +1054,13 @@ - exit 0; - } - -+if (! $pk11_libname) -+ { -+ print STDERR "You must set --pk11-libname for PKCS#11 library.\n"; -+ print STDERR "See README.pkcs11 for more information.\n"; -+ exit 1; -+ } -+ - if ($target =~ m/^CygWin32(-.*)$/) { - $target = "Cygwin".$1; - } -@@ -1209,6 +1226,8 @@ - if ($flags ne "") { $cflags="$flags$cflags"; } - else { $no_user_cflags=1; } - -+$cflags="-DPK11_LIB_LOCATION=\"$pk11_libname\" $cflags"; -+ - # Kerberos settings. The flavor must be provided from outside, either through - # the script "config" or manually. - if (!$no_krb5) -@@ -1598,6 +1617,7 @@ - s/^VERSION=.*/VERSION=$version/; - s/^MAJOR=.*/MAJOR=$major/; - s/^MINOR=.*/MINOR=$minor/; -+ s/^PK11_LIB_LOCATION=.*/PK11_LIB_LOCATION=$pk11_libname/; - s/^SHLIB_VERSION_NUMBER=.*/SHLIB_VERSION_NUMBER=$shlib_version_number/; - s/^SHLIB_VERSION_HISTORY=.*/SHLIB_VERSION_HISTORY=$shlib_version_history/; - s/^SHLIB_MAJOR=.*/SHLIB_MAJOR=$shlib_major/; ---- /tmp/Makefile.org Fri Feb 11 14:41:54 2011 -+++ openssl-1.0.0d/Makefile.org Fri Feb 11 14:38:01 2011 -@@ -26,6 +26,9 @@ - INSTALL_PREFIX= - INSTALLTOP=/usr/local/ssl - -+# You must set this through --pk11-libname configure option. -+PK11_LIB_LOCATION= -+ - # Do not edit this manually. Use Configure --openssldir=DIR do change this! - OPENSSLDIR=/usr/local/ssl - ---- /tmp/Makefile Fri Feb 11 14:42:03 2011 -+++ openssl-1.0.0d/crypto/engine/Makefile Fri Feb 11 14:45:43 2011 -@@ -22,13 +22,13 @@ - tb_rsa.c tb_dsa.c tb_ecdsa.c tb_dh.c tb_ecdh.c tb_rand.c tb_store.c \ - tb_cipher.c tb_digest.c tb_pkmeth.c tb_asnmth.c \ - eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c \ -- eng_rsax.c eng_rdrand.c -+ eng_rsax.c eng_rdrand.c hw_pk11.c hw_pk11_pub.c hw_pk11_uri.c - LIBOBJ= eng_err.o eng_lib.o eng_list.o eng_init.o eng_ctrl.o \ - eng_table.o eng_pkey.o eng_fat.o eng_all.o \ - tb_rsa.o tb_dsa.o tb_ecdsa.o tb_dh.o tb_ecdh.o tb_rand.o tb_store.o \ - tb_cipher.o tb_digest.o tb_pkmeth.o tb_asnmth.o \ - eng_openssl.o eng_cnf.o eng_dyn.o eng_cryptodev.o \ -- eng_rsax.o eng_rdrand.o -+ eng_rsax.o eng_rdrand.o hw_pk11.o hw_pk11_pub.o hw_pk11_uri.o - - SRC= $(LIBSRC) - ---- /tmp/eng_all.c Fri Feb 11 14:46:11 2011 -+++ openssl-1.0.0d/crypto/engine/eng_all.c Fri Feb 11 14:38:01 2011 -@@ -80,6 +80,9 @@ - ENGINE_load_rdrand(); - #endif - ENGINE_load_dynamic(); -+#ifndef OPENSSL_NO_HW_PKCS11 -+ ENGINE_load_pk11(); -+#endif - #ifndef OPENSSL_NO_STATIC_ENGINE - #ifndef OPENSSL_NO_HW - #ifndef OPENSSL_NO_HW_4758_CCA ---- /tmp/engine.h Fri Feb 11 14:46:24 2011 -+++ openssl-1.0.0d/crypto/engine/engine.h Fri Feb 11 14:47:32 2011 -@@ -351,6 +351,7 @@ - #endif - #endif - void ENGINE_load_cryptodev(void); -+void ENGINE_load_pk11(void); - void ENGINE_load_rsax(void); - void ENGINE_load_rdrand(void); - void ENGINE_load_builtin_engines(void); diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/patches/18-compiler_opts.patch --- a/components/openssl/openssl-1.0.1-fips-140/patches/18-compiler_opts.patch Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -diff -ruN openssl-0.9.8k/Configure openssl-0.9.8k/Configure ---- openssl-0.9.8k/Configure 2009-02-16 09:44:22.000000000 +0100 -+++ openssl-0.9.8k/Configure 2009-06-25 16:19:22.897811727 +0200 -@@ -133,7 +133,7 @@ - - my $x86_64_asm="x86_64cpuid.o:x86_64-gcc.o x86_64-mont.o x86_64-mont5.o x86_64-gf2m.o modexp512-x86_64.o::aes-x86_64.o vpaes-x86_64.o bsaes-x86_64.o aesni-x86_64.o aesni-sha1-x86_64.o::md5-x86_64.o:sha1-x86_64.o sha256-x86_64.o sha512-x86_64.o::rc4-x86_64.o rc4-md5-x86_64.o:::wp-x86_64.o:cmll-x86_64.o cmll_misc.o:ghash-x86_64.o:"; - my $ia64_asm="ia64cpuid.o:bn-ia64.o ia64-mont.o::aes_core.o aes_cbc.o aes-ia64.o::md5-ia64.o:sha1-ia64.o sha256-ia64.o sha512-ia64.o::rc4-ia64.o rc4_skey.o:::::ghash-ia64.o::void"; --my $sparcv9_asm="sparcv9cap.o sparccpuid.o:bn-sparcv9.o sparcv9-mont.o sparcv9a-mont.o:des_enc-sparc.o fcrypt_b.o:aes_core.o aes_cbc.o aes-sparcv9.o:::sha1-sparcv9.o sha256-sparcv9.o sha512-sparcv9.o:::::::ghash-sparcv9.o::void"; -+my $sparcv9_asm="sparcv9cap.o sparccpuid.o:bn-sparcv9.o sparcv9-mont.o:des_enc-sparc.o fcrypt_b.o:aes_core.o aes_cbc.o aes-sparcv9.o:::sha1-sparcv9.o sha256-sparcv9.o sha512-sparcv9.o:::::::ghash-sparcv9.o::void"; - my $sparcv8_asm=":sparcv8.o:des_enc-sparc.o fcrypt_b.o:::::::::::::void"; - my $alpha_asm="alphacpuid.o:bn_asm.o alpha-mont.o:::::sha1-alpha.o:::::::ghash-alpha.o::void"; - my $mips32_asm=":bn-mips.o::aes_cbc.o aes-mips.o:::sha1-mips.o sha256-mips.o::::::::"; -@@ -257,6 +264,12 @@ - #"sunos-cc", "cc:-O4 -DNOPROTO -DNOCONST::(unknown):SUNOS::DES_UNROLL:${no_asm}::", - "sunos-gcc","gcc:-O3 -mv8 -Dssize_t=int::(unknown):SUNOS::BN_LLONG RC4_CHAR RC4_CHUNK DES_UNROLL DES_PTR DES_RISC1:${no_asm}::", - -+#### Solaris configs, used for OpenSSL as delivered by OpenSolaris -+"solaris-x86-cc-sunw","cc:-m32 -xO3 -xspace -Xa::-D_REENTRANT::-lsocket -lnsl -lc -R /lib/openssl/fips-140:BN_LLONG RC4_CHUNK DES_PTR DES_UNROLL BF_PTR:${x86_elf_asm}:dlfcn:solaris-shared:-KPIC:-m32 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign -M/usr/lib/ld/map.noexdata:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"solaris64-x86_64-cc-sunw","cc:-xO3 -m64 -xstrconst -Xa -DL_ENDIAN::-D_REENTRANT::-lsocket -lnsl -lc -R /lib/openssl/fips-140/64:SIXTY_FOUR_BIT_LONG RC4_CHUNK BF_PTR DES_PTR DES_INT DES_UNROLL:${x86_64_asm}:elf:dlfcn:solaris-shared:-KPIC:-m64 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign -M/usr/lib/ld/map.noexdata:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"solaris-sparcv8-cc-sunw","cc:-xtarget=ultra -m32 -Qoption cg -xregs=no%appl -xO5 -xstrconst -xdepend -Xa -DB_ENDIAN -DBN_DIV2W::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -lc -lsoftcrypto -R /lib/openssl/fips-140:BN_LLONG RC4_CHUNK_LL DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${sparcv8_asm}:dlfcn:solaris-shared:-KPIC:-m32 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", -+"solaris64-sparcv9-cc-sunw","cc:-xtarget=ultra -m64 -Qoption cg -xregs=no%appl -xO5 -xstrconst -xdepend -xspace -Xa -DB_ENDIAN::-D_REENTRANT:ULTRASPARC:-lsocket -lnsl -lc -lsoftcrypto -R /lib/openssl/fips-140/64:BN_LLONG RC4_CHUNK DES_INT DES_PTR DES_RISC1 DES_UNROLL BF_PTR:${sparcv9_asm}:dlfcn:solaris-shared:-KPIC:-m64 -G -dy -z text -zdefs -Bdirect -zignore -M/usr/lib/ld/map.pagealign:.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR):/usr/ccs/bin/ar rs::/64", -+ - #### IRIX 5.x configs - # -mips2 flag is added by ./config when appropriate. - "irix-gcc","gcc:-O3 -DTERMIOS -DB_ENDIAN::(unknown):::BN_LLONG MD2_CHAR RC4_INDEX RC4_CHAR RC4_CHUNK DES_UNROLL DES_RISC2 DES_PTR BF_PTR:${mips32_asm}:o32:dlfcn:irix-shared:::.so.\$(SHLIB_MAJOR).\$(SHLIB_MINOR)", diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/patches/20-remove_rpath.patch --- a/components/openssl/openssl-1.0.1-fips-140/patches/20-remove_rpath.patch Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ ---- /export/openssl/openssl-1.0.0d/Makefile.shared Sat Aug 21 13:36:49 2010 -+++ openssl-1.0.0d/Makefile.shared Mon Feb 14 14:25:51 2011 -@@ -393,7 +393,7 @@ - @ if $(DETECT_GNU_LD); then \ - $(DO_GNU_APP); \ - else \ -- LDFLAGS="$(CFLAGS) -R $(LIBRPATH)"; \ -+ LDFLAGS="$(CFLAGS)"; \ - fi; \ - $(LINK_APP) - diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/patches/23-noexstack.patch --- a/components/openssl/openssl-1.0.1-fips-140/patches/23-noexstack.patch Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,21 +0,0 @@ ---- /tmp/Makefile.shared Mon Feb 14 14:33:05 2011 -+++ openssl-1.0.0d/Makefile.shared Mon Feb 14 14:35:56 2011 -@@ -389,6 +389,7 @@ - SHAREDFLAGS="$(CFLAGS) $(SHARED_LDFLAGS) -h $$SHLIB$$SHLIB_SOVER$$SHLIB_SUFFIX -Wl,-Bsymbolic"; \ - fi; \ - $(LINK_SO_A) -+# Make sure the apps have non-executable stacks and data (x86/x64 only). - link_app.solaris: - @ if $(DETECT_GNU_LD); then \ - $(DO_GNU_APP); \ -@@ -395,6 +396,10 @@ - else \ - LDFLAGS="$(CFLAGS)"; \ - fi; \ -+ if expr $(PLATFORM) : '.*x86.*' > /dev/null; then \ -+ LDFLAGS="$${LDFLAGS} -M/usr/lib/ld/map.noexdata"; \ -+ fi; \ -+ LDFLAGS="$${LDFLAGS} -M/usr/lib/ld/map.noexstk -M/usr/lib/ld/map.pagealign"; \ - $(LINK_APP) - - # OpenServer 5 native compilers used diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/patches/26-openssl_fips.patch --- a/components/openssl/openssl-1.0.1-fips-140/patches/26-openssl_fips.patch Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ ---- openssl-0.9.8m/apps/openssl.c Thu Oct 15 19:28:02 2009 -+++ openssl-0.9.8m/apps/openssl.c Fri Feb 26 16:12:30 2010 -@@ -133,6 +133,9 @@ - #include - #endif - -+/* Solaris OpenSSL */ -+#include -+ - /* The LHASH callbacks ("hash" & "cmp") have been replaced by functions with the - * base prototypes (we cast each variable inside the function to the required - * type of "FUNCTION*"). This removes the necessity for macro-generated wrapper -@@ -152,9 +155,10 @@ - #endif - - -+static int *modes; -+ - static void lock_dbg_cb(int mode, int type, const char *file, int line) - { -- static int modes[CRYPTO_NUM_LOCKS]; /* = {0, 0, ... } */ - const char *errstr = NULL; - int rw; - -@@ -165,7 +169,7 @@ - goto err; - } - -- if (type < 0 || type >= CRYPTO_NUM_LOCKS) -+ if (type < 0 || type >= CRYPTO_num_locks()) - { - errstr = "type out of bounds"; - goto err; -@@ -310,6 +314,14 @@ - if (getenv("OPENSSL_DEBUG_LOCKING") != NULL) - #endif - { -+ modes = OPENSSL_malloc(CRYPTO_num_locks() * sizeof (int)); -+ if (modes == NULL) { -+ ERR_load_crypto_strings(); -+ BIO_printf(bio_err,"Memory allocation failure\n"); -+ ERR_print_errors(bio_err); -+ EXIT(1); -+ } -+ memset(modes, 0, CRYPTO_num_locks() * sizeof (int)); - CRYPTO_set_locking_callback(lock_dbg_cb); - } - -@@ -313,18 +325,28 @@ - CRYPTO_set_locking_callback(lock_dbg_cb); - } - -+/* -+ * Solaris OpenSSL -+ * Add a further check for the FIPS_mode_set() symbol before calling to -+ * allow openssl(1openssl) to be run against both fips and non-fips libraries. -+ */ - if(getenv("OPENSSL_FIPS")) { --#ifdef OPENSSL_FIPS -- if (!FIPS_mode_set(1)) { -+ -+ int (*FIPS_mode_set)(int); -+ FIPS_mode_set = (int (*)(int)) dlsym(RTLD_NEXT, "FIPS_mode_set"); -+ -+ if (FIPS_mode_set != NULL) { -+ if (!(*FIPS_mode_set)(1)) { - ERR_load_crypto_strings(); - ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE)); - EXIT(1); - } --#else -- fprintf(stderr, "FIPS mode not supported.\n"); -+ } else { -+ fprintf(stderr, "Failed to enable FIPS mode. " -+ "For more information about running in FIPS mode see openssl(5).\n"); - EXIT(1); --#endif - } -+ } - - apps_startup(); - diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/patches/27-6978791.patch --- a/components/openssl/openssl-1.0.1-fips-140/patches/27-6978791.patch Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ ---- /tmp/Makefile.shared Mon Feb 14 14:39:29 2011 -+++ openssl-1.0.0d/Makefile.shared Mon Feb 14 14:50:52 2011 -@@ -387,6 +387,9 @@ - ALLSYMSFLAGS="$${MINUSZ}allextract"; \ - NOALLSYMSFLAGS="$${MINUSZ}defaultextract"; \ - SHAREDFLAGS="$(CFLAGS) $(SHARED_LDFLAGS) -h $$SHLIB$$SHLIB_SOVER$$SHLIB_SUFFIX -Wl,-Bsymbolic"; \ -+ if [ $(LIBNAME) = "ssl" ]; then \ -+ SHAREDFLAGS="$$SHAREDFLAGS $${MINUSZ}nodelete"; \ -+ fi; \ - fi; \ - $(LINK_SO_A) - # Make sure the apps have non-executable stacks and data (x86/x64 only). diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/patches/28-enginesdir.patch --- a/components/openssl/openssl-1.0.1-fips-140/patches/28-enginesdir.patch Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ ---- /tmp/18/Configure Fri Feb 11 15:15:50 2011 -+++ openssl-1.0.0d/Configure Fri Feb 11 15:18:09 2011 -@@ -18,6 +18,8 @@ - # --prefix option is given; /usr/local/ssl otherwise) - # --prefix prefix for the OpenSSL include, lib and bin directories - # (Default: the OPENSSLDIR directory) -+# --enginesdir engines shared library location -+# (Default: $prefix/lib/engines) - # - # --pk11-libname PKCS#11 library name. - # (Default: none) -@@ -672,6 +672,7 @@ - my $prefix=""; - my $libdir=""; - my $openssldir=""; -+my $enginesdir=""; - my $exe_ext=""; - my $install_prefix= "$ENV{'INSTALL_PREFIX'}"; - my $cross_compile_prefix=""; -@@ -904,6 +904,10 @@ - { - $openssldir=$1; - } -+ elsif (/^--enginesdir=(.*)$/) -+ { -+ $enginesdir=$1; -+ } - elsif (/^--install.prefix=(.*)$/) - { - $install_prefix=$1; -@@ -1211,6 +1218,10 @@ - # we're ready to tolerate, so don't... - $multilib="" if !-d "$prefix/lib$multilib"; - -+if ($enginesdir eq "") { -+ $enginesdir = "$prefix/lib/engines"; -+} -+ - $libdir="lib$multilib" if $libdir eq ""; - - $cflags = "$cflags$exp_cflags"; -@@ -1830,7 +1841,7 @@ - } - elsif (/^#define\s+ENGINESDIR/) - { -- my $foo = "$prefix/$libdir/engines"; -+ my $foo = "$enginesdir"; - $foo =~ s/\\/\\\\/g; - print OUT "#define ENGINESDIR \"$foo\"\n"; - } diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-1.0.1-fips-140/resolve.deps --- a/components/openssl/openssl-1.0.1-fips-140/resolve.deps Mon Dec 09 15:11:31 2013 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -system/library diff -r 2d3ec080d6a3 -r 314c74b881bc components/openssl/openssl-fips/Makefile --- a/components/openssl/openssl-fips/Makefile Mon Dec 09 15:11:31 2013 -0800 +++ b/components/openssl/openssl-fips/Makefile Mon Dec 09 18:42:02 2013 -0800 @@ -18,22 +18,22 @@ # # CDDL HEADER END # -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. # # -# This component is not to be installed. It is used to build FIPS-140 -# certified OpenSSL libraries. +# This component is not to be installed. It is used from openssl-0.9.8-fips-140 +# to build FIPS-140 certified OpenSSL libraries. # include ../../../make-rules/shared-macros.mk COMPONENT_NAME = openssl-fips -COMPONENT_VERSION = 2.0.5 -COMPONENT_SRC = $(COMPONENT_NAME)-ecp-$(COMPONENT_VERSION) +COMPONENT_VERSION = 1.2 +COMPONENT_SRC = $(COMPONENT_NAME)-$(COMPONENT_VERSION) COMPONENT_ARCHIVE = $(COMPONENT_SRC).tar.gz COMPONENT_ARCHIVE_HASH= \ - sha256:f1abdd0ca1a9467a3eba15564fc2b3447114d1d63020c33cd3210f2a43a5ff4d + sha256:645cc77775a3e2e50d766ae0e0631327ceec6ab7793fe582da51cb04c007a5e1 COMPONENT_ARCHIVE_URL = http://www.openssl.org/source/$(COMPONENT_ARCHIVE) COMPONENT_BUGDB= utility/openssl @@ -47,7 +47,7 @@ # its output. isalist is used internally when configuring the canister before # building it. In order to allow make install to be run as a no-op we have to # fake "make install" since we do not want to install the files anywhere. The -# command sets U1 and U2 are defined in the FIPS 2.0.5 security policy and must be +# command sets U1 and U2 are defined in the FIPS 1.2 security policy and must be # run as shown there. Nothing from the tarball can be modified. We use the U2 # command set, see below. FAKE_ISALIST = 32/isalist @@ -58,14 +58,14 @@ CLOBBER_PATHS += $(FAKE_APPS) # Do not use $(PWD), it would not work if run from a different directory with -# "gmake -C" as we do from openssl-1.0.1 +# "gmake -C" as we do from openssl-0.9.8-fips-140. # we'll also pick up gcc if we find it in the path, so force it to # find one that doesn't work like it wants FIPS_PATH_32 = $(COMPONENT_DIR)/32:$(COMPONENT_DIR)/gcc:$(PATH) FIPS_PATH_64 = $(COMPONENT_DIR)/gcc:$(PATH) OPENSSL_FIPS_HMAC_KEY = etaonrishdlcupfm -OPENSSL_FIPS_HMAC = 148e4e127ffef1df80c0ed61bae35b07ec7b7b36 +OPENSSL_FIPS_HMAC = 79193087e8115df76d3de1f346f7410df79cf6e0 # There is a broken link in the tarball which causes cp(1) to fail which would # fail the whole configure process. It's safer to get rid of the link than @@ -77,18 +77,8 @@ # There is a specific way that must be followed to build the FIPS-140 canister. # It is "./config fipscanisterbuild; make; make install" and is called a command # set "U2" in the OpenSSL FIPS-140 User Guide. -ifeq ($(MACH), sparc) -CONFIGURE_SCRIPT_32 = config -# For 64-bit, use './Configure fipscanisterbuild solaris64-sparcv9-cc'. -CONFIGURE_SCRIPT_64 = ./Configure -CONFIGURE_OPTIONS.64 = solaris64-sparcv9-cc -CONFIGURE_SCRIPT = $(CONFIGURE_SCRIPT_$(BITS)) -else CONFIGURE_SCRIPT = config -endif - CONFIGURE_OPTIONS = fipscanisterbuild -CONFIGURE_OPTIONS += $(CONFIGURE_OPTIONS.$(BITS)) COMPONENT_BUILD_ARGS = COMPONENT_BUILD_TARGETS = COMPONENT_INSTALL_ARGS = @@ -113,8 +103,8 @@ # used and that we used the correct tarball. $(BUILD_DIR)/%/.verified: $(BUILD_DIR)/%/.installed (printf x; \ - $(ENV) - LD_LIBRARY_PATH=$(@D) \ - openssl sha1 -hmac $(OPENSSL_FIPS_HMAC_KEY) \ + $(ENV) - OPENSSL_FIPS=1 LD_LIBRARY_PATH=$(@D) \ + $(@D)/apps/openssl sha1 -hmac $(OPENSSL_FIPS_HMAC_KEY) \ $(COMPONENT_ARCHIVE)) | \ $(NAWK) '{ if ($$2 != "$(OPENSSL_FIPS_HMAC)") exit 1 }' @echo Basic FIPS-140 mode verification passed.