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 
155*30a5e8faSwyllys 
156*30a5e8faSwyllys 
15799ebb4caSwyllys static void free_extensions(KMF_X509_EXTENSIONS *extns);
15899ebb4caSwyllys 
1599b37d296Swyllys KMF_RETURN
1609b37d296Swyllys init_pk11()
16199ebb4caSwyllys {
1629b37d296Swyllys 	(void) mutex_lock(&init_lock);
1639b37d296Swyllys 	if (!pkcs11_initialized) {
1649b37d296Swyllys 		CK_RV rv = C_Initialize(NULL);
1659b37d296Swyllys 		if ((rv != CKR_OK) &&
1669b37d296Swyllys 		    (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
1679b37d296Swyllys 			(void) mutex_unlock(&init_lock);
1689b37d296Swyllys 			return (KMF_ERR_UNINITIALIZED);
1699b37d296Swyllys 		} else {
1709b37d296Swyllys 			pkcs11_initialized = 1;
1719b37d296Swyllys 		}
1729b37d296Swyllys 	}
1739b37d296Swyllys 	(void) mutex_unlock(&init_lock);
1749b37d296Swyllys 	return (KMF_OK);
17599ebb4caSwyllys }
17699ebb4caSwyllys 
17799ebb4caSwyllys /*
17899ebb4caSwyllys  * Private method for searching the plugin list for the correct
17999ebb4caSwyllys  * Plugin to use.
18099ebb4caSwyllys  */
18199ebb4caSwyllys KMF_PLUGIN *
18299ebb4caSwyllys FindPlugin(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE kstype)
18399ebb4caSwyllys {
18499ebb4caSwyllys 	KMF_PLUGIN_LIST *node;
18599ebb4caSwyllys 
18699ebb4caSwyllys 	if (handle == NULL)
18799ebb4caSwyllys 		return (NULL);
18899ebb4caSwyllys 
18999ebb4caSwyllys 	node = handle->plugins;
19099ebb4caSwyllys 
19199ebb4caSwyllys 	while (node != NULL && node->plugin->type != kstype)
19299ebb4caSwyllys 		node = node->next;
19399ebb4caSwyllys 
19499ebb4caSwyllys 	/* If it is NULL, that is indication enough of an error */
19599ebb4caSwyllys 	return (node ? node->plugin : NULL);
19699ebb4caSwyllys }
19799ebb4caSwyllys 
19899ebb4caSwyllys static KMF_RETURN
19999ebb4caSwyllys InitializePlugin(KMF_KEYSTORE_TYPE kstype, char *path, KMF_PLUGIN **plugin)
20099ebb4caSwyllys {
20199ebb4caSwyllys 	KMF_PLUGIN *p = NULL;
20299ebb4caSwyllys 	KMF_PLUGIN_FUNCLIST *(*sym)();
20399ebb4caSwyllys 
20499ebb4caSwyllys 	if (path == NULL || plugin == NULL)
20599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
20699ebb4caSwyllys 
20799ebb4caSwyllys 	*plugin = NULL;
20899ebb4caSwyllys 
20999ebb4caSwyllys 	p = (KMF_PLUGIN *)malloc(sizeof (KMF_PLUGIN));
21099ebb4caSwyllys 	if (p == NULL)
21199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
21299ebb4caSwyllys 
21399ebb4caSwyllys 	p->type = kstype;
21499ebb4caSwyllys 	p->path = strdup(path);
21599ebb4caSwyllys 	if (p->path == NULL) {
21699ebb4caSwyllys 		free(p);
21799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
21899ebb4caSwyllys 	}
21999ebb4caSwyllys 	p->dldesc = dlopen(path, RTLD_NOW | RTLD_GROUP | RTLD_PARENT);
22099ebb4caSwyllys 	if (p->dldesc == NULL) {
22199ebb4caSwyllys 		free(p->path);
22299ebb4caSwyllys 		free(p);
22399ebb4caSwyllys 		return (KMF_ERR_PLUGIN_INIT);
22499ebb4caSwyllys 	}
22599ebb4caSwyllys 
22699ebb4caSwyllys 	sym = (KMF_PLUGIN_FUNCLIST *(*)())dlsym(p->dldesc,
227*30a5e8faSwyllys 	    KMF_PLUGIN_INIT_SYMBOL);
22899ebb4caSwyllys 	if (sym == NULL) {
22999ebb4caSwyllys 		(void) dlclose(p->dldesc);
23099ebb4caSwyllys 		free(p->path);
23199ebb4caSwyllys 		free(p);
23299ebb4caSwyllys 		return (KMF_ERR_PLUGIN_INIT);
23399ebb4caSwyllys 	}
23499ebb4caSwyllys 
23599ebb4caSwyllys 	/* Get the function list */
23699ebb4caSwyllys 	if ((p->funclist = (*sym)()) == NULL) {
23799ebb4caSwyllys 		(void) dlclose(p->dldesc);
23899ebb4caSwyllys 		free(p->path);
23999ebb4caSwyllys 		free(p);
24099ebb4caSwyllys 		return (KMF_ERR_PLUGIN_INIT);
24199ebb4caSwyllys 	}
24299ebb4caSwyllys 
24399ebb4caSwyllys 	*plugin = p;
24499ebb4caSwyllys 
24599ebb4caSwyllys 	return (KMF_OK);
24699ebb4caSwyllys }
24799ebb4caSwyllys 
24899ebb4caSwyllys static KMF_RETURN
24999ebb4caSwyllys AddPlugin(KMF_HANDLE_T handle, KMF_PLUGIN *plugin)
25099ebb4caSwyllys {
25199ebb4caSwyllys 	KMF_PLUGIN_LIST *n;
25299ebb4caSwyllys 
25399ebb4caSwyllys 	if (handle == NULL || plugin == NULL)
25499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
25599ebb4caSwyllys 
25699ebb4caSwyllys 	/* If the head is NULL, create it */
25799ebb4caSwyllys 	if (handle->plugins == NULL) {
25899ebb4caSwyllys 		handle->plugins = (KMF_PLUGIN_LIST *)malloc(
259*30a5e8faSwyllys 		    sizeof (KMF_PLUGIN_LIST));
26099ebb4caSwyllys 		if (handle->plugins == NULL)
26199ebb4caSwyllys 			return (KMF_ERR_MEMORY);
26299ebb4caSwyllys 		handle->plugins->plugin = plugin;
26399ebb4caSwyllys 		handle->plugins->next = NULL;
26499ebb4caSwyllys 	} else {
26599ebb4caSwyllys 		/* walk the list to find the tail */
26699ebb4caSwyllys 		n = handle->plugins;
26799ebb4caSwyllys 		while (n->next != NULL)
26899ebb4caSwyllys 			n = n->next;
26999ebb4caSwyllys 		n->next = (KMF_PLUGIN_LIST *)malloc(sizeof (KMF_PLUGIN_LIST));
27099ebb4caSwyllys 		if (n->next == NULL)
27199ebb4caSwyllys 			return (KMF_ERR_MEMORY);
27299ebb4caSwyllys 
27399ebb4caSwyllys 		n->next->plugin = plugin;
27499ebb4caSwyllys 		n->next->next = NULL;
27599ebb4caSwyllys 	}
27699ebb4caSwyllys 	return (0);
27799ebb4caSwyllys }
27899ebb4caSwyllys 
27999ebb4caSwyllys static void
28099ebb4caSwyllys DestroyPlugin(KMF_PLUGIN *plugin)
28199ebb4caSwyllys {
28299ebb4caSwyllys 	if (plugin) {
28399ebb4caSwyllys 		if (plugin->path)
28499ebb4caSwyllys 			free(plugin->path);
28599ebb4caSwyllys 		free(plugin);
28699ebb4caSwyllys 	}
28799ebb4caSwyllys }
28899ebb4caSwyllys 
28999ebb4caSwyllys static void
29099ebb4caSwyllys Cleanup_KMF_Handle(KMF_HANDLE_T handle)
29199ebb4caSwyllys {
29299ebb4caSwyllys 	if (handle != NULL) {
29399ebb4caSwyllys 		while (handle->plugins != NULL) {
29499ebb4caSwyllys 			KMF_PLUGIN_LIST *next = handle->plugins->next;
29599ebb4caSwyllys 
29699ebb4caSwyllys 			DestroyPlugin(handle->plugins->plugin);
29799ebb4caSwyllys 
29899ebb4caSwyllys 			free(handle->plugins);
29999ebb4caSwyllys 
30099ebb4caSwyllys 			handle->plugins = next;
30199ebb4caSwyllys 		}
30299ebb4caSwyllys 
303*30a5e8faSwyllys 		kmf_free_policy_record(handle->policy);
30499ebb4caSwyllys 		free(handle->policy);
30599ebb4caSwyllys 	}
30699ebb4caSwyllys 	free(handle);
30799ebb4caSwyllys }
30899ebb4caSwyllys 
30999ebb4caSwyllys void
31099ebb4caSwyllys Cleanup_PK11_Session(KMF_HANDLE_T handle)
31199ebb4caSwyllys {
31299ebb4caSwyllys 	if (handle != NULL) {
31399ebb4caSwyllys 		/* Close active session on a pkcs11 token */
31499ebb4caSwyllys 		if (handle->pk11handle != NULL) {
31599ebb4caSwyllys 			(void) C_CloseSession(handle->pk11handle);
31699ebb4caSwyllys 			handle->pk11handle = NULL;
31799ebb4caSwyllys 		}
31899ebb4caSwyllys 	}
31999ebb4caSwyllys }
32099ebb4caSwyllys 
32199ebb4caSwyllys KMF_RETURN
322*30a5e8faSwyllys kmf_initialize(KMF_HANDLE_T *outhandle, char *policyfile, char *policyname)
32399ebb4caSwyllys {
32499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
32599ebb4caSwyllys 	KMF_HANDLE *handle = NULL;
32699ebb4caSwyllys 	KMF_PLUGIN *pluginrec = NULL;
32785b65b39Swyllys 	int i, numitems;
32899ebb4caSwyllys 
32999ebb4caSwyllys 	if (outhandle == NULL)
33099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
33199ebb4caSwyllys 
33299ebb4caSwyllys 	*outhandle = NULL;
33399ebb4caSwyllys 	handle = (KMF_HANDLE *)malloc(sizeof (KMF_HANDLE));
33499ebb4caSwyllys 	if (handle == NULL)
33599ebb4caSwyllys 		return (KMF_ERR_MEMORY);
33699ebb4caSwyllys 
33799ebb4caSwyllys 	(void) memset(handle, 0, sizeof (KMF_HANDLE));
33899ebb4caSwyllys 	handle->plugins = NULL;
33999ebb4caSwyllys 
34099ebb4caSwyllys 	/* Initialize the handle with the policy */
341*30a5e8faSwyllys 	ret = kmf_set_policy((void *)handle,
34299ebb4caSwyllys 	    policyfile == NULL ? KMF_DEFAULT_POLICY_FILE : policyfile,
34399ebb4caSwyllys 	    policyname == NULL ? KMF_DEFAULT_POLICY_NAME : policyname);
34499ebb4caSwyllys 	if (ret != KMF_OK)
34599ebb4caSwyllys 		goto errout;
34699ebb4caSwyllys 
34785b65b39Swyllys 	numitems = sizeof (plugin_list)/sizeof (KMF_PLUGIN_ITEM);
34885b65b39Swyllys 	for (i = 0; i < numitems; i++) {
34985b65b39Swyllys 		ret = InitializePlugin(plugin_list[i].kstype,
350*30a5e8faSwyllys 		    plugin_list[i].path, &pluginrec);
35185b65b39Swyllys 		if (ret != KMF_OK) {
35285b65b39Swyllys 			cryptoerror(
35385b65b39Swyllys 			    plugin_list[i].critical ? LOG_WARNING : LOG_DEBUG,
35485b65b39Swyllys 			    "KMF was unable to load %s plugin module %s\n",
35585b65b39Swyllys 			    plugin_list[i].critical ? "critical" : "optional",
35685b65b39Swyllys 			    plugin_list[i].path);
35785b65b39Swyllys 
35885b65b39Swyllys 			if (plugin_list[i].critical == FALSE)
35985b65b39Swyllys 				ret = KMF_OK;
36085b65b39Swyllys 			else
36185b65b39Swyllys 				goto errout;
36285b65b39Swyllys 		}
36385b65b39Swyllys 		if (pluginrec != NULL) {
36485b65b39Swyllys 			if ((ret = AddPlugin(handle, pluginrec)))
36585b65b39Swyllys 				goto errout;
36685b65b39Swyllys 		}
36799ebb4caSwyllys 	}
36899ebb4caSwyllys 
36999ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
37099ebb4caSwyllys errout:
37199ebb4caSwyllys 	if (ret != KMF_OK) {
37299ebb4caSwyllys 		Cleanup_KMF_Handle(handle);
37399ebb4caSwyllys 		handle = NULL;
37499ebb4caSwyllys 	}
37599ebb4caSwyllys 
37699ebb4caSwyllys 	*outhandle = (KMF_HANDLE_T)handle;
37799ebb4caSwyllys 	return (ret);
37899ebb4caSwyllys }
37999ebb4caSwyllys 
38099ebb4caSwyllys KMF_RETURN
381*30a5e8faSwyllys kmf_configure_keystore(KMF_HANDLE_T handle,
382*30a5e8faSwyllys 	int	num_args,
383*30a5e8faSwyllys 	KMF_ATTRIBUTE	*attrlist)
38499ebb4caSwyllys {
385*30a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
38699ebb4caSwyllys 	KMF_PLUGIN *plugin;
387*30a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype;
388*30a5e8faSwyllys 	uint32_t len;
389*30a5e8faSwyllys 
390*30a5e8faSwyllys 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
391*30a5e8faSwyllys 		{KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
392*30a5e8faSwyllys 	};
393*30a5e8faSwyllys 
394*30a5e8faSwyllys 	int num_req_attrs = sizeof (required_attrs) /
395*30a5e8faSwyllys 	    sizeof (KMF_ATTRIBUTE_TESTER);
396*30a5e8faSwyllys 
397*30a5e8faSwyllys 	if (handle == NULL)
398*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
39999ebb4caSwyllys 
40099ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
401*30a5e8faSwyllys 
402*30a5e8faSwyllys 	ret = test_attributes(num_req_attrs, required_attrs,
403*30a5e8faSwyllys 	    0, NULL, num_args, attrlist);
404*30a5e8faSwyllys 
40599ebb4caSwyllys 	if (ret != KMF_OK)
40699ebb4caSwyllys 		return (ret);
40799ebb4caSwyllys 
408*30a5e8faSwyllys 	len = sizeof (kstype);
409*30a5e8faSwyllys 	ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, num_args,
410*30a5e8faSwyllys 	    &kstype, &len);
411*30a5e8faSwyllys 	if (ret != KMF_OK)
412*30a5e8faSwyllys 		return (ret);
41399ebb4caSwyllys 
414*30a5e8faSwyllys 	plugin = FindPlugin(handle, kstype);
415*30a5e8faSwyllys 	if (plugin != NULL && plugin->funclist->ConfigureKeystore != NULL) {
416*30a5e8faSwyllys 		return (plugin->funclist->ConfigureKeystore(handle, num_args,
417*30a5e8faSwyllys 		    attrlist));
418*30a5e8faSwyllys 	} else {
41999ebb4caSwyllys 		/* return KMF_OK, if the plugin does not have an entry */
42099ebb4caSwyllys 		return (KMF_OK);
421*30a5e8faSwyllys 	}
42299ebb4caSwyllys }
42399ebb4caSwyllys 
42499ebb4caSwyllys KMF_RETURN
425*30a5e8faSwyllys kmf_finalize(KMF_HANDLE_T handle)
42699ebb4caSwyllys {
42799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
42899ebb4caSwyllys 
42999ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
43099ebb4caSwyllys 	if (ret != KMF_OK)
43199ebb4caSwyllys 		return (ret);
43299ebb4caSwyllys 
43399ebb4caSwyllys 	if (pkcs11_initialized) {
43499ebb4caSwyllys 		Cleanup_PK11_Session(handle);
43599ebb4caSwyllys 	}
43699ebb4caSwyllys 	Cleanup_KMF_Handle(handle);
43799ebb4caSwyllys 
43899ebb4caSwyllys 	return (ret);
43999ebb4caSwyllys }
44099ebb4caSwyllys 
44199ebb4caSwyllys KMF_RETURN
442*30a5e8faSwyllys kmf_get_kmf_error_str(KMF_RETURN errcode, char **errmsg)
44399ebb4caSwyllys {
44499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
44599ebb4caSwyllys 	int i, maxerr;
44699ebb4caSwyllys 
44799ebb4caSwyllys 	if (errmsg == NULL)
44899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
44999ebb4caSwyllys 
45099ebb4caSwyllys 	*errmsg = NULL;
45199ebb4caSwyllys 	maxerr = sizeof (kmf_errcodes) / sizeof (kmf_error_map);
45299ebb4caSwyllys 
453*30a5e8faSwyllys 	for (i = 0; i < maxerr && errcode != kmf_errcodes[i].code; i++)
454*30a5e8faSwyllys 		/* empty body */
455*30a5e8faSwyllys 		;
45699ebb4caSwyllys 
45799ebb4caSwyllys 	if (i == maxerr)
45899ebb4caSwyllys 		return (KMF_ERR_MISSING_ERRCODE);
45999ebb4caSwyllys 	else {
46099ebb4caSwyllys 		*errmsg = strdup(kmf_errcodes[i].message);
46199ebb4caSwyllys 		if ((*errmsg) == NULL)
46299ebb4caSwyllys 			return (KMF_ERR_MEMORY);
46399ebb4caSwyllys 	}
46499ebb4caSwyllys 	return (ret);
46599ebb4caSwyllys }
46699ebb4caSwyllys 
46799ebb4caSwyllys KMF_RETURN
468*30a5e8faSwyllys kmf_get_plugin_error_str(KMF_HANDLE_T handle, char **msgstr)
46999ebb4caSwyllys {
47099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
47199ebb4caSwyllys 	KMF_PLUGIN *plugin;
47299ebb4caSwyllys 
47399ebb4caSwyllys 	if (handle == NULL || msgstr == NULL)
47499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
47599ebb4caSwyllys 
47699ebb4caSwyllys 	*msgstr = NULL;
47799ebb4caSwyllys 
47899ebb4caSwyllys 	if (handle->lasterr.errcode == 0) {
47999ebb4caSwyllys 		return (KMF_ERR_MISSING_ERRCODE);
48099ebb4caSwyllys 	}
48199ebb4caSwyllys 
48299ebb4caSwyllys 	if (handle->lasterr.kstype == -1) { /* System error */
48399ebb4caSwyllys 		char *str = strerror(handle->lasterr.errcode);
48499ebb4caSwyllys 		if (str != NULL) {
48599ebb4caSwyllys 			*msgstr = strdup(str);
48699ebb4caSwyllys 			if ((*msgstr) == NULL)
48799ebb4caSwyllys 				return (KMF_ERR_MEMORY);
48899ebb4caSwyllys 		}
48999ebb4caSwyllys 		return (KMF_OK);
49099ebb4caSwyllys 	}
49199ebb4caSwyllys 
49299ebb4caSwyllys 	plugin = FindPlugin(handle, handle->lasterr.kstype);
49399ebb4caSwyllys 	if (plugin == NULL)
49499ebb4caSwyllys 		return (KMF_ERR_PLUGIN_NOTFOUND);
49599ebb4caSwyllys 
49699ebb4caSwyllys 	if (plugin->funclist->GetErrorString != NULL) {
49799ebb4caSwyllys 		ret = plugin->funclist->GetErrorString(handle, msgstr);
49899ebb4caSwyllys 	} else {
49999ebb4caSwyllys 		return (KMF_ERR_FUNCTION_NOT_FOUND);
50099ebb4caSwyllys 	}
50199ebb4caSwyllys 
50299ebb4caSwyllys 	return (ret);
50399ebb4caSwyllys }
50499ebb4caSwyllys 
50599ebb4caSwyllys 
5069b37d296Swyllys #define	SET_SYS_ERROR(h, c) if (h) {\
5079b37d296Swyllys 	h->lasterr.kstype = -1;\
5089b37d296Swyllys 	h->lasterr.errcode = c;\
5099b37d296Swyllys }
51099ebb4caSwyllys 
51199ebb4caSwyllys KMF_RETURN
512*30a5e8faSwyllys kmf_read_input_file(KMF_HANDLE_T handle, char *filename,  KMF_DATA *pdata)
51399ebb4caSwyllys {
51499ebb4caSwyllys 	struct stat s;
51599ebb4caSwyllys 	long nread, total = 0;
51699ebb4caSwyllys 	int fd;
51799ebb4caSwyllys 	unsigned char *buf = NULL;
51899ebb4caSwyllys 	KMF_RETURN ret;
51999ebb4caSwyllys 
5209b37d296Swyllys 	if (handle) {
5219b37d296Swyllys 		CLEAR_ERROR(handle, ret);
5229b37d296Swyllys 		if (ret != KMF_OK)
5239b37d296Swyllys 			return (ret);
5249b37d296Swyllys 	}
52599ebb4caSwyllys 
52699ebb4caSwyllys 	if (filename == NULL || pdata == NULL) {
52799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
52899ebb4caSwyllys 	}
52999ebb4caSwyllys 
53099ebb4caSwyllys 	if ((fd = open(filename, O_RDONLY)) < 0) {
53199ebb4caSwyllys 		SET_SYS_ERROR(handle, errno);
53299ebb4caSwyllys 		return (KMF_ERR_OPEN_FILE);
53399ebb4caSwyllys 	}
53499ebb4caSwyllys 
53599ebb4caSwyllys 	if (fstat(fd, &s) < 0) {
53699ebb4caSwyllys 		SET_SYS_ERROR(handle, errno);
53799ebb4caSwyllys 		(void) close(fd);
53899ebb4caSwyllys 		return (KMF_ERR_OPEN_FILE);
53999ebb4caSwyllys 	}
54099ebb4caSwyllys 
54199ebb4caSwyllys 	if ((buf = (unsigned char *) malloc(s.st_size)) == NULL) {
54299ebb4caSwyllys 		(void) close(fd);
54399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
54499ebb4caSwyllys 	}
54599ebb4caSwyllys 
54699ebb4caSwyllys 	do {
54799ebb4caSwyllys 		nread = read(fd, buf+total, s.st_size-total);
54899ebb4caSwyllys 		if (nread < 0) {
54999ebb4caSwyllys 			SET_SYS_ERROR(handle, errno);
55099ebb4caSwyllys 			(void) close(fd);
55199ebb4caSwyllys 			free(buf);
55299ebb4caSwyllys 			return (KMF_ERR_INTERNAL);
55399ebb4caSwyllys 		}
55499ebb4caSwyllys 		total += nread;
55599ebb4caSwyllys 	} while (total < s.st_size);
55699ebb4caSwyllys 
55799ebb4caSwyllys 	pdata->Data = buf;
55899ebb4caSwyllys 	pdata->Length = s.st_size;
55999ebb4caSwyllys 	(void) close(fd);
56099ebb4caSwyllys 	return (KMF_OK);
56199ebb4caSwyllys }
56299ebb4caSwyllys 
56399ebb4caSwyllys /*
56499ebb4caSwyllys  *
565*30a5e8faSwyllys  * Name: kmf_der_to_pem
56699ebb4caSwyllys  *
56799ebb4caSwyllys  * Description:
56899ebb4caSwyllys  *   Function for converting DER encoded format to PEM encoded format
56999ebb4caSwyllys  *
57099ebb4caSwyllys  * Parameters:
57199ebb4caSwyllys  *   type(input) - CERTIFICATE or CSR
57299ebb4caSwyllys  *   data(input) - pointer to the DER encoded data
57399ebb4caSwyllys  *   len(input)  - length of input data
57499ebb4caSwyllys  *   out(output) - contains the output buffer address to be returned
57599ebb4caSwyllys  *   outlen(output) - pointer to the returned output length
57699ebb4caSwyllys  *
57799ebb4caSwyllys  * Returns:
57899ebb4caSwyllys  *   A KMF_RETURN value indicating success or specifying a particular
57999ebb4caSwyllys  * error condition.
58099ebb4caSwyllys  *   The value KMF_OK indicates success. All other values represent
58199ebb4caSwyllys  * an error condition.
58299ebb4caSwyllys  *
58399ebb4caSwyllys  */
58499ebb4caSwyllys KMF_RETURN
585*30a5e8faSwyllys kmf_der_to_pem(KMF_OBJECT_TYPE type, unsigned char *data,
58699ebb4caSwyllys 	int len, unsigned char **out, int *outlen)
58799ebb4caSwyllys {
58899ebb4caSwyllys 
58999ebb4caSwyllys 	KMF_RETURN err;
59099ebb4caSwyllys 	if (data == NULL || out == NULL || outlen == NULL)
59199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
59299ebb4caSwyllys 
59399ebb4caSwyllys 	err = Der2Pem(type, data, len, out, outlen);
59499ebb4caSwyllys 	return (err);
59599ebb4caSwyllys 
59699ebb4caSwyllys }
59799ebb4caSwyllys 
59899ebb4caSwyllys /*
59999ebb4caSwyllys  *
600*30a5e8faSwyllys  * Name: kmf_pem_to_der
60199ebb4caSwyllys  *
60299ebb4caSwyllys  * Description:
60399ebb4caSwyllys  *   Function for converting PEM encoded format to DER encoded format
60499ebb4caSwyllys  *
60599ebb4caSwyllys  * Parameters:
60699ebb4caSwyllys  *   in(input) - pointer to the PEM encoded data
60799ebb4caSwyllys  *   inlen(input)  - length of input data
60899ebb4caSwyllys  *   out(output) - contains the output buffer address to be returned
60999ebb4caSwyllys  *   outlen(output) - pointer to the returned output length
61099ebb4caSwyllys  *
61199ebb4caSwyllys  * Returns:
61299ebb4caSwyllys  *   A KMF_RETURN value indicating success or specifying a particular
61399ebb4caSwyllys  *   error condition.
61499ebb4caSwyllys  *   The value KMF_OK indicates success. All other values represent
61599ebb4caSwyllys  *   an error condition.
61699ebb4caSwyllys  *
61799ebb4caSwyllys  */
61899ebb4caSwyllys KMF_RETURN
619*30a5e8faSwyllys kmf_pem_to_der(unsigned char *in, int inlen,
62099ebb4caSwyllys 	unsigned char **out, int *outlen)
62199ebb4caSwyllys {
62299ebb4caSwyllys 	KMF_RETURN err;
62399ebb4caSwyllys 	if (in == NULL || out == NULL || outlen == NULL)
62499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
62599ebb4caSwyllys 
62699ebb4caSwyllys 	err = Pem2Der(in, inlen, out, outlen);
62799ebb4caSwyllys 	return (err);
62899ebb4caSwyllys }
62999ebb4caSwyllys 
63099ebb4caSwyllys char *
631*30a5e8faSwyllys kmf_oid_to_string(KMF_OID *oid)
63299ebb4caSwyllys {
63399ebb4caSwyllys 	char numstr[128];
63499ebb4caSwyllys 	uint32_t number;
63599ebb4caSwyllys 	int numshift;
63699ebb4caSwyllys 	uint32_t i, string_length;
63799ebb4caSwyllys 	uchar_t *cp;
63899ebb4caSwyllys 	char *bp;
63999ebb4caSwyllys 
64099ebb4caSwyllys 	/* First determine the size of the string */
64199ebb4caSwyllys 	string_length = 0;
64299ebb4caSwyllys 	number = 0;
64399ebb4caSwyllys 	numshift = 0;
64499ebb4caSwyllys 	cp = (unsigned char *)oid->Data;
64599ebb4caSwyllys 
64699ebb4caSwyllys 	number = (uint32_t)cp[0];
64799ebb4caSwyllys 	(void) sprintf(numstr, "%d ", number/40);
64899ebb4caSwyllys 
64999ebb4caSwyllys 	string_length += strlen(numstr);
65099ebb4caSwyllys 	(void) sprintf(numstr, "%d ", number%40);
65199ebb4caSwyllys 
65299ebb4caSwyllys 	string_length += strlen(numstr);
65399ebb4caSwyllys 
65499ebb4caSwyllys 	for (i = 1; i < oid->Length; i++) {
65599ebb4caSwyllys 		if ((uint32_t)(numshift+7) < (sizeof (uint32_t)*8)) {
65699ebb4caSwyllys 			number = (number << 7) | (cp[i] & 0x7f);
65799ebb4caSwyllys 			numshift += 7;
65899ebb4caSwyllys 		} else {
65999ebb4caSwyllys 			return (NULL);
66099ebb4caSwyllys 		}
66199ebb4caSwyllys 
66299ebb4caSwyllys 		if ((cp[i] & 0x80) == 0) {
66399ebb4caSwyllys 			(void) sprintf(numstr, "%d ", number);
66499ebb4caSwyllys 			string_length += strlen(numstr);
66599ebb4caSwyllys 			number = 0;
66699ebb4caSwyllys 			numshift = 0;
66799ebb4caSwyllys 		}
66899ebb4caSwyllys 	}
66999ebb4caSwyllys 	/*
67099ebb4caSwyllys 	 * If we get here, we've calculated the length of "n n n ... n ".  Add 4
67199ebb4caSwyllys 	 * here for "{ " and "}\0".
67299ebb4caSwyllys 	 */
67399ebb4caSwyllys 	string_length += 4;
67499ebb4caSwyllys 	if ((bp = (char *)malloc(string_length))) {
67599ebb4caSwyllys 		number = (uint32_t)cp[0];
67699ebb4caSwyllys 
67799ebb4caSwyllys 		(void) sprintf(numstr, "%d.", number/40);
67899ebb4caSwyllys 		(void) strcpy(bp, numstr);
67999ebb4caSwyllys 
68099ebb4caSwyllys 		(void) sprintf(numstr, "%d.", number%40);
68199ebb4caSwyllys 		(void) strcat(bp, numstr);
68299ebb4caSwyllys 
68399ebb4caSwyllys 		number = 0;
68499ebb4caSwyllys 		cp = (unsigned char *) oid->Data;
68599ebb4caSwyllys 		for (i = 1; i < oid->Length; i++) {
68699ebb4caSwyllys 			number = (number << 7) | (cp[i] & 0x7f);
68799ebb4caSwyllys 			if ((cp[i] & 0x80) == 0) {
68899ebb4caSwyllys 				(void) sprintf(numstr, "%d", number);
68999ebb4caSwyllys 				(void) strcat(bp, numstr);
69099ebb4caSwyllys 				number = 0;
69199ebb4caSwyllys 				if (i+1 < oid->Length)
69299ebb4caSwyllys 					(void) strcat(bp, ".");
69399ebb4caSwyllys 			}
69499ebb4caSwyllys 		}
69599ebb4caSwyllys 	}
69699ebb4caSwyllys 	return (bp);
69799ebb4caSwyllys }
69899ebb4caSwyllys 
69902744e81Swyllys static boolean_t
70008ec4bd3Shylee check_for_pem(uchar_t *buf, KMF_ENCODE_FORMAT *fmt)
70102744e81Swyllys {
7029b37d296Swyllys 	char *p;
70302744e81Swyllys 
70408ec4bd3Shylee 	if (buf == NULL)
70502744e81Swyllys 		return (FALSE);
70602744e81Swyllys 
70708ec4bd3Shylee 	if (memcmp(buf, "Bag Attr", 8) == 0) {
70808ec4bd3Shylee 		*fmt = KMF_FORMAT_PEM_KEYPAIR;
70908ec4bd3Shylee 		return (TRUE);
71008ec4bd3Shylee 	}
71108ec4bd3Shylee 
7129b37d296Swyllys 	/* Look for "-----BEGIN" right after a newline */
71308ec4bd3Shylee 	p = strtok((char *)buf, "\n");
7149b37d296Swyllys 	while (p != NULL) {
7159b37d296Swyllys 		if (strstr(p, "-----BEGIN") != NULL) {
71608ec4bd3Shylee 			*fmt = KMF_FORMAT_PEM;
7179b37d296Swyllys 			return (TRUE);
71802744e81Swyllys 		}
7199b37d296Swyllys 		p = strtok(NULL, "\n");
72002744e81Swyllys 	}
72102744e81Swyllys 	return (FALSE);
72202744e81Swyllys }
72302744e81Swyllys 
72408ec4bd3Shylee 
72508ec4bd3Shylee static unsigned char pkcs12_version[3] = {0x02, 0x01, 0x03};
72608ec4bd3Shylee static unsigned char pkcs12_oid[11] =
72708ec4bd3Shylee {0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01};
72808ec4bd3Shylee 
72908ec4bd3Shylee /*
73008ec4bd3Shylee  * This function takes a BER encoded string as input and checks the version
73108ec4bd3Shylee  * and the oid in the the top-level ASN.1 structure to see if it complies to
73208ec4bd3Shylee  * the PKCS#12 Syntax.
73308ec4bd3Shylee  */
73408ec4bd3Shylee static boolean_t
73508ec4bd3Shylee check_for_pkcs12(uchar_t *buf, int buf_len)
73608ec4bd3Shylee {
73708ec4bd3Shylee 	int index = 0;
73808ec4bd3Shylee 	int length_octets;
73908ec4bd3Shylee 
74008ec4bd3Shylee 	if (buf == NULL || buf_len <= 0)
74108ec4bd3Shylee 		return (FALSE);
74208ec4bd3Shylee 
74308ec4bd3Shylee 	/*
74408ec4bd3Shylee 	 * The top level structure for a PKCS12 string:
74508ec4bd3Shylee 	 *
74608ec4bd3Shylee 	 * PFX ::= SEQUENCE {
74708ec4bd3Shylee 	 *	version		INTEGER {v3(3)}(v3,...)
74808ec4bd3Shylee 	 *	authSafe	ContentInfo
74908ec4bd3Shylee 	 *	macData		MacData OPTIONAL
75008ec4bd3Shylee 	 * }
75108ec4bd3Shylee 	 *
75208ec4bd3Shylee 	 * ContentInfo
75308ec4bd3Shylee 	 *	FROM PKCS-7 {iso(1) member-body(2) us(840) rsadsi(113549)
75408ec4bd3Shylee 	 *		pkcs(1) pkcs-7(7) modules(0) pkcs-7(1)}
75508ec4bd3Shylee 	 *
75608ec4bd3Shylee 	 * Therefore, the BER/DER dump of a PKCS#12 file for the first 2
75708ec4bd3Shylee 	 * sequences up to the oid part is as following:
75808ec4bd3Shylee 	 *
75908ec4bd3Shylee 	 *	SEQUENCE {
76008ec4bd3Shylee 	 *	    INTEGER 3
76108ec4bd3Shylee 	 *	    SEQUENCE {
76208ec4bd3Shylee 	 *		OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
76308ec4bd3Shylee 	 */
76408ec4bd3Shylee 
76508ec4bd3Shylee 	/*
76608ec4bd3Shylee 	 * Check the first sequence and calculate the number of bytes used
76708ec4bd3Shylee 	 * to store the length.
76808ec4bd3Shylee 	 */
76908ec4bd3Shylee 	if (buf[index++] != 0x30)
77008ec4bd3Shylee 		return (FALSE);
77108ec4bd3Shylee 
77208ec4bd3Shylee 	if (buf[index] & 0x80) {
77308ec4bd3Shylee 		length_octets = buf[index++] & 0x0F;  /* long form */
77408ec4bd3Shylee 	} else {
77508ec4bd3Shylee 		length_octets = 1; /* short form */
77608ec4bd3Shylee 	}
77708ec4bd3Shylee 
77808ec4bd3Shylee 	index += length_octets;
77908ec4bd3Shylee 	if (index  >= buf_len)
78008ec4bd3Shylee 		return (FALSE);
78108ec4bd3Shylee 
78208ec4bd3Shylee 	/* Skip the length octets and check the pkcs12 version */
78308ec4bd3Shylee 	if (memcmp(buf + index, pkcs12_version, sizeof (pkcs12_version)) != 0)
78408ec4bd3Shylee 		return (FALSE);
78508ec4bd3Shylee 
78608ec4bd3Shylee 	index += sizeof (pkcs12_version);
78708ec4bd3Shylee 	if (index  >= buf_len)
78808ec4bd3Shylee 		return (FALSE);
78908ec4bd3Shylee 
79008ec4bd3Shylee 	/*
79108ec4bd3Shylee 	 * Check the 2nd sequence and calculate the number of bytes used
79208ec4bd3Shylee 	 * to store the length.
79308ec4bd3Shylee 	 */
79408ec4bd3Shylee 	if ((buf[index++] & 0xFF) != 0x30)
79508ec4bd3Shylee 		return (FALSE);
79608ec4bd3Shylee 
79708ec4bd3Shylee 	if (buf[index] & 0x80) {
79808ec4bd3Shylee 		length_octets = buf[index++] & 0x0F;
79908ec4bd3Shylee 	} else {
80008ec4bd3Shylee 		length_octets = 1;
80108ec4bd3Shylee 	}
80208ec4bd3Shylee 
80308ec4bd3Shylee 	index += length_octets;
80408ec4bd3Shylee 	if (index + sizeof (pkcs12_oid) >= buf_len)
80508ec4bd3Shylee 		return (FALSE);
80608ec4bd3Shylee 
80708ec4bd3Shylee 	/* Skip the length octets and check the oid */
80808ec4bd3Shylee 	if (memcmp(buf + index, pkcs12_oid, sizeof (pkcs12_oid)) != 0)
80908ec4bd3Shylee 		return (FALSE);
81008ec4bd3Shylee 	else
81108ec4bd3Shylee 		return (TRUE);
81208ec4bd3Shylee }
81308ec4bd3Shylee 
81499ebb4caSwyllys KMF_RETURN
815*30a5e8faSwyllys kmf_get_file_format(char *filename, KMF_ENCODE_FORMAT *fmt)
81699ebb4caSwyllys {
81799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
81808ec4bd3Shylee 	KMF_DATA filebuf = {NULL, 0};
81908ec4bd3Shylee 	uchar_t *buf;
82099ebb4caSwyllys 
82199ebb4caSwyllys 	if (filename == NULL || !strlen(filename) || fmt == NULL)
82299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
82399ebb4caSwyllys 
82499ebb4caSwyllys 	*fmt = 0;
825*30a5e8faSwyllys 	ret = kmf_read_input_file(NULL, filename, &filebuf);
82608ec4bd3Shylee 	if (ret != KMF_OK)
82708ec4bd3Shylee 		return (ret);
82899ebb4caSwyllys 
82908ec4bd3Shylee 	if (filebuf.Length < 8) {
83008ec4bd3Shylee 		ret = KMF_ERR_ENCODING; /* too small */
83199ebb4caSwyllys 		goto end;
83299ebb4caSwyllys 	}
83399ebb4caSwyllys 
83408ec4bd3Shylee 	buf = filebuf.Data;
83508ec4bd3Shylee 	if (check_for_pkcs12(buf, filebuf.Length) == TRUE) {
83608ec4bd3Shylee 		*fmt = KMF_FORMAT_PKCS12;
83708ec4bd3Shylee 	} else if (buf[0] == 0x30 && (buf[1] & 0x80)) {
83899ebb4caSwyllys 		/* It is most likely a generic ASN.1 encoded file */
83908ec4bd3Shylee 		*fmt = KMF_FORMAT_ASN1;
84008ec4bd3Shylee 	} else if (check_for_pem(buf, fmt) == TRUE) {
84108ec4bd3Shylee 		goto end;
84299ebb4caSwyllys 	} else {
84308ec4bd3Shylee 		/* Cannot determine this file format */
84408ec4bd3Shylee 		*fmt = 0;
84508ec4bd3Shylee 		ret = KMF_ERR_ENCODING;
84699ebb4caSwyllys 	}
84708ec4bd3Shylee 
84899ebb4caSwyllys end:
849*30a5e8faSwyllys 	kmf_free_data(&filebuf);
85099ebb4caSwyllys 	return (ret);
85199ebb4caSwyllys }
85299ebb4caSwyllys 
85399ebb4caSwyllys KMF_RETURN
854*30a5e8faSwyllys kmf_hexstr_to_bytes(unsigned char *hexstr, unsigned char **bytes,
85599ebb4caSwyllys 	size_t *outlen)
85699ebb4caSwyllys {
85799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
85899ebb4caSwyllys 	unsigned char *buf = NULL;
85999ebb4caSwyllys 	int len, stringlen;
86099ebb4caSwyllys 	int i;
86199ebb4caSwyllys 	unsigned char ch;
86299ebb4caSwyllys 
86399ebb4caSwyllys 	if (hexstr == NULL) {
86499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
86599ebb4caSwyllys 	}
86699ebb4caSwyllys 
867*30a5e8faSwyllys 	if (hexstr[0] == '0' && ((hexstr[1] == 'x') || (hexstr[1] == 'X')))
86899ebb4caSwyllys 		hexstr += 2;
86999ebb4caSwyllys 
870*30a5e8faSwyllys 	for (i = 0; i < strlen((char *)hexstr) && isxdigit(hexstr[i]); i++)
871*30a5e8faSwyllys 		/* empty body */
872*30a5e8faSwyllys 		;
87399ebb4caSwyllys 	/*
87499ebb4caSwyllys 	 * If all the characters are not legitimate hex chars,
87599ebb4caSwyllys 	 * return an error.
87699ebb4caSwyllys 	 */
87799ebb4caSwyllys 	if (i != strlen((char *)hexstr))
87899ebb4caSwyllys 		return (KMF_ERR_BAD_HEX_STRING);
87999ebb4caSwyllys 	stringlen = i;
88099ebb4caSwyllys 	len = (i / 2) + (i % 2);
88199ebb4caSwyllys 
88299ebb4caSwyllys 	buf = malloc(len);
88399ebb4caSwyllys 	if (buf == NULL) {
88499ebb4caSwyllys 		return (KMF_ERR_MEMORY);
88599ebb4caSwyllys 	}
88699ebb4caSwyllys 	(void) memset(buf, 0, len);
88799ebb4caSwyllys 
88899ebb4caSwyllys 	for (i = 0; i < stringlen; i++) {
88999ebb4caSwyllys 		ch = (unsigned char) *hexstr;
89099ebb4caSwyllys 		hexstr++;
89199ebb4caSwyllys 		if ((ch >= '0') && (ch <= '9'))
89299ebb4caSwyllys 			ch -= '0';
89399ebb4caSwyllys 		else if ((ch >= 'A') && (ch <= 'F'))
89499ebb4caSwyllys 			ch = ch - 'A' + 10;
89599ebb4caSwyllys 		else if ((ch >= 'a') && (ch <= 'f'))
89699ebb4caSwyllys 			ch = ch - 'a' + 10;
89799ebb4caSwyllys 		else {
89899ebb4caSwyllys 			ret = KMF_ERR_BAD_HEX_STRING;
89999ebb4caSwyllys 			goto out;
90099ebb4caSwyllys 		}
90199ebb4caSwyllys 
90299ebb4caSwyllys 		if (i & 1) {
90399ebb4caSwyllys 			buf[i/2] |= ch;
90499ebb4caSwyllys 		} else {
90599ebb4caSwyllys 			buf[i/2] = (ch << 4);
90699ebb4caSwyllys 		}
90799ebb4caSwyllys 	}
90899ebb4caSwyllys 
90999ebb4caSwyllys 	*bytes = buf;
91099ebb4caSwyllys 	*outlen = len;
91199ebb4caSwyllys out:
91299ebb4caSwyllys 	if (buf != NULL && ret != KMF_OK) {
91399ebb4caSwyllys 		free(buf);
91499ebb4caSwyllys 	}
91599ebb4caSwyllys 	return (ret);
91699ebb4caSwyllys }
91799ebb4caSwyllys 
91899ebb4caSwyllys void
919*30a5e8faSwyllys kmf_free_dn(KMF_X509_NAME *name)
92099ebb4caSwyllys {
92199ebb4caSwyllys 	KMF_X509_RDN 		*newrdn = NULL;
92299ebb4caSwyllys 	KMF_X509_TYPE_VALUE_PAIR *av = NULL;
92399ebb4caSwyllys 	int i, j;
92499ebb4caSwyllys 
92599ebb4caSwyllys 	if (name && name->numberOfRDNs) {
92699ebb4caSwyllys 		for (i = 0; i < name->numberOfRDNs; i++) {
92799ebb4caSwyllys 			newrdn = &name->RelativeDistinguishedName[i];
92899ebb4caSwyllys 			for (j = 0; j < newrdn->numberOfPairs; j++) {
92999ebb4caSwyllys 				av = &newrdn->AttributeTypeAndValue[j];
930*30a5e8faSwyllys 				kmf_free_data(&av->type);
931*30a5e8faSwyllys 				kmf_free_data(&av->value);
93299ebb4caSwyllys 			}
93399ebb4caSwyllys 			free(newrdn->AttributeTypeAndValue);
93499ebb4caSwyllys 			newrdn->numberOfPairs = 0;
93599ebb4caSwyllys 			newrdn->AttributeTypeAndValue = NULL;
93699ebb4caSwyllys 		}
93799ebb4caSwyllys 		free(name->RelativeDistinguishedName);
93899ebb4caSwyllys 		name->numberOfRDNs = 0;
93999ebb4caSwyllys 		name->RelativeDistinguishedName = NULL;
94099ebb4caSwyllys 	}
94199ebb4caSwyllys }
94299ebb4caSwyllys 
94399ebb4caSwyllys void
944*30a5e8faSwyllys kmf_free_kmf_cert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
94599ebb4caSwyllys {
94699ebb4caSwyllys 	KMF_PLUGIN *plugin;
94799ebb4caSwyllys 	KMF_RETURN ret;
94899ebb4caSwyllys 
94999ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
95099ebb4caSwyllys 	if (ret != KMF_OK)
95199ebb4caSwyllys 		return;
95299ebb4caSwyllys 
95399ebb4caSwyllys 	if (kmf_cert == NULL)
95499ebb4caSwyllys 		return;
95599ebb4caSwyllys 
95699ebb4caSwyllys 	plugin = FindPlugin(handle, kmf_cert->kmf_private.keystore_type);
95799ebb4caSwyllys 
95899ebb4caSwyllys 	if (plugin != NULL && plugin->funclist->FreeKMFCert != NULL) {
95999ebb4caSwyllys 		plugin->funclist->FreeKMFCert(handle, kmf_cert);
96099ebb4caSwyllys 	}
96199ebb4caSwyllys }
96299ebb4caSwyllys 
96399ebb4caSwyllys void
964*30a5e8faSwyllys kmf_free_data(KMF_DATA *datablock)
96599ebb4caSwyllys {
96699ebb4caSwyllys 	if (datablock != NULL && datablock->Data != NULL) {
96799ebb4caSwyllys 		free(datablock->Data);
96899ebb4caSwyllys 		datablock->Data = NULL;
96999ebb4caSwyllys 		datablock->Length = 0;
97099ebb4caSwyllys 	}
97199ebb4caSwyllys }
97299ebb4caSwyllys 
97399ebb4caSwyllys void
974*30a5e8faSwyllys kmf_free_algoid(KMF_X509_ALGORITHM_IDENTIFIER *algoid)
97599ebb4caSwyllys {
97699ebb4caSwyllys 	if (algoid == NULL)
97799ebb4caSwyllys 		return;
978*30a5e8faSwyllys 	kmf_free_data(&algoid->algorithm);
979*30a5e8faSwyllys 	kmf_free_data(&algoid->parameters);
98099ebb4caSwyllys }
98199ebb4caSwyllys 
98299ebb4caSwyllys void
983*30a5e8faSwyllys kmf_free_extn(KMF_X509_EXTENSION *exptr)
98499ebb4caSwyllys {
98599ebb4caSwyllys 	if (exptr == NULL)
98699ebb4caSwyllys 		return;
98799ebb4caSwyllys 
988*30a5e8faSwyllys 	kmf_free_data((KMF_DATA *)&exptr->extnId);
989*30a5e8faSwyllys 	kmf_free_data(&exptr->BERvalue);
99099ebb4caSwyllys 
99199ebb4caSwyllys 	if (exptr->value.tagAndValue) {
992*30a5e8faSwyllys 		kmf_free_data(&exptr->value.tagAndValue->value);
99399ebb4caSwyllys 		free(exptr->value.tagAndValue);
99499ebb4caSwyllys 	}
99599ebb4caSwyllys }
99699ebb4caSwyllys 
99799ebb4caSwyllys void
998*30a5e8faSwyllys kmf_free_tbs_csr(KMF_TBS_CSR *tbscsr)
99999ebb4caSwyllys {
100099ebb4caSwyllys 	if (tbscsr) {
1001*30a5e8faSwyllys 		kmf_free_data(&tbscsr->version);
100299ebb4caSwyllys 
1003*30a5e8faSwyllys 		kmf_free_dn(&tbscsr->subject);
100499ebb4caSwyllys 
1005*30a5e8faSwyllys 		kmf_free_algoid(&tbscsr->subjectPublicKeyInfo.algorithm);
1006*30a5e8faSwyllys 		kmf_free_data(&tbscsr->subjectPublicKeyInfo.subjectPublicKey);
100799ebb4caSwyllys 
100899ebb4caSwyllys 		free_extensions(&tbscsr->extensions);
100999ebb4caSwyllys 	}
101099ebb4caSwyllys }
101199ebb4caSwyllys 
101299ebb4caSwyllys void
1013*30a5e8faSwyllys kmf_free_signed_csr(KMF_CSR_DATA *csr)
101499ebb4caSwyllys {
101599ebb4caSwyllys 	if (csr) {
1016*30a5e8faSwyllys 		kmf_free_tbs_csr(&csr->csr);
101799ebb4caSwyllys 
1018*30a5e8faSwyllys 		kmf_free_algoid(&csr->signature.algorithmIdentifier);
1019*30a5e8faSwyllys 		kmf_free_data(&csr->signature.encrypted);
102099ebb4caSwyllys 	}
102199ebb4caSwyllys }
102299ebb4caSwyllys 
102399ebb4caSwyllys static void
102499ebb4caSwyllys free_validity(KMF_X509_VALIDITY *validity)
102599ebb4caSwyllys {
102699ebb4caSwyllys 	if (validity == NULL)
102799ebb4caSwyllys 		return;
1028*30a5e8faSwyllys 	kmf_free_data(&validity->notBefore.time);
1029*30a5e8faSwyllys 	kmf_free_data(&validity->notAfter.time);
103099ebb4caSwyllys }
103199ebb4caSwyllys 
103299ebb4caSwyllys static void
103399ebb4caSwyllys free_extensions(KMF_X509_EXTENSIONS *extns)
103499ebb4caSwyllys {
103599ebb4caSwyllys 	int i;
103699ebb4caSwyllys 	KMF_X509_EXTENSION *exptr;
103799ebb4caSwyllys 
103899ebb4caSwyllys 	if (extns && extns->numberOfExtensions > 0) {
103999ebb4caSwyllys 		for (i = 0; i < extns->numberOfExtensions; i++) {
104099ebb4caSwyllys 			exptr = &extns->extensions[i];
1041*30a5e8faSwyllys 			kmf_free_extn(exptr);
104299ebb4caSwyllys 		}
104399ebb4caSwyllys 		free(extns->extensions);
104499ebb4caSwyllys 		extns->numberOfExtensions = 0;
104599ebb4caSwyllys 		extns->extensions = NULL;
104699ebb4caSwyllys 	}
104799ebb4caSwyllys }
104899ebb4caSwyllys 
104999ebb4caSwyllys void
1050*30a5e8faSwyllys kmf_free_tbs_cert(KMF_X509_TBS_CERT *tbscert)
105199ebb4caSwyllys {
105299ebb4caSwyllys 	if (tbscert) {
1053*30a5e8faSwyllys 		kmf_free_data(&tbscert->version);
1054*30a5e8faSwyllys 		kmf_free_bigint(&tbscert->serialNumber);
1055*30a5e8faSwyllys 		kmf_free_algoid(&tbscert->signature);
105699ebb4caSwyllys 
1057*30a5e8faSwyllys 		kmf_free_dn(&tbscert->issuer);
1058*30a5e8faSwyllys 		kmf_free_dn(&tbscert->subject);
105999ebb4caSwyllys 
106099ebb4caSwyllys 		free_validity(&tbscert->validity);
106199ebb4caSwyllys 
1062*30a5e8faSwyllys 		kmf_free_data(&tbscert->issuerUniqueIdentifier);
1063*30a5e8faSwyllys 		kmf_free_data(&tbscert->subjectUniqueIdentifier);
106499ebb4caSwyllys 
1065*30a5e8faSwyllys 		kmf_free_algoid(&tbscert->subjectPublicKeyInfo.algorithm);
1066*30a5e8faSwyllys 		kmf_free_data(&tbscert->subjectPublicKeyInfo.subjectPublicKey);
106799ebb4caSwyllys 
106899ebb4caSwyllys 		free_extensions(&tbscert->extensions);
106999ebb4caSwyllys 
1070*30a5e8faSwyllys 		kmf_free_data(&tbscert->issuerUniqueIdentifier);
1071*30a5e8faSwyllys 		kmf_free_data(&tbscert->subjectUniqueIdentifier);
107299ebb4caSwyllys 	}
107399ebb4caSwyllys }
107499ebb4caSwyllys 
107599ebb4caSwyllys void
1076*30a5e8faSwyllys kmf_free_signed_cert(KMF_X509_CERTIFICATE *certptr)
107799ebb4caSwyllys {
107899ebb4caSwyllys 	if (!certptr)
107999ebb4caSwyllys 		return;
108099ebb4caSwyllys 
1081*30a5e8faSwyllys 	kmf_free_tbs_cert(&certptr->certificate);
108299ebb4caSwyllys 
1083*30a5e8faSwyllys 	kmf_free_algoid(&certptr->signature.algorithmIdentifier);
1084*30a5e8faSwyllys 	kmf_free_data(&certptr->signature.encrypted);
108599ebb4caSwyllys }
108699ebb4caSwyllys 
108799ebb4caSwyllys void
1088*30a5e8faSwyllys kmf_free_str(char *pstr)
108999ebb4caSwyllys {
109099ebb4caSwyllys 	if (pstr != NULL)
109199ebb4caSwyllys 		free(pstr);
109299ebb4caSwyllys }
109399ebb4caSwyllys 
109499ebb4caSwyllys void
109599ebb4caSwyllys free_keyidlist(KMF_OID *oidlist, int len)
109699ebb4caSwyllys {
109799ebb4caSwyllys 	int i;
109899ebb4caSwyllys 	for (i = 0; i < len; i++) {
1099*30a5e8faSwyllys 		kmf_free_data((KMF_DATA *)&oidlist[i]);
110099ebb4caSwyllys 	}
110199ebb4caSwyllys 	free(oidlist);
110299ebb4caSwyllys }
110399ebb4caSwyllys 
110499ebb4caSwyllys void
1105*30a5e8faSwyllys kmf_free_eku(KMF_X509EXT_EKU *eptr)
110699ebb4caSwyllys {
1107*30a5e8faSwyllys 	if (eptr && eptr->nEKUs > 0 && eptr->keyPurposeIdList != NULL)
110899ebb4caSwyllys 		free_keyidlist(eptr->keyPurposeIdList, eptr->nEKUs);
110999ebb4caSwyllys }
111099ebb4caSwyllys 
111199ebb4caSwyllys void
1112*30a5e8faSwyllys kmf_free_spki(KMF_X509_SPKI *spki)
111399ebb4caSwyllys {
111499ebb4caSwyllys 	if (spki != NULL) {
1115*30a5e8faSwyllys 		kmf_free_algoid(&spki->algorithm);
1116*30a5e8faSwyllys 		kmf_free_data(&spki->subjectPublicKey);
111799ebb4caSwyllys 	}
111899ebb4caSwyllys }
111999ebb4caSwyllys 
112099ebb4caSwyllys void
1121*30a5e8faSwyllys kmf_free_kmf_key(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key)
112299ebb4caSwyllys {
112399ebb4caSwyllys 	KMF_PLUGIN *plugin;
112499ebb4caSwyllys 	KMF_RETURN ret;
1125*30a5e8faSwyllys 	KMF_ATTRIBUTE attlist[2]; /* only 2 attributes for DeleteKey op */
1126*30a5e8faSwyllys 	int i = 0;
1127*30a5e8faSwyllys 	boolean_t token_destroy = B_FALSE;
1128*30a5e8faSwyllys 
1129*30a5e8faSwyllys 	if (key == NULL)
1130*30a5e8faSwyllys 		return;
113199ebb4caSwyllys 
113299ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
113399ebb4caSwyllys 	if (ret != KMF_OK)
113499ebb4caSwyllys 		return;
113599ebb4caSwyllys 
1136*30a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
1137*30a5e8faSwyllys 	    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
1138*30a5e8faSwyllys 	i++;
1139*30a5e8faSwyllys 
1140*30a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
1141*30a5e8faSwyllys 	    KMF_DESTROY_BOOL_ATTR, &token_destroy, sizeof (boolean_t));
1142*30a5e8faSwyllys 	i++;
114399ebb4caSwyllys 
114499ebb4caSwyllys 	plugin = FindPlugin(handle, key->kstype);
114599ebb4caSwyllys 	if (plugin != NULL && plugin->funclist->DeleteKey != NULL) {
1146*30a5e8faSwyllys 		(void) plugin->funclist->DeleteKey(handle, i, attlist);
114799ebb4caSwyllys 	}
114899ebb4caSwyllys 
114999ebb4caSwyllys 	if (key->keylabel)
115099ebb4caSwyllys 		free(key->keylabel);
115199ebb4caSwyllys 
115299ebb4caSwyllys 	if (key->israw) {
1153*30a5e8faSwyllys 		kmf_free_raw_key(key->keyp);
115499ebb4caSwyllys 		free(key->keyp);
115599ebb4caSwyllys 	}
115699ebb4caSwyllys 
115799ebb4caSwyllys 	(void) memset(key, 0, sizeof (KMF_KEY_HANDLE));
115899ebb4caSwyllys }
115999ebb4caSwyllys 
116099ebb4caSwyllys void
1161*30a5e8faSwyllys kmf_free_bigint(KMF_BIGINT *big)
116299ebb4caSwyllys {
116399ebb4caSwyllys 	if (big != NULL && big->val != NULL) {
116402744e81Swyllys 		/* Clear it out before returning it to the pool */
116502744e81Swyllys 		(void) memset(big->val, 0x00, big->len);
116699ebb4caSwyllys 		free(big->val);
116799ebb4caSwyllys 		big->val = NULL;
116899ebb4caSwyllys 		big->len = 0;
116999ebb4caSwyllys 	}
117099ebb4caSwyllys }
117199ebb4caSwyllys 
117299ebb4caSwyllys static void
117399ebb4caSwyllys free_raw_rsa(KMF_RAW_RSA_KEY *key)
117499ebb4caSwyllys {
117599ebb4caSwyllys 	if (key == NULL)
117699ebb4caSwyllys 		return;
1177*30a5e8faSwyllys 	kmf_free_bigint(&key->mod);
1178*30a5e8faSwyllys 	kmf_free_bigint(&key->pubexp);
1179*30a5e8faSwyllys 	kmf_free_bigint(&key->priexp);
1180*30a5e8faSwyllys 	kmf_free_bigint(&key->prime1);
1181*30a5e8faSwyllys 	kmf_free_bigint(&key->prime2);
1182*30a5e8faSwyllys 	kmf_free_bigint(&key->exp1);
1183*30a5e8faSwyllys 	kmf_free_bigint(&key->exp2);
1184*30a5e8faSwyllys 	kmf_free_bigint(&key->coef);
118599ebb4caSwyllys }
118699ebb4caSwyllys 
118799ebb4caSwyllys static void
118899ebb4caSwyllys free_raw_dsa(KMF_RAW_DSA_KEY *key)
118999ebb4caSwyllys {
119099ebb4caSwyllys 	if (key == NULL)
119199ebb4caSwyllys 		return;
1192*30a5e8faSwyllys 	kmf_free_bigint(&key->prime);
1193*30a5e8faSwyllys 	kmf_free_bigint(&key->subprime);
1194*30a5e8faSwyllys 	kmf_free_bigint(&key->base);
1195*30a5e8faSwyllys 	kmf_free_bigint(&key->value);
119699ebb4caSwyllys }
119799ebb4caSwyllys 
119899ebb4caSwyllys static void
119999ebb4caSwyllys free_raw_sym(KMF_RAW_SYM_KEY *key)
120099ebb4caSwyllys {
120199ebb4caSwyllys 	if (key == NULL)
120299ebb4caSwyllys 		return;
1203*30a5e8faSwyllys 	kmf_free_bigint(&key->keydata);
120499ebb4caSwyllys }
120599ebb4caSwyllys 
120699ebb4caSwyllys void
1207*30a5e8faSwyllys kmf_free_raw_key(KMF_RAW_KEY_DATA *key)
120899ebb4caSwyllys {
120999ebb4caSwyllys 	if (key == NULL)
121099ebb4caSwyllys 		return;
121199ebb4caSwyllys 
121299ebb4caSwyllys 	switch (key->keytype) {
121399ebb4caSwyllys 	case KMF_RSA:
121499ebb4caSwyllys 		free_raw_rsa(&key->rawdata.rsa);
121599ebb4caSwyllys 		break;
121699ebb4caSwyllys 	case KMF_DSA:
121799ebb4caSwyllys 		free_raw_dsa(&key->rawdata.dsa);
121899ebb4caSwyllys 		break;
121999ebb4caSwyllys 	case KMF_AES:
122099ebb4caSwyllys 	case KMF_RC4:
122199ebb4caSwyllys 	case KMF_DES:
122299ebb4caSwyllys 	case KMF_DES3:
122399ebb4caSwyllys 		free_raw_sym(&key->rawdata.sym);
122499ebb4caSwyllys 		break;
122599ebb4caSwyllys 	}
122699ebb4caSwyllys }
122799ebb4caSwyllys 
122899ebb4caSwyllys void
1229*30a5e8faSwyllys kmf_free_raw_sym_key(KMF_RAW_SYM_KEY *key)
123099ebb4caSwyllys {
123199ebb4caSwyllys 	if (key == NULL)
123299ebb4caSwyllys 		return;
1233*30a5e8faSwyllys 	kmf_free_bigint(&key->keydata);
123499ebb4caSwyllys 	free(key);
123599ebb4caSwyllys }
123699ebb4caSwyllys 
123799ebb4caSwyllys /*
123899ebb4caSwyllys  * This function frees the space allocated for the name portion of a
123999ebb4caSwyllys  * KMF_CRL_DIST_POINT.
124099ebb4caSwyllys  */
124199ebb4caSwyllys void
124299ebb4caSwyllys free_dp_name(KMF_CRL_DIST_POINT *dp)
124399ebb4caSwyllys {
124499ebb4caSwyllys 	KMF_GENERALNAMES *fullname;
124599ebb4caSwyllys 	KMF_DATA *urldata;
124699ebb4caSwyllys 	int i;
124799ebb4caSwyllys 
124899ebb4caSwyllys 	if (dp == NULL)
124999ebb4caSwyllys 		return;
125099ebb4caSwyllys 
125199ebb4caSwyllys 	/* For phase 1, we only need to free the fullname space. */
125299ebb4caSwyllys 	fullname = &(dp->name.full_name);
125399ebb4caSwyllys 	if (fullname->number == 0)
125499ebb4caSwyllys 		return;
125599ebb4caSwyllys 
125699ebb4caSwyllys 	for (i = 0; i < fullname->number; i++) {
125799ebb4caSwyllys 		urldata = &(fullname->namelist[fullname->number - 1].name);
1258*30a5e8faSwyllys 		kmf_free_data(urldata);
125999ebb4caSwyllys 	}
126099ebb4caSwyllys 
126199ebb4caSwyllys 	free(fullname->namelist);
126299ebb4caSwyllys }
126399ebb4caSwyllys 
126499ebb4caSwyllys /*
126599ebb4caSwyllys  * This function frees the space allocated for a KMF_CRL_DIST_POINT.
126699ebb4caSwyllys  */
126799ebb4caSwyllys void
126899ebb4caSwyllys free_dp(KMF_CRL_DIST_POINT *dp)
126999ebb4caSwyllys {
127099ebb4caSwyllys 	if (dp == NULL)
127199ebb4caSwyllys 		return;
127299ebb4caSwyllys 
127399ebb4caSwyllys 	free_dp_name(dp);
1274*30a5e8faSwyllys 	kmf_free_data(&(dp->reasons));
127599ebb4caSwyllys 	/* Need not to free crl_issuer space at phase 1 */
127699ebb4caSwyllys }
127799ebb4caSwyllys 
127899ebb4caSwyllys /*
127999ebb4caSwyllys  * This function frees space for a KMF_X509EXT_CRLDISTPOINTS internally.
128099ebb4caSwyllys  */
128199ebb4caSwyllys void
1282*30a5e8faSwyllys kmf_free_crl_dist_pts(KMF_X509EXT_CRLDISTPOINTS *crl_dps)
128399ebb4caSwyllys {
128499ebb4caSwyllys 	int i;
128599ebb4caSwyllys 
128699ebb4caSwyllys 	if (crl_dps == NULL)
128799ebb4caSwyllys 		return;
128899ebb4caSwyllys 
128999ebb4caSwyllys 	for (i = 0; i < crl_dps->number; i++)
129099ebb4caSwyllys 		free_dp(&(crl_dps->dplist[i]));
129199ebb4caSwyllys 
129299ebb4caSwyllys 	free(crl_dps->dplist);
129399ebb4caSwyllys }
129499ebb4caSwyllys 
129599ebb4caSwyllys KMF_RETURN
1296*30a5e8faSwyllys kmf_create_ocsp_request(KMF_HANDLE_T handle,
1297*30a5e8faSwyllys 	int	num_args,
1298*30a5e8faSwyllys 	KMF_ATTRIBUTE	*attrlist)
129999ebb4caSwyllys {
1300*30a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
130199ebb4caSwyllys 	KMF_PLUGIN *plugin;
1302*30a5e8faSwyllys 	KMF_RETURN (*createReqFn)(void *, int num_args,
1303*30a5e8faSwyllys 	    KMF_ATTRIBUTE *attrlist);
130499ebb4caSwyllys 
1305*30a5e8faSwyllys 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
1306*30a5e8faSwyllys 		{KMF_OCSP_REQUEST_FILENAME_ATTR, FALSE, 1, 0},
1307*30a5e8faSwyllys 		{KMF_USER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1308*30a5e8faSwyllys 			sizeof (KMF_DATA)},
1309*30a5e8faSwyllys 		{KMF_ISSUER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1310*30a5e8faSwyllys 			sizeof (KMF_DATA)},
1311*30a5e8faSwyllys 	};
131299ebb4caSwyllys 
1313*30a5e8faSwyllys 	int num_req_attrs = sizeof (required_attrs) /
1314*30a5e8faSwyllys 	    sizeof (KMF_ATTRIBUTE_TESTER);
131599ebb4caSwyllys 
1316*30a5e8faSwyllys 	if (handle == NULL)
131799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
131899ebb4caSwyllys 
1319*30a5e8faSwyllys 	CLEAR_ERROR(handle, ret);
1320*30a5e8faSwyllys 
1321*30a5e8faSwyllys 	ret = test_attributes(num_req_attrs, required_attrs,
1322*30a5e8faSwyllys 	    0, NULL, num_args, attrlist);
1323*30a5e8faSwyllys 
1324*30a5e8faSwyllys 	if (ret != KMF_OK)
1325*30a5e8faSwyllys 		return (ret);
1326*30a5e8faSwyllys 
132799ebb4caSwyllys 	/*
132899ebb4caSwyllys 	 * This framework function is actually implemented in the openssl
132999ebb4caSwyllys 	 * plugin library, so we find the function address and call it.
133099ebb4caSwyllys 	 */
133199ebb4caSwyllys 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
133299ebb4caSwyllys 	if (plugin == NULL || plugin->dldesc == NULL) {
133399ebb4caSwyllys 		return (KMF_ERR_PLUGIN_NOTFOUND);
133499ebb4caSwyllys 	}
133599ebb4caSwyllys 
133699ebb4caSwyllys 	createReqFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
133799ebb4caSwyllys 	    "OpenSSL_CreateOCSPRequest");
133899ebb4caSwyllys 	if (createReqFn == NULL) {
133999ebb4caSwyllys 		return (KMF_ERR_FUNCTION_NOT_FOUND);
134099ebb4caSwyllys 	}
134199ebb4caSwyllys 
1342*30a5e8faSwyllys 	return (createReqFn(handle, num_args, attrlist));
1343*30a5e8faSwyllys 
134499ebb4caSwyllys }
134599ebb4caSwyllys 
134699ebb4caSwyllys KMF_RETURN
1347*30a5e8faSwyllys kmf_get_ocsp_status_for_cert(KMF_HANDLE_T handle,
1348*30a5e8faSwyllys 	int	num_args,
1349*30a5e8faSwyllys 	KMF_ATTRIBUTE	*attrlist)
135099ebb4caSwyllys {
1351*30a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
135299ebb4caSwyllys 	KMF_PLUGIN *plugin;
1353*30a5e8faSwyllys 	KMF_RETURN (*getCertStatusFn)(void *, int num_args,
1354*30a5e8faSwyllys 	    KMF_ATTRIBUTE *attrlist);
1355*30a5e8faSwyllys 
1356*30a5e8faSwyllys 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
1357*30a5e8faSwyllys 		{KMF_USER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1358*30a5e8faSwyllys 			sizeof (KMF_DATA)},
1359*30a5e8faSwyllys 		{KMF_ISSUER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1360*30a5e8faSwyllys 			sizeof (KMF_DATA)},
1361*30a5e8faSwyllys 		{KMF_OCSP_RESPONSE_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1362*30a5e8faSwyllys 			sizeof (KMF_DATA)},
1363*30a5e8faSwyllys 		{KMF_OCSP_RESPONSE_STATUS_ATTR, FALSE, sizeof (int),
1364*30a5e8faSwyllys 			sizeof (uint32_t)},
1365*30a5e8faSwyllys 		{KMF_OCSP_RESPONSE_REASON_ATTR, FALSE, sizeof (int),
1366*30a5e8faSwyllys 			sizeof (uint32_t)},
1367*30a5e8faSwyllys 		{KMF_OCSP_RESPONSE_CERT_STATUS_ATTR, FALSE, sizeof (int),
1368*30a5e8faSwyllys 			sizeof (uint32_t)},
1369*30a5e8faSwyllys 	};
1370*30a5e8faSwyllys 
1371*30a5e8faSwyllys 	int num_req_attrs = sizeof (required_attrs) /
1372*30a5e8faSwyllys 	    sizeof (KMF_ATTRIBUTE_TESTER);
1373*30a5e8faSwyllys 
1374*30a5e8faSwyllys 	if (handle == NULL)
1375*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
137699ebb4caSwyllys 
137799ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
137899ebb4caSwyllys 
1379*30a5e8faSwyllys 	ret = test_attributes(num_req_attrs, required_attrs,
1380*30a5e8faSwyllys 	    0, NULL, num_args, attrlist);
138199ebb4caSwyllys 
1382*30a5e8faSwyllys 	if (ret != KMF_OK)
1383*30a5e8faSwyllys 		return (ret);
138499ebb4caSwyllys 
138599ebb4caSwyllys 	/*
138699ebb4caSwyllys 	 * This framework function is actually implemented in the openssl
138799ebb4caSwyllys 	 * plugin library, so we find the function address and call it.
138899ebb4caSwyllys 	 */
138999ebb4caSwyllys 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
139099ebb4caSwyllys 	if (plugin == NULL || plugin->dldesc == NULL) {
139199ebb4caSwyllys 		return (KMF_ERR_INTERNAL);
139299ebb4caSwyllys 	}
139399ebb4caSwyllys 
139499ebb4caSwyllys 	getCertStatusFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
139599ebb4caSwyllys 	    "OpenSSL_GetOCSPStatusForCert");
139699ebb4caSwyllys 	if (getCertStatusFn == NULL) {
139799ebb4caSwyllys 		return (KMF_ERR_INTERNAL);
139899ebb4caSwyllys 	}
139999ebb4caSwyllys 
1400*30a5e8faSwyllys 	return (getCertStatusFn(handle, num_args, attrlist));
1401*30a5e8faSwyllys 
140299ebb4caSwyllys }
140399ebb4caSwyllys 
140499ebb4caSwyllys KMF_RETURN
1405*30a5e8faSwyllys kmf_string_to_oid(char *oidstring, KMF_OID *oid)
140699ebb4caSwyllys {
140799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
140899ebb4caSwyllys 	char *cp, *bp, *startp;
140999ebb4caSwyllys 	int numbuf;
141099ebb4caSwyllys 	int onumbuf;
141199ebb4caSwyllys 	int nbytes, index;
141299ebb4caSwyllys 	int len;
141399ebb4caSwyllys 	unsigned char *op;
141499ebb4caSwyllys 
141599ebb4caSwyllys 	if (oidstring == NULL || oid == NULL)
141699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
141799ebb4caSwyllys 
141899ebb4caSwyllys 	len = strlen(oidstring);
141999ebb4caSwyllys 
142099ebb4caSwyllys 	bp = oidstring;
142199ebb4caSwyllys 	cp = bp;
142299ebb4caSwyllys 	/* Skip over leading space */
142399ebb4caSwyllys 	while ((bp < &cp[len]) && isspace(*bp))
142499ebb4caSwyllys 		bp++;
142599ebb4caSwyllys 
142699ebb4caSwyllys 	startp = bp;
142799ebb4caSwyllys 	nbytes = 0;
142899ebb4caSwyllys 
142999ebb4caSwyllys 	/*
143099ebb4caSwyllys 	 * The first two numbers are chewed up by the first octet.
143199ebb4caSwyllys 	 */
143299ebb4caSwyllys 	if (sscanf(bp, "%d", &numbuf) != 1)
143399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
143499ebb4caSwyllys 	while ((bp < &cp[len]) && isdigit(*bp))
143599ebb4caSwyllys 		bp++;
143699ebb4caSwyllys 	while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
143799ebb4caSwyllys 		bp++;
143899ebb4caSwyllys 	if (sscanf(bp, "%d", &numbuf) != 1)
143999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
144099ebb4caSwyllys 	while ((bp < &cp[len]) && isdigit(*bp))
144199ebb4caSwyllys 		bp++;
144299ebb4caSwyllys 	while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
144399ebb4caSwyllys 		bp++;
144499ebb4caSwyllys 	nbytes++;
144599ebb4caSwyllys 
144699ebb4caSwyllys 	while (isdigit(*bp)) {
144799ebb4caSwyllys 		if (sscanf(bp, "%d", &numbuf) != 1)
144899ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
144999ebb4caSwyllys 		while (numbuf) {
145099ebb4caSwyllys 			nbytes++;
145199ebb4caSwyllys 			numbuf >>= 7;
145299ebb4caSwyllys 		}
145399ebb4caSwyllys 		while ((bp < &cp[len]) && isdigit(*bp))
145499ebb4caSwyllys 			bp++;
145599ebb4caSwyllys 		while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
145699ebb4caSwyllys 			bp++;
145799ebb4caSwyllys 	}
145899ebb4caSwyllys 
145999ebb4caSwyllys 	oid->Length = nbytes;
146099ebb4caSwyllys 	oid->Data = malloc(oid->Length);
146199ebb4caSwyllys 	if (oid->Data == NULL) {
146299ebb4caSwyllys 		return (KMF_ERR_MEMORY);
146399ebb4caSwyllys 	}
146499ebb4caSwyllys 	(void) memset(oid->Data, 0, oid->Length);
146599ebb4caSwyllys 
146699ebb4caSwyllys 	op = oid->Data;
146799ebb4caSwyllys 
146899ebb4caSwyllys 	bp = startp;
146999ebb4caSwyllys 	(void) sscanf(bp, "%d", &numbuf);
147099ebb4caSwyllys 
147199ebb4caSwyllys 	while (isdigit(*bp)) bp++;
147299ebb4caSwyllys 	while (isspace(*bp) || *bp == '.') bp++;
147399ebb4caSwyllys 
147499ebb4caSwyllys 	onumbuf = 40 * numbuf;
147599ebb4caSwyllys 	(void) sscanf(bp, "%d", &numbuf);
147699ebb4caSwyllys 	onumbuf += numbuf;
147799ebb4caSwyllys 	*op = (unsigned char) onumbuf;
147899ebb4caSwyllys 	op++;
147999ebb4caSwyllys 
148099ebb4caSwyllys 	while (isdigit(*bp)) bp++;
148199ebb4caSwyllys 	while (isspace(*bp) || *bp == '.') bp++;
148299ebb4caSwyllys 	while (isdigit(*bp)) {
148399ebb4caSwyllys 		(void) sscanf(bp, "%d", &numbuf);
148499ebb4caSwyllys 		nbytes = 0;
148599ebb4caSwyllys 		/* Have to fill in the bytes msb-first */
148699ebb4caSwyllys 		onumbuf = numbuf;
148799ebb4caSwyllys 		while (numbuf) {
148899ebb4caSwyllys 			nbytes++;
148999ebb4caSwyllys 			numbuf >>= 7;
149099ebb4caSwyllys 		}
149199ebb4caSwyllys 		numbuf = onumbuf;
149299ebb4caSwyllys 		op += nbytes;
149399ebb4caSwyllys 		index = -1;
149499ebb4caSwyllys 		while (numbuf) {
149599ebb4caSwyllys 			op[index] = (unsigned char)numbuf & 0x7f;
149699ebb4caSwyllys 			if (index != -1)
149799ebb4caSwyllys 				op[index] |= 0x80;
149899ebb4caSwyllys 			index--;
149999ebb4caSwyllys 			numbuf >>= 7;
150099ebb4caSwyllys 		}
150199ebb4caSwyllys 		while (isdigit(*bp)) bp++;
150299ebb4caSwyllys 		while (isspace(*bp) || *bp == '.') bp++;
150399ebb4caSwyllys 	}
150499ebb4caSwyllys 
150599ebb4caSwyllys 	return (rv);
150699ebb4caSwyllys }
150799ebb4caSwyllys 
150899ebb4caSwyllys static KMF_RETURN
150999ebb4caSwyllys encode_rid(char *name, KMF_DATA *derdata)
151099ebb4caSwyllys {
151199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
151299ebb4caSwyllys 
151399ebb4caSwyllys 	if (name == NULL || derdata == NULL)
151499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
151599ebb4caSwyllys 
1516*30a5e8faSwyllys 	rv = kmf_string_to_oid(name, (KMF_OID *)derdata);
151799ebb4caSwyllys 
151899ebb4caSwyllys 	return (rv);
151999ebb4caSwyllys }
152099ebb4caSwyllys 
152199ebb4caSwyllys static KMF_RETURN
152299ebb4caSwyllys encode_ipaddr(char *name, KMF_DATA *derdata)
152399ebb4caSwyllys {
152499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
152599ebb4caSwyllys 	size_t len;
152699ebb4caSwyllys 	in_addr_t v4;
152799ebb4caSwyllys 	in6_addr_t v6;
152899ebb4caSwyllys 	uint8_t *ptr;
152999ebb4caSwyllys 
153099ebb4caSwyllys 	if (name == NULL || derdata == NULL)
153199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
153299ebb4caSwyllys 
153399ebb4caSwyllys 	v4 = inet_addr(name);
153499ebb4caSwyllys 	if (v4 == (in_addr_t)-1) {
153599ebb4caSwyllys 		ptr = (uint8_t *)&v6;
153699ebb4caSwyllys 		if (inet_pton(AF_INET6, name, ptr) != 1)
153799ebb4caSwyllys 			return (KMF_ERR_ENCODING);
153899ebb4caSwyllys 		len = sizeof (v6);
153999ebb4caSwyllys 	} else {
154099ebb4caSwyllys 		ptr = (uint8_t *)&v4;
154199ebb4caSwyllys 		len = sizeof (v4);
154299ebb4caSwyllys 	}
154399ebb4caSwyllys 
154499ebb4caSwyllys 	derdata->Data = malloc(len);
154599ebb4caSwyllys 	if (derdata->Data == NULL)
154699ebb4caSwyllys 		return (KMF_ERR_MEMORY);
154799ebb4caSwyllys 	(void) memcpy(derdata->Data, ptr, len);
154899ebb4caSwyllys 	derdata->Length = len;
154999ebb4caSwyllys 
155099ebb4caSwyllys 	return (rv);
155199ebb4caSwyllys }
155299ebb4caSwyllys 
155399ebb4caSwyllys static KMF_RETURN
155499ebb4caSwyllys verify_uri_format(char *uristring)
155599ebb4caSwyllys {
155699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
155799ebb4caSwyllys 	xmlURIPtr   uriptr = NULL;
155899ebb4caSwyllys 
155999ebb4caSwyllys 	/* Parse the URI string; get the hostname and port */
156099ebb4caSwyllys 	uriptr = xmlParseURI(uristring);
156199ebb4caSwyllys 	if (uriptr == NULL) {
156299ebb4caSwyllys 		ret = KMF_ERR_BAD_URI;
156399ebb4caSwyllys 		goto out;
156499ebb4caSwyllys 	}
156599ebb4caSwyllys 
156699ebb4caSwyllys 	if (uriptr->scheme == NULL || !strlen(uriptr->scheme)) {
156799ebb4caSwyllys 		ret = KMF_ERR_BAD_URI;
156899ebb4caSwyllys 		goto out;
156999ebb4caSwyllys 	}
157099ebb4caSwyllys 
157199ebb4caSwyllys 	if (uriptr->server == NULL || !strlen(uriptr->server)) {
157299ebb4caSwyllys 		ret = KMF_ERR_BAD_URI;
157399ebb4caSwyllys 		goto out;
157499ebb4caSwyllys 	}
157599ebb4caSwyllys out:
157699ebb4caSwyllys 	if (uriptr != NULL)
157799ebb4caSwyllys 		xmlFreeURI(uriptr);
157899ebb4caSwyllys 	return (ret);
157999ebb4caSwyllys }
158099ebb4caSwyllys 
158199ebb4caSwyllys static KMF_RETURN
158299ebb4caSwyllys encode_altname(char *namedata,
158399ebb4caSwyllys 	KMF_GENERALNAMECHOICES nametype, KMF_DATA *encodedname)
158499ebb4caSwyllys {
158599ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
158699ebb4caSwyllys 	KMF_X509_NAME dnname;
158799ebb4caSwyllys 	uchar_t tagval;
158899ebb4caSwyllys 	BerElement *asn1 = NULL;
158999ebb4caSwyllys 	BerValue *extdata;
159099ebb4caSwyllys 
159199ebb4caSwyllys 	if (namedata == NULL || encodedname == NULL)
159299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
159399ebb4caSwyllys 
159499ebb4caSwyllys 	/*
159599ebb4caSwyllys 	 * Encode the namedata according to rules in RFC 3280 for GeneralName.
159699ebb4caSwyllys 	 * The input "namedata" is assumed to be an ASCII string representation
159799ebb4caSwyllys 	 * of the AltName, we need to convert it to correct ASN.1 here before
159899ebb4caSwyllys 	 * adding it to the cert.
159999ebb4caSwyllys 	 */
160099ebb4caSwyllys 	switch (nametype) {
160199ebb4caSwyllys 		case GENNAME_RFC822NAME: /* rfc 822 */
160299ebb4caSwyllys 			/* IA5String, no encoding needed */
160399ebb4caSwyllys 			encodedname->Data = (uchar_t *)strdup(namedata);
160499ebb4caSwyllys 			if (encodedname->Data == NULL)
160599ebb4caSwyllys 				return (KMF_ERR_MEMORY);
160699ebb4caSwyllys 			encodedname->Length = strlen(namedata);
160799ebb4caSwyllys 			tagval = (0x80 | nametype);
160899ebb4caSwyllys 			break;
160999ebb4caSwyllys 		case GENNAME_DNSNAME: /* rfc 1034 */
161099ebb4caSwyllys 			encodedname->Data = (uchar_t *)strdup(namedata);
161199ebb4caSwyllys 			if (encodedname->Data == NULL)
161299ebb4caSwyllys 				return (KMF_ERR_MEMORY);
161399ebb4caSwyllys 			encodedname->Length = strlen(namedata);
161499ebb4caSwyllys 			tagval = (0x80 | nametype);
161599ebb4caSwyllys 			break;
161699ebb4caSwyllys 		case GENNAME_URI: /* rfc 1738 */
161799ebb4caSwyllys 			ret = verify_uri_format(namedata);
161899ebb4caSwyllys 			if (ret != KMF_OK)
161999ebb4caSwyllys 				return (ret);
162099ebb4caSwyllys 			/* IA5String, no encoding needed */
162199ebb4caSwyllys 			encodedname->Data = (uchar_t *)strdup(namedata);
162299ebb4caSwyllys 			if (encodedname->Data == NULL)
162399ebb4caSwyllys 				return (KMF_ERR_MEMORY);
162499ebb4caSwyllys 			encodedname->Length = strlen(namedata);
162599ebb4caSwyllys 			tagval = (0x80 | nametype);
162699ebb4caSwyllys 			break;
162799ebb4caSwyllys 		case GENNAME_IPADDRESS:
162899ebb4caSwyllys 			ret =  encode_ipaddr(namedata, encodedname);
162999ebb4caSwyllys 			tagval = (0x80 | nametype);
163099ebb4caSwyllys 			break;
163199ebb4caSwyllys 		case GENNAME_REGISTEREDID:
163299ebb4caSwyllys 			ret = encode_rid(namedata, encodedname);
163399ebb4caSwyllys 			tagval = (0x80 | nametype);
163499ebb4caSwyllys 			break;
163599ebb4caSwyllys 		case GENNAME_DIRECTORYNAME:
1636*30a5e8faSwyllys 			ret = kmf_dn_parser(namedata, &dnname);
163799ebb4caSwyllys 			if (ret == KMF_OK) {
1638*30a5e8faSwyllys 				ret = DerEncodeName(&dnname, encodedname);
163999ebb4caSwyllys 			}
1640*30a5e8faSwyllys 			(void) kmf_free_dn(&dnname);
164199ebb4caSwyllys 			tagval = (0xA0 | nametype);
164299ebb4caSwyllys 			break;
164399ebb4caSwyllys 		default:
164499ebb4caSwyllys 			/* unsupported */
164599ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
164699ebb4caSwyllys 
164799ebb4caSwyllys 	}
164899ebb4caSwyllys 	if (ret != KMF_OK) {
1649*30a5e8faSwyllys 		kmf_free_data(encodedname);
165099ebb4caSwyllys 		return (ret);
165199ebb4caSwyllys 	}
165299ebb4caSwyllys 
165399ebb4caSwyllys 	if ((asn1 = kmfder_alloc()) == NULL)
165499ebb4caSwyllys 		return (KMF_ERR_MEMORY);
165599ebb4caSwyllys 
1656*30a5e8faSwyllys 	if (kmfber_printf(asn1, "Tl", tagval, encodedname->Length) == -1)
165799ebb4caSwyllys 		goto cleanup;
165899ebb4caSwyllys 
165999ebb4caSwyllys 	if (kmfber_write(asn1, (char *)encodedname->Data,
1660*30a5e8faSwyllys 	    encodedname->Length, 0) == -1) {
166199ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
166299ebb4caSwyllys 		goto cleanup;
166399ebb4caSwyllys 	}
166499ebb4caSwyllys 	if (kmfber_flatten(asn1, &extdata) == -1) {
166599ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
166699ebb4caSwyllys 		goto cleanup;
166799ebb4caSwyllys 	}
166899ebb4caSwyllys 
1669*30a5e8faSwyllys 	kmf_free_data(encodedname);
167099ebb4caSwyllys 	encodedname->Data = (uchar_t *)extdata->bv_val;
167199ebb4caSwyllys 	encodedname->Length = extdata->bv_len;
167299ebb4caSwyllys 
167399ebb4caSwyllys 	free(extdata);
167499ebb4caSwyllys 
167599ebb4caSwyllys cleanup:
167699ebb4caSwyllys 	if (asn1)
167799ebb4caSwyllys 		kmfber_free(asn1, 1);
167899ebb4caSwyllys 
167999ebb4caSwyllys 	if (ret != KMF_OK)
1680*30a5e8faSwyllys 		kmf_free_data(encodedname);
168199ebb4caSwyllys 
168299ebb4caSwyllys 	return (ret);
168399ebb4caSwyllys }
168499ebb4caSwyllys 
168599ebb4caSwyllys KMF_X509_EXTENSION *
168699ebb4caSwyllys FindExtn(KMF_X509_EXTENSIONS *exts, KMF_OID *oid)
168799ebb4caSwyllys {
168899ebb4caSwyllys 	KMF_X509_EXTENSION *foundextn = NULL;
168999ebb4caSwyllys 	int i;
169099ebb4caSwyllys 
169199ebb4caSwyllys 	if (exts == NULL || oid == NULL)
169299ebb4caSwyllys 		return (NULL);
169399ebb4caSwyllys 
169499ebb4caSwyllys 	for (i = 0; i < exts->numberOfExtensions; i++) {
169599ebb4caSwyllys 		if (IsEqualOid(oid, &exts->extensions[i].extnId))  {
169699ebb4caSwyllys 			foundextn = &exts->extensions[i];
169799ebb4caSwyllys 			break;
169899ebb4caSwyllys 		}
169999ebb4caSwyllys 	}
170099ebb4caSwyllys 	return (foundextn);
170199ebb4caSwyllys }
170299ebb4caSwyllys 
170399ebb4caSwyllys KMF_RETURN
170499ebb4caSwyllys GetSequenceContents(char *data, size_t len,
170599ebb4caSwyllys 	char **contents, size_t *outlen)
170699ebb4caSwyllys {
170799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
170899ebb4caSwyllys 	BerElement *exasn1 = NULL;
170999ebb4caSwyllys 	BerValue oldextn;
171099ebb4caSwyllys 	int tag;
171199ebb4caSwyllys 	size_t oldsize;
171299ebb4caSwyllys 	char *olddata = NULL;
171399ebb4caSwyllys 
171499ebb4caSwyllys 	if (data == NULL || contents == NULL || outlen == NULL)
171599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
171699ebb4caSwyllys 
171799ebb4caSwyllys 	/*
171899ebb4caSwyllys 	 * Decode the sequence of general names
171999ebb4caSwyllys 	 */
172099ebb4caSwyllys 	oldextn.bv_val = data;
172199ebb4caSwyllys 	oldextn.bv_len = len;
172299ebb4caSwyllys 
172399ebb4caSwyllys 	if ((exasn1 = kmfder_init(&oldextn)) == NULL) {
172499ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
172599ebb4caSwyllys 		goto out;
172699ebb4caSwyllys 	}
172799ebb4caSwyllys 
172899ebb4caSwyllys 	/*
172999ebb4caSwyllys 	 * Unwrap the sequence to find the size of the block
173099ebb4caSwyllys 	 * of GeneralName items in the set.
173199ebb4caSwyllys 	 *
173299ebb4caSwyllys 	 * Peek at the tag and length ("tl"),
173399ebb4caSwyllys 	 * then consume them ("{").
173499ebb4caSwyllys 	 */
173599ebb4caSwyllys 	if (kmfber_scanf(exasn1, "tl{", &tag, &oldsize) == KMFBER_DEFAULT ||
1736*30a5e8faSwyllys 	    oldsize == 0) {
173799ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
173899ebb4caSwyllys 		goto out;
173999ebb4caSwyllys 	}
174099ebb4caSwyllys 
174199ebb4caSwyllys 	olddata = malloc(oldsize);
174299ebb4caSwyllys 	if (olddata == NULL) {
174399ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
174499ebb4caSwyllys 		goto out;
174599ebb4caSwyllys 	}
174699ebb4caSwyllys 	(void) memset(olddata, 0, oldsize);
174799ebb4caSwyllys 	/*
174899ebb4caSwyllys 	 * Read the entire blob of GeneralNames, we don't
174999ebb4caSwyllys 	 * need to interpret them now.
175099ebb4caSwyllys 	 */
175199ebb4caSwyllys 	if (kmfber_read(exasn1, olddata, oldsize) != oldsize) {
175299ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
175399ebb4caSwyllys 		goto out;
175499ebb4caSwyllys 	}
175599ebb4caSwyllys out:
175699ebb4caSwyllys 	if (exasn1 != NULL)
175799ebb4caSwyllys 		kmfber_free(exasn1, 1);
175899ebb4caSwyllys 
175999ebb4caSwyllys 	if (ret != KMF_OK) {
176099ebb4caSwyllys 		*contents = NULL;
176199ebb4caSwyllys 		*outlen = 0;
176299ebb4caSwyllys 		if (olddata != NULL)
176399ebb4caSwyllys 			free(olddata);
176499ebb4caSwyllys 	} else {
176599ebb4caSwyllys 		*contents = olddata;
176699ebb4caSwyllys 		*outlen = oldsize;
176799ebb4caSwyllys 	}
176899ebb4caSwyllys 	return (ret);
176999ebb4caSwyllys }
177099ebb4caSwyllys 
177199ebb4caSwyllys KMF_RETURN
177299ebb4caSwyllys add_an_extension(KMF_X509_EXTENSIONS *exts, KMF_X509_EXTENSION *newextn)
177399ebb4caSwyllys {
177499ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
177599ebb4caSwyllys 	KMF_X509_EXTENSION *extlist;
177699ebb4caSwyllys 
177799ebb4caSwyllys 	if (exts == NULL || newextn == NULL)
177899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
177999ebb4caSwyllys 
178099ebb4caSwyllys 	extlist = malloc(sizeof (KMF_X509_EXTENSION) *
1781*30a5e8faSwyllys 	    (exts->numberOfExtensions + 1));
178299ebb4caSwyllys 	if (extlist == NULL)
178399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
178499ebb4caSwyllys 
178599ebb4caSwyllys 	(void) memcpy(extlist, exts->extensions,
178699ebb4caSwyllys 	    exts->numberOfExtensions * sizeof (KMF_X509_EXTENSION));
178799ebb4caSwyllys 
178899ebb4caSwyllys 	(void) memcpy(&extlist[exts->numberOfExtensions], newextn,
1789*30a5e8faSwyllys 	    sizeof (KMF_X509_EXTENSION));
179099ebb4caSwyllys 
179199ebb4caSwyllys 	free(exts->extensions);
179299ebb4caSwyllys 	exts->numberOfExtensions++;
179399ebb4caSwyllys 	exts->extensions = extlist;
179499ebb4caSwyllys 
179599ebb4caSwyllys 	return (ret);
179699ebb4caSwyllys }
179799ebb4caSwyllys 
179899ebb4caSwyllys KMF_RETURN
1799*30a5e8faSwyllys kmf_set_altname(KMF_X509_EXTENSIONS *extensions,
180099ebb4caSwyllys 	KMF_OID *oid,
180199ebb4caSwyllys 	int critical,
180299ebb4caSwyllys 	KMF_GENERALNAMECHOICES nametype,
180399ebb4caSwyllys 	char *namedata)
180499ebb4caSwyllys {
180599ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
180699ebb4caSwyllys 	KMF_X509_EXTENSION subjAltName;
180799ebb4caSwyllys 	KMF_DATA dername = { NULL, 0 };
180899ebb4caSwyllys 	BerElement *asn1 = NULL;
180999ebb4caSwyllys 	BerValue *extdata;
181099ebb4caSwyllys 	char *olddata = NULL;
181199ebb4caSwyllys 	KMF_X509_EXTENSION *foundextn = NULL;
181299ebb4caSwyllys 	size_t	oldsize = 0;
181399ebb4caSwyllys 
181499ebb4caSwyllys 	if (extensions == NULL || oid == NULL || namedata == NULL)
181599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
181699ebb4caSwyllys 
181799ebb4caSwyllys 	ret = encode_altname(namedata, nametype, &dername);
181899ebb4caSwyllys 
181999ebb4caSwyllys 	if (ret != KMF_OK)
182099ebb4caSwyllys 		return (ret);
182199ebb4caSwyllys 
182299ebb4caSwyllys 	(void) memset(&subjAltName, 0, sizeof (subjAltName));
182399ebb4caSwyllys 
182499ebb4caSwyllys 	ret = copy_data(&subjAltName.extnId, oid);
182599ebb4caSwyllys 	if (ret != KMF_OK)
182699ebb4caSwyllys 		goto out;
182799ebb4caSwyllys 	/*
182899ebb4caSwyllys 	 * Check to see if this cert already has a subjectAltName.
182999ebb4caSwyllys 	 */
183099ebb4caSwyllys 	foundextn = FindExtn(extensions, oid);
183199ebb4caSwyllys 
183299ebb4caSwyllys 	if (foundextn != NULL) {
183399ebb4caSwyllys 		ret = GetSequenceContents(
1834*30a5e8faSwyllys 		    (char *)foundextn->BERvalue.Data,
1835*30a5e8faSwyllys 		    foundextn->BERvalue.Length,
1836*30a5e8faSwyllys 		    &olddata, &oldsize);
183799ebb4caSwyllys 		if (ret != KMF_OK)
183899ebb4caSwyllys 			goto out;
183999ebb4caSwyllys 	}
184099ebb4caSwyllys 
184199ebb4caSwyllys 	/*
184299ebb4caSwyllys 	 * Assume (!!) that the namedata given is already properly encoded.
184399ebb4caSwyllys 	 */
184499ebb4caSwyllys 	if ((asn1 = kmfder_alloc()) == NULL)
184599ebb4caSwyllys 		return (KMF_ERR_MEMORY);
184699ebb4caSwyllys 
184799ebb4caSwyllys 	if (kmfber_printf(asn1, "{") == -1) {
184899ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
184999ebb4caSwyllys 		goto out;
185099ebb4caSwyllys 	}
185199ebb4caSwyllys 
185299ebb4caSwyllys 	/* Write the old extension data first */
185399ebb4caSwyllys 	if (olddata != NULL && oldsize > 0) {
185499ebb4caSwyllys 		if (kmfber_write(asn1, olddata, oldsize, 0) == -1) {
185599ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
185699ebb4caSwyllys 			goto out;
185799ebb4caSwyllys 		}
185899ebb4caSwyllys 	}
185999ebb4caSwyllys 
186099ebb4caSwyllys 	/* Now add the new name to the list */
186199ebb4caSwyllys 	if (kmfber_write(asn1, (char *)dername.Data, dername.Length, 0) == -1) {
186299ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
186399ebb4caSwyllys 		goto out;
186499ebb4caSwyllys 	}
186599ebb4caSwyllys 
186699ebb4caSwyllys 	/* Now close the sequence */
186799ebb4caSwyllys 	if (kmfber_printf(asn1, "}") == -1) {
186899ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
186999ebb4caSwyllys 		goto out;
187099ebb4caSwyllys 	}
187199ebb4caSwyllys 	if (kmfber_flatten(asn1, &extdata) == -1) {
187299ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
187399ebb4caSwyllys 		goto out;
187499ebb4caSwyllys 	}
187599ebb4caSwyllys 
187699ebb4caSwyllys 	/*
187799ebb4caSwyllys 	 * If we are just adding to an existing list of altNames,
187899ebb4caSwyllys 	 * just replace the BER data associated with the found extension.
187999ebb4caSwyllys 	 */
188099ebb4caSwyllys 	if (foundextn != NULL) {
188199ebb4caSwyllys 		free(foundextn->BERvalue.Data);
188299ebb4caSwyllys 		foundextn->critical = critical;
188399ebb4caSwyllys 		foundextn->BERvalue.Data = (uchar_t *)extdata->bv_val;
188499ebb4caSwyllys 		foundextn->BERvalue.Length = extdata->bv_len;
188599ebb4caSwyllys 	} else {
188699ebb4caSwyllys 		subjAltName.critical = critical;
188799ebb4caSwyllys 		subjAltName.format = KMF_X509_DATAFORMAT_ENCODED;
188899ebb4caSwyllys 		subjAltName.BERvalue.Data = (uchar_t *)extdata->bv_val;
188999ebb4caSwyllys 		subjAltName.BERvalue.Length = extdata->bv_len;
189099ebb4caSwyllys 		ret = add_an_extension(extensions, &subjAltName);
189199ebb4caSwyllys 		if (ret != KMF_OK)
189299ebb4caSwyllys 			free(subjAltName.BERvalue.Data);
189399ebb4caSwyllys 	}
189499ebb4caSwyllys 
189599ebb4caSwyllys 	free(extdata);
189699ebb4caSwyllys out:
189799ebb4caSwyllys 	if (olddata != NULL)
189899ebb4caSwyllys 		free(olddata);
189999ebb4caSwyllys 
1900*30a5e8faSwyllys 	kmf_free_data(&dername);
190199ebb4caSwyllys 	if (ret != KMF_OK)
1902*30a5e8faSwyllys 		kmf_free_data(&subjAltName.extnId);
190399ebb4caSwyllys 	if (asn1 != NULL)
190499ebb4caSwyllys 		kmfber_free(asn1, 1);
190599ebb4caSwyllys 	return (ret);
190699ebb4caSwyllys }
1907*30a5e8faSwyllys 
1908*30a5e8faSwyllys /*
1909*30a5e8faSwyllys  * Search a list of attributes for one that matches the given type.
1910*30a5e8faSwyllys  * Return a pointer into the attribute list.  This does not
1911*30a5e8faSwyllys  * return a copy of the value, it returns a reference into the
1912*30a5e8faSwyllys  * given list.
1913*30a5e8faSwyllys  */
1914*30a5e8faSwyllys int
1915*30a5e8faSwyllys kmf_find_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist, int numattrs)
1916*30a5e8faSwyllys {
1917*30a5e8faSwyllys 	int i;
1918*30a5e8faSwyllys 	for (i = 0; i < numattrs; i++) {
1919*30a5e8faSwyllys 		if (attlist[i].type == type)
1920*30a5e8faSwyllys 			return (i);
1921*30a5e8faSwyllys 	}
1922*30a5e8faSwyllys 	return (-1);
1923*30a5e8faSwyllys }
1924*30a5e8faSwyllys 
1925*30a5e8faSwyllys /*
1926*30a5e8faSwyllys  * Verify that a given attribute is consistent with the
1927*30a5e8faSwyllys  * "test" attribute.
1928*30a5e8faSwyllys  */
1929*30a5e8faSwyllys static KMF_RETURN
1930*30a5e8faSwyllys verify_attribute(KMF_ATTRIBUTE *givenattr,
1931*30a5e8faSwyllys 	KMF_ATTRIBUTE_TESTER *testattr)
1932*30a5e8faSwyllys {
1933*30a5e8faSwyllys 	/* A NULL pValue was found where one is required */
1934*30a5e8faSwyllys 	if (testattr->null_value_ok == FALSE &&
1935*30a5e8faSwyllys 	    givenattr->pValue == NULL)
1936*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1937*30a5e8faSwyllys 
1938*30a5e8faSwyllys 	/* If the given valueLen is too small, return error */
1939*30a5e8faSwyllys 	if (givenattr->pValue != NULL &&
1940*30a5e8faSwyllys 	    testattr->minlen > 0 &&
1941*30a5e8faSwyllys 	    (givenattr->valueLen < testattr->minlen))
1942*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1943*30a5e8faSwyllys 
1944*30a5e8faSwyllys 	/* If the given valueLen is too big, return error */
1945*30a5e8faSwyllys 	if (givenattr->pValue != NULL &&
1946*30a5e8faSwyllys 	    testattr->maxlen > 0 &&
1947*30a5e8faSwyllys 	    (givenattr->valueLen > testattr->maxlen))
1948*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1949*30a5e8faSwyllys 
1950*30a5e8faSwyllys 	return (KMF_OK);
1951*30a5e8faSwyllys }
1952*30a5e8faSwyllys 
1953*30a5e8faSwyllys /*
1954*30a5e8faSwyllys  * Given a set of required attribute tests and optional
1955*30a5e8faSwyllys  * attributes, make sure that the actual attributes
1956*30a5e8faSwyllys  * being tested (attrlist below) are allowed and are
1957*30a5e8faSwyllys  * properly specified.
1958*30a5e8faSwyllys  */
1959*30a5e8faSwyllys KMF_RETURN
1960*30a5e8faSwyllys test_attributes(int reqnum, KMF_ATTRIBUTE_TESTER *reqattrs,
1961*30a5e8faSwyllys 	int optnum, KMF_ATTRIBUTE_TESTER *optattrs,
1962*30a5e8faSwyllys 	int numattrs, KMF_ATTRIBUTE *attrlist)
1963*30a5e8faSwyllys {
1964*30a5e8faSwyllys 	KMF_RETURN ret = KMF_OK;
1965*30a5e8faSwyllys 	int i, idx;
1966*30a5e8faSwyllys 
1967*30a5e8faSwyllys 	/*
1968*30a5e8faSwyllys 	 * If the caller didn't supply enough attributes,
1969*30a5e8faSwyllys 	 * return an error.
1970*30a5e8faSwyllys 	 */
1971*30a5e8faSwyllys 	if (numattrs < reqnum || attrlist == NULL)
1972*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
1973*30a5e8faSwyllys 
1974*30a5e8faSwyllys 	/*
1975*30a5e8faSwyllys 	 * Make sure all required attrs are present and
1976*30a5e8faSwyllys 	 * correct.
1977*30a5e8faSwyllys 	 */
1978*30a5e8faSwyllys 	for (i = 0; i < reqnum && ret == KMF_OK; i++) {
1979*30a5e8faSwyllys 		idx = kmf_find_attr(reqattrs[i].type, attrlist, numattrs);
1980*30a5e8faSwyllys 		/* If a required attr is not found, return error */
1981*30a5e8faSwyllys 		if (idx == -1) {
1982*30a5e8faSwyllys 			return (KMF_ERR_BAD_PARAMETER);
1983*30a5e8faSwyllys 		}
1984*30a5e8faSwyllys 
1985*30a5e8faSwyllys 		ret = verify_attribute(&attrlist[idx], &reqattrs[i]);
1986*30a5e8faSwyllys 	}
1987*30a5e8faSwyllys 	/*
1988*30a5e8faSwyllys 	 * Now test the optional parameters.
1989*30a5e8faSwyllys 	 */
1990*30a5e8faSwyllys 	for (i = 0; i < optnum && ret == KMF_OK; i++) {
1991*30a5e8faSwyllys 		idx = kmf_find_attr(optattrs[i].type, attrlist, numattrs);
1992*30a5e8faSwyllys 		/* If a optional attr is not found, continue. */
1993*30a5e8faSwyllys 		if (idx == -1) {
1994*30a5e8faSwyllys 			continue;
1995*30a5e8faSwyllys 		}
1996*30a5e8faSwyllys 
1997*30a5e8faSwyllys 		ret = verify_attribute(&attrlist[idx], &optattrs[i]);
1998*30a5e8faSwyllys 	}
1999*30a5e8faSwyllys 
2000*30a5e8faSwyllys 	return (ret);
2001*30a5e8faSwyllys }
2002*30a5e8faSwyllys 
2003*30a5e8faSwyllys /*
2004*30a5e8faSwyllys  * Given an already allocated attribute list, insert
2005*30a5e8faSwyllys  * the given attribute information at a specific index
2006*30a5e8faSwyllys  * in the list.
2007*30a5e8faSwyllys  */
2008*30a5e8faSwyllys void
2009*30a5e8faSwyllys kmf_set_attr_at_index(KMF_ATTRIBUTE *attlist, int index,
2010*30a5e8faSwyllys 	KMF_ATTR_TYPE type,  void *pValue, uint32_t len)
2011*30a5e8faSwyllys {
2012*30a5e8faSwyllys 	if (attlist == NULL)
2013*30a5e8faSwyllys 		return;
2014*30a5e8faSwyllys 
2015*30a5e8faSwyllys 	attlist[index].type = type;
2016*30a5e8faSwyllys 	attlist[index].pValue = pValue;
2017*30a5e8faSwyllys 	attlist[index].valueLen = len;
2018*30a5e8faSwyllys }
2019*30a5e8faSwyllys 
2020*30a5e8faSwyllys /*
2021*30a5e8faSwyllys  * Find an attribute matching a particular type and set
2022*30a5e8faSwyllys  * the pValue and length fields to the given values.
2023*30a5e8faSwyllys  */
2024*30a5e8faSwyllys KMF_RETURN
2025*30a5e8faSwyllys kmf_set_attr(KMF_ATTRIBUTE *attlist, int numattr,
2026*30a5e8faSwyllys 	KMF_ATTR_TYPE type,  void *pValue, uint32_t len)
2027*30a5e8faSwyllys {
2028*30a5e8faSwyllys 	int idx;
2029*30a5e8faSwyllys 	if (attlist == NULL)
2030*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2031*30a5e8faSwyllys 
2032*30a5e8faSwyllys 	idx = kmf_find_attr(type, attlist, numattr);
2033*30a5e8faSwyllys 	if (idx == -1)
2034*30a5e8faSwyllys 		return (KMF_ERR_ATTR_NOT_FOUND);
2035*30a5e8faSwyllys 
2036*30a5e8faSwyllys 	attlist[idx].type = type;
2037*30a5e8faSwyllys 	/* Assumes the attribute pValue can hold the result */
2038*30a5e8faSwyllys 	if (attlist[idx].pValue != NULL) {
2039*30a5e8faSwyllys 		if (attlist[idx].valueLen >= len)
2040*30a5e8faSwyllys 			(void) memcpy(attlist[idx].pValue, pValue, len);
2041*30a5e8faSwyllys 		else
2042*30a5e8faSwyllys 			return (KMF_ERR_BUFFER_SIZE);
2043*30a5e8faSwyllys 	}
2044*30a5e8faSwyllys 	attlist[idx].valueLen = len;
2045*30a5e8faSwyllys 	return (KMF_OK);
2046*30a5e8faSwyllys }
2047*30a5e8faSwyllys 
2048*30a5e8faSwyllys /*
2049*30a5e8faSwyllys  * Find a particular attribute in a list and return
2050*30a5e8faSwyllys  * a pointer to its value.
2051*30a5e8faSwyllys  */
2052*30a5e8faSwyllys void *
2053*30a5e8faSwyllys kmf_get_attr_ptr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist,
2054*30a5e8faSwyllys 	int numattrs)
2055*30a5e8faSwyllys {
2056*30a5e8faSwyllys 	int i;
2057*30a5e8faSwyllys 
2058*30a5e8faSwyllys 	i = kmf_find_attr(type, attlist, numattrs);
2059*30a5e8faSwyllys 	if (i == -1)
2060*30a5e8faSwyllys 		return (NULL);
2061*30a5e8faSwyllys 
2062*30a5e8faSwyllys 	return (attlist[i].pValue);
2063*30a5e8faSwyllys }
2064*30a5e8faSwyllys 
2065*30a5e8faSwyllys /*
2066*30a5e8faSwyllys  * Find a particular attribute in a list and return
2067*30a5e8faSwyllys  * the value and length values.  Value and length
2068*30a5e8faSwyllys  * may be NULL if the caller doesn't want their values
2069*30a5e8faSwyllys  * to be filled in.
2070*30a5e8faSwyllys  */
2071*30a5e8faSwyllys KMF_RETURN
2072*30a5e8faSwyllys kmf_get_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist,
2073*30a5e8faSwyllys 	int numattrs, void *outValue, uint32_t *outlen)
2074*30a5e8faSwyllys {
2075*30a5e8faSwyllys 	int i;
2076*30a5e8faSwyllys 	uint32_t len = 0;
2077*30a5e8faSwyllys 	uint32_t *lenptr = outlen;
2078*30a5e8faSwyllys 
2079*30a5e8faSwyllys 	if (lenptr == NULL)
2080*30a5e8faSwyllys 		lenptr = &len;
2081*30a5e8faSwyllys 
2082*30a5e8faSwyllys 	i = kmf_find_attr(type, attlist, numattrs);
2083*30a5e8faSwyllys 	if (i == -1)
2084*30a5e8faSwyllys 		return (KMF_ERR_ATTR_NOT_FOUND);
2085*30a5e8faSwyllys 
2086*30a5e8faSwyllys 	/* This assumes that the ptr passed in is pre-allocated space */
2087*30a5e8faSwyllys 	if (attlist[i].pValue != NULL && outValue != NULL) {
2088*30a5e8faSwyllys 		/*
2089*30a5e8faSwyllys 		 * If the caller did not specify a length,
2090*30a5e8faSwyllys 		 * assume "outValue" is big enough.
2091*30a5e8faSwyllys 		 */
2092*30a5e8faSwyllys 		if (outlen != NULL) {
2093*30a5e8faSwyllys 			if (*outlen >= attlist[i].valueLen)
2094*30a5e8faSwyllys 				(void) memcpy(outValue, attlist[i].pValue,
2095*30a5e8faSwyllys 				    attlist[i].valueLen);
2096*30a5e8faSwyllys 			else
2097*30a5e8faSwyllys 				return (KMF_ERR_BUFFER_SIZE);
2098*30a5e8faSwyllys 		} else {
2099*30a5e8faSwyllys 			(void) memcpy(outValue, attlist[i].pValue,
2100*30a5e8faSwyllys 			    attlist[i].valueLen);
2101*30a5e8faSwyllys 		}
2102*30a5e8faSwyllys 	}
2103*30a5e8faSwyllys 
2104*30a5e8faSwyllys 	if (outlen != NULL)
2105*30a5e8faSwyllys 		*outlen = attlist[i].valueLen;
2106*30a5e8faSwyllys 	return (KMF_OK);
2107*30a5e8faSwyllys }
2108*30a5e8faSwyllys 
2109*30a5e8faSwyllys /*
2110*30a5e8faSwyllys  * Utility routine to find a string type attribute, allocate it
2111*30a5e8faSwyllys  * and return the value to the caller.  This simplifies the
2112*30a5e8faSwyllys  * operation by doing both "kmf_get_attr" calls and avoids
2113*30a5e8faSwyllys  * duplicating this block of code in lots of places.
2114*30a5e8faSwyllys  */
2115*30a5e8faSwyllys KMF_RETURN
2116*30a5e8faSwyllys kmf_get_string_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attrlist,
2117*30a5e8faSwyllys 	int numattrs, char **outstr)
2118*30a5e8faSwyllys {
2119*30a5e8faSwyllys 	KMF_RETURN rv;
2120*30a5e8faSwyllys 	uint32_t len;
2121*30a5e8faSwyllys 
2122*30a5e8faSwyllys 	if (outstr == NULL)
2123*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2124*30a5e8faSwyllys 
2125*30a5e8faSwyllys 	if ((rv = kmf_get_attr(type, attrlist, numattrs, NULL, &len)) ==
2126*30a5e8faSwyllys 	    KMF_OK) {
2127*30a5e8faSwyllys 		*outstr = malloc(len + 1);
2128*30a5e8faSwyllys 		if ((*outstr) == NULL)
2129*30a5e8faSwyllys 			return (KMF_ERR_MEMORY);
2130*30a5e8faSwyllys 		(void) memset((*outstr), 0, len + 1);
2131*30a5e8faSwyllys 		rv = kmf_get_attr(type, attrlist, numattrs, (*outstr), &len);
2132*30a5e8faSwyllys 		if (rv != KMF_OK) {
2133*30a5e8faSwyllys 			free(*outstr);
2134*30a5e8faSwyllys 			*outstr = NULL;
2135*30a5e8faSwyllys 		}
2136*30a5e8faSwyllys 	}
2137*30a5e8faSwyllys 
2138*30a5e8faSwyllys 	return (rv);
2139*30a5e8faSwyllys }
2140*30a5e8faSwyllys 
2141*30a5e8faSwyllys /*
2142*30a5e8faSwyllys  * This API is used by elfsign. We must keep it in old API form.
2143*30a5e8faSwyllys  */
2144*30a5e8faSwyllys KMF_RETURN
2145*30a5e8faSwyllys KMF_ConfigureKeystore(KMF_HANDLE_T handle, KMF_CONFIG_PARAMS *params)
2146*30a5e8faSwyllys {
2147*30a5e8faSwyllys 
2148*30a5e8faSwyllys 	KMF_ATTRIBUTE attlist[32];
2149*30a5e8faSwyllys 	int i = 0;
2150*30a5e8faSwyllys 
2151*30a5e8faSwyllys 	if (params == NULL)
2152*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
2153*30a5e8faSwyllys 
2154*30a5e8faSwyllys 	kmf_set_attr_at_index(attlist, i,
2155*30a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &params->kstype, sizeof (params->kstype));
2156*30a5e8faSwyllys 	i++;
2157*30a5e8faSwyllys 
2158*30a5e8faSwyllys 	if (params->kstype == KMF_KEYSTORE_NSS) {
2159*30a5e8faSwyllys 		if (params->nssconfig.configdir != NULL) {
2160*30a5e8faSwyllys 			kmf_set_attr_at_index(attlist, i,
2161*30a5e8faSwyllys 			    KMF_DIRPATH_ATTR,
2162*30a5e8faSwyllys 			    params->nssconfig.configdir,
2163*30a5e8faSwyllys 			    strlen(params->nssconfig.configdir));
2164*30a5e8faSwyllys 			i++;
2165*30a5e8faSwyllys 		}
2166*30a5e8faSwyllys 		if (params->nssconfig.certPrefix != NULL) {
2167*30a5e8faSwyllys 			kmf_set_attr_at_index(attlist, i,
2168*30a5e8faSwyllys 			    KMF_CERTPREFIX_ATTR,
2169*30a5e8faSwyllys 			    params->nssconfig.certPrefix,
2170*30a5e8faSwyllys 			    strlen(params->nssconfig.certPrefix));
2171*30a5e8faSwyllys 			i++;
2172*30a5e8faSwyllys 		}
2173*30a5e8faSwyllys 		if (params->nssconfig.keyPrefix != NULL) {
2174*30a5e8faSwyllys 			kmf_set_attr_at_index(attlist, i,
2175*30a5e8faSwyllys 			    KMF_KEYPREFIX_ATTR,
2176*30a5e8faSwyllys 			    params->nssconfig.keyPrefix,
2177*30a5e8faSwyllys 			    strlen(params->nssconfig.keyPrefix));
2178*30a5e8faSwyllys 			i++;
2179*30a5e8faSwyllys 		}
2180*30a5e8faSwyllys 		if (params->nssconfig.secModName != NULL) {
2181*30a5e8faSwyllys 			kmf_set_attr_at_index(attlist, i,
2182*30a5e8faSwyllys 			    KMF_SECMODNAME_ATTR,
2183*30a5e8faSwyllys 			    params->nssconfig.secModName,
2184*30a5e8faSwyllys 			    strlen(params->nssconfig.secModName));
2185*30a5e8faSwyllys 			i++;
2186*30a5e8faSwyllys 		}
2187*30a5e8faSwyllys 	} else if (params->kstype == KMF_KEYSTORE_PK11TOKEN) {
2188*30a5e8faSwyllys 		if (params->pkcs11config.label != NULL) {
2189*30a5e8faSwyllys 			kmf_set_attr_at_index(attlist, i,
2190*30a5e8faSwyllys 			    KMF_TOKEN_LABEL_ATTR,
2191*30a5e8faSwyllys 			    params->pkcs11config.label,
2192*30a5e8faSwyllys 			    strlen(params->pkcs11config.label));
2193*30a5e8faSwyllys 			i++;
2194*30a5e8faSwyllys 		}
2195*30a5e8faSwyllys 		kmf_set_attr_at_index(attlist, i,
2196*30a5e8faSwyllys 		    KMF_READONLY_ATTR,
2197*30a5e8faSwyllys 		    &params->pkcs11config.readonly,
2198*30a5e8faSwyllys 		    sizeof (params->pkcs11config.readonly));
2199*30a5e8faSwyllys 		i++;
2200*30a5e8faSwyllys 	}
2201*30a5e8faSwyllys 
2202*30a5e8faSwyllys 	return (kmf_configure_keystore(handle, i, attlist));
2203*30a5e8faSwyllys }
2204*30a5e8faSwyllys 
2205*30a5e8faSwyllys /*
2206*30a5e8faSwyllys  * This API is used by elfsign. We must keep it in old API form.
2207*30a5e8faSwyllys  */
2208*30a5e8faSwyllys KMF_RETURN
2209*30a5e8faSwyllys KMF_Initialize(KMF_HANDLE_T *outhandle, char *policyfile, char *policyname)
2210*30a5e8faSwyllys {
2211*30a5e8faSwyllys 	return (kmf_initialize(outhandle, policyfile, policyname));
2212*30a5e8faSwyllys }
2213*30a5e8faSwyllys 
2214*30a5e8faSwyllys /*
2215*30a5e8faSwyllys  * This API is used by elfsign. We must keep it in old API form.
2216*30a5e8faSwyllys  */
2217*30a5e8faSwyllys KMF_RETURN
2218*30a5e8faSwyllys KMF_Finalize(KMF_HANDLE_T handle)
2219*30a5e8faSwyllys {
2220*30a5e8faSwyllys 	return (kmf_finalize(handle));
2221*30a5e8faSwyllys }
2222*30a5e8faSwyllys 
2223*30a5e8faSwyllys /*
2224*30a5e8faSwyllys  * This API is used by elfsign. We must keep it in old API form.
2225*30a5e8faSwyllys  */
2226*30a5e8faSwyllys KMF_RETURN
2227*30a5e8faSwyllys KMF_GetKMFErrorString(KMF_RETURN errcode, char **errmsg)
2228*30a5e8faSwyllys {
2229*30a5e8faSwyllys 	return (kmf_get_kmf_error_str(errcode, errmsg));
2230*30a5e8faSwyllys }
2231*30a5e8faSwyllys 
2232*30a5e8faSwyllys /*
2233*30a5e8faSwyllys  * This API is used by elfsign. We must keep it in old API form.
2234*30a5e8faSwyllys  */
2235*30a5e8faSwyllys KMF_RETURN
2236*30a5e8faSwyllys KMF_ReadInputFile(KMF_HANDLE_T handle, char *filename,  KMF_DATA *pdata)
2237*30a5e8faSwyllys {
2238*30a5e8faSwyllys 	return (kmf_read_input_file(handle, filename, pdata));
2239*30a5e8faSwyllys }
2240*30a5e8faSwyllys 
2241*30a5e8faSwyllys 
2242*30a5e8faSwyllys /*
2243*30a5e8faSwyllys  * This API is used by elfsign. We must keep it in old API form.
2244*30a5e8faSwyllys  */
2245*30a5e8faSwyllys void
2246*30a5e8faSwyllys KMF_FreeKMFCert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
2247*30a5e8faSwyllys {
2248*30a5e8faSwyllys 	kmf_free_kmf_cert(handle, kmf_cert);
2249*30a5e8faSwyllys }
2250*30a5e8faSwyllys 
2251*30a5e8faSwyllys /*
2252*30a5e8faSwyllys  * This API is used by elfsign. We must keep it in old API form.
2253*30a5e8faSwyllys  */
2254*30a5e8faSwyllys void
2255*30a5e8faSwyllys KMF_FreeData(KMF_DATA *datablock)
2256*30a5e8faSwyllys {
2257*30a5e8faSwyllys 	kmf_free_data(datablock);
2258*30a5e8faSwyllys }
2259*30a5e8faSwyllys 
2260*30a5e8faSwyllys /*
2261*30a5e8faSwyllys  * This API is used by elfsign. We must keep it in old API form.
2262*30a5e8faSwyllys  */
2263*30a5e8faSwyllys void
2264*30a5e8faSwyllys KMF_FreeKMFKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key)
2265*30a5e8faSwyllys {
2266*30a5e8faSwyllys 	kmf_free_kmf_key(handle, key);
2267*30a5e8faSwyllys }
2268*30a5e8faSwyllys 
2269*30a5e8faSwyllys /*
2270*30a5e8faSwyllys  * This API is used by elfsign. We must keep it in old API form.
2271*30a5e8faSwyllys  */
2272*30a5e8faSwyllys void
2273*30a5e8faSwyllys KMF_FreeSignedCSR(KMF_CSR_DATA *csr)
2274*30a5e8faSwyllys {
2275*30a5e8faSwyllys 	kmf_free_signed_csr(csr);
2276*30a5e8faSwyllys }
2277