10Sstevel@tonic-gate /* 2*6847Svk199839 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 30Sstevel@tonic-gate * Use is subject to license terms. 40Sstevel@tonic-gate */ 50Sstevel@tonic-gate 60Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 70Sstevel@tonic-gate 80Sstevel@tonic-gate /* crypto/engine/hw_pk11.c */ 90Sstevel@tonic-gate /* This product includes software developed by the OpenSSL Project for 100Sstevel@tonic-gate * use in the OpenSSL Toolkit (http://www.openssl.org/). 110Sstevel@tonic-gate * 120Sstevel@tonic-gate * This project also referenced hw_pkcs11-0.9.7b.patch written by 130Sstevel@tonic-gate * Afchine Madjlessi. 140Sstevel@tonic-gate */ 150Sstevel@tonic-gate /* ==================================================================== 160Sstevel@tonic-gate * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. 170Sstevel@tonic-gate * 180Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 190Sstevel@tonic-gate * modification, are permitted provided that the following conditions 200Sstevel@tonic-gate * are met: 210Sstevel@tonic-gate * 220Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 230Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 240Sstevel@tonic-gate * 250Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 260Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in 270Sstevel@tonic-gate * the documentation and/or other materials provided with the 280Sstevel@tonic-gate * distribution. 290Sstevel@tonic-gate * 300Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this 310Sstevel@tonic-gate * software must display the following acknowledgment: 320Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project 330Sstevel@tonic-gate * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 340Sstevel@tonic-gate * 350Sstevel@tonic-gate * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 360Sstevel@tonic-gate * endorse or promote products derived from this software without 370Sstevel@tonic-gate * prior written permission. For written permission, please contact 380Sstevel@tonic-gate * licensing@OpenSSL.org. 390Sstevel@tonic-gate * 400Sstevel@tonic-gate * 5. Products derived from this software may not be called "OpenSSL" 410Sstevel@tonic-gate * nor may "OpenSSL" appear in their names without prior written 420Sstevel@tonic-gate * permission of the OpenSSL Project. 430Sstevel@tonic-gate * 440Sstevel@tonic-gate * 6. Redistributions of any form whatsoever must retain the following 450Sstevel@tonic-gate * acknowledgment: 460Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project 470Sstevel@tonic-gate * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 480Sstevel@tonic-gate * 490Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 500Sstevel@tonic-gate * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 510Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 520Sstevel@tonic-gate * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 530Sstevel@tonic-gate * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 540Sstevel@tonic-gate * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 550Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 560Sstevel@tonic-gate * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 570Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 580Sstevel@tonic-gate * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 590Sstevel@tonic-gate * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 600Sstevel@tonic-gate * OF THE POSSIBILITY OF SUCH DAMAGE. 610Sstevel@tonic-gate * ==================================================================== 620Sstevel@tonic-gate * 630Sstevel@tonic-gate * This product includes cryptographic software written by Eric Young 640Sstevel@tonic-gate * (eay@cryptsoft.com). This product includes software written by Tim 650Sstevel@tonic-gate * Hudson (tjh@cryptsoft.com). 660Sstevel@tonic-gate * 670Sstevel@tonic-gate */ 680Sstevel@tonic-gate 690Sstevel@tonic-gate #include <stdio.h> 700Sstevel@tonic-gate #include <stdlib.h> 710Sstevel@tonic-gate #include <string.h> 720Sstevel@tonic-gate #include <sys/types.h> 730Sstevel@tonic-gate #include <unistd.h> 740Sstevel@tonic-gate 750Sstevel@tonic-gate #include <openssl/e_os2.h> 76*6847Svk199839 #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> 83*6847Svk199839 #ifndef OPENSSL_NO_RSA 840Sstevel@tonic-gate #include <openssl/rsa.h> 85*6847Svk199839 #endif 86*6847Svk199839 #ifndef OPENSSL_NO_DSA 87*6847Svk199839 #include <openssl/dsa.h> 88*6847Svk199839 #endif 89*6847Svk199839 #ifndef OPENSSL_NO_DH 90*6847Svk199839 #include <openssl/dh.h> 91*6847Svk199839 #endif 920Sstevel@tonic-gate #include <openssl/rand.h> 930Sstevel@tonic-gate #include <openssl/objects.h> 940Sstevel@tonic-gate #include <openssl/x509.h> 950Sstevel@tonic-gate #include <cryptlib.h> 960Sstevel@tonic-gate 970Sstevel@tonic-gate #ifndef OPENSSL_NO_HW 980Sstevel@tonic-gate #ifndef OPENSSL_NO_HW_PK11 990Sstevel@tonic-gate 1000Sstevel@tonic-gate #undef DEBUG_SLOT_SELECTION 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate #include "security/cryptoki.h" 1030Sstevel@tonic-gate #include "security/pkcs11.h" 1040Sstevel@tonic-gate #include "hw_pk11_err.c" 1050Sstevel@tonic-gate 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate /* The head of the free PK11 session list */ 1080Sstevel@tonic-gate static struct PK11_SESSION_st *free_session = NULL; 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate /* Create all secret key objects in a global session so that they are available 1110Sstevel@tonic-gate * to use for other sessions. These other sessions may be opened or closed 1120Sstevel@tonic-gate * without losing the secret key objects */ 1130Sstevel@tonic-gate static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE; 1140Sstevel@tonic-gate 1150Sstevel@tonic-gate /* ENGINE level stuff */ 1160Sstevel@tonic-gate static int pk11_init(ENGINE *e); 1170Sstevel@tonic-gate static int pk11_library_init(ENGINE *e); 1180Sstevel@tonic-gate static int pk11_finish(ENGINE *e); 1190Sstevel@tonic-gate static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); 1200Sstevel@tonic-gate static int pk11_destroy(ENGINE *e); 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate /* RAND stuff */ 1230Sstevel@tonic-gate static void pk11_rand_seed(const void *buf, int num); 1240Sstevel@tonic-gate static void pk11_rand_add(const void *buf, int num, double add_entropy); 1250Sstevel@tonic-gate static void pk11_rand_cleanup(void); 1260Sstevel@tonic-gate static int pk11_rand_bytes(unsigned char *buf, int num); 1270Sstevel@tonic-gate static int pk11_rand_status(void); 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate /* These functions are also used in other files */ 1300Sstevel@tonic-gate PK11_SESSION *pk11_get_session(); 1310Sstevel@tonic-gate void pk11_return_session(PK11_SESSION *sp); 132*6847Svk199839 133*6847Svk199839 /* active list manipulation functions used here */ 134*6847Svk199839 int pk11_active_delete(CK_OBJECT_HANDLE h); 135*6847Svk199839 136*6847Svk199839 #ifndef OPENSSL_NO_RSA 1370Sstevel@tonic-gate int pk11_destroy_rsa_key_objects(PK11_SESSION *session); 138*6847Svk199839 int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); 139*6847Svk199839 int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); 140*6847Svk199839 #endif 141*6847Svk199839 #ifndef OPENSSL_NO_DSA 1420Sstevel@tonic-gate int pk11_destroy_dsa_key_objects(PK11_SESSION *session); 143*6847Svk199839 int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock); 144*6847Svk199839 int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock); 145*6847Svk199839 #endif 146*6847Svk199839 #ifndef OPENSSL_NO_DH 1470Sstevel@tonic-gate int pk11_destroy_dh_key_objects(PK11_SESSION *session); 148*6847Svk199839 int pk11_destroy_dh_object(PK11_SESSION *session, CK_BBOOL uselock); 149*6847Svk199839 #endif 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate /* Local helper functions */ 1520Sstevel@tonic-gate static int pk11_free_all_sessions(); 1530Sstevel@tonic-gate static int pk11_setup_session(PK11_SESSION *sp); 1540Sstevel@tonic-gate static int pk11_destroy_cipher_key_objects(PK11_SESSION *session); 155*6847Svk199839 static int pk11_destroy_object(CK_SESSION_HANDLE session, 1560Sstevel@tonic-gate CK_OBJECT_HANDLE oh); 1570Sstevel@tonic-gate static const char *get_PK11_LIBNAME(void); 1580Sstevel@tonic-gate static void free_PK11_LIBNAME(void); 1590Sstevel@tonic-gate static long set_PK11_LIBNAME(const char *name); 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate /* Symmetric cipher and digest support functions */ 1620Sstevel@tonic-gate static int cipher_nid_to_pk11(int nid); 1630Sstevel@tonic-gate static int pk11_usable_ciphers(const int **nids); 1640Sstevel@tonic-gate static int pk11_usable_digests(const int **nids); 1650Sstevel@tonic-gate static int pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, 1660Sstevel@tonic-gate const unsigned char *iv, int enc); 167*6847Svk199839 static int pk11_init_symmetric(EVP_CIPHER_CTX *ctx, PK11_SESSION *sp, 168*6847Svk199839 CK_MECHANISM_PTR pmech); 1690Sstevel@tonic-gate static int pk11_cipher_final(PK11_SESSION *sp); 1700Sstevel@tonic-gate static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 1710Sstevel@tonic-gate const unsigned char *in, unsigned int inl); 1720Sstevel@tonic-gate static int pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx); 1730Sstevel@tonic-gate static int pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 1740Sstevel@tonic-gate const int **nids, int nid); 1750Sstevel@tonic-gate static int pk11_engine_digests(ENGINE *e, const EVP_MD **digest, 1760Sstevel@tonic-gate const int **nids, int nid); 1770Sstevel@tonic-gate static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, 1780Sstevel@tonic-gate const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp); 179*6847Svk199839 static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key); 1800Sstevel@tonic-gate static int md_nid_to_pk11(int nid); 1810Sstevel@tonic-gate static int pk11_digest_init(EVP_MD_CTX *ctx); 1820Sstevel@tonic-gate static int pk11_digest_update(EVP_MD_CTX *ctx,const void *data, 1832139Sjp161948 size_t count); 1840Sstevel@tonic-gate static int pk11_digest_final(EVP_MD_CTX *ctx,unsigned char *md); 1850Sstevel@tonic-gate static int pk11_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from); 1860Sstevel@tonic-gate static int pk11_digest_cleanup(EVP_MD_CTX *ctx); 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate static int pk11_choose_slot(); 1890Sstevel@tonic-gate static int pk11_count_symmetric_cipher(int slot_id, CK_MECHANISM_TYPE mech, 1900Sstevel@tonic-gate int *current_slot_n_cipher, int *local_cipher_nids, int id); 1910Sstevel@tonic-gate static int pk11_count_digest(int slot_id, CK_MECHANISM_TYPE mech, 1920Sstevel@tonic-gate int *current_slot_n_digest, int *local_digest_nids, int id); 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate /* Index for the supported ciphers */ 1950Sstevel@tonic-gate #define PK11_DES_CBC 0 1960Sstevel@tonic-gate #define PK11_DES3_CBC 1 1970Sstevel@tonic-gate #define PK11_AES_CBC 2 1980Sstevel@tonic-gate #define PK11_RC4 3 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate /* Index for the supported digests */ 2010Sstevel@tonic-gate #define PK11_MD5 0 2020Sstevel@tonic-gate #define PK11_SHA1 1 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate #define PK11_CIPHER_MAX 4 /* Max num of ciphers supported */ 2050Sstevel@tonic-gate #define PK11_DIGEST_MAX 2 /* Max num of digests supported */ 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate #define PK11_KEY_LEN_MAX 24 2080Sstevel@tonic-gate 209*6847Svk199839 #define TRY_OBJ_DESTROY(sess_hdl, obj_hdl, retval, uselock) \ 210*6847Svk199839 { \ 211*6847Svk199839 if (uselock) \ 212*6847Svk199839 CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); \ 213*6847Svk199839 if (pk11_active_delete(obj_hdl) == 1) \ 214*6847Svk199839 { \ 215*6847Svk199839 retval = pk11_destroy_object(sess_hdl, obj_hdl); \ 216*6847Svk199839 } \ 217*6847Svk199839 if (uselock) \ 218*6847Svk199839 CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); \ 219*6847Svk199839 } 220*6847Svk199839 2210Sstevel@tonic-gate static int cipher_nids[PK11_CIPHER_MAX]; 2220Sstevel@tonic-gate static int digest_nids[PK11_DIGEST_MAX]; 2230Sstevel@tonic-gate static int cipher_count = 0; 2240Sstevel@tonic-gate static int digest_count = 0; 2250Sstevel@tonic-gate static CK_BBOOL pk11_have_rsa = CK_FALSE; 2260Sstevel@tonic-gate static CK_BBOOL pk11_have_dsa = CK_FALSE; 2270Sstevel@tonic-gate static CK_BBOOL pk11_have_dh = CK_FALSE; 2280Sstevel@tonic-gate static CK_BBOOL pk11_have_random = CK_FALSE; 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate typedef struct PK11_CIPHER_st 2310Sstevel@tonic-gate { 2324320Sjp161948 int id; 2334320Sjp161948 int nid; 2344320Sjp161948 int ivmax; 2354320Sjp161948 int key_len; 2364320Sjp161948 CK_KEY_TYPE key_type; 2374320Sjp161948 CK_MECHANISM_TYPE mech_type; 2380Sstevel@tonic-gate } PK11_CIPHER; 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate static PK11_CIPHER ciphers[] = 2410Sstevel@tonic-gate { 2424320Sjp161948 {PK11_DES_CBC, NID_des_cbc, 8, 8, CKK_DES, CKM_DES_CBC, }, 2434320Sjp161948 {PK11_DES3_CBC, NID_des_ede3_cbc, 8, 24, CKK_DES3, CKM_DES3_CBC, }, 2444320Sjp161948 {PK11_AES_CBC, NID_aes_128_cbc, 16, 16, CKK_AES, CKM_AES_CBC, }, 2454320Sjp161948 {PK11_RC4, NID_rc4, 0, 16, CKK_RC4, CKM_RC4, }, 2460Sstevel@tonic-gate }; 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate typedef struct PK11_DIGEST_st 2490Sstevel@tonic-gate { 2504320Sjp161948 int id; 2514320Sjp161948 int nid; 2524320Sjp161948 CK_MECHANISM_TYPE mech_type; 2530Sstevel@tonic-gate } PK11_DIGEST; 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate static PK11_DIGEST digests[] = 2560Sstevel@tonic-gate { 2574320Sjp161948 {PK11_MD5, NID_md5, CKM_MD5, }, 2584320Sjp161948 {PK11_SHA1, NID_sha1, CKM_SHA_1, }, 2594320Sjp161948 {0, NID_undef, 0xFFFF, }, 2600Sstevel@tonic-gate }; 2610Sstevel@tonic-gate 2620Sstevel@tonic-gate /* Structure to be used for the cipher_data/md_data in 2630Sstevel@tonic-gate * EVP_CIPHER_CTX/EVP_MD_CTX structures in order to use the same 2640Sstevel@tonic-gate * pk11 session in multiple cipher_update calls 2650Sstevel@tonic-gate */ 2660Sstevel@tonic-gate typedef struct PK11_CIPHER_STATE_st 2670Sstevel@tonic-gate { 2680Sstevel@tonic-gate PK11_SESSION *sp; 2690Sstevel@tonic-gate } PK11_CIPHER_STATE; 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate /* libcrypto EVP stuff - this is how we get wired to EVP so the engine 2730Sstevel@tonic-gate * gets called when libcrypto requests a cipher NID. 2740Sstevel@tonic-gate * Note how the PK11_CIPHER_STATE is used here. 2750Sstevel@tonic-gate */ 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate /* DES CBC EVP */ 2780Sstevel@tonic-gate static const EVP_CIPHER pk11_des_cbc = 2790Sstevel@tonic-gate { 2800Sstevel@tonic-gate NID_des_cbc, 2810Sstevel@tonic-gate 8, 8, 8, 2820Sstevel@tonic-gate EVP_CIPH_CBC_MODE, 2830Sstevel@tonic-gate pk11_cipher_init, 2840Sstevel@tonic-gate pk11_cipher_do_cipher, 2850Sstevel@tonic-gate pk11_cipher_cleanup, 2860Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 2870Sstevel@tonic-gate EVP_CIPHER_set_asn1_iv, 2880Sstevel@tonic-gate EVP_CIPHER_get_asn1_iv, 2890Sstevel@tonic-gate NULL 2900Sstevel@tonic-gate }; 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate /* 3DES CBC EVP */ 2930Sstevel@tonic-gate static const EVP_CIPHER pk11_3des_cbc = 2940Sstevel@tonic-gate { 2950Sstevel@tonic-gate NID_des_ede3_cbc, 2960Sstevel@tonic-gate 8, 24, 8, 2970Sstevel@tonic-gate EVP_CIPH_CBC_MODE, 2980Sstevel@tonic-gate pk11_cipher_init, 2990Sstevel@tonic-gate pk11_cipher_do_cipher, 3000Sstevel@tonic-gate pk11_cipher_cleanup, 3010Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 3020Sstevel@tonic-gate EVP_CIPHER_set_asn1_iv, 3030Sstevel@tonic-gate EVP_CIPHER_get_asn1_iv, 3040Sstevel@tonic-gate NULL 3050Sstevel@tonic-gate }; 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate static const EVP_CIPHER pk11_aes_cbc = 3080Sstevel@tonic-gate { 3090Sstevel@tonic-gate NID_aes_128_cbc, 3100Sstevel@tonic-gate 16, 16, 16, 3110Sstevel@tonic-gate EVP_CIPH_CBC_MODE, 3120Sstevel@tonic-gate pk11_cipher_init, 3130Sstevel@tonic-gate pk11_cipher_do_cipher, 3140Sstevel@tonic-gate pk11_cipher_cleanup, 3150Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 3160Sstevel@tonic-gate EVP_CIPHER_set_asn1_iv, 3170Sstevel@tonic-gate EVP_CIPHER_get_asn1_iv, 3180Sstevel@tonic-gate NULL 3190Sstevel@tonic-gate }; 3200Sstevel@tonic-gate 3210Sstevel@tonic-gate static const EVP_CIPHER pk11_rc4 = 3220Sstevel@tonic-gate { 3230Sstevel@tonic-gate NID_rc4, 3240Sstevel@tonic-gate 1,16,0, 3250Sstevel@tonic-gate EVP_CIPH_VARIABLE_LENGTH, 3260Sstevel@tonic-gate pk11_cipher_init, 3270Sstevel@tonic-gate pk11_cipher_do_cipher, 3280Sstevel@tonic-gate pk11_cipher_cleanup, 3290Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 3300Sstevel@tonic-gate NULL, 3310Sstevel@tonic-gate NULL, 3320Sstevel@tonic-gate NULL 3330Sstevel@tonic-gate }; 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate static const EVP_MD pk11_md5 = 3360Sstevel@tonic-gate { 3370Sstevel@tonic-gate NID_md5, 3380Sstevel@tonic-gate NID_md5WithRSAEncryption, 3390Sstevel@tonic-gate MD5_DIGEST_LENGTH, 3400Sstevel@tonic-gate 0, 3410Sstevel@tonic-gate pk11_digest_init, 3420Sstevel@tonic-gate pk11_digest_update, 3430Sstevel@tonic-gate pk11_digest_final, 3440Sstevel@tonic-gate pk11_digest_copy, 3450Sstevel@tonic-gate pk11_digest_cleanup, 3460Sstevel@tonic-gate EVP_PKEY_RSA_method, 3470Sstevel@tonic-gate MD5_CBLOCK, 3480Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 3490Sstevel@tonic-gate }; 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate static const EVP_MD pk11_sha1 = 3520Sstevel@tonic-gate { 3530Sstevel@tonic-gate NID_sha1, 3540Sstevel@tonic-gate NID_sha1WithRSAEncryption, 3550Sstevel@tonic-gate SHA_DIGEST_LENGTH, 3560Sstevel@tonic-gate 0, 3570Sstevel@tonic-gate pk11_digest_init, 3580Sstevel@tonic-gate pk11_digest_update, 3590Sstevel@tonic-gate pk11_digest_final, 3600Sstevel@tonic-gate pk11_digest_copy, 3610Sstevel@tonic-gate pk11_digest_cleanup, 3620Sstevel@tonic-gate EVP_PKEY_RSA_method, 3630Sstevel@tonic-gate SHA_CBLOCK, 3640Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 3650Sstevel@tonic-gate }; 3660Sstevel@tonic-gate 3670Sstevel@tonic-gate /* Initialization function. Sets up various pk11 library components. 3680Sstevel@tonic-gate */ 3690Sstevel@tonic-gate /* The definitions for control commands specific to this engine 3700Sstevel@tonic-gate */ 3710Sstevel@tonic-gate #define PK11_CMD_SO_PATH ENGINE_CMD_BASE 3720Sstevel@tonic-gate static const ENGINE_CMD_DEFN pk11_cmd_defns[] = 3730Sstevel@tonic-gate { 3740Sstevel@tonic-gate { 3750Sstevel@tonic-gate PK11_CMD_SO_PATH, 3760Sstevel@tonic-gate "SO_PATH", 3770Sstevel@tonic-gate "Specifies the path to the 'pkcs#11' shared library", 3780Sstevel@tonic-gate ENGINE_CMD_FLAG_STRING 3790Sstevel@tonic-gate }, 3800Sstevel@tonic-gate {0, NULL, NULL, 0} 3810Sstevel@tonic-gate }; 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate static RAND_METHOD pk11_random = 3850Sstevel@tonic-gate { 3860Sstevel@tonic-gate pk11_rand_seed, 3870Sstevel@tonic-gate pk11_rand_bytes, 3880Sstevel@tonic-gate pk11_rand_cleanup, 3890Sstevel@tonic-gate pk11_rand_add, 3900Sstevel@tonic-gate pk11_rand_bytes, 3910Sstevel@tonic-gate pk11_rand_status 3920Sstevel@tonic-gate }; 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate /* Constants used when creating the ENGINE 3960Sstevel@tonic-gate */ 3970Sstevel@tonic-gate static const char *engine_pk11_id = "pkcs11"; 3980Sstevel@tonic-gate static const char *engine_pk11_name = "PKCS #11 engine support"; 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate CK_FUNCTION_LIST_PTR pFuncList = NULL; 4010Sstevel@tonic-gate static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList"; 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate /* These are the static string constants for the DSO file name and the function 4040Sstevel@tonic-gate * symbol names to bind to. 4050Sstevel@tonic-gate */ 4060Sstevel@tonic-gate #if defined(__sparcv9) || defined(__x86_64) || defined(__amd64) 4070Sstevel@tonic-gate static const char def_PK11_LIBNAME[] = "/usr/lib/64/libpkcs11.so.1"; 4080Sstevel@tonic-gate #else 4090Sstevel@tonic-gate static const char def_PK11_LIBNAME[] = "/usr/lib/libpkcs11.so.1"; 4100Sstevel@tonic-gate #endif 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate static CK_BBOOL true = TRUE; 4130Sstevel@tonic-gate static CK_BBOOL false = FALSE; 4140Sstevel@tonic-gate static CK_SLOT_ID SLOTID = 0; 4150Sstevel@tonic-gate static int pk11_library_initialized = 0; 4160Sstevel@tonic-gate 4170Sstevel@tonic-gate static DSO *pk11_dso = NULL; 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate /* 4200Sstevel@tonic-gate * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support. 4210Sstevel@tonic-gate */ 4220Sstevel@tonic-gate static int bind_pk11(ENGINE *e) 4230Sstevel@tonic-gate { 424*6847Svk199839 #ifndef OPENSSL_NO_RSA 4250Sstevel@tonic-gate const RSA_METHOD *rsa = NULL; 4260Sstevel@tonic-gate RSA_METHOD *pk11_rsa = PK11_RSA(); 427*6847Svk199839 #endif 4280Sstevel@tonic-gate if (!pk11_library_initialized) 4290Sstevel@tonic-gate pk11_library_init(e); 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate if(!ENGINE_set_id(e, engine_pk11_id) || 4320Sstevel@tonic-gate !ENGINE_set_name(e, engine_pk11_name) || 4330Sstevel@tonic-gate !ENGINE_set_ciphers(e, pk11_engine_ciphers) || 4340Sstevel@tonic-gate !ENGINE_set_digests(e, pk11_engine_digests)) 4350Sstevel@tonic-gate return 0; 4360Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA 4370Sstevel@tonic-gate if(pk11_have_rsa == CK_TRUE) 4380Sstevel@tonic-gate { 4390Sstevel@tonic-gate if(!ENGINE_set_RSA(e, PK11_RSA()) || 4400Sstevel@tonic-gate !ENGINE_set_load_privkey_function(e, pk11_load_privkey) || 4410Sstevel@tonic-gate !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey)) 4420Sstevel@tonic-gate return 0; 4430Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 4440Sstevel@tonic-gate fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: registered RSA\n"); 4450Sstevel@tonic-gate #endif /* DEBUG_SLOT_SELECTION */ 4460Sstevel@tonic-gate } 4470Sstevel@tonic-gate #endif 4480Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA 4490Sstevel@tonic-gate if(pk11_have_dsa == CK_TRUE) 4500Sstevel@tonic-gate { 4510Sstevel@tonic-gate if (!ENGINE_set_DSA(e, PK11_DSA())) 4520Sstevel@tonic-gate return 0; 4530Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 4540Sstevel@tonic-gate fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: registered DSA\n"); 4550Sstevel@tonic-gate #endif /* DEBUG_SLOT_SELECTION */ 4560Sstevel@tonic-gate } 4570Sstevel@tonic-gate #endif 4580Sstevel@tonic-gate #ifndef OPENSSL_NO_DH 4590Sstevel@tonic-gate if(pk11_have_dh == CK_TRUE) 4600Sstevel@tonic-gate { 4610Sstevel@tonic-gate if (!ENGINE_set_DH(e, PK11_DH())) 4620Sstevel@tonic-gate return 0; 4630Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 4640Sstevel@tonic-gate fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: registered DH\n"); 4650Sstevel@tonic-gate #endif /* DEBUG_SLOT_SELECTION */ 4660Sstevel@tonic-gate } 4670Sstevel@tonic-gate #endif 4680Sstevel@tonic-gate if(pk11_have_random) 4690Sstevel@tonic-gate { 4700Sstevel@tonic-gate if(!ENGINE_set_RAND(e, &pk11_random)) 4710Sstevel@tonic-gate return 0; 4720Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 4730Sstevel@tonic-gate fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: registered random\n"); 4740Sstevel@tonic-gate #endif /* DEBUG_SLOT_SELECTION */ 4750Sstevel@tonic-gate } 4760Sstevel@tonic-gate if(!ENGINE_set_init_function(e, pk11_init) || 4770Sstevel@tonic-gate !ENGINE_set_destroy_function(e, pk11_destroy) || 4780Sstevel@tonic-gate !ENGINE_set_finish_function(e, pk11_finish) || 4790Sstevel@tonic-gate !ENGINE_set_ctrl_function(e, pk11_ctrl) || 4800Sstevel@tonic-gate !ENGINE_set_cmd_defns(e, pk11_cmd_defns)) 4810Sstevel@tonic-gate return 0; 4820Sstevel@tonic-gate 4830Sstevel@tonic-gate /* Apache calls OpenSSL function RSA_blinding_on() once during startup 4840Sstevel@tonic-gate * which in turn calls bn_mod_exp. Since we do not implement bn_mod_exp 4850Sstevel@tonic-gate * here, we wire it back to the OpenSSL software implementation. 4860Sstevel@tonic-gate * Since it is used only once, performance is not a concern. */ 4870Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA 4880Sstevel@tonic-gate rsa = RSA_PKCS1_SSLeay(); 4890Sstevel@tonic-gate pk11_rsa->rsa_mod_exp = rsa->rsa_mod_exp; 4900Sstevel@tonic-gate pk11_rsa->bn_mod_exp = rsa->bn_mod_exp; 4910Sstevel@tonic-gate #endif 4920Sstevel@tonic-gate 4930Sstevel@tonic-gate /* Ensure the pk11 error handling is set up */ 4940Sstevel@tonic-gate ERR_load_pk11_strings(); 4950Sstevel@tonic-gate 4960Sstevel@tonic-gate return 1; 4970Sstevel@tonic-gate } 4980Sstevel@tonic-gate 4990Sstevel@tonic-gate /* Dynamic engine support is disabled at a higher level for Solaris 5000Sstevel@tonic-gate */ 5010Sstevel@tonic-gate #ifdef ENGINE_DYNAMIC_SUPPORT 5020Sstevel@tonic-gate static int bind_helper(ENGINE *e, const char *id) 5030Sstevel@tonic-gate { 5040Sstevel@tonic-gate if (id && (strcmp(id, engine_pk11_id) != 0)) 5050Sstevel@tonic-gate return 0; 5060Sstevel@tonic-gate 5070Sstevel@tonic-gate if (!bind_pk11(e)) 5080Sstevel@tonic-gate return 0; 5090Sstevel@tonic-gate 5100Sstevel@tonic-gate return 1; 5110Sstevel@tonic-gate } 5120Sstevel@tonic-gate 5130Sstevel@tonic-gate IMPLEMENT_DYNAMIC_CHECK_FN() 5140Sstevel@tonic-gate IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) 5150Sstevel@tonic-gate 5160Sstevel@tonic-gate #else 5170Sstevel@tonic-gate static ENGINE *engine_pk11(void) 5180Sstevel@tonic-gate { 5190Sstevel@tonic-gate ENGINE *ret = ENGINE_new(); 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate if (!ret) 5220Sstevel@tonic-gate return NULL; 5230Sstevel@tonic-gate 5240Sstevel@tonic-gate if (!bind_pk11(ret)) 5250Sstevel@tonic-gate { 5260Sstevel@tonic-gate ENGINE_free(ret); 5270Sstevel@tonic-gate return NULL; 5280Sstevel@tonic-gate } 5290Sstevel@tonic-gate 5300Sstevel@tonic-gate return ret; 5310Sstevel@tonic-gate } 5320Sstevel@tonic-gate 5330Sstevel@tonic-gate void ENGINE_load_pk11(void) 5340Sstevel@tonic-gate { 5350Sstevel@tonic-gate ENGINE *e_pk11 = NULL; 5360Sstevel@tonic-gate 5370Sstevel@tonic-gate /* Do not use dynamic PKCS#11 library on Solaris due to 5380Sstevel@tonic-gate * security reasons. We will link it in statically 5390Sstevel@tonic-gate */ 5400Sstevel@tonic-gate /* Attempt to load PKCS#11 library 5410Sstevel@tonic-gate */ 5420Sstevel@tonic-gate if (!pk11_dso) 5430Sstevel@tonic-gate pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0); 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate if (pk11_dso == NULL) 5460Sstevel@tonic-gate { 5470Sstevel@tonic-gate PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE); 5480Sstevel@tonic-gate return; 5490Sstevel@tonic-gate } 5500Sstevel@tonic-gate 5510Sstevel@tonic-gate e_pk11 = engine_pk11(); 5520Sstevel@tonic-gate if (!e_pk11) 5530Sstevel@tonic-gate { 5540Sstevel@tonic-gate DSO_free(pk11_dso); 5550Sstevel@tonic-gate pk11_dso = NULL; 5560Sstevel@tonic-gate return; 5570Sstevel@tonic-gate } 5580Sstevel@tonic-gate 5590Sstevel@tonic-gate /* At this point, the pk11 shared library is either dynamically 5600Sstevel@tonic-gate * loaded or statically linked in. So, initialize the pk11 5610Sstevel@tonic-gate * library before calling ENGINE_set_default since the latter 5620Sstevel@tonic-gate * needs cipher and digest algorithm information 5630Sstevel@tonic-gate */ 5640Sstevel@tonic-gate if (!pk11_library_init(e_pk11)) 5650Sstevel@tonic-gate { 5660Sstevel@tonic-gate DSO_free(pk11_dso); 5670Sstevel@tonic-gate pk11_dso = NULL; 5680Sstevel@tonic-gate ENGINE_free(e_pk11); 5690Sstevel@tonic-gate return; 5700Sstevel@tonic-gate } 5710Sstevel@tonic-gate 5720Sstevel@tonic-gate ENGINE_add(e_pk11); 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate ENGINE_free(e_pk11); 5750Sstevel@tonic-gate ERR_clear_error(); 5760Sstevel@tonic-gate } 5770Sstevel@tonic-gate #endif 5780Sstevel@tonic-gate 5790Sstevel@tonic-gate /* These are the static string constants for the DSO file name and 5800Sstevel@tonic-gate * the function symbol names to bind to. 5810Sstevel@tonic-gate */ 5820Sstevel@tonic-gate static const char *PK11_LIBNAME = NULL; 5830Sstevel@tonic-gate 5840Sstevel@tonic-gate static const char *get_PK11_LIBNAME(void) 5850Sstevel@tonic-gate { 5860Sstevel@tonic-gate if (PK11_LIBNAME) 5870Sstevel@tonic-gate return PK11_LIBNAME; 5880Sstevel@tonic-gate 5890Sstevel@tonic-gate return def_PK11_LIBNAME; 5900Sstevel@tonic-gate } 5910Sstevel@tonic-gate 5920Sstevel@tonic-gate static void free_PK11_LIBNAME(void) 5930Sstevel@tonic-gate { 5940Sstevel@tonic-gate if (PK11_LIBNAME) 5950Sstevel@tonic-gate OPENSSL_free((void*)PK11_LIBNAME); 5960Sstevel@tonic-gate 5970Sstevel@tonic-gate PK11_LIBNAME = NULL; 5980Sstevel@tonic-gate } 5990Sstevel@tonic-gate 6000Sstevel@tonic-gate static long set_PK11_LIBNAME(const char *name) 6010Sstevel@tonic-gate { 6020Sstevel@tonic-gate free_PK11_LIBNAME(); 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0); 6050Sstevel@tonic-gate } 6060Sstevel@tonic-gate 6070Sstevel@tonic-gate /* Initialization function for the pk11 engine */ 6080Sstevel@tonic-gate static int pk11_init(ENGINE *e) 6090Sstevel@tonic-gate { 6100Sstevel@tonic-gate return pk11_library_init(e); 6110Sstevel@tonic-gate } 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate /* Initialization function. Sets up various pk11 library components. 6140Sstevel@tonic-gate * It selects a slot based on predefined critiera. In the process, it also 6150Sstevel@tonic-gate * count how many ciphers and digests to support. Since the cipher and 6160Sstevel@tonic-gate * digest information is needed when setting default engine, this function 6170Sstevel@tonic-gate * needs to be called before calling ENGINE_set_default. 6180Sstevel@tonic-gate */ 6190Sstevel@tonic-gate static int pk11_library_init(ENGINE *e) 6200Sstevel@tonic-gate { 6210Sstevel@tonic-gate CK_C_GetFunctionList p; 6220Sstevel@tonic-gate CK_RV rv = CKR_OK; 6230Sstevel@tonic-gate CK_INFO info; 6240Sstevel@tonic-gate CK_ULONG ul_state_len; 6250Sstevel@tonic-gate char tmp_buf[20]; 6260Sstevel@tonic-gate 6270Sstevel@tonic-gate if (pk11_library_initialized) 6280Sstevel@tonic-gate return 1; 6290Sstevel@tonic-gate 6300Sstevel@tonic-gate if (pk11_dso == NULL) 6310Sstevel@tonic-gate { 6320Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); 6330Sstevel@tonic-gate goto err; 6340Sstevel@tonic-gate } 6350Sstevel@tonic-gate 6360Sstevel@tonic-gate /* get the C_GetFunctionList function from the loaded library 6370Sstevel@tonic-gate */ 6380Sstevel@tonic-gate p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso, 6390Sstevel@tonic-gate PK11_GET_FUNCTION_LIST); 6400Sstevel@tonic-gate if ( !p ) 6410Sstevel@tonic-gate { 6420Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); 6430Sstevel@tonic-gate goto err; 6440Sstevel@tonic-gate } 6450Sstevel@tonic-gate 6460Sstevel@tonic-gate /* get the full function list from the loaded library 6470Sstevel@tonic-gate */ 6480Sstevel@tonic-gate rv = p(&pFuncList); 6490Sstevel@tonic-gate if (rv != CKR_OK) 6500Sstevel@tonic-gate { 6510Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); 6520Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 6530Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 6540Sstevel@tonic-gate goto err; 6550Sstevel@tonic-gate } 6560Sstevel@tonic-gate 6570Sstevel@tonic-gate rv = pFuncList->C_Initialize(NULL_PTR); 6580Sstevel@tonic-gate if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) 6590Sstevel@tonic-gate { 6600Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE); 6610Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 6620Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 6630Sstevel@tonic-gate goto err; 6640Sstevel@tonic-gate } 6650Sstevel@tonic-gate 6660Sstevel@tonic-gate rv = pFuncList->C_GetInfo(&info); 6670Sstevel@tonic-gate if (rv != CKR_OK) 6680Sstevel@tonic-gate { 6690Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_GETINFO); 6700Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 6710Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 6720Sstevel@tonic-gate goto err; 6730Sstevel@tonic-gate } 6740Sstevel@tonic-gate 6750Sstevel@tonic-gate if (pk11_choose_slot() == 0) 6760Sstevel@tonic-gate goto err; 6770Sstevel@tonic-gate 6780Sstevel@tonic-gate if (global_session == CK_INVALID_HANDLE) 6790Sstevel@tonic-gate { 6800Sstevel@tonic-gate /* Open the global_session for the new process */ 6810Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 6820Sstevel@tonic-gate NULL_PTR, NULL_PTR, &global_session); 6830Sstevel@tonic-gate if (rv != CKR_OK) 6840Sstevel@tonic-gate { 6850Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_OPENSESSION); 6860Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 6870Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 6880Sstevel@tonic-gate goto err; 6890Sstevel@tonic-gate } 6900Sstevel@tonic-gate } 6910Sstevel@tonic-gate 6920Sstevel@tonic-gate /* Disable digest if C_GetOperationState is not supported since 6930Sstevel@tonic-gate * this function is required by OpenSSL digest copy function */ 6940Sstevel@tonic-gate if (pFuncList->C_GetOperationState(global_session, NULL, &ul_state_len) 6950Sstevel@tonic-gate == CKR_FUNCTION_NOT_SUPPORTED) 6960Sstevel@tonic-gate digest_count = 0; 6970Sstevel@tonic-gate 6980Sstevel@tonic-gate pk11_library_initialized = 1; 6990Sstevel@tonic-gate return 1; 7000Sstevel@tonic-gate 7010Sstevel@tonic-gate err: 7020Sstevel@tonic-gate 7030Sstevel@tonic-gate return 0; 7040Sstevel@tonic-gate } 7050Sstevel@tonic-gate 7060Sstevel@tonic-gate /* Destructor (complements the "ENGINE_pk11()" constructor) 7070Sstevel@tonic-gate */ 7080Sstevel@tonic-gate static int pk11_destroy(ENGINE *e) 7090Sstevel@tonic-gate { 7100Sstevel@tonic-gate free_PK11_LIBNAME(); 7110Sstevel@tonic-gate ERR_unload_pk11_strings(); 7120Sstevel@tonic-gate return 1; 7130Sstevel@tonic-gate } 7140Sstevel@tonic-gate 7150Sstevel@tonic-gate /* Termination function to clean up the session, the token, and 7160Sstevel@tonic-gate * the pk11 library. 7170Sstevel@tonic-gate */ 7180Sstevel@tonic-gate static int pk11_finish(ENGINE *e) 7190Sstevel@tonic-gate { 7200Sstevel@tonic-gate 7210Sstevel@tonic-gate if (pk11_dso == NULL) 7220Sstevel@tonic-gate { 7230Sstevel@tonic-gate PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED); 7240Sstevel@tonic-gate goto err; 7250Sstevel@tonic-gate } 7260Sstevel@tonic-gate 727*6847Svk199839 OPENSSL_assert(pFuncList != NULL); 7280Sstevel@tonic-gate 7290Sstevel@tonic-gate if (pk11_free_all_sessions() == 0) 7300Sstevel@tonic-gate goto err; 7310Sstevel@tonic-gate 7320Sstevel@tonic-gate pFuncList->C_CloseSession(global_session); 7330Sstevel@tonic-gate 7340Sstevel@tonic-gate /* Since we are part of a library (libcrypto.so), calling this 7350Sstevel@tonic-gate * function may have side-effects. 7360Sstevel@tonic-gate pFuncList->C_Finalize(NULL); 7370Sstevel@tonic-gate */ 7380Sstevel@tonic-gate 7390Sstevel@tonic-gate if (!DSO_free(pk11_dso)) 7400Sstevel@tonic-gate { 7410Sstevel@tonic-gate PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE); 7420Sstevel@tonic-gate goto err; 7430Sstevel@tonic-gate } 7440Sstevel@tonic-gate pk11_dso = NULL; 7450Sstevel@tonic-gate pFuncList = NULL; 7460Sstevel@tonic-gate pk11_library_initialized = 0; 7470Sstevel@tonic-gate 7480Sstevel@tonic-gate return 1; 7490Sstevel@tonic-gate 7500Sstevel@tonic-gate err: 7510Sstevel@tonic-gate return 0; 7520Sstevel@tonic-gate } 7530Sstevel@tonic-gate 7540Sstevel@tonic-gate /* Standard engine interface function to set the dynamic library path */ 7550Sstevel@tonic-gate static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) 7560Sstevel@tonic-gate { 7570Sstevel@tonic-gate int initialized = ((pk11_dso == NULL) ? 0 : 1); 7580Sstevel@tonic-gate 7590Sstevel@tonic-gate switch(cmd) 7600Sstevel@tonic-gate { 7610Sstevel@tonic-gate case PK11_CMD_SO_PATH: 7620Sstevel@tonic-gate if (p == NULL) 7630Sstevel@tonic-gate { 7640Sstevel@tonic-gate PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); 7650Sstevel@tonic-gate return 0; 7660Sstevel@tonic-gate } 7670Sstevel@tonic-gate 7680Sstevel@tonic-gate if (initialized) 7690Sstevel@tonic-gate { 7700Sstevel@tonic-gate PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED); 7710Sstevel@tonic-gate return 0; 7720Sstevel@tonic-gate } 7730Sstevel@tonic-gate 7740Sstevel@tonic-gate return set_PK11_LIBNAME((const char*)p); 7750Sstevel@tonic-gate default: 7760Sstevel@tonic-gate break; 7770Sstevel@tonic-gate } 7780Sstevel@tonic-gate 7790Sstevel@tonic-gate PK11err(PK11_F_CTRL,PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED); 7800Sstevel@tonic-gate 7810Sstevel@tonic-gate return 0; 7820Sstevel@tonic-gate } 7830Sstevel@tonic-gate 7840Sstevel@tonic-gate 7850Sstevel@tonic-gate /* Required function by the engine random interface. It does nothing here 7860Sstevel@tonic-gate */ 7870Sstevel@tonic-gate static void pk11_rand_cleanup(void) 7880Sstevel@tonic-gate { 7890Sstevel@tonic-gate return; 7900Sstevel@tonic-gate } 7910Sstevel@tonic-gate 7920Sstevel@tonic-gate static void pk11_rand_add(const void *buf, int num, double add) 7930Sstevel@tonic-gate { 7940Sstevel@tonic-gate PK11_SESSION *sp; 7950Sstevel@tonic-gate 7960Sstevel@tonic-gate if ((sp = pk11_get_session()) == NULL) 7970Sstevel@tonic-gate return; 7980Sstevel@tonic-gate 7990Sstevel@tonic-gate /* Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since 8000Sstevel@tonic-gate * the calling functions do not care anyway 8010Sstevel@tonic-gate */ 8020Sstevel@tonic-gate pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num); 8030Sstevel@tonic-gate pk11_return_session(sp); 8040Sstevel@tonic-gate 8050Sstevel@tonic-gate return; 8060Sstevel@tonic-gate } 8070Sstevel@tonic-gate 8080Sstevel@tonic-gate static void pk11_rand_seed(const void *buf, int num) 8090Sstevel@tonic-gate { 8100Sstevel@tonic-gate pk11_rand_add(buf, num, 0); 8110Sstevel@tonic-gate } 8120Sstevel@tonic-gate 8130Sstevel@tonic-gate static int pk11_rand_bytes(unsigned char *buf, int num) 8140Sstevel@tonic-gate { 8150Sstevel@tonic-gate CK_RV rv; 8160Sstevel@tonic-gate PK11_SESSION *sp; 8170Sstevel@tonic-gate 8180Sstevel@tonic-gate if ((sp = pk11_get_session()) == NULL) 8190Sstevel@tonic-gate return 0; 8200Sstevel@tonic-gate 8210Sstevel@tonic-gate rv = pFuncList->C_GenerateRandom(sp->session, buf, num); 8220Sstevel@tonic-gate if (rv != CKR_OK) 8230Sstevel@tonic-gate { 8240Sstevel@tonic-gate char tmp_buf[20]; 8250Sstevel@tonic-gate PK11err(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM); 8260Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 8270Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 8280Sstevel@tonic-gate pk11_return_session(sp); 8290Sstevel@tonic-gate return 0; 8300Sstevel@tonic-gate } 8310Sstevel@tonic-gate 8320Sstevel@tonic-gate pk11_return_session(sp); 8330Sstevel@tonic-gate return 1; 8340Sstevel@tonic-gate } 8350Sstevel@tonic-gate 8360Sstevel@tonic-gate 8370Sstevel@tonic-gate /* Required function by the engine random interface. It does nothing here 8380Sstevel@tonic-gate */ 8390Sstevel@tonic-gate static int pk11_rand_status(void) 8400Sstevel@tonic-gate { 8410Sstevel@tonic-gate return 1; 8420Sstevel@tonic-gate } 8430Sstevel@tonic-gate 844*6847Svk199839 /* 845*6847Svk199839 * Free all BIGNUM structures from PK11_SESSION. 846*6847Svk199839 */ 847*6847Svk199839 static void pk11_free_nums(PK11_SESSION *sp) 848*6847Svk199839 { 849*6847Svk199839 #ifndef OPENSSL_NO_RSA 850*6847Svk199839 if (sp->rsa_n_num != NULL) 851*6847Svk199839 BN_free(sp->rsa_n_num); 852*6847Svk199839 if (sp->rsa_e_num != NULL) 853*6847Svk199839 BN_free(sp->rsa_e_num); 854*6847Svk199839 if (sp->rsa_d_num != NULL) 855*6847Svk199839 BN_free(sp->rsa_d_num); 856*6847Svk199839 #endif 857*6847Svk199839 #ifndef OPENSSL_NO_DSA 858*6847Svk199839 if (sp->dsa_pub_num != NULL) 859*6847Svk199839 BN_free(sp->dsa_pub_num); 860*6847Svk199839 if (sp->dsa_priv_num != NULL) 861*6847Svk199839 BN_free(sp->dsa_priv_num); 862*6847Svk199839 #endif 863*6847Svk199839 #ifndef OPENSSL_NO_DH 864*6847Svk199839 if (sp->dh_priv_num != NULL) 865*6847Svk199839 BN_free(sp->dh_priv_num); 866*6847Svk199839 #endif 867*6847Svk199839 } 8680Sstevel@tonic-gate 869*6847Svk199839 /* 870*6847Svk199839 * Get new PK11_SESSION structure ready for use. Every process must have 871*6847Svk199839 * its own freelist of PK11_SESSION structures so handle fork() here 872*6847Svk199839 * by destroying the old and creating new freelist. 873*6847Svk199839 * The returned PK11_SESSION structure is disconnected from the freelist. 874*6847Svk199839 */ 8750Sstevel@tonic-gate PK11_SESSION *pk11_get_session() 8760Sstevel@tonic-gate { 8770Sstevel@tonic-gate PK11_SESSION *sp, *sp1; 8780Sstevel@tonic-gate CK_RV rv; 8790Sstevel@tonic-gate char tmp_buf[20]; 8800Sstevel@tonic-gate 8810Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 882*6847Svk199839 /* 883*6847Svk199839 * If the free list is empty, allocate new unitialized (filled 884*6847Svk199839 * with zeroes) PK11_SESSION structure otherwise return first 885*6847Svk199839 * structure from the freelist. 886*6847Svk199839 */ 8870Sstevel@tonic-gate if ((sp = free_session) == NULL) 8880Sstevel@tonic-gate { 8890Sstevel@tonic-gate if ((sp = OPENSSL_malloc(sizeof(PK11_SESSION))) == NULL) 8900Sstevel@tonic-gate { 8910Sstevel@tonic-gate PK11err(PK11_F_GET_SESSION, 8920Sstevel@tonic-gate PK11_R_MALLOC_FAILURE); 8930Sstevel@tonic-gate goto err; 8940Sstevel@tonic-gate } 8950Sstevel@tonic-gate memset(sp, 0, sizeof(PK11_SESSION)); 8960Sstevel@tonic-gate } 8970Sstevel@tonic-gate else 8980Sstevel@tonic-gate { 8990Sstevel@tonic-gate free_session = sp->next; 9000Sstevel@tonic-gate } 9010Sstevel@tonic-gate 9020Sstevel@tonic-gate if (sp->pid != 0 && sp->pid != getpid()) 9030Sstevel@tonic-gate { 904*6847Svk199839 /* 905*6847Svk199839 * We are a new process and thus need to free any inherited 9060Sstevel@tonic-gate * PK11_SESSION objects. 9070Sstevel@tonic-gate */ 9080Sstevel@tonic-gate while ((sp1 = free_session) != NULL) 9090Sstevel@tonic-gate { 9100Sstevel@tonic-gate free_session = sp1->next; 911*6847Svk199839 /* 912*6847Svk199839 * NOTE: 913*6847Svk199839 * we do not want to call pk11_free_all_sessions() 914*6847Svk199839 * here because it would close underlying PKCS11 915*6847Svk199839 * sessions and destroy objects. 916*6847Svk199839 */ 917*6847Svk199839 pk11_free_nums(sp1); 9180Sstevel@tonic-gate OPENSSL_free(sp1); 9190Sstevel@tonic-gate } 9200Sstevel@tonic-gate 9210Sstevel@tonic-gate /* Initialize the process */ 9220Sstevel@tonic-gate rv = pFuncList->C_Initialize(NULL_PTR); 9230Sstevel@tonic-gate if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) 9240Sstevel@tonic-gate { 9250Sstevel@tonic-gate PK11err(PK11_F_GET_SESSION, PK11_R_INITIALIZE); 9260Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 9270Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 9280Sstevel@tonic-gate OPENSSL_free(sp); 9290Sstevel@tonic-gate sp = NULL; 9300Sstevel@tonic-gate goto err; 9310Sstevel@tonic-gate } 9320Sstevel@tonic-gate 933*6847Svk199839 /* 934*6847Svk199839 * Choose slot here since the slot table is different on 9350Sstevel@tonic-gate * this process. 9360Sstevel@tonic-gate */ 9370Sstevel@tonic-gate if (pk11_choose_slot() == 0) 9380Sstevel@tonic-gate goto err; 9390Sstevel@tonic-gate 9400Sstevel@tonic-gate /* Open the global_session for the new process */ 9410Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 9420Sstevel@tonic-gate NULL_PTR, NULL_PTR, &global_session); 9430Sstevel@tonic-gate if (rv != CKR_OK) 9440Sstevel@tonic-gate { 9450Sstevel@tonic-gate PK11err(PK11_F_GET_SESSION, PK11_R_OPENSESSION); 9460Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 9470Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 9480Sstevel@tonic-gate OPENSSL_free(sp); 9490Sstevel@tonic-gate sp = NULL; 9500Sstevel@tonic-gate goto err; 9510Sstevel@tonic-gate } 9520Sstevel@tonic-gate 9530Sstevel@tonic-gate /* It is an inherited session and needs re-initialization. 9540Sstevel@tonic-gate */ 9550Sstevel@tonic-gate if (pk11_setup_session(sp) == 0) 9560Sstevel@tonic-gate { 9570Sstevel@tonic-gate OPENSSL_free(sp); 9580Sstevel@tonic-gate sp = NULL; 9590Sstevel@tonic-gate } 9600Sstevel@tonic-gate } 9610Sstevel@tonic-gate else if (sp->pid == 0) 9620Sstevel@tonic-gate { 9630Sstevel@tonic-gate /* It is a new session and needs initialization. 9640Sstevel@tonic-gate */ 9650Sstevel@tonic-gate if (pk11_setup_session(sp) == 0) 9660Sstevel@tonic-gate { 9670Sstevel@tonic-gate OPENSSL_free(sp); 9680Sstevel@tonic-gate sp = NULL; 9690Sstevel@tonic-gate } 9700Sstevel@tonic-gate } 9710Sstevel@tonic-gate 9720Sstevel@tonic-gate err: 973*6847Svk199839 if (sp != NULL) 9740Sstevel@tonic-gate sp->next = NULL; 9750Sstevel@tonic-gate 9760Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 9770Sstevel@tonic-gate 9780Sstevel@tonic-gate return sp; 9790Sstevel@tonic-gate } 9800Sstevel@tonic-gate 9810Sstevel@tonic-gate 9820Sstevel@tonic-gate void pk11_return_session(PK11_SESSION *sp) 9830Sstevel@tonic-gate { 9840Sstevel@tonic-gate if (sp == NULL || sp->pid != getpid()) 9850Sstevel@tonic-gate return; 9860Sstevel@tonic-gate 9870Sstevel@tonic-gate 9880Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 9890Sstevel@tonic-gate 9900Sstevel@tonic-gate sp->next = free_session; 9910Sstevel@tonic-gate free_session = sp; 9920Sstevel@tonic-gate 9930Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 9940Sstevel@tonic-gate } 9950Sstevel@tonic-gate 9960Sstevel@tonic-gate 9970Sstevel@tonic-gate /* Destroy all objects. This function is called when the engine is finished 9980Sstevel@tonic-gate */ 9990Sstevel@tonic-gate static int pk11_free_all_sessions() 10000Sstevel@tonic-gate { 10010Sstevel@tonic-gate CK_RV rv; 10020Sstevel@tonic-gate PK11_SESSION *sp = NULL; 10030Sstevel@tonic-gate pid_t mypid = getpid(); 10040Sstevel@tonic-gate int ret = 0; 10050Sstevel@tonic-gate 1006*6847Svk199839 #ifndef OPENSSL_NO_RSA 1007*6847Svk199839 (void) pk11_destroy_rsa_key_objects(NULL); 1008*6847Svk199839 #endif 1009*6847Svk199839 #ifndef OPENSSL_NO_DSA 1010*6847Svk199839 (void) pk11_destroy_dsa_key_objects(NULL); 1011*6847Svk199839 #endif 1012*6847Svk199839 #ifndef OPENSSL_NO_DH 1013*6847Svk199839 (void) pk11_destroy_dh_key_objects(NULL); 1014*6847Svk199839 #endif 1015*6847Svk199839 (void) pk11_destroy_cipher_key_objects(NULL); 10160Sstevel@tonic-gate 10170Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 10180Sstevel@tonic-gate while ((sp = free_session) != NULL) 10190Sstevel@tonic-gate { 10200Sstevel@tonic-gate if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid) 10210Sstevel@tonic-gate { 10220Sstevel@tonic-gate rv = pFuncList->C_CloseSession(sp->session); 10230Sstevel@tonic-gate if (rv != CKR_OK) 10240Sstevel@tonic-gate { 10250Sstevel@tonic-gate char tmp_buf[20]; 10260Sstevel@tonic-gate PK11err(PK11_F_FREE_ALL_SESSIONS, 10270Sstevel@tonic-gate PK11_R_CLOSESESSION); 10280Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 10290Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 10300Sstevel@tonic-gate } 10310Sstevel@tonic-gate } 10320Sstevel@tonic-gate if (sp->session_cipher != CK_INVALID_HANDLE && sp->pid == mypid) 10330Sstevel@tonic-gate { 10340Sstevel@tonic-gate rv = pFuncList->C_CloseSession(sp->session_cipher); 10350Sstevel@tonic-gate if (rv != CKR_OK) 10360Sstevel@tonic-gate { 10370Sstevel@tonic-gate char tmp_buf[20]; 10380Sstevel@tonic-gate PK11err(PK11_F_FREE_ALL_SESSIONS, 10390Sstevel@tonic-gate PK11_R_CLOSESESSION); 10400Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 10410Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 10420Sstevel@tonic-gate } 10430Sstevel@tonic-gate } 10440Sstevel@tonic-gate free_session = sp->next; 1045*6847Svk199839 pk11_free_nums(sp); 10460Sstevel@tonic-gate OPENSSL_free(sp); 10470Sstevel@tonic-gate } 10480Sstevel@tonic-gate ret = 1; 10490Sstevel@tonic-gate err: 10500Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 10510Sstevel@tonic-gate 10520Sstevel@tonic-gate return ret; 10530Sstevel@tonic-gate } 10540Sstevel@tonic-gate 10550Sstevel@tonic-gate 10560Sstevel@tonic-gate static int pk11_setup_session(PK11_SESSION *sp) 10570Sstevel@tonic-gate { 10580Sstevel@tonic-gate CK_RV rv; 10590Sstevel@tonic-gate sp->session = CK_INVALID_HANDLE; 10600Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 10610Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session); 10620Sstevel@tonic-gate if (rv == CKR_CRYPTOKI_NOT_INITIALIZED) 10630Sstevel@tonic-gate { 10640Sstevel@tonic-gate /* 10650Sstevel@tonic-gate * We are probably a child process so force the 10660Sstevel@tonic-gate * reinitialize of the session 10670Sstevel@tonic-gate */ 10680Sstevel@tonic-gate pk11_library_initialized = 0; 10690Sstevel@tonic-gate (void) pk11_library_init(NULL); 10700Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 10710Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session); 10720Sstevel@tonic-gate } 10730Sstevel@tonic-gate if (rv != CKR_OK) 10740Sstevel@tonic-gate { 10750Sstevel@tonic-gate char tmp_buf[20]; 10760Sstevel@tonic-gate PK11err(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION); 10770Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 10780Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 10790Sstevel@tonic-gate return 0; 10800Sstevel@tonic-gate } 10810Sstevel@tonic-gate 10820Sstevel@tonic-gate sp->session_cipher = CK_INVALID_HANDLE; 10830Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 10840Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session_cipher); 10850Sstevel@tonic-gate if (rv != CKR_OK) 10860Sstevel@tonic-gate { 10870Sstevel@tonic-gate char tmp_buf[20]; 10880Sstevel@tonic-gate 10890Sstevel@tonic-gate (void) pFuncList->C_CloseSession(sp->session); 10900Sstevel@tonic-gate sp->session = CK_INVALID_HANDLE; 10910Sstevel@tonic-gate 10920Sstevel@tonic-gate PK11err(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION); 10930Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 10940Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 10950Sstevel@tonic-gate return 0; 10960Sstevel@tonic-gate } 10970Sstevel@tonic-gate 10980Sstevel@tonic-gate sp->pid = getpid(); 10990Sstevel@tonic-gate sp->rsa_pub_key = CK_INVALID_HANDLE; 11000Sstevel@tonic-gate sp->rsa_priv_key = CK_INVALID_HANDLE; 11010Sstevel@tonic-gate sp->dsa_pub_key = CK_INVALID_HANDLE; 11020Sstevel@tonic-gate sp->dsa_priv_key = CK_INVALID_HANDLE; 11030Sstevel@tonic-gate sp->dh_key = CK_INVALID_HANDLE; 11040Sstevel@tonic-gate sp->cipher_key = CK_INVALID_HANDLE; 1105*6847Svk199839 #ifndef OPENSSL_NO_RSA 1106*6847Svk199839 sp->rsa_pub = NULL; 1107*6847Svk199839 sp->rsa_n_num = NULL; 1108*6847Svk199839 sp->rsa_e_num = NULL; 1109*6847Svk199839 sp->rsa_priv = NULL; 1110*6847Svk199839 sp->rsa_d_num = NULL; 1111*6847Svk199839 #endif 1112*6847Svk199839 #ifndef OPENSSL_NO_DSA 1113*6847Svk199839 sp->dsa_pub = NULL; 1114*6847Svk199839 sp->dsa_pub_num = NULL; 1115*6847Svk199839 sp->dsa_priv = NULL; 1116*6847Svk199839 sp->dsa_priv_num = NULL; 1117*6847Svk199839 #endif 1118*6847Svk199839 #ifndef OPENSSL_NO_DH 11190Sstevel@tonic-gate sp->dh = NULL; 1120*6847Svk199839 sp->dh_priv_num = NULL; 1121*6847Svk199839 #endif 11220Sstevel@tonic-gate sp->encrypt = -1; 11230Sstevel@tonic-gate 11240Sstevel@tonic-gate return 1; 11250Sstevel@tonic-gate } 11260Sstevel@tonic-gate 1127*6847Svk199839 #ifndef OPENSSL_NO_RSA 1128*6847Svk199839 /* Destroy RSA public key from single session. */ 1129*6847Svk199839 int pk11_destroy_rsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) 1130*6847Svk199839 { 1131*6847Svk199839 int ret = 0; 1132*6847Svk199839 1133*6847Svk199839 if (sp->rsa_pub_key != CK_INVALID_HANDLE) 1134*6847Svk199839 { 1135*6847Svk199839 TRY_OBJ_DESTROY(sp->session, sp->rsa_pub_key, ret, uselock); 1136*6847Svk199839 sp->rsa_pub_key = CK_INVALID_HANDLE; 1137*6847Svk199839 sp->rsa_pub = NULL; 1138*6847Svk199839 if (sp->rsa_n_num != NULL) 1139*6847Svk199839 BN_free(sp->rsa_n_num); 1140*6847Svk199839 sp->rsa_n_num = NULL; 1141*6847Svk199839 if (sp->rsa_e_num != NULL) 1142*6847Svk199839 BN_free(sp->rsa_e_num); 1143*6847Svk199839 sp->rsa_e_num = NULL; 1144*6847Svk199839 } 1145*6847Svk199839 1146*6847Svk199839 return (ret); 1147*6847Svk199839 } 1148*6847Svk199839 1149*6847Svk199839 /* Destroy RSA private key from single session. */ 1150*6847Svk199839 int pk11_destroy_rsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) 11510Sstevel@tonic-gate { 11520Sstevel@tonic-gate int ret = 0; 1153*6847Svk199839 1154*6847Svk199839 if (sp->rsa_priv_key != CK_INVALID_HANDLE) 1155*6847Svk199839 { 1156*6847Svk199839 TRY_OBJ_DESTROY(sp->session, sp->rsa_priv_key, ret, uselock); 1157*6847Svk199839 sp->rsa_priv_key = CK_INVALID_HANDLE; 1158*6847Svk199839 sp->rsa_priv = NULL; 1159*6847Svk199839 if (sp->rsa_d_num != NULL) 1160*6847Svk199839 BN_free(sp->rsa_d_num); 1161*6847Svk199839 sp->rsa_d_num = NULL; 1162*6847Svk199839 } 1163*6847Svk199839 1164*6847Svk199839 return (ret); 1165*6847Svk199839 } 1166*6847Svk199839 1167*6847Svk199839 1168*6847Svk199839 /* 1169*6847Svk199839 * Destroy RSA key object wrapper. 1170*6847Svk199839 * 1171*6847Svk199839 * arg0: pointer to PKCS#11 engine session structure 1172*6847Svk199839 * if session is NULL, try to destroy all objects in the free list 1173*6847Svk199839 */ 1174*6847Svk199839 int pk11_destroy_rsa_key_objects(PK11_SESSION *session) 1175*6847Svk199839 { 1176*6847Svk199839 int ret = 1; 11770Sstevel@tonic-gate PK11_SESSION *sp = NULL; 11780Sstevel@tonic-gate PK11_SESSION *local_free_session; 1179*6847Svk199839 CK_BBOOL uselock = TRUE; 11800Sstevel@tonic-gate 1181*6847Svk199839 if (session != NULL) 11820Sstevel@tonic-gate local_free_session = session; 11830Sstevel@tonic-gate else 1184*6847Svk199839 { 1185*6847Svk199839 CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 11860Sstevel@tonic-gate local_free_session = free_session; 1187*6847Svk199839 uselock = FALSE; 1188*6847Svk199839 } 11890Sstevel@tonic-gate 1190*6847Svk199839 /* 1191*6847Svk199839 * go through the list of sessions and delete key objects 1192*6847Svk199839 */ 11930Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 11940Sstevel@tonic-gate { 11950Sstevel@tonic-gate local_free_session = sp->next; 11960Sstevel@tonic-gate 1197*6847Svk199839 /* 1198*6847Svk199839 * Do not terminate list traversal if one of the 1199*6847Svk199839 * destroy operations fails. 1200*6847Svk199839 */ 1201*6847Svk199839 if (pk11_destroy_rsa_object_pub(sp, uselock) == 0) 12020Sstevel@tonic-gate { 1203*6847Svk199839 ret = 0; 1204*6847Svk199839 continue; 12050Sstevel@tonic-gate } 1206*6847Svk199839 if (pk11_destroy_rsa_object_priv(sp, uselock) == 0) 1207*6847Svk199839 { 1208*6847Svk199839 ret = 0; 1209*6847Svk199839 continue; 1210*6847Svk199839 } 1211*6847Svk199839 } 12120Sstevel@tonic-gate 1213*6847Svk199839 if (session == NULL) 1214*6847Svk199839 CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 12150Sstevel@tonic-gate 12160Sstevel@tonic-gate return ret; 12170Sstevel@tonic-gate } 1218*6847Svk199839 #endif 12190Sstevel@tonic-gate 1220*6847Svk199839 #ifndef OPENSSL_NO_DSA 1221*6847Svk199839 /* Destroy DSA public key from single session. */ 1222*6847Svk199839 int pk11_destroy_dsa_object_pub(PK11_SESSION *sp, CK_BBOOL uselock) 12230Sstevel@tonic-gate { 12240Sstevel@tonic-gate int ret = 0; 1225*6847Svk199839 1226*6847Svk199839 if (sp->dsa_pub_key != CK_INVALID_HANDLE) 1227*6847Svk199839 { 1228*6847Svk199839 TRY_OBJ_DESTROY(sp->session, sp->dsa_pub_key, ret, uselock); 1229*6847Svk199839 sp->dsa_pub_key = CK_INVALID_HANDLE; 1230*6847Svk199839 sp->dsa_pub = NULL; 1231*6847Svk199839 if (sp->dsa_pub_num != NULL) 1232*6847Svk199839 BN_free(sp->dsa_pub_num); 1233*6847Svk199839 sp->dsa_pub_num = NULL; 1234*6847Svk199839 } 1235*6847Svk199839 1236*6847Svk199839 return (ret); 1237*6847Svk199839 } 1238*6847Svk199839 1239*6847Svk199839 /* Destroy DSA private key from single session. */ 1240*6847Svk199839 int pk11_destroy_dsa_object_priv(PK11_SESSION *sp, CK_BBOOL uselock) 1241*6847Svk199839 { 1242*6847Svk199839 int ret = 0; 1243*6847Svk199839 1244*6847Svk199839 if (sp->dsa_priv_key != CK_INVALID_HANDLE) 1245*6847Svk199839 { 1246*6847Svk199839 TRY_OBJ_DESTROY(sp->session, sp->dsa_priv_key, ret, uselock); 1247*6847Svk199839 sp->dsa_priv_key = CK_INVALID_HANDLE; 1248*6847Svk199839 sp->dsa_priv = NULL; 1249*6847Svk199839 if (sp->dsa_priv_num != NULL) 1250*6847Svk199839 BN_free(sp->dsa_priv_num); 1251*6847Svk199839 sp->dsa_priv_num = NULL; 1252*6847Svk199839 } 1253*6847Svk199839 1254*6847Svk199839 return (ret); 1255*6847Svk199839 } 1256*6847Svk199839 1257*6847Svk199839 /* 1258*6847Svk199839 * Destroy DSA key object wrapper. 1259*6847Svk199839 * 1260*6847Svk199839 * arg0: pointer to PKCS#11 engine session structure 1261*6847Svk199839 * if session is NULL, try to destroy all objects in the free list 1262*6847Svk199839 */ 1263*6847Svk199839 int pk11_destroy_dsa_key_objects(PK11_SESSION *session) 1264*6847Svk199839 { 1265*6847Svk199839 int ret = 1; 12660Sstevel@tonic-gate PK11_SESSION *sp = NULL; 12670Sstevel@tonic-gate PK11_SESSION *local_free_session; 1268*6847Svk199839 CK_BBOOL uselock = TRUE; 12690Sstevel@tonic-gate 1270*6847Svk199839 if (session != NULL) 12710Sstevel@tonic-gate local_free_session = session; 12720Sstevel@tonic-gate else 1273*6847Svk199839 { 1274*6847Svk199839 CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 12750Sstevel@tonic-gate local_free_session = free_session; 1276*6847Svk199839 uselock = FALSE; 1277*6847Svk199839 } 1278*6847Svk199839 1279*6847Svk199839 /* 1280*6847Svk199839 * go through the list of sessions and delete key objects 1281*6847Svk199839 */ 12820Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 12830Sstevel@tonic-gate { 12840Sstevel@tonic-gate local_free_session = sp->next; 12850Sstevel@tonic-gate 1286*6847Svk199839 /* 1287*6847Svk199839 * Do not terminate list traversal if one of the 1288*6847Svk199839 * destroy operations fails. 1289*6847Svk199839 */ 1290*6847Svk199839 if (pk11_destroy_dsa_object_pub(sp, uselock) == 0) 12910Sstevel@tonic-gate { 1292*6847Svk199839 ret = 0; 1293*6847Svk199839 continue; 12940Sstevel@tonic-gate } 1295*6847Svk199839 if (pk11_destroy_dsa_object_priv(sp, uselock) == 0) 1296*6847Svk199839 { 1297*6847Svk199839 ret = 0; 1298*6847Svk199839 continue; 1299*6847Svk199839 } 13000Sstevel@tonic-gate } 1301*6847Svk199839 1302*6847Svk199839 if (session == NULL) 1303*6847Svk199839 CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 13040Sstevel@tonic-gate 13050Sstevel@tonic-gate return ret; 13060Sstevel@tonic-gate } 1307*6847Svk199839 #endif 1308*6847Svk199839 1309*6847Svk199839 #ifndef OPENSSL_NO_DH 1310*6847Svk199839 /* Destroy DH key from single session. */ 1311*6847Svk199839 int pk11_destroy_dh_object(PK11_SESSION *sp, CK_BBOOL uselock) 1312*6847Svk199839 { 1313*6847Svk199839 int ret = 0; 1314*6847Svk199839 1315*6847Svk199839 if (sp->dh_key != CK_INVALID_HANDLE) 1316*6847Svk199839 { 1317*6847Svk199839 TRY_OBJ_DESTROY(sp->session, sp->dh_key, ret, uselock); 1318*6847Svk199839 sp->dh_key = CK_INVALID_HANDLE; 1319*6847Svk199839 sp->dh = NULL; 1320*6847Svk199839 if (sp->dh_priv_num != NULL) 1321*6847Svk199839 BN_free(sp->dh_priv_num); 1322*6847Svk199839 sp->dh_priv_num = NULL; 1323*6847Svk199839 } 1324*6847Svk199839 1325*6847Svk199839 return (ret); 1326*6847Svk199839 } 1327*6847Svk199839 1328*6847Svk199839 /* 1329*6847Svk199839 * Destroy DH key object wrapper. 1330*6847Svk199839 * 1331*6847Svk199839 * arg0: pointer to PKCS#11 engine session structure 1332*6847Svk199839 * if session is NULL, try to destroy all objects in the free list 1333*6847Svk199839 */ 1334*6847Svk199839 int pk11_destroy_dh_key_objects(PK11_SESSION *session) 1335*6847Svk199839 { 1336*6847Svk199839 int ret = 1; 1337*6847Svk199839 PK11_SESSION *sp = NULL; 1338*6847Svk199839 PK11_SESSION *local_free_session; 1339*6847Svk199839 CK_BBOOL uselock = TRUE; 1340*6847Svk199839 1341*6847Svk199839 if (session != NULL) 1342*6847Svk199839 local_free_session = session; 1343*6847Svk199839 else 1344*6847Svk199839 { 1345*6847Svk199839 CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 1346*6847Svk199839 local_free_session = free_session; 1347*6847Svk199839 uselock = FALSE; 1348*6847Svk199839 } 1349*6847Svk199839 1350*6847Svk199839 while ((sp = local_free_session) != NULL) 1351*6847Svk199839 { 1352*6847Svk199839 local_free_session = sp->next; 1353*6847Svk199839 1354*6847Svk199839 /* 1355*6847Svk199839 * Do not terminate list traversal if one of the 1356*6847Svk199839 * destroy operations fails. 1357*6847Svk199839 */ 1358*6847Svk199839 if (pk11_destroy_dh_object(sp, uselock) == 0) 1359*6847Svk199839 { 1360*6847Svk199839 ret = 0; 1361*6847Svk199839 continue; 1362*6847Svk199839 } 1363*6847Svk199839 } 1364*6847Svk199839 err: 1365*6847Svk199839 if (session == NULL) 1366*6847Svk199839 CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 1367*6847Svk199839 1368*6847Svk199839 return ret; 1369*6847Svk199839 } 1370*6847Svk199839 #endif 1371*6847Svk199839 13720Sstevel@tonic-gate 13730Sstevel@tonic-gate static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh) 13740Sstevel@tonic-gate { 13750Sstevel@tonic-gate CK_RV rv; 13760Sstevel@tonic-gate rv = pFuncList->C_DestroyObject(session, oh); 13770Sstevel@tonic-gate if (rv != CKR_OK) 13780Sstevel@tonic-gate { 13790Sstevel@tonic-gate char tmp_buf[20]; 13800Sstevel@tonic-gate PK11err(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT); 13810Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 13820Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", 13830Sstevel@tonic-gate tmp_buf); 13840Sstevel@tonic-gate return 0; 13850Sstevel@tonic-gate } 13860Sstevel@tonic-gate 13870Sstevel@tonic-gate return 1; 13880Sstevel@tonic-gate } 13890Sstevel@tonic-gate 13900Sstevel@tonic-gate 13910Sstevel@tonic-gate /* Symmetric ciphers and digests support functions 13920Sstevel@tonic-gate */ 13930Sstevel@tonic-gate 13940Sstevel@tonic-gate static int 13950Sstevel@tonic-gate cipher_nid_to_pk11(int nid) 13960Sstevel@tonic-gate { 13970Sstevel@tonic-gate int i; 13980Sstevel@tonic-gate 13990Sstevel@tonic-gate for (i = 0; i < PK11_CIPHER_MAX; i++) 14000Sstevel@tonic-gate if (ciphers[i].nid == nid) 14010Sstevel@tonic-gate return (ciphers[i].id); 14020Sstevel@tonic-gate return (-1); 14030Sstevel@tonic-gate } 14040Sstevel@tonic-gate 14050Sstevel@tonic-gate static int 14060Sstevel@tonic-gate pk11_usable_ciphers(const int **nids) 14070Sstevel@tonic-gate { 14080Sstevel@tonic-gate if (cipher_count > 0) 14090Sstevel@tonic-gate *nids = cipher_nids; 14100Sstevel@tonic-gate else 14110Sstevel@tonic-gate *nids = NULL; 14120Sstevel@tonic-gate return (cipher_count); 14130Sstevel@tonic-gate } 14140Sstevel@tonic-gate 14150Sstevel@tonic-gate static int 14160Sstevel@tonic-gate pk11_usable_digests(const int **nids) 14170Sstevel@tonic-gate { 14180Sstevel@tonic-gate if (digest_count > 0) 14190Sstevel@tonic-gate *nids = digest_nids; 14200Sstevel@tonic-gate else 14210Sstevel@tonic-gate *nids = NULL; 14220Sstevel@tonic-gate return (digest_count); 14230Sstevel@tonic-gate } 14240Sstevel@tonic-gate 14250Sstevel@tonic-gate static int 14260Sstevel@tonic-gate pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, 14270Sstevel@tonic-gate const unsigned char *iv, int enc) 14280Sstevel@tonic-gate { 14290Sstevel@tonic-gate CK_RV rv; 14304320Sjp161948 CK_MECHANISM mech; 14310Sstevel@tonic-gate int index; 14320Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; 14330Sstevel@tonic-gate PK11_SESSION *sp; 14340Sstevel@tonic-gate PK11_CIPHER *pcp; 14350Sstevel@tonic-gate char tmp_buf[20]; 14360Sstevel@tonic-gate 14370Sstevel@tonic-gate state->sp = NULL; 14380Sstevel@tonic-gate 14390Sstevel@tonic-gate index = cipher_nid_to_pk11(ctx->cipher->nid); 14400Sstevel@tonic-gate if (index < 0 || index >= PK11_CIPHER_MAX) 14410Sstevel@tonic-gate return 0; 14420Sstevel@tonic-gate 14430Sstevel@tonic-gate pcp = &ciphers[index]; 14440Sstevel@tonic-gate if (ctx->cipher->iv_len > pcp->ivmax || ctx->key_len != pcp->key_len) 14450Sstevel@tonic-gate return 0; 14460Sstevel@tonic-gate 14470Sstevel@tonic-gate if ((sp = pk11_get_session()) == NULL) 14480Sstevel@tonic-gate return 0; 14490Sstevel@tonic-gate 14504320Sjp161948 /* if applicable, the mechanism parameter is used for IV */ 14514320Sjp161948 mech.mechanism = pcp->mech_type; 14524320Sjp161948 mech.pParameter = NULL; 14534320Sjp161948 mech.ulParameterLen = 0; 14544320Sjp161948 14550Sstevel@tonic-gate /* The key object is destroyed here if it is not the current key 14560Sstevel@tonic-gate */ 1457*6847Svk199839 (void) check_new_cipher_key(sp, key); 14580Sstevel@tonic-gate 14590Sstevel@tonic-gate /* If the key is the same and the encryption is also the same, 1460*6847Svk199839 * then just reuse it. However, we must not forget to reinitialize the 1461*6847Svk199839 * context that was finalized in pk11_cipher_cleanup(). 14620Sstevel@tonic-gate */ 14630Sstevel@tonic-gate if (sp->cipher_key != CK_INVALID_HANDLE && sp->encrypt == ctx->encrypt) 14640Sstevel@tonic-gate { 14650Sstevel@tonic-gate state->sp = sp; 1466*6847Svk199839 if (pk11_init_symmetric(ctx, sp, &mech) == 0) 1467*6847Svk199839 return (0); 1468*6847Svk199839 1469*6847Svk199839 return (1); 14700Sstevel@tonic-gate } 14710Sstevel@tonic-gate 14720Sstevel@tonic-gate /* Check if the key has been invalidated. If so, a new key object 14730Sstevel@tonic-gate * needs to be created. 14740Sstevel@tonic-gate */ 14750Sstevel@tonic-gate if (sp->cipher_key == CK_INVALID_HANDLE) 14760Sstevel@tonic-gate { 14770Sstevel@tonic-gate sp->cipher_key = pk11_get_cipher_key( 14780Sstevel@tonic-gate ctx, key, pcp->key_type, sp); 14790Sstevel@tonic-gate } 14800Sstevel@tonic-gate 14810Sstevel@tonic-gate if (sp->encrypt != ctx->encrypt && sp->encrypt != -1) 14820Sstevel@tonic-gate { 14830Sstevel@tonic-gate /* The previous encryption/decryption 14840Sstevel@tonic-gate * is different. Need to terminate the previous 14850Sstevel@tonic-gate * active encryption/decryption here 14860Sstevel@tonic-gate */ 14870Sstevel@tonic-gate if (!pk11_cipher_final(sp)) 14880Sstevel@tonic-gate { 14890Sstevel@tonic-gate pk11_return_session(sp); 14900Sstevel@tonic-gate return 0; 14910Sstevel@tonic-gate } 14920Sstevel@tonic-gate } 14930Sstevel@tonic-gate 14940Sstevel@tonic-gate if (sp->cipher_key == CK_INVALID_HANDLE) 14950Sstevel@tonic-gate { 14960Sstevel@tonic-gate pk11_return_session(sp); 14970Sstevel@tonic-gate return 0; 14980Sstevel@tonic-gate } 14990Sstevel@tonic-gate 1500*6847Svk199839 /* now initialize the context with a new key */ 1501*6847Svk199839 if (pk11_init_symmetric(ctx, sp, &mech) == 0) 1502*6847Svk199839 return (0); 15030Sstevel@tonic-gate 15040Sstevel@tonic-gate sp->encrypt = ctx->encrypt; 15050Sstevel@tonic-gate state->sp = sp; 15060Sstevel@tonic-gate 15070Sstevel@tonic-gate return 1; 15080Sstevel@tonic-gate } 15090Sstevel@tonic-gate 15100Sstevel@tonic-gate /* When reusing the same key in an encryption/decryption session for a 15110Sstevel@tonic-gate * decryption/encryption session, we need to close the active session 15120Sstevel@tonic-gate * and recreate a new one. Note that the key is in the global session so 15130Sstevel@tonic-gate * that it needs not be recreated. 15140Sstevel@tonic-gate * 15150Sstevel@tonic-gate * It is more appropriate to use C_En/DecryptFinish here. At the time of this 15160Sstevel@tonic-gate * development, these two functions in the PKCS#11 libraries used return 15170Sstevel@tonic-gate * unexpected errors when passing in 0 length output. It may be a good 15180Sstevel@tonic-gate * idea to try them again if performance is a problem here and fix 15190Sstevel@tonic-gate * C_En/DecryptFinial if there are bugs there causing the problem. 15200Sstevel@tonic-gate */ 15210Sstevel@tonic-gate static int 15220Sstevel@tonic-gate pk11_cipher_final(PK11_SESSION *sp) 15230Sstevel@tonic-gate { 15240Sstevel@tonic-gate CK_RV rv; 15250Sstevel@tonic-gate char tmp_buf[20]; 15260Sstevel@tonic-gate 15270Sstevel@tonic-gate rv = pFuncList->C_CloseSession(sp->session_cipher); 15280Sstevel@tonic-gate if (rv != CKR_OK) 15290Sstevel@tonic-gate { 15300Sstevel@tonic-gate PK11err(PK11_F_CIPHER_FINAL, PK11_R_CLOSESESSION); 15310Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 15320Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 15330Sstevel@tonic-gate return 0; 15340Sstevel@tonic-gate } 15350Sstevel@tonic-gate 15360Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 15370Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session_cipher); 15380Sstevel@tonic-gate if (rv != CKR_OK) 15390Sstevel@tonic-gate { 15400Sstevel@tonic-gate PK11err(PK11_F_CIPHER_FINAL, PK11_R_OPENSESSION); 15410Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 15420Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 15430Sstevel@tonic-gate return 0; 15440Sstevel@tonic-gate } 15450Sstevel@tonic-gate 15460Sstevel@tonic-gate return 1; 15470Sstevel@tonic-gate } 15480Sstevel@tonic-gate 15490Sstevel@tonic-gate /* An engine interface function. The calling function allocates sufficient 15500Sstevel@tonic-gate * memory for the output buffer "out" to hold the results */ 15510Sstevel@tonic-gate static int 15520Sstevel@tonic-gate pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 15530Sstevel@tonic-gate const unsigned char *in, unsigned int inl) 15540Sstevel@tonic-gate { 15550Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; 15560Sstevel@tonic-gate PK11_SESSION *sp; 15570Sstevel@tonic-gate CK_RV rv; 15580Sstevel@tonic-gate unsigned long outl = inl; 15590Sstevel@tonic-gate char tmp_buf[20]; 15600Sstevel@tonic-gate 15610Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 15620Sstevel@tonic-gate return 0; 15630Sstevel@tonic-gate 15640Sstevel@tonic-gate sp = (PK11_SESSION *) state->sp; 15650Sstevel@tonic-gate 15660Sstevel@tonic-gate if (!inl) 15670Sstevel@tonic-gate return 1; 15680Sstevel@tonic-gate 15690Sstevel@tonic-gate /* RC4 is the only stream cipher we support */ 15700Sstevel@tonic-gate if (ctx->cipher->nid != NID_rc4 && (inl % ctx->cipher->block_size) != 0) 15710Sstevel@tonic-gate return 0; 15720Sstevel@tonic-gate 15730Sstevel@tonic-gate if (ctx->encrypt) 15740Sstevel@tonic-gate { 15750Sstevel@tonic-gate rv = pFuncList->C_EncryptUpdate(sp->session_cipher, 15760Sstevel@tonic-gate (unsigned char *)in, inl, out, &outl); 15770Sstevel@tonic-gate 15780Sstevel@tonic-gate if (rv != CKR_OK) 15790Sstevel@tonic-gate { 15800Sstevel@tonic-gate PK11err(PK11_F_CIPHER_DO_CIPHER, 15810Sstevel@tonic-gate PK11_R_ENCRYPTUPDATE); 15820Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 15830Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 15840Sstevel@tonic-gate return 0; 15850Sstevel@tonic-gate } 15860Sstevel@tonic-gate } 15870Sstevel@tonic-gate else 15880Sstevel@tonic-gate { 15890Sstevel@tonic-gate rv = pFuncList->C_DecryptUpdate(sp->session_cipher, 15900Sstevel@tonic-gate (unsigned char *)in, inl, out, &outl); 15910Sstevel@tonic-gate 15920Sstevel@tonic-gate if (rv != CKR_OK) 15930Sstevel@tonic-gate { 15940Sstevel@tonic-gate PK11err(PK11_F_CIPHER_DO_CIPHER, 15950Sstevel@tonic-gate PK11_R_DECRYPTUPDATE); 15960Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 15970Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 15980Sstevel@tonic-gate return 0; 15990Sstevel@tonic-gate } 16000Sstevel@tonic-gate } 16010Sstevel@tonic-gate 16020Sstevel@tonic-gate /* for DES_CBC, DES3_CBC, AES_CBC, and RC4, the output size is always 16030Sstevel@tonic-gate * the same size of input 16040Sstevel@tonic-gate * The application has guaranteed to call the block ciphers with 16050Sstevel@tonic-gate * correctly aligned buffers. 16060Sstevel@tonic-gate */ 16070Sstevel@tonic-gate if (inl != outl) 16080Sstevel@tonic-gate return 0; 16090Sstevel@tonic-gate 16100Sstevel@tonic-gate return 1; 16110Sstevel@tonic-gate } 16120Sstevel@tonic-gate 1613*6847Svk199839 /* 1614*6847Svk199839 * Return the session to the pool. Calling C_EncryptFinal() and 1615*6847Svk199839 * C_DecryptFinal() here is the right thing because in 1616*6847Svk199839 * EVP_DecryptFinal_ex(), engine's do_cipher() is not even called, and in 1617*6847Svk199839 * EVP_EncryptFinal_ex() it is called but the engine can't find out that 1618*6847Svk199839 * it's the finalizing call. We wouldn't necessarily have to finalize the 1619*6847Svk199839 * context here since reinitializing it with C_(Encrypt|Decrypt)Init() 1620*6847Svk199839 * should be fine but for the sake of correctness, let's do it. Some 1621*6847Svk199839 * implementations might leak memory if the previously used context is 1622*6847Svk199839 * initialized without finalizing it first. 16230Sstevel@tonic-gate */ 16240Sstevel@tonic-gate static int 16250Sstevel@tonic-gate pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx) 16260Sstevel@tonic-gate { 1627*6847Svk199839 CK_RV rv; 1628*6847Svk199839 CK_ULONG len; 1629*6847Svk199839 char tmp_buf[20]; 1630*6847Svk199839 CK_BYTE buf[EVP_MAX_BLOCK_LENGTH]; 16310Sstevel@tonic-gate PK11_CIPHER_STATE *state = ctx->cipher_data; 16320Sstevel@tonic-gate 16330Sstevel@tonic-gate if (state != NULL && state->sp != NULL) 16340Sstevel@tonic-gate { 1635*6847Svk199839 /* 1636*6847Svk199839 * We are not interested in the data here, we just need to get 1637*6847Svk199839 * rid of the context. 1638*6847Svk199839 */ 1639*6847Svk199839 if (ctx->encrypt) 1640*6847Svk199839 rv = pFuncList->C_EncryptFinal( 1641*6847Svk199839 state->sp->session_cipher, buf, &len); 1642*6847Svk199839 else 1643*6847Svk199839 rv = pFuncList->C_DecryptFinal( 1644*6847Svk199839 state->sp->session_cipher, buf, &len); 1645*6847Svk199839 1646*6847Svk199839 if (rv != CKR_OK) 1647*6847Svk199839 { 1648*6847Svk199839 PK11err(PK11_F_CIPHER_CLEANUP, ctx->encrypt ? 1649*6847Svk199839 PK11_R_ENCRYPTFINAL : PK11_R_DECRYPTFINAL); 1650*6847Svk199839 snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1651*6847Svk199839 ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1652*6847Svk199839 pk11_return_session(state->sp); 1653*6847Svk199839 return (0); 1654*6847Svk199839 } 1655*6847Svk199839 16560Sstevel@tonic-gate pk11_return_session(state->sp); 16570Sstevel@tonic-gate state->sp = NULL; 16580Sstevel@tonic-gate } 16590Sstevel@tonic-gate 1660*6847Svk199839 return (1); 1661*6847Svk199839 } 1662*6847Svk199839 1663*6847Svk199839 /* 1664*6847Svk199839 * Init context for encryption or decryption using a symmetric key. 1665*6847Svk199839 */ 1666*6847Svk199839 static int pk11_init_symmetric(EVP_CIPHER_CTX *ctx, PK11_SESSION *sp, 1667*6847Svk199839 CK_MECHANISM_PTR pmech) 1668*6847Svk199839 { 1669*6847Svk199839 CK_RV rv; 1670*6847Svk199839 char tmp_buf[20]; 1671*6847Svk199839 1672*6847Svk199839 if (ctx->cipher->iv_len > 0) 1673*6847Svk199839 { 1674*6847Svk199839 /* 1675*6847Svk199839 * We expect pmech->mechanism to be already set and 1676*6847Svk199839 * pParameter/ulParameterLen initialized to NULL/0 before 1677*6847Svk199839 * pk11_init_symetric() is called. 1678*6847Svk199839 */ 1679*6847Svk199839 OPENSSL_assert(pmech->mechanism != NULL); 1680*6847Svk199839 OPENSSL_assert(pmech->pParameter == NULL); 1681*6847Svk199839 OPENSSL_assert(pmech->ulParameterLen == 0); 1682*6847Svk199839 pmech->pParameter = (void *) ctx->iv; 1683*6847Svk199839 pmech->ulParameterLen = ctx->cipher->iv_len; 1684*6847Svk199839 } 1685*6847Svk199839 1686*6847Svk199839 /* If we get here, the encryption needs to be reinitialized */ 1687*6847Svk199839 if (ctx->encrypt) 1688*6847Svk199839 rv = pFuncList->C_EncryptInit(sp->session_cipher, pmech, 1689*6847Svk199839 sp->cipher_key); 1690*6847Svk199839 else 1691*6847Svk199839 rv = pFuncList->C_DecryptInit(sp->session_cipher, pmech, 1692*6847Svk199839 sp->cipher_key); 1693*6847Svk199839 1694*6847Svk199839 if (rv != CKR_OK) 1695*6847Svk199839 { 1696*6847Svk199839 PK11err(PK11_F_CIPHER_INIT, ctx->encrypt ? 1697*6847Svk199839 PK11_R_ENCRYPTINIT : PK11_R_DECRYPTINIT); 1698*6847Svk199839 snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1699*6847Svk199839 ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1700*6847Svk199839 pk11_return_session(sp); 1701*6847Svk199839 return (0); 1702*6847Svk199839 } 1703*6847Svk199839 1704*6847Svk199839 return (1); 17050Sstevel@tonic-gate } 17060Sstevel@tonic-gate 17070Sstevel@tonic-gate /* Registered by the ENGINE when used to find out how to deal with 17080Sstevel@tonic-gate * a particular NID in the ENGINE. This says what we'll do at the 17090Sstevel@tonic-gate * top level - note, that list is restricted by what we answer with 17100Sstevel@tonic-gate */ 17110Sstevel@tonic-gate static int 17120Sstevel@tonic-gate pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 17130Sstevel@tonic-gate const int **nids, int nid) 17140Sstevel@tonic-gate { 17150Sstevel@tonic-gate if (!cipher) 17160Sstevel@tonic-gate return (pk11_usable_ciphers(nids)); 17170Sstevel@tonic-gate 17180Sstevel@tonic-gate switch (nid) 17190Sstevel@tonic-gate { 17200Sstevel@tonic-gate case NID_des_ede3_cbc: 17210Sstevel@tonic-gate *cipher = &pk11_3des_cbc; 17220Sstevel@tonic-gate break; 17230Sstevel@tonic-gate case NID_des_cbc: 17240Sstevel@tonic-gate *cipher = &pk11_des_cbc; 17250Sstevel@tonic-gate break; 17260Sstevel@tonic-gate case NID_aes_128_cbc: 17270Sstevel@tonic-gate *cipher = &pk11_aes_cbc; 17280Sstevel@tonic-gate break; 17290Sstevel@tonic-gate case NID_rc4: 17300Sstevel@tonic-gate *cipher = &pk11_rc4; 17310Sstevel@tonic-gate break; 17320Sstevel@tonic-gate default: 17330Sstevel@tonic-gate *cipher = NULL; 17340Sstevel@tonic-gate break; 17350Sstevel@tonic-gate } 17360Sstevel@tonic-gate return (*cipher != NULL); 17370Sstevel@tonic-gate } 17380Sstevel@tonic-gate 17390Sstevel@tonic-gate static int 17400Sstevel@tonic-gate pk11_engine_digests(ENGINE *e, const EVP_MD **digest, 17410Sstevel@tonic-gate const int **nids, int nid) 17420Sstevel@tonic-gate { 17430Sstevel@tonic-gate if (!digest) 17440Sstevel@tonic-gate return (pk11_usable_digests(nids)); 17450Sstevel@tonic-gate 17460Sstevel@tonic-gate switch (nid) 17470Sstevel@tonic-gate { 17480Sstevel@tonic-gate case NID_md5: 17490Sstevel@tonic-gate *digest = &pk11_md5; 17500Sstevel@tonic-gate break; 17510Sstevel@tonic-gate case NID_sha1: 17520Sstevel@tonic-gate *digest = &pk11_sha1; 17530Sstevel@tonic-gate break; 17540Sstevel@tonic-gate default: 17550Sstevel@tonic-gate *digest = NULL; 17560Sstevel@tonic-gate break; 17570Sstevel@tonic-gate } 17580Sstevel@tonic-gate return (*digest != NULL); 17590Sstevel@tonic-gate } 17600Sstevel@tonic-gate 17610Sstevel@tonic-gate 17620Sstevel@tonic-gate /* Create a secret key object in a PKCS#11 session 17630Sstevel@tonic-gate */ 17640Sstevel@tonic-gate static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, 17650Sstevel@tonic-gate const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp) 17660Sstevel@tonic-gate { 17670Sstevel@tonic-gate CK_RV rv; 17680Sstevel@tonic-gate CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; 17690Sstevel@tonic-gate CK_OBJECT_CLASS obj_key = CKO_SECRET_KEY; 17700Sstevel@tonic-gate CK_ULONG ul_key_attr_count = 6; 17710Sstevel@tonic-gate char tmp_buf[20]; 17720Sstevel@tonic-gate 17730Sstevel@tonic-gate CK_ATTRIBUTE a_key_template[] = 17740Sstevel@tonic-gate { 17750Sstevel@tonic-gate {CKA_CLASS, (void*) NULL, sizeof(CK_OBJECT_CLASS)}, 17760Sstevel@tonic-gate {CKA_KEY_TYPE, (void*) NULL, sizeof(CK_KEY_TYPE)}, 17770Sstevel@tonic-gate {CKA_TOKEN, &false, sizeof(false)}, 17780Sstevel@tonic-gate {CKA_ENCRYPT, &true, sizeof(true)}, 17790Sstevel@tonic-gate {CKA_DECRYPT, &true, sizeof(true)}, 17800Sstevel@tonic-gate {CKA_VALUE, (void*) NULL, 0}, 17810Sstevel@tonic-gate }; 17820Sstevel@tonic-gate 17830Sstevel@tonic-gate /* Create secret key object in global_session. All other sessions 17840Sstevel@tonic-gate * can use the key handles. Here is why: 17850Sstevel@tonic-gate * OpenSSL will call EncryptInit and EncryptUpdate using a secret key. 17860Sstevel@tonic-gate * It may then call DecryptInit and DecryptUpdate using the same key. 17870Sstevel@tonic-gate * To use the same key object, we need to call EncryptFinal with 17880Sstevel@tonic-gate * a 0 length message. Currently, this does not work for 3DES 17890Sstevel@tonic-gate * mechanism. To get around this problem, we close the session and 17900Sstevel@tonic-gate * then create a new session to use the same key object. When a session 17910Sstevel@tonic-gate * is closed, all the object handles will be invalid. Thus, create key 17920Sstevel@tonic-gate * objects in a global session, an individual session may be closed to 17930Sstevel@tonic-gate * terminate the active operation. 17940Sstevel@tonic-gate */ 17950Sstevel@tonic-gate CK_SESSION_HANDLE session = global_session; 17960Sstevel@tonic-gate a_key_template[0].pValue = &obj_key; 17970Sstevel@tonic-gate a_key_template[1].pValue = &key_type; 17980Sstevel@tonic-gate a_key_template[5].pValue = (void *) key; 17990Sstevel@tonic-gate a_key_template[5].ulValueLen = (unsigned long) ctx->key_len; 18000Sstevel@tonic-gate 18014602Sjp161948 rv = pFuncList->C_CreateObject(session, 18024602Sjp161948 a_key_template, ul_key_attr_count, &h_key); 18030Sstevel@tonic-gate if (rv != CKR_OK) 18040Sstevel@tonic-gate { 18054602Sjp161948 PK11err(PK11_F_GET_CIPHER_KEY, PK11_R_CREATEOBJECT); 18060Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 18070Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 18080Sstevel@tonic-gate goto err; 18090Sstevel@tonic-gate } 18100Sstevel@tonic-gate 18110Sstevel@tonic-gate /* Save the key information used in this session. 18120Sstevel@tonic-gate * The max can be saved is PK11_KEY_LEN_MAX. 18130Sstevel@tonic-gate */ 18140Sstevel@tonic-gate sp->key_len = ctx->key_len > PK11_KEY_LEN_MAX ? 18150Sstevel@tonic-gate PK11_KEY_LEN_MAX : ctx->key_len; 18160Sstevel@tonic-gate memcpy(sp->key, key, sp->key_len); 18170Sstevel@tonic-gate err: 18180Sstevel@tonic-gate 18190Sstevel@tonic-gate return h_key; 18200Sstevel@tonic-gate } 18210Sstevel@tonic-gate 18220Sstevel@tonic-gate static int 18230Sstevel@tonic-gate md_nid_to_pk11(int nid) 18240Sstevel@tonic-gate { 18250Sstevel@tonic-gate int i; 18260Sstevel@tonic-gate 18270Sstevel@tonic-gate for (i = 0; i < PK11_DIGEST_MAX; i++) 18280Sstevel@tonic-gate if (digests[i].nid == nid) 18290Sstevel@tonic-gate return (digests[i].id); 18300Sstevel@tonic-gate return (-1); 18310Sstevel@tonic-gate } 18320Sstevel@tonic-gate 18330Sstevel@tonic-gate static int 18340Sstevel@tonic-gate pk11_digest_init(EVP_MD_CTX *ctx) 18350Sstevel@tonic-gate { 18360Sstevel@tonic-gate CK_RV rv; 18374320Sjp161948 CK_MECHANISM mech; 18380Sstevel@tonic-gate int index; 18390Sstevel@tonic-gate PK11_SESSION *sp; 18400Sstevel@tonic-gate PK11_DIGEST *pdp; 18410Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; 18420Sstevel@tonic-gate 18430Sstevel@tonic-gate state->sp = NULL; 18440Sstevel@tonic-gate 18450Sstevel@tonic-gate index = md_nid_to_pk11(ctx->digest->type); 18460Sstevel@tonic-gate if (index < 0 || index >= PK11_DIGEST_MAX) 18470Sstevel@tonic-gate return 0; 18480Sstevel@tonic-gate 18490Sstevel@tonic-gate pdp = &digests[index]; 18500Sstevel@tonic-gate if ((sp = pk11_get_session()) == NULL) 18510Sstevel@tonic-gate return 0; 18520Sstevel@tonic-gate 18534320Sjp161948 /* at present, no parameter is needed for supported digests */ 18544320Sjp161948 mech.mechanism = pdp->mech_type; 18554320Sjp161948 mech.pParameter = NULL; 18564320Sjp161948 mech.ulParameterLen = 0; 18574320Sjp161948 18584320Sjp161948 rv = pFuncList->C_DigestInit(sp->session, &mech); 18590Sstevel@tonic-gate 18600Sstevel@tonic-gate if (rv != CKR_OK) 18610Sstevel@tonic-gate { 18620Sstevel@tonic-gate char tmp_buf[20]; 18630Sstevel@tonic-gate PK11err(PK11_F_DIGEST_INIT, PK11_R_DIGESTINIT); 18640Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 18650Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 18660Sstevel@tonic-gate pk11_return_session(sp); 18670Sstevel@tonic-gate return 0; 18680Sstevel@tonic-gate } 18690Sstevel@tonic-gate 18700Sstevel@tonic-gate state->sp = sp; 18710Sstevel@tonic-gate 18720Sstevel@tonic-gate return 1; 18730Sstevel@tonic-gate } 18740Sstevel@tonic-gate 18750Sstevel@tonic-gate static int 18762139Sjp161948 pk11_digest_update(EVP_MD_CTX *ctx,const void *data,size_t count) 18770Sstevel@tonic-gate { 18780Sstevel@tonic-gate CK_RV rv; 18790Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; 18800Sstevel@tonic-gate 18810Sstevel@tonic-gate /* 0 length message will cause a failure in C_DigestFinal */ 18820Sstevel@tonic-gate if (count == 0) 18830Sstevel@tonic-gate return 1; 18840Sstevel@tonic-gate 18850Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 18860Sstevel@tonic-gate return 0; 18870Sstevel@tonic-gate 18880Sstevel@tonic-gate rv = pFuncList->C_DigestUpdate(state->sp->session, (CK_BYTE *) data, 18890Sstevel@tonic-gate count); 18900Sstevel@tonic-gate 18910Sstevel@tonic-gate if (rv != CKR_OK) 18920Sstevel@tonic-gate { 18930Sstevel@tonic-gate char tmp_buf[20]; 18940Sstevel@tonic-gate PK11err(PK11_F_DIGEST_UPDATE, PK11_R_DIGESTUPDATE); 18950Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 18960Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 18970Sstevel@tonic-gate pk11_return_session(state->sp); 18980Sstevel@tonic-gate state->sp = NULL; 18990Sstevel@tonic-gate return 0; 19000Sstevel@tonic-gate } 19010Sstevel@tonic-gate 19020Sstevel@tonic-gate return 1; 19030Sstevel@tonic-gate } 19040Sstevel@tonic-gate 19050Sstevel@tonic-gate static int 19060Sstevel@tonic-gate pk11_digest_final(EVP_MD_CTX *ctx,unsigned char *md) 19070Sstevel@tonic-gate { 19080Sstevel@tonic-gate CK_RV rv; 19090Sstevel@tonic-gate unsigned long len; 19100Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; 19110Sstevel@tonic-gate len = ctx->digest->md_size; 19120Sstevel@tonic-gate 19130Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 19140Sstevel@tonic-gate return 0; 19150Sstevel@tonic-gate 19160Sstevel@tonic-gate rv = pFuncList->C_DigestFinal(state->sp->session, md, &len); 19170Sstevel@tonic-gate 19180Sstevel@tonic-gate if (rv != CKR_OK) 19190Sstevel@tonic-gate { 19200Sstevel@tonic-gate char tmp_buf[20]; 19210Sstevel@tonic-gate PK11err(PK11_F_DIGEST_FINAL, PK11_R_DIGESTFINAL); 19220Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 19230Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 19240Sstevel@tonic-gate pk11_return_session(state->sp); 19250Sstevel@tonic-gate state->sp = NULL; 19260Sstevel@tonic-gate return 0; 19270Sstevel@tonic-gate } 19280Sstevel@tonic-gate 19290Sstevel@tonic-gate if (ctx->digest->md_size != len) 19300Sstevel@tonic-gate return 0; 19310Sstevel@tonic-gate 19320Sstevel@tonic-gate /* Final is called and digest is returned, so return the session 19330Sstevel@tonic-gate * to the pool 19340Sstevel@tonic-gate */ 19350Sstevel@tonic-gate pk11_return_session(state->sp); 19360Sstevel@tonic-gate state->sp = NULL; 19370Sstevel@tonic-gate 19380Sstevel@tonic-gate return 1; 19390Sstevel@tonic-gate } 19400Sstevel@tonic-gate 19410Sstevel@tonic-gate static int 19420Sstevel@tonic-gate pk11_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from) 19430Sstevel@tonic-gate { 19440Sstevel@tonic-gate CK_RV rv; 19450Sstevel@tonic-gate int ret = 0; 19460Sstevel@tonic-gate PK11_CIPHER_STATE *state, *state_to; 19470Sstevel@tonic-gate CK_BYTE_PTR pstate = NULL; 19480Sstevel@tonic-gate CK_ULONG ul_state_len; 19490Sstevel@tonic-gate char tmp_buf[20]; 19500Sstevel@tonic-gate 19510Sstevel@tonic-gate /* The copy-from state */ 19520Sstevel@tonic-gate state = (PK11_CIPHER_STATE *) from->md_data; 19530Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 19540Sstevel@tonic-gate goto err; 19550Sstevel@tonic-gate 19560Sstevel@tonic-gate /* Initialize the copy-to state */ 19570Sstevel@tonic-gate if (!pk11_digest_init(to)) 19580Sstevel@tonic-gate goto err; 19590Sstevel@tonic-gate state_to = (PK11_CIPHER_STATE *) to->md_data; 19600Sstevel@tonic-gate 19610Sstevel@tonic-gate /* Get the size of the operation state of the copy-from session */ 19620Sstevel@tonic-gate rv = pFuncList->C_GetOperationState(state->sp->session, NULL, 19630Sstevel@tonic-gate &ul_state_len); 19640Sstevel@tonic-gate 19650Sstevel@tonic-gate if (rv != CKR_OK) 19660Sstevel@tonic-gate { 19670Sstevel@tonic-gate PK11err(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE); 19680Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 19690Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 19700Sstevel@tonic-gate goto err; 19710Sstevel@tonic-gate } 19720Sstevel@tonic-gate if (ul_state_len == 0) 19730Sstevel@tonic-gate { 19740Sstevel@tonic-gate goto err; 19750Sstevel@tonic-gate } 19760Sstevel@tonic-gate 19770Sstevel@tonic-gate pstate = OPENSSL_malloc(ul_state_len); 19780Sstevel@tonic-gate if (pstate == NULL) 19790Sstevel@tonic-gate { 1980*6847Svk199839 PK11err(PK11_F_DIGEST_COPY, PK11_R_MALLOC_FAILURE); 19810Sstevel@tonic-gate goto err; 19820Sstevel@tonic-gate } 19830Sstevel@tonic-gate 19840Sstevel@tonic-gate /* Get the operation state of the copy-from session */ 19850Sstevel@tonic-gate rv = pFuncList->C_GetOperationState(state->sp->session, pstate, 19860Sstevel@tonic-gate &ul_state_len); 19870Sstevel@tonic-gate 19880Sstevel@tonic-gate if (rv != CKR_OK) 19890Sstevel@tonic-gate { 19900Sstevel@tonic-gate PK11err(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE); 19910Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 19920Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 19930Sstevel@tonic-gate goto err; 19940Sstevel@tonic-gate } 19950Sstevel@tonic-gate 19960Sstevel@tonic-gate /* Set the operation state of the copy-to session */ 19970Sstevel@tonic-gate rv = pFuncList->C_SetOperationState(state_to->sp->session, pstate, 19980Sstevel@tonic-gate ul_state_len, 0, 0); 19990Sstevel@tonic-gate 20000Sstevel@tonic-gate if (rv != CKR_OK) 20010Sstevel@tonic-gate { 20020Sstevel@tonic-gate PK11err(PK11_F_DIGEST_COPY, PK11_R_SET_OPERATION_STATE); 20030Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 20040Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 20050Sstevel@tonic-gate goto err; 20060Sstevel@tonic-gate } 20070Sstevel@tonic-gate 20080Sstevel@tonic-gate ret = 1; 20090Sstevel@tonic-gate err: 20100Sstevel@tonic-gate if (pstate != NULL) 20110Sstevel@tonic-gate OPENSSL_free(pstate); 20120Sstevel@tonic-gate 20130Sstevel@tonic-gate return ret; 20140Sstevel@tonic-gate } 20150Sstevel@tonic-gate 20160Sstevel@tonic-gate /* Return any pending session state to the pool */ 20170Sstevel@tonic-gate static int 20180Sstevel@tonic-gate pk11_digest_cleanup(EVP_MD_CTX *ctx) 20190Sstevel@tonic-gate { 20200Sstevel@tonic-gate PK11_CIPHER_STATE *state = ctx->md_data; 20214602Sjp161948 unsigned char buf[EVP_MAX_MD_SIZE]; 20220Sstevel@tonic-gate 20230Sstevel@tonic-gate if (state != NULL && state->sp != NULL) 20240Sstevel@tonic-gate { 20254602Sjp161948 /* 20264602Sjp161948 * If state->sp is not NULL then pk11_digest_final() has not 20274602Sjp161948 * been called yet. We must call it now to free any memory 20284602Sjp161948 * that might have been allocated in the token when 20294602Sjp161948 * pk11_digest_init() was called. 20304602Sjp161948 */ 20314602Sjp161948 pk11_digest_final(ctx,buf); 20320Sstevel@tonic-gate pk11_return_session(state->sp); 20330Sstevel@tonic-gate state->sp = NULL; 20340Sstevel@tonic-gate } 20350Sstevel@tonic-gate 20360Sstevel@tonic-gate return 1; 20370Sstevel@tonic-gate } 20380Sstevel@tonic-gate 2039*6847Svk199839 /* 2040*6847Svk199839 * Check if the new key is the same as the key object in the session. 20410Sstevel@tonic-gate * If the key is the same, no need to create a new key object. Otherwise, 2042*6847Svk199839 * the old key object needs to be destroyed and a new one will be created. 2043*6847Svk199839 * Return 1 for cache hit, 0 for cache miss. 20440Sstevel@tonic-gate */ 2045*6847Svk199839 static int check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key) 20460Sstevel@tonic-gate { 20470Sstevel@tonic-gate if (memcmp(sp->key, key, sp->key_len) != 0) 2048*6847Svk199839 { 20490Sstevel@tonic-gate pk11_destroy_cipher_key_objects(sp); 2050*6847Svk199839 return (0); 2051*6847Svk199839 } 2052*6847Svk199839 return (1); 20530Sstevel@tonic-gate } 20540Sstevel@tonic-gate 20550Sstevel@tonic-gate /* Destroy one or more secret key objects. 20560Sstevel@tonic-gate */ 20570Sstevel@tonic-gate static int pk11_destroy_cipher_key_objects(PK11_SESSION *session) 20580Sstevel@tonic-gate { 20590Sstevel@tonic-gate int ret = 0; 20600Sstevel@tonic-gate PK11_SESSION *sp = NULL; 20610Sstevel@tonic-gate PK11_SESSION *local_free_session; 20620Sstevel@tonic-gate 20630Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 20640Sstevel@tonic-gate if (session) 20650Sstevel@tonic-gate local_free_session = session; 20660Sstevel@tonic-gate else 20670Sstevel@tonic-gate local_free_session = free_session; 20680Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 20690Sstevel@tonic-gate { 20700Sstevel@tonic-gate local_free_session = sp->next; 20710Sstevel@tonic-gate 20720Sstevel@tonic-gate if (sp->cipher_key != CK_INVALID_HANDLE) 20730Sstevel@tonic-gate { 20740Sstevel@tonic-gate /* The secret key object is created in the 20750Sstevel@tonic-gate * global_session. See pk11_get_cipher_key 20760Sstevel@tonic-gate */ 20770Sstevel@tonic-gate if (pk11_destroy_object(global_session, 20780Sstevel@tonic-gate sp->cipher_key) == 0) 20790Sstevel@tonic-gate goto err; 20800Sstevel@tonic-gate sp->cipher_key = CK_INVALID_HANDLE; 20810Sstevel@tonic-gate } 20820Sstevel@tonic-gate } 20830Sstevel@tonic-gate ret = 1; 20840Sstevel@tonic-gate err: 20850Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 20860Sstevel@tonic-gate 20870Sstevel@tonic-gate return ret; 20880Sstevel@tonic-gate } 20890Sstevel@tonic-gate 20900Sstevel@tonic-gate 20910Sstevel@tonic-gate /* 20920Sstevel@tonic-gate * Required mechanisms 20930Sstevel@tonic-gate * 20940Sstevel@tonic-gate * CKM_RSA_X_509 20950Sstevel@tonic-gate * CKM_RSA_PKCS 20960Sstevel@tonic-gate * CKM_DSA 20970Sstevel@tonic-gate * 20980Sstevel@tonic-gate * As long as these required mechanisms are met, it will return success. 20990Sstevel@tonic-gate * Otherwise, it will return failure and the engine initialization will fail. 21000Sstevel@tonic-gate * The application will then decide whether to use another engine or 21010Sstevel@tonic-gate * no engine. 21020Sstevel@tonic-gate * 21030Sstevel@tonic-gate * Symmetric ciphers optionally supported 21040Sstevel@tonic-gate * 21050Sstevel@tonic-gate * CKM_DES3_CBC 21060Sstevel@tonic-gate * CKM_DES_CBC 21070Sstevel@tonic-gate * CKM_AES_CBC 21080Sstevel@tonic-gate * CKM_RC4 21090Sstevel@tonic-gate * 21100Sstevel@tonic-gate * Digests optionally supported 21110Sstevel@tonic-gate * 21120Sstevel@tonic-gate * CKM_MD5 21130Sstevel@tonic-gate * CKM_SHA_1 21140Sstevel@tonic-gate */ 21150Sstevel@tonic-gate 21160Sstevel@tonic-gate static int 21170Sstevel@tonic-gate pk11_choose_slot() 21180Sstevel@tonic-gate { 21190Sstevel@tonic-gate CK_SLOT_ID_PTR pSlotList = NULL_PTR; 21200Sstevel@tonic-gate CK_ULONG ulSlotCount = 0; 21210Sstevel@tonic-gate CK_MECHANISM_INFO mech_info; 21220Sstevel@tonic-gate CK_TOKEN_INFO token_info; 21230Sstevel@tonic-gate int i; 21240Sstevel@tonic-gate CK_RV rv; 21250Sstevel@tonic-gate CK_SLOT_ID best_slot_sofar; 21260Sstevel@tonic-gate CK_BBOOL found_candidate_slot = CK_FALSE; 21270Sstevel@tonic-gate int slot_n_cipher = 0; 21280Sstevel@tonic-gate int slot_n_digest = 0; 21290Sstevel@tonic-gate CK_SLOT_ID current_slot = 0; 21300Sstevel@tonic-gate int current_slot_n_cipher = 0; 21310Sstevel@tonic-gate int current_slot_n_digest = 0; 21320Sstevel@tonic-gate 21330Sstevel@tonic-gate int local_cipher_nids[PK11_CIPHER_MAX]; 21340Sstevel@tonic-gate int local_digest_nids[PK11_DIGEST_MAX]; 21350Sstevel@tonic-gate char tmp_buf[20]; 21360Sstevel@tonic-gate int retval = 0; 21370Sstevel@tonic-gate 21380Sstevel@tonic-gate /* Get slot list for memory alloction */ 21390Sstevel@tonic-gate rv = pFuncList->C_GetSlotList(0, NULL_PTR, &ulSlotCount); 21400Sstevel@tonic-gate 21410Sstevel@tonic-gate if (rv != CKR_OK) 21420Sstevel@tonic-gate { 21430Sstevel@tonic-gate PK11err(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST); 21440Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 21450Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 21460Sstevel@tonic-gate return retval; 21470Sstevel@tonic-gate } 21480Sstevel@tonic-gate 21490Sstevel@tonic-gate if (ulSlotCount == 0) 21500Sstevel@tonic-gate { 21510Sstevel@tonic-gate PK11err(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST); 21520Sstevel@tonic-gate return retval; 21530Sstevel@tonic-gate } 21540Sstevel@tonic-gate 21550Sstevel@tonic-gate pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); 21560Sstevel@tonic-gate 21570Sstevel@tonic-gate if (pSlotList == NULL) 21580Sstevel@tonic-gate { 2159*6847Svk199839 PK11err(PK11_F_CHOOSE_SLOT, PK11_R_MALLOC_FAILURE); 21600Sstevel@tonic-gate return retval; 21610Sstevel@tonic-gate } 21620Sstevel@tonic-gate 21630Sstevel@tonic-gate /* Get the slot list for processing */ 21640Sstevel@tonic-gate rv = pFuncList->C_GetSlotList(0, pSlotList, &ulSlotCount); 21650Sstevel@tonic-gate if (rv != CKR_OK) 21660Sstevel@tonic-gate { 21670Sstevel@tonic-gate PK11err(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST); 21680Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 21690Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 21700Sstevel@tonic-gate OPENSSL_free(pSlotList); 21710Sstevel@tonic-gate return retval; 21720Sstevel@tonic-gate } 21730Sstevel@tonic-gate 21740Sstevel@tonic-gate for (i = 0; i < ulSlotCount; i++) 21750Sstevel@tonic-gate { 21760Sstevel@tonic-gate CK_BBOOL slot_has_rsa = CK_FALSE; 21770Sstevel@tonic-gate CK_BBOOL slot_has_dsa = CK_FALSE; 21780Sstevel@tonic-gate CK_BBOOL slot_has_dh = CK_FALSE; 21790Sstevel@tonic-gate current_slot = pSlotList[i]; 21800Sstevel@tonic-gate current_slot_n_cipher = 0; 21810Sstevel@tonic-gate current_slot_n_digest = 0; 21820Sstevel@tonic-gate memset(local_cipher_nids, 0, sizeof(local_cipher_nids)); 21830Sstevel@tonic-gate memset(local_digest_nids, 0, sizeof(local_digest_nids)); 21840Sstevel@tonic-gate 21850Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 21860Sstevel@tonic-gate fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: checking slot: %d\n", 21870Sstevel@tonic-gate current_slot); 21880Sstevel@tonic-gate #endif 21890Sstevel@tonic-gate /* Check if slot has random support. */ 21900Sstevel@tonic-gate rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); 21910Sstevel@tonic-gate if (rv != CKR_OK) 21920Sstevel@tonic-gate continue; 21930Sstevel@tonic-gate 21940Sstevel@tonic-gate if (token_info.flags & CKF_RNG) 21950Sstevel@tonic-gate pk11_have_random = CK_TRUE; 2196*6847Svk199839 #ifndef OPENSSL_NO_RSA 21970Sstevel@tonic-gate /* 21980Sstevel@tonic-gate * Check if this slot is capable of signing and 21990Sstevel@tonic-gate * verifying with CKM_RSA_PKCS. 22000Sstevel@tonic-gate */ 22010Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS, 22020Sstevel@tonic-gate &mech_info); 22030Sstevel@tonic-gate 22040Sstevel@tonic-gate if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && 22050Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY))) 22060Sstevel@tonic-gate { 22070Sstevel@tonic-gate /* 22080Sstevel@tonic-gate * Check if this slot is capable of encryption, 22090Sstevel@tonic-gate * decryption, sign, and verify with CKM_RSA_X_509. 22100Sstevel@tonic-gate */ 22110Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, 22120Sstevel@tonic-gate CKM_RSA_X_509, &mech_info); 22130Sstevel@tonic-gate 22140Sstevel@tonic-gate if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && 22150Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY) && 22160Sstevel@tonic-gate (mech_info.flags & CKF_ENCRYPT) && 22170Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY_RECOVER) && 22180Sstevel@tonic-gate (mech_info.flags & CKF_DECRYPT))) 22190Sstevel@tonic-gate slot_has_rsa = CK_TRUE; 22200Sstevel@tonic-gate } 2221*6847Svk199839 #endif 2222*6847Svk199839 #ifndef OPENSSL_NO_DSA 22230Sstevel@tonic-gate /* 22240Sstevel@tonic-gate * Check if this slot is capable of signing and 22250Sstevel@tonic-gate * verifying with CKM_DSA. 22260Sstevel@tonic-gate */ 22270Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA, 22280Sstevel@tonic-gate &mech_info); 22290Sstevel@tonic-gate if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && 22300Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY))) 22310Sstevel@tonic-gate slot_has_dsa = CK_TRUE; 2232*6847Svk199839 #endif 2233*6847Svk199839 #ifndef OPENSSL_NO_DH 22340Sstevel@tonic-gate /* 22350Sstevel@tonic-gate * Check if this slot is capable of DH key generataion and 22360Sstevel@tonic-gate * derivation. 22370Sstevel@tonic-gate */ 22380Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, 22390Sstevel@tonic-gate CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info); 22400Sstevel@tonic-gate 22410Sstevel@tonic-gate if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR)) 22420Sstevel@tonic-gate { 22430Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, 22440Sstevel@tonic-gate CKM_DH_PKCS_DERIVE, &mech_info); 22450Sstevel@tonic-gate if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE)) 22460Sstevel@tonic-gate slot_has_dh = CK_TRUE; 22470Sstevel@tonic-gate } 2248*6847Svk199839 #endif 22490Sstevel@tonic-gate if (!found_candidate_slot && 22500Sstevel@tonic-gate (slot_has_rsa || slot_has_dsa || slot_has_dh)) 22510Sstevel@tonic-gate { 22520Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 22530Sstevel@tonic-gate fprintf(stderr, 22540Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: potential slot: %d\n", 22550Sstevel@tonic-gate current_slot); 22560Sstevel@tonic-gate #endif 22570Sstevel@tonic-gate best_slot_sofar = current_slot; 22580Sstevel@tonic-gate pk11_have_rsa = slot_has_rsa; 22590Sstevel@tonic-gate pk11_have_dsa = slot_has_dsa; 22600Sstevel@tonic-gate pk11_have_dh = slot_has_dh; 22610Sstevel@tonic-gate found_candidate_slot = CK_TRUE; 22620Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 22630Sstevel@tonic-gate fprintf(stderr, 22640Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: best so far slot: %d\n", 22650Sstevel@tonic-gate best_slot_sofar); 22660Sstevel@tonic-gate #endif 22670Sstevel@tonic-gate } 22680Sstevel@tonic-gate 22690Sstevel@tonic-gate /* Count symmetric cipher support. */ 22700Sstevel@tonic-gate if (!pk11_count_symmetric_cipher(current_slot, CKM_DES_CBC, 22710Sstevel@tonic-gate ¤t_slot_n_cipher, local_cipher_nids, 22720Sstevel@tonic-gate PK11_DES_CBC)) 22730Sstevel@tonic-gate continue; 22740Sstevel@tonic-gate if (!pk11_count_symmetric_cipher(current_slot, CKM_DES3_CBC, 22750Sstevel@tonic-gate ¤t_slot_n_cipher, local_cipher_nids, 22760Sstevel@tonic-gate PK11_DES3_CBC)) 22770Sstevel@tonic-gate continue; 22780Sstevel@tonic-gate if (!pk11_count_symmetric_cipher(current_slot, CKM_AES_CBC, 22790Sstevel@tonic-gate ¤t_slot_n_cipher, local_cipher_nids, 22800Sstevel@tonic-gate PK11_AES_CBC)) 22810Sstevel@tonic-gate continue; 22820Sstevel@tonic-gate if (!pk11_count_symmetric_cipher(current_slot, CKM_RC4, 22830Sstevel@tonic-gate ¤t_slot_n_cipher, local_cipher_nids, 22840Sstevel@tonic-gate PK11_RC4)) 22850Sstevel@tonic-gate continue; 22860Sstevel@tonic-gate 22870Sstevel@tonic-gate /* Count digest support */ 22880Sstevel@tonic-gate if (!pk11_count_digest(current_slot, CKM_MD5, 22890Sstevel@tonic-gate ¤t_slot_n_digest, local_digest_nids, 22900Sstevel@tonic-gate PK11_MD5)) 22910Sstevel@tonic-gate continue; 22920Sstevel@tonic-gate if (!pk11_count_digest(current_slot, CKM_SHA_1, 22930Sstevel@tonic-gate ¤t_slot_n_digest, local_digest_nids, 22940Sstevel@tonic-gate PK11_SHA1)) 22950Sstevel@tonic-gate continue; 22960Sstevel@tonic-gate 22970Sstevel@tonic-gate /* 22980Sstevel@tonic-gate * If the current slot supports more ciphers/digests than 22990Sstevel@tonic-gate * the previous best one we change the current best to this one. 23000Sstevel@tonic-gate * otherwise leave it where it is. 23010Sstevel@tonic-gate */ 23020Sstevel@tonic-gate if (((current_slot_n_cipher > slot_n_cipher) && 23030Sstevel@tonic-gate (current_slot_n_digest > slot_n_digest)) && 23040Sstevel@tonic-gate ((slot_has_rsa == pk11_have_rsa) && 23050Sstevel@tonic-gate (slot_has_dsa == pk11_have_dsa) && 23060Sstevel@tonic-gate (slot_has_dh == pk11_have_dh))) 23070Sstevel@tonic-gate { 23080Sstevel@tonic-gate best_slot_sofar = current_slot; 23090Sstevel@tonic-gate slot_n_cipher = current_slot_n_cipher; 23100Sstevel@tonic-gate slot_n_digest = current_slot_n_digest; 23110Sstevel@tonic-gate 23120Sstevel@tonic-gate memcpy(cipher_nids, local_cipher_nids, 23130Sstevel@tonic-gate sizeof(local_cipher_nids)); 23140Sstevel@tonic-gate memcpy(digest_nids, local_digest_nids, 23150Sstevel@tonic-gate sizeof(local_digest_nids)); 23160Sstevel@tonic-gate } 23170Sstevel@tonic-gate 23180Sstevel@tonic-gate } 23190Sstevel@tonic-gate 23200Sstevel@tonic-gate if (found_candidate_slot) 23210Sstevel@tonic-gate { 23220Sstevel@tonic-gate cipher_count = slot_n_cipher; 23230Sstevel@tonic-gate digest_count = slot_n_digest; 23240Sstevel@tonic-gate SLOTID = best_slot_sofar; 23250Sstevel@tonic-gate retval = 1; 23260Sstevel@tonic-gate } 23270Sstevel@tonic-gate else 23280Sstevel@tonic-gate { 23290Sstevel@tonic-gate cipher_count = 0; 23300Sstevel@tonic-gate digest_count = 0; 23310Sstevel@tonic-gate } 23320Sstevel@tonic-gate 23330Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 23340Sstevel@tonic-gate fprintf(stderr, 23350Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: choose slot: %d\n", SLOTID); 23360Sstevel@tonic-gate fprintf(stderr, 23370Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: pk11_have_rsa %d\n", pk11_have_rsa); 23380Sstevel@tonic-gate fprintf(stderr, 23390Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: pk11_have_dsa %d\n", pk11_have_dsa); 23400Sstevel@tonic-gate fprintf(stderr, 23410Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: pk11_have_dh %d\n", pk11_have_dh); 23420Sstevel@tonic-gate fprintf(stderr, 23430Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: pk11_have_random %d\n", pk11_have_random); 23440Sstevel@tonic-gate #endif /* DEBUG_SLOT_SELECTION */ 23450Sstevel@tonic-gate 2346*6847Svk199839 if (pSlotList != NULL) 2347*6847Svk199839 OPENSSL_free(pSlotList); 23480Sstevel@tonic-gate 23490Sstevel@tonic-gate return retval; 23500Sstevel@tonic-gate } 23510Sstevel@tonic-gate 23520Sstevel@tonic-gate static int pk11_count_symmetric_cipher(int slot_id, CK_MECHANISM_TYPE mech, 23530Sstevel@tonic-gate int *current_slot_n_cipher, int *local_cipher_nids, int id) 23540Sstevel@tonic-gate { 23550Sstevel@tonic-gate CK_MECHANISM_INFO mech_info; 23560Sstevel@tonic-gate CK_RV rv; 23570Sstevel@tonic-gate 23580Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(slot_id, mech, &mech_info); 23590Sstevel@tonic-gate 23600Sstevel@tonic-gate if (rv != CKR_OK) 23610Sstevel@tonic-gate return 0; 23620Sstevel@tonic-gate 23630Sstevel@tonic-gate if ((mech_info.flags & CKF_ENCRYPT) && 23640Sstevel@tonic-gate (mech_info.flags & CKF_DECRYPT)) 23650Sstevel@tonic-gate { 23660Sstevel@tonic-gate local_cipher_nids[(*current_slot_n_cipher)++] = ciphers[id].nid; 23670Sstevel@tonic-gate } 23680Sstevel@tonic-gate 23690Sstevel@tonic-gate return 1; 23700Sstevel@tonic-gate } 23710Sstevel@tonic-gate 23720Sstevel@tonic-gate 23730Sstevel@tonic-gate static int pk11_count_digest(int slot_id, CK_MECHANISM_TYPE mech, 23740Sstevel@tonic-gate int *current_slot_n_digest, int *local_digest_nids, int id) 23750Sstevel@tonic-gate { 23760Sstevel@tonic-gate CK_MECHANISM_INFO mech_info; 23770Sstevel@tonic-gate CK_RV rv; 23780Sstevel@tonic-gate 23790Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(slot_id, mech, &mech_info); 23800Sstevel@tonic-gate 23810Sstevel@tonic-gate if (rv != CKR_OK) 23820Sstevel@tonic-gate return 0; 23830Sstevel@tonic-gate 23840Sstevel@tonic-gate if (mech_info.flags & CKF_DIGEST) 23850Sstevel@tonic-gate { 23860Sstevel@tonic-gate local_digest_nids[(*current_slot_n_digest)++] = digests[id].nid; 23870Sstevel@tonic-gate } 23880Sstevel@tonic-gate 23890Sstevel@tonic-gate return 1; 23900Sstevel@tonic-gate } 23910Sstevel@tonic-gate #endif 23920Sstevel@tonic-gate #endif 2393