xref: /onnv-gate/usr/src/common/openssl/crypto/engine/hw_pk11_pub.c (revision 11411:c2fe1bf96826)
10Sstevel@tonic-gate /*
2*11411SSurya.Prakki@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
30Sstevel@tonic-gate  * Use is subject to license terms.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate 
60Sstevel@tonic-gate /* crypto/engine/hw_pk11_pub.c */
77616SVladimir.Kotal@Sun.COM /*
87616SVladimir.Kotal@Sun.COM  * This product includes software developed by the OpenSSL Project for
90Sstevel@tonic-gate  * use in the OpenSSL Toolkit (http://www.openssl.org/).
100Sstevel@tonic-gate  *
117616SVladimir.Kotal@Sun.COM  * This project also referenced hw_pkcs11-0.9.7b.patch written by
120Sstevel@tonic-gate  * Afchine Madjlessi.
130Sstevel@tonic-gate  */
147616SVladimir.Kotal@Sun.COM /*
157616SVladimir.Kotal@Sun.COM  * ====================================================================
160Sstevel@tonic-gate  * Copyright (c) 2000-2001 The OpenSSL Project.  All rights reserved.
170Sstevel@tonic-gate  *
180Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
190Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
200Sstevel@tonic-gate  * are met:
210Sstevel@tonic-gate  *
220Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
237616SVladimir.Kotal@Sun.COM  *    notice, this list of conditions and the following disclaimer.
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
260Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
270Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
280Sstevel@tonic-gate  *    distribution.
290Sstevel@tonic-gate  *
300Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this
310Sstevel@tonic-gate  *    software must display the following acknowledgment:
320Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
330Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
340Sstevel@tonic-gate  *
350Sstevel@tonic-gate  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
360Sstevel@tonic-gate  *    endorse or promote products derived from this software without
370Sstevel@tonic-gate  *    prior written permission. For written permission, please contact
380Sstevel@tonic-gate  *    licensing@OpenSSL.org.
390Sstevel@tonic-gate  *
400Sstevel@tonic-gate  * 5. Products derived from this software may not be called "OpenSSL"
410Sstevel@tonic-gate  *    nor may "OpenSSL" appear in their names without prior written
420Sstevel@tonic-gate  *    permission of the OpenSSL Project.
430Sstevel@tonic-gate  *
440Sstevel@tonic-gate  * 6. Redistributions of any form whatsoever must retain the following
450Sstevel@tonic-gate  *    acknowledgment:
460Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
470Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
480Sstevel@tonic-gate  *
490Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
500Sstevel@tonic-gate  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
510Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
520Sstevel@tonic-gate  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
530Sstevel@tonic-gate  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
540Sstevel@tonic-gate  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
550Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
560Sstevel@tonic-gate  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
570Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
580Sstevel@tonic-gate  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
590Sstevel@tonic-gate  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
600Sstevel@tonic-gate  * OF THE POSSIBILITY OF SUCH DAMAGE.
610Sstevel@tonic-gate  * ====================================================================
620Sstevel@tonic-gate  *
630Sstevel@tonic-gate  * This product includes cryptographic software written by Eric Young
640Sstevel@tonic-gate  * (eay@cryptsoft.com).  This product includes software written by Tim
650Sstevel@tonic-gate  * Hudson (tjh@cryptsoft.com).
660Sstevel@tonic-gate  *
670Sstevel@tonic-gate  */
680Sstevel@tonic-gate 
690Sstevel@tonic-gate #include <stdio.h>
700Sstevel@tonic-gate #include <stdlib.h>
710Sstevel@tonic-gate #include <string.h>
720Sstevel@tonic-gate #include <sys/types.h>
730Sstevel@tonic-gate #include <unistd.h>
740Sstevel@tonic-gate 
750Sstevel@tonic-gate #include <openssl/e_os2.h>
766847Svk199839 #include <openssl/crypto.h>
770Sstevel@tonic-gate #include <openssl/engine.h>
780Sstevel@tonic-gate #include <openssl/dso.h>
790Sstevel@tonic-gate #include <openssl/err.h>
800Sstevel@tonic-gate #include <openssl/bn.h>
810Sstevel@tonic-gate #include <openssl/pem.h>
826847Svk199839 #ifndef OPENSSL_NO_RSA
830Sstevel@tonic-gate #include <openssl/rsa.h>
847211Sjp161948 #endif /* OPENSSL_NO_RSA */
856847Svk199839 #ifndef OPENSSL_NO_DSA
866847Svk199839 #include <openssl/dsa.h>
877211Sjp161948 #endif /* OPENSSL_NO_DSA */
886847Svk199839 #ifndef OPENSSL_NO_DH
896847Svk199839 #include <openssl/dh.h>
907211Sjp161948 #endif /* OPENSSL_NO_DH */
910Sstevel@tonic-gate #include <openssl/rand.h>
920Sstevel@tonic-gate #include <openssl/objects.h>
930Sstevel@tonic-gate #include <openssl/x509.h>
940Sstevel@tonic-gate #include <cryptlib.h>
957526SVladimir.Kotal@Sun.COM #include <pthread.h>
960Sstevel@tonic-gate 
970Sstevel@tonic-gate #ifndef OPENSSL_NO_HW
980Sstevel@tonic-gate #ifndef OPENSSL_NO_HW_PK11
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate #include "security/cryptoki.h"
1010Sstevel@tonic-gate #include "security/pkcs11.h"
1027534SVladimir.Kotal@Sun.COM #include "hw_pk11_err.h"
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA
1050Sstevel@tonic-gate /* RSA stuff */
1067526SVladimir.Kotal@Sun.COM static int pk11_RSA_public_encrypt(int flen, const unsigned char *from,
1070Sstevel@tonic-gate 	unsigned char *to, RSA *rsa, int padding);
1087526SVladimir.Kotal@Sun.COM static int pk11_RSA_private_encrypt(int flen, const unsigned char *from,
1090Sstevel@tonic-gate 	unsigned char *to, RSA *rsa, int padding);
1107526SVladimir.Kotal@Sun.COM static int pk11_RSA_public_decrypt(int flen, const unsigned char *from,
1110Sstevel@tonic-gate 	unsigned char *to, RSA *rsa, int padding);
1127526SVladimir.Kotal@Sun.COM static int pk11_RSA_private_decrypt(int flen, const unsigned char *from,
1130Sstevel@tonic-gate 	unsigned char *to, RSA *rsa, int padding);
1140Sstevel@tonic-gate static int pk11_RSA_init(RSA *rsa);
1150Sstevel@tonic-gate static int pk11_RSA_finish(RSA *rsa);
1160Sstevel@tonic-gate static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
1170Sstevel@tonic-gate 	unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
1187526SVladimir.Kotal@Sun.COM static int pk11_RSA_verify(int dtype, const unsigned char *m,
1197526SVladimir.Kotal@Sun.COM 	unsigned int m_len, unsigned char *sigbuf, unsigned int siglen,
1200Sstevel@tonic-gate 	const RSA *rsa);
1217616SVladimir.Kotal@Sun.COM EVP_PKEY *pk11_load_privkey(ENGINE*, const char *pubkey_file,
1220Sstevel@tonic-gate 	UI_METHOD *ui_method, void *callback_data);
1237616SVladimir.Kotal@Sun.COM EVP_PKEY *pk11_load_pubkey(ENGINE*, const char *pubkey_file,
1240Sstevel@tonic-gate 	UI_METHOD *ui_method, void *callback_data);
1250Sstevel@tonic-gate 
1267616SVladimir.Kotal@Sun.COM static int pk11_RSA_public_encrypt_low(int flen, const unsigned char *from,
1270Sstevel@tonic-gate 	unsigned char *to, RSA *rsa);
1287616SVladimir.Kotal@Sun.COM static int pk11_RSA_private_encrypt_low(int flen, const unsigned char *from,
1290Sstevel@tonic-gate 	unsigned char *to, RSA *rsa);
1307616SVladimir.Kotal@Sun.COM static int pk11_RSA_public_decrypt_low(int flen, const unsigned char *from,
1310Sstevel@tonic-gate 	unsigned char *to, RSA *rsa);
1327616SVladimir.Kotal@Sun.COM static int pk11_RSA_private_decrypt_low(int flen, const unsigned char *from,
1330Sstevel@tonic-gate 	unsigned char *to, RSA *rsa);
1340Sstevel@tonic-gate 
1356847Svk199839 static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa, RSA** key_ptr,
1366847Svk199839 	BIGNUM **rsa_n_num, BIGNUM **rsa_e_num, CK_SESSION_HANDLE session);
1376847Svk199839 static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa, RSA** key_ptr,
1386847Svk199839 	BIGNUM **rsa_d_num, CK_SESSION_HANDLE session);
1396847Svk199839 
1406847Svk199839 static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa);
1416847Svk199839 static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa);
1420Sstevel@tonic-gate #endif
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate /* DSA stuff */
1456847Svk199839 #ifndef OPENSSL_NO_DSA
1460Sstevel@tonic-gate static int pk11_DSA_init(DSA *dsa);
1470Sstevel@tonic-gate static int pk11_DSA_finish(DSA *dsa);
1487616SVladimir.Kotal@Sun.COM static DSA_SIG *pk11_dsa_do_sign(const unsigned char *dgst, int dlen,
1490Sstevel@tonic-gate 	DSA *dsa);
1500Sstevel@tonic-gate static int pk11_dsa_do_verify(const unsigned char *dgst, int dgst_len,
1510Sstevel@tonic-gate 	DSA_SIG *sig, DSA *dsa);
1520Sstevel@tonic-gate 
1536847Svk199839 static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa, DSA **key_ptr,
1546847Svk199839 	BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session);
1556847Svk199839 static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa, DSA **key_ptr,
1566847Svk199839 	BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session);
1576847Svk199839 
1586847Svk199839 static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa);
1596847Svk199839 static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa);
1600Sstevel@tonic-gate #endif
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate /* DH stuff */
1630Sstevel@tonic-gate #ifndef OPENSSL_NO_DH
1640Sstevel@tonic-gate static int pk11_DH_init(DH *dh);
1650Sstevel@tonic-gate static int pk11_DH_finish(DH *dh);
1660Sstevel@tonic-gate static int pk11_DH_generate_key(DH *dh);
1670Sstevel@tonic-gate static int pk11_DH_compute_key(unsigned char *key,
1687616SVladimir.Kotal@Sun.COM 	const BIGNUM *pub_key, DH *dh);
1690Sstevel@tonic-gate 
1706847Svk199839 static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh, DH **key_ptr,
1716847Svk199839 	BIGNUM **priv_key, CK_SESSION_HANDLE session);
1726847Svk199839 
1736847Svk199839 static int check_new_dh_key(PK11_SESSION *sp, DH *dh);
1740Sstevel@tonic-gate #endif
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate static int init_template_value(BIGNUM *bn, CK_VOID_PTR *pValue,
1777616SVladimir.Kotal@Sun.COM 	CK_ULONG *ulValueLen);
1786847Svk199839 
1797628SVladimir.Kotal@Sun.COM /* Read mode string to be used for fopen() */
1807628SVladimir.Kotal@Sun.COM #if SOLARIS_OPENSSL
1817628SVladimir.Kotal@Sun.COM static char *read_mode_flags = "rF";
1827628SVladimir.Kotal@Sun.COM #else
1837628SVladimir.Kotal@Sun.COM static char *read_mode_flags = "r";
1847628SVladimir.Kotal@Sun.COM #endif
1857628SVladimir.Kotal@Sun.COM 
1866847Svk199839 /*
1877526SVladimir.Kotal@Sun.COM  * increment/create reference for an asymmetric key handle via active list
1887526SVladimir.Kotal@Sun.COM  * manipulation. If active list operation fails, unlock (if locked), set error
1897526SVladimir.Kotal@Sun.COM  * variable and jump to the specified label.
1906847Svk199839  */
1917526SVladimir.Kotal@Sun.COM #define	KEY_HANDLE_REFHOLD(key_handle, alg_type, unlock, var, label)	\
1927526SVladimir.Kotal@Sun.COM 	{								\
1937526SVladimir.Kotal@Sun.COM 	if (pk11_active_add(key_handle, alg_type) < 0)			\
1947526SVladimir.Kotal@Sun.COM 		{							\
1957526SVladimir.Kotal@Sun.COM 		var = TRUE;						\
1967526SVladimir.Kotal@Sun.COM 		if (unlock)						\
1977526SVladimir.Kotal@Sun.COM 			UNLOCK_OBJSTORE(alg_type);			\
1987526SVladimir.Kotal@Sun.COM 		goto label;						\
1997526SVladimir.Kotal@Sun.COM 		}							\
2007526SVladimir.Kotal@Sun.COM 	}
2017526SVladimir.Kotal@Sun.COM 
2027526SVladimir.Kotal@Sun.COM /*
2037526SVladimir.Kotal@Sun.COM  * Find active list entry according to object handle and return pointer to the
2047526SVladimir.Kotal@Sun.COM  * entry otherwise return NULL.
2057526SVladimir.Kotal@Sun.COM  *
2067526SVladimir.Kotal@Sun.COM  * This function presumes it is called with lock protecting the active list
2077526SVladimir.Kotal@Sun.COM  * held.
2087526SVladimir.Kotal@Sun.COM  */
pk11_active_find(CK_OBJECT_HANDLE h,PK11_OPTYPE type)2097526SVladimir.Kotal@Sun.COM static PK11_active *pk11_active_find(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
2106847Svk199839 	{
2116847Svk199839 	PK11_active *entry;
2126847Svk199839 
2137526SVladimir.Kotal@Sun.COM 	for (entry = active_list[type]; entry != NULL; entry = entry->next)
2146847Svk199839 		if (entry->h == h)
2156847Svk199839 			return (entry);
2166847Svk199839 
2176847Svk199839 	return (NULL);
2186847Svk199839 	}
2196847Svk199839 
2206847Svk199839 /*
2216847Svk199839  * Search for an entry in the active list using PKCS#11 object handle as a
2227526SVladimir.Kotal@Sun.COM  * search key and return refcnt of the found/created entry or -1 in case of
2237526SVladimir.Kotal@Sun.COM  * failure.
2246847Svk199839  *
2257526SVladimir.Kotal@Sun.COM  * This function presumes it is called with lock protecting the active list
2267526SVladimir.Kotal@Sun.COM  * held.
2276847Svk199839  */
2287616SVladimir.Kotal@Sun.COM int
pk11_active_add(CK_OBJECT_HANDLE h,PK11_OPTYPE type)2297616SVladimir.Kotal@Sun.COM pk11_active_add(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
2306847Svk199839 	{
2316847Svk199839 	PK11_active *entry = NULL;
2326847Svk199839 
2336847Svk199839 	if (h == CK_INVALID_HANDLE)
2346847Svk199839 		{
2356847Svk199839 		PK11err(PK11_F_ACTIVE_ADD, PK11_R_INVALID_HANDLE);
2366847Svk199839 		return (-1);
2376847Svk199839 		}
2380Sstevel@tonic-gate 
2396847Svk199839 	/* search for entry in the active list */
2407526SVladimir.Kotal@Sun.COM 	if ((entry = pk11_active_find(h, type)) != NULL)
2416847Svk199839 		entry->refcnt++;
2426847Svk199839 	else
2436847Svk199839 		{
2446847Svk199839 		/* not found, create new entry and add it to the list */
2456847Svk199839 		entry = OPENSSL_malloc(sizeof (PK11_active));
2466847Svk199839 		if (entry == NULL)
2476847Svk199839 			{
2486847Svk199839 			PK11err(PK11_F_ACTIVE_ADD, PK11_R_MALLOC_FAILURE);
2496847Svk199839 			return (-1);
2506847Svk199839 			}
2516847Svk199839 		entry->h = h;
2526847Svk199839 		entry->refcnt = 1;
2536847Svk199839 		entry->prev = NULL;
2546847Svk199839 		entry->next = NULL;
2556847Svk199839 		/* connect the newly created entry to the list */
2567526SVladimir.Kotal@Sun.COM 		if (active_list[type] == NULL)
2577526SVladimir.Kotal@Sun.COM 			active_list[type] = entry;
2586847Svk199839 		else /* make the entry first in the list */
2596847Svk199839 			{
2607526SVladimir.Kotal@Sun.COM 			entry->next = active_list[type];
2617526SVladimir.Kotal@Sun.COM 			active_list[type]->prev = entry;
2627526SVladimir.Kotal@Sun.COM 			active_list[type] = entry;
2636847Svk199839 			}
2646847Svk199839 		}
2656847Svk199839 
2666847Svk199839 	return (entry->refcnt);
2676847Svk199839 	}
2686847Svk199839 
2696847Svk199839 /*
2707526SVladimir.Kotal@Sun.COM  * Remove active list entry from the list and free it.
2717526SVladimir.Kotal@Sun.COM  *
2727526SVladimir.Kotal@Sun.COM  * This function presumes it is called with lock protecting the active list
2737526SVladimir.Kotal@Sun.COM  * held.
2747526SVladimir.Kotal@Sun.COM  */
2757616SVladimir.Kotal@Sun.COM void
pk11_active_remove(PK11_active * entry,PK11_OPTYPE type)2767616SVladimir.Kotal@Sun.COM pk11_active_remove(PK11_active *entry, PK11_OPTYPE type)
2777526SVladimir.Kotal@Sun.COM 	{
2787526SVladimir.Kotal@Sun.COM 	PK11_active *prev_entry;
2797526SVladimir.Kotal@Sun.COM 
2807526SVladimir.Kotal@Sun.COM 	/* remove the entry from the list and free it */
2817526SVladimir.Kotal@Sun.COM 	if ((prev_entry = entry->prev) != NULL)
2827526SVladimir.Kotal@Sun.COM 		{
2837526SVladimir.Kotal@Sun.COM 		prev_entry->next = entry->next;
2847526SVladimir.Kotal@Sun.COM 		if (entry->next != NULL)
2857526SVladimir.Kotal@Sun.COM 			entry->next->prev = prev_entry;
2867526SVladimir.Kotal@Sun.COM 		}
2877526SVladimir.Kotal@Sun.COM 	else
2887526SVladimir.Kotal@Sun.COM 		{
2897526SVladimir.Kotal@Sun.COM 		active_list[type] = entry->next;
2907526SVladimir.Kotal@Sun.COM 		/* we were the first but not the only one */
2917526SVladimir.Kotal@Sun.COM 		if (entry->next != NULL)
2927526SVladimir.Kotal@Sun.COM 			entry->next->prev = NULL;
2937526SVladimir.Kotal@Sun.COM 		}
2947526SVladimir.Kotal@Sun.COM 
2957526SVladimir.Kotal@Sun.COM 	/* sanitization */
2967526SVladimir.Kotal@Sun.COM 	entry->h = CK_INVALID_HANDLE;
2977526SVladimir.Kotal@Sun.COM 	entry->prev = NULL;
2987526SVladimir.Kotal@Sun.COM 	entry->next = NULL;
2997526SVladimir.Kotal@Sun.COM 	OPENSSL_free(entry);
3007526SVladimir.Kotal@Sun.COM 	}
3017526SVladimir.Kotal@Sun.COM 
3027526SVladimir.Kotal@Sun.COM /* Free all entries from the active list. */
3037616SVladimir.Kotal@Sun.COM void
pk11_free_active_list(PK11_OPTYPE type)3047616SVladimir.Kotal@Sun.COM pk11_free_active_list(PK11_OPTYPE type)
3057526SVladimir.Kotal@Sun.COM 	{
3067526SVladimir.Kotal@Sun.COM 	PK11_active *entry;
3077526SVladimir.Kotal@Sun.COM 
3087526SVladimir.Kotal@Sun.COM 	/* only for asymmetric types since only they have C_Find* locks. */
3097526SVladimir.Kotal@Sun.COM 	switch (type)
3107526SVladimir.Kotal@Sun.COM 		{
3117526SVladimir.Kotal@Sun.COM 		case OP_RSA:
3127526SVladimir.Kotal@Sun.COM 		case OP_DSA:
3137526SVladimir.Kotal@Sun.COM 		case OP_DH:
3147526SVladimir.Kotal@Sun.COM 			break;
3157526SVladimir.Kotal@Sun.COM 		default:
3167526SVladimir.Kotal@Sun.COM 			return;
3177526SVladimir.Kotal@Sun.COM 		}
3187526SVladimir.Kotal@Sun.COM 
3197526SVladimir.Kotal@Sun.COM 	/* see find_lock array definition for more info on object locking */
3207526SVladimir.Kotal@Sun.COM 	LOCK_OBJSTORE(type);
3217526SVladimir.Kotal@Sun.COM 	while ((entry = active_list[type]) != NULL)
3227526SVladimir.Kotal@Sun.COM 		pk11_active_remove(entry, type);
3237526SVladimir.Kotal@Sun.COM 	UNLOCK_OBJSTORE(type);
3247526SVladimir.Kotal@Sun.COM 	}
3257526SVladimir.Kotal@Sun.COM 
3267526SVladimir.Kotal@Sun.COM /*
3276847Svk199839  * Search for active list entry associated with given PKCS#11 object handle,
3286847Svk199839  * decrement its refcnt and if it drops to 0, disconnect the entry and free it.
3296847Svk199839  *
3306847Svk199839  * Return 1 if the PKCS#11 object associated with the entry has no references,
3316847Svk199839  * return 0 if there is at least one reference, -1 on error.
3326847Svk199839  *
3337526SVladimir.Kotal@Sun.COM  * This function presumes it is called with lock protecting the active list
3347526SVladimir.Kotal@Sun.COM  * held.
3356847Svk199839  */
3367616SVladimir.Kotal@Sun.COM int
pk11_active_delete(CK_OBJECT_HANDLE h,PK11_OPTYPE type)3377616SVladimir.Kotal@Sun.COM pk11_active_delete(CK_OBJECT_HANDLE h, PK11_OPTYPE type)
3386847Svk199839 	{
3396847Svk199839 	PK11_active *entry = NULL;
3406847Svk199839 
3417526SVladimir.Kotal@Sun.COM 	if ((entry = pk11_active_find(h, type)) == NULL)
3426847Svk199839 		{
3436847Svk199839 		PK11err(PK11_F_ACTIVE_DELETE, PK11_R_INVALID_HANDLE);
3446847Svk199839 		return (-1);
3456847Svk199839 		}
3466847Svk199839 
3476847Svk199839 	OPENSSL_assert(entry->refcnt > 0);
3486847Svk199839 	entry->refcnt--;
3496847Svk199839 	if (entry->refcnt == 0)
3506847Svk199839 		{
3517526SVladimir.Kotal@Sun.COM 		pk11_active_remove(entry, type);
3526847Svk199839 		return (1);
3536847Svk199839 		}
3546847Svk199839 
3556847Svk199839 	return (0);
3566847Svk199839 	}
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA
3590Sstevel@tonic-gate /* Our internal RSA_METHOD that we provide pointers to */
3600Sstevel@tonic-gate static RSA_METHOD pk11_rsa =
3610Sstevel@tonic-gate 	{
3620Sstevel@tonic-gate 	"PKCS#11 RSA method",
3630Sstevel@tonic-gate 	pk11_RSA_public_encrypt,		/* rsa_pub_encrypt */
3640Sstevel@tonic-gate 	pk11_RSA_public_decrypt,		/* rsa_pub_decrypt */
3650Sstevel@tonic-gate 	pk11_RSA_private_encrypt,		/* rsa_priv_encrypt */
3660Sstevel@tonic-gate 	pk11_RSA_private_decrypt,		/* rsa_priv_decrypt */
3670Sstevel@tonic-gate 	NULL,					/* rsa_mod_exp */
3680Sstevel@tonic-gate 	NULL,					/* bn_mod_exp */
3690Sstevel@tonic-gate 	pk11_RSA_init,				/* init */
3700Sstevel@tonic-gate 	pk11_RSA_finish,			/* finish */
3710Sstevel@tonic-gate 	RSA_FLAG_SIGN_VER,			/* flags */
3720Sstevel@tonic-gate 	NULL,					/* app_data */
3730Sstevel@tonic-gate 	pk11_RSA_sign,				/* rsa_sign */
3747616SVladimir.Kotal@Sun.COM 	pk11_RSA_verify				/* rsa_verify */
3750Sstevel@tonic-gate 	};
3760Sstevel@tonic-gate 
3777616SVladimir.Kotal@Sun.COM RSA_METHOD *
PK11_RSA(void)3787616SVladimir.Kotal@Sun.COM PK11_RSA(void)
3790Sstevel@tonic-gate 	{
3807616SVladimir.Kotal@Sun.COM 	return (&pk11_rsa);
3810Sstevel@tonic-gate 	}
3820Sstevel@tonic-gate #endif
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
3850Sstevel@tonic-gate /* Our internal DSA_METHOD that we provide pointers to */
3860Sstevel@tonic-gate static DSA_METHOD pk11_dsa =
3870Sstevel@tonic-gate 	{
3880Sstevel@tonic-gate 	"PKCS#11 DSA method",
3890Sstevel@tonic-gate 	pk11_dsa_do_sign, 	/* dsa_do_sign */
3900Sstevel@tonic-gate 	NULL, 			/* dsa_sign_setup */
3910Sstevel@tonic-gate 	pk11_dsa_do_verify, 	/* dsa_do_verify */
3920Sstevel@tonic-gate 	NULL,			/* dsa_mod_exp */
3930Sstevel@tonic-gate 	NULL, 			/* bn_mod_exp */
3940Sstevel@tonic-gate 	pk11_DSA_init, 		/* init */
3950Sstevel@tonic-gate 	pk11_DSA_finish, 	/* finish */
3960Sstevel@tonic-gate 	0, 			/* flags */
3970Sstevel@tonic-gate 	NULL 			/* app_data */
3980Sstevel@tonic-gate 	};
3990Sstevel@tonic-gate 
4007616SVladimir.Kotal@Sun.COM DSA_METHOD *
PK11_DSA(void)4017616SVladimir.Kotal@Sun.COM PK11_DSA(void)
4020Sstevel@tonic-gate 	{
4037616SVladimir.Kotal@Sun.COM 	return (&pk11_dsa);
4040Sstevel@tonic-gate 	}
4050Sstevel@tonic-gate #endif
4060Sstevel@tonic-gate 
4076847Svk199839 #ifndef OPENSSL_NO_DH
4086847Svk199839 /*
4096847Svk199839  * PKCS #11 V2.20, section 11.2 specifies that the number of bytes needed for
4106847Svk199839  * output buffer may somewhat exceed the precise number of bytes needed, but
4116847Svk199839  * should not exceed it by a large amount. That may be caused, for example, by
4126847Svk199839  * rounding it up to multiple of X in the underlying bignum library. 8 should be
4136847Svk199839  * enough.
4146847Svk199839  */
4156847Svk199839 #define	DH_BUF_RESERVE	8
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate /* Our internal DH_METHOD that we provide pointers to */
4180Sstevel@tonic-gate static DH_METHOD pk11_dh =
4190Sstevel@tonic-gate 	{
4200Sstevel@tonic-gate 	"PKCS#11 DH method",
4210Sstevel@tonic-gate 	pk11_DH_generate_key,	/* generate_key */
4220Sstevel@tonic-gate 	pk11_DH_compute_key,	/* compute_key */
4230Sstevel@tonic-gate 	NULL,			/* bn_mod_exp */
4240Sstevel@tonic-gate 	pk11_DH_init,		/* init */
4250Sstevel@tonic-gate 	pk11_DH_finish,		/* finish */
4260Sstevel@tonic-gate 	0,			/* flags */
4277211Sjp161948 	NULL,			/* app_data */
4287211Sjp161948 	NULL			/* generate_params */
4290Sstevel@tonic-gate 	};
4300Sstevel@tonic-gate 
4317616SVladimir.Kotal@Sun.COM DH_METHOD *
PK11_DH(void)4327616SVladimir.Kotal@Sun.COM PK11_DH(void)
4330Sstevel@tonic-gate 	{
4347616SVladimir.Kotal@Sun.COM 	return (&pk11_dh);
4350Sstevel@tonic-gate 	}
4360Sstevel@tonic-gate #endif
4370Sstevel@tonic-gate 
4387616SVladimir.Kotal@Sun.COM /* Size of an SSL signature: MD5+SHA1 */
4397616SVladimir.Kotal@Sun.COM #define	SSL_SIG_LENGTH		36
4400Sstevel@tonic-gate 
4417616SVladimir.Kotal@Sun.COM /* Lengths of DSA data and signature */
4427616SVladimir.Kotal@Sun.COM #define	DSA_DATA_LEN		20
4437616SVladimir.Kotal@Sun.COM #define	DSA_SIGNATURE_LEN	40
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate static CK_BBOOL true = TRUE;
4460Sstevel@tonic-gate static CK_BBOOL false = FALSE;
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA
4497616SVladimir.Kotal@Sun.COM /*
4507616SVladimir.Kotal@Sun.COM  * Similiar to OpenSSL to take advantage of the paddings. The goal is to
4517616SVladimir.Kotal@Sun.COM  * support all paddings in this engine although PK11 library does not
4527616SVladimir.Kotal@Sun.COM  * support all the paddings used in OpenSSL.
4537616SVladimir.Kotal@Sun.COM  * The input errors should have been checked in the padding functions.
4540Sstevel@tonic-gate  */
pk11_RSA_public_encrypt(int flen,const unsigned char * from,unsigned char * to,RSA * rsa,int padding)4550Sstevel@tonic-gate static int pk11_RSA_public_encrypt(int flen, const unsigned char *from,
4560Sstevel@tonic-gate 		unsigned char *to, RSA *rsa, int padding)
4570Sstevel@tonic-gate 	{
4587616SVladimir.Kotal@Sun.COM 	int i, num = 0, r = -1;
4597616SVladimir.Kotal@Sun.COM 	unsigned char *buf = NULL;
4600Sstevel@tonic-gate 
4617616SVladimir.Kotal@Sun.COM 	num = BN_num_bytes(rsa->n);
4627616SVladimir.Kotal@Sun.COM 	if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL)
4630Sstevel@tonic-gate 		{
4647616SVladimir.Kotal@Sun.COM 		RSAerr(PK11_F_RSA_PUB_ENC, PK11_R_MALLOC_FAILURE);
4650Sstevel@tonic-gate 		goto err;
4660Sstevel@tonic-gate 		}
4670Sstevel@tonic-gate 
4680Sstevel@tonic-gate 	switch (padding)
4690Sstevel@tonic-gate 		{
4700Sstevel@tonic-gate 	case RSA_PKCS1_PADDING:
4717616SVladimir.Kotal@Sun.COM 		i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen);
4720Sstevel@tonic-gate 		break;
4730Sstevel@tonic-gate #ifndef OPENSSL_NO_SHA
4740Sstevel@tonic-gate 	case RSA_PKCS1_OAEP_PADDING:
4757616SVladimir.Kotal@Sun.COM 		i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0);
4760Sstevel@tonic-gate 		break;
4770Sstevel@tonic-gate #endif
4780Sstevel@tonic-gate 	case RSA_SSLV23_PADDING:
4797616SVladimir.Kotal@Sun.COM 		i = RSA_padding_add_SSLv23(buf, num, from, flen);
4800Sstevel@tonic-gate 		break;
4810Sstevel@tonic-gate 	case RSA_NO_PADDING:
4827616SVladimir.Kotal@Sun.COM 		i = RSA_padding_add_none(buf, num, from, flen);
4830Sstevel@tonic-gate 		break;
4840Sstevel@tonic-gate 	default:
4857616SVladimir.Kotal@Sun.COM 		RSAerr(PK11_F_RSA_PUB_ENC, PK11_R_UNKNOWN_PADDING_TYPE);
4860Sstevel@tonic-gate 		goto err;
4870Sstevel@tonic-gate 		}
4880Sstevel@tonic-gate 	if (i <= 0) goto err;
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate 	/* PK11 functions are called here */
4910Sstevel@tonic-gate 	r = pk11_RSA_public_encrypt_low(num, buf, to, rsa);
4920Sstevel@tonic-gate err:
4937616SVladimir.Kotal@Sun.COM 	if (buf != NULL)
4940Sstevel@tonic-gate 		{
4957616SVladimir.Kotal@Sun.COM 		OPENSSL_cleanse(buf, num);
4960Sstevel@tonic-gate 		OPENSSL_free(buf);
4970Sstevel@tonic-gate 		}
4987616SVladimir.Kotal@Sun.COM 	return (r);
4990Sstevel@tonic-gate 	}
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 
5027616SVladimir.Kotal@Sun.COM /*
5037616SVladimir.Kotal@Sun.COM  * Similar to Openssl to take advantage of the paddings. The input errors
5040Sstevel@tonic-gate  * should be catched in the padding functions
5050Sstevel@tonic-gate  */
pk11_RSA_private_encrypt(int flen,const unsigned char * from,unsigned char * to,RSA * rsa,int padding)5060Sstevel@tonic-gate static int pk11_RSA_private_encrypt(int flen, const unsigned char *from,
5077616SVladimir.Kotal@Sun.COM 	unsigned char *to, RSA *rsa, int padding)
5080Sstevel@tonic-gate 	{
5097616SVladimir.Kotal@Sun.COM 	int i, num = 0, r = -1;
5107616SVladimir.Kotal@Sun.COM 	unsigned char *buf = NULL;
5110Sstevel@tonic-gate 
5127616SVladimir.Kotal@Sun.COM 	num = BN_num_bytes(rsa->n);
5137616SVladimir.Kotal@Sun.COM 	if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL)
5140Sstevel@tonic-gate 		{
5157616SVladimir.Kotal@Sun.COM 		RSAerr(PK11_F_RSA_PRIV_ENC, PK11_R_MALLOC_FAILURE);
5160Sstevel@tonic-gate 		goto err;
5170Sstevel@tonic-gate 		}
5180Sstevel@tonic-gate 
5190Sstevel@tonic-gate 	switch (padding)
5200Sstevel@tonic-gate 		{
5210Sstevel@tonic-gate 	case RSA_PKCS1_PADDING:
5227616SVladimir.Kotal@Sun.COM 		i = RSA_padding_add_PKCS1_type_1(buf, num, from, flen);
5230Sstevel@tonic-gate 		break;
5240Sstevel@tonic-gate 	case RSA_NO_PADDING:
5257616SVladimir.Kotal@Sun.COM 		i = RSA_padding_add_none(buf, num, from, flen);
5260Sstevel@tonic-gate 		break;
5270Sstevel@tonic-gate 	case RSA_SSLV23_PADDING:
5280Sstevel@tonic-gate 	default:
5297616SVladimir.Kotal@Sun.COM 		RSAerr(PK11_F_RSA_PRIV_ENC, PK11_R_UNKNOWN_PADDING_TYPE);
5300Sstevel@tonic-gate 		goto err;
5310Sstevel@tonic-gate 		}
5320Sstevel@tonic-gate 	if (i <= 0) goto err;
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 	/* PK11 functions are called here */
5357616SVladimir.Kotal@Sun.COM 	r = pk11_RSA_private_encrypt_low(num, buf, to, rsa);
5360Sstevel@tonic-gate err:
5370Sstevel@tonic-gate 	if (buf != NULL)
5380Sstevel@tonic-gate 		{
5397616SVladimir.Kotal@Sun.COM 		OPENSSL_cleanse(buf, num);
5400Sstevel@tonic-gate 		OPENSSL_free(buf);
5410Sstevel@tonic-gate 		}
5427616SVladimir.Kotal@Sun.COM 	return (r);
5430Sstevel@tonic-gate 	}
5440Sstevel@tonic-gate 
5457616SVladimir.Kotal@Sun.COM /* Similar to OpenSSL code. Input errors are also checked here */
pk11_RSA_private_decrypt(int flen,const unsigned char * from,unsigned char * to,RSA * rsa,int padding)5460Sstevel@tonic-gate static int pk11_RSA_private_decrypt(int flen, const unsigned char *from,
5477616SVladimir.Kotal@Sun.COM 	unsigned char *to, RSA *rsa, int padding)
5480Sstevel@tonic-gate 	{
5490Sstevel@tonic-gate 	BIGNUM f;
5507616SVladimir.Kotal@Sun.COM 	int j, num = 0, r = -1;
5510Sstevel@tonic-gate 	unsigned char *p;
5527616SVladimir.Kotal@Sun.COM 	unsigned char *buf = NULL;
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 	BN_init(&f);
5550Sstevel@tonic-gate 
5567616SVladimir.Kotal@Sun.COM 	num = BN_num_bytes(rsa->n);
5570Sstevel@tonic-gate 
5587616SVladimir.Kotal@Sun.COM 	if ((buf = (unsigned char *)OPENSSL_malloc(num)) == NULL)
5590Sstevel@tonic-gate 		{
5607616SVladimir.Kotal@Sun.COM 		RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_MALLOC_FAILURE);
5610Sstevel@tonic-gate 		goto err;
5620Sstevel@tonic-gate 		}
5630Sstevel@tonic-gate 
5647616SVladimir.Kotal@Sun.COM 	/*
5657616SVladimir.Kotal@Sun.COM 	 * This check was for equality but PGP does evil things
5667616SVladimir.Kotal@Sun.COM 	 * and chops off the top '0' bytes
5677616SVladimir.Kotal@Sun.COM 	 */
5680Sstevel@tonic-gate 	if (flen > num)
5690Sstevel@tonic-gate 		{
5700Sstevel@tonic-gate 		RSAerr(PK11_F_RSA_PRIV_DEC,
5710Sstevel@tonic-gate 			PK11_R_DATA_GREATER_THAN_MOD_LEN);
5720Sstevel@tonic-gate 		goto err;
5730Sstevel@tonic-gate 		}
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 	/* make data into a big number */
5767526SVladimir.Kotal@Sun.COM 	if (BN_bin2bn(from, (int)flen, &f) == NULL)
5777526SVladimir.Kotal@Sun.COM 		goto err;
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate 	if (BN_ucmp(&f, rsa->n) >= 0)
5800Sstevel@tonic-gate 		{
5810Sstevel@tonic-gate 		RSAerr(PK11_F_RSA_PRIV_DEC,
5820Sstevel@tonic-gate 			PK11_R_DATA_TOO_LARGE_FOR_MODULUS);
5830Sstevel@tonic-gate 		goto err;
5840Sstevel@tonic-gate 		}
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate 	/* PK11 functions are called here */
5870Sstevel@tonic-gate 	r = pk11_RSA_private_decrypt_low(flen, from, buf, rsa);
5880Sstevel@tonic-gate 
5897616SVladimir.Kotal@Sun.COM 	/*
5907616SVladimir.Kotal@Sun.COM 	 * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning.
5917616SVladimir.Kotal@Sun.COM 	 * Needs to skip these 0's paddings here.
5927616SVladimir.Kotal@Sun.COM 	 */
5930Sstevel@tonic-gate 	for (j = 0; j < r; j++)
5940Sstevel@tonic-gate 		if (buf[j] != 0)
5950Sstevel@tonic-gate 			break;
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate 	p = buf + j;
5980Sstevel@tonic-gate 	j = r - j;  /* j is only used with no-padding mode */
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate 	switch (padding)
6010Sstevel@tonic-gate 		{
6020Sstevel@tonic-gate 	case RSA_PKCS1_PADDING:
6037616SVladimir.Kotal@Sun.COM 		r = RSA_padding_check_PKCS1_type_2(to, num, p, j, num);
6040Sstevel@tonic-gate 		break;
6050Sstevel@tonic-gate #ifndef OPENSSL_NO_SHA
6060Sstevel@tonic-gate 	case RSA_PKCS1_OAEP_PADDING:
6077616SVladimir.Kotal@Sun.COM 		r = RSA_padding_check_PKCS1_OAEP(to, num, p, j, num, NULL, 0);
6080Sstevel@tonic-gate 		break;
6090Sstevel@tonic-gate #endif
6107616SVladimir.Kotal@Sun.COM 	case RSA_SSLV23_PADDING:
6117616SVladimir.Kotal@Sun.COM 		r = RSA_padding_check_SSLv23(to, num, p, j, num);
6120Sstevel@tonic-gate 		break;
6130Sstevel@tonic-gate 	case RSA_NO_PADDING:
6147616SVladimir.Kotal@Sun.COM 		r = RSA_padding_check_none(to, num, p, j, num);
6150Sstevel@tonic-gate 		break;
6160Sstevel@tonic-gate 	default:
6177616SVladimir.Kotal@Sun.COM 		RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_UNKNOWN_PADDING_TYPE);
6180Sstevel@tonic-gate 		goto err;
6190Sstevel@tonic-gate 		}
6200Sstevel@tonic-gate 	if (r < 0)
6217616SVladimir.Kotal@Sun.COM 		RSAerr(PK11_F_RSA_PRIV_DEC, PK11_R_PADDING_CHECK_FAILED);
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate err:
6240Sstevel@tonic-gate 	BN_clear_free(&f);
6250Sstevel@tonic-gate 	if (buf != NULL)
6260Sstevel@tonic-gate 		{
6277616SVladimir.Kotal@Sun.COM 		OPENSSL_cleanse(buf, num);
6280Sstevel@tonic-gate 		OPENSSL_free(buf);
6290Sstevel@tonic-gate 		}
6307616SVladimir.Kotal@Sun.COM 	return (r);
6310Sstevel@tonic-gate 	}
6320Sstevel@tonic-gate 
6337616SVladimir.Kotal@Sun.COM /* Similar to OpenSSL code. Input errors are also checked here */
pk11_RSA_public_decrypt(int flen,const unsigned char * from,unsigned char * to,RSA * rsa,int padding)6340Sstevel@tonic-gate static int pk11_RSA_public_decrypt(int flen, const unsigned char *from,
6357616SVladimir.Kotal@Sun.COM 	unsigned char *to, RSA *rsa, int padding)
6360Sstevel@tonic-gate 	{
6370Sstevel@tonic-gate 	BIGNUM f;
6387616SVladimir.Kotal@Sun.COM 	int i, num = 0, r = -1;
6390Sstevel@tonic-gate 	unsigned char *p;
6407616SVladimir.Kotal@Sun.COM 	unsigned char *buf = NULL;
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate 	BN_init(&f);
6437616SVladimir.Kotal@Sun.COM 	num = BN_num_bytes(rsa->n);
6447616SVladimir.Kotal@Sun.COM 	buf = (unsigned char *)OPENSSL_malloc(num);
6450Sstevel@tonic-gate 	if (buf == NULL)
6460Sstevel@tonic-gate 		{
6477616SVladimir.Kotal@Sun.COM 		RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_MALLOC_FAILURE);
6480Sstevel@tonic-gate 		goto err;
6490Sstevel@tonic-gate 		}
6500Sstevel@tonic-gate 
6517616SVladimir.Kotal@Sun.COM 	/*
6527616SVladimir.Kotal@Sun.COM 	 * This check was for equality but PGP does evil things
6537616SVladimir.Kotal@Sun.COM 	 * and chops off the top '0' bytes
6547616SVladimir.Kotal@Sun.COM 	 */
6550Sstevel@tonic-gate 	if (flen > num)
6560Sstevel@tonic-gate 		{
6577616SVladimir.Kotal@Sun.COM 		RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_DATA_GREATER_THAN_MOD_LEN);
6580Sstevel@tonic-gate 		goto err;
6590Sstevel@tonic-gate 		}
6600Sstevel@tonic-gate 
6617526SVladimir.Kotal@Sun.COM 	if (BN_bin2bn(from, flen, &f) == NULL)
6627526SVladimir.Kotal@Sun.COM 		goto err;
6630Sstevel@tonic-gate 
6640Sstevel@tonic-gate 	if (BN_ucmp(&f, rsa->n) >= 0)
6650Sstevel@tonic-gate 		{
6660Sstevel@tonic-gate 		RSAerr(PK11_F_RSA_PUB_DEC,
6670Sstevel@tonic-gate 			PK11_R_DATA_TOO_LARGE_FOR_MODULUS);
6680Sstevel@tonic-gate 		goto err;
6690Sstevel@tonic-gate 		}
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate 	/* PK11 functions are called here */
6720Sstevel@tonic-gate 	r = pk11_RSA_public_decrypt_low(flen, from, buf, rsa);
6730Sstevel@tonic-gate 
6747616SVladimir.Kotal@Sun.COM 	/*
6757616SVladimir.Kotal@Sun.COM 	 * PK11 CKM_RSA_X_509 mechanism pads 0's at the beginning.
6767616SVladimir.Kotal@Sun.COM 	 * Needs to skip these 0's here
6777616SVladimir.Kotal@Sun.COM 	 */
6780Sstevel@tonic-gate 	for (i = 0; i < r; i++)
6790Sstevel@tonic-gate 		if (buf[i] != 0)
6800Sstevel@tonic-gate 			break;
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate 	p = buf + i;
6830Sstevel@tonic-gate 	i = r - i;  /* i is only used with no-padding mode */
6840Sstevel@tonic-gate 
6850Sstevel@tonic-gate 	switch (padding)
6860Sstevel@tonic-gate 		{
6870Sstevel@tonic-gate 	case RSA_PKCS1_PADDING:
6887616SVladimir.Kotal@Sun.COM 		r = RSA_padding_check_PKCS1_type_1(to, num, p, i, num);
6890Sstevel@tonic-gate 		break;
6900Sstevel@tonic-gate 	case RSA_NO_PADDING:
6917616SVladimir.Kotal@Sun.COM 		r = RSA_padding_check_none(to, num, p, i, num);
6920Sstevel@tonic-gate 		break;
6930Sstevel@tonic-gate 	default:
6947616SVladimir.Kotal@Sun.COM 		RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_UNKNOWN_PADDING_TYPE);
6950Sstevel@tonic-gate 		goto err;
6960Sstevel@tonic-gate 		}
6970Sstevel@tonic-gate 	if (r < 0)
6987616SVladimir.Kotal@Sun.COM 		RSAerr(PK11_F_RSA_PUB_DEC, PK11_R_PADDING_CHECK_FAILED);
6990Sstevel@tonic-gate 
7000Sstevel@tonic-gate err:
7010Sstevel@tonic-gate 	BN_clear_free(&f);
7020Sstevel@tonic-gate 	if (buf != NULL)
7030Sstevel@tonic-gate 		{
7047616SVladimir.Kotal@Sun.COM 		OPENSSL_cleanse(buf, num);
7050Sstevel@tonic-gate 		OPENSSL_free(buf);
7060Sstevel@tonic-gate 		}
7077616SVladimir.Kotal@Sun.COM 	return (r);
7080Sstevel@tonic-gate 	}
7090Sstevel@tonic-gate 
7107616SVladimir.Kotal@Sun.COM /*
7117616SVladimir.Kotal@Sun.COM  * This function implements RSA public encryption using C_EncryptInit and
7120Sstevel@tonic-gate  * C_Encrypt pk11 interfaces. Note that the CKM_RSA_X_509 is used here.
7130Sstevel@tonic-gate  * The calling function allocated sufficient memory in "to" to store results.
7140Sstevel@tonic-gate  */
pk11_RSA_public_encrypt_low(int flen,const unsigned char * from,unsigned char * to,RSA * rsa)7150Sstevel@tonic-gate static int pk11_RSA_public_encrypt_low(int flen,
7160Sstevel@tonic-gate 	const unsigned char *from, unsigned char *to, RSA *rsa)
7170Sstevel@tonic-gate 	{
7187616SVladimir.Kotal@Sun.COM 	CK_ULONG bytes_encrypted = flen;
7190Sstevel@tonic-gate 	int retval = -1;
7200Sstevel@tonic-gate 	CK_RV rv;
7210Sstevel@tonic-gate 	CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
7220Sstevel@tonic-gate 	CK_MECHANISM *p_mech = &mech_rsa;
7230Sstevel@tonic-gate 	CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
7240Sstevel@tonic-gate 	PK11_SESSION *sp;
7257616SVladimir.Kotal@Sun.COM 
7267526SVladimir.Kotal@Sun.COM 	if ((sp = pk11_get_session(OP_RSA)) == NULL)
7277616SVladimir.Kotal@Sun.COM 		return (-1);
7280Sstevel@tonic-gate 
7296847Svk199839 	(void) check_new_rsa_key_pub(sp, rsa);
7307616SVladimir.Kotal@Sun.COM 
7317526SVladimir.Kotal@Sun.COM 	h_pub_key = sp->opdata_rsa_pub_key;
7320Sstevel@tonic-gate 	if (h_pub_key == CK_INVALID_HANDLE)
7337526SVladimir.Kotal@Sun.COM 		h_pub_key = sp->opdata_rsa_pub_key =
7347526SVladimir.Kotal@Sun.COM 			pk11_get_public_rsa_key(rsa, &sp->opdata_rsa_pub,
7357526SVladimir.Kotal@Sun.COM 			    &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num,
7367526SVladimir.Kotal@Sun.COM 			    sp->session);
7370Sstevel@tonic-gate 
7380Sstevel@tonic-gate 	if (h_pub_key != CK_INVALID_HANDLE)
7390Sstevel@tonic-gate 		{
7407616SVladimir.Kotal@Sun.COM 		rv = pFuncList->C_EncryptInit(sp->session, p_mech,
7410Sstevel@tonic-gate 			h_pub_key);
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate 		if (rv != CKR_OK)
7440Sstevel@tonic-gate 			{
7457616SVladimir.Kotal@Sun.COM 			PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW,
7467211Sjp161948 			    PK11_R_ENCRYPTINIT, rv);
7477526SVladimir.Kotal@Sun.COM 			pk11_return_session(sp, OP_RSA);
7487616SVladimir.Kotal@Sun.COM 			return (-1);
7490Sstevel@tonic-gate 			}
7507616SVladimir.Kotal@Sun.COM 
7517616SVladimir.Kotal@Sun.COM 		rv = pFuncList->C_Encrypt(sp->session,
7520Sstevel@tonic-gate 			(unsigned char *)from, flen, to, &bytes_encrypted);
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate 		if (rv != CKR_OK)
7550Sstevel@tonic-gate 			{
7567616SVladimir.Kotal@Sun.COM 			PK11err_add_data(PK11_F_RSA_PUB_ENC_LOW,
7577616SVladimir.Kotal@Sun.COM 			    PK11_R_ENCRYPT, rv);
7587526SVladimir.Kotal@Sun.COM 			pk11_return_session(sp, OP_RSA);
7597616SVladimir.Kotal@Sun.COM 			return (-1);
7600Sstevel@tonic-gate 			}
7610Sstevel@tonic-gate 		retval = bytes_encrypted;
7620Sstevel@tonic-gate 		}
7637616SVladimir.Kotal@Sun.COM 
7647526SVladimir.Kotal@Sun.COM 	pk11_return_session(sp, OP_RSA);
7657616SVladimir.Kotal@Sun.COM 	return (retval);
7660Sstevel@tonic-gate 	}
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate 
7697616SVladimir.Kotal@Sun.COM /*
7707616SVladimir.Kotal@Sun.COM  * This function implements RSA private encryption using C_SignInit and
7710Sstevel@tonic-gate  * C_Sign pk11 APIs. Note that CKM_RSA_X_509 is used here.
7720Sstevel@tonic-gate  * The calling function allocated sufficient memory in "to" to store results.
7730Sstevel@tonic-gate  */
pk11_RSA_private_encrypt_low(int flen,const unsigned char * from,unsigned char * to,RSA * rsa)7740Sstevel@tonic-gate static int pk11_RSA_private_encrypt_low(int flen,
7750Sstevel@tonic-gate 	const unsigned char *from, unsigned char *to, RSA *rsa)
7760Sstevel@tonic-gate 	{
7777616SVladimir.Kotal@Sun.COM 	CK_ULONG ul_sig_len = flen;
7780Sstevel@tonic-gate 	int retval = -1;
7790Sstevel@tonic-gate 	CK_RV rv;
7800Sstevel@tonic-gate 	CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
7810Sstevel@tonic-gate 	CK_MECHANISM *p_mech = &mech_rsa;
7827616SVladimir.Kotal@Sun.COM 	CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
7830Sstevel@tonic-gate 	PK11_SESSION *sp;
7847616SVladimir.Kotal@Sun.COM 
7857526SVladimir.Kotal@Sun.COM 	if ((sp = pk11_get_session(OP_RSA)) == NULL)
7867616SVladimir.Kotal@Sun.COM 		return (-1);
7877616SVladimir.Kotal@Sun.COM 
7886847Svk199839 	(void) check_new_rsa_key_priv(sp, rsa);
7897616SVladimir.Kotal@Sun.COM 
7907526SVladimir.Kotal@Sun.COM 	h_priv_key = sp->opdata_rsa_priv_key;
7910Sstevel@tonic-gate 	if (h_priv_key == CK_INVALID_HANDLE)
7927526SVladimir.Kotal@Sun.COM 		h_priv_key = sp->opdata_rsa_priv_key =
7937526SVladimir.Kotal@Sun.COM 			pk11_get_private_rsa_key(rsa, &sp->opdata_rsa_priv,
7947526SVladimir.Kotal@Sun.COM 			    &sp->opdata_rsa_d_num, sp->session);
7957616SVladimir.Kotal@Sun.COM 
7960Sstevel@tonic-gate 	if (h_priv_key != CK_INVALID_HANDLE)
7970Sstevel@tonic-gate 		{
7987616SVladimir.Kotal@Sun.COM 		rv = pFuncList->C_SignInit(sp->session, p_mech,
7990Sstevel@tonic-gate 			h_priv_key);
8000Sstevel@tonic-gate 
8010Sstevel@tonic-gate 		if (rv != CKR_OK)
8020Sstevel@tonic-gate 			{
8037211Sjp161948 			PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW,
8047211Sjp161948 			    PK11_R_SIGNINIT, rv);
8057526SVladimir.Kotal@Sun.COM 			pk11_return_session(sp, OP_RSA);
8067616SVladimir.Kotal@Sun.COM 			return (-1);
8070Sstevel@tonic-gate 			}
8087616SVladimir.Kotal@Sun.COM 
8097616SVladimir.Kotal@Sun.COM 		rv = pFuncList->C_Sign(sp->session,
8100Sstevel@tonic-gate 			(unsigned char *)from, flen, to, &ul_sig_len);
8110Sstevel@tonic-gate 
8120Sstevel@tonic-gate 		if (rv != CKR_OK)
8130Sstevel@tonic-gate 			{
8147211Sjp161948 			PK11err_add_data(PK11_F_RSA_PRIV_ENC_LOW, PK11_R_SIGN,
8157211Sjp161948 			    rv);
8167526SVladimir.Kotal@Sun.COM 			pk11_return_session(sp, OP_RSA);
8177616SVladimir.Kotal@Sun.COM 			return (-1);
8180Sstevel@tonic-gate 			}
8190Sstevel@tonic-gate 
8200Sstevel@tonic-gate 		retval = ul_sig_len;
8210Sstevel@tonic-gate 		}
8227616SVladimir.Kotal@Sun.COM 
8237526SVladimir.Kotal@Sun.COM 	pk11_return_session(sp, OP_RSA);
8247616SVladimir.Kotal@Sun.COM 	return (retval);
8250Sstevel@tonic-gate 	}
8260Sstevel@tonic-gate 
8270Sstevel@tonic-gate 
8287616SVladimir.Kotal@Sun.COM /*
8297616SVladimir.Kotal@Sun.COM  * This function implements RSA private decryption using C_DecryptInit and
8300Sstevel@tonic-gate  * C_Decrypt pk11 APIs. Note that CKM_RSA_X_509 mechanism is used here.
8310Sstevel@tonic-gate  * The calling function allocated sufficient memory in "to" to store results.
8320Sstevel@tonic-gate  */
pk11_RSA_private_decrypt_low(int flen,const unsigned char * from,unsigned char * to,RSA * rsa)8330Sstevel@tonic-gate static int pk11_RSA_private_decrypt_low(int flen,
8340Sstevel@tonic-gate 	const unsigned char *from, unsigned char *to, RSA *rsa)
8350Sstevel@tonic-gate 	{
8360Sstevel@tonic-gate 	CK_ULONG bytes_decrypted = flen;
8370Sstevel@tonic-gate 	int retval = -1;
8380Sstevel@tonic-gate 	CK_RV rv;
8390Sstevel@tonic-gate 	CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
8400Sstevel@tonic-gate 	CK_MECHANISM *p_mech = &mech_rsa;
8410Sstevel@tonic-gate 	CK_OBJECT_HANDLE h_priv_key;
8420Sstevel@tonic-gate 	PK11_SESSION *sp;
8437616SVladimir.Kotal@Sun.COM 
8447526SVladimir.Kotal@Sun.COM 	if ((sp = pk11_get_session(OP_RSA)) == NULL)
8457616SVladimir.Kotal@Sun.COM 		return (-1);
8467616SVladimir.Kotal@Sun.COM 
8476847Svk199839 	(void) check_new_rsa_key_priv(sp, rsa);
8487616SVladimir.Kotal@Sun.COM 
8497526SVladimir.Kotal@Sun.COM 	h_priv_key = sp->opdata_rsa_priv_key;
8500Sstevel@tonic-gate 	if (h_priv_key == CK_INVALID_HANDLE)
8517526SVladimir.Kotal@Sun.COM 		h_priv_key = sp->opdata_rsa_priv_key =
8527526SVladimir.Kotal@Sun.COM 			pk11_get_private_rsa_key(rsa, &sp->opdata_rsa_priv,
8537526SVladimir.Kotal@Sun.COM 			    &sp->opdata_rsa_d_num, sp->session);
8540Sstevel@tonic-gate 
8550Sstevel@tonic-gate 	if (h_priv_key != CK_INVALID_HANDLE)
8560Sstevel@tonic-gate 		{
8577616SVladimir.Kotal@Sun.COM 		rv = pFuncList->C_DecryptInit(sp->session, p_mech,
8580Sstevel@tonic-gate 			h_priv_key);
8590Sstevel@tonic-gate 
8600Sstevel@tonic-gate 		if (rv != CKR_OK)
8610Sstevel@tonic-gate 			{
8627616SVladimir.Kotal@Sun.COM 			PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW,
8637211Sjp161948 				PK11_R_DECRYPTINIT, rv);
8647526SVladimir.Kotal@Sun.COM 			pk11_return_session(sp, OP_RSA);
8657616SVladimir.Kotal@Sun.COM 			return (-1);
8660Sstevel@tonic-gate 			}
8677616SVladimir.Kotal@Sun.COM 
8687616SVladimir.Kotal@Sun.COM 		rv = pFuncList->C_Decrypt(sp->session,
8690Sstevel@tonic-gate 			(unsigned char *)from, flen, to, &bytes_decrypted);
8700Sstevel@tonic-gate 
8710Sstevel@tonic-gate 		if (rv != CKR_OK)
8720Sstevel@tonic-gate 			{
8737211Sjp161948 			PK11err_add_data(PK11_F_RSA_PRIV_DEC_LOW,
8747211Sjp161948 			    PK11_R_DECRYPT, rv);
8757526SVladimir.Kotal@Sun.COM 			pk11_return_session(sp, OP_RSA);
8767616SVladimir.Kotal@Sun.COM 			return (-1);
8770Sstevel@tonic-gate 			}
8780Sstevel@tonic-gate 		retval = bytes_decrypted;
8790Sstevel@tonic-gate 		}
8800Sstevel@tonic-gate 
8817526SVladimir.Kotal@Sun.COM 	pk11_return_session(sp, OP_RSA);
8827616SVladimir.Kotal@Sun.COM 	return (retval);
8830Sstevel@tonic-gate 	}
8840Sstevel@tonic-gate 
8850Sstevel@tonic-gate 
8867616SVladimir.Kotal@Sun.COM /*
8877616SVladimir.Kotal@Sun.COM  * This function implements RSA public decryption using C_VerifyRecoverInit
8880Sstevel@tonic-gate  * and C_VerifyRecover pk11 APIs. Note that CKM_RSA_X_509 is used here.
8890Sstevel@tonic-gate  * The calling function allocated sufficient memory in "to" to store results.
8900Sstevel@tonic-gate  */
pk11_RSA_public_decrypt_low(int flen,const unsigned char * from,unsigned char * to,RSA * rsa)8910Sstevel@tonic-gate static int pk11_RSA_public_decrypt_low(int flen,
8920Sstevel@tonic-gate 	const unsigned char *from, unsigned char *to, RSA *rsa)
8930Sstevel@tonic-gate 	{
8940Sstevel@tonic-gate 	CK_ULONG bytes_decrypted = flen;
8950Sstevel@tonic-gate 	int retval = -1;
8960Sstevel@tonic-gate 	CK_RV rv;
8970Sstevel@tonic-gate 	CK_MECHANISM mech_rsa = {CKM_RSA_X_509, NULL, 0};
8980Sstevel@tonic-gate 	CK_MECHANISM *p_mech = &mech_rsa;
8990Sstevel@tonic-gate 	CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
9000Sstevel@tonic-gate 	PK11_SESSION *sp;
9017616SVladimir.Kotal@Sun.COM 
9027526SVladimir.Kotal@Sun.COM 	if ((sp = pk11_get_session(OP_RSA)) == NULL)
9037616SVladimir.Kotal@Sun.COM 		return (-1);
9047616SVladimir.Kotal@Sun.COM 
9056847Svk199839 	(void) check_new_rsa_key_pub(sp, rsa);
9067616SVladimir.Kotal@Sun.COM 
9077526SVladimir.Kotal@Sun.COM 	h_pub_key = sp->opdata_rsa_pub_key;
9080Sstevel@tonic-gate 	if (h_pub_key == CK_INVALID_HANDLE)
9097526SVladimir.Kotal@Sun.COM 		h_pub_key = sp->opdata_rsa_pub_key =
9107526SVladimir.Kotal@Sun.COM 			pk11_get_public_rsa_key(rsa, &sp->opdata_rsa_pub,
9117526SVladimir.Kotal@Sun.COM 			    &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num,
9127526SVladimir.Kotal@Sun.COM 			    sp->session);
9130Sstevel@tonic-gate 
9140Sstevel@tonic-gate 	if (h_pub_key != CK_INVALID_HANDLE)
9157616SVladimir.Kotal@Sun.COM 		{
9167616SVladimir.Kotal@Sun.COM 		rv = pFuncList->C_VerifyRecoverInit(sp->session,
9170Sstevel@tonic-gate 			p_mech, h_pub_key);
9180Sstevel@tonic-gate 
9190Sstevel@tonic-gate 		if (rv != CKR_OK)
9200Sstevel@tonic-gate 			{
9217616SVladimir.Kotal@Sun.COM 			PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW,
9227211Sjp161948 				PK11_R_VERIFYRECOVERINIT, rv);
9237526SVladimir.Kotal@Sun.COM 			pk11_return_session(sp, OP_RSA);
9247616SVladimir.Kotal@Sun.COM 			return (-1);
9250Sstevel@tonic-gate 			}
9267616SVladimir.Kotal@Sun.COM 
9277616SVladimir.Kotal@Sun.COM 		rv = pFuncList->C_VerifyRecover(sp->session,
9280Sstevel@tonic-gate 			(unsigned char *)from, flen, to, &bytes_decrypted);
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate 		if (rv != CKR_OK)
9310Sstevel@tonic-gate 			{
9327616SVladimir.Kotal@Sun.COM 			PK11err_add_data(PK11_F_RSA_PUB_DEC_LOW,
9337211Sjp161948 			    PK11_R_VERIFYRECOVER, rv);
9347526SVladimir.Kotal@Sun.COM 			pk11_return_session(sp, OP_RSA);
9357616SVladimir.Kotal@Sun.COM 			return (-1);
9360Sstevel@tonic-gate 			}
9370Sstevel@tonic-gate 		retval = bytes_decrypted;
9380Sstevel@tonic-gate 		}
9390Sstevel@tonic-gate 
9407526SVladimir.Kotal@Sun.COM 	pk11_return_session(sp, OP_RSA);
9417616SVladimir.Kotal@Sun.COM 	return (retval);
9420Sstevel@tonic-gate 	}
9430Sstevel@tonic-gate 
pk11_RSA_init(RSA * rsa)9440Sstevel@tonic-gate static int pk11_RSA_init(RSA *rsa)
9450Sstevel@tonic-gate 	{
9467616SVladimir.Kotal@Sun.COM 	/*
9477616SVladimir.Kotal@Sun.COM 	 * This flag in the RSA_METHOD enables the new rsa_sign,
9487616SVladimir.Kotal@Sun.COM 	 * rsa_verify functions. See rsa.h for details.
9497616SVladimir.Kotal@Sun.COM 	 */
9500Sstevel@tonic-gate 	rsa->flags |= RSA_FLAG_SIGN_VER;
9510Sstevel@tonic-gate 
9527616SVladimir.Kotal@Sun.COM 	return (1);
9530Sstevel@tonic-gate 	}
9540Sstevel@tonic-gate 
pk11_RSA_finish(RSA * rsa)9550Sstevel@tonic-gate static int pk11_RSA_finish(RSA *rsa)
9560Sstevel@tonic-gate 	{
9576847Svk199839 	/*
9586847Svk199839 	 * Since we are overloading OpenSSL's native RSA_eay_finish() we need
9596847Svk199839 	 * to do the same as in the original function, i.e. to free bignum
9606847Svk199839 	 * structures.
9616847Svk199839 	 */
9620Sstevel@tonic-gate 	if (rsa->_method_mod_n != NULL)
9630Sstevel@tonic-gate 		BN_MONT_CTX_free(rsa->_method_mod_n);
9640Sstevel@tonic-gate 	if (rsa->_method_mod_p != NULL)
9650Sstevel@tonic-gate 		BN_MONT_CTX_free(rsa->_method_mod_p);
9660Sstevel@tonic-gate 	if (rsa->_method_mod_q != NULL)
9670Sstevel@tonic-gate 		BN_MONT_CTX_free(rsa->_method_mod_q);
9686847Svk199839 
9696847Svk199839 	return (1);
9700Sstevel@tonic-gate 	}
9710Sstevel@tonic-gate 
9727616SVladimir.Kotal@Sun.COM /*
9737616SVladimir.Kotal@Sun.COM  * Standard engine interface function. Majority codes here are from
9740Sstevel@tonic-gate  * rsa/rsa_sign.c. We replaced the decrypt function call by C_Sign of PKCS#11.
9757616SVladimir.Kotal@Sun.COM  * See more details in rsa/rsa_sign.c
9767616SVladimir.Kotal@Sun.COM  */
pk11_RSA_sign(int type,const unsigned char * m,unsigned int m_len,unsigned char * sigret,unsigned int * siglen,const RSA * rsa)9770Sstevel@tonic-gate static int pk11_RSA_sign(int type, const unsigned char *m, unsigned int m_len,
9780Sstevel@tonic-gate 	unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
9790Sstevel@tonic-gate 	{
9800Sstevel@tonic-gate 	X509_SIG sig;
9810Sstevel@tonic-gate 	ASN1_TYPE parameter;
9827616SVladimir.Kotal@Sun.COM 	int i, j;
9837616SVladimir.Kotal@Sun.COM 	unsigned char *p, *s = NULL;
9840Sstevel@tonic-gate 	X509_ALGOR algor;
9850Sstevel@tonic-gate 	ASN1_OCTET_STRING digest;
9860Sstevel@tonic-gate 	CK_RV rv;
9870Sstevel@tonic-gate 	CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0};
9880Sstevel@tonic-gate 	CK_MECHANISM *p_mech = &mech_rsa;
9890Sstevel@tonic-gate 	CK_OBJECT_HANDLE h_priv_key;
9900Sstevel@tonic-gate 	PK11_SESSION *sp = NULL;
9910Sstevel@tonic-gate 	int ret = 0;
9922378Sjp161948 	unsigned long ulsiglen;
9930Sstevel@tonic-gate 
9940Sstevel@tonic-gate 	/* Encode the digest */
9950Sstevel@tonic-gate 	/* Special case: SSL signature, just check the length */
9960Sstevel@tonic-gate 	if (type == NID_md5_sha1)
9970Sstevel@tonic-gate 		{
9980Sstevel@tonic-gate 		if (m_len != SSL_SIG_LENGTH)
9990Sstevel@tonic-gate 			{
10007616SVladimir.Kotal@Sun.COM 			PK11err(PK11_F_RSA_SIGN,
10010Sstevel@tonic-gate 				PK11_R_INVALID_MESSAGE_LENGTH);
10020Sstevel@tonic-gate 			goto err;
10030Sstevel@tonic-gate 			}
10040Sstevel@tonic-gate 		i = SSL_SIG_LENGTH;
10050Sstevel@tonic-gate 		s = (unsigned char *)m;
10060Sstevel@tonic-gate 		}
10070Sstevel@tonic-gate 	else
10080Sstevel@tonic-gate 		{
10097616SVladimir.Kotal@Sun.COM 		sig.algor = &algor;
10107616SVladimir.Kotal@Sun.COM 		sig.algor->algorithm = OBJ_nid2obj(type);
10110Sstevel@tonic-gate 		if (sig.algor->algorithm == NULL)
10120Sstevel@tonic-gate 			{
10137616SVladimir.Kotal@Sun.COM 			PK11err(PK11_F_RSA_SIGN,
10140Sstevel@tonic-gate 				PK11_R_UNKNOWN_ALGORITHM_TYPE);
10150Sstevel@tonic-gate 			goto err;
10160Sstevel@tonic-gate 			}
10170Sstevel@tonic-gate 		if (sig.algor->algorithm->length == 0)
10180Sstevel@tonic-gate 			{
10197616SVladimir.Kotal@Sun.COM 			PK11err(PK11_F_RSA_SIGN,
10200Sstevel@tonic-gate 				PK11_R_UNKNOWN_ASN1_OBJECT_ID);
10210Sstevel@tonic-gate 			goto err;
10220Sstevel@tonic-gate 			}
10237616SVladimir.Kotal@Sun.COM 		parameter.type = V_ASN1_NULL;
10247616SVladimir.Kotal@Sun.COM 		parameter.value.ptr = NULL;
10257616SVladimir.Kotal@Sun.COM 		sig.algor->parameter = &parameter;
10267616SVladimir.Kotal@Sun.COM 
10277616SVladimir.Kotal@Sun.COM 		sig.digest = &digest;
10287616SVladimir.Kotal@Sun.COM 		sig.digest->data = (unsigned char *)m;
10297616SVladimir.Kotal@Sun.COM 		sig.digest->length = m_len;
10307616SVladimir.Kotal@Sun.COM 
10317616SVladimir.Kotal@Sun.COM 		i = i2d_X509_SIG(&sig, NULL);
10320Sstevel@tonic-gate 		}
10337616SVladimir.Kotal@Sun.COM 
10347616SVladimir.Kotal@Sun.COM 	j = RSA_size(rsa);
10357628SVladimir.Kotal@Sun.COM 	if ((i - RSA_PKCS1_PADDING) > j)
10360Sstevel@tonic-gate 		{
10370Sstevel@tonic-gate 		PK11err(PK11_F_RSA_SIGN, PK11_R_DIGEST_TOO_BIG);
10380Sstevel@tonic-gate 		goto err;
10390Sstevel@tonic-gate 		}
10407616SVladimir.Kotal@Sun.COM 
10410Sstevel@tonic-gate 	if (type != NID_md5_sha1)
10420Sstevel@tonic-gate 		{
10437616SVladimir.Kotal@Sun.COM 		s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1));
10440Sstevel@tonic-gate 		if (s == NULL)
10450Sstevel@tonic-gate 			{
10460Sstevel@tonic-gate 			PK11err(PK11_F_RSA_SIGN, PK11_R_MALLOC_FAILURE);
10470Sstevel@tonic-gate 			goto err;
10480Sstevel@tonic-gate 			}
10497616SVladimir.Kotal@Sun.COM 		p = s;
10507526SVladimir.Kotal@Sun.COM 		(void) i2d_X509_SIG(&sig, &p);
10510Sstevel@tonic-gate 		}
10527616SVladimir.Kotal@Sun.COM 
10537526SVladimir.Kotal@Sun.COM 	if ((sp = pk11_get_session(OP_RSA)) == NULL)
10540Sstevel@tonic-gate 		goto err;
10550Sstevel@tonic-gate 
10566847Svk199839 	(void) check_new_rsa_key_priv(sp, rsa);
10577616SVladimir.Kotal@Sun.COM 
10587526SVladimir.Kotal@Sun.COM 	h_priv_key = sp->opdata_rsa_priv_key;
10590Sstevel@tonic-gate 	if (h_priv_key == CK_INVALID_HANDLE)
10607526SVladimir.Kotal@Sun.COM 		h_priv_key = sp->opdata_rsa_priv_key =
10617526SVladimir.Kotal@Sun.COM 			pk11_get_private_rsa_key((RSA *)rsa,
10627526SVladimir.Kotal@Sun.COM 			    &sp->opdata_rsa_priv,
10637526SVladimir.Kotal@Sun.COM 			    &sp->opdata_rsa_d_num, sp->session);
10640Sstevel@tonic-gate 
10650Sstevel@tonic-gate 	if (h_priv_key != CK_INVALID_HANDLE)
10660Sstevel@tonic-gate 		{
10670Sstevel@tonic-gate 		rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key);
10680Sstevel@tonic-gate 
10690Sstevel@tonic-gate 		if (rv != CKR_OK)
10700Sstevel@tonic-gate 			{
10717211Sjp161948 			PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGNINIT, rv);
10720Sstevel@tonic-gate 			goto err;
10730Sstevel@tonic-gate 			}
10740Sstevel@tonic-gate 
10752378Sjp161948 		ulsiglen = j;
10767616SVladimir.Kotal@Sun.COM 		rv = pFuncList->C_Sign(sp->session, s, i, sigret,
10772378Sjp161948 			(CK_ULONG_PTR) &ulsiglen);
10782378Sjp161948 		*siglen = ulsiglen;
10790Sstevel@tonic-gate 
10800Sstevel@tonic-gate 		if (rv != CKR_OK)
10810Sstevel@tonic-gate 			{
10827211Sjp161948 			PK11err_add_data(PK11_F_RSA_SIGN, PK11_R_SIGN, rv);
10830Sstevel@tonic-gate 			goto err;
10840Sstevel@tonic-gate 			}
10850Sstevel@tonic-gate 		ret = 1;
10860Sstevel@tonic-gate 		}
10870Sstevel@tonic-gate 
10880Sstevel@tonic-gate err:
10890Sstevel@tonic-gate 	if (type != NID_md5_sha1)
10900Sstevel@tonic-gate 		{
10917616SVladimir.Kotal@Sun.COM 		(void) memset(s, 0, (unsigned int)(j + 1));
10920Sstevel@tonic-gate 		OPENSSL_free(s);
10930Sstevel@tonic-gate 		}
10947616SVladimir.Kotal@Sun.COM 
10957526SVladimir.Kotal@Sun.COM 	pk11_return_session(sp, OP_RSA);
10967616SVladimir.Kotal@Sun.COM 	return (ret);
10970Sstevel@tonic-gate 	}
10980Sstevel@tonic-gate 
pk11_RSA_verify(int type,const unsigned char * m,unsigned int m_len,unsigned char * sigbuf,unsigned int siglen,const RSA * rsa)10990Sstevel@tonic-gate static int pk11_RSA_verify(int type, const unsigned char *m,
11000Sstevel@tonic-gate 	unsigned int m_len, unsigned char *sigbuf, unsigned int siglen,
11010Sstevel@tonic-gate 	const RSA *rsa)
11020Sstevel@tonic-gate 	{
11030Sstevel@tonic-gate 	X509_SIG sig;
11040Sstevel@tonic-gate 	ASN1_TYPE parameter;
11057616SVladimir.Kotal@Sun.COM 	int i, j;
11067616SVladimir.Kotal@Sun.COM 	unsigned char *p, *s = NULL;
11070Sstevel@tonic-gate 	X509_ALGOR algor;
11080Sstevel@tonic-gate 	ASN1_OCTET_STRING digest;
11090Sstevel@tonic-gate 	CK_RV rv;
11100Sstevel@tonic-gate 	CK_MECHANISM mech_rsa = {CKM_RSA_PKCS, NULL, 0};
11110Sstevel@tonic-gate 	CK_MECHANISM *p_mech = &mech_rsa;
11120Sstevel@tonic-gate 	CK_OBJECT_HANDLE h_pub_key;
11130Sstevel@tonic-gate 	PK11_SESSION *sp = NULL;
11140Sstevel@tonic-gate 	int ret = 0;
11150Sstevel@tonic-gate 
11160Sstevel@tonic-gate 	/* Encode the digest	*/
11170Sstevel@tonic-gate 	/* Special case: SSL signature, just check the length */
11180Sstevel@tonic-gate 	if (type == NID_md5_sha1)
11190Sstevel@tonic-gate 		{
11200Sstevel@tonic-gate 		if (m_len != SSL_SIG_LENGTH)
11210Sstevel@tonic-gate 			{
11227616SVladimir.Kotal@Sun.COM 			PK11err(PK11_F_RSA_VERIFY,
11230Sstevel@tonic-gate 				PK11_R_INVALID_MESSAGE_LENGTH);
11240Sstevel@tonic-gate 			goto err;
11250Sstevel@tonic-gate 			}
11260Sstevel@tonic-gate 		i = SSL_SIG_LENGTH;
11270Sstevel@tonic-gate 		s = (unsigned char *)m;
11280Sstevel@tonic-gate 		}
11290Sstevel@tonic-gate 	else
11300Sstevel@tonic-gate 		{
11317616SVladimir.Kotal@Sun.COM 		sig.algor = &algor;
11327616SVladimir.Kotal@Sun.COM 		sig.algor->algorithm = OBJ_nid2obj(type);
11330Sstevel@tonic-gate 		if (sig.algor->algorithm == NULL)
11340Sstevel@tonic-gate 			{
11357616SVladimir.Kotal@Sun.COM 			PK11err(PK11_F_RSA_VERIFY,
11360Sstevel@tonic-gate 				PK11_R_UNKNOWN_ALGORITHM_TYPE);
11370Sstevel@tonic-gate 			goto err;
11380Sstevel@tonic-gate 			}
11390Sstevel@tonic-gate 		if (sig.algor->algorithm->length == 0)
11400Sstevel@tonic-gate 			{
11417616SVladimir.Kotal@Sun.COM 			PK11err(PK11_F_RSA_VERIFY,
11420Sstevel@tonic-gate 				PK11_R_UNKNOWN_ASN1_OBJECT_ID);
11430Sstevel@tonic-gate 			goto err;
11440Sstevel@tonic-gate 			}
11457616SVladimir.Kotal@Sun.COM 		parameter.type = V_ASN1_NULL;
11467616SVladimir.Kotal@Sun.COM 		parameter.value.ptr = NULL;
11477616SVladimir.Kotal@Sun.COM 		sig.algor->parameter = &parameter;
11487616SVladimir.Kotal@Sun.COM 		sig.digest = &digest;
11497616SVladimir.Kotal@Sun.COM 		sig.digest->data = (unsigned char *)m;
11507616SVladimir.Kotal@Sun.COM 		sig.digest->length = m_len;
11517616SVladimir.Kotal@Sun.COM 		i = i2d_X509_SIG(&sig, NULL);
11520Sstevel@tonic-gate 		}
11537616SVladimir.Kotal@Sun.COM 
11547616SVladimir.Kotal@Sun.COM 	j = RSA_size(rsa);
11557628SVladimir.Kotal@Sun.COM 	if ((i - RSA_PKCS1_PADDING) > j)
11560Sstevel@tonic-gate 		{
11570Sstevel@tonic-gate 		PK11err(PK11_F_RSA_VERIFY, PK11_R_DIGEST_TOO_BIG);
11580Sstevel@tonic-gate 		goto err;
11590Sstevel@tonic-gate 		}
11607616SVladimir.Kotal@Sun.COM 
11610Sstevel@tonic-gate 	if (type != NID_md5_sha1)
11620Sstevel@tonic-gate 		{
11637616SVladimir.Kotal@Sun.COM 		s = (unsigned char *)OPENSSL_malloc((unsigned int)(j + 1));
11640Sstevel@tonic-gate 		if (s == NULL)
11650Sstevel@tonic-gate 			{
11660Sstevel@tonic-gate 			PK11err(PK11_F_RSA_VERIFY, PK11_R_MALLOC_FAILURE);
11670Sstevel@tonic-gate 			goto err;
11680Sstevel@tonic-gate 			}
11697616SVladimir.Kotal@Sun.COM 		p = s;
11707628SVladimir.Kotal@Sun.COM 		(void) i2d_X509_SIG(&sig, &p);
11710Sstevel@tonic-gate 		}
11727616SVladimir.Kotal@Sun.COM 
11737526SVladimir.Kotal@Sun.COM 	if ((sp = pk11_get_session(OP_RSA)) == NULL)
11740Sstevel@tonic-gate 		goto err;
11757616SVladimir.Kotal@Sun.COM 
11766847Svk199839 	(void) check_new_rsa_key_pub(sp, rsa);
11777616SVladimir.Kotal@Sun.COM 
11787526SVladimir.Kotal@Sun.COM 	h_pub_key = sp->opdata_rsa_pub_key;
11790Sstevel@tonic-gate 	if (h_pub_key == CK_INVALID_HANDLE)
11807526SVladimir.Kotal@Sun.COM 		h_pub_key = sp->opdata_rsa_pub_key =
11817526SVladimir.Kotal@Sun.COM 			pk11_get_public_rsa_key((RSA *)rsa, &sp->opdata_rsa_pub,
11827526SVladimir.Kotal@Sun.COM 			    &sp->opdata_rsa_n_num, &sp->opdata_rsa_e_num,
11837526SVladimir.Kotal@Sun.COM 			    sp->session);
11840Sstevel@tonic-gate 
11850Sstevel@tonic-gate 	if (h_pub_key != CK_INVALID_HANDLE)
11860Sstevel@tonic-gate 		{
11877616SVladimir.Kotal@Sun.COM 		rv = pFuncList->C_VerifyInit(sp->session, p_mech,
11880Sstevel@tonic-gate 			h_pub_key);
11890Sstevel@tonic-gate 
11900Sstevel@tonic-gate 		if (rv != CKR_OK)
11910Sstevel@tonic-gate 			{
11927211Sjp161948 			PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFYINIT,
11937211Sjp161948 			    rv);
11940Sstevel@tonic-gate 			goto err;
11950Sstevel@tonic-gate 			}
11967616SVladimir.Kotal@Sun.COM 		rv = pFuncList->C_Verify(sp->session, s, i, sigbuf,
11970Sstevel@tonic-gate 			(CK_ULONG)siglen);
11980Sstevel@tonic-gate 
11990Sstevel@tonic-gate 		if (rv != CKR_OK)
12000Sstevel@tonic-gate 			{
12017211Sjp161948 			PK11err_add_data(PK11_F_RSA_VERIFY, PK11_R_VERIFY, rv);
12020Sstevel@tonic-gate 			goto err;
12030Sstevel@tonic-gate 			}
12040Sstevel@tonic-gate 		ret = 1;
12050Sstevel@tonic-gate 		}
12060Sstevel@tonic-gate 
12070Sstevel@tonic-gate err:
12080Sstevel@tonic-gate 	if (type != NID_md5_sha1)
12090Sstevel@tonic-gate 		{
12107616SVladimir.Kotal@Sun.COM 		(void) memset(s, 0, (unsigned int)siglen);
12110Sstevel@tonic-gate 		OPENSSL_free(s);
12120Sstevel@tonic-gate 		}
12130Sstevel@tonic-gate 
12147526SVladimir.Kotal@Sun.COM 	pk11_return_session(sp, OP_RSA);
12157616SVladimir.Kotal@Sun.COM 	return (ret);
12160Sstevel@tonic-gate 	}
12170Sstevel@tonic-gate 
12186847Svk199839 /* load RSA private key from a file */
12197534SVladimir.Kotal@Sun.COM /* ARGSUSED */
pk11_load_privkey(ENGINE * e,const char * privkey_file,UI_METHOD * ui_method,void * callback_data)12207616SVladimir.Kotal@Sun.COM EVP_PKEY *pk11_load_privkey(ENGINE* e, const char *privkey_file,
12210Sstevel@tonic-gate 	UI_METHOD *ui_method, void *callback_data)
12220Sstevel@tonic-gate 	{
12237616SVladimir.Kotal@Sun.COM 	EVP_PKEY *pkey = NULL;
12240Sstevel@tonic-gate 	FILE *pubkey;
12250Sstevel@tonic-gate 	CK_OBJECT_HANDLE  h_priv_key = CK_INVALID_HANDLE;
12260Sstevel@tonic-gate 	RSA *rsa;
12270Sstevel@tonic-gate 	PK11_SESSION *sp;
12280Sstevel@tonic-gate 
12297526SVladimir.Kotal@Sun.COM 	if ((sp = pk11_get_session(OP_RSA)) == NULL)
12307616SVladimir.Kotal@Sun.COM 		return (NULL);
12310Sstevel@tonic-gate 
12327628SVladimir.Kotal@Sun.COM 	if ((pubkey = fopen(privkey_file, read_mode_flags)) != NULL)
12330Sstevel@tonic-gate 		{
12346847Svk199839 		pkey = PEM_read_PrivateKey(pubkey, NULL, NULL, NULL);
12357534SVladimir.Kotal@Sun.COM 		(void) fclose(pubkey);
12366847Svk199839 		if (pkey != NULL)
12370Sstevel@tonic-gate 			{
12380Sstevel@tonic-gate 			rsa = EVP_PKEY_get1_RSA(pkey);
12396847Svk199839 			if (rsa != NULL)
12400Sstevel@tonic-gate 				{
12416847Svk199839 				(void) check_new_rsa_key_priv(sp, rsa);
12427616SVladimir.Kotal@Sun.COM 
12437526SVladimir.Kotal@Sun.COM 				h_priv_key = sp->opdata_rsa_priv_key =
12446847Svk199839 				    pk11_get_private_rsa_key(rsa,
12457526SVladimir.Kotal@Sun.COM 				    &sp->opdata_rsa_priv, &sp->opdata_rsa_d_num,
12467526SVladimir.Kotal@Sun.COM 				    sp->session);
12470Sstevel@tonic-gate 				if (h_priv_key == CK_INVALID_HANDLE)
12480Sstevel@tonic-gate 					{
12490Sstevel@tonic-gate 					EVP_PKEY_free(pkey);
12500Sstevel@tonic-gate 					pkey = NULL;
12510Sstevel@tonic-gate 					}
12520Sstevel@tonic-gate 				}
12530Sstevel@tonic-gate 			else
12540Sstevel@tonic-gate 				{
12550Sstevel@tonic-gate 				EVP_PKEY_free(pkey);
12560Sstevel@tonic-gate 				pkey = NULL;
12570Sstevel@tonic-gate 				}
12580Sstevel@tonic-gate 			}
12590Sstevel@tonic-gate 		}
12600Sstevel@tonic-gate 
12617526SVladimir.Kotal@Sun.COM 	pk11_return_session(sp, OP_RSA);
12627616SVladimir.Kotal@Sun.COM 	return (pkey);
12630Sstevel@tonic-gate 	}
12640Sstevel@tonic-gate 
12656847Svk199839 /* load RSA public key from a file */
12667534SVladimir.Kotal@Sun.COM /* ARGSUSED */
pk11_load_pubkey(ENGINE * e,const char * pubkey_file,UI_METHOD * ui_method,void * callback_data)12677616SVladimir.Kotal@Sun.COM EVP_PKEY *pk11_load_pubkey(ENGINE* e, const char *pubkey_file,
12680Sstevel@tonic-gate 	UI_METHOD *ui_method, void *callback_data)
12690Sstevel@tonic-gate 	{
12707616SVladimir.Kotal@Sun.COM 	EVP_PKEY *pkey = NULL;
12710Sstevel@tonic-gate 	FILE *pubkey;
12720Sstevel@tonic-gate 	CK_OBJECT_HANDLE  h_pub_key = CK_INVALID_HANDLE;
12730Sstevel@tonic-gate 	RSA *rsa;
12740Sstevel@tonic-gate 	PK11_SESSION *sp;
12750Sstevel@tonic-gate 
12767526SVladimir.Kotal@Sun.COM 	if ((sp = pk11_get_session(OP_RSA)) == NULL)
12777616SVladimir.Kotal@Sun.COM 		return (NULL);
12780Sstevel@tonic-gate 
12797628SVladimir.Kotal@Sun.COM 	if ((pubkey = fopen(pubkey_file, read_mode_flags)) != NULL)
12800Sstevel@tonic-gate 		{
12810Sstevel@tonic-gate 		pkey = PEM_read_PUBKEY(pubkey, NULL, NULL, NULL);
12827534SVladimir.Kotal@Sun.COM 		(void) fclose(pubkey);
12836847Svk199839 		if (pkey != NULL)
12840Sstevel@tonic-gate 			{
12850Sstevel@tonic-gate 			rsa = EVP_PKEY_get1_RSA(pkey);
12866847Svk199839 			if (rsa != NULL)
12870Sstevel@tonic-gate 				{
12886847Svk199839 				(void) check_new_rsa_key_pub(sp, rsa);
12897616SVladimir.Kotal@Sun.COM 
12907526SVladimir.Kotal@Sun.COM 				h_pub_key = sp->opdata_rsa_pub_key =
12916847Svk199839 				    pk11_get_public_rsa_key(rsa,
12927526SVladimir.Kotal@Sun.COM 				    &sp->opdata_rsa_pub, &sp->opdata_rsa_n_num,
12937526SVladimir.Kotal@Sun.COM 				    &sp->opdata_rsa_e_num, sp->session);
12940Sstevel@tonic-gate 				if (h_pub_key == CK_INVALID_HANDLE)
12950Sstevel@tonic-gate 					{
12960Sstevel@tonic-gate 					EVP_PKEY_free(pkey);
12970Sstevel@tonic-gate 					pkey = NULL;
12980Sstevel@tonic-gate 					}
12990Sstevel@tonic-gate 				}
13000Sstevel@tonic-gate 			else
13010Sstevel@tonic-gate 				{
13020Sstevel@tonic-gate 				EVP_PKEY_free(pkey);
13030Sstevel@tonic-gate 				pkey = NULL;
13040Sstevel@tonic-gate 				}
13050Sstevel@tonic-gate 			}
13060Sstevel@tonic-gate 		}
13070Sstevel@tonic-gate 
13087526SVladimir.Kotal@Sun.COM 	pk11_return_session(sp, OP_RSA);
13097616SVladimir.Kotal@Sun.COM 	return (pkey);
13100Sstevel@tonic-gate 	}
13110Sstevel@tonic-gate 
13127526SVladimir.Kotal@Sun.COM /*
13137526SVladimir.Kotal@Sun.COM  * Create a public key object in a session from a given rsa structure.
13147526SVladimir.Kotal@Sun.COM  * The *rsa_n_num and *rsa_e_num pointers are non-NULL for RSA public keys.
13150Sstevel@tonic-gate  */
pk11_get_public_rsa_key(RSA * rsa,RSA ** key_ptr,BIGNUM ** rsa_n_num,BIGNUM ** rsa_e_num,CK_SESSION_HANDLE session)13166847Svk199839 static CK_OBJECT_HANDLE pk11_get_public_rsa_key(RSA* rsa,
13176847Svk199839     RSA** key_ptr, BIGNUM **rsa_n_num, BIGNUM **rsa_e_num,
13186847Svk199839     CK_SESSION_HANDLE session)
13190Sstevel@tonic-gate 	{
13200Sstevel@tonic-gate 	CK_RV rv;
13210Sstevel@tonic-gate 	CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
13220Sstevel@tonic-gate 	CK_ULONG found;
13230Sstevel@tonic-gate 	CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY;
13240Sstevel@tonic-gate 	CK_KEY_TYPE k_type = CKK_RSA;
13250Sstevel@tonic-gate 	CK_ULONG ul_key_attr_count = 7;
13267526SVladimir.Kotal@Sun.COM 	CK_BBOOL rollback = FALSE;
13270Sstevel@tonic-gate 
13280Sstevel@tonic-gate 	CK_ATTRIBUTE  a_key_template[] =
13290Sstevel@tonic-gate 		{
13307616SVladimir.Kotal@Sun.COM 		{CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
13317616SVladimir.Kotal@Sun.COM 		{CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
13327616SVladimir.Kotal@Sun.COM 		{CKA_TOKEN, &false, sizeof (true)},
13337616SVladimir.Kotal@Sun.COM 		{CKA_ENCRYPT, &true, sizeof (true)},
13347616SVladimir.Kotal@Sun.COM 		{CKA_VERIFY_RECOVER, &true, sizeof (true)},
13350Sstevel@tonic-gate 		{CKA_MODULUS, (void *)NULL, 0},
13360Sstevel@tonic-gate 		{CKA_PUBLIC_EXPONENT, (void *)NULL, 0}
13370Sstevel@tonic-gate 		};
13380Sstevel@tonic-gate 
13390Sstevel@tonic-gate 	int i;
13400Sstevel@tonic-gate 
13410Sstevel@tonic-gate 	a_key_template[0].pValue = &o_key;
13420Sstevel@tonic-gate 	a_key_template[1].pValue = &k_type;
13430Sstevel@tonic-gate 
13440Sstevel@tonic-gate 	a_key_template[5].ulValueLen = BN_num_bytes(rsa->n);
13450Sstevel@tonic-gate 	a_key_template[5].pValue = (CK_VOID_PTR)OPENSSL_malloc(
13460Sstevel@tonic-gate 		(size_t)a_key_template[5].ulValueLen);
13470Sstevel@tonic-gate 	if (a_key_template[5].pValue == NULL)
13480Sstevel@tonic-gate 		{
13490Sstevel@tonic-gate 		PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
13507526SVladimir.Kotal@Sun.COM 		goto malloc_err;
13510Sstevel@tonic-gate 		}
13520Sstevel@tonic-gate 
1353*11411SSurya.Prakki@Sun.COM 	(void) BN_bn2bin(rsa->n, a_key_template[5].pValue);
13540Sstevel@tonic-gate 
13550Sstevel@tonic-gate 	a_key_template[6].ulValueLen = BN_num_bytes(rsa->e);
13560Sstevel@tonic-gate 	a_key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc(
13570Sstevel@tonic-gate 		(size_t)a_key_template[6].ulValueLen);
13580Sstevel@tonic-gate 	if (a_key_template[6].pValue == NULL)
13590Sstevel@tonic-gate 		{
13600Sstevel@tonic-gate 		PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
13617526SVladimir.Kotal@Sun.COM 		goto malloc_err;
13620Sstevel@tonic-gate 		}
13630Sstevel@tonic-gate 
1364*11411SSurya.Prakki@Sun.COM 	(void) BN_bn2bin(rsa->e, a_key_template[6].pValue);
13650Sstevel@tonic-gate 
13667526SVladimir.Kotal@Sun.COM 	/* see find_lock array definition for more info on object locking */
13677526SVladimir.Kotal@Sun.COM 	LOCK_OBJSTORE(OP_RSA);
13687616SVladimir.Kotal@Sun.COM 	rv = pFuncList->C_FindObjectsInit(session, a_key_template,
13690Sstevel@tonic-gate 		ul_key_attr_count);
13700Sstevel@tonic-gate 
13710Sstevel@tonic-gate 	if (rv != CKR_OK)
13720Sstevel@tonic-gate 		{
13737211Sjp161948 		PK11err_add_data(PK11_F_GET_PUB_RSA_KEY, PK11_R_FINDOBJECTSINIT,
13747211Sjp161948 		    rv);
13750Sstevel@tonic-gate 		goto err;
13760Sstevel@tonic-gate 		}
13770Sstevel@tonic-gate 
13780Sstevel@tonic-gate 	rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
13790Sstevel@tonic-gate 
13800Sstevel@tonic-gate 	if (rv != CKR_OK)
13810Sstevel@tonic-gate 		{
13827616SVladimir.Kotal@Sun.COM 		PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
13837616SVladimir.Kotal@Sun.COM 		    PK11_R_FINDOBJECTS, rv);
13840Sstevel@tonic-gate 		goto err;
13850Sstevel@tonic-gate 		}
13860Sstevel@tonic-gate 
13870Sstevel@tonic-gate 	rv = pFuncList->C_FindObjectsFinal(session);
13880Sstevel@tonic-gate 
13890Sstevel@tonic-gate 	if (rv != CKR_OK)
13900Sstevel@tonic-gate 		{
13917211Sjp161948 		PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
13927211Sjp161948 		    PK11_R_FINDOBJECTSFINAL, rv);
13930Sstevel@tonic-gate 		goto err;
13940Sstevel@tonic-gate 		}
13950Sstevel@tonic-gate 
13960Sstevel@tonic-gate 	if (found == 0)
13970Sstevel@tonic-gate 		{
13987616SVladimir.Kotal@Sun.COM 		rv = pFuncList->C_CreateObject(session,
13990Sstevel@tonic-gate 			a_key_template, ul_key_attr_count, &h_key);
14000Sstevel@tonic-gate 		if (rv != CKR_OK)
14010Sstevel@tonic-gate 			{
14027616SVladimir.Kotal@Sun.COM 			PK11err_add_data(PK11_F_GET_PUB_RSA_KEY,
14037211Sjp161948 			    PK11_R_CREATEOBJECT, rv);
14040Sstevel@tonic-gate 			goto err;
14050Sstevel@tonic-gate 			}
14060Sstevel@tonic-gate 		}
14070Sstevel@tonic-gate 
14086847Svk199839 	if (rsa_n_num != NULL)
14096847Svk199839 		if ((*rsa_n_num = BN_dup(rsa->n)) == NULL)
14106847Svk199839 			{
14116847Svk199839 			PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
14127526SVladimir.Kotal@Sun.COM 			rollback = TRUE;
14136847Svk199839 			goto err;
14146847Svk199839 			}
14156847Svk199839 	if (rsa_e_num != NULL)
14166847Svk199839 		if ((*rsa_e_num = BN_dup(rsa->e)) == NULL)
14176847Svk199839 			{
14186847Svk199839 			PK11err(PK11_F_GET_PUB_RSA_KEY, PK11_R_MALLOC_FAILURE);
14197526SVladimir.Kotal@Sun.COM 			BN_free(*rsa_n_num);
14207526SVladimir.Kotal@Sun.COM 			*rsa_n_num = NULL;
14217526SVladimir.Kotal@Sun.COM 			rollback = TRUE;
14226847Svk199839 			goto err;
14236847Svk199839 			}
14247526SVladimir.Kotal@Sun.COM 
14257534SVladimir.Kotal@Sun.COM 	/* LINTED: E_CONSTANT_CONDITION */
14267526SVladimir.Kotal@Sun.COM 	KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err);
14277526SVladimir.Kotal@Sun.COM 	if (key_ptr != NULL)
14287526SVladimir.Kotal@Sun.COM 		*key_ptr = rsa;
14290Sstevel@tonic-gate 
14306847Svk199839 err:
14317526SVladimir.Kotal@Sun.COM 	if (rollback)
14327526SVladimir.Kotal@Sun.COM 		{
14337628SVladimir.Kotal@Sun.COM 		/*
14347628SVladimir.Kotal@Sun.COM 		 * We do not care about the return value from C_DestroyObject()
14357628SVladimir.Kotal@Sun.COM 		 * since we are doing rollback.
14367628SVladimir.Kotal@Sun.COM 		 */
14377526SVladimir.Kotal@Sun.COM 		if (found == 0)
14387526SVladimir.Kotal@Sun.COM 			(void) pFuncList->C_DestroyObject(session, h_key);
14397526SVladimir.Kotal@Sun.COM 		h_key = CK_INVALID_HANDLE;
14407526SVladimir.Kotal@Sun.COM 		}
14417526SVladimir.Kotal@Sun.COM 
14427526SVladimir.Kotal@Sun.COM 	UNLOCK_OBJSTORE(OP_RSA);
14437526SVladimir.Kotal@Sun.COM 
14447526SVladimir.Kotal@Sun.COM malloc_err:
14450Sstevel@tonic-gate 	for (i = 5; i <= 6; i++)
14460Sstevel@tonic-gate 		{
14470Sstevel@tonic-gate 		if (a_key_template[i].pValue != NULL)
14480Sstevel@tonic-gate 			{
14490Sstevel@tonic-gate 			OPENSSL_free(a_key_template[i].pValue);
14500Sstevel@tonic-gate 			a_key_template[i].pValue = NULL;
14510Sstevel@tonic-gate 			}
14520Sstevel@tonic-gate 		}
14530Sstevel@tonic-gate 
14547616SVladimir.Kotal@Sun.COM 	return (h_key);
14550Sstevel@tonic-gate 	}
14560Sstevel@tonic-gate 
14577526SVladimir.Kotal@Sun.COM /*
14587526SVladimir.Kotal@Sun.COM  * Create a private key object in the session from a given rsa structure.
14597526SVladimir.Kotal@Sun.COM  * The *rsa_d_num pointer is non-NULL for RSA private keys.
14600Sstevel@tonic-gate  */
pk11_get_private_rsa_key(RSA * rsa,RSA ** key_ptr,BIGNUM ** rsa_d_num,CK_SESSION_HANDLE session)14616847Svk199839 static CK_OBJECT_HANDLE pk11_get_private_rsa_key(RSA* rsa,
14626847Svk199839     RSA** key_ptr, BIGNUM **rsa_d_num, CK_SESSION_HANDLE session)
14630Sstevel@tonic-gate 	{
14640Sstevel@tonic-gate 	CK_RV rv;
14650Sstevel@tonic-gate 	CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
14660Sstevel@tonic-gate 	int i;
14670Sstevel@tonic-gate 	CK_ULONG found;
14680Sstevel@tonic-gate 	CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY;
14690Sstevel@tonic-gate 	CK_KEY_TYPE k_type = CKK_RSA;
14700Sstevel@tonic-gate 	CK_ULONG ul_key_attr_count = 14;
14717526SVladimir.Kotal@Sun.COM 	CK_BBOOL rollback = FALSE;
14720Sstevel@tonic-gate 
14737616SVladimir.Kotal@Sun.COM 	/* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */
14740Sstevel@tonic-gate 	CK_ATTRIBUTE  a_key_template[] =
14750Sstevel@tonic-gate 		{
14767616SVladimir.Kotal@Sun.COM 		{CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
14777616SVladimir.Kotal@Sun.COM 		{CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
14787616SVladimir.Kotal@Sun.COM 		{CKA_TOKEN, &false, sizeof (true)},
14797616SVladimir.Kotal@Sun.COM 		{CKA_SENSITIVE, &false, sizeof (true)},
14807616SVladimir.Kotal@Sun.COM 		{CKA_DECRYPT, &true, sizeof (true)},
14817616SVladimir.Kotal@Sun.COM 		{CKA_SIGN, &true, sizeof (true)},
14820Sstevel@tonic-gate 		{CKA_MODULUS, (void *)NULL, 0},
14830Sstevel@tonic-gate 		{CKA_PUBLIC_EXPONENT, (void *)NULL, 0},
14840Sstevel@tonic-gate 		{CKA_PRIVATE_EXPONENT, (void *)NULL, 0},
14850Sstevel@tonic-gate 		{CKA_PRIME_1, (void *)NULL, 0},
14860Sstevel@tonic-gate 		{CKA_PRIME_2, (void *)NULL, 0},
14870Sstevel@tonic-gate 		{CKA_EXPONENT_1, (void *)NULL, 0},
14880Sstevel@tonic-gate 		{CKA_EXPONENT_2, (void *)NULL, 0},
14890Sstevel@tonic-gate 		{CKA_COEFFICIENT, (void *)NULL, 0}
14900Sstevel@tonic-gate 		};
14910Sstevel@tonic-gate 
14920Sstevel@tonic-gate 	a_key_template[0].pValue = &o_key;
14930Sstevel@tonic-gate 	a_key_template[1].pValue = &k_type;
14940Sstevel@tonic-gate 
14950Sstevel@tonic-gate 	/* Put the private key components into the template */
14960Sstevel@tonic-gate 	if (init_template_value(rsa->n, &a_key_template[6].pValue,
14970Sstevel@tonic-gate 		&a_key_template[6].ulValueLen) == 0 ||
14980Sstevel@tonic-gate 	    init_template_value(rsa->e, &a_key_template[7].pValue,
14990Sstevel@tonic-gate 		&a_key_template[7].ulValueLen) == 0 ||
15000Sstevel@tonic-gate 	    init_template_value(rsa->d, &a_key_template[8].pValue,
15010Sstevel@tonic-gate 		&a_key_template[8].ulValueLen) == 0 ||
15020Sstevel@tonic-gate 	    init_template_value(rsa->p, &a_key_template[9].pValue,
15030Sstevel@tonic-gate 		&a_key_template[9].ulValueLen) == 0 ||
15040Sstevel@tonic-gate 	    init_template_value(rsa->q, &a_key_template[10].pValue,
15050Sstevel@tonic-gate 		&a_key_template[10].ulValueLen) == 0 ||
15060Sstevel@tonic-gate 	    init_template_value(rsa->dmp1, &a_key_template[11].pValue,
15070Sstevel@tonic-gate 		&a_key_template[11].ulValueLen) == 0 ||
15080Sstevel@tonic-gate 	    init_template_value(rsa->dmq1, &a_key_template[12].pValue,
15090Sstevel@tonic-gate 		&a_key_template[12].ulValueLen) == 0 ||
15100Sstevel@tonic-gate 	    init_template_value(rsa->iqmp, &a_key_template[13].pValue,
15110Sstevel@tonic-gate 		&a_key_template[13].ulValueLen) == 0)
15120Sstevel@tonic-gate 		{
15130Sstevel@tonic-gate 		PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
15147526SVladimir.Kotal@Sun.COM 		goto malloc_err;
15150Sstevel@tonic-gate 		}
15160Sstevel@tonic-gate 
15177526SVladimir.Kotal@Sun.COM 	/* see find_lock array definition for more info on object locking */
15187526SVladimir.Kotal@Sun.COM 	LOCK_OBJSTORE(OP_RSA);
15197616SVladimir.Kotal@Sun.COM 	rv = pFuncList->C_FindObjectsInit(session, a_key_template,
15200Sstevel@tonic-gate 		ul_key_attr_count);
15210Sstevel@tonic-gate 
15220Sstevel@tonic-gate 	if (rv != CKR_OK)
15230Sstevel@tonic-gate 		{
15247211Sjp161948 		PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
15257211Sjp161948 		    PK11_R_FINDOBJECTSINIT, rv);
15260Sstevel@tonic-gate 		goto err;
15270Sstevel@tonic-gate 		}
15280Sstevel@tonic-gate 
15290Sstevel@tonic-gate 	rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
15300Sstevel@tonic-gate 
15310Sstevel@tonic-gate 	if (rv != CKR_OK)
15320Sstevel@tonic-gate 		{
15337616SVladimir.Kotal@Sun.COM 		PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
15347616SVladimir.Kotal@Sun.COM 		    PK11_R_FINDOBJECTS, rv);
15350Sstevel@tonic-gate 		goto err;
15360Sstevel@tonic-gate 		}
15370Sstevel@tonic-gate 
15380Sstevel@tonic-gate 	rv = pFuncList->C_FindObjectsFinal(session);
15390Sstevel@tonic-gate 
15400Sstevel@tonic-gate 	if (rv != CKR_OK)
15410Sstevel@tonic-gate 		{
15427211Sjp161948 		PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
15437211Sjp161948 		    PK11_R_FINDOBJECTSFINAL, rv);
15440Sstevel@tonic-gate 		goto err;
15450Sstevel@tonic-gate 		}
15460Sstevel@tonic-gate 
15470Sstevel@tonic-gate 	if (found == 0)
15480Sstevel@tonic-gate 		{
15497616SVladimir.Kotal@Sun.COM 		rv = pFuncList->C_CreateObject(session,
15500Sstevel@tonic-gate 			a_key_template, ul_key_attr_count, &h_key);
15510Sstevel@tonic-gate 		if (rv != CKR_OK)
15520Sstevel@tonic-gate 			{
15537616SVladimir.Kotal@Sun.COM 			PK11err_add_data(PK11_F_GET_PRIV_RSA_KEY,
15547211Sjp161948 				PK11_R_CREATEOBJECT, rv);
15550Sstevel@tonic-gate 			goto err;
15560Sstevel@tonic-gate 			}
15570Sstevel@tonic-gate 		}
15580Sstevel@tonic-gate 
15596847Svk199839 	if (rsa_d_num != NULL)
15606847Svk199839 		if ((*rsa_d_num = BN_dup(rsa->d)) == NULL)
15616847Svk199839 			{
15626847Svk199839 			PK11err(PK11_F_GET_PRIV_RSA_KEY, PK11_R_MALLOC_FAILURE);
15637526SVladimir.Kotal@Sun.COM 			rollback = TRUE;
15646847Svk199839 			goto err;
15656847Svk199839 			}
15667526SVladimir.Kotal@Sun.COM 
15677534SVladimir.Kotal@Sun.COM 	/* LINTED: E_CONSTANT_CONDITION */
15687526SVladimir.Kotal@Sun.COM 	KEY_HANDLE_REFHOLD(h_key, OP_RSA, FALSE, rollback, err);
15697526SVladimir.Kotal@Sun.COM 	if (key_ptr != NULL)
15707526SVladimir.Kotal@Sun.COM 		*key_ptr = rsa;
15710Sstevel@tonic-gate 
15726847Svk199839 err:
15737526SVladimir.Kotal@Sun.COM 	if (rollback)
15747526SVladimir.Kotal@Sun.COM 		{
15757628SVladimir.Kotal@Sun.COM 		/*
15767628SVladimir.Kotal@Sun.COM 		 * We do not care about the return value from C_DestroyObject()
15777628SVladimir.Kotal@Sun.COM 		 * since we are doing rollback.
15787628SVladimir.Kotal@Sun.COM 		 */
15797526SVladimir.Kotal@Sun.COM 		if (found == 0)
15807526SVladimir.Kotal@Sun.COM 			(void) pFuncList->C_DestroyObject(session, h_key);
15817526SVladimir.Kotal@Sun.COM 		h_key = CK_INVALID_HANDLE;
15827526SVladimir.Kotal@Sun.COM 		}
15837526SVladimir.Kotal@Sun.COM 
15847526SVladimir.Kotal@Sun.COM 	UNLOCK_OBJSTORE(OP_RSA);
15857526SVladimir.Kotal@Sun.COM 
15867526SVladimir.Kotal@Sun.COM malloc_err:
15877616SVladimir.Kotal@Sun.COM 	/*
15887616SVladimir.Kotal@Sun.COM 	 * 6 to 13 entries in the key template are key components.
15890Sstevel@tonic-gate 	 * They need to be freed apon exit or error.
15900Sstevel@tonic-gate 	 */
15910Sstevel@tonic-gate 	for (i = 6; i <= 13; i++)
15920Sstevel@tonic-gate 		{
15930Sstevel@tonic-gate 		if (a_key_template[i].pValue != NULL)
15940Sstevel@tonic-gate 			{
15957616SVladimir.Kotal@Sun.COM 			(void) memset(a_key_template[i].pValue, 0,
15960Sstevel@tonic-gate 				a_key_template[i].ulValueLen);
15970Sstevel@tonic-gate 			OPENSSL_free(a_key_template[i].pValue);
15980Sstevel@tonic-gate 			a_key_template[i].pValue = NULL;
15990Sstevel@tonic-gate 			}
16000Sstevel@tonic-gate 		}
16010Sstevel@tonic-gate 
16027616SVladimir.Kotal@Sun.COM 	return (h_key);
16030Sstevel@tonic-gate 	}
16040Sstevel@tonic-gate 
16056847Svk199839 /*
16066847Svk199839  * Check for cache miss and clean the object pointer and handle
16076847Svk199839  * in such case. Return 1 for cache hit, 0 for cache miss.
16086847Svk199839  */
check_new_rsa_key_pub(PK11_SESSION * sp,const RSA * rsa)16096847Svk199839 static int check_new_rsa_key_pub(PK11_SESSION *sp, const RSA *rsa)
16106847Svk199839 	{
16116847Svk199839 	/*
16126847Svk199839 	 * Provide protection against RSA structure reuse by making the
16136847Svk199839 	 * check for cache hit stronger. Only public components of RSA
16146847Svk199839 	 * key matter here so it is sufficient to compare them with values
16156847Svk199839 	 * cached in PK11_SESSION structure.
16166847Svk199839 	 */
16177526SVladimir.Kotal@Sun.COM 	if ((sp->opdata_rsa_pub != rsa) ||
16187526SVladimir.Kotal@Sun.COM 	    (BN_cmp(sp->opdata_rsa_n_num, rsa->n) != 0) ||
16197526SVladimir.Kotal@Sun.COM 	    (BN_cmp(sp->opdata_rsa_e_num, rsa->e) != 0))
16206847Svk199839 		{
16216847Svk199839 		/*
16226847Svk199839 		 * We do not check the return value because even in case of
16236847Svk199839 		 * failure the sp structure will have both key pointer
16246847Svk199839 		 * and object handle cleaned and pk11_destroy_object()
16256847Svk199839 		 * reports the failure to the OpenSSL error message buffer.
16266847Svk199839 		 */
16276847Svk199839 		(void) pk11_destroy_rsa_object_pub(sp, TRUE);
16286847Svk199839 		return (0);
16296847Svk199839 		}
16306847Svk199839 	return (1);
16316847Svk199839 	}
16326847Svk199839 
16336847Svk199839 /*
16346847Svk199839  * Check for cache miss and clean the object pointer and handle
16356847Svk199839  * in such case. Return 1 for cache hit, 0 for cache miss.
16366847Svk199839  */
check_new_rsa_key_priv(PK11_SESSION * sp,const RSA * rsa)16376847Svk199839 static int check_new_rsa_key_priv(PK11_SESSION *sp, const RSA *rsa)
16386847Svk199839 	{
16396847Svk199839 	/*
16406847Svk199839 	 * Provide protection against RSA structure reuse by making the
16416847Svk199839 	 * check for cache hit stronger. Comparing private exponent of RSA
16426847Svk199839 	 * key with value cached in PK11_SESSION structure should
16436847Svk199839 	 * be sufficient.
16446847Svk199839 	 */
16457526SVladimir.Kotal@Sun.COM 	if ((sp->opdata_rsa_priv != rsa) ||
16467526SVladimir.Kotal@Sun.COM 	    (BN_cmp(sp->opdata_rsa_d_num, rsa->d) != 0))
16476847Svk199839 		{
16486847Svk199839 		/*
16496847Svk199839 		 * We do not check the return value because even in case of
16506847Svk199839 		 * failure the sp structure will have both key pointer
16516847Svk199839 		 * and object handle cleaned and pk11_destroy_object()
16526847Svk199839 		 * reports the failure to the OpenSSL error message buffer.
16536847Svk199839 		 */
16546847Svk199839 		(void) pk11_destroy_rsa_object_priv(sp, TRUE);
16556847Svk199839 		return (0);
16566847Svk199839 		}
16576847Svk199839 	return (1);
16586847Svk199839 	}
16590Sstevel@tonic-gate #endif
16600Sstevel@tonic-gate 
16610Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
16627616SVladimir.Kotal@Sun.COM /* The DSA function implementation */
16637534SVladimir.Kotal@Sun.COM /* ARGSUSED */
pk11_DSA_init(DSA * dsa)16640Sstevel@tonic-gate static int pk11_DSA_init(DSA *dsa)
16650Sstevel@tonic-gate 	{
16667616SVladimir.Kotal@Sun.COM 	return (1);
16670Sstevel@tonic-gate 	}
16680Sstevel@tonic-gate 
16697534SVladimir.Kotal@Sun.COM /* ARGSUSED */
pk11_DSA_finish(DSA * dsa)16700Sstevel@tonic-gate static int pk11_DSA_finish(DSA *dsa)
16710Sstevel@tonic-gate 	{
16726847Svk199839 	return (1);
16730Sstevel@tonic-gate 	}
16740Sstevel@tonic-gate 
16750Sstevel@tonic-gate 
16760Sstevel@tonic-gate static DSA_SIG *
pk11_dsa_do_sign(const unsigned char * dgst,int dlen,DSA * dsa)16770Sstevel@tonic-gate pk11_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
16780Sstevel@tonic-gate 	{
16790Sstevel@tonic-gate 	BIGNUM *r = NULL, *s = NULL;
16800Sstevel@tonic-gate 	int i;
16810Sstevel@tonic-gate 	DSA_SIG *dsa_sig = NULL;
16820Sstevel@tonic-gate 
16830Sstevel@tonic-gate 	CK_RV rv;
16840Sstevel@tonic-gate 	CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0};
16850Sstevel@tonic-gate 	CK_MECHANISM *p_mech = &Mechanism_dsa;
16860Sstevel@tonic-gate 	CK_OBJECT_HANDLE h_priv_key;
16870Sstevel@tonic-gate 
16887616SVladimir.Kotal@Sun.COM 	/*
16897616SVladimir.Kotal@Sun.COM 	 * The signature is the concatenation of r and s,
16900Sstevel@tonic-gate 	 * each is 20 bytes long
16910Sstevel@tonic-gate 	 */
16920Sstevel@tonic-gate 	unsigned char sigret[DSA_SIGNATURE_LEN];
16932378Sjp161948 	unsigned long siglen = DSA_SIGNATURE_LEN;
16940Sstevel@tonic-gate 	unsigned int siglen2 = DSA_SIGNATURE_LEN / 2;
16950Sstevel@tonic-gate 
16960Sstevel@tonic-gate 	PK11_SESSION *sp = NULL;
16970Sstevel@tonic-gate 
16987616SVladimir.Kotal@Sun.COM 	if ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL))
16990Sstevel@tonic-gate 		{
17000Sstevel@tonic-gate 		PK11err(PK11_F_DSA_SIGN, PK11_R_MISSING_KEY_COMPONENT);
17010Sstevel@tonic-gate 		goto ret;
17020Sstevel@tonic-gate 		}
17030Sstevel@tonic-gate 
17047616SVladimir.Kotal@Sun.COM 	i = BN_num_bytes(dsa->q); /* should be 20 */
17050Sstevel@tonic-gate 	if (dlen > i)
17060Sstevel@tonic-gate 		{
17070Sstevel@tonic-gate 		PK11err(PK11_F_DSA_SIGN, PK11_R_INVALID_SIGNATURE_LENGTH);
17080Sstevel@tonic-gate 		goto ret;
17090Sstevel@tonic-gate 		}
17100Sstevel@tonic-gate 
17117526SVladimir.Kotal@Sun.COM 	if ((sp = pk11_get_session(OP_DSA)) == NULL)
17120Sstevel@tonic-gate 		goto ret;
17130Sstevel@tonic-gate 
17146847Svk199839 	(void) check_new_dsa_key_priv(sp, dsa);
17150Sstevel@tonic-gate 
17167526SVladimir.Kotal@Sun.COM 	h_priv_key = sp->opdata_dsa_priv_key;
17170Sstevel@tonic-gate 	if (h_priv_key == CK_INVALID_HANDLE)
17187526SVladimir.Kotal@Sun.COM 		h_priv_key = sp->opdata_dsa_priv_key =
17197526SVladimir.Kotal@Sun.COM 			pk11_get_private_dsa_key((DSA *)dsa,
17207526SVladimir.Kotal@Sun.COM 			    &sp->opdata_dsa_priv,
17217526SVladimir.Kotal@Sun.COM 			    &sp->opdata_dsa_priv_num, sp->session);
17220Sstevel@tonic-gate 
17230Sstevel@tonic-gate 	if (h_priv_key != CK_INVALID_HANDLE)
17240Sstevel@tonic-gate 		{
17250Sstevel@tonic-gate 		rv = pFuncList->C_SignInit(sp->session, p_mech, h_priv_key);
17260Sstevel@tonic-gate 
17270Sstevel@tonic-gate 		if (rv != CKR_OK)
17280Sstevel@tonic-gate 			{
17297211Sjp161948 			PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGNINIT, rv);
17300Sstevel@tonic-gate 			goto ret;
17310Sstevel@tonic-gate 			}
17320Sstevel@tonic-gate 
17337616SVladimir.Kotal@Sun.COM 			(void) memset(sigret, 0, siglen);
17347616SVladimir.Kotal@Sun.COM 			rv = pFuncList->C_Sign(sp->session,
17357616SVladimir.Kotal@Sun.COM 			    (unsigned char *) dgst, dlen, sigret,
17367616SVladimir.Kotal@Sun.COM 			    (CK_ULONG_PTR) &siglen);
17370Sstevel@tonic-gate 
17380Sstevel@tonic-gate 		if (rv != CKR_OK)
17390Sstevel@tonic-gate 			{
17407211Sjp161948 			PK11err_add_data(PK11_F_DSA_SIGN, PK11_R_SIGN, rv);
17410Sstevel@tonic-gate 			goto ret;
17420Sstevel@tonic-gate 			}
17430Sstevel@tonic-gate 		}
17440Sstevel@tonic-gate 
17450Sstevel@tonic-gate 
17460Sstevel@tonic-gate 	if ((s = BN_new()) == NULL)
17470Sstevel@tonic-gate 		{
17480Sstevel@tonic-gate 		PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
17490Sstevel@tonic-gate 		goto ret;
17500Sstevel@tonic-gate 		}
17510Sstevel@tonic-gate 
17520Sstevel@tonic-gate 	if ((r = BN_new()) == NULL)
17530Sstevel@tonic-gate 		{
17540Sstevel@tonic-gate 		PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
17550Sstevel@tonic-gate 		goto ret;
17560Sstevel@tonic-gate 		}
17570Sstevel@tonic-gate 
17580Sstevel@tonic-gate 	if ((dsa_sig = DSA_SIG_new()) == NULL)
17590Sstevel@tonic-gate 		{
17600Sstevel@tonic-gate 		PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
17610Sstevel@tonic-gate 		goto ret;
17620Sstevel@tonic-gate 		}
17630Sstevel@tonic-gate 
17647526SVladimir.Kotal@Sun.COM 	if (BN_bin2bn(sigret, siglen2, r) == NULL ||
17657526SVladimir.Kotal@Sun.COM 	    BN_bin2bn(&sigret[siglen2], siglen2, s) == NULL)
17667526SVladimir.Kotal@Sun.COM 		{
17677526SVladimir.Kotal@Sun.COM 		PK11err(PK11_F_DSA_SIGN, PK11_R_MALLOC_FAILURE);
17687526SVladimir.Kotal@Sun.COM 		goto ret;
17697526SVladimir.Kotal@Sun.COM 		}
17700Sstevel@tonic-gate 
17710Sstevel@tonic-gate 	dsa_sig->r = r;
17720Sstevel@tonic-gate 	dsa_sig->s = s;
17730Sstevel@tonic-gate 
17740Sstevel@tonic-gate ret:
17757616SVladimir.Kotal@Sun.COM 	if (dsa_sig == NULL)
17760Sstevel@tonic-gate 		{
17770Sstevel@tonic-gate 		if (r != NULL)
17780Sstevel@tonic-gate 			BN_free(r);
17790Sstevel@tonic-gate 		if (s != NULL)
17800Sstevel@tonic-gate 			BN_free(s);
17810Sstevel@tonic-gate 		}
17820Sstevel@tonic-gate 
17837526SVladimir.Kotal@Sun.COM 	pk11_return_session(sp, OP_DSA);
17840Sstevel@tonic-gate 	return (dsa_sig);
17850Sstevel@tonic-gate 	}
17860Sstevel@tonic-gate 
17870Sstevel@tonic-gate static int
pk11_dsa_do_verify(const unsigned char * dgst,int dlen,DSA_SIG * sig,DSA * dsa)17880Sstevel@tonic-gate pk11_dsa_do_verify(const unsigned char *dgst, int dlen, DSA_SIG *sig,
17890Sstevel@tonic-gate 	DSA *dsa)
17900Sstevel@tonic-gate 	{
17910Sstevel@tonic-gate 	int i;
17920Sstevel@tonic-gate 	CK_RV rv;
17930Sstevel@tonic-gate 	int retval = 0;
17940Sstevel@tonic-gate 	CK_MECHANISM Mechanism_dsa = {CKM_DSA, NULL, 0};
17950Sstevel@tonic-gate 	CK_MECHANISM *p_mech = &Mechanism_dsa;
17960Sstevel@tonic-gate 	CK_OBJECT_HANDLE h_pub_key;
17970Sstevel@tonic-gate 
17980Sstevel@tonic-gate 	unsigned char sigbuf[DSA_SIGNATURE_LEN];
17990Sstevel@tonic-gate 	unsigned long siglen = DSA_SIGNATURE_LEN;
18000Sstevel@tonic-gate 	unsigned long siglen2 = DSA_SIGNATURE_LEN/2;
18010Sstevel@tonic-gate 
18020Sstevel@tonic-gate 	PK11_SESSION *sp = NULL;
18030Sstevel@tonic-gate 
18040Sstevel@tonic-gate 	if (BN_is_zero(sig->r) || sig->r->neg || BN_ucmp(sig->r, dsa->q) >= 0)
18050Sstevel@tonic-gate 		{
18067616SVladimir.Kotal@Sun.COM 		PK11err(PK11_F_DSA_VERIFY,
18070Sstevel@tonic-gate 			PK11_R_INVALID_DSA_SIGNATURE_R);
18080Sstevel@tonic-gate 		goto ret;
18090Sstevel@tonic-gate 		}
18100Sstevel@tonic-gate 
18117616SVladimir.Kotal@Sun.COM 	if (BN_is_zero(sig->s) || sig->s->neg || BN_ucmp(sig->s, dsa->q) >= 0)
18120Sstevel@tonic-gate 		{
18137616SVladimir.Kotal@Sun.COM 		PK11err(PK11_F_DSA_VERIFY,
18140Sstevel@tonic-gate 			PK11_R_INVALID_DSA_SIGNATURE_S);
18150Sstevel@tonic-gate 		goto ret;
18160Sstevel@tonic-gate 		}
18170Sstevel@tonic-gate 
18180Sstevel@tonic-gate 	i = BN_num_bytes(dsa->q); /* should be 20 */
18190Sstevel@tonic-gate 
18200Sstevel@tonic-gate 	if (dlen > i)
18210Sstevel@tonic-gate 		{
18227616SVladimir.Kotal@Sun.COM 		PK11err(PK11_F_DSA_VERIFY,
18230Sstevel@tonic-gate 			PK11_R_INVALID_SIGNATURE_LENGTH);
18240Sstevel@tonic-gate 		goto ret;
18250Sstevel@tonic-gate 		}
18260Sstevel@tonic-gate 
18277526SVladimir.Kotal@Sun.COM 	if ((sp = pk11_get_session(OP_DSA)) == NULL)
18280Sstevel@tonic-gate 		goto ret;
18297616SVladimir.Kotal@Sun.COM 
18306847Svk199839 	(void) check_new_dsa_key_pub(sp, dsa);
18310Sstevel@tonic-gate 
18327526SVladimir.Kotal@Sun.COM 	h_pub_key = sp->opdata_dsa_pub_key;
18330Sstevel@tonic-gate 	if (h_pub_key == CK_INVALID_HANDLE)
18347526SVladimir.Kotal@Sun.COM 		h_pub_key = sp->opdata_dsa_pub_key =
18357526SVladimir.Kotal@Sun.COM 			pk11_get_public_dsa_key((DSA *)dsa, &sp->opdata_dsa_pub,
18367526SVladimir.Kotal@Sun.COM 			    &sp->opdata_dsa_pub_num, sp->session);
18370Sstevel@tonic-gate 
18380Sstevel@tonic-gate 	if (h_pub_key != CK_INVALID_HANDLE)
18390Sstevel@tonic-gate 		{
18407616SVladimir.Kotal@Sun.COM 		rv = pFuncList->C_VerifyInit(sp->session, p_mech,
18410Sstevel@tonic-gate 			h_pub_key);
18420Sstevel@tonic-gate 
18430Sstevel@tonic-gate 		if (rv != CKR_OK)
18440Sstevel@tonic-gate 			{
18457211Sjp161948 			PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFYINIT,
18467211Sjp161948 			    rv);
18470Sstevel@tonic-gate 			goto ret;
18480Sstevel@tonic-gate 			}
18490Sstevel@tonic-gate 
18506847Svk199839 		/*
18516847Svk199839 		 * The representation of each of the two big numbers could
18526847Svk199839 		 * be shorter than DSA_SIGNATURE_LEN/2 bytes so we need
18536847Svk199839 		 * to act accordingly and shift if necessary.
18546847Svk199839 		 */
18557534SVladimir.Kotal@Sun.COM 		(void) memset(sigbuf, 0, siglen);
1856*11411SSurya.Prakki@Sun.COM 		(void) BN_bn2bin(sig->r,
1857*11411SSurya.Prakki@Sun.COM 		    sigbuf + siglen2 - BN_num_bytes(sig->r));
1858*11411SSurya.Prakki@Sun.COM 		(void) BN_bn2bin(sig->s, &sigbuf[siglen2] + siglen2 -
18597211Sjp161948 		    BN_num_bytes(sig->s));
18607616SVladimir.Kotal@Sun.COM 
18617616SVladimir.Kotal@Sun.COM 		rv = pFuncList->C_Verify(sp->session,
18620Sstevel@tonic-gate 			(unsigned char *) dgst, dlen, sigbuf, (CK_ULONG)siglen);
18630Sstevel@tonic-gate 
18640Sstevel@tonic-gate 		if (rv != CKR_OK)
18650Sstevel@tonic-gate 			{
18667211Sjp161948 			PK11err_add_data(PK11_F_DSA_VERIFY, PK11_R_VERIFY, rv);
18670Sstevel@tonic-gate 			goto ret;
18680Sstevel@tonic-gate 			}
18690Sstevel@tonic-gate 		}
18700Sstevel@tonic-gate 
18710Sstevel@tonic-gate 	retval = 1;
18720Sstevel@tonic-gate ret:
18730Sstevel@tonic-gate 
18747526SVladimir.Kotal@Sun.COM 	pk11_return_session(sp, OP_DSA);
18757616SVladimir.Kotal@Sun.COM 	return (retval);
18760Sstevel@tonic-gate 	}
18770Sstevel@tonic-gate 
18780Sstevel@tonic-gate 
18797526SVladimir.Kotal@Sun.COM /*
18807526SVladimir.Kotal@Sun.COM  * Create a public key object in a session from a given dsa structure.
18817526SVladimir.Kotal@Sun.COM  * The *dsa_pub_num pointer is non-NULL for DSA public keys.
18820Sstevel@tonic-gate  */
pk11_get_public_dsa_key(DSA * dsa,DSA ** key_ptr,BIGNUM ** dsa_pub_num,CK_SESSION_HANDLE session)18836847Svk199839 static CK_OBJECT_HANDLE pk11_get_public_dsa_key(DSA* dsa,
18846847Svk199839     DSA **key_ptr, BIGNUM **dsa_pub_num, CK_SESSION_HANDLE session)
18850Sstevel@tonic-gate 	{
18860Sstevel@tonic-gate 	CK_RV rv;
18870Sstevel@tonic-gate 	CK_OBJECT_CLASS o_key = CKO_PUBLIC_KEY;
18880Sstevel@tonic-gate 	CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
18890Sstevel@tonic-gate 	CK_ULONG found;
18900Sstevel@tonic-gate 	CK_KEY_TYPE k_type = CKK_DSA;
18910Sstevel@tonic-gate 	CK_ULONG ul_key_attr_count = 8;
18927526SVladimir.Kotal@Sun.COM 	CK_BBOOL rollback = FALSE;
18930Sstevel@tonic-gate 	int i;
18940Sstevel@tonic-gate 
18950Sstevel@tonic-gate 	CK_ATTRIBUTE  a_key_template[] =
18960Sstevel@tonic-gate 		{
18977616SVladimir.Kotal@Sun.COM 		{CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
18987616SVladimir.Kotal@Sun.COM 		{CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
18997616SVladimir.Kotal@Sun.COM 		{CKA_TOKEN, &false, sizeof (true)},
19007616SVladimir.Kotal@Sun.COM 		{CKA_VERIFY, &true, sizeof (true)},
19010Sstevel@tonic-gate 		{CKA_PRIME, (void *)NULL, 0},		/* p */
19020Sstevel@tonic-gate 		{CKA_SUBPRIME, (void *)NULL, 0},	/* q */
19030Sstevel@tonic-gate 		{CKA_BASE, (void *)NULL, 0},		/* g */
19040Sstevel@tonic-gate 		{CKA_VALUE, (void *)NULL, 0}		/* pub_key - y */
19050Sstevel@tonic-gate 		};
19060Sstevel@tonic-gate 
19070Sstevel@tonic-gate 	a_key_template[0].pValue = &o_key;
19080Sstevel@tonic-gate 	a_key_template[1].pValue = &k_type;
19090Sstevel@tonic-gate 
19100Sstevel@tonic-gate 	if (init_template_value(dsa->p, &a_key_template[4].pValue,
19110Sstevel@tonic-gate 		&a_key_template[4].ulValueLen) == 0 ||
19120Sstevel@tonic-gate 	    init_template_value(dsa->q, &a_key_template[5].pValue,
19130Sstevel@tonic-gate 		&a_key_template[5].ulValueLen) == 0 ||
19140Sstevel@tonic-gate 	    init_template_value(dsa->g, &a_key_template[6].pValue,
19150Sstevel@tonic-gate 		&a_key_template[6].ulValueLen) == 0 ||
19160Sstevel@tonic-gate 	    init_template_value(dsa->pub_key, &a_key_template[7].pValue,
19170Sstevel@tonic-gate 		&a_key_template[7].ulValueLen) == 0)
19180Sstevel@tonic-gate 		{
19190Sstevel@tonic-gate 		PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE);
19207526SVladimir.Kotal@Sun.COM 		goto malloc_err;
19210Sstevel@tonic-gate 		}
19220Sstevel@tonic-gate 
19237526SVladimir.Kotal@Sun.COM 	/* see find_lock array definition for more info on object locking */
19247526SVladimir.Kotal@Sun.COM 	LOCK_OBJSTORE(OP_DSA);
19257616SVladimir.Kotal@Sun.COM 	rv = pFuncList->C_FindObjectsInit(session, a_key_template,
19260Sstevel@tonic-gate 		ul_key_attr_count);
19270Sstevel@tonic-gate 
19280Sstevel@tonic-gate 	if (rv != CKR_OK)
19290Sstevel@tonic-gate 		{
19307211Sjp161948 		PK11err_add_data(PK11_F_GET_PUB_DSA_KEY, PK11_R_FINDOBJECTSINIT,
19317211Sjp161948 		    rv);
19320Sstevel@tonic-gate 		goto err;
19330Sstevel@tonic-gate 		}
19340Sstevel@tonic-gate 
19350Sstevel@tonic-gate 	rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
19360Sstevel@tonic-gate 
19370Sstevel@tonic-gate 	if (rv != CKR_OK)
19380Sstevel@tonic-gate 		{
19397616SVladimir.Kotal@Sun.COM 		PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
19407616SVladimir.Kotal@Sun.COM 		    PK11_R_FINDOBJECTS, rv);
19410Sstevel@tonic-gate 		goto err;
19420Sstevel@tonic-gate 		}
19430Sstevel@tonic-gate 
19440Sstevel@tonic-gate 	rv = pFuncList->C_FindObjectsFinal(session);
19450Sstevel@tonic-gate 
19460Sstevel@tonic-gate 	if (rv != CKR_OK)
19470Sstevel@tonic-gate 		{
19487211Sjp161948 		PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
19497211Sjp161948 		    PK11_R_FINDOBJECTSFINAL, rv);
19500Sstevel@tonic-gate 		goto err;
19510Sstevel@tonic-gate 		}
19520Sstevel@tonic-gate 
19530Sstevel@tonic-gate 	if (found == 0)
19540Sstevel@tonic-gate 		{
19557616SVladimir.Kotal@Sun.COM 		rv = pFuncList->C_CreateObject(session,
19560Sstevel@tonic-gate 			a_key_template, ul_key_attr_count, &h_key);
19570Sstevel@tonic-gate 		if (rv != CKR_OK)
19580Sstevel@tonic-gate 			{
19597616SVladimir.Kotal@Sun.COM 			PK11err_add_data(PK11_F_GET_PUB_DSA_KEY,
19607211Sjp161948 			    PK11_R_CREATEOBJECT, rv);
19610Sstevel@tonic-gate 			goto err;
19620Sstevel@tonic-gate 			}
19630Sstevel@tonic-gate 		}
19640Sstevel@tonic-gate 
19656847Svk199839 	if (dsa_pub_num != NULL)
19666847Svk199839 		if ((*dsa_pub_num = BN_dup(dsa->pub_key)) == NULL)
19676847Svk199839 			{
19686847Svk199839 			PK11err(PK11_F_GET_PUB_DSA_KEY, PK11_R_MALLOC_FAILURE);
19697526SVladimir.Kotal@Sun.COM 			rollback = TRUE;
19706847Svk199839 			goto err;
19716847Svk199839 			}
19727526SVladimir.Kotal@Sun.COM 
19737534SVladimir.Kotal@Sun.COM 	/* LINTED: E_CONSTANT_CONDITION */
19747526SVladimir.Kotal@Sun.COM 	KEY_HANDLE_REFHOLD(h_key, OP_DSA, FALSE, rollback, err);
19757526SVladimir.Kotal@Sun.COM 	if (key_ptr != NULL)
19767526SVladimir.Kotal@Sun.COM 		*key_ptr = dsa;
19770Sstevel@tonic-gate 
19786847Svk199839 err:
19797526SVladimir.Kotal@Sun.COM 	if (rollback)
19807526SVladimir.Kotal@Sun.COM 		{
19817628SVladimir.Kotal@Sun.COM 		/*
19827628SVladimir.Kotal@Sun.COM 		 * We do not care about the return value from C_DestroyObject()
19837628SVladimir.Kotal@Sun.COM 		 * since we are doing rollback.
19847628SVladimir.Kotal@Sun.COM 		 */
19857526SVladimir.Kotal@Sun.COM 		if (found == 0)
19867526SVladimir.Kotal@Sun.COM 			(void) pFuncList->C_DestroyObject(session, h_key);
19877526SVladimir.Kotal@Sun.COM 		h_key = CK_INVALID_HANDLE;
19887526SVladimir.Kotal@Sun.COM 		}
19897526SVladimir.Kotal@Sun.COM 
19907526SVladimir.Kotal@Sun.COM 	UNLOCK_OBJSTORE(OP_DSA);
19917526SVladimir.Kotal@Sun.COM 
19927526SVladimir.Kotal@Sun.COM malloc_err:
19930Sstevel@tonic-gate 	for (i = 4; i <= 7; i++)
19940Sstevel@tonic-gate 		{
19950Sstevel@tonic-gate 		if (a_key_template[i].pValue != NULL)
19960Sstevel@tonic-gate 			{
19970Sstevel@tonic-gate 			OPENSSL_free(a_key_template[i].pValue);
19980Sstevel@tonic-gate 			a_key_template[i].pValue = NULL;
19990Sstevel@tonic-gate 			}
20000Sstevel@tonic-gate 		}
20010Sstevel@tonic-gate 
20027616SVladimir.Kotal@Sun.COM 	return (h_key);
20030Sstevel@tonic-gate 	}
20040Sstevel@tonic-gate 
20057526SVladimir.Kotal@Sun.COM /*
20067526SVladimir.Kotal@Sun.COM  * Create a private key object in the session from a given dsa structure
20077526SVladimir.Kotal@Sun.COM  * The *dsa_priv_num pointer is non-NULL for DSA private keys.
20080Sstevel@tonic-gate  */
pk11_get_private_dsa_key(DSA * dsa,DSA ** key_ptr,BIGNUM ** dsa_priv_num,CK_SESSION_HANDLE session)20096847Svk199839 static CK_OBJECT_HANDLE pk11_get_private_dsa_key(DSA* dsa,
20106847Svk199839     DSA **key_ptr, BIGNUM **dsa_priv_num, CK_SESSION_HANDLE session)
20110Sstevel@tonic-gate 	{
20120Sstevel@tonic-gate 	CK_RV rv;
20130Sstevel@tonic-gate 	CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
20140Sstevel@tonic-gate 	CK_OBJECT_CLASS o_key = CKO_PRIVATE_KEY;
20150Sstevel@tonic-gate 	int i;
20160Sstevel@tonic-gate 	CK_ULONG found;
20170Sstevel@tonic-gate 	CK_KEY_TYPE k_type = CKK_DSA;
20180Sstevel@tonic-gate 	CK_ULONG ul_key_attr_count = 9;
20197526SVladimir.Kotal@Sun.COM 	CK_BBOOL rollback = FALSE;
20200Sstevel@tonic-gate 
20217616SVladimir.Kotal@Sun.COM 	/* Both CKA_TOKEN and CKA_SENSITIVE have to be FALSE for session keys */
20220Sstevel@tonic-gate 	CK_ATTRIBUTE  a_key_template[] =
20230Sstevel@tonic-gate 		{
20247616SVladimir.Kotal@Sun.COM 		{CKA_CLASS, (void *) NULL, sizeof (CK_OBJECT_CLASS)},
20257616SVladimir.Kotal@Sun.COM 		{CKA_KEY_TYPE, (void *) NULL, sizeof (CK_KEY_TYPE)},
20267616SVladimir.Kotal@Sun.COM 		{CKA_TOKEN, &false, sizeof (true)},
20277616SVladimir.Kotal@Sun.COM 		{CKA_SENSITIVE, &false, sizeof (true)},
20287616SVladimir.Kotal@Sun.COM 		{CKA_SIGN, &true, sizeof (true)},
20290Sstevel@tonic-gate 		{CKA_PRIME, (void *)NULL, 0},		/* p */
20300Sstevel@tonic-gate 		{CKA_SUBPRIME, (void *)NULL, 0},	/* q */
20310Sstevel@tonic-gate 		{CKA_BASE, (void *)NULL, 0},		/* g */
20320Sstevel@tonic-gate 		{CKA_VALUE, (void *)NULL, 0}		/* priv_key - x */
20330Sstevel@tonic-gate 		};
20340Sstevel@tonic-gate 
20350Sstevel@tonic-gate 	a_key_template[0].pValue = &o_key;
20360Sstevel@tonic-gate 	a_key_template[1].pValue = &k_type;
20370Sstevel@tonic-gate 
20387616SVladimir.Kotal@Sun.COM 	/* Put the private key components into the template */
20390Sstevel@tonic-gate 	if (init_template_value(dsa->p, &a_key_template[5].pValue,
20400Sstevel@tonic-gate 		&a_key_template[5].ulValueLen) == 0 ||
20410Sstevel@tonic-gate 	    init_template_value(dsa->q, &a_key_template[6].pValue,
20420Sstevel@tonic-gate 		&a_key_template[6].ulValueLen) == 0 ||
20430Sstevel@tonic-gate 	    init_template_value(dsa->g, &a_key_template[7].pValue,
20440Sstevel@tonic-gate 		&a_key_template[7].ulValueLen) == 0 ||
20450Sstevel@tonic-gate 	    init_template_value(dsa->priv_key, &a_key_template[8].pValue,
20460Sstevel@tonic-gate 		&a_key_template[8].ulValueLen) == 0)
20470Sstevel@tonic-gate 		{
20480Sstevel@tonic-gate 		PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE);
20497526SVladimir.Kotal@Sun.COM 		goto malloc_err;
20500Sstevel@tonic-gate 		}
20510Sstevel@tonic-gate 
20527526SVladimir.Kotal@Sun.COM 	/* see find_lock array definition for more info on object locking */
20537526SVladimir.Kotal@Sun.COM 	LOCK_OBJSTORE(OP_DSA);
20547616SVladimir.Kotal@Sun.COM 	rv = pFuncList->C_FindObjectsInit(session, a_key_template,
20550Sstevel@tonic-gate 		ul_key_attr_count);
20560Sstevel@tonic-gate 
20570Sstevel@tonic-gate 	if (rv != CKR_OK)
20580Sstevel@tonic-gate 		{
20597211Sjp161948 		PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
20607211Sjp161948 		    PK11_R_FINDOBJECTSINIT, rv);
20610Sstevel@tonic-gate 		goto err;
20620Sstevel@tonic-gate 		}
20630Sstevel@tonic-gate 
20640Sstevel@tonic-gate 	rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
20650Sstevel@tonic-gate 
20660Sstevel@tonic-gate 	if (rv != CKR_OK)
20670Sstevel@tonic-gate 		{
20687616SVladimir.Kotal@Sun.COM 		PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
20697616SVladimir.Kotal@Sun.COM 		    PK11_R_FINDOBJECTS, rv);
20700Sstevel@tonic-gate 		goto err;
20710Sstevel@tonic-gate 		}
20720Sstevel@tonic-gate 
20730Sstevel@tonic-gate 	rv = pFuncList->C_FindObjectsFinal(session);
20740Sstevel@tonic-gate 
20750Sstevel@tonic-gate 	if (rv != CKR_OK)
20760Sstevel@tonic-gate 		{
20777211Sjp161948 		PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
20787211Sjp161948 		    PK11_R_FINDOBJECTSFINAL, rv);
20790Sstevel@tonic-gate 		goto err;
20800Sstevel@tonic-gate 		}
20810Sstevel@tonic-gate 
20820Sstevel@tonic-gate 	if (found == 0)
20830Sstevel@tonic-gate 		{
20847616SVladimir.Kotal@Sun.COM 		rv = pFuncList->C_CreateObject(session,
20850Sstevel@tonic-gate 			a_key_template, ul_key_attr_count, &h_key);
20860Sstevel@tonic-gate 		if (rv != CKR_OK)
20870Sstevel@tonic-gate 			{
20887616SVladimir.Kotal@Sun.COM 			PK11err_add_data(PK11_F_GET_PRIV_DSA_KEY,
20897211Sjp161948 			    PK11_R_CREATEOBJECT, rv);
20900Sstevel@tonic-gate 			goto err;
20910Sstevel@tonic-gate 			}
20920Sstevel@tonic-gate 		}
20930Sstevel@tonic-gate 
20946847Svk199839 	if (dsa_priv_num != NULL)
20956847Svk199839 		if ((*dsa_priv_num = BN_dup(dsa->priv_key)) == NULL)
20966847Svk199839 			{
20976847Svk199839 			PK11err(PK11_F_GET_PRIV_DSA_KEY, PK11_R_MALLOC_FAILURE);
20987526SVladimir.Kotal@Sun.COM 			rollback = TRUE;
20996847Svk199839 			goto err;
21006847Svk199839 			}
21017526SVladimir.Kotal@Sun.COM 
21027534SVladimir.Kotal@Sun.COM 	/* LINTED: E_CONSTANT_CONDITION */
21037526SVladimir.Kotal@Sun.COM 	KEY_HANDLE_REFHOLD(h_key, OP_DSA, FALSE, rollback, err);
21047526SVladimir.Kotal@Sun.COM 	if (key_ptr != NULL)
21057526SVladimir.Kotal@Sun.COM 		*key_ptr = dsa;
21060Sstevel@tonic-gate 
21070Sstevel@tonic-gate err:
21087526SVladimir.Kotal@Sun.COM 	if (rollback)
21097526SVladimir.Kotal@Sun.COM 		{
21107628SVladimir.Kotal@Sun.COM 		/*
21117628SVladimir.Kotal@Sun.COM 		 * We do not care about the return value from C_DestroyObject()
21127628SVladimir.Kotal@Sun.COM 		 * since we are doing rollback.
21137628SVladimir.Kotal@Sun.COM 		 */
21147526SVladimir.Kotal@Sun.COM 		if (found == 0)
21157526SVladimir.Kotal@Sun.COM 			(void) pFuncList->C_DestroyObject(session, h_key);
21167526SVladimir.Kotal@Sun.COM 		h_key = CK_INVALID_HANDLE;
21177526SVladimir.Kotal@Sun.COM 		}
21187526SVladimir.Kotal@Sun.COM 
21197526SVladimir.Kotal@Sun.COM 	UNLOCK_OBJSTORE(OP_DSA);
21207526SVladimir.Kotal@Sun.COM 
21217526SVladimir.Kotal@Sun.COM malloc_err:
21227616SVladimir.Kotal@Sun.COM 	/*
21237616SVladimir.Kotal@Sun.COM 	 * 5 to 8 entries in the key template are key components.
21240Sstevel@tonic-gate 	 * They need to be freed apon exit or error.
21250Sstevel@tonic-gate 	 */
21260Sstevel@tonic-gate 	for (i = 5; i <= 8; i++)
21270Sstevel@tonic-gate 		{
21280Sstevel@tonic-gate 		if (a_key_template[i].pValue != NULL)
21290Sstevel@tonic-gate 			{
21307534SVladimir.Kotal@Sun.COM 			(void) memset(a_key_template[i].pValue, 0,
21310Sstevel@tonic-gate 				a_key_template[i].ulValueLen);
21320Sstevel@tonic-gate 			OPENSSL_free(a_key_template[i].pValue);
21330Sstevel@tonic-gate 			a_key_template[i].pValue = NULL;
21340Sstevel@tonic-gate 			}
21350Sstevel@tonic-gate 		}
21360Sstevel@tonic-gate 
21377616SVladimir.Kotal@Sun.COM 	return (h_key);
21380Sstevel@tonic-gate 	}
21396847Svk199839 
21406847Svk199839 /*
21416847Svk199839  * Check for cache miss and clean the object pointer and handle
21426847Svk199839  * in such case. Return 1 for cache hit, 0 for cache miss.
21436847Svk199839  */
check_new_dsa_key_pub(PK11_SESSION * sp,DSA * dsa)21446847Svk199839 static int check_new_dsa_key_pub(PK11_SESSION *sp, DSA *dsa)
21456847Svk199839 	{
21466847Svk199839 	/*
21476847Svk199839 	 * Provide protection against DSA structure reuse by making the
21486847Svk199839 	 * check for cache hit stronger. Only public key component of DSA
21496847Svk199839 	 * key matters here so it is sufficient to compare it with value
21506847Svk199839 	 * cached in PK11_SESSION structure.
21516847Svk199839 	 */
21527526SVladimir.Kotal@Sun.COM 	if ((sp->opdata_dsa_pub != dsa) ||
21537526SVladimir.Kotal@Sun.COM 	    (BN_cmp(sp->opdata_dsa_pub_num, dsa->pub_key) != 0))
21546847Svk199839 		{
21556847Svk199839 		/*
21566847Svk199839 		 * We do not check the return value because even in case of
21576847Svk199839 		 * failure the sp structure will have both key pointer
21586847Svk199839 		 * and object handle cleaned and pk11_destroy_object()
21596847Svk199839 		 * reports the failure to the OpenSSL error message buffer.
21606847Svk199839 		 */
21616847Svk199839 		(void) pk11_destroy_dsa_object_pub(sp, TRUE);
21626847Svk199839 		return (0);
21636847Svk199839 		}
21646847Svk199839 	return (1);
21656847Svk199839 	}
21666847Svk199839 
21676847Svk199839 /*
21686847Svk199839  * Check for cache miss and clean the object pointer and handle
21696847Svk199839  * in such case. Return 1 for cache hit, 0 for cache miss.
21706847Svk199839  */
check_new_dsa_key_priv(PK11_SESSION * sp,DSA * dsa)21716847Svk199839 static int check_new_dsa_key_priv(PK11_SESSION *sp, DSA *dsa)
21726847Svk199839 	{
21736847Svk199839 	/*
21746847Svk199839 	 * Provide protection against DSA structure reuse by making the
21756847Svk199839 	 * check for cache hit stronger. Only private key component of DSA
21766847Svk199839 	 * key matters here so it is sufficient to compare it with value
21776847Svk199839 	 * cached in PK11_SESSION structure.
21786847Svk199839 	 */
21797526SVladimir.Kotal@Sun.COM 	if ((sp->opdata_dsa_priv != dsa) ||
21807526SVladimir.Kotal@Sun.COM 	    (BN_cmp(sp->opdata_dsa_priv_num, dsa->priv_key) != 0))
21816847Svk199839 		{
21826847Svk199839 		/*
21836847Svk199839 		 * We do not check the return value because even in case of
21846847Svk199839 		 * failure the sp structure will have both key pointer
21856847Svk199839 		 * and object handle cleaned and pk11_destroy_object()
21866847Svk199839 		 * reports the failure to the OpenSSL error message buffer.
21876847Svk199839 		 */
21886847Svk199839 		(void) pk11_destroy_dsa_object_priv(sp, TRUE);
21896847Svk199839 		return (0);
21906847Svk199839 		}
21916847Svk199839 	return (1);
21926847Svk199839 	}
21930Sstevel@tonic-gate #endif
21940Sstevel@tonic-gate 
21950Sstevel@tonic-gate 
21960Sstevel@tonic-gate #ifndef OPENSSL_NO_DH
21977616SVladimir.Kotal@Sun.COM /* The DH function implementation */
21987534SVladimir.Kotal@Sun.COM /* ARGSUSED */
pk11_DH_init(DH * dh)21990Sstevel@tonic-gate static int pk11_DH_init(DH *dh)
22000Sstevel@tonic-gate 	{
22017616SVladimir.Kotal@Sun.COM 	return (1);
22020Sstevel@tonic-gate 	}
22030Sstevel@tonic-gate 
22047534SVladimir.Kotal@Sun.COM /* ARGSUSED */
pk11_DH_finish(DH * dh)22050Sstevel@tonic-gate static int pk11_DH_finish(DH *dh)
22060Sstevel@tonic-gate 	{
22076847Svk199839 	return (1);
22080Sstevel@tonic-gate 	}
22090Sstevel@tonic-gate 
22106847Svk199839 /*
22116847Svk199839  * Generate DH key-pair.
22126847Svk199839  *
22136847Svk199839  * Warning: Unlike OpenSSL's DH_generate_key(3) we ignore dh->priv_key
22146847Svk199839  * and override it even if it is set. OpenSSL does not touch dh->priv_key
22156847Svk199839  * if set and just computes dh->pub_key. It looks like PKCS#11 standard
22166847Svk199839  * is not capable of providing this functionality. This could be a problem
22176847Svk199839  * for applications relying on OpenSSL's semantics.
22186847Svk199839  */
pk11_DH_generate_key(DH * dh)22190Sstevel@tonic-gate static int pk11_DH_generate_key(DH *dh)
22200Sstevel@tonic-gate 	{
22210Sstevel@tonic-gate 	CK_ULONG i;
22220Sstevel@tonic-gate 	CK_RV rv, rv1;
22236847Svk199839 	int reuse_mem_len = 0, ret = 0;
22240Sstevel@tonic-gate 	PK11_SESSION *sp = NULL;
22250Sstevel@tonic-gate 	CK_BYTE_PTR reuse_mem;
22260Sstevel@tonic-gate 
22270Sstevel@tonic-gate 	CK_MECHANISM mechanism = {CKM_DH_PKCS_KEY_PAIR_GEN, NULL_PTR, 0};
22280Sstevel@tonic-gate 	CK_OBJECT_HANDLE h_pub_key = CK_INVALID_HANDLE;
22290Sstevel@tonic-gate 	CK_OBJECT_HANDLE h_priv_key = CK_INVALID_HANDLE;
22300Sstevel@tonic-gate 
22317616SVladimir.Kotal@Sun.COM 	CK_ULONG ul_pub_key_attr_count = 3;
22320Sstevel@tonic-gate 	CK_ATTRIBUTE pub_key_template[] =
22330Sstevel@tonic-gate 		{
22347616SVladimir.Kotal@Sun.COM 		{CKA_PRIVATE, &false, sizeof (false)},
22350Sstevel@tonic-gate 		{CKA_PRIME, (void *)NULL, 0},
22360Sstevel@tonic-gate 		{CKA_BASE, (void *)NULL, 0}
22370Sstevel@tonic-gate 		};
22380Sstevel@tonic-gate 
22397616SVladimir.Kotal@Sun.COM 	CK_ULONG ul_priv_key_attr_count = 3;
22400Sstevel@tonic-gate 	CK_ATTRIBUTE priv_key_template[] =
22410Sstevel@tonic-gate 		{
22427616SVladimir.Kotal@Sun.COM 		{CKA_PRIVATE, &false, sizeof (false)},
22437616SVladimir.Kotal@Sun.COM 		{CKA_SENSITIVE, &false, sizeof (false)},
22447616SVladimir.Kotal@Sun.COM 		{CKA_DERIVE, &true, sizeof (true)}
22450Sstevel@tonic-gate 		};
22460Sstevel@tonic-gate 
22470Sstevel@tonic-gate 	CK_ULONG pub_key_attr_result_count = 1;
22480Sstevel@tonic-gate 	CK_ATTRIBUTE pub_key_result[] =
22490Sstevel@tonic-gate 		{
22500Sstevel@tonic-gate 		{CKA_VALUE, (void *)NULL, 0}
22510Sstevel@tonic-gate 		};
22520Sstevel@tonic-gate 
22530Sstevel@tonic-gate 	CK_ULONG priv_key_attr_result_count = 1;
22540Sstevel@tonic-gate 	CK_ATTRIBUTE priv_key_result[] =
22550Sstevel@tonic-gate 		{
22560Sstevel@tonic-gate 		{CKA_VALUE, (void *)NULL, 0}
22570Sstevel@tonic-gate 		};
22580Sstevel@tonic-gate 
22590Sstevel@tonic-gate 	pub_key_template[1].ulValueLen = BN_num_bytes(dh->p);
22600Sstevel@tonic-gate 	if (pub_key_template[1].ulValueLen > 0)
22610Sstevel@tonic-gate 		{
22626847Svk199839 		/*
22636847Svk199839 		 * We must not increase ulValueLen by DH_BUF_RESERVE since that
22646847Svk199839 		 * could cause the same rounding problem. See definition of
22656847Svk199839 		 * DH_BUF_RESERVE above.
22666847Svk199839 		 */
22677616SVladimir.Kotal@Sun.COM 		pub_key_template[1].pValue =
22686847Svk199839 			OPENSSL_malloc(pub_key_template[1].ulValueLen +
22696847Svk199839 			DH_BUF_RESERVE);
22700Sstevel@tonic-gate 		if (pub_key_template[1].pValue == NULL)
22710Sstevel@tonic-gate 			{
22720Sstevel@tonic-gate 			PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
22730Sstevel@tonic-gate 			goto err;
22740Sstevel@tonic-gate 			}
22750Sstevel@tonic-gate 
22760Sstevel@tonic-gate 		i = BN_bn2bin(dh->p, pub_key_template[1].pValue);
22770Sstevel@tonic-gate 		}
22780Sstevel@tonic-gate 	else
22790Sstevel@tonic-gate 		goto err;
22800Sstevel@tonic-gate 
22810Sstevel@tonic-gate 	pub_key_template[2].ulValueLen = BN_num_bytes(dh->g);
22820Sstevel@tonic-gate 	if (pub_key_template[2].ulValueLen > 0)
22830Sstevel@tonic-gate 		{
22847616SVladimir.Kotal@Sun.COM 		pub_key_template[2].pValue =
22856847Svk199839 			OPENSSL_malloc(pub_key_template[2].ulValueLen +
22866847Svk199839 			DH_BUF_RESERVE);
22870Sstevel@tonic-gate 		if (pub_key_template[2].pValue == NULL)
22880Sstevel@tonic-gate 			{
22890Sstevel@tonic-gate 			PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
22900Sstevel@tonic-gate 			goto err;
22910Sstevel@tonic-gate 			}
22920Sstevel@tonic-gate 
22930Sstevel@tonic-gate 		i = BN_bn2bin(dh->g, pub_key_template[2].pValue);
22940Sstevel@tonic-gate 		}
22950Sstevel@tonic-gate 	else
22960Sstevel@tonic-gate 		goto err;
22970Sstevel@tonic-gate 
22986847Svk199839 	/*
22996847Svk199839 	 * Note: we are only using PK11_SESSION structure for getting
23006847Svk199839 	 *	 a session handle. The objects created in this function are
23016847Svk199839 	 *	 destroyed before return and thus not cached.
23026847Svk199839 	 */
23037526SVladimir.Kotal@Sun.COM 	if ((sp = pk11_get_session(OP_DH)) == NULL)
23040Sstevel@tonic-gate 		goto err;
23057616SVladimir.Kotal@Sun.COM 
23060Sstevel@tonic-gate 	rv = pFuncList->C_GenerateKeyPair(sp->session,
23077616SVladimir.Kotal@Sun.COM 	    &mechanism,
23087616SVladimir.Kotal@Sun.COM 	    pub_key_template,
23097616SVladimir.Kotal@Sun.COM 	    ul_pub_key_attr_count,
23107616SVladimir.Kotal@Sun.COM 	    priv_key_template,
23117616SVladimir.Kotal@Sun.COM 	    ul_priv_key_attr_count,
23127616SVladimir.Kotal@Sun.COM 	    &h_pub_key,
23137616SVladimir.Kotal@Sun.COM 	    &h_priv_key);
23140Sstevel@tonic-gate 	if (rv != CKR_OK)
23150Sstevel@tonic-gate 		{
23167211Sjp161948 		PK11err_add_data(PK11_F_DH_GEN_KEY, PK11_R_GEN_KEY, rv);
23170Sstevel@tonic-gate 		goto err;
23180Sstevel@tonic-gate 		}
23190Sstevel@tonic-gate 
23207616SVladimir.Kotal@Sun.COM 	/*
23217616SVladimir.Kotal@Sun.COM 	 * Reuse the larger memory allocated. We know the larger memory
23227616SVladimir.Kotal@Sun.COM 	 * should be sufficient for reuse.
23237616SVladimir.Kotal@Sun.COM 	 */
23240Sstevel@tonic-gate 	if (pub_key_template[1].ulValueLen > pub_key_template[2].ulValueLen)
23256847Svk199839 		{
23260Sstevel@tonic-gate 		reuse_mem = pub_key_template[1].pValue;
23276847Svk199839 		reuse_mem_len = pub_key_template[1].ulValueLen + DH_BUF_RESERVE;
23286847Svk199839 		}
23290Sstevel@tonic-gate 	else
23306847Svk199839 		{
23310Sstevel@tonic-gate 		reuse_mem = pub_key_template[2].pValue;
23326847Svk199839 		reuse_mem_len = pub_key_template[2].ulValueLen + DH_BUF_RESERVE;
23336847Svk199839 		}
23340Sstevel@tonic-gate 
23357526SVladimir.Kotal@Sun.COM 	rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key,
23360Sstevel@tonic-gate 		pub_key_result, pub_key_attr_result_count);
23377526SVladimir.Kotal@Sun.COM 	rv1 = pFuncList->C_GetAttributeValue(sp->session, h_priv_key,
23380Sstevel@tonic-gate 		priv_key_result, priv_key_attr_result_count);
23390Sstevel@tonic-gate 
23400Sstevel@tonic-gate 	if (rv != CKR_OK || rv1 != CKR_OK)
23410Sstevel@tonic-gate 		{
23420Sstevel@tonic-gate 		rv = (rv != CKR_OK) ? rv : rv1;
23437616SVladimir.Kotal@Sun.COM 		PK11err_add_data(PK11_F_DH_GEN_KEY,
23447616SVladimir.Kotal@Sun.COM 		    PK11_R_GETATTRIBUTVALUE, rv);
23450Sstevel@tonic-gate 		goto err;
23460Sstevel@tonic-gate 		}
23470Sstevel@tonic-gate 
23480Sstevel@tonic-gate 	if (((CK_LONG) pub_key_result[0].ulValueLen) <= 0 ||
23490Sstevel@tonic-gate 		((CK_LONG) priv_key_result[0].ulValueLen) <= 0)
23500Sstevel@tonic-gate 		{
23510Sstevel@tonic-gate 		PK11err(PK11_F_DH_GEN_KEY, PK11_R_GETATTRIBUTVALUE);
23520Sstevel@tonic-gate 		goto err;
23530Sstevel@tonic-gate 		}
23547616SVladimir.Kotal@Sun.COM 
23550Sstevel@tonic-gate 	/* Reuse the memory allocated */
23560Sstevel@tonic-gate 	pub_key_result[0].pValue = reuse_mem;
23576847Svk199839 	pub_key_result[0].ulValueLen = reuse_mem_len;
23580Sstevel@tonic-gate 
23597616SVladimir.Kotal@Sun.COM 	rv = pFuncList->C_GetAttributeValue(sp->session, h_pub_key,
23600Sstevel@tonic-gate 		pub_key_result, pub_key_attr_result_count);
23610Sstevel@tonic-gate 
23620Sstevel@tonic-gate 	if (rv != CKR_OK)
23630Sstevel@tonic-gate 		{
23647616SVladimir.Kotal@Sun.COM 		PK11err_add_data(PK11_F_DH_GEN_KEY,
23657616SVladimir.Kotal@Sun.COM 		    PK11_R_GETATTRIBUTVALUE, rv);
23660Sstevel@tonic-gate 		goto err;
23670Sstevel@tonic-gate 		}
23680Sstevel@tonic-gate 
23690Sstevel@tonic-gate 	if (pub_key_result[0].type == CKA_VALUE)
23700Sstevel@tonic-gate 		{
23710Sstevel@tonic-gate 		if (dh->pub_key == NULL)
23726847Svk199839 			if ((dh->pub_key = BN_new()) == NULL)
23736847Svk199839 				{
23746847Svk199839 				PK11err(PK11_F_DH_GEN_KEY,
23756847Svk199839 					PK11_R_MALLOC_FAILURE);
23766847Svk199839 				goto err;
23776847Svk199839 				}
23787616SVladimir.Kotal@Sun.COM 		dh->pub_key = BN_bin2bn(pub_key_result[0].pValue,
23790Sstevel@tonic-gate 			pub_key_result[0].ulValueLen, dh->pub_key);
23807526SVladimir.Kotal@Sun.COM 		if (dh->pub_key == NULL)
23817526SVladimir.Kotal@Sun.COM 			{
23827526SVladimir.Kotal@Sun.COM 			PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
23837526SVladimir.Kotal@Sun.COM 			goto err;
23847526SVladimir.Kotal@Sun.COM 			}
23850Sstevel@tonic-gate 		}
23860Sstevel@tonic-gate 
23870Sstevel@tonic-gate 	/* Reuse the memory allocated */
23880Sstevel@tonic-gate 	priv_key_result[0].pValue = reuse_mem;
23896847Svk199839 	priv_key_result[0].ulValueLen = reuse_mem_len;
23900Sstevel@tonic-gate 
23917616SVladimir.Kotal@Sun.COM 	rv = pFuncList->C_GetAttributeValue(sp->session, h_priv_key,
23920Sstevel@tonic-gate 		priv_key_result, priv_key_attr_result_count);
23930Sstevel@tonic-gate 
23940Sstevel@tonic-gate 	if (rv != CKR_OK)
23950Sstevel@tonic-gate 		{
23967616SVladimir.Kotal@Sun.COM 		PK11err_add_data(PK11_F_DH_GEN_KEY,
23977616SVladimir.Kotal@Sun.COM 		    PK11_R_GETATTRIBUTVALUE, rv);
23980Sstevel@tonic-gate 		goto err;
23990Sstevel@tonic-gate 		}
24000Sstevel@tonic-gate 
24010Sstevel@tonic-gate 	if (priv_key_result[0].type == CKA_VALUE)
24020Sstevel@tonic-gate 		{
24030Sstevel@tonic-gate 		if (dh->priv_key == NULL)
24046847Svk199839 			if ((dh->priv_key = BN_new()) == NULL)
24056847Svk199839 				{
24066847Svk199839 				PK11err(PK11_F_DH_GEN_KEY,
24076847Svk199839 					PK11_R_MALLOC_FAILURE);
24086847Svk199839 				goto err;
24096847Svk199839 				}
24107616SVladimir.Kotal@Sun.COM 		dh->priv_key = BN_bin2bn(priv_key_result[0].pValue,
24110Sstevel@tonic-gate 			priv_key_result[0].ulValueLen, dh->priv_key);
24127526SVladimir.Kotal@Sun.COM 		if (dh->priv_key == NULL)
24137526SVladimir.Kotal@Sun.COM 			{
24147526SVladimir.Kotal@Sun.COM 			PK11err(PK11_F_DH_GEN_KEY, PK11_R_MALLOC_FAILURE);
24157526SVladimir.Kotal@Sun.COM 			goto err;
24167526SVladimir.Kotal@Sun.COM 			}
24170Sstevel@tonic-gate 		}
24180Sstevel@tonic-gate 
24190Sstevel@tonic-gate 	ret = 1;
24200Sstevel@tonic-gate 
24210Sstevel@tonic-gate err:
24227616SVladimir.Kotal@Sun.COM 
24230Sstevel@tonic-gate 	if (h_pub_key != CK_INVALID_HANDLE)
24240Sstevel@tonic-gate 		{
24250Sstevel@tonic-gate 		rv = pFuncList->C_DestroyObject(sp->session, h_pub_key);
24260Sstevel@tonic-gate 		if (rv != CKR_OK)
24270Sstevel@tonic-gate 			{
24287211Sjp161948 			PK11err_add_data(PK11_F_DH_GEN_KEY,
24297211Sjp161948 			    PK11_R_DESTROYOBJECT, rv);
24300Sstevel@tonic-gate 			}
24310Sstevel@tonic-gate 		}
24320Sstevel@tonic-gate 
24330Sstevel@tonic-gate 	if (h_priv_key != CK_INVALID_HANDLE)
24340Sstevel@tonic-gate 		{
24350Sstevel@tonic-gate 		rv = pFuncList->C_DestroyObject(sp->session, h_priv_key);
24360Sstevel@tonic-gate 		if (rv != CKR_OK)
24370Sstevel@tonic-gate 			{
24387211Sjp161948 			PK11err_add_data(PK11_F_DH_GEN_KEY,
24397211Sjp161948 			    PK11_R_DESTROYOBJECT, rv);
24400Sstevel@tonic-gate 			}
24410Sstevel@tonic-gate 		}
24420Sstevel@tonic-gate 
24430Sstevel@tonic-gate 	for (i = 1; i <= 2; i++)
24440Sstevel@tonic-gate 		{
24450Sstevel@tonic-gate 		if (pub_key_template[i].pValue != NULL)
24460Sstevel@tonic-gate 			{
24470Sstevel@tonic-gate 			OPENSSL_free(pub_key_template[i].pValue);
24480Sstevel@tonic-gate 			pub_key_template[i].pValue = NULL;
24490Sstevel@tonic-gate 			}
24500Sstevel@tonic-gate 		}
24510Sstevel@tonic-gate 
24527526SVladimir.Kotal@Sun.COM 	pk11_return_session(sp, OP_DH);
24537616SVladimir.Kotal@Sun.COM 	return (ret);
24540Sstevel@tonic-gate 	}
24550Sstevel@tonic-gate 
pk11_DH_compute_key(unsigned char * key,const BIGNUM * pub_key,DH * dh)24567616SVladimir.Kotal@Sun.COM static int pk11_DH_compute_key(unsigned char *key, const BIGNUM *pub_key,
24577616SVladimir.Kotal@Sun.COM 	DH *dh)
24580Sstevel@tonic-gate 	{
24594245Sjp161948 	int i;
24600Sstevel@tonic-gate 	CK_MECHANISM mechanism = {CKM_DH_PKCS_DERIVE, NULL_PTR, 0};
24610Sstevel@tonic-gate 	CK_OBJECT_CLASS key_class = CKO_SECRET_KEY;
24620Sstevel@tonic-gate 	CK_KEY_TYPE key_type = CKK_GENERIC_SECRET;
24630Sstevel@tonic-gate 	CK_OBJECT_HANDLE h_derived_key = CK_INVALID_HANDLE;
24640Sstevel@tonic-gate 	CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
24650Sstevel@tonic-gate 
24664245Sjp161948 	CK_ULONG ul_priv_key_attr_count = 2;
24670Sstevel@tonic-gate 	CK_ATTRIBUTE priv_key_template[] =
24680Sstevel@tonic-gate 		{
24697616SVladimir.Kotal@Sun.COM 		{CKA_CLASS, (void*) NULL, sizeof (key_class)},
24707616SVladimir.Kotal@Sun.COM 		{CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)},
24710Sstevel@tonic-gate 		};
24720Sstevel@tonic-gate 
24730Sstevel@tonic-gate 	CK_ULONG priv_key_attr_result_count = 1;
24740Sstevel@tonic-gate 	CK_ATTRIBUTE priv_key_result[] =
24750Sstevel@tonic-gate 		{
24760Sstevel@tonic-gate 		{CKA_VALUE, (void *)NULL, 0}
24770Sstevel@tonic-gate 		};
24780Sstevel@tonic-gate 
24790Sstevel@tonic-gate 	CK_RV rv;
24806847Svk199839 	int ret = -1;
24810Sstevel@tonic-gate 	PK11_SESSION *sp = NULL;
24820Sstevel@tonic-gate 
24836847Svk199839 	if (dh->priv_key == NULL)
24846847Svk199839 		goto err;
24856847Svk199839 
24860Sstevel@tonic-gate 	priv_key_template[0].pValue = &key_class;
24870Sstevel@tonic-gate 	priv_key_template[1].pValue = &key_type;
24880Sstevel@tonic-gate 
24897526SVladimir.Kotal@Sun.COM 	if ((sp = pk11_get_session(OP_DH)) == NULL)
24900Sstevel@tonic-gate 		goto err;
24910Sstevel@tonic-gate 
24920Sstevel@tonic-gate 	mechanism.ulParameterLen = BN_num_bytes(pub_key);
24930Sstevel@tonic-gate 	mechanism.pParameter = OPENSSL_malloc(mechanism.ulParameterLen);
24940Sstevel@tonic-gate 	if (mechanism.pParameter == NULL)
24950Sstevel@tonic-gate 		{
24960Sstevel@tonic-gate 		PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE);
24970Sstevel@tonic-gate 		goto err;
24980Sstevel@tonic-gate 		}
2499*11411SSurya.Prakki@Sun.COM 	(void) BN_bn2bin(pub_key, mechanism.pParameter);
25000Sstevel@tonic-gate 
25016847Svk199839 	(void) check_new_dh_key(sp, dh);
25020Sstevel@tonic-gate 
25037526SVladimir.Kotal@Sun.COM 	h_key = sp->opdata_dh_key;
25040Sstevel@tonic-gate 	if (h_key == CK_INVALID_HANDLE)
25057526SVladimir.Kotal@Sun.COM 		h_key = sp->opdata_dh_key =
25067526SVladimir.Kotal@Sun.COM 			pk11_get_dh_key((DH*) dh, &sp->opdata_dh,
25077526SVladimir.Kotal@Sun.COM 			    &sp->opdata_dh_priv_num, sp->session);
25080Sstevel@tonic-gate 
25090Sstevel@tonic-gate 	if (h_key == CK_INVALID_HANDLE)
25100Sstevel@tonic-gate 		{
25110Sstevel@tonic-gate 		PK11err(PK11_F_DH_COMP_KEY, PK11_R_CREATEOBJECT);
25120Sstevel@tonic-gate 		goto err;
25130Sstevel@tonic-gate 		}
25140Sstevel@tonic-gate 
25150Sstevel@tonic-gate 	rv = pFuncList->C_DeriveKey(sp->session,
25167616SVladimir.Kotal@Sun.COM 	    &mechanism,
25177616SVladimir.Kotal@Sun.COM 	    h_key,
25187616SVladimir.Kotal@Sun.COM 	    priv_key_template,
25197616SVladimir.Kotal@Sun.COM 	    ul_priv_key_attr_count,
25207616SVladimir.Kotal@Sun.COM 	    &h_derived_key);
25210Sstevel@tonic-gate 	if (rv != CKR_OK)
25220Sstevel@tonic-gate 		{
25237211Sjp161948 		PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_DERIVEKEY, rv);
25240Sstevel@tonic-gate 		goto err;
25250Sstevel@tonic-gate 		}
25260Sstevel@tonic-gate 
25277616SVladimir.Kotal@Sun.COM 	rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key,
25287616SVladimir.Kotal@Sun.COM 	    priv_key_result, priv_key_attr_result_count);
25290Sstevel@tonic-gate 
25300Sstevel@tonic-gate 	if (rv != CKR_OK)
25310Sstevel@tonic-gate 		{
25327526SVladimir.Kotal@Sun.COM 		PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE,
25337526SVladimir.Kotal@Sun.COM 		    rv);
25340Sstevel@tonic-gate 		goto err;
25350Sstevel@tonic-gate 		}
25360Sstevel@tonic-gate 
25370Sstevel@tonic-gate 	if (((CK_LONG) priv_key_result[0].ulValueLen) <= 0)
25380Sstevel@tonic-gate 		{
25390Sstevel@tonic-gate 		PK11err(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE);
25400Sstevel@tonic-gate 		goto err;
25410Sstevel@tonic-gate 		}
25427616SVladimir.Kotal@Sun.COM 	priv_key_result[0].pValue =
25430Sstevel@tonic-gate 		OPENSSL_malloc(priv_key_result[0].ulValueLen);
25440Sstevel@tonic-gate 	if (!priv_key_result[0].pValue)
25450Sstevel@tonic-gate 		{
25460Sstevel@tonic-gate 		PK11err(PK11_F_DH_COMP_KEY, PK11_R_MALLOC_FAILURE);
25470Sstevel@tonic-gate 		goto err;
25480Sstevel@tonic-gate 		}
25490Sstevel@tonic-gate 
25507616SVladimir.Kotal@Sun.COM 	rv = pFuncList->C_GetAttributeValue(sp->session, h_derived_key,
25510Sstevel@tonic-gate 		priv_key_result, priv_key_attr_result_count);
25520Sstevel@tonic-gate 
25530Sstevel@tonic-gate 	if (rv != CKR_OK)
25540Sstevel@tonic-gate 		{
25557526SVladimir.Kotal@Sun.COM 		PK11err_add_data(PK11_F_DH_COMP_KEY, PK11_R_GETATTRIBUTVALUE,
25567526SVladimir.Kotal@Sun.COM 		    rv);
25570Sstevel@tonic-gate 		goto err;
25580Sstevel@tonic-gate 		}
25590Sstevel@tonic-gate 
25607616SVladimir.Kotal@Sun.COM 	/*
25617616SVladimir.Kotal@Sun.COM 	 * OpenSSL allocates the output buffer 'key' which is the same
25627616SVladimir.Kotal@Sun.COM 	 * length of the public key. It is long enough for the derived key
25637616SVladimir.Kotal@Sun.COM 	 */
25640Sstevel@tonic-gate 	if (priv_key_result[0].type == CKA_VALUE)
25650Sstevel@tonic-gate 		{
25667616SVladimir.Kotal@Sun.COM 		/*
25677616SVladimir.Kotal@Sun.COM 		 * CKM_DH_PKCS_DERIVE mechanism is not supposed to strip
25684245Sjp161948 		 * leading zeros from a computed shared secret. However,
25694245Sjp161948 		 * OpenSSL always did it so we must do the same here. The
25704245Sjp161948 		 * vagueness of the spec regarding leading zero bytes was
25714245Sjp161948 		 * finally cleared with TLS 1.1 (RFC 4346) saying that leading
25724245Sjp161948 		 * zeros are stripped before the computed data is used as the
25734245Sjp161948 		 * pre-master secret.
25744245Sjp161948 		 */
25754245Sjp161948 		for (i = 0; i < priv_key_result[0].ulValueLen; ++i)
25764245Sjp161948 			{
25777616SVladimir.Kotal@Sun.COM 			if (((char *)priv_key_result[0].pValue)[i] != 0)
25784245Sjp161948 				break;
25794245Sjp161948 			}
25804245Sjp161948 
25817616SVladimir.Kotal@Sun.COM 		(void) memcpy(key, ((char *)priv_key_result[0].pValue) + i,
25824245Sjp161948 			priv_key_result[0].ulValueLen - i);
25834245Sjp161948 		ret = priv_key_result[0].ulValueLen - i;
25840Sstevel@tonic-gate 		}
25850Sstevel@tonic-gate 
25860Sstevel@tonic-gate err:
25870Sstevel@tonic-gate 
25880Sstevel@tonic-gate 	if (h_derived_key != CK_INVALID_HANDLE)
25890Sstevel@tonic-gate 		{
25900Sstevel@tonic-gate 		rv = pFuncList->C_DestroyObject(sp->session, h_derived_key);
25910Sstevel@tonic-gate 		if (rv != CKR_OK)
25920Sstevel@tonic-gate 			{
25937211Sjp161948 			PK11err_add_data(PK11_F_DH_COMP_KEY,
25947211Sjp161948 			    PK11_R_DESTROYOBJECT, rv);
25950Sstevel@tonic-gate 			}
25960Sstevel@tonic-gate 		}
25970Sstevel@tonic-gate 	if (priv_key_result[0].pValue)
25987526SVladimir.Kotal@Sun.COM 		{
25990Sstevel@tonic-gate 		OPENSSL_free(priv_key_result[0].pValue);
26000Sstevel@tonic-gate 		priv_key_result[0].pValue = NULL;
26010Sstevel@tonic-gate 		}
26020Sstevel@tonic-gate 
26030Sstevel@tonic-gate 	if (mechanism.pParameter)
26040Sstevel@tonic-gate 		{
26050Sstevel@tonic-gate 		OPENSSL_free(mechanism.pParameter);
26060Sstevel@tonic-gate 		mechanism.pParameter = NULL;
26070Sstevel@tonic-gate 		}
26080Sstevel@tonic-gate 
26097526SVladimir.Kotal@Sun.COM 	pk11_return_session(sp, OP_DH);
26107616SVladimir.Kotal@Sun.COM 	return (ret);
26110Sstevel@tonic-gate 	}
26120Sstevel@tonic-gate 
26130Sstevel@tonic-gate 
pk11_get_dh_key(DH * dh,DH ** key_ptr,BIGNUM ** dh_priv_num,CK_SESSION_HANDLE session)26146847Svk199839 static CK_OBJECT_HANDLE pk11_get_dh_key(DH* dh,
26156847Svk199839 	DH **key_ptr, BIGNUM **dh_priv_num, CK_SESSION_HANDLE session)
26160Sstevel@tonic-gate 	{
26170Sstevel@tonic-gate 	CK_RV rv;
26180Sstevel@tonic-gate 	CK_OBJECT_HANDLE h_key = CK_INVALID_HANDLE;
26190Sstevel@tonic-gate 	CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
26200Sstevel@tonic-gate 	CK_KEY_TYPE key_type = CKK_DH;
26210Sstevel@tonic-gate 	CK_ULONG found;
26227526SVladimir.Kotal@Sun.COM 	CK_BBOOL rollback = FALSE;
26230Sstevel@tonic-gate 	int i;
26240Sstevel@tonic-gate 
26250Sstevel@tonic-gate 	CK_ULONG ul_key_attr_count = 7;
26260Sstevel@tonic-gate 	CK_ATTRIBUTE key_template[] =
26270Sstevel@tonic-gate 		{
26287616SVladimir.Kotal@Sun.COM 		{CKA_CLASS, (void*) NULL, sizeof (class)},
26297616SVladimir.Kotal@Sun.COM 		{CKA_KEY_TYPE, (void*) NULL, sizeof (key_type)},
26307616SVladimir.Kotal@Sun.COM 		{CKA_DERIVE, &true, sizeof (true)},
26317616SVladimir.Kotal@Sun.COM 		{CKA_PRIVATE, &false, sizeof (false)},
26320Sstevel@tonic-gate 		{CKA_PRIME, (void *) NULL, 0},
26330Sstevel@tonic-gate 		{CKA_BASE, (void *) NULL, 0},
26340Sstevel@tonic-gate 		{CKA_VALUE, (void *) NULL, 0},
26350Sstevel@tonic-gate 		};
26360Sstevel@tonic-gate 
26370Sstevel@tonic-gate 	key_template[0].pValue = &class;
26380Sstevel@tonic-gate 	key_template[1].pValue = &key_type;
26390Sstevel@tonic-gate 
26400Sstevel@tonic-gate 	key_template[4].ulValueLen = BN_num_bytes(dh->p);
26410Sstevel@tonic-gate 	key_template[4].pValue = (CK_VOID_PTR)OPENSSL_malloc(
26420Sstevel@tonic-gate 		(size_t)key_template[4].ulValueLen);
26430Sstevel@tonic-gate 	if (key_template[4].pValue == NULL)
26440Sstevel@tonic-gate 		{
26450Sstevel@tonic-gate 		PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
26467526SVladimir.Kotal@Sun.COM 		goto malloc_err;
26470Sstevel@tonic-gate 		}
26480Sstevel@tonic-gate 
2649*11411SSurya.Prakki@Sun.COM 	(void) BN_bn2bin(dh->p, key_template[4].pValue);
26500Sstevel@tonic-gate 
26510Sstevel@tonic-gate 	key_template[5].ulValueLen = BN_num_bytes(dh->g);
26520Sstevel@tonic-gate 	key_template[5].pValue = (CK_VOID_PTR)OPENSSL_malloc(
26530Sstevel@tonic-gate 		(size_t)key_template[5].ulValueLen);
26540Sstevel@tonic-gate 	if (key_template[5].pValue == NULL)
26550Sstevel@tonic-gate 		{
26560Sstevel@tonic-gate 		PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
26577526SVladimir.Kotal@Sun.COM 		goto malloc_err;
26580Sstevel@tonic-gate 		}
26590Sstevel@tonic-gate 
2660*11411SSurya.Prakki@Sun.COM 	(void) BN_bn2bin(dh->g, key_template[5].pValue);
26610Sstevel@tonic-gate 
26620Sstevel@tonic-gate 	key_template[6].ulValueLen = BN_num_bytes(dh->priv_key);
26630Sstevel@tonic-gate 	key_template[6].pValue = (CK_VOID_PTR)OPENSSL_malloc(
26640Sstevel@tonic-gate 		(size_t)key_template[6].ulValueLen);
26650Sstevel@tonic-gate 	if (key_template[6].pValue == NULL)
26660Sstevel@tonic-gate 		{
26670Sstevel@tonic-gate 		PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
26687526SVladimir.Kotal@Sun.COM 		goto malloc_err;
26690Sstevel@tonic-gate 		}
26700Sstevel@tonic-gate 
2671*11411SSurya.Prakki@Sun.COM 	(void) BN_bn2bin(dh->priv_key, key_template[6].pValue);
26720Sstevel@tonic-gate 
26737526SVladimir.Kotal@Sun.COM 	/* see find_lock array definition for more info on object locking */
26747526SVladimir.Kotal@Sun.COM 	LOCK_OBJSTORE(OP_DH);
26757616SVladimir.Kotal@Sun.COM 	rv = pFuncList->C_FindObjectsInit(session, key_template,
26760Sstevel@tonic-gate 		ul_key_attr_count);
26770Sstevel@tonic-gate 
26780Sstevel@tonic-gate 	if (rv != CKR_OK)
26790Sstevel@tonic-gate 		{
26807211Sjp161948 		PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSINIT, rv);
26810Sstevel@tonic-gate 		goto err;
26820Sstevel@tonic-gate 		}
26830Sstevel@tonic-gate 
26840Sstevel@tonic-gate 	rv = pFuncList->C_FindObjects(session, &h_key, 1, &found);
26850Sstevel@tonic-gate 
26860Sstevel@tonic-gate 	if (rv != CKR_OK)
26870Sstevel@tonic-gate 		{
26887211Sjp161948 		PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTS, rv);
26890Sstevel@tonic-gate 		goto err;
26900Sstevel@tonic-gate 		}
26910Sstevel@tonic-gate 
26920Sstevel@tonic-gate 	rv = pFuncList->C_FindObjectsFinal(session);
26930Sstevel@tonic-gate 
26940Sstevel@tonic-gate 	if (rv != CKR_OK)
26950Sstevel@tonic-gate 		{
26967526SVladimir.Kotal@Sun.COM 		PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_FINDOBJECTSFINAL,
26977526SVladimir.Kotal@Sun.COM 		    rv);
26980Sstevel@tonic-gate 		goto err;
26990Sstevel@tonic-gate 		}
27000Sstevel@tonic-gate 
27010Sstevel@tonic-gate 	if (found == 0)
27020Sstevel@tonic-gate 		{
27037616SVladimir.Kotal@Sun.COM 		rv = pFuncList->C_CreateObject(session,
27040Sstevel@tonic-gate 			key_template, ul_key_attr_count, &h_key);
27050Sstevel@tonic-gate 		if (rv != CKR_OK)
27060Sstevel@tonic-gate 			{
27077211Sjp161948 			PK11err_add_data(PK11_F_GET_DH_KEY, PK11_R_CREATEOBJECT,
27087211Sjp161948 			    rv);
27090Sstevel@tonic-gate 			goto err;
27100Sstevel@tonic-gate 			}
27110Sstevel@tonic-gate 		}
27120Sstevel@tonic-gate 
27136847Svk199839 	if (dh_priv_num != NULL)
27146847Svk199839 		if ((*dh_priv_num = BN_dup(dh->priv_key)) == NULL)
27156847Svk199839 			{
27166847Svk199839 			PK11err(PK11_F_GET_DH_KEY, PK11_R_MALLOC_FAILURE);
27177526SVladimir.Kotal@Sun.COM 			rollback = TRUE;
27186847Svk199839 			goto err;
27196847Svk199839 			}
27207526SVladimir.Kotal@Sun.COM 
27217534SVladimir.Kotal@Sun.COM 	/* LINTED: E_CONSTANT_CONDITION */
27227526SVladimir.Kotal@Sun.COM 	KEY_HANDLE_REFHOLD(h_key, OP_DH, FALSE, rollback, err);
27237526SVladimir.Kotal@Sun.COM 	if (key_ptr != NULL)
27247526SVladimir.Kotal@Sun.COM 		*key_ptr = dh;
27250Sstevel@tonic-gate 
27266847Svk199839 err:
27277526SVladimir.Kotal@Sun.COM 	if (rollback)
27287526SVladimir.Kotal@Sun.COM 		{
27297628SVladimir.Kotal@Sun.COM 		/*
27307628SVladimir.Kotal@Sun.COM 		 * We do not care about the return value from C_DestroyObject()
27317628SVladimir.Kotal@Sun.COM 		 * since we are doing rollback.
27327628SVladimir.Kotal@Sun.COM 		 */
27337526SVladimir.Kotal@Sun.COM 		if (found == 0)
27347526SVladimir.Kotal@Sun.COM 			(void) pFuncList->C_DestroyObject(session, h_key);
27357526SVladimir.Kotal@Sun.COM 		h_key = CK_INVALID_HANDLE;
27367526SVladimir.Kotal@Sun.COM 		}
27377526SVladimir.Kotal@Sun.COM 
27387526SVladimir.Kotal@Sun.COM 	UNLOCK_OBJSTORE(OP_DH);
27397526SVladimir.Kotal@Sun.COM 
27407526SVladimir.Kotal@Sun.COM malloc_err:
27410Sstevel@tonic-gate 	for (i = 4; i <= 6; i++)
27420Sstevel@tonic-gate 		{
27430Sstevel@tonic-gate 		if (key_template[i].pValue != NULL)
27440Sstevel@tonic-gate 			{
27450Sstevel@tonic-gate 			OPENSSL_free(key_template[i].pValue);
27460Sstevel@tonic-gate 			key_template[i].pValue = NULL;
27470Sstevel@tonic-gate 			}
27480Sstevel@tonic-gate 		}
27490Sstevel@tonic-gate 
27507616SVladimir.Kotal@Sun.COM 	return (h_key);
27510Sstevel@tonic-gate 	}
27520Sstevel@tonic-gate 
27536847Svk199839 /*
27546847Svk199839  * Check for cache miss and clean the object pointer and handle
27556847Svk199839  * in such case. Return 1 for cache hit, 0 for cache miss.
27566847Svk199839  *
27577526SVladimir.Kotal@Sun.COM  * Note: we rely on pk11_destroy_dh_key_objects() to set sp->opdata_dh
27586847Svk199839  *       to CK_INVALID_HANDLE even when it fails to destroy the object.
27596847Svk199839  */
check_new_dh_key(PK11_SESSION * sp,DH * dh)27606847Svk199839 static int check_new_dh_key(PK11_SESSION *sp, DH *dh)
27616847Svk199839 	{
27626847Svk199839 	/*
27636847Svk199839 	 * Provide protection against DH structure reuse by making the
27646847Svk199839 	 * check for cache hit stronger. Private key component of DH key
27656847Svk199839 	 * is unique so it is sufficient to compare it with value cached
27666847Svk199839 	 * in PK11_SESSION structure.
27676847Svk199839 	 */
27687526SVladimir.Kotal@Sun.COM 	if ((sp->opdata_dh != dh) ||
27697526SVladimir.Kotal@Sun.COM 	    (BN_cmp(sp->opdata_dh_priv_num, dh->priv_key) != 0))
27706847Svk199839 		{
27716847Svk199839 		/*
27726847Svk199839 		 * We do not check the return value because even in case of
27736847Svk199839 		 * failure the sp structure will have both key pointer
27746847Svk199839 		 * and object handle cleaned and pk11_destroy_object()
27756847Svk199839 		 * reports the failure to the OpenSSL error message buffer.
27766847Svk199839 		 */
27776847Svk199839 		(void) pk11_destroy_dh_object(sp, TRUE);
27786847Svk199839 		return (0);
27796847Svk199839 		}
27806847Svk199839 	return (1);
27816847Svk199839 	}
27820Sstevel@tonic-gate #endif
27830Sstevel@tonic-gate 
27847616SVladimir.Kotal@Sun.COM /*
27857616SVladimir.Kotal@Sun.COM  * Local function to simplify key template population
27860Sstevel@tonic-gate  * Return 0 -- error, 1 -- no error
27870Sstevel@tonic-gate  */
init_template_value(BIGNUM * bn,CK_VOID_PTR * p_value,CK_ULONG * ul_value_len)27887616SVladimir.Kotal@Sun.COM static int init_template_value(BIGNUM *bn, CK_VOID_PTR *p_value,
27890Sstevel@tonic-gate 	CK_ULONG *ul_value_len)
27900Sstevel@tonic-gate 	{
27910Sstevel@tonic-gate 	CK_ULONG len = BN_num_bytes(bn);
27920Sstevel@tonic-gate 	if (len == 0)
27937616SVladimir.Kotal@Sun.COM 		return (1);
27940Sstevel@tonic-gate 
27950Sstevel@tonic-gate 	*ul_value_len = len;
27967616SVladimir.Kotal@Sun.COM 	*p_value = (CK_VOID_PTR)OPENSSL_malloc((size_t)*ul_value_len);
27970Sstevel@tonic-gate 	if (*p_value == NULL)
27987616SVladimir.Kotal@Sun.COM 		return (0);
27990Sstevel@tonic-gate 
2800*11411SSurya.Prakki@Sun.COM 	(void) BN_bn2bin(bn, *p_value);
28010Sstevel@tonic-gate 
28027616SVladimir.Kotal@Sun.COM 	return (1);
28030Sstevel@tonic-gate 	}
28047211Sjp161948 
28057211Sjp161948 #endif	/* OPENSSL_NO_HW_PK11 */
28067211Sjp161948 #endif	/* OPENSSL_NO_HW */
2807