1*e65e5c2dSWyllys Ingersoll /* 2*e65e5c2dSWyllys Ingersoll * CDDL HEADER START 3*e65e5c2dSWyllys Ingersoll * 4*e65e5c2dSWyllys Ingersoll * The contents of this file are subject to the terms of the 5*e65e5c2dSWyllys Ingersoll * Common Development and Distribution License (the "License"). 6*e65e5c2dSWyllys Ingersoll * You may not use this file except in compliance with the License. 7*e65e5c2dSWyllys Ingersoll * 8*e65e5c2dSWyllys Ingersoll * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*e65e5c2dSWyllys Ingersoll * or http://www.opensolaris.org/os/licensing. 10*e65e5c2dSWyllys Ingersoll * See the License for the specific language governing permissions 11*e65e5c2dSWyllys Ingersoll * and limitations under the License. 12*e65e5c2dSWyllys Ingersoll * 13*e65e5c2dSWyllys Ingersoll * When distributing Covered Code, include this CDDL HEADER in each 14*e65e5c2dSWyllys Ingersoll * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*e65e5c2dSWyllys Ingersoll * If applicable, add the following below this CDDL HEADER, with the 16*e65e5c2dSWyllys Ingersoll * fields enclosed by brackets "[]" replaced with your own identifying 17*e65e5c2dSWyllys Ingersoll * information: Portions Copyright [yyyy] [name of copyright owner] 18*e65e5c2dSWyllys Ingersoll * 19*e65e5c2dSWyllys Ingersoll * CDDL HEADER END 20*e65e5c2dSWyllys Ingersoll */ 21*e65e5c2dSWyllys Ingersoll /* 22*e65e5c2dSWyllys Ingersoll * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23*e65e5c2dSWyllys Ingersoll * Use is subject to license terms. 24*e65e5c2dSWyllys Ingersoll */ 25*e65e5c2dSWyllys Ingersoll 26*e65e5c2dSWyllys Ingersoll #include <stdio.h> 27*e65e5c2dSWyllys Ingersoll #include <string.h> 28*e65e5c2dSWyllys Ingersoll #include <ctype.h> 29*e65e5c2dSWyllys Ingersoll #include <malloc.h> 30*e65e5c2dSWyllys Ingersoll #include <libgen.h> 31*e65e5c2dSWyllys Ingersoll #include <errno.h> 32*e65e5c2dSWyllys Ingersoll #include <cryptoutil.h> 33*e65e5c2dSWyllys Ingersoll #include <security/cryptoki.h> 34*e65e5c2dSWyllys Ingersoll #include "common.h" 35*e65e5c2dSWyllys Ingersoll 36*e65e5c2dSWyllys Ingersoll #include <kmfapi.h> 37*e65e5c2dSWyllys Ingersoll 38*e65e5c2dSWyllys Ingersoll #define SET_VALUE(f, s) \ 39*e65e5c2dSWyllys Ingersoll kmfrv = f; \ 40*e65e5c2dSWyllys Ingersoll if (kmfrv != KMF_OK) { \ 41*e65e5c2dSWyllys Ingersoll cryptoerror(LOG_STDERR, \ 42*e65e5c2dSWyllys Ingersoll gettext("Failed to set %s: 0x%02x\n"), \ 43*e65e5c2dSWyllys Ingersoll s, kmfrv); \ 44*e65e5c2dSWyllys Ingersoll goto cleanup; \ 45*e65e5c2dSWyllys Ingersoll } 46*e65e5c2dSWyllys Ingersoll 47*e65e5c2dSWyllys Ingersoll KMF_RETURN 48*e65e5c2dSWyllys Ingersoll genkeypair_pkcs11(KMF_HANDLE_T kmfhandle, 49*e65e5c2dSWyllys Ingersoll char *token, char *keylabel, KMF_KEY_ALG keyAlg, 50*e65e5c2dSWyllys Ingersoll int keylen, KMF_CREDENTIAL *tokencred, KMF_OID *curveoid, 51*e65e5c2dSWyllys Ingersoll KMF_KEY_HANDLE *outPriKey, KMF_KEY_HANDLE *outPubKey) 52*e65e5c2dSWyllys Ingersoll { 53*e65e5c2dSWyllys Ingersoll KMF_RETURN kmfrv = KMF_OK; 54*e65e5c2dSWyllys Ingersoll KMF_KEY_HANDLE pubk, prik; 55*e65e5c2dSWyllys Ingersoll KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 56*e65e5c2dSWyllys Ingersoll KMF_ATTRIBUTE attrlist[16]; 57*e65e5c2dSWyllys Ingersoll int numattr = 0; 58*e65e5c2dSWyllys Ingersoll KMF_KEY_ALG keytype; 59*e65e5c2dSWyllys Ingersoll uint32_t keylength; 60*e65e5c2dSWyllys Ingersoll 61*e65e5c2dSWyllys Ingersoll keylength = keylen; /* bits */ 62*e65e5c2dSWyllys Ingersoll keytype = keyAlg; 63*e65e5c2dSWyllys Ingersoll 64*e65e5c2dSWyllys Ingersoll /* Select a PKCS11 token */ 65*e65e5c2dSWyllys Ingersoll kmfrv = select_token(kmfhandle, token, FALSE); 66*e65e5c2dSWyllys Ingersoll if (kmfrv != KMF_OK) 67*e65e5c2dSWyllys Ingersoll return (kmfrv); 68*e65e5c2dSWyllys Ingersoll 69*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 70*e65e5c2dSWyllys Ingersoll KMF_KEYSTORE_TYPE_ATTR, &kstype, 71*e65e5c2dSWyllys Ingersoll sizeof (kstype)); 72*e65e5c2dSWyllys Ingersoll numattr++; 73*e65e5c2dSWyllys Ingersoll 74*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 75*e65e5c2dSWyllys Ingersoll KMF_KEYALG_ATTR, &keytype, 76*e65e5c2dSWyllys Ingersoll sizeof (keytype)); 77*e65e5c2dSWyllys Ingersoll numattr++; 78*e65e5c2dSWyllys Ingersoll 79*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 80*e65e5c2dSWyllys Ingersoll KMF_KEYLENGTH_ATTR, &keylength, 81*e65e5c2dSWyllys Ingersoll sizeof (keylength)); 82*e65e5c2dSWyllys Ingersoll numattr++; 83*e65e5c2dSWyllys Ingersoll 84*e65e5c2dSWyllys Ingersoll if (keylabel != NULL) { 85*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 86*e65e5c2dSWyllys Ingersoll KMF_KEYLABEL_ATTR, keylabel, 87*e65e5c2dSWyllys Ingersoll strlen(keylabel)); 88*e65e5c2dSWyllys Ingersoll numattr++; 89*e65e5c2dSWyllys Ingersoll } 90*e65e5c2dSWyllys Ingersoll 91*e65e5c2dSWyllys Ingersoll if (tokencred != NULL && tokencred->cred != NULL) { 92*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 93*e65e5c2dSWyllys Ingersoll KMF_CREDENTIAL_ATTR, tokencred, 94*e65e5c2dSWyllys Ingersoll sizeof (KMF_CREDENTIAL)); 95*e65e5c2dSWyllys Ingersoll numattr++; 96*e65e5c2dSWyllys Ingersoll } 97*e65e5c2dSWyllys Ingersoll 98*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 99*e65e5c2dSWyllys Ingersoll KMF_PRIVKEY_HANDLE_ATTR, &prik, 100*e65e5c2dSWyllys Ingersoll sizeof (KMF_KEY_HANDLE)); 101*e65e5c2dSWyllys Ingersoll numattr++; 102*e65e5c2dSWyllys Ingersoll 103*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 104*e65e5c2dSWyllys Ingersoll KMF_PUBKEY_HANDLE_ATTR, &pubk, 105*e65e5c2dSWyllys Ingersoll sizeof (KMF_KEY_HANDLE)); 106*e65e5c2dSWyllys Ingersoll numattr++; 107*e65e5c2dSWyllys Ingersoll 108*e65e5c2dSWyllys Ingersoll if (keytype == KMF_ECDSA && curveoid != NULL) { 109*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 110*e65e5c2dSWyllys Ingersoll KMF_ECC_CURVE_OID_ATTR, curveoid, 111*e65e5c2dSWyllys Ingersoll sizeof (KMF_OID)); 112*e65e5c2dSWyllys Ingersoll numattr++; 113*e65e5c2dSWyllys Ingersoll } 114*e65e5c2dSWyllys Ingersoll 115*e65e5c2dSWyllys Ingersoll kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist); 116*e65e5c2dSWyllys Ingersoll if (kmfrv != KMF_OK) { 117*e65e5c2dSWyllys Ingersoll return (kmfrv); 118*e65e5c2dSWyllys Ingersoll } 119*e65e5c2dSWyllys Ingersoll 120*e65e5c2dSWyllys Ingersoll cleanup: 121*e65e5c2dSWyllys Ingersoll if (kmfrv == KMF_OK) { 122*e65e5c2dSWyllys Ingersoll if (outPriKey != NULL) 123*e65e5c2dSWyllys Ingersoll *outPriKey = prik; 124*e65e5c2dSWyllys Ingersoll if (outPubKey != NULL) 125*e65e5c2dSWyllys Ingersoll *outPubKey = pubk; 126*e65e5c2dSWyllys Ingersoll } 127*e65e5c2dSWyllys Ingersoll 128*e65e5c2dSWyllys Ingersoll return (kmfrv); 129*e65e5c2dSWyllys Ingersoll } 130*e65e5c2dSWyllys Ingersoll 131*e65e5c2dSWyllys Ingersoll KMF_RETURN 132*e65e5c2dSWyllys Ingersoll genkeypair_file(KMF_HANDLE_T kmfhandle, 133*e65e5c2dSWyllys Ingersoll KMF_KEY_ALG keyAlg, int keylen, KMF_ENCODE_FORMAT fmt, 134*e65e5c2dSWyllys Ingersoll char *outkey, 135*e65e5c2dSWyllys Ingersoll KMF_KEY_HANDLE *outPriKey, KMF_KEY_HANDLE *outPubKey) 136*e65e5c2dSWyllys Ingersoll { 137*e65e5c2dSWyllys Ingersoll KMF_RETURN kmfrv; 138*e65e5c2dSWyllys Ingersoll KMF_KEY_HANDLE pubk, prik; 139*e65e5c2dSWyllys Ingersoll char *fullkeypath = NULL; 140*e65e5c2dSWyllys Ingersoll KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL; 141*e65e5c2dSWyllys Ingersoll KMF_ATTRIBUTE attrlist[10]; 142*e65e5c2dSWyllys Ingersoll int numattr = 0; 143*e65e5c2dSWyllys Ingersoll KMF_KEY_ALG keytype; 144*e65e5c2dSWyllys Ingersoll uint32_t keylength; 145*e65e5c2dSWyllys Ingersoll KMF_ENCODE_FORMAT format; 146*e65e5c2dSWyllys Ingersoll 147*e65e5c2dSWyllys Ingersoll if (EMPTYSTRING(outkey)) { 148*e65e5c2dSWyllys Ingersoll cryptoerror(LOG_STDERR, 149*e65e5c2dSWyllys Ingersoll gettext("No output file was specified for " 150*e65e5c2dSWyllys Ingersoll "the key\n")); 151*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 152*e65e5c2dSWyllys Ingersoll } 153*e65e5c2dSWyllys Ingersoll 154*e65e5c2dSWyllys Ingersoll fullkeypath = strdup(outkey); 155*e65e5c2dSWyllys Ingersoll if (verify_file(fullkeypath)) { 156*e65e5c2dSWyllys Ingersoll cryptoerror(LOG_STDERR, 157*e65e5c2dSWyllys Ingersoll gettext("Cannot write the indicated output " 158*e65e5c2dSWyllys Ingersoll "key file (%s).\n"), fullkeypath); 159*e65e5c2dSWyllys Ingersoll free(fullkeypath); 160*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 161*e65e5c2dSWyllys Ingersoll } 162*e65e5c2dSWyllys Ingersoll 163*e65e5c2dSWyllys Ingersoll keylength = keylen; /* bits */ 164*e65e5c2dSWyllys Ingersoll keytype = keyAlg; 165*e65e5c2dSWyllys Ingersoll format = fmt; 166*e65e5c2dSWyllys Ingersoll 167*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 168*e65e5c2dSWyllys Ingersoll KMF_KEYSTORE_TYPE_ATTR, &kstype, 169*e65e5c2dSWyllys Ingersoll sizeof (kstype)); 170*e65e5c2dSWyllys Ingersoll numattr++; 171*e65e5c2dSWyllys Ingersoll 172*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 173*e65e5c2dSWyllys Ingersoll KMF_KEYALG_ATTR, &keytype, 174*e65e5c2dSWyllys Ingersoll sizeof (keytype)); 175*e65e5c2dSWyllys Ingersoll numattr++; 176*e65e5c2dSWyllys Ingersoll 177*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 178*e65e5c2dSWyllys Ingersoll KMF_KEYLENGTH_ATTR, &keylength, 179*e65e5c2dSWyllys Ingersoll sizeof (keylength)); 180*e65e5c2dSWyllys Ingersoll numattr++; 181*e65e5c2dSWyllys Ingersoll 182*e65e5c2dSWyllys Ingersoll if (fullkeypath != NULL) { 183*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 184*e65e5c2dSWyllys Ingersoll KMF_KEY_FILENAME_ATTR, fullkeypath, 185*e65e5c2dSWyllys Ingersoll strlen(fullkeypath)); 186*e65e5c2dSWyllys Ingersoll numattr++; 187*e65e5c2dSWyllys Ingersoll } 188*e65e5c2dSWyllys Ingersoll 189*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 190*e65e5c2dSWyllys Ingersoll KMF_ENCODE_FORMAT_ATTR, &format, 191*e65e5c2dSWyllys Ingersoll sizeof (format)); 192*e65e5c2dSWyllys Ingersoll numattr++; 193*e65e5c2dSWyllys Ingersoll 194*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 195*e65e5c2dSWyllys Ingersoll KMF_PRIVKEY_HANDLE_ATTR, &prik, 196*e65e5c2dSWyllys Ingersoll sizeof (KMF_KEY_HANDLE)); 197*e65e5c2dSWyllys Ingersoll numattr++; 198*e65e5c2dSWyllys Ingersoll 199*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 200*e65e5c2dSWyllys Ingersoll KMF_PUBKEY_HANDLE_ATTR, &pubk, 201*e65e5c2dSWyllys Ingersoll sizeof (KMF_KEY_HANDLE)); 202*e65e5c2dSWyllys Ingersoll numattr++; 203*e65e5c2dSWyllys Ingersoll 204*e65e5c2dSWyllys Ingersoll kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist); 205*e65e5c2dSWyllys Ingersoll if (kmfrv != KMF_OK) { 206*e65e5c2dSWyllys Ingersoll goto cleanup; 207*e65e5c2dSWyllys Ingersoll } 208*e65e5c2dSWyllys Ingersoll 209*e65e5c2dSWyllys Ingersoll cleanup: 210*e65e5c2dSWyllys Ingersoll if (fullkeypath != NULL) 211*e65e5c2dSWyllys Ingersoll free(fullkeypath); 212*e65e5c2dSWyllys Ingersoll 213*e65e5c2dSWyllys Ingersoll if (kmfrv == KMF_OK) { 214*e65e5c2dSWyllys Ingersoll if (outPriKey != NULL) 215*e65e5c2dSWyllys Ingersoll *outPriKey = prik; 216*e65e5c2dSWyllys Ingersoll if (outPubKey != NULL) 217*e65e5c2dSWyllys Ingersoll *outPubKey = pubk; 218*e65e5c2dSWyllys Ingersoll } 219*e65e5c2dSWyllys Ingersoll 220*e65e5c2dSWyllys Ingersoll return (kmfrv); 221*e65e5c2dSWyllys Ingersoll } 222*e65e5c2dSWyllys Ingersoll 223*e65e5c2dSWyllys Ingersoll KMF_RETURN 224*e65e5c2dSWyllys Ingersoll genkeypair_nss(KMF_HANDLE_T kmfhandle, 225*e65e5c2dSWyllys Ingersoll char *token, 226*e65e5c2dSWyllys Ingersoll char *nickname, char *dir, char *prefix, 227*e65e5c2dSWyllys Ingersoll KMF_KEY_ALG keyAlg, 228*e65e5c2dSWyllys Ingersoll int keylen, KMF_CREDENTIAL *tokencred, 229*e65e5c2dSWyllys Ingersoll KMF_OID *curveoid, 230*e65e5c2dSWyllys Ingersoll KMF_KEY_HANDLE *outPriKey, KMF_KEY_HANDLE *outPubKey) 231*e65e5c2dSWyllys Ingersoll { 232*e65e5c2dSWyllys Ingersoll KMF_RETURN kmfrv; 233*e65e5c2dSWyllys Ingersoll KMF_KEY_HANDLE pubk, prik; 234*e65e5c2dSWyllys Ingersoll KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 235*e65e5c2dSWyllys Ingersoll KMF_ATTRIBUTE attrlist[16]; 236*e65e5c2dSWyllys Ingersoll int numattr = 0; 237*e65e5c2dSWyllys Ingersoll KMF_KEY_ALG keytype; 238*e65e5c2dSWyllys Ingersoll uint32_t keylength; 239*e65e5c2dSWyllys Ingersoll 240*e65e5c2dSWyllys Ingersoll if (token == NULL) 241*e65e5c2dSWyllys Ingersoll token = DEFAULT_NSS_TOKEN; 242*e65e5c2dSWyllys Ingersoll 243*e65e5c2dSWyllys Ingersoll kmfrv = configure_nss(kmfhandle, dir, prefix); 244*e65e5c2dSWyllys Ingersoll if (kmfrv != KMF_OK) 245*e65e5c2dSWyllys Ingersoll return (kmfrv); 246*e65e5c2dSWyllys Ingersoll 247*e65e5c2dSWyllys Ingersoll keylength = keylen; /* bits */ 248*e65e5c2dSWyllys Ingersoll keytype = keyAlg; 249*e65e5c2dSWyllys Ingersoll 250*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 251*e65e5c2dSWyllys Ingersoll KMF_KEYSTORE_TYPE_ATTR, &kstype, 252*e65e5c2dSWyllys Ingersoll sizeof (kstype)); 253*e65e5c2dSWyllys Ingersoll numattr++; 254*e65e5c2dSWyllys Ingersoll 255*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 256*e65e5c2dSWyllys Ingersoll KMF_KEYALG_ATTR, &keytype, 257*e65e5c2dSWyllys Ingersoll sizeof (keytype)); 258*e65e5c2dSWyllys Ingersoll numattr++; 259*e65e5c2dSWyllys Ingersoll 260*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 261*e65e5c2dSWyllys Ingersoll KMF_KEYLENGTH_ATTR, &keylength, 262*e65e5c2dSWyllys Ingersoll sizeof (keylength)); 263*e65e5c2dSWyllys Ingersoll numattr++; 264*e65e5c2dSWyllys Ingersoll 265*e65e5c2dSWyllys Ingersoll if (nickname != NULL) { 266*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 267*e65e5c2dSWyllys Ingersoll KMF_KEYLABEL_ATTR, nickname, 268*e65e5c2dSWyllys Ingersoll strlen(nickname)); 269*e65e5c2dSWyllys Ingersoll numattr++; 270*e65e5c2dSWyllys Ingersoll } 271*e65e5c2dSWyllys Ingersoll 272*e65e5c2dSWyllys Ingersoll if (tokencred != NULL && tokencred->cred != NULL) { 273*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 274*e65e5c2dSWyllys Ingersoll KMF_CREDENTIAL_ATTR, tokencred, 275*e65e5c2dSWyllys Ingersoll sizeof (KMF_CREDENTIAL)); 276*e65e5c2dSWyllys Ingersoll numattr++; 277*e65e5c2dSWyllys Ingersoll } 278*e65e5c2dSWyllys Ingersoll 279*e65e5c2dSWyllys Ingersoll if (token != NULL) { 280*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 281*e65e5c2dSWyllys Ingersoll KMF_TOKEN_LABEL_ATTR, token, 282*e65e5c2dSWyllys Ingersoll strlen(token)); 283*e65e5c2dSWyllys Ingersoll numattr++; 284*e65e5c2dSWyllys Ingersoll } 285*e65e5c2dSWyllys Ingersoll 286*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 287*e65e5c2dSWyllys Ingersoll KMF_PRIVKEY_HANDLE_ATTR, &prik, 288*e65e5c2dSWyllys Ingersoll sizeof (KMF_KEY_HANDLE)); 289*e65e5c2dSWyllys Ingersoll numattr++; 290*e65e5c2dSWyllys Ingersoll 291*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 292*e65e5c2dSWyllys Ingersoll KMF_PUBKEY_HANDLE_ATTR, &pubk, 293*e65e5c2dSWyllys Ingersoll sizeof (KMF_KEY_HANDLE)); 294*e65e5c2dSWyllys Ingersoll numattr++; 295*e65e5c2dSWyllys Ingersoll 296*e65e5c2dSWyllys Ingersoll if (keytype == KMF_ECDSA && curveoid != NULL) { 297*e65e5c2dSWyllys Ingersoll kmf_set_attr_at_index(attrlist, numattr, 298*e65e5c2dSWyllys Ingersoll KMF_ECC_CURVE_OID_ATTR, curveoid, 299*e65e5c2dSWyllys Ingersoll sizeof (KMF_OID)); 300*e65e5c2dSWyllys Ingersoll numattr++; 301*e65e5c2dSWyllys Ingersoll } 302*e65e5c2dSWyllys Ingersoll 303*e65e5c2dSWyllys Ingersoll kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist); 304*e65e5c2dSWyllys Ingersoll if (kmfrv != KMF_OK) { 305*e65e5c2dSWyllys Ingersoll return (kmfrv); 306*e65e5c2dSWyllys Ingersoll } 307*e65e5c2dSWyllys Ingersoll cleanup: 308*e65e5c2dSWyllys Ingersoll if (kmfrv == KMF_OK) { 309*e65e5c2dSWyllys Ingersoll if (outPriKey != NULL) 310*e65e5c2dSWyllys Ingersoll *outPriKey = prik; 311*e65e5c2dSWyllys Ingersoll if (outPubKey != NULL) 312*e65e5c2dSWyllys Ingersoll *outPubKey = pubk; 313*e65e5c2dSWyllys Ingersoll } 314*e65e5c2dSWyllys Ingersoll return (kmfrv); 315*e65e5c2dSWyllys Ingersoll } 316*e65e5c2dSWyllys Ingersoll 317*e65e5c2dSWyllys Ingersoll int 318*e65e5c2dSWyllys Ingersoll pk_genkeypair(int argc, char *argv[]) 319*e65e5c2dSWyllys Ingersoll { 320*e65e5c2dSWyllys Ingersoll int rv; 321*e65e5c2dSWyllys Ingersoll int opt; 322*e65e5c2dSWyllys Ingersoll extern int optind_av; 323*e65e5c2dSWyllys Ingersoll extern char *optarg_av; 324*e65e5c2dSWyllys Ingersoll KMF_KEYSTORE_TYPE kstype = 0; 325*e65e5c2dSWyllys Ingersoll char *tokenname = NULL; 326*e65e5c2dSWyllys Ingersoll char *dir = NULL; 327*e65e5c2dSWyllys Ingersoll char *prefix = NULL; 328*e65e5c2dSWyllys Ingersoll char *keytype = PK_DEFAULT_KEYTYPE; 329*e65e5c2dSWyllys Ingersoll int keylen = PK_DEFAULT_KEYLENGTH; 330*e65e5c2dSWyllys Ingersoll char *label = NULL; 331*e65e5c2dSWyllys Ingersoll char *outkey = NULL; 332*e65e5c2dSWyllys Ingersoll char *format = NULL; 333*e65e5c2dSWyllys Ingersoll KMF_HANDLE_T kmfhandle = NULL; 334*e65e5c2dSWyllys Ingersoll KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1; 335*e65e5c2dSWyllys Ingersoll KMF_KEY_ALG keyAlg = KMF_RSA; 336*e65e5c2dSWyllys Ingersoll KMF_ALGORITHM_INDEX sigAlg; 337*e65e5c2dSWyllys Ingersoll KMF_CREDENTIAL tokencred = { NULL, 0 }; 338*e65e5c2dSWyllys Ingersoll KMF_OID *curveoid = NULL; /* ECC */ 339*e65e5c2dSWyllys Ingersoll int y_flag = 0; 340*e65e5c2dSWyllys Ingersoll 341*e65e5c2dSWyllys Ingersoll while ((opt = getopt_av(argc, argv, 342*e65e5c2dSWyllys Ingersoll "k:(keystore)s:(subject)n:(nickname)" 343*e65e5c2dSWyllys Ingersoll "T:(token)d:(dir)p:(prefix)t:(keytype)y:(keylen)" 344*e65e5c2dSWyllys Ingersoll "l:(label)K:(outkey)F:(format)C:(curve)" 345*e65e5c2dSWyllys Ingersoll "E(listcurves)")) != EOF) { 346*e65e5c2dSWyllys Ingersoll 347*e65e5c2dSWyllys Ingersoll if (opt != 'i' && opt != 'E' && EMPTYSTRING(optarg_av)) 348*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 349*e65e5c2dSWyllys Ingersoll 350*e65e5c2dSWyllys Ingersoll switch (opt) { 351*e65e5c2dSWyllys Ingersoll case 'k': 352*e65e5c2dSWyllys Ingersoll kstype = KS2Int(optarg_av); 353*e65e5c2dSWyllys Ingersoll if (kstype == 0) 354*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 355*e65e5c2dSWyllys Ingersoll break; 356*e65e5c2dSWyllys Ingersoll case 'l': 357*e65e5c2dSWyllys Ingersoll case 'n': 358*e65e5c2dSWyllys Ingersoll if (label) 359*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 360*e65e5c2dSWyllys Ingersoll label = optarg_av; 361*e65e5c2dSWyllys Ingersoll break; 362*e65e5c2dSWyllys Ingersoll case 'T': 363*e65e5c2dSWyllys Ingersoll if (tokenname) 364*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 365*e65e5c2dSWyllys Ingersoll tokenname = optarg_av; 366*e65e5c2dSWyllys Ingersoll break; 367*e65e5c2dSWyllys Ingersoll case 'd': 368*e65e5c2dSWyllys Ingersoll if (dir) 369*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 370*e65e5c2dSWyllys Ingersoll dir = optarg_av; 371*e65e5c2dSWyllys Ingersoll break; 372*e65e5c2dSWyllys Ingersoll case 'p': 373*e65e5c2dSWyllys Ingersoll if (prefix) 374*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 375*e65e5c2dSWyllys Ingersoll prefix = optarg_av; 376*e65e5c2dSWyllys Ingersoll break; 377*e65e5c2dSWyllys Ingersoll case 't': 378*e65e5c2dSWyllys Ingersoll keytype = optarg_av; 379*e65e5c2dSWyllys Ingersoll break; 380*e65e5c2dSWyllys Ingersoll case 'y': 381*e65e5c2dSWyllys Ingersoll if (sscanf(optarg_av, "%d", 382*e65e5c2dSWyllys Ingersoll &keylen) != 1) { 383*e65e5c2dSWyllys Ingersoll cryptoerror(LOG_STDERR, 384*e65e5c2dSWyllys Ingersoll gettext("key length must be" 385*e65e5c2dSWyllys Ingersoll "a numeric value (%s)\n"), 386*e65e5c2dSWyllys Ingersoll optarg_av); 387*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 388*e65e5c2dSWyllys Ingersoll } 389*e65e5c2dSWyllys Ingersoll y_flag++; 390*e65e5c2dSWyllys Ingersoll break; 391*e65e5c2dSWyllys Ingersoll case 'K': 392*e65e5c2dSWyllys Ingersoll if (outkey) 393*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 394*e65e5c2dSWyllys Ingersoll outkey = optarg_av; 395*e65e5c2dSWyllys Ingersoll break; 396*e65e5c2dSWyllys Ingersoll case 'F': 397*e65e5c2dSWyllys Ingersoll if (format) 398*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 399*e65e5c2dSWyllys Ingersoll format = optarg_av; 400*e65e5c2dSWyllys Ingersoll break; 401*e65e5c2dSWyllys Ingersoll case 'C': 402*e65e5c2dSWyllys Ingersoll curveoid = ecc_name_to_oid(optarg_av); 403*e65e5c2dSWyllys Ingersoll if (curveoid == NULL) { 404*e65e5c2dSWyllys Ingersoll cryptoerror(LOG_STDERR, 405*e65e5c2dSWyllys Ingersoll gettext( 406*e65e5c2dSWyllys Ingersoll "Unrecognized ECC curve.\n")); 407*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 408*e65e5c2dSWyllys Ingersoll } 409*e65e5c2dSWyllys Ingersoll break; 410*e65e5c2dSWyllys Ingersoll case 'E': 411*e65e5c2dSWyllys Ingersoll show_ecc_curves(); 412*e65e5c2dSWyllys Ingersoll return (0); 413*e65e5c2dSWyllys Ingersoll default: 414*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 415*e65e5c2dSWyllys Ingersoll } 416*e65e5c2dSWyllys Ingersoll } 417*e65e5c2dSWyllys Ingersoll 418*e65e5c2dSWyllys Ingersoll /* No additional args allowed. */ 419*e65e5c2dSWyllys Ingersoll argc -= optind_av; 420*e65e5c2dSWyllys Ingersoll argv += optind_av; 421*e65e5c2dSWyllys Ingersoll if (argc) { 422*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 423*e65e5c2dSWyllys Ingersoll } 424*e65e5c2dSWyllys Ingersoll 425*e65e5c2dSWyllys Ingersoll if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 426*e65e5c2dSWyllys Ingersoll cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n")); 427*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 428*e65e5c2dSWyllys Ingersoll } 429*e65e5c2dSWyllys Ingersoll 430*e65e5c2dSWyllys Ingersoll /* Assume keystore = PKCS#11 if not specified. */ 431*e65e5c2dSWyllys Ingersoll if (kstype == 0) 432*e65e5c2dSWyllys Ingersoll kstype = KMF_KEYSTORE_PK11TOKEN; 433*e65e5c2dSWyllys Ingersoll 434*e65e5c2dSWyllys Ingersoll DIR_OPTION_CHECK(kstype, dir); 435*e65e5c2dSWyllys Ingersoll 436*e65e5c2dSWyllys Ingersoll if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) { 437*e65e5c2dSWyllys Ingersoll cryptoerror(LOG_STDERR, 438*e65e5c2dSWyllys Ingersoll gettext("Error parsing format string (%s).\n"), 439*e65e5c2dSWyllys Ingersoll format); 440*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 441*e65e5c2dSWyllys Ingersoll } 442*e65e5c2dSWyllys Ingersoll 443*e65e5c2dSWyllys Ingersoll if (Str2KeyType(keytype, NULL, &keyAlg, &sigAlg) != 0) { 444*e65e5c2dSWyllys Ingersoll cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"), 445*e65e5c2dSWyllys Ingersoll keytype); 446*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 447*e65e5c2dSWyllys Ingersoll } 448*e65e5c2dSWyllys Ingersoll if (curveoid != NULL && keyAlg != KMF_ECDSA) { 449*e65e5c2dSWyllys Ingersoll cryptoerror(LOG_STDERR, gettext("EC curves are only " 450*e65e5c2dSWyllys Ingersoll "valid for EC keytypes.\n")); 451*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 452*e65e5c2dSWyllys Ingersoll } 453*e65e5c2dSWyllys Ingersoll if (keyAlg == KMF_ECDSA && curveoid == NULL) { 454*e65e5c2dSWyllys Ingersoll cryptoerror(LOG_STDERR, gettext("A curve must be " 455*e65e5c2dSWyllys Ingersoll "specifed when using EC keys.\n")); 456*e65e5c2dSWyllys Ingersoll return (PK_ERR_USAGE); 457*e65e5c2dSWyllys Ingersoll } 458*e65e5c2dSWyllys Ingersoll if (keyAlg == KMF_ECDSA && kstype == KMF_KEYSTORE_OPENSSL) { 459*e65e5c2dSWyllys Ingersoll (void) fprintf(stderr, gettext("ECC certificates are" 460*e65e5c2dSWyllys Ingersoll "only supported with the pkcs11 and nss keystores\n")); 461*e65e5c2dSWyllys Ingersoll rv = PK_ERR_USAGE; 462*e65e5c2dSWyllys Ingersoll goto end; 463*e65e5c2dSWyllys Ingersoll } 464*e65e5c2dSWyllys Ingersoll /* Adjust default keylength for NSS and DSA */ 465*e65e5c2dSWyllys Ingersoll if (keyAlg == KMF_DSA && kstype == KMF_KEYSTORE_NSS) { 466*e65e5c2dSWyllys Ingersoll /* NSS only allows for 512-1024 bit DSA keys */ 467*e65e5c2dSWyllys Ingersoll if (!y_flag) 468*e65e5c2dSWyllys Ingersoll /* If nothing was given, default to 1024 */ 469*e65e5c2dSWyllys Ingersoll keylen = 1024; 470*e65e5c2dSWyllys Ingersoll else if (keylen > 1024 || keylen < 512) { 471*e65e5c2dSWyllys Ingersoll (void) fprintf(stderr, gettext("NSS keystore only " 472*e65e5c2dSWyllys Ingersoll "supports DSA keylengths of 512 - 1024 bits\n")); 473*e65e5c2dSWyllys Ingersoll rv = PK_ERR_USAGE; 474*e65e5c2dSWyllys Ingersoll goto end; 475*e65e5c2dSWyllys Ingersoll } 476*e65e5c2dSWyllys Ingersoll } 477*e65e5c2dSWyllys Ingersoll 478*e65e5c2dSWyllys Ingersoll if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) { 479*e65e5c2dSWyllys Ingersoll if (label == NULL) { 480*e65e5c2dSWyllys Ingersoll (void) fprintf(stderr, 481*e65e5c2dSWyllys Ingersoll gettext("No key label specified\n")); 482*e65e5c2dSWyllys Ingersoll rv = PK_ERR_USAGE; 483*e65e5c2dSWyllys Ingersoll goto end; 484*e65e5c2dSWyllys Ingersoll } 485*e65e5c2dSWyllys Ingersoll if (tokenname == NULL || !strlen(tokenname)) { 486*e65e5c2dSWyllys Ingersoll if (kstype == KMF_KEYSTORE_NSS) { 487*e65e5c2dSWyllys Ingersoll tokenname = "internal"; 488*e65e5c2dSWyllys Ingersoll } else { 489*e65e5c2dSWyllys Ingersoll tokenname = PK_DEFAULT_PK11TOKEN; 490*e65e5c2dSWyllys Ingersoll } 491*e65e5c2dSWyllys Ingersoll } 492*e65e5c2dSWyllys Ingersoll 493*e65e5c2dSWyllys Ingersoll (void) get_token_password(kstype, tokenname, &tokencred); 494*e65e5c2dSWyllys Ingersoll } 495*e65e5c2dSWyllys Ingersoll 496*e65e5c2dSWyllys Ingersoll if (kstype == KMF_KEYSTORE_NSS) { 497*e65e5c2dSWyllys Ingersoll if (dir == NULL) 498*e65e5c2dSWyllys Ingersoll dir = PK_DEFAULT_DIRECTORY; 499*e65e5c2dSWyllys Ingersoll 500*e65e5c2dSWyllys Ingersoll rv = genkeypair_nss(kmfhandle, 501*e65e5c2dSWyllys Ingersoll tokenname, label, dir, prefix, keyAlg, keylen, 502*e65e5c2dSWyllys Ingersoll &tokencred, curveoid, NULL, NULL); 503*e65e5c2dSWyllys Ingersoll 504*e65e5c2dSWyllys Ingersoll } else if (kstype == KMF_KEYSTORE_PK11TOKEN) { 505*e65e5c2dSWyllys Ingersoll rv = genkeypair_pkcs11(kmfhandle, 506*e65e5c2dSWyllys Ingersoll tokenname, label, keyAlg, keylen, 507*e65e5c2dSWyllys Ingersoll &tokencred, curveoid, NULL, NULL); 508*e65e5c2dSWyllys Ingersoll 509*e65e5c2dSWyllys Ingersoll } else if (kstype == KMF_KEYSTORE_OPENSSL) { 510*e65e5c2dSWyllys Ingersoll rv = genkeypair_file(kmfhandle, keyAlg, keylen, 511*e65e5c2dSWyllys Ingersoll fmt, outkey, NULL, NULL); 512*e65e5c2dSWyllys Ingersoll } 513*e65e5c2dSWyllys Ingersoll 514*e65e5c2dSWyllys Ingersoll if (rv != KMF_OK) 515*e65e5c2dSWyllys Ingersoll display_error(kmfhandle, rv, 516*e65e5c2dSWyllys Ingersoll gettext("Error creating and keypair")); 517*e65e5c2dSWyllys Ingersoll end: 518*e65e5c2dSWyllys Ingersoll if (tokencred.cred != NULL) 519*e65e5c2dSWyllys Ingersoll free(tokencred.cred); 520*e65e5c2dSWyllys Ingersoll 521*e65e5c2dSWyllys Ingersoll (void) kmf_finalize(kmfhandle); 522*e65e5c2dSWyllys Ingersoll return (rv); 523*e65e5c2dSWyllys Ingersoll } 524