1*99ebb4caSwyllys /* 2*99ebb4caSwyllys * CDDL HEADER START 3*99ebb4caSwyllys * 4*99ebb4caSwyllys * The contents of this file are subject to the terms of the 5*99ebb4caSwyllys * Common Development and Distribution License (the "License"). 6*99ebb4caSwyllys * You may not use this file except in compliance with the License. 7*99ebb4caSwyllys * 8*99ebb4caSwyllys * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*99ebb4caSwyllys * or http://www.opensolaris.org/os/licensing. 10*99ebb4caSwyllys * See the License for the specific language governing permissions 11*99ebb4caSwyllys * and limitations under the License. 12*99ebb4caSwyllys * 13*99ebb4caSwyllys * When distributing Covered Code, include this CDDL HEADER in each 14*99ebb4caSwyllys * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*99ebb4caSwyllys * If applicable, add the following below this CDDL HEADER, with the 16*99ebb4caSwyllys * fields enclosed by brackets "[]" replaced with your own identifying 17*99ebb4caSwyllys * information: Portions Copyright [yyyy] [name of copyright owner] 18*99ebb4caSwyllys * 19*99ebb4caSwyllys * CDDL HEADER END 20*99ebb4caSwyllys * 21*99ebb4caSwyllys * 22*99ebb4caSwyllys * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23*99ebb4caSwyllys * Use is subject to license terms. 24*99ebb4caSwyllys */ 25*99ebb4caSwyllys 26*99ebb4caSwyllys #pragma ident "%Z%%M% %I% %E% SMI" 27*99ebb4caSwyllys 28*99ebb4caSwyllys #include <stdio.h> 29*99ebb4caSwyllys #include <string.h> 30*99ebb4caSwyllys #include <ctype.h> 31*99ebb4caSwyllys #include <malloc.h> 32*99ebb4caSwyllys #include <libgen.h> 33*99ebb4caSwyllys #include <errno.h> 34*99ebb4caSwyllys #include <cryptoutil.h> 35*99ebb4caSwyllys #include <security/cryptoki.h> 36*99ebb4caSwyllys #include "common.h" 37*99ebb4caSwyllys 38*99ebb4caSwyllys #include <kmfapi.h> 39*99ebb4caSwyllys 40*99ebb4caSwyllys #define SET_VALUE(f, s) \ 41*99ebb4caSwyllys kmfrv = f; \ 42*99ebb4caSwyllys if (kmfrv != KMF_OK) { \ 43*99ebb4caSwyllys cryptoerror(LOG_STDERR, \ 44*99ebb4caSwyllys gettext("Failed to %s: 0x%02\n"), \ 45*99ebb4caSwyllys s, kmfrv); \ 46*99ebb4caSwyllys goto cleanup; \ 47*99ebb4caSwyllys } 48*99ebb4caSwyllys 49*99ebb4caSwyllys static KMF_RETURN 50*99ebb4caSwyllys gencsr_pkcs11(KMF_HANDLE_T kmfhandle, 51*99ebb4caSwyllys char *token, char *subject, char *altname, 52*99ebb4caSwyllys KMF_GENERALNAMECHOICES alttype, int altcrit, 53*99ebb4caSwyllys char *certlabel, KMF_KEY_ALG keyAlg, 54*99ebb4caSwyllys int keylen, 55*99ebb4caSwyllys uint16_t kubits, int kucrit, 56*99ebb4caSwyllys KMF_ENCODE_FORMAT fmt, char *csrfile, 57*99ebb4caSwyllys KMF_CREDENTIAL *tokencred) 58*99ebb4caSwyllys { 59*99ebb4caSwyllys KMF_RETURN kmfrv = KMF_OK; 60*99ebb4caSwyllys KMF_CREATEKEYPAIR_PARAMS kp_params; 61*99ebb4caSwyllys KMF_DELETEKEY_PARAMS dk_params; 62*99ebb4caSwyllys KMF_KEY_HANDLE pubk, prik; 63*99ebb4caSwyllys KMF_X509_NAME csrSubject; 64*99ebb4caSwyllys KMF_CSR_DATA csr; 65*99ebb4caSwyllys KMF_ALGORITHM_INDEX sigAlg; 66*99ebb4caSwyllys KMF_DATA signedCsr = {NULL, 0}; 67*99ebb4caSwyllys 68*99ebb4caSwyllys (void) memset(&csr, 0, sizeof (csr)); 69*99ebb4caSwyllys (void) memset(&csrSubject, 0, sizeof (csrSubject)); 70*99ebb4caSwyllys (void) memset(&kp_params, 0, sizeof (kp_params)); 71*99ebb4caSwyllys 72*99ebb4caSwyllys if (keyAlg == KMF_DSA) 73*99ebb4caSwyllys sigAlg = KMF_ALGID_SHA1WithDSA; 74*99ebb4caSwyllys else 75*99ebb4caSwyllys sigAlg = KMF_ALGID_MD5WithRSA; 76*99ebb4caSwyllys 77*99ebb4caSwyllys 78*99ebb4caSwyllys /* If the subject name cannot be parsed, flag it now and exit */ 79*99ebb4caSwyllys if ((kmfrv = KMF_DNParser(subject, &csrSubject)) != KMF_OK) { 80*99ebb4caSwyllys return (kmfrv); 81*99ebb4caSwyllys } 82*99ebb4caSwyllys 83*99ebb4caSwyllys kp_params.kstype = KMF_KEYSTORE_PK11TOKEN; 84*99ebb4caSwyllys kp_params.keylabel = certlabel; 85*99ebb4caSwyllys kp_params.keylength = keylen; /* bits */ 86*99ebb4caSwyllys kp_params.keytype = keyAlg; 87*99ebb4caSwyllys kp_params.cred.cred = tokencred->cred; 88*99ebb4caSwyllys kp_params.cred.credlen = tokencred->credlen; 89*99ebb4caSwyllys 90*99ebb4caSwyllys /* Select a PKCS11 token */ 91*99ebb4caSwyllys kmfrv = select_token(kmfhandle, token, FALSE); 92*99ebb4caSwyllys if (kmfrv != KMF_OK) { 93*99ebb4caSwyllys return (kmfrv); 94*99ebb4caSwyllys } 95*99ebb4caSwyllys 96*99ebb4caSwyllys kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk); 97*99ebb4caSwyllys if (kmfrv != KMF_OK) { 98*99ebb4caSwyllys return (kmfrv); 99*99ebb4caSwyllys } 100*99ebb4caSwyllys 101*99ebb4caSwyllys SET_VALUE(KMF_SetCSRPubKey(kmfhandle, &pubk, &csr), "keypair"); 102*99ebb4caSwyllys 103*99ebb4caSwyllys SET_VALUE(KMF_SetCSRVersion(&csr, 2), "version number"); 104*99ebb4caSwyllys 105*99ebb4caSwyllys SET_VALUE(KMF_SetCSRSubjectName(&csr, &csrSubject), 106*99ebb4caSwyllys "subject name"); 107*99ebb4caSwyllys 108*99ebb4caSwyllys SET_VALUE(KMF_SetCSRSignatureAlgorithm(&csr, sigAlg), 109*99ebb4caSwyllys "SignatureAlgorithm"); 110*99ebb4caSwyllys 111*99ebb4caSwyllys if (altname != NULL) { 112*99ebb4caSwyllys SET_VALUE(KMF_SetCSRSubjectAltName(&csr, altname, altcrit, 113*99ebb4caSwyllys alttype), "SetCSRSubjectAltName"); 114*99ebb4caSwyllys } 115*99ebb4caSwyllys 116*99ebb4caSwyllys if (kubits != 0) { 117*99ebb4caSwyllys SET_VALUE(KMF_SetCSRKeyUsage(&csr, kucrit, kubits), 118*99ebb4caSwyllys "SetCSRKeyUsage"); 119*99ebb4caSwyllys } 120*99ebb4caSwyllys 121*99ebb4caSwyllys if ((kmfrv = KMF_SignCSR(kmfhandle, &csr, &prik, &signedCsr)) == 122*99ebb4caSwyllys KMF_OK) { 123*99ebb4caSwyllys kmfrv = KMF_CreateCSRFile(&signedCsr, fmt, csrfile); 124*99ebb4caSwyllys } 125*99ebb4caSwyllys 126*99ebb4caSwyllys cleanup: 127*99ebb4caSwyllys (void) KMF_FreeData(&signedCsr); 128*99ebb4caSwyllys (void) KMF_FreeKMFKey(kmfhandle, &prik); 129*99ebb4caSwyllys /* delete the key */ 130*99ebb4caSwyllys (void) memset(&dk_params, 0, sizeof (dk_params)); 131*99ebb4caSwyllys dk_params.kstype = KMF_KEYSTORE_PK11TOKEN; 132*99ebb4caSwyllys (void) KMF_DeleteKeyFromKeystore(kmfhandle, &dk_params, &pubk); 133*99ebb4caSwyllys (void) KMF_FreeSignedCSR(&csr); 134*99ebb4caSwyllys 135*99ebb4caSwyllys return (kmfrv); 136*99ebb4caSwyllys } 137*99ebb4caSwyllys 138*99ebb4caSwyllys static KMF_RETURN 139*99ebb4caSwyllys gencsr_file(KMF_HANDLE_T kmfhandle, 140*99ebb4caSwyllys KMF_KEY_ALG keyAlg, 141*99ebb4caSwyllys int keylen, KMF_ENCODE_FORMAT fmt, 142*99ebb4caSwyllys char *subject, char *altname, KMF_GENERALNAMECHOICES alttype, 143*99ebb4caSwyllys int altcrit, uint16_t kubits, int kucrit, 144*99ebb4caSwyllys char *dir, char *outcsr, char *outkey) 145*99ebb4caSwyllys { 146*99ebb4caSwyllys KMF_RETURN kmfrv; 147*99ebb4caSwyllys KMF_CREATEKEYPAIR_PARAMS kp_params; 148*99ebb4caSwyllys KMF_KEY_HANDLE pubk, prik; 149*99ebb4caSwyllys KMF_X509_NAME csrSubject; 150*99ebb4caSwyllys KMF_CSR_DATA csr; 151*99ebb4caSwyllys KMF_ALGORITHM_INDEX sigAlg; 152*99ebb4caSwyllys KMF_DATA signedCsr = {NULL, 0}; 153*99ebb4caSwyllys char *fullcsrpath = NULL; 154*99ebb4caSwyllys char *fullkeypath = NULL; 155*99ebb4caSwyllys 156*99ebb4caSwyllys (void) memset(&csr, 0, sizeof (csr)); 157*99ebb4caSwyllys (void) memset(&csrSubject, 0, sizeof (csrSubject)); 158*99ebb4caSwyllys (void) memset(&kp_params, 0, sizeof (kp_params)); 159*99ebb4caSwyllys 160*99ebb4caSwyllys if (EMPTYSTRING(outcsr) || EMPTYSTRING(outkey)) { 161*99ebb4caSwyllys cryptoerror(LOG_STDERR, 162*99ebb4caSwyllys gettext("No output file was specified for " 163*99ebb4caSwyllys "the csr or key\n")); 164*99ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 165*99ebb4caSwyllys } 166*99ebb4caSwyllys if (dir != NULL) { 167*99ebb4caSwyllys fullcsrpath = get_fullpath(dir, outcsr); 168*99ebb4caSwyllys if (fullcsrpath == NULL) { 169*99ebb4caSwyllys cryptoerror(LOG_STDERR, 170*99ebb4caSwyllys gettext("Cannot create file %s in " 171*99ebb4caSwyllys "directory %s\n"), dir, outcsr); 172*99ebb4caSwyllys return (PK_ERR_USAGE); 173*99ebb4caSwyllys } 174*99ebb4caSwyllys } else { 175*99ebb4caSwyllys fullcsrpath = strdup(outcsr); 176*99ebb4caSwyllys } 177*99ebb4caSwyllys if (verify_file(fullcsrpath)) { 178*99ebb4caSwyllys cryptoerror(LOG_STDERR, 179*99ebb4caSwyllys gettext("Cannot write the indicated output " 180*99ebb4caSwyllys "certificate file (%s).\n"), fullcsrpath); 181*99ebb4caSwyllys free(fullcsrpath); 182*99ebb4caSwyllys return (PK_ERR_USAGE); 183*99ebb4caSwyllys } 184*99ebb4caSwyllys if (dir != NULL) { 185*99ebb4caSwyllys fullkeypath = get_fullpath(dir, outkey); 186*99ebb4caSwyllys if (fullkeypath == NULL) { 187*99ebb4caSwyllys cryptoerror(LOG_STDERR, 188*99ebb4caSwyllys gettext("Cannot create file %s in " 189*99ebb4caSwyllys "directory %s\n"), dir, outkey); 190*99ebb4caSwyllys free(fullcsrpath); 191*99ebb4caSwyllys return (PK_ERR_USAGE); 192*99ebb4caSwyllys } 193*99ebb4caSwyllys } else { 194*99ebb4caSwyllys fullkeypath = strdup(outkey); 195*99ebb4caSwyllys } 196*99ebb4caSwyllys if (verify_file(fullcsrpath)) { 197*99ebb4caSwyllys cryptoerror(LOG_STDERR, 198*99ebb4caSwyllys gettext("Cannot write the indicated output " 199*99ebb4caSwyllys "key file (%s).\n"), fullkeypath); 200*99ebb4caSwyllys free(fullcsrpath); 201*99ebb4caSwyllys return (PK_ERR_USAGE); 202*99ebb4caSwyllys } 203*99ebb4caSwyllys 204*99ebb4caSwyllys if (keyAlg == KMF_DSA) 205*99ebb4caSwyllys sigAlg = KMF_ALGID_SHA1WithDSA; 206*99ebb4caSwyllys else 207*99ebb4caSwyllys sigAlg = KMF_ALGID_MD5WithRSA; 208*99ebb4caSwyllys 209*99ebb4caSwyllys /* If the subject name cannot be parsed, flag it now and exit */ 210*99ebb4caSwyllys if ((kmfrv = KMF_DNParser(subject, &csrSubject)) != KMF_OK) { 211*99ebb4caSwyllys return (kmfrv); 212*99ebb4caSwyllys } 213*99ebb4caSwyllys 214*99ebb4caSwyllys kp_params.kstype = KMF_KEYSTORE_OPENSSL; 215*99ebb4caSwyllys kp_params.keylength = keylen; /* bits */ 216*99ebb4caSwyllys kp_params.keytype = keyAlg; 217*99ebb4caSwyllys 218*99ebb4caSwyllys kp_params.sslparms.keyfile = fullkeypath; 219*99ebb4caSwyllys kp_params.sslparms.format = fmt; 220*99ebb4caSwyllys 221*99ebb4caSwyllys kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk); 222*99ebb4caSwyllys if (kmfrv != KMF_OK) { 223*99ebb4caSwyllys goto cleanup; 224*99ebb4caSwyllys } 225*99ebb4caSwyllys SET_VALUE(KMF_SetCSRPubKey(kmfhandle, &pubk, &csr), 226*99ebb4caSwyllys "SetCSRPubKey"); 227*99ebb4caSwyllys 228*99ebb4caSwyllys SET_VALUE(KMF_SetCSRVersion(&csr, 2), "SetCSRVersion"); 229*99ebb4caSwyllys 230*99ebb4caSwyllys SET_VALUE(KMF_SetCSRSubjectName(&csr, &csrSubject), 231*99ebb4caSwyllys "SetCSRSubjectName"); 232*99ebb4caSwyllys 233*99ebb4caSwyllys SET_VALUE(KMF_SetCSRSignatureAlgorithm(&csr, sigAlg), 234*99ebb4caSwyllys "SetCSRSignatureAlgorithm"); 235*99ebb4caSwyllys 236*99ebb4caSwyllys if (altname != NULL) { 237*99ebb4caSwyllys SET_VALUE(KMF_SetCSRSubjectAltName(&csr, altname, altcrit, 238*99ebb4caSwyllys alttype), "SetCSRSubjectAltName"); 239*99ebb4caSwyllys } 240*99ebb4caSwyllys if (kubits != NULL) { 241*99ebb4caSwyllys SET_VALUE(KMF_SetCSRKeyUsage(&csr, kucrit, kubits), 242*99ebb4caSwyllys "SetCSRKeyUsage"); 243*99ebb4caSwyllys } 244*99ebb4caSwyllys if ((kmfrv = KMF_SignCSR(kmfhandle, &csr, &prik, &signedCsr)) == 245*99ebb4caSwyllys KMF_OK) { 246*99ebb4caSwyllys kmfrv = KMF_CreateCSRFile(&signedCsr, fmt, fullcsrpath); 247*99ebb4caSwyllys } 248*99ebb4caSwyllys 249*99ebb4caSwyllys cleanup: 250*99ebb4caSwyllys if (fullkeypath) 251*99ebb4caSwyllys free(fullkeypath); 252*99ebb4caSwyllys if (fullcsrpath) 253*99ebb4caSwyllys free(fullcsrpath); 254*99ebb4caSwyllys 255*99ebb4caSwyllys KMF_FreeData(&signedCsr); 256*99ebb4caSwyllys KMF_FreeKMFKey(kmfhandle, &prik); 257*99ebb4caSwyllys KMF_FreeSignedCSR(&csr); 258*99ebb4caSwyllys 259*99ebb4caSwyllys return (kmfrv); 260*99ebb4caSwyllys } 261*99ebb4caSwyllys 262*99ebb4caSwyllys static KMF_RETURN 263*99ebb4caSwyllys gencsr_nss(KMF_HANDLE_T kmfhandle, 264*99ebb4caSwyllys char *token, char *subject, char *altname, 265*99ebb4caSwyllys KMF_GENERALNAMECHOICES alttype, int altcrit, 266*99ebb4caSwyllys char *nickname, char *dir, char *prefix, 267*99ebb4caSwyllys KMF_KEY_ALG keyAlg, int keylen, 268*99ebb4caSwyllys uint16_t kubits, int kucrit, 269*99ebb4caSwyllys KMF_ENCODE_FORMAT fmt, char *csrfile, 270*99ebb4caSwyllys KMF_CREDENTIAL *tokencred) 271*99ebb4caSwyllys { 272*99ebb4caSwyllys KMF_RETURN kmfrv; 273*99ebb4caSwyllys KMF_CREATEKEYPAIR_PARAMS kp_params; 274*99ebb4caSwyllys KMF_KEY_HANDLE pubk, prik; 275*99ebb4caSwyllys KMF_X509_NAME csrSubject; 276*99ebb4caSwyllys KMF_CSR_DATA csr; 277*99ebb4caSwyllys KMF_ALGORITHM_INDEX sigAlg; 278*99ebb4caSwyllys KMF_DATA signedCsr = {NULL, 0}; 279*99ebb4caSwyllys KMF_DELETEKEY_PARAMS dk_params; 280*99ebb4caSwyllys 281*99ebb4caSwyllys if (token == NULL) 282*99ebb4caSwyllys token = DEFAULT_NSS_TOKEN; 283*99ebb4caSwyllys 284*99ebb4caSwyllys if (keyAlg == KMF_DSA) 285*99ebb4caSwyllys sigAlg = KMF_ALGID_SHA1WithDSA; 286*99ebb4caSwyllys else 287*99ebb4caSwyllys sigAlg = KMF_ALGID_MD5WithRSA; 288*99ebb4caSwyllys 289*99ebb4caSwyllys kmfrv = configure_nss(kmfhandle, dir, prefix); 290*99ebb4caSwyllys if (kmfrv != KMF_OK) 291*99ebb4caSwyllys return (kmfrv); 292*99ebb4caSwyllys 293*99ebb4caSwyllys (void) memset(&csr, 0, sizeof (csr)); 294*99ebb4caSwyllys (void) memset(&csrSubject, 0, sizeof (csrSubject)); 295*99ebb4caSwyllys 296*99ebb4caSwyllys /* If the subject name cannot be parsed, flag it now and exit */ 297*99ebb4caSwyllys if ((kmfrv = KMF_DNParser(subject, &csrSubject)) != KMF_OK) { 298*99ebb4caSwyllys return (kmfrv); 299*99ebb4caSwyllys } 300*99ebb4caSwyllys 301*99ebb4caSwyllys (void) memset(&kp_params, 0, sizeof (kp_params)); 302*99ebb4caSwyllys 303*99ebb4caSwyllys kp_params.kstype = KMF_KEYSTORE_NSS; 304*99ebb4caSwyllys kp_params.keylabel = nickname; 305*99ebb4caSwyllys kp_params.keylength = keylen; /* bits */ 306*99ebb4caSwyllys kp_params.keytype = keyAlg; 307*99ebb4caSwyllys kp_params.cred.cred = tokencred->cred; 308*99ebb4caSwyllys kp_params.cred.credlen = tokencred->credlen; 309*99ebb4caSwyllys kp_params.nssparms.slotlabel = token; 310*99ebb4caSwyllys 311*99ebb4caSwyllys kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk); 312*99ebb4caSwyllys if (kmfrv != KMF_OK) { 313*99ebb4caSwyllys goto cleanup; 314*99ebb4caSwyllys } 315*99ebb4caSwyllys 316*99ebb4caSwyllys SET_VALUE(KMF_SetCSRPubKey(kmfhandle, &pubk, &csr), "SetCSRPubKey"); 317*99ebb4caSwyllys SET_VALUE(KMF_SetCSRVersion(&csr, 2), "SetCSRVersion"); 318*99ebb4caSwyllys SET_VALUE(KMF_SetCSRSubjectName(&csr, &csrSubject), 319*99ebb4caSwyllys "SetCSRSubjectName"); 320*99ebb4caSwyllys SET_VALUE(KMF_SetCSRSignatureAlgorithm(&csr, sigAlg), 321*99ebb4caSwyllys "SetCSRSignatureAlgorithm"); 322*99ebb4caSwyllys 323*99ebb4caSwyllys if (altname != NULL) { 324*99ebb4caSwyllys SET_VALUE(KMF_SetCSRSubjectAltName(&csr, altname, altcrit, 325*99ebb4caSwyllys alttype), "SetCSRSubjectAltName"); 326*99ebb4caSwyllys } 327*99ebb4caSwyllys if (kubits != NULL) { 328*99ebb4caSwyllys SET_VALUE(KMF_SetCSRKeyUsage(&csr, kucrit, kubits), 329*99ebb4caSwyllys "SetCSRKeyUsage"); 330*99ebb4caSwyllys } 331*99ebb4caSwyllys if ((kmfrv = KMF_SignCSR(kmfhandle, &csr, &prik, &signedCsr)) == 332*99ebb4caSwyllys KMF_OK) { 333*99ebb4caSwyllys kmfrv = KMF_CreateCSRFile(&signedCsr, fmt, csrfile); 334*99ebb4caSwyllys } 335*99ebb4caSwyllys 336*99ebb4caSwyllys cleanup: 337*99ebb4caSwyllys (void) KMF_FreeData(&signedCsr); 338*99ebb4caSwyllys (void) KMF_FreeKMFKey(kmfhandle, &prik); 339*99ebb4caSwyllys /* delete the key */ 340*99ebb4caSwyllys (void) memset(&dk_params, 0, sizeof (dk_params)); 341*99ebb4caSwyllys dk_params.kstype = KMF_KEYSTORE_NSS; 342*99ebb4caSwyllys dk_params.cred.cred = tokencred->cred; 343*99ebb4caSwyllys dk_params.cred.credlen = tokencred->credlen; 344*99ebb4caSwyllys dk_params.nssparms.slotlabel = token; 345*99ebb4caSwyllys (void) KMF_DeleteKeyFromKeystore(kmfhandle, &dk_params, &pubk); 346*99ebb4caSwyllys (void) KMF_FreeSignedCSR(&csr); 347*99ebb4caSwyllys 348*99ebb4caSwyllys return (kmfrv); 349*99ebb4caSwyllys } 350*99ebb4caSwyllys 351*99ebb4caSwyllys int 352*99ebb4caSwyllys pk_gencsr(int argc, char *argv[]) 353*99ebb4caSwyllys { 354*99ebb4caSwyllys KMF_RETURN rv; 355*99ebb4caSwyllys int opt; 356*99ebb4caSwyllys extern int optind_av; 357*99ebb4caSwyllys extern char *optarg_av; 358*99ebb4caSwyllys KMF_KEYSTORE_TYPE kstype = 0; 359*99ebb4caSwyllys char *subject = NULL; 360*99ebb4caSwyllys char *tokenname = NULL; 361*99ebb4caSwyllys char *dir = NULL; 362*99ebb4caSwyllys char *prefix = NULL; 363*99ebb4caSwyllys int keylen = PK_DEFAULT_KEYLENGTH; 364*99ebb4caSwyllys char *certlabel = NULL; 365*99ebb4caSwyllys char *outcsr = NULL; 366*99ebb4caSwyllys char *outkey = NULL; 367*99ebb4caSwyllys char *format = NULL; 368*99ebb4caSwyllys char *altname = NULL; 369*99ebb4caSwyllys char *kustr = NULL; 370*99ebb4caSwyllys uint16_t kubits = 0; 371*99ebb4caSwyllys char *keytype = PK_DEFAULT_KEYTYPE; 372*99ebb4caSwyllys KMF_HANDLE_T kmfhandle = NULL; 373*99ebb4caSwyllys KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1; 374*99ebb4caSwyllys KMF_KEY_ALG keyAlg = KMF_RSA; 375*99ebb4caSwyllys KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA; 376*99ebb4caSwyllys boolean_t interactive = B_FALSE; 377*99ebb4caSwyllys char *subname = NULL; 378*99ebb4caSwyllys KMF_CREDENTIAL tokencred = {NULL, 0}; 379*99ebb4caSwyllys KMF_GENERALNAMECHOICES alttype = 0; 380*99ebb4caSwyllys int altcrit = 0, kucrit = 0; 381*99ebb4caSwyllys 382*99ebb4caSwyllys while ((opt = getopt_av(argc, argv, 383*99ebb4caSwyllys "ik:(keystore)s:(subject)n:(nickname)A:(altname)" 384*99ebb4caSwyllys "u:(keyusage)T:(token)d:(dir)p:(prefix)t:(keytype)" 385*99ebb4caSwyllys "y:(keylen)l:(label)c:(outcsr)" 386*99ebb4caSwyllys "K:(outkey)F:(format)")) != EOF) { 387*99ebb4caSwyllys 388*99ebb4caSwyllys if (opt != 'i' && EMPTYSTRING(optarg_av)) 389*99ebb4caSwyllys return (PK_ERR_USAGE); 390*99ebb4caSwyllys 391*99ebb4caSwyllys switch (opt) { 392*99ebb4caSwyllys case 'A': 393*99ebb4caSwyllys altname = optarg_av; 394*99ebb4caSwyllys break; 395*99ebb4caSwyllys case 'i': 396*99ebb4caSwyllys if (interactive || subject) 397*99ebb4caSwyllys return (PK_ERR_USAGE); 398*99ebb4caSwyllys else 399*99ebb4caSwyllys interactive = B_TRUE; 400*99ebb4caSwyllys break; 401*99ebb4caSwyllys case 'k': 402*99ebb4caSwyllys kstype = KS2Int(optarg_av); 403*99ebb4caSwyllys if (kstype == 0) 404*99ebb4caSwyllys return (PK_ERR_USAGE); 405*99ebb4caSwyllys break; 406*99ebb4caSwyllys case 's': 407*99ebb4caSwyllys if (interactive || subject) 408*99ebb4caSwyllys return (PK_ERR_USAGE); 409*99ebb4caSwyllys else 410*99ebb4caSwyllys subject = optarg_av; 411*99ebb4caSwyllys break; 412*99ebb4caSwyllys case 'l': 413*99ebb4caSwyllys case 'n': 414*99ebb4caSwyllys if (certlabel) 415*99ebb4caSwyllys return (PK_ERR_USAGE); 416*99ebb4caSwyllys certlabel = optarg_av; 417*99ebb4caSwyllys break; 418*99ebb4caSwyllys case 'T': 419*99ebb4caSwyllys if (tokenname) 420*99ebb4caSwyllys return (PK_ERR_USAGE); 421*99ebb4caSwyllys tokenname = optarg_av; 422*99ebb4caSwyllys break; 423*99ebb4caSwyllys case 'd': 424*99ebb4caSwyllys dir = optarg_av; 425*99ebb4caSwyllys break; 426*99ebb4caSwyllys case 'p': 427*99ebb4caSwyllys if (prefix) 428*99ebb4caSwyllys return (PK_ERR_USAGE); 429*99ebb4caSwyllys prefix = optarg_av; 430*99ebb4caSwyllys break; 431*99ebb4caSwyllys case 't': 432*99ebb4caSwyllys keytype = optarg_av; 433*99ebb4caSwyllys break; 434*99ebb4caSwyllys case 'u': 435*99ebb4caSwyllys kustr = optarg_av; 436*99ebb4caSwyllys break; 437*99ebb4caSwyllys case 'y': 438*99ebb4caSwyllys if (sscanf(optarg_av, "%d", 439*99ebb4caSwyllys &keylen) != 1) { 440*99ebb4caSwyllys cryptoerror(LOG_STDERR, 441*99ebb4caSwyllys gettext("Unrecognized " 442*99ebb4caSwyllys "key length (%s)\n"), 443*99ebb4caSwyllys optarg_av); 444*99ebb4caSwyllys return (PK_ERR_USAGE); 445*99ebb4caSwyllys } 446*99ebb4caSwyllys break; 447*99ebb4caSwyllys case 'c': 448*99ebb4caSwyllys if (outcsr) 449*99ebb4caSwyllys return (PK_ERR_USAGE); 450*99ebb4caSwyllys outcsr = optarg_av; 451*99ebb4caSwyllys break; 452*99ebb4caSwyllys case 'K': 453*99ebb4caSwyllys if (outkey) 454*99ebb4caSwyllys return (PK_ERR_USAGE); 455*99ebb4caSwyllys outkey = optarg_av; 456*99ebb4caSwyllys break; 457*99ebb4caSwyllys case 'F': 458*99ebb4caSwyllys if (format) 459*99ebb4caSwyllys return (PK_ERR_USAGE); 460*99ebb4caSwyllys format = optarg_av; 461*99ebb4caSwyllys break; 462*99ebb4caSwyllys default: 463*99ebb4caSwyllys cryptoerror(LOG_STDERR, gettext( 464*99ebb4caSwyllys "unrecognized gencsr option '%s'\n"), 465*99ebb4caSwyllys argv[optind_av]); 466*99ebb4caSwyllys return (PK_ERR_USAGE); 467*99ebb4caSwyllys } 468*99ebb4caSwyllys } 469*99ebb4caSwyllys /* No additional args allowed. */ 470*99ebb4caSwyllys argc -= optind_av; 471*99ebb4caSwyllys argv += optind_av; 472*99ebb4caSwyllys if (argc) { 473*99ebb4caSwyllys return (PK_ERR_USAGE); 474*99ebb4caSwyllys } 475*99ebb4caSwyllys 476*99ebb4caSwyllys if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 477*99ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n")); 478*99ebb4caSwyllys return (PK_ERR_USAGE); 479*99ebb4caSwyllys } 480*99ebb4caSwyllys 481*99ebb4caSwyllys /* Assume keystore = PKCS#11 if not specified. */ 482*99ebb4caSwyllys if (kstype == 0) 483*99ebb4caSwyllys kstype = KMF_KEYSTORE_PK11TOKEN; 484*99ebb4caSwyllys 485*99ebb4caSwyllys if (EMPTYSTRING(outcsr)) { 486*99ebb4caSwyllys (void) printf(gettext("A filename must be specified to hold" 487*99ebb4caSwyllys "the final certificate request data.\n")); 488*99ebb4caSwyllys return (PK_ERR_USAGE); 489*99ebb4caSwyllys } else { 490*99ebb4caSwyllys /* 491*99ebb4caSwyllys * verify that the outcsr file does not already exist 492*99ebb4caSwyllys * and that it can be created. 493*99ebb4caSwyllys */ 494*99ebb4caSwyllys rv = verify_file(outcsr); 495*99ebb4caSwyllys if (rv != KMF_OK) { 496*99ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("output file (%s) " 497*99ebb4caSwyllys "cannot be created.\n"), outcsr); 498*99ebb4caSwyllys return (PK_ERR_USAGE); 499*99ebb4caSwyllys } 500*99ebb4caSwyllys } 501*99ebb4caSwyllys 502*99ebb4caSwyllys if ((kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) && 503*99ebb4caSwyllys EMPTYSTRING(certlabel)) { 504*99ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("A label must be specified " 505*99ebb4caSwyllys "to create a certificate request.\n")); 506*99ebb4caSwyllys return (PK_ERR_USAGE); 507*99ebb4caSwyllys } else if (kstype == KMF_KEYSTORE_OPENSSL && EMPTYSTRING(outkey)) { 508*99ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("A key filename must be " 509*99ebb4caSwyllys "specified to create a certificate request.\n")); 510*99ebb4caSwyllys return (PK_ERR_USAGE); 511*99ebb4caSwyllys } 512*99ebb4caSwyllys 513*99ebb4caSwyllys if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) { 514*99ebb4caSwyllys cryptoerror(LOG_STDERR, 515*99ebb4caSwyllys gettext("Error parsing format string (%s).\n"), 516*99ebb4caSwyllys format); 517*99ebb4caSwyllys return (PK_ERR_USAGE); 518*99ebb4caSwyllys } 519*99ebb4caSwyllys if (format && fmt != KMF_FORMAT_ASN1 && fmt != KMF_FORMAT_PEM) { 520*99ebb4caSwyllys cryptoerror(LOG_STDERR, 521*99ebb4caSwyllys gettext("CSR must be DER or PEM format.\n")); 522*99ebb4caSwyllys return (PK_ERR_USAGE); 523*99ebb4caSwyllys } 524*99ebb4caSwyllys 525*99ebb4caSwyllys /* 526*99ebb4caSwyllys * Check the subject name. 527*99ebb4caSwyllys * If interactive is true, get it now interactively. 528*99ebb4caSwyllys */ 529*99ebb4caSwyllys if (interactive) { 530*99ebb4caSwyllys if (get_subname(&subname) != KMF_OK) { 531*99ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("Failed to get the " 532*99ebb4caSwyllys "subject name interactively.\n")); 533*99ebb4caSwyllys return (PK_ERR_USAGE); 534*99ebb4caSwyllys } 535*99ebb4caSwyllys } else { 536*99ebb4caSwyllys if (EMPTYSTRING(subject)) { 537*99ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("A subject name or " 538*99ebb4caSwyllys "-i must be specified to create a certificate " 539*99ebb4caSwyllys "request.\n")); 540*99ebb4caSwyllys return (PK_ERR_USAGE); 541*99ebb4caSwyllys } else { 542*99ebb4caSwyllys subname = strdup(subject); 543*99ebb4caSwyllys if (subname == NULL) { 544*99ebb4caSwyllys cryptoerror(LOG_STDERR, 545*99ebb4caSwyllys gettext("Out of memory.\n")); 546*99ebb4caSwyllys return (PK_ERR_SYSTEM); 547*99ebb4caSwyllys } 548*99ebb4caSwyllys } 549*99ebb4caSwyllys } 550*99ebb4caSwyllys if (altname != NULL) { 551*99ebb4caSwyllys rv = verify_altname(altname, &alttype, &altcrit); 552*99ebb4caSwyllys if (rv != KMF_OK) { 553*99ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("Subject AltName " 554*99ebb4caSwyllys "must be specified as a name=value pair. " 555*99ebb4caSwyllys "See the man page for details.")); 556*99ebb4caSwyllys goto end; 557*99ebb4caSwyllys } else { 558*99ebb4caSwyllys /* advance the altname past the '=' sign */ 559*99ebb4caSwyllys char *p = strchr(altname, '='); 560*99ebb4caSwyllys if (p != NULL) 561*99ebb4caSwyllys altname = p + 1; 562*99ebb4caSwyllys } 563*99ebb4caSwyllys } 564*99ebb4caSwyllys 565*99ebb4caSwyllys if (kustr != NULL) { 566*99ebb4caSwyllys rv = verify_keyusage(kustr, &kubits, &kucrit); 567*99ebb4caSwyllys if (rv != KMF_OK) { 568*99ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("KeyUsage " 569*99ebb4caSwyllys "must be specified as a comma-separated list. " 570*99ebb4caSwyllys "See the man page for details.")); 571*99ebb4caSwyllys goto end; 572*99ebb4caSwyllys } 573*99ebb4caSwyllys } 574*99ebb4caSwyllys if ((rv = Str2KeyType(keytype, &keyAlg, &sigAlg)) != 0) { 575*99ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"), 576*99ebb4caSwyllys keytype); 577*99ebb4caSwyllys goto end; 578*99ebb4caSwyllys } 579*99ebb4caSwyllys 580*99ebb4caSwyllys if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) { 581*99ebb4caSwyllys if (tokenname == NULL || !strlen(tokenname)) { 582*99ebb4caSwyllys if (kstype == KMF_KEYSTORE_NSS) { 583*99ebb4caSwyllys tokenname = "internal"; 584*99ebb4caSwyllys } else { 585*99ebb4caSwyllys tokenname = PK_DEFAULT_PK11TOKEN; 586*99ebb4caSwyllys } 587*99ebb4caSwyllys } 588*99ebb4caSwyllys 589*99ebb4caSwyllys (void) get_token_password(kstype, tokenname, &tokencred); 590*99ebb4caSwyllys } 591*99ebb4caSwyllys 592*99ebb4caSwyllys if (kstype == KMF_KEYSTORE_NSS) { 593*99ebb4caSwyllys if (dir == NULL) 594*99ebb4caSwyllys dir = PK_DEFAULT_DIRECTORY; 595*99ebb4caSwyllys 596*99ebb4caSwyllys rv = gencsr_nss(kmfhandle, 597*99ebb4caSwyllys tokenname, subname, altname, alttype, altcrit, 598*99ebb4caSwyllys certlabel, dir, prefix, 599*99ebb4caSwyllys keyAlg, keylen, kubits, kucrit, 600*99ebb4caSwyllys fmt, outcsr, &tokencred); 601*99ebb4caSwyllys 602*99ebb4caSwyllys } else if (kstype == KMF_KEYSTORE_PK11TOKEN) { 603*99ebb4caSwyllys rv = gencsr_pkcs11(kmfhandle, 604*99ebb4caSwyllys tokenname, subname, altname, alttype, altcrit, 605*99ebb4caSwyllys certlabel, keyAlg, keylen, 606*99ebb4caSwyllys kubits, kucrit, fmt, outcsr, &tokencred); 607*99ebb4caSwyllys 608*99ebb4caSwyllys } else if (kstype == KMF_KEYSTORE_OPENSSL) { 609*99ebb4caSwyllys rv = gencsr_file(kmfhandle, 610*99ebb4caSwyllys keyAlg, keylen, fmt, subname, altname, 611*99ebb4caSwyllys alttype, altcrit, kubits, kucrit, 612*99ebb4caSwyllys dir, outcsr, outkey); 613*99ebb4caSwyllys } 614*99ebb4caSwyllys 615*99ebb4caSwyllys end: 616*99ebb4caSwyllys if (rv != KMF_OK) 617*99ebb4caSwyllys display_error(kmfhandle, rv, 618*99ebb4caSwyllys gettext("Error creating CSR or keypair")); 619*99ebb4caSwyllys 620*99ebb4caSwyllys if (subname) 621*99ebb4caSwyllys free(subname); 622*99ebb4caSwyllys 623*99ebb4caSwyllys if (tokencred.cred != NULL) 624*99ebb4caSwyllys free(tokencred.cred); 625*99ebb4caSwyllys 626*99ebb4caSwyllys (void) KMF_Finalize(kmfhandle); 627*99ebb4caSwyllys if (rv != KMF_OK) 628*99ebb4caSwyllys return (PK_ERR_USAGE); 629*99ebb4caSwyllys 630*99ebb4caSwyllys return (0); 631*99ebb4caSwyllys } 632