1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate 6*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 7*0Sstevel@tonic-gate 8*0Sstevel@tonic-gate /* crypto/engine/hw_pk11.c */ 9*0Sstevel@tonic-gate /* This product includes software developed by the OpenSSL Project for 10*0Sstevel@tonic-gate * use in the OpenSSL Toolkit (http://www.openssl.org/). 11*0Sstevel@tonic-gate * 12*0Sstevel@tonic-gate * This project also referenced hw_pkcs11-0.9.7b.patch written by 13*0Sstevel@tonic-gate * Afchine Madjlessi. 14*0Sstevel@tonic-gate */ 15*0Sstevel@tonic-gate /* ==================================================================== 16*0Sstevel@tonic-gate * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. 17*0Sstevel@tonic-gate * 18*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 19*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 20*0Sstevel@tonic-gate * are met: 21*0Sstevel@tonic-gate * 22*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 23*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 24*0Sstevel@tonic-gate * 25*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 26*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in 27*0Sstevel@tonic-gate * the documentation and/or other materials provided with the 28*0Sstevel@tonic-gate * distribution. 29*0Sstevel@tonic-gate * 30*0Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this 31*0Sstevel@tonic-gate * software must display the following acknowledgment: 32*0Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project 33*0Sstevel@tonic-gate * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 34*0Sstevel@tonic-gate * 35*0Sstevel@tonic-gate * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 36*0Sstevel@tonic-gate * endorse or promote products derived from this software without 37*0Sstevel@tonic-gate * prior written permission. For written permission, please contact 38*0Sstevel@tonic-gate * licensing@OpenSSL.org. 39*0Sstevel@tonic-gate * 40*0Sstevel@tonic-gate * 5. Products derived from this software may not be called "OpenSSL" 41*0Sstevel@tonic-gate * nor may "OpenSSL" appear in their names without prior written 42*0Sstevel@tonic-gate * permission of the OpenSSL Project. 43*0Sstevel@tonic-gate * 44*0Sstevel@tonic-gate * 6. Redistributions of any form whatsoever must retain the following 45*0Sstevel@tonic-gate * acknowledgment: 46*0Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project 47*0Sstevel@tonic-gate * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 48*0Sstevel@tonic-gate * 49*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 50*0Sstevel@tonic-gate * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51*0Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 52*0Sstevel@tonic-gate * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 53*0Sstevel@tonic-gate * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 54*0Sstevel@tonic-gate * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 55*0Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 56*0Sstevel@tonic-gate * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 57*0Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 58*0Sstevel@tonic-gate * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 59*0Sstevel@tonic-gate * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 60*0Sstevel@tonic-gate * OF THE POSSIBILITY OF SUCH DAMAGE. 61*0Sstevel@tonic-gate * ==================================================================== 62*0Sstevel@tonic-gate * 63*0Sstevel@tonic-gate * This product includes cryptographic software written by Eric Young 64*0Sstevel@tonic-gate * (eay@cryptsoft.com). This product includes software written by Tim 65*0Sstevel@tonic-gate * Hudson (tjh@cryptsoft.com). 66*0Sstevel@tonic-gate * 67*0Sstevel@tonic-gate */ 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate #include <stdio.h> 70*0Sstevel@tonic-gate #include <assert.h> 71*0Sstevel@tonic-gate #include <stdlib.h> 72*0Sstevel@tonic-gate #include <string.h> 73*0Sstevel@tonic-gate #include <sys/types.h> 74*0Sstevel@tonic-gate #include <unistd.h> 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate #include <openssl/e_os2.h> 77*0Sstevel@tonic-gate #include <openssl/engine.h> 78*0Sstevel@tonic-gate #include <openssl/dso.h> 79*0Sstevel@tonic-gate #include <openssl/err.h> 80*0Sstevel@tonic-gate #include <openssl/bn.h> 81*0Sstevel@tonic-gate #include <openssl/pem.h> 82*0Sstevel@tonic-gate #include <openssl/rsa.h> 83*0Sstevel@tonic-gate #include <openssl/rand.h> 84*0Sstevel@tonic-gate #include <openssl/objects.h> 85*0Sstevel@tonic-gate #include <openssl/x509.h> 86*0Sstevel@tonic-gate #include <cryptlib.h> 87*0Sstevel@tonic-gate 88*0Sstevel@tonic-gate #ifndef OPENSSL_NO_HW 89*0Sstevel@tonic-gate #ifndef OPENSSL_NO_HW_PK11 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate #undef DEBUG_SLOT_SELECTION 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate #include "security/cryptoki.h" 94*0Sstevel@tonic-gate #include "security/pkcs11.h" 95*0Sstevel@tonic-gate #include "hw_pk11_err.c" 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate /* The head of the free PK11 session list */ 99*0Sstevel@tonic-gate static struct PK11_SESSION_st *free_session = NULL; 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate /* Create all secret key objects in a global session so that they are available 102*0Sstevel@tonic-gate * to use for other sessions. These other sessions may be opened or closed 103*0Sstevel@tonic-gate * without losing the secret key objects */ 104*0Sstevel@tonic-gate static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE; 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate /* ENGINE level stuff */ 107*0Sstevel@tonic-gate static int pk11_init(ENGINE *e); 108*0Sstevel@tonic-gate static int pk11_library_init(ENGINE *e); 109*0Sstevel@tonic-gate static int pk11_finish(ENGINE *e); 110*0Sstevel@tonic-gate static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); 111*0Sstevel@tonic-gate static int pk11_destroy(ENGINE *e); 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate /* RAND stuff */ 114*0Sstevel@tonic-gate static void pk11_rand_seed(const void *buf, int num); 115*0Sstevel@tonic-gate static void pk11_rand_add(const void *buf, int num, double add_entropy); 116*0Sstevel@tonic-gate static void pk11_rand_cleanup(void); 117*0Sstevel@tonic-gate static int pk11_rand_bytes(unsigned char *buf, int num); 118*0Sstevel@tonic-gate static int pk11_rand_status(void); 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate /* These functions are also used in other files */ 121*0Sstevel@tonic-gate PK11_SESSION *pk11_get_session(); 122*0Sstevel@tonic-gate void pk11_return_session(PK11_SESSION *sp); 123*0Sstevel@tonic-gate int pk11_destroy_rsa_key_objects(PK11_SESSION *session); 124*0Sstevel@tonic-gate int pk11_destroy_dsa_key_objects(PK11_SESSION *session); 125*0Sstevel@tonic-gate int pk11_destroy_dh_key_objects(PK11_SESSION *session); 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate /* Local helper functions */ 128*0Sstevel@tonic-gate static int pk11_free_all_sessions(); 129*0Sstevel@tonic-gate static int pk11_setup_session(PK11_SESSION *sp); 130*0Sstevel@tonic-gate static int pk11_destroy_cipher_key_objects(PK11_SESSION *session); 131*0Sstevel@tonic-gate static int pk11_destroy_object(CK_SESSION_HANDLE session, 132*0Sstevel@tonic-gate CK_OBJECT_HANDLE oh); 133*0Sstevel@tonic-gate static const char *get_PK11_LIBNAME(void); 134*0Sstevel@tonic-gate static void free_PK11_LIBNAME(void); 135*0Sstevel@tonic-gate static long set_PK11_LIBNAME(const char *name); 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate /* Symmetric cipher and digest support functions */ 138*0Sstevel@tonic-gate static int cipher_nid_to_pk11(int nid); 139*0Sstevel@tonic-gate static int pk11_usable_ciphers(const int **nids); 140*0Sstevel@tonic-gate static int pk11_usable_digests(const int **nids); 141*0Sstevel@tonic-gate static int pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, 142*0Sstevel@tonic-gate const unsigned char *iv, int enc); 143*0Sstevel@tonic-gate static int pk11_cipher_final(PK11_SESSION *sp); 144*0Sstevel@tonic-gate static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 145*0Sstevel@tonic-gate const unsigned char *in, unsigned int inl); 146*0Sstevel@tonic-gate static int pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx); 147*0Sstevel@tonic-gate static int pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 148*0Sstevel@tonic-gate const int **nids, int nid); 149*0Sstevel@tonic-gate static int pk11_engine_digests(ENGINE *e, const EVP_MD **digest, 150*0Sstevel@tonic-gate const int **nids, int nid); 151*0Sstevel@tonic-gate static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, 152*0Sstevel@tonic-gate const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp); 153*0Sstevel@tonic-gate static void check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key); 154*0Sstevel@tonic-gate static int md_nid_to_pk11(int nid); 155*0Sstevel@tonic-gate static int pk11_digest_init(EVP_MD_CTX *ctx); 156*0Sstevel@tonic-gate static int pk11_digest_update(EVP_MD_CTX *ctx,const void *data, 157*0Sstevel@tonic-gate unsigned long count); 158*0Sstevel@tonic-gate static int pk11_digest_final(EVP_MD_CTX *ctx,unsigned char *md); 159*0Sstevel@tonic-gate static int pk11_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from); 160*0Sstevel@tonic-gate static int pk11_digest_cleanup(EVP_MD_CTX *ctx); 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate static int pk11_choose_slot(); 163*0Sstevel@tonic-gate static int pk11_count_symmetric_cipher(int slot_id, CK_MECHANISM_TYPE mech, 164*0Sstevel@tonic-gate int *current_slot_n_cipher, int *local_cipher_nids, int id); 165*0Sstevel@tonic-gate static int pk11_count_digest(int slot_id, CK_MECHANISM_TYPE mech, 166*0Sstevel@tonic-gate int *current_slot_n_digest, int *local_digest_nids, int id); 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate /* Index for the supported ciphers */ 169*0Sstevel@tonic-gate #define PK11_DES_CBC 0 170*0Sstevel@tonic-gate #define PK11_DES3_CBC 1 171*0Sstevel@tonic-gate #define PK11_AES_CBC 2 172*0Sstevel@tonic-gate #define PK11_RC4 3 173*0Sstevel@tonic-gate 174*0Sstevel@tonic-gate /* Index for the supported digests */ 175*0Sstevel@tonic-gate #define PK11_MD5 0 176*0Sstevel@tonic-gate #define PK11_SHA1 1 177*0Sstevel@tonic-gate 178*0Sstevel@tonic-gate #define PK11_CIPHER_MAX 4 /* Max num of ciphers supported */ 179*0Sstevel@tonic-gate #define PK11_DIGEST_MAX 2 /* Max num of digests supported */ 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate #define PK11_KEY_LEN_MAX 24 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate static int cipher_nids[PK11_CIPHER_MAX]; 184*0Sstevel@tonic-gate static int digest_nids[PK11_DIGEST_MAX]; 185*0Sstevel@tonic-gate static int cipher_count = 0; 186*0Sstevel@tonic-gate static int digest_count = 0; 187*0Sstevel@tonic-gate static CK_BBOOL pk11_have_rsa = CK_FALSE; 188*0Sstevel@tonic-gate static CK_BBOOL pk11_have_dsa = CK_FALSE; 189*0Sstevel@tonic-gate static CK_BBOOL pk11_have_dh = CK_FALSE; 190*0Sstevel@tonic-gate static CK_BBOOL pk11_have_random = CK_FALSE; 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate typedef struct PK11_CIPHER_st 193*0Sstevel@tonic-gate { 194*0Sstevel@tonic-gate int id; 195*0Sstevel@tonic-gate int nid; 196*0Sstevel@tonic-gate int ivmax; 197*0Sstevel@tonic-gate int key_len; 198*0Sstevel@tonic-gate CK_KEY_TYPE key_type; 199*0Sstevel@tonic-gate CK_MECHANISM mech; 200*0Sstevel@tonic-gate } PK11_CIPHER; 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate static PK11_CIPHER ciphers[] = 203*0Sstevel@tonic-gate { 204*0Sstevel@tonic-gate {PK11_DES_CBC, NID_des_cbc, 8, 8, CKK_DES, 205*0Sstevel@tonic-gate {CKM_DES_CBC, NULL, 0},}, 206*0Sstevel@tonic-gate {PK11_DES3_CBC, NID_des_ede3_cbc, 8, 24, CKK_DES3, 207*0Sstevel@tonic-gate {CKM_DES3_CBC, NULL, 0},}, 208*0Sstevel@tonic-gate {PK11_AES_CBC, NID_aes_128_cbc, 16, 16, CKK_AES, 209*0Sstevel@tonic-gate {CKM_AES_CBC, NULL, 0},}, 210*0Sstevel@tonic-gate {PK11_RC4, NID_rc4, 0, 16, CKK_RC4, 211*0Sstevel@tonic-gate {CKM_RC4, NULL, 0},}, 212*0Sstevel@tonic-gate }; 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate typedef struct PK11_DIGEST_st 215*0Sstevel@tonic-gate { 216*0Sstevel@tonic-gate int id; 217*0Sstevel@tonic-gate int nid; 218*0Sstevel@tonic-gate CK_MECHANISM mech; 219*0Sstevel@tonic-gate } PK11_DIGEST; 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate static PK11_DIGEST digests[] = 222*0Sstevel@tonic-gate { 223*0Sstevel@tonic-gate {PK11_MD5, NID_md5, {CKM_MD5, NULL, 0},}, 224*0Sstevel@tonic-gate {PK11_SHA1, NID_sha1, {CKM_SHA_1, NULL, 0},}, 225*0Sstevel@tonic-gate {0, NID_undef, {0xFFFF, NULL, 0},}, 226*0Sstevel@tonic-gate }; 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate /* Structure to be used for the cipher_data/md_data in 229*0Sstevel@tonic-gate * EVP_CIPHER_CTX/EVP_MD_CTX structures in order to use the same 230*0Sstevel@tonic-gate * pk11 session in multiple cipher_update calls 231*0Sstevel@tonic-gate */ 232*0Sstevel@tonic-gate typedef struct PK11_CIPHER_STATE_st 233*0Sstevel@tonic-gate { 234*0Sstevel@tonic-gate PK11_SESSION *sp; 235*0Sstevel@tonic-gate } PK11_CIPHER_STATE; 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate /* libcrypto EVP stuff - this is how we get wired to EVP so the engine 239*0Sstevel@tonic-gate * gets called when libcrypto requests a cipher NID. 240*0Sstevel@tonic-gate * Note how the PK11_CIPHER_STATE is used here. 241*0Sstevel@tonic-gate */ 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate /* DES CBC EVP */ 244*0Sstevel@tonic-gate static const EVP_CIPHER pk11_des_cbc = 245*0Sstevel@tonic-gate { 246*0Sstevel@tonic-gate NID_des_cbc, 247*0Sstevel@tonic-gate 8, 8, 8, 248*0Sstevel@tonic-gate EVP_CIPH_CBC_MODE, 249*0Sstevel@tonic-gate pk11_cipher_init, 250*0Sstevel@tonic-gate pk11_cipher_do_cipher, 251*0Sstevel@tonic-gate pk11_cipher_cleanup, 252*0Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 253*0Sstevel@tonic-gate EVP_CIPHER_set_asn1_iv, 254*0Sstevel@tonic-gate EVP_CIPHER_get_asn1_iv, 255*0Sstevel@tonic-gate NULL 256*0Sstevel@tonic-gate }; 257*0Sstevel@tonic-gate 258*0Sstevel@tonic-gate /* 3DES CBC EVP */ 259*0Sstevel@tonic-gate static const EVP_CIPHER pk11_3des_cbc = 260*0Sstevel@tonic-gate { 261*0Sstevel@tonic-gate NID_des_ede3_cbc, 262*0Sstevel@tonic-gate 8, 24, 8, 263*0Sstevel@tonic-gate EVP_CIPH_CBC_MODE, 264*0Sstevel@tonic-gate pk11_cipher_init, 265*0Sstevel@tonic-gate pk11_cipher_do_cipher, 266*0Sstevel@tonic-gate pk11_cipher_cleanup, 267*0Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 268*0Sstevel@tonic-gate EVP_CIPHER_set_asn1_iv, 269*0Sstevel@tonic-gate EVP_CIPHER_get_asn1_iv, 270*0Sstevel@tonic-gate NULL 271*0Sstevel@tonic-gate }; 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate static const EVP_CIPHER pk11_aes_cbc = 274*0Sstevel@tonic-gate { 275*0Sstevel@tonic-gate NID_aes_128_cbc, 276*0Sstevel@tonic-gate 16, 16, 16, 277*0Sstevel@tonic-gate EVP_CIPH_CBC_MODE, 278*0Sstevel@tonic-gate pk11_cipher_init, 279*0Sstevel@tonic-gate pk11_cipher_do_cipher, 280*0Sstevel@tonic-gate pk11_cipher_cleanup, 281*0Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 282*0Sstevel@tonic-gate EVP_CIPHER_set_asn1_iv, 283*0Sstevel@tonic-gate EVP_CIPHER_get_asn1_iv, 284*0Sstevel@tonic-gate NULL 285*0Sstevel@tonic-gate }; 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate static const EVP_CIPHER pk11_rc4 = 288*0Sstevel@tonic-gate { 289*0Sstevel@tonic-gate NID_rc4, 290*0Sstevel@tonic-gate 1,16,0, 291*0Sstevel@tonic-gate EVP_CIPH_VARIABLE_LENGTH, 292*0Sstevel@tonic-gate pk11_cipher_init, 293*0Sstevel@tonic-gate pk11_cipher_do_cipher, 294*0Sstevel@tonic-gate pk11_cipher_cleanup, 295*0Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 296*0Sstevel@tonic-gate NULL, 297*0Sstevel@tonic-gate NULL, 298*0Sstevel@tonic-gate NULL 299*0Sstevel@tonic-gate }; 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate static const EVP_MD pk11_md5 = 302*0Sstevel@tonic-gate { 303*0Sstevel@tonic-gate NID_md5, 304*0Sstevel@tonic-gate NID_md5WithRSAEncryption, 305*0Sstevel@tonic-gate MD5_DIGEST_LENGTH, 306*0Sstevel@tonic-gate 0, 307*0Sstevel@tonic-gate pk11_digest_init, 308*0Sstevel@tonic-gate pk11_digest_update, 309*0Sstevel@tonic-gate pk11_digest_final, 310*0Sstevel@tonic-gate pk11_digest_copy, 311*0Sstevel@tonic-gate pk11_digest_cleanup, 312*0Sstevel@tonic-gate EVP_PKEY_RSA_method, 313*0Sstevel@tonic-gate MD5_CBLOCK, 314*0Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 315*0Sstevel@tonic-gate }; 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate static const EVP_MD pk11_sha1 = 318*0Sstevel@tonic-gate { 319*0Sstevel@tonic-gate NID_sha1, 320*0Sstevel@tonic-gate NID_sha1WithRSAEncryption, 321*0Sstevel@tonic-gate SHA_DIGEST_LENGTH, 322*0Sstevel@tonic-gate 0, 323*0Sstevel@tonic-gate pk11_digest_init, 324*0Sstevel@tonic-gate pk11_digest_update, 325*0Sstevel@tonic-gate pk11_digest_final, 326*0Sstevel@tonic-gate pk11_digest_copy, 327*0Sstevel@tonic-gate pk11_digest_cleanup, 328*0Sstevel@tonic-gate EVP_PKEY_RSA_method, 329*0Sstevel@tonic-gate SHA_CBLOCK, 330*0Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 331*0Sstevel@tonic-gate }; 332*0Sstevel@tonic-gate 333*0Sstevel@tonic-gate /* Initialization function. Sets up various pk11 library components. 334*0Sstevel@tonic-gate */ 335*0Sstevel@tonic-gate /* The definitions for control commands specific to this engine 336*0Sstevel@tonic-gate */ 337*0Sstevel@tonic-gate #define PK11_CMD_SO_PATH ENGINE_CMD_BASE 338*0Sstevel@tonic-gate static const ENGINE_CMD_DEFN pk11_cmd_defns[] = 339*0Sstevel@tonic-gate { 340*0Sstevel@tonic-gate { 341*0Sstevel@tonic-gate PK11_CMD_SO_PATH, 342*0Sstevel@tonic-gate "SO_PATH", 343*0Sstevel@tonic-gate "Specifies the path to the 'pkcs#11' shared library", 344*0Sstevel@tonic-gate ENGINE_CMD_FLAG_STRING 345*0Sstevel@tonic-gate }, 346*0Sstevel@tonic-gate {0, NULL, NULL, 0} 347*0Sstevel@tonic-gate }; 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate static RAND_METHOD pk11_random = 351*0Sstevel@tonic-gate { 352*0Sstevel@tonic-gate pk11_rand_seed, 353*0Sstevel@tonic-gate pk11_rand_bytes, 354*0Sstevel@tonic-gate pk11_rand_cleanup, 355*0Sstevel@tonic-gate pk11_rand_add, 356*0Sstevel@tonic-gate pk11_rand_bytes, 357*0Sstevel@tonic-gate pk11_rand_status 358*0Sstevel@tonic-gate }; 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate /* Constants used when creating the ENGINE 362*0Sstevel@tonic-gate */ 363*0Sstevel@tonic-gate static const char *engine_pk11_id = "pkcs11"; 364*0Sstevel@tonic-gate static const char *engine_pk11_name = "PKCS #11 engine support"; 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate CK_FUNCTION_LIST_PTR pFuncList = NULL; 367*0Sstevel@tonic-gate static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList"; 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate /* These are the static string constants for the DSO file name and the function 370*0Sstevel@tonic-gate * symbol names to bind to. 371*0Sstevel@tonic-gate */ 372*0Sstevel@tonic-gate #if defined(__sparcv9) || defined(__x86_64) || defined(__amd64) 373*0Sstevel@tonic-gate static const char def_PK11_LIBNAME[] = "/usr/lib/64/libpkcs11.so.1"; 374*0Sstevel@tonic-gate #else 375*0Sstevel@tonic-gate static const char def_PK11_LIBNAME[] = "/usr/lib/libpkcs11.so.1"; 376*0Sstevel@tonic-gate #endif 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate /* CRYPTO_LOCK_RSA is defined in OpenSSL for RSA method. Since this pk11 379*0Sstevel@tonic-gate * engine replaces RSA method, we may reuse this lock here. 380*0Sstevel@tonic-gate */ 381*0Sstevel@tonic-gate #define CRYPTO_LOCK_PK11_ENGINE CRYPTO_LOCK_RSA 382*0Sstevel@tonic-gate 383*0Sstevel@tonic-gate static CK_BBOOL true = TRUE; 384*0Sstevel@tonic-gate static CK_BBOOL false = FALSE; 385*0Sstevel@tonic-gate static CK_SLOT_ID SLOTID = 0; 386*0Sstevel@tonic-gate static int pk11_library_initialized = 0; 387*0Sstevel@tonic-gate 388*0Sstevel@tonic-gate static DSO *pk11_dso = NULL; 389*0Sstevel@tonic-gate 390*0Sstevel@tonic-gate /* 391*0Sstevel@tonic-gate * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support. 392*0Sstevel@tonic-gate */ 393*0Sstevel@tonic-gate static int bind_pk11(ENGINE *e) 394*0Sstevel@tonic-gate { 395*0Sstevel@tonic-gate const RSA_METHOD *rsa = NULL; 396*0Sstevel@tonic-gate RSA_METHOD *pk11_rsa = PK11_RSA(); 397*0Sstevel@tonic-gate 398*0Sstevel@tonic-gate if (!pk11_library_initialized) 399*0Sstevel@tonic-gate pk11_library_init(e); 400*0Sstevel@tonic-gate 401*0Sstevel@tonic-gate if(!ENGINE_set_id(e, engine_pk11_id) || 402*0Sstevel@tonic-gate !ENGINE_set_name(e, engine_pk11_name) || 403*0Sstevel@tonic-gate !ENGINE_set_ciphers(e, pk11_engine_ciphers) || 404*0Sstevel@tonic-gate !ENGINE_set_digests(e, pk11_engine_digests)) 405*0Sstevel@tonic-gate return 0; 406*0Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA 407*0Sstevel@tonic-gate if(pk11_have_rsa == CK_TRUE) 408*0Sstevel@tonic-gate { 409*0Sstevel@tonic-gate if(!ENGINE_set_RSA(e, PK11_RSA()) || 410*0Sstevel@tonic-gate !ENGINE_set_load_privkey_function(e, pk11_load_privkey) || 411*0Sstevel@tonic-gate !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey)) 412*0Sstevel@tonic-gate return 0; 413*0Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 414*0Sstevel@tonic-gate fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: registered RSA\n"); 415*0Sstevel@tonic-gate #endif /* DEBUG_SLOT_SELECTION */ 416*0Sstevel@tonic-gate } 417*0Sstevel@tonic-gate #endif 418*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA 419*0Sstevel@tonic-gate if(pk11_have_dsa == CK_TRUE) 420*0Sstevel@tonic-gate { 421*0Sstevel@tonic-gate if (!ENGINE_set_DSA(e, PK11_DSA())) 422*0Sstevel@tonic-gate return 0; 423*0Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 424*0Sstevel@tonic-gate fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: registered DSA\n"); 425*0Sstevel@tonic-gate #endif /* DEBUG_SLOT_SELECTION */ 426*0Sstevel@tonic-gate } 427*0Sstevel@tonic-gate #endif 428*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DH 429*0Sstevel@tonic-gate if(pk11_have_dh == CK_TRUE) 430*0Sstevel@tonic-gate { 431*0Sstevel@tonic-gate if (!ENGINE_set_DH(e, PK11_DH())) 432*0Sstevel@tonic-gate return 0; 433*0Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 434*0Sstevel@tonic-gate fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: registered DH\n"); 435*0Sstevel@tonic-gate #endif /* DEBUG_SLOT_SELECTION */ 436*0Sstevel@tonic-gate } 437*0Sstevel@tonic-gate #endif 438*0Sstevel@tonic-gate if(pk11_have_random) 439*0Sstevel@tonic-gate { 440*0Sstevel@tonic-gate if(!ENGINE_set_RAND(e, &pk11_random)) 441*0Sstevel@tonic-gate return 0; 442*0Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 443*0Sstevel@tonic-gate fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: registered random\n"); 444*0Sstevel@tonic-gate #endif /* DEBUG_SLOT_SELECTION */ 445*0Sstevel@tonic-gate } 446*0Sstevel@tonic-gate if(!ENGINE_set_init_function(e, pk11_init) || 447*0Sstevel@tonic-gate !ENGINE_set_destroy_function(e, pk11_destroy) || 448*0Sstevel@tonic-gate !ENGINE_set_finish_function(e, pk11_finish) || 449*0Sstevel@tonic-gate !ENGINE_set_ctrl_function(e, pk11_ctrl) || 450*0Sstevel@tonic-gate !ENGINE_set_cmd_defns(e, pk11_cmd_defns)) 451*0Sstevel@tonic-gate return 0; 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate /* Apache calls OpenSSL function RSA_blinding_on() once during startup 454*0Sstevel@tonic-gate * which in turn calls bn_mod_exp. Since we do not implement bn_mod_exp 455*0Sstevel@tonic-gate * here, we wire it back to the OpenSSL software implementation. 456*0Sstevel@tonic-gate * Since it is used only once, performance is not a concern. */ 457*0Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA 458*0Sstevel@tonic-gate rsa = RSA_PKCS1_SSLeay(); 459*0Sstevel@tonic-gate pk11_rsa->rsa_mod_exp = rsa->rsa_mod_exp; 460*0Sstevel@tonic-gate pk11_rsa->bn_mod_exp = rsa->bn_mod_exp; 461*0Sstevel@tonic-gate #endif 462*0Sstevel@tonic-gate 463*0Sstevel@tonic-gate /* Ensure the pk11 error handling is set up */ 464*0Sstevel@tonic-gate ERR_load_pk11_strings(); 465*0Sstevel@tonic-gate 466*0Sstevel@tonic-gate return 1; 467*0Sstevel@tonic-gate } 468*0Sstevel@tonic-gate 469*0Sstevel@tonic-gate /* Dynamic engine support is disabled at a higher level for Solaris 470*0Sstevel@tonic-gate */ 471*0Sstevel@tonic-gate #ifdef ENGINE_DYNAMIC_SUPPORT 472*0Sstevel@tonic-gate static int bind_helper(ENGINE *e, const char *id) 473*0Sstevel@tonic-gate { 474*0Sstevel@tonic-gate if (id && (strcmp(id, engine_pk11_id) != 0)) 475*0Sstevel@tonic-gate return 0; 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gate if (!bind_pk11(e)) 478*0Sstevel@tonic-gate return 0; 479*0Sstevel@tonic-gate 480*0Sstevel@tonic-gate return 1; 481*0Sstevel@tonic-gate } 482*0Sstevel@tonic-gate 483*0Sstevel@tonic-gate IMPLEMENT_DYNAMIC_CHECK_FN() 484*0Sstevel@tonic-gate IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) 485*0Sstevel@tonic-gate 486*0Sstevel@tonic-gate #else 487*0Sstevel@tonic-gate static ENGINE *engine_pk11(void) 488*0Sstevel@tonic-gate { 489*0Sstevel@tonic-gate ENGINE *ret = ENGINE_new(); 490*0Sstevel@tonic-gate 491*0Sstevel@tonic-gate if (!ret) 492*0Sstevel@tonic-gate return NULL; 493*0Sstevel@tonic-gate 494*0Sstevel@tonic-gate if (!bind_pk11(ret)) 495*0Sstevel@tonic-gate { 496*0Sstevel@tonic-gate ENGINE_free(ret); 497*0Sstevel@tonic-gate return NULL; 498*0Sstevel@tonic-gate } 499*0Sstevel@tonic-gate 500*0Sstevel@tonic-gate return ret; 501*0Sstevel@tonic-gate } 502*0Sstevel@tonic-gate 503*0Sstevel@tonic-gate void ENGINE_load_pk11(void) 504*0Sstevel@tonic-gate { 505*0Sstevel@tonic-gate ENGINE *e_pk11 = NULL; 506*0Sstevel@tonic-gate 507*0Sstevel@tonic-gate /* Do not use dynamic PKCS#11 library on Solaris due to 508*0Sstevel@tonic-gate * security reasons. We will link it in statically 509*0Sstevel@tonic-gate */ 510*0Sstevel@tonic-gate /* Attempt to load PKCS#11 library 511*0Sstevel@tonic-gate */ 512*0Sstevel@tonic-gate if (!pk11_dso) 513*0Sstevel@tonic-gate pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0); 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate if (pk11_dso == NULL) 516*0Sstevel@tonic-gate { 517*0Sstevel@tonic-gate PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE); 518*0Sstevel@tonic-gate return; 519*0Sstevel@tonic-gate } 520*0Sstevel@tonic-gate 521*0Sstevel@tonic-gate e_pk11 = engine_pk11(); 522*0Sstevel@tonic-gate if (!e_pk11) 523*0Sstevel@tonic-gate { 524*0Sstevel@tonic-gate DSO_free(pk11_dso); 525*0Sstevel@tonic-gate pk11_dso = NULL; 526*0Sstevel@tonic-gate return; 527*0Sstevel@tonic-gate } 528*0Sstevel@tonic-gate 529*0Sstevel@tonic-gate /* At this point, the pk11 shared library is either dynamically 530*0Sstevel@tonic-gate * loaded or statically linked in. So, initialize the pk11 531*0Sstevel@tonic-gate * library before calling ENGINE_set_default since the latter 532*0Sstevel@tonic-gate * needs cipher and digest algorithm information 533*0Sstevel@tonic-gate */ 534*0Sstevel@tonic-gate if (!pk11_library_init(e_pk11)) 535*0Sstevel@tonic-gate { 536*0Sstevel@tonic-gate DSO_free(pk11_dso); 537*0Sstevel@tonic-gate pk11_dso = NULL; 538*0Sstevel@tonic-gate ENGINE_free(e_pk11); 539*0Sstevel@tonic-gate return; 540*0Sstevel@tonic-gate } 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate ENGINE_add(e_pk11); 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate ENGINE_free(e_pk11); 545*0Sstevel@tonic-gate ERR_clear_error(); 546*0Sstevel@tonic-gate } 547*0Sstevel@tonic-gate #endif 548*0Sstevel@tonic-gate 549*0Sstevel@tonic-gate /* These are the static string constants for the DSO file name and 550*0Sstevel@tonic-gate * the function symbol names to bind to. 551*0Sstevel@tonic-gate */ 552*0Sstevel@tonic-gate static const char *PK11_LIBNAME = NULL; 553*0Sstevel@tonic-gate 554*0Sstevel@tonic-gate static const char *get_PK11_LIBNAME(void) 555*0Sstevel@tonic-gate { 556*0Sstevel@tonic-gate if (PK11_LIBNAME) 557*0Sstevel@tonic-gate return PK11_LIBNAME; 558*0Sstevel@tonic-gate 559*0Sstevel@tonic-gate return def_PK11_LIBNAME; 560*0Sstevel@tonic-gate } 561*0Sstevel@tonic-gate 562*0Sstevel@tonic-gate static void free_PK11_LIBNAME(void) 563*0Sstevel@tonic-gate { 564*0Sstevel@tonic-gate if (PK11_LIBNAME) 565*0Sstevel@tonic-gate OPENSSL_free((void*)PK11_LIBNAME); 566*0Sstevel@tonic-gate 567*0Sstevel@tonic-gate PK11_LIBNAME = NULL; 568*0Sstevel@tonic-gate } 569*0Sstevel@tonic-gate 570*0Sstevel@tonic-gate static long set_PK11_LIBNAME(const char *name) 571*0Sstevel@tonic-gate { 572*0Sstevel@tonic-gate free_PK11_LIBNAME(); 573*0Sstevel@tonic-gate 574*0Sstevel@tonic-gate return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0); 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate /* Initialization function for the pk11 engine */ 578*0Sstevel@tonic-gate static int pk11_init(ENGINE *e) 579*0Sstevel@tonic-gate { 580*0Sstevel@tonic-gate return pk11_library_init(e); 581*0Sstevel@tonic-gate } 582*0Sstevel@tonic-gate 583*0Sstevel@tonic-gate /* Initialization function. Sets up various pk11 library components. 584*0Sstevel@tonic-gate * It selects a slot based on predefined critiera. In the process, it also 585*0Sstevel@tonic-gate * count how many ciphers and digests to support. Since the cipher and 586*0Sstevel@tonic-gate * digest information is needed when setting default engine, this function 587*0Sstevel@tonic-gate * needs to be called before calling ENGINE_set_default. 588*0Sstevel@tonic-gate */ 589*0Sstevel@tonic-gate static int pk11_library_init(ENGINE *e) 590*0Sstevel@tonic-gate { 591*0Sstevel@tonic-gate CK_C_GetFunctionList p; 592*0Sstevel@tonic-gate CK_RV rv = CKR_OK; 593*0Sstevel@tonic-gate CK_INFO info; 594*0Sstevel@tonic-gate CK_ULONG ul_state_len; 595*0Sstevel@tonic-gate char tmp_buf[20]; 596*0Sstevel@tonic-gate 597*0Sstevel@tonic-gate if (pk11_library_initialized) 598*0Sstevel@tonic-gate return 1; 599*0Sstevel@tonic-gate 600*0Sstevel@tonic-gate if (pk11_dso == NULL) 601*0Sstevel@tonic-gate { 602*0Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); 603*0Sstevel@tonic-gate goto err; 604*0Sstevel@tonic-gate } 605*0Sstevel@tonic-gate 606*0Sstevel@tonic-gate /* get the C_GetFunctionList function from the loaded library 607*0Sstevel@tonic-gate */ 608*0Sstevel@tonic-gate p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso, 609*0Sstevel@tonic-gate PK11_GET_FUNCTION_LIST); 610*0Sstevel@tonic-gate if ( !p ) 611*0Sstevel@tonic-gate { 612*0Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); 613*0Sstevel@tonic-gate goto err; 614*0Sstevel@tonic-gate } 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gate /* get the full function list from the loaded library 617*0Sstevel@tonic-gate */ 618*0Sstevel@tonic-gate rv = p(&pFuncList); 619*0Sstevel@tonic-gate if (rv != CKR_OK) 620*0Sstevel@tonic-gate { 621*0Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); 622*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 623*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 624*0Sstevel@tonic-gate goto err; 625*0Sstevel@tonic-gate } 626*0Sstevel@tonic-gate 627*0Sstevel@tonic-gate rv = pFuncList->C_Initialize(NULL_PTR); 628*0Sstevel@tonic-gate if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) 629*0Sstevel@tonic-gate { 630*0Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE); 631*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 632*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 633*0Sstevel@tonic-gate goto err; 634*0Sstevel@tonic-gate } 635*0Sstevel@tonic-gate 636*0Sstevel@tonic-gate rv = pFuncList->C_GetInfo(&info); 637*0Sstevel@tonic-gate if (rv != CKR_OK) 638*0Sstevel@tonic-gate { 639*0Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_GETINFO); 640*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 641*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 642*0Sstevel@tonic-gate goto err; 643*0Sstevel@tonic-gate } 644*0Sstevel@tonic-gate 645*0Sstevel@tonic-gate if (pk11_choose_slot() == 0) 646*0Sstevel@tonic-gate goto err; 647*0Sstevel@tonic-gate 648*0Sstevel@tonic-gate if (global_session == CK_INVALID_HANDLE) 649*0Sstevel@tonic-gate { 650*0Sstevel@tonic-gate /* Open the global_session for the new process */ 651*0Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 652*0Sstevel@tonic-gate NULL_PTR, NULL_PTR, &global_session); 653*0Sstevel@tonic-gate if (rv != CKR_OK) 654*0Sstevel@tonic-gate { 655*0Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_OPENSESSION); 656*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 657*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 658*0Sstevel@tonic-gate goto err; 659*0Sstevel@tonic-gate } 660*0Sstevel@tonic-gate } 661*0Sstevel@tonic-gate 662*0Sstevel@tonic-gate /* Disable digest if C_GetOperationState is not supported since 663*0Sstevel@tonic-gate * this function is required by OpenSSL digest copy function */ 664*0Sstevel@tonic-gate if (pFuncList->C_GetOperationState(global_session, NULL, &ul_state_len) 665*0Sstevel@tonic-gate == CKR_FUNCTION_NOT_SUPPORTED) 666*0Sstevel@tonic-gate digest_count = 0; 667*0Sstevel@tonic-gate 668*0Sstevel@tonic-gate pk11_library_initialized = 1; 669*0Sstevel@tonic-gate return 1; 670*0Sstevel@tonic-gate 671*0Sstevel@tonic-gate err: 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gate return 0; 674*0Sstevel@tonic-gate } 675*0Sstevel@tonic-gate 676*0Sstevel@tonic-gate /* Destructor (complements the "ENGINE_pk11()" constructor) 677*0Sstevel@tonic-gate */ 678*0Sstevel@tonic-gate static int pk11_destroy(ENGINE *e) 679*0Sstevel@tonic-gate { 680*0Sstevel@tonic-gate free_PK11_LIBNAME(); 681*0Sstevel@tonic-gate ERR_unload_pk11_strings(); 682*0Sstevel@tonic-gate return 1; 683*0Sstevel@tonic-gate } 684*0Sstevel@tonic-gate 685*0Sstevel@tonic-gate /* Termination function to clean up the session, the token, and 686*0Sstevel@tonic-gate * the pk11 library. 687*0Sstevel@tonic-gate */ 688*0Sstevel@tonic-gate static int pk11_finish(ENGINE *e) 689*0Sstevel@tonic-gate { 690*0Sstevel@tonic-gate 691*0Sstevel@tonic-gate if (pk11_dso == NULL) 692*0Sstevel@tonic-gate { 693*0Sstevel@tonic-gate PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED); 694*0Sstevel@tonic-gate goto err; 695*0Sstevel@tonic-gate } 696*0Sstevel@tonic-gate 697*0Sstevel@tonic-gate assert(pFuncList != NULL); 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate if (pk11_free_all_sessions() == 0) 700*0Sstevel@tonic-gate goto err; 701*0Sstevel@tonic-gate 702*0Sstevel@tonic-gate pFuncList->C_CloseSession(global_session); 703*0Sstevel@tonic-gate 704*0Sstevel@tonic-gate /* Since we are part of a library (libcrypto.so), calling this 705*0Sstevel@tonic-gate * function may have side-effects. 706*0Sstevel@tonic-gate pFuncList->C_Finalize(NULL); 707*0Sstevel@tonic-gate */ 708*0Sstevel@tonic-gate 709*0Sstevel@tonic-gate if (!DSO_free(pk11_dso)) 710*0Sstevel@tonic-gate { 711*0Sstevel@tonic-gate PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE); 712*0Sstevel@tonic-gate goto err; 713*0Sstevel@tonic-gate } 714*0Sstevel@tonic-gate pk11_dso = NULL; 715*0Sstevel@tonic-gate pFuncList = NULL; 716*0Sstevel@tonic-gate pk11_library_initialized = 0; 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate return 1; 719*0Sstevel@tonic-gate 720*0Sstevel@tonic-gate err: 721*0Sstevel@tonic-gate return 0; 722*0Sstevel@tonic-gate } 723*0Sstevel@tonic-gate 724*0Sstevel@tonic-gate /* Standard engine interface function to set the dynamic library path */ 725*0Sstevel@tonic-gate static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) 726*0Sstevel@tonic-gate { 727*0Sstevel@tonic-gate int initialized = ((pk11_dso == NULL) ? 0 : 1); 728*0Sstevel@tonic-gate 729*0Sstevel@tonic-gate switch(cmd) 730*0Sstevel@tonic-gate { 731*0Sstevel@tonic-gate case PK11_CMD_SO_PATH: 732*0Sstevel@tonic-gate if (p == NULL) 733*0Sstevel@tonic-gate { 734*0Sstevel@tonic-gate PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); 735*0Sstevel@tonic-gate return 0; 736*0Sstevel@tonic-gate } 737*0Sstevel@tonic-gate 738*0Sstevel@tonic-gate if (initialized) 739*0Sstevel@tonic-gate { 740*0Sstevel@tonic-gate PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED); 741*0Sstevel@tonic-gate return 0; 742*0Sstevel@tonic-gate } 743*0Sstevel@tonic-gate 744*0Sstevel@tonic-gate return set_PK11_LIBNAME((const char*)p); 745*0Sstevel@tonic-gate default: 746*0Sstevel@tonic-gate break; 747*0Sstevel@tonic-gate } 748*0Sstevel@tonic-gate 749*0Sstevel@tonic-gate PK11err(PK11_F_CTRL,PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED); 750*0Sstevel@tonic-gate 751*0Sstevel@tonic-gate return 0; 752*0Sstevel@tonic-gate } 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate 755*0Sstevel@tonic-gate /* Required function by the engine random interface. It does nothing here 756*0Sstevel@tonic-gate */ 757*0Sstevel@tonic-gate static void pk11_rand_cleanup(void) 758*0Sstevel@tonic-gate { 759*0Sstevel@tonic-gate return; 760*0Sstevel@tonic-gate } 761*0Sstevel@tonic-gate 762*0Sstevel@tonic-gate static void pk11_rand_add(const void *buf, int num, double add) 763*0Sstevel@tonic-gate { 764*0Sstevel@tonic-gate PK11_SESSION *sp; 765*0Sstevel@tonic-gate 766*0Sstevel@tonic-gate if ((sp = pk11_get_session()) == NULL) 767*0Sstevel@tonic-gate return; 768*0Sstevel@tonic-gate 769*0Sstevel@tonic-gate /* Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since 770*0Sstevel@tonic-gate * the calling functions do not care anyway 771*0Sstevel@tonic-gate */ 772*0Sstevel@tonic-gate pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num); 773*0Sstevel@tonic-gate pk11_return_session(sp); 774*0Sstevel@tonic-gate 775*0Sstevel@tonic-gate return; 776*0Sstevel@tonic-gate } 777*0Sstevel@tonic-gate 778*0Sstevel@tonic-gate static void pk11_rand_seed(const void *buf, int num) 779*0Sstevel@tonic-gate { 780*0Sstevel@tonic-gate pk11_rand_add(buf, num, 0); 781*0Sstevel@tonic-gate } 782*0Sstevel@tonic-gate 783*0Sstevel@tonic-gate static int pk11_rand_bytes(unsigned char *buf, int num) 784*0Sstevel@tonic-gate { 785*0Sstevel@tonic-gate CK_RV rv; 786*0Sstevel@tonic-gate PK11_SESSION *sp; 787*0Sstevel@tonic-gate 788*0Sstevel@tonic-gate if ((sp = pk11_get_session()) == NULL) 789*0Sstevel@tonic-gate return 0; 790*0Sstevel@tonic-gate 791*0Sstevel@tonic-gate rv = pFuncList->C_GenerateRandom(sp->session, buf, num); 792*0Sstevel@tonic-gate if (rv != CKR_OK) 793*0Sstevel@tonic-gate { 794*0Sstevel@tonic-gate char tmp_buf[20]; 795*0Sstevel@tonic-gate PK11err(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM); 796*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 797*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 798*0Sstevel@tonic-gate pk11_return_session(sp); 799*0Sstevel@tonic-gate return 0; 800*0Sstevel@tonic-gate } 801*0Sstevel@tonic-gate 802*0Sstevel@tonic-gate pk11_return_session(sp); 803*0Sstevel@tonic-gate return 1; 804*0Sstevel@tonic-gate } 805*0Sstevel@tonic-gate 806*0Sstevel@tonic-gate 807*0Sstevel@tonic-gate /* Required function by the engine random interface. It does nothing here 808*0Sstevel@tonic-gate */ 809*0Sstevel@tonic-gate static int pk11_rand_status(void) 810*0Sstevel@tonic-gate { 811*0Sstevel@tonic-gate return 1; 812*0Sstevel@tonic-gate } 813*0Sstevel@tonic-gate 814*0Sstevel@tonic-gate 815*0Sstevel@tonic-gate PK11_SESSION *pk11_get_session() 816*0Sstevel@tonic-gate { 817*0Sstevel@tonic-gate PK11_SESSION *sp, *sp1; 818*0Sstevel@tonic-gate CK_RV rv; 819*0Sstevel@tonic-gate char tmp_buf[20]; 820*0Sstevel@tonic-gate 821*0Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 822*0Sstevel@tonic-gate if ((sp = free_session) == NULL) 823*0Sstevel@tonic-gate { 824*0Sstevel@tonic-gate if ((sp = OPENSSL_malloc(sizeof(PK11_SESSION))) == NULL) 825*0Sstevel@tonic-gate { 826*0Sstevel@tonic-gate PK11err(PK11_F_GET_SESSION, 827*0Sstevel@tonic-gate PK11_R_MALLOC_FAILURE); 828*0Sstevel@tonic-gate goto err; 829*0Sstevel@tonic-gate } 830*0Sstevel@tonic-gate memset(sp, 0, sizeof(PK11_SESSION)); 831*0Sstevel@tonic-gate } 832*0Sstevel@tonic-gate else 833*0Sstevel@tonic-gate { 834*0Sstevel@tonic-gate free_session = sp->next; 835*0Sstevel@tonic-gate } 836*0Sstevel@tonic-gate 837*0Sstevel@tonic-gate if (sp->pid != 0 && sp->pid != getpid()) 838*0Sstevel@tonic-gate { 839*0Sstevel@tonic-gate /* We are a new process and thus need to free any inherated 840*0Sstevel@tonic-gate * PK11_SESSION objects. 841*0Sstevel@tonic-gate */ 842*0Sstevel@tonic-gate while ((sp1 = free_session) != NULL) 843*0Sstevel@tonic-gate { 844*0Sstevel@tonic-gate free_session = sp1->next; 845*0Sstevel@tonic-gate OPENSSL_free(sp1); 846*0Sstevel@tonic-gate } 847*0Sstevel@tonic-gate 848*0Sstevel@tonic-gate /* Initialize the process */ 849*0Sstevel@tonic-gate rv = pFuncList->C_Initialize(NULL_PTR); 850*0Sstevel@tonic-gate if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) 851*0Sstevel@tonic-gate { 852*0Sstevel@tonic-gate PK11err(PK11_F_GET_SESSION, PK11_R_INITIALIZE); 853*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 854*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 855*0Sstevel@tonic-gate OPENSSL_free(sp); 856*0Sstevel@tonic-gate sp = NULL; 857*0Sstevel@tonic-gate goto err; 858*0Sstevel@tonic-gate } 859*0Sstevel@tonic-gate 860*0Sstevel@tonic-gate /* Choose slot here since the slot table is different on 861*0Sstevel@tonic-gate * this process. 862*0Sstevel@tonic-gate */ 863*0Sstevel@tonic-gate if (pk11_choose_slot() == 0) 864*0Sstevel@tonic-gate goto err; 865*0Sstevel@tonic-gate 866*0Sstevel@tonic-gate /* Open the global_session for the new process */ 867*0Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 868*0Sstevel@tonic-gate NULL_PTR, NULL_PTR, &global_session); 869*0Sstevel@tonic-gate if (rv != CKR_OK) 870*0Sstevel@tonic-gate { 871*0Sstevel@tonic-gate PK11err(PK11_F_GET_SESSION, PK11_R_OPENSESSION); 872*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 873*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 874*0Sstevel@tonic-gate OPENSSL_free(sp); 875*0Sstevel@tonic-gate sp = NULL; 876*0Sstevel@tonic-gate goto err; 877*0Sstevel@tonic-gate } 878*0Sstevel@tonic-gate 879*0Sstevel@tonic-gate /* It is an inherited session and needs re-initialization. 880*0Sstevel@tonic-gate */ 881*0Sstevel@tonic-gate if (pk11_setup_session(sp) == 0) 882*0Sstevel@tonic-gate { 883*0Sstevel@tonic-gate OPENSSL_free(sp); 884*0Sstevel@tonic-gate sp = NULL; 885*0Sstevel@tonic-gate } 886*0Sstevel@tonic-gate } 887*0Sstevel@tonic-gate else if (sp->pid == 0) 888*0Sstevel@tonic-gate { 889*0Sstevel@tonic-gate /* It is a new session and needs initialization. 890*0Sstevel@tonic-gate */ 891*0Sstevel@tonic-gate if (pk11_setup_session(sp) == 0) 892*0Sstevel@tonic-gate { 893*0Sstevel@tonic-gate OPENSSL_free(sp); 894*0Sstevel@tonic-gate sp = NULL; 895*0Sstevel@tonic-gate } 896*0Sstevel@tonic-gate } 897*0Sstevel@tonic-gate 898*0Sstevel@tonic-gate err: 899*0Sstevel@tonic-gate if (sp) 900*0Sstevel@tonic-gate sp->next = NULL; 901*0Sstevel@tonic-gate 902*0Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 903*0Sstevel@tonic-gate 904*0Sstevel@tonic-gate return sp; 905*0Sstevel@tonic-gate } 906*0Sstevel@tonic-gate 907*0Sstevel@tonic-gate 908*0Sstevel@tonic-gate void pk11_return_session(PK11_SESSION *sp) 909*0Sstevel@tonic-gate { 910*0Sstevel@tonic-gate if (sp == NULL || sp->pid != getpid()) 911*0Sstevel@tonic-gate return; 912*0Sstevel@tonic-gate 913*0Sstevel@tonic-gate 914*0Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 915*0Sstevel@tonic-gate 916*0Sstevel@tonic-gate sp->next = free_session; 917*0Sstevel@tonic-gate free_session = sp; 918*0Sstevel@tonic-gate 919*0Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 920*0Sstevel@tonic-gate } 921*0Sstevel@tonic-gate 922*0Sstevel@tonic-gate 923*0Sstevel@tonic-gate /* Destroy all objects. This function is called when the engine is finished 924*0Sstevel@tonic-gate */ 925*0Sstevel@tonic-gate static int pk11_free_all_sessions() 926*0Sstevel@tonic-gate { 927*0Sstevel@tonic-gate CK_RV rv; 928*0Sstevel@tonic-gate PK11_SESSION *sp = NULL; 929*0Sstevel@tonic-gate pid_t mypid = getpid(); 930*0Sstevel@tonic-gate int ret = 0; 931*0Sstevel@tonic-gate 932*0Sstevel@tonic-gate pk11_destroy_rsa_key_objects(NULL); 933*0Sstevel@tonic-gate pk11_destroy_dsa_key_objects(NULL); 934*0Sstevel@tonic-gate pk11_destroy_dh_key_objects(NULL); 935*0Sstevel@tonic-gate pk11_destroy_cipher_key_objects(NULL); 936*0Sstevel@tonic-gate 937*0Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 938*0Sstevel@tonic-gate while ((sp = free_session) != NULL) 939*0Sstevel@tonic-gate { 940*0Sstevel@tonic-gate if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid) 941*0Sstevel@tonic-gate { 942*0Sstevel@tonic-gate rv = pFuncList->C_CloseSession(sp->session); 943*0Sstevel@tonic-gate if (rv != CKR_OK) 944*0Sstevel@tonic-gate { 945*0Sstevel@tonic-gate char tmp_buf[20]; 946*0Sstevel@tonic-gate PK11err(PK11_F_FREE_ALL_SESSIONS, 947*0Sstevel@tonic-gate PK11_R_CLOSESESSION); 948*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 949*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 950*0Sstevel@tonic-gate } 951*0Sstevel@tonic-gate } 952*0Sstevel@tonic-gate if (sp->session_cipher != CK_INVALID_HANDLE && sp->pid == mypid) 953*0Sstevel@tonic-gate { 954*0Sstevel@tonic-gate rv = pFuncList->C_CloseSession(sp->session_cipher); 955*0Sstevel@tonic-gate if (rv != CKR_OK) 956*0Sstevel@tonic-gate { 957*0Sstevel@tonic-gate char tmp_buf[20]; 958*0Sstevel@tonic-gate PK11err(PK11_F_FREE_ALL_SESSIONS, 959*0Sstevel@tonic-gate PK11_R_CLOSESESSION); 960*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 961*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 962*0Sstevel@tonic-gate } 963*0Sstevel@tonic-gate } 964*0Sstevel@tonic-gate free_session = sp->next; 965*0Sstevel@tonic-gate OPENSSL_free(sp); 966*0Sstevel@tonic-gate } 967*0Sstevel@tonic-gate ret = 1; 968*0Sstevel@tonic-gate err: 969*0Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 970*0Sstevel@tonic-gate 971*0Sstevel@tonic-gate return ret; 972*0Sstevel@tonic-gate } 973*0Sstevel@tonic-gate 974*0Sstevel@tonic-gate 975*0Sstevel@tonic-gate static int pk11_setup_session(PK11_SESSION *sp) 976*0Sstevel@tonic-gate { 977*0Sstevel@tonic-gate CK_RV rv; 978*0Sstevel@tonic-gate sp->session = CK_INVALID_HANDLE; 979*0Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 980*0Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session); 981*0Sstevel@tonic-gate if (rv == CKR_CRYPTOKI_NOT_INITIALIZED) 982*0Sstevel@tonic-gate { 983*0Sstevel@tonic-gate /* 984*0Sstevel@tonic-gate * We are probably a child process so force the 985*0Sstevel@tonic-gate * reinitialize of the session 986*0Sstevel@tonic-gate */ 987*0Sstevel@tonic-gate pk11_library_initialized = 0; 988*0Sstevel@tonic-gate (void) pk11_library_init(NULL); 989*0Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 990*0Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session); 991*0Sstevel@tonic-gate } 992*0Sstevel@tonic-gate if (rv != CKR_OK) 993*0Sstevel@tonic-gate { 994*0Sstevel@tonic-gate char tmp_buf[20]; 995*0Sstevel@tonic-gate PK11err(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION); 996*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 997*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 998*0Sstevel@tonic-gate return 0; 999*0Sstevel@tonic-gate } 1000*0Sstevel@tonic-gate 1001*0Sstevel@tonic-gate sp->session_cipher = CK_INVALID_HANDLE; 1002*0Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 1003*0Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session_cipher); 1004*0Sstevel@tonic-gate if (rv != CKR_OK) 1005*0Sstevel@tonic-gate { 1006*0Sstevel@tonic-gate char tmp_buf[20]; 1007*0Sstevel@tonic-gate 1008*0Sstevel@tonic-gate (void) pFuncList->C_CloseSession(sp->session); 1009*0Sstevel@tonic-gate sp->session = CK_INVALID_HANDLE; 1010*0Sstevel@tonic-gate 1011*0Sstevel@tonic-gate PK11err(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION); 1012*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1013*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1014*0Sstevel@tonic-gate return 0; 1015*0Sstevel@tonic-gate } 1016*0Sstevel@tonic-gate 1017*0Sstevel@tonic-gate sp->pid = getpid(); 1018*0Sstevel@tonic-gate sp->rsa_pub_key = CK_INVALID_HANDLE; 1019*0Sstevel@tonic-gate sp->rsa_priv_key = CK_INVALID_HANDLE; 1020*0Sstevel@tonic-gate sp->dsa_pub_key = CK_INVALID_HANDLE; 1021*0Sstevel@tonic-gate sp->dsa_priv_key = CK_INVALID_HANDLE; 1022*0Sstevel@tonic-gate sp->dh_key = CK_INVALID_HANDLE; 1023*0Sstevel@tonic-gate sp->cipher_key = CK_INVALID_HANDLE; 1024*0Sstevel@tonic-gate sp->rsa = NULL; 1025*0Sstevel@tonic-gate sp->dsa = NULL; 1026*0Sstevel@tonic-gate sp->dh = NULL; 1027*0Sstevel@tonic-gate sp->encrypt = -1; 1028*0Sstevel@tonic-gate 1029*0Sstevel@tonic-gate return 1; 1030*0Sstevel@tonic-gate } 1031*0Sstevel@tonic-gate 1032*0Sstevel@tonic-gate int pk11_destroy_rsa_key_objects(PK11_SESSION *session) 1033*0Sstevel@tonic-gate { 1034*0Sstevel@tonic-gate int ret = 0; 1035*0Sstevel@tonic-gate PK11_SESSION *sp = NULL; 1036*0Sstevel@tonic-gate PK11_SESSION *local_free_session; 1037*0Sstevel@tonic-gate 1038*0Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 1039*0Sstevel@tonic-gate if (session) 1040*0Sstevel@tonic-gate local_free_session = session; 1041*0Sstevel@tonic-gate else 1042*0Sstevel@tonic-gate local_free_session = free_session; 1043*0Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 1044*0Sstevel@tonic-gate { 1045*0Sstevel@tonic-gate local_free_session = sp->next; 1046*0Sstevel@tonic-gate 1047*0Sstevel@tonic-gate if (sp->rsa_pub_key != CK_INVALID_HANDLE) 1048*0Sstevel@tonic-gate { 1049*0Sstevel@tonic-gate if (pk11_destroy_object(sp->session, 1050*0Sstevel@tonic-gate sp->rsa_pub_key) == 0) 1051*0Sstevel@tonic-gate goto err; 1052*0Sstevel@tonic-gate sp->rsa_pub_key = CK_INVALID_HANDLE; 1053*0Sstevel@tonic-gate } 1054*0Sstevel@tonic-gate 1055*0Sstevel@tonic-gate if (sp->rsa_priv_key != CK_INVALID_HANDLE) 1056*0Sstevel@tonic-gate { 1057*0Sstevel@tonic-gate if (pk11_destroy_object(sp->session, 1058*0Sstevel@tonic-gate sp->rsa_priv_key) == 0) 1059*0Sstevel@tonic-gate goto err; 1060*0Sstevel@tonic-gate sp->rsa_priv_key = CK_INVALID_HANDLE; 1061*0Sstevel@tonic-gate } 1062*0Sstevel@tonic-gate 1063*0Sstevel@tonic-gate sp->rsa = NULL; 1064*0Sstevel@tonic-gate } 1065*0Sstevel@tonic-gate ret = 1; 1066*0Sstevel@tonic-gate err: 1067*0Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 1068*0Sstevel@tonic-gate 1069*0Sstevel@tonic-gate return ret; 1070*0Sstevel@tonic-gate } 1071*0Sstevel@tonic-gate 1072*0Sstevel@tonic-gate int pk11_destroy_dsa_key_objects(PK11_SESSION *session) 1073*0Sstevel@tonic-gate { 1074*0Sstevel@tonic-gate int ret = 0; 1075*0Sstevel@tonic-gate PK11_SESSION *sp = NULL; 1076*0Sstevel@tonic-gate PK11_SESSION *local_free_session; 1077*0Sstevel@tonic-gate 1078*0Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 1079*0Sstevel@tonic-gate if (session) 1080*0Sstevel@tonic-gate local_free_session = session; 1081*0Sstevel@tonic-gate else 1082*0Sstevel@tonic-gate local_free_session = free_session; 1083*0Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 1084*0Sstevel@tonic-gate { 1085*0Sstevel@tonic-gate local_free_session = sp->next; 1086*0Sstevel@tonic-gate 1087*0Sstevel@tonic-gate if (sp->dsa_pub_key != CK_INVALID_HANDLE) 1088*0Sstevel@tonic-gate { 1089*0Sstevel@tonic-gate if (pk11_destroy_object(sp->session, 1090*0Sstevel@tonic-gate sp->dsa_pub_key) == 0) 1091*0Sstevel@tonic-gate goto err; 1092*0Sstevel@tonic-gate sp->dsa_pub_key = CK_INVALID_HANDLE; 1093*0Sstevel@tonic-gate } 1094*0Sstevel@tonic-gate 1095*0Sstevel@tonic-gate if (sp->dsa_priv_key != CK_INVALID_HANDLE) 1096*0Sstevel@tonic-gate { 1097*0Sstevel@tonic-gate if (pk11_destroy_object(sp->session, 1098*0Sstevel@tonic-gate sp->dsa_priv_key) == 0) 1099*0Sstevel@tonic-gate goto err; 1100*0Sstevel@tonic-gate sp->dsa_priv_key = CK_INVALID_HANDLE; 1101*0Sstevel@tonic-gate } 1102*0Sstevel@tonic-gate 1103*0Sstevel@tonic-gate sp->dsa = NULL; 1104*0Sstevel@tonic-gate } 1105*0Sstevel@tonic-gate ret = 1; 1106*0Sstevel@tonic-gate err: 1107*0Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 1108*0Sstevel@tonic-gate 1109*0Sstevel@tonic-gate return ret; 1110*0Sstevel@tonic-gate } 1111*0Sstevel@tonic-gate 1112*0Sstevel@tonic-gate int pk11_destroy_dh_key_objects(PK11_SESSION *session) 1113*0Sstevel@tonic-gate { 1114*0Sstevel@tonic-gate int ret = 0; 1115*0Sstevel@tonic-gate PK11_SESSION *sp = NULL; 1116*0Sstevel@tonic-gate PK11_SESSION *local_free_session; 1117*0Sstevel@tonic-gate 1118*0Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 1119*0Sstevel@tonic-gate if (session) 1120*0Sstevel@tonic-gate local_free_session = session; 1121*0Sstevel@tonic-gate else 1122*0Sstevel@tonic-gate local_free_session = free_session; 1123*0Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 1124*0Sstevel@tonic-gate { 1125*0Sstevel@tonic-gate local_free_session = sp->next; 1126*0Sstevel@tonic-gate 1127*0Sstevel@tonic-gate if (sp->dh_key != CK_INVALID_HANDLE) 1128*0Sstevel@tonic-gate { 1129*0Sstevel@tonic-gate if (pk11_destroy_object(sp->session, 1130*0Sstevel@tonic-gate sp->dh_key) == 0) 1131*0Sstevel@tonic-gate goto err; 1132*0Sstevel@tonic-gate sp->dh_key = CK_INVALID_HANDLE; 1133*0Sstevel@tonic-gate } 1134*0Sstevel@tonic-gate 1135*0Sstevel@tonic-gate sp->dh = NULL; 1136*0Sstevel@tonic-gate } 1137*0Sstevel@tonic-gate ret = 1; 1138*0Sstevel@tonic-gate err: 1139*0Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 1140*0Sstevel@tonic-gate 1141*0Sstevel@tonic-gate return ret; 1142*0Sstevel@tonic-gate } 1143*0Sstevel@tonic-gate 1144*0Sstevel@tonic-gate static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh) 1145*0Sstevel@tonic-gate { 1146*0Sstevel@tonic-gate CK_RV rv; 1147*0Sstevel@tonic-gate rv = pFuncList->C_DestroyObject(session, oh); 1148*0Sstevel@tonic-gate if (rv != CKR_OK) 1149*0Sstevel@tonic-gate { 1150*0Sstevel@tonic-gate char tmp_buf[20]; 1151*0Sstevel@tonic-gate PK11err(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT); 1152*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1153*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", 1154*0Sstevel@tonic-gate tmp_buf); 1155*0Sstevel@tonic-gate return 0; 1156*0Sstevel@tonic-gate } 1157*0Sstevel@tonic-gate 1158*0Sstevel@tonic-gate return 1; 1159*0Sstevel@tonic-gate } 1160*0Sstevel@tonic-gate 1161*0Sstevel@tonic-gate 1162*0Sstevel@tonic-gate /* Symmetric ciphers and digests support functions 1163*0Sstevel@tonic-gate */ 1164*0Sstevel@tonic-gate 1165*0Sstevel@tonic-gate static int 1166*0Sstevel@tonic-gate cipher_nid_to_pk11(int nid) 1167*0Sstevel@tonic-gate { 1168*0Sstevel@tonic-gate int i; 1169*0Sstevel@tonic-gate 1170*0Sstevel@tonic-gate for (i = 0; i < PK11_CIPHER_MAX; i++) 1171*0Sstevel@tonic-gate if (ciphers[i].nid == nid) 1172*0Sstevel@tonic-gate return (ciphers[i].id); 1173*0Sstevel@tonic-gate return (-1); 1174*0Sstevel@tonic-gate } 1175*0Sstevel@tonic-gate 1176*0Sstevel@tonic-gate static int 1177*0Sstevel@tonic-gate pk11_usable_ciphers(const int **nids) 1178*0Sstevel@tonic-gate { 1179*0Sstevel@tonic-gate if (cipher_count > 0) 1180*0Sstevel@tonic-gate *nids = cipher_nids; 1181*0Sstevel@tonic-gate else 1182*0Sstevel@tonic-gate *nids = NULL; 1183*0Sstevel@tonic-gate return (cipher_count); 1184*0Sstevel@tonic-gate } 1185*0Sstevel@tonic-gate 1186*0Sstevel@tonic-gate static int 1187*0Sstevel@tonic-gate pk11_usable_digests(const int **nids) 1188*0Sstevel@tonic-gate { 1189*0Sstevel@tonic-gate if (digest_count > 0) 1190*0Sstevel@tonic-gate *nids = digest_nids; 1191*0Sstevel@tonic-gate else 1192*0Sstevel@tonic-gate *nids = NULL; 1193*0Sstevel@tonic-gate return (digest_count); 1194*0Sstevel@tonic-gate } 1195*0Sstevel@tonic-gate 1196*0Sstevel@tonic-gate static int 1197*0Sstevel@tonic-gate pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, 1198*0Sstevel@tonic-gate const unsigned char *iv, int enc) 1199*0Sstevel@tonic-gate { 1200*0Sstevel@tonic-gate CK_RV rv; 1201*0Sstevel@tonic-gate int index; 1202*0Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; 1203*0Sstevel@tonic-gate PK11_SESSION *sp; 1204*0Sstevel@tonic-gate PK11_CIPHER *pcp; 1205*0Sstevel@tonic-gate char tmp_buf[20]; 1206*0Sstevel@tonic-gate 1207*0Sstevel@tonic-gate state->sp = NULL; 1208*0Sstevel@tonic-gate 1209*0Sstevel@tonic-gate index = cipher_nid_to_pk11(ctx->cipher->nid); 1210*0Sstevel@tonic-gate if (index < 0 || index >= PK11_CIPHER_MAX) 1211*0Sstevel@tonic-gate return 0; 1212*0Sstevel@tonic-gate 1213*0Sstevel@tonic-gate pcp = &ciphers[index]; 1214*0Sstevel@tonic-gate if (ctx->cipher->iv_len > pcp->ivmax || ctx->key_len != pcp->key_len) 1215*0Sstevel@tonic-gate return 0; 1216*0Sstevel@tonic-gate 1217*0Sstevel@tonic-gate if ((sp = pk11_get_session()) == NULL) 1218*0Sstevel@tonic-gate return 0; 1219*0Sstevel@tonic-gate 1220*0Sstevel@tonic-gate /* The key object is destroyed here if it is not the current key 1221*0Sstevel@tonic-gate */ 1222*0Sstevel@tonic-gate check_new_cipher_key(sp, key); 1223*0Sstevel@tonic-gate 1224*0Sstevel@tonic-gate /* If the key is the same and the encryption is also the same, 1225*0Sstevel@tonic-gate * then just reuse it 1226*0Sstevel@tonic-gate */ 1227*0Sstevel@tonic-gate if (sp->cipher_key != CK_INVALID_HANDLE && sp->encrypt == ctx->encrypt) 1228*0Sstevel@tonic-gate { 1229*0Sstevel@tonic-gate state->sp = sp; 1230*0Sstevel@tonic-gate return 1; 1231*0Sstevel@tonic-gate } 1232*0Sstevel@tonic-gate 1233*0Sstevel@tonic-gate /* Check if the key has been invalidated. If so, a new key object 1234*0Sstevel@tonic-gate * needs to be created. 1235*0Sstevel@tonic-gate */ 1236*0Sstevel@tonic-gate if (sp->cipher_key == CK_INVALID_HANDLE) 1237*0Sstevel@tonic-gate { 1238*0Sstevel@tonic-gate sp->cipher_key = pk11_get_cipher_key( 1239*0Sstevel@tonic-gate ctx, key, pcp->key_type, sp); 1240*0Sstevel@tonic-gate } 1241*0Sstevel@tonic-gate 1242*0Sstevel@tonic-gate if (sp->encrypt != ctx->encrypt && sp->encrypt != -1) 1243*0Sstevel@tonic-gate { 1244*0Sstevel@tonic-gate /* The previous encryption/decryption 1245*0Sstevel@tonic-gate * is different. Need to terminate the previous 1246*0Sstevel@tonic-gate * active encryption/decryption here 1247*0Sstevel@tonic-gate */ 1248*0Sstevel@tonic-gate if (!pk11_cipher_final(sp)) 1249*0Sstevel@tonic-gate { 1250*0Sstevel@tonic-gate pk11_return_session(sp); 1251*0Sstevel@tonic-gate return 0; 1252*0Sstevel@tonic-gate } 1253*0Sstevel@tonic-gate } 1254*0Sstevel@tonic-gate 1255*0Sstevel@tonic-gate if (sp->cipher_key == CK_INVALID_HANDLE) 1256*0Sstevel@tonic-gate { 1257*0Sstevel@tonic-gate pk11_return_session(sp); 1258*0Sstevel@tonic-gate return 0; 1259*0Sstevel@tonic-gate } 1260*0Sstevel@tonic-gate 1261*0Sstevel@tonic-gate if (ctx->cipher->iv_len > 0) 1262*0Sstevel@tonic-gate { 1263*0Sstevel@tonic-gate pcp->mech.pParameter = (void *) ctx->iv; 1264*0Sstevel@tonic-gate pcp->mech.ulParameterLen = ctx->cipher->iv_len; 1265*0Sstevel@tonic-gate } 1266*0Sstevel@tonic-gate 1267*0Sstevel@tonic-gate /* If we get here, the encryption needs to be reinitialized */ 1268*0Sstevel@tonic-gate if (ctx->encrypt) 1269*0Sstevel@tonic-gate { 1270*0Sstevel@tonic-gate rv = pFuncList->C_EncryptInit(sp->session_cipher, &pcp->mech, 1271*0Sstevel@tonic-gate sp->cipher_key); 1272*0Sstevel@tonic-gate 1273*0Sstevel@tonic-gate if (rv != CKR_OK) 1274*0Sstevel@tonic-gate { 1275*0Sstevel@tonic-gate PK11err(PK11_F_CIPHER_INIT, PK11_R_ENCRYPTINIT); 1276*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1277*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1278*0Sstevel@tonic-gate pk11_return_session(sp); 1279*0Sstevel@tonic-gate return 0; 1280*0Sstevel@tonic-gate } 1281*0Sstevel@tonic-gate } 1282*0Sstevel@tonic-gate else 1283*0Sstevel@tonic-gate { 1284*0Sstevel@tonic-gate rv = pFuncList->C_DecryptInit(sp->session_cipher, &pcp->mech, 1285*0Sstevel@tonic-gate sp->cipher_key); 1286*0Sstevel@tonic-gate 1287*0Sstevel@tonic-gate if (rv != CKR_OK) 1288*0Sstevel@tonic-gate { 1289*0Sstevel@tonic-gate PK11err(PK11_F_CIPHER_INIT, PK11_R_DECRYPTINIT); 1290*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1291*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1292*0Sstevel@tonic-gate pk11_return_session(sp); 1293*0Sstevel@tonic-gate return 0; 1294*0Sstevel@tonic-gate } 1295*0Sstevel@tonic-gate } 1296*0Sstevel@tonic-gate 1297*0Sstevel@tonic-gate sp->encrypt = ctx->encrypt; 1298*0Sstevel@tonic-gate state->sp = sp; 1299*0Sstevel@tonic-gate 1300*0Sstevel@tonic-gate return 1; 1301*0Sstevel@tonic-gate } 1302*0Sstevel@tonic-gate 1303*0Sstevel@tonic-gate /* When reusing the same key in an encryption/decryption session for a 1304*0Sstevel@tonic-gate * decryption/encryption session, we need to close the active session 1305*0Sstevel@tonic-gate * and recreate a new one. Note that the key is in the global session so 1306*0Sstevel@tonic-gate * that it needs not be recreated. 1307*0Sstevel@tonic-gate * 1308*0Sstevel@tonic-gate * It is more appropriate to use C_En/DecryptFinish here. At the time of this 1309*0Sstevel@tonic-gate * development, these two functions in the PKCS#11 libraries used return 1310*0Sstevel@tonic-gate * unexpected errors when passing in 0 length output. It may be a good 1311*0Sstevel@tonic-gate * idea to try them again if performance is a problem here and fix 1312*0Sstevel@tonic-gate * C_En/DecryptFinial if there are bugs there causing the problem. 1313*0Sstevel@tonic-gate */ 1314*0Sstevel@tonic-gate static int 1315*0Sstevel@tonic-gate pk11_cipher_final(PK11_SESSION *sp) 1316*0Sstevel@tonic-gate { 1317*0Sstevel@tonic-gate CK_RV rv; 1318*0Sstevel@tonic-gate char tmp_buf[20]; 1319*0Sstevel@tonic-gate 1320*0Sstevel@tonic-gate rv = pFuncList->C_CloseSession(sp->session_cipher); 1321*0Sstevel@tonic-gate if (rv != CKR_OK) 1322*0Sstevel@tonic-gate { 1323*0Sstevel@tonic-gate PK11err(PK11_F_CIPHER_FINAL, PK11_R_CLOSESESSION); 1324*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1325*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1326*0Sstevel@tonic-gate return 0; 1327*0Sstevel@tonic-gate } 1328*0Sstevel@tonic-gate 1329*0Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 1330*0Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session_cipher); 1331*0Sstevel@tonic-gate if (rv != CKR_OK) 1332*0Sstevel@tonic-gate { 1333*0Sstevel@tonic-gate PK11err(PK11_F_CIPHER_FINAL, PK11_R_OPENSESSION); 1334*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1335*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1336*0Sstevel@tonic-gate return 0; 1337*0Sstevel@tonic-gate } 1338*0Sstevel@tonic-gate 1339*0Sstevel@tonic-gate return 1; 1340*0Sstevel@tonic-gate } 1341*0Sstevel@tonic-gate 1342*0Sstevel@tonic-gate /* An engine interface function. The calling function allocates sufficient 1343*0Sstevel@tonic-gate * memory for the output buffer "out" to hold the results */ 1344*0Sstevel@tonic-gate static int 1345*0Sstevel@tonic-gate pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 1346*0Sstevel@tonic-gate const unsigned char *in, unsigned int inl) 1347*0Sstevel@tonic-gate { 1348*0Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; 1349*0Sstevel@tonic-gate PK11_SESSION *sp; 1350*0Sstevel@tonic-gate CK_RV rv; 1351*0Sstevel@tonic-gate unsigned long outl = inl; 1352*0Sstevel@tonic-gate char tmp_buf[20]; 1353*0Sstevel@tonic-gate 1354*0Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 1355*0Sstevel@tonic-gate return 0; 1356*0Sstevel@tonic-gate 1357*0Sstevel@tonic-gate sp = (PK11_SESSION *) state->sp; 1358*0Sstevel@tonic-gate 1359*0Sstevel@tonic-gate if (!inl) 1360*0Sstevel@tonic-gate return 1; 1361*0Sstevel@tonic-gate 1362*0Sstevel@tonic-gate /* RC4 is the only stream cipher we support */ 1363*0Sstevel@tonic-gate if (ctx->cipher->nid != NID_rc4 && (inl % ctx->cipher->block_size) != 0) 1364*0Sstevel@tonic-gate return 0; 1365*0Sstevel@tonic-gate 1366*0Sstevel@tonic-gate if (ctx->encrypt) 1367*0Sstevel@tonic-gate { 1368*0Sstevel@tonic-gate rv = pFuncList->C_EncryptUpdate(sp->session_cipher, 1369*0Sstevel@tonic-gate (unsigned char *)in, inl, out, &outl); 1370*0Sstevel@tonic-gate 1371*0Sstevel@tonic-gate if (rv != CKR_OK) 1372*0Sstevel@tonic-gate { 1373*0Sstevel@tonic-gate PK11err(PK11_F_CIPHER_DO_CIPHER, 1374*0Sstevel@tonic-gate PK11_R_ENCRYPTUPDATE); 1375*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1376*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1377*0Sstevel@tonic-gate return 0; 1378*0Sstevel@tonic-gate } 1379*0Sstevel@tonic-gate } 1380*0Sstevel@tonic-gate else 1381*0Sstevel@tonic-gate { 1382*0Sstevel@tonic-gate rv = pFuncList->C_DecryptUpdate(sp->session_cipher, 1383*0Sstevel@tonic-gate (unsigned char *)in, inl, out, &outl); 1384*0Sstevel@tonic-gate 1385*0Sstevel@tonic-gate if (rv != CKR_OK) 1386*0Sstevel@tonic-gate { 1387*0Sstevel@tonic-gate PK11err(PK11_F_CIPHER_DO_CIPHER, 1388*0Sstevel@tonic-gate PK11_R_DECRYPTUPDATE); 1389*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1390*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1391*0Sstevel@tonic-gate return 0; 1392*0Sstevel@tonic-gate } 1393*0Sstevel@tonic-gate } 1394*0Sstevel@tonic-gate 1395*0Sstevel@tonic-gate /* for DES_CBC, DES3_CBC, AES_CBC, and RC4, the output size is always 1396*0Sstevel@tonic-gate * the same size of input 1397*0Sstevel@tonic-gate * The application has guaranteed to call the block ciphers with 1398*0Sstevel@tonic-gate * correctly aligned buffers. 1399*0Sstevel@tonic-gate */ 1400*0Sstevel@tonic-gate if (inl != outl) 1401*0Sstevel@tonic-gate return 0; 1402*0Sstevel@tonic-gate 1403*0Sstevel@tonic-gate return 1; 1404*0Sstevel@tonic-gate } 1405*0Sstevel@tonic-gate 1406*0Sstevel@tonic-gate /* Return the session to the pool. The C_EncryptFinal and C_DecryptFinal are 1407*0Sstevel@tonic-gate * not used. Once a secret key is initialized, it is used until destroyed. 1408*0Sstevel@tonic-gate */ 1409*0Sstevel@tonic-gate static int 1410*0Sstevel@tonic-gate pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx) 1411*0Sstevel@tonic-gate { 1412*0Sstevel@tonic-gate PK11_CIPHER_STATE *state = ctx->cipher_data; 1413*0Sstevel@tonic-gate 1414*0Sstevel@tonic-gate if (state != NULL && state->sp != NULL) 1415*0Sstevel@tonic-gate { 1416*0Sstevel@tonic-gate pk11_return_session(state->sp); 1417*0Sstevel@tonic-gate state->sp = NULL; 1418*0Sstevel@tonic-gate } 1419*0Sstevel@tonic-gate 1420*0Sstevel@tonic-gate return 1; 1421*0Sstevel@tonic-gate } 1422*0Sstevel@tonic-gate 1423*0Sstevel@tonic-gate /* Registered by the ENGINE when used to find out how to deal with 1424*0Sstevel@tonic-gate * a particular NID in the ENGINE. This says what we'll do at the 1425*0Sstevel@tonic-gate * top level - note, that list is restricted by what we answer with 1426*0Sstevel@tonic-gate */ 1427*0Sstevel@tonic-gate static int 1428*0Sstevel@tonic-gate pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 1429*0Sstevel@tonic-gate const int **nids, int nid) 1430*0Sstevel@tonic-gate { 1431*0Sstevel@tonic-gate if (!cipher) 1432*0Sstevel@tonic-gate return (pk11_usable_ciphers(nids)); 1433*0Sstevel@tonic-gate 1434*0Sstevel@tonic-gate switch (nid) 1435*0Sstevel@tonic-gate { 1436*0Sstevel@tonic-gate case NID_des_ede3_cbc: 1437*0Sstevel@tonic-gate *cipher = &pk11_3des_cbc; 1438*0Sstevel@tonic-gate break; 1439*0Sstevel@tonic-gate case NID_des_cbc: 1440*0Sstevel@tonic-gate *cipher = &pk11_des_cbc; 1441*0Sstevel@tonic-gate break; 1442*0Sstevel@tonic-gate case NID_aes_128_cbc: 1443*0Sstevel@tonic-gate *cipher = &pk11_aes_cbc; 1444*0Sstevel@tonic-gate break; 1445*0Sstevel@tonic-gate case NID_rc4: 1446*0Sstevel@tonic-gate *cipher = &pk11_rc4; 1447*0Sstevel@tonic-gate break; 1448*0Sstevel@tonic-gate default: 1449*0Sstevel@tonic-gate *cipher = NULL; 1450*0Sstevel@tonic-gate break; 1451*0Sstevel@tonic-gate } 1452*0Sstevel@tonic-gate return (*cipher != NULL); 1453*0Sstevel@tonic-gate } 1454*0Sstevel@tonic-gate 1455*0Sstevel@tonic-gate static int 1456*0Sstevel@tonic-gate pk11_engine_digests(ENGINE *e, const EVP_MD **digest, 1457*0Sstevel@tonic-gate const int **nids, int nid) 1458*0Sstevel@tonic-gate { 1459*0Sstevel@tonic-gate if (!digest) 1460*0Sstevel@tonic-gate return (pk11_usable_digests(nids)); 1461*0Sstevel@tonic-gate 1462*0Sstevel@tonic-gate switch (nid) 1463*0Sstevel@tonic-gate { 1464*0Sstevel@tonic-gate case NID_md5: 1465*0Sstevel@tonic-gate *digest = &pk11_md5; 1466*0Sstevel@tonic-gate break; 1467*0Sstevel@tonic-gate case NID_sha1: 1468*0Sstevel@tonic-gate *digest = &pk11_sha1; 1469*0Sstevel@tonic-gate break; 1470*0Sstevel@tonic-gate default: 1471*0Sstevel@tonic-gate *digest = NULL; 1472*0Sstevel@tonic-gate break; 1473*0Sstevel@tonic-gate } 1474*0Sstevel@tonic-gate return (*digest != NULL); 1475*0Sstevel@tonic-gate } 1476*0Sstevel@tonic-gate 1477*0Sstevel@tonic-gate 1478*0Sstevel@tonic-gate /* Create a secret key object in a PKCS#11 session 1479*0Sstevel@tonic-gate */ 1480*0Sstevel@tonic-gate static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, 1481*0Sstevel@tonic-gate const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp) 1482*0Sstevel@tonic-gate { 1483*0Sstevel@tonic-gate CK_RV rv; 1484*0Sstevel@tonic-gate CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; 1485*0Sstevel@tonic-gate CK_ULONG found; 1486*0Sstevel@tonic-gate CK_OBJECT_CLASS obj_key = CKO_SECRET_KEY; 1487*0Sstevel@tonic-gate CK_ULONG ul_key_attr_count = 6; 1488*0Sstevel@tonic-gate char tmp_buf[20]; 1489*0Sstevel@tonic-gate 1490*0Sstevel@tonic-gate CK_ATTRIBUTE a_key_template[] = 1491*0Sstevel@tonic-gate { 1492*0Sstevel@tonic-gate {CKA_CLASS, (void*) NULL, sizeof(CK_OBJECT_CLASS)}, 1493*0Sstevel@tonic-gate {CKA_KEY_TYPE, (void*) NULL, sizeof(CK_KEY_TYPE)}, 1494*0Sstevel@tonic-gate {CKA_TOKEN, &false, sizeof(false)}, 1495*0Sstevel@tonic-gate {CKA_ENCRYPT, &true, sizeof(true)}, 1496*0Sstevel@tonic-gate {CKA_DECRYPT, &true, sizeof(true)}, 1497*0Sstevel@tonic-gate {CKA_VALUE, (void*) NULL, 0}, 1498*0Sstevel@tonic-gate }; 1499*0Sstevel@tonic-gate 1500*0Sstevel@tonic-gate /* Create secret key object in global_session. All other sessions 1501*0Sstevel@tonic-gate * can use the key handles. Here is why: 1502*0Sstevel@tonic-gate * OpenSSL will call EncryptInit and EncryptUpdate using a secret key. 1503*0Sstevel@tonic-gate * It may then call DecryptInit and DecryptUpdate using the same key. 1504*0Sstevel@tonic-gate * To use the same key object, we need to call EncryptFinal with 1505*0Sstevel@tonic-gate * a 0 length message. Currently, this does not work for 3DES 1506*0Sstevel@tonic-gate * mechanism. To get around this problem, we close the session and 1507*0Sstevel@tonic-gate * then create a new session to use the same key object. When a session 1508*0Sstevel@tonic-gate * is closed, all the object handles will be invalid. Thus, create key 1509*0Sstevel@tonic-gate * objects in a global session, an individual session may be closed to 1510*0Sstevel@tonic-gate * terminate the active operation. 1511*0Sstevel@tonic-gate */ 1512*0Sstevel@tonic-gate CK_SESSION_HANDLE session = global_session; 1513*0Sstevel@tonic-gate a_key_template[0].pValue = &obj_key; 1514*0Sstevel@tonic-gate a_key_template[1].pValue = &key_type; 1515*0Sstevel@tonic-gate a_key_template[5].pValue = (void *) key; 1516*0Sstevel@tonic-gate a_key_template[5].ulValueLen = (unsigned long) ctx->key_len; 1517*0Sstevel@tonic-gate 1518*0Sstevel@tonic-gate rv = pFuncList->C_FindObjectsInit(session, a_key_template, 1519*0Sstevel@tonic-gate ul_key_attr_count); 1520*0Sstevel@tonic-gate 1521*0Sstevel@tonic-gate if (rv != CKR_OK) 1522*0Sstevel@tonic-gate { 1523*0Sstevel@tonic-gate PK11err(PK11_F_GET_CIPHER_KEY, PK11_R_FINDOBJECTSINIT); 1524*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1525*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1526*0Sstevel@tonic-gate goto err; 1527*0Sstevel@tonic-gate } 1528*0Sstevel@tonic-gate 1529*0Sstevel@tonic-gate rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); 1530*0Sstevel@tonic-gate 1531*0Sstevel@tonic-gate if (rv != CKR_OK) 1532*0Sstevel@tonic-gate { 1533*0Sstevel@tonic-gate PK11err(PK11_F_GET_CIPHER_KEY, PK11_R_FINDOBJECTS); 1534*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1535*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1536*0Sstevel@tonic-gate goto err; 1537*0Sstevel@tonic-gate } 1538*0Sstevel@tonic-gate 1539*0Sstevel@tonic-gate rv = pFuncList->C_FindObjectsFinal(session); 1540*0Sstevel@tonic-gate 1541*0Sstevel@tonic-gate if (rv != CKR_OK) 1542*0Sstevel@tonic-gate { 1543*0Sstevel@tonic-gate PK11err(PK11_F_GET_CIPHER_KEY, PK11_R_FINDOBJECTSFINAL); 1544*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1545*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1546*0Sstevel@tonic-gate goto err; 1547*0Sstevel@tonic-gate } 1548*0Sstevel@tonic-gate 1549*0Sstevel@tonic-gate if (found == 0) 1550*0Sstevel@tonic-gate { 1551*0Sstevel@tonic-gate rv = pFuncList->C_CreateObject(session, 1552*0Sstevel@tonic-gate a_key_template, ul_key_attr_count, &h_key); 1553*0Sstevel@tonic-gate if (rv != CKR_OK) 1554*0Sstevel@tonic-gate { 1555*0Sstevel@tonic-gate PK11err(PK11_F_GET_CIPHER_KEY, 1556*0Sstevel@tonic-gate PK11_R_CREATEOBJECT); 1557*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1558*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1559*0Sstevel@tonic-gate goto err; 1560*0Sstevel@tonic-gate } 1561*0Sstevel@tonic-gate } 1562*0Sstevel@tonic-gate 1563*0Sstevel@tonic-gate /* Save the key information used in this session. 1564*0Sstevel@tonic-gate * The max can be saved is PK11_KEY_LEN_MAX. 1565*0Sstevel@tonic-gate */ 1566*0Sstevel@tonic-gate sp->key_len = ctx->key_len > PK11_KEY_LEN_MAX ? 1567*0Sstevel@tonic-gate PK11_KEY_LEN_MAX : ctx->key_len; 1568*0Sstevel@tonic-gate memcpy(sp->key, key, sp->key_len); 1569*0Sstevel@tonic-gate err: 1570*0Sstevel@tonic-gate 1571*0Sstevel@tonic-gate return h_key; 1572*0Sstevel@tonic-gate } 1573*0Sstevel@tonic-gate 1574*0Sstevel@tonic-gate static int 1575*0Sstevel@tonic-gate md_nid_to_pk11(int nid) 1576*0Sstevel@tonic-gate { 1577*0Sstevel@tonic-gate int i; 1578*0Sstevel@tonic-gate 1579*0Sstevel@tonic-gate for (i = 0; i < PK11_DIGEST_MAX; i++) 1580*0Sstevel@tonic-gate if (digests[i].nid == nid) 1581*0Sstevel@tonic-gate return (digests[i].id); 1582*0Sstevel@tonic-gate return (-1); 1583*0Sstevel@tonic-gate } 1584*0Sstevel@tonic-gate 1585*0Sstevel@tonic-gate static int 1586*0Sstevel@tonic-gate pk11_digest_init(EVP_MD_CTX *ctx) 1587*0Sstevel@tonic-gate { 1588*0Sstevel@tonic-gate CK_RV rv; 1589*0Sstevel@tonic-gate int index; 1590*0Sstevel@tonic-gate PK11_SESSION *sp; 1591*0Sstevel@tonic-gate PK11_DIGEST *pdp; 1592*0Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; 1593*0Sstevel@tonic-gate 1594*0Sstevel@tonic-gate state->sp = NULL; 1595*0Sstevel@tonic-gate 1596*0Sstevel@tonic-gate index = md_nid_to_pk11(ctx->digest->type); 1597*0Sstevel@tonic-gate if (index < 0 || index >= PK11_DIGEST_MAX) 1598*0Sstevel@tonic-gate return 0; 1599*0Sstevel@tonic-gate 1600*0Sstevel@tonic-gate pdp = &digests[index]; 1601*0Sstevel@tonic-gate if ((sp = pk11_get_session()) == NULL) 1602*0Sstevel@tonic-gate return 0; 1603*0Sstevel@tonic-gate 1604*0Sstevel@tonic-gate rv = pFuncList->C_DigestInit(sp->session, &pdp->mech); 1605*0Sstevel@tonic-gate 1606*0Sstevel@tonic-gate if (rv != CKR_OK) 1607*0Sstevel@tonic-gate { 1608*0Sstevel@tonic-gate char tmp_buf[20]; 1609*0Sstevel@tonic-gate PK11err(PK11_F_DIGEST_INIT, PK11_R_DIGESTINIT); 1610*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1611*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1612*0Sstevel@tonic-gate pk11_return_session(sp); 1613*0Sstevel@tonic-gate return 0; 1614*0Sstevel@tonic-gate } 1615*0Sstevel@tonic-gate 1616*0Sstevel@tonic-gate state->sp = sp; 1617*0Sstevel@tonic-gate 1618*0Sstevel@tonic-gate return 1; 1619*0Sstevel@tonic-gate } 1620*0Sstevel@tonic-gate 1621*0Sstevel@tonic-gate static int 1622*0Sstevel@tonic-gate pk11_digest_update(EVP_MD_CTX *ctx,const void *data,unsigned long count) 1623*0Sstevel@tonic-gate { 1624*0Sstevel@tonic-gate CK_RV rv; 1625*0Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; 1626*0Sstevel@tonic-gate 1627*0Sstevel@tonic-gate /* 0 length message will cause a failure in C_DigestFinal */ 1628*0Sstevel@tonic-gate if (count == 0) 1629*0Sstevel@tonic-gate return 1; 1630*0Sstevel@tonic-gate 1631*0Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 1632*0Sstevel@tonic-gate return 0; 1633*0Sstevel@tonic-gate 1634*0Sstevel@tonic-gate rv = pFuncList->C_DigestUpdate(state->sp->session, (CK_BYTE *) data, 1635*0Sstevel@tonic-gate count); 1636*0Sstevel@tonic-gate 1637*0Sstevel@tonic-gate if (rv != CKR_OK) 1638*0Sstevel@tonic-gate { 1639*0Sstevel@tonic-gate char tmp_buf[20]; 1640*0Sstevel@tonic-gate PK11err(PK11_F_DIGEST_UPDATE, PK11_R_DIGESTUPDATE); 1641*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1642*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1643*0Sstevel@tonic-gate pk11_return_session(state->sp); 1644*0Sstevel@tonic-gate state->sp = NULL; 1645*0Sstevel@tonic-gate return 0; 1646*0Sstevel@tonic-gate } 1647*0Sstevel@tonic-gate 1648*0Sstevel@tonic-gate return 1; 1649*0Sstevel@tonic-gate } 1650*0Sstevel@tonic-gate 1651*0Sstevel@tonic-gate static int 1652*0Sstevel@tonic-gate pk11_digest_final(EVP_MD_CTX *ctx,unsigned char *md) 1653*0Sstevel@tonic-gate { 1654*0Sstevel@tonic-gate CK_RV rv; 1655*0Sstevel@tonic-gate unsigned long len; 1656*0Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; 1657*0Sstevel@tonic-gate len = ctx->digest->md_size; 1658*0Sstevel@tonic-gate 1659*0Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 1660*0Sstevel@tonic-gate return 0; 1661*0Sstevel@tonic-gate 1662*0Sstevel@tonic-gate rv = pFuncList->C_DigestFinal(state->sp->session, md, &len); 1663*0Sstevel@tonic-gate 1664*0Sstevel@tonic-gate if (rv != CKR_OK) 1665*0Sstevel@tonic-gate { 1666*0Sstevel@tonic-gate char tmp_buf[20]; 1667*0Sstevel@tonic-gate PK11err(PK11_F_DIGEST_FINAL, PK11_R_DIGESTFINAL); 1668*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1669*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1670*0Sstevel@tonic-gate pk11_return_session(state->sp); 1671*0Sstevel@tonic-gate state->sp = NULL; 1672*0Sstevel@tonic-gate return 0; 1673*0Sstevel@tonic-gate } 1674*0Sstevel@tonic-gate 1675*0Sstevel@tonic-gate if (ctx->digest->md_size != len) 1676*0Sstevel@tonic-gate return 0; 1677*0Sstevel@tonic-gate 1678*0Sstevel@tonic-gate /* Final is called and digest is returned, so return the session 1679*0Sstevel@tonic-gate * to the pool 1680*0Sstevel@tonic-gate */ 1681*0Sstevel@tonic-gate pk11_return_session(state->sp); 1682*0Sstevel@tonic-gate state->sp = NULL; 1683*0Sstevel@tonic-gate 1684*0Sstevel@tonic-gate return 1; 1685*0Sstevel@tonic-gate } 1686*0Sstevel@tonic-gate 1687*0Sstevel@tonic-gate static int 1688*0Sstevel@tonic-gate pk11_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from) 1689*0Sstevel@tonic-gate { 1690*0Sstevel@tonic-gate CK_RV rv; 1691*0Sstevel@tonic-gate int ret = 0; 1692*0Sstevel@tonic-gate PK11_CIPHER_STATE *state, *state_to; 1693*0Sstevel@tonic-gate CK_BYTE_PTR pstate = NULL; 1694*0Sstevel@tonic-gate CK_ULONG ul_state_len; 1695*0Sstevel@tonic-gate char tmp_buf[20]; 1696*0Sstevel@tonic-gate 1697*0Sstevel@tonic-gate /* The copy-from state */ 1698*0Sstevel@tonic-gate state = (PK11_CIPHER_STATE *) from->md_data; 1699*0Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 1700*0Sstevel@tonic-gate goto err; 1701*0Sstevel@tonic-gate 1702*0Sstevel@tonic-gate /* Initialize the copy-to state */ 1703*0Sstevel@tonic-gate if (!pk11_digest_init(to)) 1704*0Sstevel@tonic-gate goto err; 1705*0Sstevel@tonic-gate state_to = (PK11_CIPHER_STATE *) to->md_data; 1706*0Sstevel@tonic-gate 1707*0Sstevel@tonic-gate /* Get the size of the operation state of the copy-from session */ 1708*0Sstevel@tonic-gate rv = pFuncList->C_GetOperationState(state->sp->session, NULL, 1709*0Sstevel@tonic-gate &ul_state_len); 1710*0Sstevel@tonic-gate 1711*0Sstevel@tonic-gate if (rv != CKR_OK) 1712*0Sstevel@tonic-gate { 1713*0Sstevel@tonic-gate PK11err(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE); 1714*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1715*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1716*0Sstevel@tonic-gate goto err; 1717*0Sstevel@tonic-gate } 1718*0Sstevel@tonic-gate if (ul_state_len == 0) 1719*0Sstevel@tonic-gate { 1720*0Sstevel@tonic-gate goto err; 1721*0Sstevel@tonic-gate } 1722*0Sstevel@tonic-gate 1723*0Sstevel@tonic-gate pstate = OPENSSL_malloc(ul_state_len); 1724*0Sstevel@tonic-gate if (pstate == NULL) 1725*0Sstevel@tonic-gate { 1726*0Sstevel@tonic-gate RSAerr(PK11_F_DIGEST_COPY, PK11_R_MALLOC_FAILURE); 1727*0Sstevel@tonic-gate goto err; 1728*0Sstevel@tonic-gate } 1729*0Sstevel@tonic-gate 1730*0Sstevel@tonic-gate /* Get the operation state of the copy-from session */ 1731*0Sstevel@tonic-gate rv = pFuncList->C_GetOperationState(state->sp->session, pstate, 1732*0Sstevel@tonic-gate &ul_state_len); 1733*0Sstevel@tonic-gate 1734*0Sstevel@tonic-gate if (rv != CKR_OK) 1735*0Sstevel@tonic-gate { 1736*0Sstevel@tonic-gate PK11err(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE); 1737*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1738*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1739*0Sstevel@tonic-gate goto err; 1740*0Sstevel@tonic-gate } 1741*0Sstevel@tonic-gate 1742*0Sstevel@tonic-gate /* Set the operation state of the copy-to session */ 1743*0Sstevel@tonic-gate rv = pFuncList->C_SetOperationState(state_to->sp->session, pstate, 1744*0Sstevel@tonic-gate ul_state_len, 0, 0); 1745*0Sstevel@tonic-gate 1746*0Sstevel@tonic-gate if (rv != CKR_OK) 1747*0Sstevel@tonic-gate { 1748*0Sstevel@tonic-gate PK11err(PK11_F_DIGEST_COPY, PK11_R_SET_OPERATION_STATE); 1749*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1750*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1751*0Sstevel@tonic-gate goto err; 1752*0Sstevel@tonic-gate } 1753*0Sstevel@tonic-gate 1754*0Sstevel@tonic-gate ret = 1; 1755*0Sstevel@tonic-gate err: 1756*0Sstevel@tonic-gate if (pstate != NULL) 1757*0Sstevel@tonic-gate OPENSSL_free(pstate); 1758*0Sstevel@tonic-gate 1759*0Sstevel@tonic-gate return ret; 1760*0Sstevel@tonic-gate } 1761*0Sstevel@tonic-gate 1762*0Sstevel@tonic-gate /* Return any pending session state to the pool */ 1763*0Sstevel@tonic-gate static int 1764*0Sstevel@tonic-gate pk11_digest_cleanup(EVP_MD_CTX *ctx) 1765*0Sstevel@tonic-gate { 1766*0Sstevel@tonic-gate PK11_CIPHER_STATE *state = ctx->md_data; 1767*0Sstevel@tonic-gate 1768*0Sstevel@tonic-gate if (state != NULL && state->sp != NULL) 1769*0Sstevel@tonic-gate { 1770*0Sstevel@tonic-gate pk11_return_session(state->sp); 1771*0Sstevel@tonic-gate state->sp = NULL; 1772*0Sstevel@tonic-gate } 1773*0Sstevel@tonic-gate 1774*0Sstevel@tonic-gate return 1; 1775*0Sstevel@tonic-gate } 1776*0Sstevel@tonic-gate 1777*0Sstevel@tonic-gate /* Check if the new key is the same as the key object in the session. 1778*0Sstevel@tonic-gate * If the key is the same, no need to create a new key object. Otherwise, 1779*0Sstevel@tonic-gate * the old key object needs to be destroyed and a new one will be created 1780*0Sstevel@tonic-gate */ 1781*0Sstevel@tonic-gate static void check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key) 1782*0Sstevel@tonic-gate { 1783*0Sstevel@tonic-gate if (memcmp(sp->key, key, sp->key_len) != 0) 1784*0Sstevel@tonic-gate pk11_destroy_cipher_key_objects(sp); 1785*0Sstevel@tonic-gate } 1786*0Sstevel@tonic-gate 1787*0Sstevel@tonic-gate /* Destroy one or more secret key objects. 1788*0Sstevel@tonic-gate */ 1789*0Sstevel@tonic-gate static int pk11_destroy_cipher_key_objects(PK11_SESSION *session) 1790*0Sstevel@tonic-gate { 1791*0Sstevel@tonic-gate int ret = 0; 1792*0Sstevel@tonic-gate PK11_SESSION *sp = NULL; 1793*0Sstevel@tonic-gate PK11_SESSION *local_free_session; 1794*0Sstevel@tonic-gate 1795*0Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 1796*0Sstevel@tonic-gate if (session) 1797*0Sstevel@tonic-gate local_free_session = session; 1798*0Sstevel@tonic-gate else 1799*0Sstevel@tonic-gate local_free_session = free_session; 1800*0Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 1801*0Sstevel@tonic-gate { 1802*0Sstevel@tonic-gate local_free_session = sp->next; 1803*0Sstevel@tonic-gate 1804*0Sstevel@tonic-gate if (sp->cipher_key != CK_INVALID_HANDLE) 1805*0Sstevel@tonic-gate { 1806*0Sstevel@tonic-gate /* The secret key object is created in the 1807*0Sstevel@tonic-gate * global_session. See pk11_get_cipher_key 1808*0Sstevel@tonic-gate */ 1809*0Sstevel@tonic-gate if (pk11_destroy_object(global_session, 1810*0Sstevel@tonic-gate sp->cipher_key) == 0) 1811*0Sstevel@tonic-gate goto err; 1812*0Sstevel@tonic-gate sp->cipher_key = CK_INVALID_HANDLE; 1813*0Sstevel@tonic-gate } 1814*0Sstevel@tonic-gate } 1815*0Sstevel@tonic-gate ret = 1; 1816*0Sstevel@tonic-gate err: 1817*0Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 1818*0Sstevel@tonic-gate 1819*0Sstevel@tonic-gate return ret; 1820*0Sstevel@tonic-gate } 1821*0Sstevel@tonic-gate 1822*0Sstevel@tonic-gate 1823*0Sstevel@tonic-gate /* 1824*0Sstevel@tonic-gate * Required mechanisms 1825*0Sstevel@tonic-gate * 1826*0Sstevel@tonic-gate * CKM_RSA_X_509 1827*0Sstevel@tonic-gate * CKM_RSA_PKCS 1828*0Sstevel@tonic-gate * CKM_DSA 1829*0Sstevel@tonic-gate * 1830*0Sstevel@tonic-gate * As long as these required mechanisms are met, it will return success. 1831*0Sstevel@tonic-gate * Otherwise, it will return failure and the engine initialization will fail. 1832*0Sstevel@tonic-gate * The application will then decide whether to use another engine or 1833*0Sstevel@tonic-gate * no engine. 1834*0Sstevel@tonic-gate * 1835*0Sstevel@tonic-gate * Symmetric ciphers optionally supported 1836*0Sstevel@tonic-gate * 1837*0Sstevel@tonic-gate * CKM_DES3_CBC 1838*0Sstevel@tonic-gate * CKM_DES_CBC 1839*0Sstevel@tonic-gate * CKM_AES_CBC 1840*0Sstevel@tonic-gate * CKM_RC4 1841*0Sstevel@tonic-gate * 1842*0Sstevel@tonic-gate * Digests optionally supported 1843*0Sstevel@tonic-gate * 1844*0Sstevel@tonic-gate * CKM_MD5 1845*0Sstevel@tonic-gate * CKM_SHA_1 1846*0Sstevel@tonic-gate */ 1847*0Sstevel@tonic-gate 1848*0Sstevel@tonic-gate static int 1849*0Sstevel@tonic-gate pk11_choose_slot() 1850*0Sstevel@tonic-gate { 1851*0Sstevel@tonic-gate CK_SLOT_ID_PTR pSlotList = NULL_PTR; 1852*0Sstevel@tonic-gate CK_ULONG ulSlotCount = 0; 1853*0Sstevel@tonic-gate CK_MECHANISM_INFO mech_info; 1854*0Sstevel@tonic-gate CK_TOKEN_INFO token_info; 1855*0Sstevel@tonic-gate int i; 1856*0Sstevel@tonic-gate CK_RV rv; 1857*0Sstevel@tonic-gate CK_SLOT_ID best_slot_sofar; 1858*0Sstevel@tonic-gate CK_BBOOL found_candidate_slot = CK_FALSE; 1859*0Sstevel@tonic-gate int slot_n_cipher = 0; 1860*0Sstevel@tonic-gate int slot_n_digest = 0; 1861*0Sstevel@tonic-gate CK_SLOT_ID current_slot = 0; 1862*0Sstevel@tonic-gate int current_slot_n_cipher = 0; 1863*0Sstevel@tonic-gate int current_slot_n_digest = 0; 1864*0Sstevel@tonic-gate 1865*0Sstevel@tonic-gate int local_cipher_nids[PK11_CIPHER_MAX]; 1866*0Sstevel@tonic-gate int local_digest_nids[PK11_DIGEST_MAX]; 1867*0Sstevel@tonic-gate char tmp_buf[20]; 1868*0Sstevel@tonic-gate int retval = 0; 1869*0Sstevel@tonic-gate 1870*0Sstevel@tonic-gate /* Get slot list for memory alloction */ 1871*0Sstevel@tonic-gate rv = pFuncList->C_GetSlotList(0, NULL_PTR, &ulSlotCount); 1872*0Sstevel@tonic-gate 1873*0Sstevel@tonic-gate if (rv != CKR_OK) 1874*0Sstevel@tonic-gate { 1875*0Sstevel@tonic-gate PK11err(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST); 1876*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1877*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1878*0Sstevel@tonic-gate return retval; 1879*0Sstevel@tonic-gate } 1880*0Sstevel@tonic-gate 1881*0Sstevel@tonic-gate if (ulSlotCount == 0) 1882*0Sstevel@tonic-gate { 1883*0Sstevel@tonic-gate PK11err(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST); 1884*0Sstevel@tonic-gate return retval; 1885*0Sstevel@tonic-gate } 1886*0Sstevel@tonic-gate 1887*0Sstevel@tonic-gate pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); 1888*0Sstevel@tonic-gate 1889*0Sstevel@tonic-gate if (pSlotList == NULL) 1890*0Sstevel@tonic-gate { 1891*0Sstevel@tonic-gate RSAerr(PK11_F_CHOOSE_SLOT,PK11_R_MALLOC_FAILURE); 1892*0Sstevel@tonic-gate return retval; 1893*0Sstevel@tonic-gate } 1894*0Sstevel@tonic-gate 1895*0Sstevel@tonic-gate /* Get the slot list for processing */ 1896*0Sstevel@tonic-gate rv = pFuncList->C_GetSlotList(0, pSlotList, &ulSlotCount); 1897*0Sstevel@tonic-gate if (rv != CKR_OK) 1898*0Sstevel@tonic-gate { 1899*0Sstevel@tonic-gate PK11err(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST); 1900*0Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 1901*0Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 1902*0Sstevel@tonic-gate OPENSSL_free(pSlotList); 1903*0Sstevel@tonic-gate return retval; 1904*0Sstevel@tonic-gate } 1905*0Sstevel@tonic-gate 1906*0Sstevel@tonic-gate for (i = 0; i < ulSlotCount; i++) 1907*0Sstevel@tonic-gate { 1908*0Sstevel@tonic-gate CK_BBOOL slot_has_rsa = CK_FALSE; 1909*0Sstevel@tonic-gate CK_BBOOL slot_has_dsa = CK_FALSE; 1910*0Sstevel@tonic-gate CK_BBOOL slot_has_dh = CK_FALSE; 1911*0Sstevel@tonic-gate current_slot = pSlotList[i]; 1912*0Sstevel@tonic-gate current_slot_n_cipher = 0; 1913*0Sstevel@tonic-gate current_slot_n_digest = 0; 1914*0Sstevel@tonic-gate memset(local_cipher_nids, 0, sizeof(local_cipher_nids)); 1915*0Sstevel@tonic-gate memset(local_digest_nids, 0, sizeof(local_digest_nids)); 1916*0Sstevel@tonic-gate 1917*0Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 1918*0Sstevel@tonic-gate fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: checking slot: %d\n", 1919*0Sstevel@tonic-gate current_slot); 1920*0Sstevel@tonic-gate #endif 1921*0Sstevel@tonic-gate /* Check if slot has random support. */ 1922*0Sstevel@tonic-gate rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); 1923*0Sstevel@tonic-gate if (rv != CKR_OK) 1924*0Sstevel@tonic-gate continue; 1925*0Sstevel@tonic-gate 1926*0Sstevel@tonic-gate if (token_info.flags & CKF_RNG) 1927*0Sstevel@tonic-gate pk11_have_random = CK_TRUE; 1928*0Sstevel@tonic-gate 1929*0Sstevel@tonic-gate /* 1930*0Sstevel@tonic-gate * Check if this slot is capable of signing and 1931*0Sstevel@tonic-gate * verifying with CKM_RSA_PKCS. 1932*0Sstevel@tonic-gate */ 1933*0Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS, 1934*0Sstevel@tonic-gate &mech_info); 1935*0Sstevel@tonic-gate 1936*0Sstevel@tonic-gate if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && 1937*0Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY))) 1938*0Sstevel@tonic-gate { 1939*0Sstevel@tonic-gate /* 1940*0Sstevel@tonic-gate * Check if this slot is capable of encryption, 1941*0Sstevel@tonic-gate * decryption, sign, and verify with CKM_RSA_X_509. 1942*0Sstevel@tonic-gate */ 1943*0Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, 1944*0Sstevel@tonic-gate CKM_RSA_X_509, &mech_info); 1945*0Sstevel@tonic-gate 1946*0Sstevel@tonic-gate if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && 1947*0Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY) && 1948*0Sstevel@tonic-gate (mech_info.flags & CKF_ENCRYPT) && 1949*0Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY_RECOVER) && 1950*0Sstevel@tonic-gate (mech_info.flags & CKF_DECRYPT))) 1951*0Sstevel@tonic-gate slot_has_rsa = CK_TRUE; 1952*0Sstevel@tonic-gate } 1953*0Sstevel@tonic-gate 1954*0Sstevel@tonic-gate /* 1955*0Sstevel@tonic-gate * Check if this slot is capable of signing and 1956*0Sstevel@tonic-gate * verifying with CKM_DSA. 1957*0Sstevel@tonic-gate */ 1958*0Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA, 1959*0Sstevel@tonic-gate &mech_info); 1960*0Sstevel@tonic-gate if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && 1961*0Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY))) 1962*0Sstevel@tonic-gate slot_has_dsa = CK_TRUE; 1963*0Sstevel@tonic-gate 1964*0Sstevel@tonic-gate /* 1965*0Sstevel@tonic-gate * Check if this slot is capable of DH key generataion and 1966*0Sstevel@tonic-gate * derivation. 1967*0Sstevel@tonic-gate */ 1968*0Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, 1969*0Sstevel@tonic-gate CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info); 1970*0Sstevel@tonic-gate 1971*0Sstevel@tonic-gate if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR)) 1972*0Sstevel@tonic-gate { 1973*0Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, 1974*0Sstevel@tonic-gate CKM_DH_PKCS_DERIVE, &mech_info); 1975*0Sstevel@tonic-gate if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE)) 1976*0Sstevel@tonic-gate slot_has_dh = CK_TRUE; 1977*0Sstevel@tonic-gate } 1978*0Sstevel@tonic-gate 1979*0Sstevel@tonic-gate if (!found_candidate_slot && 1980*0Sstevel@tonic-gate (slot_has_rsa || slot_has_dsa || slot_has_dh)) 1981*0Sstevel@tonic-gate { 1982*0Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 1983*0Sstevel@tonic-gate fprintf(stderr, 1984*0Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: potential slot: %d\n", 1985*0Sstevel@tonic-gate current_slot); 1986*0Sstevel@tonic-gate #endif 1987*0Sstevel@tonic-gate best_slot_sofar = current_slot; 1988*0Sstevel@tonic-gate pk11_have_rsa = slot_has_rsa; 1989*0Sstevel@tonic-gate pk11_have_dsa = slot_has_dsa; 1990*0Sstevel@tonic-gate pk11_have_dh = slot_has_dh; 1991*0Sstevel@tonic-gate found_candidate_slot = CK_TRUE; 1992*0Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 1993*0Sstevel@tonic-gate fprintf(stderr, 1994*0Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: best so far slot: %d\n", 1995*0Sstevel@tonic-gate best_slot_sofar); 1996*0Sstevel@tonic-gate #endif 1997*0Sstevel@tonic-gate } 1998*0Sstevel@tonic-gate 1999*0Sstevel@tonic-gate /* Count symmetric cipher support. */ 2000*0Sstevel@tonic-gate if (!pk11_count_symmetric_cipher(current_slot, CKM_DES_CBC, 2001*0Sstevel@tonic-gate ¤t_slot_n_cipher, local_cipher_nids, 2002*0Sstevel@tonic-gate PK11_DES_CBC)) 2003*0Sstevel@tonic-gate continue; 2004*0Sstevel@tonic-gate if (!pk11_count_symmetric_cipher(current_slot, CKM_DES3_CBC, 2005*0Sstevel@tonic-gate ¤t_slot_n_cipher, local_cipher_nids, 2006*0Sstevel@tonic-gate PK11_DES3_CBC)) 2007*0Sstevel@tonic-gate continue; 2008*0Sstevel@tonic-gate if (!pk11_count_symmetric_cipher(current_slot, CKM_AES_CBC, 2009*0Sstevel@tonic-gate ¤t_slot_n_cipher, local_cipher_nids, 2010*0Sstevel@tonic-gate PK11_AES_CBC)) 2011*0Sstevel@tonic-gate continue; 2012*0Sstevel@tonic-gate if (!pk11_count_symmetric_cipher(current_slot, CKM_RC4, 2013*0Sstevel@tonic-gate ¤t_slot_n_cipher, local_cipher_nids, 2014*0Sstevel@tonic-gate PK11_RC4)) 2015*0Sstevel@tonic-gate continue; 2016*0Sstevel@tonic-gate 2017*0Sstevel@tonic-gate /* Count digest support */ 2018*0Sstevel@tonic-gate if (!pk11_count_digest(current_slot, CKM_MD5, 2019*0Sstevel@tonic-gate ¤t_slot_n_digest, local_digest_nids, 2020*0Sstevel@tonic-gate PK11_MD5)) 2021*0Sstevel@tonic-gate continue; 2022*0Sstevel@tonic-gate if (!pk11_count_digest(current_slot, CKM_SHA_1, 2023*0Sstevel@tonic-gate ¤t_slot_n_digest, local_digest_nids, 2024*0Sstevel@tonic-gate PK11_SHA1)) 2025*0Sstevel@tonic-gate continue; 2026*0Sstevel@tonic-gate 2027*0Sstevel@tonic-gate /* 2028*0Sstevel@tonic-gate * If the current slot supports more ciphers/digests than 2029*0Sstevel@tonic-gate * the previous best one we change the current best to this one. 2030*0Sstevel@tonic-gate * otherwise leave it where it is. 2031*0Sstevel@tonic-gate */ 2032*0Sstevel@tonic-gate if (((current_slot_n_cipher > slot_n_cipher) && 2033*0Sstevel@tonic-gate (current_slot_n_digest > slot_n_digest)) && 2034*0Sstevel@tonic-gate ((slot_has_rsa == pk11_have_rsa) && 2035*0Sstevel@tonic-gate (slot_has_dsa == pk11_have_dsa) && 2036*0Sstevel@tonic-gate (slot_has_dh == pk11_have_dh))) 2037*0Sstevel@tonic-gate { 2038*0Sstevel@tonic-gate best_slot_sofar = current_slot; 2039*0Sstevel@tonic-gate slot_n_cipher = current_slot_n_cipher; 2040*0Sstevel@tonic-gate slot_n_digest = current_slot_n_digest; 2041*0Sstevel@tonic-gate 2042*0Sstevel@tonic-gate memcpy(cipher_nids, local_cipher_nids, 2043*0Sstevel@tonic-gate sizeof(local_cipher_nids)); 2044*0Sstevel@tonic-gate memcpy(digest_nids, local_digest_nids, 2045*0Sstevel@tonic-gate sizeof(local_digest_nids)); 2046*0Sstevel@tonic-gate } 2047*0Sstevel@tonic-gate 2048*0Sstevel@tonic-gate } 2049*0Sstevel@tonic-gate 2050*0Sstevel@tonic-gate if (found_candidate_slot) 2051*0Sstevel@tonic-gate { 2052*0Sstevel@tonic-gate cipher_count = slot_n_cipher; 2053*0Sstevel@tonic-gate digest_count = slot_n_digest; 2054*0Sstevel@tonic-gate SLOTID = best_slot_sofar; 2055*0Sstevel@tonic-gate retval = 1; 2056*0Sstevel@tonic-gate } 2057*0Sstevel@tonic-gate else 2058*0Sstevel@tonic-gate { 2059*0Sstevel@tonic-gate cipher_count = 0; 2060*0Sstevel@tonic-gate digest_count = 0; 2061*0Sstevel@tonic-gate } 2062*0Sstevel@tonic-gate 2063*0Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 2064*0Sstevel@tonic-gate fprintf(stderr, 2065*0Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: choose slot: %d\n", SLOTID); 2066*0Sstevel@tonic-gate fprintf(stderr, 2067*0Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: pk11_have_rsa %d\n", pk11_have_rsa); 2068*0Sstevel@tonic-gate fprintf(stderr, 2069*0Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: pk11_have_dsa %d\n", pk11_have_dsa); 2070*0Sstevel@tonic-gate fprintf(stderr, 2071*0Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: pk11_have_dh %d\n", pk11_have_dh); 2072*0Sstevel@tonic-gate fprintf(stderr, 2073*0Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: pk11_have_random %d\n", pk11_have_random); 2074*0Sstevel@tonic-gate #endif /* DEBUG_SLOT_SELECTION */ 2075*0Sstevel@tonic-gate 2076*0Sstevel@tonic-gate if (pSlotList) 2077*0Sstevel@tonic-gate free(pSlotList); 2078*0Sstevel@tonic-gate 2079*0Sstevel@tonic-gate return retval; 2080*0Sstevel@tonic-gate } 2081*0Sstevel@tonic-gate 2082*0Sstevel@tonic-gate static int pk11_count_symmetric_cipher(int slot_id, CK_MECHANISM_TYPE mech, 2083*0Sstevel@tonic-gate int *current_slot_n_cipher, int *local_cipher_nids, int id) 2084*0Sstevel@tonic-gate { 2085*0Sstevel@tonic-gate CK_MECHANISM_INFO mech_info; 2086*0Sstevel@tonic-gate CK_RV rv; 2087*0Sstevel@tonic-gate 2088*0Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(slot_id, mech, &mech_info); 2089*0Sstevel@tonic-gate 2090*0Sstevel@tonic-gate if (rv != CKR_OK) 2091*0Sstevel@tonic-gate return 0; 2092*0Sstevel@tonic-gate 2093*0Sstevel@tonic-gate if ((mech_info.flags & CKF_ENCRYPT) && 2094*0Sstevel@tonic-gate (mech_info.flags & CKF_DECRYPT)) 2095*0Sstevel@tonic-gate { 2096*0Sstevel@tonic-gate local_cipher_nids[(*current_slot_n_cipher)++] = ciphers[id].nid; 2097*0Sstevel@tonic-gate } 2098*0Sstevel@tonic-gate 2099*0Sstevel@tonic-gate return 1; 2100*0Sstevel@tonic-gate } 2101*0Sstevel@tonic-gate 2102*0Sstevel@tonic-gate 2103*0Sstevel@tonic-gate static int pk11_count_digest(int slot_id, CK_MECHANISM_TYPE mech, 2104*0Sstevel@tonic-gate int *current_slot_n_digest, int *local_digest_nids, int id) 2105*0Sstevel@tonic-gate { 2106*0Sstevel@tonic-gate CK_MECHANISM_INFO mech_info; 2107*0Sstevel@tonic-gate CK_RV rv; 2108*0Sstevel@tonic-gate 2109*0Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(slot_id, mech, &mech_info); 2110*0Sstevel@tonic-gate 2111*0Sstevel@tonic-gate if (rv != CKR_OK) 2112*0Sstevel@tonic-gate return 0; 2113*0Sstevel@tonic-gate 2114*0Sstevel@tonic-gate if (mech_info.flags & CKF_DIGEST) 2115*0Sstevel@tonic-gate { 2116*0Sstevel@tonic-gate local_digest_nids[(*current_slot_n_digest)++] = digests[id].nid; 2117*0Sstevel@tonic-gate } 2118*0Sstevel@tonic-gate 2119*0Sstevel@tonic-gate return 1; 2120*0Sstevel@tonic-gate } 2121*0Sstevel@tonic-gate 2122*0Sstevel@tonic-gate 2123*0Sstevel@tonic-gate #endif 2124*0Sstevel@tonic-gate #endif 2125*0Sstevel@tonic-gate 2126