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