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