xref: /illumos-gate/usr/src/cmd/cmd-crypto/pktool/gencert.c (revision 7a088f03b431bdffa96c3b2175964d4d38420caa)
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 set %s: 0x%02x\n"), \
43 			s, kmfrv); \
44 		goto cleanup; \
45 	}
46 
47 static int
48 gencert_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 	KMF_ALGORITHM_INDEX sigAlg,
53 	int keylen, uint32_t ltime, KMF_BIGINT *serial,
54 	uint16_t kubits, int kucrit, KMF_CREDENTIAL *tokencred,
55 	EKU_LIST *ekulist)
56 {
57 	KMF_RETURN kmfrv = KMF_OK;
58 	KMF_KEY_HANDLE pubk, prik;
59 	KMF_X509_CERTIFICATE signedCert;
60 	KMF_X509_NAME	certSubject;
61 	KMF_X509_NAME	certIssuer;
62 	KMF_DATA x509DER;
63 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
64 	KMF_ATTRIBUTE attrlist[16];
65 	int numattr = 0;
66 	KMF_KEY_ALG keytype;
67 	uint32_t keylength;
68 
69 	(void) memset(&signedCert, 0, sizeof (signedCert));
70 	(void) memset(&certSubject, 0, sizeof (certSubject));
71 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
72 	(void) memset(&x509DER, 0, sizeof (x509DER));
73 
74 	/* If the subject name cannot be parsed, flag it now and exit */
75 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
76 		cryptoerror(LOG_STDERR,
77 		    gettext("Subject name cannot be parsed.\n"));
78 		return (PK_ERR_USAGE);
79 	}
80 
81 	/* For a self-signed cert, the issuser and subject are the same */
82 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
83 		cryptoerror(LOG_STDERR,
84 		    gettext("Subject name cannot be parsed.\n"));
85 		return (PK_ERR_USAGE);
86 	}
87 
88 	keylength = keylen; /* bits */
89 	keytype = keyAlg;
90 
91 	/* Select a PKCS11 token */
92 	kmfrv = select_token(kmfhandle, token, FALSE);
93 
94 	if (kmfrv != KMF_OK) {
95 		return (kmfrv);
96 	}
97 
98 	kmf_set_attr_at_index(attrlist, numattr,
99 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
100 	    sizeof (kstype));
101 	numattr++;
102 
103 	kmf_set_attr_at_index(attrlist, numattr,
104 	    KMF_KEYALG_ATTR, &keytype,
105 	    sizeof (keytype));
106 	numattr++;
107 
108 	kmf_set_attr_at_index(attrlist, numattr,
109 	    KMF_KEYLENGTH_ATTR, &keylength,
110 	    sizeof (keylength));
111 	numattr++;
112 
113 	if (certlabel != NULL) {
114 		kmf_set_attr_at_index(attrlist, numattr,
115 		    KMF_KEYLABEL_ATTR, certlabel,
116 		    strlen(certlabel));
117 		numattr++;
118 	}
119 
120 	if (tokencred != NULL && tokencred->cred != NULL) {
121 		kmf_set_attr_at_index(attrlist, numattr,
122 		    KMF_CREDENTIAL_ATTR, tokencred,
123 		    sizeof (KMF_CREDENTIAL));
124 		numattr++;
125 	}
126 
127 	kmf_set_attr_at_index(attrlist, numattr,
128 	    KMF_PRIVKEY_HANDLE_ATTR, &prik,
129 	    sizeof (KMF_KEY_HANDLE));
130 	numattr++;
131 
132 	kmf_set_attr_at_index(attrlist, numattr,
133 	    KMF_PUBKEY_HANDLE_ATTR, &pubk,
134 	    sizeof (KMF_KEY_HANDLE));
135 	numattr++;
136 
137 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
138 	if (kmfrv != KMF_OK) {
139 		return (kmfrv);
140 	}
141 
142 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
143 	    "keypair");
144 
145 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
146 
147 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
148 	    "serial number");
149 
150 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
151 	    "validity time");
152 
153 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
154 	    "signature algorithm");
155 
156 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
157 	    "subject name");
158 
159 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
160 	    "issuer name");
161 
162 	if (altname != NULL)
163 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
164 		    alttype, altname), "subjectAltName");
165 
166 	if (kubits != 0)
167 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
168 		    "KeyUsage");
169 
170 	if (ekulist != NULL) {
171 		int i;
172 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
173 			SET_VALUE(kmf_add_cert_eku(&signedCert,
174 			    &ekulist->ekulist[i], ekulist->critlist[i]),
175 			    "Extended Key Usage");
176 		}
177 	}
178 
179 	/*
180 	 * Construct attributes for the kmf_sign_cert operation.
181 	 */
182 	numattr = 0;
183 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
184 	    &kstype, sizeof (kstype));
185 	numattr++;
186 
187 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
188 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
189 	numattr++;
190 
191 	/* cert data that is to be signed */
192 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
193 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
194 	numattr++;
195 
196 	/* output buffer for the signed cert */
197 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
198 	    &x509DER, sizeof (KMF_DATA));
199 	numattr++;
200 
201 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
202 	    KMF_OK) {
203 		goto cleanup;
204 	}
205 
206 	/*
207 	 * Store the cert in the DB.
208 	 */
209 	numattr = 0;
210 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
211 	    &kstype, sizeof (kstype));
212 	numattr++;
213 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
214 	    &x509DER, sizeof (KMF_DATA));
215 	numattr++;
216 
217 	if (certlabel != NULL) {
218 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
219 		    certlabel, strlen(certlabel));
220 		numattr++;
221 	}
222 
223 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
224 
225 cleanup:
226 	kmf_free_data(&x509DER);
227 	kmf_free_dn(&certSubject);
228 	kmf_free_dn(&certIssuer);
229 
230 	/*
231 	 * If kmf_sign_cert or kmf_store_cert failed, then we need to clean up
232 	 * the key pair from the token.
233 	 */
234 	if (kmfrv != KMF_OK) {
235 		/* delete the public key */
236 		numattr = 0;
237 		kmf_set_attr_at_index(attrlist, numattr,
238 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
239 		numattr++;
240 
241 		kmf_set_attr_at_index(attrlist, numattr,
242 		    KMF_KEY_HANDLE_ATTR, &pubk, sizeof (KMF_KEY_HANDLE));
243 		numattr++;
244 
245 		if (tokencred != NULL && tokencred->cred != NULL) {
246 			kmf_set_attr_at_index(attrlist, numattr,
247 			    KMF_CREDENTIAL_ATTR, tokencred,
248 			    sizeof (KMF_CREDENTIAL));
249 			numattr++;
250 		}
251 
252 		(void) kmf_delete_key_from_keystore(kmfhandle, numattr,
253 		    attrlist);
254 
255 		/* delete the private key */
256 		numattr = 0;
257 		kmf_set_attr_at_index(attrlist, numattr,
258 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
259 		numattr++;
260 
261 		kmf_set_attr_at_index(attrlist, numattr,
262 		    KMF_KEY_HANDLE_ATTR, &prik, sizeof (KMF_KEY_HANDLE));
263 		numattr++;
264 
265 		if (tokencred != NULL && tokencred->cred != NULL) {
266 			kmf_set_attr_at_index(attrlist, numattr,
267 			    KMF_CREDENTIAL_ATTR, tokencred,
268 			    sizeof (KMF_CREDENTIAL));
269 			numattr++;
270 		}
271 
272 		(void) kmf_delete_key_from_keystore(kmfhandle, numattr,
273 		    attrlist);
274 	}
275 
276 	return (kmfrv);
277 }
278 
279 static int
280 gencert_file(KMF_HANDLE_T kmfhandle,
281 	KMF_KEY_ALG keyAlg, KMF_ALGORITHM_INDEX sigAlg,
282 	int keylen, KMF_ENCODE_FORMAT fmt,
283 	uint32_t ltime, char *subject, char *altname,
284 	KMF_GENERALNAMECHOICES alttype, int altcrit,
285 	KMF_BIGINT *serial, uint16_t kubits, int kucrit,
286 	char *outcert, char *outkey,
287 	EKU_LIST *ekulist)
288 {
289 	KMF_RETURN kmfrv;
290 	KMF_KEY_HANDLE pubk, prik;
291 	KMF_X509_CERTIFICATE signedCert;
292 	KMF_X509_NAME	certSubject;
293 	KMF_X509_NAME	certIssuer;
294 	KMF_DATA x509DER;
295 	char *fullcertpath = NULL;
296 	char *fullkeypath = NULL;
297 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
298 	KMF_ATTRIBUTE attrlist[10];
299 	int numattr = 0;
300 	KMF_KEY_ALG keytype;
301 	uint32_t keylength;
302 	KMF_ENCODE_FORMAT format;
303 
304 	(void) memset(&signedCert, 0, sizeof (signedCert));
305 	(void) memset(&certSubject, 0, sizeof (certSubject));
306 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
307 	(void) memset(&x509DER, 0, sizeof (x509DER));
308 
309 	if (EMPTYSTRING(outcert) || EMPTYSTRING(outkey)) {
310 		cryptoerror(LOG_STDERR,
311 		    gettext("No output file was specified for "
312 		    "the cert or key\n"));
313 		return (PK_ERR_USAGE);
314 	}
315 	fullcertpath = strdup(outcert);
316 	if (verify_file(fullcertpath)) {
317 		cryptoerror(LOG_STDERR,
318 		    gettext("Cannot write the indicated output "
319 		    "certificate file (%s).\n"), fullcertpath);
320 		free(fullcertpath);
321 		return (PK_ERR_USAGE);
322 	}
323 
324 	fullkeypath = strdup(outkey);
325 	if (verify_file(fullkeypath)) {
326 		cryptoerror(LOG_STDERR,
327 		    gettext("Cannot write the indicated output "
328 		    "key file (%s).\n"), fullkeypath);
329 		free(fullkeypath);
330 		free(fullcertpath);
331 		return (PK_ERR_USAGE);
332 	}
333 
334 	/* If the subject name cannot be parsed, flag it now and exit */
335 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
336 		cryptoerror(LOG_STDERR,
337 		    gettext("Subject name cannot be parsed (%s)\n"), subject);
338 		return (PK_ERR_USAGE);
339 	}
340 
341 	/* For a self-signed cert, the issuser and subject are the same */
342 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
343 		cryptoerror(LOG_STDERR,
344 		    gettext("Subject name cannot be parsed (%s)\n"), subject);
345 		kmf_free_dn(&certSubject);
346 		return (PK_ERR_USAGE);
347 	}
348 
349 	keylength = keylen; /* bits */
350 	keytype = keyAlg;
351 	format = fmt;
352 
353 	kmf_set_attr_at_index(attrlist, numattr,
354 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
355 	    sizeof (kstype));
356 	numattr++;
357 
358 	kmf_set_attr_at_index(attrlist, numattr,
359 	    KMF_KEYALG_ATTR, &keytype,
360 	    sizeof (keytype));
361 	numattr++;
362 
363 	kmf_set_attr_at_index(attrlist, numattr,
364 	    KMF_KEYLENGTH_ATTR, &keylength,
365 	    sizeof (keylength));
366 	numattr++;
367 
368 	if (fullkeypath != NULL) {
369 		kmf_set_attr_at_index(attrlist, numattr,
370 		    KMF_KEY_FILENAME_ATTR, fullkeypath,
371 		    strlen(fullkeypath));
372 		numattr++;
373 	}
374 
375 	kmf_set_attr_at_index(attrlist, numattr,
376 	    KMF_ENCODE_FORMAT_ATTR, &format,
377 	    sizeof (format));
378 	numattr++;
379 
380 	kmf_set_attr_at_index(attrlist, numattr,
381 	    KMF_PRIVKEY_HANDLE_ATTR, &prik,
382 	    sizeof (KMF_KEY_HANDLE));
383 	numattr++;
384 
385 	kmf_set_attr_at_index(attrlist, numattr,
386 	    KMF_PUBKEY_HANDLE_ATTR, &pubk,
387 	    sizeof (KMF_KEY_HANDLE));
388 	numattr++;
389 
390 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
391 	if (kmfrv != KMF_OK) {
392 		goto cleanup;
393 	}
394 
395 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
396 	    "keypair");
397 
398 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
399 
400 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
401 	    "serial number");
402 
403 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
404 	    "validity time");
405 
406 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
407 	    "signature algorithm");
408 
409 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
410 	    "subject name");
411 
412 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
413 	    "issuer name");
414 
415 	if (altname != NULL)
416 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
417 		    alttype, altname), "subjectAltName");
418 
419 	if (kubits != 0)
420 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
421 		    "KeyUsage");
422 
423 	if (ekulist != NULL) {
424 		int i;
425 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
426 			SET_VALUE(kmf_add_cert_eku(&signedCert,
427 			    &ekulist->ekulist[i],
428 			    ekulist->critlist[i]), "Extended Key Usage");
429 		}
430 	}
431 	/*
432 	 * Construct attributes for the kmf_sign_cert operation.
433 	 */
434 	numattr = 0;
435 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
436 	    &kstype, sizeof (kstype));
437 	numattr++;
438 
439 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
440 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
441 	numattr++;
442 
443 	/* cert data that is to be signed */
444 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
445 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
446 	numattr++;
447 
448 	/* output buffer for the signed cert */
449 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
450 	    &x509DER, sizeof (KMF_DATA));
451 	numattr++;
452 
453 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
454 	    KMF_OK) {
455 		goto cleanup;
456 	}
457 
458 	/*
459 	 * Store the cert in the DB.
460 	 */
461 	numattr = 0;
462 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
463 	    &kstype, sizeof (kstype));
464 	numattr++;
465 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
466 	    &x509DER, sizeof (KMF_DATA));
467 	numattr++;
468 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_FILENAME_ATTR,
469 	    fullcertpath, strlen(fullcertpath));
470 	numattr++;
471 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
472 	    &fmt, sizeof (fmt));
473 	numattr++;
474 
475 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
476 
477 cleanup:
478 	if (fullkeypath != NULL)
479 		free(fullkeypath);
480 	if (fullcertpath != NULL)
481 		free(fullcertpath);
482 
483 	kmf_free_data(&x509DER);
484 	kmf_free_dn(&certSubject);
485 	kmf_free_dn(&certIssuer);
486 	return (kmfrv);
487 }
488 
489 static KMF_RETURN
490 gencert_nss(KMF_HANDLE_T kmfhandle,
491 	char *token, char *subject, char *altname,
492 	KMF_GENERALNAMECHOICES alttype, int altcrit,
493 	char *nickname, char *dir, char *prefix,
494 	KMF_KEY_ALG keyAlg,
495 	KMF_ALGORITHM_INDEX sigAlg,
496 	int keylen, char *trust,
497 	uint32_t ltime, KMF_BIGINT *serial, uint16_t kubits,
498 	int kucrit, KMF_CREDENTIAL *tokencred,
499 	EKU_LIST *ekulist)
500 {
501 	KMF_RETURN kmfrv;
502 	KMF_KEY_HANDLE pubk, prik;
503 	KMF_X509_CERTIFICATE signedCert;
504 	KMF_X509_NAME	certSubject;
505 	KMF_X509_NAME	certIssuer;
506 	KMF_DATA x509DER;
507 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
508 	KMF_ATTRIBUTE attrlist[16];
509 	int numattr = 0;
510 	KMF_KEY_ALG keytype;
511 	uint32_t keylength;
512 
513 	if (token == NULL)
514 		token = DEFAULT_NSS_TOKEN;
515 
516 	kmfrv = configure_nss(kmfhandle, dir, prefix);
517 	if (kmfrv != KMF_OK)
518 		return (kmfrv);
519 
520 	(void) memset(&signedCert, 0, sizeof (signedCert));
521 	(void) memset(&certSubject, 0, sizeof (certSubject));
522 	(void) memset(&certIssuer, 0, sizeof (certIssuer));
523 	(void) memset(&x509DER, 0, sizeof (x509DER));
524 
525 	/* If the subject name cannot be parsed, flag it now and exit */
526 	if (kmf_dn_parser(subject, &certSubject) != KMF_OK) {
527 		cryptoerror(LOG_STDERR,
528 		    gettext("Subject name cannot be parsed.\n"));
529 		return (PK_ERR_USAGE);
530 	}
531 
532 	/* For a self-signed cert, the issuser and subject are the same */
533 	if (kmf_dn_parser(subject, &certIssuer) != KMF_OK) {
534 		cryptoerror(LOG_STDERR,
535 		    gettext("Subject name cannot be parsed.\n"));
536 		return (PK_ERR_USAGE);
537 	}
538 
539 	keylength = keylen; /* bits */
540 	keytype = keyAlg;
541 
542 	kmf_set_attr_at_index(attrlist, numattr,
543 	    KMF_KEYSTORE_TYPE_ATTR, &kstype,
544 	    sizeof (kstype));
545 	numattr++;
546 
547 	kmf_set_attr_at_index(attrlist, numattr,
548 	    KMF_KEYALG_ATTR, &keytype,
549 	    sizeof (keytype));
550 	numattr++;
551 
552 	kmf_set_attr_at_index(attrlist, numattr,
553 	    KMF_KEYLENGTH_ATTR, &keylength,
554 	    sizeof (keylength));
555 	numattr++;
556 
557 	if (nickname != NULL) {
558 		kmf_set_attr_at_index(attrlist, numattr,
559 		    KMF_KEYLABEL_ATTR, nickname,
560 		    strlen(nickname));
561 		numattr++;
562 	}
563 
564 	if (tokencred != NULL && tokencred->cred != NULL) {
565 		kmf_set_attr_at_index(attrlist, numattr,
566 		    KMF_CREDENTIAL_ATTR, tokencred,
567 		    sizeof (KMF_CREDENTIAL));
568 		numattr++;
569 	}
570 
571 	if (token != NULL) {
572 		kmf_set_attr_at_index(attrlist, numattr,
573 		    KMF_TOKEN_LABEL_ATTR, token,
574 		    strlen(token));
575 		numattr++;
576 	}
577 
578 	kmf_set_attr_at_index(attrlist, numattr,
579 	    KMF_PRIVKEY_HANDLE_ATTR, &prik,
580 	    sizeof (KMF_KEY_HANDLE));
581 	numattr++;
582 
583 	kmf_set_attr_at_index(attrlist, numattr,
584 	    KMF_PUBKEY_HANDLE_ATTR, &pubk,
585 	    sizeof (KMF_KEY_HANDLE));
586 	numattr++;
587 
588 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
589 	if (kmfrv != KMF_OK) {
590 		return (kmfrv);
591 	}
592 
593 	SET_VALUE(kmf_set_cert_pubkey(kmfhandle, &pubk, &signedCert),
594 	    "keypair");
595 
596 	SET_VALUE(kmf_set_cert_version(&signedCert, 2), "version number");
597 
598 	SET_VALUE(kmf_set_cert_serial(&signedCert, serial),
599 	    "serial number");
600 
601 	SET_VALUE(kmf_set_cert_validity(&signedCert, NULL, ltime),
602 	    "validity time");
603 
604 	SET_VALUE(kmf_set_cert_sig_alg(&signedCert, sigAlg),
605 	    "signature algorithm");
606 
607 	SET_VALUE(kmf_set_cert_subject(&signedCert, &certSubject),
608 	    "subject name");
609 
610 	SET_VALUE(kmf_set_cert_issuer(&signedCert, &certIssuer),
611 	    "issuer name");
612 
613 	if (altname != NULL)
614 		SET_VALUE(kmf_set_cert_subject_altname(&signedCert, altcrit,
615 		    alttype, altname), "subjectAltName");
616 
617 	if (kubits)
618 		SET_VALUE(kmf_set_cert_ku(&signedCert, kucrit, kubits),
619 		    "subjectAltName");
620 
621 	if (ekulist != NULL) {
622 		int i;
623 		for (i = 0; kmfrv == KMF_OK && i < ekulist->eku_count; i++) {
624 			SET_VALUE(kmf_add_cert_eku(&signedCert,
625 			    &ekulist->ekulist[i],
626 			    ekulist->critlist[i]), "Extended Key Usage");
627 		}
628 	}
629 	/*
630 	 * Construct attributes for the kmf_sign_cert operation.
631 	 */
632 	numattr = 0;
633 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
634 	    &kstype, sizeof (kstype));
635 	numattr++;
636 
637 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
638 	    &prik, sizeof (KMF_KEY_HANDLE_ATTR));
639 	numattr++;
640 
641 	/* cert data that is to be signed */
642 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
643 	    &signedCert, sizeof (KMF_X509_CERTIFICATE));
644 	numattr++;
645 
646 	/* output buffer for the signed cert */
647 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
648 	    &x509DER, sizeof (KMF_DATA));
649 	numattr++;
650 
651 	if ((kmfrv = kmf_sign_cert(kmfhandle, numattr, attrlist)) !=
652 	    KMF_OK) {
653 		goto cleanup;
654 	}
655 
656 	/*
657 	 * Store the cert in the DB.
658 	 */
659 	numattr = 0;
660 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
661 	    &kstype, sizeof (kstype));
662 	numattr++;
663 
664 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
665 	    &x509DER, sizeof (KMF_DATA));
666 	numattr++;
667 
668 	if (nickname != NULL) {
669 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
670 		    nickname, strlen(nickname));
671 		numattr++;
672 	}
673 
674 	if (trust != NULL) {
675 		kmf_set_attr_at_index(attrlist, numattr, KMF_TRUSTFLAG_ATTR,
676 		    trust, strlen(trust));
677 		numattr++;
678 	}
679 
680 	if (token != NULL) {
681 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
682 		    token, strlen(token));
683 		numattr++;
684 	}
685 
686 	kmfrv = kmf_store_cert(kmfhandle, numattr, attrlist);
687 
688 cleanup:
689 	kmf_free_data(&x509DER);
690 	kmf_free_dn(&certSubject);
691 	kmf_free_dn(&certIssuer);
692 	return (kmfrv);
693 }
694 
695 int
696 pk_gencert(int argc, char *argv[])
697 {
698 	int rv;
699 	int opt;
700 	extern int	optind_av;
701 	extern char	*optarg_av;
702 	KMF_KEYSTORE_TYPE kstype = 0;
703 	char *subject = NULL;
704 	char *tokenname = NULL;
705 	char *dir = NULL;
706 	char *prefix = NULL;
707 	char *keytype = PK_DEFAULT_KEYTYPE;
708 	int keylen = PK_DEFAULT_KEYLENGTH;
709 	char *trust = NULL;
710 	char *lifetime = NULL;
711 	char *certlabel = NULL;
712 	char *outcert = NULL;
713 	char *outkey = NULL;
714 	char *format = NULL;
715 	char *serstr = NULL;
716 	char *altname = NULL;
717 	char *keyusagestr = NULL;
718 	char *ekustr = NULL;
719 	KMF_GENERALNAMECHOICES alttype = 0;
720 	KMF_BIGINT serial = { NULL, 0 };
721 	uint32_t ltime;
722 	KMF_HANDLE_T kmfhandle = NULL;
723 	KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1;
724 	KMF_KEY_ALG keyAlg = KMF_RSA;
725 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA;
726 	boolean_t interactive = B_FALSE;
727 	char *subname = NULL;
728 	KMF_CREDENTIAL tokencred = {NULL, 0};
729 	uint16_t kubits = 0;
730 	int altcrit = 0, kucrit = 0;
731 	EKU_LIST *ekulist = NULL;
732 
733 	while ((opt = getopt_av(argc, argv,
734 	    "ik:(keystore)s:(subject)n:(nickname)A:(altname)"
735 	    "T:(token)d:(dir)p:(prefix)t:(keytype)y:(keylen)"
736 	    "r:(trust)L:(lifetime)l:(label)c:(outcert)e:(eku)"
737 	    "K:(outkey)S:(serial)F:(format)u:(keyusage)")) != EOF) {
738 
739 		if (opt != 'i' && EMPTYSTRING(optarg_av))
740 			return (PK_ERR_USAGE);
741 
742 		switch (opt) {
743 			case 'A':
744 				altname = optarg_av;
745 				break;
746 			case 'i':
747 				if (interactive || subject)
748 					return (PK_ERR_USAGE);
749 				else
750 					interactive = B_TRUE;
751 				break;
752 			case 'k':
753 				kstype = KS2Int(optarg_av);
754 				if (kstype == 0)
755 					return (PK_ERR_USAGE);
756 				break;
757 			case 's':
758 				if (interactive || subject)
759 					return (PK_ERR_USAGE);
760 				else
761 					subject = optarg_av;
762 				break;
763 			case 'l':
764 			case 'n':
765 				if (certlabel)
766 					return (PK_ERR_USAGE);
767 				certlabel = optarg_av;
768 				break;
769 			case 'T':
770 				if (tokenname)
771 					return (PK_ERR_USAGE);
772 				tokenname = optarg_av;
773 				break;
774 			case 'd':
775 				if (dir)
776 					return (PK_ERR_USAGE);
777 				dir = optarg_av;
778 				break;
779 			case 'p':
780 				if (prefix)
781 					return (PK_ERR_USAGE);
782 				prefix = optarg_av;
783 				break;
784 			case 't':
785 				keytype = optarg_av;
786 				break;
787 			case 'u':
788 				keyusagestr = optarg_av;
789 				break;
790 			case 'y':
791 				if (sscanf(optarg_av, "%d",
792 				    &keylen) != 1) {
793 					cryptoerror(LOG_STDERR,
794 					    gettext("key length must be"
795 					    "a numeric value (%s)\n"),
796 					    optarg_av);
797 					return (PK_ERR_USAGE);
798 				}
799 				break;
800 			case 'r':
801 				if (trust)
802 					return (PK_ERR_USAGE);
803 				trust = optarg_av;
804 				break;
805 			case 'L':
806 				if (lifetime)
807 					return (PK_ERR_USAGE);
808 				lifetime = optarg_av;
809 				break;
810 			case 'c':
811 				if (outcert)
812 					return (PK_ERR_USAGE);
813 				outcert = optarg_av;
814 				break;
815 			case 'K':
816 				if (outkey)
817 					return (PK_ERR_USAGE);
818 				outkey = optarg_av;
819 				break;
820 			case 'S':
821 				serstr = optarg_av;
822 				break;
823 			case 'F':
824 				if (format)
825 					return (PK_ERR_USAGE);
826 				format = optarg_av;
827 				break;
828 			case 'e':
829 				ekustr = optarg_av;
830 				break;
831 			default:
832 				return (PK_ERR_USAGE);
833 		}
834 	}
835 
836 	/* No additional args allowed. */
837 	argc -= optind_av;
838 	argv += optind_av;
839 	if (argc) {
840 		return (PK_ERR_USAGE);
841 	}
842 
843 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
844 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
845 		return (PK_ERR_USAGE);
846 	}
847 
848 	/* Assume keystore = PKCS#11 if not specified. */
849 	if (kstype == 0)
850 		kstype = KMF_KEYSTORE_PK11TOKEN;
851 
852 	if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN)) {
853 		if (interactive && EMPTYSTRING(certlabel)) {
854 			(void) get_certlabel(&certlabel);
855 		}
856 		/* It better not be empty now */
857 		if (EMPTYSTRING(certlabel)) {
858 			cryptoerror(LOG_STDERR, gettext("A label must be "
859 			    "specified to create a self-signed certificate."
860 			    "\n"));
861 			return (PK_ERR_USAGE);
862 		}
863 	} else if (kstype == KMF_KEYSTORE_OPENSSL && EMPTYSTRING(outcert)) {
864 		cryptoerror(LOG_STDERR, gettext("A certificate filename must "
865 		    "be specified to create a self-signed certificate.\n"));
866 		return (PK_ERR_USAGE);
867 	}
868 
869 	DIR_OPTION_CHECK(kstype, dir);
870 
871 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
872 		cryptoerror(LOG_STDERR,
873 		    gettext("Error parsing format string (%s).\n"),
874 		    format);
875 		return (PK_ERR_USAGE);
876 	}
877 
878 	if (Str2Lifetime(lifetime, &ltime) != 0) {
879 		cryptoerror(LOG_STDERR,
880 		    gettext("Error parsing lifetime string\n"));
881 		return (PK_ERR_USAGE);
882 	}
883 
884 	if (Str2KeyType(keytype, &keyAlg, &sigAlg) != 0) {
885 		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
886 		    keytype);
887 		return (PK_ERR_USAGE);
888 	}
889 
890 	/*
891 	 * Check the subject name.
892 	 * If interactive is true, get it now interactively.
893 	 */
894 	if (interactive) {
895 		subname = NULL;
896 		if (get_subname(&subname) != KMF_OK || subname == NULL) {
897 			cryptoerror(LOG_STDERR, gettext("Failed to get the "
898 			    "subject name interactively.\n"));
899 			return (PK_ERR_USAGE);
900 		}
901 		if (serstr == NULL) {
902 			(void) get_serial(&serstr);
903 		}
904 	} else {
905 		if (EMPTYSTRING(subject)) {
906 			cryptoerror(LOG_STDERR, gettext("A subject name or "
907 			    "-i must be specified to create a self-signed "
908 			    "certificate.\n"));
909 			return (PK_ERR_USAGE);
910 		} else {
911 			subname = strdup(subject);
912 			if (subname == NULL) {
913 				cryptoerror(LOG_STDERR,
914 				    gettext("Out of memory.\n"));
915 				return (PK_ERR_SYSTEM);
916 			}
917 		}
918 	}
919 
920 	if (serstr == NULL) {
921 		(void) fprintf(stderr, gettext("A serial number "
922 		    "must be specified as a hex number when creating"
923 		    " a self-signed certificate "
924 		    "(ex: serial=0x0102030405feedface)\n"));
925 		rv = PK_ERR_USAGE;
926 		goto end;
927 	} else {
928 		uchar_t *bytes = NULL;
929 		size_t bytelen;
930 
931 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
932 		if (rv != KMF_OK || bytes == NULL) {
933 			(void) fprintf(stderr, gettext("serial number "
934 			    "must be specified as a hex number "
935 			    "(ex: 0x0102030405ffeeddee)\n"));
936 			rv = PK_ERR_USAGE;
937 			goto end;
938 		}
939 		serial.val = bytes;
940 		serial.len = bytelen;
941 	}
942 
943 	if (altname != NULL) {
944 		rv = verify_altname(altname, &alttype, &altcrit);
945 		if (rv != KMF_OK) {
946 			(void) fprintf(stderr, gettext("Subject AltName "
947 			    "must be specified as a name=value pair. "
948 			    "See the man page for details.\n"));
949 			rv = PK_ERR_USAGE;
950 			goto end;
951 		} else {
952 			/* advance the altname past the '=' sign */
953 			char *p = strchr(altname, '=');
954 			if (p != NULL)
955 				altname = p + 1;
956 		}
957 	}
958 
959 	if (keyusagestr != NULL) {
960 		rv = verify_keyusage(keyusagestr, &kubits, &kucrit);
961 		if (rv != KMF_OK) {
962 			(void) fprintf(stderr, gettext("KeyUsage "
963 			    "must be specified as a comma-separated list. "
964 			    "See the man page for details.\n"));
965 			rv = PK_ERR_USAGE;
966 			goto end;
967 		}
968 	}
969 	if (ekustr != NULL) {
970 		rv = verify_ekunames(ekustr, &ekulist);
971 		if (rv != KMF_OK) {
972 			(void) fprintf(stderr, gettext("EKUs must "
973 			    "be specified as a comma-separated list. "
974 			    "See the man page for details.\n"));
975 			rv = PK_ERR_USAGE;
976 			goto end;
977 		}
978 	}
979 
980 	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
981 		if (tokenname == NULL || !strlen(tokenname)) {
982 			if (kstype == KMF_KEYSTORE_NSS) {
983 				tokenname = "internal";
984 			} else  {
985 				tokenname = PK_DEFAULT_PK11TOKEN;
986 			}
987 		}
988 
989 		(void) get_token_password(kstype, tokenname, &tokencred);
990 	}
991 
992 	if (kstype == KMF_KEYSTORE_NSS) {
993 		if (dir == NULL)
994 			dir = PK_DEFAULT_DIRECTORY;
995 
996 		rv = gencert_nss(kmfhandle,
997 		    tokenname, subname, altname, alttype, altcrit,
998 		    certlabel, dir, prefix, keyAlg, sigAlg, keylen,
999 		    trust, ltime, &serial, kubits, kucrit, &tokencred,
1000 		    ekulist);
1001 
1002 	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
1003 		rv = gencert_pkcs11(kmfhandle,
1004 		    tokenname, subname, altname, alttype, altcrit,
1005 		    certlabel, keyAlg, sigAlg, keylen, ltime,
1006 		    &serial, kubits, kucrit, &tokencred, ekulist);
1007 
1008 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
1009 		rv = gencert_file(kmfhandle,
1010 		    keyAlg, sigAlg, keylen, fmt,
1011 		    ltime, subname, altname, alttype, altcrit,
1012 		    &serial, kubits, kucrit, outcert, outkey,
1013 		    ekulist);
1014 	}
1015 
1016 	if (rv != KMF_OK)
1017 		display_error(kmfhandle, rv,
1018 		    gettext("Error creating certificate and keypair"));
1019 end:
1020 	if (ekulist != NULL)
1021 		free_eku_list(ekulist);
1022 	if (subname)
1023 		free(subname);
1024 	if (tokencred.cred != NULL)
1025 		free(tokencred.cred);
1026 
1027 	if (serial.val != NULL)
1028 		free(serial.val);
1029 
1030 	(void) kmf_finalize(kmfhandle);
1031 	return (rv);
1032 }
1033