changeset 3408:67ca9373b99e

6501154 kssladm could use KMF
author wyllys
date Thu, 11 Jan 2007 18:12:31 -0800
parents d9ac3b8746e4
children 95e86faf5436
files usr/src/cmd/cmd-crypto/pktool/delete.c usr/src/cmd/cmd-crypto/pktool/list.c usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/Makefile usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm.h usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm_create.c usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/ksslutil.c usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/openssl_util.c usr/src/lib/libkmf/include/kmfapi.h usr/src/lib/libkmf/include/kmftypes.h usr/src/lib/libkmf/libkmf/common/certop.c usr/src/lib/libkmf/libkmf/common/generalop.c usr/src/lib/libkmf/libkmf/common/mapfile-vers usr/src/lib/libkmf/libkmf/common/pk11tokens.c usr/src/lib/libkmf/plugins/kmf_openssl/common/mapfile-vers usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c
diffstat 16 files changed, 1209 insertions(+), 1204 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/cmd-crypto/pktool/delete.c	Thu Jan 11 16:21:40 2007 -0800
+++ b/usr/src/cmd/cmd-crypto/pktool/delete.c	Thu Jan 11 18:12:31 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -280,6 +280,7 @@
 	parms.findLabel = (char *)objlabel;
 	parms.keytype = 0;
 	parms.pkcs11parms.private = ((oclass & PK_PRIVATE_OBJ) > 0);
+	parms.pkcs11parms.token = 1;
 	parms.cred.cred = tokencred->cred;
 	parms.cred.credlen = tokencred->credlen;
 
--- a/usr/src/cmd/cmd-crypto/pktool/list.c	Thu Jan 11 16:21:40 2007 -0800
+++ b/usr/src/cmd/cmd-crypto/pktool/list.c	Thu Jan 11 18:12:31 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -291,6 +291,7 @@
 			parms.cred = *tokencred;
 			parms.pkcs11parms.private =
 				((oclass & PK_PRIVATE_OBJ) > 0);
+			parms.pkcs11parms.token = 1;
 
 			/* list asymmetric private keys */
 			rv = pk_list_keys(kmfhandle, &parms);
@@ -303,6 +304,7 @@
 			parms.format = KMF_FORMAT_RAWKEY;
 			parms.pkcs11parms.private =
 				((oclass & PK_PRIVATE_OBJ) > 0);
+			parms.pkcs11parms.token = 1;
 
 			/* list symmetric keys */
 			rv = pk_list_keys(kmfhandle, &parms);
@@ -313,6 +315,7 @@
 			parms.findLabel = objlabel;
 			parms.pkcs11parms.private =
 				((oclass & PK_PRIVATE_OBJ) > 0);
+			parms.pkcs11parms.token = 1;
 
 			/* list asymmetric public keys (if any) */
 			rv = pk_list_keys(kmfhandle, &parms);
--- a/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/Makefile	Thu Jan 11 16:21:40 2007 -0800
+++ b/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/Makefile	Thu Jan 11 18:12:31 2007 -0800
@@ -2,9 +2,8 @@
 # CDDL HEADER START
 #
 # The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License").  You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
 #
 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 # or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 # 
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -31,13 +30,12 @@
 PROG= kssladm
 
 include $(SRC)/cmd/Makefile.cmd
-include $(SRC)/lib/openssl/Makefile.openssl
 
 OBJS =	\
     kssladm.o \
     kssladm_create.o \
     kssladm_delete.o \
-    openssl_util.o
+    ksslutil.o
 
 SRCS = $(OBJS:%.o=%.c)
 
@@ -47,12 +45,7 @@
 
 CFLAGS +=	$(CCVERBOSE)
 
-CPPFLAGS += $(OPENSSL_CPPFLAGS)
-DYNFLAGS += $(OPENSSL_DYNFLAGS)
-LDFLAGS += $(OPENSSL_LDFLAGS)
-LINTFLAGS += $(OPENSSL_LDFLAGS)
-
-LDLIBS += -lnsl -lpkcs11 -lcrypto -lcryptoutil
+LDLIBS += -lkmf -lpkcs11 -lcryptoutil -lnsl
 
 all: $(PROG)
 
--- a/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm.h	Thu Jan 11 16:21:40 2007 -0800
+++ b/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm.h	Thu Jan 11 18:12:31 2007 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -38,13 +38,21 @@
 #endif
 
 #include <netinet/in.h>
-#include <openssl/rsa.h>
+#include <kmfapi.h>
 
 #define	SUCCESS		0
 #define	FAILURE		1
 #define	ERROR_USAGE	2
 
 #define	MAX_CHAIN_LENGTH	12
+#define	REPORT_KMF_ERROR(r, t, e) { \
+	(void) KMF_GetKMFErrorString(r, &e); \
+	(void) fprintf(stderr, t ": %s\n", \
+		(e != NULL ? e : "<unknown error>")); \
+	if (e) free(e); \
+}
+
+#define	MAX_ATTR_CNT	8
 
 extern boolean_t verbose;
 
@@ -53,11 +61,12 @@
 extern void usage_create(boolean_t do_print);
 extern void usage_delete(boolean_t do_print);
 
-extern uchar_t *get_modulus(uchar_t *ber_buf, int buflen, int *modlen);
-extern uchar_t **PEM_get_rsa_key_certs(const char *filename,
-    char *password_file, RSA **rsa, int **cert_sizes, int *ncerts);
-extern uchar_t **PKCS12_get_rsa_key_certs(const char *filename,
-    const char *password_file, RSA **rsa, int **cert_sizes, int *ncerts);
+extern int PEM_get_rsa_key_certs(const char *,
+    char *, KMF_RAW_KEY_DATA **, KMF_DATA **);
+
+extern int PKCS12_get_rsa_key_certs(const char *,
+    const char *, KMF_RAW_KEY_DATA **, KMF_DATA **);
+
 extern int get_passphrase(const char *password_file, char *buf, int buf_size);
 extern int kssl_send_command(char *buf, int cmd);
 extern int parse_and_set_addr(char *arg1, char *arg2, struct sockaddr_in *addr);
--- a/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm_create.c	Thu Jan 11 16:21:40 2007 -0800
+++ b/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/kssladm_create.c	Thu Jan 11 18:12:31 2007 -0800
@@ -20,28 +20,32 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
-#include <arpa/inet.h>
 #include <errno.h>
 #include <sys/sysmacros.h>
-#include <netdb.h> /* hostent */
-#include <netinet/in.h>
-#include <openssl/rsa.h>
 #include <security/cryptoki.h>
 #include <security/pkcs11.h>
-#include <cryptoutil.h>
 #include <stdio.h>
 #include <strings.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <inet/kssl/kssl.h>
+#include <cryptoutil.h>
 #include <libscf.h>
-#include <inet/kssl/kssl.h>
 #include "kssladm.h"
 
+#include <kmfapi.h>
+
 void
 usage_create(boolean_t do_print)
 {
@@ -69,56 +73,6 @@
 		"\t[-v]\n");
 }
 
-static uchar_t *
-get_cert_val(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE cert_obj, int *len)
-{
-	CK_RV rv;
-	uchar_t *buf;
-	CK_ATTRIBUTE cert_attrs[] = {{CKA_VALUE, NULL_PTR, 0}};
-
-	/* the certs ... */
-	rv = C_GetAttributeValue(sess, cert_obj, cert_attrs, 1);
-	if (rv != CKR_OK) {
-		(void) fprintf(stderr, "Cannot get cert size."
-		    " error = %s\n", pkcs11_strerror(rv));
-		return (NULL);
-	}
-
-	buf = malloc(cert_attrs[0].ulValueLen);
-	if (buf == NULL)
-		return (NULL);
-	cert_attrs[0].pValue = buf;
-
-	rv = C_GetAttributeValue(sess, cert_obj, cert_attrs, 1);
-	if (rv != CKR_OK) {
-		(void) fprintf(stderr, "Cannot get cert value."
-		    " error = %s\n", pkcs11_strerror(rv));
-		free(buf);
-		return (NULL);
-	}
-
-	*len = cert_attrs[0].ulValueLen;
-	return (buf);
-}
-
-#define	OPT_ATTR_CNT	6
-#define	MAX_ATTR_CNT	16
-
-int known_attr_cnt = 0;
-
-#define	CKA_TOKEN_INDEX	1
-/*
- * The order of the attributes must stay in the same order
- * as in the attribute template, privkey_tmpl, in load_from_pkcs11().
- */
-CK_ATTRIBUTE key_gattrs[MAX_ATTR_CNT] = {
-	{CKA_MODULUS, NULL_PTR, 0},
-	{CKA_TOKEN, NULL_PTR, 0},
-	{CKA_CLASS, NULL_PTR, 0},
-	{CKA_KEY_TYPE, NULL_PTR, 0},
-};
-CK_ATTRIBUTE known_cert_attrs[1];
-
 /*
  * Everything is allocated in one single contiguous buffer.
  * The layout is the following:
@@ -134,522 +88,28 @@
  * to sc_sizes[0] and sc_certs_offset points to sc_certs[0].
  */
 static kssl_params_t *
