changeset 6669:bc95c5ad177e

PSARC 2008/306 pktool CLI update (dir option correction) 6670712 cert of dsa type with key pair can not signcsr of rsa type, viceversa. 6670714 pktool gencert keystore=nss and keytype=dsa FAIL, parameter error 6670715 pktool gencsr keystore=nss and token="install" (something not "internal") core dumped 6670725 pktool signcsr command fails to update the keyusage values. 6699535 pktool operations should not have "dir" option for file-based keystore 6700175 fix for 6654080 is not complete
author wyllys
date Tue, 20 May 2008 12:13:00 -0700
parents 9fa3fc23fb8f
children 1961a43f2335
files usr/src/cmd/cmd-crypto/pktool/Makefile usr/src/cmd/cmd-crypto/pktool/common.c usr/src/cmd/cmd-crypto/pktool/common.h usr/src/cmd/cmd-crypto/pktool/delete.c usr/src/cmd/cmd-crypto/pktool/export.c usr/src/cmd/cmd-crypto/pktool/gencert.c usr/src/cmd/cmd-crypto/pktool/gencsr.c usr/src/cmd/cmd-crypto/pktool/import.c usr/src/cmd/cmd-crypto/pktool/pktool.c usr/src/cmd/cmd-crypto/pktool/signcsr.c usr/src/lib/libkmf/include/kmfapiP.h usr/src/lib/libkmf/libkmf/common/certgetsetop.c usr/src/lib/libkmf/libkmf/common/certop.c usr/src/lib/libkmf/libkmf/common/kmfoids.c usr/src/lib/libkmf/libkmf/common/mapfile-vers
diffstat 15 files changed, 157 insertions(+), 143 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/cmd-crypto/pktool/Makefile	Tue May 20 10:53:08 2008 -0700
+++ b/usr/src/cmd/cmd-crypto/pktool/Makefile	Tue May 20 12:13:00 2008 -0700
@@ -48,7 +48,7 @@
 POFILE = $(PROG)_msg.po
 MSGFILES=$(SRCS:%.c=%.i)
 
-CPPFLAGS += -I. -I$(KMFDIR)/include
+CPPFLAGS += -I. -I$(KMFDIR)/include -I/usr/include/libxml2
 CFLAGS += $(CCVERBOSE) -DDEBUG
 
 LDFLAGS += -L$(SRC)/lib/libkmf/libkmf/$(MACH)
--- a/usr/src/cmd/cmd-crypto/pktool/common.c	Tue May 20 10:53:08 2008 -0700
+++ b/usr/src/cmd/cmd-crypto/pktool/common.c	Tue May 20 12:13:00 2008 -0700
@@ -73,8 +73,8 @@
  * Perform PKCS#11 setup here.  Currently only C_Initialize is required,
  * along with setting/resetting state variables.
  */
-CK_RV
-init_pk11(void)
+static CK_RV
+init_pkcs11(void)
 {
 	CK_RV		rv = CKR_OK;
 
@@ -269,7 +269,7 @@
 	int		rv = CKR_OK;
 
 	if (!initialized)
-		if ((rv = init_pk11()) != CKR_OK)
+		if ((rv = init_pkcs11()) != CKR_OK)
 			return (rv);
 
 	/*
--- a/usr/src/cmd/cmd-crypto/pktool/common.h	Tue May 20 10:53:08 2008 -0700
+++ b/usr/src/cmd/cmd-crypto/pktool/common.h	Tue May 20 12:13:00 2008 -0700
@@ -86,7 +86,6 @@
 } EKU_LIST;
 
 /* Common functions. */
-extern CK_RV	init_pk11(void);
 extern void	final_pk11(CK_SESSION_HANDLE sess);
 
 extern CK_RV	login_token(CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin,
--- a/usr/src/cmd/cmd-crypto/pktool/delete.c	Tue May 20 10:53:08 2008 -0700
+++ b/usr/src/cmd/cmd-crypto/pktool/delete.c	Tue May 20 12:13:00 2008 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -673,22 +673,20 @@
 }
 
 static KMF_RETURN
-delete_file_crl(void *kmfhandle, char *dir, char *filename)
+delete_file_crl(void *kmfhandle, char *filename)
 {
 	KMF_RETURN rv;
 	int numattr = 0;
 	KMF_ATTRIBUTE attrlist[4];
 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
 
+	if (filename == NULL || strlen(filename) == 0)
+		return (KMF_ERR_BAD_PARAMETER);
+
 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
 	    &kstype, sizeof (kstype));
 	numattr++;
 
-	if (dir) {
-		kmf_set_attr_at_index(attrlist, numattr, KMF_DIRPATH_ATTR,
-		    dir, strlen(dir));
-		numattr++;
-	}
 	if (filename) {
 		kmf_set_attr_at_index(attrlist, numattr, KMF_CRL_FILENAME_ATTR,
 		    filename, strlen(filename));
@@ -897,7 +895,7 @@
 			}
 			if (oclass & PK_CRL_OBJ)
 				kmfrv = delete_file_crl(kmfhandle,
-				    dir, infile);
+				    infile);
 			break;
 		case KMF_KEYSTORE_NSS:
 			if (oclass & PK_KEY_OBJ) {
@@ -938,7 +936,7 @@
 			}
 			if (oclass & PK_CRL_OBJ)
 				kmfrv = delete_file_crl(kmfhandle,
-				    dir, infile);
+				    infile);
 			break;
 		default:
 			rv = PK_ERR_USAGE;
