10Sstevel@tonic-gate /* 24245Sjp161948 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 30Sstevel@tonic-gate * Use is subject to license terms. 40Sstevel@tonic-gate */ 50Sstevel@tonic-gate 60Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 70Sstevel@tonic-gate 80Sstevel@tonic-gate /* crypto/engine/hw_pk11.c */ 90Sstevel@tonic-gate /* This product includes software developed by the OpenSSL Project for 100Sstevel@tonic-gate * use in the OpenSSL Toolkit (http://www.openssl.org/). 110Sstevel@tonic-gate * 120Sstevel@tonic-gate * This project also referenced hw_pkcs11-0.9.7b.patch written by 130Sstevel@tonic-gate * Afchine Madjlessi. 140Sstevel@tonic-gate */ 150Sstevel@tonic-gate /* ==================================================================== 160Sstevel@tonic-gate * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. 170Sstevel@tonic-gate * 180Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 190Sstevel@tonic-gate * modification, are permitted provided that the following conditions 200Sstevel@tonic-gate * are met: 210Sstevel@tonic-gate * 220Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 230Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 240Sstevel@tonic-gate * 250Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 260Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in 270Sstevel@tonic-gate * the documentation and/or other materials provided with the 280Sstevel@tonic-gate * distribution. 290Sstevel@tonic-gate * 300Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this 310Sstevel@tonic-gate * software must display the following acknowledgment: 320Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project 330Sstevel@tonic-gate * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 340Sstevel@tonic-gate * 350Sstevel@tonic-gate * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 360Sstevel@tonic-gate * endorse or promote products derived from this software without 370Sstevel@tonic-gate * prior written permission. For written permission, please contact 380Sstevel@tonic-gate * licensing@OpenSSL.org. 390Sstevel@tonic-gate * 400Sstevel@tonic-gate * 5. Products derived from this software may not be called "OpenSSL" 410Sstevel@tonic-gate * nor may "OpenSSL" appear in their names without prior written 420Sstevel@tonic-gate * permission of the OpenSSL Project. 430Sstevel@tonic-gate * 440Sstevel@tonic-gate * 6. Redistributions of any form whatsoever must retain the following 450Sstevel@tonic-gate * acknowledgment: 460Sstevel@tonic-gate * "This product includes software developed by the OpenSSL Project 470Sstevel@tonic-gate * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 480Sstevel@tonic-gate * 490Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 500Sstevel@tonic-gate * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 510Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 520Sstevel@tonic-gate * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 530Sstevel@tonic-gate * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 540Sstevel@tonic-gate * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 550Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 560Sstevel@tonic-gate * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 570Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 580Sstevel@tonic-gate * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 590Sstevel@tonic-gate * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 600Sstevel@tonic-gate * OF THE POSSIBILITY OF SUCH DAMAGE. 610Sstevel@tonic-gate * ==================================================================== 620Sstevel@tonic-gate * 630Sstevel@tonic-gate * This product includes cryptographic software written by Eric Young 640Sstevel@tonic-gate * (eay@cryptsoft.com). This product includes software written by Tim 650Sstevel@tonic-gate * Hudson (tjh@cryptsoft.com). 660Sstevel@tonic-gate * 670Sstevel@tonic-gate */ 680Sstevel@tonic-gate 690Sstevel@tonic-gate #include <stdio.h> 700Sstevel@tonic-gate #include <assert.h> 710Sstevel@tonic-gate #include <stdlib.h> 720Sstevel@tonic-gate #include <string.h> 730Sstevel@tonic-gate #include <sys/types.h> 740Sstevel@tonic-gate #include <unistd.h> 750Sstevel@tonic-gate 760Sstevel@tonic-gate #include <openssl/e_os2.h> 770Sstevel@tonic-gate #include <openssl/engine.h> 780Sstevel@tonic-gate #include <openssl/dso.h> 790Sstevel@tonic-gate #include <openssl/err.h> 800Sstevel@tonic-gate #include <openssl/bn.h> 812139Sjp161948 #include <openssl/md5.h> 820Sstevel@tonic-gate #include <openssl/pem.h> 830Sstevel@tonic-gate #include <openssl/rsa.h> 840Sstevel@tonic-gate #include <openssl/rand.h> 850Sstevel@tonic-gate #include <openssl/objects.h> 860Sstevel@tonic-gate #include <openssl/x509.h> 870Sstevel@tonic-gate #include <cryptlib.h> 880Sstevel@tonic-gate 890Sstevel@tonic-gate #ifndef OPENSSL_NO_HW 900Sstevel@tonic-gate #ifndef OPENSSL_NO_HW_PK11 910Sstevel@tonic-gate 920Sstevel@tonic-gate #undef DEBUG_SLOT_SELECTION 930Sstevel@tonic-gate 940Sstevel@tonic-gate #include "security/cryptoki.h" 950Sstevel@tonic-gate #include "security/pkcs11.h" 960Sstevel@tonic-gate #include "hw_pk11_err.c" 970Sstevel@tonic-gate 980Sstevel@tonic-gate 990Sstevel@tonic-gate /* The head of the free PK11 session list */ 1000Sstevel@tonic-gate static struct PK11_SESSION_st *free_session = NULL; 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate /* Create all secret key objects in a global session so that they are available 1030Sstevel@tonic-gate * to use for other sessions. These other sessions may be opened or closed 1040Sstevel@tonic-gate * without losing the secret key objects */ 1050Sstevel@tonic-gate static CK_SESSION_HANDLE global_session = CK_INVALID_HANDLE; 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate /* ENGINE level stuff */ 1080Sstevel@tonic-gate static int pk11_init(ENGINE *e); 1090Sstevel@tonic-gate static int pk11_library_init(ENGINE *e); 1100Sstevel@tonic-gate static int pk11_finish(ENGINE *e); 1110Sstevel@tonic-gate static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()); 1120Sstevel@tonic-gate static int pk11_destroy(ENGINE *e); 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate /* RAND stuff */ 1150Sstevel@tonic-gate static void pk11_rand_seed(const void *buf, int num); 1160Sstevel@tonic-gate static void pk11_rand_add(const void *buf, int num, double add_entropy); 1170Sstevel@tonic-gate static void pk11_rand_cleanup(void); 1180Sstevel@tonic-gate static int pk11_rand_bytes(unsigned char *buf, int num); 1190Sstevel@tonic-gate static int pk11_rand_status(void); 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate /* These functions are also used in other files */ 1220Sstevel@tonic-gate PK11_SESSION *pk11_get_session(); 1230Sstevel@tonic-gate void pk11_return_session(PK11_SESSION *sp); 1240Sstevel@tonic-gate int pk11_destroy_rsa_key_objects(PK11_SESSION *session); 1250Sstevel@tonic-gate int pk11_destroy_dsa_key_objects(PK11_SESSION *session); 1260Sstevel@tonic-gate int pk11_destroy_dh_key_objects(PK11_SESSION *session); 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate /* Local helper functions */ 1290Sstevel@tonic-gate static int pk11_free_all_sessions(); 1300Sstevel@tonic-gate static int pk11_setup_session(PK11_SESSION *sp); 1310Sstevel@tonic-gate static int pk11_destroy_cipher_key_objects(PK11_SESSION *session); 1320Sstevel@tonic-gate static int pk11_destroy_object(CK_SESSION_HANDLE session, 1330Sstevel@tonic-gate CK_OBJECT_HANDLE oh); 1340Sstevel@tonic-gate static const char *get_PK11_LIBNAME(void); 1350Sstevel@tonic-gate static void free_PK11_LIBNAME(void); 1360Sstevel@tonic-gate static long set_PK11_LIBNAME(const char *name); 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate /* Symmetric cipher and digest support functions */ 1390Sstevel@tonic-gate static int cipher_nid_to_pk11(int nid); 1400Sstevel@tonic-gate static int pk11_usable_ciphers(const int **nids); 1410Sstevel@tonic-gate static int pk11_usable_digests(const int **nids); 1420Sstevel@tonic-gate static int pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, 1430Sstevel@tonic-gate const unsigned char *iv, int enc); 1440Sstevel@tonic-gate static int pk11_cipher_final(PK11_SESSION *sp); 1450Sstevel@tonic-gate static int pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 1460Sstevel@tonic-gate const unsigned char *in, unsigned int inl); 1470Sstevel@tonic-gate static int pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx); 1480Sstevel@tonic-gate static int pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 1490Sstevel@tonic-gate const int **nids, int nid); 1500Sstevel@tonic-gate static int pk11_engine_digests(ENGINE *e, const EVP_MD **digest, 1510Sstevel@tonic-gate const int **nids, int nid); 1520Sstevel@tonic-gate static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, 1530Sstevel@tonic-gate const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp); 1540Sstevel@tonic-gate static void check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key); 1550Sstevel@tonic-gate static int md_nid_to_pk11(int nid); 1560Sstevel@tonic-gate static int pk11_digest_init(EVP_MD_CTX *ctx); 1570Sstevel@tonic-gate static int pk11_digest_update(EVP_MD_CTX *ctx,const void *data, 1582139Sjp161948 size_t count); 1590Sstevel@tonic-gate static int pk11_digest_final(EVP_MD_CTX *ctx,unsigned char *md); 1600Sstevel@tonic-gate static int pk11_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from); 1610Sstevel@tonic-gate static int pk11_digest_cleanup(EVP_MD_CTX *ctx); 1620Sstevel@tonic-gate 1630Sstevel@tonic-gate static int pk11_choose_slot(); 1640Sstevel@tonic-gate static int pk11_count_symmetric_cipher(int slot_id, CK_MECHANISM_TYPE mech, 1650Sstevel@tonic-gate int *current_slot_n_cipher, int *local_cipher_nids, int id); 1660Sstevel@tonic-gate static int pk11_count_digest(int slot_id, CK_MECHANISM_TYPE mech, 1670Sstevel@tonic-gate int *current_slot_n_digest, int *local_digest_nids, int id); 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate /* Index for the supported ciphers */ 1700Sstevel@tonic-gate #define PK11_DES_CBC 0 1710Sstevel@tonic-gate #define PK11_DES3_CBC 1 1720Sstevel@tonic-gate #define PK11_AES_CBC 2 1730Sstevel@tonic-gate #define PK11_RC4 3 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate /* Index for the supported digests */ 1760Sstevel@tonic-gate #define PK11_MD5 0 1770Sstevel@tonic-gate #define PK11_SHA1 1 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate #define PK11_CIPHER_MAX 4 /* Max num of ciphers supported */ 1800Sstevel@tonic-gate #define PK11_DIGEST_MAX 2 /* Max num of digests supported */ 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate #define PK11_KEY_LEN_MAX 24 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate static int cipher_nids[PK11_CIPHER_MAX]; 1850Sstevel@tonic-gate static int digest_nids[PK11_DIGEST_MAX]; 1860Sstevel@tonic-gate static int cipher_count = 0; 1870Sstevel@tonic-gate static int digest_count = 0; 1880Sstevel@tonic-gate static CK_BBOOL pk11_have_rsa = CK_FALSE; 1890Sstevel@tonic-gate static CK_BBOOL pk11_have_dsa = CK_FALSE; 1900Sstevel@tonic-gate static CK_BBOOL pk11_have_dh = CK_FALSE; 1910Sstevel@tonic-gate static CK_BBOOL pk11_have_random = CK_FALSE; 1920Sstevel@tonic-gate 1930Sstevel@tonic-gate typedef struct PK11_CIPHER_st 1940Sstevel@tonic-gate { 195*4320Sjp161948 int id; 196*4320Sjp161948 int nid; 197*4320Sjp161948 int ivmax; 198*4320Sjp161948 int key_len; 199*4320Sjp161948 CK_KEY_TYPE key_type; 200*4320Sjp161948 CK_MECHANISM_TYPE mech_type; 2010Sstevel@tonic-gate } PK11_CIPHER; 2020Sstevel@tonic-gate 2030Sstevel@tonic-gate static PK11_CIPHER ciphers[] = 2040Sstevel@tonic-gate { 205*4320Sjp161948 {PK11_DES_CBC, NID_des_cbc, 8, 8, CKK_DES, CKM_DES_CBC, }, 206*4320Sjp161948 {PK11_DES3_CBC, NID_des_ede3_cbc, 8, 24, CKK_DES3, CKM_DES3_CBC, }, 207*4320Sjp161948 {PK11_AES_CBC, NID_aes_128_cbc, 16, 16, CKK_AES, CKM_AES_CBC, }, 208*4320Sjp161948 {PK11_RC4, NID_rc4, 0, 16, CKK_RC4, CKM_RC4, }, 2090Sstevel@tonic-gate }; 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate typedef struct PK11_DIGEST_st 2120Sstevel@tonic-gate { 213*4320Sjp161948 int id; 214*4320Sjp161948 int nid; 215*4320Sjp161948 CK_MECHANISM_TYPE mech_type; 2160Sstevel@tonic-gate } PK11_DIGEST; 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate static PK11_DIGEST digests[] = 2190Sstevel@tonic-gate { 220*4320Sjp161948 {PK11_MD5, NID_md5, CKM_MD5, }, 221*4320Sjp161948 {PK11_SHA1, NID_sha1, CKM_SHA_1, }, 222*4320Sjp161948 {0, NID_undef, 0xFFFF, }, 2230Sstevel@tonic-gate }; 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate /* Structure to be used for the cipher_data/md_data in 2260Sstevel@tonic-gate * EVP_CIPHER_CTX/EVP_MD_CTX structures in order to use the same 2270Sstevel@tonic-gate * pk11 session in multiple cipher_update calls 2280Sstevel@tonic-gate */ 2290Sstevel@tonic-gate typedef struct PK11_CIPHER_STATE_st 2300Sstevel@tonic-gate { 2310Sstevel@tonic-gate PK11_SESSION *sp; 2320Sstevel@tonic-gate } PK11_CIPHER_STATE; 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate 2350Sstevel@tonic-gate /* libcrypto EVP stuff - this is how we get wired to EVP so the engine 2360Sstevel@tonic-gate * gets called when libcrypto requests a cipher NID. 2370Sstevel@tonic-gate * Note how the PK11_CIPHER_STATE is used here. 2380Sstevel@tonic-gate */ 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate /* DES CBC EVP */ 2410Sstevel@tonic-gate static const EVP_CIPHER pk11_des_cbc = 2420Sstevel@tonic-gate { 2430Sstevel@tonic-gate NID_des_cbc, 2440Sstevel@tonic-gate 8, 8, 8, 2450Sstevel@tonic-gate EVP_CIPH_CBC_MODE, 2460Sstevel@tonic-gate pk11_cipher_init, 2470Sstevel@tonic-gate pk11_cipher_do_cipher, 2480Sstevel@tonic-gate pk11_cipher_cleanup, 2490Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 2500Sstevel@tonic-gate EVP_CIPHER_set_asn1_iv, 2510Sstevel@tonic-gate EVP_CIPHER_get_asn1_iv, 2520Sstevel@tonic-gate NULL 2530Sstevel@tonic-gate }; 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate /* 3DES CBC EVP */ 2560Sstevel@tonic-gate static const EVP_CIPHER pk11_3des_cbc = 2570Sstevel@tonic-gate { 2580Sstevel@tonic-gate NID_des_ede3_cbc, 2590Sstevel@tonic-gate 8, 24, 8, 2600Sstevel@tonic-gate EVP_CIPH_CBC_MODE, 2610Sstevel@tonic-gate pk11_cipher_init, 2620Sstevel@tonic-gate pk11_cipher_do_cipher, 2630Sstevel@tonic-gate pk11_cipher_cleanup, 2640Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 2650Sstevel@tonic-gate EVP_CIPHER_set_asn1_iv, 2660Sstevel@tonic-gate EVP_CIPHER_get_asn1_iv, 2670Sstevel@tonic-gate NULL 2680Sstevel@tonic-gate }; 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate static const EVP_CIPHER pk11_aes_cbc = 2710Sstevel@tonic-gate { 2720Sstevel@tonic-gate NID_aes_128_cbc, 2730Sstevel@tonic-gate 16, 16, 16, 2740Sstevel@tonic-gate EVP_CIPH_CBC_MODE, 2750Sstevel@tonic-gate pk11_cipher_init, 2760Sstevel@tonic-gate pk11_cipher_do_cipher, 2770Sstevel@tonic-gate pk11_cipher_cleanup, 2780Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 2790Sstevel@tonic-gate EVP_CIPHER_set_asn1_iv, 2800Sstevel@tonic-gate EVP_CIPHER_get_asn1_iv, 2810Sstevel@tonic-gate NULL 2820Sstevel@tonic-gate }; 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate static const EVP_CIPHER pk11_rc4 = 2850Sstevel@tonic-gate { 2860Sstevel@tonic-gate NID_rc4, 2870Sstevel@tonic-gate 1,16,0, 2880Sstevel@tonic-gate EVP_CIPH_VARIABLE_LENGTH, 2890Sstevel@tonic-gate pk11_cipher_init, 2900Sstevel@tonic-gate pk11_cipher_do_cipher, 2910Sstevel@tonic-gate pk11_cipher_cleanup, 2920Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 2930Sstevel@tonic-gate NULL, 2940Sstevel@tonic-gate NULL, 2950Sstevel@tonic-gate NULL 2960Sstevel@tonic-gate }; 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate static const EVP_MD pk11_md5 = 2990Sstevel@tonic-gate { 3000Sstevel@tonic-gate NID_md5, 3010Sstevel@tonic-gate NID_md5WithRSAEncryption, 3020Sstevel@tonic-gate MD5_DIGEST_LENGTH, 3030Sstevel@tonic-gate 0, 3040Sstevel@tonic-gate pk11_digest_init, 3050Sstevel@tonic-gate pk11_digest_update, 3060Sstevel@tonic-gate pk11_digest_final, 3070Sstevel@tonic-gate pk11_digest_copy, 3080Sstevel@tonic-gate pk11_digest_cleanup, 3090Sstevel@tonic-gate EVP_PKEY_RSA_method, 3100Sstevel@tonic-gate MD5_CBLOCK, 3110Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 3120Sstevel@tonic-gate }; 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate static const EVP_MD pk11_sha1 = 3150Sstevel@tonic-gate { 3160Sstevel@tonic-gate NID_sha1, 3170Sstevel@tonic-gate NID_sha1WithRSAEncryption, 3180Sstevel@tonic-gate SHA_DIGEST_LENGTH, 3190Sstevel@tonic-gate 0, 3200Sstevel@tonic-gate pk11_digest_init, 3210Sstevel@tonic-gate pk11_digest_update, 3220Sstevel@tonic-gate pk11_digest_final, 3230Sstevel@tonic-gate pk11_digest_copy, 3240Sstevel@tonic-gate pk11_digest_cleanup, 3250Sstevel@tonic-gate EVP_PKEY_RSA_method, 3260Sstevel@tonic-gate SHA_CBLOCK, 3270Sstevel@tonic-gate sizeof(PK11_CIPHER_STATE), 3280Sstevel@tonic-gate }; 3290Sstevel@tonic-gate 3300Sstevel@tonic-gate /* Initialization function. Sets up various pk11 library components. 3310Sstevel@tonic-gate */ 3320Sstevel@tonic-gate /* The definitions for control commands specific to this engine 3330Sstevel@tonic-gate */ 3340Sstevel@tonic-gate #define PK11_CMD_SO_PATH ENGINE_CMD_BASE 3350Sstevel@tonic-gate static const ENGINE_CMD_DEFN pk11_cmd_defns[] = 3360Sstevel@tonic-gate { 3370Sstevel@tonic-gate { 3380Sstevel@tonic-gate PK11_CMD_SO_PATH, 3390Sstevel@tonic-gate "SO_PATH", 3400Sstevel@tonic-gate "Specifies the path to the 'pkcs#11' shared library", 3410Sstevel@tonic-gate ENGINE_CMD_FLAG_STRING 3420Sstevel@tonic-gate }, 3430Sstevel@tonic-gate {0, NULL, NULL, 0} 3440Sstevel@tonic-gate }; 3450Sstevel@tonic-gate 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate static RAND_METHOD pk11_random = 3480Sstevel@tonic-gate { 3490Sstevel@tonic-gate pk11_rand_seed, 3500Sstevel@tonic-gate pk11_rand_bytes, 3510Sstevel@tonic-gate pk11_rand_cleanup, 3520Sstevel@tonic-gate pk11_rand_add, 3530Sstevel@tonic-gate pk11_rand_bytes, 3540Sstevel@tonic-gate pk11_rand_status 3550Sstevel@tonic-gate }; 3560Sstevel@tonic-gate 3570Sstevel@tonic-gate 3580Sstevel@tonic-gate /* Constants used when creating the ENGINE 3590Sstevel@tonic-gate */ 3600Sstevel@tonic-gate static const char *engine_pk11_id = "pkcs11"; 3610Sstevel@tonic-gate static const char *engine_pk11_name = "PKCS #11 engine support"; 3620Sstevel@tonic-gate 3630Sstevel@tonic-gate CK_FUNCTION_LIST_PTR pFuncList = NULL; 3640Sstevel@tonic-gate static const char PK11_GET_FUNCTION_LIST[] = "C_GetFunctionList"; 3650Sstevel@tonic-gate 3660Sstevel@tonic-gate /* These are the static string constants for the DSO file name and the function 3670Sstevel@tonic-gate * symbol names to bind to. 3680Sstevel@tonic-gate */ 3690Sstevel@tonic-gate #if defined(__sparcv9) || defined(__x86_64) || defined(__amd64) 3700Sstevel@tonic-gate static const char def_PK11_LIBNAME[] = "/usr/lib/64/libpkcs11.so.1"; 3710Sstevel@tonic-gate #else 3720Sstevel@tonic-gate static const char def_PK11_LIBNAME[] = "/usr/lib/libpkcs11.so.1"; 3730Sstevel@tonic-gate #endif 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate /* CRYPTO_LOCK_RSA is defined in OpenSSL for RSA method. Since this pk11 3760Sstevel@tonic-gate * engine replaces RSA method, we may reuse this lock here. 3770Sstevel@tonic-gate */ 3780Sstevel@tonic-gate #define CRYPTO_LOCK_PK11_ENGINE CRYPTO_LOCK_RSA 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate static CK_BBOOL true = TRUE; 3810Sstevel@tonic-gate static CK_BBOOL false = FALSE; 3820Sstevel@tonic-gate static CK_SLOT_ID SLOTID = 0; 3830Sstevel@tonic-gate static int pk11_library_initialized = 0; 3840Sstevel@tonic-gate 3850Sstevel@tonic-gate static DSO *pk11_dso = NULL; 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate /* 3880Sstevel@tonic-gate * This internal function is used by ENGINE_pk11() and "dynamic" ENGINE support. 3890Sstevel@tonic-gate */ 3900Sstevel@tonic-gate static int bind_pk11(ENGINE *e) 3910Sstevel@tonic-gate { 3920Sstevel@tonic-gate const RSA_METHOD *rsa = NULL; 3930Sstevel@tonic-gate RSA_METHOD *pk11_rsa = PK11_RSA(); 3940Sstevel@tonic-gate 3950Sstevel@tonic-gate if (!pk11_library_initialized) 3960Sstevel@tonic-gate pk11_library_init(e); 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate if(!ENGINE_set_id(e, engine_pk11_id) || 3990Sstevel@tonic-gate !ENGINE_set_name(e, engine_pk11_name) || 4000Sstevel@tonic-gate !ENGINE_set_ciphers(e, pk11_engine_ciphers) || 4010Sstevel@tonic-gate !ENGINE_set_digests(e, pk11_engine_digests)) 4020Sstevel@tonic-gate return 0; 4030Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA 4040Sstevel@tonic-gate if(pk11_have_rsa == CK_TRUE) 4050Sstevel@tonic-gate { 4060Sstevel@tonic-gate if(!ENGINE_set_RSA(e, PK11_RSA()) || 4070Sstevel@tonic-gate !ENGINE_set_load_privkey_function(e, pk11_load_privkey) || 4080Sstevel@tonic-gate !ENGINE_set_load_pubkey_function(e, pk11_load_pubkey)) 4090Sstevel@tonic-gate return 0; 4100Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 4110Sstevel@tonic-gate fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: registered RSA\n"); 4120Sstevel@tonic-gate #endif /* DEBUG_SLOT_SELECTION */ 4130Sstevel@tonic-gate } 4140Sstevel@tonic-gate #endif 4150Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA 4160Sstevel@tonic-gate if(pk11_have_dsa == CK_TRUE) 4170Sstevel@tonic-gate { 4180Sstevel@tonic-gate if (!ENGINE_set_DSA(e, PK11_DSA())) 4190Sstevel@tonic-gate return 0; 4200Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 4210Sstevel@tonic-gate fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: registered DSA\n"); 4220Sstevel@tonic-gate #endif /* DEBUG_SLOT_SELECTION */ 4230Sstevel@tonic-gate } 4240Sstevel@tonic-gate #endif 4250Sstevel@tonic-gate #ifndef OPENSSL_NO_DH 4260Sstevel@tonic-gate if(pk11_have_dh == CK_TRUE) 4270Sstevel@tonic-gate { 4280Sstevel@tonic-gate if (!ENGINE_set_DH(e, PK11_DH())) 4290Sstevel@tonic-gate return 0; 4300Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 4310Sstevel@tonic-gate fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: registered DH\n"); 4320Sstevel@tonic-gate #endif /* DEBUG_SLOT_SELECTION */ 4330Sstevel@tonic-gate } 4340Sstevel@tonic-gate #endif 4350Sstevel@tonic-gate if(pk11_have_random) 4360Sstevel@tonic-gate { 4370Sstevel@tonic-gate if(!ENGINE_set_RAND(e, &pk11_random)) 4380Sstevel@tonic-gate return 0; 4390Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 4400Sstevel@tonic-gate fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: registered random\n"); 4410Sstevel@tonic-gate #endif /* DEBUG_SLOT_SELECTION */ 4420Sstevel@tonic-gate } 4430Sstevel@tonic-gate if(!ENGINE_set_init_function(e, pk11_init) || 4440Sstevel@tonic-gate !ENGINE_set_destroy_function(e, pk11_destroy) || 4450Sstevel@tonic-gate !ENGINE_set_finish_function(e, pk11_finish) || 4460Sstevel@tonic-gate !ENGINE_set_ctrl_function(e, pk11_ctrl) || 4470Sstevel@tonic-gate !ENGINE_set_cmd_defns(e, pk11_cmd_defns)) 4480Sstevel@tonic-gate return 0; 4490Sstevel@tonic-gate 4500Sstevel@tonic-gate /* Apache calls OpenSSL function RSA_blinding_on() once during startup 4510Sstevel@tonic-gate * which in turn calls bn_mod_exp. Since we do not implement bn_mod_exp 4520Sstevel@tonic-gate * here, we wire it back to the OpenSSL software implementation. 4530Sstevel@tonic-gate * Since it is used only once, performance is not a concern. */ 4540Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA 4550Sstevel@tonic-gate rsa = RSA_PKCS1_SSLeay(); 4560Sstevel@tonic-gate pk11_rsa->rsa_mod_exp = rsa->rsa_mod_exp; 4570Sstevel@tonic-gate pk11_rsa->bn_mod_exp = rsa->bn_mod_exp; 4580Sstevel@tonic-gate #endif 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate /* Ensure the pk11 error handling is set up */ 4610Sstevel@tonic-gate ERR_load_pk11_strings(); 4620Sstevel@tonic-gate 4630Sstevel@tonic-gate return 1; 4640Sstevel@tonic-gate } 4650Sstevel@tonic-gate 4660Sstevel@tonic-gate /* Dynamic engine support is disabled at a higher level for Solaris 4670Sstevel@tonic-gate */ 4680Sstevel@tonic-gate #ifdef ENGINE_DYNAMIC_SUPPORT 4690Sstevel@tonic-gate static int bind_helper(ENGINE *e, const char *id) 4700Sstevel@tonic-gate { 4710Sstevel@tonic-gate if (id && (strcmp(id, engine_pk11_id) != 0)) 4720Sstevel@tonic-gate return 0; 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate if (!bind_pk11(e)) 4750Sstevel@tonic-gate return 0; 4760Sstevel@tonic-gate 4770Sstevel@tonic-gate return 1; 4780Sstevel@tonic-gate } 4790Sstevel@tonic-gate 4800Sstevel@tonic-gate IMPLEMENT_DYNAMIC_CHECK_FN() 4810Sstevel@tonic-gate IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) 4820Sstevel@tonic-gate 4830Sstevel@tonic-gate #else 4840Sstevel@tonic-gate static ENGINE *engine_pk11(void) 4850Sstevel@tonic-gate { 4860Sstevel@tonic-gate ENGINE *ret = ENGINE_new(); 4870Sstevel@tonic-gate 4880Sstevel@tonic-gate if (!ret) 4890Sstevel@tonic-gate return NULL; 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate if (!bind_pk11(ret)) 4920Sstevel@tonic-gate { 4930Sstevel@tonic-gate ENGINE_free(ret); 4940Sstevel@tonic-gate return NULL; 4950Sstevel@tonic-gate } 4960Sstevel@tonic-gate 4970Sstevel@tonic-gate return ret; 4980Sstevel@tonic-gate } 4990Sstevel@tonic-gate 5000Sstevel@tonic-gate void ENGINE_load_pk11(void) 5010Sstevel@tonic-gate { 5020Sstevel@tonic-gate ENGINE *e_pk11 = NULL; 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate /* Do not use dynamic PKCS#11 library on Solaris due to 5050Sstevel@tonic-gate * security reasons. We will link it in statically 5060Sstevel@tonic-gate */ 5070Sstevel@tonic-gate /* Attempt to load PKCS#11 library 5080Sstevel@tonic-gate */ 5090Sstevel@tonic-gate if (!pk11_dso) 5100Sstevel@tonic-gate pk11_dso = DSO_load(NULL, get_PK11_LIBNAME(), NULL, 0); 5110Sstevel@tonic-gate 5120Sstevel@tonic-gate if (pk11_dso == NULL) 5130Sstevel@tonic-gate { 5140Sstevel@tonic-gate PK11err(PK11_F_LOAD, PK11_R_DSO_FAILURE); 5150Sstevel@tonic-gate return; 5160Sstevel@tonic-gate } 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate e_pk11 = engine_pk11(); 5190Sstevel@tonic-gate if (!e_pk11) 5200Sstevel@tonic-gate { 5210Sstevel@tonic-gate DSO_free(pk11_dso); 5220Sstevel@tonic-gate pk11_dso = NULL; 5230Sstevel@tonic-gate return; 5240Sstevel@tonic-gate } 5250Sstevel@tonic-gate 5260Sstevel@tonic-gate /* At this point, the pk11 shared library is either dynamically 5270Sstevel@tonic-gate * loaded or statically linked in. So, initialize the pk11 5280Sstevel@tonic-gate * library before calling ENGINE_set_default since the latter 5290Sstevel@tonic-gate * needs cipher and digest algorithm information 5300Sstevel@tonic-gate */ 5310Sstevel@tonic-gate if (!pk11_library_init(e_pk11)) 5320Sstevel@tonic-gate { 5330Sstevel@tonic-gate DSO_free(pk11_dso); 5340Sstevel@tonic-gate pk11_dso = NULL; 5350Sstevel@tonic-gate ENGINE_free(e_pk11); 5360Sstevel@tonic-gate return; 5370Sstevel@tonic-gate } 5380Sstevel@tonic-gate 5390Sstevel@tonic-gate ENGINE_add(e_pk11); 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate ENGINE_free(e_pk11); 5420Sstevel@tonic-gate ERR_clear_error(); 5430Sstevel@tonic-gate } 5440Sstevel@tonic-gate #endif 5450Sstevel@tonic-gate 5460Sstevel@tonic-gate /* These are the static string constants for the DSO file name and 5470Sstevel@tonic-gate * the function symbol names to bind to. 5480Sstevel@tonic-gate */ 5490Sstevel@tonic-gate static const char *PK11_LIBNAME = NULL; 5500Sstevel@tonic-gate 5510Sstevel@tonic-gate static const char *get_PK11_LIBNAME(void) 5520Sstevel@tonic-gate { 5530Sstevel@tonic-gate if (PK11_LIBNAME) 5540Sstevel@tonic-gate return PK11_LIBNAME; 5550Sstevel@tonic-gate 5560Sstevel@tonic-gate return def_PK11_LIBNAME; 5570Sstevel@tonic-gate } 5580Sstevel@tonic-gate 5590Sstevel@tonic-gate static void free_PK11_LIBNAME(void) 5600Sstevel@tonic-gate { 5610Sstevel@tonic-gate if (PK11_LIBNAME) 5620Sstevel@tonic-gate OPENSSL_free((void*)PK11_LIBNAME); 5630Sstevel@tonic-gate 5640Sstevel@tonic-gate PK11_LIBNAME = NULL; 5650Sstevel@tonic-gate } 5660Sstevel@tonic-gate 5670Sstevel@tonic-gate static long set_PK11_LIBNAME(const char *name) 5680Sstevel@tonic-gate { 5690Sstevel@tonic-gate free_PK11_LIBNAME(); 5700Sstevel@tonic-gate 5710Sstevel@tonic-gate return ((PK11_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0); 5720Sstevel@tonic-gate } 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate /* Initialization function for the pk11 engine */ 5750Sstevel@tonic-gate static int pk11_init(ENGINE *e) 5760Sstevel@tonic-gate { 5770Sstevel@tonic-gate return pk11_library_init(e); 5780Sstevel@tonic-gate } 5790Sstevel@tonic-gate 5800Sstevel@tonic-gate /* Initialization function. Sets up various pk11 library components. 5810Sstevel@tonic-gate * It selects a slot based on predefined critiera. In the process, it also 5820Sstevel@tonic-gate * count how many ciphers and digests to support. Since the cipher and 5830Sstevel@tonic-gate * digest information is needed when setting default engine, this function 5840Sstevel@tonic-gate * needs to be called before calling ENGINE_set_default. 5850Sstevel@tonic-gate */ 5860Sstevel@tonic-gate static int pk11_library_init(ENGINE *e) 5870Sstevel@tonic-gate { 5880Sstevel@tonic-gate CK_C_GetFunctionList p; 5890Sstevel@tonic-gate CK_RV rv = CKR_OK; 5900Sstevel@tonic-gate CK_INFO info; 5910Sstevel@tonic-gate CK_ULONG ul_state_len; 5920Sstevel@tonic-gate char tmp_buf[20]; 5930Sstevel@tonic-gate 5940Sstevel@tonic-gate if (pk11_library_initialized) 5950Sstevel@tonic-gate return 1; 5960Sstevel@tonic-gate 5970Sstevel@tonic-gate if (pk11_dso == NULL) 5980Sstevel@tonic-gate { 5990Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); 6000Sstevel@tonic-gate goto err; 6010Sstevel@tonic-gate } 6020Sstevel@tonic-gate 6030Sstevel@tonic-gate /* get the C_GetFunctionList function from the loaded library 6040Sstevel@tonic-gate */ 6050Sstevel@tonic-gate p = (CK_C_GetFunctionList)DSO_bind_func(pk11_dso, 6060Sstevel@tonic-gate PK11_GET_FUNCTION_LIST); 6070Sstevel@tonic-gate if ( !p ) 6080Sstevel@tonic-gate { 6090Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); 6100Sstevel@tonic-gate goto err; 6110Sstevel@tonic-gate } 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate /* get the full function list from the loaded library 6140Sstevel@tonic-gate */ 6150Sstevel@tonic-gate rv = p(&pFuncList); 6160Sstevel@tonic-gate if (rv != CKR_OK) 6170Sstevel@tonic-gate { 6180Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_DSO_FAILURE); 6190Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 6200Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 6210Sstevel@tonic-gate goto err; 6220Sstevel@tonic-gate } 6230Sstevel@tonic-gate 6240Sstevel@tonic-gate rv = pFuncList->C_Initialize(NULL_PTR); 6250Sstevel@tonic-gate if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) 6260Sstevel@tonic-gate { 6270Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_INITIALIZE); 6280Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 6290Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 6300Sstevel@tonic-gate goto err; 6310Sstevel@tonic-gate } 6320Sstevel@tonic-gate 6330Sstevel@tonic-gate rv = pFuncList->C_GetInfo(&info); 6340Sstevel@tonic-gate if (rv != CKR_OK) 6350Sstevel@tonic-gate { 6360Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_GETINFO); 6370Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 6380Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 6390Sstevel@tonic-gate goto err; 6400Sstevel@tonic-gate } 6410Sstevel@tonic-gate 6420Sstevel@tonic-gate if (pk11_choose_slot() == 0) 6430Sstevel@tonic-gate goto err; 6440Sstevel@tonic-gate 6450Sstevel@tonic-gate if (global_session == CK_INVALID_HANDLE) 6460Sstevel@tonic-gate { 6470Sstevel@tonic-gate /* Open the global_session for the new process */ 6480Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 6490Sstevel@tonic-gate NULL_PTR, NULL_PTR, &global_session); 6500Sstevel@tonic-gate if (rv != CKR_OK) 6510Sstevel@tonic-gate { 6520Sstevel@tonic-gate PK11err(PK11_F_LIBRARY_INIT, PK11_R_OPENSESSION); 6530Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 6540Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 6550Sstevel@tonic-gate goto err; 6560Sstevel@tonic-gate } 6570Sstevel@tonic-gate } 6580Sstevel@tonic-gate 6590Sstevel@tonic-gate /* Disable digest if C_GetOperationState is not supported since 6600Sstevel@tonic-gate * this function is required by OpenSSL digest copy function */ 6610Sstevel@tonic-gate if (pFuncList->C_GetOperationState(global_session, NULL, &ul_state_len) 6620Sstevel@tonic-gate == CKR_FUNCTION_NOT_SUPPORTED) 6630Sstevel@tonic-gate digest_count = 0; 6640Sstevel@tonic-gate 6650Sstevel@tonic-gate pk11_library_initialized = 1; 6660Sstevel@tonic-gate return 1; 6670Sstevel@tonic-gate 6680Sstevel@tonic-gate err: 6690Sstevel@tonic-gate 6700Sstevel@tonic-gate return 0; 6710Sstevel@tonic-gate } 6720Sstevel@tonic-gate 6730Sstevel@tonic-gate /* Destructor (complements the "ENGINE_pk11()" constructor) 6740Sstevel@tonic-gate */ 6750Sstevel@tonic-gate static int pk11_destroy(ENGINE *e) 6760Sstevel@tonic-gate { 6770Sstevel@tonic-gate free_PK11_LIBNAME(); 6780Sstevel@tonic-gate ERR_unload_pk11_strings(); 6790Sstevel@tonic-gate return 1; 6800Sstevel@tonic-gate } 6810Sstevel@tonic-gate 6820Sstevel@tonic-gate /* Termination function to clean up the session, the token, and 6830Sstevel@tonic-gate * the pk11 library. 6840Sstevel@tonic-gate */ 6850Sstevel@tonic-gate static int pk11_finish(ENGINE *e) 6860Sstevel@tonic-gate { 6870Sstevel@tonic-gate 6880Sstevel@tonic-gate if (pk11_dso == NULL) 6890Sstevel@tonic-gate { 6900Sstevel@tonic-gate PK11err(PK11_F_FINISH, PK11_R_NOT_LOADED); 6910Sstevel@tonic-gate goto err; 6920Sstevel@tonic-gate } 6930Sstevel@tonic-gate 6940Sstevel@tonic-gate assert(pFuncList != NULL); 6950Sstevel@tonic-gate 6960Sstevel@tonic-gate if (pk11_free_all_sessions() == 0) 6970Sstevel@tonic-gate goto err; 6980Sstevel@tonic-gate 6990Sstevel@tonic-gate pFuncList->C_CloseSession(global_session); 7000Sstevel@tonic-gate 7010Sstevel@tonic-gate /* Since we are part of a library (libcrypto.so), calling this 7020Sstevel@tonic-gate * function may have side-effects. 7030Sstevel@tonic-gate pFuncList->C_Finalize(NULL); 7040Sstevel@tonic-gate */ 7050Sstevel@tonic-gate 7060Sstevel@tonic-gate if (!DSO_free(pk11_dso)) 7070Sstevel@tonic-gate { 7080Sstevel@tonic-gate PK11err(PK11_F_FINISH, PK11_R_DSO_FAILURE); 7090Sstevel@tonic-gate goto err; 7100Sstevel@tonic-gate } 7110Sstevel@tonic-gate pk11_dso = NULL; 7120Sstevel@tonic-gate pFuncList = NULL; 7130Sstevel@tonic-gate pk11_library_initialized = 0; 7140Sstevel@tonic-gate 7150Sstevel@tonic-gate return 1; 7160Sstevel@tonic-gate 7170Sstevel@tonic-gate err: 7180Sstevel@tonic-gate return 0; 7190Sstevel@tonic-gate } 7200Sstevel@tonic-gate 7210Sstevel@tonic-gate /* Standard engine interface function to set the dynamic library path */ 7220Sstevel@tonic-gate static int pk11_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) 7230Sstevel@tonic-gate { 7240Sstevel@tonic-gate int initialized = ((pk11_dso == NULL) ? 0 : 1); 7250Sstevel@tonic-gate 7260Sstevel@tonic-gate switch(cmd) 7270Sstevel@tonic-gate { 7280Sstevel@tonic-gate case PK11_CMD_SO_PATH: 7290Sstevel@tonic-gate if (p == NULL) 7300Sstevel@tonic-gate { 7310Sstevel@tonic-gate PK11err(PK11_F_CTRL, ERR_R_PASSED_NULL_PARAMETER); 7320Sstevel@tonic-gate return 0; 7330Sstevel@tonic-gate } 7340Sstevel@tonic-gate 7350Sstevel@tonic-gate if (initialized) 7360Sstevel@tonic-gate { 7370Sstevel@tonic-gate PK11err(PK11_F_CTRL, PK11_R_ALREADY_LOADED); 7380Sstevel@tonic-gate return 0; 7390Sstevel@tonic-gate } 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate return set_PK11_LIBNAME((const char*)p); 7420Sstevel@tonic-gate default: 7430Sstevel@tonic-gate break; 7440Sstevel@tonic-gate } 7450Sstevel@tonic-gate 7460Sstevel@tonic-gate PK11err(PK11_F_CTRL,PK11_R_CTRL_COMMAND_NOT_IMPLEMENTED); 7470Sstevel@tonic-gate 7480Sstevel@tonic-gate return 0; 7490Sstevel@tonic-gate } 7500Sstevel@tonic-gate 7510Sstevel@tonic-gate 7520Sstevel@tonic-gate /* Required function by the engine random interface. It does nothing here 7530Sstevel@tonic-gate */ 7540Sstevel@tonic-gate static void pk11_rand_cleanup(void) 7550Sstevel@tonic-gate { 7560Sstevel@tonic-gate return; 7570Sstevel@tonic-gate } 7580Sstevel@tonic-gate 7590Sstevel@tonic-gate static void pk11_rand_add(const void *buf, int num, double add) 7600Sstevel@tonic-gate { 7610Sstevel@tonic-gate PK11_SESSION *sp; 7620Sstevel@tonic-gate 7630Sstevel@tonic-gate if ((sp = pk11_get_session()) == NULL) 7640Sstevel@tonic-gate return; 7650Sstevel@tonic-gate 7660Sstevel@tonic-gate /* Ignore any errors (e.g. CKR_RANDOM_SEED_NOT_SUPPORTED) since 7670Sstevel@tonic-gate * the calling functions do not care anyway 7680Sstevel@tonic-gate */ 7690Sstevel@tonic-gate pFuncList->C_SeedRandom(sp->session, (unsigned char *) buf, num); 7700Sstevel@tonic-gate pk11_return_session(sp); 7710Sstevel@tonic-gate 7720Sstevel@tonic-gate return; 7730Sstevel@tonic-gate } 7740Sstevel@tonic-gate 7750Sstevel@tonic-gate static void pk11_rand_seed(const void *buf, int num) 7760Sstevel@tonic-gate { 7770Sstevel@tonic-gate pk11_rand_add(buf, num, 0); 7780Sstevel@tonic-gate } 7790Sstevel@tonic-gate 7800Sstevel@tonic-gate static int pk11_rand_bytes(unsigned char *buf, int num) 7810Sstevel@tonic-gate { 7820Sstevel@tonic-gate CK_RV rv; 7830Sstevel@tonic-gate PK11_SESSION *sp; 7840Sstevel@tonic-gate 7850Sstevel@tonic-gate if ((sp = pk11_get_session()) == NULL) 7860Sstevel@tonic-gate return 0; 7870Sstevel@tonic-gate 7880Sstevel@tonic-gate rv = pFuncList->C_GenerateRandom(sp->session, buf, num); 7890Sstevel@tonic-gate if (rv != CKR_OK) 7900Sstevel@tonic-gate { 7910Sstevel@tonic-gate char tmp_buf[20]; 7920Sstevel@tonic-gate PK11err(PK11_F_RAND_BYTES, PK11_R_GENERATERANDOM); 7930Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 7940Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 7950Sstevel@tonic-gate pk11_return_session(sp); 7960Sstevel@tonic-gate return 0; 7970Sstevel@tonic-gate } 7980Sstevel@tonic-gate 7990Sstevel@tonic-gate pk11_return_session(sp); 8000Sstevel@tonic-gate return 1; 8010Sstevel@tonic-gate } 8020Sstevel@tonic-gate 8030Sstevel@tonic-gate 8040Sstevel@tonic-gate /* Required function by the engine random interface. It does nothing here 8050Sstevel@tonic-gate */ 8060Sstevel@tonic-gate static int pk11_rand_status(void) 8070Sstevel@tonic-gate { 8080Sstevel@tonic-gate return 1; 8090Sstevel@tonic-gate } 8100Sstevel@tonic-gate 8110Sstevel@tonic-gate 8120Sstevel@tonic-gate PK11_SESSION *pk11_get_session() 8130Sstevel@tonic-gate { 8140Sstevel@tonic-gate PK11_SESSION *sp, *sp1; 8150Sstevel@tonic-gate CK_RV rv; 8160Sstevel@tonic-gate char tmp_buf[20]; 8170Sstevel@tonic-gate 8180Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 8190Sstevel@tonic-gate if ((sp = free_session) == NULL) 8200Sstevel@tonic-gate { 8210Sstevel@tonic-gate if ((sp = OPENSSL_malloc(sizeof(PK11_SESSION))) == NULL) 8220Sstevel@tonic-gate { 8230Sstevel@tonic-gate PK11err(PK11_F_GET_SESSION, 8240Sstevel@tonic-gate PK11_R_MALLOC_FAILURE); 8250Sstevel@tonic-gate goto err; 8260Sstevel@tonic-gate } 8270Sstevel@tonic-gate memset(sp, 0, sizeof(PK11_SESSION)); 8280Sstevel@tonic-gate } 8290Sstevel@tonic-gate else 8300Sstevel@tonic-gate { 8310Sstevel@tonic-gate free_session = sp->next; 8320Sstevel@tonic-gate } 8330Sstevel@tonic-gate 8340Sstevel@tonic-gate if (sp->pid != 0 && sp->pid != getpid()) 8350Sstevel@tonic-gate { 8360Sstevel@tonic-gate /* We are a new process and thus need to free any inherated 8370Sstevel@tonic-gate * PK11_SESSION objects. 8380Sstevel@tonic-gate */ 8390Sstevel@tonic-gate while ((sp1 = free_session) != NULL) 8400Sstevel@tonic-gate { 8410Sstevel@tonic-gate free_session = sp1->next; 8420Sstevel@tonic-gate OPENSSL_free(sp1); 8430Sstevel@tonic-gate } 8440Sstevel@tonic-gate 8450Sstevel@tonic-gate /* Initialize the process */ 8460Sstevel@tonic-gate rv = pFuncList->C_Initialize(NULL_PTR); 8470Sstevel@tonic-gate if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) 8480Sstevel@tonic-gate { 8490Sstevel@tonic-gate PK11err(PK11_F_GET_SESSION, PK11_R_INITIALIZE); 8500Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 8510Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 8520Sstevel@tonic-gate OPENSSL_free(sp); 8530Sstevel@tonic-gate sp = NULL; 8540Sstevel@tonic-gate goto err; 8550Sstevel@tonic-gate } 8560Sstevel@tonic-gate 8570Sstevel@tonic-gate /* Choose slot here since the slot table is different on 8580Sstevel@tonic-gate * this process. 8590Sstevel@tonic-gate */ 8600Sstevel@tonic-gate if (pk11_choose_slot() == 0) 8610Sstevel@tonic-gate goto err; 8620Sstevel@tonic-gate 8630Sstevel@tonic-gate /* Open the global_session for the new process */ 8640Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 8650Sstevel@tonic-gate NULL_PTR, NULL_PTR, &global_session); 8660Sstevel@tonic-gate if (rv != CKR_OK) 8670Sstevel@tonic-gate { 8680Sstevel@tonic-gate PK11err(PK11_F_GET_SESSION, PK11_R_OPENSESSION); 8690Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 8700Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 8710Sstevel@tonic-gate OPENSSL_free(sp); 8720Sstevel@tonic-gate sp = NULL; 8730Sstevel@tonic-gate goto err; 8740Sstevel@tonic-gate } 8750Sstevel@tonic-gate 8760Sstevel@tonic-gate /* It is an inherited session and needs re-initialization. 8770Sstevel@tonic-gate */ 8780Sstevel@tonic-gate if (pk11_setup_session(sp) == 0) 8790Sstevel@tonic-gate { 8800Sstevel@tonic-gate OPENSSL_free(sp); 8810Sstevel@tonic-gate sp = NULL; 8820Sstevel@tonic-gate } 8830Sstevel@tonic-gate } 8840Sstevel@tonic-gate else if (sp->pid == 0) 8850Sstevel@tonic-gate { 8860Sstevel@tonic-gate /* It is a new session and needs initialization. 8870Sstevel@tonic-gate */ 8880Sstevel@tonic-gate if (pk11_setup_session(sp) == 0) 8890Sstevel@tonic-gate { 8900Sstevel@tonic-gate OPENSSL_free(sp); 8910Sstevel@tonic-gate sp = NULL; 8920Sstevel@tonic-gate } 8930Sstevel@tonic-gate } 8940Sstevel@tonic-gate 8950Sstevel@tonic-gate err: 8960Sstevel@tonic-gate if (sp) 8970Sstevel@tonic-gate sp->next = NULL; 8980Sstevel@tonic-gate 8990Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 9000Sstevel@tonic-gate 9010Sstevel@tonic-gate return sp; 9020Sstevel@tonic-gate } 9030Sstevel@tonic-gate 9040Sstevel@tonic-gate 9050Sstevel@tonic-gate void pk11_return_session(PK11_SESSION *sp) 9060Sstevel@tonic-gate { 9070Sstevel@tonic-gate if (sp == NULL || sp->pid != getpid()) 9080Sstevel@tonic-gate return; 9090Sstevel@tonic-gate 9100Sstevel@tonic-gate 9110Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 9120Sstevel@tonic-gate 9130Sstevel@tonic-gate sp->next = free_session; 9140Sstevel@tonic-gate free_session = sp; 9150Sstevel@tonic-gate 9160Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 9170Sstevel@tonic-gate } 9180Sstevel@tonic-gate 9190Sstevel@tonic-gate 9200Sstevel@tonic-gate /* Destroy all objects. This function is called when the engine is finished 9210Sstevel@tonic-gate */ 9220Sstevel@tonic-gate static int pk11_free_all_sessions() 9230Sstevel@tonic-gate { 9240Sstevel@tonic-gate CK_RV rv; 9250Sstevel@tonic-gate PK11_SESSION *sp = NULL; 9260Sstevel@tonic-gate pid_t mypid = getpid(); 9270Sstevel@tonic-gate int ret = 0; 9280Sstevel@tonic-gate 9290Sstevel@tonic-gate pk11_destroy_rsa_key_objects(NULL); 9300Sstevel@tonic-gate pk11_destroy_dsa_key_objects(NULL); 9310Sstevel@tonic-gate pk11_destroy_dh_key_objects(NULL); 9320Sstevel@tonic-gate pk11_destroy_cipher_key_objects(NULL); 9330Sstevel@tonic-gate 9340Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 9350Sstevel@tonic-gate while ((sp = free_session) != NULL) 9360Sstevel@tonic-gate { 9370Sstevel@tonic-gate if (sp->session != CK_INVALID_HANDLE && sp->pid == mypid) 9380Sstevel@tonic-gate { 9390Sstevel@tonic-gate rv = pFuncList->C_CloseSession(sp->session); 9400Sstevel@tonic-gate if (rv != CKR_OK) 9410Sstevel@tonic-gate { 9420Sstevel@tonic-gate char tmp_buf[20]; 9430Sstevel@tonic-gate PK11err(PK11_F_FREE_ALL_SESSIONS, 9440Sstevel@tonic-gate PK11_R_CLOSESESSION); 9450Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 9460Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 9470Sstevel@tonic-gate } 9480Sstevel@tonic-gate } 9490Sstevel@tonic-gate if (sp->session_cipher != CK_INVALID_HANDLE && sp->pid == mypid) 9500Sstevel@tonic-gate { 9510Sstevel@tonic-gate rv = pFuncList->C_CloseSession(sp->session_cipher); 9520Sstevel@tonic-gate if (rv != CKR_OK) 9530Sstevel@tonic-gate { 9540Sstevel@tonic-gate char tmp_buf[20]; 9550Sstevel@tonic-gate PK11err(PK11_F_FREE_ALL_SESSIONS, 9560Sstevel@tonic-gate PK11_R_CLOSESESSION); 9570Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 9580Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 9590Sstevel@tonic-gate } 9600Sstevel@tonic-gate } 9610Sstevel@tonic-gate free_session = sp->next; 9620Sstevel@tonic-gate OPENSSL_free(sp); 9630Sstevel@tonic-gate } 9640Sstevel@tonic-gate ret = 1; 9650Sstevel@tonic-gate err: 9660Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 9670Sstevel@tonic-gate 9680Sstevel@tonic-gate return ret; 9690Sstevel@tonic-gate } 9700Sstevel@tonic-gate 9710Sstevel@tonic-gate 9720Sstevel@tonic-gate static int pk11_setup_session(PK11_SESSION *sp) 9730Sstevel@tonic-gate { 9740Sstevel@tonic-gate CK_RV rv; 9750Sstevel@tonic-gate sp->session = CK_INVALID_HANDLE; 9760Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 9770Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session); 9780Sstevel@tonic-gate if (rv == CKR_CRYPTOKI_NOT_INITIALIZED) 9790Sstevel@tonic-gate { 9800Sstevel@tonic-gate /* 9810Sstevel@tonic-gate * We are probably a child process so force the 9820Sstevel@tonic-gate * reinitialize of the session 9830Sstevel@tonic-gate */ 9840Sstevel@tonic-gate pk11_library_initialized = 0; 9850Sstevel@tonic-gate (void) pk11_library_init(NULL); 9860Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 9870Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session); 9880Sstevel@tonic-gate } 9890Sstevel@tonic-gate if (rv != CKR_OK) 9900Sstevel@tonic-gate { 9910Sstevel@tonic-gate char tmp_buf[20]; 9920Sstevel@tonic-gate PK11err(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION); 9930Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 9940Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 9950Sstevel@tonic-gate return 0; 9960Sstevel@tonic-gate } 9970Sstevel@tonic-gate 9980Sstevel@tonic-gate sp->session_cipher = CK_INVALID_HANDLE; 9990Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 10000Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session_cipher); 10010Sstevel@tonic-gate if (rv != CKR_OK) 10020Sstevel@tonic-gate { 10030Sstevel@tonic-gate char tmp_buf[20]; 10040Sstevel@tonic-gate 10050Sstevel@tonic-gate (void) pFuncList->C_CloseSession(sp->session); 10060Sstevel@tonic-gate sp->session = CK_INVALID_HANDLE; 10070Sstevel@tonic-gate 10080Sstevel@tonic-gate PK11err(PK11_F_SETUP_SESSION, PK11_R_OPENSESSION); 10090Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 10100Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 10110Sstevel@tonic-gate return 0; 10120Sstevel@tonic-gate } 10130Sstevel@tonic-gate 10140Sstevel@tonic-gate sp->pid = getpid(); 10150Sstevel@tonic-gate sp->rsa_pub_key = CK_INVALID_HANDLE; 10160Sstevel@tonic-gate sp->rsa_priv_key = CK_INVALID_HANDLE; 10170Sstevel@tonic-gate sp->dsa_pub_key = CK_INVALID_HANDLE; 10180Sstevel@tonic-gate sp->dsa_priv_key = CK_INVALID_HANDLE; 10190Sstevel@tonic-gate sp->dh_key = CK_INVALID_HANDLE; 10200Sstevel@tonic-gate sp->cipher_key = CK_INVALID_HANDLE; 10210Sstevel@tonic-gate sp->rsa = NULL; 10220Sstevel@tonic-gate sp->dsa = NULL; 10230Sstevel@tonic-gate sp->dh = NULL; 10240Sstevel@tonic-gate sp->encrypt = -1; 10250Sstevel@tonic-gate 10260Sstevel@tonic-gate return 1; 10270Sstevel@tonic-gate } 10280Sstevel@tonic-gate 10290Sstevel@tonic-gate int pk11_destroy_rsa_key_objects(PK11_SESSION *session) 10300Sstevel@tonic-gate { 10310Sstevel@tonic-gate int ret = 0; 10320Sstevel@tonic-gate PK11_SESSION *sp = NULL; 10330Sstevel@tonic-gate PK11_SESSION *local_free_session; 10340Sstevel@tonic-gate 10350Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 10360Sstevel@tonic-gate if (session) 10370Sstevel@tonic-gate local_free_session = session; 10380Sstevel@tonic-gate else 10390Sstevel@tonic-gate local_free_session = free_session; 10400Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 10410Sstevel@tonic-gate { 10420Sstevel@tonic-gate local_free_session = sp->next; 10430Sstevel@tonic-gate 10440Sstevel@tonic-gate if (sp->rsa_pub_key != CK_INVALID_HANDLE) 10450Sstevel@tonic-gate { 10460Sstevel@tonic-gate if (pk11_destroy_object(sp->session, 10470Sstevel@tonic-gate sp->rsa_pub_key) == 0) 10480Sstevel@tonic-gate goto err; 10490Sstevel@tonic-gate sp->rsa_pub_key = CK_INVALID_HANDLE; 10500Sstevel@tonic-gate } 10510Sstevel@tonic-gate 10520Sstevel@tonic-gate if (sp->rsa_priv_key != CK_INVALID_HANDLE) 10530Sstevel@tonic-gate { 10540Sstevel@tonic-gate if (pk11_destroy_object(sp->session, 10550Sstevel@tonic-gate sp->rsa_priv_key) == 0) 10560Sstevel@tonic-gate goto err; 10570Sstevel@tonic-gate sp->rsa_priv_key = CK_INVALID_HANDLE; 10580Sstevel@tonic-gate } 10590Sstevel@tonic-gate 10600Sstevel@tonic-gate sp->rsa = NULL; 10610Sstevel@tonic-gate } 10620Sstevel@tonic-gate ret = 1; 10630Sstevel@tonic-gate err: 10640Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 10650Sstevel@tonic-gate 10660Sstevel@tonic-gate return ret; 10670Sstevel@tonic-gate } 10680Sstevel@tonic-gate 10690Sstevel@tonic-gate int pk11_destroy_dsa_key_objects(PK11_SESSION *session) 10700Sstevel@tonic-gate { 10710Sstevel@tonic-gate int ret = 0; 10720Sstevel@tonic-gate PK11_SESSION *sp = NULL; 10730Sstevel@tonic-gate PK11_SESSION *local_free_session; 10740Sstevel@tonic-gate 10750Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 10760Sstevel@tonic-gate if (session) 10770Sstevel@tonic-gate local_free_session = session; 10780Sstevel@tonic-gate else 10790Sstevel@tonic-gate local_free_session = free_session; 10800Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 10810Sstevel@tonic-gate { 10820Sstevel@tonic-gate local_free_session = sp->next; 10830Sstevel@tonic-gate 10840Sstevel@tonic-gate if (sp->dsa_pub_key != CK_INVALID_HANDLE) 10850Sstevel@tonic-gate { 10860Sstevel@tonic-gate if (pk11_destroy_object(sp->session, 10870Sstevel@tonic-gate sp->dsa_pub_key) == 0) 10880Sstevel@tonic-gate goto err; 10890Sstevel@tonic-gate sp->dsa_pub_key = CK_INVALID_HANDLE; 10900Sstevel@tonic-gate } 10910Sstevel@tonic-gate 10920Sstevel@tonic-gate if (sp->dsa_priv_key != CK_INVALID_HANDLE) 10930Sstevel@tonic-gate { 10940Sstevel@tonic-gate if (pk11_destroy_object(sp->session, 10950Sstevel@tonic-gate sp->dsa_priv_key) == 0) 10960Sstevel@tonic-gate goto err; 10970Sstevel@tonic-gate sp->dsa_priv_key = CK_INVALID_HANDLE; 10980Sstevel@tonic-gate } 10990Sstevel@tonic-gate 11000Sstevel@tonic-gate sp->dsa = NULL; 11010Sstevel@tonic-gate } 11020Sstevel@tonic-gate ret = 1; 11030Sstevel@tonic-gate err: 11040Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 11050Sstevel@tonic-gate 11060Sstevel@tonic-gate return ret; 11070Sstevel@tonic-gate } 11080Sstevel@tonic-gate 11090Sstevel@tonic-gate int pk11_destroy_dh_key_objects(PK11_SESSION *session) 11100Sstevel@tonic-gate { 11110Sstevel@tonic-gate int ret = 0; 11120Sstevel@tonic-gate PK11_SESSION *sp = NULL; 11130Sstevel@tonic-gate PK11_SESSION *local_free_session; 11140Sstevel@tonic-gate 11150Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 11160Sstevel@tonic-gate if (session) 11170Sstevel@tonic-gate local_free_session = session; 11180Sstevel@tonic-gate else 11190Sstevel@tonic-gate local_free_session = free_session; 11200Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 11210Sstevel@tonic-gate { 11220Sstevel@tonic-gate local_free_session = sp->next; 11230Sstevel@tonic-gate 11240Sstevel@tonic-gate if (sp->dh_key != CK_INVALID_HANDLE) 11250Sstevel@tonic-gate { 11260Sstevel@tonic-gate if (pk11_destroy_object(sp->session, 11270Sstevel@tonic-gate sp->dh_key) == 0) 11280Sstevel@tonic-gate goto err; 11290Sstevel@tonic-gate sp->dh_key = CK_INVALID_HANDLE; 11300Sstevel@tonic-gate } 11310Sstevel@tonic-gate 11320Sstevel@tonic-gate sp->dh = NULL; 11330Sstevel@tonic-gate } 11340Sstevel@tonic-gate ret = 1; 11350Sstevel@tonic-gate err: 11360Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 11370Sstevel@tonic-gate 11380Sstevel@tonic-gate return ret; 11390Sstevel@tonic-gate } 11400Sstevel@tonic-gate 11410Sstevel@tonic-gate static int pk11_destroy_object(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE oh) 11420Sstevel@tonic-gate { 11430Sstevel@tonic-gate CK_RV rv; 11440Sstevel@tonic-gate rv = pFuncList->C_DestroyObject(session, oh); 11450Sstevel@tonic-gate if (rv != CKR_OK) 11460Sstevel@tonic-gate { 11470Sstevel@tonic-gate char tmp_buf[20]; 11480Sstevel@tonic-gate PK11err(PK11_F_DESTROY_OBJECT, PK11_R_DESTROYOBJECT); 11490Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 11500Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", 11510Sstevel@tonic-gate tmp_buf); 11520Sstevel@tonic-gate return 0; 11530Sstevel@tonic-gate } 11540Sstevel@tonic-gate 11550Sstevel@tonic-gate return 1; 11560Sstevel@tonic-gate } 11570Sstevel@tonic-gate 11580Sstevel@tonic-gate 11590Sstevel@tonic-gate /* Symmetric ciphers and digests support functions 11600Sstevel@tonic-gate */ 11610Sstevel@tonic-gate 11620Sstevel@tonic-gate static int 11630Sstevel@tonic-gate cipher_nid_to_pk11(int nid) 11640Sstevel@tonic-gate { 11650Sstevel@tonic-gate int i; 11660Sstevel@tonic-gate 11670Sstevel@tonic-gate for (i = 0; i < PK11_CIPHER_MAX; i++) 11680Sstevel@tonic-gate if (ciphers[i].nid == nid) 11690Sstevel@tonic-gate return (ciphers[i].id); 11700Sstevel@tonic-gate return (-1); 11710Sstevel@tonic-gate } 11720Sstevel@tonic-gate 11730Sstevel@tonic-gate static int 11740Sstevel@tonic-gate pk11_usable_ciphers(const int **nids) 11750Sstevel@tonic-gate { 11760Sstevel@tonic-gate if (cipher_count > 0) 11770Sstevel@tonic-gate *nids = cipher_nids; 11780Sstevel@tonic-gate else 11790Sstevel@tonic-gate *nids = NULL; 11800Sstevel@tonic-gate return (cipher_count); 11810Sstevel@tonic-gate } 11820Sstevel@tonic-gate 11830Sstevel@tonic-gate static int 11840Sstevel@tonic-gate pk11_usable_digests(const int **nids) 11850Sstevel@tonic-gate { 11860Sstevel@tonic-gate if (digest_count > 0) 11870Sstevel@tonic-gate *nids = digest_nids; 11880Sstevel@tonic-gate else 11890Sstevel@tonic-gate *nids = NULL; 11900Sstevel@tonic-gate return (digest_count); 11910Sstevel@tonic-gate } 11920Sstevel@tonic-gate 11930Sstevel@tonic-gate static int 11940Sstevel@tonic-gate pk11_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, 11950Sstevel@tonic-gate const unsigned char *iv, int enc) 11960Sstevel@tonic-gate { 11970Sstevel@tonic-gate CK_RV rv; 1198*4320Sjp161948 CK_MECHANISM mech; 11990Sstevel@tonic-gate int index; 12000Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; 12010Sstevel@tonic-gate PK11_SESSION *sp; 12020Sstevel@tonic-gate PK11_CIPHER *pcp; 12030Sstevel@tonic-gate char tmp_buf[20]; 12040Sstevel@tonic-gate 12050Sstevel@tonic-gate state->sp = NULL; 12060Sstevel@tonic-gate 12070Sstevel@tonic-gate index = cipher_nid_to_pk11(ctx->cipher->nid); 12080Sstevel@tonic-gate if (index < 0 || index >= PK11_CIPHER_MAX) 12090Sstevel@tonic-gate return 0; 12100Sstevel@tonic-gate 12110Sstevel@tonic-gate pcp = &ciphers[index]; 12120Sstevel@tonic-gate if (ctx->cipher->iv_len > pcp->ivmax || ctx->key_len != pcp->key_len) 12130Sstevel@tonic-gate return 0; 12140Sstevel@tonic-gate 12150Sstevel@tonic-gate if ((sp = pk11_get_session()) == NULL) 12160Sstevel@tonic-gate return 0; 12170Sstevel@tonic-gate 1218*4320Sjp161948 /* if applicable, the mechanism parameter is used for IV */ 1219*4320Sjp161948 mech.mechanism = pcp->mech_type; 1220*4320Sjp161948 mech.pParameter = NULL; 1221*4320Sjp161948 mech.ulParameterLen = 0; 1222*4320Sjp161948 12230Sstevel@tonic-gate /* The key object is destroyed here if it is not the current key 12240Sstevel@tonic-gate */ 12250Sstevel@tonic-gate check_new_cipher_key(sp, key); 12260Sstevel@tonic-gate 12270Sstevel@tonic-gate /* If the key is the same and the encryption is also the same, 12280Sstevel@tonic-gate * then just reuse it 12290Sstevel@tonic-gate */ 12300Sstevel@tonic-gate if (sp->cipher_key != CK_INVALID_HANDLE && sp->encrypt == ctx->encrypt) 12310Sstevel@tonic-gate { 12320Sstevel@tonic-gate state->sp = sp; 12330Sstevel@tonic-gate return 1; 12340Sstevel@tonic-gate } 12350Sstevel@tonic-gate 12360Sstevel@tonic-gate /* Check if the key has been invalidated. If so, a new key object 12370Sstevel@tonic-gate * needs to be created. 12380Sstevel@tonic-gate */ 12390Sstevel@tonic-gate if (sp->cipher_key == CK_INVALID_HANDLE) 12400Sstevel@tonic-gate { 12410Sstevel@tonic-gate sp->cipher_key = pk11_get_cipher_key( 12420Sstevel@tonic-gate ctx, key, pcp->key_type, sp); 12430Sstevel@tonic-gate } 12440Sstevel@tonic-gate 12450Sstevel@tonic-gate if (sp->encrypt != ctx->encrypt && sp->encrypt != -1) 12460Sstevel@tonic-gate { 12470Sstevel@tonic-gate /* The previous encryption/decryption 12480Sstevel@tonic-gate * is different. Need to terminate the previous 12490Sstevel@tonic-gate * active encryption/decryption here 12500Sstevel@tonic-gate */ 12510Sstevel@tonic-gate if (!pk11_cipher_final(sp)) 12520Sstevel@tonic-gate { 12530Sstevel@tonic-gate pk11_return_session(sp); 12540Sstevel@tonic-gate return 0; 12550Sstevel@tonic-gate } 12560Sstevel@tonic-gate } 12570Sstevel@tonic-gate 12580Sstevel@tonic-gate if (sp->cipher_key == CK_INVALID_HANDLE) 12590Sstevel@tonic-gate { 12600Sstevel@tonic-gate pk11_return_session(sp); 12610Sstevel@tonic-gate return 0; 12620Sstevel@tonic-gate } 12630Sstevel@tonic-gate 12640Sstevel@tonic-gate if (ctx->cipher->iv_len > 0) 12650Sstevel@tonic-gate { 1266*4320Sjp161948 mech.pParameter = (void *) ctx->iv; 1267*4320Sjp161948 mech.ulParameterLen = ctx->cipher->iv_len; 12680Sstevel@tonic-gate } 12690Sstevel@tonic-gate 12700Sstevel@tonic-gate /* If we get here, the encryption needs to be reinitialized */ 12710Sstevel@tonic-gate if (ctx->encrypt) 12720Sstevel@tonic-gate { 1273*4320Sjp161948 rv = pFuncList->C_EncryptInit(sp->session_cipher, &mech, 12740Sstevel@tonic-gate sp->cipher_key); 12750Sstevel@tonic-gate 12760Sstevel@tonic-gate if (rv != CKR_OK) 12770Sstevel@tonic-gate { 12780Sstevel@tonic-gate PK11err(PK11_F_CIPHER_INIT, PK11_R_ENCRYPTINIT); 12790Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 12800Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 12810Sstevel@tonic-gate pk11_return_session(sp); 12820Sstevel@tonic-gate return 0; 12830Sstevel@tonic-gate } 12840Sstevel@tonic-gate } 12850Sstevel@tonic-gate else 12860Sstevel@tonic-gate { 1287*4320Sjp161948 rv = pFuncList->C_DecryptInit(sp->session_cipher, &mech, 12880Sstevel@tonic-gate sp->cipher_key); 12890Sstevel@tonic-gate 12900Sstevel@tonic-gate if (rv != CKR_OK) 12910Sstevel@tonic-gate { 12920Sstevel@tonic-gate PK11err(PK11_F_CIPHER_INIT, PK11_R_DECRYPTINIT); 12930Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 12940Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 12950Sstevel@tonic-gate pk11_return_session(sp); 12960Sstevel@tonic-gate return 0; 12970Sstevel@tonic-gate } 12980Sstevel@tonic-gate } 12990Sstevel@tonic-gate 13000Sstevel@tonic-gate sp->encrypt = ctx->encrypt; 13010Sstevel@tonic-gate state->sp = sp; 13020Sstevel@tonic-gate 13030Sstevel@tonic-gate return 1; 13040Sstevel@tonic-gate } 13050Sstevel@tonic-gate 13060Sstevel@tonic-gate /* When reusing the same key in an encryption/decryption session for a 13070Sstevel@tonic-gate * decryption/encryption session, we need to close the active session 13080Sstevel@tonic-gate * and recreate a new one. Note that the key is in the global session so 13090Sstevel@tonic-gate * that it needs not be recreated. 13100Sstevel@tonic-gate * 13110Sstevel@tonic-gate * It is more appropriate to use C_En/DecryptFinish here. At the time of this 13120Sstevel@tonic-gate * development, these two functions in the PKCS#11 libraries used return 13130Sstevel@tonic-gate * unexpected errors when passing in 0 length output. It may be a good 13140Sstevel@tonic-gate * idea to try them again if performance is a problem here and fix 13150Sstevel@tonic-gate * C_En/DecryptFinial if there are bugs there causing the problem. 13160Sstevel@tonic-gate */ 13170Sstevel@tonic-gate static int 13180Sstevel@tonic-gate pk11_cipher_final(PK11_SESSION *sp) 13190Sstevel@tonic-gate { 13200Sstevel@tonic-gate CK_RV rv; 13210Sstevel@tonic-gate char tmp_buf[20]; 13220Sstevel@tonic-gate 13230Sstevel@tonic-gate rv = pFuncList->C_CloseSession(sp->session_cipher); 13240Sstevel@tonic-gate if (rv != CKR_OK) 13250Sstevel@tonic-gate { 13260Sstevel@tonic-gate PK11err(PK11_F_CIPHER_FINAL, PK11_R_CLOSESESSION); 13270Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 13280Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 13290Sstevel@tonic-gate return 0; 13300Sstevel@tonic-gate } 13310Sstevel@tonic-gate 13320Sstevel@tonic-gate rv = pFuncList->C_OpenSession(SLOTID, CKF_SERIAL_SESSION, 13330Sstevel@tonic-gate NULL_PTR, NULL_PTR, &sp->session_cipher); 13340Sstevel@tonic-gate if (rv != CKR_OK) 13350Sstevel@tonic-gate { 13360Sstevel@tonic-gate PK11err(PK11_F_CIPHER_FINAL, PK11_R_OPENSESSION); 13370Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 13380Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 13390Sstevel@tonic-gate return 0; 13400Sstevel@tonic-gate } 13410Sstevel@tonic-gate 13420Sstevel@tonic-gate return 1; 13430Sstevel@tonic-gate } 13440Sstevel@tonic-gate 13450Sstevel@tonic-gate /* An engine interface function. The calling function allocates sufficient 13460Sstevel@tonic-gate * memory for the output buffer "out" to hold the results */ 13470Sstevel@tonic-gate static int 13480Sstevel@tonic-gate pk11_cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 13490Sstevel@tonic-gate const unsigned char *in, unsigned int inl) 13500Sstevel@tonic-gate { 13510Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->cipher_data; 13520Sstevel@tonic-gate PK11_SESSION *sp; 13530Sstevel@tonic-gate CK_RV rv; 13540Sstevel@tonic-gate unsigned long outl = inl; 13550Sstevel@tonic-gate char tmp_buf[20]; 13560Sstevel@tonic-gate 13570Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 13580Sstevel@tonic-gate return 0; 13590Sstevel@tonic-gate 13600Sstevel@tonic-gate sp = (PK11_SESSION *) state->sp; 13610Sstevel@tonic-gate 13620Sstevel@tonic-gate if (!inl) 13630Sstevel@tonic-gate return 1; 13640Sstevel@tonic-gate 13650Sstevel@tonic-gate /* RC4 is the only stream cipher we support */ 13660Sstevel@tonic-gate if (ctx->cipher->nid != NID_rc4 && (inl % ctx->cipher->block_size) != 0) 13670Sstevel@tonic-gate return 0; 13680Sstevel@tonic-gate 13690Sstevel@tonic-gate if (ctx->encrypt) 13700Sstevel@tonic-gate { 13710Sstevel@tonic-gate rv = pFuncList->C_EncryptUpdate(sp->session_cipher, 13720Sstevel@tonic-gate (unsigned char *)in, inl, out, &outl); 13730Sstevel@tonic-gate 13740Sstevel@tonic-gate if (rv != CKR_OK) 13750Sstevel@tonic-gate { 13760Sstevel@tonic-gate PK11err(PK11_F_CIPHER_DO_CIPHER, 13770Sstevel@tonic-gate PK11_R_ENCRYPTUPDATE); 13780Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 13790Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 13800Sstevel@tonic-gate return 0; 13810Sstevel@tonic-gate } 13820Sstevel@tonic-gate } 13830Sstevel@tonic-gate else 13840Sstevel@tonic-gate { 13850Sstevel@tonic-gate rv = pFuncList->C_DecryptUpdate(sp->session_cipher, 13860Sstevel@tonic-gate (unsigned char *)in, inl, out, &outl); 13870Sstevel@tonic-gate 13880Sstevel@tonic-gate if (rv != CKR_OK) 13890Sstevel@tonic-gate { 13900Sstevel@tonic-gate PK11err(PK11_F_CIPHER_DO_CIPHER, 13910Sstevel@tonic-gate PK11_R_DECRYPTUPDATE); 13920Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 13930Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 13940Sstevel@tonic-gate return 0; 13950Sstevel@tonic-gate } 13960Sstevel@tonic-gate } 13970Sstevel@tonic-gate 13980Sstevel@tonic-gate /* for DES_CBC, DES3_CBC, AES_CBC, and RC4, the output size is always 13990Sstevel@tonic-gate * the same size of input 14000Sstevel@tonic-gate * The application has guaranteed to call the block ciphers with 14010Sstevel@tonic-gate * correctly aligned buffers. 14020Sstevel@tonic-gate */ 14030Sstevel@tonic-gate if (inl != outl) 14040Sstevel@tonic-gate return 0; 14050Sstevel@tonic-gate 14060Sstevel@tonic-gate return 1; 14070Sstevel@tonic-gate } 14080Sstevel@tonic-gate 14090Sstevel@tonic-gate /* Return the session to the pool. The C_EncryptFinal and C_DecryptFinal are 14100Sstevel@tonic-gate * not used. Once a secret key is initialized, it is used until destroyed. 14110Sstevel@tonic-gate */ 14120Sstevel@tonic-gate static int 14130Sstevel@tonic-gate pk11_cipher_cleanup(EVP_CIPHER_CTX *ctx) 14140Sstevel@tonic-gate { 14150Sstevel@tonic-gate PK11_CIPHER_STATE *state = ctx->cipher_data; 14160Sstevel@tonic-gate 14170Sstevel@tonic-gate if (state != NULL && state->sp != NULL) 14180Sstevel@tonic-gate { 14190Sstevel@tonic-gate pk11_return_session(state->sp); 14200Sstevel@tonic-gate state->sp = NULL; 14210Sstevel@tonic-gate } 14220Sstevel@tonic-gate 14230Sstevel@tonic-gate return 1; 14240Sstevel@tonic-gate } 14250Sstevel@tonic-gate 14260Sstevel@tonic-gate /* Registered by the ENGINE when used to find out how to deal with 14270Sstevel@tonic-gate * a particular NID in the ENGINE. This says what we'll do at the 14280Sstevel@tonic-gate * top level - note, that list is restricted by what we answer with 14290Sstevel@tonic-gate */ 14300Sstevel@tonic-gate static int 14310Sstevel@tonic-gate pk11_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 14320Sstevel@tonic-gate const int **nids, int nid) 14330Sstevel@tonic-gate { 14340Sstevel@tonic-gate if (!cipher) 14350Sstevel@tonic-gate return (pk11_usable_ciphers(nids)); 14360Sstevel@tonic-gate 14370Sstevel@tonic-gate switch (nid) 14380Sstevel@tonic-gate { 14390Sstevel@tonic-gate case NID_des_ede3_cbc: 14400Sstevel@tonic-gate *cipher = &pk11_3des_cbc; 14410Sstevel@tonic-gate break; 14420Sstevel@tonic-gate case NID_des_cbc: 14430Sstevel@tonic-gate *cipher = &pk11_des_cbc; 14440Sstevel@tonic-gate break; 14450Sstevel@tonic-gate case NID_aes_128_cbc: 14460Sstevel@tonic-gate *cipher = &pk11_aes_cbc; 14470Sstevel@tonic-gate break; 14480Sstevel@tonic-gate case NID_rc4: 14490Sstevel@tonic-gate *cipher = &pk11_rc4; 14500Sstevel@tonic-gate break; 14510Sstevel@tonic-gate default: 14520Sstevel@tonic-gate *cipher = NULL; 14530Sstevel@tonic-gate break; 14540Sstevel@tonic-gate } 14550Sstevel@tonic-gate return (*cipher != NULL); 14560Sstevel@tonic-gate } 14570Sstevel@tonic-gate 14580Sstevel@tonic-gate static int 14590Sstevel@tonic-gate pk11_engine_digests(ENGINE *e, const EVP_MD **digest, 14600Sstevel@tonic-gate const int **nids, int nid) 14610Sstevel@tonic-gate { 14620Sstevel@tonic-gate if (!digest) 14630Sstevel@tonic-gate return (pk11_usable_digests(nids)); 14640Sstevel@tonic-gate 14650Sstevel@tonic-gate switch (nid) 14660Sstevel@tonic-gate { 14670Sstevel@tonic-gate case NID_md5: 14680Sstevel@tonic-gate *digest = &pk11_md5; 14690Sstevel@tonic-gate break; 14700Sstevel@tonic-gate case NID_sha1: 14710Sstevel@tonic-gate *digest = &pk11_sha1; 14720Sstevel@tonic-gate break; 14730Sstevel@tonic-gate default: 14740Sstevel@tonic-gate *digest = NULL; 14750Sstevel@tonic-gate break; 14760Sstevel@tonic-gate } 14770Sstevel@tonic-gate return (*digest != NULL); 14780Sstevel@tonic-gate } 14790Sstevel@tonic-gate 14800Sstevel@tonic-gate 14810Sstevel@tonic-gate /* Create a secret key object in a PKCS#11 session 14820Sstevel@tonic-gate */ 14830Sstevel@tonic-gate static CK_OBJECT_HANDLE pk11_get_cipher_key(EVP_CIPHER_CTX *ctx, 14840Sstevel@tonic-gate const unsigned char *key, CK_KEY_TYPE key_type, PK11_SESSION *sp) 14850Sstevel@tonic-gate { 14860Sstevel@tonic-gate CK_RV rv; 14870Sstevel@tonic-gate CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE; 14880Sstevel@tonic-gate CK_ULONG found; 14890Sstevel@tonic-gate CK_OBJECT_CLASS obj_key = CKO_SECRET_KEY; 14900Sstevel@tonic-gate CK_ULONG ul_key_attr_count = 6; 14910Sstevel@tonic-gate char tmp_buf[20]; 14920Sstevel@tonic-gate 14930Sstevel@tonic-gate CK_ATTRIBUTE a_key_template[] = 14940Sstevel@tonic-gate { 14950Sstevel@tonic-gate {CKA_CLASS, (void*) NULL, sizeof(CK_OBJECT_CLASS)}, 14960Sstevel@tonic-gate {CKA_KEY_TYPE, (void*) NULL, sizeof(CK_KEY_TYPE)}, 14970Sstevel@tonic-gate {CKA_TOKEN, &false, sizeof(false)}, 14980Sstevel@tonic-gate {CKA_ENCRYPT, &true, sizeof(true)}, 14990Sstevel@tonic-gate {CKA_DECRYPT, &true, sizeof(true)}, 15000Sstevel@tonic-gate {CKA_VALUE, (void*) NULL, 0}, 15010Sstevel@tonic-gate }; 15020Sstevel@tonic-gate 15030Sstevel@tonic-gate /* Create secret key object in global_session. All other sessions 15040Sstevel@tonic-gate * can use the key handles. Here is why: 15050Sstevel@tonic-gate * OpenSSL will call EncryptInit and EncryptUpdate using a secret key. 15060Sstevel@tonic-gate * It may then call DecryptInit and DecryptUpdate using the same key. 15070Sstevel@tonic-gate * To use the same key object, we need to call EncryptFinal with 15080Sstevel@tonic-gate * a 0 length message. Currently, this does not work for 3DES 15090Sstevel@tonic-gate * mechanism. To get around this problem, we close the session and 15100Sstevel@tonic-gate * then create a new session to use the same key object. When a session 15110Sstevel@tonic-gate * is closed, all the object handles will be invalid. Thus, create key 15120Sstevel@tonic-gate * objects in a global session, an individual session may be closed to 15130Sstevel@tonic-gate * terminate the active operation. 15140Sstevel@tonic-gate */ 15150Sstevel@tonic-gate CK_SESSION_HANDLE session = global_session; 15160Sstevel@tonic-gate a_key_template[0].pValue = &obj_key; 15170Sstevel@tonic-gate a_key_template[1].pValue = &key_type; 15180Sstevel@tonic-gate a_key_template[5].pValue = (void *) key; 15190Sstevel@tonic-gate a_key_template[5].ulValueLen = (unsigned long) ctx->key_len; 15200Sstevel@tonic-gate 15214245Sjp161948 /* 15224245Sjp161948 * As stated in v2.20, 11.7 Object Management Function, in section for 15234245Sjp161948 * C_FindObjectsInit(), at most one search operation may be active at 15244245Sjp161948 * a given time in a given session. Therefore, we must group these 15254245Sjp161948 * three calls in one atomic operation. 15264245Sjp161948 */ 15274245Sjp161948 CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 15280Sstevel@tonic-gate rv = pFuncList->C_FindObjectsInit(session, a_key_template, 15290Sstevel@tonic-gate ul_key_attr_count); 15300Sstevel@tonic-gate 15310Sstevel@tonic-gate if (rv != CKR_OK) 15320Sstevel@tonic-gate { 15334245Sjp161948 CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 15340Sstevel@tonic-gate PK11err(PK11_F_GET_CIPHER_KEY, PK11_R_FINDOBJECTSINIT); 15350Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 15360Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 15370Sstevel@tonic-gate goto err; 15380Sstevel@tonic-gate } 15390Sstevel@tonic-gate 15400Sstevel@tonic-gate rv = pFuncList->C_FindObjects(session, &h_key, 1, &found); 15410Sstevel@tonic-gate 15420Sstevel@tonic-gate if (rv != CKR_OK) 15430Sstevel@tonic-gate { 15444245Sjp161948 CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 15450Sstevel@tonic-gate PK11err(PK11_F_GET_CIPHER_KEY, PK11_R_FINDOBJECTS); 15460Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 15470Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 15480Sstevel@tonic-gate goto err; 15490Sstevel@tonic-gate } 15500Sstevel@tonic-gate 15510Sstevel@tonic-gate rv = pFuncList->C_FindObjectsFinal(session); 15524245Sjp161948 CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 15530Sstevel@tonic-gate 15540Sstevel@tonic-gate if (rv != CKR_OK) 15550Sstevel@tonic-gate { 15560Sstevel@tonic-gate PK11err(PK11_F_GET_CIPHER_KEY, PK11_R_FINDOBJECTSFINAL); 15570Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 15580Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 15590Sstevel@tonic-gate goto err; 15600Sstevel@tonic-gate } 15610Sstevel@tonic-gate 15620Sstevel@tonic-gate if (found == 0) 15630Sstevel@tonic-gate { 15640Sstevel@tonic-gate rv = pFuncList->C_CreateObject(session, 15650Sstevel@tonic-gate a_key_template, ul_key_attr_count, &h_key); 15660Sstevel@tonic-gate if (rv != CKR_OK) 15670Sstevel@tonic-gate { 15680Sstevel@tonic-gate PK11err(PK11_F_GET_CIPHER_KEY, 15690Sstevel@tonic-gate PK11_R_CREATEOBJECT); 15700Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 15710Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 15720Sstevel@tonic-gate goto err; 15730Sstevel@tonic-gate } 15740Sstevel@tonic-gate } 15750Sstevel@tonic-gate 15760Sstevel@tonic-gate /* Save the key information used in this session. 15770Sstevel@tonic-gate * The max can be saved is PK11_KEY_LEN_MAX. 15780Sstevel@tonic-gate */ 15790Sstevel@tonic-gate sp->key_len = ctx->key_len > PK11_KEY_LEN_MAX ? 15800Sstevel@tonic-gate PK11_KEY_LEN_MAX : ctx->key_len; 15810Sstevel@tonic-gate memcpy(sp->key, key, sp->key_len); 15820Sstevel@tonic-gate err: 15830Sstevel@tonic-gate 15840Sstevel@tonic-gate return h_key; 15850Sstevel@tonic-gate } 15860Sstevel@tonic-gate 15870Sstevel@tonic-gate static int 15880Sstevel@tonic-gate md_nid_to_pk11(int nid) 15890Sstevel@tonic-gate { 15900Sstevel@tonic-gate int i; 15910Sstevel@tonic-gate 15920Sstevel@tonic-gate for (i = 0; i < PK11_DIGEST_MAX; i++) 15930Sstevel@tonic-gate if (digests[i].nid == nid) 15940Sstevel@tonic-gate return (digests[i].id); 15950Sstevel@tonic-gate return (-1); 15960Sstevel@tonic-gate } 15970Sstevel@tonic-gate 15980Sstevel@tonic-gate static int 15990Sstevel@tonic-gate pk11_digest_init(EVP_MD_CTX *ctx) 16000Sstevel@tonic-gate { 16010Sstevel@tonic-gate CK_RV rv; 1602*4320Sjp161948 CK_MECHANISM mech; 16030Sstevel@tonic-gate int index; 16040Sstevel@tonic-gate PK11_SESSION *sp; 16050Sstevel@tonic-gate PK11_DIGEST *pdp; 16060Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; 16070Sstevel@tonic-gate 16080Sstevel@tonic-gate state->sp = NULL; 16090Sstevel@tonic-gate 16100Sstevel@tonic-gate index = md_nid_to_pk11(ctx->digest->type); 16110Sstevel@tonic-gate if (index < 0 || index >= PK11_DIGEST_MAX) 16120Sstevel@tonic-gate return 0; 16130Sstevel@tonic-gate 16140Sstevel@tonic-gate pdp = &digests[index]; 16150Sstevel@tonic-gate if ((sp = pk11_get_session()) == NULL) 16160Sstevel@tonic-gate return 0; 16170Sstevel@tonic-gate 1618*4320Sjp161948 /* at present, no parameter is needed for supported digests */ 1619*4320Sjp161948 mech.mechanism = pdp->mech_type; 1620*4320Sjp161948 mech.pParameter = NULL; 1621*4320Sjp161948 mech.ulParameterLen = 0; 1622*4320Sjp161948 1623*4320Sjp161948 rv = pFuncList->C_DigestInit(sp->session, &mech); 16240Sstevel@tonic-gate 16250Sstevel@tonic-gate if (rv != CKR_OK) 16260Sstevel@tonic-gate { 16270Sstevel@tonic-gate char tmp_buf[20]; 16280Sstevel@tonic-gate PK11err(PK11_F_DIGEST_INIT, PK11_R_DIGESTINIT); 16290Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 16300Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 16310Sstevel@tonic-gate pk11_return_session(sp); 16320Sstevel@tonic-gate return 0; 16330Sstevel@tonic-gate } 16340Sstevel@tonic-gate 16350Sstevel@tonic-gate state->sp = sp; 16360Sstevel@tonic-gate 16370Sstevel@tonic-gate return 1; 16380Sstevel@tonic-gate } 16390Sstevel@tonic-gate 16400Sstevel@tonic-gate static int 16412139Sjp161948 pk11_digest_update(EVP_MD_CTX *ctx,const void *data,size_t count) 16420Sstevel@tonic-gate { 16430Sstevel@tonic-gate CK_RV rv; 16440Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; 16450Sstevel@tonic-gate 16460Sstevel@tonic-gate /* 0 length message will cause a failure in C_DigestFinal */ 16470Sstevel@tonic-gate if (count == 0) 16480Sstevel@tonic-gate return 1; 16490Sstevel@tonic-gate 16500Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 16510Sstevel@tonic-gate return 0; 16520Sstevel@tonic-gate 16530Sstevel@tonic-gate rv = pFuncList->C_DigestUpdate(state->sp->session, (CK_BYTE *) data, 16540Sstevel@tonic-gate count); 16550Sstevel@tonic-gate 16560Sstevel@tonic-gate if (rv != CKR_OK) 16570Sstevel@tonic-gate { 16580Sstevel@tonic-gate char tmp_buf[20]; 16590Sstevel@tonic-gate PK11err(PK11_F_DIGEST_UPDATE, PK11_R_DIGESTUPDATE); 16600Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 16610Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 16620Sstevel@tonic-gate pk11_return_session(state->sp); 16630Sstevel@tonic-gate state->sp = NULL; 16640Sstevel@tonic-gate return 0; 16650Sstevel@tonic-gate } 16660Sstevel@tonic-gate 16670Sstevel@tonic-gate return 1; 16680Sstevel@tonic-gate } 16690Sstevel@tonic-gate 16700Sstevel@tonic-gate static int 16710Sstevel@tonic-gate pk11_digest_final(EVP_MD_CTX *ctx,unsigned char *md) 16720Sstevel@tonic-gate { 16730Sstevel@tonic-gate CK_RV rv; 16740Sstevel@tonic-gate unsigned long len; 16750Sstevel@tonic-gate PK11_CIPHER_STATE *state = (PK11_CIPHER_STATE *) ctx->md_data; 16760Sstevel@tonic-gate len = ctx->digest->md_size; 16770Sstevel@tonic-gate 16780Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 16790Sstevel@tonic-gate return 0; 16800Sstevel@tonic-gate 16810Sstevel@tonic-gate rv = pFuncList->C_DigestFinal(state->sp->session, md, &len); 16820Sstevel@tonic-gate 16830Sstevel@tonic-gate if (rv != CKR_OK) 16840Sstevel@tonic-gate { 16850Sstevel@tonic-gate char tmp_buf[20]; 16860Sstevel@tonic-gate PK11err(PK11_F_DIGEST_FINAL, PK11_R_DIGESTFINAL); 16870Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 16880Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 16890Sstevel@tonic-gate pk11_return_session(state->sp); 16900Sstevel@tonic-gate state->sp = NULL; 16910Sstevel@tonic-gate return 0; 16920Sstevel@tonic-gate } 16930Sstevel@tonic-gate 16940Sstevel@tonic-gate if (ctx->digest->md_size != len) 16950Sstevel@tonic-gate return 0; 16960Sstevel@tonic-gate 16970Sstevel@tonic-gate /* Final is called and digest is returned, so return the session 16980Sstevel@tonic-gate * to the pool 16990Sstevel@tonic-gate */ 17000Sstevel@tonic-gate pk11_return_session(state->sp); 17010Sstevel@tonic-gate state->sp = NULL; 17020Sstevel@tonic-gate 17030Sstevel@tonic-gate return 1; 17040Sstevel@tonic-gate } 17050Sstevel@tonic-gate 17060Sstevel@tonic-gate static int 17070Sstevel@tonic-gate pk11_digest_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from) 17080Sstevel@tonic-gate { 17090Sstevel@tonic-gate CK_RV rv; 17100Sstevel@tonic-gate int ret = 0; 17110Sstevel@tonic-gate PK11_CIPHER_STATE *state, *state_to; 17120Sstevel@tonic-gate CK_BYTE_PTR pstate = NULL; 17130Sstevel@tonic-gate CK_ULONG ul_state_len; 17140Sstevel@tonic-gate char tmp_buf[20]; 17150Sstevel@tonic-gate 17160Sstevel@tonic-gate /* The copy-from state */ 17170Sstevel@tonic-gate state = (PK11_CIPHER_STATE *) from->md_data; 17180Sstevel@tonic-gate if (state == NULL || state->sp == NULL) 17190Sstevel@tonic-gate goto err; 17200Sstevel@tonic-gate 17210Sstevel@tonic-gate /* Initialize the copy-to state */ 17220Sstevel@tonic-gate if (!pk11_digest_init(to)) 17230Sstevel@tonic-gate goto err; 17240Sstevel@tonic-gate state_to = (PK11_CIPHER_STATE *) to->md_data; 17250Sstevel@tonic-gate 17260Sstevel@tonic-gate /* Get the size of the operation state of the copy-from session */ 17270Sstevel@tonic-gate rv = pFuncList->C_GetOperationState(state->sp->session, NULL, 17280Sstevel@tonic-gate &ul_state_len); 17290Sstevel@tonic-gate 17300Sstevel@tonic-gate if (rv != CKR_OK) 17310Sstevel@tonic-gate { 17320Sstevel@tonic-gate PK11err(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE); 17330Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 17340Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 17350Sstevel@tonic-gate goto err; 17360Sstevel@tonic-gate } 17370Sstevel@tonic-gate if (ul_state_len == 0) 17380Sstevel@tonic-gate { 17390Sstevel@tonic-gate goto err; 17400Sstevel@tonic-gate } 17410Sstevel@tonic-gate 17420Sstevel@tonic-gate pstate = OPENSSL_malloc(ul_state_len); 17430Sstevel@tonic-gate if (pstate == NULL) 17440Sstevel@tonic-gate { 17450Sstevel@tonic-gate RSAerr(PK11_F_DIGEST_COPY, PK11_R_MALLOC_FAILURE); 17460Sstevel@tonic-gate goto err; 17470Sstevel@tonic-gate } 17480Sstevel@tonic-gate 17490Sstevel@tonic-gate /* Get the operation state of the copy-from session */ 17500Sstevel@tonic-gate rv = pFuncList->C_GetOperationState(state->sp->session, pstate, 17510Sstevel@tonic-gate &ul_state_len); 17520Sstevel@tonic-gate 17530Sstevel@tonic-gate if (rv != CKR_OK) 17540Sstevel@tonic-gate { 17550Sstevel@tonic-gate PK11err(PK11_F_DIGEST_COPY, PK11_R_GET_OPERATION_STATE); 17560Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 17570Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 17580Sstevel@tonic-gate goto err; 17590Sstevel@tonic-gate } 17600Sstevel@tonic-gate 17610Sstevel@tonic-gate /* Set the operation state of the copy-to session */ 17620Sstevel@tonic-gate rv = pFuncList->C_SetOperationState(state_to->sp->session, pstate, 17630Sstevel@tonic-gate ul_state_len, 0, 0); 17640Sstevel@tonic-gate 17650Sstevel@tonic-gate if (rv != CKR_OK) 17660Sstevel@tonic-gate { 17670Sstevel@tonic-gate PK11err(PK11_F_DIGEST_COPY, PK11_R_SET_OPERATION_STATE); 17680Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 17690Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 17700Sstevel@tonic-gate goto err; 17710Sstevel@tonic-gate } 17720Sstevel@tonic-gate 17730Sstevel@tonic-gate ret = 1; 17740Sstevel@tonic-gate err: 17750Sstevel@tonic-gate if (pstate != NULL) 17760Sstevel@tonic-gate OPENSSL_free(pstate); 17770Sstevel@tonic-gate 17780Sstevel@tonic-gate return ret; 17790Sstevel@tonic-gate } 17800Sstevel@tonic-gate 17810Sstevel@tonic-gate /* Return any pending session state to the pool */ 17820Sstevel@tonic-gate static int 17830Sstevel@tonic-gate pk11_digest_cleanup(EVP_MD_CTX *ctx) 17840Sstevel@tonic-gate { 17850Sstevel@tonic-gate PK11_CIPHER_STATE *state = ctx->md_data; 17860Sstevel@tonic-gate 17870Sstevel@tonic-gate if (state != NULL && state->sp != NULL) 17880Sstevel@tonic-gate { 17890Sstevel@tonic-gate pk11_return_session(state->sp); 17900Sstevel@tonic-gate state->sp = NULL; 17910Sstevel@tonic-gate } 17920Sstevel@tonic-gate 17930Sstevel@tonic-gate return 1; 17940Sstevel@tonic-gate } 17950Sstevel@tonic-gate 17960Sstevel@tonic-gate /* Check if the new key is the same as the key object in the session. 17970Sstevel@tonic-gate * If the key is the same, no need to create a new key object. Otherwise, 17980Sstevel@tonic-gate * the old key object needs to be destroyed and a new one will be created 17990Sstevel@tonic-gate */ 18000Sstevel@tonic-gate static void check_new_cipher_key(PK11_SESSION *sp, const unsigned char *key) 18010Sstevel@tonic-gate { 18020Sstevel@tonic-gate if (memcmp(sp->key, key, sp->key_len) != 0) 18030Sstevel@tonic-gate pk11_destroy_cipher_key_objects(sp); 18040Sstevel@tonic-gate } 18050Sstevel@tonic-gate 18060Sstevel@tonic-gate /* Destroy one or more secret key objects. 18070Sstevel@tonic-gate */ 18080Sstevel@tonic-gate static int pk11_destroy_cipher_key_objects(PK11_SESSION *session) 18090Sstevel@tonic-gate { 18100Sstevel@tonic-gate int ret = 0; 18110Sstevel@tonic-gate PK11_SESSION *sp = NULL; 18120Sstevel@tonic-gate PK11_SESSION *local_free_session; 18130Sstevel@tonic-gate 18140Sstevel@tonic-gate CRYPTO_w_lock(CRYPTO_LOCK_PK11_ENGINE); 18150Sstevel@tonic-gate if (session) 18160Sstevel@tonic-gate local_free_session = session; 18170Sstevel@tonic-gate else 18180Sstevel@tonic-gate local_free_session = free_session; 18190Sstevel@tonic-gate while ((sp = local_free_session) != NULL) 18200Sstevel@tonic-gate { 18210Sstevel@tonic-gate local_free_session = sp->next; 18220Sstevel@tonic-gate 18230Sstevel@tonic-gate if (sp->cipher_key != CK_INVALID_HANDLE) 18240Sstevel@tonic-gate { 18250Sstevel@tonic-gate /* The secret key object is created in the 18260Sstevel@tonic-gate * global_session. See pk11_get_cipher_key 18270Sstevel@tonic-gate */ 18280Sstevel@tonic-gate if (pk11_destroy_object(global_session, 18290Sstevel@tonic-gate sp->cipher_key) == 0) 18300Sstevel@tonic-gate goto err; 18310Sstevel@tonic-gate sp->cipher_key = CK_INVALID_HANDLE; 18320Sstevel@tonic-gate } 18330Sstevel@tonic-gate } 18340Sstevel@tonic-gate ret = 1; 18350Sstevel@tonic-gate err: 18360Sstevel@tonic-gate CRYPTO_w_unlock(CRYPTO_LOCK_PK11_ENGINE); 18370Sstevel@tonic-gate 18380Sstevel@tonic-gate return ret; 18390Sstevel@tonic-gate } 18400Sstevel@tonic-gate 18410Sstevel@tonic-gate 18420Sstevel@tonic-gate /* 18430Sstevel@tonic-gate * Required mechanisms 18440Sstevel@tonic-gate * 18450Sstevel@tonic-gate * CKM_RSA_X_509 18460Sstevel@tonic-gate * CKM_RSA_PKCS 18470Sstevel@tonic-gate * CKM_DSA 18480Sstevel@tonic-gate * 18490Sstevel@tonic-gate * As long as these required mechanisms are met, it will return success. 18500Sstevel@tonic-gate * Otherwise, it will return failure and the engine initialization will fail. 18510Sstevel@tonic-gate * The application will then decide whether to use another engine or 18520Sstevel@tonic-gate * no engine. 18530Sstevel@tonic-gate * 18540Sstevel@tonic-gate * Symmetric ciphers optionally supported 18550Sstevel@tonic-gate * 18560Sstevel@tonic-gate * CKM_DES3_CBC 18570Sstevel@tonic-gate * CKM_DES_CBC 18580Sstevel@tonic-gate * CKM_AES_CBC 18590Sstevel@tonic-gate * CKM_RC4 18600Sstevel@tonic-gate * 18610Sstevel@tonic-gate * Digests optionally supported 18620Sstevel@tonic-gate * 18630Sstevel@tonic-gate * CKM_MD5 18640Sstevel@tonic-gate * CKM_SHA_1 18650Sstevel@tonic-gate */ 18660Sstevel@tonic-gate 18670Sstevel@tonic-gate static int 18680Sstevel@tonic-gate pk11_choose_slot() 18690Sstevel@tonic-gate { 18700Sstevel@tonic-gate CK_SLOT_ID_PTR pSlotList = NULL_PTR; 18710Sstevel@tonic-gate CK_ULONG ulSlotCount = 0; 18720Sstevel@tonic-gate CK_MECHANISM_INFO mech_info; 18730Sstevel@tonic-gate CK_TOKEN_INFO token_info; 18740Sstevel@tonic-gate int i; 18750Sstevel@tonic-gate CK_RV rv; 18760Sstevel@tonic-gate CK_SLOT_ID best_slot_sofar; 18770Sstevel@tonic-gate CK_BBOOL found_candidate_slot = CK_FALSE; 18780Sstevel@tonic-gate int slot_n_cipher = 0; 18790Sstevel@tonic-gate int slot_n_digest = 0; 18800Sstevel@tonic-gate CK_SLOT_ID current_slot = 0; 18810Sstevel@tonic-gate int current_slot_n_cipher = 0; 18820Sstevel@tonic-gate int current_slot_n_digest = 0; 18830Sstevel@tonic-gate 18840Sstevel@tonic-gate int local_cipher_nids[PK11_CIPHER_MAX]; 18850Sstevel@tonic-gate int local_digest_nids[PK11_DIGEST_MAX]; 18860Sstevel@tonic-gate char tmp_buf[20]; 18870Sstevel@tonic-gate int retval = 0; 18880Sstevel@tonic-gate 18890Sstevel@tonic-gate /* Get slot list for memory alloction */ 18900Sstevel@tonic-gate rv = pFuncList->C_GetSlotList(0, NULL_PTR, &ulSlotCount); 18910Sstevel@tonic-gate 18920Sstevel@tonic-gate if (rv != CKR_OK) 18930Sstevel@tonic-gate { 18940Sstevel@tonic-gate PK11err(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST); 18950Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 18960Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 18970Sstevel@tonic-gate return retval; 18980Sstevel@tonic-gate } 18990Sstevel@tonic-gate 19000Sstevel@tonic-gate if (ulSlotCount == 0) 19010Sstevel@tonic-gate { 19020Sstevel@tonic-gate PK11err(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST); 19030Sstevel@tonic-gate return retval; 19040Sstevel@tonic-gate } 19050Sstevel@tonic-gate 19060Sstevel@tonic-gate pSlotList = OPENSSL_malloc(ulSlotCount * sizeof (CK_SLOT_ID)); 19070Sstevel@tonic-gate 19080Sstevel@tonic-gate if (pSlotList == NULL) 19090Sstevel@tonic-gate { 19100Sstevel@tonic-gate RSAerr(PK11_F_CHOOSE_SLOT,PK11_R_MALLOC_FAILURE); 19110Sstevel@tonic-gate return retval; 19120Sstevel@tonic-gate } 19130Sstevel@tonic-gate 19140Sstevel@tonic-gate /* Get the slot list for processing */ 19150Sstevel@tonic-gate rv = pFuncList->C_GetSlotList(0, pSlotList, &ulSlotCount); 19160Sstevel@tonic-gate if (rv != CKR_OK) 19170Sstevel@tonic-gate { 19180Sstevel@tonic-gate PK11err(PK11_F_CHOOSE_SLOT, PK11_R_GETSLOTLIST); 19190Sstevel@tonic-gate snprintf(tmp_buf, sizeof (tmp_buf), "%lx", rv); 19200Sstevel@tonic-gate ERR_add_error_data(2, "PK11 CK_RV=0X", tmp_buf); 19210Sstevel@tonic-gate OPENSSL_free(pSlotList); 19220Sstevel@tonic-gate return retval; 19230Sstevel@tonic-gate } 19240Sstevel@tonic-gate 19250Sstevel@tonic-gate for (i = 0; i < ulSlotCount; i++) 19260Sstevel@tonic-gate { 19270Sstevel@tonic-gate CK_BBOOL slot_has_rsa = CK_FALSE; 19280Sstevel@tonic-gate CK_BBOOL slot_has_dsa = CK_FALSE; 19290Sstevel@tonic-gate CK_BBOOL slot_has_dh = CK_FALSE; 19300Sstevel@tonic-gate current_slot = pSlotList[i]; 19310Sstevel@tonic-gate current_slot_n_cipher = 0; 19320Sstevel@tonic-gate current_slot_n_digest = 0; 19330Sstevel@tonic-gate memset(local_cipher_nids, 0, sizeof(local_cipher_nids)); 19340Sstevel@tonic-gate memset(local_digest_nids, 0, sizeof(local_digest_nids)); 19350Sstevel@tonic-gate 19360Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 19370Sstevel@tonic-gate fprintf(stderr, "OPENSSL_PKCS#11_ENGINE: checking slot: %d\n", 19380Sstevel@tonic-gate current_slot); 19390Sstevel@tonic-gate #endif 19400Sstevel@tonic-gate /* Check if slot has random support. */ 19410Sstevel@tonic-gate rv = pFuncList->C_GetTokenInfo(current_slot, &token_info); 19420Sstevel@tonic-gate if (rv != CKR_OK) 19430Sstevel@tonic-gate continue; 19440Sstevel@tonic-gate 19450Sstevel@tonic-gate if (token_info.flags & CKF_RNG) 19460Sstevel@tonic-gate pk11_have_random = CK_TRUE; 19470Sstevel@tonic-gate 19480Sstevel@tonic-gate /* 19490Sstevel@tonic-gate * Check if this slot is capable of signing and 19500Sstevel@tonic-gate * verifying with CKM_RSA_PKCS. 19510Sstevel@tonic-gate */ 19520Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_RSA_PKCS, 19530Sstevel@tonic-gate &mech_info); 19540Sstevel@tonic-gate 19550Sstevel@tonic-gate if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && 19560Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY))) 19570Sstevel@tonic-gate { 19580Sstevel@tonic-gate /* 19590Sstevel@tonic-gate * Check if this slot is capable of encryption, 19600Sstevel@tonic-gate * decryption, sign, and verify with CKM_RSA_X_509. 19610Sstevel@tonic-gate */ 19620Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, 19630Sstevel@tonic-gate CKM_RSA_X_509, &mech_info); 19640Sstevel@tonic-gate 19650Sstevel@tonic-gate if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && 19660Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY) && 19670Sstevel@tonic-gate (mech_info.flags & CKF_ENCRYPT) && 19680Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY_RECOVER) && 19690Sstevel@tonic-gate (mech_info.flags & CKF_DECRYPT))) 19700Sstevel@tonic-gate slot_has_rsa = CK_TRUE; 19710Sstevel@tonic-gate } 19720Sstevel@tonic-gate 19730Sstevel@tonic-gate /* 19740Sstevel@tonic-gate * Check if this slot is capable of signing and 19750Sstevel@tonic-gate * verifying with CKM_DSA. 19760Sstevel@tonic-gate */ 19770Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, CKM_DSA, 19780Sstevel@tonic-gate &mech_info); 19790Sstevel@tonic-gate if (rv == CKR_OK && ((mech_info.flags & CKF_SIGN) && 19800Sstevel@tonic-gate (mech_info.flags & CKF_VERIFY))) 19810Sstevel@tonic-gate slot_has_dsa = CK_TRUE; 19820Sstevel@tonic-gate 19830Sstevel@tonic-gate /* 19840Sstevel@tonic-gate * Check if this slot is capable of DH key generataion and 19850Sstevel@tonic-gate * derivation. 19860Sstevel@tonic-gate */ 19870Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, 19880Sstevel@tonic-gate CKM_DH_PKCS_KEY_PAIR_GEN, &mech_info); 19890Sstevel@tonic-gate 19900Sstevel@tonic-gate if (rv == CKR_OK && (mech_info.flags & CKF_GENERATE_KEY_PAIR)) 19910Sstevel@tonic-gate { 19920Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(current_slot, 19930Sstevel@tonic-gate CKM_DH_PKCS_DERIVE, &mech_info); 19940Sstevel@tonic-gate if (rv == CKR_OK && (mech_info.flags & CKF_DERIVE)) 19950Sstevel@tonic-gate slot_has_dh = CK_TRUE; 19960Sstevel@tonic-gate } 19970Sstevel@tonic-gate 19980Sstevel@tonic-gate if (!found_candidate_slot && 19990Sstevel@tonic-gate (slot_has_rsa || slot_has_dsa || slot_has_dh)) 20000Sstevel@tonic-gate { 20010Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 20020Sstevel@tonic-gate fprintf(stderr, 20030Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: potential slot: %d\n", 20040Sstevel@tonic-gate current_slot); 20050Sstevel@tonic-gate #endif 20060Sstevel@tonic-gate best_slot_sofar = current_slot; 20070Sstevel@tonic-gate pk11_have_rsa = slot_has_rsa; 20080Sstevel@tonic-gate pk11_have_dsa = slot_has_dsa; 20090Sstevel@tonic-gate pk11_have_dh = slot_has_dh; 20100Sstevel@tonic-gate found_candidate_slot = CK_TRUE; 20110Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 20120Sstevel@tonic-gate fprintf(stderr, 20130Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: best so far slot: %d\n", 20140Sstevel@tonic-gate best_slot_sofar); 20150Sstevel@tonic-gate #endif 20160Sstevel@tonic-gate } 20170Sstevel@tonic-gate 20180Sstevel@tonic-gate /* Count symmetric cipher support. */ 20190Sstevel@tonic-gate if (!pk11_count_symmetric_cipher(current_slot, CKM_DES_CBC, 20200Sstevel@tonic-gate ¤t_slot_n_cipher, local_cipher_nids, 20210Sstevel@tonic-gate PK11_DES_CBC)) 20220Sstevel@tonic-gate continue; 20230Sstevel@tonic-gate if (!pk11_count_symmetric_cipher(current_slot, CKM_DES3_CBC, 20240Sstevel@tonic-gate ¤t_slot_n_cipher, local_cipher_nids, 20250Sstevel@tonic-gate PK11_DES3_CBC)) 20260Sstevel@tonic-gate continue; 20270Sstevel@tonic-gate if (!pk11_count_symmetric_cipher(current_slot, CKM_AES_CBC, 20280Sstevel@tonic-gate ¤t_slot_n_cipher, local_cipher_nids, 20290Sstevel@tonic-gate PK11_AES_CBC)) 20300Sstevel@tonic-gate continue; 20310Sstevel@tonic-gate if (!pk11_count_symmetric_cipher(current_slot, CKM_RC4, 20320Sstevel@tonic-gate ¤t_slot_n_cipher, local_cipher_nids, 20330Sstevel@tonic-gate PK11_RC4)) 20340Sstevel@tonic-gate continue; 20350Sstevel@tonic-gate 20360Sstevel@tonic-gate /* Count digest support */ 20370Sstevel@tonic-gate if (!pk11_count_digest(current_slot, CKM_MD5, 20380Sstevel@tonic-gate ¤t_slot_n_digest, local_digest_nids, 20390Sstevel@tonic-gate PK11_MD5)) 20400Sstevel@tonic-gate continue; 20410Sstevel@tonic-gate if (!pk11_count_digest(current_slot, CKM_SHA_1, 20420Sstevel@tonic-gate ¤t_slot_n_digest, local_digest_nids, 20430Sstevel@tonic-gate PK11_SHA1)) 20440Sstevel@tonic-gate continue; 20450Sstevel@tonic-gate 20460Sstevel@tonic-gate /* 20470Sstevel@tonic-gate * If the current slot supports more ciphers/digests than 20480Sstevel@tonic-gate * the previous best one we change the current best to this one. 20490Sstevel@tonic-gate * otherwise leave it where it is. 20500Sstevel@tonic-gate */ 20510Sstevel@tonic-gate if (((current_slot_n_cipher > slot_n_cipher) && 20520Sstevel@tonic-gate (current_slot_n_digest > slot_n_digest)) && 20530Sstevel@tonic-gate ((slot_has_rsa == pk11_have_rsa) && 20540Sstevel@tonic-gate (slot_has_dsa == pk11_have_dsa) && 20550Sstevel@tonic-gate (slot_has_dh == pk11_have_dh))) 20560Sstevel@tonic-gate { 20570Sstevel@tonic-gate best_slot_sofar = current_slot; 20580Sstevel@tonic-gate slot_n_cipher = current_slot_n_cipher; 20590Sstevel@tonic-gate slot_n_digest = current_slot_n_digest; 20600Sstevel@tonic-gate 20610Sstevel@tonic-gate memcpy(cipher_nids, local_cipher_nids, 20620Sstevel@tonic-gate sizeof(local_cipher_nids)); 20630Sstevel@tonic-gate memcpy(digest_nids, local_digest_nids, 20640Sstevel@tonic-gate sizeof(local_digest_nids)); 20650Sstevel@tonic-gate } 20660Sstevel@tonic-gate 20670Sstevel@tonic-gate } 20680Sstevel@tonic-gate 20690Sstevel@tonic-gate if (found_candidate_slot) 20700Sstevel@tonic-gate { 20710Sstevel@tonic-gate cipher_count = slot_n_cipher; 20720Sstevel@tonic-gate digest_count = slot_n_digest; 20730Sstevel@tonic-gate SLOTID = best_slot_sofar; 20740Sstevel@tonic-gate retval = 1; 20750Sstevel@tonic-gate } 20760Sstevel@tonic-gate else 20770Sstevel@tonic-gate { 20780Sstevel@tonic-gate cipher_count = 0; 20790Sstevel@tonic-gate digest_count = 0; 20800Sstevel@tonic-gate } 20810Sstevel@tonic-gate 20820Sstevel@tonic-gate #ifdef DEBUG_SLOT_SELECTION 20830Sstevel@tonic-gate fprintf(stderr, 20840Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: choose slot: %d\n", SLOTID); 20850Sstevel@tonic-gate fprintf(stderr, 20860Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: pk11_have_rsa %d\n", pk11_have_rsa); 20870Sstevel@tonic-gate fprintf(stderr, 20880Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: pk11_have_dsa %d\n", pk11_have_dsa); 20890Sstevel@tonic-gate fprintf(stderr, 20900Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: pk11_have_dh %d\n", pk11_have_dh); 20910Sstevel@tonic-gate fprintf(stderr, 20920Sstevel@tonic-gate "OPENSSL_PKCS#11_ENGINE: pk11_have_random %d\n", pk11_have_random); 20930Sstevel@tonic-gate #endif /* DEBUG_SLOT_SELECTION */ 20940Sstevel@tonic-gate 20950Sstevel@tonic-gate if (pSlotList) 20960Sstevel@tonic-gate free(pSlotList); 20970Sstevel@tonic-gate 20980Sstevel@tonic-gate return retval; 20990Sstevel@tonic-gate } 21000Sstevel@tonic-gate 21010Sstevel@tonic-gate static int pk11_count_symmetric_cipher(int slot_id, CK_MECHANISM_TYPE mech, 21020Sstevel@tonic-gate int *current_slot_n_cipher, int *local_cipher_nids, int id) 21030Sstevel@tonic-gate { 21040Sstevel@tonic-gate CK_MECHANISM_INFO mech_info; 21050Sstevel@tonic-gate CK_RV rv; 21060Sstevel@tonic-gate 21070Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(slot_id, mech, &mech_info); 21080Sstevel@tonic-gate 21090Sstevel@tonic-gate if (rv != CKR_OK) 21100Sstevel@tonic-gate return 0; 21110Sstevel@tonic-gate 21120Sstevel@tonic-gate if ((mech_info.flags & CKF_ENCRYPT) && 21130Sstevel@tonic-gate (mech_info.flags & CKF_DECRYPT)) 21140Sstevel@tonic-gate { 21150Sstevel@tonic-gate local_cipher_nids[(*current_slot_n_cipher)++] = ciphers[id].nid; 21160Sstevel@tonic-gate } 21170Sstevel@tonic-gate 21180Sstevel@tonic-gate return 1; 21190Sstevel@tonic-gate } 21200Sstevel@tonic-gate 21210Sstevel@tonic-gate 21220Sstevel@tonic-gate static int pk11_count_digest(int slot_id, CK_MECHANISM_TYPE mech, 21230Sstevel@tonic-gate int *current_slot_n_digest, int *local_digest_nids, int id) 21240Sstevel@tonic-gate { 21250Sstevel@tonic-gate CK_MECHANISM_INFO mech_info; 21260Sstevel@tonic-gate CK_RV rv; 21270Sstevel@tonic-gate 21280Sstevel@tonic-gate rv = pFuncList->C_GetMechanismInfo(slot_id, mech, &mech_info); 21290Sstevel@tonic-gate 21300Sstevel@tonic-gate if (rv != CKR_OK) 21310Sstevel@tonic-gate return 0; 21320Sstevel@tonic-gate 21330Sstevel@tonic-gate if (mech_info.flags & CKF_DIGEST) 21340Sstevel@tonic-gate { 21350Sstevel@tonic-gate local_digest_nids[(*current_slot_n_digest)++] = digests[id].nid; 21360Sstevel@tonic-gate } 21370Sstevel@tonic-gate 21380Sstevel@tonic-gate return 1; 21390Sstevel@tonic-gate } 21400Sstevel@tonic-gate 21410Sstevel@tonic-gate 21420Sstevel@tonic-gate #endif 21430Sstevel@tonic-gate #endif 21440Sstevel@tonic-gate 2145