-pkcs11_to_kssl(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE privkey_obj,
-    boolean_t is_nxkey, int *paramsize, char *label, char *pin, int pinlen)
-{
-	int i;
-	CK_RV rv;
-	int total_attr_cnt;
-	uint32_t cert_size, bufsize;
-	char *buf;
-	kssl_key_t *key;
-	kssl_params_t *kssl_params;
-	CK_ATTRIBUTE privkey_opt_attrs[OPT_ATTR_CNT] = {
-		{CKA_PUBLIC_EXPONENT, NULL_PTR, 0},
-		{CKA_PRIME_1, NULL_PTR, 0},
-		{CKA_PRIME_2, NULL_PTR, 0},
-		{CKA_EXPONENT_1, NULL_PTR, 0},
-		{CKA_EXPONENT_2, NULL_PTR, 0},
-		{CKA_COEFFICIENT, NULL_PTR, 0}
-	};
-	kssl_object_attribute_t kssl_attrs[MAX_ATTR_CNT];
-
-	/* Get the certificate size */
-	bufsize = sizeof (kssl_params_t);
-	cert_size = (uint32_t)known_cert_attrs[0].ulValueLen;
-	bufsize += cert_size + MAX_CHAIN_LENGTH * sizeof (uint32_t);
-
-	/* These are attributes for which we have the value and length */
-	for (i = 0; i < known_attr_cnt; i++) {
-		bufsize += sizeof (crypto_object_attribute_t) +
-		    key_gattrs[i].ulValueLen;
-	}
-	total_attr_cnt = known_attr_cnt;
-
-	if (!is_nxkey) {
-		/* Add CKA_PRIVATE_EXPONENT for extractable key */
-		key_gattrs[total_attr_cnt].type = CKA_PRIVATE_EXPONENT;
-		key_gattrs[total_attr_cnt].pValue  = NULL_PTR;
-		key_gattrs[total_attr_cnt].ulValueLen = 0;
-
-		rv = C_GetAttributeValue(sess, privkey_obj,
-		    &key_gattrs[total_attr_cnt], 1);
-		if (rv != CKR_OK) {
-			(void) fprintf(stderr,
-			    "Cannot get private key object attribute."
-			    " error = %s\n", pkcs11_strerror(rv));
-			return (NULL);
-		}
-
-		bufsize += sizeof (crypto_object_attribute_t) +
-		    key_gattrs[total_attr_cnt].ulValueLen;
-		total_attr_cnt++;
-	}
-
-	/*
-	 * Get the optional key attributes. The return values could be
-	 * CKR_ATTRIBUTE_TYPE_INVALID with ulValueLen set to -1 OR
-	 * CKR_OK with ulValueLen set to 0. The latter is done by
-	 * soft token and seems dubious.
-	 */
-	if (!is_nxkey) {
-		rv = C_GetAttributeValue(sess, privkey_obj, privkey_opt_attrs,
-		    OPT_ATTR_CNT);
-		if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID) {
-			(void) fprintf(stderr,
-			    "Cannot get private key object attributes."
-			    " error = %s\n", pkcs11_strerror(rv));
-			return (NULL);
-		}
-
-		for (i = 0; i < OPT_ATTR_CNT; i++) {
-			if (privkey_opt_attrs[i].ulValueLen == (CK_ULONG)-1 ||
-			    privkey_opt_attrs[i].ulValueLen == 0)
-				continue;
-			/* Structure copy */
-			key_gattrs[total_attr_cnt] = privkey_opt_attrs[i];
-			bufsize += sizeof (crypto_object_attribute_t) +
-			    privkey_opt_attrs[i].ulValueLen;
-			total_attr_cnt++;
-		}
-	} else
-		bufsize += pinlen;
-
-	/* Add 4-byte cushion as sc_sizes[0] needs 32-bit alignment */
-	bufsize += sizeof (uint32_t);
-
-	/* Now the big memory allocation */
-	if ((buf = calloc(bufsize, 1)) == NULL) {
-		(void) fprintf(stderr,
-			"Cannot allocate memory for the kssl_params "
-			"and values\n");
-		return (NULL);
-	}
-
-	/* LINTED */
-	kssl_params = (kssl_params_t *)buf;
-
-	buf = (char *)(kssl_params + 1);
-
-	if (is_nxkey) {
-		kssl_params->kssl_is_nxkey = 1;
-		bcopy(label, kssl_params->kssl_token.toklabel,
-		    CRYPTO_EXT_SIZE_LABEL);
-		kssl_params->kssl_token.pinlen = pinlen;
-		kssl_params->kssl_token.tokpin_offset =
-		    buf - (char *)kssl_params;
-		kssl_params->kssl_token.ck_rv = 0;
-		bcopy(pin, buf, pinlen);
-		buf += pinlen;
-	}
-
-	/* the keys attributes structs array */
-	key = &kssl_params->kssl_privkey;
-	key->ks_format = CRYPTO_KEY_ATTR_LIST;
-	key->ks_count = total_attr_cnt;
-	key->ks_attrs_offset = buf - (char *)kssl_params;
-	buf += total_attr_cnt * sizeof (kssl_object_attribute_t);
-
-	/* These are attributes for which we already have the value */
-	for (i = 0; i < known_attr_cnt; i++) {
-		bcopy(key_gattrs[i].pValue, buf, key_gattrs[i].ulValueLen);
-		kssl_attrs[i].ka_type = key_gattrs[i].type;
-		kssl_attrs[i].ka_value_offset = buf - (char *)kssl_params;
-		kssl_attrs[i].ka_value_len = key_gattrs[i].ulValueLen;
-		buf += key_gattrs[i].ulValueLen;
-	}
-
-	if (total_attr_cnt > known_attr_cnt) {
-		/* These are attributes for which we need to get the value */
-		for (i = known_attr_cnt; i < total_attr_cnt; i++) {
-			key_gattrs[i].pValue = buf;
-			kssl_attrs[i].ka_type = key_gattrs[i].type;
-			kssl_attrs[i].ka_value_offset =
-			    buf - (char *)kssl_params;
-			kssl_attrs[i].ka_value_len = key_gattrs[i].ulValueLen;
-			buf += key_gattrs[i].ulValueLen;
-		}
-
-		rv = C_GetAttributeValue(sess, privkey_obj,
-		    &key_gattrs[known_attr_cnt],
-		    total_attr_cnt - known_attr_cnt);
-		if (rv != CKR_OK) {
-			(void) fprintf(stderr,
-			    "Cannot get private key object attributes."
-			    " error = %s\n", pkcs11_strerror(rv));
-			return (NULL);
-		}
-	}
-
-	bcopy(kssl_attrs, ((char *)kssl_params) + key->ks_attrs_offset,
-	    total_attr_cnt * sizeof (kssl_object_attribute_t));
-
-	buf = (char *)P2ROUNDUP((uintptr_t)buf, sizeof (uint32_t));
-	kssl_params->kssl_certs.sc_count = 1;
-	bcopy(&cert_size, buf, sizeof (uint32_t));
-	kssl_params->kssl_certs.sc_sizes_offset = buf - (char *)kssl_params;
-	buf += MAX_CHAIN_LENGTH * sizeof (uint32_t);
-
-	/* now the certs values */
-	bcopy(known_cert_attrs[0].pValue, buf, known_cert_attrs[0].ulValueLen);
-	free(known_cert_attrs[0].pValue);
-	kssl_params->kssl_certs.sc_certs_offset = buf - (char *)kssl_params;
-
-	*paramsize = bufsize;
-	bzero(pin, pinlen);
-	(void) C_Logout(sess);
-	(void) C_CloseSession(sess);
-	return (kssl_params);
-}
-
-#define	max_num_cert 32
-
-static kssl_params_t *
-load_from_pkcs11(const char *token_label, const char *password_file,
-    const char *certname, int *bufsize)
-{
-	static CK_BBOOL true = TRUE;
-	static CK_BBOOL false = FALSE;
-
-	CK_RV rv;
-	CK_SLOT_ID slot;
-	CK_SLOT_ID_PTR	pk11_slots;
-	CK_ULONG slotcnt = 10;
-	CK_TOKEN_INFO	token_info;
-	CK_SESSION_HANDLE sess;
-	static CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE;
-	static CK_CERTIFICATE_TYPE cert_type = CKC_X_509;
-	CK_ATTRIBUTE cert_tmpl[4] = {
-		{CKA_TOKEN, &true, sizeof (true)},
-		{CKA_LABEL, NULL_PTR, 0},
-		{CKA_CLASS, &cert_class, sizeof (cert_class)},
-		{CKA_CERTIFICATE_TYPE, &cert_type, sizeof (cert_type)}
-	};
-	CK_ULONG cert_tmpl_count = 4, cert_obj_count = 1;
-	CK_OBJECT_HANDLE cert_obj, privkey_obj;
-	CK_OBJECT_HANDLE cert_objs[max_num_cert];
-	static CK_OBJECT_CLASS privkey_class = CKO_PRIVATE_KEY;
-	static CK_KEY_TYPE privkey_type = CKK_RSA;
-	CK_ATTRIBUTE privkey_tmpl[] = {
-		/*
-		 * The order of attributes must stay in the same order
-		 * as in the global attribute array, key_gattrs.
-		 */
-		{CKA_MODULUS, NULL_PTR, 0},
-		{CKA_TOKEN, &true, sizeof (true)},
-		{CKA_CLASS, &privkey_class, sizeof (privkey_class)},
-		{CKA_KEY_TYPE, &privkey_type, sizeof (privkey_type)}
-	};
-	CK_ULONG privkey_tmpl_count = 4, privkey_obj_count = 1;
-	CK_BBOOL is_extractable;
-	CK_ATTRIBUTE privkey_attrs[1] = {
-		{CKA_EXTRACTABLE, NULL_PTR, 0},
-	};
-	boolean_t bingo = B_FALSE;
-	int i, blen, mlen;
-	uchar_t *mval, *ber_buf;
-	char token_label_padded[sizeof (token_info.label) + 1];
-	char passphrase[MAX_PIN_LENGTH];
-	CK_ULONG ulPinLen;
-
-	(void) snprintf(token_label_padded, sizeof (token_label_padded),
-		"%-32s", token_label);
-
-	rv = C_Initialize(NULL_PTR);
-
-	if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
-		(void) fprintf(stderr,
-		    "Cannot initialize PKCS#11. error = %s\n",
-		    pkcs11_strerror(rv));
-		return (NULL);
-	}
-
-	/* Get slot count */
-	rv = C_GetSlotList(1, NULL_PTR, &slotcnt);
-	if (rv != CKR_OK || slotcnt == 0) {
-		(void) fprintf(stderr,
-		    "Cannot get PKCS#11 slot list. error = %s\n",
-		    pkcs11_strerror(rv));
-		return (NULL);
-	}
-
-	pk11_slots = calloc(slotcnt, sizeof (CK_SLOT_ID));
-	if (pk11_slots == NULL) {
-		(void) fprintf(stderr,
-		    "Cannot get memory for %ld slots\n", slotcnt);
-		return (NULL);
-	}
-
-	rv = C_GetSlotList(1, pk11_slots, &slotcnt);
-	if (rv != CKR_OK) {
-		(void) fprintf(stderr,
-		    "Cannot get PKCS#11 slot list. error = %s\n",
-		    pkcs11_strerror(rv));
-		return (NULL);
-	}
-
-	if (verbose)
-		(void) printf("Found %ld slots\n", slotcnt);
-
-	/* Search the token that matches the label */
-	while (slotcnt > 0) {
-		rv = C_GetTokenInfo(pk11_slots[--slotcnt], &token_info);
-		if (rv != CKR_OK)
-			continue;
-
-		if (verbose)
-			(void) printf("slot [%ld] = %s\n",
-			    slotcnt, token_info.label);
-		if (memcmp(token_label_padded, token_info.label,
-		    sizeof (token_info.label)) == 0) {
-			bingo = B_TRUE;
-			slot = pk11_slots[slotcnt];
-			break;
-		}
-		if (verbose) {
-			token_info.label[31] = '\0';
-			(void) printf("found slot [%s]\n", token_info.label);
-		}
-	}
-
-	if (!bingo) {
-		(void) fprintf(stderr, "no matching PKCS#11 token found\n");
-		return (NULL);
-	}
-
-	rv = C_OpenSession(slot, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR,
-		&sess);
-	if (rv != CKR_OK) {
-		(void) fprintf(stderr, "Cannot open session. error = %s\n",
-		    pkcs11_strerror(rv));
-		return (NULL);
-	}
-
-	/*
-	 * Some tokens may not be setting CKF_LOGIN_REQUIRED. So, we do
-	 * not check for this flag and always login to be safe.
-	 */
-	ulPinLen = get_passphrase(password_file, passphrase,
-	    sizeof (passphrase));
-	if (ulPinLen == 0) {
-		(void) fprintf(stderr, "Unable to read passphrase");
-		return (NULL);
-	}
-
-	rv = C_Login(sess, CKU_USER, (CK_UTF8CHAR_PTR)passphrase,
-	    ulPinLen);
-	if (rv != CKR_OK) {
-		(void) fprintf(stderr, "Cannot login to the token."
-		    " error = %s\n", pkcs11_strerror(rv));
-		return (NULL);
-	}
-
-	cert_tmpl[1].pValue = (CK_VOID_PTR) certname;
-	cert_tmpl[1].ulValueLen = strlen(certname);
-
-	rv = C_FindObjectsInit(sess, cert_tmpl, cert_tmpl_count);
-	if (rv != CKR_OK) {
-		(void) fprintf(stderr,
-		    "Cannot initialize cert search."
-		    " error = %s\n", pkcs11_strerror(rv));
-		return (NULL);
-	}
-
-	rv = C_FindObjects(sess, cert_objs,
-		(certname == NULL ? 1 : max_num_cert), &cert_obj_count);
-	if (rv != CKR_OK) {
-		(void) fprintf(stderr,
-		    "Cannot retrieve cert object. error = %s\n",
-		    pkcs11_strerror(rv));
-		return (NULL);
-	}
-
-	/* Who cares if this fails! */
-	(void) C_FindObjectsFinal(sess);
-	if (verbose)
-		(void) printf("found %ld certificates\n", cert_obj_count);
-
-	if (cert_obj_count == 0) {
-		(void) fprintf(stderr, "\"%s\" not found.\n", certname);
-		(void) fprintf(stderr, "no certs. bye.\n");
-		return (NULL);
-	}
-
-	cert_obj = cert_objs[0];
-
-	/* Get the modulus value from the certificate */
-	ber_buf = get_cert_val(sess, cert_obj, &blen);
-	if (ber_buf == NULL) {
-		(void) fprintf(stderr,
-		    "Cannot get certificate data for \"%s\".\n", certname);
-		return (NULL);
-	}
-
-	/* Store it for later use. We free the buffer at that time. */
-	known_cert_attrs[0].type = CKA_VALUE;
-	known_cert_attrs[0].pValue = ber_buf;
-	known_cert_attrs[0].ulValueLen = blen;
-
-	mval = get_modulus(ber_buf, blen, &mlen);
-	if (mval == NULL) {
-		(void) fprintf(stderr,
-		    "Cannot get Modulus in certificate \"%s\".\n", certname);
-		return (NULL);
-	}
-
-	/* Now get the private key */
-	privkey_tmpl[0].pValue = mval;
-	privkey_tmpl[0].ulValueLen = mlen;
-
-	rv = C_FindObjectsInit(sess, privkey_tmpl, privkey_tmpl_count);
-	if (rv != CKR_OK) {
-		(void) fprintf(stderr, "Cannot intialize private key search."
-		    " error = %s\n", pkcs11_strerror(rv));
-		return (NULL);
-	}
-
-	rv = C_FindObjects(sess, &privkey_obj, 1,  &privkey_obj_count);
-	if (rv != CKR_OK) {
-		(void) fprintf(stderr, "Cannot retrieve private key object "
-		    " error = %s\n", pkcs11_strerror(rv));
-		return (NULL);
-	}
-	/* Who cares if this fails! */
-	(void) C_FindObjectsFinal(sess);
-
-	if (privkey_obj_count == 0) {
-		(void) fprintf(stderr, "no private keys. bye.\n");
-		return (NULL);
-	}
-
-	(void) printf("found %ld private keys\n", privkey_obj_count);
-	if (verbose) {
-		(void) printf("private key attributes:    \n");
-		(void) printf("\tmodulus: size %d \n", mlen);
-	}
-
-	/*
-	 * Store it for later use. The index of the attributes
-	 * is the same in both the structures.
-	 */
-	known_attr_cnt = privkey_tmpl_count;
-	for (i = 0; i < privkey_tmpl_count; i++)
-		key_gattrs[i] = privkey_tmpl[i];
-
-	/*
-	 * Get CKA_EXTRACTABLE value. We set the default value
-	 * TRUE if the token returns CKR_ATTRIBUTE_TYPE_INVALID.
-	 * The token would supply this attribute if the key
-	 * is not extractable.
-	 */
-	privkey_attrs[0].pValue = &is_extractable;
-	privkey_attrs[0].ulValueLen = sizeof (is_extractable);
-	rv = C_GetAttributeValue(sess, privkey_obj, privkey_attrs, 1);
-	if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID) {
-		(void) fprintf(stderr,
-		    "Cannot get CKA_EXTRACTABLE attribute."
-		    " error = %s\n", pkcs11_strerror(rv));
-		return (NULL);
-	}
-
-	if (rv == CKR_ATTRIBUTE_TYPE_INVALID)
-		is_extractable = TRUE;
-	key_gattrs[known_attr_cnt++] = privkey_attrs[0];
-
-	if (is_extractable) {
-	/* Now wrap the key, then unwrap it */
-	CK_BYTE	aes_key_val[16] = {
-		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
-	static CK_BYTE aes_param[16] = {
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-	CK_MECHANISM aes_cbc_pad_mech = {CKM_AES_CBC_PAD, aes_param, 16};
-	CK_OBJECT_HANDLE aes_key_obj, sess_privkey_obj;
-	CK_BYTE *wrapped_privkey;
-	CK_ULONG wrapped_privkey_len;
-
-	CK_ATTRIBUTE unwrap_tmpl[] = {
-		/* code below depends on the following attribute order */
-		{CKA_TOKEN, &false, sizeof (false)},
-		{CKA_CLASS, &privkey_class, sizeof (privkey_class)},
-		{CKA_KEY_TYPE, &privkey_type, sizeof (privkey_type)},
-		{CKA_SENSITIVE, &false, sizeof (false)},
-		{CKA_PRIVATE, &false, sizeof (false)}
-	};
-
-	rv = SUNW_C_KeyToObject(sess, CKM_AES_CBC_PAD, aes_key_val, 16,
-	    &aes_key_obj);
-
-	if (rv != CKR_OK) {
-		(void) fprintf(stderr,
-		    "Cannot create wrapping key. error = %s\n",
-		    pkcs11_strerror(rv));
-		return (NULL);
-	}
-
-	/* get the size of the wrapped key */
-	rv = C_WrapKey(sess, &aes_cbc_pad_mech, aes_key_obj, privkey_obj,
-	    NULL, &wrapped_privkey_len);
-	if (rv != CKR_OK) {
-		(void) fprintf(stderr, "Cannot get key size. error = %s\n",
-		    pkcs11_strerror(rv));
-		return (NULL);
-	}
-
-	wrapped_privkey = malloc(wrapped_privkey_len * sizeof (CK_BYTE));
-	if (wrapped_privkey == NULL) {
-		return (NULL);
-	}
-
-	/* do the actual key wrapping */
-	rv = C_WrapKey(sess, &aes_cbc_pad_mech, aes_key_obj, privkey_obj,
-	    wrapped_privkey, &wrapped_privkey_len);
-	if (rv != CKR_OK) {
-		(void) fprintf(stderr, "Cannot wrap private key. error = %s\n",
-		    pkcs11_strerror(rv));
-		return (NULL);
-	}
-	(void) printf("private key successfully wrapped, "
-		"wrapped blob length: %ld\n",
-		wrapped_privkey_len);
-
-	rv = C_UnwrapKey(sess, &aes_cbc_pad_mech, aes_key_obj,
-	    wrapped_privkey, wrapped_privkey_len,
-	    unwrap_tmpl, 5, &sess_privkey_obj);
-	if (rv != CKR_OK) {
-		(void) fprintf(stderr, "Cannot unwrap private key."
-		    " error = %s\n", pkcs11_strerror(rv));
-		return (NULL);
-	}
-	(void) printf("session private key successfully unwrapped\n");
-
-	privkey_obj = sess_privkey_obj;
-	/* Store the one modified attribute and the two new attributes. */
-	key_gattrs[CKA_TOKEN_INDEX] = unwrap_tmpl[0];
-	key_gattrs[known_attr_cnt++] = unwrap_tmpl[3];
-	key_gattrs[known_attr_cnt++] = unwrap_tmpl[4];
-	}
-
-	return (pkcs11_to_kssl(sess, privkey_obj, !is_extractable, bufsize,
-	    token_label_padded, passphrase, ulPinLen));
-}
-
-#define	MAX_OPENSSL_ATTR_CNT	8
-
-/*
- * See the comments for pkcs11_to_kssl() for the layout of the
- * returned buffer.
- */
-static kssl_params_t *
-openssl_to_kssl(RSA *rsa, int ncerts, uchar_t *cert_bufs[], int *cert_sizes,
-    int *paramsize)
+kmf_to_kssl(int nxkey, KMF_RAW_KEY_DATA *rsa, int ncerts,
+	KMF_DATA *certs, int *paramsize, char *token_label, KMF_DATA *idstr,
+	KMF_CREDENTIAL *creds)
 {
 	int i, tcsize;
 	kssl_params_t *kssl_params;
 	kssl_key_t *key;
 	char *buf;
 	uint32_t bufsize;
-	kssl_object_attribute_t kssl_attrs[MAX_OPENSSL_ATTR_CNT];
-	kssl_object_attribute_t kssl_tmpl_attrs[MAX_OPENSSL_ATTR_CNT] = {
+	static CK_BBOOL true = TRUE;
+	static CK_BBOOL false = FALSE;
+	static CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
+	static CK_KEY_TYPE keytype = CKK_RSA;
+	kssl_object_attribute_t kssl_attrs[MAX_ATTR_CNT];
+	CK_ATTRIBUTE exkey_attrs[MAX_ATTR_CNT] = {
+		{CKA_TOKEN, &true, sizeof (true)},
+		{CKA_EXTRACTABLE, &false, sizeof (false)},
+		{CKA_CLASS,	&class, sizeof (class) },
+		{CKA_KEY_TYPE,	&keytype, sizeof (keytype) },
+		{CKA_ID,	NULL, 0}
+	};
+	kssl_object_attribute_t kssl_tmpl_attrs[MAX_ATTR_CNT] = {
 		{SUN_CKA_MODULUS, NULL, 0},
 		{SUN_CKA_PUBLIC_EXPONENT, NULL, 0},
 		{SUN_CKA_PRIVATE_EXPONENT, NULL, 0},
@@ -659,42 +119,64 @@
 		{SUN_CKA_EXPONENT_2, NULL, 0},
 		{SUN_CKA_COEFFICIENT, NULL, 0}
 	};
-	BIGNUM *priv_key_bignums[MAX_OPENSSL_ATTR_CNT];
+	KMF_BIGINT priv_key_bignums[MAX_ATTR_CNT];
 	int attr_cnt;
 
+	if (nxkey && idstr != NULL) {
+		exkey_attrs[4].pValue = idstr->Data;
+		exkey_attrs[4].ulValueLen = idstr->Length;
+	}
 	tcsize = 0;
 	for (i = 0; i < ncerts; i++)
-		tcsize += cert_sizes[i];
+		tcsize += certs[i].Length;
 
 	bufsize = sizeof (kssl_params_t);
-	bufsize += (tcsize + MAX_CHAIN_LENGTH * sizeof (uint32_t));
+	bufsize += (tcsize + (MAX_CHAIN_LENGTH * sizeof (uint32_t)));
 
-	/* and the key attributes */
-	priv_key_bignums[0] = rsa->n;		/* MODULUS */
-	priv_key_bignums[1] = rsa->e; 		/* PUBLIC_EXPONENT */
-	priv_key_bignums[2] = rsa->d; 		/* PRIVATE_EXPONENT */
-	priv_key_bignums[3] = rsa->p;		/* PRIME_1 */
-	priv_key_bignums[4] = rsa->q;		/* PRIME_2 */
-	priv_key_bignums[5] = rsa->dmp1;	/* EXPONENT_1 */
-	priv_key_bignums[6] = rsa->dmq1;	/* EXPONENT_2 */
-	priv_key_bignums[7] = rsa->iqmp;	/* COEFFICIENT */
+	if (!nxkey) {
+		bzero(priv_key_bignums, sizeof (KMF_BIGINT) *
+			MAX_ATTR_CNT);
+		/* and the key attributes */
+		priv_key_bignums[0] = rsa->rawdata.rsa.mod;
+		priv_key_bignums[1] = rsa->rawdata.rsa.pubexp;
+		priv_key_bignums[2] = rsa->rawdata.rsa.priexp;
+		priv_key_bignums[3] = rsa->rawdata.rsa.prime1;
+		priv_key_bignums[4] = rsa->rawdata.rsa.prime2;
+		priv_key_bignums[5] = rsa->rawdata.rsa.exp1;
+		priv_key_bignums[6] = rsa->rawdata.rsa.exp2;
+		priv_key_bignums[7] = rsa->rawdata.rsa.coef;
+
+		if (rsa->rawdata.rsa.mod.val == NULL ||
+			rsa->rawdata.rsa.priexp.val == NULL) {
+			(void) fprintf(stderr,
+			    "missing required attributes in private key.\n");
+			return (NULL);
+		}
 
-	if (rsa->n == NULL || rsa->d == NULL) {
-		(void) fprintf(stderr,
-		    "missing required attributes in private key.\n");
-		return (NULL);
-	}
-
-	attr_cnt = 0;
-	for (i = 0; i < MAX_OPENSSL_ATTR_CNT; i++) {
-		if (priv_key_bignums[i] == NULL)
-			continue;
-		kssl_attrs[attr_cnt].ka_type = kssl_tmpl_attrs[i].ka_type;
-		kssl_attrs[attr_cnt].ka_value_len =
-		    BN_num_bytes(priv_key_bignums[i]);
-		bufsize += sizeof (crypto_object_attribute_t) +
-		    kssl_attrs[attr_cnt].ka_value_len;
-		attr_cnt++;
+		attr_cnt = 0;
+		for (i = 0; i < MAX_ATTR_CNT; i++) {
+			if (priv_key_bignums[i].val == NULL)
+				continue;
+			kssl_attrs[attr_cnt].ka_type =
+				kssl_tmpl_attrs[i].ka_type;
+			kssl_attrs[attr_cnt].ka_value_len =
+				priv_key_bignums[i].len;
+			bufsize += sizeof (crypto_object_attribute_t) +
+			    kssl_attrs[attr_cnt].ka_value_len;
+			attr_cnt++;
+		}
+	} else {
+		/*
+		 * Compute space for the attributes and values that the
+		 * kssl kernel module will need in order to search for
+		 * the private key.
+		 */
+		for (attr_cnt = 0; attr_cnt < 5; attr_cnt++) {
+			bufsize += sizeof (crypto_object_attribute_t) +
+				exkey_attrs[attr_cnt].ulValueLen;
+		}
+		if (creds)
+			bufsize += creds->credlen;
 	}
 
 	/* Add 4-byte cushion as sc_sizes[0] needs 32-bit alignment */
@@ -713,60 +195,458 @@
 
 	buf = (char *)(kssl_params + 1);
 
-	/* the keys attributes structs array */
-	key = &kssl_params->kssl_privkey;
-	key->ks_format = CRYPTO_KEY_ATTR_LIST;
-	key->ks_count = attr_cnt;
-	key->ks_attrs_offset = buf - (char *)kssl_params;
-	buf += attr_cnt * sizeof (kssl_object_attribute_t);
+	if (!nxkey) {
+		/* the keys attributes structs array */
+		key = &kssl_params->kssl_privkey;
+		key->ks_format = CRYPTO_KEY_ATTR_LIST;
+		key->ks_count = attr_cnt;
+		key->ks_attrs_offset = buf - (char *)kssl_params;
+		buf += attr_cnt * sizeof (kssl_object_attribute_t);
+
+		attr_cnt = 0;
+		/* then the key attributes values */
+		for (i = 0; i < MAX_ATTR_CNT; i++) {
+			if (priv_key_bignums[i].val == NULL)
+				continue;
+			(void) memcpy(buf, priv_key_bignums[i].val,
+				priv_key_bignums[i].len);
+			kssl_attrs[attr_cnt].ka_value_offset =
+			    buf - (char *)kssl_params;
+			buf += kssl_attrs[attr_cnt].ka_value_len;
+			attr_cnt++;
+		}
+	} else {
+		char tlabel[CRYPTO_EXT_SIZE_LABEL];
+		bzero(tlabel, sizeof (tlabel));
+		(void) strlcpy(tlabel, token_label, sizeof (tlabel));
+
+		/*
+		 * For a non-extractable key, we must provide the PIN
+		 * so the kssl module can access the token to find
+		 * the key handle.
+		 */
+		kssl_params->kssl_is_nxkey = 1;
+		bcopy(tlabel, kssl_params->kssl_token.toklabel,
+			CRYPTO_EXT_SIZE_LABEL);
+		kssl_params->kssl_token.pinlen = creds->credlen;
+		kssl_params->kssl_token.tokpin_offset =
+			buf - (char *)kssl_params;
+		kssl_params->kssl_token.ck_rv = 0;
+		bcopy(creds->cred, buf, creds->credlen);
+		buf += creds->credlen;
 
-	attr_cnt = 0;
-	/* then the key attributes values */
-	for (i = 0; i < MAX_OPENSSL_ATTR_CNT; i++) {
-		if (priv_key_bignums[i] == NULL)
-			continue;
-		(void) BN_bn2bin(priv_key_bignums[i], (unsigned char *)buf);
-		kssl_attrs[attr_cnt].ka_value_offset =
-		    buf - (char *)kssl_params;
-		buf += kssl_attrs[attr_cnt].ka_value_len;
-		attr_cnt++;
+		/*
+		 * Next in the buffer, we must provide the attributes
+		 * that the kssl module will use to search in the
+		 * token to find the protected key handle.
+		 */
+		key = &kssl_params->kssl_privkey;
+		key->ks_format = CRYPTO_KEY_ATTR_LIST;
+		key->ks_count = attr_cnt;
+		key->ks_attrs_offset = buf - (char *)kssl_params;
+
+		buf += attr_cnt * sizeof (kssl_object_attribute_t);
+		for (i = 0; i < attr_cnt; i++) {
+			bcopy(exkey_attrs[i].pValue, buf,
+				exkey_attrs[i].ulValueLen);
+
+			kssl_attrs[i].ka_type = exkey_attrs[i].type;
+			kssl_attrs[i].ka_value_offset =
+				buf - (char *)kssl_params;
+			kssl_attrs[i].ka_value_len = exkey_attrs[i].ulValueLen;
+
+			buf += exkey_attrs[i].ulValueLen;
+		}
+	}
+	/* Copy the key attributes array here */
+	bcopy(kssl_attrs, ((char *)kssl_params) + key->ks_attrs_offset,
+		attr_cnt * sizeof (kssl_object_attribute_t));
+
+	buf = (char *)P2ROUNDUP((uintptr_t)buf, sizeof (uint32_t));
+
+	/*
+	 * Finally, add the certificate chain to the buffer.
+	 */
+	kssl_params->kssl_certs.sc_count = ncerts;
+
+	/* First, an array of certificate sizes */
+	for (i = 0; i < ncerts; i++) {
+		uint32_t certsz = (uint32_t)certs[i].Length;
+		char *p = buf + (i * sizeof (uint32_t));
+		bcopy(&certsz, p, sizeof (uint32_t));
 	}
 
-	bcopy(kssl_attrs, ((char *)kssl_params) + key->ks_attrs_offset,
-	    attr_cnt * sizeof (kssl_object_attribute_t));
-
-	buf = (char *)P2ROUNDUP((uintptr_t)buf, sizeof (uint32_t));
-	kssl_params->kssl_certs.sc_count = ncerts;
-	bcopy(cert_sizes, buf, ncerts * sizeof (uint32_t));
 	kssl_params->kssl_certs.sc_sizes_offset = buf - (char *)kssl_params;
 	buf += MAX_CHAIN_LENGTH * sizeof (uint32_t);
 
 	kssl_params->kssl_certs.sc_certs_offset = buf - (char *)kssl_params;
-	/* now the certs values */
+
+	/* Now add the certificate data (ASN.1 DER encoded) */
 	for (i = 0; i < ncerts; i++) {
-		bcopy(cert_bufs[i], buf, cert_sizes[i]);
-		buf += cert_sizes[i];
+		bcopy(certs[i].Data, buf, certs[i].Length);
+		buf += certs[i].Length;
 	}
 
 	*paramsize = bufsize;
 	return (kssl_params);
 }
 
-static kssl_params_t *
-add_cacerts(kssl_params_t *old_params, const char *cacert_chain_file,
-    const char *password_file)
+/*
+ * Extract a sensitive key via wrap/unwrap operations.
+ *
+ * This function requires that we call PKCS#11 API directly since
+ * KMF does not yet support wrapping/unwrapping of keys.   By extracting
+ * a sensitive key in wrapped form, we then unwrap it into a session key
+ * object.  KMF is then used to find the session key and return it in
+ * KMF_RAW_KEY format which is then passed along to KSSL by the caller.
+ */
+static KMF_RETURN
+get_sensitive_key_data(KMF_HANDLE_T kmfh, KMF_FINDKEY_PARAMS *fkparams,
+	KMF_KEY_HANDLE *key, KMF_KEY_HANDLE *rawkey)
 {
-	int i, ncerts, newlen;
-	int *cert_sizes;
-	uint32_t certlen = 0;
+	KMF_RETURN rv = KMF_OK;
+	static CK_BYTE aes_param[16];
+	static CK_OBJECT_CLASS privkey_class = CKO_PRIVATE_KEY;
+	static CK_KEY_TYPE privkey_type = CKK_RSA;
+	static CK_BBOOL true = TRUE;
+	static CK_BBOOL false = FALSE;
+	char *err = NULL;
+	char wrapkey_label[BUFSIZ];
+	int fd;
+	uint32_t nkeys = 0;
+	CK_RV ckrv;
+	CK_SESSION_HANDLE pk11session;
+	CK_BYTE aes_key_val[16];
+
+	CK_MECHANISM aes_cbc_pad_mech = {CKM_AES_CBC_PAD, aes_param,
+		sizeof (aes_param)};
+	CK_OBJECT_HANDLE aes_key_obj = CK_INVALID_HANDLE;
+	CK_OBJECT_HANDLE sess_privkey_obj = CK_INVALID_HANDLE;
+	CK_BYTE *wrapped_privkey = NULL;
+	CK_ULONG wrapped_privkey_len = 0;
+
+	CK_ATTRIBUTE unwrap_tmpl[] = {
+		/* code below depends on the following attribute order */
+		{CKA_TOKEN, &false, sizeof (false)},
+		{CKA_CLASS, &privkey_class, sizeof (privkey_class)},
+		{CKA_KEY_TYPE, &privkey_type, sizeof (privkey_type)},
+		{CKA_SENSITIVE, &false, sizeof (false)},
+		{CKA_PRIVATE, &false, sizeof (false)},
+		{CKA_LABEL, NULL, 0}
+	};
+
+	/*
+	 * Create a wrap key with random data.
+	 */
+	fd = open("/dev/urandom", O_RDONLY);
+	if (fd == -1) {
+		perror("Error reading /dev/urandom");
+		return (KMF_ERR_INTERNAL);
+	}
+	if (read(fd, aes_key_val, sizeof (aes_key_val)) !=
+		sizeof (aes_key_val)) {
+		perror("Error reading from /dev/urandom");
+		(void) close(fd);
+		return (KMF_ERR_INTERNAL);
+	}
+	(void) close(fd);
+
+	pk11session = KMF_GetPK11Handle(kmfh);
+
+	/*
+	 * Login to create the wrap key stuff.
+	 */
+	ckrv = C_Login(pk11session, CKU_USER,
+		(CK_UTF8CHAR_PTR)fkparams->cred.cred,
+		fkparams->cred.credlen);
+	if (ckrv != CKR_OK && ckrv != CKR_USER_ALREADY_LOGGED_IN) {
+		(void) fprintf(stderr,
+			"Cannot login to the token. error = %s\n",
+			pkcs11_strerror(ckrv));
+		return (KMF_ERR_INTERNAL);
+	}
+
+	/*
+	 * Turn the random key into a PKCS#11 session object.
+	 */
+	ckrv = SUNW_C_KeyToObject(pk11session, CKM_AES_CBC_PAD, aes_key_val,
+		sizeof (aes_key_val), &aes_key_obj);
+	if (ckrv != CKR_OK) {
+		(void) fprintf(stderr,
+			"Cannot create wrapping key. error = %s\n",
+			pkcs11_strerror(ckrv));
+		return (KMF_ERR_INTERNAL);
+	}
+
+	/*
+	 * Find the original private key that we are going to wrap.
+	 */
+	rv = KMF_FindKey(kmfh, fkparams, key, &nkeys);
+	if (rv != KMF_OK) {
+		REPORT_KMF_ERROR(rv, "Error finding private key", err);
+		goto out;
+	}
+
+	/*
+	 * Get the size of the wrapped private key.
+	 */
+	bzero(aes_param, sizeof (aes_param));
+	ckrv = C_WrapKey(pk11session, &aes_cbc_pad_mech,
+		aes_key_obj, (CK_OBJECT_HANDLE)key->keyp,
+		NULL, &wrapped_privkey_len);
+	if (ckrv != CKR_OK) {
+		/*
+		 * Most common error here is that the token doesn't
+		 * support the wrapping mechanism or the key is
+		 * marked non-extractable.  Return an error and let
+		 * the caller deal with it gracefully.
+		 */
+		(void) fprintf(stderr,
+			"Cannot get wrap key size. error = %s\n",
+			pkcs11_strerror(ckrv));
+		rv = KMF_ERR_INTERNAL;
+		goto out;
+	}
+	wrapped_privkey = malloc(wrapped_privkey_len);
+	if (wrapped_privkey == NULL) {
+		rv = KMF_ERR_MEMORY;
+		goto out;
+	}
+	/*
+	 * Now get the actual wrapped key data.
+	 */
+	ckrv = C_WrapKey(pk11session, &aes_cbc_pad_mech,
+		aes_key_obj, (CK_OBJECT_HANDLE)key->keyp,
+		wrapped_privkey, &wrapped_privkey_len);
+	if (ckrv != CKR_OK) {
+		(void) fprintf(stderr,
+			"Cannot wrap private key. error = %s\n",
+			pkcs11_strerror(ckrv));
+		rv = KMF_ERR_INTERNAL;
+		goto out;
+	}
+	/*
+	 * Create a label for the wrapped session key so we can find
+	 * it easier later.
+	 */
+	snprintf(wrapkey_label, sizeof (wrapkey_label), "ksslprikey_%d",
+		getpid());
+
+	unwrap_tmpl[5].pValue = wrapkey_label;
+	unwrap_tmpl[5].ulValueLen = strlen(wrapkey_label);
+
+	/*
+	 * Unwrap the key into the template and create a temporary
+	 * session private key.
+	 */
+	ckrv = C_UnwrapKey(pk11session, &aes_cbc_pad_mech, aes_key_obj,
+		wrapped_privkey, wrapped_privkey_len,
+		unwrap_tmpl, 6, &sess_privkey_obj);
+	if (ckrv != CKR_OK) {
+		(void) fprintf(stderr,
+			"Cannot unwrap private key. error = %s\n",
+			pkcs11_strerror(ckrv));
+		rv = KMF_ERR_INTERNAL;
+		goto out;
+	}
+
+	/*
+	 * Use KMF to find the session key and return it as RAW data
+	 * so we can pass it along to KSSL.
+	 */
+	fkparams->kstype = KMF_KEYSTORE_PK11TOKEN;
+	fkparams->keyclass = KMF_ASYM_PRI;
+	fkparams->format = KMF_FORMAT_RAWKEY;
+	fkparams->findLabel = wrapkey_label;
+	fkparams->pkcs11parms.sensitive = FALSE;
+	fkparams->pkcs11parms.private = FALSE;
+	fkparams->pkcs11parms.token = FALSE; /* <-- very important! */
+
+	rv = KMF_FindKey(kmfh, fkparams, rawkey, &nkeys);
+	if (rv != KMF_OK) {
+		REPORT_KMF_ERROR(rv, "Error finding raw private key", err);
+		goto out;
+	}
+out:
+	if (wrapped_privkey)
+		free(wrapped_privkey);
+
+	if (aes_key_obj != CK_INVALID_HANDLE)
+		C_DestroyObject(pk11session, aes_key_obj);
+
+	if (sess_privkey_obj != CK_INVALID_HANDLE)
+		C_DestroyObject(pk11session, sess_privkey_obj);
+
+	return (rv);
+}
+
+static kssl_params_t *
+load_from_pkcs11(const char *token_label, const char *password_file,
+    const char *certname, int *bufsize)
+{
+	KMF_RETURN rv;
+	KMF_HANDLE_T kmfh;
+	KMF_X509_DER_CERT cert;
+	KMF_KEY_HANDLE key, rawkey;
+	KMF_CREDENTIAL creds;
+	KMF_FINDCERT_PARAMS fcparams;
+	KMF_FINDKEY_PARAMS fkparams;
+	KMF_CONFIG_PARAMS cfgparams;
+	KMF_DATA iddata = { NULL, 0 };
+	kssl_params_t *kssl_params = NULL;
+	uint32_t ncerts, nkeys;
+	char *err, *idstr = NULL;
+	char password_buf[1024];
+	int nxkey = 0;
+
+	rv = KMF_Initialize(&kmfh, NULL, NULL);
+	if (rv != KMF_OK) {
+		REPORT_KMF_ERROR(rv, "Error initializing KMF", err);
+		return (0);
+	}
+	if (get_passphrase(password_file, password_buf,
+		sizeof (password_buf)) <= 0) {
+		perror("Unable to read passphrase");
+		goto done;
+	}
+	creds.cred = password_buf;
+	creds.credlen = strlen(password_buf);
+
+	bzero(&cfgparams, sizeof (cfgparams));
+	bzero(&fcparams, sizeof (fcparams));
+	bzero(&fkparams, sizeof (fkparams));
+
+	cfgparams.kstype = KMF_KEYSTORE_PK11TOKEN;
+	cfgparams.pkcs11config.label = (char *)token_label;
+	cfgparams.pkcs11config.readonly = B_FALSE;
+
+	rv = KMF_ConfigureKeystore(kmfh, &cfgparams);
+	if (rv != KMF_OK) {
+		REPORT_KMF_ERROR(rv, "Error configuring KMF keystore", err);
+		goto done;
+	}
+
+	/*
+	 * Find the certificate matching the given label.
+	 */
+	fcparams.kstype = KMF_KEYSTORE_PK11TOKEN;
+	fcparams.certLabel = (char *)certname;
+	rv = KMF_FindCert(kmfh, &fcparams, &cert, &ncerts);
+	if (rv != KMF_OK || ncerts == 0)
+		goto done;
+
+	/*
+	 * Find the associated private key for this cert by
+	 * keying off of the label and the ASCII ID string.
+	 */
+	rv = KMF_GetCertIDString(&cert.certificate, &idstr);
+	if (rv != KMF_OK)
+		goto done;
+
+	fkparams.kstype = KMF_KEYSTORE_PK11TOKEN;
+	fkparams.keyclass = KMF_ASYM_PRI;
+	fkparams.cred = creds;
+	fkparams.format = KMF_FORMAT_RAWKEY;
+	fkparams.findLabel = (char *)certname;
+	fkparams.idstr = idstr;
+	fkparams.pkcs11parms.private = TRUE;
+	fkparams.pkcs11parms.token = TRUE;
+
+	rv = KMF_FindKey(kmfh, &fkparams, &key, &nkeys);
+	if (rv == KMF_ERR_SENSITIVE_KEY) {
+		KMF_FreeKMFKey(kmfh, &key);
+		/*
+		 * Get a normal key handle and then do a wrap/unwrap
+		 * in order to get the necessary raw data fields needed
+		 * to send to KSSL.
+		 */
+		fkparams.format = KMF_FORMAT_NATIVE;
+		rv = get_sensitive_key_data(kmfh, &fkparams, &key, &rawkey);
+		if (rv == KMF_OK) {
+			/* Swap "key" for "rawkey" */
+			KMF_FreeKMFKey(kmfh, &key);
+
+			key = rawkey;
+		} else {
+			KMF_FreeKMFKey(kmfh, &key);
+
+			/* Let kssl try to find the key. */
+			nxkey = 1;
+			rv = KMF_GetCertIDData(&cert.certificate, &iddata);
+		}
+	} else if (rv == KMF_ERR_UNEXTRACTABLE_KEY) {
+			KMF_FreeKMFKey(kmfh, &key);
+
+			/* Let kssl try to find the key. */
+			nxkey = 1;
+			rv = KMF_GetCertIDData(&cert.certificate, &iddata);
+	} else if (rv != KMF_OK || nkeys == 0)
+		goto done;
+
+	if (rv == KMF_OK)
+		kssl_params = kmf_to_kssl(nxkey, (KMF_RAW_KEY_DATA *)key.keyp,
+			1, &cert.certificate, bufsize,
+			(char *)token_label, &iddata, &creds);
+done:
+	if (ncerts != 0)
+		KMF_FreeKMFCert(kmfh, &cert);
+	if (nkeys != 0)
+		KMF_FreeKMFKey(kmfh, &key);
+	if (idstr)
+		free(idstr);
+
+	if (kmfh != NULL)
+		(void) KMF_Finalize(kmfh);
+
+	return (kssl_params);
+}
+
+/*
+ * add_cacerts
+ *
+ * Load a chain of certificates from a PEM file.
+ */
+static kssl_params_t *
+add_cacerts(kssl_params_t *old_params, const char *cacert_chain_file)
+{
+	int i, newlen;
+	uint32_t certlen = 0, ncerts;
 	char *buf;
-	uchar_t **cert_bufs;
+	KMF_RETURN rv;
+	KMF_X509_DER_CERT *certs = NULL;
+	KMF_FINDCERT_PARAMS fcparms;
 	kssl_params_t *kssl_params;
+	KMF_HANDLE_T kmfh;
+	char *err = NULL;
+
+	bzero(&fcparms, sizeof (fcparms));
+	fcparms.kstype = KMF_KEYSTORE_OPENSSL;
+	fcparms.sslparms.certfile = (char *)cacert_chain_file;
 
-	ncerts = 0;
-	cert_bufs = PEM_get_rsa_key_certs(cacert_chain_file,
-	    (char *)password_file, NULL, &cert_sizes, &ncerts);
-	if (cert_bufs == NULL || ncerts == 0) {
+	rv = KMF_Initialize(&kmfh, NULL, NULL);
+	if (rv != KMF_OK) {
+		REPORT_KMF_ERROR(rv, "Error initializing KMF", err);
+		return (0);
+	}
+	rv = KMF_FindCert(kmfh, &fcparms, NULL, &ncerts);
+	if (rv != KMF_OK) {
+		REPORT_KMF_ERROR(rv, "Error finding CA certificates", err);
+		(void) KMF_Finalize(kmfh);
+		return (0);
+	}
+	certs = (KMF_X509_DER_CERT *)malloc(ncerts *
+		sizeof (KMF_X509_DER_CERT));
+	if (certs == NULL) {
+		(void) fprintf(stderr, "memory allocation error.\n");
+		(void) KMF_Finalize(kmfh);
+		return (NULL);
+	}
+	bzero(certs, ncerts * sizeof (KMF_X509_DER_CERT));
+	rv = KMF_FindCert(kmfh, &fcparms, certs, &ncerts);
+
+	(void) KMF_Finalize(kmfh);
+
+	if (rv != KMF_OK || ncerts == 0) {
 		bzero(old_params, old_params->kssl_params_size);
 		free(old_params);
 		return (NULL);
@@ -778,7 +658,7 @@
 
 	newlen = old_params->kssl_params_size;
 	for (i = 0; i < ncerts; i++)
-		newlen += cert_sizes[i];
+		newlen += certs[i].certificate.Length;
 
 	/*
 	 * Get a bigger structure and update the
@@ -789,12 +669,16 @@
 	kssl_params->kssl_params_size = newlen;
 	kssl_params->kssl_certs.sc_count += ncerts;
 
-	/* Put the cert_sizes starting from sc_sizes[1] */
+	/* Put the cert size info starting from sc_sizes[1] */
 	buf = (char *)kssl_params;
 	buf += kssl_params->kssl_certs.sc_sizes_offset;
 	bcopy(buf, &certlen, sizeof (uint32_t));
 	buf += sizeof (uint32_t);
-	bcopy(cert_sizes, buf, ncerts * sizeof (uint32_t));
+	for (i = 0; i < ncerts; i++) {
+		uint32_t size = (uint32_t)certs[i].certificate.Length;
+		bcopy(&size, buf, sizeof (uint32_t));
+		buf += sizeof (uint32_t);
+	}
 
 	/* Put the cert_bufs starting from sc_certs[1] */
 	buf = (char *)kssl_params;
@@ -803,60 +687,65 @@
 
 	/* now the certs values */
 	for (i = 0; i < ncerts; i++) {
-		bcopy(cert_bufs[i], buf, cert_sizes[i]);
-		buf += cert_sizes[i];
+		bcopy(certs[i].certificate.Data, buf,
+			certs[i].certificate.Length);
+		buf += certs[i].certificate.Length;
 	}
 
 	for (i = 0; i < ncerts; i++)
-		free(cert_bufs[i]);
-	free(cert_bufs);
-	free(cert_sizes);
+		KMF_FreeKMFCert(kmfh, &certs[i]);
+	free(certs);
 
 	return (kssl_params);
 }
 
+/*
+ * Find a key and certificate(s) from a single PEM file.
+ */
 static kssl_params_t *
 load_from_pem(const char *filename, const char *password_file, int *paramsize)
 {
-	uchar_t **cert_bufs;
-	int *cert_sizes, ncerts, i;
-	RSA *rsa;
+	int ncerts = 0, i;
 	kssl_params_t *kssl_params;
+	KMF_RAW_KEY_DATA *rsa = NULL;
+	KMF_DATA *certs = NULL;
 
-	ncerts = 0;
-	cert_bufs = PEM_get_rsa_key_certs(filename, (char *)password_file,
-	    &rsa, &cert_sizes, &ncerts);
-	if (rsa == NULL || cert_bufs == NULL || ncerts == 0) {
+	ncerts = PEM_get_rsa_key_certs(filename, (char *)password_file,
+		&rsa, &certs);
+	if (rsa == NULL || certs == NULL || ncerts == 0) {
 		return (NULL);
 	}
 
 	if (verbose)
 		(void) printf("%d certificates read successfully\n", ncerts);
 
-	kssl_params = openssl_to_kssl(rsa, ncerts, cert_bufs,
-	    cert_sizes, paramsize);
+	kssl_params = kmf_to_kssl(0, rsa, ncerts, certs, paramsize, NULL,
+		NULL, NULL);
 
 	for (i = 0; i < ncerts; i++)
-		free(cert_bufs[i]);
-	free(cert_bufs);
-	free(cert_sizes);
-	RSA_free(rsa);
+		KMF_FreeData(&certs[i]);
+	free(certs);
+	KMF_FreeRawKey(rsa);
+
 	return (kssl_params);
 }
 
+/*
+ * Load a raw key and certificate(s) from a PKCS#12 file.
+ */
 static kssl_params_t *
 load_from_pkcs12(const char *filename, const char *password_file,
     int *paramsize)
 {
-	RSA *rsa;
+	KMF_RAW_KEY_DATA *rsa = NULL;
 	kssl_params_t *kssl_params;
-	uchar_t **cert_bufs;
-	int *cert_sizes, ncerts, i;
+	KMF_DATA *certs = NULL;
+	int ncerts = 0, i;
 
-	ncerts = 0;
-	cert_bufs = PKCS12_get_rsa_key_certs(filename, password_file, &rsa,
-	    &cert_sizes, &ncerts);
-	if (cert_bufs == NULL || ncerts == 0) {
+	ncerts = PKCS12_get_rsa_key_certs(filename,
+		password_file, &rsa, &certs);
+
+	if (certs == NULL || ncerts == 0) {
 		(void) fprintf(stderr,
 		    "Unable to read cert and/or key from %s\n", filename);
 		return (NULL);
@@ -865,19 +754,17 @@
 	if (verbose)
 		(void) printf("%d certificates read successfully\n", ncerts);
 
-	kssl_params = openssl_to_kssl(rsa, ncerts, cert_bufs,
-	    cert_sizes, paramsize);
+	kssl_params = kmf_to_kssl(0, rsa, ncerts, certs, paramsize, NULL,
+		NULL, NULL);
 
 	for (i = 0; i < ncerts; i++)
-		free(cert_bufs[i]);
-	free(cert_bufs);
-	free(cert_sizes);
+		KMF_FreeData(&certs[i]);
+	free(certs);
 
-	RSA_free(rsa);
+	KMF_FreeRawKey(rsa);
 	return (kssl_params);
 }
 
-
 int
 parse_and_set_addr(char *server_address, char *server_port,
     struct sockaddr_in *addr)
@@ -1105,6 +992,9 @@
 		return (FAILURE);
 	}
 
+	/*
+	 * Add the list of supported ciphers to the buffer.
+	 */
 	bcopy(kssl_suites, kssl_params->kssl_suites,
 	    sizeof (kssl_params->kssl_suites));
 	kssl_params->kssl_params_size = bufsize;
@@ -1114,8 +1004,7 @@
 	kssl_params->kssl_session_cache_size = scache_size;
 
 	if (cacert_chain_file != NULL) {
-		kssl_params = add_cacerts(kssl_params, cacert_chain_file,
-		    password_file);
+		kssl_params = add_cacerts(kssl_params, cacert_chain_file);
 		if (kssl_params == NULL) {
 			return (FAILURE);
 		}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/ksslutil.c	Thu Jan 11 18:12:31 2007 -0800
@@ -0,0 +1,172 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <stdio.h>
+#include <assert.h>
+#include <strings.h>
+
+#include <kmfapi.h>
+#include "kssladm.h"
+
+/*
+ * Extract the Certificate and raw key data from a PKCS#12 file.
+ * The password needed for decrypting the PKCS#12 PDU is stored
+ * in plaintext in the given "password_file" parameter.
+ */
+int
+PKCS12_get_rsa_key_certs(const char *filename, const char *password_file,
+    KMF_RAW_KEY_DATA **rsa, KMF_DATA **certs)
+{
+	char password_buf[1024];
+	KMF_HANDLE_T kmfh;
+	KMF_RETURN rv = KMF_OK;
+	KMF_CREDENTIAL pk12cred;
+	KMF_DATA *tcerts;
+	KMF_RAW_KEY_DATA *keys;
+	int ncerts, nkeys;
+	char *err = NULL;
+
+	rv = KMF_Initialize(&kmfh, NULL, NULL);
+	if (rv != KMF_OK) {
+		REPORT_KMF_ERROR(rv, "Error initializing KMF", err);
+		return (0);
+	}
+
+	tcerts = NULL;
+	keys = NULL;
+	ncerts = 0;
+	nkeys = 0;
+
+	if (get_passphrase(password_file, password_buf,
+		sizeof (password_buf)) <= 0) {
+		perror("Unable to read passphrase");
+		goto done;
+	}
+	pk12cred.cred = password_buf;
+	pk12cred.credlen = strlen(password_buf);
+
+	rv = KMF_ImportPK12(kmfh, (char *)filename, &pk12cred, &tcerts, &ncerts,
+		&keys, &nkeys);
+	if (rv != KMF_OK) {
+		REPORT_KMF_ERROR(rv, "Error importing PKCS12 data", err);
+	}
+
+done:
+	if (rv != KMF_OK) {
+		int i;
+		if (tcerts != NULL) {
+			for (i = 0; i < ncerts; i++)
+				KMF_FreeData(&tcerts[i]);
+			free(tcerts);
+		}
+		tcerts = NULL;
+		ncerts = 0;
+		if (keys != NULL) {
+			for (i = 0; i < nkeys; i++)
+				KMF_FreeRawKey(&keys[i]);
+			free(keys);
+		}
+		keys = NULL;
+	}
+	*certs = tcerts;
+	*rsa = keys;
+
+	(void) KMF_Finalize(kmfh);
+
+	return (ncerts);
+}
+
+/*
+ * Parse a PEM file which should contain RSA private keys and
+ * their associated X.509v3 certificates.  More than 1 may
+ * be present in the file.
+ */
+int
+PEM_get_rsa_key_certs(const char *filename, char *password_file,
+    KMF_RAW_KEY_DATA **rsa, KMF_DATA **certs)
+{
+	KMF_HANDLE_T kmfh;
+	KMF_RETURN rv = KMF_OK;
+	KMF_CREDENTIAL creds;
+	KMF_DATA *tcerts;
+	KMF_RAW_KEY_DATA *keys;
+	int ncerts, nkeys;
+	char *err = NULL;
+	char password_buf[1024];
+
+	rv = KMF_Initialize(&kmfh, NULL, NULL);
+	if (rv != KMF_OK) {
+		REPORT_KMF_ERROR(rv, "Error initializing KMF", err);
+		return (0);
+	}
+
+	tcerts = NULL;
+	keys = NULL;
+	ncerts = 0;
+	nkeys = 0;
+
+	if (get_passphrase(password_file, password_buf,
+		sizeof (password_buf)) <= 0) {
+		perror("Unable to read passphrase");
+		goto done;
+	}
+	creds.cred = password_buf;
+	creds.credlen = strlen(password_buf);
+
+	rv = KMF_ImportKeypair(kmfh, (char *)filename, &creds, &tcerts, &ncerts,
+		&keys, &nkeys);
+	if (rv != KMF_OK) {
+		REPORT_KMF_ERROR(rv, "Error importing key data", err);
+	}
+
+done:
+	if (rv != KMF_OK) {
+		int i;
+		if (tcerts != NULL) {
+			for (i = 0; i < ncerts; i++)
+				KMF_FreeData(&tcerts[i]);
+			free(tcerts);
+		}
+		tcerts = NULL;
+		ncerts = 0;
+		if (keys != NULL) {
+			for (i = 0; i < nkeys; i++)
+				KMF_FreeRawKey(&keys[i]);
+			free(keys);
+		}
+		keys = NULL;
+	}
+	if (certs != NULL)
+		*certs = tcerts;
+	if (rsa != NULL)
+		*rsa = keys;
+
+	(void) KMF_Finalize(kmfh);
+
+	return (ncerts);
+}
--- a/usr/src/cmd/cmd-inet/usr.sbin/kssl/kssladm/openssl_util.c	Thu Jan 11 16:21:40 2007 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,406 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-#include <assert.h>
-#include <strings.h>
-#include <openssl/err.h>
-#include <openssl/pem.h>
-#include <openssl/x509.h>
-#include <openssl/pkcs12.h>
-#include "kssladm.h"
-
-static void
-print_crypto_error(void)
-{
-	ERR_load_crypto_strings();
-	ERR_print_errors_fp(stderr);
-}
-
-/* ARGSUSED */
-static int
-pem_password_callback(char *buf, int size, int rwflag, void *userdata)
-{
-	return (get_passphrase((const char *)userdata, buf, size));
-}
-
-
-static STACK_OF(X509_INFO) *
-PEM_get_x509_info_stack(const char *filename, char *password_file)
-{
-	FILE *fp;
-	STACK_OF(X509_INFO) *x509_info_stack;
-
-	fp = fopen(filename, "r");
-	if (fp == NULL) {
-		perror("Unable to open pem file for reading");
-		return (NULL);
-	}
-	if (verbose)
-		(void) printf("In PEM_get_x509_info_stack: %s opened\n",
-		    filename);
-
-	OpenSSL_add_all_algorithms();
-
-	x509_info_stack = PEM_X509_INFO_read(
-	    fp, NULL, pem_password_callback, password_file);
-	(void) fclose(fp);
-
-	if (x509_info_stack == NULL) {
-		print_crypto_error();
-	}
-
-	return (x509_info_stack);
-}
-
-static EVP_PKEY *
-PEM_get_key(const char *filename, const char *password_file)
-{
-	FILE *fp;
-	EVP_PKEY *pkey = NULL;
-
-	fp = fopen(filename, "r");
-	if (fp == NULL) {
-		perror("Unable to open pem file for reading");
-		return (NULL);
-	}
-	if (verbose)
-		(void) printf("In PEM_get_key: %s opened\n", filename);
-
-	OpenSSL_add_all_algorithms();
-
-	pkey = PEM_read_PrivateKey(fp, NULL, pem_password_callback,
-	    (char *)password_file);
-	(void) fclose(fp);
-
-	if (pkey == NULL) {
-		print_crypto_error();
-	}
-
-	return (pkey);
-}
-
-uchar_t *
-get_modulus(uchar_t *ber_buf, int buflen, int *modlen)
-{
-	int i, j, v;
-	X509 *x;
-	EVP_PKEY *pkey;
-	BIGNUM *bn;
-	uchar_t *m = NULL, *mptr;
-
-	x = d2i_X509(NULL, (const unsigned char **) &ber_buf, buflen);
-	if (x != NULL) {
-		pkey = X509_get_pubkey(x);
-		if (pkey == NULL) {
-			X509_free(x);
-			return (NULL);
-		}
-
-		bn = pkey->pkey.rsa->n;
-		mptr = m = malloc(bn->top * BN_BYTES);
-		for (i = bn->top - 1; i >= 0; i--) {
-			for (j = BN_BITS2 - 8; j >= 0; j -= 8) {
-				v = ((int)(bn->d[i] >> (long)j)) & 0xff;
-				*m = v;
-				m++;
-			}
-		}
-		*modlen = bn->top * BN_BYTES;
-		EVP_PKEY_free(pkey);
-		X509_free(x);
-	}
-
-	return (mptr);
-}
-
-static uchar_t *
-X509_to_bytes(X509 *cert, int *cert_size)
-{
-	uchar_t *cert_buf = NULL;
-	int size;
-
-	size = i2d_X509(cert, &cert_buf);
-	if (size < 0)  {
-		perror("Invalid cert\n");
-		return (NULL);
-	}
-
-	*cert_size = size;
-	return (cert_buf);
-}
-
-static uchar_t **
-init_cert_vars(int **rlens)
-{
-	int i;
-	uchar_t **cert_bufs;
-	int *lcert_lens;
-
-	cert_bufs = (uchar_t **)malloc(MAX_CHAIN_LENGTH * sizeof (uchar_t **));
-	if (cert_bufs == NULL)
-		return (NULL);
-	for (i = 0; i < MAX_CHAIN_LENGTH; i++)
-		cert_bufs[i] = NULL;
-
-	lcert_lens = malloc(MAX_CHAIN_LENGTH * sizeof (int));
-	if (lcert_lens == NULL) {
-		free(cert_bufs);
-		return (NULL);
-	}
-	for (i = 0; i < MAX_CHAIN_LENGTH; i++)
-		lcert_lens[i] = 0;
-
-	*rlens = lcert_lens;
-	return (cert_bufs);
-}
-
-static void
-print_subject(X509 *x)
-{
-	char buf[256];
-
-	(void) X509_NAME_oneline(X509_get_subject_name(x),
-	    buf, sizeof (buf));
-	(void) fprintf(stdout, "/* subject: %s */ \n", buf);
-}
-
-/*
- * Returns DER encoded certs in an array of pointers
- * and their sizes in cert_sizes. If the rsa argument is
- * not NULL, we return the RSA key in it. The caller needs
- * to free the structures when done.
- */
-uchar_t **
-PEM_get_rsa_key_certs(const char *filename, char *password_file,
-    RSA **rsa, int **cert_sizes, int *n)
-{
-	int i, cert_size, ncerts;
-	int *cert_lens;
-	uchar_t **cert_bufs;
-	EVP_PKEY *pkey = NULL;
-	X509_INFO *info;
-	X509_INFO *cert_infos[MAX_CHAIN_LENGTH];
-	STACK_OF(X509_INFO) *x509_info_stack;
-
-	x509_info_stack = PEM_get_x509_info_stack(filename, password_file);
-	if (x509_info_stack == NULL) {
-		return (NULL);
-	}
-
-	ncerts = 0;
-	/* LINTED */
-	while ((info = sk_X509_INFO_pop(x509_info_stack)) != NULL &&
-	    ncerts < MAX_CHAIN_LENGTH) {
-		cert_infos[ncerts] = info;
-		ncerts++;
-		if (verbose)
-			print_subject(info->x509);
-	}
-
-	if (ncerts == 0) {
-		(void) fprintf(stderr, "No cert found\n");
-		return (NULL);
-	}
-
-	if (rsa != NULL) {
-		X509 *x;
-
-		pkey = PEM_get_key(filename, password_file);
-		if (pkey == NULL)
-			return (NULL);
-
-		x = cert_infos[ncerts - 1]->x509;
-		if (!X509_check_private_key(x, pkey)) {
-			(void) fprintf(stderr, "Error: Server certificate "
-			    "and server private key do not match.\n");
-			EVP_PKEY_free(pkey);
-			return (NULL);
-		}
-
-		*rsa = EVP_PKEY_get1_RSA(pkey);
-	}
-
-	if ((cert_bufs = init_cert_vars(&cert_lens)) == NULL) {
-		if (pkey != NULL)
-			EVP_PKEY_free(pkey);
-		return (NULL);
-	}
-
-	/*
-	 * cert_infos[] is constructed from a stack of certificates structure
-	 * and hence the order is high level CA certificate first. SSL protocol
-	 * needs the certificates in the order of low level CA certificate
-	 * first. So, we walk cert_infos[] in reverse order below.
-	 */
-	for (i = 0; i < ncerts; i++) {
-		info =  cert_infos[ncerts - 1 - i];
-		cert_bufs[i] = X509_to_bytes(info->x509, &cert_size);
-		cert_lens[i] = cert_size;
-		X509_INFO_free(info);
-	}
-
-	*cert_sizes = cert_lens;
-	*n = ncerts;
-	return (cert_bufs);
-}
-
-static PKCS12 *
-PKCS12_load(const char *filename)
-{
-	FILE *fp;
-	PKCS12 *p12;
-
-	fp = fopen(filename, "r");
-	if (fp == NULL) {
-		perror("Unable to open file for reading");
-		return (NULL);
-	}
-
-	OpenSSL_add_all_algorithms();
-
-	p12 = d2i_PKCS12_fp(fp, NULL);
-	(void) fclose(fp);
-	if (p12 == NULL) {
-		ERR_load_PKCS12_strings();
-		ERR_print_errors_fp(stderr);
-		(void) fprintf(stderr, "Unable to load from %s\n", filename);
-		return (NULL);
-	}
-
-	return (p12);
-}
-
-/*
- * Returns DER encoded certs in an array of pointers and their
- * sizes in cert_sizes. The RSA key is returned in the rsa argument.
- * The caller needs to free the structures when done.
- */
-uchar_t **
-PKCS12_get_rsa_key_certs(const char *filename, const char *password_file,
-    RSA **rsa, int **cert_sizes, int *n)
-{
-	int i, ncerts, cert_size;
-	int *cert_lens;
-	char *password = NULL;
-	char password_buf[1024];
-	uchar_t **cert_bufs = NULL;
-	uchar_t *cert_buf;
-	PKCS12 *p12 = NULL;
-	EVP_PKEY *pkey = NULL;
-	X509 *x509 = NULL;
-	X509 *certs[MAX_CHAIN_LENGTH];
-	STACK_OF(X509) *ca = NULL;
-
-	p12 = PKCS12_load(filename);
-	if (p12 == NULL) {
-		return (NULL);
-	}
-
-	if (! PKCS12_verify_mac(p12, NULL, 0)) {
-		if (get_passphrase(
-		    password_file, password_buf, sizeof (password_buf)) <= 0) {
-			perror("Unable to read passphrase");
-			goto done;
-		}
-
-		password = password_buf;
-	}
-
-	if (PKCS12_parse(p12, password, &pkey, &x509, &ca) <= 0) {
-		(void) fprintf(stderr, "Unable to parse PKCS12 file.\n");
-		goto done;
-	}
-
-	if (pkey == NULL) {
-		(void) fprintf(stderr, "No key returned\n");
-		goto done;
-	}
-	if (x509 == NULL) {
-		(void) fprintf(stderr, "No cert returned\n");
-		goto done;
-	}
-
-	if (!X509_check_private_key(x509, pkey)) {
-		(void) fprintf(stderr, "Error: Server certificate and server "
-		    "private key do not match.\n");
-		goto done;
-	}
-
-	cert_buf = X509_to_bytes(x509, &cert_size);
-	if (cert_buf == NULL)
-		goto done;
-	X509_free(x509);
-
-	*rsa = EVP_PKEY_get1_RSA(pkey);
-	if (*rsa == NULL) {
-		goto done;
-	}
-
-	if ((cert_bufs = init_cert_vars(&cert_lens)) == NULL) {
-		RSA_free(*rsa);
-		goto done;
-	}
-
-	ncerts = 0;
-	cert_bufs[0] = cert_buf;
-	cert_lens[0] = cert_size;
-	ncerts++;
-
-	/* LINTED */
-	while ((ca != NULL) && ((x509 = sk_X509_pop(ca)) != NULL) &&
-	    ncerts < MAX_CHAIN_LENGTH) {
-		certs[ncerts] = x509;
-		ncerts++;
-		if (verbose)
-			print_subject(x509);
-	}
-
-	/*
-	 * certs[1..ncerts-1] is constructed from a stack of certificates
-	 * structure and hence the order is high level CA certificate first.
-	 * SSL protocol needs the certificates in the order of low level CA
-	 * certificate first. So, we walk certs[] in reverse order below.
-	 */
-	for (i = 1; i < ncerts; i++) {
-		x509 =  certs[ncerts - i];
-		cert_bufs[i] = X509_to_bytes(x509, &cert_size);
-		cert_lens[i] = cert_size;
-		X509_free(x509);
-	}
-
-	*cert_sizes = cert_lens;
-	*n = ncerts;
-
-done:
-	if (pkey != NULL)
-		EVP_PKEY_free(pkey);
-	if (p12 != NULL)
-		PKCS12_free(p12);
-
-	return (cert_bufs);
-}
--- a/usr/src/lib/libkmf/include/kmfapi.h	Thu Jan 11 16:21:40 2007 -0800
+++ b/usr/src/lib/libkmf/include/kmfapi.h	Thu Jan 11 18:12:31 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  *
  *
@@ -269,6 +269,8 @@
 extern KMF_RETURN KMF_ExportPK12(KMF_HANDLE_T, KMF_EXPORTP12_PARAMS *, char *);
 extern KMF_RETURN KMF_ImportPK12(KMF_HANDLE_T, char *, KMF_CREDENTIAL *,
 	KMF_DATA **, int *, KMF_RAW_KEY_DATA **, int *);
+extern KMF_RETURN KMF_ImportKeypair(KMF_HANDLE_T, char *, KMF_CREDENTIAL *,
+	KMF_DATA **, int *, KMF_RAW_KEY_DATA **, int *);
 
 /*
  * Get OCSP response operation.
@@ -339,6 +341,7 @@
 
 /* APIs for PKCS#11 token */
 extern KMF_RETURN KMF_PK11TokenLookup(KMF_HANDLE_T, char *, CK_SLOT_ID *);
+extern CK_SESSION_HANDLE KMF_GetPK11Handle(KMF_HANDLE_T);
 
 #ifdef __cplusplus
 }
--- a/usr/src/lib/libkmf/include/kmftypes.h	Thu Jan 11 16:21:40 2007 -0800
+++ b/usr/src/lib/libkmf/include/kmftypes.h	Thu Jan 11 18:12:31 2007 -0800
@@ -23,7 +23,7 @@
  *
  * Copyright (c) 1995-2000 Intel Corporation. All rights reserved.
  *
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -110,8 +110,10 @@
 	KMF_FORMAT_ASN1 =	1,	/* DER */
 	KMF_FORMAT_PEM =	2,
 	KMF_FORMAT_PKCS12 =	3,
-	KMF_FORMAT_RAWKEY =	4	/* For FindKey operation */
+	KMF_FORMAT_RAWKEY =	4,	/* For FindKey operation */
+	KMF_FORMAT_PEM_KEYPAIR = 5
 } KMF_ENCODE_FORMAT;
+#define	KMF_FORMAT_NATIVE KMF_FORMAT_UNDEF
 
 typedef enum {
 	KMF_ALL_CERTS =		0,
@@ -193,6 +195,7 @@
 	boolean_t	private; /* for finding CKA_PRIVATE objects */
 	boolean_t	sensitive;
 	boolean_t	not_extractable;
+	boolean_t	token; /* true == token object, false == session */
 } KMF_PKCS11_PARAMS;
 
 typedef struct {
@@ -599,7 +602,10 @@
 	KMF_ERR_UNINITIALIZED_TOKEN	= 0x4d,
 	KMF_ERR_INCOMPLETE_TBS_CERT	= 0x4e,
 	KMF_ERR_MISSING_ERRCODE		= 0x4f,
-	KMF_KEYSTORE_ALREADY_INITIALIZED = 0x50
+	KMF_KEYSTORE_ALREADY_INITIALIZED = 0x50,
+	KMF_ERR_SENSITIVE_KEY		= 0x51,
+	KMF_ERR_UNEXTRACTABLE_KEY	= 0x52,
+	KMF_ERR_KEY_MISMATCH		= 0x53
 } KMF_RETURN;
 
 typedef enum {
--- a/usr/src/lib/libkmf/libkmf/common/certop.c	Thu Jan 11 16:21:40 2007 -0800
+++ b/usr/src/lib/libkmf/libkmf/common/certop.c	Thu Jan 11 18:12:31 2007 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  *
  * Copyright(c) 1995-2000 Intel Corporation. All rights reserved.
@@ -2289,6 +2289,49 @@
 	return (rv);
 }
 
+KMF_RETURN
+KMF_ImportKeypair(KMF_HANDLE_T handle, char *filename,
+	KMF_CREDENTIAL *cred,
+	KMF_DATA **certs, int *ncerts,
+	KMF_RAW_KEY_DATA **rawkeys, int *nkeys)
+{
+	KMF_RETURN rv;
+	KMF_PLUGIN *plugin;
+	KMF_RETURN (*import_keypair)(KMF_HANDLE *,
+		char *, KMF_CREDENTIAL *,
+		KMF_DATA **, int *,
+		KMF_RAW_KEY_DATA **, int *);
+
+	CLEAR_ERROR(handle, rv);
+	if (rv != KMF_OK)
+		return (rv);
+
+	if (filename == NULL ||
+		cred == NULL ||
+		certs == NULL || ncerts == NULL ||
+		rawkeys == NULL || nkeys == NULL)
+		return (KMF_ERR_BAD_PARAMETER);
+
+	/*
+	 * Use the Keypair reader from the OpenSSL plugin.
+	 */
+	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
+	if (plugin == NULL || plugin->dldesc == NULL) {
+		return (KMF_ERR_PLUGIN_NOTFOUND);
+	}
+
+	import_keypair = (KMF_RETURN(*)())dlsym(plugin->dldesc,
+	    "openssl_import_keypair");
+	if (import_keypair == NULL) {
+		return (KMF_ERR_FUNCTION_NOT_FOUND);
+	}
+
+	/* Use OpenSSL interfaces to get raw key and cert data */
+	rv = import_keypair(handle, filename, cred, certs, ncerts,
+		rawkeys, nkeys);
+
+	return (rv);
+}
 
 KMF_BOOL
 IsEqualOid(KMF_OID *Oid1, KMF_OID *Oid2)
--- a/usr/src/lib/libkmf/libkmf/common/generalop.c	Thu Jan 11 16:21:40 2007 -0800
+++ b/usr/src/lib/libkmf/libkmf/common/generalop.c	Thu Jan 11 18:12:31 2007 -0800
@@ -19,10 +19,9 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright(c) 1995-2000 Intel Corporation. All rights reserved.
  */
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -135,7 +134,10 @@
 	{KMF_ERR_UNINITIALIZED_TOKEN,	"KMF_ERR_UNINITIALIZED_TOKEN"},
 	{KMF_ERR_INCOMPLETE_TBS_CERT,	"KMF_ERR_INCOMPLETE_TBS_CERT"},
 	{KMF_ERR_MISSING_ERRCODE,	"KMF_ERR_MISSING_ERRCODE"},
-	{KMF_KEYSTORE_ALREADY_INITIALIZED, "KMF_KEYSTORE_ALREADY_INITIALIZED"}
+	{KMF_KEYSTORE_ALREADY_INITIALIZED, "KMF_KEYSTORE_ALREADY_INITIALIZED"},
+	{KMF_ERR_SENSITIVE_KEY,		"KMF_ERR_SENSITIVE_KEY"},
+	{KMF_ERR_UNEXTRACTABLE_KEY,	"KMF_ERR_UNEXTRACTABLE_KEY"},
+	{KMF_ERR_KEY_MISMATCH,		"KMF_ERR_KEY_MISMATCH"}
 };
 
 
@@ -720,6 +722,8 @@
 		} else {
 			*fmt = KMF_FORMAT_ASN1;
 		}
+	} else if (memcmp(buf, "Bag Attr", 8) == 0) {
+		*fmt = KMF_FORMAT_PEM_KEYPAIR;
 	} else {
 		/* Cannot determine this file format */
 		*fmt = 0;
--- a/usr/src/lib/libkmf/libkmf/common/mapfile-vers	Thu Jan 11 16:21:40 2007 -0800
+++ b/usr/src/lib/libkmf/libkmf/common/mapfile-vers	Thu Jan 11 18:12:31 2007 -0800
@@ -18,8 +18,7 @@
 #
 # CDDL HEADER END
 #
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -105,12 +104,14 @@
 	KMF_GetKMFErrorString;
 	KMF_GetOCSPForCert;
 	KMF_GetOCSPStatusForCert;
+	KMF_GetPK11Handle;
 	KMF_GetPluginErrorString;
 	KMF_GetPolicy;
 	KMF_GetSymKeyValue;
 	KMF_HexString2Bytes;
 	KMF_ImportCRL;
 	KMF_ImportCert;
+	KMF_ImportKeypair;
 	KMF_ImportPK12;
 	KMF_Initialize;
 	KMF_IsCRLFile;
--- a/usr/src/lib/libkmf/libkmf/common/pk11tokens.c	Thu Jan 11 16:21:40 2007 -0800
+++ b/usr/src/lib/libkmf/libkmf/common/pk11tokens.c	Thu Jan 11 18:12:31 2007 -0800
@@ -17,11 +17,10 @@
  * information: Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
- */
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ *
+ *
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
- *
  */
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
@@ -529,3 +528,9 @@
 
 	return (kmf_rv);
 }
+
+CK_SESSION_HANDLE
+KMF_GetPK11Handle(KMF_HANDLE_T kmfh)
+{
+	return (kmfh->pk11handle);
+}
--- a/usr/src/lib/libkmf/plugins/kmf_openssl/common/mapfile-vers	Thu Jan 11 16:21:40 2007 -0800
+++ b/usr/src/lib/libkmf/plugins/kmf_openssl/common/mapfile-vers	Thu Jan 11 18:12:31 2007 -0800
@@ -18,8 +18,7 @@
 #
 # CDDL HEADER END
 #
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -56,6 +55,7 @@
 	OpenSSL_StorePrivateKey;
 	OpenSSL_VerifyCRLFile;
 	openssl_read_pkcs12;
+	openssl_import_keypair;
     local:
 	*;
 };
--- a/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c	Thu Jan 11 16:21:40 2007 -0800
+++ b/usr/src/lib/libkmf/plugins/kmf_openssl/common/openssl_spi.c	Thu Jan 11 18:12:31 2007 -0800
@@ -20,12 +20,13 @@
  *
  * OpenSSL keystore wrapper
  *
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #pragma ident	"%Z%%M%	%I%	%E% SMI"
 
+#include <stdlib.h>
 #include <kmfapiP.h>
 #include <ber_der.h>
 #include <oidsalg.h>
@@ -99,6 +100,13 @@
 mutex_t init_lock = DEFAULTMUTEX;
 static int ssl_initialized = 0;
 
+static KMF_RETURN
+extract_objects(KMF_HANDLE *, char *, CK_UTF8CHAR *, CK_ULONG,
+	EVP_PKEY **, KMF_DATA **, int *);
+
+static KMF_RETURN
+kmf_load_cert(KMF_HANDLE *, KMF_FINDCERT_PARAMS *, char *, KMF_DATA *);
+
 KMF_RETURN
 OpenSSL_FindCert(KMF_HANDLE_T,
 	KMF_FINDCERT_PARAMS *,
@@ -567,6 +575,99 @@
 	return (rv);
 }
 
+static int
+datacmp(const void *a, const void *b)
+{
+	KMF_DATA *adata = (KMF_DATA *)a;
+	KMF_DATA *bdata = (KMF_DATA *)b;
+	if (adata->Length > bdata->Length)
+		return (-1);
+	if (adata->Length < bdata->Length)
+		return (1);
+	return (0);
+}
+
+static KMF_RETURN
+load_certs(KMF_HANDLE *kmfh, KMF_FINDCERT_PARAMS *params, char *pathname,
+	KMF_DATA **certlist, uint32_t *numcerts)
+{
+	KMF_RETURN rv = KMF_OK;
+	int i;
+	KMF_DATA *certs = NULL;
+	int nc = 0;
+	int hits = 0;
+	KMF_ENCODE_FORMAT format;
+
+	rv = KMF_GetFileFormat(pathname, &format);
+	if (rv != KMF_OK) {
+		if (rv == KMF_ERR_OPEN_FILE)
+			rv = KMF_ERR_CERT_NOT_FOUND;
+		return (rv);
+	}
+	if (format == KMF_FORMAT_ASN1) {
+		/* load a single certificate */
+		certs = (KMF_DATA *)malloc(sizeof (KMF_DATA));
+		if (certs == NULL)
+			return (KMF_ERR_MEMORY);
+		certs->Data = NULL;
+		certs->Length = 0;
+		rv = kmf_load_cert(kmfh, params, pathname, certs);
+		if (rv == KMF_OK) {
+			*certlist = certs;
+			*numcerts = 1;
+		}
+		return (rv);
+	} else if (format == KMF_FORMAT_PKCS12) {
+		/* We need a credential to access a PKCS#12 file */
+		rv = KMF_ERR_BAD_CERT_FORMAT;
+	} else if (format == KMF_FORMAT_PEM ||
+		format != KMF_FORMAT_PEM_KEYPAIR) {
+
+		/* This function only works on PEM files */
+		rv = extract_objects(kmfh, pathname,
+			(uchar_t *)NULL, 0, NULL,
+			&certs, &nc);
+	} else {
+		return (KMF_ERR_ENCODING);
+	}
+
+	if (rv != KMF_OK)
+		return (rv);
+
+	for (i = 0; i < nc; i++) {
+		if (params->find_cert_validity == KMF_NONEXPIRED_CERTS) {
+			rv = KMF_CheckCertDate(kmfh, &certs[i]);
+		} else if (params->find_cert_validity == KMF_EXPIRED_CERTS) {
+			rv = KMF_CheckCertDate(kmfh, &certs[i]);
+			if (rv == KMF_OK)
+				rv = KMF_ERR_CERT_NOT_FOUND;
+			if (rv == KMF_ERR_VALIDITY_PERIOD)
+				rv = KMF_OK;
+		}
+		if (rv != KMF_OK) {
+			/* Remove this cert from the list by clearing it. */
+			KMF_FreeData(&certs[i]);
+		} else {
+			hits++; /* count valid certs found */
+		}
+		rv = KMF_OK;
+	}
+	if (rv == KMF_OK && hits == 0) {
+		rv = KMF_ERR_CERT_NOT_FOUND;
+	} else if (rv == KMF_OK && hits > 0) {
+		/*
+		 * Sort the list of certs by length to put the cleared ones
+		 * at the end so they don't get accessed by the caller.
+		 */
+		qsort((void *)certs, nc, sizeof (KMF_DATA), datacmp);
+		*certlist = certs;
+
+		/* since we sorted the list, just return the number of hits */
+		*numcerts = hits;
+	}
+	return (rv);
+}
+
 static KMF_RETURN
 kmf_load_cert(KMF_HANDLE *kmfh,
 	KMF_FINDCERT_PARAMS *params,
@@ -631,7 +732,8 @@
 
 	if (format == KMF_FORMAT_ASN1)
 		pkey = d2i_PrivateKey_bio(keyfile, NULL);
-	else if (format == KMF_FORMAT_PEM)
+	else if (format == KMF_FORMAT_PEM ||
+		format == KMF_FORMAT_PEM_KEYPAIR)
 		pkey = PEM_read_bio_PrivateKey(keyfile, NULL, NULL, NULL);
 
 end:
@@ -652,8 +754,8 @@
 {
 	KMF_RETURN rv = KMF_OK;
 	KMF_HANDLE *kmfh = (KMF_HANDLE *)handle;
-	KMF_DATA certdata = {NULL, 0};
 	char *fullpath;
+	int i;
 
 	if (num_certs == NULL || params == NULL)
 		return (KMF_ERR_BAD_PARAMETER);
@@ -677,6 +779,9 @@
 		}
 		while ((dp = readdir(dirp)) != NULL) {
 			char *fname;
+			KMF_DATA *certlist = NULL;
+			uint32_t numcerts = 0;
+
 			if (strcmp(dp->d_name, ".") == 0 ||
 			    strcmp(dp->d_name, "..") == 0)
 				continue;
@@ -684,34 +789,43 @@
 			fname = get_fullpath(fullpath,
 				(char *)&dp->d_name);
 
-			rv = kmf_load_cert(kmfh, params, fname,
-				&certdata);
+			rv = load_certs(kmfh, params, fname, &certlist,
+				&numcerts);
 
 			if (rv != KMF_OK) {
 				free(fname);
-				KMF_FreeData(&certdata);
+				if (certlist != NULL) {
+					for (i = 0; i < numcerts; i++)
+						KMF_FreeData(&certlist[i]);
+					free(certlist);
+				}
 				continue;
 			}
 
 			/* If load succeeds, add certdata to the list */
 			if (kmf_cert != NULL) {
-				kmf_cert[n].certificate.Data = certdata.Data;
-				kmf_cert[n].certificate.Length =
-					certdata.Length;
-
-				kmf_cert[n].kmf_private.keystore_type =
-					KMF_KEYSTORE_OPENSSL;
-				kmf_cert[n].kmf_private.flags =
-					KMF_FLAG_CERT_VALID;
-				kmf_cert[n].kmf_private.label = fname;
-
-				certdata.Data = NULL;
-				certdata.Length = 0;
+				for (i = 0; i < numcerts; i++) {
+					kmf_cert[n].certificate.Data =
+						certlist[i].Data;
+					kmf_cert[n].certificate.Length =
+						certlist[i].Length;
+
+					kmf_cert[n].kmf_private.keystore_type =
+						KMF_KEYSTORE_OPENSSL;
+					kmf_cert[n].kmf_private.flags =
+						KMF_FLAG_CERT_VALID;
+					kmf_cert[n].kmf_private.label =
+						strdup(fname);
+					n++;
+				}
+				free(certlist);
 			} else {
-				free(fname);
-				KMF_FreeData(&certdata);
+				for (i = 0; i < numcerts; i++)
+					KMF_FreeData(&certlist[i]);
+				free(certlist);
+				n += numcerts;
 			}
-			n++;
+			free(fname);
 		}
 		(*num_certs) = n;
 		if (*num_certs == 0)
@@ -721,33 +835,42 @@
 exit:
 		(void) closedir(dirp);
 	} else {
-		/* Just try to load a single certificate */
-		rv = kmf_load_cert(kmfh, params, fullpath, &certdata);
+		KMF_DATA *certlist = NULL;
+		uint32_t numcerts = 0;
+
+		rv = load_certs(kmfh, params, fullpath, &certlist, &numcerts);
 		if (rv != KMF_OK) {
 			free(fullpath);
-			KMF_FreeData(&certdata);
 			return (rv);
 		}
 
-		if (kmf_cert != NULL) {
-			kmf_cert->certificate.Data = certdata.Data;
-			kmf_cert->certificate.Length = certdata.Length;
-			kmf_cert->kmf_private.keystore_type =
-				KMF_KEYSTORE_OPENSSL;
-			kmf_cert->kmf_private.flags = KMF_FLAG_CERT_VALID;
-			kmf_cert->kmf_private.label = fullpath;
+		if (kmf_cert != NULL && certlist != NULL) {
+			for (i = 0; i < numcerts; i++) {
+				kmf_cert[i].certificate.Data =
+					certlist[i].Data;
+				kmf_cert[i].certificate.Length =
+					certlist[i].Length;
+				kmf_cert[i].kmf_private.keystore_type =
+					KMF_KEYSTORE_OPENSSL;
+				kmf_cert[i].kmf_private.flags =
+					KMF_FLAG_CERT_VALID;
+				kmf_cert[i].kmf_private.label =
+					strdup(fullpath);
+			}
+			free(certlist);
 		} else {
-			KMF_FreeData(&certdata);
+			if (certlist != NULL) {
+				for (i = 0; i < numcerts; i++)
+					KMF_FreeData(&certlist[i]);
+				free(certlist);
+			}
 		}
-
-		*num_certs = 1;
-	}
-
-	if (kmf_cert == NULL || rv != KMF_OK)
-		free(fullpath);
+		*num_certs = numcerts;
+	}
+
+	free(fullpath);
 
 	return (rv);
-
 }
 
 void
@@ -3265,6 +3388,107 @@
 	return (rv);
 }
 
+#define	MAX_CHAIN_LENGTH 100
+/*
+ * Helper function to extract keys and certificates from
+ * a single PEM file.  Typically the file should contain a
+ * private key and an associated public key wrapped in an x509 cert.
+ * However, the file may be just a list of X509 certs with no keys.
+ */
+static KMF_RETURN
+extract_objects(KMF_HANDLE *kmfh, char *filename, CK_UTF8CHAR *pin,
+	CK_ULONG pinlen, EVP_PKEY **priv_key, KMF_DATA **certs,
+	int *numcerts)
+/* ARGSUSED */
+{
+	KMF_RETURN rv = KMF_OK;
+	FILE *fp;
+	STACK_OF(X509_INFO) *x509_info_stack;
+	int i, ncerts = 0;
+	EVP_PKEY *pkey = NULL;
+	X509_INFO *info;
+	X509 *x;
+	X509_INFO *cert_infos[MAX_CHAIN_LENGTH];
+	KMF_DATA *certlist = NULL;
+
+	if (priv_key)
+		*priv_key = NULL;
+	if (certs)
+		*certs = NULL;
+	fp = fopen(filename, "r");
+	if (fp == NULL) {
+		return (KMF_ERR_OPEN_FILE);
+	}
+	x509_info_stack = PEM_X509_INFO_read(fp, NULL, NULL, pin);
+	if (x509_info_stack == NULL) {
+		(void) fclose(fp);
+		return (KMF_ERR_ENCODING);
+	}
+
+	/*LINTED*/
+	while ((info = sk_X509_INFO_pop(x509_info_stack)) != NULL &&
+		ncerts < MAX_CHAIN_LENGTH) {
+		cert_infos[ncerts] = info;
+		ncerts++;
+	}
+
+	if (ncerts == 0) {
+		(void) fclose(fp);
+		return (KMF_ERR_CERT_NOT_FOUND);
+	}
+
+	if (priv_key != NULL) {
+		rewind(fp);
+		pkey = PEM_read_PrivateKey(fp, NULL, NULL, pin);
+	}
+	(void) fclose(fp);
+
+	x = cert_infos[ncerts - 1]->x509;
+	/*
+	 * Make sure the private key matchs the last cert in the file.
+	 */
+	if (pkey != NULL && !X509_check_private_key(x, pkey)) {
+		EVP_PKEY_free(pkey);
+		return (KMF_ERR_KEY_MISMATCH);
+	}
+
+	certlist = (KMF_DATA *)malloc(ncerts * sizeof (KMF_DATA));
+	if (certlist == NULL) {
+		if (pkey != NULL)
+			EVP_PKEY_free(pkey);
+		X509_INFO_free(info);
+		return (KMF_ERR_MEMORY);
+	}
+
+	/*
+	 * Convert all of the certs to DER format.
+	 */
+	for (i = 0; rv == KMF_OK && certs != NULL && i < ncerts; i++) {
+		info =  cert_infos[ncerts - 1 - i];
+
+		rv = ssl_cert2KMFDATA(kmfh, info->x509, &certlist[i]);
+
+		if (rv != KMF_OK) {
+			free(certlist);
+			certlist = NULL;
+			ncerts = 0;
+		}
+		X509_INFO_free(info);
+	}
+
+	if (numcerts != NULL)
+		*numcerts = ncerts;
+	if (certs != NULL)
+		*certs = certlist;
+
+	if (priv_key == NULL && pkey != NULL)
+		EVP_PKEY_free(pkey);
+	else if (priv_key != NULL && pkey != NULL)
+		*priv_key = pkey;
+
+	return (rv);
+}
+
 /*
  * Helper function to decrypt and parse PKCS#12 import file.
  */
@@ -3517,7 +3741,7 @@
 	}
 
 	/* Also add any included CA certs to the list */