--- a/usr/src/cmd/cmd-crypto/pktool/export.c	Tue May 20 10:53:08 2008 -0700
+++ b/usr/src/cmd/cmd-crypto/pktool/export.c	Tue May 20 12:13:00 2008 -0700
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  *
  *
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -86,7 +86,7 @@
 static KMF_RETURN
 pk_export_file_objects(KMF_HANDLE_T kmfhandle, int oclass,
 	char *issuer, char *subject, KMF_BIGINT *serial,
-	char *dir, char *infile, char *filename)
+	char *infile, char *filename)
 {
 	KMF_RETURN rv = KMF_OK;
 	KMF_X509_DER_CERT kmfcert;
@@ -122,13 +122,6 @@
 			numattr++;
 		}
 
-		if (dir != NULL) {
-			kmf_set_attr_at_index(attrlist, numattr,
-			    KMF_DIRPATH_ATTR, dir,
-			    strlen(dir));
-			numattr++;
-		}
-
 		if (infile != NULL) {
 			kmf_set_attr_at_index(attrlist, numattr,
 			    KMF_CERT_FILENAME_ATTR, infile,
@@ -243,7 +236,7 @@
 
 static KMF_RETURN
 pk_export_pk12_files(KMF_HANDLE_T kmfhandle,
-	char *certfile, char *keyfile, char *dir,
+	char *certfile, char *keyfile,
 	char *outfile)
 {
 	KMF_RETURN rv;
@@ -257,12 +250,6 @@
 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
 	numattr++;
 
-	if (dir != NULL) {
-		kmf_set_attr_at_index(attrlist, numattr,
-		    KMF_DIRPATH_ATTR, dir, strlen(dir));
-		numattr++;
-	}
-
 	if (certfile != NULL) {
 		kmf_set_attr_at_index(attrlist, numattr,
 		    KMF_CERT_FILENAME_ATTR, certfile, strlen(certfile));
@@ -929,12 +916,11 @@
 		case KMF_KEYSTORE_OPENSSL:
 			if (kfmt == KMF_FORMAT_PKCS12)
 				rv = pk_export_pk12_files(kmfhandle,
-				    certfile, keyfile, dir,
-				    filename);
+				    certfile, keyfile, filename);
 			else
 				rv = pk_export_file_objects(kmfhandle, oclass,
 				    issuer, subject, &serial,
-				    dir, infile, filename);
+				    infile, filename);
 			break;
 		default:
 			rv = PK_ERR_USAGE;
--- a/usr/src/cmd/cmd-crypto/pktool/gencert.c	Tue May 20 10:53:08 2008 -0700
+++ b/usr/src/cmd/cmd-crypto/pktool/gencert.c	Tue May 20 12:13:00 2008 -0700
@@ -239,7 +239,7 @@
 	uint32_t ltime, char *subject, char *altname,
 	KMF_GENERALNAMECHOICES alttype, int altcrit,
 	KMF_BIGINT *serial, uint16_t kubits, int kucrit,
-	char *dir, char *outcert, char *outkey,
+	char *outcert, char *outkey,
 	EKU_LIST *ekulist)
 {
 	KMF_RETURN kmfrv;
@@ -268,17 +268,7 @@
 		    "the cert or key\n"));
 		return (PK_ERR_USAGE);
 	}
