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