-	for (i = 0; i != sk_X509_num(sslcacerts); i++) {
+	for (i = 0; sslcacerts != NULL && i < sk_X509_num(sslcacerts); i++) {
 		X509 *c;
 		/*
 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
@@ -3601,6 +3825,54 @@
 }
 
 KMF_RETURN
+openssl_import_keypair(KMF_HANDLE *kmfh,
+	char *filename, KMF_CREDENTIAL *cred,
+	KMF_DATA **certlist, int *ncerts,
+	KMF_RAW_KEY_DATA **keylist, int *nkeys)
+{
+	KMF_RETURN	rv = KMF_OK;
+	EVP_PKEY	*privkey = NULL;
+	KMF_ENCODE_FORMAT format;
+
+	/*
+	 * auto-detect the file format, regardless of what
+	 * the 'format' parameters in the params say.
+	 */
+	rv = KMF_GetFileFormat(filename, &format);
+	if (rv != KMF_OK) {
+		if (rv == KMF_ERR_OPEN_FILE)
+			rv = KMF_ERR_CERT_NOT_FOUND;
+		return (rv);
+	}
+
+	/* This function only works on PEM files */
+	if (format != KMF_FORMAT_PEM &&
+		format != KMF_FORMAT_PEM_KEYPAIR)
+		return (KMF_ERR_ENCODING);
+
+	*certlist = NULL;
+	*keylist = NULL;
+	*ncerts = 0;
+	*nkeys = 0;
+	rv = extract_objects(kmfh, filename,
+		(uchar_t *)cred->cred,
+		(uint32_t)cred->credlen,
+		&privkey, certlist, ncerts);
+
+	/* Reached end of import file? */
+	if (rv == KMF_OK)
+		/* Convert keys and certs to exportable format */
+		rv = convertPK12Objects(kmfh, privkey, NULL, NULL,
+			keylist, nkeys, NULL, NULL);
+
+end:
+	if (privkey)
+		EVP_PKEY_free(privkey);
+
+	return (rv);
+}
+
+KMF_RETURN
 OpenSSL_StorePrivateKey(KMF_HANDLE_T handle, KMF_STOREKEY_PARAMS *params,
 	KMF_RAW_KEY_DATA *key)
 {
--- a/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c	Thu Jan 11 16:21:40 2007 -0800
+++ b/usr/src/lib/libkmf/plugins/kmf_pkcs11/common/pkcs11_spi.c	Thu Jan 11 18:12:31 2007 -0800
@@ -21,7 +21,7 @@
 /*
  * PKCS11 token KMF Plugin
  *
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -57,6 +57,9 @@
 search_certs(KMF_HANDLE_T, char *, char *, char *, KMF_BIGINT *,
 	boolean_t, KMF_CERT_VALIDITY, OBJLIST **, uint32_t *);
 
+static CK_RV
+getObjectLabel(KMF_HANDLE_T, CK_OBJECT_HANDLE, char **);
+
 static KMF_RETURN
 keyObj2RawKey(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_KEY_DATA **);
 
@@ -213,13 +216,12 @@
 
 	CK_CERTIFICATE_TYPE cktype;
 	CK_OBJECT_CLASS	class;
-	CK_BBOOL	cktrusted, token;
 	CK_ULONG subject_len, value_len, issuer_len, serno_len, id_len;
 	CK_BYTE *subject = NULL, *value = NULL;
-	CK_BYTE *label = NULL;
-	CK_ULONG label_len = 0;
+	char *label = NULL;
 	CK_ATTRIBUTE templ[10];
 
+	(void) memset(templ, 0, 10 * sizeof (CK_ATTRIBUTE));
 	SETATTR(templ, 0, CKA_CLASS, &class, sizeof (class));
 
 	/*  Is this a certificate object ? */
@@ -230,30 +232,32 @@
 	}
 
 	SETATTR(templ, 0, CKA_CERTIFICATE_TYPE, &cktype, sizeof (cktype));
-	SETATTR(templ, 1, CKA_TOKEN, &token, sizeof (token));
-	SETATTR(templ, 2, CKA_TRUSTED, &cktrusted, sizeof (cktrusted));
-
-	ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 3);
+	ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 1);
 
 	if (ckrv != CKR_OK || cktype != CKC_X_509)  {
 		SET_ERROR(kmfh, ckrv);
 		return (ckrv);
 	} else {
+		int i = 0;
 		/* What attributes are available and how big are they? */
-		subject_len = issuer_len = serno_len = id_len = value_len =
-			label_len = 0;
-		SETATTR(templ, 0, CKA_SUBJECT,	NULL, subject_len);
-		SETATTR(templ, 1, CKA_ISSUER,	NULL, issuer_len);
-		SETATTR(templ, 2, CKA_SERIAL_NUMBER, NULL, serno_len);
-		SETATTR(templ, 3, CKA_ID, NULL, id_len);
-		SETATTR(templ, 4, CKA_VALUE, NULL, value_len);
-		SETATTR(templ, 5, CKA_LABEL, NULL, label_len);
+		subject_len = issuer_len = serno_len = id_len = value_len = 0;
+
+		SETATTR(templ, i, CKA_SUBJECT,	NULL, subject_len);
+		i++;
+		SETATTR(templ, i, CKA_ISSUER,	NULL, issuer_len);
+		i++;
+		SETATTR(templ, i, CKA_SERIAL_NUMBER, NULL, serno_len);
+		i++;
+		SETATTR(templ, i, CKA_ID, NULL, id_len);
+		i++;
+		SETATTR(templ, i, CKA_VALUE, NULL, value_len);
+		i++;
 
 		/*
 		 * Query the object with NULL values in the pValue spot
 		 * so we know how much space to allocate for each field.
 		 */
-		ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, 6);
+		ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj, templ, i);
 		if (ckrv != CKR_OK)  {
 			SET_ERROR(kmfh, ckrv);
 			return (KMF_ERR_INTERNAL); /* TODO - Error messages ? */
@@ -264,7 +268,6 @@
 		serno_len	= templ[2].ulValueLen;
 		id_len		= templ[3].ulValueLen;
 		value_len	= templ[4].ulValueLen;
-		label_len	= templ[5].ulValueLen;
 
 		/*
 		 * For PKCS#11 CKC_X_509 certificate objects,
@@ -288,17 +291,6 @@
 
 			SETATTR(templ, i, CKA_VALUE, value, value_len);
 			i++;
-			if (label_len > 0) {
-				label = malloc(label_len + 1);
-				if (label == NULL) {
-					rv = KMF_ERR_MEMORY;
-					goto errout;
-				}
-				(void) memset(label, 0, label_len + 1);
-				SETATTR(templ, i, CKA_LABEL, label,
-					label_len);
-				i++;
-			}
 
 			/* re-query the object with room for the value attr */
 			ckrv = C_GetAttributeValue(kmfh->pk11handle, hObj,
@@ -315,7 +307,11 @@
 			kmfcert->kmf_private.flags |= KMF_FLAG_CERT_SIGNED;
 			kmfcert->kmf_private.keystore_type =
 				KMF_KEYSTORE_PK11TOKEN;
-			kmfcert->kmf_private.label = (char *)label;
+
+			ckrv = getObjectLabel(kmfh, hObj, &label);
+			if (ckrv == CKR_OK && label != NULL) {
+				kmfcert->kmf_private.label = (char *)label;
+			}
 
 			rv = KMF_OK;
 		}
@@ -1024,7 +1020,7 @@
 
 	CK_RV ckrv;
 	CK_ULONG subject_len, issuer_len, serno_len;
-	CK_BYTE *subject, *issuer, *serial;
+	CK_BYTE *subject, *issuer, *serial, nullserno;
 	CK_BBOOL true = TRUE;
 	CK_CERTIFICATE_TYPE certtype = CKC_X_509;
 	CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
@@ -1082,8 +1078,13 @@
 		serial = signed_cert_ptr->certificate.serialNumber.val;
 		serno_len = signed_cert_ptr->certificate.serialNumber.len;
 	} else {
-		rv = KMF_ERR_ENCODING;
-		goto cleanup;
+		/*
+		 * RFC3280 says to gracefully handle certs with serial numbers
+		 * of 0.
+		 */
+		nullserno = '\0';
+		serial  = &nullserno;
+		serno_len = 1;
 	}
 
 	/* Generate an ID from the SPKI data */
