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