10Sstevel@tonic-gate /* 26847Svk199839 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 30Sstevel@tonic-gate * Use is subject to license terms. 40Sstevel@tonic-gate */ 50Sstevel@tonic-gate 60Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 70Sstevel@tonic-gate 80Sstevel@tonic-gate /* crypto/engine/hw_pk11.c */ 90Sstevel@tonic-gate /* This product includes software developed by the OpenSSL Project for 100Sstevel@tonic-gate * use in the OpenSSL Toolkit (http://www.openssl.org/). 110Sstevel@tonic-gate * 120Sstevel@tonic-gate * This project also referenced hw_pkcs11-0.9.7b.patch written by 130Sstevel@tonic-gate * Afchine Madjlessi. 140Sstevel@tonic-gate */ 150Sstevel@tonic-gate /* ==================================================================== 160Sstevel@tonic-gate * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. 170Sstevel@tonic-gate * 180Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 190Sstevel@tonic-gate * modification, are permitted provided that the following conditions 200Sstevel@tonic-gate * are met: 210Sstevel@tonic-gate * 220Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 230Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 240Sstevel@tonic-gate * 250Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 260Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in 270Sstevel@tonic-gate * the documentation and/or other materials provided with the 280Sstevel@tonic-gate * distribution. 290Sstevel@tonic-gate * 300Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this 310Sstevel@tonic-gate * software must display the following acknowledgment: 320Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project 330Sstevel@tonic-gate * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 340Sstevel@tonic-gate * 350Sstevel@tonic-gate * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 360Sstevel@tonic-gate * endorse or promote products derived from this software without 370Sstevel@tonic-gate * prior written permission. For written permission, please contact 380Sstevel@tonic-gate * licensing@OpenSSL.org. 390Sstevel@tonic-gate * 400Sstevel@tonic-gate * 5. Products derived from this software may not be called "OpenSSL" 410Sstevel@tonic-gate * nor may "OpenSSL" appear in their names without prior written 420Sstevel@tonic-gate * permission of the OpenSSL Project. 430Sstevel@tonic-gate * 440Sstevel@tonic-gate * 6. Redistributions of any form whatsoever must retain the following 450Sstevel@tonic-gate * acknowledgment: 460Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project 470Sstevel@tonic-gate * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 480Sstevel@tonic-gate * 490Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 500Sstevel@tonic-gate * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 510Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 520Sstevel@tonic-gate * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 530Sstevel@tonic-gate * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 540Sstevel@tonic-gate * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 550Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 560Sstevel@tonic-gate * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 570Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 580Sstevel@tonic-gate * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 590Sstevel@tonic-gate * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 600Sstevel@tonic-gate * OF THE POSSIBILITY OF SUCH DAMAGE. 610Sstevel@tonic-gate * ==================================================================== 620Sstevel@tonic-gate * 630Sstevel@tonic-gate * This product includes cryptographic software written by Eric Young 640Sstevel@tonic-gate * (eay@cryptsoft.com). This product includes software written by Tim 650Sstevel@tonic-gate * Hudson (tjh@cryptsoft.com). 660Sstevel@tonic-gate * 670Sstevel@tonic-gate */ 680Sstevel@tonic-gate 690Sstevel@tonic-gate #include <stdio.h> 700Sstevel@tonic-gate #include <stdlib.h> 710Sstevel@tonic-gate #include <string.h> 720Sstevel@tonic-gate #include <sys/types.h> 730Sstevel@tonic-gate #include <unistd.h> 740Sstevel@tonic-gate 750Sstevel@tonic-gate #include <openssl/e_os2.h> 766847Svk199839 #include <openssl/crypto.h> 770Sstevel@tonic-gate #include <openssl/engine.h> 780Sstevel@tonic-gate #include <openssl/dso.h> 790Sstevel@tonic-gate #include <openssl/err.h> 800Sstevel@tonic-gate #include <openssl/bn.h> 812139Sjp161948 #include <openssl/md5.h> 820Sstevel@tonic-gate #include <openssl/pem.h> 836847Svk199839 #ifndef OPENSSL_NO_RSA 840Sstevel@tonic-gate #include <openssl/rsa.h> 856847Svk199839 #endif 866847Svk199839 #ifndef OPENSSL_NO_DSA 876847Svk199839 #include <openssl/dsa.h> 886847Svk199839 #endif 896847Svk199839 #ifndef OPENSSL_NO_DH 906847Svk199839 #include <openssl/dh.h> 916847Svk199839 #endif 920Sstevel@tonic-gate #include <openssl/rand.h> 930Sstevel@tonic-gate #include <openssl/objects.h> 940Sstevel@tonic-gate #include <openssl/x509.h> 95*7211Sjp161948 #include <openssl/aes.h> 960Sstevel@tonic-gate #include <cryptlib.h> 97*7211Sjp161948 #include <dlfcn.h> 980Sstevel@tonic-gate 990Sstevel@tonic-gate #ifndef OPENSSL_NO_HW 1000Sstevel@tonic-gate #ifndef OPENSSL_NO_HW_PK11 1010Sstevel@tonic-gate 102*7211Sjp161948 /* label for debug messages printed on stderr */ 103*7211Sjp161948 #define PK11_DBG "PKCS#11 ENGINE DEBUG" 104*7211Sjp161948 /* prints a lot of debug messages on stderr about slot selection process */ 105*7211Sjp161948 #undef DEBUG_SLOT_SELECTION 106*7211Sjp161948 /* 107*7211Sjp161948 * Solaris specific code. See comment at check_hw_mechanisms() for more 108*7211Sjp161948 * information. 109*7211Sjp161948 */ 110*7211Sjp161948 #define SOLARIS_HW_SLOT_SELECTION 111*7211Sjp161948 112*7211Sjp161948 /* 113*7211Sjp161948 * AES counter mode is not supported in the OpenSSL EVP API yet and neither 114*7211Sjp161948 * there are official OIDs for mechanisms based on this mode. With our changes, 115*7211Sjp161948 * an application can define its own EVP calls for AES counter mode and then 116*7211Sjp161948 * it can make use of hardware acceleration through this engine. However, it's 117*7211Sjp161948 * better if we keep AES CTR support code under ifdef's. 118*7211Sjp161948 */ 119*7211Sjp161948 #define SOLARIS_AES_CTR 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate #include "security/cryptoki.h" 1220Sstevel@tonic-gate #include "security/pkcs11.h" 1230Sstevel@tonic-gate #include "hw_pk11_err.c" 1240Sstevel@tonic-gate 125*7211Sjp161948 #ifdef SOLARIS_AES_CTR 126*7211Sjp161948 /* 127*7211Sjp161948 * NIDs for AES counter mode that will be defined during the engine 128*7211Sjp161948 * initialization. 129*7211Sjp161948 */ 130*7211Sjp161948 int NID_aes_128_ctr = NID_undef; 131*7211Sjp161948 int NID_aes_192_ctr = NID_undef; 132*7211Sjp161948 int NID_aes_256_ctr = NID_undef; 133*7211Sjp161948 #endif /* SOLARIS_AES_CTR */ 134*7211Sjp161948 135*7211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 136*7211Sjp161948 /* 137*7211Sjp161948 * Tables for symmetric ciphers and digest mechs found in the pkcs11_kernel 138*7211Sjp161948 * library. See comment at check_hw_mechanisms() for more information. 139*7211Sjp161948 */ 140*7211Sjp161948 int *hw_cnids; 141*7211Sjp161948 int *hw_dnids; 142*7211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 143*7211Sjp161948 144*7211Sjp161948 /* 145*7211Sjp161948 * Heads of the free PK11 session lists. We have three groups of algorithms in 146*7211Sjp161948 * the engine. Public key mechanisms, random operations, and symetric ciphers 147*7211Sjp161948 * and digests. We can use a different slot for each group so we must keep a 148*7211Sjp161948 * separate cache of sessions for them. 149*7211Sjp161948 */ 150*7211Sjp161948 static struct PK11_SESSION_st *pubkey_free_session = NULL; 151*7211Sjp161948 static struct PK11_SESSION_st *rand_free_session = NULL; 1520Sstevel@tonic-gate static struct PK11_SESSION_st *free_session = NULL; 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate /* Create all secret key objects in a global session so that they are available 1550Sstevel@tonic-gate * to use for other sessions. These other sessions may be opened or closed 1560Sstevel@tonic-gate * without losing the secret key objects */ 1570Sstevel@tonic-gate static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE; 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate /* ENGINE level stuff */ 1600Sstevel@tonic-gate static int pk11_init(ENGINE *e); 1610Sstevel@tonic-gate static int pk11_library_init(ENGINE *e); 1620Sstevel@tonic-gate static int pk11_finish(ENGINE *e); 1630Sstevel@tonic-gate static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); 1640Sstevel@tonic-gate static int pk11_destroy(ENGINE *e); 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate /* RAND stuff */ 1670Sstevel@tonic-gate static void pk11_rand_seed(const void *buf, int num); 1680Sstevel@tonic-gate static void pk11_rand_add(const void *buf, int num, double add_entropy); 1690Sstevel@tonic-gate static void pk11_rand_cleanup(void); 1700Sstevel@tonic-gate static int pk11_rand_bytes(unsigned char *buf, int num); 1710Sstevel@tonic-gate static int pk11_rand_status(void); 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate /* These functions are also used in other files */ 174*7211Sjp161948 PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); 175*7211Sjp161948 void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); 1766847Svk199839 1776847Svk199839 /* active list manipulation functions used here */ 1786847Svk199839 int pk11_active_delete(CK_OBJECT_HANDLE h); 1796847Svk199839 1806847Svk199839 #ifndef OPENSSL_NO_RSA 1810Sstevel@tonic-gate int pk11_destroy_rsa_key_objects(PK11_SESSION *session); 1826847Svk199839 int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); 1836847Svk199839 int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); 1846847Svk199839 #endif 1856847Svk199839 #ifndef OPENSSL_NO_DSA 1860Sstevel@tonic-gate int pk11_destroy_dsa_key_objects(PK11_SESSION *session); 1876847Svk199839 int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); 1886847Svk199839 int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); 1896847Svk199839 #endif 1906847Svk199839 #ifndef OPENSSL_NO_DH 1910Sstevel@tonic-gate int pk11_destroy_dh_key_objects(PK11_SESSION *session); 1926847Svk199839 int pk11_destroy_dh_object(PK11_SESSION *session, CK_BBOOL uselock); 1936847Svk199839 #endif 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate /* Local helper functions */ 196*7211Sjp161948 static int pk11_free_all_sessions(void); 197*7211Sjp161948 static int pk11_free_session_list(PK11_SESSION **sp); 198*7211Sjp161948 static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype); 1990Sstevel@tonic-gate static int pk11_destroy_cipher_key_objects(PK11_SESSION *session); 2006847Svk199839 static int pk11_destroy_object(CK_SESSION_HANDLE session, 2010Sstevel@tonic-gate CK_OBJECT_HANDLE oh); 2020Sstevel@tonic-gate static const char *get_PK11_LIBNAME(void); 2030Sstevel@tonic-gate static void free_PK11_LIBNAME(void); 2040Sstevel@tonic-gate static long set_PK11_LIBNAME(const char *name); 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate /* Symmetric cipher and digest support functions */ 2070Sstevel@tonic-gate static int cipher_nid_to_pk11(int nid); 208*7211Sjp161948 #ifdef SOLARIS_AES_CTR 209*7211Sjp161948 static int pk11_add_NID(char *sn, char *ln); 210*7211Sjp161948 static int pk11_add_aes_ctr_NIDs(void); 211*7211Sjp161948 #endif /* SOLARIS_AES_CTR */ 2120Sstevel@tonic-gate static int pk11_usable_ciphers(const int **nids); 2130Sstevel@tonic-gate static int pk11_usable_digests(const int **nids); 2140Sstevel@tonic-gate static int pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, 2150Sstevel@tonic-gate const unsigned char *iv, int enc); 2160Sstevel@tonic-gate static int pk11_cipher_final(PK11_SESSION *sp); 2170Sstevel@tonic-gate static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 2180Sstevel@tonic-gate const unsigned char *in, unsigned int inl); 2190Sstevel@tonic-gate static int pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx); 2200Sstevel@tonic-gate static int pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 2210Sstevel@tonic-gate const int **nids, int nid); 2220Sstevel@tonic-gate static int pk11_engine_digests(ENGINE *e, const EVP_MD **digest, 2230Sstevel@tonic-gate const int **nids, int nid); 2240Sstevel@tonic-gate static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, 2250Sstevel@tonic-gate const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp); 226*7211Sjp161948 static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key, 227*7211Sjp161948 int key_len); 2280Sstevel@tonic-gate static int md_nid_to_pk11(int nid); 2290Sstevel@tonic-gate static int pk11_digest_init(EVP_MD_CTX *ctx); 2300Sstevel@tonic-gate static int pk11_digest_update(EVP_MD_CTX *ctx,const void *data, 2312139Sjp161948 size_t count); 2320Sstevel@tonic-gate static int pk11_digest_final(EVP_MD_CTX *ctx,unsigned char *md); 2330Sstevel@tonic-gate static int pk11_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from); 2340Sstevel@tonic-gate static int pk11_digest_cleanup(EVP_MD_CTX *ctx); 2350Sstevel@tonic-gate 236*7211Sjp161948 static int pk11_choose_slots(int *any_slot_found); 237*7211Sjp161948 static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist, 238*7211Sjp161948 CK_SLOT_ID current_slot, int *current_slot_n_cipher, 239*7211Sjp161948 int *local_cipher_nids); 240*7211Sjp161948 static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist, 241*7211Sjp161948 CK_SLOT_ID current_slot, int *current_slot_n_digest, 242*7211Sjp161948 int *local_digest_nids); 243*7211Sjp161948 static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR, int slot_id, 244*7211Sjp161948 CK_MECHANISM_TYPE mech, int *current_slot_n_cipher, int *local_cipher_nids, 245*7211Sjp161948 int id); 246*7211Sjp161948 static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id, 247*7211Sjp161948 CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids, 248*7211Sjp161948 int id); 249*7211Sjp161948 250*7211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 251*7211Sjp161948 static int check_hw_mechanisms(void); 252*7211Sjp161948 static int nid_in_table(int nid, int *nid_table); 253*7211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate /* Index for the supported ciphers */ 256*7211Sjp161948 enum pk11_cipher_id { 257*7211Sjp161948 PK11_DES_CBC, 258*7211Sjp161948 PK11_DES3_CBC, 259*7211Sjp161948 PK11_DES_ECB, 260*7211Sjp161948 PK11_DES3_ECB, 261*7211Sjp161948 PK11_RC4, 262*7211Sjp161948 PK11_AES_128_CBC, 263*7211Sjp161948 PK11_AES_192_CBC, 264*7211Sjp161948 PK11_AES_256_CBC, 265*7211Sjp161948 PK11_AES_128_ECB, 266*7211Sjp161948 PK11_AES_192_ECB, 267*7211Sjp161948 PK11_AES_256_ECB, 268*7211Sjp161948 PK11_BLOWFISH_CBC, 269*7211Sjp161948 #ifdef SOLARIS_AES_CTR 270*7211Sjp161948 PK11_AES_128_CTR, 271*7211Sjp161948 PK11_AES_192_CTR, 272*7211Sjp161948 PK11_AES_256_CTR, 273*7211Sjp161948 #endif /* SOLARIS_AES_CTR */ 274*7211Sjp161948 PK11_CIPHER_MAX 275*7211Sjp161948 }; 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate /* Index for the supported digests */ 278*7211Sjp161948 enum pk11_digest_id { 279*7211Sjp161948 PK11_MD5, 280*7211Sjp161948 PK11_SHA1, 281*7211Sjp161948 PK11_SHA224, 282*7211Sjp161948 PK11_SHA256, 283*7211Sjp161948 PK11_SHA384, 284*7211Sjp161948 PK11_SHA512, 285*7211Sjp161948 PK11_DIGEST_MAX 286*7211Sjp161948 }; 2870Sstevel@tonic-gate 2886847Svk199839 #define TRY_OBJ_DESTROY(sess_hdl, obj_hdl, retval, uselock) \ 2896847Svk199839 { \ 2906847Svk199839 if (uselock) \ 2916847Svk199839 CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); \ 2926847Svk199839 if (pk11_active_delete(obj_hdl) == 1) \ 2936847Svk199839 { \ 2946847Svk199839 retval = pk11_destroy_object(sess_hdl, obj_hdl); \ 2956847Svk199839 } \ 2966847Svk199839 if (uselock) \ 2976847Svk199839 CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); \ 2986847Svk199839 } 2996847Svk199839 3000Sstevel@tonic-gate static int cipher_nids[PK11_CIPHER_MAX]; 3010Sstevel@tonic-gate static int digest_nids[PK11_DIGEST_MAX]; 3020Sstevel@tonic-gate static int cipher_count = 0; 3030Sstevel@tonic-gate static int digest_count = 0; 3040Sstevel@tonic-gate static CK_BBOOL pk11_have_rsa = CK_FALSE; 3050Sstevel@tonic-gate static CK_BBOOL pk11_have_dsa = CK_FALSE; 3060Sstevel@tonic-gate static CK_BBOOL pk11_have_dh = CK_FALSE; 3070Sstevel@tonic-gate static CK_BBOOL pk11_have_random = CK_FALSE; 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate typedef struct PK11_CIPHER_st 3100Sstevel@tonic-gate { 311*7211Sjp161948 enum pk11_cipher_id id; 3124320Sjp161948 int nid; 313*7211Sjp161948 int iv_len; 3144320Sjp161948 int key_len; 3154320Sjp161948 CK_KEY_TYPE key_type; 3164320Sjp161948 CK_MECHANISM_TYPE mech_type; 3170Sstevel@tonic-gate } PK11_CIPHER; 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate static PK11_CIPHER ciphers[] = 3200Sstevel@tonic-gate { 321*7211Sjp161948 {PK11_DES_CBC, NID_des_cbc, 8, 8, CKK_DES, CKM_DES_CBC, }, 322*7211Sjp161948 {PK11_DES3_CBC, NID_des_ede3_cbc, 8, 24, CKK_DES3, CKM_DES3_CBC, }, 323*7211Sjp161948 {PK11_DES_ECB, NID_des_ecb, 0, 8, CKK_DES, CKM_DES_ECB, }, 324*7211Sjp161948 {PK11_DES3_ECB, NID_des_ede3_ecb, 0, 24, CKK_DES3, CKM_DES3_ECB, }, 325*7211Sjp161948 {PK11_RC4, NID_rc4, 0, 16, CKK_RC4, CKM_RC4, }, 326*7211Sjp161948 {PK11_AES_128_CBC, NID_aes_128_cbc, 16, 16, CKK_AES, CKM_AES_CBC, }, 327*7211Sjp161948 {PK11_AES_192_CBC, NID_aes_192_cbc, 16, 24, CKK_AES, CKM_AES_CBC, }, 328*7211Sjp161948 {PK11_AES_256_CBC, NID_aes_256_cbc, 16, 32, CKK_AES, CKM_AES_CBC, }, 329*7211Sjp161948 {PK11_AES_128_ECB, NID_aes_128_ecb, 0, 16, CKK_AES, CKM_AES_ECB, }, 330*7211Sjp161948 {PK11_AES_192_ECB, NID_aes_192_ecb, 0, 24, CKK_AES, CKM_AES_ECB, }, 331*7211Sjp161948 {PK11_AES_256_ECB, NID_aes_256_ecb, 0, 32, CKK_AES, CKM_AES_ECB, }, 332*7211Sjp161948 {PK11_BLOWFISH_CBC,NID_bf_cbc, 8, 16, CKK_BLOWFISH, CKM_BLOWFISH_CBC,}, 333*7211Sjp161948 #ifdef SOLARIS_AES_CTR 334*7211Sjp161948 /* we don't know the correct NIDs until the engine is initialized */ 335*7211Sjp161948 {PK11_AES_128_CTR, NID_undef, 16, 16, CKK_AES, CKM_AES_CTR, }, 336*7211Sjp161948 {PK11_AES_192_CTR, NID_undef, 16, 24, CKK_AES, CKM_AES_CTR, }, 337*7211Sjp161948 {PK11_AES_256_CTR, NID_undef, 16, 32, CKK_AES, CKM_AES_CTR, }, 338*7211Sjp161948 #endif /* SOLARIS_AES_CTR */ 3390Sstevel@tonic-gate }; 3400Sstevel@tonic-gate 3410Sstevel@tonic-gate typedef struct PK11_DIGEST_st 3420Sstevel@tonic-gate { 343*7211Sjp161948 enum pk11_digest_id id; 3444320Sjp161948 int nid; 3454320Sjp161948 CK_MECHANISM_TYPE mech_type; 3460Sstevel@tonic-gate } PK11_DIGEST; 3470Sstevel@tonic-gate 3480Sstevel@tonic-gate static PK11_DIGEST digests[] = 3490Sstevel@tonic-gate { 3504320Sjp161948 {PK11_MD5, NID_md5, CKM_MD5, }, 3514320Sjp161948 {PK11_SHA1, NID_sha1, CKM_SHA_1, }, 352*7211Sjp161948 {PK11_SHA224, NID_sha224, CKM_SHA224, }, 353*7211Sjp161948 {PK11_SHA256, NID_sha256, CKM_SHA256, }, 354*7211Sjp161948 {PK11_SHA384, NID_sha384, CKM_SHA384, }, 355*7211Sjp161948 {PK11_SHA512, NID_sha512, CKM_SHA512, }, 3564320Sjp161948 {0, NID_undef, 0xFFFF, }, 3570Sstevel@tonic-gate }; 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate /* Structure to be used for the cipher_data/md_data in 3600Sstevel@tonic-gate * EVP_CIPHER_CTX/EVP_MD_CTX structures in order to use the same 3610Sstevel@tonic-gate * pk11 session in multiple cipher_update calls 3620Sstevel@tonic-gate */ 3630Sstevel@tonic-gate typedef struct PK11_CIPHER_STATE_st 3640Sstevel@tonic-gate { 3650Sstevel@tonic-gate PK11_SESSION *sp; 3660Sstevel@tonic-gate } PK11_CIPHER_STATE; 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate 369*7211Sjp161948 /* 370*7211Sjp161948 * libcrypto EVP stuff - this is how we get wired to EVP so the engine gets 371*7211Sjp161948 * called when libcrypto requests a cipher NID. 372*7211Sjp161948 * 3730Sstevel@tonic-gate * Note how the PK11_CIPHER_STATE is used here. 3740Sstevel@tonic-gate */ 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate /* DES CBC EVP */ 3770Sstevel@tonic-gate static const EVP_CIPHER pk11_des_cbc = 3780Sstevel@tonic-gate { 3790Sstevel@tonic-gate NID_des_cbc, 3800Sstevel@tonic-gate 8, 8, 8, 3810Sstevel@tonic-gate EVP_CIPH_CBC_MODE, 3820Sstevel@tonic-gate pk11_cipher_init, 3830Sstevel@tonic-gate pk11_cipher_do_cipher, 3840Sstevel@tonic-gate pk11_cipher_cleanup, 3850Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 3860Sstevel@tonic-gate EVP_CIPHER_set_asn1_iv, 3870Sstevel@tonic-gate EVP_CIPHER_get_asn1_iv, 3880Sstevel@tonic-gate NULL 3890Sstevel@tonic-gate }; 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate /* 3DES CBC EVP */ 3920Sstevel@tonic-gate static const EVP_CIPHER pk11_3des_cbc = 3930Sstevel@tonic-gate { 3940Sstevel@tonic-gate NID_des_ede3_cbc, 3950Sstevel@tonic-gate 8, 24, 8, 3960Sstevel@tonic-gate EVP_CIPH_CBC_MODE, 3970Sstevel@tonic-gate pk11_cipher_init, 3980Sstevel@tonic-gate pk11_cipher_do_cipher, 3990Sstevel@tonic-gate pk11_cipher_cleanup, 4000Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 4010Sstevel@tonic-gate EVP_CIPHER_set_asn1_iv, 4020Sstevel@tonic-gate EVP_CIPHER_get_asn1_iv, 4030Sstevel@tonic-gate NULL 4040Sstevel@tonic-gate }; 4050Sstevel@tonic-gate 406*7211Sjp161948 /* 407*7211Sjp161948 * ECB modes don't use an Initial Vector so that's why set_asn1_parameters and 408*7211Sjp161948 * get_asn1_parameters fields are set to NULL. 409*7211Sjp161948 */ 410*7211Sjp161948 static const EVP_CIPHER pk11_des_ecb = 411*7211Sjp161948 { 412*7211Sjp161948 NID_des_ecb, 413*7211Sjp161948 8, 8, 8, 414*7211Sjp161948 EVP_CIPH_ECB_MODE, 415*7211Sjp161948 pk11_cipher_init, 416*7211Sjp161948 pk11_cipher_do_cipher, 417*7211Sjp161948 pk11_cipher_cleanup, 418*7211Sjp161948 sizeof(PK11_CIPHER_STATE), 419*7211Sjp161948 NULL, 420*7211Sjp161948 NULL, 421*7211Sjp161948 NULL 422*7211Sjp161948 }; 423*7211Sjp161948 424*7211Sjp161948 static const EVP_CIPHER pk11_3des_ecb = 425*7211Sjp161948 { 426*7211Sjp161948 NID_des_ede3_ecb, 427*7211Sjp161948 8, 24, 8, 428*7211Sjp161948 EVP_CIPH_ECB_MODE, 429*7211Sjp161948 pk11_cipher_init, 430*7211Sjp161948 pk11_cipher_do_cipher, 431*7211Sjp161948 pk11_cipher_cleanup, 432*7211Sjp161948 sizeof(PK11_CIPHER_STATE), 433*7211Sjp161948 NULL, 434*7211Sjp161948 NULL, 435*7211Sjp161948 NULL 436*7211Sjp161948 }; 437*7211Sjp161948 438*7211Sjp161948 439*7211Sjp161948 static const EVP_CIPHER pk11_aes_128_cbc = 4400Sstevel@tonic-gate { 4410Sstevel@tonic-gate NID_aes_128_cbc, 4420Sstevel@tonic-gate 16, 16, 16, 4430Sstevel@tonic-gate EVP_CIPH_CBC_MODE, 4440Sstevel@tonic-gate pk11_cipher_init, 4450Sstevel@tonic-gate pk11_cipher_do_cipher, 4460Sstevel@tonic-gate pk11_cipher_cleanup, 4470Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 4480Sstevel@tonic-gate EVP_CIPHER_set_asn1_iv, 4490Sstevel@tonic-gate EVP_CIPHER_get_asn1_iv, 4500Sstevel@tonic-gate NULL 4510Sstevel@tonic-gate }; 4520Sstevel@tonic-gate 453*7211Sjp161948 static const EVP_CIPHER pk11_aes_192_cbc = 454*7211Sjp161948 { 455*7211Sjp161948 NID_aes_192_cbc, 456*7211Sjp161948 16, 24, 16, 457*7211Sjp161948 EVP_CIPH_CBC_MODE, 458*7211Sjp161948 pk11_cipher_init, 459*7211Sjp161948 pk11_cipher_do_cipher, 460*7211Sjp161948 pk11_cipher_cleanup, 461*7211Sjp161948 sizeof(PK11_CIPHER_STATE), 462*7211Sjp161948 EVP_CIPHER_set_asn1_iv, 463*7211Sjp161948 EVP_CIPHER_get_asn1_iv, 464*7211Sjp161948 NULL 465*7211Sjp161948 }; 466*7211Sjp161948 467*7211Sjp161948 static const EVP_CIPHER pk11_aes_256_cbc = 468*7211Sjp161948 { 469*7211Sjp161948 NID_aes_256_cbc, 470*7211Sjp161948 16, 32, 16, 471*7211Sjp161948 EVP_CIPH_CBC_MODE, 472*7211Sjp161948 pk11_cipher_init, 473*7211Sjp161948 pk11_cipher_do_cipher, 474*7211Sjp161948 pk11_cipher_cleanup, 475*7211Sjp161948 sizeof(PK11_CIPHER_STATE), 476*7211Sjp161948 EVP_CIPHER_set_asn1_iv, 477*7211Sjp161948 EVP_CIPHER_get_asn1_iv, 478*7211Sjp161948 NULL 479*7211Sjp161948 }; 480*7211Sjp161948 481*7211Sjp161948 /* 482*7211Sjp161948 * ECB modes don't use IV so that's why set_asn1_parameters and 483*7211Sjp161948 * get_asn1_parameters are set to NULL. 484*7211Sjp161948 */ 485*7211Sjp161948 static const EVP_CIPHER pk11_aes_128_ecb = 486*7211Sjp161948 { 487*7211Sjp161948 NID_aes_128_ecb, 488*7211Sjp161948 16, 16, 0, 489*7211Sjp161948 EVP_CIPH_ECB_MODE, 490*7211Sjp161948 pk11_cipher_init, 491*7211Sjp161948 pk11_cipher_do_cipher, 492*7211Sjp161948 pk11_cipher_cleanup, 493*7211Sjp161948 sizeof(PK11_CIPHER_STATE), 494*7211Sjp161948 NULL, 495*7211Sjp161948 NULL, 496*7211Sjp161948 NULL 497*7211Sjp161948 }; 498*7211Sjp161948 499*7211Sjp161948 static const EVP_CIPHER pk11_aes_192_ecb = 500*7211Sjp161948 { 501*7211Sjp161948 NID_aes_192_ecb, 502*7211Sjp161948 16, 24, 0, 503*7211Sjp161948 EVP_CIPH_ECB_MODE, 504*7211Sjp161948 pk11_cipher_init, 505*7211Sjp161948 pk11_cipher_do_cipher, 506*7211Sjp161948 pk11_cipher_cleanup, 507*7211Sjp161948 sizeof(PK11_CIPHER_STATE), 508*7211Sjp161948 NULL, 509*7211Sjp161948 NULL, 510*7211Sjp161948 NULL 511*7211Sjp161948 }; 512*7211Sjp161948 513*7211Sjp161948 static const EVP_CIPHER pk11_aes_256_ecb = 514*7211Sjp161948 { 515*7211Sjp161948 NID_aes_256_ecb, 516*7211Sjp161948 16, 32, 0, 517*7211Sjp161948 EVP_CIPH_ECB_MODE, 518*7211Sjp161948 pk11_cipher_init, 519*7211Sjp161948 pk11_cipher_do_cipher, 520*7211Sjp161948 pk11_cipher_cleanup, 521*7211Sjp161948 sizeof(PK11_CIPHER_STATE), 522*7211Sjp161948 NULL, 523*7211Sjp161948 NULL, 524*7211Sjp161948 NULL 525*7211Sjp161948 }; 526*7211Sjp161948 527*7211Sjp161948 #ifdef SOLARIS_AES_CTR 528*7211Sjp161948 /* 529*7211Sjp161948 * NID_undef's will be changed to the AES counter mode NIDs as soon they are 530*7211Sjp161948 * created in pk11_library_init(). Note that the need to change these structures 531*7211Sjp161948 * is the reason why we don't define them with the const keyword. 532*7211Sjp161948 */ 533*7211Sjp161948 static EVP_CIPHER pk11_aes_128_ctr = 534*7211Sjp161948 { 535*7211Sjp161948 NID_undef, 536*7211Sjp161948 16, 16, 16, 537*7211Sjp161948 EVP_CIPH_CBC_MODE, 538*7211Sjp161948 pk11_cipher_init, 539*7211Sjp161948 pk11_cipher_do_cipher, 540*7211Sjp161948 pk11_cipher_cleanup, 541*7211Sjp161948 sizeof(PK11_CIPHER_STATE), 542*7211Sjp161948 EVP_CIPHER_set_asn1_iv, 543*7211Sjp161948 EVP_CIPHER_get_asn1_iv, 544*7211Sjp161948 NULL 545*7211Sjp161948 }; 546*7211Sjp161948 547*7211Sjp161948 static EVP_CIPHER pk11_aes_192_ctr = 548*7211Sjp161948 { 549*7211Sjp161948 NID_undef, 550*7211Sjp161948 16, 24, 16, 551*7211Sjp161948 EVP_CIPH_CBC_MODE, 552*7211Sjp161948 pk11_cipher_init, 553*7211Sjp161948 pk11_cipher_do_cipher, 554*7211Sjp161948 pk11_cipher_cleanup, 555*7211Sjp161948 sizeof(PK11_CIPHER_STATE), 556*7211Sjp161948 EVP_CIPHER_set_asn1_iv, 557*7211Sjp161948 EVP_CIPHER_get_asn1_iv, 558*7211Sjp161948 NULL 559*7211Sjp161948 }; 560*7211Sjp161948 561*7211Sjp161948 static EVP_CIPHER pk11_aes_256_ctr = 562*7211Sjp161948 { 563*7211Sjp161948 NID_undef, 564*7211Sjp161948 16, 32, 16, 565*7211Sjp161948 EVP_CIPH_CBC_MODE, 566*7211Sjp161948 pk11_cipher_init, 567*7211Sjp161948 pk11_cipher_do_cipher, 568*7211Sjp161948 pk11_cipher_cleanup, 569*7211Sjp161948 sizeof(PK11_CIPHER_STATE), 570*7211Sjp161948 EVP_CIPHER_set_asn1_iv, 571*7211Sjp161948 EVP_CIPHER_get_asn1_iv, 572*7211Sjp161948 NULL 573*7211Sjp161948 }; 574*7211Sjp161948 #endif /* SOLARIS_AES_CTR */ 575*7211Sjp161948 576*7211Sjp161948 static const EVP_CIPHER pk11_bf_cbc = 577*7211Sjp161948 { 578*7211Sjp161948 NID_bf_cbc, 579*7211Sjp161948 8, 16, 8, 580*7211Sjp161948 EVP_CIPH_VARIABLE_LENGTH, 581*7211Sjp161948 pk11_cipher_init, 582*7211Sjp161948 pk11_cipher_do_cipher, 583*7211Sjp161948 pk11_cipher_cleanup, 584*7211Sjp161948 sizeof(PK11_CIPHER_STATE), 585*7211Sjp161948 EVP_CIPHER_set_asn1_iv, 586*7211Sjp161948 EVP_CIPHER_get_asn1_iv, 587*7211Sjp161948 NULL 588*7211Sjp161948 }; 589*7211Sjp161948 5900Sstevel@tonic-gate static const EVP_CIPHER pk11_rc4 = 5910Sstevel@tonic-gate { 5920Sstevel@tonic-gate NID_rc4, 593*7211Sjp161948 1, 16, 0, 5940Sstevel@tonic-gate EVP_CIPH_VARIABLE_LENGTH, 5950Sstevel@tonic-gate pk11_cipher_init, 5960Sstevel@tonic-gate pk11_cipher_do_cipher, 5970Sstevel@tonic-gate pk11_cipher_cleanup, 5980Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 5990Sstevel@tonic-gate NULL, 6000Sstevel@tonic-gate NULL, 6010Sstevel@tonic-gate NULL 6020Sstevel@tonic-gate }; 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate static const EVP_MD pk11_md5 = 6050Sstevel@tonic-gate { 6060Sstevel@tonic-gate NID_md5, 6070Sstevel@tonic-gate NID_md5WithRSAEncryption, 6080Sstevel@tonic-gate MD5_DIGEST_LENGTH, 6090Sstevel@tonic-gate 0, 6100Sstevel@tonic-gate pk11_digest_init, 6110Sstevel@tonic-gate pk11_digest_update, 6120Sstevel@tonic-gate pk11_digest_final, 6130Sstevel@tonic-gate pk11_digest_copy, 6140Sstevel@tonic-gate pk11_digest_cleanup, 6150Sstevel@tonic-gate EVP_PKEY_RSA_method, 6160Sstevel@tonic-gate MD5_CBLOCK, 6170Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 6180Sstevel@tonic-gate }; 6190Sstevel@tonic-gate 6200Sstevel@tonic-gate static const EVP_MD pk11_sha1 = 6210Sstevel@tonic-gate { 6220Sstevel@tonic-gate NID_sha1, 6230Sstevel@tonic-gate NID_sha1WithRSAEncryption, 6240Sstevel@tonic-gate SHA_DIGEST_LENGTH, 6250Sstevel@tonic-gate 0, 6260Sstevel@tonic-gate pk11_digest_init, 6270Sstevel@tonic-gate pk11_digest_update, 6280Sstevel@tonic-gate pk11_digest_final, 6290Sstevel@tonic-gate pk11_digest_copy, 6300Sstevel@tonic-gate pk11_digest_cleanup, 6310Sstevel@tonic-gate EVP_PKEY_RSA_method, 6320Sstevel@tonic-gate SHA_CBLOCK, 6330Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 6340Sstevel@tonic-gate }; 6350Sstevel@tonic-gate 636*7211Sjp161948 static const EVP_MD pk11_sha224 = 637*7211Sjp161948 { 638*7211Sjp161948 NID_sha224, 639*7211Sjp161948 NID_sha224WithRSAEncryption, 640*7211Sjp161948 SHA224_DIGEST_LENGTH, 641*7211Sjp161948 0, 642*7211Sjp161948 pk11_digest_init, 643*7211Sjp161948 pk11_digest_update, 644*7211Sjp161948 pk11_digest_final, 645*7211Sjp161948 pk11_digest_copy, 646*7211Sjp161948 pk11_digest_cleanup, 647*7211Sjp161948 EVP_PKEY_RSA_method, 648*7211Sjp161948 /* SHA-224 uses the same cblock size as SHA-256 */ 649*7211Sjp161948 SHA256_CBLOCK, 650*7211Sjp161948 sizeof(PK11_CIPHER_STATE), 651*7211Sjp161948 }; 652*7211Sjp161948 653*7211Sjp161948 static const EVP_MD pk11_sha256 = 654*7211Sjp161948 { 655*7211Sjp161948 NID_sha256, 656*7211Sjp161948 NID_sha256WithRSAEncryption, 657*7211Sjp161948 SHA256_DIGEST_LENGTH, 658*7211Sjp161948 0, 659*7211Sjp161948 pk11_digest_init, 660*7211Sjp161948 pk11_digest_update, 661*7211Sjp161948 pk11_digest_final, 662*7211Sjp161948 pk11_digest_copy, 663*7211Sjp161948 pk11_digest_cleanup, 664*7211Sjp161948 EVP_PKEY_RSA_method, 665*7211Sjp161948 SHA256_CBLOCK, 666*7211Sjp161948 sizeof(PK11_CIPHER_STATE), 667*7211Sjp161948 }; 668*7211Sjp161948 669*7211Sjp161948 static const EVP_MD pk11_sha384 = 670*7211Sjp161948 { 671*7211Sjp161948 NID_sha384, 672*7211Sjp161948 NID_sha384WithRSAEncryption, 673*7211Sjp161948 SHA384_DIGEST_LENGTH, 674*7211Sjp161948 0, 675*7211Sjp161948 pk11_digest_init, 676*7211Sjp161948 pk11_digest_update, 677*7211Sjp161948 pk11_digest_final, 678*7211Sjp161948 pk11_digest_copy, 679*7211Sjp161948 pk11_digest_cleanup, 680*7211Sjp161948 EVP_PKEY_RSA_method, 681*7211Sjp161948 /* SHA-384 uses the same cblock size as SHA-512 */ 682*7211Sjp161948 SHA512_CBLOCK, 683*7211Sjp161948 sizeof(PK11_CIPHER_STATE), 684*7211Sjp161948 }; 685*7211Sjp161948 686*7211Sjp161948 static const EVP_MD pk11_sha512 = 687*7211Sjp161948 { 688*7211Sjp161948 NID_sha512, 689*7211Sjp161948 NID_sha512WithRSAEncryption, 690*7211Sjp161948 SHA512_DIGEST_LENGTH, 691*7211Sjp161948 0, 692*7211Sjp161948 pk11_digest_init, 693*7211Sjp161948 pk11_digest_update, 694*7211Sjp161948 pk11_digest_final, 695*7211Sjp161948 pk11_digest_copy, 696*7211Sjp161948 pk11_digest_cleanup, 697*7211Sjp161948 EVP_PKEY_RSA_method, 698*7211Sjp161948 SHA512_CBLOCK, 699*7211Sjp161948 sizeof(PK11_CIPHER_STATE), 700*7211Sjp161948 }; 701*7211Sjp161948 7020Sstevel@tonic-gate /* Initialization function. Sets up various pk11 library components. 7030Sstevel@tonic-gate */ 7040Sstevel@tonic-gate /* The definitions for control commands specific to this engine 7050Sstevel@tonic-gate */ 7060Sstevel@tonic-gate #define PK11_CMD_SO_PATH ENGINE_CMD_BASE 7070Sstevel@tonic-gate static const ENGINE_CMD_DEFN pk11_cmd_defns[] = 7080Sstevel@tonic-gate { 7090Sstevel@tonic-gate { 7100Sstevel@tonic-gate PK11_CMD_SO_PATH, 7110Sstevel@tonic-gate "SO_PATH", 7120Sstevel@tonic-gate "Specifies the path to the 'pkcs#11' shared library", 7130Sstevel@tonic-gate ENGINE_CMD_FLAG_STRING 7140Sstevel@tonic-gate }, 7150Sstevel@tonic-gate {0, NULL, NULL, 0} 7160Sstevel@tonic-gate }; 7170Sstevel@tonic-gate 7180Sstevel@tonic-gate 7190Sstevel@tonic-gate static RAND_METHOD pk11_random = 7200Sstevel@tonic-gate { 7210Sstevel@tonic-gate pk11_rand_seed, 7220Sstevel@tonic-gate pk11_rand_bytes, 7230Sstevel@tonic-gate pk11_rand_cleanup, 7240Sstevel@tonic-gate pk11_rand_add, 7250Sstevel@tonic-gate pk11_rand_bytes, 7260Sstevel@tonic-gate pk11_rand_status 7270Sstevel@tonic-gate }; 7280Sstevel@tonic-gate 7290Sstevel@tonic-gate 7300Sstevel@tonic-gate /* Constants used when creating the ENGINE 7310Sstevel@tonic-gate */ 7320Sstevel@tonic-gate static const char *engine_pk11_id = "pkcs11"; 7330Sstevel@tonic-gate static const char *engine_pk11_name = "PKCS #11 engine support"; 7340Sstevel@tonic-gate 7350Sstevel@tonic-gate CK_FUNCTION_LIST_PTR pFuncList = NULL; 7360Sstevel@tonic-gate static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList"; 7370Sstevel@tonic-gate 7380Sstevel@tonic-gate /* These are the static string constants for the DSO file name and the function 739*7211Sjp161948 * symbol names to bind to. 7400Sstevel@tonic-gate */ 7410Sstevel@tonic-gate #if defined(__sparcv9) || defined(__x86_64) || defined(__amd64) 7420Sstevel@tonic-gate static const char def_PK11_LIBNAME[] = "/usr/lib/64/libpkcs11.so.1"; 7430Sstevel@tonic-gate #else 7440Sstevel@tonic-gate static const char def_PK11_LIBNAME[] = "/usr/lib/libpkcs11.so.1"; 7450Sstevel@tonic-gate #endif 7460Sstevel@tonic-gate 7470Sstevel@tonic-gate static CK_BBOOL true = TRUE; 7480Sstevel@tonic-gate static CK_BBOOL false = FALSE; 749*7211Sjp161948 static CK_SLOT_ID pubkey_SLOTID = 0; 750*7211Sjp161948 static CK_SLOT_ID rand_SLOTID = 0; 7510Sstevel@tonic-gate static CK_SLOT_ID SLOTID = 0; 7520Sstevel@tonic-gate static int pk11_library_initialized = 0; 753*7211Sjp161948 static int pk11_pid = 0; 7540Sstevel@tonic-gate 7550Sstevel@tonic-gate static DSO *pk11_dso = NULL; 7560Sstevel@tonic-gate 7570Sstevel@tonic-gate /* 7580Sstevel@tonic-gate * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support. 7590Sstevel@tonic-gate */ 7600Sstevel@tonic-gate static int bind_pk11(ENGINE *e) 7610Sstevel@tonic-gate { 7626847Svk199839 #ifndef OPENSSL_NO_RSA 7630Sstevel@tonic-gate const RSA_METHOD *rsa = NULL; 7640Sstevel@tonic-gate RSA_METHOD *pk11_rsa = PK11_RSA(); 765*7211Sjp161948 #endif /* OPENSSL_NO_RSA */ 7660Sstevel@tonic-gate if (!pk11_library_initialized) 7670Sstevel@tonic-gate pk11_library_init(e); 7680Sstevel@tonic-gate 7690Sstevel@tonic-gate if(!ENGINE_set_id(e, engine_pk11_id) || 7700Sstevel@tonic-gate !ENGINE_set_name(e, engine_pk11_name) || 7710Sstevel@tonic-gate !ENGINE_set_ciphers(e, pk11_engine_ciphers) || 7720Sstevel@tonic-gate !ENGINE_set_digests(e, pk11_engine_digests)) 7730Sstevel@tonic-gate return 0; 7740Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA 7750Sstevel@tonic-gate if(pk11_have_rsa == CK_TRUE) 7760Sstevel@tonic-gate { 7770Sstevel@tonic-gate if(!ENGINE_set_RSA(e, PK11_RSA()) || 7780Sstevel@tonic-gate !ENGINE_set_load_privkey_function(e, pk11_load_privkey) || 7790Sstevel@tonic-gate !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey)) 7800Sstevel@tonic-gate return 0; 781*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 782*7211Sjp161948 fprintf(stderr, "%s: registered RSA\n", PK11_DBG); 783*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 7840Sstevel@tonic-gate } 785*7211Sjp161948 #endif /* OPENSSL_NO_RSA */ 7860Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA 7870Sstevel@tonic-gate if(pk11_have_dsa == CK_TRUE) 7880Sstevel@tonic-gate { 7890Sstevel@tonic-gate if (!ENGINE_set_DSA(e, PK11_DSA())) 7900Sstevel@tonic-gate return 0; 791*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 792*7211Sjp161948 fprintf(stderr, "%s: registered DSA\n", PK11_DBG); 793*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 7940Sstevel@tonic-gate } 795*7211Sjp161948 #endif /* OPENSSL_NO_DSA */ 7960Sstevel@tonic-gate #ifndef OPENSSL_NO_DH 7970Sstevel@tonic-gate if(pk11_have_dh == CK_TRUE) 7980Sstevel@tonic-gate { 7990Sstevel@tonic-gate if (!ENGINE_set_DH(e, PK11_DH())) 8000Sstevel@tonic-gate return 0; 801*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 802*7211Sjp161948 fprintf(stderr, "%s: registered DH\n", PK11_DBG); 803*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 8040Sstevel@tonic-gate } 805*7211Sjp161948 #endif /* OPENSSL_NO_DH */ 8060Sstevel@tonic-gate if(pk11_have_random) 8070Sstevel@tonic-gate { 8080Sstevel@tonic-gate if(!ENGINE_set_RAND(e, &pk11_random)) 8090Sstevel@tonic-gate return 0; 810*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 811*7211Sjp161948 fprintf(stderr, "%s: registered random\n", PK11_DBG); 812*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 8130Sstevel@tonic-gate } 8140Sstevel@tonic-gate if(!ENGINE_set_init_function(e, pk11_init) || 8150Sstevel@tonic-gate !ENGINE_set_destroy_function(e, pk11_destroy) || 8160Sstevel@tonic-gate !ENGINE_set_finish_function(e, pk11_finish) || 8170Sstevel@tonic-gate !ENGINE_set_ctrl_function(e, pk11_ctrl) || 8180Sstevel@tonic-gate !ENGINE_set_cmd_defns(e, pk11_cmd_defns)) 8190Sstevel@tonic-gate return 0; 8200Sstevel@tonic-gate 8210Sstevel@tonic-gate /* Apache calls OpenSSL function RSA_blinding_on() once during startup 8220Sstevel@tonic-gate * which in turn calls bn_mod_exp. Since we do not implement bn_mod_exp 8230Sstevel@tonic-gate * here, we wire it back to the OpenSSL software implementation. 8240Sstevel@tonic-gate * Since it is used only once, performance is not a concern. */ 8250Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA 8260Sstevel@tonic-gate rsa = RSA_PKCS1_SSLeay(); 8270Sstevel@tonic-gate pk11_rsa->rsa_mod_exp = rsa->rsa_mod_exp; 8280Sstevel@tonic-gate pk11_rsa->bn_mod_exp = rsa->bn_mod_exp; 829*7211Sjp161948 #endif /* OPENSSL_NO_RSA */ 8300Sstevel@tonic-gate 8310Sstevel@tonic-gate /* Ensure the pk11 error handling is set up */ 8320Sstevel@tonic-gate ERR_load_pk11_strings(); 8330Sstevel@tonic-gate 8340Sstevel@tonic-gate return 1; 8350Sstevel@tonic-gate } 8360Sstevel@tonic-gate 8370Sstevel@tonic-gate /* Dynamic engine support is disabled at a higher level for Solaris 8380Sstevel@tonic-gate */ 839*7211Sjp161948 #ifdef ENGINE_DYNAMIC_SUPPORT 8400Sstevel@tonic-gate static int bind_helper(ENGINE *e, const char *id) 8410Sstevel@tonic-gate { 8420Sstevel@tonic-gate if (id && (strcmp(id, engine_pk11_id) != 0)) 8430Sstevel@tonic-gate return 0; 8440Sstevel@tonic-gate 8450Sstevel@tonic-gate if (!bind_pk11(e)) 8460Sstevel@tonic-gate return 0; 8470Sstevel@tonic-gate 8480Sstevel@tonic-gate return 1; 8490Sstevel@tonic-gate } 8500Sstevel@tonic-gate 8510Sstevel@tonic-gate IMPLEMENT_DYNAMIC_CHECK_FN() 8520Sstevel@tonic-gate IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) 8530Sstevel@tonic-gate 8540Sstevel@tonic-gate #else 8550Sstevel@tonic-gate static ENGINE *engine_pk11(void) 8560Sstevel@tonic-gate { 8570Sstevel@tonic-gate ENGINE *ret = ENGINE_new(); 8580Sstevel@tonic-gate 8590Sstevel@tonic-gate if (!ret) 8600Sstevel@tonic-gate return NULL; 8610Sstevel@tonic-gate 8620Sstevel@tonic-gate if (!bind_pk11(ret)) 8630Sstevel@tonic-gate { 8640Sstevel@tonic-gate ENGINE_free(ret); 8650Sstevel@tonic-gate return NULL; 8660Sstevel@tonic-gate } 8670Sstevel@tonic-gate 8680Sstevel@tonic-gate return ret; 8690Sstevel@tonic-gate } 8700Sstevel@tonic-gate 8710Sstevel@tonic-gate void ENGINE_load_pk11(void) 8720Sstevel@tonic-gate { 8730Sstevel@tonic-gate ENGINE *e_pk11 = NULL; 8740Sstevel@tonic-gate 8750Sstevel@tonic-gate /* Do not use dynamic PKCS#11 library on Solaris due to 8760Sstevel@tonic-gate * security reasons. We will link it in statically 8770Sstevel@tonic-gate */ 8780Sstevel@tonic-gate /* Attempt to load PKCS#11 library 8790Sstevel@tonic-gate */ 8800Sstevel@tonic-gate if (!pk11_dso) 8810Sstevel@tonic-gate pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0); 8820Sstevel@tonic-gate 8830Sstevel@tonic-gate if (pk11_dso == NULL) 8840Sstevel@tonic-gate { 8850Sstevel@tonic-gate PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE); 8860Sstevel@tonic-gate return; 8870Sstevel@tonic-gate } 8880Sstevel@tonic-gate 8890Sstevel@tonic-gate e_pk11 = engine_pk11(); 8900Sstevel@tonic-gate if (!e_pk11) 8910Sstevel@tonic-gate { 8920Sstevel@tonic-gate DSO_free(pk11_dso); 8930Sstevel@tonic-gate pk11_dso = NULL; 8940Sstevel@tonic-gate return; 8950Sstevel@tonic-gate } 8960Sstevel@tonic-gate 8970Sstevel@tonic-gate /* At this point, the pk11 shared library is either dynamically 8980Sstevel@tonic-gate * loaded or statically linked in. So, initialize the pk11 8990Sstevel@tonic-gate * library before calling ENGINE_set_default since the latter 9000Sstevel@tonic-gate * needs cipher and digest algorithm information 9010Sstevel@tonic-gate */ 9020Sstevel@tonic-gate if (!pk11_library_init(e_pk11)) 9030Sstevel@tonic-gate { 9040Sstevel@tonic-gate DSO_free(pk11_dso); 9050Sstevel@tonic-gate pk11_dso = NULL; 9060Sstevel@tonic-gate ENGINE_free(e_pk11); 9070Sstevel@tonic-gate return; 9080Sstevel@tonic-gate } 9090Sstevel@tonic-gate 9100Sstevel@tonic-gate ENGINE_add(e_pk11); 9110Sstevel@tonic-gate 9120Sstevel@tonic-gate ENGINE_free(e_pk11); 9130Sstevel@tonic-gate ERR_clear_error(); 9140Sstevel@tonic-gate } 915*7211Sjp161948 #endif /* ENGINE_DYNAMIC_SUPPORT */ 9160Sstevel@tonic-gate 9170Sstevel@tonic-gate /* These are the static string constants for the DSO file name and 9180Sstevel@tonic-gate * the function symbol names to bind to. 9190Sstevel@tonic-gate */ 9200Sstevel@tonic-gate static const char *PK11_LIBNAME = NULL; 9210Sstevel@tonic-gate 9220Sstevel@tonic-gate static const char *get_PK11_LIBNAME(void) 9230Sstevel@tonic-gate { 9240Sstevel@tonic-gate if (PK11_LIBNAME) 9250Sstevel@tonic-gate return PK11_LIBNAME; 9260Sstevel@tonic-gate 9270Sstevel@tonic-gate return def_PK11_LIBNAME; 9280Sstevel@tonic-gate } 9290Sstevel@tonic-gate 9300Sstevel@tonic-gate static void free_PK11_LIBNAME(void) 9310Sstevel@tonic-gate { 9320Sstevel@tonic-gate if (PK11_LIBNAME) 9330Sstevel@tonic-gate OPENSSL_free((void*)PK11_LIBNAME); 9340Sstevel@tonic-gate 9350Sstevel@tonic-gate PK11_LIBNAME = NULL; 9360Sstevel@tonic-gate } 9370Sstevel@tonic-gate 9380Sstevel@tonic-gate static long set_PK11_LIBNAME(const char *name) 9390Sstevel@tonic-gate { 9400Sstevel@tonic-gate free_PK11_LIBNAME(); 9410Sstevel@tonic-gate 9420Sstevel@tonic-gate return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0); 9430Sstevel@tonic-gate } 9440Sstevel@tonic-gate 9450Sstevel@tonic-gate /* Initialization function for the pk11 engine */ 9460Sstevel@tonic-gate static int pk11_init(ENGINE *e) 9470Sstevel@tonic-gate { 9480Sstevel@tonic-gate return pk11_library_init(e); 9490Sstevel@tonic-gate } 9500Sstevel@tonic-gate 9510Sstevel@tonic-gate /* Initialization function. Sets up various pk11 library components. 9520Sstevel@tonic-gate * It selects a slot based on predefined critiera. In the process, it also 9530Sstevel@tonic-gate * count how many ciphers and digests to support. Since the cipher and 9540Sstevel@tonic-gate * digest information is needed when setting default engine, this function 9550Sstevel@tonic-gate * needs to be called before calling ENGINE_set_default. 9560Sstevel@tonic-gate */ 9570Sstevel@tonic-gate static int pk11_library_init(ENGINE *e) 9580Sstevel@tonic-gate { 9590Sstevel@tonic-gate CK_C_GetFunctionList p; 9600Sstevel@tonic-gate CK_RV rv = CKR_OK; 9610Sstevel@tonic-gate CK_INFO info; 9620Sstevel@tonic-gate CK_ULONG ul_state_len; 963*7211Sjp161948 int any_slot_found; 964*7211Sjp161948 965*7211Sjp161948 /* 966*7211Sjp161948 * pk11_library_initialized is set to 0 in pk11_finish() which is called 967*7211Sjp161948 * from ENGINE_finish(). However, if there is still at least one 968*7211Sjp161948 * existing functional reference to the engine (see engine(3) for more 969*7211Sjp161948 * information), pk11_finish() is skipped. For example, this can happen 970*7211Sjp161948 * if an application forgets to clear one cipher context. In case of a 971*7211Sjp161948 * fork() when the application is finishing the engine so that it can be 972*7211Sjp161948 * reinitialized in the child, forgotten functional reference causes 973*7211Sjp161948 * pk11_library_initialized to stay 1. In that case we need the PID 974*7211Sjp161948 * check so that we properly initialize the engine again. 975*7211Sjp161948 */ 9760Sstevel@tonic-gate if (pk11_library_initialized) 977*7211Sjp161948 { 978*7211Sjp161948 if (pk11_pid == getpid()) 979*7211Sjp161948 return 1; 980*7211Sjp161948 else 981*7211Sjp161948 global_session = CK_INVALID_HANDLE; 982*7211Sjp161948 } 9830Sstevel@tonic-gate 9840Sstevel@tonic-gate if (pk11_dso == NULL) 9850Sstevel@tonic-gate { 9860Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); 9870Sstevel@tonic-gate goto err; 9880Sstevel@tonic-gate } 9890Sstevel@tonic-gate 990*7211Sjp161948 #ifdef SOLARIS_AES_CTR 991*7211Sjp161948 /* 992*7211Sjp161948 * We must do this before we start working with slots since we need all 993*7211Sjp161948 * NIDs there. 994*7211Sjp161948 */ 995*7211Sjp161948 if (pk11_add_aes_ctr_NIDs() == 0) 996*7211Sjp161948 goto err; 997*7211Sjp161948 #endif /* SOLARIS_AES_CTR */ 998*7211Sjp161948 999*7211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 1000*7211Sjp161948 if (check_hw_mechanisms() == 0) 1001*7211Sjp161948 goto err; 1002*7211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 1003*7211Sjp161948 10040Sstevel@tonic-gate /* get the C_GetFunctionList function from the loaded library 10050Sstevel@tonic-gate */ 10060Sstevel@tonic-gate p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso, 10070Sstevel@tonic-gate PK11_GET_FUNCTION_LIST); 10080Sstevel@tonic-gate if ( !p ) 10090Sstevel@tonic-gate { 10100Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); 10110Sstevel@tonic-gate goto err; 10120Sstevel@tonic-gate } 10130Sstevel@tonic-gate 10140Sstevel@tonic-gate /* get the full function list from the loaded library 10150Sstevel@tonic-gate */ 10160Sstevel@tonic-gate rv = p(&pFuncList); 10170Sstevel@tonic-gate if (rv != CKR_OK) 10180Sstevel@tonic-gate { 1019*7211Sjp161948 PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv); 10200Sstevel@tonic-gate goto err; 10210Sstevel@tonic-gate } 10220Sstevel@tonic-gate 10230Sstevel@tonic-gate rv = pFuncList->C_Initialize(NULL_PTR); 10240Sstevel@tonic-gate if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) 10250Sstevel@tonic-gate { 1026*7211Sjp161948 PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv); 10270Sstevel@tonic-gate goto err; 10280Sstevel@tonic-gate } 10290Sstevel@tonic-gate 10300Sstevel@tonic-gate rv = pFuncList->C_GetInfo(&info); 10310Sstevel@tonic-gate if (rv != CKR_OK) 10320Sstevel@tonic-gate { 1033*7211Sjp161948 PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv); 10340Sstevel@tonic-gate goto err; 10350Sstevel@tonic-gate } 10360Sstevel@tonic-gate 1037*7211Sjp161948 if (pk11_choose_slots(&any_slot_found) == 0) 10380Sstevel@tonic-gate goto err; 10390Sstevel@tonic-gate 1040*7211Sjp161948 /* 1041*7211Sjp161948 * The library we use, set in def_PK11_LIBNAME, may not offer any 1042*7211Sjp161948 * slot(s). In that case, we must not proceed but we must not return an 1043*7211Sjp161948 * error. The reason is that applications that try to set up the PKCS#11 1044*7211Sjp161948 * engine don't exit on error during the engine initialization just 1045*7211Sjp161948 * because no slot was present. 1046*7211Sjp161948 */ 1047*7211Sjp161948 if (any_slot_found == 0) 1048*7211Sjp161948 return 1; 1049*7211Sjp161948 10500Sstevel@tonic-gate if (global_session == CK_INVALID_HANDLE) 10510Sstevel@tonic-gate { 10520Sstevel@tonic-gate /* Open the global_session for the new process */ 10530Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 10540Sstevel@tonic-gate NULL_PTR, NULL_PTR, &global_session); 10550Sstevel@tonic-gate if (rv != CKR_OK) 10560Sstevel@tonic-gate { 1057*7211Sjp161948 PK11err_add_data(PK11_F_LIBRARY_INIT, 1058*7211Sjp161948 PK11_R_OPENSESSION, rv); 10590Sstevel@tonic-gate goto err; 10600Sstevel@tonic-gate } 10610Sstevel@tonic-gate } 10620Sstevel@tonic-gate 10630Sstevel@tonic-gate /* Disable digest if C_GetOperationState is not supported since 10640Sstevel@tonic-gate * this function is required by OpenSSL digest copy function */ 10650Sstevel@tonic-gate if (pFuncList->C_GetOperationState(global_session, NULL, &ul_state_len) 1066*7211Sjp161948 == CKR_FUNCTION_NOT_SUPPORTED) { 1067*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 1068*7211Sjp161948 fprintf(stderr, "%s: C_GetOperationState() not supported, " 1069*7211Sjp161948 "setting digest_count to 0\n", PK11_DBG); 1070*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 10710Sstevel@tonic-gate digest_count = 0; 1072*7211Sjp161948 } 10730Sstevel@tonic-gate 10740Sstevel@tonic-gate pk11_library_initialized = 1; 1075*7211Sjp161948 pk11_pid = getpid(); 10760Sstevel@tonic-gate return 1; 10770Sstevel@tonic-gate 10780Sstevel@tonic-gate err: 10790Sstevel@tonic-gate return 0; 10800Sstevel@tonic-gate } 10810Sstevel@tonic-gate 10820Sstevel@tonic-gate /* Destructor (complements the "ENGINE_pk11()" constructor) 10830Sstevel@tonic-gate */ 10840Sstevel@tonic-gate static int pk11_destroy(ENGINE *e) 10850Sstevel@tonic-gate { 10860Sstevel@tonic-gate free_PK11_LIBNAME(); 10870Sstevel@tonic-gate ERR_unload_pk11_strings(); 10880Sstevel@tonic-gate return 1; 10890Sstevel@tonic-gate } 10900Sstevel@tonic-gate 10910Sstevel@tonic-gate /* Termination function to clean up the session, the token, and 10920Sstevel@tonic-gate * the pk11 library. 10930Sstevel@tonic-gate */ 10940Sstevel@tonic-gate static int pk11_finish(ENGINE *e) 10950Sstevel@tonic-gate { 10960Sstevel@tonic-gate if (pk11_dso == NULL) 10970Sstevel@tonic-gate { 10980Sstevel@tonic-gate PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED); 10990Sstevel@tonic-gate goto err; 11000Sstevel@tonic-gate } 11010Sstevel@tonic-gate 11026847Svk199839 OPENSSL_assert(pFuncList != NULL); 11030Sstevel@tonic-gate 11040Sstevel@tonic-gate if (pk11_free_all_sessions() == 0) 11050Sstevel@tonic-gate goto err; 11060Sstevel@tonic-gate 11070Sstevel@tonic-gate pFuncList->C_CloseSession(global_session); 1108*7211Sjp161948 global_session = CK_INVALID_HANDLE; 1109*7211Sjp161948 1110*7211Sjp161948 /* 1111*7211Sjp161948 * Since we are part of a library (libcrypto.so), calling this function 1112*7211Sjp161948 * may have side-effects. 1113*7211Sjp161948 */ 1114*7211Sjp161948 #if 0 11150Sstevel@tonic-gate pFuncList->C_Finalize(NULL); 1116*7211Sjp161948 #endif 11170Sstevel@tonic-gate 11180Sstevel@tonic-gate if (!DSO_free(pk11_dso)) 11190Sstevel@tonic-gate { 11200Sstevel@tonic-gate PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE); 11210Sstevel@tonic-gate goto err; 11220Sstevel@tonic-gate } 11230Sstevel@tonic-gate pk11_dso = NULL; 11240Sstevel@tonic-gate pFuncList = NULL; 11250Sstevel@tonic-gate pk11_library_initialized = 0; 1126*7211Sjp161948 pk11_pid = 0; 11270Sstevel@tonic-gate 11280Sstevel@tonic-gate return 1; 11290Sstevel@tonic-gate 11300Sstevel@tonic-gate err: 11310Sstevel@tonic-gate return 0; 11320Sstevel@tonic-gate } 11330Sstevel@tonic-gate 11340Sstevel@tonic-gate /* Standard engine interface function to set the dynamic library path */ 11350Sstevel@tonic-gate static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) 11360Sstevel@tonic-gate { 11370Sstevel@tonic-gate int initialized = ((pk11_dso == NULL) ? 0 : 1); 11380Sstevel@tonic-gate 11390Sstevel@tonic-gate switch(cmd) 11400Sstevel@tonic-gate { 11410Sstevel@tonic-gate case PK11_CMD_SO_PATH: 11420Sstevel@tonic-gate if (p == NULL) 11430Sstevel@tonic-gate { 11440Sstevel@tonic-gate PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); 11450Sstevel@tonic-gate return 0; 11460Sstevel@tonic-gate } 11470Sstevel@tonic-gate 11480Sstevel@tonic-gate if (initialized) 11490Sstevel@tonic-gate { 11500Sstevel@tonic-gate PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED); 11510Sstevel@tonic-gate return 0; 11520Sstevel@tonic-gate } 11530Sstevel@tonic-gate 11540Sstevel@tonic-gate return set_PK11_LIBNAME((const char*)p); 11550Sstevel@tonic-gate default: 11560Sstevel@tonic-gate break; 11570Sstevel@tonic-gate } 11580Sstevel@tonic-gate 11590Sstevel@tonic-gate PK11err(PK11_F_CTRL,PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED); 11600Sstevel@tonic-gate 11610Sstevel@tonic-gate return 0; 11620Sstevel@tonic-gate } 11630Sstevel@tonic-gate 11640Sstevel@tonic-gate 11650Sstevel@tonic-gate /* Required function by the engine random interface. It does nothing here 11660Sstevel@tonic-gate */ 11670Sstevel@tonic-gate static void pk11_rand_cleanup(void) 11680Sstevel@tonic-gate { 11690Sstevel@tonic-gate return; 11700Sstevel@tonic-gate } 11710Sstevel@tonic-gate 11720Sstevel@tonic-gate static void pk11_rand_add(const void *buf, int num, double add) 11730Sstevel@tonic-gate { 11740Sstevel@tonic-gate PK11_SESSION *sp; 11750Sstevel@tonic-gate 1176*7211Sjp161948 if ((sp = pk11_get_session(OP_RAND)) == NULL) 11770Sstevel@tonic-gate return; 11780Sstevel@tonic-gate 11790Sstevel@tonic-gate /* Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since 11800Sstevel@tonic-gate * the calling functions do not care anyway 11810Sstevel@tonic-gate */ 11820Sstevel@tonic-gate pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num); 1183*7211Sjp161948 pk11_return_session(sp, OP_RAND); 11840Sstevel@tonic-gate 11850Sstevel@tonic-gate return; 11860Sstevel@tonic-gate } 11870Sstevel@tonic-gate 11880Sstevel@tonic-gate static void pk11_rand_seed(const void *buf, int num) 11890Sstevel@tonic-gate { 11900Sstevel@tonic-gate pk11_rand_add(buf, num, 0); 11910Sstevel@tonic-gate } 11920Sstevel@tonic-gate 11930Sstevel@tonic-gate static int pk11_rand_bytes(unsigned char *buf, int num) 11940Sstevel@tonic-gate { 11950Sstevel@tonic-gate CK_RV rv; 11960Sstevel@tonic-gate PK11_SESSION *sp; 11970Sstevel@tonic-gate 1198*7211Sjp161948 if ((sp = pk11_get_session(OP_RAND)) == NULL) 11990Sstevel@tonic-gate return 0; 12000Sstevel@tonic-gate 12010Sstevel@tonic-gate rv = pFuncList->C_GenerateRandom(sp->session, buf, num); 12020Sstevel@tonic-gate if (rv != CKR_OK) 12030Sstevel@tonic-gate { 1204*7211Sjp161948 PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv); 1205*7211Sjp161948 pk11_return_session(sp, OP_RAND); 12060Sstevel@tonic-gate return 0; 12070Sstevel@tonic-gate } 12080Sstevel@tonic-gate 1209*7211Sjp161948 pk11_return_session(sp, OP_RAND); 12100Sstevel@tonic-gate return 1; 12110Sstevel@tonic-gate } 12120Sstevel@tonic-gate 12130Sstevel@tonic-gate /* Required function by the engine random interface. It does nothing here 12140Sstevel@tonic-gate */ 12150Sstevel@tonic-gate static int pk11_rand_status(void) 12160Sstevel@tonic-gate { 12170Sstevel@tonic-gate return 1; 12180Sstevel@tonic-gate } 12190Sstevel@tonic-gate 12206847Svk199839 /* 12216847Svk199839 * Free all BIGNUM structures from PK11_SESSION. 12226847Svk199839 */ 12236847Svk199839 static void pk11_free_nums(PK11_SESSION *sp) 12246847Svk199839 { 12256847Svk199839 #ifndef OPENSSL_NO_RSA 12266847Svk199839 if (sp->rsa_n_num != NULL) 12276847Svk199839 BN_free(sp->rsa_n_num); 12286847Svk199839 if (sp->rsa_e_num != NULL) 12296847Svk199839 BN_free(sp->rsa_e_num); 12306847Svk199839 if (sp->rsa_d_num != NULL) 12316847Svk199839 BN_free(sp->rsa_d_num); 12326847Svk199839 #endif 12336847Svk199839 #ifndef OPENSSL_NO_DSA 12346847Svk199839 if (sp->dsa_pub_num != NULL) 12356847Svk199839 BN_free(sp->dsa_pub_num); 12366847Svk199839 if (sp->dsa_priv_num != NULL) 12376847Svk199839 BN_free(sp->dsa_priv_num); 12386847Svk199839 #endif 12396847Svk199839 #ifndef OPENSSL_NO_DH 12406847Svk199839 if (sp->dh_priv_num != NULL) 12416847Svk199839 BN_free(sp->dh_priv_num); 12426847Svk199839 #endif 12436847Svk199839 } 12440Sstevel@tonic-gate 12456847Svk199839 /* 12466847Svk199839 * Get new PK11_SESSION structure ready for use. Every process must have 12476847Svk199839 * its own freelist of PK11_SESSION structures so handle fork() here 12486847Svk199839 * by destroying the old and creating new freelist. 12496847Svk199839 * The returned PK11_SESSION structure is disconnected from the freelist. 12506847Svk199839 */ 1251*7211Sjp161948 PK11_SESSION *pk11_get_session(PK11_OPTYPE optype) 12520Sstevel@tonic-gate { 1253*7211Sjp161948 PK11_SESSION *sp, *sp1, *freelist; 12540Sstevel@tonic-gate CK_RV rv; 12550Sstevel@tonic-gate 12560Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 1257*7211Sjp161948 switch (optype) 1258*7211Sjp161948 { 1259*7211Sjp161948 case OP_PUBKEY: 1260*7211Sjp161948 freelist = pubkey_free_session; 1261*7211Sjp161948 break; 1262*7211Sjp161948 case OP_RAND: 1263*7211Sjp161948 freelist = rand_free_session; 1264*7211Sjp161948 break; 1265*7211Sjp161948 case OP_DIGEST: 1266*7211Sjp161948 case OP_CIPHER: 1267*7211Sjp161948 freelist = free_session; 1268*7211Sjp161948 break; 1269*7211Sjp161948 default: 1270*7211Sjp161948 PK11err(PK11_F_GET_SESSION, 1271*7211Sjp161948 PK11_R_INVALID_OPERATION_TYPE); 1272*7211Sjp161948 goto err; 1273*7211Sjp161948 } 1274*7211Sjp161948 sp = freelist; 1275*7211Sjp161948 12766847Svk199839 /* 12776847Svk199839 * If the free list is empty, allocate new unitialized (filled 12786847Svk199839 * with zeroes) PK11_SESSION structure otherwise return first 12796847Svk199839 * structure from the freelist. 12806847Svk199839 */ 1281*7211Sjp161948 if (sp == NULL) 12820Sstevel@tonic-gate { 12830Sstevel@tonic-gate if ((sp = OPENSSL_malloc(sizeof(PK11_SESSION))) == NULL) 12840Sstevel@tonic-gate { 12850Sstevel@tonic-gate PK11err(PK11_F_GET_SESSION, 12860Sstevel@tonic-gate PK11_R_MALLOC_FAILURE); 12870Sstevel@tonic-gate goto err; 12880Sstevel@tonic-gate } 12890Sstevel@tonic-gate memset(sp, 0, sizeof(PK11_SESSION)); 12900Sstevel@tonic-gate } 12910Sstevel@tonic-gate else 12920Sstevel@tonic-gate { 1293*7211Sjp161948 freelist = sp->next; 12940Sstevel@tonic-gate } 12950Sstevel@tonic-gate 12960Sstevel@tonic-gate if (sp->pid != 0 && sp->pid != getpid()) 12970Sstevel@tonic-gate { 12986847Svk199839 /* 12996847Svk199839 * We are a new process and thus need to free any inherited 13000Sstevel@tonic-gate * PK11_SESSION objects. 13010Sstevel@tonic-gate */ 1302*7211Sjp161948 while ((sp1 = freelist) != NULL) 13030Sstevel@tonic-gate { 1304*7211Sjp161948 freelist = sp1->next; 13056847Svk199839 /* 1306*7211Sjp161948 * NOTE: we do not want to call pk11_free_all_sessions() 1307*7211Sjp161948 * here because it would close underlying PKCS#11 1308*7211Sjp161948 * sessions and destroy all objects. 13096847Svk199839 */ 13106847Svk199839 pk11_free_nums(sp1); 13110Sstevel@tonic-gate OPENSSL_free(sp1); 13120Sstevel@tonic-gate } 13130Sstevel@tonic-gate 13140Sstevel@tonic-gate /* Initialize the process */ 13150Sstevel@tonic-gate rv = pFuncList->C_Initialize(NULL_PTR); 13160Sstevel@tonic-gate if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) 13170Sstevel@tonic-gate { 1318*7211Sjp161948 PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE, 1319*7211Sjp161948 rv); 13200Sstevel@tonic-gate OPENSSL_free(sp); 13210Sstevel@tonic-gate sp = NULL; 13220Sstevel@tonic-gate goto err; 13230Sstevel@tonic-gate } 13240Sstevel@tonic-gate 13256847Svk199839 /* 1326*7211Sjp161948 * Choose slot here since the slot table is different on this 1327*7211Sjp161948 * process. If we are here then we must have found at least one 1328*7211Sjp161948 * usable slot before so we don't need to check any_slot_found. 1329*7211Sjp161948 * See pk11_library_init()'s usage of this function for more 1330*7211Sjp161948 * information. 13310Sstevel@tonic-gate */ 1332*7211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 1333*7211Sjp161948 if (check_hw_mechanisms() == 0) 1334*7211Sjp161948 goto err; 1335*7211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 1336*7211Sjp161948 if (pk11_choose_slots(NULL) == 0) 13370Sstevel@tonic-gate goto err; 13380Sstevel@tonic-gate 13390Sstevel@tonic-gate /* Open the global_session for the new process */ 13400Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 13410Sstevel@tonic-gate NULL_PTR, NULL_PTR, &global_session); 13420Sstevel@tonic-gate if (rv != CKR_OK) 13430Sstevel@tonic-gate { 1344*7211Sjp161948 PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION, 1345*7211Sjp161948 rv); 13460Sstevel@tonic-gate OPENSSL_free(sp); 13470Sstevel@tonic-gate sp = NULL; 13480Sstevel@tonic-gate goto err; 13490Sstevel@tonic-gate } 13500Sstevel@tonic-gate 13510Sstevel@tonic-gate /* It is an inherited session and needs re-initialization. 13520Sstevel@tonic-gate */ 1353*7211Sjp161948 if (pk11_setup_session(sp, optype) == 0) 13540Sstevel@tonic-gate { 13550Sstevel@tonic-gate OPENSSL_free(sp); 13560Sstevel@tonic-gate sp = NULL; 13570Sstevel@tonic-gate } 13580Sstevel@tonic-gate } 13590Sstevel@tonic-gate else if (sp->pid == 0) 13600Sstevel@tonic-gate { 1361*7211Sjp161948 /* It is a new session and needs initialization. */ 1362*7211Sjp161948 if (pk11_setup_session(sp, optype) == 0) 13630Sstevel@tonic-gate { 13640Sstevel@tonic-gate OPENSSL_free(sp); 13650Sstevel@tonic-gate sp = NULL; 13660Sstevel@tonic-gate } 13670Sstevel@tonic-gate } 13680Sstevel@tonic-gate 1369*7211Sjp161948 switch (optype) 1370*7211Sjp161948 { 1371*7211Sjp161948 case OP_PUBKEY: 1372*7211Sjp161948 pubkey_free_session = freelist; 1373*7211Sjp161948 break; 1374*7211Sjp161948 case OP_RAND: 1375*7211Sjp161948 rand_free_session = freelist; 1376*7211Sjp161948 break; 1377*7211Sjp161948 case OP_DIGEST: 1378*7211Sjp161948 case OP_CIPHER: 1379*7211Sjp161948 free_session = freelist; 1380*7211Sjp161948 break; 1381*7211Sjp161948 } 1382*7211Sjp161948 13830Sstevel@tonic-gate err: 13846847Svk199839 if (sp != NULL) 13850Sstevel@tonic-gate sp->next = NULL; 13860Sstevel@tonic-gate 13870Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 13880Sstevel@tonic-gate 13890Sstevel@tonic-gate return sp; 13900Sstevel@tonic-gate } 13910Sstevel@tonic-gate 13920Sstevel@tonic-gate 1393*7211Sjp161948 void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype) 13940Sstevel@tonic-gate { 13950Sstevel@tonic-gate if (sp == NULL || sp->pid != getpid()) 13960Sstevel@tonic-gate return; 13970Sstevel@tonic-gate 13980Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 13990Sstevel@tonic-gate 1400*7211Sjp161948 switch (optype) 1401*7211Sjp161948 { 1402*7211Sjp161948 case OP_PUBKEY: 1403*7211Sjp161948 sp->next = pubkey_free_session; 1404*7211Sjp161948 pubkey_free_session = sp; 1405*7211Sjp161948 break; 1406*7211Sjp161948 case OP_RAND: 1407*7211Sjp161948 sp->next = rand_free_session; 1408*7211Sjp161948 rand_free_session = sp; 1409*7211Sjp161948 break; 1410*7211Sjp161948 case OP_DIGEST: 1411*7211Sjp161948 case OP_CIPHER: 1412*7211Sjp161948 sp->next = free_session; 1413*7211Sjp161948 free_session = sp; 1414*7211Sjp161948 break; 1415*7211Sjp161948 } 14160Sstevel@tonic-gate 14170Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 14180Sstevel@tonic-gate } 14190Sstevel@tonic-gate 14200Sstevel@tonic-gate 14210Sstevel@tonic-gate /* Destroy all objects. This function is called when the engine is finished 14220Sstevel@tonic-gate */ 14230Sstevel@tonic-gate static int pk11_free_all_sessions() 14240Sstevel@tonic-gate { 1425*7211Sjp161948 int ret = 1; 14260Sstevel@tonic-gate 14276847Svk199839 #ifndef OPENSSL_NO_RSA 14286847Svk199839 (void) pk11_destroy_rsa_key_objects(NULL); 1429*7211Sjp161948 #endif /* OPENSSL_NO_RSA */ 14306847Svk199839 #ifndef OPENSSL_NO_DSA 14316847Svk199839 (void) pk11_destroy_dsa_key_objects(NULL); 1432*7211Sjp161948 #endif /* OPENSSL_NO_DSA */ 14336847Svk199839 #ifndef OPENSSL_NO_DH 14346847Svk199839 (void) pk11_destroy_dh_key_objects(NULL); 1435*7211Sjp161948 #endif /* OPENSSL_NO_DH */ 14366847Svk199839 (void) pk11_destroy_cipher_key_objects(NULL); 1437*7211Sjp161948 1438*7211Sjp161948 /* 1439*7211Sjp161948 * We try to release as much as we can but any error means that we will 1440*7211Sjp161948 * return 0 on exit. 1441*7211Sjp161948 */ 1442*7211Sjp161948 if (pk11_free_session_list(&free_session) == 0) 1443*7211Sjp161948 ret = 0; 1444*7211Sjp161948 if (pk11_free_session_list(&pubkey_free_session) == 0) 1445*7211Sjp161948 ret = 0; 1446*7211Sjp161948 if (pk11_free_session_list(&rand_free_session) == 0) 1447*7211Sjp161948 ret = 0; 1448*7211Sjp161948 1449*7211Sjp161948 return ret; 1450*7211Sjp161948 } 14510Sstevel@tonic-gate 1452*7211Sjp161948 /* 1453*7211Sjp161948 * Destroy session structures from the specified linked list. Free as many 1454*7211Sjp161948 * sessions as possible but any failure in C_CloseSession() means that we return 1455*7211Sjp161948 * an error on return. 1456*7211Sjp161948 */ 1457*7211Sjp161948 static int pk11_free_session_list(PK11_SESSION **sessions) 1458*7211Sjp161948 { 1459*7211Sjp161948 CK_RV rv; 1460*7211Sjp161948 PK11_SESSION *sp = NULL; 1461*7211Sjp161948 pid_t mypid = getpid(); 1462*7211Sjp161948 int ret = 1; 1463*7211Sjp161948 14640Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 1465*7211Sjp161948 while ((sp = *sessions) != NULL) 14660Sstevel@tonic-gate { 14670Sstevel@tonic-gate if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid) 14680Sstevel@tonic-gate { 14690Sstevel@tonic-gate rv = pFuncList->C_CloseSession(sp->session); 14700Sstevel@tonic-gate if (rv != CKR_OK) 14710Sstevel@tonic-gate { 1472*7211Sjp161948 PK11err_add_data(PK11_F_FREE_ALL_SESSIONS, 1473*7211Sjp161948 PK11_R_CLOSESESSION, rv); 1474*7211Sjp161948 ret = 0; 14750Sstevel@tonic-gate } 14760Sstevel@tonic-gate } 14770Sstevel@tonic-gate if (sp->session_cipher != CK_INVALID_HANDLE && sp->pid == mypid) 14780Sstevel@tonic-gate { 14790Sstevel@tonic-gate rv = pFuncList->C_CloseSession(sp->session_cipher); 14800Sstevel@tonic-gate if (rv != CKR_OK) 14810Sstevel@tonic-gate { 1482*7211Sjp161948 PK11err_add_data(PK11_F_FREE_ALL_SESSIONS, 1483*7211Sjp161948 PK11_R_CLOSESESSION, rv); 1484*7211Sjp161948 ret = 0; 14850Sstevel@tonic-gate } 14860Sstevel@tonic-gate } 1487*7211Sjp161948 *sessions = sp->next; 14886847Svk199839 pk11_free_nums(sp); 14890Sstevel@tonic-gate OPENSSL_free(sp); 14900Sstevel@tonic-gate } 1491*7211Sjp161948 14920Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 14930Sstevel@tonic-gate return ret; 14940Sstevel@tonic-gate } 14950Sstevel@tonic-gate 14960Sstevel@tonic-gate 1497*7211Sjp161948 static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype) 14980Sstevel@tonic-gate { 14990Sstevel@tonic-gate CK_RV rv; 1500*7211Sjp161948 CK_SLOT_ID myslot; 1501*7211Sjp161948 1502*7211Sjp161948 switch (optype) 1503*7211Sjp161948 { 1504*7211Sjp161948 case OP_PUBKEY: 1505*7211Sjp161948 myslot = pubkey_SLOTID; 1506*7211Sjp161948 break; 1507*7211Sjp161948 case OP_RAND: 1508*7211Sjp161948 myslot = rand_SLOTID; 1509*7211Sjp161948 break; 1510*7211Sjp161948 case OP_DIGEST: 1511*7211Sjp161948 case OP_CIPHER: 1512*7211Sjp161948 myslot = SLOTID; 1513*7211Sjp161948 break; 1514*7211Sjp161948 default: 1515*7211Sjp161948 PK11err(PK11_F_SETUP_SESSION, 1516*7211Sjp161948 PK11_R_INVALID_OPERATION_TYPE); 1517*7211Sjp161948 return 0; 1518*7211Sjp161948 } 1519*7211Sjp161948 15200Sstevel@tonic-gate sp->session = CK_INVALID_HANDLE; 1521*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 1522*7211Sjp161948 fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype); 1523*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 1524*7211Sjp161948 rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, 15250Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session); 15260Sstevel@tonic-gate if (rv == CKR_CRYPTOKI_NOT_INITIALIZED) 15270Sstevel@tonic-gate { 15280Sstevel@tonic-gate /* 15290Sstevel@tonic-gate * We are probably a child process so force the 15300Sstevel@tonic-gate * reinitialize of the session 15310Sstevel@tonic-gate */ 15320Sstevel@tonic-gate pk11_library_initialized = 0; 15330Sstevel@tonic-gate (void) pk11_library_init(NULL); 1534*7211Sjp161948 rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, 15350Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session); 15360Sstevel@tonic-gate } 15370Sstevel@tonic-gate if (rv != CKR_OK) 15380Sstevel@tonic-gate { 1539*7211Sjp161948 PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv); 15400Sstevel@tonic-gate return 0; 15410Sstevel@tonic-gate } 15420Sstevel@tonic-gate 15430Sstevel@tonic-gate sp->session_cipher = CK_INVALID_HANDLE; 1544*7211Sjp161948 rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, 15450Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session_cipher); 15460Sstevel@tonic-gate if (rv != CKR_OK) 15470Sstevel@tonic-gate { 15480Sstevel@tonic-gate (void) pFuncList->C_CloseSession(sp->session); 15490Sstevel@tonic-gate sp->session = CK_INVALID_HANDLE; 15500Sstevel@tonic-gate 1551*7211Sjp161948 PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv); 15520Sstevel@tonic-gate return 0; 15530Sstevel@tonic-gate } 15540Sstevel@tonic-gate 15550Sstevel@tonic-gate sp->pid = getpid(); 15560Sstevel@tonic-gate sp->rsa_pub_key = CK_INVALID_HANDLE; 15570Sstevel@tonic-gate sp->rsa_priv_key = CK_INVALID_HANDLE; 15580Sstevel@tonic-gate sp->dsa_pub_key = CK_INVALID_HANDLE; 15590Sstevel@tonic-gate sp->dsa_priv_key = CK_INVALID_HANDLE; 15600Sstevel@tonic-gate sp->dh_key = CK_INVALID_HANDLE; 15610Sstevel@tonic-gate sp->cipher_key = CK_INVALID_HANDLE; 15626847Svk199839 #ifndef OPENSSL_NO_RSA 15636847Svk199839 sp->rsa_pub = NULL; 15646847Svk199839 sp->rsa_n_num = NULL; 15656847Svk199839 sp->rsa_e_num = NULL; 15666847Svk199839 sp->rsa_priv = NULL; 15676847Svk199839 sp->rsa_d_num = NULL; 1568*7211Sjp161948 #endif /* OPENSSL_NO_RSA */ 15696847Svk199839 #ifndef OPENSSL_NO_DSA 15706847Svk199839 sp->dsa_pub = NULL; 15716847Svk199839 sp->dsa_pub_num = NULL; 15726847Svk199839 sp->dsa_priv = NULL; 15736847Svk199839 sp->dsa_priv_num = NULL; 1574*7211Sjp161948 #endif /* OPENSSL_NO_DSA */ 15756847Svk199839 #ifndef OPENSSL_NO_DH 15760Sstevel@tonic-gate sp->dh = NULL; 15776847Svk199839 sp->dh_priv_num = NULL; 1578*7211Sjp161948 #endif /* OPENSSL_NO_DH */ 15790Sstevel@tonic-gate sp->encrypt = -1; 15800Sstevel@tonic-gate 15810Sstevel@tonic-gate return 1; 15820Sstevel@tonic-gate } 15830Sstevel@tonic-gate 15846847Svk199839 #ifndef OPENSSL_NO_RSA 15856847Svk199839 /* Destroy RSA public key from single session. */ 15866847Svk199839 int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) 15876847Svk199839 { 15886847Svk199839 int ret = 0; 15896847Svk199839 15906847Svk199839 if (sp->rsa_pub_key != CK_INVALID_HANDLE) 15916847Svk199839 { 15926847Svk199839 TRY_OBJ_DESTROY(sp->session, sp->rsa_pub_key, ret, uselock); 15936847Svk199839 sp->rsa_pub_key = CK_INVALID_HANDLE; 15946847Svk199839 sp->rsa_pub = NULL; 15956847Svk199839 if (sp->rsa_n_num != NULL) 15966847Svk199839 BN_free(sp->rsa_n_num); 15976847Svk199839 sp->rsa_n_num = NULL; 15986847Svk199839 if (sp->rsa_e_num != NULL) 15996847Svk199839 BN_free(sp->rsa_e_num); 16006847Svk199839 sp->rsa_e_num = NULL; 16016847Svk199839 } 16026847Svk199839 16036847Svk199839 return (ret); 16046847Svk199839 } 16056847Svk199839 16066847Svk199839 /* Destroy RSA private key from single session. */ 16076847Svk199839 int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) 16080Sstevel@tonic-gate { 16090Sstevel@tonic-gate int ret = 0; 16106847Svk199839 16116847Svk199839 if (sp->rsa_priv_key != CK_INVALID_HANDLE) 16126847Svk199839 { 16136847Svk199839 TRY_OBJ_DESTROY(sp->session, sp->rsa_priv_key, ret, uselock); 16146847Svk199839 sp->rsa_priv_key = CK_INVALID_HANDLE; 16156847Svk199839 sp->rsa_priv = NULL; 16166847Svk199839 if (sp->rsa_d_num != NULL) 16176847Svk199839 BN_free(sp->rsa_d_num); 16186847Svk199839 sp->rsa_d_num = NULL; 16196847Svk199839 } 16206847Svk199839 16216847Svk199839 return (ret); 16226847Svk199839 } 16236847Svk199839 16246847Svk199839 /* 1625*7211Sjp161948 * Destroy RSA key object wrapper. If session is NULL, try to destroy all 1626*7211Sjp161948 * objects in the free list. 16276847Svk199839 */ 16286847Svk199839 int pk11_destroy_rsa_key_objects(PK11_SESSION *session) 16296847Svk199839 { 16306847Svk199839 int ret = 1; 16310Sstevel@tonic-gate PK11_SESSION *sp = NULL; 16320Sstevel@tonic-gate PK11_SESSION *local_free_session; 16336847Svk199839 CK_BBOOL uselock = TRUE; 16340Sstevel@tonic-gate 16356847Svk199839 if (session != NULL) 16360Sstevel@tonic-gate local_free_session = session; 16370Sstevel@tonic-gate else 16386847Svk199839 { 16396847Svk199839 CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 1640*7211Sjp161948 local_free_session = pubkey_free_session; 16416847Svk199839 uselock = FALSE; 16426847Svk199839 } 16430Sstevel@tonic-gate 16446847Svk199839 /* 16456847Svk199839 * go through the list of sessions and delete key objects 16466847Svk199839 */ 16470Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 16480Sstevel@tonic-gate { 16490Sstevel@tonic-gate local_free_session = sp->next; 16500Sstevel@tonic-gate 16516847Svk199839 /* 16526847Svk199839 * Do not terminate list traversal if one of the 16536847Svk199839 * destroy operations fails. 16546847Svk199839 */ 16556847Svk199839 if (pk11_destroy_rsa_object_pub(sp, uselock) == 0) 16560Sstevel@tonic-gate { 16576847Svk199839 ret = 0; 16586847Svk199839 continue; 16590Sstevel@tonic-gate } 16606847Svk199839 if (pk11_destroy_rsa_object_priv(sp, uselock) == 0) 16616847Svk199839 { 16626847Svk199839 ret = 0; 16636847Svk199839 continue; 16646847Svk199839 } 16656847Svk199839 } 16660Sstevel@tonic-gate 16676847Svk199839 if (session == NULL) 16686847Svk199839 CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 16690Sstevel@tonic-gate 16700Sstevel@tonic-gate return ret; 16710Sstevel@tonic-gate } 1672*7211Sjp161948 #endif /* OPENSSL_NO_RSA */ 16730Sstevel@tonic-gate 16746847Svk199839 #ifndef OPENSSL_NO_DSA 16756847Svk199839 /* Destroy DSA public key from single session. */ 16766847Svk199839 int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) 16770Sstevel@tonic-gate { 16780Sstevel@tonic-gate int ret = 0; 16796847Svk199839 16806847Svk199839 if (sp->dsa_pub_key != CK_INVALID_HANDLE) 16816847Svk199839 { 16826847Svk199839 TRY_OBJ_DESTROY(sp->session, sp->dsa_pub_key, ret, uselock); 16836847Svk199839 sp->dsa_pub_key = CK_INVALID_HANDLE; 16846847Svk199839 sp->dsa_pub = NULL; 16856847Svk199839 if (sp->dsa_pub_num != NULL) 16866847Svk199839 BN_free(sp->dsa_pub_num); 16876847Svk199839 sp->dsa_pub_num = NULL; 16886847Svk199839 } 16896847Svk199839 16906847Svk199839 return (ret); 16916847Svk199839 } 16926847Svk199839 16936847Svk199839 /* Destroy DSA private key from single session. */ 16946847Svk199839 int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) 16956847Svk199839 { 16966847Svk199839 int ret = 0; 16976847Svk199839 16986847Svk199839 if (sp->dsa_priv_key != CK_INVALID_HANDLE) 16996847Svk199839 { 17006847Svk199839 TRY_OBJ_DESTROY(sp->session, sp->dsa_priv_key, ret, uselock); 17016847Svk199839 sp->dsa_priv_key = CK_INVALID_HANDLE; 17026847Svk199839 sp->dsa_priv = NULL; 17036847Svk199839 if (sp->dsa_priv_num != NULL) 17046847Svk199839 BN_free(sp->dsa_priv_num); 17056847Svk199839 sp->dsa_priv_num = NULL; 17066847Svk199839 } 17076847Svk199839 17086847Svk199839 return (ret); 17096847Svk199839 } 17106847Svk199839 17116847Svk199839 /* 1712*7211Sjp161948 * Destroy DSA key object wrapper. If session is NULL, try to destroy all 1713*7211Sjp161948 * objects in the free list. 17146847Svk199839 */ 17156847Svk199839 int pk11_destroy_dsa_key_objects(PK11_SESSION *session) 17166847Svk199839 { 17176847Svk199839 int ret = 1; 17180Sstevel@tonic-gate PK11_SESSION *sp = NULL; 17190Sstevel@tonic-gate PK11_SESSION *local_free_session; 17206847Svk199839 CK_BBOOL uselock = TRUE; 17210Sstevel@tonic-gate 17226847Svk199839 if (session != NULL) 17230Sstevel@tonic-gate local_free_session = session; 17240Sstevel@tonic-gate else 17256847Svk199839 { 17266847Svk199839 CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 1727*7211Sjp161948 local_free_session = pubkey_free_session; 17286847Svk199839 uselock = FALSE; 17296847Svk199839 } 17306847Svk199839 17316847Svk199839 /* 17326847Svk199839 * go through the list of sessions and delete key objects 17336847Svk199839 */ 17340Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 17350Sstevel@tonic-gate { 17360Sstevel@tonic-gate local_free_session = sp->next; 17370Sstevel@tonic-gate 17386847Svk199839 /* 17396847Svk199839 * Do not terminate list traversal if one of the 17406847Svk199839 * destroy operations fails. 17416847Svk199839 */ 17426847Svk199839 if (pk11_destroy_dsa_object_pub(sp, uselock) == 0) 17430Sstevel@tonic-gate { 17446847Svk199839 ret = 0; 17456847Svk199839 continue; 17460Sstevel@tonic-gate } 17476847Svk199839 if (pk11_destroy_dsa_object_priv(sp, uselock) == 0) 17486847Svk199839 { 17496847Svk199839 ret = 0; 17506847Svk199839 continue; 17516847Svk199839 } 17520Sstevel@tonic-gate } 17536847Svk199839 17546847Svk199839 if (session == NULL) 17556847Svk199839 CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 17560Sstevel@tonic-gate 17570Sstevel@tonic-gate return ret; 17580Sstevel@tonic-gate } 1759*7211Sjp161948 #endif /* OPENSSL_NO_DSA */ 17606847Svk199839 17616847Svk199839 #ifndef OPENSSL_NO_DH 17626847Svk199839 /* Destroy DH key from single session. */ 17636847Svk199839 int pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock) 17646847Svk199839 { 17656847Svk199839 int ret = 0; 17666847Svk199839 17676847Svk199839 if (sp->dh_key != CK_INVALID_HANDLE) 17686847Svk199839 { 17696847Svk199839 TRY_OBJ_DESTROY(sp->session, sp->dh_key, ret, uselock); 17706847Svk199839 sp->dh_key = CK_INVALID_HANDLE; 17716847Svk199839 sp->dh = NULL; 17726847Svk199839 if (sp->dh_priv_num != NULL) 17736847Svk199839 BN_free(sp->dh_priv_num); 17746847Svk199839 sp->dh_priv_num = NULL; 17756847Svk199839 } 17766847Svk199839 17776847Svk199839 return (ret); 17786847Svk199839 } 17796847Svk199839 17806847Svk199839 /* 17816847Svk199839 * Destroy DH key object wrapper. 17826847Svk199839 * 17836847Svk199839 * arg0: pointer to PKCS#11 engine session structure 17846847Svk199839 * if session is NULL, try to destroy all objects in the free list 17856847Svk199839 */ 17866847Svk199839 int pk11_destroy_dh_key_objects(PK11_SESSION *session) 17876847Svk199839 { 17886847Svk199839 int ret = 1; 17896847Svk199839 PK11_SESSION *sp = NULL; 17906847Svk199839 PK11_SESSION *local_free_session; 17916847Svk199839 CK_BBOOL uselock = TRUE; 17926847Svk199839 17936847Svk199839 if (session != NULL) 17946847Svk199839 local_free_session = session; 17956847Svk199839 else 17966847Svk199839 { 17976847Svk199839 CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 1798*7211Sjp161948 local_free_session = pubkey_free_session; 17996847Svk199839 uselock = FALSE; 18006847Svk199839 } 18016847Svk199839 18026847Svk199839 while ((sp = local_free_session) != NULL) 18036847Svk199839 { 18046847Svk199839 local_free_session = sp->next; 18056847Svk199839 18066847Svk199839 /* 18076847Svk199839 * Do not terminate list traversal if one of the 18086847Svk199839 * destroy operations fails. 18096847Svk199839 */ 18106847Svk199839 if (pk11_destroy_dh_object(sp, uselock) == 0) 18116847Svk199839 { 18126847Svk199839 ret = 0; 18136847Svk199839 continue; 18146847Svk199839 } 18156847Svk199839 } 18166847Svk199839 err: 18176847Svk199839 if (session == NULL) 18186847Svk199839 CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 18196847Svk199839 18206847Svk199839 return ret; 18216847Svk199839 } 1822*7211Sjp161948 #endif /* OPENSSL_NO_DH */ 18230Sstevel@tonic-gate 18240Sstevel@tonic-gate static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh) 18250Sstevel@tonic-gate { 18260Sstevel@tonic-gate CK_RV rv; 18270Sstevel@tonic-gate rv = pFuncList->C_DestroyObject(session, oh); 18280Sstevel@tonic-gate if (rv != CKR_OK) 18290Sstevel@tonic-gate { 1830*7211Sjp161948 PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT, 1831*7211Sjp161948 rv); 18320Sstevel@tonic-gate return 0; 18330Sstevel@tonic-gate } 18340Sstevel@tonic-gate 18350Sstevel@tonic-gate return 1; 18360Sstevel@tonic-gate } 18370Sstevel@tonic-gate 18380Sstevel@tonic-gate 18390Sstevel@tonic-gate /* Symmetric ciphers and digests support functions 18400Sstevel@tonic-gate */ 18410Sstevel@tonic-gate 18420Sstevel@tonic-gate static int 18430Sstevel@tonic-gate cipher_nid_to_pk11(int nid) 18440Sstevel@tonic-gate { 18450Sstevel@tonic-gate int i; 18460Sstevel@tonic-gate 18470Sstevel@tonic-gate for (i = 0; i < PK11_CIPHER_MAX; i++) 18480Sstevel@tonic-gate if (ciphers[i].nid == nid) 18490Sstevel@tonic-gate return (ciphers[i].id); 18500Sstevel@tonic-gate return (-1); 18510Sstevel@tonic-gate } 18520Sstevel@tonic-gate 18530Sstevel@tonic-gate static int 18540Sstevel@tonic-gate pk11_usable_ciphers(const int **nids) 18550Sstevel@tonic-gate { 18560Sstevel@tonic-gate if (cipher_count > 0) 18570Sstevel@tonic-gate *nids = cipher_nids; 18580Sstevel@tonic-gate else 18590Sstevel@tonic-gate *nids = NULL; 18600Sstevel@tonic-gate return (cipher_count); 18610Sstevel@tonic-gate } 18620Sstevel@tonic-gate 18630Sstevel@tonic-gate static int 18640Sstevel@tonic-gate pk11_usable_digests(const int **nids) 18650Sstevel@tonic-gate { 18660Sstevel@tonic-gate if (digest_count > 0) 18670Sstevel@tonic-gate *nids = digest_nids; 18680Sstevel@tonic-gate else 18690Sstevel@tonic-gate *nids = NULL; 18700Sstevel@tonic-gate return (digest_count); 18710Sstevel@tonic-gate } 18720Sstevel@tonic-gate 1873*7211Sjp161948 /* 1874*7211Sjp161948 * Init context for encryption or decryption using a symmetric key. 1875*7211Sjp161948 */ 1876*7211Sjp161948 static int pk11_init_symmetric(EVP_CIPHER_CTX *ctx, PK11_CIPHER *pcipher, 1877*7211Sjp161948 PK11_SESSION *sp, CK_MECHANISM_PTR pmech) 1878*7211Sjp161948 { 1879*7211Sjp161948 CK_RV rv; 1880*7211Sjp161948 #ifdef SOLARIS_AES_CTR 1881*7211Sjp161948 CK_AES_CTR_PARAMS ctr_params; 1882*7211Sjp161948 #endif /* SOLARIS_AES_CTR */ 1883*7211Sjp161948 1884*7211Sjp161948 /* 1885*7211Sjp161948 * We expect pmech->mechanism to be already set and 1886*7211Sjp161948 * pParameter/ulParameterLen initialized to NULL/0 before 1887*7211Sjp161948 * pk11_init_symetric() is called. 1888*7211Sjp161948 */ 1889*7211Sjp161948 OPENSSL_assert(pmech->mechanism != NULL); 1890*7211Sjp161948 OPENSSL_assert(pmech->pParameter == NULL); 1891*7211Sjp161948 OPENSSL_assert(pmech->ulParameterLen == 0); 1892*7211Sjp161948 1893*7211Sjp161948 #ifdef SOLARIS_AES_CTR 1894*7211Sjp161948 if (ctx->cipher->nid == NID_aes_128_ctr || 1895*7211Sjp161948 ctx->cipher->nid == NID_aes_192_ctr || 1896*7211Sjp161948 ctx->cipher->nid == NID_aes_256_ctr) 1897*7211Sjp161948 { 1898*7211Sjp161948 pmech->pParameter = (void *)(&ctr_params); 1899*7211Sjp161948 pmech->ulParameterLen = sizeof(ctr_params); 1900*7211Sjp161948 /* 1901*7211Sjp161948 * For now, we are limited to the fixed length of the counter, 1902*7211Sjp161948 * it covers the whole counter block. That's what RFC 4344 1903*7211Sjp161948 * needs. For more information on internal structure of the 1904*7211Sjp161948 * counter block, see RFC 3686. If needed in the future, we can 1905*7211Sjp161948 * add code so that the counter length can be set via 1906*7211Sjp161948 * ENGINE_ctrl() function. 1907*7211Sjp161948 */ 1908*7211Sjp161948 ctr_params.ulCounterBits = AES_BLOCK_SIZE * 8; 1909*7211Sjp161948 OPENSSL_assert(pcipher->iv_len == AES_BLOCK_SIZE); 1910*7211Sjp161948 memcpy(ctr_params.cb, ctx->iv, AES_BLOCK_SIZE); 1911*7211Sjp161948 } 1912*7211Sjp161948 else 1913*7211Sjp161948 #endif /* SOLARIS_AES_CTR */ 1914*7211Sjp161948 { 1915*7211Sjp161948 if (pcipher->iv_len > 0) 1916*7211Sjp161948 { 1917*7211Sjp161948 pmech->pParameter = (void *)ctx->iv; 1918*7211Sjp161948 pmech->ulParameterLen = pcipher->iv_len; 1919*7211Sjp161948 } 1920*7211Sjp161948 } 1921*7211Sjp161948 1922*7211Sjp161948 /* if we get here, the encryption needs to be reinitialized */ 1923*7211Sjp161948 if (ctx->encrypt) 1924*7211Sjp161948 rv = pFuncList->C_EncryptInit(sp->session_cipher, pmech, 1925*7211Sjp161948 sp->cipher_key); 1926*7211Sjp161948 else 1927*7211Sjp161948 rv = pFuncList->C_DecryptInit(sp->session_cipher, pmech, 1928*7211Sjp161948 sp->cipher_key); 1929*7211Sjp161948 1930*7211Sjp161948 if (rv != CKR_OK) 1931*7211Sjp161948 { 1932*7211Sjp161948 PK11err_add_data(PK11_F_CIPHER_INIT, ctx->encrypt ? 1933*7211Sjp161948 PK11_R_ENCRYPTINIT : PK11_R_DECRYPTINIT, rv); 1934*7211Sjp161948 pk11_return_session(sp, OP_CIPHER); 1935*7211Sjp161948 return (0); 1936*7211Sjp161948 } 1937*7211Sjp161948 1938*7211Sjp161948 return (1); 1939*7211Sjp161948 } 1940*7211Sjp161948 19410Sstevel@tonic-gate static int 19420Sstevel@tonic-gate pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, 19430Sstevel@tonic-gate const unsigned char *iv, int enc) 19440Sstevel@tonic-gate { 19454320Sjp161948 CK_MECHANISM mech; 19460Sstevel@tonic-gate int index; 19470Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; 19480Sstevel@tonic-gate PK11_SESSION *sp; 1949*7211Sjp161948 PK11_CIPHER *p_ciph_table_row; 19500Sstevel@tonic-gate 19510Sstevel@tonic-gate state->sp = NULL; 19520Sstevel@tonic-gate 19530Sstevel@tonic-gate index = cipher_nid_to_pk11(ctx->cipher->nid); 19540Sstevel@tonic-gate if (index < 0 || index >= PK11_CIPHER_MAX) 19550Sstevel@tonic-gate return 0; 19560Sstevel@tonic-gate 1957*7211Sjp161948 p_ciph_table_row = &ciphers[index]; 1958*7211Sjp161948 /* 1959*7211Sjp161948 * iv_len in the ctx->cipher structure is the maximum IV length for the 1960*7211Sjp161948 * current cipher and it must be less or equal to the IV length in our 1961*7211Sjp161948 * ciphers table. The key length must match precisely. Every application 1962*7211Sjp161948 * can define its own EVP functions so this code serves as a sanity 1963*7211Sjp161948 * check. 1964*7211Sjp161948 * 1965*7211Sjp161948 * Note that the reason why the IV length in ctx->cipher might be 1966*7211Sjp161948 * greater than the actual length is that OpenSSL uses BLOCK_CIPHER_defs 1967*7211Sjp161948 * macro to define functions that return EVP structures for all DES 1968*7211Sjp161948 * modes. So, even ECB modes get 8 byte IV. 1969*7211Sjp161948 */ 1970*7211Sjp161948 if (ctx->cipher->iv_len < p_ciph_table_row->iv_len || 1971*7211Sjp161948 ctx->key_len != p_ciph_table_row->key_len) 1972*7211Sjp161948 { 1973*7211Sjp161948 PK11err(PK11_F_CIPHER_INIT, PK11_R_KEY_OR_IV_LEN_PROBLEM); 19740Sstevel@tonic-gate return 0; 1975*7211Sjp161948 } 1976*7211Sjp161948 1977*7211Sjp161948 if ((sp = pk11_get_session(OP_CIPHER)) == NULL) 19780Sstevel@tonic-gate return 0; 19790Sstevel@tonic-gate 19804320Sjp161948 /* if applicable, the mechanism parameter is used for IV */ 1981*7211Sjp161948 mech.mechanism = p_ciph_table_row->mech_type; 19824320Sjp161948 mech.pParameter = NULL; 19834320Sjp161948 mech.ulParameterLen = 0; 19844320Sjp161948 19850Sstevel@tonic-gate /* The key object is destroyed here if it is not the current key 19860Sstevel@tonic-gate */ 1987*7211Sjp161948 (void) check_new_cipher_key(sp, key, p_ciph_table_row->key_len); 19880Sstevel@tonic-gate 19890Sstevel@tonic-gate /* If the key is the same and the encryption is also the same, 19906847Svk199839 * then just reuse it. However, we must not forget to reinitialize the 19916847Svk199839 * context that was finalized in pk11_cipher_cleanup(). 19920Sstevel@tonic-gate */ 19930Sstevel@tonic-gate if (sp->cipher_key != CK_INVALID_HANDLE && sp->encrypt == ctx->encrypt) 19940Sstevel@tonic-gate { 19950Sstevel@tonic-gate state->sp = sp; 1996*7211Sjp161948 if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0) 19976847Svk199839 return (0); 19986847Svk199839 19996847Svk199839 return (1); 20000Sstevel@tonic-gate } 20010Sstevel@tonic-gate 20020Sstevel@tonic-gate /* Check if the key has been invalidated. If so, a new key object 20030Sstevel@tonic-gate * needs to be created. 20040Sstevel@tonic-gate */ 20050Sstevel@tonic-gate if (sp->cipher_key == CK_INVALID_HANDLE) 20060Sstevel@tonic-gate { 20070Sstevel@tonic-gate sp->cipher_key = pk11_get_cipher_key( 2008*7211Sjp161948 ctx, key, p_ciph_table_row->key_type, sp); 20090Sstevel@tonic-gate } 20100Sstevel@tonic-gate 20110Sstevel@tonic-gate if (sp->encrypt != ctx->encrypt && sp->encrypt != -1) 20120Sstevel@tonic-gate { 20130Sstevel@tonic-gate /* The previous encryption/decryption 20140Sstevel@tonic-gate * is different. Need to terminate the previous 20150Sstevel@tonic-gate * active encryption/decryption here 20160Sstevel@tonic-gate */ 20170Sstevel@tonic-gate if (!pk11_cipher_final(sp)) 20180Sstevel@tonic-gate { 2019*7211Sjp161948 pk11_return_session(sp, OP_CIPHER); 20200Sstevel@tonic-gate return 0; 20210Sstevel@tonic-gate } 20220Sstevel@tonic-gate } 20230Sstevel@tonic-gate 20240Sstevel@tonic-gate if (sp->cipher_key == CK_INVALID_HANDLE) 20250Sstevel@tonic-gate { 2026*7211Sjp161948 pk11_return_session(sp, OP_CIPHER); 20270Sstevel@tonic-gate return 0; 20280Sstevel@tonic-gate } 20290Sstevel@tonic-gate 20306847Svk199839 /* now initialize the context with a new key */ 2031*7211Sjp161948 if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0) 20326847Svk199839 return (0); 20330Sstevel@tonic-gate 20340Sstevel@tonic-gate sp->encrypt = ctx->encrypt; 20350Sstevel@tonic-gate state->sp = sp; 20360Sstevel@tonic-gate 20370Sstevel@tonic-gate return 1; 20380Sstevel@tonic-gate } 20390Sstevel@tonic-gate 20400Sstevel@tonic-gate /* When reusing the same key in an encryption/decryption session for a 20410Sstevel@tonic-gate * decryption/encryption session, we need to close the active session 20420Sstevel@tonic-gate * and recreate a new one. Note that the key is in the global session so 20430Sstevel@tonic-gate * that it needs not be recreated. 20440Sstevel@tonic-gate * 20450Sstevel@tonic-gate * It is more appropriate to use C_En/DecryptFinish here. At the time of this 20460Sstevel@tonic-gate * development, these two functions in the PKCS#11 libraries used return 20470Sstevel@tonic-gate * unexpected errors when passing in 0 length output. It may be a good 20480Sstevel@tonic-gate * idea to try them again if performance is a problem here and fix 20490Sstevel@tonic-gate * C_En/DecryptFinial if there are bugs there causing the problem. 20500Sstevel@tonic-gate */ 20510Sstevel@tonic-gate static int 20520Sstevel@tonic-gate pk11_cipher_final(PK11_SESSION *sp) 20530Sstevel@tonic-gate { 20540Sstevel@tonic-gate CK_RV rv; 20550Sstevel@tonic-gate 20560Sstevel@tonic-gate rv = pFuncList->C_CloseSession(sp->session_cipher); 20570Sstevel@tonic-gate if (rv != CKR_OK) 20580Sstevel@tonic-gate { 2059*7211Sjp161948 PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_CLOSESESSION, rv); 20600Sstevel@tonic-gate return 0; 20610Sstevel@tonic-gate } 20620Sstevel@tonic-gate 20630Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 20640Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session_cipher); 20650Sstevel@tonic-gate if (rv != CKR_OK) 20660Sstevel@tonic-gate { 2067*7211Sjp161948 PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_OPENSESSION, rv); 20680Sstevel@tonic-gate return 0; 20690Sstevel@tonic-gate } 20700Sstevel@tonic-gate 20710Sstevel@tonic-gate return 1; 20720Sstevel@tonic-gate } 20730Sstevel@tonic-gate 20740Sstevel@tonic-gate /* An engine interface function. The calling function allocates sufficient 20750Sstevel@tonic-gate * memory for the output buffer "out" to hold the results */ 20760Sstevel@tonic-gate static int 20770Sstevel@tonic-gate pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 20780Sstevel@tonic-gate const unsigned char *in, unsigned int inl) 20790Sstevel@tonic-gate { 20800Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; 20810Sstevel@tonic-gate PK11_SESSION *sp; 20820Sstevel@tonic-gate CK_RV rv; 20830Sstevel@tonic-gate unsigned long outl = inl; 20840Sstevel@tonic-gate 20850Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 20860Sstevel@tonic-gate return 0; 20870Sstevel@tonic-gate 20880Sstevel@tonic-gate sp = (PK11_SESSION *) state->sp; 20890Sstevel@tonic-gate 20900Sstevel@tonic-gate if (!inl) 20910Sstevel@tonic-gate return 1; 20920Sstevel@tonic-gate 20930Sstevel@tonic-gate /* RC4 is the only stream cipher we support */ 20940Sstevel@tonic-gate if (ctx->cipher->nid != NID_rc4 && (inl % ctx->cipher->block_size) != 0) 20950Sstevel@tonic-gate return 0; 20960Sstevel@tonic-gate 20970Sstevel@tonic-gate if (ctx->encrypt) 20980Sstevel@tonic-gate { 20990Sstevel@tonic-gate rv = pFuncList->C_EncryptUpdate(sp->session_cipher, 21000Sstevel@tonic-gate (unsigned char *)in, inl, out, &outl); 21010Sstevel@tonic-gate 21020Sstevel@tonic-gate if (rv != CKR_OK) 21030Sstevel@tonic-gate { 2104*7211Sjp161948 PK11err_add_data(PK11_F_CIPHER_DO_CIPHER, 2105*7211Sjp161948 PK11_R_ENCRYPTUPDATE, rv); 21060Sstevel@tonic-gate return 0; 21070Sstevel@tonic-gate } 21080Sstevel@tonic-gate } 21090Sstevel@tonic-gate else 21100Sstevel@tonic-gate { 21110Sstevel@tonic-gate rv = pFuncList->C_DecryptUpdate(sp->session_cipher, 21120Sstevel@tonic-gate (unsigned char *)in, inl, out, &outl); 21130Sstevel@tonic-gate 21140Sstevel@tonic-gate if (rv != CKR_OK) 21150Sstevel@tonic-gate { 2116*7211Sjp161948 PK11err_add_data(PK11_F_CIPHER_DO_CIPHER, 2117*7211Sjp161948 PK11_R_DECRYPTUPDATE, rv); 21180Sstevel@tonic-gate return 0; 21190Sstevel@tonic-gate } 21200Sstevel@tonic-gate } 21210Sstevel@tonic-gate 21220Sstevel@tonic-gate /* for DES_CBC, DES3_CBC, AES_CBC, and RC4, the output size is always 21230Sstevel@tonic-gate * the same size of input 21240Sstevel@tonic-gate * The application has guaranteed to call the block ciphers with 21250Sstevel@tonic-gate * correctly aligned buffers. 21260Sstevel@tonic-gate */ 21270Sstevel@tonic-gate if (inl != outl) 21280Sstevel@tonic-gate return 0; 21290Sstevel@tonic-gate 21300Sstevel@tonic-gate return 1; 21310Sstevel@tonic-gate } 21320Sstevel@tonic-gate 21336847Svk199839 /* 2134*7211Sjp161948 * Return the session to the pool. Calling C_EncryptFinal() and C_DecryptFinal() 2135*7211Sjp161948 * here is the right thing because in EVP_DecryptFinal_ex(), engine's 2136*7211Sjp161948 * do_cipher() is not even called, and in EVP_EncryptFinal_ex() it is called but 2137*7211Sjp161948 * the engine can't find out that it's the finalizing call. We wouldn't 2138*7211Sjp161948 * necessarily have to finalize the context here since reinitializing it with 2139*7211Sjp161948 * C_(Encrypt|Decrypt)Init() should be fine but for the sake of correctness, 2140*7211Sjp161948 * let's do it. Some implementations might leak memory if the previously used 2141*7211Sjp161948 * context is initialized without finalizing it first. 21420Sstevel@tonic-gate */ 21430Sstevel@tonic-gate static int 21440Sstevel@tonic-gate pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx) 21450Sstevel@tonic-gate { 21466847Svk199839 CK_RV rv; 2147*7211Sjp161948 CK_ULONG len = EVP_MAX_BLOCK_LENGTH; 21486847Svk199839 CK_BYTE buf[EVP_MAX_BLOCK_LENGTH]; 21490Sstevel@tonic-gate PK11_CIPHER_STATE *state = ctx->cipher_data; 21500Sstevel@tonic-gate 21510Sstevel@tonic-gate if (state != NULL && state->sp != NULL) 21520Sstevel@tonic-gate { 21536847Svk199839 /* 21546847Svk199839 * We are not interested in the data here, we just need to get 21556847Svk199839 * rid of the context. 21566847Svk199839 */ 21576847Svk199839 if (ctx->encrypt) 21586847Svk199839 rv = pFuncList->C_EncryptFinal( 21596847Svk199839 state->sp->session_cipher, buf, &len); 21606847Svk199839 else 21616847Svk199839 rv = pFuncList->C_DecryptFinal( 21626847Svk199839 state->sp->session_cipher, buf, &len); 21636847Svk199839 21646847Svk199839 if (rv != CKR_OK) 21656847Svk199839 { 2166*7211Sjp161948 PK11err_add_data(PK11_F_CIPHER_CLEANUP, ctx->encrypt ? 2167*7211Sjp161948 PK11_R_ENCRYPTFINAL : PK11_R_DECRYPTFINAL, rv); 2168*7211Sjp161948 pk11_return_session(state->sp, OP_CIPHER); 21696847Svk199839 return (0); 21706847Svk199839 } 21716847Svk199839 2172*7211Sjp161948 pk11_return_session(state->sp, OP_CIPHER); 21730Sstevel@tonic-gate state->sp = NULL; 21740Sstevel@tonic-gate } 21750Sstevel@tonic-gate 21766847Svk199839 return (1); 21776847Svk199839 } 21786847Svk199839 21790Sstevel@tonic-gate /* Registered by the ENGINE when used to find out how to deal with 21800Sstevel@tonic-gate * a particular NID in the ENGINE. This says what we'll do at the 21810Sstevel@tonic-gate * top level - note, that list is restricted by what we answer with 21820Sstevel@tonic-gate */ 21830Sstevel@tonic-gate static int 21840Sstevel@tonic-gate pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 21850Sstevel@tonic-gate const int **nids, int nid) 21860Sstevel@tonic-gate { 21870Sstevel@tonic-gate if (!cipher) 21880Sstevel@tonic-gate return (pk11_usable_ciphers(nids)); 21890Sstevel@tonic-gate 21900Sstevel@tonic-gate switch (nid) 21910Sstevel@tonic-gate { 21920Sstevel@tonic-gate case NID_des_ede3_cbc: 21930Sstevel@tonic-gate *cipher = &pk11_3des_cbc; 21940Sstevel@tonic-gate break; 21950Sstevel@tonic-gate case NID_des_cbc: 21960Sstevel@tonic-gate *cipher = &pk11_des_cbc; 21970Sstevel@tonic-gate break; 2198*7211Sjp161948 case NID_des_ede3_ecb: 2199*7211Sjp161948 *cipher = &pk11_3des_ecb; 2200*7211Sjp161948 break; 2201*7211Sjp161948 case NID_des_ecb: 2202*7211Sjp161948 *cipher = &pk11_des_ecb; 2203*7211Sjp161948 break; 22040Sstevel@tonic-gate case NID_aes_128_cbc: 2205*7211Sjp161948 *cipher = &pk11_aes_128_cbc; 2206*7211Sjp161948 break; 2207*7211Sjp161948 case NID_aes_192_cbc: 2208*7211Sjp161948 *cipher = &pk11_aes_192_cbc; 2209*7211Sjp161948 break; 2210*7211Sjp161948 case NID_aes_256_cbc: 2211*7211Sjp161948 *cipher = &pk11_aes_256_cbc; 2212*7211Sjp161948 break; 2213*7211Sjp161948 case NID_aes_128_ecb: 2214*7211Sjp161948 *cipher = &pk11_aes_128_ecb; 2215*7211Sjp161948 break; 2216*7211Sjp161948 case NID_aes_192_ecb: 2217*7211Sjp161948 *cipher = &pk11_aes_192_ecb; 2218*7211Sjp161948 break; 2219*7211Sjp161948 case NID_aes_256_ecb: 2220*7211Sjp161948 *cipher = &pk11_aes_256_ecb; 2221*7211Sjp161948 break; 2222*7211Sjp161948 case NID_bf_cbc: 2223*7211Sjp161948 *cipher = &pk11_bf_cbc; 22240Sstevel@tonic-gate break; 22250Sstevel@tonic-gate case NID_rc4: 22260Sstevel@tonic-gate *cipher = &pk11_rc4; 22270Sstevel@tonic-gate break; 22280Sstevel@tonic-gate default: 2229*7211Sjp161948 #ifdef SOLARIS_AES_CTR 2230*7211Sjp161948 /* 2231*7211Sjp161948 * These can't be in separated cases because the NIDs 2232*7211Sjp161948 * here are not constants. 2233*7211Sjp161948 */ 2234*7211Sjp161948 if (nid == NID_aes_128_ctr) 2235*7211Sjp161948 *cipher = &pk11_aes_128_ctr; 2236*7211Sjp161948 else if (nid == NID_aes_192_ctr) 2237*7211Sjp161948 *cipher = &pk11_aes_192_ctr; 2238*7211Sjp161948 else if (nid == NID_aes_256_ctr) 2239*7211Sjp161948 *cipher = &pk11_aes_256_ctr; 2240*7211Sjp161948 else 2241*7211Sjp161948 #endif /* SOLARIS_AES_CTR */ 22420Sstevel@tonic-gate *cipher = NULL; 22430Sstevel@tonic-gate break; 22440Sstevel@tonic-gate } 22450Sstevel@tonic-gate return (*cipher != NULL); 22460Sstevel@tonic-gate } 22470Sstevel@tonic-gate 22480Sstevel@tonic-gate static int 22490Sstevel@tonic-gate pk11_engine_digests(ENGINE *e, const EVP_MD **digest, 22500Sstevel@tonic-gate const int **nids, int nid) 22510Sstevel@tonic-gate { 22520Sstevel@tonic-gate if (!digest) 22530Sstevel@tonic-gate return (pk11_usable_digests(nids)); 22540Sstevel@tonic-gate 22550Sstevel@tonic-gate switch (nid) 22560Sstevel@tonic-gate { 22570Sstevel@tonic-gate case NID_md5: 22580Sstevel@tonic-gate *digest = &pk11_md5; 22590Sstevel@tonic-gate break; 22600Sstevel@tonic-gate case NID_sha1: 22610Sstevel@tonic-gate *digest = &pk11_sha1; 22620Sstevel@tonic-gate break; 2263*7211Sjp161948 case NID_sha224: 2264*7211Sjp161948 *digest = &pk11_sha224; 2265*7211Sjp161948 break; 2266*7211Sjp161948 case NID_sha256: 2267*7211Sjp161948 *digest = &pk11_sha256; 2268*7211Sjp161948 break; 2269*7211Sjp161948 case NID_sha384: 2270*7211Sjp161948 *digest = &pk11_sha384; 2271*7211Sjp161948 break; 2272*7211Sjp161948 case NID_sha512: 2273*7211Sjp161948 *digest = &pk11_sha512; 2274*7211Sjp161948 break; 22750Sstevel@tonic-gate default: 22760Sstevel@tonic-gate *digest = NULL; 22770Sstevel@tonic-gate break; 22780Sstevel@tonic-gate } 22790Sstevel@tonic-gate return (*digest != NULL); 22800Sstevel@tonic-gate } 22810Sstevel@tonic-gate 22820Sstevel@tonic-gate 22830Sstevel@tonic-gate /* Create a secret key object in a PKCS#11 session 22840Sstevel@tonic-gate */ 22850Sstevel@tonic-gate static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, 22860Sstevel@tonic-gate const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp) 22870Sstevel@tonic-gate { 22880Sstevel@tonic-gate CK_RV rv; 22890Sstevel@tonic-gate CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; 22900Sstevel@tonic-gate CK_OBJECT_CLASS obj_key = CKO_SECRET_KEY; 22910Sstevel@tonic-gate CK_ULONG ul_key_attr_count = 6; 22920Sstevel@tonic-gate 22930Sstevel@tonic-gate CK_ATTRIBUTE a_key_template[] = 22940Sstevel@tonic-gate { 22950Sstevel@tonic-gate {CKA_CLASS, (void*) NULL, sizeof(CK_OBJECT_CLASS)}, 22960Sstevel@tonic-gate {CKA_KEY_TYPE, (void*) NULL, sizeof(CK_KEY_TYPE)}, 22970Sstevel@tonic-gate {CKA_TOKEN, &false, sizeof(false)}, 22980Sstevel@tonic-gate {CKA_ENCRYPT, &true, sizeof(true)}, 22990Sstevel@tonic-gate {CKA_DECRYPT, &true, sizeof(true)}, 23000Sstevel@tonic-gate {CKA_VALUE, (void*) NULL, 0}, 23010Sstevel@tonic-gate }; 23020Sstevel@tonic-gate 23030Sstevel@tonic-gate /* Create secret key object in global_session. All other sessions 23040Sstevel@tonic-gate * can use the key handles. Here is why: 23050Sstevel@tonic-gate * OpenSSL will call EncryptInit and EncryptUpdate using a secret key. 23060Sstevel@tonic-gate * It may then call DecryptInit and DecryptUpdate using the same key. 23070Sstevel@tonic-gate * To use the same key object, we need to call EncryptFinal with 23080Sstevel@tonic-gate * a 0 length message. Currently, this does not work for 3DES 23090Sstevel@tonic-gate * mechanism. To get around this problem, we close the session and 23100Sstevel@tonic-gate * then create a new session to use the same key object. When a session 23110Sstevel@tonic-gate * is closed, all the object handles will be invalid. Thus, create key 23120Sstevel@tonic-gate * objects in a global session, an individual session may be closed to 23130Sstevel@tonic-gate * terminate the active operation. 23140Sstevel@tonic-gate */ 23150Sstevel@tonic-gate CK_SESSION_HANDLE session = global_session; 23160Sstevel@tonic-gate a_key_template[0].pValue = &obj_key; 23170Sstevel@tonic-gate a_key_template[1].pValue = &key_type; 23180Sstevel@tonic-gate a_key_template[5].pValue = (void *) key; 23190Sstevel@tonic-gate a_key_template[5].ulValueLen = (unsigned long) ctx->key_len; 23200Sstevel@tonic-gate 23214602Sjp161948 rv = pFuncList->C_CreateObject(session, 23224602Sjp161948 a_key_template, ul_key_attr_count, &h_key); 23230Sstevel@tonic-gate if (rv != CKR_OK) 23240Sstevel@tonic-gate { 2325*7211Sjp161948 PK11err_add_data(PK11_F_GET_CIPHER_KEY, PK11_R_CREATEOBJECT, 2326*7211Sjp161948 rv); 23270Sstevel@tonic-gate goto err; 23280Sstevel@tonic-gate } 23290Sstevel@tonic-gate 23300Sstevel@tonic-gate /* Save the key information used in this session. 23310Sstevel@tonic-gate * The max can be saved is PK11_KEY_LEN_MAX. 23320Sstevel@tonic-gate */ 23330Sstevel@tonic-gate sp->key_len = ctx->key_len > PK11_KEY_LEN_MAX ? 23340Sstevel@tonic-gate PK11_KEY_LEN_MAX : ctx->key_len; 23350Sstevel@tonic-gate memcpy(sp->key, key, sp->key_len); 23360Sstevel@tonic-gate err: 23370Sstevel@tonic-gate 23380Sstevel@tonic-gate return h_key; 23390Sstevel@tonic-gate } 23400Sstevel@tonic-gate 23410Sstevel@tonic-gate static int 23420Sstevel@tonic-gate md_nid_to_pk11(int nid) 23430Sstevel@tonic-gate { 23440Sstevel@tonic-gate int i; 23450Sstevel@tonic-gate 23460Sstevel@tonic-gate for (i = 0; i < PK11_DIGEST_MAX; i++) 23470Sstevel@tonic-gate if (digests[i].nid == nid) 23480Sstevel@tonic-gate return (digests[i].id); 23490Sstevel@tonic-gate return (-1); 23500Sstevel@tonic-gate } 23510Sstevel@tonic-gate 23520Sstevel@tonic-gate static int 23530Sstevel@tonic-gate pk11_digest_init(EVP_MD_CTX *ctx) 23540Sstevel@tonic-gate { 23550Sstevel@tonic-gate CK_RV rv; 23564320Sjp161948 CK_MECHANISM mech; 23570Sstevel@tonic-gate int index; 23580Sstevel@tonic-gate PK11_SESSION *sp; 23590Sstevel@tonic-gate PK11_DIGEST *pdp; 23600Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; 23610Sstevel@tonic-gate 23620Sstevel@tonic-gate state->sp = NULL; 23630Sstevel@tonic-gate 23640Sstevel@tonic-gate index = md_nid_to_pk11(ctx->digest->type); 23650Sstevel@tonic-gate if (index < 0 || index >= PK11_DIGEST_MAX) 23660Sstevel@tonic-gate return 0; 23670Sstevel@tonic-gate 23680Sstevel@tonic-gate pdp = &digests[index]; 2369*7211Sjp161948 if ((sp = pk11_get_session(OP_DIGEST)) == NULL) 23700Sstevel@tonic-gate return 0; 23710Sstevel@tonic-gate 23724320Sjp161948 /* at present, no parameter is needed for supported digests */ 23734320Sjp161948 mech.mechanism = pdp->mech_type; 23744320Sjp161948 mech.pParameter = NULL; 23754320Sjp161948 mech.ulParameterLen = 0; 23764320Sjp161948 23774320Sjp161948 rv = pFuncList->C_DigestInit(sp->session, &mech); 23780Sstevel@tonic-gate 23790Sstevel@tonic-gate if (rv != CKR_OK) 23800Sstevel@tonic-gate { 2381*7211Sjp161948 PK11err_add_data(PK11_F_DIGEST_INIT, PK11_R_DIGESTINIT, rv); 2382*7211Sjp161948 pk11_return_session(sp, OP_DIGEST); 23830Sstevel@tonic-gate return 0; 23840Sstevel@tonic-gate } 23850Sstevel@tonic-gate 23860Sstevel@tonic-gate state->sp = sp; 23870Sstevel@tonic-gate 23880Sstevel@tonic-gate return 1; 23890Sstevel@tonic-gate } 23900Sstevel@tonic-gate 23910Sstevel@tonic-gate static int 23922139Sjp161948 pk11_digest_update(EVP_MD_CTX *ctx,const void *data,size_t count) 23930Sstevel@tonic-gate { 23940Sstevel@tonic-gate CK_RV rv; 23950Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; 23960Sstevel@tonic-gate 23970Sstevel@tonic-gate /* 0 length message will cause a failure in C_DigestFinal */ 23980Sstevel@tonic-gate if (count == 0) 23990Sstevel@tonic-gate return 1; 24000Sstevel@tonic-gate 24010Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 24020Sstevel@tonic-gate return 0; 24030Sstevel@tonic-gate 24040Sstevel@tonic-gate rv = pFuncList->C_DigestUpdate(state->sp->session, (CK_BYTE *) data, 24050Sstevel@tonic-gate count); 24060Sstevel@tonic-gate 24070Sstevel@tonic-gate if (rv != CKR_OK) 24080Sstevel@tonic-gate { 2409*7211Sjp161948 PK11err_add_data(PK11_F_DIGEST_UPDATE, PK11_R_DIGESTUPDATE, rv); 2410*7211Sjp161948 pk11_return_session(state->sp, OP_DIGEST); 24110Sstevel@tonic-gate state->sp = NULL; 24120Sstevel@tonic-gate return 0; 24130Sstevel@tonic-gate } 24140Sstevel@tonic-gate 24150Sstevel@tonic-gate return 1; 24160Sstevel@tonic-gate } 24170Sstevel@tonic-gate 24180Sstevel@tonic-gate static int 24190Sstevel@tonic-gate pk11_digest_final(EVP_MD_CTX *ctx,unsigned char *md) 24200Sstevel@tonic-gate { 24210Sstevel@tonic-gate CK_RV rv; 24220Sstevel@tonic-gate unsigned long len; 24230Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; 24240Sstevel@tonic-gate len = ctx->digest->md_size; 24250Sstevel@tonic-gate 24260Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 24270Sstevel@tonic-gate return 0; 24280Sstevel@tonic-gate 24290Sstevel@tonic-gate rv = pFuncList->C_DigestFinal(state->sp->session, md, &len); 24300Sstevel@tonic-gate 24310Sstevel@tonic-gate if (rv != CKR_OK) 24320Sstevel@tonic-gate { 2433*7211Sjp161948 PK11err_add_data(PK11_F_DIGEST_FINAL, PK11_R_DIGESTFINAL, rv); 2434*7211Sjp161948 pk11_return_session(state->sp, OP_DIGEST); 24350Sstevel@tonic-gate state->sp = NULL; 24360Sstevel@tonic-gate return 0; 24370Sstevel@tonic-gate } 24380Sstevel@tonic-gate 24390Sstevel@tonic-gate if (ctx->digest->md_size != len) 24400Sstevel@tonic-gate return 0; 24410Sstevel@tonic-gate 24420Sstevel@tonic-gate /* Final is called and digest is returned, so return the session 24430Sstevel@tonic-gate * to the pool 24440Sstevel@tonic-gate */ 2445*7211Sjp161948 pk11_return_session(state->sp, OP_DIGEST); 24460Sstevel@tonic-gate state->sp = NULL; 24470Sstevel@tonic-gate 24480Sstevel@tonic-gate return 1; 24490Sstevel@tonic-gate } 24500Sstevel@tonic-gate 24510Sstevel@tonic-gate static int 24520Sstevel@tonic-gate pk11_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from) 24530Sstevel@tonic-gate { 24540Sstevel@tonic-gate CK_RV rv; 24550Sstevel@tonic-gate int ret = 0; 24560Sstevel@tonic-gate PK11_CIPHER_STATE *state, *state_to; 24570Sstevel@tonic-gate CK_BYTE_PTR pstate = NULL; 24580Sstevel@tonic-gate CK_ULONG ul_state_len; 24590Sstevel@tonic-gate 24600Sstevel@tonic-gate /* The copy-from state */ 24610Sstevel@tonic-gate state = (PK11_CIPHER_STATE *) from->md_data; 24620Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 24630Sstevel@tonic-gate goto err; 24640Sstevel@tonic-gate 24650Sstevel@tonic-gate /* Initialize the copy-to state */ 24660Sstevel@tonic-gate if (!pk11_digest_init(to)) 24670Sstevel@tonic-gate goto err; 24680Sstevel@tonic-gate state_to = (PK11_CIPHER_STATE *) to->md_data; 24690Sstevel@tonic-gate 24700Sstevel@tonic-gate /* Get the size of the operation state of the copy-from session */ 24710Sstevel@tonic-gate rv = pFuncList->C_GetOperationState(state->sp->session, NULL, 24720Sstevel@tonic-gate &ul_state_len); 24730Sstevel@tonic-gate 24740Sstevel@tonic-gate if (rv != CKR_OK) 24750Sstevel@tonic-gate { 2476*7211Sjp161948 PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE, 2477*7211Sjp161948 rv); 24780Sstevel@tonic-gate goto err; 24790Sstevel@tonic-gate } 24800Sstevel@tonic-gate if (ul_state_len == 0) 24810Sstevel@tonic-gate { 24820Sstevel@tonic-gate goto err; 24830Sstevel@tonic-gate } 24840Sstevel@tonic-gate 24850Sstevel@tonic-gate pstate = OPENSSL_malloc(ul_state_len); 24860Sstevel@tonic-gate if (pstate == NULL) 24870Sstevel@tonic-gate { 24886847Svk199839 PK11err(PK11_F_DIGEST_COPY, PK11_R_MALLOC_FAILURE); 24890Sstevel@tonic-gate goto err; 24900Sstevel@tonic-gate } 24910Sstevel@tonic-gate 24920Sstevel@tonic-gate /* Get the operation state of the copy-from session */ 24930Sstevel@tonic-gate rv = pFuncList->C_GetOperationState(state->sp->session, pstate, 24940Sstevel@tonic-gate &ul_state_len); 24950Sstevel@tonic-gate 24960Sstevel@tonic-gate if (rv != CKR_OK) 24970Sstevel@tonic-gate { 2498*7211Sjp161948 PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE, 2499*7211Sjp161948 rv); 25000Sstevel@tonic-gate goto err; 25010Sstevel@tonic-gate } 25020Sstevel@tonic-gate 25030Sstevel@tonic-gate /* Set the operation state of the copy-to session */ 25040Sstevel@tonic-gate rv = pFuncList->C_SetOperationState(state_to->sp->session, pstate, 25050Sstevel@tonic-gate ul_state_len, 0, 0); 25060Sstevel@tonic-gate 25070Sstevel@tonic-gate if (rv != CKR_OK) 25080Sstevel@tonic-gate { 2509*7211Sjp161948 PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_SET_OPERATION_STATE, rv); 25100Sstevel@tonic-gate goto err; 25110Sstevel@tonic-gate } 25120Sstevel@tonic-gate 25130Sstevel@tonic-gate ret = 1; 25140Sstevel@tonic-gate err: 25150Sstevel@tonic-gate if (pstate != NULL) 25160Sstevel@tonic-gate OPENSSL_free(pstate); 25170Sstevel@tonic-gate 25180Sstevel@tonic-gate return ret; 25190Sstevel@tonic-gate } 25200Sstevel@tonic-gate 25210Sstevel@tonic-gate /* Return any pending session state to the pool */ 25220Sstevel@tonic-gate static int 25230Sstevel@tonic-gate pk11_digest_cleanup(EVP_MD_CTX *ctx) 25240Sstevel@tonic-gate { 25250Sstevel@tonic-gate PK11_CIPHER_STATE *state = ctx->md_data; 25264602Sjp161948 unsigned char buf[EVP_MAX_MD_SIZE]; 25270Sstevel@tonic-gate 25280Sstevel@tonic-gate if (state != NULL && state->sp != NULL) 25290Sstevel@tonic-gate { 25304602Sjp161948 /* 25314602Sjp161948 * If state->sp is not NULL then pk11_digest_final() has not 25324602Sjp161948 * been called yet. We must call it now to free any memory 25334602Sjp161948 * that might have been allocated in the token when 25344602Sjp161948 * pk11_digest_init() was called. 25354602Sjp161948 */ 2536*7211Sjp161948 (void) pk11_digest_final(ctx,buf); 2537*7211Sjp161948 pk11_return_session(state->sp, OP_DIGEST); 25380Sstevel@tonic-gate state->sp = NULL; 25390Sstevel@tonic-gate } 25400Sstevel@tonic-gate 25410Sstevel@tonic-gate return 1; 25420Sstevel@tonic-gate } 25430Sstevel@tonic-gate 25446847Svk199839 /* 2545*7211Sjp161948 * Check if the new key is the same as the key object in the session. If the key 2546*7211Sjp161948 * is the same, no need to create a new key object. Otherwise, the old key 2547*7211Sjp161948 * object needs to be destroyed and a new one will be created. Return 1 for 2548*7211Sjp161948 * cache hit, 0 for cache miss. Note that we must check the key length first 2549*7211Sjp161948 * otherwise we could end up reusing a different, longer key with the same 2550*7211Sjp161948 * prefix. 25510Sstevel@tonic-gate */ 2552*7211Sjp161948 static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key, 2553*7211Sjp161948 int key_len) 25540Sstevel@tonic-gate { 2555*7211Sjp161948 if (sp->key_len != key_len || memcmp(sp->key, key, key_len) != 0) 25566847Svk199839 { 2557*7211Sjp161948 (void) pk11_destroy_cipher_key_objects(sp); 25586847Svk199839 return (0); 25596847Svk199839 } 25606847Svk199839 return (1); 25610Sstevel@tonic-gate } 25620Sstevel@tonic-gate 25630Sstevel@tonic-gate /* Destroy one or more secret key objects. 25640Sstevel@tonic-gate */ 25650Sstevel@tonic-gate static int pk11_destroy_cipher_key_objects(PK11_SESSION *session) 25660Sstevel@tonic-gate { 25670Sstevel@tonic-gate int ret = 0; 25680Sstevel@tonic-gate PK11_SESSION *sp = NULL; 25690Sstevel@tonic-gate PK11_SESSION *local_free_session; 25700Sstevel@tonic-gate 25710Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 25720Sstevel@tonic-gate if (session) 25730Sstevel@tonic-gate local_free_session = session; 25740Sstevel@tonic-gate else 25750Sstevel@tonic-gate local_free_session = free_session; 25760Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 25770Sstevel@tonic-gate { 25780Sstevel@tonic-gate local_free_session = sp->next; 25790Sstevel@tonic-gate 25800Sstevel@tonic-gate if (sp->cipher_key != CK_INVALID_HANDLE) 25810Sstevel@tonic-gate { 25820Sstevel@tonic-gate /* The secret key object is created in the 25830Sstevel@tonic-gate * global_session. See pk11_get_cipher_key 25840Sstevel@tonic-gate */ 25850Sstevel@tonic-gate if (pk11_destroy_object(global_session, 25860Sstevel@tonic-gate sp->cipher_key) == 0) 25870Sstevel@tonic-gate goto err; 25880Sstevel@tonic-gate sp->cipher_key = CK_INVALID_HANDLE; 25890Sstevel@tonic-gate } 25900Sstevel@tonic-gate } 25910Sstevel@tonic-gate ret = 1; 25920Sstevel@tonic-gate err: 25930Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 25940Sstevel@tonic-gate 25950Sstevel@tonic-gate return ret; 25960Sstevel@tonic-gate } 25970Sstevel@tonic-gate 25980Sstevel@tonic-gate 25990Sstevel@tonic-gate /* 2600*7211Sjp161948 * Public key mechanisms optionally supported 26010Sstevel@tonic-gate * 26020Sstevel@tonic-gate * CKM_RSA_X_509 26030Sstevel@tonic-gate * CKM_RSA_PKCS 26040Sstevel@tonic-gate * CKM_DSA 26050Sstevel@tonic-gate * 2606*7211Sjp161948 * The first slot that supports at least one of those mechanisms is chosen as a 2607*7211Sjp161948 * public key slot. 26080Sstevel@tonic-gate * 26090Sstevel@tonic-gate * Symmetric ciphers optionally supported 26100Sstevel@tonic-gate * 26110Sstevel@tonic-gate * CKM_DES3_CBC 26120Sstevel@tonic-gate * CKM_DES_CBC 26130Sstevel@tonic-gate * CKM_AES_CBC 2614*7211Sjp161948 * CKM_DES3_ECB 2615*7211Sjp161948 * CKM_DES_ECB 2616*7211Sjp161948 * CKM_AES_ECB 2617*7211Sjp161948 * CKM_AES_CTR 26180Sstevel@tonic-gate * CKM_RC4 2619*7211Sjp161948 * CKM_BLOWFISH_CBC 26200Sstevel@tonic-gate * 26210Sstevel@tonic-gate * Digests optionally supported 26220Sstevel@tonic-gate * 26230Sstevel@tonic-gate * CKM_MD5 26240Sstevel@tonic-gate * CKM_SHA_1 2625*7211Sjp161948 * CKM_SHA224 2626*7211Sjp161948 * CKM_SHA256 2627*7211Sjp161948 * CKM_SHA384 2628*7211Sjp161948 * CKM_SHA512 2629*7211Sjp161948 * 2630*7211Sjp161948 * The output of this function is a set of global variables indicating which 2631*7211Sjp161948 * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of 2632*7211Sjp161948 * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global 2633*7211Sjp161948 * variables carry information about which slot was chosen for (a) public key 2634*7211Sjp161948 * mechanisms, (b) random operations, and (c) symmetric ciphers and digests. 26350Sstevel@tonic-gate */ 26360Sstevel@tonic-gate static int 2637*7211Sjp161948 pk11_choose_slots(int *any_slot_found) 26380Sstevel@tonic-gate { 26390Sstevel@tonic-gate CK_SLOT_ID_PTR pSlotList = NULL_PTR; 26400Sstevel@tonic-gate CK_ULONG ulSlotCount = 0; 26410Sstevel@tonic-gate CK_MECHANISM_INFO mech_info; 26420Sstevel@tonic-gate CK_TOKEN_INFO token_info; 26430Sstevel@tonic-gate int i; 26440Sstevel@tonic-gate CK_RV rv; 26450Sstevel@tonic-gate CK_SLOT_ID best_slot_sofar; 26460Sstevel@tonic-gate CK_BBOOL found_candidate_slot = CK_FALSE; 26470Sstevel@tonic-gate int slot_n_cipher = 0; 26480Sstevel@tonic-gate int slot_n_digest = 0; 26490Sstevel@tonic-gate CK_SLOT_ID current_slot = 0; 26500Sstevel@tonic-gate int current_slot_n_cipher = 0; 26510Sstevel@tonic-gate int current_slot_n_digest = 0; 26520Sstevel@tonic-gate 26530Sstevel@tonic-gate int local_cipher_nids[PK11_CIPHER_MAX]; 26540Sstevel@tonic-gate int local_digest_nids[PK11_DIGEST_MAX]; 2655*7211Sjp161948 2656*7211Sjp161948 /* let's initialize the output parameter */ 2657*7211Sjp161948 if (any_slot_found != NULL) 2658*7211Sjp161948 *any_slot_found = 0; 2659*7211Sjp161948 2660*7211Sjp161948 /* Get slot list for memory allocation */ 26610Sstevel@tonic-gate rv = pFuncList->C_GetSlotList(0, NULL_PTR, &ulSlotCount); 26620Sstevel@tonic-gate 26630Sstevel@tonic-gate if (rv != CKR_OK) 26640Sstevel@tonic-gate { 2665*7211Sjp161948 PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); 2666*7211Sjp161948 return 0; 26670Sstevel@tonic-gate } 26680Sstevel@tonic-gate 2669*7211Sjp161948 /* it's not an error if we didn't find any providers */ 26700Sstevel@tonic-gate if (ulSlotCount == 0) 26710Sstevel@tonic-gate { 2672*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2673*7211Sjp161948 fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG); 2674*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 2675*7211Sjp161948 return 1; 26760Sstevel@tonic-gate } 26770Sstevel@tonic-gate 26780Sstevel@tonic-gate pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); 26790Sstevel@tonic-gate 26800Sstevel@tonic-gate if (pSlotList == NULL) 26810Sstevel@tonic-gate { 26826847Svk199839 PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE); 2683*7211Sjp161948 return 0; 26840Sstevel@tonic-gate } 26850Sstevel@tonic-gate 26860Sstevel@tonic-gate /* Get the slot list for processing */ 26870Sstevel@tonic-gate rv = pFuncList->C_GetSlotList(0, pSlotList, &ulSlotCount); 26880Sstevel@tonic-gate if (rv != CKR_OK) 26890Sstevel@tonic-gate { 2690*7211Sjp161948 PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); 26910Sstevel@tonic-gate OPENSSL_free(pSlotList); 2692*7211Sjp161948 return 0; 26930Sstevel@tonic-gate } 26940Sstevel@tonic-gate 2695*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2696*7211Sjp161948 fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME); 2697*7211Sjp161948 fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount); 2698*7211Sjp161948 2699*7211Sjp161948 fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG); 2700*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 2701*7211Sjp161948 for (i = 0; i < ulSlotCount; i++) 2702*7211Sjp161948 { 2703*7211Sjp161948 current_slot = pSlotList[i]; 2704*7211Sjp161948 2705*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2706*7211Sjp161948 fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); 2707*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 2708*7211Sjp161948 /* Check if slot has random support. */ 2709*7211Sjp161948 rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); 2710*7211Sjp161948 if (rv != CKR_OK) 2711*7211Sjp161948 continue; 2712*7211Sjp161948 2713*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2714*7211Sjp161948 fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); 2715*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 2716*7211Sjp161948 2717*7211Sjp161948 if (token_info.flags & CKF_RNG) 2718*7211Sjp161948 { 2719*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2720*7211Sjp161948 fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG); 2721*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 2722*7211Sjp161948 pk11_have_random = CK_TRUE; 2723*7211Sjp161948 break; 2724*7211Sjp161948 } 2725*7211Sjp161948 } 2726*7211Sjp161948 2727*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2728*7211Sjp161948 fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG); 2729*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 27300Sstevel@tonic-gate for (i = 0; i < ulSlotCount; i++) 27310Sstevel@tonic-gate { 27320Sstevel@tonic-gate CK_BBOOL slot_has_rsa = CK_FALSE; 27330Sstevel@tonic-gate CK_BBOOL slot_has_dsa = CK_FALSE; 27340Sstevel@tonic-gate CK_BBOOL slot_has_dh = CK_FALSE; 27350Sstevel@tonic-gate current_slot = pSlotList[i]; 2736*7211Sjp161948 2737*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2738*7211Sjp161948 fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); 2739*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 27400Sstevel@tonic-gate rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); 27410Sstevel@tonic-gate if (rv != CKR_OK) 27420Sstevel@tonic-gate continue; 27430Sstevel@tonic-gate 2744*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2745*7211Sjp161948 fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); 2746*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 2747*7211Sjp161948 27486847Svk199839 #ifndef OPENSSL_NO_RSA 27490Sstevel@tonic-gate /* 27500Sstevel@tonic-gate * Check if this slot is capable of signing and 27510Sstevel@tonic-gate * verifying with CKM_RSA_PKCS. 27520Sstevel@tonic-gate */ 27530Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS, 27540Sstevel@tonic-gate &mech_info); 27550Sstevel@tonic-gate 27560Sstevel@tonic-gate if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && 27570Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY))) 27580Sstevel@tonic-gate { 27590Sstevel@tonic-gate /* 27600Sstevel@tonic-gate * Check if this slot is capable of encryption, 27610Sstevel@tonic-gate * decryption, sign, and verify with CKM_RSA_X_509. 27620Sstevel@tonic-gate */ 27630Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, 27640Sstevel@tonic-gate CKM_RSA_X_509, &mech_info); 27650Sstevel@tonic-gate 27660Sstevel@tonic-gate if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && 27670Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY) && 27680Sstevel@tonic-gate (mech_info.flags & CKF_ENCRYPT) && 27690Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY_RECOVER) && 27700Sstevel@tonic-gate (mech_info.flags & CKF_DECRYPT))) 2771*7211Sjp161948 { 27720Sstevel@tonic-gate slot_has_rsa = CK_TRUE; 2773*7211Sjp161948 } 27740Sstevel@tonic-gate } 2775*7211Sjp161948 #endif /* OPENSSL_NO_RSA */ 2776*7211Sjp161948 27776847Svk199839 #ifndef OPENSSL_NO_DSA 27780Sstevel@tonic-gate /* 27790Sstevel@tonic-gate * Check if this slot is capable of signing and 27800Sstevel@tonic-gate * verifying with CKM_DSA. 27810Sstevel@tonic-gate */ 27820Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA, 27830Sstevel@tonic-gate &mech_info); 27840Sstevel@tonic-gate if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && 27850Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY))) 2786*7211Sjp161948 { 27870Sstevel@tonic-gate slot_has_dsa = CK_TRUE; 2788*7211Sjp161948 } 2789*7211Sjp161948 #endif /* OPENSSL_NO_DSA */ 2790*7211Sjp161948 27916847Svk199839 #ifndef OPENSSL_NO_DH 27920Sstevel@tonic-gate /* 27930Sstevel@tonic-gate * Check if this slot is capable of DH key generataion and 27940Sstevel@tonic-gate * derivation. 27950Sstevel@tonic-gate */ 27960Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, 27970Sstevel@tonic-gate CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info); 27980Sstevel@tonic-gate 27990Sstevel@tonic-gate if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR)) 28000Sstevel@tonic-gate { 28010Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, 28020Sstevel@tonic-gate CKM_DH_PKCS_DERIVE, &mech_info); 28030Sstevel@tonic-gate if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE)) 2804*7211Sjp161948 { 28050Sstevel@tonic-gate slot_has_dh = CK_TRUE; 2806*7211Sjp161948 } 28070Sstevel@tonic-gate } 2808*7211Sjp161948 #endif /* OPENSSL_NO_DH */ 2809*7211Sjp161948 28100Sstevel@tonic-gate if (!found_candidate_slot && 28110Sstevel@tonic-gate (slot_has_rsa || slot_has_dsa || slot_has_dh)) 28120Sstevel@tonic-gate { 2813*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 28140Sstevel@tonic-gate fprintf(stderr, 2815*7211Sjp161948 "%s: potential slot: %d\n", PK11_DBG, current_slot); 2816*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 28170Sstevel@tonic-gate best_slot_sofar = current_slot; 28180Sstevel@tonic-gate pk11_have_rsa = slot_has_rsa; 28190Sstevel@tonic-gate pk11_have_dsa = slot_has_dsa; 28200Sstevel@tonic-gate pk11_have_dh = slot_has_dh; 28210Sstevel@tonic-gate found_candidate_slot = CK_TRUE; 2822*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2823*7211Sjp161948 fprintf(stderr, 2824*7211Sjp161948 "%s: setting found_candidate_slot to CK_TRUE\n", 2825*7211Sjp161948 PK11_DBG); 28260Sstevel@tonic-gate fprintf(stderr, 2827*7211Sjp161948 "%s: best so far slot: %d\n", PK11_DBG, 28280Sstevel@tonic-gate best_slot_sofar); 2829*7211Sjp161948 } 2830*7211Sjp161948 else 2831*7211Sjp161948 { 2832*7211Sjp161948 fprintf(stderr, 2833*7211Sjp161948 "%s: no rsa/dsa/dh\n", PK11_DBG); 28340Sstevel@tonic-gate } 2835*7211Sjp161948 #else 2836*7211Sjp161948 } /* if */ 2837*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 2838*7211Sjp161948 } /* for */ 2839*7211Sjp161948 2840*7211Sjp161948 if (found_candidate_slot) 2841*7211Sjp161948 { 2842*7211Sjp161948 pubkey_SLOTID = best_slot_sofar; 2843*7211Sjp161948 } 2844*7211Sjp161948 2845*7211Sjp161948 found_candidate_slot = CK_FALSE; 2846*7211Sjp161948 best_slot_sofar = 0; 2847*7211Sjp161948 2848*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2849*7211Sjp161948 fprintf(stderr, "%s: == checking cipher/digest ==\n", PK11_DBG); 2850*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 2851*7211Sjp161948 for (i = 0; i < ulSlotCount; i++) 2852*7211Sjp161948 { 2853*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2854*7211Sjp161948 fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); 2855*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 2856*7211Sjp161948 2857*7211Sjp161948 current_slot = pSlotList[i]; 2858*7211Sjp161948 current_slot_n_cipher = 0; 2859*7211Sjp161948 current_slot_n_digest = 0; 2860*7211Sjp161948 memset(local_cipher_nids, 0, sizeof(local_cipher_nids)); 2861*7211Sjp161948 memset(local_digest_nids, 0, sizeof(local_digest_nids)); 2862*7211Sjp161948 2863*7211Sjp161948 pk11_find_symmetric_ciphers(pFuncList, current_slot, 2864*7211Sjp161948 ¤t_slot_n_cipher, local_cipher_nids); 2865*7211Sjp161948 2866*7211Sjp161948 pk11_find_digests(pFuncList, current_slot, 2867*7211Sjp161948 ¤t_slot_n_digest, local_digest_nids); 2868*7211Sjp161948 2869*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2870*7211Sjp161948 fprintf(stderr, "%s: current_slot_n_cipher %d\n", PK11_DBG, 2871*7211Sjp161948 current_slot_n_cipher); 2872*7211Sjp161948 fprintf(stderr, "%s: current_slot_n_digest %d\n", PK11_DBG, 2873*7211Sjp161948 current_slot_n_digest); 2874*7211Sjp161948 fprintf(stderr, "%s: best so far cipher/digest slot: %d\n", 2875*7211Sjp161948 PK11_DBG, best_slot_sofar); 2876*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 28770Sstevel@tonic-gate 28780Sstevel@tonic-gate /* 28790Sstevel@tonic-gate * If the current slot supports more ciphers/digests than 28800Sstevel@tonic-gate * the previous best one we change the current best to this one. 28810Sstevel@tonic-gate * otherwise leave it where it is. 28820Sstevel@tonic-gate */ 2883*7211Sjp161948 if ((current_slot_n_cipher > slot_n_cipher) || 2884*7211Sjp161948 (current_slot_n_digest > slot_n_digest)) 28850Sstevel@tonic-gate { 2886*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2887*7211Sjp161948 fprintf(stderr, 2888*7211Sjp161948 "%s: changing best so far slot to %d\n", 2889*7211Sjp161948 PK11_DBG, current_slot); 2890*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 2891*7211Sjp161948 best_slot_sofar = SLOTID = current_slot; 28920Sstevel@tonic-gate slot_n_cipher = current_slot_n_cipher; 28930Sstevel@tonic-gate slot_n_digest = current_slot_n_digest; 28940Sstevel@tonic-gate 28950Sstevel@tonic-gate } 28960Sstevel@tonic-gate } 28970Sstevel@tonic-gate 2898*7211Sjp161948 if (slot_n_cipher > 0) 28990Sstevel@tonic-gate { 29000Sstevel@tonic-gate cipher_count = slot_n_cipher; 2901*7211Sjp161948 memcpy(cipher_nids, local_cipher_nids, 2902*7211Sjp161948 sizeof(local_cipher_nids)); 29030Sstevel@tonic-gate } 2904*7211Sjp161948 if (slot_n_digest > 0) 29050Sstevel@tonic-gate { 2906*7211Sjp161948 digest_count = slot_n_digest; 2907*7211Sjp161948 memcpy(digest_nids, local_digest_nids, 2908*7211Sjp161948 sizeof(local_digest_nids)); 29090Sstevel@tonic-gate } 29100Sstevel@tonic-gate 2911*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2912*7211Sjp161948 fprintf(stderr, 2913*7211Sjp161948 "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID); 29140Sstevel@tonic-gate fprintf(stderr, 2915*7211Sjp161948 "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID); 29160Sstevel@tonic-gate fprintf(stderr, 2917*7211Sjp161948 "%s: chosen cipher/digest slot: %d\n", PK11_DBG, SLOTID); 2918*7211Sjp161948 fprintf(stderr, 2919*7211Sjp161948 "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa); 29200Sstevel@tonic-gate fprintf(stderr, 2921*7211Sjp161948 "%s: pk11_have_dsa %d\n", PK11_DBG, pk11_have_dsa); 2922*7211Sjp161948 fprintf(stderr, 2923*7211Sjp161948 "%s: pk11_have_dh %d\n", PK11_DBG, pk11_have_dh); 29240Sstevel@tonic-gate fprintf(stderr, 2925*7211Sjp161948 "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random); 29260Sstevel@tonic-gate fprintf(stderr, 2927*7211Sjp161948 "%s: cipher_count %d\n", PK11_DBG, cipher_count); 2928*7211Sjp161948 fprintf(stderr, 2929*7211Sjp161948 "%s: digest_count %d\n", PK11_DBG, digest_count); 2930*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 29310Sstevel@tonic-gate 29326847Svk199839 if (pSlotList != NULL) 29336847Svk199839 OPENSSL_free(pSlotList); 29340Sstevel@tonic-gate 2935*7211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 2936*7211Sjp161948 OPENSSL_free(hw_cnids); 2937*7211Sjp161948 OPENSSL_free(hw_dnids); 2938*7211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 2939*7211Sjp161948 2940*7211Sjp161948 if (any_slot_found != NULL) 2941*7211Sjp161948 *any_slot_found = 1; 2942*7211Sjp161948 return 1; 29430Sstevel@tonic-gate } 29440Sstevel@tonic-gate 2945*7211Sjp161948 static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR pflist, 2946*7211Sjp161948 int slot_id, CK_MECHANISM_TYPE mech, int *current_slot_n_cipher, 2947*7211Sjp161948 int *local_cipher_nids, int id) 2948*7211Sjp161948 { 2949*7211Sjp161948 CK_MECHANISM_INFO mech_info; 2950*7211Sjp161948 CK_RV rv; 2951*7211Sjp161948 2952*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2953*7211Sjp161948 fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech); 2954*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 2955*7211Sjp161948 rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info); 2956*7211Sjp161948 2957*7211Sjp161948 if (rv != CKR_OK) 2958*7211Sjp161948 { 2959*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2960*7211Sjp161948 fprintf(stderr, " not found\n"); 2961*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 2962*7211Sjp161948 return; 2963*7211Sjp161948 } 2964*7211Sjp161948 2965*7211Sjp161948 if ((mech_info.flags & CKF_ENCRYPT) && 2966*7211Sjp161948 (mech_info.flags & CKF_DECRYPT)) 2967*7211Sjp161948 { 2968*7211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 2969*7211Sjp161948 if (nid_in_table(ciphers[id].nid, hw_cnids)) 2970*7211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 2971*7211Sjp161948 { 2972*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2973*7211Sjp161948 fprintf(stderr, " usable\n"); 2974*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 2975*7211Sjp161948 local_cipher_nids[(*current_slot_n_cipher)++] = 2976*7211Sjp161948 ciphers[id].nid; 2977*7211Sjp161948 } 2978*7211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 2979*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2980*7211Sjp161948 else 2981*7211Sjp161948 { 2982*7211Sjp161948 fprintf(stderr, " rejected, software implementation only\n"); 2983*7211Sjp161948 } 2984*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 2985*7211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 2986*7211Sjp161948 } 2987*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 2988*7211Sjp161948 else 2989*7211Sjp161948 { 2990*7211Sjp161948 fprintf(stderr, " unusable\n"); 2991*7211Sjp161948 } 2992*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 2993*7211Sjp161948 2994*7211Sjp161948 return; 2995*7211Sjp161948 } 2996*7211Sjp161948 2997*7211Sjp161948 static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id, 2998*7211Sjp161948 CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids, 2999*7211Sjp161948 int id) 30000Sstevel@tonic-gate { 30010Sstevel@tonic-gate CK_MECHANISM_INFO mech_info; 30020Sstevel@tonic-gate CK_RV rv; 30030Sstevel@tonic-gate 3004*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 3005*7211Sjp161948 fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech); 3006*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 3007*7211Sjp161948 rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info); 30080Sstevel@tonic-gate 30090Sstevel@tonic-gate if (rv != CKR_OK) 30100Sstevel@tonic-gate { 3011*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 3012*7211Sjp161948 fprintf(stderr, " not found\n"); 3013*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 3014*7211Sjp161948 return; 30150Sstevel@tonic-gate } 30160Sstevel@tonic-gate 30170Sstevel@tonic-gate if (mech_info.flags & CKF_DIGEST) 30180Sstevel@tonic-gate { 3019*7211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 3020*7211Sjp161948 if (nid_in_table(digests[id].nid, hw_dnids)) 3021*7211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 3022*7211Sjp161948 { 3023*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 3024*7211Sjp161948 fprintf(stderr, " usable\n"); 3025*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 3026*7211Sjp161948 local_digest_nids[(*current_slot_n_digest)++] = 3027*7211Sjp161948 digests[id].nid; 3028*7211Sjp161948 } 3029*7211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 3030*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 3031*7211Sjp161948 else 3032*7211Sjp161948 { 3033*7211Sjp161948 fprintf(stderr, " rejected, software implementation only\n"); 3034*7211Sjp161948 } 3035*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 3036*7211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 3037*7211Sjp161948 } 3038*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 3039*7211Sjp161948 else 3040*7211Sjp161948 { 3041*7211Sjp161948 fprintf(stderr, " unusable\n"); 30420Sstevel@tonic-gate } 3043*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 3044*7211Sjp161948 3045*7211Sjp161948 return; 3046*7211Sjp161948 } 3047*7211Sjp161948 3048*7211Sjp161948 #ifdef SOLARIS_AES_CTR 3049*7211Sjp161948 /* create a new NID when we have no OID for that mechanism */ 3050*7211Sjp161948 static int pk11_add_NID(char *sn, char *ln) 3051*7211Sjp161948 { 3052*7211Sjp161948 ASN1_OBJECT *o; 3053*7211Sjp161948 int nid; 3054*7211Sjp161948 3055*7211Sjp161948 if ((o = ASN1_OBJECT_create(OBJ_new_nid(1), (unsigned char *)"", 3056*7211Sjp161948 1, sn, ln)) == NULL) 3057*7211Sjp161948 { 3058*7211Sjp161948 return 0; 3059*7211Sjp161948 } 3060*7211Sjp161948 3061*7211Sjp161948 /* will return NID_undef on error */ 3062*7211Sjp161948 nid = OBJ_add_object(o); 3063*7211Sjp161948 ASN1_OBJECT_free(o); 3064*7211Sjp161948 3065*7211Sjp161948 return (nid); 3066*7211Sjp161948 } 3067*7211Sjp161948 3068*7211Sjp161948 /* 3069*7211Sjp161948 * Create new NIDs for AES counter mode. OpenSSL doesn't support them now so we 3070*7211Sjp161948 * have to help ourselves here. 3071*7211Sjp161948 */ 3072*7211Sjp161948 static int pk11_add_aes_ctr_NIDs(void) 3073*7211Sjp161948 { 3074*7211Sjp161948 /* are we already set? */ 3075*7211Sjp161948 if (NID_aes_256_ctr != NID_undef) 3076*7211Sjp161948 return 1; 3077*7211Sjp161948 3078*7211Sjp161948 /* 3079*7211Sjp161948 * There are no official names for AES counter modes yet so we just 3080*7211Sjp161948 * follow the format of those that exist. 3081*7211Sjp161948 */ 3082*7211Sjp161948 if ((NID_aes_128_ctr = pk11_add_NID("AES-128-CTR", "aes-128-ctr")) == 3083*7211Sjp161948 NID_undef) 3084*7211Sjp161948 goto err; 3085*7211Sjp161948 ciphers[PK11_AES_128_CTR].nid = pk11_aes_128_ctr.nid = NID_aes_128_ctr; 3086*7211Sjp161948 if ((NID_aes_192_ctr = pk11_add_NID("AES-192-CTR", "aes-192-ctr")) == 3087*7211Sjp161948 NID_undef) 3088*7211Sjp161948 goto err; 3089*7211Sjp161948 ciphers[PK11_AES_192_CTR].nid = pk11_aes_192_ctr.nid = NID_aes_192_ctr; 3090*7211Sjp161948 if ((NID_aes_256_ctr = pk11_add_NID("AES-256-CTR", "aes-256-ctr")) == 3091*7211Sjp161948 NID_undef) 3092*7211Sjp161948 goto err; 3093*7211Sjp161948 ciphers[PK11_AES_256_CTR].nid = pk11_aes_256_ctr.nid = NID_aes_256_ctr; 30940Sstevel@tonic-gate return 1; 3095*7211Sjp161948 3096*7211Sjp161948 err: 3097*7211Sjp161948 PK11err(PK11_F_ADD_AES_CTR_NIDS, PK11_R_ADD_NID_FAILED); 3098*7211Sjp161948 return 0; 30990Sstevel@tonic-gate } 3100*7211Sjp161948 #endif /* SOLARIS_AES_CTR */ 3101*7211Sjp161948 3102*7211Sjp161948 /* Find what symmetric ciphers this slot supports. */ 3103*7211Sjp161948 static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist, 3104*7211Sjp161948 CK_SLOT_ID current_slot, int *current_slot_n_cipher, int *local_cipher_nids) 3105*7211Sjp161948 { 3106*7211Sjp161948 int i; 3107*7211Sjp161948 3108*7211Sjp161948 for (i = 0; i < PK11_CIPHER_MAX; ++i) 3109*7211Sjp161948 { 3110*7211Sjp161948 pk11_get_symmetric_cipher(pflist, current_slot, 3111*7211Sjp161948 ciphers[i].mech_type, current_slot_n_cipher, 3112*7211Sjp161948 local_cipher_nids, ciphers[i].id); 3113*7211Sjp161948 } 3114*7211Sjp161948 } 3115*7211Sjp161948 3116*7211Sjp161948 /* Find what digest algorithms this slot supports. */ 3117*7211Sjp161948 static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist, 3118*7211Sjp161948 CK_SLOT_ID current_slot, int *current_slot_n_digest, int *local_digest_nids) 3119*7211Sjp161948 { 3120*7211Sjp161948 int i; 3121*7211Sjp161948 3122*7211Sjp161948 for (i = 0; i < PK11_DIGEST_MAX; ++i) 3123*7211Sjp161948 { 3124*7211Sjp161948 pk11_get_digest(pflist, current_slot, digests[i].mech_type, 3125*7211Sjp161948 current_slot_n_digest, local_digest_nids, digests[i].id); 3126*7211Sjp161948 } 3127*7211Sjp161948 } 3128*7211Sjp161948 3129*7211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 3130*7211Sjp161948 /* 3131*7211Sjp161948 * It would be great if we could use pkcs11_kernel directly since this library 3132*7211Sjp161948 * offers hardware slots only. That's the easiest way to achieve the situation 3133*7211Sjp161948 * where we use the hardware accelerators when present and OpenSSL native code 3134*7211Sjp161948 * otherwise. That presumes the fact that OpenSSL native code is faster than the 3135*7211Sjp161948 * code in the soft token. It's a logical assumption - Crypto Framework has some 3136*7211Sjp161948 * inherent overhead so going there for the software implementation of a 3137*7211Sjp161948 * mechanism should be logically slower in contrast to the OpenSSL native code, 3138*7211Sjp161948 * presuming that both implementations are of similar speed. For example, the 3139*7211Sjp161948 * soft token for AES is roughly three times slower than OpenSSL for 64 byte 3140*7211Sjp161948 * blocks and still 20% slower for 8KB blocks. So, if we want to ship products 3141*7211Sjp161948 * that use the PKCS#11 engine by default, we must somehow avoid that regression 3142*7211Sjp161948 * on machines without hardware acceleration. That's why switching to the 3143*7211Sjp161948 * pkcs11_kernel library seems like a very good idea. 3144*7211Sjp161948 * 3145*7211Sjp161948 * The problem is that OpenSSL built with SunStudio is roughly 2x slower for 3146*7211Sjp161948 * asymmetric operations (RSA/DSA/DH) than the soft token built with the same 3147*7211Sjp161948 * compiler. That means that if we switched to pkcs11_kernel from the libpkcs11 3148*7211Sjp161948 * library, we would have had a performance regression on machines without 3149*7211Sjp161948 * hardware acceleration for asymmetric operations for all applications that use 3150*7211Sjp161948 * the PKCS#11 engine. There is one such application - Apache web server since 3151*7211Sjp161948 * it's shipped configured to use the PKCS#11 engine by default. Having said 3152*7211Sjp161948 * that, we can't switch to the pkcs11_kernel library now and have to come with 3153*7211Sjp161948 * a solution that, on non-accelerated machines, uses the OpenSSL native code 3154*7211Sjp161948 * for all symmetric ciphers and digests while it uses the soft token for 3155*7211Sjp161948 * asymmetric operations. 3156*7211Sjp161948 * 3157*7211Sjp161948 * This is the idea: dlopen() pkcs11_kernel directly and find out what 3158*7211Sjp161948 * mechanisms are there. We don't care about duplications (more slots can 3159*7211Sjp161948 * support the same mechanism), we just want to know what mechanisms can be 3160*7211Sjp161948 * possibly supported in hardware on that particular machine. As said before, 3161*7211Sjp161948 * pkcs11_kernel will show you hardware providers only. 3162*7211Sjp161948 * 3163*7211Sjp161948 * Then, we rely on the fact that since we use libpkcs11 library we will find 3164*7211Sjp161948 * the metaslot. When we go through the metaslot's mechanisms for symmetric 3165*7211Sjp161948 * ciphers and digests, we check that any found mechanism is in the table 3166*7211Sjp161948 * created using the pkcs11_kernel library. So, as a result we have two arrays 3167*7211Sjp161948 * of mechanisms that were advertised as supported in hardware which was the 3168*7211Sjp161948 * goal of that whole excercise. Thus, we can use libpkcs11 but avoid soft token 3169*7211Sjp161948 * code for symmetric ciphers and digests. See pk11_choose_slots() for more 3170*7211Sjp161948 * information. 3171*7211Sjp161948 * 3172*7211Sjp161948 * This is Solaris specific code, if SOLARIS_HW_SLOT_SELECTION is not defined 3173*7211Sjp161948 * the code won't be used. 3174*7211Sjp161948 */ 3175*7211Sjp161948 #if defined(__sparcv9) || defined(__x86_64) || defined(__amd64) 3176*7211Sjp161948 static const char pkcs11_kernel[] = "/usr/lib/security/64/pkcs11_kernel.so.1"; 3177*7211Sjp161948 #else 3178*7211Sjp161948 static const char pkcs11_kernel[] = "/usr/lib/security/pkcs11_kernel.so.1"; 3179*7211Sjp161948 #endif 3180*7211Sjp161948 3181*7211Sjp161948 /* 3182*7211Sjp161948 * Check hardware capabilities of the machines. The output are two lists, 3183*7211Sjp161948 * hw_cnids and hw_dnids, that contain hardware mechanisms found in all hardware 3184*7211Sjp161948 * providers together. They are not sorted and may contain duplicate mechanisms. 3185*7211Sjp161948 */ 3186*7211Sjp161948 static int check_hw_mechanisms(void) 3187*7211Sjp161948 { 3188*7211Sjp161948 int i; 3189*7211Sjp161948 CK_RV rv; 3190*7211Sjp161948 void *handle; 3191*7211Sjp161948 CK_C_GetFunctionList p; 3192*7211Sjp161948 CK_TOKEN_INFO token_info; 3193*7211Sjp161948 CK_ULONG ulSlotCount = 0; 3194*7211Sjp161948 int n_cipher = 0, n_digest = 0; 3195*7211Sjp161948 CK_FUNCTION_LIST_PTR pflist = NULL; 3196*7211Sjp161948 CK_SLOT_ID_PTR pSlotList = NULL_PTR; 3197*7211Sjp161948 int *tmp_hw_cnids, *tmp_hw_dnids; 3198*7211Sjp161948 int hw_ctable_size, hw_dtable_size; 3199*7211Sjp161948 3200*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 3201*7211Sjp161948 fprintf(stderr, "%s: SOLARIS_HW_SLOT_SELECTION code running\n", 3202*7211Sjp161948 PK11_DBG); 32030Sstevel@tonic-gate #endif 3204*7211Sjp161948 if ((handle = dlopen(pkcs11_kernel, RTLD_LAZY)) == NULL) 3205*7211Sjp161948 { 3206*7211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); 3207*7211Sjp161948 goto err; 3208*7211Sjp161948 } 3209*7211Sjp161948 3210*7211Sjp161948 if ((p = (CK_C_GetFunctionList)dlsym(handle, 3211*7211Sjp161948 PK11_GET_FUNCTION_LIST)) == NULL) 3212*7211Sjp161948 { 3213*7211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); 3214*7211Sjp161948 goto err; 3215*7211Sjp161948 } 3216*7211Sjp161948 3217*7211Sjp161948 /* get the full function list from the loaded library 3218*7211Sjp161948 */ 3219*7211Sjp161948 if (p(&pflist) != CKR_OK) 3220*7211Sjp161948 { 3221*7211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); 3222*7211Sjp161948 goto err; 3223*7211Sjp161948 } 3224*7211Sjp161948 3225*7211Sjp161948 rv = pflist->C_Initialize(NULL_PTR); 3226*7211Sjp161948 if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) 3227*7211Sjp161948 { 3228*7211Sjp161948 PK11err_add_data(PK11_F_CHECK_HW_MECHANISMS, 3229*7211Sjp161948 PK11_R_INITIALIZE, rv); 3230*7211Sjp161948 goto err; 3231*7211Sjp161948 } 3232*7211Sjp161948 3233*7211Sjp161948 if (pflist->C_GetSlotList(0, NULL_PTR, &ulSlotCount) != CKR_OK) 3234*7211Sjp161948 { 3235*7211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); 3236*7211Sjp161948 goto err; 3237*7211Sjp161948 } 3238*7211Sjp161948 3239*7211Sjp161948 /* no slots, set the hw mechanism tables as empty */ 3240*7211Sjp161948 if (ulSlotCount == 0) 3241*7211Sjp161948 { 3242*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 3243*7211Sjp161948 fprintf(stderr, "%s: no hardware mechanisms found\n", PK11_DBG); 32440Sstevel@tonic-gate #endif 3245*7211Sjp161948 hw_cnids = OPENSSL_malloc(sizeof (int)); 3246*7211Sjp161948 hw_dnids = OPENSSL_malloc(sizeof (int)); 3247*7211Sjp161948 if (hw_cnids == NULL || hw_dnids == NULL) 3248*7211Sjp161948 { 3249*7211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, 3250*7211Sjp161948 PK11_R_MALLOC_FAILURE); 3251*7211Sjp161948 return (0); 3252*7211Sjp161948 } 3253*7211Sjp161948 /* this means empty tables */ 3254*7211Sjp161948 hw_cnids[0] = NID_undef; 3255*7211Sjp161948 hw_dnids[0] = NID_undef; 3256*7211Sjp161948 return (1); 3257*7211Sjp161948 } 3258*7211Sjp161948 3259*7211Sjp161948 pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); 3260*7211Sjp161948 if (pSlotList == NULL) 3261*7211Sjp161948 { 3262*7211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); 3263*7211Sjp161948 goto err; 3264*7211Sjp161948 } 3265*7211Sjp161948 3266*7211Sjp161948 /* Get the slot list for processing */ 3267*7211Sjp161948 if (pflist->C_GetSlotList(0, pSlotList, &ulSlotCount) != CKR_OK) 3268*7211Sjp161948 { 3269*7211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); 3270*7211Sjp161948 goto err; 3271*7211Sjp161948 } 3272*7211Sjp161948 3273*7211Sjp161948 /* 3274*7211Sjp161948 * We don't care about duplicit mechanisms in multiple slots and also 3275*7211Sjp161948 * reserve one slot for the terminal NID_undef which we use to stop the 3276*7211Sjp161948 * search. 3277*7211Sjp161948 */ 3278*7211Sjp161948 hw_ctable_size = ulSlotCount * PK11_CIPHER_MAX + 1; 3279*7211Sjp161948 hw_dtable_size = ulSlotCount * PK11_DIGEST_MAX + 1; 3280*7211Sjp161948 tmp_hw_cnids = OPENSSL_malloc(hw_ctable_size * sizeof (int)); 3281*7211Sjp161948 tmp_hw_dnids = OPENSSL_malloc(hw_dtable_size * sizeof (int)); 3282*7211Sjp161948 if (tmp_hw_cnids == NULL || tmp_hw_dnids == NULL) 3283*7211Sjp161948 { 3284*7211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); 3285*7211Sjp161948 goto err; 3286*7211Sjp161948 } 3287*7211Sjp161948 3288*7211Sjp161948 /* 3289*7211Sjp161948 * Do not use memset since we should not rely on the fact that NID_undef 3290*7211Sjp161948 * is zero now. 3291*7211Sjp161948 */ 3292*7211Sjp161948 for (i = 0; i < hw_ctable_size; ++i) 3293*7211Sjp161948 tmp_hw_cnids[i] = NID_undef; 3294*7211Sjp161948 for (i = 0; i < hw_dtable_size; ++i) 3295*7211Sjp161948 tmp_hw_dnids[i] = NID_undef; 3296*7211Sjp161948 3297*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 3298*7211Sjp161948 fprintf(stderr, "%s: provider: %s\n", PK11_DBG, pkcs11_kernel); 3299*7211Sjp161948 fprintf(stderr, "%s: found %d hardware slots\n", PK11_DBG, ulSlotCount); 3300*7211Sjp161948 fprintf(stderr, "%s: now looking for mechs supported in hw\n", 3301*7211Sjp161948 PK11_DBG); 3302*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 3303*7211Sjp161948 3304*7211Sjp161948 for (i = 0; i < ulSlotCount; i++) 3305*7211Sjp161948 { 3306*7211Sjp161948 if (pflist->C_GetTokenInfo(pSlotList[i], &token_info) != CKR_OK) 3307*7211Sjp161948 continue; 3308*7211Sjp161948 3309*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 3310*7211Sjp161948 fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); 3311*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 3312*7211Sjp161948 3313*7211Sjp161948 /* 3314*7211Sjp161948 * We are filling the hw mech tables here. Global tables are 3315*7211Sjp161948 * still NULL so all mechanisms are put into tmp tables. 3316*7211Sjp161948 */ 3317*7211Sjp161948 pk11_find_symmetric_ciphers(pflist, pSlotList[i], 3318*7211Sjp161948 &n_cipher, tmp_hw_cnids); 3319*7211Sjp161948 pk11_find_digests(pflist, pSlotList[i], 3320*7211Sjp161948 &n_digest, tmp_hw_dnids); 3321*7211Sjp161948 } 3322*7211Sjp161948 3323*7211Sjp161948 /* 3324*7211Sjp161948 * Since we are part of a library (libcrypto.so), calling this function 3325*7211Sjp161948 * may have side-effects. Also, C_Finalize() is triggered by 3326*7211Sjp161948 * dlclose(3C). 3327*7211Sjp161948 */ 3328*7211Sjp161948 #if 0 3329*7211Sjp161948 pflist->C_Finalize(NULL); 3330*7211Sjp161948 #endif 3331*7211Sjp161948 OPENSSL_free(pSlotList); 3332*7211Sjp161948 dlclose(handle); 3333*7211Sjp161948 hw_cnids = tmp_hw_cnids; 3334*7211Sjp161948 hw_dnids = tmp_hw_dnids; 3335*7211Sjp161948 3336*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 3337*7211Sjp161948 fprintf(stderr, "%s: hw mechs check complete\n", PK11_DBG); 3338*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 3339*7211Sjp161948 return (1); 3340*7211Sjp161948 3341*7211Sjp161948 err: 3342*7211Sjp161948 if (pSlotList != NULL) 3343*7211Sjp161948 OPENSSL_free(pSlotList); 3344*7211Sjp161948 if (tmp_hw_cnids != NULL) 3345*7211Sjp161948 OPENSSL_free(tmp_hw_cnids); 3346*7211Sjp161948 if (tmp_hw_dnids != NULL) 3347*7211Sjp161948 OPENSSL_free(tmp_hw_dnids); 3348*7211Sjp161948 3349*7211Sjp161948 return (0); 3350*7211Sjp161948 } 3351*7211Sjp161948 3352*7211Sjp161948 /* 3353*7211Sjp161948 * Check presence of a NID in the table of NIDs. The table may be NULL (i.e., 3354*7211Sjp161948 * non-existent). 3355*7211Sjp161948 */ 3356*7211Sjp161948 static int nid_in_table(int nid, int *nid_table) 3357*7211Sjp161948 { 3358*7211Sjp161948 int i = 0; 3359*7211Sjp161948 3360*7211Sjp161948 /* 3361*7211Sjp161948 * a special case. NULL means that we are initializing a new 3362*7211Sjp161948 * table. 3363*7211Sjp161948 */ 3364*7211Sjp161948 if (nid_table == NULL) 3365*7211Sjp161948 return (1); 3366*7211Sjp161948 3367*7211Sjp161948 /* 3368*7211Sjp161948 * the table is never full, there is always at least one 3369*7211Sjp161948 * NID_undef. 3370*7211Sjp161948 */ 3371*7211Sjp161948 while (nid_table[i] != NID_undef) 3372*7211Sjp161948 { 3373*7211Sjp161948 if (nid_table[i++] == nid) 3374*7211Sjp161948 { 3375*7211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 3376*7211Sjp161948 fprintf(stderr, " (NID %d in hw table, idx %d)", nid, i); 3377*7211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 3378*7211Sjp161948 return (1); 3379*7211Sjp161948 } 3380*7211Sjp161948 } 3381*7211Sjp161948 3382*7211Sjp161948 return (0); 3383*7211Sjp161948 } 3384*7211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 3385*7211Sjp161948 3386*7211Sjp161948 #endif /* OPENSSL_NO_HW_PK11 */ 3387*7211Sjp161948 #endif /* OPENSSL_NO_HW */ 3388