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