xref: /titanic_50/usr/src/cmd/cmd-crypto/pktool/import.c (revision 32e0ab73531b6e6e8957e9ecdbbd42603865f2d0)
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  */
25 
26 /*
27  * This file implements the import operation for this tool.
28  * The basic flow of the process is to decrypt the PKCS#12
29  * input file if it has a password, parse the elements in
30  * the file, find the soft token, log into it, import the
31  * PKCS#11 objects into the soft token, and log out.
32  */
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include "common.h"
43 
44 #include <kmfapi.h>
45 
46 #define	NEW_ATTRLIST(a, n) \
47 { \
48 	a = (KMF_ATTRIBUTE *)malloc(n * sizeof (KMF_ATTRIBUTE)); \
49 	if (a == NULL) { \
50 		rv = KMF_ERR_MEMORY; \
51 		goto end; \
52 	} \
53 	(void) memset(a, 0, n * sizeof (KMF_ATTRIBUTE));  \
54 }
55 
56 static KMF_RETURN
57 pk_import_pk12_files(KMF_HANDLE_T kmfhandle, KMF_CREDENTIAL *cred,
58 	char *outfile, char *certfile, char *keyfile,
59 	KMF_ENCODE_FORMAT outformat)
60 {
61 	KMF_RETURN rv = KMF_OK;
62 	KMF_X509_DER_CERT *certs = NULL;
63 	KMF_RAW_KEY_DATA *keys = NULL;
64 	int ncerts = 0;
65 	int nkeys = 0;
66 	int i;
67 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
68 	KMF_ATTRIBUTE *attrlist = NULL;
69 	int numattr = 0;
70 
71 	rv = kmf_import_objects(kmfhandle, outfile, cred,
72 	    &certs, &ncerts, &keys, &nkeys);
73 
74 	if (rv == KMF_OK) {
75 		(void) printf(gettext("Found %d certificate(s) and %d "
76 		    "key(s) in %s\n"), ncerts, nkeys, outfile);
77 	}
78 
79 	if (rv == KMF_OK && ncerts > 0) {
80 		char newcertfile[MAXPATHLEN];
81 
82 		NEW_ATTRLIST(attrlist,  (3 + (3 * ncerts)));
83 
84 		kmf_set_attr_at_index(attrlist, numattr,
85 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
86 		numattr++;
87 
88 		kmf_set_attr_at_index(attrlist, numattr,
89 		    KMF_ENCODE_FORMAT_ATTR, &outformat, sizeof (outformat));
90 		numattr++;
91 
92 		for (i = 0; rv == KMF_OK && i < ncerts; i++) {
93 			int num = numattr;
94 
95 			/*
96 			 * If storing more than 1 cert, gotta change
97 			 * the name so we don't overwrite the previous one.
98 			 * Just append a _# to the name.
99 			 */
100 			if (i > 0) {
101 				(void) snprintf(newcertfile,
102 				    sizeof (newcertfile), "%s_%d", certfile, i);
103 
104 				kmf_set_attr_at_index(attrlist, num,
105 				    KMF_CERT_FILENAME_ATTR, newcertfile,
106 				    strlen(newcertfile));
107 				num++;
108 			} else {
109 				kmf_set_attr_at_index(attrlist, num,
110 				    KMF_CERT_FILENAME_ATTR, certfile,
111 				    strlen(certfile));
112 				num++;
113 			}
114 
115 			if (certs[i].kmf_private.label != NULL) {
116 				kmf_set_attr_at_index(attrlist, num,
117 				    KMF_CERT_LABEL_ATTR,
118 				    certs[i].kmf_private.label,
119 				    strlen(certs[i].kmf_private.label));
120 				num++;
121 			}
122 			kmf_set_attr_at_index(attrlist, num,
123 			    KMF_CERT_DATA_ATTR, &certs[i].certificate,
124 			    sizeof (KMF_DATA));
125 			num++;
126 			rv = kmf_store_cert(kmfhandle, num, attrlist);
127 		}
128 		free(attrlist);
129 	}
130 	if (rv == KMF_OK && nkeys > 0) {
131 		char newkeyfile[MAXPATHLEN];
132 		numattr = 0;
133 		NEW_ATTRLIST(attrlist, (4 + (4 * nkeys)));
134 
135 		kmf_set_attr_at_index(attrlist, numattr,
136 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
137 		    sizeof (kstype));
138 		numattr++;
139 
140 		kmf_set_attr_at_index(attrlist, numattr,
141 		    KMF_ENCODE_FORMAT_ATTR, &outformat,
142 		    sizeof (outformat));
143 		numattr++;
144 
145 		if (cred != NULL && cred->credlen > 0) {
146 			kmf_set_attr_at_index(attrlist, numattr,
147 			    KMF_CREDENTIAL_ATTR, cred,
148 			    sizeof (KMF_CREDENTIAL));
149 			numattr++;
150 		}
151 
152 		/* The order of certificates and keys should match */
153 		for (i = 0; rv == KMF_OK && i < nkeys; i++) {
154 			int num = numattr;
155 
156 			if (i > 0) {
157 				(void) snprintf(newkeyfile,
158 				    sizeof (newkeyfile), "%s_%d", keyfile, i);
159 
160 				kmf_set_attr_at_index(attrlist, num,
161 				    KMF_KEY_FILENAME_ATTR, newkeyfile,
162 				    strlen(newkeyfile));
163 				num++;
164 			} else {
165 				kmf_set_attr_at_index(attrlist, num,
166 				    KMF_KEY_FILENAME_ATTR, keyfile,
167 				    strlen(keyfile));
168 				num++;
169 			}
170 
171 			if (i < ncerts) {
172 				kmf_set_attr_at_index(attrlist, num,
173 				    KMF_CERT_DATA_ATTR, &certs[i],
174 				    sizeof (KMF_CERT_DATA_ATTR));
175 				num++;
176 			}
177 
178 			kmf_set_attr_at_index(attrlist, num,
179 			    KMF_RAW_KEY_ATTR, &keys[i],
180 			    sizeof (KMF_RAW_KEY_DATA));
181 			num++;
182 
183 			rv = kmf_store_key(kmfhandle, num, attrlist);
184 		}
185 		free(attrlist);
186 	}
187 end:
188 	/*
189 	 * Cleanup memory.
190 	 */
191 	if (certs) {
192 		for (i = 0; i < ncerts; i++)
193 			kmf_free_kmf_cert(kmfhandle, &certs[i]);
194 		free(certs);
195 	}
196 	if (keys) {
197 		for (i = 0; i < nkeys; i++)
198 			kmf_free_raw_key(&keys[i]);
199 		free(keys);
200 	}
201 
202 
203 	return (rv);
204 }
205 
206 
207 static KMF_RETURN
208 pk_import_pk12_nss(
209 	KMF_HANDLE_T kmfhandle, KMF_CREDENTIAL *kmfcred,
210 	KMF_CREDENTIAL *tokencred,
211 	char *token_spec, char *dir, char *prefix,
212 	char *nickname, char *trustflags, char *filename)
213 {
214 	KMF_RETURN rv = KMF_OK;
215 	KMF_X509_DER_CERT *certs = NULL;
216 	KMF_RAW_KEY_DATA *keys = NULL;
217 	int ncerts = 0;
218 	int nkeys = 0;
219 	int i;
220 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
221 	KMF_ATTRIBUTE *attrlist = NULL;
222 	int numattr = 0;
223 
224 	rv = configure_nss(kmfhandle, dir, prefix);
225 	if (rv != KMF_OK)
226 		return (rv);
227 
228 	rv = kmf_import_objects(kmfhandle, filename, kmfcred,
229 	    &certs, &ncerts, &keys, &nkeys);
230 
231 	if (rv == KMF_OK)
232 		(void) printf(gettext("Found %d certificate(s) and %d "
233 		    "key(s) in %s\n"), ncerts, nkeys, filename);
234 
235 	if (rv == KMF_OK) {
236 		numattr = 0;
237 		NEW_ATTRLIST(attrlist, (4 + (2 * nkeys)));
238 
239 		kmf_set_attr_at_index(attrlist, numattr,
240 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
241 		    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 (nickname != NULL) {
252 			kmf_set_attr_at_index(attrlist, numattr,
253 			    KMF_KEYLABEL_ATTR, nickname,
254 			    strlen(nickname));
255 			numattr++;
256 		}
257 
258 		if (tokencred->credlen > 0) {
259 			kmf_set_attr_at_index(attrlist, numattr,
260 			    KMF_CREDENTIAL_ATTR, tokencred,
261 			    sizeof (KMF_CREDENTIAL));
262 			numattr++;
263 		}
264 
265 		/* The order of certificates and keys should match */
266 		for (i = 0; i < nkeys; i++) {
267 			int num = numattr;
268 
269 			if (i < ncerts) {
270 				kmf_set_attr_at_index(attrlist, num,
271 				    KMF_CERT_DATA_ATTR, &certs[i],
272 				    sizeof (KMF_DATA));
273 				num++;
274 			}
275 
276 			kmf_set_attr_at_index(attrlist, num,
277 			    KMF_RAW_KEY_ATTR, &keys[i],
278 			    sizeof (KMF_RAW_KEY_DATA));
279 			num++;
280 
281 			rv = kmf_store_key(kmfhandle, num, attrlist);
282 		}
283 		free(attrlist);
284 		attrlist = NULL;
285 	}
286 
287 	if (rv == KMF_OK) {
288 		numattr = 0;
289 		NEW_ATTRLIST(attrlist, (3 + (2 * ncerts)));
290 
291 		kmf_set_attr_at_index(attrlist, numattr,
292 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
293 		numattr++;
294 
295 		if (token_spec != NULL) {
296 			kmf_set_attr_at_index(attrlist, numattr,
297 			    KMF_TOKEN_LABEL_ATTR, token_spec,
298 			    strlen(token_spec));
299 			numattr++;
300 		}
301 
302 		if (trustflags != NULL) {
303 			kmf_set_attr_at_index(attrlist, numattr,
304 			    KMF_TRUSTFLAG_ATTR, trustflags,
305 			    strlen(trustflags));
306 			numattr++;
307 		}
308 
309 		for (i = 0; rv == KMF_OK && i < ncerts; i++) {
310 			int num = numattr;
311 
312 			if (certs[i].kmf_private.label != NULL) {
313 				kmf_set_attr_at_index(attrlist, num,
314 				    KMF_CERT_LABEL_ATTR,
315 				    certs[i].kmf_private.label,
316 				    strlen(certs[i].kmf_private.label));
317 				num++;
318 			} else if (i == 0 && nickname != NULL) {
319 				kmf_set_attr_at_index(attrlist, num,
320 				    KMF_CERT_LABEL_ATTR, nickname,
321 				    strlen(nickname));
322 				num++;
323 			}
324 
325 			kmf_set_attr_at_index(attrlist, num,
326 			    KMF_CERT_DATA_ATTR,
327 			    &certs[i].certificate, sizeof (KMF_DATA));
328 			num++;
329 			rv = kmf_store_cert(kmfhandle, num, attrlist);
330 		}
331 		free(attrlist);
332 		attrlist = NULL;
333 		if (rv != KMF_OK) {
334 			display_error(kmfhandle, rv,
335 			    gettext("Error storing certificate in NSS token"));
336 		}
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 		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