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