-	if (dir != NULL) {
-		fullcertpath = get_fullpath(dir, outcert);
-		if (fullcertpath == NULL) {
-			cryptoerror(LOG_STDERR,
-			    gettext("Cannot create file %s in directory %s\n"),
-			    dir, outcert);
-			return (PK_ERR_USAGE);
-		}
-	} else {
-		fullcertpath = strdup(outcert);
-	}
+	fullcertpath = strdup(outcert);
 	if (verify_file(fullcertpath)) {
 		cryptoerror(LOG_STDERR,
 		    gettext("Cannot write the indicated output "
@@ -286,18 +276,8 @@
 		free(fullcertpath);
 		return (PK_ERR_USAGE);
 	}
-	if (dir != NULL) {
-		fullkeypath = get_fullpath(dir, outkey);
-		if (fullkeypath == NULL) {
-			cryptoerror(LOG_STDERR,
-			    gettext("Cannot create file %s in directory %s\n"),
-			    dir, outkey);
-			free(fullcertpath);
-			return (PK_ERR_USAGE);
-		}
-	} else {
-		fullkeypath = strdup(outkey);
-	}
+
+	fullkeypath = strdup(outkey);
 	if (verify_file(fullkeypath)) {
 		cryptoerror(LOG_STDERR,
 		    gettext("Cannot write the indicated output "
@@ -983,7 +963,7 @@
 		rv = gencert_file(kmfhandle,
 		    keyAlg, sigAlg, keylen, fmt,
 		    ltime, subname, altname, alttype, altcrit,
-		    &serial, kubits, kucrit, dir, outcert, outkey,
+		    &serial, kubits, kucrit, outcert, outkey,
 		    ekulist);
 	}
 
--- a/usr/src/cmd/cmd-crypto/pktool/gencsr.c	Tue May 20 10:53:08 2008 -0700
+++ b/usr/src/cmd/cmd-crypto/pktool/gencsr.c	Tue May 20 12:13:00 2008 -0700
@@ -188,7 +188,7 @@
 	int keylen, KMF_ENCODE_FORMAT fmt,
 	char *subject, char *altname, KMF_GENERALNAMECHOICES alttype,
 	int altcrit, uint16_t kubits, int kucrit,
-	char *dir, char *outcsr, char *outkey, EKU_LIST *ekulist)
+	char *outcsr, char *outkey, EKU_LIST *ekulist)
 {
 	KMF_RETURN kmfrv;
 	KMF_KEY_HANDLE pubk, prik;
@@ -213,17 +213,7 @@
 		    "the csr or key\n"));
 		return (KMF_ERR_BAD_PARAMETER);
 	}
