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