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 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <stdio.h>
     27 #include <string.h>
     28 #include <ctype.h>
     29 #include <malloc.h>
     30 #include <libgen.h>
     31 #include <errno.h>
     32 #include <cryptoutil.h>
     33 #include <security/cryptoki.h>
     34 #include "common.h"
     35 
     36 #include <kmfapi.h>
     37 
     38 #define	SET_VALUE(f, s) \
     39 	kmfrv = f; \
     40 	if (kmfrv != KMF_OK) { \
     41 		cryptoerror(LOG_STDERR, \
     42 			gettext("Failed to %s: 0x%02\n"), \
     43 			s, kmfrv); \
     44 		goto cleanup; \
     45 	}
     46 
     47 static KMF_RETURN
     48 gencsr_pkcs11(KMF_HANDLE_T kmfhandle,
     49 	char *token, char *subject, char *altname,
     50 	KMF_GENERALNAMECHOICES alttype, int altcrit,
     51 	char *certlabel, KMF_KEY_ALG keyAlg,
     52 	int keylen, uint16_t kubits, int kucrit,
     53 	KMF_ENCODE_FORMAT fmt, char *csrfile,
     54 	KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist)
     55 {
     56 	KMF_RETURN kmfrv = KMF_OK;
     57 	KMF_KEY_HANDLE pubk, prik;
     58 	KMF_X509_NAME	csrSubject;
     59 	KMF_CSR_DATA	csr;
     60 	KMF_ALGORITHM_INDEX sigAlg;
     61 	KMF_DATA signedCsr = {NULL, 0};
     62 
     63 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
     64 	int numattr = 0;
     65 	KMF_ATTRIBUTE attrlist[16];
     66 	boolean_t storekey = TRUE;
     67 
     68 	(void) memset(&csr, 0, sizeof (csr));
     69 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
     70 
     71 	if (keyAlg == KMF_DSA)
     72 		sigAlg = KMF_ALGID_SHA1WithDSA;
     73 	else
     74 		sigAlg = KMF_ALGID_SHA1WithRSA;
     75 
     76 
     77 	/* If the subject name cannot be parsed, flag it now and exit */
     78 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
     79 		return (kmfrv);
     80 	}
     81 
     82 	/* Select a PKCS11 token */
     83 	kmfrv = select_token(kmfhandle, token, FALSE);
     84 	if (kmfrv != KMF_OK) {
     85 		return (kmfrv);
     86 	}
     87 
     88 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
     89 	    &kstype, sizeof (kstype));
     90 	numattr++;
     91 
     92 	if (certlabel != NULL && strlen(certlabel)) {
     93 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
     94 		    certlabel, strlen(certlabel));
     95 		numattr++;
     96 	}
     97 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR,
     98 	    &keylen, sizeof (keylen));
     99 	numattr++;
    100 
    101 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR,
    102 	    &keyAlg, sizeof (keyAlg));
    103 	numattr++;
    104 
    105 	kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
    106 	    tokencred, sizeof (KMF_CREDENTIAL));
    107 	numattr++;
    108 
    109 	if (token && strlen(token)) {
    110 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
    111 		    token, strlen(token));
    112 		numattr++;
    113 	}
    114 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
    115 	    &pubk, sizeof (KMF_KEY_HANDLE));
    116 	numattr++;
    117 
    118 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR,
    119 	    &prik, sizeof (KMF_KEY_HANDLE));
    120 	numattr++;
    121 
    122 	kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR,
    123 	    &storekey, sizeof (storekey));
    124 	numattr++;
    125 
    126 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
    127 	if (kmfrv != KMF_OK) {
    128 		return (kmfrv);
    129 	}
    130 
    131 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), "keypair");
    132 
    133 	SET_VALUE(kmf_set_csr_version(&csr, 2), "version number");
    134 
    135 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), "subject name");
    136 
    137 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg),
    138 	    "SignatureAlgorithm");
    139 
    140 	if (altname != NULL) {
    141 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
    142 		    alttype), "SetCSRSubjectAltName");
    143 	}
    144 
    145 	if (kubits != 0) {
    146 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
    147 		    "SetCSRKeyUsage");
    148 	}
    149 	if (ekulist != NULL) {
    150 		int i;
    151 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
    152 			SET_VALUE(kmf_add_csr_eku(&csr,
    153 			    &ekulist->ekulist[i],
    154 			    ekulist->critlist[i]),
    155 			    "Extended Key Usage");
    156 		}
    157 	}
    158 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
    159 	    KMF_OK) {
    160 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile);
    161 	}
    162 
    163 cleanup:
    164 	(void) kmf_free_data(&signedCsr);
    165 	(void) kmf_free_signed_csr(&csr);
    166 
    167 	/* delete the public key */
    168 	numattr = 0;
    169 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
    170 	    &kstype, sizeof (kstype));
    171 	numattr++;
    172 
    173 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
    174 	    &pubk, sizeof (KMF_KEY_HANDLE));
    175 	numattr++;
    176 
    177 	if (tokencred != NULL && tokencred->cred != NULL) {
    178 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
    179 		    tokencred, sizeof (KMF_CREDENTIAL));
    180 		numattr++;
    181 	}
    182 
    183 	(void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist);
    184 
    185 	/*
    186 	 * If there is an error, then we need to remove the private key
    187 	 * from the token.
    188 	 */
    189 	if (kmfrv != KMF_OK) {
    190 		numattr = 0;
    191 		kmf_set_attr_at_index(attrlist, numattr,
    192 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
    193 		numattr++;
    194 
    195 		kmf_set_attr_at_index(attrlist, numattr,
    196 		    KMF_KEY_HANDLE_ATTR, &prik, sizeof (KMF_KEY_HANDLE));
    197 		numattr++;
    198 
    199 		if (tokencred != NULL && tokencred->cred != NULL) {
    200 			kmf_set_attr_at_index(attrlist, numattr,
    201 			    KMF_CREDENTIAL_ATTR, tokencred,
    202 			    sizeof (KMF_CREDENTIAL));
    203 			numattr++;
    204 		}
    205 
    206 		(void) kmf_delete_key_from_keystore(kmfhandle, numattr,
    207 		    attrlist);
    208 	}
    209 
    210 	(void) kmf_free_kmf_key(kmfhandle, &prik);
    211 	return (kmfrv);
    212 }
    213 
    214 static KMF_RETURN
    215 gencsr_file(KMF_HANDLE_T kmfhandle,
    216 	KMF_KEY_ALG keyAlg,
    217 	int keylen, KMF_ENCODE_FORMAT fmt,
    218 	char *subject, char *altname, KMF_GENERALNAMECHOICES alttype,
    219 	int altcrit, uint16_t kubits, int kucrit,
    220 	char *outcsr, char *outkey, EKU_LIST *ekulist)
    221 {
    222 	KMF_RETURN kmfrv;
    223 	KMF_KEY_HANDLE pubk, prik;
    224 	KMF_X509_NAME	csrSubject;
    225 	KMF_CSR_DATA	csr;
    226 	KMF_ALGORITHM_INDEX sigAlg;
    227 	KMF_DATA signedCsr = {NULL, 0};
    228 	char *fullcsrpath = NULL;
    229 	char *fullkeypath = NULL;
    230 
    231 	int numattr = 0;
    232 	KMF_ATTRIBUTE attrlist[16];
    233 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
    234 	boolean_t	storekey = TRUE;
    235 
    236 	(void) memset(&csr, 0, sizeof (csr));
    237 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
    238 
    239 	if (EMPTYSTRING(outcsr) || EMPTYSTRING(outkey)) {
    240 		cryptoerror(LOG_STDERR,
    241 		    gettext("No output file was specified for "
    242 		    "the csr or key\n"));
    243 		return (KMF_ERR_BAD_PARAMETER);
    244 	}
    245 	fullcsrpath = strdup(outcsr);
    246 	if (verify_file(fullcsrpath)) {
    247 		cryptoerror(LOG_STDERR,
    248 		    gettext("Cannot write the indicated output "
    249 		    "certificate file (%s).\n"), fullcsrpath);
    250 		free(fullcsrpath);
    251 		return (PK_ERR_USAGE);
    252 	}
    253 
    254 	fullkeypath = strdup(outkey);
    255 	if (verify_file(fullcsrpath)) {
    256 		cryptoerror(LOG_STDERR,
    257 		    gettext("Cannot write the indicated output "
    258 		    "key file (%s).\n"), fullkeypath);
    259 		free(fullcsrpath);
    260 		return (PK_ERR_USAGE);
    261 	}
    262 
    263 	if (keyAlg == KMF_DSA)
    264 		sigAlg = KMF_ALGID_SHA1WithDSA;
    265 	else
    266 		sigAlg = KMF_ALGID_SHA1WithRSA;
    267 
    268 	/* If the subject name cannot be parsed, flag it now and exit */
    269 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
    270 		return (kmfrv);
    271 	}
    272 
    273 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
    274 	    &kstype, sizeof (kstype));
    275 	numattr++;
    276 
    277 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
    278 	    fullkeypath, strlen(fullkeypath));
    279 	numattr++;
    280 
    281 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR,
    282 	    &keylen, sizeof (keylen));
    283 	numattr++;
    284 
    285 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR,
    286 	    &keyAlg, sizeof (keyAlg));
    287 	numattr++;
    288 
    289 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
    290 	    &fmt, sizeof (fmt));
    291 	numattr++;
    292 
    293 	(void) memset(&prik, 0, sizeof (prik));
    294 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR,
    295 	    &prik, sizeof (KMF_KEY_HANDLE));
    296 	numattr++;
    297 
    298 	(void) memset(&pubk, 0, sizeof (pubk));
    299 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
    300 	    &pubk, sizeof (KMF_KEY_HANDLE));
    301 	numattr++;
    302 
    303 	kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR,
    304 	    &storekey, sizeof (storekey));
    305 	numattr++;
    306 
    307 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
    308 	if (kmfrv != KMF_OK) {
    309 		goto cleanup;
    310 	}
    311 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
    312 	    "SetCSRPubKey");
    313 
    314 	SET_VALUE(kmf_set_csr_version(&csr, 2), "SetCSRVersion");
    315 
    316 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
    317 	    "kmf_set_csr_subject");
    318 
    319 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");
    320 
    321 	if (altname != NULL) {
    322 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
    323 		    alttype), "kmf_set_csr_subject_altname");
    324 	}
    325 	if (kubits != NULL) {
    326 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
    327 		    "kmf_set_csr_ku");
    328 	}
    329 	if (ekulist != NULL) {
    330 		int i;
    331 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
    332 			SET_VALUE(kmf_add_csr_eku(&csr,
    333 			    &ekulist->ekulist[i],
    334 			    ekulist->critlist[i]),
    335 			    "Extended Key Usage");
    336 		}
    337 	}
    338 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
    339 	    KMF_OK) {
    340 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, fullcsrpath);
    341 	}
    342 
    343 cleanup:
    344 	if (fullkeypath)
    345 		free(fullkeypath);
    346 	if (fullcsrpath)
    347 		free(fullcsrpath);
    348 
    349 	kmf_free_data(&signedCsr);
    350 	kmf_free_kmf_key(kmfhandle, &prik);
    351 	kmf_free_signed_csr(&csr);
    352 
    353 	return (kmfrv);
    354 }
    355 
    356 static KMF_RETURN
    357 gencsr_nss(KMF_HANDLE_T kmfhandle,
    358 	char *token, char *subject, char *altname,
    359 	KMF_GENERALNAMECHOICES alttype, int altcrit,
    360 	char *nickname, char *dir, char *prefix,
    361 	KMF_KEY_ALG keyAlg, int keylen,
    362 	uint16_t kubits, int kucrit,
    363 	KMF_ENCODE_FORMAT fmt, char *csrfile,
    364 	KMF_CREDENTIAL *tokencred, EKU_LIST *ekulist)
    365 {
    366 	KMF_RETURN kmfrv;
    367 	KMF_KEY_HANDLE pubk, prik;
    368 	KMF_X509_NAME	csrSubject;
    369 	KMF_CSR_DATA	csr;
    370 	KMF_ALGORITHM_INDEX sigAlg;
    371 	KMF_DATA signedCsr = {NULL, 0};
    372 
    373 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
    374 	int numattr = 0;
    375 	KMF_ATTRIBUTE attrlist[16];
    376 	boolean_t storekey = TRUE;
    377 
    378 	if (token == NULL)
    379 		token = DEFAULT_NSS_TOKEN;
    380 
    381 	if (keyAlg == KMF_DSA)
    382 		sigAlg = KMF_ALGID_SHA1WithDSA;
    383 	else
    384 		sigAlg = KMF_ALGID_SHA1WithRSA;
    385 
    386 	kmfrv = configure_nss(kmfhandle, dir, prefix);
    387 	if (kmfrv != KMF_OK)
    388 		return (kmfrv);
    389 
    390 	(void) memset(&csr, 0, sizeof (csr));
    391 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
    392 	(void) memset(&pubk, 0, sizeof (pubk));
    393 	(void) memset(&prik, 0, sizeof (prik));
    394 
    395 	/* If the subject name cannot be parsed, flag it now and exit */
    396 	if ((kmfrv = kmf_dn_parser(subject, &csrSubject)) != KMF_OK) {
    397 		return (kmfrv);
    398 	}
    399 
    400 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
    401 	    &kstype, sizeof (kstype));
    402 	numattr++;
    403 
    404 	if (nickname != NULL && strlen(nickname)) {
    405 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
    406 		    nickname, strlen(nickname));
    407 		numattr++;
    408 	}
    409 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLENGTH_ATTR,
    410 	    &keylen, sizeof (keylen));
    411 	numattr++;
    412 
    413 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYALG_ATTR,
    414 	    &keyAlg, sizeof (keyAlg));
    415 	numattr++;
    416 
    417 	if (tokencred != NULL && tokencred->credlen > 0) {
    418 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
    419 		    tokencred, sizeof (KMF_CREDENTIAL));
    420 		numattr++;
    421 	}
    422 
    423 	if (token && strlen(token)) {
    424 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
    425 		    token, strlen(token));
    426 		numattr++;
    427 	}
    428 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
    429 	    &pubk, sizeof (KMF_KEY_HANDLE));
    430 	numattr++;
    431 
    432 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVKEY_HANDLE_ATTR,
    433 	    &prik, sizeof (KMF_KEY_HANDLE));
    434 	numattr++;
    435 
    436 	kmf_set_attr_at_index(attrlist, numattr, KMF_STOREKEY_BOOL_ATTR,
    437 	    &storekey, sizeof (storekey));
    438 	numattr++;
    439 
    440 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
    441 	if (kmfrv != KMF_OK) {
    442 		goto cleanup;
    443 	}
    444 
    445 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr),
    446 	    "kmf_set_csr_pubkey");
    447 	SET_VALUE(kmf_set_csr_version(&csr, 2), "kmf_set_csr_version");
    448 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject),
    449 	    "kmf_set_csr_subject");
    450 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "kmf_set_csr_sig_alg");
    451 
    452 	if (altname != NULL) {
    453 		SET_VALUE(kmf_set_csr_subject_altname(&csr, altname, altcrit,
    454 		    alttype), "kmf_set_csr_subject_altname");
    455 	}
    456 	if (kubits != NULL) {
    457 		SET_VALUE(kmf_set_csr_ku(&csr, kucrit, kubits),
    458 		    "kmf_set_csr_ku");
    459 	}
    460 	if (ekulist != NULL) {
    461 		int i;
    462 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
    463 			SET_VALUE(kmf_add_csr_eku(&csr,
    464 			    &ekulist->ekulist[i],
    465 			    ekulist->critlist[i]),
    466 			    "Extended Key Usage");
    467 		}
    468 	}
    469 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
    470 	    KMF_OK) {
    471 		kmfrv = kmf_create_csr_file(&signedCsr, fmt, csrfile);
    472 	}
    473 
    474 cleanup:
    475 	(void) kmf_free_data(&signedCsr);
    476 	(void) kmf_free_kmf_key(kmfhandle, &prik);
    477 
    478 	/* delete the key */
    479 	numattr = 0;
    480 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
    481 	    &kstype, sizeof (kstype));
    482 	numattr++;
    483 
    484 	kmf_set_attr_at_index(attrlist, numattr, KMF_PUBKEY_HANDLE_ATTR,
    485 	    &pubk, sizeof (KMF_KEY_HANDLE));
    486 	numattr++;
    487 
    488 	if (tokencred != NULL && tokencred->credlen > 0) {
    489 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
    490 		    tokencred, sizeof (KMF_CREDENTIAL));
    491 		numattr++;
    492 	}
    493 
    494 	if (token && strlen(token)) {
    495 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
    496 		    token, strlen(token));
    497 		numattr++;
    498 	}
    499 
    500 	(void) kmf_delete_key_from_keystore(kmfhandle, numattr, attrlist);
    501 
    502 	(void) kmf_free_signed_csr(&csr);
    503 
    504 	return (kmfrv);
    505 }
    506 
    507 int
    508 pk_gencsr(int argc, char *argv[])
    509 {
    510 	KMF_RETURN rv;
    511 	int opt;
    512 	extern int	optind_av;
    513 	extern char	*optarg_av;
    514 	KMF_KEYSTORE_TYPE kstype = 0;
    515 	char *subject = NULL;
    516 	char *tokenname = NULL;
    517 	char *dir = NULL;
    518 	char *prefix = NULL;
    519 	int keylen = PK_DEFAULT_KEYLENGTH;
    520 	char *certlabel = NULL;
    521 	char *outcsr = NULL;
    522 	char *outkey = NULL;
    523 	char *format = NULL;
    524 	char *altname = NULL;
    525 	char *kustr = NULL;
    526 	char *ekustr = NULL;
    527 	uint16_t kubits = 0;
    528 	char *keytype = PK_DEFAULT_KEYTYPE;
    529 	KMF_HANDLE_T kmfhandle = NULL;
    530 	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
    531 	KMF_KEY_ALG keyAlg = KMF_RSA;
    532 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_SHA1WithRSA;
    533 	boolean_t interactive = B_FALSE;
    534 	char *subname = NULL;
    535 	KMF_CREDENTIAL tokencred = {NULL, 0};
    536 	KMF_GENERALNAMECHOICES alttype = 0;
    537 	int altcrit = 0, kucrit = 0;
    538 	EKU_LIST *ekulist = NULL;
    539 
    540 	while ((opt = getopt_av(argc, argv,
    541 	    "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
    542 	    "u:(keyusage)T:(token)d:(dir)p:(prefix)t:(keytype)"
    543 	    "y:(keylen)l:(label)c:(outcsr)e:(eku)"
    544 	    "K:(outkey)F:(format)")) != EOF) {
    545 
    546 		if (opt != 'i' && EMPTYSTRING(optarg_av))
    547 			return (PK_ERR_USAGE);
    548 
    549 		switch (opt) {
    550 			case 'A':
    551 				altname = optarg_av;
    552 				break;
    553 			case 'i':
    554 				if (interactive)
    555 					return (PK_ERR_USAGE);
    556 				else if (subject) {
    557 					cryptoerror(LOG_STDERR,
    558 					    gettext("Interactive (-i) and "
    559 					    "subject options are mutually "
    560 					    "exclusive.\n"));
    561 					return (PK_ERR_USAGE);
    562 				} else
    563 					interactive = B_TRUE;
    564 				break;
    565 			case 'k':
    566 				kstype = KS2Int(optarg_av);
    567 				if (kstype == 0)
    568 					return (PK_ERR_USAGE);
    569 				break;
    570 			case 's':
    571 				if (subject)
    572 					return (PK_ERR_USAGE);
    573 				else if (interactive) {
    574 					cryptoerror(LOG_STDERR,
    575 					    gettext("Interactive (-i) and "
    576 					    "subject options are mutually "
    577 					    "exclusive.\n"));
    578 					return (PK_ERR_USAGE);
    579 				} else
    580 					subject = optarg_av;
    581 				break;
    582 			case 'l':
    583 			case 'n':
    584 				if (certlabel)
    585 					return (PK_ERR_USAGE);
    586 				certlabel = optarg_av;
    587 				break;
    588 			case 'T':
    589 				if (tokenname)
    590 					return (PK_ERR_USAGE);
    591 				tokenname = optarg_av;
    592 				break;
    593 			case 'd':
    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 't':
    602 				keytype = optarg_av;
    603 				break;
    604 			case 'u':
    605 				kustr = optarg_av;
    606 				break;
    607 			case 'y':
    608 				if (sscanf(optarg_av, "%d",
    609 				    &keylen) != 1) {
    610 					cryptoerror(LOG_STDERR,
    611 					    gettext("Unrecognized "
    612 					    "key length (%s)\n"), optarg_av);
    613 					return (PK_ERR_USAGE);
    614 				}
    615 				break;
    616 			case 'c':
    617 				if (outcsr)
    618 					return (PK_ERR_USAGE);
    619 				outcsr = optarg_av;
    620 				break;
    621 			case 'K':
    622 				if (outkey)
    623 					return (PK_ERR_USAGE);
    624 				outkey = optarg_av;
    625 				break;
    626 			case 'F':
    627 				if (format)
    628 					return (PK_ERR_USAGE);
    629 				format = optarg_av;
    630 				break;
    631 			case 'e':
    632 				ekustr = optarg_av;
    633 				break;
    634 			default:
    635 				cryptoerror(LOG_STDERR, gettext(
    636 				    "unrecognized gencsr option '%s'\n"),
    637 				    argv[optind_av]);
    638 				return (PK_ERR_USAGE);
    639 		}
    640 	}
    641 	/* No additional args allowed. */
    642 	argc -= optind_av;
    643 	argv += optind_av;
    644 	if (argc) {
    645 		return (PK_ERR_USAGE);
    646 	}
    647 
    648 	/* Assume keystore = PKCS#11 if not specified. */
    649 	if (kstype == 0)
    650 		kstype = KMF_KEYSTORE_PK11TOKEN;
    651 
    652 	DIR_OPTION_CHECK(kstype, dir);
    653 
    654 	if (EMPTYSTRING(outcsr) && interactive) {
    655 		(void) get_filename("CSR", &outcsr);
    656 	}
    657 	if (EMPTYSTRING(outcsr)) {
    658 		(void) printf(gettext("A filename must be specified to hold"
    659 		    "the final certificate request data.\n"));
    660 		return (PK_ERR_USAGE);
    661 	}
    662 	/*
    663 	 * verify that the outcsr file does not already exist
    664 	 * and that it can be created.
    665 	 */
    666 	rv = verify_file(outcsr);
    667 	if (rv != KMF_OK) {
    668 		cryptoerror(LOG_STDERR, gettext("output file (%s) "
    669 		    "cannot be created.\n"), outcsr);
    670 		return (PK_ERR_USAGE);
    671 	}
    672 
    673 	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) {
    674 		if (EMPTYSTRING(certlabel) && interactive)
    675 			(void) get_certlabel(&certlabel);
    676 
    677 		if (EMPTYSTRING(certlabel)) {
    678 			cryptoerror(LOG_STDERR, gettext("A label must be "
    679 			    "specified to create a certificate request.\n"));
    680 			return (PK_ERR_USAGE);
    681 		}
    682 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
    683 		if (EMPTYSTRING(outkey) && interactive)
    684 			(void) get_filename("private key", &outkey);
    685 
    686 		if (EMPTYSTRING(outkey)) {
    687 			cryptoerror(LOG_STDERR, gettext("A key filename "
    688 			    "must be specified to create a certificate "
    689 			    "request.\n"));
    690 			return (PK_ERR_USAGE);
    691 		}
    692 	}
    693 
    694 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
    695 		cryptoerror(LOG_STDERR,
    696 		    gettext("Error parsing format string (%s).\n"), format);
    697 		return (PK_ERR_USAGE);
    698 	}
    699 	if (format && fmt != KMF_FORMAT_ASN1 && fmt != KMF_FORMAT_PEM) {
    700 		cryptoerror(LOG_STDERR,
    701 		    gettext("CSR must be DER or PEM format.\n"));
    702 		return (PK_ERR_USAGE);
    703 	}
    704 
    705 	/*
    706 	 * Check the subject name.
    707 	 * If interactive is true, get it now interactively.
    708 	 */
    709 	if (interactive) {
    710 		if (get_subname(&subname) != KMF_OK) {
    711 			cryptoerror(LOG_STDERR, gettext("Failed to get the "
    712 			    "subject name interactively.\n"));
    713 			return (PK_ERR_USAGE);
    714 		}
    715 	} else {
    716 		if (EMPTYSTRING(subject)) {
    717 			cryptoerror(LOG_STDERR, gettext("A subject name or "
    718 			    "-i must be specified to create a certificate "
    719 			    "request.\n"));
    720 			return (PK_ERR_USAGE);
    721 		} else {
    722 			subname = strdup(subject);
    723 			if (subname == NULL) {
    724 				cryptoerror(LOG_STDERR,
    725 				    gettext("Out of memory.\n"));
    726 				return (PK_ERR_SYSTEM);
    727 			}
    728 		}
    729 	}
    730 	if (altname != NULL) {
    731 		rv = verify_altname(altname, &alttype, &altcrit);
    732 		if (rv != KMF_OK) {
    733 			cryptoerror(LOG_STDERR, gettext("Subject AltName "
    734 			    "must be specified as a name=value pair. "
    735 			    "See the man page for details."));
    736 			goto end;
    737 		} else {
    738 			/* advance the altname past the '=' sign */
    739 			char *p = strchr(altname, '=');
    740 			if (p != NULL)
    741 				altname = p + 1;
    742 		}
    743 	}
    744 
    745 	if (kustr != NULL) {
    746 		rv = verify_keyusage(kustr, &kubits, &kucrit);
    747 		if (rv != KMF_OK) {
    748 			cryptoerror(LOG_STDERR, gettext("KeyUsage "
    749 			    "must be specified as a comma-separated list. "
    750 			    "See the man page for details."));
    751 			goto end;
    752 		}
    753 	}
    754 	if (ekustr != NULL) {
    755 		rv = verify_ekunames(ekustr, &ekulist);
    756 		if (rv != KMF_OK) {
    757 			(void) fprintf(stderr, gettext("EKUs must "
    758 			    "be specified as a comma-separated list. "
    759 			    "See the man page for details.\n"));
    760 			rv = PK_ERR_USAGE;
    761 			goto end;
    762 		}
    763 	}
    764 
    765 	if ((rv = Str2KeyType(keytype, &keyAlg, &sigAlg)) != 0) {
    766 		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
    767 		    keytype);
    768 		goto end;
    769 	}
    770 
    771 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
    772 		if (tokenname == NULL || !strlen(tokenname)) {
    773 			if (kstype == KMF_KEYSTORE_NSS) {
    774 				tokenname = "internal";
    775 			} else  {
    776 				tokenname = PK_DEFAULT_PK11TOKEN;
    777 			}
    778 		}
    779 
    780 		(void) get_token_password(kstype, tokenname, &tokencred);
    781 	}
    782 
    783 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
    784 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
    785 		return (PK_ERR_USAGE);
    786 	}
    787 
    788 
    789 	if (kstype == KMF_KEYSTORE_NSS) {
    790 		if (dir == NULL)
    791 			dir = PK_DEFAULT_DIRECTORY;
    792 
    793 		rv = gencsr_nss(kmfhandle,
    794 		    tokenname, subname, altname, alttype, altcrit,
    795 		    certlabel, dir, prefix,
    796 		    keyAlg, keylen, kubits, kucrit,
    797 		    fmt, outcsr, &tokencred, ekulist);
    798 
    799 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
    800 		rv = gencsr_pkcs11(kmfhandle,
    801 		    tokenname, subname, altname, alttype, altcrit,
    802 		    certlabel, keyAlg, keylen,
    803 		    kubits, kucrit, fmt, outcsr, &tokencred, ekulist);
    804 
    805 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
    806 		rv = gencsr_file(kmfhandle,
    807 		    keyAlg, keylen, fmt, subname, altname,
    808 		    alttype, altcrit, kubits, kucrit,
    809 		    outcsr, outkey, ekulist);
    810 	}
    811 
    812 end:
    813 	if (rv != KMF_OK) {
    814 		display_error(kmfhandle, rv,
    815 		    gettext("Error creating CSR or keypair"));
    816 
    817 		if (rv == KMF_ERR_RDN_PARSER) {
    818 			cryptoerror(LOG_STDERR, gettext("subject or "
    819 			    "issuer name must be in proper DN format.\n"));
    820 		}
    821 	}
    822 
    823 	if (ekulist != NULL)
    824 		free_eku_list(ekulist);
    825 
    826 	if (subname)
    827 		free(subname);
    828 
    829 	if (tokencred.cred != NULL)
    830 		free(tokencred.cred);
    831 
    832 	(void) kmf_finalize(kmfhandle);
    833 	if (rv != KMF_OK)
    834 		return (PK_ERR_USAGE);
    835 
    836 	return (0);
    837 }
    838