xref: /illumos-gate/usr/src/cmd/cmd-crypto/pktool/import.c (revision 843e19887f64dde75055cf8842fc4db2171eff45)
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 /*
29  * This file implements the import operation for this tool.
30  * The basic flow of the process is to decrypt the PKCS#12
31  * input file if it has a password, parse the elements in
32  * the file, find the soft token, log into it, import the
33  * PKCS#11 objects into the soft token, and log out.
34  */
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include <errno.h>
41 #include <fcntl.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include "common.h"
45 
46 #include <kmfapi.h>
47 
48 static KMF_RETURN
49 pk_import_pk12_files(KMF_HANDLE_T kmfhandle, KMF_CREDENTIAL *cred,
50 	char *outfile, char *certfile, char *keyfile,
51 	char *dir, char *keydir, KMF_ENCODE_FORMAT outformat)
52 {
53 	KMF_RETURN rv = KMF_OK;
54 	KMF_DATA *certs = NULL;
55 	KMF_RAW_KEY_DATA *keys = NULL;
56 	int ncerts = 0;
57 	int nkeys = 0;
58 	int i;
59 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
60 	KMF_ATTRIBUTE attrlist[16];
61 	int numattr = 0;
62 
63 	rv = kmf_import_objects(kmfhandle, outfile, cred,
64 	    &certs, &ncerts, &keys, &nkeys);
65 
66 	if (rv == KMF_OK) {
67 		(void) printf(gettext("Found %d certificate(s) and %d "
68 		    "key(s) in %s\n"), ncerts, nkeys, outfile);
69 	}
70 
71 	if (rv == KMF_OK && ncerts > 0) {
72 		char newcertfile[MAXPATHLEN];
73 
74 		kmf_set_attr_at_index(attrlist, numattr,
75 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
76 		numattr++;
77 
78 		if (dir != NULL) {
79 			kmf_set_attr_at_index(attrlist, numattr,
80 			    KMF_DIRPATH_ATTR, dir, strlen(dir));
81 			numattr++;
82 		}
83 
84 		kmf_set_attr_at_index(attrlist, numattr,
85 		    KMF_ENCODE_FORMAT_ATTR, &outformat, sizeof (outformat));
86 		numattr++;
87 
88 		for (i = 0; rv == KMF_OK && i < ncerts; i++) {
89 			int num = numattr;
90 
91 			/*
92 			 * If storing more than 1 cert, gotta change
93 			 * the name so we don't overwrite the previous one.
94 			 * Just append a _# to the name.
95 			 */
96 			if (i > 0) {
97 				(void) snprintf(newcertfile,
98 				    sizeof (newcertfile), "%s_%d", certfile, i);
99 
100 				kmf_set_attr_at_index(attrlist, num,
101 				    KMF_CERT_FILENAME_ATTR, newcertfile,
102 				    strlen(newcertfile));
103 				num++;
104 			} else {
105 				kmf_set_attr_at_index(attrlist, num,
106 				    KMF_CERT_FILENAME_ATTR, certfile,
107 				    strlen(certfile));
108 				num++;
109 			}
110 
111 			kmf_set_attr_at_index(attrlist, num,
112 			    KMF_CERT_DATA_ATTR, &certs[i], sizeof (KMF_DATA));
113 			num++;
114 			rv = kmf_store_cert(kmfhandle, num, attrlist);
115 		}
116 	}
117 	if (rv == KMF_OK && nkeys > 0) {
118 		char newkeyfile[MAXPATHLEN];
119 
120 		numattr = 0;
121 
122 		kmf_set_attr_at_index(attrlist, numattr,
123 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
124 		    sizeof (kstype));
125 		numattr++;
126 
127 		if (keydir != NULL) {
128 			kmf_set_attr_at_index(attrlist, numattr,
129 			    KMF_DIRPATH_ATTR, keydir,
130 			    strlen(keydir));
131 			numattr++;
132 		}
133 
134 		kmf_set_attr_at_index(attrlist, numattr,
135 		    KMF_ENCODE_FORMAT_ATTR, &outformat,
136 		    sizeof (outformat));
137 		numattr++;
138 
139 		if (cred != NULL && cred->credlen > 0) {
140 			kmf_set_attr_at_index(attrlist, numattr,
141 			    KMF_CREDENTIAL_ATTR, cred,
142 			    sizeof (KMF_CREDENTIAL));
143 			numattr++;
144 		}
145 
146 		/* The order of certificates and keys should match */
147 		for (i = 0; rv == KMF_OK && i < nkeys; i++) {
148 			int num = numattr;
149 
150 			if (i > 0) {
151 				(void) snprintf(newkeyfile,
152 				    sizeof (newkeyfile), "%s_%d", keyfile, i);
153 
154 				kmf_set_attr_at_index(attrlist, num,
155 				    KMF_KEY_FILENAME_ATTR, newkeyfile,
156 				    strlen(newkeyfile));
157 				num++;
158 			} else {
159 				kmf_set_attr_at_index(attrlist, num,
160 				    KMF_KEY_FILENAME_ATTR, keyfile,
161 				    strlen(keyfile));
162 				num++;
163 			}
164 
165 			kmf_set_attr_at_index(attrlist, num,
166 			    KMF_CERT_DATA_ATTR, &certs[i],
167 			    sizeof (KMF_DATA));
168 			num++;
169 
170 			kmf_set_attr_at_index(attrlist, num,
171 			    KMF_RAW_KEY_ATTR, &keys[i],
172 			    sizeof (KMF_RAW_KEY_DATA));
173 			num++;
174 
175 			rv = kmf_store_key(kmfhandle, num, attrlist);
176 		}
177 	}
178 	/*
179 	 * Cleanup memory.
180 	 */
181 	if (certs) {
182 		for (i = 0; i < ncerts; i++)
183 			kmf_free_data(&certs[i]);
184 		free(certs);
185 	}
186 	if (keys) {
187 		for (i = 0; i < nkeys; i++)
188 			kmf_free_raw_key(&keys[i]);
189 		free(keys);
190 	}
191 
192 
193 	return (rv);
194 }
195 
196 
197 static KMF_RETURN
198 pk_import_pk12_nss(
199 	KMF_HANDLE_T kmfhandle, KMF_CREDENTIAL *kmfcred,
200 	KMF_CREDENTIAL *tokencred,
201 	char *token_spec, char *dir, char *prefix,
202 	char *nickname, char *trustflags, char *filename)
203 {
204 	KMF_RETURN rv = KMF_OK;
205 	KMF_DATA *certs = NULL;
206 	KMF_RAW_KEY_DATA *keys = NULL;
207 	int ncerts = 0;
208 	int nkeys = 0;
209 	int i;
210 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
211 	KMF_ATTRIBUTE attrlist[16];
212 	int numattr = 0;
213 
214 	rv = configure_nss(kmfhandle, dir, prefix);
215 	if (rv != KMF_OK)
216 		return (rv);
217 
218 	rv = kmf_import_objects(kmfhandle, filename, kmfcred,
219 	    &certs, &ncerts, &keys, &nkeys);
220 
221 	if (rv == KMF_OK)
222 		(void) printf(gettext("Found %d certificate(s) and %d "
223 		    "key(s) in %s\n"), ncerts, nkeys, filename);
224 
225 	if (rv == KMF_OK) {
226 		kmf_set_attr_at_index(attrlist, numattr,
227 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
228 		numattr++;
229 
230 		if (token_spec != NULL) {
231 			kmf_set_attr_at_index(attrlist, numattr,
232 			    KMF_TOKEN_LABEL_ATTR, token_spec,
233 			    strlen(token_spec));
234 			numattr++;
235 		}
236 
237 		if (trustflags != NULL) {
238 			kmf_set_attr_at_index(attrlist, numattr,
239 			    KMF_TRUSTFLAG_ATTR, trustflags,
240 			    strlen(trustflags));
241 			numattr++;
242 		}
243 
244 		for (i = 0; rv == KMF_OK && i < ncerts; i++) {
245 			int num = numattr;
246 
247 			if (i == 0 && nickname != NULL) {
248 				kmf_set_attr_at_index(attrlist, num,
249 				    KMF_CERT_LABEL_ATTR, nickname,
250 				    strlen(nickname));
251 				num++;
252 			}
253 
254 			kmf_set_attr_at_index(attrlist, num,
255 			    KMF_CERT_DATA_ATTR, &certs[i], sizeof (KMF_DATA));
256 			num++;
257 			rv = kmf_store_cert(kmfhandle, num, attrlist);
258 		}
259 		if (rv != KMF_OK) {
260 			display_error(kmfhandle, rv,
261 			    gettext("Error storing certificate in NSS token"));
262 		}
263 	}
264 
265 	if (rv == KMF_OK) {
266 		numattr = 0;
267 
268 		kmf_set_attr_at_index(attrlist, numattr,
269 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
270 		    sizeof (kstype));
271 		numattr++;
272 
273 		if (token_spec != NULL) {
274 			kmf_set_attr_at_index(attrlist, numattr,
275 			    KMF_TOKEN_LABEL_ATTR, token_spec,
276 			    strlen(token_spec));
277 			numattr++;
278 		}
279 
280 		if (nickname != NULL) {
281 			kmf_set_attr_at_index(attrlist, numattr,
282 			    KMF_KEYLABEL_ATTR, nickname,
283 			    strlen(nickname));
284 			numattr++;
285 		}
286 
287 		if (tokencred->credlen > 0) {
288 			kmf_set_attr_at_index(attrlist, numattr,
289 			    KMF_CREDENTIAL_ATTR, tokencred,
290 			    sizeof (KMF_CREDENTIAL));
291 			numattr++;
292 		}
293 
294 		/* The order of certificates and keys should match */
295 		for (i = 0; i < nkeys; i++) {
296 			int num = numattr;
297 
298 			kmf_set_attr_at_index(attrlist, num,
299 			    KMF_CERT_DATA_ATTR, &certs[i],
300 			    sizeof (KMF_DATA));
301 			num++;
302 
303 			kmf_set_attr_at_index(attrlist, num,
304 			    KMF_RAW_KEY_ATTR, &keys[i],
305 			    sizeof (KMF_RAW_KEY_DATA));
306 			num++;
307 
308 			rv = kmf_store_key(kmfhandle, num, attrlist);
309 		}
310 	}
311 
312 	/*
313 	 * Cleanup memory.
314 	 */
315 	if (certs) {
316 		for (i = 0; i < ncerts; i++)
317 			kmf_free_data(&certs[i]);
318 		free(certs);
319 	}
320 	if (keys) {
321 		for (i = 0; i < nkeys; i++)
322 			kmf_free_raw_key(&keys[i]);
323 		free(keys);
324 	}
325 
326 	return (rv);
327 }
328 
329 static KMF_RETURN
330 pk_import_cert(
331 	KMF_HANDLE_T kmfhandle,
332 	KMF_KEYSTORE_TYPE kstype,
333 	char *label, char *token_spec, char *filename,
334 	char *dir, char *prefix, char *trustflags)
335 {
336 	KMF_RETURN rv = KMF_OK;
337 	KMF_ATTRIBUTE attrlist[32];
338 	int i = 0;
339 
340 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
341 		rv = select_token(kmfhandle, token_spec, FALSE);
342 	} else if (kstype == KMF_KEYSTORE_NSS) {
343 		rv = configure_nss(kmfhandle, dir, prefix);
344 	}
345 	if (rv != KMF_OK)
346 		return (rv);
347 
348 	kmf_set_attr_at_index(attrlist, i,
349 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (KMF_KEYSTORE_TYPE));
350 	i++;
351 
352 	kmf_set_attr_at_index(attrlist, i, KMF_CERT_FILENAME_ATTR,
353 	    filename, strlen(filename));
354 	i++;
355 
356 	if (label != NULL) {
357 		kmf_set_attr_at_index(attrlist, i, KMF_CERT_LABEL_ATTR,
358 		    label, strlen(label));
359 		i++;
360 	}
361 
362 	if (kstype == KMF_KEYSTORE_NSS) {
363 		if (trustflags != NULL) {
364 			kmf_set_attr_at_index(attrlist, i, KMF_TRUSTFLAG_ATTR,
365 			    trustflags, strlen(trustflags));
366 			i++;
367 		}
368 
369 		if (token_spec != NULL) {
370 			kmf_set_attr_at_index(attrlist, i,
371 			    KMF_TOKEN_LABEL_ATTR,
372 			    token_spec, strlen(token_spec));
373 			i++;
374 		}
375 	}
376 
377 	rv = kmf_import_cert(kmfhandle, i, attrlist);
378 	return (rv);
379 }
380 
381 static KMF_RETURN
382 pk_import_file_crl(void *kmfhandle,
383 	char *infile,
384 	char *outfile,
385 	char *outdir,
386 	KMF_ENCODE_FORMAT outfmt)
387 {
388 	int numattr = 0;
389 	KMF_ATTRIBUTE attrlist[8];
390 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
391 
392 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
393 	    &kstype, sizeof (kstype));
394 	numattr++;
395 	if (infile) {
396 		kmf_set_attr_at_index(attrlist, numattr,
397 		    KMF_CRL_FILENAME_ATTR, infile, strlen(infile));
398 		numattr++;
399 	}
400 	if (outdir) {
401 		kmf_set_attr_at_index(attrlist, numattr,
402 		    KMF_DIRPATH_ATTR, outdir, strlen(outdir));
403 		numattr++;
404 	}
405 	if (outfile) {
406 		kmf_set_attr_at_index(attrlist, numattr,
407 		    KMF_CRL_OUTFILE_ATTR, outfile, strlen(outfile));
408 		numattr++;
409 	}
410 	kmf_set_attr_at_index(attrlist, numattr,
411 	    KMF_ENCODE_FORMAT_ATTR, &outfmt, sizeof (outfmt));
412 	numattr++;
413 
414 	return (kmf_import_crl(kmfhandle, numattr, attrlist));
415 }
416 
417 static KMF_RETURN
418 pk_import_nss_crl(void *kmfhandle,
419 	boolean_t verify_crl_flag,
420 	char *infile,
421 	char *outdir,
422 	char *prefix)
423 {
424 	KMF_RETURN rv;
425 	int numattr = 0;
426 	KMF_ATTRIBUTE attrlist[4];
427 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
428 
429 	rv = configure_nss(kmfhandle, outdir, prefix);
430 	if (rv != KMF_OK)
431 		return (rv);
432 
433 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
434 	    &kstype, sizeof (kstype));
435 	numattr++;
436 	if (infile) {
437 		kmf_set_attr_at_index(attrlist, numattr, KMF_CRL_FILENAME_ATTR,
438 		    infile, strlen(infile));
439 		numattr++;
440 	}
441 	kmf_set_attr_at_index(attrlist, numattr, KMF_CRL_CHECK_ATTR,
442 	    &verify_crl_flag, sizeof (verify_crl_flag));
443 	numattr++;
444 
445 	return (kmf_import_crl(kmfhandle, numattr, attrlist));
446 
447 }
448 
449 static KMF_RETURN
450 pk_import_pk12_pk11(
451 	KMF_HANDLE_T kmfhandle,
452 	KMF_CREDENTIAL *p12cred,
453 	KMF_CREDENTIAL *tokencred,
454 	char *label, char *token_spec,
455 	char *filename)
456 {
457 	KMF_RETURN rv = KMF_OK;
458 	KMF_DATA *certs = NULL;
459 	KMF_RAW_KEY_DATA *keys = NULL;
460 	int ncerts = 0;
461 	int nkeys = 0;
462 	int i;
463 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
464 	KMF_ATTRIBUTE attrlist[16];
465 	int numattr = 0;
466 
467 	rv = select_token(kmfhandle, token_spec, FALSE);
468 
469 	if (rv != KMF_OK) {
470 		return (rv);
471 	}
472 
473 	rv = kmf_import_objects(kmfhandle, filename, p12cred,
474 	    &certs, &ncerts, &keys, &nkeys);
475 
476 	if (rv == KMF_OK) {
477 
478 		kmf_set_attr_at_index(attrlist, numattr,
479 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
480 		    sizeof (kstype));
481 		numattr++;
482 
483 		if (label != NULL) {
484 			kmf_set_attr_at_index(attrlist, numattr,
485 			    KMF_KEYLABEL_ATTR, label,
486 			    strlen(label));
487 			numattr++;
488 		}
489 
490 		if (tokencred != NULL && tokencred->credlen > 0) {
491 			kmf_set_attr_at_index(attrlist, numattr,
492 			    KMF_CREDENTIAL_ATTR, tokencred,
493 			    sizeof (KMF_CREDENTIAL));
494 			numattr++;
495 		}
496 
497 		/* The order of certificates and keys should match */
498 		for (i = 0; i < nkeys; i++) {
499 			int num = numattr;
500 
501 			kmf_set_attr_at_index(attrlist, num,
502 			    KMF_CERT_DATA_ATTR, &certs[i],
503 			    sizeof (KMF_DATA));
504 			num++;
505 
506 			kmf_set_attr_at_index(attrlist, num,
507 			    KMF_RAW_KEY_ATTR, &keys[i],
508 			    sizeof (KMF_RAW_KEY_DATA));
509 			num++;
510 
511 			rv = kmf_store_key(kmfhandle, num, attrlist);
512 
513 		}
514 	}
515 
516 	if (rv == KMF_OK) {
517 
518 		(void) printf(gettext("Found %d certificate(s) and %d "
519 		    "key(s) in %s\n"), ncerts, nkeys, filename);
520 		numattr = 0;
521 		kmf_set_attr_at_index(attrlist, numattr,
522 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
523 		numattr++;
524 
525 		for (i = 0; rv == KMF_OK && i < ncerts; i++) {
526 			int num = numattr;
527 
528 			if (i == 0 && label != NULL) {
529 				kmf_set_attr_at_index(attrlist, num,
530 				    KMF_CERT_LABEL_ATTR, label, strlen(label));
531 				num++;
532 			}
533 
534 			kmf_set_attr_at_index(attrlist, num,
535 			    KMF_CERT_DATA_ATTR, &certs[i], sizeof (KMF_DATA));
536 			num++;
537 
538 			rv = kmf_store_cert(kmfhandle, num, attrlist);
539 		}
540 	}
541 
542 	/*
543 	 * Cleanup memory.
544 	 */
545 	if (certs) {
546 		for (i = 0; i < ncerts; i++)
547 			kmf_free_data(&certs[i]);
548 		free(certs);
549 	}
550 	if (keys) {
551 		for (i = 0; i < nkeys; i++)
552 			kmf_free_raw_key(&keys[i]);
553 		free(keys);
554 	}
555 
556 	return (rv);
557 }
558 
559 /*ARGSUSED*/
560 static KMF_RETURN
561 pk_import_keys(KMF_HANDLE_T kmfhandle,
562 	KMF_KEYSTORE_TYPE kstype, char *token_spec,
563 	KMF_CREDENTIAL *cred, char *filename,
564 	char *label, char *senstr, char *extstr)
565 {
566 	KMF_RETURN rv = KMF_OK;
567 	KMF_ATTRIBUTE attrlist[16];
568 	KMF_KEYSTORE_TYPE fileks = KMF_KEYSTORE_OPENSSL;
569 	int numattr = 0;
570 	KMF_KEY_HANDLE key;
571 	KMF_RAW_KEY_DATA rawkey;
572 	KMF_KEY_CLASS class = KMF_ASYM_PRI;
573 	int numkeys = 1;
574 
575 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
576 		rv = select_token(kmfhandle, token_spec, FALSE);
577 	}
578 	if (rv != KMF_OK)
579 		return (rv);
580 	/*
581 	 * First, set up to read the keyfile using the FILE plugin
582 	 * mechanisms.
583 	 */
584 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
585 	    &fileks, sizeof (fileks));
586 	numattr++;
587 
588 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
589 	    &numkeys, sizeof (numkeys));
590 	numattr++;
591 
592 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
593 	    &key, sizeof (key));
594 	numattr++;
595 
596 	kmf_set_attr_at_index(attrlist, numattr, KMF_RAW_KEY_ATTR,
597 	    &rawkey, sizeof (rawkey));
598 	numattr++;
599 
600 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
601 	    &class, sizeof (class));
602 	numattr++;
603 
604 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
605 	    filename, strlen(filename));
606 	numattr++;
607 
608 	rv = kmf_find_key(kmfhandle, numattr, attrlist);
609 	if (rv == KMF_OK) {
610 		numattr = 0;
611 
612 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
613 		    &kstype, sizeof (kstype));
614 		numattr++;
615 
616 		if (cred != NULL && cred->credlen > 0) {
617 			kmf_set_attr_at_index(attrlist, numattr,
618 			    KMF_CREDENTIAL_ATTR, cred, sizeof (KMF_CREDENTIAL));
619 			numattr++;
620 		}
621 
622 		if (label != NULL) {
623 			kmf_set_attr_at_index(attrlist, numattr,
624 			    KMF_KEYLABEL_ATTR, label, strlen(label));
625 			numattr++;
626 		}
627 
628 		kmf_set_attr_at_index(attrlist, numattr,
629 		    KMF_RAW_KEY_ATTR, &rawkey, sizeof (rawkey));
630 		numattr++;
631 
632 		rv = kmf_store_key(kmfhandle, numattr, attrlist);
633 		if (rv == KMF_OK) {
634 			(void) printf(gettext("Importing %d keys\n"), numkeys);
635 		}
636 
637 		kmf_free_kmf_key(kmfhandle, &key);
638 		kmf_free_raw_key(&rawkey);
639 	} else {
640 		cryptoerror(LOG_STDERR,
641 		    gettext("Failed to load key from file (%s)\n"),
642 		    filename);
643 	}
644 	return (rv);
645 }
646 
647 static KMF_RETURN
648 pk_import_rawkey(KMF_HANDLE_T kmfhandle,
649 	KMF_KEYSTORE_TYPE kstype, char *token,
650 	KMF_CREDENTIAL *cred,
651 	char *filename, char *label, KMF_KEY_ALG keyAlg,
652 	char *senstr, char *extstr)
653 {
654 	KMF_RETURN rv = KMF_OK;
655 	KMF_ATTRIBUTE attrlist[16];
656 	int numattr = 0;
657 	uint32_t keylen;
658 	boolean_t sensitive = B_FALSE;
659 	boolean_t not_extractable = B_FALSE;
660 	KMF_DATA keydata = {NULL, 0};
661 	KMF_KEY_HANDLE rawkey;
662 
663 	rv = kmf_read_input_file(kmfhandle, filename, &keydata);
664 	if (rv != KMF_OK)
665 		return (rv);
666 
667 	rv = select_token(kmfhandle, token, FALSE);
668 
669 	if (rv != KMF_OK) {
670 		return (rv);
671 	}
672 	if (senstr != NULL) {
673 		if (tolower(senstr[0]) == 'y')
674 			sensitive = B_TRUE;
675 		else if (tolower(senstr[0]) == 'n')
676 			sensitive = B_FALSE;
677 		else {
678 			cryptoerror(LOG_STDERR,
679 			    gettext("Incorrect sensitive option value.\n"));
680 			return (KMF_ERR_BAD_PARAMETER);
681 		}
682 	}
683 
684 	if (extstr != NULL) {
685 		if (tolower(extstr[0]) == 'y')
686 			not_extractable = B_FALSE;
687 		else if (tolower(extstr[0]) == 'n')
688 			not_extractable = B_TRUE;
689 		else {
690 			cryptoerror(LOG_STDERR,
691 			    gettext("Incorrect extractable option value.\n"));
692 			return (KMF_ERR_BAD_PARAMETER);
693 		}
694 	}
695 	kmf_set_attr_at_index(attrlist, numattr,
696 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
697 	numattr++;
698 
699 	kmf_set_attr_at_index(attrlist, numattr,
700 	    KMF_KEY_HANDLE_ATTR, &rawkey, sizeof (rawkey));
701 	numattr++;
702 
703 	kmf_set_attr_at_index(attrlist, numattr,
704 	    KMF_KEYALG_ATTR, &keyAlg, sizeof (KMF_KEY_ALG));
705 	numattr++;
706 
707 	kmf_set_attr_at_index(attrlist, numattr,
708 	    KMF_KEY_DATA_ATTR, keydata.Data, keydata.Length);
709 	numattr++;
710 
711 	/* Key length is given in bits not bytes */
712 	keylen = keydata.Length * 8;
713 	kmf_set_attr_at_index(attrlist, numattr,
714 	    KMF_KEYLENGTH_ATTR, &keylen, sizeof (keydata.Length));
715 	numattr++;
716 
717 	kmf_set_attr_at_index(attrlist, numattr,
718 	    KMF_SENSITIVE_BOOL_ATTR, &sensitive, sizeof (sensitive));
719 	numattr++;
720 
721 	kmf_set_attr_at_index(attrlist, numattr,
722 	    KMF_NON_EXTRACTABLE_BOOL_ATTR, &not_extractable,
723 	    sizeof (not_extractable));
724 	numattr++;
725 
726 	if (label != NULL) {
727 		kmf_set_attr_at_index(attrlist, numattr,
728 		    KMF_KEYLABEL_ATTR, label, strlen(label));
729 		numattr++;
730 	}
731 	if (cred != NULL && cred->credlen > 0) {
732 		kmf_set_attr_at_index(attrlist, numattr,
733 		    KMF_CREDENTIAL_ATTR, cred, sizeof (KMF_CREDENTIAL));
734 		numattr++;
735 	}
736 	rv = kmf_create_sym_key(kmfhandle, numattr, attrlist);
737 
738 	return (rv);
739 }
740 
741 /*
742  * Import objects from into KMF repositories.
743  */
744 int
745 pk_import(int argc, char *argv[])
746 {
747 	int		opt;
748 	extern int	optind_av;
749 	extern char	*optarg_av;
750 	char		*token_spec = NULL;
751 	char		*filename = NULL;
752 	char		*keyfile = NULL;
753 	char		*certfile = NULL;
754 	char		*crlfile = NULL;
755 	char		*label = NULL;
756 	char		*dir = NULL;
757 	char		*keydir = NULL;
758 	char		*prefix = NULL;
759 	char		*trustflags = NULL;
760 	char		*verify_crl = NULL;
761 	char		*keytype = "generic";
762 	char		*senstr = NULL;
763 	char		*extstr = NULL;
764 	boolean_t	verify_crl_flag = B_FALSE;
765 	int		oclass = 0;
766 	KMF_KEYSTORE_TYPE	kstype = 0;
767 	KMF_ENCODE_FORMAT	kfmt = 0;
768 	KMF_ENCODE_FORMAT	okfmt = KMF_FORMAT_ASN1;
769 	KMF_RETURN		rv = KMF_OK;
770 	KMF_CREDENTIAL	pk12cred = { NULL, 0 };
771 	KMF_CREDENTIAL	tokencred = { NULL, 0 };
772 	KMF_HANDLE_T	kmfhandle = NULL;
773 	KMF_KEY_ALG	keyAlg = KMF_GENERIC_SECRET;
774 
775 	/* Parse command line options.  Do NOT i18n/l10n. */
776 	while ((opt = getopt_av(argc, argv,
777 	    "T:(token)i:(infile)"
778 	    "k:(keystore)y:(objtype)"
779 	    "d:(dir)p:(prefix)"
780 	    "n:(certlabel)N:(label)"
781 	    "K:(outkey)c:(outcert)"
782 	    "v:(verifycrl)l:(outcrl)"
783 	    "E:(keytype)s:(sensitive)x:(extractable)"
784 	    "t:(trust)D:(keydir)F:(outformat)")) != EOF) {
785 		if (EMPTYSTRING(optarg_av))
786 			return (PK_ERR_USAGE);
787 		switch (opt) {
788 		case 'T':	/* token specifier */
789 			if (token_spec)
790 				return (PK_ERR_USAGE);
791 			token_spec = optarg_av;
792 			break;
793 		case 'c':	/* output cert file name */
794 			if (certfile)
795 				return (PK_ERR_USAGE);
796 			certfile = optarg_av;
797 			break;
798 		case 'l':	/* output CRL file name */
799 			if (crlfile)
800 				return (PK_ERR_USAGE);
801 			crlfile = optarg_av;
802 			break;
803 		case 'K':	/* output key file name */
804 			if (keyfile)
805 				return (PK_ERR_USAGE);
806 			keyfile = optarg_av;
807 			break;
808 		case 'i':	/* input file name */
809 			if (filename)
810 				return (PK_ERR_USAGE);
811 			filename = optarg_av;
812 			break;
813 		case 'k':
814 			kstype = KS2Int(optarg_av);
815 			if (kstype == 0)
816 				return (PK_ERR_USAGE);
817 			break;
818 		case 'y':
819 			oclass = OT2Int(optarg_av);
820 			if (oclass == -1)
821 				return (PK_ERR_USAGE);
822 			break;
823 		case 'd':
824 			dir = optarg_av;
825 			break;
826 		case 'D':
827 			keydir = optarg_av;
828 			break;
829 		case 'p':
830 			if (prefix)
831 				return (PK_ERR_USAGE);
832 			prefix = optarg_av;
833 			break;
834 		case 'n':
835 		case 'N':
836 			if (label)
837 				return (PK_ERR_USAGE);
838 			label = optarg_av;
839 			break;
840 		case 'F':
841 			okfmt = Str2Format(optarg_av);
842 			if (okfmt == KMF_FORMAT_UNDEF)
843 				return (PK_ERR_USAGE);
844 			break;
845 		case 't':
846 			if (trustflags)
847 				return (PK_ERR_USAGE);
848 			trustflags = optarg_av;
849 			break;
850 		case 'v':
851 			verify_crl = optarg_av;
852 			if (tolower(verify_crl[0]) == 'y')
853 				verify_crl_flag = B_TRUE;
854 			else if (tolower(verify_crl[0]) == 'n')
855 				verify_crl_flag = B_FALSE;
856 			else
857 				return (PK_ERR_USAGE);
858 			break;
859 		case 'E':
860 			keytype = optarg_av;
861 			break;
862 		case 's':
863 			if (senstr)
864 				return (PK_ERR_USAGE);
865 			senstr = optarg_av;
866 			break;
867 		case 'x':
868 			if (extstr)
869 				return (PK_ERR_USAGE);
870 			extstr = optarg_av;
871 			break;
872 		default:
873 			return (PK_ERR_USAGE);
874 			break;
875 		}
876 	}
877 
878 	/* Assume keystore = PKCS#11 if not specified */
879 	if (kstype == 0)
880 		kstype = KMF_KEYSTORE_PK11TOKEN;
881 
882 	/* Filename arg is required. */
883 	if (EMPTYSTRING(filename)) {
884 		cryptoerror(LOG_STDERR, gettext("The 'infile' parameter"
885 		    "is required for the import operation.\n"));
886 		return (PK_ERR_USAGE);
887 	}
888 
889 	/* No additional args allowed. */
890 	argc -= optind_av;
891 	argv += optind_av;
892 	if (argc)
893 		return (PK_ERR_USAGE);
894 
895 	/* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
896 	if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
897 	    kstype != KMF_KEYSTORE_PK11TOKEN) {
898 
899 		(void) fprintf(stderr, gettext("The objtype parameter "
900 		    "is only relevant if keystore=pkcs11\n"));
901 		return (PK_ERR_USAGE);
902 	}
903 
904 	/*
905 	 * You must specify a certlabel (cert label) when importing
906 	 * into NSS or PKCS#11.
907 	 */
908 	if (kstype == KMF_KEYSTORE_NSS &&
909 	    (oclass != PK_CRL_OBJ) && EMPTYSTRING(label)) {
910 		cryptoerror(LOG_STDERR, gettext("The 'label' argument "
911 		    "is required for this operation\n"));
912 		return (PK_ERR_USAGE);
913 	}
914 
915 	if ((rv = kmf_get_file_format(filename, &kfmt)) != KMF_OK) {
916 		/*
917 		 * Allow for raw key data to be imported.
918 		 */
919 		if (rv == KMF_ERR_ENCODING) {
920 			rv = KMF_OK;
921 			kfmt = KMF_FORMAT_RAWKEY;
922 			/*
923 			 * Set the object class only if it was not
924 			 * given on the command line or if it was
925 			 * specified as a symmetric key object.
926 			 */
927 			if (oclass == 0 || (oclass & PK_SYMKEY_OBJ)) {
928 				oclass = PK_SYMKEY_OBJ;
929 			} else {
930 				cryptoerror(LOG_STDERR, gettext(
931 				    "The input file does not contain the "
932 				    "object type indicated on command "
933 				    "line."));
934 				return (KMF_ERR_BAD_PARAMETER);
935 			}
936 		} else {
937 			cryptoerror(LOG_STDERR,
938 			    gettext("File format not recognized."));
939 			return (rv);
940 		}
941 	}
942 
943 	/* Check parameters for raw key import operation */
944 	if (kfmt == KMF_FORMAT_RAWKEY) {
945 		if (keytype != NULL &&
946 		    Str2SymKeyType(keytype, &keyAlg) != 0) {
947 			cryptoerror(LOG_STDERR,
948 			    gettext("Unrecognized keytype(%s).\n"), keytype);
949 			return (PK_ERR_USAGE);
950 		}
951 		if (senstr != NULL && extstr != NULL &&
952 		    kstype != KMF_KEYSTORE_PK11TOKEN) {
953 			cryptoerror(LOG_STDERR,
954 			    gettext("The sensitive or extractable option "
955 			    "applies only when importing a key from a file "
956 			    "into a PKCS#11 keystore.\n"));
957 			return (PK_ERR_USAGE);
958 		}
959 	}
960 
961 	/* If no objtype was given, treat it as a certificate */
962 	if (oclass == 0 && (kfmt == KMF_FORMAT_ASN1 ||
963 	    kfmt == KMF_FORMAT_PEM))
964 		oclass = PK_CERT_OBJ;
965 
966 	if (kstype == KMF_KEYSTORE_NSS) {
967 		if (oclass == PK_CRL_OBJ &&
968 		    (kfmt != KMF_FORMAT_ASN1 && kfmt != KMF_FORMAT_PEM)) {
969 			cryptoerror(LOG_STDERR, gettext(
970 			    "CRL data can only be imported as DER or "
971 			    "PEM format"));
972 			return (PK_ERR_USAGE);
973 		}
974 
975 		if (oclass == PK_CERT_OBJ &&
976 		    (kfmt != KMF_FORMAT_ASN1 && kfmt != KMF_FORMAT_PEM)) {
977 			cryptoerror(LOG_STDERR, gettext(
978 			    "Certificates can only be imported as DER or "
979 			    "PEM format"));
980 			return (PK_ERR_USAGE);
981 		}
982 
983 		/* we do not import private keys except in PKCS12 bundles */
984 		if (oclass & (PK_PRIVATE_OBJ | PK_PRIKEY_OBJ)) {
985 			cryptoerror(LOG_STDERR, gettext(
986 			    "Private key data can only be imported as part "
987 			    "of a PKCS12 file.\n"));
988 			return (PK_ERR_USAGE);
989 		}
990 	}
991 
992 	if (kstype == KMF_KEYSTORE_OPENSSL && oclass != PK_CRL_OBJ) {
993 		if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) {
994 			cryptoerror(LOG_STDERR, gettext(
995 			    "The 'outkey' and 'outcert' parameters "
996 			    "are required for the import operation "
997 			    "when the 'file' keystore is used.\n"));
998 			return (PK_ERR_USAGE);
999 		}
1000 	}
1001 
1002 	if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec))
1003 		token_spec = PK_DEFAULT_PK11TOKEN;
1004 	else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec))
1005 		token_spec = DEFAULT_NSS_TOKEN;
1006 
1007 	if (kfmt == KMF_FORMAT_PKCS12) {
1008 		(void) get_pk12_password(&pk12cred);
1009 	}
1010 
1011 	if ((kfmt == KMF_FORMAT_PKCS12 || kfmt == KMF_FORMAT_RAWKEY ||
1012 	    (kfmt == KMF_FORMAT_PEM && (oclass & PK_KEY_OBJ))) &&
1013 	    (kstype == KMF_KEYSTORE_PK11TOKEN || kstype == KMF_KEYSTORE_NSS)) {
1014 		(void) get_token_password(kstype, token_spec, &tokencred);
1015 	}
1016 
1017 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
1018 		cryptoerror(LOG_STDERR, gettext("Error initializing "
1019 		    "KMF: 0x%02x\n"), rv);
1020 		goto end;
1021 	}
1022 
1023 	switch (kstype) {
1024 		case KMF_KEYSTORE_PK11TOKEN:
1025 			if (kfmt == KMF_FORMAT_PKCS12)
1026 				rv = pk_import_pk12_pk11(
1027 				    kmfhandle, &pk12cred,
1028 				    &tokencred, label,
1029 				    token_spec, filename);
1030 			else if (oclass == PK_CERT_OBJ)
1031 				rv = pk_import_cert(
1032 				    kmfhandle, kstype,
1033 				    label, token_spec,
1034 				    filename,
1035 				    NULL, NULL, NULL);
1036 			else if (oclass == PK_CRL_OBJ)
1037 				rv = pk_import_file_crl(
1038 				    kmfhandle, filename,
1039 				    crlfile, dir, okfmt);
1040 			else if (kfmt == KMF_FORMAT_RAWKEY &&
1041 			    oclass == PK_SYMKEY_OBJ) {
1042 				rv = pk_import_rawkey(kmfhandle,
1043 				    kstype, token_spec, &tokencred,
1044 				    filename, label,
1045 				    keyAlg, senstr, extstr);
1046 			} else if (kfmt == KMF_FORMAT_PEM ||
1047 			    kfmt == KMF_FORMAT_PEM_KEYPAIR) {
1048 				rv = pk_import_keys(kmfhandle,
1049 				    kstype, token_spec, &tokencred,
1050 				    filename, label, senstr, extstr);
1051 			} else {
1052 				rv = PK_ERR_USAGE;
1053 			}
1054 			break;
1055 		case KMF_KEYSTORE_NSS:
1056 			if (dir == NULL)
1057 				dir = PK_DEFAULT_DIRECTORY;
1058 			if (kfmt == KMF_FORMAT_PKCS12)
1059 				rv = pk_import_pk12_nss(
1060 				    kmfhandle, &pk12cred,
1061 				    &tokencred,
1062 				    token_spec, dir, prefix,
1063 				    label, trustflags, filename);
1064 			else if (oclass == PK_CERT_OBJ) {
1065 				rv = pk_import_cert(
1066 				    kmfhandle, kstype,
1067 				    label, token_spec,
1068 				    filename, dir, prefix, trustflags);
1069 			} else if (oclass == PK_CRL_OBJ) {
1070 				rv = pk_import_nss_crl(
1071 				    kmfhandle, verify_crl_flag,
1072 				    filename, dir, prefix);
1073 			}
1074 			break;
1075 		case KMF_KEYSTORE_OPENSSL:
1076 			if (kfmt == KMF_FORMAT_PKCS12)
1077 				rv = pk_import_pk12_files(
1078 				    kmfhandle, &pk12cred,
1079 				    filename, certfile, keyfile,
1080 				    dir, keydir, okfmt);
1081 			else if (oclass == PK_CRL_OBJ) {
1082 				rv = pk_import_file_crl(
1083 				    kmfhandle, filename,
1084 				    crlfile, dir, okfmt);
1085 			} else
1086 				/*
1087 				 * It doesn't make sense to import anything
1088 				 * else for the files plugin.
1089 				 */
1090 				return (PK_ERR_USAGE);
1091 			break;
1092 		default:
1093 			rv = PK_ERR_USAGE;
1094 			break;
1095 	}
1096 
1097 end:
1098 	if (rv != KMF_OK)
1099 		display_error(kmfhandle, rv,
1100 		    gettext("Error importing objects"));
1101 
1102 	if (tokencred.cred != NULL)
1103 		free(tokencred.cred);
1104 
1105 	if (pk12cred.cred != NULL)
1106 		free(pk12cred.cred);
1107 
1108 	(void) kmf_finalize(kmfhandle);
1109 
1110 	if (rv != KMF_OK)
1111 		return (PK_ERR_USAGE);
1112 
1113 	return (0);
1114 }
1115