xref: /illumos-gate/usr/src/cmd/cmd-crypto/pktool/import.c (revision 160abee025ef30c34521b981edd40ffcaab560aa)
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 #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 	int i = 0;
380 
381 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
382 		rv = select_token(kmfhandle, token_spec, FALSE);
383 	} else if (kstype == KMF_KEYSTORE_NSS) {
384 		rv = configure_nss(kmfhandle, dir, prefix);
385 	}
386 	if (rv != KMF_OK)
387 		return (rv);
388 
389 	kmf_set_attr_at_index(attrlist, i,
390 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (KMF_KEYSTORE_TYPE));
391 	i++;
392 
393 	kmf_set_attr_at_index(attrlist, i, KMF_CERT_FILENAME_ATTR,
394 	    filename, strlen(filename));
395 	i++;
396 
397 	if (label != NULL) {
398 		kmf_set_attr_at_index(attrlist, i, KMF_CERT_LABEL_ATTR,
399 		    label, strlen(label));
400 		i++;
401 	}
402 
403 	if (kstype == KMF_KEYSTORE_NSS) {
404 		if (trustflags != NULL) {
405 			kmf_set_attr_at_index(attrlist, i, KMF_TRUSTFLAG_ATTR,
406 			    trustflags, strlen(trustflags));
407 			i++;
408 		}
409 
410 		if (token_spec != NULL) {
411 			kmf_set_attr_at_index(attrlist, i,
412 			    KMF_TOKEN_LABEL_ATTR,
413 			    token_spec, strlen(token_spec));
414 			i++;
415 		}
416 	}
417 
418 	rv = kmf_import_cert(kmfhandle, i, attrlist);
419 	return (rv);
420 }
421 
422 static KMF_RETURN
423 pk_import_file_crl(void *kmfhandle,
424 	char *infile,
425 	char *outfile,
426 	char *outdir,
427 	KMF_ENCODE_FORMAT outfmt)
428 {
429 	int numattr = 0;
430 	KMF_ATTRIBUTE attrlist[8];
431 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
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,
438 		    KMF_CRL_FILENAME_ATTR, infile, strlen(infile));
439 		numattr++;
440 	}
441 	if (outdir) {
442 		kmf_set_attr_at_index(attrlist, numattr,
443 		    KMF_DIRPATH_ATTR, outdir, strlen(outdir));
444 		numattr++;
445 	}
446 	if (outfile) {
447 		kmf_set_attr_at_index(attrlist, numattr,
448 		    KMF_CRL_OUTFILE_ATTR, outfile, strlen(outfile));
449 		numattr++;
450 	}
451 	kmf_set_attr_at_index(attrlist, numattr,
452 	    KMF_ENCODE_FORMAT_ATTR, &outfmt, sizeof (outfmt));
453 	numattr++;
454 
455 	return (kmf_import_crl(kmfhandle, numattr, attrlist));
456 }
457 
458 static KMF_RETURN
459 pk_import_nss_crl(void *kmfhandle,
460 	boolean_t verify_crl_flag,
461 	char *infile,
462 	char *outdir,
463 	char *prefix)
464 {
465 	KMF_RETURN rv;
466 	int numattr = 0;
467 	KMF_ATTRIBUTE attrlist[4];
468 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
469 
470 	rv = configure_nss(kmfhandle, outdir, prefix);
471 	if (rv != KMF_OK)
472 		return (rv);
473 
474 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
475 	    &kstype, sizeof (kstype));
476 	numattr++;
477 	if (infile) {
478 		kmf_set_attr_at_index(attrlist, numattr, KMF_CRL_FILENAME_ATTR,
479 		    infile, strlen(infile));
480 		numattr++;
481 	}
482 	kmf_set_attr_at_index(attrlist, numattr, KMF_CRL_CHECK_ATTR,
483 	    &verify_crl_flag, sizeof (verify_crl_flag));
484 	numattr++;
485 
486 	return (kmf_import_crl(kmfhandle, numattr, attrlist));
487 
488 }
489 
490 static KMF_RETURN
491 pk_import_pk12_pk11(
492 	KMF_HANDLE_T kmfhandle,
493 	KMF_CREDENTIAL *p12cred,
494 	KMF_CREDENTIAL *tokencred,
495 	char *label, char *token_spec,
496 	char *filename)
497 {
498 	KMF_RETURN rv = KMF_OK;
499 	KMF_X509_DER_CERT *certs = NULL;
500 	KMF_RAW_KEY_DATA *keys = NULL;
501 	int ncerts = 0;
502 	int nkeys = 0;
503 	int i;
504 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
505 	KMF_ATTRIBUTE *attrlist = NULL;
506 	int numattr = 0;
507 
508 	rv = select_token(kmfhandle, token_spec, FALSE);
509 
510 	if (rv != KMF_OK) {
511 		return (rv);
512 	}
513 
514 	rv = kmf_import_objects(kmfhandle, filename, p12cred,
515 	    &certs, &ncerts, &keys, &nkeys);
516 
517 	if (rv == KMF_OK) {
518 		NEW_ATTRLIST(attrlist, (3 + (2 * nkeys)));
519 
520 		kmf_set_attr_at_index(attrlist, numattr,
521 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
522 		    sizeof (kstype));
523 		numattr++;
524 
525 		if (label != NULL) {
526 			kmf_set_attr_at_index(attrlist, numattr,
527 			    KMF_KEYLABEL_ATTR, label,
528 			    strlen(label));
529 			numattr++;
530 		}
531 
532 		if (tokencred != NULL && tokencred->credlen > 0) {
533 			kmf_set_attr_at_index(attrlist, numattr,
534 			    KMF_CREDENTIAL_ATTR, tokencred,
535 			    sizeof (KMF_CREDENTIAL));
536 			numattr++;
537 		}
538 
539 		/* The order of certificates and keys should match */
540 		for (i = 0; i < nkeys; i++) {
541 			int num = numattr;
542 
543 			if (i < ncerts) {
544 				kmf_set_attr_at_index(attrlist, num,
545 				    KMF_CERT_DATA_ATTR, &certs[i].certificate,
546 				    sizeof (KMF_DATA));
547 				num++;
548 			}
549 
550 			kmf_set_attr_at_index(attrlist, num,
551 			    KMF_RAW_KEY_ATTR, &keys[i],
552 			    sizeof (KMF_RAW_KEY_DATA));
553 			num++;
554 
555 			rv = kmf_store_key(kmfhandle, num, attrlist);
556 
557 		}
558 		free(attrlist);
559 	}
560 
561 	if (rv == KMF_OK) {
562 		numattr = 0;
563 		NEW_ATTRLIST(attrlist, (1 + (2 * ncerts)));
564 
565 		(void) printf(gettext("Found %d certificate(s) and %d "
566 		    "key(s) in %s\n"), ncerts, nkeys, filename);
567 
568 		kmf_set_attr_at_index(attrlist, numattr,
569 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
570 		numattr++;
571 
572 		for (i = 0; rv == KMF_OK && i < ncerts; i++) {
573 			int num = numattr;
574 			if (certs[i].kmf_private.label != NULL) {
575 				kmf_set_attr_at_index(attrlist, num,
576 				    KMF_CERT_LABEL_ATTR,
577 				    certs[i].kmf_private.label,
578 				    strlen(certs[i].kmf_private.label));
579 				num++;
580 			} else if (i == 0 && label != NULL) {
581 				kmf_set_attr_at_index(attrlist, num,
582 				    KMF_CERT_LABEL_ATTR, label, strlen(label));
583 				num++;
584 			}
585 
586 			kmf_set_attr_at_index(attrlist, num,
587 			    KMF_CERT_DATA_ATTR, &certs[i].certificate,
588 			    sizeof (KMF_DATA));
589 			num++;
590 
591 			rv = kmf_store_cert(kmfhandle, num, attrlist);
592 		}
593 		free(attrlist);
594 	}
595 
596 end:
597 	/*
598 	 * Cleanup memory.
599 	 */
600 	if (certs) {
601 		for (i = 0; i < ncerts; i++)
602 			kmf_free_kmf_cert(kmfhandle, &certs[i]);
603 		free(certs);
604 	}
605 	if (keys) {
606 		for (i = 0; i < nkeys; i++)
607 			kmf_free_raw_key(&keys[i]);
608 		free(keys);
609 	}
610 
611 	return (rv);
612 }
613 
614 /*ARGSUSED*/
615 static KMF_RETURN
616 pk_import_keys(KMF_HANDLE_T kmfhandle,
617 	KMF_KEYSTORE_TYPE kstype, char *token_spec,
618 	KMF_CREDENTIAL *cred, char *filename,
619 	char *label, char *senstr, char *extstr)
620 {
621 	KMF_RETURN rv = KMF_OK;
622 	KMF_ATTRIBUTE attrlist[16];
623 	KMF_KEYSTORE_TYPE fileks = KMF_KEYSTORE_OPENSSL;
624 	int numattr = 0;
625 	KMF_KEY_HANDLE key;
626 	KMF_RAW_KEY_DATA rawkey;
627 	KMF_KEY_CLASS class = KMF_ASYM_PRI;
628 	int numkeys = 1;
629 
630 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
631 		rv = select_token(kmfhandle, token_spec, FALSE);
632 	}
633 	if (rv != KMF_OK)
634 		return (rv);
635 	/*
636 	 * First, set up to read the keyfile using the FILE plugin
637 	 * mechanisms.
638 	 */
639 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
640 	    &fileks, sizeof (fileks));
641 	numattr++;
642 
643 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
644 	    &numkeys, sizeof (numkeys));
645 	numattr++;
646 
647 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
648 	    &key, sizeof (key));
649 	numattr++;
650 
651 	kmf_set_attr_at_index(attrlist, numattr, KMF_RAW_KEY_ATTR,
652 	    &rawkey, sizeof (rawkey));
653 	numattr++;
654 
655 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
656 	    &class, sizeof (class));
657 	numattr++;
658 
659 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
660 	    filename, strlen(filename));
661 	numattr++;
662 
663 	rv = kmf_find_key(kmfhandle, numattr, attrlist);
664 	if (rv == KMF_OK) {
665 		numattr = 0;
666 
667 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
668 		    &kstype, sizeof (kstype));
669 		numattr++;
670 
671 		if (cred != NULL && cred->credlen > 0) {
672 			kmf_set_attr_at_index(attrlist, numattr,
673 			    KMF_CREDENTIAL_ATTR, cred, sizeof (KMF_CREDENTIAL));
674 			numattr++;
675 		}
676 
677 		if (label != NULL) {
678 			kmf_set_attr_at_index(attrlist, numattr,
679 			    KMF_KEYLABEL_ATTR, label, strlen(label));
680 			numattr++;
681 		}
682 
683 		kmf_set_attr_at_index(attrlist, numattr,
684 		    KMF_RAW_KEY_ATTR, &rawkey, sizeof (rawkey));
685 		numattr++;
686 
687 		rv = kmf_store_key(kmfhandle, numattr, attrlist);
688 		if (rv == KMF_OK) {
689 			(void) printf(gettext("Importing %d keys\n"), numkeys);
690 		}
691 
692 		kmf_free_kmf_key(kmfhandle, &key);
693 		kmf_free_raw_key(&rawkey);
694 	} else {
695 		cryptoerror(LOG_STDERR,
696 		    gettext("Failed to load key from file (%s)\n"),
697 		    filename);
698 	}
699 	return (rv);
700 }
701 
702 static KMF_RETURN
703 pk_import_rawkey(KMF_HANDLE_T kmfhandle,
704 	KMF_KEYSTORE_TYPE kstype, char *token,
705 	KMF_CREDENTIAL *cred,
706 	char *filename, char *label, KMF_KEY_ALG keyAlg,
707 	char *senstr, char *extstr)
708 {
709 	KMF_RETURN rv = KMF_OK;
710 	KMF_ATTRIBUTE attrlist[16];
711 	int numattr = 0;
712 	uint32_t keylen;
713 	boolean_t sensitive = B_FALSE;
714 	boolean_t not_extractable = B_FALSE;
715 	KMF_DATA keydata = {NULL, 0};
716 	KMF_KEY_HANDLE rawkey;
717 
718 	rv = kmf_read_input_file(kmfhandle, filename, &keydata);
719 	if (rv != KMF_OK)
720 		return (rv);
721 
722 	rv = select_token(kmfhandle, token, FALSE);
723 
724 	if (rv != KMF_OK) {
725 		return (rv);
726 	}
727 	if (senstr != NULL) {
728 		if (tolower(senstr[0]) == 'y')
729 			sensitive = B_TRUE;
730 		else if (tolower(senstr[0]) == 'n')
731 			sensitive = B_FALSE;
732 		else {
733 			cryptoerror(LOG_STDERR,
734 			    gettext("Incorrect sensitive option value.\n"));
735 			return (KMF_ERR_BAD_PARAMETER);
736 		}
737 	}
738 
739 	if (extstr != NULL) {
740 		if (tolower(extstr[0]) == 'y')
741 			not_extractable = B_FALSE;
742 		else if (tolower(extstr[0]) == 'n')
743 			not_extractable = B_TRUE;
744 		else {
745 			cryptoerror(LOG_STDERR,
746 			    gettext("Incorrect extractable option value.\n"));
747 			return (KMF_ERR_BAD_PARAMETER);
748 		}
749 	}
750 	kmf_set_attr_at_index(attrlist, numattr,
751 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
752 	numattr++;
753 
754 	kmf_set_attr_at_index(attrlist, numattr,
755 	    KMF_KEY_HANDLE_ATTR, &rawkey, sizeof (rawkey));
756 	numattr++;
757 
758 	kmf_set_attr_at_index(attrlist, numattr,
759 	    KMF_KEYALG_ATTR, &keyAlg, sizeof (KMF_KEY_ALG));
760 	numattr++;
761 
762 	kmf_set_attr_at_index(attrlist, numattr,
763 	    KMF_KEY_DATA_ATTR, keydata.Data, keydata.Length);
764 	numattr++;
765 
766 	/* Key length is given in bits not bytes */
767 	keylen = keydata.Length * 8;
768 	kmf_set_attr_at_index(attrlist, numattr,
769 	    KMF_KEYLENGTH_ATTR, &keylen, sizeof (keydata.Length));
770 	numattr++;
771 
772 	kmf_set_attr_at_index(attrlist, numattr,
773 	    KMF_SENSITIVE_BOOL_ATTR, &sensitive, sizeof (sensitive));
774 	numattr++;
775 
776 	kmf_set_attr_at_index(attrlist, numattr,
777 	    KMF_NON_EXTRACTABLE_BOOL_ATTR, &not_extractable,
778 	    sizeof (not_extractable));
779 	numattr++;
780 
781 	if (label != NULL) {
782 		kmf_set_attr_at_index(attrlist, numattr,
783 		    KMF_KEYLABEL_ATTR, label, strlen(label));
784 		numattr++;
785 	}
786 	if (cred != NULL && cred->credlen > 0) {
787 		kmf_set_attr_at_index(attrlist, numattr,
788 		    KMF_CREDENTIAL_ATTR, cred, sizeof (KMF_CREDENTIAL));
789 		numattr++;
790 	}
791 	rv = kmf_create_sym_key(kmfhandle, numattr, attrlist);
792 
793 	return (rv);
794 }
795 
796 /*
797  * Import objects from into KMF repositories.
798  */
799 int
800 pk_import(int argc, char *argv[])
801 {
802 	int		opt;
803 	extern int	optind_av;
804 	extern char	*optarg_av;
805 	char		*token_spec = NULL;
806 	char		*filename = NULL;
807 	char		*keyfile = NULL;
808 	char		*certfile = NULL;
809 	char		*crlfile = NULL;
810 	char		*label = NULL;
811 	char		*dir = NULL;
812 	char		*keydir = NULL;
813 	char		*prefix = NULL;
814 	char		*trustflags = NULL;
815 	char		*verify_crl = NULL;
816 	char		*keytype = "generic";
817 	char		*senstr = NULL;
818 	char		*extstr = NULL;
819 	boolean_t	verify_crl_flag = B_FALSE;
820 	int		oclass = 0;
821 	KMF_KEYSTORE_TYPE	kstype = 0;
822 	KMF_ENCODE_FORMAT	kfmt = 0;
823 	KMF_ENCODE_FORMAT	okfmt = KMF_FORMAT_ASN1;
824 	KMF_RETURN		rv = KMF_OK;
825 	KMF_CREDENTIAL	pk12cred = { NULL, 0 };
826 	KMF_CREDENTIAL	tokencred = { NULL, 0 };
827 	KMF_HANDLE_T	kmfhandle = NULL;
828 	KMF_KEY_ALG	keyAlg = KMF_GENERIC_SECRET;
829 
830 	/* Parse command line options.  Do NOT i18n/l10n. */
831 	while ((opt = getopt_av(argc, argv,
832 	    "T:(token)i:(infile)"
833 	    "k:(keystore)y:(objtype)"
834 	    "d:(dir)p:(prefix)"
835 	    "n:(certlabel)N:(label)"
836 	    "K:(outkey)c:(outcert)"
837 	    "v:(verifycrl)l:(outcrl)"
838 	    "E:(keytype)s:(sensitive)x:(extractable)"
839 	    "t:(trust)D:(keydir)F:(outformat)")) != EOF) {
840 		if (EMPTYSTRING(optarg_av))
841 			return (PK_ERR_USAGE);
842 		switch (opt) {
843 		case 'T':	/* token specifier */
844 			if (token_spec)
845 				return (PK_ERR_USAGE);
846 			token_spec = optarg_av;
847 			break;
848 		case 'c':	/* output cert file name */
849 			if (certfile)
850 				return (PK_ERR_USAGE);
851 			certfile = optarg_av;
852 			break;
853 		case 'l':	/* output CRL file name */
854 			if (crlfile)
855 				return (PK_ERR_USAGE);
856 			crlfile = optarg_av;
857 			break;
858 		case 'K':	/* output key file name */
859 			if (keyfile)
860 				return (PK_ERR_USAGE);
861 			keyfile = optarg_av;
862 			break;
863 		case 'i':	/* input file name */
864 			if (filename)
865 				return (PK_ERR_USAGE);
866 			filename = optarg_av;
867 			break;
868 		case 'k':
869 			kstype = KS2Int(optarg_av);
870 			if (kstype == 0)
871 				return (PK_ERR_USAGE);
872 			break;
873 		case 'y':
874 			oclass = OT2Int(optarg_av);
875 			if (oclass == -1)
876 				return (PK_ERR_USAGE);
877 			break;
878 		case 'd':
879 			dir = optarg_av;
880 			break;
881 		case 'D':
882 			keydir = optarg_av;
883 			break;
884 		case 'p':
885 			if (prefix)
886 				return (PK_ERR_USAGE);
887 			prefix = optarg_av;
888 			break;
889 		case 'n':
890 		case 'N':
891 			if (label)
892 				return (PK_ERR_USAGE);
893 			label = optarg_av;
894 			break;
895 		case 'F':
896 			okfmt = Str2Format(optarg_av);
897 			if (okfmt == KMF_FORMAT_UNDEF)
898 				return (PK_ERR_USAGE);
899 			break;
900 		case 't':
901 			if (trustflags)
902 				return (PK_ERR_USAGE);
903 			trustflags = optarg_av;
904 			break;
905 		case 'v':
906 			verify_crl = optarg_av;
907 			if (tolower(verify_crl[0]) == 'y')
908 				verify_crl_flag = B_TRUE;
909 			else if (tolower(verify_crl[0]) == 'n')
910 				verify_crl_flag = B_FALSE;
911 			else
912 				return (PK_ERR_USAGE);
913 			break;
914 		case 'E':
915 			keytype = optarg_av;
916 			break;
917 		case 's':
918 			if (senstr)
919 				return (PK_ERR_USAGE);
920 			senstr = optarg_av;
921 			break;
922 		case 'x':
923 			if (extstr)
924 				return (PK_ERR_USAGE);
925 			extstr = optarg_av;
926 			break;
927 		default:
928 			return (PK_ERR_USAGE);
929 			break;
930 		}
931 	}
932 
933 	/* Assume keystore = PKCS#11 if not specified */
934 	if (kstype == 0)
935 		kstype = KMF_KEYSTORE_PK11TOKEN;
936 
937 	/* Filename arg is required. */
938 	if (EMPTYSTRING(filename)) {
939 		cryptoerror(LOG_STDERR, gettext("The 'infile' parameter"
940 		    "is required for the import operation.\n"));
941 		return (PK_ERR_USAGE);
942 	}
943 
944 	/* No additional args allowed. */
945 	argc -= optind_av;
946 	argv += optind_av;
947 	if (argc)
948 		return (PK_ERR_USAGE);
949 
950 	/* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
951 	if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
952 	    kstype != KMF_KEYSTORE_PK11TOKEN) {
953 
954 		(void) fprintf(stderr, gettext("The objtype parameter "
955 		    "is only relevant if keystore=pkcs11\n"));
956 		return (PK_ERR_USAGE);
957 	}
958 
959 	/*
960 	 * You must specify a certlabel (cert label) when importing
961 	 * into NSS or PKCS#11.
962 	 */
963 	if (kstype == KMF_KEYSTORE_NSS &&
964 	    (oclass != PK_CRL_OBJ) && EMPTYSTRING(label)) {
965 		cryptoerror(LOG_STDERR, gettext("The 'label' argument "
966 		    "is required for this operation\n"));
967 		return (PK_ERR_USAGE);
968 	}
969 
970 	if ((rv = kmf_get_file_format(filename, &kfmt)) != KMF_OK) {
971 		/*
972 		 * Allow for raw key data to be imported.
973 		 */
974 		if (rv == KMF_ERR_ENCODING) {
975 			rv = KMF_OK;
976 			kfmt = KMF_FORMAT_RAWKEY;
977 			/*
978 			 * Set the object class only if it was not
979 			 * given on the command line or if it was
980 			 * specified as a symmetric key object.
981 			 */
982 			if (oclass == 0 || (oclass & PK_SYMKEY_OBJ)) {
983 				oclass = PK_SYMKEY_OBJ;
984 			} else {
985 				cryptoerror(LOG_STDERR, gettext(
986 				    "The input file does not contain the "
987 				    "object type indicated on command "
988 				    "line."));
989 				return (KMF_ERR_BAD_PARAMETER);
990 			}
991 		} else {
992 			cryptoerror(LOG_STDERR,
993 			    gettext("File format not recognized."));
994 			return (rv);
995 		}
996 	}
997 
998 	/* Check parameters for raw key import operation */
999 	if (kfmt == KMF_FORMAT_RAWKEY) {
1000 		if (keytype != NULL &&
1001 		    Str2SymKeyType(keytype, &keyAlg) != 0) {
1002 			cryptoerror(LOG_STDERR,
1003 			    gettext("Unrecognized keytype(%s).\n"), keytype);
1004 			return (PK_ERR_USAGE);
1005 		}
1006 		if (senstr != NULL && extstr != NULL &&
1007 		    kstype != KMF_KEYSTORE_PK11TOKEN) {
1008 			cryptoerror(LOG_STDERR,
1009 			    gettext("The sensitive or extractable option "
1010 			    "applies only when importing a key from a file "
1011 			    "into a PKCS#11 keystore.\n"));
1012 			return (PK_ERR_USAGE);
1013 		}
1014 	}
1015 
1016 	/* If no objtype was given, treat it as a certificate */
1017 	if (oclass == 0 && (kfmt == KMF_FORMAT_ASN1 ||
1018 	    kfmt == KMF_FORMAT_PEM))
1019 		oclass = PK_CERT_OBJ;
1020 
1021 	if (kstype == KMF_KEYSTORE_NSS) {
1022 		if (oclass == PK_CRL_OBJ &&
1023 		    (kfmt != KMF_FORMAT_ASN1 && kfmt != KMF_FORMAT_PEM)) {
1024 			cryptoerror(LOG_STDERR, gettext(
1025 			    "CRL data can only be imported as DER or "
1026 			    "PEM format"));
1027 			return (PK_ERR_USAGE);
1028 		}
1029 
1030 		if (oclass == PK_CERT_OBJ &&
1031 		    (kfmt != KMF_FORMAT_ASN1 && kfmt != KMF_FORMAT_PEM)) {
1032 			cryptoerror(LOG_STDERR, gettext(
1033 			    "Certificates can only be imported as DER or "
1034 			    "PEM format"));
1035 			return (PK_ERR_USAGE);
1036 		}
1037 
1038 		/* we do not import private keys except in PKCS12 bundles */
1039 		if (oclass & (PK_PRIVATE_OBJ | PK_PRIKEY_OBJ)) {
1040 			cryptoerror(LOG_STDERR, gettext(
1041 			    "Private key data can only be imported as part "
1042 			    "of a PKCS12 file.\n"));
1043 			return (PK_ERR_USAGE);
1044 		}
1045 	}
1046 
1047 	if (kstype == KMF_KEYSTORE_OPENSSL && oclass != PK_CRL_OBJ) {
1048 		if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) {
1049 			cryptoerror(LOG_STDERR, gettext(
1050 			    "The 'outkey' and 'outcert' parameters "
1051 			    "are required for the import operation "
1052 			    "when the 'file' keystore is used.\n"));
1053 			return (PK_ERR_USAGE);
1054 		}
1055 	}
1056 
1057 	if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec))
1058 		token_spec = PK_DEFAULT_PK11TOKEN;
1059 	else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec))
1060 		token_spec = DEFAULT_NSS_TOKEN;
1061 
1062 	if (kfmt == KMF_FORMAT_PKCS12) {
1063 		(void) get_pk12_password(&pk12cred);
1064 	}
1065 
1066 	if ((kfmt == KMF_FORMAT_PKCS12 || kfmt == KMF_FORMAT_RAWKEY ||
1067 	    (kfmt == KMF_FORMAT_PEM && (oclass & PK_KEY_OBJ))) &&
1068 	    (kstype == KMF_KEYSTORE_PK11TOKEN || kstype == KMF_KEYSTORE_NSS)) {
1069 		(void) get_token_password(kstype, token_spec, &tokencred);
1070 	}
1071 
1072 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
1073 		cryptoerror(LOG_STDERR, gettext("Error initializing "
1074 		    "KMF: 0x%02x\n"), rv);
1075 		goto end;
1076 	}
1077 
1078 	switch (kstype) {
1079 		case KMF_KEYSTORE_PK11TOKEN:
1080 			if (kfmt == KMF_FORMAT_PKCS12)
1081 				rv = pk_import_pk12_pk11(
1082 				    kmfhandle, &pk12cred,
1083 				    &tokencred, label,
1084 				    token_spec, filename);
1085 			else if (oclass == PK_CERT_OBJ)
1086 				rv = pk_import_cert(
1087 				    kmfhandle, kstype,
1088 				    label, token_spec,
1089 				    filename,
1090 				    NULL, NULL, NULL);
1091 			else if (oclass == PK_CRL_OBJ)
1092 				rv = pk_import_file_crl(
1093 				    kmfhandle, filename,
1094 				    crlfile, dir, okfmt);
1095 			else if (kfmt == KMF_FORMAT_RAWKEY &&
1096 			    oclass == PK_SYMKEY_OBJ) {
1097 				rv = pk_import_rawkey(kmfhandle,
1098 				    kstype, token_spec, &tokencred,
1099 				    filename, label,
1100 				    keyAlg, senstr, extstr);
1101 			} else if (kfmt == KMF_FORMAT_PEM ||
1102 			    kfmt == KMF_FORMAT_PEM_KEYPAIR) {
1103 				rv = pk_import_keys(kmfhandle,
1104 				    kstype, token_spec, &tokencred,
1105 				    filename, label, senstr, extstr);
1106 			} else {
1107 				rv = PK_ERR_USAGE;
1108 			}
1109 			break;
1110 		case KMF_KEYSTORE_NSS:
1111 			if (dir == NULL)
1112 				dir = PK_DEFAULT_DIRECTORY;
1113 			if (kfmt == KMF_FORMAT_PKCS12)
1114 				rv = pk_import_pk12_nss(
1115 				    kmfhandle, &pk12cred,
1116 				    &tokencred,
1117 				    token_spec, dir, prefix,
1118 				    label, trustflags, filename);
1119 			else if (oclass == PK_CERT_OBJ) {
1120 				rv = pk_import_cert(
1121 				    kmfhandle, kstype,
1122 				    label, token_spec,
1123 				    filename, dir, prefix, trustflags);
1124 			} else if (oclass == PK_CRL_OBJ) {
1125 				rv = pk_import_nss_crl(
1126 				    kmfhandle, verify_crl_flag,
1127 				    filename, dir, prefix);
1128 			}
1129 			break;
1130 		case KMF_KEYSTORE_OPENSSL:
1131 			if (kfmt == KMF_FORMAT_PKCS12)
1132 				rv = pk_import_pk12_files(
1133 				    kmfhandle, &pk12cred,
1134 				    filename, certfile, keyfile,
1135 				    dir, keydir, okfmt);
1136 			else if (oclass == PK_CRL_OBJ) {
1137 				rv = pk_import_file_crl(
1138 				    kmfhandle, filename,
1139 				    crlfile, dir, okfmt);
1140 			} else
1141 				/*
1142 				 * It doesn't make sense to import anything
1143 				 * else for the files plugin.
1144 				 */
1145 				return (PK_ERR_USAGE);
1146 			break;
1147 		default:
1148 			rv = PK_ERR_USAGE;
1149 			break;
1150 	}
1151 
1152 end:
1153 	if (rv != KMF_OK)
1154 		display_error(kmfhandle, rv,
1155 		    gettext("Error importing objects"));
1156 
1157 	if (tokencred.cred != NULL)
1158 		free(tokencred.cred);
1159 
1160 	if (pk12cred.cred != NULL)
1161 		free(pk12cred.cred);
1162 
1163 	(void) kmf_finalize(kmfhandle);
1164 
1165 	if (rv != KMF_OK)
1166 		return (PK_ERR_USAGE);
1167 
1168 	return (0);
1169 }
1170