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