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