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