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, <ime) != 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