Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  *
     25  */
     26 
     27 #include <stdio.h>
     28 #include <dlfcn.h>
     29 #include <link.h>
     30 #include <fcntl.h>
     31 #include <ctype.h>
     32 #include <sys/param.h>
     33 #include <sys/types.h>
     34 #include <sys/stat.h>
     35 #include <errno.h>
     36 #include <sys/socket.h>
     37 #include <netinet/in.h>
     38 #include <arpa/inet.h>
     39 #include <thread.h>
     40 
     41 #include <ber_der.h>
     42 #include <kmfapiP.h>
     43 
     44 #include <pem_encode.h>
     45 #include <rdn_parser.h>
     46 #include <libxml2/libxml/uri.h>
     47 #include <libgen.h>
     48 #include <cryptoutil.h>
     49 
     50 static uchar_t pkcs11_initialized = 0;
     51 mutex_t init_lock = DEFAULTMUTEX;
     52 extern int errno;
     53 
     54 typedef struct {
     55 	KMF_RETURN code;
     56 	char	*message;
     57 } kmf_error_map;
     58 
     59 static kmf_error_map kmf_errcodes[] = {
     60 	{KMF_OK,	"KMF_OK"},
     61 	{KMF_ERR_BAD_PARAMETER,	"KMF_ERR_BAD_PARAMETER"},
     62 	{KMF_ERR_BAD_KEY_FORMAT,	"KMF_ERR_BAD_KEY_FORMAT"},
     63 	{KMF_ERR_BAD_ALGORITHM,	"KMF_ERR_BAD_ALGORITHM"},
     64 	{KMF_ERR_MEMORY,	"KMF_ERR_MEMORY"},
     65 	{KMF_ERR_ENCODING,	"KMF_ERR_ENCODING"},
     66 	{KMF_ERR_PLUGIN_INIT,	"KMF_ERR_PLUGIN_INIT"},
     67 	{KMF_ERR_PLUGIN_NOTFOUND,	"KMF_ERR_PLUGIN_NOTFOUND"},
     68 	{KMF_ERR_INTERNAL,	"KMF_ERR_INTERNAL"},
     69 	{KMF_ERR_BAD_CERT_FORMAT,	"KMF_ERR_BAD_CERT_FORMAT"},
     70 	{KMF_ERR_KEYGEN_FAILED,	"KMF_ERR_KEYGEN_FAILED"},
     71 	{KMF_ERR_UNINITIALIZED,	"KMF_ERR_UNINITIALIZED"},
     72 	{KMF_ERR_ISSUER,	"KMF_ERR_ISSUER"},
     73 	{KMF_ERR_NOT_REVOKED,	"KMF_ERR_NOT_REVOKED"},
     74 	{KMF_ERR_CERT_NOT_FOUND,	"KMF_ERR_CERT_NOT_FOUND"},
     75 	{KMF_ERR_CRL_NOT_FOUND,	"KMF_ERR_CRL_NOT_FOUND"},
     76 	{KMF_ERR_RDN_PARSER,	"KMF_ERR_RDN_PARSER"},
     77 	{KMF_ERR_RDN_ATTR,	"KMF_ERR_RDN_ATTR"},
     78 	{KMF_ERR_SLOTNAME,	"KMF_ERR_SLOTNAME"},
     79 	{KMF_ERR_EMPTY_CRL,	"KMF_ERR_EMPTY_CRL"},
     80 	{KMF_ERR_BUFFER_SIZE,	"KMF_ERR_BUFFER_SIZE"},
     81 	{KMF_ERR_AUTH_FAILED,	"KMF_ERR_AUTH_FAILED"},
     82 	{KMF_ERR_TOKEN_SELECTED,	"KMF_ERR_TOKEN_SELECTED"},
     83 	{KMF_ERR_NO_TOKEN_SELECTED,	"KMF_ERR_NO_TOKEN_SELECTED"},
     84 	{KMF_ERR_TOKEN_NOT_PRESENT,	"KMF_ERR_TOKEN_NOT_PRESENT"},
     85 	{KMF_ERR_EXTENSION_NOT_FOUND,	"KMF_ERR_EXTENSION_NOT_FOUND"},
     86 	{KMF_ERR_POLICY_ENGINE,	"KMF_ERR_POLICY_ENGINE"},
     87 	{KMF_ERR_POLICY_DB_FORMAT,	"KMF_ERR_POLICY_DB_FORMAT"},
     88 	{KMF_ERR_POLICY_NOT_FOUND,	"KMF_ERR_POLICY_NOT_FOUND"},
     89 	{KMF_ERR_POLICY_DB_FILE,	"KMF_ERR_POLICY_DB_FILE"},
     90 	{KMF_ERR_POLICY_NAME,	"KMF_ERR_POLICY_NAME"},
     91 	{KMF_ERR_OCSP_POLICY,	"KMF_ERR_OCSP_POLICY"},
     92 	{KMF_ERR_TA_POLICY,	"KMF_ERR_TA_POLICY"},
     93 	{KMF_ERR_KEY_NOT_FOUND,	"KMF_ERR_KEY_NOT_FOUND"},
     94 	{KMF_ERR_OPEN_FILE,	"KMF_ERR_OPEN_FILE"},
     95 	{KMF_ERR_OCSP_BAD_ISSUER,	"KMF_ERR_OCSP_BAD_ISSUER"},
     96 	{KMF_ERR_OCSP_BAD_CERT,	"KMF_ERR_OCSP_BAD_CERT"},
     97 	{KMF_ERR_OCSP_CREATE_REQUEST,	"KMF_ERR_OCSP_CREATE_REQUEST"},
     98 	{KMF_ERR_CONNECT_SERVER,	"KMF_ERR_CONNECT_SERVER"},
     99 	{KMF_ERR_SEND_REQUEST,	"KMF_ERR_SEND_REQUEST"},
    100 	{KMF_ERR_OCSP_CERTID,	"KMF_ERR_OCSP_CERTID"},
    101 	{KMF_ERR_OCSP_MALFORMED_RESPONSE, "KMF_ERR_OCSP_MALFORMED_RESPONSE"},
    102 	{KMF_ERR_OCSP_RESPONSE_STATUS,	"KMF_ERR_OCSP_RESPONSE_STATUS"},
    103 	{KMF_ERR_OCSP_NO_BASIC_RESPONSE, "KMF_ERR_OCSP_NO_BASIC_RESPONSE"},
    104 	{KMF_ERR_OCSP_BAD_SIGNER,	"KMF_ERR_OCSP_BAD_SIGNER"},
    105 	{KMF_ERR_OCSP_RESPONSE_SIGNATURE, "KMF_ERR_OCSP_RESPONSE_SIGNATURE"},
    106 	{KMF_ERR_OCSP_UNKNOWN_CERT,	"KMF_ERR_OCSP_UNKNOWN_CERT"},
    107 	{KMF_ERR_OCSP_STATUS_TIME_INVALID, "KMF_ERR_OCSP_STATUS_TIME_INVALID"},
    108 	{KMF_ERR_BAD_HTTP_RESPONSE,	"KMF_ERR_BAD_HTTP_RESPONSE"},
    109 	{KMF_ERR_RECV_RESPONSE,	"KMF_ERR_RECV_RESPONSE"},
    110 	{KMF_ERR_RECV_TIMEOUT,	"KMF_ERR_RECV_TIMEOUT"},
    111 	{KMF_ERR_DUPLICATE_KEYFILE,	"KMF_ERR_DUPLICATE_KEYFILE"},
    112 	{KMF_ERR_AMBIGUOUS_PATHNAME,	"KMF_ERR_AMBIGUOUS_PATHNAME"},
    113 	{KMF_ERR_FUNCTION_NOT_FOUND,	"KMF_ERR_FUNCTION_NOT_FOUND"},
    114 	{KMF_ERR_PKCS12_FORMAT,	"KMF_ERR_PKCS12_FORMAT"},
    115 	{KMF_ERR_BAD_KEY_TYPE,	"KMF_ERR_BAD_KEY_TYPE"},
    116 	{KMF_ERR_BAD_KEY_CLASS,	"KMF_ERR_BAD_KEY_CLASS"},
    117 	{KMF_ERR_BAD_KEY_SIZE,	"KMF_ERR_BAD_KEY_SIZE"},
    118 	{KMF_ERR_BAD_HEX_STRING,	"KMF_ERR_BAD_HEX_STRING"},
    119 	{KMF_ERR_KEYUSAGE,	"KMF_ERR_KEYUSAGE"},
    120 	{KMF_ERR_VALIDITY_PERIOD,	"KMF_ERR_VALIDITY_PERIOD"},
    121 	{KMF_ERR_OCSP_REVOKED,	"KMF_ERR_OCSP_REVOKED"},
    122 	{KMF_ERR_CERT_MULTIPLE_FOUND,	"KMF_ERR_CERT_MULTIPLE_FOUND"},
    123 	{KMF_ERR_WRITE_FILE,	"KMF_ERR_WRITE_FILE"},
    124 	{KMF_ERR_BAD_URI,	"KMF_ERR_BAD_URI"},
    125 	{KMF_ERR_BAD_CRLFILE,	"KMF_ERR_BAD_CRLFILE"},
    126 	{KMF_ERR_BAD_CERTFILE,	"KMF_ERR_BAD_CERTFILE"},
    127 	{KMF_ERR_GETKEYVALUE_FAILED,	"KMF_ERR_GETKEYVALUE_FAILED"},
    128 	{KMF_ERR_BAD_KEYHANDLE,	"KMF_ERR_BAD_KEYHANDLE"},
    129 	{KMF_ERR_BAD_OBJECT_TYPE,	"KMF_ERR_BAD_OBJECT_TYPE"},
    130 	{KMF_ERR_OCSP_RESPONSE_LIFETIME, "KMF_ERR_OCSP_RESPONSE_LIFETIME"},
    131 	{KMF_ERR_UNKNOWN_CSR_ATTRIBUTE,	"KMF_ERR_UNKNOWN_CSR_ATTRIBUTE"},
    132 	{KMF_ERR_UNINITIALIZED_TOKEN,	"KMF_ERR_UNINITIALIZED_TOKEN"},
    133 	{KMF_ERR_INCOMPLETE_TBS_CERT,	"KMF_ERR_INCOMPLETE_TBS_CERT"},
    134 	{KMF_ERR_MISSING_ERRCODE,	"KMF_ERR_MISSING_ERRCODE"},
    135 	{KMF_KEYSTORE_ALREADY_INITIALIZED, "KMF_KEYSTORE_ALREADY_INITIALIZED"},
    136 	{KMF_ERR_SENSITIVE_KEY,		"KMF_ERR_SENSITIVE_KEY"},
    137 	{KMF_ERR_UNEXTRACTABLE_KEY,	"KMF_ERR_UNEXTRACTABLE_KEY"},
    138 	{KMF_ERR_KEY_MISMATCH,		"KMF_ERR_KEY_MISMATCH"},
    139 	{KMF_ERR_ATTR_NOT_FOUND,	"KMF_ERR_ATTR_NOT_FOUND"},
    140 	{KMF_ERR_KMF_CONF,		"KMF_ERR_KMF_CONF"}
    141 };
    142 
    143 typedef struct {
    144 	KMF_KEYSTORE_TYPE	kstype;
    145 	char			*path;
    146 	boolean_t		critical;
    147 } KMF_PLUGIN_ITEM;
    148 
    149 KMF_PLUGIN_ITEM plugin_list[] = {
    150 	{KMF_KEYSTORE_OPENSSL,	KMF_PLUGIN_PATH "kmf_openssl.so.1",  TRUE},
    151 	{KMF_KEYSTORE_PK11TOKEN, KMF_PLUGIN_PATH "kmf_pkcs11.so.1",  TRUE},
    152 	{KMF_KEYSTORE_NSS,	KMF_PLUGIN_PATH "kmf_nss.so.1",  FALSE}
    153 };
    154 
    155 
    156 
    157 static KMF_RETURN InitializePlugin(KMF_KEYSTORE_TYPE, char *, KMF_PLUGIN **);
    158 static KMF_RETURN AddPlugin(KMF_HANDLE_T, KMF_PLUGIN *);
    159 static void free_extensions(KMF_X509_EXTENSIONS *extns);
    160 static void DestroyPlugin(KMF_PLUGIN *);
    161 
    162 #if defined(__sparcv9)
    163 #define	ISA_PATH	"/sparcv9"
    164 #elif defined(__sparc)
    165 #define	ISA_PATH	"/"
    166 #elif defined(__i386)
    167 #define	ISA_PATH	"/"
    168 #elif defined(__amd64)
    169 #define	ISA_PATH	"/amd64"
    170 #endif
    171 
    172 #define	DEFAULT_KEYSTORE_NUM	3
    173 static int kstore_num = DEFAULT_KEYSTORE_NUM;
    174 conf_entrylist_t *extra_plugin_list = NULL;
    175 static boolean_t check_extra_plugin = B_FALSE;
    176 mutex_t extra_plugin_lock = DEFAULTMUTEX;
    177 
    178 KMF_RETURN
    179 init_pk11()
    180 {
    181 	(void) mutex_lock(&init_lock);
    182 	if (!pkcs11_initialized) {
    183 		CK_RV rv = C_Initialize(NULL);
    184 		if ((rv != CKR_OK) &&
    185 		    (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
    186 			(void) mutex_unlock(&init_lock);
    187 			return (KMF_ERR_UNINITIALIZED);
    188 		} else {
    189 			pkcs11_initialized = 1;
    190 		}
    191 	}
    192 	(void) mutex_unlock(&init_lock);
    193 	return (KMF_OK);
    194 }
    195 
    196 /*
    197  * Private method for searching the plugin list for the correct
    198  * Plugin to use.
    199  */
    200 KMF_PLUGIN *
    201 FindPlugin(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE kstype)
    202 {
    203 	KMF_PLUGIN_LIST *node;
    204 	KMF_RETURN ret = KMF_OK;
    205 	KMF_PLUGIN *pluginrec = NULL;
    206 
    207 	if (handle == NULL)
    208 		return (NULL);
    209 
    210 	node = handle->plugins;
    211 
    212 	/* See if the desired plugin was already initialized. */
    213 	while (node != NULL && node->plugin->type != kstype)
    214 		node = node->next;
    215 
    216 	if (node != NULL)
    217 		return (node->plugin);
    218 
    219 	/* The plugin was not found, try to initialize it here. */
    220 	if (VALID_DEFAULT_KEYSTORE_TYPE(kstype)) {
    221 		int i;
    222 		int numitems = sizeof (plugin_list)/sizeof (KMF_PLUGIN_ITEM);
    223 		for (i = 0; i < numitems; i++) {
    224 			if (plugin_list[i].kstype == kstype) {
    225 				ret = InitializePlugin(plugin_list[i].kstype,
    226 				    plugin_list[i].path, &pluginrec);
    227 				break;
    228 			}
    229 		}
    230 
    231 		goto out;
    232 
    233 	} else {
    234 		/*
    235 		 * Not a built-in plugin. Check if it is in the
    236 		 * extra_plugin_list.  If it is, try to initialize it here.
    237 		 */
    238 		conf_entrylist_t *phead = extra_plugin_list;
    239 		char realpath[MAXPATHLEN];
    240 
    241 		while (phead != NULL) {
    242 			if (phead->entry->kstype == kstype)
    243 				break;
    244 			else
    245 				phead = phead->next;
    246 		}
    247 
    248 		if (phead == NULL)
    249 			return (NULL);
    250 
    251 		/*
    252 		 * Get the absolute path of the module.
    253 		 * - If modulepath is not a full path, then prepend it
    254 		 *   with KMF_PLUGIN_PATH.
    255 		 * - If modulepath is a full path and contain $ISA, then
    256 		 *   subsitute the architecture dependent path.
    257 		 */
    258 		(void) memset(realpath, 0, sizeof (realpath));
    259 		if (strncmp(phead->entry->modulepath, "/", 1) != 0) {
    260 			(void) snprintf(realpath, MAXPATHLEN, "%s%s",
    261 			    KMF_PLUGIN_PATH, phead->entry->modulepath);
    262 		} else {
    263 			char *buf = phead->entry->modulepath;
    264 			char *isa;
    265 
    266 			if ((isa = strstr(buf, PKCS11_ISA)) != NULL) {
    267 				char *isa_str;
    268 
    269 				(void) strncpy(realpath, buf, isa - buf);
    270 				isa_str = strdup(ISA_PATH);
    271 				if (isa_str == NULL) /* not enough memory */
    272 					return (NULL);
    273 
    274 				(void) strncat(realpath, isa_str,
    275 				    strlen(isa_str));
    276 				free(isa_str);
    277 
    278 				isa += strlen(PKCS11_ISA);
    279 				(void) strlcat(realpath, isa, MAXPATHLEN);
    280 			} else {
    281 				(void) snprintf(realpath, MAXPATHLEN, "%s",
    282 				    phead->entry->modulepath);
    283 			}
    284 		}
    285 
    286 		ret = InitializePlugin(phead->entry->kstype, realpath,
    287 		    &pluginrec);
    288 		goto out;
    289 	}
    290 
    291 out:
    292 	if (ret != KMF_OK || pluginrec == NULL)
    293 		/* No matching plugins found in the built-in list */
    294 		return (NULL);
    295 
    296 	ret = AddPlugin(handle, pluginrec);
    297 	if (ret != KMF_OK) {
    298 		DestroyPlugin(pluginrec);
    299 		pluginrec = NULL;
    300 	}
    301 	return (pluginrec);
    302 }
    303 
    304 
    305 static KMF_RETURN
    306 InitializePlugin(KMF_KEYSTORE_TYPE kstype, char *path, KMF_PLUGIN **plugin)
    307 {
    308 	KMF_PLUGIN *p = NULL;
    309 	KMF_PLUGIN_FUNCLIST *(*sym)();
    310 
    311 	if (path == NULL || plugin == NULL)
    312 		return (KMF_ERR_BAD_PARAMETER);
    313 
    314 	*plugin = NULL;
    315 
    316 	p = (KMF_PLUGIN *)malloc(sizeof (KMF_PLUGIN));
    317 	if (p == NULL)
    318 		return (KMF_ERR_MEMORY);
    319 
    320 	p->type = kstype;
    321 	p->path = strdup(path);
    322 	if (p->path == NULL) {
    323 		free(p);
    324 		return (KMF_ERR_MEMORY);
    325 	}
    326 	/*
    327 	 * Do not use RTLD_GROUP here, or this will cause a circular
    328 	 * dependency when kmf_pkcs11.so.1 gets its PKCS#11 functions
    329 	 * from libpkcs11.so.1 when kmf is used via libelfsign.so.1
    330 	 * called from kcfd.
    331 	 */
    332 	p->dldesc = dlopen(path, RTLD_LAZY | RTLD_PARENT);
    333 	if (p->dldesc == NULL) {
    334 		free(p->path);
    335 		free(p);
    336 		return (KMF_ERR_PLUGIN_INIT);
    337 	}
    338 
    339 	sym = (KMF_PLUGIN_FUNCLIST *(*)())dlsym(p->dldesc,
    340 	    KMF_PLUGIN_INIT_SYMBOL);
    341 	if (sym == NULL) {
    342 		(void) dlclose(p->dldesc);
    343 		free(p->path);
    344 		free(p);
    345 		return (KMF_ERR_PLUGIN_INIT);
    346 	}
    347 
    348 	/* Get the function list */
    349 	if ((p->funclist = (*sym)()) == NULL) {
    350 		(void) dlclose(p->dldesc);
    351 		free(p->path);
    352 		free(p);
    353 		return (KMF_ERR_PLUGIN_INIT);
    354 	}
    355 
    356 	*plugin = p;
    357 
    358 	return (KMF_OK);
    359 }
    360 
    361 static KMF_RETURN
    362 AddPlugin(KMF_HANDLE_T handle, KMF_PLUGIN *plugin)
    363 {
    364 	KMF_PLUGIN_LIST *n;
    365 
    366 	if (handle == NULL || plugin == NULL)
    367 		return (KMF_ERR_BAD_PARAMETER);
    368 
    369 	/* If the head is NULL, create it */
    370 	if (handle->plugins == NULL) {
    371 		handle->plugins = (KMF_PLUGIN_LIST *)malloc(
    372 		    sizeof (KMF_PLUGIN_LIST));
    373 		if (handle->plugins == NULL)
    374 			return (KMF_ERR_MEMORY);
    375 		handle->plugins->plugin = plugin;
    376 		handle->plugins->next = NULL;
    377 	} else {
    378 		/* walk the list to find the tail */
    379 		n = handle->plugins;
    380 		while (n->next != NULL)
    381 			n = n->next;
    382 		n->next = (KMF_PLUGIN_LIST *)malloc(sizeof (KMF_PLUGIN_LIST));
    383 		if (n->next == NULL)
    384 			return (KMF_ERR_MEMORY);
    385 
    386 		n->next->plugin = plugin;
    387 		n->next->next = NULL;
    388 	}
    389 	return (0);
    390 }
    391 
    392 static void
    393 DestroyPlugin(KMF_PLUGIN *plugin)
    394 {
    395 	if (plugin) {
    396 		if (plugin->path)
    397 			free(plugin->path);
    398 		free(plugin);
    399 	}
    400 }
    401 
    402 static void
    403 Cleanup_KMF_Handle(KMF_HANDLE_T handle)
    404 {
    405 	if (handle != NULL) {
    406 		while (handle->plugins != NULL) {
    407 			KMF_PLUGIN_LIST *next = handle->plugins->next;
    408 
    409 			DestroyPlugin(handle->plugins->plugin);
    410 			free(handle->plugins);
    411 			handle->plugins = next;
    412 		}
    413 		kmf_free_policy_record(handle->policy);
    414 		free(handle->policy);
    415 	}
    416 	free(handle);
    417 }
    418 
    419 void
    420 Cleanup_PK11_Session(KMF_HANDLE_T handle)
    421 {
    422 	if (handle != NULL) {
    423 		/* Close active session on a pkcs11 token */
    424 		if (handle->pk11handle != NULL) {
    425 			(void) C_CloseSession(handle->pk11handle);
    426 			handle->pk11handle = NULL;
    427 		}
    428 	}
    429 }
    430 
    431 KMF_RETURN
    432 kmf_initialize(KMF_HANDLE_T *outhandle, char *policyfile, char *policyname)
    433 {
    434 	KMF_RETURN ret = KMF_OK;
    435 	KMF_HANDLE *handle = NULL;
    436 
    437 	if (outhandle == NULL)
    438 		return (KMF_ERR_BAD_PARAMETER);
    439 
    440 	*outhandle = NULL;
    441 	handle = (KMF_HANDLE *)malloc(sizeof (KMF_HANDLE));
    442 	if (handle == NULL)
    443 		return (KMF_ERR_MEMORY);
    444 
    445 	(void) memset(handle, 0, sizeof (KMF_HANDLE));
    446 	handle->plugins = NULL;
    447 
    448 	/*
    449 	 * When this function is called the first time, get the additional
    450 	 * plugins from the config file.
    451 	 */
    452 	(void) mutex_lock(&extra_plugin_lock);
    453 	if (!check_extra_plugin) {
    454 
    455 		ret = get_entrylist(&extra_plugin_list);
    456 		check_extra_plugin = B_TRUE;
    457 
    458 		/*
    459 		 * Assign the kstype number to the additional plugins here.
    460 		 * The global kstore_num will be protected by the mutex lock.
    461 		 */
    462 		if (ret == KMF_OK) {
    463 			conf_entrylist_t *phead = extra_plugin_list;
    464 			while (phead != NULL) {
    465 				phead->entry->kstype = ++kstore_num;
    466 				phead = phead->next;
    467 			}
    468 		}
    469 
    470 		/*
    471 		 * If the KMF configuration file does not exist or cannot be
    472 		 * parsed correctly, we will give a warning in syslog and
    473 		 * continue on as there is no extra plugins in the system.
    474 		 */
    475 		if (ret == KMF_ERR_KMF_CONF) {
    476 			cryptoerror(LOG_WARNING, "KMF was unable to parse "
    477 			    "the private KMF config file.\n");
    478 			ret = KMF_OK;
    479 		}
    480 
    481 		if (ret != KMF_OK) {
    482 			(void) mutex_unlock(&extra_plugin_lock);
    483 			goto errout;
    484 		}
    485 	}
    486 	(void) mutex_unlock(&extra_plugin_lock);
    487 
    488 	/* Initialize the handle with the policy */
    489 	ret = kmf_set_policy((void *)handle,
    490 	    policyfile == NULL ? KMF_DEFAULT_POLICY_FILE : policyfile,
    491 	    policyname == NULL ? KMF_DEFAULT_POLICY_NAME : policyname);
    492 	if (ret != KMF_OK)
    493 		goto errout;
    494 
    495 	CLEAR_ERROR(handle, ret);
    496 errout:
    497 	if (ret != KMF_OK) {
    498 		Cleanup_KMF_Handle(handle);
    499 		handle = NULL;
    500 	}
    501 
    502 	*outhandle = (KMF_HANDLE_T)handle;
    503 	return (ret);
    504 }
    505 
    506 KMF_RETURN
    507 kmf_configure_keystore(KMF_HANDLE_T handle,
    508 	int	num_args,
    509 	KMF_ATTRIBUTE	*attrlist)
    510 {
    511 	KMF_RETURN ret = KMF_OK;
    512 	KMF_PLUGIN *plugin;
    513 	KMF_KEYSTORE_TYPE kstype;
    514 	uint32_t len;
    515 
    516 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
    517 		{KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
    518 	};
    519 
    520 	int num_req_attrs = sizeof (required_attrs) /
    521 	    sizeof (KMF_ATTRIBUTE_TESTER);
    522 
    523 	if (handle == NULL)
    524 		return (KMF_ERR_BAD_PARAMETER);
    525 
    526 	CLEAR_ERROR(handle, ret);
    527 
    528 	ret = test_attributes(num_req_attrs, required_attrs,
    529 	    0, NULL, num_args, attrlist);
    530 
    531 	if (ret != KMF_OK)
    532 		return (ret);
    533 
    534 	len = sizeof (kstype);
    535 	ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, num_args,
    536 	    &kstype, &len);
    537 	if (ret != KMF_OK)
    538 		return (ret);
    539 
    540 	plugin = FindPlugin(handle, kstype);
    541 	if (plugin != NULL && plugin->funclist->ConfigureKeystore != NULL) {
    542 		return (plugin->funclist->ConfigureKeystore(handle, num_args,
    543 		    attrlist));
    544 	} else {
    545 		/* return KMF_OK, if the plugin does not have an entry */
    546 		return (KMF_OK);
    547 	}
    548 }
    549 
    550 KMF_RETURN
    551 kmf_finalize(KMF_HANDLE_T handle)
    552 {
    553 	KMF_RETURN ret = KMF_OK;
    554 
    555 	CLEAR_ERROR(handle, ret);
    556 	if (ret != KMF_OK)
    557 		return (ret);
    558 
    559 	if (pkcs11_initialized) {
    560 		Cleanup_PK11_Session(handle);
    561 	}
    562 	Cleanup_KMF_Handle(handle);
    563 
    564 	return (ret);
    565 }
    566 
    567 KMF_RETURN
    568 kmf_get_kmf_error_str(KMF_RETURN errcode, char **errmsg)
    569 {
    570 	KMF_RETURN ret = KMF_OK;
    571 	int i, maxerr;
    572 
    573 	if (errmsg == NULL)
    574 		return (KMF_ERR_BAD_PARAMETER);
    575 
    576 	*errmsg = NULL;
    577 	maxerr = sizeof (kmf_errcodes) / sizeof (kmf_error_map);
    578 
    579 	for (i = 0; i < maxerr && errcode != kmf_errcodes[i].code; i++)
    580 		/* empty body */
    581 		;
    582 
    583 	if (i == maxerr)
    584 		return (KMF_ERR_MISSING_ERRCODE);
    585 	else {
    586 		*errmsg = strdup(kmf_errcodes[i].message);
    587 		if ((*errmsg) == NULL)
    588 			return (KMF_ERR_MEMORY);
    589 	}
    590 	return (ret);
    591 }
    592 
    593 KMF_RETURN
    594 kmf_get_plugin_error_str(KMF_HANDLE_T handle, char **msgstr)
    595 {
    596 	KMF_RETURN ret = KMF_OK;
    597 	KMF_PLUGIN *plugin;
    598 
    599 	if (handle == NULL || msgstr == NULL)
    600 		return (KMF_ERR_BAD_PARAMETER);
    601 
    602 	*msgstr = NULL;
    603 
    604 	if (handle->lasterr.errcode == 0) {
    605 		return (KMF_ERR_MISSING_ERRCODE);
    606 	}
    607 
    608 	if (handle->lasterr.kstype == -1) { /* System error */
    609 		char *str = strerror(handle->lasterr.errcode);
    610 		if (str != NULL) {
    611 			*msgstr = strdup(str);
    612 			if ((*msgstr) == NULL)
    613 				return (KMF_ERR_MEMORY);
    614 		}
    615 		return (KMF_OK);
    616 	}
    617 
    618 	plugin = FindPlugin(handle, handle->lasterr.kstype);
    619 	if (plugin == NULL)
    620 		return (KMF_ERR_PLUGIN_NOTFOUND);
    621 
    622 	if (plugin->funclist->GetErrorString != NULL) {
    623 		ret = plugin->funclist->GetErrorString(handle, msgstr);
    624 	} else {
    625 		return (KMF_ERR_FUNCTION_NOT_FOUND);
    626 	}
    627 
    628 	return (ret);
    629 }
    630 
    631 
    632 #define	SET_SYS_ERROR(h, c) if (h) {\
    633 	h->lasterr.kstype = -1;\
    634 	h->lasterr.errcode = c;\
    635 }
    636 
    637 KMF_RETURN
    638 kmf_read_input_file(KMF_HANDLE_T handle, char *filename,  KMF_DATA *pdata)
    639 {
    640 	struct stat s;
    641 	long nread, total = 0;
    642 	int fd;
    643 	unsigned char *buf = NULL;
    644 	KMF_RETURN ret;
    645 
    646 	if (handle) {
    647 		CLEAR_ERROR(handle, ret);
    648 		if (ret != KMF_OK)
    649 			return (ret);
    650 	}
    651 
    652 	if (filename == NULL || pdata == NULL) {
    653 		return (KMF_ERR_BAD_PARAMETER);
    654 	}
    655 
    656 	if ((fd = open(filename, O_RDONLY)) < 0) {
    657 		SET_SYS_ERROR(handle, errno);
    658 		return (KMF_ERR_OPEN_FILE);
    659 	}
    660 
    661 	if (fstat(fd, &s) < 0) {
    662 		SET_SYS_ERROR(handle, errno);
    663 		(void) close(fd);
    664 		return (KMF_ERR_OPEN_FILE);
    665 	}
    666 
    667 	if ((buf = (unsigned char *) malloc(s.st_size)) == NULL) {
    668 		(void) close(fd);
    669 		return (KMF_ERR_MEMORY);
    670 	}
    671 
    672 	do {
    673 		nread = read(fd, buf+total, s.st_size-total);
    674 		if (nread < 0) {
    675 			SET_SYS_ERROR(handle, errno);
    676 			(void) close(fd);
    677 			free(buf);
    678 			return (KMF_ERR_INTERNAL);
    679 		}
    680 		total += nread;
    681 	} while (total < s.st_size);
    682 
    683 	pdata->Data = buf;
    684 	pdata->Length = s.st_size;
    685 	(void) close(fd);
    686 	return (KMF_OK);
    687 }
    688 
    689 /*
    690  *
    691  * Name: kmf_der_to_pem
    692  *
    693  * Description:
    694  *   Function for converting DER encoded format to PEM encoded format
    695  *
    696  * Parameters:
    697  *   type(input) - CERTIFICATE or CSR
    698  *   data(input) - pointer to the DER encoded data
    699  *   len(input)  - length of input data
    700  *   out(output) - contains the output buffer address to be returned
    701  *   outlen(output) - pointer to the returned output length
    702  *
    703  * Returns:
    704  *   A KMF_RETURN value indicating success or specifying a particular
    705  * error condition.
    706  *   The value KMF_OK indicates success. All other values represent
    707  * an error condition.
    708  *
    709  */
    710 KMF_RETURN
    711 kmf_der_to_pem(KMF_OBJECT_TYPE type, unsigned char *data,
    712 	int len, unsigned char **out, int *outlen)
    713 {
    714 
    715 	KMF_RETURN err;
    716 	if (data == NULL || out == NULL || outlen == NULL)
    717 		return (KMF_ERR_BAD_PARAMETER);
    718 
    719 	err = Der2Pem(type, data, len, out, outlen);
    720 	return (err);
    721 
    722 }
    723 
    724 /*
    725  *
    726  * Name: kmf_pem_to_der
    727  *
    728  * Description:
    729  *   Function for converting PEM encoded format to DER encoded format
    730  *
    731  * Parameters:
    732  *   in(input) - pointer to the PEM encoded data
    733  *   inlen(input)  - length of input data
    734  *   out(output) - contains the output buffer address to be returned
    735  *   outlen(output) - pointer to the returned output length
    736  *
    737  * Returns:
    738  *   A KMF_RETURN value indicating success or specifying a particular
    739  *   error condition.
    740  *   The value KMF_OK indicates success. All other values represent
    741  *   an error condition.
    742  *
    743  */
    744 KMF_RETURN
    745 kmf_pem_to_der(unsigned char *in, int inlen,
    746 	unsigned char **out, int *outlen)
    747 {
    748 	KMF_RETURN err;
    749 	if (in == NULL || out == NULL || outlen == NULL)
    750 		return (KMF_ERR_BAD_PARAMETER);
    751 
    752 	err = Pem2Der(in, inlen, out, outlen);
    753 	return (err);
    754 }
    755 
    756 char *
    757 kmf_oid_to_string(KMF_OID *oid)
    758 {
    759 	char numstr[128];
    760 	uint32_t number;
    761 	int numshift;
    762 	uint32_t i, string_length;
    763 	uchar_t *cp;
    764 	char *bp;
    765 
    766 	/* First determine the size of the string */
    767 	string_length = 0;
    768 	number = 0;
    769 	numshift = 0;
    770 	cp = (unsigned char *)oid->Data;
    771 
    772 	number = (uint32_t)cp[0];
    773 	(void) sprintf(numstr, "%d ", number/40);
    774 
    775 	string_length += strlen(numstr);
    776 	(void) sprintf(numstr, "%d ", number%40);
    777 
    778 	string_length += strlen(numstr);
    779 
    780 	for (i = 1; i < oid->Length; i++) {
    781 		if ((uint32_t)(numshift+7) < (sizeof (uint32_t)*8)) {
    782 			number = (number << 7) | (cp[i] & 0x7f);
    783 			numshift += 7;
    784 		} else {
    785 			return (NULL);
    786 		}
    787 
    788 		if ((cp[i] & 0x80) == 0) {
    789 			(void) sprintf(numstr, "%d ", number);
    790 			string_length += strlen(numstr);
    791 			number = 0;
    792 			numshift = 0;
    793 		}
    794 	}
    795 	/*
    796 	 * If we get here, we've calculated the length of "n n n ... n ".  Add 4
    797 	 * here for "{ " and "}\0".
    798 	 */
    799 	string_length += 4;
    800 	if ((bp = (char *)malloc(string_length))) {
    801 		number = (uint32_t)cp[0];
    802 
    803 		(void) sprintf(numstr, "%d.", number/40);
    804 		(void) strcpy(bp, numstr);
    805 
    806 		(void) sprintf(numstr, "%d.", number%40);
    807 		(void) strcat(bp, numstr);
    808 
    809 		number = 0;
    810 		cp = (unsigned char *) oid->Data;
    811 		for (i = 1; i < oid->Length; i++) {
    812 			number = (number << 7) | (cp[i] & 0x7f);
    813 			if ((cp[i] & 0x80) == 0) {
    814 				(void) sprintf(numstr, "%d", number);
    815 				(void) strcat(bp, numstr);
    816 				number = 0;
    817 				if (i+1 < oid->Length)
    818 					(void) strcat(bp, ".");
    819 			}
    820 		}
    821 	}
    822 	return (bp);
    823 }
    824 
    825 static boolean_t
    826 check_for_pem(uchar_t *buf, KMF_ENCODE_FORMAT *fmt)
    827 {
    828 	char *p;
    829 	int i;
    830 
    831 	if (buf == NULL)
    832 		return (FALSE);
    833 
    834 	for (i = 0; i < 8 && isascii(buf[i]); i++)
    835 		/* loop to make sure this is ascii */;
    836 	if (i != 8)
    837 		return (FALSE);
    838 
    839 	if (memcmp(buf, "Bag Attr", 8) == 0) {
    840 		*fmt = KMF_FORMAT_PEM_KEYPAIR;
    841 		return (TRUE);
    842 	}
    843 
    844 	/* Look for "-----BEGIN" right after a newline */
    845 	p = strtok((char *)buf, "\n");
    846 	while (p != NULL) {
    847 		if (strstr(p, "-----BEGIN") != NULL) {
    848 			*fmt = KMF_FORMAT_PEM;
    849 			/* Restore the buffer */
    850 			buf[strlen(p)] = '\n';
    851 			return (TRUE);
    852 		}
    853 		buf[strlen(p)] = '\n';
    854 		p = strtok(NULL, "\n");
    855 	}
    856 	return (FALSE);
    857 }
    858 
    859 
    860 static unsigned char pkcs12_version[3] = {0x02, 0x01, 0x03};
    861 static unsigned char pkcs12_oid[11] =
    862 {0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01};
    863 
    864 /*
    865  * This function takes a BER encoded string as input and checks the version
    866  * and the oid in the the top-level ASN.1 structure to see if it complies to
    867  * the PKCS#12 Syntax.
    868  */
    869 static boolean_t
    870 check_for_pkcs12(uchar_t *buf, int buf_len)
    871 {
    872 	int index = 0;
    873 	int length_octets;
    874 
    875 	if (buf == NULL || buf_len <= 0)
    876 		return (FALSE);
    877 
    878 	/*
    879 	 * The top level structure for a PKCS12 string:
    880 	 *
    881 	 * PFX ::= SEQUENCE {
    882 	 *	version		INTEGER {v3(3)}(v3,...)
    883 	 *	authSafe	ContentInfo
    884 	 *	macData		MacData OPTIONAL
    885 	 * }
    886 	 *
    887 	 * ContentInfo
    888 	 *	FROM PKCS-7 {iso(1) member-body(2) us(840) rsadsi(113549)
    889 	 *		pkcs(1) pkcs-7(7) modules(0) pkcs-7(1)}
    890 	 *
    891 	 * Therefore, the BER/DER dump of a PKCS#12 file for the first 2
    892 	 * sequences up to the oid part is as following:
    893 	 *
    894 	 *	SEQUENCE {
    895 	 *	    INTEGER 3
    896 	 *	    SEQUENCE {
    897 	 *		OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
    898 	 */
    899 
    900 	/*
    901 	 * Check the first sequence and calculate the number of bytes used
    902 	 * to store the length.
    903 	 */
    904 	if (buf[index++] != 0x30)
    905 		return (FALSE);
    906 
    907 	if (buf[index] & 0x80) {
    908 		length_octets = buf[index++] & 0x0F;  /* long form */
    909 	} else {
    910 		length_octets = 1; /* short form */
    911 	}
    912 
    913 	index += length_octets;
    914 	if (index  >= buf_len)
    915 		return (FALSE);
    916 
    917 	/* Skip the length octets and check the pkcs12 version */
    918 	if (memcmp(buf + index, pkcs12_version, sizeof (pkcs12_version)) != 0)
    919 		return (FALSE);
    920 
    921 	index += sizeof (pkcs12_version);
    922 	if (index  >= buf_len)
    923 		return (FALSE);
    924 
    925 	/*
    926 	 * Check the 2nd sequence and calculate the number of bytes used
    927 	 * to store the length.
    928 	 */
    929 	if ((buf[index++] & 0xFF) != 0x30)
    930 		return (FALSE);
    931 
    932 	if (buf[index] & 0x80) {
    933 		length_octets = buf[index++] & 0x0F;
    934 	} else {
    935 		length_octets = 1;
    936 	}
    937 
    938 	index += length_octets;
    939 	if (index + sizeof (pkcs12_oid) >= buf_len)
    940 		return (FALSE);
    941 
    942 	/* Skip the length octets and check the oid */
    943 	if (memcmp(buf + index, pkcs12_oid, sizeof (pkcs12_oid)) != 0)
    944 		return (FALSE);
    945 	else
    946 		return (TRUE);
    947 }
    948 
    949 KMF_RETURN
    950 kmf_get_data_format(KMF_DATA *data, KMF_ENCODE_FORMAT *fmt)
    951 {
    952 	uchar_t *buf = data->Data;
    953 
    954 	if (check_for_pkcs12(buf, data->Length) == TRUE) {
    955 		*fmt = KMF_FORMAT_PKCS12;
    956 	} else if (buf[0] == 0x30 && (buf[1] & 0x80)) {
    957 		/* It is most likely a generic ASN.1 encoded file */
    958 		*fmt = KMF_FORMAT_ASN1;
    959 	} else if (check_for_pem(buf, fmt) != TRUE) {
    960 		/* Cannot determine this file format */
    961 		*fmt = KMF_FORMAT_UNDEF;
    962 		return (KMF_ERR_ENCODING);
    963 	}
    964 	return (KMF_OK);
    965 }
    966 
    967 KMF_RETURN
    968 kmf_get_file_format(char *filename, KMF_ENCODE_FORMAT *fmt)
    969 {
    970 	KMF_RETURN ret = KMF_OK;
    971 	KMF_DATA filebuf = {NULL, 0};
    972 
    973 	if (filename == NULL || !strlen(filename) || fmt == NULL)
    974 		return (KMF_ERR_BAD_PARAMETER);
    975 
    976 	*fmt = 0;
    977 	ret = kmf_read_input_file(NULL, filename, &filebuf);
    978 	if (ret != KMF_OK)
    979 		return (ret);
    980 
    981 	if (filebuf.Length < 8) {
    982 		ret = KMF_ERR_ENCODING; /* too small */
    983 		goto end;
    984 	}
    985 
    986 	ret = kmf_get_data_format(&filebuf, fmt);
    987 end:
    988 	kmf_free_data(&filebuf);
    989 	return (ret);
    990 }
    991 
    992 KMF_RETURN
    993 kmf_hexstr_to_bytes(unsigned char *hexstr, unsigned char **bytes,
    994 	size_t *outlen)
    995 {
    996 	KMF_RETURN ret = KMF_OK;
    997 	unsigned char *buf = NULL;
    998 	int len, stringlen;
    999 	int i;
   1000 	unsigned char ch;
   1001 
   1002 	if (hexstr == NULL) {
   1003 		return (KMF_ERR_BAD_PARAMETER);
   1004 	}
   1005 
   1006 	if (hexstr[0] == '0' && ((hexstr[1] == 'x') || (hexstr[1] == 'X')))
   1007 		hexstr += 2;
   1008 
   1009 	for (i = 0; i < strlen((char *)hexstr) && isxdigit(hexstr[i]); i++)
   1010 		/* empty body */
   1011 		;
   1012 	/*
   1013 	 * If all the characters are not legitimate hex chars,
   1014 	 * return an error.
   1015 	 */
   1016 	if (i != strlen((char *)hexstr))
   1017 		return (KMF_ERR_BAD_HEX_STRING);
   1018 	stringlen = i;
   1019 	len = (i / 2) + (i % 2);
   1020 
   1021 	buf = malloc(len);
   1022 	if (buf == NULL) {
   1023 		return (KMF_ERR_MEMORY);
   1024 	}
   1025 	(void) memset(buf, 0, len);
   1026 
   1027 	for (i = 0; i < stringlen; i++) {
   1028 		ch = (unsigned char) *hexstr;
   1029 		hexstr++;
   1030 		if ((ch >= '0') && (ch <= '9'))
   1031 			ch -= '0';
   1032 		else if ((ch >= 'A') && (ch <= 'F'))
   1033 			ch = ch - 'A' + 10;
   1034 		else if ((ch >= 'a') && (ch <= 'f'))
   1035 			ch = ch - 'a' + 10;
   1036 		else {
   1037 			ret = KMF_ERR_BAD_HEX_STRING;
   1038 			goto out;
   1039 		}
   1040 
   1041 		if (i & 1) {
   1042 			buf[i/2] |= ch;
   1043 		} else {
   1044 			buf[i/2] = (ch << 4);
   1045 		}
   1046 	}
   1047 
   1048 	*bytes = buf;
   1049 	*outlen = len;
   1050 out:
   1051 	if (buf != NULL && ret != KMF_OK) {
   1052 		free(buf);
   1053 	}
   1054 	return (ret);
   1055 }
   1056 
   1057 void
   1058 kmf_free_dn(KMF_X509_NAME *name)
   1059 {
   1060 	KMF_X509_RDN 		*newrdn = NULL;
   1061 	KMF_X509_TYPE_VALUE_PAIR *av = NULL;
   1062 	int i, j;
   1063 
   1064 	if (name && name->numberOfRDNs) {
   1065 		for (i = 0; i < name->numberOfRDNs; i++) {
   1066 			newrdn = &name->RelativeDistinguishedName[i];
   1067 			for (j = 0; j < newrdn->numberOfPairs; j++) {
   1068 				av = &newrdn->AttributeTypeAndValue[j];
   1069 				kmf_free_data(&av->type);
   1070 				kmf_free_data(&av->value);
   1071 			}
   1072 			free(newrdn->AttributeTypeAndValue);
   1073 			newrdn->numberOfPairs = 0;
   1074 			newrdn->AttributeTypeAndValue = NULL;
   1075 		}
   1076 		free(name->RelativeDistinguishedName);
   1077 		name->numberOfRDNs = 0;
   1078 		name->RelativeDistinguishedName = NULL;
   1079 	}
   1080 }
   1081 
   1082 void
   1083 kmf_free_kmf_cert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
   1084 {
   1085 	KMF_PLUGIN *plugin;
   1086 	KMF_RETURN ret;
   1087 
   1088 	CLEAR_ERROR(handle, ret);
   1089 	if (ret != KMF_OK)
   1090 		return;
   1091 
   1092 	if (kmf_cert == NULL)
   1093 		return;
   1094 
   1095 	plugin = FindPlugin(handle, kmf_cert->kmf_private.keystore_type);
   1096 
   1097 	if (plugin != NULL && plugin->funclist->FreeKMFCert != NULL) {
   1098 		plugin->funclist->FreeKMFCert(handle, kmf_cert);
   1099 	}
   1100 }
   1101 
   1102 void
   1103 kmf_free_data(KMF_DATA *datablock)
   1104 {
   1105 	if (datablock != NULL && datablock->Data != NULL) {
   1106 		free(datablock->Data);
   1107 		datablock->Data = NULL;
   1108 		datablock->Length = 0;
   1109 	}
   1110 }
   1111 
   1112 void
   1113 kmf_free_algoid(KMF_X509_ALGORITHM_IDENTIFIER *algoid)
   1114 {
   1115 	if (algoid == NULL)
   1116 		return;
   1117 	kmf_free_data(&algoid->algorithm);
   1118 	kmf_free_data(&algoid->parameters);
   1119 }
   1120 
   1121 void
   1122 kmf_free_extn(KMF_X509_EXTENSION *exptr)
   1123 {
   1124 	if (exptr == NULL)
   1125 		return;
   1126 
   1127 	kmf_free_data((KMF_DATA *)&exptr->extnId);
   1128 	kmf_free_data(&exptr->BERvalue);
   1129 
   1130 	if (exptr->value.tagAndValue) {
   1131 		kmf_free_data(&exptr->value.tagAndValue->value);
   1132 		free(exptr->value.tagAndValue);
   1133 	}
   1134 }
   1135 
   1136 void
   1137 kmf_free_tbs_csr(KMF_TBS_CSR *tbscsr)
   1138 {
   1139 	if (tbscsr) {
   1140 		kmf_free_data(&tbscsr->version);
   1141 
   1142 		kmf_free_dn(&tbscsr->subject);
   1143 
   1144 		kmf_free_algoid(&tbscsr->subjectPublicKeyInfo.algorithm);
   1145 		kmf_free_data(&tbscsr->subjectPublicKeyInfo.subjectPublicKey);
   1146 
   1147 		free_extensions(&tbscsr->extensions);
   1148 	}
   1149 }
   1150 
   1151 void
   1152 kmf_free_signed_csr(KMF_CSR_DATA *csr)
   1153 {
   1154 	if (csr) {
   1155 		kmf_free_tbs_csr(&csr->csr);
   1156 
   1157 		kmf_free_algoid(&csr->signature.algorithmIdentifier);
   1158 		kmf_free_data(&csr->signature.encrypted);
   1159 	}
   1160 }
   1161 
   1162 static void
   1163 free_validity(KMF_X509_VALIDITY *validity)
   1164 {
   1165 	if (validity == NULL)
   1166 		return;
   1167 	kmf_free_data(&validity->notBefore.time);
   1168 	kmf_free_data(&validity->notAfter.time);
   1169 }
   1170 
   1171 static void
   1172 free_extensions(KMF_X509_EXTENSIONS *extns)
   1173 {
   1174 	int i;
   1175 	KMF_X509_EXTENSION *exptr;
   1176 
   1177 	if (extns && extns->numberOfExtensions > 0) {
   1178 		for (i = 0; i < extns->numberOfExtensions; i++) {
   1179 			exptr = &extns->extensions[i];
   1180 			kmf_free_extn(exptr);
   1181 		}
   1182 		free(extns->extensions);
   1183 		extns->numberOfExtensions = 0;
   1184 		extns->extensions = NULL;
   1185 	}
   1186 }
   1187 
   1188 void
   1189 kmf_free_tbs_cert(KMF_X509_TBS_CERT *tbscert)
   1190 {
   1191 	if (tbscert) {
   1192 		kmf_free_data(&tbscert->version);
   1193 		kmf_free_bigint(&tbscert->serialNumber);
   1194 		kmf_free_algoid(&tbscert->signature);
   1195 
   1196 		kmf_free_dn(&tbscert->issuer);
   1197 		kmf_free_dn(&tbscert->subject);
   1198 
   1199 		free_validity(&tbscert->validity);
   1200 
   1201 		kmf_free_data(&tbscert->issuerUniqueIdentifier);
   1202 		kmf_free_data(&tbscert->subjectUniqueIdentifier);
   1203 
   1204 		kmf_free_algoid(&tbscert->subjectPublicKeyInfo.algorithm);
   1205 		kmf_free_data(&tbscert->subjectPublicKeyInfo.subjectPublicKey);
   1206 
   1207 		free_extensions(&tbscert->extensions);
   1208 
   1209 		kmf_free_data(&tbscert->issuerUniqueIdentifier);
   1210 		kmf_free_data(&tbscert->subjectUniqueIdentifier);
   1211 	}
   1212 }
   1213 
   1214 void
   1215 kmf_free_signed_cert(KMF_X509_CERTIFICATE *certptr)
   1216 {
   1217 	if (!certptr)
   1218 		return;
   1219 
   1220 	kmf_free_tbs_cert(&certptr->certificate);
   1221 
   1222 	kmf_free_algoid(&certptr->signature.algorithmIdentifier);
   1223 	kmf_free_data(&certptr->signature.encrypted);
   1224 }
   1225 
   1226 void
   1227 kmf_free_str(char *pstr)
   1228 {
   1229 	if (pstr != NULL)
   1230 		free(pstr);
   1231 }
   1232 
   1233 void
   1234 free_keyidlist(KMF_OID *oidlist, int len)
   1235 {
   1236 	int i;
   1237 	for (i = 0; i < len; i++) {
   1238 		kmf_free_data((KMF_DATA *)&oidlist[i]);
   1239 	}
   1240 	free(oidlist);
   1241 }
   1242 
   1243 void
   1244 kmf_free_eku(KMF_X509EXT_EKU *eptr)
   1245 {
   1246 	if (eptr && eptr->nEKUs > 0 && eptr->keyPurposeIdList != NULL)
   1247 		free_keyidlist(eptr->keyPurposeIdList, eptr->nEKUs);
   1248 }
   1249 
   1250 void
   1251 kmf_free_spki(KMF_X509_SPKI *spki)
   1252 {
   1253 	if (spki != NULL) {
   1254 		kmf_free_algoid(&spki->algorithm);
   1255 		kmf_free_data(&spki->subjectPublicKey);
   1256 	}
   1257 }
   1258 
   1259 void
   1260 kmf_free_kmf_key(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key)
   1261 {
   1262 	KMF_PLUGIN *plugin;
   1263 	KMF_RETURN ret;
   1264 	KMF_ATTRIBUTE attlist[2]; /* only 2 attributes for DeleteKey op */
   1265 	int i = 0;
   1266 	boolean_t token_destroy = B_FALSE;
   1267 
   1268 	if (key == NULL)
   1269 		return;
   1270 
   1271 	CLEAR_ERROR(handle, ret);
   1272 	if (ret != KMF_OK)
   1273 		return;
   1274 
   1275 	kmf_set_attr_at_index(attlist, i,
   1276 	    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
   1277 	i++;
   1278 
   1279 	kmf_set_attr_at_index(attlist, i,
   1280 	    KMF_DESTROY_BOOL_ATTR, &token_destroy, sizeof (boolean_t));
   1281 	i++;
   1282 
   1283 	plugin = FindPlugin(handle, key->kstype);
   1284 	if (plugin != NULL && plugin->funclist->DeleteKey != NULL) {
   1285 		(void) plugin->funclist->DeleteKey(handle, i, attlist);
   1286 	}
   1287 
   1288 	if (key->keylabel)
   1289 		free(key->keylabel);
   1290 
   1291 	if (key->israw) {
   1292 		kmf_free_raw_key(key->keyp);
   1293 		free(key->keyp);
   1294 	}
   1295 
   1296 	(void) memset(key, 0, sizeof (KMF_KEY_HANDLE));
   1297 }
   1298 
   1299 void
   1300 kmf_free_bigint(KMF_BIGINT *big)
   1301 {
   1302 	if (big != NULL && big->val != NULL) {
   1303 		/* Clear it out before returning it to the pool */
   1304 		(void) memset(big->val, 0x00, big->len);
   1305 		free(big->val);
   1306 		big->val = NULL;
   1307 		big->len = 0;
   1308 	}
   1309 }
   1310 
   1311 static void
   1312 free_raw_rsa(KMF_RAW_RSA_KEY *key)
   1313 {
   1314 	if (key == NULL)
   1315 		return;
   1316 	kmf_free_bigint(&key->mod);
   1317 	kmf_free_bigint(&key->pubexp);
   1318 	kmf_free_bigint(&key->priexp);
   1319 	kmf_free_bigint(&key->prime1);
   1320 	kmf_free_bigint(&key->prime2);
   1321 	kmf_free_bigint(&key->exp1);
   1322 	kmf_free_bigint(&key->exp2);
   1323 	kmf_free_bigint(&key->coef);
   1324 }
   1325 
   1326 static void
   1327 free_raw_dsa(KMF_RAW_DSA_KEY *key)
   1328 {
   1329 	if (key == NULL)
   1330 		return;
   1331 	kmf_free_bigint(&key->prime);
   1332 	kmf_free_bigint(&key->subprime);
   1333 	kmf_free_bigint(&key->base);
   1334 	kmf_free_bigint(&key->value);
   1335 }
   1336 
   1337 static void
   1338 free_raw_sym(KMF_RAW_SYM_KEY *key)
   1339 {
   1340 	if (key == NULL)
   1341 		return;
   1342 	kmf_free_bigint(&key->keydata);
   1343 }
   1344 
   1345 void
   1346 kmf_free_raw_key(KMF_RAW_KEY_DATA *key)
   1347 {
   1348 	if (key == NULL)
   1349 		return;
   1350 
   1351 	switch (key->keytype) {
   1352 	case KMF_RSA:
   1353 		free_raw_rsa(&key->rawdata.rsa);
   1354 		break;
   1355 	case KMF_DSA:
   1356 		free_raw_dsa(&key->rawdata.dsa);
   1357 		break;
   1358 	case KMF_AES:
   1359 	case KMF_RC4:
   1360 	case KMF_DES:
   1361 	case KMF_DES3:
   1362 		free_raw_sym(&key->rawdata.sym);
   1363 		break;
   1364 	}
   1365 	if (key->label) {
   1366 		free(key->label);
   1367 		key->label = NULL;
   1368 	}
   1369 	kmf_free_data(&key->id);
   1370 }
   1371 
   1372 void
   1373 kmf_free_raw_sym_key(KMF_RAW_SYM_KEY *key)
   1374 {
   1375 	if (key == NULL)
   1376 		return;
   1377 	kmf_free_bigint(&key->keydata);
   1378 	free(key);
   1379 }
   1380 
   1381 /*
   1382  * This function frees the space allocated for the name portion of a
   1383  * KMF_CRL_DIST_POINT.
   1384  */
   1385 void
   1386 free_dp_name(KMF_CRL_DIST_POINT *dp)
   1387 {
   1388 	KMF_GENERALNAMES *fullname;
   1389 	KMF_DATA *urldata;
   1390 	int i;
   1391 
   1392 	if (dp == NULL)
   1393 		return;
   1394 
   1395 	/* For phase 1, we only need to free the fullname space. */
   1396 	fullname = &(dp->name.full_name);
   1397 	if (fullname->number == 0)
   1398 		return;
   1399 
   1400 	for (i = 0; i < fullname->number; i++) {
   1401 		urldata = &(fullname->namelist[fullname->number - 1].name);
   1402 		kmf_free_data(urldata);
   1403 	}
   1404 
   1405 	free(fullname->namelist);
   1406 }
   1407 
   1408 /*
   1409  * This function frees the space allocated for a KMF_CRL_DIST_POINT.
   1410  */
   1411 void
   1412 free_dp(KMF_CRL_DIST_POINT *dp)
   1413 {
   1414 	if (dp == NULL)
   1415 		return;
   1416 
   1417 	free_dp_name(dp);
   1418 	kmf_free_data(&(dp->reasons));
   1419 	/* Need not to free crl_issuer space at phase 1 */
   1420 }
   1421 
   1422 /*
   1423  * This function frees space for a KMF_X509EXT_CRLDISTPOINTS internally.
   1424  */
   1425 void
   1426 kmf_free_crl_dist_pts(KMF_X509EXT_CRLDISTPOINTS *crl_dps)
   1427 {
   1428 	int i;
   1429 
   1430 	if (crl_dps == NULL)
   1431 		return;
   1432 
   1433 	for (i = 0; i < crl_dps->number; i++)
   1434 		free_dp(&(crl_dps->dplist[i]));
   1435 
   1436 	free(crl_dps->dplist);
   1437 }
   1438 
   1439 KMF_RETURN
   1440 kmf_create_ocsp_request(KMF_HANDLE_T handle,
   1441 	int	num_args,
   1442 	KMF_ATTRIBUTE	*attrlist)
   1443 {
   1444 	KMF_RETURN ret = KMF_OK;
   1445 	KMF_PLUGIN *plugin;
   1446 	KMF_RETURN (*createReqFn)(void *, int num_args,
   1447 	    KMF_ATTRIBUTE *attrlist);
   1448 
   1449 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
   1450 		{KMF_OCSP_REQUEST_FILENAME_ATTR, FALSE, 1, 0},
   1451 		{KMF_USER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
   1452 			sizeof (KMF_DATA)},
   1453 		{KMF_ISSUER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
   1454 			sizeof (KMF_DATA)},
   1455 	};
   1456 
   1457 	int num_req_attrs = sizeof (required_attrs) /
   1458 	    sizeof (KMF_ATTRIBUTE_TESTER);
   1459 
   1460 	if (handle == NULL)
   1461 		return (KMF_ERR_BAD_PARAMETER);
   1462 
   1463 	CLEAR_ERROR(handle, ret);
   1464 
   1465 	ret = test_attributes(num_req_attrs, required_attrs,
   1466 	    0, NULL, num_args, attrlist);
   1467 
   1468 	if (ret != KMF_OK)
   1469 		return (ret);
   1470 
   1471 	/*
   1472 	 * This framework function is actually implemented in the openssl
   1473 	 * plugin library, so we find the function address and call it.
   1474 	 */
   1475 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
   1476 	if (plugin == NULL || plugin->dldesc == NULL) {
   1477 		return (KMF_ERR_PLUGIN_NOTFOUND);
   1478 	}
   1479 
   1480 	createReqFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
   1481 	    "OpenSSL_CreateOCSPRequest");
   1482 	if (createReqFn == NULL) {
   1483 		return (KMF_ERR_FUNCTION_NOT_FOUND);
   1484 	}
   1485 
   1486 	return (createReqFn(handle, num_args, attrlist));
   1487 
   1488 }
   1489 
   1490 KMF_RETURN
   1491 kmf_get_ocsp_status_for_cert(KMF_HANDLE_T handle,
   1492 	int	num_args,
   1493 	KMF_ATTRIBUTE	*attrlist)
   1494 {
   1495 	KMF_RETURN ret = KMF_OK;
   1496 	KMF_PLUGIN *plugin;
   1497 	KMF_RETURN (*getCertStatusFn)(void *, int num_args,
   1498 	    KMF_ATTRIBUTE *attrlist);
   1499 
   1500 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
   1501 		{KMF_USER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
   1502 			sizeof (KMF_DATA)},
   1503 		{KMF_ISSUER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
   1504 			sizeof (KMF_DATA)},
   1505 		{KMF_OCSP_RESPONSE_DATA_ATTR, FALSE, sizeof (KMF_DATA),
   1506 			sizeof (KMF_DATA)},
   1507 		{KMF_OCSP_RESPONSE_STATUS_ATTR, FALSE, sizeof (int),
   1508 			sizeof (uint32_t)},
   1509 		{KMF_OCSP_RESPONSE_REASON_ATTR, FALSE, sizeof (int),
   1510 			sizeof (uint32_t)},
   1511 		{KMF_OCSP_RESPONSE_CERT_STATUS_ATTR, FALSE, sizeof (int),
   1512 			sizeof (uint32_t)},
   1513 	};
   1514 
   1515 	int num_req_attrs = sizeof (required_attrs) /
   1516 	    sizeof (KMF_ATTRIBUTE_TESTER);
   1517 
   1518 	if (handle == NULL)
   1519 		return (KMF_ERR_BAD_PARAMETER);
   1520 
   1521 	CLEAR_ERROR(handle, ret);
   1522 
   1523 	ret = test_attributes(num_req_attrs, required_attrs,
   1524 	    0, NULL, num_args, attrlist);
   1525 
   1526 	if (ret != KMF_OK)
   1527 		return (ret);
   1528 
   1529 	/*
   1530 	 * This framework function is actually implemented in the openssl
   1531 	 * plugin library, so we find the function address and call it.
   1532 	 */
   1533 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
   1534 	if (plugin == NULL || plugin->dldesc == NULL) {
   1535 		return (KMF_ERR_INTERNAL);
   1536 	}
   1537 
   1538 	getCertStatusFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
   1539 	    "OpenSSL_GetOCSPStatusForCert");
   1540 	if (getCertStatusFn == NULL) {
   1541 		return (KMF_ERR_INTERNAL);
   1542 	}
   1543 
   1544 	return (getCertStatusFn(handle, num_args, attrlist));
   1545 
   1546 }
   1547 
   1548 KMF_RETURN
   1549 kmf_string_to_oid(char *oidstring, KMF_OID *oid)
   1550 {
   1551 	KMF_RETURN rv = KMF_OK;
   1552 	char *cp, *bp, *startp;
   1553 	int numbuf;
   1554 	int onumbuf;
   1555 	int nbytes, index;
   1556 	int len;
   1557 	unsigned char *op;
   1558 
   1559 	if (oidstring == NULL || oid == NULL)
   1560 		return (KMF_ERR_BAD_PARAMETER);
   1561 
   1562 	len = strlen(oidstring);
   1563 
   1564 	bp = oidstring;
   1565 	cp = bp;
   1566 	/* Skip over leading space */
   1567 	while ((bp < &cp[len]) && isspace(*bp))
   1568 		bp++;
   1569 
   1570 	startp = bp;
   1571 	nbytes = 0;
   1572 
   1573 	/*
   1574 	 * The first two numbers are chewed up by the first octet.
   1575 	 */
   1576 	if (sscanf(bp, "%d", &numbuf) != 1)
   1577 		return (KMF_ERR_BAD_PARAMETER);
   1578 	while ((bp < &cp[len]) && isdigit(*bp))
   1579 		bp++;
   1580 	while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
   1581 		bp++;
   1582 	if (sscanf(bp, "%d", &numbuf) != 1)
   1583 		return (KMF_ERR_BAD_PARAMETER);
   1584 	while ((bp < &cp[len]) && isdigit(*bp))
   1585 		bp++;
   1586 	while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
   1587 		bp++;
   1588 	nbytes++;
   1589 
   1590 	while (isdigit(*bp)) {
   1591 		if (sscanf(bp, "%d", &numbuf) != 1)
   1592 			return (KMF_ERR_BAD_PARAMETER);
   1593 		while (numbuf) {
   1594 			nbytes++;
   1595 			numbuf >>= 7;
   1596 		}
   1597 		while ((bp < &cp[len]) && isdigit(*bp))
   1598 			bp++;
   1599 		while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
   1600 			bp++;
   1601 	}
   1602 
   1603 	oid->Length = nbytes;
   1604 	oid->Data = malloc(oid->Length);
   1605 	if (oid->Data == NULL) {
   1606 		return (KMF_ERR_MEMORY);
   1607 	}
   1608 	(void) memset(oid->Data, 0, oid->Length);
   1609 
   1610 	op = oid->Data;
   1611 
   1612 	bp = startp;
   1613 	(void) sscanf(bp, "%d", &numbuf);
   1614 
   1615 	while (isdigit(*bp)) bp++;
   1616 	while (isspace(*bp) || *bp == '.') bp++;
   1617 
   1618 	onumbuf = 40 * numbuf;
   1619 	(void) sscanf(bp, "%d", &numbuf);
   1620 	onumbuf += numbuf;
   1621 	*op = (unsigned char) onumbuf;
   1622 	op++;
   1623 
   1624 	while (isdigit(*bp)) bp++;
   1625 	while (isspace(*bp) || *bp == '.') bp++;
   1626 	while (isdigit(*bp)) {
   1627 		(void) sscanf(bp, "%d", &numbuf);
   1628 		nbytes = 0;
   1629 		/* Have to fill in the bytes msb-first */
   1630 		onumbuf = numbuf;
   1631 		while (numbuf) {
   1632 			nbytes++;
   1633 			numbuf >>= 7;
   1634 		}
   1635 		numbuf = onumbuf;
   1636 		op += nbytes;
   1637 		index = -1;
   1638 		while (numbuf) {
   1639 			op[index] = (unsigned char)numbuf & 0x7f;
   1640 			if (index != -1)
   1641 				op[index] |= 0x80;
   1642 			index--;
   1643 			numbuf >>= 7;
   1644 		}
   1645 		while (isdigit(*bp)) bp++;
   1646 		while (isspace(*bp) || *bp == '.') bp++;
   1647 	}
   1648 
   1649 	return (rv);
   1650 }
   1651 
   1652 static KMF_RETURN
   1653 encode_rid(char *name, KMF_DATA *derdata)
   1654 {
   1655 	KMF_RETURN rv = KMF_OK;
   1656 
   1657 	if (name == NULL || derdata == NULL)
   1658 		return (KMF_ERR_BAD_PARAMETER);
   1659 
   1660 	rv = kmf_string_to_oid(name, (KMF_OID *)derdata);
   1661 
   1662 	return (rv);
   1663 }
   1664 
   1665 static KMF_RETURN
   1666 encode_ipaddr(char *name, KMF_DATA *derdata)
   1667 {
   1668 	KMF_RETURN rv = KMF_OK;
   1669 	size_t len;
   1670 	in_addr_t v4;
   1671 	in6_addr_t v6;
   1672 	uint8_t *ptr;
   1673 
   1674 	if (name == NULL || derdata == NULL)
   1675 		return (KMF_ERR_BAD_PARAMETER);
   1676 
   1677 	v4 = inet_addr(name);
   1678 	if (v4 == (in_addr_t)-1) {
   1679 		ptr = (uint8_t *)&v6;
   1680 		if (inet_pton(AF_INET6, name, ptr) != 1)
   1681 			return (KMF_ERR_ENCODING);
   1682 		len = sizeof (v6);
   1683 	} else {
   1684 		ptr = (uint8_t *)&v4;
   1685 		len = sizeof (v4);
   1686 	}
   1687 
   1688 	derdata->Data = malloc(len);
   1689 	if (derdata->Data == NULL)
   1690 		return (KMF_ERR_MEMORY);
   1691 	(void) memcpy(derdata->Data, ptr, len);
   1692 	derdata->Length = len;
   1693 
   1694 	return (rv);
   1695 }
   1696 
   1697 static KMF_RETURN
   1698 encode_krb5(char *name, KMF_DATA *derdata)
   1699 {
   1700 	KMF_RETURN rv = KMF_OK;
   1701 	char *at, *realm;
   1702 	char *slash, *inst = NULL;
   1703 	BerElement *asn1 = NULL;
   1704 	BerValue *extdata = NULL;
   1705 
   1706 	at = strchr(name, '@');
   1707 	if (at == NULL)
   1708 		return (KMF_ERR_ENCODING);
   1709 
   1710 	realm = at + 1;
   1711 	*at = 0;
   1712 
   1713 	/*
   1714 	 * KRB5PrincipalName ::= SEQUENCE {
   1715 	 *	realm		[0] Realm,
   1716 	 *	principalName	[1] PrincipalName
   1717 	 * }
   1718 	 *
   1719 	 * KerberosString	::= GeneralString (IA5String)
   1720 	 * Realm	::= KerberosString
   1721 	 * PrincipalName	::= SEQUENCE {
   1722 	 *	name-type	[0] Int32,
   1723 	 *	name-string	[1] SEQUENCE OF KerberosString
   1724 	 * }
   1725 	 */
   1726 
   1727 	/*
   1728 	 * Construct the "principalName" first.
   1729 	 *
   1730 	 * The name may be split with a "/" to indicate a new instance.
   1731 	 * This must be separated in the ASN.1
   1732 	 */
   1733 	slash = strchr(name, '/');
   1734 	if (slash != NULL) {
   1735 		inst = name;
   1736 		name = slash + 1;
   1737 		*slash = 0;
   1738 	}
   1739 	if ((asn1 = kmfder_alloc()) == NULL) {
   1740 		rv = KMF_ERR_MEMORY;
   1741 		goto cleanup;
   1742 	}
   1743 	if (kmfber_printf(asn1, "{Tli", 0xa0, 3, 0x01) == -1)
   1744 		goto cleanup;
   1745 
   1746 	if (inst != NULL) {
   1747 		if (kmfber_printf(asn1, "Tl{Tl", 0xA1,
   1748 		    strlen(inst) + strlen(name) + 6,
   1749 		    BER_GENERALSTRING, strlen(inst)) == -1)
   1750 			goto cleanup;
   1751 		if (kmfber_write(asn1, inst, strlen(inst), 0) != strlen(inst))
   1752 			goto cleanup;
   1753 		if (kmfber_printf(asn1, "Tl", BER_GENERALSTRING,
   1754 		    strlen(name)) == -1)
   1755 			goto cleanup;
   1756 		if (kmfber_write(asn1, name, strlen(name), 0) != strlen(name))
   1757 			goto cleanup;
   1758 	} else {
   1759 		if (kmfber_printf(asn1, "Tl{Tl", 0xA1,
   1760 		    strlen(name) + 4, BER_GENERALSTRING, strlen(name)) == -1)
   1761 			goto cleanup;
   1762 		if (kmfber_write(asn1, name, strlen(name), 0) != strlen(name))
   1763 			goto cleanup;
   1764 	}
   1765 
   1766 	if (kmfber_printf(asn1, "}}") == -1)
   1767 		goto cleanup;
   1768 	if (kmfber_flatten(asn1, &extdata) == -1) {
   1769 		rv = KMF_ERR_ENCODING;
   1770 		goto cleanup;
   1771 	}
   1772 	kmfber_free(asn1, 1);
   1773 	asn1 = NULL;
   1774 
   1775 	/* Next construct the KRB5PrincipalNameSeq */
   1776 	if ((asn1 = kmfder_alloc()) == NULL) {
   1777 		kmfber_bvfree(extdata);
   1778 		rv = KMF_ERR_MEMORY;
   1779 		goto cleanup;
   1780 	}
   1781 	if (kmfber_printf(asn1, "{TlTl", 0xA0, strlen(realm) + 2,
   1782 	    BER_GENERALSTRING, strlen(realm)) == -1)
   1783 		goto cleanup;
   1784 	if (kmfber_write(asn1, realm, strlen(realm), 0) != strlen(realm))
   1785 		goto cleanup;
   1786 	if (kmfber_printf(asn1, "Tl", 0xA1, extdata->bv_len) == -1)
   1787 		goto cleanup;
   1788 	if (kmfber_write(asn1, extdata->bv_val,
   1789 	    extdata->bv_len, 0) != extdata->bv_len)
   1790 		goto cleanup;
   1791 	if (kmfber_printf(asn1, "}") == -1)
   1792 		goto cleanup;
   1793 	kmfber_bvfree(extdata);
   1794 	extdata = NULL;
   1795 	if (kmfber_flatten(asn1, &extdata) == -1) {
   1796 		rv = KMF_ERR_ENCODING;
   1797 		goto cleanup;
   1798 	}
   1799 	kmfber_free(asn1, 1);
   1800 	asn1 = NULL;
   1801 
   1802 	/*
   1803 	 * GeneralName ::= CHOICE {
   1804 	 *	otherName	[0]	OtherName,
   1805 	 *	...
   1806 	 * }
   1807 	 *
   1808 	 * OtherName ::= SEQUENCE {
   1809 	 *	type-id	OBJECT IDENTIFIER,
   1810 	 *	value	[0] EXPLICIT ANY DEFINED BY type-id
   1811 	 * }
   1812 	 */
   1813 
   1814 	/* Now construct the SAN: OID + typed data. */
   1815 	if ((asn1 = kmfder_alloc()) == NULL) {
   1816 		kmfber_bvfree(extdata);
   1817 		rv = KMF_ERR_MEMORY;
   1818 		goto cleanup;
   1819 	}
   1820 	if (kmfber_printf(asn1, "D", &KMFOID_PKINIT_san) == -1)
   1821 		goto cleanup;
   1822 	if (kmfber_printf(asn1, "Tl", 0xA0, extdata->bv_len) == -1)
   1823 		goto cleanup;
   1824 	if (kmfber_write(asn1, extdata->bv_val,
   1825 	    extdata->bv_len, 0) != extdata->bv_len)
   1826 		goto cleanup;
   1827 	kmfber_bvfree(extdata);
   1828 	extdata = NULL;
   1829 	if (kmfber_flatten(asn1, &extdata) == -1) {
   1830 		rv = KMF_ERR_ENCODING;
   1831 		goto cleanup;
   1832 	}
   1833 	kmfber_free(asn1, 1);
   1834 	asn1 = NULL;
   1835 
   1836 	derdata->Data = (uchar_t *)extdata->bv_val;
   1837 	extdata->bv_val = NULL; /* clear it so it is not freed later */
   1838 	derdata->Length = extdata->bv_len;
   1839 
   1840 cleanup:
   1841 	if (asn1 != NULL)
   1842 		kmfber_free(asn1, 1);
   1843 
   1844 	if (extdata != NULL)
   1845 		kmfber_bvfree(extdata);
   1846 
   1847 	if (*at == 0)
   1848 		*at = '@';
   1849 
   1850 	if (inst != NULL)
   1851 		*slash = '/';
   1852 
   1853 	return (rv);
   1854 }
   1855 
   1856 static KMF_RETURN
   1857 encode_sclogon(char *name, KMF_DATA *derdata)
   1858 {
   1859 	KMF_RETURN rv = KMF_OK;
   1860 	BerElement *asn1 = NULL;
   1861 	BerValue *extdata = NULL;
   1862 
   1863 	if ((asn1 = kmfder_alloc()) == NULL)
   1864 		return (KMF_ERR_MEMORY);
   1865 
   1866 	/* The name is encoded as a KerberosString (IA5STRING) */
   1867 	if (kmfber_printf(asn1, "{Ds}",
   1868 	    &KMFOID_MS_KP_SCLogon, name) == -1)
   1869 		goto cleanup;
   1870 
   1871 	if (kmfber_flatten(asn1, &extdata) == -1) {
   1872 		rv = KMF_ERR_ENCODING;
   1873 		goto cleanup;
   1874 	}
   1875 
   1876 	derdata->Data = (uchar_t *)extdata->bv_val;
   1877 	derdata->Length = extdata->bv_len;
   1878 
   1879 	free(extdata);
   1880 cleanup:
   1881 	if (asn1 != NULL)
   1882 		kmfber_free(asn1, 1);
   1883 
   1884 	return (rv);
   1885 }
   1886 
   1887 static KMF_RETURN
   1888 verify_uri_format(char *uristring)
   1889 {
   1890 	KMF_RETURN ret = KMF_OK;
   1891 	xmlURIPtr   uriptr = NULL;
   1892 
   1893 	/* Parse the URI string; get the hostname and port */
   1894 	uriptr = xmlParseURI(uristring);
   1895 	if (uriptr == NULL) {
   1896 		ret = KMF_ERR_BAD_URI;
   1897 		goto out;
   1898 	}
   1899 
   1900 	if (uriptr->scheme == NULL || !strlen(uriptr->scheme)) {
   1901 		ret = KMF_ERR_BAD_URI;
   1902 		goto out;
   1903 	}
   1904 
   1905 	if (uriptr->server == NULL || !strlen(uriptr->server)) {
   1906 		ret = KMF_ERR_BAD_URI;
   1907 		goto out;
   1908 	}
   1909 out:
   1910 	if (uriptr != NULL)
   1911 		xmlFreeURI(uriptr);
   1912 	return (ret);
   1913 }
   1914 
   1915 static KMF_RETURN
   1916 encode_altname(char *namedata,
   1917 	KMF_GENERALNAMECHOICES nametype, KMF_DATA *encodedname)
   1918 {
   1919 	KMF_RETURN ret = KMF_OK;
   1920 	KMF_X509_NAME dnname;
   1921 	uchar_t tagval;
   1922 	BerElement *asn1 = NULL;
   1923 	BerValue *extdata;
   1924 
   1925 	if (namedata == NULL || encodedname == NULL)
   1926 		return (KMF_ERR_BAD_PARAMETER);
   1927 
   1928 	/*
   1929 	 * Encode the namedata according to rules in RFC 3280 for GeneralName.
   1930 	 * The input "namedata" is assumed to be an ASCII string representation
   1931 	 * of the AltName, we need to convert it to correct ASN.1 here before
   1932 	 * adding it to the cert.
   1933 	 */
   1934 	switch (nametype) {
   1935 		case GENNAME_RFC822NAME: /* rfc 822 */
   1936 			/* IA5String, no encoding needed */
   1937 			encodedname->Data = (uchar_t *)strdup(namedata);
   1938 			if (encodedname->Data == NULL)
   1939 				return (KMF_ERR_MEMORY);
   1940 			encodedname->Length = strlen(namedata);
   1941 			tagval = (0x80 | nametype);
   1942 			break;
   1943 		case GENNAME_DNSNAME: /* rfc 1034 */
   1944 			encodedname->Data = (uchar_t *)strdup(namedata);
   1945 			if (encodedname->Data == NULL)
   1946 				return (KMF_ERR_MEMORY);
   1947 			encodedname->Length = strlen(namedata);
   1948 			tagval = (0x80 | nametype);
   1949 			break;
   1950 		case GENNAME_URI: /* rfc 1738 */
   1951 			ret = verify_uri_format(namedata);
   1952 			if (ret != KMF_OK)
   1953 				return (ret);
   1954 			/* IA5String, no encoding needed */
   1955 			encodedname->Data = (uchar_t *)strdup(namedata);
   1956 			if (encodedname->Data == NULL)
   1957 				return (KMF_ERR_MEMORY);
   1958 			encodedname->Length = strlen(namedata);
   1959 			tagval = (0x80 | nametype);
   1960 			break;
   1961 		case GENNAME_IPADDRESS:
   1962 			ret =  encode_ipaddr(namedata, encodedname);
   1963 			tagval = (0x80 | nametype);
   1964 			break;
   1965 		case GENNAME_REGISTEREDID:
   1966 			ret = encode_rid(namedata, encodedname);
   1967 			tagval = (0x80 | nametype);
   1968 			break;
   1969 		case GENNAME_DIRECTORYNAME:
   1970 			ret = kmf_dn_parser(namedata, &dnname);
   1971 			if (ret == KMF_OK) {
   1972 				ret = DerEncodeName(&dnname, encodedname);
   1973 			}
   1974 			(void) kmf_free_dn(&dnname);
   1975 			tagval = (0x80 | nametype);
   1976 			break;
   1977 		case GENNAME_KRB5PRINC:
   1978 			tagval = (0xA0 | GENNAME_OTHERNAME);
   1979 			ret = encode_krb5(namedata, encodedname);
   1980 			break;
   1981 		case GENNAME_SCLOGON_UPN:
   1982 			tagval = (0xA0 | GENNAME_OTHERNAME);
   1983 			ret = encode_sclogon(namedata, encodedname);
   1984 			break;
   1985 		default:
   1986 			/* unsupported */
   1987 			return (KMF_ERR_BAD_PARAMETER);
   1988 
   1989 	}
   1990 	if (ret != KMF_OK) {
   1991 		kmf_free_data(encodedname);
   1992 		return (ret);
   1993 	}
   1994 
   1995 	if ((asn1 = kmfder_alloc()) == NULL)
   1996 		return (KMF_ERR_MEMORY);
   1997 
   1998 	if (kmfber_printf(asn1, "Tl", tagval, encodedname->Length) == -1)
   1999 		goto cleanup;
   2000 
   2001 	if (kmfber_write(asn1, (char *)encodedname->Data,
   2002 	    encodedname->Length, 0) == -1) {
   2003 		ret = KMF_ERR_ENCODING;
   2004 		goto cleanup;
   2005 	}
   2006 	if (kmfber_flatten(asn1, &extdata) == -1) {
   2007 		ret = KMF_ERR_ENCODING;
   2008 		goto cleanup;
   2009 	}
   2010 
   2011 	kmf_free_data(encodedname);
   2012 	encodedname->Data = (uchar_t *)extdata->bv_val;
   2013 	encodedname->Length = extdata->bv_len;
   2014 
   2015 	free(extdata);
   2016 
   2017 cleanup:
   2018 	if (asn1)
   2019 		kmfber_free(asn1, 1);
   2020 
   2021 	if (ret != KMF_OK)
   2022 		kmf_free_data(encodedname);
   2023 
   2024 	return (ret);
   2025 }
   2026 
   2027 KMF_X509_EXTENSION *
   2028 FindExtn(KMF_X509_EXTENSIONS *exts, KMF_OID *oid)
   2029 {
   2030 	KMF_X509_EXTENSION *foundextn = NULL;
   2031 	int i;
   2032 
   2033 	if (exts == NULL || oid == NULL)
   2034 		return (NULL);
   2035 
   2036 	for (i = 0; i < exts->numberOfExtensions; i++) {
   2037 		if (IsEqualOid(oid, &exts->extensions[i].extnId))  {
   2038 			foundextn = &exts->extensions[i];
   2039 			break;
   2040 		}
   2041 	}
   2042 	return (foundextn);
   2043 }
   2044 
   2045 KMF_RETURN
   2046 GetSequenceContents(char *data, size_t len,
   2047 	char **contents, size_t *outlen)
   2048 {
   2049 	KMF_RETURN ret = KMF_OK;
   2050 	BerElement *exasn1 = NULL;
   2051 	BerValue oldextn;
   2052 	int tag;
   2053 	size_t oldsize;
   2054 	char *olddata = NULL;
   2055 
   2056 	if (data == NULL || contents == NULL || outlen == NULL)
   2057 		return (KMF_ERR_BAD_PARAMETER);
   2058 
   2059 	/*
   2060 	 * Decode the sequence of general names
   2061 	 */
   2062 	oldextn.bv_val = data;
   2063 	oldextn.bv_len = len;
   2064 
   2065 	if ((exasn1 = kmfder_init(&oldextn)) == NULL) {
   2066 		ret = KMF_ERR_MEMORY;
   2067 		goto out;
   2068 	}
   2069 
   2070 	/*
   2071 	 * Unwrap the sequence to find the size of the block
   2072 	 * of GeneralName items in the set.
   2073 	 *
   2074 	 * Peek at the tag and length ("tl"),
   2075 	 * then consume them ("{").
   2076 	 */
   2077 	if (kmfber_scanf(exasn1, "tl{", &tag, &oldsize) == KMFBER_DEFAULT ||
   2078 	    oldsize == 0) {
   2079 		ret = KMF_ERR_ENCODING;
   2080 		goto out;
   2081 	}
   2082 
   2083 	olddata = malloc(oldsize);
   2084 	if (olddata == NULL) {
   2085 		ret = KMF_ERR_MEMORY;
   2086 		goto out;
   2087 	}
   2088 	(void) memset(olddata, 0, oldsize);
   2089 	/*
   2090 	 * Read the entire blob of GeneralNames, we don't
   2091 	 * need to interpret them now.
   2092 	 */
   2093 	if (kmfber_read(exasn1, olddata, oldsize) != oldsize) {
   2094 		ret = KMF_ERR_ENCODING;
   2095 		goto out;
   2096 	}
   2097 out:
   2098 	if (exasn1 != NULL)
   2099 		kmfber_free(exasn1, 1);
   2100 
   2101 	if (ret != KMF_OK) {
   2102 		*contents = NULL;
   2103 		*outlen = 0;
   2104 		if (olddata != NULL)
   2105 			free(olddata);
   2106 	} else {
   2107 		*contents = olddata;
   2108 		*outlen = oldsize;
   2109 	}
   2110 	return (ret);
   2111 }
   2112 
   2113 KMF_RETURN
   2114 add_an_extension(KMF_X509_EXTENSIONS *exts, KMF_X509_EXTENSION *newextn)
   2115 {
   2116 	KMF_RETURN ret = KMF_OK;
   2117 	KMF_X509_EXTENSION *extlist;
   2118 
   2119 	if (exts == NULL || newextn == NULL)
   2120 		return (KMF_ERR_BAD_PARAMETER);
   2121 
   2122 	extlist = malloc(sizeof (KMF_X509_EXTENSION) *
   2123 	    (exts->numberOfExtensions + 1));
   2124 	if (extlist == NULL)
   2125 		return (KMF_ERR_MEMORY);
   2126 
   2127 	(void) memcpy(extlist, exts->extensions,
   2128 	    exts->numberOfExtensions * sizeof (KMF_X509_EXTENSION));
   2129 
   2130 	(void) memcpy(&extlist[exts->numberOfExtensions], newextn,
   2131 	    sizeof (KMF_X509_EXTENSION));
   2132 
   2133 	free(exts->extensions);
   2134 	exts->numberOfExtensions++;
   2135 	exts->extensions = extlist;
   2136 
   2137 	return (ret);
   2138 }
   2139 
   2140 KMF_RETURN
   2141 kmf_set_altname(KMF_X509_EXTENSIONS *extensions,
   2142 	KMF_OID *oid,
   2143 	int critical,
   2144 	KMF_GENERALNAMECHOICES nametype,
   2145 	char *namedata)
   2146 {
   2147 	KMF_RETURN ret = KMF_OK;
   2148 	KMF_X509_EXTENSION subjAltName;
   2149 	KMF_DATA dername = { NULL, 0 };
   2150 	BerElement *asn1 = NULL;
   2151 	BerValue *extdata;
   2152 	char *olddata = NULL;
   2153 	KMF_X509_EXTENSION *foundextn = NULL;
   2154 	size_t	oldsize = 0;
   2155 
   2156 	if (extensions == NULL || oid == NULL || namedata == NULL)
   2157 		return (KMF_ERR_BAD_PARAMETER);
   2158 
   2159 	ret = encode_altname(namedata, nametype, &dername);
   2160 
   2161 	if (ret != KMF_OK)
   2162 		return (ret);
   2163 
   2164 	(void) memset(&subjAltName, 0, sizeof (subjAltName));
   2165 
   2166 	ret = copy_data(&subjAltName.extnId, oid);
   2167 	if (ret != KMF_OK)
   2168 		goto out;
   2169 	/*
   2170 	 * Check to see if this cert already has a subjectAltName.
   2171 	 */
   2172 	foundextn = FindExtn(extensions, oid);
   2173 
   2174 	if (foundextn != NULL) {
   2175 		ret = GetSequenceContents(
   2176 		    (char *)foundextn->BERvalue.Data,
   2177 		    foundextn->BERvalue.Length,
   2178 		    &olddata, &oldsize);
   2179 		if (ret != KMF_OK)
   2180 			goto out;
   2181 	}
   2182 
   2183 	/*
   2184 	 * Assume (!!) that the namedata given is already properly encoded.
   2185 	 */
   2186 	if ((asn1 = kmfder_alloc()) == NULL)
   2187 		return (KMF_ERR_MEMORY);
   2188 
   2189 	if (kmfber_printf(asn1, "{") == -1) {
   2190 		ret = KMF_ERR_ENCODING;
   2191 		goto out;
   2192 	}
   2193 
   2194 	/* Write the old extension data first */
   2195 	if (olddata != NULL && oldsize > 0) {
   2196 		if (kmfber_write(asn1, olddata, oldsize, 0) == -1) {
   2197 			ret = KMF_ERR_ENCODING;
   2198 			goto out;
   2199 		}
   2200 	}
   2201 
   2202 	/* Now add the new name to the list */
   2203 	if (kmfber_write(asn1, (char *)dername.Data, dername.Length, 0) == -1) {
   2204 		ret = KMF_ERR_ENCODING;
   2205 		goto out;
   2206 	}
   2207 
   2208 	/* Now close the sequence */
   2209 	if (kmfber_printf(asn1, "}") == -1) {
   2210 		ret = KMF_ERR_ENCODING;
   2211 		goto out;
   2212 	}
   2213 	if (kmfber_flatten(asn1, &extdata) == -1) {
   2214 		ret = KMF_ERR_ENCODING;
   2215 		goto out;
   2216 	}
   2217 
   2218 	/*
   2219 	 * If we are just adding to an existing list of altNames,
   2220 	 * just replace the BER data associated with the found extension.
   2221 	 */
   2222 	if (foundextn != NULL) {
   2223 		free(foundextn->BERvalue.Data);
   2224 		foundextn->critical = critical;
   2225 		foundextn->BERvalue.Data = (uchar_t *)extdata->bv_val;
   2226 		foundextn->BERvalue.Length = extdata->bv_len;
   2227 	} else {
   2228 		subjAltName.critical = critical;
   2229 		subjAltName.format = KMF_X509_DATAFORMAT_ENCODED;
   2230 		subjAltName.BERvalue.Data = (uchar_t *)extdata->bv_val;
   2231 		subjAltName.BERvalue.Length = extdata->bv_len;
   2232 		ret = add_an_extension(extensions, &subjAltName);
   2233 		if (ret != KMF_OK)
   2234 			free(subjAltName.BERvalue.Data);
   2235 	}
   2236 
   2237 	free(extdata);
   2238 out:
   2239 	if (olddata != NULL)
   2240 		free(olddata);
   2241 
   2242 	kmf_free_data(&dername);
   2243 	if (ret != KMF_OK)
   2244 		kmf_free_data(&subjAltName.extnId);
   2245 	if (asn1 != NULL)
   2246 		kmfber_free(asn1, 1);
   2247 	return (ret);
   2248 }
   2249 
   2250 /*
   2251  * Search a list of attributes for one that matches the given type.
   2252  * Return a pointer into the attribute list.  This does not
   2253  * return a copy of the value, it returns a reference into the
   2254  * given list.
   2255  */
   2256 int
   2257 kmf_find_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist, int numattrs)
   2258 {
   2259 	int i;
   2260 	for (i = 0; i < numattrs; i++) {
   2261 		if (attlist[i].type == type)
   2262 			return (i);
   2263 	}
   2264 	return (-1);
   2265 }
   2266 
   2267 /*
   2268  * Verify that a given attribute is consistent with the
   2269  * "test" attribute.
   2270  */
   2271 static KMF_RETURN
   2272 verify_attribute(KMF_ATTRIBUTE *givenattr,
   2273 	KMF_ATTRIBUTE_TESTER *testattr)
   2274 {
   2275 	/* A NULL pValue was found where one is required */
   2276 	if (testattr->null_value_ok == FALSE &&
   2277 	    givenattr->pValue == NULL)
   2278 		return (KMF_ERR_BAD_PARAMETER);
   2279 
   2280 	/* If the given valueLen is too small, return error */
   2281 	if (givenattr->pValue != NULL &&
   2282 	    testattr->minlen > 0 &&
   2283 	    (givenattr->valueLen < testattr->minlen))
   2284 		return (KMF_ERR_BAD_PARAMETER);
   2285 
   2286 	/* If the given valueLen is too big, return error */
   2287 	if (givenattr->pValue != NULL &&
   2288 	    testattr->maxlen > 0 &&
   2289 	    (givenattr->valueLen > testattr->maxlen))
   2290 		return (KMF_ERR_BAD_PARAMETER);
   2291 
   2292 	return (KMF_OK);
   2293 }
   2294 
   2295 /*
   2296  * Given a set of required attribute tests and optional
   2297  * attributes, make sure that the actual attributes
   2298  * being tested (attrlist below) are allowed and are
   2299  * properly specified.
   2300  */
   2301 KMF_RETURN
   2302 test_attributes(int reqnum, KMF_ATTRIBUTE_TESTER *reqattrs,
   2303 	int optnum, KMF_ATTRIBUTE_TESTER *optattrs,
   2304 	int numattrs, KMF_ATTRIBUTE *attrlist)
   2305 {
   2306 	KMF_RETURN ret = KMF_OK;
   2307 	int i, idx;
   2308 
   2309 	/*
   2310 	 * If the caller didn't supply enough attributes,
   2311 	 * return an error.
   2312 	 */
   2313 	if (numattrs < reqnum || attrlist == NULL)
   2314 		return (KMF_ERR_BAD_PARAMETER);
   2315 
   2316 	/*
   2317 	 * Make sure all required attrs are present and
   2318 	 * correct.
   2319 	 */
   2320 	for (i = 0; i < reqnum && ret == KMF_OK; i++) {
   2321 		idx = kmf_find_attr(reqattrs[i].type, attrlist, numattrs);
   2322 		/* If a required attr is not found, return error */
   2323 		if (idx == -1) {
   2324 			return (KMF_ERR_BAD_PARAMETER);
   2325 		}
   2326 
   2327 		ret = verify_attribute(&attrlist[idx], &reqattrs[i]);
   2328 	}
   2329 	/*
   2330 	 * Now test the optional parameters.
   2331 	 */
   2332 	for (i = 0; i < optnum && ret == KMF_OK; i++) {
   2333 		idx = kmf_find_attr(optattrs[i].type, attrlist, numattrs);
   2334 		/* If a optional attr is not found, continue. */
   2335 		if (idx == -1) {
   2336 			continue;
   2337 		}
   2338 
   2339 		ret = verify_attribute(&attrlist[idx], &optattrs[i]);
   2340 	}
   2341 
   2342 	return (ret);
   2343 }
   2344 
   2345 /*
   2346  * Given an already allocated attribute list, insert
   2347  * the given attribute information at a specific index
   2348  * in the list.
   2349  */
   2350 void
   2351 kmf_set_attr_at_index(KMF_ATTRIBUTE *attlist, int index,
   2352 	KMF_ATTR_TYPE type,  void *pValue, uint32_t len)
   2353 {
   2354 	if (attlist == NULL)
   2355 		return;
   2356 
   2357 	attlist[index].type = type;
   2358 	attlist[index].pValue = pValue;
   2359 	attlist[index].valueLen = len;
   2360 }
   2361 
   2362 /*
   2363  * Find an attribute matching a particular type and set
   2364  * the pValue and length fields to the given values.
   2365  */
   2366 KMF_RETURN
   2367 kmf_set_attr(KMF_ATTRIBUTE *attlist, int numattr,
   2368 	KMF_ATTR_TYPE type,  void *pValue, uint32_t len)
   2369 {
   2370 	int idx;
   2371 	if (attlist == NULL)
   2372 		return (KMF_ERR_BAD_PARAMETER);
   2373 
   2374 	idx = kmf_find_attr(type, attlist, numattr);
   2375 	if (idx == -1)
   2376 		return (KMF_ERR_ATTR_NOT_FOUND);
   2377 
   2378 	attlist[idx].type = type;
   2379 	/* Assumes the attribute pValue can hold the result */
   2380 	if (attlist[idx].pValue != NULL) {
   2381 		if (attlist[idx].valueLen >= len)
   2382 			(void) memcpy(attlist[idx].pValue, pValue, len);
   2383 		else
   2384 			return (KMF_ERR_BUFFER_SIZE);
   2385 	}
   2386 	attlist[idx].valueLen = len;
   2387 	return (KMF_OK);
   2388 }
   2389 
   2390 /*
   2391  * Find a particular attribute in a list and return
   2392  * a pointer to its value.
   2393  */
   2394 void *
   2395 kmf_get_attr_ptr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist,
   2396 	int numattrs)
   2397 {
   2398 	int i;
   2399 
   2400 	i = kmf_find_attr(type, attlist, numattrs);
   2401 	if (i == -1)
   2402 		return (NULL);
   2403 
   2404 	return (attlist[i].pValue);
   2405 }
   2406 
   2407 /*
   2408  * Find a particular attribute in a list and return
   2409  * the value and length values.  Value and length
   2410  * may be NULL if the caller doesn't want their values
   2411  * to be filled in.
   2412  */
   2413 KMF_RETURN
   2414 kmf_get_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist,
   2415 	int numattrs, void *outValue, uint32_t *outlen)
   2416 {
   2417 	int i;
   2418 	uint32_t len = 0;
   2419 	uint32_t *lenptr = outlen;
   2420 
   2421 	if (lenptr == NULL)
   2422 		lenptr = &len;
   2423 
   2424 	i = kmf_find_attr(type, attlist, numattrs);
   2425 	if (i == -1)
   2426 		return (KMF_ERR_ATTR_NOT_FOUND);
   2427 
   2428 	/* This assumes that the ptr passed in is pre-allocated space */
   2429 	if (attlist[i].pValue != NULL && outValue != NULL) {
   2430 		/*
   2431 		 * If the caller did not specify a length,
   2432 		 * assume "outValue" is big enough.
   2433 		 */
   2434 		if (outlen != NULL) {
   2435 			if (*outlen >= attlist[i].valueLen)
   2436 				(void) memcpy(outValue, attlist[i].pValue,
   2437 				    attlist[i].valueLen);
   2438 			else
   2439 				return (KMF_ERR_BUFFER_SIZE);
   2440 		} else {
   2441 			(void) memcpy(outValue, attlist[i].pValue,
   2442 			    attlist[i].valueLen);
   2443 		}
   2444 	}
   2445 
   2446 	if (outlen != NULL)
   2447 		*outlen = attlist[i].valueLen;
   2448 	return (KMF_OK);
   2449 }
   2450 
   2451 /*
   2452  * Utility routine to find a string type attribute, allocate it
   2453  * and return the value to the caller.  This simplifies the
   2454  * operation by doing both "kmf_get_attr" calls and avoids
   2455  * duplicating this block of code in lots of places.
   2456  */
   2457 KMF_RETURN
   2458 kmf_get_string_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attrlist,
   2459 	int numattrs, char **outstr)
   2460 {
   2461 	KMF_RETURN rv;
   2462 	uint32_t len;
   2463 
   2464 	if (outstr == NULL)
   2465 		return (KMF_ERR_BAD_PARAMETER);
   2466 
   2467 	if ((rv = kmf_get_attr(type, attrlist, numattrs, NULL, &len)) ==
   2468 	    KMF_OK) {
   2469 		*outstr = malloc(len + 1);
   2470 		if ((*outstr) == NULL)
   2471 			return (KMF_ERR_MEMORY);
   2472 		(void) memset((*outstr), 0, len + 1);
   2473 		rv = kmf_get_attr(type, attrlist, numattrs, (*outstr), &len);
   2474 		if (rv != KMF_OK) {
   2475 			free(*outstr);
   2476 			*outstr = NULL;
   2477 		}
   2478 	}
   2479 
   2480 	return (rv);
   2481 }
   2482 
   2483 
   2484 void
   2485 free_entry(conf_entry_t *entry)
   2486 {
   2487 	if (entry == NULL)
   2488 		return;
   2489 	free(entry->keystore);
   2490 	free(entry->modulepath);
   2491 	free(entry->option);
   2492 }
   2493 
   2494 void
   2495 free_entrylist(conf_entrylist_t *list)
   2496 {
   2497 	conf_entrylist_t *next;
   2498 
   2499 	while (list != NULL) {
   2500 		next = list->next;
   2501 		free_entry(list->entry);
   2502 		free(list);
   2503 		list = next;
   2504 	}
   2505 }
   2506 
   2507 static KMF_RETURN
   2508 parse_entry(char *buf, conf_entry_t **entry)
   2509 {
   2510 	KMF_RETURN ret = KMF_OK;
   2511 	conf_entry_t *tmp = NULL;
   2512 	char *token1;
   2513 	char *token2;
   2514 	char *token3;
   2515 	char *lasts;
   2516 	char *value;
   2517 
   2518 	if ((token1 = strtok_r(buf, SEP_COLON, &lasts)) == NULL)
   2519 		return (KMF_ERR_KMF_CONF);
   2520 
   2521 	if ((tmp = calloc(sizeof (conf_entry_t), 1)) == NULL)
   2522 		return (KMF_ERR_MEMORY);
   2523 
   2524 	if ((tmp->keystore = strdup(token1)) == NULL) {
   2525 		ret = KMF_ERR_MEMORY;
   2526 		goto end;
   2527 	}
   2528 
   2529 	if ((token2 = strtok_r(NULL, SEP_SEMICOLON, &lasts)) == NULL) {
   2530 		ret = KMF_ERR_KMF_CONF;
   2531 		goto end;
   2532 	}
   2533 
   2534 	/* need to get token3 first to satisfy nested strtok invocations */
   2535 	token3 = strtok_r(NULL, SEP_SEMICOLON, &lasts);
   2536 
   2537 	/* parse token2 */
   2538 	if (strncmp(token2, CONF_MODULEPATH, strlen(CONF_MODULEPATH)) != 0) {
   2539 		ret = KMF_ERR_KMF_CONF;
   2540 		goto end;
   2541 	}
   2542 
   2543 	if (value = strpbrk(token2, SEP_EQUAL)) {
   2544 		value++; /* get rid of = */
   2545 	} else {
   2546 		ret = KMF_ERR_KMF_CONF;
   2547 		goto end;
   2548 	}
   2549 
   2550 	if ((tmp->modulepath = strdup(value)) == NULL) {
   2551 		ret = KMF_ERR_MEMORY;
   2552 		goto end;
   2553 	}
   2554 
   2555 	/* parse token3, if it exists */
   2556 	if (token3 != NULL) {
   2557 		if (strncmp(token3, CONF_OPTION, strlen(CONF_OPTION))
   2558 		    != 0) {
   2559 			ret = KMF_ERR_KMF_CONF;
   2560 			goto end;
   2561 		}
   2562 
   2563 		if (value = strpbrk(token3, SEP_EQUAL)) {
   2564 			value++; /* get rid of = */
   2565 		} else {
   2566 			ret = KMF_ERR_KMF_CONF;
   2567 			goto end;
   2568 		}
   2569 
   2570 		if ((tmp->option = strdup(value)) == NULL) {
   2571 			ret = KMF_ERR_MEMORY;
   2572 			goto end;
   2573 		}
   2574 	}
   2575 
   2576 	*entry = tmp;
   2577 
   2578 end:
   2579 	if (ret != KMF_OK) {
   2580 		free_entry(tmp);
   2581 		free(tmp);
   2582 	}
   2583 	return (ret);
   2584 }
   2585 
   2586 
   2587 conf_entry_t *
   2588 dup_entry(conf_entry_t *entry)
   2589 {
   2590 	conf_entry_t *rtn_entry;
   2591 
   2592 	if (entry == NULL)
   2593 		return (NULL);
   2594 
   2595 	rtn_entry = malloc(sizeof (conf_entry_t));
   2596 	if (rtn_entry == NULL)
   2597 		return (NULL);
   2598 
   2599 	if ((rtn_entry->keystore = strdup(entry->keystore)) == NULL)
   2600 		goto out;
   2601 
   2602 	if ((rtn_entry->modulepath = strdup(entry->modulepath)) == NULL)
   2603 		goto out;
   2604 
   2605 	if (entry->option != NULL &&
   2606 	    (rtn_entry->option = strdup(entry->modulepath)) == NULL)
   2607 		goto out;
   2608 
   2609 	return (rtn_entry);
   2610 
   2611 out:
   2612 	free_entry(rtn_entry);
   2613 	return (NULL);
   2614 }
   2615 
   2616 
   2617 /*
   2618  * This function takes a keystore_name as input and returns
   2619  * the KMF_KEYSTORE_TYPE value assigned to it.  If the "option"
   2620  * argument is not NULL, this function also returns the option string
   2621  * if there is an option string for the plugin module.
   2622  */
   2623 KMF_RETURN
   2624 kmf_get_plugin_info(KMF_HANDLE_T handle, char *keystore_name,
   2625     KMF_KEYSTORE_TYPE *kstype, char **option)
   2626 {
   2627 	KMF_RETURN ret = KMF_OK;
   2628 	conf_entrylist_t  *phead = extra_plugin_list;
   2629 	boolean_t is_default = B_TRUE;
   2630 
   2631 	/*
   2632 	 * Although handle is not really used in the function, we will
   2633 	 * check the handle to make sure that kmf_intialize() is called
   2634 	 * before this function.
   2635 	 */
   2636 	if (handle == NULL || keystore_name == NULL || kstype == NULL)
   2637 		return (KMF_ERR_BAD_PARAMETER);
   2638 
   2639 	if (strcmp(keystore_name, "pkcs11") == 0) {
   2640 		*kstype = KMF_KEYSTORE_PK11TOKEN;
   2641 	} else if (strcmp(keystore_name, "file") == 0) {
   2642 		*kstype = KMF_KEYSTORE_OPENSSL;
   2643 	} else if (strcmp(keystore_name, "nss") == 0) {
   2644 		*kstype = KMF_KEYSTORE_NSS;
   2645 	} else {
   2646 		is_default = B_FALSE;
   2647 	}
   2648 
   2649 	if (is_default) {
   2650 		if (option != NULL)
   2651 			*option = NULL;
   2652 		goto out;
   2653 	}
   2654 
   2655 	/* Not a built-in plugin; check if it is in extra_plugin_list. */
   2656 	while (phead != NULL) {
   2657 		if (strcmp(phead->entry->keystore, keystore_name) == 0)
   2658 			break;
   2659 		phead = phead->next;
   2660 	}
   2661 
   2662 	if (phead == NULL) {
   2663 		ret = KMF_ERR_PLUGIN_NOTFOUND;
   2664 		goto out;
   2665 	}
   2666 
   2667 	/* found it */
   2668 	*kstype = phead->entry->kstype;
   2669 	if (option != NULL) {
   2670 		if (phead->entry->option == NULL)
   2671 			*option = NULL;
   2672 		else {
   2673 			*option = strdup(phead->entry->option);
   2674 			if (*option == NULL) {
   2675 				ret = KMF_ERR_MEMORY;
   2676 				goto out;
   2677 			}
   2678 		}
   2679 	}
   2680 
   2681 out:
   2682 	return (ret);
   2683 }
   2684 
   2685 /*
   2686  * Retrieve the non-default plugin list from the kmf.conf file.
   2687  */
   2688 KMF_RETURN
   2689 get_entrylist(conf_entrylist_t **entlist)
   2690 {
   2691 	KMF_RETURN rv = KMF_OK;
   2692 	FILE *pfile;
   2693 	conf_entry_t *entry;
   2694 	conf_entrylist_t *rtnlist = NULL;
   2695 	conf_entrylist_t *ptmp;
   2696 	conf_entrylist_t *pcur;
   2697 	char buffer[MAXPATHLEN];
   2698 	size_t len;
   2699 
   2700 	if ((pfile = fopen(_PATH_KMF_CONF, "rF")) == NULL) {
   2701 		cryptoerror(LOG_ERR, "failed to open %s.\n", _PATH_KMF_CONF);
   2702 		return (KMF_ERR_KMF_CONF);
   2703 	}
   2704 
   2705 	while (fgets(buffer, MAXPATHLEN, pfile) != NULL) {
   2706 		if (buffer[0] == '#' || buffer[0] == ' ' ||
   2707 		    buffer[0] == '\n'|| buffer[0] == '\t') {
   2708 			continue;   /* ignore comment lines */
   2709 		}
   2710 
   2711 		len = strlen(buffer);
   2712 		if (buffer[len-1] == '\n') { /* get rid of trailing '\n' */
   2713 			len--;
   2714 		}
   2715 		buffer[len] = '\0';
   2716 
   2717 		rv = parse_entry(buffer, &entry);
   2718 		if (rv != KMF_OK) {
   2719 			goto end;
   2720 		}
   2721 
   2722 		if ((ptmp = malloc(sizeof (conf_entrylist_t))) == NULL) {
   2723 			rv = KMF_ERR_MEMORY;
   2724 			goto end;
   2725 		}
   2726 		ptmp->entry = entry;
   2727 		ptmp->next = NULL;
   2728 
   2729 		if (rtnlist == NULL) {
   2730 			rtnlist = pcur = ptmp;
   2731 		} else {
   2732 			pcur->next = ptmp;
   2733 			pcur = ptmp;
   2734 		}
   2735 	}
   2736 
   2737 end:
   2738 	(void) fclose(pfile);
   2739 
   2740 	if (rv == KMF_OK) {
   2741 		*entlist = rtnlist;
   2742 	} else if (rtnlist != NULL) {
   2743 		free_entrylist(rtnlist);
   2744 		*entlist = NULL;
   2745 		kstore_num = DEFAULT_KEYSTORE_NUM;
   2746 	}
   2747 
   2748 	return (rv);
   2749 }
   2750 
   2751 
   2752 boolean_t
   2753 is_valid_keystore_type(KMF_KEYSTORE_TYPE kstype)
   2754 {
   2755 
   2756 	if (kstype > 0 && kstype <= kstore_num)
   2757 		return (B_TRUE);
   2758 	else
   2759 		return (B_FALSE);
   2760 }
   2761 
   2762 
   2763 /*
   2764  * This API is used by elfsign. We must keep it in old API form.
   2765  */
   2766 KMF_RETURN
   2767 KMF_ConfigureKeystore(KMF_HANDLE_T handle, KMF_CONFIG_PARAMS *params)
   2768 {
   2769 
   2770 	KMF_ATTRIBUTE attlist[32];
   2771 	int i = 0;
   2772 
   2773 	if (params == NULL)
   2774 		return (KMF_ERR_BAD_PARAMETER);
   2775 
   2776 	kmf_set_attr_at_index(attlist, i,
   2777 	    KMF_KEYSTORE_TYPE_ATTR, &params->kstype, sizeof (params->kstype));
   2778 	i++;
   2779 
   2780 	if (params->kstype == KMF_KEYSTORE_NSS) {
   2781 		if (params->nssconfig.configdir != NULL) {
   2782 			kmf_set_attr_at_index(attlist, i,
   2783 			    KMF_DIRPATH_ATTR,
   2784 			    params->nssconfig.configdir,
   2785 			    strlen(params->nssconfig.configdir));
   2786 			i++;
   2787 		}
   2788 		if (params->nssconfig.certPrefix != NULL) {
   2789 			kmf_set_attr_at_index(attlist, i,
   2790 			    KMF_CERTPREFIX_ATTR,
   2791 			    params->nssconfig.certPrefix,
   2792 			    strlen(params->nssconfig.certPrefix));
   2793 			i++;
   2794 		}
   2795 		if (params->nssconfig.keyPrefix != NULL) {
   2796 			kmf_set_attr_at_index(attlist, i,
   2797 			    KMF_KEYPREFIX_ATTR,
   2798 			    params->nssconfig.keyPrefix,
   2799 			    strlen(params->nssconfig.keyPrefix));
   2800 			i++;
   2801 		}
   2802 		if (params->nssconfig.secModName != NULL) {
   2803 			kmf_set_attr_at_index(attlist, i,
   2804 			    KMF_SECMODNAME_ATTR,
   2805 			    params->nssconfig.secModName,
   2806 			    strlen(params->nssconfig.secModName));
   2807 			i++;
   2808 		}
   2809 	} else if (params->kstype == KMF_KEYSTORE_PK11TOKEN) {
   2810 		if (params->pkcs11config.label != NULL) {
   2811 			kmf_set_attr_at_index(attlist, i,
   2812 			    KMF_TOKEN_LABEL_ATTR,
   2813 			    params->pkcs11config.label,
   2814 			    strlen(params->pkcs11config.label));
   2815 			i++;
   2816 		}
   2817 		kmf_set_attr_at_index(attlist, i,
   2818 		    KMF_READONLY_ATTR,
   2819 		    &params->pkcs11config.readonly,
   2820 		    sizeof (params->pkcs11config.readonly));
   2821 		i++;
   2822 	}
   2823 
   2824 	return (kmf_configure_keystore(handle, i, attlist));
   2825 }
   2826 
   2827 /*
   2828  * This API is used by elfsign. We must keep it in old API form.
   2829  */
   2830 KMF_RETURN
   2831 KMF_Initialize(KMF_HANDLE_T *outhandle, char *policyfile, char *policyname)
   2832 {
   2833 	return (kmf_initialize(outhandle, policyfile, policyname));
   2834 }
   2835 
   2836 /*
   2837  * This API is used by elfsign. We must keep it in old API form.
   2838  */
   2839 KMF_RETURN
   2840 KMF_Finalize(KMF_HANDLE_T handle)
   2841 {
   2842 	return (kmf_finalize(handle));
   2843 }
   2844 
   2845 /*
   2846  * This API is used by elfsign. We must keep it in old API form.
   2847  */
   2848 KMF_RETURN
   2849 KMF_GetKMFErrorString(KMF_RETURN errcode, char **errmsg)
   2850 {
   2851 	return (kmf_get_kmf_error_str(errcode, errmsg));
   2852 }
   2853 
   2854 /*
   2855  * This API is used by elfsign. We must keep it in old API form.
   2856  */
   2857 KMF_RETURN
   2858 KMF_ReadInputFile(KMF_HANDLE_T handle, char *filename,  KMF_DATA *pdata)
   2859 {
   2860 	return (kmf_read_input_file(handle, filename, pdata));
   2861 }
   2862 
   2863 
   2864 /*
   2865  * This API is used by elfsign. We must keep it in old API form.
   2866  */
   2867 void
   2868 KMF_FreeKMFCert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
   2869 {
   2870 	kmf_free_kmf_cert(handle, kmf_cert);
   2871 }
   2872 
   2873 /*
   2874  * This API is used by elfsign. We must keep it in old API form.
   2875  */
   2876 void
   2877 KMF_FreeData(KMF_DATA *datablock)
   2878 {
   2879 	kmf_free_data(datablock);
   2880 }
   2881 
   2882 /*
   2883  * This API is used by elfsign. We must keep it in old API form.
   2884  */
   2885 void
   2886 KMF_FreeKMFKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key)
   2887 {
   2888 	kmf_free_kmf_key(handle, key);
   2889 }
   2890 
   2891 /*
   2892  * This API is used by elfsign. We must keep it in old API form.
   2893  */
   2894 void
   2895 KMF_FreeSignedCSR(KMF_CSR_DATA *csr)
   2896 {
   2897 	kmf_free_signed_csr(csr);
   2898 }
   2899