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 
14399ebb4caSwyllys 
14499ebb4caSwyllys static void free_extensions(KMF_X509_EXTENSIONS *extns);
14599ebb4caSwyllys 
146*9b37d296Swyllys KMF_RETURN
147*9b37d296Swyllys init_pk11()
14899ebb4caSwyllys {
149*9b37d296Swyllys 	(void) mutex_lock(&init_lock);
150*9b37d296Swyllys 	if (!pkcs11_initialized) {
151*9b37d296Swyllys 		CK_RV rv = C_Initialize(NULL);
152*9b37d296Swyllys 		if ((rv != CKR_OK) &&
153*9b37d296Swyllys 		    (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
154*9b37d296Swyllys 			(void) mutex_unlock(&init_lock);
155*9b37d296Swyllys 			return (KMF_ERR_UNINITIALIZED);
156*9b37d296Swyllys 		} else {
157*9b37d296Swyllys 			pkcs11_initialized = 1;
158*9b37d296Swyllys 		}
159*9b37d296Swyllys 	}
160*9b37d296Swyllys 	(void) mutex_unlock(&init_lock);
161*9b37d296Swyllys 	return (KMF_OK);
16299ebb4caSwyllys }
16399ebb4caSwyllys 
16499ebb4caSwyllys /*
16599ebb4caSwyllys  * Private method for searching the plugin list for the correct
16699ebb4caSwyllys  * Plugin to use.
16799ebb4caSwyllys  */
16899ebb4caSwyllys KMF_PLUGIN *
16999ebb4caSwyllys FindPlugin(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE kstype)
17099ebb4caSwyllys {
17199ebb4caSwyllys 	KMF_PLUGIN_LIST *node;
17299ebb4caSwyllys 
17399ebb4caSwyllys 	if (handle == NULL)
17499ebb4caSwyllys 		return (NULL);
17599ebb4caSwyllys 
17699ebb4caSwyllys 	node = handle->plugins;
17799ebb4caSwyllys 
17899ebb4caSwyllys 	while (node != NULL && node->plugin->type != kstype)
17999ebb4caSwyllys 		node = node->next;
18099ebb4caSwyllys 
18199ebb4caSwyllys 	/* If it is NULL, that is indication enough of an error */
18299ebb4caSwyllys 	return (node ? node->plugin : NULL);
18399ebb4caSwyllys }
18499ebb4caSwyllys 
18599ebb4caSwyllys static KMF_RETURN
18699ebb4caSwyllys InitializePlugin(KMF_KEYSTORE_TYPE kstype, char *path, KMF_PLUGIN **plugin)
18799ebb4caSwyllys {
18899ebb4caSwyllys 	KMF_PLUGIN *p = NULL;
18999ebb4caSwyllys 	KMF_PLUGIN_FUNCLIST *(*sym)();
19099ebb4caSwyllys 
19199ebb4caSwyllys 	if (path == NULL || plugin == NULL)
19299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
19399ebb4caSwyllys 
19499ebb4caSwyllys 	*plugin = NULL;
19599ebb4caSwyllys 
19699ebb4caSwyllys 	p = (KMF_PLUGIN *)malloc(sizeof (KMF_PLUGIN));
19799ebb4caSwyllys 	if (p == NULL)
19899ebb4caSwyllys 		return (KMF_ERR_MEMORY);
19999ebb4caSwyllys 
20099ebb4caSwyllys 	p->type = kstype;
20199ebb4caSwyllys 	p->path = strdup(path);
20299ebb4caSwyllys 	if (p->path == NULL) {
20399ebb4caSwyllys 		free(p);
20499ebb4caSwyllys 		return (KMF_ERR_MEMORY);
20599ebb4caSwyllys 	}
20699ebb4caSwyllys 	p->dldesc = dlopen(path, RTLD_NOW | RTLD_GROUP | RTLD_PARENT);
20799ebb4caSwyllys 	if (p->dldesc == NULL) {
20899ebb4caSwyllys 		free(p->path);
20999ebb4caSwyllys 		free(p);
21099ebb4caSwyllys 		return (KMF_ERR_PLUGIN_INIT);
21199ebb4caSwyllys 	}
21299ebb4caSwyllys 
21399ebb4caSwyllys 	sym = (KMF_PLUGIN_FUNCLIST *(*)())dlsym(p->dldesc,
21499ebb4caSwyllys 		KMF_PLUGIN_INIT_SYMBOL);
21599ebb4caSwyllys 	if (sym == NULL) {
21699ebb4caSwyllys 		(void) dlclose(p->dldesc);
21799ebb4caSwyllys 		free(p->path);
21899ebb4caSwyllys 		free(p);
21999ebb4caSwyllys 		return (KMF_ERR_PLUGIN_INIT);
22099ebb4caSwyllys 	}
22199ebb4caSwyllys 
22299ebb4caSwyllys 	/* Get the function list */
22399ebb4caSwyllys 	if ((p->funclist = (*sym)()) == NULL) {
22499ebb4caSwyllys 		(void) dlclose(p->dldesc);
22599ebb4caSwyllys 		free(p->path);
22699ebb4caSwyllys 		free(p);
22799ebb4caSwyllys 		return (KMF_ERR_PLUGIN_INIT);
22899ebb4caSwyllys 	}
22999ebb4caSwyllys 
23099ebb4caSwyllys 	*plugin = p;
23199ebb4caSwyllys 
23299ebb4caSwyllys 	return (KMF_OK);
23399ebb4caSwyllys }
23499ebb4caSwyllys 
23599ebb4caSwyllys static KMF_RETURN
23699ebb4caSwyllys AddPlugin(KMF_HANDLE_T handle, KMF_PLUGIN *plugin)
23799ebb4caSwyllys {
23899ebb4caSwyllys 	KMF_PLUGIN_LIST *n;
23999ebb4caSwyllys 
24099ebb4caSwyllys 	if (handle == NULL || plugin == NULL)
24199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
24299ebb4caSwyllys 
24399ebb4caSwyllys 	/* If the head is NULL, create it */
24499ebb4caSwyllys 	if (handle->plugins == NULL) {
24599ebb4caSwyllys 		handle->plugins = (KMF_PLUGIN_LIST *)malloc(
24699ebb4caSwyllys 			sizeof (KMF_PLUGIN_LIST));
24799ebb4caSwyllys 		if (handle->plugins == NULL)
24899ebb4caSwyllys 			return (KMF_ERR_MEMORY);
24999ebb4caSwyllys 		handle->plugins->plugin = plugin;
25099ebb4caSwyllys 		handle->plugins->next = NULL;
25199ebb4caSwyllys 	} else {
25299ebb4caSwyllys 		/* walk the list to find the tail */
25399ebb4caSwyllys 		n = handle->plugins;
25499ebb4caSwyllys 		while (n->next != NULL)
25599ebb4caSwyllys 			n = n->next;
25699ebb4caSwyllys 		n->next = (KMF_PLUGIN_LIST *)malloc(sizeof (KMF_PLUGIN_LIST));
25799ebb4caSwyllys 		if (n->next == NULL)
25899ebb4caSwyllys 			return (KMF_ERR_MEMORY);
25999ebb4caSwyllys 
26099ebb4caSwyllys 		n->next->plugin = plugin;
26199ebb4caSwyllys 		n->next->next = NULL;
26299ebb4caSwyllys 	}
26399ebb4caSwyllys 	return (0);
26499ebb4caSwyllys }
26599ebb4caSwyllys 
26699ebb4caSwyllys static void
26799ebb4caSwyllys DestroyPlugin(KMF_PLUGIN *plugin)
26899ebb4caSwyllys {
26999ebb4caSwyllys 	if (plugin) {
27099ebb4caSwyllys 		if (plugin->path)
27199ebb4caSwyllys 			free(plugin->path);
27299ebb4caSwyllys 		free(plugin);
27399ebb4caSwyllys 	}
27499ebb4caSwyllys }
27599ebb4caSwyllys 
27699ebb4caSwyllys static void
27799ebb4caSwyllys Cleanup_KMF_Handle(KMF_HANDLE_T handle)
27899ebb4caSwyllys {
27999ebb4caSwyllys 	if (handle != NULL) {
28099ebb4caSwyllys 		while (handle->plugins != NULL) {
28199ebb4caSwyllys 			KMF_PLUGIN_LIST *next = handle->plugins->next;
28299ebb4caSwyllys 
28399ebb4caSwyllys 			DestroyPlugin(handle->plugins->plugin);
28499ebb4caSwyllys 
28599ebb4caSwyllys 			free(handle->plugins);
28699ebb4caSwyllys 
28799ebb4caSwyllys 			handle->plugins = next;
28899ebb4caSwyllys 		}
28999ebb4caSwyllys 
29099ebb4caSwyllys 		KMF_FreePolicyRecord(handle->policy);
29199ebb4caSwyllys 		free(handle->policy);
29299ebb4caSwyllys 	}
29399ebb4caSwyllys 	free(handle);
29499ebb4caSwyllys }
29599ebb4caSwyllys 
29699ebb4caSwyllys void
29799ebb4caSwyllys Cleanup_PK11_Session(KMF_HANDLE_T handle)
29899ebb4caSwyllys {
29999ebb4caSwyllys 	if (handle != NULL) {
30099ebb4caSwyllys 		/* Close active session on a pkcs11 token */
30199ebb4caSwyllys 		if (handle->pk11handle != NULL) {
30299ebb4caSwyllys 			(void) C_CloseSession(handle->pk11handle);
30399ebb4caSwyllys 			handle->pk11handle = NULL;
30499ebb4caSwyllys 		}
30599ebb4caSwyllys 	}
30699ebb4caSwyllys }
30799ebb4caSwyllys 
30899ebb4caSwyllys KMF_RETURN
30999ebb4caSwyllys KMF_Initialize(KMF_HANDLE_T *outhandle, char *policyfile, char *policyname)
31099ebb4caSwyllys {
31199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
31299ebb4caSwyllys 	KMF_HANDLE *handle = NULL;
31399ebb4caSwyllys 	KMF_PLUGIN *pluginrec = NULL;
31499ebb4caSwyllys 
31599ebb4caSwyllys 	if (outhandle == NULL)
31699ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
31799ebb4caSwyllys 
31899ebb4caSwyllys 	*outhandle = NULL;
31999ebb4caSwyllys 	handle = (KMF_HANDLE *)malloc(sizeof (KMF_HANDLE));
32099ebb4caSwyllys 	if (handle == NULL)
32199ebb4caSwyllys 		return (KMF_ERR_MEMORY);
32299ebb4caSwyllys 
32399ebb4caSwyllys 	(void) memset(handle, 0, sizeof (KMF_HANDLE));
32499ebb4caSwyllys 	handle->plugins = NULL;
32599ebb4caSwyllys 
32699ebb4caSwyllys 
32799ebb4caSwyllys 	/* Initialize the handle with the policy */
32899ebb4caSwyllys 	ret = KMF_SetPolicy((void *)handle,
32999ebb4caSwyllys 	    policyfile == NULL ? KMF_DEFAULT_POLICY_FILE : policyfile,
33099ebb4caSwyllys 	    policyname == NULL ? KMF_DEFAULT_POLICY_NAME : policyname);
33199ebb4caSwyllys 	if (ret != KMF_OK)
33299ebb4caSwyllys 		goto errout;
33399ebb4caSwyllys 
33499ebb4caSwyllys 	/* Create a record for the plugin */
33599ebb4caSwyllys 	if ((ret = InitializePlugin(KMF_KEYSTORE_NSS,
33699ebb4caSwyllys 		KMF_PLUGIN_PATH "kmf_nss.so.1", &pluginrec)) != KMF_OK)
33799ebb4caSwyllys 		goto errout;
33899ebb4caSwyllys 
33999ebb4caSwyllys 	/* Add it to the handle */
34099ebb4caSwyllys 	if (pluginrec != NULL) {
34199ebb4caSwyllys 		if ((ret = AddPlugin(handle, pluginrec)))
34299ebb4caSwyllys 			goto errout;
34399ebb4caSwyllys 	}
34499ebb4caSwyllys 	if ((ret = InitializePlugin(KMF_KEYSTORE_OPENSSL,
34599ebb4caSwyllys 		KMF_PLUGIN_PATH "kmf_openssl.so.1", &pluginrec)) != KMF_OK)
34699ebb4caSwyllys 		goto errout;
34799ebb4caSwyllys 
34899ebb4caSwyllys 	/* Add it to the handle */
34999ebb4caSwyllys 	if (pluginrec != NULL)
35099ebb4caSwyllys 		if ((ret = AddPlugin(handle, pluginrec)))
35199ebb4caSwyllys 			goto errout;
35299ebb4caSwyllys 
35399ebb4caSwyllys 	if ((ret = InitializePlugin(KMF_KEYSTORE_PK11TOKEN,
35499ebb4caSwyllys 		KMF_PLUGIN_PATH "kmf_pkcs11.so.1", &pluginrec)) != KMF_OK)
35599ebb4caSwyllys 		goto errout;
35699ebb4caSwyllys 
35799ebb4caSwyllys 	/* Add it to the handle */
35899ebb4caSwyllys 	if (pluginrec != NULL)
35999ebb4caSwyllys 		if ((ret = AddPlugin(handle, pluginrec)))
36099ebb4caSwyllys 			goto errout;
36199ebb4caSwyllys 
36299ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
36399ebb4caSwyllys errout:
36499ebb4caSwyllys 	if (ret != KMF_OK) {
36599ebb4caSwyllys 		Cleanup_KMF_Handle(handle);
36699ebb4caSwyllys 		handle = NULL;
36799ebb4caSwyllys 	}
36899ebb4caSwyllys 
36999ebb4caSwyllys 	*outhandle = (KMF_HANDLE_T)handle;
37099ebb4caSwyllys 	return (ret);
37199ebb4caSwyllys }
37299ebb4caSwyllys 
37399ebb4caSwyllys KMF_RETURN
37499ebb4caSwyllys KMF_ConfigureKeystore(KMF_HANDLE_T handle, KMF_CONFIG_PARAMS *params)
37599ebb4caSwyllys {
37699ebb4caSwyllys 	KMF_PLUGIN *plugin;
37799ebb4caSwyllys 	KMF_RETURN ret;
37899ebb4caSwyllys 
37999ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
38099ebb4caSwyllys 	if (ret != KMF_OK)
38199ebb4caSwyllys 		return (ret);
38299ebb4caSwyllys 
38399ebb4caSwyllys 	if (params == NULL)
38499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
38599ebb4caSwyllys 
38699ebb4caSwyllys 	plugin = FindPlugin(handle, params->kstype);
38799ebb4caSwyllys 	if (plugin == NULL)
38899ebb4caSwyllys 		return (KMF_ERR_PLUGIN_NOTFOUND);
38999ebb4caSwyllys 
39099ebb4caSwyllys 	if (plugin->funclist->ConfigureKeystore != NULL)
39199ebb4caSwyllys 		return (plugin->funclist->ConfigureKeystore(handle, params));
39299ebb4caSwyllys 	else
39399ebb4caSwyllys 		/* return KMF_OK, if the plugin does not have an entry */
39499ebb4caSwyllys 		return (KMF_OK);
39599ebb4caSwyllys }
39699ebb4caSwyllys 
39799ebb4caSwyllys KMF_RETURN
39899ebb4caSwyllys KMF_Finalize(KMF_HANDLE_T handle)
39999ebb4caSwyllys {
40099ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
40199ebb4caSwyllys 
40299ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
40399ebb4caSwyllys 	if (ret != KMF_OK)
40499ebb4caSwyllys 		return (ret);
40599ebb4caSwyllys 
40699ebb4caSwyllys 	if (pkcs11_initialized) {
40799ebb4caSwyllys 		Cleanup_PK11_Session(handle);
40899ebb4caSwyllys 	}
40999ebb4caSwyllys 	Cleanup_KMF_Handle(handle);
41099ebb4caSwyllys 
41199ebb4caSwyllys 	return (ret);
41299ebb4caSwyllys }
41399ebb4caSwyllys 
41499ebb4caSwyllys KMF_RETURN
41599ebb4caSwyllys KMF_GetKMFErrorString(KMF_RETURN errcode, char **errmsg)
41699ebb4caSwyllys {
41799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
41899ebb4caSwyllys 	int i, maxerr;
41999ebb4caSwyllys 
42099ebb4caSwyllys 	if (errmsg == NULL)
42199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
42299ebb4caSwyllys 
42399ebb4caSwyllys 	*errmsg = NULL;
42499ebb4caSwyllys 	maxerr = sizeof (kmf_errcodes) / sizeof (kmf_error_map);
42599ebb4caSwyllys 
42699ebb4caSwyllys 	for (i = 0; i < maxerr && errcode != kmf_errcodes[i].code; i++);
42799ebb4caSwyllys 
42899ebb4caSwyllys 	if (i == maxerr)
42999ebb4caSwyllys 		return (KMF_ERR_MISSING_ERRCODE);
43099ebb4caSwyllys 	else {
43199ebb4caSwyllys 		*errmsg = strdup(kmf_errcodes[i].message);
43299ebb4caSwyllys 		if ((*errmsg) == NULL)
43399ebb4caSwyllys 			return (KMF_ERR_MEMORY);
43499ebb4caSwyllys 	}
43599ebb4caSwyllys 	return (ret);
43699ebb4caSwyllys }
43799ebb4caSwyllys 
43899ebb4caSwyllys KMF_RETURN
43999ebb4caSwyllys KMF_GetPluginErrorString(KMF_HANDLE_T handle, char **msgstr)
44099ebb4caSwyllys {
44199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
44299ebb4caSwyllys 	KMF_PLUGIN *plugin;
44399ebb4caSwyllys 
44499ebb4caSwyllys 	if (handle == NULL || msgstr == NULL)
44599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
44699ebb4caSwyllys 
44799ebb4caSwyllys 	*msgstr = NULL;
44899ebb4caSwyllys 
44999ebb4caSwyllys 	if (handle->lasterr.errcode == 0) {
45099ebb4caSwyllys 		return (KMF_ERR_MISSING_ERRCODE);
45199ebb4caSwyllys 	}
45299ebb4caSwyllys 
45399ebb4caSwyllys 	if (handle->lasterr.kstype == -1) { /* System error */
45499ebb4caSwyllys 		char *str = strerror(handle->lasterr.errcode);
45599ebb4caSwyllys 		if (str != NULL) {
45699ebb4caSwyllys 			*msgstr = strdup(str);
45799ebb4caSwyllys 			if ((*msgstr) == NULL)
45899ebb4caSwyllys 				return (KMF_ERR_MEMORY);
45999ebb4caSwyllys 		}
46099ebb4caSwyllys 		return (KMF_OK);
46199ebb4caSwyllys 	}
46299ebb4caSwyllys 
46399ebb4caSwyllys 	plugin = FindPlugin(handle, handle->lasterr.kstype);
46499ebb4caSwyllys 	if (plugin == NULL)
46599ebb4caSwyllys 		return (KMF_ERR_PLUGIN_NOTFOUND);
46699ebb4caSwyllys 
46799ebb4caSwyllys 	if (plugin->funclist->GetErrorString != NULL) {
46899ebb4caSwyllys 		ret = plugin->funclist->GetErrorString(handle, msgstr);
46999ebb4caSwyllys 	} else {
47099ebb4caSwyllys 		return (KMF_ERR_FUNCTION_NOT_FOUND);
47199ebb4caSwyllys 	}
47299ebb4caSwyllys 
47399ebb4caSwyllys 	return (ret);
47499ebb4caSwyllys }
47599ebb4caSwyllys 
47699ebb4caSwyllys KMF_RETURN
47799ebb4caSwyllys KMF_DNParser(char *string, KMF_X509_NAME *name)
47899ebb4caSwyllys {
47999ebb4caSwyllys 	KMF_RETURN err;
48099ebb4caSwyllys 
48199ebb4caSwyllys 	if (string == NULL || name == NULL)
48299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
48399ebb4caSwyllys 
48499ebb4caSwyllys 	err = ParseDistinguishedName(string, (int)strlen(string), name);
48599ebb4caSwyllys 	return (err);
48699ebb4caSwyllys }
48799ebb4caSwyllys 
48899ebb4caSwyllys KMF_RETURN
48999ebb4caSwyllys KMF_DN2Der(KMF_X509_NAME *dn, KMF_DATA *der)
49099ebb4caSwyllys {
49199ebb4caSwyllys 	KMF_RETURN rv;
49299ebb4caSwyllys 
49399ebb4caSwyllys 	if (dn == NULL || der == NULL)
49499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
49599ebb4caSwyllys 
49699ebb4caSwyllys 	rv = DerEncodeName(dn, der);
49799ebb4caSwyllys 	return (rv);
49899ebb4caSwyllys }
49999ebb4caSwyllys 
500*9b37d296Swyllys #define	SET_SYS_ERROR(h, c) if (h) {\
501*9b37d296Swyllys 	h->lasterr.kstype = -1;\
502*9b37d296Swyllys 	h->lasterr.errcode = c;\
503*9b37d296Swyllys }
50499ebb4caSwyllys 
50599ebb4caSwyllys KMF_RETURN
50699ebb4caSwyllys KMF_ReadInputFile(KMF_HANDLE_T handle, char *filename,  KMF_DATA *pdata)
50799ebb4caSwyllys {
50899ebb4caSwyllys 	struct stat s;
50999ebb4caSwyllys 	long nread, total = 0;
51099ebb4caSwyllys 	int fd;
51199ebb4caSwyllys 	unsigned char *buf = NULL;
51299ebb4caSwyllys 	KMF_RETURN ret;
51399ebb4caSwyllys 
514*9b37d296Swyllys 	if (handle) {
515*9b37d296Swyllys 		CLEAR_ERROR(handle, ret);
516*9b37d296Swyllys 		if (ret != KMF_OK)
517*9b37d296Swyllys 			return (ret);
518*9b37d296Swyllys 	}
51999ebb4caSwyllys 
52099ebb4caSwyllys 	if (filename == NULL || pdata == NULL) {
52199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
52299ebb4caSwyllys 	}
52399ebb4caSwyllys 
52499ebb4caSwyllys 	if ((fd = open(filename, O_RDONLY)) < 0) {
52599ebb4caSwyllys 		SET_SYS_ERROR(handle, errno);
52699ebb4caSwyllys 		return (KMF_ERR_OPEN_FILE);
52799ebb4caSwyllys 	}
52899ebb4caSwyllys 
52999ebb4caSwyllys 	if (fstat(fd, &s) < 0) {
53099ebb4caSwyllys 		SET_SYS_ERROR(handle, errno);
53199ebb4caSwyllys 		(void) close(fd);
53299ebb4caSwyllys 		return (KMF_ERR_OPEN_FILE);
53399ebb4caSwyllys 	}
53499ebb4caSwyllys 
53599ebb4caSwyllys 	if ((buf = (unsigned char *) malloc(s.st_size)) == NULL) {
53699ebb4caSwyllys 		(void) close(fd);
53799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
53899ebb4caSwyllys 	}
53999ebb4caSwyllys 
54099ebb4caSwyllys 	do {
54199ebb4caSwyllys 		nread = read(fd, buf+total, s.st_size-total);
54299ebb4caSwyllys 		if (nread < 0) {
54399ebb4caSwyllys 			SET_SYS_ERROR(handle, errno);
54499ebb4caSwyllys 			(void) close(fd);
54599ebb4caSwyllys 			free(buf);
54699ebb4caSwyllys 			return (KMF_ERR_INTERNAL);
54799ebb4caSwyllys 		}
54899ebb4caSwyllys 		total += nread;
54999ebb4caSwyllys 	} while (total < s.st_size);
55099ebb4caSwyllys 
55199ebb4caSwyllys 	pdata->Data = buf;
55299ebb4caSwyllys 	pdata->Length = s.st_size;
55399ebb4caSwyllys 	(void) close(fd);
55499ebb4caSwyllys 	return (KMF_OK);
55599ebb4caSwyllys }
55699ebb4caSwyllys 
55799ebb4caSwyllys /*
55899ebb4caSwyllys  *
55999ebb4caSwyllys  * Name: KMF_Der2Pem
56099ebb4caSwyllys  *
56199ebb4caSwyllys  * Description:
56299ebb4caSwyllys  *   Function for converting DER encoded format to PEM encoded format
56399ebb4caSwyllys  *
56499ebb4caSwyllys  * Parameters:
56599ebb4caSwyllys  *   type(input) - CERTIFICATE or CSR
56699ebb4caSwyllys  *   data(input) - pointer to the DER encoded data
56799ebb4caSwyllys  *   len(input)  - length of input data
56899ebb4caSwyllys  *   out(output) - contains the output buffer address to be returned
56999ebb4caSwyllys  *   outlen(output) - pointer to the returned output length
57099ebb4caSwyllys  *
57199ebb4caSwyllys  * Returns:
57299ebb4caSwyllys  *   A KMF_RETURN value indicating success or specifying a particular
57399ebb4caSwyllys  * error condition.
57499ebb4caSwyllys  *   The value KMF_OK indicates success. All other values represent
57599ebb4caSwyllys  * an error condition.
57699ebb4caSwyllys  *
57799ebb4caSwyllys  */
57899ebb4caSwyllys KMF_RETURN
57999ebb4caSwyllys KMF_Der2Pem(KMF_OBJECT_TYPE type, unsigned char *data,
58099ebb4caSwyllys 	int len, unsigned char **out, int *outlen)
58199ebb4caSwyllys {
58299ebb4caSwyllys 
58399ebb4caSwyllys 	KMF_RETURN err;
58499ebb4caSwyllys 	if (data == NULL || out == NULL || outlen == NULL)
58599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
58699ebb4caSwyllys 
58799ebb4caSwyllys 	err = Der2Pem(type, data, len, out, outlen);
58899ebb4caSwyllys 	return (err);
58999ebb4caSwyllys 
59099ebb4caSwyllys }
59199ebb4caSwyllys 
59299ebb4caSwyllys /*
59399ebb4caSwyllys  *
59499ebb4caSwyllys  * Name: KMF_Pem2Der
59599ebb4caSwyllys  *
59699ebb4caSwyllys  * Description:
59799ebb4caSwyllys  *   Function for converting PEM encoded format to DER encoded format
59899ebb4caSwyllys  *
59999ebb4caSwyllys  * Parameters:
60099ebb4caSwyllys  *   in(input) - pointer to the PEM encoded data
60199ebb4caSwyllys  *   inlen(input)  - length of input data
60299ebb4caSwyllys  *   out(output) - contains the output buffer address to be returned
60399ebb4caSwyllys  *   outlen(output) - pointer to the returned output length
60499ebb4caSwyllys  *
60599ebb4caSwyllys  * Returns:
60699ebb4caSwyllys  *   A KMF_RETURN value indicating success or specifying a particular
60799ebb4caSwyllys  *   error condition.
60899ebb4caSwyllys  *   The value KMF_OK indicates success. All other values represent
60999ebb4caSwyllys  *   an error condition.
61099ebb4caSwyllys  *
61199ebb4caSwyllys  */
61299ebb4caSwyllys KMF_RETURN
61399ebb4caSwyllys KMF_Pem2Der(unsigned char *in, int inlen,
61499ebb4caSwyllys 	unsigned char **out, int *outlen)
61599ebb4caSwyllys {
61699ebb4caSwyllys 	KMF_RETURN err;
61799ebb4caSwyllys 	if (in == NULL || out == NULL || outlen == NULL)
61899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
61999ebb4caSwyllys 
62099ebb4caSwyllys 	err = Pem2Der(in, inlen, out, outlen);
62199ebb4caSwyllys 	return (err);
62299ebb4caSwyllys }
62399ebb4caSwyllys 
62499ebb4caSwyllys char *
62599ebb4caSwyllys KMF_OID2String(KMF_OID *oid)
62699ebb4caSwyllys {
62799ebb4caSwyllys 	char numstr[128];
62899ebb4caSwyllys 	uint32_t number;
62999ebb4caSwyllys 	int numshift;
63099ebb4caSwyllys 	uint32_t i, string_length;
63199ebb4caSwyllys 	uchar_t *cp;
63299ebb4caSwyllys 	char *bp;
63399ebb4caSwyllys 
63499ebb4caSwyllys 	/* First determine the size of the string */
63599ebb4caSwyllys 	string_length = 0;
63699ebb4caSwyllys 	number = 0;
63799ebb4caSwyllys 	numshift = 0;
63899ebb4caSwyllys 	cp = (unsigned char *)oid->Data;
63999ebb4caSwyllys 
64099ebb4caSwyllys 	number = (uint32_t)cp[0];
64199ebb4caSwyllys 	(void) sprintf(numstr, "%d ", number/40);
64299ebb4caSwyllys 
64399ebb4caSwyllys 	string_length += strlen(numstr);
64499ebb4caSwyllys 	(void) sprintf(numstr, "%d ", number%40);
64599ebb4caSwyllys 
64699ebb4caSwyllys 	string_length += strlen(numstr);
64799ebb4caSwyllys 
64899ebb4caSwyllys 	for (i = 1; i < oid->Length; i++) {
64999ebb4caSwyllys 		if ((uint32_t)(numshift+7) < (sizeof (uint32_t)*8)) {
65099ebb4caSwyllys 			number = (number << 7) | (cp[i] & 0x7f);
65199ebb4caSwyllys 			numshift += 7;
65299ebb4caSwyllys 		} else {
65399ebb4caSwyllys 			return (NULL);
65499ebb4caSwyllys 		}
65599ebb4caSwyllys 
65699ebb4caSwyllys 		if ((cp[i] & 0x80) == 0) {
65799ebb4caSwyllys 			(void) sprintf(numstr, "%d ", number);
65899ebb4caSwyllys 			string_length += strlen(numstr);
65999ebb4caSwyllys 			number = 0;
66099ebb4caSwyllys 			numshift = 0;
66199ebb4caSwyllys 		}
66299ebb4caSwyllys 	}
66399ebb4caSwyllys 	/*
66499ebb4caSwyllys 	 * If we get here, we've calculated the length of "n n n ... n ".  Add 4
66599ebb4caSwyllys 	 * here for "{ " and "}\0".
66699ebb4caSwyllys 	 */
66799ebb4caSwyllys 	string_length += 4;
66899ebb4caSwyllys 	if ((bp = (char *)malloc(string_length))) {
66999ebb4caSwyllys 		number = (uint32_t)cp[0];
67099ebb4caSwyllys 
67199ebb4caSwyllys 		(void) sprintf(numstr, "%d.", number/40);
67299ebb4caSwyllys 		(void) strcpy(bp, numstr);
67399ebb4caSwyllys 
67499ebb4caSwyllys 		(void) sprintf(numstr, "%d.", number%40);
67599ebb4caSwyllys 		(void) strcat(bp, numstr);
67699ebb4caSwyllys 
67799ebb4caSwyllys 		number = 0;
67899ebb4caSwyllys 		cp = (unsigned char *) oid->Data;
67999ebb4caSwyllys 		for (i = 1; i < oid->Length; i++) {
68099ebb4caSwyllys 			number = (number << 7) | (cp[i] & 0x7f);
68199ebb4caSwyllys 			if ((cp[i] & 0x80) == 0) {
68299ebb4caSwyllys 				(void) sprintf(numstr, "%d", number);
68399ebb4caSwyllys 				(void) strcat(bp, numstr);
68499ebb4caSwyllys 				number = 0;
68599ebb4caSwyllys 				if (i+1 < oid->Length)
68699ebb4caSwyllys 					(void) strcat(bp, ".");
68799ebb4caSwyllys 			}
68899ebb4caSwyllys 		}
68999ebb4caSwyllys 	}
69099ebb4caSwyllys 	return (bp);
69199ebb4caSwyllys }
69299ebb4caSwyllys 
69302744e81Swyllys static boolean_t
69402744e81Swyllys check_for_pem(char *filename)
69502744e81Swyllys {
696*9b37d296Swyllys 	KMF_DATA filebuf;
697*9b37d296Swyllys 	KMF_RETURN rv;
698*9b37d296Swyllys 	char *p;
69902744e81Swyllys 
700*9b37d296Swyllys 	rv = KMF_ReadInputFile(NULL, filename, &filebuf);
701*9b37d296Swyllys 	if (rv != KMF_OK)
70202744e81Swyllys 		return (FALSE);
70302744e81Swyllys 
704*9b37d296Swyllys 	/* Look for "-----BEGIN" right after a newline */
705*9b37d296Swyllys 	p = strtok((char *)filebuf.Data, "\n");
706*9b37d296Swyllys 	while (p != NULL) {
707*9b37d296Swyllys 		if (strstr(p, "-----BEGIN") != NULL) {
708*9b37d296Swyllys 			free(filebuf.Data);
709*9b37d296Swyllys 			return (TRUE);
71002744e81Swyllys 		}
711*9b37d296Swyllys 		p = strtok(NULL, "\n");
71202744e81Swyllys 	}
713*9b37d296Swyllys 	free(filebuf.Data);
71402744e81Swyllys 	return (FALSE);
71502744e81Swyllys }
71602744e81Swyllys 
71799ebb4caSwyllys KMF_RETURN
71899ebb4caSwyllys KMF_GetFileFormat(char *filename, KMF_ENCODE_FORMAT *fmt)
71999ebb4caSwyllys {
72099ebb4caSwyllys 	int f;
72199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
72299ebb4caSwyllys 	uchar_t buf[16];
72399ebb4caSwyllys 
72499ebb4caSwyllys 	if (filename == NULL || !strlen(filename) || fmt == NULL)
72599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
72699ebb4caSwyllys 
72799ebb4caSwyllys 	*fmt = 0;
72899ebb4caSwyllys 	if ((f = open(filename, O_RDONLY)) == -1) {
72999ebb4caSwyllys 		return (KMF_ERR_OPEN_FILE);
73099ebb4caSwyllys 	}
73199ebb4caSwyllys 
73299ebb4caSwyllys 	if (read(f, buf, 8) != 8) {
73399ebb4caSwyllys 		ret = KMF_ERR_OPEN_FILE;
73499ebb4caSwyllys 		goto end;
73599ebb4caSwyllys 	}
73699ebb4caSwyllys 
73702744e81Swyllys 	(void) close(f);
73802744e81Swyllys 	if (buf[0] == 0x30 && (buf[1] & 0x80)) {
73999ebb4caSwyllys 		if ((buf[1] & 0xFF) == 0x80 &&
74099ebb4caSwyllys 		    (buf[2] & 0xFF) == 0x02 &&
74199ebb4caSwyllys 		    (buf[5] & 0xFF) == 0x30) {
74299ebb4caSwyllys 			*fmt = KMF_FORMAT_PKCS12;
74399ebb4caSwyllys 		} else if ((buf[1] & 0xFF) == 0x82 &&
74499ebb4caSwyllys 			(buf[4] & 0xFF) == 0x02 &&
74599ebb4caSwyllys 			(buf[7] & 0xFF) == 0x30) {
74699ebb4caSwyllys 			*fmt = KMF_FORMAT_PKCS12;
74799ebb4caSwyllys 		/* It is most likely a generic ASN.1 encoded file */
74899ebb4caSwyllys 		} else {
74999ebb4caSwyllys 			*fmt = KMF_FORMAT_ASN1;
75099ebb4caSwyllys 		}
75171593db2Swyllys 	} else if (memcmp(buf, "Bag Attr", 8) == 0) {
75271593db2Swyllys 		*fmt = KMF_FORMAT_PEM_KEYPAIR;
75399ebb4caSwyllys 	} else {
75402744e81Swyllys 		/* Try PEM */
75502744e81Swyllys 		if (check_for_pem(filename) == TRUE) {
75602744e81Swyllys 			*fmt = KMF_FORMAT_PEM;
75702744e81Swyllys 		} else {
75802744e81Swyllys 			/* Cannot determine this file format */
75902744e81Swyllys 			*fmt = 0;
76002744e81Swyllys 			ret = KMF_ERR_ENCODING;
76102744e81Swyllys 		}
76299ebb4caSwyllys 	}
76399ebb4caSwyllys end:
76499ebb4caSwyllys 	return (ret);
76599ebb4caSwyllys }
76699ebb4caSwyllys 
76799ebb4caSwyllys KMF_RETURN
76899ebb4caSwyllys KMF_HexString2Bytes(unsigned char *hexstr, unsigned char **bytes,
76999ebb4caSwyllys 	size_t *outlen)
77099ebb4caSwyllys {
77199ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
77299ebb4caSwyllys 	unsigned char *buf = NULL;
77399ebb4caSwyllys 	int len, stringlen;
77499ebb4caSwyllys 	int i;
77599ebb4caSwyllys 	unsigned char ch;
77699ebb4caSwyllys 
77799ebb4caSwyllys 	if (hexstr == NULL) {
77899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
77999ebb4caSwyllys 	}
78099ebb4caSwyllys 
78199ebb4caSwyllys 	if (hexstr[0] == '0' &&
78299ebb4caSwyllys 		((hexstr[1] == 'x') || (hexstr[1] == 'X')))
78399ebb4caSwyllys 		hexstr += 2;
78499ebb4caSwyllys 
78599ebb4caSwyllys 	for (i = 0; i < strlen((char *)hexstr) && isxdigit(hexstr[i]); i++);
78699ebb4caSwyllys 	/*
78799ebb4caSwyllys 	 * If all the characters are not legitimate hex chars,
78899ebb4caSwyllys 	 * return an error.
78999ebb4caSwyllys 	 */
79099ebb4caSwyllys 	if (i != strlen((char *)hexstr))
79199ebb4caSwyllys 		return (KMF_ERR_BAD_HEX_STRING);
79299ebb4caSwyllys 	stringlen = i;
79399ebb4caSwyllys 	len = (i / 2) + (i % 2);
79499ebb4caSwyllys 
79599ebb4caSwyllys 	buf = malloc(len);
79699ebb4caSwyllys 	if (buf == NULL) {
79799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
79899ebb4caSwyllys 	}
79999ebb4caSwyllys 	(void) memset(buf, 0, len);
80099ebb4caSwyllys 
80199ebb4caSwyllys 	for (i = 0; i < stringlen; i++) {
80299ebb4caSwyllys 		ch = (unsigned char) *hexstr;
80399ebb4caSwyllys 		hexstr++;
80499ebb4caSwyllys 		if ((ch >= '0') && (ch <= '9'))
80599ebb4caSwyllys 			ch -= '0';
80699ebb4caSwyllys 		else if ((ch >= 'A') && (ch <= 'F'))
80799ebb4caSwyllys 			ch = ch - 'A' + 10;
80899ebb4caSwyllys 		else if ((ch >= 'a') && (ch <= 'f'))
80999ebb4caSwyllys 			ch = ch - 'a' + 10;
81099ebb4caSwyllys 		else {
81199ebb4caSwyllys 			ret = KMF_ERR_BAD_HEX_STRING;
81299ebb4caSwyllys 			goto out;
81399ebb4caSwyllys 		}
81499ebb4caSwyllys 
81599ebb4caSwyllys 		if (i & 1) {
81699ebb4caSwyllys 			buf[i/2] |= ch;
81799ebb4caSwyllys 		} else {
81899ebb4caSwyllys 			buf[i/2] = (ch << 4);
81999ebb4caSwyllys 		}
82099ebb4caSwyllys 	}
82199ebb4caSwyllys 
82299ebb4caSwyllys 	*bytes = buf;
82399ebb4caSwyllys 	*outlen = len;
82499ebb4caSwyllys out:
82599ebb4caSwyllys 	if (buf != NULL && ret != KMF_OK) {
82699ebb4caSwyllys 		free(buf);
82799ebb4caSwyllys 	}
82899ebb4caSwyllys 	return (ret);
82999ebb4caSwyllys }
83099ebb4caSwyllys 
83199ebb4caSwyllys void
83299ebb4caSwyllys KMF_FreeDN(KMF_X509_NAME *name)
83399ebb4caSwyllys {
83499ebb4caSwyllys 	KMF_X509_RDN 		*newrdn = NULL;
83599ebb4caSwyllys 	KMF_X509_TYPE_VALUE_PAIR *av = NULL;
83699ebb4caSwyllys 	int i, j;
83799ebb4caSwyllys 
83899ebb4caSwyllys 	if (name && name->numberOfRDNs) {
83999ebb4caSwyllys 		for (i = 0; i < name->numberOfRDNs; i++) {
84099ebb4caSwyllys 			newrdn = &name->RelativeDistinguishedName[i];
84199ebb4caSwyllys 			for (j = 0; j < newrdn->numberOfPairs; j++) {
84299ebb4caSwyllys 				av = &newrdn->AttributeTypeAndValue[j];
84399ebb4caSwyllys 				KMF_FreeData(&av->type);
84499ebb4caSwyllys 				KMF_FreeData(&av->value);
84599ebb4caSwyllys 			}
84699ebb4caSwyllys 			free(newrdn->AttributeTypeAndValue);
84799ebb4caSwyllys 			newrdn->numberOfPairs = 0;
84899ebb4caSwyllys 			newrdn->AttributeTypeAndValue = NULL;
84999ebb4caSwyllys 		}
85099ebb4caSwyllys 		free(name->RelativeDistinguishedName);
85199ebb4caSwyllys 		name->numberOfRDNs = 0;
85299ebb4caSwyllys 		name->RelativeDistinguishedName = NULL;
85399ebb4caSwyllys 	}
85499ebb4caSwyllys }
85599ebb4caSwyllys 
85699ebb4caSwyllys void
85799ebb4caSwyllys KMF_FreeKMFCert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
85899ebb4caSwyllys {
85999ebb4caSwyllys 	KMF_PLUGIN *plugin;
86099ebb4caSwyllys 	KMF_RETURN ret;
86199ebb4caSwyllys 
86299ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
86399ebb4caSwyllys 	if (ret != KMF_OK)
86499ebb4caSwyllys 		return;
86599ebb4caSwyllys 
86699ebb4caSwyllys 	if (kmf_cert == NULL)
86799ebb4caSwyllys 		return;
86899ebb4caSwyllys 
86999ebb4caSwyllys 	plugin = FindPlugin(handle, kmf_cert->kmf_private.keystore_type);
87099ebb4caSwyllys 
87199ebb4caSwyllys 	if (plugin != NULL && plugin->funclist->FreeKMFCert != NULL) {
87299ebb4caSwyllys 		plugin->funclist->FreeKMFCert(handle, kmf_cert);
87399ebb4caSwyllys 	}
87499ebb4caSwyllys }
87599ebb4caSwyllys 
87699ebb4caSwyllys void
87799ebb4caSwyllys KMF_FreeData(KMF_DATA *datablock)
87899ebb4caSwyllys {
87999ebb4caSwyllys 	if (datablock != NULL && datablock->Data != NULL) {
88099ebb4caSwyllys 		free(datablock->Data);
88199ebb4caSwyllys 		datablock->Data = NULL;
88299ebb4caSwyllys 		datablock->Length = 0;
88399ebb4caSwyllys 	}
88499ebb4caSwyllys }
88599ebb4caSwyllys 
88699ebb4caSwyllys void
88799ebb4caSwyllys KMF_FreeAlgOID(KMF_X509_ALGORITHM_IDENTIFIER *algoid)
88899ebb4caSwyllys {
88999ebb4caSwyllys 	if (algoid == NULL)
89099ebb4caSwyllys 		return;
89199ebb4caSwyllys 	KMF_FreeData(&algoid->algorithm);
89299ebb4caSwyllys 	KMF_FreeData(&algoid->parameters);
89399ebb4caSwyllys }
89499ebb4caSwyllys 
89599ebb4caSwyllys void
89699ebb4caSwyllys KMF_FreeExtension(KMF_X509_EXTENSION *exptr)
89799ebb4caSwyllys {
89899ebb4caSwyllys 	if (exptr == NULL)
89999ebb4caSwyllys 		return;
90099ebb4caSwyllys 
90199ebb4caSwyllys 	KMF_FreeData((KMF_DATA *)&exptr->extnId);
90299ebb4caSwyllys 	KMF_FreeData(&exptr->BERvalue);
90399ebb4caSwyllys 
90499ebb4caSwyllys 	if (exptr->value.tagAndValue) {
90599ebb4caSwyllys 		KMF_FreeData(&exptr->value.tagAndValue->value);
90699ebb4caSwyllys 		free(exptr->value.tagAndValue);
90799ebb4caSwyllys 	}
90899ebb4caSwyllys }
90999ebb4caSwyllys 
91099ebb4caSwyllys void
91199ebb4caSwyllys KMF_FreeTBSCSR(KMF_TBS_CSR *tbscsr)
91299ebb4caSwyllys {
91399ebb4caSwyllys 	if (tbscsr) {
91499ebb4caSwyllys 		KMF_FreeData(&tbscsr->version);
91599ebb4caSwyllys 
91699ebb4caSwyllys 		KMF_FreeDN(&tbscsr->subject);
91799ebb4caSwyllys 
91899ebb4caSwyllys 		KMF_FreeAlgOID(&tbscsr->subjectPublicKeyInfo.algorithm);
91999ebb4caSwyllys 		KMF_FreeData(&tbscsr->subjectPublicKeyInfo.subjectPublicKey);
92099ebb4caSwyllys 
92199ebb4caSwyllys 		free_extensions(&tbscsr->extensions);
92299ebb4caSwyllys 	}
92399ebb4caSwyllys }
92499ebb4caSwyllys 
92599ebb4caSwyllys void
92699ebb4caSwyllys KMF_FreeSignedCSR(KMF_CSR_DATA *csr)
92799ebb4caSwyllys {
92899ebb4caSwyllys 	if (csr) {
92999ebb4caSwyllys 		KMF_FreeTBSCSR(&csr->csr);
93099ebb4caSwyllys 
93199ebb4caSwyllys 		KMF_FreeAlgOID(&csr->signature.algorithmIdentifier);
93299ebb4caSwyllys 		KMF_FreeData(&csr->signature.encrypted);
93399ebb4caSwyllys 	}
93499ebb4caSwyllys }
93599ebb4caSwyllys 
93699ebb4caSwyllys static void
93799ebb4caSwyllys free_validity(KMF_X509_VALIDITY *validity)
93899ebb4caSwyllys {
93999ebb4caSwyllys 	if (validity == NULL)
94099ebb4caSwyllys 		return;
94199ebb4caSwyllys 	KMF_FreeData(&validity->notBefore.time);
94299ebb4caSwyllys 	KMF_FreeData(&validity->notAfter.time);
94399ebb4caSwyllys }
94499ebb4caSwyllys 
94599ebb4caSwyllys static void
94699ebb4caSwyllys free_extensions(KMF_X509_EXTENSIONS *extns)
94799ebb4caSwyllys {
94899ebb4caSwyllys 	int i;
94999ebb4caSwyllys 	KMF_X509_EXTENSION *exptr;
95099ebb4caSwyllys 
95199ebb4caSwyllys 	if (extns && extns->numberOfExtensions > 0) {
95299ebb4caSwyllys 		for (i = 0; i < extns->numberOfExtensions; i++) {
95399ebb4caSwyllys 			exptr = &extns->extensions[i];
95499ebb4caSwyllys 			KMF_FreeExtension(exptr);
95599ebb4caSwyllys 		}
95699ebb4caSwyllys 		free(extns->extensions);
95799ebb4caSwyllys 		extns->numberOfExtensions = 0;
95899ebb4caSwyllys 		extns->extensions = NULL;
95999ebb4caSwyllys 	}
96099ebb4caSwyllys }
96199ebb4caSwyllys 
96299ebb4caSwyllys void
96399ebb4caSwyllys KMF_FreeTBSCert(KMF_X509_TBS_CERT *tbscert)
96499ebb4caSwyllys {
96599ebb4caSwyllys 	if (tbscert) {
96699ebb4caSwyllys 		KMF_FreeData(&tbscert->version);
96799ebb4caSwyllys 		KMF_FreeBigint(&tbscert->serialNumber);
96899ebb4caSwyllys 		KMF_FreeAlgOID(&tbscert->signature);
96999ebb4caSwyllys 
97099ebb4caSwyllys 		KMF_FreeDN(&tbscert->issuer);
97199ebb4caSwyllys 		KMF_FreeDN(&tbscert->subject);
97299ebb4caSwyllys 
97399ebb4caSwyllys 		free_validity(&tbscert->validity);
97499ebb4caSwyllys 
97599ebb4caSwyllys 		KMF_FreeData(&tbscert->issuerUniqueIdentifier);
97699ebb4caSwyllys 		KMF_FreeData(&tbscert->subjectUniqueIdentifier);
97799ebb4caSwyllys 
97899ebb4caSwyllys 		KMF_FreeAlgOID(&tbscert->subjectPublicKeyInfo.algorithm);
97999ebb4caSwyllys 		KMF_FreeData(&tbscert->subjectPublicKeyInfo.subjectPublicKey);
98099ebb4caSwyllys 
98199ebb4caSwyllys 		free_extensions(&tbscert->extensions);
98299ebb4caSwyllys 
98399ebb4caSwyllys 		KMF_FreeData(&tbscert->issuerUniqueIdentifier);
98499ebb4caSwyllys 		KMF_FreeData(&tbscert->subjectUniqueIdentifier);
98599ebb4caSwyllys 	}
98699ebb4caSwyllys }
98799ebb4caSwyllys 
98899ebb4caSwyllys void
98999ebb4caSwyllys KMF_FreeSignedCert(KMF_X509_CERTIFICATE *certptr)
99099ebb4caSwyllys {
99199ebb4caSwyllys 	if (!certptr)
99299ebb4caSwyllys 		return;
99399ebb4caSwyllys 
99499ebb4caSwyllys 	KMF_FreeTBSCert(&certptr->certificate);
99599ebb4caSwyllys 
99699ebb4caSwyllys 	KMF_FreeAlgOID(&certptr->signature.algorithmIdentifier);
99799ebb4caSwyllys 	KMF_FreeData(&certptr->signature.encrypted);
99899ebb4caSwyllys }
99999ebb4caSwyllys 
100099ebb4caSwyllys void
100199ebb4caSwyllys KMF_FreeString(char *pstr)
100299ebb4caSwyllys {
100399ebb4caSwyllys 	if (pstr != NULL)
100499ebb4caSwyllys 		free(pstr);
100599ebb4caSwyllys }
100699ebb4caSwyllys 
100799ebb4caSwyllys void
100899ebb4caSwyllys free_keyidlist(KMF_OID *oidlist, int len)
100999ebb4caSwyllys {
101099ebb4caSwyllys 	int i;
101199ebb4caSwyllys 	for (i = 0; i < len; i++) {
101299ebb4caSwyllys 		KMF_FreeData((KMF_DATA *)&oidlist[i]);
101399ebb4caSwyllys 	}
101499ebb4caSwyllys 	free(oidlist);
101599ebb4caSwyllys }
101699ebb4caSwyllys 
101799ebb4caSwyllys void
101899ebb4caSwyllys KMF_FreeEKU(KMF_X509EXT_EKU *eptr)
101999ebb4caSwyllys {
102099ebb4caSwyllys 	if (eptr && eptr->nEKUs > 0 &&
102199ebb4caSwyllys 		eptr->keyPurposeIdList != NULL)
102299ebb4caSwyllys 		free_keyidlist(eptr->keyPurposeIdList, eptr->nEKUs);
102399ebb4caSwyllys }
102499ebb4caSwyllys 
102599ebb4caSwyllys void
102699ebb4caSwyllys KMF_FreeSPKI(KMF_X509_SPKI *spki)
102799ebb4caSwyllys {
102899ebb4caSwyllys 	if (spki != NULL) {
102999ebb4caSwyllys 		KMF_FreeAlgOID(&spki->algorithm);
103099ebb4caSwyllys 		KMF_FreeData(&spki->subjectPublicKey);
103199ebb4caSwyllys 	}
103299ebb4caSwyllys }
103399ebb4caSwyllys 
103499ebb4caSwyllys void
103599ebb4caSwyllys KMF_FreeKMFKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key)
103699ebb4caSwyllys {
103799ebb4caSwyllys 	KMF_PLUGIN *plugin;
103899ebb4caSwyllys 	KMF_RETURN ret;
103999ebb4caSwyllys 
104099ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
104199ebb4caSwyllys 	if (ret != KMF_OK)
104299ebb4caSwyllys 		return;
104399ebb4caSwyllys 
104499ebb4caSwyllys 	if (key == NULL)
104599ebb4caSwyllys 		return;
104699ebb4caSwyllys 
104799ebb4caSwyllys 	plugin = FindPlugin(handle, key->kstype);
104899ebb4caSwyllys 	if (plugin != NULL && plugin->funclist->DeleteKey != NULL) {
104999ebb4caSwyllys 		(void) plugin->funclist->DeleteKey(handle, NULL, key, FALSE);
105099ebb4caSwyllys 	}
105199ebb4caSwyllys 
105299ebb4caSwyllys 	if (key == NULL)
105399ebb4caSwyllys 		return;
105499ebb4caSwyllys 
105599ebb4caSwyllys 	if (key->keylabel)
105699ebb4caSwyllys 		free(key->keylabel);
105799ebb4caSwyllys 
105899ebb4caSwyllys 	if (key->israw) {
105999ebb4caSwyllys 		KMF_FreeRawKey(key->keyp);
106099ebb4caSwyllys 		free(key->keyp);
106199ebb4caSwyllys 	}
106299ebb4caSwyllys 
106399ebb4caSwyllys 	(void) memset(key, 0, sizeof (KMF_KEY_HANDLE));
106499ebb4caSwyllys }
106599ebb4caSwyllys 
106699ebb4caSwyllys void
106799ebb4caSwyllys KMF_FreeBigint(KMF_BIGINT *big)
106899ebb4caSwyllys {
106999ebb4caSwyllys 	if (big != NULL && big->val != NULL) {
107002744e81Swyllys 		/* Clear it out before returning it to the pool */
107102744e81Swyllys 		(void) memset(big->val, 0x00, big->len);
107299ebb4caSwyllys 		free(big->val);
107399ebb4caSwyllys 		big->val = NULL;
107499ebb4caSwyllys 		big->len = 0;
107599ebb4caSwyllys 	}
107699ebb4caSwyllys }
107799ebb4caSwyllys 
107899ebb4caSwyllys static void
107999ebb4caSwyllys free_raw_rsa(KMF_RAW_RSA_KEY *key)
108099ebb4caSwyllys {
108199ebb4caSwyllys 	if (key == NULL)
108299ebb4caSwyllys 		return;
108399ebb4caSwyllys 	KMF_FreeBigint(&key->mod);
108499ebb4caSwyllys 	KMF_FreeBigint(&key->pubexp);
108599ebb4caSwyllys 	KMF_FreeBigint(&key->priexp);
108699ebb4caSwyllys 	KMF_FreeBigint(&key->prime1);
108799ebb4caSwyllys 	KMF_FreeBigint(&key->prime2);
108899ebb4caSwyllys 	KMF_FreeBigint(&key->exp1);
108999ebb4caSwyllys 	KMF_FreeBigint(&key->exp2);
109099ebb4caSwyllys 	KMF_FreeBigint(&key->coef);
109199ebb4caSwyllys }
109299ebb4caSwyllys 
109399ebb4caSwyllys static void
109499ebb4caSwyllys free_raw_dsa(KMF_RAW_DSA_KEY *key)
109599ebb4caSwyllys {
109699ebb4caSwyllys 	if (key == NULL)
109799ebb4caSwyllys 		return;
109899ebb4caSwyllys 	KMF_FreeBigint(&key->prime);
109999ebb4caSwyllys 	KMF_FreeBigint(&key->subprime);
110099ebb4caSwyllys 	KMF_FreeBigint(&key->base);
110199ebb4caSwyllys 	KMF_FreeBigint(&key->value);
110299ebb4caSwyllys }
110399ebb4caSwyllys 
110499ebb4caSwyllys static void
110599ebb4caSwyllys free_raw_sym(KMF_RAW_SYM_KEY *key)
110699ebb4caSwyllys {
110799ebb4caSwyllys 	if (key == NULL)
110899ebb4caSwyllys 		return;
110999ebb4caSwyllys 	KMF_FreeBigint(&key->keydata);
111099ebb4caSwyllys }
111199ebb4caSwyllys 
111299ebb4caSwyllys void
111399ebb4caSwyllys KMF_FreeRawKey(KMF_RAW_KEY_DATA *key)
111499ebb4caSwyllys {
111599ebb4caSwyllys 	if (key == NULL)
111699ebb4caSwyllys 		return;
111799ebb4caSwyllys 
111899ebb4caSwyllys 	switch (key->keytype) {
111999ebb4caSwyllys 	case KMF_RSA:
112099ebb4caSwyllys 		free_raw_rsa(&key->rawdata.rsa);
112199ebb4caSwyllys 		break;
112299ebb4caSwyllys 	case KMF_DSA:
112399ebb4caSwyllys 		free_raw_dsa(&key->rawdata.dsa);
112499ebb4caSwyllys 		break;
112599ebb4caSwyllys 	case KMF_AES:
112699ebb4caSwyllys 	case KMF_RC4:
112799ebb4caSwyllys 	case KMF_DES:
112899ebb4caSwyllys 	case KMF_DES3:
112999ebb4caSwyllys 		free_raw_sym(&key->rawdata.sym);
113099ebb4caSwyllys 		break;
113199ebb4caSwyllys 	}
113299ebb4caSwyllys }
113399ebb4caSwyllys 
113499ebb4caSwyllys void
113599ebb4caSwyllys KMF_FreeRawSymKey(KMF_RAW_SYM_KEY *key)
113699ebb4caSwyllys {
113799ebb4caSwyllys 	if (key == NULL)
113899ebb4caSwyllys 		return;
113999ebb4caSwyllys 	KMF_FreeBigint(&key->keydata);
114099ebb4caSwyllys 	free(key);
114199ebb4caSwyllys }
114299ebb4caSwyllys 
114399ebb4caSwyllys /*
114499ebb4caSwyllys  * This function frees the space allocated for the name portion of a
114599ebb4caSwyllys  * KMF_CRL_DIST_POINT.
114699ebb4caSwyllys  */
114799ebb4caSwyllys void
114899ebb4caSwyllys free_dp_name(KMF_CRL_DIST_POINT *dp)
114999ebb4caSwyllys {
115099ebb4caSwyllys 	KMF_GENERALNAMES *fullname;
115199ebb4caSwyllys 	KMF_DATA *urldata;
115299ebb4caSwyllys 	int i;
115399ebb4caSwyllys 
115499ebb4caSwyllys 	if (dp == NULL)
115599ebb4caSwyllys 		return;
115699ebb4caSwyllys 
115799ebb4caSwyllys 	/* For phase 1, we only need to free the fullname space. */
115899ebb4caSwyllys 	fullname = &(dp->name.full_name);
115999ebb4caSwyllys 	if (fullname->number == 0)
116099ebb4caSwyllys 		return;
116199ebb4caSwyllys 
116299ebb4caSwyllys 	for (i = 0; i < fullname->number; i++) {
116399ebb4caSwyllys 		urldata = &(fullname->namelist[fullname->number - 1].name);
116499ebb4caSwyllys 		KMF_FreeData(urldata);
116599ebb4caSwyllys 	}
116699ebb4caSwyllys 
116799ebb4caSwyllys 	free(fullname->namelist);
116899ebb4caSwyllys }
116999ebb4caSwyllys 
117099ebb4caSwyllys /*
117199ebb4caSwyllys  * This function frees the space allocated for a KMF_CRL_DIST_POINT.
117299ebb4caSwyllys  */
117399ebb4caSwyllys void
117499ebb4caSwyllys free_dp(KMF_CRL_DIST_POINT *dp)
117599ebb4caSwyllys {
117699ebb4caSwyllys 	if (dp == NULL)
117799ebb4caSwyllys 		return;
117899ebb4caSwyllys 
117999ebb4caSwyllys 	free_dp_name(dp);
118099ebb4caSwyllys 	KMF_FreeData(&(dp->reasons));
118199ebb4caSwyllys 	/* Need not to free crl_issuer space at phase 1 */
118299ebb4caSwyllys }
118399ebb4caSwyllys 
118499ebb4caSwyllys /*
118599ebb4caSwyllys  * This function frees space for a KMF_X509EXT_CRLDISTPOINTS internally.
118699ebb4caSwyllys  */
118799ebb4caSwyllys void
118899ebb4caSwyllys KMF_FreeCRLDistributionPoints(KMF_X509EXT_CRLDISTPOINTS *crl_dps)
118999ebb4caSwyllys {
119099ebb4caSwyllys 	int i;
119199ebb4caSwyllys 
119299ebb4caSwyllys 	if (crl_dps == NULL)
119399ebb4caSwyllys 		return;
119499ebb4caSwyllys 
119599ebb4caSwyllys 	for (i = 0; i < crl_dps->number; i++)
119699ebb4caSwyllys 		free_dp(&(crl_dps->dplist[i]));
119799ebb4caSwyllys 
119899ebb4caSwyllys 	free(crl_dps->dplist);
119999ebb4caSwyllys }
120099ebb4caSwyllys 
120199ebb4caSwyllys KMF_RETURN
120299ebb4caSwyllys KMF_CreateOCSPRequest(KMF_HANDLE_T handle,  KMF_OCSPREQUEST_PARAMS *params,
120399ebb4caSwyllys     char *reqfile)
120499ebb4caSwyllys {
120599ebb4caSwyllys 	KMF_PLUGIN *plugin;
120699ebb4caSwyllys 	KMF_RETURN (*createReqFn)(void *, KMF_OCSPREQUEST_PARAMS *params,
120799ebb4caSwyllys 	    char *reqfile);
120899ebb4caSwyllys 	KMF_RETURN ret;
120999ebb4caSwyllys 
121099ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
121199ebb4caSwyllys 	if (ret != KMF_OK)
121299ebb4caSwyllys 		return (ret);
121399ebb4caSwyllys 
121499ebb4caSwyllys 
121599ebb4caSwyllys 	if (params == NULL ||
121699ebb4caSwyllys 		reqfile == NULL)
121799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
121899ebb4caSwyllys 
121999ebb4caSwyllys 	/*
122099ebb4caSwyllys 	 * This framework function is actually implemented in the openssl
122199ebb4caSwyllys 	 * plugin library, so we find the function address and call it.
122299ebb4caSwyllys 	 */
122399ebb4caSwyllys 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
122499ebb4caSwyllys 	if (plugin == NULL || plugin->dldesc == NULL) {
122599ebb4caSwyllys 		return (KMF_ERR_PLUGIN_NOTFOUND);
122699ebb4caSwyllys 	}
122799ebb4caSwyllys 
122899ebb4caSwyllys 	createReqFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
122999ebb4caSwyllys 	    "OpenSSL_CreateOCSPRequest");
123099ebb4caSwyllys 	if (createReqFn == NULL) {
123199ebb4caSwyllys 		return (KMF_ERR_FUNCTION_NOT_FOUND);
123299ebb4caSwyllys 	}
123399ebb4caSwyllys 
123499ebb4caSwyllys 	return (createReqFn(handle, params, reqfile));
123599ebb4caSwyllys }
123699ebb4caSwyllys 
123799ebb4caSwyllys KMF_RETURN
123899ebb4caSwyllys KMF_GetOCSPStatusForCert(KMF_HANDLE_T handle,
123999ebb4caSwyllys     KMF_OCSPRESPONSE_PARAMS_INPUT *params_in,
124099ebb4caSwyllys     KMF_OCSPRESPONSE_PARAMS_OUTPUT *params_out)
124199ebb4caSwyllys {
124299ebb4caSwyllys 	KMF_PLUGIN *plugin;
124399ebb4caSwyllys 	KMF_RETURN (*getCertStatusFn)(void *,
124499ebb4caSwyllys 	    KMF_OCSPRESPONSE_PARAMS_INPUT *params_in,
124599ebb4caSwyllys 	    KMF_OCSPRESPONSE_PARAMS_OUTPUT *params_out);
124699ebb4caSwyllys 	KMF_RETURN ret;
124799ebb4caSwyllys 
124899ebb4caSwyllys 	CLEAR_ERROR(handle, ret);
124999ebb4caSwyllys 	if (ret != KMF_OK)
125099ebb4caSwyllys 		return (ret);
125199ebb4caSwyllys 
125299ebb4caSwyllys 
125399ebb4caSwyllys 	if (params_in == NULL ||
125499ebb4caSwyllys 		params_out == NULL)
125599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
125699ebb4caSwyllys 
125799ebb4caSwyllys 	/*
125899ebb4caSwyllys 	 * This framework function is actually implemented in the openssl
125999ebb4caSwyllys 	 * plugin library, so we find the function address and call it.
126099ebb4caSwyllys 	 */
126199ebb4caSwyllys 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
126299ebb4caSwyllys 	if (plugin == NULL || plugin->dldesc == NULL) {
126399ebb4caSwyllys 		return (KMF_ERR_INTERNAL);
126499ebb4caSwyllys 	}
126599ebb4caSwyllys 
126699ebb4caSwyllys 	getCertStatusFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
126799ebb4caSwyllys 	    "OpenSSL_GetOCSPStatusForCert");
126899ebb4caSwyllys 	if (getCertStatusFn == NULL) {
126999ebb4caSwyllys 		return (KMF_ERR_INTERNAL);
127099ebb4caSwyllys 	}
127199ebb4caSwyllys 
127299ebb4caSwyllys 	return (getCertStatusFn(handle, params_in, params_out));
127399ebb4caSwyllys }
127499ebb4caSwyllys 
127599ebb4caSwyllys KMF_RETURN
127699ebb4caSwyllys KMF_String2OID(char *oidstring, KMF_OID *oid)
127799ebb4caSwyllys {
127899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
127999ebb4caSwyllys 	char *cp, *bp, *startp;
128099ebb4caSwyllys 	int numbuf;
128199ebb4caSwyllys 	int onumbuf;
128299ebb4caSwyllys 	int nbytes, index;
128399ebb4caSwyllys 	int len;
128499ebb4caSwyllys 	unsigned char *op;
128599ebb4caSwyllys 
128699ebb4caSwyllys 	if (oidstring == NULL || oid == NULL)
128799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
128899ebb4caSwyllys 
128999ebb4caSwyllys 	len = strlen(oidstring);
129099ebb4caSwyllys 
129199ebb4caSwyllys 	bp = oidstring;
129299ebb4caSwyllys 	cp = bp;
129399ebb4caSwyllys 	/* Skip over leading space */
129499ebb4caSwyllys 	while ((bp < &cp[len]) && isspace(*bp))
129599ebb4caSwyllys 		bp++;
129699ebb4caSwyllys 
129799ebb4caSwyllys 	startp = bp;
129899ebb4caSwyllys 	nbytes = 0;
129999ebb4caSwyllys 
130099ebb4caSwyllys 	/*
130199ebb4caSwyllys 	 * The first two numbers are chewed up by the first octet.
130299ebb4caSwyllys 	 */
130399ebb4caSwyllys 	if (sscanf(bp, "%d", &numbuf) != 1)
130499ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
130599ebb4caSwyllys 	while ((bp < &cp[len]) && isdigit(*bp))
130699ebb4caSwyllys 		bp++;
130799ebb4caSwyllys 	while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
130899ebb4caSwyllys 		bp++;
130999ebb4caSwyllys 	if (sscanf(bp, "%d", &numbuf) != 1)
131099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
131199ebb4caSwyllys 	while ((bp < &cp[len]) && isdigit(*bp))
131299ebb4caSwyllys 		bp++;
131399ebb4caSwyllys 	while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
131499ebb4caSwyllys 		bp++;
131599ebb4caSwyllys 	nbytes++;
131699ebb4caSwyllys 
131799ebb4caSwyllys 	while (isdigit(*bp)) {
131899ebb4caSwyllys 		if (sscanf(bp, "%d", &numbuf) != 1)
131999ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
132099ebb4caSwyllys 		while (numbuf) {
132199ebb4caSwyllys 			nbytes++;
132299ebb4caSwyllys 			numbuf >>= 7;
132399ebb4caSwyllys 		}
132499ebb4caSwyllys 		while ((bp < &cp[len]) && isdigit(*bp))
132599ebb4caSwyllys 			bp++;
132699ebb4caSwyllys 		while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
132799ebb4caSwyllys 			bp++;
132899ebb4caSwyllys 	}
132999ebb4caSwyllys 
133099ebb4caSwyllys 	oid->Length = nbytes;
133199ebb4caSwyllys 	oid->Data = malloc(oid->Length);
133299ebb4caSwyllys 	if (oid->Data == NULL) {
133399ebb4caSwyllys 		return (KMF_ERR_MEMORY);
133499ebb4caSwyllys 	}
133599ebb4caSwyllys 	(void) memset(oid->Data, 0, oid->Length);
133699ebb4caSwyllys 
133799ebb4caSwyllys 	op = oid->Data;
133899ebb4caSwyllys 
133999ebb4caSwyllys 	bp = startp;
134099ebb4caSwyllys 	(void) sscanf(bp, "%d", &numbuf);
134199ebb4caSwyllys 
134299ebb4caSwyllys 	while (isdigit(*bp)) bp++;
134399ebb4caSwyllys 	while (isspace(*bp) || *bp == '.') bp++;
134499ebb4caSwyllys 
134599ebb4caSwyllys 	onumbuf = 40 * numbuf;
134699ebb4caSwyllys 	(void) sscanf(bp, "%d", &numbuf);
134799ebb4caSwyllys 	onumbuf += numbuf;
134899ebb4caSwyllys 	*op = (unsigned char) onumbuf;
134999ebb4caSwyllys 	op++;
135099ebb4caSwyllys 
135199ebb4caSwyllys 	while (isdigit(*bp)) bp++;
135299ebb4caSwyllys 	while (isspace(*bp) || *bp == '.') bp++;
135399ebb4caSwyllys 	while (isdigit(*bp)) {
135499ebb4caSwyllys 		(void) sscanf(bp, "%d", &numbuf);
135599ebb4caSwyllys 		nbytes = 0;
135699ebb4caSwyllys 		/* Have to fill in the bytes msb-first */
135799ebb4caSwyllys 		onumbuf = numbuf;
135899ebb4caSwyllys 		while (numbuf) {
135999ebb4caSwyllys 			nbytes++;
136099ebb4caSwyllys 			numbuf >>= 7;
136199ebb4caSwyllys 		}
136299ebb4caSwyllys 		numbuf = onumbuf;
136399ebb4caSwyllys 		op += nbytes;
136499ebb4caSwyllys 		index = -1;
136599ebb4caSwyllys 		while (numbuf) {
136699ebb4caSwyllys 			op[index] = (unsigned char)numbuf & 0x7f;
136799ebb4caSwyllys 			if (index != -1)
136899ebb4caSwyllys 				op[index] |= 0x80;
136999ebb4caSwyllys 			index--;
137099ebb4caSwyllys 			numbuf >>= 7;
137199ebb4caSwyllys 		}
137299ebb4caSwyllys 		while (isdigit(*bp)) bp++;
137399ebb4caSwyllys 		while (isspace(*bp) || *bp == '.') bp++;
137499ebb4caSwyllys 	}
137599ebb4caSwyllys 
137699ebb4caSwyllys 	return (rv);
137799ebb4caSwyllys }
137899ebb4caSwyllys 
137999ebb4caSwyllys static KMF_RETURN
138099ebb4caSwyllys encode_rid(char *name, KMF_DATA *derdata)
138199ebb4caSwyllys {
138299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
138399ebb4caSwyllys 
138499ebb4caSwyllys 	if (name == NULL || derdata == NULL)
138599ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
138699ebb4caSwyllys 
138799ebb4caSwyllys 	rv = KMF_String2OID(name, (KMF_OID *)derdata);
138899ebb4caSwyllys 
138999ebb4caSwyllys 	return (rv);
139099ebb4caSwyllys }
139199ebb4caSwyllys 
139299ebb4caSwyllys static KMF_RETURN
139399ebb4caSwyllys encode_ipaddr(char *name, KMF_DATA *derdata)
139499ebb4caSwyllys {
139599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
139699ebb4caSwyllys 	size_t len;
139799ebb4caSwyllys 	in_addr_t v4;
139899ebb4caSwyllys 	in6_addr_t v6;
139999ebb4caSwyllys 	uint8_t *ptr;
140099ebb4caSwyllys 
140199ebb4caSwyllys 	if (name == NULL || derdata == NULL)
140299ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
140399ebb4caSwyllys 
140499ebb4caSwyllys 	v4 = inet_addr(name);
140599ebb4caSwyllys 	if (v4 == (in_addr_t)-1) {
140699ebb4caSwyllys 		ptr = (uint8_t *)&v6;
140799ebb4caSwyllys 		if (inet_pton(AF_INET6, name, ptr) != 1)
140899ebb4caSwyllys 			return (KMF_ERR_ENCODING);
140999ebb4caSwyllys 		len = sizeof (v6);
141099ebb4caSwyllys 	} else {
141199ebb4caSwyllys 		ptr = (uint8_t *)&v4;
141299ebb4caSwyllys 		len = sizeof (v4);
141399ebb4caSwyllys 	}
141499ebb4caSwyllys 
141599ebb4caSwyllys 	derdata->Data = malloc(len);
141699ebb4caSwyllys 	if (derdata->Data == NULL)
141799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
141899ebb4caSwyllys 	(void) memcpy(derdata->Data, ptr, len);
141999ebb4caSwyllys 	derdata->Length = len;
142099ebb4caSwyllys 
142199ebb4caSwyllys 	return (rv);
142299ebb4caSwyllys }
142399ebb4caSwyllys 
142499ebb4caSwyllys static KMF_RETURN
142599ebb4caSwyllys verify_uri_format(char *uristring)
142699ebb4caSwyllys {
142799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
142899ebb4caSwyllys 	xmlURIPtr   uriptr = NULL;
142999ebb4caSwyllys 
143099ebb4caSwyllys 	/* Parse the URI string; get the hostname and port */
143199ebb4caSwyllys 	uriptr = xmlParseURI(uristring);
143299ebb4caSwyllys 	if (uriptr == NULL) {
143399ebb4caSwyllys 		ret = KMF_ERR_BAD_URI;
143499ebb4caSwyllys 		goto out;
143599ebb4caSwyllys 	}
143699ebb4caSwyllys 
143799ebb4caSwyllys 	if (uriptr->scheme == NULL || !strlen(uriptr->scheme)) {
143899ebb4caSwyllys 		ret = KMF_ERR_BAD_URI;
143999ebb4caSwyllys 		goto out;
144099ebb4caSwyllys 	}
144199ebb4caSwyllys 
144299ebb4caSwyllys 	if (uriptr->server == NULL || !strlen(uriptr->server)) {
144399ebb4caSwyllys 		ret = KMF_ERR_BAD_URI;
144499ebb4caSwyllys 		goto out;
144599ebb4caSwyllys 	}
144699ebb4caSwyllys out:
144799ebb4caSwyllys 	if (uriptr != NULL)
144899ebb4caSwyllys 		xmlFreeURI(uriptr);
144999ebb4caSwyllys 	return (ret);
145099ebb4caSwyllys }
145199ebb4caSwyllys 
145299ebb4caSwyllys static KMF_RETURN
145399ebb4caSwyllys encode_altname(char *namedata,
145499ebb4caSwyllys 	KMF_GENERALNAMECHOICES nametype, KMF_DATA *encodedname)
145599ebb4caSwyllys {
145699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
145799ebb4caSwyllys 	KMF_X509_NAME dnname;
145899ebb4caSwyllys 	uchar_t tagval;
145999ebb4caSwyllys 	BerElement *asn1 = NULL;
146099ebb4caSwyllys 	BerValue *extdata;
146199ebb4caSwyllys 
146299ebb4caSwyllys 	if (namedata == NULL || encodedname == NULL)
146399ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
146499ebb4caSwyllys 
146599ebb4caSwyllys 	/*
146699ebb4caSwyllys 	 * Encode the namedata according to rules in RFC 3280 for GeneralName.
146799ebb4caSwyllys 	 * The input "namedata" is assumed to be an ASCII string representation
146899ebb4caSwyllys 	 * of the AltName, we need to convert it to correct ASN.1 here before
146999ebb4caSwyllys 	 * adding it to the cert.
147099ebb4caSwyllys 	 */
147199ebb4caSwyllys 	switch (nametype) {
147299ebb4caSwyllys 		case GENNAME_RFC822NAME: /* rfc 822 */
147399ebb4caSwyllys 			/* IA5String, no encoding needed */
147499ebb4caSwyllys 			encodedname->Data = (uchar_t *)strdup(namedata);
147599ebb4caSwyllys 			if (encodedname->Data == NULL)
147699ebb4caSwyllys 				return (KMF_ERR_MEMORY);
147799ebb4caSwyllys 			encodedname->Length = strlen(namedata);
147899ebb4caSwyllys 			tagval = (0x80 | nametype);
147999ebb4caSwyllys 			break;
148099ebb4caSwyllys 		case GENNAME_DNSNAME: /* rfc 1034 */
148199ebb4caSwyllys 			encodedname->Data = (uchar_t *)strdup(namedata);
148299ebb4caSwyllys 			if (encodedname->Data == NULL)
148399ebb4caSwyllys 				return (KMF_ERR_MEMORY);
148499ebb4caSwyllys 			encodedname->Length = strlen(namedata);
148599ebb4caSwyllys 			tagval = (0x80 | nametype);
148699ebb4caSwyllys 			break;
148799ebb4caSwyllys 		case GENNAME_URI: /* rfc 1738 */
148899ebb4caSwyllys 			ret = verify_uri_format(namedata);
148999ebb4caSwyllys 			if (ret != KMF_OK)
149099ebb4caSwyllys 				return (ret);
149199ebb4caSwyllys 			/* IA5String, no encoding needed */
149299ebb4caSwyllys 			encodedname->Data = (uchar_t *)strdup(namedata);
149399ebb4caSwyllys 			if (encodedname->Data == NULL)
149499ebb4caSwyllys 				return (KMF_ERR_MEMORY);
149599ebb4caSwyllys 			encodedname->Length = strlen(namedata);
149699ebb4caSwyllys 			tagval = (0x80 | nametype);
149799ebb4caSwyllys 			break;
149899ebb4caSwyllys 		case GENNAME_IPADDRESS:
149999ebb4caSwyllys 			ret =  encode_ipaddr(namedata, encodedname);
150099ebb4caSwyllys 			tagval = (0x80 | nametype);
150199ebb4caSwyllys 			break;
150299ebb4caSwyllys 		case GENNAME_REGISTEREDID:
150399ebb4caSwyllys 			ret = encode_rid(namedata, encodedname);
150499ebb4caSwyllys 			tagval = (0x80 | nametype);
150599ebb4caSwyllys 			break;
150699ebb4caSwyllys 		case GENNAME_DIRECTORYNAME:
150799ebb4caSwyllys 			ret = KMF_DNParser(namedata, &dnname);
150899ebb4caSwyllys 			if (ret == KMF_OK) {
150999ebb4caSwyllys 				ret = KMF_DN2Der(&dnname, encodedname);
151099ebb4caSwyllys 			}
151199ebb4caSwyllys 			(void) KMF_FreeDN(&dnname);
151299ebb4caSwyllys 			tagval = (0xA0 | nametype);
151399ebb4caSwyllys 			break;
151499ebb4caSwyllys 		default:
151599ebb4caSwyllys 			/* unsupported */
151699ebb4caSwyllys 			return (KMF_ERR_BAD_PARAMETER);
151799ebb4caSwyllys 
151899ebb4caSwyllys 	}
151999ebb4caSwyllys 	if (ret != KMF_OK) {
152099ebb4caSwyllys 		KMF_FreeData(encodedname);
152199ebb4caSwyllys 		return (ret);
152299ebb4caSwyllys 	}
152399ebb4caSwyllys 
152499ebb4caSwyllys 	if ((asn1 = kmfder_alloc()) == NULL)
152599ebb4caSwyllys 		return (KMF_ERR_MEMORY);
152699ebb4caSwyllys 
152799ebb4caSwyllys 	if (kmfber_printf(asn1, "Tl",
152899ebb4caSwyllys 		tagval, encodedname->Length) == -1)
152999ebb4caSwyllys 		goto cleanup;
153099ebb4caSwyllys 
153199ebb4caSwyllys 	if (kmfber_write(asn1, (char *)encodedname->Data,
153299ebb4caSwyllys 		encodedname->Length, 0) == -1) {
153399ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
153499ebb4caSwyllys 		goto cleanup;
153599ebb4caSwyllys 	}
153699ebb4caSwyllys 	if (kmfber_flatten(asn1, &extdata) == -1) {
153799ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
153899ebb4caSwyllys 		goto cleanup;
153999ebb4caSwyllys 	}
154099ebb4caSwyllys 
154199ebb4caSwyllys 	KMF_FreeData(encodedname);
154299ebb4caSwyllys 	encodedname->Data = (uchar_t *)extdata->bv_val;
154399ebb4caSwyllys 	encodedname->Length = extdata->bv_len;
154499ebb4caSwyllys 
154599ebb4caSwyllys 	free(extdata);
154699ebb4caSwyllys 
154799ebb4caSwyllys cleanup:
154899ebb4caSwyllys 	if (asn1)
154999ebb4caSwyllys 		kmfber_free(asn1, 1);
155099ebb4caSwyllys 
155199ebb4caSwyllys 	if (ret != KMF_OK)
155299ebb4caSwyllys 		KMF_FreeData(encodedname);
155399ebb4caSwyllys 
155499ebb4caSwyllys 	return (ret);
155599ebb4caSwyllys }
155699ebb4caSwyllys 
155799ebb4caSwyllys KMF_X509_EXTENSION *
155899ebb4caSwyllys FindExtn(KMF_X509_EXTENSIONS *exts, KMF_OID *oid)
155999ebb4caSwyllys {
156099ebb4caSwyllys 	KMF_X509_EXTENSION *foundextn = NULL;
156199ebb4caSwyllys 	int i;
156299ebb4caSwyllys 
156399ebb4caSwyllys 	if (exts == NULL || oid == NULL)
156499ebb4caSwyllys 		return (NULL);
156599ebb4caSwyllys 
156699ebb4caSwyllys 	for (i = 0; i < exts->numberOfExtensions; i++) {
156799ebb4caSwyllys 		if (IsEqualOid(oid, &exts->extensions[i].extnId))  {
156899ebb4caSwyllys 			foundextn = &exts->extensions[i];
156999ebb4caSwyllys 			break;
157099ebb4caSwyllys 		}
157199ebb4caSwyllys 	}
157299ebb4caSwyllys 	return (foundextn);
157399ebb4caSwyllys }
157499ebb4caSwyllys 
157599ebb4caSwyllys KMF_RETURN
157699ebb4caSwyllys GetSequenceContents(char *data, size_t len,
157799ebb4caSwyllys 	char **contents, size_t *outlen)
157899ebb4caSwyllys {
157999ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
158099ebb4caSwyllys 	BerElement *exasn1 = NULL;
158199ebb4caSwyllys 	BerValue oldextn;
158299ebb4caSwyllys 	int tag;
158399ebb4caSwyllys 	size_t oldsize;
158499ebb4caSwyllys 	char *olddata = NULL;
158599ebb4caSwyllys 
158699ebb4caSwyllys 	if (data == NULL || contents == NULL || outlen == NULL)
158799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
158899ebb4caSwyllys 
158999ebb4caSwyllys 	/*
159099ebb4caSwyllys 	 * Decode the sequence of general names
159199ebb4caSwyllys 	 */
159299ebb4caSwyllys 	oldextn.bv_val = data;
159399ebb4caSwyllys 	oldextn.bv_len = len;
159499ebb4caSwyllys 
159599ebb4caSwyllys 	if ((exasn1 = kmfder_init(&oldextn)) == NULL) {
159699ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
159799ebb4caSwyllys 		goto out;
159899ebb4caSwyllys 	}
159999ebb4caSwyllys 
160099ebb4caSwyllys 	/*
160199ebb4caSwyllys 	 * Unwrap the sequence to find the size of the block
160299ebb4caSwyllys 	 * of GeneralName items in the set.
160399ebb4caSwyllys 	 *
160499ebb4caSwyllys 	 * Peek at the tag and length ("tl"),
160599ebb4caSwyllys 	 * then consume them ("{").
160699ebb4caSwyllys 	 */
160799ebb4caSwyllys 	if (kmfber_scanf(exasn1, "tl{", &tag, &oldsize) == KMFBER_DEFAULT ||
160899ebb4caSwyllys 		oldsize == 0) {
160999ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
161099ebb4caSwyllys 		goto out;
161199ebb4caSwyllys 	}
161299ebb4caSwyllys 
161399ebb4caSwyllys 	olddata = malloc(oldsize);
161499ebb4caSwyllys 	if (olddata == NULL) {
161599ebb4caSwyllys 		ret = KMF_ERR_MEMORY;
161699ebb4caSwyllys 		goto out;
161799ebb4caSwyllys 	}
161899ebb4caSwyllys 	(void) memset(olddata, 0, oldsize);
161999ebb4caSwyllys 	/*
162099ebb4caSwyllys 	 * Read the entire blob of GeneralNames, we don't
162199ebb4caSwyllys 	 * need to interpret them now.
162299ebb4caSwyllys 	 */
162399ebb4caSwyllys 	if (kmfber_read(exasn1, olddata, oldsize) != oldsize) {
162499ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
162599ebb4caSwyllys 		goto out;
162699ebb4caSwyllys 	}
162799ebb4caSwyllys out:
162899ebb4caSwyllys 	if (exasn1 != NULL)
162999ebb4caSwyllys 		kmfber_free(exasn1, 1);
163099ebb4caSwyllys 
163199ebb4caSwyllys 	if (ret != KMF_OK) {
163299ebb4caSwyllys 		*contents = NULL;
163399ebb4caSwyllys 		*outlen = 0;
163499ebb4caSwyllys 		if (olddata != NULL)
163599ebb4caSwyllys 			free(olddata);
163699ebb4caSwyllys 	} else {
163799ebb4caSwyllys 		*contents = olddata;
163899ebb4caSwyllys 		*outlen = oldsize;
163999ebb4caSwyllys 	}
164099ebb4caSwyllys 	return (ret);
164199ebb4caSwyllys }
164299ebb4caSwyllys 
164399ebb4caSwyllys KMF_RETURN
164499ebb4caSwyllys add_an_extension(KMF_X509_EXTENSIONS *exts, KMF_X509_EXTENSION *newextn)
164599ebb4caSwyllys {
164699ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
164799ebb4caSwyllys 	KMF_X509_EXTENSION *extlist;
164899ebb4caSwyllys 
164999ebb4caSwyllys 	if (exts == NULL || newextn == NULL)
165099ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
165199ebb4caSwyllys 
165299ebb4caSwyllys 	extlist = malloc(sizeof (KMF_X509_EXTENSION) *
165399ebb4caSwyllys 			(exts->numberOfExtensions + 1));
165499ebb4caSwyllys 	if (extlist == NULL)
165599ebb4caSwyllys 		return (KMF_ERR_MEMORY);
165699ebb4caSwyllys 
165799ebb4caSwyllys 	(void) memcpy(extlist, exts->extensions,
165899ebb4caSwyllys 	    exts->numberOfExtensions * sizeof (KMF_X509_EXTENSION));
165999ebb4caSwyllys 
166099ebb4caSwyllys 	(void) memcpy(&extlist[exts->numberOfExtensions], newextn,
166199ebb4caSwyllys 		sizeof (KMF_X509_EXTENSION));
166299ebb4caSwyllys 
166399ebb4caSwyllys 	free(exts->extensions);
166499ebb4caSwyllys 	exts->numberOfExtensions++;
166599ebb4caSwyllys 	exts->extensions = extlist;
166699ebb4caSwyllys 
166799ebb4caSwyllys 	return (ret);
166899ebb4caSwyllys }
166999ebb4caSwyllys 
167099ebb4caSwyllys KMF_RETURN
167199ebb4caSwyllys KMF_SetAltName(KMF_X509_EXTENSIONS *extensions,
167299ebb4caSwyllys 	KMF_OID *oid,
167399ebb4caSwyllys 	int critical,
167499ebb4caSwyllys 	KMF_GENERALNAMECHOICES nametype,
167599ebb4caSwyllys 	char *namedata)
167699ebb4caSwyllys {
167799ebb4caSwyllys 	KMF_RETURN ret = KMF_OK;
167899ebb4caSwyllys 	KMF_X509_EXTENSION subjAltName;
167999ebb4caSwyllys 	KMF_DATA dername = { NULL, 0 };
168099ebb4caSwyllys 	BerElement *asn1 = NULL;
168199ebb4caSwyllys 	BerValue *extdata;
168299ebb4caSwyllys 	char *olddata = NULL;
168399ebb4caSwyllys 	KMF_X509_EXTENSION *foundextn = NULL;
168499ebb4caSwyllys 	size_t	oldsize = 0;
168599ebb4caSwyllys 
168699ebb4caSwyllys 	if (extensions == NULL || oid == NULL || namedata == NULL)
168799ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
168899ebb4caSwyllys 
168999ebb4caSwyllys 	ret = encode_altname(namedata, nametype, &dername);
169099ebb4caSwyllys 
169199ebb4caSwyllys 	if (ret != KMF_OK)
169299ebb4caSwyllys 		return (ret);
169399ebb4caSwyllys 
169499ebb4caSwyllys 	(void) memset(&subjAltName, 0, sizeof (subjAltName));
169599ebb4caSwyllys 
169699ebb4caSwyllys 	ret = copy_data(&subjAltName.extnId, oid);
169799ebb4caSwyllys 	if (ret != KMF_OK)
169899ebb4caSwyllys 		goto out;
169999ebb4caSwyllys 	/*
170099ebb4caSwyllys 	 * Check to see if this cert already has a subjectAltName.
170199ebb4caSwyllys 	 */
170299ebb4caSwyllys 	foundextn = FindExtn(extensions, oid);
170399ebb4caSwyllys 
170499ebb4caSwyllys 	if (foundextn != NULL) {
170599ebb4caSwyllys 		ret = GetSequenceContents(
170699ebb4caSwyllys 				(char *)foundextn->BERvalue.Data,
170799ebb4caSwyllys 				foundextn->BERvalue.Length,
170899ebb4caSwyllys 				&olddata, &oldsize);
170999ebb4caSwyllys 		if (ret != KMF_OK)
171099ebb4caSwyllys 			goto out;
171199ebb4caSwyllys 	}
171299ebb4caSwyllys 
171399ebb4caSwyllys 	/*
171499ebb4caSwyllys 	 * Assume (!!) that the namedata given is already properly encoded.
171599ebb4caSwyllys 	 */
171699ebb4caSwyllys 	if ((asn1 = kmfder_alloc()) == NULL)
171799ebb4caSwyllys 		return (KMF_ERR_MEMORY);
171899ebb4caSwyllys 
171999ebb4caSwyllys 	if (kmfber_printf(asn1, "{") == -1) {
172099ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
172199ebb4caSwyllys 		goto out;
172299ebb4caSwyllys 	}
172399ebb4caSwyllys 
172499ebb4caSwyllys 	/* Write the old extension data first */
172599ebb4caSwyllys 	if (olddata != NULL && oldsize > 0) {
172699ebb4caSwyllys 		if (kmfber_write(asn1, olddata, oldsize, 0) == -1) {
172799ebb4caSwyllys 			ret = KMF_ERR_ENCODING;
172899ebb4caSwyllys 			goto out;
172999ebb4caSwyllys 		}
173099ebb4caSwyllys 	}
173199ebb4caSwyllys 
173299ebb4caSwyllys 	/* Now add the new name to the list */
173399ebb4caSwyllys 	if (kmfber_write(asn1, (char *)dername.Data, dername.Length, 0) == -1) {
173499ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
173599ebb4caSwyllys 		goto out;
173699ebb4caSwyllys 	}
173799ebb4caSwyllys 
173899ebb4caSwyllys 	/* Now close the sequence */
173999ebb4caSwyllys 	if (kmfber_printf(asn1, "}") == -1) {
174099ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
174199ebb4caSwyllys 		goto out;
174299ebb4caSwyllys 	}
174399ebb4caSwyllys 	if (kmfber_flatten(asn1, &extdata) == -1) {
174499ebb4caSwyllys 		ret = KMF_ERR_ENCODING;
174599ebb4caSwyllys 		goto out;
174699ebb4caSwyllys 	}
174799ebb4caSwyllys 
174899ebb4caSwyllys 	/*
174999ebb4caSwyllys 	 * If we are just adding to an existing list of altNames,
175099ebb4caSwyllys 	 * just replace the BER data associated with the found extension.
175199ebb4caSwyllys 	 */
175299ebb4caSwyllys 	if (foundextn != NULL) {
175399ebb4caSwyllys 		free(foundextn->BERvalue.Data);
175499ebb4caSwyllys 		foundextn->critical = critical;
175599ebb4caSwyllys 		foundextn->BERvalue.Data = (uchar_t *)extdata->bv_val;
175699ebb4caSwyllys 		foundextn->BERvalue.Length = extdata->bv_len;
175799ebb4caSwyllys 	} else {
175899ebb4caSwyllys 		subjAltName.critical = critical;
175999ebb4caSwyllys 		subjAltName.format = KMF_X509_DATAFORMAT_ENCODED;
176099ebb4caSwyllys 		subjAltName.BERvalue.Data = (uchar_t *)extdata->bv_val;
176199ebb4caSwyllys 		subjAltName.BERvalue.Length = extdata->bv_len;
176299ebb4caSwyllys 		ret = add_an_extension(extensions, &subjAltName);
176399ebb4caSwyllys 		if (ret != KMF_OK)
176499ebb4caSwyllys 			free(subjAltName.BERvalue.Data);
176599ebb4caSwyllys 	}
176699ebb4caSwyllys 
176799ebb4caSwyllys 	free(extdata);
176899ebb4caSwyllys out:
176999ebb4caSwyllys 	if (olddata != NULL)
177099ebb4caSwyllys 		free(olddata);
177199ebb4caSwyllys 
177299ebb4caSwyllys 	KMF_FreeData(&dername);
177399ebb4caSwyllys 	if (ret != KMF_OK)
177499ebb4caSwyllys 		KMF_FreeData(&subjAltName.extnId);
177599ebb4caSwyllys 	if (asn1 != NULL)
177699ebb4caSwyllys 		kmfber_free(asn1, 1);
177799ebb4caSwyllys 	return (ret);
177899ebb4caSwyllys }
1779