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 */ 7*7616SVladimir.Kotal@Sun.COM /* 8*7616SVladimir.Kotal@Sun.COM * This product includes software developed by the OpenSSL Project for 90Sstevel@tonic-gate * use in the OpenSSL Toolkit (http://www.openssl.org/). 100Sstevel@tonic-gate * 11*7616SVladimir.Kotal@Sun.COM * This project also referenced hw_pkcs11-0.9.7b.patch written by 120Sstevel@tonic-gate * Afchine Madjlessi. 130Sstevel@tonic-gate */ 14*7616SVladimir.Kotal@Sun.COM /* 15*7616SVladimir.Kotal@Sun.COM * ==================================================================== 160Sstevel@tonic-gate * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. 170Sstevel@tonic-gate * 180Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 190Sstevel@tonic-gate * modification, are permitted provided that the following conditions 200Sstevel@tonic-gate * are met: 210Sstevel@tonic-gate * 220Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 23*7616SVladimir.Kotal@Sun.COM * notice, this list of conditions and the following disclaimer. 240Sstevel@tonic-gate * 250Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 260Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in 270Sstevel@tonic-gate * the documentation and/or other materials provided with the 280Sstevel@tonic-gate * distribution. 290Sstevel@tonic-gate * 300Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this 310Sstevel@tonic-gate * software must display the following acknowledgment: 320Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project 330Sstevel@tonic-gate * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 340Sstevel@tonic-gate * 350Sstevel@tonic-gate * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 360Sstevel@tonic-gate * endorse or promote products derived from this software without 370Sstevel@tonic-gate * prior written permission. For written permission, please contact 380Sstevel@tonic-gate * licensing@OpenSSL.org. 390Sstevel@tonic-gate * 400Sstevel@tonic-gate * 5. Products derived from this software may not be called "OpenSSL" 410Sstevel@tonic-gate * nor may "OpenSSL" appear in their names without prior written 420Sstevel@tonic-gate * permission of the OpenSSL Project. 430Sstevel@tonic-gate * 440Sstevel@tonic-gate * 6. Redistributions of any form whatsoever must retain the following 450Sstevel@tonic-gate * acknowledgment: 460Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project 470Sstevel@tonic-gate * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 480Sstevel@tonic-gate * 490Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 500Sstevel@tonic-gate * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 510Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 520Sstevel@tonic-gate * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 530Sstevel@tonic-gate * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 540Sstevel@tonic-gate * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 550Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 560Sstevel@tonic-gate * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 570Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 580Sstevel@tonic-gate * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 590Sstevel@tonic-gate * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 600Sstevel@tonic-gate * OF THE POSSIBILITY OF SUCH DAMAGE. 610Sstevel@tonic-gate * ==================================================================== 620Sstevel@tonic-gate * 630Sstevel@tonic-gate * This product includes cryptographic software written by Eric Young 640Sstevel@tonic-gate * (eay@cryptsoft.com). This product includes software written by Tim 650Sstevel@tonic-gate * Hudson (tjh@cryptsoft.com). 660Sstevel@tonic-gate * 670Sstevel@tonic-gate */ 680Sstevel@tonic-gate 690Sstevel@tonic-gate #include <stdio.h> 700Sstevel@tonic-gate #include <stdlib.h> 710Sstevel@tonic-gate #include <string.h> 720Sstevel@tonic-gate #include <sys/types.h> 730Sstevel@tonic-gate #include <unistd.h> 740Sstevel@tonic-gate 750Sstevel@tonic-gate #include <openssl/e_os2.h> 766847Svk199839 #include <openssl/crypto.h> 770Sstevel@tonic-gate #include <openssl/engine.h> 780Sstevel@tonic-gate #include <openssl/dso.h> 790Sstevel@tonic-gate #include <openssl/err.h> 800Sstevel@tonic-gate #include <openssl/bn.h> 812139Sjp161948 #include <openssl/md5.h> 820Sstevel@tonic-gate #include <openssl/pem.h> 836847Svk199839 #ifndef OPENSSL_NO_RSA 840Sstevel@tonic-gate #include <openssl/rsa.h> 856847Svk199839 #endif 866847Svk199839 #ifndef OPENSSL_NO_DSA 876847Svk199839 #include <openssl/dsa.h> 886847Svk199839 #endif 896847Svk199839 #ifndef OPENSSL_NO_DH 906847Svk199839 #include <openssl/dh.h> 916847Svk199839 #endif 920Sstevel@tonic-gate #include <openssl/rand.h> 930Sstevel@tonic-gate #include <openssl/objects.h> 940Sstevel@tonic-gate #include <openssl/x509.h> 957211Sjp161948 #include <openssl/aes.h> 960Sstevel@tonic-gate #include <cryptlib.h> 977211Sjp161948 #include <dlfcn.h> 987526SVladimir.Kotal@Sun.COM #include <pthread.h> 990Sstevel@tonic-gate 1000Sstevel@tonic-gate #ifndef OPENSSL_NO_HW 1010Sstevel@tonic-gate #ifndef OPENSSL_NO_HW_PK11 1020Sstevel@tonic-gate 1037211Sjp161948 /* label for debug messages printed on stderr */ 1047211Sjp161948 #define PK11_DBG "PKCS#11 ENGINE DEBUG" 1057211Sjp161948 /* prints a lot of debug messages on stderr about slot selection process */ 1067211Sjp161948 #undef DEBUG_SLOT_SELECTION 1077211Sjp161948 /* 1087211Sjp161948 * Solaris specific code. See comment at check_hw_mechanisms() for more 1097211Sjp161948 * information. 1107211Sjp161948 */ 1117211Sjp161948 #define SOLARIS_HW_SLOT_SELECTION 1127211Sjp161948 1137211Sjp161948 /* 1147211Sjp161948 * AES counter mode is not supported in the OpenSSL EVP API yet and neither 1157211Sjp161948 * there are official OIDs for mechanisms based on this mode. With our changes, 1167211Sjp161948 * an application can define its own EVP calls for AES counter mode and then 1177211Sjp161948 * it can make use of hardware acceleration through this engine. However, it's 1187211Sjp161948 * better if we keep AES CTR support code under ifdef's. 1197211Sjp161948 */ 1207211Sjp161948 #define SOLARIS_AES_CTR 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate #include "security/cryptoki.h" 1230Sstevel@tonic-gate #include "security/pkcs11.h" 1240Sstevel@tonic-gate #include "hw_pk11_err.c" 1250Sstevel@tonic-gate 1267211Sjp161948 #ifdef SOLARIS_AES_CTR 1277211Sjp161948 /* 1287211Sjp161948 * NIDs for AES counter mode that will be defined during the engine 1297211Sjp161948 * initialization. 1307211Sjp161948 */ 1317211Sjp161948 int NID_aes_128_ctr = NID_undef; 1327211Sjp161948 int NID_aes_192_ctr = NID_undef; 1337211Sjp161948 int NID_aes_256_ctr = NID_undef; 1347211Sjp161948 #endif /* SOLARIS_AES_CTR */ 1357211Sjp161948 1367211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 1377211Sjp161948 /* 1387211Sjp161948 * Tables for symmetric ciphers and digest mechs found in the pkcs11_kernel 1397211Sjp161948 * library. See comment at check_hw_mechanisms() for more information. 1407211Sjp161948 */ 1417211Sjp161948 int *hw_cnids; 1427211Sjp161948 int *hw_dnids; 1437211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 1447211Sjp161948 1457526SVladimir.Kotal@Sun.COM /* PKCS#11 session caches and their locks for all operation types */ 1467526SVladimir.Kotal@Sun.COM static PK11_CACHE session_cache[OP_MAX]; 1477526SVladimir.Kotal@Sun.COM 1487211Sjp161948 /* 1497526SVladimir.Kotal@Sun.COM * As stated in v2.20, 11.7 Object Management Function, in section for 1507526SVladimir.Kotal@Sun.COM * C_FindObjectsInit(), at most one search operation may be active at a given 1517526SVladimir.Kotal@Sun.COM * time in a given session. Therefore, C_Find{,Init,Final}Objects() should be 1527526SVladimir.Kotal@Sun.COM * grouped together to form one atomic search operation. This is already 1537526SVladimir.Kotal@Sun.COM * ensured by the property of unique PKCS#11 session handle used for each 1547526SVladimir.Kotal@Sun.COM * PK11_SESSION object. 1557526SVladimir.Kotal@Sun.COM * 1567526SVladimir.Kotal@Sun.COM * This is however not the biggest concern - maintaining consistency of the 1577526SVladimir.Kotal@Sun.COM * underlying object store is more important. The same section of the spec also 1587526SVladimir.Kotal@Sun.COM * says that one thread can be in the middle of a search operation while another 1597526SVladimir.Kotal@Sun.COM * thread destroys the object matching the search template which would result in 1607526SVladimir.Kotal@Sun.COM * invalid handle returned from the search operation. 1617526SVladimir.Kotal@Sun.COM * 1627526SVladimir.Kotal@Sun.COM * Hence, the following locks are used for both protection of the object stores. 1637526SVladimir.Kotal@Sun.COM * They are also used for active list protection. 1647211Sjp161948 */ 1657526SVladimir.Kotal@Sun.COM pthread_mutex_t *find_lock[OP_MAX] = { NULL }; 1667526SVladimir.Kotal@Sun.COM 1677526SVladimir.Kotal@Sun.COM /* 1687526SVladimir.Kotal@Sun.COM * lists of asymmetric key handles which are active (referenced by at least one 1697526SVladimir.Kotal@Sun.COM * PK11_SESSION structure, either held by a thread or present in free_session 1707526SVladimir.Kotal@Sun.COM * list) for given algorithm type 1717526SVladimir.Kotal@Sun.COM */ 1727526SVladimir.Kotal@Sun.COM PK11_active *active_list[OP_MAX] = { NULL }; 1737526SVladimir.Kotal@Sun.COM 1747526SVladimir.Kotal@Sun.COM /* 1757526SVladimir.Kotal@Sun.COM * Create all secret key objects in a global session so that they are available 1760Sstevel@tonic-gate * to use for other sessions. These other sessions may be opened or closed 1777526SVladimir.Kotal@Sun.COM * without losing the secret key objects. 1787526SVladimir.Kotal@Sun.COM */ 1790Sstevel@tonic-gate static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE; 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate /* ENGINE level stuff */ 1820Sstevel@tonic-gate static int pk11_init(ENGINE *e); 1830Sstevel@tonic-gate static int pk11_library_init(ENGINE *e); 1840Sstevel@tonic-gate static int pk11_finish(ENGINE *e); 1850Sstevel@tonic-gate static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); 1860Sstevel@tonic-gate static int pk11_destroy(ENGINE *e); 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate /* RAND stuff */ 1890Sstevel@tonic-gate static void pk11_rand_seed(const void *buf, int num); 1900Sstevel@tonic-gate static void pk11_rand_add(const void *buf, int num, double add_entropy); 1910Sstevel@tonic-gate static void pk11_rand_cleanup(void); 1920Sstevel@tonic-gate static int pk11_rand_bytes(unsigned char *buf, int num); 1930Sstevel@tonic-gate static int pk11_rand_status(void); 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate /* These functions are also used in other files */ 1967211Sjp161948 PK11_SESSION *pk11_get_session(PK11_OPTYPE optype); 1977211Sjp161948 void pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype); 1986847Svk199839 1997526SVladimir.Kotal@Sun.COM /* active list manipulation functions used in this file */ 2007526SVladimir.Kotal@Sun.COM extern int pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type); 2017526SVladimir.Kotal@Sun.COM extern void pk11_free_active_list(PK11_OPTYPE type); 2026847Svk199839 2036847Svk199839 #ifndef OPENSSL_NO_RSA 2040Sstevel@tonic-gate int pk11_destroy_rsa_key_objects(PK11_SESSION *session); 2056847Svk199839 int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); 2066847Svk199839 int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); 2076847Svk199839 #endif 2086847Svk199839 #ifndef OPENSSL_NO_DSA 2090Sstevel@tonic-gate int pk11_destroy_dsa_key_objects(PK11_SESSION *session); 2106847Svk199839 int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); 2116847Svk199839 int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); 2126847Svk199839 #endif 2136847Svk199839 #ifndef OPENSSL_NO_DH 2140Sstevel@tonic-gate int pk11_destroy_dh_key_objects(PK11_SESSION *session); 2156847Svk199839 int pk11_destroy_dh_object(PK11_SESSION *session, CK_BBOOL uselock); 2166847Svk199839 #endif 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate /* Local helper functions */ 2197211Sjp161948 static int pk11_free_all_sessions(void); 2207526SVladimir.Kotal@Sun.COM static int pk11_free_session_list(PK11_OPTYPE optype); 2217211Sjp161948 static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype); 2220Sstevel@tonic-gate static int pk11_destroy_cipher_key_objects(PK11_SESSION *session); 2236847Svk199839 static int pk11_destroy_object(CK_SESSION_HANDLE session, 2240Sstevel@tonic-gate CK_OBJECT_HANDLE oh); 2250Sstevel@tonic-gate static const char *get_PK11_LIBNAME(void); 2260Sstevel@tonic-gate static void free_PK11_LIBNAME(void); 2270Sstevel@tonic-gate static long set_PK11_LIBNAME(const char *name); 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate /* Symmetric cipher and digest support functions */ 2300Sstevel@tonic-gate static int cipher_nid_to_pk11(int nid); 2317211Sjp161948 #ifdef SOLARIS_AES_CTR 2327211Sjp161948 static int pk11_add_NID(char *sn, char *ln); 2337211Sjp161948 static int pk11_add_aes_ctr_NIDs(void); 2347211Sjp161948 #endif /* SOLARIS_AES_CTR */ 2350Sstevel@tonic-gate static int pk11_usable_ciphers(const int **nids); 2360Sstevel@tonic-gate static int pk11_usable_digests(const int **nids); 2370Sstevel@tonic-gate static int pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, 2380Sstevel@tonic-gate const unsigned char *iv, int enc); 2390Sstevel@tonic-gate static int pk11_cipher_final(PK11_SESSION *sp); 2400Sstevel@tonic-gate static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 2410Sstevel@tonic-gate const unsigned char *in, unsigned int inl); 2420Sstevel@tonic-gate static int pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx); 2430Sstevel@tonic-gate static int pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 2440Sstevel@tonic-gate const int **nids, int nid); 2450Sstevel@tonic-gate static int pk11_engine_digests(ENGINE *e, const EVP_MD **digest, 2460Sstevel@tonic-gate const int **nids, int nid); 247*7616SVladimir.Kotal@Sun.COM static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, 2480Sstevel@tonic-gate const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp); 2497211Sjp161948 static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key, 2507211Sjp161948 int key_len); 2510Sstevel@tonic-gate static int md_nid_to_pk11(int nid); 2520Sstevel@tonic-gate static int pk11_digest_init(EVP_MD_CTX *ctx); 253*7616SVladimir.Kotal@Sun.COM static int pk11_digest_update(EVP_MD_CTX *ctx, const void *data, 2542139Sjp161948 size_t count); 255*7616SVladimir.Kotal@Sun.COM static int pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md); 256*7616SVladimir.Kotal@Sun.COM static int pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from); 2570Sstevel@tonic-gate static int pk11_digest_cleanup(EVP_MD_CTX *ctx); 2580Sstevel@tonic-gate 2597211Sjp161948 static int pk11_choose_slots(int *any_slot_found); 2607211Sjp161948 static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist, 2617211Sjp161948 CK_SLOT_ID current_slot, int *current_slot_n_cipher, 2627211Sjp161948 int *local_cipher_nids); 2637211Sjp161948 static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist, 2647211Sjp161948 CK_SLOT_ID current_slot, int *current_slot_n_digest, 2657211Sjp161948 int *local_digest_nids); 2667211Sjp161948 static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR, int slot_id, 2677211Sjp161948 CK_MECHANISM_TYPE mech, int *current_slot_n_cipher, int *local_cipher_nids, 2687211Sjp161948 int id); 2697211Sjp161948 static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id, 2707211Sjp161948 CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids, 2717211Sjp161948 int id); 2727211Sjp161948 2737526SVladimir.Kotal@Sun.COM static int pk11_init_all_locks(void); 2747526SVladimir.Kotal@Sun.COM static void pk11_free_all_locks(void); 2757526SVladimir.Kotal@Sun.COM 2767211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 2777211Sjp161948 static int check_hw_mechanisms(void); 2787211Sjp161948 static int nid_in_table(int nid, int *nid_table); 2797211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 2800Sstevel@tonic-gate 2810Sstevel@tonic-gate /* Index for the supported ciphers */ 2827211Sjp161948 enum pk11_cipher_id { 2837211Sjp161948 PK11_DES_CBC, 2847211Sjp161948 PK11_DES3_CBC, 2857211Sjp161948 PK11_DES_ECB, 2867211Sjp161948 PK11_DES3_ECB, 2877211Sjp161948 PK11_RC4, 2887211Sjp161948 PK11_AES_128_CBC, 2897211Sjp161948 PK11_AES_192_CBC, 2907211Sjp161948 PK11_AES_256_CBC, 2917211Sjp161948 PK11_AES_128_ECB, 2927211Sjp161948 PK11_AES_192_ECB, 2937211Sjp161948 PK11_AES_256_ECB, 2947211Sjp161948 PK11_BLOWFISH_CBC, 2957211Sjp161948 #ifdef SOLARIS_AES_CTR 2967211Sjp161948 PK11_AES_128_CTR, 2977211Sjp161948 PK11_AES_192_CTR, 2987211Sjp161948 PK11_AES_256_CTR, 2997211Sjp161948 #endif /* SOLARIS_AES_CTR */ 3007211Sjp161948 PK11_CIPHER_MAX 3017211Sjp161948 }; 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate /* Index for the supported digests */ 3047211Sjp161948 enum pk11_digest_id { 3057211Sjp161948 PK11_MD5, 3067211Sjp161948 PK11_SHA1, 3077211Sjp161948 PK11_SHA224, 3087211Sjp161948 PK11_SHA256, 3097211Sjp161948 PK11_SHA384, 3107211Sjp161948 PK11_SHA512, 3117211Sjp161948 PK11_DIGEST_MAX 3127211Sjp161948 }; 3130Sstevel@tonic-gate 3147526SVladimir.Kotal@Sun.COM #define TRY_OBJ_DESTROY(sess_hdl, obj_hdl, retval, uselock, alg_type) \ 3156847Svk199839 { \ 3166847Svk199839 if (uselock) \ 3177526SVladimir.Kotal@Sun.COM LOCK_OBJSTORE(alg_type); \ 3187526SVladimir.Kotal@Sun.COM if (pk11_active_delete(obj_hdl, alg_type) == 1) \ 3196847Svk199839 { \ 3206847Svk199839 retval = pk11_destroy_object(sess_hdl, obj_hdl); \ 3216847Svk199839 } \ 3226847Svk199839 if (uselock) \ 3237526SVladimir.Kotal@Sun.COM UNLOCK_OBJSTORE(alg_type); \ 3246847Svk199839 } 3256847Svk199839 3260Sstevel@tonic-gate static int cipher_nids[PK11_CIPHER_MAX]; 3270Sstevel@tonic-gate static int digest_nids[PK11_DIGEST_MAX]; 3280Sstevel@tonic-gate static int cipher_count = 0; 3290Sstevel@tonic-gate static int digest_count = 0; 3300Sstevel@tonic-gate static CK_BBOOL pk11_have_rsa = CK_FALSE; 3310Sstevel@tonic-gate static CK_BBOOL pk11_have_dsa = CK_FALSE; 3320Sstevel@tonic-gate static CK_BBOOL pk11_have_dh = CK_FALSE; 3330Sstevel@tonic-gate static CK_BBOOL pk11_have_random = CK_FALSE; 3340Sstevel@tonic-gate 335*7616SVladimir.Kotal@Sun.COM typedef struct PK11_CIPHER_st 3360Sstevel@tonic-gate { 3377211Sjp161948 enum pk11_cipher_id id; 3384320Sjp161948 int nid; 3397211Sjp161948 int iv_len; 3404320Sjp161948 int key_len; 3414320Sjp161948 CK_KEY_TYPE key_type; 3424320Sjp161948 CK_MECHANISM_TYPE mech_type; 3430Sstevel@tonic-gate } PK11_CIPHER; 3440Sstevel@tonic-gate 345*7616SVladimir.Kotal@Sun.COM static PK11_CIPHER ciphers[] = 3460Sstevel@tonic-gate { 347*7616SVladimir.Kotal@Sun.COM { PK11_DES_CBC, NID_des_cbc, 8, 8, 348*7616SVladimir.Kotal@Sun.COM CKK_DES, CKM_DES_CBC, }, 349*7616SVladimir.Kotal@Sun.COM { PK11_DES3_CBC, NID_des_ede3_cbc, 8, 24, 350*7616SVladimir.Kotal@Sun.COM CKK_DES3, CKM_DES3_CBC, }, 351*7616SVladimir.Kotal@Sun.COM { PK11_DES_ECB, NID_des_ecb, 0, 8, 352*7616SVladimir.Kotal@Sun.COM CKK_DES, CKM_DES_ECB, }, 353*7616SVladimir.Kotal@Sun.COM { PK11_DES3_ECB, NID_des_ede3_ecb, 0, 24, 354*7616SVladimir.Kotal@Sun.COM CKK_DES3, CKM_DES3_ECB, }, 355*7616SVladimir.Kotal@Sun.COM { PK11_RC4, NID_rc4, 0, 16, 356*7616SVladimir.Kotal@Sun.COM CKK_RC4, CKM_RC4, }, 357*7616SVladimir.Kotal@Sun.COM { PK11_AES_128_CBC, NID_aes_128_cbc, 16, 16, 358*7616SVladimir.Kotal@Sun.COM CKK_AES, CKM_AES_CBC, }, 359*7616SVladimir.Kotal@Sun.COM { PK11_AES_192_CBC, NID_aes_192_cbc, 16, 24, 360*7616SVladimir.Kotal@Sun.COM CKK_AES, CKM_AES_CBC, }, 361*7616SVladimir.Kotal@Sun.COM { PK11_AES_256_CBC, NID_aes_256_cbc, 16, 32, 362*7616SVladimir.Kotal@Sun.COM CKK_AES, CKM_AES_CBC, }, 363*7616SVladimir.Kotal@Sun.COM { PK11_AES_128_ECB, NID_aes_128_ecb, 0, 16, 364*7616SVladimir.Kotal@Sun.COM CKK_AES, CKM_AES_ECB, }, 365*7616SVladimir.Kotal@Sun.COM { PK11_AES_192_ECB, NID_aes_192_ecb, 0, 24, 366*7616SVladimir.Kotal@Sun.COM CKK_AES, CKM_AES_ECB, }, 367*7616SVladimir.Kotal@Sun.COM { PK11_AES_256_ECB, NID_aes_256_ecb, 0, 32, 368*7616SVladimir.Kotal@Sun.COM CKK_AES, CKM_AES_ECB, }, 369*7616SVladimir.Kotal@Sun.COM { PK11_BLOWFISH_CBC, NID_bf_cbc, 8, 16, 370*7616SVladimir.Kotal@Sun.COM CKK_BLOWFISH, CKM_BLOWFISH_CBC, }, 3717211Sjp161948 #ifdef SOLARIS_AES_CTR 3727211Sjp161948 /* we don't know the correct NIDs until the engine is initialized */ 373*7616SVladimir.Kotal@Sun.COM { PK11_AES_128_CTR, NID_undef, 16, 16, 374*7616SVladimir.Kotal@Sun.COM CKK_AES, CKM_AES_CTR, }, 375*7616SVladimir.Kotal@Sun.COM { PK11_AES_192_CTR, NID_undef, 16, 24, 376*7616SVladimir.Kotal@Sun.COM CKK_AES, CKM_AES_CTR, }, 377*7616SVladimir.Kotal@Sun.COM { PK11_AES_256_CTR, NID_undef, 16, 32, 378*7616SVladimir.Kotal@Sun.COM CKK_AES, CKM_AES_CTR, }, 3797211Sjp161948 #endif /* SOLARIS_AES_CTR */ 3800Sstevel@tonic-gate }; 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate typedef struct PK11_DIGEST_st 3830Sstevel@tonic-gate { 3847211Sjp161948 enum pk11_digest_id id; 3854320Sjp161948 int nid; 3864320Sjp161948 CK_MECHANISM_TYPE mech_type; 3870Sstevel@tonic-gate } PK11_DIGEST; 3880Sstevel@tonic-gate 389*7616SVladimir.Kotal@Sun.COM static PK11_DIGEST digests[] = 3900Sstevel@tonic-gate { 3914320Sjp161948 {PK11_MD5, NID_md5, CKM_MD5, }, 3924320Sjp161948 {PK11_SHA1, NID_sha1, CKM_SHA_1, }, 3937211Sjp161948 {PK11_SHA224, NID_sha224, CKM_SHA224, }, 3947211Sjp161948 {PK11_SHA256, NID_sha256, CKM_SHA256, }, 3957211Sjp161948 {PK11_SHA384, NID_sha384, CKM_SHA384, }, 3967211Sjp161948 {PK11_SHA512, NID_sha512, CKM_SHA512, }, 3974320Sjp161948 {0, NID_undef, 0xFFFF, }, 3980Sstevel@tonic-gate }; 3990Sstevel@tonic-gate 400*7616SVladimir.Kotal@Sun.COM /* 401*7616SVladimir.Kotal@Sun.COM * Structure to be used for the cipher_data/md_data in 402*7616SVladimir.Kotal@Sun.COM * EVP_CIPHER_CTX/EVP_MD_CTX structures in order to use the same pk11 403*7616SVladimir.Kotal@Sun.COM * session in multiple cipher_update calls 4040Sstevel@tonic-gate */ 4050Sstevel@tonic-gate typedef struct PK11_CIPHER_STATE_st 4060Sstevel@tonic-gate { 4070Sstevel@tonic-gate PK11_SESSION *sp; 4080Sstevel@tonic-gate } PK11_CIPHER_STATE; 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate 4117211Sjp161948 /* 4127211Sjp161948 * libcrypto EVP stuff - this is how we get wired to EVP so the engine gets 4137211Sjp161948 * called when libcrypto requests a cipher NID. 4147211Sjp161948 * 4150Sstevel@tonic-gate * Note how the PK11_CIPHER_STATE is used here. 4160Sstevel@tonic-gate */ 4170Sstevel@tonic-gate 4180Sstevel@tonic-gate /* DES CBC EVP */ 419*7616SVladimir.Kotal@Sun.COM static const EVP_CIPHER pk11_des_cbc = 4200Sstevel@tonic-gate { 4210Sstevel@tonic-gate NID_des_cbc, 4220Sstevel@tonic-gate 8, 8, 8, 4230Sstevel@tonic-gate EVP_CIPH_CBC_MODE, 4240Sstevel@tonic-gate pk11_cipher_init, 4250Sstevel@tonic-gate pk11_cipher_do_cipher, 4260Sstevel@tonic-gate pk11_cipher_cleanup, 427*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 4280Sstevel@tonic-gate EVP_CIPHER_set_asn1_iv, 4290Sstevel@tonic-gate EVP_CIPHER_get_asn1_iv, 4300Sstevel@tonic-gate NULL 4310Sstevel@tonic-gate }; 4320Sstevel@tonic-gate 4330Sstevel@tonic-gate /* 3DES CBC EVP */ 434*7616SVladimir.Kotal@Sun.COM static const EVP_CIPHER pk11_3des_cbc = 4350Sstevel@tonic-gate { 4360Sstevel@tonic-gate NID_des_ede3_cbc, 4370Sstevel@tonic-gate 8, 24, 8, 4380Sstevel@tonic-gate EVP_CIPH_CBC_MODE, 4390Sstevel@tonic-gate pk11_cipher_init, 4400Sstevel@tonic-gate pk11_cipher_do_cipher, 4410Sstevel@tonic-gate pk11_cipher_cleanup, 442*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 4430Sstevel@tonic-gate EVP_CIPHER_set_asn1_iv, 4440Sstevel@tonic-gate EVP_CIPHER_get_asn1_iv, 4450Sstevel@tonic-gate NULL 4460Sstevel@tonic-gate }; 4470Sstevel@tonic-gate 4487211Sjp161948 /* 4497211Sjp161948 * ECB modes don't use an Initial Vector so that's why set_asn1_parameters and 4507211Sjp161948 * get_asn1_parameters fields are set to NULL. 4517211Sjp161948 */ 452*7616SVladimir.Kotal@Sun.COM static const EVP_CIPHER pk11_des_ecb = 4537211Sjp161948 { 4547211Sjp161948 NID_des_ecb, 4557211Sjp161948 8, 8, 8, 4567211Sjp161948 EVP_CIPH_ECB_MODE, 4577211Sjp161948 pk11_cipher_init, 4587211Sjp161948 pk11_cipher_do_cipher, 4597211Sjp161948 pk11_cipher_cleanup, 460*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 4617211Sjp161948 NULL, 4627211Sjp161948 NULL, 4637211Sjp161948 NULL 4647211Sjp161948 }; 4657211Sjp161948 466*7616SVladimir.Kotal@Sun.COM static const EVP_CIPHER pk11_3des_ecb = 4677211Sjp161948 { 4687211Sjp161948 NID_des_ede3_ecb, 4697211Sjp161948 8, 24, 8, 4707211Sjp161948 EVP_CIPH_ECB_MODE, 4717211Sjp161948 pk11_cipher_init, 4727211Sjp161948 pk11_cipher_do_cipher, 4737211Sjp161948 pk11_cipher_cleanup, 474*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 4757211Sjp161948 NULL, 4767211Sjp161948 NULL, 4777211Sjp161948 NULL 4787211Sjp161948 }; 4797211Sjp161948 4807211Sjp161948 481*7616SVladimir.Kotal@Sun.COM static const EVP_CIPHER pk11_aes_128_cbc = 4820Sstevel@tonic-gate { 4830Sstevel@tonic-gate NID_aes_128_cbc, 4840Sstevel@tonic-gate 16, 16, 16, 4850Sstevel@tonic-gate EVP_CIPH_CBC_MODE, 4860Sstevel@tonic-gate pk11_cipher_init, 4870Sstevel@tonic-gate pk11_cipher_do_cipher, 4880Sstevel@tonic-gate pk11_cipher_cleanup, 489*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 4900Sstevel@tonic-gate EVP_CIPHER_set_asn1_iv, 4910Sstevel@tonic-gate EVP_CIPHER_get_asn1_iv, 4920Sstevel@tonic-gate NULL 4930Sstevel@tonic-gate }; 4940Sstevel@tonic-gate 495*7616SVladimir.Kotal@Sun.COM static const EVP_CIPHER pk11_aes_192_cbc = 4967211Sjp161948 { 4977211Sjp161948 NID_aes_192_cbc, 4987211Sjp161948 16, 24, 16, 4997211Sjp161948 EVP_CIPH_CBC_MODE, 5007211Sjp161948 pk11_cipher_init, 5017211Sjp161948 pk11_cipher_do_cipher, 5027211Sjp161948 pk11_cipher_cleanup, 503*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 5047211Sjp161948 EVP_CIPHER_set_asn1_iv, 5057211Sjp161948 EVP_CIPHER_get_asn1_iv, 5067211Sjp161948 NULL 5077211Sjp161948 }; 5087211Sjp161948 509*7616SVladimir.Kotal@Sun.COM static const EVP_CIPHER pk11_aes_256_cbc = 5107211Sjp161948 { 5117211Sjp161948 NID_aes_256_cbc, 5127211Sjp161948 16, 32, 16, 5137211Sjp161948 EVP_CIPH_CBC_MODE, 5147211Sjp161948 pk11_cipher_init, 5157211Sjp161948 pk11_cipher_do_cipher, 5167211Sjp161948 pk11_cipher_cleanup, 517*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 5187211Sjp161948 EVP_CIPHER_set_asn1_iv, 5197211Sjp161948 EVP_CIPHER_get_asn1_iv, 5207211Sjp161948 NULL 5217211Sjp161948 }; 5227211Sjp161948 5237211Sjp161948 /* 5247211Sjp161948 * ECB modes don't use IV so that's why set_asn1_parameters and 5257211Sjp161948 * get_asn1_parameters are set to NULL. 5267211Sjp161948 */ 527*7616SVladimir.Kotal@Sun.COM static const EVP_CIPHER pk11_aes_128_ecb = 5287211Sjp161948 { 5297211Sjp161948 NID_aes_128_ecb, 5307211Sjp161948 16, 16, 0, 5317211Sjp161948 EVP_CIPH_ECB_MODE, 5327211Sjp161948 pk11_cipher_init, 5337211Sjp161948 pk11_cipher_do_cipher, 5347211Sjp161948 pk11_cipher_cleanup, 535*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 5367211Sjp161948 NULL, 5377211Sjp161948 NULL, 5387211Sjp161948 NULL 5397211Sjp161948 }; 5407211Sjp161948 541*7616SVladimir.Kotal@Sun.COM static const EVP_CIPHER pk11_aes_192_ecb = 5427211Sjp161948 { 5437211Sjp161948 NID_aes_192_ecb, 5447211Sjp161948 16, 24, 0, 5457211Sjp161948 EVP_CIPH_ECB_MODE, 5467211Sjp161948 pk11_cipher_init, 5477211Sjp161948 pk11_cipher_do_cipher, 5487211Sjp161948 pk11_cipher_cleanup, 549*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 5507211Sjp161948 NULL, 5517211Sjp161948 NULL, 5527211Sjp161948 NULL 5537211Sjp161948 }; 5547211Sjp161948 555*7616SVladimir.Kotal@Sun.COM static const EVP_CIPHER pk11_aes_256_ecb = 5567211Sjp161948 { 5577211Sjp161948 NID_aes_256_ecb, 5587211Sjp161948 16, 32, 0, 5597211Sjp161948 EVP_CIPH_ECB_MODE, 5607211Sjp161948 pk11_cipher_init, 5617211Sjp161948 pk11_cipher_do_cipher, 5627211Sjp161948 pk11_cipher_cleanup, 563*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 5647211Sjp161948 NULL, 5657211Sjp161948 NULL, 5667211Sjp161948 NULL 5677211Sjp161948 }; 5687211Sjp161948 5697211Sjp161948 #ifdef SOLARIS_AES_CTR 5707211Sjp161948 /* 5717211Sjp161948 * NID_undef's will be changed to the AES counter mode NIDs as soon they are 5727211Sjp161948 * created in pk11_library_init(). Note that the need to change these structures 5737211Sjp161948 * is the reason why we don't define them with the const keyword. 5747211Sjp161948 */ 575*7616SVladimir.Kotal@Sun.COM static EVP_CIPHER pk11_aes_128_ctr = 5767211Sjp161948 { 5777211Sjp161948 NID_undef, 5787211Sjp161948 16, 16, 16, 5797211Sjp161948 EVP_CIPH_CBC_MODE, 5807211Sjp161948 pk11_cipher_init, 5817211Sjp161948 pk11_cipher_do_cipher, 5827211Sjp161948 pk11_cipher_cleanup, 583*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 5847211Sjp161948 EVP_CIPHER_set_asn1_iv, 5857211Sjp161948 EVP_CIPHER_get_asn1_iv, 5867211Sjp161948 NULL 5877211Sjp161948 }; 5887211Sjp161948 589*7616SVladimir.Kotal@Sun.COM static EVP_CIPHER pk11_aes_192_ctr = 5907211Sjp161948 { 5917211Sjp161948 NID_undef, 5927211Sjp161948 16, 24, 16, 5937211Sjp161948 EVP_CIPH_CBC_MODE, 5947211Sjp161948 pk11_cipher_init, 5957211Sjp161948 pk11_cipher_do_cipher, 5967211Sjp161948 pk11_cipher_cleanup, 597*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 5987211Sjp161948 EVP_CIPHER_set_asn1_iv, 5997211Sjp161948 EVP_CIPHER_get_asn1_iv, 6007211Sjp161948 NULL 6017211Sjp161948 }; 6027211Sjp161948 603*7616SVladimir.Kotal@Sun.COM static EVP_CIPHER pk11_aes_256_ctr = 6047211Sjp161948 { 6057211Sjp161948 NID_undef, 6067211Sjp161948 16, 32, 16, 6077211Sjp161948 EVP_CIPH_CBC_MODE, 6087211Sjp161948 pk11_cipher_init, 6097211Sjp161948 pk11_cipher_do_cipher, 6107211Sjp161948 pk11_cipher_cleanup, 611*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 6127211Sjp161948 EVP_CIPHER_set_asn1_iv, 6137211Sjp161948 EVP_CIPHER_get_asn1_iv, 6147211Sjp161948 NULL 6157211Sjp161948 }; 6167211Sjp161948 #endif /* SOLARIS_AES_CTR */ 6177211Sjp161948 618*7616SVladimir.Kotal@Sun.COM static const EVP_CIPHER pk11_bf_cbc = 6197211Sjp161948 { 6207211Sjp161948 NID_bf_cbc, 6217211Sjp161948 8, 16, 8, 6227211Sjp161948 EVP_CIPH_VARIABLE_LENGTH, 6237211Sjp161948 pk11_cipher_init, 6247211Sjp161948 pk11_cipher_do_cipher, 6257211Sjp161948 pk11_cipher_cleanup, 626*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 6277211Sjp161948 EVP_CIPHER_set_asn1_iv, 6287211Sjp161948 EVP_CIPHER_get_asn1_iv, 6297211Sjp161948 NULL 6307211Sjp161948 }; 6317211Sjp161948 6320Sstevel@tonic-gate static const EVP_CIPHER pk11_rc4 = 6330Sstevel@tonic-gate { 6340Sstevel@tonic-gate NID_rc4, 6357211Sjp161948 1, 16, 0, 6360Sstevel@tonic-gate EVP_CIPH_VARIABLE_LENGTH, 6370Sstevel@tonic-gate pk11_cipher_init, 6380Sstevel@tonic-gate pk11_cipher_do_cipher, 6390Sstevel@tonic-gate pk11_cipher_cleanup, 640*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 6410Sstevel@tonic-gate NULL, 6420Sstevel@tonic-gate NULL, 6430Sstevel@tonic-gate NULL 6440Sstevel@tonic-gate }; 6450Sstevel@tonic-gate 6460Sstevel@tonic-gate static const EVP_MD pk11_md5 = 6470Sstevel@tonic-gate { 6480Sstevel@tonic-gate NID_md5, 6490Sstevel@tonic-gate NID_md5WithRSAEncryption, 6500Sstevel@tonic-gate MD5_DIGEST_LENGTH, 6510Sstevel@tonic-gate 0, 6520Sstevel@tonic-gate pk11_digest_init, 6530Sstevel@tonic-gate pk11_digest_update, 6540Sstevel@tonic-gate pk11_digest_final, 6550Sstevel@tonic-gate pk11_digest_copy, 6560Sstevel@tonic-gate pk11_digest_cleanup, 6570Sstevel@tonic-gate EVP_PKEY_RSA_method, 6580Sstevel@tonic-gate MD5_CBLOCK, 659*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 6600Sstevel@tonic-gate }; 6610Sstevel@tonic-gate 6620Sstevel@tonic-gate static const EVP_MD pk11_sha1 = 6630Sstevel@tonic-gate { 6640Sstevel@tonic-gate NID_sha1, 6650Sstevel@tonic-gate NID_sha1WithRSAEncryption, 6660Sstevel@tonic-gate SHA_DIGEST_LENGTH, 6670Sstevel@tonic-gate 0, 6680Sstevel@tonic-gate pk11_digest_init, 6690Sstevel@tonic-gate pk11_digest_update, 6700Sstevel@tonic-gate pk11_digest_final, 6710Sstevel@tonic-gate pk11_digest_copy, 6720Sstevel@tonic-gate pk11_digest_cleanup, 6730Sstevel@tonic-gate EVP_PKEY_RSA_method, 6740Sstevel@tonic-gate SHA_CBLOCK, 675*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 6760Sstevel@tonic-gate }; 6770Sstevel@tonic-gate 6787211Sjp161948 static const EVP_MD pk11_sha224 = 6797211Sjp161948 { 6807211Sjp161948 NID_sha224, 6817211Sjp161948 NID_sha224WithRSAEncryption, 6827211Sjp161948 SHA224_DIGEST_LENGTH, 6837211Sjp161948 0, 6847211Sjp161948 pk11_digest_init, 6857211Sjp161948 pk11_digest_update, 6867211Sjp161948 pk11_digest_final, 6877211Sjp161948 pk11_digest_copy, 6887211Sjp161948 pk11_digest_cleanup, 6897211Sjp161948 EVP_PKEY_RSA_method, 6907211Sjp161948 /* SHA-224 uses the same cblock size as SHA-256 */ 6917211Sjp161948 SHA256_CBLOCK, 692*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 6937211Sjp161948 }; 6947211Sjp161948 6957211Sjp161948 static const EVP_MD pk11_sha256 = 6967211Sjp161948 { 6977211Sjp161948 NID_sha256, 6987211Sjp161948 NID_sha256WithRSAEncryption, 6997211Sjp161948 SHA256_DIGEST_LENGTH, 7007211Sjp161948 0, 7017211Sjp161948 pk11_digest_init, 7027211Sjp161948 pk11_digest_update, 7037211Sjp161948 pk11_digest_final, 7047211Sjp161948 pk11_digest_copy, 7057211Sjp161948 pk11_digest_cleanup, 7067211Sjp161948 EVP_PKEY_RSA_method, 7077211Sjp161948 SHA256_CBLOCK, 708*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 7097211Sjp161948 }; 7107211Sjp161948 7117211Sjp161948 static const EVP_MD pk11_sha384 = 7127211Sjp161948 { 7137211Sjp161948 NID_sha384, 7147211Sjp161948 NID_sha384WithRSAEncryption, 7157211Sjp161948 SHA384_DIGEST_LENGTH, 7167211Sjp161948 0, 7177211Sjp161948 pk11_digest_init, 7187211Sjp161948 pk11_digest_update, 7197211Sjp161948 pk11_digest_final, 7207211Sjp161948 pk11_digest_copy, 7217211Sjp161948 pk11_digest_cleanup, 7227211Sjp161948 EVP_PKEY_RSA_method, 7237211Sjp161948 /* SHA-384 uses the same cblock size as SHA-512 */ 7247211Sjp161948 SHA512_CBLOCK, 725*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 7267211Sjp161948 }; 7277211Sjp161948 7287211Sjp161948 static const EVP_MD pk11_sha512 = 7297211Sjp161948 { 7307211Sjp161948 NID_sha512, 7317211Sjp161948 NID_sha512WithRSAEncryption, 7327211Sjp161948 SHA512_DIGEST_LENGTH, 7337211Sjp161948 0, 7347211Sjp161948 pk11_digest_init, 7357211Sjp161948 pk11_digest_update, 7367211Sjp161948 pk11_digest_final, 7377211Sjp161948 pk11_digest_copy, 7387211Sjp161948 pk11_digest_cleanup, 7397211Sjp161948 EVP_PKEY_RSA_method, 7407211Sjp161948 SHA512_CBLOCK, 741*7616SVladimir.Kotal@Sun.COM sizeof (PK11_CIPHER_STATE), 7427211Sjp161948 }; 7437211Sjp161948 744*7616SVladimir.Kotal@Sun.COM /* 745*7616SVladimir.Kotal@Sun.COM * Initialization function. Sets up various PKCS#11 library components. 746*7616SVladimir.Kotal@Sun.COM * The definitions for control commands specific to this engine 7470Sstevel@tonic-gate */ 748*7616SVladimir.Kotal@Sun.COM #define PK11_CMD_SO_PATH ENGINE_CMD_BASE 7490Sstevel@tonic-gate static const ENGINE_CMD_DEFN pk11_cmd_defns[] = 7500Sstevel@tonic-gate { 7510Sstevel@tonic-gate { 7520Sstevel@tonic-gate PK11_CMD_SO_PATH, 7530Sstevel@tonic-gate "SO_PATH", 7540Sstevel@tonic-gate "Specifies the path to the 'pkcs#11' shared library", 7550Sstevel@tonic-gate ENGINE_CMD_FLAG_STRING 7560Sstevel@tonic-gate }, 7570Sstevel@tonic-gate {0, NULL, NULL, 0} 7580Sstevel@tonic-gate }; 7590Sstevel@tonic-gate 7600Sstevel@tonic-gate 7610Sstevel@tonic-gate static RAND_METHOD pk11_random = 7620Sstevel@tonic-gate { 7630Sstevel@tonic-gate pk11_rand_seed, 7640Sstevel@tonic-gate pk11_rand_bytes, 7650Sstevel@tonic-gate pk11_rand_cleanup, 7660Sstevel@tonic-gate pk11_rand_add, 7670Sstevel@tonic-gate pk11_rand_bytes, 7680Sstevel@tonic-gate pk11_rand_status 7690Sstevel@tonic-gate }; 7700Sstevel@tonic-gate 7710Sstevel@tonic-gate 772*7616SVladimir.Kotal@Sun.COM /* Constants used when creating the ENGINE */ 7730Sstevel@tonic-gate static const char *engine_pk11_id = "pkcs11"; 7740Sstevel@tonic-gate static const char *engine_pk11_name = "PKCS #11 engine support"; 7750Sstevel@tonic-gate 7760Sstevel@tonic-gate CK_FUNCTION_LIST_PTR pFuncList = NULL; 7770Sstevel@tonic-gate static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList"; 7780Sstevel@tonic-gate 779*7616SVladimir.Kotal@Sun.COM /* 780*7616SVladimir.Kotal@Sun.COM * These are the static string constants for the DSO file name and the function 7817211Sjp161948 * symbol names to bind to. 7820Sstevel@tonic-gate */ 7830Sstevel@tonic-gate #if defined(__sparcv9) || defined(__x86_64) || defined(__amd64) 7840Sstevel@tonic-gate static const char def_PK11_LIBNAME[] = "/usr/lib/64/libpkcs11.so.1"; 7850Sstevel@tonic-gate #else 7860Sstevel@tonic-gate static const char def_PK11_LIBNAME[] = "/usr/lib/libpkcs11.so.1"; 7870Sstevel@tonic-gate #endif 7880Sstevel@tonic-gate 7890Sstevel@tonic-gate static CK_BBOOL true = TRUE; 7900Sstevel@tonic-gate static CK_BBOOL false = FALSE; 7917211Sjp161948 static CK_SLOT_ID pubkey_SLOTID = 0; 7927211Sjp161948 static CK_SLOT_ID rand_SLOTID = 0; 7930Sstevel@tonic-gate static CK_SLOT_ID SLOTID = 0; 7947526SVladimir.Kotal@Sun.COM static CK_BBOOL pk11_library_initialized = FALSE; 7957526SVladimir.Kotal@Sun.COM static CK_BBOOL pk11_atfork_initialized = FALSE; 7967211Sjp161948 static int pk11_pid = 0; 7970Sstevel@tonic-gate 7980Sstevel@tonic-gate static DSO *pk11_dso = NULL; 7990Sstevel@tonic-gate 8007526SVladimir.Kotal@Sun.COM /* allocate and initialize all locks used by the engine itself */ 8017526SVladimir.Kotal@Sun.COM static int pk11_init_all_locks(void) 8027526SVladimir.Kotal@Sun.COM { 8037526SVladimir.Kotal@Sun.COM int type; 8047526SVladimir.Kotal@Sun.COM 8057526SVladimir.Kotal@Sun.COM #ifndef OPENSSL_NO_RSA 8067526SVladimir.Kotal@Sun.COM find_lock[OP_RSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); 8077526SVladimir.Kotal@Sun.COM if (find_lock[OP_RSA] == NULL) 8087526SVladimir.Kotal@Sun.COM goto malloc_err; 8097526SVladimir.Kotal@Sun.COM (void) pthread_mutex_init(find_lock[OP_RSA], NULL); 8107526SVladimir.Kotal@Sun.COM #endif /* OPENSSL_NO_RSA */ 8117526SVladimir.Kotal@Sun.COM 8127526SVladimir.Kotal@Sun.COM #ifndef OPENSSL_NO_DSA 8137526SVladimir.Kotal@Sun.COM find_lock[OP_DSA] = OPENSSL_malloc(sizeof (pthread_mutex_t)); 8147526SVladimir.Kotal@Sun.COM if (find_lock[OP_DSA] == NULL) 8157526SVladimir.Kotal@Sun.COM goto malloc_err; 8167526SVladimir.Kotal@Sun.COM (void) pthread_mutex_init(find_lock[OP_DSA], NULL); 8177526SVladimir.Kotal@Sun.COM #endif /* OPENSSL_NO_DSA */ 8187526SVladimir.Kotal@Sun.COM 8197526SVladimir.Kotal@Sun.COM #ifndef OPENSSL_NO_DH 8207526SVladimir.Kotal@Sun.COM find_lock[OP_DH] = OPENSSL_malloc(sizeof (pthread_mutex_t)); 8217526SVladimir.Kotal@Sun.COM if (find_lock[OP_DH] == NULL) 8227526SVladimir.Kotal@Sun.COM goto malloc_err; 8237526SVladimir.Kotal@Sun.COM (void) pthread_mutex_init(find_lock[OP_DH], NULL); 8247526SVladimir.Kotal@Sun.COM #endif /* OPENSSL_NO_DH */ 8257526SVladimir.Kotal@Sun.COM 8267526SVladimir.Kotal@Sun.COM for (type = 0; type < OP_MAX; type++) 8277526SVladimir.Kotal@Sun.COM { 8287526SVladimir.Kotal@Sun.COM session_cache[type].lock = 8297526SVladimir.Kotal@Sun.COM OPENSSL_malloc(sizeof (pthread_mutex_t)); 8307526SVladimir.Kotal@Sun.COM if (session_cache[type].lock == NULL) 8317526SVladimir.Kotal@Sun.COM goto malloc_err; 8327526SVladimir.Kotal@Sun.COM (void) pthread_mutex_init(session_cache[type].lock, NULL); 8337526SVladimir.Kotal@Sun.COM } 8347526SVladimir.Kotal@Sun.COM 8357526SVladimir.Kotal@Sun.COM return (1); 8367526SVladimir.Kotal@Sun.COM 8377526SVladimir.Kotal@Sun.COM malloc_err: 8387526SVladimir.Kotal@Sun.COM pk11_free_all_locks(); 8397526SVladimir.Kotal@Sun.COM PK11err(PK11_F_INIT_ALL_LOCKS, PK11_R_MALLOC_FAILURE); 8407526SVladimir.Kotal@Sun.COM return (0); 8417526SVladimir.Kotal@Sun.COM } 8427526SVladimir.Kotal@Sun.COM 8437526SVladimir.Kotal@Sun.COM static void pk11_free_all_locks(void) 8447526SVladimir.Kotal@Sun.COM { 8457526SVladimir.Kotal@Sun.COM int type; 8467526SVladimir.Kotal@Sun.COM 8477526SVladimir.Kotal@Sun.COM #ifndef OPENSSL_NO_RSA 8487526SVladimir.Kotal@Sun.COM if (find_lock[OP_RSA] != NULL) 8497526SVladimir.Kotal@Sun.COM { 8507526SVladimir.Kotal@Sun.COM (void) pthread_mutex_destroy(find_lock[OP_RSA]); 8517526SVladimir.Kotal@Sun.COM OPENSSL_free(find_lock[OP_RSA]); 8527526SVladimir.Kotal@Sun.COM find_lock[OP_RSA] = NULL; 8537526SVladimir.Kotal@Sun.COM } 8547526SVladimir.Kotal@Sun.COM #endif /* OPENSSL_NO_RSA */ 8557526SVladimir.Kotal@Sun.COM #ifndef OPENSSL_NO_DSA 8567526SVladimir.Kotal@Sun.COM if (find_lock[OP_DSA] != NULL) 8577526SVladimir.Kotal@Sun.COM { 8587526SVladimir.Kotal@Sun.COM (void) pthread_mutex_destroy(find_lock[OP_DSA]); 8597526SVladimir.Kotal@Sun.COM OPENSSL_free(find_lock[OP_DSA]); 8607526SVladimir.Kotal@Sun.COM find_lock[OP_DSA] = NULL; 8617526SVladimir.Kotal@Sun.COM } 8627526SVladimir.Kotal@Sun.COM #endif /* OPENSSL_NO_DSA */ 8637526SVladimir.Kotal@Sun.COM #ifndef OPENSSL_NO_DH 8647526SVladimir.Kotal@Sun.COM if (find_lock[OP_DH] != NULL) 8657526SVladimir.Kotal@Sun.COM { 8667526SVladimir.Kotal@Sun.COM (void) pthread_mutex_destroy(find_lock[OP_DH]); 8677526SVladimir.Kotal@Sun.COM OPENSSL_free(find_lock[OP_DH]); 8687526SVladimir.Kotal@Sun.COM find_lock[OP_DH] = NULL; 8697526SVladimir.Kotal@Sun.COM } 8707526SVladimir.Kotal@Sun.COM #endif /* OPENSSL_NO_DH */ 8717526SVladimir.Kotal@Sun.COM 8727526SVladimir.Kotal@Sun.COM for (type = 0; type < OP_MAX; type++) 8737526SVladimir.Kotal@Sun.COM { 8747526SVladimir.Kotal@Sun.COM if (session_cache[type].lock != NULL) 8757526SVladimir.Kotal@Sun.COM { 8767526SVladimir.Kotal@Sun.COM (void) pthread_mutex_destroy(session_cache[type].lock); 8777526SVladimir.Kotal@Sun.COM OPENSSL_free(session_cache[type].lock); 8787526SVladimir.Kotal@Sun.COM session_cache[type].lock = NULL; 8797526SVladimir.Kotal@Sun.COM } 8807526SVladimir.Kotal@Sun.COM } 8817526SVladimir.Kotal@Sun.COM } 8827526SVladimir.Kotal@Sun.COM 8830Sstevel@tonic-gate /* 8840Sstevel@tonic-gate * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support. 8850Sstevel@tonic-gate */ 8860Sstevel@tonic-gate static int bind_pk11(ENGINE *e) 8870Sstevel@tonic-gate { 8886847Svk199839 #ifndef OPENSSL_NO_RSA 8890Sstevel@tonic-gate const RSA_METHOD *rsa = NULL; 8900Sstevel@tonic-gate RSA_METHOD *pk11_rsa = PK11_RSA(); 8917211Sjp161948 #endif /* OPENSSL_NO_RSA */ 8920Sstevel@tonic-gate if (!pk11_library_initialized) 8937526SVladimir.Kotal@Sun.COM (void) pk11_library_init(e); 8940Sstevel@tonic-gate 895*7616SVladimir.Kotal@Sun.COM if (!ENGINE_set_id(e, engine_pk11_id) || 896*7616SVladimir.Kotal@Sun.COM !ENGINE_set_name(e, engine_pk11_name) || 897*7616SVladimir.Kotal@Sun.COM !ENGINE_set_ciphers(e, pk11_engine_ciphers) || 898*7616SVladimir.Kotal@Sun.COM !ENGINE_set_digests(e, pk11_engine_digests)) 899*7616SVladimir.Kotal@Sun.COM return (0); 9000Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA 901*7616SVladimir.Kotal@Sun.COM if (pk11_have_rsa == CK_TRUE) 9020Sstevel@tonic-gate { 903*7616SVladimir.Kotal@Sun.COM if (!ENGINE_set_RSA(e, PK11_RSA()) || 904*7616SVladimir.Kotal@Sun.COM !ENGINE_set_load_privkey_function(e, pk11_load_privkey) || 905*7616SVladimir.Kotal@Sun.COM !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey)) 906*7616SVladimir.Kotal@Sun.COM return (0); 9077211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 9087211Sjp161948 fprintf(stderr, "%s: registered RSA\n", PK11_DBG); 9097211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 9100Sstevel@tonic-gate } 9117211Sjp161948 #endif /* OPENSSL_NO_RSA */ 9120Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA 913*7616SVladimir.Kotal@Sun.COM if (pk11_have_dsa == CK_TRUE) 914*7616SVladimir.Kotal@Sun.COM { 915*7616SVladimir.Kotal@Sun.COM if (!ENGINE_set_DSA(e, PK11_DSA())) 916*7616SVladimir.Kotal@Sun.COM return (0); 9177211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 9187211Sjp161948 fprintf(stderr, "%s: registered DSA\n", PK11_DBG); 9197211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 920*7616SVladimir.Kotal@Sun.COM } 9217211Sjp161948 #endif /* OPENSSL_NO_DSA */ 9220Sstevel@tonic-gate #ifndef OPENSSL_NO_DH 923*7616SVladimir.Kotal@Sun.COM if (pk11_have_dh == CK_TRUE) 9240Sstevel@tonic-gate { 925*7616SVladimir.Kotal@Sun.COM if (!ENGINE_set_DH(e, PK11_DH())) 926*7616SVladimir.Kotal@Sun.COM return (0); 9277211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 9287211Sjp161948 fprintf(stderr, "%s: registered DH\n", PK11_DBG); 9297211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 930*7616SVladimir.Kotal@Sun.COM } 9317211Sjp161948 #endif /* OPENSSL_NO_DH */ 932*7616SVladimir.Kotal@Sun.COM if (pk11_have_random) 9330Sstevel@tonic-gate { 934*7616SVladimir.Kotal@Sun.COM if (!ENGINE_set_RAND(e, &pk11_random)) 935*7616SVladimir.Kotal@Sun.COM return (0); 9367211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 9377211Sjp161948 fprintf(stderr, "%s: registered random\n", PK11_DBG); 9387211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 9390Sstevel@tonic-gate } 940*7616SVladimir.Kotal@Sun.COM if (!ENGINE_set_init_function(e, pk11_init) || 941*7616SVladimir.Kotal@Sun.COM !ENGINE_set_destroy_function(e, pk11_destroy) || 942*7616SVladimir.Kotal@Sun.COM !ENGINE_set_finish_function(e, pk11_finish) || 943*7616SVladimir.Kotal@Sun.COM !ENGINE_set_ctrl_function(e, pk11_ctrl) || 944*7616SVladimir.Kotal@Sun.COM !ENGINE_set_cmd_defns(e, pk11_cmd_defns)) 945*7616SVladimir.Kotal@Sun.COM return (0); 946*7616SVladimir.Kotal@Sun.COM 947*7616SVladimir.Kotal@Sun.COM /* 948*7616SVladimir.Kotal@Sun.COM * Apache calls OpenSSL function RSA_blinding_on() once during startup 9490Sstevel@tonic-gate * which in turn calls bn_mod_exp. Since we do not implement bn_mod_exp 950*7616SVladimir.Kotal@Sun.COM * here, we wire it back to the OpenSSL software implementation. 951*7616SVladimir.Kotal@Sun.COM * Since it is used only once, performance is not a concern. 952*7616SVladimir.Kotal@Sun.COM */ 9530Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA 954*7616SVladimir.Kotal@Sun.COM rsa = RSA_PKCS1_SSLeay(); 955*7616SVladimir.Kotal@Sun.COM pk11_rsa->rsa_mod_exp = rsa->rsa_mod_exp; 956*7616SVladimir.Kotal@Sun.COM pk11_rsa->bn_mod_exp = rsa->bn_mod_exp; 9577211Sjp161948 #endif /* OPENSSL_NO_RSA */ 9580Sstevel@tonic-gate 9590Sstevel@tonic-gate /* Ensure the pk11 error handling is set up */ 9600Sstevel@tonic-gate ERR_load_pk11_strings(); 961*7616SVladimir.Kotal@Sun.COM 962*7616SVladimir.Kotal@Sun.COM return (1); 9630Sstevel@tonic-gate } 9640Sstevel@tonic-gate 965*7616SVladimir.Kotal@Sun.COM /* Dynamic engine support is disabled at a higher level for Solaris */ 9667211Sjp161948 #ifdef ENGINE_DYNAMIC_SUPPORT 9670Sstevel@tonic-gate static int bind_helper(ENGINE *e, const char *id) 9680Sstevel@tonic-gate { 9690Sstevel@tonic-gate if (id && (strcmp(id, engine_pk11_id) != 0)) 970*7616SVladimir.Kotal@Sun.COM return (0); 9710Sstevel@tonic-gate 9720Sstevel@tonic-gate if (!bind_pk11(e)) 973*7616SVladimir.Kotal@Sun.COM return (0); 974*7616SVladimir.Kotal@Sun.COM 975*7616SVladimir.Kotal@Sun.COM return (1); 976*7616SVladimir.Kotal@Sun.COM } 9770Sstevel@tonic-gate 9780Sstevel@tonic-gate IMPLEMENT_DYNAMIC_CHECK_FN() 9790Sstevel@tonic-gate IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) 9800Sstevel@tonic-gate 9810Sstevel@tonic-gate #else 9820Sstevel@tonic-gate static ENGINE *engine_pk11(void) 9830Sstevel@tonic-gate { 9840Sstevel@tonic-gate ENGINE *ret = ENGINE_new(); 9850Sstevel@tonic-gate 9860Sstevel@tonic-gate if (!ret) 987*7616SVladimir.Kotal@Sun.COM return (NULL); 9880Sstevel@tonic-gate 9890Sstevel@tonic-gate if (!bind_pk11(ret)) 9900Sstevel@tonic-gate { 9910Sstevel@tonic-gate ENGINE_free(ret); 992*7616SVladimir.Kotal@Sun.COM return (NULL); 9930Sstevel@tonic-gate } 9940Sstevel@tonic-gate 995*7616SVladimir.Kotal@Sun.COM return (ret); 9960Sstevel@tonic-gate } 9970Sstevel@tonic-gate 998*7616SVladimir.Kotal@Sun.COM void 999*7616SVladimir.Kotal@Sun.COM ENGINE_load_pk11(void) 10000Sstevel@tonic-gate { 10010Sstevel@tonic-gate ENGINE *e_pk11 = NULL; 10020Sstevel@tonic-gate 1003*7616SVladimir.Kotal@Sun.COM /* 1004*7616SVladimir.Kotal@Sun.COM * Do not use dynamic PKCS#11 library on Solaris due to 1005*7616SVladimir.Kotal@Sun.COM * security reasons. We will link it in statically. 10060Sstevel@tonic-gate */ 1007*7616SVladimir.Kotal@Sun.COM /* Attempt to load PKCS#11 library */ 10080Sstevel@tonic-gate if (!pk11_dso) 10090Sstevel@tonic-gate pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0); 10100Sstevel@tonic-gate 10110Sstevel@tonic-gate if (pk11_dso == NULL) 10120Sstevel@tonic-gate { 10130Sstevel@tonic-gate PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE); 10140Sstevel@tonic-gate return; 10150Sstevel@tonic-gate } 10160Sstevel@tonic-gate 10170Sstevel@tonic-gate e_pk11 = engine_pk11(); 1018*7616SVladimir.Kotal@Sun.COM if (!e_pk11) 10190Sstevel@tonic-gate { 10200Sstevel@tonic-gate DSO_free(pk11_dso); 10210Sstevel@tonic-gate pk11_dso = NULL; 10220Sstevel@tonic-gate return; 10230Sstevel@tonic-gate } 10240Sstevel@tonic-gate 1025*7616SVladimir.Kotal@Sun.COM /* 1026*7616SVladimir.Kotal@Sun.COM * At this point, the pk11 shared library is either dynamically 1027*7616SVladimir.Kotal@Sun.COM * loaded or statically linked in. So, initialize the pk11 1028*7616SVladimir.Kotal@Sun.COM * library before calling ENGINE_set_default since the latter 10290Sstevel@tonic-gate * needs cipher and digest algorithm information 10300Sstevel@tonic-gate */ 10310Sstevel@tonic-gate if (!pk11_library_init(e_pk11)) 10320Sstevel@tonic-gate { 10330Sstevel@tonic-gate DSO_free(pk11_dso); 10340Sstevel@tonic-gate pk11_dso = NULL; 10350Sstevel@tonic-gate ENGINE_free(e_pk11); 10360Sstevel@tonic-gate return; 10370Sstevel@tonic-gate } 10380Sstevel@tonic-gate 10390Sstevel@tonic-gate ENGINE_add(e_pk11); 10400Sstevel@tonic-gate 10410Sstevel@tonic-gate ENGINE_free(e_pk11); 10420Sstevel@tonic-gate ERR_clear_error(); 10430Sstevel@tonic-gate } 10447211Sjp161948 #endif /* ENGINE_DYNAMIC_SUPPORT */ 10450Sstevel@tonic-gate 1046*7616SVladimir.Kotal@Sun.COM /* 1047*7616SVladimir.Kotal@Sun.COM * These are the static string constants for the DSO file name and 1048*7616SVladimir.Kotal@Sun.COM * the function symbol names to bind to. 10490Sstevel@tonic-gate */ 10500Sstevel@tonic-gate static const char *PK11_LIBNAME = NULL; 10510Sstevel@tonic-gate 10520Sstevel@tonic-gate static const char *get_PK11_LIBNAME(void) 10530Sstevel@tonic-gate { 10540Sstevel@tonic-gate if (PK11_LIBNAME) 1055*7616SVladimir.Kotal@Sun.COM return (PK11_LIBNAME); 1056*7616SVladimir.Kotal@Sun.COM 1057*7616SVladimir.Kotal@Sun.COM return (def_PK11_LIBNAME); 10580Sstevel@tonic-gate } 10590Sstevel@tonic-gate 10600Sstevel@tonic-gate static void free_PK11_LIBNAME(void) 10610Sstevel@tonic-gate { 10620Sstevel@tonic-gate if (PK11_LIBNAME) 10630Sstevel@tonic-gate OPENSSL_free((void*)PK11_LIBNAME); 10640Sstevel@tonic-gate 10650Sstevel@tonic-gate PK11_LIBNAME = NULL; 10660Sstevel@tonic-gate } 10670Sstevel@tonic-gate 10680Sstevel@tonic-gate static long set_PK11_LIBNAME(const char *name) 10690Sstevel@tonic-gate { 10700Sstevel@tonic-gate free_PK11_LIBNAME(); 10710Sstevel@tonic-gate 10720Sstevel@tonic-gate return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0); 10730Sstevel@tonic-gate } 10740Sstevel@tonic-gate 10757526SVladimir.Kotal@Sun.COM /* acquire all engine specific mutexes before fork */ 10767526SVladimir.Kotal@Sun.COM static void pk11_fork_prepare(void) 10777526SVladimir.Kotal@Sun.COM { 10787526SVladimir.Kotal@Sun.COM int i; 10797526SVladimir.Kotal@Sun.COM 10807560SVladimir.Kotal@Sun.COM if (!pk11_library_initialized) 10817560SVladimir.Kotal@Sun.COM return; 10827560SVladimir.Kotal@Sun.COM 10837526SVladimir.Kotal@Sun.COM LOCK_OBJSTORE(OP_RSA); 10847526SVladimir.Kotal@Sun.COM LOCK_OBJSTORE(OP_DSA); 10857526SVladimir.Kotal@Sun.COM LOCK_OBJSTORE(OP_DH); 10867526SVladimir.Kotal@Sun.COM for (i = 0; i < OP_MAX; i++) 10877526SVladimir.Kotal@Sun.COM { 10887526SVladimir.Kotal@Sun.COM (void) pthread_mutex_lock(session_cache[i].lock); 10897526SVladimir.Kotal@Sun.COM } 10907526SVladimir.Kotal@Sun.COM } 10917526SVladimir.Kotal@Sun.COM 10927526SVladimir.Kotal@Sun.COM /* release all engine specific mutexes */ 10937526SVladimir.Kotal@Sun.COM static void pk11_fork_parent(void) 10947526SVladimir.Kotal@Sun.COM { 10957526SVladimir.Kotal@Sun.COM int i; 10967526SVladimir.Kotal@Sun.COM 10977560SVladimir.Kotal@Sun.COM if (!pk11_library_initialized) 10987560SVladimir.Kotal@Sun.COM return; 10997560SVladimir.Kotal@Sun.COM 11007526SVladimir.Kotal@Sun.COM for (i = OP_MAX - 1; i >= 0; i--) 11017526SVladimir.Kotal@Sun.COM { 11027526SVladimir.Kotal@Sun.COM (void) pthread_mutex_unlock(session_cache[i].lock); 11037526SVladimir.Kotal@Sun.COM } 11047526SVladimir.Kotal@Sun.COM UNLOCK_OBJSTORE(OP_DH); 11057526SVladimir.Kotal@Sun.COM UNLOCK_OBJSTORE(OP_DSA); 11067526SVladimir.Kotal@Sun.COM UNLOCK_OBJSTORE(OP_RSA); 11077526SVladimir.Kotal@Sun.COM } 11087526SVladimir.Kotal@Sun.COM 11097526SVladimir.Kotal@Sun.COM /* 11107526SVladimir.Kotal@Sun.COM * same situation as in parent - we need to unlock all locks to make them 11117526SVladimir.Kotal@Sun.COM * accessible to all threads. 11127526SVladimir.Kotal@Sun.COM */ 11137526SVladimir.Kotal@Sun.COM static void pk11_fork_child(void) 11147526SVladimir.Kotal@Sun.COM { 11157526SVladimir.Kotal@Sun.COM int i; 11167526SVladimir.Kotal@Sun.COM 11177560SVladimir.Kotal@Sun.COM if (!pk11_library_initialized) 11187560SVladimir.Kotal@Sun.COM return; 11197560SVladimir.Kotal@Sun.COM 11207526SVladimir.Kotal@Sun.COM for (i = OP_MAX - 1; i >= 0; i--) 11217526SVladimir.Kotal@Sun.COM { 11227526SVladimir.Kotal@Sun.COM (void) pthread_mutex_unlock(session_cache[i].lock); 11237526SVladimir.Kotal@Sun.COM } 11247526SVladimir.Kotal@Sun.COM UNLOCK_OBJSTORE(OP_DH); 11257526SVladimir.Kotal@Sun.COM UNLOCK_OBJSTORE(OP_DSA); 11267526SVladimir.Kotal@Sun.COM UNLOCK_OBJSTORE(OP_RSA); 11277526SVladimir.Kotal@Sun.COM } 11287526SVladimir.Kotal@Sun.COM 11290Sstevel@tonic-gate /* Initialization function for the pk11 engine */ 11300Sstevel@tonic-gate static int pk11_init(ENGINE *e) 11310Sstevel@tonic-gate { 1132*7616SVladimir.Kotal@Sun.COM return (pk11_library_init(e)); 11330Sstevel@tonic-gate } 11340Sstevel@tonic-gate 1135*7616SVladimir.Kotal@Sun.COM /* 1136*7616SVladimir.Kotal@Sun.COM * Initialization function. Sets up various PKCS#11 library components. 11370Sstevel@tonic-gate * It selects a slot based on predefined critiera. In the process, it also 11380Sstevel@tonic-gate * count how many ciphers and digests to support. Since the cipher and 11390Sstevel@tonic-gate * digest information is needed when setting default engine, this function 11400Sstevel@tonic-gate * needs to be called before calling ENGINE_set_default. 11410Sstevel@tonic-gate */ 11427534SVladimir.Kotal@Sun.COM /* ARGSUSED */ 11430Sstevel@tonic-gate static int pk11_library_init(ENGINE *e) 11440Sstevel@tonic-gate { 11450Sstevel@tonic-gate CK_C_GetFunctionList p; 11460Sstevel@tonic-gate CK_RV rv = CKR_OK; 11470Sstevel@tonic-gate CK_INFO info; 11480Sstevel@tonic-gate CK_ULONG ul_state_len; 11497211Sjp161948 int any_slot_found; 11507526SVladimir.Kotal@Sun.COM int i; 11517211Sjp161948 11527211Sjp161948 /* 11537211Sjp161948 * pk11_library_initialized is set to 0 in pk11_finish() which is called 11547211Sjp161948 * from ENGINE_finish(). However, if there is still at least one 11557211Sjp161948 * existing functional reference to the engine (see engine(3) for more 11567211Sjp161948 * information), pk11_finish() is skipped. For example, this can happen 11577211Sjp161948 * if an application forgets to clear one cipher context. In case of a 11587211Sjp161948 * fork() when the application is finishing the engine so that it can be 11597211Sjp161948 * reinitialized in the child, forgotten functional reference causes 11607211Sjp161948 * pk11_library_initialized to stay 1. In that case we need the PID 11617211Sjp161948 * check so that we properly initialize the engine again. 11627211Sjp161948 */ 11630Sstevel@tonic-gate if (pk11_library_initialized) 11647211Sjp161948 { 11657211Sjp161948 if (pk11_pid == getpid()) 11667526SVladimir.Kotal@Sun.COM { 1167*7616SVladimir.Kotal@Sun.COM return (1); 11687526SVladimir.Kotal@Sun.COM } 11697211Sjp161948 else 11707526SVladimir.Kotal@Sun.COM { 11717211Sjp161948 global_session = CK_INVALID_HANDLE; 11727526SVladimir.Kotal@Sun.COM /* 11737526SVladimir.Kotal@Sun.COM * free the locks first to prevent memory leak in case 11747526SVladimir.Kotal@Sun.COM * the application calls fork() without finishing the 11757526SVladimir.Kotal@Sun.COM * engine first. 11767526SVladimir.Kotal@Sun.COM */ 11777526SVladimir.Kotal@Sun.COM pk11_free_all_locks(); 11787526SVladimir.Kotal@Sun.COM } 11797211Sjp161948 } 1180*7616SVladimir.Kotal@Sun.COM 11810Sstevel@tonic-gate if (pk11_dso == NULL) 11820Sstevel@tonic-gate { 11830Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); 11840Sstevel@tonic-gate goto err; 11850Sstevel@tonic-gate } 11860Sstevel@tonic-gate 11877211Sjp161948 #ifdef SOLARIS_AES_CTR 11887211Sjp161948 /* 11897211Sjp161948 * We must do this before we start working with slots since we need all 11907211Sjp161948 * NIDs there. 11917211Sjp161948 */ 11927211Sjp161948 if (pk11_add_aes_ctr_NIDs() == 0) 11937211Sjp161948 goto err; 11947211Sjp161948 #endif /* SOLARIS_AES_CTR */ 11957211Sjp161948 11967211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 11977211Sjp161948 if (check_hw_mechanisms() == 0) 11987211Sjp161948 goto err; 11997211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 12007211Sjp161948 1201*7616SVladimir.Kotal@Sun.COM /* get the C_GetFunctionList function from the loaded library */ 1202*7616SVladimir.Kotal@Sun.COM p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso, 12030Sstevel@tonic-gate PK11_GET_FUNCTION_LIST); 1204*7616SVladimir.Kotal@Sun.COM if (!p) 12050Sstevel@tonic-gate { 12060Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); 12070Sstevel@tonic-gate goto err; 12080Sstevel@tonic-gate } 1209*7616SVladimir.Kotal@Sun.COM 1210*7616SVladimir.Kotal@Sun.COM /* get the full function list from the loaded library */ 12110Sstevel@tonic-gate rv = p(&pFuncList); 12120Sstevel@tonic-gate if (rv != CKR_OK) 12130Sstevel@tonic-gate { 12147211Sjp161948 PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE, rv); 12150Sstevel@tonic-gate goto err; 12160Sstevel@tonic-gate } 1217*7616SVladimir.Kotal@Sun.COM 12180Sstevel@tonic-gate rv = pFuncList->C_Initialize(NULL_PTR); 12190Sstevel@tonic-gate if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) 12200Sstevel@tonic-gate { 12217211Sjp161948 PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE, rv); 12220Sstevel@tonic-gate goto err; 12230Sstevel@tonic-gate } 12240Sstevel@tonic-gate 12250Sstevel@tonic-gate rv = pFuncList->C_GetInfo(&info); 1226*7616SVladimir.Kotal@Sun.COM if (rv != CKR_OK) 12270Sstevel@tonic-gate { 12287211Sjp161948 PK11err_add_data(PK11_F_LIBRARY_INIT, PK11_R_GETINFO, rv); 12290Sstevel@tonic-gate goto err; 12300Sstevel@tonic-gate } 12310Sstevel@tonic-gate 12327211Sjp161948 if (pk11_choose_slots(&any_slot_found) == 0) 12330Sstevel@tonic-gate goto err; 12340Sstevel@tonic-gate 12357211Sjp161948 /* 12367211Sjp161948 * The library we use, set in def_PK11_LIBNAME, may not offer any 12377211Sjp161948 * slot(s). In that case, we must not proceed but we must not return an 12387211Sjp161948 * error. The reason is that applications that try to set up the PKCS#11 12397211Sjp161948 * engine don't exit on error during the engine initialization just 12407211Sjp161948 * because no slot was present. 12417211Sjp161948 */ 12427211Sjp161948 if (any_slot_found == 0) 1243*7616SVladimir.Kotal@Sun.COM return (1); 12447211Sjp161948 12450Sstevel@tonic-gate if (global_session == CK_INVALID_HANDLE) 12460Sstevel@tonic-gate { 12470Sstevel@tonic-gate /* Open the global_session for the new process */ 12480Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 12490Sstevel@tonic-gate NULL_PTR, NULL_PTR, &global_session); 12500Sstevel@tonic-gate if (rv != CKR_OK) 12510Sstevel@tonic-gate { 12527211Sjp161948 PK11err_add_data(PK11_F_LIBRARY_INIT, 12537211Sjp161948 PK11_R_OPENSESSION, rv); 12540Sstevel@tonic-gate goto err; 12550Sstevel@tonic-gate } 12560Sstevel@tonic-gate } 12570Sstevel@tonic-gate 1258*7616SVladimir.Kotal@Sun.COM /* 1259*7616SVladimir.Kotal@Sun.COM * Disable digest if C_GetOperationState is not supported since 1260*7616SVladimir.Kotal@Sun.COM * this function is required by OpenSSL digest copy function 1261*7616SVladimir.Kotal@Sun.COM */ 12620Sstevel@tonic-gate if (pFuncList->C_GetOperationState(global_session, NULL, &ul_state_len) 12637211Sjp161948 == CKR_FUNCTION_NOT_SUPPORTED) { 12647211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 12657211Sjp161948 fprintf(stderr, "%s: C_GetOperationState() not supported, " 12667211Sjp161948 "setting digest_count to 0\n", PK11_DBG); 12677211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 12680Sstevel@tonic-gate digest_count = 0; 12697211Sjp161948 } 12700Sstevel@tonic-gate 12717526SVladimir.Kotal@Sun.COM pk11_library_initialized = TRUE; 12727211Sjp161948 pk11_pid = getpid(); 12737526SVladimir.Kotal@Sun.COM /* 12747526SVladimir.Kotal@Sun.COM * if initialization of the locks fails pk11_init_all_locks() 12757526SVladimir.Kotal@Sun.COM * will do the cleanup. 12767526SVladimir.Kotal@Sun.COM */ 12777526SVladimir.Kotal@Sun.COM if (!pk11_init_all_locks()) 12787526SVladimir.Kotal@Sun.COM goto err; 12797526SVladimir.Kotal@Sun.COM for (i = 0; i < OP_MAX; i++) 12807526SVladimir.Kotal@Sun.COM session_cache[i].head = NULL; 12817526SVladimir.Kotal@Sun.COM /* 12827526SVladimir.Kotal@Sun.COM * initialize active lists. We only use active lists 12837526SVladimir.Kotal@Sun.COM * for asymmetric ciphers. 12847526SVladimir.Kotal@Sun.COM */ 12857526SVladimir.Kotal@Sun.COM for (i = 0; i < OP_MAX; i++) 12867526SVladimir.Kotal@Sun.COM active_list[i] = NULL; 12877526SVladimir.Kotal@Sun.COM 12887526SVladimir.Kotal@Sun.COM if (!pk11_atfork_initialized) 12897526SVladimir.Kotal@Sun.COM { 12907526SVladimir.Kotal@Sun.COM if (pthread_atfork(pk11_fork_prepare, pk11_fork_parent, 12917526SVladimir.Kotal@Sun.COM pk11_fork_child) != 0) 12927526SVladimir.Kotal@Sun.COM { 12937526SVladimir.Kotal@Sun.COM PK11err(PK11_F_LIBRARY_INIT, PK11_R_ATFORK_FAILED); 12947526SVladimir.Kotal@Sun.COM goto err; 12957526SVladimir.Kotal@Sun.COM } 12967526SVladimir.Kotal@Sun.COM pk11_atfork_initialized = TRUE; 12977526SVladimir.Kotal@Sun.COM } 12987526SVladimir.Kotal@Sun.COM 1299*7616SVladimir.Kotal@Sun.COM return (1); 13000Sstevel@tonic-gate 13010Sstevel@tonic-gate err: 1302*7616SVladimir.Kotal@Sun.COM return (0); 13030Sstevel@tonic-gate } 13040Sstevel@tonic-gate 1305*7616SVladimir.Kotal@Sun.COM /* Destructor (complements the "ENGINE_pk11()" constructor) */ 13067534SVladimir.Kotal@Sun.COM /* ARGSUSED */ 13070Sstevel@tonic-gate static int pk11_destroy(ENGINE *e) 13080Sstevel@tonic-gate { 13090Sstevel@tonic-gate free_PK11_LIBNAME(); 13100Sstevel@tonic-gate ERR_unload_pk11_strings(); 1311*7616SVladimir.Kotal@Sun.COM return (1); 13120Sstevel@tonic-gate } 13130Sstevel@tonic-gate 1314*7616SVladimir.Kotal@Sun.COM /* 1315*7616SVladimir.Kotal@Sun.COM * Termination function to clean up the session, the token, and the pk11 1316*7616SVladimir.Kotal@Sun.COM * library. 13170Sstevel@tonic-gate */ 13187534SVladimir.Kotal@Sun.COM /* ARGSUSED */ 13190Sstevel@tonic-gate static int pk11_finish(ENGINE *e) 13200Sstevel@tonic-gate { 13217526SVladimir.Kotal@Sun.COM int i; 13227526SVladimir.Kotal@Sun.COM 13230Sstevel@tonic-gate if (pk11_dso == NULL) 13240Sstevel@tonic-gate { 13250Sstevel@tonic-gate PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED); 13260Sstevel@tonic-gate goto err; 13270Sstevel@tonic-gate } 13280Sstevel@tonic-gate 13296847Svk199839 OPENSSL_assert(pFuncList != NULL); 13300Sstevel@tonic-gate 13310Sstevel@tonic-gate if (pk11_free_all_sessions() == 0) 13320Sstevel@tonic-gate goto err; 13330Sstevel@tonic-gate 13347526SVladimir.Kotal@Sun.COM /* free all active lists */ 13357526SVladimir.Kotal@Sun.COM for (i = 0; i < OP_MAX; i++) 13367526SVladimir.Kotal@Sun.COM pk11_free_active_list(i); 13377526SVladimir.Kotal@Sun.COM 13380Sstevel@tonic-gate pFuncList->C_CloseSession(global_session); 13397211Sjp161948 global_session = CK_INVALID_HANDLE; 13407211Sjp161948 13417211Sjp161948 /* 13427211Sjp161948 * Since we are part of a library (libcrypto.so), calling this function 13437211Sjp161948 * may have side-effects. 13447211Sjp161948 */ 13457211Sjp161948 #if 0 13460Sstevel@tonic-gate pFuncList->C_Finalize(NULL); 13477211Sjp161948 #endif 13480Sstevel@tonic-gate 13490Sstevel@tonic-gate if (!DSO_free(pk11_dso)) 13500Sstevel@tonic-gate { 13510Sstevel@tonic-gate PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE); 13520Sstevel@tonic-gate goto err; 13530Sstevel@tonic-gate } 13540Sstevel@tonic-gate pk11_dso = NULL; 13550Sstevel@tonic-gate pFuncList = NULL; 13567526SVladimir.Kotal@Sun.COM pk11_library_initialized = FALSE; 13577211Sjp161948 pk11_pid = 0; 13587560SVladimir.Kotal@Sun.COM /* 13597560SVladimir.Kotal@Sun.COM * There is no way how to unregister atfork handlers (other than 13607560SVladimir.Kotal@Sun.COM * unloading the library) so we just free the locks. For this reason 13617560SVladimir.Kotal@Sun.COM * the atfork handlers check if the engine is initialized and bail out 13627560SVladimir.Kotal@Sun.COM * immediately if not. This is necessary in case a process finishes 13637560SVladimir.Kotal@Sun.COM * the engine before calling fork(). 13647560SVladimir.Kotal@Sun.COM */ 13657526SVladimir.Kotal@Sun.COM pk11_free_all_locks(); 13660Sstevel@tonic-gate 1367*7616SVladimir.Kotal@Sun.COM return (1); 13680Sstevel@tonic-gate 13690Sstevel@tonic-gate err: 1370*7616SVladimir.Kotal@Sun.COM return (0); 13710Sstevel@tonic-gate } 13720Sstevel@tonic-gate 13730Sstevel@tonic-gate /* Standard engine interface function to set the dynamic library path */ 13747534SVladimir.Kotal@Sun.COM /* ARGSUSED */ 13750Sstevel@tonic-gate static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) 13760Sstevel@tonic-gate { 13770Sstevel@tonic-gate int initialized = ((pk11_dso == NULL) ? 0 : 1); 13780Sstevel@tonic-gate 1379*7616SVladimir.Kotal@Sun.COM switch (cmd) 13800Sstevel@tonic-gate { 13810Sstevel@tonic-gate case PK11_CMD_SO_PATH: 13820Sstevel@tonic-gate if (p == NULL) 13830Sstevel@tonic-gate { 13840Sstevel@tonic-gate PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); 1385*7616SVladimir.Kotal@Sun.COM return (0); 13860Sstevel@tonic-gate } 13870Sstevel@tonic-gate 13880Sstevel@tonic-gate if (initialized) 13890Sstevel@tonic-gate { 13900Sstevel@tonic-gate PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED); 1391*7616SVladimir.Kotal@Sun.COM return (0); 13920Sstevel@tonic-gate } 13930Sstevel@tonic-gate 1394*7616SVladimir.Kotal@Sun.COM return (set_PK11_LIBNAME((const char *)p)); 13950Sstevel@tonic-gate default: 13960Sstevel@tonic-gate break; 13970Sstevel@tonic-gate } 13980Sstevel@tonic-gate 1399*7616SVladimir.Kotal@Sun.COM PK11err(PK11_F_CTRL, PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED); 1400*7616SVladimir.Kotal@Sun.COM 1401*7616SVladimir.Kotal@Sun.COM return (0); 14020Sstevel@tonic-gate } 14030Sstevel@tonic-gate 14040Sstevel@tonic-gate 1405*7616SVladimir.Kotal@Sun.COM /* Required function by the engine random interface. It does nothing here */ 14060Sstevel@tonic-gate static void pk11_rand_cleanup(void) 14070Sstevel@tonic-gate { 14080Sstevel@tonic-gate return; 14090Sstevel@tonic-gate } 14100Sstevel@tonic-gate 14117534SVladimir.Kotal@Sun.COM /* ARGSUSED */ 14120Sstevel@tonic-gate static void pk11_rand_add(const void *buf, int num, double add) 14130Sstevel@tonic-gate { 14140Sstevel@tonic-gate PK11_SESSION *sp; 14150Sstevel@tonic-gate 14167211Sjp161948 if ((sp = pk11_get_session(OP_RAND)) == NULL) 14170Sstevel@tonic-gate return; 14180Sstevel@tonic-gate 1419*7616SVladimir.Kotal@Sun.COM /* 1420*7616SVladimir.Kotal@Sun.COM * Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since 14210Sstevel@tonic-gate * the calling functions do not care anyway 14220Sstevel@tonic-gate */ 14230Sstevel@tonic-gate pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num); 14247211Sjp161948 pk11_return_session(sp, OP_RAND); 14250Sstevel@tonic-gate 14260Sstevel@tonic-gate return; 14270Sstevel@tonic-gate } 14280Sstevel@tonic-gate 14290Sstevel@tonic-gate static void pk11_rand_seed(const void *buf, int num) 14300Sstevel@tonic-gate { 14310Sstevel@tonic-gate pk11_rand_add(buf, num, 0); 14320Sstevel@tonic-gate } 14330Sstevel@tonic-gate 14340Sstevel@tonic-gate static int pk11_rand_bytes(unsigned char *buf, int num) 14350Sstevel@tonic-gate { 14360Sstevel@tonic-gate CK_RV rv; 14370Sstevel@tonic-gate PK11_SESSION *sp; 1438*7616SVladimir.Kotal@Sun.COM 14397211Sjp161948 if ((sp = pk11_get_session(OP_RAND)) == NULL) 1440*7616SVladimir.Kotal@Sun.COM return (0); 1441*7616SVladimir.Kotal@Sun.COM 14420Sstevel@tonic-gate rv = pFuncList->C_GenerateRandom(sp->session, buf, num); 14430Sstevel@tonic-gate if (rv != CKR_OK) 14440Sstevel@tonic-gate { 14457211Sjp161948 PK11err_add_data(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM, rv); 14467211Sjp161948 pk11_return_session(sp, OP_RAND); 1447*7616SVladimir.Kotal@Sun.COM return (0); 14480Sstevel@tonic-gate } 14490Sstevel@tonic-gate 14507211Sjp161948 pk11_return_session(sp, OP_RAND); 1451*7616SVladimir.Kotal@Sun.COM return (1); 14520Sstevel@tonic-gate } 14530Sstevel@tonic-gate 1454*7616SVladimir.Kotal@Sun.COM /* Required function by the engine random interface. It does nothing here */ 14550Sstevel@tonic-gate static int pk11_rand_status(void) 14560Sstevel@tonic-gate { 1457*7616SVladimir.Kotal@Sun.COM return (1); 14580Sstevel@tonic-gate } 14590Sstevel@tonic-gate 1460*7616SVladimir.Kotal@Sun.COM /* Free all BIGNUM structures from PK11_SESSION. */ 14617526SVladimir.Kotal@Sun.COM static void pk11_free_nums(PK11_SESSION *sp, PK11_OPTYPE optype) 14626847Svk199839 { 14637526SVladimir.Kotal@Sun.COM switch (optype) 14647526SVladimir.Kotal@Sun.COM { 14656847Svk199839 #ifndef OPENSSL_NO_RSA 14667526SVladimir.Kotal@Sun.COM case OP_RSA: 14677526SVladimir.Kotal@Sun.COM if (sp->opdata_rsa_n_num != NULL) 14687526SVladimir.Kotal@Sun.COM { 14697526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_rsa_n_num); 14707526SVladimir.Kotal@Sun.COM sp->opdata_rsa_n_num = NULL; 14717526SVladimir.Kotal@Sun.COM } 14727526SVladimir.Kotal@Sun.COM if (sp->opdata_rsa_e_num != NULL) 14737526SVladimir.Kotal@Sun.COM { 14747526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_rsa_e_num); 14757526SVladimir.Kotal@Sun.COM sp->opdata_rsa_e_num = NULL; 14767526SVladimir.Kotal@Sun.COM } 14777526SVladimir.Kotal@Sun.COM if (sp->opdata_rsa_d_num != NULL) 14787526SVladimir.Kotal@Sun.COM { 14797526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_rsa_d_num); 14807526SVladimir.Kotal@Sun.COM sp->opdata_rsa_d_num = NULL; 14817526SVladimir.Kotal@Sun.COM } 14827526SVladimir.Kotal@Sun.COM break; 14836847Svk199839 #endif 14846847Svk199839 #ifndef OPENSSL_NO_DSA 14857526SVladimir.Kotal@Sun.COM case OP_DSA: 14867526SVladimir.Kotal@Sun.COM if (sp->opdata_dsa_pub_num != NULL) 14877526SVladimir.Kotal@Sun.COM { 14887526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_dsa_pub_num); 14897526SVladimir.Kotal@Sun.COM sp->opdata_dsa_pub_num = NULL; 14907526SVladimir.Kotal@Sun.COM } 14917526SVladimir.Kotal@Sun.COM if (sp->opdata_dsa_priv_num != NULL) 14927526SVladimir.Kotal@Sun.COM { 14937526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_dsa_priv_num); 14947526SVladimir.Kotal@Sun.COM sp->opdata_dsa_priv_num = NULL; 14957526SVladimir.Kotal@Sun.COM } 14967526SVladimir.Kotal@Sun.COM break; 14976847Svk199839 #endif 14986847Svk199839 #ifndef OPENSSL_NO_DH 14997526SVladimir.Kotal@Sun.COM case OP_DH: 15007526SVladimir.Kotal@Sun.COM if (sp->opdata_dh_priv_num != NULL) 15017526SVladimir.Kotal@Sun.COM { 15027526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_dh_priv_num); 15037526SVladimir.Kotal@Sun.COM sp->opdata_dh_priv_num = NULL; 15047526SVladimir.Kotal@Sun.COM } 15057526SVladimir.Kotal@Sun.COM break; 15066847Svk199839 #endif 15077526SVladimir.Kotal@Sun.COM default: 15087526SVladimir.Kotal@Sun.COM break; 15097526SVladimir.Kotal@Sun.COM } 15106847Svk199839 } 15110Sstevel@tonic-gate 15126847Svk199839 /* 15136847Svk199839 * Get new PK11_SESSION structure ready for use. Every process must have 15146847Svk199839 * its own freelist of PK11_SESSION structures so handle fork() here 15156847Svk199839 * by destroying the old and creating new freelist. 15166847Svk199839 * The returned PK11_SESSION structure is disconnected from the freelist. 15176847Svk199839 */ 1518*7616SVladimir.Kotal@Sun.COM PK11_SESSION * 1519*7616SVladimir.Kotal@Sun.COM pk11_get_session(PK11_OPTYPE optype) 15200Sstevel@tonic-gate { 15217526SVladimir.Kotal@Sun.COM PK11_SESSION *sp = NULL, *sp1, *freelist; 15227526SVladimir.Kotal@Sun.COM pthread_mutex_t *freelist_lock; 15230Sstevel@tonic-gate CK_RV rv; 15240Sstevel@tonic-gate 15257211Sjp161948 switch (optype) 15267211Sjp161948 { 15277526SVladimir.Kotal@Sun.COM case OP_RSA: 15287526SVladimir.Kotal@Sun.COM case OP_DSA: 15297526SVladimir.Kotal@Sun.COM case OP_DH: 15307211Sjp161948 case OP_RAND: 15317211Sjp161948 case OP_DIGEST: 15327211Sjp161948 case OP_CIPHER: 15337526SVladimir.Kotal@Sun.COM freelist_lock = session_cache[optype].lock; 15347211Sjp161948 break; 15357211Sjp161948 default: 1536*7616SVladimir.Kotal@Sun.COM PK11err(PK11_F_GET_SESSION, 15377211Sjp161948 PK11_R_INVALID_OPERATION_TYPE); 15387526SVladimir.Kotal@Sun.COM return (NULL); 15397211Sjp161948 } 15407526SVladimir.Kotal@Sun.COM (void) pthread_mutex_lock(freelist_lock); 15417526SVladimir.Kotal@Sun.COM freelist = session_cache[optype].head; 15427211Sjp161948 sp = freelist; 15437211Sjp161948 15446847Svk199839 /* 15456847Svk199839 * If the free list is empty, allocate new unitialized (filled 15466847Svk199839 * with zeroes) PK11_SESSION structure otherwise return first 15476847Svk199839 * structure from the freelist. 15486847Svk199839 */ 15497211Sjp161948 if (sp == NULL) 15500Sstevel@tonic-gate { 1551*7616SVladimir.Kotal@Sun.COM if ((sp = OPENSSL_malloc(sizeof (PK11_SESSION))) == NULL) 15520Sstevel@tonic-gate { 1553*7616SVladimir.Kotal@Sun.COM PK11err(PK11_F_GET_SESSION, 15540Sstevel@tonic-gate PK11_R_MALLOC_FAILURE); 15550Sstevel@tonic-gate goto err; 15560Sstevel@tonic-gate } 1557*7616SVladimir.Kotal@Sun.COM (void) memset(sp, 0, sizeof (PK11_SESSION)); 15580Sstevel@tonic-gate } 15590Sstevel@tonic-gate else 15600Sstevel@tonic-gate { 15617211Sjp161948 freelist = sp->next; 15620Sstevel@tonic-gate } 15630Sstevel@tonic-gate 15640Sstevel@tonic-gate if (sp->pid != 0 && sp->pid != getpid()) 15650Sstevel@tonic-gate { 15666847Svk199839 /* 15676847Svk199839 * We are a new process and thus need to free any inherited 15680Sstevel@tonic-gate * PK11_SESSION objects. 15690Sstevel@tonic-gate */ 15707211Sjp161948 while ((sp1 = freelist) != NULL) 15710Sstevel@tonic-gate { 15727211Sjp161948 freelist = sp1->next; 15736847Svk199839 /* 15747211Sjp161948 * NOTE: we do not want to call pk11_free_all_sessions() 15757211Sjp161948 * here because it would close underlying PKCS#11 15767211Sjp161948 * sessions and destroy all objects. 15776847Svk199839 */ 15787526SVladimir.Kotal@Sun.COM pk11_free_nums(sp1, optype); 15790Sstevel@tonic-gate OPENSSL_free(sp1); 15800Sstevel@tonic-gate } 15810Sstevel@tonic-gate 15827526SVladimir.Kotal@Sun.COM /* we have to free the active list as well. */ 15837526SVladimir.Kotal@Sun.COM pk11_free_active_list(optype); 15847526SVladimir.Kotal@Sun.COM 15850Sstevel@tonic-gate /* Initialize the process */ 15860Sstevel@tonic-gate rv = pFuncList->C_Initialize(NULL_PTR); 15870Sstevel@tonic-gate if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) 15880Sstevel@tonic-gate { 15897211Sjp161948 PK11err_add_data(PK11_F_GET_SESSION, PK11_R_INITIALIZE, 15907211Sjp161948 rv); 15910Sstevel@tonic-gate OPENSSL_free(sp); 15920Sstevel@tonic-gate sp = NULL; 15930Sstevel@tonic-gate goto err; 15940Sstevel@tonic-gate } 15950Sstevel@tonic-gate 15966847Svk199839 /* 15977211Sjp161948 * Choose slot here since the slot table is different on this 15987211Sjp161948 * process. If we are here then we must have found at least one 15997211Sjp161948 * usable slot before so we don't need to check any_slot_found. 16007211Sjp161948 * See pk11_library_init()'s usage of this function for more 16017211Sjp161948 * information. 16020Sstevel@tonic-gate */ 16037211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 16047211Sjp161948 if (check_hw_mechanisms() == 0) 16057211Sjp161948 goto err; 16067211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 16077211Sjp161948 if (pk11_choose_slots(NULL) == 0) 16080Sstevel@tonic-gate goto err; 16090Sstevel@tonic-gate 16100Sstevel@tonic-gate /* Open the global_session for the new process */ 16110Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 16120Sstevel@tonic-gate NULL_PTR, NULL_PTR, &global_session); 16130Sstevel@tonic-gate if (rv != CKR_OK) 16140Sstevel@tonic-gate { 16157211Sjp161948 PK11err_add_data(PK11_F_GET_SESSION, PK11_R_OPENSESSION, 16167211Sjp161948 rv); 16170Sstevel@tonic-gate OPENSSL_free(sp); 16180Sstevel@tonic-gate sp = NULL; 16190Sstevel@tonic-gate goto err; 16200Sstevel@tonic-gate } 16210Sstevel@tonic-gate 1622*7616SVladimir.Kotal@Sun.COM /* It is an inherited session and needs re-initialization. */ 16237211Sjp161948 if (pk11_setup_session(sp, optype) == 0) 16240Sstevel@tonic-gate { 16250Sstevel@tonic-gate OPENSSL_free(sp); 16260Sstevel@tonic-gate sp = NULL; 16270Sstevel@tonic-gate } 16280Sstevel@tonic-gate } 1629*7616SVladimir.Kotal@Sun.COM if (sp->pid == 0) 16300Sstevel@tonic-gate { 16317211Sjp161948 /* It is a new session and needs initialization. */ 16327211Sjp161948 if (pk11_setup_session(sp, optype) == 0) 16330Sstevel@tonic-gate { 16340Sstevel@tonic-gate OPENSSL_free(sp); 16350Sstevel@tonic-gate sp = NULL; 16360Sstevel@tonic-gate } 16370Sstevel@tonic-gate } 16380Sstevel@tonic-gate 16397526SVladimir.Kotal@Sun.COM /* set new head for the list of PK11_SESSION objects */ 16407526SVladimir.Kotal@Sun.COM session_cache[optype].head = freelist; 16417211Sjp161948 16420Sstevel@tonic-gate err: 16436847Svk199839 if (sp != NULL) 16440Sstevel@tonic-gate sp->next = NULL; 16450Sstevel@tonic-gate 16467526SVladimir.Kotal@Sun.COM (void) pthread_mutex_unlock(freelist_lock); 16470Sstevel@tonic-gate 1648*7616SVladimir.Kotal@Sun.COM return (sp); 16490Sstevel@tonic-gate } 16500Sstevel@tonic-gate 16510Sstevel@tonic-gate 1652*7616SVladimir.Kotal@Sun.COM void 1653*7616SVladimir.Kotal@Sun.COM pk11_return_session(PK11_SESSION *sp, PK11_OPTYPE optype) 16540Sstevel@tonic-gate { 16557526SVladimir.Kotal@Sun.COM pthread_mutex_t *freelist_lock; 16567526SVladimir.Kotal@Sun.COM PK11_SESSION *freelist; 16577526SVladimir.Kotal@Sun.COM 16580Sstevel@tonic-gate if (sp == NULL || sp->pid != getpid()) 16590Sstevel@tonic-gate return; 1660*7616SVladimir.Kotal@Sun.COM 16617211Sjp161948 switch (optype) 16627211Sjp161948 { 16637526SVladimir.Kotal@Sun.COM case OP_RSA: 16647526SVladimir.Kotal@Sun.COM case OP_DSA: 16657526SVladimir.Kotal@Sun.COM case OP_DH: 16667211Sjp161948 case OP_RAND: 16677211Sjp161948 case OP_DIGEST: 16687211Sjp161948 case OP_CIPHER: 16697526SVladimir.Kotal@Sun.COM freelist_lock = session_cache[optype].lock; 16707211Sjp161948 break; 16717526SVladimir.Kotal@Sun.COM default: 16727526SVladimir.Kotal@Sun.COM PK11err(PK11_F_RETURN_SESSION, 16737526SVladimir.Kotal@Sun.COM PK11_R_INVALID_OPERATION_TYPE); 16747526SVladimir.Kotal@Sun.COM return; 16757211Sjp161948 } 16760Sstevel@tonic-gate 16777526SVladimir.Kotal@Sun.COM (void) pthread_mutex_lock(freelist_lock); 16787526SVladimir.Kotal@Sun.COM freelist = session_cache[optype].head; 16797526SVladimir.Kotal@Sun.COM sp->next = freelist; 16807526SVladimir.Kotal@Sun.COM session_cache[optype].head = sp; 16817526SVladimir.Kotal@Sun.COM (void) pthread_mutex_unlock(freelist_lock); 16820Sstevel@tonic-gate } 16830Sstevel@tonic-gate 16840Sstevel@tonic-gate 1685*7616SVladimir.Kotal@Sun.COM /* Destroy all objects. This function is called when the engine is finished */ 16860Sstevel@tonic-gate static int pk11_free_all_sessions() 16870Sstevel@tonic-gate { 16887211Sjp161948 int ret = 1; 16897526SVladimir.Kotal@Sun.COM int type; 16900Sstevel@tonic-gate 16916847Svk199839 #ifndef OPENSSL_NO_RSA 16926847Svk199839 (void) pk11_destroy_rsa_key_objects(NULL); 16937211Sjp161948 #endif /* OPENSSL_NO_RSA */ 16946847Svk199839 #ifndef OPENSSL_NO_DSA 16956847Svk199839 (void) pk11_destroy_dsa_key_objects(NULL); 16967211Sjp161948 #endif /* OPENSSL_NO_DSA */ 16976847Svk199839 #ifndef OPENSSL_NO_DH 16986847Svk199839 (void) pk11_destroy_dh_key_objects(NULL); 16997211Sjp161948 #endif /* OPENSSL_NO_DH */ 17006847Svk199839 (void) pk11_destroy_cipher_key_objects(NULL); 17017211Sjp161948 17027211Sjp161948 /* 17037211Sjp161948 * We try to release as much as we can but any error means that we will 17047211Sjp161948 * return 0 on exit. 17057211Sjp161948 */ 17067526SVladimir.Kotal@Sun.COM for (type = 0; type < OP_MAX; type++) 17077526SVladimir.Kotal@Sun.COM { 17087526SVladimir.Kotal@Sun.COM if (pk11_free_session_list(type) == 0) 17097526SVladimir.Kotal@Sun.COM ret = 0; 17107526SVladimir.Kotal@Sun.COM } 17117211Sjp161948 1712*7616SVladimir.Kotal@Sun.COM return (ret); 17137211Sjp161948 } 1714*7616SVladimir.Kotal@Sun.COM 17157211Sjp161948 /* 17167526SVladimir.Kotal@Sun.COM * Destroy session structures from the linked list specified. Free as many 17177526SVladimir.Kotal@Sun.COM * sessions as possible but any failure in C_CloseSession() means that we 17187526SVladimir.Kotal@Sun.COM * return an error on return. 17197211Sjp161948 */ 17207526SVladimir.Kotal@Sun.COM static int pk11_free_session_list(PK11_OPTYPE optype) 17217211Sjp161948 { 17227211Sjp161948 CK_RV rv; 17237211Sjp161948 PK11_SESSION *sp = NULL; 17247526SVladimir.Kotal@Sun.COM PK11_SESSION *freelist = NULL; 17257211Sjp161948 pid_t mypid = getpid(); 17267526SVladimir.Kotal@Sun.COM pthread_mutex_t *freelist_lock; 17277211Sjp161948 int ret = 1; 17287211Sjp161948 17297526SVladimir.Kotal@Sun.COM switch (optype) 17307526SVladimir.Kotal@Sun.COM { 17317526SVladimir.Kotal@Sun.COM case OP_RSA: 17327526SVladimir.Kotal@Sun.COM case OP_DSA: 17337526SVladimir.Kotal@Sun.COM case OP_DH: 17347526SVladimir.Kotal@Sun.COM case OP_RAND: 17357526SVladimir.Kotal@Sun.COM case OP_DIGEST: 17367526SVladimir.Kotal@Sun.COM case OP_CIPHER: 17377526SVladimir.Kotal@Sun.COM freelist_lock = session_cache[optype].lock; 17387526SVladimir.Kotal@Sun.COM break; 17397526SVladimir.Kotal@Sun.COM default: 17407526SVladimir.Kotal@Sun.COM PK11err(PK11_F_FREE_ALL_SESSIONS, 17417526SVladimir.Kotal@Sun.COM PK11_R_INVALID_OPERATION_TYPE); 17427526SVladimir.Kotal@Sun.COM return (0); 17437526SVladimir.Kotal@Sun.COM } 17447526SVladimir.Kotal@Sun.COM 17457526SVladimir.Kotal@Sun.COM (void) pthread_mutex_lock(freelist_lock); 17467526SVladimir.Kotal@Sun.COM freelist = session_cache[optype].head; 17477526SVladimir.Kotal@Sun.COM while ((sp = freelist) != NULL) 17480Sstevel@tonic-gate { 17490Sstevel@tonic-gate if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid) 17500Sstevel@tonic-gate { 17510Sstevel@tonic-gate rv = pFuncList->C_CloseSession(sp->session); 17520Sstevel@tonic-gate if (rv != CKR_OK) 17530Sstevel@tonic-gate { 1754*7616SVladimir.Kotal@Sun.COM PK11err_add_data(PK11_F_FREE_ALL_SESSIONS, 17557211Sjp161948 PK11_R_CLOSESESSION, rv); 17567211Sjp161948 ret = 0; 17570Sstevel@tonic-gate } 17580Sstevel@tonic-gate } 17597526SVladimir.Kotal@Sun.COM freelist = sp->next; 17607526SVladimir.Kotal@Sun.COM pk11_free_nums(sp, optype); 17610Sstevel@tonic-gate OPENSSL_free(sp); 17620Sstevel@tonic-gate } 17637211Sjp161948 17647526SVladimir.Kotal@Sun.COM (void) pthread_mutex_unlock(freelist_lock); 1765*7616SVladimir.Kotal@Sun.COM return (ret); 17660Sstevel@tonic-gate } 17670Sstevel@tonic-gate 17680Sstevel@tonic-gate 17697211Sjp161948 static int pk11_setup_session(PK11_SESSION *sp, PK11_OPTYPE optype) 17700Sstevel@tonic-gate { 17710Sstevel@tonic-gate CK_RV rv; 17727211Sjp161948 CK_SLOT_ID myslot; 17737211Sjp161948 17747211Sjp161948 switch (optype) 17757211Sjp161948 { 17767526SVladimir.Kotal@Sun.COM case OP_RSA: 17777526SVladimir.Kotal@Sun.COM case OP_DSA: 17787526SVladimir.Kotal@Sun.COM case OP_DH: 17797211Sjp161948 myslot = pubkey_SLOTID; 17807211Sjp161948 break; 17817211Sjp161948 case OP_RAND: 17827211Sjp161948 myslot = rand_SLOTID; 17837211Sjp161948 break; 17847211Sjp161948 case OP_DIGEST: 17857211Sjp161948 case OP_CIPHER: 17867211Sjp161948 myslot = SLOTID; 17877211Sjp161948 break; 17887211Sjp161948 default: 17897211Sjp161948 PK11err(PK11_F_SETUP_SESSION, 17907211Sjp161948 PK11_R_INVALID_OPERATION_TYPE); 1791*7616SVladimir.Kotal@Sun.COM return (0); 17927211Sjp161948 } 17937211Sjp161948 17940Sstevel@tonic-gate sp->session = CK_INVALID_HANDLE; 17957211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 17967211Sjp161948 fprintf(stderr, "%s: myslot=%d optype=%d\n", PK11_DBG, myslot, optype); 17977211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 17987211Sjp161948 rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, 17990Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session); 18000Sstevel@tonic-gate if (rv == CKR_CRYPTOKI_NOT_INITIALIZED) 18010Sstevel@tonic-gate { 18020Sstevel@tonic-gate /* 18030Sstevel@tonic-gate * We are probably a child process so force the 18040Sstevel@tonic-gate * reinitialize of the session 18050Sstevel@tonic-gate */ 18067526SVladimir.Kotal@Sun.COM pk11_library_initialized = FALSE; 18070Sstevel@tonic-gate (void) pk11_library_init(NULL); 18087211Sjp161948 rv = pFuncList->C_OpenSession(myslot, CKF_SERIAL_SESSION, 18090Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session); 18100Sstevel@tonic-gate } 18110Sstevel@tonic-gate if (rv != CKR_OK) 18120Sstevel@tonic-gate { 18137211Sjp161948 PK11err_add_data(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION, rv); 1814*7616SVladimir.Kotal@Sun.COM return (0); 18150Sstevel@tonic-gate } 18160Sstevel@tonic-gate 18177526SVladimir.Kotal@Sun.COM sp->pid = getpid(); 18187526SVladimir.Kotal@Sun.COM 18197526SVladimir.Kotal@Sun.COM switch (optype) 18200Sstevel@tonic-gate { 18216847Svk199839 #ifndef OPENSSL_NO_RSA 18227526SVladimir.Kotal@Sun.COM case OP_RSA: 18237526SVladimir.Kotal@Sun.COM sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; 18247526SVladimir.Kotal@Sun.COM sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; 18257526SVladimir.Kotal@Sun.COM sp->opdata_rsa_pub = NULL; 18267526SVladimir.Kotal@Sun.COM sp->opdata_rsa_n_num = NULL; 18277526SVladimir.Kotal@Sun.COM sp->opdata_rsa_e_num = NULL; 18287526SVladimir.Kotal@Sun.COM sp->opdata_rsa_priv = NULL; 18297526SVladimir.Kotal@Sun.COM sp->opdata_rsa_d_num = NULL; 18307526SVladimir.Kotal@Sun.COM break; 18317211Sjp161948 #endif /* OPENSSL_NO_RSA */ 18326847Svk199839 #ifndef OPENSSL_NO_DSA 18337526SVladimir.Kotal@Sun.COM case OP_DSA: 18347526SVladimir.Kotal@Sun.COM sp->opdata_dsa_pub_key = CK_INVALID_HANDLE; 18357526SVladimir.Kotal@Sun.COM sp->opdata_dsa_priv_key = CK_INVALID_HANDLE; 18367526SVladimir.Kotal@Sun.COM sp->opdata_dsa_pub = NULL; 18377526SVladimir.Kotal@Sun.COM sp->opdata_dsa_pub_num = NULL; 18387526SVladimir.Kotal@Sun.COM sp->opdata_dsa_priv = NULL; 18397526SVladimir.Kotal@Sun.COM sp->opdata_dsa_priv_num = NULL; 18407526SVladimir.Kotal@Sun.COM break; 18417211Sjp161948 #endif /* OPENSSL_NO_DSA */ 18426847Svk199839 #ifndef OPENSSL_NO_DH 18437526SVladimir.Kotal@Sun.COM case OP_DH: 18447526SVladimir.Kotal@Sun.COM sp->opdata_dh_key = CK_INVALID_HANDLE; 18457526SVladimir.Kotal@Sun.COM sp->opdata_dh = NULL; 18467526SVladimir.Kotal@Sun.COM sp->opdata_dh_priv_num = NULL; 18477526SVladimir.Kotal@Sun.COM break; 18487211Sjp161948 #endif /* OPENSSL_NO_DH */ 18497526SVladimir.Kotal@Sun.COM case OP_CIPHER: 18507526SVladimir.Kotal@Sun.COM sp->opdata_cipher_key = CK_INVALID_HANDLE; 18517526SVladimir.Kotal@Sun.COM sp->opdata_encrypt = -1; 18527526SVladimir.Kotal@Sun.COM break; 18537526SVladimir.Kotal@Sun.COM } 18540Sstevel@tonic-gate 1855*7616SVladimir.Kotal@Sun.COM return (1); 18560Sstevel@tonic-gate } 18570Sstevel@tonic-gate 18586847Svk199839 #ifndef OPENSSL_NO_RSA 18596847Svk199839 /* Destroy RSA public key from single session. */ 1860*7616SVladimir.Kotal@Sun.COM int 1861*7616SVladimir.Kotal@Sun.COM pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) 18626847Svk199839 { 18636847Svk199839 int ret = 0; 18646847Svk199839 18657526SVladimir.Kotal@Sun.COM if (sp->opdata_rsa_pub_key != CK_INVALID_HANDLE) 18666847Svk199839 { 18677526SVladimir.Kotal@Sun.COM TRY_OBJ_DESTROY(sp->session, sp->opdata_rsa_pub_key, 18687526SVladimir.Kotal@Sun.COM ret, uselock, OP_RSA); 18697526SVladimir.Kotal@Sun.COM sp->opdata_rsa_pub_key = CK_INVALID_HANDLE; 18707526SVladimir.Kotal@Sun.COM sp->opdata_rsa_pub = NULL; 18717526SVladimir.Kotal@Sun.COM if (sp->opdata_rsa_n_num != NULL) 18727526SVladimir.Kotal@Sun.COM { 18737526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_rsa_n_num); 18747526SVladimir.Kotal@Sun.COM sp->opdata_rsa_n_num = NULL; 18757526SVladimir.Kotal@Sun.COM } 18767526SVladimir.Kotal@Sun.COM if (sp->opdata_rsa_e_num != NULL) 18777526SVladimir.Kotal@Sun.COM { 18787526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_rsa_e_num); 18797526SVladimir.Kotal@Sun.COM sp->opdata_rsa_e_num = NULL; 18807526SVladimir.Kotal@Sun.COM } 18816847Svk199839 } 18826847Svk199839 18836847Svk199839 return (ret); 18846847Svk199839 } 18856847Svk199839 18866847Svk199839 /* Destroy RSA private key from single session. */ 1887*7616SVladimir.Kotal@Sun.COM int 1888*7616SVladimir.Kotal@Sun.COM pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) 18890Sstevel@tonic-gate { 18900Sstevel@tonic-gate int ret = 0; 18916847Svk199839 18927526SVladimir.Kotal@Sun.COM if (sp->opdata_rsa_priv_key != CK_INVALID_HANDLE) 18936847Svk199839 { 18947526SVladimir.Kotal@Sun.COM TRY_OBJ_DESTROY(sp->session, sp->opdata_rsa_priv_key, 18957526SVladimir.Kotal@Sun.COM ret, uselock, OP_RSA); 18967526SVladimir.Kotal@Sun.COM sp->opdata_rsa_priv_key = CK_INVALID_HANDLE; 18977526SVladimir.Kotal@Sun.COM sp->opdata_rsa_priv = NULL; 18987526SVladimir.Kotal@Sun.COM if (sp->opdata_rsa_d_num != NULL) 18997526SVladimir.Kotal@Sun.COM { 19007526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_rsa_d_num); 19017526SVladimir.Kotal@Sun.COM sp->opdata_rsa_d_num = NULL; 19027526SVladimir.Kotal@Sun.COM } 19036847Svk199839 } 19046847Svk199839 19056847Svk199839 return (ret); 19066847Svk199839 } 19076847Svk199839 19086847Svk199839 /* 19097211Sjp161948 * Destroy RSA key object wrapper. If session is NULL, try to destroy all 19107211Sjp161948 * objects in the free list. 19116847Svk199839 */ 1912*7616SVladimir.Kotal@Sun.COM int 1913*7616SVladimir.Kotal@Sun.COM pk11_destroy_rsa_key_objects(PK11_SESSION *session) 19146847Svk199839 { 19156847Svk199839 int ret = 1; 19160Sstevel@tonic-gate PK11_SESSION *sp = NULL; 19170Sstevel@tonic-gate PK11_SESSION *local_free_session; 19186847Svk199839 CK_BBOOL uselock = TRUE; 19190Sstevel@tonic-gate 19206847Svk199839 if (session != NULL) 19210Sstevel@tonic-gate local_free_session = session; 19220Sstevel@tonic-gate else 19236847Svk199839 { 19247526SVladimir.Kotal@Sun.COM (void) pthread_mutex_lock(session_cache[OP_RSA].lock); 19257526SVladimir.Kotal@Sun.COM local_free_session = session_cache[OP_RSA].head; 19266847Svk199839 uselock = FALSE; 19276847Svk199839 } 19280Sstevel@tonic-gate 19296847Svk199839 /* 19306847Svk199839 * go through the list of sessions and delete key objects 19316847Svk199839 */ 19320Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 19330Sstevel@tonic-gate { 19340Sstevel@tonic-gate local_free_session = sp->next; 19350Sstevel@tonic-gate 19366847Svk199839 /* 19376847Svk199839 * Do not terminate list traversal if one of the 19386847Svk199839 * destroy operations fails. 19396847Svk199839 */ 19406847Svk199839 if (pk11_destroy_rsa_object_pub(sp, uselock) == 0) 19410Sstevel@tonic-gate { 19426847Svk199839 ret = 0; 19436847Svk199839 continue; 19440Sstevel@tonic-gate } 19456847Svk199839 if (pk11_destroy_rsa_object_priv(sp, uselock) == 0) 19466847Svk199839 { 19476847Svk199839 ret = 0; 19486847Svk199839 continue; 19496847Svk199839 } 19506847Svk199839 } 19510Sstevel@tonic-gate 19526847Svk199839 if (session == NULL) 19537526SVladimir.Kotal@Sun.COM (void) pthread_mutex_unlock(session_cache[OP_RSA].lock); 19540Sstevel@tonic-gate 1955*7616SVladimir.Kotal@Sun.COM return (ret); 19560Sstevel@tonic-gate } 19577211Sjp161948 #endif /* OPENSSL_NO_RSA */ 19580Sstevel@tonic-gate 19596847Svk199839 #ifndef OPENSSL_NO_DSA 19606847Svk199839 /* Destroy DSA public key from single session. */ 1961*7616SVladimir.Kotal@Sun.COM int 1962*7616SVladimir.Kotal@Sun.COM pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) 19630Sstevel@tonic-gate { 19640Sstevel@tonic-gate int ret = 0; 19656847Svk199839 19667526SVladimir.Kotal@Sun.COM if (sp->opdata_dsa_pub_key != CK_INVALID_HANDLE) 19676847Svk199839 { 19687526SVladimir.Kotal@Sun.COM TRY_OBJ_DESTROY(sp->session, sp->opdata_dsa_pub_key, 19697526SVladimir.Kotal@Sun.COM ret, uselock, OP_DSA); 19707526SVladimir.Kotal@Sun.COM sp->opdata_dsa_pub_key = CK_INVALID_HANDLE; 19717526SVladimir.Kotal@Sun.COM sp->opdata_dsa_pub = NULL; 19727526SVladimir.Kotal@Sun.COM if (sp->opdata_dsa_pub_num != NULL) 19737526SVladimir.Kotal@Sun.COM { 19747526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_dsa_pub_num); 19757526SVladimir.Kotal@Sun.COM sp->opdata_dsa_pub_num = NULL; 19767526SVladimir.Kotal@Sun.COM } 19776847Svk199839 } 19786847Svk199839 19796847Svk199839 return (ret); 19806847Svk199839 } 19816847Svk199839 19826847Svk199839 /* Destroy DSA private key from single session. */ 1983*7616SVladimir.Kotal@Sun.COM int 1984*7616SVladimir.Kotal@Sun.COM pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) 19856847Svk199839 { 19866847Svk199839 int ret = 0; 19876847Svk199839 19887526SVladimir.Kotal@Sun.COM if (sp->opdata_dsa_priv_key != CK_INVALID_HANDLE) 19896847Svk199839 { 19907526SVladimir.Kotal@Sun.COM TRY_OBJ_DESTROY(sp->session, sp->opdata_dsa_priv_key, 19917526SVladimir.Kotal@Sun.COM ret, uselock, OP_DSA); 19927526SVladimir.Kotal@Sun.COM sp->opdata_dsa_priv_key = CK_INVALID_HANDLE; 19937526SVladimir.Kotal@Sun.COM sp->opdata_dsa_priv = NULL; 19947526SVladimir.Kotal@Sun.COM if (sp->opdata_dsa_priv_num != NULL) 19957526SVladimir.Kotal@Sun.COM { 19967526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_dsa_priv_num); 19977526SVladimir.Kotal@Sun.COM sp->opdata_dsa_priv_num = NULL; 19987526SVladimir.Kotal@Sun.COM } 19996847Svk199839 } 20006847Svk199839 20016847Svk199839 return (ret); 20026847Svk199839 } 20036847Svk199839 20046847Svk199839 /* 20057211Sjp161948 * Destroy DSA key object wrapper. If session is NULL, try to destroy all 20067211Sjp161948 * objects in the free list. 20076847Svk199839 */ 2008*7616SVladimir.Kotal@Sun.COM int 2009*7616SVladimir.Kotal@Sun.COM pk11_destroy_dsa_key_objects(PK11_SESSION *session) 20106847Svk199839 { 20116847Svk199839 int ret = 1; 20120Sstevel@tonic-gate PK11_SESSION *sp = NULL; 20130Sstevel@tonic-gate PK11_SESSION *local_free_session; 20146847Svk199839 CK_BBOOL uselock = TRUE; 20150Sstevel@tonic-gate 20166847Svk199839 if (session != NULL) 20170Sstevel@tonic-gate local_free_session = session; 20180Sstevel@tonic-gate else 20196847Svk199839 { 20207526SVladimir.Kotal@Sun.COM (void) pthread_mutex_lock(session_cache[OP_DSA].lock); 20217526SVladimir.Kotal@Sun.COM local_free_session = session_cache[OP_DSA].head; 20226847Svk199839 uselock = FALSE; 20236847Svk199839 } 20246847Svk199839 20256847Svk199839 /* 20266847Svk199839 * go through the list of sessions and delete key objects 20276847Svk199839 */ 20280Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 20290Sstevel@tonic-gate { 20300Sstevel@tonic-gate local_free_session = sp->next; 20310Sstevel@tonic-gate 20326847Svk199839 /* 20336847Svk199839 * Do not terminate list traversal if one of the 20346847Svk199839 * destroy operations fails. 20356847Svk199839 */ 20366847Svk199839 if (pk11_destroy_dsa_object_pub(sp, uselock) == 0) 20370Sstevel@tonic-gate { 20386847Svk199839 ret = 0; 20396847Svk199839 continue; 20400Sstevel@tonic-gate } 20416847Svk199839 if (pk11_destroy_dsa_object_priv(sp, uselock) == 0) 20426847Svk199839 { 20436847Svk199839 ret = 0; 20446847Svk199839 continue; 20456847Svk199839 } 20460Sstevel@tonic-gate } 20476847Svk199839 20486847Svk199839 if (session == NULL) 20497526SVladimir.Kotal@Sun.COM (void) pthread_mutex_unlock(session_cache[OP_DSA].lock); 20500Sstevel@tonic-gate 2051*7616SVladimir.Kotal@Sun.COM return (ret); 20520Sstevel@tonic-gate } 20537211Sjp161948 #endif /* OPENSSL_NO_DSA */ 20546847Svk199839 20556847Svk199839 #ifndef OPENSSL_NO_DH 20566847Svk199839 /* Destroy DH key from single session. */ 2057*7616SVladimir.Kotal@Sun.COM int 2058*7616SVladimir.Kotal@Sun.COM pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock) 20596847Svk199839 { 20606847Svk199839 int ret = 0; 20616847Svk199839 20627526SVladimir.Kotal@Sun.COM if (sp->opdata_dh_key != CK_INVALID_HANDLE) 20636847Svk199839 { 20647526SVladimir.Kotal@Sun.COM TRY_OBJ_DESTROY(sp->session, sp->opdata_dh_key, 20657526SVladimir.Kotal@Sun.COM ret, uselock, OP_DH); 20667526SVladimir.Kotal@Sun.COM sp->opdata_dh_key = CK_INVALID_HANDLE; 20677526SVladimir.Kotal@Sun.COM sp->opdata_dh = NULL; 20687526SVladimir.Kotal@Sun.COM if (sp->opdata_dh_priv_num != NULL) 20697526SVladimir.Kotal@Sun.COM { 20707526SVladimir.Kotal@Sun.COM BN_free(sp->opdata_dh_priv_num); 20717526SVladimir.Kotal@Sun.COM sp->opdata_dh_priv_num = NULL; 20727526SVladimir.Kotal@Sun.COM } 20736847Svk199839 } 20746847Svk199839 20756847Svk199839 return (ret); 20766847Svk199839 } 20776847Svk199839 20786847Svk199839 /* 20796847Svk199839 * Destroy DH key object wrapper. 20806847Svk199839 * 20816847Svk199839 * arg0: pointer to PKCS#11 engine session structure 20826847Svk199839 * if session is NULL, try to destroy all objects in the free list 20836847Svk199839 */ 2084*7616SVladimir.Kotal@Sun.COM int 2085*7616SVladimir.Kotal@Sun.COM pk11_destroy_dh_key_objects(PK11_SESSION *session) 20866847Svk199839 { 20876847Svk199839 int ret = 1; 20886847Svk199839 PK11_SESSION *sp = NULL; 20896847Svk199839 PK11_SESSION *local_free_session; 20906847Svk199839 CK_BBOOL uselock = TRUE; 20916847Svk199839 20926847Svk199839 if (session != NULL) 20936847Svk199839 local_free_session = session; 20946847Svk199839 else 20956847Svk199839 { 20967526SVladimir.Kotal@Sun.COM (void) pthread_mutex_lock(session_cache[OP_DH].lock); 20977526SVladimir.Kotal@Sun.COM local_free_session = session_cache[OP_DH].head; 20986847Svk199839 uselock = FALSE; 20996847Svk199839 } 21006847Svk199839 21016847Svk199839 while ((sp = local_free_session) != NULL) 21026847Svk199839 { 21036847Svk199839 local_free_session = sp->next; 21046847Svk199839 21056847Svk199839 /* 21066847Svk199839 * Do not terminate list traversal if one of the 21076847Svk199839 * destroy operations fails. 21086847Svk199839 */ 21096847Svk199839 if (pk11_destroy_dh_object(sp, uselock) == 0) 21106847Svk199839 { 21116847Svk199839 ret = 0; 21126847Svk199839 continue; 21136847Svk199839 } 21146847Svk199839 } 21156847Svk199839 err: 21166847Svk199839 if (session == NULL) 21177526SVladimir.Kotal@Sun.COM (void) pthread_mutex_unlock(session_cache[OP_DH].lock); 21186847Svk199839 2119*7616SVladimir.Kotal@Sun.COM return (ret); 21206847Svk199839 } 21217211Sjp161948 #endif /* OPENSSL_NO_DH */ 21220Sstevel@tonic-gate 21230Sstevel@tonic-gate static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh) 21240Sstevel@tonic-gate { 21250Sstevel@tonic-gate CK_RV rv; 21260Sstevel@tonic-gate rv = pFuncList->C_DestroyObject(session, oh); 21270Sstevel@tonic-gate if (rv != CKR_OK) 21280Sstevel@tonic-gate { 21297211Sjp161948 PK11err_add_data(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT, 21307211Sjp161948 rv); 2131*7616SVladimir.Kotal@Sun.COM return (0); 21320Sstevel@tonic-gate } 21330Sstevel@tonic-gate 2134*7616SVladimir.Kotal@Sun.COM return (1); 21350Sstevel@tonic-gate } 21360Sstevel@tonic-gate 21370Sstevel@tonic-gate 2138*7616SVladimir.Kotal@Sun.COM /* Symmetric ciphers and digests support functions */ 21390Sstevel@tonic-gate 21400Sstevel@tonic-gate static int 21410Sstevel@tonic-gate cipher_nid_to_pk11(int nid) 21420Sstevel@tonic-gate { 21430Sstevel@tonic-gate int i; 21440Sstevel@tonic-gate 21450Sstevel@tonic-gate for (i = 0; i < PK11_CIPHER_MAX; i++) 21460Sstevel@tonic-gate if (ciphers[i].nid == nid) 21470Sstevel@tonic-gate return (ciphers[i].id); 21480Sstevel@tonic-gate return (-1); 21490Sstevel@tonic-gate } 21500Sstevel@tonic-gate 21510Sstevel@tonic-gate static int 21520Sstevel@tonic-gate pk11_usable_ciphers(const int **nids) 21530Sstevel@tonic-gate { 21540Sstevel@tonic-gate if (cipher_count > 0) 21550Sstevel@tonic-gate *nids = cipher_nids; 21560Sstevel@tonic-gate else 21570Sstevel@tonic-gate *nids = NULL; 21580Sstevel@tonic-gate return (cipher_count); 21590Sstevel@tonic-gate } 21600Sstevel@tonic-gate 21610Sstevel@tonic-gate static int 21620Sstevel@tonic-gate pk11_usable_digests(const int **nids) 21630Sstevel@tonic-gate { 21640Sstevel@tonic-gate if (digest_count > 0) 21650Sstevel@tonic-gate *nids = digest_nids; 21660Sstevel@tonic-gate else 21670Sstevel@tonic-gate *nids = NULL; 21680Sstevel@tonic-gate return (digest_count); 21690Sstevel@tonic-gate } 21700Sstevel@tonic-gate 21717211Sjp161948 /* 21727211Sjp161948 * Init context for encryption or decryption using a symmetric key. 21737211Sjp161948 */ 21747211Sjp161948 static int pk11_init_symmetric(EVP_CIPHER_CTX *ctx, PK11_CIPHER *pcipher, 21757211Sjp161948 PK11_SESSION *sp, CK_MECHANISM_PTR pmech) 21767211Sjp161948 { 21777211Sjp161948 CK_RV rv; 21787211Sjp161948 #ifdef SOLARIS_AES_CTR 21797211Sjp161948 CK_AES_CTR_PARAMS ctr_params; 21807211Sjp161948 #endif /* SOLARIS_AES_CTR */ 2181*7616SVladimir.Kotal@Sun.COM 21827211Sjp161948 /* 21837211Sjp161948 * We expect pmech->mechanism to be already set and 21847211Sjp161948 * pParameter/ulParameterLen initialized to NULL/0 before 21857211Sjp161948 * pk11_init_symetric() is called. 21867211Sjp161948 */ 21877211Sjp161948 OPENSSL_assert(pmech->mechanism != NULL); 21887211Sjp161948 OPENSSL_assert(pmech->pParameter == NULL); 21897211Sjp161948 OPENSSL_assert(pmech->ulParameterLen == 0); 21907211Sjp161948 21917211Sjp161948 #ifdef SOLARIS_AES_CTR 21927211Sjp161948 if (ctx->cipher->nid == NID_aes_128_ctr || 21937211Sjp161948 ctx->cipher->nid == NID_aes_192_ctr || 21947211Sjp161948 ctx->cipher->nid == NID_aes_256_ctr) 21957211Sjp161948 { 21967211Sjp161948 pmech->pParameter = (void *)(&ctr_params); 2197*7616SVladimir.Kotal@Sun.COM pmech->ulParameterLen = sizeof (ctr_params); 21987211Sjp161948 /* 21997211Sjp161948 * For now, we are limited to the fixed length of the counter, 22007211Sjp161948 * it covers the whole counter block. That's what RFC 4344 22017211Sjp161948 * needs. For more information on internal structure of the 22027211Sjp161948 * counter block, see RFC 3686. If needed in the future, we can 22037211Sjp161948 * add code so that the counter length can be set via 22047211Sjp161948 * ENGINE_ctrl() function. 22057211Sjp161948 */ 22067211Sjp161948 ctr_params.ulCounterBits = AES_BLOCK_SIZE * 8; 22077211Sjp161948 OPENSSL_assert(pcipher->iv_len == AES_BLOCK_SIZE); 22087534SVladimir.Kotal@Sun.COM (void) memcpy(ctr_params.cb, ctx->iv, AES_BLOCK_SIZE); 22097211Sjp161948 } 22107211Sjp161948 else 22117211Sjp161948 #endif /* SOLARIS_AES_CTR */ 22127211Sjp161948 { 22137211Sjp161948 if (pcipher->iv_len > 0) 22147211Sjp161948 { 22157211Sjp161948 pmech->pParameter = (void *)ctx->iv; 22167211Sjp161948 pmech->ulParameterLen = pcipher->iv_len; 22177211Sjp161948 } 22187211Sjp161948 } 22197211Sjp161948 22207211Sjp161948 /* if we get here, the encryption needs to be reinitialized */ 22217211Sjp161948 if (ctx->encrypt) 22227526SVladimir.Kotal@Sun.COM rv = pFuncList->C_EncryptInit(sp->session, pmech, 22237526SVladimir.Kotal@Sun.COM sp->opdata_cipher_key); 22247211Sjp161948 else 22257526SVladimir.Kotal@Sun.COM rv = pFuncList->C_DecryptInit(sp->session, pmech, 22267526SVladimir.Kotal@Sun.COM sp->opdata_cipher_key); 22277211Sjp161948 22287211Sjp161948 if (rv != CKR_OK) 22297211Sjp161948 { 22307211Sjp161948 PK11err_add_data(PK11_F_CIPHER_INIT, ctx->encrypt ? 22317211Sjp161948 PK11_R_ENCRYPTINIT : PK11_R_DECRYPTINIT, rv); 22327211Sjp161948 pk11_return_session(sp, OP_CIPHER); 22337211Sjp161948 return (0); 22347211Sjp161948 } 22357211Sjp161948 22367211Sjp161948 return (1); 22377211Sjp161948 } 22387211Sjp161948 22397534SVladimir.Kotal@Sun.COM /* ARGSUSED */ 22400Sstevel@tonic-gate static int 22410Sstevel@tonic-gate pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, 22420Sstevel@tonic-gate const unsigned char *iv, int enc) 22430Sstevel@tonic-gate { 22444320Sjp161948 CK_MECHANISM mech; 22450Sstevel@tonic-gate int index; 22460Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; 22470Sstevel@tonic-gate PK11_SESSION *sp; 22487211Sjp161948 PK11_CIPHER *p_ciph_table_row; 2249*7616SVladimir.Kotal@Sun.COM 22500Sstevel@tonic-gate state->sp = NULL; 22510Sstevel@tonic-gate 22520Sstevel@tonic-gate index = cipher_nid_to_pk11(ctx->cipher->nid); 22530Sstevel@tonic-gate if (index < 0 || index >= PK11_CIPHER_MAX) 2254*7616SVladimir.Kotal@Sun.COM return (0); 22550Sstevel@tonic-gate 22567211Sjp161948 p_ciph_table_row = &ciphers[index]; 22577211Sjp161948 /* 22587211Sjp161948 * iv_len in the ctx->cipher structure is the maximum IV length for the 22597211Sjp161948 * current cipher and it must be less or equal to the IV length in our 22607211Sjp161948 * ciphers table. The key length must match precisely. Every application 22617211Sjp161948 * can define its own EVP functions so this code serves as a sanity 22627211Sjp161948 * check. 22637211Sjp161948 * 22647211Sjp161948 * Note that the reason why the IV length in ctx->cipher might be 22657211Sjp161948 * greater than the actual length is that OpenSSL uses BLOCK_CIPHER_defs 22667211Sjp161948 * macro to define functions that return EVP structures for all DES 22677211Sjp161948 * modes. So, even ECB modes get 8 byte IV. 22687211Sjp161948 */ 22697211Sjp161948 if (ctx->cipher->iv_len < p_ciph_table_row->iv_len || 22707211Sjp161948 ctx->key_len != p_ciph_table_row->key_len) 22717211Sjp161948 { 22727211Sjp161948 PK11err(PK11_F_CIPHER_INIT, PK11_R_KEY_OR_IV_LEN_PROBLEM); 2273*7616SVladimir.Kotal@Sun.COM return (0); 22747211Sjp161948 } 22757211Sjp161948 22767211Sjp161948 if ((sp = pk11_get_session(OP_CIPHER)) == NULL) 2277*7616SVladimir.Kotal@Sun.COM return (0); 22780Sstevel@tonic-gate 22794320Sjp161948 /* if applicable, the mechanism parameter is used for IV */ 22807211Sjp161948 mech.mechanism = p_ciph_table_row->mech_type; 22814320Sjp161948 mech.pParameter = NULL; 22824320Sjp161948 mech.ulParameterLen = 0; 22834320Sjp161948 2284*7616SVladimir.Kotal@Sun.COM /* The key object is destroyed here if it is not the current key. */ 22857211Sjp161948 (void) check_new_cipher_key(sp, key, p_ciph_table_row->key_len); 2286*7616SVladimir.Kotal@Sun.COM 2287*7616SVladimir.Kotal@Sun.COM /* 2288*7616SVladimir.Kotal@Sun.COM * If the key is the same and the encryption is also the same, then 2289*7616SVladimir.Kotal@Sun.COM * just reuse it. However, we must not forget to reinitialize the 22906847Svk199839 * context that was finalized in pk11_cipher_cleanup(). 22910Sstevel@tonic-gate */ 22927526SVladimir.Kotal@Sun.COM if (sp->opdata_cipher_key != CK_INVALID_HANDLE && 22937526SVladimir.Kotal@Sun.COM sp->opdata_encrypt == ctx->encrypt) 22940Sstevel@tonic-gate { 22950Sstevel@tonic-gate state->sp = sp; 22967211Sjp161948 if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0) 22976847Svk199839 return (0); 22986847Svk199839 22996847Svk199839 return (1); 23000Sstevel@tonic-gate } 23010Sstevel@tonic-gate 2302*7616SVladimir.Kotal@Sun.COM /* 2303*7616SVladimir.Kotal@Sun.COM * Check if the key has been invalidated. If so, a new key object 23040Sstevel@tonic-gate * needs to be created. 23050Sstevel@tonic-gate */ 23067526SVladimir.Kotal@Sun.COM if (sp->opdata_cipher_key == CK_INVALID_HANDLE) 23070Sstevel@tonic-gate { 23087526SVladimir.Kotal@Sun.COM sp->opdata_cipher_key = pk11_get_cipher_key( 23097211Sjp161948 ctx, key, p_ciph_table_row->key_type, sp); 23100Sstevel@tonic-gate } 23110Sstevel@tonic-gate 23127526SVladimir.Kotal@Sun.COM if (sp->opdata_encrypt != ctx->encrypt && sp->opdata_encrypt != -1) 23130Sstevel@tonic-gate { 2314*7616SVladimir.Kotal@Sun.COM /* 2315*7616SVladimir.Kotal@Sun.COM * The previous encryption/decryption is different. Need to 2316*7616SVladimir.Kotal@Sun.COM * terminate the previous * active encryption/decryption here. 23170Sstevel@tonic-gate */ 23180Sstevel@tonic-gate if (!pk11_cipher_final(sp)) 23190Sstevel@tonic-gate { 23207211Sjp161948 pk11_return_session(sp, OP_CIPHER); 2321*7616SVladimir.Kotal@Sun.COM return (0); 23220Sstevel@tonic-gate } 23230Sstevel@tonic-gate } 23240Sstevel@tonic-gate 23257526SVladimir.Kotal@Sun.COM if (sp->opdata_cipher_key == CK_INVALID_HANDLE) 23260Sstevel@tonic-gate { 23277211Sjp161948 pk11_return_session(sp, OP_CIPHER); 2328*7616SVladimir.Kotal@Sun.COM return (0); 23290Sstevel@tonic-gate } 23300Sstevel@tonic-gate 23316847Svk199839 /* now initialize the context with a new key */ 23327211Sjp161948 if (pk11_init_symmetric(ctx, p_ciph_table_row, sp, &mech) == 0) 23336847Svk199839 return (0); 23340Sstevel@tonic-gate 23357526SVladimir.Kotal@Sun.COM sp->opdata_encrypt = ctx->encrypt; 23360Sstevel@tonic-gate state->sp = sp; 23370Sstevel@tonic-gate 2338*7616SVladimir.Kotal@Sun.COM return (1); 23390Sstevel@tonic-gate } 23400Sstevel@tonic-gate 2341*7616SVladimir.Kotal@Sun.COM /* 2342*7616SVladimir.Kotal@Sun.COM * When reusing the same key in an encryption/decryption session for a 23430Sstevel@tonic-gate * decryption/encryption session, we need to close the active session 23440Sstevel@tonic-gate * and recreate a new one. Note that the key is in the global session so 23450Sstevel@tonic-gate * that it needs not be recreated. 23460Sstevel@tonic-gate * 23470Sstevel@tonic-gate * It is more appropriate to use C_En/DecryptFinish here. At the time of this 23480Sstevel@tonic-gate * development, these two functions in the PKCS#11 libraries used return 23490Sstevel@tonic-gate * unexpected errors when passing in 0 length output. It may be a good 23500Sstevel@tonic-gate * idea to try them again if performance is a problem here and fix 23510Sstevel@tonic-gate * C_En/DecryptFinial if there are bugs there causing the problem. 23520Sstevel@tonic-gate */ 23530Sstevel@tonic-gate static int 23540Sstevel@tonic-gate pk11_cipher_final(PK11_SESSION *sp) 23550Sstevel@tonic-gate { 23560Sstevel@tonic-gate CK_RV rv; 23570Sstevel@tonic-gate 23587526SVladimir.Kotal@Sun.COM rv = pFuncList->C_CloseSession(sp->session); 23590Sstevel@tonic-gate if (rv != CKR_OK) 23600Sstevel@tonic-gate { 23617211Sjp161948 PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_CLOSESESSION, rv); 2362*7616SVladimir.Kotal@Sun.COM return (0); 23630Sstevel@tonic-gate } 23640Sstevel@tonic-gate 23650Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 23667526SVladimir.Kotal@Sun.COM NULL_PTR, NULL_PTR, &sp->session); 23670Sstevel@tonic-gate if (rv != CKR_OK) 23680Sstevel@tonic-gate { 23697211Sjp161948 PK11err_add_data(PK11_F_CIPHER_FINAL, PK11_R_OPENSESSION, rv); 2370*7616SVladimir.Kotal@Sun.COM return (0); 23710Sstevel@tonic-gate } 23720Sstevel@tonic-gate 2373*7616SVladimir.Kotal@Sun.COM return (1); 23740Sstevel@tonic-gate } 23750Sstevel@tonic-gate 2376*7616SVladimir.Kotal@Sun.COM /* 2377*7616SVladimir.Kotal@Sun.COM * An engine interface function. The calling function allocates sufficient 2378*7616SVladimir.Kotal@Sun.COM * memory for the output buffer "out" to hold the results. 2379*7616SVladimir.Kotal@Sun.COM */ 23800Sstevel@tonic-gate static int 23810Sstevel@tonic-gate pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 23820Sstevel@tonic-gate const unsigned char *in, unsigned int inl) 23830Sstevel@tonic-gate { 23840Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; 23850Sstevel@tonic-gate PK11_SESSION *sp; 23860Sstevel@tonic-gate CK_RV rv; 23870Sstevel@tonic-gate unsigned long outl = inl; 23880Sstevel@tonic-gate 23890Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 2390*7616SVladimir.Kotal@Sun.COM return (0); 23910Sstevel@tonic-gate 23920Sstevel@tonic-gate sp = (PK11_SESSION *) state->sp; 23930Sstevel@tonic-gate 23940Sstevel@tonic-gate if (!inl) 2395*7616SVladimir.Kotal@Sun.COM return (1); 23960Sstevel@tonic-gate 23970Sstevel@tonic-gate /* RC4 is the only stream cipher we support */ 23980Sstevel@tonic-gate if (ctx->cipher->nid != NID_rc4 && (inl % ctx->cipher->block_size) != 0) 2399*7616SVladimir.Kotal@Sun.COM return (0); 24000Sstevel@tonic-gate 24010Sstevel@tonic-gate if (ctx->encrypt) 24020Sstevel@tonic-gate { 24037526SVladimir.Kotal@Sun.COM rv = pFuncList->C_EncryptUpdate(sp->session, 24040Sstevel@tonic-gate (unsigned char *)in, inl, out, &outl); 24050Sstevel@tonic-gate 24060Sstevel@tonic-gate if (rv != CKR_OK) 24070Sstevel@tonic-gate { 2408*7616SVladimir.Kotal@Sun.COM PK11err_add_data(PK11_F_CIPHER_DO_CIPHER, 24097211Sjp161948 PK11_R_ENCRYPTUPDATE, rv); 2410*7616SVladimir.Kotal@Sun.COM return (0); 24110Sstevel@tonic-gate } 24120Sstevel@tonic-gate } 24130Sstevel@tonic-gate else 24140Sstevel@tonic-gate { 24157526SVladimir.Kotal@Sun.COM rv = pFuncList->C_DecryptUpdate(sp->session, 24160Sstevel@tonic-gate (unsigned char *)in, inl, out, &outl); 24170Sstevel@tonic-gate 24180Sstevel@tonic-gate if (rv != CKR_OK) 24190Sstevel@tonic-gate { 24207211Sjp161948 PK11err_add_data(PK11_F_CIPHER_DO_CIPHER, 24217211Sjp161948 PK11_R_DECRYPTUPDATE, rv); 2422*7616SVladimir.Kotal@Sun.COM return (0); 24230Sstevel@tonic-gate } 24240Sstevel@tonic-gate } 24250Sstevel@tonic-gate 2426*7616SVladimir.Kotal@Sun.COM /* 2427*7616SVladimir.Kotal@Sun.COM * For DES_CBC, DES3_CBC, AES_CBC, and RC4, the output size is always 2428*7616SVladimir.Kotal@Sun.COM * the same size of input. 2429*7616SVladimir.Kotal@Sun.COM * The application has guaranteed to call the block ciphers with 24300Sstevel@tonic-gate * correctly aligned buffers. 24310Sstevel@tonic-gate */ 24320Sstevel@tonic-gate if (inl != outl) 2433*7616SVladimir.Kotal@Sun.COM return (0); 2434*7616SVladimir.Kotal@Sun.COM 2435*7616SVladimir.Kotal@Sun.COM return (1); 24360Sstevel@tonic-gate } 24370Sstevel@tonic-gate 24386847Svk199839 /* 24397211Sjp161948 * Return the session to the pool. Calling C_EncryptFinal() and C_DecryptFinal() 24407211Sjp161948 * here is the right thing because in EVP_DecryptFinal_ex(), engine's 24417211Sjp161948 * do_cipher() is not even called, and in EVP_EncryptFinal_ex() it is called but 24427211Sjp161948 * the engine can't find out that it's the finalizing call. We wouldn't 24437211Sjp161948 * necessarily have to finalize the context here since reinitializing it with 24447211Sjp161948 * C_(Encrypt|Decrypt)Init() should be fine but for the sake of correctness, 24457211Sjp161948 * let's do it. Some implementations might leak memory if the previously used 24467211Sjp161948 * context is initialized without finalizing it first. 24470Sstevel@tonic-gate */ 24480Sstevel@tonic-gate static int 24490Sstevel@tonic-gate pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx) 24500Sstevel@tonic-gate { 24516847Svk199839 CK_RV rv; 24527211Sjp161948 CK_ULONG len = EVP_MAX_BLOCK_LENGTH; 24536847Svk199839 CK_BYTE buf[EVP_MAX_BLOCK_LENGTH]; 24540Sstevel@tonic-gate PK11_CIPHER_STATE *state = ctx->cipher_data; 24550Sstevel@tonic-gate 24560Sstevel@tonic-gate if (state != NULL && state->sp != NULL) 24570Sstevel@tonic-gate { 24586847Svk199839 /* 24596847Svk199839 * We are not interested in the data here, we just need to get 24606847Svk199839 * rid of the context. 24616847Svk199839 */ 24626847Svk199839 if (ctx->encrypt) 24636847Svk199839 rv = pFuncList->C_EncryptFinal( 24647526SVladimir.Kotal@Sun.COM state->sp->session, buf, &len); 24656847Svk199839 else 24666847Svk199839 rv = pFuncList->C_DecryptFinal( 24677526SVladimir.Kotal@Sun.COM state->sp->session, buf, &len); 24686847Svk199839 24696847Svk199839 if (rv != CKR_OK) 24706847Svk199839 { 24717211Sjp161948 PK11err_add_data(PK11_F_CIPHER_CLEANUP, ctx->encrypt ? 24727211Sjp161948 PK11_R_ENCRYPTFINAL : PK11_R_DECRYPTFINAL, rv); 24737211Sjp161948 pk11_return_session(state->sp, OP_CIPHER); 24746847Svk199839 return (0); 24756847Svk199839 } 24766847Svk199839 24777211Sjp161948 pk11_return_session(state->sp, OP_CIPHER); 24780Sstevel@tonic-gate state->sp = NULL; 24790Sstevel@tonic-gate } 24800Sstevel@tonic-gate 24816847Svk199839 return (1); 24826847Svk199839 } 24836847Svk199839 2484*7616SVladimir.Kotal@Sun.COM /* 2485*7616SVladimir.Kotal@Sun.COM * Registered by the ENGINE when used to find out how to deal with 24860Sstevel@tonic-gate * a particular NID in the ENGINE. This says what we'll do at the 24870Sstevel@tonic-gate * top level - note, that list is restricted by what we answer with 24880Sstevel@tonic-gate */ 24897534SVladimir.Kotal@Sun.COM /* ARGSUSED */ 24900Sstevel@tonic-gate static int 24910Sstevel@tonic-gate pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 24920Sstevel@tonic-gate const int **nids, int nid) 24930Sstevel@tonic-gate { 24940Sstevel@tonic-gate if (!cipher) 24950Sstevel@tonic-gate return (pk11_usable_ciphers(nids)); 24960Sstevel@tonic-gate 24970Sstevel@tonic-gate switch (nid) 24980Sstevel@tonic-gate { 24990Sstevel@tonic-gate case NID_des_ede3_cbc: 25000Sstevel@tonic-gate *cipher = &pk11_3des_cbc; 25010Sstevel@tonic-gate break; 25020Sstevel@tonic-gate case NID_des_cbc: 25030Sstevel@tonic-gate *cipher = &pk11_des_cbc; 25040Sstevel@tonic-gate break; 25057211Sjp161948 case NID_des_ede3_ecb: 25067211Sjp161948 *cipher = &pk11_3des_ecb; 25077211Sjp161948 break; 25087211Sjp161948 case NID_des_ecb: 25097211Sjp161948 *cipher = &pk11_des_ecb; 25107211Sjp161948 break; 25110Sstevel@tonic-gate case NID_aes_128_cbc: 25127211Sjp161948 *cipher = &pk11_aes_128_cbc; 25137211Sjp161948 break; 25147211Sjp161948 case NID_aes_192_cbc: 25157211Sjp161948 *cipher = &pk11_aes_192_cbc; 25167211Sjp161948 break; 25177211Sjp161948 case NID_aes_256_cbc: 25187211Sjp161948 *cipher = &pk11_aes_256_cbc; 25197211Sjp161948 break; 25207211Sjp161948 case NID_aes_128_ecb: 25217211Sjp161948 *cipher = &pk11_aes_128_ecb; 25227211Sjp161948 break; 25237211Sjp161948 case NID_aes_192_ecb: 25247211Sjp161948 *cipher = &pk11_aes_192_ecb; 25257211Sjp161948 break; 25267211Sjp161948 case NID_aes_256_ecb: 25277211Sjp161948 *cipher = &pk11_aes_256_ecb; 25287211Sjp161948 break; 25297211Sjp161948 case NID_bf_cbc: 25307211Sjp161948 *cipher = &pk11_bf_cbc; 25310Sstevel@tonic-gate break; 25320Sstevel@tonic-gate case NID_rc4: 25330Sstevel@tonic-gate *cipher = &pk11_rc4; 25340Sstevel@tonic-gate break; 25350Sstevel@tonic-gate default: 25367211Sjp161948 #ifdef SOLARIS_AES_CTR 25377211Sjp161948 /* 25387211Sjp161948 * These can't be in separated cases because the NIDs 25397211Sjp161948 * here are not constants. 25407211Sjp161948 */ 25417211Sjp161948 if (nid == NID_aes_128_ctr) 25427211Sjp161948 *cipher = &pk11_aes_128_ctr; 25437211Sjp161948 else if (nid == NID_aes_192_ctr) 25447211Sjp161948 *cipher = &pk11_aes_192_ctr; 25457211Sjp161948 else if (nid == NID_aes_256_ctr) 25467211Sjp161948 *cipher = &pk11_aes_256_ctr; 25477211Sjp161948 else 25487211Sjp161948 #endif /* SOLARIS_AES_CTR */ 25490Sstevel@tonic-gate *cipher = NULL; 25500Sstevel@tonic-gate break; 25510Sstevel@tonic-gate } 25520Sstevel@tonic-gate return (*cipher != NULL); 25530Sstevel@tonic-gate } 25540Sstevel@tonic-gate 25557534SVladimir.Kotal@Sun.COM /* ARGSUSED */ 25560Sstevel@tonic-gate static int 25570Sstevel@tonic-gate pk11_engine_digests(ENGINE *e, const EVP_MD **digest, 25580Sstevel@tonic-gate const int **nids, int nid) 25590Sstevel@tonic-gate { 25600Sstevel@tonic-gate if (!digest) 25610Sstevel@tonic-gate return (pk11_usable_digests(nids)); 25620Sstevel@tonic-gate 25630Sstevel@tonic-gate switch (nid) 25640Sstevel@tonic-gate { 25650Sstevel@tonic-gate case NID_md5: 2566*7616SVladimir.Kotal@Sun.COM *digest = &pk11_md5; 25670Sstevel@tonic-gate break; 25680Sstevel@tonic-gate case NID_sha1: 2569*7616SVladimir.Kotal@Sun.COM *digest = &pk11_sha1; 25700Sstevel@tonic-gate break; 25717211Sjp161948 case NID_sha224: 2572*7616SVladimir.Kotal@Sun.COM *digest = &pk11_sha224; 25737211Sjp161948 break; 25747211Sjp161948 case NID_sha256: 2575*7616SVladimir.Kotal@Sun.COM *digest = &pk11_sha256; 25767211Sjp161948 break; 25777211Sjp161948 case NID_sha384: 2578*7616SVladimir.Kotal@Sun.COM *digest = &pk11_sha384; 25797211Sjp161948 break; 25807211Sjp161948 case NID_sha512: 2581*7616SVladimir.Kotal@Sun.COM *digest = &pk11_sha512; 25827211Sjp161948 break; 25830Sstevel@tonic-gate default: 25840Sstevel@tonic-gate *digest = NULL; 25850Sstevel@tonic-gate break; 25860Sstevel@tonic-gate } 25870Sstevel@tonic-gate return (*digest != NULL); 25880Sstevel@tonic-gate } 25890Sstevel@tonic-gate 25900Sstevel@tonic-gate 2591*7616SVladimir.Kotal@Sun.COM /* Create a secret key object in a PKCS#11 session */ 2592*7616SVladimir.Kotal@Sun.COM static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, 25930Sstevel@tonic-gate const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp) 25940Sstevel@tonic-gate { 25950Sstevel@tonic-gate CK_RV rv; 25960Sstevel@tonic-gate CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; 25970Sstevel@tonic-gate CK_OBJECT_CLASS obj_key = CKO_SECRET_KEY; 25980Sstevel@tonic-gate CK_ULONG ul_key_attr_count = 6; 25990Sstevel@tonic-gate 26000Sstevel@tonic-gate CK_ATTRIBUTE a_key_template[] = 26010Sstevel@tonic-gate { 2602*7616SVladimir.Kotal@Sun.COM {CKA_CLASS, (void*) NULL, sizeof (CK_OBJECT_CLASS)}, 2603*7616SVladimir.Kotal@Sun.COM {CKA_KEY_TYPE, (void*) NULL, sizeof (CK_KEY_TYPE)}, 2604*7616SVladimir.Kotal@Sun.COM {CKA_TOKEN, &false, sizeof (false)}, 2605*7616SVladimir.Kotal@Sun.COM {CKA_ENCRYPT, &true, sizeof (true)}, 2606*7616SVladimir.Kotal@Sun.COM {CKA_DECRYPT, &true, sizeof (true)}, 26070Sstevel@tonic-gate {CKA_VALUE, (void*) NULL, 0}, 26080Sstevel@tonic-gate }; 26090Sstevel@tonic-gate 2610*7616SVladimir.Kotal@Sun.COM /* 2611*7616SVladimir.Kotal@Sun.COM * Create secret key object in global_session. All other sessions 26120Sstevel@tonic-gate * can use the key handles. Here is why: 26130Sstevel@tonic-gate * OpenSSL will call EncryptInit and EncryptUpdate using a secret key. 26140Sstevel@tonic-gate * It may then call DecryptInit and DecryptUpdate using the same key. 26150Sstevel@tonic-gate * To use the same key object, we need to call EncryptFinal with 2616*7616SVladimir.Kotal@Sun.COM * a 0 length message. Currently, this does not work for 3DES 26170Sstevel@tonic-gate * mechanism. To get around this problem, we close the session and 26180Sstevel@tonic-gate * then create a new session to use the same key object. When a session 2619*7616SVladimir.Kotal@Sun.COM * is closed, all the object handles will be invalid. Thus, create key 26200Sstevel@tonic-gate * objects in a global session, an individual session may be closed to 26210Sstevel@tonic-gate * terminate the active operation. 26220Sstevel@tonic-gate */ 26230Sstevel@tonic-gate CK_SESSION_HANDLE session = global_session; 26240Sstevel@tonic-gate a_key_template[0].pValue = &obj_key; 26250Sstevel@tonic-gate a_key_template[1].pValue = &key_type; 26260Sstevel@tonic-gate a_key_template[5].pValue = (void *) key; 26270Sstevel@tonic-gate a_key_template[5].ulValueLen = (unsigned long) ctx->key_len; 26280Sstevel@tonic-gate 2629*7616SVladimir.Kotal@Sun.COM rv = pFuncList->C_CreateObject(session, 26304602Sjp161948 a_key_template, ul_key_attr_count, &h_key); 26310Sstevel@tonic-gate if (rv != CKR_OK) 26320Sstevel@tonic-gate { 26337211Sjp161948 PK11err_add_data(PK11_F_GET_CIPHER_KEY, PK11_R_CREATEOBJECT, 26347211Sjp161948 rv); 26350Sstevel@tonic-gate goto err; 26360Sstevel@tonic-gate } 26370Sstevel@tonic-gate 2638*7616SVladimir.Kotal@Sun.COM /* 2639*7616SVladimir.Kotal@Sun.COM * Save the key information used in this session. 26400Sstevel@tonic-gate * The max can be saved is PK11_KEY_LEN_MAX. 26410Sstevel@tonic-gate */ 26427526SVladimir.Kotal@Sun.COM sp->opdata_key_len = ctx->key_len > PK11_KEY_LEN_MAX ? 26430Sstevel@tonic-gate PK11_KEY_LEN_MAX : ctx->key_len; 26447534SVladimir.Kotal@Sun.COM (void) memcpy(sp->opdata_key, key, sp->opdata_key_len); 26450Sstevel@tonic-gate err: 26460Sstevel@tonic-gate 2647*7616SVladimir.Kotal@Sun.COM return (h_key); 26480Sstevel@tonic-gate } 26490Sstevel@tonic-gate 26500Sstevel@tonic-gate static int 26510Sstevel@tonic-gate md_nid_to_pk11(int nid) 26520Sstevel@tonic-gate { 26530Sstevel@tonic-gate int i; 26540Sstevel@tonic-gate 26550Sstevel@tonic-gate for (i = 0; i < PK11_DIGEST_MAX; i++) 26560Sstevel@tonic-gate if (digests[i].nid == nid) 26570Sstevel@tonic-gate return (digests[i].id); 26580Sstevel@tonic-gate return (-1); 26590Sstevel@tonic-gate } 26600Sstevel@tonic-gate 2661*7616SVladimir.Kotal@Sun.COM static int 26620Sstevel@tonic-gate pk11_digest_init(EVP_MD_CTX *ctx) 2663*7616SVladimir.Kotal@Sun.COM { 26640Sstevel@tonic-gate CK_RV rv; 26654320Sjp161948 CK_MECHANISM mech; 26660Sstevel@tonic-gate int index; 26670Sstevel@tonic-gate PK11_SESSION *sp; 26680Sstevel@tonic-gate PK11_DIGEST *pdp; 26690Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; 2670*7616SVladimir.Kotal@Sun.COM 26710Sstevel@tonic-gate state->sp = NULL; 26720Sstevel@tonic-gate 26730Sstevel@tonic-gate index = md_nid_to_pk11(ctx->digest->type); 26740Sstevel@tonic-gate if (index < 0 || index >= PK11_DIGEST_MAX) 2675*7616SVladimir.Kotal@Sun.COM return (0); 26760Sstevel@tonic-gate 26770Sstevel@tonic-gate pdp = &digests[index]; 26787211Sjp161948 if ((sp = pk11_get_session(OP_DIGEST)) == NULL) 2679*7616SVladimir.Kotal@Sun.COM return (0); 26800Sstevel@tonic-gate 26814320Sjp161948 /* at present, no parameter is needed for supported digests */ 26824320Sjp161948 mech.mechanism = pdp->mech_type; 26834320Sjp161948 mech.pParameter = NULL; 26844320Sjp161948 mech.ulParameterLen = 0; 26854320Sjp161948 26864320Sjp161948 rv = pFuncList->C_DigestInit(sp->session, &mech); 26870Sstevel@tonic-gate 26880Sstevel@tonic-gate if (rv != CKR_OK) 26890Sstevel@tonic-gate { 26907211Sjp161948 PK11err_add_data(PK11_F_DIGEST_INIT, PK11_R_DIGESTINIT, rv); 26917211Sjp161948 pk11_return_session(sp, OP_DIGEST); 2692*7616SVladimir.Kotal@Sun.COM return (0); 26930Sstevel@tonic-gate } 26940Sstevel@tonic-gate 26950Sstevel@tonic-gate state->sp = sp; 26960Sstevel@tonic-gate 2697*7616SVladimir.Kotal@Sun.COM return (1); 26980Sstevel@tonic-gate } 26990Sstevel@tonic-gate 2700*7616SVladimir.Kotal@Sun.COM static int 2701*7616SVladimir.Kotal@Sun.COM pk11_digest_update(EVP_MD_CTX *ctx, const void *data, size_t count) 2702*7616SVladimir.Kotal@Sun.COM { 27030Sstevel@tonic-gate CK_RV rv; 27040Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; 2705*7616SVladimir.Kotal@Sun.COM 27060Sstevel@tonic-gate /* 0 length message will cause a failure in C_DigestFinal */ 27070Sstevel@tonic-gate if (count == 0) 2708*7616SVladimir.Kotal@Sun.COM return (1); 27090Sstevel@tonic-gate 27100Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 2711*7616SVladimir.Kotal@Sun.COM return (0); 27120Sstevel@tonic-gate 27130Sstevel@tonic-gate rv = pFuncList->C_DigestUpdate(state->sp->session, (CK_BYTE *) data, 27140Sstevel@tonic-gate count); 27150Sstevel@tonic-gate 27160Sstevel@tonic-gate if (rv != CKR_OK) 27170Sstevel@tonic-gate { 27187211Sjp161948 PK11err_add_data(PK11_F_DIGEST_UPDATE, PK11_R_DIGESTUPDATE, rv); 27197211Sjp161948 pk11_return_session(state->sp, OP_DIGEST); 27200Sstevel@tonic-gate state->sp = NULL; 2721*7616SVladimir.Kotal@Sun.COM return (0); 27220Sstevel@tonic-gate } 27230Sstevel@tonic-gate 2724*7616SVladimir.Kotal@Sun.COM return (1); 27250Sstevel@tonic-gate } 27260Sstevel@tonic-gate 2727*7616SVladimir.Kotal@Sun.COM static int 2728*7616SVladimir.Kotal@Sun.COM pk11_digest_final(EVP_MD_CTX *ctx, unsigned char *md) 2729*7616SVladimir.Kotal@Sun.COM { 27300Sstevel@tonic-gate CK_RV rv; 27310Sstevel@tonic-gate unsigned long len; 27320Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; 27330Sstevel@tonic-gate len = ctx->digest->md_size; 2734*7616SVladimir.Kotal@Sun.COM 27350Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 2736*7616SVladimir.Kotal@Sun.COM return (0); 27370Sstevel@tonic-gate 27380Sstevel@tonic-gate rv = pFuncList->C_DigestFinal(state->sp->session, md, &len); 27390Sstevel@tonic-gate 27400Sstevel@tonic-gate if (rv != CKR_OK) 27410Sstevel@tonic-gate { 27427211Sjp161948 PK11err_add_data(PK11_F_DIGEST_FINAL, PK11_R_DIGESTFINAL, rv); 27437211Sjp161948 pk11_return_session(state->sp, OP_DIGEST); 27440Sstevel@tonic-gate state->sp = NULL; 2745*7616SVladimir.Kotal@Sun.COM return (0); 27460Sstevel@tonic-gate } 27470Sstevel@tonic-gate 27480Sstevel@tonic-gate if (ctx->digest->md_size != len) 2749*7616SVladimir.Kotal@Sun.COM return (0); 2750*7616SVladimir.Kotal@Sun.COM 2751*7616SVladimir.Kotal@Sun.COM /* 2752*7616SVladimir.Kotal@Sun.COM * Final is called and digest is returned, so return the session 27530Sstevel@tonic-gate * to the pool 27540Sstevel@tonic-gate */ 27557211Sjp161948 pk11_return_session(state->sp, OP_DIGEST); 27560Sstevel@tonic-gate state->sp = NULL; 27570Sstevel@tonic-gate 2758*7616SVladimir.Kotal@Sun.COM return (1); 27590Sstevel@tonic-gate } 27600Sstevel@tonic-gate 2761*7616SVladimir.Kotal@Sun.COM static int 2762*7616SVladimir.Kotal@Sun.COM pk11_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) 2763*7616SVladimir.Kotal@Sun.COM { 27640Sstevel@tonic-gate CK_RV rv; 27650Sstevel@tonic-gate int ret = 0; 27660Sstevel@tonic-gate PK11_CIPHER_STATE *state, *state_to; 27670Sstevel@tonic-gate CK_BYTE_PTR pstate = NULL; 27680Sstevel@tonic-gate CK_ULONG ul_state_len; 2769*7616SVladimir.Kotal@Sun.COM 27700Sstevel@tonic-gate /* The copy-from state */ 27710Sstevel@tonic-gate state = (PK11_CIPHER_STATE *) from->md_data; 27720Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 27730Sstevel@tonic-gate goto err; 27740Sstevel@tonic-gate 27750Sstevel@tonic-gate /* Initialize the copy-to state */ 27760Sstevel@tonic-gate if (!pk11_digest_init(to)) 27770Sstevel@tonic-gate goto err; 27780Sstevel@tonic-gate state_to = (PK11_CIPHER_STATE *) to->md_data; 27790Sstevel@tonic-gate 27800Sstevel@tonic-gate /* Get the size of the operation state of the copy-from session */ 2781*7616SVladimir.Kotal@Sun.COM rv = pFuncList->C_GetOperationState(state->sp->session, NULL, 27820Sstevel@tonic-gate &ul_state_len); 27830Sstevel@tonic-gate 27840Sstevel@tonic-gate if (rv != CKR_OK) 27850Sstevel@tonic-gate { 27867211Sjp161948 PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE, 27877211Sjp161948 rv); 27880Sstevel@tonic-gate goto err; 27890Sstevel@tonic-gate } 27900Sstevel@tonic-gate if (ul_state_len == 0) 27910Sstevel@tonic-gate { 27920Sstevel@tonic-gate goto err; 27930Sstevel@tonic-gate } 27940Sstevel@tonic-gate 27950Sstevel@tonic-gate pstate = OPENSSL_malloc(ul_state_len); 27960Sstevel@tonic-gate if (pstate == NULL) 27970Sstevel@tonic-gate { 27986847Svk199839 PK11err(PK11_F_DIGEST_COPY, PK11_R_MALLOC_FAILURE); 27990Sstevel@tonic-gate goto err; 28000Sstevel@tonic-gate } 28010Sstevel@tonic-gate 28020Sstevel@tonic-gate /* Get the operation state of the copy-from session */ 2803*7616SVladimir.Kotal@Sun.COM rv = pFuncList->C_GetOperationState(state->sp->session, pstate, 28040Sstevel@tonic-gate &ul_state_len); 28050Sstevel@tonic-gate 28060Sstevel@tonic-gate if (rv != CKR_OK) 28070Sstevel@tonic-gate { 28087211Sjp161948 PK11err_add_data(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE, 28097211Sjp161948 rv); 28100Sstevel@tonic-gate goto err; 28110Sstevel@tonic-gate } 28120Sstevel@tonic-gate 28130Sstevel@tonic-gate /* Set the operation state of the copy-to session */ 2814*7616SVladimir.Kotal@Sun.COM rv = pFuncList->C_SetOperationState(state_to->sp->session, pstate, 28150Sstevel@tonic-gate ul_state_len, 0, 0); 28160Sstevel@tonic-gate 28170Sstevel@tonic-gate if (rv != CKR_OK) 28180Sstevel@tonic-gate { 2819*7616SVladimir.Kotal@Sun.COM PK11err_add_data(PK11_F_DIGEST_COPY, 2820*7616SVladimir.Kotal@Sun.COM PK11_R_SET_OPERATION_STATE, rv); 28210Sstevel@tonic-gate goto err; 28220Sstevel@tonic-gate } 28230Sstevel@tonic-gate 28240Sstevel@tonic-gate ret = 1; 28250Sstevel@tonic-gate err: 28260Sstevel@tonic-gate if (pstate != NULL) 28270Sstevel@tonic-gate OPENSSL_free(pstate); 28280Sstevel@tonic-gate 2829*7616SVladimir.Kotal@Sun.COM return (ret); 28300Sstevel@tonic-gate } 28310Sstevel@tonic-gate 28320Sstevel@tonic-gate /* Return any pending session state to the pool */ 28330Sstevel@tonic-gate static int 28340Sstevel@tonic-gate pk11_digest_cleanup(EVP_MD_CTX *ctx) 28350Sstevel@tonic-gate { 28360Sstevel@tonic-gate PK11_CIPHER_STATE *state = ctx->md_data; 28374602Sjp161948 unsigned char buf[EVP_MAX_MD_SIZE]; 28380Sstevel@tonic-gate 28390Sstevel@tonic-gate if (state != NULL && state->sp != NULL) 28400Sstevel@tonic-gate { 28414602Sjp161948 /* 28424602Sjp161948 * If state->sp is not NULL then pk11_digest_final() has not 28434602Sjp161948 * been called yet. We must call it now to free any memory 28444602Sjp161948 * that might have been allocated in the token when 28454602Sjp161948 * pk11_digest_init() was called. 28464602Sjp161948 */ 28477526SVladimir.Kotal@Sun.COM (void) pk11_digest_final(ctx, buf); 28487211Sjp161948 pk11_return_session(state->sp, OP_DIGEST); 28490Sstevel@tonic-gate state->sp = NULL; 28500Sstevel@tonic-gate } 28510Sstevel@tonic-gate 2852*7616SVladimir.Kotal@Sun.COM return (1); 28530Sstevel@tonic-gate } 28540Sstevel@tonic-gate 28556847Svk199839 /* 28567211Sjp161948 * Check if the new key is the same as the key object in the session. If the key 28577211Sjp161948 * is the same, no need to create a new key object. Otherwise, the old key 28587211Sjp161948 * object needs to be destroyed and a new one will be created. Return 1 for 28597211Sjp161948 * cache hit, 0 for cache miss. Note that we must check the key length first 28607211Sjp161948 * otherwise we could end up reusing a different, longer key with the same 28617211Sjp161948 * prefix. 28620Sstevel@tonic-gate */ 28637211Sjp161948 static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key, 28647211Sjp161948 int key_len) 28650Sstevel@tonic-gate { 28667526SVladimir.Kotal@Sun.COM if (sp->opdata_key_len != key_len || 28677526SVladimir.Kotal@Sun.COM memcmp(sp->opdata_key, key, key_len) != 0) 28686847Svk199839 { 28697211Sjp161948 (void) pk11_destroy_cipher_key_objects(sp); 28706847Svk199839 return (0); 28716847Svk199839 } 28726847Svk199839 return (1); 28730Sstevel@tonic-gate } 28740Sstevel@tonic-gate 2875*7616SVladimir.Kotal@Sun.COM /* Destroy one or more secret key objects. */ 28760Sstevel@tonic-gate static int pk11_destroy_cipher_key_objects(PK11_SESSION *session) 28770Sstevel@tonic-gate { 28780Sstevel@tonic-gate int ret = 0; 28790Sstevel@tonic-gate PK11_SESSION *sp = NULL; 28800Sstevel@tonic-gate PK11_SESSION *local_free_session; 28810Sstevel@tonic-gate 28827526SVladimir.Kotal@Sun.COM if (session != NULL) 28830Sstevel@tonic-gate local_free_session = session; 28840Sstevel@tonic-gate else 28857526SVladimir.Kotal@Sun.COM { 28867526SVladimir.Kotal@Sun.COM (void) pthread_mutex_lock(session_cache[OP_CIPHER].lock); 28877526SVladimir.Kotal@Sun.COM local_free_session = session_cache[OP_CIPHER].head; 28887526SVladimir.Kotal@Sun.COM } 28897526SVladimir.Kotal@Sun.COM 28900Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 28910Sstevel@tonic-gate { 28920Sstevel@tonic-gate local_free_session = sp->next; 28930Sstevel@tonic-gate 28947526SVladimir.Kotal@Sun.COM if (sp->opdata_cipher_key != CK_INVALID_HANDLE) 28950Sstevel@tonic-gate { 2896*7616SVladimir.Kotal@Sun.COM /* 2897*7616SVladimir.Kotal@Sun.COM * The secret key object is created in the 28980Sstevel@tonic-gate * global_session. See pk11_get_cipher_key 28990Sstevel@tonic-gate */ 2900*7616SVladimir.Kotal@Sun.COM if (pk11_destroy_object(global_session, 29017526SVladimir.Kotal@Sun.COM sp->opdata_cipher_key) == 0) 29020Sstevel@tonic-gate goto err; 29037526SVladimir.Kotal@Sun.COM sp->opdata_cipher_key = CK_INVALID_HANDLE; 29040Sstevel@tonic-gate } 29050Sstevel@tonic-gate } 29060Sstevel@tonic-gate ret = 1; 29070Sstevel@tonic-gate err: 29087526SVladimir.Kotal@Sun.COM 29097526SVladimir.Kotal@Sun.COM if (session == NULL) 29107526SVladimir.Kotal@Sun.COM (void) pthread_mutex_unlock(session_cache[OP_CIPHER].lock); 29110Sstevel@tonic-gate 2912*7616SVladimir.Kotal@Sun.COM return (ret); 29130Sstevel@tonic-gate } 29140Sstevel@tonic-gate 29150Sstevel@tonic-gate 29160Sstevel@tonic-gate /* 29177211Sjp161948 * Public key mechanisms optionally supported 29180Sstevel@tonic-gate * 29190Sstevel@tonic-gate * CKM_RSA_X_509 29200Sstevel@tonic-gate * CKM_RSA_PKCS 29210Sstevel@tonic-gate * CKM_DSA 29220Sstevel@tonic-gate * 29237211Sjp161948 * The first slot that supports at least one of those mechanisms is chosen as a 29247211Sjp161948 * public key slot. 29250Sstevel@tonic-gate * 29260Sstevel@tonic-gate * Symmetric ciphers optionally supported 29270Sstevel@tonic-gate * 29280Sstevel@tonic-gate * CKM_DES3_CBC 29290Sstevel@tonic-gate * CKM_DES_CBC 29300Sstevel@tonic-gate * CKM_AES_CBC 29317211Sjp161948 * CKM_DES3_ECB 29327211Sjp161948 * CKM_DES_ECB 29337211Sjp161948 * CKM_AES_ECB 29347211Sjp161948 * CKM_AES_CTR 29350Sstevel@tonic-gate * CKM_RC4 29367211Sjp161948 * CKM_BLOWFISH_CBC 29370Sstevel@tonic-gate * 29380Sstevel@tonic-gate * Digests optionally supported 29390Sstevel@tonic-gate * 29400Sstevel@tonic-gate * CKM_MD5 29410Sstevel@tonic-gate * CKM_SHA_1 29427211Sjp161948 * CKM_SHA224 29437211Sjp161948 * CKM_SHA256 29447211Sjp161948 * CKM_SHA384 29457211Sjp161948 * CKM_SHA512 29467211Sjp161948 * 29477211Sjp161948 * The output of this function is a set of global variables indicating which 29487211Sjp161948 * mechanisms from RSA, DSA, DH and RAND are present, and also two arrays of 29497211Sjp161948 * mechanisms, one for symmetric ciphers and one for digests. Also, 3 global 29507211Sjp161948 * variables carry information about which slot was chosen for (a) public key 29517211Sjp161948 * mechanisms, (b) random operations, and (c) symmetric ciphers and digests. 29520Sstevel@tonic-gate */ 2953*7616SVladimir.Kotal@Sun.COM static int 29547211Sjp161948 pk11_choose_slots(int *any_slot_found) 29550Sstevel@tonic-gate { 29560Sstevel@tonic-gate CK_SLOT_ID_PTR pSlotList = NULL_PTR; 29570Sstevel@tonic-gate CK_ULONG ulSlotCount = 0; 29580Sstevel@tonic-gate CK_MECHANISM_INFO mech_info; 29590Sstevel@tonic-gate CK_TOKEN_INFO token_info; 29600Sstevel@tonic-gate int i; 29610Sstevel@tonic-gate CK_RV rv; 29620Sstevel@tonic-gate CK_SLOT_ID best_slot_sofar; 29630Sstevel@tonic-gate CK_BBOOL found_candidate_slot = CK_FALSE; 29640Sstevel@tonic-gate int slot_n_cipher = 0; 29650Sstevel@tonic-gate int slot_n_digest = 0; 29660Sstevel@tonic-gate CK_SLOT_ID current_slot = 0; 29670Sstevel@tonic-gate int current_slot_n_cipher = 0; 29680Sstevel@tonic-gate int current_slot_n_digest = 0; 29690Sstevel@tonic-gate 29700Sstevel@tonic-gate int local_cipher_nids[PK11_CIPHER_MAX]; 29710Sstevel@tonic-gate int local_digest_nids[PK11_DIGEST_MAX]; 29727211Sjp161948 29737211Sjp161948 /* let's initialize the output parameter */ 29747211Sjp161948 if (any_slot_found != NULL) 29757211Sjp161948 *any_slot_found = 0; 29767211Sjp161948 29777211Sjp161948 /* Get slot list for memory allocation */ 29780Sstevel@tonic-gate rv = pFuncList->C_GetSlotList(0, NULL_PTR, &ulSlotCount); 29790Sstevel@tonic-gate 29800Sstevel@tonic-gate if (rv != CKR_OK) 29810Sstevel@tonic-gate { 29827211Sjp161948 PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); 2983*7616SVladimir.Kotal@Sun.COM return (0); 29840Sstevel@tonic-gate } 29850Sstevel@tonic-gate 29867211Sjp161948 /* it's not an error if we didn't find any providers */ 2987*7616SVladimir.Kotal@Sun.COM if (ulSlotCount == 0) 29880Sstevel@tonic-gate { 29897211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 29907211Sjp161948 fprintf(stderr, "%s: no crypto providers found\n", PK11_DBG); 29917211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 2992*7616SVladimir.Kotal@Sun.COM return (1); 29930Sstevel@tonic-gate } 29940Sstevel@tonic-gate 29950Sstevel@tonic-gate pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); 29960Sstevel@tonic-gate 2997*7616SVladimir.Kotal@Sun.COM if (pSlotList == NULL) 29980Sstevel@tonic-gate { 29996847Svk199839 PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE); 3000*7616SVladimir.Kotal@Sun.COM return (0); 30010Sstevel@tonic-gate } 30020Sstevel@tonic-gate 30030Sstevel@tonic-gate /* Get the slot list for processing */ 30040Sstevel@tonic-gate rv = pFuncList->C_GetSlotList(0, pSlotList, &ulSlotCount); 3005*7616SVladimir.Kotal@Sun.COM if (rv != CKR_OK) 30060Sstevel@tonic-gate { 30077211Sjp161948 PK11err_add_data(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST, rv); 30080Sstevel@tonic-gate OPENSSL_free(pSlotList); 3009*7616SVladimir.Kotal@Sun.COM return (0); 30100Sstevel@tonic-gate } 30110Sstevel@tonic-gate 30127211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 30137211Sjp161948 fprintf(stderr, "%s: provider: %s\n", PK11_DBG, def_PK11_LIBNAME); 30147211Sjp161948 fprintf(stderr, "%s: number of slots: %d\n", PK11_DBG, ulSlotCount); 30157211Sjp161948 30167211Sjp161948 fprintf(stderr, "%s: == checking rand slots ==\n", PK11_DBG); 30177211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 3018*7616SVladimir.Kotal@Sun.COM for (i = 0; i < ulSlotCount; i++) 30197211Sjp161948 { 30207211Sjp161948 current_slot = pSlotList[i]; 30217211Sjp161948 30227211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 30237211Sjp161948 fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); 30247211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 30257211Sjp161948 /* Check if slot has random support. */ 30267211Sjp161948 rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); 30277211Sjp161948 if (rv != CKR_OK) 30287211Sjp161948 continue; 30297211Sjp161948 30307211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 30317211Sjp161948 fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); 30327211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 30337211Sjp161948 30347211Sjp161948 if (token_info.flags & CKF_RNG) 30357211Sjp161948 { 30367211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 30377211Sjp161948 fprintf(stderr, "%s: this token has CKF_RNG flag\n", PK11_DBG); 30387211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 30397211Sjp161948 pk11_have_random = CK_TRUE; 30407211Sjp161948 break; 30417211Sjp161948 } 30427211Sjp161948 } 30437211Sjp161948 30447211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 30457211Sjp161948 fprintf(stderr, "%s: == checking pubkey slots ==\n", PK11_DBG); 30467211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 3047*7616SVladimir.Kotal@Sun.COM for (i = 0; i < ulSlotCount; i++) 30480Sstevel@tonic-gate { 30490Sstevel@tonic-gate CK_BBOOL slot_has_rsa = CK_FALSE; 30500Sstevel@tonic-gate CK_BBOOL slot_has_dsa = CK_FALSE; 30510Sstevel@tonic-gate CK_BBOOL slot_has_dh = CK_FALSE; 30520Sstevel@tonic-gate current_slot = pSlotList[i]; 30537211Sjp161948 30547211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 30557211Sjp161948 fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); 30567211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 30570Sstevel@tonic-gate rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); 30580Sstevel@tonic-gate if (rv != CKR_OK) 30590Sstevel@tonic-gate continue; 30600Sstevel@tonic-gate 30617211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 30627211Sjp161948 fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); 30637211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 30647211Sjp161948 30656847Svk199839 #ifndef OPENSSL_NO_RSA 30660Sstevel@tonic-gate /* 30670Sstevel@tonic-gate * Check if this slot is capable of signing and 30680Sstevel@tonic-gate * verifying with CKM_RSA_PKCS. 30690Sstevel@tonic-gate */ 3070*7616SVladimir.Kotal@Sun.COM rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS, 30710Sstevel@tonic-gate &mech_info); 30720Sstevel@tonic-gate 30730Sstevel@tonic-gate if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && 30740Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY))) 30750Sstevel@tonic-gate { 30760Sstevel@tonic-gate /* 30770Sstevel@tonic-gate * Check if this slot is capable of encryption, 30780Sstevel@tonic-gate * decryption, sign, and verify with CKM_RSA_X_509. 30790Sstevel@tonic-gate */ 30800Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, 3081*7616SVladimir.Kotal@Sun.COM CKM_RSA_X_509, &mech_info); 30820Sstevel@tonic-gate 30830Sstevel@tonic-gate if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && 30840Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY) && 30850Sstevel@tonic-gate (mech_info.flags & CKF_ENCRYPT) && 30860Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY_RECOVER) && 30870Sstevel@tonic-gate (mech_info.flags & CKF_DECRYPT))) 30887211Sjp161948 { 30890Sstevel@tonic-gate slot_has_rsa = CK_TRUE; 30907211Sjp161948 } 30910Sstevel@tonic-gate } 30927211Sjp161948 #endif /* OPENSSL_NO_RSA */ 30937211Sjp161948 30946847Svk199839 #ifndef OPENSSL_NO_DSA 30950Sstevel@tonic-gate /* 30960Sstevel@tonic-gate * Check if this slot is capable of signing and 30970Sstevel@tonic-gate * verifying with CKM_DSA. 30980Sstevel@tonic-gate */ 3099*7616SVladimir.Kotal@Sun.COM rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA, 31000Sstevel@tonic-gate &mech_info); 31010Sstevel@tonic-gate if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && 31020Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY))) 31037211Sjp161948 { 31040Sstevel@tonic-gate slot_has_dsa = CK_TRUE; 31057211Sjp161948 } 31067526SVladimir.Kotal@Sun.COM 31077211Sjp161948 #endif /* OPENSSL_NO_DSA */ 31087211Sjp161948 31096847Svk199839 #ifndef OPENSSL_NO_DH 31100Sstevel@tonic-gate /* 31110Sstevel@tonic-gate * Check if this slot is capable of DH key generataion and 31120Sstevel@tonic-gate * derivation. 31130Sstevel@tonic-gate */ 31140Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, 3115*7616SVladimir.Kotal@Sun.COM CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info); 31160Sstevel@tonic-gate 31170Sstevel@tonic-gate if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR)) 3118*7616SVladimir.Kotal@Sun.COM { 31190Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, 31200Sstevel@tonic-gate CKM_DH_PKCS_DERIVE, &mech_info); 31210Sstevel@tonic-gate if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE)) 31227211Sjp161948 { 31230Sstevel@tonic-gate slot_has_dh = CK_TRUE; 31247211Sjp161948 } 31250Sstevel@tonic-gate } 31267211Sjp161948 #endif /* OPENSSL_NO_DH */ 31277211Sjp161948 31280Sstevel@tonic-gate if (!found_candidate_slot && 31290Sstevel@tonic-gate (slot_has_rsa || slot_has_dsa || slot_has_dh)) 31300Sstevel@tonic-gate { 31317211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 31320Sstevel@tonic-gate fprintf(stderr, 3133*7616SVladimir.Kotal@Sun.COM "%s: potential slot: %d\n", PK11_DBG, current_slot); 31347211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 31350Sstevel@tonic-gate best_slot_sofar = current_slot; 31360Sstevel@tonic-gate pk11_have_rsa = slot_has_rsa; 31370Sstevel@tonic-gate pk11_have_dsa = slot_has_dsa; 31380Sstevel@tonic-gate pk11_have_dh = slot_has_dh; 31390Sstevel@tonic-gate found_candidate_slot = CK_TRUE; 31407211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 31417211Sjp161948 fprintf(stderr, 3142*7616SVladimir.Kotal@Sun.COM "%s: setting found_candidate_slot to CK_TRUE\n", 31437211Sjp161948 PK11_DBG); 31440Sstevel@tonic-gate fprintf(stderr, 3145*7616SVladimir.Kotal@Sun.COM "%s: best so far slot: %d\n", PK11_DBG, 3146*7616SVladimir.Kotal@Sun.COM best_slot_sofar); 31477211Sjp161948 } 31487211Sjp161948 else 31497211Sjp161948 { 31507211Sjp161948 fprintf(stderr, 3151*7616SVladimir.Kotal@Sun.COM "%s: no rsa/dsa/dh\n", PK11_DBG); 31520Sstevel@tonic-gate } 31537211Sjp161948 #else 31547211Sjp161948 } /* if */ 31557211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 31567211Sjp161948 } /* for */ 31577211Sjp161948 31587211Sjp161948 if (found_candidate_slot) 31597211Sjp161948 { 31607211Sjp161948 pubkey_SLOTID = best_slot_sofar; 31617211Sjp161948 } 31627211Sjp161948 31637211Sjp161948 found_candidate_slot = CK_FALSE; 31647211Sjp161948 best_slot_sofar = 0; 31657211Sjp161948 31667211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 31677211Sjp161948 fprintf(stderr, "%s: == checking cipher/digest ==\n", PK11_DBG); 31687211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 3169*7616SVladimir.Kotal@Sun.COM for (i = 0; i < ulSlotCount; i++) 31707211Sjp161948 { 31717211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 31727211Sjp161948 fprintf(stderr, "%s: checking slot: %d\n", PK11_DBG, i); 31737211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 31747211Sjp161948 31757211Sjp161948 current_slot = pSlotList[i]; 31767211Sjp161948 current_slot_n_cipher = 0; 31777211Sjp161948 current_slot_n_digest = 0; 3178*7616SVladimir.Kotal@Sun.COM (void) memset(local_cipher_nids, 0, sizeof (local_cipher_nids)); 3179*7616SVladimir.Kotal@Sun.COM (void) memset(local_digest_nids, 0, sizeof (local_digest_nids)); 31807211Sjp161948 31817211Sjp161948 pk11_find_symmetric_ciphers(pFuncList, current_slot, 31827211Sjp161948 ¤t_slot_n_cipher, local_cipher_nids); 31837211Sjp161948 31847211Sjp161948 pk11_find_digests(pFuncList, current_slot, 31857211Sjp161948 ¤t_slot_n_digest, local_digest_nids); 31867211Sjp161948 31877211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 31887211Sjp161948 fprintf(stderr, "%s: current_slot_n_cipher %d\n", PK11_DBG, 31897211Sjp161948 current_slot_n_cipher); 31907211Sjp161948 fprintf(stderr, "%s: current_slot_n_digest %d\n", PK11_DBG, 31917211Sjp161948 current_slot_n_digest); 31927211Sjp161948 fprintf(stderr, "%s: best so far cipher/digest slot: %d\n", 31937211Sjp161948 PK11_DBG, best_slot_sofar); 31947211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 31950Sstevel@tonic-gate 31960Sstevel@tonic-gate /* 3197*7616SVladimir.Kotal@Sun.COM * If the current slot supports more ciphers/digests than 31987250Sjp161948 * the previous best one we change the current best to this one, 31990Sstevel@tonic-gate * otherwise leave it where it is. 32000Sstevel@tonic-gate */ 32017250Sjp161948 if ((current_slot_n_cipher + current_slot_n_digest) > 32027250Sjp161948 (slot_n_cipher + slot_n_digest)) 32030Sstevel@tonic-gate { 32047211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 32057211Sjp161948 fprintf(stderr, 32067211Sjp161948 "%s: changing best so far slot to %d\n", 32077211Sjp161948 PK11_DBG, current_slot); 32087211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 32097211Sjp161948 best_slot_sofar = SLOTID = current_slot; 32107250Sjp161948 cipher_count = slot_n_cipher = current_slot_n_cipher; 32117250Sjp161948 digest_count = slot_n_digest = current_slot_n_digest; 32127534SVladimir.Kotal@Sun.COM (void) memcpy(cipher_nids, local_cipher_nids, 32137526SVladimir.Kotal@Sun.COM sizeof (local_cipher_nids)); 32147534SVladimir.Kotal@Sun.COM (void) memcpy(digest_nids, local_digest_nids, 32157526SVladimir.Kotal@Sun.COM sizeof (local_digest_nids)); 32160Sstevel@tonic-gate } 32170Sstevel@tonic-gate } 32180Sstevel@tonic-gate 32197211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 32207211Sjp161948 fprintf(stderr, 32217526SVladimir.Kotal@Sun.COM "%s: chosen pubkey slot: %d\n", PK11_DBG, pubkey_SLOTID); 32220Sstevel@tonic-gate fprintf(stderr, 32237526SVladimir.Kotal@Sun.COM "%s: chosen rand slot: %d\n", PK11_DBG, rand_SLOTID); 32240Sstevel@tonic-gate fprintf(stderr, 32257526SVladimir.Kotal@Sun.COM "%s: chosen cipher/digest slot: %d\n", PK11_DBG, SLOTID); 32267211Sjp161948 fprintf(stderr, 32277526SVladimir.Kotal@Sun.COM "%s: pk11_have_rsa %d\n", PK11_DBG, pk11_have_rsa); 32280Sstevel@tonic-gate fprintf(stderr, 32297526SVladimir.Kotal@Sun.COM "%s: pk11_have_dsa %d\n", PK11_DBG, pk11_have_dsa); 32307211Sjp161948 fprintf(stderr, 32317526SVladimir.Kotal@Sun.COM "%s: pk11_have_dh %d\n", PK11_DBG, pk11_have_dh); 32320Sstevel@tonic-gate fprintf(stderr, 32337526SVladimir.Kotal@Sun.COM "%s: pk11_have_random %d\n", PK11_DBG, pk11_have_random); 32340Sstevel@tonic-gate fprintf(stderr, 32357526SVladimir.Kotal@Sun.COM "%s: cipher_count %d\n", PK11_DBG, cipher_count); 32367211Sjp161948 fprintf(stderr, 32377526SVladimir.Kotal@Sun.COM "%s: digest_count %d\n", PK11_DBG, digest_count); 32387211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 3239*7616SVladimir.Kotal@Sun.COM 32406847Svk199839 if (pSlotList != NULL) 32416847Svk199839 OPENSSL_free(pSlotList); 32420Sstevel@tonic-gate 32437211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 32447211Sjp161948 OPENSSL_free(hw_cnids); 32457211Sjp161948 OPENSSL_free(hw_dnids); 32467211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 32477211Sjp161948 32487211Sjp161948 if (any_slot_found != NULL) 32497211Sjp161948 *any_slot_found = 1; 3250*7616SVladimir.Kotal@Sun.COM return (1); 32510Sstevel@tonic-gate } 32520Sstevel@tonic-gate 32537211Sjp161948 static void pk11_get_symmetric_cipher(CK_FUNCTION_LIST_PTR pflist, 32547211Sjp161948 int slot_id, CK_MECHANISM_TYPE mech, int *current_slot_n_cipher, 32557211Sjp161948 int *local_cipher_nids, int id) 32567211Sjp161948 { 32577211Sjp161948 CK_MECHANISM_INFO mech_info; 32587211Sjp161948 CK_RV rv; 32597211Sjp161948 32607211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 32617211Sjp161948 fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech); 32627211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 32637211Sjp161948 rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info); 32647211Sjp161948 3265*7616SVladimir.Kotal@Sun.COM if (rv != CKR_OK) 32667211Sjp161948 { 32677211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 32687211Sjp161948 fprintf(stderr, " not found\n"); 32697211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 32707211Sjp161948 return; 32717211Sjp161948 } 32727211Sjp161948 32737211Sjp161948 if ((mech_info.flags & CKF_ENCRYPT) && 32747211Sjp161948 (mech_info.flags & CKF_DECRYPT)) 32757211Sjp161948 { 32767211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 32777211Sjp161948 if (nid_in_table(ciphers[id].nid, hw_cnids)) 32787211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 32797211Sjp161948 { 32807211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 32817211Sjp161948 fprintf(stderr, " usable\n"); 32827211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 32837211Sjp161948 local_cipher_nids[(*current_slot_n_cipher)++] = 32847211Sjp161948 ciphers[id].nid; 32857211Sjp161948 } 32867211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 32877211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 32887211Sjp161948 else 32897211Sjp161948 { 32907211Sjp161948 fprintf(stderr, " rejected, software implementation only\n"); 32917211Sjp161948 } 32927211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 32937211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 32947211Sjp161948 } 32957211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 32967211Sjp161948 else 32977211Sjp161948 { 32987211Sjp161948 fprintf(stderr, " unusable\n"); 32997211Sjp161948 } 33007211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 33017211Sjp161948 33027211Sjp161948 return; 33037211Sjp161948 } 33047211Sjp161948 33057211Sjp161948 static void pk11_get_digest(CK_FUNCTION_LIST_PTR pflist, int slot_id, 33067211Sjp161948 CK_MECHANISM_TYPE mech, int *current_slot_n_digest, int *local_digest_nids, 33077211Sjp161948 int id) 33080Sstevel@tonic-gate { 33090Sstevel@tonic-gate CK_MECHANISM_INFO mech_info; 33100Sstevel@tonic-gate CK_RV rv; 33110Sstevel@tonic-gate 33127211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 33137211Sjp161948 fprintf(stderr, "%s: checking mech: %x", PK11_DBG, mech); 33147211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 33157211Sjp161948 rv = pflist->C_GetMechanismInfo(slot_id, mech, &mech_info); 33160Sstevel@tonic-gate 3317*7616SVladimir.Kotal@Sun.COM if (rv != CKR_OK) 33180Sstevel@tonic-gate { 33197211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 33207211Sjp161948 fprintf(stderr, " not found\n"); 33217211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 33227211Sjp161948 return; 33230Sstevel@tonic-gate } 33240Sstevel@tonic-gate 33250Sstevel@tonic-gate if (mech_info.flags & CKF_DIGEST) 33260Sstevel@tonic-gate { 33277211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 3328*7616SVladimir.Kotal@Sun.COM if (nid_in_table(digests[id].nid, hw_dnids)) 33297211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 33307211Sjp161948 { 33317211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 33327211Sjp161948 fprintf(stderr, " usable\n"); 33337211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 33347211Sjp161948 local_digest_nids[(*current_slot_n_digest)++] = 33357211Sjp161948 digests[id].nid; 33367211Sjp161948 } 33377211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 33387211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 33397211Sjp161948 else 33407211Sjp161948 { 33417211Sjp161948 fprintf(stderr, " rejected, software implementation only\n"); 33427211Sjp161948 } 33437211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 33447211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 33457211Sjp161948 } 33467211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 33477211Sjp161948 else 33487211Sjp161948 { 33497211Sjp161948 fprintf(stderr, " unusable\n"); 33500Sstevel@tonic-gate } 33517211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 33527211Sjp161948 33537211Sjp161948 return; 33547211Sjp161948 } 33557211Sjp161948 33567211Sjp161948 #ifdef SOLARIS_AES_CTR 33577211Sjp161948 /* create a new NID when we have no OID for that mechanism */ 33587211Sjp161948 static int pk11_add_NID(char *sn, char *ln) 33597211Sjp161948 { 33607211Sjp161948 ASN1_OBJECT *o; 33617211Sjp161948 int nid; 33627211Sjp161948 33637211Sjp161948 if ((o = ASN1_OBJECT_create(OBJ_new_nid(1), (unsigned char *)"", 33647211Sjp161948 1, sn, ln)) == NULL) 33657211Sjp161948 { 3366*7616SVladimir.Kotal@Sun.COM return (0); 33677211Sjp161948 } 33687211Sjp161948 33697211Sjp161948 /* will return NID_undef on error */ 33707211Sjp161948 nid = OBJ_add_object(o); 33717211Sjp161948 ASN1_OBJECT_free(o); 33727211Sjp161948 33737211Sjp161948 return (nid); 33747211Sjp161948 } 33757211Sjp161948 33767211Sjp161948 /* 33777211Sjp161948 * Create new NIDs for AES counter mode. OpenSSL doesn't support them now so we 33787211Sjp161948 * have to help ourselves here. 33797211Sjp161948 */ 33807211Sjp161948 static int pk11_add_aes_ctr_NIDs(void) 33817211Sjp161948 { 33827211Sjp161948 /* are we already set? */ 33837211Sjp161948 if (NID_aes_256_ctr != NID_undef) 3384*7616SVladimir.Kotal@Sun.COM return (1); 33857211Sjp161948 33867211Sjp161948 /* 33877211Sjp161948 * There are no official names for AES counter modes yet so we just 33887211Sjp161948 * follow the format of those that exist. 33897211Sjp161948 */ 33907211Sjp161948 if ((NID_aes_128_ctr = pk11_add_NID("AES-128-CTR", "aes-128-ctr")) == 33917211Sjp161948 NID_undef) 33927211Sjp161948 goto err; 33937211Sjp161948 ciphers[PK11_AES_128_CTR].nid = pk11_aes_128_ctr.nid = NID_aes_128_ctr; 33947211Sjp161948 if ((NID_aes_192_ctr = pk11_add_NID("AES-192-CTR", "aes-192-ctr")) == 33957211Sjp161948 NID_undef) 33967211Sjp161948 goto err; 33977211Sjp161948 ciphers[PK11_AES_192_CTR].nid = pk11_aes_192_ctr.nid = NID_aes_192_ctr; 33987211Sjp161948 if ((NID_aes_256_ctr = pk11_add_NID("AES-256-CTR", "aes-256-ctr")) == 33997211Sjp161948 NID_undef) 34007211Sjp161948 goto err; 34017211Sjp161948 ciphers[PK11_AES_256_CTR].nid = pk11_aes_256_ctr.nid = NID_aes_256_ctr; 3402*7616SVladimir.Kotal@Sun.COM return (1); 34037211Sjp161948 34047211Sjp161948 err: 34057211Sjp161948 PK11err(PK11_F_ADD_AES_CTR_NIDS, PK11_R_ADD_NID_FAILED); 3406*7616SVladimir.Kotal@Sun.COM return (0); 34070Sstevel@tonic-gate } 34087211Sjp161948 #endif /* SOLARIS_AES_CTR */ 34097211Sjp161948 34107211Sjp161948 /* Find what symmetric ciphers this slot supports. */ 34117211Sjp161948 static void pk11_find_symmetric_ciphers(CK_FUNCTION_LIST_PTR pflist, 34127211Sjp161948 CK_SLOT_ID current_slot, int *current_slot_n_cipher, int *local_cipher_nids) 34137211Sjp161948 { 34147211Sjp161948 int i; 34157211Sjp161948 34167211Sjp161948 for (i = 0; i < PK11_CIPHER_MAX; ++i) 34177211Sjp161948 { 34187211Sjp161948 pk11_get_symmetric_cipher(pflist, current_slot, 34197211Sjp161948 ciphers[i].mech_type, current_slot_n_cipher, 34207211Sjp161948 local_cipher_nids, ciphers[i].id); 34217211Sjp161948 } 34227211Sjp161948 } 34237211Sjp161948 34247211Sjp161948 /* Find what digest algorithms this slot supports. */ 34257211Sjp161948 static void pk11_find_digests(CK_FUNCTION_LIST_PTR pflist, 34267211Sjp161948 CK_SLOT_ID current_slot, int *current_slot_n_digest, int *local_digest_nids) 34277211Sjp161948 { 34287211Sjp161948 int i; 34297211Sjp161948 34307211Sjp161948 for (i = 0; i < PK11_DIGEST_MAX; ++i) 34317211Sjp161948 { 34327211Sjp161948 pk11_get_digest(pflist, current_slot, digests[i].mech_type, 34337211Sjp161948 current_slot_n_digest, local_digest_nids, digests[i].id); 34347211Sjp161948 } 34357211Sjp161948 } 34367211Sjp161948 34377211Sjp161948 #ifdef SOLARIS_HW_SLOT_SELECTION 34387211Sjp161948 /* 34397211Sjp161948 * It would be great if we could use pkcs11_kernel directly since this library 34407211Sjp161948 * offers hardware slots only. That's the easiest way to achieve the situation 34417211Sjp161948 * where we use the hardware accelerators when present and OpenSSL native code 34427211Sjp161948 * otherwise. That presumes the fact that OpenSSL native code is faster than the 34437211Sjp161948 * code in the soft token. It's a logical assumption - Crypto Framework has some 34447211Sjp161948 * inherent overhead so going there for the software implementation of a 34457211Sjp161948 * mechanism should be logically slower in contrast to the OpenSSL native code, 34467211Sjp161948 * presuming that both implementations are of similar speed. For example, the 34477211Sjp161948 * soft token for AES is roughly three times slower than OpenSSL for 64 byte 34487211Sjp161948 * blocks and still 20% slower for 8KB blocks. So, if we want to ship products 34497211Sjp161948 * that use the PKCS#11 engine by default, we must somehow avoid that regression 34507211Sjp161948 * on machines without hardware acceleration. That's why switching to the 34517211Sjp161948 * pkcs11_kernel library seems like a very good idea. 34527211Sjp161948 * 34537211Sjp161948 * The problem is that OpenSSL built with SunStudio is roughly 2x slower for 34547211Sjp161948 * asymmetric operations (RSA/DSA/DH) than the soft token built with the same 34557211Sjp161948 * compiler. That means that if we switched to pkcs11_kernel from the libpkcs11 34567211Sjp161948 * library, we would have had a performance regression on machines without 34577211Sjp161948 * hardware acceleration for asymmetric operations for all applications that use 34587211Sjp161948 * the PKCS#11 engine. There is one such application - Apache web server since 34597211Sjp161948 * it's shipped configured to use the PKCS#11 engine by default. Having said 34607211Sjp161948 * that, we can't switch to the pkcs11_kernel library now and have to come with 34617211Sjp161948 * a solution that, on non-accelerated machines, uses the OpenSSL native code 34627211Sjp161948 * for all symmetric ciphers and digests while it uses the soft token for 34637211Sjp161948 * asymmetric operations. 34647211Sjp161948 * 34657211Sjp161948 * This is the idea: dlopen() pkcs11_kernel directly and find out what 34667211Sjp161948 * mechanisms are there. We don't care about duplications (more slots can 34677211Sjp161948 * support the same mechanism), we just want to know what mechanisms can be 34687211Sjp161948 * possibly supported in hardware on that particular machine. As said before, 34697211Sjp161948 * pkcs11_kernel will show you hardware providers only. 34707211Sjp161948 * 34717211Sjp161948 * Then, we rely on the fact that since we use libpkcs11 library we will find 34727211Sjp161948 * the metaslot. When we go through the metaslot's mechanisms for symmetric 34737211Sjp161948 * ciphers and digests, we check that any found mechanism is in the table 34747211Sjp161948 * created using the pkcs11_kernel library. So, as a result we have two arrays 34757211Sjp161948 * of mechanisms that were advertised as supported in hardware which was the 34767211Sjp161948 * goal of that whole excercise. Thus, we can use libpkcs11 but avoid soft token 34777211Sjp161948 * code for symmetric ciphers and digests. See pk11_choose_slots() for more 34787211Sjp161948 * information. 34797211Sjp161948 * 34807211Sjp161948 * This is Solaris specific code, if SOLARIS_HW_SLOT_SELECTION is not defined 34817211Sjp161948 * the code won't be used. 34827211Sjp161948 */ 34837211Sjp161948 #if defined(__sparcv9) || defined(__x86_64) || defined(__amd64) 34847211Sjp161948 static const char pkcs11_kernel[] = "/usr/lib/security/64/pkcs11_kernel.so.1"; 34857211Sjp161948 #else 34867211Sjp161948 static const char pkcs11_kernel[] = "/usr/lib/security/pkcs11_kernel.so.1"; 34877211Sjp161948 #endif 34887211Sjp161948 34897211Sjp161948 /* 34907211Sjp161948 * Check hardware capabilities of the machines. The output are two lists, 34917211Sjp161948 * hw_cnids and hw_dnids, that contain hardware mechanisms found in all hardware 34927211Sjp161948 * providers together. They are not sorted and may contain duplicate mechanisms. 34937211Sjp161948 */ 34947211Sjp161948 static int check_hw_mechanisms(void) 34957211Sjp161948 { 34967211Sjp161948 int i; 34977211Sjp161948 CK_RV rv; 34987211Sjp161948 void *handle; 34997211Sjp161948 CK_C_GetFunctionList p; 35007211Sjp161948 CK_TOKEN_INFO token_info; 35017211Sjp161948 CK_ULONG ulSlotCount = 0; 35027211Sjp161948 int n_cipher = 0, n_digest = 0; 35037211Sjp161948 CK_FUNCTION_LIST_PTR pflist = NULL; 35047211Sjp161948 CK_SLOT_ID_PTR pSlotList = NULL_PTR; 35057211Sjp161948 int *tmp_hw_cnids, *tmp_hw_dnids; 35067211Sjp161948 int hw_ctable_size, hw_dtable_size; 35077211Sjp161948 35087211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 35097211Sjp161948 fprintf(stderr, "%s: SOLARIS_HW_SLOT_SELECTION code running\n", 35107211Sjp161948 PK11_DBG); 35110Sstevel@tonic-gate #endif 35127211Sjp161948 if ((handle = dlopen(pkcs11_kernel, RTLD_LAZY)) == NULL) 35137211Sjp161948 { 35147211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); 35157211Sjp161948 goto err; 35167211Sjp161948 } 35177211Sjp161948 3518*7616SVladimir.Kotal@Sun.COM if ((p = (CK_C_GetFunctionList)dlsym(handle, 35197211Sjp161948 PK11_GET_FUNCTION_LIST)) == NULL) 35207211Sjp161948 { 35217211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); 35227211Sjp161948 goto err; 35237211Sjp161948 } 3524*7616SVladimir.Kotal@Sun.COM 3525*7616SVladimir.Kotal@Sun.COM /* get the full function list from the loaded library */ 35267211Sjp161948 if (p(&pflist) != CKR_OK) 35277211Sjp161948 { 35287211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_DSO_FAILURE); 35297211Sjp161948 goto err; 35307211Sjp161948 } 3531*7616SVladimir.Kotal@Sun.COM 35327211Sjp161948 rv = pflist->C_Initialize(NULL_PTR); 35337211Sjp161948 if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) 35347211Sjp161948 { 35357211Sjp161948 PK11err_add_data(PK11_F_CHECK_HW_MECHANISMS, 35367211Sjp161948 PK11_R_INITIALIZE, rv); 35377211Sjp161948 goto err; 35387211Sjp161948 } 35397211Sjp161948 35407211Sjp161948 if (pflist->C_GetSlotList(0, NULL_PTR, &ulSlotCount) != CKR_OK) 35417211Sjp161948 { 35427211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); 35437211Sjp161948 goto err; 35447211Sjp161948 } 35457211Sjp161948 35467211Sjp161948 /* no slots, set the hw mechanism tables as empty */ 35477211Sjp161948 if (ulSlotCount == 0) 35487211Sjp161948 { 35497211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 35507211Sjp161948 fprintf(stderr, "%s: no hardware mechanisms found\n", PK11_DBG); 35510Sstevel@tonic-gate #endif 35527211Sjp161948 hw_cnids = OPENSSL_malloc(sizeof (int)); 35537211Sjp161948 hw_dnids = OPENSSL_malloc(sizeof (int)); 35547211Sjp161948 if (hw_cnids == NULL || hw_dnids == NULL) 35557211Sjp161948 { 35567211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, 35577211Sjp161948 PK11_R_MALLOC_FAILURE); 35587211Sjp161948 return (0); 35597211Sjp161948 } 35607211Sjp161948 /* this means empty tables */ 35617211Sjp161948 hw_cnids[0] = NID_undef; 35627211Sjp161948 hw_dnids[0] = NID_undef; 35637211Sjp161948 return (1); 35647211Sjp161948 } 35657211Sjp161948 35667211Sjp161948 pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); 3567*7616SVladimir.Kotal@Sun.COM if (pSlotList == NULL) 35687211Sjp161948 { 35697211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); 35707211Sjp161948 goto err; 35717211Sjp161948 } 35727211Sjp161948 35737211Sjp161948 /* Get the slot list for processing */ 35747211Sjp161948 if (pflist->C_GetSlotList(0, pSlotList, &ulSlotCount) != CKR_OK) 35757211Sjp161948 { 35767211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_GETSLOTLIST); 35777211Sjp161948 goto err; 35787211Sjp161948 } 35797211Sjp161948 35807211Sjp161948 /* 35817211Sjp161948 * We don't care about duplicit mechanisms in multiple slots and also 35827211Sjp161948 * reserve one slot for the terminal NID_undef which we use to stop the 35837211Sjp161948 * search. 35847211Sjp161948 */ 35857211Sjp161948 hw_ctable_size = ulSlotCount * PK11_CIPHER_MAX + 1; 35867211Sjp161948 hw_dtable_size = ulSlotCount * PK11_DIGEST_MAX + 1; 35877211Sjp161948 tmp_hw_cnids = OPENSSL_malloc(hw_ctable_size * sizeof (int)); 35887211Sjp161948 tmp_hw_dnids = OPENSSL_malloc(hw_dtable_size * sizeof (int)); 35897211Sjp161948 if (tmp_hw_cnids == NULL || tmp_hw_dnids == NULL) 35907211Sjp161948 { 35917211Sjp161948 PK11err(PK11_F_CHECK_HW_MECHANISMS, PK11_R_MALLOC_FAILURE); 35927211Sjp161948 goto err; 35937211Sjp161948 } 35947211Sjp161948 35957211Sjp161948 /* 35967211Sjp161948 * Do not use memset since we should not rely on the fact that NID_undef 35977211Sjp161948 * is zero now. 35987211Sjp161948 */ 35997211Sjp161948 for (i = 0; i < hw_ctable_size; ++i) 36007211Sjp161948 tmp_hw_cnids[i] = NID_undef; 36017211Sjp161948 for (i = 0; i < hw_dtable_size; ++i) 36027211Sjp161948 tmp_hw_dnids[i] = NID_undef; 36037211Sjp161948 36047211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 36057211Sjp161948 fprintf(stderr, "%s: provider: %s\n", PK11_DBG, pkcs11_kernel); 36067211Sjp161948 fprintf(stderr, "%s: found %d hardware slots\n", PK11_DBG, ulSlotCount); 36077211Sjp161948 fprintf(stderr, "%s: now looking for mechs supported in hw\n", 3608*7616SVladimir.Kotal@Sun.COM PK11_DBG); 36097211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 36107211Sjp161948 3611*7616SVladimir.Kotal@Sun.COM for (i = 0; i < ulSlotCount; i++) 36127211Sjp161948 { 36137211Sjp161948 if (pflist->C_GetTokenInfo(pSlotList[i], &token_info) != CKR_OK) 36147211Sjp161948 continue; 36157211Sjp161948 36167211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 36177211Sjp161948 fprintf(stderr, "%s: token label: %.32s\n", PK11_DBG, token_info.label); 36187211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 36197211Sjp161948 36207211Sjp161948 /* 36217211Sjp161948 * We are filling the hw mech tables here. Global tables are 36227211Sjp161948 * still NULL so all mechanisms are put into tmp tables. 36237211Sjp161948 */ 36247211Sjp161948 pk11_find_symmetric_ciphers(pflist, pSlotList[i], 36257211Sjp161948 &n_cipher, tmp_hw_cnids); 36267211Sjp161948 pk11_find_digests(pflist, pSlotList[i], 36277211Sjp161948 &n_digest, tmp_hw_dnids); 36287211Sjp161948 } 36297211Sjp161948 36307211Sjp161948 /* 36317211Sjp161948 * Since we are part of a library (libcrypto.so), calling this function 36327211Sjp161948 * may have side-effects. Also, C_Finalize() is triggered by 36337211Sjp161948 * dlclose(3C). 36347211Sjp161948 */ 36357211Sjp161948 #if 0 36367211Sjp161948 pflist->C_Finalize(NULL); 36377211Sjp161948 #endif 36387211Sjp161948 OPENSSL_free(pSlotList); 36397534SVladimir.Kotal@Sun.COM (void) dlclose(handle); 36407211Sjp161948 hw_cnids = tmp_hw_cnids; 36417211Sjp161948 hw_dnids = tmp_hw_dnids; 36427211Sjp161948 36437211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 36447211Sjp161948 fprintf(stderr, "%s: hw mechs check complete\n", PK11_DBG); 36457211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 36467211Sjp161948 return (1); 36477211Sjp161948 36487211Sjp161948 err: 36497211Sjp161948 if (pSlotList != NULL) 36507211Sjp161948 OPENSSL_free(pSlotList); 36517211Sjp161948 if (tmp_hw_cnids != NULL) 36527211Sjp161948 OPENSSL_free(tmp_hw_cnids); 36537211Sjp161948 if (tmp_hw_dnids != NULL) 36547211Sjp161948 OPENSSL_free(tmp_hw_dnids); 36557211Sjp161948 36567211Sjp161948 return (0); 36577211Sjp161948 } 36587211Sjp161948 36597211Sjp161948 /* 36607211Sjp161948 * Check presence of a NID in the table of NIDs. The table may be NULL (i.e., 36617211Sjp161948 * non-existent). 36627211Sjp161948 */ 36637211Sjp161948 static int nid_in_table(int nid, int *nid_table) 36647211Sjp161948 { 36657211Sjp161948 int i = 0; 36667211Sjp161948 36677211Sjp161948 /* 36687211Sjp161948 * a special case. NULL means that we are initializing a new 36697211Sjp161948 * table. 36707211Sjp161948 */ 36717211Sjp161948 if (nid_table == NULL) 36727211Sjp161948 return (1); 36737211Sjp161948 36747211Sjp161948 /* 36757211Sjp161948 * the table is never full, there is always at least one 36767211Sjp161948 * NID_undef. 36777211Sjp161948 */ 36787211Sjp161948 while (nid_table[i] != NID_undef) 36797211Sjp161948 { 36807211Sjp161948 if (nid_table[i++] == nid) 36817211Sjp161948 { 36827211Sjp161948 #ifdef DEBUG_SLOT_SELECTION 36837211Sjp161948 fprintf(stderr, " (NID %d in hw table, idx %d)", nid, i); 36847211Sjp161948 #endif /* DEBUG_SLOT_SELECTION */ 36857211Sjp161948 return (1); 36867211Sjp161948 } 36877211Sjp161948 } 36887211Sjp161948 36897211Sjp161948 return (0); 36907211Sjp161948 } 36917211Sjp161948 #endif /* SOLARIS_HW_SLOT_SELECTION */ 36927211Sjp161948 36937211Sjp161948 #endif /* OPENSSL_NO_HW_PK11 */ 36947211Sjp161948 #endif /* OPENSSL_NO_HW */ 3695