summaryrefslogtreecommitdiff
path: root/usr/src/cmd/cmd-crypto
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/cmd-crypto')
-rw-r--r--usr/src/cmd/cmd-crypto/Makefile10
-rw-r--r--usr/src/cmd/cmd-crypto/cryptoadm/adm_uef.c120
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/Makefile91
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/create.c498
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/delete.c132
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/export.c167
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/import.c169
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/kmfcfg.c245
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.dtd84
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.xml40
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/list.c277
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/modify.c845
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/util.c497
-rw-r--r--usr/src/cmd/cmd-crypto/kmfcfg/util.h66
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/Makefile33
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/biginteger.h58
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/common.c1471
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/common.h86
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/delete.c739
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/derparse.c371
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/derparse.h55
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/download.c274
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/export.c1682
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/gencert.c729
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/gencsr.c631
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/genkey.c450
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/import.c1341
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/list.c1479
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/osslcommon.c224
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/osslcommon.h50
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/p12common.c103
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/p12common.h46
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/pktool.c455
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/setpin.c264
-rw-r--r--usr/src/cmd/cmd-crypto/pktool/tokens.c13
35 files changed, 8501 insertions, 5294 deletions
diff --git a/usr/src/cmd/cmd-crypto/Makefile b/usr/src/cmd/cmd-crypto/Makefile
index f02549ce64..a046256e8a 100644
--- a/usr/src/cmd/cmd-crypto/Makefile
+++ b/usr/src/cmd/cmd-crypto/Makefile
@@ -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 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -32,7 +31,8 @@ SUBDIRS1 = \
cryptoadm \
decrypt \
digest \
- pktool
+ pktool \
+ kmfcfg
$(CLOSED_BUILD)SUBDIRS1 += \
$(CLOSED)/cmd/cmd-crypto/elfsign \
diff --git a/usr/src/cmd/cmd-crypto/cryptoadm/adm_uef.c b/usr/src/cmd/cmd-crypto/cryptoadm/adm_uef.c
index 999ab4cb17..aad2a69f84 100644
--- a/usr/src/cmd/cmd-crypto/cryptoadm/adm_uef.c
+++ b/usr/src/cmd/cmd-crypto/cryptoadm/adm_uef.c
@@ -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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -52,8 +51,6 @@
static int err; /* To store errno which may be overwritten by gettext() */
static boolean_t is_in_policylist(midstr_t, umechlist_t *);
-static umechlist_t *dup_umechlist(umechlist_t *);
-static uentry_t *dup_uentry(uentry_t *);
static char *uent2str(uentry_t *);
static boolean_t check_random(CK_SLOT_ID, CK_FUNCTION_LIST_PTR);
@@ -1114,117 +1111,6 @@ uninstall_uef_lib(char *libname)
}
-
-/*
- * Duplicate an UEF mechanism list. A NULL pointer is returned if out of
- * memory or the input argument is NULL.
- */
-static umechlist_t *
-dup_umechlist(umechlist_t *plist)
-{
- umechlist_t *pres = NULL;
- umechlist_t *pcur;
- umechlist_t *ptmp;
- int rc = SUCCESS;
-
- while (plist != NULL) {
- if (!(ptmp = create_umech(plist->name))) {
- rc = FAILURE;
- break;
- }
-
- if (pres == NULL) {
- pres = pcur = ptmp;
- } else {
- pcur->next = ptmp;
- pcur = pcur->next;
- }
- plist = plist->next;
- }
-
- if (rc != SUCCESS) {
- free_umechlist(pres);
- return (NULL);
- }
-
- return (pres);
-}
-
-
-
-/*
- * Duplicate an uentry. A NULL pointer is returned if out of memory
- * or the input argument is NULL.
- */
-static uentry_t *
-dup_uentry(uentry_t *puent1)
-{
- uentry_t *puent2 = NULL;
-
- if (puent1 == NULL) {
- return (NULL);
- }
-
- if ((puent2 = malloc(sizeof (uentry_t))) == NULL) {
- cryptoerror(LOG_STDERR, gettext("out of memory."));
- return (NULL);
- } else {
- (void) strlcpy(puent2->name, puent1->name,
- sizeof (puent2->name));
- puent2->flag_norandom = puent1->flag_norandom;
- puent2->flag_enabledlist = puent1->flag_enabledlist;
- puent2->count = puent1->count;
- puent2->policylist = dup_umechlist(puent1->policylist);
- puent2->flag_metaslot_enabled = puent1->flag_metaslot_enabled;
- puent2->flag_metaslot_auto_key_migrate
- = puent1->flag_metaslot_auto_key_migrate;
- (void) memcpy(puent2->metaslot_ks_slot,
- puent1->metaslot_ks_slot, SLOT_DESCRIPTION_SIZE);
- (void) memcpy(puent2->metaslot_ks_token,
- puent1->metaslot_ks_token, TOKEN_LABEL_SIZE);
- return (puent2);
- }
-}
-
-
-/*
- * Find the entry in the "pkcs11.conf" file with "libname" as the provider
- * name. Return the entry if found, otherwise return NULL.
- */
-uentry_t *
-getent_uef(char *libname)
-{
- uentrylist_t *pliblist = NULL;
- uentrylist_t *plib = NULL;
- uentry_t *puent = NULL;
- boolean_t found = B_FALSE;
-
- if (libname == NULL) {
- return (NULL);
- }
-
- if ((get_pkcs11conf_info(&pliblist)) == FAILURE) {
- return (NULL);
- }
-
- plib = pliblist;
- while (plib) {
- if (strcmp(plib->puent->name, libname) == 0) {
- found = B_TRUE;
- break;
- } else {
- plib = plib->next;
- }
- }
-
- if (found) {
- puent = dup_uentry(plib->puent);
- }
-
- free_uentrylist(pliblist);
- return (puent);
-}
-
int
display_policy(uentry_t *puent)
{
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/Makefile b/usr/src/cmd/cmd-crypto/kmfcfg/Makefile
new file mode 100644
index 0000000000..86fd4eb30e
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/Makefile
@@ -0,0 +1,91 @@
+#
+# 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.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# Makefile for policy testing code
+#
+
+PROG = kmfcfg
+
+OBJS = kmfcfg.o \
+ list.o \
+ delete.o \
+ util.o \
+ create.o \
+ modify.o \
+ export.o \
+ import.o
+
+include ../../Makefile.cmd
+
+KMFDIR = $(SRC)/lib/libkmf
+SRCS = $(OBJS:%.o=%.c)
+
+POFILES = $(OBJS:%.o=%.po)
+POFILE = $(PROG)_msg.po
+MSGFILES = $(SRCS:%.c=%.i)
+
+CPPFLAGS += -I/usr/include/libxml2 -I$(KMFDIR)/include -I.
+LDLIBS += -L$(ROOT)/usr/lib -lkmf -lcryptoutil
+XMLLIB = -lxml2
+
+.KEEP_STATE:
+
+XMLDIR= $(ROOT)/etc/security
+DTDDIR= $(ROOT)/usr/share/lib/xml/dtd
+ROOTDTDS= $(DTDDIR)/kmfpolicy.dtd
+ROOTXML= $(XMLDIR)/kmfpolicy.xml
+
+$(ROOTDTDS) := FILEMODE = 444
+$(ROOTDTDS) := OWNER = root
+$(ROOTDTDS) := GROUP = bin
+
+$(ROOTXML) := FILEMODE = 644
+$(ROOTXML) := OWNER = root
+$(ROOTXML) := GROUP = bin
+
+all: $(PROG) $(ROOTDTDS)
+
+$(PROG): $(OBJS)
+ $(LINK.c) -o $@ $(OBJS) $(LDLIBS) $(XMLLIB)
+ $(POST_PROCESS)
+
+$(POFILE): $(POFILES)
+ $(BUILDPO.pofiles)
+
+install: all $(ROOTDTDS) $(ROOTXML) $(ROOTPROG)
+
+$(XMLDIR)/%: %
+ $(INS.file)
+
+$(DTDDIR)/%: %
+ $(INS.file)
+
+clean:
+ $(RM) $(OBJS)
+
+lint : lint_SRCS
+
+include ../../Makefile.targ
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/create.c b/usr/src/cmd/cmd-crypto/kmfcfg/create.c
new file mode 100644
index 0000000000..ceacf5f5d5
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/create.c
@@ -0,0 +1,498 @@
+/*
+ * 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 <stdio.h>
+#include <strings.h>
+#include <ctype.h>
+#include <libgen.h>
+#include <libintl.h>
+#include <errno.h>
+#include <kmfapiP.h>
+#include <cryptoutil.h>
+#include "util.h"
+
+int
+kc_create(int argc, char *argv[])
+{
+ KMF_RETURN ret;
+ int rv = KC_OK;
+ int opt;
+ extern int optind_av;
+ extern char *optarg_av;
+ char *filename = NULL;
+ int ocsp_set_attr = 0;
+ boolean_t crl_set_attr = 0;
+ KMF_POLICY_RECORD plc;
+
+ (void) memset(&plc, 0, sizeof (KMF_POLICY_RECORD));
+
+ while ((opt = getopt_av(argc, argv,
+ "i:(dbfile)"
+ "p:(policy)"
+ "d:(ignore-date)"
+ "e:(ignore-unknown-eku)"
+ "a:(ignore-trust-anchor)"
+ "v:(validity-adjusttime)"
+ "t:(ta-name)"
+ "s:(ta-serial)"
+ "o:(ocsp-responder)"
+ "P:(ocsp-proxy)"
+ "r:(ocsp-use-cert-responder)"
+ "T:(ocsp-response-lifetime)"
+ "R:(ocsp-ignore-response-sign)"
+ "n:(ocsp-responder-cert-name)"
+ "A:(ocsp-responder-cert-serial)"
+ "c:(crl-basefilename)"
+ "I:(crl-directory)"
+ "g:(crl-get-crl-uri)"
+ "X:(crl-proxy)"
+ "S:(crl-ignore-crl-sign)"
+ "D:(crl-ignore-crl-date)"
+ "u:(keyusage)"
+ "E:(ekunames)"
+ "O:(ekuoids)")) != EOF) {
+ switch (opt) {
+ case 'i':
+ filename = get_string(optarg_av, &rv);
+ if (filename == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error dbfile input.\n"));
+ }
+ break;
+ case 'p':
+ plc.name = get_string(optarg_av, &rv);
+ if (plc.name == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error policy name.\n"));
+ }
+ break;
+ case 'd':
+ plc.ignore_date = get_boolean(optarg_av);
+ if (plc.ignore_date == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ }
+ break;
+ case 'e':
+ plc.ignore_unknown_ekus =
+ get_boolean(optarg_av);
+ if (plc.ignore_unknown_ekus == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ }
+ break;
+ case 'a':
+ plc.ignore_trust_anchor =
+ get_boolean(optarg_av);
+ if (plc.ignore_trust_anchor == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ }
+ break;
+ case 'v':
+ plc.validity_adjusttime =
+ get_string(optarg_av, &rv);
+ if (plc.validity_adjusttime == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error time input.\n"));
+ } else {
+ uint32_t adj;
+ /* for syntax checking */
+ if (str2lifetime(
+ plc.validity_adjusttime,
+ &adj) < 0) {
+ (void) fprintf(stderr,
+ gettext("Error time "
+ "input.\n"));
+ rv = KC_ERR_USAGE;
+ }
+ }
+ break;
+ case 't':
+ plc.ta_name = get_string(optarg_av, &rv);
+ if (plc.ta_name == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error name input.\n"));
+ } else {
+ KMF_X509_NAME taDN;
+ /* for syntax checking */
+ if (KMF_DNParser(plc.ta_name,
+ &taDN) != KMF_OK) {
+ (void) fprintf(stderr,
+ gettext("Error name "
+ "input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ KMF_FreeDN(&taDN);
+ }
+ }
+ break;
+ case 's':
+ plc.ta_serial = get_string(optarg_av, &rv);
+ if (plc.ta_serial == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error serial input.\n"));
+ } else {
+ uchar_t *bytes = NULL;
+ size_t bytelen;
+
+ ret = KMF_HexString2Bytes(
+ (uchar_t *)plc.ta_serial,
+ &bytes, &bytelen);
+ if (ret != KMF_OK || bytes == NULL) {
+ (void) fprintf(stderr,
+ gettext("serial number "
+ "must be specified as a "
+ "hex number "
+ "(ex: 0x0102030405"
+ "ffeeddee)\n"));
+ rv = KC_ERR_USAGE;
+ }
+ if (bytes != NULL)
+ free(bytes);
+ }
+ break;
+ case 'o':
+ plc.VAL_OCSP_RESPONDER_URI =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_RESPONDER_URI == NULL) {
+ (void) fprintf(stderr, gettext(
+ "Error responder input.\n"));
+ } else {
+ ocsp_set_attr++;
+ }
+ break;
+ case 'P':
+ plc.VAL_OCSP_PROXY =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_PROXY == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error proxy input.\n"));
+ } else {
+ ocsp_set_attr++;
+ }
+ break;
+ case 'r':
+ plc.VAL_OCSP_URI_FROM_CERT =
+ get_boolean(optarg_av);
+ if (plc.VAL_OCSP_URI_FROM_CERT == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ ocsp_set_attr++;
+ }
+ break;
+ case 'T':
+ plc.VAL_OCSP_RESP_LIFETIME =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_RESP_LIFETIME == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error time input.\n"));
+ } else {
+ uint32_t adj;
+ /* for syntax checking */
+ if (str2lifetime(
+ plc.VAL_OCSP_RESP_LIFETIME,
+ &adj) < 0) {
+ (void) fprintf(stderr,
+ gettext("Error time "
+ "input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ ocsp_set_attr++;
+ }
+ }
+ break;
+ case 'R':
+ plc.VAL_OCSP_IGNORE_RESP_SIGN =
+ get_boolean(optarg_av);
+ if (plc.VAL_OCSP_IGNORE_RESP_SIGN == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ ocsp_set_attr++;
+ }
+ break;
+ case 'n':
+ plc.VAL_OCSP_RESP_CERT_NAME =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_RESP_CERT_NAME == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error name input.\n"));
+ } else {
+ KMF_X509_NAME respDN;
+ /* for syntax checking */
+ if (KMF_DNParser(
+ plc.VAL_OCSP_RESP_CERT_NAME,
+ &respDN) != KMF_OK) {
+ (void) fprintf(stderr,
+ gettext("Error name "
+ "input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ KMF_FreeDN(&respDN);
+ ocsp_set_attr++;
+ }
+ }
+ break;
+ case 'A':
+ plc.VAL_OCSP_RESP_CERT_SERIAL =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_RESP_CERT_SERIAL == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error serial input.\n"));
+ } else {
+ uchar_t *bytes = NULL;
+ size_t bytelen;
+
+ ret = KMF_HexString2Bytes((uchar_t *)
+ plc.VAL_OCSP_RESP_CERT_SERIAL,
+ &bytes, &bytelen);
+ if (ret != KMF_OK || bytes == NULL) {
+ (void) fprintf(stderr,
+ gettext("serial number "
+ "must be specified as a "
+ "hex number "
+ "(ex: 0x0102030405"
+ "ffeeddee)\n"));
+ rv = KC_ERR_USAGE;
+ break;
+ }
+ if (bytes != NULL)
+ free(bytes);
+ ocsp_set_attr++;
+ }
+ break;
+ case 'c':
+ plc.VAL_CRL_BASEFILENAME =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_CRL_BASEFILENAME == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ } else {
+ crl_set_attr++;
+ }
+ break;
+ case 'I':
+ plc.VAL_CRL_DIRECTORY =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_CRL_DIRECTORY == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ } else {
+ crl_set_attr++;
+ }
+ break;
+ case 'g':
+ plc.VAL_CRL_GET_URI = get_boolean(optarg_av);
+ if (plc.VAL_CRL_GET_URI == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ crl_set_attr++;
+ }
+ break;
+ case 'X':
+ plc.VAL_CRL_PROXY = get_string(optarg_av, &rv);
+ if (plc.VAL_CRL_PROXY == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error proxy input.\n"));
+ } else {
+ crl_set_attr++;
+ }
+ break;
+ case 'S':
+ plc.VAL_CRL_IGNORE_SIGN =
+ get_boolean(optarg_av);
+ if (plc.VAL_CRL_IGNORE_SIGN == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ crl_set_attr++;
+ }
+ break;
+ case 'D':
+ plc.VAL_CRL_IGNORE_DATE =
+ get_boolean(optarg_av);
+ if (plc.VAL_CRL_IGNORE_DATE == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ crl_set_attr++;
+ }
+ break;
+ case 'u':
+ plc.ku_bits = parseKUlist(optarg_av);
+ if (plc.ku_bits == 0) {
+ (void) fprintf(stderr, gettext(
+ "Error keyusage input.\n"));
+ rv = KC_ERR_USAGE;
+ }
+ break;
+ case 'E':
+ if (parseEKUNames(optarg_av, &plc) != 0) {
+ (void) fprintf(stderr,
+ gettext("Error EKU input.\n"));
+ rv = KC_ERR_USAGE;
+ }
+ break;
+ case 'O':
+ if (parseEKUOIDs(optarg_av, &plc) != 0) {
+ (void) fprintf(stderr,
+ gettext("Error EKU OID input.\n"));
+ rv = KC_ERR_USAGE;
+ }
+ break;
+ default:
+ (void) fprintf(stderr,
+ gettext("Error input option.\n"));
+ rv = KC_ERR_USAGE;
+ break;
+ }
+
+ if (rv != KC_OK)
+ goto out;
+ }
+
+ /* No additional args allowed. */
+ argc -= optind_av;
+ if (argc) {
+ (void) fprintf(stderr,
+ gettext("Error input option\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ if (filename == NULL) {
+ filename = strdup(KMF_DEFAULT_POLICY_FILE);
+ if (filename == NULL) {
+ rv = KC_ERR_MEMORY;
+ goto out;
+ }
+ }
+
+ /*
+ * Must have a policy name. The policy name can not be default
+ * if using the default policy file.
+ */
+ if (plc.name == NULL) {
+ (void) fprintf(stderr,
+ gettext("You must specify a policy name\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ } else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
+ strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) {
+ (void) fprintf(stderr,
+ gettext("Can not create a default policy in the default "
+ "policy file\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ /*
+ * If the policy file exists and the policy is in the policy file
+ * already, we will not create it again.
+ */
+ if (access(filename, R_OK) == 0) {
+ POLICY_LIST *plclist = NULL, *pnode;
+ int found = 0;
+
+ rv = load_policies(filename, &plclist);
+ if (rv != KMF_OK)
+ goto out;
+
+ pnode = plclist;
+ while (pnode != NULL && !found) {
+ if (strcmp(plc.name, pnode->plc.name) == 0)
+ found++;
+ pnode = pnode->next;
+ }
+ free_policy_list(plclist);
+
+ if (found) {
+ (void) fprintf(stderr,
+ gettext("Could not create policy \"%s\" - exists "
+ "already\n"), plc.name);
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+ }
+
+ /*
+ * If any OCSP attribute is set, turn on the OCSP checking flag.
+ * Also set "has_resp_cert" to be true, if the responder cert
+ * is provided.
+ */
+ if (ocsp_set_attr > 0)
+ plc.revocation |= KMF_REVOCATION_METHOD_OCSP;
+
+ if (plc.VAL_OCSP_RESP_CERT.name != NULL &&
+ plc.VAL_OCSP_RESP_CERT.serial != NULL) {
+ plc.VAL_OCSP.has_resp_cert = B_TRUE;
+ }
+
+ /*
+ * If any CRL attribute is set, turn on the CRL checking flag.
+ */
+ if (crl_set_attr > 0)
+ plc.revocation |= KMF_REVOCATION_METHOD_CRL;
+
+ /*
+ * Does a sanity check on the new policy.
+ */
+ ret = KMF_VerifyPolicy(&plc);
+ if (ret != KMF_OK) {
+ print_sanity_error(ret);
+ rv = KC_ERR_ADD_POLICY;
+ goto out;
+ }
+
+ /*
+ * Add to the DB.
+ */
+ ret = KMF_AddPolicyToDB(&plc, filename, B_FALSE);
+ if (ret != KMF_OK) {
+ (void) fprintf(stderr,
+ gettext("Error adding policy to database: 0x%04x\n"), ret);
+ rv = KC_ERR_ADD_POLICY;
+ }
+
+out:
+ if (filename != NULL)
+ free(filename);
+
+ KMF_FreePolicyRecord(&plc);
+
+ return (rv);
+}
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/delete.c b/usr/src/cmd/cmd-crypto/kmfcfg/delete.c
new file mode 100644
index 0000000000..7e0a1c7d45
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/delete.c
@@ -0,0 +1,132 @@
+/*
+ * 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 <stdio.h>
+#include <strings.h>
+#include <ctype.h>
+#include <libgen.h>
+#include <libintl.h>
+#include <errno.h>
+#include <kmfapiP.h>
+#include "util.h"
+
+int
+kc_delete(int argc, char *argv[])
+{
+ int rv = KC_OK;
+ KMF_RETURN kmfrv = KMF_OK;
+ int opt;
+ extern int optind_av;
+ extern char *optarg_av;
+ char *filename = NULL;
+ char *policyname = NULL;
+
+ while ((opt = getopt_av(argc, argv, "i:(dbfile)p:(policy)")) != EOF) {
+ switch (opt) {
+ case 'i':
+ filename = get_string(optarg_av, &rv);
+ if (filename == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error dbfile input.\n"));
+ }
+ break;
+ case 'p':
+ policyname = get_string(optarg_av, &rv);
+ if (policyname == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error policy name.\n"));
+ }
+ break;
+ default:
+ (void) fprintf(stderr,
+ gettext("Error input option.\n"));
+ rv = KC_ERR_USAGE;
+ break;
+
+ }
+
+ if (rv != KC_OK)
+ goto out;
+ }
+
+ /* No additional args allowed. */
+ argc -= optind_av;
+ if (argc) {
+ (void) fprintf(stderr,
+ gettext("Error input option\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ if (filename == NULL) {
+ filename = strdup(KMF_DEFAULT_POLICY_FILE);
+ if (filename == NULL) {
+ rv = KC_ERR_MEMORY;
+ goto out;
+ }
+ }
+
+ /*
+ * Must have a policy name. The policy name can not be default
+ * if using the default policy file.
+ */
+ if (policyname == NULL) {
+ (void) fprintf(stderr,
+ gettext("You must specify a policy name\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ } else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
+ strcmp(policyname, KMF_DEFAULT_POLICY_NAME) == 0) {
+ (void) fprintf(stderr,
+ gettext("Can not delete the default policy in the default "
+ "policy file\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ /* Check the access permission of the policy DB */
+ if (access(filename, W_OK) < 0) {
+ int err = errno;
+ (void) fprintf(stderr,
+ gettext("Cannot access \"%s\" for delete - %s\n"),
+ filename, strerror(err));
+ rv = KC_ERR_ACCESS;
+ goto out;
+ }
+
+ kmfrv = KMF_DeletePolicyFromDB(policyname, filename);
+ if (kmfrv != KMF_OK)
+ rv = KC_ERR_DELETE_POLICY;
+
+out:
+ if (filename != NULL)
+ free(filename);
+
+ if (policyname != NULL)
+ free(policyname);
+
+ return (rv);
+}
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/export.c b/usr/src/cmd/cmd-crypto/kmfcfg/export.c
new file mode 100644
index 0000000000..c1ddab153c
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/export.c
@@ -0,0 +1,167 @@
+/*
+ * 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 <stdio.h>
+#include <strings.h>
+#include <ctype.h>
+#include <libgen.h>
+#include <libintl.h>
+#include <locale.h>
+#include <errno.h>
+#include <kmfapiP.h>
+
+#include "util.h"
+
+int
+kc_export(int argc, char *argv[])
+{
+ int rv = KC_OK;
+ char *filename = NULL;
+ char *outfile = NULL;
+ char *policyname = NULL;
+ POLICY_LIST *plclist = NULL, *pnode;
+ int opt, found = 0;
+ extern int optind_av;
+ extern char *optarg_av;
+
+ while ((opt = getopt_av(argc, argv,
+ "d:(dbfile)p:(policy)o:(outfile)")) != EOF) {
+ switch (opt) {
+ case 'd':
+ filename = get_string(optarg_av, &rv);
+ if (filename == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error dbfile input.\n"));
+ }
+ break;
+ case 'p':
+ policyname = get_string(optarg_av, &rv);
+ if (policyname == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error policy name.\n"));
+ }
+ break;
+ case 'o':
+ outfile = get_string(optarg_av, &rv);
+ if (outfile == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error outfile input.\n"));
+ }
+ break;
+ default:
+ (void) fprintf(stderr,
+ gettext("Error input option.\n"));
+ rv = KC_ERR_USAGE;
+ break;
+ }
+
+ if (rv != KC_OK)
+ goto out;
+ }
+
+ /* No additional args allowed. */
+ argc -= optind_av;
+ if (argc) {
+ (void) fprintf(stderr,
+ gettext("Error input option\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ if (filename == NULL) {
+ filename = strdup(KMF_DEFAULT_POLICY_FILE);
+ if (filename == NULL) {
+ rv = KC_ERR_MEMORY;
+ goto out;
+ }
+ }
+
+ if (policyname == NULL) {
+ (void) fprintf(stderr,
+ gettext("You must specify a policy name\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ if (outfile == NULL) {
+ (void) fprintf(stderr,
+ gettext("You must specify a output DB file\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ if (strcmp(outfile, KMF_DEFAULT_POLICY_FILE) == 0 &&
+ strcmp(policyname, KMF_DEFAULT_POLICY_NAME) == 0) {
+ (void) fprintf(stderr,
+ gettext("Can not export the default policy record to "
+ "the system default policy database\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ rv = load_policies(filename, &plclist);
+ if (rv != KMF_OK)
+ goto out;
+
+ pnode = plclist;
+ while (pnode != NULL && !found) {
+ if (strcmp(policyname, pnode->plc.name) == 0) {
+ KMF_RETURN ret;
+
+ found++;
+ ret = KMF_VerifyPolicy(&pnode->plc);
+ if (ret != KMF_OK) {
+ print_sanity_error(ret);
+ rv = KC_ERR_VERIFY_POLICY;
+ break;
+ }
+ rv = KMF_AddPolicyToDB(&pnode->plc, outfile, B_FALSE);
+ }
+ pnode = pnode->next;
+ }
+
+ if (!found) {
+ (void) fprintf(stderr,
+ gettext("Could not find policy \"%s\" in %s\n"),
+ policyname, filename);
+ rv = KC_ERR_FIND_POLICY;
+ }
+
+out:
+ if (filename != NULL)
+ free(filename);
+
+ if (policyname != NULL)
+ free(policyname);
+
+ if (outfile != NULL)
+ free(outfile);
+
+ free_policy_list(plclist);
+
+ return (rv);
+}
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/import.c b/usr/src/cmd/cmd-crypto/kmfcfg/import.c
new file mode 100644
index 0000000000..b55caac068
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/import.c
@@ -0,0 +1,169 @@
+/*
+ * 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 <stdio.h>
+#include <strings.h>
+#include <ctype.h>
+#include <libgen.h>
+#include <libintl.h>
+#include <locale.h>
+#include <errno.h>
+
+#include <kmfapiP.h>
+
+#include "util.h"
+
+int
+kc_import(int argc, char *argv[])
+{
+ int rv = KC_OK;
+ char *filename = NULL;
+ char *infile = NULL;
+ char *policyname = NULL;
+ POLICY_LIST *plclist = NULL, *pnode;
+ int opt, found = 0;
+ extern int optind_av;
+ extern char *optarg_av;
+
+ while ((opt = getopt_av(argc, argv,
+ "d:(dbfile)p:(policy)i:(infile)")) != EOF) {
+ switch (opt) {
+ case 'd':
+ filename = get_string(optarg_av, &rv);
+ if (filename == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error dbfile input.\n"));
+ }
+ break;
+ case 'p':
+ policyname = get_string(optarg_av, &rv);
+ if (policyname == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error policy name.\n"));
+ }
+ break;
+ case 'i':
+ infile = get_string(optarg_av, &rv);
+ if (infile == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error infile input.\n"));
+ }
+ break;
+ default:
+ (void) fprintf(stderr,
+ gettext("Error input option.\n"));
+ rv = KC_ERR_USAGE;
+ break;
+ }
+
+ if (rv != KC_OK)
+ goto out;
+
+ }
+
+ /* No additional args allowed. */
+ argc -= optind_av;
+ if (argc) {
+ (void) fprintf(stderr,
+ gettext("Error input option\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ if (filename == NULL) {
+ filename = strdup(KMF_DEFAULT_POLICY_FILE);
+ if (filename == NULL) {
+ rv = KC_ERR_MEMORY;
+ goto out;
+ }
+ }
+
+ if (policyname == NULL) {
+ (void) fprintf(stderr,
+ gettext("You must specify a policy name\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ if (infile == NULL) {
+ (void) fprintf(stderr,
+ gettext("You must specify a input DB file\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
+ strcmp(policyname, KMF_DEFAULT_POLICY_NAME) == 0) {
+ (void) fprintf(stderr,
+ gettext("Can not import the default policy record to "
+ "the system default policy database\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ rv = load_policies(infile, &plclist);
+ if (rv != KMF_OK)
+ goto out;
+
+ pnode = plclist;
+ while (pnode != NULL && !found) {
+ if (strcmp(policyname, pnode->plc.name) == 0) {
+ KMF_RETURN ret;
+
+ found++;
+ ret = KMF_VerifyPolicy(&pnode->plc);
+ if (ret != KMF_OK) {
+ print_sanity_error(ret);
+ rv = KC_ERR_VERIFY_POLICY;
+ break;
+ }
+ rv = KMF_AddPolicyToDB(&pnode->plc, filename, B_FALSE);
+ }
+ pnode = pnode->next;
+ }
+
+ if (!found) {
+ (void) fprintf(stderr,
+ gettext("Could not find policy \"%s\" in %s\n"),
+ policyname, infile);
+ rv = KC_ERR_FIND_POLICY;
+ }
+
+out:
+ if (filename != NULL)
+ free(filename);
+
+ if (policyname != NULL)
+ free(policyname);
+
+ if (infile != NULL)
+ free(infile);
+
+ free_policy_list(plclist);
+
+ return (rv);
+}
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/kmfcfg.c b/usr/src/cmd/cmd-crypto/kmfcfg/kmfcfg.c
new file mode 100644
index 0000000000..e58368284f
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/kmfcfg.c
@@ -0,0 +1,245 @@
+/*
+ * 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 <stdio.h>
+#include <strings.h>
+#include <ctype.h>
+#include <libgen.h>
+#include <libintl.h>
+#include <locale.h>
+
+#include <kmfapiP.h>
+
+#include "util.h"
+
+/*
+ * The verbcmd construct allows genericizing information about a verb so
+ * that it is easier to manipulate. Makes parsing code easier to read,
+ * fix, and extend with new verbs.
+ */
+typedef struct verbcmd_s {
+ char *verb;
+ int (*action)(int, char *[]);
+ char *synopsis;
+} verbcmd;
+
+int kc_list(int argc, char *argv[]);
+int kc_delete(int argc, char *argv[]);
+int kc_create(int argc, char *argv[]);
+int kc_modify(int argc, char *argv[]);
+int kc_export(int argc, char *argv[]);
+int kc_import(int argc, char *argv[]);
+static int kc_help();
+
+static verbcmd cmds[] = {
+ { "list", kc_list, "list [dbfile=dbfile] "
+ "[policy=policyname]" },
+ { "delete", kc_delete, "delete [dbfile=dbfile] "
+ "policy=policyname" },
+ { "create", kc_create,
+ "create [dbfile=dbfile] policy=policyname\n"
+ "\t\t[ignore-date=true|false]\n"
+ "\t\t[ignore-unknown-eku=true|false]\n"
+ "\t\t[ignore-trust-anchor=true|false]\n"
+ "\t\t[validity-adjusttime=adjusttime]\n"
+ "\t\t[ta-name=trust anchor subject DN]\n"
+ "\t\t[ta-serial=trust anchor serial number]\n"
+ "\t\t[ocsp-responder=URL]\n"
+ "\t\t[ocsp-proxy=URL]\n"
+ "\t\t[ocsp-use-cert-responder=true|false]\n"
+ "\t\t[ocsp-response-lifetime=timelimit]\n"
+ "\t\t[ocsp-ignore-response-sign=true|false]\n"
+ "\t\t[ocsp-responder-cert-name=Issuer DN]\n"
+ "\t\t[ocsp-responder-cert-serial=serial number]\n"
+ "\t\t[crl-basefilename=basefilename]\n"
+ "\t\t[crl-directory=directory]\n"
+ "\t\t[crl-get-crl-uri=true|false]\n"
+ "\t\t[crl-proxy=URL]\n"
+ "\t\t[crl-ignore-crl-sign=true|false]\n"
+ "\t\t[crl-ignore-crl-date=true|false]\n"
+ "\t\t[keyusage=digitalSignature|nonRepudiation\n\t"
+ "\t\t|keyEncipherment | dataEncipherment |\n\t"
+ "\t\tkeyAgreement |keyCertSign |\n\t"
+ "\t\tcRLSign | encipherOnly | decipherOnly],[...]\n"
+ "\t\t[ekunames=serverAuth | clientAuth |\n\t"
+ "\t\tcodeSigning | emailProtection |\n\t"
+ "\t\tipsecEndSystem | ipsecTunnel |\n\t"
+ "\t\tipsecUser | timeStamping |\n\t"
+ "\t\tOCSPSigning],[...]\n"
+ "\t\t[ekuoids=OID,OID,OID...]\n" },
+ { "modify", kc_modify,
+ "modify [dbfile=dbfile] policy=policyname\n"
+ "\t\t[ignore-date=true|false]\n"
+ "\t\t[ignore-unknown-eku=true|false]\n"
+ "\t\t[ignore-trust-anchor=true|false]\n"
+ "\t\t[validity-adjusttime=adjusttime]\n"
+ "\t\t[ta-name=trust anchor subject DN]\n"
+ "\t\t[ta-serial=trust anchor serial number]\n"
+ "\t\t[ocsp-responder=URL]\n"
+ "\t\t[ocsp-proxy=URL]\n"
+ "\t\t[ocsp-use-cert-responder=true|false]\n"
+ "\t\t[ocsp-response-lifetime=timelimit]\n"
+ "\t\t[ocsp-ignore-response-sign=true|false]\n"
+ "\t\t[ocsp-responder-cert-name=Issuer DN]\n"
+ "\t\t[ocsp-responder-cert-serial=serial number]\n"
+ "\t\t[ocsp-none=true|false]\n"
+ "\t\t[crl-basefilename=basefilename]\n"
+ "\t\t[crl-directory=directory]\n"
+ "\t\t[crl-get-crl-uri=true|false]\n"
+ "\t\t[crl-proxy=URL]\n"
+ "\t\t[crl-ignore-crl-sign=true|false]\n"
+ "\t\t[crl-ignore-crl-date=true|false]\n"
+ "\t\t[crl-none=true|false]\n"
+ "\t\t[keyusage=digitalSignature|nonRepudiation\n\t"
+ "\t\t|keyEncipherment | dataEncipherment |\n\t"
+ "\t\tkeyAgreement |keyCertSign |\n\t"
+ "\t\tcRLSign | encipherOnly | decipherOnly],[...]\n"
+ "\t\t[keyusage-none=true|false]\n"
+ "\t\t[ekunames=serverAuth | clientAuth |\n\t"
+ "\t\tcodeSigning | emailProtection |\n\t"
+ "\t\tipsecEndSystem | ipsecTunnel |\n\t"
+ "\t\tipsecUser | timeStamping |\n\t"
+ "\t\tOCSPSigning],[...]\n"
+ "\t\t[ekuoids=OID,OID,OID...]\n"
+ "\t\t[eku-none=true|false]\n" },
+ { "import", kc_import, "import [dbfile=dbfile] policy=policyname "
+ "infile=inputdbfile\n" },
+ { "export", kc_export, "export [dbfile=dbfile] policy=policyname "
+ "outfile=newdbfile\n" },
+ { "-?", kc_help, "help"},
+ { "help", kc_help, ""}
+};
+
+static int num_cmds = sizeof (cmds) / sizeof (verbcmd);
+static char *prog;
+
+static void
+usage(void)
+{
+ int i;
+
+ /* Display this block only in command-line mode. */
+ (void) fprintf(stdout, gettext("Usage:\n"));
+ (void) fprintf(stdout, gettext("\t%s -?\t(help and usage)\n"), prog);
+ (void) fprintf(stdout, gettext("\t%s subcommand [options...]\n"), prog);
+ (void) fprintf(stdout, gettext("where subcommands may be:\n"));
+
+ /* Display only those verbs that match the current tool mode. */
+ for (i = 0; i < num_cmds; i++) {
+ /* Do NOT i18n/l10n. */
+ (void) fprintf(stdout, "\t%s\n", cmds[i].synopsis);
+ }
+}
+
+static int
+kc_help()
+{
+ usage();
+ return (0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ KMF_RETURN ret;
+ int found;
+ int i;
+
+ (void) setlocale(LC_ALL, "");
+#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D. */
+#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it isn't. */
+#endif
+ (void) textdomain(TEXT_DOMAIN);
+
+ prog = basename(argv[0]);
+ argv++; argc--;
+
+ if (argc == 0) {
+ usage();
+ exit(1);
+ }
+
+ if (argc == 1 && argv[0][0] == '-') {
+ switch (argv[0][1]) {
+ case '?':
+ return (kc_help());
+ default:
+ usage();
+ exit(1);
+ }
+ }
+
+ found = -1;
+ for (i = 0; i < num_cmds; i++) {
+ if (strcmp(cmds[i].verb, argv[0]) == 0) {
+ found = i;
+ break;
+ }
+ }
+
+ if (found < 0) {
+ (void) fprintf(stderr, gettext("Invalid command: %s\n"),
+ argv[0]);
+ exit(1);
+ }
+
+ ret = (*cmds[found].action)(argc, argv);
+
+ switch (ret) {
+ case KC_OK:
+ break;
+ case KC_ERR_USAGE:
+ break;
+ case KC_ERR_LOADDB:
+ (void) fprintf(stderr,
+ gettext("Error loading database\n"));
+ break;
+ case KC_ERR_FIND_POLICY:
+ break;
+ case KC_ERR_DELETE_POLICY:
+ (void) fprintf(stderr, gettext("Error deleting policy "
+ "from database.\n"));
+ break;
+ case KC_ERR_ADD_POLICY:
+ break;
+ case KC_ERR_VERIFY_POLICY:
+ break;
+ case KC_ERR_INCOMPLETE_POLICY:
+ break;
+ case KC_ERR_MEMORY:
+ (void) fprintf(stderr, gettext("Out of memory.\n"));
+ break;
+ case KC_ERR_ACCESS:
+ break;
+ default:
+ (void) fprintf(stderr, gettext("%s operation failed. "
+ "error 0x%02x\n"), cmds[found].verb, ret);
+ break;
+ }
+
+ return (ret);
+}
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.dtd b/usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.dtd
new file mode 100644
index 0000000000..32fa28e99a
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.dtd
@@ -0,0 +1,84 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+
+<!--
+ Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ Use is subject to license terms.
+
+ 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
+
+ ident "%Z%%M% %I% %E% SMI"
+-->
+
+<!--Element Definitions-->
+
+<!ELEMENT kmf-policy-db (kmf-policy*)>
+<!ATTLIST kmf-policy-db allow-local-files (TRUE|FALSE) #IMPLIED>
+
+<!ELEMENT kmf-policy (validation-methods, key-usage-set?, ext-key-usage?)>
+<!ATTLIST kmf-policy name CDATA #REQUIRED>
+<!ATTLIST kmf-policy ignore-date (TRUE|FALSE) #IMPLIED>
+<!ATTLIST kmf-policy ignore-unknown-eku (TRUE|FALSE) #IMPLIED>
+<!ATTLIST kmf-policy ignore-trust-anchor (TRUE|FALSE) #IMPLIED>
+<!ATTLIST kmf-policy validity-adjusttime CDATA #IMPLIED>
+<!ATTLIST kmf-policy ta-name CDATA #IMPLIED>
+<!ATTLIST kmf-policy ta-serial CDATA #IMPLIED>
+
+<!ELEMENT validation-methods (ocsp?, crl?)>
+<!ELEMENT ocsp (ocsp-basic, responder-cert?)>
+
+<!ELEMENT ocsp-basic EMPTY>
+<!ATTLIST ocsp-basic
+ responder CDATA #IMPLIED
+ proxy CDATA #IMPLIED
+ uri-from-cert (TRUE|FALSE) #IMPLIED
+ response-lifetime CDATA #IMPLIED
+ ignore-response-sign (TRUE|FALSE) #IMPLIED
+>
+
+<!ELEMENT responder-cert EMPTY>
+<!ATTLIST responder-cert
+ name CDATA #REQUIRED
+ serial CDATA #REQUIRED
+>
+
+<!ELEMENT crl EMPTY>
+<!ATTLIST crl basefilename CDATA #IMPLIED>
+<!ATTLIST crl directory CDATA #IMPLIED>
+<!ATTLIST crl get-crl-uri (TRUE|FALSE) #IMPLIED>
+<!ATTLIST crl proxy CDATA #IMPLIED>
+<!ATTLIST crl ignore-crl-sign (TRUE|FALSE) #IMPLIED>
+<!ATTLIST crl ignore-crl-date (TRUE|FALSE) #IMPLIED>
+
+<!ELEMENT key-usage-set (key-usage+)>
+
+<!ELEMENT key-usage EMPTY>
+<!ATTLIST key-usage use (digitalSignature | nonRepudiation |
+ keyEncipherment | dataEncipherment | keyAgreement |
+ keyCertSign | cRLSign | encipherOnly | decipherOnly) #IMPLIED>
+
+<!ELEMENT ext-key-usage (eku-name*, eku-oid*)>
+
+<!ELEMENT eku-name EMPTY>
+<!ATTLIST eku-name name (serverAuth | clientAuth |
+ codeSigning | emailProtection |
+ ipsecEndSystem | ipsecTunnel | ipsecUser |
+ timeStamping | OCSPSigning) #IMPLIED >
+<!ELEMENT eku-oid EMPTY>
+<!ATTLIST eku-oid oid CDATA #IMPLIED>
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.xml b/usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.xml
new file mode 100644
index 0000000000..2c2ed35e2c
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/kmfpolicy.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ Use is subject to license terms.
+
+ 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
+
+ Sample KMF Policy Database file.
+
+ ident "%Z%%M% %I% %E% SMI"
+-->
+<!DOCTYPE kmf-policy-db SYSTEM "/usr/share/lib/xml/dtd/kmfpolicy.dtd">
+<kmf-policy-db>
+
+<kmf-policy name="default" ignore-date="TRUE" ignore-trust-anchor="TRUE">
+ <validation-methods>
+ <ocsp>
+ <ocsp-basic uri-from-cert="TRUE"
+ ignore-response-sign="TRUE"/>
+ </ocsp>
+ </validation-methods>
+</kmf-policy>
+</kmf-policy-db>
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/list.c b/usr/src/cmd/cmd-crypto/kmfcfg/list.c
new file mode 100644
index 0000000000..e68e2b8643
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/list.c
@@ -0,0 +1,277 @@
+/*
+ * 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 <stdio.h>
+#include <strings.h>
+#include <ctype.h>
+#include <libgen.h>
+#include <libintl.h>
+#include <errno.h>
+#include <kmfapiP.h>
+
+#include "util.h"
+
+static void
+show_policy(KMF_POLICY_RECORD *plc)
+{
+ int i;
+ if (plc == NULL)
+ return;
+
+ (void) printf("Name: %s\n", plc->name);
+
+ (void) printf(gettext("Ignore Date: %s\n"),
+ plc->ignore_date ? gettext("true") : gettext("false"));
+
+ (void) printf(gettext("Ignore Unknown EKUs: %s\n"),
+ plc->ignore_unknown_ekus ? gettext("true") : gettext("false"));
+
+ (void) printf(gettext("Ignore TA: %s\n"),
+ plc->ignore_trust_anchor ? gettext("true") : gettext("false"));
+
+ (void) printf(gettext("Validity Adjusted Time: %s\n"),
+ plc->validity_adjusttime ?
+ plc->validity_adjusttime : "<null>");
+
+ if (plc->ta_name == NULL && plc->ta_serial == NULL) {
+ (void) printf(gettext("Trust Anchor Certificate: <null>\n"));
+ } else {
+ (void) printf(gettext("Trust Anchor Certificate:\n"));
+ (void) printf(gettext("\tName: %s\n"),
+ plc->ta_name ? plc->ta_name : "<null>");
+ (void) printf(gettext("\tSerial Number: %s\n"),
+ plc->ta_serial ? plc->ta_serial : "<null>");
+ }
+
+ if (plc->ku_bits != 0) {
+ (void) printf(gettext("Key Usage Bits: "));
+ for (i = KULOWBIT; i <= KUHIGHBIT; i++) {
+ char *s = ku2str((plc->ku_bits & (1<<i)));
+ if (s != NULL) {
+ (void) printf("%s ", s);
+ }
+ }
+ (void) printf("\n");
+ } else {
+ (void) printf(gettext("Key Usage Bits: 0\n"));
+ }
+
+ if (plc->eku_set.eku_count > 0) {
+ (void) printf(gettext("Extended Key Usage Values:\n"));
+ for (i = 0; i < plc->eku_set.eku_count; i++) {
+ char *s = KMF_OID2EKUString(&plc->eku_set.ekulist[i]);
+ (void) printf("\t%s\t(%s)\n",
+ KMF_OID2String(&plc->eku_set.ekulist[i]),
+ s ? s : "unknown");
+ }
+ } else {
+ (void) printf(gettext("Extended Key Usage Values: <null>\n"));
+ }
+
+ (void) printf(gettext("Validation Policy Information:\n"));
+
+ if (plc->revocation & KMF_REVOCATION_METHOD_OCSP) {
+ (void) printf(gettext(" OCSP:\n"));
+
+ (void) printf(gettext("\tResponder URI: %s\n"),
+ plc->VAL_OCSP_BASIC.responderURI ?
+ plc->VAL_OCSP_BASIC.responderURI : "<null>");
+
+ (void) printf(gettext("\tProxy: %s\n"),
+ plc->VAL_OCSP_BASIC.proxy ?
+ plc->VAL_OCSP_BASIC.proxy : "<null>");
+
+ (void) printf(gettext("\tUse ResponderURI from Certificate: "
+ "%s\n"), plc->VAL_OCSP_BASIC.uri_from_cert ?
+ gettext("true") : gettext("false"));
+
+ (void) printf(gettext("\tResponse lifetime: %s\n"),
+ plc->VAL_OCSP_BASIC.response_lifetime ?
+ plc->VAL_OCSP_BASIC.response_lifetime : "<null>");
+
+ (void) printf(gettext("\tIgnore Response signature: %s\n"),
+ plc->VAL_OCSP_BASIC.ignore_response_sign ?
+ gettext("true") : gettext("false"));
+
+ if (!plc->VAL_OCSP.has_resp_cert) {
+ (void) printf(gettext("\tResponder Certificate:"
+ " <null>\n"));
+ } else {
+ (void) printf(gettext("\tResponder Certificate:\n"));
+ (void) printf(gettext("\t\tName: %s\n"),
+ plc->VAL_OCSP_RESP_CERT.name ?
+ plc->VAL_OCSP_RESP_CERT.name : "<null>");
+ (void) printf(gettext("\t\tSerial: %s\n"),
+ plc->VAL_OCSP_RESP_CERT.serial ?
+ plc->VAL_OCSP_RESP_CERT.serial : "<null>");
+ }
+ }
+
+ if (plc->revocation & KMF_REVOCATION_METHOD_CRL) {
+ (void) printf(gettext(" CRL:\n"));
+
+ (void) printf(gettext("\tBase filename: %s\n"),
+ plc->validation_info.crl_info.basefilename ?
+ plc->validation_info.crl_info.basefilename : "<null>");
+
+ (void) printf(gettext("\tDirectory: %s\n"),
+ plc->validation_info.crl_info.directory ?
+ plc->validation_info.crl_info.directory : "<null>");
+
+ (void) printf(gettext("\tDownload and cache CRL: %s\n"),
+ plc->validation_info.crl_info.get_crl_uri ?
+ gettext("true") : gettext("false"));
+
+ (void) printf(gettext("\tProxy: %s\n"),
+ plc->validation_info.crl_info.proxy ?
+ plc->validation_info.crl_info.proxy : "<null>");
+
+ (void) printf(gettext("\tIgnore CRL signature: %s\n"),
+ plc->validation_info.crl_info.ignore_crl_sign ?
+ gettext("true") : gettext("false"));
+
+ (void) printf(gettext("\tIgnore CRL validity date: %s\n"),
+ plc->validation_info.crl_info.ignore_crl_date ?
+ gettext("true") : gettext("false"));
+ }
+
+ (void) printf("\n");
+}
+
+int
+kc_list(int argc, char *argv[])
+{
+ int rv = KC_OK;
+ int opt, found = 0;
+ extern int optind_av;
+ extern char *optarg_av;
+ char *filename = NULL;
+ char *policyname = NULL;
+ POLICY_LIST *plclist = NULL, *pnode;
+ int sanity_err = 0;
+
+ while ((opt = getopt_av(argc, argv, "i:(dbfile)p:(policy)")) != EOF) {
+ switch (opt) {
+ case 'i':
+ filename = get_string(optarg_av, &rv);
+ if (filename == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error dbfile input.\n"));
+ }
+ break;
+ case 'p':
+ policyname = get_string(optarg_av, &rv);
+ if (policyname == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error policy name.\n"));
+ }
+ break;
+ default:
+ (void) fprintf(stderr,
+ gettext("Error input option.\n"));
+ rv = KC_ERR_USAGE;
+ break;
+ }
+ if (rv != KC_OK)
+ goto out;
+ }
+
+ /* No additional args allowed. */
+ argc -= optind_av;
+ if (argc) {
+ (void) fprintf(stderr,
+ gettext("Error input option\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ if (filename == NULL) {
+ filename = strdup(KMF_DEFAULT_POLICY_FILE);
+ if (filename == NULL) {
+ rv = KC_ERR_MEMORY;
+ goto out;
+ }
+ }
+
+ /* Check the access permission of the policy DB */
+ if (access(filename, R_OK) < 0) {
+ int err = errno;
+ (void) fprintf(stderr,
+ gettext("Cannot access \"%s\" for list - %s\n"), filename,
+ strerror(err));
+ rv = KC_ERR_ACCESS;
+ goto out;
+ }
+
+ rv = load_policies(filename, &plclist);
+ if (rv != KMF_OK) {
+ goto out;
+ }
+
+ pnode = plclist;
+ while (pnode != NULL) {
+ if (policyname == NULL ||
+ strcmp(policyname, pnode->plc.name) == 0) {
+ KMF_POLICY_RECORD *plc = &pnode->plc;
+
+ found++;
+ rv = KMF_VerifyPolicy(plc);
+ if (rv != KMF_OK) {
+ (void) fprintf(stderr, gettext(
+ "Policy Name: '%s' is invalid\n"),
+ plc->name);
+ sanity_err++;
+ } else {
+ show_policy(&pnode->plc);
+ }
+ }
+ pnode = pnode->next;
+ }
+
+ free_policy_list(plclist);
+
+ if (!found) {
+ if (policyname)
+ (void) fprintf(stderr, gettext(
+ "Cannot find policy '%s'\n"), policyname);
+ else
+ (void) fprintf(stderr, gettext("Cannot find "
+ "any policies to display\n"));
+ rv = KC_ERR_FIND_POLICY;
+ } else if (sanity_err) {
+ rv = KC_ERR_VERIFY_POLICY;
+ }
+
+out:
+
+ if (filename != NULL)
+ free(filename);
+
+ if (policyname != NULL)
+ free(policyname);
+
+ return (rv);
+}
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/modify.c b/usr/src/cmd/cmd-crypto/kmfcfg/modify.c
new file mode 100644
index 0000000000..413bda3be7
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/modify.c
@@ -0,0 +1,845 @@
+/*
+ * 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 <stdio.h>
+#include <strings.h>
+#include <ctype.h>
+#include <libgen.h>
+#include <libintl.h>
+#include <errno.h>
+#include <kmfapiP.h>
+#include <cryptoutil.h>
+#include "util.h"
+
+#define KC_IGNORE_DATE 0x0000001
+#define KC_IGNORE_UNKNOWN_EKUS 0x0000002
+#define KC_IGNORE_TRUST_ANCHOR 0x0000004
+#define KC_VALIDITY_ADJUSTTIME 0x0000008
+#define KC_TA_NAME 0x0000010
+#define KC_TA_SERIAL 0x0000020
+#define KC_OCSP_RESPONDER_URI 0x0000040
+#define KC_OCSP_PROXY 0x0000080
+#define KC_OCSP_URI_FROM_CERT 0x0000100
+#define KC_OCSP_RESP_LIFETIME 0x0000200
+#define KC_OCSP_IGNORE_RESP_SIGN 0x0000400
+#define KC_OCSP_RESP_CERT_NAME 0x0000800
+#define KC_OCSP_RESP_CERT_SERIAL 0x0001000
+#define KC_OCSP_NONE 0x0002000
+#define KC_CRL_BASEFILENAME 0x0004000
+#define KC_CRL_DIRECTORY 0x0008000
+#define KC_CRL_GET_URI 0x0010000
+#define KC_CRL_PROXY 0x0020000
+#define KC_CRL_IGNORE_SIGN 0x0040000
+#define KC_CRL_IGNORE_DATE 0x0080000
+#define KC_CRL_NONE 0x0100000
+#define KC_KEYUSAGE 0x0200000
+#define KC_KEYUSAGE_NONE 0x0400000
+#define KC_EKUS 0x0800000
+#define KC_EKUS_NONE 0x1000000
+
+int
+kc_modify(int argc, char *argv[])
+{
+ KMF_RETURN ret;
+ int rv = KC_OK;
+ int opt;
+ extern int optind_av;
+ extern char *optarg_av;
+ char *filename = NULL;
+ uint32_t flags = 0;
+ boolean_t ocsp_none_opt = B_FALSE;
+ boolean_t crl_none_opt = B_FALSE;
+ boolean_t ku_none_opt = B_FALSE;
+ boolean_t eku_none_opt = B_FALSE;
+ int ocsp_set_attr = 0;
+ int crl_set_attr = 0;
+ KMF_POLICY_RECORD oplc, plc;
+
+ (void) memset(&plc, 0, sizeof (KMF_POLICY_RECORD));
+ (void) memset(&oplc, 0, sizeof (KMF_POLICY_RECORD));
+
+ while ((opt = getopt_av(argc, argv,
+ "i:(dbfile)"
+ "p:(policy)"
+ "d:(ignore-date)"
+ "e:(ignore-unknown-eku)"
+ "a:(ignore-trust-anchor)"
+ "v:(validity-adjusttime)"
+ "t:(ta-name)"
+ "s:(ta-serial)"
+ "o:(ocsp-responder)"
+ "P:(ocsp-proxy)"
+ "r:(ocsp-use-cert-responder)"
+ "T:(ocsp-response-lifetime)"
+ "R:(ocsp-ignore-response-sign)"
+ "n:(ocsp-responder-cert-name)"
+ "A:(ocsp-responder-cert-serial)"
+ "y:(ocsp-none)"
+ "c:(crl-basefilename)"
+ "I:(crl-directory)"
+ "g:(crl-get-crl-uri)"
+ "X:(crl-proxy)"
+ "S:(crl-ignore-crl-sign)"
+ "D:(crl-ignore-crl-date)"
+ "z:(crl-none)"
+ "u:(keyusage)"
+ "Y:(keyusage-none)"
+ "E:(ekunames)"
+ "O:(ekuoids)"
+ "Z:(eku-none)")) != EOF) {
+ switch (opt) {
+ case 'i':
+ filename = get_string(optarg_av, &rv);
+ if (filename == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error dbfile input.\n"));
+ }
+ break;
+ case 'p':
+ plc.name = get_string(optarg_av, &rv);
+ if (plc.name == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error policy name.\n"));
+ }
+ break;
+ case 'd':
+ plc.ignore_date = get_boolean(optarg_av);
+ if (plc.ignore_date == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_IGNORE_DATE;
+ }
+ break;
+ case 'e':
+ plc.ignore_unknown_ekus =
+ get_boolean(optarg_av);
+ if (plc.ignore_unknown_ekus == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_IGNORE_UNKNOWN_EKUS;
+ }
+ break;
+ case 'a':
+ plc.ignore_trust_anchor =
+ get_boolean(optarg_av);
+ if (plc.ignore_trust_anchor == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_IGNORE_TRUST_ANCHOR;
+ }
+ break;
+ case 'v':
+ plc.validity_adjusttime =
+ get_string(optarg_av, &rv);
+ if (plc.validity_adjusttime == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error time input.\n"));
+ } else {
+ uint32_t adj;
+ /* for syntax checking */
+ if (str2lifetime(
+ plc.validity_adjusttime,
+ &adj) < 0) {
+ (void) fprintf(stderr,
+ gettext("Error time "
+ "input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_VALIDITY_ADJUSTTIME;
+ }
+ }
+ break;
+ case 't':
+ plc.ta_name = get_string(optarg_av, &rv);
+ if (plc.ta_name == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error name input.\n"));
+ } else {
+ KMF_X509_NAME taDN;
+ /* for syntax checking */
+ if (KMF_DNParser(plc.ta_name,
+ &taDN) != KMF_OK) {
+ (void) fprintf(stderr,
+ gettext("Error name "
+ "input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ KMF_FreeDN(&taDN);
+ flags |= KC_TA_NAME;
+ }
+ }
+ break;
+ case 's':
+ plc.ta_serial = get_string(optarg_av, &rv);
+ if (plc.ta_serial == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error serial input.\n"));
+ } else {
+ uchar_t *bytes = NULL;
+ size_t bytelen;
+
+ ret = KMF_HexString2Bytes(
+ (uchar_t *)plc.ta_serial,
+ &bytes, &bytelen);
+ if (ret != KMF_OK || bytes == NULL) {
+ (void) fprintf(stderr,
+ gettext("serial number "
+ "must be specified as a "
+ "hex number "
+ "(ex: 0x0102030405"
+ "ffeeddee)\n"));
+ rv = KC_ERR_USAGE;
+ break;
+ }
+ if (bytes != NULL)
+ free(bytes);
+ flags |= KC_TA_SERIAL;
+ }
+ break;
+ case 'o':
+ plc.VAL_OCSP_RESPONDER_URI =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_RESPONDER_URI == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error responder "
+ "input.\n"));
+ } else {
+ flags |= KC_OCSP_RESPONDER_URI;
+ ocsp_set_attr++;
+ }
+ break;
+ case 'P':
+ plc.VAL_OCSP_PROXY = get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_PROXY == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error proxy input.\n"));
+ } else {
+ flags |= KC_OCSP_PROXY;
+ ocsp_set_attr++;
+ }
+ break;
+ case 'r':
+ plc.VAL_OCSP_URI_FROM_CERT =
+ get_boolean(optarg_av);
+ if (plc.VAL_OCSP_URI_FROM_CERT == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_OCSP_URI_FROM_CERT;
+ ocsp_set_attr++;
+ }
+ break;
+ case 'T':
+ plc.VAL_OCSP_RESP_LIFETIME =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_RESP_LIFETIME == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error time input.\n"));
+ } else {
+ uint32_t adj;
+ /* for syntax checking */
+ if (str2lifetime(
+ plc.VAL_OCSP_RESP_LIFETIME,
+ &adj) < 0) {
+ (void) fprintf(stderr,
+ gettext("Error time "
+ "input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_OCSP_RESP_LIFETIME;
+ ocsp_set_attr++;
+ }
+ }
+ break;
+ case 'R':
+ plc.VAL_OCSP_IGNORE_RESP_SIGN =
+ get_boolean(optarg_av);
+ if (plc.VAL_OCSP_IGNORE_RESP_SIGN == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_OCSP_IGNORE_RESP_SIGN;
+ ocsp_set_attr++;
+ }
+ break;
+ case 'n':
+ plc.VAL_OCSP_RESP_CERT_NAME =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_RESP_CERT_NAME == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error name input.\n"));
+ } else {
+ KMF_X509_NAME respDN;
+ /* for syntax checking */
+ if (KMF_DNParser(
+ plc.VAL_OCSP_RESP_CERT_NAME,
+ &respDN) != KMF_OK) {
+ (void) fprintf(stderr,
+ gettext("Error name "
+ "input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ KMF_FreeDN(&respDN);
+ flags |= KC_OCSP_RESP_CERT_NAME;
+ ocsp_set_attr++;
+ }
+ }
+ break;
+ case 'A':
+ plc.VAL_OCSP_RESP_CERT_SERIAL =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_OCSP_RESP_CERT_SERIAL == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error serial input.\n"));
+ } else {
+ uchar_t *bytes = NULL;
+ size_t bytelen;
+
+ ret = KMF_HexString2Bytes((uchar_t *)
+ plc.VAL_OCSP_RESP_CERT_SERIAL,
+ &bytes, &bytelen);
+ if (ret != KMF_OK || bytes == NULL) {
+ (void) fprintf(stderr,
+ gettext("serial number "
+ "must be specified as a "
+ "hex number "
+ "(ex: 0x0102030405"
+ "ffeeddee)\n"));
+ rv = KC_ERR_USAGE;
+ break;
+ }
+ if (bytes != NULL)
+ free(bytes);
+ flags |= KC_OCSP_RESP_CERT_SERIAL;
+ ocsp_set_attr++;
+ }
+ break;
+ case 'y':
+ ocsp_none_opt = get_boolean(optarg_av);
+ if (ocsp_none_opt == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_OCSP_NONE;
+ }
+ break;
+ case 'c':
+ plc.VAL_CRL_BASEFILENAME =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_CRL_BASEFILENAME == NULL) {
+ (void) fprintf(stderr, gettext(
+ "Error basefilename input.\n"));
+ } else {
+ flags |= KC_CRL_BASEFILENAME;
+ crl_set_attr++;
+ }
+ break;
+ case 'I':
+ plc.VAL_CRL_DIRECTORY =
+ get_string(optarg_av, &rv);
+ if (plc.VAL_CRL_DIRECTORY == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ } else {
+ flags |= KC_CRL_DIRECTORY;
+ crl_set_attr++;
+ }
+ break;
+ case 'g':
+ plc.VAL_CRL_GET_URI = get_boolean(optarg_av);
+ if (plc.VAL_CRL_GET_URI == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_CRL_GET_URI;
+ crl_set_attr++;
+ }
+ break;
+ case 'X':
+ plc.VAL_CRL_PROXY = get_string(optarg_av, &rv);
+ if (plc.VAL_CRL_PROXY == NULL) {
+ (void) fprintf(stderr,
+ gettext("Error proxy input.\n"));
+ } else {
+ flags |= KC_CRL_PROXY;
+ crl_set_attr++;
+ }
+ break;
+ case 'S':
+ plc.VAL_CRL_IGNORE_SIGN =
+ get_boolean(optarg_av);
+ if (plc.VAL_CRL_IGNORE_SIGN == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_CRL_IGNORE_SIGN;
+ crl_set_attr++;
+ }
+ break;
+ case 'D':
+ plc.VAL_CRL_IGNORE_DATE =
+ get_boolean(optarg_av);
+ if (plc.VAL_CRL_IGNORE_DATE == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_CRL_IGNORE_DATE;
+ crl_set_attr++;
+ }
+ break;
+ case 'z':
+ crl_none_opt = get_boolean(optarg_av);
+ if (crl_none_opt == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_CRL_NONE;
+ }
+ break;
+ case 'u':
+ plc.ku_bits = parseKUlist(optarg_av);
+ if (plc.ku_bits == 0) {
+ (void) fprintf(stderr, gettext(
+ "Error keyusage input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_KEYUSAGE;
+ }
+ break;
+ case 'Y':
+ ku_none_opt = get_boolean(optarg_av);
+ if (ku_none_opt == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_KEYUSAGE_NONE;
+ }
+ break;
+ case 'E':
+ if (parseEKUNames(optarg_av, &plc) != 0) {
+ (void) fprintf(stderr,
+ gettext("Error EKU input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_EKUS;
+ }
+ break;
+ case 'O':
+ if (parseEKUOIDs(optarg_av, &plc) != 0) {
+ (void) fprintf(stderr,
+ gettext("Error EKU OID input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_EKUS;
+ }
+ break;
+ case 'Z':
+ eku_none_opt = get_boolean(optarg_av);
+ if (eku_none_opt == -1) {
+ (void) fprintf(stderr,
+ gettext("Error boolean input.\n"));
+ rv = KC_ERR_USAGE;
+ } else {
+ flags |= KC_EKUS_NONE;
+ }
+ break;
+ default:
+ (void) fprintf(stderr,
+ gettext("Error input option.\n"));
+ rv = KC_ERR_USAGE;
+ break;
+ }
+ if (rv != KC_OK)
+ goto out;
+ }
+
+ /* No additional args allowed. */
+ argc -= optind_av;
+ if (argc) {
+ (void) fprintf(stderr,
+ gettext("Error input option\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ if (filename == NULL) {
+ filename = strdup(KMF_DEFAULT_POLICY_FILE);
+ if (filename == NULL) {
+ rv = KC_ERR_MEMORY;
+ goto out;
+ }
+ }
+
+ /*
+ * Must have a policy name. The policy name can not be default
+ * if using the default policy file.
+ */
+ if (plc.name == NULL) {
+ (void) fprintf(stderr,
+ gettext("You must specify a policy name.\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ } else if (strcmp(filename, KMF_DEFAULT_POLICY_FILE) == 0 &&
+ strcmp(plc.name, KMF_DEFAULT_POLICY_NAME) == 0) {
+ (void) fprintf(stderr,
+ gettext("Can not modify the default policy in the default "
+ "policy file.\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ /* Check the access permission of the policy DB */
+ if (access(filename, W_OK) < 0) {
+ int err = errno;
+ (void) fprintf(stderr,
+ gettext("Cannot access \"%s\" for modify - %s\n"),
+ filename, strerror(err));
+ rv = KC_ERR_ACCESS;
+ goto out;
+ }
+
+ /* Try to load the named policy from the DB */
+ ret = KMF_GetPolicy(filename, plc.name, &oplc);
+ if (ret != KMF_OK) {
+ (void) fprintf(stderr,
+ gettext("Error loading policy \"%s\" from %s\n"), filename,
+ plc.name);
+ return (KC_ERR_FIND_POLICY);
+ }
+
+ /* Update the general policy attributes. */
+ if (flags & KC_IGNORE_DATE)
+ oplc.ignore_date = plc.ignore_date;
+
+ if (flags & KC_IGNORE_UNKNOWN_EKUS)
+ oplc.ignore_unknown_ekus = plc.ignore_unknown_ekus;
+
+ if (flags & KC_IGNORE_TRUST_ANCHOR)
+ oplc.ignore_trust_anchor = plc.ignore_trust_anchor;
+
+ if (flags & KC_VALIDITY_ADJUSTTIME) {
+ if (oplc.validity_adjusttime)
+ free(oplc.validity_adjusttime);
+ oplc.validity_adjusttime =
+ plc.validity_adjusttime;
+ }
+
+ if (flags & KC_TA_NAME) {
+ if (oplc.ta_name)
+ free(oplc.ta_name);
+ oplc.ta_name = plc.ta_name;
+ }
+ if (flags & KC_TA_SERIAL) {
+ if (oplc.ta_serial)
+ free(oplc.ta_serial);
+ oplc.ta_serial = plc.ta_serial;
+ }
+
+ /* Update the OCSP policy */
+ if (ocsp_none_opt == B_TRUE) {
+ if (ocsp_set_attr > 0) {
+ (void) fprintf(stderr,
+ gettext("Can not set ocsp-none=true and other "
+ "OCSP attributes at the same time.\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ /*
+ * If the original policy does not have OCSP checking,
+ * then we do not need to do anything. If the original
+ * policy has the OCSP checking, then we need to release the
+ * space of OCSP attributes and turn the OCSP checking off.
+ */
+ if (oplc.revocation & KMF_REVOCATION_METHOD_OCSP) {
+ if (oplc.VAL_OCSP_BASIC.responderURI) {
+ free(oplc.VAL_OCSP_BASIC.responderURI);
+ oplc.VAL_OCSP_BASIC.responderURI = NULL;
+ }
+
+ if (oplc.VAL_OCSP_BASIC.proxy) {
+ free(oplc.VAL_OCSP_BASIC.proxy);
+ oplc.VAL_OCSP_BASIC.proxy = NULL;
+ }
+
+ if (oplc.VAL_OCSP_BASIC.response_lifetime) {
+ free(oplc.VAL_OCSP_BASIC.response_lifetime);
+ oplc.VAL_OCSP_BASIC.response_lifetime = NULL;
+ }
+
+ if (flags & KC_OCSP_RESP_CERT_NAME) {
+ free(oplc.VAL_OCSP_RESP_CERT.name);
+ oplc.VAL_OCSP_RESP_CERT.name = NULL;
+ }
+
+ if (flags & KC_OCSP_RESP_CERT_SERIAL) {
+ free(oplc.VAL_OCSP_RESP_CERT.serial);
+ oplc.VAL_OCSP_RESP_CERT.serial = NULL;
+ }
+
+ /* Turn off the OCSP checking */
+ oplc.revocation &= ~KMF_REVOCATION_METHOD_OCSP;
+ }
+
+ } else {
+ /*
+ * If the "ocsp-none" option is not set or is set to false,
+ * then we only need to do the modification if there is at
+ * least one OCSP attribute is specified.
+ */
+ if (ocsp_set_attr > 0) {
+ if (flags & KC_OCSP_RESPONDER_URI) {
+ if (oplc.VAL_OCSP_RESPONDER_URI)
+ free(oplc.VAL_OCSP_RESPONDER_URI);
+ oplc.VAL_OCSP_RESPONDER_URI =
+ plc.VAL_OCSP_RESPONDER_URI;
+ }
+
+ if (flags & KC_OCSP_PROXY) {
+ if (oplc.VAL_OCSP_PROXY)
+ free(oplc.VAL_OCSP_PROXY);
+ oplc.VAL_OCSP_PROXY = plc.VAL_OCSP_PROXY;
+ }
+
+ if (flags & KC_OCSP_URI_FROM_CERT)
+ oplc.VAL_OCSP_URI_FROM_CERT =
+ plc.VAL_OCSP_URI_FROM_CERT;
+
+ if (flags & KC_OCSP_RESP_LIFETIME) {
+ if (oplc.VAL_OCSP_RESP_LIFETIME)
+ free(oplc.VAL_OCSP_RESP_LIFETIME);
+ oplc.VAL_OCSP_RESP_LIFETIME =
+ plc.VAL_OCSP_RESP_LIFETIME;
+ }
+
+ if (flags & KC_OCSP_IGNORE_RESP_SIGN)
+ oplc.VAL_OCSP_IGNORE_RESP_SIGN =
+ plc.VAL_OCSP_IGNORE_RESP_SIGN;
+
+ if (flags & KC_OCSP_RESP_CERT_NAME) {
+ if (oplc.VAL_OCSP_RESP_CERT_NAME)
+ free(oplc.VAL_OCSP_RESP_CERT_NAME);
+ oplc.VAL_OCSP_RESP_CERT_NAME =
+ plc.VAL_OCSP_RESP_CERT_NAME;
+ }
+
+ if (flags & KC_OCSP_RESP_CERT_SERIAL) {
+ if (oplc.VAL_OCSP_RESP_CERT_SERIAL)
+ free(oplc.VAL_OCSP_RESP_CERT_SERIAL);
+ oplc.VAL_OCSP_RESP_CERT_SERIAL =
+ plc.VAL_OCSP_RESP_CERT_SERIAL;
+ }
+
+ if (oplc.VAL_OCSP_RESP_CERT_NAME != NULL &&
+ oplc.VAL_OCSP_RESP_CERT_SERIAL != NULL)
+ oplc.VAL_OCSP.has_resp_cert = B_TRUE;
+ else
+ oplc.VAL_OCSP.has_resp_cert = B_FALSE;
+
+ /* Turn on the OCSP checking */
+ oplc.revocation |= KMF_REVOCATION_METHOD_OCSP;
+ }
+ }
+
+ /* Update the CRL policy */
+ if (crl_none_opt == B_TRUE) {
+ if (crl_set_attr > 0) {
+ (void) fprintf(stderr,
+ gettext("Can not set crl-none=true and other CRL "
+ "attributes at the same time.\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ /*
+ * If the original policy does not have CRL checking,
+ * then we do not need to do anything. If the original
+ * policy has the CRL checking, then we need to release the
+ * space of CRL attributes and turn the CRL checking off.
+ */
+ if (oplc.revocation & KMF_REVOCATION_METHOD_CRL) {
+ if (oplc.VAL_CRL_BASEFILENAME) {
+ free(oplc.VAL_CRL_BASEFILENAME);
+ oplc.VAL_CRL_BASEFILENAME = NULL;
+ }
+
+ if (oplc.VAL_CRL_DIRECTORY) {
+ free(oplc.VAL_CRL_DIRECTORY);
+ oplc.VAL_CRL_DIRECTORY = NULL;
+ }
+
+ if (oplc.VAL_CRL_PROXY) {
+ free(oplc.VAL_CRL_PROXY);
+ oplc.VAL_CRL_PROXY = NULL;
+ }
+
+ /* Turn off the CRL checking */
+ oplc.revocation &= ~KMF_REVOCATION_METHOD_CRL;
+ }
+ } else {
+ /*
+ * If the "ocsp-none" option is not set or is set to false,
+ * then we only need to do the modification if there is at
+ * least one CRL attribute is specified.
+ */
+ if (crl_set_attr > 0) {
+ if (flags & KC_CRL_BASEFILENAME) {
+ if (oplc.VAL_CRL_BASEFILENAME)
+ free(oplc.VAL_CRL_BASEFILENAME);
+ oplc.VAL_CRL_BASEFILENAME =
+ plc.VAL_CRL_BASEFILENAME;
+ }
+
+ if (flags & KC_CRL_DIRECTORY) {
+ if (oplc.VAL_CRL_DIRECTORY)
+ free(oplc.VAL_CRL_DIRECTORY);
+ oplc.VAL_CRL_DIRECTORY = plc.VAL_CRL_DIRECTORY;
+ }
+
+ if (flags & KC_CRL_GET_URI) {
+ oplc.VAL_CRL_GET_URI = plc.VAL_CRL_GET_URI;
+ }
+
+ if (flags & KC_CRL_PROXY) {
+ if (oplc.VAL_CRL_PROXY)
+ free(oplc.VAL_CRL_PROXY);
+ oplc.VAL_CRL_PROXY = plc.VAL_CRL_PROXY;
+ }
+
+ if (flags & KC_CRL_IGNORE_SIGN) {
+ oplc.VAL_CRL_IGNORE_SIGN =
+ plc.VAL_CRL_IGNORE_SIGN;
+ }
+
+ if (flags & KC_CRL_IGNORE_DATE) {
+ oplc.VAL_CRL_IGNORE_DATE =
+ plc.VAL_CRL_IGNORE_DATE;
+ }
+
+ /* Turn on the CRL checking */
+ oplc.revocation |= KMF_REVOCATION_METHOD_CRL;
+ }
+ }
+
+ /* Update the Key Usage */
+ if (ku_none_opt == B_TRUE) {
+ if (flags & KC_KEYUSAGE) {
+ (void) fprintf(stderr,
+ gettext("Can not set keyusage-none=true and "
+ "modify the keyusage value at the same time.\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ oplc.ku_bits = 0;
+ } else {
+ /*
+ * If the "keyusage-none" option is not set or is set to
+ * false, then we only need to do the modification if
+ * the keyusage value is specified.
+ */
+ if (flags & KC_KEYUSAGE)
+ oplc.ku_bits = plc.ku_bits;
+ }
+
+
+ /* Update the Extended Key Usage */
+ if (eku_none_opt == B_TRUE) {
+ if (flags & KC_EKUS) {
+ (void) fprintf(stderr,
+ gettext("Can not set eku-none=true and modify "
+ "EKU values at the same time.\n"));
+ rv = KC_ERR_USAGE;
+ goto out;
+ }
+
+ /* Release current EKU list (if any) */
+ if (oplc.eku_set.eku_count > 0) {
+ KMF_FreeEKUPolicy(&oplc.eku_set);
+ oplc.eku_set.eku_count = 0;
+ oplc.eku_set.ekulist = NULL;
+ }
+ } else {
+ /*
+ * If the "eku-none" option is not set or is set to false,
+ * then we only need to do the modification if either
+ * "ekuname" or "ekuoids" is specified.
+ */
+ if (flags & KC_EKUS) {
+ /* Release current EKU list (if any) */
+ KMF_FreeEKUPolicy(&oplc.eku_set);
+ oplc.eku_set = plc.eku_set;
+ }
+ }
+
+ /* Do a sanity check on the modified policy */
+ ret = KMF_VerifyPolicy(&oplc);
+ if (ret != KMF_OK) {
+ print_sanity_error(ret);
+ rv = KC_ERR_VERIFY_POLICY;
+ goto out;
+ }
+
+ /* The modify operation is a delete followed by an add */
+ ret = KMF_DeletePolicyFromDB(oplc.name, filename);
+ if (ret != KMF_OK) {
+ rv = KC_ERR_DELETE_POLICY;
+ goto out;
+ }
+
+ /*
+ * Now add the modified policy back to the DB.
+ */
+ ret = KMF_AddPolicyToDB(&oplc, filename, B_FALSE);
+ if (ret != KMF_OK) {
+ (void) fprintf(stderr,
+ gettext("Error adding policy to database: 0x%04x\n"), ret);
+ rv = KC_ERR_ADD_POLICY;
+ goto out;
+ }
+
+out:
+ if (filename != NULL)
+ free(filename);
+
+ KMF_FreePolicyRecord(&oplc);
+
+ return (rv);
+}
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/util.c b/usr/src/cmd/cmd-crypto/kmfcfg/util.c
new file mode 100644
index 0000000000..f3bdc633f2
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/util.c
@@ -0,0 +1,497 @@
+/*
+ * 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 <stdio.h>
+#include <strings.h>
+#include <ctype.h>
+#include <libgen.h>
+#include <libintl.h>
+
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+
+#include <kmfapiP.h>
+
+#include "util.h"
+
+/* Supporting structures and global variables for getopt_av(). */
+typedef struct av_opts_s {
+ int shortnm; /* short name character */
+ char *longnm; /* long name string, NOT terminated */
+ int longnm_len; /* length of long name string */
+ boolean_t has_arg; /* takes optional argument */
+} av_opts;
+
+static av_opts *opts_av = NULL;
+static const char *_save_optstr = NULL;
+static int _save_numopts = 0;
+int optind_av = 1;
+char *optarg_av = NULL;
+
+void
+free_policy_list(POLICY_LIST *plist)
+{
+ POLICY_LIST *n = plist, *old;
+
+ if (plist == NULL)
+ return;
+
+ while (n != NULL) {
+ old = n;
+ KMF_FreePolicyRecord(&n->plc);
+ n = n->next;
+ free(old);
+ }
+ plist = NULL;
+}
+
+int
+load_policies(char *file, POLICY_LIST **policy_list)
+{
+ int rv = KC_OK;
+ KMF_RETURN kmfrv = KMF_OK;
+ POLICY_LIST *newitem, *plist = NULL;
+ xmlParserCtxtPtr ctxt;
+ xmlDocPtr doc = NULL;
+ xmlNodePtr cur, node;
+
+ /* Create a parser context */
+ ctxt = xmlNewParserCtxt();
+ if (ctxt == NULL)
+ return (KMF_ERR_POLICY_DB_FORMAT);
+
+ /* Read the policy DB and verify it against the schema. */
+ doc = xmlCtxtReadFile(ctxt, file, NULL,
+ XML_PARSE_DTDVALID | XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
+ if (doc == NULL || ctxt->valid == 0) {
+ kmfrv = KMF_ERR_POLICY_DB_FORMAT;
+ goto end;
+ }
+
+ cur = xmlDocGetRootElement(doc);
+ if (cur == NULL) {
+ kmfrv = KMF_ERR_POLICY_DB_FORMAT;
+ goto end;
+ }
+
+ node = cur->xmlChildrenNode;
+ while (node != NULL) {
+ char *c;
+ /*
+ * Search for the policy that matches the given name.
+ */
+ if (!xmlStrcmp((const xmlChar *)node->name,
+ (const xmlChar *)KMF_POLICY_ELEMENT)) {
+ /* Check the name attribute */
+ c = (char *)xmlGetProp(node,
+ (const xmlChar *)KMF_POLICY_NAME_ATTR);
+
+ /* If a match, parse the rest of the data */
+ if (c != NULL) {
+ xmlFree(c);
+ newitem = malloc(sizeof (POLICY_LIST));
+ if (newitem != NULL) {
+ (void) memset(newitem, 0,
+ sizeof (POLICY_LIST));
+ kmfrv = parsePolicyElement(node,
+ &newitem->plc);
+ } else {
+ kmfrv = KMF_ERR_MEMORY;
+ goto end;
+ }
+ /* add to linked list */
+ if (plist == NULL) {
+ plist = newitem;
+ } else {
+ POLICY_LIST *n = plist;
+ while (n->next != NULL)
+ n = n->next;
+
+ n->next = newitem;
+ newitem->next = NULL;
+ }
+ }
+ }
+ node = node->next;
+ }
+
+end:
+ if (ctxt != NULL)
+ xmlFreeParserCtxt(ctxt);
+
+ if (doc != NULL)
+ xmlFreeDoc(doc);
+
+ if (kmfrv != KMF_OK) {
+ free_policy_list(plist);
+ rv = KC_ERR_LOADDB;
+ } else {
+ *policy_list = plist;
+ }
+
+ return (rv);
+}
+
+/*
+ * Return 0 if there is any error in the input string.
+ */
+uint16_t
+parseKUlist(char *kustring)
+{
+ uint16_t cur_bit;
+ uint16_t kubits = 0;
+ char *p;
+
+ p = strtok(kustring, ",");
+ while (p != NULL) {
+ cur_bit = KMF_StringToKeyUsage(p);
+ if (cur_bit == 0) {
+ kubits = 0;
+ break;
+ }
+ kubits |= cur_bit;
+ p = strtok(NULL, ",");
+ }
+
+ return (kubits);
+}
+
+static void
+addToEKUList(KMF_EKU_POLICY *ekus, KMF_OID *newoid)
+{
+ if (newoid != NULL && ekus != NULL) {
+ ekus->eku_count++;
+ ekus->ekulist = realloc(
+ ekus->ekulist,
+ ekus->eku_count * sizeof (KMF_OID));
+ if (ekus->ekulist != NULL) {
+ ekus->ekulist[ekus->eku_count-1] = *newoid;
+ }
+ }
+}
+
+int
+parseEKUNames(char *ekulist, KMF_POLICY_RECORD *plc)
+{
+ int rv = KC_OK;
+ char *p;
+ KMF_OID *newoid;
+ KMF_EKU_POLICY *ekus = &plc->eku_set;
+
+ if (ekulist == NULL || !strlen(ekulist))
+ return (0);
+
+ /*
+ * The list should be comma separated list of EKU Names.
+ */
+ p = strtok(ekulist, ",");
+
+ /* If no tokens found, then maybe its just a single EKU value */
+ if (p == NULL) {
+ newoid = kmf_ekuname2oid(ekulist);
+ if (newoid != NULL) {
+ addToEKUList(ekus, newoid);
+ free(newoid);
+ } else {
+ rv = KC_ERR_USAGE;
+ }
+ }
+
+ while (p != NULL) {
+ newoid = kmf_ekuname2oid(p);
+ if (newoid != NULL) {
+ addToEKUList(ekus, newoid);
+ free(newoid);
+ } else {
+ rv = KC_ERR_USAGE;
+ break;
+ }
+ p = strtok(NULL, ",");
+ }
+
+ if (rv != KC_OK)
+ KMF_FreeEKUPolicy(ekus);
+
+ return (rv);
+}
+
+int
+parseEKUOIDs(char *ekulist, KMF_POLICY_RECORD *plc)
+{
+ int rv = KC_OK;
+ char *p;
+ KMF_OID *newoid;
+ KMF_EKU_POLICY *ekus = &plc->eku_set;
+
+ if (ekulist == NULL || !strlen(ekulist))
+ return (0);
+
+ /*
+ * The list should be comma separated list of EKU Names.
+ */
+ p = strtok(ekulist, ",");
+ if (p == NULL) {
+ newoid = kmf_string2oid(ekulist);
+ if (newoid != NULL) {
+ addToEKUList(ekus, newoid);
+ free(newoid);
+ } else {
+ rv = KC_ERR_USAGE;
+ }
+ }
+
+ while (p != NULL && rv == 0) {
+ newoid = kmf_string2oid(p);
+ if (newoid != NULL) {
+ addToEKUList(ekus, newoid);
+ free(newoid);
+ } else {
+ rv = KC_ERR_USAGE;
+ break;
+ }
+ p = strtok(NULL, ",");
+ }
+
+ if (rv != KC_OK)
+ KMF_FreeEKUPolicy(ekus);
+
+ return (rv);
+}
+
+int
+get_boolean(char *arg)
+{
+ if (arg == NULL)
+ return (-1);
+ if (strcasecmp(arg, "true") == 0)
+ return (1);
+ if (strcasecmp(arg, "false") == 0)
+ return (0);
+ return (-1);
+}
+
+/*
+ * This function processes the input string. It removes the beginning
+ * and ending blank's first, makes a copy of the resulting string and
+ * return it.
+ *
+ * This function returns NULL, if there is an error in the
+ * input string or when the system is out of memory. The output
+ * "err_flag" argument will record the error code, if it is not NULL.
+ */
+char *
+get_string(char *str, int *err_flag)
+{
+ char *p;
+ int len, i;
+ char *retstr = NULL;
+
+ if (str == NULL) {
+ if (err_flag != NULL)
+ *err_flag = KC_ERR_USAGE;
+ return (NULL);
+ }
+
+ /* Remove beginning whitespace */
+ p = str;
+ while (p != NULL && isspace(*p))
+ p++;
+
+ if (p == NULL) {
+ if (err_flag != NULL)
+ *err_flag = KC_ERR_USAGE;
+ return (NULL);
+ }
+
+ /* Remove the trailing blanks */
+ len = strlen(p);
+ while (len > 0 && isspace(p[len-1]))
+ len--;
+
+ if (len == 0) {
+ if (err_flag != NULL)
+ *err_flag = KC_ERR_USAGE;
+ return (NULL);
+ }
+
+ /* Check if there is any non-printable character */
+ i = 0;
+ while (i < len) {
+ if (isprint(p[i]))
+ i++;
+ else {
+ if (err_flag != NULL)
+ *err_flag = KC_ERR_USAGE;
+ return (NULL);
+ }
+ }
+
+ /* Make a copy of the string and return it */
+ retstr = malloc(len + 1);
+ if (retstr == NULL) {
+ if (err_flag != NULL)
+ *err_flag = KC_ERR_MEMORY;
+ return (NULL);
+ }
+
+ if (err_flag != NULL)
+ *err_flag = KC_OK;
+
+ (void) strncpy(retstr, p, len);
+ retstr[len] = '\0';
+ return (retstr);
+}
+
+/*
+ * Breaks out the getopt-style option string into a structure that can be
+ * traversed later for calls to getopt_av(). Option string is NOT altered,
+ * but the struct fields point to locations within option string.
+ */
+static int
+populate_opts(char *optstring)
+{
+ int i;
+ av_opts *temp;
+ char *marker;
+
+ if (optstring == NULL || *optstring == '\0')
+ return (0);
+
+ /*
+ * This tries to imitate getopt(3c) Each option must conform to:
+ * <short name char> [ ':' ] [ '(' <long name string> ')' ]
+ * If long name is missing, the short name is used for long name.
+ */
+ for (i = 0; *optstring != '\0'; i++) {
+ if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
+ realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) {
+ free(opts_av);
+ opts_av = NULL;
+ return (0);
+ } else
+ opts_av = (av_opts *)temp;
+
+ marker = optstring; /* may need optstring later */
+
+ opts_av[i].shortnm = *marker++; /* set short name */
+
+ if (*marker == ':') { /* check for opt arg */
+ marker++;
+ opts_av[i].has_arg = B_TRUE;
+ }
+
+ if (*marker == '(') { /* check and set long name */
+ marker++;
+ opts_av[i].longnm = marker;
+ opts_av[i].longnm_len = strcspn(marker, ")");
+ optstring = marker + opts_av[i].longnm_len + 1;
+ } else {
+ /* use short name option character */
+ opts_av[i].longnm = optstring;
+ opts_av[i].longnm_len = 1;
+ optstring = marker;
+ }
+ }
+
+ return (i);
+}
+
+/*
+ * getopt_av() is very similar to getopt(3c) in that the takes an option
+ * string, compares command line arguments for matches, and returns a single
+ * letter option when a match is found. However, getopt_av() differs from
+ * getopt(3c) by allowing both longname options and values be found
+ * on the command line.
+ */
+int
+getopt_av(int argc, char * const *argv, const char *optstring)
+{
+ int i;
+ int len;
+
+ if (optind_av >= argc)
+ return (EOF);
+
+ /* First time or when optstring changes from previous one */
+ if (_save_optstr != optstring) {
+ if (opts_av != NULL)
+ free(opts_av);
+ opts_av = NULL;
+ _save_optstr = optstring;
+ _save_numopts = populate_opts((char *)optstring);
+ }
+
+ for (i = 0; i < _save_numopts; i++) {
+ if (strcmp(argv[optind_av], "--") == 0) {
+ optind_av++;
+ break;
+ }
+
+ len = strcspn(argv[optind_av], "=");
+
+ if (len == opts_av[i].longnm_len && strncmp(argv[optind_av],
+ opts_av[i].longnm, opts_av[i].longnm_len) == 0) {
+ /* matched */
+ if (!opts_av[i].has_arg) {
+ optind_av++;
+ return (opts_av[i].shortnm);
+ }
+
+ /* needs optarg */
+ if (argv[optind_av][len] == '=') {
+ optarg_av = &(argv[optind_av][len+1]);
+ optind_av++;
+ return (opts_av[i].shortnm);
+ }
+
+ optarg_av = NULL;
+ optind_av++;
+ return ((int)'?');
+ }
+ }
+
+ return (EOF);
+}
+
+void
+print_sanity_error(KMF_RETURN ret)
+{
+ switch (ret) {
+ case KMF_ERR_POLICY_NAME:
+ (void) fprintf(stderr, gettext("Error in the policy name\n"));
+ break;
+ case KMF_ERR_TA_POLICY:
+ (void) fprintf(stderr,
+ gettext("Error in trust anchor attributes\n"));
+ break;
+ case KMF_ERR_OCSP_POLICY:
+ (void) fprintf(stderr,
+ gettext("Error in OCSP policy attributes\n"));
+ break;
+ default:
+ break;
+ }
+}
diff --git a/usr/src/cmd/cmd-crypto/kmfcfg/util.h b/usr/src/cmd/cmd-crypto/kmfcfg/util.h
new file mode 100644
index 0000000000..74f4b0be9b
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/kmfcfg/util.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+#ifndef _UTIL_H
+#define _UTIL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <kmfapiP.h>
+
+
+typedef struct _policy_list {
+ KMF_POLICY_RECORD plc;
+ struct _policy_list *next;
+} POLICY_LIST;
+
+void free_policy_list(POLICY_LIST *);
+int getopt_av(int, char * const *, const char *);
+
+int load_policies(char *, POLICY_LIST **);
+int get_boolean(char *);
+char *get_string(char *, int *err_flag);
+int parseEKUOIDs(char *, KMF_POLICY_RECORD *);
+int parseEKUNames(char *, KMF_POLICY_RECORD *);
+uint16_t parseKUlist(char *);
+void print_sanity_error(KMF_RETURN);
+
+#define KC_OK 0
+#define KC_ERR_USAGE 1
+#define KC_ERR_LOADDB 2
+#define KC_ERR_FIND_POLICY 3
+#define KC_ERR_DELETE_POLICY 4
+#define KC_ERR_ADD_POLICY 5
+#define KC_ERR_VERIFY_POLICY 6
+#define KC_ERR_INCOMPLETE_POLICY 7
+#define KC_ERR_MEMORY 8
+#define KC_ERR_ACCESS 9
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _UTIL_H */
diff --git a/usr/src/cmd/cmd-crypto/pktool/Makefile b/usr/src/cmd/cmd-crypto/pktool/Makefile
index 0ad8e96905..dcfefac49a 100644
--- a/usr/src/cmd/cmd-crypto/pktool/Makefile
+++ b/usr/src/cmd/cmd-crypto/pktool/Makefile
@@ -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 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -30,31 +29,30 @@ PROG = pktool
OBJS = pktool.o \
common.o \
- derparse.o \
- osslcommon.o \
- p12common.o \
setpin.o \
list.o \
delete.o \
import.o \
export.o \
- tokens.o
+ tokens.o \
+ gencert.o \
+ gencsr.o \
+ download.o \
+ genkey.o
include ../../Makefile.cmd
-include $(SRC)/lib/openssl/Makefile.openssl
+KMFDIR = $(SRC)/lib/libkmf
SRCS = $(OBJS:%.o=%.c)
POFILES = $(OBJS:%.o=%.po)
POFILE = $(PROG)_msg.po
+MSGFILES=$(SRCS:%.c=%.i)
-CPPFLAGS += -I. $(OPENSSL_CPPFLAGS)
-CFLAGS += $(CCVERBOSE)
+CPPFLAGS += -I. -I$(KMFDIR)/include
+CFLAGS += $(CCVERBOSE) -DDEBUG
-DYNFLAGS += $(OPENSSL_DYNFLAGS)
-LDFLAGS += $(OPENSSL_LDFLAGS)
-LDLIBS += -lpkcs11 -lcryptoutil -lcrypto -lldap
-
-LINTFLAGS += $(OPENSSL_LDFLAGS)
+LDFLAGS += -L$(SRC)/lib/libkmf/libkmf/$(MACH)
+LDLIBS += -lkmf -lpkcs11 -lcryptoutil
.KEEP_STATE:
@@ -65,7 +63,7 @@ $(PROG) : $(OBJS)
$(POST_PROCESS)
$(POFILE) : $(POFILES)
- $(RM) $@; cat $(POFILES) > $@
+ $(BUILDPO.pofiles)
install : all $(ROOTPROG)
@@ -75,4 +73,3 @@ clean :
lint : lint_SRCS
include ../../Makefile.targ
-
diff --git a/usr/src/cmd/cmd-crypto/pktool/biginteger.h b/usr/src/cmd/cmd-crypto/pktool/biginteger.h
deleted file mode 100644
index 3764e47aaa..0000000000
--- a/usr/src/cmd/cmd-crypto/pktool/biginteger.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.
- *
- * 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 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _PKTOOL_BIGINTEGER_H
-#define _PKTOOL_BIGINTEGER_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <security/pkcs11t.h>
-
-/*
- * NOTE:
- *
- * This is same "biginteger_t" found in both these places:
- * usr/src/lib/pkcs11/pkcs11_softtoken/common/softObject.h
- * usr/src/lib/pkcs11/pkcs11_kernel/common/kernelObject.h
- * The BIGNUM implementation in usr/src/common/bignum does not
- * meet the need. It is recommended that the biginteger_t be
- * factored out of pkcs11_softtoken/pkcs11_kernel/pktool and
- * the pkcs11 libraries and moved into cryptoutil.h
- */
-typedef struct biginteger {
- CK_BYTE *big_value;
- CK_ULONG big_value_len;
-} biginteger_t;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PKTOOL_BIGINTEGER_H */
diff --git a/usr/src/cmd/cmd-crypto/pktool/common.c b/usr/src/cmd/cmd-crypto/pktool/common.c
index 030f8c158a..660afe2d57 100644
--- a/usr/src/cmd/cmd-crypto/pktool/common.c
+++ b/usr/src/cmd/cmd-crypto/pktool/common.c
@@ -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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -38,19 +37,19 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <tzfile.h>
#include <cryptoutil.h>
#include <security/cryptoki.h>
-#include "common.h"
-#include "biginteger.h"
+#include <kmfapi.h>
-/* True and false for attribute templates. */
-CK_BBOOL pk_true = B_TRUE;
-CK_BBOOL pk_false = B_FALSE;
+#include "common.h"
/* Local status variables. */
static boolean_t initialized = B_FALSE;
static boolean_t session_opened = B_FALSE;
-static boolean_t session_writable = B_FALSE;
static boolean_t logged_in = B_FALSE;
/* Supporting structures and global variables for getopt_av(). */
@@ -67,6 +66,9 @@ static int _save_numopts = 0;
int optind_av = 1;
char *optarg_av = NULL;
+static void close_sess(CK_SESSION_HANDLE);
+static void logout_token(CK_SESSION_HANDLE);
+
/*
* Perform PKCS#11 setup here. Currently only C_Initialize is required,
* along with setting/resetting state variables.
@@ -76,19 +78,15 @@ init_pk11(void)
{
CK_RV rv = CKR_OK;
- cryptodebug("inside init_pk11");
-
/* If C_Initialize() already called, nothing to do here. */
if (initialized == B_TRUE)
return (CKR_OK);
/* Reset state variables because C_Initialize() not yet done. */
session_opened = B_FALSE;
- session_writable = B_FALSE;
logged_in = B_FALSE;
/* Initialize PKCS#11 library. */
- cryptodebug("calling C_Initialize()");
if ((rv = C_Initialize(NULL_PTR)) != CKR_OK &&
rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
return (rv);
@@ -105,7 +103,6 @@ init_pk11(void)
void
final_pk11(CK_SESSION_HANDLE sess)
{
- cryptodebug("inside final_pk11");
/* If the library wasn't initialized, nothing to do here. */
if (!initialized)
@@ -114,127 +111,41 @@ final_pk11(CK_SESSION_HANDLE sess)
/* Make sure the sesion is closed first. */
close_sess(sess);
- cryptodebug("calling C_Finalize()");
(void) C_Finalize(NULL);
initialized = B_FALSE;
}
/*
- * Create a PKCS#11 session on the given slot, and set state information.
- * If session is already open, check that the read-only/read-write state
- * requested matches that of the session. If it doesn't, make it so.
- */
-CK_RV
-open_sess(CK_SLOT_ID slot_id, CK_FLAGS sess_flags, CK_SESSION_HANDLE_PTR sess)
-{
- CK_RV rv = CKR_OK;
-
- cryptodebug("inside open_sess");
-
- /* If the session is already open, check the session flags. */
- if (session_opened) {
- /*
- * If requesting R/W session and it is currently R/O,
- * need to close the session and reopen it R/W. The
- * other cases are considered acceptable:
- * sess_flags current state
- * ---------- -------------
- * ~CKF_RW_SESSION !session_writable
- * ~CKF_RW_SESSION session_writable
- * CKF_RW_SESSION session_writable
- */
- if ((sess_flags & CKF_RW_SESSION) && !session_writable)
- close_sess(*sess);
- else
- return (CKR_OK);
- }
-
- /* Make sure the PKCS#11 is already initialized. */
- if (!initialized)
- if ((rv = init_pk11()) != CKR_OK)
- return (rv);
-
- /* Create a session for subsequent operations. */
- cryptodebug("calling C_OpenSession()");
- if ((rv = C_OpenSession(slot_id, CKF_SERIAL_SESSION|sess_flags,
- NULL, NULL, sess)) != CKR_OK)
- return (rv);
- session_opened = B_TRUE;
- session_writable = (sess_flags & CKF_RW_SESSION) ? B_TRUE : B_FALSE;
- return (CKR_OK);
-}
-
-/*
* Close PKCS#11 session and reset state variables. Any logins are
* logged out.
*/
-void
+static void
close_sess(CK_SESSION_HANDLE sess)
{
- cryptodebug("inside close_sess");
if (sess == NULL) {
- cryptodebug("session handle is null");
return;
}
/* If session is already closed, nothing to do here. */
- session_writable = B_FALSE;
if (!session_opened)
return;
/* Make sure user is logged out of token. */
logout_token(sess);
- cryptodebug("calling C_CloseSession()");
(void) C_CloseSession(sess);
session_opened = B_FALSE;
}
/*
- * Log user into token in given slot. If this first login ever for this
- * token, the initial PIN is "changeme", C_Login() will succeed, but all
- * PKCS#11 calls following the C_Login() will fail with CKR_PIN_EXPIRED.
- */
-CK_RV
-login_token(CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin, CK_ULONG pinlen,
- CK_SESSION_HANDLE_PTR sess)
-{
- CK_RV rv = CKR_OK;
-
- cryptodebug("inside login_token");
-
- /* If already logged in, nothing to do here. */
- if (logged_in)
- return (CKR_OK);
-
- /* Make sure we have a session first, assume R/O is enough. */
- if (!session_opened)
- if ((rv = open_sess(slot_id, CKF_SERIAL_SESSION, sess)) !=
- CKR_OK)
- return (rv);
-
- /* Log the user into the token. */
- cryptodebug("calling C_Login()");
- if ((rv = C_Login(*sess, CKU_USER, pin, pinlen)) != CKR_OK) {
- cryptodebug("C_Login returns %s", pkcs11_strerror(rv));
- return (rv);
- }
-
- logged_in = B_TRUE;
- return (CKR_OK);
-}
-
-/*
* Log user out of token and reset status variable.
*/
-void
+static void
logout_token(CK_SESSION_HANDLE sess)
{
- cryptodebug("inside logout_token");
if (sess == NULL) {
- cryptodebug("session handle is null");
return;
}
@@ -242,49 +153,11 @@ logout_token(CK_SESSION_HANDLE sess)
if (!logged_in)
return;
- cryptodebug("calling C_Logout()");
(void) C_Logout(sess);
logged_in = B_FALSE;
}
/*
- * Shortcut function to get from an uninitialized state to user logged in.
- * If the library is already initialized, the session is already opened,
- * or the user is already logged in, those steps are skipped and the next
- * step is checked.
- */
-CK_RV
-quick_start(CK_SLOT_ID slot_id, CK_FLAGS sess_flags, CK_UTF8CHAR_PTR pin,
- CK_ULONG pinlen, CK_SESSION_HANDLE_PTR sess)
-{
- CK_RV rv = CKR_OK;
-
- cryptodebug("inside quick_start");
-
- /* Call open_sess() explicitly if R/W session is needed. */
- if (sess_flags & CKF_RW_SESSION)
- if ((rv = open_sess(slot_id, sess_flags, sess)) != CKR_OK)
- return (rv);
-
- if ((rv = login_token(slot_id, pin, pinlen, sess)) != CKR_OK)
- return (rv);
-
- return (CKR_OK);
-}
-
-/*
- * Shortcut function to go from any state to uninitialized PKCS#11 library.
- */
-void
-quick_finish(CK_SESSION_HANDLE sess)
-{
- cryptodebug("inside quick_finish");
-
- /* All the needed calls are done implicitly. */
- final_pk11(sess);
-}
-
-/*
* Gets PIN from user. Caller needs to free the returned PIN when done.
* If two prompts are given, the PIN is confirmed with second prompt.
* Note that getphassphrase() may return data in static memory area.
@@ -294,15 +167,20 @@ get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen)
{
char *save_phrase, *phrase1, *phrase2;
- cryptodebug("inside get_pin");
+
+#ifdef DEBUG
+ if (getenv("TOKENPIN") != NULL) {
+ *pin = (CK_UTF8CHAR_PTR)strdup(getenv("TOKENPIN"));
+ *pinlen = strlen((char *)(*pin));
+ return (CKR_OK);
+ }
+#endif /* DEBUG */
/* Prompt user for a PIN. */
if (prompt1 == NULL) {
- cryptodebug("no passphrase prompt given");
return (CKR_ARGUMENTS_BAD);
}
if ((phrase1 = getpassphrase(prompt1)) == NULL) {
- cryptodebug("getpassphrase() failed");
return (CKR_FUNCTION_FAILED);
}
@@ -313,12 +191,10 @@ get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen)
/* If second prompt given, PIN confirmation is requested. */
if (prompt2 != NULL) {
if ((phrase2 = getpassphrase(prompt2)) == NULL) {
- cryptodebug("getpassphrase() confirmation failed");
free(save_phrase);
return (CKR_FUNCTION_FAILED);
}
if (strcmp(save_phrase, phrase2) != 0) {
- cryptodebug("passphrases do not match");
free(save_phrase);
return (CKR_PIN_INCORRECT);
}
@@ -343,7 +219,13 @@ yesno(char *prompt, char *invalid, boolean_t dflt)
char *yes = gettext("yes");
char *no = gettext("no");
- cryptodebug("inside yesno");
+
+#ifdef DEBUG
+ /* If debugging or testing, return TRUE and avoid prompting */
+ if (getenv("TOKENPIN") != NULL) {
+ return (B_TRUE);
+ }
+#endif /* DEBUG */
if (prompt == NULL)
prompt = gettext("Enter (y)es or (n)o? ");
@@ -388,8 +270,6 @@ get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
CK_SLOT_ID_PTR tmp_list = NULL_PTR, tmp2_list = NULL_PTR;
int rv = CKR_OK;
- cryptodebug("inside get_token_slots");
-
if (!initialized)
if ((rv = init_pk11()) != CKR_OK)
return (rv);
@@ -402,12 +282,10 @@ get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
* Also select only those slots that have tokens in them,
* because this tool has no need to know about empty slots.
*/
- cryptodebug("calling C_GetSlotList() for slot count");
if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK)
return (rv);
if (tmp_count == 0) {
- cryptodebug("no slots with tokens found");
*slot_list = NULL_PTR;
*slot_count = 0;
return (CKR_OK);
@@ -420,7 +298,6 @@ get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
/* Then get the slot list itself. */
for (;;) {
- cryptodebug("calling C_GetSlotList()");
if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) {
*slot_list = tmp_list;
*slot_count = tmp_count;
@@ -433,7 +310,6 @@ get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
}
/* If the number of slots grew, try again. */
- cryptodebug("number of tokens present increased");
if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list,
tmp_count * sizeof (CK_SLOT_ID))) == NULL) {
free(tmp_list);
@@ -447,878 +323,683 @@ get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
}
/*
- * memcmp_pad_max() is a specialized version of memcmp() which
- * compares two pieces of data up to a maximum length. If the
- * the two data match up the maximum length, they are considered
- * matching. Trailing blanks do not cause the match to fail if
- * one of the data is shorted.
- *
- * Examples of matches:
- * "one" |
- * "one " |
- * ^maximum length
- *
- * "Number One | X" (X is beyond maximum length)
- * "Number One " |
- * ^maximum length
- *
- * Examples of mismatches:
- * " one"
- * "one"
- *
- * "Number One X|"
- * "Number One |"
- * ^maximum length
+ * Breaks out the getopt-style option string into a structure that can be
+ * traversed later for calls to getopt_av(). Option string is NOT altered,
+ * but the struct fields point to locations within option string.
*/
static int
-memcmp_pad_max(void *d1, uint_t d1_len, void *d2, uint_t d2_len, uint_t max_sz)
+populate_opts(char *optstring)
{
- uint_t len, extra_len;
+ int i;
+ av_opts *temp;
char *marker;
- /* No point in comparing anything beyond max_sz */
- if (d1_len > max_sz)
- d1_len = max_sz;
- if (d2_len > max_sz)
- d2_len = max_sz;
-
- /* Find shorter of the two data. */
- if (d1_len <= d2_len) {
- len = d1_len;
- extra_len = d2_len;
- marker = d2;
- } else { /* d1_len > d2_len */
- len = d2_len;
- extra_len = d1_len;
- marker = d1;
- }
+ if (optstring == NULL || *optstring == '\0')
+ return (0);
+
+ /*
+ * This tries to imitate getopt(3c) Each option must conform to:
+ * <short name char> [ ':' ] [ '(' <long name string> ')' ]
+ * If long name is missing, the short name is used for long name.
+ */
+ for (i = 0; *optstring != '\0'; i++) {
+ if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
+ realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) {
+ if (opts_av != NULL)
+ free(opts_av);
+ opts_av = NULL;
+ return (0);
+ } else {
+ opts_av = (av_opts *)temp;
+ }
- /* Have a match in the shortest length of data? */
- if (memcmp(d1, d2, len) != 0)
- /* CONSTCOND */
- return (!0);
+ (void) memset(&opts_av[i], 0, sizeof (av_opts));
+ marker = optstring; /* may need optstring later */
- /* If the rest of longer data is nulls or blanks, call it a match. */
- while (len < extra_len)
- if (!isspace(marker[len++]))
- /* CONSTCOND */
- return (!0);
- return (0);
+ opts_av[i].shortnm = *marker++; /* set short name */
+
+ if (*marker == ':') { /* check for opt arg */
+ marker++;
+ opts_av[i].has_arg = B_TRUE;
+ }
+
+ if (*marker == '(') { /* check and set long name */
+ marker++;
+ opts_av[i].longnm = marker;
+ opts_av[i].longnm_len = strcspn(marker, ")");
+ optstring = marker + opts_av[i].longnm_len + 1;
+ } else {
+ /* use short name option character */
+ opts_av[i].longnm = optstring;
+ opts_av[i].longnm_len = 1;
+ optstring = marker;
+ }
+ }
+
+ return (i);
}
/*
- * Locate a token slot whose token matches the label, manufacturer ID, and
- * serial number given. Token label must be specified, manufacturer ID and
- * serial number are optional. When the token is located, the PIN state
- * is also returned to determine if it still has the default PIN.
+ * getopt_av() is very similar to getopt(3c) in that the takes an option
+ * string, compares command line arguments for matches, and returns a single
+ * letter option when a match is found. However, getopt_av() differs from
+ * getopt(3c) by requiring that only longname options and values be found
+ * on the command line and all leading dashes are omitted. In other words,
+ * it tries to enforce only longname "option=value" arguments on the command
+ * line. Boolean options are not allowed either.
*/
-CK_RV
-find_token_slot(char *token_name, char *manuf_id, char *serial_no,
- CK_SLOT_ID *slot_id, CK_FLAGS *pin_state)
+int
+getopt_av(int argc, char * const *argv, const char *optstring)
{
- CK_SLOT_ID_PTR slot_list;
- CK_TOKEN_INFO token_info;
- CK_ULONG slot_count = 0;
- int rv = CKR_OK;
- int i;
- uint_t len, max_sz;
- boolean_t tok_match = B_FALSE,
- man_match = B_FALSE,
- ser_match = B_FALSE;
+ int i;
+ int len;
+ char *cur_option;
- cryptodebug("inside find_token_slot");
+ if (optind_av >= argc)
+ return (EOF);
- if (token_name == NULL)
- return (CKR_ARGUMENTS_BAD);
+ /* First time or when optstring changes from previous one */
+ if (_save_optstr != optstring) {
+ if (opts_av != NULL)
+ free(opts_av);
+ opts_av = NULL;
+ _save_optstr = optstring;
+ _save_numopts = populate_opts((char *)optstring);
+ }
- /* Get a list of all slots with tokens present. */
- if ((rv = get_token_slots(&slot_list, &slot_count)) != CKR_OK)
- return (rv);
+ for (i = 0; i < _save_numopts; i++) {
+ cur_option = argv[optind_av];
- /* If there are no such slots, the desired token won't be found. */
- if (slot_count == 0)
- return (CKR_TOKEN_NOT_PRESENT);
-
- /* Search the slot list for the token. */
- for (i = 0; i < slot_count; i++) {
- cryptodebug("calling C_GetTokenInfo()");
- if ((rv = C_GetTokenInfo(slot_list[i], &token_info)) !=
- CKR_OK) {
- cryptodebug("token in slot %d returns %s", i,
- pkcs11_strerror(rv));
- continue;
+ if (strcmp(cur_option, "--") == 0) {
+ optind_av++;
+ break;
}
- /* See if the token label matches. */
- len = strlen(token_name);
- max_sz = sizeof (token_info.label);
- if (memcmp_pad_max(&(token_info.label), max_sz, token_name, len,
- max_sz) == 0)
- tok_match = B_TRUE;
-
- /*
- * If manufacturer id was given, see if it actually matches.
- * If no manufacturer id was given, assume match is true.
- */
- if (manuf_id) {
- len = strlen(manuf_id);
- max_sz = sizeof ((char *)(token_info.manufacturerID));
- if (memcmp_pad_max(&(token_info.manufacturerID), max_sz,
- manuf_id, len, max_sz) == 0)
- man_match = B_TRUE;
- } else
- man_match = B_TRUE;
-
- /*
- * If serial number was given, see if it actually matches.
- * If no serial number was given, assume match is true.
- */
- if (serial_no) {
- len = strlen(serial_no);
- max_sz = sizeof ((char *)(token_info.serialNumber));
- if (memcmp_pad_max(&(token_info.serialNumber), max_sz,
- serial_no, len, max_sz) == 0)
- ser_match = B_TRUE;
- } else
- ser_match = B_TRUE;
-
- cryptodebug("slot %d:", i);
- cryptodebug("\tlabel = \"%.32s\"%s", token_info.label,
- tok_match ? " match" : "");
- cryptodebug("\tmanuf = \"%.32s\"%s", token_info.manufacturerID,
- man_match ? " match" : "");
- cryptodebug("\tserno = \"%.16s\"%s", token_info.serialNumber,
- ser_match ? " match" : "");
- cryptodebug("\tmodel = \"%.16s\"", token_info.model);
-
- cryptodebug("\tCKF_USER_PIN_INITIALIZED = %s",
- (token_info.flags & CKF_USER_PIN_INITIALIZED) ?
- "true" : "false");
- cryptodebug("\tCKF_USER_PIN_TO_BE_CHANGED = %s",
- (token_info.flags & CKF_USER_PIN_TO_BE_CHANGED) ?
- "true" : "false");
-
- if (tok_match && man_match && ser_match)
- break; /* found it! */
- }
+ if (cur_option[0] == '-' && strlen(cur_option) == 2) {
+ len = 1;
+ cur_option++; /* remove "-" */
+ } else {
+ len = strcspn(cur_option, "=");
+ }
- /* Scanned the whole list without finding the token. */
- if (i == slot_count) {
- cryptodebug("token not found");
- free(slot_list);
- return (CKR_TOKEN_NOT_PRESENT);
+ if (len == opts_av[i].longnm_len && strncmp(cur_option,
+ opts_av[i].longnm, opts_av[i].longnm_len) == 0) {
+ /* matched */
+ if (!opts_av[i].has_arg) {
+ optind_av++;
+ return (opts_av[i].shortnm);
+ }
+
+ /* needs optarg */
+ if (cur_option[len] == '=') {
+ optarg_av = &(cur_option[len+1]);
+ optind_av++;
+ return (opts_av[i].shortnm);
+ }
+
+ optarg_av = NULL;
+ optind_av++;
+ return ((int)'?');
+ }
}
- /* Return slot id where token was found and its PIN state. */
- cryptodebug("token found at slot %d", i);
- *slot_id = slot_list[i];
- *pin_state = (token_info.flags & CKF_USER_PIN_TO_BE_CHANGED);
- free(slot_list);
- return (CKR_OK);
+ return (EOF);
}
-/*
- * Returns pointer to either null-terminator or next unescaped colon. The
- * string to be extracted starts at the beginning and goes until one character
- * before this pointer. If NULL is returned, the string itself is NULL.
- */
-static char *
-find_unescaped_colon(char *str)
+KMF_KEYSTORE_TYPE
+KS2Int(char *keystore_str)
{
- char *end;
+ if (keystore_str == NULL)
+ return (0);
+ if (!strcasecmp(keystore_str, "pkcs11"))
+ return (KMF_KEYSTORE_PK11TOKEN);
+ else if (!strcasecmp(keystore_str, "nss"))
+ return (KMF_KEYSTORE_NSS);
+ else if (!strcasecmp(keystore_str, "file"))
+ return (KMF_KEYSTORE_OPENSSL);
+ else
+ return (0);
+}
- if (str == NULL)
- return (NULL);
- while ((end = strchr(str, ':')) != NULL) {
- if (end != str && *(end-1) != '\\')
- return (end);
- str = end + 1; /* could point to null-terminator */
+int
+Str2KeyType(char *algm, KMF_KEY_ALG *ktype, KMF_ALGORITHM_INDEX *sigAlg)
+{
+ if (algm == NULL) {
+ *sigAlg = KMF_ALGID_MD5WithRSA;
+ *ktype = KMF_RSA;
+ } else if (strcasecmp(algm, "DSA") == 0) {
+ *sigAlg = KMF_ALGID_SHA1WithDSA;
+ *ktype = KMF_DSA;
+ } else if (strcasecmp(algm, "RSA") == 0) {
+ *sigAlg = KMF_ALGID_MD5WithRSA;
+ *ktype = KMF_RSA;
+ } else {
+ return (-1);
}
- if (end == NULL)
- end = strchr(str, '\0');
- return (end);
+ return (0);
}
-/*
- * Compresses away any characters escaped with backslash from given string.
- * The string is altered in-place. Example, "ab\:\\e" becomes "ab:\e".
- */
-static void
-unescape_str(char *str)
+int
+Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype)
{
- boolean_t escaped = B_FALSE;
- char *mark;
-
- if (str == NULL)
- return;
+ if (algm == NULL)
+ *ktype = KMF_AES;
+ else if (strcasecmp(algm, "aes") == 0)
+ *ktype = KMF_AES;
+ else if (strcasecmp(algm, "arcfour") == 0)
+ *ktype = KMF_RC4;
+ else if (strcasecmp(algm, "des") == 0)
+ *ktype = KMF_DES;
+ else if (strcasecmp(algm, "3des") == 0)
+ *ktype = KMF_DES3;
+ else
+ return (-1);
- for (mark = str; *str != '\0'; str++) {
- if (*str != '\\' || escaped == B_TRUE) {
- *mark++ = *str;
- escaped = B_FALSE;
- } else {
- escaped = B_TRUE;
- }
- }
- *mark = '\0';
+ return (0);
}
-/*
- * Given a colon-separated token specifier, this functions splits it into
- * its label, manufacturer ID (if any), and serial number (if any). Literal
- * colons within the label/manuf/serial can be escaped with a backslash.
- * Fields can left blank and trailing colons can be omitted, however leading
- * colons are required as placeholders. For example, these are equivalent:
- * (a) "lbl", "lbl:", "lbl::" (b) "lbl:man", "lbl:man:"
- * but these are not:
- * (c) "man", ":man" (d) "ser", "::ser"
- * Furthermore, the token label is required always.
- *
- * The buffer containing the token specifier is altered by replacing the
- * colons to null-terminators, and pointers returned are pointers into this
- * string. No new memory is allocated.
- */
int
-parse_token_spec(char *token_spec, char **token_name, char **manuf_id,
- char **serial_no)
+Str2Lifetime(char *ltimestr, uint32_t *ltime)
{
- char *mark;
+ int num;
+ char timetok[6];
- if (token_spec == NULL || *token_spec == '\0') {
- cryptodebug("token specifier is empty");
- return (-1);
+ if (ltimestr == NULL || !strlen(ltimestr)) {
+ /* default to 1 year lifetime */
+ *ltime = SECSPERDAY * DAYSPERNYEAR;
+ return (0);
}
- *token_name = NULL;
- *manuf_id = NULL;
- *serial_no = NULL;
-
- /* Token label (required) */
- mark = find_unescaped_colon(token_spec);
- *token_name = token_spec;
- if (*mark != '\0')
- *mark++ = '\0'; /* mark points to next field, if any */
- unescape_str(*token_name);
+ (void) memset(timetok, 0, sizeof (timetok));
+ if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2)
+ return (-1);
- if (*(*token_name) == '\0') { /* token label is required */
- cryptodebug("no token label found");
+ if (!strcasecmp(timetok, "day") ||
+ !strcasecmp(timetok, "days")) {
+ *ltime = num * SECSPERDAY;
+ } else if (!strcasecmp(timetok, "hour") ||
+ !strcasecmp(timetok, "hours")) {
+ *ltime = num * SECSPERHOUR;
+ } else if (!strcasecmp(timetok, "year") ||
+ !strcasecmp(timetok, "years")) {
+ *ltime = num * SECSPERDAY * DAYSPERNYEAR;
+ } else {
+ *ltime = 0;
return (-1);
}
- if (*mark == '\0' || *(mark+1) == '\0') /* no more fields */
- return (0);
- token_spec = mark;
-
- /* Manufacturer identifier (optional) */
- mark = find_unescaped_colon(token_spec);
- *manuf_id = token_spec;
- if (*mark != '\0')
- *mark++ = '\0'; /* mark points to next field, if any */
- unescape_str(*manuf_id);
+ return (0);
+}
- if (*mark == '\0' || *(mark+1) == '\0') /* no more fields */
- return (0);
- token_spec = mark;
+int
+OT2Int(char *objclass)
+{
+ char *c = NULL;
+ int retval = 0;
- /* Serial number (optional) */
- mark = find_unescaped_colon(token_spec);
- *serial_no = token_spec;
- if (*mark != '\0')
- *mark++ = '\0'; /* null-terminate, just in case */
- unescape_str(*serial_no);
+ if (objclass == NULL)
+ return (-1);
- return (0);
+ c = strchr(objclass, ':');
+ if (c != NULL) {
+ if (!strcasecmp(c, ":private"))
+ retval = PK_PRIVATE_OBJ;
+ else if (!strcasecmp(c, ":public"))
+ retval = PK_PUBLIC_OBJ;
+ else if (!strcasecmp(c, ":both"))
+ retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ;
+ else /* unrecognized option */
+ return (-1);
+
+ *c = '\0';
+ }
+
+ if (!strcasecmp(objclass, "public")) {
+ if (retval)
+ return (-1);
+ return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ |
+ PK_PUBKEY_OBJ);
+ } else if (!strcasecmp(objclass, "private")) {
+ if (retval)
+ return (-1);
+ return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ);
+ } else if (!strcasecmp(objclass, "both")) {
+ if (retval)
+ return (-1);
+ return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ);
+ } else if (!strcasecmp(objclass, "cert")) {
+ return (retval | PK_CERT_OBJ);
+ } else if (!strcasecmp(objclass, "key")) {
+ if (retval == 0) /* return all keys */
+ return (retval | PK_KEY_OBJ);
+ else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ))
+ /* return all keys */
+ return (retval | PK_KEY_OBJ);
+ else if (retval & PK_PUBLIC_OBJ)
+ /* Only return public keys */
+ return (retval | PK_PUBKEY_OBJ);
+ else if (retval & PK_PRIVATE_OBJ)
+ /* Only return private keys */
+ return (retval | PK_PRIKEY_OBJ);
+ } else if (!strcasecmp(objclass, "crl")) {
+ if (retval)
+ return (-1);
+ return (retval | PK_CRL_OBJ);
+ }
+
+ if (retval == 0) /* No matches found */
+ retval = -1;
+ return (retval);
}
-/*
- * Constructs a fully qualified token name from its label, manufacturer ID
- * (if any), and its serial number (if any). Note that the given buf must
- * be big enough. Do NOT i18n/l10n.
- *
- * FULL_NAME_LEN is defined in common.h to be 91 because a fully qualified
- * token name adds up this way:
- * =32(label) + 32(manuf) + 16(serial) + 4("", ) + 4("", ) + 3("" and nul)
- */
-void
-full_token_name(char *token_name, char *manuf_id, char *serial_no, char *buf)
+KMF_ENCODE_FORMAT
+Str2Format(char *formstr)
{
- char *marker = buf;
- int n_written = 0;
- int space_left = FULL_NAME_LEN;
+ if (formstr == NULL || !strcasecmp(formstr, "der"))
+ return (KMF_FORMAT_ASN1);
+ if (!strcasecmp(formstr, "pem"))
+ return (KMF_FORMAT_PEM);
+ if (!strcasecmp(formstr, "pkcs12"))
+ return (KMF_FORMAT_PKCS12);
+
+ return (KMF_FORMAT_UNDEF);
+}
- if (!token_name)
- return;
- n_written = sprintf(buf, "\"%.32s\"", token_name);
- marker += n_written;
- space_left -= n_written;
+KMF_RETURN
+select_token(void *kmfhandle, char *token,
+ int readonly)
+{
+ KMF_RETURN rv = KMF_OK;
+ KMF_CONFIG_PARAMS config;
- n_written = sprintf(marker, ", \"%.32s\"", manuf_id ? manuf_id : "");
- marker += n_written;
- space_left -= n_written;
+ if (token == NULL)
+ return (KMF_ERR_BAD_PARAMETER);
- n_written = sprintf(marker, ", \"%.16s\"", serial_no ? serial_no : "");
- marker += n_written;
- space_left -= n_written;
+ (void) memset(&config, 0, sizeof (config));
+ config.kstype = KMF_KEYSTORE_PK11TOKEN;
+ config.pkcs11config.label = token;
+ config.pkcs11config.readonly = readonly;
- /* space_left should always be >= 1 */
+ rv = KMF_ConfigureKeystore(kmfhandle, &config);
+ if (rv == KMF_ERR_TOKEN_SELECTED)
+ rv = KMF_OK;
+ return (rv);
}
-/*
- * Find how many token objects with the given label.
- */
-CK_RV
-find_obj_count(CK_SESSION_HANDLE sess, int obj_type, CK_BYTE *label,
- CK_ULONG *count)
+
+KMF_RETURN
+configure_nss(void *kmfhandle, char *dir, char *prefix)
{
- CK_RV rv = CKR_OK;
- CK_ATTRIBUTE attrs[4] = {
- { CKA_TOKEN, &pk_true, sizeof (pk_true) },
- { 0, NULL, 0 },
- { 0, NULL, 0 },
- { 0, NULL, 0 }
- };
- CK_ULONG num_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE);
- CK_ULONG cur_attr = 1; /* CKA_TOKEN already set */
- CK_OBJECT_CLASS obj_class;
- CK_OBJECT_HANDLE tmp_obj;
- CK_ULONG obj_count = 0;
-
- cryptodebug("inside find_obj_count");
-
- if (!session_opened || sess == NULL) {
- cryptodebug("session handle is null");
- return (CKR_SESSION_HANDLE_INVALID);
- }
+ KMF_RETURN rv = KMF_OK;
+ KMF_CONFIG_PARAMS config;
- if (label) {
- cryptodebug("object label was specified");
- attrs[cur_attr].type = CKA_LABEL;
- attrs[cur_attr].pValue = label;
- attrs[cur_attr].ulValueLen = strlen((char *)label);
- cur_attr++;
- }
+ (void) memset(&config, 0, sizeof (config));
+ config.kstype = KMF_KEYSTORE_NSS;
+ config.nssconfig.configdir = dir;
+ config.nssconfig.certPrefix = prefix;
+ config.nssconfig.keyPrefix = prefix;
+ config.nssconfig.secModName = NULL;
- if ((obj_type & PK_PRIVATE_OBJ) && !(obj_type & PK_PUBLIC_OBJ)) {
- cryptodebug("only searching for private objects");
- attrs[cur_attr].type = CKA_PRIVATE;
- attrs[cur_attr].pValue = &pk_true;
- attrs[cur_attr].ulValueLen = sizeof (pk_true);
- cur_attr++;
- }
+ rv = KMF_ConfigureKeystore(kmfhandle, &config);
+ if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED)
+ rv = KMF_OK;
- /*
- * If "certs and all keys" is not specified, but at least either
- * "certs" or some "keys" is specified, then go into this block.
- * If all certs and keys were specified, there's no point in
- * putting that fact in the attribute template -- leave that open,
- * and all certs and keys will be matched automatically.
- * In other words, only if at least one of 0x10,0x20,0x40,0x80
- * bits is off, go into this code block.
- *
- * NOTE: For now, only one of cert or key types is allowed.
- * This needs to change in the future.
- */
- if ((obj_type & (PK_CERT_OBJ|PK_KEY_OBJ)) != (PK_CERT_OBJ|PK_KEY_OBJ) &&
- ((obj_type & PK_CERT_OBJ) || (obj_type & PK_KEY_OBJ))) {
- if (obj_type & PK_CERT_OBJ) {
- cryptodebug("only searching for certificates");
- obj_class = CKO_CERTIFICATE;
- } else if (obj_type & PK_PRIKEY_OBJ) {
- cryptodebug("only searching for private keys");
- obj_class = CKO_PRIVATE_KEY;
- } else if (obj_type & PK_PUBKEY_OBJ) {
- cryptodebug("only searching for public keys");
- obj_class = CKO_PUBLIC_KEY;
- } else if (obj_type & PK_SECKEY_OBJ) {
- cryptodebug("only searching for secret keys");
- obj_class = CKO_SECRET_KEY;
- }
+ return (rv);
+}
- attrs[cur_attr].type = CKA_CLASS;
- attrs[cur_attr].pValue = &obj_class;
- attrs[cur_attr].ulValueLen = sizeof (CK_OBJECT_CLASS);
- cur_attr++;
- }
+
+KMF_RETURN
+get_pk12_password(KMF_CREDENTIAL *cred)
+{
+ KMF_RETURN rv = KMF_OK;
+ char prompt[1024];
/*
- * This can't happen now. When finding objects is enhanced in the
- * future. this could lead to buffer overruns.
+ * Get the password to use for the PK12 encryption.
*/
- if (cur_attr > num_attrs)
- cryptodebug("internal error: attr template overrun");
+ (void) strlcpy(prompt,
+ gettext("Enter password to use for "
+ "accessing the PKCS12 file: "),
+ sizeof (prompt));
- cryptodebug("calling C_FindObjectsInit");
- if ((rv = C_FindObjectsInit(sess, attrs, cur_attr)) != CKR_OK)
- return (rv);
-
- /* Look for the object, checking if there are more than one. */
- cryptodebug("calling C_FindObjects");
- for (*count = 0; /* empty */; (*count)++) {
- if ((rv = C_FindObjects(sess, &tmp_obj, 1, &obj_count)) !=
- CKR_OK)
- break;
-
- /* No more found. */
- if (obj_count == 0)
- break;
+ if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
+ (ulong_t *)&cred->credlen) != CKR_OK) {
+ cred->cred = NULL;
+ cred->credlen = 0;
}
- cryptodebug("%d matching objects found", *count);
-
- cryptodebug("calling C_FindObjectsFinal");
- (void) C_FindObjectsFinal(sess);
return (rv);
}
-/*
- * Find the token object with the given label.
- */
-CK_RV
-find_objs(CK_SESSION_HANDLE sess, int obj_type, CK_BYTE *label,
- CK_OBJECT_HANDLE_PTR *obj, CK_ULONG *count)
-{
- CK_RV rv = CKR_OK;
- CK_ATTRIBUTE attrs[4] = {
- { CKA_TOKEN, &pk_true, sizeof (pk_true) },
- { 0, NULL, 0 },
- { 0, NULL, 0 },
- { 0, NULL, 0 }
- };
- CK_ULONG num_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE);
- CK_ULONG cur_attr = 1; /* CKA_TOKEN already set */
- CK_OBJECT_CLASS obj_class;
- CK_OBJECT_HANDLE tmp_obj;
- CK_ULONG obj_count = 0;
- int i;
-
- cryptodebug("inside find_obj");
-
- if ((rv = find_obj_count(sess, obj_type, label, count)) != CKR_OK)
- return (rv);
- if (*count == 0)
- return (CKR_OK);
+#define COUNTRY_PROMPT "Country Name (2 letter code) [US]:"
+#define STATE_PROMPT "State or Province Name (full name) [Some-State]:"
+#define LOCALITY_PROMPT "Locality Name (eg, city) []:"
+#define ORG_PROMPT "Organization Name (eg, company) []:"
+#define UNIT_PROMPT "Organizational Unit Name (eg, section) []:"
+#define NAME_PROMPT "Common Name (eg, YOUR name) []:"
+#define EMAIL_PROMPT "Email Address []:"
- if ((*obj = (CK_OBJECT_HANDLE_PTR) malloc((*count) *
- sizeof (CK_OBJECT_HANDLE))) == NULL) {
- cryptodebug("no memory for found object");
- return (CKR_HOST_MEMORY);
- }
+#define COUNTRY_DEFAULT "US"
+#define STATE_DEFAULT "Some-State"
+#define INVALID_INPUT "Invalid input; please re-enter ..."
- if (label) {
- cryptodebug("object label was specified");
- attrs[cur_attr].type = CKA_LABEL;
- attrs[cur_attr].pValue = label;
- attrs[cur_attr].ulValueLen = strlen((char *)label);
- cur_attr++;
- }
+#define SUBNAMESIZ 1024
+#define RDN_MIN 1
+#define RDN_MAX 64
+#define COUNTRYNAME_MIN 2
+#define COUNTRYNAME_MAX 2
- if ((obj_type & PK_PRIVATE_OBJ) && !(obj_type & PK_PUBLIC_OBJ)) {
- cryptodebug("only searching for private objects");
- attrs[cur_attr].type = CKA_PRIVATE;
- attrs[cur_attr].pValue = &pk_true;
- attrs[cur_attr].ulValueLen = sizeof (pk_true);
- cur_attr++;
- }
+static char *
+get_input_string(char *prompt, char *default_str, int min_len, int max_len)
+{
+ char buf[1024];
+ char *response = NULL;
+ char *ret = NULL;
+ int len;
- /*
- * If "certs and all keys" is not specified, but at least either
- * "certs" or some "keys" is specified, then go into this block.
- * If all certs and keys were specified, there's no point in
- * putting that fact in the attribute template -- leave that open,
- * and all certs and keys will be matched automatically.
- * In other words, only if at least one of 0x10,0x20,0x40,0x80
- * bits is off, go into this code block.
- *
- * NOTE: For now, only one of cert or key types is allowed.
- * This needs to change in the future.
- */
- if ((obj_type & (PK_CERT_OBJ|PK_KEY_OBJ)) != (PK_CERT_OBJ|PK_KEY_OBJ) &&
- ((obj_type & PK_CERT_OBJ) || (obj_type & PK_KEY_OBJ))) {
- if (obj_type & PK_CERT_OBJ) {
- cryptodebug("only searching for certificates");
- obj_class = CKO_CERTIFICATE;
- } else if (obj_type & PK_PRIKEY_OBJ) {
- cryptodebug("only searching for private keys");
- obj_class = CKO_PRIVATE_KEY;
- } else if (obj_type & PK_PUBKEY_OBJ) {
- cryptodebug("only searching for public keys");
- obj_class = CKO_PUBLIC_KEY;
- } else if (obj_type & PK_SECKEY_OBJ) {
- cryptodebug("only searching for secret keys");
- obj_class = CKO_SECRET_KEY;
+ for (;;) {
+ (void) printf("\t%s", prompt);
+ (void) fflush(stdout);
+
+ response = fgets(buf, sizeof (buf), stdin);
+ if (response == NULL) {
+ if (default_str != NULL) {
+ ret = strdup(default_str);
+ }
+ break;
+ }
+
+ /* Skip any leading white space. */
+ while (isspace(*response))
+ response++;
+ if (*response == '\0') {
+ if (default_str != NULL) {
+ ret = strdup(default_str);
+ }
+ break;
+ }
+
+ len = strlen(response);
+ response[len-1] = '\0'; /* get rid of "LF" */
+ len--;
+ if (len >= min_len && len <= max_len) {
+ ret = strdup(response);
+ break;
}
- attrs[cur_attr].type = CKA_CLASS;
- attrs[cur_attr].pValue = &obj_class;
- attrs[cur_attr].ulValueLen = sizeof (CK_OBJECT_CLASS);
- cur_attr++;
+ (void) printf("%s\n", INVALID_INPUT);
+
}
- /*
- * This can't happen now. When finding objects is enhanced in the
- * future. this could lead to buffer overruns.
- */
- if (cur_attr > num_attrs)
- cryptodebug("internal error: attr template overrun");
+ return (ret);
+}
- cryptodebug("calling C_FindObjectsInit");
- if ((rv = C_FindObjectsInit(sess, attrs, cur_attr)) != CKR_OK) {
- free(*obj);
- return (rv);
+int
+get_subname(char **result)
+{
+ char *country = NULL;
+ char *state = NULL;
+ char *locality = NULL;
+ char *org = NULL;
+ char *unit = NULL;
+ char *name = NULL;
+ char *email = NULL;
+ char *subname = NULL;
+
+ (void) printf("Entering following fields for subject (a DN) ...\n");
+ country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT,
+ COUNTRYNAME_MIN, COUNTRYNAME_MAX);
+ if (country == NULL)
+ return (-1);
+
+ state = get_input_string(STATE_PROMPT, STATE_DEFAULT,
+ RDN_MIN, RDN_MAX);
+ if (state == NULL) {
+ goto out;
}
- /*
- * Find all the matching objects. The loop goes 1 more beyond
- * the number of objects found to determine if any new objects
- * were created since the time the object count was done.
- */
- cryptodebug("calling C_FindObjects");
- for (i = 0; i < (*count) + 1; i++) {
- if ((rv = C_FindObjects(sess, &tmp_obj, 1, &obj_count)) !=
- CKR_OK)
- break;
+ locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX);
+ org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX);
+ unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX);
+ name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX);
+ email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX);
- /* No more found. */
- if (obj_count == 0)
- break;
+ /* Now create a subject name from the input strings */
+ if ((subname = malloc(SUBNAMESIZ)) == NULL)
+ goto out;
+
+ (void) memset(subname, 0, SUBNAMESIZ);
+ (void) strlcpy(subname, "C=", SUBNAMESIZ);
+ (void) strlcat(subname, country, SUBNAMESIZ);
+ (void) strlcat(subname, ", ", SUBNAMESIZ);
+ (void) strlcat(subname, "ST=", SUBNAMESIZ);
+ (void) strlcat(subname, state, SUBNAMESIZ);
- /*
- * Save the object in the list being created, as long as
- * we don't overrun the size of the list.
- */
- if (i < *count)
- (*obj)[i] = tmp_obj;
- else
- cryptodebug("number of objects changed since last count");
+ if (locality) {
+ (void) strlcat(subname, ", ", SUBNAMESIZ);
+ (void) strlcat(subname, "L=", SUBNAMESIZ);
+ (void) strlcat(subname, locality, SUBNAMESIZ);
}
- if (rv != CKR_OK) {
- free(*obj);
- } else {
- /*
- * There are three cases to handle: (1) fewer objects were
- * found than originally counted => change *count to the
- * smaller number; (2) the number of objects found matches
- * the number originally counted => do nothing; (3) more
- * objects found than originally counted => list passed
- * in is too small to contain the extra object(s), flag
- * that in the debug output but don't change number of
- * objects returned. The caller can double-check by
- * calling find_obj_count() after this function to make
- * sure the numbers match, if desired.
- */
- /* Case 1: Fewer objects. */
- if (i < *count) {
- cryptodebug("%d objects found, expected %d", i, *count);
- *count = i;
- /* Case 3: More objects. */
- } else if (i > *count) {
- cryptodebug("at least %d objects found, expected %d",
- i, *count);
- }
- /*
- * Case 2: Same number of objects.
- *
- * else if (i == *count)
- * ;
- */
+ if (org) {
+ (void) strlcat(subname, ", ", SUBNAMESIZ);
+ (void) strlcat(subname, "O=", SUBNAMESIZ);
+ (void) strlcat(subname, org, SUBNAMESIZ);
}
- cryptodebug("calling C_FindObjectsFinal");
- (void) C_FindObjectsFinal(sess);
- return (rv);
-}
+ if (unit) {
+ (void) strlcat(subname, ", ", SUBNAMESIZ);
+ (void) strlcat(subname, "OU=", SUBNAMESIZ);
+ (void) strlcat(subname, unit, SUBNAMESIZ);
+ }
-char *
-class_str(CK_OBJECT_CLASS class)
-{
- switch (class) {
- case CKO_DATA: return (gettext("data"));
- case CKO_CERTIFICATE: return (gettext("certificate"));
- case CKO_PUBLIC_KEY: return (gettext("public key"));
- case CKO_PRIVATE_KEY: return (gettext("private key"));
- case CKO_SECRET_KEY: return (gettext("secret key"));
- case CKO_DOMAIN_PARAMETERS: return (gettext("domain parameter"));
- default: return (gettext("unknown object"));
+ if (name) {
+ (void) strlcat(subname, ", ", SUBNAMESIZ);
+ (void) strlcat(subname, "CN=", SUBNAMESIZ);
+ (void) strlcat(subname, name, SUBNAMESIZ);
}
-}
-char *
-keytype_str(CK_KEY_TYPE keytype)
-{
- switch (keytype) {
- case CKK_RSA: return (gettext("RSA"));
- case CKK_DSA: return (gettext("DSA"));
- case CKK_DH: return (gettext("Diffie-Hellman"));
- case CKK_X9_42_DH: return (gettext("X9.42 Diffie-Hellman"));
- case CKK_GENERIC_SECRET: return (gettext("generic"));
- case CKK_RC2: return (gettext("RC2"));
- case CKK_RC4: return (gettext("RC4"));
- case CKK_DES: return (gettext("DES"));
- case CKK_DES2: return (gettext("Double-DES"));
- case CKK_DES3: return (gettext("Triple-DES"));
- case CKK_RC5: return (gettext("RC5"));
- case CKK_AES: return (gettext("AES"));
- default: return (gettext("typeless"));
+ if (email) {
+ (void) strlcat(subname, ", ", SUBNAMESIZ);
+ (void) strlcat(subname, "E=", SUBNAMESIZ);
+ (void) strlcat(subname, email, SUBNAMESIZ);
}
-}
-char *
-attr_str(CK_ATTRIBUTE_TYPE attrtype)
-{
- switch (attrtype) {
- case CKA_PRIVATE: return (gettext("private"));
- case CKA_LOCAL: return (gettext("local"));
- case CKA_SENSITIVE: return (gettext("sensitive"));
- case CKA_EXTRACTABLE: return (gettext("extractable"));
- case CKA_ENCRYPT: return (gettext("encrypt"));
- case CKA_DECRYPT: return (gettext("decrypt"));
- case CKA_WRAP: return (gettext("wrap"));
- case CKA_UNWRAP: return (gettext("unwrap"));
- case CKA_SIGN: return (gettext("sign"));
- case CKA_SIGN_RECOVER: return (gettext("sign-recover"));
- case CKA_VERIFY: return (gettext("verify"));
- case CKA_VERIFY_RECOVER: return (gettext("verify-recover"));
- case CKA_DERIVE: return (gettext("derive"));
- case CKA_ALWAYS_SENSITIVE: return (gettext("always sensitive"));
- case CKA_NEVER_EXTRACTABLE: return (gettext("never extractable"));
- default: return (gettext("unknown capability"));
+out:
+ if (country)
+ free(country);
+ if (state)
+ free(state);
+ if (locality)
+ free(locality);
+ if (org)
+ free(org);
+ if (unit)
+ free(unit);
+ if (name)
+ free(name);
+ if (email)
+ free(email);
+
+ if (subname == NULL)
+ return (-1);
+ else {
+ *result = subname;
+ return (0);
}
}
/*
- * Convert a byte string into a string of octets formatted like this:
- * oo oo oo oo oo ... oo
- * where each "oo" is an octet is space separated and in the form:
- * [0-f][0-f] if the octet is a non-printable character
- * <space><char> if the octet is a printable character
- *
- * Note: octets_sz must be 3 * str_sz + 1, or at least as long as "blank"
+ * Parse a string of KeyUsage values and convert
+ * them to the correct KU Bits.
+ * The field may be marked "critical" by prepending
+ * "critical:" to the list.
+ * EX: critical:digitialSignature,keyEncipherment
*/
-void
-octetify(CK_BYTE *str, CK_ULONG str_sz, char *octets, int octets_sz,
- boolean_t stop_on_nul, boolean_t do_ascii, int limit, char *indent,
- char *blank)
+KMF_RETURN
+verify_keyusage(char *kustr, uint16_t *kubits, int *critical)
{
- char *marker;
- int nc;
- int newline;
- int indent_len;
- boolean_t first = B_TRUE;
-
- cryptodebug("inside octetify");
-
- cryptodebug(stop_on_nul ? "stopping on first nul found" :
- "continuing to full length of buffer");
- cryptodebug(do_ascii ? "using ascii chars where printable" :
- "using only hex octets");
- cryptodebug("every %d characters indent with \"%s\"\n ", limit, indent);
- cryptodebug("return \"%s\" if buffer is null or empty", blank);
-
- /* If string is empty, write as much of the blank string and leave. */
- if (str_sz == 0) {
- (void) snprintf(octets, octets_sz, "%s", blank);
- return;
+ KMF_RETURN ret = KMF_OK;
+ uint16_t kuval;
+ char *k;
+
+ *kubits = 0;
+ if (kustr == NULL || !strlen(kustr))
+ return (KMF_ERR_BAD_PARAMETER);
+
+ /* Check to see if this is critical */
+ if (!strncasecmp(kustr, "critical:", strlen("critical:"))) {
+ *critical = TRUE;
+ kustr += strlen("critical:");
+ } else {
+ *critical = FALSE;
}
- /* If only limit or indent is set, pick default for the other. */
- if (limit > 0 && indent == NULL)
- indent = "\n";
- if (indent != NULL && limit == 0)
- limit = 60;
- indent_len = strlen(indent);
-
- for (marker = octets, newline = 0, first = B_TRUE;
- (stop_on_nul && *str != '\0') ||
- (!stop_on_nul && str_sz > 0 && octets_sz > 0);
- str++, str_sz--, marker += nc, octets_sz -= nc) {
- if (!first) {
- if (limit > 0 && ((marker - octets) / limit) >
- newline) {
- nc = snprintf(marker, indent_len, "%s", indent);
- newline++;
- continue;
- }
- nc = sprintf(marker,
- ((do_ascii && isprint(*str) && !isspace(*str)) ?
- "%s%c" : "%s%02x"), (do_ascii ? " " : ":"), *str);
- } else {
- nc = sprintf(marker,
- ((do_ascii && isprint(*str) && !isspace(*str)) ?
- "%c" : "%02x"), *str);
- first = B_FALSE;
+ k = strtok(kustr, ",");
+ while (k != NULL) {
+ kuval = KMF_StringToKeyUsage(k);
+ if (kuval == 0) {
+ *kubits = 0;
+ return (KMF_ERR_BAD_PARAMETER);
}
+ *kubits |= kuval;
+ k = strtok(NULL, ",");
}
- *marker = '\0';
-}
-/*
- * Copies a biginteger_t to a template attribute.
- * Should be a macro instead of a function.
- */
-void
-copy_bigint_to_attr(biginteger_t big, CK_ATTRIBUTE_PTR attr)
-{
- attr->pValue = big.big_value;
- attr->ulValueLen = big.big_value_len;
+ return (ret);
}
/*
- * Copies a string and its length to a template attribute.
- * Should be a macro instead of a function.
+ * Verify the alternate subject label is real or invalid.
+ *
+ * The field may be marked "critical" by prepending
+ * "critical:" to the list.
+ * EX: "critical:IP=1.2.3.4"
*/
-void
-copy_string_to_attr(CK_BYTE *buf, CK_ULONG buflen, CK_ATTRIBUTE_PTR attr)
+KMF_RETURN
+verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical)
{
- attr->pValue = buf;
- attr->ulValueLen = buflen;
-}
+ char *p;
+ KMF_RETURN rv = KMF_OK;
-/*
- * Copies a template attribute to a biginteger_t.
- * Should be a macro instead of a function.
- */
-void
-copy_attr_to_bigint(CK_ATTRIBUTE_PTR attr, biginteger_t *big)
-{
- big->big_value = attr->pValue;
- big->big_value_len = attr->ulValueLen;
-}
+ /* Check to see if this is critical */
+ if (!strncasecmp(arg, "critical:", strlen("critical:"))) {
+ *critical = TRUE;
+ arg += strlen("critical:");
+ } else {
+ *critical = FALSE;
+ }
-/*
- * Copies a template attribute to a string and its length.
- * Should be a macro instead of a function.
- */
-void
-copy_attr_to_string(CK_ATTRIBUTE_PTR attr, CK_BYTE **buf, CK_ULONG *buflen)
-{
- *buf = attr->pValue;
- *buflen = attr->ulValueLen;
-}
+ /* Make sure there is an "=" sign */
+ p = strchr(arg, '=');
+ if (p == NULL)
+ return (KMF_ERR_BAD_PARAMETER);
-/*
- * Copies a template attribute to a date and its length.
- * Should be a macro instead of a function.
- */
-void
-copy_attr_to_date(CK_ATTRIBUTE_PTR attr, CK_DATE **buf, CK_ULONG *buflen)
-{
- *buf = (CK_DATE *)attr->pValue;
- *buflen = attr->ulValueLen;
+ p[0] = '\0';
+
+ if (strcmp(arg, "IP") == 0)
+ *type = GENNAME_IPADDRESS;
+ else if (strcmp(arg, "DNS") == 0)
+ *type = GENNAME_DNSNAME;
+ else if (strcmp(arg, "EMAIL") == 0)
+ *type = GENNAME_RFC822NAME;
+ else if (strcmp(arg, "URI") == 0)
+ *type = GENNAME_URI;
+ else if (strcmp(arg, "DN") == 0)
+ *type = GENNAME_DIRECTORYNAME;
+ else if (strcmp(arg, "RID") == 0)
+ *type = GENNAME_REGISTEREDID;
+ else
+ rv = KMF_ERR_BAD_PARAMETER;
+
+ p[0] = '=';
+
+ return (rv);
}
-/*
- * Breaks out the getopt-style option string into a structure that can be
- * traversed later for calls to getopt_av(). Option string is NOT altered,
- * but the struct fields point to locations within option string.
- */
-static int
-populate_opts(char *optstring)
+int
+get_token_password(KMF_KEYSTORE_TYPE kstype,
+ char *token_spec, KMF_CREDENTIAL *cred)
{
- int i;
- av_opts *temp;
- char *marker;
-
- if (optstring == NULL || *optstring == '\0')
- return (0);
+ char prompt[1024];
+ char *p = NULL;
+ if (kstype == KMF_KEYSTORE_PK11TOKEN) {
+ p = strchr(token_spec, ':');
+ if (p != NULL)
+ *p = 0;
+ }
/*
- * This tries to imitate getopt(3c) Each option must conform to:
- * <short name char> [ ':' ] [ '(' <long name string> ')' ]
- * If long name is missing, the short name is used for long name.
+ * Login to the token first.
*/
- for (i = 0; *optstring != '\0'; i++) {
- if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
- realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) {
- free(opts_av);
- opts_av = NULL;
- return (0);
- } else
- opts_av = (av_opts *)temp;
-
- marker = optstring; /* may need optstring later */
-
- opts_av[i].shortnm = *marker++; /* set short name */
-
- if (*marker == ':') { /* check for opt arg */
- marker++;
- opts_av[i].has_arg = B_TRUE;
- }
+ (void) snprintf(prompt, sizeof (prompt),
+ gettext(DEFAULT_TOKEN_PROMPT),
+ token_spec);
- if (*marker == '(') { /* check and set long name */
- marker++;
- opts_av[i].longnm = marker;
- opts_av[i].longnm_len = strcspn(marker, ")");
- optstring = marker + opts_av[i].longnm_len + 1;
- } else {
- /* use short name option character */
- opts_av[i].longnm = optstring;
- opts_av[i].longnm_len = 1;
- optstring = marker;
- }
+ if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
+ (ulong_t *)&cred->credlen) != CKR_OK) {
+ cred->cred = NULL;
+ cred->credlen = 0;
}
- return (i);
+ if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL)
+ *p = ':';
+ return (KMF_OK);
}
-/*
- * getopt_av() is very similar to getopt(3c) in that the takes an option
- * string, compares command line arguments for matches, and returns a single
- * letter option when a match is found. However, getopt_av() differs from
- * getopt(3c) by requiring that only longname options and values be found
- * on the command line and all leading dashes are omitted. In other words,
- * it tries to enforce only longname "option=value" arguments on the command
- * line. Boolean options are not allowed either.
- */
-int
-getopt_av(int argc, char * const *argv, const char *optstring)
+KMF_RETURN
+verify_file(char *filename)
{
- int i;
- int len;
+ KMF_RETURN ret = KMF_OK;
+ int fd;
- if (optind_av >= argc)
- return (EOF);
+ /*
+ * Attempt to open with the EXCL flag so that if
+ * it already exists, the open will fail. It will
+ * also fail if the file cannot be created due to
+ * permissions on the parent directory, or if the
+ * parent directory itself does not exist.
+ */
+ fd = open(filename, O_CREAT | O_EXCL, 0600);
+ if (fd == -1)
+ return (KMF_ERR_OPEN_FILE);
- /* First time or when optstring changes from previous one */
- if (_save_optstr != optstring) {
- if (opts_av != NULL)
- free(opts_av);
- opts_av = NULL;
- _save_optstr = optstring;
- _save_numopts = populate_opts((char *)optstring);
- }
+ /* If we were able to create it, delete it. */
+ (void) close(fd);
+ (void) unlink(filename);
- for (i = 0; i < _save_numopts; i++) {
- if (strcmp(argv[optind_av], "--") == 0) {
- optind_av++;
- break;
- }
+ return (ret);
+}
- len = strcspn(argv[optind_av], "=");
+void
+display_error(void *handle, KMF_RETURN errcode, char *prefix)
+{
+ KMF_RETURN rv1, rv2;
+ char *plugin_errmsg = NULL;
+ char *kmf_errmsg = NULL;
- if (len == opts_av[i].longnm_len && strncmp(argv[optind_av],
- opts_av[i].longnm, opts_av[i].longnm_len) == 0) {
- /* matched */
- if (!opts_av[i].has_arg) {
- optind_av++;
- return (opts_av[i].shortnm);
- }
+ rv1 = KMF_GetPluginErrorString(handle, &plugin_errmsg);
+ rv2 = KMF_GetKMFErrorString(errcode, &kmf_errmsg);
- /* needs optarg */
- if (argv[optind_av][len] == '=') {
- optarg_av = &(argv[optind_av][len+1]);
- optind_av++;
- return (opts_av[i].shortnm);
- }
+ cryptoerror(LOG_STDERR, "%s:", prefix);
+ if (rv1 == KMF_OK && plugin_errmsg) {
+ cryptoerror(LOG_STDERR,
+ gettext("keystore error: %s"),
+ plugin_errmsg);
+ KMF_FreeString(plugin_errmsg);
+ }
- optarg_av = NULL;
- optind_av++;
- return ((int)'?');
- }
+ if (rv2 == KMF_OK && kmf_errmsg) {
+ cryptoerror(LOG_STDERR,
+ gettext("libkmf error: %s"),
+ kmf_errmsg);
+ KMF_FreeString(kmf_errmsg);
}
- return (EOF);
+ if (rv1 != KMF_OK && rv2 != KMF_OK)
+ cryptoerror(LOG_STDERR, gettext("<unknown error>\n"));
+
}
diff --git a/usr/src/cmd/cmd-crypto/pktool/common.h b/usr/src/cmd/cmd-crypto/pktool/common.h
index 30e2890b4b..e15cee3282 100644
--- a/usr/src/cmd/cmd-crypto/pktool/common.h
+++ b/usr/src/cmd/cmd-crypto/pktool/common.h
@@ -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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -39,14 +38,14 @@ extern "C" {
#endif
#include <cryptoutil.h>
-#include <biginteger.h>
/* I18N helpers. */
#include <libintl.h>
#include <locale.h>
+#include <errno.h>
+#include <kmfapi.h>
/* Defines used throughout */
-#define FULL_NAME_LEN 91 /* See full_token_name() for this number. */
/* Error codes */
#define PK_ERR_NONE 0
@@ -55,6 +54,7 @@ extern "C" {
#define PK_ERR_PK11 3
#define PK_ERR_SYSTEM 4
#define PK_ERR_OPENSSL 5
+#define PK_ERR_NSS 6
/* Types of objects for searches. */
#define PK_PRIVATE_OBJ 0x0001
@@ -62,11 +62,18 @@ extern "C" {
#define PK_CERT_OBJ 0x0010
#define PK_PRIKEY_OBJ 0x0020
#define PK_PUBKEY_OBJ 0x0040
-#define PK_SECKEY_OBJ 0x0080
+#define PK_SYMKEY_OBJ 0x0080
+#define PK_CRL_OBJ 0x0100
-#define PK_KEY_OBJ (PK_PRIKEY_OBJ|PK_PUBKEY_OBJ|PK_SECKEY_OBJ)
-#define PK_ALL_OBJ (PK_PRIVATE_OBJ|PK_PUBLIC_OBJ|\
- PK_CERT_OBJ|PK_KEY_OBJ)
+#define PK_KEY_OBJ (PK_PRIKEY_OBJ | PK_PUBKEY_OBJ | PK_SYMKEY_OBJ)
+#define PK_ALL_OBJ (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ |\
+ PK_CERT_OBJ| PK_CRL_OBJ | PK_KEY_OBJ)
+
+#define PK_DEFAULT_KEYTYPE "rsa"
+#define PK_DEFAULT_KEYLENGTH 1024
+#define PK_DEFAULT_DIRECTORY "."
+#define PK_DEFAULT_SERIALNUM 1
+#define PK_DEFAULT_PK11TOKEN SOFT_TOKEN_LABEL
/* Constants for attribute templates. */
extern CK_BBOOL pk_false;
@@ -77,18 +84,12 @@ extern CK_BBOOL pk_true;
extern CK_RV init_pk11(void);
extern void final_pk11(CK_SESSION_HANDLE sess);
-extern CK_RV open_sess(CK_SLOT_ID slot_id, CK_FLAGS sess_flags,
- CK_SESSION_HANDLE_PTR sess);
-extern void close_sess(CK_SESSION_HANDLE sess);
-
extern CK_RV login_token(CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin,
CK_ULONG pinlen, CK_SESSION_HANDLE_PTR sess);
-extern void logout_token(CK_SESSION_HANDLE sess);
extern CK_RV quick_start(CK_SLOT_ID slot_id, CK_FLAGS sess_flags,
CK_UTF8CHAR_PTR pin, CK_ULONG pinlen,
CK_SESSION_HANDLE_PTR sess);
-extern void quick_finish(CK_SESSION_HANDLE sess);
extern CK_RV get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin,
CK_ULONG *pinlen);
@@ -96,40 +97,35 @@ extern boolean_t yesno(char *prompt, char *invalid, boolean_t dflt);
extern CK_RV get_token_slots(CK_SLOT_ID_PTR *slot_list,
CK_ULONG *slot_count);
-extern CK_RV find_token_slot(char *token_name, char *manuf_id,
- char *serial_no, CK_SLOT_ID *slot_id, CK_FLAGS *pin_state);
-
-extern CK_RV find_obj_count(CK_SESSION_HANDLE sess, int obj_type,
- CK_BYTE *label, CK_ULONG *count);
-extern CK_RV find_objs(CK_SESSION_HANDLE sess, int obj_type,
- CK_BYTE *label, CK_OBJECT_HANDLE_PTR *obj, CK_ULONG *count);
-
-extern int parse_token_spec(char *spec, char **label, char **manuf,
- char **buf);
-extern void full_token_name(char *token, char *manuf, char *serial,
- char *buf);
-
-extern char *class_str(CK_OBJECT_CLASS class);
-extern char *keytype_str(CK_KEY_TYPE keytype);
-extern char *attr_str(CK_ATTRIBUTE_TYPE attrtype);
-
-extern void octetify(CK_BYTE *str, CK_ULONG str_sz, char *oct, int oct_sz,
- boolean_t stop_on_nul, boolean_t do_ascii, int limit,
- char *indent, char *blank);
-
-extern void copy_bigint_to_attr(biginteger_t big, CK_ATTRIBUTE_PTR attr);
-extern void copy_string_to_attr(CK_BYTE *buf, CK_ULONG buflen,
- CK_ATTRIBUTE_PTR attr);
-extern void copy_attr_to_bigint(CK_ATTRIBUTE_PTR attr, biginteger_t *big);
-extern void copy_attr_to_string(CK_ATTRIBUTE_PTR attr, CK_BYTE **buf,
- CK_ULONG *buflen);
-extern void copy_attr_to_date(CK_ATTRIBUTE_PTR attr, CK_DATE **buf,
- CK_ULONG *buflen);
+
+extern int get_subname(char **);
extern int getopt_av(int argc, char * const argv[], const char *optstring);
extern char *optarg_av;
extern int optind_av;
+int OT2Int(char *);
+int PK2Int(char *);
+KMF_KEYSTORE_TYPE KS2Int(char *);
+int Str2KeyType(char *, KMF_KEY_ALG *, KMF_ALGORITHM_INDEX *);
+int Str2SymKeyType(char *, KMF_KEY_ALG *);
+int Str2Lifetime(char *, uint32_t *);
+KMF_RETURN select_token(void *, char *, int);
+KMF_RETURN configure_nss(void *, char *, char *);
+
+KMF_ENCODE_FORMAT Str2Format(char *);
+KMF_RETURN get_pk12_password(KMF_CREDENTIAL *);
+KMF_RETURN hexstring2bytes(uchar_t *, uchar_t **, size_t *);
+KMF_RETURN verify_altname(char *arg, KMF_GENERALNAMECHOICES *, int *);
+KMF_RETURN verify_keyusage(char *arg, uint16_t *, int *);
+KMF_RETURN verify_file(char *);
+int get_token_password(KMF_KEYSTORE_TYPE, char *, KMF_CREDENTIAL *);
+void display_error(void *, KMF_RETURN, char *);
+#define DEFAULT_NSS_TOKEN "internal"
+#define DEFAULT_TOKEN_PROMPT "Enter pin for %s: "
+
+#define EMPTYSTRING(s) (s == NULL || !strlen((char *)s))
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/cmd/cmd-crypto/pktool/delete.c b/usr/src/cmd/cmd-crypto/pktool/delete.c
index ea550974c5..57d484cbe2 100644
--- a/usr/src/cmd/cmd-crypto/pktool/delete.c
+++ b/usr/src/cmd/cmd-crypto/pktool/delete.c
@@ -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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -37,6 +36,382 @@
#include <cryptoutil.h>
#include <security/cryptoki.h>
#include "common.h"
+#include <kmfapi.h>
+
+static KMF_RETURN
+pk_destroy_keys(void *handle, KMF_KEY_HANDLE *keys,
+ KMF_FINDKEY_PARAMS *fkparams, uint32_t numkeys)
+{
+ int i;
+ KMF_RETURN rv = KMF_OK;
+ KMF_DELETEKEY_PARAMS dkparams;
+
+ (void) memset(&dkparams, 0, sizeof (dkparams));
+ dkparams.kstype = fkparams->kstype;
+
+ switch (fkparams->kstype) {
+ case KMF_KEYSTORE_NSS:
+ dkparams.nssparms = fkparams->nssparms;
+ dkparams.cred = fkparams->cred;
+ break;
+ case KMF_KEYSTORE_OPENSSL:
+ break;
+ case KMF_KEYSTORE_PK11TOKEN:
+ dkparams.cred = fkparams->cred;
+ break;
+ default:
+ return (PK_ERR_USAGE);
+ }
+
+ for (i = 0; rv == KMF_OK && i < numkeys; i++) {
+ rv = KMF_DeleteKeyFromKeystore(handle, &dkparams, &keys[i]);
+ }
+ return (rv);
+}
+
+static KMF_RETURN
+pk_delete_keys(KMF_HANDLE_T kmfhandle, KMF_FINDKEY_PARAMS *parms, char *desc,
+ int *keysdeleted)
+{
+ KMF_RETURN rv = KMF_OK;
+ uint32_t numkeys = 0;
+
+ *keysdeleted = 0;
+ numkeys = 0;
+ rv = KMF_FindKey(kmfhandle, parms, NULL, &numkeys);
+ if (rv == KMF_OK && numkeys > 0) {
+ KMF_KEY_HANDLE *keys = NULL;
+ char prompt[1024];
+
+ (void) snprintf(prompt, sizeof (prompt),
+ gettext("%d %s key(s) found, do you want "
+ "to delete them (y/N) ?"), numkeys,
+ (desc != NULL ? desc : ""));
+
+ if (!yesno(prompt,
+ gettext("Respond with yes or no.\n"),
+ B_FALSE)) {
+ return (KMF_OK);
+ }
+ keys = (KMF_KEY_HANDLE *)malloc(numkeys *
+ sizeof (KMF_KEY_HANDLE));
+ if (keys == NULL)
+ return (KMF_ERR_MEMORY);
+ (void) memset(keys, 0, numkeys *
+ sizeof (KMF_KEY_HANDLE));
+
+ rv = KMF_FindKey(kmfhandle, parms, keys, &numkeys);
+ if (rv == KMF_OK) {
+ rv = pk_destroy_keys(kmfhandle, keys,
+ parms, numkeys);
+ }
+
+ free(keys);
+ }
+
+ if (rv == KMF_ERR_KEY_NOT_FOUND) {
+ rv = KMF_OK;
+ }
+
+ *keysdeleted = numkeys;
+ return (rv);
+}
+
+static KMF_RETURN
+pk_delete_certs(KMF_HANDLE_T kmfhandle, KMF_FINDCERT_PARAMS *fcparms,
+ KMF_DELETECERT_PARAMS *dcparms)
+{
+ KMF_RETURN rv = KMF_OK;
+ uint32_t numcerts = 0;
+
+ rv = KMF_FindCert(kmfhandle, fcparms, NULL, &numcerts);
+ if (rv == KMF_OK && numcerts > 0) {
+ char prompt[1024];
+ (void) snprintf(prompt, sizeof (prompt),
+ gettext("%d certificate(s) found, do you want "
+ "to delete them (y/N) ?"), numcerts);
+
+ if (!yesno(prompt,
+ gettext("Respond with yes or no.\n"),
+ B_FALSE)) {
+ return (KMF_OK);
+ }
+
+ rv = KMF_DeleteCertFromKeystore(kmfhandle, dcparms);
+
+ } else if (rv == KMF_ERR_CERT_NOT_FOUND) {
+ rv = KMF_OK;
+ }
+
+ return (rv);
+}
+
+static KMF_RETURN
+delete_nss_keys(KMF_HANDLE_T kmfhandle, char *dir, char *prefix,
+ char *token, int oclass, char *objlabel,
+ KMF_CREDENTIAL *tokencred)
+{
+ KMF_RETURN rv = KMF_OK;
+ KMF_FINDKEY_PARAMS parms;
+ char *keytype = NULL;
+ int nk, numkeys = 0;
+
+ rv = configure_nss(kmfhandle, dir, prefix);
+ if (rv != KMF_OK)
+ return (rv);
+
+ (void) memset(&parms, 0, sizeof (parms));
+ parms.kstype = KMF_KEYSTORE_NSS;
+ parms.findLabel = objlabel;
+ parms.cred = *tokencred;
+ parms.nssparms.slotlabel = token;
+
+ if (oclass & PK_PRIKEY_OBJ) {
+ parms.keyclass = KMF_ASYM_PRI;
+ keytype = "private";
+ rv = pk_delete_keys(kmfhandle, &parms, keytype, &nk);
+ numkeys += nk;
+ }
+ if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
+ parms.keyclass = KMF_SYMMETRIC;
+ keytype = "symmetric";
+ rv = pk_delete_keys(kmfhandle, &parms, keytype, &nk);
+ numkeys += nk;
+ }
+ if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) {
+ parms.keyclass = KMF_ASYM_PUB;
+ keytype = "public";
+ rv = pk_delete_keys(kmfhandle, &parms, keytype, &nk);
+ numkeys += nk;
+ }
+ if (rv == KMF_OK && numkeys == 0)
+ rv = KMF_ERR_KEY_NOT_FOUND;
+
+ return (rv);
+}
+
+
+static KMF_RETURN
+delete_nss_certs(KMF_HANDLE_T kmfhandle,
+ char *dir, char *prefix,
+ char *token, char *objlabel,
+ KMF_BIGINT *serno, char *issuer, char *subject,
+ KMF_CERT_VALIDITY find_criteria_flag)
+{
+ KMF_RETURN rv = KMF_OK;
+ KMF_DELETECERT_PARAMS dcparms;
+ KMF_FINDCERT_PARAMS fcargs;
+
+ rv = configure_nss(kmfhandle, dir, prefix);
+ if (rv != KMF_OK)
+ return (rv);
+
+ (void) memset(&dcparms, 0, sizeof (dcparms));
+ dcparms.kstype = KMF_KEYSTORE_NSS;
+ dcparms.certLabel = objlabel;
+ dcparms.issuer = issuer;
+ dcparms.subject = subject;
+ dcparms.serial = serno;
+ dcparms.find_cert_validity = find_criteria_flag;
+ dcparms.nssparms.slotlabel = token;
+
+ (void) memset(&fcargs, 0, sizeof (fcargs));
+ fcargs.kstype = KMF_KEYSTORE_NSS;
+ fcargs.certLabel = objlabel;
+ fcargs.issuer = issuer;
+ fcargs.subject = subject;
+ fcargs.serial = serno;
+ fcargs.find_cert_validity = find_criteria_flag;
+ fcargs.nssparms.slotlabel = token;
+
+ rv = pk_delete_certs(kmfhandle, &fcargs, &dcparms);
+
+ return (rv);
+}
+
+static KMF_RETURN
+delete_nss_crl(void *kmfhandle,
+ char *dir, char *prefix, char *token,
+ char *issuernickname, char *subject)
+{
+ KMF_RETURN rv = KMF_OK;
+ KMF_DELETECRL_PARAMS dcrlparms;
+
+ rv = configure_nss(kmfhandle, dir, prefix);
+ if (rv != KMF_OK)
+ return (rv);
+
+ (void) memset(&dcrlparms, 0, sizeof (dcrlparms));
+
+ dcrlparms.kstype = KMF_KEYSTORE_NSS;
+ dcrlparms.nssparms.slotlabel = token;
+ dcrlparms.nssparms.crl_issuerName = issuernickname;
+ dcrlparms.nssparms.crl_subjName = subject;
+
+ rv = KMF_DeleteCRL(kmfhandle, &dcrlparms);
+
+ return (rv);
+}
+
+static KMF_RETURN
+delete_pk11_keys(KMF_HANDLE_T kmfhandle,
+ char *token, int oclass, char *objlabel,
+ KMF_CREDENTIAL *tokencred)
+{
+ KMF_RETURN rv = KMF_OK;
+ KMF_FINDKEY_PARAMS parms;
+ int nk, numkeys = 0;
+
+ /*
+ * Symmetric keys and RSA/DSA private keys are always
+ * created with the "CKA_PRIVATE" field == TRUE, so
+ * make sure we search for them with it also set.
+ */
+ if (oclass & (PK_SYMKEY_OBJ | PK_PRIKEY_OBJ))
+ oclass |= PK_PRIVATE_OBJ;
+
+ rv = select_token(kmfhandle, token, FALSE);
+ if (rv != KMF_OK) {
+ return (rv);
+ }
+
+ (void) memset(&parms, 0, sizeof (parms));
+ parms.kstype = KMF_KEYSTORE_PK11TOKEN;
+ parms.findLabel = (char *)objlabel;
+ parms.keytype = 0;
+ parms.pkcs11parms.private = ((oclass & PK_PRIVATE_OBJ) > 0);
+ parms.cred.cred = tokencred->cred;
+ parms.cred.credlen = tokencred->credlen;
+
+ if (oclass & PK_PRIKEY_OBJ) {
+ parms.keyclass = KMF_ASYM_PRI;
+ rv = pk_delete_keys(kmfhandle, &parms, "private", &nk);
+ numkeys += nk;
+ }
+
+ if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
+ parms.keyclass = KMF_SYMMETRIC;
+ rv = pk_delete_keys(kmfhandle, &parms, "symmetric", &nk);
+ numkeys += nk;
+ }
+
+ if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) {
+ parms.keyclass = KMF_ASYM_PUB;
+ rv = pk_delete_keys(kmfhandle, &parms, "public", &nk);
+ numkeys += nk;
+ }
+ if (rv == KMF_OK && numkeys == 0)
+ rv = KMF_ERR_KEY_NOT_FOUND;
+
+ return (rv);
+}
+
+static KMF_RETURN
+delete_pk11_certs(KMF_HANDLE_T kmfhandle,
+ char *token, char *objlabel,
+ KMF_BIGINT *serno, char *issuer, char *subject,
+ KMF_CERT_VALIDITY find_criteria_flag)
+{
+ KMF_RETURN kmfrv;
+ KMF_DELETECERT_PARAMS dparms;
+ KMF_FINDCERT_PARAMS fcargs;
+
+ kmfrv = select_token(kmfhandle, token, FALSE);
+
+ if (kmfrv != KMF_OK) {
+ return (kmfrv);
+ }
+
+ (void) memset(&dparms, 0, sizeof (dparms));
+ dparms.kstype = KMF_KEYSTORE_PK11TOKEN;
+ dparms.certLabel = objlabel;
+ dparms.issuer = issuer;
+ dparms.subject = subject;
+ dparms.serial = serno;
+ dparms.find_cert_validity = find_criteria_flag;
+
+ fcargs = dparms;
+ kmfrv = pk_delete_certs(kmfhandle, &fcargs, &dparms);
+
+ return (kmfrv);
+}
+
+static KMF_RETURN
+delete_file_certs(KMF_HANDLE_T kmfhandle,
+ char *dir, char *filename, KMF_BIGINT *serial, char *issuer,
+ char *subject, KMF_CERT_VALIDITY find_criteria_flag)
+{
+ KMF_RETURN rv;
+ KMF_DELETECERT_PARAMS dparms;
+ KMF_FINDCERT_PARAMS fcargs;
+
+ (void *)memset(&dparms, 0, sizeof (dparms));
+ (void *)memset(&fcargs, 0, sizeof (fcargs));
+ fcargs.kstype = KMF_KEYSTORE_OPENSSL;
+ fcargs.certLabel = NULL;
+ fcargs.issuer = issuer;
+ fcargs.subject = subject;
+ fcargs.serial = serial;
+ fcargs.sslparms.dirpath = dir;
+ fcargs.sslparms.certfile = filename;
+ fcargs.find_cert_validity = find_criteria_flag;
+
+ /* For now, delete parameters and find parameters are the same */
+ dparms = fcargs;
+
+ rv = pk_delete_certs(kmfhandle, &fcargs, &dparms);
+
+ return (rv);
+}
+
+static KMF_RETURN
+delete_file_keys(KMF_HANDLE_T kmfhandle, int oclass,
+ char *dir, char *infile)
+{
+ KMF_RETURN rv = KMF_OK;
+ KMF_FINDKEY_PARAMS parms;
+ char *keytype = "";
+ int nk, numkeys = 0;
+
+ (void) memset(&parms, 0, sizeof (parms));
+ parms.kstype = KMF_KEYSTORE_OPENSSL;
+ parms.sslparms.dirpath = dir;
+ parms.sslparms.keyfile = infile;
+
+ if (oclass & (PK_PUBKEY_OBJ | PK_PRIKEY_OBJ)) {
+ parms.keyclass = KMF_ASYM_PRI;
+ keytype = "Asymmetric";
+ rv = pk_delete_keys(kmfhandle, &parms, keytype, &nk);
+ numkeys += nk;
+ }
+ if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
+ parms.keyclass = KMF_SYMMETRIC;
+ keytype = "symmetric";
+ rv = pk_delete_keys(kmfhandle, &parms, keytype, &nk);
+ numkeys += nk;
+ }
+ if (rv == KMF_OK && numkeys == 0)
+ rv = KMF_ERR_KEY_NOT_FOUND;
+
+ return (rv);
+}
+
+static KMF_RETURN
+delete_file_crl(void *kmfhandle, char *dir, char *filename)
+{
+ KMF_RETURN rv;
+ KMF_DELETECRL_PARAMS dcrlparms;
+
+ (void) memset(&dcrlparms, 0, sizeof (dcrlparms));
+
+ dcrlparms.kstype = KMF_KEYSTORE_OPENSSL;
+ dcrlparms.sslparms.dirpath = dir;
+ dcrlparms.sslparms.crlfile = filename;
+
+ rv = KMF_DeleteCRL(kmfhandle, &dcrlparms);
+
+ return (rv);
+}
/*
* Delete token objects.
@@ -48,31 +423,34 @@ pk_delete(int argc, char *argv[])
extern int optind_av;
extern char *optarg_av;
char *token_spec = NULL;
- char *token_name = NULL;
- char *manuf_id = NULL;
- char *serial_no = NULL;
- char *type_spec = NULL;
- char full_name[FULL_NAME_LEN];
- boolean_t public_objs = B_FALSE;
- boolean_t private_objs = B_FALSE;
- CK_BYTE *object_label = NULL;
- int obj_type = 0x00;
- CK_SLOT_ID slot_id;
- CK_FLAGS pin_state;
- CK_UTF8CHAR_PTR pin = NULL;
- CK_ULONG pinlen = 0;
- CK_SESSION_HANDLE sess;
- CK_OBJECT_HANDLE *objs;
- CK_ULONG num_objs;
- CK_ATTRIBUTE label = { CKA_LABEL, NULL, 0 };
- CK_RV rv = CKR_OK;
- int i;
-
- cryptodebug("inside pk_delete");
+ char *subject = NULL;
+ char *issuer = NULL;
+ char *dir = NULL;
+ char *prefix = NULL;
+ char *infile = NULL;
+ char *object_label = NULL;
+ char *serstr = NULL;
+
+ int oclass = 0;
+ KMF_BIGINT serial = { NULL, 0 };
+ KMF_HANDLE_T kmfhandle = NULL;
+ KMF_KEYSTORE_TYPE kstype = 0;
+ KMF_RETURN kmfrv;
+ int rv = 0;
+ char *find_criteria = NULL;
+ KMF_CERT_VALIDITY find_criteria_flag = KMF_ALL_CERTS;
+ KMF_CREDENTIAL tokencred = {NULL, 0};
/* Parse command line options. Do NOT i18n/l10n. */
while ((opt = getopt_av(argc, argv,
- "T:(token)y:(objtype)l:(label)")) != EOF) {
+ "T:(token)y:(objtype)l:(label)"
+ "k:(keystore)s:(subject)n:(nickname)"
+ "d:(dir)p:(prefix)S:(serial)i:(issuer)"
+ "c:(criteria)"
+ "f:(infile)")) != EOF) {
+
+ if (EMPTYSTRING(optarg_av))
+ return (PK_ERR_USAGE);
switch (opt) {
case 'T': /* token specifier */
if (token_spec)
@@ -80,14 +458,52 @@ pk_delete(int argc, char *argv[])
token_spec = optarg_av;
break;
case 'y': /* object type: public, private, both */
- if (type_spec)
+ if (oclass)
+ return (PK_ERR_USAGE);
+ oclass = OT2Int(optarg_av);
+ if (oclass == -1)
return (PK_ERR_USAGE);
- type_spec = optarg_av;
break;
case 'l': /* objects with specific label */
+ case 'n':
if (object_label)
return (PK_ERR_USAGE);
- object_label = (CK_BYTE *)optarg_av;
+ object_label = (char *)optarg_av;
+ break;
+ case 'k':
+ kstype = KS2Int(optarg_av);
+ if (kstype == 0)
+ return (PK_ERR_USAGE);
+ break;
+ case 's':
+ subject = optarg_av;
+ break;
+ case 'i':
+ issuer = optarg_av;
+ break;
+ case 'd':
+ dir = optarg_av;
+ break;
+ case 'p':
+ prefix = optarg_av;
+ break;
+ case 'S':
+ serstr = optarg_av;
+ break;
+ case 'f':
+ infile = optarg_av;
+ break;
+ case 'c':
+ find_criteria = optarg_av;
+ if (!strcasecmp(find_criteria, "valid"))
+ find_criteria_flag =
+ KMF_NONEXPIRED_CERTS;
+ else if (!strcasecmp(find_criteria, "expired"))
+ find_criteria_flag = KMF_EXPIRED_CERTS;
+ else if (!strcasecmp(find_criteria, "both"))
+ find_criteria_flag = KMF_ALL_CERTS;
+ else
+ return (PK_ERR_USAGE);
break;
default:
return (PK_ERR_USAGE);
@@ -95,55 +511,23 @@ pk_delete(int argc, char *argv[])
}
}
- /* If no token is specified, default is to use softtoken. */
- if (token_spec == NULL) {
- token_name = SOFT_TOKEN_LABEL;
- manuf_id = SOFT_MANUFACTURER_ID;
- serial_no = SOFT_TOKEN_SERIAL;
- } else {
- /*
- * Parse token specifier into token_name, manuf_id, serial_no.
- * Token_name is required; manuf_id and serial_no are optional.
- */
- if (parse_token_spec(token_spec, &token_name, &manuf_id,
- &serial_no) < 0)
- return (PK_ERR_USAGE);
- }
+ /* Assume keystore = PKCS#11 if not specified */
+ if (kstype == 0)
+ kstype = KMF_KEYSTORE_PK11TOKEN;
- /* If no object type specified, default is public objects. */
- if (!type_spec) {
- public_objs = B_TRUE;
- } else {
- /*
- * Otherwise, the object type must be "public", "private",
- * or "both".
- */
- if (strcmp(type_spec, "private") == 0) {
- private_objs = B_TRUE;
- } else if (strcmp(type_spec, "public") == 0) {
- public_objs = B_TRUE;
- } else if (strcmp(type_spec, "both") == 0) {
- private_objs = B_TRUE;
- public_objs = B_TRUE;
- } else
- return (PK_ERR_USAGE);
- }
-
- if (private_objs)
- obj_type |= PK_PRIVATE_OBJ;
- if (public_objs)
- obj_type |= PK_PUBLIC_OBJ;
+ /* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
+ if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
+ kstype != KMF_KEYSTORE_PK11TOKEN) {
- /* At least one of public, private, or object label is required. */
- if (!private_objs && !public_objs && object_label == NULL)
+ (void) fprintf(stderr, gettext("The objtype parameter "
+ "is only relevant if keystore=pkcs11\n"));
return (PK_ERR_USAGE);
+ }
- /*
- * If object label is given but neither public/private is specified,
- * delete all objects with that label.
- */
- if (!private_objs && !public_objs && object_label != NULL)
- obj_type = PK_ALL_OBJ;
+ /* If no object class specified, delete everything but CRLs */
+ if (oclass == 0)
+ oclass = PK_CERT_OBJ | PK_PUBKEY_OBJ | PK_PRIKEY_OBJ |
+ PK_SYMKEY_OBJ;
/* No additional args allowed. */
argc -= optind_av;
@@ -152,112 +536,129 @@ pk_delete(int argc, char *argv[])
return (PK_ERR_USAGE);
/* Done parsing command line options. */
- full_token_name(token_name, manuf_id, serial_no, full_name);
-
- /* Find the slot with token. */
- if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
- &pin_state)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to find token %s (%s)."), full_name,
- pkcs11_strerror(rv));
- return (PK_ERR_PK11);
+ if (kstype == KMF_KEYSTORE_PK11TOKEN && token_spec == NULL) {
+ token_spec = PK_DEFAULT_PK11TOKEN;
+ } else if (kstype == KMF_KEYSTORE_NSS && token_spec == NULL) {
+ token_spec = DEFAULT_NSS_TOKEN;
}
- /* Always get the user's PIN for delete operations. */
- if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin,
- &pinlen)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get token passphrase (%s)."),
- pkcs11_strerror(rv));
- quick_finish(NULL);
- return (PK_ERR_PK11);
- }
+ if (serstr != NULL) {
+ uchar_t *bytes = NULL;
+ size_t bytelen;
- /* Log the user R/W into the token. */
- if ((rv = quick_start(slot_id, CKF_RW_SESSION, pin, pinlen, &sess)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to log into token (%s)."), pkcs11_strerror(rv));
- quick_finish(sess);
- return (PK_ERR_PK11);
+ rv = KMF_HexString2Bytes((uchar_t *)serstr, &bytes, &bytelen);
+ if (rv != KMF_OK || bytes == NULL) {
+ (void) fprintf(stderr, gettext("serial number "
+ "must be specified as a hex number "
+ "(ex: 0x0102030405ffeeddee)\n"));
+ return (PK_ERR_USAGE);
+ }
+ serial.val = bytes;
+ serial.len = bytelen;
}
- /* Find the object(s) with the given label and/or type. */
- if ((rv = find_objs(sess, obj_type, object_label, &objs, &num_objs)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to find token objects (%s)."), pkcs11_strerror(rv));
- quick_finish(sess);
- return (PK_ERR_PK11);
- }
+ if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
+ kstype == KMF_KEYSTORE_NSS) &&
+ (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ))) {
- if (num_objs == 0) {
- (void) fprintf(stdout, gettext("No matching objects found.\n"));
- quick_finish(sess);
- return (0);
+ (void) get_token_password(kstype, token_spec,
+ &tokencred);
}
- if (num_objs != 1) {
- (void) fprintf(stdout, gettext(
- "Warning: %d matching objects found, deleting all.\n"),
- num_objs);
- if (yesno(gettext("Continue with delete? "),
- gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
- quick_finish(sess);
- return (0);
- }
- }
+ if ((kmfrv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK)
+ return (kmfrv);
- /* Destroy the objects if found. */
- for (i = 0; i < num_objs; i++) {
- /*
- * To give nice feedback to the user, get the object's
- * label before deleting it.
- */
- cryptodebug("calling C_GetAttributeValue for label");
- label.pValue = NULL;
- label.ulValueLen = 0;
- if (C_GetAttributeValue(sess, objs[i], &label, 1) == CKR_OK) {
- if (label.ulValueLen != (CK_ULONG)-1 &&
- label.ulValueLen != 0 &&
- (label.pValue = malloc(label.ulValueLen)) != NULL) {
- if (C_GetAttributeValue(sess, objs[i], &label,
- 1) != CKR_OK) {
- free(label.pValue);
- label.pValue = NULL;
- label.ulValueLen = 0;
- }
- } else {
- label.ulValueLen = 0;
+ switch (kstype) {
+ case KMF_KEYSTORE_PK11TOKEN:
+ if (oclass & PK_KEY_OBJ) {
+ kmfrv = delete_pk11_keys(kmfhandle,
+ token_spec, oclass,
+ object_label,
+ &tokencred);
+ /*
+ * If deleting groups of objects, it is OK
+ * to ignore the "key not found" case so that
+ * we can continue to find other objects.
+ */
+ if (kmfrv == KMF_ERR_KEY_NOT_FOUND &&
+ (oclass != PK_KEY_OBJ))
+ kmfrv = KMF_OK;
+ if (kmfrv != KMF_OK)
+ break;
}
- }
-
- cryptodebug("calling C_DestroyObject");
- if ((rv = C_DestroyObject(sess, objs[i])) != CKR_OK) {
- if (label.pValue != NULL)
- cryptoerror(LOG_STDERR, gettext(
- "Unable to delete object #%d \"%.*s\" "
- "(%s)."), i+1, label.ulValueLen,
- label.pValue, pkcs11_strerror(rv));
- else
- cryptoerror(LOG_STDERR, gettext(
- "Unable to delete object #%d (%s)."),
- i+1, pkcs11_strerror(rv));
- } else {
- if (label.pValue != NULL)
- (void) fprintf(stdout, gettext("Object #%d "
- "\"%.*s\" successfully deleted.\n"),
- i+1, label.ulValueLen, label.pValue);
- else
- (void) fprintf(stdout, gettext(
- "Object #%d successfully deleted.\n"), i+1);
- }
+ if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
+ kmfrv = delete_pk11_certs(kmfhandle,
+ token_spec,
+ object_label,
+ &serial, issuer,
+ subject, find_criteria_flag);
+ /*
+ * If cert delete failed, but we are looking at
+ * other objects, then it is OK.
+ */
+ if (kmfrv == KMF_ERR_CERT_NOT_FOUND &&
+ (oclass & (PK_CRL_OBJ | PK_KEY_OBJ)))
+ kmfrv = KMF_OK;
+ if (kmfrv != KMF_OK)
+ break;
+ }
+ if (oclass & PK_CRL_OBJ)
+ kmfrv = delete_file_crl(kmfhandle,
+ dir, infile);
+ break;
+ case KMF_KEYSTORE_NSS:
+ if (oclass & PK_KEY_OBJ) {
+ kmfrv = delete_nss_keys(kmfhandle,
+ dir, prefix, token_spec,
+ oclass, (char *)object_label,
+ &tokencred);
+ if (kmfrv != KMF_OK)
+ break;
+ }
+ if (oclass & PK_CERT_OBJ) {
+ kmfrv = delete_nss_certs(kmfhandle,
+ dir, prefix, token_spec,
+ (char *)object_label,
+ &serial, issuer, subject,
+ find_criteria_flag);
+ if (kmfrv != KMF_OK)
+ break;
+ }
+ if (oclass & PK_CRL_OBJ)
+ kmfrv = delete_nss_crl(kmfhandle,
+ dir, prefix, token_spec,
+ (char *)object_label, subject);
+ break;
+ case KMF_KEYSTORE_OPENSSL:
+ if (oclass & PK_KEY_OBJ) {
+ kmfrv = delete_file_keys(kmfhandle, oclass,
+ dir, infile);
+ if (kmfrv != KMF_OK)
+ break;
+ }
+ if (oclass & (PK_CERT_OBJ)) {
+ kmfrv = delete_file_certs(kmfhandle,
+ dir, infile, &serial, issuer,
+ subject, find_criteria_flag);
+ if (kmfrv != KMF_OK)
+ break;
+ }
+ if (oclass & PK_CRL_OBJ)
+ kmfrv = delete_file_crl(kmfhandle,
+ dir, infile);
+ break;
+ default:
+ rv = PK_ERR_USAGE;
+ break;
+ }
- if (label.pValue != NULL)
- free(label.pValue);
+ if (kmfrv != KMF_OK) {
+ display_error(kmfhandle, kmfrv,
+ gettext("Error deleting objects"));
}
- /* Clean up. */
- quick_finish(sess);
- return (0);
+ if (serial.val != NULL)
+ free(serial.val);
+ (void) KMF_Finalize(kmfhandle);
+ return (kmfrv);
}
diff --git a/usr/src/cmd/cmd-crypto/pktool/derparse.c b/usr/src/cmd/cmd-crypto/pktool/derparse.c
deleted file mode 100644
index cec607220a..0000000000
--- a/usr/src/cmd/cmd-crypto/pktool/derparse.c
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * 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.
- *
- * 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 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * derparse.c - Functions for parsing DER-encoded data
- *
- * NOTE: This code was originally written by Cryptographic Products
- * Group at Sun Microsystems for the SCA 1000 "realmparse" program.
- * It is mostly intact except for necessary adaptaions to allow it to
- * compile in this environment.
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <lber.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <strings.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <cryptoutil.h>
-#include "derparse.h"
-
-/* I18N helpers. */
-#include <libintl.h>
-#include <locale.h>
-
-/*
- * Some types that we need below.
- */
-typedef struct oidinfo {
- uint8_t *value; /* OID value in bytes */
- size_t length; /* Length of OID */
- char *strval; /* String rep. for OID in RDN */
-} oidinfo_t;
-
-/*
- * X.509 Issuer OIDs as recommended by RFC 3280
- * We might see these in certificates in their subject an issuer names.
- */
-static uint8_t common_name_oid[] = {0x55, 0x04, 0x03};
-static uint8_t surname_oid[] = {0x55, 0x04, 0x04};
-static uint8_t serial_number_oid[] = {0x55, 0x04, 0x05};
-static uint8_t country_name_oid[] = {0x55, 0x04, 0x06};
-static uint8_t locality_name_oid[] = {0x55, 0x04, 0x07};
-static uint8_t state_name_oid[] = {0x55, 0x04, 0x08};
-static uint8_t org_name_oid[] = {0x55, 0x04, 0x0a};
-static uint8_t org_unit_name_oid[] = {0x55, 0x04, 0x0b};
-static uint8_t title_oid[] = {0x55, 0x04, 0x0c};
-static uint8_t name_oid[] = {0x55, 0x04, 0x29};
-static uint8_t given_name_oid[] = {0x55, 0x04, 0x2a};
-static uint8_t initials_oid[] = {0x55, 0x04, 0x2b};
-static uint8_t gen_qual_oid[] = {0x55, 0x04, 0x2c};
-static uint8_t dn_qual_oid[] = {0x55, 0x04, 0x2e};
-static uint8_t pseudonym_oid[] = {0x55, 0x04, 0x31};
-static uint8_t uid_oid[] =
- {0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x01};
-static uint8_t domain_comp_oid[] =
- {0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19};
-static uint8_t email_addr_oid[] =
- {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01};
-
-/* Define this structure so we can match on a given oid */
-static oidinfo_t oids[] = {
- {common_name_oid, sizeof (common_name_oid), "CN"},
- {surname_oid, sizeof (surname_oid), "SN"},
- {serial_number_oid, sizeof (serial_number_oid), "SerialNum"},
- {country_name_oid, sizeof (country_name_oid), "C"},
- {locality_name_oid, sizeof (locality_name_oid), "L"},
- {state_name_oid, sizeof (state_name_oid), "ST"},
- {org_name_oid, sizeof (org_name_oid), "O"},
- {org_unit_name_oid, sizeof (org_unit_name_oid), "OU"},
- {title_oid, sizeof (title_oid), "Title"},
- {name_oid, sizeof (name_oid), "Name"},
- {given_name_oid, sizeof (given_name_oid), "GN"},
- {initials_oid, sizeof (initials_oid), "Initials"},
- {gen_qual_oid, sizeof (gen_qual_oid), "GenQual"},
- {dn_qual_oid, sizeof (dn_qual_oid), "DNQual"},
- {pseudonym_oid, sizeof (pseudonym_oid), "Pseudonym"},
- {uid_oid, sizeof (uid_oid), "UID"},
- {domain_comp_oid, sizeof (domain_comp_oid), "DC"},
- {email_addr_oid, sizeof (email_addr_oid), "E"}
-};
-static int oidblocklen = sizeof (oids) / sizeof (oidinfo_t);
-
-/* Local functions */
-static int oid_to_str(uint8_t *, size_t, char *, size_t);
-static int get_oid_type(char *);
-
-/*
- * An RDNSequence is what is handed to us when we get attributes like
- * CKA_ISSUER and CKA_SUBJECT_NAME. This function will take in a buffer
- * with the DER encoded bytes of an RDNSequence and print out the components.
- *
- * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
- *
- * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue
- *
- * AttributeTypeAndValue ::= SEQUENCE {
- * type AttributeType,
- * value AttributeValue
- * }
- *
- * AttributeType ::= OBJECT IDENTIFIER
- *
- * AttributeValue ::= ANY DEFINED BY AttributeType
- */
-void
-rdnseq_to_str(uchar_t *derdata, size_t dersz, char *out, size_t outsz)
-{
-#define PKTOOL_LINEMAX 1024
- char oidout[PKTOOL_LINEMAX];
- BerElement *ber = NULL;
- BerValue ber_rdns;
- int tag;
- ber_len_t size;
- char *atv_type = NULL; /* Attribute Type */
- ber_len_t atv_type_size;
- char *atv_value = NULL; /* Attribute Value */
- ber_len_t atv_value_size;
- char *cookie = NULL;
- int idx;
- char *prndata = NULL;
- int prnsz;
- int offset = 0;
- boolean_t first = B_TRUE;
-
- cryptodebug("inside rdnseq_to_str");
-
- if (derdata == NULL || dersz == 0) {
- cryptodebug("nothing to parse");
- return;
- }
-
- /* Take the raw bytes and stuff them into a BerValue structure */
- ber_rdns.bv_val = (char *)derdata;
- ber_rdns.bv_len = dersz;
-
- /* Allocate the BerElement */
- if ((ber = ber_init(&ber_rdns)) == NULLBER) {
- cryptodebug("ber_init failed to return ber element");
- cryptoerror(LOG_STDERR, gettext(
- "Unable to begin parsing RDNSequence."));
- return;
- }
-
- /* Begin by parsing out the outer sequence */
- tag = ber_next_element(ber, &size, cookie);
- if (tag != LBER_SEQUENCE) {
- cryptodebug("ber_next_element tag is not SEQUENCE");
- cryptoerror(LOG_STDERR, gettext(
- "Expected RDNSequence SEQUENCE object, got tag [%02x]."),
- tag);
- return;
- }
- tag = ber_scanf(ber, "{");
-
- /* Parse the sequence of RelativeDistinguishedName objects */
- while ((tag = ber_next_element(ber, &size, cookie)) != -1) {
- if (tag != LBER_SET) {
- cryptodebug("ber_next_element tag is not SET");
- cryptoerror(LOG_STDERR, gettext(
- "Expected RelativeDistinguishedName SET object, "
- "got tag [%02x]."), tag);
- return;
- }
- tag = ber_scanf(ber, "[");
-
- /* AttributeTypeAndValue */
- tag = ber_next_element(ber, &size, cookie);
- if (tag != LBER_SEQUENCE) {
- cryptodebug("ber_next_element tag is not SEQUENCE");
- cryptoerror(LOG_STDERR, gettext(
- "Expected AttributeTypeAndValue SEQUENCE object, "
- "got tag [%02x]."), tag);
- return;
- }
- tag = ber_scanf(ber, "{");
-
- /* AttributeType OID */
- tag = ber_next_element(ber, &atv_type_size, cookie);
- atv_type_size++; /* Add room for null terminator */
- if (tag != LBER_OID) {
- cryptodebug("ber_next_element tag is not OID");
- cryptoerror(LOG_STDERR, gettext(
- "Expected an OID, got tag [%02x]."), tag);
- return;
- }
- /* Note: ber_scanf() allocates memory here for "a". */
- tag = ber_scanf(ber, "a", &atv_type, &atv_type_size);
-
- /* AttributeValue */
- tag = ber_next_element(ber, &atv_value_size, cookie);
- atv_value_size++;
- if ((tag != LBER_PRINTABLE_STRING) && (tag != LBER_IA5STRING)) {
- cryptodebug("ber_next_element tag is not "
- "PRINTABLE_STRING/IA5STRING");
- cryptoerror(LOG_STDERR, gettext("Expected a STRING, "
- "got tag [%02x]."), tag);
- free(atv_type);
- return;
- }
- /* Note: ber_scanf() allocates memory here for "a". */
- tag = ber_scanf(ber, "a", &atv_value, &atv_value_size);
-
- /*
- * Now go and turn the attribute type and value into
- * some kind of meaningful output.
- */
- if ((idx = get_oid_type(atv_type)) == -1) {
- if (oid_to_str((uint8_t *)atv_type, strlen(atv_type),
- oidout, sizeof (oidout)) < 0) {
- cryptodebug("oid_to_str failed");
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert OID to string."));
- free(atv_type);
- free(atv_value);
- return;
- }
- prndata = oidout;
- } else {
- prndata = oids[idx].strval;
- }
-
- if (!first)
- prnsz = snprintf(out + offset, outsz - offset,
- ", %s = %s", prndata, atv_value);
- else {
- prnsz = snprintf(out + offset, outsz - offset,
- "%s = %s", prndata, atv_value);
- first = B_FALSE;
- }
-
- free(atv_type);
- free(atv_value);
- atv_type = NULL;
- atv_value = NULL;
-
- offset += prnsz;
- if (offset >= outsz)
- break;
- }
-}
-
-/*
- * Convert OID to dotted notation string.
- */
-static int
-oid_to_str(uint8_t *oid, size_t oidlen, char *oidout, size_t oidout_len)
-{
- int count = 0;
- int offset = 0;
- int prnsz;
- uint_t firstnum;
- uint_t secondnum;
- uint64_t nextnum = 0;
-
- cryptodebug("inside oid_to_str");
-
- if (oidlen == 0)
- return (-1);
-
- /*
- * The first octet has a value of (40 x oidnum1) + oidnum2. We
- * will deconstruct it here and sanity check the result. According
- * to X.690, oidnum1 should never be more than 2 and oidnum2
- * shouldn't be greater than 39 when oidnum1 = 0 or 1.
- */
- firstnum = oid[count] / 40;
- if (firstnum > 2) /* force remainder to be > 39 */
- firstnum = 2;
- secondnum = oid[count] - (firstnum * 40);
-
- (void) memset(oidout, 0, oidout_len);
-
- prnsz = snprintf(oidout, oidout_len, "%d.%d", firstnum, secondnum);
- offset += prnsz;
- if (offset >= oidout_len)
- return (0);
-
- /* Start at the second byte and move our way forward */
- for (count = 1; count < oidlen; count++) {
- /* ORIGINAL COMMENT */
- /*
- * Each oid byte is taken as a 7-bit number. If bit 8 is
- * set, it means the next octet and this one are to be
- * chained together as a single bit string, and so forth.
- * We need to mask of bit 8, then shift over 7 bits in the
- * resulting integer, and then stuff the new 7 bits in
- * the low order byte, all the while making sure we don't
- * stomp bit 1 from the previous octet.
- * See X.690 or the layman's guide to ASN.1 for more.
- */
-
- /*
- * String together as many of the next octets if each of
- * their high order bits is set to 1. For example,
- * 1 1010111, 1 0010100, 1 0010110, 0 1101111, ...
- * (3 8-bit octets)
- * becomes
- * 1010111 0010100 0010110, 1101111, ...
- * (one 21 bit integer)
- * The high order bit functions as a "link" between octets.
- * Note that if there are more than 9 octets with their
- * high order bits set, it will overflow a 64-bit integer.
- */
- for (nextnum = 0; (oid[count] & 0x80) && (count < oidlen);
- count++) {
- nextnum <<= 7;
- nextnum |= (oid[count] & 0x7f);
- }
- if (count == oidlen) /* last number not terminated? */
- return (-1);
-
- /* We're done with this oid number, write it and move on */
- prnsz = snprintf(oidout + offset, oidout_len - offset,
- ".%lld", nextnum);
- offset += prnsz;
- if (offset >= oidout_len)
- return (0);
- }
-
- return (0);
-}
-
-/*
- * Returns the index in the oids[] array that matches the input type,
- * or -1 if it could not find a match.
- */
-static int
-get_oid_type(char *type)
-{
- int count;
-
- cryptodebug("inside get_oid_type");
-
- for (count = 0; count < oidblocklen; count++) {
- if (memcmp(oids[count].value, type, oids[count].length) == 0) {
- return (count);
- }
- }
-
- /* If we get here, we haven't found a match, so return -1 */
- return (-1);
-}
diff --git a/usr/src/cmd/cmd-crypto/pktool/derparse.h b/usr/src/cmd/cmd-crypto/pktool/derparse.h
deleted file mode 100644
index 2ff36d2163..0000000000
--- a/usr/src/cmd/cmd-crypto/pktool/derparse.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.
- *
- * 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 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _PKTOOL_DERPARSE_H
-#define _PKTOOL_DERPARSE_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef LBER_OID
-#define LBER_OID 0x06
-#endif
-
-#ifndef LBER_PRINTABLE_STRING
-#define LBER_PRINTABLE_STRING 0x13
-#endif
-
-#ifndef LBER_IA5STRING
-#define LBER_IA5STRING 0x16
-#endif
-
-extern void rdnseq_to_str(uchar_t *from, size_t from_sz, char *to,
- size_t to_sz);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PKTOOL_DERPARSE_H */
diff --git a/usr/src/cmd/cmd-crypto/pktool/download.c b/usr/src/cmd/cmd-crypto/pktool/download.c
new file mode 100644
index 0000000000..1eabc85ee3
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/pktool/download.c
@@ -0,0 +1,274 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <malloc.h>
+#include <libgen.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <cryptoutil.h>
+#include "common.h"
+#include <kmfapi.h>
+
+int
+pk_download(int argc, char *argv[])
+{
+ int rv;
+ int opt;
+ extern int optind_av;
+ extern char *optarg_av;
+ int oclass = 0;
+ char *url = NULL;
+ char *http_proxy = NULL;
+ char *dir = NULL;
+ char *outfile = NULL;
+ char *proxy = NULL;
+ int proxy_port = 0;
+ KMF_HANDLE_T kmfhandle = NULL;
+ KMF_ENCODE_FORMAT format;
+ KMF_RETURN ch_rv = KMF_OK;
+ char *fullpath = NULL;
+ KMF_DATA cert = {NULL, 0};
+ KMF_DATA cert_der = {NULL, 0};
+
+ while ((opt = getopt_av(argc, argv,
+ "t:(objtype)u:(url)h:(http_proxy)o:(outfile)d:(dir)")) != EOF) {
+
+ if (EMPTYSTRING(optarg_av))
+ return (PK_ERR_USAGE);
+ switch (opt) {
+ case 't':
+ if (oclass)
+ return (PK_ERR_USAGE);
+ oclass = OT2Int(optarg_av);
+ if (!(oclass & (PK_CERT_OBJ | PK_CRL_OBJ)))
+ return (PK_ERR_USAGE);
+ break;
+ case 'u':
+ if (url)
+ return (PK_ERR_USAGE);
+ url = optarg_av;
+ break;
+ case 'h':
+ if (http_proxy)
+ return (PK_ERR_USAGE);
+ http_proxy = optarg_av;
+ break;
+ case 'o':
+ if (outfile)
+ return (PK_ERR_USAGE);
+ outfile = optarg_av;
+ break;
+ case 'd':
+ if (dir)
+ return (PK_ERR_USAGE);
+ dir = optarg_av;
+ break;
+ default:
+ cryptoerror(LOG_STDERR, gettext(
+ "unrecognized download option '%s'\n"),
+ argv[optind_av]);
+ return (PK_ERR_USAGE);
+ }
+ }
+
+ /* No additional args allowed. */
+ argc -= optind_av;
+ argv += optind_av;
+ if (argc) {
+ return (PK_ERR_USAGE);
+ }
+
+ /* Check the dir and outfile options */
+ if (outfile == NULL) {
+ /* If outfile is not specified, use the basename of URI */
+ outfile = basename(url);
+ }
+
+ fullpath = get_fullpath(dir, outfile);
+ if (fullpath == NULL) {
+ cryptoerror(LOG_STDERR, gettext("Incorrect dir or outfile "
+ "option value \n"));
+ return (PK_ERR_USAGE);
+ }
+ /* Check if the file exists and might be overwritten. */
+ if (access(fullpath, F_OK) == 0) {
+ cryptoerror(LOG_STDERR,
+ gettext("Warning: file \"%s\" exists, "
+ "will be overwritten."), fullpath);
+ if (yesno(gettext("Continue with download? "),
+ gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
+ return (0);
+ }
+ } else {
+ rv = verify_file(fullpath);
+ if (rv != KMF_OK) {
+ cryptoerror(LOG_STDERR, gettext("The file (%s) "
+ "cannot be created.\n"), fullpath);
+ return (PK_ERR_USAGE);
+ }
+ }
+
+
+ /* URI MUST be specified */
+ if (url == NULL) {
+ cryptoerror(LOG_STDERR, gettext("A URL must be specified\n"));
+ rv = PK_ERR_USAGE;
+ goto end;
+ }
+
+ /*
+ * Get the http proxy from the command "http_proxy" option or the
+ * environment variable. The command option has a higher priority.
+ */
+ if (http_proxy == NULL)
+ http_proxy = getenv("http_proxy");
+
+ if (http_proxy != NULL) {
+ char *ptmp = http_proxy;
+ char *proxy_port_s;
+
+ if (strncasecmp(ptmp, "http://", 7) == 0)
+ ptmp += 7; /* skip the scheme prefix */
+
+ proxy = strtok(ptmp, ":");
+ proxy_port_s = strtok(NULL, "\0");
+ if (proxy_port_s != NULL)
+ proxy_port = strtol(proxy_port_s, NULL, 0);
+ else
+ proxy_port = 8080;
+ }
+
+ /* If objtype is not specified, default to CRL */
+ if (oclass == 0) {
+ oclass = PK_CRL_OBJ;
+ }
+
+ if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
+ cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
+ rv = PK_ERR_USAGE;
+ goto end;
+ }
+
+ /* Now we are ready to download */
+ if (oclass & PK_CRL_OBJ) {
+ rv = KMF_DownloadCRL(kmfhandle, url, proxy, proxy_port, 30,
+ fullpath, &format);
+ } else if (oclass & PK_CERT_OBJ) {
+ rv = KMF_DownloadCert(kmfhandle, url, proxy, proxy_port, 30,
+ fullpath, &format);
+ }
+
+ if (rv != KMF_OK) {
+ switch (rv) {
+ case KMF_ERR_BAD_URI:
+ cryptoerror(LOG_STDERR,
+ gettext("Error in parsing URI\n"));
+ rv = PK_ERR_USAGE;
+ break;
+ case KMF_ERR_OPEN_FILE:
+ cryptoerror(LOG_STDERR,
+ gettext("Error in opening file\n"));
+ rv = PK_ERR_USAGE;
+ break;
+ case KMF_ERR_WRITE_FILE:
+ cryptoerror(LOG_STDERR,
+ gettext("Error in writing file\n"));
+ rv = PK_ERR_USAGE;
+ break;
+ case KMF_ERR_BAD_CRLFILE:
+ cryptoerror(LOG_STDERR, gettext("Not a CRL file\n"));
+ rv = PK_ERR_USAGE;
+ break;
+ case KMF_ERR_BAD_CERTFILE:
+ cryptoerror(LOG_STDERR,
+ gettext("Not a certificate file\n"));
+ rv = PK_ERR_USAGE;
+ break;
+ case KMF_ERR_MEMORY:
+ cryptoerror(LOG_STDERR,
+ gettext("Not enough memory\n"));
+ rv = PK_ERR_SYSTEM;
+ break;
+ default:
+ cryptoerror(LOG_STDERR,
+ gettext("Error in downloading the file.\n"));
+ rv = PK_ERR_SYSTEM;
+ break;
+ }
+ goto end;
+ }
+
+ /*
+ * If the file is successfully downloaded, we also check the date.
+ * If the downloaded file is outdated, give a warning.
+ */
+ if (oclass & PK_CRL_OBJ) {
+ KMF_CHECKCRLDATE_PARAMS params;
+
+ params.crl_name = fullpath;
+ ch_rv = KMF_CheckCRLDate(kmfhandle, &params);
+
+ } else { /* certificate */
+ ch_rv = KMF_ReadInputFile(kmfhandle, fullpath, &cert);
+ if (ch_rv != KMF_OK)
+ goto end;
+
+ if (format == KMF_FORMAT_PEM) {
+ int len;
+ ch_rv = KMF_Pem2Der(cert.Data, cert.Length,
+ &cert_der.Data, &len);
+ if (ch_rv != KMF_OK)
+ goto end;
+ cert_der.Length = (size_t)len;
+ }
+
+ ch_rv = KMF_CheckCertDate(kmfhandle,
+ format == KMF_FORMAT_ASN1 ? &cert : &cert_der);
+ }
+
+end:
+ if (ch_rv == KMF_ERR_VALIDITY_PERIOD) {
+ cryptoerror(LOG_STDERR,
+ gettext("Warning: the downloaded file is expired.\n"));
+ } else if (ch_rv != KMF_OK) {
+ cryptoerror(LOG_STDERR,
+ gettext("Warning: failed to check the validity.\n"));
+ }
+
+ if (fullpath)
+ free(fullpath);
+
+ KMF_FreeData(&cert);
+ KMF_FreeData(&cert_der);
+
+ (void) KMF_Finalize(kmfhandle);
+ return (rv);
+}
diff --git a/usr/src/cmd/cmd-crypto/pktool/export.c b/usr/src/cmd/cmd-crypto/pktool/export.c
index 46fbccb37e..9170a00468 100644
--- a/usr/src/cmd/cmd-crypto/pktool/export.c
+++ b/usr/src/cmd/cmd-crypto/pktool/export.c
@@ -17,8 +17,8 @@
* 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.
*/
@@ -38,1170 +38,264 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
-#include <cryptoutil.h>
-#include <security/cryptoki.h>
+#include <fcntl.h>
#include "common.h"
-#include "biginteger.h"
-#include "osslcommon.h"
-#include "p12common.h"
-#include <openssl/pkcs12.h>
-
-/*
- * Writes OpenSSL objects to PKCS#12 file. The PKCS#11 objects from
- * the soft token need to be converted to OpenSSL structures prior
- * to this call, since the PKCS#12 routines depend on that format.
- * This code is patterned from OpenSSL apps that write PKCS#12 files.
- *
- * Note: it's not clear from the usage of all the functions here by
- * OpenSSL apps whether these functions have return values or error
- * conditions that can be checked. This function may benefit from
- * a closer review at a later time.
- */
-static int
-write_objs_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
- CK_BYTE_PTR id, CK_ULONG id_len, EVP_PKEY *priv_key, X509 *cert,
- STACK_OF(X509) *ca_certs, int *successes, int *failures)
-/* ARGSUSED */
-{
- STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL;
- PKCS12_SAFEBAG *bag = NULL;
- X509 *ca = NULL;
- PKCS7 *cert_authsafe = NULL;
- PKCS8_PRIV_KEY_INFO *p8 = NULL;
- PKCS7 *key_authsafe = NULL;
- STACK_OF(PKCS7) *authsafe_stack = NULL;
- PKCS12 *p12_elem = NULL;
- unsigned char *lab = NULL;
- int lab_len = 0;
- int i;
- int n_writes = 0;
-
- cryptodebug("inside write_objs_pkcs12");
-
- /* Do not reset *successes or *failures -- keep running totals. */
-
- /* If there is nothing to write to the PKCS#12 file, leave. */
- if (cert == NULL && ca_certs == NULL && priv_key == NULL) {
- cryptodebug("nothing to write to export file");
- return (0);
- }
-
- /*
- * Section 1:
- *
- * The first PKCS#12 container (safebag) will hold the certificates
- * associated with this key. The result of this section is a
- * PIN-encrypted PKCS#7 container (authsafe). If there are no
- * certificates, there is no point in creating the "safebag" or the
- * "authsafe" so we go to the next section.
- */
- if (cert != NULL || ca_certs != NULL) {
- /* Start a PKCS#12 safebag container for the certificates. */
- cryptodebug("creating certificate PKCS#12 safebag");
- bag_stack = sk_PKCS12_SAFEBAG_new_null();
- if (bag_stack == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to create PKCS#12 certificate bag."));
- (*failures)++;
- return (-1);
- }
-
- /* Add the cert corresponding to private key to bag_stack. */
- if (cert) {
- /* Convert cert from X509 struct to PKCS#12 bag */
- cryptodebug("adding certificate to PKCS#12 safebag");
- bag = PKCS12_x5092certbag(cert);
- if (bag == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert certificate to "
- "PKCS#12 bag."));
- /* Cleanup the safebag. */
- sk_PKCS12_SAFEBAG_pop_free(bag_stack,
- PKCS12_SAFEBAG_free);
- (*failures)++;
- return (-1);
- }
-
- /* Add the key id to the certificate bag. */
- cryptodebug("add key id to PKCS#12 safebag");
- if (!PKCS12_add_localkeyid(bag, id, id_len))
- cryptodebug("error not caught");
-
- /* Add the friendly name to the certificate bag. */
- if ((lab = X509_alias_get0(cert, &lab_len)) != NULL) {
- cryptodebug(
- "label PKCS#12 safebag with friendly name");
- if (!PKCS12_add_friendlyname(bag, (char *)lab,
- lab_len))
- cryptodebug("error not caught");
- }
-
- /* Pile it on the bag_stack. */
- if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
- cryptodebug("error not caught");
-
- n_writes++;
- }
-
- /* Add all the CA chain certs to the bag_stack. */
- if (ca_certs) {
- cryptodebug("adding CA certificate chain to PKCS#12 "
- "safebag");
- /*
- * Go through the stack of CA certs, converting each
- * one to a PKCS#12 bag and piling them onto the
- * bag_stack.
- */
- for (i = 0; i < sk_X509_num(ca_certs); i++) {
- /*
- * sk_X509_value() is macro that embeds a
- * cast to (X509 *). Here it translates
- * into ((X509 *)sk_value((ca_certs), (i))).
- * Lint is complaining about the embedded
- * casting, and to fix it, you need to fix
- * openssl header files.
- */
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- ca = sk_X509_value(ca_certs, i);
-
- /* Convert CA cert to PKCS#12 bag. */
- cryptodebug("adding CA certificate #%d "
- "to PKCS#12 safebag", i+1);
- bag = PKCS12_x5092certbag(ca);
- if (bag == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert CA certificate "
- "#%d to PKCS#12 bag."), i+1);
- /* Cleanup the safebag. */
- sk_PKCS12_SAFEBAG_pop_free(bag_stack,
- PKCS12_SAFEBAG_free);
- (*failures)++;
- return (-1);
- }
-
- /* Note CA certs do not have friendly name. */
-
- /* Pile it onto the bag_stack. */
- if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
- cryptodebug("error not caught");
-
- n_writes++;
- }
- }
-
- /* Turn bag_stack of certs into encrypted authsafe. */
- cryptodebug("encrypt certificate PKCS#12 bag into "
- "PKCS#7 authsafe");
- cert_authsafe = PKCS12_pack_p7encdata(
- NID_pbe_WithSHA1And40BitRC2_CBC, (char *)pin, -1, NULL,
- 0, PKCS12_DEFAULT_ITER, bag_stack);
-
- /* Clear away this bag_stack, we're done with it. */
- sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
- bag_stack = NULL;
-
- if (cert_authsafe == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to PKCS#7-encrypt certificate bag."));
- (*failures)++;
- return (-1);
- }
- }
-
- /*
- * Section 2:
- *
- * The second PKCS#12 container (safebag) will hold the private key
- * that goes with the certificates above. The results of this section
- * is an unencrypted PKCS#7 container (authsafe). If there is no
- * private key, there is no point in creating the "safebag" or the
- * "authsafe" so we go to the next section.
- */
- if (priv_key != NULL) {
- /* Make a PKCS#8 shrouded key bag. */
- cryptodebug("create PKCS#8 shrouded key out of private key");
- p8 = EVP_PKEY2PKCS8(priv_key);
- if (p8 == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to create PKCS#8 shrouded key for "
- "private key."));
- (*failures)++;
- return (-1);
- }
-
- /* Put the shrouded key into a PKCS#12 bag. */
- cryptodebug("convert shrouded key to PKCS#12 bag");
- bag = PKCS12_MAKE_SHKEYBAG(
- NID_pbe_WithSHA1And3_Key_TripleDES_CBC, (char *)pin,
- -1, NULL, 0, PKCS12_DEFAULT_ITER, p8);
-
- /* Clean up the PKCS#8 shrouded key, don't need it now. */
- PKCS8_PRIV_KEY_INFO_free(p8);
- p8 = NULL;
-
- if (bag == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert private key to PKCS#12 bag."));
- (*failures)++;
- return (-1);
- }
-
- /* Add the key id to the certificate bag. */
- cryptodebug("add key id to PKCS#12 safebag");
- if (!PKCS12_add_localkeyid(bag, id, id_len))
- cryptodebug("error not caught");
-
- /* Add the cert friendly name to the private key bag. */
- if (lab != NULL) {
- cryptodebug("label PKCS#12 safebag with friendly name");
- if (!PKCS12_add_friendlyname(bag, (char *)lab, lab_len))
- cryptodebug("error not caught");
- }
-
- /* Start a PKCS#12 safebag container for the private key. */
- cryptodebug("creating private key PKCS#12 safebag");
- bag_stack = sk_PKCS12_SAFEBAG_new_null();
- if (bag_stack == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to create PKCS#12 private key bag."));
- (*failures)++;
- return (-1);
- }
-
- /* Pile on the private key on the bag_stack. */
- if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag))
- cryptodebug("error not caught");
- /* Turn bag_stack with private key into unencrypted authsafe. */
- cryptodebug("put private PKCS#12 bag into PKCS#7 authsafe");
- key_authsafe = PKCS12_pack_p7data(bag_stack);
+#include <kmfapi.h>
- /* Clear away this bag_stack, we're done with it. */
- sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
- bag_stack = NULL;
-
- if (key_authsafe == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to PKCS#7-convert private key bag."));
- (*failures)++;
- return (-1);
- }
-
- n_writes++;
- }
-
- /*
- * Section 3:
- *
- * This is where the two PKCS#7 containers, one for the certificates
- * and one for the private key, are put together into a PKCS#12
- * element. This final PKCS#12 element is written to the export file.
- */
- /* Start a PKCS#7 stack. */
- cryptodebug("create PKCS#7 authsafe for private key and certificates");
- authsafe_stack = sk_PKCS7_new_null();
- if (authsafe_stack == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to create PKCS#7 container for private key "
- "and certificates."));
- (*failures)++;
- return (-1);
- }
-
- /* Put certificates and private key into PKCS#7 stack. */
- if (key_authsafe != NULL) {
- cryptodebug("put private key authsafe into PKCS#7 container");
- if (!sk_PKCS7_push(authsafe_stack, key_authsafe))
- cryptodebug("error not caught");
- }
- if (cert_authsafe != NULL) {
- cryptodebug("put certificate authsafe into PKCS#7 container");
- if (!sk_PKCS7_push(authsafe_stack, cert_authsafe))
- cryptodebug("error not caught");
- }
-
- /* Create PKCS#12 element out of PKCS#7 stack. */
- cryptodebug("create PKCS#12 element for export file");
- p12_elem = PKCS12_init(NID_pkcs7_data);
- if (p12_elem == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to create PKCS#12 element for export file."));
- sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
- (*failures)++;
- return (-1);
- }
-
- /* Put the PKCS#7 stack into the PKCS#12 element. */
- if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack))
- cryptodebug("error not caught");
-
- /* Clear away the PKCS#7 stack, we're done with it. */
- sk_PKCS7_pop_free(authsafe_stack, PKCS7_free);
- authsafe_stack = NULL;
-
- /* Set the integrity MAC on the PKCS#12 element. */
- cryptodebug("setting MAC for PKCS#12 element");
- if (!PKCS12_set_mac(p12_elem, (char *)pin, -1, NULL, 0,
- PKCS12_DEFAULT_ITER, NULL))
- cryptodebug("error not caught");
-
- /* Write the PKCS#12 element to the export file. */
- cryptodebug("writing PKCS#12 element to export file");
- if (!i2d_PKCS12_bio(fbio, p12_elem))
- cryptodebug("error not caught");
-
- (*successes) += n_writes;
-
- /* Clear away the PKCS#12 element. */
- PKCS12_free(p12_elem);
- return (0);
-}
-
-/*
- * Get token objects: private key, its cert, and its cert chain.
- */
-static CK_RV
-get_token_objs(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj,
- CK_OBJECT_HANDLE *mate, CK_OBJECT_HANDLE_PTR *chain,
- CK_ULONG *chain_len, CK_BYTE_PTR *id, CK_ULONG *id_len)
+static KMF_RETURN
+pk_find_export_cert(KMF_HANDLE_T kmfhandle, KMF_FINDCERT_PARAMS *parms,
+ KMF_X509_DER_CERT *cert)
{
- CK_RV rv = CKR_OK;
- CK_ATTRIBUTE keyid_attr[1] = {
- { CKA_ID, NULL, 0 }
- };
- static CK_OBJECT_CLASS class = CKO_CERTIFICATE;
- static CK_CERTIFICATE_TYPE certtype = CKC_X_509;
- CK_ATTRIBUTE cert_attr[4] = {
- { CKA_CLASS, &class, sizeof (CK_OBJECT_CLASS) },
- { CKA_CERTIFICATE_TYPE, &certtype, sizeof (certtype) },
- { CKA_TOKEN, &pk_true, sizeof (pk_true) },
- { CKA_ID, NULL, 0 }
- };
- CK_ULONG num_attr = sizeof (cert_attr) / sizeof (CK_ATTRIBUTE);
- CK_OBJECT_HANDLE cert = ~0UL;
- CK_ULONG num = 0;
-
- cryptodebug("inside get_token_objs");
-
- /* Get the size of the object's CKA_ID field first. */
- cryptodebug("getting CKA_ID size for object 0x%x", obj);
- if ((rv = C_GetAttributeValue(sess, obj, keyid_attr, 1)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext("Unable to get size of object"
- " key id (%s)."), pkcs11_strerror(rv));
- return (rv);
- }
-
- /* Allocate the space needed for the key id. */
- if ((keyid_attr[0].pValue = malloc(keyid_attr[0].ulValueLen)) == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- return (CKR_HOST_MEMORY);
- }
+ KMF_RETURN rv = KMF_OK;
+ uint32_t numcerts = 0;
- /* Get the CKA_ID field to match obj with its cert. */
- cryptodebug("getting CKA_ID attribute for object 0x%x", obj);
- if ((rv = C_GetAttributeValue(sess, obj, keyid_attr, 1)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext("Unable to get object "
- "key id (%s)."), pkcs11_strerror(rv));
- free(keyid_attr[0].pValue);
+ numcerts = 0;
+ (void) memset(cert, 0, sizeof (KMF_X509_DER_CERT));
+ rv = KMF_FindCert(kmfhandle, parms, NULL, &numcerts);
+ if (rv != KMF_OK) {
return (rv);
}
+ if (numcerts == 0) {
+ cryptoerror(LOG_STDERR,
+ gettext("No matching certificates found."));
+ return (KMF_ERR_CERT_NOT_FOUND);
- /* Now try to find any certs that have the same id. */
- cryptodebug("searching for certificates with same CKA_ID");
- cert_attr[3].pValue = keyid_attr[0].pValue;
- cert_attr[3].ulValueLen = keyid_attr[0].ulValueLen;
- if ((rv = C_FindObjectsInit(sess, cert_attr, num_attr)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext("Unable to initialize "
- "certificate search (%s)."), pkcs11_strerror(rv));
- free(keyid_attr[0].pValue);
- return (rv);
- }
+ } else if (numcerts == 1) {
+ rv = KMF_FindCert(kmfhandle, parms, cert, &numcerts);
- /* Find the first cert that matches the key id. */
- if ((rv = C_FindObjects(sess, &cert, 1, &num)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext("Certificate search failed "
- "(%s)."), pkcs11_strerror(rv));
- free(keyid_attr[0].pValue);
- return (rv);
+ } else if (numcerts > 1) {
+ cryptoerror(LOG_STDERR,
+ gettext("%d certificates found, refine the "
+ "search parameters to eliminate ambiguity\n"),
+ numcerts);
+ return (KMF_ERR_BAD_PARAMETER);
}
-
- (void) C_FindObjectsFinal(sess);
-
- *id = keyid_attr[0].pValue;
- *id_len = keyid_attr[0].ulValueLen;
-
- *mate = (num == 1) ? cert : ~0UL;
-
- /* We currently do not find all the certs in the chain. */
- *chain_len = 0;
- *chain = NULL;
-
- return (CKR_OK);
+ return (rv);
}
-/*
- * Converts PKCS#11 biginteger_t format to OpenSSL BIGNUM.
- * "to" should be the address of a ptr init'ed to NULL to
- * receive the BIGNUM, e.g.,
- * biginteger_t from;
- * BIGNUM *foo = NULL;
- * cvt_bigint2bn(&from, &foo);
- */
-static int
-cvt_bigint2bn(biginteger_t *from, BIGNUM **to)
+static KMF_RETURN
+pk_export_file_objects(KMF_HANDLE_T kmfhandle, int oclass,
+ char *issuer, char *subject, KMF_BIGINT *serial,
+ KMF_ENCODE_FORMAT ofmt,
+ char *dir, char *infile, char *filename)
{
- BIGNUM *temp = NULL;
-
- cryptodebug("inside cvt_bigint2bn");
-
- if (from == NULL || to == NULL)
- return (-1);
-
- cryptodebug("calling BN_bin2bn");
- if ((temp = BN_bin2bn(from->big_value, from->big_value_len, *to)) ==
- NULL)
- return (-1);
-
- *to = temp;
- return (0);
+ KMF_RETURN rv = KMF_OK;
+ KMF_STORECERT_PARAMS scparms;
+ KMF_X509_DER_CERT kmfcert;
+
+ /* If searching for public objects or certificates, find certs now */
+ if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
+ KMF_FINDCERT_PARAMS fcargs;
+
+ (void) memset(&fcargs, 0, sizeof (fcargs));
+ fcargs.kstype = KMF_KEYSTORE_OPENSSL;
+ fcargs.certLabel = NULL;
+ fcargs.issuer = issuer;
+ fcargs.subject = subject;
+ fcargs.serial = serial;
+ fcargs.sslparms.dirpath = dir;
+ fcargs.sslparms.certfile = infile;
+ fcargs.sslparms.format = ofmt;
+
+ rv = pk_find_export_cert(kmfhandle, &fcargs, &kmfcert);
+ if (rv == KMF_OK) {
+ (void) memset(&scparms, 0, sizeof (scparms));
+ scparms.kstype = KMF_KEYSTORE_OPENSSL;
+ scparms.sslparms.certfile = filename;
+ rv = KMF_StoreCert(kmfhandle, &scparms,
+ &kmfcert.certificate);
+
+ KMF_FreeKMFCert(kmfhandle, &kmfcert);
+ }
+ }
+ return (rv);
}
-/*
- * Convert PKCS#11 RSA private key to OpenSSL EVP_PKEY structure.
- */
-static CK_RV
-cvt_rsa2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
+static KMF_RETURN
+pk_export_pk12_nss(KMF_HANDLE_T kmfhandle,
+ char *token_spec, char *dir, char *prefix,
+ char *certlabel, char *issuer, char *subject,
+ KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred,
+ char *filename)
{
- CK_RV rv = CKR_OK;
- EVP_PKEY *key = NULL; /* OpenSSL representation */
- RSA *rsa = NULL; /* OpenSSL representation */
- biginteger_t mod = { NULL, 0 }; /* required */
- biginteger_t pubexp = { NULL, 0 }; /* required */
- biginteger_t priexp = { NULL, 0 }; /* optional */
- biginteger_t prime1 = { NULL, 0 }; /* optional */
- biginteger_t prime2 = { NULL, 0 }; /* optional */
- biginteger_t exp1 = { NULL, 0 }; /* optional */
- biginteger_t exp2 = { NULL, 0 }; /* optional */
- biginteger_t coef = { NULL, 0 }; /* optional */
- CK_ATTRIBUTE rsa_pri_attrs[8] = {
- { CKA_MODULUS, NULL, 0 },
- { CKA_PUBLIC_EXPONENT, NULL, 0 },
- { CKA_PRIVATE_EXPONENT, NULL, 0 }, /* optional */
- { CKA_PRIME_1, NULL, 0 }, /* | */
- { CKA_PRIME_2, NULL, 0 }, /* | */
- { CKA_EXPONENT_1, NULL, 0 }, /* | */
- { CKA_EXPONENT_2, NULL, 0 }, /* | */
- { CKA_COEFFICIENT, NULL, 0 } /* V */
- };
- CK_ULONG count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
- int i;
-
- cryptodebug("inside cvt_rsa2evp_pkey");
-
- cryptodebug("calling RSA_new");
- if ((rsa = RSA_new()) == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to allocate internal RSA structure."));
- return (CKR_HOST_MEMORY);
- }
+ KMF_RETURN rv = KMF_OK;
+ KMF_EXPORTP12_PARAMS p12parms;
- /* Get the sizes of the attributes we need. */
- cryptodebug("calling C_GetAttributeValue for size info");
- if ((rv = C_GetAttributeValue(sess, obj, rsa_pri_attrs, count)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get RSA private key attribute sizes (%s)."),
- pkcs11_strerror(rv));
+ rv = configure_nss(kmfhandle, dir, prefix);
+ if (rv != KMF_OK)
return (rv);
- }
- /* Allocate memory for each attribute. */
- for (i = 0; i < count; i++) {
- if (rsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
- rsa_pri_attrs[i].ulValueLen == 0) {
- cryptodebug("cvt_rsa2evp_pkey: *** should not happen");
- rsa_pri_attrs[i].ulValueLen = 0;
- continue;
- }
- if ((rsa_pri_attrs[i].pValue =
- malloc(rsa_pri_attrs[i].ulValueLen)) == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- return (CKR_HOST_MEMORY);
- }
- }
+ (void) memset(&p12parms, 0, sizeof (p12parms));
+ if (token_spec == NULL)
+ token_spec = DEFAULT_NSS_TOKEN;
- /* Now really get the attributes. */
- cryptodebug("calling C_GetAttributeValue for attribute info");
- if ((rv = C_GetAttributeValue(sess, obj, rsa_pri_attrs, count)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get RSA private key attributes (%s)."),
- pkcs11_strerror(rv));
- return (rv);
- }
+ p12parms.kstype = KMF_KEYSTORE_NSS;
+ p12parms.certLabel = certlabel;
+ p12parms.issuer = issuer;
+ p12parms.subject = subject;
+ p12parms.serial = serial;
+ p12parms.idstr = NULL;
+ if (tokencred != NULL)
+ p12parms.cred = *tokencred;
+ p12parms.nssparms.slotlabel = token_spec;
- /*
- * Fill in all the temp variables. Modulus and public exponent
- * are required. The rest are optional.
- */
- i = 0;
- copy_attr_to_bigint(&(rsa_pri_attrs[i++]), &mod);
- copy_attr_to_bigint(&(rsa_pri_attrs[i++]), &pubexp);
-
- if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
- rsa_pri_attrs[i].ulValueLen != 0)
- copy_attr_to_bigint(&(rsa_pri_attrs[i]), &priexp);
- i++;
-
- if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
- rsa_pri_attrs[i].ulValueLen != 0)
- copy_attr_to_bigint(&(rsa_pri_attrs[i]), &prime1);
- i++;
-
- if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
- rsa_pri_attrs[i].ulValueLen != 0)
- copy_attr_to_bigint(&(rsa_pri_attrs[i]), &prime2);
- i++;
-
- if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
- rsa_pri_attrs[i].ulValueLen != 0)
- copy_attr_to_bigint(&(rsa_pri_attrs[i]), &exp1);
- i++;
-
- if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
- rsa_pri_attrs[i].ulValueLen != 0)
- copy_attr_to_bigint(&(rsa_pri_attrs[i]), &exp2);
- i++;
-
- if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 &&
- rsa_pri_attrs[i].ulValueLen != 0)
- copy_attr_to_bigint(&(rsa_pri_attrs[i]), &coef);
- i++;
-
- /* Start the conversion to internal OpenSSL RSA structure. */
-
- /* Modulus n */
- if (cvt_bigint2bn(&mod, &(rsa->n)) < 0) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert RSA private key modulus."));
- return (CKR_GENERAL_ERROR);
- }
+ (void) get_pk12_password(&p12parms.p12cred);
- /* Public exponent e */
- if (cvt_bigint2bn(&pubexp, &(rsa->e)) < 0) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert RSA private key public exponent."));
- return (CKR_GENERAL_ERROR);
- }
+ rv = KMF_ExportPK12(kmfhandle, &p12parms, filename);
+ if (p12parms.p12cred.cred)
+ free(p12parms.p12cred.cred);
- /* Private exponent e */
- if (priexp.big_value != NULL) {
- if (cvt_bigint2bn(&priexp, &(rsa->d)) < 0) {
- cryptoerror(LOG_STDERR, gettext("Unable to convert "
- "RSA private key private exponent."));
- return (CKR_GENERAL_ERROR);
- }
- } else
- cryptodebug("no RSA private key private exponent");
-
- /* Prime p */
- if (prime1.big_value != NULL) {
- if (cvt_bigint2bn(&prime1, &(rsa->p)) < 0) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert RSA private key prime 1."));
- return (CKR_GENERAL_ERROR);
- }
- } else
- cryptodebug("no RSA private key prime 1");
-
- /* Prime q */
- if (prime2.big_value != NULL) {
- if (cvt_bigint2bn(&prime2, &(rsa->q)) < 0) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert RSA private key prime 2."));
- return (CKR_GENERAL_ERROR);
- }
- } else
- cryptodebug("no RSA private key prime 2");
-
- /* Private exponent d modulo p-1 */
- if (exp1.big_value != NULL) {
- if (cvt_bigint2bn(&exp1, &(rsa->dmp1)) < 0) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert RSA private key exponent 1."));
- return (CKR_GENERAL_ERROR);
- }
- } else
- cryptodebug("no RSA private key exponent 1");
-
- /* Private exponent d modulo q-1 */
- if (exp2.big_value != NULL) {
- if (cvt_bigint2bn(&exp2, &(rsa->dmq1)) < 0) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert RSA private key exponent 2."));
- return (CKR_GENERAL_ERROR);
- }
- } else
- cryptodebug("no RSA private key exponent 2");
-
- /* CRT coefficient q-inverse mod p */
- if (coef.big_value != NULL) {
- if (cvt_bigint2bn(&coef, &(rsa->iqmp)) < 0) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert RSA private key coefficient."));
- return (CKR_GENERAL_ERROR);
- }
- } else
- cryptodebug("no RSA private key coefficient");
-
- /* Create OpenSSL EVP_PKEY struct in which to stuff RSA struct. */
- cryptodebug("calling EVP_PKEY_new");
- if ((key = EVP_PKEY_new()) == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to allocate internal EVP_PKEY structure."));
- return (CKR_HOST_MEMORY);
- }
-
- /* Put the RSA struct into the EVP_PKEY struct and return it. */
- cryptodebug("calling EVP_PKEY_set1_RSA");
- (void) EVP_PKEY_set1_RSA(key, rsa);
-
- *pk = key;
- return (CKR_OK);
+ return (rv);
}
-/*
- * Convert PKCS#11 DSA private key to OpenSSL EVP_PKEY structure.
- */
-static CK_RV
-cvt_dsa2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
+static KMF_RETURN
+pk_export_pk12_files(KMF_HANDLE_T kmfhandle,
+ char *certfile, char *keyfile, char *dir,
+ char *outfile)
{
- CK_RV rv = CKR_OK;
- EVP_PKEY *key = NULL; /* OpenSSL representation */
- DSA *dsa = NULL; /* OpenSSL representation */
- biginteger_t prime = { NULL, 0 }; /* required */
- biginteger_t subprime = { NULL, 0 }; /* required */
- biginteger_t base = { NULL, 0 }; /* required */
- biginteger_t value = { NULL, 0 }; /* required */
- CK_ATTRIBUTE dsa_pri_attrs[4] = {
- { CKA_PRIME, NULL, 0 },
- { CKA_SUBPRIME, NULL, 0 },
- { CKA_BASE, NULL, 0 },
- { CKA_VALUE, NULL, 0 }
- };
- CK_ULONG count = sizeof (dsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
- int i;
-
- cryptodebug("inside cvt_dsa2evp_pkey");
-
- cryptodebug("calling DSA_new");
- if ((dsa = DSA_new()) == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to allocate internal DSA structure."));
- return (CKR_HOST_MEMORY);
- }
-
- /* Get the sizes of the attributes we need. */
- cryptodebug("calling C_GetAttributeValue for size info");
- if ((rv = C_GetAttributeValue(sess, obj, dsa_pri_attrs, count)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get DSA private key object attributes (%s)."),
- pkcs11_strerror(rv));
- return (rv);
- }
-
- /* Allocate memory for each attribute. */
- for (i = 0; i < count; i++) {
- if (dsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
- dsa_pri_attrs[i].ulValueLen == 0) {
- cryptodebug("cvt_dsa2evp_pkey: *** should not happen");
- dsa_pri_attrs[i].ulValueLen = 0;
- continue;
- }
- if ((dsa_pri_attrs[i].pValue =
- malloc(dsa_pri_attrs[i].ulValueLen)) == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- return (CKR_HOST_MEMORY);
- }
- }
-
- /* Now really get the attributes. */
- cryptodebug("calling C_GetAttributeValue for attribute info");
- if ((rv = C_GetAttributeValue(sess, obj, dsa_pri_attrs, count)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get DSA private key attributes (%s)."),
- pkcs11_strerror(rv));
- return (rv);
- }
-
- /* Fill in all the temp variables. They are all required. */
- i = 0;
- copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &prime);
- copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &subprime);
- copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &base);
- copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &value);
-
- /* Start the conversion to internal OpenSSL DSA structure. */
+ KMF_RETURN rv;
+ KMF_EXPORTP12_PARAMS p12parms;
- /* Prime p */
- if (cvt_bigint2bn(&prime, &(dsa->p)) < 0) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert DSA private key prime."));
- return (CKR_GENERAL_ERROR);
- }
+ (void) memset(&p12parms, 0, sizeof (p12parms));
- /* Subprime q */
- if (cvt_bigint2bn(&subprime, &(dsa->q)) < 0) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert DSA private key subprime."));
- return (CKR_GENERAL_ERROR);
- }
+ p12parms.kstype = KMF_KEYSTORE_OPENSSL;
+ p12parms.certLabel = NULL;
+ p12parms.issuer = NULL;
+ p12parms.subject = NULL;
+ p12parms.serial = 0;
+ p12parms.idstr = NULL;
+ p12parms.sslparms.dirpath = dir;
+ p12parms.sslparms.certfile = certfile;
+ p12parms.sslparms.keyfile = keyfile;
- /* Base g */
- if (cvt_bigint2bn(&base, &(dsa->g)) < 0) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert DSA private key base."));
- return (CKR_GENERAL_ERROR);
- }
+ (void) get_pk12_password(&p12parms.p12cred);
- /* Private key x */
- if (cvt_bigint2bn(&value, &(dsa->priv_key)) < 0) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert DSA private key value."));
- return (CKR_GENERAL_ERROR);
- }
+ rv = KMF_ExportPK12(kmfhandle, &p12parms, outfile);
- /* Create OpenSSL EVP PKEY struct in which to stuff DSA struct. */
- cryptodebug("calling EVP_PKEY_new");
- if ((key = EVP_PKEY_new()) == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to allocate internal EVP_PKEY structure."));
- return (CKR_HOST_MEMORY);
- }
-
- /* Put the DSA struct into the EVP_PKEY struct and return it. */
- cryptodebug("calling EVP_PKEY_set1_DSA");
- (void) EVP_PKEY_set1_DSA(key, dsa);
+ if (p12parms.p12cred.cred)
+ free(p12parms.p12cred.cred);
- *pk = key;
- return (CKR_OK);
+ return (rv);
}
-/*
- * Convert PKCS#11 DH private key to OpenSSL EVP_PKEY structure.
- */
-static CK_RV
-cvt_dh2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
+static KMF_RETURN
+pk_export_nss_objects(KMF_HANDLE_T kmfhandle, char *token_spec,
+ int oclass, char *certlabel, char *issuer, char *subject,
+ KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, char *dir,
+ char *prefix, char *filename)
{
- CK_RV rv = CKR_OK;
- EVP_PKEY *key = NULL; /* OpenSSL representation */
- DH *dh = NULL; /* OpenSSL representation */
- biginteger_t prime = { NULL, 0 }; /* required */
- biginteger_t base = { NULL, 0 }; /* required */
- biginteger_t value = { NULL, 0 }; /* required */
- CK_ATTRIBUTE dh_pri_attrs[3] = {
- { CKA_PRIME, NULL, 0 },
- { CKA_BASE, NULL, 0 },
- { CKA_VALUE, NULL, 0 }
- };
- CK_ULONG count = sizeof (dh_pri_attrs) / sizeof (CK_ATTRIBUTE);
- int i;
-
- cryptodebug("inside cvt_dh2evp_pkey");
-
- cryptodebug("calling DH_new");
- if ((dh = DH_new()) == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to allocate internal DH structure."));
- return (CKR_HOST_MEMORY);
- }
+ KMF_RETURN rv = KMF_OK;
+ KMF_STORECERT_PARAMS scparms;
+ KMF_X509_DER_CERT kmfcert;
- /* Get the sizes of the attributes we need. */
- cryptodebug("calling C_GetAttributeValue for size info");
- if ((rv = C_GetAttributeValue(sess, obj, dh_pri_attrs, count)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get DH private key object attributes (%s)."),
- pkcs11_strerror(rv));
+ rv = configure_nss(kmfhandle, dir, prefix);
+ if (rv != KMF_OK)
return (rv);
- }
- /* Allocate memory for each attribute. */
- for (i = 0; i < count; i++) {
- if (dh_pri_attrs[i].ulValueLen == (CK_ULONG)-1 ||
- dh_pri_attrs[i].ulValueLen == 0) {
- cryptodebug("cvt_dh2evp_pkey: ***should not happen");
- dh_pri_attrs[i].ulValueLen = 0;
- continue;
- }
- if ((dh_pri_attrs[i].pValue =
- malloc(dh_pri_attrs[i].ulValueLen)) == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- return (CKR_HOST_MEMORY);
+ /* If searching for public objects or certificates, find certs now */
+ if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
+ KMF_FINDCERT_PARAMS fcargs;
+
+ (void) memset(&fcargs, 0, sizeof (fcargs));
+ fcargs.kstype = KMF_KEYSTORE_NSS;
+ fcargs.certLabel = certlabel;
+ fcargs.issuer = issuer;
+ fcargs.subject = subject;
+ fcargs.serial = serial;
+ fcargs.nssparms.slotlabel = token_spec;
+
+ rv = pk_find_export_cert(kmfhandle, &fcargs, &kmfcert);
+ if (rv == KMF_OK) {
+ (void) memset(&scparms, 0, sizeof (scparms));
+ scparms.kstype = KMF_KEYSTORE_OPENSSL;
+ scparms.sslparms.certfile = filename;
+ scparms.sslparms.format = kfmt;
+
+ rv = KMF_StoreCert(kmfhandle, &scparms,
+ &kmfcert.certificate);
+
+ KMF_FreeKMFCert(kmfhandle, &kmfcert);
}
}
+ return (rv);
+}
- /* Now really get the attributes. */
- cryptodebug("calling C_GetAttributeValue for attribute info");
- if ((rv = C_GetAttributeValue(sess, obj, dh_pri_attrs, count)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get DH private key attributes (%s)."),
- pkcs11_strerror(rv));
- return (rv);
- }
-
- /* Fill in all the temp variables. They are all required. */
- i = 0;
- copy_attr_to_bigint(&(dh_pri_attrs[i++]), &prime);
- copy_attr_to_bigint(&(dh_pri_attrs[i++]), &base);
- copy_attr_to_bigint(&(dh_pri_attrs[i++]), &value);
-
- /* Start the conversion to internal OpenSSL DH structure. */
+static KMF_RETURN
+pk_export_pk12_pk11(KMF_HANDLE_T kmfhandle, char *token_spec,
+ char *certlabel, char *issuer, char *subject,
+ KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred, char *filename)
+{
+ KMF_RETURN rv = KMF_OK;
+ KMF_EXPORTP12_PARAMS p12parms;
- /* Prime p */
- if (cvt_bigint2bn(&prime, &(dh->p)) < 0) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert DH private key prime."));
- return (CKR_GENERAL_ERROR);
+ rv = select_token(kmfhandle, token_spec, TRUE);
+ if (rv != KMF_OK) {
+ return (rv);
}
- /* Base g */
- if (cvt_bigint2bn(&base, &(dh->g)) < 0) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert DH private key base."));
- return (CKR_GENERAL_ERROR);
- }
+ (void) memset(&p12parms, 0, sizeof (p12parms));
- /* Private value x */
- if (cvt_bigint2bn(&value, &(dh->priv_key)) < 0) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert DH private key value."));
- return (CKR_GENERAL_ERROR);
- }
+ p12parms.kstype = KMF_KEYSTORE_PK11TOKEN;
+ p12parms.certLabel = certlabel;
+ p12parms.issuer = issuer;
+ p12parms.subject = subject;
+ p12parms.serial = serial;
+ p12parms.idstr = NULL;
+ if (tokencred != NULL)
+ p12parms.cred = *tokencred;
+ (void) get_pk12_password(&p12parms.p12cred);
- /* Create OpenSSL EVP PKEY struct in which to stuff DH struct. */
- cryptodebug("calling EVP_PKEY_new");
- if ((key = EVP_PKEY_new()) == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to allocate internal EVP_PKEY structure."));
- return (CKR_HOST_MEMORY);
- }
+ rv = KMF_ExportPK12(kmfhandle, &p12parms, filename);
- /* Put the DH struct into the EVP_PKEY struct and return it. */
- cryptodebug("calling EVP_PKEY_set1_DH");
- (void) EVP_PKEY_set1_DH(key, dh);
+ if (p12parms.p12cred.cred)
+ free(p12parms.p12cred.cred);
- *pk = key;
- return (CKR_OK);
+ return (rv);
}
-/*
- * Convert PKCS#11 private key object to OpenSSL EVP_PKEY structure.
- */
-static CK_RV
-cvt_obj2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
+static KMF_RETURN
+pk_export_pk11_objects(KMF_HANDLE_T kmfhandle, char *token_spec,
+ char *certlabel, char *issuer, char *subject,
+ KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt,
+ char *filename)
{
- CK_RV rv = CKR_OK;
- static CK_KEY_TYPE keytype = 0;
- CK_ATTRIBUTE keytype_attr[1] = {
- { CKA_KEY_TYPE, &keytype, sizeof (keytype) }
- };
-
- cryptodebug("inside cvt_obj2evp_pkey");
-
- /* Find out the key type to do the right conversion. */
- cryptodebug("calling C_GetAttributeValue");
- if ((rv = C_GetAttributeValue(sess, obj, keytype_attr, 1)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get token object key type (%s)."),
- pkcs11_strerror(rv));
- return (rv);
- }
+ KMF_RETURN rv = KMF_OK;
+ KMF_FINDCERT_PARAMS fcparms;
+ KMF_STORECERT_PARAMS scparms;
+ KMF_X509_DER_CERT kmfcert;
- switch (keytype) {
- case CKK_RSA:
- cryptodebug("converting RSA key");
- return (cvt_rsa2evp_pkey(sess, obj, pk));
- case CKK_DSA:
- cryptodebug("converting DSA key");
- return (cvt_dsa2evp_pkey(sess, obj, pk));
- case CKK_DH:
- cryptodebug("converting DH key");
- return (cvt_dh2evp_pkey(sess, obj, pk));
- default:
- cryptoerror(LOG_STDERR, gettext(
- "Private key type 0x%02x conversion not supported."),
- keytype);
- return (CKR_GENERAL_ERROR);
- }
-}
-
-/*
- * Convert PKCS#11 certificate object to OpenSSL X509 structure.
- */
-static CK_RV
-cvt_cert2x509(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, X509 **c)
-{
- CK_RV rv = CKR_OK;
- X509 *cert = NULL; /* OpenSSL representation */
- X509 *temp_cert = NULL;
- CK_BYTE *subject = NULL;
- CK_ULONG subject_len = 0;
- CK_BYTE *value = NULL;
- CK_ULONG value_len = 0;
- CK_BYTE *label = NULL;
- CK_ULONG label_len = 0;
- CK_BYTE *id = NULL;
- CK_ULONG id_len = 0;
- CK_BYTE *issuer = NULL;
- CK_ULONG issuer_len = 0;
- CK_BYTE *serial = NULL;
- CK_ULONG serial_len = 0;
- CK_ATTRIBUTE cert_attrs[6] = {
- { CKA_SUBJECT, NULL, 0 }, /* required */
- { CKA_VALUE, NULL, 0 }, /* required */
- { CKA_LABEL, NULL, 0 }, /* optional */
- { CKA_ID, NULL, 0 }, /* optional */
- { CKA_ISSUER, NULL, 0 }, /* optional */
- { CKA_SERIAL_NUMBER, NULL, 0 } /* optional */
- };
- CK_ULONG count = sizeof (cert_attrs) / sizeof (CK_ATTRIBUTE);
- int i = 0;
- X509_NAME *ssl_subject = NULL;
- X509_NAME *ssl_issuer = NULL;
- ASN1_INTEGER *ssl_serial = NULL;
-
- cryptodebug("inside cvt_cert2x509");
-
- cryptodebug("calling X509_new");
- if ((cert = X509_new()) == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to allocate internal X509 structure."));
- return (CKR_HOST_MEMORY);
- }
+ rv = select_token(kmfhandle, token_spec, TRUE);
- /* Get the sizes of the attributes we need. */
- cryptodebug("calling C_GetAttributeValue for size info");
- if ((rv = C_GetAttributeValue(sess, obj, cert_attrs, count)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get certificate attribute sizes (%s)."),
- pkcs11_strerror(rv));
+ if (rv != KMF_OK) {
return (rv);
}
- /* Allocate memory for each attribute. */
- for (i = 0; i < count; i++) {
- if (cert_attrs[i].ulValueLen == (CK_ULONG)-1 ||
- cert_attrs[i].ulValueLen == 0) {
- cryptodebug("cvt_cert2x509: *** should not happen");
- cert_attrs[i].ulValueLen = 0;
- continue;
- }
- if ((cert_attrs[i].pValue = malloc(cert_attrs[i].ulValueLen))
- == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- return (CKR_HOST_MEMORY);
- }
- }
+ (void) memset(&fcparms, 0, sizeof (fcparms));
+ fcparms.kstype = KMF_KEYSTORE_PK11TOKEN;
+ fcparms.certLabel = certlabel;
+ fcparms.issuer = issuer;
+ fcparms.subject = subject;
+ fcparms.serial = serial;
- /* Now really get the attributes. */
- cryptodebug("calling C_GetAttributeValue for attribute info");
- if ((rv = C_GetAttributeValue(sess, obj, cert_attrs, count)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get certificate attributes (%s)."),
- pkcs11_strerror(rv));
- return (rv);
- }
-
- /*
- * Fill in all the temp variables. Subject and value are required.
- * The rest are optional.
- */
- i = 0;
- copy_attr_to_string(&(cert_attrs[i++]), &subject, &subject_len);
- copy_attr_to_string(&(cert_attrs[i++]), &value, &value_len);
-
- if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 &&
- cert_attrs[i].ulValueLen != 0)
- copy_attr_to_string(&(cert_attrs[i]), &label, &label_len);
- i++;
-
- if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 &&
- cert_attrs[i].ulValueLen != 0)
- copy_attr_to_string(&(cert_attrs[i]), &id, &id_len);
- i++;
-
- if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 &&
- cert_attrs[i].ulValueLen != 0)
- copy_attr_to_string(&(cert_attrs[i]), &issuer, &issuer_len);
- i++;
-
- if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 &&
- cert_attrs[i].ulValueLen != 0)
- copy_attr_to_string(&(cert_attrs[i]), &serial, &serial_len);
- i++;
-
- /* Start the conversion to internal OpenSSL X509 structure. */
-
- /* Subject name (required) */
- cryptodebug("calling d2i_X509_NAME for subject name");
- if ((ssl_subject = d2i_X509_NAME(NULL,
- (const unsigned char **) &subject, subject_len)) == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert certificate subject name."));
- return (CKR_GENERAL_ERROR);
- }
- cryptodebug("calling X509_set_subject_name");
- if (!X509_set_subject_name(cert, ssl_subject)) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to pack certificate subject name entries."));
- return (CKR_GENERAL_ERROR);
- }
-
- /* Label (optional) */
- cryptodebug("calling X509_alias_set1");
- if (!X509_alias_set1(cert, label, label_len))
- cryptodebug("error not caught");
-
- /* Id (optional) */
- cryptodebug("calling X509_keyid_set1");
- if (!X509_keyid_set1(cert, id, id_len))
- cryptodebug("error not caught");
-
- /* Issuer name (optional) */
- cryptodebug("calling d2i_X509_NAME for issuer name");
- if ((ssl_issuer = d2i_X509_NAME(NULL, (const unsigned char **) &issuer,
- issuer_len)) == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert certificate issuer name."));
- return (CKR_GENERAL_ERROR);
- }
- cryptodebug("calling X509_set_issuer_name");
- if (!X509_set_issuer_name(cert, ssl_issuer)) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to pack certificate issuer name entries."));
- return (CKR_GENERAL_ERROR);
- }
-
- /* Serial number (optional) */
- cryptodebug("calling OPENSSL_malloc() for serial number");
- if ((ssl_serial = OPENSSL_malloc(sizeof (ASN1_INTEGER))) == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert certificate serial number."));
- return (CKR_HOST_MEMORY);
- }
- ssl_serial->length = serial_len;
- ssl_serial->type = (serial[0] & 0x80) ? V_ASN1_NEG_INTEGER :
- V_ASN1_INTEGER;
- ssl_serial->data = serial;
- ssl_serial->flags = 0;
- cryptodebug("calling X509_set_serialNumber");
- if (!X509_set_serialNumber(cert, ssl_serial))
- cryptodebug("error not caught");
-
- /*
- * Value (required)
- *
- * The rest of this code takes the CKA_VALUE attribute, converts
- * it into a temp OpenSSL X509 structure and picks out the rest
- * of the fields we need to convert it back into the current X509
- * structure that will get exported. The reason we don't just
- * start with CKA_VALUE is because while the object was in the
- * softtoken, it is possible that some of its attributes changed.
- * Those changes would not appear in CKA_VALUE and would be lost
- * if we started with CKA_VALUE that was saved originally.
- */
- cryptodebug("calling d2i_X509 for cert value");
- if ((temp_cert = d2i_X509(NULL, (const unsigned char **) &value,
- value_len)) == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert main certificate values."));
- return (CKR_GENERAL_ERROR);
- }
-
- /* Transfer these values from temp_cert to cert. */
- cryptodebug("calling X509_set_version/X509_get_version");
- if (!X509_set_version(cert, X509_get_version(temp_cert)))
- cryptodebug("error not caught");
-
- cryptodebug("calling X509_set_notBefore/X509_get_notBefore");
- if (!X509_set_notBefore(cert, X509_get_notBefore(temp_cert)))
- cryptodebug("error not caught");
-
- cryptodebug("calling X509_set_notAfter/X509_get_notAfter");
- if (!X509_set_notAfter(cert, X509_get_notAfter(temp_cert)))
- cryptodebug("error not caught");
-
- cryptodebug("calling X509_set_pubkey/X509_get_pubkey");
- if (!X509_set_pubkey(cert, X509_get_pubkey(temp_cert)))
- cryptodebug("error not caught");
-
- /*
- * These don't get transfered from temp_cert to cert.
- * It -appears- that they may get regenerated as needed.
- *
- * cert->cert_info->signature = dup(temp_cert->cert_info->signature);
- * cert->sig_alg = dup(temp_cert->sig_alg);
- * cert->signature = dup(temp_cert->signature);
- * cert->skid = dup(temp_cert->skid);
- * cert->akid = dup(temp_cert->akid);
- */
-
- *c = cert;
- return (CKR_OK);
-}
-
-static CK_RV
-convert_token_objs(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj,
- CK_OBJECT_HANDLE mate, CK_OBJECT_HANDLE *chain, CK_ULONG chain_len,
- EVP_PKEY **priv_key, X509 **cert, STACK_OF(X509) **ca)
-{
- CK_RV rv = CKR_OK;
- EVP_PKEY *pk = NULL;
- X509 *c = NULL;
- X509 *one_ca = NULL;
- STACK_OF(X509) *ch = NULL;
- int i;
+ rv = pk_find_export_cert(kmfhandle, &fcparms, &kmfcert);
- cryptodebug("inside convert_token_objs");
+ if (rv == KMF_OK) {
+ (void) memset(&scparms, 0, sizeof (scparms));
+ scparms.kstype = KMF_KEYSTORE_OPENSSL;
+ scparms.sslparms.certfile = filename;
+ scparms.sslparms.format = kfmt;
- if ((rv = cvt_obj2evp_pkey(sess, obj, &pk)) != CKR_OK)
- return (rv);
-
- if (mate != ~0UL) {
- cryptodebug("converting cert corresponding to private key");
- if ((rv = cvt_cert2x509(sess, mate, &c)) != CKR_OK)
- return (rv);
- }
+ rv = KMF_StoreCert(kmfhandle, &scparms,
+ &kmfcert.certificate);
- if (chain_len != 0) {
- cryptodebug("converting ca chain of %d certs corresponding "
- "to private key", chain_len);
- ch = sk_X509_new_null();
- for (i = 0; i < chain_len; i++) {
- if ((rv = cvt_cert2x509(sess, chain[i], &one_ca)) !=
- CKR_OK) {
- return (rv);
- }
- if (!sk_X509_push(ch, one_ca))
- cryptodebug("error not caught");
- }
+ KMF_FreeKMFCert(kmfhandle, &kmfcert);
}
-
- *priv_key = pk;
- *cert = (mate != ~0UL) ? c : NULL;
- *ca = (chain_len != 0) ? ch : NULL;
- return (CKR_OK);
+ return (rv);
}
/*
- * Export objects from token to PKCS#12 file.
+ * Export objects from one keystore to a file.
*/
int
pk_export(int argc, char *argv[])
@@ -1210,231 +304,263 @@ pk_export(int argc, char *argv[])
extern int optind_av;
extern char *optarg_av;
char *token_spec = NULL;
- char *token_name = NULL;
- char *manuf_id = NULL;
- char *serial_no = NULL;
- char full_name[FULL_NAME_LEN];
char *filename = NULL;
- CK_SLOT_ID slot_id;
- CK_FLAGS pin_state;
- CK_UTF8CHAR_PTR pin = NULL;
- CK_ULONG pinlen = 0;
- CK_UTF8CHAR_PTR pk12pin = NULL;
- CK_ULONG pk12pinlen = 0;
- CK_SESSION_HANDLE sess;
- BIO *fbio = NULL;
- EVP_PKEY *priv_key = NULL;
- X509 *cert = NULL;
- STACK_OF(X509) *ca = NULL;
- CK_RV rv = CKR_OK;
- CK_OBJECT_HANDLE *objs = NULL;
- CK_ULONG num_objs = 0;
- CK_OBJECT_HANDLE mate = ~0UL;
- CK_OBJECT_HANDLE *chain = NULL;
- CK_ULONG chain_len;
- CK_BYTE *id = NULL;
- CK_ULONG id_len = 0;
- int i = 0;
- int good_ones = 0, bad_ones = 0; /* running totals */
-
- cryptodebug("inside pk_export");
+ char *dir = NULL;
+ char *prefix = NULL;
+ char *certlabel = NULL;
+ char *subject = NULL;
+ char *issuer = NULL;
+ char *infile = NULL;
+ char *keyfile = NULL;
+ char *certfile = NULL;
+ char *serstr = NULL;
+ KMF_KEYSTORE_TYPE kstype = 0;
+ KMF_ENCODE_FORMAT kfmt = KMF_FORMAT_PKCS12;
+ KMF_RETURN rv = KMF_OK;
+ int oclass = PK_CERT_OBJ;
+ KMF_BIGINT serial = { NULL, 0 };
+ KMF_HANDLE_T kmfhandle = NULL;
+ KMF_CREDENTIAL tokencred = {NULL, 0};
/* Parse command line options. Do NOT i18n/l10n. */
- while ((opt = getopt_av(argc, argv, "T:(token)o:(outfile)")) != EOF) {
+ while ((opt = getopt_av(argc, argv,
+ "k:(keystore)y:(objtype)T:(token)"
+ "d:(dir)p:(prefix)"
+ "l:(label)n:(nickname)s:(subject)"
+ "i:(issuer)S:(serial)"
+ "K:(keyfile)c:(certfile)"
+ "F:(outformat)"
+ "I:(infile)o:(outfile)")) != EOF) {
+ if (EMPTYSTRING(optarg_av))
+ return (PK_ERR_USAGE);
switch (opt) {
+ case 'k':
+ kstype = KS2Int(optarg_av);
+ if (kstype == 0)
+ return (PK_ERR_USAGE);
+ break;
+ case 'y':
+ oclass = OT2Int(optarg_av);
+ if (oclass == -1)
+ return (PK_ERR_USAGE);
+ break;
case 'T': /* token specifier */
if (token_spec)
return (PK_ERR_USAGE);
token_spec = optarg_av;
break;
+ case 'd':
+ if (dir)
+ return (PK_ERR_USAGE);
+ dir = optarg_av;
+ break;
+ case 'p':
+ if (prefix)
+ return (PK_ERR_USAGE);
+ prefix = optarg_av;
+ break;
+ case 'n':
+ case 'l':
+ if (certlabel)
+ return (PK_ERR_USAGE);
+ certlabel = optarg_av;
+ break;
+ case 's':
+ if (subject)
+ return (PK_ERR_USAGE);
+ subject = optarg_av;
+ break;
+ case 'i':
+ if (issuer)
+ return (PK_ERR_USAGE);
+ issuer = optarg_av;
+ break;
+ case 'S':
+ serstr = optarg_av;
+ break;
+ case 'F':
+ kfmt = Str2Format(optarg_av);
+ if (kfmt == KMF_FORMAT_UNDEF)
+ return (PK_ERR_USAGE);
+ break;
+ case 'I': /* output file name */
+ if (infile)
+ return (PK_ERR_USAGE);
+ infile = optarg_av;
+ break;
case 'o': /* output file name */
if (filename)
return (PK_ERR_USAGE);
filename = optarg_av;
break;
+ case 'c': /* input cert file name */
+ if (certfile)
+ return (PK_ERR_USAGE);
+ certfile = optarg_av;
+ break;
+ case 'K': /* input key file name */
+ if (keyfile)
+ return (PK_ERR_USAGE);
+ keyfile = optarg_av;
+ break;
default:
return (PK_ERR_USAGE);
break;
}
}
- /* If nothing is specified, default is to use softtoken. */
- if (token_spec == NULL) {
- token_name = SOFT_TOKEN_LABEL;
- manuf_id = SOFT_MANUFACTURER_ID;
- serial_no = SOFT_TOKEN_SERIAL;
- } else {
- /*
- * Parse token specifier into token_name, manuf_id, serial_no.
- * Token_name is required; manuf_id and serial_no are optional.
- */
- if (parse_token_spec(token_spec, &token_name, &manuf_id,
- &serial_no) < 0)
- return (PK_ERR_USAGE);
- }
+ /* Assume keystore = PKCS#11 if not specified */
+ if (kstype == 0)
+ kstype = KMF_KEYSTORE_PK11TOKEN;
/* Filename arg is required. */
- if (filename == NULL)
+ if (EMPTYSTRING(filename)) {
+ cryptoerror(LOG_STDERR, gettext("You must specify "
+ "an 'outfile' parameter when exporting.\n"));
return (PK_ERR_USAGE);
+ }
/* No additional args allowed. */
argc -= optind_av;
argv += optind_av;
if (argc)
return (PK_ERR_USAGE);
- /* Done parsing command line options. */
+
+ /* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
+ if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
+ kstype != KMF_KEYSTORE_PK11TOKEN) {
+
+ (void) fprintf(stderr, gettext("The objtype parameter "
+ "is only relevant if keystore=pkcs11\n"));
+ return (PK_ERR_USAGE);
+ }
+
+ if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec))
+ token_spec = PK_DEFAULT_PK11TOKEN;
+ else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec))
+ token_spec = DEFAULT_NSS_TOKEN;
+
+ if (kstype == KMF_KEYSTORE_OPENSSL) {
+ if (kfmt != KMF_FORMAT_PKCS12) {
+ cryptoerror(LOG_STDERR, gettext("PKCS12 "
+ "is the only export format "
+ "supported for the 'file' "
+ "keystore.\n"));
+ return (PK_ERR_USAGE);
+ }
+ if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) {
+ cryptoerror(LOG_STDERR, gettext("A cert file"
+ "and a key file must be specified "
+ "when exporting to PKCS12 from the "
+ "'file' keystore.\n"));
+ return (PK_ERR_USAGE);
+ }
+ }
/* Check if the file exists and might be overwritten. */
if (access(filename, F_OK) == 0) {
- cryptoerror(LOG_STDERR, gettext("Warning: file \"%s\" exists, "
- "will be overwritten."), filename);
+ cryptoerror(LOG_STDERR,
+ gettext("Warning: file \"%s\" exists, "
+ "will be overwritten."), filename);
if (yesno(gettext("Continue with export? "),
gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
return (0);
}
+ } else {
+ rv = verify_file(filename);
+ if (rv != KMF_OK) {
+ cryptoerror(LOG_STDERR, gettext("The file (%s) "
+ "cannot be created.\n"), filename);
+ return (PK_ERR_USAGE);
+ }
}
- full_token_name(token_name, manuf_id, serial_no, full_name);
-
- /* Find the slot with token. */
- if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
- &pin_state)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to find token %s (%s)."), full_name,
- pkcs11_strerror(rv));
- return (PK_ERR_PK11);
- }
-
- /* Get the user's PIN. */
- if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin,
- &pinlen)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get token passphrase (%s)."),
- pkcs11_strerror(rv));
- quick_finish(NULL);
- return (PK_ERR_PK11);
- }
-
- /* Assume user must be logged in R/W to export objects from token. */
- if ((rv = quick_start(slot_id, CKF_RW_SESSION, pin, pinlen, &sess)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR,
- gettext("Unable to log into token (%s)."),
- pkcs11_strerror(rv));
- quick_finish(sess);
- return (PK_ERR_PK11);
- }
+ if (serstr != NULL) {
+ uchar_t *bytes = NULL;
+ size_t bytelen;
- /* Collect all private keys first. */
- if ((rv = find_objs(sess, PK_PRIVATE_OBJ|PK_KEY_OBJ, NULL,
- &objs, &num_objs)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to retrieve private key token objects (%s)."),
- pkcs11_strerror(rv));
- quick_finish(sess);
- return (PK_ERR_PK11);
+ rv = KMF_HexString2Bytes((uchar_t *)serstr, &bytes, &bytelen);
+ if (rv != KMF_OK || bytes == NULL) {
+ (void) fprintf(stderr, gettext("serial number "
+ "must be specified as a hex number "
+ "(ex: 0x0102030405ffeeddee)\n"));
+ return (PK_ERR_USAGE);
+ }
+ serial.val = bytes;
+ serial.len = bytelen;
}
- /* Nothing to do? */
- if (num_objs == 0) {
- cryptoerror(LOG_STDERR, gettext("No objects found."));
- quick_finish(sess);
- return (0);
+ if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
+ kstype == KMF_KEYSTORE_NSS) &&
+ (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ) ||
+ kfmt == KMF_FORMAT_PKCS12)) {
+ (void) get_token_password(kstype, token_spec,
+ &tokencred);
}
- /* Setup OpenSSL context. */
- PKTOOL_setup_openssl();
-
- /* Create PKCS#12 file. */
- if ((create_pkcs12(filename, &fbio)) < 0) {
- cryptoerror(LOG_STDERR, gettext("No export file created."));
- quick_finish(sess);
- return (PK_ERR_SYSTEM);
+ if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
+ cryptoerror(LOG_STDERR, gettext("Error initializing "
+ "KMF: 0x%02x\n"), rv);
+ return (rv);
}
- /* Get the PIN for the PKCS#12 export file. */
- if ((rv = get_pin(gettext("Create export file passphrase:"), gettext(
- "Re-enter export file passphrase:"), &pk12pin, &pk12pinlen)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR,
- gettext("Unable to get export file passphrase (%s)."),
- pkcs11_strerror(rv));
- close_pkcs12(fbio);
- quick_finish(sess);
- return (PK_ERR_PK11);
+ switch (kstype) {
+ case KMF_KEYSTORE_PK11TOKEN:
+ if (kfmt == KMF_FORMAT_PKCS12)
+ rv = pk_export_pk12_pk11(
+ kmfhandle,
+ token_spec,
+ certlabel,
+ issuer, subject,
+ &serial, &tokencred,
+ filename);
+ else
+ rv = pk_export_pk11_objects(kmfhandle,
+ token_spec,
+ certlabel,
+ issuer, subject,
+ &serial, kfmt,
+ filename);
+ break;
+ case KMF_KEYSTORE_NSS:
+ if (dir == NULL)
+ dir = PK_DEFAULT_DIRECTORY;
+ if (kfmt == KMF_FORMAT_PKCS12)
+ rv = pk_export_pk12_nss(kmfhandle,
+ token_spec, dir, prefix,
+ certlabel, issuer,
+ subject, &serial,
+ &tokencred, filename);
+ else
+ rv = pk_export_nss_objects(kmfhandle,
+ token_spec,
+ oclass, certlabel, issuer, subject,
+ &serial, kfmt, dir, prefix, filename);
+ break;
+ case KMF_KEYSTORE_OPENSSL:
+ if (kfmt == KMF_FORMAT_PKCS12)
+ rv = pk_export_pk12_files(kmfhandle,
+ certfile, keyfile, dir,
+ filename);
+ else
+ rv = pk_export_file_objects(kmfhandle, oclass,
+ issuer, subject, &serial, kfmt,
+ dir, infile, filename);
+ break;
+ default:
+ rv = PK_ERR_USAGE;
+ break;
}
- for (i = 0; i < num_objs; i++) {
- /* Get a private key and its certificate and CA chain. */
- if ((rv = get_token_objs(sess, objs[i], &mate, &chain,
- &chain_len, &id, &id_len)) != CKR_OK) {
- /*
- * Note this "rv" is either CKR_OK or !CKR_OK. The
- * real error codes/messages are handled inside
- * read_token_objs().
- */
- cryptoerror(LOG_STDERR,
- gettext("Unable to get token objects."));
- free(id);
- close_pkcs12(fbio);
- quick_finish(sess);
- return (PK_ERR_PK11);
- }
-
- /* Convert to OpenSSL equivalents. */
- if ((rv = convert_token_objs(sess, objs[i], mate, chain,
- chain_len, &priv_key, &cert, &ca)) != CKR_OK) {
- /*
- * Note this "rv" is either CKR_OK or !CKR_OK. The
- * real error codes/messages are handled inside
- * read_token_objs().
- */
- cryptoerror(LOG_STDERR,
- gettext("Unable to convert token objects."));
- free(id);
- close_pkcs12(fbio);
- quick_finish(sess);
- return (PK_ERR_PK11);
- }
-
- /*
- * When exporting of cert chains is implemented, these
- * messages should be updated accordingly.
- */
- if (mate == ~0UL)
- (void) fprintf(stdout, gettext(
- "Writing object #%d...\n"), i+1);
- else
- (void) fprintf(stdout, gettext("Writing object #%d "
- "and its certificate...\n"), i+1);
-
- /* Write object and its certs to the PKCS#12 export file. */
- if (write_objs_pkcs12(fbio, pk12pin, pk12pinlen, id, id_len,
- priv_key, cert, ca, &good_ones, &bad_ones) < 0) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to write object #%d to export file."), i+1);
- sk_X509_pop_free(ca, X509_free);
- free(id);
- close_pkcs12(fbio);
- quick_finish(sess);
- return (PK_ERR_OPENSSL);
- }
-
- /* Destroy key id and CA cert chain, done with them. */
- free(id);
- id = NULL;
- sk_X509_pop_free(ca, X509_free);
- ca = NULL;
+ if (rv != KMF_OK) {
+ display_error(kmfhandle, rv,
+ gettext("Error exporting objects"));
}
- (void) fprintf(stdout, gettext(
- "%d token objects exported, %d errors occurred.\n"),
- good_ones, bad_ones);
+ if (serial.val != NULL)
+ free(serial.val);
- /* Close PKCS#12 file. */
- close_pkcs12(fbio);
+ (void) KMF_Finalize(kmfhandle);
- /* Clean up. */
- quick_finish(sess);
- return (0);
+ return (rv);
}
diff --git a/usr/src/cmd/cmd-crypto/pktool/gencert.c b/usr/src/cmd/cmd-crypto/pktool/gencert.c
new file mode 100644
index 0000000000..ae79c579a4
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/pktool/gencert.c
@@ -0,0 +1,729 @@
+/*
+ * 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 <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <malloc.h>
+#include <libgen.h>
+#include <errno.h>
+#include <cryptoutil.h>
+#include <security/cryptoki.h>
+#include "common.h"
+
+#include <kmfapi.h>
+
+#define SET_VALUE(f, s) \
+ kmfrv = f; \
+ if (kmfrv != KMF_OK) { \
+ cryptoerror(LOG_STDERR, \
+ gettext("Failed to set %s: 0x%02x\n"), \
+ s, kmfrv); \
+ goto cleanup; \
+ }
+
+static int
+gencert_pkcs11(KMF_HANDLE_T kmfhandle,
+ char *token, char *subject, char *altname,
+ KMF_GENERALNAMECHOICES alttype, int altcrit,
+ char *certlabel, KMF_KEY_ALG keyAlg,
+ KMF_ALGORITHM_INDEX sigAlg,
+ int keylen, uint32_t ltime, KMF_BIGINT *serial,
+ uint16_t kubits, int kucrit, KMF_CREDENTIAL *tokencred)
+{
+ KMF_RETURN kmfrv = KMF_OK;
+ KMF_CREATEKEYPAIR_PARAMS kp_params;
+ KMF_STORECERT_PARAMS sc_params;
+ KMF_KEY_HANDLE pubk, prik;
+ KMF_X509_CERTIFICATE signedCert;
+ KMF_X509_NAME certSubject;
+ KMF_X509_NAME certIssuer;
+ KMF_DATA x509DER;
+
+ (void) memset(&signedCert, 0, sizeof (signedCert));
+ (void) memset(&certSubject, 0, sizeof (certSubject));
+ (void) memset(&certIssuer, 0, sizeof (certIssuer));
+ (void) memset(&x509DER, 0, sizeof (x509DER));
+ (void) memset(&kp_params, 0, sizeof (kp_params));
+
+ /* If the subject name cannot be parsed, flag it now and exit */
+ if (KMF_DNParser(subject, &certSubject) != KMF_OK) {
+ cryptoerror(LOG_STDERR,
+ gettext("Subject name cannot be parsed.\n"));
+ return (PK_ERR_USAGE);
+ }
+
+ /* For a self-signed cert, the issuser and subject are the same */
+ if (KMF_DNParser(subject, &certIssuer) != KMF_OK) {
+ cryptoerror(LOG_STDERR,
+ gettext("Subject name cannot be parsed.\n"));
+ return (PK_ERR_USAGE);
+ }
+
+ kp_params.kstype = KMF_KEYSTORE_PK11TOKEN;
+ kp_params.keylabel = certlabel;
+ kp_params.keylength = keylen; /* bits */
+ kp_params.keytype = keyAlg;
+ kp_params.cred.cred = tokencred->cred;
+ kp_params.cred.credlen = tokencred->credlen;
+
+ /* Select a PKCS11 token */
+ kmfrv = select_token(kmfhandle, token, FALSE);
+
+ if (kmfrv != KMF_OK) {
+ return (kmfrv);
+ }
+
+ kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk);
+ if (kmfrv != KMF_OK) {
+ return (kmfrv);
+ }
+
+ SET_VALUE(KMF_SetCertPubKey(kmfhandle, &pubk, &signedCert),
+ "keypair");
+
+ SET_VALUE(KMF_SetCertVersion(&signedCert, 2), "version number");
+
+ SET_VALUE(KMF_SetCertSerialNumber(&signedCert, serial),
+ "serial number");
+
+ SET_VALUE(KMF_SetCertValidityTimes(&signedCert, NULL, ltime),
+ "validity time");
+
+ SET_VALUE(KMF_SetCertSignatureAlgorithm(&signedCert, sigAlg),
+ "signature algorithm");
+
+ SET_VALUE(KMF_SetCertSubjectName(&signedCert, &certSubject),
+ "subject name");
+
+ SET_VALUE(KMF_SetCertIssuerName(&signedCert, &certIssuer),
+ "issuer name");
+
+ if (altname != NULL)
+ SET_VALUE(KMF_SetCertSubjectAltName(&signedCert, altcrit,
+ alttype, altname), "subjectAltName");
+
+ if (kubits != 0)
+ SET_VALUE(KMF_SetCertKeyUsage(&signedCert, kucrit, kubits),
+ "KeyUsage");
+
+ if ((kmfrv = KMF_SignCertRecord(kmfhandle, &prik,
+ &signedCert, &x509DER)) != KMF_OK) {
+ goto cleanup;
+ }
+
+ (void) memset(&sc_params, 0, sizeof (sc_params));
+ sc_params.kstype = KMF_KEYSTORE_PK11TOKEN;
+ sc_params.certLabel = certlabel;
+
+ /*
+ * Store the cert in the DB.
+ */
+ kmfrv = KMF_StoreCert(kmfhandle, &sc_params, &x509DER);
+
+cleanup:
+ KMF_FreeData(&x509DER);
+ KMF_FreeDN(&certSubject);
+ KMF_FreeDN(&certIssuer);
+ return (kmfrv);
+}
+
+static int
+gencert_file(KMF_HANDLE_T kmfhandle,
+ KMF_KEY_ALG keyAlg, KMF_ALGORITHM_INDEX sigAlg,
+ int keylen, KMF_ENCODE_FORMAT fmt,
+ 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)
+{
+ KMF_RETURN kmfrv;
+ KMF_CREATEKEYPAIR_PARAMS kp_params;
+ KMF_STORECERT_PARAMS sc_params;
+ KMF_KEY_HANDLE pubk, prik;
+ KMF_X509_CERTIFICATE signedCert;
+ KMF_X509_NAME certSubject;
+ KMF_X509_NAME certIssuer;
+ KMF_DATA x509DER;
+ char *fullcertpath = NULL;
+ char *fullkeypath = NULL;
+
+ (void) memset(&signedCert, 0, sizeof (signedCert));
+ (void) memset(&certSubject, 0, sizeof (certSubject));
+ (void) memset(&certIssuer, 0, sizeof (certIssuer));
+ (void) memset(&x509DER, 0, sizeof (x509DER));
+ (void) memset(&kp_params, 0, sizeof (kp_params));
+ (void) memset(&sc_params, 0, sizeof (sc_params));
+
+ if (EMPTYSTRING(outcert) || EMPTYSTRING(outkey)) {
+ cryptoerror(LOG_STDERR,
+ gettext("No output file was specified for "
+ "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);
+ }
+ if (verify_file(fullcertpath)) {
+ cryptoerror(LOG_STDERR,
+ gettext("Cannot write the indicated output "
+ "certificate file (%s).\n"),
+ fullcertpath);
+ 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);
+ }
+ if (verify_file(fullkeypath)) {
+ cryptoerror(LOG_STDERR,
+ gettext("Cannot write the indicated output "
+ "key file (%s).\n"),
+ fullkeypath);
+ free(fullkeypath);
+ free(fullcertpath);
+ return (PK_ERR_USAGE);
+ }
+
+ /* If the subject name cannot be parsed, flag it now and exit */
+ if (KMF_DNParser(subject, &certSubject) != KMF_OK) {
+ cryptoerror(LOG_STDERR,
+ gettext("Subject name cannot be parsed (%s)\n"),
+ subject);
+ return (PK_ERR_USAGE);
+ }
+
+ /* For a self-signed cert, the issuser and subject are the same */
+ if (KMF_DNParser(subject, &certIssuer) != KMF_OK) {
+ cryptoerror(LOG_STDERR,
+ gettext("Subject name cannot be parsed (%s)\n"),
+ subject);
+ KMF_FreeDN(&certSubject);
+ return (PK_ERR_USAGE);
+ }
+
+ kp_params.kstype = KMF_KEYSTORE_OPENSSL;
+ kp_params.keylength = keylen; /* bits */
+ kp_params.keytype = keyAlg;
+
+ kp_params.sslparms.keyfile = fullkeypath;
+ kp_params.sslparms.format = fmt;
+
+ kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk);
+ if (kmfrv != KMF_OK) {
+ goto cleanup;
+ }
+ SET_VALUE(KMF_SetCertPubKey(kmfhandle, &pubk, &signedCert),
+ "keypair");
+
+ SET_VALUE(KMF_SetCertVersion(&signedCert, 2), "version number");
+
+ SET_VALUE(KMF_SetCertSerialNumber(&signedCert, serial),
+ "serial number");
+
+ SET_VALUE(KMF_SetCertValidityTimes(&signedCert, NULL, ltime),
+ "validity time");
+
+ SET_VALUE(KMF_SetCertSignatureAlgorithm(&signedCert, sigAlg),
+ "signature algorithm");
+
+ SET_VALUE(KMF_SetCertSubjectName(&signedCert, &certSubject),
+ "subject name");
+
+ SET_VALUE(KMF_SetCertIssuerName(&signedCert, &certIssuer),
+ "issuer name");
+
+ if (altname != NULL)
+ SET_VALUE(KMF_SetCertSubjectAltName(&signedCert, altcrit,
+ alttype, altname), "subjectAltName");
+
+ if (kubits != 0)
+ SET_VALUE(KMF_SetCertKeyUsage(&signedCert, kucrit, kubits),
+ "KeyUsage");
+
+ if ((kmfrv = KMF_SignCertRecord(kmfhandle, &prik,
+ &signedCert, &x509DER)) != KMF_OK) {
+ goto cleanup;
+ }
+
+ sc_params.kstype = KMF_KEYSTORE_OPENSSL;
+ sc_params.sslparms.certfile = fullcertpath;
+ sc_params.sslparms.keyfile = fullkeypath;
+ sc_params.sslparms.format = fmt;
+ /*
+ * Store the cert in the DB.
+ */
+ kmfrv = KMF_StoreCert(kmfhandle, &sc_params, &x509DER);
+
+cleanup:
+ if (fullkeypath != NULL)
+ free(fullkeypath);
+ if (fullcertpath != NULL)
+ free(fullcertpath);
+
+ KMF_FreeData(&x509DER);
+ KMF_FreeDN(&certSubject);
+ KMF_FreeDN(&certIssuer);
+ return (kmfrv);
+}
+
+static KMF_RETURN
+gencert_nss(KMF_HANDLE_T kmfhandle,
+ char *token, char *subject, char *altname,
+ KMF_GENERALNAMECHOICES alttype, int altcrit,
+ char *nickname, char *dir, char *prefix,
+ KMF_KEY_ALG keyAlg,
+ KMF_ALGORITHM_INDEX sigAlg,
+ int keylen, char *trust,
+ uint32_t ltime, KMF_BIGINT *serial, uint16_t kubits,
+ int kucrit, KMF_CREDENTIAL *tokencred)
+{
+ KMF_RETURN kmfrv;
+ KMF_CREATEKEYPAIR_PARAMS kp_params;
+ KMF_STORECERT_PARAMS sc_params;
+ KMF_KEY_HANDLE pubk, prik;
+ KMF_X509_CERTIFICATE signedCert;
+ KMF_X509_NAME certSubject;
+ KMF_X509_NAME certIssuer;
+ KMF_DATA x509DER;
+
+ if (token == NULL)
+ token = DEFAULT_NSS_TOKEN;
+
+ kmfrv = configure_nss(kmfhandle, dir, prefix);
+ if (kmfrv != KMF_OK)
+ return (kmfrv);
+
+ (void) memset(&signedCert, 0, sizeof (signedCert));
+ (void) memset(&certSubject, 0, sizeof (certSubject));
+ (void) memset(&certIssuer, 0, sizeof (certIssuer));
+ (void) memset(&x509DER, 0, sizeof (x509DER));
+
+ /* If the subject name cannot be parsed, flag it now and exit */
+ if (KMF_DNParser(subject, &certSubject) != KMF_OK) {
+ cryptoerror(LOG_STDERR,
+ gettext("Subject name cannot be parsed.\n"));
+ return (PK_ERR_USAGE);
+ }
+
+ /* For a self-signed cert, the issuser and subject are the same */
+ if (KMF_DNParser(subject, &certIssuer) != KMF_OK) {
+ cryptoerror(LOG_STDERR,
+ gettext("Subject name cannot be parsed.\n"));
+ return (PK_ERR_USAGE);
+ }
+
+ (void) memset(&kp_params, 0, sizeof (kp_params));
+
+ kp_params.kstype = KMF_KEYSTORE_NSS;
+ kp_params.keylabel = nickname;
+ kp_params.keylength = keylen; /* bits */
+ kp_params.keytype = keyAlg;
+ kp_params.cred.cred = tokencred->cred;
+ kp_params.cred.credlen = tokencred->credlen;
+ kp_params.nssparms.slotlabel = token;
+
+ kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk);
+ if (kmfrv != KMF_OK) {
+ return (kmfrv);
+ }
+
+ SET_VALUE(KMF_SetCertPubKey(kmfhandle, &pubk, &signedCert),
+ "keypair");
+
+ SET_VALUE(KMF_SetCertVersion(&signedCert, 2), "version number");
+
+ SET_VALUE(KMF_SetCertSerialNumber(&signedCert, serial),
+ "serial number");
+
+ SET_VALUE(KMF_SetCertValidityTimes(&signedCert, NULL, ltime),
+ "validity time");
+
+ SET_VALUE(KMF_SetCertSignatureAlgorithm(&signedCert, sigAlg),
+ "signature algorithm");
+
+ SET_VALUE(KMF_SetCertSubjectName(&signedCert, &certSubject),
+ "subject name");
+
+ SET_VALUE(KMF_SetCertIssuerName(&signedCert, &certIssuer),
+ "issuer name");
+
+ if (altname != NULL)
+ SET_VALUE(KMF_SetCertSubjectAltName(&signedCert, altcrit,
+ alttype, altname), "subjectAltName");
+
+ if (kubits)
+ SET_VALUE(KMF_SetCertKeyUsage(&signedCert, kucrit, kubits),
+ "subjectAltName");
+
+ if ((kmfrv = KMF_SignCertRecord(kmfhandle, &prik,
+ &signedCert, &x509DER)) != KMF_OK) {
+ goto cleanup;
+ }
+
+ sc_params.kstype = KMF_KEYSTORE_NSS;
+ sc_params.certLabel = nickname;
+ sc_params.nssparms.trustflag = trust;
+ sc_params.nssparms.slotlabel = token;
+
+ /*
+ * Store the cert in the DB.
+ */
+ kmfrv = KMF_StoreCert(kmfhandle, &sc_params, &x509DER);
+
+cleanup:
+ KMF_FreeData(&x509DER);
+ KMF_FreeDN(&certSubject);
+ KMF_FreeDN(&certIssuer);
+ return (kmfrv);
+}
+
+int
+pk_gencert(int argc, char *argv[])
+{
+ int rv;
+ int opt;
+ extern int optind_av;
+ extern char *optarg_av;
+ KMF_KEYSTORE_TYPE kstype = 0;
+ char *subject = NULL;
+ char *tokenname = NULL;
+ char *dir = NULL;
+ char *prefix = NULL;
+ char *keytype = PK_DEFAULT_KEYTYPE;
+ int keylen = PK_DEFAULT_KEYLENGTH;
+ char *trust = NULL;
+ char *lifetime = NULL;
+ char *certlabel = NULL;
+ char *outcert = NULL;
+ char *outkey = NULL;
+ char *format = NULL;
+ char *serstr = NULL;
+ char *altname = NULL;
+ char *keyusagestr = NULL;
+ KMF_GENERALNAMECHOICES alttype = 0;
+ KMF_BIGINT serial = { NULL, 0 };
+ uint32_t ltime;
+ KMF_HANDLE_T kmfhandle = NULL;
+ KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
+ KMF_KEY_ALG keyAlg = KMF_RSA;
+ KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA;
+ boolean_t interactive = B_FALSE;
+ char *subname = NULL;
+ KMF_CREDENTIAL tokencred = {NULL, 0};
+ uint16_t kubits = 0;
+ int altcrit = 0, kucrit = 0;
+
+ while ((opt = getopt_av(argc, argv,
+ "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
+ "T:(token)d:(dir)p:(prefix)t:(keytype)y:(keylen)"
+ "r:(trust)L:(lifetime)l:(label)c:(outcert)"
+ "K:(outkey)S:(serial)F:(format)u:(keyusage)")) != EOF) {
+
+ if (opt != 'i' && EMPTYSTRING(optarg_av))
+ return (PK_ERR_USAGE);
+
+ switch (opt) {
+ case 'A':
+ altname = optarg_av;
+ break;
+ case 'i':
+ if (interactive || subject)
+ return (PK_ERR_USAGE);
+ else
+ interactive = B_TRUE;
+ break;
+ case 'k':
+ kstype = KS2Int(optarg_av);
+ if (kstype == 0)
+ return (PK_ERR_USAGE);
+ break;
+ case 's':
+ if (interactive || subject)
+ return (PK_ERR_USAGE);
+ else
+ subject = optarg_av;
+ break;
+ case 'l':
+ case 'n':
+ if (certlabel)
+ return (PK_ERR_USAGE);
+ certlabel = optarg_av;
+ break;
+ case 'T':
+ if (tokenname)
+ return (PK_ERR_USAGE);
+ tokenname = optarg_av;
+ break;
+ case 'd':
+ if (dir)
+ return (PK_ERR_USAGE);
+ dir = optarg_av;
+ break;
+ case 'p':
+ if (prefix)
+ return (PK_ERR_USAGE);
+ prefix = optarg_av;
+ break;
+ case 't':
+ keytype = optarg_av;
+ break;
+ case 'u':
+ keyusagestr = optarg_av;
+ break;
+ case 'y':
+ if (sscanf(optarg_av, "%d",
+ &keylen) != 1) {
+ cryptoerror(LOG_STDERR,
+ gettext("key length must be"
+ "a numeric value (%s)\n"),
+ optarg_av);
+ return (PK_ERR_USAGE);
+ }
+ break;
+ case 'r':
+ if (trust)
+ return (PK_ERR_USAGE);
+ trust = optarg_av;
+ break;
+ case 'L':
+ if (lifetime)
+ return (PK_ERR_USAGE);
+ lifetime = optarg_av;
+ break;
+ case 'c':
+ if (outcert)
+ return (PK_ERR_USAGE);
+ outcert = optarg_av;
+ break;
+ case 'K':
+ if (outkey)
+ return (PK_ERR_USAGE);
+ outkey = optarg_av;
+ break;
+ case 'S':
+ serstr = optarg_av;
+ break;
+ case 'F':
+ if (format)
+ return (PK_ERR_USAGE);
+ format = optarg_av;
+ break;
+ default:
+ return (PK_ERR_USAGE);
+ }
+ }
+
+ /* No additional args allowed. */
+ argc -= optind_av;
+ argv += optind_av;
+ if (argc) {
+ return (PK_ERR_USAGE);
+ }
+
+ if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
+ cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
+ return (PK_ERR_USAGE);
+ }
+
+ /* Assume keystore = PKCS#11 if not specified. */
+ if (kstype == 0)
+ kstype = KMF_KEYSTORE_PK11TOKEN;
+
+ if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) &&
+ EMPTYSTRING(certlabel)) {
+ cryptoerror(LOG_STDERR, gettext("A label must be specified "
+ "to create a self-signed certificate.\n"));
+ return (PK_ERR_USAGE);
+ } else if (kstype == KMF_KEYSTORE_OPENSSL && EMPTYSTRING(outcert)) {
+ cryptoerror(LOG_STDERR, gettext("A certificate filename must "
+ "be specified to create a self-signed certificate.\n"));
+ return (PK_ERR_USAGE);
+ }
+
+ if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
+ cryptoerror(LOG_STDERR,
+ gettext("Error parsing format string (%s).\n"),
+ format);
+ return (PK_ERR_USAGE);
+ }
+
+ if (Str2Lifetime(lifetime, &ltime) != 0) {
+ cryptoerror(LOG_STDERR,
+ gettext("Error parsing lifetime string\n"));
+ return (PK_ERR_USAGE);
+ }
+
+ if (Str2KeyType(keytype, &keyAlg, &sigAlg) != 0) {
+ cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
+ keytype);
+ return (PK_ERR_USAGE);
+ }
+
+
+ /*
+ * Check the subject name.
+ * If interactive is true, get it now interactively.
+ */
+ if (interactive) {
+ if (get_subname(&subname) != KMF_OK) {
+ cryptoerror(LOG_STDERR, gettext("Failed to get the "
+ "subject name interactively.\n"));
+ return (PK_ERR_USAGE);
+ }
+ } else {
+ if (EMPTYSTRING(subject)) {
+ cryptoerror(LOG_STDERR, gettext("A subject name or "
+ "-i must be specified to create a self-signed "
+ "certificate.\n"));
+ return (PK_ERR_USAGE);
+ } else {
+ subname = strdup(subject);
+ if (subname == NULL) {
+ cryptoerror(LOG_STDERR,
+ gettext("Out of memory.\n"));
+ return (PK_ERR_SYSTEM);
+ }
+ }
+ }
+
+ if (serstr == NULL) {
+ (void) fprintf(stderr, gettext("A serial number "
+ "must be specified as a hex number when creating"
+ " a self-signed certificate "
+ "(ex: serno=0x0102030405feedface)\n"));
+ rv = PK_ERR_USAGE;
+ goto end;
+ } else {
+ uchar_t *bytes = NULL;
+ size_t bytelen;
+
+ rv = KMF_HexString2Bytes((uchar_t *)serstr, &bytes, &bytelen);
+ if (rv != KMF_OK || bytes == NULL) {
+ (void) fprintf(stderr, gettext("serial number "
+ "must be specified as a hex number "
+ "(ex: 0x0102030405ffeeddee)\n"));
+ rv = PK_ERR_USAGE;
+ goto end;
+ }
+ serial.val = bytes;
+ serial.len = bytelen;
+ }
+
+ if (altname != NULL) {
+ rv = verify_altname(altname, &alttype, &altcrit);
+ if (rv != KMF_OK) {
+ (void) fprintf(stderr, gettext("Subject AltName "
+ "must be specified as a name=value pair. "
+ "See the man page for details.\n"));
+ rv = PK_ERR_USAGE;
+ goto end;
+ } else {
+ /* advance the altname past the '=' sign */
+ char *p = strchr(altname, '=');
+ if (p != NULL)
+ altname = p + 1;
+ }
+ }
+
+ if (keyusagestr != NULL) {
+ rv = verify_keyusage(keyusagestr, &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 (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
+ if (tokenname == NULL || !strlen(tokenname)) {
+ if (kstype == KMF_KEYSTORE_NSS) {
+ tokenname = "internal";
+ } else {
+ tokenname = PK_DEFAULT_PK11TOKEN;
+ }
+ }
+
+ (void) get_token_password(kstype, tokenname, &tokencred);
+ }
+
+ if (kstype == KMF_KEYSTORE_NSS) {
+ if (dir == NULL)
+ dir = PK_DEFAULT_DIRECTORY;
+
+ rv = gencert_nss(kmfhandle,
+ tokenname, subname, altname, alttype, altcrit,
+ certlabel, dir, prefix, keyAlg, sigAlg, keylen,
+ trust, ltime, &serial, kubits, kucrit, &tokencred);
+
+ } else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
+ rv = gencert_pkcs11(kmfhandle,
+ tokenname, subname, altname, alttype, altcrit,
+ certlabel, keyAlg, sigAlg, keylen, ltime,
+ &serial, kubits, kucrit, &tokencred);
+
+ } else if (kstype == KMF_KEYSTORE_OPENSSL) {
+ rv = gencert_file(kmfhandle,
+ keyAlg, sigAlg, keylen, fmt,
+ ltime, subname, altname, alttype, altcrit,
+ &serial, kubits, kucrit, dir, outcert, outkey);
+ }
+
+ if (rv != KMF_OK)
+ display_error(kmfhandle, rv,
+ gettext("Error creating certificate and keypair"));
+end:
+ if (subname)
+ free(subname);
+ if (tokencred.cred != NULL)
+ free(tokencred.cred);
+
+ if (serial.val != NULL)
+ free(serial.val);
+
+ (void) KMF_Finalize(kmfhandle);
+ return (rv);
+}
diff --git a/usr/src/cmd/cmd-crypto/pktool/gencsr.c b/usr/src/cmd/cmd-crypto/pktool/gencsr.c
new file mode 100644
index 0000000000..fcc00d01c8
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/pktool/gencsr.c
@@ -0,0 +1,631 @@
+/*
+ * 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 <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <malloc.h>
+#include <libgen.h>
+#include <errno.h>
+#include <cryptoutil.h>
+#include <security/cryptoki.h>
+#include "common.h"
+
+#include <kmfapi.h>
+
+#define SET_VALUE(f, s) \
+ kmfrv = f; \
+ if (kmfrv != KMF_OK) { \
+ cryptoerror(LOG_STDERR, \
+ gettext("Failed to %s: 0x%02\n"), \
+ s, kmfrv); \
+ goto cleanup; \
+ }
+
+static KMF_RETURN
+gencsr_pkcs11(KMF_HANDLE_T kmfhandle,
+ char *token, char *subject, char *altname,
+ KMF_GENERALNAMECHOICES alttype, int altcrit,
+ char *certlabel, KMF_KEY_ALG keyAlg,
+ int keylen,
+ uint16_t kubits, int kucrit,
+ KMF_ENCODE_FORMAT fmt, char *csrfile,
+ KMF_CREDENTIAL *tokencred)
+{
+ KMF_RETURN kmfrv = KMF_OK;
+ KMF_CREATEKEYPAIR_PARAMS kp_params;
+ KMF_DELETEKEY_PARAMS dk_params;
+ KMF_KEY_HANDLE pubk, prik;
+ KMF_X509_NAME csrSubject;
+ KMF_CSR_DATA csr;
+ KMF_ALGORITHM_INDEX sigAlg;
+ KMF_DATA signedCsr = {NULL, 0};
+
+ (void) memset(&csr, 0, sizeof (csr));
+ (void) memset(&csrSubject, 0, sizeof (csrSubject));
+ (void) memset(&kp_params, 0, sizeof (kp_params));
+
+ if (keyAlg == KMF_DSA)
+ sigAlg = KMF_ALGID_SHA1WithDSA;
+ else
+ sigAlg = KMF_ALGID_MD5WithRSA;
+
+
+ /* If the subject name cannot be parsed, flag it now and exit */
+ if ((kmfrv = KMF_DNParser(subject, &csrSubject)) != KMF_OK) {
+ return (kmfrv);
+ }
+
+ kp_params.kstype = KMF_KEYSTORE_PK11TOKEN;
+ kp_params.keylabel = certlabel;
+ kp_params.keylength = keylen; /* bits */
+ kp_params.keytype = keyAlg;
+ kp_params.cred.cred = tokencred->cred;
+ kp_params.cred.credlen = tokencred->credlen;
+
+ /* Select a PKCS11 token */
+ kmfrv = select_token(kmfhandle, token, FALSE);
+ if (kmfrv != KMF_OK) {
+ return (kmfrv);
+ }
+
+ kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk);
+ if (kmfrv != KMF_OK) {
+ return (kmfrv);
+ }
+
+ SET_VALUE(KMF_SetCSRPubKey(kmfhandle, &pubk, &csr), "keypair");
+
+ SET_VALUE(KMF_SetCSRVersion(&csr, 2), "version number");
+
+ SET_VALUE(KMF_SetCSRSubjectName(&csr, &csrSubject),
+ "subject name");
+
+ SET_VALUE(KMF_SetCSRSignatureAlgorithm(&csr, sigAlg),
+ "SignatureAlgorithm");
+
+ if (altname != NULL) {
+ SET_VALUE(KMF_SetCSRSubjectAltName(&csr, altname, altcrit,
+ alttype), "SetCSRSubjectAltName");
+ }
+
+ if (kubits != 0) {
+ SET_VALUE(KMF_SetCSRKeyUsage(&csr, kucrit, kubits),
+ "SetCSRKeyUsage");
+ }
+
+ if ((kmfrv = KMF_SignCSR(kmfhandle, &csr, &prik, &signedCsr)) ==
+ KMF_OK) {
+ kmfrv = KMF_CreateCSRFile(&signedCsr, fmt, csrfile);
+ }
+
+cleanup:
+ (void) KMF_FreeData(&signedCsr);
+ (void) KMF_FreeKMFKey(kmfhandle, &prik);
+ /* delete the key */
+ (void) memset(&dk_params, 0, sizeof (dk_params));
+ dk_params.kstype = KMF_KEYSTORE_PK11TOKEN;
+ (void) KMF_DeleteKeyFromKeystore(kmfhandle, &dk_params, &pubk);
+ (void) KMF_FreeSignedCSR(&csr);
+
+ return (kmfrv);
+}
+
+static KMF_RETURN
+gencsr_file(KMF_HANDLE_T kmfhandle,
+ KMF_KEY_ALG keyAlg,
+ 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)
+{
+ KMF_RETURN kmfrv;
+ KMF_CREATEKEYPAIR_PARAMS kp_params;
+ KMF_KEY_HANDLE pubk, prik;
+ KMF_X509_NAME csrSubject;
+ KMF_CSR_DATA csr;
+ KMF_ALGORITHM_INDEX sigAlg;
+ KMF_DATA signedCsr = {NULL, 0};
+ char *fullcsrpath = NULL;
+ char *fullkeypath = NULL;
+
+ (void) memset(&csr, 0, sizeof (csr));
+ (void) memset(&csrSubject, 0, sizeof (csrSubject));
+ (void) memset(&kp_params, 0, sizeof (kp_params));
+
+ if (EMPTYSTRING(outcsr) || EMPTYSTRING(outkey)) {
+ cryptoerror(LOG_STDERR,
+ gettext("No output file was specified for "
+ "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);
+ }
+ if (verify_file(fullcsrpath)) {
+ cryptoerror(LOG_STDERR,
+ gettext("Cannot write the indicated output "
+ "certificate file (%s).\n"), fullcsrpath);
+ 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);
+ }
+ if (verify_file(fullcsrpath)) {
+ cryptoerror(LOG_STDERR,
+ gettext("Cannot write the indicated output "
+ "key file (%s).\n"), fullkeypath);
+ free(fullcsrpath);
+ return (PK_ERR_USAGE);
+ }
+
+ if (keyAlg == KMF_DSA)
+ sigAlg = KMF_ALGID_SHA1WithDSA;
+ else
+ sigAlg = KMF_ALGID_MD5WithRSA;
+
+ /* If the subject name cannot be parsed, flag it now and exit */
+ if ((kmfrv = KMF_DNParser(subject, &csrSubject)) != KMF_OK) {
+ return (kmfrv);
+ }
+
+ kp_params.kstype = KMF_KEYSTORE_OPENSSL;
+ kp_params.keylength = keylen; /* bits */
+ kp_params.keytype = keyAlg;
+
+ kp_params.sslparms.keyfile = fullkeypath;
+ kp_params.sslparms.format = fmt;
+
+ kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk);
+ if (kmfrv != KMF_OK) {
+ goto cleanup;
+ }
+ SET_VALUE(KMF_SetCSRPubKey(kmfhandle, &pubk, &csr),
+ "SetCSRPubKey");
+
+ SET_VALUE(KMF_SetCSRVersion(&csr, 2), "SetCSRVersion");
+
+ SET_VALUE(KMF_SetCSRSubjectName(&csr, &csrSubject),
+ "SetCSRSubjectName");
+
+ SET_VALUE(KMF_SetCSRSignatureAlgorithm(&csr, sigAlg),
+ "SetCSRSignatureAlgorithm");
+
+ if (altname != NULL) {
+ SET_VALUE(KMF_SetCSRSubjectAltName(&csr, altname, altcrit,
+ alttype), "SetCSRSubjectAltName");
+ }
+ if (kubits != NULL) {
+ SET_VALUE(KMF_SetCSRKeyUsage(&csr, kucrit, kubits),
+ "SetCSRKeyUsage");
+ }
+ if ((kmfrv = KMF_SignCSR(kmfhandle, &csr, &prik, &signedCsr)) ==
+ KMF_OK) {
+ kmfrv = KMF_CreateCSRFile(&signedCsr, fmt, fullcsrpath);
+ }
+
+cleanup:
+ if (fullkeypath)
+ free(fullkeypath);
+ if (fullcsrpath)
+ free(fullcsrpath);
+
+ KMF_FreeData(&signedCsr);
+ KMF_FreeKMFKey(kmfhandle, &prik);
+ KMF_FreeSignedCSR(&csr);
+
+ return (kmfrv);
+}
+
+static KMF_RETURN
+gencsr_nss(KMF_HANDLE_T kmfhandle,
+ char *token, char *subject, char *altname,
+ KMF_GENERALNAMECHOICES alttype, int altcrit,
+ char *nickname, char *dir, char *prefix,
+ KMF_KEY_ALG keyAlg, int keylen,
+ uint16_t kubits, int kucrit,
+ KMF_ENCODE_FORMAT fmt, char *csrfile,
+ KMF_CREDENTIAL *tokencred)
+{
+ KMF_RETURN kmfrv;
+ KMF_CREATEKEYPAIR_PARAMS kp_params;
+ KMF_KEY_HANDLE pubk, prik;
+ KMF_X509_NAME csrSubject;
+ KMF_CSR_DATA csr;
+ KMF_ALGORITHM_INDEX sigAlg;
+ KMF_DATA signedCsr = {NULL, 0};
+ KMF_DELETEKEY_PARAMS dk_params;
+
+ if (token == NULL)
+ token = DEFAULT_NSS_TOKEN;
+
+ if (keyAlg == KMF_DSA)
+ sigAlg = KMF_ALGID_SHA1WithDSA;
+ else
+ sigAlg = KMF_ALGID_MD5WithRSA;
+
+ kmfrv = configure_nss(kmfhandle, dir, prefix);
+ if (kmfrv != KMF_OK)
+ return (kmfrv);
+
+ (void) memset(&csr, 0, sizeof (csr));
+ (void) memset(&csrSubject, 0, sizeof (csrSubject));
+
+ /* If the subject name cannot be parsed, flag it now and exit */
+ if ((kmfrv = KMF_DNParser(subject, &csrSubject)) != KMF_OK) {
+ return (kmfrv);
+ }
+
+ (void) memset(&kp_params, 0, sizeof (kp_params));
+
+ kp_params.kstype = KMF_KEYSTORE_NSS;
+ kp_params.keylabel = nickname;
+ kp_params.keylength = keylen; /* bits */
+ kp_params.keytype = keyAlg;
+ kp_params.cred.cred = tokencred->cred;
+ kp_params.cred.credlen = tokencred->credlen;
+ kp_params.nssparms.slotlabel = token;
+
+ kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk);
+ if (kmfrv != KMF_OK) {
+ goto cleanup;
+ }
+
+ SET_VALUE(KMF_SetCSRPubKey(kmfhandle, &pubk, &csr), "SetCSRPubKey");
+ SET_VALUE(KMF_SetCSRVersion(&csr, 2), "SetCSRVersion");
+ SET_VALUE(KMF_SetCSRSubjectName(&csr, &csrSubject),
+ "SetCSRSubjectName");
+ SET_VALUE(KMF_SetCSRSignatureAlgorithm(&csr, sigAlg),
+ "SetCSRSignatureAlgorithm");
+
+ if (altname != NULL) {
+ SET_VALUE(KMF_SetCSRSubjectAltName(&csr, altname, altcrit,
+ alttype), "SetCSRSubjectAltName");
+ }
+ if (kubits != NULL) {
+ SET_VALUE(KMF_SetCSRKeyUsage(&csr, kucrit, kubits),
+ "SetCSRKeyUsage");
+ }
+ if ((kmfrv = KMF_SignCSR(kmfhandle, &csr, &prik, &signedCsr)) ==
+ KMF_OK) {
+ kmfrv = KMF_CreateCSRFile(&signedCsr, fmt, csrfile);
+ }
+
+cleanup:
+ (void) KMF_FreeData(&signedCsr);
+ (void) KMF_FreeKMFKey(kmfhandle, &prik);
+ /* delete the key */
+ (void) memset(&dk_params, 0, sizeof (dk_params));
+ dk_params.kstype = KMF_KEYSTORE_NSS;
+ dk_params.cred.cred = tokencred->cred;
+ dk_params.cred.credlen = tokencred->credlen;
+ dk_params.nssparms.slotlabel = token;
+ (void) KMF_DeleteKeyFromKeystore(kmfhandle, &dk_params, &pubk);
+ (void) KMF_FreeSignedCSR(&csr);
+
+ return (kmfrv);
+}
+
+int
+pk_gencsr(int argc, char *argv[])
+{
+ KMF_RETURN rv;
+ int opt;
+ extern int optind_av;
+ extern char *optarg_av;
+ KMF_KEYSTORE_TYPE kstype = 0;
+ char *subject = NULL;
+ char *tokenname = NULL;
+ char *dir = NULL;
+ char *prefix = NULL;
+ int keylen = PK_DEFAULT_KEYLENGTH;
+ char *certlabel = NULL;
+ char *outcsr = NULL;
+ char *outkey = NULL;
+ char *format = NULL;
+ char *altname = NULL;
+ char *kustr = NULL;
+ uint16_t kubits = 0;
+ char *keytype = PK_DEFAULT_KEYTYPE;
+ KMF_HANDLE_T kmfhandle = NULL;
+ KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
+ KMF_KEY_ALG keyAlg = KMF_RSA;
+ KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA;
+ boolean_t interactive = B_FALSE;
+ char *subname = NULL;
+ KMF_CREDENTIAL tokencred = {NULL, 0};
+ KMF_GENERALNAMECHOICES alttype = 0;
+ int altcrit = 0, kucrit = 0;
+
+ while ((opt = getopt_av(argc, argv,
+ "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
+ "u:(keyusage)T:(token)d:(dir)p:(prefix)t:(keytype)"
+ "y:(keylen)l:(label)c:(outcsr)"
+ "K:(outkey)F:(format)")) != EOF) {
+
+ if (opt != 'i' && EMPTYSTRING(optarg_av))
+ return (PK_ERR_USAGE);
+
+ switch (opt) {
+ case 'A':
+ altname = optarg_av;
+ break;
+ case 'i':
+ if (interactive || subject)
+ return (PK_ERR_USAGE);
+ else
+ interactive = B_TRUE;
+ break;
+ case 'k':
+ kstype = KS2Int(optarg_av);
+ if (kstype == 0)
+ return (PK_ERR_USAGE);
+ break;
+ case 's':
+ if (interactive || subject)
+ return (PK_ERR_USAGE);
+ else
+ subject = optarg_av;
+ break;
+ case 'l':
+ case 'n':
+ if (certlabel)
+ return (PK_ERR_USAGE);
+ certlabel = optarg_av;
+ break;
+ case 'T':
+ if (tokenname)
+ return (PK_ERR_USAGE);
+ tokenname = optarg_av;
+ break;
+ case 'd':
+ dir = optarg_av;
+ break;
+ case 'p':
+ if (prefix)
+ return (PK_ERR_USAGE);
+ prefix = optarg_av;
+ break;
+ case 't':
+ keytype = optarg_av;
+ break;
+ case 'u':
+ kustr = optarg_av;
+ break;
+ case 'y':
+ if (sscanf(optarg_av, "%d",
+ &keylen) != 1) {
+ cryptoerror(LOG_STDERR,
+ gettext("Unrecognized "
+ "key length (%s)\n"),
+ optarg_av);
+ return (PK_ERR_USAGE);
+ }
+ break;
+ case 'c':
+ if (outcsr)
+ return (PK_ERR_USAGE);
+ outcsr = optarg_av;
+ break;
+ case 'K':
+ if (outkey)
+ return (PK_ERR_USAGE);
+ outkey = optarg_av;
+ break;
+ case 'F':
+ if (format)
+ return (PK_ERR_USAGE);
+ format = optarg_av;
+ break;
+ default:
+ cryptoerror(LOG_STDERR, gettext(
+ "unrecognized gencsr option '%s'\n"),
+ argv[optind_av]);
+ return (PK_ERR_USAGE);
+ }
+ }
+ /* No additional args allowed. */
+ argc -= optind_av;
+ argv += optind_av;
+ if (argc) {
+ return (PK_ERR_USAGE);
+ }
+
+ if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
+ cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
+ return (PK_ERR_USAGE);
+ }
+
+ /* Assume keystore = PKCS#11 if not specified. */
+ if (kstype == 0)
+ kstype = KMF_KEYSTORE_PK11TOKEN;
+
+ if (EMPTYSTRING(outcsr)) {
+ (void) printf(gettext("A filename must be specified to hold"
+ "the final certificate request data.\n"));
+ return (PK_ERR_USAGE);
+ } else {
+ /*
+ * verify that the outcsr file does not already exist
+ * and that it can be created.
+ */
+ rv = verify_file(outcsr);
+ if (rv != KMF_OK) {
+ cryptoerror(LOG_STDERR, gettext("output file (%s) "
+ "cannot be created.\n"), outcsr);
+ return (PK_ERR_USAGE);
+ }
+ }
+
+ if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) &&
+ EMPTYSTRING(certlabel)) {
+ cryptoerror(LOG_STDERR, gettext("A label must be specified "
+ "to create a certificate request.\n"));
+ return (PK_ERR_USAGE);
+ } else if (kstype == KMF_KEYSTORE_OPENSSL && EMPTYSTRING(outkey)) {
+ cryptoerror(LOG_STDERR, gettext("A key filename must be "
+ "specified to create a certificate request.\n"));
+ return (PK_ERR_USAGE);
+ }
+
+ if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
+ cryptoerror(LOG_STDERR,
+ gettext("Error parsing format string (%s).\n"),
+ format);
+ return (PK_ERR_USAGE);
+ }
+ if (format && fmt != KMF_FORMAT_ASN1 && fmt != KMF_FORMAT_PEM) {
+ cryptoerror(LOG_STDERR,
+ gettext("CSR must be DER or PEM format.\n"));
+ return (PK_ERR_USAGE);
+ }
+
+ /*
+ * Check the subject name.
+ * If interactive is true, get it now interactively.
+ */
+ if (interactive) {
+ if (get_subname(&subname) != KMF_OK) {
+ cryptoerror(LOG_STDERR, gettext("Failed to get the "
+ "subject name interactively.\n"));
+ return (PK_ERR_USAGE);
+ }
+ } else {
+ if (EMPTYSTRING(subject)) {
+ cryptoerror(LOG_STDERR, gettext("A subject name or "
+ "-i must be specified to create a certificate "
+ "request.\n"));
+ return (PK_ERR_USAGE);
+ } else {
+ subname = strdup(subject);
+ if (subname == NULL) {
+ cryptoerror(LOG_STDERR,
+ gettext("Out of memory.\n"));
+ return (PK_ERR_SYSTEM);
+ }
+ }
+ }
+ if (altname != NULL) {
+ rv = verify_altname(altname, &alttype, &altcrit);
+ if (rv != KMF_OK) {
+ cryptoerror(LOG_STDERR, gettext("Subject AltName "
+ "must be specified as a name=value pair. "
+ "See the man page for details."));
+ goto end;
+ } else {
+ /* advance the altname past the '=' sign */
+ char *p = strchr(altname, '=');
+ if (p != NULL)
+ altname = p + 1;
+ }
+ }
+
+ if (kustr != NULL) {
+ rv = verify_keyusage(kustr, &kubits, &kucrit);
+ if (rv != KMF_OK) {
+ cryptoerror(LOG_STDERR, gettext("KeyUsage "
+ "must be specified as a comma-separated list. "
+ "See the man page for details."));
+ goto end;
+ }
+ }
+ if ((rv = Str2KeyType(keytype, &keyAlg, &sigAlg)) != 0) {
+ cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
+ keytype);
+ goto end;
+ }
+
+ if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
+ if (tokenname == NULL || !strlen(tokenname)) {
+ if (kstype == KMF_KEYSTORE_NSS) {
+ tokenname = "internal";
+ } else {
+ tokenname = PK_DEFAULT_PK11TOKEN;
+ }
+ }
+
+ (void) get_token_password(kstype, tokenname, &tokencred);
+ }
+
+ if (kstype == KMF_KEYSTORE_NSS) {
+ if (dir == NULL)
+ dir = PK_DEFAULT_DIRECTORY;
+
+ rv = gencsr_nss(kmfhandle,
+ tokenname, subname, altname, alttype, altcrit,
+ certlabel, dir, prefix,
+ keyAlg, keylen, kubits, kucrit,
+ fmt, outcsr, &tokencred);
+
+ } else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
+ rv = gencsr_pkcs11(kmfhandle,
+ tokenname, subname, altname, alttype, altcrit,
+ certlabel, keyAlg, keylen,
+ kubits, kucrit, fmt, outcsr, &tokencred);
+
+ } else if (kstype == KMF_KEYSTORE_OPENSSL) {
+ rv = gencsr_file(kmfhandle,
+ keyAlg, keylen, fmt, subname, altname,
+ alttype, altcrit, kubits, kucrit,
+ dir, outcsr, outkey);
+ }
+
+end:
+ if (rv != KMF_OK)
+ display_error(kmfhandle, rv,
+ gettext("Error creating CSR or keypair"));
+
+ if (subname)
+ free(subname);
+
+ if (tokencred.cred != NULL)
+ free(tokencred.cred);
+
+ (void) KMF_Finalize(kmfhandle);
+ if (rv != KMF_OK)
+ return (PK_ERR_USAGE);
+
+ return (0);
+}
diff --git a/usr/src/cmd/cmd-crypto/pktool/genkey.c b/usr/src/cmd/cmd-crypto/pktool/genkey.c
new file mode 100644
index 0000000000..f94093029e
--- /dev/null
+++ b/usr/src/cmd/cmd-crypto/pktool/genkey.c
@@ -0,0 +1,450 @@
+/*
+ * 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 <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <malloc.h>
+#include <libgen.h>
+#include <errno.h>
+#include <cryptoutil.h>
+#include <security/cryptoki.h>
+#include "common.h"
+#include <kmfapi.h>
+
+
+static KMF_RETURN
+genkey_nss(KMF_HANDLE_T kmfhandle, char *token, char *dir, char *prefix,
+ char *keylabel, KMF_KEY_ALG keyAlg, int keylen, KMF_CREDENTIAL *tokencred)
+{
+ KMF_RETURN kmfrv = KMF_OK;
+ KMF_CREATESYMKEY_PARAMS csk_params;
+ KMF_KEY_HANDLE key;
+
+ if (keylabel == NULL) {
+ cryptoerror(LOG_STDERR,
+ gettext("A key label must be specified \n"));
+ return (KMF_ERR_BAD_PARAMETER);
+ }
+
+ kmfrv = configure_nss(kmfhandle, dir, prefix);
+ if (kmfrv != KMF_OK)
+ return (kmfrv);
+
+ (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
+ csk_params.kstype = KMF_KEYSTORE_NSS;
+ csk_params.nssparms.slotlabel = token;
+ csk_params.keytype = keyAlg;
+ csk_params.keylength = keylen;
+ csk_params.keylabel = keylabel;
+ csk_params.cred.cred = tokencred->cred;
+ csk_params.cred.credlen = tokencred->credlen;
+ kmfrv = KMF_CreateSymKey(kmfhandle, &csk_params, &key);
+
+ return (kmfrv);
+}
+
+static KMF_RETURN
+genkey_pkcs11(KMF_HANDLE_T kmfhandle, char *token,
+ char *keylabel, KMF_KEY_ALG keyAlg, int keylen,
+ char *senstr, char *extstr, boolean_t print_hex,
+ KMF_CREDENTIAL *tokencred)
+{
+ KMF_RETURN kmfrv = KMF_OK;
+ KMF_CREATESYMKEY_PARAMS params;
+ KMF_KEY_HANDLE key;
+ KMF_RAW_SYM_KEY *rkey = NULL;
+ boolean_t sensitive = B_FALSE;
+ boolean_t not_extractable = B_FALSE;
+ char *hexstr = NULL;
+ int hexstrlen;
+
+ if (keylabel == NULL) {
+ cryptoerror(LOG_STDERR,
+ gettext("A key label must be specified \n"));
+ return (KMF_ERR_BAD_PARAMETER);
+ }
+
+ /* Check the sensitive option value if specified. */
+ if (senstr != NULL) {
+ if (tolower(senstr[0]) == 'y')
+ sensitive = B_TRUE;
+ else if (tolower(senstr[0]) == 'n')
+ sensitive = B_FALSE;
+ else {
+ cryptoerror(LOG_STDERR,
+ gettext("Incorrect sensitive option value.\n"));
+ return (KMF_ERR_BAD_PARAMETER);
+ }
+ }
+
+ /* Check the extractable option value if specified. */
+ if (extstr != NULL) {
+ if (tolower(extstr[0]) == 'y')
+ not_extractable = B_FALSE;
+ else if (tolower(extstr[0]) == 'n')
+ not_extractable = B_TRUE;
+ else {
+ cryptoerror(LOG_STDERR,
+ gettext("Incorrect extractable option value.\n"));
+ return (KMF_ERR_BAD_PARAMETER);
+ }
+ }
+
+ /* Select a PKCS11 token first */
+ kmfrv = select_token(kmfhandle, token, FALSE);
+ if (kmfrv != KMF_OK) {
+ return (kmfrv);
+ }
+
+ (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
+ params.kstype = KMF_KEYSTORE_PK11TOKEN;
+ params.keytype = keyAlg;
+ params.keylength = keylen; /* bits */
+ params.keylabel = keylabel;
+ params.pkcs11parms.sensitive = sensitive;
+ params.pkcs11parms.not_extractable = not_extractable;
+ params.cred.cred = tokencred->cred;
+ params.cred.credlen = tokencred->credlen;
+ kmfrv = KMF_CreateSymKey(kmfhandle, &params, &key);
+ if (kmfrv != KMF_OK) {
+ goto out;
+ }
+
+ if (print_hex) {
+ if (sensitive == B_TRUE || not_extractable == B_TRUE) {
+ cryptoerror(LOG_STDERR,
+ gettext("Warning: can not reveal the key value "
+ "for a sensitive or non-extractable key.\n"));
+ goto out;
+ } else {
+ rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
+ if (rkey == NULL) {
+ kmfrv = KMF_ERR_MEMORY;
+ goto out;
+ }
+ (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
+ kmfrv = KMF_GetSymKeyValue(kmfhandle, &key, rkey);
+ if (kmfrv != KMF_OK) {
+ goto out;
+ }
+ hexstrlen = 2 * rkey->keydata.len + 1;
+ hexstr = malloc(hexstrlen);
+ if (hexstr == NULL) {
+ kmfrv = KMF_ERR_MEMORY;
+ goto out;
+ }
+
+ tohexstr(rkey->keydata.val, rkey->keydata.len, hexstr,
+ hexstrlen);
+ (void) printf(gettext("\tKey Value =\"%s\"\n"), hexstr);
+ }
+ }
+
+out:
+ KMF_FreeRawSymKey(rkey);
+
+ if (hexstr != NULL)
+ free(hexstr);
+
+ return (kmfrv);
+}
+
+
+static KMF_RETURN
+genkey_file(KMF_HANDLE_T kmfhandle, KMF_KEY_ALG keyAlg, int keylen, char *dir,
+ char *outkey, boolean_t print_hex)
+{
+ KMF_RETURN kmfrv = KMF_OK;
+ KMF_CREATESYMKEY_PARAMS csk_params;
+ KMF_KEY_HANDLE key;
+ KMF_RAW_SYM_KEY *rkey = NULL;
+ char *hexstr = NULL;
+ int hexstrlen;
+
+ if (EMPTYSTRING(outkey)) {
+ cryptoerror(LOG_STDERR,
+ gettext("No output key file was specified for the key\n"));
+ return (KMF_ERR_BAD_PARAMETER);
+ }
+
+ if (verify_file(outkey)) {
+ cryptoerror(LOG_STDERR,
+ gettext("Cannot write the indicated output "
+ "key file (%s).\n"), outkey);
+ return (KMF_ERR_BAD_PARAMETER);
+ }
+
+ (void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
+ csk_params.kstype = KMF_KEYSTORE_OPENSSL;
+ csk_params.keytype = keyAlg;
+ csk_params.keylength = keylen;
+ csk_params.cred.cred = NULL;
+ csk_params.cred.credlen = 0;
+ csk_params.sslparms.dirpath = (dir == NULL) ? "." : dir;
+ csk_params.sslparms.keyfile = outkey;
+
+ kmfrv = KMF_CreateSymKey(kmfhandle, &csk_params, &key);
+ if (kmfrv != KMF_OK) {
+ goto out;
+ }
+
+ if (print_hex) {
+ rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
+ if (rkey == NULL) {
+ kmfrv = KMF_ERR_MEMORY;
+ goto out;
+ }
+ (void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
+ kmfrv = KMF_GetSymKeyValue(kmfhandle, &key, rkey);
+ if (kmfrv != KMF_OK) {
+ goto out;
+ }
+
+ hexstrlen = 2 * rkey->keydata.len + 1;
+ hexstr = malloc(hexstrlen);
+ if (hexstr == NULL) {
+ kmfrv = KMF_ERR_MEMORY;
+ goto out;
+ }
+ tohexstr(rkey->keydata.val, rkey->keydata.len, hexstr,
+ hexstrlen);
+ (void) printf(gettext("\tKey Value =\"%s\"\n"), hexstr);
+ }
+
+out:
+ KMF_FreeRawSymKey(rkey);
+
+ if (hexstr != NULL)
+ free(hexstr);
+
+ return (kmfrv);
+}
+
+int
+pk_genkey(int argc, char *argv[])
+{
+ int rv;
+ int opt;
+ extern int optind_av;
+ extern char *optarg_av;
+ KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
+ char *tokenname = NULL;
+ char *dir = NULL;
+ char *prefix = NULL;
+ char *keytype = "AES";
+ char *keylenstr = NULL;
+ int keylen = 0;
+ char *keylabel = NULL;
+ char *outkey = NULL;
+ char *senstr = NULL;
+ char *extstr = NULL;
+ char *printstr = NULL;
+ KMF_HANDLE_T kmfhandle = NULL;
+ KMF_KEY_ALG keyAlg = KMF_AES;
+ boolean_t print_hex = B_FALSE;
+ KMF_CREDENTIAL tokencred = {NULL, 0};
+
+ while ((opt = getopt_av(argc, argv,
+ "k:(keystore)l:(label)T:(token)d:(dir)p:(prefix)"
+ "t:(keytype)y:(keylen)K:(outkey)P:(print)"
+ "s:(sensitive)e:(extractable)")) != EOF) {
+ if (EMPTYSTRING(optarg_av))
+ return (PK_ERR_USAGE);
+ switch (opt) {
+ case 'k':
+ kstype = KS2Int(optarg_av);
+ if (kstype == 0)
+ return (PK_ERR_USAGE);
+ break;
+ case 'l':
+ if (keylabel)
+ return (PK_ERR_USAGE);
+ keylabel = optarg_av;
+ break;
+ case 'T':
+ if (tokenname)
+ return (PK_ERR_USAGE);
+ tokenname = optarg_av;
+ break;
+ case 'd':
+ if (dir)
+ return (PK_ERR_USAGE);
+ dir = optarg_av;
+ break;
+ case 'p':
+ if (prefix)
+ return (PK_ERR_USAGE);
+ prefix = optarg_av;
+ break;
+ case 't':
+ keytype = optarg_av;
+ break;
+ case 'y':
+ if (keylenstr)
+ return (PK_ERR_USAGE);
+ keylenstr = optarg_av;
+ break;
+ case 'K':
+ if (outkey)
+ return (PK_ERR_USAGE);
+ outkey = optarg_av;
+ break;
+ case 'P':
+ if (printstr)
+ return (PK_ERR_USAGE);
+ printstr = optarg_av;
+ break;
+ case 's':
+ if (senstr)
+ return (PK_ERR_USAGE);
+ senstr = optarg_av;
+ break;
+ case 'e':
+ if (extstr)
+ return (PK_ERR_USAGE);
+ extstr = optarg_av;
+ break;
+ default:
+ return (PK_ERR_USAGE);
+ }
+ }
+
+ /* No additional args allowed. */
+ argc -= optind_av;
+ argv += optind_av;
+ if (argc) {
+ return (PK_ERR_USAGE);
+ }
+
+ /* Check keytype. If not specified, default to AES */
+ if (keytype != NULL && Str2SymKeyType(keytype, &keyAlg) != 0) {
+ cryptoerror(LOG_STDERR, gettext("Unrecognized keytype(%s).\n"),
+ keytype);
+ return (PK_ERR_USAGE);
+ }
+
+ /*
+ * Check and set the key length.
+ * - For DES and 3DES, the key size are fixed. Ingore the keylen
+ * option, even if it is specified.
+ * - For AES and ARCFOUR, if keylen is not specified, default to
+ * 128 bits.
+ */
+ if (keyAlg == KMF_DES)
+ keylen = 64; /* fixed size; ignore input */
+ else if (keyAlg == KMF_DES3)
+ keylen = 192; /* fixed size; ignore input */
+ else /* AES or ARCFOUR */ {
+ if (keylenstr == NULL) {
+ cryptoerror(LOG_STDERR,
+ gettext("Key length must be specified "
+ "for AES and ARCFOUR symmetric keys.\n"));
+ return (PK_ERR_USAGE);
+ }
+ if (sscanf(keylenstr, "%d", &keylen) != 1) {
+ cryptoerror(LOG_STDERR,
+ gettext("Unrecognized key length (%s).\n"),
+ keytype);
+ return (PK_ERR_USAGE);
+ }
+ if (keylen == 0 || (keylen % 8) != 0) {
+ cryptoerror(LOG_STDERR,
+ gettext("Key length bitlength must be a "
+ "multiple of 8.\n"));
+ return (PK_ERR_USAGE);
+ }
+ }
+
+ /* check the print option */
+ if (printstr != NULL) {
+ if (kstype == KMF_KEYSTORE_NSS) {
+ cryptoerror(LOG_STDERR,
+ gettext("The print option does not apply "
+ "to the NSS keystore.\n"));
+ return (PK_ERR_USAGE);
+ }
+
+ if (tolower(printstr[0]) == 'y')
+ print_hex = B_TRUE;
+ else if (tolower(printstr[0]) == 'n')
+ print_hex = B_FALSE;
+ else {
+ cryptoerror(LOG_STDERR,
+ gettext("Incorrect print option value.\n"));
+ return (PK_ERR_USAGE);
+ }
+ }
+
+ /* check the sensitive and extractable options */
+ if ((senstr != NULL || extstr != NULL) &&
+ (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_OPENSSL)) {
+ cryptoerror(LOG_STDERR,
+ gettext("The sensitive or extractable option applies "
+ "to the PKCS11 keystore only.\n"));
+ return (PK_ERR_USAGE);
+ }
+
+ if (kstype == KMF_KEYSTORE_PK11TOKEN && tokenname == NULL) {
+ tokenname = PK_DEFAULT_PK11TOKEN;
+ } else if (kstype == KMF_KEYSTORE_NSS && tokenname == NULL) {
+ tokenname = DEFAULT_NSS_TOKEN;
+ }
+
+ if (kstype == KMF_KEYSTORE_PK11TOKEN || kstype == KMF_KEYSTORE_NSS)
+ (void) get_token_password(kstype, tokenname, &tokencred);
+
+ if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
+ cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
+ goto end;
+ }
+
+ if (kstype == KMF_KEYSTORE_NSS) {
+ rv = genkey_nss(kmfhandle, tokenname, dir, prefix,
+ keylabel, keyAlg, keylen, &tokencred);
+ } else if (kstype == KMF_KEYSTORE_OPENSSL) {
+ rv = genkey_file(kmfhandle, keyAlg, keylen, dir, outkey,
+ print_hex);
+ } else {
+ rv = genkey_pkcs11(kmfhandle, tokenname, keylabel, keyAlg,
+ keylen, senstr, extstr, print_hex, &tokencred);
+ }
+
+end:
+ if (rv != KMF_OK)
+ display_error(kmfhandle, rv,
+ gettext("Error generating key"));
+
+ if (tokencred.cred != NULL)
+ free(tokencred.cred);
+
+ (void) KMF_Finalize(kmfhandle);
+ if (rv != KMF_OK)
+ return (PK_ERR_USAGE);
+
+ return (0);
+}
diff --git a/usr/src/cmd/cmd-crypto/pktool/import.c b/usr/src/cmd/cmd-crypto/pktool/import.c
index 0afba0ef2e..ac706b82ab 100644
--- a/usr/src/cmd/cmd-crypto/pktool/import.c
+++ b/usr/src/cmd/cmd-crypto/pktool/import.c
@@ -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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -37,754 +36,354 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <cryptoutil.h>
-#include <security/cryptoki.h>
#include "common.h"
-#include "biginteger.h"
-#include "osslcommon.h"
-#include "p12common.h"
-#include <openssl/pkcs12.h>
-#include <openssl/err.h>
-/*
- * Helper function decrypt and parse PKCS#12 import file.
- */
-static CK_RV
-extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
- EVP_PKEY **priv_key, X509 **cert, STACK_OF(X509) **ca)
-/* ARGSUSED */
+#include <kmfapi.h>
+
+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)
{
- PKCS12 *pk12, *pk12_tmp;
- EVP_PKEY *temp_pkey = NULL;
- X509 *temp_cert = NULL;
- STACK_OF(X509) *temp_ca = NULL;
-
- cryptodebug("inside extract_pkcs12");
-
- cryptodebug("calling PKCS12_new");
- if ((pk12 = PKCS12_new()) == NULL) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to create PKCS#12 context."));
- return (CKR_GENERAL_ERROR);
+ KMF_RETURN rv = KMF_OK;
+ KMF_DATA *certs = NULL;
+ KMF_RAW_KEY_DATA *keys = NULL;
+ int ncerts = 0;
+ int nkeys = 0;
+ int i;
+
+ rv = KMF_ImportPK12(kmfhandle, outfile, cred,
+ &certs, &ncerts, &keys, &nkeys);
+
+ if (rv == KMF_OK) {
+ (void) printf(gettext("Found %d certificate(s) and %d "
+ "key(s) in %s\n"), ncerts, nkeys, outfile);
+ }
+
+ if (rv == KMF_OK && ncerts > 0) {
+ KMF_STORECERT_PARAMS params;
+ char newcertfile[MAXPATHLEN];
+
+ (void) memset(&params, 0, sizeof (KMF_STORECERT_PARAMS));
+ params.kstype = KMF_KEYSTORE_OPENSSL;
+ params.sslparms.dirpath = dir;
+ params.sslparms.format = outformat;
+
+ for (i = 0; rv == KMF_OK && i < ncerts; i++) {
+ /*
+ * If storing more than 1 cert, gotta change
+ * the name so we don't overwrite the previous one.
+ * Just append a _# to the name.
+ */
+ if (i > 0) {
+ (void) snprintf(newcertfile,
+ sizeof (newcertfile),
+ "%s_%d", certfile, i);
+ params.sslparms.certfile = newcertfile;
+ } else {
+ params.sslparms.certfile = certfile;
+ }
+ rv = KMF_StoreCert(kmfhandle, &params, &certs[i]);
+ }
}
-
- cryptodebug("calling d2i_PKCS12_bio");
- if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
- /* This is ok; it seems to mean there is no more to read. */
- if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
- ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
- goto end_extract_pkcs12;
-
- cryptoerror(LOG_STDERR, gettext(
- "Unable to populate PKCS#12 context."));
- PKCS12_free(pk12);
- return (CKR_GENERAL_ERROR);
+ if (rv == KMF_OK && nkeys > 0) {
+ KMF_STOREKEY_PARAMS skparms;
+ char newkeyfile[MAXPATHLEN];
+
+ (void) memset(&skparms, 0, sizeof (skparms));
+
+ /* The order of certificates and keys should match */
+ for (i = 0; rv == KMF_OK && i < nkeys; i++) {
+ skparms.kstype = KMF_KEYSTORE_OPENSSL;
+ skparms.sslparms.dirpath = keydir;
+ skparms.sslparms.format = outformat;
+ skparms.cred = *cred;
+ skparms.certificate = &certs[i];
+
+ if (i > 0) {
+ (void) snprintf(newkeyfile,
+ sizeof (newkeyfile),
+ "%s_%d", keyfile, i);
+ skparms.sslparms.keyfile = newkeyfile;
+ } else {
+ skparms.sslparms.keyfile = keyfile;
+ }
+
+ rv = KMF_StorePrivateKey(kmfhandle, &skparms,
+ &keys[i]);
+ }
}
- pk12 = pk12_tmp;
-
- cryptodebug("calling PKCS12_parse");
- if (PKCS12_parse(pk12, (char *)pin, &temp_pkey, &temp_cert,
- &temp_ca) <= 0) {
- cryptoerror(LOG_STDERR,
- gettext("Unable to parse import file."));
- PKCS12_free(pk12);
- return (CKR_GENERAL_ERROR);
+ /*
+ * Cleanup memory.
+ */
+ if (certs) {
+ for (i = 0; i < ncerts; i++)
+ KMF_FreeData(&certs[i]);
+ free(certs);
+ }
+ if (keys) {
+ for (i = 0; i < nkeys; i++)
+ KMF_FreeRawKey(&keys[i]);
+ free(keys);
}
-end_extract_pkcs12:
-
- *priv_key = temp_pkey;
- *cert = temp_cert;
- *ca = temp_ca;
- PKCS12_free(pk12);
- return (CKR_OK);
+ return (rv);
}
-/*
- * Converts OpenSSL BIGNUM into PKCS#11 biginteger_t format.
- */
-static CK_RV
-cvt_bn2bigint(BIGNUM *from, biginteger_t *to)
+
+static KMF_RETURN
+pk_import_pk12_nss(
+ KMF_HANDLE_T kmfhandle, KMF_CREDENTIAL *kmfcred,
+ KMF_CREDENTIAL *tokencred,
+ char *token_spec, char *dir, char *prefix,
+ char *nickname, char *trustflags, char *filename)
{
- CK_BYTE *temp;
- CK_ULONG temp_alloc_sz, temp_cvt_sz;
+ KMF_RETURN rv = KMF_OK;
+ KMF_DATA *certs = NULL;
+ KMF_RAW_KEY_DATA *keys = NULL;
+ int ncerts = 0;
+ int nkeys = 0;
+ int i;
+
+ rv = configure_nss(kmfhandle, dir, prefix);
+ if (rv != KMF_OK)
+ return (rv);
- cryptodebug("inside cvt_bn2bigint");
+ rv = KMF_ImportPK12(kmfhandle, filename, kmfcred,
+ &certs, &ncerts, &keys, &nkeys);
- if (from == NULL || to == NULL)
- return (CKR_ARGUMENTS_BAD);
+ if (rv == KMF_OK)
+ (void) printf(gettext("Found %d certificate(s) and %d "
+ "key(s) in %s\n"), ncerts, nkeys, filename);
- cryptodebug("calling BN_num_bytes");
- temp_alloc_sz = BN_num_bytes(from);
- if ((temp = malloc(temp_alloc_sz)) == NULL)
- return (CKR_HOST_MEMORY);
+ if (rv == KMF_OK) {
+ KMF_STORECERT_PARAMS params;
- cryptodebug("calling BN_bn2bin");
- temp_cvt_sz = BN_bn2bin(from, (unsigned char *)temp);
- if (temp_cvt_sz != temp_alloc_sz)
- return (CKR_GENERAL_ERROR);
+ (void) memset(&params, 0, sizeof (KMF_STORECERT_PARAMS));
+ params.kstype = KMF_KEYSTORE_NSS;
+ params.nssparms.slotlabel = token_spec;
+ params.nssparms.trustflag = trustflags;
- to->big_value = temp;
- to->big_value_len = temp_cvt_sz;
- return (CKR_OK);
-}
+ for (i = 0; rv == KMF_OK && i < ncerts; i++) {
+ if (i == 0)
+ params.certLabel = nickname;
+ else
+ params.certLabel = NULL;
-/*
- * Write RSA private key to token.
- */
-static CK_RV
-write_rsa_private(CK_SESSION_HANDLE sess, RSA *rsa, X509 *cert)
-{
- CK_RV rv = CKR_OK;
- int i = 0;
- static CK_OBJECT_CLASS objclass = CKO_PRIVATE_KEY;
- static CK_KEY_TYPE keytype = CKK_RSA;
- CK_BYTE *label = NULL;
- CK_ULONG label_len = 0;
- CK_BYTE *id = NULL;
- CK_ULONG id_len = 0;
- CK_DATE startdate = { "", "", "" };
- CK_DATE enddate = { "", "", "" };
- char tmpdate[8];
- biginteger_t mod = { NULL, 0 }; /* required */
- biginteger_t pubexp = { NULL, 0 }; /* required */
- biginteger_t priexp = { NULL, 0 }; /* optional */
- biginteger_t prime1 = { NULL, 0 }; /* optional */
- biginteger_t prime2 = { NULL, 0 }; /* optional */
- biginteger_t exp1 = { NULL, 0 }; /* optional */
- biginteger_t exp2 = { NULL, 0 }; /* optional */
- biginteger_t coef = { NULL, 0 }; /* optional */
- CK_ATTRIBUTE rsa_pri_attrs[16] = {
- { CKA_CLASS, &objclass, sizeof (objclass) },
- { CKA_KEY_TYPE, &keytype, sizeof (keytype) },
- { CKA_PRIVATE, &pk_true, sizeof (pk_true) },
- { CKA_TOKEN, &pk_true, sizeof (pk_true) },
- { CKA_LABEL, NULL, 0 },
- { CKA_ID, NULL, 0 },
- { CKA_START_DATE, NULL, 0 },
- { CKA_END_DATE, NULL, 0 },
- { CKA_MODULUS, NULL, 0 },
- { CKA_PUBLIC_EXPONENT, NULL, 0 },
- { 0 /* CKA_PRIVATE_EXPONENT */, NULL, 0 }, /* optional */
- { 0 /* CKA_PRIME_1 */, NULL, 0 }, /* | */
- { 0 /* CKA_PRIME_2 */, NULL, 0 }, /* | */
- { 0 /* CKA_EXPONENT_1 */, NULL, 0 }, /* | */
- { 0 /* CKA_EXPONENT_2 */, NULL, 0 }, /* | */
- { 0 /* CKA_COEFFICIENT */, NULL, 0 } /* V */
- };
- CK_ULONG count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
- CK_OBJECT_HANDLE obj;
-
- cryptodebug("inside write_rsa_private");
-
- /* Attributes start at array index 4. */
- i = 4;
-
- /* Recycle the certificate label for the private key label. */
- cryptodebug("calling X509_alias_get0");
- if ((label = X509_alias_get0(cert, (int *)&label_len)) == NULL) {
- label = (CK_BYTE *)gettext("no label");
- label_len = strlen((char *)label);
- }
- copy_string_to_attr(label, label_len, &(rsa_pri_attrs[i++]));
-
- /* Recycle the certificate id for the private key id. */
- cryptodebug("calling PKTOOL_X509_keyid_get0");
- if ((id = PKTOOL_X509_keyid_get0(cert, (int *)&id_len)) == NULL) {
- id = (CK_BYTE *)gettext("no id");
- id_len = strlen((char *)id);
- }
- copy_string_to_attr(id, id_len, &(rsa_pri_attrs[i++]));
-
- /* Recycle the certificate start and end dates for private key. */
- cryptodebug("calling X509_get_notBefore");
- if (PKTOOL_cvt_ossltime(X509_get_notBefore(cert), tmpdate)) {
- (void) memcpy(&startdate, tmpdate, sizeof (startdate));
- copy_string_to_attr((CK_BYTE *)&startdate, sizeof (startdate),
- &(rsa_pri_attrs[i++]));
- }
-
- cryptodebug("calling X509_get_notAfter");
- if (PKTOOL_cvt_ossltime(X509_get_notAfter(cert), tmpdate)) {
- (void) memcpy(&enddate, tmpdate, sizeof (enddate));
- copy_string_to_attr((CK_BYTE *)&enddate, sizeof (enddate),
- &(rsa_pri_attrs[i++]));
- }
-
- /* Modulus n */
- cryptodebug("converting RSA private key modulus");
- if ((rv = cvt_bn2bigint(rsa->n, &mod)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert RSA private key modulus."));
- return (rv);
- }
- copy_bigint_to_attr(mod, &(rsa_pri_attrs[i++]));
-
- /* Public exponent e */
- cryptodebug("converting RSA private key public exponent");
- if ((rv = cvt_bn2bigint(rsa->e, &pubexp)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert RSA private key public exponent."));
- return (rv);
- }
- copy_bigint_to_attr(pubexp, &(rsa_pri_attrs[i++]));
-
- /* Private exponent d */
- if (rsa->d != NULL) {
- cryptodebug("converting RSA private key private exponent");
- if ((rv = cvt_bn2bigint(rsa->d, &priexp)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext("Unable to convert "
- "RSA private key private exponent."));
- return (rv);
- }
- rsa_pri_attrs[i].type = CKA_PRIVATE_EXPONENT;
- copy_bigint_to_attr(priexp, &(rsa_pri_attrs[i++]));
- } else
- cryptodebug("no RSA private key private exponent");
-
- /* Prime p */
- if (rsa->p != NULL) {
- cryptodebug("converting RSA private key prime 1");
- if ((rv = cvt_bn2bigint(rsa->p, &prime1)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert RSA private key prime 1."));
- return (rv);
- }
- rsa_pri_attrs[i].type = CKA_PRIME_1;
- copy_bigint_to_attr(prime1, &(rsa_pri_attrs[i++]));
- } else
- cryptodebug("no RSA private key prime 1");
-
- /* Prime q */
- if (rsa->q != NULL) {
- cryptodebug("converting RSA private key prime 2");
- if ((rv = cvt_bn2bigint(rsa->q, &prime2)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert RSA private key prime 2."));
- return (rv);
- }
- rsa_pri_attrs[i].type = CKA_PRIME_2;
- copy_bigint_to_attr(prime2, &(rsa_pri_attrs[i++]));
- } else
- cryptodebug("no RSA private key prime 2");
-
- /* Private exponent d modulo p-1 */
- if (rsa->dmp1 != NULL) {
- cryptodebug("converting RSA private key exponent 1");
- if ((rv = cvt_bn2bigint(rsa->dmp1, &exp1)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert RSA private key exponent 1."));
- return (rv);
- }
- rsa_pri_attrs[i].type = CKA_EXPONENT_1;
- copy_bigint_to_attr(exp1, &(rsa_pri_attrs[i++]));
- } else
- cryptodebug("no RSA private key exponent 1");
-
- /* Private exponent d modulo q-1 */
- if (rsa->dmq1 != NULL) {
- cryptodebug("converting RSA private key exponent 2");
- if ((rv = cvt_bn2bigint(rsa->dmq1, &exp2)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert RSA private key exponent 2."));
- return (rv);
+ rv = KMF_StoreCert(kmfhandle, &params, &certs[i]);
}
- rsa_pri_attrs[i].type = CKA_EXPONENT_2;
- copy_bigint_to_attr(exp2, &(rsa_pri_attrs[i++]));
- } else
- cryptodebug("no RSA private key exponent 2");
-
- /* CRT coefficient q-inverse mod p */
- if (rsa->iqmp != NULL) {
- cryptodebug("converting RSA private key coefficient");
- if ((rv = cvt_bn2bigint(rsa->iqmp, &coef)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert RSA private key coefficient."));
- return (rv);
+ if (rv != KMF_OK) {
+ display_error(kmfhandle, rv,
+ gettext("Error storing certificate "
+ "in PKCS11 token"));
}
- rsa_pri_attrs[i].type = CKA_COEFFICIENT;
- copy_bigint_to_attr(coef, &(rsa_pri_attrs[i++]));
- } else
- cryptodebug("no RSA private key coefficient");
-
- /* Indicates programming error: attributes overran the template */
- if (i > count) {
- cryptodebug("error: more attributes found than accounted for");
- i = count;
}
- cryptodebug("calling C_CreateObject");
- if ((rv = C_CreateObject(sess, rsa_pri_attrs, i, &obj)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to create RSA private key object."));
- return (rv);
- }
+ if (rv == KMF_OK) {
+ KMF_STOREKEY_PARAMS skparms;
- return (CKR_OK);
-}
+ /* The order of certificates and keys should match */
+ for (i = 0; i < nkeys; i++) {
+ (void) memset(&skparms, 0,
+ sizeof (KMF_STOREKEY_PARAMS));
+ skparms.kstype = KMF_KEYSTORE_NSS;
+ skparms.cred = *tokencred;
+ skparms.label = nickname;
+ skparms.certificate = &certs[i];
+ skparms.nssparms.slotlabel = token_spec;
-/*
- * Write DSA private key to token.
- */
-static CK_RV
-write_dsa_private(CK_SESSION_HANDLE sess, DSA *dsa, X509 *cert)
-{
- CK_RV rv = CKR_OK;
- int i = 0;
- static CK_OBJECT_CLASS objclass = CKO_PRIVATE_KEY;
- static CK_KEY_TYPE keytype = CKK_DSA;
- CK_BYTE *label = NULL;
- CK_ULONG label_len = 0;
- CK_BYTE *id = NULL;
- CK_ULONG id_len = 0;
- CK_DATE startdate = { "", "", "" };
- CK_DATE enddate = { "", "", "" };
- char tmpdate[8];
- biginteger_t prime = { NULL, 0 }; /* required */
- biginteger_t subprime = { NULL, 0 }; /* required */
- biginteger_t base = { NULL, 0 }; /* required */
- biginteger_t value = { NULL, 0 }; /* required */
- CK_ATTRIBUTE dsa_pri_attrs[12] = {
- { CKA_CLASS, &objclass, sizeof (objclass) },
- { CKA_KEY_TYPE, &keytype, sizeof (keytype) },
- { CKA_PRIVATE, &pk_true, sizeof (pk_true) },
- { CKA_TOKEN, &pk_true, sizeof (pk_true) },
- { CKA_LABEL, NULL, 0 },
- { CKA_ID, NULL, 0 },
- { CKA_START_DATE, NULL, 0 },
- { CKA_END_DATE, NULL, 0 },
- { CKA_PRIME, NULL, 0 },
- { CKA_SUBPRIME, NULL, 0 },
- { CKA_BASE, NULL, 0 },
- { CKA_VALUE, NULL, 0 }
- };
- CK_ULONG count = sizeof (dsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
- CK_OBJECT_HANDLE obj;
-
- cryptodebug("inside write_dsa_private");
-
- /* Attributes start at array index 4. */
- i = 4;
-
- /* Recycle the certificate label for the private key label. */
- cryptodebug("calling X509_alias_get0");
- if ((label = X509_alias_get0(cert, (int *)&label_len)) == NULL) {
- label = (CK_BYTE *)gettext("no label");
- label_len = strlen((char *)label);
+ rv = KMF_StorePrivateKey(kmfhandle, &skparms, &keys[i]);
+ }
}
- copy_string_to_attr(label, label_len, &(dsa_pri_attrs[i++]));
- /* Recycle the certificate id for the private key id. */
- cryptodebug("calling PKTOOL_X509_keyid_get0");
- if ((id = PKTOOL_X509_keyid_get0(cert, (int *)&id_len)) == NULL) {
- id = (CK_BYTE *)gettext("no id");
- id_len = strlen((char *)id);
+ /*
+ * Cleanup memory.
+ */
+ if (certs) {
+ for (i = 0; i < ncerts; i++)
+ KMF_FreeData(&certs[i]);
+ free(certs);
}
- copy_string_to_attr(id, id_len, &(dsa_pri_attrs[i++]));
-
- /* Recycle the certificate start and end dates for private key. */
- cryptodebug("calling X509_get_notBefore");
- if (PKTOOL_cvt_ossltime(X509_get_notBefore(cert), tmpdate)) {
- (void) memcpy(&startdate, tmpdate, sizeof (startdate));
- copy_string_to_attr((CK_BYTE *)&startdate, sizeof (startdate),
- &(dsa_pri_attrs[i++]));
+ if (keys) {
+ for (i = 0; i < nkeys; i++)
+ KMF_FreeRawKey(&keys[i]);
+ free(keys);
}
- cryptodebug("calling X509_get_notAfter");
- if (PKTOOL_cvt_ossltime(X509_get_notAfter(cert), tmpdate)) {
- (void) memcpy(&enddate, tmpdate, sizeof (enddate));
- copy_string_to_attr((CK_BYTE *)&enddate, sizeof (enddate),
- &(dsa_pri_attrs[i++]));
- }
+ return (rv);
+}
- /* Prime p */
- cryptodebug("converting DSA private key prime");
- if ((rv = cvt_bn2bigint(dsa->p, &prime)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert DSA private key prime."));
- return (rv);
- }
- copy_bigint_to_attr(prime, &(dsa_pri_attrs[i++]));
+static KMF_RETURN
+pk_import_cert(
+ KMF_HANDLE_T kmfhandle,
+ KMF_KEYSTORE_TYPE kstype,
+ char *label, char *token_spec, char *filename,
+ char *dir, char *prefix, char *trustflags)
+{
+ KMF_RETURN rv = KMF_OK;
+ KMF_IMPORTCERT_PARAMS params;
- /* Subprime q */
- cryptodebug("converting DSA private key subprime");
- if ((rv = cvt_bn2bigint(dsa->q, &subprime)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert DSA private key subprime."));
- return (rv);
- }
- copy_bigint_to_attr(subprime, &(dsa_pri_attrs[i++]));
+ if (kstype == KMF_KEYSTORE_PK11TOKEN) {
+ rv = select_token(kmfhandle, token_spec, FALSE);
- /* Base g */
- cryptodebug("converting DSA private key base");
- if ((rv = cvt_bn2bigint(dsa->g, &base)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert DSA private key base."));
- return (rv);
+ if (rv != KMF_OK) {
+ return (rv);
+ }
}
- copy_bigint_to_attr(base, &(dsa_pri_attrs[i++]));
- /* Private key x */
- cryptodebug("converting DSA private key value");
- if ((rv = cvt_bn2bigint(dsa->priv_key, &value)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert DSA private key value."));
- return (rv);
- }
- copy_bigint_to_attr(value, &(dsa_pri_attrs[i++]));
+ (void) memset(&params, 0, sizeof (params));
+ params.kstype = kstype;
+ params.certfile = filename;
+ params.certLabel = label;
- /* Indicates programming error: attributes overran the template */
- if (i > count) {
- cryptodebug("error: more attributes found than accounted for");
- i = count;
+ if (kstype == KMF_KEYSTORE_NSS) {
+ rv = configure_nss(kmfhandle, dir, prefix);
+ if (rv != KMF_OK)
+ return (rv);
+ params.nssparms.trustflag = trustflags;
+ params.nssparms.slotlabel = token_spec;
}
- cryptodebug("calling C_CreateObject");
- if ((rv = C_CreateObject(sess, dsa_pri_attrs, i, &obj)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to create DSA private key object."));
- return (rv);
- }
+ rv = KMF_ImportCert(kmfhandle, &params);
- return (CKR_OK);
+ return (rv);
}
-/*
- * Write DH private key to token.
- */
-static CK_RV
-write_dh_private(CK_SESSION_HANDLE sess, DH *dh, X509 *cert)
+static KMF_RETURN
+pk_import_file_crl(void *kmfhandle,
+ char *infile,
+ char *outfile,
+ char *outdir,
+ KMF_ENCODE_FORMAT outfmt)
{
- CK_RV rv = CKR_OK;
- int i = 0;
- static CK_OBJECT_CLASS objclass = CKO_PRIVATE_KEY;
- static CK_KEY_TYPE keytype = CKK_DH;
- CK_BYTE *label = NULL;
- CK_ULONG label_len = 0;
- CK_BYTE *id = NULL;
- CK_ULONG id_len = 0;
- CK_DATE startdate = { "", "", "" };
- CK_DATE enddate = { "", "", "" };
- char tmpdate[8];
- biginteger_t prime = { NULL, 0 }; /* required */
- biginteger_t base = { NULL, 0 }; /* required */
- biginteger_t value = { NULL, 0 }; /* required */
- CK_ATTRIBUTE dh_pri_attrs[11] = {
- { CKA_CLASS, &objclass, sizeof (objclass) },
- { CKA_KEY_TYPE, &keytype, sizeof (keytype) },
- { CKA_PRIVATE, &pk_true, sizeof (pk_true) },
- { CKA_TOKEN, &pk_true, sizeof (pk_true) },
- { CKA_LABEL, NULL, 0 },
- { CKA_ID, NULL, 0 },
- { CKA_START_DATE, NULL, 0 },
- { CKA_END_DATE, NULL, 0 },
- { CKA_PRIME, NULL, 0 },
- { CKA_BASE, NULL, 0 },
- { CKA_VALUE, NULL, 0 }
- };
- CK_ULONG count = sizeof (dh_pri_attrs) / sizeof (CK_ATTRIBUTE);
- CK_OBJECT_HANDLE obj;
-
- cryptodebug("inside write_dh_private");
-
- /* Attributes start at array index 4. */
- i = 4;
-
- /* Recycle the certificate label for the private key label. */
- cryptodebug("calling X509_alias_get0");
- if ((label = X509_alias_get0(cert, (int *)&label_len)) == NULL) {
- label = (CK_BYTE *)gettext("no label");
- label_len = strlen((char *)label);
- }
- copy_string_to_attr(label, label_len, &(dh_pri_attrs[i++]));
+ KMF_IMPORTCRL_PARAMS icrl_params;
+ KMF_OPENSSL_PARAMS sslparams;
- /* Recycle the certificate id for the private key id. */
- cryptodebug("PKTOOL_X509_keyid_get0");
- if ((id = PKTOOL_X509_keyid_get0(cert, (int *)&id_len)) == NULL) {
- id = (CK_BYTE *)gettext("no id");
- id_len = strlen((char *)id);
- }
- copy_string_to_attr(id, id_len, &(dh_pri_attrs[i++]));
-
- /* Recycle the certificate start and end dates for private key. */
- cryptodebug("calling X509_get_notBefore");
- if (PKTOOL_cvt_ossltime(X509_get_notBefore(cert), tmpdate)) {
- (void) memcpy(&startdate, tmpdate, sizeof (startdate));
- copy_string_to_attr((CK_BYTE *)&startdate, sizeof (startdate),
- &(dh_pri_attrs[i++]));
- }
+ sslparams.crlfile = infile;
+ sslparams.dirpath = outdir;
+ sslparams.outcrlfile = outfile;
+ sslparams.format = outfmt;
+ sslparams.crl_check = B_FALSE;
- cryptodebug("calling X509_get_notAfter");
- if (PKTOOL_cvt_ossltime(X509_get_notAfter(cert), tmpdate)) {
- (void) memcpy(&enddate, tmpdate, sizeof (enddate));
- copy_string_to_attr((CK_BYTE *)&enddate, sizeof (enddate),
- &(dh_pri_attrs[i++]));
- }
+ icrl_params.kstype = KMF_KEYSTORE_OPENSSL;
+ icrl_params.sslparms = sslparams;
- /* Prime p */
- cryptodebug("converting DH private key prime");
- if ((rv = cvt_bn2bigint(dh->p, &prime)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert DH private key prime."));
- return (rv);
- }
- copy_bigint_to_attr(prime, &(dh_pri_attrs[i++]));
+ return (KMF_ImportCRL(kmfhandle, &icrl_params));
- /* Base g */
- cryptodebug("converting DH private key base");
- if ((rv = cvt_bn2bigint(dh->g, &base)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert DH private key base."));
- return (rv);
- }
- copy_bigint_to_attr(base, &(dh_pri_attrs[i++]));
+}
- /* Private value x */
- cryptodebug("converting DH private key value");
- if ((rv = cvt_bn2bigint(dh->priv_key, &value)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to convert DH private key value."));
+static KMF_RETURN
+pk_import_nss_crl(void *kmfhandle,
+ boolean_t verify_crl_flag,
+ char *infile,
+ char *outdir,
+ char *prefix)
+{
+ KMF_IMPORTCRL_PARAMS icrl_params;
+ KMF_RETURN rv;
+
+ rv = configure_nss(kmfhandle, outdir, prefix);
+ if (rv != KMF_OK)
return (rv);
- }
- copy_bigint_to_attr(value, &(dh_pri_attrs[i++]));
- /* Indicates programming error: attributes overran the template */
- if (i > count) {
- cryptodebug("error: more attributes found than accounted for");
- i = count;
- }
+ icrl_params.kstype = KMF_KEYSTORE_NSS;
+ icrl_params.nssparms.slotlabel = NULL;
+ icrl_params.nssparms.crlfile = infile;
+ icrl_params.nssparms.crl_check = verify_crl_flag;
- cryptodebug("calling C_CreateObject");
- if ((rv = C_CreateObject(sess, dh_pri_attrs, i, &obj)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to create DH private key object."));
- return (rv);
- }
+ return (KMF_ImportCRL(kmfhandle, &icrl_params));
- return (CKR_OK);
}
-/*
- * Write certificate to token.
- */
-static CK_RV
-write_cert(CK_SESSION_HANDLE sess, X509 *cert)
+static KMF_RETURN
+pk_import_pk12_pk11(
+ KMF_HANDLE_T kmfhandle,
+ KMF_CREDENTIAL *p12cred,
+ KMF_CREDENTIAL *tokencred,
+ char *label, char *token_spec,
+ char *filename)
{
- CK_RV rv = CKR_OK;
- int i = 0;
- static CK_OBJECT_CLASS objclass = CKO_CERTIFICATE;
- static CK_CERTIFICATE_TYPE certtype = CKC_X_509;
- CK_BYTE *subject = NULL;
- CK_ULONG subject_len = 0;
- CK_BYTE *value = NULL;
- CK_ULONG value_len = 0;
- CK_BYTE *label = NULL;
- CK_ULONG label_len = 0;
- CK_BYTE *id = NULL;
- CK_ULONG id_len = 0;
- CK_BYTE *issuer = NULL;
- CK_ULONG issuer_len = 0;
- CK_BYTE *serial = NULL;
- CK_ULONG serial_len = 0;
- CK_ATTRIBUTE cert_attrs[9] = {
- { CKA_CLASS, &objclass, sizeof (objclass) },
- { CKA_CERTIFICATE_TYPE, &certtype, sizeof (certtype) },
- { CKA_TOKEN, &pk_true, sizeof (pk_true) },
- { CKA_SUBJECT, NULL, 0 }, /* required */
- { CKA_VALUE, NULL, 0 }, /* required */
- { 0 /* CKA_LABEL */, NULL, 0 }, /* optional */
- { 0 /* CKA_ID */, NULL, 0 }, /* optional */
- { 0 /* CKA_ISSUER */, NULL, 0 }, /* optional */
- { 0 /* CKA_SERIAL_NUMBER */, NULL, 0 } /* optional */
- };
- CK_ULONG count = sizeof (cert_attrs) / sizeof (CK_ATTRIBUTE);
- CK_OBJECT_HANDLE obj;
-
- cryptodebug("inside write_cert");
-
- /* Attributes start at array index 3. */
- i = 3;
+ KMF_RETURN rv = KMF_OK;
+ KMF_DATA *certs = NULL;
+ KMF_RAW_KEY_DATA *keys = NULL;
+ int ncerts = 0;
+ int nkeys = 0;
+ int i;
- /*
- * OpenSSL subject name and issuer (a little further below) are
- * actually stack structures that contain individual ASN.1
- * components. This stack of entries is packed into one DER string.
- */
- cryptodebug("calling PKTOOL_X509_subject_name");
- if ((subject = PKTOOL_X509_subject_name(cert, (int *)&subject_len)) ==
- NULL) {
- subject = (CK_BYTE *)gettext("no subject name");
- subject_len = strlen((char *)subject);
- }
- copy_string_to_attr(subject, subject_len, &(cert_attrs[i++]));
+ rv = select_token(kmfhandle, token_spec, FALSE);
- /* Get cert value, but it has to be reconstructed from cert. */
- cryptodebug("calling PKTOOL_X509_cert_value");
- if ((value = PKTOOL_X509_cert_value(cert, (int *)&value_len)) == NULL) {
- value = (CK_BYTE *)gettext("no value");
- value_len = strlen((char *)value);
- }
- copy_string_to_attr(value, value_len, &(cert_attrs[i++]));
-
- /*
- * Get certificate label which is "friendlyName" Netscape,
- * "alias" in OpenSSL.
- */
- if ((label = X509_alias_get0(cert, (int *)&label_len)) == NULL) {
- cryptodebug("no certificate label");
- } else {
- cert_attrs[i].type = CKA_LABEL;
- copy_string_to_attr(label, label_len, &(cert_attrs[i++]));
+ if (rv != KMF_OK) {
+ return (rv);
}
- /* Get the keyid for the cert. */
- if ((id = PKTOOL_X509_keyid_get0(cert, (int *)&id_len)) == NULL) {
- cryptodebug("no certificate id");
- } else {
- cert_attrs[i].type = CKA_ID;
- copy_string_to_attr(id, id_len, &(cert_attrs[i++]));
- }
+ rv = KMF_ImportPK12(kmfhandle, filename, p12cred,
+ &certs, &ncerts, &keys, &nkeys);
- /* Get the issuer name for the cert. */
- if ((issuer = PKTOOL_X509_issuer_name(cert, (int *)&issuer_len)) ==
- NULL) {
- cryptodebug("no certificate issuer name");
- } else {
- cert_attrs[i].type = CKA_ISSUER;
- copy_string_to_attr(issuer, issuer_len, &(cert_attrs[i++]));
- }
+ if (rv == KMF_OK) {
+ KMF_STOREKEY_PARAMS skparms;
- /* Get the cert serial number. */
- if ((serial = PKTOOL_X509_serial_number(cert, (int *)&serial_len)) ==
- NULL) {
- cryptodebug("no certificate serial number");
- } else {
- cert_attrs[i].type = CKA_SERIAL_NUMBER;
- copy_string_to_attr(serial, serial_len, &(cert_attrs[i++]));
- }
+ /* The order of certificates and keys should match */
+ for (i = 0; i < nkeys; i++) {
+ (void) memset(&skparms, 0,
+ sizeof (KMF_STOREKEY_PARAMS));
+ skparms.kstype = KMF_KEYSTORE_PK11TOKEN;
+ skparms.certificate = &certs[i];
+ if (tokencred != NULL)
+ skparms.cred = *tokencred;
+ if (i == 0)
+ skparms.label = label;
+ else
+ skparms.label = NULL;
- /* Indicates programming error: attributes overran the template */
- if (i > count) {
- cryptodebug("error: more attributes found than accounted for");
- i = count;
- }
-
- cryptodebug("calling C_CreateObject");
- if ((rv = C_CreateObject(sess, cert_attrs, i, &obj)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to create X.509 certificate object."));
- return (rv);
+ rv = KMF_StorePrivateKey(kmfhandle, &skparms,
+ &keys[i]);
+ }
}
- return (CKR_OK);
-}
+ if (rv == KMF_OK) {
+ KMF_STORECERT_PARAMS params;
-/*
- * Helper function to write PKCS#12 items to token. Returns CKR_OK
- * or CKR_GENERAL_ERROR
- */
-static CK_RV
-write_token_objs(CK_SESSION_HANDLE sess, EVP_PKEY *priv_key, X509 *cert,
- STACK_OF(X509) *ca, int *successes, int *failures)
-{
- int i;
- X509 *c;
- CK_RV rv = CKR_OK;
+ (void) printf(gettext("Found %d certificate(s) and %d "
+ "key(s) in %s\n"), ncerts, nkeys, filename);
+ (void) memset(&params, 0, sizeof (KMF_STORECERT_PARAMS));
- cryptodebug("inside write_token_objs");
+ params.kstype = KMF_KEYSTORE_PK11TOKEN;
- /* Do not reset *successes or *failures -- keep running totals. */
+ for (i = 0; rv == KMF_OK && i < ncerts; i++) {
+ if (i == 0)
+ params.certLabel = label;
+ else
+ params.certLabel = NULL;
- /* Import user key. */
- switch (priv_key->type) {
- case EVP_PKEY_RSA:
- (void) fprintf(stdout, gettext("Writing RSA private key...\n"));
- if ((rv = write_rsa_private(sess,
- EVP_PKEY_get1_RSA(priv_key), cert)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to write RSA private key (%s)."),
- pkcs11_strerror(rv));
- (*failures)++;
- } else
- (*successes)++;
- break;
- case EVP_PKEY_DSA:
- (void) fprintf(stdout, gettext("Writing DSA private key...\n"));
- if ((rv = write_dsa_private(sess,
- EVP_PKEY_get1_DSA(priv_key), cert)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to write DSA private key (%s)."),
- pkcs11_strerror(rv));
- (*failures)++;
- } else
- (*successes)++;
- break;
- case EVP_PKEY_DH:
- (void) fprintf(stdout, gettext("Writing DH private key...\n"));
- if ((rv = write_dh_private(sess,
- EVP_PKEY_get1_DH(priv_key), cert)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to write DH private key (%s)."),
- pkcs11_strerror(rv));
- (*failures)++;
- } else
- (*successes)++;
- break;
-
- default:
- /*
- * Note that EVP_PKEY_DH for X9.42 is not implemented
- * in the OpenSSL library.
- */
- cryptoerror(LOG_STDERR, gettext(
- "Private key type 0x%02x import not supported."),
- priv_key->type);
- (*failures)++;
- break;
+ rv = KMF_StoreCert(kmfhandle, &params, &certs[i]);
+ }
}
- /* Import user certificate. */
- (void) fprintf(stdout, gettext("Writing user certificate...\n"));
- if ((rv = write_cert(sess, cert)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to write user certificate (%s)."),
- pkcs11_strerror(rv));
- (*failures)++;
- } else
- (*successes)++;
-
- /* Import as many stacks of authority certificates as possible. */
- for (i = 0; i != sk_X509_num(ca); i++) {
- /*
- * sk_X509_value() is macro that embeds a cast to (X509 *).
- * Here it translates into ((X509 *)sk_value((ca), (i))).
- * Lint is complaining about the embedded casting, and
- * to fix it, you need to fix openssl header files.
- */
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- c = sk_X509_value(ca, i);
- (void) fprintf(stdout, gettext(
- "Writing authority certificate...\n"));
- if ((rv = write_cert(sess, c)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to write authority certificate (%s)."),
- pkcs11_strerror(rv));
- (*failures)++;
- } else
- (*successes)++;
+ /*
+ * Cleanup memory.
+ */
+ if (certs) {
+ for (i = 0; i < ncerts; i++)
+ KMF_FreeData(&certs[i]);
+ free(certs);
+ }
+ if (keys) {
+ for (i = 0; i < nkeys; i++)
+ KMF_FreeRawKey(&keys[i]);
+ free(keys);
}
- (void) fprintf(stdout, gettext("PKCS#12 element scan completed.\n"));
- return (*failures != 0 ? CKR_GENERAL_ERROR : CKR_OK);
+ return (rv);
}
/*
- * Import objects from PKCS#12 file into token.
+ * Import objects from into KMF repositories.
*/
int
pk_import(int argc, char *argv[])
@@ -793,184 +392,320 @@ pk_import(int argc, char *argv[])
extern int optind_av;
extern char *optarg_av;
char *token_spec = NULL;
- char *token_name = NULL;
- char *manuf_id = NULL;
- char *serial_no = NULL;
- char full_name[FULL_NAME_LEN];
char *filename = NULL;
- struct stat statbuf;
- CK_SLOT_ID slot_id;
- CK_FLAGS pin_state;
- CK_UTF8CHAR_PTR pin = NULL;
- CK_ULONG pinlen = 0;
- CK_UTF8CHAR_PTR pk12pin = NULL;
- CK_ULONG pk12pinlen = 0;
- CK_SESSION_HANDLE sess;
- BIO *fbio = NULL;
- EVP_PKEY *priv_key = NULL;
- X509 *cert = NULL;
- STACK_OF(X509) *ca = NULL;
- CK_RV rv = CKR_OK;
- int i;
- int good_count = 0, bad_count = 0; /* running totals */
-
- cryptodebug("inside pk_import");
+ char *keyfile = NULL;
+ char *certfile = NULL;
+ char *crlfile = NULL;
+ char *certlabel = NULL;
+ char *dir = NULL;
+ char *keydir = NULL;
+ char *prefix = NULL;
+ char *trustflags = NULL;
+ char *verify_crl = NULL;
+ boolean_t verify_crl_flag = B_FALSE;
+ int oclass = 0;
+ KMF_KEYSTORE_TYPE kstype = 0;
+ KMF_ENCODE_FORMAT kfmt = 0;
+ KMF_ENCODE_FORMAT okfmt = KMF_FORMAT_ASN1;
+ KMF_RETURN rv = KMF_OK;
+ KMF_CREDENTIAL pk12cred = { NULL, 0 };
+ KMF_CREDENTIAL tokencred = { NULL, 0 };
+ KMF_HANDLE_T kmfhandle = NULL;
/* Parse command line options. Do NOT i18n/l10n. */
- while ((opt = getopt_av(argc, argv, "T:(token)i:(infile)")) != EOF) {
+ while ((opt = getopt_av(argc, argv,
+ "T:(token)i:(infile)"
+ "k:(keystore)y:(objtype)"
+ "d:(dir)p:(prefix)"
+ "n:(certlabel)N:(label)"
+ "K:(outkey)c:(outcert)"
+ "v:(verifycrl)l:(outcrl)"
+ "t:(trust)D:(keydir)F:(outformat)")) != EOF) {
+ if (EMPTYSTRING(optarg_av))
+ return (PK_ERR_USAGE);
switch (opt) {
case 'T': /* token specifier */
if (token_spec)
return (PK_ERR_USAGE);
token_spec = optarg_av;
break;
+ case 'c': /* output cert file name */
+ if (certfile)
+ return (PK_ERR_USAGE);
+ certfile = optarg_av;
+ break;
+ case 'l': /* output CRL file name */
+ if (crlfile)
+ return (PK_ERR_USAGE);
+ crlfile = optarg_av;
+ break;
+ case 'K': /* output key file name */
+ if (keyfile)
+ return (PK_ERR_USAGE);
+ keyfile = optarg_av;
+ break;
case 'i': /* input file name */
if (filename)
return (PK_ERR_USAGE);
filename = optarg_av;
break;
+ case 'k':
+ kstype = KS2Int(optarg_av);
+ if (kstype == 0)
+ return (PK_ERR_USAGE);
+ break;
+ case 'y':
+ oclass = OT2Int(optarg_av);
+ if (oclass == -1)
+ return (PK_ERR_USAGE);
+ break;
+ case 'd':
+ dir = optarg_av;
+ break;
+ case 'D':
+ keydir = optarg_av;
+ break;
+ case 'p':
+ if (prefix)
+ return (PK_ERR_USAGE);
+ prefix = optarg_av;
+ break;
+ case 'n':
+ case 'N':
+ if (certlabel)
+ return (PK_ERR_USAGE);
+ certlabel = optarg_av;
+ break;
+ case 'F':
+ okfmt = Str2Format(optarg_av);
+ if (okfmt == KMF_FORMAT_UNDEF)
+ return (PK_ERR_USAGE);
+ break;
+ case 't':
+ if (trustflags)
+ return (PK_ERR_USAGE);
+ trustflags = optarg_av;
+ break;
+ case 'v':
+ verify_crl = optarg_av;
+ if (tolower(verify_crl[0]) == 'y')
+ verify_crl_flag = B_TRUE;
+ else if (tolower(verify_crl[0]) == 'n')
+ verify_crl_flag = B_FALSE;
+ else
+ return (PK_ERR_USAGE);
+ break;
default:
return (PK_ERR_USAGE);
break;
}
}
- /* If nothing is specified, default is to use softtoken. */
- if (token_spec == NULL) {
- token_name = SOFT_TOKEN_LABEL;
- manuf_id = SOFT_MANUFACTURER_ID;
- serial_no = SOFT_TOKEN_SERIAL;
- } else {
- /*
- * Parse token specifier into token_name, manuf_id, serial_no.
- * Token_name is required; manuf_id and serial_no are optional.
- */
- if (parse_token_spec(token_spec, &token_name, &manuf_id,
- &serial_no) < 0)
- return (PK_ERR_USAGE);
- }
+ /* Assume keystore = PKCS#11 if not specified */
+ if (kstype == 0)
+ kstype = KMF_KEYSTORE_PK11TOKEN;
/* Filename arg is required. */
- if (filename == NULL)
+ if (EMPTYSTRING(filename)) {
+ cryptoerror(LOG_STDERR, gettext("The 'infile' parameter"
+ "is required for the import operation.\n"));
return (PK_ERR_USAGE);
+ }
/* No additional args allowed. */
argc -= optind_av;
argv += optind_av;
if (argc)
return (PK_ERR_USAGE);
- /* Done parsing command line options. */
- /* Check that the file exists and is non-empty. */
- if (access(filename, R_OK) < 0) {
- cryptoerror(LOG_STDERR, gettext("File \"%s\" is unreadable "
- "(%s)."), filename, strerror(errno));
- return (CKR_OK);
- }
- if (stat(filename, &statbuf) < 0) {
- cryptoerror(LOG_STDERR, gettext("Unable to get size of "
- "file \"%s\" (%s)."), filename, strerror(errno));
- return (CKR_OK);
- }
- if (statbuf.st_size == 0) {
- cryptoerror(LOG_STDERR, gettext("File \"%s\" is empty."),
- filename);
- return (CKR_OK);
- }
+ /* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
+ if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
+ kstype != KMF_KEYSTORE_PK11TOKEN) {
- full_token_name(token_name, manuf_id, serial_no, full_name);
+ (void) fprintf(stderr, gettext("The objtype parameter "
+ "is only relevant if keystore=pkcs11\n"));
+ return (PK_ERR_USAGE);
+ }
- /* Find the slot with token. */
- if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
- &pin_state)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to find token %s (%s)."), full_name,
- pkcs11_strerror(rv));
- return (PK_ERR_PK11);
+ /*
+ * You must specify a certlabel (cert label) when importing
+ * into NSS or PKCS#11.
+ */
+ if (kstype == KMF_KEYSTORE_NSS &&
+ (oclass != PK_CRL_OBJ) && EMPTYSTRING(certlabel)) {
+ cryptoerror(LOG_STDERR, gettext("The 'label' argument "
+ "is required for this operation\n"));
+ return (PK_ERR_USAGE);
}
- /* Get the user's PIN. */
- if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin,
- &pinlen)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get token passphrase (%s)."),
- pkcs11_strerror(rv));
- quick_finish(NULL);
- return (PK_ERR_PK11);
+ /*
+ * PKCS11 only imports PKCS#12 files or PEM/DER Cert files.
+ */
+ if (kstype == KMF_KEYSTORE_PK11TOKEN) {
+ /* we do not import private keys except in PKCS12 bundles */
+ if (oclass & (PK_PRIVATE_OBJ | PK_PRIKEY_OBJ)) {
+ cryptoerror(LOG_STDERR, gettext(
+ "The PKCS11 keystore only imports PKCS12 "
+ "files or raw certificate data files "
+ " or CRL file.\n"));
+ return (PK_ERR_USAGE);
+ }
}
- /* Assume user must be logged in R/W to import objects into token. */
- if ((rv = quick_start(slot_id, CKF_RW_SESSION, pin, pinlen, &sess)) !=
- CKR_OK) {
+ if ((rv = KMF_GetFileFormat(filename, &kfmt)) != KMF_OK) {
cryptoerror(LOG_STDERR,
- gettext("Unable to log into token (%s)."),
- pkcs11_strerror(rv));
- quick_finish(sess);
- return (PK_ERR_PK11);
+ gettext("File format not recognized."));
+ return (rv);
}
+ if (oclass == 0 && (kfmt == KMF_FORMAT_ASN1 ||
+ kfmt == KMF_FORMAT_PEM))
+ oclass = PK_CERT_OBJ;
- /* Setup OpenSSL context. */
- PKTOOL_setup_openssl();
+ if (kstype == KMF_KEYSTORE_NSS) {
+ if (oclass == PK_CRL_OBJ &&
+ (kfmt != KMF_FORMAT_ASN1 && kfmt != KMF_FORMAT_PEM)) {
+ cryptoerror(LOG_STDERR, gettext(
+ "CRL data can only be imported as DER or "
+ "PEM format"));
+ return (PK_ERR_USAGE);
+ }
- /* Open PKCS#12 file. */
- if ((open_pkcs12(filename, &fbio)) < 0) {
- cryptoerror(LOG_STDERR, gettext("Unable to open import file."));
- quick_finish(sess);
- return (PK_ERR_SYSTEM);
- }
+ if (oclass == PK_CERT_OBJ &&
+ (kfmt != KMF_FORMAT_ASN1 && kfmt != KMF_FORMAT_PEM)) {
+ cryptoerror(LOG_STDERR, gettext(
+ "Certificates can only be imported as DER or "
+ "PEM format"));
+ return (PK_ERR_USAGE);
+ }
- /* Get the PIN for the PKCS#12 import file. */
- if ((rv = get_pin(gettext("Enter import file passphrase:"), NULL,
- &pk12pin, &pk12pinlen)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get import file passphrase (%s)."),
- pkcs11_strerror(rv));
- close_pkcs12(fbio);
- quick_finish(sess);
- return (PK_ERR_PK11);
+ /* we do not import private keys except in PKCS12 bundles */
+ if (oclass & (PK_PRIVATE_OBJ | PK_PRIKEY_OBJ)) {
+ cryptoerror(LOG_STDERR, gettext(
+ "Private key data can only be imported as part "
+ "of a PKCS12 file.\n"));
+ return (PK_ERR_USAGE);
+ }
}
- /* PKCS#12 import file may have multiple elements, loop until done. */
- for (i = 0; /* */; i++) {
- /* Extract the contents of the PKCS#12 import file. */
- if ((rv = extract_pkcs12(fbio, pk12pin, pk12pinlen, &priv_key,
- &cert, &ca)) != CKR_OK) {
+ if (kstype == KMF_KEYSTORE_OPENSSL && oclass != PK_CRL_OBJ) {
+ if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) {
cryptoerror(LOG_STDERR, gettext(
- "Unable to parse PKCS#12 element #%d "
- "in import file (%s)."), i+1, pkcs11_strerror(rv));
- close_pkcs12(fbio);
- quick_finish(sess);
- return (PK_ERR_OPENSSL);
+ "The 'outkey' and 'outcert' parameters "
+ "are required for the import operation "
+ "when the 'file' keystore is used.\n"));
+ return (PK_ERR_USAGE);
}
+ }
- /* Reached end of import file? */
- if (rv == CKR_OK && priv_key == NULL && cert == NULL &&
- ca == NULL)
+ if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec))
+ token_spec = PK_DEFAULT_PK11TOKEN;
+ else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec))
+ token_spec = DEFAULT_NSS_TOKEN;
+
+ if (kfmt == KMF_FORMAT_PKCS12) {
+ (void) get_pk12_password(&pk12cred);
+
+ if (kstype == KMF_KEYSTORE_PK11TOKEN ||
+ kstype == KMF_KEYSTORE_NSS)
+ (void) get_token_password(kstype, token_spec,
+ &tokencred);
+ }
+
+ if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
+ cryptoerror(LOG_STDERR, gettext("Error initializing "
+ "KMF: 0x%02x\n"), rv);
+ goto end;
+ }
+
+ switch (kstype) {
+ case KMF_KEYSTORE_PK11TOKEN:
+ if (kfmt == KMF_FORMAT_PKCS12)
+ rv = pk_import_pk12_pk11(
+ kmfhandle,
+ &pk12cred,
+ &tokencred,
+ certlabel,
+ token_spec,
+ filename);
+ else if (oclass == PK_CERT_OBJ)
+ rv = pk_import_cert(
+ kmfhandle,
+ kstype,
+ certlabel,
+ token_spec,
+ filename,
+ NULL, NULL, NULL);
+ else if (oclass == PK_CRL_OBJ)
+ rv = pk_import_file_crl(
+ kmfhandle,
+ filename,
+ crlfile,
+ dir,
+ okfmt);
break;
+ case KMF_KEYSTORE_NSS:
+ if (dir == NULL)
+ dir = PK_DEFAULT_DIRECTORY;
+ if (kfmt == KMF_FORMAT_PKCS12)
+ rv = pk_import_pk12_nss(
+ kmfhandle, &pk12cred,
+ &tokencred,
+ token_spec, dir, prefix,
+ certlabel, trustflags, filename);
+ else if (oclass == PK_CERT_OBJ) {
+ rv = pk_import_cert(
+ kmfhandle, kstype,
+ certlabel, token_spec,
+ filename, dir, prefix, trustflags);
+ } else if (oclass == PK_CRL_OBJ) {
+ rv = pk_import_nss_crl(
+ kmfhandle,
+ verify_crl_flag,
+ filename,
+ dir,
+ prefix);
+ }
+ break;
+ case KMF_KEYSTORE_OPENSSL:
+ if (kfmt == KMF_FORMAT_PKCS12)
+ rv = pk_import_pk12_files(
+ kmfhandle, &pk12cred,
+ filename, certfile, keyfile,
+ dir, keydir, okfmt);
+ else if (oclass == PK_CRL_OBJ) {
+ rv = pk_import_file_crl(
+ kmfhandle,
+ filename,
+ crlfile,
+ dir,
+ okfmt);
+ } else
+ /*
+ * It doesn't make sense to import anything
+ * else for the files plugin.
+ */
+ return (PK_ERR_USAGE);
+ break;
+ default:
+ rv = PK_ERR_USAGE;
+ break;
+ }
- (void) fprintf(stdout, gettext(
- "Scanning PKCS#12 element #%d for objects...\n"), i+1);
+end:
+ if (rv != KMF_OK)
+ display_error(kmfhandle, rv,
+ gettext("Error importing objects"));
- /* Write the objects to the token. */
- if ((rv = write_token_objs(sess, priv_key, cert, ca,
- &good_count, &bad_count)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to write PKCS#12 element #%d to token %s."),
- i+1, full_name);
- close_pkcs12(fbio);
- quick_finish(sess);
- return (PK_ERR_PK11);
- }
- }
+ if (tokencred.cred != NULL)
+ free(tokencred.cred);
- (void) fprintf(stdout, gettext("%d PKCS#12 elements scanned: "
- "%d objects imported, %d errors occurred.\n"), i,
- good_count, bad_count);
+ if (pk12cred.cred != NULL)
+ free(pk12cred.cred);
- /* Close PKCS#12 file. */
- close_pkcs12(fbio);
+ (void) KMF_Finalize(kmfhandle);
+
+ if (rv != KMF_OK)
+ return (PK_ERR_USAGE);
- /* Clean up. */
- quick_finish(sess);
return (0);
}
diff --git a/usr/src/cmd/cmd-crypto/pktool/list.c b/usr/src/cmd/cmd-crypto/pktool/list.c
index 496642c8da..2a427dfc36 100644
--- a/usr/src/cmd/cmd-crypto/pktool/list.c
+++ b/usr/src/cmd/cmd-crypto/pktool/list.c
@@ -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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -39,794 +38,482 @@
#include <cryptoutil.h>
#include <security/cryptoki.h>
#include "common.h"
-#include "derparse.h"
-/*
- * Get key size based on the key type.
- */
-static CK_ULONG
-get_key_size(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, CK_KEY_TYPE key_type)
+#include <kmfapi.h>
+
+static void
+pk_show_certs(KMF_HANDLE_T kmfhandle, KMF_X509_DER_CERT *certs, int num_certs)
{
- CK_RV rv = CKR_OK;
- CK_ULONG key_size;
- CK_ATTRIBUTE modulus_sz =
- { CKA_MODULUS, NULL, 0 }; /* RSA */
- CK_ATTRIBUTE prime_sz =
- { CKA_PRIME, NULL, 0 }; /* DSA, DH X9.42 */
- CK_ATTRIBUTE value_sz =
- { CKA_VALUE, NULL_PTR, 0 }; /* DH, DES/DES3, AES, GENERIC */
-
- cryptodebug("inside get_key_size");
-
- switch (key_type) {
- case CKK_RSA:
- if ((rv = C_GetAttributeValue(sess, obj, &modulus_sz, 1)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get modulus attribute size (%s)."),
- pkcs11_strerror(rv));
- } else
- /* Convert key size to bits. */
- key_size = modulus_sz.ulValueLen * 8;
- break;
- case CKK_DH:
- if ((rv = C_GetAttributeValue(sess, obj, &value_sz, 1)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get value attribute size (%s)."),
- pkcs11_strerror(rv));
- } else
- /* Convert key size to bits. */
- key_size = value_sz.ulValueLen * 8;
- break;
- case CKK_X9_42_DH:
- case CKK_DSA:
- if ((rv = C_GetAttributeValue(sess, obj, &prime_sz, 1)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get prime attribute size (%s)."),
- pkcs11_strerror(rv));
- } else
- /* Convert key size to bits. */
- key_size = prime_sz.ulValueLen * 8;
- break;
- case CKK_DES:
- case CKK_DES3:
- if ((rv = C_GetAttributeValue(sess, obj, &value_sz, 1)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get value attribute size (%s)."),
- pkcs11_strerror(rv));
- } else
- /* Convert key size to bits -- omitting parity bit. */
- key_size = value_sz.ulValueLen * 7;
- break;
- case CKK_AES:
- case CKK_GENERIC_SECRET:
- if ((rv = C_GetAttributeValue(sess, obj, &value_sz, 1)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get value attribute size (%s)."),
- pkcs11_strerror(rv));
- } else
- /* Convert key size to bits. */
- key_size = value_sz.ulValueLen * 8;
- break;
- default:
- cryptoerror(LOG_STDERR, gettext(
- "Unknown object key type (0x%02x)."), key_type);
- break;
- }
+ int i;
+ char *subject, *issuer, *serial, *id, *altname;
+
+ for (i = 0; i < num_certs; i++) {
+ subject = NULL;
+ issuer = NULL;
+ serial = NULL;
+ id = NULL;
+ altname = NULL;
+
+ (void) fprintf(stdout,
+ gettext("%d. (X.509 certificate)\n"), i + 1);
+ if (certs[i].kmf_private.label != NULL)
+ (void) fprintf(stdout, gettext("\t%s: %s\n"),
+ (certs[i].kmf_private.keystore_type ==
+ KMF_KEYSTORE_OPENSSL ? "Filename" : "Label"),
+ certs[i].kmf_private.label);
+ if (KMF_GetCertIDString(&certs[i].certificate,
+ &id) == KMF_OK)
+ (void) fprintf(stdout, gettext("\tID: %s\n"), id);
+ if (KMF_GetCertSubjectNameString(kmfhandle,
+ &certs[i].certificate, &subject) == KMF_OK)
+ (void) fprintf(stdout, gettext("\tSubject: %s\n"),
+ subject);
+ if (KMF_GetCertIssuerNameString(kmfhandle,
+ &certs[i].certificate, &issuer) == KMF_OK)
+ (void) fprintf(stdout, gettext("\tIssuer: %s\n"),
+ issuer);
+ if (KMF_GetCertSerialNumberString(kmfhandle,
+ &certs[i].certificate, &serial) == KMF_OK)
+ (void) fprintf(stdout, gettext("\tSerial: %s\n"),
+ serial);
+
+ if (KMF_GetCertExtensionString(kmfhandle,
+ &certs[i].certificate, KMF_X509_EXT_SUBJ_ALTNAME,
+ &altname) == KMF_OK) {
+ (void) fprintf(stdout, gettext("\t%s\n"),
+ altname);
+ }
- return (key_size);
+ KMF_FreeString(subject);
+ KMF_FreeString(issuer);
+ KMF_FreeString(serial);
+ KMF_FreeString(id);
+ KMF_FreeString(altname);
+ (void) fprintf(stdout, "\n");
+ }
}
-/*
- * Display private key.
- */
-static CK_RV
-display_prikey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, int counter)
+static char *
+describeKey(KMF_KEY_HANDLE *key)
{
- CK_RV rv = CKR_OK;
- static CK_BBOOL private;
- static CK_BBOOL modifiable;
- static CK_KEY_TYPE key_type;
- CK_ULONG key_size;
- CK_BYTE *label = NULL;
- CK_ULONG label_len = 0;
- CK_BYTE *id = NULL;
- CK_ULONG id_len = 0;
- CK_BYTE *subject = NULL;
- CK_ULONG subject_len = 0;
- CK_DATE *start_date = NULL;
- CK_ULONG start_date_len = 0;
- CK_DATE *end_date = NULL;
- CK_ULONG end_date_len = 0;
- CK_ATTRIBUTE attrs[18] = {
- /* 0 to 2 */
- { CKA_PRIVATE, &private, sizeof (private) },
- { CKA_MODIFIABLE, &modifiable, sizeof (modifiable) },
- { CKA_KEY_TYPE, &key_type, sizeof (key_type) },
- /* 3 to 12 */
- { CKA_DERIVE, NULL, 0 },
- { CKA_LOCAL, NULL, 0 },
- { CKA_DECRYPT, NULL, 0 },
- { CKA_SIGN, NULL, 0 },
- { CKA_SIGN_RECOVER, NULL, 0 },
- { CKA_UNWRAP, NULL, 0 },
- { CKA_SENSITIVE, NULL, 0 },
- { CKA_ALWAYS_SENSITIVE, NULL, 0 },
- { CKA_EXTRACTABLE, NULL, 0 },
- { CKA_NEVER_EXTRACTABLE, NULL, 0 },
- /* 13 to 17 */
- { CKA_LABEL, NULL, 0 }, /* optional */
- { CKA_ID, NULL, 0 }, /* optional */
- { CKA_SUBJECT, NULL, 0 }, /* optional */
- { CKA_START_DATE, NULL, 0 }, /* optional */
- { CKA_END_DATE, NULL, 0 } /* optional */
- /* not displaying CKA_KEY_GEN_MECHANISM */
- };
- CK_ULONG n_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE);
- int i;
- char *hex_id = NULL;
- int hex_id_len = 0;
- char *hex_subject = NULL;
- int hex_subject_len = 0;
-
- cryptodebug("inside display_prikey");
-
- /* Get the sizes of the attributes we need. */
- cryptodebug("calling C_GetAttributeValue for size info");
- if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get private key attribute sizes (%s)."),
- pkcs11_strerror(rv));
- return (rv);
- }
-
- /* Allocate memory for each variable-length attribute. */
- for (i = 3; i < n_attrs; i++) {
- if (attrs[i].ulValueLen == (CK_ULONG)-1 ||
- attrs[i].ulValueLen == 0) {
- cryptodebug("display_prikey: *** should not happen");
- attrs[i].ulValueLen = 0;
- continue;
- }
- if ((attrs[i].pValue = malloc(attrs[i].ulValueLen)) == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- rv = CKR_HOST_MEMORY;
- goto free_display_prikey;
+ if (key->keyclass == KMF_ASYM_PUB) {
+ if (key->keyalg == KMF_RSA)
+ return (gettext("RSA public key"));
+ if (key->keyalg == KMF_DSA)
+ return (gettext("DSA public key"));
+ }
+ if (key->keyclass == KMF_ASYM_PRI) {
+ if (key->keyalg == KMF_RSA)
+ return ("RSA private key");
+ if (key->keyalg == KMF_DSA)
+ return ("DSA private key");
+ }
+ if (key->keyclass == KMF_SYMMETRIC) {
+ switch (key->keyalg) {
+ case KMF_AES:
+ return (gettext("AES"));
+ break;
+ case KMF_RC4:
+ return (gettext("ARCFOUR"));
+ break;
+ case KMF_DES:
+ return (gettext("DES"));
+ break;
+ case KMF_DES3:
+ return (gettext("Triple-DES"));
+ break;
+ default:
+ return (gettext("symmetric"));
+ break;
}
}
- /* Now really get the attributes. */
- cryptodebug("calling C_GetAttributeValue for attribute info");
- if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get private key attributes (%s)."),
- pkcs11_strerror(rv));
- goto free_display_prikey;
+ return (gettext("unrecognized key object"));
+
+}
+
+static char *
+keybitstr(KMF_KEY_HANDLE *key)
+{
+ KMF_RAW_SYM_KEY *rkey;
+ char keystr[256];
+ char *p;
+
+ if (key == NULL || (key->keyclass != KMF_SYMMETRIC))
+ return ("");
+
+ rkey = (KMF_RAW_SYM_KEY *)key->keyp;
+ (void) memset(keystr, 0, sizeof (keystr));
+ if (rkey != NULL) {
+ (void) snprintf(keystr, sizeof (keystr),
+ " (%d bits)", rkey->keydata.len * 8);
+ p = keystr;
+ } else {
+ return ("");
}
- /* Fill in all the optional temp variables. */
- i = 13;
- copy_attr_to_string(&(attrs[i++]), &label, &label_len);
- copy_attr_to_string(&(attrs[i++]), &id, &id_len);
- copy_attr_to_string(&(attrs[i++]), &subject, &subject_len);
- copy_attr_to_date(&(attrs[i++]), &start_date, &start_date_len);
- copy_attr_to_date(&(attrs[i++]), &end_date, &end_date_len);
-
- /* Get the key size for the object. */
- key_size = get_key_size(sess, obj, key_type);
-
- /* Display the object ... */
- /* ... the label and what it is (and key size in bits) ... */
- (void) fprintf(stdout, gettext("%d. \"%.*s\" (%d-bit %s %s)\n"),
- counter, label_len, label_len > 0 ? (char *)label :
- gettext("<no label>"), key_size, keytype_str(key_type),
- class_str(CKO_PRIVATE_KEY));
-
- /* ... the id ... */
- if (id_len == (CK_ULONG)-1 || id_len == 0)
- (void) fprintf(stdout, gettext("\tId: --\n"));
- else {
- hex_id_len = 3 * id_len + 1;
- if ((hex_id = malloc(hex_id_len)) == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- rv = CKR_HOST_MEMORY;
- goto free_display_prikey;
+ return (p);
+}
+
+static void
+pk_show_keys(void *handle, KMF_KEY_HANDLE *keys, int numkeys)
+{
+ int i;
+
+ for (i = 0; i < numkeys; i++) {
+ (void) fprintf(stdout, gettext("Key #%d - %s: %s%s"),
+ i+1, describeKey(&keys[i]),
+ keys[i].keylabel ? keys[i].keylabel :
+ gettext("No label"),
+ (keys[i].keyclass == KMF_SYMMETRIC ?
+ keybitstr(&keys[i]) : ""));
+
+ if (keys[i].keyclass == KMF_SYMMETRIC) {
+ KMF_RETURN rv;
+ KMF_RAW_SYM_KEY rkey;
+ rv = KMF_GetSymKeyValue(handle, &keys[i],
+ &rkey);
+ if (rv == KMF_OK) {
+ (void) fprintf(stdout, "\t %d bits",
+ rkey.keydata.len * 8);
+ KMF_FreeRawSymKey(&rkey);
+ }
}
- octetify(id, id_len, hex_id, hex_id_len, B_FALSE, B_FALSE, 60,
- "\n\t\t", "");
- (void) fprintf(stdout, gettext("\tId: %s\n"), hex_id);
- free(hex_id);
+ (void) fprintf(stdout, "\n");
}
+}
- /* ... the subject name ... */
- if (subject_len == (CK_ULONG)-1 || subject_len == 0)
- (void) fprintf(stdout, gettext("\tSubject: --\n"));
- else {
- hex_subject_len = 2 * subject_len + 1; /* best guesstimate */
- if ((hex_subject = malloc(hex_subject_len)) == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- rv = CKR_HOST_MEMORY;
- goto free_display_prikey;
+/*
+ * Generic routine used by all "list cert" operations to find
+ * all matching certificates.
+ */
+static KMF_RETURN
+pk_find_certs(KMF_HANDLE_T kmfhandle, KMF_FINDCERT_PARAMS *params)
+{
+ KMF_RETURN rv = KMF_OK;
+ KMF_X509_DER_CERT *certlist = NULL;
+ uint32_t numcerts = 0;
+
+ numcerts = 0;
+ rv = KMF_FindCert(kmfhandle, params, NULL, &numcerts);
+ if (rv == KMF_OK && numcerts > 0) {
+ (void) printf(gettext("Found %d certificates.\n"),
+ numcerts);
+ certlist = (KMF_X509_DER_CERT *)malloc(numcerts *
+ sizeof (KMF_X509_DER_CERT));
+ if (certlist == NULL)
+ return (KMF_ERR_MEMORY);
+ (void) memset(certlist, 0, numcerts *
+ sizeof (KMF_X509_DER_CERT));
+
+ rv = KMF_FindCert(kmfhandle, params, certlist, &numcerts);
+ if (rv == KMF_OK) {
+ int i;
+ (void) pk_show_certs(kmfhandle, certlist,
+ numcerts);
+ for (i = 0; i < numcerts; i++)
+ KMF_FreeKMFCert(kmfhandle, &certlist[i]);
}
- rdnseq_to_str(subject, subject_len, hex_subject,
- hex_subject_len);
- (void) fprintf(stdout, gettext("\tSubject: %.*s\n"),
- hex_subject_len, hex_subject);
- free(hex_subject);
+ free(certlist);
}
+ if (rv == KMF_ERR_CERT_NOT_FOUND &&
+ params->kstype != KMF_KEYSTORE_OPENSSL)
+ rv = KMF_OK;
- /* ... the start date ... */
- if (start_date_len == (CK_ULONG)-1 || start_date_len == 0)
- (void) fprintf(stdout, gettext("\tStart Date: --\n"));
- else
- (void) fprintf(stdout, gettext(
- "\tStart Date: %02.2s/%02.2s/%04.4s\n"),
- start_date->month, start_date->day, start_date->year);
-
- /* ... the end date ... */
- if (end_date_len == (CK_ULONG)-1 || end_date_len == 0)
- (void) fprintf(stdout, gettext("\tEnd Date: --\n"));
- else
- (void) fprintf(stdout, gettext(
- "\tEnd Date: %02.2s/%02.2s/%04.4s\n"),
- end_date->month, end_date->day, end_date->year);
-
- /* ... and its capabilities */
- (void) fprintf(stdout, "\t(%s, %s",
- private != pk_false ? gettext("private") : gettext("public"),
- modifiable == B_TRUE ? gettext("modifiable") :
- gettext("not modifiable"));
- for (i = 3; i <= 12; i++) {
- if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
- attrs[i].ulValueLen != 0 &&
- *((CK_BBOOL *)(attrs[i].pValue)) == B_TRUE)
- (void) fprintf(stdout, ", %s", attr_str(attrs[i].type));
- }
- (void) fprintf(stdout, ")\n");
+ return (rv);
+}
-free_display_prikey:
- for (i = 3; i < n_attrs; i++)
- if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
- attrs[i].ulValueLen != 0)
- free(attrs[i].pValue);
+static KMF_RETURN
+pk_list_keys(void *handle, KMF_FINDKEY_PARAMS *parms)
+{
+ KMF_RETURN rv;
+ KMF_KEY_HANDLE *keys;
+ uint32_t numkeys = 0;
+
+ numkeys = 0;
+ rv = KMF_FindKey(handle, parms, NULL, &numkeys);
+ if (rv == KMF_OK && numkeys > 0) {
+ int i;
+ (void) printf(gettext("Found %d keys.\n"), numkeys);
+ keys = (KMF_KEY_HANDLE *)malloc(numkeys *
+ sizeof (KMF_KEY_HANDLE));
+ if (keys == NULL)
+ return (KMF_ERR_MEMORY);
+ (void) memset(keys, 0, numkeys *
+ sizeof (KMF_KEY_HANDLE));
+
+ rv = KMF_FindKey(handle, parms, keys, &numkeys);
+ if (rv == KMF_OK)
+ pk_show_keys(handle, keys, numkeys);
+ for (i = 0; i < numkeys; i++)
+ KMF_FreeKMFKey(handle, &keys[i]);
+ free(keys);
+ }
+ if (rv == KMF_ERR_KEY_NOT_FOUND &&
+ parms->kstype != KMF_KEYSTORE_OPENSSL)
+ rv = KMF_OK;
return (rv);
}
-/*
- * Display public key.
- */
-static CK_RV
-display_pubkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, int counter)
+static KMF_RETURN
+list_pk11_objects(KMF_HANDLE_T kmfhandle, char *token, int oclass,
+ char *objlabel, KMF_BIGINT *serial, char *issuer, char *subject,
+ char *dir, char *filename, KMF_CREDENTIAL *tokencred,
+ KMF_CERT_VALIDITY find_criteria_flag)
{
- CK_RV rv = CKR_OK;
- static CK_BBOOL private;
- static CK_BBOOL modifiable;
- static CK_BBOOL trusted;
- static CK_KEY_TYPE key_type;
- CK_ULONG key_size;
- CK_BYTE *label = NULL;
- CK_ULONG label_len = 0;
- CK_BYTE *id = NULL;
- CK_ULONG id_len = 0;
- CK_BYTE *subject = NULL;
- CK_ULONG subject_len = 0;
- CK_DATE *start_date = NULL;
- CK_ULONG start_date_len = 0;
- CK_DATE *end_date = NULL;
- CK_ULONG end_date_len = 0;
- CK_ATTRIBUTE attrs[15] = {
- /* 0 to 3 */
- { CKA_PRIVATE, &private, sizeof (private) },
- { CKA_MODIFIABLE, &modifiable, sizeof (modifiable) },
- { CKA_TRUSTED, &trusted, sizeof (trusted) },
- { CKA_KEY_TYPE, &key_type, sizeof (key_type) },
- /* 4 to 9 */
- { CKA_DERIVE, NULL, 0 },
- { CKA_LOCAL, NULL, 0 },
- { CKA_ENCRYPT, NULL, 0 },
- { CKA_VERIFY, NULL, 0 },
- { CKA_VERIFY_RECOVER, NULL, 0 },
- { CKA_WRAP, NULL, 0 },
- /* 10 to 14 */
- { CKA_LABEL, NULL, 0 }, /* optional */
- { CKA_ID, NULL, 0 }, /* optional */
- { CKA_SUBJECT, NULL, 0 }, /* optional */
- { CKA_START_DATE, NULL, 0 }, /* optional */
- { CKA_END_DATE, NULL, 0 } /* optional */
- /* not displaying CKA_KEY_GEN_MECHANISM */
- };
- CK_ULONG n_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE);
- int i;
- char *hex_id = NULL;
- int hex_id_len = 0;
- char *hex_subject = NULL;
- int hex_subject_len = 0;
-
- cryptodebug("inside display_pubkey");
-
- /* Get the sizes of the attributes we need. */
- cryptodebug("calling C_GetAttributeValue for size info");
- if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get public key attribute sizes (%s)."),
- pkcs11_strerror(rv));
+ KMF_RETURN rv;
+ KMF_LISTCRL_PARAMS lcrlargs;
+
+ /*
+ * Symmetric keys and RSA/DSA private keys are always
+ * created with the "CKA_PRIVATE" field == TRUE, so
+ * make sure we search for them with it also set.
+ */
+ if (oclass & (PK_SYMKEY_OBJ | PK_PRIKEY_OBJ))
+ oclass |= PK_PRIVATE_OBJ;
+
+ rv = select_token(kmfhandle, token,
+ !(oclass & (PK_PRIVATE_OBJ | PK_PRIKEY_OBJ)));
+
+ if (rv != KMF_OK) {
return (rv);
}
- /* Allocate memory for each variable-length attribute. */
- for (i = 4; i < n_attrs; i++) {
- if (attrs[i].ulValueLen == (CK_ULONG)-1 ||
- attrs[i].ulValueLen == 0) {
- cryptodebug("display_pubkey: *** should not happen");
- attrs[i].ulValueLen = 0;
- continue;
+ if (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ)) {
+ KMF_FINDKEY_PARAMS parms;
+
+ (void) memset(&parms, 0, sizeof (parms));
+ parms.kstype = KMF_KEYSTORE_PK11TOKEN;
+
+ if (oclass & PK_PRIKEY_OBJ) {
+ parms.keyclass = KMF_ASYM_PRI;
+ parms.findLabel = objlabel;
+ parms.cred = *tokencred;
+ parms.pkcs11parms.private =
+ ((oclass & PK_PRIVATE_OBJ) > 0);
+
+ /* list asymmetric private keys */
+ rv = pk_list_keys(kmfhandle, &parms);
}
- if ((attrs[i].pValue = malloc(attrs[i].ulValueLen)) == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- rv = CKR_HOST_MEMORY;
- goto free_display_pubkey;
+
+ if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
+ parms.keyclass = KMF_SYMMETRIC;
+ parms.findLabel = objlabel;
+ parms.cred = *tokencred;
+ parms.format = KMF_FORMAT_RAWKEY;
+ parms.pkcs11parms.private =
+ ((oclass & PK_PRIVATE_OBJ) > 0);
+
+ /* list symmetric keys */
+ rv = pk_list_keys(kmfhandle, &parms);
}
- }
- /* Now really get the attributes. */
- cryptodebug("calling C_GetAttributeValue for attribute info");
- if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get public key attributes (%s)."),
- pkcs11_strerror(rv));
- goto free_display_pubkey;
- }
+ if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) {
+ parms.keyclass = KMF_ASYM_PUB;
+ parms.findLabel = objlabel;
+ parms.pkcs11parms.private =
+ ((oclass & PK_PRIVATE_OBJ) > 0);
- /* Fill in all the optional temp variables. */
- i = 10;
- copy_attr_to_string(&(attrs[i++]), &label, &label_len);
- copy_attr_to_string(&(attrs[i++]), &id, &id_len);
- copy_attr_to_string(&(attrs[i++]), &subject, &subject_len);
- copy_attr_to_date(&(attrs[i++]), &start_date, &start_date_len);
- copy_attr_to_date(&(attrs[i++]), &end_date, &end_date_len);
-
- /* Get the key size for the object. */
- key_size = get_key_size(sess, obj, key_type);
-
- /* Display the object ... */
- /* ... the label and what it is (and key size in bits) ... */
- (void) fprintf(stdout, gettext("%d. \"%.*s\" (%d-bit %s %s)\n"),
- counter, label_len, label_len > 0 ? (char *)label :
- gettext("<no label>"), key_size, keytype_str(key_type),
- class_str(CKO_PUBLIC_KEY));
-
- /* ... the id ... */
- if (id_len == (CK_ULONG)-1 || id_len == 0)
- (void) fprintf(stdout, gettext("\tId: --\n"));
- else {
- hex_id_len = 3 * id_len + 1;
- if ((hex_id = malloc(hex_id_len)) == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- rv = CKR_HOST_MEMORY;
- goto free_display_pubkey;
+ /* list asymmetric public keys (if any) */
+ rv = pk_list_keys(kmfhandle, &parms);
}
- octetify(id, id_len, hex_id, hex_id_len, B_FALSE, B_FALSE, 60,
- "\n\t\t", "");
- (void) fprintf(stdout, gettext("\tId: %s\n"), hex_id);
- free(hex_id);
+
+ if (rv != KMF_OK)
+ return (rv);
}
- /* ... the subject name ... */
- if (subject_len == (CK_ULONG)-1 || subject_len == 0)
- (void) fprintf(stdout, gettext("\tSubject: --\n"));
- else {
- hex_subject_len = 2 * subject_len + 1; /* best guesstimate */
- if ((hex_subject = malloc(hex_subject_len)) == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- rv = CKR_HOST_MEMORY;
- goto free_display_pubkey;
- }
- rdnseq_to_str(subject, subject_len, hex_subject,
- hex_subject_len);
- (void) fprintf(stdout, gettext("\tSubject: %.*s\n"),
- hex_subject_len, hex_subject);
- free(hex_subject);
+ if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
+ KMF_FINDCERT_PARAMS parms;
+
+ (void) memset(&parms, 0, sizeof (parms));
+ parms.kstype = KMF_KEYSTORE_PK11TOKEN;
+ parms.certLabel = objlabel;
+ parms.issuer = issuer;
+ parms.subject = subject;
+ parms.serial = serial;
+ parms.pkcs11parms.private = FALSE;
+ parms.find_cert_validity = find_criteria_flag;
+
+ rv = pk_find_certs(kmfhandle, &parms);
+ if (rv != KMF_OK)
+ return (rv);
}
- /* ... the start date ... */
- if (start_date_len == (CK_ULONG)-1 || start_date_len == 0)
- (void) fprintf(stdout, gettext("\tStart Date: --\n"));
- else
- (void) fprintf(stdout, gettext(
- "\tStart Date: %02.2s/%02.2s/%04.4s\n"),
- start_date->month, start_date->day, start_date->year);
-
- /* ... the end date ... */
- if (end_date_len == (CK_ULONG)-1 || end_date_len == 0)
- (void) fprintf(stdout, gettext("\tEnd Date: --\n"));
- else
- (void) fprintf(stdout, gettext(
- "\tEnd Date: %02.2s/%02.2s/%04.4s\n"),
- end_date->month, end_date->day, end_date->year);
-
- /* ... and its capabilities */
- (void) fprintf(stdout, "\t(%s, %s, %s",
- private == B_TRUE ? gettext("private") : gettext("public"),
- modifiable == B_TRUE ? gettext("modifiable") :
- gettext("not modifiable"),
- trusted == B_TRUE ? gettext("trusted") : gettext("untrusted"));
- for (i = 4; i <= 9; i++) {
- if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
- attrs[i].ulValueLen != 0 &&
- *((CK_BBOOL *)(attrs[i].pValue)) == B_TRUE)
- (void) fprintf(stdout, ", %s", attr_str(attrs[i].type));
+ if (oclass & PK_CRL_OBJ) {
+ char *crldata;
+
+ (void) memset(&lcrlargs, 0, sizeof (lcrlargs));
+ lcrlargs.kstype = KMF_KEYSTORE_OPENSSL;
+ lcrlargs.sslparms.dirpath = dir;
+ lcrlargs.sslparms.crlfile = filename;
+
+ rv = KMF_ListCRL(kmfhandle, &lcrlargs, &crldata);
+ if (rv == KMF_OK) {
+ (void) printf("%s\n", crldata);
+ free(crldata);
+ }
}
- (void) fprintf(stdout, ")\n");
-free_display_pubkey:
- for (i = 4; i < n_attrs; i++)
- if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
- attrs[i].ulValueLen != 0)
- free(attrs[i].pValue);
return (rv);
}
-/*
- * Display secret key.
- */
-static CK_RV
-display_seckey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, int counter)
+static int
+list_file_objects(KMF_HANDLE_T kmfhandle, int oclass,
+ char *dir, char *filename, KMF_BIGINT *serial,
+ char *issuer, char *subject,
+ KMF_CERT_VALIDITY find_criteria_flag)
{
- CK_RV rv = CKR_OK;
- static CK_BBOOL private;
- static CK_BBOOL modifiable;
- static CK_KEY_TYPE key_type;
- static CK_ULONG key_size;
- CK_BYTE *label = NULL;
- CK_ULONG label_len = 0;
- CK_BYTE *id = NULL;
- CK_ULONG id_len = 0;
- CK_DATE *start_date = NULL;
- CK_ULONG start_date_len = 0;
- CK_DATE *end_date = NULL;
- CK_ULONG end_date_len = 0;
- CK_ATTRIBUTE attrs[19] = {
- /* 0 to 2 */
- { CKA_PRIVATE, &private, sizeof (private) },
- { CKA_MODIFIABLE, &modifiable, sizeof (modifiable) },
- { CKA_KEY_TYPE, &key_type, sizeof (key_type) },
- /* 3 to 14 */
- { CKA_DERIVE, NULL, 0 },
- { CKA_LOCAL, NULL, 0 },
- { CKA_ENCRYPT, NULL, 0 },
- { CKA_DECRYPT, NULL, 0 },
- { CKA_SIGN, NULL, 0 },
- { CKA_VERIFY, NULL, 0 },
- { CKA_WRAP, NULL, 0 },
- { CKA_UNWRAP, NULL, 0 },
- { CKA_SENSITIVE, NULL, 0 },
- { CKA_ALWAYS_SENSITIVE, NULL, 0 },
- { CKA_EXTRACTABLE, NULL, 0 },
- { CKA_NEVER_EXTRACTABLE, 0 },
- /* 15 to 18 */
- { CKA_LABEL, NULL, 0 }, /* optional */
- { CKA_ID, NULL, 0 }, /* optional */
- { CKA_START_DATE, NULL, 0 }, /* optional */
- { CKA_END_DATE, NULL, 0 } /* optional */
- /* not displaying CKA_KEY_GEN_MECHANISM */
- };
- CK_ULONG n_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE);
- int i;
- char *hex_id = NULL;
- int hex_id_len = 0;
-
- cryptodebug("inside display_seckey");
-
- /* Get the sizes of the attributes we need. */
- cryptodebug("calling C_GetAttributeValue for size info");
- if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get secret key attribute sizes (%s)."),
- pkcs11_strerror(rv));
- return (rv);
- }
-
- /* Allocate memory for each variable-length attribute. */
- for (i = 3; i < n_attrs; i++) {
- if (attrs[i].ulValueLen == (CK_ULONG)-1 ||
- attrs[i].ulValueLen == 0) {
- cryptodebug("display_seckey: *** should not happen");
- attrs[i].ulValueLen = 0;
- continue;
+ int rv;
+ KMF_FINDCERT_PARAMS fcargs;
+ KMF_FINDKEY_PARAMS fkargs;
+ KMF_LISTCRL_PARAMS lcrlargs;
+
+ if (oclass & PK_KEY_OBJ) {
+ (void) memset(&fkargs, 0, sizeof (fkargs));
+ fkargs.kstype = KMF_KEYSTORE_OPENSSL;
+ fkargs.sslparms.dirpath = dir;
+ fkargs.sslparms.keyfile = filename;
+ if (oclass & PK_PRIKEY_OBJ) {
+ fkargs.keyclass = KMF_ASYM_PRI;
+
+ rv = pk_list_keys(kmfhandle, &fkargs);
}
- if ((attrs[i].pValue = malloc(attrs[i].ulValueLen)) == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- rv = CKR_HOST_MEMORY;
- goto free_display_seckey;
- }
- }
+ if (rv == KMF_ERR_KEY_NOT_FOUND)
+ rv = KMF_OK;
- /* Now really get the attributes. */
- cryptodebug("calling C_GetAttributeValue for attribute info");
- if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get secret key attributes (%s)."),
- pkcs11_strerror(rv));
- goto free_display_seckey;
- }
+ if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
+ fkargs.keyclass = KMF_SYMMETRIC;
+ fkargs.format = KMF_FORMAT_RAWKEY;
- /* Fill in all the optional temp variables. */
- i = 15;
- copy_attr_to_string(&(attrs[i++]), &label, &label_len);
- copy_attr_to_string(&(attrs[i++]), &id, &id_len);
- copy_attr_to_date(&(attrs[i++]), &start_date, &start_date_len);
- copy_attr_to_date(&(attrs[i++]), &end_date, &end_date_len);
-
- /* Get the key size for the object. */
- key_size = get_key_size(sess, obj, key_type);
-
- /* Display the object ... */
- /* ... the label and what it is (and key size in bytes) ... */
- (void) fprintf(stdout, gettext("%d. \"%.*s\" (%d-bit %s %s)\n"),
- counter, label_len, label_len > 0 ? (char *)label :
- gettext("<no label>"), key_size, keytype_str(key_type),
- class_str(CKO_SECRET_KEY));
-
- /* ... the id ... */
- if (id_len == (CK_ULONG)-1 || id_len == 0)
- (void) fprintf(stdout, gettext("\tId: --\n"));
- else {
- hex_id_len = 3 * id_len + 1;
- if ((hex_id = malloc(hex_id_len)) == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- rv = CKR_HOST_MEMORY;
- goto free_display_seckey;
+ rv = pk_list_keys(kmfhandle, &fkargs);
+ }
+ if (rv == KMF_ERR_KEY_NOT_FOUND)
+ rv = KMF_OK;
+ if (rv != KMF_OK)
+ return (rv);
+ }
+
+ if (oclass & PK_CERT_OBJ) {
+ (void) memset(&fcargs, 0, sizeof (fcargs));
+ fcargs.kstype = KMF_KEYSTORE_OPENSSL;
+ fcargs.certLabel = NULL;
+ fcargs.issuer = issuer;
+ fcargs.subject = subject;
+ fcargs.serial = serial;
+ fcargs.sslparms.dirpath = dir;
+ fcargs.sslparms.certfile = filename;
+ fcargs.find_cert_validity = find_criteria_flag;
+
+ rv = pk_find_certs(kmfhandle, &fcargs);
+ if (rv != KMF_OK)
+ return (rv);
+ }
+
+ if (oclass & PK_CRL_OBJ) {
+ char *crldata;
+
+ (void) memset(&lcrlargs, 0, sizeof (lcrlargs));
+ lcrlargs.kstype = KMF_KEYSTORE_OPENSSL;
+ lcrlargs.sslparms.dirpath = dir;
+ lcrlargs.sslparms.crlfile = filename;
+
+ rv = KMF_ListCRL(kmfhandle, &lcrlargs, &crldata);
+ if (rv == KMF_OK) {
+ (void) printf("%s\n", crldata);
+ free(crldata);
}
- octetify(id, id_len, hex_id, hex_id_len, B_FALSE, B_FALSE, 60,
- "\n\t\t", "");
- (void) fprintf(stdout, gettext("\tId: %s\n"), hex_id);
- free(hex_id);
- }
-
- /* ... the start date ... */
- if (start_date_len == (CK_ULONG)-1 || start_date_len == 0)
- (void) fprintf(stdout, gettext("\tStart Date: --\n"));
- else
- (void) fprintf(stdout, gettext(
- "\tStart Date: %02.2s/%02.2s/%04.4s\n"),
- start_date->month, start_date->day, start_date->year);
-
- /* ... the end date ... */
- if (end_date_len == (CK_ULONG)-1 || end_date_len == 0)
- (void) fprintf(stdout, gettext("\tEnd Date: --\n"));
- else
- (void) fprintf(stdout, gettext(
- "\tEnd Date: %02.2s/%02.2s/%04.4s\n"),
- end_date->month, end_date->day, end_date->year);
-
- /* ... and its capabilities */
- (void) fprintf(stdout, "\t(%s, %s",
- private == B_TRUE ? gettext("private") : gettext("public"),
- modifiable == B_TRUE ? gettext("modifiable") :
- gettext("not modifiable"));
- for (i = 3; i <= 14; i++) {
- if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
- attrs[i].ulValueLen != 0 &&
- *((CK_BBOOL *)(attrs[i].pValue)) == B_TRUE)
- (void) fprintf(stdout, ", %s", attr_str(attrs[i].type));
}
- (void) fprintf(stdout, ")\n");
-free_display_seckey:
- for (i = 3; i < n_attrs; i++)
- if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
- attrs[i].ulValueLen != 0)
- free(attrs[i].pValue);
return (rv);
}
-/*
- * Display certificate.
- */
-static CK_RV
-display_cert(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, int counter)
+static int
+list_nss_objects(KMF_HANDLE_T kmfhandle,
+ int oclass, char *token_spec, char *dir, char *prefix,
+ char *nickname, KMF_BIGINT *serial, char *issuer, char *subject,
+ KMF_CREDENTIAL *tokencred,
+ KMF_CERT_VALIDITY find_criteria_flag)
{
- CK_RV rv = CKR_OK;
- static CK_BBOOL private;
- static CK_BBOOL modifiable;
- static CK_BBOOL trusted;
- CK_BYTE *subject = NULL;
- CK_ULONG subject_len = 0;
- CK_BYTE *value = NULL;
- CK_ULONG value_len = 0;
- CK_BYTE *label = NULL;
- CK_ULONG label_len = 0;
- CK_BYTE *id = NULL;
- CK_ULONG id_len = 0;
- CK_BYTE *issuer = NULL;
- CK_ULONG issuer_len = 0;
- CK_BYTE *serial = NULL;
- CK_ULONG serial_len = 0;
- CK_ATTRIBUTE attrs[9] = {
- { CKA_PRIVATE, &private, sizeof (private) },
- { CKA_MODIFIABLE, &modifiable, sizeof (modifiable) },
- { CKA_TRUSTED, &trusted, sizeof (trusted) },
- { CKA_SUBJECT, NULL, 0 }, /* required */
- { CKA_VALUE, NULL, 0 }, /* required */
- { CKA_LABEL, NULL, 0 }, /* optional */
- { CKA_ID, NULL, 0 }, /* optional */
- { CKA_ISSUER, NULL, 0 }, /* optional */
- { CKA_SERIAL_NUMBER, NULL, 0 } /* optional */
- };
- CK_ULONG n_attrs = sizeof (attrs) / sizeof (CK_ATTRIBUTE);
- int i;
- char *hex_id = NULL;
- int hex_id_len = 0;
- char *hex_subject = NULL;
- int hex_subject_len = 0;
- char *hex_issuer = NULL;
- int hex_issuer_len = 0;
- char *hex_serial = NULL;
- int hex_serial_len = NULL;
- uint32_t serial_value = 0;
- char *hex_value = NULL;
- int hex_value_len = 0;
-
- cryptodebug("inside display_cert");
-
- /* Get the sizes of the attributes we need. */
- cryptodebug("calling C_GetAttributeValue for size info");
- if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get certificate attribute sizes (%s)."),
- pkcs11_strerror(rv));
+ KMF_RETURN rv = KMF_OK;
+ KMF_FINDKEY_PARAMS fkargs;
+
+ rv = configure_nss(kmfhandle, dir, prefix);
+ if (rv != KMF_OK)
return (rv);
- }
- /* Allocate memory for each variable-length attribute. */
- for (i = 3; i < n_attrs; i++) {
- if (attrs[i].ulValueLen == (CK_ULONG)-1 ||
- attrs[i].ulValueLen == 0) {
- cryptodebug("display_cert: *** should not happen");
- attrs[i].ulValueLen = 0;
- continue;
- }
- if ((attrs[i].pValue = malloc(attrs[i].ulValueLen)) == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- rv = CKR_HOST_MEMORY;
- goto free_display_cert;
- }
+ if (oclass & PK_KEY_OBJ) {
+ (void) memset(&fkargs, 0, sizeof (fkargs));
+ fkargs.kstype = KMF_KEYSTORE_NSS;
+ fkargs.findLabel = nickname;
+ fkargs.cred = *tokencred;
+ fkargs.nssparms.slotlabel = token_spec;
}
- /* Now really get the attributes. */
- cryptodebug("calling C_GetAttributeValue for attribute info");
- if ((rv = C_GetAttributeValue(sess, obj, attrs, n_attrs)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get certificate attributes (%s)."),
- pkcs11_strerror(rv));
- goto free_display_cert;
+ if (oclass & PK_PRIKEY_OBJ) {
+ fkargs.keyclass = KMF_ASYM_PRI;
+ rv = pk_list_keys(kmfhandle, &fkargs);
}
-
- /*
- * Fill in all the temp variables. Subject and value are required.
- * The rest are optional.
- */
- i = 3;
- copy_attr_to_string(&(attrs[i++]), &subject, &subject_len);
- copy_attr_to_string(&(attrs[i++]), &value, &value_len);
- copy_attr_to_string(&(attrs[i++]), &label, &label_len);
- copy_attr_to_string(&(attrs[i++]), &id, &id_len);
- copy_attr_to_string(&(attrs[i++]), &issuer, &issuer_len);
- copy_attr_to_string(&(attrs[i++]), &serial, &serial_len);
-
- /* Display the object ... */
- /* ... the label and what it is ... */
- (void) fprintf(stdout, gettext("%d. \"%.*s\" (%s %s)\n"),
- counter, label_len, label_len > 0 ? (char *)label :
- gettext("<no label>"), "X.509", class_str(CKO_CERTIFICATE));
-
- /* ... its capabilities ... */
- (void) fprintf(stdout, gettext("\t(%s, %s, %s)\n"),
- private == B_TRUE ? gettext("private") : gettext("public"),
- modifiable == B_TRUE ? gettext("modifiable") :
- gettext("not modifiable"),
- trusted == B_TRUE ? gettext("trusted") : gettext("untrusted"));
-
- /* ... the id ... */
- if (id_len == (CK_ULONG)-1 || id_len == 0)
- (void) fprintf(stdout, gettext("\tId: --\n"));
- else {
- hex_id_len = 3 * id_len + 1;
- if ((hex_id = malloc(hex_id_len)) == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- rv = CKR_HOST_MEMORY;
- goto free_display_cert;
- }
- octetify(id, id_len, hex_id, hex_id_len, B_FALSE, B_FALSE, 60,
- "\n\t\t", "");
- (void) fprintf(stdout, gettext("\tId: %s\n"), hex_id);
- free(hex_id);
+ if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) {
+ fkargs.keyclass = KMF_SYMMETRIC;
+ fkargs.format = KMF_FORMAT_RAWKEY;
+ rv = pk_list_keys(kmfhandle, &fkargs);
}
-
- /* ... the subject name ... */
- if (subject_len == (CK_ULONG)-1 || subject_len == 0)
- (void) fprintf(stdout, gettext("\tSubject: --\n"));
- else {
- hex_subject_len = 2 * subject_len + 1; /* best guesstimate */
- if ((hex_subject = malloc(hex_subject_len)) == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- rv = CKR_HOST_MEMORY;
- goto free_display_cert;
- }
- rdnseq_to_str(subject, subject_len, hex_subject,
- hex_subject_len);
- (void) fprintf(stdout, gettext("\tSubject: %.*s\n"),
- hex_subject_len, hex_subject);
- free(hex_subject);
+ if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) {
+ fkargs.keyclass = KMF_ASYM_PUB;
+ rv = pk_list_keys(kmfhandle, &fkargs);
}
- /* ... the issuer name ... */
- if (issuer_len == (CK_ULONG)-1 || issuer_len == 0)
- (void) fprintf(stdout, gettext("\tIssuer: --\n"));
- else {
- hex_issuer_len = 2 * issuer_len + 1; /* best guesstimate */
- if ((hex_issuer = malloc(hex_issuer_len)) == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- rv = CKR_HOST_MEMORY;
- goto free_display_cert;
- }
- rdnseq_to_str(issuer, issuer_len, hex_issuer, hex_issuer_len);
- (void) fprintf(stdout, gettext("\tIssuer: %.*s\n"),
- hex_issuer_len, hex_issuer);
- free(hex_issuer);
- }
+ /* If searching for public objects or certificates, find certs now */
+ if (rv == KMF_OK && (oclass & PK_CERT_OBJ)) {
+ KMF_FINDCERT_PARAMS fcargs;
- /* ... the serial number ... */
- if (serial_len == (CK_ULONG)-1 || serial_len == 0)
- (void) fprintf(stdout, gettext("\tSerial: --\n"));
- else {
- hex_serial_len = 3 * serial_len + 1;
- if ((hex_serial = malloc(hex_serial_len)) == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- rv = CKR_HOST_MEMORY;
- goto free_display_cert;
- }
- octetify(serial, serial_len, hex_serial, hex_serial_len,
- B_FALSE, B_FALSE, 60, "\n\t\t", "");
- if (serial_len > 4)
- (void) fprintf(stdout, gettext("\tSerial: %s\n"),
- hex_serial);
- else {
- for (i = 0; i < serial_len; i++) {
- serial_value <<= 8;
- serial_value |= (serial[i] & 0xff);
- }
- (void) fprintf(stdout, gettext("\tSerial: %s (%d)\n"),
- hex_serial, serial_value);
- }
- free(hex_serial);
+ (void) memset(&fcargs, 0, sizeof (fcargs));
+ fcargs.kstype = KMF_KEYSTORE_NSS;
+ fcargs.certLabel = nickname;
+ fcargs.issuer = issuer;
+ fcargs.subject = subject;
+ fcargs.serial = serial;
+ fcargs.nssparms.slotlabel = token_spec;
+ fcargs.find_cert_validity = find_criteria_flag;
+
+ rv = pk_find_certs(kmfhandle, &fcargs);
}
- /* ... and the value */
- if (value_len == (CK_ULONG)-1 || value_len == 0)
- (void) fprintf(stdout, gettext("\tValue: --\n"));
- else {
- hex_value_len = 3 * value_len + 1;
- if ((hex_value = malloc(hex_value_len)) == NULL) {
- cryptoerror(LOG_STDERR, "%s.", strerror(errno));
- rv = CKR_HOST_MEMORY;
- goto free_display_cert;
+ if (rv == KMF_OK && (oclass & PK_CRL_OBJ)) {
+ int numcrls;
+ KMF_FINDCRL_PARAMS fcrlargs;
+
+ (void) memset(&fcrlargs, 0, sizeof (fcrlargs));
+ fcrlargs.kstype = KMF_KEYSTORE_NSS;
+ fcrlargs.nssparms.slotlabel = token_spec;
+
+ rv = KMF_FindCRL(kmfhandle, &fcrlargs, NULL, &numcrls);
+ if (rv == KMF_OK) {
+ char **p;
+ if (numcrls == 0) {
+ (void) printf(gettext("No CRLs found in "
+ "NSS keystore.\n"));
+
+ return (KMF_OK);
+ }
+ p = malloc(numcrls * sizeof (char *));
+ if (p == NULL) {
+ return (KMF_ERR_MEMORY);
+ }
+ (void) memset(p, 0, numcrls * sizeof (char *));
+ rv = KMF_FindCRL(kmfhandle, &fcrlargs,
+ p, &numcrls);
+ if (rv == KMF_OK) {
+ int i;
+ for (i = 0; i < numcrls; i++) {
+ (void) printf("%d. Name = %s\n",
+ i + 1, p[i]);
+ free(p[i]);
+ }
+ }
+ free(p);
}
- octetify(value, value_len, hex_value, hex_value_len,
- B_FALSE, B_FALSE, 60, "\n\t\t", "");
- (void) fprintf(stdout, gettext("\tValue: %s\n"), hex_value);
- free(hex_value);
}
-
-free_display_cert:
- for (i = 3; i < n_attrs; i++)
- if (attrs[i].ulValueLen != (CK_ULONG)-1 &&
- attrs[i].ulValueLen != 0)
- free(attrs[i].pValue);
return (rv);
}
@@ -840,207 +527,189 @@ pk_list(int argc, char *argv[])
extern int optind_av;
extern char *optarg_av;
char *token_spec = NULL;
- char *token_name = NULL;
- char *manuf_id = NULL;
- char *serial_no = NULL;
- char *type_spec = NULL;
- char full_name[FULL_NAME_LEN];
- boolean_t public_objs = B_FALSE;
- boolean_t private_objs = B_FALSE;
- CK_BYTE *list_label = NULL;
- int obj_type = 0x00;
- CK_SLOT_ID slot_id;
- CK_FLAGS pin_state;
- CK_UTF8CHAR_PTR pin = NULL;
- CK_ULONG pinlen = 0;
- CK_SESSION_HANDLE sess;
- CK_OBJECT_HANDLE *objs;
- CK_ULONG num_objs;
- CK_RV rv = CKR_OK;
- int i;
- static CK_OBJECT_CLASS objclass;
- CK_ATTRIBUTE class_attr =
- { CKA_CLASS, &objclass, sizeof (objclass) };
-
- cryptodebug("inside pk_list");
+ char *subject = NULL;
+ char *issuer = NULL;
+ char *dir = NULL;
+ char *prefix = NULL;
+ char *filename = NULL;
+ char *serstr = NULL;
+ KMF_BIGINT serial = { NULL, 0 };
+
+ char *list_label = NULL;
+ int oclass = 0;
+ KMF_KEYSTORE_TYPE kstype = 0;
+ KMF_RETURN rv = KMF_OK;
+ KMF_HANDLE_T kmfhandle = NULL;
+ char *find_criteria = NULL;
+ KMF_CERT_VALIDITY find_criteria_flag = KMF_ALL_CERTS;
+ KMF_CREDENTIAL tokencred = {NULL, 0};
/* Parse command line options. Do NOT i18n/l10n. */
while ((opt = getopt_av(argc, argv,
- "T:(token)y:(objtype)l:(label)")) != EOF) {
+ "k:(keystore)t:(objtype)T:(token)d:(dir)"
+ "p:(prefix)n:(nickname)S:(serial)s:(subject)"
+ "c:(criteria)"
+ "i:(issuer)l:(label)f:(infile)")) != EOF) {
+ if (EMPTYSTRING(optarg_av))
+ return (PK_ERR_USAGE);
switch (opt) {
- case 'T': /* token specifier */
- if (token_spec)
+ case 'k':
+ if (kstype != 0)
+ return (PK_ERR_USAGE);
+ kstype = KS2Int(optarg_av);
+ if (kstype == 0)
+ return (PK_ERR_USAGE);
+ break;
+ case 't':
+ if (oclass != 0)
+ return (PK_ERR_USAGE);
+ oclass = OT2Int(optarg_av);
+ if (oclass == -1)
+ return (PK_ERR_USAGE);
+ break;
+ case 's':
+ if (subject)
+ return (PK_ERR_USAGE);
+ subject = optarg_av;
+ break;
+ case 'i':
+ if (issuer)
+ return (PK_ERR_USAGE);
+ issuer = optarg_av;
+ break;
+ case 'd':
+ if (dir)
+ return (PK_ERR_USAGE);
+ dir = optarg_av;
+ break;
+ case 'p':
+ if (prefix)
+ return (PK_ERR_USAGE);
+ prefix = optarg_av;
+ break;
+ case 'S':
+ serstr = optarg_av;
+ break;
+ case 'f':
+ if (filename)
+ return (PK_ERR_USAGE);
+ filename = optarg_av;
+ break;
+ case 'T': /* token specifier */
+ if (token_spec)
+ return (PK_ERR_USAGE);
+ token_spec = optarg_av;
+ break;
+ case 'n':
+ case 'l': /* object with specific label */
+ if (list_label)
+ return (PK_ERR_USAGE);
+ list_label = optarg_av;
+ break;
+ case 'c':
+ find_criteria = optarg_av;
+ if (!strcasecmp(find_criteria, "valid"))
+ find_criteria_flag =
+ KMF_NONEXPIRED_CERTS;
+ else if (!strcasecmp(find_criteria, "expired"))
+ find_criteria_flag = KMF_EXPIRED_CERTS;
+ else if (!strcasecmp(find_criteria, "both"))
+ find_criteria_flag = KMF_ALL_CERTS;
+ else
+ return (PK_ERR_USAGE);
+ break;
+ default:
return (PK_ERR_USAGE);
- token_spec = optarg_av;
- break;
- case 'y': /* object type: public, private, both */
- if (type_spec)
- return (PK_ERR_USAGE);
- type_spec = optarg_av;
- break;
- case 'l': /* object with specific label */
- if (list_label)
- return (PK_ERR_USAGE);
- list_label = (CK_BYTE *)optarg_av;
- break;
- default:
- return (PK_ERR_USAGE);
- break;
}
}
+ /* No additional args allowed. */
+ argc -= optind_av;
+ argv += optind_av;
+ if (argc)
+ return (PK_ERR_USAGE);
- /* If no token is specified, default is to use softtoken. */
- if (token_spec == NULL) {
- token_name = SOFT_TOKEN_LABEL;
- manuf_id = SOFT_MANUFACTURER_ID;
- serial_no = SOFT_TOKEN_SERIAL;
- } else {
- /*
- * Parse token specifier into token_name, manuf_id, serial_no.
- * Token_name is required; manuf_id and serial_no are optional.
- */
- if (parse_token_spec(token_spec, &token_name, &manuf_id,
- &serial_no) < 0)
- return (PK_ERR_USAGE);
+ if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
+ /* Error message ? */
+ return (rv);
}
- /* If no object type specified, default is public objects. */
- if (!type_spec) {
- public_objs = B_TRUE;
- } else {
- /*
- * Otherwise, the object type must be "public", "private",
- * or "both".
- */
- if (strcmp(type_spec, "private") == 0) {
- private_objs = B_TRUE;
- } else if (strcmp(type_spec, "public") == 0) {
- public_objs = B_TRUE;
- } else if (strcmp(type_spec, "both") == 0) {
- private_objs = B_TRUE;
- public_objs = B_TRUE;
- } else
- return (PK_ERR_USAGE);
- }
+ /* Assume keystore = PKCS#11 if not specified. */
+ if (kstype == 0)
+ kstype = KMF_KEYSTORE_PK11TOKEN;
- if (private_objs)
- obj_type |= PK_PRIVATE_OBJ;
- if (public_objs)
- obj_type |= PK_PUBLIC_OBJ;
+ /* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
+ if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
+ kstype != KMF_KEYSTORE_PK11TOKEN) {
- /* No additional args allowed. */
- argc -= optind_av;
- argv += optind_av;
- if (argc)
+ (void) fprintf(stderr, gettext("The objtype parameter "
+ "is only relevant if keystore=pkcs11\n"));
return (PK_ERR_USAGE);
- /* Done parsing command line options. */
+ }
- full_token_name(token_name, manuf_id, serial_no, full_name);
+ /* If no object class specified, list certificate objects. */
+ if (oclass == 0)
+ oclass = PK_CERT_OBJ;
- /* Find the slot with token. */
- if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
- &pin_state)) != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to find token %s (%s)."), full_name,
- pkcs11_strerror(rv));
- return (PK_ERR_PK11);
+ if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) {
+ token_spec = PK_DEFAULT_PK11TOKEN;
+ } else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) {
+ token_spec = DEFAULT_NSS_TOKEN;
}
- /* If private objects are to be listed, user must be logged in. */
- if (private_objs) {
- /* Get the user's PIN. */
- if ((rv = get_pin(gettext("Enter token passphrase:"), NULL,
- &pin, &pinlen)) != CKR_OK) {
- cryptoerror(LOG_STDERR,
- gettext("Unable to get token passphrase (%s)."),
- pkcs11_strerror(rv));
- quick_finish(NULL);
- return (PK_ERR_PK11);
- }
+ if (serstr != NULL) {
+ uchar_t *bytes = NULL;
+ size_t bytelen;
- /* Logging in user R/O into the token is sufficient. */
- cryptodebug("logging in with readonly session");
- if ((rv = quick_start(slot_id, 0, pin, pinlen, &sess)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR,
- gettext("Unable to log into token (%s)."),
- pkcs11_strerror(rv));
- quick_finish(sess);
- return (PK_ERR_PK11);
- }
- /* Otherwise, just create a session. */
- } else {
- cryptodebug("opening a readonly session");
- if ((rv = open_sess(slot_id, 0, &sess)) != CKR_OK) {
- cryptoerror(LOG_STDERR,
- gettext("Unable to open token session (%s)."),
- pkcs11_strerror(rv));
- quick_finish(sess);
- return (PK_ERR_PK11);
+ rv = KMF_HexString2Bytes((uchar_t *)serstr, &bytes, &bytelen);
+ if (rv != KMF_OK || bytes == NULL) {
+ (void) fprintf(stderr, gettext("serial number "
+ "must be specified as a hex number "
+ "(ex: 0x0102030405ffeeddee)\n"));
+ return (PK_ERR_USAGE);
}
+ serial.val = bytes;
+ serial.len = bytelen;
}
- /* Find the object(s) with the given label and/or type. */
- if ((rv = find_objs(sess, obj_type, list_label, &objs, &num_objs)) !=
- CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to find token objects (%s)."), pkcs11_strerror(rv));
- quick_finish(sess);
- return (PK_ERR_PK11);
- }
+ if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
+ kstype == KMF_KEYSTORE_NSS) &&
+ (oclass & (PK_PRIKEY_OBJ | PK_PRIVATE_OBJ))) {
- if (num_objs == 0) {
- cryptoerror(LOG_STDERR, gettext("No objects found."));
- quick_finish(sess);
- return (0);
+ (void) get_token_password(kstype, token_spec,
+ &tokencred);
}
+ if (kstype == KMF_KEYSTORE_PK11TOKEN) {
+ rv = list_pk11_objects(kmfhandle, token_spec,
+ oclass, list_label, &serial,
+ issuer, subject, dir, filename,
+ &tokencred, find_criteria_flag);
- /* List the objects found. */
- for (i = 0; i < num_objs; i++) {
- /* Get object class first, then decide what is next. */
- cryptodebug("calling C_GetAttributeValue for object class");
- if ((rv = C_GetAttributeValue(sess, objs[i], &class_attr, 1))
- != CKR_OK) {
- cryptoerror(LOG_STDERR, gettext(
- "Unable to get object #%d class attribute (%s)."),
- i+1, pkcs11_strerror(rv));
- continue;
- }
+ } else if (kstype == KMF_KEYSTORE_NSS) {
+ if (dir == NULL)
+ dir = PK_DEFAULT_DIRECTORY;
+ rv = list_nss_objects(kmfhandle,
+ oclass, token_spec, dir, prefix,
+ list_label, &serial, issuer, subject,
+ &tokencred, find_criteria_flag);
- /* Display based on the type of object. */
- switch (objclass) {
- case CKO_CERTIFICATE:
- if ((rv = display_cert(sess, objs[i], i+1)) != CKR_OK)
- cryptoerror(LOG_STDERR,
- gettext("Unable to display certificate."));
- break;
- case CKO_PUBLIC_KEY:
- if ((rv = display_pubkey(sess, objs[i], i+1)) != CKR_OK)
- cryptoerror(LOG_STDERR,
- gettext("Unable to display public key."));
- break;
- case CKO_PRIVATE_KEY:
- if ((rv = display_prikey(sess, objs[i], i+1)) != CKR_OK)
- cryptoerror(LOG_STDERR,
- gettext("Unable to display private key."));
- break;
- case CKO_SECRET_KEY:
- if ((rv = display_seckey(sess, objs[i], i+1)) != CKR_OK)
- cryptoerror(LOG_STDERR,
- gettext("Unable to display secret key."));
- break;
- case CKO_DATA:
- cryptoerror(LOG_STDERR,
- gettext("Data object display not implemented."));
- break;
- default:
- cryptoerror(LOG_STDERR, gettext(
- "Unknown token object class (0x%02x)."), objclass);
- break;
- }
+ } else if (kstype == KMF_KEYSTORE_OPENSSL) {
+
+ rv = list_file_objects(kmfhandle,
+ oclass, dir, filename,
+ &serial, issuer, subject, find_criteria_flag);
+ }
+
+ if (rv != KMF_OK) {
+ display_error(kmfhandle, rv,
+ gettext("Error listing objects"));
}
- /* Clean up. */
- quick_finish(sess);
- return (0);
+ if (serial.val != NULL)
+ free(serial.val);
+
+ if (tokencred.cred != NULL)
+ free(tokencred.cred);
+
+ (void) KMF_Finalize(kmfhandle);
+ return (rv);
}
diff --git a/usr/src/cmd/cmd-crypto/pktool/osslcommon.c b/usr/src/cmd/cmd-crypto/pktool/osslcommon.c
deleted file mode 100644
index 84b4fdbdce..0000000000
--- a/usr/src/cmd/cmd-crypto/pktool/osslcommon.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * 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.
- *
- * 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 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * This file implements some "missing" routines that should
- * be part of the OpenSSL library but are not there yet.
- */
-
-#include <cryptoutil.h>
-#include "osslcommon.h"
-#include <openssl/pkcs12.h>
-#include <openssl/engine.h>
-
-/*
- * OpenSSL usage needs algorithms (ciphers and digests), strings,
- * and engines loaded first to be useful.
- */
-void
-PKTOOL_setup_openssl(void)
-{
- cryptodebug("inside PKTOOL_setup_openssl");
-
- /* Add all ciphers and digests. */
- OpenSSL_add_all_algorithms();
-
- /* Load up error message strings. */
- ERR_load_crypto_strings();
-
- /* Load up PKCS#11 engine. */
- /* ENGINE_load_pk11(); */
-
- /* Load up builtin crypto engines. */
- /*
- * This function is actually defined in OpenSSL libcrypto
- * library. However it doesn't make its lint library correctly
- * which is why this lint error occurs. OpenSSL needs fixing.
- * Do not put a LINTED comment here because lint will complain
- * that the directive is ununsed.
- */
- ENGINE_load_builtin_engines();
-
- /* U/I methods are not necessary here. */
- /* setup_ui_method(); */
-}
-
-/*
- * This should be an OpenSSL function, but they haven't added it yet.
- * See <openssl>/crypto/asn1/x_x509a.c:X509_alias_get0() for the model.
- */
-unsigned char *
-PKTOOL_X509_keyid_get0(X509 *x, int *len)
-{
- cryptodebug("inside PKTOOL_setup_openssl");
-
- if (x->aux == NULL || x->aux->keyid == NULL) {
- cryptodebug("certificate aux or aux->keyid is null");
- return (NULL);
- }
- if (len)
- *len = x->aux->keyid->length;
- return (x->aux->keyid->data);
-}
-
-/*
- * This should be an OpenSSL function, but couldn't find it yet.
- * It gets the subject name safely without dereferencing null pointers.
- * If it is ever found in OpenSSL, this should be removed and all
- * calls to it need to be replaced with right OpenSSL function.
- */
-unsigned char *
-PKTOOL_X509_subject_name(X509 *x, int *len)
-{
- X509_NAME *temp;
-
- cryptodebug("inside PKTOOL_X509_subject_name");
-
- if ((temp = X509_get_subject_name(x)) == NULL) {
- cryptodebug("certificate subject name stack is null");
- return (NULL);
- }
- if (temp->bytes == NULL) {
- cryptodebug("certificate subject name stack bytes is null");
- return (NULL);
- }
- if (len)
- *len = temp->bytes->length;
- return ((unsigned char *)temp->bytes->data);
-}
-
-/*
- * This should be an OpenSSL function, but couldn't find it yet.
- * It gets the issuer name safely without dereferencing null pointers.
- * If it is ever found in OpenSSL, this should be removed and all
- * calls to it need to be replaced with right OpenSSL function.
- */
-unsigned char *
-PKTOOL_X509_issuer_name(X509 *x, int *len)
-{
- X509_NAME *temp;
-
- cryptodebug("inside PKTOOL_X509_issuer_name");
-
- if ((temp = X509_get_issuer_name(x)) == NULL) {
- cryptodebug("certificate issuer name stack is null");
- return (NULL);
- }
- if (temp->bytes == NULL) {
- cryptodebug("certificate issuer name stack bytes is null");
- return (NULL);
- }
- if (len)
- *len = temp->bytes->length;
- return ((unsigned char *)temp->bytes->data);
-}
-
-/*
- * This should be an OpenSSL function, but couldn't find it yet.
- * It gets the serial number safely without dereferencing null pointers.
- * If it is ever found in OpenSSL, this should be removed and all
- * calls to it need to be replaced with right OpenSSL function.
- */
-unsigned char *
-PKTOOL_X509_serial_number(X509 *x, int *len)
-{
- ASN1_INTEGER *temp;
-
- cryptodebug("inside PKTOOL_X509_serial_number");
-
- if ((temp = X509_get_serialNumber(x)) == NULL) {
- cryptodebug("certificate serial number is null");
- return (NULL);
- }
- if (len)
- *len = temp->length;
- return (temp->data);
-}
-
-/*
- * This should be an OpenSSL function, but couldn't find it yet.
- * It gets the cert value safely without dereferencing null pointers.
- * If it is ever found in OpenSSL, this should be removed and all
- * calls to it need to be replaced with right OpenSSL function.
- */
-unsigned char *
-PKTOOL_X509_cert_value(X509 *x, int *len)
-{
- PKCS12_SAFEBAG *bag;
-
- cryptodebug("inside PKTOOL_X509_cert_value");
-
- if ((bag = PKCS12_x5092certbag(x)) == NULL) {
- cryptodebug("unable to convert cert to PKCS#12 bag");
- return (NULL);
- }
- if (bag->value.bag == NULL || bag->value.bag->value.x509cert == NULL) {
- cryptodebug("PKCS#12 bag value or cert inside it is null");
- return (NULL);
- }
- if (len)
- *len = bag->value.bag->value.x509cert->length;
- return (bag->value.bag->value.x509cert->data);
-}
-
-/*
- * Convert OpenSSL's ASN1_TIME format into a character buffer that
- * can then be converted into PKCS#11 format. The buffer must be
- * at least 8 bytes long. The length of the result will be 8 bytes.
- * Return value of 0 indicates failure, 1 indicates success.
- */
-int
-PKTOOL_cvt_ossltime(ASN1_TIME *t, char *buf)
-{
- cryptodebug("inside PKTOOL_cvt_ossltime");
-
- if (t == NULL) {
- cryptodebug("time string is empty");
- buf[0] = '\0';
- return (0);
- }
-
- if (t->length == 15) { /* generalized time: YYYYMMDDmmhhssZ */
- cryptodebug("time string is in generalized format");
- (void) snprintf(buf, 8, "%08.8s", t->data);
- return (1);
- }
-
- if (t->length == 13) { /* UTC time: YYMMDDmmhhssZ */
- cryptodebug("time string is in UTC format");
- /* Guess whether its a 197x to 199x date, or a 20xx date. */
- (void) snprintf(buf, 8, "%s%06.6s",
- ('7' <= t->data[0] && t->data[0] <= '9') ? "19" : "20",
- t->data);
- return (1);
- }
-
- cryptodebug("time string is in unknown format");
- buf[0] = '\0';
- return (0);
-}
diff --git a/usr/src/cmd/cmd-crypto/pktool/osslcommon.h b/usr/src/cmd/cmd-crypto/pktool/osslcommon.h
deleted file mode 100644
index 098d0e1f6a..0000000000
--- a/usr/src/cmd/cmd-crypto/pktool/osslcommon.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.
- *
- * 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 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _PKTOOL_OSSLCOMMON_H
-#define _PKTOOL_OSSLCOMMON_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <openssl/x509.h>
-
-extern void PKTOOL_setup_openssl(void);
-extern unsigned char *PKTOOL_X509_keyid_get0(X509 *x, int *len);
-extern unsigned char *PKTOOL_X509_subject_name(X509 *x, int *len);
-extern unsigned char *PKTOOL_X509_issuer_name(X509 *x, int *len);
-extern unsigned char *PKTOOL_X509_serial_number(X509 *x, int *len);
-extern unsigned char *PKTOOL_X509_cert_value(X509 *x, int *len);
-extern int PKTOOL_cvt_ossltime(ASN1_TIME *t, char *buf);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PKTOOL_OSSLCOMMON_H */
diff --git a/usr/src/cmd/cmd-crypto/pktool/p12common.c b/usr/src/cmd/cmd-crypto/pktool/p12common.c
deleted file mode 100644
index 4e164ea911..0000000000
--- a/usr/src/cmd/cmd-crypto/pktool/p12common.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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.
- *
- * 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 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * This file implements some of the common PKCS#12 routines.
- */
-
-#include <errno.h>
-#include <string.h>
-#include <cryptoutil.h>
-#include "p12common.h"
-#include <openssl/pkcs12.h>
-
-/* I18N helpers. */
-#include <libintl.h>
-#include <locale.h>
-
-/*
- * Common function to create/open PKCS#12 files.
- */
-static int
-pkcs12_file(char *filename, boolean_t create, BIO **fbio)
-{
- cryptodebug("inside pkcs12_file");
-
- if (fbio == NULL) {
- cryptoerror(LOG_STDERR, create ?
- gettext("Error creating file \"%s\", invalid input.") :
- gettext("Error opening file \"%s\", invalid input."),
- filename);
- return (-1);
- }
-
- cryptodebug(create ? "creating %s for binary writes" :
- "opening %s for binary reads", filename);
- if ((*fbio = BIO_new_file(filename, create ? "wb" : "rb")) == NULL) {
- cryptoerror(LOG_STDERR, create ?
- gettext("Error creating file \"%s\" (%s).") :
- gettext("Error opening file \"%s\" (%s)."),
- filename, strerror(errno));
- return (-1);
- }
-
- return (0);
-}
-
-/*
- * Create PKCS#12 export file.
- */
-int
-create_pkcs12(char *filename, BIO **fbio)
-{
- cryptodebug("inside create_pkcs12");
-
- return (pkcs12_file(filename, B_TRUE, fbio));
-}
-
-/*
- * Opens PKCS#12 import file.
- */
-int
-open_pkcs12(char *filename, BIO **fbio)
-{
- cryptodebug("inside open_pkcs12");
-
- return (pkcs12_file(filename, B_FALSE, fbio));
-}
-
-/*
- * Closes PKCS#12 export file.
- */
-void
-close_pkcs12(BIO *fbio)
-{
- cryptodebug("inside close_pkcs12");
-
- BIO_free_all(fbio);
-}
diff --git a/usr/src/cmd/cmd-crypto/pktool/p12common.h b/usr/src/cmd/cmd-crypto/pktool/p12common.h
deleted file mode 100644
index 03a2a6ae5e..0000000000
--- a/usr/src/cmd/cmd-crypto/pktool/p12common.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.
- *
- * 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 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _PKTOOL_P12COMMON_H
-#define _PKTOOL_P12COMMON_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <openssl/bio.h>
-
-extern int create_pkcs12(char *filename, BIO **fbio);
-extern int open_pkcs12(char *filename, BIO **fbio);
-extern void close_pkcs12(BIO *fbio);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PKTOOL_P12COMMON_H */
diff --git a/usr/src/cmd/cmd-crypto/pktool/pktool.c b/usr/src/cmd/cmd-crypto/pktool/pktool.c
index ce7a26235c..c97cf80063 100644
--- a/usr/src/cmd/cmd-crypto/pktool/pktool.c
+++ b/usr/src/cmd/cmd-crypto/pktool/pktool.c
@@ -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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -62,6 +61,10 @@ extern int pk_delete(int argc, char *argv[]);
extern int pk_import(int argc, char *argv[]);
extern int pk_export(int argc, char *argv[]);
extern int pk_tokens(int argc, char *argv[]);
+extern int pk_gencert(int argc, char *argv[]);
+extern int pk_gencsr(int argc, char *argv[]);
+extern int pk_download(int argc, char *argv[]);
+extern int pk_genkey(int argc, char *argv[]);
/* Forward declarations for "built-in" verb actions. */
static int pk_help(int argc, char *argv[]);
@@ -70,45 +73,353 @@ static int pk_help(int argc, char *argv[]);
static verbcmd cmds[] = {
{ "tokens", pk_tokens, 0, "tokens" },
{ "setpin", pk_setpin, 0,
- "setpin [token=<token>[:<manuf>[:<serial>]]]" },
+ "setpin [ keystore=pkcs11 ]\n\t\t"
+ "[ token=token[:manuf[:serial]]]\n\t"
+
+ "setpin keystore=nss\n\t\t"
+ "[ token=token ]\n\t\t"
+ "[ dir=directory-path ]\n\t\t"
+ "[ prefix=DBprefix ]\n\t"
+ },
{ "list", pk_list, 0,
- "list [token=<token>[:<manuf>[:<serial>]]] "
- "[objtype=private|public|both] [label=<label>]" },
+
+ "list [ token=token[:manuf[:serial]]]\n\t\t"
+ "[ objtype=private|public|both ]\n\t\t"
+ "[ label=label ]\n\t"
+
+ "list objtype=cert[:[public | private | both ]]\n\t\t"
+ "[ subject=subject-DN ]\n\t\t"
+ "[ keystore=pkcs11 ]\n\t\t"
+ "[ issuer=issuer-DN ]\n\t\t"
+ "[ serial=serial number]\n\t\t"
+ "[ label=cert-label ]\n\t\t"
+ "[ token=token[:manuf[:serial]]]\n\t\t"
+ "[ criteria=valid|expired|both ]\n\t"
+
+ "list objtype=key[:[public | private | both ]]\n\t\t"
+ "[ keystore=pkcs11 ]\n\t\t"
+ "[ subject=subject-DN ]\n\t\t"
+ "[ label=key-label ]\n\t\t"
+ "[ 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"
+
+ "list keystore=nss objtype=cert\n\t\t"
+ "[ subject=subject-DN ]\n\t\t"
+ "[ issuer=issuer-DN ]\n\t\t"
+ "[ serial=serial number]\n\t\t"
+ "[ nickname=cert-nickname ]\n\t\t"
+ "[ token=token[:manuf[:serial]]]\n\t\t"
+ "[ dir=directory-path ]\n\t\t"
+ "[ prefix=DBprefix ]\n\t\t"
+ "[ criteria=valid|expired|both ]\n\t"
+
+ "list keystore=nss objtype=key\n\t\t"
+ "[ token=token[:manuf[:serial]]]\n\t\t"
+ "[ dir=directory-path ]\n\t\t"
+ "[ prefix=DBprefix ]\n\t\t"
+ "[ nickname=key-nickname ]\n\t"
+
+ "list keystore=file objtype=cert\n\t\t"
+ "[ subject=subject-DN ]\n\t\t"
+ "[ issuer=issuer-DN ]\n\t\t"
+ "[ serial=serial number]\n\t\t"
+ "[ infile=cert-fn ]\n\t\t"
+ "[ dir=directory-path ]\n\t\t"
+ "[ criteria=valid|expired|both ]\n\t"
+
+ "list keystore=file objtype=key\n\t\t"
+ "[ infile=key-fn ]\n\t\t"
+ "[ dir=directory-path ]\n\t"
+
+ "list keystore=file objtype=crl\n\t\t"
+ "infile=crl-fn\n\t\t"
+ "[ dir=directory-path ]\n\t"
+ },
+
{ "delete", pk_delete, 0,
- "delete [token=<token>[:<manuf>[:<serial>]]] "
- "{ [objtype=private|public|both] [label=<label>] }" },
+
+ "delete [ token=token[:manuf[:serial]]]\n\t\t"
+ "[ objtype=private|public|both ]\n\t\t"
+ "[ label=object-label ]\n\t"
+
+ "delete keystore=nss objtype=cert\n\t\t"
+ "[ subject=subject-DN ]\n\t\t"
+ "[ issuer=issuer-DN ]\n\t\t"
+ "[ serial=serial number]\n\t\t"
+ "[ nickname=cert-nickname ]\n\t\t"
+ "[ token=token[:manuf[:serial]]]\n\t\t"
+ "[ dir=directory-path ]\n\t\t"
+ "[ prefix=DBprefix ]\n\t\t"
+ "[ criteria=valid|expired|both ]\n\t"
+
+ "delete keystore=nss objtype=key\n\t\t"
+ "[ token=token[:manuf[:serial]]]\n\t\t"
+ "[ dir=directory-path ]\n\t\t"
+ "[ prefix=DBprefix ]\n\t\t"
+ "[ nickname=key-nickname ]\n\t\t"
+
+ "delete keystore=nss objtype=crl\n\t\t"
+ "[ nickname=issuer-nickname ]\n\t\t"
+ "[ subject=subject-DN ]\n\t\t"
+ "[ token=token[:manuf[:serial]]]\n\t\t"
+ "[ dir=directory-path ]\n\t\t"
+ "[ prefix=DBprefix ]\n\t"
+
+ "delete keystore=pkcs11 objtype=cert[:[public | private | both]]\n\t\t"
+ "[ subject=subject-DN ]\n\t\t"
+ "[ issuer=issuer-DN ]\n\t\t"
+ "[ serial=serial number]\n\t\t"
+ "[ label=cert-label ]\n\t\t"
+ "[ token=token[:manuf[:serial]]]\n\t\t"
+ "[ criteria=valid|expired|both ]\n\t"
+
+ "delete keystore=pkcs11 objtype=key[:[public | private | both]]\n\t\t"
+ "[ subject=subject-DN ]\n\t\t"
+ "[ label=key-label ]\n\t\t"
+ "[ 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"
+
+ "delete keystore=file objtype=cert\n\t\t"
+ "[ subject=subject-DN ]\n\t\t"
+ "[ issuer=issuer-DN ]\n\t\t"
+ "[ serial=serial number]\n\t\t"
+ "[ infile=cert-fn ]\n\t\t"
+ "[ dir=directory-path ]\n\t\t"
+ "[ criteria=valid|expired|both ]\n\t"
+
+ "delete keystore=file objtype=key\n\t\t"
+ "[ infile=key-fn ]\n\t\t"
+ "[ dir=directory-path ]\n\t"
+
+ "delete keystore=file objtype=crl\n\t\t"
+ "infile=crl-fn\n\t\t"
+ "[ dir=directory-path ]\n\t"
+ },
{ "import", pk_import, 0,
- "import [token=<token>[:<manuf>[:<serial>]]] infile=<file>" },
+
+ "import [token=token[:manuf[:serial]]]\n\t\t"
+ "infile=input-fn\n\t"
+
+ "import keystore=nss objtype=cert\n\t\t"
+ "infile=input-fn\n\t\t"
+ "nickname=cert-nickname\n\t\t"
+ "[ trust=trust-value ]\n\t\t"
+ "[ token=token[:manuf[:serial]]]\n\t\t"
+ "[ dir=directory-path ]\n\t\t"
+ "[ prefix=DBprefix ]\n\t"
+
+ "import keystore=nss objtype=crl\n\t\t"
+ "infile=input-fn\n\t\t"
+ "[ verifycrl=y|n ]\n\t\t"
+ "[ token=token[:manuf[:serial]]]\n\t\t"
+ "[ dir=directory-path ]\n\t\t"
+ "[ prefix=DBprefix ]\n\t"
+
+ "import keystore=pkcs11\n\t\t"
+ "infile=input-fn\n\t\t"
+ "label=cert-label\n\t\t"
+ "[ token=token[:manuf[:serial]]]\n\t"
+
+ "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"
+
+ "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"
+ },
+
{ "export", pk_export, 0,
- "export [token=<token>[:<manuf>[:<serial>]]] outfile=<file>" },
- { "-?", pk_help, 0, "help\t(help and usage)" },
+
+ "export [token=token[:manuf[:serial]]]\n\t\t"
+ "outfile=output-fn\n\t"
+
+ "export keystore=nss\n\t\t"
+ "outfile=output-fn\n\t\t"
+ "[ objtype=cert|key ]\n\t\t"
+ "[ subject=subject-DN ]\n\t\t"
+ "[ issuer=issuer-DN ]\n\t\t"
+ "[ serial=serial number]\n\t\t"
+ "[ nickname=cert-nickname]\n\t\t"
+ "[ token=token[:manuf[:serial]]]\n\t\t"
+ "[ dir=directory-path ]\n\t\t"
+ "[ prefix=DBPrefix ]\n\t\t"
+ "[ outformat=pem|der|pkcs12 ]\n\t"
+
+ "export keystore=pkcs11\n\t\t"
+ "outfile=output-fn\n\t\t"
+ "[ label=cert-label]\n\t\t"
+ "[ subject=subject-DN ]\n\t\t"
+ "[ issuer=issuer-DN ]\n\t\t"
+ "[ serial=serial number]\n\t\t"
+ "[ outformat=pem|der|pkcs12]\n\t\t"
+ "[ token=token[:manuf[:serial]]]\n\t"
+
+ "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"
+ },
+
+ { "gencert", pk_gencert, 0,
+ "gencert [-i] keystore=nss\n\t\t"
+ "label=cert-nickname\n\t\t"
+ "serial=serial number hex string]\n\t\t"
+ "subject=subject-DN\n\t\t"
+ "[ altname=[critical:]SubjectAltName ]\n\t\t"
+ "[ keyusage=[critical:]usage,usage,...]\n\t\t"
+ "[ token=token[:manuf[:serial]]]\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"
+ "[ trust=trust-value ]\n\t\t"
+ "[ lifetime=number-hour|number-day|number-year ]\n\t"
+
+ "gencert [-i] [ keystore=pkcs11 ]\n\t\t"
+ "label=key/cert-label\n\t\t"
+ "subject=subject-DN\n\t\t"
+ "serial=serial number hex string\n\t\t"
+ "[ altname=[critical:]SubjectAltName ]\n\t\t"
+ "[ keyusage=[critical:]usage,usage,...]\n\t\t"
+ "[ token=token[:manuf[:serial]]]\n\t\t"
+ "[ keytype=rsa|dsa ]\n\t\t"
+ "[ keylen=key-size ]\n\t\t"
+ "[ lifetime=number-hour|number-day|number-year ]\n\t"
+
+ "gencert [-i] keystore=file\n\t\t"
+ "outcert=cert_filename\n\t\t"
+ "outkey=key_filename\n\t\t"
+ "subject=subject-DN\n\t\t"
+ "serial=serial number hex string\n\t\t"
+ "[ 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"
+ "[ lifetime=number-hour|number-day|number-year ]\n\t"
+ },
+ { "gencsr", pk_gencsr, 0,
+ "gencsr [-i] keystore=nss \n\t\t"
+ "nickname=cert-nickname\n\t\t"
+ "outcsr=csr-fn\n\t\t"
+ "subject=subject-DN\n\t\t"
+ "[ altname=[critical:]SubjectAltName ]\n\t\t"
+ "[ keyusage=[critical:]usage,usage,...]\n\t\t"
+ "[ token=token[:manuf[:serial]]]\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"
+ "[ format=pem|der]\n\t"
+ "gencsr [-i] [ keystore=pkcs11 ]\n\t\t"
+ "label=key-label\n\t\t"
+ "outcsr=csr-fn\n\t\t"
+ "subject=subject-DN\n\t\t"
+ "[ altname=[critical:]SubjectAltName ]\n\t\t"
+ "[ keyusage=[critical:]usage,usage,...]\n\t\t"
+ "[ token=token[:manuf[:serial]]]\n\t\t"
+ "[ keytype=rsa|dsa ]\n\t\t"
+ "[ keylen=key-size ]\n\t\t"
+ "[ format=pem|der]\n\t"
+ "gencsr [-i] keystore=file\n\t\t"
+ "outcsr=csr-fn\n\t\t"
+ "outkey=key-fn\n\t\t"
+ "subject=subject-DN\n\t\t"
+ "[ altname=[critical:]SubjectAltName ]\n\t\t"
+ "[ keyusage=[critical:]usage,usage,...]\n\t\t"
+ "[ keytype=rsa|dsa ]\n\t\t"
+ "[ keylen=key-size ]\n\t\t"
+ "[ dir=directory-path ]\n\t\t"
+ "[ format=pem|der]\n\t"
+ },
+
+ { "download", pk_download, 0,
+ "download url=url_str\n\t\t"
+ "[ objtype=crl|cert ]\n\t\t"
+ "[ http_proxy=proxy_str ]\n\t\t"
+ "[ outfile = outfile ]\n\t\t"
+ },
+
+ { "genkey", pk_genkey, 0,
+ "genkey [ keystore=pkcs11 ]\n\t\t"
+ "label=key-label\n\t\t"
+ "[ keytype=aes|arcfour|des|3des ]\n\t\t"
+ "[ keylen=key-size (AES or ARCFOUR only)]\n\t\t"
+ "[ token=token[:manuf[:serial]]]\n\t\t"
+ "[ sensitive=y|n ]\n\t\t"
+ "[ extractable=y|n ]\n\t\t"
+ "[ print=y|n ]\n\t"
+
+ "genkey keystore=nss\n\t\t"
+ "label=key-label\n\t\t"
+ "[ keytype=aes|arcfour|des|3des ]\n\t\t"
+ "[ keylen=key-size (AES or ARCFOUR only)]\n\t\t"
+ "[ token=token[:manuf[:serial]]]\n\t\t"
+ "[ dir=directory-path ]\n\t\t"
+ "[ prefix=DBprefix ]\n\t"
+
+ "genkey keystore=file\n\t\t"
+ "outkey=key-fn\n\t\t"
+ "[ keytype=aes|arcfour|des|3des ]\n\t\t"
+ "[ keylen=key-size (AES or ARCFOUR only)]\n\t\t"
+ "[ dir=directory-path ]\n\t\t"
+ "[ print=y|n ]\n\t"
+ },
+
+ { "-?", pk_help, 0, "help\t(help and usage)" },
+ { "-f", pk_help, 0, "-f option_file" }
};
static int num_cmds = sizeof (cmds) / sizeof (verbcmd);
static char *prog;
-static void usage(void);
+static void usage(int);
/*
* Usage information. This function must be updated when new verbs or
* options are added.
*/
static void
-usage(void)
+usage(int idx)
{
int i;
- cryptodebug("inside usage");
-
/* Display this block only in command-line mode. */
(void) fprintf(stdout, gettext("Usage:\n"));
(void) fprintf(stdout, gettext("\t%s -?\t(help and usage)\n"), prog);
+ (void) fprintf(stdout, gettext("\t%s -f option_file\n"), prog);
(void) fprintf(stdout, gettext("\t%s subcommand [options...]\n"), prog);
(void) fprintf(stdout, gettext("where subcommands may be:\n"));
/* Display only those verbs that match the current tool mode. */
- for (i = 0; i < num_cmds; i++) {
- /* Do NOT i18n/l10n. */
- (void) fprintf(stdout, "\t%s\n", cmds[i].synopsis);
+ if (idx == -1) {
+ for (i = 0; i < num_cmds; i++) {
+ /* Do NOT i18n/l10n. */
+ (void) fprintf(stdout, "\t%s\n", cmds[i].synopsis);
+ }
+ } else {
+ (void) fprintf(stdout, "\t%s\n", cmds[idx].synopsis);
}
}
@@ -119,9 +430,59 @@ static int
pk_help(int argc, char *argv[])
/* ARGSUSED */
{
- cryptodebug("inside pk_help");
+ usage(-1);
+ return (0);
+}
+
+/*
+ * Process arguments from the argfile and create a new
+ * argv/argc list to be processed later.
+ */
+static int
+process_arg_file(char *argfile, char ***argv, int *argc)
+{
+ FILE *fp;
+ char argline[2 * BUFSIZ]; /* 2048 bytes should be plenty */
+ char *p;
+ int nargs = 0;
+
+ if ((fp = fopen(argfile, "rF")) == NULL) {
+ (void) fprintf(stderr,
+ gettext("Cannot read argfile %s: %s\n"),
+ argfile, strerror(errno));
+ return (errno);
+ }
- usage();
+ while (fgets(argline, sizeof (argline), fp) != NULL) {
+ int j;
+ /* remove trailing whitespace */
+ j = strlen(argline) - 1;
+ while (j >= 0 && isspace(argline[j])) {
+ argline[j] = 0;
+ j--;
+ }
+ /* If it was a blank line, get the next one. */
+ if (!strlen(argline))
+ continue;
+
+ (*argv) = realloc((*argv),
+ (nargs + 1) * sizeof (char *));
+ if ((*argv) == NULL) {
+ perror("memory error");
+ (void) fclose(fp);
+ return (errno);
+ }
+ p = (char *)strdup(argline);
+ if (p == NULL) {
+ perror("memory error");
+ (void) fclose(fp);
+ return (errno);
+ }
+ (*argv)[nargs] = p;
+ nargs++;
+ }
+ *argc = nargs;
+ (void) fclose(fp);
return (0);
}
@@ -150,26 +511,24 @@ main(int argc, char *argv[], char *envp[])
argv++, argc--;
/* Set up for debug and error output. */
- cryptodebug_init(prog);
-
if (argc == 0) {
- usage();
+ usage(-1);
return (1);
}
/* Check for help options. For CLIP-compliance. */
- if (argc == 1 && argv[0][0] == '-') {
- switch (argv[0][1]) {
- case '?':
- return (pk_help(argc, argv));
- default:
- usage();
- return (1);
- }
+ if (strcmp(argv[0], "-?") == 0) {
+ return (pk_help(argc, argv));
+ } else if (strcmp(argv[0], "-f") == 0 && argc == 2) {
+ rv = process_arg_file(argv[1], &pk_argv, &pk_argc);
+ if (rv)
+ return (rv);
+ } else if (argc >= 1 && argv[0][0] == '-') {
+ usage(-1);
+ return (1);
}
/* Always turns off Metaslot so that we can see softtoken. */
- cryptodebug("disabling Metaslot");
if (setenv("METASLOT_ENABLED", "false", 1) < 0) {
save_errno = errno;
cryptoerror(LOG_STDERR,
@@ -179,21 +538,18 @@ main(int argc, char *argv[], char *envp[])
}
/* Begin parsing command line. */
- cryptodebug("begin parsing command line");
- pk_argc = argc;
- pk_argv = argv;
+ if (pk_argc == 0 && pk_argv == NULL) {
+ pk_argc = argc;
+ pk_argv = argv;
+ }
/* Check for valid verb (or an abbreviation of it). */
found = -1;
for (i = 0; i < num_cmds; i++) {
if (strcmp(cmds[i].verb, pk_argv[0]) == 0) {
if (found < 0) {
- cryptodebug("found cmd %s", cmds[i].verb);
found = i;
break;
- } else {
- cryptodebug("also found cmd %s, skipping",
- cmds[i].verb);
}
}
}
@@ -205,36 +561,21 @@ main(int argc, char *argv[], char *envp[])
}
/* Get to work! */
- cryptodebug("begin executing cmd action");
rv = (*cmds[found].action)(pk_argc, pk_argv);
- cryptodebug("end executing cmd action");
switch (rv) {
case PK_ERR_NONE:
- cryptodebug("subcommand succeeded");
break; /* Command succeeded, do nothing. */
case PK_ERR_USAGE:
- cryptodebug("usage error detected");
- usage();
+ usage(found);
break;
case PK_ERR_QUIT:
- cryptodebug("quit command received");
exit(0);
/* NOTREACHED */
case PK_ERR_PK11:
- cryptoerror(LOG_STDERR, "%s",
- gettext("Command failed due to PKCS#11 error."));
- break;
case PK_ERR_SYSTEM:
- cryptoerror(LOG_STDERR, "%s",
- gettext("Command failed due to system error."));
- break;
case PK_ERR_OPENSSL:
- cryptoerror(LOG_STDERR, "%s",
- gettext("Command failed due to OpenSSL error."));
- break;
+ case PK_ERR_NSS:
default:
- cryptoerror(LOG_STDERR, "%s (%d).",
- gettext("Unknown error value"), rv);
break;
}
return (rv);
diff --git a/usr/src/cmd/cmd-crypto/pktool/setpin.c b/usr/src/cmd/cmd-crypto/pktool/setpin.c
index 038f57169e..62416e8c7d 100644
--- a/usr/src/cmd/cmd-crypto/pktool/setpin.c
+++ b/usr/src/cmd/cmd-crypto/pktool/setpin.c
@@ -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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -41,76 +40,90 @@
#include <security/cryptoki.h>
#include "common.h"
-/*
- * Changes the token's PIN.
- */
-int
-pk_setpin(int argc, char *argv[])
-/* ARGSUSED */
+static int
+setpin_nss(KMF_HANDLE_T handle,
+ char *token_spec, char *dir, char *prefix)
{
- int opt;
- extern int optind_av;
- extern char *optarg_av;
- char *token_spec = NULL;
- char *token_name = NULL;
- char *manuf_id = NULL;
- char *serial_no = NULL;
- CK_SLOT_ID slot_id;
- CK_FLAGS pin_state;
- CK_SESSION_HANDLE sess;
+ int rv = 0;
+ KMF_SETPIN_PARAMS params;
+ KMF_CREDENTIAL newpincred = { NULL, 0 };
CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL;
CK_ULONG old_pinlen = 0, new_pinlen = 0;
- CK_RV rv = CKR_OK;
- char full_name[FULL_NAME_LEN];
- cryptodebug("inside pk_setpin");
+ rv = configure_nss(handle, dir, prefix);
+ if (rv != KMF_OK)
+ return (rv);
- /* Parse command line options. Do NOT i18n/l10n. */
- while ((opt = getopt_av(argc, argv, "T:(token)")) != EOF) {
- switch (opt) {
- case 'T': /* token specifier */
- if (token_spec)
- return (PK_ERR_USAGE);
- token_spec = optarg_av;
- break;
- default:
- return (PK_ERR_USAGE);
- break;
- }
+ (void) memset(&params, 0, sizeof (params));
+ params.kstype = KMF_KEYSTORE_NSS;
+ params.tokenname = token_spec;
+ params.nssparms.slotlabel = token_spec;
+
+ if ((rv = get_pin(gettext("Enter current token passphrase "
+ "(<CR> if not set):"), NULL, &old_pin, &old_pinlen)) !=
+ CKR_OK) {
+ cryptoerror(LOG_STDERR,
+ gettext("Unable to get token passphrase."));
+ return (PK_ERR_NSS);
}
+ /* Get the user's new PIN. */
+ if ((rv = get_pin(gettext("Create new passphrase:"), gettext(
+ "Re-enter new passphrase:"), &new_pin, &new_pinlen)) != CKR_OK) {
+ if (rv == CKR_PIN_INCORRECT)
+ cryptoerror(LOG_STDERR, gettext(
+ "Passphrases do not match."));
+ else
+ cryptoerror(LOG_STDERR, gettext(
+ "Unable to get and confirm new passphrase."));
+ if (old_pin != NULL)
+ free(old_pin);
+ return (PK_ERR_NSS);
+ }
+
+ params.cred.cred = (char *)old_pin;
+ params.cred.credlen = old_pinlen;
+
+ newpincred.cred = (char *)new_pin;
+ newpincred.credlen = new_pinlen;
+
+ rv = KMF_SetTokenPin(handle, &params, &newpincred);
+
+ if (new_pin)
+ free(new_pin);
+ if (old_pin)
+ free(old_pin);
+
+ return (rv);
+}
+
+static int
+setpin_pkcs11(KMF_HANDLE_T handle, char *token_spec)
+{
+ CK_SLOT_ID slot_id;
+ CK_FLAGS pin_state;
+ CK_UTF8CHAR_PTR old_pin = NULL, new_pin = NULL;
+ CK_ULONG old_pinlen = 0, new_pinlen = 0;
+ CK_RV rv = CKR_OK;
+ char *token_name = NULL;
+ KMF_SETPIN_PARAMS params;
+ CK_TOKEN_INFO token_info;
+ KMF_CREDENTIAL newpincred = { NULL, 0 };
/* If nothing is specified, default is to use softtoken. */
if (token_spec == NULL) {
+ token_spec = SOFT_TOKEN_LABEL ":" SOFT_MANUFACTURER_ID;
token_name = SOFT_TOKEN_LABEL;
- manuf_id = SOFT_MANUFACTURER_ID;
- serial_no = SOFT_TOKEN_SERIAL;
- } else {
- /*
- * Parse token specifier into token_name, manuf_id, serial_no.
- * Token_name is required; manuf_id and serial_no are optional.
- */
- if (parse_token_spec(token_spec, &token_name, &manuf_id,
- &serial_no) < 0)
- return (PK_ERR_USAGE);
}
- /* No additional args allowed. */
- argc -= optind_av;
- argv += optind_av;
- if (argc != 0)
- return (PK_ERR_USAGE);
- /* Done parsing command line options. */
-
- full_token_name(token_name, manuf_id, serial_no, full_name);
+ rv = KMF_PK11TokenLookup(NULL, token_spec, &slot_id);
+ if (rv == KMF_OK) {
+ /* find the pin state for the selected token */
+ if (C_GetTokenInfo(slot_id, &token_info) != CKR_OK)
+ return (PK_ERR_PK11);
- /* Find the slot with token. */
- if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
- &pin_state)) != CKR_OK) {
- cryptoerror(LOG_STDERR,
- gettext("Unable to find token %s (%s)."), full_name,
- pkcs11_strerror(rv));
- final_pk11(NULL);
- return (PK_ERR_PK11);
+ pin_state = token_info.flags & CKF_USER_PIN_TO_BE_CHANGED;
+ if (token_name == NULL)
+ token_name = (char *)token_info.label;
}
/*
@@ -121,7 +134,6 @@ pk_setpin(int argc, char *argv[])
*/
if (pin_state == CKF_USER_PIN_TO_BE_CHANGED &&
strcmp(token_name, SOFT_TOKEN_LABEL) == 0) {
- cryptodebug("pin_state: first time passphrase is being set");
if ((old_pin = (CK_UTF8CHAR_PTR) strdup(SOFT_DEFAULT_PIN)) ==
NULL) {
cryptoerror(LOG_STDERR, "%s.", strerror(errno));
@@ -130,7 +142,6 @@ pk_setpin(int argc, char *argv[])
}
old_pinlen = strlen(SOFT_DEFAULT_PIN);
} else {
- cryptodebug("pin_state: changing an existing pin ");
if ((rv = get_pin(gettext("Enter token passphrase:"), NULL,
&old_pin, &old_pinlen)) != CKR_OK) {
cryptoerror(LOG_STDERR,
@@ -156,36 +167,117 @@ pk_setpin(int argc, char *argv[])
return (PK_ERR_PK11);
}
- /* Open a R/W session to the token to change the PIN. */
- if ((rv = open_sess(slot_id, CKF_RW_SESSION, &sess)) != CKR_OK) {
- cryptoerror(LOG_STDERR,
- gettext("Unable to open token session (%s)."),
- pkcs11_strerror(rv));
+ (void) memset(&params, 0, sizeof (params));
+ params.kstype = KMF_KEYSTORE_PK11TOKEN;
+ params.tokenname = (char *)token_info.label;
+ params.cred.cred = (char *)old_pin;
+ params.cred.credlen = old_pinlen;
+ params.pkcs11parms.slot = slot_id;
+
+ newpincred.cred = (char *)new_pin;
+ newpincred.credlen = new_pinlen;
+
+ rv = KMF_SetTokenPin(handle, &params, &newpincred);
+
+ /* Clean up. */
+ if (old_pin != NULL)
free(old_pin);
- final_pk11(NULL);
- return (PK_ERR_PK11);
+ if (new_pin != NULL)
+ free(new_pin);
+
+ return (rv);
+}
+
+/*
+ * Changes the token's PIN.
+ */
+int
+pk_setpin(int argc, char *argv[])
+/* ARGSUSED */
+{
+ int opt;
+ int rv;
+ extern int optind_av;
+ extern char *optarg_av;
+ char *token_spec = NULL;
+ char *dir = NULL;
+ char *prefix = NULL;
+ KMF_HANDLE_T handle;
+ KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
+
+ /* Parse command line options. Do NOT i18n/l10n. */
+ while ((opt = getopt_av(argc, argv,
+ "T:(token)k:(keystore)d:(dir)"
+ "p:(prefix)")) != EOF) {
+ switch (opt) {
+ case 'k':
+ kstype = KS2Int(optarg_av);
+ if (kstype == 0)
+ return (PK_ERR_USAGE);
+ break;
+ case 'T': /* token specifier */
+ if (token_spec)
+ return (PK_ERR_USAGE);
+ token_spec = optarg_av;
+ break;
+ case 'd':
+ if (dir)
+ return (PK_ERR_USAGE);
+ dir = optarg_av;
+ break;
+ case 'p':
+ if (prefix)
+ return (PK_ERR_USAGE);
+ prefix = optarg_av;
+ break;
+ default:
+ return (PK_ERR_USAGE);
+ break;
+ }
}
- /* Change the PIN if possible. */
- cryptodebug("calling C_SetPIN");
- rv = C_SetPIN(sess, old_pin, old_pinlen, new_pin, new_pinlen);
- /* Clean up. */
- free(old_pin);
- free(new_pin);
- quick_finish(sess);
+ /* No additional args allowed. */
+ argc -= optind_av;
+ argv += optind_av;
+ if (argc != 0)
+ return (PK_ERR_USAGE);
- if (rv != CKR_OK) {
- if (rv == CKR_PIN_INCORRECT)
- cryptoerror(LOG_STDERR,
- gettext("Incorrect passphrase."));
- else
+ /* Done parsing command line options. */
+ if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) {
+ token_spec = PK_DEFAULT_PK11TOKEN;
+ } else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) {
+ token_spec = DEFAULT_NSS_TOKEN;
+ }
+
+ if ((rv = KMF_Initialize(&handle, NULL, NULL)) != KMF_OK)
+ return (rv);
+
+ switch (kstype) {
+ case KMF_KEYSTORE_PK11TOKEN:
+ rv = setpin_pkcs11(handle, token_spec);
+ break;
+ case KMF_KEYSTORE_NSS:
+ rv = setpin_nss(handle, token_spec, dir, prefix);
+ break;
+ default:
cryptoerror(LOG_STDERR,
- gettext("Unable to change passphrase (%s)."),
- pkcs11_strerror(rv));
- return (PK_ERR_PK11);
+ gettext("incorrect keystore."));
+ return (PK_ERR_USAGE);
}
- (void) fprintf(stdout, gettext("Passphrase changed.\n"));
+ (void) KMF_Finalize(handle);
+
+ if (rv == KMF_ERR_AUTH_FAILED) {
+ cryptoerror(LOG_STDERR,
+ gettext("Incorrect passphrase."));
+ return (PK_ERR_SYSTEM);
+ } else if (rv != CKR_OK) {
+ cryptoerror(LOG_STDERR,
+ gettext("Unable to change passphrase."));
+ return (PK_ERR_SYSTEM);
+ } else {
+ (void) fprintf(stdout, gettext("Passphrase changed.\n"));
+ }
return (0);
}
diff --git a/usr/src/cmd/cmd-crypto/pktool/tokens.c b/usr/src/cmd/cmd-crypto/pktool/tokens.c
index e6345c77b8..ea9d556caa 100644
--- a/usr/src/cmd/cmd-crypto/pktool/tokens.c
+++ b/usr/src/cmd/cmd-crypto/pktool/tokens.c
@@ -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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -51,7 +50,6 @@ pk_tokens(int argc, char *argv[])
CK_RV rv = CKR_OK;
int i;
- cryptodebug("inside pk_tokens");
/* Get rid of subcommand word "tokens". */
argc--;
@@ -81,13 +79,10 @@ pk_tokens(int argc, char *argv[])
(void) fprintf(stdout, fmt, gettext("Token Label"), gettext("Manuf ID"),
gettext("Serial No"), gettext("PIN State"));
for (i = 0; i < slot_count; i++) {
- cryptodebug("calling C_GetTokenInfo");
if ((rv = C_GetTokenInfo(slots[i], &token_info)) != CKR_OK) {
cryptoerror(LOG_STDERR,
gettext("Unable to get slot %d token info (%s)."),
i, pkcs11_strerror(rv));
- cryptodebug("token info error, slot %d (%s)", i,
- pkcs11_strerror(rv));
continue;
}
@@ -99,6 +94,6 @@ pk_tokens(int argc, char *argv[])
/* Clean up. */
free(slots);
- quick_finish(NULL);
+ (void) C_Finalize(NULL);
return (0);
}