-	if (dir != NULL) {
-		fullcsrpath = get_fullpath(dir, outcsr);
-		if (fullcsrpath == NULL) {
-			cryptoerror(LOG_STDERR,
-			    gettext("Cannot create file %s in "
-			    "directory %s\n"), dir, outcsr);
-			return (PK_ERR_USAGE);
-		}
-	} else {
-		fullcsrpath = strdup(outcsr);
-	}
+	fullcsrpath = strdup(outcsr);
 	if (verify_file(fullcsrpath)) {
 		cryptoerror(LOG_STDERR,
 		    gettext("Cannot write the indicated output "
@@ -231,18 +221,8 @@
 		free(fullcsrpath);
 		return (PK_ERR_USAGE);
 	}
-	if (dir != NULL) {
-		fullkeypath = get_fullpath(dir, outkey);
-		if (fullkeypath == NULL) {
-			cryptoerror(LOG_STDERR,
-			    gettext("Cannot create file %s in "
-			    "directory %s\n"), dir, outkey);
-			free(fullcsrpath);
-			return (PK_ERR_USAGE);
-		}
-	} else {
-		fullkeypath = strdup(outkey);
-	}
+
+	fullkeypath = strdup(outkey);
 	if (verify_file(fullcsrpath)) {
 		cryptoerror(LOG_STDERR,
 		    gettext("Cannot write the indicated output "
@@ -380,6 +360,8 @@
 
 	(void) memset(&csr, 0, sizeof (csr));
 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
+	(void) memset(&pubk, 0, sizeof (pubk));
+	(void) memset(&prik, 0, sizeof (prik));
 
 	/* If the subject name cannot be parsed, flag it now and exit */
 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
@@ -781,7 +763,7 @@
 		rv = gencsr_file(kmfhandle,
 		    keyAlg, keylen, fmt, subname, altname,
 		    alttype, altcrit, kubits, kucrit,
-		    dir, outcsr, outkey, ekulist);
+		    outcsr, outkey, ekulist);
 	}
 
 end:
--- a/usr/src/cmd/cmd-crypto/pktool/import.c	Tue May 20 10:53:08 2008 -0700
+++ b/usr/src/cmd/cmd-crypto/pktool/import.c	Tue May 20 12:13:00 2008 -0700
@@ -58,7 +58,7 @@
 static KMF_RETURN
 pk_import_pk12_files(KMF_HANDLE_T kmfhandle, KMF_CREDENTIAL *cred,
 	char *outfile, char *certfile, char *keyfile,
-	char *dir, char *keydir, KMF_ENCODE_FORMAT outformat)
+	KMF_ENCODE_FORMAT outformat)
 {
 	KMF_RETURN rv = KMF_OK;
 	KMF_X509_DER_CERT *certs = NULL;
@@ -87,12 +87,6 @@
 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
 		numattr++;
 
-		if (dir != NULL) {
-			kmf_set_attr_at_index(attrlist, numattr,
-			    KMF_DIRPATH_ATTR, dir, strlen(dir));
-			numattr++;
-		}
-
 		kmf_set_attr_at_index(attrlist, numattr,
 		    KMF_ENCODE_FORMAT_ATTR, &outformat, sizeof (outformat));
 		numattr++;
@@ -145,13 +139,6 @@
 		    sizeof (kstype));
 		numattr++;
 
-		if (keydir != NULL) {
-			kmf_set_attr_at_index(attrlist, numattr,
-			    KMF_DIRPATH_ATTR, keydir,
-			    strlen(keydir));
-			numattr++;
-		}
-
 		kmf_set_attr_at_index(attrlist, numattr,
 		    KMF_ENCODE_FORMAT_ATTR, &outformat,
 		    sizeof (outformat));
@@ -436,7 +423,6 @@
 pk_import_file_crl(void *kmfhandle,
 	char *infile,
 	char *outfile,
-	char *outdir,
 	KMF_ENCODE_FORMAT outfmt)
 {
 	int numattr = 0;
@@ -451,11 +437,6 @@
 		    KMF_CRL_FILENAME_ATTR, infile, strlen(infile));
 		numattr++;
 	}
-	if (outdir) {
-		kmf_set_attr_at_index(attrlist, numattr,
-		    KMF_DIRPATH_ATTR, outdir, strlen(outdir));
-		numattr++;
-	}
 	if (outfile) {
 		kmf_set_attr_at_index(attrlist, numattr,
 		    KMF_CRL_OUTFILE_ATTR, outfile, strlen(outfile));
@@ -822,7 +803,6 @@
 	char		*crlfile = NULL;
 	char		*label = NULL;
 	char		*dir = NULL;
-	char		*keydir = NULL;
 	char		*prefix = NULL;
 	char		*trustflags = NULL;
 	char		*verify_crl = NULL;
@@ -849,7 +829,7 @@
 	    "K:(outkey)c:(outcert)"
 	    "v:(verifycrl)l:(outcrl)"
 	    "E:(keytype)s:(sensitive)x:(extractable)"
-	    "t:(trust)D:(keydir)F:(outformat)")) != EOF) {
+	    "t:(trust)F:(outformat)")) != EOF) {
 		if (EMPTYSTRING(optarg_av))
 			return (PK_ERR_USAGE);
 		switch (opt) {
@@ -891,9 +871,6 @@
 		case 'd':
 			dir = optarg_av;
 			break;
-		case 'D':
-			keydir = optarg_av;
-			break;
 		case 'p':
 			if (prefix)
 				return (PK_ERR_USAGE);
@@ -1104,7 +1081,7 @@
 			else if (oclass == PK_CRL_OBJ)
 				rv = pk_import_file_crl(
 				    kmfhandle, filename,
-				    crlfile, dir, okfmt);
+				    crlfile, okfmt);
 			else if (kfmt == KMF_FORMAT_RAWKEY &&
 			    oclass == PK_SYMKEY_OBJ) {
 				rv = pk_import_rawkey(kmfhandle,
@@ -1145,11 +1122,11 @@
 				rv = pk_import_pk12_files(
 				    kmfhandle, &pk12cred,
 				    filename, certfile, keyfile,
-				    dir, keydir, okfmt);
+				    okfmt);
 			else if (oclass == PK_CRL_OBJ) {
 				rv = pk_import_file_crl(
 				    kmfhandle, filename,
-				    crlfile, dir, okfmt);
+				    crlfile, okfmt);
 			} else
 				/*
 				 * It doesn't make sense to import anything
--- a/usr/src/cmd/cmd-crypto/pktool/pktool.c	Tue May 20 10:53:08 2008 -0700
+++ b/usr/src/cmd/cmd-crypto/pktool/pktool.c	Tue May 20 12:13:00 2008 -0700
@@ -113,8 +113,7 @@
 	"[ token=token[:manuf[:serial]]]\n\t" \
  \
 	"list keystore=pkcs11 objtype=crl\n\t\t" \
-	"infile=crl-fn\n\t\t" \
-	"[ dir=directory-path ]\n\t" \
+	"infile=crl-fn\n\t" \
  \
 	"list keystore=nss objtype=cert\n\t\t" \
 	"[ subject=subject-DN ]\n\t\t" \
@@ -145,8 +144,7 @@
 	"[ dir=directory-path ]\n\t" \
  \
 	"list keystore=file objtype=crl\n\t\t" \
-	"infile=crl-fn\n\t\t" \
-	"[ dir=directory-path ]\n\t"
+	"infile=crl-fn\n\t"
 
 #define	DELETE_IDX 3
 #define	DELETE_VERB "delete"
@@ -195,8 +193,7 @@
 	"[ token=token[:manuf[:serial]]]\n\t" \
  \
 	"delete keystore=pkcs11 objtype=crl\n\t\t" \
-	"infile=crl-fn\n\t\t" \
-	"[ dir=directory-path ]\n\t" \
+	"infile=crl-fn\n\t" \
  \
 	"delete keystore=file objtype=cert\n\t\t" \
 	"[ subject=subject-DN ]\n\t\t" \
@@ -211,8 +208,7 @@
 	"[ dir=directory-path ]\n\t" \
  \
 	"delete keystore=file objtype=crl\n\t\t" \
-	"infile=crl-fn\n\t\t" \
-	"[ dir=directory-path ]\n\t"
+	"infile=crl-fn\n\t"
 
 #define	IMPORT_IDX 4
 #define	IMPORT_VERB "import"
@@ -248,22 +244,18 @@
 	"import keystore=pkcs11 objtype=crl\n\t\t" \
 	"infile=input-crl-fn\n\t\t" \
 	"outcrl=output-crl-fn\n\t\t" \
-	"outformat=pem|der\n\t\t" \
-	"[ dir=output-crl-directory-path ]\n\t" \
+	"outformat=pem|der\n\t" \
  \
 	"import keystore=file\n\t\t" \
 	"infile=input-fn\n\t\t" \
 	"outkey=output-key-fn\n\t\t" \
 	"outcert=output-cert-fn\n\t\t" \
-	"[ dir=output-cert-dir-path ]\n\t\t" \
-	"[ keydir=output-key-dir-path ]\n\t\t" \
 	"[ outformat=pem|der|pkcs12 ]\n\t" \
  \
 	"import keystore=file objtype=crl\n\t\t" \
 	"infile=input-crl-fn\n\t\t" \
 	"outcrl=output-crl-fn\n\t\t" \
-	"outformat=pem|der\n\t\t" \
-	"[ dir=output-crl-directory-path ]\n\t"
+	"outformat=pem|der\n\t"
 
 #define	EXPORT_IDX 5
 #define	EXPORT_VERB "export"
@@ -297,8 +289,7 @@
 	"export keystore=file\n\t\t" \
 	"certfile=cert-input-fn\n\t\t" \
 	"keyfile=key-input-fn\n\t\t" \
-	"outfile=output-pkcs12-fn\n\t\t" \
-	"[ dir=directory-path ]\n\t"
+	"outfile=output-pkcs12-fn\n\t"
 
 #define	GENCERT_IDX 6
 #define	GENCERT_VERB "gencert"
@@ -339,7 +330,6 @@
 	"[ altname=[critical:]SubjectAltName ]\n\t\t" \
 	"[ keyusage=[critical:]usage,usage,...]\n\t\t" \
 	"[ format=der|pem ]\n\t\t" \
-	"[ dir=directory-path ]\n\t\t" \
 	"[ prefix=DBprefix ]\n\t\t" \
 	"[ keytype=rsa|dsa ]\n\t\t" \
 	"[ keylen=key-size ]\n\t\t" \
@@ -387,7 +377,6 @@
 	"[ keytype=rsa|dsa ]\n\t\t" \
 	"[ keylen=key-size ]\n\t\t" \
 	"[ eku=[critical:]EKU name,...]\n\t\t" \
-	"[ dir=directory-path ]\n\t\t" \
 	"[ format=pem|der ]\n\t"
 
 #define	DOWNLOAD_IDX 8
@@ -425,7 +414,6 @@
 	"outkey=key-fn\n\t\t" \
 	"[ keytype=aes|arcfour|des|3des|generic ]\n\t\t" \
 	"[ keylen=key-size (AES, ARCFOUR or GENERIC only)]\n\t\t" \
-	"[ dir=directory-path ]\n\t\t" \
 	"[ print=y|n ]\n\t"
 
 #define	SIGNCSR_IDX 10
--- a/usr/src/cmd/cmd-crypto/pktool/signcsr.c	Tue May 20 10:53:08 2008 -0700
+++ b/usr/src/cmd/cmd-crypto/pktool/signcsr.c	Tue May 20 12:13:00 2008 -0700
@@ -37,6 +37,8 @@
 #include "common.h"
 
 #include <kmfapi.h>
+#include <kmfapiP.h>
+
 #define	SET_VALUE(f, s) \
 	rv = f; \
 	if (rv != KMF_OK) { \
@@ -80,6 +82,28 @@
 	return (rv);
 }
 
+static KMF_RETURN
+find_csr_extn(KMF_X509_EXTENSIONS *extnlist, KMF_OID *extoid,
+	KMF_X509_EXTENSION *outextn)
+{
+	int i, found = 0;
+	KMF_X509_EXTENSION *eptr;
+	KMF_RETURN rv = KMF_OK;
+
+	(void) memset(outextn, 0, sizeof (KMF_X509_EXTENSION));
+	for (i = 0; !found && i < extnlist->numberOfExtensions; i++) {
+		eptr = &extnlist->extensions[i];
+		if (IsEqualOid(extoid, &eptr->extnId)) {
+			rv = copy_extension_data(outextn, eptr);
+			found++;
+		}
+	}
+	if (found == 0 || rv != KMF_OK)
+		return (1);
+	else
+		return (rv);
+}
+
 static int
 build_cert_from_csr(KMF_CSR_DATA *csrdata,
 	KMF_X509_CERTIFICATE *signedCert,
@@ -140,8 +164,27 @@
 	    csrdata->signature.algorithmIdentifier;
 
 	if (kubits != 0) {
-		SET_VALUE(kmf_set_cert_ku(signedCert, kucrit, kubits),
-		    "KeyUsage");
+		KMF_X509_EXTENSION extn;
+		uint16_t oldbits;
+		/*
+		 * If the CSR already has KU, merge them.
+		 */
+		rv = find_csr_extn(&csrdata->csr.extensions,
+		    (KMF_OID *)&KMFOID_KeyUsage, &extn);
+		if (rv == KMF_OK) {
+			extn.critical |= kucrit;
+			if (extn.value.tagAndValue->value.Length > 1) {
+				oldbits =
+				    extn.value.tagAndValue->value.Data[1] << 8;
+			} else {
+				oldbits =
+				    extn.value.tagAndValue->value.Data[0];
+			}
+			oldbits |= kubits;
+		} else {
+			SET_VALUE(kmf_set_cert_ku(signedCert, kucrit, kubits),
+			    "KeyUsage");
+		}
 	}
 	if (altname != NULL) {
 		SET_VALUE(kmf_set_cert_subject_altname(signedCert,
@@ -681,6 +724,16 @@
 		(void) get_token_password(kstype, token_spec,
 		    &tokencred);
 	}
+	if (kustr != NULL) {
+		rv = verify_keyusage(kustr, &kubits, &kucrit);
+		if (rv != KMF_OK) {
+			(void) fprintf(stderr, gettext("KeyUsage "
+			    "must be specified as a comma-separated list. "
+			    "See the man page for details.\n"));
+			rv = PK_ERR_USAGE;
+			goto end;
+		}
+	}
 	if (ekustr != NULL) {
 		rv = verify_ekunames(ekustr, &ekulist);
 		if (rv != KMF_OK) {
--- a/usr/src/lib/libkmf/include/kmfapiP.h	Tue May 20 10:53:08 2008 -0700
+++ b/usr/src/lib/libkmf/include/kmfapiP.h	Tue May 20 12:13:00 2008 -0700
@@ -351,6 +351,8 @@
 extern boolean_t is_valid_keystore_type(KMF_KEYSTORE_TYPE);
 extern KMF_BOOL is_eku_present(KMF_X509EXT_EKU *, KMF_OID *);
 extern KMF_RETURN parse_eku_data(const KMF_DATA *, KMF_X509EXT_EKU *);
+extern KMF_RETURN
+copy_extension_data(KMF_X509_EXTENSION *, KMF_X509_EXTENSION *);
 
 #ifdef __cplusplus
 }
--- a/usr/src/lib/libkmf/libkmf/common/certgetsetop.c	Tue May 20 10:53:08 2008 -0700
+++ b/usr/src/lib/libkmf/libkmf/common/certgetsetop.c	Tue May 20 12:13:00 2008 -0700
@@ -59,7 +59,7 @@
 	return (ret);
 }
 
-static KMF_RETURN
+KMF_RETURN
 copy_extension_data(KMF_X509_EXTENSION *dstext,
 	KMF_X509_EXTENSION *srcext)
 {
--- a/usr/src/lib/libkmf/libkmf/common/certop.c	Tue May 20 10:53:08 2008 -0700
+++ b/usr/src/lib/libkmf/libkmf/common/certop.c	Tue May 20 12:13:00 2008 -0700
@@ -44,7 +44,8 @@
 #define	X509_FORMAT_VERSION 2
 
 static KMF_RETURN
-sign_cert(KMF_HANDLE_T, const KMF_DATA *, KMF_KEY_HANDLE *, KMF_DATA *);
+sign_cert(KMF_HANDLE_T, const KMF_DATA *, KMF_KEY_HANDLE *,
+    KMF_OID *, KMF_DATA *);
 
 static KMF_RETURN
 verify_cert_with_key(KMF_HANDLE_T, KMF_DATA *, const KMF_DATA *);
@@ -53,6 +54,9 @@
 verify_cert_with_cert(KMF_HANDLE_T, const KMF_DATA *, const KMF_DATA *);
 
 static KMF_RETURN
+get_sigalg_from_cert(KMF_DATA *, KMF_ALGORITHM_INDEX *);
+
+static KMF_RETURN
 get_keyalg_from_cert(KMF_DATA *cert, KMF_KEY_ALG *keyalg)
 {
 	KMF_RETURN rv;
@@ -408,6 +412,8 @@
 	KMF_KEY_HANDLE sign_key, *sign_key_ptr;
 	int freethekey = 0;
 	KMF_POLICY_RECORD *policy;
+	KMF_OID *oid = NULL;
+	KMF_ALGORITHM_INDEX AlgId;
 	KMF_X509_CERTIFICATE *x509cert;
 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
 	    {KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
@@ -431,8 +437,13 @@
 	    numattr);
 	sign_key_ptr = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist,
 	    numattr);
+	/*
+	 * Only accept 1 or the other, not both.
+	 */
 	if (signer_cert == NULL && sign_key_ptr == NULL)
 		return (KMF_ERR_BAD_PARAMETER);
+	if (signer_cert != NULL && sign_key_ptr != NULL)
+		return (KMF_ERR_BAD_PARAMETER);
 
 	if (signer_cert != NULL) {
 		policy = handle->policy;
@@ -458,6 +469,18 @@
 		}
 		sign_key_ptr = &sign_key;
 		freethekey = 1;
+
+		ret = get_sigalg_from_cert(signer_cert, &AlgId);
+		if (ret != KMF_OK)
+			goto out;
+		else
+			oid = x509_algid_to_algoid(AlgId);
+	} else if (sign_key_ptr != NULL) {
+		if (sign_key_ptr->keyalg == KMF_RSA) {
+			oid = (KMF_OID *)&KMFOID_SHA1WithRSA;
+		} else if (sign_key_ptr->keyalg == KMF_DSA) {
+			oid = (KMF_OID *)&KMFOID_SHA1WithDSA;
+		}
 	}
 
 	/* Now we are ready to sign */
@@ -484,7 +507,7 @@
 		goto out;
 	}
 
-	ret = sign_cert(handle, tbs_cert, sign_key_ptr, signed_cert);
+	ret = sign_cert(handle, tbs_cert, sign_key_ptr, oid, signed_cert);
 
 out:
 	if (new_attrlist)
@@ -651,6 +674,8 @@
 	} else if (oid == NULL && ret == KMF_OK) {
 		/* AlgID was given by caller, convert it to OID */
 		oid = x509_algid_to_algoid(AlgId);
+	} else if (oid != NULL && ret == KMF_ERR_ATTR_NOT_FOUND) {
+		AlgId = x509_algoid_to_algid(oid);
 	} else { /* Else, the OID must have been given */
 		ret = KMF_OK;
 	}
