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