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
2099ebb4caSwyllys  */
2199ebb4caSwyllys /*
2271593db2Swyllys  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
2399ebb4caSwyllys  * Use is subject to license terms.
2499ebb4caSwyllys  *
2599ebb4caSwyllys  */
2699ebb4caSwyllys 
2799ebb4caSwyllys #pragma ident	"%Z%%M%	%I%	%E% SMI"
2899ebb4caSwyllys 
2999ebb4caSwyllys #include <stdio.h>
3099ebb4caSwyllys #include <dlfcn.h>
3199ebb4caSwyllys #include <link.h>
3299ebb4caSwyllys #include <fcntl.h>
3399ebb4caSwyllys #include <ctype.h>
3499ebb4caSwyllys #include <sys/param.h>
3599ebb4caSwyllys #include <sys/types.h>
3699ebb4caSwyllys #include <sys/stat.h>
3799ebb4caSwyllys #include <errno.h>
3899ebb4caSwyllys #include <sys/socket.h>
3999ebb4caSwyllys #include <netinet/in.h>
4099ebb4caSwyllys #include <arpa/inet.h>
4199ebb4caSwyllys #include <thread.h>
4299ebb4caSwyllys 
4399ebb4caSwyllys #include <ber_der.h>
4499ebb4caSwyllys #include <kmfapiP.h>
4599ebb4caSwyllys 
4699ebb4caSwyllys #include <pem_encode.h>
4799ebb4caSwyllys #include <rdn_parser.h>
4899ebb4caSwyllys #include <libxml2/libxml/uri.h>
4999ebb4caSwyllys #include <libgen.h>
5099ebb4caSwyllys #include <cryptoutil.h>
5199ebb4caSwyllys 
5299ebb4caSwyllys static uchar_t pkcs11_initialized = 0;
5399ebb4caSwyllys mutex_t init_lock = DEFAULTMUTEX;
5499ebb4caSwyllys extern int errno;
5599ebb4caSwyllys 
5699ebb4caSwyllys typedef struct {
5799ebb4caSwyllys 	KMF_RETURN code;
5899ebb4caSwyllys 	char	*message;
5999ebb4caSwyllys } kmf_error_map;
6099ebb4caSwyllys 
6199ebb4caSwyllys static kmf_error_map kmf_errcodes[] = {
6299ebb4caSwyllys 	{KMF_OK,	"KMF_OK"},
6399ebb4caSwyllys 	{KMF_ERR_BAD_PARAMETER,	"KMF_ERR_BAD_PARAMETER"},
6499ebb4caSwyllys 	{KMF_ERR_BAD_KEY_FORMAT,	"KMF_ERR_BAD_KEY_FORMAT"},
6599ebb4caSwyllys 	{KMF_ERR_BAD_ALGORITHM,	"KMF_ERR_BAD_ALGORITHM"},
6699ebb4caSwyllys 	{KMF_ERR_MEMORY,	"KMF_ERR_MEMORY"},
6799ebb4caSwyllys 	{KMF_ERR_ENCODING,	"KMF_ERR_ENCODING"},
6899ebb4caSwyllys 	{KMF_ERR_PLUGIN_INIT,	"KMF_ERR_PLUGIN_INIT"},
6999ebb4caSwyllys 	{KMF_ERR_PLUGIN_NOTFOUND,	"KMF_ERR_PLUGIN_NOTFOUND"},
7099ebb4caSwyllys 	{KMF_ERR_INTERNAL,	"KMF_ERR_INTERNAL"},
7199ebb4caSwyllys 	{KMF_ERR_BAD_CERT_FORMAT,	"KMF_ERR_BAD_CERT_FORMAT"},
7299ebb4caSwyllys 	{KMF_ERR_KEYGEN_FAILED,	"KMF_ERR_KEYGEN_FAILED"},
7399ebb4caSwyllys 	{KMF_ERR_UNINITIALIZED,	"KMF_ERR_UNINITIALIZED"},
7499ebb4caSwyllys 	{KMF_ERR_ISSUER,	"KMF_ERR_ISSUER"},
7599ebb4caSwyllys 	{KMF_ERR_NOT_REVOKED,	"KMF_ERR_NOT_REVOKED"},
7699ebb4caSwyllys 	{KMF_ERR_CERT_NOT_FOUND,	"KMF_ERR_CERT_NOT_FOUND"},
7799ebb4caSwyllys 	{KMF_ERR_CRL_NOT_FOUND,	"KMF_ERR_CRL_NOT_FOUND"},
7899ebb4caSwyllys 	{KMF_ERR_RDN_PARSER,	"KMF_ERR_RDN_PARSER"},
7999ebb4caSwyllys 	{KMF_ERR_RDN_ATTR,	"KMF_ERR_RDN_ATTR"},
8099ebb4caSwyllys 	{KMF_ERR_SLOTNAME,	"KMF_ERR_SLOTNAME"},
8199ebb4caSwyllys 	{KMF_ERR_EMPTY_CRL,	"KMF_ERR_EMPTY_CRL"},
8299ebb4caSwyllys 	{KMF_ERR_BUFFER_SIZE,	"KMF_ERR_BUFFER_SIZE"},
8399ebb4caSwyllys 	{KMF_ERR_AUTH_FAILED,	"KMF_ERR_AUTH_FAILED"},
8499ebb4caSwyllys 	{KMF_ERR_TOKEN_SELECTED,	"KMF_ERR_TOKEN_SELECTED"},
8599ebb4caSwyllys 	{KMF_ERR_NO_TOKEN_SELECTED,	"KMF_ERR_NO_TOKEN_SELECTED"},
8699ebb4caSwyllys 	{KMF_ERR_TOKEN_NOT_PRESENT,	"KMF_ERR_TOKEN_NOT_PRESENT"},
8799ebb4caSwyllys 	{KMF_ERR_EXTENSION_NOT_FOUND,	"KMF_ERR_EXTENSION_NOT_FOUND"},
8899ebb4caSwyllys 	{KMF_ERR_POLICY_ENGINE,	"KMF_ERR_POLICY_ENGINE"},
8999ebb4caSwyllys 	{KMF_ERR_POLICY_DB_FORMAT,	"KMF_ERR_POLICY_DB_FORMAT"},
9099ebb4caSwyllys 	{KMF_ERR_POLICY_NOT_FOUND,	"KMF_ERR_POLICY_NOT_FOUND"},
9199ebb4caSwyllys 	{KMF_ERR_POLICY_DB_FILE,	"KMF_ERR_POLICY_DB_FILE"},
9299ebb4caSwyllys 	{KMF_ERR_POLICY_NAME,	"KMF_ERR_POLICY_NAME"},
9399ebb4caSwyllys 	{KMF_ERR_OCSP_POLICY,	"KMF_ERR_OCSP_POLICY"},
9499ebb4caSwyllys 	{KMF_ERR_TA_POLICY,	"KMF_ERR_TA_POLICY"},
9599ebb4caSwyllys 	{KMF_ERR_KEY_NOT_FOUND,	"KMF_ERR_KEY_NOT_FOUND"},
9699ebb4caSwyllys 	{KMF_ERR_OPEN_FILE,	"KMF_ERR_OPEN_FILE"},
9799ebb4caSwyllys 	{KMF_ERR_OCSP_BAD_ISSUER,	"KMF_ERR_OCSP_BAD_ISSUER"},
9899ebb4caSwyllys 	{KMF_ERR_OCSP_BAD_CERT,	"KMF_ERR_OCSP_BAD_CERT"},
9999ebb4caSwyllys 	{KMF_ERR_OCSP_CREATE_REQUEST,	"KMF_ERR_OCSP_CREATE_REQUEST"},
10099ebb4caSwyllys 	{KMF_ERR_CONNECT_SERVER,	"KMF_ERR_CONNECT_SERVER"},
10199ebb4caSwyllys 	{KMF_ERR_SEND_REQUEST,	"KMF_ERR_SEND_REQUEST"},
10299ebb4caSwyllys 	{KMF_ERR_OCSP_CERTID,	"KMF_ERR_OCSP_CERTID"},
10399ebb4caSwyllys 	{KMF_ERR_OCSP_MALFORMED_RESPONSE, "KMF_ERR_OCSP_MALFORMED_RESPONSE"},
10499ebb4caSwyllys 	{KMF_ERR_OCSP_RESPONSE_STATUS,	"KMF_ERR_OCSP_RESPONSE_STATUS"},
10599ebb4caSwyllys 	{KMF_ERR_OCSP_NO_BASIC_RESPONSE, "KMF_ERR_OCSP_NO_BASIC_RESPONSE"},
10699ebb4caSwyllys 	{KMF_ERR_OCSP_BAD_SIGNER,	"KMF_ERR_OCSP_BAD_SIGNER"},
10799ebb4caSwyllys 	{KMF_ERR_OCSP_RESPONSE_SIGNATURE, "KMF_ERR_OCSP_RESPONSE_SIGNATURE"},
10899ebb4caSwyllys 	{KMF_ERR_OCSP_UNKNOWN_CERT,	"KMF_ERR_OCSP_UNKNOWN_CERT"},
10999ebb4caSwyllys 	{KMF_ERR_OCSP_STATUS_TIME_INVALID, "KMF_ERR_OCSP_STATUS_TIME_INVALID"},
11099ebb4caSwyllys 	{KMF_ERR_BAD_HTTP_RESPONSE,	"KMF_ERR_BAD_HTTP_RESPONSE"},
11199ebb4caSwyllys 	{KMF_ERR_RECV_RESPONSE,	"KMF_ERR_RECV_RESPONSE"},
11299ebb4caSwyllys 	{KMF_ERR_RECV_TIMEOUT,	"KMF_ERR_RECV_TIMEOUT"},
11399ebb4caSwyllys 	{KMF_ERR_DUPLICATE_KEYFILE,	"KMF_ERR_DUPLICATE_KEYFILE"},
11499ebb4caSwyllys 	{KMF_ERR_AMBIGUOUS_PATHNAME,	"KMF_ERR_AMBIGUOUS_PATHNAME"},
11599ebb4caSwyllys 	{KMF_ERR_FUNCTION_NOT_FOUND,	"KMF_ERR_FUNCTION_NOT_FOUND"},
11699ebb4caSwyllys 	{KMF_ERR_PKCS12_FORMAT,	"KMF_ERR_PKCS12_FORMAT"},
11799ebb4caSwyllys 	{KMF_ERR_BAD_KEY_TYPE,	"KMF_ERR_BAD_KEY_TYPE"},
11899ebb4caSwyllys 	{KMF_ERR_BAD_KEY_CLASS,	"KMF_ERR_BAD_KEY_CLASS"},
11999ebb4caSwyllys 	{KMF_ERR_BAD_KEY_SIZE,	"KMF_ERR_BAD_KEY_SIZE"},
12099ebb4caSwyllys 	{KMF_ERR_BAD_HEX_STRING,	"KMF_ERR_BAD_HEX_STRING"},
12199ebb4caSwyllys 	{KMF_ERR_KEYUSAGE,	"KMF_ERR_KEYUSAGE"},
12299ebb4caSwyllys 	{KMF_ERR_VALIDITY_PERIOD,	"KMF_ERR_VALIDITY_PERIOD"},
12399ebb4caSwyllys 	{KMF_ERR_OCSP_REVOKED,	"KMF_ERR_OCSP_REVOKED"},
12499ebb4caSwyllys 	{KMF_ERR_CERT_MULTIPLE_FOUND,	"KMF_ERR_CERT_MULTIPLE_FOUND"},
12599ebb4caSwyllys 	{KMF_ERR_WRITE_FILE,	"KMF_ERR_WRITE_FILE"},
12699ebb4caSwyllys 	{KMF_ERR_BAD_URI,	"KMF_ERR_BAD_URI"},
12799ebb4caSwyllys 	{KMF_ERR_BAD_CRLFILE,	"KMF_ERR_BAD_CRLFILE"},
12899ebb4caSwyllys 	{KMF_ERR_BAD_CERTFILE,	"KMF_ERR_BAD_CERTFILE"},
12999ebb4caSwyllys 	{KMF_ERR_GETKEYVALUE_FAILED,	"KMF_ERR_GETKEYVALUE_FAILED"},
13099ebb4caSwyllys 	{KMF_ERR_BAD_KEYHANDLE,	"KMF_ERR_BAD_KEYHANDLE"},
13199ebb4caSwyllys 	{KMF_ERR_BAD_OBJECT_TYPE,	"KMF_ERR_BAD_OBJECT_TYPE"},
13299ebb4caSwyllys 	{KMF_ERR_OCSP_RESPONSE_LIFETIME, "KMF_ERR_OCSP_RESPONSE_LIFETIME"},
13399ebb4caSwyllys 	{KMF_ERR_UNKNOWN_CSR_ATTRIBUTE,	"KMF_ERR_UNKNOWN_CSR_ATTRIBUTE"},
13499ebb4caSwyllys 	{KMF_ERR_UNINITIALIZED_TOKEN,	"KMF_ERR_UNINITIALIZED_TOKEN"},
13599ebb4caSwyllys 	{KMF_ERR_INCOMPLETE_TBS_CERT,	"KMF_ERR_INCOMPLETE_TBS_CERT"},
13699ebb4caSwyllys 	{KMF_ERR_MISSING_ERRCODE,	"KMF_ERR_MISSING_ERRCODE"},
13771593db2Swyllys 	{KMF_KEYSTORE_ALREADY_INITIALIZED, "KMF_KEYSTORE_ALREADY_INITIALIZED"},
13871593db2Swyllys 	{KMF_ERR_SENSITIVE_KEY,		"KMF_ERR_SENSITIVE_KEY"},
13971593db2Swyllys 	{KMF_ERR_UNEXTRACTABLE_KEY,	"KMF_ERR_UNEXTRACTABLE_KEY"},
14071593db2Swyllys 	{KMF_ERR_KEY_MISMATCH,		"KMF_ERR_KEY_MISMATCH"}
14199ebb4caSwyllys };
14299ebb4caSwyllys 
14385b65b39Swyllys typedef struct {
14485b65b39Swyllys 	KMF_KEYSTORE_TYPE	kstype;
14585b65b39Swyllys 	char			*path;
14685b65b39Swyllys 	boolean_t		critical;
14785b65b39Swyllys } KMF_PLUGIN_ITEM;
14885b65b39Swyllys 
14985b65b39Swyllys KMF_PLUGIN_ITEM plugin_list[] = {
15085b65b39Swyllys 	{KMF_KEYSTORE_OPENSSL,	KMF_PLUGIN_PATH "kmf_openssl.so.1",  TRUE},
15185b65b39Swyllys 	{KMF_KEYSTORE_PK11TOKEN, KMF_PLUGIN_PATH "kmf_pkcs11.so.1",  TRUE},
15285b65b39Swyllys 	{KMF_KEYSTORE_NSS,	KMF_PLUGIN_PATH "kmf_nss.so.1",  FALSE}
15385b65b39Swyllys };
15499ebb4caSwyllys 
15530a5e8faSwyllys 
15630a5e8faSwyllys 
15790c85bf8Swyllys static KMF_RETURN InitializePlugin(KMF_KEYSTORE_TYPE, char *, KMF_PLUGIN **);
15890c85bf8Swyllys static KMF_RETURN AddPlugin(KMF_HANDLE_T, KMF_PLUGIN *);
15999ebb4caSwyllys static void free_extensions(KMF_X509_EXTENSIONS *extns);
16090c85bf8Swyllys static void DestroyPlugin(KMF_PLUGIN *);
16199ebb4caSwyllys 
162*431deaa0Shylee #if defined(__sparcv9)
163*431deaa0Shylee #define	ISA_PATH	"/sparcv9"
164*431deaa0Shylee #elif defined(__sparc)
165*431deaa0Shylee #define	ISA_PATH	"/"
166*431deaa0Shylee #elif defined(__i386)
167*431deaa0Shylee #define	ISA_PATH	"/"
168*431deaa0Shylee #elif defined(__amd64)
169*431deaa0Shylee #define	ISA_PATH	"/amd64"
170*431deaa0Shylee #endif
171*431deaa0Shylee 
172*431deaa0Shylee #define	DEFAULT_KEYSTORE_NUM	3
173*431deaa0Shylee static int kstore_num = DEFAULT_KEYSTORE_NUM;
174*431deaa0Shylee conf_entrylist_t *extra_plugin_list = NULL;
175*431deaa0Shylee static boolean_t check_extra_plugin = B_FALSE;
176*431deaa0Shylee mutex_t extra_plugin_lock = DEFAULTMUTEX;
177*431deaa0Shylee 
1789b37d296Swyllys KMF_RETURN
1799b37d296Swyllys init_pk11()
18099ebb4caSwyllys {
1819b37d296Swyllys 	(void) mutex_lock(&init_lock);
1829b37d296Swyllys 	if (!pkcs11_initialized) {
1839b37d296Swyllys 		CK_RV rv = C_Initialize(NULL);
1849b37d296Swyllys 		if ((rv != CKR_OK) &&
1859b37d296Swyllys 		    (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
1869b37d296Swyllys 			(void) mutex_unlock(&init_lock);
1879b37d296Swyllys 			return (KMF_ERR_UNINITIALIZED);
1889b37d296Swyllys 		} else {
1899b37d296Swyllys 			pkcs11_initialized = 1;
1909b37d296Swyllys 		}
1919b37d296Swyllys 	}
1929b37d296Swyllys 	(void) mutex_unlock(&init_lock);
1939b37d296Swyllys 	return (KMF_OK);
19499ebb4caSwyllys }
19599ebb4caSwyllys 
19699ebb4caSwyllys /*
19799ebb4caSwyllys  * Private method for searching the plugin list for the correct
19899ebb4caSwyllys  * Plugin to use.
19999ebb4caSwyllys  */
20099ebb4caSwyllys KMF_PLUGIN *
20199ebb4caSwyllys FindPlugin(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE kstype)
20299ebb4caSwyllys {
20399ebb4caSwyllys 	KMF_PLUGIN_LIST *node;
20490c85bf8Swyllys 	KMF_RETURN ret = KMF_OK;
205*431deaa0Shylee 	KMF_PLUGIN *pluginrec = NULL;
20699ebb4caSwyllys 
20799ebb4caSwyllys 	if (handle == NULL)
20899ebb4caSwyllys 		return (NULL);
20999ebb4caSwyllys 
21099ebb4caSwyllys 	node = handle->plugins;
21199ebb4caSwyllys 
21290c85bf8Swyllys 	/* See if the desired plugin was already initialized. */
21399ebb4caSwyllys 	while (node != NULL && node->plugin->type != kstype)
21499ebb4caSwyllys 		node = node->next;
21599ebb4caSwyllys 
216*431deaa0Shylee 	if (node != NULL)
217*431deaa0Shylee 		return (node->plugin);
218*431deaa0Shylee 
219*431deaa0Shylee 	/* The plugin was not found, try to initialize it here. */
220*431deaa0Shylee 	if (VALID_DEFAULT_KEYSTORE_TYPE(kstype)) {
22190c85bf8Swyllys 		int i;
22290c85bf8Swyllys 		int numitems = sizeof (plugin_list)/sizeof (KMF_PLUGIN_ITEM);
22390c85bf8Swyllys 		for (i = 0; i < numitems; i++) {
22490c85bf8Swyllys 			if (plugin_list[i].kstype == kstype) {
22590c85bf8Swyllys 				ret = InitializePlugin(plugin_list[i].kstype,
22690c85bf8Swyllys 				    plugin_list[i].path, &pluginrec);
22790c85bf8Swyllys 				break;
22890c85bf8Swyllys 			}
22990c85bf8Swyllys 		}
23090c85bf8Swyllys 
231*431deaa0Shylee 		goto out;
232*431deaa0Shylee 
233*431deaa0Shylee 	} else {
234*431deaa0Shylee 		/*
235*431deaa0Shylee 		 * Not a built-in plugin. Check if it is in the
236*431deaa0Shylee 		 * extra_plugin_list.  If it is, try to initialize it here.
237*431deaa0Shylee 		 */
238*431deaa0Shylee 		conf_entrylist_t *phead = extra_plugin_list;
239*431deaa0Shylee 		char realpath[MAXPATHLEN];
240*431deaa0Shylee 
241*431deaa0Shylee 		while (phead != NULL) {
242*431deaa0Shylee 			if (phead->entry->kstype == kstype)
243*431deaa0Shylee 				break;
244*431deaa0Shylee 			else
245*431deaa0Shylee 				phead = phead->next;
246*431deaa0Shylee 		}
247*431deaa0Shylee 
248*431deaa0Shylee 		if (phead == NULL)
24990c85bf8Swyllys 			return (NULL);
25090c85bf8Swyllys 
251*431deaa0Shylee 		/*
252*431deaa0Shylee 		 * Get the absolute path of the module.
253*431deaa0Shylee 		 * - If modulepath is not a full path, then prepend it
254*431deaa0Shylee 		 *   with KMF_PLUGIN_PATH.
255*431deaa0Shylee 		 * - If modulepath is a full path and contain $ISA, then
256*431deaa0Shylee 		 *   subsitute the architecture dependent path.
257*431deaa0Shylee 		 */
258*431deaa0Shylee 		(void) memset(realpath, 0, sizeof (realpath));
259*431deaa0Shylee 		if (strncmp(phead->entry->modulepath, "/", 1) != 0) {
260*431deaa0Shylee 			(void) snprintf(realpath, MAXPATHLEN, "%s%s",
261*431deaa0Shylee 			    KMF_PLUGIN_PATH, phead->entry->modulepath);
262*431deaa0Shylee 		} else {
263*431deaa0Shylee 			char *buf = phead->entry->modulepath;
264*431deaa0Shylee 			char *isa;
265*431deaa0Shylee 
266*431deaa0Shylee 			if ((isa = strstr(buf, PKCS11_ISA)) != NULL) {
267*431deaa0Shylee 				char *isa_str;
268*431deaa0Shylee 
269*431deaa0Shylee 				(void) strncpy(realpath, buf, isa - buf);
270*431deaa0Shylee 				isa_str = strdup(ISA_PATH);
271*431deaa0Shylee 				if (isa_str == NULL) /* not enough memory */
272*431deaa0Shylee 					return (NULL);
273*431deaa0Shylee 
274*431deaa0Shylee 				(void) strncat(realpath, isa_str,
275*431deaa0Shylee 				    strlen(isa_str));
276*431deaa0Shylee 				free(isa_str);
277*431deaa0Shylee 
278*431deaa0Shylee 				isa += strlen(PKCS11_ISA);
279*431deaa0Shylee 				(void) strlcat(realpath, isa, MAXPATHLEN);
280*431deaa0Shylee 			} else {
281*431deaa0Shylee 				(void) snprintf(realpath, MAXPATHLEN, "%s",
282*431deaa0Shylee 				    phead->entry->modulepath);
283*431deaa0Shylee 			}
28490c85bf8Swyllys 		}
285*431deaa0Shylee 
286*431deaa0Shylee 		ret = InitializePlugin(phead->entry->kstype, realpath,
287*431deaa0Shylee 		    &pluginrec);
288*431deaa0Shylee 		goto out;
289*431deaa0Shylee 	}
290*431deaa0Shylee 
291*431deaa0Shylee out:
292*431deaa0Shylee 	if (ret != KMF_OK || pluginrec == NULL)
293*431deaa0Shylee 		/* No matching plugins found in the built-in list */
294*431deaa0Shylee 		return (NULL);
295*431deaa0Shylee 
296*431deaa0Shylee 	ret = AddPlugin(handle, pluginrec);
297*431deaa0Shylee 	if (ret != KMF_OK) {
298*431deaa0Shylee 		DestroyPlugin(pluginrec);
299*431deaa0Shylee 		pluginrec = NULL;
30090c85bf8Swyllys 	}
301*431deaa0Shylee 	return (pluginrec);
30299ebb4caSwyllys }
30399ebb4caSwyllys 
304*431deaa0Shylee 
30599ebb4caSwyllys static KMF_RETURN
30699ebb4caSwyllys InitializePlugin(KMF_KEYSTORE_TYPE kstype, char *path, KMF_PLUGIN **plugin)
30799ebb4caSwyllys {
30899ebb4caSwyllys 	KMF_PLUGIN *p = NULL;
30999ebb4caSwyllys 	KMF_PLUGIN_FUNCLIST *(*sym)();
31099ebb4caSwyllys 
31199ebb4caSwyllys 	if (path == NULL || plugin == NULL)
31299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
31399ebb4caSwyllys 
31499ebb4caSwyllys 	*plugin = NULL;
31599ebb4caSwyllys 
31699ebb4caSwyllys 	p = (KMF_PLUGIN *)malloc(sizeof (KMF_PLUGIN));
31799ebb4caSwyllys 	if (p == NULL)
31899ebb4caSwyllys 		return (KMF_ERR_MEMORY);
31999ebb4caSwyllys 
32099ebb4caSwyllys 	p->type = kstype;
32199ebb4caSwyllys 	p->path = strdup(path);
32299ebb4caSwyllys 	if (p->path == NULL) {
32399ebb4caSwyllys 		free(p);
32499ebb4caSwyllys 		return (KMF_ERR_MEMORY);
32599ebb4caSwyllys 	}
32690c85bf8Swyllys 	p->dldesc = dlopen(path, RTLD_LAZY | RTLD_GROUP | RTLD_PARENT);
32799ebb4caSwyllys 	if (p->dldesc == NULL) {
32899ebb4caSwyllys 		free(p->path);
32999ebb4caSwyllys 		free(p);
33099ebb4caSwyllys 		return (KMF_ERR_PLUGIN_INIT);
33199ebb4caSwyllys 	}
33299ebb4caSwyllys 
33399ebb4caSwyllys 	sym = (KMF_PLUGIN_FUNCLIST *(*)())dlsym(p->dldesc,
33430a5e8faSwyllys 	    KMF_PLUGIN_INIT_SYMBOL);
33599ebb4caSwyllys 	if (sym == NULL) {
33699ebb4caSwyllys 		(void) dlclose(p->dldesc);
33799ebb4caSwyllys 		free(p->path);
33899ebb4caSwyllys 		free(p);
33999ebb4caSwyllys 		return (KMF_ERR_PLUGIN_INIT);
34099ebb4caSwyllys 	}
34199ebb4caSwyllys 
34299ebb4caSwyllys 	/* Get the function list */
34399ebb4caSwyllys 	if ((p->funclist = (*sym)()) == NULL) {
34499ebb4caSwyllys 		(void) dlclose(p->dldesc);
34599ebb4caSwyllys 		free(p->path);
34699ebb4caSwyllys 		free(p);
34799ebb4caSwyllys 		return (KMF_ERR_PLUGIN_INIT);
34899ebb4caSwyllys 	}
34999ebb4caSwyllys 
35099ebb4caSwyllys 	*plugin = p;
35199ebb4caSwyllys 
35299ebb4caSwyllys 	return (KMF_OK);
35399ebb4caSwyllys }
35499ebb4caSwyllys 
35599ebb4caSwyllys static KMF_RETURN
35699ebb4caSwyllys AddPlugin(KMF_HANDLE_T handle, KMF_PLUGIN *plugin)
35799ebb4caSwyllys {
35899ebb4caSwyllys 	KMF_PLUGIN_LIST *n;
35999ebb4caSwyllys 
36099ebb4caSwyllys 	if (handle == NULL || plugin == NULL)
36199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
36299ebb4caSwyllys 
36399ebb4caSwyllys 	/* If the head is NULL, create it */
36499ebb4caSwyllys 	if (handle->plugins == NULL) {
36599ebb4caSwyllys 		handle->plugins = (KMF_PLUGIN_LIST *)malloc(
36630a5e8faSwyllys 		    sizeof (KMF_PLUGIN_LIST));
36799ebb4caSwyllys 		if (handle->plugins == NULL)
36899ebb4caSwyllys 			return (KMF_ERR_MEMORY);
36999ebb4caSwyllys 		handle->plugins->plugin = plugin;
37099ebb4caSwyllys 		handle->plugins->next = NULL;
37199ebb4caSwyllys 	} else {
37299ebb4caSwyllys 		/* walk the list to find the tail */
37399ebb4caSwyllys 		n = handle->plugins;
37499ebb4caSwyllys 		while (n->next != NULL)
37599ebb4caSwyllys 			n = n->next;
37699ebb4caSwyllys 		n->next = (KMF_PLUGIN_LIST *)malloc(sizeof (KMF_PLUGIN_LIST));
37799ebb4caSwyllys 		if (n->next == NULL)
37899ebb4caSwyllys 			return (KMF_ERR_MEMORY);
37999ebb4caSwyllys 
38099ebb4caSwyllys 		n->next->plugin = plugin;
38199ebb4caSwyllys 		n->next->next = NULL;
38299ebb4caSwyllys 	}
38399ebb4caSwyllys 	return (0);
38499ebb4caSwyllys }
38599ebb4caSwyllys 
38699ebb4caSwyllys static void
38799ebb4caSwyllys DestroyPlugin(KMF_PLUGIN *plugin)
38899ebb4caSwyllys {
38999ebb4caSwyllys 	if (plugin) {
39099ebb4caSwyllys 		if (plugin->path)
39199ebb4caSwyllys 			free(plugin->path);
39299ebb4caSwyllys 		free(plugin);
39399ebb4caSwyllys 	}
39499ebb4caSwyllys }
39599ebb4caSwyllys 
39699ebb4caSwyllys static void
39799ebb4caSwyllys Cleanup_KMF_Handle(KMF_HANDLE_T handle)
39899ebb4caSwyllys {
39999ebb4caSwyllys 	if (handle != NULL) {
40099ebb4caSwyllys 		while (handle->plugins != NULL) {
40199ebb4caSwyllys 			KMF_PLUGIN_LIST *next = handle->plugins->next;
40299ebb4caSwyllys 
40399ebb4caSwyllys 			DestroyPlugin(handle->plugins->plugin);
40499ebb4caSwyllys 			free(handle->plugins);
40599ebb4caSwyllys 			handle->plugins = next;
40699ebb4caSwyllys 		}
40730a5e8faSwyllys 		kmf_free_policy_record(handle->policy);
40899ebb4caSwyllys 		free(handle->policy);
40999ebb4caSwyllys 	}
41099ebb4caSwyllys 	free(handle);
41199ebb4caSwyllys }
41299ebb4caSwyllys 
41399ebb4caSwyllys void
41499ebb4caSwyllys Cleanup_PK11_Session(KMF_HANDLE_T handle)
41599ebb4caSwyllys {
41699ebb4caSwyllys 	if (handle != NULL) {
41799ebb4caSwyllys 		/* Close active session on a pkcs11 token */
41899ebb4caSwyllys 		if (handle->pk11handle != NULL) {
41999ebb4caSwyllys 			(void) C_CloseSession(handle->pk11handle);
42099ebb4caSwyllys 			handle->pk11handle = NULL;
42199ebb4caSwyllys 		}
42299ebb4caSwyllys 	}
42399ebb4caSwyllys }
42499ebb4caSwyllys 
42599ebb4caSwyllys KMF_RETURN
42630a5e8faSwyllys kmf_initialize(KMF_HANDLE_T *outhandle, char *policyfile, char *policyname)
42799ebb4caSwyllys {
42899ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
42999ebb4caSwyllys 	KMF_HANDLE *handle = NULL;
43099ebb4caSwyllys 
43199ebb4caSwyllys 	if (outhandle == NULL)
43299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
43399ebb4caSwyllys 
43499ebb4caSwyllys 	*outhandle = NULL;
43599ebb4caSwyllys 	handle = (KMF_HANDLE *)malloc(sizeof (KMF_HANDLE));
43699ebb4caSwyllys 	if (handle == NULL)
43799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
43899ebb4caSwyllys 
43999ebb4caSwyllys 	(void) memset(handle, 0, sizeof (KMF_HANDLE));
44099ebb4caSwyllys 	handle->plugins = NULL;
44199ebb4caSwyllys 
442*431deaa0Shylee 	/*
443*431deaa0Shylee 	 * When this function is called the first time, get the additional
444*431deaa0Shylee 	 * plugins from the config file.
445*431deaa0Shylee 	 */
446*431deaa0Shylee 	(void) mutex_lock(&extra_plugin_lock);
447*431deaa0Shylee 	if (!check_extra_plugin) {
448*431deaa0Shylee 
449*431deaa0Shylee 		ret = get_entrylist(&extra_plugin_list);
450*431deaa0Shylee 		check_extra_plugin = B_TRUE;
451*431deaa0Shylee 
452*431deaa0Shylee 		/*
453*431deaa0Shylee 		 * Assign the kstype number to the additional plugins here.
454*431deaa0Shylee 		 * The global kstore_num will be protected by the mutex lock.
455*431deaa0Shylee 		 */
456*431deaa0Shylee 		if (ret == KMF_OK) {
457*431deaa0Shylee 			conf_entrylist_t *phead = extra_plugin_list;
458*431deaa0Shylee 			while (phead != NULL) {
459*431deaa0Shylee 				phead->entry->kstype = ++kstore_num;
460*431deaa0Shylee 				phead = phead->next;
461*431deaa0Shylee 			}
462*431deaa0Shylee 		}
463*431deaa0Shylee 
464*431deaa0Shylee 		/*
465*431deaa0Shylee 		 * If the KMF configuration file does not exist or cannot be
466*431deaa0Shylee 		 * parsed correctly, we will give a warning in syslog and
467*431deaa0Shylee 		 * continue on as there is no extra plugins in the system.
468*431deaa0Shylee 		 */
469*431deaa0Shylee 		if (ret == KMF_ERR_KMF_CONF) {
470*431deaa0Shylee 			cryptoerror(LOG_WARNING, "KMF was unable to parse "
471*431deaa0Shylee 			    "the private KMF config file.\n");
472*431deaa0Shylee 			ret = KMF_OK;
473*431deaa0Shylee 		}
474*431deaa0Shylee 
475*431deaa0Shylee 		if (ret != KMF_OK) {
476*431deaa0Shylee 			(void) mutex_unlock(&extra_plugin_lock);
477*431deaa0Shylee 			goto errout;
478*431deaa0Shylee 		}
479*431deaa0Shylee 	}
480*431deaa0Shylee 	(void) mutex_unlock(&extra_plugin_lock);
481*431deaa0Shylee 
48299ebb4caSwyllys 	/* Initialize the handle with the policy */
48330a5e8faSwyllys 	ret = kmf_set_policy((void *)handle,
48499ebb4caSwyllys 	    policyfile == NULL ? KMF_DEFAULT_POLICY_FILE : policyfile,
48599ebb4caSwyllys 	    policyname == NULL ? KMF_DEFAULT_POLICY_NAME : policyname);
48699ebb4caSwyllys 	if (ret != KMF_OK)
48799ebb4caSwyllys 		goto errout;
48899ebb4caSwyllys 
48999ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
49099ebb4caSwyllys errout:
49199ebb4caSwyllys 	if (ret != KMF_OK) {
49299ebb4caSwyllys 		Cleanup_KMF_Handle(handle);
49399ebb4caSwyllys 		handle = NULL;
49499ebb4caSwyllys 	}
49599ebb4caSwyllys 
49699ebb4caSwyllys 	*outhandle = (KMF_HANDLE_T)handle;
49799ebb4caSwyllys 	return (ret);
49899ebb4caSwyllys }
49999ebb4caSwyllys 
50099ebb4caSwyllys KMF_RETURN
50130a5e8faSwyllys kmf_configure_keystore(KMF_HANDLE_T handle,
50230a5e8faSwyllys 	int	num_args,
50330a5e8faSwyllys 	KMF_ATTRIBUTE	*attrlist)
50499ebb4caSwyllys {
50530a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
50699ebb4caSwyllys 	KMF_PLUGIN *plugin;
50730a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype;
50830a5e8faSwyllys 	uint32_t len;
50930a5e8faSwyllys 
51030a5e8faSwyllys 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
51130a5e8faSwyllys 		{KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
51230a5e8faSwyllys 	};
51330a5e8faSwyllys 
51430a5e8faSwyllys 	int num_req_attrs = sizeof (required_attrs) /
51530a5e8faSwyllys 	    sizeof (KMF_ATTRIBUTE_TESTER);
51630a5e8faSwyllys 
51730a5e8faSwyllys 	if (handle == NULL)
51830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
51999ebb4caSwyllys 
52099ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
52130a5e8faSwyllys 
52230a5e8faSwyllys 	ret = test_attributes(num_req_attrs, required_attrs,
52330a5e8faSwyllys 	    0, NULL, num_args, attrlist);
52430a5e8faSwyllys 
52599ebb4caSwyllys 	if (ret != KMF_OK)
52699ebb4caSwyllys 		return (ret);
52799ebb4caSwyllys 
52830a5e8faSwyllys 	len = sizeof (kstype);
52930a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, num_args,
53030a5e8faSwyllys 	    &kstype, &len);
53130a5e8faSwyllys 	if (ret != KMF_OK)
53230a5e8faSwyllys 		return (ret);
53399ebb4caSwyllys 
53430a5e8faSwyllys 	plugin = FindPlugin(handle, kstype);
53530a5e8faSwyllys 	if (plugin != NULL && plugin->funclist->ConfigureKeystore != NULL) {
53630a5e8faSwyllys 		return (plugin->funclist->ConfigureKeystore(handle, num_args,
53730a5e8faSwyllys 		    attrlist));
53830a5e8faSwyllys 	} else {
53999ebb4caSwyllys 		/* return KMF_OK, if the plugin does not have an entry */
54099ebb4caSwyllys 		return (KMF_OK);
54130a5e8faSwyllys 	}
54299ebb4caSwyllys }
54399ebb4caSwyllys 
54499ebb4caSwyllys KMF_RETURN
54530a5e8faSwyllys kmf_finalize(KMF_HANDLE_T handle)
54699ebb4caSwyllys {
54799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
54899ebb4caSwyllys 
54999ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
55099ebb4caSwyllys 	if (ret != KMF_OK)
55199ebb4caSwyllys 		return (ret);
55299ebb4caSwyllys 
55399ebb4caSwyllys 	if (pkcs11_initialized) {
55499ebb4caSwyllys 		Cleanup_PK11_Session(handle);
55599ebb4caSwyllys 	}
55699ebb4caSwyllys 	Cleanup_KMF_Handle(handle);
55799ebb4caSwyllys 
55899ebb4caSwyllys 	return (ret);
55999ebb4caSwyllys }
56099ebb4caSwyllys 
56199ebb4caSwyllys KMF_RETURN
56230a5e8faSwyllys kmf_get_kmf_error_str(KMF_RETURN errcode, char **errmsg)
56399ebb4caSwyllys {
56499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
56599ebb4caSwyllys 	int i, maxerr;
56699ebb4caSwyllys 
56799ebb4caSwyllys 	if (errmsg == NULL)
56899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
56999ebb4caSwyllys 
57099ebb4caSwyllys 	*errmsg = NULL;
57199ebb4caSwyllys 	maxerr = sizeof (kmf_errcodes) / sizeof (kmf_error_map);
57299ebb4caSwyllys 
57330a5e8faSwyllys 	for (i = 0; i < maxerr && errcode != kmf_errcodes[i].code; i++)
57430a5e8faSwyllys 		/* empty body */
57530a5e8faSwyllys 		;
57699ebb4caSwyllys 
57799ebb4caSwyllys 	if (i == maxerr)
57899ebb4caSwyllys 		return (KMF_ERR_MISSING_ERRCODE);
57999ebb4caSwyllys 	else {
58099ebb4caSwyllys 		*errmsg = strdup(kmf_errcodes[i].message);
58199ebb4caSwyllys 		if ((*errmsg) == NULL)
58299ebb4caSwyllys 			return (KMF_ERR_MEMORY);
58399ebb4caSwyllys 	}
58499ebb4caSwyllys 	return (ret);
58599ebb4caSwyllys }
58699ebb4caSwyllys 
58799ebb4caSwyllys KMF_RETURN
58830a5e8faSwyllys kmf_get_plugin_error_str(KMF_HANDLE_T handle, char **msgstr)
58999ebb4caSwyllys {
59099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
59199ebb4caSwyllys 	KMF_PLUGIN *plugin;
59299ebb4caSwyllys 
59399ebb4caSwyllys 	if (handle == NULL || msgstr == NULL)
59499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
59599ebb4caSwyllys 
59699ebb4caSwyllys 	*msgstr = NULL;
59799ebb4caSwyllys 
59899ebb4caSwyllys 	if (handle->lasterr.errcode == 0) {
59999ebb4caSwyllys 		return (KMF_ERR_MISSING_ERRCODE);
60099ebb4caSwyllys 	}
60199ebb4caSwyllys 
60299ebb4caSwyllys 	if (handle->lasterr.kstype == -1) { /* System error */
60399ebb4caSwyllys 		char *str = strerror(handle->lasterr.errcode);
60499ebb4caSwyllys 		if (str != NULL) {
60599ebb4caSwyllys 			*msgstr = strdup(str);
60699ebb4caSwyllys 			if ((*msgstr) == NULL)
60799ebb4caSwyllys 				return (KMF_ERR_MEMORY);
60899ebb4caSwyllys 		}
60999ebb4caSwyllys 		return (KMF_OK);
61099ebb4caSwyllys 	}
61199ebb4caSwyllys 
61299ebb4caSwyllys 	plugin = FindPlugin(handle, handle->lasterr.kstype);
61399ebb4caSwyllys 	if (plugin == NULL)
61499ebb4caSwyllys 		return (KMF_ERR_PLUGIN_NOTFOUND);
61599ebb4caSwyllys 
61699ebb4caSwyllys 	if (plugin->funclist->GetErrorString != NULL) {
61799ebb4caSwyllys 		ret = plugin->funclist->GetErrorString(handle, msgstr);
61899ebb4caSwyllys 	} else {
61999ebb4caSwyllys 		return (KMF_ERR_FUNCTION_NOT_FOUND);
62099ebb4caSwyllys 	}
62199ebb4caSwyllys 
62299ebb4caSwyllys 	return (ret);
62399ebb4caSwyllys }
62499ebb4caSwyllys 
62599ebb4caSwyllys 
6269b37d296Swyllys #define	SET_SYS_ERROR(h, c) if (h) {\
6279b37d296Swyllys 	h->lasterr.kstype = -1;\
6289b37d296Swyllys 	h->lasterr.errcode = c;\
6299b37d296Swyllys }
63099ebb4caSwyllys 
63199ebb4caSwyllys KMF_RETURN
63230a5e8faSwyllys kmf_read_input_file(KMF_HANDLE_T handle, char *filename,  KMF_DATA *pdata)
63399ebb4caSwyllys {
63499ebb4caSwyllys 	struct stat s;
63599ebb4caSwyllys 	long nread, total = 0;
63699ebb4caSwyllys 	int fd;
63799ebb4caSwyllys 	unsigned char *buf = NULL;
63899ebb4caSwyllys 	KMF_RETURN ret;
63999ebb4caSwyllys 
6409b37d296Swyllys 	if (handle) {
6419b37d296Swyllys 		CLEAR_ERROR(handle, ret);
6429b37d296Swyllys 		if (ret != KMF_OK)
6439b37d296Swyllys 			return (ret);
6449b37d296Swyllys 	}
64599ebb4caSwyllys 
64699ebb4caSwyllys 	if (filename == NULL || pdata == NULL) {
64799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
64899ebb4caSwyllys 	}
64999ebb4caSwyllys 
65099ebb4caSwyllys 	if ((fd = open(filename, O_RDONLY)) < 0) {
65199ebb4caSwyllys 		SET_SYS_ERROR(handle, errno);
65299ebb4caSwyllys 		return (KMF_ERR_OPEN_FILE);
65399ebb4caSwyllys 	}
65499ebb4caSwyllys 
65599ebb4caSwyllys 	if (fstat(fd, &s) < 0) {
65699ebb4caSwyllys 		SET_SYS_ERROR(handle, errno);
65799ebb4caSwyllys 		(void) close(fd);
65899ebb4caSwyllys 		return (KMF_ERR_OPEN_FILE);
65999ebb4caSwyllys 	}
66099ebb4caSwyllys 
66199ebb4caSwyllys 	if ((buf = (unsigned char *) malloc(s.st_size)) == NULL) {
66299ebb4caSwyllys 		(void) close(fd);
66399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
66499ebb4caSwyllys 	}
66599ebb4caSwyllys 
66699ebb4caSwyllys 	do {
66799ebb4caSwyllys 		nread = read(fd, buf+total, s.st_size-total);
66899ebb4caSwyllys 		if (nread < 0) {
66999ebb4caSwyllys 			SET_SYS_ERROR(handle, errno);
67099ebb4caSwyllys 			(void) close(fd);
67199ebb4caSwyllys 			free(buf);
67299ebb4caSwyllys 			return (KMF_ERR_INTERNAL);
67399ebb4caSwyllys 		}
67499ebb4caSwyllys 		total += nread;
67599ebb4caSwyllys 	} while (total < s.st_size);
67699ebb4caSwyllys 
67799ebb4caSwyllys 	pdata->Data = buf;
67899ebb4caSwyllys 	pdata->Length = s.st_size;
67999ebb4caSwyllys 	(void) close(fd);
68099ebb4caSwyllys 	return (KMF_OK);
68199ebb4caSwyllys }
68299ebb4caSwyllys 
68399ebb4caSwyllys /*
68499ebb4caSwyllys  *
68530a5e8faSwyllys  * Name: kmf_der_to_pem
68699ebb4caSwyllys  *
68799ebb4caSwyllys  * Description:
68899ebb4caSwyllys  *   Function for converting DER encoded format to PEM encoded format
68999ebb4caSwyllys  *
69099ebb4caSwyllys  * Parameters:
69199ebb4caSwyllys  *   type(input) - CERTIFICATE or CSR
69299ebb4caSwyllys  *   data(input) - pointer to the DER encoded data
69399ebb4caSwyllys  *   len(input)  - length of input data
69499ebb4caSwyllys  *   out(output) - contains the output buffer address to be returned
69599ebb4caSwyllys  *   outlen(output) - pointer to the returned output length
69699ebb4caSwyllys  *
69799ebb4caSwyllys  * Returns:
69899ebb4caSwyllys  *   A KMF_RETURN value indicating success or specifying a particular
69999ebb4caSwyllys  * error condition.
70099ebb4caSwyllys  *   The value KMF_OK indicates success. All other values represent
70199ebb4caSwyllys  * an error condition.
70299ebb4caSwyllys  *
70399ebb4caSwyllys  */
70499ebb4caSwyllys KMF_RETURN
70530a5e8faSwyllys kmf_der_to_pem(KMF_OBJECT_TYPE type, unsigned char *data,
70699ebb4caSwyllys 	int len, unsigned char **out, int *outlen)
70799ebb4caSwyllys {
70899ebb4caSwyllys 
70999ebb4caSwyllys 	KMF_RETURN err;
71099ebb4caSwyllys 	if (data == NULL || out == NULL || outlen == NULL)
71199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
71299ebb4caSwyllys 
71399ebb4caSwyllys 	err = Der2Pem(type, data, len, out, outlen);
71499ebb4caSwyllys 	return (err);
71599ebb4caSwyllys 
71699ebb4caSwyllys }
71799ebb4caSwyllys 
71899ebb4caSwyllys /*
71999ebb4caSwyllys  *
72030a5e8faSwyllys  * Name: kmf_pem_to_der
72199ebb4caSwyllys  *
72299ebb4caSwyllys  * Description:
72399ebb4caSwyllys  *   Function for converting PEM encoded format to DER encoded format
72499ebb4caSwyllys  *
72599ebb4caSwyllys  * Parameters:
72699ebb4caSwyllys  *   in(input) - pointer to the PEM encoded data
72799ebb4caSwyllys  *   inlen(input)  - length of input data
72899ebb4caSwyllys  *   out(output) - contains the output buffer address to be returned
72999ebb4caSwyllys  *   outlen(output) - pointer to the returned output length
73099ebb4caSwyllys  *
73199ebb4caSwyllys  * Returns:
73299ebb4caSwyllys  *   A KMF_RETURN value indicating success or specifying a particular
73399ebb4caSwyllys  *   error condition.
73499ebb4caSwyllys  *   The value KMF_OK indicates success. All other values represent
73599ebb4caSwyllys  *   an error condition.
73699ebb4caSwyllys  *
73799ebb4caSwyllys  */
73899ebb4caSwyllys KMF_RETURN
73930a5e8faSwyllys kmf_pem_to_der(unsigned char *in, int inlen,
74099ebb4caSwyllys 	unsigned char **out, int *outlen)
74199ebb4caSwyllys {
74299ebb4caSwyllys 	KMF_RETURN err;
74399ebb4caSwyllys 	if (in == NULL || out == NULL || outlen == NULL)
74499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
74599ebb4caSwyllys 
74699ebb4caSwyllys 	err = Pem2Der(in, inlen, out, outlen);
74799ebb4caSwyllys 	return (err);
74899ebb4caSwyllys }
74999ebb4caSwyllys 
75099ebb4caSwyllys char *
75130a5e8faSwyllys kmf_oid_to_string(KMF_OID *oid)
75299ebb4caSwyllys {
75399ebb4caSwyllys 	char numstr[128];
75499ebb4caSwyllys 	uint32_t number;
75599ebb4caSwyllys 	int numshift;
75699ebb4caSwyllys 	uint32_t i, string_length;
75799ebb4caSwyllys 	uchar_t *cp;
75899ebb4caSwyllys 	char *bp;
75999ebb4caSwyllys 
76099ebb4caSwyllys 	/* First determine the size of the string */
76199ebb4caSwyllys 	string_length = 0;
76299ebb4caSwyllys 	number = 0;
76399ebb4caSwyllys 	numshift = 0;
76499ebb4caSwyllys 	cp = (unsigned char *)oid->Data;
76599ebb4caSwyllys 
76699ebb4caSwyllys 	number = (uint32_t)cp[0];
76799ebb4caSwyllys 	(void) sprintf(numstr, "%d ", number/40);
76899ebb4caSwyllys 
76999ebb4caSwyllys 	string_length += strlen(numstr);
77099ebb4caSwyllys 	(void) sprintf(numstr, "%d ", number%40);
77199ebb4caSwyllys 
77299ebb4caSwyllys 	string_length += strlen(numstr);
77399ebb4caSwyllys 
77499ebb4caSwyllys 	for (i = 1; i < oid->Length; i++) {
77599ebb4caSwyllys 		if ((uint32_t)(numshift+7) < (sizeof (uint32_t)*8)) {
77699ebb4caSwyllys 			number = (number << 7) | (cp[i] & 0x7f);
77799ebb4caSwyllys 			numshift += 7;
77899ebb4caSwyllys 		} else {
77999ebb4caSwyllys 			return (NULL);
78099ebb4caSwyllys 		}
78199ebb4caSwyllys 
78299ebb4caSwyllys 		if ((cp[i] & 0x80) == 0) {
78399ebb4caSwyllys 			(void) sprintf(numstr, "%d ", number);
78499ebb4caSwyllys 			string_length += strlen(numstr);
78599ebb4caSwyllys 			number = 0;
78699ebb4caSwyllys 			numshift = 0;
78799ebb4caSwyllys 		}
78899ebb4caSwyllys 	}
78999ebb4caSwyllys 	/*
79099ebb4caSwyllys 	 * If we get here, we've calculated the length of "n n n ... n ".  Add 4
79199ebb4caSwyllys 	 * here for "{ " and "}\0".
79299ebb4caSwyllys 	 */
79399ebb4caSwyllys 	string_length += 4;
79499ebb4caSwyllys 	if ((bp = (char *)malloc(string_length))) {
79599ebb4caSwyllys 		number = (uint32_t)cp[0];
79699ebb4caSwyllys 
79799ebb4caSwyllys 		(void) sprintf(numstr, "%d.", number/40);
79899ebb4caSwyllys 		(void) strcpy(bp, numstr);
79999ebb4caSwyllys 
80099ebb4caSwyllys 		(void) sprintf(numstr, "%d.", number%40);
80199ebb4caSwyllys 		(void) strcat(bp, numstr);
80299ebb4caSwyllys 
80399ebb4caSwyllys 		number = 0;
80499ebb4caSwyllys 		cp = (unsigned char *) oid->Data;
80599ebb4caSwyllys 		for (i = 1; i < oid->Length; i++) {
80699ebb4caSwyllys 			number = (number << 7) | (cp[i] & 0x7f);
80799ebb4caSwyllys 			if ((cp[i] & 0x80) == 0) {
80899ebb4caSwyllys 				(void) sprintf(numstr, "%d", number);
80999ebb4caSwyllys 				(void) strcat(bp, numstr);
81099ebb4caSwyllys 				number = 0;
81199ebb4caSwyllys 				if (i+1 < oid->Length)
81299ebb4caSwyllys 					(void) strcat(bp, ".");
81399ebb4caSwyllys 			}
81499ebb4caSwyllys 		}
81599ebb4caSwyllys 	}
81699ebb4caSwyllys 	return (bp);
81799ebb4caSwyllys }
81899ebb4caSwyllys 
81902744e81Swyllys static boolean_t
82008ec4bd3Shylee check_for_pem(uchar_t *buf, KMF_ENCODE_FORMAT *fmt)
82102744e81Swyllys {
8229b37d296Swyllys 	char *p;
82302744e81Swyllys 
82408ec4bd3Shylee 	if (buf == NULL)
82502744e81Swyllys 		return (FALSE);
82602744e81Swyllys 
82708ec4bd3Shylee 	if (memcmp(buf, "Bag Attr", 8) == 0) {
82808ec4bd3Shylee 		*fmt = KMF_FORMAT_PEM_KEYPAIR;
82908ec4bd3Shylee 		return (TRUE);
83008ec4bd3Shylee 	}
83108ec4bd3Shylee 
8329b37d296Swyllys 	/* Look for "-----BEGIN" right after a newline */
83308ec4bd3Shylee 	p = strtok((char *)buf, "\n");
8349b37d296Swyllys 	while (p != NULL) {
8359b37d296Swyllys 		if (strstr(p, "-----BEGIN") != NULL) {
83608ec4bd3Shylee 			*fmt = KMF_FORMAT_PEM;
8379b37d296Swyllys 			return (TRUE);
83802744e81Swyllys 		}
8399b37d296Swyllys 		p = strtok(NULL, "\n");
84002744e81Swyllys 	}
84102744e81Swyllys 	return (FALSE);
84202744e81Swyllys }
84302744e81Swyllys 
84408ec4bd3Shylee 
84508ec4bd3Shylee static unsigned char pkcs12_version[3] = {0x02, 0x01, 0x03};
84608ec4bd3Shylee static unsigned char pkcs12_oid[11] =
84708ec4bd3Shylee {0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01};
84808ec4bd3Shylee 
84908ec4bd3Shylee /*
85008ec4bd3Shylee  * This function takes a BER encoded string as input and checks the version
85108ec4bd3Shylee  * and the oid in the the top-level ASN.1 structure to see if it complies to
85208ec4bd3Shylee  * the PKCS#12 Syntax.
85308ec4bd3Shylee  */
85408ec4bd3Shylee static boolean_t
85508ec4bd3Shylee check_for_pkcs12(uchar_t *buf, int buf_len)
85608ec4bd3Shylee {
85708ec4bd3Shylee 	int index = 0;
85808ec4bd3Shylee 	int length_octets;
85908ec4bd3Shylee 
86008ec4bd3Shylee 	if (buf == NULL || buf_len <= 0)
86108ec4bd3Shylee 		return (FALSE);
86208ec4bd3Shylee 
86308ec4bd3Shylee 	/*
86408ec4bd3Shylee 	 * The top level structure for a PKCS12 string:
86508ec4bd3Shylee 	 *
86608ec4bd3Shylee 	 * PFX ::= SEQUENCE {
86708ec4bd3Shylee 	 *	version		INTEGER {v3(3)}(v3,...)
86808ec4bd3Shylee 	 *	authSafe	ContentInfo
86908ec4bd3Shylee 	 *	macData		MacData OPTIONAL
87008ec4bd3Shylee 	 * }
87108ec4bd3Shylee 	 *
87208ec4bd3Shylee 	 * ContentInfo
87308ec4bd3Shylee 	 *	FROM PKCS-7 {iso(1) member-body(2) us(840) rsadsi(113549)
87408ec4bd3Shylee 	 *		pkcs(1) pkcs-7(7) modules(0) pkcs-7(1)}
87508ec4bd3Shylee 	 *
87608ec4bd3Shylee 	 * Therefore, the BER/DER dump of a PKCS#12 file for the first 2
87708ec4bd3Shylee 	 * sequences up to the oid part is as following:
87808ec4bd3Shylee 	 *
87908ec4bd3Shylee 	 *	SEQUENCE {
88008ec4bd3Shylee 	 *	    INTEGER 3
88108ec4bd3Shylee 	 *	    SEQUENCE {
88208ec4bd3Shylee 	 *		OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
88308ec4bd3Shylee 	 */
88408ec4bd3Shylee 
88508ec4bd3Shylee 	/*
88608ec4bd3Shylee 	 * Check the first sequence and calculate the number of bytes used
88708ec4bd3Shylee 	 * to store the length.
88808ec4bd3Shylee 	 */
88908ec4bd3Shylee 	if (buf[index++] != 0x30)
89008ec4bd3Shylee 		return (FALSE);
89108ec4bd3Shylee 
89208ec4bd3Shylee 	if (buf[index] & 0x80) {
89308ec4bd3Shylee 		length_octets = buf[index++] & 0x0F;  /* long form */
89408ec4bd3Shylee 	} else {
89508ec4bd3Shylee 		length_octets = 1; /* short form */
89608ec4bd3Shylee 	}
89708ec4bd3Shylee 
89808ec4bd3Shylee 	index += length_octets;
89908ec4bd3Shylee 	if (index  >= buf_len)
90008ec4bd3Shylee 		return (FALSE);
90108ec4bd3Shylee 
90208ec4bd3Shylee 	/* Skip the length octets and check the pkcs12 version */
90308ec4bd3Shylee 	if (memcmp(buf + index, pkcs12_version, sizeof (pkcs12_version)) != 0)
90408ec4bd3Shylee 		return (FALSE);
90508ec4bd3Shylee 
90608ec4bd3Shylee 	index += sizeof (pkcs12_version);
90708ec4bd3Shylee 	if (index  >= buf_len)
90808ec4bd3Shylee 		return (FALSE);
90908ec4bd3Shylee 
91008ec4bd3Shylee 	/*
91108ec4bd3Shylee 	 * Check the 2nd sequence and calculate the number of bytes used
91208ec4bd3Shylee 	 * to store the length.
91308ec4bd3Shylee 	 */
91408ec4bd3Shylee 	if ((buf[index++] & 0xFF) != 0x30)
91508ec4bd3Shylee 		return (FALSE);
91608ec4bd3Shylee 
91708ec4bd3Shylee 	if (buf[index] & 0x80) {
91808ec4bd3Shylee 		length_octets = buf[index++] & 0x0F;
91908ec4bd3Shylee 	} else {
92008ec4bd3Shylee 		length_octets = 1;
92108ec4bd3Shylee 	}
92208ec4bd3Shylee 
92308ec4bd3Shylee 	index += length_octets;
92408ec4bd3Shylee 	if (index + sizeof (pkcs12_oid) >= buf_len)
92508ec4bd3Shylee 		return (FALSE);
92608ec4bd3Shylee 
92708ec4bd3Shylee 	/* Skip the length octets and check the oid */
92808ec4bd3Shylee 	if (memcmp(buf + index, pkcs12_oid, sizeof (pkcs12_oid)) != 0)
92908ec4bd3Shylee 		return (FALSE);
93008ec4bd3Shylee 	else
93108ec4bd3Shylee 		return (TRUE);
93208ec4bd3Shylee }
93308ec4bd3Shylee 
93499ebb4caSwyllys KMF_RETURN
93530a5e8faSwyllys kmf_get_file_format(char *filename, KMF_ENCODE_FORMAT *fmt)
93699ebb4caSwyllys {
93799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
93808ec4bd3Shylee 	KMF_DATA filebuf = {NULL, 0};
93908ec4bd3Shylee 	uchar_t *buf;
94099ebb4caSwyllys 
94199ebb4caSwyllys 	if (filename == NULL || !strlen(filename) || fmt == NULL)
94299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
94399ebb4caSwyllys 
94499ebb4caSwyllys 	*fmt = 0;
94530a5e8faSwyllys 	ret = kmf_read_input_file(NULL, filename, &filebuf);
94608ec4bd3Shylee 	if (ret != KMF_OK)
94708ec4bd3Shylee 		return (ret);
94899ebb4caSwyllys 
94908ec4bd3Shylee 	if (filebuf.Length < 8) {
95008ec4bd3Shylee 		ret = KMF_ERR_ENCODING; /* too small */
95199ebb4caSwyllys 		goto end;
95299ebb4caSwyllys 	}
95399ebb4caSwyllys 
95408ec4bd3Shylee 	buf = filebuf.Data;
95508ec4bd3Shylee 	if (check_for_pkcs12(buf, filebuf.Length) == TRUE) {
95608ec4bd3Shylee 		*fmt = KMF_FORMAT_PKCS12;
95708ec4bd3Shylee 	} else if (buf[0] == 0x30 && (buf[1] & 0x80)) {
95899ebb4caSwyllys 		/* It is most likely a generic ASN.1 encoded file */
95908ec4bd3Shylee 		*fmt = KMF_FORMAT_ASN1;
96008ec4bd3Shylee 	} else if (check_for_pem(buf, fmt) == TRUE) {
96108ec4bd3Shylee 		goto end;
96299ebb4caSwyllys 	} else {
96308ec4bd3Shylee 		/* Cannot determine this file format */
96408ec4bd3Shylee 		*fmt = 0;
96508ec4bd3Shylee 		ret = KMF_ERR_ENCODING;
96699ebb4caSwyllys 	}
96708ec4bd3Shylee 
96899ebb4caSwyllys end:
96930a5e8faSwyllys 	kmf_free_data(&filebuf);
97099ebb4caSwyllys 	return (ret);
97199ebb4caSwyllys }
97299ebb4caSwyllys 
97399ebb4caSwyllys KMF_RETURN
97430a5e8faSwyllys kmf_hexstr_to_bytes(unsigned char *hexstr, unsigned char **bytes,
97599ebb4caSwyllys 	size_t *outlen)
97699ebb4caSwyllys {
97799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
97899ebb4caSwyllys 	unsigned char *buf = NULL;
97999ebb4caSwyllys 	int len, stringlen;
98099ebb4caSwyllys 	int i;
98199ebb4caSwyllys 	unsigned char ch;
98299ebb4caSwyllys 
98399ebb4caSwyllys 	if (hexstr == NULL) {
98499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
98599ebb4caSwyllys 	}
98699ebb4caSwyllys 
98730a5e8faSwyllys 	if (hexstr[0] == '0' && ((hexstr[1] == 'x') || (hexstr[1] == 'X')))
98899ebb4caSwyllys 		hexstr += 2;
98999ebb4caSwyllys 
99030a5e8faSwyllys 	for (i = 0; i < strlen((char *)hexstr) && isxdigit(hexstr[i]); i++)
99130a5e8faSwyllys 		/* empty body */
99230a5e8faSwyllys 		;
99399ebb4caSwyllys 	/*
99499ebb4caSwyllys 	 * If all the characters are not legitimate hex chars,
99599ebb4caSwyllys 	 * return an error.
99699ebb4caSwyllys 	 */
99799ebb4caSwyllys 	if (i != strlen((char *)hexstr))
99899ebb4caSwyllys 		return (KMF_ERR_BAD_HEX_STRING);
99999ebb4caSwyllys 	stringlen = i;
100099ebb4caSwyllys 	len = (i / 2) + (i % 2);
100199ebb4caSwyllys 
100299ebb4caSwyllys 	buf = malloc(len);
100399ebb4caSwyllys 	if (buf == NULL) {
100499ebb4caSwyllys 		return (KMF_ERR_MEMORY);
100599ebb4caSwyllys 	}
100699ebb4caSwyllys 	(void) memset(buf, 0, len);
100799ebb4caSwyllys 
100899ebb4caSwyllys 	for (i = 0; i < stringlen; i++) {
100999ebb4caSwyllys 		ch = (unsigned char) *hexstr;
101099ebb4caSwyllys 		hexstr++;
101199ebb4caSwyllys 		if ((ch >= '0') && (ch <= '9'))
101299ebb4caSwyllys 			ch -= '0';
101399ebb4caSwyllys 		else if ((ch >= 'A') && (ch <= 'F'))
101499ebb4caSwyllys 			ch = ch - 'A' + 10;
101599ebb4caSwyllys 		else if ((ch >= 'a') && (ch <= 'f'))
101699ebb4caSwyllys 			ch = ch - 'a' + 10;
101799ebb4caSwyllys 		else {
101899ebb4caSwyllys 			ret = KMF_ERR_BAD_HEX_STRING;
101999ebb4caSwyllys 			goto out;
102099ebb4caSwyllys 		}
102199ebb4caSwyllys 
102299ebb4caSwyllys 		if (i & 1) {
102399ebb4caSwyllys 			buf[i/2] |= ch;
102499ebb4caSwyllys 		} else {
102599ebb4caSwyllys 			buf[i/2] = (ch << 4);
102699ebb4caSwyllys 		}
102799ebb4caSwyllys 	}
102899ebb4caSwyllys 
102999ebb4caSwyllys 	*bytes = buf;
103099ebb4caSwyllys 	*outlen = len;
103199ebb4caSwyllys out:
103299ebb4caSwyllys 	if (buf != NULL && ret != KMF_OK) {
103399ebb4caSwyllys 		free(buf);
103499ebb4caSwyllys 	}
103599ebb4caSwyllys 	return (ret);
103699ebb4caSwyllys }
103799ebb4caSwyllys 
103899ebb4caSwyllys void
103930a5e8faSwyllys kmf_free_dn(KMF_X509_NAME *name)
104099ebb4caSwyllys {
104199ebb4caSwyllys 	KMF_X509_RDN 		*newrdn = NULL;
104299ebb4caSwyllys 	KMF_X509_TYPE_VALUE_PAIR *av = NULL;
104399ebb4caSwyllys 	int i, j;
104499ebb4caSwyllys 
104599ebb4caSwyllys 	if (name && name->numberOfRDNs) {
104699ebb4caSwyllys 		for (i = 0; i < name->numberOfRDNs; i++) {
104799ebb4caSwyllys 			newrdn = &name->RelativeDistinguishedName[i];
104899ebb4caSwyllys 			for (j = 0; j < newrdn->numberOfPairs; j++) {
104999ebb4caSwyllys 				av = &newrdn->AttributeTypeAndValue[j];
105030a5e8faSwyllys 				kmf_free_data(&av->type);
105130a5e8faSwyllys 				kmf_free_data(&av->value);
105299ebb4caSwyllys 			}
105399ebb4caSwyllys 			free(newrdn->AttributeTypeAndValue);
105499ebb4caSwyllys 			newrdn->numberOfPairs = 0;
105599ebb4caSwyllys 			newrdn->AttributeTypeAndValue = NULL;
105699ebb4caSwyllys 		}
105799ebb4caSwyllys 		free(name->RelativeDistinguishedName);
105899ebb4caSwyllys 		name->numberOfRDNs = 0;
105999ebb4caSwyllys 		name->RelativeDistinguishedName = NULL;
106099ebb4caSwyllys 	}
106199ebb4caSwyllys }
106299ebb4caSwyllys 
106399ebb4caSwyllys void
106430a5e8faSwyllys kmf_free_kmf_cert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
106599ebb4caSwyllys {
106699ebb4caSwyllys 	KMF_PLUGIN *plugin;
106799ebb4caSwyllys 	KMF_RETURN ret;
106899ebb4caSwyllys 
106999ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
107099ebb4caSwyllys 	if (ret != KMF_OK)
107199ebb4caSwyllys 		return;
107299ebb4caSwyllys 
107399ebb4caSwyllys 	if (kmf_cert == NULL)
107499ebb4caSwyllys 		return;
107599ebb4caSwyllys 
107699ebb4caSwyllys 	plugin = FindPlugin(handle, kmf_cert->kmf_private.keystore_type);
107799ebb4caSwyllys 
107899ebb4caSwyllys 	if (plugin != NULL && plugin->funclist->FreeKMFCert != NULL) {
107999ebb4caSwyllys 		plugin->funclist->FreeKMFCert(handle, kmf_cert);
108099ebb4caSwyllys 	}
108199ebb4caSwyllys }
108299ebb4caSwyllys 
108399ebb4caSwyllys void
108430a5e8faSwyllys kmf_free_data(KMF_DATA *datablock)
108599ebb4caSwyllys {
108699ebb4caSwyllys 	if (datablock != NULL && datablock->Data != NULL) {
108799ebb4caSwyllys 		free(datablock->Data);
108899ebb4caSwyllys 		datablock->Data = NULL;
108999ebb4caSwyllys 		datablock->Length = 0;
109099ebb4caSwyllys 	}
109199ebb4caSwyllys }
109299ebb4caSwyllys 
109399ebb4caSwyllys void
109430a5e8faSwyllys kmf_free_algoid(KMF_X509_ALGORITHM_IDENTIFIER *algoid)
109599ebb4caSwyllys {
109699ebb4caSwyllys 	if (algoid == NULL)
109799ebb4caSwyllys 		return;
109830a5e8faSwyllys 	kmf_free_data(&algoid->algorithm);
109930a5e8faSwyllys 	kmf_free_data(&algoid->parameters);
110099ebb4caSwyllys }
110199ebb4caSwyllys 
110299ebb4caSwyllys void
110330a5e8faSwyllys kmf_free_extn(KMF_X509_EXTENSION *exptr)
110499ebb4caSwyllys {
110599ebb4caSwyllys 	if (exptr == NULL)
110699ebb4caSwyllys 		return;
110799ebb4caSwyllys 
110830a5e8faSwyllys 	kmf_free_data((KMF_DATA *)&exptr->extnId);
110930a5e8faSwyllys 	kmf_free_data(&exptr->BERvalue);
111099ebb4caSwyllys 
111199ebb4caSwyllys 	if (exptr->value.tagAndValue) {
111230a5e8faSwyllys 		kmf_free_data(&exptr->value.tagAndValue->value);
111399ebb4caSwyllys 		free(exptr->value.tagAndValue);
111499ebb4caSwyllys 	}
111599ebb4caSwyllys }
111699ebb4caSwyllys 
111799ebb4caSwyllys void
111830a5e8faSwyllys kmf_free_tbs_csr(KMF_TBS_CSR *tbscsr)
111999ebb4caSwyllys {
112099ebb4caSwyllys 	if (tbscsr) {
112130a5e8faSwyllys 		kmf_free_data(&tbscsr->version);
112299ebb4caSwyllys 
112330a5e8faSwyllys 		kmf_free_dn(&tbscsr->subject);
112499ebb4caSwyllys 
112530a5e8faSwyllys 		kmf_free_algoid(&tbscsr->subjectPublicKeyInfo.algorithm);
112630a5e8faSwyllys 		kmf_free_data(&tbscsr->subjectPublicKeyInfo.subjectPublicKey);
112799ebb4caSwyllys 
112899ebb4caSwyllys 		free_extensions(&tbscsr->extensions);
112999ebb4caSwyllys 	}
113099ebb4caSwyllys }
113199ebb4caSwyllys 
113299ebb4caSwyllys void
113330a5e8faSwyllys kmf_free_signed_csr(KMF_CSR_DATA *csr)
113499ebb4caSwyllys {
113599ebb4caSwyllys 	if (csr) {
113630a5e8faSwyllys 		kmf_free_tbs_csr(&csr->csr);
113799ebb4caSwyllys 
113830a5e8faSwyllys 		kmf_free_algoid(&csr->signature.algorithmIdentifier);
113930a5e8faSwyllys 		kmf_free_data(&csr->signature.encrypted);
114099ebb4caSwyllys 	}
114199ebb4caSwyllys }
114299ebb4caSwyllys 
114399ebb4caSwyllys static void
114499ebb4caSwyllys free_validity(KMF_X509_VALIDITY *validity)
114599ebb4caSwyllys {
114699ebb4caSwyllys 	if (validity == NULL)
114799ebb4caSwyllys 		return;
114830a5e8faSwyllys 	kmf_free_data(&validity->notBefore.time);
114930a5e8faSwyllys 	kmf_free_data(&validity->notAfter.time);
115099ebb4caSwyllys }
115199ebb4caSwyllys 
115299ebb4caSwyllys static void
115399ebb4caSwyllys free_extensions(KMF_X509_EXTENSIONS *extns)
115499ebb4caSwyllys {
115599ebb4caSwyllys 	int i;
115699ebb4caSwyllys 	KMF_X509_EXTENSION *exptr;
115799ebb4caSwyllys 
115899ebb4caSwyllys 	if (extns && extns->numberOfExtensions > 0) {
115999ebb4caSwyllys 		for (i = 0; i < extns->numberOfExtensions; i++) {
116099ebb4caSwyllys 			exptr = &extns->extensions[i];
116130a5e8faSwyllys 			kmf_free_extn(exptr);
116299ebb4caSwyllys 		}
116399ebb4caSwyllys 		free(extns->extensions);
116499ebb4caSwyllys 		extns->numberOfExtensions = 0;
116599ebb4caSwyllys 		extns->extensions = NULL;
116699ebb4caSwyllys 	}
116799ebb4caSwyllys }
116899ebb4caSwyllys 
116999ebb4caSwyllys void
117030a5e8faSwyllys kmf_free_tbs_cert(KMF_X509_TBS_CERT *tbscert)
117199ebb4caSwyllys {
117299ebb4caSwyllys 	if (tbscert) {
117330a5e8faSwyllys 		kmf_free_data(&tbscert->version);
117430a5e8faSwyllys 		kmf_free_bigint(&tbscert->serialNumber);
117530a5e8faSwyllys 		kmf_free_algoid(&tbscert->signature);
117699ebb4caSwyllys 
117730a5e8faSwyllys 		kmf_free_dn(&tbscert->issuer);
117830a5e8faSwyllys 		kmf_free_dn(&tbscert->subject);
117999ebb4caSwyllys 
118099ebb4caSwyllys 		free_validity(&tbscert->validity);
118199ebb4caSwyllys 
118230a5e8faSwyllys 		kmf_free_data(&tbscert->issuerUniqueIdentifier);
118330a5e8faSwyllys 		kmf_free_data(&tbscert->subjectUniqueIdentifier);
118499ebb4caSwyllys 
118530a5e8faSwyllys 		kmf_free_algoid(&tbscert->subjectPublicKeyInfo.algorithm);
118630a5e8faSwyllys 		kmf_free_data(&tbscert->subjectPublicKeyInfo.subjectPublicKey);
118799ebb4caSwyllys 
118899ebb4caSwyllys 		free_extensions(&tbscert->extensions);
118999ebb4caSwyllys 
119030a5e8faSwyllys 		kmf_free_data(&tbscert->issuerUniqueIdentifier);
119130a5e8faSwyllys 		kmf_free_data(&tbscert->subjectUniqueIdentifier);
119299ebb4caSwyllys 	}
119399ebb4caSwyllys }
119499ebb4caSwyllys 
119599ebb4caSwyllys void
119630a5e8faSwyllys kmf_free_signed_cert(KMF_X509_CERTIFICATE *certptr)
119799ebb4caSwyllys {
119899ebb4caSwyllys 	if (!certptr)
119999ebb4caSwyllys 		return;
120099ebb4caSwyllys 
120130a5e8faSwyllys 	kmf_free_tbs_cert(&certptr->certificate);
120299ebb4caSwyllys 
120330a5e8faSwyllys 	kmf_free_algoid(&certptr->signature.algorithmIdentifier);
120430a5e8faSwyllys 	kmf_free_data(&certptr->signature.encrypted);
120599ebb4caSwyllys }
120699ebb4caSwyllys 
120799ebb4caSwyllys void
120830a5e8faSwyllys kmf_free_str(char *pstr)
120999ebb4caSwyllys {
121099ebb4caSwyllys 	if (pstr != NULL)
121199ebb4caSwyllys 		free(pstr);
121299ebb4caSwyllys }
121399ebb4caSwyllys 
121499ebb4caSwyllys void
121599ebb4caSwyllys free_keyidlist(KMF_OID *oidlist, int len)
121699ebb4caSwyllys {
121799ebb4caSwyllys 	int i;
121899ebb4caSwyllys 	for (i = 0; i < len; i++) {
121930a5e8faSwyllys 		kmf_free_data((KMF_DATA *)&oidlist[i]);
122099ebb4caSwyllys 	}
122199ebb4caSwyllys 	free(oidlist);
122299ebb4caSwyllys }
122399ebb4caSwyllys 
122499ebb4caSwyllys void
122530a5e8faSwyllys kmf_free_eku(KMF_X509EXT_EKU *eptr)
122699ebb4caSwyllys {
122730a5e8faSwyllys 	if (eptr && eptr->nEKUs > 0 && eptr->keyPurposeIdList != NULL)
122899ebb4caSwyllys 		free_keyidlist(eptr->keyPurposeIdList, eptr->nEKUs);
122999ebb4caSwyllys }
123099ebb4caSwyllys 
123199ebb4caSwyllys void
123230a5e8faSwyllys kmf_free_spki(KMF_X509_SPKI *spki)
123399ebb4caSwyllys {
123499ebb4caSwyllys 	if (spki != NULL) {
123530a5e8faSwyllys 		kmf_free_algoid(&spki->algorithm);
123630a5e8faSwyllys 		kmf_free_data(&spki->subjectPublicKey);
123799ebb4caSwyllys 	}
123899ebb4caSwyllys }
123999ebb4caSwyllys 
124099ebb4caSwyllys void
124130a5e8faSwyllys kmf_free_kmf_key(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key)
124299ebb4caSwyllys {
124399ebb4caSwyllys 	KMF_PLUGIN *plugin;
124499ebb4caSwyllys 	KMF_RETURN ret;
124530a5e8faSwyllys 	KMF_ATTRIBUTE attlist[2]; /* only 2 attributes for DeleteKey op */
124630a5e8faSwyllys 	int i = 0;
124730a5e8faSwyllys 	boolean_t token_destroy = B_FALSE;
124830a5e8faSwyllys 
124930a5e8faSwyllys 	if (key == NULL)
125030a5e8faSwyllys 		return;
125199ebb4caSwyllys 
125299ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
125399ebb4caSwyllys 	if (ret != KMF_OK)
125499ebb4caSwyllys 		return;
125599ebb4caSwyllys 
125630a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
125730a5e8faSwyllys 	    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
125830a5e8faSwyllys 	i++;
125930a5e8faSwyllys 
126030a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
126130a5e8faSwyllys 	    KMF_DESTROY_BOOL_ATTR, &token_destroy, sizeof (boolean_t));
126230a5e8faSwyllys 	i++;
126399ebb4caSwyllys 
126499ebb4caSwyllys 	plugin = FindPlugin(handle, key->kstype);
126599ebb4caSwyllys 	if (plugin != NULL && plugin->funclist->DeleteKey != NULL) {
126630a5e8faSwyllys 		(void) plugin->funclist->DeleteKey(handle, i, attlist);
126799ebb4caSwyllys 	}
126899ebb4caSwyllys 
126999ebb4caSwyllys 	if (key->keylabel)
127099ebb4caSwyllys 		free(key->keylabel);
127199ebb4caSwyllys 
127299ebb4caSwyllys 	if (key->israw) {
127330a5e8faSwyllys 		kmf_free_raw_key(key->keyp);
127499ebb4caSwyllys 		free(key->keyp);
127599ebb4caSwyllys 	}
127699ebb4caSwyllys 
127799ebb4caSwyllys 	(void) memset(key, 0, sizeof (KMF_KEY_HANDLE));
127899ebb4caSwyllys }
127999ebb4caSwyllys 
128099ebb4caSwyllys void
128130a5e8faSwyllys kmf_free_bigint(KMF_BIGINT *big)
128299ebb4caSwyllys {
128399ebb4caSwyllys 	if (big != NULL && big->val != NULL) {
128402744e81Swyllys 		/* Clear it out before returning it to the pool */
128502744e81Swyllys 		(void) memset(big->val, 0x00, big->len);
128699ebb4caSwyllys 		free(big->val);
128799ebb4caSwyllys 		big->val = NULL;
128899ebb4caSwyllys 		big->len = 0;
128999ebb4caSwyllys 	}
129099ebb4caSwyllys }
129199ebb4caSwyllys 
129299ebb4caSwyllys static void
129399ebb4caSwyllys free_raw_rsa(KMF_RAW_RSA_KEY *key)
129499ebb4caSwyllys {
129599ebb4caSwyllys 	if (key == NULL)
129699ebb4caSwyllys 		return;
129730a5e8faSwyllys 	kmf_free_bigint(&key->mod);
129830a5e8faSwyllys 	kmf_free_bigint(&key->pubexp);
129930a5e8faSwyllys 	kmf_free_bigint(&key->priexp);
130030a5e8faSwyllys 	kmf_free_bigint(&key->prime1);
130130a5e8faSwyllys 	kmf_free_bigint(&key->prime2);
130230a5e8faSwyllys 	kmf_free_bigint(&key->exp1);
130330a5e8faSwyllys 	kmf_free_bigint(&key->exp2);
130430a5e8faSwyllys 	kmf_free_bigint(&key->coef);
130599ebb4caSwyllys }
130699ebb4caSwyllys 
130799ebb4caSwyllys static void
130899ebb4caSwyllys free_raw_dsa(KMF_RAW_DSA_KEY *key)
130999ebb4caSwyllys {
131099ebb4caSwyllys 	if (key == NULL)
131199ebb4caSwyllys 		return;
131230a5e8faSwyllys 	kmf_free_bigint(&key->prime);
131330a5e8faSwyllys 	kmf_free_bigint(&key->subprime);
131430a5e8faSwyllys 	kmf_free_bigint(&key->base);
131530a5e8faSwyllys 	kmf_free_bigint(&key->value);
131699ebb4caSwyllys }
131799ebb4caSwyllys 
131899ebb4caSwyllys static void
131999ebb4caSwyllys free_raw_sym(KMF_RAW_SYM_KEY *key)
132099ebb4caSwyllys {
132199ebb4caSwyllys 	if (key == NULL)
132299ebb4caSwyllys 		return;
132330a5e8faSwyllys 	kmf_free_bigint(&key->keydata);
132499ebb4caSwyllys }
132599ebb4caSwyllys 
132699ebb4caSwyllys void
132730a5e8faSwyllys kmf_free_raw_key(KMF_RAW_KEY_DATA *key)
132899ebb4caSwyllys {
132999ebb4caSwyllys 	if (key == NULL)
133099ebb4caSwyllys 		return;
133199ebb4caSwyllys 
133299ebb4caSwyllys 	switch (key->keytype) {
133399ebb4caSwyllys 	case KMF_RSA:
133499ebb4caSwyllys 		free_raw_rsa(&key->rawdata.rsa);
133599ebb4caSwyllys 		break;
133699ebb4caSwyllys 	case KMF_DSA:
133799ebb4caSwyllys 		free_raw_dsa(&key->rawdata.dsa);
133899ebb4caSwyllys 		break;
133999ebb4caSwyllys 	case KMF_AES:
134099ebb4caSwyllys 	case KMF_RC4:
134199ebb4caSwyllys 	case KMF_DES:
134299ebb4caSwyllys 	case KMF_DES3:
134399ebb4caSwyllys 		free_raw_sym(&key->rawdata.sym);
134499ebb4caSwyllys 		break;
134599ebb4caSwyllys 	}
13465b3e1433Swyllys 	if (key->label) {
13475b3e1433Swyllys 		free(key->label);
13485b3e1433Swyllys 		key->label = NULL;
13495b3e1433Swyllys 	}
13505b3e1433Swyllys 	kmf_free_data(&key->id);
135199ebb4caSwyllys }
135299ebb4caSwyllys 
135399ebb4caSwyllys void
135430a5e8faSwyllys kmf_free_raw_sym_key(KMF_RAW_SYM_KEY *key)
135599ebb4caSwyllys {
135699ebb4caSwyllys 	if (key == NULL)
135799ebb4caSwyllys 		return;
135830a5e8faSwyllys 	kmf_free_bigint(&key->keydata);
135999ebb4caSwyllys 	free(key);
136099ebb4caSwyllys }
136199ebb4caSwyllys 
136299ebb4caSwyllys /*
136399ebb4caSwyllys  * This function frees the space allocated for the name portion of a
136499ebb4caSwyllys  * KMF_CRL_DIST_POINT.
136599ebb4caSwyllys  */
136699ebb4caSwyllys void
136799ebb4caSwyllys free_dp_name(KMF_CRL_DIST_POINT *dp)
136899ebb4caSwyllys {
136999ebb4caSwyllys 	KMF_GENERALNAMES *fullname;
137099ebb4caSwyllys 	KMF_DATA *urldata;
137199ebb4caSwyllys 	int i;
137299ebb4caSwyllys 
137399ebb4caSwyllys 	if (dp == NULL)
137499ebb4caSwyllys 		return;
137599ebb4caSwyllys 
137699ebb4caSwyllys 	/* For phase 1, we only need to free the fullname space. */
137799ebb4caSwyllys 	fullname = &(dp->name.full_name);
137899ebb4caSwyllys 	if (fullname->number == 0)
137999ebb4caSwyllys 		return;
138099ebb4caSwyllys 
138199ebb4caSwyllys 	for (i = 0; i < fullname->number; i++) {
138299ebb4caSwyllys 		urldata = &(fullname->namelist[fullname->number - 1].name);
138330a5e8faSwyllys 		kmf_free_data(urldata);
138499ebb4caSwyllys 	}
138599ebb4caSwyllys 
138699ebb4caSwyllys 	free(fullname->namelist);
138799ebb4caSwyllys }
138899ebb4caSwyllys 
138999ebb4caSwyllys /*
139099ebb4caSwyllys  * This function frees the space allocated for a KMF_CRL_DIST_POINT.
139199ebb4caSwyllys  */
139299ebb4caSwyllys void
139399ebb4caSwyllys free_dp(KMF_CRL_DIST_POINT *dp)
139499ebb4caSwyllys {
139599ebb4caSwyllys 	if (dp == NULL)
139699ebb4caSwyllys 		return;
139799ebb4caSwyllys 
139899ebb4caSwyllys 	free_dp_name(dp);
139930a5e8faSwyllys 	kmf_free_data(&(dp->reasons));
140099ebb4caSwyllys 	/* Need not to free crl_issuer space at phase 1 */
140199ebb4caSwyllys }
140299ebb4caSwyllys 
140399ebb4caSwyllys /*
140499ebb4caSwyllys  * This function frees space for a KMF_X509EXT_CRLDISTPOINTS internally.
140599ebb4caSwyllys  */
140699ebb4caSwyllys void
140730a5e8faSwyllys kmf_free_crl_dist_pts(KMF_X509EXT_CRLDISTPOINTS *crl_dps)
140899ebb4caSwyllys {
140999ebb4caSwyllys 	int i;
141099ebb4caSwyllys 
141199ebb4caSwyllys 	if (crl_dps == NULL)
141299ebb4caSwyllys 		return;
141399ebb4caSwyllys 
141499ebb4caSwyllys 	for (i = 0; i < crl_dps->number; i++)
141599ebb4caSwyllys 		free_dp(&(crl_dps->dplist[i]));
141699ebb4caSwyllys 
141799ebb4caSwyllys 	free(crl_dps->dplist);
141899ebb4caSwyllys }
141999ebb4caSwyllys 
142099ebb4caSwyllys KMF_RETURN
142130a5e8faSwyllys kmf_create_ocsp_request(KMF_HANDLE_T handle,
142230a5e8faSwyllys 	int	num_args,
142330a5e8faSwyllys 	KMF_ATTRIBUTE	*attrlist)
142499ebb4caSwyllys {
142530a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
142699ebb4caSwyllys 	KMF_PLUGIN *plugin;
142730a5e8faSwyllys 	KMF_RETURN (*createReqFn)(void *, int num_args,
142830a5e8faSwyllys 	    KMF_ATTRIBUTE *attrlist);
142999ebb4caSwyllys 
143030a5e8faSwyllys 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
143130a5e8faSwyllys 		{KMF_OCSP_REQUEST_FILENAME_ATTR, FALSE, 1, 0},
143230a5e8faSwyllys 		{KMF_USER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
143330a5e8faSwyllys 			sizeof (KMF_DATA)},
143430a5e8faSwyllys 		{KMF_ISSUER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
143530a5e8faSwyllys 			sizeof (KMF_DATA)},
143630a5e8faSwyllys 	};
143799ebb4caSwyllys 
143830a5e8faSwyllys 	int num_req_attrs = sizeof (required_attrs) /
143930a5e8faSwyllys 	    sizeof (KMF_ATTRIBUTE_TESTER);
144099ebb4caSwyllys 
144130a5e8faSwyllys 	if (handle == NULL)
144299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
144399ebb4caSwyllys 
144430a5e8faSwyllys 	CLEAR_ERROR(handle, ret);
144530a5e8faSwyllys 
144630a5e8faSwyllys 	ret = test_attributes(num_req_attrs, required_attrs,
144730a5e8faSwyllys 	    0, NULL, num_args, attrlist);
144830a5e8faSwyllys 
144930a5e8faSwyllys 	if (ret != KMF_OK)
145030a5e8faSwyllys 		return (ret);
145130a5e8faSwyllys 
145299ebb4caSwyllys 	/*
145399ebb4caSwyllys 	 * This framework function is actually implemented in the openssl
145499ebb4caSwyllys 	 * plugin library, so we find the function address and call it.
145599ebb4caSwyllys 	 */
145699ebb4caSwyllys 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
145799ebb4caSwyllys 	if (plugin == NULL || plugin->dldesc == NULL) {
145899ebb4caSwyllys 		return (KMF_ERR_PLUGIN_NOTFOUND);
145999ebb4caSwyllys 	}
146099ebb4caSwyllys 
146199ebb4caSwyllys 	createReqFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
146299ebb4caSwyllys 	    "OpenSSL_CreateOCSPRequest");
146399ebb4caSwyllys 	if (createReqFn == NULL) {
146499ebb4caSwyllys 		return (KMF_ERR_FUNCTION_NOT_FOUND);
146599ebb4caSwyllys 	}
146699ebb4caSwyllys 
146730a5e8faSwyllys 	return (createReqFn(handle, num_args, attrlist));
146830a5e8faSwyllys 
146999ebb4caSwyllys }
147099ebb4caSwyllys 
147199ebb4caSwyllys KMF_RETURN
147230a5e8faSwyllys kmf_get_ocsp_status_for_cert(KMF_HANDLE_T handle,
147330a5e8faSwyllys 	int	num_args,
147430a5e8faSwyllys 	KMF_ATTRIBUTE	*attrlist)
147599ebb4caSwyllys {
147630a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
147799ebb4caSwyllys 	KMF_PLUGIN *plugin;
147830a5e8faSwyllys 	KMF_RETURN (*getCertStatusFn)(void *, int num_args,
147930a5e8faSwyllys 	    KMF_ATTRIBUTE *attrlist);
148030a5e8faSwyllys 
148130a5e8faSwyllys 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
148230a5e8faSwyllys 		{KMF_USER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
148330a5e8faSwyllys 			sizeof (KMF_DATA)},
148430a5e8faSwyllys 		{KMF_ISSUER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
148530a5e8faSwyllys 			sizeof (KMF_DATA)},
148630a5e8faSwyllys 		{KMF_OCSP_RESPONSE_DATA_ATTR, FALSE, sizeof (KMF_DATA),
148730a5e8faSwyllys 			sizeof (KMF_DATA)},
148830a5e8faSwyllys 		{KMF_OCSP_RESPONSE_STATUS_ATTR, FALSE, sizeof (int),
148930a5e8faSwyllys 			sizeof (uint32_t)},
149030a5e8faSwyllys 		{KMF_OCSP_RESPONSE_REASON_ATTR, FALSE, sizeof (int),
149130a5e8faSwyllys 			sizeof (uint32_t)},
149230a5e8faSwyllys 		{KMF_OCSP_RESPONSE_CERT_STATUS_ATTR, FALSE, sizeof (int),
149330a5e8faSwyllys 			sizeof (uint32_t)},
149430a5e8faSwyllys 	};
149530a5e8faSwyllys 
149630a5e8faSwyllys 	int num_req_attrs = sizeof (required_attrs) /
149730a5e8faSwyllys 	    sizeof (KMF_ATTRIBUTE_TESTER);
149830a5e8faSwyllys 
149930a5e8faSwyllys 	if (handle == NULL)
150030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
150199ebb4caSwyllys 
150299ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
150399ebb4caSwyllys 
150430a5e8faSwyllys 	ret = test_attributes(num_req_attrs, required_attrs,
150530a5e8faSwyllys 	    0, NULL, num_args, attrlist);
150699ebb4caSwyllys 
150730a5e8faSwyllys 	if (ret != KMF_OK)
150830a5e8faSwyllys 		return (ret);
150999ebb4caSwyllys 
151099ebb4caSwyllys 	/*
151199ebb4caSwyllys 	 * This framework function is actually implemented in the openssl
151299ebb4caSwyllys 	 * plugin library, so we find the function address and call it.
151399ebb4caSwyllys 	 */
151499ebb4caSwyllys 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
151599ebb4caSwyllys 	if (plugin == NULL || plugin->dldesc == NULL) {
151699ebb4caSwyllys 		return (KMF_ERR_INTERNAL);
151799ebb4caSwyllys 	}
151899ebb4caSwyllys 
151999ebb4caSwyllys 	getCertStatusFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
152099ebb4caSwyllys 	    "OpenSSL_GetOCSPStatusForCert");
152199ebb4caSwyllys 	if (getCertStatusFn == NULL) {
152299ebb4caSwyllys 		return (KMF_ERR_INTERNAL);
152399ebb4caSwyllys 	}
152499ebb4caSwyllys 
152530a5e8faSwyllys 	return (getCertStatusFn(handle, num_args, attrlist));
152630a5e8faSwyllys 
152799ebb4caSwyllys }
152899ebb4caSwyllys 
152999ebb4caSwyllys KMF_RETURN
153030a5e8faSwyllys kmf_string_to_oid(char *oidstring, KMF_OID *oid)
153199ebb4caSwyllys {
153299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
153399ebb4caSwyllys 	char *cp, *bp, *startp;
153499ebb4caSwyllys 	int numbuf;
153599ebb4caSwyllys 	int onumbuf;
153699ebb4caSwyllys 	int nbytes, index;
153799ebb4caSwyllys 	int len;
153899ebb4caSwyllys 	unsigned char *op;
153999ebb4caSwyllys 
154099ebb4caSwyllys 	if (oidstring == NULL || oid == NULL)
154199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
154299ebb4caSwyllys 
154399ebb4caSwyllys 	len = strlen(oidstring);
154499ebb4caSwyllys 
154599ebb4caSwyllys 	bp = oidstring;
154699ebb4caSwyllys 	cp = bp;
154799ebb4caSwyllys 	/* Skip over leading space */
154899ebb4caSwyllys 	while ((bp < &cp[len]) && isspace(*bp))
154999ebb4caSwyllys 		bp++;
155099ebb4caSwyllys 
155199ebb4caSwyllys 	startp = bp;
155299ebb4caSwyllys 	nbytes = 0;
155399ebb4caSwyllys 
155499ebb4caSwyllys 	/*
155599ebb4caSwyllys 	 * The first two numbers are chewed up by the first octet.
155699ebb4caSwyllys 	 */
155799ebb4caSwyllys 	if (sscanf(bp, "%d", &numbuf) != 1)
155899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
155999ebb4caSwyllys 	while ((bp < &cp[len]) && isdigit(*bp))
156099ebb4caSwyllys 		bp++;
156199ebb4caSwyllys 	while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
156299ebb4caSwyllys 		bp++;
156399ebb4caSwyllys 	if (sscanf(bp, "%d", &numbuf) != 1)
156499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
156599ebb4caSwyllys 	while ((bp < &cp[len]) && isdigit(*bp))
156699ebb4caSwyllys 		bp++;
156799ebb4caSwyllys 	while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
156899ebb4caSwyllys 		bp++;
156999ebb4caSwyllys 	nbytes++;
157099ebb4caSwyllys 
157199ebb4caSwyllys 	while (isdigit(*bp)) {
157299ebb4caSwyllys 		if (sscanf(bp, "%d", &numbuf) != 1)
157399ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
157499ebb4caSwyllys 		while (numbuf) {
157599ebb4caSwyllys 			nbytes++;
157699ebb4caSwyllys 			numbuf >>= 7;
157799ebb4caSwyllys 		}
157899ebb4caSwyllys 		while ((bp < &cp[len]) && isdigit(*bp))
157999ebb4caSwyllys 			bp++;
158099ebb4caSwyllys 		while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
158199ebb4caSwyllys 			bp++;
158299ebb4caSwyllys 	}
158399ebb4caSwyllys 
158499ebb4caSwyllys 	oid->Length = nbytes;
158599ebb4caSwyllys 	oid->Data = malloc(oid->Length);
158699ebb4caSwyllys 	if (oid->Data == NULL) {
158799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
158899ebb4caSwyllys 	}
158999ebb4caSwyllys 	(void) memset(oid->Data, 0, oid->Length);
159099ebb4caSwyllys 
159199ebb4caSwyllys 	op = oid->Data;
159299ebb4caSwyllys 
159399ebb4caSwyllys 	bp = startp;
159499ebb4caSwyllys 	(void) sscanf(bp, "%d", &numbuf);
159599ebb4caSwyllys 
159699ebb4caSwyllys 	while (isdigit(*bp)) bp++;
159799ebb4caSwyllys 	while (isspace(*bp) || *bp == '.') bp++;
159899ebb4caSwyllys 
159999ebb4caSwyllys 	onumbuf = 40 * numbuf;
160099ebb4caSwyllys 	(void) sscanf(bp, "%d", &numbuf);
160199ebb4caSwyllys 	onumbuf += numbuf;
160299ebb4caSwyllys 	*op = (unsigned char) onumbuf;
160399ebb4caSwyllys 	op++;
160499ebb4caSwyllys 
160599ebb4caSwyllys 	while (isdigit(*bp)) bp++;
160699ebb4caSwyllys 	while (isspace(*bp) || *bp == '.') bp++;
160799ebb4caSwyllys 	while (isdigit(*bp)) {
160899ebb4caSwyllys 		(void) sscanf(bp, "%d", &numbuf);
160999ebb4caSwyllys 		nbytes = 0;
161099ebb4caSwyllys 		/* Have to fill in the bytes msb-first */
161199ebb4caSwyllys 		onumbuf = numbuf;
161299ebb4caSwyllys 		while (numbuf) {
161399ebb4caSwyllys 			nbytes++;
161499ebb4caSwyllys 			numbuf >>= 7;
161599ebb4caSwyllys 		}
161699ebb4caSwyllys 		numbuf = onumbuf;
161799ebb4caSwyllys 		op += nbytes;
161899ebb4caSwyllys 		index = -1;
161999ebb4caSwyllys 		while (numbuf) {
162099ebb4caSwyllys 			op[index] = (unsigned char)numbuf & 0x7f;
162199ebb4caSwyllys 			if (index != -1)
162299ebb4caSwyllys 				op[index] |= 0x80;
162399ebb4caSwyllys 			index--;
162499ebb4caSwyllys 			numbuf >>= 7;
162599ebb4caSwyllys 		}
162699ebb4caSwyllys 		while (isdigit(*bp)) bp++;
162799ebb4caSwyllys 		while (isspace(*bp) || *bp == '.') bp++;
162899ebb4caSwyllys 	}
162999ebb4caSwyllys 
163099ebb4caSwyllys 	return (rv);
163199ebb4caSwyllys }
163299ebb4caSwyllys 
163399ebb4caSwyllys static KMF_RETURN
163499ebb4caSwyllys encode_rid(char *name, KMF_DATA *derdata)
163599ebb4caSwyllys {
163699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
163799ebb4caSwyllys 
163899ebb4caSwyllys 	if (name == NULL || derdata == NULL)
163999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
164099ebb4caSwyllys 
164130a5e8faSwyllys 	rv = kmf_string_to_oid(name, (KMF_OID *)derdata);
164299ebb4caSwyllys 
164399ebb4caSwyllys 	return (rv);
164499ebb4caSwyllys }
164599ebb4caSwyllys 
164699ebb4caSwyllys static KMF_RETURN
164799ebb4caSwyllys encode_ipaddr(char *name, KMF_DATA *derdata)
164899ebb4caSwyllys {
164999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
165099ebb4caSwyllys 	size_t len;
165199ebb4caSwyllys 	in_addr_t v4;
165299ebb4caSwyllys 	in6_addr_t v6;
165399ebb4caSwyllys 	uint8_t *ptr;
165499ebb4caSwyllys 
165599ebb4caSwyllys 	if (name == NULL || derdata == NULL)
165699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
165799ebb4caSwyllys 
165899ebb4caSwyllys 	v4 = inet_addr(name);
165999ebb4caSwyllys 	if (v4 == (in_addr_t)-1) {
166099ebb4caSwyllys 		ptr = (uint8_t *)&v6;
166199ebb4caSwyllys 		if (inet_pton(AF_INET6, name, ptr) != 1)
166299ebb4caSwyllys 			return (KMF_ERR_ENCODING);
166399ebb4caSwyllys 		len = sizeof (v6);
166499ebb4caSwyllys 	} else {
166599ebb4caSwyllys 		ptr = (uint8_t *)&v4;
166699ebb4caSwyllys 		len = sizeof (v4);
166799ebb4caSwyllys 	}
166899ebb4caSwyllys 
166999ebb4caSwyllys 	derdata->Data = malloc(len);
167099ebb4caSwyllys 	if (derdata->Data == NULL)
167199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
167299ebb4caSwyllys 	(void) memcpy(derdata->Data, ptr, len);
167399ebb4caSwyllys 	derdata->Length = len;
167499ebb4caSwyllys 
167599ebb4caSwyllys 	return (rv);
167699ebb4caSwyllys }
167799ebb4caSwyllys 
167899ebb4caSwyllys static KMF_RETURN
167999ebb4caSwyllys verify_uri_format(char *uristring)
168099ebb4caSwyllys {
168199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
168299ebb4caSwyllys 	xmlURIPtr   uriptr = NULL;
168399ebb4caSwyllys 
168499ebb4caSwyllys 	/* Parse the URI string; get the hostname and port */
168599ebb4caSwyllys 	uriptr = xmlParseURI(uristring);
168699ebb4caSwyllys 	if (uriptr == NULL) {
168799ebb4caSwyllys 		ret = KMF_ERR_BAD_URI;
168899ebb4caSwyllys 		goto out;
168999ebb4caSwyllys 	}
169099ebb4caSwyllys 
169199ebb4caSwyllys 	if (uriptr->scheme == NULL || !strlen(uriptr->scheme)) {
169299ebb4caSwyllys 		ret = KMF_ERR_BAD_URI;
169399ebb4caSwyllys 		goto out;
169499ebb4caSwyllys 	}
169599ebb4caSwyllys 
169699ebb4caSwyllys 	if (uriptr->server == NULL || !strlen(uriptr->server)) {
169799ebb4caSwyllys 		ret = KMF_ERR_BAD_URI;
169899ebb4caSwyllys 		goto out;
169999ebb4caSwyllys 	}
170099ebb4caSwyllys out:
170199ebb4caSwyllys 	if (uriptr != NULL)
170299ebb4caSwyllys 		xmlFreeURI(uriptr);
170399ebb4caSwyllys 	return (ret);
170499ebb4caSwyllys }
170599ebb4caSwyllys 
170699ebb4caSwyllys static KMF_RETURN
170799ebb4caSwyllys encode_altname(char *namedata,
170899ebb4caSwyllys 	KMF_GENERALNAMECHOICES nametype, KMF_DATA *encodedname)
170999ebb4caSwyllys {
171099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
171199ebb4caSwyllys 	KMF_X509_NAME dnname;
171299ebb4caSwyllys 	uchar_t tagval;
171399ebb4caSwyllys 	BerElement *asn1 = NULL;
171499ebb4caSwyllys 	BerValue *extdata;
171599ebb4caSwyllys 
171699ebb4caSwyllys 	if (namedata == NULL || encodedname == NULL)
171799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
171899ebb4caSwyllys 
171999ebb4caSwyllys 	/*
172099ebb4caSwyllys 	 * Encode the namedata according to rules in RFC 3280 for GeneralName.
172199ebb4caSwyllys 	 * The input "namedata" is assumed to be an ASCII string representation
172299ebb4caSwyllys 	 * of the AltName, we need to convert it to correct ASN.1 here before
172399ebb4caSwyllys 	 * adding it to the cert.
172499ebb4caSwyllys 	 */
172599ebb4caSwyllys 	switch (nametype) {
172699ebb4caSwyllys 		case GENNAME_RFC822NAME: /* rfc 822 */
172799ebb4caSwyllys 			/* IA5String, no encoding needed */
172899ebb4caSwyllys 			encodedname->Data = (uchar_t *)strdup(namedata);
172999ebb4caSwyllys 			if (encodedname->Data == NULL)
173099ebb4caSwyllys 				return (KMF_ERR_MEMORY);
173199ebb4caSwyllys 			encodedname->Length = strlen(namedata);
173299ebb4caSwyllys 			tagval = (0x80 | nametype);
173399ebb4caSwyllys 			break;
173499ebb4caSwyllys 		case GENNAME_DNSNAME: /* rfc 1034 */
173599ebb4caSwyllys 			encodedname->Data = (uchar_t *)strdup(namedata);
173699ebb4caSwyllys 			if (encodedname->Data == NULL)
173799ebb4caSwyllys 				return (KMF_ERR_MEMORY);
173899ebb4caSwyllys 			encodedname->Length = strlen(namedata);
173999ebb4caSwyllys 			tagval = (0x80 | nametype);
174099ebb4caSwyllys 			break;
174199ebb4caSwyllys 		case GENNAME_URI: /* rfc 1738 */
174299ebb4caSwyllys 			ret = verify_uri_format(namedata);
174399ebb4caSwyllys 			if (ret != KMF_OK)
174499ebb4caSwyllys 				return (ret);
174599ebb4caSwyllys 			/* IA5String, no encoding needed */
174699ebb4caSwyllys 			encodedname->Data = (uchar_t *)strdup(namedata);
174799ebb4caSwyllys 			if (encodedname->Data == NULL)
174899ebb4caSwyllys 				return (KMF_ERR_MEMORY);
174999ebb4caSwyllys 			encodedname->Length = strlen(namedata);
175099ebb4caSwyllys 			tagval = (0x80 | nametype);
175199ebb4caSwyllys 			break;
175299ebb4caSwyllys 		case GENNAME_IPADDRESS:
175399ebb4caSwyllys 			ret =  encode_ipaddr(namedata, encodedname);
175499ebb4caSwyllys 			tagval = (0x80 | nametype);
175599ebb4caSwyllys 			break;
175699ebb4caSwyllys 		case GENNAME_REGISTEREDID:
175799ebb4caSwyllys 			ret = encode_rid(namedata, encodedname);
175899ebb4caSwyllys 			tagval = (0x80 | nametype);
175999ebb4caSwyllys 			break;
176099ebb4caSwyllys 		case GENNAME_DIRECTORYNAME:
176130a5e8faSwyllys 			ret = kmf_dn_parser(namedata, &dnname);
176299ebb4caSwyllys 			if (ret == KMF_OK) {
176330a5e8faSwyllys 				ret = DerEncodeName(&dnname, encodedname);
176499ebb4caSwyllys 			}
176530a5e8faSwyllys 			(void) kmf_free_dn(&dnname);
176699ebb4caSwyllys 			tagval = (0xA0 | nametype);
176799ebb4caSwyllys 			break;
176899ebb4caSwyllys 		default:
176999ebb4caSwyllys 			/* unsupported */
177099ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
177199ebb4caSwyllys 
177299ebb4caSwyllys 	}
177399ebb4caSwyllys 	if (ret != KMF_OK) {
177430a5e8faSwyllys 		kmf_free_data(encodedname);
177599ebb4caSwyllys 		return (ret);
177699ebb4caSwyllys 	}
177799ebb4caSwyllys 
177899ebb4caSwyllys 	if ((asn1 = kmfder_alloc()) == NULL)
177999ebb4caSwyllys 		return (KMF_ERR_MEMORY);
178099ebb4caSwyllys 
178130a5e8faSwyllys 	if (kmfber_printf(asn1, "Tl", tagval, encodedname->Length) == -1)
178299ebb4caSwyllys 		goto cleanup;
178399ebb4caSwyllys 
178499ebb4caSwyllys 	if (kmfber_write(asn1, (char *)encodedname->Data,
178530a5e8faSwyllys 	    encodedname->Length, 0) == -1) {
178699ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
178799ebb4caSwyllys 		goto cleanup;
178899ebb4caSwyllys 	}
178999ebb4caSwyllys 	if (kmfber_flatten(asn1, &extdata) == -1) {
179099ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
179199ebb4caSwyllys 		goto cleanup;
179299ebb4caSwyllys 	}
179399ebb4caSwyllys 
179430a5e8faSwyllys 	kmf_free_data(encodedname);
179599ebb4caSwyllys 	encodedname->Data = (uchar_t *)extdata->bv_val;
179699ebb4caSwyllys 	encodedname->Length = extdata->bv_len;
179799ebb4caSwyllys 
179899ebb4caSwyllys 	free(extdata);
179999ebb4caSwyllys 
180099ebb4caSwyllys cleanup:
180199ebb4caSwyllys 	if (asn1)
180299ebb4caSwyllys 		kmfber_free(asn1, 1);
180399ebb4caSwyllys 
180499ebb4caSwyllys 	if (ret != KMF_OK)
180530a5e8faSwyllys 		kmf_free_data(encodedname);
180699ebb4caSwyllys 
180799ebb4caSwyllys 	return (ret);
180899ebb4caSwyllys }
180999ebb4caSwyllys 
181099ebb4caSwyllys KMF_X509_EXTENSION *
181199ebb4caSwyllys FindExtn(KMF_X509_EXTENSIONS *exts, KMF_OID *oid)
181299ebb4caSwyllys {
181399ebb4caSwyllys 	KMF_X509_EXTENSION *foundextn = NULL;
181499ebb4caSwyllys 	int i;
181599ebb4caSwyllys 
181699ebb4caSwyllys 	if (exts == NULL || oid == NULL)
181799ebb4caSwyllys 		return (NULL);
181899ebb4caSwyllys 
181999ebb4caSwyllys 	for (i = 0; i < exts->numberOfExtensions; i++) {
182099ebb4caSwyllys 		if (IsEqualOid(oid, &exts->extensions[i].extnId))  {
182199ebb4caSwyllys 			foundextn = &exts->extensions[i];
182299ebb4caSwyllys 			break;
182399ebb4caSwyllys 		}
182499ebb4caSwyllys 	}
182599ebb4caSwyllys 	return (foundextn);
182699ebb4caSwyllys }
182799ebb4caSwyllys 
182899ebb4caSwyllys KMF_RETURN
182999ebb4caSwyllys GetSequenceContents(char *data, size_t len,
183099ebb4caSwyllys 	char **contents, size_t *outlen)
183199ebb4caSwyllys {
183299ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
183399ebb4caSwyllys 	BerElement *exasn1 = NULL;
183499ebb4caSwyllys 	BerValue oldextn;
183599ebb4caSwyllys 	int tag;
183699ebb4caSwyllys 	size_t oldsize;
183799ebb4caSwyllys 	char *olddata = NULL;
183899ebb4caSwyllys 
183999ebb4caSwyllys 	if (data == NULL || contents == NULL || outlen == NULL)
184099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
184199ebb4caSwyllys 
184299ebb4caSwyllys 	/*
184399ebb4caSwyllys 	 * Decode the sequence of general names
184499ebb4caSwyllys 	 */
184599ebb4caSwyllys 	oldextn.bv_val = data;
184699ebb4caSwyllys 	oldextn.bv_len = len;
184799ebb4caSwyllys 
184899ebb4caSwyllys 	if ((exasn1 = kmfder_init(&oldextn)) == NULL) {
184999ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
185099ebb4caSwyllys 		goto out;
185199ebb4caSwyllys 	}
185299ebb4caSwyllys 
185399ebb4caSwyllys 	/*
185499ebb4caSwyllys 	 * Unwrap the sequence to find the size of the block
185599ebb4caSwyllys 	 * of GeneralName items in the set.
185699ebb4caSwyllys 	 *
185799ebb4caSwyllys 	 * Peek at the tag and length ("tl"),
185899ebb4caSwyllys 	 * then consume them ("{").
185999ebb4caSwyllys 	 */
186099ebb4caSwyllys 	if (kmfber_scanf(exasn1, "tl{", &tag, &oldsize) == KMFBER_DEFAULT ||
186130a5e8faSwyllys 	    oldsize == 0) {
186299ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
186399ebb4caSwyllys 		goto out;
186499ebb4caSwyllys 	}
186599ebb4caSwyllys 
186699ebb4caSwyllys 	olddata = malloc(oldsize);
186799ebb4caSwyllys 	if (olddata == NULL) {
186899ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
186999ebb4caSwyllys 		goto out;
187099ebb4caSwyllys 	}
187199ebb4caSwyllys 	(void) memset(olddata, 0, oldsize);
187299ebb4caSwyllys 	/*
187399ebb4caSwyllys 	 * Read the entire blob of GeneralNames, we don't
187499ebb4caSwyllys 	 * need to interpret them now.
187599ebb4caSwyllys 	 */
187699ebb4caSwyllys 	if (kmfber_read(exasn1, olddata, oldsize) != oldsize) {
187799ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
187899ebb4caSwyllys 		goto out;
187999ebb4caSwyllys 	}
188099ebb4caSwyllys out:
188199ebb4caSwyllys 	if (exasn1 != NULL)
188299ebb4caSwyllys 		kmfber_free(exasn1, 1);
188399ebb4caSwyllys 
188499ebb4caSwyllys 	if (ret != KMF_OK) {
188599ebb4caSwyllys 		*contents = NULL;
188699ebb4caSwyllys 		*outlen = 0;
188799ebb4caSwyllys 		if (olddata != NULL)
188899ebb4caSwyllys 			free(olddata);
188999ebb4caSwyllys 	} else {
189099ebb4caSwyllys 		*contents = olddata;
189199ebb4caSwyllys 		*outlen = oldsize;
189299ebb4caSwyllys 	}
189399ebb4caSwyllys 	return (ret);
189499ebb4caSwyllys }
189599ebb4caSwyllys 
189699ebb4caSwyllys KMF_RETURN
189799ebb4caSwyllys add_an_extension(KMF_X509_EXTENSIONS *exts, KMF_X509_EXTENSION *newextn)
189899ebb4caSwyllys {
189999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
190099ebb4caSwyllys 	KMF_X509_EXTENSION *extlist;
190199ebb4caSwyllys 
190299ebb4caSwyllys 	if (exts == NULL || newextn == NULL)
190399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
190499ebb4caSwyllys 
190599ebb4caSwyllys 	extlist = malloc(sizeof (KMF_X509_EXTENSION) *
190630a5e8faSwyllys 	    (exts->numberOfExtensions + 1));
190799ebb4caSwyllys 	if (extlist == NULL)
190899ebb4caSwyllys 		return (KMF_ERR_MEMORY);
190999ebb4caSwyllys 
191099ebb4caSwyllys 	(void) memcpy(extlist, exts->extensions,
191199ebb4caSwyllys 	    exts->numberOfExtensions * sizeof (KMF_X509_EXTENSION));
191299ebb4caSwyllys 
191399ebb4caSwyllys 	(void) memcpy(&extlist[exts->numberOfExtensions], newextn,
191430a5e8faSwyllys 	    sizeof (KMF_X509_EXTENSION));
191599ebb4caSwyllys 
191699ebb4caSwyllys 	free(exts->extensions);
191799ebb4caSwyllys 	exts->numberOfExtensions++;
191899ebb4caSwyllys 	exts->extensions = extlist;
191999ebb4caSwyllys 
192099ebb4caSwyllys 	return (ret);
192199ebb4caSwyllys }
192299ebb4caSwyllys 
192399ebb4caSwyllys KMF_RETURN
192430a5e8faSwyllys kmf_set_altname(KMF_X509_EXTENSIONS *extensions,
192599ebb4caSwyllys 	KMF_OID *oid,
192699ebb4caSwyllys 	int critical,
192799ebb4caSwyllys 	KMF_GENERALNAMECHOICES nametype,
192899ebb4caSwyllys 	char *namedata)
192999ebb4caSwyllys {
193099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
193199ebb4caSwyllys 	KMF_X509_EXTENSION subjAltName;
193299ebb4caSwyllys 	KMF_DATA dername = { NULL, 0 };
193399ebb4caSwyllys 	BerElement *asn1 = NULL;
193499ebb4caSwyllys 	BerValue *extdata;
193599ebb4caSwyllys 	char *olddata = NULL;
193699ebb4caSwyllys 	KMF_X509_EXTENSION *foundextn = NULL;
193799ebb4caSwyllys 	size_t	oldsize = 0;
193899ebb4caSwyllys 
193999ebb4caSwyllys 	if (extensions == NULL || oid == NULL || namedata == NULL)
194099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
194199ebb4caSwyllys 
194299ebb4caSwyllys 	ret = encode_altname(namedata, nametype, &dername);
194399ebb4caSwyllys 
194499ebb4caSwyllys 	if (ret != KMF_OK)
194599ebb4caSwyllys 		return (ret);
194699ebb4caSwyllys 
194799ebb4caSwyllys 	(void) memset(&subjAltName, 0, sizeof (subjAltName));
194899ebb4caSwyllys 
194999ebb4caSwyllys 	ret = copy_data(&subjAltName.extnId, oid);
195099ebb4caSwyllys 	if (ret != KMF_OK)
195199ebb4caSwyllys 		goto out;
195299ebb4caSwyllys 	/*
195399ebb4caSwyllys 	 * Check to see if this cert already has a subjectAltName.
195499ebb4caSwyllys 	 */
195599ebb4caSwyllys 	foundextn = FindExtn(extensions, oid);
195699ebb4caSwyllys 
195799ebb4caSwyllys 	if (foundextn != NULL) {
195899ebb4caSwyllys 		ret = GetSequenceContents(
195930a5e8faSwyllys 		    (char *)foundextn->BERvalue.Data,
196030a5e8faSwyllys 		    foundextn->BERvalue.Length,
196130a5e8faSwyllys 		    &olddata, &oldsize);
196299ebb4caSwyllys 		if (ret != KMF_OK)
196399ebb4caSwyllys 			goto out;
196499ebb4caSwyllys 	}
196599ebb4caSwyllys 
196699ebb4caSwyllys 	/*
196799ebb4caSwyllys 	 * Assume (!!) that the namedata given is already properly encoded.
196899ebb4caSwyllys 	 */
196999ebb4caSwyllys 	if ((asn1 = kmfder_alloc()) == NULL)
197099ebb4caSwyllys 		return (KMF_ERR_MEMORY);
197199ebb4caSwyllys 
197299ebb4caSwyllys 	if (kmfber_printf(asn1, "{") == -1) {
197399ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
197499ebb4caSwyllys 		goto out;
197599ebb4caSwyllys 	}
197699ebb4caSwyllys 
197799ebb4caSwyllys 	/* Write the old extension data first */
197899ebb4caSwyllys 	if (olddata != NULL && oldsize > 0) {
197999ebb4caSwyllys 		if (kmfber_write(asn1, olddata, oldsize, 0) == -1) {
198099ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
198199ebb4caSwyllys 			goto out;
198299ebb4caSwyllys 		}
198399ebb4caSwyllys 	}
198499ebb4caSwyllys 
198599ebb4caSwyllys 	/* Now add the new name to the list */
198699ebb4caSwyllys 	if (kmfber_write(asn1, (char *)dername.Data, dername.Length, 0) == -1) {
198799ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
198899ebb4caSwyllys 		goto out;
198999ebb4caSwyllys 	}
199099ebb4caSwyllys 
199199ebb4caSwyllys 	/* Now close the sequence */
199299ebb4caSwyllys 	if (kmfber_printf(asn1, "}") == -1) {
199399ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
199499ebb4caSwyllys 		goto out;
199599ebb4caSwyllys 	}
199699ebb4caSwyllys 	if (kmfber_flatten(asn1, &extdata) == -1) {
199799ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
199899ebb4caSwyllys 		goto out;
199999ebb4caSwyllys 	}
200099ebb4caSwyllys 
200199ebb4caSwyllys 	/*
200299ebb4caSwyllys 	 * If we are just adding to an existing list of altNames,
200399ebb4caSwyllys 	 * just replace the BER data associated with the found extension.
200499ebb4caSwyllys 	 */
200599ebb4caSwyllys 	if (foundextn != NULL) {
200699ebb4caSwyllys 		free(foundextn->BERvalue.Data);
200799ebb4caSwyllys 		foundextn->critical = critical;
200899ebb4caSwyllys 		foundextn->BERvalue.Data = (uchar_t *)extdata->bv_val;
200999ebb4caSwyllys 		foundextn->BERvalue.Length = extdata->bv_len;
201099ebb4caSwyllys 	} else {
201199ebb4caSwyllys 		subjAltName.critical = critical;
201299ebb4caSwyllys 		subjAltName.format = KMF_X509_DATAFORMAT_ENCODED;
201399ebb4caSwyllys 		subjAltName.BERvalue.Data = (uchar_t *)extdata->bv_val;
201499ebb4caSwyllys 		subjAltName.BERvalue.Length = extdata->bv_len;
201599ebb4caSwyllys 		ret = add_an_extension(extensions, &subjAltName);
201699ebb4caSwyllys 		if (ret != KMF_OK)
201799ebb4caSwyllys 			free(subjAltName.BERvalue.Data);
201899ebb4caSwyllys 	}
201999ebb4caSwyllys 
202099ebb4caSwyllys 	free(extdata);
202199ebb4caSwyllys out:
202299ebb4caSwyllys 	if (olddata != NULL)
202399ebb4caSwyllys 		free(olddata);
202499ebb4caSwyllys 
202530a5e8faSwyllys 	kmf_free_data(&dername);
202699ebb4caSwyllys 	if (ret != KMF_OK)
202730a5e8faSwyllys 		kmf_free_data(&subjAltName.extnId);
202899ebb4caSwyllys 	if (asn1 != NULL)
202999ebb4caSwyllys 		kmfber_free(asn1, 1);
203099ebb4caSwyllys 	return (ret);
203199ebb4caSwyllys }
203230a5e8faSwyllys 
203330a5e8faSwyllys /*
203430a5e8faSwyllys  * Search a list of attributes for one that matches the given type.
203530a5e8faSwyllys  * Return a pointer into the attribute list.  This does not
203630a5e8faSwyllys  * return a copy of the value, it returns a reference into the
203730a5e8faSwyllys  * given list.
203830a5e8faSwyllys  */
203930a5e8faSwyllys int
204030a5e8faSwyllys kmf_find_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist, int numattrs)
204130a5e8faSwyllys {
204230a5e8faSwyllys 	int i;
204330a5e8faSwyllys 	for (i = 0; i < numattrs; i++) {
204430a5e8faSwyllys 		if (attlist[i].type == type)
204530a5e8faSwyllys 			return (i);
204630a5e8faSwyllys 	}
204730a5e8faSwyllys 	return (-1);
204830a5e8faSwyllys }
204930a5e8faSwyllys 
205030a5e8faSwyllys /*
205130a5e8faSwyllys  * Verify that a given attribute is consistent with the
205230a5e8faSwyllys  * "test" attribute.
205330a5e8faSwyllys  */
205430a5e8faSwyllys static KMF_RETURN
205530a5e8faSwyllys verify_attribute(KMF_ATTRIBUTE *givenattr,
205630a5e8faSwyllys 	KMF_ATTRIBUTE_TESTER *testattr)
205730a5e8faSwyllys {
205830a5e8faSwyllys 	/* A NULL pValue was found where one is required */
205930a5e8faSwyllys 	if (testattr->null_value_ok == FALSE &&
206030a5e8faSwyllys 	    givenattr->pValue == NULL)
206130a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
206230a5e8faSwyllys 
206330a5e8faSwyllys 	/* If the given valueLen is too small, return error */
206430a5e8faSwyllys 	if (givenattr->pValue != NULL &&
206530a5e8faSwyllys 	    testattr->minlen > 0 &&
206630a5e8faSwyllys 	    (givenattr->valueLen < testattr->minlen))
206730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
206830a5e8faSwyllys 
206930a5e8faSwyllys 	/* If the given valueLen is too big, return error */
207030a5e8faSwyllys 	if (givenattr->pValue != NULL &&
207130a5e8faSwyllys 	    testattr->maxlen > 0 &&
207230a5e8faSwyllys 	    (givenattr->valueLen > testattr->maxlen))
207330a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
207430a5e8faSwyllys 
207530a5e8faSwyllys 	return (KMF_OK);
207630a5e8faSwyllys }
207730a5e8faSwyllys 
207830a5e8faSwyllys /*
207930a5e8faSwyllys  * Given a set of required attribute tests and optional
208030a5e8faSwyllys  * attributes, make sure that the actual attributes
208130a5e8faSwyllys  * being tested (attrlist below) are allowed and are
208230a5e8faSwyllys  * properly specified.
208330a5e8faSwyllys  */
208430a5e8faSwyllys KMF_RETURN
208530a5e8faSwyllys test_attributes(int reqnum, KMF_ATTRIBUTE_TESTER *reqattrs,
208630a5e8faSwyllys 	int optnum, KMF_ATTRIBUTE_TESTER *optattrs,
208730a5e8faSwyllys 	int numattrs, KMF_ATTRIBUTE *attrlist)
208830a5e8faSwyllys {
208930a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
209030a5e8faSwyllys 	int i, idx;
209130a5e8faSwyllys 
209230a5e8faSwyllys 	/*
209330a5e8faSwyllys 	 * If the caller didn't supply enough attributes,
209430a5e8faSwyllys 	 * return an error.
209530a5e8faSwyllys 	 */
209630a5e8faSwyllys 	if (numattrs < reqnum || attrlist == NULL)
209730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
209830a5e8faSwyllys 
209930a5e8faSwyllys 	/*
210030a5e8faSwyllys 	 * Make sure all required attrs are present and
210130a5e8faSwyllys 	 * correct.
210230a5e8faSwyllys 	 */
210330a5e8faSwyllys 	for (i = 0; i < reqnum && ret == KMF_OK; i++) {
210430a5e8faSwyllys 		idx = kmf_find_attr(reqattrs[i].type, attrlist, numattrs);
210530a5e8faSwyllys 		/* If a required attr is not found, return error */
210630a5e8faSwyllys 		if (idx == -1) {
210730a5e8faSwyllys 			return (KMF_ERR_BAD_PARAMETER);
210830a5e8faSwyllys 		}
210930a5e8faSwyllys 
211030a5e8faSwyllys 		ret = verify_attribute(&attrlist[idx], &reqattrs[i]);
211130a5e8faSwyllys 	}
211230a5e8faSwyllys 	/*
211330a5e8faSwyllys 	 * Now test the optional parameters.
211430a5e8faSwyllys 	 */
211530a5e8faSwyllys 	for (i = 0; i < optnum && ret == KMF_OK; i++) {
211630a5e8faSwyllys 		idx = kmf_find_attr(optattrs[i].type, attrlist, numattrs);
211730a5e8faSwyllys 		/* If a optional attr is not found, continue. */
211830a5e8faSwyllys 		if (idx == -1) {
211930a5e8faSwyllys 			continue;
212030a5e8faSwyllys 		}
212130a5e8faSwyllys 
212230a5e8faSwyllys 		ret = verify_attribute(&attrlist[idx], &optattrs[i]);
212330a5e8faSwyllys 	}
212430a5e8faSwyllys 
212530a5e8faSwyllys 	return (ret);
212630a5e8faSwyllys }
212730a5e8faSwyllys 
212830a5e8faSwyllys /*
212930a5e8faSwyllys  * Given an already allocated attribute list, insert
213030a5e8faSwyllys  * the given attribute information at a specific index
213130a5e8faSwyllys  * in the list.
213230a5e8faSwyllys  */
213330a5e8faSwyllys void
213430a5e8faSwyllys kmf_set_attr_at_index(KMF_ATTRIBUTE *attlist, int index,
213530a5e8faSwyllys 	KMF_ATTR_TYPE type,  void *pValue, uint32_t len)
213630a5e8faSwyllys {
213730a5e8faSwyllys 	if (attlist == NULL)
213830a5e8faSwyllys 		return;
213930a5e8faSwyllys 
214030a5e8faSwyllys 	attlist[index].type = type;
214130a5e8faSwyllys 	attlist[index].pValue = pValue;
214230a5e8faSwyllys 	attlist[index].valueLen = len;
214330a5e8faSwyllys }
214430a5e8faSwyllys 
214530a5e8faSwyllys /*
214630a5e8faSwyllys  * Find an attribute matching a particular type and set
214730a5e8faSwyllys  * the pValue and length fields to the given values.
214830a5e8faSwyllys  */
214930a5e8faSwyllys KMF_RETURN
215030a5e8faSwyllys kmf_set_attr(KMF_ATTRIBUTE *attlist, int numattr,
215130a5e8faSwyllys 	KMF_ATTR_TYPE type,  void *pValue, uint32_t len)
215230a5e8faSwyllys {
215330a5e8faSwyllys 	int idx;
215430a5e8faSwyllys 	if (attlist == NULL)
215530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
215630a5e8faSwyllys 
215730a5e8faSwyllys 	idx = kmf_find_attr(type, attlist, numattr);
215830a5e8faSwyllys 	if (idx == -1)
215930a5e8faSwyllys 		return (KMF_ERR_ATTR_NOT_FOUND);
216030a5e8faSwyllys 
216130a5e8faSwyllys 	attlist[idx].type = type;
216230a5e8faSwyllys 	/* Assumes the attribute pValue can hold the result */
216330a5e8faSwyllys 	if (attlist[idx].pValue != NULL) {
216430a5e8faSwyllys 		if (attlist[idx].valueLen >= len)
216530a5e8faSwyllys 			(void) memcpy(attlist[idx].pValue, pValue, len);
216630a5e8faSwyllys 		else
216730a5e8faSwyllys 			return (KMF_ERR_BUFFER_SIZE);
216830a5e8faSwyllys 	}
216930a5e8faSwyllys 	attlist[idx].valueLen = len;
217030a5e8faSwyllys 	return (KMF_OK);
217130a5e8faSwyllys }
217230a5e8faSwyllys 
217330a5e8faSwyllys /*
217430a5e8faSwyllys  * Find a particular attribute in a list and return
217530a5e8faSwyllys  * a pointer to its value.
217630a5e8faSwyllys  */
217730a5e8faSwyllys void *
217830a5e8faSwyllys kmf_get_attr_ptr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist,
217930a5e8faSwyllys 	int numattrs)
218030a5e8faSwyllys {
218130a5e8faSwyllys 	int i;
218230a5e8faSwyllys 
218330a5e8faSwyllys 	i = kmf_find_attr(type, attlist, numattrs);
218430a5e8faSwyllys 	if (i == -1)
218530a5e8faSwyllys 		return (NULL);
218630a5e8faSwyllys 
218730a5e8faSwyllys 	return (attlist[i].pValue);
218830a5e8faSwyllys }
218930a5e8faSwyllys 
219030a5e8faSwyllys /*
219130a5e8faSwyllys  * Find a particular attribute in a list and return
219230a5e8faSwyllys  * the value and length values.  Value and length
219330a5e8faSwyllys  * may be NULL if the caller doesn't want their values
219430a5e8faSwyllys  * to be filled in.
219530a5e8faSwyllys  */
219630a5e8faSwyllys KMF_RETURN
219730a5e8faSwyllys kmf_get_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist,
219830a5e8faSwyllys 	int numattrs, void *outValue, uint32_t *outlen)
219930a5e8faSwyllys {
220030a5e8faSwyllys 	int i;
220130a5e8faSwyllys 	uint32_t len = 0;
220230a5e8faSwyllys 	uint32_t *lenptr = outlen;
220330a5e8faSwyllys 
220430a5e8faSwyllys 	if (lenptr == NULL)
220530a5e8faSwyllys 		lenptr = &len;
220630a5e8faSwyllys 
220730a5e8faSwyllys 	i = kmf_find_attr(type, attlist, numattrs);
220830a5e8faSwyllys 	if (i == -1)
220930a5e8faSwyllys 		return (KMF_ERR_ATTR_NOT_FOUND);
221030a5e8faSwyllys 
221130a5e8faSwyllys 	/* This assumes that the ptr passed in is pre-allocated space */
221230a5e8faSwyllys 	if (attlist[i].pValue != NULL && outValue != NULL) {
221330a5e8faSwyllys 		/*
221430a5e8faSwyllys 		 * If the caller did not specify a length,
221530a5e8faSwyllys 		 * assume "outValue" is big enough.
221630a5e8faSwyllys 		 */
221730a5e8faSwyllys 		if (outlen != NULL) {
221830a5e8faSwyllys 			if (*outlen >= attlist[i].valueLen)
221930a5e8faSwyllys 				(void) memcpy(outValue, attlist[i].pValue,
222030a5e8faSwyllys 				    attlist[i].valueLen);
222130a5e8faSwyllys 			else
222230a5e8faSwyllys 				return (KMF_ERR_BUFFER_SIZE);
222330a5e8faSwyllys 		} else {
222430a5e8faSwyllys 			(void) memcpy(outValue, attlist[i].pValue,
222530a5e8faSwyllys 			    attlist[i].valueLen);
222630a5e8faSwyllys 		}
222730a5e8faSwyllys 	}
222830a5e8faSwyllys 
222930a5e8faSwyllys 	if (outlen != NULL)
223030a5e8faSwyllys 		*outlen = attlist[i].valueLen;
223130a5e8faSwyllys 	return (KMF_OK);
223230a5e8faSwyllys }
223330a5e8faSwyllys 
223430a5e8faSwyllys /*
223530a5e8faSwyllys  * Utility routine to find a string type attribute, allocate it
223630a5e8faSwyllys  * and return the value to the caller.  This simplifies the
223730a5e8faSwyllys  * operation by doing both "kmf_get_attr" calls and avoids
223830a5e8faSwyllys  * duplicating this block of code in lots of places.
223930a5e8faSwyllys  */
224030a5e8faSwyllys KMF_RETURN
224130a5e8faSwyllys kmf_get_string_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attrlist,
224230a5e8faSwyllys 	int numattrs, char **outstr)
224330a5e8faSwyllys {
224430a5e8faSwyllys 	KMF_RETURN rv;
224530a5e8faSwyllys 	uint32_t len;
224630a5e8faSwyllys 
224730a5e8faSwyllys 	if (outstr == NULL)
224830a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
224930a5e8faSwyllys 
225030a5e8faSwyllys 	if ((rv = kmf_get_attr(type, attrlist, numattrs, NULL, &len)) ==
225130a5e8faSwyllys 	    KMF_OK) {
225230a5e8faSwyllys 		*outstr = malloc(len + 1);
225330a5e8faSwyllys 		if ((*outstr) == NULL)
225430a5e8faSwyllys 			return (KMF_ERR_MEMORY);
225530a5e8faSwyllys 		(void) memset((*outstr), 0, len + 1);
225630a5e8faSwyllys 		rv = kmf_get_attr(type, attrlist, numattrs, (*outstr), &len);
225730a5e8faSwyllys 		if (rv != KMF_OK) {
225830a5e8faSwyllys 			free(*outstr);
225930a5e8faSwyllys 			*outstr = NULL;
226030a5e8faSwyllys 		}
226130a5e8faSwyllys 	}
226230a5e8faSwyllys 
226330a5e8faSwyllys 	return (rv);
226430a5e8faSwyllys }
226530a5e8faSwyllys 
2266*431deaa0Shylee 
2267*431deaa0Shylee void
2268*431deaa0Shylee free_entry(conf_entry_t *entry)
2269*431deaa0Shylee {
2270*431deaa0Shylee 	if (entry == NULL)
2271*431deaa0Shylee 		return;
2272*431deaa0Shylee 	free(entry->keystore);
2273*431deaa0Shylee 	free(entry->modulepath);
2274*431deaa0Shylee 	free(entry->option);
2275*431deaa0Shylee }
2276*431deaa0Shylee 
2277*431deaa0Shylee void
2278*431deaa0Shylee free_entrylist(conf_entrylist_t *list)
2279*431deaa0Shylee {
2280*431deaa0Shylee 	conf_entrylist_t *next;
2281*431deaa0Shylee 
2282*431deaa0Shylee 	while (list != NULL) {
2283*431deaa0Shylee 		next = list->next;
2284*431deaa0Shylee 		free_entry(list->entry);
2285*431deaa0Shylee 		free(list);
2286*431deaa0Shylee 		list = next;
2287*431deaa0Shylee 	}
2288*431deaa0Shylee }
2289*431deaa0Shylee 
2290*431deaa0Shylee static KMF_RETURN
2291*431deaa0Shylee parse_entry(char *buf, conf_entry_t **entry)
2292*431deaa0Shylee {
2293*431deaa0Shylee 	KMF_RETURN ret = KMF_OK;
2294*431deaa0Shylee 	conf_entry_t *tmp = NULL;
2295*431deaa0Shylee 	char *token1;
2296*431deaa0Shylee 	char *token2;
2297*431deaa0Shylee 	char *token3;
2298*431deaa0Shylee 	char *lasts;
2299*431deaa0Shylee 	char *value;
2300*431deaa0Shylee 
2301*431deaa0Shylee 	if ((token1 = strtok_r(buf, SEP_COLON, &lasts)) == NULL)
2302*431deaa0Shylee 		return (KMF_ERR_KMF_CONF);
2303*431deaa0Shylee 
2304*431deaa0Shylee 	if ((tmp = calloc(sizeof (conf_entry_t), 1)) == NULL)
2305*431deaa0Shylee 		return (KMF_ERR_MEMORY);
2306*431deaa0Shylee 
2307*431deaa0Shylee 	if ((tmp->keystore = strdup(token1)) == NULL) {
2308*431deaa0Shylee 		ret = KMF_ERR_MEMORY;
2309*431deaa0Shylee 		goto end;
2310*431deaa0Shylee 	}
2311*431deaa0Shylee 
2312*431deaa0Shylee 	if ((token2 = strtok_r(NULL, SEP_SEMICOLON, &lasts)) == NULL) {
2313*431deaa0Shylee 		ret = KMF_ERR_KMF_CONF;
2314*431deaa0Shylee 		goto end;
2315*431deaa0Shylee 	}
2316*431deaa0Shylee 
2317*431deaa0Shylee 	/* need to get token3 first to satisfy nested strtok invocations */
2318*431deaa0Shylee 	token3 = strtok_r(NULL, SEP_SEMICOLON, &lasts);
2319*431deaa0Shylee 
2320*431deaa0Shylee 	/* parse token2 */
2321*431deaa0Shylee 	if (strncmp(token2, CONF_MODULEPATH, strlen(CONF_MODULEPATH)) != 0) {
2322*431deaa0Shylee 		ret = KMF_ERR_KMF_CONF;
2323*431deaa0Shylee 		goto end;
2324*431deaa0Shylee 	}
2325*431deaa0Shylee 
2326*431deaa0Shylee 	if (value = strpbrk(token2, SEP_EQUAL)) {
2327*431deaa0Shylee 		value++; /* get rid of = */
2328*431deaa0Shylee 	} else {
2329*431deaa0Shylee 		ret = KMF_ERR_KMF_CONF;
2330*431deaa0Shylee 		goto end;
2331*431deaa0Shylee 	}
2332*431deaa0Shylee 
2333*431deaa0Shylee 	if ((tmp->modulepath = strdup(value)) == NULL) {
2334*431deaa0Shylee 		ret = KMF_ERR_MEMORY;
2335*431deaa0Shylee 		goto end;
2336*431deaa0Shylee 	}
2337*431deaa0Shylee 
2338*431deaa0Shylee 	/* parse token3, if it exists */
2339*431deaa0Shylee 	if (token3 != NULL) {
2340*431deaa0Shylee 		if (strncmp(token3, CONF_OPTION, strlen(CONF_OPTION))
2341*431deaa0Shylee 		    != 0) {
2342*431deaa0Shylee 			ret = KMF_ERR_KMF_CONF;
2343*431deaa0Shylee 			goto end;
2344*431deaa0Shylee 		}
2345*431deaa0Shylee 
2346*431deaa0Shylee 		if (value = strpbrk(token3, SEP_EQUAL)) {
2347*431deaa0Shylee 			value++; /* get rid of = */
2348*431deaa0Shylee 		} else {
2349*431deaa0Shylee 			ret = KMF_ERR_KMF_CONF;
2350*431deaa0Shylee 			goto end;
2351*431deaa0Shylee 		}
2352*431deaa0Shylee 
2353*431deaa0Shylee 		if ((tmp->option = strdup(value)) == NULL) {
2354*431deaa0Shylee 			ret = KMF_ERR_MEMORY;
2355*431deaa0Shylee 			goto end;
2356*431deaa0Shylee 		}
2357*431deaa0Shylee 	}
2358*431deaa0Shylee 
2359*431deaa0Shylee 	*entry = tmp;
2360*431deaa0Shylee 
2361*431deaa0Shylee end:
2362*431deaa0Shylee 	if (ret != KMF_OK) {
2363*431deaa0Shylee 		free_entry(tmp);
2364*431deaa0Shylee 		free(tmp);
2365*431deaa0Shylee 	}
2366*431deaa0Shylee 	return (ret);
2367*431deaa0Shylee }
2368*431deaa0Shylee 
2369*431deaa0Shylee 
2370*431deaa0Shylee conf_entry_t *
2371*431deaa0Shylee dup_entry(conf_entry_t *entry)
2372*431deaa0Shylee {
2373*431deaa0Shylee 	conf_entry_t *rtn_entry;
2374*431deaa0Shylee 
2375*431deaa0Shylee 	if (entry == NULL)
2376*431deaa0Shylee 		return (NULL);
2377*431deaa0Shylee 
2378*431deaa0Shylee 	rtn_entry = malloc(sizeof (conf_entry_t));
2379*431deaa0Shylee 	if (rtn_entry == NULL)
2380*431deaa0Shylee 		return (NULL);
2381*431deaa0Shylee 
2382*431deaa0Shylee 	if ((rtn_entry->keystore = strdup(entry->keystore)) == NULL)
2383*431deaa0Shylee 		goto out;
2384*431deaa0Shylee 
2385*431deaa0Shylee 	if ((rtn_entry->modulepath = strdup(entry->modulepath)) == NULL)
2386*431deaa0Shylee 		goto out;
2387*431deaa0Shylee 
2388*431deaa0Shylee 	if (entry->option != NULL &&
2389*431deaa0Shylee 	    (rtn_entry->option = strdup(entry->modulepath)) == NULL)
2390*431deaa0Shylee 		goto out;
2391*431deaa0Shylee 
2392*431deaa0Shylee 	return (rtn_entry);
2393*431deaa0Shylee 
2394*431deaa0Shylee out:
2395*431deaa0Shylee 	free_entry(rtn_entry);
2396*431deaa0Shylee 	return (NULL);
2397*431deaa0Shylee }
2398*431deaa0Shylee 
2399*431deaa0Shylee 
2400*431deaa0Shylee /*
2401*431deaa0Shylee  * This function takes a keystore_name as input and returns
2402*431deaa0Shylee  * the KMF_KEYSTORE_TYPE value assigned to it.  If the "option"
2403*431deaa0Shylee  * argument is not NULL, this function also returns the option string
2404*431deaa0Shylee  * if there is an option string for the plugin module.
2405*431deaa0Shylee  */
2406*431deaa0Shylee KMF_RETURN
2407*431deaa0Shylee kmf_get_plugin_info(KMF_HANDLE_T handle, char *keystore_name,
2408*431deaa0Shylee     KMF_KEYSTORE_TYPE *kstype, char **option)
2409*431deaa0Shylee {
2410*431deaa0Shylee 	KMF_RETURN ret = KMF_OK;
2411*431deaa0Shylee 	conf_entrylist_t  *phead = extra_plugin_list;
2412*431deaa0Shylee 	boolean_t is_default = B_TRUE;
2413*431deaa0Shylee 
2414*431deaa0Shylee 	/*
2415*431deaa0Shylee 	 * Although handle is not really used in the function, we will
2416*431deaa0Shylee 	 * check the handle to make sure that kmf_intialize() is called
2417*431deaa0Shylee 	 * before this function.
2418*431deaa0Shylee 	 */
2419*431deaa0Shylee 	if (handle == NULL || keystore_name == NULL || kstype == NULL)
2420*431deaa0Shylee 		return (KMF_ERR_BAD_PARAMETER);
2421*431deaa0Shylee 
2422*431deaa0Shylee 	if (strcmp(keystore_name, "pkcs11") == 0) {
2423*431deaa0Shylee 		*kstype = KMF_KEYSTORE_PK11TOKEN;
2424*431deaa0Shylee 	} else if (strcmp(keystore_name, "file") == 0) {
2425*431deaa0Shylee 		*kstype = KMF_KEYSTORE_OPENSSL;
2426*431deaa0Shylee 	} else if (strcmp(keystore_name, "nss") == 0) {
2427*431deaa0Shylee 		*kstype = KMF_KEYSTORE_NSS;
2428*431deaa0Shylee 	} else {
2429*431deaa0Shylee 		is_default = B_FALSE;
2430*431deaa0Shylee 	}
2431*431deaa0Shylee 
2432*431deaa0Shylee 	if (is_default) {
2433*431deaa0Shylee 		if (option != NULL)
2434*431deaa0Shylee 			*option = NULL;
2435*431deaa0Shylee 		goto out;
2436*431deaa0Shylee 	}
2437*431deaa0Shylee 
2438*431deaa0Shylee 	/* Not a built-in plugin; check if it is in extra_plugin_list. */
2439*431deaa0Shylee 	while (phead != NULL) {
2440*431deaa0Shylee 		if (strcmp(phead->entry->keystore, keystore_name) == 0)
2441*431deaa0Shylee 			break;
2442*431deaa0Shylee 		phead = phead->next;
2443*431deaa0Shylee 	}
2444*431deaa0Shylee 
2445*431deaa0Shylee 	if (phead == NULL) {
2446*431deaa0Shylee 		ret = KMF_ERR_PLUGIN_NOTFOUND;
2447*431deaa0Shylee 		goto out;
2448*431deaa0Shylee 	}
2449*431deaa0Shylee 
2450*431deaa0Shylee 	/* found it */
2451*431deaa0Shylee 	*kstype = phead->entry->kstype;
2452*431deaa0Shylee 	if (option != NULL) {
2453*431deaa0Shylee 		if (phead->entry->option == NULL)
2454*431deaa0Shylee 			*option = NULL;
2455*431deaa0Shylee 		else {
2456*431deaa0Shylee 			*option = strdup(phead->entry->option);
2457*431deaa0Shylee 			if (*option == NULL) {
2458*431deaa0Shylee 				ret = KMF_ERR_MEMORY;
2459*431deaa0Shylee 				goto out;
2460*431deaa0Shylee 			}
2461*431deaa0Shylee 		}
2462*431deaa0Shylee 	}
2463*431deaa0Shylee 
2464*431deaa0Shylee out:
2465*431deaa0Shylee 	return (ret);
2466*431deaa0Shylee }
2467*431deaa0Shylee 
2468*431deaa0Shylee /*
2469*431deaa0Shylee  * Retrieve the non-default plugin list from the kmf.conf file.
2470*431deaa0Shylee  */
2471*431deaa0Shylee KMF_RETURN
2472*431deaa0Shylee get_entrylist(conf_entrylist_t **entlist)
2473*431deaa0Shylee {
2474*431deaa0Shylee 	KMF_RETURN rv = KMF_OK;
2475*431deaa0Shylee 	FILE *pfile;
2476*431deaa0Shylee 	conf_entry_t *entry;
2477*431deaa0Shylee 	conf_entrylist_t *rtnlist = NULL;
2478*431deaa0Shylee 	conf_entrylist_t *ptmp;
2479*431deaa0Shylee 	conf_entrylist_t *pcur;
2480*431deaa0Shylee 	char buffer[MAXPATHLEN];
2481*431deaa0Shylee 	size_t len;
2482*431deaa0Shylee 
2483*431deaa0Shylee 	if ((pfile = fopen(_PATH_KMF_CONF, "rF")) == NULL) {
2484*431deaa0Shylee 		cryptoerror(LOG_ERR, "failed to open %s.\n", _PATH_KMF_CONF);
2485*431deaa0Shylee 		return (KMF_ERR_KMF_CONF);
2486*431deaa0Shylee 	}
2487*431deaa0Shylee 
2488*431deaa0Shylee 	while (fgets(buffer, MAXPATHLEN, pfile) != NULL) {
2489*431deaa0Shylee 		if (buffer[0] == '#' || buffer[0] == ' ' ||
2490*431deaa0Shylee 		    buffer[0] == '\n'|| buffer[0] == '\t') {
2491*431deaa0Shylee 			continue;   /* ignore comment lines */
2492*431deaa0Shylee 		}
2493*431deaa0Shylee 
2494*431deaa0Shylee 		len = strlen(buffer);
2495*431deaa0Shylee 		if (buffer[len-1] == '\n') { /* get rid of trailing '\n' */
2496*431deaa0Shylee 			len--;
2497*431deaa0Shylee 		}
2498*431deaa0Shylee 		buffer[len] = '\0';
2499*431deaa0Shylee 
2500*431deaa0Shylee 		rv = parse_entry(buffer, &entry);
2501*431deaa0Shylee 		if (rv != KMF_OK) {
2502*431deaa0Shylee 			goto end;
2503*431deaa0Shylee 		}
2504*431deaa0Shylee 
2505*431deaa0Shylee 		if ((ptmp = malloc(sizeof (conf_entrylist_t))) == NULL) {
2506*431deaa0Shylee 			rv = KMF_ERR_MEMORY;
2507*431deaa0Shylee 			goto end;
2508*431deaa0Shylee 		}
2509*431deaa0Shylee 		ptmp->entry = entry;
2510*431deaa0Shylee 		ptmp->next = NULL;
2511*431deaa0Shylee 
2512*431deaa0Shylee 		if (rtnlist == NULL) {
2513*431deaa0Shylee 			rtnlist = pcur = ptmp;
2514*431deaa0Shylee 		} else {
2515*431deaa0Shylee 			pcur->next = ptmp;
2516*431deaa0Shylee 			pcur = ptmp;
2517*431deaa0Shylee 		}
2518*431deaa0Shylee 	}
2519*431deaa0Shylee 
2520*431deaa0Shylee end:
2521*431deaa0Shylee 	(void) fclose(pfile);
2522*431deaa0Shylee 
2523*431deaa0Shylee 	if (rv == KMF_OK) {
2524*431deaa0Shylee 		*entlist = rtnlist;
2525*431deaa0Shylee 	} else if (rtnlist != NULL) {
2526*431deaa0Shylee 		free_entrylist(rtnlist);
2527*431deaa0Shylee 		*entlist = NULL;
2528*431deaa0Shylee 		kstore_num = DEFAULT_KEYSTORE_NUM;
2529*431deaa0Shylee 	}
2530*431deaa0Shylee 
2531*431deaa0Shylee 	return (rv);
2532*431deaa0Shylee }
2533*431deaa0Shylee 
2534*431deaa0Shylee 
2535*431deaa0Shylee boolean_t
2536*431deaa0Shylee is_valid_keystore_type(KMF_KEYSTORE_TYPE kstype)
2537*431deaa0Shylee {
2538*431deaa0Shylee 
2539*431deaa0Shylee 	if (kstype > 0 && kstype <= kstore_num)
2540*431deaa0Shylee 		return (B_TRUE);
2541*431deaa0Shylee 	else
2542*431deaa0Shylee 		return (B_FALSE);
2543*431deaa0Shylee }
2544*431deaa0Shylee 
2545*431deaa0Shylee 
254630a5e8faSwyllys /*
254730a5e8faSwyllys  * This API is used by elfsign. We must keep it in old API form.
254830a5e8faSwyllys  */
254930a5e8faSwyllys KMF_RETURN
255030a5e8faSwyllys KMF_ConfigureKeystore(KMF_HANDLE_T handle, KMF_CONFIG_PARAMS *params)
255130a5e8faSwyllys {
255230a5e8faSwyllys 
255330a5e8faSwyllys 	KMF_ATTRIBUTE attlist[32];
255430a5e8faSwyllys 	int i = 0;
255530a5e8faSwyllys 
255630a5e8faSwyllys 	if (params == NULL)
255730a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
255830a5e8faSwyllys 
255930a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
256030a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &params->kstype, sizeof (params->kstype));
256130a5e8faSwyllys 	i++;
256230a5e8faSwyllys 
256330a5e8faSwyllys 	if (params->kstype == KMF_KEYSTORE_NSS) {
256430a5e8faSwyllys 		if (params->nssconfig.configdir != NULL) {
256530a5e8faSwyllys 			kmf_set_attr_at_index(attlist, i,
256630a5e8faSwyllys 			    KMF_DIRPATH_ATTR,
256730a5e8faSwyllys 			    params->nssconfig.configdir,
256830a5e8faSwyllys 			    strlen(params->nssconfig.configdir));
256930a5e8faSwyllys 			i++;
257030a5e8faSwyllys 		}
257130a5e8faSwyllys 		if (params->nssconfig.certPrefix != NULL) {
257230a5e8faSwyllys 			kmf_set_attr_at_index(attlist, i,
257330a5e8faSwyllys 			    KMF_CERTPREFIX_ATTR,
257430a5e8faSwyllys 			    params->nssconfig.certPrefix,
257530a5e8faSwyllys 			    strlen(params->nssconfig.certPrefix));
257630a5e8faSwyllys 			i++;
257730a5e8faSwyllys 		}
257830a5e8faSwyllys 		if (params->nssconfig.keyPrefix != NULL) {
257930a5e8faSwyllys 			kmf_set_attr_at_index(attlist, i,
258030a5e8faSwyllys 			    KMF_KEYPREFIX_ATTR,
258130a5e8faSwyllys 			    params->nssconfig.keyPrefix,
258230a5e8faSwyllys 			    strlen(params->nssconfig.keyPrefix));
258330a5e8faSwyllys 			i++;
258430a5e8faSwyllys 		}
258530a5e8faSwyllys 		if (params->nssconfig.secModName != NULL) {
258630a5e8faSwyllys 			kmf_set_attr_at_index(attlist, i,
258730a5e8faSwyllys 			    KMF_SECMODNAME_ATTR,
258830a5e8faSwyllys 			    params->nssconfig.secModName,
258930a5e8faSwyllys 			    strlen(params->nssconfig.secModName));
259030a5e8faSwyllys 			i++;
259130a5e8faSwyllys 		}
259230a5e8faSwyllys 	} else if (params->kstype == KMF_KEYSTORE_PK11TOKEN) {
259330a5e8faSwyllys 		if (params->pkcs11config.label != NULL) {
259430a5e8faSwyllys 			kmf_set_attr_at_index(attlist, i,
259530a5e8faSwyllys 			    KMF_TOKEN_LABEL_ATTR,
259630a5e8faSwyllys 			    params->pkcs11config.label,
259730a5e8faSwyllys 			    strlen(params->pkcs11config.label));
259830a5e8faSwyllys 			i++;
259930a5e8faSwyllys 		}
260030a5e8faSwyllys 		kmf_set_attr_at_index(attlist, i,
260130a5e8faSwyllys 		    KMF_READONLY_ATTR,
260230a5e8faSwyllys 		    &params->pkcs11config.readonly,
260330a5e8faSwyllys 		    sizeof (params->pkcs11config.readonly));
260430a5e8faSwyllys 		i++;
260530a5e8faSwyllys 	}
260630a5e8faSwyllys 
260730a5e8faSwyllys 	return (kmf_configure_keystore(handle, i, attlist));
260830a5e8faSwyllys }
260930a5e8faSwyllys 
261030a5e8faSwyllys /*
261130a5e8faSwyllys  * This API is used by elfsign. We must keep it in old API form.
261230a5e8faSwyllys  */
261330a5e8faSwyllys KMF_RETURN
261430a5e8faSwyllys KMF_Initialize(KMF_HANDLE_T *outhandle, char *policyfile, char *policyname)
261530a5e8faSwyllys {
261630a5e8faSwyllys 	return (kmf_initialize(outhandle, policyfile, policyname));
261730a5e8faSwyllys }
261830a5e8faSwyllys 
261930a5e8faSwyllys /*
262030a5e8faSwyllys  * This API is used by elfsign. We must keep it in old API form.
262130a5e8faSwyllys  */
262230a5e8faSwyllys KMF_RETURN
262330a5e8faSwyllys KMF_Finalize(KMF_HANDLE_T handle)
262430a5e8faSwyllys {
262530a5e8faSwyllys 	return (kmf_finalize(handle));
262630a5e8faSwyllys }
262730a5e8faSwyllys 
262830a5e8faSwyllys /*
262930a5e8faSwyllys  * This API is used by elfsign. We must keep it in old API form.
263030a5e8faSwyllys  */
263130a5e8faSwyllys KMF_RETURN
263230a5e8faSwyllys KMF_GetKMFErrorString(KMF_RETURN errcode, char **errmsg)
263330a5e8faSwyllys {
263430a5e8faSwyllys 	return (kmf_get_kmf_error_str(errcode, errmsg));
263530a5e8faSwyllys }
263630a5e8faSwyllys 
263730a5e8faSwyllys /*
263830a5e8faSwyllys  * This API is used by elfsign. We must keep it in old API form.
263930a5e8faSwyllys  */
264030a5e8faSwyllys KMF_RETURN
264130a5e8faSwyllys KMF_ReadInputFile(KMF_HANDLE_T handle, char *filename,  KMF_DATA *pdata)
264230a5e8faSwyllys {
264330a5e8faSwyllys 	return (kmf_read_input_file(handle, filename, pdata));
264430a5e8faSwyllys }
264530a5e8faSwyllys 
264630a5e8faSwyllys 
264730a5e8faSwyllys /*
264830a5e8faSwyllys  * This API is used by elfsign. We must keep it in old API form.
264930a5e8faSwyllys  */
265030a5e8faSwyllys void
265130a5e8faSwyllys KMF_FreeKMFCert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
265230a5e8faSwyllys {
265330a5e8faSwyllys 	kmf_free_kmf_cert(handle, kmf_cert);
265430a5e8faSwyllys }
265530a5e8faSwyllys 
265630a5e8faSwyllys /*
265730a5e8faSwyllys  * This API is used by elfsign. We must keep it in old API form.
265830a5e8faSwyllys  */
265930a5e8faSwyllys void
266030a5e8faSwyllys KMF_FreeData(KMF_DATA *datablock)
266130a5e8faSwyllys {
266230a5e8faSwyllys 	kmf_free_data(datablock);
266330a5e8faSwyllys }
266430a5e8faSwyllys 
266530a5e8faSwyllys /*
266630a5e8faSwyllys  * This API is used by elfsign. We must keep it in old API form.
266730a5e8faSwyllys  */
266830a5e8faSwyllys void
266930a5e8faSwyllys KMF_FreeKMFKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key)
267030a5e8faSwyllys {
267130a5e8faSwyllys 	kmf_free_kmf_key(handle, key);
267230a5e8faSwyllys }
267330a5e8faSwyllys 
267430a5e8faSwyllys /*
267530a5e8faSwyllys  * This API is used by elfsign. We must keep it in old API form.
267630a5e8faSwyllys  */
267730a5e8faSwyllys void
267830a5e8faSwyllys KMF_FreeSignedCSR(KMF_CSR_DATA *csr)
267930a5e8faSwyllys {
268030a5e8faSwyllys 	kmf_free_signed_csr(csr);
268130a5e8faSwyllys }
2682