@@ -724,7 +749,7 @@
 	uint32_t len;
 	KMF_DATA	derkey = {0, NULL};
 	KMF_KEY_HANDLE *KMFKey;
-	KMF_ALGORITHM_INDEX sigAlg;
+	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_NONE;
 	KMF_DATA *indata;
 	KMF_DATA *insig;
 	KMF_DATA *signer_cert;
@@ -2830,6 +2855,24 @@
 	    !memcmp(Oid1->Data, Oid2->Data, Oid1->Length));
 }
 
+static KMF_RETURN
+set_algoid(KMF_X509_ALGORITHM_IDENTIFIER *destid,
+	KMF_OID *newoid)
+{
+	if (destid == NULL || newoid == NULL)
+		return (KMF_ERR_BAD_PARAMETER);
+
+	destid->algorithm.Length = newoid->Length;
+	destid->algorithm.Data = malloc(destid->algorithm.Length);
+	if (destid->algorithm.Data == NULL)
+		return (KMF_ERR_MEMORY);
+
+	(void) memcpy(destid->algorithm.Data, newoid->Data,
+	    destid->algorithm.Length);
+
+	return (KMF_OK);
+}
+
 KMF_RETURN
 copy_algoid(KMF_X509_ALGORITHM_IDENTIFIER *destid,
 	KMF_X509_ALGORITHM_IDENTIFIER *srcid)
