xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/signcsr.c (revision 12234:cd6642d6b7dd)
16051Swyllys /*
26051Swyllys  * CDDL HEADER START
36051Swyllys  *
46051Swyllys  * The contents of this file are subject to the terms of the
56051Swyllys  * Common Development and Distribution License (the "License").
66051Swyllys  * You may not use this file except in compliance with the License.
76051Swyllys  *
86051Swyllys  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96051Swyllys  * or http://www.opensolaris.org/os/licensing.
106051Swyllys  * See the License for the specific language governing permissions
116051Swyllys  * and limitations under the License.
126051Swyllys  *
136051Swyllys  * When distributing Covered Code, include this CDDL HEADER in each
146051Swyllys  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156051Swyllys  * If applicable, add the following below this CDDL HEADER, with the
166051Swyllys  * fields enclosed by brackets "[]" replaced with your own identifying
176051Swyllys  * information: Portions Copyright [yyyy] [name of copyright owner]
186051Swyllys  *
196051Swyllys  * CDDL HEADER END
208132SWyllys.Ingersoll@Sun.COM  *
21*12234Swyllys.ingersoll@sun.com  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
226051Swyllys  */
236051Swyllys 
246051Swyllys /*
256051Swyllys  * This file implements the sign CSR operation for this tool.
266051Swyllys  */
276051Swyllys 
286051Swyllys #include <stdio.h>
296051Swyllys #include <errno.h>
306051Swyllys #include <string.h>
316051Swyllys #include <cryptoutil.h>
326051Swyllys #include <security/cryptoki.h>
336051Swyllys #include "common.h"
346051Swyllys 
356051Swyllys #include <kmfapi.h>
366669Swyllys #include <kmfapiP.h>
376669Swyllys 
386051Swyllys #define	SET_VALUE(f, s) \
396051Swyllys 	rv = f; \
406051Swyllys 	if (rv != KMF_OK) { \
416051Swyllys 		cryptoerror(LOG_STDERR, \
426051Swyllys 		    gettext("Failed to set %s: 0x%02x\n"), s, rv); \
436051Swyllys 		goto cleanup; \
446051Swyllys 	}
456051Swyllys 
466051Swyllys 
476051Swyllys static int
read_csrdata(KMF_HANDLE_T handle,char * csrfile,KMF_CSR_DATA * csrdata)486051Swyllys read_csrdata(KMF_HANDLE_T handle, char *csrfile, KMF_CSR_DATA *csrdata)
496051Swyllys {
506051Swyllys 	KMF_RETURN rv = KMF_OK;
516051Swyllys 	KMF_ENCODE_FORMAT csrfmt;
526051Swyllys 	KMF_DATA csrfiledata = {NULL, 0};
536051Swyllys 	KMF_DATA rawcsr = {NULL, 0};
546051Swyllys 
556051Swyllys 	rv = kmf_get_file_format(csrfile, &csrfmt);
566051Swyllys 	if (rv != KMF_OK)
576051Swyllys 		return (rv);
586051Swyllys 
596051Swyllys 	rv = kmf_read_input_file(handle, csrfile, &csrfiledata);
606051Swyllys 	if (rv != KMF_OK)
616051Swyllys 		return (rv);
626051Swyllys 
636051Swyllys 	if (csrfmt == KMF_FORMAT_PEM) {
646051Swyllys 		rv = kmf_pem_to_der(csrfiledata.Data, csrfiledata.Length,
656051Swyllys 		    &rawcsr.Data, (int *)&rawcsr.Length);
666051Swyllys 		if (rv != KMF_OK)
676051Swyllys 			return (rv);
686051Swyllys 
696051Swyllys 		kmf_free_data(&csrfiledata);
706051Swyllys 	} else {
716051Swyllys 		rawcsr.Data = csrfiledata.Data;
726051Swyllys 		rawcsr.Length = csrfiledata.Length;
736051Swyllys 	}
746051Swyllys 
756051Swyllys 	rv = kmf_decode_csr(handle, &rawcsr, csrdata);
766051Swyllys 	kmf_free_data(&rawcsr);
776051Swyllys 
786051Swyllys 	return (rv);
796051Swyllys }
806051Swyllys 
816669Swyllys static KMF_RETURN
find_csr_extn(KMF_X509_EXTENSIONS * extnlist,KMF_OID * extoid,KMF_X509_EXTENSION * outextn)826669Swyllys find_csr_extn(KMF_X509_EXTENSIONS *extnlist, KMF_OID *extoid,
836669Swyllys 	KMF_X509_EXTENSION *outextn)
846669Swyllys {
856669Swyllys 	int i, found = 0;
866669Swyllys 	KMF_X509_EXTENSION *eptr;
876669Swyllys 	KMF_RETURN rv = KMF_OK;
886669Swyllys 
896669Swyllys 	(void) memset(outextn, 0, sizeof (KMF_X509_EXTENSION));
906669Swyllys 	for (i = 0; !found && i < extnlist->numberOfExtensions; i++) {
916669Swyllys 		eptr = &extnlist->extensions[i];
926669Swyllys 		if (IsEqualOid(extoid, &eptr->extnId)) {
936669Swyllys 			rv = copy_extension_data(outextn, eptr);
946669Swyllys 			found++;
956669Swyllys 		}
966669Swyllys 	}
976669Swyllys 	if (found == 0 || rv != KMF_OK)
986669Swyllys 		return (1);
996669Swyllys 	else
1006669Swyllys 		return (rv);
1016669Swyllys }
1026669Swyllys 
1036051Swyllys static int
build_cert_from_csr(KMF_CSR_DATA * csrdata,KMF_X509_CERTIFICATE * signedCert,KMF_BIGINT * serial,uint32_t ltime,char * issuer,char * subject,char * altname,KMF_GENERALNAMECHOICES alttype,int altcrit,uint16_t kubits,int kucrit,EKU_LIST * ekulist)1046051Swyllys build_cert_from_csr(KMF_CSR_DATA *csrdata,
1056051Swyllys 	KMF_X509_CERTIFICATE *signedCert,
1066051Swyllys 	KMF_BIGINT *serial,
1076051Swyllys 	uint32_t ltime,
1086051Swyllys 	char *issuer, char *subject,
1096051Swyllys 	char *altname,
1106051Swyllys 	KMF_GENERALNAMECHOICES alttype,
1116051Swyllys 	int altcrit,
1126051Swyllys 	uint16_t kubits,
1136051Swyllys 	int kucrit,
1146051Swyllys 	EKU_LIST *ekulist)
1156051Swyllys {
1166051Swyllys 	KMF_RETURN rv = KMF_OK;
1176051Swyllys 	KMF_X509_NAME issuerDN, subjectDN;
1186051Swyllys 
1196051Swyllys 	/*
1206051Swyllys 	 * If the CSR is ok, now we can generate the final certificate.
1216051Swyllys 	 */
1226051Swyllys 	(void) memset(signedCert, 0, sizeof (KMF_X509_CERTIFICATE));
1236051Swyllys 	(void) memset(&issuerDN, 0, sizeof (issuerDN));
1246051Swyllys 	(void) memset(&subjectDN, 0, sizeof (subjectDN));
1256051Swyllys 
1266051Swyllys 	SET_VALUE(kmf_set_cert_version(signedCert, 2), "version number");
1276051Swyllys 
1286051Swyllys 	SET_VALUE(kmf_set_cert_serial(signedCert, serial), "serial number");
1296051Swyllys 
1306051Swyllys 	SET_VALUE(kmf_set_cert_validity(signedCert, NULL, ltime),
1316051Swyllys 	    "validity time");
1326051Swyllys 
1336051Swyllys 	if (issuer) {
1346051Swyllys 		if (kmf_dn_parser(issuer, &issuerDN) != KMF_OK) {
1356051Swyllys 			cryptoerror(LOG_STDERR,
1366051Swyllys 			    gettext("Issuer name cannot be parsed\n"));
1376051Swyllys 			return (PK_ERR_USAGE);
1386051Swyllys 		}
1396051Swyllys 		SET_VALUE(kmf_set_cert_issuer(signedCert, &issuerDN),
1406051Swyllys 		    "Issuer Name");
1416051Swyllys 	}
1426051Swyllys 	if (subject) {
1436051Swyllys 		if (kmf_dn_parser(subject, &subjectDN) != KMF_OK) {
1446051Swyllys 			cryptoerror(LOG_STDERR,
1456051Swyllys 			    gettext("Subject name cannot be parsed\n"));
1466051Swyllys 			return (PK_ERR_USAGE);
1476051Swyllys 		}
1486051Swyllys 		SET_VALUE(kmf_set_cert_subject(signedCert, &subjectDN),
1496051Swyllys 		    "Subject Name");
1506051Swyllys 	} else {
1516051Swyllys 		signedCert->certificate.subject = csrdata->csr.subject;
1526051Swyllys 	}
1536051Swyllys 
1546051Swyllys 	signedCert->certificate.subjectPublicKeyInfo =
1556051Swyllys 	    csrdata->csr.subjectPublicKeyInfo;
1566051Swyllys 
1576051Swyllys 	signedCert->certificate.extensions = csrdata->csr.extensions;
1586051Swyllys 
1596051Swyllys 	signedCert->certificate.signature =
1606051Swyllys 	    csrdata->signature.algorithmIdentifier;
1616051Swyllys 
1626051Swyllys 	if (kubits != 0) {
1636669Swyllys 		KMF_X509_EXTENSION extn;
1646669Swyllys 		uint16_t oldbits;
1656669Swyllys 		/*
1666669Swyllys 		 * If the CSR already has KU, merge them.
1676669Swyllys 		 */
1686669Swyllys 		rv = find_csr_extn(&csrdata->csr.extensions,
1696669Swyllys 		    (KMF_OID *)&KMFOID_KeyUsage, &extn);
1706669Swyllys 		if (rv == KMF_OK) {
1716669Swyllys 			extn.critical |= kucrit;
1726669Swyllys 			if (extn.value.tagAndValue->value.Length > 1) {
1736669Swyllys 				oldbits =
1746669Swyllys 				    extn.value.tagAndValue->value.Data[1] << 8;
1756669Swyllys 			} else {
1766669Swyllys 				oldbits =
1776669Swyllys 				    extn.value.tagAndValue->value.Data[0];
1786669Swyllys 			}
1796669Swyllys 			oldbits |= kubits;
1806669Swyllys 		} else {
1816669Swyllys 			SET_VALUE(kmf_set_cert_ku(signedCert, kucrit, kubits),
1826669Swyllys 			    "KeyUsage");
1836669Swyllys 		}
1846051Swyllys 	}
1856051Swyllys 	if (altname != NULL) {
1866051Swyllys 		SET_VALUE(kmf_set_cert_subject_altname(signedCert,
1876051Swyllys 		    altcrit, alttype, altname), "subjectAltName");
1886051Swyllys 	}
1896051Swyllys 	if (ekulist != NULL) {
1906051Swyllys 		int i;
1916051Swyllys 		for (i = 0; rv == KMF_OK && i < ekulist->eku_count; i++) {
1926051Swyllys 			SET_VALUE(kmf_add_cert_eku(signedCert,
1936051Swyllys 			    &ekulist->ekulist[i],
1946051Swyllys 			    ekulist->critlist[i]), "Extended Key Usage");
1956051Swyllys 		}
1966051Swyllys 	}
1976051Swyllys cleanup:
1986051Swyllys 	if (issuer != NULL)
1996051Swyllys 		kmf_free_dn(&issuerDN);
2006051Swyllys 	if (subject != NULL)
2016051Swyllys 		kmf_free_dn(&subjectDN);
2026051Swyllys 
2036051Swyllys 	return (rv);
2046051Swyllys }
2056051Swyllys 
2066051Swyllys static int
pk_sign_cert(KMF_HANDLE_T handle,KMF_X509_CERTIFICATE * cert,KMF_KEY_HANDLE * key,KMF_OID * sigoid,KMF_DATA * outdata)2076051Swyllys pk_sign_cert(KMF_HANDLE_T handle, KMF_X509_CERTIFICATE *cert,
208*12234Swyllys.ingersoll@sun.com 	KMF_KEY_HANDLE *key, KMF_OID *sigoid, KMF_DATA *outdata)
2096051Swyllys {
2106051Swyllys 	KMF_RETURN rv;
2116051Swyllys 	int numattr;
2126051Swyllys 	KMF_ATTRIBUTE attrlist[4];
2136051Swyllys 
2146051Swyllys 	numattr = 0;
215*12234Swyllys.ingersoll@sun.com 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR,
2166051Swyllys 	    &key->kstype, sizeof (KMF_KEYSTORE_TYPE));
2176051Swyllys 
218*12234Swyllys.ingersoll@sun.com 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_HANDLE_ATTR,
2196051Swyllys 	    key, sizeof (KMF_KEY_HANDLE_ATTR));
2206051Swyllys 
2216051Swyllys 	/* cert data that is to be signed */
222*12234Swyllys.ingersoll@sun.com 	kmf_set_attr_at_index(attrlist, numattr++, KMF_X509_CERTIFICATE_ATTR,
2236051Swyllys 	    cert, sizeof (KMF_X509_CERTIFICATE));
2246051Swyllys 
2256051Swyllys 	/* output buffer for the signed cert */
226*12234Swyllys.ingersoll@sun.com 	kmf_set_attr_at_index(attrlist, numattr++, KMF_CERT_DATA_ATTR,
2276051Swyllys 	    outdata, sizeof (KMF_DATA));
228*12234Swyllys.ingersoll@sun.com 
229*12234Swyllys.ingersoll@sun.com 	/* Set the signature OID value so KMF knows how to generate the sig */
230*12234Swyllys.ingersoll@sun.com 	if (sigoid) {
231*12234Swyllys.ingersoll@sun.com 		kmf_set_attr_at_index(attrlist, numattr++, KMF_OID_ATTR,
232*12234Swyllys.ingersoll@sun.com 		    sigoid, sizeof (KMF_OID));
233*12234Swyllys.ingersoll@sun.com 	}
2346051Swyllys 
2356051Swyllys 	if ((rv = kmf_sign_cert(handle, numattr, attrlist)) != KMF_OK) {
2366051Swyllys 		cryptoerror(LOG_STDERR,
2376051Swyllys 		    gettext("Failed to sign certificate.\n"));
2386051Swyllys 		return (rv);
2396051Swyllys 	}
2406051Swyllys 
2416051Swyllys 	return (rv);
2426051Swyllys }
2436051Swyllys 
2446051Swyllys static int
pk_signcsr_files(KMF_HANDLE_T handle,char * signkey,char * csrfile,KMF_BIGINT * serial,char * certfile,char * issuer,char * subject,char * altname,KMF_GENERALNAMECHOICES alttype,int altcrit,uint16_t kubits,int kucrit,EKU_LIST * ekulist,uint32_t ltime,KMF_ENCODE_FORMAT fmt)2456051Swyllys pk_signcsr_files(KMF_HANDLE_T handle,
2466051Swyllys 	char *signkey,
2476051Swyllys 	char *csrfile,
2486051Swyllys 	KMF_BIGINT *serial,
2496051Swyllys 	char *certfile,
2506051Swyllys 	char *issuer,
2516051Swyllys 	char *subject,
2526051Swyllys 	char *altname,
2536051Swyllys 	KMF_GENERALNAMECHOICES alttype,
2546051Swyllys 	int altcrit,
2556051Swyllys 	uint16_t kubits,
2566051Swyllys 	int kucrit,
2576051Swyllys 	EKU_LIST *ekulist,
2586051Swyllys 	uint32_t ltime,
2596051Swyllys 	KMF_ENCODE_FORMAT fmt)
2606051Swyllys {
2616051Swyllys 	KMF_RETURN rv = KMF_OK;
2626051Swyllys 	KMF_CSR_DATA csrdata;
2636051Swyllys 	KMF_ATTRIBUTE attrlist[16];
2646051Swyllys 	KMF_X509_CERTIFICATE signedCert;
2656051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
2666051Swyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
2676051Swyllys 	KMF_KEY_HANDLE cakey;
2686051Swyllys 	KMF_DATA certdata = {NULL, 0};
2696051Swyllys 	int numattr, count;
2706051Swyllys 
27111973Swyllys.ingersoll@sun.com 	(void) memset(&cakey, 0, sizeof (cakey));
27211973Swyllys.ingersoll@sun.com 	(void) memset(&signedCert, 0, sizeof (signedCert));
27311973Swyllys.ingersoll@sun.com 
2746051Swyllys 	rv = read_csrdata(handle, csrfile, &csrdata);
2756051Swyllys 	if (rv != KMF_OK) {
2766051Swyllys 		cryptoerror(LOG_STDERR,
2776051Swyllys 		    gettext("Error reading CSR data\n"));
2786051Swyllys 		return (rv);
2796051Swyllys 	}
2806051Swyllys 
2816051Swyllys 	/* verify the signature first */
2826051Swyllys 	numattr = 0;
2836051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CSR_DATA_ATTR,
2846051Swyllys 	    &csrdata, sizeof (csrdata));
2856051Swyllys 	numattr++;
2866051Swyllys 
2876051Swyllys 	rv = kmf_verify_csr(handle, numattr, attrlist);
2886051Swyllys 	if (rv != KMF_OK) {
2896051Swyllys 		cryptoerror(LOG_STDERR, gettext("CSR signature "
2906051Swyllys 		    "verification failed.\n"));
2916051Swyllys 		goto cleanup;
2926051Swyllys 	}
2936051Swyllys 
2946051Swyllys 	rv = build_cert_from_csr(&csrdata, &signedCert, serial, ltime,
2956051Swyllys 	    issuer, subject, altname, alttype, altcrit, kubits,
2966051Swyllys 	    kucrit, ekulist);
2976051Swyllys 
2986051Swyllys 	if (rv != KMF_OK)
2996051Swyllys 		goto cleanup;
3006051Swyllys 
3016051Swyllys 	/*
3026051Swyllys 	 * Find the signing key.
3036051Swyllys 	 */
3046051Swyllys 	(void) memset(&cakey, 0, sizeof (cakey));
3056051Swyllys 
3066051Swyllys 	numattr = 0;
3076051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
3086051Swyllys 	    &kstype, sizeof (kstype));
3096051Swyllys 	numattr++;
3106051Swyllys 
3116051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
3126051Swyllys 	    signkey, strlen(signkey));
3136051Swyllys 	numattr++;
3146051Swyllys 
3156051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
3166051Swyllys 	    &keyclass, sizeof (keyclass));
3176051Swyllys 	numattr++;
3186051Swyllys 
3196051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
3206051Swyllys 	    &cakey, sizeof (cakey));
3216051Swyllys 	numattr++;
3226051Swyllys 
3236051Swyllys 	count = 1;
3246051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
3256051Swyllys 	    &count, sizeof (count));
3266051Swyllys 	numattr++;
3276051Swyllys 
3286051Swyllys 	rv = kmf_find_key(handle, numattr, attrlist);
3296051Swyllys 	if (rv != KMF_OK) {
3306051Swyllys 		cryptoerror(LOG_STDERR, gettext(
3316051Swyllys 		    "Error finding CA signing key\n"));
3326051Swyllys 		goto cleanup;
3336051Swyllys 	}
3346051Swyllys 
335*12234Swyllys.ingersoll@sun.com 	rv = pk_sign_cert(handle, &signedCert, &cakey, NULL, &certdata);
3366051Swyllys 	if (rv != KMF_OK) {
3376051Swyllys 		cryptoerror(LOG_STDERR, gettext(
3386051Swyllys 		    "Error signing certificate.\n"));
3396051Swyllys 		goto cleanup;
3406051Swyllys 	}
3416051Swyllys 
3426051Swyllys 	rv = kmf_create_cert_file(&certdata, fmt, certfile);
3436051Swyllys 
3446051Swyllys cleanup:
3456051Swyllys 	kmf_free_signed_csr(&csrdata);
3466051Swyllys 	kmf_free_data(&certdata);
3476051Swyllys 	kmf_free_kmf_key(handle, &cakey);
3486051Swyllys 	return (rv);
3496051Swyllys }
3506051Swyllys 
3516051Swyllys static int
pk_signcsr_pk11_nss(KMF_HANDLE_T handle,KMF_KEYSTORE_TYPE kstype,char * dir,char * prefix,char * token,KMF_CREDENTIAL * cred,char * signkey,char * csrfile,KMF_BIGINT * serial,char * certfile,char * issuer,char * subject,char * altname,KMF_GENERALNAMECHOICES alttype,int altcrit,uint16_t kubits,int kucrit,EKU_LIST * ekulist,uint32_t ltime,KMF_ENCODE_FORMAT fmt,int store,char * outlabel)3526051Swyllys pk_signcsr_pk11_nss(KMF_HANDLE_T handle,
3536051Swyllys 	KMF_KEYSTORE_TYPE kstype,
3546051Swyllys 	char *dir, char *prefix,
3556051Swyllys 	char *token, KMF_CREDENTIAL *cred,
3566051Swyllys 	char *signkey, char *csrfile,
3576051Swyllys 	KMF_BIGINT *serial, char *certfile, char *issuer, char *subject,
3586051Swyllys 	char *altname, KMF_GENERALNAMECHOICES alttype, int altcrit,
3596051Swyllys 	uint16_t kubits, int kucrit,
3606051Swyllys 	EKU_LIST *ekulist, uint32_t ltime,
3616051Swyllys 	KMF_ENCODE_FORMAT fmt, int store, char *outlabel)
3626051Swyllys {
3636051Swyllys 	KMF_RETURN rv = KMF_OK;
3646051Swyllys 	KMF_DATA outcert = {NULL, 0};
365*12234Swyllys.ingersoll@sun.com 	KMF_CSR_DATA csrdata = {NULL, 0};
3666051Swyllys 	KMF_KEY_HANDLE casignkey;
3676051Swyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
3686051Swyllys 	KMF_ATTRIBUTE attrlist[16];
3696051Swyllys 	KMF_X509_CERTIFICATE signedCert;
3706051Swyllys 	boolean_t token_bool = B_TRUE;
3716051Swyllys 	boolean_t private_bool = B_TRUE;
372*12234Swyllys.ingersoll@sun.com 	int numattr = 0;
373*12234Swyllys.ingersoll@sun.com 	int keys = 1;
3746051Swyllys 
3758132SWyllys.Ingersoll@Sun.COM 	(void) memset(&casignkey, 0, sizeof (KMF_KEY_HANDLE));
37611973Swyllys.ingersoll@sun.com 	(void) memset(&signedCert, 0, sizeof (signedCert));
3778132SWyllys.Ingersoll@Sun.COM 
3786051Swyllys 	rv = read_csrdata(handle, csrfile, &csrdata);
3796051Swyllys 	if (rv != KMF_OK) {
3806051Swyllys 		cryptoerror(LOG_STDERR,
3816051Swyllys 		    gettext("Error reading CSR data\n"));
3826051Swyllys 		return (rv);
3836051Swyllys 	}
3846051Swyllys 
3856051Swyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
3866051Swyllys 		rv = select_token(handle, token, FALSE);
3876051Swyllys 	} else if (kstype == KMF_KEYSTORE_NSS) {
3886051Swyllys 		rv = configure_nss(handle, dir, prefix);
3896051Swyllys 	}
3906051Swyllys 
3916051Swyllys 	/* verify the signature first */
3926051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CSR_DATA_ATTR,
3936051Swyllys 	    &csrdata, sizeof (csrdata));
3946051Swyllys 	numattr++;
3956051Swyllys 
3966051Swyllys 	rv = kmf_verify_csr(handle, numattr, attrlist);
3976051Swyllys 	if (rv != KMF_OK) {
3986051Swyllys 		cryptoerror(LOG_STDERR, gettext("CSR signature "
3996051Swyllys 		    "verification failed.\n"));
4006051Swyllys 		goto cleanup;
4016051Swyllys 	}
4026051Swyllys 
4036051Swyllys 	rv = build_cert_from_csr(&csrdata,
4046051Swyllys 	    &signedCert, serial, ltime,
4056051Swyllys 	    issuer, subject, altname,
4066051Swyllys 	    alttype, altcrit, kubits,
4076051Swyllys 	    kucrit, ekulist);
4086051Swyllys 
4096051Swyllys 	if (rv != KMF_OK)
4106051Swyllys 		goto cleanup;
4116051Swyllys 
4126051Swyllys 	/*
4136051Swyllys 	 * Find the signing key.
4146051Swyllys 	 */
4156051Swyllys 	numattr = 0;
4166051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
4176051Swyllys 	    &kstype, sizeof (kstype));
4186051Swyllys 	numattr++;
4196051Swyllys 	if (kstype == KMF_KEYSTORE_NSS) {
4206051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
4216051Swyllys 		    token, strlen(token));
4226051Swyllys 		numattr++;
4236051Swyllys 	}
4246051Swyllys 
4256051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR, signkey,
4266051Swyllys 	    strlen(signkey));
4276051Swyllys 	numattr++;
4286051Swyllys 
4296051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVATE_BOOL_ATTR,
4306051Swyllys 	    &private_bool, sizeof (private_bool));
4316051Swyllys 	numattr++;
4326051Swyllys 
4336051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
4346051Swyllys 	    &token_bool, sizeof (token_bool));
4356051Swyllys 	numattr++;
4366051Swyllys 
4376051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
4386051Swyllys 	    &keyclass, sizeof (keyclass));
4396051Swyllys 	numattr++;
4406051Swyllys 
4416051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
4426051Swyllys 	    cred, sizeof (KMF_CREDENTIAL_ATTR));
4436051Swyllys 	numattr++;
4446051Swyllys 
4456051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
4466051Swyllys 	    &keys, sizeof (keys));
4476051Swyllys 	numattr++;
4486051Swyllys 
4496051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
4506051Swyllys 	    &casignkey, sizeof (casignkey));
4516051Swyllys 	numattr++;
4526051Swyllys 
4536051Swyllys 	rv = kmf_find_key(handle, numattr, attrlist);
4546051Swyllys 	if (rv != KMF_OK) {
4556051Swyllys 		cryptoerror(LOG_STDERR,
4566051Swyllys 		    gettext("Failed to find signing key\n"));
4576051Swyllys 		goto cleanup;
4586051Swyllys 	}
4596051Swyllys 	/*
4606051Swyllys 	 * If we found the key, now we can sign the cert.
4616051Swyllys 	 */
462*12234Swyllys.ingersoll@sun.com 	rv = pk_sign_cert(handle, &signedCert, &casignkey, NULL,
463*12234Swyllys.ingersoll@sun.com 	    &outcert);
4646051Swyllys 	if (rv != KMF_OK) {
4656051Swyllys 		cryptoerror(LOG_STDERR, gettext(
4666051Swyllys 		    "Error signing certificate.\n"));
4676051Swyllys 		goto cleanup;
4686051Swyllys 	}
4696051Swyllys 
4706051Swyllys 	/*
4716051Swyllys 	 * Store it on the token if the user asked for it.
4726051Swyllys 	 */
4736051Swyllys 	if (store) {
4746051Swyllys 		numattr = 0;
4756051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
4766051Swyllys 		    &kstype, sizeof (kstype));
4776051Swyllys 		numattr++;
4786051Swyllys 
4796051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
4806051Swyllys 		    &outcert, sizeof (KMF_DATA));
4816051Swyllys 		numattr++;
4826051Swyllys 
4836051Swyllys 		if (outlabel != NULL) {
4846051Swyllys 			kmf_set_attr_at_index(attrlist, numattr,
4856051Swyllys 			    KMF_CERT_LABEL_ATTR,
4866051Swyllys 			    outlabel, strlen(outlabel));
4876051Swyllys 			numattr++;
4886051Swyllys 		}
4896051Swyllys 
4906051Swyllys 		if (kstype == KMF_KEYSTORE_NSS) {
4916051Swyllys 			if (token != NULL)
4926051Swyllys 				kmf_set_attr_at_index(attrlist, numattr,
4936051Swyllys 				    KMF_TOKEN_LABEL_ATTR,
4946051Swyllys 				    token, strlen(token));
4956051Swyllys 			numattr++;
4966051Swyllys 		}
4976051Swyllys 
4986051Swyllys 		rv = kmf_store_cert(handle, numattr, attrlist);
4996051Swyllys 		if (rv != KMF_OK) {
5006051Swyllys 			display_error(handle, rv,
5016051Swyllys 			    gettext("Failed to store cert "
5026051Swyllys 			    "on PKCS#11 token.\n"));
5036051Swyllys 			rv = KMF_OK;
5046051Swyllys 			/* Not fatal, we can still write it to a file. */
5056051Swyllys 		}
5066051Swyllys 	}
5076051Swyllys 	rv = kmf_create_cert_file(&outcert, fmt, certfile);
5086051Swyllys 
5096051Swyllys cleanup:
5106051Swyllys 	kmf_free_signed_csr(&csrdata);
5116051Swyllys 	kmf_free_data(&outcert);
5126051Swyllys 	kmf_free_kmf_key(handle, &casignkey);
5136051Swyllys 
5146051Swyllys 	return (rv);
5156051Swyllys }
5166051Swyllys 
5176051Swyllys /*
5186051Swyllys  * sign a CSR and generate an x509v3 certificate file.
5196051Swyllys  */
5206051Swyllys int
pk_signcsr(int argc,char * argv[])5216051Swyllys pk_signcsr(int argc, char *argv[])
5226051Swyllys {
5236051Swyllys 	int			opt;
5246051Swyllys 	extern int		optind_av;
5256051Swyllys 	extern char		*optarg_av;
5266051Swyllys 	char			*token_spec = NULL;
5276051Swyllys 	char			*subject = NULL;
5286051Swyllys 	char			*issuer = NULL;
5296051Swyllys 	char			*dir = NULL;
5306051Swyllys 	char			*prefix = NULL;
5316051Swyllys 	char			*csrfile = NULL;
5326051Swyllys 	char			*serstr = NULL;
5336051Swyllys 	char			*ekustr = NULL;
5346051Swyllys 	char			*kustr = NULL;
5356051Swyllys 	char			*format = NULL;
5366051Swyllys 	char			*storestr = NULL;
5376051Swyllys 	char			*altname = NULL;
5386051Swyllys 	char			*certfile = NULL;
5396051Swyllys 	char			*lifetime = NULL;
5406051Swyllys 	char			*signkey = NULL;
5416051Swyllys 	char			*outlabel = NULL;
5426051Swyllys 	uint32_t		ltime = 365 * 24 * 60 * 60; /* 1 Year */
5436051Swyllys 	int			store = 0;
5446051Swyllys 	uint16_t		kubits = 0;
5456051Swyllys 	int			altcrit = 0, kucrit = 0;
5466051Swyllys 	KMF_BIGINT		serial = { NULL, 0 };
5476051Swyllys 	EKU_LIST		*ekulist = NULL;
5486051Swyllys 	KMF_KEYSTORE_TYPE	kstype = 0;
5496051Swyllys 	KMF_RETURN		rv = KMF_OK;
5506051Swyllys 	KMF_HANDLE_T		kmfhandle = NULL;
5516051Swyllys 	KMF_CREDENTIAL		tokencred = {NULL, 0};
5526051Swyllys 	KMF_GENERALNAMECHOICES	alttype = 0;
5536051Swyllys 	KMF_ENCODE_FORMAT	fmt = KMF_FORMAT_PEM;
5546051Swyllys 
5556051Swyllys 	/* Parse command line options.  Do NOT i18n/l10n. */
5566051Swyllys 	while ((opt = getopt_av(argc, argv,
5576051Swyllys 	    "k:(keystore)c:(csr)T:(token)d:(dir)"
5586051Swyllys 	    "p:(prefix)S:(serial)s:(subject)a:(altname)"
5596051Swyllys 	    "t:(store)F:(format)K:(keyusage)l:(signkey)"
5606051Swyllys 	    "L:(lifetime)e:(eku)i:(issuer)"
5616051Swyllys 	    "n:(outlabel)o:(outcert)")) != EOF) {
5626051Swyllys 		if (EMPTYSTRING(optarg_av))
5636051Swyllys 			return (PK_ERR_USAGE);
5646051Swyllys 		switch (opt) {
5656051Swyllys 			case 'k':
5666051Swyllys 				if (kstype != 0)
5676051Swyllys 					return (PK_ERR_USAGE);
5686051Swyllys 				kstype = KS2Int(optarg_av);
5696051Swyllys 				if (kstype == 0)
5706051Swyllys 					return (PK_ERR_USAGE);
5716051Swyllys 				break;
5726051Swyllys 			case 't':
5736051Swyllys 				if (storestr != NULL)
5746051Swyllys 					return (PK_ERR_USAGE);
5756051Swyllys 				storestr = optarg_av;
5766051Swyllys 				store = yn_to_int(optarg_av);
5776051Swyllys 				if (store == -1)
5786051Swyllys 					return (PK_ERR_USAGE);
5796051Swyllys 				break;
5806051Swyllys 			case 'a':
5816051Swyllys 				if (altname)
5826051Swyllys 					return (PK_ERR_USAGE);
5836051Swyllys 				altname = optarg_av;
5846051Swyllys 				break;
5856051Swyllys 			case 's':
5866051Swyllys 				if (subject)
5876051Swyllys 					return (PK_ERR_USAGE);
5886051Swyllys 				subject = optarg_av;
5896051Swyllys 				break;
5906051Swyllys 			case 'i':
5916051Swyllys 				if (issuer)
5926051Swyllys 					return (PK_ERR_USAGE);
5936051Swyllys 				issuer = optarg_av;
5946051Swyllys 				break;
5956051Swyllys 			case 'd':
5966051Swyllys 				if (dir)
5976051Swyllys 					return (PK_ERR_USAGE);
5986051Swyllys 				dir = optarg_av;
5996051Swyllys 				break;
6006051Swyllys 			case 'p':
6016051Swyllys 				if (prefix)
6026051Swyllys 					return (PK_ERR_USAGE);
6036051Swyllys 				prefix = optarg_av;
6046051Swyllys 				break;
6056051Swyllys 			case 'S':
6066051Swyllys 				if (serstr != NULL)
6076051Swyllys 					return (PK_ERR_USAGE);
6086051Swyllys 				serstr = optarg_av;
6096051Swyllys 				break;
6106051Swyllys 			case 'c':
6116051Swyllys 				if (csrfile)
6126051Swyllys 					return (PK_ERR_USAGE);
6136051Swyllys 				csrfile = optarg_av;
6146051Swyllys 				break;
6156051Swyllys 			case 'T':	/* token specifier */
6166051Swyllys 				if (token_spec)
6176051Swyllys 					return (PK_ERR_USAGE);
6186051Swyllys 				token_spec = optarg_av;
6196051Swyllys 				break;
6206051Swyllys 			case 'l':	/* object with specific label */
6216051Swyllys 				if (signkey)
6226051Swyllys 					return (PK_ERR_USAGE);
6236051Swyllys 				signkey = optarg_av;
6246051Swyllys 				break;
6256051Swyllys 			case 'e':
6266051Swyllys 				if (ekustr != NULL)
6276051Swyllys 					return (PK_ERR_USAGE);
6286051Swyllys 				ekustr = optarg_av;
6296051Swyllys 				break;
6306051Swyllys 			case 'K':
6316051Swyllys 				if (kustr != NULL)
6326051Swyllys 					return (PK_ERR_USAGE);
6336051Swyllys 				kustr = optarg_av;
6346051Swyllys 				break;
6356051Swyllys 			case 'F':
6366051Swyllys 				if (format != NULL)
6376051Swyllys 					return (PK_ERR_USAGE);
6386051Swyllys 				format = optarg_av;
6396051Swyllys 				break;
6406051Swyllys 			case 'o':
6416051Swyllys 				if (certfile != NULL)
6426051Swyllys 					return (PK_ERR_USAGE);
6436051Swyllys 				certfile = optarg_av;
6446051Swyllys 				break;
6456051Swyllys 			case 'L':
6466051Swyllys 				if (lifetime != NULL)
6476051Swyllys 					return (PK_ERR_USAGE);
6486051Swyllys 				lifetime = optarg_av;
6496051Swyllys 				break;
6506051Swyllys 			case 'n':
6516051Swyllys 				if (outlabel != NULL)
6526051Swyllys 					return (PK_ERR_USAGE);
6536051Swyllys 				outlabel = optarg_av;
6546051Swyllys 				break;
6556051Swyllys 			default:
6566051Swyllys 				return (PK_ERR_USAGE);
6576051Swyllys 		}
6586051Swyllys 	}
6596051Swyllys 	/* No additional args allowed. */
6606051Swyllys 	argc -= optind_av;
6616051Swyllys 	argv += optind_av;
6626051Swyllys 	if (argc)
6636051Swyllys 		return (PK_ERR_USAGE);
6646051Swyllys 
6656051Swyllys 
6666051Swyllys 	/* Assume keystore = PKCS#11 if not specified. */
6676051Swyllys 	if (kstype == 0)
6686051Swyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
6696051Swyllys 
6706884Swyllys 	DIR_OPTION_CHECK(kstype, dir);
6716884Swyllys 
6726051Swyllys 	if (signkey == NULL) {
6736051Swyllys 		(void) fprintf(stderr, gettext("The signing key label "
6746051Swyllys 		    "or filename was not specified\n"));
6756051Swyllys 		return (PK_ERR_USAGE);
6766051Swyllys 	}
6776051Swyllys 	if (csrfile == NULL) {
6786051Swyllys 		(void) fprintf(stderr, gettext("The CSR filename was not"
6796051Swyllys 		    " specified\n"));
6806051Swyllys 		return (PK_ERR_USAGE);
6816051Swyllys 	}
6826051Swyllys 	if (certfile == NULL) {
6836051Swyllys 		(void) fprintf(stderr, gettext("The output certificate file "
6846051Swyllys 		    "was not specified\n"));
6856051Swyllys 		return (PK_ERR_USAGE);
6866051Swyllys 	}
6876051Swyllys 	if (issuer == NULL) {
6886051Swyllys 		(void) fprintf(stderr, gettext("The issuer DN "
6896051Swyllys 		    "was not specified\n"));
6906051Swyllys 		return (PK_ERR_USAGE);
6916051Swyllys 	}
6926051Swyllys 	if (lifetime != NULL) {
6936051Swyllys 		if (Str2Lifetime(lifetime, &ltime) != 0) {
6946051Swyllys 			cryptoerror(LOG_STDERR,
6956051Swyllys 			    gettext("Error parsing lifetime string\n"));
6966051Swyllys 			return (PK_ERR_USAGE);
6976051Swyllys 		}
6986051Swyllys 	}
6996051Swyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) {
7006051Swyllys 		token_spec = PK_DEFAULT_PK11TOKEN;
7016051Swyllys 	} else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) {
7026051Swyllys 		token_spec = DEFAULT_NSS_TOKEN;
7036051Swyllys 	}
7046051Swyllys 
7056051Swyllys 	if (serstr != NULL) {
7066051Swyllys 		uchar_t *bytes = NULL;
7076051Swyllys 		size_t bytelen;
7086051Swyllys 
7096051Swyllys 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
7106051Swyllys 		if (rv != KMF_OK || bytes == NULL) {
7116051Swyllys 			(void) fprintf(stderr, gettext("Serial number "
7126051Swyllys 			    "must be specified as a hex number "
7136051Swyllys 			    "(ex: 0x0102030405ffeeddee)\n"));
7146051Swyllys 			return (PK_ERR_USAGE);
7156051Swyllys 		}
7166051Swyllys 		serial.val = bytes;
7176051Swyllys 		serial.len = bytelen;
7186051Swyllys 	} else {
7196051Swyllys 		(void) fprintf(stderr, gettext("The serial number was not"
7206051Swyllys 		    " specified\n"));
7216051Swyllys 		return (PK_ERR_USAGE);
7226051Swyllys 	}
7236051Swyllys 
7246051Swyllys 	if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
7256051Swyllys 	    kstype == KMF_KEYSTORE_NSS)) {
7266051Swyllys 		/* Need to get password for private key access */
7276051Swyllys 		(void) get_token_password(kstype, token_spec,
7286051Swyllys 		    &tokencred);
7296051Swyllys 	}
7306669Swyllys 	if (kustr != NULL) {
7316669Swyllys 		rv = verify_keyusage(kustr, &kubits, &kucrit);
7326669Swyllys 		if (rv != KMF_OK) {
7336669Swyllys 			(void) fprintf(stderr, gettext("KeyUsage "
7346669Swyllys 			    "must be specified as a comma-separated list. "
7356669Swyllys 			    "See the man page for details.\n"));
7366669Swyllys 			rv = PK_ERR_USAGE;
7376669Swyllys 			goto end;
7386669Swyllys 		}
7396669Swyllys 	}
7406051Swyllys 	if (ekustr != NULL) {
7416051Swyllys 		rv = verify_ekunames(ekustr, &ekulist);
7426051Swyllys 		if (rv != KMF_OK) {
7436051Swyllys 			(void) fprintf(stderr, gettext("EKUs must "
7446051Swyllys 			    "be specified as a comma-separated list. "
7456051Swyllys 			    "See the man page for details.\n"));
7466051Swyllys 			rv = PK_ERR_USAGE;
7476051Swyllys 			goto end;
7486051Swyllys 		}
7496051Swyllys 	}
7506051Swyllys 	if (altname != NULL) {
7516051Swyllys 		char *p;
7526051Swyllys 		rv = verify_altname(altname, &alttype, &altcrit);
7536051Swyllys 		if (rv != KMF_OK) {
7546051Swyllys 			(void) fprintf(stderr, gettext("Subject AltName "
7556051Swyllys 			    "must be specified as a name=value pair. "
7566051Swyllys 			    "See the man page for details.\n"));
7576051Swyllys 			rv = PK_ERR_USAGE;
7586051Swyllys 			goto end;
7596051Swyllys 		}
7606051Swyllys 		/* advance the altname past the '=' sign */
7616051Swyllys 		p = strchr(altname, '=');
7626051Swyllys 		if (p != NULL)
7636051Swyllys 			altname = p + 1;
7646051Swyllys 	}
7656051Swyllys 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
7666051Swyllys 		cryptoerror(LOG_STDERR,
7676051Swyllys 		    gettext("Error parsing format string (%s).\n"),
7686051Swyllys 		    format);
7696051Swyllys 		return (PK_ERR_USAGE);
7706051Swyllys 	}
7716051Swyllys 
7726884Swyllys 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
7736884Swyllys 		return (rv);
7746884Swyllys 	}
7756884Swyllys 
7766051Swyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
7776051Swyllys 		rv = pk_signcsr_pk11_nss(kmfhandle,
7786051Swyllys 		    kstype, dir, prefix, token_spec, &tokencred,
7796051Swyllys 		    signkey, csrfile, &serial, certfile, issuer, subject,
7806051Swyllys 		    altname, alttype, altcrit, kubits, kucrit,
7816051Swyllys 		    ekulist, ltime, fmt, store, outlabel);
7826051Swyllys 
7836051Swyllys 	} else if (kstype == KMF_KEYSTORE_NSS) {
7846051Swyllys 		if (dir == NULL)
7856051Swyllys 			dir = PK_DEFAULT_DIRECTORY;
7866051Swyllys 
7876051Swyllys 		rv = pk_signcsr_pk11_nss(kmfhandle,
7886051Swyllys 		    kstype, dir, prefix, token_spec, &tokencred,
7896051Swyllys 		    signkey, csrfile, &serial, certfile, issuer, subject,
7906051Swyllys 		    altname, alttype, altcrit, kubits, kucrit,
7916051Swyllys 		    ekulist, ltime, fmt, store, outlabel);
7926051Swyllys 
7936051Swyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
7946051Swyllys 		rv = pk_signcsr_files(kmfhandle,
7956051Swyllys 		    signkey, csrfile, &serial, certfile, issuer, subject,
7966051Swyllys 		    altname, alttype, altcrit, kubits, kucrit,
7976051Swyllys 		    ekulist, ltime, fmt);
7986051Swyllys 	}
7996051Swyllys 
8006051Swyllys end:
8016051Swyllys 	if (rv != KMF_OK) {
8026051Swyllys 		display_error(kmfhandle, rv,
8036051Swyllys 		    gettext("Error listing objects"));
8046051Swyllys 	}
8056051Swyllys 
8066051Swyllys 	if (serial.val != NULL)
8076051Swyllys 		free(serial.val);
8086051Swyllys 
8096051Swyllys 	if (tokencred.cred != NULL)
8106051Swyllys 		free(tokencred.cred);
8116051Swyllys 
8126051Swyllys 	free_eku_list(ekulist);
8136051Swyllys 
8146051Swyllys 	(void) kmf_finalize(kmfhandle);
8156051Swyllys 	return (rv);
8166051Swyllys }
817