1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  *
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <dlfcn.h>
31 #include <link.h>
32 #include <fcntl.h>
33 #include <ctype.h>
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <errno.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
41 #include <thread.h>
42 
43 #include <ber_der.h>
44 #include <kmfapiP.h>
45 
46 #include <pem_encode.h>
47 #include <rdn_parser.h>
48 #include <libxml2/libxml/uri.h>
49 #include <libgen.h>
50 #include <cryptoutil.h>
51 
52 static uchar_t pkcs11_initialized = 0;
53 mutex_t init_lock = DEFAULTMUTEX;
54 extern int errno;
55 
56 typedef struct {
57 	KMF_RETURN code;
58 	char	*message;
59 } kmf_error_map;
60 
61 static kmf_error_map kmf_errcodes[] = {
62 	{KMF_OK,	"KMF_OK"},
63 	{KMF_ERR_BAD_PARAMETER,	"KMF_ERR_BAD_PARAMETER"},
64 	{KMF_ERR_BAD_KEY_FORMAT,	"KMF_ERR_BAD_KEY_FORMAT"},
65 	{KMF_ERR_BAD_ALGORITHM,	"KMF_ERR_BAD_ALGORITHM"},
66 	{KMF_ERR_MEMORY,	"KMF_ERR_MEMORY"},
67 	{KMF_ERR_ENCODING,	"KMF_ERR_ENCODING"},
68 	{KMF_ERR_PLUGIN_INIT,	"KMF_ERR_PLUGIN_INIT"},
69 	{KMF_ERR_PLUGIN_NOTFOUND,	"KMF_ERR_PLUGIN_NOTFOUND"},
70 	{KMF_ERR_INTERNAL,	"KMF_ERR_INTERNAL"},
71 	{KMF_ERR_BAD_CERT_FORMAT,	"KMF_ERR_BAD_CERT_FORMAT"},
72 	{KMF_ERR_KEYGEN_FAILED,	"KMF_ERR_KEYGEN_FAILED"},
73 	{KMF_ERR_UNINITIALIZED,	"KMF_ERR_UNINITIALIZED"},
74 	{KMF_ERR_ISSUER,	"KMF_ERR_ISSUER"},
75 	{KMF_ERR_NOT_REVOKED,	"KMF_ERR_NOT_REVOKED"},
76 	{KMF_ERR_CERT_NOT_FOUND,	"KMF_ERR_CERT_NOT_FOUND"},
77 	{KMF_ERR_CRL_NOT_FOUND,	"KMF_ERR_CRL_NOT_FOUND"},
78 	{KMF_ERR_RDN_PARSER,	"KMF_ERR_RDN_PARSER"},
79 	{KMF_ERR_RDN_ATTR,	"KMF_ERR_RDN_ATTR"},
80 	{KMF_ERR_SLOTNAME,	"KMF_ERR_SLOTNAME"},
81 	{KMF_ERR_EMPTY_CRL,	"KMF_ERR_EMPTY_CRL"},
82 	{KMF_ERR_BUFFER_SIZE,	"KMF_ERR_BUFFER_SIZE"},
83 	{KMF_ERR_AUTH_FAILED,	"KMF_ERR_AUTH_FAILED"},
84 	{KMF_ERR_TOKEN_SELECTED,	"KMF_ERR_TOKEN_SELECTED"},
85 	{KMF_ERR_NO_TOKEN_SELECTED,	"KMF_ERR_NO_TOKEN_SELECTED"},
86 	{KMF_ERR_TOKEN_NOT_PRESENT,	"KMF_ERR_TOKEN_NOT_PRESENT"},
87 	{KMF_ERR_EXTENSION_NOT_FOUND,	"KMF_ERR_EXTENSION_NOT_FOUND"},
88 	{KMF_ERR_POLICY_ENGINE,	"KMF_ERR_POLICY_ENGINE"},
89 	{KMF_ERR_POLICY_DB_FORMAT,	"KMF_ERR_POLICY_DB_FORMAT"},
90 	{KMF_ERR_POLICY_NOT_FOUND,	"KMF_ERR_POLICY_NOT_FOUND"},
91 	{KMF_ERR_POLICY_DB_FILE,	"KMF_ERR_POLICY_DB_FILE"},
92 	{KMF_ERR_POLICY_NAME,	"KMF_ERR_POLICY_NAME"},
93 	{KMF_ERR_OCSP_POLICY,	"KMF_ERR_OCSP_POLICY"},
94 	{KMF_ERR_TA_POLICY,	"KMF_ERR_TA_POLICY"},
95 	{KMF_ERR_KEY_NOT_FOUND,	"KMF_ERR_KEY_NOT_FOUND"},
96 	{KMF_ERR_OPEN_FILE,	"KMF_ERR_OPEN_FILE"},
97 	{KMF_ERR_OCSP_BAD_ISSUER,	"KMF_ERR_OCSP_BAD_ISSUER"},
98 	{KMF_ERR_OCSP_BAD_CERT,	"KMF_ERR_OCSP_BAD_CERT"},
99 	{KMF_ERR_OCSP_CREATE_REQUEST,	"KMF_ERR_OCSP_CREATE_REQUEST"},
100 	{KMF_ERR_CONNECT_SERVER,	"KMF_ERR_CONNECT_SERVER"},
101 	{KMF_ERR_SEND_REQUEST,	"KMF_ERR_SEND_REQUEST"},
102 	{KMF_ERR_OCSP_CERTID,	"KMF_ERR_OCSP_CERTID"},
103 	{KMF_ERR_OCSP_MALFORMED_RESPONSE, "KMF_ERR_OCSP_MALFORMED_RESPONSE"},
104 	{KMF_ERR_OCSP_RESPONSE_STATUS,	"KMF_ERR_OCSP_RESPONSE_STATUS"},
105 	{KMF_ERR_OCSP_NO_BASIC_RESPONSE, "KMF_ERR_OCSP_NO_BASIC_RESPONSE"},
106 	{KMF_ERR_OCSP_BAD_SIGNER,	"KMF_ERR_OCSP_BAD_SIGNER"},
107 	{KMF_ERR_OCSP_RESPONSE_SIGNATURE, "KMF_ERR_OCSP_RESPONSE_SIGNATURE"},
108 	{KMF_ERR_OCSP_UNKNOWN_CERT,	"KMF_ERR_OCSP_UNKNOWN_CERT"},
109 	{KMF_ERR_OCSP_STATUS_TIME_INVALID, "KMF_ERR_OCSP_STATUS_TIME_INVALID"},
110 	{KMF_ERR_BAD_HTTP_RESPONSE,	"KMF_ERR_BAD_HTTP_RESPONSE"},
111 	{KMF_ERR_RECV_RESPONSE,	"KMF_ERR_RECV_RESPONSE"},
112 	{KMF_ERR_RECV_TIMEOUT,	"KMF_ERR_RECV_TIMEOUT"},
113 	{KMF_ERR_DUPLICATE_KEYFILE,	"KMF_ERR_DUPLICATE_KEYFILE"},
114 	{KMF_ERR_AMBIGUOUS_PATHNAME,	"KMF_ERR_AMBIGUOUS_PATHNAME"},
115 	{KMF_ERR_FUNCTION_NOT_FOUND,	"KMF_ERR_FUNCTION_NOT_FOUND"},
116 	{KMF_ERR_PKCS12_FORMAT,	"KMF_ERR_PKCS12_FORMAT"},
117 	{KMF_ERR_BAD_KEY_TYPE,	"KMF_ERR_BAD_KEY_TYPE"},
118 	{KMF_ERR_BAD_KEY_CLASS,	"KMF_ERR_BAD_KEY_CLASS"},
119 	{KMF_ERR_BAD_KEY_SIZE,	"KMF_ERR_BAD_KEY_SIZE"},
120 	{KMF_ERR_BAD_HEX_STRING,	"KMF_ERR_BAD_HEX_STRING"},
121 	{KMF_ERR_KEYUSAGE,	"KMF_ERR_KEYUSAGE"},
122 	{KMF_ERR_VALIDITY_PERIOD,	"KMF_ERR_VALIDITY_PERIOD"},
123 	{KMF_ERR_OCSP_REVOKED,	"KMF_ERR_OCSP_REVOKED"},
124 	{KMF_ERR_CERT_MULTIPLE_FOUND,	"KMF_ERR_CERT_MULTIPLE_FOUND"},
125 	{KMF_ERR_WRITE_FILE,	"KMF_ERR_WRITE_FILE"},
126 	{KMF_ERR_BAD_URI,	"KMF_ERR_BAD_URI"},
127 	{KMF_ERR_BAD_CRLFILE,	"KMF_ERR_BAD_CRLFILE"},
128 	{KMF_ERR_BAD_CERTFILE,	"KMF_ERR_BAD_CERTFILE"},
129 	{KMF_ERR_GETKEYVALUE_FAILED,	"KMF_ERR_GETKEYVALUE_FAILED"},
130 	{KMF_ERR_BAD_KEYHANDLE,	"KMF_ERR_BAD_KEYHANDLE"},
131 	{KMF_ERR_BAD_OBJECT_TYPE,	"KMF_ERR_BAD_OBJECT_TYPE"},
132 	{KMF_ERR_OCSP_RESPONSE_LIFETIME, "KMF_ERR_OCSP_RESPONSE_LIFETIME"},
133 	{KMF_ERR_UNKNOWN_CSR_ATTRIBUTE,	"KMF_ERR_UNKNOWN_CSR_ATTRIBUTE"},
134 	{KMF_ERR_UNINITIALIZED_TOKEN,	"KMF_ERR_UNINITIALIZED_TOKEN"},
135 	{KMF_ERR_INCOMPLETE_TBS_CERT,	"KMF_ERR_INCOMPLETE_TBS_CERT"},
136 	{KMF_ERR_MISSING_ERRCODE,	"KMF_ERR_MISSING_ERRCODE"},
137 	{KMF_KEYSTORE_ALREADY_INITIALIZED, "KMF_KEYSTORE_ALREADY_INITIALIZED"},
138 	{KMF_ERR_SENSITIVE_KEY,		"KMF_ERR_SENSITIVE_KEY"},
139 	{KMF_ERR_UNEXTRACTABLE_KEY,	"KMF_ERR_UNEXTRACTABLE_KEY"},
140 	{KMF_ERR_KEY_MISMATCH,		"KMF_ERR_KEY_MISMATCH"}
141 };
142 
143 typedef struct {
144 	KMF_KEYSTORE_TYPE	kstype;
145 	char			*path;
146 	boolean_t		critical;
147 } KMF_PLUGIN_ITEM;
148 
149 KMF_PLUGIN_ITEM plugin_list[] = {
150 	{KMF_KEYSTORE_OPENSSL,	KMF_PLUGIN_PATH "kmf_openssl.so.1",  TRUE},
151 	{KMF_KEYSTORE_PK11TOKEN, KMF_PLUGIN_PATH "kmf_pkcs11.so.1",  TRUE},
152 	{KMF_KEYSTORE_NSS,	KMF_PLUGIN_PATH "kmf_nss.so.1",  FALSE}
153 };
154 
155 
156 
157 static KMF_RETURN InitializePlugin(KMF_KEYSTORE_TYPE, char *, KMF_PLUGIN **);
158 static KMF_RETURN AddPlugin(KMF_HANDLE_T, KMF_PLUGIN *);
159 static void free_extensions(KMF_X509_EXTENSIONS *extns);
160 static void DestroyPlugin(KMF_PLUGIN *);
161 
162 #if defined(__sparcv9)
163 #define	ISA_PATH	"/sparcv9"
164 #elif defined(__sparc)
165 #define	ISA_PATH	"/"
166 #elif defined(__i386)
167 #define	ISA_PATH	"/"
168 #elif defined(__amd64)
169 #define	ISA_PATH	"/amd64"
170 #endif
171 
172 #define	DEFAULT_KEYSTORE_NUM	3
173 static int kstore_num = DEFAULT_KEYSTORE_NUM;
174 conf_entrylist_t *extra_plugin_list = NULL;
175 static boolean_t check_extra_plugin = B_FALSE;
176 mutex_t extra_plugin_lock = DEFAULTMUTEX;
177 
178 KMF_RETURN
179 init_pk11()
180 {
181 	(void) mutex_lock(&init_lock);
182 	if (!pkcs11_initialized) {
183 		CK_RV rv = C_Initialize(NULL);
184 		if ((rv != CKR_OK) &&
185 		    (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
186 			(void) mutex_unlock(&init_lock);
187 			return (KMF_ERR_UNINITIALIZED);
188 		} else {
189 			pkcs11_initialized = 1;
190 		}
191 	}
192 	(void) mutex_unlock(&init_lock);
193 	return (KMF_OK);
194 }
195 
196 /*
197  * Private method for searching the plugin list for the correct
198  * Plugin to use.
199  */
200 KMF_PLUGIN *
201 FindPlugin(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE kstype)
202 {
203 	KMF_PLUGIN_LIST *node;
204 	KMF_RETURN ret = KMF_OK;
205 	KMF_PLUGIN *pluginrec = NULL;
206 
207 	if (handle == NULL)
208 		return (NULL);
209 
210 	node = handle->plugins;
211 
212 	/* See if the desired plugin was already initialized. */
213 	while (node != NULL && node->plugin->type != kstype)
214 		node = node->next;
215 
216 	if (node != NULL)
217 		return (node->plugin);
218 
219 	/* The plugin was not found, try to initialize it here. */
220 	if (VALID_DEFAULT_KEYSTORE_TYPE(kstype)) {
221 		int i;
222 		int numitems = sizeof (plugin_list)/sizeof (KMF_PLUGIN_ITEM);
223 		for (i = 0; i < numitems; i++) {
224 			if (plugin_list[i].kstype == kstype) {
225 				ret = InitializePlugin(plugin_list[i].kstype,
226 				    plugin_list[i].path, &pluginrec);
227 				break;
228 			}
229 		}
230 
231 		goto out;
232 
233 	} else {
234 		/*
235 		 * Not a built-in plugin. Check if it is in the
236 		 * extra_plugin_list.  If it is, try to initialize it here.
237 		 */
238 		conf_entrylist_t *phead = extra_plugin_list;
239 		char realpath[MAXPATHLEN];
240 
241 		while (phead != NULL) {
242 			if (phead->entry->kstype == kstype)
243 				break;
244 			else
245 				phead = phead->next;
246 		}
247 
248 		if (phead == NULL)
249 			return (NULL);
250 
251 		/*
252 		 * Get the absolute path of the module.
253 		 * - If modulepath is not a full path, then prepend it
254 		 *   with KMF_PLUGIN_PATH.
255 		 * - If modulepath is a full path and contain $ISA, then
256 		 *   subsitute the architecture dependent path.
257 		 */
258 		(void) memset(realpath, 0, sizeof (realpath));
259 		if (strncmp(phead->entry->modulepath, "/", 1) != 0) {
260 			(void) snprintf(realpath, MAXPATHLEN, "%s%s",
261 			    KMF_PLUGIN_PATH, phead->entry->modulepath);
262 		} else {
263 			char *buf = phead->entry->modulepath;
264 			char *isa;
265 
266 			if ((isa = strstr(buf, PKCS11_ISA)) != NULL) {
267 				char *isa_str;
268 
269 				(void) strncpy(realpath, buf, isa - buf);
270 				isa_str = strdup(ISA_PATH);
271 				if (isa_str == NULL) /* not enough memory */
272 					return (NULL);
273 
274 				(void) strncat(realpath, isa_str,
275 				    strlen(isa_str));
276 				free(isa_str);
277 
278 				isa += strlen(PKCS11_ISA);
279 				(void) strlcat(realpath, isa, MAXPATHLEN);
280 			} else {
281 				(void) snprintf(realpath, MAXPATHLEN, "%s",
282 				    phead->entry->modulepath);
283 			}
284 		}
285 
286 		ret = InitializePlugin(phead->entry->kstype, realpath,
287 		    &pluginrec);
288 		goto out;
289 	}
290 
291 out:
292 	if (ret != KMF_OK || pluginrec == NULL)
293 		/* No matching plugins found in the built-in list */
294 		return (NULL);
295 
296 	ret = AddPlugin(handle, pluginrec);
297 	if (ret != KMF_OK) {
298 		DestroyPlugin(pluginrec);
299 		pluginrec = NULL;
300 	}
301 	return (pluginrec);
302 }
303 
304 
305 static KMF_RETURN
306 InitializePlugin(KMF_KEYSTORE_TYPE kstype, char *path, KMF_PLUGIN **plugin)
307 {
308 	KMF_PLUGIN *p = NULL;
309 	KMF_PLUGIN_FUNCLIST *(*sym)();
310 
311 	if (path == NULL || plugin == NULL)
312 		return (KMF_ERR_BAD_PARAMETER);
313 
314 	*plugin = NULL;
315 
316 	p = (KMF_PLUGIN *)malloc(sizeof (KMF_PLUGIN));
317 	if (p == NULL)
318 		return (KMF_ERR_MEMORY);
319 
320 	p->type = kstype;
321 	p->path = strdup(path);
322 	if (p->path == NULL) {
323 		free(p);
324 		return (KMF_ERR_MEMORY);
325 	}
326 	p->dldesc = dlopen(path, RTLD_LAZY | RTLD_GROUP | RTLD_PARENT);
327 	if (p->dldesc == NULL) {
328 		free(p->path);
329 		free(p);
330 		return (KMF_ERR_PLUGIN_INIT);
331 	}
332 
333 	sym = (KMF_PLUGIN_FUNCLIST *(*)())dlsym(p->dldesc,
334 	    KMF_PLUGIN_INIT_SYMBOL);
335 	if (sym == NULL) {
336 		(void) dlclose(p->dldesc);
337 		free(p->path);
338 		free(p);
339 		return (KMF_ERR_PLUGIN_INIT);
340 	}
341 
342 	/* Get the function list */
343 	if ((p->funclist = (*sym)()) == NULL) {
344 		(void) dlclose(p->dldesc);
345 		free(p->path);
346 		free(p);
347 		return (KMF_ERR_PLUGIN_INIT);
348 	}
349 
350 	*plugin = p;
351 
352 	return (KMF_OK);
353 }
354 
355 static KMF_RETURN
356 AddPlugin(KMF_HANDLE_T handle, KMF_PLUGIN *plugin)
357 {
358 	KMF_PLUGIN_LIST *n;
359 
360 	if (handle == NULL || plugin == NULL)
361 		return (KMF_ERR_BAD_PARAMETER);
362 
363 	/* If the head is NULL, create it */
364 	if (handle->plugins == NULL) {
365 		handle->plugins = (KMF_PLUGIN_LIST *)malloc(
366 		    sizeof (KMF_PLUGIN_LIST));
367 		if (handle->plugins == NULL)
368 			return (KMF_ERR_MEMORY);
369 		handle->plugins->plugin = plugin;
370 		handle->plugins->next = NULL;
371 	} else {
372 		/* walk the list to find the tail */
373 		n = handle->plugins;
374 		while (n->next != NULL)
375 			n = n->next;
376 		n->next = (KMF_PLUGIN_LIST *)malloc(sizeof (KMF_PLUGIN_LIST));
377 		if (n->next == NULL)
378 			return (KMF_ERR_MEMORY);
379 
380 		n->next->plugin = plugin;
381 		n->next->next = NULL;
382 	}
383 	return (0);
384 }
385 
386 static void
387 DestroyPlugin(KMF_PLUGIN *plugin)
388 {
389 	if (plugin) {
390 		if (plugin->path)
391 			free(plugin->path);
392 		free(plugin);
393 	}
394 }
395 
396 static void
397 Cleanup_KMF_Handle(KMF_HANDLE_T handle)
398 {
399 	if (handle != NULL) {
400 		while (handle->plugins != NULL) {
401 			KMF_PLUGIN_LIST *next = handle->plugins->next;
402 
403 			DestroyPlugin(handle->plugins->plugin);
404 			free(handle->plugins);
405 			handle->plugins = next;
406 		}
407 		kmf_free_policy_record(handle->policy);
408 		free(handle->policy);
409 	}
410 	free(handle);
411 }
412 
413 void
414 Cleanup_PK11_Session(KMF_HANDLE_T handle)
415 {
416 	if (handle != NULL) {
417 		/* Close active session on a pkcs11 token */
418 		if (handle->pk11handle != NULL) {
419 			(void) C_CloseSession(handle->pk11handle);
420 			handle->pk11handle = NULL;
421 		}
422 	}
423 }
424 
425 KMF_RETURN
426 kmf_initialize(KMF_HANDLE_T *outhandle, char *policyfile, char *policyname)
427 {
428 	KMF_RETURN ret = KMF_OK;
429 	KMF_HANDLE *handle = NULL;
430 
431 	if (outhandle == NULL)
432 		return (KMF_ERR_BAD_PARAMETER);
433 
434 	*outhandle = NULL;
435 	handle = (KMF_HANDLE *)malloc(sizeof (KMF_HANDLE));
436 	if (handle == NULL)
437 		return (KMF_ERR_MEMORY);
438 
439 	(void) memset(handle, 0, sizeof (KMF_HANDLE));
440 	handle->plugins = NULL;
441 
442 	/*
443 	 * When this function is called the first time, get the additional
444 	 * plugins from the config file.
445 	 */
446 	(void) mutex_lock(&extra_plugin_lock);
447 	if (!check_extra_plugin) {
448 
449 		ret = get_entrylist(&extra_plugin_list);
450 		check_extra_plugin = B_TRUE;
451 
452 		/*
453 		 * Assign the kstype number to the additional plugins here.
454 		 * The global kstore_num will be protected by the mutex lock.
455 		 */
456 		if (ret == KMF_OK) {
457 			conf_entrylist_t *phead = extra_plugin_list;
458 			while (phead != NULL) {
459 				phead->entry->kstype = ++kstore_num;
460 				phead = phead->next;
461 			}
462 		}
463 
464 		/*
465 		 * If the KMF configuration file does not exist or cannot be
466 		 * parsed correctly, we will give a warning in syslog and
467 		 * continue on as there is no extra plugins in the system.
468 		 */
469 		if (ret == KMF_ERR_KMF_CONF) {
470 			cryptoerror(LOG_WARNING, "KMF was unable to parse "
471 			    "the private KMF config file.\n");
472 			ret = KMF_OK;
473 		}
474 
475 		if (ret != KMF_OK) {
476 			(void) mutex_unlock(&extra_plugin_lock);
477 			goto errout;
478 		}
479 	}
480 	(void) mutex_unlock(&extra_plugin_lock);
481 
482 	/* Initialize the handle with the policy */
483 	ret = kmf_set_policy((void *)handle,
484 	    policyfile == NULL ? KMF_DEFAULT_POLICY_FILE : policyfile,
485 	    policyname == NULL ? KMF_DEFAULT_POLICY_NAME : policyname);
486 	if (ret != KMF_OK)
487 		goto errout;
488 
489 	CLEAR_ERROR(handle, ret);
490 errout:
491 	if (ret != KMF_OK) {
492 		Cleanup_KMF_Handle(handle);
493 		handle = NULL;
494 	}
495 
496 	*outhandle = (KMF_HANDLE_T)handle;
497 	return (ret);
498 }
499 
500 KMF_RETURN
501 kmf_configure_keystore(KMF_HANDLE_T handle,
502 	int	num_args,
503 	KMF_ATTRIBUTE	*attrlist)
504 {
505 	KMF_RETURN ret = KMF_OK;
506 	KMF_PLUGIN *plugin;
507 	KMF_KEYSTORE_TYPE kstype;
508 	uint32_t len;
509 
510 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
511 		{KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
512 	};
513 
514 	int num_req_attrs = sizeof (required_attrs) /
515 	    sizeof (KMF_ATTRIBUTE_TESTER);
516 
517 	if (handle == NULL)
518 		return (KMF_ERR_BAD_PARAMETER);
519 
520 	CLEAR_ERROR(handle, ret);
521 
522 	ret = test_attributes(num_req_attrs, required_attrs,
523 	    0, NULL, num_args, attrlist);
524 
525 	if (ret != KMF_OK)
526 		return (ret);
527 
528 	len = sizeof (kstype);
529 	ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, num_args,
530 	    &kstype, &len);
531 	if (ret != KMF_OK)
532 		return (ret);
533 
534 	plugin = FindPlugin(handle, kstype);
535 	if (plugin != NULL && plugin->funclist->ConfigureKeystore != NULL) {
536 		return (plugin->funclist->ConfigureKeystore(handle, num_args,
537 		    attrlist));
538 	} else {
539 		/* return KMF_OK, if the plugin does not have an entry */
540 		return (KMF_OK);
541 	}
542 }
543 
544 KMF_RETURN
545 kmf_finalize(KMF_HANDLE_T handle)
546 {
547 	KMF_RETURN ret = KMF_OK;
548 
549 	CLEAR_ERROR(handle, ret);
550 	if (ret != KMF_OK)
551 		return (ret);
552 
553 	if (pkcs11_initialized) {
554 		Cleanup_PK11_Session(handle);
555 	}
556 	Cleanup_KMF_Handle(handle);
557 
558 	return (ret);
559 }
560 
561 KMF_RETURN
562 kmf_get_kmf_error_str(KMF_RETURN errcode, char **errmsg)
563 {
564 	KMF_RETURN ret = KMF_OK;
565 	int i, maxerr;
566 
567 	if (errmsg == NULL)
568 		return (KMF_ERR_BAD_PARAMETER);
569 
570 	*errmsg = NULL;
571 	maxerr = sizeof (kmf_errcodes) / sizeof (kmf_error_map);
572 
573 	for (i = 0; i < maxerr && errcode != kmf_errcodes[i].code; i++)
574 		/* empty body */
575 		;
576 
577 	if (i == maxerr)
578 		return (KMF_ERR_MISSING_ERRCODE);
579 	else {
580 		*errmsg = strdup(kmf_errcodes[i].message);
581 		if ((*errmsg) == NULL)
582 			return (KMF_ERR_MEMORY);
583 	}
584 	return (ret);
585 }
586 
587 KMF_RETURN
588 kmf_get_plugin_error_str(KMF_HANDLE_T handle, char **msgstr)
589 {
590 	KMF_RETURN ret = KMF_OK;
591 	KMF_PLUGIN *plugin;
592 
593 	if (handle == NULL || msgstr == NULL)
594 		return (KMF_ERR_BAD_PARAMETER);
595 
596 	*msgstr = NULL;
597 
598 	if (handle->lasterr.errcode == 0) {
599 		return (KMF_ERR_MISSING_ERRCODE);
600 	}
601 
602 	if (handle->lasterr.kstype == -1) { /* System error */
603 		char *str = strerror(handle->lasterr.errcode);
604 		if (str != NULL) {
605 			*msgstr = strdup(str);
606 			if ((*msgstr) == NULL)
607 				return (KMF_ERR_MEMORY);
608 		}
609 		return (KMF_OK);
610 	}
611 
612 	plugin = FindPlugin(handle, handle->lasterr.kstype);
613 	if (plugin == NULL)
614 		return (KMF_ERR_PLUGIN_NOTFOUND);
615 
616 	if (plugin->funclist->GetErrorString != NULL) {
617 		ret = plugin->funclist->GetErrorString(handle, msgstr);
618 	} else {
619 		return (KMF_ERR_FUNCTION_NOT_FOUND);
620 	}
621 
622 	return (ret);
623 }
624 
625 
626 #define	SET_SYS_ERROR(h, c) if (h) {\
627 	h->lasterr.kstype = -1;\
628 	h->lasterr.errcode = c;\
629 }
630 
631 KMF_RETURN
632 kmf_read_input_file(KMF_HANDLE_T handle, char *filename,  KMF_DATA *pdata)
633 {
634 	struct stat s;
635 	long nread, total = 0;
636 	int fd;
637 	unsigned char *buf = NULL;
638 	KMF_RETURN ret;
639 
640 	if (handle) {
641 		CLEAR_ERROR(handle, ret);
642 		if (ret != KMF_OK)
643 			return (ret);
644 	}
645 
646 	if (filename == NULL || pdata == NULL) {
647 		return (KMF_ERR_BAD_PARAMETER);
648 	}
649 
650 	if ((fd = open(filename, O_RDONLY)) < 0) {
651 		SET_SYS_ERROR(handle, errno);
652 		return (KMF_ERR_OPEN_FILE);
653 	}
654 
655 	if (fstat(fd, &s) < 0) {
656 		SET_SYS_ERROR(handle, errno);
657 		(void) close(fd);
658 		return (KMF_ERR_OPEN_FILE);
659 	}
660 
661 	if ((buf = (unsigned char *) malloc(s.st_size)) == NULL) {
662 		(void) close(fd);
663 		return (KMF_ERR_MEMORY);
664 	}
665 
666 	do {
667 		nread = read(fd, buf+total, s.st_size-total);
668 		if (nread < 0) {
669 			SET_SYS_ERROR(handle, errno);
670 			(void) close(fd);
671 			free(buf);
672 			return (KMF_ERR_INTERNAL);
673 		}
674 		total += nread;
675 	} while (total < s.st_size);
676 
677 	pdata->Data = buf;
678 	pdata->Length = s.st_size;
679 	(void) close(fd);
680 	return (KMF_OK);
681 }
682 
683 /*
684  *
685  * Name: kmf_der_to_pem
686  *
687  * Description:
688  *   Function for converting DER encoded format to PEM encoded format
689  *
690  * Parameters:
691  *   type(input) - CERTIFICATE or CSR
692  *   data(input) - pointer to the DER encoded data
693  *   len(input)  - length of input data
694  *   out(output) - contains the output buffer address to be returned
695  *   outlen(output) - pointer to the returned output length
696  *
697  * Returns:
698  *   A KMF_RETURN value indicating success or specifying a particular
699  * error condition.
700  *   The value KMF_OK indicates success. All other values represent
701  * an error condition.
702  *
703  */
704 KMF_RETURN
705 kmf_der_to_pem(KMF_OBJECT_TYPE type, unsigned char *data,
706 	int len, unsigned char **out, int *outlen)
707 {
708 
709 	KMF_RETURN err;
710 	if (data == NULL || out == NULL || outlen == NULL)
711 		return (KMF_ERR_BAD_PARAMETER);
712 
713 	err = Der2Pem(type, data, len, out, outlen);
714 	return (err);
715 
716 }
717 
718 /*
719  *
720  * Name: kmf_pem_to_der
721  *
722  * Description:
723  *   Function for converting PEM encoded format to DER encoded format
724  *
725  * Parameters:
726  *   in(input) - pointer to the PEM encoded data
727  *   inlen(input)  - length of input data
728  *   out(output) - contains the output buffer address to be returned
729  *   outlen(output) - pointer to the returned output length
730  *
731  * Returns:
732  *   A KMF_RETURN value indicating success or specifying a particular
733  *   error condition.
734  *   The value KMF_OK indicates success. All other values represent
735  *   an error condition.
736  *
737  */
738 KMF_RETURN
739 kmf_pem_to_der(unsigned char *in, int inlen,
740 	unsigned char **out, int *outlen)
741 {
742 	KMF_RETURN err;
743 	if (in == NULL || out == NULL || outlen == NULL)
744 		return (KMF_ERR_BAD_PARAMETER);
745 
746 	err = Pem2Der(in, inlen, out, outlen);
747 	return (err);
748 }
749 
750 char *
751 kmf_oid_to_string(KMF_OID *oid)
752 {
753 	char numstr[128];
754 	uint32_t number;
755 	int numshift;
756 	uint32_t i, string_length;
757 	uchar_t *cp;
758 	char *bp;
759 
760 	/* First determine the size of the string */
761 	string_length = 0;
762 	number = 0;
763 	numshift = 0;
764 	cp = (unsigned char *)oid->Data;
765 
766 	number = (uint32_t)cp[0];
767 	(void) sprintf(numstr, "%d ", number/40);
768 
769 	string_length += strlen(numstr);
770 	(void) sprintf(numstr, "%d ", number%40);
771 
772 	string_length += strlen(numstr);
773 
774 	for (i = 1; i < oid->Length; i++) {
775 		if ((uint32_t)(numshift+7) < (sizeof (uint32_t)*8)) {
776 			number = (number << 7) | (cp[i] & 0x7f);
777 			numshift += 7;
778 		} else {
779 			return (NULL);
780 		}
781 
782 		if ((cp[i] & 0x80) == 0) {
783 			(void) sprintf(numstr, "%d ", number);
784 			string_length += strlen(numstr);
785 			number = 0;
786 			numshift = 0;
787 		}
788 	}
789 	/*
790 	 * If we get here, we've calculated the length of "n n n ... n ".  Add 4
791 	 * here for "{ " and "}\0".
792 	 */
793 	string_length += 4;
794 	if ((bp = (char *)malloc(string_length))) {
795 		number = (uint32_t)cp[0];
796 
797 		(void) sprintf(numstr, "%d.", number/40);
798 		(void) strcpy(bp, numstr);
799 
800 		(void) sprintf(numstr, "%d.", number%40);
801 		(void) strcat(bp, numstr);
802 
803 		number = 0;
804 		cp = (unsigned char *) oid->Data;
805 		for (i = 1; i < oid->Length; i++) {
806 			number = (number << 7) | (cp[i] & 0x7f);
807 			if ((cp[i] & 0x80) == 0) {
808 				(void) sprintf(numstr, "%d", number);
809 				(void) strcat(bp, numstr);
810 				number = 0;
811 				if (i+1 < oid->Length)
812 					(void) strcat(bp, ".");
813 			}
814 		}
815 	}
816 	return (bp);
817 }
818 
819 static boolean_t
820 check_for_pem(uchar_t *buf, KMF_ENCODE_FORMAT *fmt)
821 {
822 	char *p;
823 
824 	if (buf == NULL)
825 		return (FALSE);
826 
827 	if (memcmp(buf, "Bag Attr", 8) == 0) {
828 		*fmt = KMF_FORMAT_PEM_KEYPAIR;
829 		return (TRUE);
830 	}
831 
832 	/* Look for "-----BEGIN" right after a newline */
833 	p = strtok((char *)buf, "\n");
834 	while (p != NULL) {
835 		if (strstr(p, "-----BEGIN") != NULL) {
836 			*fmt = KMF_FORMAT_PEM;
837 			return (TRUE);
838 		}
839 		p = strtok(NULL, "\n");
840 	}
841 	return (FALSE);
842 }
843 
844 
845 static unsigned char pkcs12_version[3] = {0x02, 0x01, 0x03};
846 static unsigned char pkcs12_oid[11] =
847 {0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01};
848 
849 /*
850  * This function takes a BER encoded string as input and checks the version
851  * and the oid in the the top-level ASN.1 structure to see if it complies to
852  * the PKCS#12 Syntax.
853  */
854 static boolean_t
855 check_for_pkcs12(uchar_t *buf, int buf_len)
856 {
857 	int index = 0;
858 	int length_octets;
859 
860 	if (buf == NULL || buf_len <= 0)
861 		return (FALSE);
862 
863 	/*
864 	 * The top level structure for a PKCS12 string:
865 	 *
866 	 * PFX ::= SEQUENCE {
867 	 *	version		INTEGER {v3(3)}(v3,...)
868 	 *	authSafe	ContentInfo
869 	 *	macData		MacData OPTIONAL
870 	 * }
871 	 *
872 	 * ContentInfo
873 	 *	FROM PKCS-7 {iso(1) member-body(2) us(840) rsadsi(113549)
874 	 *		pkcs(1) pkcs-7(7) modules(0) pkcs-7(1)}
875 	 *
876 	 * Therefore, the BER/DER dump of a PKCS#12 file for the first 2
877 	 * sequences up to the oid part is as following:
878 	 *
879 	 *	SEQUENCE {
880 	 *	    INTEGER 3
881 	 *	    SEQUENCE {
882 	 *		OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
883 	 */
884 
885 	/*
886 	 * Check the first sequence and calculate the number of bytes used
887 	 * to store the length.
888 	 */
889 	if (buf[index++] != 0x30)
890 		return (FALSE);
891 
892 	if (buf[index] & 0x80) {
893 		length_octets = buf[index++] & 0x0F;  /* long form */
894 	} else {
895 		length_octets = 1; /* short form */
896 	}
897 
898 	index += length_octets;
899 	if (index  >= buf_len)
900 		return (FALSE);
901 
902 	/* Skip the length octets and check the pkcs12 version */
903 	if (memcmp(buf + index, pkcs12_version, sizeof (pkcs12_version)) != 0)
904 		return (FALSE);
905 
906 	index += sizeof (pkcs12_version);
907 	if (index  >= buf_len)
908 		return (FALSE);
909 
910 	/*
911 	 * Check the 2nd sequence and calculate the number of bytes used
912 	 * to store the length.
913 	 */
914 	if ((buf[index++] & 0xFF) != 0x30)
915 		return (FALSE);
916 
917 	if (buf[index] & 0x80) {
918 		length_octets = buf[index++] & 0x0F;
919 	} else {
920 		length_octets = 1;
921 	}
922 
923 	index += length_octets;
924 	if (index + sizeof (pkcs12_oid) >= buf_len)
925 		return (FALSE);
926 
927 	/* Skip the length octets and check the oid */
928 	if (memcmp(buf + index, pkcs12_oid, sizeof (pkcs12_oid)) != 0)
929 		return (FALSE);
930 	else
931 		return (TRUE);
932 }
933 
934 KMF_RETURN
935 kmf_get_file_format(char *filename, KMF_ENCODE_FORMAT *fmt)
936 {
937 	KMF_RETURN ret = KMF_OK;
938 	KMF_DATA filebuf = {NULL, 0};
939 	uchar_t *buf;
940 
941 	if (filename == NULL || !strlen(filename) || fmt == NULL)
942 		return (KMF_ERR_BAD_PARAMETER);
943 
944 	*fmt = 0;
945 	ret = kmf_read_input_file(NULL, filename, &filebuf);
946 	if (ret != KMF_OK)
947 		return (ret);
948 
949 	if (filebuf.Length < 8) {
950 		ret = KMF_ERR_ENCODING; /* too small */
951 		goto end;
952 	}
953 
954 	buf = filebuf.Data;
955 	if (check_for_pkcs12(buf, filebuf.Length) == TRUE) {
956 		*fmt = KMF_FORMAT_PKCS12;
957 	} else if (buf[0] == 0x30 && (buf[1] & 0x80)) {
958 		/* It is most likely a generic ASN.1 encoded file */
959 		*fmt = KMF_FORMAT_ASN1;
960 	} else if (check_for_pem(buf, fmt) == TRUE) {
961 		goto end;
962 	} else {
963 		/* Cannot determine this file format */
964 		*fmt = 0;
965 		ret = KMF_ERR_ENCODING;
966 	}
967 
968 end:
969 	kmf_free_data(&filebuf);
970 	return (ret);
971 }
972 
973 KMF_RETURN
974 kmf_hexstr_to_bytes(unsigned char *hexstr, unsigned char **bytes,
975 	size_t *outlen)
976 {
977 	KMF_RETURN ret = KMF_OK;
978 	unsigned char *buf = NULL;
979 	int len, stringlen;
980 	int i;
981 	unsigned char ch;
982 
983 	if (hexstr == NULL) {
984 		return (KMF_ERR_BAD_PARAMETER);
985 	}
986 
987 	if (hexstr[0] == '0' && ((hexstr[1] == 'x') || (hexstr[1] == 'X')))
988 		hexstr += 2;
989 
990 	for (i = 0; i < strlen((char *)hexstr) && isxdigit(hexstr[i]); i++)
991 		/* empty body */
992 		;
993 	/*
994 	 * If all the characters are not legitimate hex chars,
995 	 * return an error.
996 	 */
997 	if (i != strlen((char *)hexstr))
998 		return (KMF_ERR_BAD_HEX_STRING);
999 	stringlen = i;
1000 	len = (i / 2) + (i % 2);
1001 
1002 	buf = malloc(len);
1003 	if (buf == NULL) {
1004 		return (KMF_ERR_MEMORY);
1005 	}
1006 	(void) memset(buf, 0, len);
1007 
1008 	for (i = 0; i < stringlen; i++) {
1009 		ch = (unsigned char) *hexstr;
1010 		hexstr++;
1011 		if ((ch >= '0') && (ch <= '9'))
1012 			ch -= '0';
1013 		else if ((ch >= 'A') && (ch <= 'F'))
1014 			ch = ch - 'A' + 10;
1015 		else if ((ch >= 'a') && (ch <= 'f'))
1016 			ch = ch - 'a' + 10;
1017 		else {
1018 			ret = KMF_ERR_BAD_HEX_STRING;
1019 			goto out;
1020 		}
1021 
1022 		if (i & 1) {
1023 			buf[i/2] |= ch;
1024 		} else {
1025 			buf[i/2] = (ch << 4);
1026 		}
1027 	}
1028 
1029 	*bytes = buf;
1030 	*outlen = len;
1031 out:
1032 	if (buf != NULL && ret != KMF_OK) {
1033 		free(buf);
1034 	}
1035 	return (ret);
1036 }
1037 
1038 void
1039 kmf_free_dn(KMF_X509_NAME *name)
1040 {
1041 	KMF_X509_RDN 		*newrdn = NULL;
1042 	KMF_X509_TYPE_VALUE_PAIR *av = NULL;
1043 	int i, j;
1044 
1045 	if (name && name->numberOfRDNs) {
1046 		for (i = 0; i < name->numberOfRDNs; i++) {
1047 			newrdn = &name->RelativeDistinguishedName[i];
1048 			for (j = 0; j < newrdn->numberOfPairs; j++) {
1049 				av = &newrdn->AttributeTypeAndValue[j];
1050 				kmf_free_data(&av->type);
1051 				kmf_free_data(&av->value);
1052 			}
1053 			free(newrdn->AttributeTypeAndValue);
1054 			newrdn->numberOfPairs = 0;
1055 			newrdn->AttributeTypeAndValue = NULL;
1056 		}
1057 		free(name->RelativeDistinguishedName);
1058 		name->numberOfRDNs = 0;
1059 		name->RelativeDistinguishedName = NULL;
1060 	}
1061 }
1062 
1063 void
1064 kmf_free_kmf_cert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
1065 {
1066 	KMF_PLUGIN *plugin;
1067 	KMF_RETURN ret;
1068 
1069 	CLEAR_ERROR(handle, ret);
1070 	if (ret != KMF_OK)
1071 		return;
1072 
1073 	if (kmf_cert == NULL)
1074 		return;
1075 
1076 	plugin = FindPlugin(handle, kmf_cert->kmf_private.keystore_type);
1077 
1078 	if (plugin != NULL && plugin->funclist->FreeKMFCert != NULL) {
1079 		plugin->funclist->FreeKMFCert(handle, kmf_cert);
1080 	}
1081 }
1082 
1083 void
1084 kmf_free_data(KMF_DATA *datablock)
1085 {
1086 	if (datablock != NULL && datablock->Data != NULL) {
1087 		free(datablock->Data);
1088 		datablock->Data = NULL;
1089 		datablock->Length = 0;
1090 	}
1091 }
1092 
1093 void
1094 kmf_free_algoid(KMF_X509_ALGORITHM_IDENTIFIER *algoid)
1095 {
1096 	if (algoid == NULL)
1097 		return;
1098 	kmf_free_data(&algoid->algorithm);
1099 	kmf_free_data(&algoid->parameters);
1100 }
1101 
1102 void
1103 kmf_free_extn(KMF_X509_EXTENSION *exptr)
1104 {
1105 	if (exptr == NULL)
1106 		return;
1107 
1108 	kmf_free_data((KMF_DATA *)&exptr->extnId);
1109 	kmf_free_data(&exptr->BERvalue);
1110 
1111 	if (exptr->value.tagAndValue) {
1112 		kmf_free_data(&exptr->value.tagAndValue->value);
1113 		free(exptr->value.tagAndValue);
1114 	}
1115 }
1116 
1117 void
1118 kmf_free_tbs_csr(KMF_TBS_CSR *tbscsr)
1119 {
1120 	if (tbscsr) {
1121 		kmf_free_data(&tbscsr->version);
1122 
1123 		kmf_free_dn(&tbscsr->subject);
1124 
1125 		kmf_free_algoid(&tbscsr->subjectPublicKeyInfo.algorithm);
1126 		kmf_free_data(&tbscsr->subjectPublicKeyInfo.subjectPublicKey);
1127 
1128 		free_extensions(&tbscsr->extensions);
1129 	}
1130 }
1131 
1132 void
1133 kmf_free_signed_csr(KMF_CSR_DATA *csr)
1134 {
1135 	if (csr) {
1136 		kmf_free_tbs_csr(&csr->csr);
1137 
1138 		kmf_free_algoid(&csr->signature.algorithmIdentifier);
1139 		kmf_free_data(&csr->signature.encrypted);
1140 	}
1141 }
1142 
1143 static void
1144 free_validity(KMF_X509_VALIDITY *validity)
1145 {
1146 	if (validity == NULL)
1147 		return;
1148 	kmf_free_data(&validity->notBefore.time);
1149 	kmf_free_data(&validity->notAfter.time);
1150 }
1151 
1152 static void
1153 free_extensions(KMF_X509_EXTENSIONS *extns)
1154 {
1155 	int i;
1156 	KMF_X509_EXTENSION *exptr;
1157 
1158 	if (extns && extns->numberOfExtensions > 0) {
1159 		for (i = 0; i < extns->numberOfExtensions; i++) {
1160 			exptr = &extns->extensions[i];
1161 			kmf_free_extn(exptr);
1162 		}
1163 		free(extns->extensions);
1164 		extns->numberOfExtensions = 0;
1165 		extns->extensions = NULL;
1166 	}
1167 }
1168 
1169 void
1170 kmf_free_tbs_cert(KMF_X509_TBS_CERT *tbscert)
1171 {
1172 	if (tbscert) {
1173 		kmf_free_data(&tbscert->version);
1174 		kmf_free_bigint(&tbscert->serialNumber);
1175 		kmf_free_algoid(&tbscert->signature);
1176 
1177 		kmf_free_dn(&tbscert->issuer);
1178 		kmf_free_dn(&tbscert->subject);
1179 
1180 		free_validity(&tbscert->validity);
1181 
1182 		kmf_free_data(&tbscert->issuerUniqueIdentifier);
1183 		kmf_free_data(&tbscert->subjectUniqueIdentifier);
1184 
1185 		kmf_free_algoid(&tbscert->subjectPublicKeyInfo.algorithm);
1186 		kmf_free_data(&tbscert->subjectPublicKeyInfo.subjectPublicKey);
1187 
1188 		free_extensions(&tbscert->extensions);
1189 
1190 		kmf_free_data(&tbscert->issuerUniqueIdentifier);
1191 		kmf_free_data(&tbscert->subjectUniqueIdentifier);
1192 	}
1193 }
1194 
1195 void
1196 kmf_free_signed_cert(KMF_X509_CERTIFICATE *certptr)
1197 {
1198 	if (!certptr)
1199 		return;
1200 
1201 	kmf_free_tbs_cert(&certptr->certificate);
1202 
1203 	kmf_free_algoid(&certptr->signature.algorithmIdentifier);
1204 	kmf_free_data(&certptr->signature.encrypted);
1205 }
1206 
1207 void
1208 kmf_free_str(char *pstr)
1209 {
1210 	if (pstr != NULL)
1211 		free(pstr);
1212 }
1213 
1214 void
1215 free_keyidlist(KMF_OID *oidlist, int len)
1216 {
1217 	int i;
1218 	for (i = 0; i < len; i++) {
1219 		kmf_free_data((KMF_DATA *)&oidlist[i]);
1220 	}
1221 	free(oidlist);
1222 }
1223 
1224 void
1225 kmf_free_eku(KMF_X509EXT_EKU *eptr)
1226 {
1227 	if (eptr && eptr->nEKUs > 0 && eptr->keyPurposeIdList != NULL)
1228 		free_keyidlist(eptr->keyPurposeIdList, eptr->nEKUs);
1229 }
1230 
1231 void
1232 kmf_free_spki(KMF_X509_SPKI *spki)
1233 {
1234 	if (spki != NULL) {
1235 		kmf_free_algoid(&spki->algorithm);
1236 		kmf_free_data(&spki->subjectPublicKey);
1237 	}
1238 }
1239 
1240 void
1241 kmf_free_kmf_key(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key)
1242 {
1243 	KMF_PLUGIN *plugin;
1244 	KMF_RETURN ret;
1245 	KMF_ATTRIBUTE attlist[2]; /* only 2 attributes for DeleteKey op */
1246 	int i = 0;
1247 	boolean_t token_destroy = B_FALSE;
1248 
1249 	if (key == NULL)
1250 		return;
1251 
1252 	CLEAR_ERROR(handle, ret);
1253 	if (ret != KMF_OK)
1254 		return;
1255 
1256 	kmf_set_attr_at_index(attlist, i,
1257 	    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
1258 	i++;
1259 
1260 	kmf_set_attr_at_index(attlist, i,
1261 	    KMF_DESTROY_BOOL_ATTR, &token_destroy, sizeof (boolean_t));
1262 	i++;
1263 
1264 	plugin = FindPlugin(handle, key->kstype);
1265 	if (plugin != NULL && plugin->funclist->DeleteKey != NULL) {
1266 		(void) plugin->funclist->DeleteKey(handle, i, attlist);
1267 	}
1268 
1269 	if (key->keylabel)
1270 		free(key->keylabel);
1271 
1272 	if (key->israw) {
1273 		kmf_free_raw_key(key->keyp);
1274 		free(key->keyp);
1275 	}
1276 
1277 	(void) memset(key, 0, sizeof (KMF_KEY_HANDLE));
1278 }
1279 
1280 void
1281 kmf_free_bigint(KMF_BIGINT *big)
1282 {
1283 	if (big != NULL && big->val != NULL) {
1284 		/* Clear it out before returning it to the pool */
1285 		(void) memset(big->val, 0x00, big->len);
1286 		free(big->val);
1287 		big->val = NULL;
1288 		big->len = 0;
1289 	}
1290 }
1291 
1292 static void
1293 free_raw_rsa(KMF_RAW_RSA_KEY *key)
1294 {
1295 	if (key == NULL)
1296 		return;
1297 	kmf_free_bigint(&key->mod);
1298 	kmf_free_bigint(&key->pubexp);
1299 	kmf_free_bigint(&key->priexp);
1300 	kmf_free_bigint(&key->prime1);
1301 	kmf_free_bigint(&key->prime2);
1302 	kmf_free_bigint(&key->exp1);
1303 	kmf_free_bigint(&key->exp2);
1304 	kmf_free_bigint(&key->coef);
1305 }
1306 
1307 static void
1308 free_raw_dsa(KMF_RAW_DSA_KEY *key)
1309 {
1310 	if (key == NULL)
1311 		return;
1312 	kmf_free_bigint(&key->prime);
1313 	kmf_free_bigint(&key->subprime);
1314 	kmf_free_bigint(&key->base);
1315 	kmf_free_bigint(&key->value);
1316 }
1317 
1318 static void
1319 free_raw_sym(KMF_RAW_SYM_KEY *key)
1320 {
1321 	if (key == NULL)
1322 		return;
1323 	kmf_free_bigint(&key->keydata);
1324 }
1325 
1326 void
1327 kmf_free_raw_key(KMF_RAW_KEY_DATA *key)
1328 {
1329 	if (key == NULL)
1330 		return;
1331 
1332 	switch (key->keytype) {
1333 	case KMF_RSA:
1334 		free_raw_rsa(&key->rawdata.rsa);
1335 		break;
1336 	case KMF_DSA:
1337 		free_raw_dsa(&key->rawdata.dsa);
1338 		break;
1339 	case KMF_AES:
1340 	case KMF_RC4:
1341 	case KMF_DES:
1342 	case KMF_DES3:
1343 		free_raw_sym(&key->rawdata.sym);
1344 		break;
1345 	}
1346 	if (key->label) {
1347 		free(key->label);
1348 		key->label = NULL;
1349 	}
1350 	kmf_free_data(&key->id);
1351 }
1352 
1353 void
1354 kmf_free_raw_sym_key(KMF_RAW_SYM_KEY *key)
1355 {
1356 	if (key == NULL)
1357 		return;
1358 	kmf_free_bigint(&key->keydata);
1359 	free(key);
1360 }
1361 
1362 /*
1363  * This function frees the space allocated for the name portion of a
1364  * KMF_CRL_DIST_POINT.
1365  */
1366 void
1367 free_dp_name(KMF_CRL_DIST_POINT *dp)
1368 {
1369 	KMF_GENERALNAMES *fullname;
1370 	KMF_DATA *urldata;
1371 	int i;
1372 
1373 	if (dp == NULL)
1374 		return;
1375 
1376 	/* For phase 1, we only need to free the fullname space. */
1377 	fullname = &(dp->name.full_name);
1378 	if (fullname->number == 0)
1379 		return;
1380 
1381 	for (i = 0; i < fullname->number; i++) {
1382 		urldata = &(fullname->namelist[fullname->number - 1].name);
1383 		kmf_free_data(urldata);
1384 	}
1385 
1386 	free(fullname->namelist);
1387 }
1388 
1389 /*
1390  * This function frees the space allocated for a KMF_CRL_DIST_POINT.
1391  */
1392 void
1393 free_dp(KMF_CRL_DIST_POINT *dp)
1394 {
1395 	if (dp == NULL)
1396 		return;
1397 
1398 	free_dp_name(dp);
1399 	kmf_free_data(&(dp->reasons));
1400 	/* Need not to free crl_issuer space at phase 1 */
1401 }
1402 
1403 /*
1404  * This function frees space for a KMF_X509EXT_CRLDISTPOINTS internally.
1405  */
1406 void
1407 kmf_free_crl_dist_pts(KMF_X509EXT_CRLDISTPOINTS *crl_dps)
1408 {
1409 	int i;
1410 
1411 	if (crl_dps == NULL)
1412 		return;
1413 
1414 	for (i = 0; i < crl_dps->number; i++)
1415 		free_dp(&(crl_dps->dplist[i]));
1416 
1417 	free(crl_dps->dplist);
1418 }
1419 
1420 KMF_RETURN
1421 kmf_create_ocsp_request(KMF_HANDLE_T handle,
1422 	int	num_args,
1423 	KMF_ATTRIBUTE	*attrlist)
1424 {
1425 	KMF_RETURN ret = KMF_OK;
1426 	KMF_PLUGIN *plugin;
1427 	KMF_RETURN (*createReqFn)(void *, int num_args,
1428 	    KMF_ATTRIBUTE *attrlist);
1429 
1430 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
1431 		{KMF_OCSP_REQUEST_FILENAME_ATTR, FALSE, 1, 0},
1432 		{KMF_USER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1433 			sizeof (KMF_DATA)},
1434 		{KMF_ISSUER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1435 			sizeof (KMF_DATA)},
1436 	};
1437 
1438 	int num_req_attrs = sizeof (required_attrs) /
1439 	    sizeof (KMF_ATTRIBUTE_TESTER);
1440 
1441 	if (handle == NULL)
1442 		return (KMF_ERR_BAD_PARAMETER);
1443 
1444 	CLEAR_ERROR(handle, ret);
1445 
1446 	ret = test_attributes(num_req_attrs, required_attrs,
1447 	    0, NULL, num_args, attrlist);
1448 
1449 	if (ret != KMF_OK)
1450 		return (ret);
1451 
1452 	/*
1453 	 * This framework function is actually implemented in the openssl
1454 	 * plugin library, so we find the function address and call it.
1455 	 */
1456 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
1457 	if (plugin == NULL || plugin->dldesc == NULL) {
1458 		return (KMF_ERR_PLUGIN_NOTFOUND);
1459 	}
1460 
1461 	createReqFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
1462 	    "OpenSSL_CreateOCSPRequest");
1463 	if (createReqFn == NULL) {
1464 		return (KMF_ERR_FUNCTION_NOT_FOUND);
1465 	}
1466 
1467 	return (createReqFn(handle, num_args, attrlist));
1468 
1469 }
1470 
1471 KMF_RETURN
1472 kmf_get_ocsp_status_for_cert(KMF_HANDLE_T handle,
1473 	int	num_args,
1474 	KMF_ATTRIBUTE	*attrlist)
1475 {
1476 	KMF_RETURN ret = KMF_OK;
1477 	KMF_PLUGIN *plugin;
1478 	KMF_RETURN (*getCertStatusFn)(void *, int num_args,
1479 	    KMF_ATTRIBUTE *attrlist);
1480 
1481 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
1482 		{KMF_USER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1483 			sizeof (KMF_DATA)},
1484 		{KMF_ISSUER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1485 			sizeof (KMF_DATA)},
1486 		{KMF_OCSP_RESPONSE_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1487 			sizeof (KMF_DATA)},
1488 		{KMF_OCSP_RESPONSE_STATUS_ATTR, FALSE, sizeof (int),
1489 			sizeof (uint32_t)},
1490 		{KMF_OCSP_RESPONSE_REASON_ATTR, FALSE, sizeof (int),
1491 			sizeof (uint32_t)},
1492 		{KMF_OCSP_RESPONSE_CERT_STATUS_ATTR, FALSE, sizeof (int),
1493 			sizeof (uint32_t)},
1494 	};
1495 
1496 	int num_req_attrs = sizeof (required_attrs) /
1497 	    sizeof (KMF_ATTRIBUTE_TESTER);
1498 
1499 	if (handle == NULL)
1500 		return (KMF_ERR_BAD_PARAMETER);
1501 
1502 	CLEAR_ERROR(handle, ret);
1503 
1504 	ret = test_attributes(num_req_attrs, required_attrs,
1505 	    0, NULL, num_args, attrlist);
1506 
1507 	if (ret != KMF_OK)
1508 		return (ret);
1509 
1510 	/*
1511 	 * This framework function is actually implemented in the openssl
1512 	 * plugin library, so we find the function address and call it.
1513 	 */
1514 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
1515 	if (plugin == NULL || plugin->dldesc == NULL) {
1516 		return (KMF_ERR_INTERNAL);
1517 	}
1518 
1519 	getCertStatusFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
1520 	    "OpenSSL_GetOCSPStatusForCert");
1521 	if (getCertStatusFn == NULL) {
1522 		return (KMF_ERR_INTERNAL);
1523 	}
1524 
1525 	return (getCertStatusFn(handle, num_args, attrlist));
1526 
1527 }
1528 
1529 KMF_RETURN
1530 kmf_string_to_oid(char *oidstring, KMF_OID *oid)
1531 {
1532 	KMF_RETURN rv = KMF_OK;
1533 	char *cp, *bp, *startp;
1534 	int numbuf;
1535 	int onumbuf;
1536 	int nbytes, index;
1537 	int len;
1538 	unsigned char *op;
1539 
1540 	if (oidstring == NULL || oid == NULL)
1541 		return (KMF_ERR_BAD_PARAMETER);
1542 
1543 	len = strlen(oidstring);
1544 
1545 	bp = oidstring;
1546 	cp = bp;
1547 	/* Skip over leading space */
1548 	while ((bp < &cp[len]) && isspace(*bp))
1549 		bp++;
1550 
1551 	startp = bp;
1552 	nbytes = 0;
1553 
1554 	/*
1555 	 * The first two numbers are chewed up by the first octet.
1556 	 */
1557 	if (sscanf(bp, "%d", &numbuf) != 1)
1558 		return (KMF_ERR_BAD_PARAMETER);
1559 	while ((bp < &cp[len]) && isdigit(*bp))
1560 		bp++;
1561 	while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
1562 		bp++;
1563 	if (sscanf(bp, "%d", &numbuf) != 1)
1564 		return (KMF_ERR_BAD_PARAMETER);
1565 	while ((bp < &cp[len]) && isdigit(*bp))
1566 		bp++;
1567 	while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
1568 		bp++;
1569 	nbytes++;
1570 
1571 	while (isdigit(*bp)) {
1572 		if (sscanf(bp, "%d", &numbuf) != 1)
1573 			return (KMF_ERR_BAD_PARAMETER);
1574 		while (numbuf) {
1575 			nbytes++;
1576 			numbuf >>= 7;
1577 		}
1578 		while ((bp < &cp[len]) && isdigit(*bp))
1579 			bp++;
1580 		while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
1581 			bp++;
1582 	}
1583 
1584 	oid->Length = nbytes;
1585 	oid->Data = malloc(oid->Length);
1586 	if (oid->Data == NULL) {
1587 		return (KMF_ERR_MEMORY);
1588 	}
1589 	(void) memset(oid->Data, 0, oid->Length);
1590 
1591 	op = oid->Data;
1592 
1593 	bp = startp;
1594 	(void) sscanf(bp, "%d", &numbuf);
1595 
1596 	while (isdigit(*bp)) bp++;
1597 	while (isspace(*bp) || *bp == '.') bp++;
1598 
1599 	onumbuf = 40 * numbuf;
1600 	(void) sscanf(bp, "%d", &numbuf);
1601 	onumbuf += numbuf;
1602 	*op = (unsigned char) onumbuf;
1603 	op++;
1604 
1605 	while (isdigit(*bp)) bp++;
1606 	while (isspace(*bp) || *bp == '.') bp++;
1607 	while (isdigit(*bp)) {
1608 		(void) sscanf(bp, "%d", &numbuf);
1609 		nbytes = 0;
1610 		/* Have to fill in the bytes msb-first */
1611 		onumbuf = numbuf;
1612 		while (numbuf) {
1613 			nbytes++;
1614 			numbuf >>= 7;
1615 		}
1616 		numbuf = onumbuf;
1617 		op += nbytes;
1618 		index = -1;
1619 		while (numbuf) {
1620 			op[index] = (unsigned char)numbuf & 0x7f;
1621 			if (index != -1)
1622 				op[index] |= 0x80;
1623 			index--;
1624 			numbuf >>= 7;
1625 		}
1626 		while (isdigit(*bp)) bp++;
1627 		while (isspace(*bp) || *bp == '.') bp++;
1628 	}
1629 
1630 	return (rv);
1631 }
1632 
1633 static KMF_RETURN
1634 encode_rid(char *name, KMF_DATA *derdata)
1635 {
1636 	KMF_RETURN rv = KMF_OK;
1637 
1638 	if (name == NULL || derdata == NULL)
1639 		return (KMF_ERR_BAD_PARAMETER);
1640 
1641 	rv = kmf_string_to_oid(name, (KMF_OID *)derdata);
1642 
1643 	return (rv);
1644 }
1645 
1646 static KMF_RETURN
1647 encode_ipaddr(char *name, KMF_DATA *derdata)
1648 {
1649 	KMF_RETURN rv = KMF_OK;
1650 	size_t len;
1651 	in_addr_t v4;
1652 	in6_addr_t v6;
1653 	uint8_t *ptr;
1654 
1655 	if (name == NULL || derdata == NULL)
1656 		return (KMF_ERR_BAD_PARAMETER);
1657 
1658 	v4 = inet_addr(name);
1659 	if (v4 == (in_addr_t)-1) {
1660 		ptr = (uint8_t *)&v6;
1661 		if (inet_pton(AF_INET6, name, ptr) != 1)
1662 			return (KMF_ERR_ENCODING);
1663 		len = sizeof (v6);
1664 	} else {
1665 		ptr = (uint8_t *)&v4;
1666 		len = sizeof (v4);
1667 	}
1668 
1669 	derdata->Data = malloc(len);
1670 	if (derdata->Data == NULL)
1671 		return (KMF_ERR_MEMORY);
1672 	(void) memcpy(derdata->Data, ptr, len);
1673 	derdata->Length = len;
1674 
1675 	return (rv);
1676 }
1677 
1678 static KMF_RETURN
1679 verify_uri_format(char *uristring)
1680 {
1681 	KMF_RETURN ret = KMF_OK;
1682 	xmlURIPtr   uriptr = NULL;
1683 
1684 	/* Parse the URI string; get the hostname and port */
1685 	uriptr = xmlParseURI(uristring);
1686 	if (uriptr == NULL) {
1687 		ret = KMF_ERR_BAD_URI;
1688 		goto out;
1689 	}
1690 
1691 	if (uriptr->scheme == NULL || !strlen(uriptr->scheme)) {
1692 		ret = KMF_ERR_BAD_URI;
1693 		goto out;
1694 	}
1695 
1696 	if (uriptr->server == NULL || !strlen(uriptr->server)) {
1697 		ret = KMF_ERR_BAD_URI;
1698 		goto out;
1699 	}
1700 out:
1701 	if (uriptr != NULL)
1702 		xmlFreeURI(uriptr);
1703 	return (ret);
1704 }
1705 
1706 static KMF_RETURN
1707 encode_altname(char *namedata,
1708 	KMF_GENERALNAMECHOICES nametype, KMF_DATA *encodedname)
1709 {
1710 	KMF_RETURN ret = KMF_OK;
1711 	KMF_X509_NAME dnname;
1712 	uchar_t tagval;
1713 	BerElement *asn1 = NULL;
1714 	BerValue *extdata;
1715 
1716 	if (namedata == NULL || encodedname == NULL)
1717 		return (KMF_ERR_BAD_PARAMETER);
1718 
1719 	/*
1720 	 * Encode the namedata according to rules in RFC 3280 for GeneralName.
1721 	 * The input "namedata" is assumed to be an ASCII string representation
1722 	 * of the AltName, we need to convert it to correct ASN.1 here before
1723 	 * adding it to the cert.
1724 	 */
1725 	switch (nametype) {
1726 		case GENNAME_RFC822NAME: /* rfc 822 */
1727 			/* IA5String, no encoding needed */
1728 			encodedname->Data = (uchar_t *)strdup(namedata);
1729 			if (encodedname->Data == NULL)
1730 				return (KMF_ERR_MEMORY);
1731 			encodedname->Length = strlen(namedata);
1732 			tagval = (0x80 | nametype);
1733 			break;
1734 		case GENNAME_DNSNAME: /* rfc 1034 */
1735 			encodedname->Data = (uchar_t *)strdup(namedata);
1736 			if (encodedname->Data == NULL)
1737 				return (KMF_ERR_MEMORY);
1738 			encodedname->Length = strlen(namedata);
1739 			tagval = (0x80 | nametype);
1740 			break;
1741 		case GENNAME_URI: /* rfc 1738 */
1742 			ret = verify_uri_format(namedata);
1743 			if (ret != KMF_OK)
1744 				return (ret);
1745 			/* IA5String, no encoding needed */
1746 			encodedname->Data = (uchar_t *)strdup(namedata);
1747 			if (encodedname->Data == NULL)
1748 				return (KMF_ERR_MEMORY);
1749 			encodedname->Length = strlen(namedata);
1750 			tagval = (0x80 | nametype);
1751 			break;
1752 		case GENNAME_IPADDRESS:
1753 			ret =  encode_ipaddr(namedata, encodedname);
1754 			tagval = (0x80 | nametype);
1755 			break;
1756 		case GENNAME_REGISTEREDID:
1757 			ret = encode_rid(namedata, encodedname);
1758 			tagval = (0x80 | nametype);
1759 			break;
1760 		case GENNAME_DIRECTORYNAME:
1761 			ret = kmf_dn_parser(namedata, &dnname);
1762 			if (ret == KMF_OK) {
1763 				ret = DerEncodeName(&dnname, encodedname);
1764 			}
1765 			(void) kmf_free_dn(&dnname);
1766 			tagval = (0xA0 | nametype);
1767 			break;
1768 		default:
1769 			/* unsupported */
1770 			return (KMF_ERR_BAD_PARAMETER);
1771 
1772 	}
1773 	if (ret != KMF_OK) {
1774 		kmf_free_data(encodedname);
1775 		return (ret);
1776 	}
1777 
1778 	if ((asn1 = kmfder_alloc()) == NULL)
1779 		return (KMF_ERR_MEMORY);
1780 
1781 	if (kmfber_printf(asn1, "Tl", tagval, encodedname->Length) == -1)
1782 		goto cleanup;
1783 
1784 	if (kmfber_write(asn1, (char *)encodedname->Data,
1785 	    encodedname->Length, 0) == -1) {
1786 		ret = KMF_ERR_ENCODING;
1787 		goto cleanup;
1788 	}
1789 	if (kmfber_flatten(asn1, &extdata) == -1) {
1790 		ret = KMF_ERR_ENCODING;
1791 		goto cleanup;
1792 	}
1793 
1794 	kmf_free_data(encodedname);
1795 	encodedname->Data = (uchar_t *)extdata->bv_val;
1796 	encodedname->Length = extdata->bv_len;
1797 
1798 	free(extdata);
1799 
1800 cleanup:
1801 	if (asn1)
1802 		kmfber_free(asn1, 1);
1803 
1804 	if (ret != KMF_OK)
1805 		kmf_free_data(encodedname);
1806 
1807 	return (ret);
1808 }
1809 
1810 KMF_X509_EXTENSION *
1811 FindExtn(KMF_X509_EXTENSIONS *exts, KMF_OID *oid)
1812 {
1813 	KMF_X509_EXTENSION *foundextn = NULL;
1814 	int i;
1815 
1816 	if (exts == NULL || oid == NULL)
1817 		return (NULL);
1818 
1819 	for (i = 0; i < exts->numberOfExtensions; i++) {
1820 		if (IsEqualOid(oid, &exts->extensions[i].extnId))  {
1821 			foundextn = &exts->extensions[i];
1822 			break;
1823 		}
1824 	}
1825 	return (foundextn);
1826 }
1827 
1828 KMF_RETURN
1829 GetSequenceContents(char *data, size_t len,
1830 	char **contents, size_t *outlen)
1831 {
1832 	KMF_RETURN ret = KMF_OK;
1833 	BerElement *exasn1 = NULL;
1834 	BerValue oldextn;
1835 	int tag;
1836 	size_t oldsize;
1837 	char *olddata = NULL;
1838 
1839 	if (data == NULL || contents == NULL || outlen == NULL)
1840 		return (KMF_ERR_BAD_PARAMETER);
1841 
1842 	/*
1843 	 * Decode the sequence of general names
1844 	 */
1845 	oldextn.bv_val = data;
1846 	oldextn.bv_len = len;
1847 
1848 	if ((exasn1 = kmfder_init(&oldextn)) == NULL) {
1849 		ret = KMF_ERR_MEMORY;
1850 		goto out;
1851 	}
1852 
1853 	/*
1854 	 * Unwrap the sequence to find the size of the block
1855 	 * of GeneralName items in the set.
1856 	 *
1857 	 * Peek at the tag and length ("tl"),
1858 	 * then consume them ("{").
1859 	 */
1860 	if (kmfber_scanf(exasn1, "tl{", &tag, &oldsize) == KMFBER_DEFAULT ||
1861 	    oldsize == 0) {
1862 		ret = KMF_ERR_ENCODING;
1863 		goto out;
1864 	}
1865 
1866 	olddata = malloc(oldsize);
1867 	if (olddata == NULL) {
1868 		ret = KMF_ERR_MEMORY;
1869 		goto out;
1870 	}
1871 	(void) memset(olddata, 0, oldsize);
1872 	/*
1873 	 * Read the entire blob of GeneralNames, we don't
1874 	 * need to interpret them now.
1875 	 */
1876 	if (kmfber_read(exasn1, olddata, oldsize) != oldsize) {
1877 		ret = KMF_ERR_ENCODING;
1878 		goto out;
1879 	}
1880 out:
1881 	if (exasn1 != NULL)
1882 		kmfber_free(exasn1, 1);
1883 
1884 	if (ret != KMF_OK) {
1885 		*contents = NULL;
1886 		*outlen = 0;
1887 		if (olddata != NULL)
1888 			free(olddata);
1889 	} else {
1890 		*contents = olddata;
1891 		*outlen = oldsize;
1892 	}
1893 	return (ret);
1894 }
1895 
1896 KMF_RETURN
1897 add_an_extension(KMF_X509_EXTENSIONS *exts, KMF_X509_EXTENSION *newextn)
1898 {
1899 	KMF_RETURN ret = KMF_OK;
1900 	KMF_X509_EXTENSION *extlist;
1901 
1902 	if (exts == NULL || newextn == NULL)
1903 		return (KMF_ERR_BAD_PARAMETER);
1904 
1905 	extlist = malloc(sizeof (KMF_X509_EXTENSION) *
1906 	    (exts->numberOfExtensions + 1));
1907 	if (extlist == NULL)
1908 		return (KMF_ERR_MEMORY);
1909 
1910 	(void) memcpy(extlist, exts->extensions,
1911 	    exts->numberOfExtensions * sizeof (KMF_X509_EXTENSION));
1912 
1913 	(void) memcpy(&extlist[exts->numberOfExtensions], newextn,
1914 	    sizeof (KMF_X509_EXTENSION));
1915 
1916 	free(exts->extensions);
1917 	exts->numberOfExtensions++;
1918 	exts->extensions = extlist;
1919 
1920 	return (ret);
1921 }
1922 
1923 KMF_RETURN
1924 kmf_set_altname(KMF_X509_EXTENSIONS *extensions,
1925 	KMF_OID *oid,
1926 	int critical,
1927 	KMF_GENERALNAMECHOICES nametype,
1928 	char *namedata)
1929 {
1930 	KMF_RETURN ret = KMF_OK;
1931 	KMF_X509_EXTENSION subjAltName;
1932 	KMF_DATA dername = { NULL, 0 };
1933 	BerElement *asn1 = NULL;
1934 	BerValue *extdata;
1935 	char *olddata = NULL;
1936 	KMF_X509_EXTENSION *foundextn = NULL;
1937 	size_t	oldsize = 0;
1938 
1939 	if (extensions == NULL || oid == NULL || namedata == NULL)
1940 		return (KMF_ERR_BAD_PARAMETER);
1941 
1942 	ret = encode_altname(namedata, nametype, &dername);
1943 
1944 	if (ret != KMF_OK)
1945 		return (ret);
1946 
1947 	(void) memset(&subjAltName, 0, sizeof (subjAltName));
1948 
1949 	ret = copy_data(&subjAltName.extnId, oid);
1950 	if (ret != KMF_OK)
1951 		goto out;
1952 	/*
1953 	 * Check to see if this cert already has a subjectAltName.
1954 	 */
1955 	foundextn = FindExtn(extensions, oid);
1956 
1957 	if (foundextn != NULL) {
1958 		ret = GetSequenceContents(
1959 		    (char *)foundextn->BERvalue.Data,
1960 		    foundextn->BERvalue.Length,
1961 		    &olddata, &oldsize);
1962 		if (ret != KMF_OK)
1963 			goto out;
1964 	}
1965 
1966 	/*
1967 	 * Assume (!!) that the namedata given is already properly encoded.
1968 	 */
1969 	if ((asn1 = kmfder_alloc()) == NULL)
1970 		return (KMF_ERR_MEMORY);
1971 
1972 	if (kmfber_printf(asn1, "{") == -1) {
1973 		ret = KMF_ERR_ENCODING;
1974 		goto out;
1975 	}
1976 
1977 	/* Write the old extension data first */
1978 	if (olddata != NULL && oldsize > 0) {
1979 		if (kmfber_write(asn1, olddata, oldsize, 0) == -1) {
1980 			ret = KMF_ERR_ENCODING;
1981 			goto out;
1982 		}
1983 	}
1984 
1985 	/* Now add the new name to the list */
1986 	if (kmfber_write(asn1, (char *)dername.Data, dername.Length, 0) == -1) {
1987 		ret = KMF_ERR_ENCODING;
1988 		goto out;
1989 	}
1990 
1991 	/* Now close the sequence */
1992 	if (kmfber_printf(asn1, "}") == -1) {
1993 		ret = KMF_ERR_ENCODING;
1994 		goto out;
1995 	}
1996 	if (kmfber_flatten(asn1, &extdata) == -1) {
1997 		ret = KMF_ERR_ENCODING;
1998 		goto out;
1999 	}
2000 
2001 	/*
2002 	 * If we are just adding to an existing list of altNames,
2003 	 * just replace the BER data associated with the found extension.
2004 	 */
2005 	if (foundextn != NULL) {
2006 		free(foundextn->BERvalue.Data);
2007 		foundextn->critical = critical;
2008 		foundextn->BERvalue.Data = (uchar_t *)extdata->bv_val;
2009 		foundextn->BERvalue.Length = extdata->bv_len;
2010 	} else {
2011 		subjAltName.critical = critical;
2012 		subjAltName.format = KMF_X509_DATAFORMAT_ENCODED;
2013 		subjAltName.BERvalue.Data = (uchar_t *)extdata->bv_val;
2014 		subjAltName.BERvalue.Length = extdata->bv_len;
2015 		ret = add_an_extension(extensions, &subjAltName);
2016 		if (ret != KMF_OK)
2017 			free(subjAltName.BERvalue.Data);
2018 	}
2019 
2020 	free(extdata);
2021 out:
2022 	if (olddata != NULL)
2023 		free(olddata);
2024 
2025 	kmf_free_data(&dername);
2026 	if (ret != KMF_OK)
2027 		kmf_free_data(&subjAltName.extnId);
2028 	if (asn1 != NULL)
2029 		kmfber_free(asn1, 1);
2030 	return (ret);
2031 }
2032 
2033 /*
2034  * Search a list of attributes for one that matches the given type.
2035  * Return a pointer into the attribute list.  This does not
2036  * return a copy of the value, it returns a reference into the
2037  * given list.
2038  */
2039 int
2040 kmf_find_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist, int numattrs)
2041 {
2042 	int i;
2043 	for (i = 0; i < numattrs; i++) {
2044 		if (attlist[i].type == type)
2045 			return (i);
2046 	}
2047 	return (-1);
2048 }
2049 
2050 /*
2051  * Verify that a given attribute is consistent with the
2052  * "test" attribute.
2053  */
2054 static KMF_RETURN
2055 verify_attribute(KMF_ATTRIBUTE *givenattr,
2056 	KMF_ATTRIBUTE_TESTER *testattr)
2057 {
2058 	/* A NULL pValue was found where one is required */
2059 	if (testattr->null_value_ok == FALSE &&
2060 	    givenattr->pValue == NULL)
2061 		return (KMF_ERR_BAD_PARAMETER);
2062 
2063 	/* If the given valueLen is too small, return error */
2064 	if (givenattr->pValue != NULL &&
2065 	    testattr->minlen > 0 &&
2066 	    (givenattr->valueLen < testattr->minlen))
2067 		return (KMF_ERR_BAD_PARAMETER);
2068 
2069 	/* If the given valueLen is too big, return error */
2070 	if (givenattr->pValue != NULL &&
2071 	    testattr->maxlen > 0 &&
2072 	    (givenattr->valueLen > testattr->maxlen))
2073 		return (KMF_ERR_BAD_PARAMETER);
2074 
2075 	return (KMF_OK);
2076 }
2077 
2078 /*
2079  * Given a set of required attribute tests and optional
2080  * attributes, make sure that the actual attributes
2081  * being tested (attrlist below) are allowed and are
2082  * properly specified.
2083  */
2084 KMF_RETURN
2085 test_attributes(int reqnum, KMF_ATTRIBUTE_TESTER *reqattrs,
2086 	int optnum, KMF_ATTRIBUTE_TESTER *optattrs,
2087 	int numattrs, KMF_ATTRIBUTE *attrlist)
2088 {
2089 	KMF_RETURN ret = KMF_OK;
2090 	int i, idx;
2091 
2092 	/*
2093 	 * If the caller didn't supply enough attributes,
2094 	 * return an error.
2095 	 */
2096 	if (numattrs < reqnum || attrlist == NULL)
2097 		return (KMF_ERR_BAD_PARAMETER);
2098 
2099 	/*
2100 	 * Make sure all required attrs are present and
2101 	 * correct.
2102 	 */
2103 	for (i = 0; i < reqnum && ret == KMF_OK; i++) {
2104 		idx = kmf_find_attr(reqattrs[i].type, attrlist, numattrs);
2105 		/* If a required attr is not found, return error */
2106 		if (idx == -1) {
2107 			return (KMF_ERR_BAD_PARAMETER);
2108 		}
2109 
2110 		ret = verify_attribute(&attrlist[idx], &reqattrs[i]);
2111 	}
2112 	/*
2113 	 * Now test the optional parameters.
2114 	 */
2115 	for (i = 0; i < optnum && ret == KMF_OK; i++) {
2116 		idx = kmf_find_attr(optattrs[i].type, attrlist, numattrs);
2117 		/* If a optional attr is not found, continue. */
2118 		if (idx == -1) {
2119 			continue;
2120 		}
2121 
2122 		ret = verify_attribute(&attrlist[idx], &optattrs[i]);
2123 	}
2124 
2125 	return (ret);
2126 }
2127 
2128 /*
2129  * Given an already allocated attribute list, insert
2130  * the given attribute information at a specific index
2131  * in the list.
2132  */
2133 void
2134 kmf_set_attr_at_index(KMF_ATTRIBUTE *attlist, int index,
2135 	KMF_ATTR_TYPE type,  void *pValue, uint32_t len)
2136 {
2137 	if (attlist == NULL)
2138 		return;
2139 
2140 	attlist[index].type = type;
2141 	attlist[index].pValue = pValue;
2142 	attlist[index].valueLen = len;
2143 }
2144 
2145 /*
2146  * Find an attribute matching a particular type and set
2147  * the pValue and length fields to the given values.
2148  */
2149 KMF_RETURN
2150 kmf_set_attr(KMF_ATTRIBUTE *attlist, int numattr,
2151 	KMF_ATTR_TYPE type,  void *pValue, uint32_t len)
2152 {
2153 	int idx;
2154 	if (attlist == NULL)
2155 		return (KMF_ERR_BAD_PARAMETER);
2156 
2157 	idx = kmf_find_attr(type, attlist, numattr);
2158 	if (idx == -1)
2159 		return (KMF_ERR_ATTR_NOT_FOUND);
2160 
2161 	attlist[idx].type = type;
2162 	/* Assumes the attribute pValue can hold the result */
2163 	if (attlist[idx].pValue != NULL) {
2164 		if (attlist[idx].valueLen >= len)
2165 			(void) memcpy(attlist[idx].pValue, pValue, len);
2166 		else
2167 			return (KMF_ERR_BUFFER_SIZE);
2168 	}
2169 	attlist[idx].valueLen = len;
2170 	return (KMF_OK);
2171 }
2172 
2173 /*
2174  * Find a particular attribute in a list and return
2175  * a pointer to its value.
2176  */
2177 void *
2178 kmf_get_attr_ptr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist,
2179 	int numattrs)
2180 {
2181 	int i;
2182 
2183 	i = kmf_find_attr(type, attlist, numattrs);
2184 	if (i == -1)
2185 		return (NULL);
2186 
2187 	return (attlist[i].pValue);
2188 }
2189 
2190 /*
2191  * Find a particular attribute in a list and return
2192  * the value and length values.  Value and length
2193  * may be NULL if the caller doesn't want their values
2194  * to be filled in.
2195  */
2196 KMF_RETURN
2197 kmf_get_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist,
2198 	int numattrs, void *outValue, uint32_t *outlen)
2199 {
2200 	int i;
2201 	uint32_t len = 0;
2202 	uint32_t *lenptr = outlen;
2203 
2204 	if (lenptr == NULL)
2205 		lenptr = &len;
2206 
2207 	i = kmf_find_attr(type, attlist, numattrs);
2208 	if (i == -1)
2209 		return (KMF_ERR_ATTR_NOT_FOUND);
2210 
2211 	/* This assumes that the ptr passed in is pre-allocated space */
2212 	if (attlist[i].pValue != NULL && outValue != NULL) {
2213 		/*
2214 		 * If the caller did not specify a length,
2215 		 * assume "outValue" is big enough.
2216 		 */
2217 		if (outlen != NULL) {
2218 			if (*outlen >= attlist[i].valueLen)
2219 				(void) memcpy(outValue, attlist[i].pValue,
2220 				    attlist[i].valueLen);
2221 			else
2222 				return (KMF_ERR_BUFFER_SIZE);
2223 		} else {
2224 			(void) memcpy(outValue, attlist[i].pValue,
2225 			    attlist[i].valueLen);
2226 		}
2227 	}
2228 
2229 	if (outlen != NULL)
2230 		*outlen = attlist[i].valueLen;
2231 	return (KMF_OK);
2232 }
2233 
2234 /*
2235  * Utility routine to find a string type attribute, allocate it
2236  * and return the value to the caller.  This simplifies the
2237  * operation by doing both "kmf_get_attr" calls and avoids
2238  * duplicating this block of code in lots of places.
2239  */
2240 KMF_RETURN
2241 kmf_get_string_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attrlist,
2242 	int numattrs, char **outstr)
2243 {
2244 	KMF_RETURN rv;
2245 	uint32_t len;
2246 
2247 	if (outstr == NULL)
2248 		return (KMF_ERR_BAD_PARAMETER);
2249 
2250 	if ((rv = kmf_get_attr(type, attrlist, numattrs, NULL, &len)) ==
2251 	    KMF_OK) {
2252 		*outstr = malloc(len + 1);
2253 		if ((*outstr) == NULL)
2254 			return (KMF_ERR_MEMORY);
2255 		(void) memset((*outstr), 0, len + 1);
2256 		rv = kmf_get_attr(type, attrlist, numattrs, (*outstr), &len);
2257 		if (rv != KMF_OK) {
2258 			free(*outstr);
2259 			*outstr = NULL;
2260 		}
2261 	}
2262 
2263 	return (rv);
2264 }
2265 
2266 
2267 void
2268 free_entry(conf_entry_t *entry)
2269 {
2270 	if (entry == NULL)
2271 		return;
2272 	free(entry->keystore);
2273 	free(entry->modulepath);
2274 	free(entry->option);
2275 }
2276 
2277 void
2278 free_entrylist(conf_entrylist_t *list)
2279 {
2280 	conf_entrylist_t *next;
2281 
2282 	while (list != NULL) {
2283 		next = list->next;
2284 		free_entry(list->entry);
2285 		free(list);
2286 		list = next;
2287 	}
2288 }
2289 
2290 static KMF_RETURN
2291 parse_entry(char *buf, conf_entry_t **entry)
2292 {
2293 	KMF_RETURN ret = KMF_OK;
2294 	conf_entry_t *tmp = NULL;
2295 	char *token1;
2296 	char *token2;
2297 	char *token3;
2298 	char *lasts;
2299 	char *value;
2300 
2301 	if ((token1 = strtok_r(buf, SEP_COLON, &lasts)) == NULL)
2302 		return (KMF_ERR_KMF_CONF);
2303 
2304 	if ((tmp = calloc(sizeof (conf_entry_t), 1)) == NULL)
2305 		return (KMF_ERR_MEMORY);
2306 
2307 	if ((tmp->keystore = strdup(token1)) == NULL) {
2308 		ret = KMF_ERR_MEMORY;
2309 		goto end;
2310 	}
2311 
2312 	if ((token2 = strtok_r(NULL, SEP_SEMICOLON, &lasts)) == NULL) {
2313 		ret = KMF_ERR_KMF_CONF;
2314 		goto end;
2315 	}
2316 
2317 	/* need to get token3 first to satisfy nested strtok invocations */
2318 	token3 = strtok_r(NULL, SEP_SEMICOLON, &lasts);
2319 
2320 	/* parse token2 */
2321 	if (strncmp(token2, CONF_MODULEPATH, strlen(CONF_MODULEPATH)) != 0) {
2322 		ret = KMF_ERR_KMF_CONF;
2323 		goto end;
2324 	}
2325 
2326 	if (value = strpbrk(token2, SEP_EQUAL)) {
2327 		value++; /* get rid of = */
2328 	} else {
2329 		ret = KMF_ERR_KMF_CONF;
2330 		goto end;
2331 	}
2332 
2333 	if ((tmp->modulepath = strdup(value)) == NULL) {
2334 		ret = KMF_ERR_MEMORY;
2335 		goto end;
2336 	}
2337 
2338 	/* parse token3, if it exists */
2339 	if (token3 != NULL) {
2340 		if (strncmp(token3, CONF_OPTION, strlen(CONF_OPTION))
2341 		    != 0) {
2342 			ret = KMF_ERR_KMF_CONF;
2343 			goto end;
2344 		}
2345 
2346 		if (value = strpbrk(token3, SEP_EQUAL)) {
2347 			value++; /* get rid of = */
2348 		} else {
2349 			ret = KMF_ERR_KMF_CONF;
2350 			goto end;
2351 		}
2352 
2353 		if ((tmp->option = strdup(value)) == NULL) {
2354 			ret = KMF_ERR_MEMORY;
2355 			goto end;
2356 		}
2357 	}
2358 
2359 	*entry = tmp;
2360 
2361 end:
2362 	if (ret != KMF_OK) {
2363 		free_entry(tmp);
2364 		free(tmp);
2365 	}
2366 	return (ret);
2367 }
2368 
2369 
2370 conf_entry_t *
2371 dup_entry(conf_entry_t *entry)
2372 {
2373 	conf_entry_t *rtn_entry;
2374 
2375 	if (entry == NULL)
2376 		return (NULL);
2377 
2378 	rtn_entry = malloc(sizeof (conf_entry_t));
2379 	if (rtn_entry == NULL)
2380 		return (NULL);
2381 
2382 	if ((rtn_entry->keystore = strdup(entry->keystore)) == NULL)
2383 		goto out;
2384 
2385 	if ((rtn_entry->modulepath = strdup(entry->modulepath)) == NULL)
2386 		goto out;
2387 
2388 	if (entry->option != NULL &&
2389 	    (rtn_entry->option = strdup(entry->modulepath)) == NULL)
2390 		goto out;
2391 
2392 	return (rtn_entry);
2393 
2394 out:
2395 	free_entry(rtn_entry);
2396 	return (NULL);
2397 }
2398 
2399 
2400 /*
2401  * This function takes a keystore_name as input and returns
2402  * the KMF_KEYSTORE_TYPE value assigned to it.  If the "option"
2403  * argument is not NULL, this function also returns the option string
2404  * if there is an option string for the plugin module.
2405  */
2406 KMF_RETURN
2407 kmf_get_plugin_info(KMF_HANDLE_T handle, char *keystore_name,
2408     KMF_KEYSTORE_TYPE *kstype, char **option)
2409 {
2410 	KMF_RETURN ret = KMF_OK;
2411 	conf_entrylist_t  *phead = extra_plugin_list;
2412 	boolean_t is_default = B_TRUE;
2413 
2414 	/*
2415 	 * Although handle is not really used in the function, we will
2416 	 * check the handle to make sure that kmf_intialize() is called
2417 	 * before this function.
2418 	 */
2419 	if (handle == NULL || keystore_name == NULL || kstype == NULL)
2420 		return (KMF_ERR_BAD_PARAMETER);
2421 
2422 	if (strcmp(keystore_name, "pkcs11") == 0) {
2423 		*kstype = KMF_KEYSTORE_PK11TOKEN;
2424 	} else if (strcmp(keystore_name, "file") == 0) {
2425 		*kstype = KMF_KEYSTORE_OPENSSL;
2426 	} else if (strcmp(keystore_name, "nss") == 0) {
2427 		*kstype = KMF_KEYSTORE_NSS;
2428 	} else {
2429 		is_default = B_FALSE;
2430 	}
2431 
2432 	if (is_default) {
2433 		if (option != NULL)
2434 			*option = NULL;
2435 		goto out;
2436 	}
2437 
2438 	/* Not a built-in plugin; check if it is in extra_plugin_list. */
2439 	while (phead != NULL) {
2440 		if (strcmp(phead->entry->keystore, keystore_name) == 0)
2441 			break;
2442 		phead = phead->next;
2443 	}
2444 
2445 	if (phead == NULL) {
2446 		ret = KMF_ERR_PLUGIN_NOTFOUND;
2447 		goto out;
2448 	}
2449 
2450 	/* found it */
2451 	*kstype = phead->entry->kstype;
2452 	if (option != NULL) {
2453 		if (phead->entry->option == NULL)
2454 			*option = NULL;
2455 		else {
2456 			*option = strdup(phead->entry->option);
2457 			if (*option == NULL) {
2458 				ret = KMF_ERR_MEMORY;
2459 				goto out;
2460 			}
2461 		}
2462 	}
2463 
2464 out:
2465 	return (ret);
2466 }
2467 
2468 /*
2469  * Retrieve the non-default plugin list from the kmf.conf file.
2470  */
2471 KMF_RETURN
2472 get_entrylist(conf_entrylist_t **entlist)
2473 {
2474 	KMF_RETURN rv = KMF_OK;
2475 	FILE *pfile;
2476 	conf_entry_t *entry;
2477 	conf_entrylist_t *rtnlist = NULL;
2478 	conf_entrylist_t *ptmp;
2479 	conf_entrylist_t *pcur;
2480 	char buffer[MAXPATHLEN];
2481 	size_t len;
2482 
2483 	if ((pfile = fopen(_PATH_KMF_CONF, "rF")) == NULL) {
2484 		cryptoerror(LOG_ERR, "failed to open %s.\n", _PATH_KMF_CONF);
2485 		return (KMF_ERR_KMF_CONF);
2486 	}
2487 
2488 	while (fgets(buffer, MAXPATHLEN, pfile) != NULL) {
2489 		if (buffer[0] == '#' || buffer[0] == ' ' ||
2490 		    buffer[0] == '\n'|| buffer[0] == '\t') {
2491 			continue;   /* ignore comment lines */
2492 		}
2493 
2494 		len = strlen(buffer);
2495 		if (buffer[len-1] == '\n') { /* get rid of trailing '\n' */
2496 			len--;
2497 		}
2498 		buffer[len] = '\0';
2499 
2500 		rv = parse_entry(buffer, &entry);
2501 		if (rv != KMF_OK) {
2502 			goto end;
2503 		}
2504 
2505 		if ((ptmp = malloc(sizeof (conf_entrylist_t))) == NULL) {
2506 			rv = KMF_ERR_MEMORY;
2507 			goto end;
2508 		}
2509 		ptmp->entry = entry;
2510 		ptmp->next = NULL;
2511 
2512 		if (rtnlist == NULL) {
2513 			rtnlist = pcur = ptmp;
2514 		} else {
2515 			pcur->next = ptmp;
2516 			pcur = ptmp;
2517 		}
2518 	}
2519 
2520 end:
2521 	(void) fclose(pfile);
2522 
2523 	if (rv == KMF_OK) {
2524 		*entlist = rtnlist;
2525 	} else if (rtnlist != NULL) {
2526 		free_entrylist(rtnlist);
2527 		*entlist = NULL;
2528 		kstore_num = DEFAULT_KEYSTORE_NUM;
2529 	}
2530 
2531 	return (rv);
2532 }
2533 
2534 
2535 boolean_t
2536 is_valid_keystore_type(KMF_KEYSTORE_TYPE kstype)
2537 {
2538 
2539 	if (kstype > 0 && kstype <= kstore_num)
2540 		return (B_TRUE);
2541 	else
2542 		return (B_FALSE);
2543 }
2544 
2545 
2546 /*
2547  * This API is used by elfsign. We must keep it in old API form.
2548  */
2549 KMF_RETURN
2550 KMF_ConfigureKeystore(KMF_HANDLE_T handle, KMF_CONFIG_PARAMS *params)
2551 {
2552 
2553 	KMF_ATTRIBUTE attlist[32];
2554 	int i = 0;
2555 
2556 	if (params == NULL)
2557 		return (KMF_ERR_BAD_PARAMETER);
2558 
2559 	kmf_set_attr_at_index(attlist, i,
2560 	    KMF_KEYSTORE_TYPE_ATTR, &params->kstype, sizeof (params->kstype));
2561 	i++;
2562 
2563 	if (params->kstype == KMF_KEYSTORE_NSS) {
2564 		if (params->nssconfig.configdir != NULL) {
2565 			kmf_set_attr_at_index(attlist, i,
2566 			    KMF_DIRPATH_ATTR,
2567 			    params->nssconfig.configdir,
2568 			    strlen(params->nssconfig.configdir));
2569 			i++;
2570 		}
2571 		if (params->nssconfig.certPrefix != NULL) {
2572 			kmf_set_attr_at_index(attlist, i,
2573 			    KMF_CERTPREFIX_ATTR,
2574 			    params->nssconfig.certPrefix,
2575 			    strlen(params->nssconfig.certPrefix));
2576 			i++;
2577 		}
2578 		if (params->nssconfig.keyPrefix != NULL) {
2579 			kmf_set_attr_at_index(attlist, i,
2580 			    KMF_KEYPREFIX_ATTR,
2581 			    params->nssconfig.keyPrefix,
2582 			    strlen(params->nssconfig.keyPrefix));
2583 			i++;
2584 		}
2585 		if (params->nssconfig.secModName != NULL) {
2586 			kmf_set_attr_at_index(attlist, i,
2587 			    KMF_SECMODNAME_ATTR,
2588 			    params->nssconfig.secModName,
2589 			    strlen(params->nssconfig.secModName));
2590 			i++;
2591 		}
2592 	} else if (params->kstype == KMF_KEYSTORE_PK11TOKEN) {
2593 		if (params->pkcs11config.label != NULL) {
2594 			kmf_set_attr_at_index(attlist, i,
2595 			    KMF_TOKEN_LABEL_ATTR,
2596 			    params->pkcs11config.label,
2597 			    strlen(params->pkcs11config.label));
2598 			i++;
2599 		}
2600 		kmf_set_attr_at_index(attlist, i,
2601 		    KMF_READONLY_ATTR,
2602 		    &params->pkcs11config.readonly,
2603 		    sizeof (params->pkcs11config.readonly));
2604 		i++;
2605 	}
2606 
2607 	return (kmf_configure_keystore(handle, i, attlist));
2608 }
2609 
2610 /*
2611  * This API is used by elfsign. We must keep it in old API form.
2612  */
2613 KMF_RETURN
2614 KMF_Initialize(KMF_HANDLE_T *outhandle, char *policyfile, char *policyname)
2615 {
2616 	return (kmf_initialize(outhandle, policyfile, policyname));
2617 }
2618 
2619 /*
2620  * This API is used by elfsign. We must keep it in old API form.
2621  */
2622 KMF_RETURN
2623 KMF_Finalize(KMF_HANDLE_T handle)
2624 {
2625 	return (kmf_finalize(handle));
2626 }
2627 
2628 /*
2629  * This API is used by elfsign. We must keep it in old API form.
2630  */
2631 KMF_RETURN
2632 KMF_GetKMFErrorString(KMF_RETURN errcode, char **errmsg)
2633 {
2634 	return (kmf_get_kmf_error_str(errcode, errmsg));
2635 }
2636 
2637 /*
2638  * This API is used by elfsign. We must keep it in old API form.
2639  */
2640 KMF_RETURN
2641 KMF_ReadInputFile(KMF_HANDLE_T handle, char *filename,  KMF_DATA *pdata)
2642 {
2643 	return (kmf_read_input_file(handle, filename, pdata));
2644 }
2645 
2646 
2647 /*
2648  * This API is used by elfsign. We must keep it in old API form.
2649  */
2650 void
2651 KMF_FreeKMFCert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
2652 {
2653 	kmf_free_kmf_cert(handle, kmf_cert);
2654 }
2655 
2656 /*
2657  * This API is used by elfsign. We must keep it in old API form.
2658  */
2659 void
2660 KMF_FreeData(KMF_DATA *datablock)
2661 {
2662 	kmf_free_data(datablock);
2663 }
2664 
2665 /*
2666  * This API is used by elfsign. We must keep it in old API form.
2667  */
2668 void
2669 KMF_FreeKMFKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key)
2670 {
2671 	kmf_free_kmf_key(handle, key);
2672 }
2673 
2674 /*
2675  * This API is used by elfsign. We must keep it in old API form.
2676  */
2677 void
2678 KMF_FreeSignedCSR(KMF_CSR_DATA *csr)
2679 {
2680 	kmf_free_signed_csr(csr);
2681 }
2682