xref: /illumos-gate/usr/src/cmd/cmd-crypto/pktool/genkey.c (revision b0fe7b8fa79924061f3bdf7f240ea116c2c0b704)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <stdio.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <malloc.h>
32 #include <libgen.h>
33 #include <errno.h>
34 #include <cryptoutil.h>
35 #include <security/cryptoki.h>
36 #include "common.h"
37 #include <kmfapi.h>
38 
39 
40 static KMF_RETURN
41 genkey_nss(KMF_HANDLE_T kmfhandle, char *token, char *dir, char *prefix,
42     char *keylabel, KMF_KEY_ALG keyAlg, int keylen, KMF_CREDENTIAL *tokencred)
43 {
44 	KMF_RETURN kmfrv = KMF_OK;
45 	KMF_CREATESYMKEY_PARAMS csk_params;
46 	KMF_KEY_HANDLE key;
47 
48 	if (keylabel == NULL) {
49 		cryptoerror(LOG_STDERR,
50 		    gettext("A key label must be specified \n"));
51 		return (KMF_ERR_BAD_PARAMETER);
52 	}
53 
54 	kmfrv = configure_nss(kmfhandle, dir, prefix);
55 	if (kmfrv != KMF_OK)
56 		return (kmfrv);
57 
58 	(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
59 	csk_params.kstype = KMF_KEYSTORE_NSS;
60 	csk_params.nssparms.slotlabel = token;
61 	csk_params.keytype = keyAlg;
62 	csk_params.keylength = keylen;
63 	csk_params.keylabel = keylabel;
64 	csk_params.cred.cred = tokencred->cred;
65 	csk_params.cred.credlen = tokencred->credlen;
66 	kmfrv = KMF_CreateSymKey(kmfhandle, &csk_params, &key);
67 
68 	return (kmfrv);
69 }
70 
71 static KMF_RETURN
72 genkey_pkcs11(KMF_HANDLE_T kmfhandle, char *token,
73 	char *keylabel, KMF_KEY_ALG keyAlg, int keylen,
74 	char *senstr, char *extstr, boolean_t print_hex,
75 	KMF_CREDENTIAL *tokencred)
76 {
77 	KMF_RETURN kmfrv = KMF_OK;
78 	KMF_CREATESYMKEY_PARAMS params;
79 	KMF_KEY_HANDLE key;
80 	KMF_RAW_SYM_KEY  *rkey = NULL;
81 	boolean_t 	sensitive = B_FALSE;
82 	boolean_t	not_extractable = B_FALSE;
83 	char *hexstr = NULL;
84 	int  hexstrlen;
85 
86 	if (keylabel == NULL) {
87 		cryptoerror(LOG_STDERR,
88 		    gettext("A key label must be specified \n"));
89 		return (KMF_ERR_BAD_PARAMETER);
90 	}
91 
92 	/* Check the sensitive option value if specified. */
93 	if (senstr != NULL) {
94 		if (tolower(senstr[0]) == 'y')
95 			sensitive = B_TRUE;
96 		else if (tolower(senstr[0]) == 'n')
97 			sensitive = B_FALSE;
98 		else {
99 			cryptoerror(LOG_STDERR,
100 			    gettext("Incorrect sensitive option value.\n"));
101 			return (KMF_ERR_BAD_PARAMETER);
102 		}
103 	}
104 
105 	/* Check the extractable option value if specified. */
106 	if (extstr != NULL) {
107 		if (tolower(extstr[0]) == 'y')
108 			not_extractable = B_FALSE;
109 		else if (tolower(extstr[0]) == 'n')
110 			not_extractable = B_TRUE;
111 		else {
112 			cryptoerror(LOG_STDERR,
113 			    gettext("Incorrect extractable option value.\n"));
114 			return (KMF_ERR_BAD_PARAMETER);
115 		}
116 	}
117 
118 	/* Select a PKCS11 token first */
119 	kmfrv = select_token(kmfhandle, token, FALSE);
120 	if (kmfrv != KMF_OK) {
121 		return (kmfrv);
122 	}
123 
124 	(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
125 	params.kstype = KMF_KEYSTORE_PK11TOKEN;
126 	params.keytype = keyAlg;
127 	params.keylength = keylen; /* bits */
128 	params.keylabel = keylabel;
129 	params.pkcs11parms.sensitive = sensitive;
130 	params.pkcs11parms.not_extractable = not_extractable;
131 	params.cred.cred = tokencred->cred;
132 	params.cred.credlen = tokencred->credlen;
133 	kmfrv = KMF_CreateSymKey(kmfhandle, &params, &key);
134 	if (kmfrv != KMF_OK) {
135 		goto out;
136 	}
137 
138 	if (print_hex) {
139 		if (sensitive == B_TRUE || not_extractable == B_TRUE) {
140 			cryptoerror(LOG_STDERR,
141 			    gettext("Warning: can not reveal the key value "
142 			    "for a sensitive or non-extractable key.\n"));
143 			goto out;
144 		} else {
145 			rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
146 			if (rkey == NULL) {
147 				kmfrv = KMF_ERR_MEMORY;
148 				goto out;
149 			}
150 			(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
151 			kmfrv = KMF_GetSymKeyValue(kmfhandle, &key, rkey);
152 			if (kmfrv != KMF_OK) {
153 				goto out;
154 			}
155 			hexstrlen = 2 * rkey->keydata.len + 1;
156 			hexstr = malloc(hexstrlen);
157 			if (hexstr == NULL) {
158 				kmfrv = KMF_ERR_MEMORY;
159 				goto out;
160 			}
161 
162 			tohexstr(rkey->keydata.val, rkey->keydata.len, hexstr,
163 			    hexstrlen);
164 			(void) printf(gettext("\tKey Value =\"%s\"\n"), hexstr);
165 		}
166 	}
167 
168 out:
169 	KMF_FreeRawSymKey(rkey);
170 
171 	if (hexstr != NULL)
172 		free(hexstr);
173 
174 	return (kmfrv);
175 }
176 
177 
178 static KMF_RETURN
179 genkey_file(KMF_HANDLE_T kmfhandle, KMF_KEY_ALG keyAlg, int keylen, char *dir,
180     char *outkey, boolean_t print_hex)
181 {
182 	KMF_RETURN kmfrv = KMF_OK;
183 	KMF_CREATESYMKEY_PARAMS csk_params;
184 	KMF_KEY_HANDLE key;
185 	KMF_RAW_SYM_KEY *rkey = NULL;
186 	char *hexstr = NULL;
187 	int hexstrlen;
188 
189 	if (EMPTYSTRING(outkey)) {
190 		cryptoerror(LOG_STDERR,
191 		    gettext("No output key file was specified for the key\n"));
192 		return (KMF_ERR_BAD_PARAMETER);
193 	}
194 
195 	if (verify_file(outkey)) {
196 		cryptoerror(LOG_STDERR,
197 			gettext("Cannot write the indicated output "
198 				"key file (%s).\n"), outkey);
199 		return (KMF_ERR_BAD_PARAMETER);
200 	}
201 
202 	(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
203 	csk_params.kstype = KMF_KEYSTORE_OPENSSL;
204 	csk_params.keytype = keyAlg;
205 	csk_params.keylength = keylen;
206 	csk_params.cred.cred = NULL;
207 	csk_params.cred.credlen = 0;
208 	csk_params.sslparms.dirpath = (dir == NULL) ? "." : dir;
209 	csk_params.sslparms.keyfile = outkey;
210 
211 	kmfrv = KMF_CreateSymKey(kmfhandle, &csk_params, &key);
212 	if (kmfrv != KMF_OK) {
213 		goto out;
214 	}
215 
216 	if (print_hex) {
217 		rkey = malloc(sizeof (KMF_RAW_SYM_KEY));
218 		if (rkey == NULL) {
219 			kmfrv = KMF_ERR_MEMORY;
220 			goto out;
221 		}
222 		(void) memset(rkey, 0, sizeof (KMF_RAW_SYM_KEY));
223 		kmfrv = KMF_GetSymKeyValue(kmfhandle, &key, rkey);
224 		if (kmfrv != KMF_OK) {
225 			goto out;
226 		}
227 
228 		hexstrlen = 2 * rkey->keydata.len + 1;
229 		hexstr = malloc(hexstrlen);
230 		if (hexstr == NULL) {
231 			kmfrv = KMF_ERR_MEMORY;
232 			goto out;
233 		}
234 		tohexstr(rkey->keydata.val, rkey->keydata.len, hexstr,
235 		    hexstrlen);
236 		(void) printf(gettext("\tKey Value =\"%s\"\n"), hexstr);
237 	}
238 
239 out:
240 	KMF_FreeRawSymKey(rkey);
241 
242 	if (hexstr != NULL)
243 		free(hexstr);
244 
245 	return (kmfrv);
246 }
247 
248 int
249 pk_genkey(int argc, char *argv[])
250 {
251 	int rv;
252 	int opt;
253 	extern int	optind_av;
254 	extern char	*optarg_av;
255 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
256 	char *tokenname = NULL;
257 	char *dir = NULL;
258 	char *prefix = NULL;
259 	char *keytype = "AES";
260 	char *keylenstr = NULL;
261 	int keylen = 0;
262 	char *keylabel = NULL;
263 	char *outkey = NULL;
264 	char *senstr = NULL;
265 	char *extstr = NULL;
266 	char *printstr = NULL;
267 	KMF_HANDLE_T kmfhandle = NULL;
268 	KMF_KEY_ALG keyAlg = KMF_AES;
269 	boolean_t print_hex = B_FALSE;
270 	KMF_CREDENTIAL tokencred = {NULL, 0};
271 
272 	while ((opt = getopt_av(argc, argv,
273 		"k:(keystore)l:(label)T:(token)d:(dir)p:(prefix)"
274 		"t:(keytype)y:(keylen)K:(outkey)P:(print)"
275 		"s:(sensitive)e:(extractable)")) != EOF) {
276 		if (EMPTYSTRING(optarg_av))
277 			return (PK_ERR_USAGE);
278 		switch (opt) {
279 			case 'k':
280 				kstype = KS2Int(optarg_av);
281 				if (kstype == 0)
282 					return (PK_ERR_USAGE);
283 				break;
284 			case 'l':
285 				if (keylabel)
286 					return (PK_ERR_USAGE);
287 				keylabel = optarg_av;
288 				break;
289 			case 'T':
290 				if (tokenname)
291 					return (PK_ERR_USAGE);
292 				tokenname = optarg_av;
293 				break;
294 			case 'd':
295 				if (dir)
296 					return (PK_ERR_USAGE);
297 				dir = optarg_av;
298 				break;
299 			case 'p':
300 				if (prefix)
301 					return (PK_ERR_USAGE);
302 				prefix = optarg_av;
303 				break;
304 			case 't':
305 				keytype = optarg_av;
306 				break;
307 			case 'y':
308 				if (keylenstr)
309 					return (PK_ERR_USAGE);
310 				keylenstr = optarg_av;
311 				break;
312 			case 'K':
313 				if (outkey)
314 					return (PK_ERR_USAGE);
315 				outkey = optarg_av;
316 				break;
317 			case 'P':
318 				if (printstr)
319 					return (PK_ERR_USAGE);
320 				printstr = optarg_av;
321 				break;
322 			case 's':
323 				if (senstr)
324 					return (PK_ERR_USAGE);
325 				senstr = optarg_av;
326 				break;
327 			case 'e':
328 				if (extstr)
329 					return (PK_ERR_USAGE);
330 				extstr = optarg_av;
331 				break;
332 			default:
333 				return (PK_ERR_USAGE);
334 		}
335 	}
336 
337 	/* No additional args allowed. */
338 	argc -= optind_av;
339 	argv += optind_av;
340 	if (argc) {
341 		return (PK_ERR_USAGE);
342 	}
343 
344 	/* Check keytype. If not specified, default to AES */
345 	if (keytype != NULL && Str2SymKeyType(keytype, &keyAlg) != 0) {
346 		cryptoerror(LOG_STDERR, gettext("Unrecognized keytype(%s).\n"),
347 			keytype);
348 		return (PK_ERR_USAGE);
349 	}
350 
351 	/*
352 	 * Check and set the key length.
353 	 * - For DES and 3DES, the key size are fixed. Ingore the keylen
354 	 *   option, even if it is specified.
355 	 * - For AES and ARCFOUR, if keylen is not specified, default to
356 	 *   128 bits.
357 	 */
358 	if (keyAlg == KMF_DES)
359 		keylen = 64;  /* fixed size; ignore input */
360 	else if (keyAlg == KMF_DES3)
361 		keylen = 192; /* fixed size; ignore input */
362 	else /* AES, ARCFOUR, or GENERIC SECRET */ {
363 		if (keylenstr == NULL) {
364 			cryptoerror(LOG_STDERR,
365 				gettext("Key length must be specified for "
366 				"AES, ARCFOUR or GENERIC symmetric keys.\n"));
367 			return (PK_ERR_USAGE);
368 		}
369 		if (sscanf(keylenstr, "%d", &keylen) != 1) {
370 			cryptoerror(LOG_STDERR,
371 				gettext("Unrecognized key length (%s).\n"),
372 				keytype);
373 			return (PK_ERR_USAGE);
374 		}
375 		if (keylen == 0 || (keylen % 8) != 0) {
376 			cryptoerror(LOG_STDERR,
377 				gettext("Key length bitlength must be a "
378 					"multiple of 8.\n"));
379 			return (PK_ERR_USAGE);
380 		}
381 	}
382 
383 	/* check the print option */
384 	if (printstr != NULL) {
385 		if (kstype == KMF_KEYSTORE_NSS) {
386 			cryptoerror(LOG_STDERR,
387 			    gettext("The print option does not apply "
388 			    "to the NSS keystore.\n"));
389 			return (PK_ERR_USAGE);
390 		}
391 
392 		if (tolower(printstr[0]) == 'y')
393 			print_hex = B_TRUE;
394 		else if (tolower(printstr[0]) == 'n')
395 			print_hex = B_FALSE;
396 		else {
397 			cryptoerror(LOG_STDERR,
398 			    gettext("Incorrect print option value.\n"));
399 			return (PK_ERR_USAGE);
400 		}
401 	}
402 
403 	/* check the sensitive and extractable options */
404 	if ((senstr != NULL || extstr != NULL) &&
405 	    (kstype == KMF_KEYSTORE_NSS || kstype == KMF_KEYSTORE_OPENSSL)) {
406 		cryptoerror(LOG_STDERR,
407 		    gettext("The sensitive or extractable option applies "
408 		    "to the PKCS11 keystore only.\n"));
409 		return (PK_ERR_USAGE);
410 	}
411 
412 	if (kstype == KMF_KEYSTORE_PK11TOKEN && tokenname == NULL) {
413 		tokenname = PK_DEFAULT_PK11TOKEN;
414 	} else if (kstype == KMF_KEYSTORE_NSS && tokenname == NULL) {
415 		tokenname = DEFAULT_NSS_TOKEN;
416 	}
417 
418 	if (kstype == KMF_KEYSTORE_PK11TOKEN || kstype == KMF_KEYSTORE_NSS)
419 		(void) get_token_password(kstype, tokenname, &tokencred);
420 
421 	if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
422 		cryptoerror(LOG_STDERR, gettext("Error initializing KMF\n"));
423 		goto end;
424 	}
425 
426 	if (kstype == KMF_KEYSTORE_NSS) {
427 		rv = genkey_nss(kmfhandle, tokenname, dir, prefix,
428 		    keylabel, keyAlg, keylen, &tokencred);
429 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
430 		rv = genkey_file(kmfhandle, keyAlg, keylen, dir, outkey,
431 		    print_hex);
432 	} else {
433 		rv = genkey_pkcs11(kmfhandle, tokenname, keylabel, keyAlg,
434 		    keylen, senstr, extstr, print_hex, &tokencred);
435 	}
436 
437 end:
438 	if (rv != KMF_OK)
439 		display_error(kmfhandle, rv,
440 			gettext("Error generating key"));
441 
442 	if (tokencred.cred != NULL)
443 		free(tokencred.cred);
444 
445 	(void) KMF_Finalize(kmfhandle);
446 	if (rv != KMF_OK)
447 		return (PK_ERR_USAGE);
448 
449 	return (0);
450 }
451