gencert.c revision 5051:cbbb7c8b40a9
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
49static int
50gencert_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
218cleanup:
219	kmf_free_data(&x509DER);
220	kmf_free_dn(&certSubject);
221	kmf_free_dn(&certIssuer);
222	return (kmfrv);
223}
224
225static int
226gencert_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
433cleanup:
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
445static KMF_RETURN
446gencert_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
635cleanup:
636	kmf_free_data(&x509DER);
637	kmf_free_dn(&certSubject);
638	kmf_free_dn(&certIssuer);
639	return (kmfrv);
640}
641
642int
643pk_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	    EMPTYSTRING(certlabel)) {
796		cryptoerror(LOG_STDERR, gettext("A label must be specified "
797		    "to create a self-signed certificate.\n"));
798		return (PK_ERR_USAGE);
799	} else if (kstype == KMF_KEYSTORE_OPENSSL && EMPTYSTRING(outcert)) {
800		cryptoerror(LOG_STDERR, gettext("A certificate filename must "
801		    "be specified to create a self-signed certificate.\n"));
802		return (PK_ERR_USAGE);
803	}
804
805	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
806		cryptoerror(LOG_STDERR,
807		    gettext("Error parsing format string (%s).\n"),
808		    format);
809		return (PK_ERR_USAGE);
810	}
811
812	if (Str2Lifetime(lifetime, &ltime) != 0) {
813		cryptoerror(LOG_STDERR,
814		    gettext("Error parsing lifetime string\n"));
815		return (PK_ERR_USAGE);
816	}
817
818	if (Str2KeyType(keytype, &keyAlg, &sigAlg) != 0) {
819		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"),
820		    keytype);
821		return (PK_ERR_USAGE);
822	}
823
824
825	/*
826	 * Check the subject name.
827	 * If interactive is true, get it now interactively.
828	 */
829	if (interactive) {
830		if (get_subname(&subname) != KMF_OK) {
831			cryptoerror(LOG_STDERR, gettext("Failed to get the "
832			    "subject name interactively.\n"));
833			return (PK_ERR_USAGE);
834		}
835	} else {
836		if (EMPTYSTRING(subject)) {
837			cryptoerror(LOG_STDERR, gettext("A subject name or "
838			    "-i must be specified to create a self-signed "
839			    "certificate.\n"));
840			return (PK_ERR_USAGE);
841		} else {
842			subname = strdup(subject);
843			if (subname == NULL) {
844				cryptoerror(LOG_STDERR,
845				    gettext("Out of memory.\n"));
846				return (PK_ERR_SYSTEM);
847			}
848		}
849	}
850
851	if (serstr == NULL) {
852		(void) fprintf(stderr, gettext("A serial number "
853		    "must be specified as a hex number when creating"
854		    " a self-signed certificate "
855		    "(ex: serial=0x0102030405feedface)\n"));
856		rv = PK_ERR_USAGE;
857		goto end;
858	} else {
859		uchar_t *bytes = NULL;
860		size_t bytelen;
861
862		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
863		if (rv != KMF_OK || bytes == NULL) {
864			(void) fprintf(stderr, gettext("serial number "
865			    "must be specified as a hex number "
866			    "(ex: 0x0102030405ffeeddee)\n"));
867			rv = PK_ERR_USAGE;
868			goto end;
869		}
870		serial.val = bytes;
871		serial.len = bytelen;
872	}
873
874	if (altname != NULL) {
875		rv = verify_altname(altname, &alttype, &altcrit);
876		if (rv != KMF_OK) {
877			(void) fprintf(stderr, gettext("Subject AltName "
878			    "must be specified as a name=value pair. "
879			    "See the man page for details.\n"));
880			rv = PK_ERR_USAGE;
881			goto end;
882		} else {
883			/* advance the altname past the '=' sign */
884			char *p = strchr(altname, '=');
885			if (p != NULL)
886				altname = p + 1;
887		}
888	}
889
890	if (keyusagestr != NULL) {
891		rv = verify_keyusage(keyusagestr, &kubits, &kucrit);
892		if (rv != KMF_OK) {
893			(void) fprintf(stderr, gettext("KeyUsage "
894			    "must be specified as a comma-separated list. "
895			    "See the man page for details.\n"));
896			rv = PK_ERR_USAGE;
897			goto end;
898		}
899	}
900
901	if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) {
902		if (tokenname == NULL || !strlen(tokenname)) {
903			if (kstype == KMF_KEYSTORE_NSS) {
904				tokenname = "internal";
905			} else  {
906				tokenname = PK_DEFAULT_PK11TOKEN;
907			}
908		}
909
910		(void) get_token_password(kstype, tokenname, &tokencred);
911	}
912
913	if (kstype == KMF_KEYSTORE_NSS) {
914		if (dir == NULL)
915			dir = PK_DEFAULT_DIRECTORY;
916
917		rv = gencert_nss(kmfhandle,
918		    tokenname, subname, altname, alttype, altcrit,
919		    certlabel, dir, prefix, keyAlg, sigAlg, keylen,
920		    trust, ltime, &serial, kubits, kucrit, &tokencred);
921
922	} else if (kstype == KMF_KEYSTORE_PK11TOKEN) {
923		rv = gencert_pkcs11(kmfhandle,
924		    tokenname, subname, altname, alttype, altcrit,
925		    certlabel, keyAlg, sigAlg, keylen, ltime,
926		    &serial, kubits, kucrit, &tokencred);
927
928	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
929		rv = gencert_file(kmfhandle,
930		    keyAlg, sigAlg, keylen, fmt,
931		    ltime, subname, altname, alttype, altcrit,
932		    &serial, kubits, kucrit, dir, outcert, outkey);
933	}
934
935	if (rv != KMF_OK)
936		display_error(kmfhandle, rv,
937		    gettext("Error creating certificate and keypair"));
938end:
939	if (subname)
940		free(subname);
941	if (tokencred.cred != NULL)
942		free(tokencred.cred);
943
944	if (serial.val != NULL)
945		free(serial.val);
946
947	(void) kmf_finalize(kmfhandle);
948	return (rv);
949}
950