Home | History | Annotate | Download | only in pktool
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  *
     21  *
     22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*
     27  * This file implements the sign CSR operation for this tool.
     28  */
     29 
     30 #include <stdio.h>
     31 #include <errno.h>
     32 #include <string.h>
     33 #include <cryptoutil.h>
     34 #include <security/cryptoki.h>
     35 #include "common.h"
     36 
     37 #include <kmfapi.h>
     38 #include <kmfapiP.h>
     39 
     40 #define	SET_VALUE(f, s) \
     41 	rv = f; \
     42 	if (rv != KMF_OK) { \
     43 		cryptoerror(LOG_STDERR, \
     44 		    gettext("Failed to set %s: 0x%02x\n"), s, rv); \
     45 		goto cleanup; \
     46 	}
     47 
     48 
     49 static int
     50 read_csrdata(KMF_HANDLE_T handle, char *csrfile, KMF_CSR_DATA *csrdata)
     51 {
     52 	KMF_RETURN rv = KMF_OK;
     53 	KMF_ENCODE_FORMAT csrfmt;
     54 	KMF_DATA csrfiledata = {NULL, 0};
     55 	KMF_DATA rawcsr = {NULL, 0};
     56 
     57 	rv = kmf_get_file_format(csrfile, &csrfmt);
     58 	if (rv != KMF_OK)
     59 		return (rv);
     60 
     61 	rv = kmf_read_input_file(handle, csrfile, &csrfiledata);
     62 	if (rv != KMF_OK)
     63 		return (rv);
     64 
     65 	if (csrfmt == KMF_FORMAT_PEM) {
     66 		rv = kmf_pem_to_der(csrfiledata.Data, csrfiledata.Length,
     67 		    &rawcsr.Data, (int *)&rawcsr.Length);
     68 		if (rv != KMF_OK)
     69 			return (rv);
     70 
     71 		kmf_free_data(&csrfiledata);
     72 	} else {
     73 		rawcsr.Data = csrfiledata.Data;
     74 		rawcsr.Length = csrfiledata.Length;
     75 	}
     76 
     77 	rv = kmf_decode_csr(handle, &rawcsr, csrdata);
     78 	kmf_free_data(&rawcsr);
     79 
     80 	return (rv);
     81 }
     82 
     83 static KMF_RETURN
     84 find_csr_extn(KMF_X509_EXTENSIONS *extnlist, KMF_OID *extoid,
     85 	KMF_X509_EXTENSION *outextn)
     86 {
     87 	int i, found = 0;
     88 	KMF_X509_EXTENSION *eptr;
     89 	KMF_RETURN rv = KMF_OK;
     90 
     91 	(void) memset(outextn, 0, sizeof (KMF_X509_EXTENSION));
     92 	for (i = 0; !found && i < extnlist->numberOfExtensions; i++) {
     93 		eptr = &extnlist->extensions[i];
     94 		if (IsEqualOid(extoid, &eptr->extnId)) {
     95 			rv = copy_extension_data(outextn, eptr);
     96 			found++;
     97 		}
     98 	}
     99 	if (found == 0 || rv != KMF_OK)
    100 		return (1);
    101 	else
    102 		return (rv);
    103 }
    104 
    105 static int
    106 build_cert_from_csr(KMF_CSR_DATA *csrdata,
    107 	KMF_X509_CERTIFICATE *signedCert,
    108 	KMF_BIGINT *serial,
    109 	uint32_t ltime,
    110 	char *issuer, char *subject,
    111 	char *altname,
    112 	KMF_GENERALNAMECHOICES alttype,
    113 	int altcrit,
    114 	uint16_t kubits,
    115 	int kucrit,
    116 	EKU_LIST *ekulist)
    117 {
    118 	KMF_RETURN rv = KMF_OK;
    119 	KMF_X509_NAME issuerDN, subjectDN;
    120 
    121 	/*
    122 	 * If the CSR is ok, now we can generate the final certificate.
    123 	 */
    124 	(void) memset(signedCert, 0, sizeof (KMF_X509_CERTIFICATE));
    125 	(void) memset(&issuerDN, 0, sizeof (issuerDN));
    126 	(void) memset(&subjectDN, 0, sizeof (subjectDN));
    127 
    128 	SET_VALUE(kmf_set_cert_version(signedCert, 2), "version number");
    129 
    130 	SET_VALUE(kmf_set_cert_serial(signedCert, serial), "serial number");
    131 
    132 	SET_VALUE(kmf_set_cert_validity(signedCert, NULL, ltime),
    133 	    "validity time");
    134 
    135 	if (issuer) {
    136 		if (kmf_dn_parser(issuer, &issuerDN) != KMF_OK) {
    137 			cryptoerror(LOG_STDERR,
    138 			    gettext("Issuer name cannot be parsed\n"));
    139 			return (PK_ERR_USAGE);
    140 		}
    141 		SET_VALUE(kmf_set_cert_issuer(signedCert, &issuerDN),
    142 		    "Issuer Name");
    143 	}
    144 	if (subject) {
    145 		if (kmf_dn_parser(subject, &subjectDN) != KMF_OK) {
    146 			cryptoerror(LOG_STDERR,
    147 			    gettext("Subject name cannot be parsed\n"));
    148 			return (PK_ERR_USAGE);
    149 		}
    150 		SET_VALUE(kmf_set_cert_subject(signedCert, &subjectDN),
    151 		    "Subject Name");
    152 	} else {
    153 		signedCert->certificate.subject = csrdata->csr.subject;
    154 	}
    155 
    156 	signedCert->certificate.subjectPublicKeyInfo =
    157 	    csrdata->csr.subjectPublicKeyInfo;
    158 
    159 	signedCert->certificate.extensions = csrdata->csr.extensions;
    160 
    161 	signedCert->certificate.signature =
    162 	    csrdata->signature.algorithmIdentifier;
    163 
    164 	if (kubits != 0) {
    165 		KMF_X509_EXTENSION extn;
    166 		uint16_t oldbits;
    167 		/*
    168 		 * If the CSR already has KU, merge them.
    169 		 */
    170 		rv = find_csr_extn(&csrdata->csr.extensions,
    171 		    (KMF_OID *)&KMFOID_KeyUsage, &extn);
    172 		if (rv == KMF_OK) {
    173 			extn.critical |= kucrit;
    174 			if (extn.value.tagAndValue->value.Length > 1) {
    175 				oldbits =
    176 				    extn.value.tagAndValue->value.Data[1] << 8;
    177 			} else {
    178 				oldbits =
    179 				    extn.value.tagAndValue->value.Data[0];
    180 			}
    181 			oldbits |= kubits;
    182 		} else {
    183 			SET_VALUE(kmf_set_cert_ku(signedCert, kucrit, kubits),
    184 			    "KeyUsage");
    185 		}
    186 	}
    187 	if (altname != NULL) {
    188 		SET_VALUE(kmf_set_cert_subject_altname(signedCert,
    189 		    altcrit, alttype, altname), "subjectAltName");
    190 	}
    191 	if (ekulist != NULL) {
    192 		int i;
    193 		for (i = 0; rv == KMF_OK && i < ekulist->eku_count; i++) {
    194 			SET_VALUE(kmf_add_cert_eku(signedCert,
    195 			    &ekulist->ekulist[i],
    196 			    ekulist->critlist[i]), "Extended Key Usage");
    197 		}
    198 	}
    199 cleanup:
    200 	if (issuer != NULL)
    201 		kmf_free_dn(&issuerDN);
    202 	if (subject != NULL)
    203 		kmf_free_dn(&subjectDN);
    204 
    205 	return (rv);
    206 }
    207 
    208 static int
    209 pk_sign_cert(KMF_HANDLE_T handle, KMF_X509_CERTIFICATE *cert,
    210 	KMF_KEY_HANDLE *key, KMF_DATA *outdata)
    211 {
    212 	KMF_RETURN rv;
    213 	int numattr;
    214 	KMF_ATTRIBUTE attrlist[4];
    215 
    216 	numattr = 0;
    217 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
    218 	    &key->kstype, sizeof (KMF_KEYSTORE_TYPE));
    219 	numattr++;
    220 
    221 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
    222 	    key, sizeof (KMF_KEY_HANDLE_ATTR));
    223 	numattr++;
    224 
    225 	/* cert data that is to be signed */
    226 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
    227 	    cert, sizeof (KMF_X509_CERTIFICATE));
    228 	numattr++;
    229 
    230 	/* output buffer for the signed cert */
    231 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
    232 	    outdata, sizeof (KMF_DATA));
    233 	numattr++;
    234 
    235 	if ((rv = kmf_sign_cert(handle, numattr, attrlist)) != KMF_OK) {
    236 		cryptoerror(LOG_STDERR,
    237 		    gettext("Failed to sign certificate.\n"));
    238 		return (rv);
    239 	}
    240 
    241 	return (rv);
    242 }
    243 
    244 static int
    245 pk_signcsr_files(KMF_HANDLE_T handle,
    246 	char *signkey,
    247 	char *csrfile,
    248 	KMF_BIGINT *serial,
    249 	char *certfile,
    250 	char *issuer,
    251 	char *subject,
    252 	char *altname,
    253 	KMF_GENERALNAMECHOICES alttype,
    254 	int altcrit,
    255 	uint16_t kubits,
    256 	int kucrit,
    257 	EKU_LIST *ekulist,
    258 	uint32_t ltime,
    259 	KMF_ENCODE_FORMAT fmt)
    260 {
    261 	KMF_RETURN rv = KMF_OK;
    262 	KMF_CSR_DATA csrdata;
    263 	KMF_ATTRIBUTE attrlist[16];
    264 	KMF_X509_CERTIFICATE signedCert;
    265 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
    266 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
    267 	KMF_KEY_HANDLE cakey;
    268 	KMF_DATA certdata = {NULL, 0};
    269 	int numattr, count;
    270 
    271 	rv = read_csrdata(handle, csrfile, &csrdata);
    272 	if (rv != KMF_OK) {
    273 		cryptoerror(LOG_STDERR,
    274 		    gettext("Error reading CSR data\n"));
    275 		return (rv);
    276 	}
    277 
    278 	/* verify the signature first */
    279 	numattr = 0;
    280 	kmf_set_attr_at_index(attrlist, numattr, KMF_CSR_DATA_ATTR,
    281 	    &csrdata, sizeof (csrdata));
    282 	numattr++;
    283 
    284 	rv = kmf_verify_csr(handle, numattr, attrlist);
    285 	if (rv != KMF_OK) {
    286 		cryptoerror(LOG_STDERR, gettext("CSR signature "
    287 		    "verification failed.\n"));
    288 		goto cleanup;
    289 	}
    290 
    291 	rv = build_cert_from_csr(&csrdata, &signedCert, serial, ltime,
    292 	    issuer, subject, altname, alttype, altcrit, kubits,
    293 	    kucrit, ekulist);
    294 
    295 	if (rv != KMF_OK)
    296 		goto cleanup;
    297 
    298 	/*
    299 	 * Find the signing key.
    300 	 */
    301 	(void) memset(&cakey, 0, sizeof (cakey));
    302 
    303 	numattr = 0;
    304 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
    305 	    &kstype, sizeof (kstype));
    306 	numattr++;
    307 
    308 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
    309 	    signkey, strlen(signkey));
    310 	numattr++;
    311 
    312 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
    313 	    &keyclass, sizeof (keyclass));
    314 	numattr++;
    315 
    316 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
    317 	    &cakey, sizeof (cakey));
    318 	numattr++;
    319 
    320 	count = 1;
    321 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
    322 	    &count, sizeof (count));
    323 	numattr++;
    324 
    325 	rv = kmf_find_key(handle, numattr, attrlist);
    326 	if (rv != KMF_OK) {
    327 		cryptoerror(LOG_STDERR, gettext(
    328 		    "Error finding CA signing key\n"));
    329 		goto cleanup;
    330 	}
    331 
    332 	rv = pk_sign_cert(handle, &signedCert, &cakey, &certdata);
    333 	if (rv != KMF_OK) {
    334 		cryptoerror(LOG_STDERR, gettext(
    335 		    "Error signing certificate.\n"));
    336 		goto cleanup;
    337 	}
    338 
    339 	rv = kmf_create_cert_file(&certdata, fmt, certfile);
    340 
    341 cleanup:
    342 	kmf_free_signed_csr(&csrdata);
    343 	kmf_free_data(&certdata);
    344 	kmf_free_kmf_key(handle, &cakey);
    345 	return (rv);
    346 }
    347 
    348 static int
    349 pk_signcsr_pk11_nss(KMF_HANDLE_T handle,
    350 	KMF_KEYSTORE_TYPE kstype,
    351 	char *dir, char *prefix,
    352 	char *token, KMF_CREDENTIAL *cred,
    353 	char *signkey, char *csrfile,
    354 	KMF_BIGINT *serial, char *certfile, char *issuer, char *subject,
    355 	char *altname, KMF_GENERALNAMECHOICES alttype, int altcrit,
    356 	uint16_t kubits, int kucrit,
    357 	EKU_LIST *ekulist, uint32_t ltime,
    358 	KMF_ENCODE_FORMAT fmt, int store, char *outlabel)
    359 {
    360 	KMF_RETURN rv = KMF_OK;
    361 	KMF_DATA outcert = {NULL, 0};
    362 	KMF_CSR_DATA csrdata;
    363 	KMF_KEY_HANDLE casignkey;
    364 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
    365 	int numattr = 0;
    366 	int keys = 1;
    367 	KMF_ATTRIBUTE attrlist[16];
    368 	KMF_X509_CERTIFICATE signedCert;
    369 	boolean_t token_bool = B_TRUE;
    370 	boolean_t private_bool = B_TRUE;
    371 
    372 	(void) memset(&casignkey, 0, sizeof (KMF_KEY_HANDLE));
    373 
    374 	rv = read_csrdata(handle, csrfile, &csrdata);
    375 	if (rv != KMF_OK) {
    376 		cryptoerror(LOG_STDERR,
    377 		    gettext("Error reading CSR data\n"));
    378 		return (rv);
    379 	}
    380 
    381 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
    382 		rv = select_token(handle, token, FALSE);
    383 	} else if (kstype == KMF_KEYSTORE_NSS) {
    384 		rv = configure_nss(handle, dir, prefix);
    385 	}
    386 
    387 	/* verify the signature first */
    388 	kmf_set_attr_at_index(attrlist, numattr, KMF_CSR_DATA_ATTR,
    389 	    &csrdata, sizeof (csrdata));
    390 	numattr++;
    391 
    392 	rv = kmf_verify_csr(handle, numattr, attrlist);
    393 	if (rv != KMF_OK) {
    394 		cryptoerror(LOG_STDERR, gettext("CSR signature "
    395 		    "verification failed.\n"));
    396 		goto cleanup;
    397 	}
    398 
    399 	rv = build_cert_from_csr(&csrdata,
    400 	    &signedCert, serial, ltime,
    401 	    issuer, subject, altname,
    402 	    alttype, altcrit, kubits,
    403 	    kucrit, ekulist);
    404 
    405 	if (rv != KMF_OK)
    406 		goto cleanup;
    407 
    408 	/*
    409 	 * Find the signing key.
    410 	 */
    411 	numattr = 0;
    412 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
    413 	    &kstype, sizeof (kstype));
    414 	numattr++;
    415 	if (kstype == KMF_KEYSTORE_NSS) {
    416 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
    417 		    token, strlen(token));
    418 		numattr++;
    419 	}
    420 
    421 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR, signkey,
    422 	    strlen(signkey));
    423 	numattr++;
    424 
    425 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVATE_BOOL_ATTR,
    426 	    &private_bool, sizeof (private_bool));
    427 	numattr++;
    428 
    429 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
    430 	    &token_bool, sizeof (token_bool));
    431 	numattr++;
    432 
    433 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
    434 	    &keyclass, sizeof (keyclass));
    435 	numattr++;
    436 
    437 	kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
    438 	    cred, sizeof (KMF_CREDENTIAL_ATTR));
    439 	numattr++;
    440 
    441 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
    442 	    &keys, sizeof (keys));
    443 	numattr++;
    444 
    445 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
    446 	    &casignkey, sizeof (casignkey));
    447 	numattr++;
    448 
    449 	rv = kmf_find_key(handle, numattr, attrlist);
    450 	if (rv != KMF_OK) {
    451 		cryptoerror(LOG_STDERR,
    452 		    gettext("Failed to find signing key\n"));
    453 		goto cleanup;
    454 	}
    455 
    456 	/*
    457 	 * If we found the key, now we can sign the cert.
    458 	 */
    459 	rv = pk_sign_cert(handle, &signedCert, &casignkey, &outcert);
    460 	if (rv != KMF_OK) {
    461 		cryptoerror(LOG_STDERR, gettext(
    462 		    "Error signing certificate.\n"));
    463 		goto cleanup;
    464 	}
    465 
    466 	/*
    467 	 * Store it on the token if the user asked for it.
    468 	 */
    469 	if (store) {
    470 		numattr = 0;
    471 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
    472 		    &kstype, sizeof (kstype));
    473 		numattr++;
    474 
    475 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
    476 		    &outcert, sizeof (KMF_DATA));
    477 		numattr++;
    478 
    479 		if (outlabel != NULL) {
    480 			kmf_set_attr_at_index(attrlist, numattr,
    481 			    KMF_CERT_LABEL_ATTR,
    482 			    outlabel, strlen(outlabel));
    483 			numattr++;
    484 		}
    485 
    486 		if (kstype == KMF_KEYSTORE_NSS) {
    487 			if (token != NULL)
    488 				kmf_set_attr_at_index(attrlist, numattr,
    489 				    KMF_TOKEN_LABEL_ATTR,
    490 				    token, strlen(token));
    491 			numattr++;
    492 		}
    493 
    494 		rv = kmf_store_cert(handle, numattr, attrlist);
    495 		if (rv != KMF_OK) {
    496 			display_error(handle, rv,
    497 			    gettext("Failed to store cert "
    498 			    "on PKCS#11 token.\n"));
    499 			rv = KMF_OK;
    500 			/* Not fatal, we can still write it to a file. */
    501 		}
    502 	}
    503 	rv = kmf_create_cert_file(&outcert, fmt, certfile);
    504 
    505 cleanup:
    506 	kmf_free_signed_csr(&csrdata);
    507 	kmf_free_data(&outcert);
    508 	kmf_free_kmf_key(handle, &casignkey);
    509 
    510 	return (rv);
    511 }
    512 
    513 /*
    514  * sign a CSR and generate an x509v3 certificate file.
    515  */
    516 int
    517 pk_signcsr(int argc, char *argv[])
    518 {
    519 	int			opt;
    520 	extern int		optind_av;
    521 	extern char		*optarg_av;
    522 	char			*token_spec = NULL;
    523 	char			*subject = NULL;
    524 	char			*issuer = NULL;
    525 	char			*dir = NULL;
    526 	char			*prefix = NULL;
    527 	char			*csrfile = NULL;
    528 	char			*serstr = NULL;
    529 	char			*ekustr = NULL;
    530 	char			*kustr = NULL;
    531 	char			*format = NULL;
    532 	char			*storestr = NULL;
    533 	char			*altname = NULL;
    534 	char			*certfile = NULL;
    535 	char			*lifetime = NULL;
    536 	char			*signkey = NULL;
    537 	char			*outlabel = NULL;
    538 	uint32_t		ltime = 365 * 24 * 60 * 60; /* 1 Year */
    539 	int			store = 0;
    540 	uint16_t		kubits = 0;
    541 	int			altcrit = 0, kucrit = 0;
    542 	KMF_BIGINT		serial = { NULL, 0 };
    543 	EKU_LIST		*ekulist = NULL;
    544 	KMF_KEYSTORE_TYPE	kstype = 0;
    545 	KMF_RETURN		rv = KMF_OK;
    546 	KMF_HANDLE_T		kmfhandle = NULL;
    547 	KMF_CREDENTIAL		tokencred = {NULL, 0};
    548 	KMF_GENERALNAMECHOICES	alttype = 0;
    549 	KMF_ENCODE_FORMAT	fmt = KMF_FORMAT_PEM;
    550 
    551 	/* Parse command line options.  Do NOT i18n/l10n. */
    552 	while ((opt = getopt_av(argc, argv,
    553 	    "k:(keystore)c:(csr)T:(token)d:(dir)"
    554 	    "p:(prefix)S:(serial)s:(subject)a:(altname)"
    555 	    "t:(store)F:(format)K:(keyusage)l:(signkey)"
    556 	    "L:(lifetime)e:(eku)i:(issuer)"
    557 	    "n:(outlabel)o:(outcert)")) != EOF) {
    558 		if (EMPTYSTRING(optarg_av))
    559 			return (PK_ERR_USAGE);
    560 		switch (opt) {
    561 			case 'k':
    562 				if (kstype != 0)
    563 					return (PK_ERR_USAGE);
    564 				kstype = KS2Int(optarg_av);
    565 				if (kstype == 0)
    566 					return (PK_ERR_USAGE);
    567 				break;
    568 			case 't':
    569 				if (storestr != NULL)
    570 					return (PK_ERR_USAGE);
    571 				storestr = optarg_av;
    572 				store = yn_to_int(optarg_av);
    573 				if (store == -1)
    574 					return (PK_ERR_USAGE);
    575 				break;
    576 			case 'a':
    577 				if (altname)
    578 					return (PK_ERR_USAGE);
    579 				altname = optarg_av;
    580 				break;
    581 			case 's':
    582 				if (subject)
    583 					return (PK_ERR_USAGE);
    584 				subject = optarg_av;
    585 				break;
    586 			case 'i':
    587 				if (issuer)
    588 					return (PK_ERR_USAGE);
    589 				issuer = optarg_av;
    590 				break;
    591 			case 'd':
    592 				if (dir)
    593 					return (PK_ERR_USAGE);
    594 				dir = optarg_av;
    595 				break;
    596 			case 'p':
    597 				if (prefix)
    598 					return (PK_ERR_USAGE);
    599 				prefix = optarg_av;
    600 				break;
    601 			case 'S':
    602 				if (serstr != NULL)
    603 					return (PK_ERR_USAGE);
    604 				serstr = optarg_av;
    605 				break;
    606 			case 'c':
    607 				if (csrfile)
    608 					return (PK_ERR_USAGE);
    609 				csrfile = optarg_av;
    610 				break;
    611 			case 'T':	/* token specifier */
    612 				if (token_spec)
    613 					return (PK_ERR_USAGE);
    614 				token_spec = optarg_av;
    615 				break;
    616 			case 'l':	/* object with specific label */
    617 				if (signkey)
    618 					return (PK_ERR_USAGE);
    619 				signkey = optarg_av;
    620 				break;
    621 			case 'e':
    622 				if (ekustr != NULL)
    623 					return (PK_ERR_USAGE);
    624 				ekustr = optarg_av;
    625 				break;
    626 			case 'K':
    627 				if (kustr != NULL)
    628 					return (PK_ERR_USAGE);
    629 				kustr = optarg_av;
    630 				break;
    631 			case 'F':
    632 				if (format != NULL)
    633 					return (PK_ERR_USAGE);
    634 				format = optarg_av;
    635 				break;
    636 			case 'o':
    637 				if (certfile != NULL)
    638 					return (PK_ERR_USAGE);
    639 				certfile = optarg_av;
    640 				break;
    641 			case 'L':
    642 				if (lifetime != NULL)
    643 					return (PK_ERR_USAGE);
    644 				lifetime = optarg_av;
    645 				break;
    646 			case 'n':
    647 				if (outlabel != NULL)
    648 					return (PK_ERR_USAGE);
    649 				outlabel = optarg_av;
    650 				break;
    651 			default:
    652 				return (PK_ERR_USAGE);
    653 		}
    654 	}
    655 	/* No additional args allowed. */
    656 	argc -= optind_av;
    657 	argv += optind_av;
    658 	if (argc)
    659 		return (PK_ERR_USAGE);
    660 
    661 
    662 	/* Assume keystore = PKCS#11 if not specified. */
    663 	if (kstype == 0)
    664 		kstype = KMF_KEYSTORE_PK11TOKEN;
    665 
    666 	DIR_OPTION_CHECK(kstype, dir);
    667 
    668 	if (signkey == NULL) {
    669 		(void) fprintf(stderr, gettext("The signing key label "
    670 		    "or filename was not specified\n"));
    671 		return (PK_ERR_USAGE);
    672 	}
    673 	if (csrfile == NULL) {
    674 		(void) fprintf(stderr, gettext("The CSR filename was not"
    675 		    " specified\n"));
    676 		return (PK_ERR_USAGE);
    677 	}
    678 	if (certfile == NULL) {
    679 		(void) fprintf(stderr, gettext("The output certificate file "
    680 		    "was not specified\n"));
    681 		return (PK_ERR_USAGE);
    682 	}
    683 	if (issuer == NULL) {
    684 		(void) fprintf(stderr, gettext("The issuer DN "
    685 		    "was not specified\n"));
    686 		return (PK_ERR_USAGE);
    687 	}
    688 	if (lifetime != NULL) {
    689 		if (Str2Lifetime(lifetime, &ltime) != 0) {
    690 			cryptoerror(LOG_STDERR,
    691 			    gettext("Error parsing lifetime string\n"));
    692 			return (PK_ERR_USAGE);
    693 		}
    694 	}
    695 	if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) {
    696 		token_spec = PK_DEFAULT_PK11TOKEN;
    697 	} else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) {
    698 		token_spec = DEFAULT_NSS_TOKEN;
    699 	}
    700 
    701 	if (serstr != NULL) {
    702 		uchar_t *bytes = NULL;
    703 		size_t bytelen;
    704 
    705 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
    706 		if (rv != KMF_OK || bytes == NULL) {
    707 			(void) fprintf(stderr, gettext("Serial number "
    708 			    "must be specified as a hex number "
    709 			    "(ex: 0x0102030405ffeeddee)\n"));
    710 			return (PK_ERR_USAGE);
    711 		}
    712 		serial.val = bytes;
    713 		serial.len = bytelen;
    714 	} else {
    715 		(void) fprintf(stderr, gettext("The serial number was not"
    716 		    " specified\n"));
    717 		return (PK_ERR_USAGE);
    718 	}
    719 
    720 	if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
    721 	    kstype == KMF_KEYSTORE_NSS)) {
    722 		/* Need to get password for private key access */
    723 		(void) get_token_password(kstype, token_spec,
    724 		    &tokencred);
    725 	}
    726 	if (kustr != NULL) {
    727 		rv = verify_keyusage(kustr, &kubits, &kucrit);
    728 		if (rv != KMF_OK) {
    729 			(void) fprintf(stderr, gettext("KeyUsage "
    730 			    "must be specified as a comma-separated list. "
    731 			    "See the man page for details.\n"));
    732 			rv = PK_ERR_USAGE;
    733 			goto end;
    734 		}
    735 	}
    736 	if (ekustr != NULL) {
    737 		rv = verify_ekunames(ekustr, &ekulist);
    738 		if (rv != KMF_OK) {
    739 			(void) fprintf(stderr, gettext("EKUs must "
    740 			    "be specified as a comma-separated list. "
    741 			    "See the man page for details.\n"));
    742 			rv = PK_ERR_USAGE;
    743 			goto end;
    744 		}
    745 	}
    746 	if (altname != NULL) {
    747 		char *p;
    748 		rv = verify_altname(altname, &alttype, &altcrit);
    749 		if (rv != KMF_OK) {
    750 			(void) fprintf(stderr, gettext("Subject AltName "
    751 			    "must be specified as a name=value pair. "
    752 			    "See the man page for details.\n"));
    753 			rv = PK_ERR_USAGE;
    754 			goto end;
    755 		}
    756 		/* advance the altname past the '=' sign */
    757 		p = strchr(altname, '=');
    758 		if (p != NULL)
    759 			altname = p + 1;
    760 	}
    761 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
    762 		cryptoerror(LOG_STDERR,
    763 		    gettext("Error parsing format string (%s).\n"),
    764 		    format);
    765 		return (PK_ERR_USAGE);
    766 	}
    767 
    768 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
    769 		return (rv);
    770 	}
    771 
    772 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
    773 		rv = pk_signcsr_pk11_nss(kmfhandle,
    774 		    kstype, dir, prefix, token_spec, &tokencred,
    775 		    signkey, csrfile, &serial, certfile, issuer, subject,
    776 		    altname, alttype, altcrit, kubits, kucrit,
    777 		    ekulist, ltime, fmt, store, outlabel);
    778 
    779 	} else if (kstype == KMF_KEYSTORE_NSS) {
    780 		if (dir == NULL)
    781 			dir = PK_DEFAULT_DIRECTORY;
    782 
    783 		rv = pk_signcsr_pk11_nss(kmfhandle,
    784 		    kstype, dir, prefix, token_spec, &tokencred,
    785 		    signkey, csrfile, &serial, certfile, issuer, subject,
    786 		    altname, alttype, altcrit, kubits, kucrit,
    787 		    ekulist, ltime, fmt, store, outlabel);
    788 
    789 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
    790 		rv = pk_signcsr_files(kmfhandle,
    791 		    signkey, csrfile, &serial, certfile, issuer, subject,
    792 		    altname, alttype, altcrit, kubits, kucrit,
    793 		    ekulist, ltime, fmt);
    794 	}
    795 
    796 end:
    797 	if (rv != KMF_OK) {
    798 		display_error(kmfhandle, rv,
    799 		    gettext("Error listing objects"));
    800 	}
    801 
    802 	if (serial.val != NULL)
    803 		free(serial.val);
    804 
    805 	if (tokencred.cred != NULL)
    806 		free(tokencred.cred);
    807 
    808 	free_eku_list(ekulist);
    809 
    810 	(void) kmf_finalize(kmfhandle);
    811 	return (rv);
    812 }
    813