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 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
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)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
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)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
pk_genkeypair(int argc,char * argv[])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