diff options
Diffstat (limited to 'usr/src/cmd/cmd-crypto')
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, ¶ms); + + } 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, <ime) != 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, ¶ms, &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(¶ms, 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, ¶ms, &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(¶ms, 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, ¶ms, &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(¶ms, 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, ¶ms); - 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(¶ms, 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, ¶ms, &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(¶ms, 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, ¶ms, &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(¶ms, 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, ¶ms, &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); } |