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 /* crypto/engine/hw_pk11.c */ 70Sstevel@tonic-gate /* This product includes software developed by the OpenSSL Project for 80Sstevel@tonic-gate * use in the OpenSSL Toolkit (http://www.openssl.org/). 90Sstevel@tonic-gate * 100Sstevel@tonic-gate * This project also referenced hw_pkcs11-0.9.7b.patch written by 110Sstevel@tonic-gate * Afchine Madjlessi. 120Sstevel@tonic-gate */ 130Sstevel@tonic-gate /* ==================================================================== 140Sstevel@tonic-gate * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. 150Sstevel@tonic-gate * 160Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 170Sstevel@tonic-gate * modification, are permitted provided that the following conditions 180Sstevel@tonic-gate * are met: 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 210Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 220Sstevel@tonic-gate * 230Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 240Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in 250Sstevel@tonic-gate * the documentation and/or other materials provided with the 260Sstevel@tonic-gate * distribution. 270Sstevel@tonic-gate * 280Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this 290Sstevel@tonic-gate * software must display the following acknowledgment: 300Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project 310Sstevel@tonic-gate * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 320Sstevel@tonic-gate * 330Sstevel@tonic-gate * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 340Sstevel@tonic-gate * endorse or promote products derived from this software without 350Sstevel@tonic-gate * prior written permission. For written permission, please contact 360Sstevel@tonic-gate * licensing@OpenSSL.org. 370Sstevel@tonic-gate * 380Sstevel@tonic-gate * 5. Products derived from this software may not be called "OpenSSL" 390Sstevel@tonic-gate * nor may "OpenSSL" appear in their names without prior written 400Sstevel@tonic-gate * permission of the OpenSSL Project. 410Sstevel@tonic-gate * 420Sstevel@tonic-gate * 6. Redistributions of any form whatsoever must retain the following 430Sstevel@tonic-gate * acknowledgment: 440Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project 450Sstevel@tonic-gate * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 460Sstevel@tonic-gate * 470Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 480Sstevel@tonic-gate * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 490Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 500Sstevel@tonic-gate * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 510Sstevel@tonic-gate * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 520Sstevel@tonic-gate * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 530Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 540Sstevel@tonic-gate * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 550Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 560Sstevel@tonic-gate * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 570Sstevel@tonic-gate * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 580Sstevel@tonic-gate * OF THE POSSIBILITY OF SUCH DAMAGE. 590Sstevel@tonic-gate * ==================================================================== 600Sstevel@tonic-gate * 610Sstevel@tonic-gate * This product includes cryptographic software written by Eric Young 620Sstevel@tonic-gate * (eay@cryptsoft.com). This product includes software written by Tim 630Sstevel@tonic-gate * Hudson (tjh@cryptsoft.com). 640Sstevel@tonic-gate * 650Sstevel@tonic-gate */ 660Sstevel@tonic-gate 670Sstevel@tonic-gate #include <stdio.h> 680Sstevel@tonic-gate #include <stdlib.h> 690Sstevel@tonic-gate #include <string.h> 700Sstevel@tonic-gate #include <sys/types.h> 710Sstevel@tonic-gate #include <unistd.h> 720Sstevel@tonic-gate 730Sstevel@tonic-gate #include <openssl/e_os2.h> 746847Svk199839 #include <openssl/crypto.h> 750Sstevel@tonic-gate #include <openssl/engine.h> 760Sstevel@tonic-gate #include <openssl/dso.h> 770Sstevel@tonic-gate #include <openssl/err.h> 780Sstevel@tonic-gate #include <openssl/bn.h> 792139Sjp161948 #include <openssl/md5.h> 800Sstevel@tonic-gate #include <openssl/pem.h> 816847Svk199839 #ifndef OPENSSL_NO_RSA 820Sstevel@tonic-gate #include <openssl/rsa.h> 836847Svk199839 #endif 846847Svk199839 #ifndef OPENSSL_NO_DSA 856847Svk199839 #include <openssl/dsa.h> 866847Svk199839 #endif 876847Svk199839 #ifndef OPENSSL_NO_DH 886847Svk199839 #include <openssl/dh.h> 896847Svk199839 #endif 900Sstevel@tonic-gate #include <openssl/rand.h> 910Sstevel@tonic-gate #include <openssl/objects.h> 920Sstevel@tonic-gate #include <openssl/x509.h> 937211Sjp161948 #include <openssl/aes.h> 940Sstevel@tonic-gate #include <cryptlib.h> 957211Sjp161948 #include <dlfcn.h> 96*7526SVladimir.Kotal@Sun.COM #include <pthread.h> 970Sstevel@tonic-gate 980Sstevel@tonic-gate #ifndef OPENSSL_NO_HW 990Sstevel@tonic-gate #ifndef OPENSSL_NO_HW_PK11 1000Sstevel@tonic-gate 1017211Sjp161948 /* label for debug messages printed on stderr */ 1027211Sjp161948 #define PK11_DBG "PKCS#11 ENGINE DEBUG" 1037211Sjp161948 /* prints a lot of debug messages on stderr about slot selection process */ 1047211Sjp161948 #undef DEBUG_SLOT_SELECTION 1057211Sjp161948 /* 1067211Sjp161948 * Solaris specific code. See comment at check_hw_mechanisms() for more 1077211Sjp161948 * information. 1087211Sjp161948 */ 1097211Sjp161948 #define SOLARIS_HW_SLOT_SELECTION 1107211Sjp161948 1117211Sjp161948 /* 1127211Sjp161948 * AES counter mode is not supported in the OpenSSL EVP API yet and neither 1137211Sjp161948 * there are official OIDs for mechanisms based on this mode. With our changes, 1147211Sjp161948 * an application can define its own EVP calls for AES counter mode and then 1157211Sjp161948 * it can make use of hardware acceleration through this engine. However, it's 1167211Sjp161948 * better if we keep AES CTR support code under ifdef's. 1177211Sjp161948 */ 1187211Sjp161948 #define SOLARIS_AES_CTR 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate #include "security/cryptoki.h" 1210Sstevel@tonic-gate #include "security/pkcs11.h" 1220Sstevel@tonic-gate #include "hw_pk11_err.c" 1230Sstevel@tonic-gate 1247211Sjp161948 #ifdef SOLARIS_AES_CTR 1257211Sjp161948 /* 1267211Sjp161948 * NIDs for AES counter mode that will be defined during the engine 1277211Sjp161948 * initialization. 1287211Sjp161948 */ 1297211Sjp161948 int NID_aes_128_ctr = NID_undef; 1307211Sjp161948 int NID_aes_192_ctr = NID_undef; 1317211Sjp161948 int NID_aes_256_ctr = NID_undef; 1327211Sjp161948 #endif /* SOLARIS_AES_CTR */ 1337211Sjp161948 1347211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 1357211Sjp161948 /* 1367211Sjp161948 * Tables for symmetric ciphers and digest mechs found in the pkcs11_kernel 1377211Sjp161948 * library. See comment at check_hw_mechanisms() for more information. 1387211Sjp161948 */ 1397211Sjp161948 int *hw_cnids; 1407211Sjp161948 int *hw_dnids; 1417211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 1427211Sjp161948 143*7526SVladimir.Kotal@Sun.COM /* PKCS#11 session caches and their locks for all operation types */ 144*7526SVladimir.Kotal@Sun.COM static PK11_CACHE session_cache[OP_MAX]; 145*7526SVladimir.Kotal@Sun.COM 1467211Sjp161948 /* 147*7526SVladimir.Kotal@Sun.COM * As stated in v2.20, 11.7 Object Management Function, in section for 148*7526SVladimir.Kotal@Sun.COM * C_FindObjectsInit(), at most one search operation may be active at a given 149*7526SVladimir.Kotal@Sun.COM * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be 150*7526SVladimir.Kotal@Sun.COM * grouped together to form one atomic search operation. This is already 151*7526SVladimir.Kotal@Sun.COM * ensured by the property of unique PKCS#11 session handle used for each 152*7526SVladimir.Kotal@Sun.COM * PK11_SESSION object. 153*7526SVladimir.Kotal@Sun.COM * 154*7526SVladimir.Kotal@Sun.COM * This is however not the biggest concern - maintaining consistency of the 155*7526SVladimir.Kotal@Sun.COM * underlying object store is more important. The same section of the spec also 156*7526SVladimir.Kotal@Sun.COM * says that one thread can be in the middle of a search operation while another 157*7526SVladimir.Kotal@Sun.COM * thread destroys the object matching the search template which would result in 158*7526SVladimir.Kotal@Sun.COM * invalid handle returned from the search operation. 159*7526SVladimir.Kotal@Sun.COM * 160*7526SVladimir.Kotal@Sun.COM * Hence, the following locks are used for both protection of the object stores. 161*7526SVladimir.Kotal@Sun.COM * They are also used for active list protection. 1627211Sjp161948 */ 163*7526SVladimir.Kotal@Sun.COM pthread_mutex_t *find_lock[OP_MAX] = { NULL }; 164*7526SVladimir.Kotal@Sun.COM 165*7526SVladimir.Kotal@Sun.COM /* 166*7526SVladimir.Kotal@Sun.COM * lists of asymmetric key handles which are active (referenced by at least one 167*7526SVladimir.Kotal@Sun.COM * PK11_SESSION structure, either held by a thread or present in free_session 168*7526SVladimir.Kotal@Sun.COM * list) for given algorithm type 169*7526SVladimir.Kotal@Sun.COM */ 170*7526SVladimir.Kotal@Sun.COM PK11_active *active_list[OP_MAX] = { NULL }; 171*7526SVladimir.Kotal@Sun.COM 172*7526SVladimir.Kotal@Sun.COM /* 173*7526SVladimir.Kotal@Sun.COM * Create all secret key objects in a global session so that they are available 1740Sstevel@tonic-gate * to use for other sessions. These other sessions may be opened or closed 175*7526SVladimir.Kotal@Sun.COM * without losing the secret key objects. 176*7526SVladimir.Kotal@Sun.COM */ 1770Sstevel@tonic-gate static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE; 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate /* ENGINE level stuff */ 1800Sstevel@tonic-gate static int pk11_init(ENGINE *e); 1810Sstevel@tonic-gate static int pk11_library_init(ENGINE *e); 1820Sstevel@tonic-gate static int pk11_finish(ENGINE *e); 1830Sstevel@tonic-gate static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); 1840Sstevel@tonic-gate static int pk11_destroy(ENGINE *e); 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate /* RAND stuff */ 1870Sstevel@tonic-gate static void pk11_rand_seed(const void *buf, int num); 1880Sstevel@tonic-gate static void pk11_rand_add(const void *buf, int num, double add_entropy); 1890Sstevel@tonic-gate static void pk11_rand_cleanup(void); 1900Sstevel@tonic-gate static int pk11_rand_bytes(unsigned char *buf, int num); 1910Sstevel@tonic-gate static int pk11_rand_status(void); 1920Sstevel@tonic-gate 1930Sstevel@tonic-gate /* These functions are also used in other files */ 1947211Sjp161948 PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); 1957211Sjp161948 void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); 1966847Svk199839 197*7526SVladimir.Kotal@Sun.COM /* active list manipulation functions used in this file */ 198*7526SVladimir.Kotal@Sun.COM extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type); 199*7526SVladimir.Kotal@Sun.COM extern void pk11_free_active_list(PK11_OPTYPE type); 2006847Svk199839 2016847Svk199839 #ifndef OPENSSL_NO_RSA 2020Sstevel@tonic-gate int pk11_destroy_rsa_key_objects(PK11_SESSION *session); 2036847Svk199839 int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); 2046847Svk199839 int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); 2056847Svk199839 #endif 2066847Svk199839 #ifndef OPENSSL_NO_DSA 2070Sstevel@tonic-gate int pk11_destroy_dsa_key_objects(PK11_SESSION *session); 2086847Svk199839 int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); 2096847Svk199839 int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); 2106847Svk199839 #endif 2116847Svk199839 #ifndef OPENSSL_NO_DH 2120Sstevel@tonic-gate int pk11_destroy_dh_key_objects(PK11_SESSION *session); 2136847Svk199839 int pk11_destroy_dh_object(PK11_SESSION *session, CK_BBOOL uselock); 2146847Svk199839 #endif 2150Sstevel@tonic-gate 2160Sstevel@tonic-gate /* Local helper functions */ 2177211Sjp161948 static int pk11_free_all_sessions(void); 218*7526SVladimir.Kotal@Sun.COM static int pk11_free_session_list(PK11_OPTYPE optype); 2197211Sjp161948 static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype); 2200Sstevel@tonic-gate static int pk11_destroy_cipher_key_objects(PK11_SESSION *session); 2216847Svk199839 static int pk11_destroy_object(CK_SESSION_HANDLE session, 2220Sstevel@tonic-gate CK_OBJECT_HANDLE oh); 2230Sstevel@tonic-gate static const char *get_PK11_LIBNAME(void); 2240Sstevel@tonic-gate static void free_PK11_LIBNAME(void); 2250Sstevel@tonic-gate static long set_PK11_LIBNAME(const char *name); 2260Sstevel@tonic-gate 2270Sstevel@tonic-gate /* Symmetric cipher and digest support functions */ 2280Sstevel@tonic-gate static int cipher_nid_to_pk11(int nid); 2297211Sjp161948 #ifdef SOLARIS_AES_CTR 2307211Sjp161948 static int pk11_add_NID(char *sn, char *ln); 2317211Sjp161948 static int pk11_add_aes_ctr_NIDs(void); 2327211Sjp161948 #endif /* SOLARIS_AES_CTR */ 2330Sstevel@tonic-gate static int pk11_usable_ciphers(const int **nids); 2340Sstevel@tonic-gate static int pk11_usable_digests(const int **nids); 2350Sstevel@tonic-gate static int pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, 2360Sstevel@tonic-gate const unsigned char *iv, int enc); 2370Sstevel@tonic-gate static int pk11_cipher_final(PK11_SESSION *sp); 2380Sstevel@tonic-gate static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 2390Sstevel@tonic-gate const unsigned char *in, unsigned int inl); 2400Sstevel@tonic-gate static int pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx); 2410Sstevel@tonic-gate static int pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 2420Sstevel@tonic-gate const int **nids, int nid); 2430Sstevel@tonic-gate static int pk11_engine_digests(ENGINE *e, const EVP_MD **digest, 2440Sstevel@tonic-gate const int **nids, int nid); 2450Sstevel@tonic-gate static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, 2460Sstevel@tonic-gate const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp); 2477211Sjp161948 static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key, 2487211Sjp161948 int key_len); 2490Sstevel@tonic-gate static int md_nid_to_pk11(int nid); 2500Sstevel@tonic-gate static int pk11_digest_init(EVP_MD_CTX *ctx); 2510Sstevel@tonic-gate static int pk11_digest_update(EVP_MD_CTX *ctx,const void *data, 2522139Sjp161948 size_t count); 2530Sstevel@tonic-gate static int pk11_digest_final(EVP_MD_CTX *ctx,unsigned char *md); 2540Sstevel@tonic-gate static int pk11_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from); 2550Sstevel@tonic-gate static int pk11_digest_cleanup(EVP_MD_CTX *ctx); 2560Sstevel@tonic-gate 2577211Sjp161948 static int pk11_choose_slots(int *any_slot_found); 2587211Sjp161948 static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist, 2597211Sjp161948 CK_SLOT_ID current_slot, int *current_slot_n_cipher, 2607211Sjp161948 int *local_cipher_nids); 2617211Sjp161948 static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist, 2627211Sjp161948 CK_SLOT_ID current_slot, int *current_slot_n_digest, 2637211Sjp161948 int *local_digest_nids); 2647211Sjp161948 static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR, int slot_id, 2657211Sjp161948 CK_MECHANISM_TYPE mech, int *current_slot_n_cipher, int *local_cipher_nids, 2667211Sjp161948 int id); 2677211Sjp161948 static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id, 2687211Sjp161948 CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids, 2697211Sjp161948 int id); 2707211Sjp161948 271*7526SVladimir.Kotal@Sun.COM static int pk11_init_all_locks(void); 272*7526SVladimir.Kotal@Sun.COM static void pk11_free_all_locks(void); 273*7526SVladimir.Kotal@Sun.COM 2747211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 2757211Sjp161948 static int check_hw_mechanisms(void); 2767211Sjp161948 static int nid_in_table(int nid, int *nid_table); 2777211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate /* Index for the supported ciphers */ 2807211Sjp161948 enum pk11_cipher_id { 2817211Sjp161948 PK11_DES_CBC, 2827211Sjp161948 PK11_DES3_CBC, 2837211Sjp161948 PK11_DES_ECB, 2847211Sjp161948 PK11_DES3_ECB, 2857211Sjp161948 PK11_RC4, 2867211Sjp161948 PK11_AES_128_CBC, 2877211Sjp161948 PK11_AES_192_CBC, 2887211Sjp161948 PK11_AES_256_CBC, 2897211Sjp161948 PK11_AES_128_ECB, 2907211Sjp161948 PK11_AES_192_ECB, 2917211Sjp161948 PK11_AES_256_ECB, 2927211Sjp161948 PK11_BLOWFISH_CBC, 2937211Sjp161948 #ifdef SOLARIS_AES_CTR 2947211Sjp161948 PK11_AES_128_CTR, 2957211Sjp161948 PK11_AES_192_CTR, 2967211Sjp161948 PK11_AES_256_CTR, 2977211Sjp161948 #endif /* SOLARIS_AES_CTR */ 2987211Sjp161948 PK11_CIPHER_MAX 2997211Sjp161948 }; 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate /* Index for the supported digests */ 3027211Sjp161948 enum pk11_digest_id { 3037211Sjp161948 PK11_MD5, 3047211Sjp161948 PK11_SHA1, 3057211Sjp161948 PK11_SHA224, 3067211Sjp161948 PK11_SHA256, 3077211Sjp161948 PK11_SHA384, 3087211Sjp161948 PK11_SHA512, 3097211Sjp161948 PK11_DIGEST_MAX 3107211Sjp161948 }; 3110Sstevel@tonic-gate 312*7526SVladimir.Kotal@Sun.COM #define TRY_OBJ_DESTROY(sess_hdl, obj_hdl, retval, uselock, alg_type) \ 3136847Svk199839 { \ 3146847Svk199839 if (uselock) \ 315*7526SVladimir.Kotal@Sun.COM LOCK_OBJSTORE(alg_type); \ 316*7526SVladimir.Kotal@Sun.COM if (pk11_active_delete(obj_hdl, alg_type) == 1) \ 3176847Svk199839 { \ 3186847Svk199839 retval = pk11_destroy_object(sess_hdl, obj_hdl); \ 3196847Svk199839 } \ 3206847Svk199839 if (uselock) \ 321*7526SVladimir.Kotal@Sun.COM UNLOCK_OBJSTORE(alg_type); \ 3226847Svk199839 } 3236847Svk199839 3240Sstevel@tonic-gate static int cipher_nids[PK11_CIPHER_MAX]; 3250Sstevel@tonic-gate static int digest_nids[PK11_DIGEST_MAX]; 3260Sstevel@tonic-gate static int cipher_count = 0; 3270Sstevel@tonic-gate static int digest_count = 0; 3280Sstevel@tonic-gate static CK_BBOOL pk11_have_rsa = CK_FALSE; 3290Sstevel@tonic-gate static CK_BBOOL pk11_have_dsa = CK_FALSE; 3300Sstevel@tonic-gate static CK_BBOOL pk11_have_dh = CK_FALSE; 3310Sstevel@tonic-gate static CK_BBOOL pk11_have_random = CK_FALSE; 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate typedef struct PK11_CIPHER_st 3340Sstevel@tonic-gate { 3357211Sjp161948 enum pk11_cipher_id id; 3364320Sjp161948 int nid; 3377211Sjp161948 int iv_len; 3384320Sjp161948 int key_len; 3394320Sjp161948 CK_KEY_TYPE key_type; 3404320Sjp161948 CK_MECHANISM_TYPE mech_type; 3410Sstevel@tonic-gate } PK11_CIPHER; 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate static PK11_CIPHER ciphers[] = 3440Sstevel@tonic-gate { 3457211Sjp161948 {PK11_DES_CBC, NID_des_cbc, 8, 8, CKK_DES, CKM_DES_CBC, }, 3467211Sjp161948 {PK11_DES3_CBC, NID_des_ede3_cbc, 8, 24, CKK_DES3, CKM_DES3_CBC, }, 3477211Sjp161948 {PK11_DES_ECB, NID_des_ecb, 0, 8, CKK_DES, CKM_DES_ECB, }, 3487211Sjp161948 {PK11_DES3_ECB, NID_des_ede3_ecb, 0, 24, CKK_DES3, CKM_DES3_ECB, }, 3497211Sjp161948 {PK11_RC4, NID_rc4, 0, 16, CKK_RC4, CKM_RC4, }, 3507211Sjp161948 {PK11_AES_128_CBC, NID_aes_128_cbc, 16, 16, CKK_AES, CKM_AES_CBC, }, 3517211Sjp161948 {PK11_AES_192_CBC, NID_aes_192_cbc, 16, 24, CKK_AES, CKM_AES_CBC, }, 3527211Sjp161948 {PK11_AES_256_CBC, NID_aes_256_cbc, 16, 32, CKK_AES, CKM_AES_CBC, }, 3537211Sjp161948 {PK11_AES_128_ECB, NID_aes_128_ecb, 0, 16, CKK_AES, CKM_AES_ECB, }, 3547211Sjp161948 {PK11_AES_192_ECB, NID_aes_192_ecb, 0, 24, CKK_AES, CKM_AES_ECB, }, 3557211Sjp161948 {PK11_AES_256_ECB, NID_aes_256_ecb, 0, 32, CKK_AES, CKM_AES_ECB, }, 3567211Sjp161948 {PK11_BLOWFISH_CBC,NID_bf_cbc, 8, 16, CKK_BLOWFISH, CKM_BLOWFISH_CBC,}, 3577211Sjp161948 #ifdef SOLARIS_AES_CTR 3587211Sjp161948 /* we don't know the correct NIDs until the engine is initialized */ 3597211Sjp161948 {PK11_AES_128_CTR, NID_undef, 16, 16, CKK_AES, CKM_AES_CTR, }, 3607211Sjp161948 {PK11_AES_192_CTR, NID_undef, 16, 24, CKK_AES, CKM_AES_CTR, }, 3617211Sjp161948 {PK11_AES_256_CTR, NID_undef, 16, 32, CKK_AES, CKM_AES_CTR, }, 3627211Sjp161948 #endif /* SOLARIS_AES_CTR */ 3630Sstevel@tonic-gate }; 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate typedef struct PK11_DIGEST_st 3660Sstevel@tonic-gate { 3677211Sjp161948 enum pk11_digest_id id; 3684320Sjp161948 int nid; 3694320Sjp161948 CK_MECHANISM_TYPE mech_type; 3700Sstevel@tonic-gate } PK11_DIGEST; 3710Sstevel@tonic-gate 3720Sstevel@tonic-gate static PK11_DIGEST digests[] = 3730Sstevel@tonic-gate { 3744320Sjp161948 {PK11_MD5, NID_md5, CKM_MD5, }, 3754320Sjp161948 {PK11_SHA1, NID_sha1, CKM_SHA_1, }, 3767211Sjp161948 {PK11_SHA224, NID_sha224, CKM_SHA224, }, 3777211Sjp161948 {PK11_SHA256, NID_sha256, CKM_SHA256, }, 3787211Sjp161948 {PK11_SHA384, NID_sha384, CKM_SHA384, }, 3797211Sjp161948 {PK11_SHA512, NID_sha512, CKM_SHA512, }, 3804320Sjp161948 {0, NID_undef, 0xFFFF, }, 3810Sstevel@tonic-gate }; 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate /* Structure to be used for the cipher_data/md_data in 3840Sstevel@tonic-gate * EVP_CIPHER_CTX/EVP_MD_CTX structures in order to use the same 3850Sstevel@tonic-gate * pk11 session in multiple cipher_update calls 3860Sstevel@tonic-gate */ 3870Sstevel@tonic-gate typedef struct PK11_CIPHER_STATE_st 3880Sstevel@tonic-gate { 3890Sstevel@tonic-gate PK11_SESSION *sp; 3900Sstevel@tonic-gate } PK11_CIPHER_STATE; 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate 3937211Sjp161948 /* 3947211Sjp161948 * libcrypto EVP stuff - this is how we get wired to EVP so the engine gets 3957211Sjp161948 * called when libcrypto requests a cipher NID. 3967211Sjp161948 * 3970Sstevel@tonic-gate * Note how the PK11_CIPHER_STATE is used here. 3980Sstevel@tonic-gate */ 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate /* DES CBC EVP */ 4010Sstevel@tonic-gate static const EVP_CIPHER pk11_des_cbc = 4020Sstevel@tonic-gate { 4030Sstevel@tonic-gate NID_des_cbc, 4040Sstevel@tonic-gate 8, 8, 8, 4050Sstevel@tonic-gate EVP_CIPH_CBC_MODE, 4060Sstevel@tonic-gate pk11_cipher_init, 4070Sstevel@tonic-gate pk11_cipher_do_cipher, 4080Sstevel@tonic-gate pk11_cipher_cleanup, 4090Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 4100Sstevel@tonic-gate EVP_CIPHER_set_asn1_iv, 4110Sstevel@tonic-gate EVP_CIPHER_get_asn1_iv, 4120Sstevel@tonic-gate NULL 4130Sstevel@tonic-gate }; 4140Sstevel@tonic-gate 4150Sstevel@tonic-gate /* 3DES CBC EVP */ 4160Sstevel@tonic-gate static const EVP_CIPHER pk11_3des_cbc = 4170Sstevel@tonic-gate { 4180Sstevel@tonic-gate NID_des_ede3_cbc, 4190Sstevel@tonic-gate 8, 24, 8, 4200Sstevel@tonic-gate EVP_CIPH_CBC_MODE, 4210Sstevel@tonic-gate pk11_cipher_init, 4220Sstevel@tonic-gate pk11_cipher_do_cipher, 4230Sstevel@tonic-gate pk11_cipher_cleanup, 4240Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 4250Sstevel@tonic-gate EVP_CIPHER_set_asn1_iv, 4260Sstevel@tonic-gate EVP_CIPHER_get_asn1_iv, 4270Sstevel@tonic-gate NULL 4280Sstevel@tonic-gate }; 4290Sstevel@tonic-gate 4307211Sjp161948 /* 4317211Sjp161948 * ECB modes don't use an Initial Vector so that's why set_asn1_parameters and 4327211Sjp161948 * get_asn1_parameters fields are set to NULL. 4337211Sjp161948 */ 4347211Sjp161948 static const EVP_CIPHER pk11_des_ecb = 4357211Sjp161948 { 4367211Sjp161948 NID_des_ecb, 4377211Sjp161948 8, 8, 8, 4387211Sjp161948 EVP_CIPH_ECB_MODE, 4397211Sjp161948 pk11_cipher_init, 4407211Sjp161948 pk11_cipher_do_cipher, 4417211Sjp161948 pk11_cipher_cleanup, 4427211Sjp161948 sizeof(PK11_CIPHER_STATE), 4437211Sjp161948 NULL, 4447211Sjp161948 NULL, 4457211Sjp161948 NULL 4467211Sjp161948 }; 4477211Sjp161948 4487211Sjp161948 static const EVP_CIPHER pk11_3des_ecb = 4497211Sjp161948 { 4507211Sjp161948 NID_des_ede3_ecb, 4517211Sjp161948 8, 24, 8, 4527211Sjp161948 EVP_CIPH_ECB_MODE, 4537211Sjp161948 pk11_cipher_init, 4547211Sjp161948 pk11_cipher_do_cipher, 4557211Sjp161948 pk11_cipher_cleanup, 4567211Sjp161948 sizeof(PK11_CIPHER_STATE), 4577211Sjp161948 NULL, 4587211Sjp161948 NULL, 4597211Sjp161948 NULL 4607211Sjp161948 }; 4617211Sjp161948 4627211Sjp161948 4637211Sjp161948 static const EVP_CIPHER pk11_aes_128_cbc = 4640Sstevel@tonic-gate { 4650Sstevel@tonic-gate NID_aes_128_cbc, 4660Sstevel@tonic-gate 16, 16, 16, 4670Sstevel@tonic-gate EVP_CIPH_CBC_MODE, 4680Sstevel@tonic-gate pk11_cipher_init, 4690Sstevel@tonic-gate pk11_cipher_do_cipher, 4700Sstevel@tonic-gate pk11_cipher_cleanup, 4710Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 4720Sstevel@tonic-gate EVP_CIPHER_set_asn1_iv, 4730Sstevel@tonic-gate EVP_CIPHER_get_asn1_iv, 4740Sstevel@tonic-gate NULL 4750Sstevel@tonic-gate }; 4760Sstevel@tonic-gate 4777211Sjp161948 static const EVP_CIPHER pk11_aes_192_cbc = 4787211Sjp161948 { 4797211Sjp161948 NID_aes_192_cbc, 4807211Sjp161948 16, 24, 16, 4817211Sjp161948 EVP_CIPH_CBC_MODE, 4827211Sjp161948 pk11_cipher_init, 4837211Sjp161948 pk11_cipher_do_cipher, 4847211Sjp161948 pk11_cipher_cleanup, 4857211Sjp161948 sizeof(PK11_CIPHER_STATE), 4867211Sjp161948 EVP_CIPHER_set_asn1_iv, 4877211Sjp161948 EVP_CIPHER_get_asn1_iv, 4887211Sjp161948 NULL 4897211Sjp161948 }; 4907211Sjp161948 4917211Sjp161948 static const EVP_CIPHER pk11_aes_256_cbc = 4927211Sjp161948 { 4937211Sjp161948 NID_aes_256_cbc, 4947211Sjp161948 16, 32, 16, 4957211Sjp161948 EVP_CIPH_CBC_MODE, 4967211Sjp161948 pk11_cipher_init, 4977211Sjp161948 pk11_cipher_do_cipher, 4987211Sjp161948 pk11_cipher_cleanup, 4997211Sjp161948 sizeof(PK11_CIPHER_STATE), 5007211Sjp161948 EVP_CIPHER_set_asn1_iv, 5017211Sjp161948 EVP_CIPHER_get_asn1_iv, 5027211Sjp161948 NULL 5037211Sjp161948 }; 5047211Sjp161948 5057211Sjp161948 /* 5067211Sjp161948 * ECB modes don't use IV so that's why set_asn1_parameters and 5077211Sjp161948 * get_asn1_parameters are set to NULL. 5087211Sjp161948 */ 5097211Sjp161948 static const EVP_CIPHER pk11_aes_128_ecb = 5107211Sjp161948 { 5117211Sjp161948 NID_aes_128_ecb, 5127211Sjp161948 16, 16, 0, 5137211Sjp161948 EVP_CIPH_ECB_MODE, 5147211Sjp161948 pk11_cipher_init, 5157211Sjp161948 pk11_cipher_do_cipher, 5167211Sjp161948 pk11_cipher_cleanup, 5177211Sjp161948 sizeof(PK11_CIPHER_STATE), 5187211Sjp161948 NULL, 5197211Sjp161948 NULL, 5207211Sjp161948 NULL 5217211Sjp161948 }; 5227211Sjp161948 5237211Sjp161948 static const EVP_CIPHER pk11_aes_192_ecb = 5247211Sjp161948 { 5257211Sjp161948 NID_aes_192_ecb, 5267211Sjp161948 16, 24, 0, 5277211Sjp161948 EVP_CIPH_ECB_MODE, 5287211Sjp161948 pk11_cipher_init, 5297211Sjp161948 pk11_cipher_do_cipher, 5307211Sjp161948 pk11_cipher_cleanup, 5317211Sjp161948 sizeof(PK11_CIPHER_STATE), 5327211Sjp161948 NULL, 5337211Sjp161948 NULL, 5347211Sjp161948 NULL 5357211Sjp161948 }; 5367211Sjp161948 5377211Sjp161948 static const EVP_CIPHER pk11_aes_256_ecb = 5387211Sjp161948 { 5397211Sjp161948 NID_aes_256_ecb, 5407211Sjp161948 16, 32, 0, 5417211Sjp161948 EVP_CIPH_ECB_MODE, 5427211Sjp161948 pk11_cipher_init, 5437211Sjp161948 pk11_cipher_do_cipher, 5447211Sjp161948 pk11_cipher_cleanup, 5457211Sjp161948 sizeof(PK11_CIPHER_STATE), 5467211Sjp161948 NULL, 5477211Sjp161948 NULL, 5487211Sjp161948 NULL 5497211Sjp161948 }; 5507211Sjp161948 5517211Sjp161948 #ifdef SOLARIS_AES_CTR 5527211Sjp161948 /* 5537211Sjp161948 * NID_undef's will be changed to the AES counter mode NIDs as soon they are 5547211Sjp161948 * created in pk11_library_init(). Note that the need to change these structures 5557211Sjp161948 * is the reason why we don't define them with the const keyword. 5567211Sjp161948 */ 5577211Sjp161948 static EVP_CIPHER pk11_aes_128_ctr = 5587211Sjp161948 { 5597211Sjp161948 NID_undef, 5607211Sjp161948 16, 16, 16, 5617211Sjp161948 EVP_CIPH_CBC_MODE, 5627211Sjp161948 pk11_cipher_init, 5637211Sjp161948 pk11_cipher_do_cipher, 5647211Sjp161948 pk11_cipher_cleanup, 5657211Sjp161948 sizeof(PK11_CIPHER_STATE), 5667211Sjp161948 EVP_CIPHER_set_asn1_iv, 5677211Sjp161948 EVP_CIPHER_get_asn1_iv, 5687211Sjp161948 NULL 5697211Sjp161948 }; 5707211Sjp161948 5717211Sjp161948 static EVP_CIPHER pk11_aes_192_ctr = 5727211Sjp161948 { 5737211Sjp161948 NID_undef, 5747211Sjp161948 16, 24, 16, 5757211Sjp161948 EVP_CIPH_CBC_MODE, 5767211Sjp161948 pk11_cipher_init, 5777211Sjp161948 pk11_cipher_do_cipher, 5787211Sjp161948 pk11_cipher_cleanup, 5797211Sjp161948 sizeof(PK11_CIPHER_STATE), 5807211Sjp161948 EVP_CIPHER_set_asn1_iv, 5817211Sjp161948 EVP_CIPHER_get_asn1_iv, 5827211Sjp161948 NULL 5837211Sjp161948 }; 5847211Sjp161948 5857211Sjp161948 static EVP_CIPHER pk11_aes_256_ctr = 5867211Sjp161948 { 5877211Sjp161948 NID_undef, 5887211Sjp161948 16, 32, 16, 5897211Sjp161948 EVP_CIPH_CBC_MODE, 5907211Sjp161948 pk11_cipher_init, 5917211Sjp161948 pk11_cipher_do_cipher, 5927211Sjp161948 pk11_cipher_cleanup, 5937211Sjp161948 sizeof(PK11_CIPHER_STATE), 5947211Sjp161948 EVP_CIPHER_set_asn1_iv, 5957211Sjp161948 EVP_CIPHER_get_asn1_iv, 5967211Sjp161948 NULL 5977211Sjp161948 }; 5987211Sjp161948 #endif /* SOLARIS_AES_CTR */ 5997211Sjp161948 6007211Sjp161948 static const EVP_CIPHER pk11_bf_cbc = 6017211Sjp161948 { 6027211Sjp161948 NID_bf_cbc, 6037211Sjp161948 8, 16, 8, 6047211Sjp161948 EVP_CIPH_VARIABLE_LENGTH, 6057211Sjp161948 pk11_cipher_init, 6067211Sjp161948 pk11_cipher_do_cipher, 6077211Sjp161948 pk11_cipher_cleanup, 6087211Sjp161948 sizeof(PK11_CIPHER_STATE), 6097211Sjp161948 EVP_CIPHER_set_asn1_iv, 6107211Sjp161948 EVP_CIPHER_get_asn1_iv, 6117211Sjp161948 NULL 6127211Sjp161948 }; 6137211Sjp161948 6140Sstevel@tonic-gate static const EVP_CIPHER pk11_rc4 = 6150Sstevel@tonic-gate { 6160Sstevel@tonic-gate NID_rc4, 6177211Sjp161948 1, 16, 0, 6180Sstevel@tonic-gate EVP_CIPH_VARIABLE_LENGTH, 6190Sstevel@tonic-gate pk11_cipher_init, 6200Sstevel@tonic-gate pk11_cipher_do_cipher, 6210Sstevel@tonic-gate pk11_cipher_cleanup, 6220Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 6230Sstevel@tonic-gate NULL, 6240Sstevel@tonic-gate NULL, 6250Sstevel@tonic-gate NULL 6260Sstevel@tonic-gate }; 6270Sstevel@tonic-gate 6280Sstevel@tonic-gate static const EVP_MD pk11_md5 = 6290Sstevel@tonic-gate { 6300Sstevel@tonic-gate NID_md5, 6310Sstevel@tonic-gate NID_md5WithRSAEncryption, 6320Sstevel@tonic-gate MD5_DIGEST_LENGTH, 6330Sstevel@tonic-gate 0, 6340Sstevel@tonic-gate pk11_digest_init, 6350Sstevel@tonic-gate pk11_digest_update, 6360Sstevel@tonic-gate pk11_digest_final, 6370Sstevel@tonic-gate pk11_digest_copy, 6380Sstevel@tonic-gate pk11_digest_cleanup, 6390Sstevel@tonic-gate EVP_PKEY_RSA_method, 6400Sstevel@tonic-gate MD5_CBLOCK, 6410Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 6420Sstevel@tonic-gate }; 6430Sstevel@tonic-gate 6440Sstevel@tonic-gate static const EVP_MD pk11_sha1 = 6450Sstevel@tonic-gate { 6460Sstevel@tonic-gate NID_sha1, 6470Sstevel@tonic-gate NID_sha1WithRSAEncryption, 6480Sstevel@tonic-gate SHA_DIGEST_LENGTH, 6490Sstevel@tonic-gate 0, 6500Sstevel@tonic-gate pk11_digest_init, 6510Sstevel@tonic-gate pk11_digest_update, 6520Sstevel@tonic-gate pk11_digest_final, 6530Sstevel@tonic-gate pk11_digest_copy, 6540Sstevel@tonic-gate pk11_digest_cleanup, 6550Sstevel@tonic-gate EVP_PKEY_RSA_method, 6560Sstevel@tonic-gate SHA_CBLOCK, 6570Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 6580Sstevel@tonic-gate }; 6590Sstevel@tonic-gate 6607211Sjp161948 static const EVP_MD pk11_sha224 = 6617211Sjp161948 { 6627211Sjp161948 NID_sha224, 6637211Sjp161948 NID_sha224WithRSAEncryption, 6647211Sjp161948 SHA224_DIGEST_LENGTH, 6657211Sjp161948 0, 6667211Sjp161948 pk11_digest_init, 6677211Sjp161948 pk11_digest_update, 6687211Sjp161948 pk11_digest_final, 6697211Sjp161948 pk11_digest_copy, 6707211Sjp161948 pk11_digest_cleanup, 6717211Sjp161948 EVP_PKEY_RSA_method, 6727211Sjp161948 /* SHA-224 uses the same cblock size as SHA-256 */ 6737211Sjp161948 SHA256_CBLOCK, 6747211Sjp161948 sizeof(PK11_CIPHER_STATE), 6757211Sjp161948 }; 6767211Sjp161948 6777211Sjp161948 static const EVP_MD pk11_sha256 = 6787211Sjp161948 { 6797211Sjp161948 NID_sha256, 6807211Sjp161948 NID_sha256WithRSAEncryption, 6817211Sjp161948 SHA256_DIGEST_LENGTH, 6827211Sjp161948 0, 6837211Sjp161948 pk11_digest_init, 6847211Sjp161948 pk11_digest_update, 6857211Sjp161948 pk11_digest_final, 6867211Sjp161948 pk11_digest_copy, 6877211Sjp161948 pk11_digest_cleanup, 6887211Sjp161948 EVP_PKEY_RSA_method, 6897211Sjp161948 SHA256_CBLOCK, 6907211Sjp161948 sizeof(PK11_CIPHER_STATE), 6917211Sjp161948 }; 6927211Sjp161948 6937211Sjp161948 static const EVP_MD pk11_sha384 = 6947211Sjp161948 { 6957211Sjp161948 NID_sha384, 6967211Sjp161948 NID_sha384WithRSAEncryption, 6977211Sjp161948 SHA384_DIGEST_LENGTH, 6987211Sjp161948 0, 6997211Sjp161948 pk11_digest_init, 7007211Sjp161948 pk11_digest_update, 7017211Sjp161948 pk11_digest_final, 7027211Sjp161948 pk11_digest_copy, 7037211Sjp161948 pk11_digest_cleanup, 7047211Sjp161948 EVP_PKEY_RSA_method, 7057211Sjp161948 /* SHA-384 uses the same cblock size as SHA-512 */ 7067211Sjp161948 SHA512_CBLOCK, 7077211Sjp161948 sizeof(PK11_CIPHER_STATE), 7087211Sjp161948 }; 7097211Sjp161948 7107211Sjp161948 static const EVP_MD pk11_sha512 = 7117211Sjp161948 { 7127211Sjp161948 NID_sha512, 7137211Sjp161948 NID_sha512WithRSAEncryption, 7147211Sjp161948 SHA512_DIGEST_LENGTH, 7157211Sjp161948 0, 7167211Sjp161948 pk11_digest_init, 7177211Sjp161948 pk11_digest_update, 7187211Sjp161948 pk11_digest_final, 7197211Sjp161948 pk11_digest_copy, 7207211Sjp161948 pk11_digest_cleanup, 7217211Sjp161948 EVP_PKEY_RSA_method, 7227211Sjp161948 SHA512_CBLOCK, 7237211Sjp161948 sizeof(PK11_CIPHER_STATE), 7247211Sjp161948 }; 7257211Sjp161948 7260Sstevel@tonic-gate /* Initialization function. Sets up various pk11 library components. 7270Sstevel@tonic-gate */ 7280Sstevel@tonic-gate /* The definitions for control commands specific to this engine 7290Sstevel@tonic-gate */ 7300Sstevel@tonic-gate #define PK11_CMD_SO_PATH ENGINE_CMD_BASE 7310Sstevel@tonic-gate static const ENGINE_CMD_DEFN pk11_cmd_defns[] = 7320Sstevel@tonic-gate { 7330Sstevel@tonic-gate { 7340Sstevel@tonic-gate PK11_CMD_SO_PATH, 7350Sstevel@tonic-gate "SO_PATH", 7360Sstevel@tonic-gate "Specifies the path to the 'pkcs#11' shared library", 7370Sstevel@tonic-gate ENGINE_CMD_FLAG_STRING 7380Sstevel@tonic-gate }, 7390Sstevel@tonic-gate {0, NULL, NULL, 0} 7400Sstevel@tonic-gate }; 7410Sstevel@tonic-gate 7420Sstevel@tonic-gate 7430Sstevel@tonic-gate static RAND_METHOD pk11_random = 7440Sstevel@tonic-gate { 7450Sstevel@tonic-gate pk11_rand_seed, 7460Sstevel@tonic-gate pk11_rand_bytes, 7470Sstevel@tonic-gate pk11_rand_cleanup, 7480Sstevel@tonic-gate pk11_rand_add, 7490Sstevel@tonic-gate pk11_rand_bytes, 7500Sstevel@tonic-gate pk11_rand_status 7510Sstevel@tonic-gate }; 7520Sstevel@tonic-gate 7530Sstevel@tonic-gate 7540Sstevel@tonic-gate /* Constants used when creating the ENGINE 7550Sstevel@tonic-gate */ 7560Sstevel@tonic-gate static const char *engine_pk11_id = "pkcs11"; 7570Sstevel@tonic-gate static const char *engine_pk11_name = "PKCS #11 engine support"; 7580Sstevel@tonic-gate 7590Sstevel@tonic-gate CK_FUNCTION_LIST_PTR pFuncList = NULL; 7600Sstevel@tonic-gate static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList"; 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate /* These are the static string constants for the DSO file name and the function 7637211Sjp161948 * symbol names to bind to. 7640Sstevel@tonic-gate */ 7650Sstevel@tonic-gate #if defined(__sparcv9) || defined(__x86_64) || defined(__amd64) 7660Sstevel@tonic-gate static const char def_PK11_LIBNAME[] = "/usr/lib/64/libpkcs11.so.1"; 7670Sstevel@tonic-gate #else 7680Sstevel@tonic-gate static const char def_PK11_LIBNAME[] = "/usr/lib/libpkcs11.so.1"; 7690Sstevel@tonic-gate #endif 7700Sstevel@tonic-gate 7710Sstevel@tonic-gate static CK_BBOOL true = TRUE; 7720Sstevel@tonic-gate static CK_BBOOL false = FALSE; 7737211Sjp161948 static CK_SLOT_ID pubkey_SLOTID = 0; 7747211Sjp161948 static CK_SLOT_ID rand_SLOTID = 0; 7750Sstevel@tonic-gate static CK_SLOT_ID SLOTID = 0; 776*7526SVladimir.Kotal@Sun.COM static CK_BBOOL pk11_library_initialized = FALSE; 777*7526SVladimir.Kotal@Sun.COM static CK_BBOOL pk11_atfork_initialized = FALSE; 7787211Sjp161948 static int pk11_pid = 0; 7790Sstevel@tonic-gate 7800Sstevel@tonic-gate static DSO *pk11_dso = NULL; 7810Sstevel@tonic-gate 782*7526SVladimir.Kotal@Sun.COM /* allocate and initialize all locks used by the engine itself */ 783*7526SVladimir.Kotal@Sun.COM static int pk11_init_all_locks(void) 784*7526SVladimir.Kotal@Sun.COM { 785*7526SVladimir.Kotal@Sun.COM int type; 786*7526SVladimir.Kotal@Sun.COM 787*7526SVladimir.Kotal@Sun.COM #ifndef OPENSSL_NO_RSA 788*7526SVladimir.Kotal@Sun.COM find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); 789*7526SVladimir.Kotal@Sun.COM if (find_lock[OP_RSA] == NULL) 790*7526SVladimir.Kotal@Sun.COM goto malloc_err; 791*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_init(find_lock[OP_RSA], NULL); 792*7526SVladimir.Kotal@Sun.COM #endif /* OPENSSL_NO_RSA */ 793*7526SVladimir.Kotal@Sun.COM 794*7526SVladimir.Kotal@Sun.COM #ifndef OPENSSL_NO_DSA 795*7526SVladimir.Kotal@Sun.COM find_lock[OP_DSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); 796*7526SVladimir.Kotal@Sun.COM if (find_lock[OP_DSA] == NULL) 797*7526SVladimir.Kotal@Sun.COM goto malloc_err; 798*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_init(find_lock[OP_DSA], NULL); 799*7526SVladimir.Kotal@Sun.COM #endif /* OPENSSL_NO_DSA */ 800*7526SVladimir.Kotal@Sun.COM 801*7526SVladimir.Kotal@Sun.COM #ifndef OPENSSL_NO_DH 802*7526SVladimir.Kotal@Sun.COM find_lock[OP_DH] = OPENSSL_malloc(sizeof (pthread_mutex_t)); 803*7526SVladimir.Kotal@Sun.COM if (find_lock[OP_DH] == NULL) 804*7526SVladimir.Kotal@Sun.COM goto malloc_err; 805*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_init(find_lock[OP_DH], NULL); 806*7526SVladimir.Kotal@Sun.COM #endif /* OPENSSL_NO_DH */ 807*7526SVladimir.Kotal@Sun.COM 808*7526SVladimir.Kotal@Sun.COM for (type = 0; type < OP_MAX; type++) 809*7526SVladimir.Kotal@Sun.COM { 810*7526SVladimir.Kotal@Sun.COM session_cache[type].lock = 811*7526SVladimir.Kotal@Sun.COM OPENSSL_malloc(sizeof (pthread_mutex_t)); 812*7526SVladimir.Kotal@Sun.COM if (session_cache[type].lock == NULL) 813*7526SVladimir.Kotal@Sun.COM goto malloc_err; 814*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_init(session_cache[type].lock, NULL); 815*7526SVladimir.Kotal@Sun.COM } 816*7526SVladimir.Kotal@Sun.COM 817*7526SVladimir.Kotal@Sun.COM return (1); 818*7526SVladimir.Kotal@Sun.COM 819*7526SVladimir.Kotal@Sun.COM malloc_err: 820*7526SVladimir.Kotal@Sun.COM pk11_free_all_locks(); 821*7526SVladimir.Kotal@Sun.COM PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE); 822*7526SVladimir.Kotal@Sun.COM return (0); 823*7526SVladimir.Kotal@Sun.COM } 824*7526SVladimir.Kotal@Sun.COM 825*7526SVladimir.Kotal@Sun.COM static void pk11_free_all_locks(void) 826*7526SVladimir.Kotal@Sun.COM { 827*7526SVladimir.Kotal@Sun.COM int type; 828*7526SVladimir.Kotal@Sun.COM 829*7526SVladimir.Kotal@Sun.COM #ifndef OPENSSL_NO_RSA 830*7526SVladimir.Kotal@Sun.COM if (find_lock[OP_RSA] != NULL) 831*7526SVladimir.Kotal@Sun.COM { 832*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_destroy(find_lock[OP_RSA]); 833*7526SVladimir.Kotal@Sun.COM OPENSSL_free(find_lock[OP_RSA]); 834*7526SVladimir.Kotal@Sun.COM find_lock[OP_RSA] = NULL; 835*7526SVladimir.Kotal@Sun.COM } 836*7526SVladimir.Kotal@Sun.COM #endif /* OPENSSL_NO_RSA */ 837*7526SVladimir.Kotal@Sun.COM #ifndef OPENSSL_NO_DSA 838*7526SVladimir.Kotal@Sun.COM if (find_lock[OP_DSA] != NULL) 839*7526SVladimir.Kotal@Sun.COM { 840*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_destroy(find_lock[OP_DSA]); 841*7526SVladimir.Kotal@Sun.COM OPENSSL_free(find_lock[OP_DSA]); 842*7526SVladimir.Kotal@Sun.COM find_lock[OP_DSA] = NULL; 843*7526SVladimir.Kotal@Sun.COM } 844*7526SVladimir.Kotal@Sun.COM #endif /* OPENSSL_NO_DSA */ 845*7526SVladimir.Kotal@Sun.COM #ifndef OPENSSL_NO_DH 846*7526SVladimir.Kotal@Sun.COM if (find_lock[OP_DH] != NULL) 847*7526SVladimir.Kotal@Sun.COM { 848*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_destroy(find_lock[OP_DH]); 849*7526SVladimir.Kotal@Sun.COM OPENSSL_free(find_lock[OP_DH]); 850*7526SVladimir.Kotal@Sun.COM find_lock[OP_DH] = NULL; 851*7526SVladimir.Kotal@Sun.COM } 852*7526SVladimir.Kotal@Sun.COM #endif /* OPENSSL_NO_DH */ 853*7526SVladimir.Kotal@Sun.COM 854*7526SVladimir.Kotal@Sun.COM for (type = 0; type < OP_MAX; type++) 855*7526SVladimir.Kotal@Sun.COM { 856*7526SVladimir.Kotal@Sun.COM if (session_cache[type].lock != NULL) 857*7526SVladimir.Kotal@Sun.COM { 858*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_destroy(session_cache[type].lock); 859*7526SVladimir.Kotal@Sun.COM OPENSSL_free(session_cache[type].lock); 860*7526SVladimir.Kotal@Sun.COM session_cache[type].lock = NULL; 861*7526SVladimir.Kotal@Sun.COM } 862*7526SVladimir.Kotal@Sun.COM } 863*7526SVladimir.Kotal@Sun.COM } 864*7526SVladimir.Kotal@Sun.COM 8650Sstevel@tonic-gate /* 8660Sstevel@tonic-gate * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support. 8670Sstevel@tonic-gate */ 8680Sstevel@tonic-gate static int bind_pk11(ENGINE *e) 8690Sstevel@tonic-gate { 8706847Svk199839 #ifndef OPENSSL_NO_RSA 8710Sstevel@tonic-gate const RSA_METHOD *rsa = NULL; 8720Sstevel@tonic-gate RSA_METHOD *pk11_rsa = PK11_RSA(); 8737211Sjp161948 #endif /* OPENSSL_NO_RSA */ 8740Sstevel@tonic-gate if (!pk11_library_initialized) 875*7526SVladimir.Kotal@Sun.COM (void) pk11_library_init(e); 8760Sstevel@tonic-gate 8770Sstevel@tonic-gate if(!ENGINE_set_id(e, engine_pk11_id) || 8780Sstevel@tonic-gate !ENGINE_set_name(e, engine_pk11_name) || 8790Sstevel@tonic-gate !ENGINE_set_ciphers(e, pk11_engine_ciphers) || 8800Sstevel@tonic-gate !ENGINE_set_digests(e, pk11_engine_digests)) 8810Sstevel@tonic-gate return 0; 8820Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA 8830Sstevel@tonic-gate if(pk11_have_rsa == CK_TRUE) 8840Sstevel@tonic-gate { 8850Sstevel@tonic-gate if(!ENGINE_set_RSA(e, PK11_RSA()) || 8860Sstevel@tonic-gate !ENGINE_set_load_privkey_function(e, pk11_load_privkey) || 8870Sstevel@tonic-gate !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey)) 8880Sstevel@tonic-gate return 0; 8897211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 8907211Sjp161948 fprintf(stderr, "%s: registered RSA\n", PK11_DBG); 8917211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 8920Sstevel@tonic-gate } 8937211Sjp161948 #endif /* OPENSSL_NO_RSA */ 8940Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA 8950Sstevel@tonic-gate if(pk11_have_dsa == CK_TRUE) 8960Sstevel@tonic-gate { 8970Sstevel@tonic-gate if (!ENGINE_set_DSA(e, PK11_DSA())) 8980Sstevel@tonic-gate return 0; 8997211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 9007211Sjp161948 fprintf(stderr, "%s: registered DSA\n", PK11_DBG); 9017211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 9020Sstevel@tonic-gate } 9037211Sjp161948 #endif /* OPENSSL_NO_DSA */ 9040Sstevel@tonic-gate #ifndef OPENSSL_NO_DH 9050Sstevel@tonic-gate if(pk11_have_dh == CK_TRUE) 9060Sstevel@tonic-gate { 9070Sstevel@tonic-gate if (!ENGINE_set_DH(e, PK11_DH())) 9080Sstevel@tonic-gate return 0; 9097211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 9107211Sjp161948 fprintf(stderr, "%s: registered DH\n", PK11_DBG); 9117211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 9120Sstevel@tonic-gate } 9137211Sjp161948 #endif /* OPENSSL_NO_DH */ 9140Sstevel@tonic-gate if(pk11_have_random) 9150Sstevel@tonic-gate { 9160Sstevel@tonic-gate if(!ENGINE_set_RAND(e, &pk11_random)) 9170Sstevel@tonic-gate return 0; 9187211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 9197211Sjp161948 fprintf(stderr, "%s: registered random\n", PK11_DBG); 9207211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 9210Sstevel@tonic-gate } 9220Sstevel@tonic-gate if(!ENGINE_set_init_function(e, pk11_init) || 9230Sstevel@tonic-gate !ENGINE_set_destroy_function(e, pk11_destroy) || 9240Sstevel@tonic-gate !ENGINE_set_finish_function(e, pk11_finish) || 9250Sstevel@tonic-gate !ENGINE_set_ctrl_function(e, pk11_ctrl) || 9260Sstevel@tonic-gate !ENGINE_set_cmd_defns(e, pk11_cmd_defns)) 9270Sstevel@tonic-gate return 0; 9280Sstevel@tonic-gate 9290Sstevel@tonic-gate /* Apache calls OpenSSL function RSA_blinding_on() once during startup 9300Sstevel@tonic-gate * which in turn calls bn_mod_exp. Since we do not implement bn_mod_exp 9310Sstevel@tonic-gate * here, we wire it back to the OpenSSL software implementation. 9320Sstevel@tonic-gate * Since it is used only once, performance is not a concern. */ 9330Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA 9340Sstevel@tonic-gate rsa = RSA_PKCS1_SSLeay(); 9350Sstevel@tonic-gate pk11_rsa->rsa_mod_exp = rsa->rsa_mod_exp; 9360Sstevel@tonic-gate pk11_rsa->bn_mod_exp = rsa->bn_mod_exp; 9377211Sjp161948 #endif /* OPENSSL_NO_RSA */ 9380Sstevel@tonic-gate 9390Sstevel@tonic-gate /* Ensure the pk11 error handling is set up */ 9400Sstevel@tonic-gate ERR_load_pk11_strings(); 9410Sstevel@tonic-gate 9420Sstevel@tonic-gate return 1; 9430Sstevel@tonic-gate } 9440Sstevel@tonic-gate 9450Sstevel@tonic-gate /* Dynamic engine support is disabled at a higher level for Solaris 9460Sstevel@tonic-gate */ 9477211Sjp161948 #ifdef ENGINE_DYNAMIC_SUPPORT 9480Sstevel@tonic-gate static int bind_helper(ENGINE *e, const char *id) 9490Sstevel@tonic-gate { 9500Sstevel@tonic-gate if (id && (strcmp(id, engine_pk11_id) != 0)) 9510Sstevel@tonic-gate return 0; 9520Sstevel@tonic-gate 9530Sstevel@tonic-gate if (!bind_pk11(e)) 9540Sstevel@tonic-gate return 0; 9550Sstevel@tonic-gate 9560Sstevel@tonic-gate return 1; 9570Sstevel@tonic-gate } 9580Sstevel@tonic-gate 9590Sstevel@tonic-gate IMPLEMENT_DYNAMIC_CHECK_FN() 9600Sstevel@tonic-gate IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) 9610Sstevel@tonic-gate 9620Sstevel@tonic-gate #else 9630Sstevel@tonic-gate static ENGINE *engine_pk11(void) 9640Sstevel@tonic-gate { 9650Sstevel@tonic-gate ENGINE *ret = ENGINE_new(); 9660Sstevel@tonic-gate 9670Sstevel@tonic-gate if (!ret) 9680Sstevel@tonic-gate return NULL; 9690Sstevel@tonic-gate 9700Sstevel@tonic-gate if (!bind_pk11(ret)) 9710Sstevel@tonic-gate { 9720Sstevel@tonic-gate ENGINE_free(ret); 9730Sstevel@tonic-gate return NULL; 9740Sstevel@tonic-gate } 9750Sstevel@tonic-gate 9760Sstevel@tonic-gate return ret; 9770Sstevel@tonic-gate } 9780Sstevel@tonic-gate 9790Sstevel@tonic-gate void ENGINE_load_pk11(void) 9800Sstevel@tonic-gate { 9810Sstevel@tonic-gate ENGINE *e_pk11 = NULL; 9820Sstevel@tonic-gate 9830Sstevel@tonic-gate /* Do not use dynamic PKCS#11 library on Solaris due to 9840Sstevel@tonic-gate * security reasons. We will link it in statically 9850Sstevel@tonic-gate */ 9860Sstevel@tonic-gate /* Attempt to load PKCS#11 library 9870Sstevel@tonic-gate */ 9880Sstevel@tonic-gate if (!pk11_dso) 9890Sstevel@tonic-gate pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0); 9900Sstevel@tonic-gate 9910Sstevel@tonic-gate if (pk11_dso == NULL) 9920Sstevel@tonic-gate { 9930Sstevel@tonic-gate PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE); 9940Sstevel@tonic-gate return; 9950Sstevel@tonic-gate } 9960Sstevel@tonic-gate 9970Sstevel@tonic-gate e_pk11 = engine_pk11(); 9980Sstevel@tonic-gate if (!e_pk11) 9990Sstevel@tonic-gate { 10000Sstevel@tonic-gate DSO_free(pk11_dso); 10010Sstevel@tonic-gate pk11_dso = NULL; 10020Sstevel@tonic-gate return; 10030Sstevel@tonic-gate } 10040Sstevel@tonic-gate 10050Sstevel@tonic-gate /* At this point, the pk11 shared library is either dynamically 10060Sstevel@tonic-gate * loaded or statically linked in. So, initialize the pk11 10070Sstevel@tonic-gate * library before calling ENGINE_set_default since the latter 10080Sstevel@tonic-gate * needs cipher and digest algorithm information 10090Sstevel@tonic-gate */ 10100Sstevel@tonic-gate if (!pk11_library_init(e_pk11)) 10110Sstevel@tonic-gate { 10120Sstevel@tonic-gate DSO_free(pk11_dso); 10130Sstevel@tonic-gate pk11_dso = NULL; 10140Sstevel@tonic-gate ENGINE_free(e_pk11); 10150Sstevel@tonic-gate return; 10160Sstevel@tonic-gate } 10170Sstevel@tonic-gate 10180Sstevel@tonic-gate ENGINE_add(e_pk11); 10190Sstevel@tonic-gate 10200Sstevel@tonic-gate ENGINE_free(e_pk11); 10210Sstevel@tonic-gate ERR_clear_error(); 10220Sstevel@tonic-gate } 10237211Sjp161948 #endif /* ENGINE_DYNAMIC_SUPPORT */ 10240Sstevel@tonic-gate 10250Sstevel@tonic-gate /* These are the static string constants for the DSO file name and 10260Sstevel@tonic-gate * the function symbol names to bind to. 10270Sstevel@tonic-gate */ 10280Sstevel@tonic-gate static const char *PK11_LIBNAME = NULL; 10290Sstevel@tonic-gate 10300Sstevel@tonic-gate static const char *get_PK11_LIBNAME(void) 10310Sstevel@tonic-gate { 10320Sstevel@tonic-gate if (PK11_LIBNAME) 10330Sstevel@tonic-gate return PK11_LIBNAME; 10340Sstevel@tonic-gate 10350Sstevel@tonic-gate return def_PK11_LIBNAME; 10360Sstevel@tonic-gate } 10370Sstevel@tonic-gate 10380Sstevel@tonic-gate static void free_PK11_LIBNAME(void) 10390Sstevel@tonic-gate { 10400Sstevel@tonic-gate if (PK11_LIBNAME) 10410Sstevel@tonic-gate OPENSSL_free((void*)PK11_LIBNAME); 10420Sstevel@tonic-gate 10430Sstevel@tonic-gate PK11_LIBNAME = NULL; 10440Sstevel@tonic-gate } 10450Sstevel@tonic-gate 10460Sstevel@tonic-gate static long set_PK11_LIBNAME(const char *name) 10470Sstevel@tonic-gate { 10480Sstevel@tonic-gate free_PK11_LIBNAME(); 10490Sstevel@tonic-gate 10500Sstevel@tonic-gate return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0); 10510Sstevel@tonic-gate } 10520Sstevel@tonic-gate 1053*7526SVladimir.Kotal@Sun.COM /* acquire all engine specific mutexes before fork */ 1054*7526SVladimir.Kotal@Sun.COM static void pk11_fork_prepare(void) 1055*7526SVladimir.Kotal@Sun.COM { 1056*7526SVladimir.Kotal@Sun.COM int i; 1057*7526SVladimir.Kotal@Sun.COM 1058*7526SVladimir.Kotal@Sun.COM LOCK_OBJSTORE(OP_RSA); 1059*7526SVladimir.Kotal@Sun.COM LOCK_OBJSTORE(OP_DSA); 1060*7526SVladimir.Kotal@Sun.COM LOCK_OBJSTORE(OP_DH); 1061*7526SVladimir.Kotal@Sun.COM for (i = 0; i < OP_MAX; i++) 1062*7526SVladimir.Kotal@Sun.COM { 1063*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_lock(session_cache[i].lock); 1064*7526SVladimir.Kotal@Sun.COM } 1065*7526SVladimir.Kotal@Sun.COM } 1066*7526SVladimir.Kotal@Sun.COM 1067*7526SVladimir.Kotal@Sun.COM /* release all engine specific mutexes */ 1068*7526SVladimir.Kotal@Sun.COM static void pk11_fork_parent(void) 1069*7526SVladimir.Kotal@Sun.COM { 1070*7526SVladimir.Kotal@Sun.COM int i; 1071*7526SVladimir.Kotal@Sun.COM 1072*7526SVladimir.Kotal@Sun.COM for (i = OP_MAX - 1; i >= 0; i--) 1073*7526SVladimir.Kotal@Sun.COM { 1074*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_unlock(session_cache[i].lock); 1075*7526SVladimir.Kotal@Sun.COM } 1076*7526SVladimir.Kotal@Sun.COM UNLOCK_OBJSTORE(OP_DH); 1077*7526SVladimir.Kotal@Sun.COM UNLOCK_OBJSTORE(OP_DSA); 1078*7526SVladimir.Kotal@Sun.COM UNLOCK_OBJSTORE(OP_RSA); 1079*7526SVladimir.Kotal@Sun.COM } 1080*7526SVladimir.Kotal@Sun.COM 1081*7526SVladimir.Kotal@Sun.COM /* 1082*7526SVladimir.Kotal@Sun.COM * same situation as in parent - we need to unlock all locks to make them 1083*7526SVladimir.Kotal@Sun.COM * accessible to all threads. 1084*7526SVladimir.Kotal@Sun.COM */ 1085*7526SVladimir.Kotal@Sun.COM static void pk11_fork_child(void) 1086*7526SVladimir.Kotal@Sun.COM { 1087*7526SVladimir.Kotal@Sun.COM int i; 1088*7526SVladimir.Kotal@Sun.COM 1089*7526SVladimir.Kotal@Sun.COM for (i = OP_MAX - 1; i >= 0; i--) 1090*7526SVladimir.Kotal@Sun.COM { 1091*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_unlock(session_cache[i].lock); 1092*7526SVladimir.Kotal@Sun.COM } 1093*7526SVladimir.Kotal@Sun.COM UNLOCK_OBJSTORE(OP_DH); 1094*7526SVladimir.Kotal@Sun.COM UNLOCK_OBJSTORE(OP_DSA); 1095*7526SVladimir.Kotal@Sun.COM UNLOCK_OBJSTORE(OP_RSA); 1096*7526SVladimir.Kotal@Sun.COM } 1097*7526SVladimir.Kotal@Sun.COM 10980Sstevel@tonic-gate /* Initialization function for the pk11 engine */ 10990Sstevel@tonic-gate static int pk11_init(ENGINE *e) 11000Sstevel@tonic-gate { 11010Sstevel@tonic-gate return pk11_library_init(e); 11020Sstevel@tonic-gate } 11030Sstevel@tonic-gate 11040Sstevel@tonic-gate /* Initialization function. Sets up various pk11 library components. 11050Sstevel@tonic-gate * It selects a slot based on predefined critiera. In the process, it also 11060Sstevel@tonic-gate * count how many ciphers and digests to support. Since the cipher and 11070Sstevel@tonic-gate * digest information is needed when setting default engine, this function 11080Sstevel@tonic-gate * needs to be called before calling ENGINE_set_default. 11090Sstevel@tonic-gate */ 11100Sstevel@tonic-gate static int pk11_library_init(ENGINE *e) 11110Sstevel@tonic-gate { 11120Sstevel@tonic-gate CK_C_GetFunctionList p; 11130Sstevel@tonic-gate CK_RV rv = CKR_OK; 11140Sstevel@tonic-gate CK_INFO info; 11150Sstevel@tonic-gate CK_ULONG ul_state_len; 11167211Sjp161948 int any_slot_found; 1117*7526SVladimir.Kotal@Sun.COM int i; 11187211Sjp161948 11197211Sjp161948 /* 11207211Sjp161948 * pk11_library_initialized is set to 0 in pk11_finish() which is called 11217211Sjp161948 * from ENGINE_finish(). However, if there is still at least one 11227211Sjp161948 * existing functional reference to the engine (see engine(3) for more 11237211Sjp161948 * information), pk11_finish() is skipped. For example, this can happen 11247211Sjp161948 * if an application forgets to clear one cipher context. In case of a 11257211Sjp161948 * fork() when the application is finishing the engine so that it can be 11267211Sjp161948 * reinitialized in the child, forgotten functional reference causes 11277211Sjp161948 * pk11_library_initialized to stay 1. In that case we need the PID 11287211Sjp161948 * check so that we properly initialize the engine again. 11297211Sjp161948 */ 11300Sstevel@tonic-gate if (pk11_library_initialized) 11317211Sjp161948 { 11327211Sjp161948 if (pk11_pid == getpid()) 1133*7526SVladimir.Kotal@Sun.COM { 11347211Sjp161948 return 1; 1135*7526SVladimir.Kotal@Sun.COM } 11367211Sjp161948 else 1137*7526SVladimir.Kotal@Sun.COM { 11387211Sjp161948 global_session = CK_INVALID_HANDLE; 1139*7526SVladimir.Kotal@Sun.COM /* 1140*7526SVladimir.Kotal@Sun.COM * free the locks first to prevent memory leak in case 1141*7526SVladimir.Kotal@Sun.COM * the application calls fork() without finishing the 1142*7526SVladimir.Kotal@Sun.COM * engine first. 1143*7526SVladimir.Kotal@Sun.COM */ 1144*7526SVladimir.Kotal@Sun.COM pk11_free_all_locks(); 1145*7526SVladimir.Kotal@Sun.COM } 11467211Sjp161948 } 11470Sstevel@tonic-gate 11480Sstevel@tonic-gate if (pk11_dso == NULL) 11490Sstevel@tonic-gate { 11500Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); 11510Sstevel@tonic-gate goto err; 11520Sstevel@tonic-gate } 11530Sstevel@tonic-gate 11547211Sjp161948 #ifdef SOLARIS_AES_CTR 11557211Sjp161948 /* 11567211Sjp161948 * We must do this before we start working with slots since we need all 11577211Sjp161948 * NIDs there. 11587211Sjp161948 */ 11597211Sjp161948 if (pk11_add_aes_ctr_NIDs() == 0) 11607211Sjp161948 goto err; 11617211Sjp161948 #endif /* SOLARIS_AES_CTR */ 11627211Sjp161948 11637211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 11647211Sjp161948 if (check_hw_mechanisms() == 0) 11657211Sjp161948 goto err; 11667211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 11677211Sjp161948 11680Sstevel@tonic-gate /* get the C_GetFunctionList function from the loaded library 11690Sstevel@tonic-gate */ 11700Sstevel@tonic-gate p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso, 11710Sstevel@tonic-gate PK11_GET_FUNCTION_LIST); 11720Sstevel@tonic-gate if ( !p ) 11730Sstevel@tonic-gate { 11740Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); 11750Sstevel@tonic-gate goto err; 11760Sstevel@tonic-gate } 11770Sstevel@tonic-gate 11780Sstevel@tonic-gate /* get the full function list from the loaded library 11790Sstevel@tonic-gate */ 11800Sstevel@tonic-gate rv = p(&pFuncList); 11810Sstevel@tonic-gate if (rv != CKR_OK) 11820Sstevel@tonic-gate { 11837211Sjp161948 PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv); 11840Sstevel@tonic-gate goto err; 11850Sstevel@tonic-gate } 11860Sstevel@tonic-gate 11870Sstevel@tonic-gate rv = pFuncList->C_Initialize(NULL_PTR); 11880Sstevel@tonic-gate if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) 11890Sstevel@tonic-gate { 11907211Sjp161948 PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv); 11910Sstevel@tonic-gate goto err; 11920Sstevel@tonic-gate } 11930Sstevel@tonic-gate 11940Sstevel@tonic-gate rv = pFuncList->C_GetInfo(&info); 11950Sstevel@tonic-gate if (rv != CKR_OK) 11960Sstevel@tonic-gate { 11977211Sjp161948 PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv); 11980Sstevel@tonic-gate goto err; 11990Sstevel@tonic-gate } 12000Sstevel@tonic-gate 12017211Sjp161948 if (pk11_choose_slots(&any_slot_found) == 0) 12020Sstevel@tonic-gate goto err; 12030Sstevel@tonic-gate 12047211Sjp161948 /* 12057211Sjp161948 * The library we use, set in def_PK11_LIBNAME, may not offer any 12067211Sjp161948 * slot(s). In that case, we must not proceed but we must not return an 12077211Sjp161948 * error. The reason is that applications that try to set up the PKCS#11 12087211Sjp161948 * engine don't exit on error during the engine initialization just 12097211Sjp161948 * because no slot was present. 12107211Sjp161948 */ 12117211Sjp161948 if (any_slot_found == 0) 12127211Sjp161948 return 1; 12137211Sjp161948 12140Sstevel@tonic-gate if (global_session == CK_INVALID_HANDLE) 12150Sstevel@tonic-gate { 12160Sstevel@tonic-gate /* Open the global_session for the new process */ 12170Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 12180Sstevel@tonic-gate NULL_PTR, NULL_PTR, &global_session); 12190Sstevel@tonic-gate if (rv != CKR_OK) 12200Sstevel@tonic-gate { 12217211Sjp161948 PK11err_add_data(PK11_F_LIBRARY_INIT, 12227211Sjp161948 PK11_R_OPENSESSION, rv); 12230Sstevel@tonic-gate goto err; 12240Sstevel@tonic-gate } 12250Sstevel@tonic-gate } 12260Sstevel@tonic-gate 12270Sstevel@tonic-gate /* Disable digest if C_GetOperationState is not supported since 12280Sstevel@tonic-gate * this function is required by OpenSSL digest copy function */ 12290Sstevel@tonic-gate if (pFuncList->C_GetOperationState(global_session, NULL, &ul_state_len) 12307211Sjp161948 == CKR_FUNCTION_NOT_SUPPORTED) { 12317211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 12327211Sjp161948 fprintf(stderr, "%s: C_GetOperationState() not supported, " 12337211Sjp161948 "setting digest_count to 0\n", PK11_DBG); 12347211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 12350Sstevel@tonic-gate digest_count = 0; 12367211Sjp161948 } 12370Sstevel@tonic-gate 1238*7526SVladimir.Kotal@Sun.COM pk11_library_initialized = TRUE; 12397211Sjp161948 pk11_pid = getpid(); 1240*7526SVladimir.Kotal@Sun.COM /* 1241*7526SVladimir.Kotal@Sun.COM * if initialization of the locks fails pk11_init_all_locks() 1242*7526SVladimir.Kotal@Sun.COM * will do the cleanup. 1243*7526SVladimir.Kotal@Sun.COM */ 1244*7526SVladimir.Kotal@Sun.COM if (!pk11_init_all_locks()) 1245*7526SVladimir.Kotal@Sun.COM goto err; 1246*7526SVladimir.Kotal@Sun.COM for (i = 0; i < OP_MAX; i++) 1247*7526SVladimir.Kotal@Sun.COM session_cache[i].head = NULL; 1248*7526SVladimir.Kotal@Sun.COM /* 1249*7526SVladimir.Kotal@Sun.COM * initialize active lists. We only use active lists 1250*7526SVladimir.Kotal@Sun.COM * for asymmetric ciphers. 1251*7526SVladimir.Kotal@Sun.COM */ 1252*7526SVladimir.Kotal@Sun.COM for (i = 0; i < OP_MAX; i++) 1253*7526SVladimir.Kotal@Sun.COM active_list[i] = NULL; 1254*7526SVladimir.Kotal@Sun.COM 1255*7526SVladimir.Kotal@Sun.COM if (!pk11_atfork_initialized) 1256*7526SVladimir.Kotal@Sun.COM { 1257*7526SVladimir.Kotal@Sun.COM if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent, 1258*7526SVladimir.Kotal@Sun.COM pk11_fork_child) != 0) 1259*7526SVladimir.Kotal@Sun.COM { 1260*7526SVladimir.Kotal@Sun.COM PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED); 1261*7526SVladimir.Kotal@Sun.COM goto err; 1262*7526SVladimir.Kotal@Sun.COM } 1263*7526SVladimir.Kotal@Sun.COM pk11_atfork_initialized = TRUE; 1264*7526SVladimir.Kotal@Sun.COM } 1265*7526SVladimir.Kotal@Sun.COM 12660Sstevel@tonic-gate return 1; 12670Sstevel@tonic-gate 12680Sstevel@tonic-gate err: 12690Sstevel@tonic-gate return 0; 12700Sstevel@tonic-gate } 12710Sstevel@tonic-gate 12720Sstevel@tonic-gate /* Destructor (complements the "ENGINE_pk11()" constructor) 12730Sstevel@tonic-gate */ 12740Sstevel@tonic-gate static int pk11_destroy(ENGINE *e) 12750Sstevel@tonic-gate { 12760Sstevel@tonic-gate free_PK11_LIBNAME(); 12770Sstevel@tonic-gate ERR_unload_pk11_strings(); 12780Sstevel@tonic-gate return 1; 12790Sstevel@tonic-gate } 12800Sstevel@tonic-gate 12810Sstevel@tonic-gate /* Termination function to clean up the session, the token, and 12820Sstevel@tonic-gate * the pk11 library. 12830Sstevel@tonic-gate */ 12840Sstevel@tonic-gate static int pk11_finish(ENGINE *e) 12850Sstevel@tonic-gate { 1286*7526SVladimir.Kotal@Sun.COM int i; 1287*7526SVladimir.Kotal@Sun.COM 12880Sstevel@tonic-gate if (pk11_dso == NULL) 12890Sstevel@tonic-gate { 12900Sstevel@tonic-gate PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED); 12910Sstevel@tonic-gate goto err; 12920Sstevel@tonic-gate } 12930Sstevel@tonic-gate 12946847Svk199839 OPENSSL_assert(pFuncList != NULL); 12950Sstevel@tonic-gate 12960Sstevel@tonic-gate if (pk11_free_all_sessions() == 0) 12970Sstevel@tonic-gate goto err; 12980Sstevel@tonic-gate 1299*7526SVladimir.Kotal@Sun.COM /* free all active lists */ 1300*7526SVladimir.Kotal@Sun.COM for (i = 0; i < OP_MAX; i++) 1301*7526SVladimir.Kotal@Sun.COM pk11_free_active_list(i); 1302*7526SVladimir.Kotal@Sun.COM 13030Sstevel@tonic-gate pFuncList->C_CloseSession(global_session); 13047211Sjp161948 global_session = CK_INVALID_HANDLE; 13057211Sjp161948 13067211Sjp161948 /* 13077211Sjp161948 * Since we are part of a library (libcrypto.so), calling this function 13087211Sjp161948 * may have side-effects. 13097211Sjp161948 */ 13107211Sjp161948 #if 0 13110Sstevel@tonic-gate pFuncList->C_Finalize(NULL); 13127211Sjp161948 #endif 13130Sstevel@tonic-gate 13140Sstevel@tonic-gate if (!DSO_free(pk11_dso)) 13150Sstevel@tonic-gate { 13160Sstevel@tonic-gate PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE); 13170Sstevel@tonic-gate goto err; 13180Sstevel@tonic-gate } 13190Sstevel@tonic-gate pk11_dso = NULL; 13200Sstevel@tonic-gate pFuncList = NULL; 1321*7526SVladimir.Kotal@Sun.COM pk11_library_initialized = FALSE; 13227211Sjp161948 pk11_pid = 0; 1323*7526SVladimir.Kotal@Sun.COM pk11_free_all_locks(); 13240Sstevel@tonic-gate 13250Sstevel@tonic-gate return 1; 13260Sstevel@tonic-gate 13270Sstevel@tonic-gate err: 13280Sstevel@tonic-gate return 0; 13290Sstevel@tonic-gate } 13300Sstevel@tonic-gate 13310Sstevel@tonic-gate /* Standard engine interface function to set the dynamic library path */ 13320Sstevel@tonic-gate static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) 13330Sstevel@tonic-gate { 13340Sstevel@tonic-gate int initialized = ((pk11_dso == NULL) ? 0 : 1); 13350Sstevel@tonic-gate 13360Sstevel@tonic-gate switch(cmd) 13370Sstevel@tonic-gate { 13380Sstevel@tonic-gate case PK11_CMD_SO_PATH: 13390Sstevel@tonic-gate if (p == NULL) 13400Sstevel@tonic-gate { 13410Sstevel@tonic-gate PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); 13420Sstevel@tonic-gate return 0; 13430Sstevel@tonic-gate } 13440Sstevel@tonic-gate 13450Sstevel@tonic-gate if (initialized) 13460Sstevel@tonic-gate { 13470Sstevel@tonic-gate PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED); 13480Sstevel@tonic-gate return 0; 13490Sstevel@tonic-gate } 13500Sstevel@tonic-gate 13510Sstevel@tonic-gate return set_PK11_LIBNAME((const char*)p); 13520Sstevel@tonic-gate default: 13530Sstevel@tonic-gate break; 13540Sstevel@tonic-gate } 13550Sstevel@tonic-gate 13560Sstevel@tonic-gate PK11err(PK11_F_CTRL,PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED); 13570Sstevel@tonic-gate 13580Sstevel@tonic-gate return 0; 13590Sstevel@tonic-gate } 13600Sstevel@tonic-gate 13610Sstevel@tonic-gate 13620Sstevel@tonic-gate /* Required function by the engine random interface. It does nothing here 13630Sstevel@tonic-gate */ 13640Sstevel@tonic-gate static void pk11_rand_cleanup(void) 13650Sstevel@tonic-gate { 13660Sstevel@tonic-gate return; 13670Sstevel@tonic-gate } 13680Sstevel@tonic-gate 13690Sstevel@tonic-gate static void pk11_rand_add(const void *buf, int num, double add) 13700Sstevel@tonic-gate { 13710Sstevel@tonic-gate PK11_SESSION *sp; 13720Sstevel@tonic-gate 13737211Sjp161948 if ((sp = pk11_get_session(OP_RAND)) == NULL) 13740Sstevel@tonic-gate return; 13750Sstevel@tonic-gate 13760Sstevel@tonic-gate /* Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since 13770Sstevel@tonic-gate * the calling functions do not care anyway 13780Sstevel@tonic-gate */ 13790Sstevel@tonic-gate pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num); 13807211Sjp161948 pk11_return_session(sp, OP_RAND); 13810Sstevel@tonic-gate 13820Sstevel@tonic-gate return; 13830Sstevel@tonic-gate } 13840Sstevel@tonic-gate 13850Sstevel@tonic-gate static void pk11_rand_seed(const void *buf, int num) 13860Sstevel@tonic-gate { 13870Sstevel@tonic-gate pk11_rand_add(buf, num, 0); 13880Sstevel@tonic-gate } 13890Sstevel@tonic-gate 13900Sstevel@tonic-gate static int pk11_rand_bytes(unsigned char *buf, int num) 13910Sstevel@tonic-gate { 13920Sstevel@tonic-gate CK_RV rv; 13930Sstevel@tonic-gate PK11_SESSION *sp; 13940Sstevel@tonic-gate 13957211Sjp161948 if ((sp = pk11_get_session(OP_RAND)) == NULL) 13960Sstevel@tonic-gate return 0; 13970Sstevel@tonic-gate 13980Sstevel@tonic-gate rv = pFuncList->C_GenerateRandom(sp->session, buf, num); 13990Sstevel@tonic-gate if (rv != CKR_OK) 14000Sstevel@tonic-gate { 14017211Sjp161948 PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv); 14027211Sjp161948 pk11_return_session(sp, OP_RAND); 14030Sstevel@tonic-gate return 0; 14040Sstevel@tonic-gate } 14050Sstevel@tonic-gate 14067211Sjp161948 pk11_return_session(sp, OP_RAND); 14070Sstevel@tonic-gate return 1; 14080Sstevel@tonic-gate } 14090Sstevel@tonic-gate 14100Sstevel@tonic-gate /* Required function by the engine random interface. It does nothing here 14110Sstevel@tonic-gate */ 14120Sstevel@tonic-gate static int pk11_rand_status(void) 14130Sstevel@tonic-gate { 14140Sstevel@tonic-gate return 1; 14150Sstevel@tonic-gate } 14160Sstevel@tonic-gate 14176847Svk199839 /* 14186847Svk199839 * Free all BIGNUM structures from PK11_SESSION. 14196847Svk199839 */ 1420*7526SVladimir.Kotal@Sun.COM static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype) 14216847Svk199839 { 1422*7526SVladimir.Kotal@Sun.COM switch (optype) 1423*7526SVladimir.Kotal@Sun.COM { 14246847Svk199839 #ifndef OPENSSL_NO_RSA 1425*7526SVladimir.Kotal@Sun.COM case OP_RSA: 1426*7526SVladimir.Kotal@Sun.COM if (sp->opdata_rsa_n_num != NULL) 1427*7526SVladimir.Kotal@Sun.COM { 1428*7526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_rsa_n_num); 1429*7526SVladimir.Kotal@Sun.COM sp->opdata_rsa_n_num = NULL; 1430*7526SVladimir.Kotal@Sun.COM } 1431*7526SVladimir.Kotal@Sun.COM if (sp->opdata_rsa_e_num != NULL) 1432*7526SVladimir.Kotal@Sun.COM { 1433*7526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_rsa_e_num); 1434*7526SVladimir.Kotal@Sun.COM sp->opdata_rsa_e_num = NULL; 1435*7526SVladimir.Kotal@Sun.COM } 1436*7526SVladimir.Kotal@Sun.COM if (sp->opdata_rsa_d_num != NULL) 1437*7526SVladimir.Kotal@Sun.COM { 1438*7526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_rsa_d_num); 1439*7526SVladimir.Kotal@Sun.COM sp->opdata_rsa_d_num = NULL; 1440*7526SVladimir.Kotal@Sun.COM } 1441*7526SVladimir.Kotal@Sun.COM break; 14426847Svk199839 #endif 14436847Svk199839 #ifndef OPENSSL_NO_DSA 1444*7526SVladimir.Kotal@Sun.COM case OP_DSA: 1445*7526SVladimir.Kotal@Sun.COM if (sp->opdata_dsa_pub_num != NULL) 1446*7526SVladimir.Kotal@Sun.COM { 1447*7526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_dsa_pub_num); 1448*7526SVladimir.Kotal@Sun.COM sp->opdata_dsa_pub_num = NULL; 1449*7526SVladimir.Kotal@Sun.COM } 1450*7526SVladimir.Kotal@Sun.COM if (sp->opdata_dsa_priv_num != NULL) 1451*7526SVladimir.Kotal@Sun.COM { 1452*7526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_dsa_priv_num); 1453*7526SVladimir.Kotal@Sun.COM sp->opdata_dsa_priv_num = NULL; 1454*7526SVladimir.Kotal@Sun.COM } 1455*7526SVladimir.Kotal@Sun.COM break; 14566847Svk199839 #endif 14576847Svk199839 #ifndef OPENSSL_NO_DH 1458*7526SVladimir.Kotal@Sun.COM case OP_DH: 1459*7526SVladimir.Kotal@Sun.COM if (sp->opdata_dh_priv_num != NULL) 1460*7526SVladimir.Kotal@Sun.COM { 1461*7526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_dh_priv_num); 1462*7526SVladimir.Kotal@Sun.COM sp->opdata_dh_priv_num = NULL; 1463*7526SVladimir.Kotal@Sun.COM } 1464*7526SVladimir.Kotal@Sun.COM break; 14656847Svk199839 #endif 1466*7526SVladimir.Kotal@Sun.COM default: 1467*7526SVladimir.Kotal@Sun.COM break; 1468*7526SVladimir.Kotal@Sun.COM } 14696847Svk199839 } 14700Sstevel@tonic-gate 14716847Svk199839 /* 14726847Svk199839 * Get new PK11_SESSION structure ready for use. Every process must have 14736847Svk199839 * its own freelist of PK11_SESSION structures so handle fork() here 14746847Svk199839 * by destroying the old and creating new freelist. 14756847Svk199839 * The returned PK11_SESSION structure is disconnected from the freelist. 14766847Svk199839 */ 14777211Sjp161948 PK11_SESSION *pk11_get_session(PK11_OPTYPE optype) 14780Sstevel@tonic-gate { 1479*7526SVladimir.Kotal@Sun.COM PK11_SESSION *sp = NULL, *sp1, *freelist; 1480*7526SVladimir.Kotal@Sun.COM pthread_mutex_t *freelist_lock; 14810Sstevel@tonic-gate CK_RV rv; 14820Sstevel@tonic-gate 14837211Sjp161948 switch (optype) 14847211Sjp161948 { 1485*7526SVladimir.Kotal@Sun.COM case OP_RSA: 1486*7526SVladimir.Kotal@Sun.COM case OP_DSA: 1487*7526SVladimir.Kotal@Sun.COM case OP_DH: 14887211Sjp161948 case OP_RAND: 14897211Sjp161948 case OP_DIGEST: 14907211Sjp161948 case OP_CIPHER: 1491*7526SVladimir.Kotal@Sun.COM freelist_lock = session_cache[optype].lock; 14927211Sjp161948 break; 14937211Sjp161948 default: 14947211Sjp161948 PK11err(PK11_F_GET_SESSION, 14957211Sjp161948 PK11_R_INVALID_OPERATION_TYPE); 1496*7526SVladimir.Kotal@Sun.COM return (NULL); 14977211Sjp161948 } 1498*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_lock(freelist_lock); 1499*7526SVladimir.Kotal@Sun.COM freelist = session_cache[optype].head; 15007211Sjp161948 sp = freelist; 15017211Sjp161948 15026847Svk199839 /* 15036847Svk199839 * If the free list is empty, allocate new unitialized (filled 15046847Svk199839 * with zeroes) PK11_SESSION structure otherwise return first 15056847Svk199839 * structure from the freelist. 15066847Svk199839 */ 15077211Sjp161948 if (sp == NULL) 15080Sstevel@tonic-gate { 15090Sstevel@tonic-gate if ((sp = OPENSSL_malloc(sizeof(PK11_SESSION))) == NULL) 15100Sstevel@tonic-gate { 15110Sstevel@tonic-gate PK11err(PK11_F_GET_SESSION, 15120Sstevel@tonic-gate PK11_R_MALLOC_FAILURE); 15130Sstevel@tonic-gate goto err; 15140Sstevel@tonic-gate } 15150Sstevel@tonic-gate memset(sp, 0, sizeof(PK11_SESSION)); 15160Sstevel@tonic-gate } 15170Sstevel@tonic-gate else 15180Sstevel@tonic-gate { 15197211Sjp161948 freelist = sp->next; 15200Sstevel@tonic-gate } 15210Sstevel@tonic-gate 15220Sstevel@tonic-gate if (sp->pid != 0 && sp->pid != getpid()) 15230Sstevel@tonic-gate { 15246847Svk199839 /* 15256847Svk199839 * We are a new process and thus need to free any inherited 15260Sstevel@tonic-gate * PK11_SESSION objects. 15270Sstevel@tonic-gate */ 15287211Sjp161948 while ((sp1 = freelist) != NULL) 15290Sstevel@tonic-gate { 15307211Sjp161948 freelist = sp1->next; 15316847Svk199839 /* 15327211Sjp161948 * NOTE: we do not want to call pk11_free_all_sessions() 15337211Sjp161948 * here because it would close underlying PKCS#11 15347211Sjp161948 * sessions and destroy all objects. 15356847Svk199839 */ 1536*7526SVladimir.Kotal@Sun.COM pk11_free_nums(sp1, optype); 15370Sstevel@tonic-gate OPENSSL_free(sp1); 15380Sstevel@tonic-gate } 15390Sstevel@tonic-gate 1540*7526SVladimir.Kotal@Sun.COM /* we have to free the active list as well. */ 1541*7526SVladimir.Kotal@Sun.COM pk11_free_active_list(optype); 1542*7526SVladimir.Kotal@Sun.COM 15430Sstevel@tonic-gate /* Initialize the process */ 15440Sstevel@tonic-gate rv = pFuncList->C_Initialize(NULL_PTR); 15450Sstevel@tonic-gate if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) 15460Sstevel@tonic-gate { 15477211Sjp161948 PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE, 15487211Sjp161948 rv); 15490Sstevel@tonic-gate OPENSSL_free(sp); 15500Sstevel@tonic-gate sp = NULL; 15510Sstevel@tonic-gate goto err; 15520Sstevel@tonic-gate } 15530Sstevel@tonic-gate 15546847Svk199839 /* 15557211Sjp161948 * Choose slot here since the slot table is different on this 15567211Sjp161948 * process. If we are here then we must have found at least one 15577211Sjp161948 * usable slot before so we don't need to check any_slot_found. 15587211Sjp161948 * See pk11_library_init()'s usage of this function for more 15597211Sjp161948 * information. 15600Sstevel@tonic-gate */ 15617211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 15627211Sjp161948 if (check_hw_mechanisms() == 0) 15637211Sjp161948 goto err; 15647211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 15657211Sjp161948 if (pk11_choose_slots(NULL) == 0) 15660Sstevel@tonic-gate goto err; 15670Sstevel@tonic-gate 15680Sstevel@tonic-gate /* Open the global_session for the new process */ 15690Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 15700Sstevel@tonic-gate NULL_PTR, NULL_PTR, &global_session); 15710Sstevel@tonic-gate if (rv != CKR_OK) 15720Sstevel@tonic-gate { 15737211Sjp161948 PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION, 15747211Sjp161948 rv); 15750Sstevel@tonic-gate OPENSSL_free(sp); 15760Sstevel@tonic-gate sp = NULL; 15770Sstevel@tonic-gate goto err; 15780Sstevel@tonic-gate } 15790Sstevel@tonic-gate 15800Sstevel@tonic-gate /* It is an inherited session and needs re-initialization. 15810Sstevel@tonic-gate */ 15827211Sjp161948 if (pk11_setup_session(sp, optype) == 0) 15830Sstevel@tonic-gate { 15840Sstevel@tonic-gate OPENSSL_free(sp); 15850Sstevel@tonic-gate sp = NULL; 15860Sstevel@tonic-gate } 15870Sstevel@tonic-gate } 15880Sstevel@tonic-gate else if (sp->pid == 0) 15890Sstevel@tonic-gate { 15907211Sjp161948 /* It is a new session and needs initialization. */ 15917211Sjp161948 if (pk11_setup_session(sp, optype) == 0) 15920Sstevel@tonic-gate { 15930Sstevel@tonic-gate OPENSSL_free(sp); 15940Sstevel@tonic-gate sp = NULL; 15950Sstevel@tonic-gate } 15960Sstevel@tonic-gate } 15970Sstevel@tonic-gate 1598*7526SVladimir.Kotal@Sun.COM /* set new head for the list of PK11_SESSION objects */ 1599*7526SVladimir.Kotal@Sun.COM session_cache[optype].head = freelist; 16007211Sjp161948 16010Sstevel@tonic-gate err: 16026847Svk199839 if (sp != NULL) 16030Sstevel@tonic-gate sp->next = NULL; 16040Sstevel@tonic-gate 1605*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_unlock(freelist_lock); 16060Sstevel@tonic-gate 16070Sstevel@tonic-gate return sp; 16080Sstevel@tonic-gate } 16090Sstevel@tonic-gate 16100Sstevel@tonic-gate 16117211Sjp161948 void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype) 16120Sstevel@tonic-gate { 1613*7526SVladimir.Kotal@Sun.COM pthread_mutex_t *freelist_lock; 1614*7526SVladimir.Kotal@Sun.COM PK11_SESSION *freelist; 1615*7526SVladimir.Kotal@Sun.COM 16160Sstevel@tonic-gate if (sp == NULL || sp->pid != getpid()) 16170Sstevel@tonic-gate return; 16180Sstevel@tonic-gate 16197211Sjp161948 switch (optype) 16207211Sjp161948 { 1621*7526SVladimir.Kotal@Sun.COM case OP_RSA: 1622*7526SVladimir.Kotal@Sun.COM case OP_DSA: 1623*7526SVladimir.Kotal@Sun.COM case OP_DH: 16247211Sjp161948 case OP_RAND: 16257211Sjp161948 case OP_DIGEST: 16267211Sjp161948 case OP_CIPHER: 1627*7526SVladimir.Kotal@Sun.COM freelist_lock = session_cache[optype].lock; 16287211Sjp161948 break; 1629*7526SVladimir.Kotal@Sun.COM default: 1630*7526SVladimir.Kotal@Sun.COM PK11err(PK11_F_RETURN_SESSION, 1631*7526SVladimir.Kotal@Sun.COM PK11_R_INVALID_OPERATION_TYPE); 1632*7526SVladimir.Kotal@Sun.COM return; 16337211Sjp161948 } 16340Sstevel@tonic-gate 1635*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_lock(freelist_lock); 1636*7526SVladimir.Kotal@Sun.COM freelist = session_cache[optype].head; 1637*7526SVladimir.Kotal@Sun.COM sp->next = freelist; 1638*7526SVladimir.Kotal@Sun.COM session_cache[optype].head = sp; 1639*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_unlock(freelist_lock); 16400Sstevel@tonic-gate } 16410Sstevel@tonic-gate 16420Sstevel@tonic-gate 16430Sstevel@tonic-gate /* Destroy all objects. This function is called when the engine is finished 16440Sstevel@tonic-gate */ 16450Sstevel@tonic-gate static int pk11_free_all_sessions() 16460Sstevel@tonic-gate { 16477211Sjp161948 int ret = 1; 1648*7526SVladimir.Kotal@Sun.COM int type; 16490Sstevel@tonic-gate 16506847Svk199839 #ifndef OPENSSL_NO_RSA 16516847Svk199839 (void) pk11_destroy_rsa_key_objects(NULL); 16527211Sjp161948 #endif /* OPENSSL_NO_RSA */ 16536847Svk199839 #ifndef OPENSSL_NO_DSA 16546847Svk199839 (void) pk11_destroy_dsa_key_objects(NULL); 16557211Sjp161948 #endif /* OPENSSL_NO_DSA */ 16566847Svk199839 #ifndef OPENSSL_NO_DH 16576847Svk199839 (void) pk11_destroy_dh_key_objects(NULL); 16587211Sjp161948 #endif /* OPENSSL_NO_DH */ 16596847Svk199839 (void) pk11_destroy_cipher_key_objects(NULL); 16607211Sjp161948 16617211Sjp161948 /* 16627211Sjp161948 * We try to release as much as we can but any error means that we will 16637211Sjp161948 * return 0 on exit. 16647211Sjp161948 */ 1665*7526SVladimir.Kotal@Sun.COM for (type = 0; type < OP_MAX; type++) 1666*7526SVladimir.Kotal@Sun.COM { 1667*7526SVladimir.Kotal@Sun.COM if (pk11_free_session_list(type) == 0) 1668*7526SVladimir.Kotal@Sun.COM ret = 0; 1669*7526SVladimir.Kotal@Sun.COM } 16707211Sjp161948 16717211Sjp161948 return ret; 16727211Sjp161948 } 16730Sstevel@tonic-gate 16747211Sjp161948 /* 1675*7526SVladimir.Kotal@Sun.COM * Destroy session structures from the linked list specified. Free as many 1676*7526SVladimir.Kotal@Sun.COM * sessions as possible but any failure in C_CloseSession() means that we 1677*7526SVladimir.Kotal@Sun.COM * return an error on return. 16787211Sjp161948 */ 1679*7526SVladimir.Kotal@Sun.COM static int pk11_free_session_list(PK11_OPTYPE optype) 16807211Sjp161948 { 16817211Sjp161948 CK_RV rv; 16827211Sjp161948 PK11_SESSION *sp = NULL; 1683*7526SVladimir.Kotal@Sun.COM PK11_SESSION *freelist = NULL; 16847211Sjp161948 pid_t mypid = getpid(); 1685*7526SVladimir.Kotal@Sun.COM pthread_mutex_t *freelist_lock; 16867211Sjp161948 int ret = 1; 16877211Sjp161948 1688*7526SVladimir.Kotal@Sun.COM switch (optype) 1689*7526SVladimir.Kotal@Sun.COM { 1690*7526SVladimir.Kotal@Sun.COM case OP_RSA: 1691*7526SVladimir.Kotal@Sun.COM case OP_DSA: 1692*7526SVladimir.Kotal@Sun.COM case OP_DH: 1693*7526SVladimir.Kotal@Sun.COM case OP_RAND: 1694*7526SVladimir.Kotal@Sun.COM case OP_DIGEST: 1695*7526SVladimir.Kotal@Sun.COM case OP_CIPHER: 1696*7526SVladimir.Kotal@Sun.COM freelist_lock = session_cache[optype].lock; 1697*7526SVladimir.Kotal@Sun.COM break; 1698*7526SVladimir.Kotal@Sun.COM default: 1699*7526SVladimir.Kotal@Sun.COM PK11err(PK11_F_FREE_ALL_SESSIONS, 1700*7526SVladimir.Kotal@Sun.COM PK11_R_INVALID_OPERATION_TYPE); 1701*7526SVladimir.Kotal@Sun.COM return (0); 1702*7526SVladimir.Kotal@Sun.COM } 1703*7526SVladimir.Kotal@Sun.COM 1704*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_lock(freelist_lock); 1705*7526SVladimir.Kotal@Sun.COM freelist = session_cache[optype].head; 1706*7526SVladimir.Kotal@Sun.COM while ((sp = freelist) != NULL) 17070Sstevel@tonic-gate { 17080Sstevel@tonic-gate if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid) 17090Sstevel@tonic-gate { 17100Sstevel@tonic-gate rv = pFuncList->C_CloseSession(sp->session); 17110Sstevel@tonic-gate if (rv != CKR_OK) 17120Sstevel@tonic-gate { 17137211Sjp161948 PK11err_add_data(PK11_F_FREE_ALL_SESSIONS, 17147211Sjp161948 PK11_R_CLOSESESSION, rv); 17157211Sjp161948 ret = 0; 17160Sstevel@tonic-gate } 17170Sstevel@tonic-gate } 1718*7526SVladimir.Kotal@Sun.COM freelist = sp->next; 1719*7526SVladimir.Kotal@Sun.COM pk11_free_nums(sp, optype); 17200Sstevel@tonic-gate OPENSSL_free(sp); 17210Sstevel@tonic-gate } 17227211Sjp161948 1723*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_unlock(freelist_lock); 17240Sstevel@tonic-gate return ret; 17250Sstevel@tonic-gate } 17260Sstevel@tonic-gate 17270Sstevel@tonic-gate 17287211Sjp161948 static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype) 17290Sstevel@tonic-gate { 17300Sstevel@tonic-gate CK_RV rv; 17317211Sjp161948 CK_SLOT_ID myslot; 17327211Sjp161948 17337211Sjp161948 switch (optype) 17347211Sjp161948 { 1735*7526SVladimir.Kotal@Sun.COM case OP_RSA: 1736*7526SVladimir.Kotal@Sun.COM case OP_DSA: 1737*7526SVladimir.Kotal@Sun.COM case OP_DH: 17387211Sjp161948 myslot = pubkey_SLOTID; 17397211Sjp161948 break; 17407211Sjp161948 case OP_RAND: 17417211Sjp161948 myslot = rand_SLOTID; 17427211Sjp161948 break; 17437211Sjp161948 case OP_DIGEST: 17447211Sjp161948 case OP_CIPHER: 17457211Sjp161948 myslot = SLOTID; 17467211Sjp161948 break; 17477211Sjp161948 default: 17487211Sjp161948 PK11err(PK11_F_SETUP_SESSION, 17497211Sjp161948 PK11_R_INVALID_OPERATION_TYPE); 17507211Sjp161948 return 0; 17517211Sjp161948 } 17527211Sjp161948 17530Sstevel@tonic-gate sp->session = CK_INVALID_HANDLE; 17547211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 17557211Sjp161948 fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype); 17567211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 17577211Sjp161948 rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, 17580Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session); 17590Sstevel@tonic-gate if (rv == CKR_CRYPTOKI_NOT_INITIALIZED) 17600Sstevel@tonic-gate { 17610Sstevel@tonic-gate /* 17620Sstevel@tonic-gate * We are probably a child process so force the 17630Sstevel@tonic-gate * reinitialize of the session 17640Sstevel@tonic-gate */ 1765*7526SVladimir.Kotal@Sun.COM pk11_library_initialized = FALSE; 17660Sstevel@tonic-gate (void) pk11_library_init(NULL); 17677211Sjp161948 rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, 17680Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session); 17690Sstevel@tonic-gate } 17700Sstevel@tonic-gate if (rv != CKR_OK) 17710Sstevel@tonic-gate { 17727211Sjp161948 PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv); 17730Sstevel@tonic-gate return 0; 17740Sstevel@tonic-gate } 17750Sstevel@tonic-gate 1776*7526SVladimir.Kotal@Sun.COM sp->pid = getpid(); 1777*7526SVladimir.Kotal@Sun.COM 1778*7526SVladimir.Kotal@Sun.COM switch (optype) 17790Sstevel@tonic-gate { 17806847Svk199839 #ifndef OPENSSL_NO_RSA 1781*7526SVladimir.Kotal@Sun.COM case OP_RSA: 1782*7526SVladimir.Kotal@Sun.COM sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; 1783*7526SVladimir.Kotal@Sun.COM sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; 1784*7526SVladimir.Kotal@Sun.COM sp->opdata_rsa_pub = NULL; 1785*7526SVladimir.Kotal@Sun.COM sp->opdata_rsa_n_num = NULL; 1786*7526SVladimir.Kotal@Sun.COM sp->opdata_rsa_e_num = NULL; 1787*7526SVladimir.Kotal@Sun.COM sp->opdata_rsa_priv = NULL; 1788*7526SVladimir.Kotal@Sun.COM sp->opdata_rsa_d_num = NULL; 1789*7526SVladimir.Kotal@Sun.COM break; 17907211Sjp161948 #endif /* OPENSSL_NO_RSA */ 17916847Svk199839 #ifndef OPENSSL_NO_DSA 1792*7526SVladimir.Kotal@Sun.COM case OP_DSA: 1793*7526SVladimir.Kotal@Sun.COM sp->opdata_dsa_pub_key = CK_INVALID_HANDLE; 1794*7526SVladimir.Kotal@Sun.COM sp->opdata_dsa_priv_key = CK_INVALID_HANDLE; 1795*7526SVladimir.Kotal@Sun.COM sp->opdata_dsa_pub = NULL; 1796*7526SVladimir.Kotal@Sun.COM sp->opdata_dsa_pub_num = NULL; 1797*7526SVladimir.Kotal@Sun.COM sp->opdata_dsa_priv = NULL; 1798*7526SVladimir.Kotal@Sun.COM sp->opdata_dsa_priv_num = NULL; 1799*7526SVladimir.Kotal@Sun.COM break; 18007211Sjp161948 #endif /* OPENSSL_NO_DSA */ 18016847Svk199839 #ifndef OPENSSL_NO_DH 1802*7526SVladimir.Kotal@Sun.COM case OP_DH: 1803*7526SVladimir.Kotal@Sun.COM sp->opdata_dh_key = CK_INVALID_HANDLE; 1804*7526SVladimir.Kotal@Sun.COM sp->opdata_dh = NULL; 1805*7526SVladimir.Kotal@Sun.COM sp->opdata_dh_priv_num = NULL; 1806*7526SVladimir.Kotal@Sun.COM break; 18077211Sjp161948 #endif /* OPENSSL_NO_DH */ 1808*7526SVladimir.Kotal@Sun.COM case OP_CIPHER: 1809*7526SVladimir.Kotal@Sun.COM sp->opdata_cipher_key = CK_INVALID_HANDLE; 1810*7526SVladimir.Kotal@Sun.COM sp->opdata_encrypt = -1; 1811*7526SVladimir.Kotal@Sun.COM break; 1812*7526SVladimir.Kotal@Sun.COM } 18130Sstevel@tonic-gate 18140Sstevel@tonic-gate return 1; 18150Sstevel@tonic-gate } 18160Sstevel@tonic-gate 18176847Svk199839 #ifndef OPENSSL_NO_RSA 18186847Svk199839 /* Destroy RSA public key from single session. */ 18196847Svk199839 int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) 18206847Svk199839 { 18216847Svk199839 int ret = 0; 18226847Svk199839 1823*7526SVladimir.Kotal@Sun.COM if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE) 18246847Svk199839 { 1825*7526SVladimir.Kotal@Sun.COM TRY_OBJ_DESTROY(sp->session, sp->opdata_rsa_pub_key, 1826*7526SVladimir.Kotal@Sun.COM ret, uselock, OP_RSA); 1827*7526SVladimir.Kotal@Sun.COM sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; 1828*7526SVladimir.Kotal@Sun.COM sp->opdata_rsa_pub = NULL; 1829*7526SVladimir.Kotal@Sun.COM if (sp->opdata_rsa_n_num != NULL) 1830*7526SVladimir.Kotal@Sun.COM { 1831*7526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_rsa_n_num); 1832*7526SVladimir.Kotal@Sun.COM sp->opdata_rsa_n_num = NULL; 1833*7526SVladimir.Kotal@Sun.COM } 1834*7526SVladimir.Kotal@Sun.COM if (sp->opdata_rsa_e_num != NULL) 1835*7526SVladimir.Kotal@Sun.COM { 1836*7526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_rsa_e_num); 1837*7526SVladimir.Kotal@Sun.COM sp->opdata_rsa_e_num = NULL; 1838*7526SVladimir.Kotal@Sun.COM } 18396847Svk199839 } 18406847Svk199839 18416847Svk199839 return (ret); 18426847Svk199839 } 18436847Svk199839 18446847Svk199839 /* Destroy RSA private key from single session. */ 18456847Svk199839 int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) 18460Sstevel@tonic-gate { 18470Sstevel@tonic-gate int ret = 0; 18486847Svk199839 1849*7526SVladimir.Kotal@Sun.COM if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE) 18506847Svk199839 { 1851*7526SVladimir.Kotal@Sun.COM TRY_OBJ_DESTROY(sp->session, sp->opdata_rsa_priv_key, 1852*7526SVladimir.Kotal@Sun.COM ret, uselock, OP_RSA); 1853*7526SVladimir.Kotal@Sun.COM sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; 1854*7526SVladimir.Kotal@Sun.COM sp->opdata_rsa_priv = NULL; 1855*7526SVladimir.Kotal@Sun.COM if (sp->opdata_rsa_d_num != NULL) 1856*7526SVladimir.Kotal@Sun.COM { 1857*7526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_rsa_d_num); 1858*7526SVladimir.Kotal@Sun.COM sp->opdata_rsa_d_num = NULL; 1859*7526SVladimir.Kotal@Sun.COM } 18606847Svk199839 } 18616847Svk199839 18626847Svk199839 return (ret); 18636847Svk199839 } 18646847Svk199839 18656847Svk199839 /* 18667211Sjp161948 * Destroy RSA key object wrapper. If session is NULL, try to destroy all 18677211Sjp161948 * objects in the free list. 18686847Svk199839 */ 18696847Svk199839 int pk11_destroy_rsa_key_objects(PK11_SESSION *session) 18706847Svk199839 { 18716847Svk199839 int ret = 1; 18720Sstevel@tonic-gate PK11_SESSION *sp = NULL; 18730Sstevel@tonic-gate PK11_SESSION *local_free_session; 18746847Svk199839 CK_BBOOL uselock = TRUE; 18750Sstevel@tonic-gate 18766847Svk199839 if (session != NULL) 18770Sstevel@tonic-gate local_free_session = session; 18780Sstevel@tonic-gate else 18796847Svk199839 { 1880*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_lock(session_cache[OP_RSA].lock); 1881*7526SVladimir.Kotal@Sun.COM local_free_session = session_cache[OP_RSA].head; 18826847Svk199839 uselock = FALSE; 18836847Svk199839 } 18840Sstevel@tonic-gate 18856847Svk199839 /* 18866847Svk199839 * go through the list of sessions and delete key objects 18876847Svk199839 */ 18880Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 18890Sstevel@tonic-gate { 18900Sstevel@tonic-gate local_free_session = sp->next; 18910Sstevel@tonic-gate 18926847Svk199839 /* 18936847Svk199839 * Do not terminate list traversal if one of the 18946847Svk199839 * destroy operations fails. 18956847Svk199839 */ 18966847Svk199839 if (pk11_destroy_rsa_object_pub(sp, uselock) == 0) 18970Sstevel@tonic-gate { 18986847Svk199839 ret = 0; 18996847Svk199839 continue; 19000Sstevel@tonic-gate } 19016847Svk199839 if (pk11_destroy_rsa_object_priv(sp, uselock) == 0) 19026847Svk199839 { 19036847Svk199839 ret = 0; 19046847Svk199839 continue; 19056847Svk199839 } 19066847Svk199839 } 19070Sstevel@tonic-gate 19086847Svk199839 if (session == NULL) 1909*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_unlock(session_cache[OP_RSA].lock); 19100Sstevel@tonic-gate 19110Sstevel@tonic-gate return ret; 19120Sstevel@tonic-gate } 19137211Sjp161948 #endif /* OPENSSL_NO_RSA */ 19140Sstevel@tonic-gate 19156847Svk199839 #ifndef OPENSSL_NO_DSA 19166847Svk199839 /* Destroy DSA public key from single session. */ 19176847Svk199839 int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) 19180Sstevel@tonic-gate { 19190Sstevel@tonic-gate int ret = 0; 19206847Svk199839 1921*7526SVladimir.Kotal@Sun.COM if (sp->opdata_dsa_pub_key != CK_INVALID_HANDLE) 19226847Svk199839 { 1923*7526SVladimir.Kotal@Sun.COM TRY_OBJ_DESTROY(sp->session, sp->opdata_dsa_pub_key, 1924*7526SVladimir.Kotal@Sun.COM ret, uselock, OP_DSA); 1925*7526SVladimir.Kotal@Sun.COM sp->opdata_dsa_pub_key = CK_INVALID_HANDLE; 1926*7526SVladimir.Kotal@Sun.COM sp->opdata_dsa_pub = NULL; 1927*7526SVladimir.Kotal@Sun.COM if (sp->opdata_dsa_pub_num != NULL) 1928*7526SVladimir.Kotal@Sun.COM { 1929*7526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_dsa_pub_num); 1930*7526SVladimir.Kotal@Sun.COM sp->opdata_dsa_pub_num = NULL; 1931*7526SVladimir.Kotal@Sun.COM } 19326847Svk199839 } 19336847Svk199839 19346847Svk199839 return (ret); 19356847Svk199839 } 19366847Svk199839 19376847Svk199839 /* Destroy DSA private key from single session. */ 19386847Svk199839 int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) 19396847Svk199839 { 19406847Svk199839 int ret = 0; 19416847Svk199839 1942*7526SVladimir.Kotal@Sun.COM if (sp->opdata_dsa_priv_key != CK_INVALID_HANDLE) 19436847Svk199839 { 1944*7526SVladimir.Kotal@Sun.COM TRY_OBJ_DESTROY(sp->session, sp->opdata_dsa_priv_key, 1945*7526SVladimir.Kotal@Sun.COM ret, uselock, OP_DSA); 1946*7526SVladimir.Kotal@Sun.COM sp->opdata_dsa_priv_key = CK_INVALID_HANDLE; 1947*7526SVladimir.Kotal@Sun.COM sp->opdata_dsa_priv = NULL; 1948*7526SVladimir.Kotal@Sun.COM if (sp->opdata_dsa_priv_num != NULL) 1949*7526SVladimir.Kotal@Sun.COM { 1950*7526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_dsa_priv_num); 1951*7526SVladimir.Kotal@Sun.COM sp->opdata_dsa_priv_num = NULL; 1952*7526SVladimir.Kotal@Sun.COM } 19536847Svk199839 } 19546847Svk199839 19556847Svk199839 return (ret); 19566847Svk199839 } 19576847Svk199839 19586847Svk199839 /* 19597211Sjp161948 * Destroy DSA key object wrapper. If session is NULL, try to destroy all 19607211Sjp161948 * objects in the free list. 19616847Svk199839 */ 19626847Svk199839 int pk11_destroy_dsa_key_objects(PK11_SESSION *session) 19636847Svk199839 { 19646847Svk199839 int ret = 1; 19650Sstevel@tonic-gate PK11_SESSION *sp = NULL; 19660Sstevel@tonic-gate PK11_SESSION *local_free_session; 19676847Svk199839 CK_BBOOL uselock = TRUE; 19680Sstevel@tonic-gate 19696847Svk199839 if (session != NULL) 19700Sstevel@tonic-gate local_free_session = session; 19710Sstevel@tonic-gate else 19726847Svk199839 { 1973*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_lock(session_cache[OP_DSA].lock); 1974*7526SVladimir.Kotal@Sun.COM local_free_session = session_cache[OP_DSA].head; 19756847Svk199839 uselock = FALSE; 19766847Svk199839 } 19776847Svk199839 19786847Svk199839 /* 19796847Svk199839 * go through the list of sessions and delete key objects 19806847Svk199839 */ 19810Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 19820Sstevel@tonic-gate { 19830Sstevel@tonic-gate local_free_session = sp->next; 19840Sstevel@tonic-gate 19856847Svk199839 /* 19866847Svk199839 * Do not terminate list traversal if one of the 19876847Svk199839 * destroy operations fails. 19886847Svk199839 */ 19896847Svk199839 if (pk11_destroy_dsa_object_pub(sp, uselock) == 0) 19900Sstevel@tonic-gate { 19916847Svk199839 ret = 0; 19926847Svk199839 continue; 19930Sstevel@tonic-gate } 19946847Svk199839 if (pk11_destroy_dsa_object_priv(sp, uselock) == 0) 19956847Svk199839 { 19966847Svk199839 ret = 0; 19976847Svk199839 continue; 19986847Svk199839 } 19990Sstevel@tonic-gate } 20006847Svk199839 20016847Svk199839 if (session == NULL) 2002*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_unlock(session_cache[OP_DSA].lock); 20030Sstevel@tonic-gate 20040Sstevel@tonic-gate return ret; 20050Sstevel@tonic-gate } 20067211Sjp161948 #endif /* OPENSSL_NO_DSA */ 20076847Svk199839 20086847Svk199839 #ifndef OPENSSL_NO_DH 20096847Svk199839 /* Destroy DH key from single session. */ 20106847Svk199839 int pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock) 20116847Svk199839 { 20126847Svk199839 int ret = 0; 20136847Svk199839 2014*7526SVladimir.Kotal@Sun.COM if (sp->opdata_dh_key != CK_INVALID_HANDLE) 20156847Svk199839 { 2016*7526SVladimir.Kotal@Sun.COM TRY_OBJ_DESTROY(sp->session, sp->opdata_dh_key, 2017*7526SVladimir.Kotal@Sun.COM ret, uselock, OP_DH); 2018*7526SVladimir.Kotal@Sun.COM sp->opdata_dh_key = CK_INVALID_HANDLE; 2019*7526SVladimir.Kotal@Sun.COM sp->opdata_dh = NULL; 2020*7526SVladimir.Kotal@Sun.COM if (sp->opdata_dh_priv_num != NULL) 2021*7526SVladimir.Kotal@Sun.COM { 2022*7526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_dh_priv_num); 2023*7526SVladimir.Kotal@Sun.COM sp->opdata_dh_priv_num = NULL; 2024*7526SVladimir.Kotal@Sun.COM } 20256847Svk199839 } 20266847Svk199839 20276847Svk199839 return (ret); 20286847Svk199839 } 20296847Svk199839 20306847Svk199839 /* 20316847Svk199839 * Destroy DH key object wrapper. 20326847Svk199839 * 20336847Svk199839 * arg0: pointer to PKCS#11 engine session structure 20346847Svk199839 * if session is NULL, try to destroy all objects in the free list 20356847Svk199839 */ 20366847Svk199839 int pk11_destroy_dh_key_objects(PK11_SESSION *session) 20376847Svk199839 { 20386847Svk199839 int ret = 1; 20396847Svk199839 PK11_SESSION *sp = NULL; 20406847Svk199839 PK11_SESSION *local_free_session; 20416847Svk199839 CK_BBOOL uselock = TRUE; 20426847Svk199839 20436847Svk199839 if (session != NULL) 20446847Svk199839 local_free_session = session; 20456847Svk199839 else 20466847Svk199839 { 2047*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_lock(session_cache[OP_DH].lock); 2048*7526SVladimir.Kotal@Sun.COM local_free_session = session_cache[OP_DH].head; 20496847Svk199839 uselock = FALSE; 20506847Svk199839 } 20516847Svk199839 20526847Svk199839 while ((sp = local_free_session) != NULL) 20536847Svk199839 { 20546847Svk199839 local_free_session = sp->next; 20556847Svk199839 20566847Svk199839 /* 20576847Svk199839 * Do not terminate list traversal if one of the 20586847Svk199839 * destroy operations fails. 20596847Svk199839 */ 20606847Svk199839 if (pk11_destroy_dh_object(sp, uselock) == 0) 20616847Svk199839 { 20626847Svk199839 ret = 0; 20636847Svk199839 continue; 20646847Svk199839 } 20656847Svk199839 } 20666847Svk199839 err: 20676847Svk199839 if (session == NULL) 2068*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_unlock(session_cache[OP_DH].lock); 20696847Svk199839 20706847Svk199839 return ret; 20716847Svk199839 } 20727211Sjp161948 #endif /* OPENSSL_NO_DH */ 20730Sstevel@tonic-gate 20740Sstevel@tonic-gate static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh) 20750Sstevel@tonic-gate { 20760Sstevel@tonic-gate CK_RV rv; 20770Sstevel@tonic-gate rv = pFuncList->C_DestroyObject(session, oh); 20780Sstevel@tonic-gate if (rv != CKR_OK) 20790Sstevel@tonic-gate { 20807211Sjp161948 PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT, 20817211Sjp161948 rv); 20820Sstevel@tonic-gate return 0; 20830Sstevel@tonic-gate } 20840Sstevel@tonic-gate 20850Sstevel@tonic-gate return 1; 20860Sstevel@tonic-gate } 20870Sstevel@tonic-gate 20880Sstevel@tonic-gate 20890Sstevel@tonic-gate /* Symmetric ciphers and digests support functions 20900Sstevel@tonic-gate */ 20910Sstevel@tonic-gate 20920Sstevel@tonic-gate static int 20930Sstevel@tonic-gate cipher_nid_to_pk11(int nid) 20940Sstevel@tonic-gate { 20950Sstevel@tonic-gate int i; 20960Sstevel@tonic-gate 20970Sstevel@tonic-gate for (i = 0; i < PK11_CIPHER_MAX; i++) 20980Sstevel@tonic-gate if (ciphers[i].nid == nid) 20990Sstevel@tonic-gate return (ciphers[i].id); 21000Sstevel@tonic-gate return (-1); 21010Sstevel@tonic-gate } 21020Sstevel@tonic-gate 21030Sstevel@tonic-gate static int 21040Sstevel@tonic-gate pk11_usable_ciphers(const int **nids) 21050Sstevel@tonic-gate { 21060Sstevel@tonic-gate if (cipher_count > 0) 21070Sstevel@tonic-gate *nids = cipher_nids; 21080Sstevel@tonic-gate else 21090Sstevel@tonic-gate *nids = NULL; 21100Sstevel@tonic-gate return (cipher_count); 21110Sstevel@tonic-gate } 21120Sstevel@tonic-gate 21130Sstevel@tonic-gate static int 21140Sstevel@tonic-gate pk11_usable_digests(const int **nids) 21150Sstevel@tonic-gate { 21160Sstevel@tonic-gate if (digest_count > 0) 21170Sstevel@tonic-gate *nids = digest_nids; 21180Sstevel@tonic-gate else 21190Sstevel@tonic-gate *nids = NULL; 21200Sstevel@tonic-gate return (digest_count); 21210Sstevel@tonic-gate } 21220Sstevel@tonic-gate 21237211Sjp161948 /* 21247211Sjp161948 * Init context for encryption or decryption using a symmetric key. 21257211Sjp161948 */ 21267211Sjp161948 static int pk11_init_symmetric(EVP_CIPHER_CTX *ctx, PK11_CIPHER *pcipher, 21277211Sjp161948 PK11_SESSION *sp, CK_MECHANISM_PTR pmech) 21287211Sjp161948 { 21297211Sjp161948 CK_RV rv; 21307211Sjp161948 #ifdef SOLARIS_AES_CTR 21317211Sjp161948 CK_AES_CTR_PARAMS ctr_params; 21327211Sjp161948 #endif /* SOLARIS_AES_CTR */ 21337211Sjp161948 21347211Sjp161948 /* 21357211Sjp161948 * We expect pmech->mechanism to be already set and 21367211Sjp161948 * pParameter/ulParameterLen initialized to NULL/0 before 21377211Sjp161948 * pk11_init_symetric() is called. 21387211Sjp161948 */ 21397211Sjp161948 OPENSSL_assert(pmech->mechanism != NULL); 21407211Sjp161948 OPENSSL_assert(pmech->pParameter == NULL); 21417211Sjp161948 OPENSSL_assert(pmech->ulParameterLen == 0); 21427211Sjp161948 21437211Sjp161948 #ifdef SOLARIS_AES_CTR 21447211Sjp161948 if (ctx->cipher->nid == NID_aes_128_ctr || 21457211Sjp161948 ctx->cipher->nid == NID_aes_192_ctr || 21467211Sjp161948 ctx->cipher->nid == NID_aes_256_ctr) 21477211Sjp161948 { 21487211Sjp161948 pmech->pParameter = (void *)(&ctr_params); 21497211Sjp161948 pmech->ulParameterLen = sizeof(ctr_params); 21507211Sjp161948 /* 21517211Sjp161948 * For now, we are limited to the fixed length of the counter, 21527211Sjp161948 * it covers the whole counter block. That's what RFC 4344 21537211Sjp161948 * needs. For more information on internal structure of the 21547211Sjp161948 * counter block, see RFC 3686. If needed in the future, we can 21557211Sjp161948 * add code so that the counter length can be set via 21567211Sjp161948 * ENGINE_ctrl() function. 21577211Sjp161948 */ 21587211Sjp161948 ctr_params.ulCounterBits = AES_BLOCK_SIZE * 8; 21597211Sjp161948 OPENSSL_assert(pcipher->iv_len == AES_BLOCK_SIZE); 21607211Sjp161948 memcpy(ctr_params.cb, ctx->iv, AES_BLOCK_SIZE); 21617211Sjp161948 } 21627211Sjp161948 else 21637211Sjp161948 #endif /* SOLARIS_AES_CTR */ 21647211Sjp161948 { 21657211Sjp161948 if (pcipher->iv_len > 0) 21667211Sjp161948 { 21677211Sjp161948 pmech->pParameter = (void *)ctx->iv; 21687211Sjp161948 pmech->ulParameterLen = pcipher->iv_len; 21697211Sjp161948 } 21707211Sjp161948 } 21717211Sjp161948 21727211Sjp161948 /* if we get here, the encryption needs to be reinitialized */ 21737211Sjp161948 if (ctx->encrypt) 2174*7526SVladimir.Kotal@Sun.COM rv = pFuncList->C_EncryptInit(sp->session, pmech, 2175*7526SVladimir.Kotal@Sun.COM sp->opdata_cipher_key); 21767211Sjp161948 else 2177*7526SVladimir.Kotal@Sun.COM rv = pFuncList->C_DecryptInit(sp->session, pmech, 2178*7526SVladimir.Kotal@Sun.COM sp->opdata_cipher_key); 21797211Sjp161948 21807211Sjp161948 if (rv != CKR_OK) 21817211Sjp161948 { 21827211Sjp161948 PK11err_add_data(PK11_F_CIPHER_INIT, ctx->encrypt ? 21837211Sjp161948 PK11_R_ENCRYPTINIT : PK11_R_DECRYPTINIT, rv); 21847211Sjp161948 pk11_return_session(sp, OP_CIPHER); 21857211Sjp161948 return (0); 21867211Sjp161948 } 21877211Sjp161948 21887211Sjp161948 return (1); 21897211Sjp161948 } 21907211Sjp161948 21910Sstevel@tonic-gate static int 21920Sstevel@tonic-gate pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, 21930Sstevel@tonic-gate const unsigned char *iv, int enc) 21940Sstevel@tonic-gate { 21954320Sjp161948 CK_MECHANISM mech; 21960Sstevel@tonic-gate int index; 21970Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; 21980Sstevel@tonic-gate PK11_SESSION *sp; 21997211Sjp161948 PK11_CIPHER *p_ciph_table_row; 22000Sstevel@tonic-gate 22010Sstevel@tonic-gate state->sp = NULL; 22020Sstevel@tonic-gate 22030Sstevel@tonic-gate index = cipher_nid_to_pk11(ctx->cipher->nid); 22040Sstevel@tonic-gate if (index < 0 || index >= PK11_CIPHER_MAX) 22050Sstevel@tonic-gate return 0; 22060Sstevel@tonic-gate 22077211Sjp161948 p_ciph_table_row = &ciphers[index]; 22087211Sjp161948 /* 22097211Sjp161948 * iv_len in the ctx->cipher structure is the maximum IV length for the 22107211Sjp161948 * current cipher and it must be less or equal to the IV length in our 22117211Sjp161948 * ciphers table. The key length must match precisely. Every application 22127211Sjp161948 * can define its own EVP functions so this code serves as a sanity 22137211Sjp161948 * check. 22147211Sjp161948 * 22157211Sjp161948 * Note that the reason why the IV length in ctx->cipher might be 22167211Sjp161948 * greater than the actual length is that OpenSSL uses BLOCK_CIPHER_defs 22177211Sjp161948 * macro to define functions that return EVP structures for all DES 22187211Sjp161948 * modes. So, even ECB modes get 8 byte IV. 22197211Sjp161948 */ 22207211Sjp161948 if (ctx->cipher->iv_len < p_ciph_table_row->iv_len || 22217211Sjp161948 ctx->key_len != p_ciph_table_row->key_len) 22227211Sjp161948 { 22237211Sjp161948 PK11err(PK11_F_CIPHER_INIT, PK11_R_KEY_OR_IV_LEN_PROBLEM); 22240Sstevel@tonic-gate return 0; 22257211Sjp161948 } 22267211Sjp161948 22277211Sjp161948 if ((sp = pk11_get_session(OP_CIPHER)) == NULL) 22280Sstevel@tonic-gate return 0; 22290Sstevel@tonic-gate 22304320Sjp161948 /* if applicable, the mechanism parameter is used for IV */ 22317211Sjp161948 mech.mechanism = p_ciph_table_row->mech_type; 22324320Sjp161948 mech.pParameter = NULL; 22334320Sjp161948 mech.ulParameterLen = 0; 22344320Sjp161948 22350Sstevel@tonic-gate /* The key object is destroyed here if it is not the current key 22360Sstevel@tonic-gate */ 22377211Sjp161948 (void) check_new_cipher_key(sp, key, p_ciph_table_row->key_len); 22380Sstevel@tonic-gate 22390Sstevel@tonic-gate /* If the key is the same and the encryption is also the same, 22406847Svk199839 * then just reuse it. However, we must not forget to reinitialize the 22416847Svk199839 * context that was finalized in pk11_cipher_cleanup(). 22420Sstevel@tonic-gate */ 2243*7526SVladimir.Kotal@Sun.COM if (sp->opdata_cipher_key != CK_INVALID_HANDLE && 2244*7526SVladimir.Kotal@Sun.COM sp->opdata_encrypt == ctx->encrypt) 22450Sstevel@tonic-gate { 22460Sstevel@tonic-gate state->sp = sp; 22477211Sjp161948 if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0) 22486847Svk199839 return (0); 22496847Svk199839 22506847Svk199839 return (1); 22510Sstevel@tonic-gate } 22520Sstevel@tonic-gate 22530Sstevel@tonic-gate /* Check if the key has been invalidated. If so, a new key object 22540Sstevel@tonic-gate * needs to be created. 22550Sstevel@tonic-gate */ 2256*7526SVladimir.Kotal@Sun.COM if (sp->opdata_cipher_key == CK_INVALID_HANDLE) 22570Sstevel@tonic-gate { 2258*7526SVladimir.Kotal@Sun.COM sp->opdata_cipher_key = pk11_get_cipher_key( 22597211Sjp161948 ctx, key, p_ciph_table_row->key_type, sp); 22600Sstevel@tonic-gate } 22610Sstevel@tonic-gate 2262*7526SVladimir.Kotal@Sun.COM if (sp->opdata_encrypt != ctx->encrypt && sp->opdata_encrypt != -1) 22630Sstevel@tonic-gate { 22640Sstevel@tonic-gate /* The previous encryption/decryption 22650Sstevel@tonic-gate * is different. Need to terminate the previous 22660Sstevel@tonic-gate * active encryption/decryption here 22670Sstevel@tonic-gate */ 22680Sstevel@tonic-gate if (!pk11_cipher_final(sp)) 22690Sstevel@tonic-gate { 22707211Sjp161948 pk11_return_session(sp, OP_CIPHER); 22710Sstevel@tonic-gate return 0; 22720Sstevel@tonic-gate } 22730Sstevel@tonic-gate } 22740Sstevel@tonic-gate 2275*7526SVladimir.Kotal@Sun.COM if (sp->opdata_cipher_key == CK_INVALID_HANDLE) 22760Sstevel@tonic-gate { 22777211Sjp161948 pk11_return_session(sp, OP_CIPHER); 22780Sstevel@tonic-gate return 0; 22790Sstevel@tonic-gate } 22800Sstevel@tonic-gate 22816847Svk199839 /* now initialize the context with a new key */ 22827211Sjp161948 if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0) 22836847Svk199839 return (0); 22840Sstevel@tonic-gate 2285*7526SVladimir.Kotal@Sun.COM sp->opdata_encrypt = ctx->encrypt; 22860Sstevel@tonic-gate state->sp = sp; 22870Sstevel@tonic-gate 22880Sstevel@tonic-gate return 1; 22890Sstevel@tonic-gate } 22900Sstevel@tonic-gate 22910Sstevel@tonic-gate /* When reusing the same key in an encryption/decryption session for a 22920Sstevel@tonic-gate * decryption/encryption session, we need to close the active session 22930Sstevel@tonic-gate * and recreate a new one. Note that the key is in the global session so 22940Sstevel@tonic-gate * that it needs not be recreated. 22950Sstevel@tonic-gate * 22960Sstevel@tonic-gate * It is more appropriate to use C_En/DecryptFinish here. At the time of this 22970Sstevel@tonic-gate * development, these two functions in the PKCS#11 libraries used return 22980Sstevel@tonic-gate * unexpected errors when passing in 0 length output. It may be a good 22990Sstevel@tonic-gate * idea to try them again if performance is a problem here and fix 23000Sstevel@tonic-gate * C_En/DecryptFinial if there are bugs there causing the problem. 23010Sstevel@tonic-gate */ 23020Sstevel@tonic-gate static int 23030Sstevel@tonic-gate pk11_cipher_final(PK11_SESSION *sp) 23040Sstevel@tonic-gate { 23050Sstevel@tonic-gate CK_RV rv; 23060Sstevel@tonic-gate 2307*7526SVladimir.Kotal@Sun.COM rv = pFuncList->C_CloseSession(sp->session); 23080Sstevel@tonic-gate if (rv != CKR_OK) 23090Sstevel@tonic-gate { 23107211Sjp161948 PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_CLOSESESSION, rv); 23110Sstevel@tonic-gate return 0; 23120Sstevel@tonic-gate } 23130Sstevel@tonic-gate 23140Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 2315*7526SVladimir.Kotal@Sun.COM NULL_PTR, NULL_PTR, &sp->session); 23160Sstevel@tonic-gate if (rv != CKR_OK) 23170Sstevel@tonic-gate { 23187211Sjp161948 PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_OPENSESSION, rv); 23190Sstevel@tonic-gate return 0; 23200Sstevel@tonic-gate } 23210Sstevel@tonic-gate 23220Sstevel@tonic-gate return 1; 23230Sstevel@tonic-gate } 23240Sstevel@tonic-gate 23250Sstevel@tonic-gate /* An engine interface function. The calling function allocates sufficient 23260Sstevel@tonic-gate * memory for the output buffer "out" to hold the results */ 23270Sstevel@tonic-gate static int 23280Sstevel@tonic-gate pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 23290Sstevel@tonic-gate const unsigned char *in, unsigned int inl) 23300Sstevel@tonic-gate { 23310Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; 23320Sstevel@tonic-gate PK11_SESSION *sp; 23330Sstevel@tonic-gate CK_RV rv; 23340Sstevel@tonic-gate unsigned long outl = inl; 23350Sstevel@tonic-gate 23360Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 23370Sstevel@tonic-gate return 0; 23380Sstevel@tonic-gate 23390Sstevel@tonic-gate sp = (PK11_SESSION *) state->sp; 23400Sstevel@tonic-gate 23410Sstevel@tonic-gate if (!inl) 23420Sstevel@tonic-gate return 1; 23430Sstevel@tonic-gate 23440Sstevel@tonic-gate /* RC4 is the only stream cipher we support */ 23450Sstevel@tonic-gate if (ctx->cipher->nid != NID_rc4 && (inl % ctx->cipher->block_size) != 0) 23460Sstevel@tonic-gate return 0; 23470Sstevel@tonic-gate 23480Sstevel@tonic-gate if (ctx->encrypt) 23490Sstevel@tonic-gate { 2350*7526SVladimir.Kotal@Sun.COM rv = pFuncList->C_EncryptUpdate(sp->session, 23510Sstevel@tonic-gate (unsigned char *)in, inl, out, &outl); 23520Sstevel@tonic-gate 23530Sstevel@tonic-gate if (rv != CKR_OK) 23540Sstevel@tonic-gate { 23557211Sjp161948 PK11err_add_data(PK11_F_CIPHER_DO_CIPHER, 23567211Sjp161948 PK11_R_ENCRYPTUPDATE, rv); 23570Sstevel@tonic-gate return 0; 23580Sstevel@tonic-gate } 23590Sstevel@tonic-gate } 23600Sstevel@tonic-gate else 23610Sstevel@tonic-gate { 2362*7526SVladimir.Kotal@Sun.COM rv = pFuncList->C_DecryptUpdate(sp->session, 23630Sstevel@tonic-gate (unsigned char *)in, inl, out, &outl); 23640Sstevel@tonic-gate 23650Sstevel@tonic-gate if (rv != CKR_OK) 23660Sstevel@tonic-gate { 23677211Sjp161948 PK11err_add_data(PK11_F_CIPHER_DO_CIPHER, 23687211Sjp161948 PK11_R_DECRYPTUPDATE, rv); 23690Sstevel@tonic-gate return 0; 23700Sstevel@tonic-gate } 23710Sstevel@tonic-gate } 23720Sstevel@tonic-gate 23730Sstevel@tonic-gate /* for DES_CBC, DES3_CBC, AES_CBC, and RC4, the output size is always 23740Sstevel@tonic-gate * the same size of input 23750Sstevel@tonic-gate * The application has guaranteed to call the block ciphers with 23760Sstevel@tonic-gate * correctly aligned buffers. 23770Sstevel@tonic-gate */ 23780Sstevel@tonic-gate if (inl != outl) 23790Sstevel@tonic-gate return 0; 23800Sstevel@tonic-gate 23810Sstevel@tonic-gate return 1; 23820Sstevel@tonic-gate } 23830Sstevel@tonic-gate 23846847Svk199839 /* 23857211Sjp161948 * Return the session to the pool. Calling C_EncryptFinal() and C_DecryptFinal() 23867211Sjp161948 * here is the right thing because in EVP_DecryptFinal_ex(), engine's 23877211Sjp161948 * do_cipher() is not even called, and in EVP_EncryptFinal_ex() it is called but 23887211Sjp161948 * the engine can't find out that it's the finalizing call. We wouldn't 23897211Sjp161948 * necessarily have to finalize the context here since reinitializing it with 23907211Sjp161948 * C_(Encrypt|Decrypt)Init() should be fine but for the sake of correctness, 23917211Sjp161948 * let's do it. Some implementations might leak memory if the previously used 23927211Sjp161948 * context is initialized without finalizing it first. 23930Sstevel@tonic-gate */ 23940Sstevel@tonic-gate static int 23950Sstevel@tonic-gate pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx) 23960Sstevel@tonic-gate { 23976847Svk199839 CK_RV rv; 23987211Sjp161948 CK_ULONG len = EVP_MAX_BLOCK_LENGTH; 23996847Svk199839 CK_BYTE buf[EVP_MAX_BLOCK_LENGTH]; 24000Sstevel@tonic-gate PK11_CIPHER_STATE *state = ctx->cipher_data; 24010Sstevel@tonic-gate 24020Sstevel@tonic-gate if (state != NULL && state->sp != NULL) 24030Sstevel@tonic-gate { 24046847Svk199839 /* 24056847Svk199839 * We are not interested in the data here, we just need to get 24066847Svk199839 * rid of the context. 24076847Svk199839 */ 24086847Svk199839 if (ctx->encrypt) 24096847Svk199839 rv = pFuncList->C_EncryptFinal( 2410*7526SVladimir.Kotal@Sun.COM state->sp->session, buf, &len); 24116847Svk199839 else 24126847Svk199839 rv = pFuncList->C_DecryptFinal( 2413*7526SVladimir.Kotal@Sun.COM state->sp->session, buf, &len); 24146847Svk199839 24156847Svk199839 if (rv != CKR_OK) 24166847Svk199839 { 24177211Sjp161948 PK11err_add_data(PK11_F_CIPHER_CLEANUP, ctx->encrypt ? 24187211Sjp161948 PK11_R_ENCRYPTFINAL : PK11_R_DECRYPTFINAL, rv); 24197211Sjp161948 pk11_return_session(state->sp, OP_CIPHER); 24206847Svk199839 return (0); 24216847Svk199839 } 24226847Svk199839 24237211Sjp161948 pk11_return_session(state->sp, OP_CIPHER); 24240Sstevel@tonic-gate state->sp = NULL; 24250Sstevel@tonic-gate } 24260Sstevel@tonic-gate 24276847Svk199839 return (1); 24286847Svk199839 } 24296847Svk199839 24300Sstevel@tonic-gate /* Registered by the ENGINE when used to find out how to deal with 24310Sstevel@tonic-gate * a particular NID in the ENGINE. This says what we'll do at the 24320Sstevel@tonic-gate * top level - note, that list is restricted by what we answer with 24330Sstevel@tonic-gate */ 24340Sstevel@tonic-gate static int 24350Sstevel@tonic-gate pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 24360Sstevel@tonic-gate const int **nids, int nid) 24370Sstevel@tonic-gate { 24380Sstevel@tonic-gate if (!cipher) 24390Sstevel@tonic-gate return (pk11_usable_ciphers(nids)); 24400Sstevel@tonic-gate 24410Sstevel@tonic-gate switch (nid) 24420Sstevel@tonic-gate { 24430Sstevel@tonic-gate case NID_des_ede3_cbc: 24440Sstevel@tonic-gate *cipher = &pk11_3des_cbc; 24450Sstevel@tonic-gate break; 24460Sstevel@tonic-gate case NID_des_cbc: 24470Sstevel@tonic-gate *cipher = &pk11_des_cbc; 24480Sstevel@tonic-gate break; 24497211Sjp161948 case NID_des_ede3_ecb: 24507211Sjp161948 *cipher = &pk11_3des_ecb; 24517211Sjp161948 break; 24527211Sjp161948 case NID_des_ecb: 24537211Sjp161948 *cipher = &pk11_des_ecb; 24547211Sjp161948 break; 24550Sstevel@tonic-gate case NID_aes_128_cbc: 24567211Sjp161948 *cipher = &pk11_aes_128_cbc; 24577211Sjp161948 break; 24587211Sjp161948 case NID_aes_192_cbc: 24597211Sjp161948 *cipher = &pk11_aes_192_cbc; 24607211Sjp161948 break; 24617211Sjp161948 case NID_aes_256_cbc: 24627211Sjp161948 *cipher = &pk11_aes_256_cbc; 24637211Sjp161948 break; 24647211Sjp161948 case NID_aes_128_ecb: 24657211Sjp161948 *cipher = &pk11_aes_128_ecb; 24667211Sjp161948 break; 24677211Sjp161948 case NID_aes_192_ecb: 24687211Sjp161948 *cipher = &pk11_aes_192_ecb; 24697211Sjp161948 break; 24707211Sjp161948 case NID_aes_256_ecb: 24717211Sjp161948 *cipher = &pk11_aes_256_ecb; 24727211Sjp161948 break; 24737211Sjp161948 case NID_bf_cbc: 24747211Sjp161948 *cipher = &pk11_bf_cbc; 24750Sstevel@tonic-gate break; 24760Sstevel@tonic-gate case NID_rc4: 24770Sstevel@tonic-gate *cipher = &pk11_rc4; 24780Sstevel@tonic-gate break; 24790Sstevel@tonic-gate default: 24807211Sjp161948 #ifdef SOLARIS_AES_CTR 24817211Sjp161948 /* 24827211Sjp161948 * These can't be in separated cases because the NIDs 24837211Sjp161948 * here are not constants. 24847211Sjp161948 */ 24857211Sjp161948 if (nid == NID_aes_128_ctr) 24867211Sjp161948 *cipher = &pk11_aes_128_ctr; 24877211Sjp161948 else if (nid == NID_aes_192_ctr) 24887211Sjp161948 *cipher = &pk11_aes_192_ctr; 24897211Sjp161948 else if (nid == NID_aes_256_ctr) 24907211Sjp161948 *cipher = &pk11_aes_256_ctr; 24917211Sjp161948 else 24927211Sjp161948 #endif /* SOLARIS_AES_CTR */ 24930Sstevel@tonic-gate *cipher = NULL; 24940Sstevel@tonic-gate break; 24950Sstevel@tonic-gate } 24960Sstevel@tonic-gate return (*cipher != NULL); 24970Sstevel@tonic-gate } 24980Sstevel@tonic-gate 24990Sstevel@tonic-gate static int 25000Sstevel@tonic-gate pk11_engine_digests(ENGINE *e, const EVP_MD **digest, 25010Sstevel@tonic-gate const int **nids, int nid) 25020Sstevel@tonic-gate { 25030Sstevel@tonic-gate if (!digest) 25040Sstevel@tonic-gate return (pk11_usable_digests(nids)); 25050Sstevel@tonic-gate 25060Sstevel@tonic-gate switch (nid) 25070Sstevel@tonic-gate { 25080Sstevel@tonic-gate case NID_md5: 25090Sstevel@tonic-gate *digest = &pk11_md5; 25100Sstevel@tonic-gate break; 25110Sstevel@tonic-gate case NID_sha1: 25120Sstevel@tonic-gate *digest = &pk11_sha1; 25130Sstevel@tonic-gate break; 25147211Sjp161948 case NID_sha224: 25157211Sjp161948 *digest = &pk11_sha224; 25167211Sjp161948 break; 25177211Sjp161948 case NID_sha256: 25187211Sjp161948 *digest = &pk11_sha256; 25197211Sjp161948 break; 25207211Sjp161948 case NID_sha384: 25217211Sjp161948 *digest = &pk11_sha384; 25227211Sjp161948 break; 25237211Sjp161948 case NID_sha512: 25247211Sjp161948 *digest = &pk11_sha512; 25257211Sjp161948 break; 25260Sstevel@tonic-gate default: 25270Sstevel@tonic-gate *digest = NULL; 25280Sstevel@tonic-gate break; 25290Sstevel@tonic-gate } 25300Sstevel@tonic-gate return (*digest != NULL); 25310Sstevel@tonic-gate } 25320Sstevel@tonic-gate 25330Sstevel@tonic-gate 25340Sstevel@tonic-gate /* Create a secret key object in a PKCS#11 session 25350Sstevel@tonic-gate */ 25360Sstevel@tonic-gate static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, 25370Sstevel@tonic-gate const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp) 25380Sstevel@tonic-gate { 25390Sstevel@tonic-gate CK_RV rv; 25400Sstevel@tonic-gate CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; 25410Sstevel@tonic-gate CK_OBJECT_CLASS obj_key = CKO_SECRET_KEY; 25420Sstevel@tonic-gate CK_ULONG ul_key_attr_count = 6; 25430Sstevel@tonic-gate 25440Sstevel@tonic-gate CK_ATTRIBUTE a_key_template[] = 25450Sstevel@tonic-gate { 25460Sstevel@tonic-gate {CKA_CLASS, (void*) NULL, sizeof(CK_OBJECT_CLASS)}, 25470Sstevel@tonic-gate {CKA_KEY_TYPE, (void*) NULL, sizeof(CK_KEY_TYPE)}, 25480Sstevel@tonic-gate {CKA_TOKEN, &false, sizeof(false)}, 25490Sstevel@tonic-gate {CKA_ENCRYPT, &true, sizeof(true)}, 25500Sstevel@tonic-gate {CKA_DECRYPT, &true, sizeof(true)}, 25510Sstevel@tonic-gate {CKA_VALUE, (void*) NULL, 0}, 25520Sstevel@tonic-gate }; 25530Sstevel@tonic-gate 25540Sstevel@tonic-gate /* Create secret key object in global_session. All other sessions 25550Sstevel@tonic-gate * can use the key handles. Here is why: 25560Sstevel@tonic-gate * OpenSSL will call EncryptInit and EncryptUpdate using a secret key. 25570Sstevel@tonic-gate * It may then call DecryptInit and DecryptUpdate using the same key. 25580Sstevel@tonic-gate * To use the same key object, we need to call EncryptFinal with 25590Sstevel@tonic-gate * a 0 length message. Currently, this does not work for 3DES 25600Sstevel@tonic-gate * mechanism. To get around this problem, we close the session and 25610Sstevel@tonic-gate * then create a new session to use the same key object. When a session 25620Sstevel@tonic-gate * is closed, all the object handles will be invalid. Thus, create key 25630Sstevel@tonic-gate * objects in a global session, an individual session may be closed to 25640Sstevel@tonic-gate * terminate the active operation. 25650Sstevel@tonic-gate */ 25660Sstevel@tonic-gate CK_SESSION_HANDLE session = global_session; 25670Sstevel@tonic-gate a_key_template[0].pValue = &obj_key; 25680Sstevel@tonic-gate a_key_template[1].pValue = &key_type; 25690Sstevel@tonic-gate a_key_template[5].pValue = (void *) key; 25700Sstevel@tonic-gate a_key_template[5].ulValueLen = (unsigned long) ctx->key_len; 25710Sstevel@tonic-gate 25724602Sjp161948 rv = pFuncList->C_CreateObject(session, 25734602Sjp161948 a_key_template, ul_key_attr_count, &h_key); 25740Sstevel@tonic-gate if (rv != CKR_OK) 25750Sstevel@tonic-gate { 25767211Sjp161948 PK11err_add_data(PK11_F_GET_CIPHER_KEY, PK11_R_CREATEOBJECT, 25777211Sjp161948 rv); 25780Sstevel@tonic-gate goto err; 25790Sstevel@tonic-gate } 25800Sstevel@tonic-gate 25810Sstevel@tonic-gate /* Save the key information used in this session. 25820Sstevel@tonic-gate * The max can be saved is PK11_KEY_LEN_MAX. 25830Sstevel@tonic-gate */ 2584*7526SVladimir.Kotal@Sun.COM sp->opdata_key_len = ctx->key_len > PK11_KEY_LEN_MAX ? 25850Sstevel@tonic-gate PK11_KEY_LEN_MAX : ctx->key_len; 2586*7526SVladimir.Kotal@Sun.COM memcpy(sp->opdata_key, key, sp->opdata_key_len); 25870Sstevel@tonic-gate err: 25880Sstevel@tonic-gate 25890Sstevel@tonic-gate return h_key; 25900Sstevel@tonic-gate } 25910Sstevel@tonic-gate 25920Sstevel@tonic-gate static int 25930Sstevel@tonic-gate md_nid_to_pk11(int nid) 25940Sstevel@tonic-gate { 25950Sstevel@tonic-gate int i; 25960Sstevel@tonic-gate 25970Sstevel@tonic-gate for (i = 0; i < PK11_DIGEST_MAX; i++) 25980Sstevel@tonic-gate if (digests[i].nid == nid) 25990Sstevel@tonic-gate return (digests[i].id); 26000Sstevel@tonic-gate return (-1); 26010Sstevel@tonic-gate } 26020Sstevel@tonic-gate 26030Sstevel@tonic-gate static int 26040Sstevel@tonic-gate pk11_digest_init(EVP_MD_CTX *ctx) 26050Sstevel@tonic-gate { 26060Sstevel@tonic-gate CK_RV rv; 26074320Sjp161948 CK_MECHANISM mech; 26080Sstevel@tonic-gate int index; 26090Sstevel@tonic-gate PK11_SESSION *sp; 26100Sstevel@tonic-gate PK11_DIGEST *pdp; 26110Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; 26120Sstevel@tonic-gate 26130Sstevel@tonic-gate state->sp = NULL; 26140Sstevel@tonic-gate 26150Sstevel@tonic-gate index = md_nid_to_pk11(ctx->digest->type); 26160Sstevel@tonic-gate if (index < 0 || index >= PK11_DIGEST_MAX) 26170Sstevel@tonic-gate return 0; 26180Sstevel@tonic-gate 26190Sstevel@tonic-gate pdp = &digests[index]; 26207211Sjp161948 if ((sp = pk11_get_session(OP_DIGEST)) == NULL) 26210Sstevel@tonic-gate return 0; 26220Sstevel@tonic-gate 26234320Sjp161948 /* at present, no parameter is needed for supported digests */ 26244320Sjp161948 mech.mechanism = pdp->mech_type; 26254320Sjp161948 mech.pParameter = NULL; 26264320Sjp161948 mech.ulParameterLen = 0; 26274320Sjp161948 26284320Sjp161948 rv = pFuncList->C_DigestInit(sp->session, &mech); 26290Sstevel@tonic-gate 26300Sstevel@tonic-gate if (rv != CKR_OK) 26310Sstevel@tonic-gate { 26327211Sjp161948 PK11err_add_data(PK11_F_DIGEST_INIT, PK11_R_DIGESTINIT, rv); 26337211Sjp161948 pk11_return_session(sp, OP_DIGEST); 26340Sstevel@tonic-gate return 0; 26350Sstevel@tonic-gate } 26360Sstevel@tonic-gate 26370Sstevel@tonic-gate state->sp = sp; 26380Sstevel@tonic-gate 26390Sstevel@tonic-gate return 1; 26400Sstevel@tonic-gate } 26410Sstevel@tonic-gate 26420Sstevel@tonic-gate static int 26432139Sjp161948 pk11_digest_update(EVP_MD_CTX *ctx,const void *data,size_t count) 26440Sstevel@tonic-gate { 26450Sstevel@tonic-gate CK_RV rv; 26460Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; 26470Sstevel@tonic-gate 26480Sstevel@tonic-gate /* 0 length message will cause a failure in C_DigestFinal */ 26490Sstevel@tonic-gate if (count == 0) 26500Sstevel@tonic-gate return 1; 26510Sstevel@tonic-gate 26520Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 26530Sstevel@tonic-gate return 0; 26540Sstevel@tonic-gate 26550Sstevel@tonic-gate rv = pFuncList->C_DigestUpdate(state->sp->session, (CK_BYTE *) data, 26560Sstevel@tonic-gate count); 26570Sstevel@tonic-gate 26580Sstevel@tonic-gate if (rv != CKR_OK) 26590Sstevel@tonic-gate { 26607211Sjp161948 PK11err_add_data(PK11_F_DIGEST_UPDATE, PK11_R_DIGESTUPDATE, rv); 26617211Sjp161948 pk11_return_session(state->sp, OP_DIGEST); 26620Sstevel@tonic-gate state->sp = NULL; 26630Sstevel@tonic-gate return 0; 26640Sstevel@tonic-gate } 26650Sstevel@tonic-gate 26660Sstevel@tonic-gate return 1; 26670Sstevel@tonic-gate } 26680Sstevel@tonic-gate 26690Sstevel@tonic-gate static int 26700Sstevel@tonic-gate pk11_digest_final(EVP_MD_CTX *ctx,unsigned char *md) 26710Sstevel@tonic-gate { 26720Sstevel@tonic-gate CK_RV rv; 26730Sstevel@tonic-gate unsigned long len; 26740Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; 26750Sstevel@tonic-gate len = ctx->digest->md_size; 26760Sstevel@tonic-gate 26770Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 26780Sstevel@tonic-gate return 0; 26790Sstevel@tonic-gate 26800Sstevel@tonic-gate rv = pFuncList->C_DigestFinal(state->sp->session, md, &len); 26810Sstevel@tonic-gate 26820Sstevel@tonic-gate if (rv != CKR_OK) 26830Sstevel@tonic-gate { 26847211Sjp161948 PK11err_add_data(PK11_F_DIGEST_FINAL, PK11_R_DIGESTFINAL, rv); 26857211Sjp161948 pk11_return_session(state->sp, OP_DIGEST); 26860Sstevel@tonic-gate state->sp = NULL; 26870Sstevel@tonic-gate return 0; 26880Sstevel@tonic-gate } 26890Sstevel@tonic-gate 26900Sstevel@tonic-gate if (ctx->digest->md_size != len) 26910Sstevel@tonic-gate return 0; 26920Sstevel@tonic-gate 26930Sstevel@tonic-gate /* Final is called and digest is returned, so return the session 26940Sstevel@tonic-gate * to the pool 26950Sstevel@tonic-gate */ 26967211Sjp161948 pk11_return_session(state->sp, OP_DIGEST); 26970Sstevel@tonic-gate state->sp = NULL; 26980Sstevel@tonic-gate 26990Sstevel@tonic-gate return 1; 27000Sstevel@tonic-gate } 27010Sstevel@tonic-gate 27020Sstevel@tonic-gate static int 27030Sstevel@tonic-gate pk11_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from) 27040Sstevel@tonic-gate { 27050Sstevel@tonic-gate CK_RV rv; 27060Sstevel@tonic-gate int ret = 0; 27070Sstevel@tonic-gate PK11_CIPHER_STATE *state, *state_to; 27080Sstevel@tonic-gate CK_BYTE_PTR pstate = NULL; 27090Sstevel@tonic-gate CK_ULONG ul_state_len; 27100Sstevel@tonic-gate 27110Sstevel@tonic-gate /* The copy-from state */ 27120Sstevel@tonic-gate state = (PK11_CIPHER_STATE *) from->md_data; 27130Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 27140Sstevel@tonic-gate goto err; 27150Sstevel@tonic-gate 27160Sstevel@tonic-gate /* Initialize the copy-to state */ 27170Sstevel@tonic-gate if (!pk11_digest_init(to)) 27180Sstevel@tonic-gate goto err; 27190Sstevel@tonic-gate state_to = (PK11_CIPHER_STATE *) to->md_data; 27200Sstevel@tonic-gate 27210Sstevel@tonic-gate /* Get the size of the operation state of the copy-from session */ 27220Sstevel@tonic-gate rv = pFuncList->C_GetOperationState(state->sp->session, NULL, 27230Sstevel@tonic-gate &ul_state_len); 27240Sstevel@tonic-gate 27250Sstevel@tonic-gate if (rv != CKR_OK) 27260Sstevel@tonic-gate { 27277211Sjp161948 PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE, 27287211Sjp161948 rv); 27290Sstevel@tonic-gate goto err; 27300Sstevel@tonic-gate } 27310Sstevel@tonic-gate if (ul_state_len == 0) 27320Sstevel@tonic-gate { 27330Sstevel@tonic-gate goto err; 27340Sstevel@tonic-gate } 27350Sstevel@tonic-gate 27360Sstevel@tonic-gate pstate = OPENSSL_malloc(ul_state_len); 27370Sstevel@tonic-gate if (pstate == NULL) 27380Sstevel@tonic-gate { 27396847Svk199839 PK11err(PK11_F_DIGEST_COPY, PK11_R_MALLOC_FAILURE); 27400Sstevel@tonic-gate goto err; 27410Sstevel@tonic-gate } 27420Sstevel@tonic-gate 27430Sstevel@tonic-gate /* Get the operation state of the copy-from session */ 27440Sstevel@tonic-gate rv = pFuncList->C_GetOperationState(state->sp->session, pstate, 27450Sstevel@tonic-gate &ul_state_len); 27460Sstevel@tonic-gate 27470Sstevel@tonic-gate if (rv != CKR_OK) 27480Sstevel@tonic-gate { 27497211Sjp161948 PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE, 27507211Sjp161948 rv); 27510Sstevel@tonic-gate goto err; 27520Sstevel@tonic-gate } 27530Sstevel@tonic-gate 27540Sstevel@tonic-gate /* Set the operation state of the copy-to session */ 27550Sstevel@tonic-gate rv = pFuncList->C_SetOperationState(state_to->sp->session, pstate, 27560Sstevel@tonic-gate ul_state_len, 0, 0); 27570Sstevel@tonic-gate 27580Sstevel@tonic-gate if (rv != CKR_OK) 27590Sstevel@tonic-gate { 27607211Sjp161948 PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_SET_OPERATION_STATE, rv); 27610Sstevel@tonic-gate goto err; 27620Sstevel@tonic-gate } 27630Sstevel@tonic-gate 27640Sstevel@tonic-gate ret = 1; 27650Sstevel@tonic-gate err: 27660Sstevel@tonic-gate if (pstate != NULL) 27670Sstevel@tonic-gate OPENSSL_free(pstate); 27680Sstevel@tonic-gate 27690Sstevel@tonic-gate return ret; 27700Sstevel@tonic-gate } 27710Sstevel@tonic-gate 27720Sstevel@tonic-gate /* Return any pending session state to the pool */ 27730Sstevel@tonic-gate static int 27740Sstevel@tonic-gate pk11_digest_cleanup(EVP_MD_CTX *ctx) 27750Sstevel@tonic-gate { 27760Sstevel@tonic-gate PK11_CIPHER_STATE *state = ctx->md_data; 27774602Sjp161948 unsigned char buf[EVP_MAX_MD_SIZE]; 27780Sstevel@tonic-gate 27790Sstevel@tonic-gate if (state != NULL && state->sp != NULL) 27800Sstevel@tonic-gate { 27814602Sjp161948 /* 27824602Sjp161948 * If state->sp is not NULL then pk11_digest_final() has not 27834602Sjp161948 * been called yet. We must call it now to free any memory 27844602Sjp161948 * that might have been allocated in the token when 27854602Sjp161948 * pk11_digest_init() was called. 27864602Sjp161948 */ 2787*7526SVladimir.Kotal@Sun.COM (void) pk11_digest_final(ctx, buf); 27887211Sjp161948 pk11_return_session(state->sp, OP_DIGEST); 27890Sstevel@tonic-gate state->sp = NULL; 27900Sstevel@tonic-gate } 27910Sstevel@tonic-gate 27920Sstevel@tonic-gate return 1; 27930Sstevel@tonic-gate } 27940Sstevel@tonic-gate 27956847Svk199839 /* 27967211Sjp161948 * Check if the new key is the same as the key object in the session. If the key 27977211Sjp161948 * is the same, no need to create a new key object. Otherwise, the old key 27987211Sjp161948 * object needs to be destroyed and a new one will be created. Return 1 for 27997211Sjp161948 * cache hit, 0 for cache miss. Note that we must check the key length first 28007211Sjp161948 * otherwise we could end up reusing a different, longer key with the same 28017211Sjp161948 * prefix. 28020Sstevel@tonic-gate */ 28037211Sjp161948 static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key, 28047211Sjp161948 int key_len) 28050Sstevel@tonic-gate { 2806*7526SVladimir.Kotal@Sun.COM if (sp->opdata_key_len != key_len || 2807*7526SVladimir.Kotal@Sun.COM memcmp(sp->opdata_key, key, key_len) != 0) 28086847Svk199839 { 28097211Sjp161948 (void) pk11_destroy_cipher_key_objects(sp); 28106847Svk199839 return (0); 28116847Svk199839 } 28126847Svk199839 return (1); 28130Sstevel@tonic-gate } 28140Sstevel@tonic-gate 28150Sstevel@tonic-gate /* Destroy one or more secret key objects. 28160Sstevel@tonic-gate */ 28170Sstevel@tonic-gate static int pk11_destroy_cipher_key_objects(PK11_SESSION *session) 28180Sstevel@tonic-gate { 28190Sstevel@tonic-gate int ret = 0; 28200Sstevel@tonic-gate PK11_SESSION *sp = NULL; 28210Sstevel@tonic-gate PK11_SESSION *local_free_session; 28220Sstevel@tonic-gate 2823*7526SVladimir.Kotal@Sun.COM if (session != NULL) 28240Sstevel@tonic-gate local_free_session = session; 28250Sstevel@tonic-gate else 2826*7526SVladimir.Kotal@Sun.COM { 2827*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_lock(session_cache[OP_CIPHER].lock); 2828*7526SVladimir.Kotal@Sun.COM local_free_session = session_cache[OP_CIPHER].head; 2829*7526SVladimir.Kotal@Sun.COM } 2830*7526SVladimir.Kotal@Sun.COM 28310Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 28320Sstevel@tonic-gate { 28330Sstevel@tonic-gate local_free_session = sp->next; 28340Sstevel@tonic-gate 2835*7526SVladimir.Kotal@Sun.COM if (sp->opdata_cipher_key != CK_INVALID_HANDLE) 28360Sstevel@tonic-gate { 28370Sstevel@tonic-gate /* The secret key object is created in the 28380Sstevel@tonic-gate * global_session. See pk11_get_cipher_key 28390Sstevel@tonic-gate */ 28400Sstevel@tonic-gate if (pk11_destroy_object(global_session, 2841*7526SVladimir.Kotal@Sun.COM sp->opdata_cipher_key) == 0) 28420Sstevel@tonic-gate goto err; 2843*7526SVladimir.Kotal@Sun.COM sp->opdata_cipher_key = CK_INVALID_HANDLE; 28440Sstevel@tonic-gate } 28450Sstevel@tonic-gate } 28460Sstevel@tonic-gate ret = 1; 28470Sstevel@tonic-gate err: 2848*7526SVladimir.Kotal@Sun.COM 2849*7526SVladimir.Kotal@Sun.COM if (session == NULL) 2850*7526SVladimir.Kotal@Sun.COM (void) pthread_mutex_unlock(session_cache[OP_CIPHER].lock); 28510Sstevel@tonic-gate 28520Sstevel@tonic-gate return ret; 28530Sstevel@tonic-gate } 28540Sstevel@tonic-gate 28550Sstevel@tonic-gate 28560Sstevel@tonic-gate /* 28577211Sjp161948 * Public key mechanisms optionally supported 28580Sstevel@tonic-gate * 28590Sstevel@tonic-gate * CKM_RSA_X_509 28600Sstevel@tonic-gate * CKM_RSA_PKCS 28610Sstevel@tonic-gate * CKM_DSA 28620Sstevel@tonic-gate * 28637211Sjp161948 * The first slot that supports at least one of those mechanisms is chosen as a 28647211Sjp161948 * public key slot. 28650Sstevel@tonic-gate * 28660Sstevel@tonic-gate * Symmetric ciphers optionally supported 28670Sstevel@tonic-gate * 28680Sstevel@tonic-gate * CKM_DES3_CBC 28690Sstevel@tonic-gate * CKM_DES_CBC 28700Sstevel@tonic-gate * CKM_AES_CBC 28717211Sjp161948 * CKM_DES3_ECB 28727211Sjp161948 * CKM_DES_ECB 28737211Sjp161948 * CKM_AES_ECB 28747211Sjp161948 * CKM_AES_CTR 28750Sstevel@tonic-gate * CKM_RC4 28767211Sjp161948 * CKM_BLOWFISH_CBC 28770Sstevel@tonic-gate * 28780Sstevel@tonic-gate * Digests optionally supported 28790Sstevel@tonic-gate * 28800Sstevel@tonic-gate * CKM_MD5 28810Sstevel@tonic-gate * CKM_SHA_1 28827211Sjp161948 * CKM_SHA224 28837211Sjp161948 * CKM_SHA256 28847211Sjp161948 * CKM_SHA384 28857211Sjp161948 * CKM_SHA512 28867211Sjp161948 * 28877211Sjp161948 * The output of this function is a set of global variables indicating which 28887211Sjp161948 * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of 28897211Sjp161948 * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global 28907211Sjp161948 * variables carry information about which slot was chosen for (a) public key 28917211Sjp161948 * mechanisms, (b) random operations, and (c) symmetric ciphers and digests. 28920Sstevel@tonic-gate */ 28930Sstevel@tonic-gate static int 28947211Sjp161948 pk11_choose_slots(int *any_slot_found) 28950Sstevel@tonic-gate { 28960Sstevel@tonic-gate CK_SLOT_ID_PTR pSlotList = NULL_PTR; 28970Sstevel@tonic-gate CK_ULONG ulSlotCount = 0; 28980Sstevel@tonic-gate CK_MECHANISM_INFO mech_info; 28990Sstevel@tonic-gate CK_TOKEN_INFO token_info; 29000Sstevel@tonic-gate int i; 29010Sstevel@tonic-gate CK_RV rv; 29020Sstevel@tonic-gate CK_SLOT_ID best_slot_sofar; 29030Sstevel@tonic-gate CK_BBOOL found_candidate_slot = CK_FALSE; 29040Sstevel@tonic-gate int slot_n_cipher = 0; 29050Sstevel@tonic-gate int slot_n_digest = 0; 29060Sstevel@tonic-gate CK_SLOT_ID current_slot = 0; 29070Sstevel@tonic-gate int current_slot_n_cipher = 0; 29080Sstevel@tonic-gate int current_slot_n_digest = 0; 29090Sstevel@tonic-gate 29100Sstevel@tonic-gate int local_cipher_nids[PK11_CIPHER_MAX]; 29110Sstevel@tonic-gate int local_digest_nids[PK11_DIGEST_MAX]; 29127211Sjp161948 29137211Sjp161948 /* let's initialize the output parameter */ 29147211Sjp161948 if (any_slot_found != NULL) 29157211Sjp161948 *any_slot_found = 0; 29167211Sjp161948 29177211Sjp161948 /* Get slot list for memory allocation */ 29180Sstevel@tonic-gate rv = pFuncList->C_GetSlotList(0, NULL_PTR, &ulSlotCount); 29190Sstevel@tonic-gate 29200Sstevel@tonic-gate if (rv != CKR_OK) 29210Sstevel@tonic-gate { 29227211Sjp161948 PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); 29237211Sjp161948 return 0; 29240Sstevel@tonic-gate } 29250Sstevel@tonic-gate 29267211Sjp161948 /* it's not an error if we didn't find any providers */ 29270Sstevel@tonic-gate if (ulSlotCount == 0) 29280Sstevel@tonic-gate { 29297211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 29307211Sjp161948 fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG); 29317211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 29327211Sjp161948 return 1; 29330Sstevel@tonic-gate } 29340Sstevel@tonic-gate 29350Sstevel@tonic-gate pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); 29360Sstevel@tonic-gate 29370Sstevel@tonic-gate if (pSlotList == NULL) 29380Sstevel@tonic-gate { 29396847Svk199839 PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE); 29407211Sjp161948 return 0; 29410Sstevel@tonic-gate } 29420Sstevel@tonic-gate 29430Sstevel@tonic-gate /* Get the slot list for processing */ 29440Sstevel@tonic-gate rv = pFuncList->C_GetSlotList(0, pSlotList, &ulSlotCount); 29450Sstevel@tonic-gate if (rv != CKR_OK) 29460Sstevel@tonic-gate { 29477211Sjp161948 PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); 29480Sstevel@tonic-gate OPENSSL_free(pSlotList); 29497211Sjp161948 return 0; 29500Sstevel@tonic-gate } 29510Sstevel@tonic-gate 29527211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 29537211Sjp161948 fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME); 29547211Sjp161948 fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount); 29557211Sjp161948 29567211Sjp161948 fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG); 29577211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 29587211Sjp161948 for (i = 0; i < ulSlotCount; i++) 29597211Sjp161948 { 29607211Sjp161948 current_slot = pSlotList[i]; 29617211Sjp161948 29627211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 29637211Sjp161948 fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); 29647211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 29657211Sjp161948 /* Check if slot has random support. */ 29667211Sjp161948 rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); 29677211Sjp161948 if (rv != CKR_OK) 29687211Sjp161948 continue; 29697211Sjp161948 29707211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 29717211Sjp161948 fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); 29727211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 29737211Sjp161948 29747211Sjp161948 if (token_info.flags & CKF_RNG) 29757211Sjp161948 { 29767211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 29777211Sjp161948 fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG); 29787211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 29797211Sjp161948 pk11_have_random = CK_TRUE; 29807211Sjp161948 break; 29817211Sjp161948 } 29827211Sjp161948 } 29837211Sjp161948 29847211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 29857211Sjp161948 fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG); 29867211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 29870Sstevel@tonic-gate for (i = 0; i < ulSlotCount; i++) 29880Sstevel@tonic-gate { 29890Sstevel@tonic-gate CK_BBOOL slot_has_rsa = CK_FALSE; 29900Sstevel@tonic-gate CK_BBOOL slot_has_dsa = CK_FALSE; 29910Sstevel@tonic-gate CK_BBOOL slot_has_dh = CK_FALSE; 29920Sstevel@tonic-gate current_slot = pSlotList[i]; 29937211Sjp161948 29947211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 29957211Sjp161948 fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); 29967211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 29970Sstevel@tonic-gate rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); 29980Sstevel@tonic-gate if (rv != CKR_OK) 29990Sstevel@tonic-gate continue; 30000Sstevel@tonic-gate 30017211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 30027211Sjp161948 fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); 30037211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 30047211Sjp161948 30056847Svk199839 #ifndef OPENSSL_NO_RSA 30060Sstevel@tonic-gate /* 30070Sstevel@tonic-gate * Check if this slot is capable of signing and 30080Sstevel@tonic-gate * verifying with CKM_RSA_PKCS. 30090Sstevel@tonic-gate */ 30100Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS, 30110Sstevel@tonic-gate &mech_info); 30120Sstevel@tonic-gate 30130Sstevel@tonic-gate if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && 30140Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY))) 30150Sstevel@tonic-gate { 30160Sstevel@tonic-gate /* 30170Sstevel@tonic-gate * Check if this slot is capable of encryption, 30180Sstevel@tonic-gate * decryption, sign, and verify with CKM_RSA_X_509. 30190Sstevel@tonic-gate */ 30200Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, 30210Sstevel@tonic-gate CKM_RSA_X_509, &mech_info); 30220Sstevel@tonic-gate 30230Sstevel@tonic-gate if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && 30240Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY) && 30250Sstevel@tonic-gate (mech_info.flags & CKF_ENCRYPT) && 30260Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY_RECOVER) && 30270Sstevel@tonic-gate (mech_info.flags & CKF_DECRYPT))) 30287211Sjp161948 { 30290Sstevel@tonic-gate slot_has_rsa = CK_TRUE; 30307211Sjp161948 } 30310Sstevel@tonic-gate } 30327211Sjp161948 #endif /* OPENSSL_NO_RSA */ 30337211Sjp161948 30346847Svk199839 #ifndef OPENSSL_NO_DSA 30350Sstevel@tonic-gate /* 30360Sstevel@tonic-gate * Check if this slot is capable of signing and 30370Sstevel@tonic-gate * verifying with CKM_DSA. 30380Sstevel@tonic-gate */ 30390Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA, 30400Sstevel@tonic-gate &mech_info); 30410Sstevel@tonic-gate if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && 30420Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY))) 30437211Sjp161948 { 30440Sstevel@tonic-gate slot_has_dsa = CK_TRUE; 30457211Sjp161948 } 3046*7526SVladimir.Kotal@Sun.COM 30477211Sjp161948 #endif /* OPENSSL_NO_DSA */ 30487211Sjp161948 30496847Svk199839 #ifndef OPENSSL_NO_DH 30500Sstevel@tonic-gate /* 30510Sstevel@tonic-gate * Check if this slot is capable of DH key generataion and 30520Sstevel@tonic-gate * derivation. 30530Sstevel@tonic-gate */ 30540Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, 30550Sstevel@tonic-gate CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info); 30560Sstevel@tonic-gate 30570Sstevel@tonic-gate if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR)) 30580Sstevel@tonic-gate { 30590Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, 30600Sstevel@tonic-gate CKM_DH_PKCS_DERIVE, &mech_info); 30610Sstevel@tonic-gate if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE)) 30627211Sjp161948 { 30630Sstevel@tonic-gate slot_has_dh = CK_TRUE; 30647211Sjp161948 } 30650Sstevel@tonic-gate } 30667211Sjp161948 #endif /* OPENSSL_NO_DH */ 30677211Sjp161948 30680Sstevel@tonic-gate if (!found_candidate_slot && 30690Sstevel@tonic-gate (slot_has_rsa || slot_has_dsa || slot_has_dh)) 30700Sstevel@tonic-gate { 30717211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 30720Sstevel@tonic-gate fprintf(stderr, 30737211Sjp161948 "%s: potential slot: %d\n", PK11_DBG, current_slot); 30747211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 30750Sstevel@tonic-gate best_slot_sofar = current_slot; 30760Sstevel@tonic-gate pk11_have_rsa = slot_has_rsa; 30770Sstevel@tonic-gate pk11_have_dsa = slot_has_dsa; 30780Sstevel@tonic-gate pk11_have_dh = slot_has_dh; 30790Sstevel@tonic-gate found_candidate_slot = CK_TRUE; 30807211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 30817211Sjp161948 fprintf(stderr, 30827211Sjp161948 "%s: setting found_candidate_slot to CK_TRUE\n", 30837211Sjp161948 PK11_DBG); 30840Sstevel@tonic-gate fprintf(stderr, 30857211Sjp161948 "%s: best so far slot: %d\n", PK11_DBG, 30860Sstevel@tonic-gate best_slot_sofar); 30877211Sjp161948 } 30887211Sjp161948 else 30897211Sjp161948 { 30907211Sjp161948 fprintf(stderr, 30917211Sjp161948 "%s: no rsa/dsa/dh\n", PK11_DBG); 30920Sstevel@tonic-gate } 30937211Sjp161948 #else 30947211Sjp161948 } /* if */ 30957211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 30967211Sjp161948 } /* for */ 30977211Sjp161948 30987211Sjp161948 if (found_candidate_slot) 30997211Sjp161948 { 31007211Sjp161948 pubkey_SLOTID = best_slot_sofar; 31017211Sjp161948 } 31027211Sjp161948 31037211Sjp161948 found_candidate_slot = CK_FALSE; 31047211Sjp161948 best_slot_sofar = 0; 31057211Sjp161948 31067211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 31077211Sjp161948 fprintf(stderr, "%s: == checking cipher/digest ==\n", PK11_DBG); 31087211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 31097211Sjp161948 for (i = 0; i < ulSlotCount; i++) 31107211Sjp161948 { 31117211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 31127211Sjp161948 fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); 31137211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 31147211Sjp161948 31157211Sjp161948 current_slot = pSlotList[i]; 31167211Sjp161948 current_slot_n_cipher = 0; 31177211Sjp161948 current_slot_n_digest = 0; 31187211Sjp161948 memset(local_cipher_nids, 0, sizeof(local_cipher_nids)); 31197211Sjp161948 memset(local_digest_nids, 0, sizeof(local_digest_nids)); 31207211Sjp161948 31217211Sjp161948 pk11_find_symmetric_ciphers(pFuncList, current_slot, 31227211Sjp161948 ¤t_slot_n_cipher, local_cipher_nids); 31237211Sjp161948 31247211Sjp161948 pk11_find_digests(pFuncList, current_slot, 31257211Sjp161948 ¤t_slot_n_digest, local_digest_nids); 31267211Sjp161948 31277211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 31287211Sjp161948 fprintf(stderr, "%s: current_slot_n_cipher %d\n", PK11_DBG, 31297211Sjp161948 current_slot_n_cipher); 31307211Sjp161948 fprintf(stderr, "%s: current_slot_n_digest %d\n", PK11_DBG, 31317211Sjp161948 current_slot_n_digest); 31327211Sjp161948 fprintf(stderr, "%s: best so far cipher/digest slot: %d\n", 31337211Sjp161948 PK11_DBG, best_slot_sofar); 31347211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 31350Sstevel@tonic-gate 31360Sstevel@tonic-gate /* 31370Sstevel@tonic-gate * If the current slot supports more ciphers/digests than 31387250Sjp161948 * the previous best one we change the current best to this one, 31390Sstevel@tonic-gate * otherwise leave it where it is. 31400Sstevel@tonic-gate */ 31417250Sjp161948 if ((current_slot_n_cipher + current_slot_n_digest) > 31427250Sjp161948 (slot_n_cipher + slot_n_digest)) 31430Sstevel@tonic-gate { 31447211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 31457211Sjp161948 fprintf(stderr, 31467211Sjp161948 "%s: changing best so far slot to %d\n", 31477211Sjp161948 PK11_DBG, current_slot); 31487211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 31497211Sjp161948 best_slot_sofar = SLOTID = current_slot; 31507250Sjp161948 cipher_count = slot_n_cipher = current_slot_n_cipher; 31517250Sjp161948 digest_count = slot_n_digest = current_slot_n_digest; 31527250Sjp161948 memcpy(cipher_nids, local_cipher_nids, 3153*7526SVladimir.Kotal@Sun.COM sizeof (local_cipher_nids)); 3154*7526SVladimir.Kotal@Sun.COM memcpy(digest_nids, local_digest_nids, 3155*7526SVladimir.Kotal@Sun.COM sizeof (local_digest_nids)); 31560Sstevel@tonic-gate } 31570Sstevel@tonic-gate } 31580Sstevel@tonic-gate 31597211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 31607211Sjp161948 fprintf(stderr, 3161*7526SVladimir.Kotal@Sun.COM "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID); 31620Sstevel@tonic-gate fprintf(stderr, 3163*7526SVladimir.Kotal@Sun.COM "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID); 31640Sstevel@tonic-gate fprintf(stderr, 3165*7526SVladimir.Kotal@Sun.COM "%s: chosen cipher/digest slot: %d\n", PK11_DBG, SLOTID); 31667211Sjp161948 fprintf(stderr, 3167*7526SVladimir.Kotal@Sun.COM "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa); 31680Sstevel@tonic-gate fprintf(stderr, 3169*7526SVladimir.Kotal@Sun.COM "%s: pk11_have_dsa %d\n", PK11_DBG, pk11_have_dsa); 31707211Sjp161948 fprintf(stderr, 3171*7526SVladimir.Kotal@Sun.COM "%s: pk11_have_dh %d\n", PK11_DBG, pk11_have_dh); 31720Sstevel@tonic-gate fprintf(stderr, 3173*7526SVladimir.Kotal@Sun.COM "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random); 31740Sstevel@tonic-gate fprintf(stderr, 3175*7526SVladimir.Kotal@Sun.COM "%s: cipher_count %d\n", PK11_DBG, cipher_count); 31767211Sjp161948 fprintf(stderr, 3177*7526SVladimir.Kotal@Sun.COM "%s: digest_count %d\n", PK11_DBG, digest_count); 31787211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 31790Sstevel@tonic-gate 31806847Svk199839 if (pSlotList != NULL) 31816847Svk199839 OPENSSL_free(pSlotList); 31820Sstevel@tonic-gate 31837211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 31847211Sjp161948 OPENSSL_free(hw_cnids); 31857211Sjp161948 OPENSSL_free(hw_dnids); 31867211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 31877211Sjp161948 31887211Sjp161948 if (any_slot_found != NULL) 31897211Sjp161948 *any_slot_found = 1; 31907211Sjp161948 return 1; 31910Sstevel@tonic-gate } 31920Sstevel@tonic-gate 31937211Sjp161948 static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR pflist, 31947211Sjp161948 int slot_id, CK_MECHANISM_TYPE mech, int *current_slot_n_cipher, 31957211Sjp161948 int *local_cipher_nids, int id) 31967211Sjp161948 { 31977211Sjp161948 CK_MECHANISM_INFO mech_info; 31987211Sjp161948 CK_RV rv; 31997211Sjp161948 32007211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 32017211Sjp161948 fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech); 32027211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 32037211Sjp161948 rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info); 32047211Sjp161948 32057211Sjp161948 if (rv != CKR_OK) 32067211Sjp161948 { 32077211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 32087211Sjp161948 fprintf(stderr, " not found\n"); 32097211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 32107211Sjp161948 return; 32117211Sjp161948 } 32127211Sjp161948 32137211Sjp161948 if ((mech_info.flags & CKF_ENCRYPT) && 32147211Sjp161948 (mech_info.flags & CKF_DECRYPT)) 32157211Sjp161948 { 32167211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 32177211Sjp161948 if (nid_in_table(ciphers[id].nid, hw_cnids)) 32187211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 32197211Sjp161948 { 32207211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 32217211Sjp161948 fprintf(stderr, " usable\n"); 32227211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 32237211Sjp161948 local_cipher_nids[(*current_slot_n_cipher)++] = 32247211Sjp161948 ciphers[id].nid; 32257211Sjp161948 } 32267211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 32277211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 32287211Sjp161948 else 32297211Sjp161948 { 32307211Sjp161948 fprintf(stderr, " rejected, software implementation only\n"); 32317211Sjp161948 } 32327211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 32337211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 32347211Sjp161948 } 32357211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 32367211Sjp161948 else 32377211Sjp161948 { 32387211Sjp161948 fprintf(stderr, " unusable\n"); 32397211Sjp161948 } 32407211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 32417211Sjp161948 32427211Sjp161948 return; 32437211Sjp161948 } 32447211Sjp161948 32457211Sjp161948 static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id, 32467211Sjp161948 CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids, 32477211Sjp161948 int id) 32480Sstevel@tonic-gate { 32490Sstevel@tonic-gate CK_MECHANISM_INFO mech_info; 32500Sstevel@tonic-gate CK_RV rv; 32510Sstevel@tonic-gate 32527211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 32537211Sjp161948 fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech); 32547211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 32557211Sjp161948 rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info); 32560Sstevel@tonic-gate 32570Sstevel@tonic-gate if (rv != CKR_OK) 32580Sstevel@tonic-gate { 32597211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 32607211Sjp161948 fprintf(stderr, " not found\n"); 32617211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 32627211Sjp161948 return; 32630Sstevel@tonic-gate } 32640Sstevel@tonic-gate 32650Sstevel@tonic-gate if (mech_info.flags & CKF_DIGEST) 32660Sstevel@tonic-gate { 32677211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 32687211Sjp161948 if (nid_in_table(digests[id].nid, hw_dnids)) 32697211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 32707211Sjp161948 { 32717211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 32727211Sjp161948 fprintf(stderr, " usable\n"); 32737211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 32747211Sjp161948 local_digest_nids[(*current_slot_n_digest)++] = 32757211Sjp161948 digests[id].nid; 32767211Sjp161948 } 32777211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 32787211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 32797211Sjp161948 else 32807211Sjp161948 { 32817211Sjp161948 fprintf(stderr, " rejected, software implementation only\n"); 32827211Sjp161948 } 32837211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 32847211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 32857211Sjp161948 } 32867211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 32877211Sjp161948 else 32887211Sjp161948 { 32897211Sjp161948 fprintf(stderr, " unusable\n"); 32900Sstevel@tonic-gate } 32917211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 32927211Sjp161948 32937211Sjp161948 return; 32947211Sjp161948 } 32957211Sjp161948 32967211Sjp161948 #ifdef SOLARIS_AES_CTR 32977211Sjp161948 /* create a new NID when we have no OID for that mechanism */ 32987211Sjp161948 static int pk11_add_NID(char *sn, char *ln) 32997211Sjp161948 { 33007211Sjp161948 ASN1_OBJECT *o; 33017211Sjp161948 int nid; 33027211Sjp161948 33037211Sjp161948 if ((o = ASN1_OBJECT_create(OBJ_new_nid(1), (unsigned char *)"", 33047211Sjp161948 1, sn, ln)) == NULL) 33057211Sjp161948 { 33067211Sjp161948 return 0; 33077211Sjp161948 } 33087211Sjp161948 33097211Sjp161948 /* will return NID_undef on error */ 33107211Sjp161948 nid = OBJ_add_object(o); 33117211Sjp161948 ASN1_OBJECT_free(o); 33127211Sjp161948 33137211Sjp161948 return (nid); 33147211Sjp161948 } 33157211Sjp161948 33167211Sjp161948 /* 33177211Sjp161948 * Create new NIDs for AES counter mode. OpenSSL doesn't support them now so we 33187211Sjp161948 * have to help ourselves here. 33197211Sjp161948 */ 33207211Sjp161948 static int pk11_add_aes_ctr_NIDs(void) 33217211Sjp161948 { 33227211Sjp161948 /* are we already set? */ 33237211Sjp161948 if (NID_aes_256_ctr != NID_undef) 33247211Sjp161948 return 1; 33257211Sjp161948 33267211Sjp161948 /* 33277211Sjp161948 * There are no official names for AES counter modes yet so we just 33287211Sjp161948 * follow the format of those that exist. 33297211Sjp161948 */ 33307211Sjp161948 if ((NID_aes_128_ctr = pk11_add_NID("AES-128-CTR", "aes-128-ctr")) == 33317211Sjp161948 NID_undef) 33327211Sjp161948 goto err; 33337211Sjp161948 ciphers[PK11_AES_128_CTR].nid = pk11_aes_128_ctr.nid = NID_aes_128_ctr; 33347211Sjp161948 if ((NID_aes_192_ctr = pk11_add_NID("AES-192-CTR", "aes-192-ctr")) == 33357211Sjp161948 NID_undef) 33367211Sjp161948 goto err; 33377211Sjp161948 ciphers[PK11_AES_192_CTR].nid = pk11_aes_192_ctr.nid = NID_aes_192_ctr; 33387211Sjp161948 if ((NID_aes_256_ctr = pk11_add_NID("AES-256-CTR", "aes-256-ctr")) == 33397211Sjp161948 NID_undef) 33407211Sjp161948 goto err; 33417211Sjp161948 ciphers[PK11_AES_256_CTR].nid = pk11_aes_256_ctr.nid = NID_aes_256_ctr; 33420Sstevel@tonic-gate return 1; 33437211Sjp161948 33447211Sjp161948 err: 33457211Sjp161948 PK11err(PK11_F_ADD_AES_CTR_NIDS, PK11_R_ADD_NID_FAILED); 33467211Sjp161948 return 0; 33470Sstevel@tonic-gate } 33487211Sjp161948 #endif /* SOLARIS_AES_CTR */ 33497211Sjp161948 33507211Sjp161948 /* Find what symmetric ciphers this slot supports. */ 33517211Sjp161948 static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist, 33527211Sjp161948 CK_SLOT_ID current_slot, int *current_slot_n_cipher, int *local_cipher_nids) 33537211Sjp161948 { 33547211Sjp161948 int i; 33557211Sjp161948 33567211Sjp161948 for (i = 0; i < PK11_CIPHER_MAX; ++i) 33577211Sjp161948 { 33587211Sjp161948 pk11_get_symmetric_cipher(pflist, current_slot, 33597211Sjp161948 ciphers[i].mech_type, current_slot_n_cipher, 33607211Sjp161948 local_cipher_nids, ciphers[i].id); 33617211Sjp161948 } 33627211Sjp161948 } 33637211Sjp161948 33647211Sjp161948 /* Find what digest algorithms this slot supports. */ 33657211Sjp161948 static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist, 33667211Sjp161948 CK_SLOT_ID current_slot, int *current_slot_n_digest, int *local_digest_nids) 33677211Sjp161948 { 33687211Sjp161948 int i; 33697211Sjp161948 33707211Sjp161948 for (i = 0; i < PK11_DIGEST_MAX; ++i) 33717211Sjp161948 { 33727211Sjp161948 pk11_get_digest(pflist, current_slot, digests[i].mech_type, 33737211Sjp161948 current_slot_n_digest, local_digest_nids, digests[i].id); 33747211Sjp161948 } 33757211Sjp161948 } 33767211Sjp161948 33777211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 33787211Sjp161948 /* 33797211Sjp161948 * It would be great if we could use pkcs11_kernel directly since this library 33807211Sjp161948 * offers hardware slots only. That's the easiest way to achieve the situation 33817211Sjp161948 * where we use the hardware accelerators when present and OpenSSL native code 33827211Sjp161948 * otherwise. That presumes the fact that OpenSSL native code is faster than the 33837211Sjp161948 * code in the soft token. It's a logical assumption - Crypto Framework has some 33847211Sjp161948 * inherent overhead so going there for the software implementation of a 33857211Sjp161948 * mechanism should be logically slower in contrast to the OpenSSL native code, 33867211Sjp161948 * presuming that both implementations are of similar speed. For example, the 33877211Sjp161948 * soft token for AES is roughly three times slower than OpenSSL for 64 byte 33887211Sjp161948 * blocks and still 20% slower for 8KB blocks. So, if we want to ship products 33897211Sjp161948 * that use the PKCS#11 engine by default, we must somehow avoid that regression 33907211Sjp161948 * on machines without hardware acceleration. That's why switching to the 33917211Sjp161948 * pkcs11_kernel library seems like a very good idea. 33927211Sjp161948 * 33937211Sjp161948 * The problem is that OpenSSL built with SunStudio is roughly 2x slower for 33947211Sjp161948 * asymmetric operations (RSA/DSA/DH) than the soft token built with the same 33957211Sjp161948 * compiler. That means that if we switched to pkcs11_kernel from the libpkcs11 33967211Sjp161948 * library, we would have had a performance regression on machines without 33977211Sjp161948 * hardware acceleration for asymmetric operations for all applications that use 33987211Sjp161948 * the PKCS#11 engine. There is one such application - Apache web server since 33997211Sjp161948 * it's shipped configured to use the PKCS#11 engine by default. Having said 34007211Sjp161948 * that, we can't switch to the pkcs11_kernel library now and have to come with 34017211Sjp161948 * a solution that, on non-accelerated machines, uses the OpenSSL native code 34027211Sjp161948 * for all symmetric ciphers and digests while it uses the soft token for 34037211Sjp161948 * asymmetric operations. 34047211Sjp161948 * 34057211Sjp161948 * This is the idea: dlopen() pkcs11_kernel directly and find out what 34067211Sjp161948 * mechanisms are there. We don't care about duplications (more slots can 34077211Sjp161948 * support the same mechanism), we just want to know what mechanisms can be 34087211Sjp161948 * possibly supported in hardware on that particular machine. As said before, 34097211Sjp161948 * pkcs11_kernel will show you hardware providers only. 34107211Sjp161948 * 34117211Sjp161948 * Then, we rely on the fact that since we use libpkcs11 library we will find 34127211Sjp161948 * the metaslot. When we go through the metaslot's mechanisms for symmetric 34137211Sjp161948 * ciphers and digests, we check that any found mechanism is in the table 34147211Sjp161948 * created using the pkcs11_kernel library. So, as a result we have two arrays 34157211Sjp161948 * of mechanisms that were advertised as supported in hardware which was the 34167211Sjp161948 * goal of that whole excercise. Thus, we can use libpkcs11 but avoid soft token 34177211Sjp161948 * code for symmetric ciphers and digests. See pk11_choose_slots() for more 34187211Sjp161948 * information. 34197211Sjp161948 * 34207211Sjp161948 * This is Solaris specific code, if SOLARIS_HW_SLOT_SELECTION is not defined 34217211Sjp161948 * the code won't be used. 34227211Sjp161948 */ 34237211Sjp161948 #if defined(__sparcv9) || defined(__x86_64) || defined(__amd64) 34247211Sjp161948 static const char pkcs11_kernel[] = "/usr/lib/security/64/pkcs11_kernel.so.1"; 34257211Sjp161948 #else 34267211Sjp161948 static const char pkcs11_kernel[] = "/usr/lib/security/pkcs11_kernel.so.1"; 34277211Sjp161948 #endif 34287211Sjp161948 34297211Sjp161948 /* 34307211Sjp161948 * Check hardware capabilities of the machines. The output are two lists, 34317211Sjp161948 * hw_cnids and hw_dnids, that contain hardware mechanisms found in all hardware 34327211Sjp161948 * providers together. They are not sorted and may contain duplicate mechanisms. 34337211Sjp161948 */ 34347211Sjp161948 static int check_hw_mechanisms(void) 34357211Sjp161948 { 34367211Sjp161948 int i; 34377211Sjp161948 CK_RV rv; 34387211Sjp161948 void *handle; 34397211Sjp161948 CK_C_GetFunctionList p; 34407211Sjp161948 CK_TOKEN_INFO token_info; 34417211Sjp161948 CK_ULONG ulSlotCount = 0; 34427211Sjp161948 int n_cipher = 0, n_digest = 0; 34437211Sjp161948 CK_FUNCTION_LIST_PTR pflist = NULL; 34447211Sjp161948 CK_SLOT_ID_PTR pSlotList = NULL_PTR; 34457211Sjp161948 int *tmp_hw_cnids, *tmp_hw_dnids; 34467211Sjp161948 int hw_ctable_size, hw_dtable_size; 34477211Sjp161948 34487211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 34497211Sjp161948 fprintf(stderr, "%s: SOLARIS_HW_SLOT_SELECTION code running\n", 34507211Sjp161948 PK11_DBG); 34510Sstevel@tonic-gate #endif 34527211Sjp161948 if ((handle = dlopen(pkcs11_kernel, RTLD_LAZY)) == NULL) 34537211Sjp161948 { 34547211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); 34557211Sjp161948 goto err; 34567211Sjp161948 } 34577211Sjp161948 34587211Sjp161948 if ((p = (CK_C_GetFunctionList)dlsym(handle, 34597211Sjp161948 PK11_GET_FUNCTION_LIST)) == NULL) 34607211Sjp161948 { 34617211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); 34627211Sjp161948 goto err; 34637211Sjp161948 } 34647211Sjp161948 34657211Sjp161948 /* get the full function list from the loaded library 34667211Sjp161948 */ 34677211Sjp161948 if (p(&pflist) != CKR_OK) 34687211Sjp161948 { 34697211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); 34707211Sjp161948 goto err; 34717211Sjp161948 } 34727211Sjp161948 34737211Sjp161948 rv = pflist->C_Initialize(NULL_PTR); 34747211Sjp161948 if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) 34757211Sjp161948 { 34767211Sjp161948 PK11err_add_data(PK11_F_CHECK_HW_MECHANISMS, 34777211Sjp161948 PK11_R_INITIALIZE, rv); 34787211Sjp161948 goto err; 34797211Sjp161948 } 34807211Sjp161948 34817211Sjp161948 if (pflist->C_GetSlotList(0, NULL_PTR, &ulSlotCount) != CKR_OK) 34827211Sjp161948 { 34837211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); 34847211Sjp161948 goto err; 34857211Sjp161948 } 34867211Sjp161948 34877211Sjp161948 /* no slots, set the hw mechanism tables as empty */ 34887211Sjp161948 if (ulSlotCount == 0) 34897211Sjp161948 { 34907211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 34917211Sjp161948 fprintf(stderr, "%s: no hardware mechanisms found\n", PK11_DBG); 34920Sstevel@tonic-gate #endif 34937211Sjp161948 hw_cnids = OPENSSL_malloc(sizeof (int)); 34947211Sjp161948 hw_dnids = OPENSSL_malloc(sizeof (int)); 34957211Sjp161948 if (hw_cnids == NULL || hw_dnids == NULL) 34967211Sjp161948 { 34977211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, 34987211Sjp161948 PK11_R_MALLOC_FAILURE); 34997211Sjp161948 return (0); 35007211Sjp161948 } 35017211Sjp161948 /* this means empty tables */ 35027211Sjp161948 hw_cnids[0] = NID_undef; 35037211Sjp161948 hw_dnids[0] = NID_undef; 35047211Sjp161948 return (1); 35057211Sjp161948 } 35067211Sjp161948 35077211Sjp161948 pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); 35087211Sjp161948 if (pSlotList == NULL) 35097211Sjp161948 { 35107211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); 35117211Sjp161948 goto err; 35127211Sjp161948 } 35137211Sjp161948 35147211Sjp161948 /* Get the slot list for processing */ 35157211Sjp161948 if (pflist->C_GetSlotList(0, pSlotList, &ulSlotCount) != CKR_OK) 35167211Sjp161948 { 35177211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); 35187211Sjp161948 goto err; 35197211Sjp161948 } 35207211Sjp161948 35217211Sjp161948 /* 35227211Sjp161948 * We don't care about duplicit mechanisms in multiple slots and also 35237211Sjp161948 * reserve one slot for the terminal NID_undef which we use to stop the 35247211Sjp161948 * search. 35257211Sjp161948 */ 35267211Sjp161948 hw_ctable_size = ulSlotCount * PK11_CIPHER_MAX + 1; 35277211Sjp161948 hw_dtable_size = ulSlotCount * PK11_DIGEST_MAX + 1; 35287211Sjp161948 tmp_hw_cnids = OPENSSL_malloc(hw_ctable_size * sizeof (int)); 35297211Sjp161948 tmp_hw_dnids = OPENSSL_malloc(hw_dtable_size * sizeof (int)); 35307211Sjp161948 if (tmp_hw_cnids == NULL || tmp_hw_dnids == NULL) 35317211Sjp161948 { 35327211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); 35337211Sjp161948 goto err; 35347211Sjp161948 } 35357211Sjp161948 35367211Sjp161948 /* 35377211Sjp161948 * Do not use memset since we should not rely on the fact that NID_undef 35387211Sjp161948 * is zero now. 35397211Sjp161948 */ 35407211Sjp161948 for (i = 0; i < hw_ctable_size; ++i) 35417211Sjp161948 tmp_hw_cnids[i] = NID_undef; 35427211Sjp161948 for (i = 0; i < hw_dtable_size; ++i) 35437211Sjp161948 tmp_hw_dnids[i] = NID_undef; 35447211Sjp161948 35457211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 35467211Sjp161948 fprintf(stderr, "%s: provider: %s\n", PK11_DBG, pkcs11_kernel); 35477211Sjp161948 fprintf(stderr, "%s: found %d hardware slots\n", PK11_DBG, ulSlotCount); 35487211Sjp161948 fprintf(stderr, "%s: now looking for mechs supported in hw\n", 35497211Sjp161948 PK11_DBG); 35507211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 35517211Sjp161948 35527211Sjp161948 for (i = 0; i < ulSlotCount; i++) 35537211Sjp161948 { 35547211Sjp161948 if (pflist->C_GetTokenInfo(pSlotList[i], &token_info) != CKR_OK) 35557211Sjp161948 continue; 35567211Sjp161948 35577211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 35587211Sjp161948 fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); 35597211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 35607211Sjp161948 35617211Sjp161948 /* 35627211Sjp161948 * We are filling the hw mech tables here. Global tables are 35637211Sjp161948 * still NULL so all mechanisms are put into tmp tables. 35647211Sjp161948 */ 35657211Sjp161948 pk11_find_symmetric_ciphers(pflist, pSlotList[i], 35667211Sjp161948 &n_cipher, tmp_hw_cnids); 35677211Sjp161948 pk11_find_digests(pflist, pSlotList[i], 35687211Sjp161948 &n_digest, tmp_hw_dnids); 35697211Sjp161948 } 35707211Sjp161948 35717211Sjp161948 /* 35727211Sjp161948 * Since we are part of a library (libcrypto.so), calling this function 35737211Sjp161948 * may have side-effects. Also, C_Finalize() is triggered by 35747211Sjp161948 * dlclose(3C). 35757211Sjp161948 */ 35767211Sjp161948 #if 0 35777211Sjp161948 pflist->C_Finalize(NULL); 35787211Sjp161948 #endif 35797211Sjp161948 OPENSSL_free(pSlotList); 35807211Sjp161948 dlclose(handle); 35817211Sjp161948 hw_cnids = tmp_hw_cnids; 35827211Sjp161948 hw_dnids = tmp_hw_dnids; 35837211Sjp161948 35847211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 35857211Sjp161948 fprintf(stderr, "%s: hw mechs check complete\n", PK11_DBG); 35867211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 35877211Sjp161948 return (1); 35887211Sjp161948 35897211Sjp161948 err: 35907211Sjp161948 if (pSlotList != NULL) 35917211Sjp161948 OPENSSL_free(pSlotList); 35927211Sjp161948 if (tmp_hw_cnids != NULL) 35937211Sjp161948 OPENSSL_free(tmp_hw_cnids); 35947211Sjp161948 if (tmp_hw_dnids != NULL) 35957211Sjp161948 OPENSSL_free(tmp_hw_dnids); 35967211Sjp161948 35977211Sjp161948 return (0); 35987211Sjp161948 } 35997211Sjp161948 36007211Sjp161948 /* 36017211Sjp161948 * Check presence of a NID in the table of NIDs. The table may be NULL (i.e., 36027211Sjp161948 * non-existent). 36037211Sjp161948 */ 36047211Sjp161948 static int nid_in_table(int nid, int *nid_table) 36057211Sjp161948 { 36067211Sjp161948 int i = 0; 36077211Sjp161948 36087211Sjp161948 /* 36097211Sjp161948 * a special case. NULL means that we are initializing a new 36107211Sjp161948 * table. 36117211Sjp161948 */ 36127211Sjp161948 if (nid_table == NULL) 36137211Sjp161948 return (1); 36147211Sjp161948 36157211Sjp161948 /* 36167211Sjp161948 * the table is never full, there is always at least one 36177211Sjp161948 * NID_undef. 36187211Sjp161948 */ 36197211Sjp161948 while (nid_table[i] != NID_undef) 36207211Sjp161948 { 36217211Sjp161948 if (nid_table[i++] == nid) 36227211Sjp161948 { 36237211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 36247211Sjp161948 fprintf(stderr, " (NID %d in hw table, idx %d)", nid, i); 36257211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 36267211Sjp161948 return (1); 36277211Sjp161948 } 36287211Sjp161948 } 36297211Sjp161948 36307211Sjp161948 return (0); 36317211Sjp161948 } 36327211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 36337211Sjp161948 36347211Sjp161948 #endif /* OPENSSL_NO_HW_PK11 */ 36357211Sjp161948 #endif /* OPENSSL_NO_HW */ 3636