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 if (kmfrv == KMF_OK) { 121 if (outPriKey != NULL) 122 *outPriKey = prik; 123 if (outPubKey != NULL) 124 *outPubKey = pubk; 125 } 126 127 return (kmfrv); 128 } 129 130 KMF_RETURN 131 genkeypair_file(KMF_HANDLE_T kmfhandle, 132 KMF_KEY_ALG keyAlg, int keylen, KMF_ENCODE_FORMAT fmt, 133 char *outkey, 134 KMF_KEY_HANDLE *outPriKey, KMF_KEY_HANDLE *outPubKey) 135 { 136 KMF_RETURN kmfrv; 137 KMF_KEY_HANDLE pubk, prik; 138 char *fullkeypath = NULL; 139 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL; 140 KMF_ATTRIBUTE attrlist[10]; 141 int numattr = 0; 142 KMF_KEY_ALG keytype; 143 uint32_t keylength; 144 KMF_ENCODE_FORMAT format; 145 146 if (EMPTYSTRING(outkey)) { 147 cryptoerror(LOG_STDERR, 148 gettext("No output file was specified for " 149 "the key\n")); 150 return (PK_ERR_USAGE); 151 } 152 153 fullkeypath = strdup(outkey); 154 if (verify_file(fullkeypath)) { 155 cryptoerror(LOG_STDERR, 156 gettext("Cannot write the indicated output " 157 "key file (%s).\n"), fullkeypath); 158 free(fullkeypath); 159 return (PK_ERR_USAGE); 160 } 161 162 keylength = keylen; /* bits */ 163 keytype = keyAlg; 164 format = fmt; 165 166 kmf_set_attr_at_index(attrlist, numattr, 167 KMF_KEYSTORE_TYPE_ATTR, &kstype, 168 sizeof (kstype)); 169 numattr++; 170 171 kmf_set_attr_at_index(attrlist, numattr, 172 KMF_KEYALG_ATTR, &keytype, 173 sizeof (keytype)); 174 numattr++; 175 176 kmf_set_attr_at_index(attrlist, numattr, 177 KMF_KEYLENGTH_ATTR, &keylength, 178 sizeof (keylength)); 179 numattr++; 180 181 if (fullkeypath != NULL) { 182 kmf_set_attr_at_index(attrlist, numattr, 183 KMF_KEY_FILENAME_ATTR, fullkeypath, 184 strlen(fullkeypath)); 185 numattr++; 186 } 187 188 kmf_set_attr_at_index(attrlist, numattr, 189 KMF_ENCODE_FORMAT_ATTR, &format, 190 sizeof (format)); 191 numattr++; 192 193 kmf_set_attr_at_index(attrlist, numattr, 194 KMF_PRIVKEY_HANDLE_ATTR, &prik, 195 sizeof (KMF_KEY_HANDLE)); 196 numattr++; 197 198 kmf_set_attr_at_index(attrlist, numattr, 199 KMF_PUBKEY_HANDLE_ATTR, &pubk, 200 sizeof (KMF_KEY_HANDLE)); 201 numattr++; 202 203 kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist); 204 if (kmfrv != KMF_OK) { 205 goto cleanup; 206 } 207 208 cleanup: 209 if (fullkeypath != NULL) 210 free(fullkeypath); 211 212 if (kmfrv == KMF_OK) { 213 if (outPriKey != NULL) 214 *outPriKey = prik; 215 if (outPubKey != NULL) 216 *outPubKey = pubk; 217 } 218 219 return (kmfrv); 220 } 221 222 KMF_RETURN 223 genkeypair_nss(KMF_HANDLE_T kmfhandle, 224 char *token, 225 char *nickname, char *dir, char *prefix, 226 KMF_KEY_ALG keyAlg, 227 int keylen, KMF_CREDENTIAL *tokencred, 228 KMF_OID *curveoid, 229 KMF_KEY_HANDLE *outPriKey, KMF_KEY_HANDLE *outPubKey) 230 { 231 KMF_RETURN kmfrv; 232 KMF_KEY_HANDLE pubk, prik; 233 KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 234 KMF_ATTRIBUTE attrlist[16]; 235 int numattr = 0; 236 KMF_KEY_ALG keytype; 237 uint32_t keylength; 238 239 if (token == NULL) 240 token = DEFAULT_NSS_TOKEN; 241 242 kmfrv = configure_nss(kmfhandle, dir, prefix); 243 if (kmfrv != KMF_OK) 244 return (kmfrv); 245 246 keylength = keylen; /* bits */ 247 keytype = keyAlg; 248 249 kmf_set_attr_at_index(attrlist, numattr, 250 KMF_KEYSTORE_TYPE_ATTR, &kstype, 251 sizeof (kstype)); 252 numattr++; 253 254 kmf_set_attr_at_index(attrlist, numattr, 255 KMF_KEYALG_ATTR, &keytype, 256 sizeof (keytype)); 257 numattr++; 258 259 kmf_set_attr_at_index(attrlist, numattr, 260 KMF_KEYLENGTH_ATTR, &keylength, 261 sizeof (keylength)); 262 numattr++; 263 264 if (nickname != NULL) { 265 kmf_set_attr_at_index(attrlist, numattr, 266 KMF_KEYLABEL_ATTR, nickname, 267 strlen(nickname)); 268 numattr++; 269 } 270 271 if (tokencred != NULL && tokencred->cred != NULL) { 272 kmf_set_attr_at_index(attrlist, numattr, 273 KMF_CREDENTIAL_ATTR, tokencred, 274 sizeof (KMF_CREDENTIAL)); 275 numattr++; 276 } 277 278 if (token != NULL) { 279 kmf_set_attr_at_index(attrlist, numattr, 280 KMF_TOKEN_LABEL_ATTR, token, 281 strlen(token)); 282 numattr++; 283 } 284 285 kmf_set_attr_at_index(attrlist, numattr, 286 KMF_PRIVKEY_HANDLE_ATTR, &prik, 287 sizeof (KMF_KEY_HANDLE)); 288 numattr++; 289 290 kmf_set_attr_at_index(attrlist, numattr, 291 KMF_PUBKEY_HANDLE_ATTR, &pubk, 292 sizeof (KMF_KEY_HANDLE)); 293 numattr++; 294 295 if (keytype == KMF_ECDSA && curveoid != NULL) { 296 kmf_set_attr_at_index(attrlist, numattr, 297 KMF_ECC_CURVE_OID_ATTR, curveoid, 298 sizeof (KMF_OID)); 299 numattr++; 300 } 301 302 kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist); 303 if (kmfrv != KMF_OK) { 304 return (kmfrv); 305 } 306 307 if (kmfrv == KMF_OK) { 308 if (outPriKey != NULL) 309 *outPriKey = prik; 310 if (outPubKey != NULL) 311 *outPubKey = pubk; 312 } 313 return (kmfrv); 314 } 315 316 int 317 pk_genkeypair(int argc, char *argv[]) 318 { 319 int rv; 320 int opt; 321 extern int optind_av; 322 extern char *optarg_av; 323 KMF_KEYSTORE_TYPE kstype = 0; 324 char *tokenname = NULL; 325 char *dir = NULL; 326 char *prefix = NULL; 327 char *keytype = PK_DEFAULT_KEYTYPE; 328 int keylen = PK_DEFAULT_KEYLENGTH; 329 char *label = NULL; 330 char *outkey = NULL; 331 char *format = NULL; 332 KMF_HANDLE_T kmfhandle = NULL; 333 KMF_ENCODE_FORMAT fmt = KMF_FORMAT_ASN1; 334 KMF_KEY_ALG keyAlg = KMF_RSA; 335 KMF_ALGORITHM_INDEX sigAlg; 336 KMF_CREDENTIAL tokencred = { NULL, 0 }; 337 KMF_OID *curveoid = NULL; /* ECC */ 338 int y_flag = 0; 339 340 while ((opt = getopt_av(argc, argv, 341 "k:(keystore)s:(subject)n:(nickname)" 342 "T:(token)d:(dir)p:(prefix)t:(keytype)y:(keylen)" 343 "l:(label)K:(outkey)F:(format)C:(curve)" 344 "E(listcurves)")) != EOF) { 345 346 if (opt != 'i' && opt != 'E' && EMPTYSTRING(optarg_av)) 347 return (PK_ERR_USAGE); 348 349 switch (opt) { 350 case 'k': 351 kstype = KS2Int(optarg_av); 352 if (kstype == 0) 353 return (PK_ERR_USAGE); 354 break; 355 case 'l': 356 case 'n': 357 if (label) 358 return (PK_ERR_USAGE); 359 label = optarg_av; 360 break; 361 case 'T': 362 if (tokenname) 363 return (PK_ERR_USAGE); 364 tokenname = optarg_av; 365 break; 366 case 'd': 367 if (dir) 368 return (PK_ERR_USAGE); 369 dir = optarg_av; 370 break; 371 case 'p': 372 if (prefix) 373 return (PK_ERR_USAGE); 374 prefix = optarg_av; 375 break; 376 case 't': 377 keytype = optarg_av; 378 break; 379 case 'y': 380 if (sscanf(optarg_av, "%d", 381 &keylen) != 1) { 382 cryptoerror(LOG_STDERR, 383 gettext("key length must be" 384 "a numeric value (%s)\n"), 385 optarg_av); 386 return (PK_ERR_USAGE); 387 } 388 y_flag++; 389 break; 390 case 'K': 391 if (outkey) 392 return (PK_ERR_USAGE); 393 outkey = optarg_av; 394 break; 395 case 'F': 396 if (format) 397 return (PK_ERR_USAGE); 398 format = optarg_av; 399 break; 400 case 'C': 401 curveoid = ecc_name_to_oid(optarg_av); 402 if (curveoid == NULL) { 403 cryptoerror(LOG_STDERR, 404 gettext( 405 "Unrecognized ECC curve.\n")); 406 return (PK_ERR_USAGE); 407 } 408 break; 409 case 'E': 410 show_ecc_curves(); 411 return (0); 412 default: 413 return (PK_ERR_USAGE); 414 } 415 } 416 417 /* No additional args allowed. */ 418 argc -= optind_av; 419 argv += optind_av; 420 if (argc) { 421 return (PK_ERR_USAGE); 422 } 423 424 if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 425 cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n")); 426 return (PK_ERR_USAGE); 427 } 428 429 /* Assume keystore = PKCS#11 if not specified. */ 430 if (kstype == 0) 431 kstype = KMF_KEYSTORE_PK11TOKEN; 432 433 DIR_OPTION_CHECK(kstype, dir); 434 435 if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) { 436 cryptoerror(LOG_STDERR, 437 gettext("Error parsing format string (%s).\n"), 438 format); 439 return (PK_ERR_USAGE); 440 } 441 442 if (Str2KeyType(keytype, NULL, &keyAlg, &sigAlg) != 0) { 443 cryptoerror(LOG_STDERR, gettext("Unrecognized keytype (%s).\n"), 444 keytype); 445 return (PK_ERR_USAGE); 446 } 447 if (curveoid != NULL && keyAlg != KMF_ECDSA) { 448 cryptoerror(LOG_STDERR, gettext("EC curves are only " 449 "valid for EC keytypes.\n")); 450 return (PK_ERR_USAGE); 451 } 452 if (keyAlg == KMF_ECDSA && curveoid == NULL) { 453 cryptoerror(LOG_STDERR, gettext("A curve must be " 454 "specifed when using EC keys.\n")); 455 return (PK_ERR_USAGE); 456 } 457 if (keyAlg == KMF_ECDSA && kstype == KMF_KEYSTORE_OPENSSL) { 458 (void) fprintf(stderr, gettext("ECC certificates are" 459 "only supported with the pkcs11 and nss keystores\n")); 460 rv = PK_ERR_USAGE; 461 goto end; 462 } 463 /* Adjust default keylength for NSS and DSA */ 464 if (keyAlg == KMF_DSA && kstype == KMF_KEYSTORE_NSS) { 465 /* NSS only allows for 512-1024 bit DSA keys */ 466 if (!y_flag) 467 /* If nothing was given, default to 1024 */ 468 keylen = 1024; 469 else if (keylen > 1024 || keylen < 512) { 470 (void) fprintf(stderr, gettext("NSS keystore only " 471 "supports DSA keylengths of 512 - 1024 bits\n")); 472 rv = PK_ERR_USAGE; 473 goto end; 474 } 475 } 476 477 if (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_PK11TOKEN) { 478 if (label == NULL) { 479 (void) fprintf(stderr, 480 gettext("No key label specified\n")); 481 rv = PK_ERR_USAGE; 482 goto end; 483 } 484 if (tokenname == NULL || !strlen(tokenname)) { 485 if (kstype == KMF_KEYSTORE_NSS) { 486 tokenname = "internal"; 487 } else { 488 tokenname = PK_DEFAULT_PK11TOKEN; 489 } 490 } 491 492 (void) get_token_password(kstype, tokenname, &tokencred); 493 } 494 495 if (kstype == KMF_KEYSTORE_NSS) { 496 if (dir == NULL) 497 dir = PK_DEFAULT_DIRECTORY; 498 499 rv = genkeypair_nss(kmfhandle, 500 tokenname, label, dir, prefix, keyAlg, keylen, 501 &tokencred, curveoid, NULL, NULL); 502 503 } else if (kstype == KMF_KEYSTORE_PK11TOKEN) { 504 rv = genkeypair_pkcs11(kmfhandle, 505 tokenname, label, keyAlg, keylen, 506 &tokencred, curveoid, NULL, NULL); 507 508 } else if (kstype == KMF_KEYSTORE_OPENSSL) { 509 rv = genkeypair_file(kmfhandle, keyAlg, keylen, 510 fmt, outkey, NULL, NULL); 511 } 512 513 if (rv != KMF_OK) 514 display_error(kmfhandle, rv, 515 gettext("Error creating and keypair")); 516 end: 517 if (tokencred.cred != NULL) 518 free(tokencred.cred); 519 520 (void) kmf_finalize(kmfhandle); 521 return (rv); 522 } 523