@@ -1110,7 +1111,6 @@
 		SETATTR(x509templ, i, CKA_LABEL, label, strlen(label));
 		i++;
 	}
-
 	/*
 	 * The cert object handle is actually "leaked" here.  If the app
 	 * really wants to clean up the data space, it will have to call
@@ -1999,6 +1999,7 @@
 get_raw_rsa(KMF_HANDLE *kmfh, CK_OBJECT_HANDLE obj, KMF_RAW_RSA_KEY *rawrsa)
 {
 	KMF_RETURN rv = KMF_OK;
+	CK_RV ckrv;
 	CK_SESSION_HANDLE sess = kmfh->pk11handle;
 	CK_ATTRIBUTE	rsa_pri_attrs[8] = {
 		{ CKA_MODULUS, NULL, 0 },
@@ -2013,10 +2014,16 @@
 	CK_ULONG	count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
 	int		i;
 
-	if ((rv = C_GetAttributeValue(sess, obj,
+	if ((ckrv = C_GetAttributeValue(sess, obj,
 			rsa_pri_attrs, count)) != CKR_OK) {
-		SET_ERROR(kmfh, rv);
-		return (KMF_ERR_INTERNAL);
+		SET_ERROR(kmfh, ckrv);
+		/* Tell the caller know why the key data cannot be retrieved. */
+		if (ckrv == CKR_ATTRIBUTE_SENSITIVE)
+			return (KMF_ERR_SENSITIVE_KEY);
+		else if (ckrv == CKR_KEY_UNEXTRACTABLE)
+			return (KMF_ERR_UNEXTRACTABLE_KEY);
+		else
+			return (KMF_ERR_INTERNAL);
 	}
 
 	/* Allocate memory for each attribute. */
