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