199ebb4cwyllys/*
299ebb4cwyllys * CDDL HEADER START
399ebb4cwyllys *
499ebb4cwyllys * The contents of this file are subject to the terms of the
599ebb4cwyllys * Common Development and Distribution License (the "License").
699ebb4cwyllys * You may not use this file except in compliance with the License.
799ebb4cwyllys *
899ebb4cwyllys * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
999ebb4cwyllys * or http://www.opensolaris.org/os/licensing.
1099ebb4cwyllys * See the License for the specific language governing permissions
1199ebb4cwyllys * and limitations under the License.
1299ebb4cwyllys *
1399ebb4cwyllys * When distributing Covered Code, include this CDDL HEADER in each
1499ebb4cwyllys * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1599ebb4cwyllys * If applicable, add the following below this CDDL HEADER, with the
1699ebb4cwyllys * fields enclosed by brackets "[]" replaced with your own identifying
1799ebb4cwyllys * information: Portions Copyright [yyyy] [name of copyright owner]
1899ebb4cwyllys *
1999ebb4cwyllys * CDDL HEADER END
209f0bc60Wyllys Ingersoll *
21269e59fJan Pechanec * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
2299ebb4cwyllys */
2399ebb4cwyllys
2499ebb4cwyllys#include <stdio.h>
2599ebb4cwyllys#include <dlfcn.h>
2699ebb4cwyllys#include <link.h>
2799ebb4cwyllys#include <fcntl.h>
2899ebb4cwyllys#include <ctype.h>
2999ebb4cwyllys#include <sys/param.h>
3099ebb4cwyllys#include <sys/types.h>
3199ebb4cwyllys#include <sys/stat.h>
3299ebb4cwyllys#include <errno.h>
3399ebb4cwyllys#include <sys/socket.h>
3499ebb4cwyllys#include <netinet/in.h>
3599ebb4cwyllys#include <arpa/inet.h>
3699ebb4cwyllys#include <thread.h>
3799ebb4cwyllys
3899ebb4cwyllys#include <ber_der.h>
3999ebb4cwyllys#include <kmfapiP.h>
4099ebb4cwyllys
4199ebb4cwyllys#include <pem_encode.h>
4299ebb4cwyllys#include <rdn_parser.h>
4399ebb4cwyllys#include <libxml2/libxml/uri.h>
4499ebb4cwyllys#include <libgen.h>
4599ebb4cwyllys#include <cryptoutil.h>
4699ebb4cwyllys
4799ebb4cwyllysstatic uchar_t pkcs11_initialized = 0;
4899ebb4cwyllysmutex_t init_lock = DEFAULTMUTEX;
4999ebb4cwyllysextern int errno;
5099ebb4cwyllys
5199ebb4cwyllystypedef struct {
5299ebb4cwyllys	KMF_RETURN code;
5399ebb4cwyllys	char	*message;
5499ebb4cwyllys} kmf_error_map;
5599ebb4cwyllys
5699ebb4cwyllysstatic kmf_error_map kmf_errcodes[] = {
5799ebb4cwyllys	{KMF_OK,	"KMF_OK"},
5899ebb4cwyllys	{KMF_ERR_BAD_PARAMETER,	"KMF_ERR_BAD_PARAMETER"},
5999ebb4cwyllys	{KMF_ERR_BAD_KEY_FORMAT,	"KMF_ERR_BAD_KEY_FORMAT"},
6099ebb4cwyllys	{KMF_ERR_BAD_ALGORITHM,	"KMF_ERR_BAD_ALGORITHM"},
6199ebb4cwyllys	{KMF_ERR_MEMORY,	"KMF_ERR_MEMORY"},
6299ebb4cwyllys	{KMF_ERR_ENCODING,	"KMF_ERR_ENCODING"},
6399ebb4cwyllys	{KMF_ERR_PLUGIN_INIT,	"KMF_ERR_PLUGIN_INIT"},
6499ebb4cwyllys	{KMF_ERR_PLUGIN_NOTFOUND,	"KMF_ERR_PLUGIN_NOTFOUND"},
6599ebb4cwyllys	{KMF_ERR_INTERNAL,	"KMF_ERR_INTERNAL"},
6699ebb4cwyllys	{KMF_ERR_BAD_CERT_FORMAT,	"KMF_ERR_BAD_CERT_FORMAT"},
6799ebb4cwyllys	{KMF_ERR_KEYGEN_FAILED,	"KMF_ERR_KEYGEN_FAILED"},
6899ebb4cwyllys	{KMF_ERR_UNINITIALIZED,	"KMF_ERR_UNINITIALIZED"},
6999ebb4cwyllys	{KMF_ERR_ISSUER,	"KMF_ERR_ISSUER"},
7099ebb4cwyllys	{KMF_ERR_NOT_REVOKED,	"KMF_ERR_NOT_REVOKED"},
7199ebb4cwyllys	{KMF_ERR_CERT_NOT_FOUND,	"KMF_ERR_CERT_NOT_FOUND"},
7299ebb4cwyllys	{KMF_ERR_CRL_NOT_FOUND,	"KMF_ERR_CRL_NOT_FOUND"},
7399ebb4cwyllys	{KMF_ERR_RDN_PARSER,	"KMF_ERR_RDN_PARSER"},
7499ebb4cwyllys	{KMF_ERR_RDN_ATTR,	"KMF_ERR_RDN_ATTR"},
7599ebb4cwyllys	{KMF_ERR_SLOTNAME,	"KMF_ERR_SLOTNAME"},
7699ebb4cwyllys	{KMF_ERR_EMPTY_CRL,	"KMF_ERR_EMPTY_CRL"},
7799ebb4cwyllys	{KMF_ERR_BUFFER_SIZE,	"KMF_ERR_BUFFER_SIZE"},
7899ebb4cwyllys	{KMF_ERR_AUTH_FAILED,	"KMF_ERR_AUTH_FAILED"},
7999ebb4cwyllys	{KMF_ERR_TOKEN_SELECTED,	"KMF_ERR_TOKEN_SELECTED"},
8099ebb4cwyllys	{KMF_ERR_NO_TOKEN_SELECTED,	"KMF_ERR_NO_TOKEN_SELECTED"},
8199ebb4cwyllys	{KMF_ERR_TOKEN_NOT_PRESENT,	"KMF_ERR_TOKEN_NOT_PRESENT"},
8299ebb4cwyllys	{KMF_ERR_EXTENSION_NOT_FOUND,	"KMF_ERR_EXTENSION_NOT_FOUND"},
8399ebb4cwyllys	{KMF_ERR_POLICY_ENGINE,	"KMF_ERR_POLICY_ENGINE"},
8499ebb4cwyllys	{KMF_ERR_POLICY_DB_FORMAT,	"KMF_ERR_POLICY_DB_FORMAT"},
8599ebb4cwyllys	{KMF_ERR_POLICY_NOT_FOUND,	"KMF_ERR_POLICY_NOT_FOUND"},
8699ebb4cwyllys	{KMF_ERR_POLICY_DB_FILE,	"KMF_ERR_POLICY_DB_FILE"},
8799ebb4cwyllys	{KMF_ERR_POLICY_NAME,	"KMF_ERR_POLICY_NAME"},
8899ebb4cwyllys	{KMF_ERR_OCSP_POLICY,	"KMF_ERR_OCSP_POLICY"},
8999ebb4cwyllys	{KMF_ERR_TA_POLICY,	"KMF_ERR_TA_POLICY"},
9099ebb4cwyllys	{KMF_ERR_KEY_NOT_FOUND,	"KMF_ERR_KEY_NOT_FOUND"},
9199ebb4cwyllys	{KMF_ERR_OPEN_FILE,	"KMF_ERR_OPEN_FILE"},
9299ebb4cwyllys	{KMF_ERR_OCSP_BAD_ISSUER,	"KMF_ERR_OCSP_BAD_ISSUER"},
9399ebb4cwyllys	{KMF_ERR_OCSP_BAD_CERT,	"KMF_ERR_OCSP_BAD_CERT"},
9499ebb4cwyllys	{KMF_ERR_OCSP_CREATE_REQUEST,	"KMF_ERR_OCSP_CREATE_REQUEST"},
9599ebb4cwyllys	{KMF_ERR_CONNECT_SERVER,	"KMF_ERR_CONNECT_SERVER"},
9699ebb4cwyllys	{KMF_ERR_SEND_REQUEST,	"KMF_ERR_SEND_REQUEST"},
9799ebb4cwyllys	{KMF_ERR_OCSP_CERTID,	"KMF_ERR_OCSP_CERTID"},
9899ebb4cwyllys	{KMF_ERR_OCSP_MALFORMED_RESPONSE, "KMF_ERR_OCSP_MALFORMED_RESPONSE"},
9999ebb4cwyllys	{KMF_ERR_OCSP_RESPONSE_STATUS,	"KMF_ERR_OCSP_RESPONSE_STATUS"},
10099ebb4cwyllys	{KMF_ERR_OCSP_NO_BASIC_RESPONSE, "KMF_ERR_OCSP_NO_BASIC_RESPONSE"},
10199ebb4cwyllys	{KMF_ERR_OCSP_BAD_SIGNER,	"KMF_ERR_OCSP_BAD_SIGNER"},
10299ebb4cwyllys	{KMF_ERR_OCSP_RESPONSE_SIGNATURE, "KMF_ERR_OCSP_RESPONSE_SIGNATURE"},
10399ebb4cwyllys	{KMF_ERR_OCSP_UNKNOWN_CERT,	"KMF_ERR_OCSP_UNKNOWN_CERT"},
10499ebb4cwyllys	{KMF_ERR_OCSP_STATUS_TIME_INVALID, "KMF_ERR_OCSP_STATUS_TIME_INVALID"},
10599ebb4cwyllys	{KMF_ERR_BAD_HTTP_RESPONSE,	"KMF_ERR_BAD_HTTP_RESPONSE"},
10699ebb4cwyllys	{KMF_ERR_RECV_RESPONSE,	"KMF_ERR_RECV_RESPONSE"},
10799ebb4cwyllys	{KMF_ERR_RECV_TIMEOUT,	"KMF_ERR_RECV_TIMEOUT"},
10899ebb4cwyllys	{KMF_ERR_DUPLICATE_KEYFILE,	"KMF_ERR_DUPLICATE_KEYFILE"},
10999ebb4cwyllys	{KMF_ERR_AMBIGUOUS_PATHNAME,	"KMF_ERR_AMBIGUOUS_PATHNAME"},
11099ebb4cwyllys	{KMF_ERR_FUNCTION_NOT_FOUND,	"KMF_ERR_FUNCTION_NOT_FOUND"},
11199ebb4cwyllys	{KMF_ERR_PKCS12_FORMAT,	"KMF_ERR_PKCS12_FORMAT"},
11299ebb4cwyllys	{KMF_ERR_BAD_KEY_TYPE,	"KMF_ERR_BAD_KEY_TYPE"},
11399ebb4cwyllys	{KMF_ERR_BAD_KEY_CLASS,	"KMF_ERR_BAD_KEY_CLASS"},
11499ebb4cwyllys	{KMF_ERR_BAD_KEY_SIZE,	"KMF_ERR_BAD_KEY_SIZE"},
11599ebb4cwyllys	{KMF_ERR_BAD_HEX_STRING,	"KMF_ERR_BAD_HEX_STRING"},
11699ebb4cwyllys	{KMF_ERR_KEYUSAGE,	"KMF_ERR_KEYUSAGE"},
11799ebb4cwyllys	{KMF_ERR_VALIDITY_PERIOD,	"KMF_ERR_VALIDITY_PERIOD"},
11899ebb4cwyllys	{KMF_ERR_OCSP_REVOKED,	"KMF_ERR_OCSP_REVOKED"},
11999ebb4cwyllys	{KMF_ERR_CERT_MULTIPLE_FOUND,	"KMF_ERR_CERT_MULTIPLE_FOUND"},
12099ebb4cwyllys	{KMF_ERR_WRITE_FILE,	"KMF_ERR_WRITE_FILE"},
12199ebb4cwyllys	{KMF_ERR_BAD_URI,	"KMF_ERR_BAD_URI"},
12299ebb4cwyllys	{KMF_ERR_BAD_CRLFILE,	"KMF_ERR_BAD_CRLFILE"},
12399ebb4cwyllys	{KMF_ERR_BAD_CERTFILE,	"KMF_ERR_BAD_CERTFILE"},
12499ebb4cwyllys	{KMF_ERR_GETKEYVALUE_FAILED,	"KMF_ERR_GETKEYVALUE_FAILED"},
12599ebb4cwyllys	{KMF_ERR_BAD_KEYHANDLE,	"KMF_ERR_BAD_KEYHANDLE"},
12699ebb4cwyllys	{KMF_ERR_BAD_OBJECT_TYPE,	"KMF_ERR_BAD_OBJECT_TYPE"},
12799ebb4cwyllys	{KMF_ERR_OCSP_RESPONSE_LIFETIME, "KMF_ERR_OCSP_RESPONSE_LIFETIME"},
12899ebb4cwyllys	{KMF_ERR_UNKNOWN_CSR_ATTRIBUTE,	"KMF_ERR_UNKNOWN_CSR_ATTRIBUTE"},
12999ebb4cwyllys	{KMF_ERR_UNINITIALIZED_TOKEN,	"KMF_ERR_UNINITIALIZED_TOKEN"},
13099ebb4cwyllys	{KMF_ERR_INCOMPLETE_TBS_CERT,	"KMF_ERR_INCOMPLETE_TBS_CERT"},
13199ebb4cwyllys	{KMF_ERR_MISSING_ERRCODE,	"KMF_ERR_MISSING_ERRCODE"},
13271593dbwyllys	{KMF_KEYSTORE_ALREADY_INITIALIZED, "KMF_KEYSTORE_ALREADY_INITIALIZED"},
13371593dbwyllys	{KMF_ERR_SENSITIVE_KEY,		"KMF_ERR_SENSITIVE_KEY"},
13471593dbwyllys	{KMF_ERR_UNEXTRACTABLE_KEY,	"KMF_ERR_UNEXTRACTABLE_KEY"},
135d00756cwyllys	{KMF_ERR_KEY_MISMATCH,		"KMF_ERR_KEY_MISMATCH"},
136d00756cwyllys	{KMF_ERR_ATTR_NOT_FOUND,	"KMF_ERR_ATTR_NOT_FOUND"},
137269e59fJan Pechanec	{KMF_ERR_KMF_CONF,		"KMF_ERR_KMF_CONF"},
138269e59fJan Pechanec	{KMF_ERR_NAME_NOT_MATCHED,	"KMF_ERR_NAME_NOT_MATCHED"},
139269e59fJan Pechanec	{KMF_ERR_MAPPER_OPEN,		"KMF_ERR_MAPPER_OPEN"},
140269e59fJan Pechanec	{KMF_ERR_MAPPER_NOT_FOUND,	"KMF_ERR_MAPPER_NOT_FOUND"},
141fc2613bWyllys Ingersoll	{KMF_ERR_MAPPING_FAILED,	"KMF_ERR_MAPPING_FAILED"},
142fc2613bWyllys Ingersoll	{KMF_ERR_CERT_VALIDATION,	"KMF_ERR_CERT_VALIDATION"}
14399ebb4cwyllys};
14499ebb4cwyllys
14585b65b3wyllystypedef struct {
14685b65b3wyllys	KMF_KEYSTORE_TYPE	kstype;
14785b65b3wyllys	char			*path;
14885b65b3wyllys	boolean_t		critical;
14985b65b3wyllys} KMF_PLUGIN_ITEM;
15085b65b3wyllys
15185b65b3wyllysKMF_PLUGIN_ITEM plugin_list[] = {
15285b65b3wyllys	{KMF_KEYSTORE_OPENSSL,	KMF_PLUGIN_PATH "kmf_openssl.so.1",  TRUE},
15385b65b3wyllys	{KMF_KEYSTORE_PK11TOKEN, KMF_PLUGIN_PATH "kmf_pkcs11.so.1",  TRUE},
15485b65b3wyllys	{KMF_KEYSTORE_NSS,	KMF_PLUGIN_PATH "kmf_nss.so.1",  FALSE}
15585b65b3wyllys};
15699ebb4cwyllys
15730a5e8fwyllys
15830a5e8fwyllys
15990c85bfwyllysstatic KMF_RETURN InitializePlugin(KMF_KEYSTORE_TYPE, char *, KMF_PLUGIN **);
16090c85bfwyllysstatic KMF_RETURN AddPlugin(KMF_HANDLE_T, KMF_PLUGIN *);
16199ebb4cwyllysstatic void free_extensions(KMF_X509_EXTENSIONS *extns);
16290c85bfwyllysstatic void DestroyPlugin(KMF_PLUGIN *);
16399ebb4cwyllys
164431deaahylee#if defined(__sparcv9)
165431deaahylee#define	ISA_PATH	"/sparcv9"
166431deaahylee#elif defined(__sparc)
167431deaahylee#define	ISA_PATH	"/"
168431deaahylee#elif defined(__i386)
169431deaahylee#define	ISA_PATH	"/"
170431deaahylee#elif defined(__amd64)
171431deaahylee#define	ISA_PATH	"/amd64"
172431deaahylee#endif
173431deaahylee
174431deaahylee#define	DEFAULT_KEYSTORE_NUM	3
175431deaahyleestatic int kstore_num = DEFAULT_KEYSTORE_NUM;
176431deaahyleeconf_entrylist_t *extra_plugin_list = NULL;
177431deaahyleestatic boolean_t check_extra_plugin = B_FALSE;
178431deaahyleemutex_t extra_plugin_lock = DEFAULTMUTEX;
179431deaahylee
1809b37d29wyllysKMF_RETURN
1819b37d29wyllysinit_pk11()
18299ebb4cwyllys{
1839b37d29wyllys	(void) mutex_lock(&init_lock);
1849b37d29wyllys	if (!pkcs11_initialized) {
1859b37d29wyllys		CK_RV rv = C_Initialize(NULL);
1869b37d29wyllys		if ((rv != CKR_OK) &&
1879b37d29wyllys		    (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
1889b37d29wyllys			(void) mutex_unlock(&init_lock);
1899b37d29wyllys			return (KMF_ERR_UNINITIALIZED);
1909b37d29wyllys		} else {
1919b37d29wyllys			pkcs11_initialized = 1;
1929b37d29wyllys		}
1939b37d29wyllys	}
1949b37d29wyllys	(void) mutex_unlock(&init_lock);
1959b37d29wyllys	return (KMF_OK);
19699ebb4cwyllys}
19799ebb4cwyllys
19899ebb4cwyllys/*
19999ebb4cwyllys * Private method for searching the plugin list for the correct
20099ebb4cwyllys * Plugin to use.
20199ebb4cwyllys */
20299ebb4cwyllysKMF_PLUGIN *
20399ebb4cwyllysFindPlugin(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE kstype)
20499ebb4cwyllys{
20599ebb4cwyllys	KMF_PLUGIN_LIST *node;
20690c85bfwyllys	KMF_RETURN ret = KMF_OK;
207431deaahylee	KMF_PLUGIN *pluginrec = NULL;
20899ebb4cwyllys
20999ebb4cwyllys	if (handle == NULL)
21099ebb4cwyllys		return (NULL);
21199ebb4cwyllys
21299ebb4cwyllys	node = handle->plugins;
21399ebb4cwyllys
21490c85bfwyllys	/* See if the desired plugin was already initialized. */
21599ebb4cwyllys	while (node != NULL && node->plugin->type != kstype)
21699ebb4cwyllys		node = node->next;
21799ebb4cwyllys
218431deaahylee	if (node != NULL)
219431deaahylee		return (node->plugin);
220431deaahylee
221431deaahylee	/* The plugin was not found, try to initialize it here. */
222431deaahylee	if (VALID_DEFAULT_KEYSTORE_TYPE(kstype)) {
22390c85bfwyllys		int i;
22490c85bfwyllys		int numitems = sizeof (plugin_list)/sizeof (KMF_PLUGIN_ITEM);
22590c85bfwyllys		for (i = 0; i < numitems; i++) {
22690c85bfwyllys			if (plugin_list[i].kstype == kstype) {
22790c85bfwyllys				ret = InitializePlugin(plugin_list[i].kstype,
22890c85bfwyllys				    plugin_list[i].path, &pluginrec);
22990c85bfwyllys				break;
23090c85bfwyllys			}
23190c85bfwyllys		}
23290c85bfwyllys
233431deaahylee		goto out;
234431deaahylee
235431deaahylee	} else {
236431deaahylee		/*
237431deaahylee		 * Not a built-in plugin. Check if it is in the
238431deaahylee		 * extra_plugin_list.  If it is, try to initialize it here.
239431deaahylee		 */
240431deaahylee		conf_entrylist_t *phead = extra_plugin_list;
241431deaahylee		char realpath[MAXPATHLEN];
242431deaahylee
243431deaahylee		while (phead != NULL) {
244431deaahylee			if (phead->entry->kstype == kstype)
245431deaahylee				break;
246431deaahylee			else
247431deaahylee				phead = phead->next;
248431deaahylee		}
249431deaahylee
250431deaahylee		if (phead == NULL)
25190c85bfwyllys			return (NULL);
25290c85bfwyllys
253431deaahylee		/*
254431deaahylee		 * Get the absolute path of the module.
255431deaahylee		 * - If modulepath is not a full path, then prepend it
256431deaahylee		 *   with KMF_PLUGIN_PATH.
257431deaahylee		 * - If modulepath is a full path and contain $ISA, then
258431deaahylee		 *   subsitute the architecture dependent path.
259431deaahylee		 */
260431deaahylee		(void) memset(realpath, 0, sizeof (realpath));
261431deaahylee		if (strncmp(phead->entry->modulepath, "/", 1) != 0) {
262431deaahylee			(void) snprintf(realpath, MAXPATHLEN, "%s%s",
263431deaahylee			    KMF_PLUGIN_PATH, phead->entry->modulepath);
264431deaahylee		} else {
265431deaahylee			char *buf = phead->entry->modulepath;
266431deaahylee			char *isa;
267431deaahylee
268431deaahylee			if ((isa = strstr(buf, PKCS11_ISA)) != NULL) {
269431deaahylee				char *isa_str;
270431deaahylee
271431deaahylee				(void) strncpy(realpath, buf, isa - buf);
272431deaahylee				isa_str = strdup(ISA_PATH);
273431deaahylee				if (isa_str == NULL) /* not enough memory */
274431deaahylee					return (NULL);
275431deaahylee
276431deaahylee				(void) strncat(realpath, isa_str,
277431deaahylee				    strlen(isa_str));
278431deaahylee				free(isa_str);
279431deaahylee
280431deaahylee				isa += strlen(PKCS11_ISA);
281431deaahylee				(void) strlcat(realpath, isa, MAXPATHLEN);
282431deaahylee			} else {
283431deaahylee				(void) snprintf(realpath, MAXPATHLEN, "%s",
284431deaahylee				    phead->entry->modulepath);
285431deaahylee			}
28690c85bfwyllys		}
287431deaahylee
288431deaahylee		ret = InitializePlugin(phead->entry->kstype, realpath,
289431deaahylee		    &pluginrec);
290431deaahylee		goto out;
291431deaahylee	}
292431deaahylee
293431deaahyleeout:
294431deaahylee	if (ret != KMF_OK || pluginrec == NULL)
295431deaahylee		/* No matching plugins found in the built-in list */
296431deaahylee		return (NULL);
297431deaahylee
298431deaahylee	ret = AddPlugin(handle, pluginrec);
299431deaahylee	if (ret != KMF_OK) {
300431deaahylee		DestroyPlugin(pluginrec);
301431deaahylee		pluginrec = NULL;
30290c85bfwyllys	}
303431deaahylee	return (pluginrec);
30499ebb4cwyllys}
30599ebb4cwyllys
306431deaahylee
30799ebb4cwyllysstatic KMF_RETURN
30899ebb4cwyllysInitializePlugin(KMF_KEYSTORE_TYPE kstype, char *path, KMF_PLUGIN **plugin)
30999ebb4cwyllys{
31099ebb4cwyllys	KMF_PLUGIN *p = NULL;
31199ebb4cwyllys	KMF_PLUGIN_FUNCLIST *(*sym)();
31299ebb4cwyllys
31399ebb4cwyllys	if (path == NULL || plugin == NULL)
31499ebb4cwyllys		return (KMF_ERR_BAD_PARAMETER);
31599ebb4cwyllys
31699ebb4cwyllys	*plugin = NULL;
31799ebb4cwyllys
31899ebb4cwyllys	p = (KMF_PLUGIN *)malloc(sizeof (KMF_PLUGIN));
31999ebb4cwyllys	if (p == NULL)
32099ebb4cwyllys		return (KMF_ERR_MEMORY);
32199ebb4cwyllys
32299ebb4cwyllys	p->type = kstype;
32399ebb4cwyllys	p->path = strdup(path);
32499ebb4cwyllys	if (p->path == NULL) {
32599ebb4cwyllys		free(p);
32699ebb4cwyllys		return (KMF_ERR_MEMORY);
32799ebb4cwyllys	}
3282225707Valerie Bubb Fenwick	/*
3292225707Valerie Bubb Fenwick	 * Do not use RTLD_GROUP here, or this will cause a circular
3302225707Valerie Bubb Fenwick	 * dependency when kmf_pkcs11.so.1 gets its PKCS#11 functions
3312225707Valerie Bubb Fenwick	 * from libpkcs11.so.1 when kmf is used via libelfsign.so.1
3322225707Valerie Bubb Fenwick	 * called from kcfd.
3332225707Valerie Bubb Fenwick	 */
3342225707Valerie Bubb Fenwick	p->dldesc = dlopen(path, RTLD_LAZY | RTLD_PARENT);
33599ebb4cwyllys	if (p->dldesc == NULL) {
33699ebb4cwyllys		free(p->path);
33799ebb4cwyllys		free(p);
33899ebb4cwyllys		return (KMF_ERR_PLUGIN_INIT);
33999ebb4cwyllys	}
34099ebb4cwyllys
34199ebb4cwyllys	sym = (KMF_PLUGIN_FUNCLIST *(*)())dlsym(p->dldesc,
34230a5e8fwyllys	    KMF_PLUGIN_INIT_SYMBOL);
34399ebb4cwyllys	if (sym == NULL) {
34499ebb4cwyllys		(void) dlclose(p->dldesc);
34599ebb4cwyllys		free(p->path);
34699ebb4cwyllys		free(p);
34799ebb4cwyllys		return (KMF_ERR_PLUGIN_INIT);
34899ebb4cwyllys	}
34999ebb4cwyllys
35099ebb4cwyllys	/* Get the function list */
35199ebb4cwyllys	if ((p->funclist = (*sym)()) == NULL) {
35299ebb4cwyllys		(void) dlclose(p->dldesc);
35399ebb4cwyllys		free(p->path);
35499ebb4cwyllys		free(p);
35599ebb4cwyllys		return (KMF_ERR_PLUGIN_INIT);
35699ebb4cwyllys	}
35799ebb4cwyllys
35899ebb4cwyllys	*plugin = p;
35999ebb4cwyllys
36099ebb4cwyllys	return (KMF_OK);
36199ebb4cwyllys}
36299ebb4cwyllys
36399ebb4cwyllysstatic KMF_RETURN
36499ebb4cwyllysAddPlugin(KMF_HANDLE_T handle, KMF_PLUGIN *plugin)
36599ebb4cwyllys{
36699ebb4cwyllys	KMF_PLUGIN_LIST *n;
36799ebb4cwyllys
36899ebb4cwyllys	if (handle == NULL || plugin == NULL)
36999ebb4cwyllys		return (KMF_ERR_BAD_PARAMETER);
37099ebb4cwyllys
37199ebb4cwyllys	/* If the head is NULL, create it */
37299ebb4cwyllys	if (handle->plugins == NULL) {
37399ebb4cwyllys		handle->plugins = (KMF_PLUGIN_LIST *)malloc(
37430a5e8fwyllys		    sizeof (KMF_PLUGIN_LIST));
37599ebb4cwyllys		if (handle->plugins == NULL)
37699ebb4cwyllys			return (KMF_ERR_MEMORY);
37799ebb4cwyllys		handle->plugins->plugin = plugin;
37899ebb4cwyllys		handle->plugins->next = NULL;
37999ebb4cwyllys	} else {
38099ebb4cwyllys		/* walk the list to find the tail */
38199ebb4cwyllys		n = handle->plugins;
38299ebb4cwyllys		while (n->next != NULL)
38399ebb4cwyllys			n = n->next;
38499ebb4cwyllys		n->next = (KMF_PLUGIN_LIST *)malloc(sizeof (KMF_PLUGIN_LIST));
38599ebb4cwyllys		if (n->next == NULL)
38699ebb4cwyllys			return (KMF_ERR_MEMORY);
38799ebb4cwyllys
38899ebb4cwyllys		n->next->plugin = plugin;
38999ebb4cwyllys		n->next->next = NULL;
39099ebb4cwyllys	}
39199ebb4cwyllys	return (0);
39299ebb4cwyllys}
39399ebb4cwyllys
39499ebb4cwyllysstatic void
39599ebb4cwyllysDestroyPlugin(KMF_PLUGIN *plugin)
39699ebb4cwyllys{
39799ebb4cwyllys	if (plugin) {
39899ebb4cwyllys		if (plugin->path)
39999ebb4cwyllys			free(plugin->path);
40099ebb4cwyllys		free(plugin);
40199ebb4cwyllys	}
40299ebb4cwyllys}
40399ebb4cwyllys
40499ebb4cwyllysstatic void
40599ebb4cwyllysCleanup_KMF_Handle(KMF_HANDLE_T handle)
40699ebb4cwyllys{
40799ebb4cwyllys	if (handle != NULL) {
40899ebb4cwyllys		while (handle->plugins != NULL) {
40999ebb4cwyllys			KMF_PLUGIN_LIST *next = handle->plugins->next;
41099ebb4cwyllys
41199ebb4cwyllys			DestroyPlugin(handle->plugins->plugin);
41299ebb4cwyllys			free(handle->plugins);
41399ebb4cwyllys			handle->plugins = next;
41499ebb4cwyllys		}
41530a5e8fwyllys		kmf_free_policy_record(handle->policy);
41699ebb4cwyllys		free(handle->policy);
41799ebb4cwyllys	}
41899ebb4cwyllys	free(handle);
41999ebb4cwyllys}
42099ebb4cwyllys
42199ebb4cwyllysvoid
42299ebb4cwyllysCleanup_PK11_Session(KMF_HANDLE_T handle)
42399ebb4cwyllys{
42499ebb4cwyllys	if (handle != NULL) {
42599ebb4cwyllys		/* Close active session on a pkcs11 token */
426f810c7eToomas Soome		if (handle->pk11handle != 0) {
42799ebb4cwyllys			(void) C_CloseSession(handle->pk11handle);
428f810c7eToomas Soome			handle->pk11handle = 0;
42999ebb4cwyllys		}
43099ebb4cwyllys	}
43199ebb4cwyllys}
43299ebb4cwyllys
43399ebb4cwyllysKMF_RETURN
43430a5e8fwyllyskmf_initialize(KMF_HANDLE_T *outhandle, char *policyfile, char *policyname)
43599ebb4cwyllys{
43699ebb4cwyllys	KMF_RETURN ret = KMF_OK;
43799ebb4cwyllys	KMF_HANDLE *handle = NULL;
43899ebb4cwyllys
43999ebb4cwyllys	if (outhandle == NULL)
44099ebb4cwyllys		return (KMF_ERR_BAD_PARAMETER);
44199ebb4cwyllys
44299ebb4cwyllys	*outhandle = NULL;
44399ebb4cwyllys	handle = (KMF_HANDLE *)malloc(sizeof (KMF_HANDLE));
44499ebb4cwyllys	if (handle == NULL)
44599ebb4cwyllys		return (KMF_ERR_MEMORY);
44699ebb4cwyllys
44799ebb4cwyllys	(void) memset(handle, 0, sizeof (KMF_HANDLE));
44899ebb4cwyllys	handle->plugins = NULL;
44999ebb4cwyllys
450431deaahylee	/*
451431deaahylee	 * When this function is called the first time, get the additional
452431deaahylee	 * plugins from the config file.
453431deaahylee	 */
454431deaahylee	(void) mutex_lock(&extra_plugin_lock);
455431deaahylee	if (!check_extra_plugin) {
456431deaahylee
457431deaahylee		ret = get_entrylist(&extra_plugin_list);
458431deaahylee		check_extra_plugin = B_TRUE;
459431deaahylee
460431deaahylee		/*
461431deaahylee		 * Assign the kstype number to the additional plugins here.
462431deaahylee		 * The global kstore_num will be protected by the mutex lock.
463431deaahylee		 */
464431deaahylee		if (ret == KMF_OK) {
465431deaahylee			conf_entrylist_t *phead = extra_plugin_list;
466431deaahylee			while (phead != NULL) {
467431deaahylee				phead->entry->kstype = ++kstore_num;
468431deaahylee				phead = phead->next;
469431deaahylee			}
470431deaahylee		}
471431deaahylee
472431deaahylee		/*
473431deaahylee		 * If the KMF configuration file does not exist or cannot be
474431deaahylee		 * parsed correctly, we will give a warning in syslog and
475431deaahylee		 * continue on as there is no extra plugins in the system.
476431deaahylee		 */
477431deaahylee		if (ret == KMF_ERR_KMF_CONF) {
478431deaahylee			cryptoerror(LOG_WARNING, "KMF was unable to parse "
479431deaahylee			    "the private KMF config file.\n");
480431deaahylee			ret = KMF_OK;
481431deaahylee		}
482431deaahylee
483431deaahylee		if (ret != KMF_OK) {
484431deaahylee			(void) mutex_unlock(&extra_plugin_lock);
485431deaahylee			goto errout;
486431deaahylee		}
487431deaahylee	}
488431deaahylee	(void) mutex_unlock(&extra_plugin_lock);
489431deaahylee
49099ebb4cwyllys	/* Initialize the handle with the policy */
49130a5e8fwyllys	ret = kmf_set_policy((void *)handle,
49299ebb4cwyllys	    policyfile == NULL ? KMF_DEFAULT_POLICY_FILE : policyfile,
49399ebb4cwyllys	    policyname == NULL ? KMF_DEFAULT_POLICY_NAME : policyname);
49499ebb4cwyllys	if (ret != KMF_OK)
49599ebb4cwyllys		goto errout;
49699ebb4cwyllys
497269e59fJan Pechanec	/*
498269e59fJan Pechanec	 * Let's have the mapper status structure even if no cert-to-name
499269e59fJan Pechanec	 * mapping is initialized. It's better not to coredump in the
500269e59fJan Pechanec	 * kmf_get_mapper_lasterror function, for example, when there is no
501269e59fJan Pechanec	 * mapping initialized.
502269e59fJan Pechanec	 */
503269e59fJan Pechanec	handle->mapstate = malloc(sizeof (KMF_MAPPER_STATE));
504269e59fJan Pechanec	if (handle->mapstate == NULL) {
505269e59fJan Pechanec		ret = KMF_ERR_MEMORY;
506269e59fJan Pechanec		goto errout;
507269e59fJan Pechanec	}
508269e59fJan Pechanec	handle->mapstate->lastmappererr = KMF_OK;
509269e59fJan Pechanec	handle->mapstate->options = NULL;
510269e59fJan Pechanec
511269e59fJan Pechanec	/*
512269e59fJan Pechanec	 * Initialize the mapping scheme according to the policy. If no mapping
513269e59fJan Pechanec	 * is set in the policy database we silently ignore the error.
514269e59fJan Pechanec	 */
515269e59fJan Pechanec	(void) kmf_cert_to_name_mapping_initialize(handle, 0, NULL);
516269e59fJan Pechanec
51799ebb4cwyllys	CLEAR_ERROR(handle, ret);
51899ebb4cwyllyserrout:
51999ebb4cwyllys	if (ret != KMF_OK) {
52099ebb4cwyllys		Cleanup_KMF_Handle(handle);
52199ebb4cwyllys		handle = NULL;
52299ebb4cwyllys	}
52399ebb4cwyllys
52499ebb4cwyllys	*outhandle = (KMF_HANDLE_T)handle;
52599ebb4cwyllys	return (ret);
52699ebb4cwyllys}
52799ebb4cwyllys
52899ebb4cwyllysKMF_RETURN
52930a5e8fwyllyskmf_configure_keystore(KMF_HANDLE_T handle,
53030a5e8fwyllys	int	num_args,
53130a5e8fwyllys	KMF_ATTRIBUTE	*attrlist)
53299ebb4cwyllys{
53330a5e8fwyllys	KMF_RETURN ret = KMF_OK;
53499ebb4cwyllys	KMF_PLUGIN *plugin;
53530a5e8fwyllys	KMF_KEYSTORE_TYPE kstype;
53630a5e8fwyllys	uint32_t len;
53730a5e8fwyllys
53830a5e8fwyllys	KMF_ATTRIBUTE_TESTER required_attrs[] = {
53930a5e8fwyllys		{KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
54030a5e8fwyllys	};
54130a5e8fwyllys
54230a5e8fwyllys	int num_req_attrs = sizeof (required_attrs) /
54330a5e8fwyllys	    sizeof (KMF_ATTRIBUTE_TESTER);
54430a5e8fwyllys
54530a5e8fwyllys	if (handle == NULL)
54630a5e8fwyllys		return (KMF_ERR_BAD_PARAMETER);
54799ebb4cwyllys
54899ebb4cwyllys	CLEAR_ERROR(handle, ret);
54930a5e8fwyllys
55030a5e8fwyllys	ret = test_attributes(num_req_attrs, required_attrs,
55130a5e8fwyllys	    0, NULL, num_args, attrlist);
55230a5e8fwyllys
55399ebb4cwyllys	if (ret != KMF_OK)
55499ebb4cwyllys		return (ret);
55599ebb4cwyllys
55630a5e8fwyllys	len = sizeof (kstype);
55730a5e8fwyllys	ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, num_args,
55830a5e8fwyllys	    &kstype, &len);
55930a5e8fwyllys	if (ret != KMF_OK)
56030a5e8fwyllys		return (ret);
56199ebb4cwyllys
56230a5e8fwyllys	plugin = FindPlugin(handle, kstype);
56330a5e8fwyllys	if (plugin != NULL && plugin->funclist->ConfigureKeystore != NULL) {
56430a5e8fwyllys		return (plugin->funclist->ConfigureKeystore(handle, num_args,
56530a5e8fwyllys		    attrlist));
56630a5e8fwyllys	} else {
56799ebb4cwyllys		/* return KMF_OK, if the plugin does not have an entry */
56899ebb4cwyllys		return (KMF_OK);
56930a5e8fwyllys	}
57099ebb4cwyllys}
57199ebb4cwyllys
57299ebb4cwyllysKMF_RETURN
57330a5e8fwyllyskmf_finalize(KMF_HANDLE_T handle)
57499ebb4cwyllys{
57599ebb4cwyllys	KMF_RETURN ret = KMF_OK;
57699ebb4cwyllys
57799ebb4cwyllys	CLEAR_ERROR(handle, ret);
57899ebb4cwyllys	if (ret != KMF_OK)
57999ebb4cwyllys		return (ret);
58099ebb4cwyllys
58199ebb4cwyllys	if (pkcs11_initialized) {
58299ebb4cwyllys		Cleanup_PK11_Session(handle);
58399ebb4cwyllys	}
58499ebb4cwyllys	Cleanup_KMF_Handle(handle);
58599ebb4cwyllys
58699ebb4cwyllys	return (ret);
58799ebb4cwyllys}
58899ebb4cwyllys
58999ebb4cwyllysKMF_RETURN
59030a5e8fwyllyskmf_get_kmf_error_str(KMF_RETURN errcode, char **errmsg)
59199ebb4cwyllys{
59299ebb4cwyllys	KMF_RETURN ret = KMF_OK;
59399ebb4cwyllys	int i, maxerr;
59499ebb4cwyllys
59599ebb4cwyllys	if (errmsg == NULL)
59699ebb4cwyllys		return (KMF_ERR_BAD_PARAMETER);
59799ebb4cwyllys
59899ebb4cwyllys	*errmsg = NULL;
59999ebb4cwyllys	maxerr = sizeof (kmf_errcodes) / sizeof (kmf_error_map);
60099ebb4cwyllys
60130a5e8fwyllys	for (i = 0; i < maxerr && errcode != kmf_errcodes[i].code; i++)
60230a5e8fwyllys		/* empty body */
60330a5e8fwyllys		;
60499ebb4cwyllys
60599ebb4cwyllys	if (i == maxerr)
60699ebb4cwyllys		return (KMF_ERR_MISSING_ERRCODE);
60799ebb4cwyllys	else {
60899ebb4cwyllys		*errmsg = strdup(kmf_errcodes[i].message);
60999ebb4cwyllys		if ((*errmsg) == NULL)
61099ebb4cwyllys			return (KMF_ERR_MEMORY);
61199ebb4cwyllys	}
61299ebb4cwyllys	return (ret);
61399ebb4cwyllys}
61499ebb4cwyllys
61599ebb4cwyllysKMF_RETURN
61630a5e8fwyllyskmf_get_plugin_error_str(KMF_HANDLE_T handle, char **msgstr)
61799ebb4cwyllys{
61899ebb4cwyllys	KMF_RETURN ret = KMF_OK;
61999ebb4cwyllys	KMF_PLUGIN *plugin;
62099ebb4cwyllys
62199ebb4cwyllys	if (handle == NULL || msgstr == NULL)
62299ebb4cwyllys		return (KMF_ERR_BAD_PARAMETER);
62399ebb4cwyllys
62499ebb4cwyllys	*msgstr = NULL;
62599ebb4cwyllys
62699ebb4cwyllys	if (handle->lasterr.errcode == 0) {
62799ebb4cwyllys		return (KMF_ERR_MISSING_ERRCODE);
62899ebb4cwyllys	}
62999ebb4cwyllys
63099ebb4cwyllys	if (handle->lasterr.kstype == -1) { /* System error */
63199ebb4cwyllys		char *str = strerror(handle->lasterr.errcode);
63299ebb4cwyllys		if (str != NULL) {
63399ebb4cwyllys			*msgstr = strdup(str);
63499ebb4cwyllys			if ((*msgstr) == NULL)
63599ebb4cwyllys				return (KMF_ERR_MEMORY);
63699ebb4cwyllys		}
63799ebb4cwyllys		return (KMF_OK);
63899ebb4cwyllys	}
63999ebb4cwyllys
64099ebb4cwyllys	plugin = FindPlugin(handle, handle->lasterr.kstype);
64199ebb4cwyllys	if (plugin == NULL)
64299ebb4cwyllys		return (KMF_ERR_PLUGIN_NOTFOUND);
64399ebb4cwyllys
64499ebb4cwyllys	if (plugin->funclist->GetErrorString != NULL) {
64599ebb4cwyllys		ret = plugin->funclist->GetErrorString(handle, msgstr);
64699ebb4cwyllys	} else {
64799ebb4cwyllys		return (KMF_ERR_FUNCTION_NOT_FOUND);
64899ebb4cwyllys	}
64999ebb4cwyllys
65099ebb4cwyllys	return (ret);
65199ebb4cwyllys}
65299ebb4cwyllys
65399ebb4cwyllys
6549b37d29wyllys#define	SET_SYS_ERROR(h, c) if (h) {\
6559b37d29wyllys	h->lasterr.kstype = -1;\
6569b37d29wyllys	h->lasterr.errcode = c;\
6579b37d29wyllys}
658