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 = ¶meter;
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 = ¶meter;
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