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
genkeypair_pkcs11(KMF_HANDLE_T kmfhandle,char * token,char * keylabel,KMF_KEY_ALG keyAlg,int keylen,KMF_CREDENTIAL * tokencred,KMF_OID * curveoid,KMF_KEY_HANDLE * outPriKey,KMF_KEY_HANDLE * outPubKey)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
genkeypair_file(KMF_HANDLE_T kmfhandle,KMF_KEY_ALG keyAlg,int keylen,KMF_ENCODE_FORMAT fmt,char * outkey,KMF_KEY_HANDLE * outPriKey,KMF_KEY_HANDLE * outPubKey)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
genkeypair_nss(KMF_HANDLE_T kmfhandle,char * token,char * nickname,char * dir,char * prefix,KMF_KEY_ALG keyAlg,int keylen,KMF_CREDENTIAL * tokencred,KMF_OID * curveoid,KMF_KEY_HANDLE * outPriKey,KMF_KEY_HANDLE * outPubKey)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
pk_genkeypair(int argc,char * argv[])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