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
47static uchar_t pkcs11_initialized = 0;
48mutex_t init_lock = DEFAULTMUTEX;
49extern int errno;
50
51typedef struct {
52	KMF_RETURN code;
53	char	*message;
54} kmf_error_map;
55
56static 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
145typedef struct {
146	KMF_KEYSTORE_TYPE	kstype;
147	char			*path;
148	boolean_t		critical;
149} KMF_PLUGIN_ITEM;
150
151KMF_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
159static KMF_RETURN InitializePlugin(KMF_KEYSTORE_TYPE, char *, KMF_PLUGIN **);
160static KMF_RETURN AddPlugin(KMF_HANDLE_T, KMF_PLUGIN *);
161static void free_extensions(KMF_X509_EXTENSIONS *extns);
162static 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
175static int kstore_num = DEFAULT_KEYSTORE_NUM;
176conf_entrylist_t *extra_plugin_list = NULL;
177static boolean_t check_extra_plugin = B_FALSE;
178mutex_t extra_plugin_lock = DEFAULTMUTEX;
179
180KMF_RETURN
181init_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 */
202KMF_PLUGIN *
203FindPlugin(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
293out:
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
307static KMF_RETURN
308InitializePlugin(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
363static KMF_RETURN
364AddPlugin(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
394static void
395DestroyPlugin(KMF_PLUGIN *plugin)
396{
397	if (plugin) {
398		if (plugin->path)
399			free(plugin->path);
400		free(plugin);
401	}
402}
403
404static void
405Cleanup_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
421void
422Cleanup_PK11_Session(KMF_HANDLE_T handle)
423{
424	if (handle != NULL) {
425		/* Close active session on a pkcs11 token */
426		if (handle->pk11handle != 0) {
427			(void) C_CloseSession(handle->pk11handle);
428			handle->pk11handle = 0;
429		}
430	}
431}
432
433KMF_RETURN
434kmf_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);
518errout:
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
528KMF_RETURN
529kmf_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
572KMF_RETURN
573kmf_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
589KMF_RETURN
590kmf_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
615KMF_RETURN
616kmf_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
659KMF_RETURN
660kmf_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 */
732KMF_RETURN
733kmf_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 */
766KMF_RETURN
767kmf_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
778char *
779kmf_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
847static boolean_t
848check_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
882static unsigned char pkcs12_version[3] = {0x02, 0x01, 0x03};
883static 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 */
891static boolean_t
892check_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
971KMF_RETURN
972kmf_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
989KMF_RETURN
990kmf_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);
1009end:
1010	kmf_free_data(&filebuf);
1011	return (ret);
1012}
1013
1014KMF_RETURN
1015kmf_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;
1072out:
1073	if (buf != NULL && ret != KMF_OK) {
1074		free(buf);
1075	}
1076	return (ret);
1077}
1078
1079void
1080kmf_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
1104void
1105kmf_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
1124void
1125kmf_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
1134void
1135kmf_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
1143void
1144kmf_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
1158void
1159kmf_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
1173void
1174kmf_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
1184static void
1185free_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
1193static void
1194free_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
1210void
1211kmf_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
1236void
1237kmf_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
1248void
1249kmf_free_str(char *pstr)
1250{
1251	if (pstr != NULL)
1252		free(pstr);
1253}
1254
1255void
1256free_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
1265void
1266kmf_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
1272void
1273kmf_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
1281void
1282kmf_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
1321void
1322kmf_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
1333static void
1334free_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
1348static void
1349free_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
1359static void
1360free_raw_sym(KMF_RAW_SYM_KEY *key)
1361{
1362	if (key == NULL)
1363		return;
1364	kmf_free_bigint(&key->keydata);
1365}
1366
1367void
1368kmf_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
1394void
1395kmf_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 */
1407void
1408free_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 */
1433void
1434free_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 */
1447void
1448kmf_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
1461KMF_RETURN
1462kmf_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
1512KMF_RETURN
1513kmf_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
1570KMF_RETURN
1571kmf_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
1674static KMF_RETURN
1675encode_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
1687static KMF_RETURN
1688encode_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
1719static KMF_RETURN
1720encode_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
1862cleanup:
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
1878static KMF_RETURN
1879encode_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);
1902cleanup:
1903	if (asn1 != NULL)
1904		kmfber_free(asn1, 1);
1905
1906	return (rv);
1907}
1908
1909static KMF_RETURN
1910verify_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	}
1931out:
1932	if (uriptr != NULL)
1933		xmlFreeURI(uriptr);
1934	return (ret);
1935}
1936
1937static KMF_RETURN
1938encode_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
2039cleanup:
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
2049KMF_X509_EXTENSION *
2050FindExtn(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
2067KMF_RETURN
2068GetSequenceContents(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	}
2119out:
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
2135KMF_RETURN
2136add_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
2162KMF_RETURN
2163kmf_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);
2260out:
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 */
2278int
2279kmf_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 */
2293static KMF_RETURN
2294verify_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 */
2323KMF_RETURN
2324test_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 */
2372void
2373kmf_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 */
2388KMF_RETURN
2389kmf_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 */
2416void *
2417kmf_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 */
2435KMF_RETURN
2436kmf_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 */
2479KMF_RETURN
2480kmf_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
2506void
2507free_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
2516void
2517free_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
2529static KMF_RETURN
2530parse_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
2600end:
2601	if (ret != KMF_OK) {
2602		free_entry(tmp);
2603		free(tmp);
2604	}
2605	return (ret);
2606}
2607
2608
2609conf_entry_t *
2610dup_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
2633out:
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 */
2645KMF_RETURN
2646kmf_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
2703out:
2704	return (ret);
2705}
2706
2707/*
2708 * Retrieve the non-default plugin list from the kmf.conf file.
2709 */
2710KMF_RETURN
2711get_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
2759end:
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
2774boolean_t
2775is_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