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 * 218132SWyllys.Ingersoll@Sun.COM * 22*11973Swyllys.ingersoll@sun.com * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 236051Swyllys * Use is subject to license terms. 246051Swyllys */ 256051Swyllys 266051Swyllys /* 276051Swyllys * This file implements the sign CSR operation for this tool. 286051Swyllys */ 296051Swyllys 306051Swyllys #include <stdio.h> 316051Swyllys #include <errno.h> 326051Swyllys #include <string.h> 336051Swyllys #include <cryptoutil.h> 346051Swyllys #include <security/cryptoki.h> 356051Swyllys #include "common.h" 366051Swyllys 376051Swyllys #include <kmfapi.h> 386669Swyllys #include <kmfapiP.h> 396669Swyllys 406051Swyllys #define SET_VALUE(f, s) \ 416051Swyllys rv = f; \ 426051Swyllys if (rv != KMF_OK) { \ 436051Swyllys cryptoerror(LOG_STDERR, \ 446051Swyllys gettext("Failed to set %s: 0x%02x\n"), s, rv); \ 456051Swyllys goto cleanup; \ 466051Swyllys } 476051Swyllys 486051Swyllys 496051Swyllys static int 506051Swyllys read_csrdata(KMF_HANDLE_T handle, char *csrfile, KMF_CSR_DATA *csrdata) 516051Swyllys { 526051Swyllys KMF_RETURN rv = KMF_OK; 536051Swyllys KMF_ENCODE_FORMAT csrfmt; 546051Swyllys KMF_DATA csrfiledata = {NULL, 0}; 556051Swyllys KMF_DATA rawcsr = {NULL, 0}; 566051Swyllys 576051Swyllys rv = kmf_get_file_format(csrfile, &csrfmt); 586051Swyllys if (rv != KMF_OK) 596051Swyllys return (rv); 606051Swyllys 616051Swyllys rv = kmf_read_input_file(handle, csrfile, &csrfiledata); 626051Swyllys if (rv != KMF_OK) 636051Swyllys return (rv); 646051Swyllys 656051Swyllys if (csrfmt == KMF_FORMAT_PEM) { 666051Swyllys rv = kmf_pem_to_der(csrfiledata.Data, csrfiledata.Length, 676051Swyllys &rawcsr.Data, (int *)&rawcsr.Length); 686051Swyllys if (rv != KMF_OK) 696051Swyllys return (rv); 706051Swyllys 716051Swyllys kmf_free_data(&csrfiledata); 726051Swyllys } else { 736051Swyllys rawcsr.Data = csrfiledata.Data; 746051Swyllys rawcsr.Length = csrfiledata.Length; 756051Swyllys } 766051Swyllys 776051Swyllys rv = kmf_decode_csr(handle, &rawcsr, csrdata); 786051Swyllys kmf_free_data(&rawcsr); 796051Swyllys 806051Swyllys return (rv); 816051Swyllys } 826051Swyllys 836669Swyllys static KMF_RETURN 846669Swyllys find_csr_extn(KMF_X509_EXTENSIONS *extnlist, KMF_OID *extoid, 856669Swyllys KMF_X509_EXTENSION *outextn) 866669Swyllys { 876669Swyllys int i, found = 0; 886669Swyllys KMF_X509_EXTENSION *eptr; 896669Swyllys KMF_RETURN rv = KMF_OK; 906669Swyllys 916669Swyllys (void) memset(outextn, 0, sizeof (KMF_X509_EXTENSION)); 926669Swyllys for (i = 0; !found && i < extnlist->numberOfExtensions; i++) { 936669Swyllys eptr = &extnlist->extensions[i]; 946669Swyllys if (IsEqualOid(extoid, &eptr->extnId)) { 956669Swyllys rv = copy_extension_data(outextn, eptr); 966669Swyllys found++; 976669Swyllys } 986669Swyllys } 996669Swyllys if (found == 0 || rv != KMF_OK) 1006669Swyllys return (1); 1016669Swyllys else 1026669Swyllys return (rv); 1036669Swyllys } 1046669Swyllys 1056051Swyllys static int 1066051Swyllys build_cert_from_csr(KMF_CSR_DATA *csrdata, 1076051Swyllys KMF_X509_CERTIFICATE *signedCert, 1086051Swyllys KMF_BIGINT *serial, 1096051Swyllys uint32_t ltime, 1106051Swyllys char *issuer, char *subject, 1116051Swyllys char *altname, 1126051Swyllys KMF_GENERALNAMECHOICES alttype, 1136051Swyllys int altcrit, 1146051Swyllys uint16_t kubits, 1156051Swyllys int kucrit, 1166051Swyllys EKU_LIST *ekulist) 1176051Swyllys { 1186051Swyllys KMF_RETURN rv = KMF_OK; 1196051Swyllys KMF_X509_NAME issuerDN, subjectDN; 1206051Swyllys 1216051Swyllys /* 1226051Swyllys * If the CSR is ok, now we can generate the final certificate. 1236051Swyllys */ 1246051Swyllys (void) memset(signedCert, 0, sizeof (KMF_X509_CERTIFICATE)); 1256051Swyllys (void) memset(&issuerDN, 0, sizeof (issuerDN)); 1266051Swyllys (void) memset(&subjectDN, 0, sizeof (subjectDN)); 1276051Swyllys 1286051Swyllys SET_VALUE(kmf_set_cert_version(signedCert, 2), "version number"); 1296051Swyllys 1306051Swyllys SET_VALUE(kmf_set_cert_serial(signedCert, serial), "serial number"); 1316051Swyllys 1326051Swyllys SET_VALUE(kmf_set_cert_validity(signedCert, NULL, ltime), 1336051Swyllys "validity time"); 1346051Swyllys 1356051Swyllys if (issuer) { 1366051Swyllys if (kmf_dn_parser(issuer, &issuerDN) != KMF_OK) { 1376051Swyllys cryptoerror(LOG_STDERR, 1386051Swyllys gettext("Issuer name cannot be parsed\n")); 1396051Swyllys return (PK_ERR_USAGE); 1406051Swyllys } 1416051Swyllys SET_VALUE(kmf_set_cert_issuer(signedCert, &issuerDN), 1426051Swyllys "Issuer Name"); 1436051Swyllys } 1446051Swyllys if (subject) { 1456051Swyllys if (kmf_dn_parser(subject, &subjectDN) != KMF_OK) { 1466051Swyllys cryptoerror(LOG_STDERR, 1476051Swyllys gettext("Subject name cannot be parsed\n")); 1486051Swyllys return (PK_ERR_USAGE); 1496051Swyllys } 1506051Swyllys SET_VALUE(kmf_set_cert_subject(signedCert, &subjectDN), 1516051Swyllys "Subject Name"); 1526051Swyllys } else { 1536051Swyllys signedCert->certificate.subject = csrdata->csr.subject; 1546051Swyllys } 1556051Swyllys 1566051Swyllys signedCert->certificate.subjectPublicKeyInfo = 1576051Swyllys csrdata->csr.subjectPublicKeyInfo; 1586051Swyllys 1596051Swyllys signedCert->certificate.extensions = csrdata->csr.extensions; 1606051Swyllys 1616051Swyllys signedCert->certificate.signature = 1626051Swyllys csrdata->signature.algorithmIdentifier; 1636051Swyllys 1646051Swyllys if (kubits != 0) { 1656669Swyllys KMF_X509_EXTENSION extn; 1666669Swyllys uint16_t oldbits; 1676669Swyllys /* 1686669Swyllys * If the CSR already has KU, merge them. 1696669Swyllys */ 1706669Swyllys rv = find_csr_extn(&csrdata->csr.extensions, 1716669Swyllys (KMF_OID *)&KMFOID_KeyUsage, &extn); 1726669Swyllys if (rv == KMF_OK) { 1736669Swyllys extn.critical |= kucrit; 1746669Swyllys if (extn.value.tagAndValue->value.Length > 1) { 1756669Swyllys oldbits = 1766669Swyllys extn.value.tagAndValue->value.Data[1] << 8; 1776669Swyllys } else { 1786669Swyllys oldbits = 1796669Swyllys extn.value.tagAndValue->value.Data[0]; 1806669Swyllys } 1816669Swyllys oldbits |= kubits; 1826669Swyllys } else { 1836669Swyllys SET_VALUE(kmf_set_cert_ku(signedCert, kucrit, kubits), 1846669Swyllys "KeyUsage"); 1856669Swyllys } 1866051Swyllys } 1876051Swyllys if (altname != NULL) { 1886051Swyllys SET_VALUE(kmf_set_cert_subject_altname(signedCert, 1896051Swyllys altcrit, alttype, altname), "subjectAltName"); 1906051Swyllys } 1916051Swyllys if (ekulist != NULL) { 1926051Swyllys int i; 1936051Swyllys for (i = 0; rv == KMF_OK && i < ekulist->eku_count; i++) { 1946051Swyllys SET_VALUE(kmf_add_cert_eku(signedCert, 1956051Swyllys &ekulist->ekulist[i], 1966051Swyllys ekulist->critlist[i]), "Extended Key Usage"); 1976051Swyllys } 1986051Swyllys } 1996051Swyllys cleanup: 2006051Swyllys if (issuer != NULL) 2016051Swyllys kmf_free_dn(&issuerDN); 2026051Swyllys if (subject != NULL) 2036051Swyllys kmf_free_dn(&subjectDN); 2046051Swyllys 2056051Swyllys return (rv); 2066051Swyllys } 2076051Swyllys 2086051Swyllys static int 2096051Swyllys pk_sign_cert(KMF_HANDLE_T handle, KMF_X509_CERTIFICATE *cert, 2106051Swyllys KMF_KEY_HANDLE *key, KMF_DATA *outdata) 2116051Swyllys { 2126051Swyllys KMF_RETURN rv; 2136051Swyllys int numattr; 2146051Swyllys KMF_ATTRIBUTE attrlist[4]; 2156051Swyllys 2166051Swyllys numattr = 0; 2176051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 2186051Swyllys &key->kstype, sizeof (KMF_KEYSTORE_TYPE)); 2196051Swyllys numattr++; 2206051Swyllys 2216051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR, 2226051Swyllys key, sizeof (KMF_KEY_HANDLE_ATTR)); 2236051Swyllys numattr++; 2246051Swyllys 2256051Swyllys /* cert data that is to be signed */ 2266051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR, 2276051Swyllys cert, sizeof (KMF_X509_CERTIFICATE)); 2286051Swyllys numattr++; 2296051Swyllys 2306051Swyllys /* output buffer for the signed cert */ 2316051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR, 2326051Swyllys outdata, sizeof (KMF_DATA)); 2336051Swyllys numattr++; 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 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 271*11973Swyllys.ingersoll@sun.com (void) memset(&cakey, 0, sizeof (cakey)); 272*11973Swyllys.ingersoll@sun.com (void) memset(&signedCert, 0, sizeof (signedCert)); 273*11973Swyllys.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 3356051Swyllys rv = pk_sign_cert(handle, &signedCert, &cakey, &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 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}; 3656051Swyllys KMF_CSR_DATA csrdata; 3666051Swyllys KMF_KEY_HANDLE casignkey; 3676051Swyllys KMF_KEY_CLASS keyclass = KMF_ASYM_PRI; 3686051Swyllys int numattr = 0; 3696051Swyllys int keys = 1; 3706051Swyllys KMF_ATTRIBUTE attrlist[16]; 3716051Swyllys KMF_X509_CERTIFICATE signedCert; 3726051Swyllys boolean_t token_bool = B_TRUE; 3736051Swyllys boolean_t private_bool = B_TRUE; 3746051Swyllys 3758132SWyllys.Ingersoll@Sun.COM (void) memset(&casignkey, 0, sizeof (KMF_KEY_HANDLE)); 376*11973Swyllys.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 /* 4616051Swyllys * If we found the key, now we can sign the cert. 4626051Swyllys */ 4636051Swyllys rv = pk_sign_cert(handle, &signedCert, &casignkey, &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 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