@@ -2864,6 +2907,7 @@
 sign_cert(KMF_HANDLE_T handle,
 	const KMF_DATA *SubjectCert,
 	KMF_KEY_HANDLE	*Signkey,
+	KMF_OID		*signature_oid,
 	KMF_DATA	*SignedCert)
 {
 	KMF_X509_CERTIFICATE	*subj_cert = NULL;
@@ -2873,7 +2917,6 @@
 	KMF_ALGORITHM_INDEX	algid;
 	int i = 0;
 	KMF_ATTRIBUTE attrlist[8];
-	KMF_OID *oid;
 
 	if (!SignedCert)
 		return (KMF_ERR_BAD_PARAMETER);
@@ -2918,8 +2961,13 @@
 	/* We are re-signing this cert, so clear out old signature data */
 	if (subj_cert->signature.algorithmIdentifier.algorithm.Length == 0) {
 		kmf_free_algoid(&subj_cert->signature.algorithmIdentifier);
-		ret = copy_algoid(&subj_cert->signature.algorithmIdentifier,
-		    &subj_cert->certificate.signature);
+		ret = set_algoid(&subj_cert->signature.algorithmIdentifier,
+		    signature_oid);
+		if (ret != KMF_OK)
+			goto cleanup;
+		ret = set_algoid(&subj_cert->certificate.signature,
+		    signature_oid);
+
 	}
 
 	if (ret)
@@ -2937,9 +2985,8 @@
 	kmf_set_attr_at_index(attrlist, i, KMF_OUT_DATA_ATTR,
 	    &signed_data, sizeof (KMF_DATA));
 	i++;
-	oid = CERT_ALG_OID(subj_cert);
 	kmf_set_attr_at_index(attrlist, i, KMF_OID_ATTR,
-	    oid, sizeof (KMF_OID));
+	    signature_oid, sizeof (KMF_OID));
 	i++;
 
 	/* Sign the data */
