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