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