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