@@ -2314,7 +2321,6 @@
 	CK_ATTRIBUTE pTmpl[10];
 	CK_OBJECT_CLASS class;
 	CK_BBOOL true = TRUE;
-	CK_BBOOL false = FALSE;
 	CK_ULONG alg;
 	CK_BBOOL is_token;
 
@@ -2332,15 +2338,13 @@
 	else
 		want_keys = MAXINT; /* count them all */
 
+	is_token = parms->pkcs11parms.token;
 	if (parms->keyclass == KMF_ASYM_PUB) {
 		class = CKO_PUBLIC_KEY;
-		is_token = false;
 	} else if (parms->keyclass == KMF_ASYM_PRI) {
 		class = CKO_PRIVATE_KEY;
-		is_token = true;
 	} else if (parms->keyclass == KMF_SYMMETRIC) {
 		class = CKO_SECRET_KEY;
-		is_token = true;
 	} else {
 		return (KMF_ERR_BAD_KEY_CLASS);
 	}
@@ -2403,7 +2407,11 @@
 		i++;
 	}
 
-	if (is_token) {
+	/*
+	 * Authenticate if the object is a token object,
+	 * a private or secred key, or if the user passed in credentials.
+	 */
+	if (parms->cred.credlen > 0) {
 		rv = pk11_authenticate(handle, &parms->cred);
 		if (rv != KMF_OK) {
 			return (rv);
@@ -2462,17 +2470,18 @@
 		/* "numkeys" indicates the number that were actually found */
 		*numkeys = n;
 	}
-	if (ckrv == KMF_OK && keys != NULL && (*numkeys) > 0 &&
-		parms->format == KMF_FORMAT_RAWKEY) {
-		/* Convert keys to "rawkey" format */
-		for (i = 0; i < (*numkeys); i++) {
-			KMF_RAW_KEY_DATA *rkey = NULL;
-			rv = keyObj2RawKey(handle, &keys[i], &rkey);
-			if (rv == KMF_OK) {
-				keys[i].keyp = rkey;
-				keys[i].israw = TRUE;
-			} else {
-				break;
+	if (ckrv == KMF_OK && keys != NULL && (*numkeys) > 0) {
+		if (parms->format == KMF_FORMAT_RAWKEY) {
+			/* Convert keys to "rawkey" format */
+			for (i = 0; i < (*numkeys); i++) {
+				KMF_RAW_KEY_DATA *rkey = NULL;
+				rv = keyObj2RawKey(handle, &keys[i], &rkey);
+				if (rv == KMF_OK) {
+					keys[i].keyp = rkey;
+					keys[i].israw = TRUE;
+				} else {
+					break;
+				}
 			}
 		}
 	}
@@ -2604,6 +2613,7 @@
 	SETATTR(templ, i, CKA_TOKEN, &cktrue, sizeof (cktrue)); i++;
 	SETATTR(templ, i, CKA_PRIVATE, &cktrue, sizeof (cktrue)); i++;
 	SETATTR(templ, i, CKA_SUBJECT, subject.Data, subject.Length); i++;
+	SETATTR(templ, i, CKA_DECRYPT, &cktrue, sizeof (cktrue)); i++;
 
 	/*
 	 * Only set the KeyUsage stuff if the KU extension was present.