@@ -2948,7 +2995,7 @@
 	if (ret != KMF_OK)
 		goto cleanup;
 
-	algid = x509_algoid_to_algid(CERT_SIG_OID(subj_cert));
+	algid = x509_algoid_to_algid(signature_oid);
 
 	/*
 	 * For DSA, KMF_SignDataWithKey() returns a 40-bytes decoded
--- a/usr/src/lib/libkmf/libkmf/common/kmfoids.c	Tue May 20 10:53:08 2008 -0700
+++ b/usr/src/lib/libkmf/libkmf/common/kmfoids.c	Tue May 20 12:13:00 2008 -0700
@@ -358,7 +358,7 @@
 static uint8_t
 OID_OIW_SHA1[] = { OID_OIW_ALGORITHM, 26},
 OID_OIW_DSA[] = { OID_OIW_ALGORITHM, 12  },
-OID_OIW_DSAWithSHA1[] = { OID_OIW_ALGORITHM, 27  },
+OID_OIW_DSAWithSHA1[] = { OID_OIW_ALGORITHM, 13 },
 OID_RSAEncryption[] = { OID_PKCS_1, 1 },
 OID_MD2WithRSA[]   = { OID_PKCS_1, 2 },
 OID_MD5WithRSA[]   = { OID_PKCS_1, 4 },
--- a/usr/src/lib/libkmf/libkmf/common/mapfile-vers	Tue May 20 10:53:08 2008 -0700
+++ b/usr/src/lib/libkmf/libkmf/common/mapfile-vers	Tue May 20 12:13:00 2008 -0700
@@ -304,6 +304,7 @@
 SUNWprivate_1.1 {
     global:
 	GetIDFromSPKI;
+	IsEqualOid;
 	KMF_ConfigureKeystore;
 	KMF_CreateCSRFile;
 	KMF_CreateKeypair;
@@ -329,6 +330,7 @@
 	KMF_SignDataWithKey;
 	KMF_VerifyCertWithCert;
 	KMF_VerifyDataWithCert;
+	copy_extension_data;
 	dup_entry;
 	free_entry;
 	free_entrylist;