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