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