xref: /illumos-gate/usr/src/lib/libkmf/libkmf/common/generalop.c (revision da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  *
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <dlfcn.h>
31 #include <link.h>
32 #include <fcntl.h>
33 #include <ctype.h>
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <errno.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
41 #include <thread.h>
42 
43 #include <ber_der.h>
44 #include <kmfapiP.h>
45 
46 #include <pem_encode.h>
47 #include <rdn_parser.h>
48 #include <libxml2/libxml/uri.h>
49 #include <libgen.h>
50 #include <cryptoutil.h>
51 
52 static uchar_t pkcs11_initialized = 0;
53 mutex_t init_lock = DEFAULTMUTEX;
54 extern int errno;
55 
56 typedef struct {
57 	KMF_RETURN code;
58 	char	*message;
59 } kmf_error_map;
60 
61 static kmf_error_map kmf_errcodes[] = {
62 	{KMF_OK,	"KMF_OK"},
63 	{KMF_ERR_BAD_PARAMETER,	"KMF_ERR_BAD_PARAMETER"},
64 	{KMF_ERR_BAD_KEY_FORMAT,	"KMF_ERR_BAD_KEY_FORMAT"},
65 	{KMF_ERR_BAD_ALGORITHM,	"KMF_ERR_BAD_ALGORITHM"},
66 	{KMF_ERR_MEMORY,	"KMF_ERR_MEMORY"},
67 	{KMF_ERR_ENCODING,	"KMF_ERR_ENCODING"},
68 	{KMF_ERR_PLUGIN_INIT,	"KMF_ERR_PLUGIN_INIT"},
69 	{KMF_ERR_PLUGIN_NOTFOUND,	"KMF_ERR_PLUGIN_NOTFOUND"},
70 	{KMF_ERR_INTERNAL,	"KMF_ERR_INTERNAL"},
71 	{KMF_ERR_BAD_CERT_FORMAT,	"KMF_ERR_BAD_CERT_FORMAT"},
72 	{KMF_ERR_KEYGEN_FAILED,	"KMF_ERR_KEYGEN_FAILED"},
73 	{KMF_ERR_UNINITIALIZED,	"KMF_ERR_UNINITIALIZED"},
74 	{KMF_ERR_ISSUER,	"KMF_ERR_ISSUER"},
75 	{KMF_ERR_NOT_REVOKED,	"KMF_ERR_NOT_REVOKED"},
76 	{KMF_ERR_CERT_NOT_FOUND,	"KMF_ERR_CERT_NOT_FOUND"},
77 	{KMF_ERR_CRL_NOT_FOUND,	"KMF_ERR_CRL_NOT_FOUND"},
78 	{KMF_ERR_RDN_PARSER,	"KMF_ERR_RDN_PARSER"},
79 	{KMF_ERR_RDN_ATTR,	"KMF_ERR_RDN_ATTR"},
80 	{KMF_ERR_SLOTNAME,	"KMF_ERR_SLOTNAME"},
81 	{KMF_ERR_EMPTY_CRL,	"KMF_ERR_EMPTY_CRL"},
82 	{KMF_ERR_BUFFER_SIZE,	"KMF_ERR_BUFFER_SIZE"},
83 	{KMF_ERR_AUTH_FAILED,	"KMF_ERR_AUTH_FAILED"},
84 	{KMF_ERR_TOKEN_SELECTED,	"KMF_ERR_TOKEN_SELECTED"},
85 	{KMF_ERR_NO_TOKEN_SELECTED,	"KMF_ERR_NO_TOKEN_SELECTED"},
86 	{KMF_ERR_TOKEN_NOT_PRESENT,	"KMF_ERR_TOKEN_NOT_PRESENT"},
87 	{KMF_ERR_EXTENSION_NOT_FOUND,	"KMF_ERR_EXTENSION_NOT_FOUND"},
88 	{KMF_ERR_POLICY_ENGINE,	"KMF_ERR_POLICY_ENGINE"},
89 	{KMF_ERR_POLICY_DB_FORMAT,	"KMF_ERR_POLICY_DB_FORMAT"},
90 	{KMF_ERR_POLICY_NOT_FOUND,	"KMF_ERR_POLICY_NOT_FOUND"},
91 	{KMF_ERR_POLICY_DB_FILE,	"KMF_ERR_POLICY_DB_FILE"},
92 	{KMF_ERR_POLICY_NAME,	"KMF_ERR_POLICY_NAME"},
93 	{KMF_ERR_OCSP_POLICY,	"KMF_ERR_OCSP_POLICY"},
94 	{KMF_ERR_TA_POLICY,	"KMF_ERR_TA_POLICY"},
95 	{KMF_ERR_KEY_NOT_FOUND,	"KMF_ERR_KEY_NOT_FOUND"},
96 	{KMF_ERR_OPEN_FILE,	"KMF_ERR_OPEN_FILE"},
97 	{KMF_ERR_OCSP_BAD_ISSUER,	"KMF_ERR_OCSP_BAD_ISSUER"},
98 	{KMF_ERR_OCSP_BAD_CERT,	"KMF_ERR_OCSP_BAD_CERT"},
99 	{KMF_ERR_OCSP_CREATE_REQUEST,	"KMF_ERR_OCSP_CREATE_REQUEST"},
100 	{KMF_ERR_CONNECT_SERVER,	"KMF_ERR_CONNECT_SERVER"},
101 	{KMF_ERR_SEND_REQUEST,	"KMF_ERR_SEND_REQUEST"},
102 	{KMF_ERR_OCSP_CERTID,	"KMF_ERR_OCSP_CERTID"},
103 	{KMF_ERR_OCSP_MALFORMED_RESPONSE, "KMF_ERR_OCSP_MALFORMED_RESPONSE"},
104 	{KMF_ERR_OCSP_RESPONSE_STATUS,	"KMF_ERR_OCSP_RESPONSE_STATUS"},
105 	{KMF_ERR_OCSP_NO_BASIC_RESPONSE, "KMF_ERR_OCSP_NO_BASIC_RESPONSE"},
106 	{KMF_ERR_OCSP_BAD_SIGNER,	"KMF_ERR_OCSP_BAD_SIGNER"},
107 	{KMF_ERR_OCSP_RESPONSE_SIGNATURE, "KMF_ERR_OCSP_RESPONSE_SIGNATURE"},
108 	{KMF_ERR_OCSP_UNKNOWN_CERT,	"KMF_ERR_OCSP_UNKNOWN_CERT"},
109 	{KMF_ERR_OCSP_STATUS_TIME_INVALID, "KMF_ERR_OCSP_STATUS_TIME_INVALID"},
110 	{KMF_ERR_BAD_HTTP_RESPONSE,	"KMF_ERR_BAD_HTTP_RESPONSE"},
111 	{KMF_ERR_RECV_RESPONSE,	"KMF_ERR_RECV_RESPONSE"},
112 	{KMF_ERR_RECV_TIMEOUT,	"KMF_ERR_RECV_TIMEOUT"},
113 	{KMF_ERR_DUPLICATE_KEYFILE,	"KMF_ERR_DUPLICATE_KEYFILE"},
114 	{KMF_ERR_AMBIGUOUS_PATHNAME,	"KMF_ERR_AMBIGUOUS_PATHNAME"},
115 	{KMF_ERR_FUNCTION_NOT_FOUND,	"KMF_ERR_FUNCTION_NOT_FOUND"},
116 	{KMF_ERR_PKCS12_FORMAT,	"KMF_ERR_PKCS12_FORMAT"},
117 	{KMF_ERR_BAD_KEY_TYPE,	"KMF_ERR_BAD_KEY_TYPE"},
118 	{KMF_ERR_BAD_KEY_CLASS,	"KMF_ERR_BAD_KEY_CLASS"},
119 	{KMF_ERR_BAD_KEY_SIZE,	"KMF_ERR_BAD_KEY_SIZE"},
120 	{KMF_ERR_BAD_HEX_STRING,	"KMF_ERR_BAD_HEX_STRING"},
121 	{KMF_ERR_KEYUSAGE,	"KMF_ERR_KEYUSAGE"},
122 	{KMF_ERR_VALIDITY_PERIOD,	"KMF_ERR_VALIDITY_PERIOD"},
123 	{KMF_ERR_OCSP_REVOKED,	"KMF_ERR_OCSP_REVOKED"},
124 	{KMF_ERR_CERT_MULTIPLE_FOUND,	"KMF_ERR_CERT_MULTIPLE_FOUND"},
125 	{KMF_ERR_WRITE_FILE,	"KMF_ERR_WRITE_FILE"},
126 	{KMF_ERR_BAD_URI,	"KMF_ERR_BAD_URI"},
127 	{KMF_ERR_BAD_CRLFILE,	"KMF_ERR_BAD_CRLFILE"},
128 	{KMF_ERR_BAD_CERTFILE,	"KMF_ERR_BAD_CERTFILE"},
129 	{KMF_ERR_GETKEYVALUE_FAILED,	"KMF_ERR_GETKEYVALUE_FAILED"},
130 	{KMF_ERR_BAD_KEYHANDLE,	"KMF_ERR_BAD_KEYHANDLE"},
131 	{KMF_ERR_BAD_OBJECT_TYPE,	"KMF_ERR_BAD_OBJECT_TYPE"},
132 	{KMF_ERR_OCSP_RESPONSE_LIFETIME, "KMF_ERR_OCSP_RESPONSE_LIFETIME"},
133 	{KMF_ERR_UNKNOWN_CSR_ATTRIBUTE,	"KMF_ERR_UNKNOWN_CSR_ATTRIBUTE"},
134 	{KMF_ERR_UNINITIALIZED_TOKEN,	"KMF_ERR_UNINITIALIZED_TOKEN"},
135 	{KMF_ERR_INCOMPLETE_TBS_CERT,	"KMF_ERR_INCOMPLETE_TBS_CERT"},
136 	{KMF_ERR_MISSING_ERRCODE,	"KMF_ERR_MISSING_ERRCODE"},
137 	{KMF_KEYSTORE_ALREADY_INITIALIZED, "KMF_KEYSTORE_ALREADY_INITIALIZED"},
138 	{KMF_ERR_SENSITIVE_KEY,		"KMF_ERR_SENSITIVE_KEY"},
139 	{KMF_ERR_UNEXTRACTABLE_KEY,	"KMF_ERR_UNEXTRACTABLE_KEY"},
140 	{KMF_ERR_KEY_MISMATCH,		"KMF_ERR_KEY_MISMATCH"}
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 KMF_RETURN
163 init_pk11()
164 {
165 	(void) mutex_lock(&init_lock);
166 	if (!pkcs11_initialized) {
167 		CK_RV rv = C_Initialize(NULL);
168 		if ((rv != CKR_OK) &&
169 		    (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
170 			(void) mutex_unlock(&init_lock);
171 			return (KMF_ERR_UNINITIALIZED);
172 		} else {
173 			pkcs11_initialized = 1;
174 		}
175 	}
176 	(void) mutex_unlock(&init_lock);
177 	return (KMF_OK);
178 }
179 
180 /*
181  * Private method for searching the plugin list for the correct
182  * Plugin to use.
183  */
184 KMF_PLUGIN *
185 FindPlugin(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE kstype)
186 {
187 	KMF_PLUGIN_LIST *node;
188 	KMF_RETURN ret = KMF_OK;
189 
190 	if (handle == NULL)
191 		return (NULL);
192 
193 	node = handle->plugins;
194 
195 	/* See if the desired plugin was already initialized. */
196 	while (node != NULL && node->plugin->type != kstype)
197 		node = node->next;
198 
199 	/* If the plugin was not found, try to initialize it here. */
200 	if (node == NULL) {
201 		int i;
202 		KMF_PLUGIN *pluginrec = NULL;
203 		int numitems = sizeof (plugin_list)/sizeof (KMF_PLUGIN_ITEM);
204 		for (i = 0; i < numitems; i++) {
205 			if (plugin_list[i].kstype == kstype) {
206 				ret = InitializePlugin(plugin_list[i].kstype,
207 				    plugin_list[i].path, &pluginrec);
208 				break;
209 			}
210 		}
211 
212 		/* No matching plugins found in the available list */
213 		if (ret != KMF_OK || pluginrec == NULL)
214 			return (NULL);
215 
216 		ret = AddPlugin(handle, pluginrec);
217 		if (ret != KMF_OK) {
218 			DestroyPlugin(pluginrec);
219 			pluginrec = NULL;
220 		}
221 		return (pluginrec);
222 	} else {
223 		return (node->plugin);
224 	}
225 }
226 
227 static KMF_RETURN
228 InitializePlugin(KMF_KEYSTORE_TYPE kstype, char *path, KMF_PLUGIN **plugin)
229 {
230 	KMF_PLUGIN *p = NULL;
231 	KMF_PLUGIN_FUNCLIST *(*sym)();
232 
233 	if (path == NULL || plugin == NULL)
234 		return (KMF_ERR_BAD_PARAMETER);
235 
236 	*plugin = NULL;
237 
238 	p = (KMF_PLUGIN *)malloc(sizeof (KMF_PLUGIN));
239 	if (p == NULL)
240 		return (KMF_ERR_MEMORY);
241 
242 	p->type = kstype;
243 	p->path = strdup(path);
244 	if (p->path == NULL) {
245 		free(p);
246 		return (KMF_ERR_MEMORY);
247 	}
248 	p->dldesc = dlopen(path, RTLD_LAZY | RTLD_GROUP | RTLD_PARENT);
249 	if (p->dldesc == NULL) {
250 		free(p->path);
251 		free(p);
252 		return (KMF_ERR_PLUGIN_INIT);
253 	}
254 
255 	sym = (KMF_PLUGIN_FUNCLIST *(*)())dlsym(p->dldesc,
256 	    KMF_PLUGIN_INIT_SYMBOL);
257 	if (sym == NULL) {
258 		(void) dlclose(p->dldesc);
259 		free(p->path);
260 		free(p);
261 		return (KMF_ERR_PLUGIN_INIT);
262 	}
263 
264 	/* Get the function list */
265 	if ((p->funclist = (*sym)()) == NULL) {
266 		(void) dlclose(p->dldesc);
267 		free(p->path);
268 		free(p);
269 		return (KMF_ERR_PLUGIN_INIT);
270 	}
271 
272 	*plugin = p;
273 
274 	return (KMF_OK);
275 }
276 
277 static KMF_RETURN
278 AddPlugin(KMF_HANDLE_T handle, KMF_PLUGIN *plugin)
279 {
280 	KMF_PLUGIN_LIST *n;
281 
282 	if (handle == NULL || plugin == NULL)
283 		return (KMF_ERR_BAD_PARAMETER);
284 
285 	/* If the head is NULL, create it */
286 	if (handle->plugins == NULL) {
287 		handle->plugins = (KMF_PLUGIN_LIST *)malloc(
288 		    sizeof (KMF_PLUGIN_LIST));
289 		if (handle->plugins == NULL)
290 			return (KMF_ERR_MEMORY);
291 		handle->plugins->plugin = plugin;
292 		handle->plugins->next = NULL;
293 	} else {
294 		/* walk the list to find the tail */
295 		n = handle->plugins;
296 		while (n->next != NULL)
297 			n = n->next;
298 		n->next = (KMF_PLUGIN_LIST *)malloc(sizeof (KMF_PLUGIN_LIST));
299 		if (n->next == NULL)
300 			return (KMF_ERR_MEMORY);
301 
302 		n->next->plugin = plugin;
303 		n->next->next = NULL;
304 	}
305 	return (0);
306 }
307 
308 static void
309 DestroyPlugin(KMF_PLUGIN *plugin)
310 {
311 	if (plugin) {
312 		if (plugin->path)
313 			free(plugin->path);
314 		free(plugin);
315 	}
316 }
317 
318 static void
319 Cleanup_KMF_Handle(KMF_HANDLE_T handle)
320 {
321 	if (handle != NULL) {
322 		while (handle->plugins != NULL) {
323 			KMF_PLUGIN_LIST *next = handle->plugins->next;
324 
325 			DestroyPlugin(handle->plugins->plugin);
326 			free(handle->plugins);
327 			handle->plugins = next;
328 		}
329 		kmf_free_policy_record(handle->policy);
330 		free(handle->policy);
331 	}
332 	free(handle);
333 }
334 
335 void
336 Cleanup_PK11_Session(KMF_HANDLE_T handle)
337 {
338 	if (handle != NULL) {
339 		/* Close active session on a pkcs11 token */
340 		if (handle->pk11handle != NULL) {
341 			(void) C_CloseSession(handle->pk11handle);
342 			handle->pk11handle = NULL;
343 		}
344 	}
345 }
346 
347 KMF_RETURN
348 kmf_initialize(KMF_HANDLE_T *outhandle, char *policyfile, char *policyname)
349 {
350 	KMF_RETURN ret = KMF_OK;
351 	KMF_HANDLE *handle = NULL;
352 
353 	if (outhandle == NULL)
354 		return (KMF_ERR_BAD_PARAMETER);
355 
356 	*outhandle = NULL;
357 	handle = (KMF_HANDLE *)malloc(sizeof (KMF_HANDLE));
358 	if (handle == NULL)
359 		return (KMF_ERR_MEMORY);
360 
361 	(void) memset(handle, 0, sizeof (KMF_HANDLE));
362 	handle->plugins = NULL;
363 
364 	/* Initialize the handle with the policy */
365 	ret = kmf_set_policy((void *)handle,
366 	    policyfile == NULL ? KMF_DEFAULT_POLICY_FILE : policyfile,
367 	    policyname == NULL ? KMF_DEFAULT_POLICY_NAME : policyname);
368 	if (ret != KMF_OK)
369 		goto errout;
370 
371 	CLEAR_ERROR(handle, ret);
372 errout:
373 	if (ret != KMF_OK) {
374 		Cleanup_KMF_Handle(handle);
375 		handle = NULL;
376 	}
377 
378 	*outhandle = (KMF_HANDLE_T)handle;
379 	return (ret);
380 }
381 
382 KMF_RETURN
383 kmf_configure_keystore(KMF_HANDLE_T handle,
384 	int	num_args,
385 	KMF_ATTRIBUTE	*attrlist)
386 {
387 	KMF_RETURN ret = KMF_OK;
388 	KMF_PLUGIN *plugin;
389 	KMF_KEYSTORE_TYPE kstype;
390 	uint32_t len;
391 
392 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
393 		{KMF_KEYSTORE_TYPE_ATTR, FALSE, 1, sizeof (KMF_KEYSTORE_TYPE)},
394 	};
395 
396 	int num_req_attrs = sizeof (required_attrs) /
397 	    sizeof (KMF_ATTRIBUTE_TESTER);
398 
399 	if (handle == NULL)
400 		return (KMF_ERR_BAD_PARAMETER);
401 
402 	CLEAR_ERROR(handle, ret);
403 
404 	ret = test_attributes(num_req_attrs, required_attrs,
405 	    0, NULL, num_args, attrlist);
406 
407 	if (ret != KMF_OK)
408 		return (ret);
409 
410 	len = sizeof (kstype);
411 	ret = kmf_get_attr(KMF_KEYSTORE_TYPE_ATTR, attrlist, num_args,
412 	    &kstype, &len);
413 	if (ret != KMF_OK)
414 		return (ret);
415 
416 	plugin = FindPlugin(handle, kstype);
417 	if (plugin != NULL && plugin->funclist->ConfigureKeystore != NULL) {
418 		return (plugin->funclist->ConfigureKeystore(handle, num_args,
419 		    attrlist));
420 	} else {
421 		/* return KMF_OK, if the plugin does not have an entry */
422 		return (KMF_OK);
423 	}
424 }
425 
426 KMF_RETURN
427 kmf_finalize(KMF_HANDLE_T handle)
428 {
429 	KMF_RETURN ret = KMF_OK;
430 
431 	CLEAR_ERROR(handle, ret);
432 	if (ret != KMF_OK)
433 		return (ret);
434 
435 	if (pkcs11_initialized) {
436 		Cleanup_PK11_Session(handle);
437 	}
438 	Cleanup_KMF_Handle(handle);
439 
440 	return (ret);
441 }
442 
443 KMF_RETURN
444 kmf_get_kmf_error_str(KMF_RETURN errcode, char **errmsg)
445 {
446 	KMF_RETURN ret = KMF_OK;
447 	int i, maxerr;
448 
449 	if (errmsg == NULL)
450 		return (KMF_ERR_BAD_PARAMETER);
451 
452 	*errmsg = NULL;
453 	maxerr = sizeof (kmf_errcodes) / sizeof (kmf_error_map);
454 
455 	for (i = 0; i < maxerr && errcode != kmf_errcodes[i].code; i++)
456 		/* empty body */
457 		;
458 
459 	if (i == maxerr)
460 		return (KMF_ERR_MISSING_ERRCODE);
461 	else {
462 		*errmsg = strdup(kmf_errcodes[i].message);
463 		if ((*errmsg) == NULL)
464 			return (KMF_ERR_MEMORY);
465 	}
466 	return (ret);
467 }
468 
469 KMF_RETURN
470 kmf_get_plugin_error_str(KMF_HANDLE_T handle, char **msgstr)
471 {
472 	KMF_RETURN ret = KMF_OK;
473 	KMF_PLUGIN *plugin;
474 
475 	if (handle == NULL || msgstr == NULL)
476 		return (KMF_ERR_BAD_PARAMETER);
477 
478 	*msgstr = NULL;
479 
480 	if (handle->lasterr.errcode == 0) {
481 		return (KMF_ERR_MISSING_ERRCODE);
482 	}
483 
484 	if (handle->lasterr.kstype == -1) { /* System error */
485 		char *str = strerror(handle->lasterr.errcode);
486 		if (str != NULL) {
487 			*msgstr = strdup(str);
488 			if ((*msgstr) == NULL)
489 				return (KMF_ERR_MEMORY);
490 		}
491 		return (KMF_OK);
492 	}
493 
494 	plugin = FindPlugin(handle, handle->lasterr.kstype);
495 	if (plugin == NULL)
496 		return (KMF_ERR_PLUGIN_NOTFOUND);
497 
498 	if (plugin->funclist->GetErrorString != NULL) {
499 		ret = plugin->funclist->GetErrorString(handle, msgstr);
500 	} else {
501 		return (KMF_ERR_FUNCTION_NOT_FOUND);
502 	}
503 
504 	return (ret);
505 }
506 
507 
508 #define	SET_SYS_ERROR(h, c) if (h) {\
509 	h->lasterr.kstype = -1;\
510 	h->lasterr.errcode = c;\
511 }
512 
513 KMF_RETURN
514 kmf_read_input_file(KMF_HANDLE_T handle, char *filename,  KMF_DATA *pdata)
515 {
516 	struct stat s;
517 	long nread, total = 0;
518 	int fd;
519 	unsigned char *buf = NULL;
520 	KMF_RETURN ret;
521 
522 	if (handle) {
523 		CLEAR_ERROR(handle, ret);
524 		if (ret != KMF_OK)
525 			return (ret);
526 	}
527 
528 	if (filename == NULL || pdata == NULL) {
529 		return (KMF_ERR_BAD_PARAMETER);
530 	}
531 
532 	if ((fd = open(filename, O_RDONLY)) < 0) {
533 		SET_SYS_ERROR(handle, errno);
534 		return (KMF_ERR_OPEN_FILE);
535 	}
536 
537 	if (fstat(fd, &s) < 0) {
538 		SET_SYS_ERROR(handle, errno);
539 		(void) close(fd);
540 		return (KMF_ERR_OPEN_FILE);
541 	}
542 
543 	if ((buf = (unsigned char *) malloc(s.st_size)) == NULL) {
544 		(void) close(fd);
545 		return (KMF_ERR_MEMORY);
546 	}
547 
548 	do {
549 		nread = read(fd, buf+total, s.st_size-total);
550 		if (nread < 0) {
551 			SET_SYS_ERROR(handle, errno);
552 			(void) close(fd);
553 			free(buf);
554 			return (KMF_ERR_INTERNAL);
555 		}
556 		total += nread;
557 	} while (total < s.st_size);
558 
559 	pdata->Data = buf;
560 	pdata->Length = s.st_size;
561 	(void) close(fd);
562 	return (KMF_OK);
563 }
564 
565 /*
566  *
567  * Name: kmf_der_to_pem
568  *
569  * Description:
570  *   Function for converting DER encoded format to PEM encoded format
571  *
572  * Parameters:
573  *   type(input) - CERTIFICATE or CSR
574  *   data(input) - pointer to the DER encoded data
575  *   len(input)  - length of input data
576  *   out(output) - contains the output buffer address to be returned
577  *   outlen(output) - pointer to the returned output length
578  *
579  * Returns:
580  *   A KMF_RETURN value indicating success or specifying a particular
581  * error condition.
582  *   The value KMF_OK indicates success. All other values represent
583  * an error condition.
584  *
585  */
586 KMF_RETURN
587 kmf_der_to_pem(KMF_OBJECT_TYPE type, unsigned char *data,
588 	int len, unsigned char **out, int *outlen)
589 {
590 
591 	KMF_RETURN err;
592 	if (data == NULL || out == NULL || outlen == NULL)
593 		return (KMF_ERR_BAD_PARAMETER);
594 
595 	err = Der2Pem(type, data, len, out, outlen);
596 	return (err);
597 
598 }
599 
600 /*
601  *
602  * Name: kmf_pem_to_der
603  *
604  * Description:
605  *   Function for converting PEM encoded format to DER encoded format
606  *
607  * Parameters:
608  *   in(input) - pointer to the PEM encoded data
609  *   inlen(input)  - length of input data
610  *   out(output) - contains the output buffer address to be returned
611  *   outlen(output) - pointer to the returned output length
612  *
613  * Returns:
614  *   A KMF_RETURN value indicating success or specifying a particular
615  *   error condition.
616  *   The value KMF_OK indicates success. All other values represent
617  *   an error condition.
618  *
619  */
620 KMF_RETURN
621 kmf_pem_to_der(unsigned char *in, int inlen,
622 	unsigned char **out, int *outlen)
623 {
624 	KMF_RETURN err;
625 	if (in == NULL || out == NULL || outlen == NULL)
626 		return (KMF_ERR_BAD_PARAMETER);
627 
628 	err = Pem2Der(in, inlen, out, outlen);
629 	return (err);
630 }
631 
632 char *
633 kmf_oid_to_string(KMF_OID *oid)
634 {
635 	char numstr[128];
636 	uint32_t number;
637 	int numshift;
638 	uint32_t i, string_length;
639 	uchar_t *cp;
640 	char *bp;
641 
642 	/* First determine the size of the string */
643 	string_length = 0;
644 	number = 0;
645 	numshift = 0;
646 	cp = (unsigned char *)oid->Data;
647 
648 	number = (uint32_t)cp[0];
649 	(void) sprintf(numstr, "%d ", number/40);
650 
651 	string_length += strlen(numstr);
652 	(void) sprintf(numstr, "%d ", number%40);
653 
654 	string_length += strlen(numstr);
655 
656 	for (i = 1; i < oid->Length; i++) {
657 		if ((uint32_t)(numshift+7) < (sizeof (uint32_t)*8)) {
658 			number = (number << 7) | (cp[i] & 0x7f);
659 			numshift += 7;
660 		} else {
661 			return (NULL);
662 		}
663 
664 		if ((cp[i] & 0x80) == 0) {
665 			(void) sprintf(numstr, "%d ", number);
666 			string_length += strlen(numstr);
667 			number = 0;
668 			numshift = 0;
669 		}
670 	}
671 	/*
672 	 * If we get here, we've calculated the length of "n n n ... n ".  Add 4
673 	 * here for "{ " and "}\0".
674 	 */
675 	string_length += 4;
676 	if ((bp = (char *)malloc(string_length))) {
677 		number = (uint32_t)cp[0];
678 
679 		(void) sprintf(numstr, "%d.", number/40);
680 		(void) strcpy(bp, numstr);
681 
682 		(void) sprintf(numstr, "%d.", number%40);
683 		(void) strcat(bp, numstr);
684 
685 		number = 0;
686 		cp = (unsigned char *) oid->Data;
687 		for (i = 1; i < oid->Length; i++) {
688 			number = (number << 7) | (cp[i] & 0x7f);
689 			if ((cp[i] & 0x80) == 0) {
690 				(void) sprintf(numstr, "%d", number);
691 				(void) strcat(bp, numstr);
692 				number = 0;
693 				if (i+1 < oid->Length)
694 					(void) strcat(bp, ".");
695 			}
696 		}
697 	}
698 	return (bp);
699 }
700 
701 static boolean_t
702 check_for_pem(uchar_t *buf, KMF_ENCODE_FORMAT *fmt)
703 {
704 	char *p;
705 
706 	if (buf == NULL)
707 		return (FALSE);
708 
709 	if (memcmp(buf, "Bag Attr", 8) == 0) {
710 		*fmt = KMF_FORMAT_PEM_KEYPAIR;
711 		return (TRUE);
712 	}
713 
714 	/* Look for "-----BEGIN" right after a newline */
715 	p = strtok((char *)buf, "\n");
716 	while (p != NULL) {
717 		if (strstr(p, "-----BEGIN") != NULL) {
718 			*fmt = KMF_FORMAT_PEM;
719 			return (TRUE);
720 		}
721 		p = strtok(NULL, "\n");
722 	}
723 	return (FALSE);
724 }
725 
726 
727 static unsigned char pkcs12_version[3] = {0x02, 0x01, 0x03};
728 static unsigned char pkcs12_oid[11] =
729 {0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01};
730 
731 /*
732  * This function takes a BER encoded string as input and checks the version
733  * and the oid in the the top-level ASN.1 structure to see if it complies to
734  * the PKCS#12 Syntax.
735  */
736 static boolean_t
737 check_for_pkcs12(uchar_t *buf, int buf_len)
738 {
739 	int index = 0;
740 	int length_octets;
741 
742 	if (buf == NULL || buf_len <= 0)
743 		return (FALSE);
744 
745 	/*
746 	 * The top level structure for a PKCS12 string:
747 	 *
748 	 * PFX ::= SEQUENCE {
749 	 *	version		INTEGER {v3(3)}(v3,...)
750 	 *	authSafe	ContentInfo
751 	 *	macData		MacData OPTIONAL
752 	 * }
753 	 *
754 	 * ContentInfo
755 	 *	FROM PKCS-7 {iso(1) member-body(2) us(840) rsadsi(113549)
756 	 *		pkcs(1) pkcs-7(7) modules(0) pkcs-7(1)}
757 	 *
758 	 * Therefore, the BER/DER dump of a PKCS#12 file for the first 2
759 	 * sequences up to the oid part is as following:
760 	 *
761 	 *	SEQUENCE {
762 	 *	    INTEGER 3
763 	 *	    SEQUENCE {
764 	 *		OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
765 	 */
766 
767 	/*
768 	 * Check the first sequence and calculate the number of bytes used
769 	 * to store the length.
770 	 */
771 	if (buf[index++] != 0x30)
772 		return (FALSE);
773 
774 	if (buf[index] & 0x80) {
775 		length_octets = buf[index++] & 0x0F;  /* long form */
776 	} else {
777 		length_octets = 1; /* short form */
778 	}
779 
780 	index += length_octets;
781 	if (index  >= buf_len)
782 		return (FALSE);
783 
784 	/* Skip the length octets and check the pkcs12 version */
785 	if (memcmp(buf + index, pkcs12_version, sizeof (pkcs12_version)) != 0)
786 		return (FALSE);
787 
788 	index += sizeof (pkcs12_version);
789 	if (index  >= buf_len)
790 		return (FALSE);
791 
792 	/*
793 	 * Check the 2nd sequence and calculate the number of bytes used
794 	 * to store the length.
795 	 */
796 	if ((buf[index++] & 0xFF) != 0x30)
797 		return (FALSE);
798 
799 	if (buf[index] & 0x80) {
800 		length_octets = buf[index++] & 0x0F;
801 	} else {
802 		length_octets = 1;
803 	}
804 
805 	index += length_octets;
806 	if (index + sizeof (pkcs12_oid) >= buf_len)
807 		return (FALSE);
808 
809 	/* Skip the length octets and check the oid */
810 	if (memcmp(buf + index, pkcs12_oid, sizeof (pkcs12_oid)) != 0)
811 		return (FALSE);
812 	else
813 		return (TRUE);
814 }
815 
816 KMF_RETURN
817 kmf_get_file_format(char *filename, KMF_ENCODE_FORMAT *fmt)
818 {
819 	KMF_RETURN ret = KMF_OK;
820 	KMF_DATA filebuf = {NULL, 0};
821 	uchar_t *buf;
822 
823 	if (filename == NULL || !strlen(filename) || fmt == NULL)
824 		return (KMF_ERR_BAD_PARAMETER);
825 
826 	*fmt = 0;
827 	ret = kmf_read_input_file(NULL, filename, &filebuf);
828 	if (ret != KMF_OK)
829 		return (ret);
830 
831 	if (filebuf.Length < 8) {
832 		ret = KMF_ERR_ENCODING; /* too small */
833 		goto end;
834 	}
835 
836 	buf = filebuf.Data;
837 	if (check_for_pkcs12(buf, filebuf.Length) == TRUE) {
838 		*fmt = KMF_FORMAT_PKCS12;
839 	} else if (buf[0] == 0x30 && (buf[1] & 0x80)) {
840 		/* It is most likely a generic ASN.1 encoded file */
841 		*fmt = KMF_FORMAT_ASN1;
842 	} else if (check_for_pem(buf, fmt) == TRUE) {
843 		goto end;
844 	} else {
845 		/* Cannot determine this file format */
846 		*fmt = 0;
847 		ret = KMF_ERR_ENCODING;
848 	}
849 
850 end:
851 	kmf_free_data(&filebuf);
852 	return (ret);
853 }
854 
855 KMF_RETURN
856 kmf_hexstr_to_bytes(unsigned char *hexstr, unsigned char **bytes,
857 	size_t *outlen)
858 {
859 	KMF_RETURN ret = KMF_OK;
860 	unsigned char *buf = NULL;
861 	int len, stringlen;
862 	int i;
863 	unsigned char ch;
864 
865 	if (hexstr == NULL) {
866 		return (KMF_ERR_BAD_PARAMETER);
867 	}
868 
869 	if (hexstr[0] == '0' && ((hexstr[1] == 'x') || (hexstr[1] == 'X')))
870 		hexstr += 2;
871 
872 	for (i = 0; i < strlen((char *)hexstr) && isxdigit(hexstr[i]); i++)
873 		/* empty body */
874 		;
875 	/*
876 	 * If all the characters are not legitimate hex chars,
877 	 * return an error.
878 	 */
879 	if (i != strlen((char *)hexstr))
880 		return (KMF_ERR_BAD_HEX_STRING);
881 	stringlen = i;
882 	len = (i / 2) + (i % 2);
883 
884 	buf = malloc(len);
885 	if (buf == NULL) {
886 		return (KMF_ERR_MEMORY);
887 	}
888 	(void) memset(buf, 0, len);
889 
890 	for (i = 0; i < stringlen; i++) {
891 		ch = (unsigned char) *hexstr;
892 		hexstr++;
893 		if ((ch >= '0') && (ch <= '9'))
894 			ch -= '0';
895 		else if ((ch >= 'A') && (ch <= 'F'))
896 			ch = ch - 'A' + 10;
897 		else if ((ch >= 'a') && (ch <= 'f'))
898 			ch = ch - 'a' + 10;
899 		else {
900 			ret = KMF_ERR_BAD_HEX_STRING;
901 			goto out;
902 		}
903 
904 		if (i & 1) {
905 			buf[i/2] |= ch;
906 		} else {
907 			buf[i/2] = (ch << 4);
908 		}
909 	}
910 
911 	*bytes = buf;
912 	*outlen = len;
913 out:
914 	if (buf != NULL && ret != KMF_OK) {
915 		free(buf);
916 	}
917 	return (ret);
918 }
919 
920 void
921 kmf_free_dn(KMF_X509_NAME *name)
922 {
923 	KMF_X509_RDN 		*newrdn = NULL;
924 	KMF_X509_TYPE_VALUE_PAIR *av = NULL;
925 	int i, j;
926 
927 	if (name && name->numberOfRDNs) {
928 		for (i = 0; i < name->numberOfRDNs; i++) {
929 			newrdn = &name->RelativeDistinguishedName[i];
930 			for (j = 0; j < newrdn->numberOfPairs; j++) {
931 				av = &newrdn->AttributeTypeAndValue[j];
932 				kmf_free_data(&av->type);
933 				kmf_free_data(&av->value);
934 			}
935 			free(newrdn->AttributeTypeAndValue);
936 			newrdn->numberOfPairs = 0;
937 			newrdn->AttributeTypeAndValue = NULL;
938 		}
939 		free(name->RelativeDistinguishedName);
940 		name->numberOfRDNs = 0;
941 		name->RelativeDistinguishedName = NULL;
942 	}
943 }
944 
945 void
946 kmf_free_kmf_cert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
947 {
948 	KMF_PLUGIN *plugin;
949 	KMF_RETURN ret;
950 
951 	CLEAR_ERROR(handle, ret);
952 	if (ret != KMF_OK)
953 		return;
954 
955 	if (kmf_cert == NULL)
956 		return;
957 
958 	plugin = FindPlugin(handle, kmf_cert->kmf_private.keystore_type);
959 
960 	if (plugin != NULL && plugin->funclist->FreeKMFCert != NULL) {
961 		plugin->funclist->FreeKMFCert(handle, kmf_cert);
962 	}
963 }
964 
965 void
966 kmf_free_data(KMF_DATA *datablock)
967 {
968 	if (datablock != NULL && datablock->Data != NULL) {
969 		free(datablock->Data);
970 		datablock->Data = NULL;
971 		datablock->Length = 0;
972 	}
973 }
974 
975 void
976 kmf_free_algoid(KMF_X509_ALGORITHM_IDENTIFIER *algoid)
977 {
978 	if (algoid == NULL)
979 		return;
980 	kmf_free_data(&algoid->algorithm);
981 	kmf_free_data(&algoid->parameters);
982 }
983 
984 void
985 kmf_free_extn(KMF_X509_EXTENSION *exptr)
986 {
987 	if (exptr == NULL)
988 		return;
989 
990 	kmf_free_data((KMF_DATA *)&exptr->extnId);
991 	kmf_free_data(&exptr->BERvalue);
992 
993 	if (exptr->value.tagAndValue) {
994 		kmf_free_data(&exptr->value.tagAndValue->value);
995 		free(exptr->value.tagAndValue);
996 	}
997 }
998 
999 void
1000 kmf_free_tbs_csr(KMF_TBS_CSR *tbscsr)
1001 {
1002 	if (tbscsr) {
1003 		kmf_free_data(&tbscsr->version);
1004 
1005 		kmf_free_dn(&tbscsr->subject);
1006 
1007 		kmf_free_algoid(&tbscsr->subjectPublicKeyInfo.algorithm);
1008 		kmf_free_data(&tbscsr->subjectPublicKeyInfo.subjectPublicKey);
1009 
1010 		free_extensions(&tbscsr->extensions);
1011 	}
1012 }
1013 
1014 void
1015 kmf_free_signed_csr(KMF_CSR_DATA *csr)
1016 {
1017 	if (csr) {
1018 		kmf_free_tbs_csr(&csr->csr);
1019 
1020 		kmf_free_algoid(&csr->signature.algorithmIdentifier);
1021 		kmf_free_data(&csr->signature.encrypted);
1022 	}
1023 }
1024 
1025 static void
1026 free_validity(KMF_X509_VALIDITY *validity)
1027 {
1028 	if (validity == NULL)
1029 		return;
1030 	kmf_free_data(&validity->notBefore.time);
1031 	kmf_free_data(&validity->notAfter.time);
1032 }
1033 
1034 static void
1035 free_extensions(KMF_X509_EXTENSIONS *extns)
1036 {
1037 	int i;
1038 	KMF_X509_EXTENSION *exptr;
1039 
1040 	if (extns && extns->numberOfExtensions > 0) {
1041 		for (i = 0; i < extns->numberOfExtensions; i++) {
1042 			exptr = &extns->extensions[i];
1043 			kmf_free_extn(exptr);
1044 		}
1045 		free(extns->extensions);
1046 		extns->numberOfExtensions = 0;
1047 		extns->extensions = NULL;
1048 	}
1049 }
1050 
1051 void
1052 kmf_free_tbs_cert(KMF_X509_TBS_CERT *tbscert)
1053 {
1054 	if (tbscert) {
1055 		kmf_free_data(&tbscert->version);
1056 		kmf_free_bigint(&tbscert->serialNumber);
1057 		kmf_free_algoid(&tbscert->signature);
1058 
1059 		kmf_free_dn(&tbscert->issuer);
1060 		kmf_free_dn(&tbscert->subject);
1061 
1062 		free_validity(&tbscert->validity);
1063 
1064 		kmf_free_data(&tbscert->issuerUniqueIdentifier);
1065 		kmf_free_data(&tbscert->subjectUniqueIdentifier);
1066 
1067 		kmf_free_algoid(&tbscert->subjectPublicKeyInfo.algorithm);
1068 		kmf_free_data(&tbscert->subjectPublicKeyInfo.subjectPublicKey);
1069 
1070 		free_extensions(&tbscert->extensions);
1071 
1072 		kmf_free_data(&tbscert->issuerUniqueIdentifier);
1073 		kmf_free_data(&tbscert->subjectUniqueIdentifier);
1074 	}
1075 }
1076 
1077 void
1078 kmf_free_signed_cert(KMF_X509_CERTIFICATE *certptr)
1079 {
1080 	if (!certptr)
1081 		return;
1082 
1083 	kmf_free_tbs_cert(&certptr->certificate);
1084 
1085 	kmf_free_algoid(&certptr->signature.algorithmIdentifier);
1086 	kmf_free_data(&certptr->signature.encrypted);
1087 }
1088 
1089 void
1090 kmf_free_str(char *pstr)
1091 {
1092 	if (pstr != NULL)
1093 		free(pstr);
1094 }
1095 
1096 void
1097 free_keyidlist(KMF_OID *oidlist, int len)
1098 {
1099 	int i;
1100 	for (i = 0; i < len; i++) {
1101 		kmf_free_data((KMF_DATA *)&oidlist[i]);
1102 	}
1103 	free(oidlist);
1104 }
1105 
1106 void
1107 kmf_free_eku(KMF_X509EXT_EKU *eptr)
1108 {
1109 	if (eptr && eptr->nEKUs > 0 && eptr->keyPurposeIdList != NULL)
1110 		free_keyidlist(eptr->keyPurposeIdList, eptr->nEKUs);
1111 }
1112 
1113 void
1114 kmf_free_spki(KMF_X509_SPKI *spki)
1115 {
1116 	if (spki != NULL) {
1117 		kmf_free_algoid(&spki->algorithm);
1118 		kmf_free_data(&spki->subjectPublicKey);
1119 	}
1120 }
1121 
1122 void
1123 kmf_free_kmf_key(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key)
1124 {
1125 	KMF_PLUGIN *plugin;
1126 	KMF_RETURN ret;
1127 	KMF_ATTRIBUTE attlist[2]; /* only 2 attributes for DeleteKey op */
1128 	int i = 0;
1129 	boolean_t token_destroy = B_FALSE;
1130 
1131 	if (key == NULL)
1132 		return;
1133 
1134 	CLEAR_ERROR(handle, ret);
1135 	if (ret != KMF_OK)
1136 		return;
1137 
1138 	kmf_set_attr_at_index(attlist, i,
1139 	    KMF_KEY_HANDLE_ATTR, key, sizeof (KMF_KEY_HANDLE));
1140 	i++;
1141 
1142 	kmf_set_attr_at_index(attlist, i,
1143 	    KMF_DESTROY_BOOL_ATTR, &token_destroy, sizeof (boolean_t));
1144 	i++;
1145 
1146 	plugin = FindPlugin(handle, key->kstype);
1147 	if (plugin != NULL && plugin->funclist->DeleteKey != NULL) {
1148 		(void) plugin->funclist->DeleteKey(handle, i, attlist);
1149 	}
1150 
1151 	if (key->keylabel)
1152 		free(key->keylabel);
1153 
1154 	if (key->israw) {
1155 		kmf_free_raw_key(key->keyp);
1156 		free(key->keyp);
1157 	}
1158 
1159 	(void) memset(key, 0, sizeof (KMF_KEY_HANDLE));
1160 }
1161 
1162 void
1163 kmf_free_bigint(KMF_BIGINT *big)
1164 {
1165 	if (big != NULL && big->val != NULL) {
1166 		/* Clear it out before returning it to the pool */
1167 		(void) memset(big->val, 0x00, big->len);
1168 		free(big->val);
1169 		big->val = NULL;
1170 		big->len = 0;
1171 	}
1172 }
1173 
1174 static void
1175 free_raw_rsa(KMF_RAW_RSA_KEY *key)
1176 {
1177 	if (key == NULL)
1178 		return;
1179 	kmf_free_bigint(&key->mod);
1180 	kmf_free_bigint(&key->pubexp);
1181 	kmf_free_bigint(&key->priexp);
1182 	kmf_free_bigint(&key->prime1);
1183 	kmf_free_bigint(&key->prime2);
1184 	kmf_free_bigint(&key->exp1);
1185 	kmf_free_bigint(&key->exp2);
1186 	kmf_free_bigint(&key->coef);
1187 }
1188 
1189 static void
1190 free_raw_dsa(KMF_RAW_DSA_KEY *key)
1191 {
1192 	if (key == NULL)
1193 		return;
1194 	kmf_free_bigint(&key->prime);
1195 	kmf_free_bigint(&key->subprime);
1196 	kmf_free_bigint(&key->base);
1197 	kmf_free_bigint(&key->value);
1198 }
1199 
1200 static void
1201 free_raw_sym(KMF_RAW_SYM_KEY *key)
1202 {
1203 	if (key == NULL)
1204 		return;
1205 	kmf_free_bigint(&key->keydata);
1206 }
1207 
1208 void
1209 kmf_free_raw_key(KMF_RAW_KEY_DATA *key)
1210 {
1211 	if (key == NULL)
1212 		return;
1213 
1214 	switch (key->keytype) {
1215 	case KMF_RSA:
1216 		free_raw_rsa(&key->rawdata.rsa);
1217 		break;
1218 	case KMF_DSA:
1219 		free_raw_dsa(&key->rawdata.dsa);
1220 		break;
1221 	case KMF_AES:
1222 	case KMF_RC4:
1223 	case KMF_DES:
1224 	case KMF_DES3:
1225 		free_raw_sym(&key->rawdata.sym);
1226 		break;
1227 	}
1228 }
1229 
1230 void
1231 kmf_free_raw_sym_key(KMF_RAW_SYM_KEY *key)
1232 {
1233 	if (key == NULL)
1234 		return;
1235 	kmf_free_bigint(&key->keydata);
1236 	free(key);
1237 }
1238 
1239 /*
1240  * This function frees the space allocated for the name portion of a
1241  * KMF_CRL_DIST_POINT.
1242  */
1243 void
1244 free_dp_name(KMF_CRL_DIST_POINT *dp)
1245 {
1246 	KMF_GENERALNAMES *fullname;
1247 	KMF_DATA *urldata;
1248 	int i;
1249 
1250 	if (dp == NULL)
1251 		return;
1252 
1253 	/* For phase 1, we only need to free the fullname space. */
1254 	fullname = &(dp->name.full_name);
1255 	if (fullname->number == 0)
1256 		return;
1257 
1258 	for (i = 0; i < fullname->number; i++) {
1259 		urldata = &(fullname->namelist[fullname->number - 1].name);
1260 		kmf_free_data(urldata);
1261 	}
1262 
1263 	free(fullname->namelist);
1264 }
1265 
1266 /*
1267  * This function frees the space allocated for a KMF_CRL_DIST_POINT.
1268  */
1269 void
1270 free_dp(KMF_CRL_DIST_POINT *dp)
1271 {
1272 	if (dp == NULL)
1273 		return;
1274 
1275 	free_dp_name(dp);
1276 	kmf_free_data(&(dp->reasons));
1277 	/* Need not to free crl_issuer space at phase 1 */
1278 }
1279 
1280 /*
1281  * This function frees space for a KMF_X509EXT_CRLDISTPOINTS internally.
1282  */
1283 void
1284 kmf_free_crl_dist_pts(KMF_X509EXT_CRLDISTPOINTS *crl_dps)
1285 {
1286 	int i;
1287 
1288 	if (crl_dps == NULL)
1289 		return;
1290 
1291 	for (i = 0; i < crl_dps->number; i++)
1292 		free_dp(&(crl_dps->dplist[i]));
1293 
1294 	free(crl_dps->dplist);
1295 }
1296 
1297 KMF_RETURN
1298 kmf_create_ocsp_request(KMF_HANDLE_T handle,
1299 	int	num_args,
1300 	KMF_ATTRIBUTE	*attrlist)
1301 {
1302 	KMF_RETURN ret = KMF_OK;
1303 	KMF_PLUGIN *plugin;
1304 	KMF_RETURN (*createReqFn)(void *, int num_args,
1305 	    KMF_ATTRIBUTE *attrlist);
1306 
1307 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
1308 		{KMF_OCSP_REQUEST_FILENAME_ATTR, FALSE, 1, 0},
1309 		{KMF_USER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1310 			sizeof (KMF_DATA)},
1311 		{KMF_ISSUER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1312 			sizeof (KMF_DATA)},
1313 	};
1314 
1315 	int num_req_attrs = sizeof (required_attrs) /
1316 	    sizeof (KMF_ATTRIBUTE_TESTER);
1317 
1318 	if (handle == NULL)
1319 		return (KMF_ERR_BAD_PARAMETER);
1320 
1321 	CLEAR_ERROR(handle, ret);
1322 
1323 	ret = test_attributes(num_req_attrs, required_attrs,
1324 	    0, NULL, num_args, attrlist);
1325 
1326 	if (ret != KMF_OK)
1327 		return (ret);
1328 
1329 	/*
1330 	 * This framework function is actually implemented in the openssl
1331 	 * plugin library, so we find the function address and call it.
1332 	 */
1333 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
1334 	if (plugin == NULL || plugin->dldesc == NULL) {
1335 		return (KMF_ERR_PLUGIN_NOTFOUND);
1336 	}
1337 
1338 	createReqFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
1339 	    "OpenSSL_CreateOCSPRequest");
1340 	if (createReqFn == NULL) {
1341 		return (KMF_ERR_FUNCTION_NOT_FOUND);
1342 	}
1343 
1344 	return (createReqFn(handle, num_args, attrlist));
1345 
1346 }
1347 
1348 KMF_RETURN
1349 kmf_get_ocsp_status_for_cert(KMF_HANDLE_T handle,
1350 	int	num_args,
1351 	KMF_ATTRIBUTE	*attrlist)
1352 {
1353 	KMF_RETURN ret = KMF_OK;
1354 	KMF_PLUGIN *plugin;
1355 	KMF_RETURN (*getCertStatusFn)(void *, int num_args,
1356 	    KMF_ATTRIBUTE *attrlist);
1357 
1358 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
1359 		{KMF_USER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1360 			sizeof (KMF_DATA)},
1361 		{KMF_ISSUER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1362 			sizeof (KMF_DATA)},
1363 		{KMF_OCSP_RESPONSE_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1364 			sizeof (KMF_DATA)},
1365 		{KMF_OCSP_RESPONSE_STATUS_ATTR, FALSE, sizeof (int),
1366 			sizeof (uint32_t)},
1367 		{KMF_OCSP_RESPONSE_REASON_ATTR, FALSE, sizeof (int),
1368 			sizeof (uint32_t)},
1369 		{KMF_OCSP_RESPONSE_CERT_STATUS_ATTR, FALSE, sizeof (int),
1370 			sizeof (uint32_t)},
1371 	};
1372 
1373 	int num_req_attrs = sizeof (required_attrs) /
1374 	    sizeof (KMF_ATTRIBUTE_TESTER);
1375 
1376 	if (handle == NULL)
1377 		return (KMF_ERR_BAD_PARAMETER);
1378 
1379 	CLEAR_ERROR(handle, ret);
1380 
1381 	ret = test_attributes(num_req_attrs, required_attrs,
1382 	    0, NULL, num_args, attrlist);
1383 
1384 	if (ret != KMF_OK)
1385 		return (ret);
1386 
1387 	/*
1388 	 * This framework function is actually implemented in the openssl
1389 	 * plugin library, so we find the function address and call it.
1390 	 */
1391 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
1392 	if (plugin == NULL || plugin->dldesc == NULL) {
1393 		return (KMF_ERR_INTERNAL);
1394 	}
1395 
1396 	getCertStatusFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
1397 	    "OpenSSL_GetOCSPStatusForCert");
1398 	if (getCertStatusFn == NULL) {
1399 		return (KMF_ERR_INTERNAL);
1400 	}
1401 
1402 	return (getCertStatusFn(handle, num_args, attrlist));
1403 
1404 }
1405 
1406 KMF_RETURN
1407 kmf_string_to_oid(char *oidstring, KMF_OID *oid)
1408 {
1409 	KMF_RETURN rv = KMF_OK;
1410 	char *cp, *bp, *startp;
1411 	int numbuf;
1412 	int onumbuf;
1413 	int nbytes, index;
1414 	int len;
1415 	unsigned char *op;
1416 
1417 	if (oidstring == NULL || oid == NULL)
1418 		return (KMF_ERR_BAD_PARAMETER);
1419 
1420 	len = strlen(oidstring);
1421 
1422 	bp = oidstring;
1423 	cp = bp;
1424 	/* Skip over leading space */
1425 	while ((bp < &cp[len]) && isspace(*bp))
1426 		bp++;
1427 
1428 	startp = bp;
1429 	nbytes = 0;
1430 
1431 	/*
1432 	 * The first two numbers are chewed up by the first octet.
1433 	 */
1434 	if (sscanf(bp, "%d", &numbuf) != 1)
1435 		return (KMF_ERR_BAD_PARAMETER);
1436 	while ((bp < &cp[len]) && isdigit(*bp))
1437 		bp++;
1438 	while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
1439 		bp++;
1440 	if (sscanf(bp, "%d", &numbuf) != 1)
1441 		return (KMF_ERR_BAD_PARAMETER);
1442 	while ((bp < &cp[len]) && isdigit(*bp))
1443 		bp++;
1444 	while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
1445 		bp++;
1446 	nbytes++;
1447 
1448 	while (isdigit(*bp)) {
1449 		if (sscanf(bp, "%d", &numbuf) != 1)
1450 			return (KMF_ERR_BAD_PARAMETER);
1451 		while (numbuf) {
1452 			nbytes++;
1453 			numbuf >>= 7;
1454 		}
1455 		while ((bp < &cp[len]) && isdigit(*bp))
1456 			bp++;
1457 		while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
1458 			bp++;
1459 	}
1460 
1461 	oid->Length = nbytes;
1462 	oid->Data = malloc(oid->Length);
1463 	if (oid->Data == NULL) {
1464 		return (KMF_ERR_MEMORY);
1465 	}
1466 	(void) memset(oid->Data, 0, oid->Length);
1467 
1468 	op = oid->Data;
1469 
1470 	bp = startp;
1471 	(void) sscanf(bp, "%d", &numbuf);
1472 
1473 	while (isdigit(*bp)) bp++;
1474 	while (isspace(*bp) || *bp == '.') bp++;
1475 
1476 	onumbuf = 40 * numbuf;
1477 	(void) sscanf(bp, "%d", &numbuf);
1478 	onumbuf += numbuf;
1479 	*op = (unsigned char) onumbuf;
1480 	op++;
1481 
1482 	while (isdigit(*bp)) bp++;
1483 	while (isspace(*bp) || *bp == '.') bp++;
1484 	while (isdigit(*bp)) {
1485 		(void) sscanf(bp, "%d", &numbuf);
1486 		nbytes = 0;
1487 		/* Have to fill in the bytes msb-first */
1488 		onumbuf = numbuf;
1489 		while (numbuf) {
1490 			nbytes++;
1491 			numbuf >>= 7;
1492 		}
1493 		numbuf = onumbuf;
1494 		op += nbytes;
1495 		index = -1;
1496 		while (numbuf) {
1497 			op[index] = (unsigned char)numbuf & 0x7f;
1498 			if (index != -1)
1499 				op[index] |= 0x80;
1500 			index--;
1501 			numbuf >>= 7;
1502 		}
1503 		while (isdigit(*bp)) bp++;
1504 		while (isspace(*bp) || *bp == '.') bp++;
1505 	}
1506 
1507 	return (rv);
1508 }
1509 
1510 static KMF_RETURN
1511 encode_rid(char *name, KMF_DATA *derdata)
1512 {
1513 	KMF_RETURN rv = KMF_OK;
1514 
1515 	if (name == NULL || derdata == NULL)
1516 		return (KMF_ERR_BAD_PARAMETER);
1517 
1518 	rv = kmf_string_to_oid(name, (KMF_OID *)derdata);
1519 
1520 	return (rv);
1521 }
1522 
1523 static KMF_RETURN
1524 encode_ipaddr(char *name, KMF_DATA *derdata)
1525 {
1526 	KMF_RETURN rv = KMF_OK;
1527 	size_t len;
1528 	in_addr_t v4;
1529 	in6_addr_t v6;
1530 	uint8_t *ptr;
1531 
1532 	if (name == NULL || derdata == NULL)
1533 		return (KMF_ERR_BAD_PARAMETER);
1534 
1535 	v4 = inet_addr(name);
1536 	if (v4 == (in_addr_t)-1) {
1537 		ptr = (uint8_t *)&v6;
1538 		if (inet_pton(AF_INET6, name, ptr) != 1)
1539 			return (KMF_ERR_ENCODING);
1540 		len = sizeof (v6);
1541 	} else {
1542 		ptr = (uint8_t *)&v4;
1543 		len = sizeof (v4);
1544 	}
1545 
1546 	derdata->Data = malloc(len);
1547 	if (derdata->Data == NULL)
1548 		return (KMF_ERR_MEMORY);
1549 	(void) memcpy(derdata->Data, ptr, len);
1550 	derdata->Length = len;
1551 
1552 	return (rv);
1553 }
1554 
1555 static KMF_RETURN
1556 verify_uri_format(char *uristring)
1557 {
1558 	KMF_RETURN ret = KMF_OK;
1559 	xmlURIPtr   uriptr = NULL;
1560 
1561 	/* Parse the URI string; get the hostname and port */
1562 	uriptr = xmlParseURI(uristring);
1563 	if (uriptr == NULL) {
1564 		ret = KMF_ERR_BAD_URI;
1565 		goto out;
1566 	}
1567 
1568 	if (uriptr->scheme == NULL || !strlen(uriptr->scheme)) {
1569 		ret = KMF_ERR_BAD_URI;
1570 		goto out;
1571 	}
1572 
1573 	if (uriptr->server == NULL || !strlen(uriptr->server)) {
1574 		ret = KMF_ERR_BAD_URI;
1575 		goto out;
1576 	}
1577 out:
1578 	if (uriptr != NULL)
1579 		xmlFreeURI(uriptr);
1580 	return (ret);
1581 }
1582 
1583 static KMF_RETURN
1584 encode_altname(char *namedata,
1585 	KMF_GENERALNAMECHOICES nametype, KMF_DATA *encodedname)
1586 {
1587 	KMF_RETURN ret = KMF_OK;
1588 	KMF_X509_NAME dnname;
1589 	uchar_t tagval;
1590 	BerElement *asn1 = NULL;
1591 	BerValue *extdata;
1592 
1593 	if (namedata == NULL || encodedname == NULL)
1594 		return (KMF_ERR_BAD_PARAMETER);
1595 
1596 	/*
1597 	 * Encode the namedata according to rules in RFC 3280 for GeneralName.
1598 	 * The input "namedata" is assumed to be an ASCII string representation
1599 	 * of the AltName, we need to convert it to correct ASN.1 here before
1600 	 * adding it to the cert.
1601 	 */
1602 	switch (nametype) {
1603 		case GENNAME_RFC822NAME: /* rfc 822 */
1604 			/* IA5String, no encoding needed */
1605 			encodedname->Data = (uchar_t *)strdup(namedata);
1606 			if (encodedname->Data == NULL)
1607 				return (KMF_ERR_MEMORY);
1608 			encodedname->Length = strlen(namedata);
1609 			tagval = (0x80 | nametype);
1610 			break;
1611 		case GENNAME_DNSNAME: /* rfc 1034 */
1612 			encodedname->Data = (uchar_t *)strdup(namedata);
1613 			if (encodedname->Data == NULL)
1614 				return (KMF_ERR_MEMORY);
1615 			encodedname->Length = strlen(namedata);
1616 			tagval = (0x80 | nametype);
1617 			break;
1618 		case GENNAME_URI: /* rfc 1738 */
1619 			ret = verify_uri_format(namedata);
1620 			if (ret != KMF_OK)
1621 				return (ret);
1622 			/* IA5String, no encoding needed */
1623 			encodedname->Data = (uchar_t *)strdup(namedata);
1624 			if (encodedname->Data == NULL)
1625 				return (KMF_ERR_MEMORY);
1626 			encodedname->Length = strlen(namedata);
1627 			tagval = (0x80 | nametype);
1628 			break;
1629 		case GENNAME_IPADDRESS:
1630 			ret =  encode_ipaddr(namedata, encodedname);
1631 			tagval = (0x80 | nametype);
1632 			break;
1633 		case GENNAME_REGISTEREDID:
1634 			ret = encode_rid(namedata, encodedname);
1635 			tagval = (0x80 | nametype);
1636 			break;
1637 		case GENNAME_DIRECTORYNAME:
1638 			ret = kmf_dn_parser(namedata, &dnname);
1639 			if (ret == KMF_OK) {
1640 				ret = DerEncodeName(&dnname, encodedname);
1641 			}
1642 			(void) kmf_free_dn(&dnname);
1643 			tagval = (0xA0 | nametype);
1644 			break;
1645 		default:
1646 			/* unsupported */
1647 			return (KMF_ERR_BAD_PARAMETER);
1648 
1649 	}
1650 	if (ret != KMF_OK) {
1651 		kmf_free_data(encodedname);
1652 		return (ret);
1653 	}
1654 
1655 	if ((asn1 = kmfder_alloc()) == NULL)
1656 		return (KMF_ERR_MEMORY);
1657 
1658 	if (kmfber_printf(asn1, "Tl", tagval, encodedname->Length) == -1)
1659 		goto cleanup;
1660 
1661 	if (kmfber_write(asn1, (char *)encodedname->Data,
1662 	    encodedname->Length, 0) == -1) {
1663 		ret = KMF_ERR_ENCODING;
1664 		goto cleanup;
1665 	}
1666 	if (kmfber_flatten(asn1, &extdata) == -1) {
1667 		ret = KMF_ERR_ENCODING;
1668 		goto cleanup;
1669 	}
1670 
1671 	kmf_free_data(encodedname);
1672 	encodedname->Data = (uchar_t *)extdata->bv_val;
1673 	encodedname->Length = extdata->bv_len;
1674 
1675 	free(extdata);
1676 
1677 cleanup:
1678 	if (asn1)
1679 		kmfber_free(asn1, 1);
1680 
1681 	if (ret != KMF_OK)
1682 		kmf_free_data(encodedname);
1683 
1684 	return (ret);
1685 }
1686 
1687 KMF_X509_EXTENSION *
1688 FindExtn(KMF_X509_EXTENSIONS *exts, KMF_OID *oid)
1689 {
1690 	KMF_X509_EXTENSION *foundextn = NULL;
1691 	int i;
1692 
1693 	if (exts == NULL || oid == NULL)
1694 		return (NULL);
1695 
1696 	for (i = 0; i < exts->numberOfExtensions; i++) {
1697 		if (IsEqualOid(oid, &exts->extensions[i].extnId))  {
1698 			foundextn = &exts->extensions[i];
1699 			break;
1700 		}
1701 	}
1702 	return (foundextn);
1703 }
1704 
1705 KMF_RETURN
1706 GetSequenceContents(char *data, size_t len,
1707 	char **contents, size_t *outlen)
1708 {
1709 	KMF_RETURN ret = KMF_OK;
1710 	BerElement *exasn1 = NULL;
1711 	BerValue oldextn;
1712 	int tag;
1713 	size_t oldsize;
1714 	char *olddata = NULL;
1715 
1716 	if (data == NULL || contents == NULL || outlen == NULL)
1717 		return (KMF_ERR_BAD_PARAMETER);
1718 
1719 	/*
1720 	 * Decode the sequence of general names
1721 	 */
1722 	oldextn.bv_val = data;
1723 	oldextn.bv_len = len;
1724 
1725 	if ((exasn1 = kmfder_init(&oldextn)) == NULL) {
1726 		ret = KMF_ERR_MEMORY;
1727 		goto out;
1728 	}
1729 
1730 	/*
1731 	 * Unwrap the sequence to find the size of the block
1732 	 * of GeneralName items in the set.
1733 	 *
1734 	 * Peek at the tag and length ("tl"),
1735 	 * then consume them ("{").
1736 	 */
1737 	if (kmfber_scanf(exasn1, "tl{", &tag, &oldsize) == KMFBER_DEFAULT ||
1738 	    oldsize == 0) {
1739 		ret = KMF_ERR_ENCODING;
1740 		goto out;
1741 	}
1742 
1743 	olddata = malloc(oldsize);
1744 	if (olddata == NULL) {
1745 		ret = KMF_ERR_MEMORY;
1746 		goto out;
1747 	}
1748 	(void) memset(olddata, 0, oldsize);
1749 	/*
1750 	 * Read the entire blob of GeneralNames, we don't
1751 	 * need to interpret them now.
1752 	 */
1753 	if (kmfber_read(exasn1, olddata, oldsize) != oldsize) {
1754 		ret = KMF_ERR_ENCODING;
1755 		goto out;
1756 	}
1757 out:
1758 	if (exasn1 != NULL)
1759 		kmfber_free(exasn1, 1);
1760 
1761 	if (ret != KMF_OK) {
1762 		*contents = NULL;
1763 		*outlen = 0;
1764 		if (olddata != NULL)
1765 			free(olddata);
1766 	} else {
1767 		*contents = olddata;
1768 		*outlen = oldsize;
1769 	}
1770 	return (ret);
1771 }
1772 
1773 KMF_RETURN
1774 add_an_extension(KMF_X509_EXTENSIONS *exts, KMF_X509_EXTENSION *newextn)
1775 {
1776 	KMF_RETURN ret = KMF_OK;
1777 	KMF_X509_EXTENSION *extlist;
1778 
1779 	if (exts == NULL || newextn == NULL)
1780 		return (KMF_ERR_BAD_PARAMETER);
1781 
1782 	extlist = malloc(sizeof (KMF_X509_EXTENSION) *
1783 	    (exts->numberOfExtensions + 1));
1784 	if (extlist == NULL)
1785 		return (KMF_ERR_MEMORY);
1786 
1787 	(void) memcpy(extlist, exts->extensions,
1788 	    exts->numberOfExtensions * sizeof (KMF_X509_EXTENSION));
1789 
1790 	(void) memcpy(&extlist[exts->numberOfExtensions], newextn,
1791 	    sizeof (KMF_X509_EXTENSION));
1792 
1793 	free(exts->extensions);
1794 	exts->numberOfExtensions++;
1795 	exts->extensions = extlist;
1796 
1797 	return (ret);
1798 }
1799 
1800 KMF_RETURN
1801 kmf_set_altname(KMF_X509_EXTENSIONS *extensions,
1802 	KMF_OID *oid,
1803 	int critical,
1804 	KMF_GENERALNAMECHOICES nametype,
1805 	char *namedata)
1806 {
1807 	KMF_RETURN ret = KMF_OK;
1808 	KMF_X509_EXTENSION subjAltName;
1809 	KMF_DATA dername = { NULL, 0 };
1810 	BerElement *asn1 = NULL;
1811 	BerValue *extdata;
1812 	char *olddata = NULL;
1813 	KMF_X509_EXTENSION *foundextn = NULL;
1814 	size_t	oldsize = 0;
1815 
1816 	if (extensions == NULL || oid == NULL || namedata == NULL)
1817 		return (KMF_ERR_BAD_PARAMETER);
1818 
1819 	ret = encode_altname(namedata, nametype, &dername);
1820 
1821 	if (ret != KMF_OK)
1822 		return (ret);
1823 
1824 	(void) memset(&subjAltName, 0, sizeof (subjAltName));
1825 
1826 	ret = copy_data(&subjAltName.extnId, oid);
1827 	if (ret != KMF_OK)
1828 		goto out;
1829 	/*
1830 	 * Check to see if this cert already has a subjectAltName.
1831 	 */
1832 	foundextn = FindExtn(extensions, oid);
1833 
1834 	if (foundextn != NULL) {
1835 		ret = GetSequenceContents(
1836 		    (char *)foundextn->BERvalue.Data,
1837 		    foundextn->BERvalue.Length,
1838 		    &olddata, &oldsize);
1839 		if (ret != KMF_OK)
1840 			goto out;
1841 	}
1842 
1843 	/*
1844 	 * Assume (!!) that the namedata given is already properly encoded.
1845 	 */
1846 	if ((asn1 = kmfder_alloc()) == NULL)
1847 		return (KMF_ERR_MEMORY);
1848 
1849 	if (kmfber_printf(asn1, "{") == -1) {
1850 		ret = KMF_ERR_ENCODING;
1851 		goto out;
1852 	}
1853 
1854 	/* Write the old extension data first */
1855 	if (olddata != NULL && oldsize > 0) {
1856 		if (kmfber_write(asn1, olddata, oldsize, 0) == -1) {
1857 			ret = KMF_ERR_ENCODING;
1858 			goto out;
1859 		}
1860 	}
1861 
1862 	/* Now add the new name to the list */
1863 	if (kmfber_write(asn1, (char *)dername.Data, dername.Length, 0) == -1) {
1864 		ret = KMF_ERR_ENCODING;
1865 		goto out;
1866 	}
1867 
1868 	/* Now close the sequence */
1869 	if (kmfber_printf(asn1, "}") == -1) {
1870 		ret = KMF_ERR_ENCODING;
1871 		goto out;
1872 	}
1873 	if (kmfber_flatten(asn1, &extdata) == -1) {
1874 		ret = KMF_ERR_ENCODING;
1875 		goto out;
1876 	}
1877 
1878 	/*
1879 	 * If we are just adding to an existing list of altNames,
1880 	 * just replace the BER data associated with the found extension.
1881 	 */
1882 	if (foundextn != NULL) {
1883 		free(foundextn->BERvalue.Data);
1884 		foundextn->critical = critical;
1885 		foundextn->BERvalue.Data = (uchar_t *)extdata->bv_val;
1886 		foundextn->BERvalue.Length = extdata->bv_len;
1887 	} else {
1888 		subjAltName.critical = critical;
1889 		subjAltName.format = KMF_X509_DATAFORMAT_ENCODED;
1890 		subjAltName.BERvalue.Data = (uchar_t *)extdata->bv_val;
1891 		subjAltName.BERvalue.Length = extdata->bv_len;
1892 		ret = add_an_extension(extensions, &subjAltName);
1893 		if (ret != KMF_OK)
1894 			free(subjAltName.BERvalue.Data);
1895 	}
1896 
1897 	free(extdata);
1898 out:
1899 	if (olddata != NULL)
1900 		free(olddata);
1901 
1902 	kmf_free_data(&dername);
1903 	if (ret != KMF_OK)
1904 		kmf_free_data(&subjAltName.extnId);
1905 	if (asn1 != NULL)
1906 		kmfber_free(asn1, 1);
1907 	return (ret);
1908 }
1909 
1910 /*
1911  * Search a list of attributes for one that matches the given type.
1912  * Return a pointer into the attribute list.  This does not
1913  * return a copy of the value, it returns a reference into the
1914  * given list.
1915  */
1916 int
1917 kmf_find_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist, int numattrs)
1918 {
1919 	int i;
1920 	for (i = 0; i < numattrs; i++) {
1921 		if (attlist[i].type == type)
1922 			return (i);
1923 	}
1924 	return (-1);
1925 }
1926 
1927 /*
1928  * Verify that a given attribute is consistent with the
1929  * "test" attribute.
1930  */
1931 static KMF_RETURN
1932 verify_attribute(KMF_ATTRIBUTE *givenattr,
1933 	KMF_ATTRIBUTE_TESTER *testattr)
1934 {
1935 	/* A NULL pValue was found where one is required */
1936 	if (testattr->null_value_ok == FALSE &&
1937 	    givenattr->pValue == NULL)
1938 		return (KMF_ERR_BAD_PARAMETER);
1939 
1940 	/* If the given valueLen is too small, return error */
1941 	if (givenattr->pValue != NULL &&
1942 	    testattr->minlen > 0 &&
1943 	    (givenattr->valueLen < testattr->minlen))
1944 		return (KMF_ERR_BAD_PARAMETER);
1945 
1946 	/* If the given valueLen is too big, return error */
1947 	if (givenattr->pValue != NULL &&
1948 	    testattr->maxlen > 0 &&
1949 	    (givenattr->valueLen > testattr->maxlen))
1950 		return (KMF_ERR_BAD_PARAMETER);
1951 
1952 	return (KMF_OK);
1953 }
1954 
1955 /*
1956  * Given a set of required attribute tests and optional
1957  * attributes, make sure that the actual attributes
1958  * being tested (attrlist below) are allowed and are
1959  * properly specified.
1960  */
1961 KMF_RETURN
1962 test_attributes(int reqnum, KMF_ATTRIBUTE_TESTER *reqattrs,
1963 	int optnum, KMF_ATTRIBUTE_TESTER *optattrs,
1964 	int numattrs, KMF_ATTRIBUTE *attrlist)
1965 {
1966 	KMF_RETURN ret = KMF_OK;
1967 	int i, idx;
1968 
1969 	/*
1970 	 * If the caller didn't supply enough attributes,
1971 	 * return an error.
1972 	 */
1973 	if (numattrs < reqnum || attrlist == NULL)
1974 		return (KMF_ERR_BAD_PARAMETER);
1975 
1976 	/*
1977 	 * Make sure all required attrs are present and
1978 	 * correct.
1979 	 */
1980 	for (i = 0; i < reqnum && ret == KMF_OK; i++) {
1981 		idx = kmf_find_attr(reqattrs[i].type, attrlist, numattrs);
1982 		/* If a required attr is not found, return error */
1983 		if (idx == -1) {
1984 			return (KMF_ERR_BAD_PARAMETER);
1985 		}
1986 
1987 		ret = verify_attribute(&attrlist[idx], &reqattrs[i]);
1988 	}
1989 	/*
1990 	 * Now test the optional parameters.
1991 	 */
1992 	for (i = 0; i < optnum && ret == KMF_OK; i++) {
1993 		idx = kmf_find_attr(optattrs[i].type, attrlist, numattrs);
1994 		/* If a optional attr is not found, continue. */
1995 		if (idx == -1) {
1996 			continue;
1997 		}
1998 
1999 		ret = verify_attribute(&attrlist[idx], &optattrs[i]);
2000 	}
2001 
2002 	return (ret);
2003 }
2004 
2005 /*
2006  * Given an already allocated attribute list, insert
2007  * the given attribute information at a specific index
2008  * in the list.
2009  */
2010 void
2011 kmf_set_attr_at_index(KMF_ATTRIBUTE *attlist, int index,
2012 	KMF_ATTR_TYPE type,  void *pValue, uint32_t len)
2013 {
2014 	if (attlist == NULL)
2015 		return;
2016 
2017 	attlist[index].type = type;
2018 	attlist[index].pValue = pValue;
2019 	attlist[index].valueLen = len;
2020 }
2021 
2022 /*
2023  * Find an attribute matching a particular type and set
2024  * the pValue and length fields to the given values.
2025  */
2026 KMF_RETURN
2027 kmf_set_attr(KMF_ATTRIBUTE *attlist, int numattr,
2028 	KMF_ATTR_TYPE type,  void *pValue, uint32_t len)
2029 {
2030 	int idx;
2031 	if (attlist == NULL)
2032 		return (KMF_ERR_BAD_PARAMETER);
2033 
2034 	idx = kmf_find_attr(type, attlist, numattr);
2035 	if (idx == -1)
2036 		return (KMF_ERR_ATTR_NOT_FOUND);
2037 
2038 	attlist[idx].type = type;
2039 	/* Assumes the attribute pValue can hold the result */
2040 	if (attlist[idx].pValue != NULL) {
2041 		if (attlist[idx].valueLen >= len)
2042 			(void) memcpy(attlist[idx].pValue, pValue, len);
2043 		else
2044 			return (KMF_ERR_BUFFER_SIZE);
2045 	}
2046 	attlist[idx].valueLen = len;
2047 	return (KMF_OK);
2048 }
2049 
2050 /*
2051  * Find a particular attribute in a list and return
2052  * a pointer to its value.
2053  */
2054 void *
2055 kmf_get_attr_ptr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist,
2056 	int numattrs)
2057 {
2058 	int i;
2059 
2060 	i = kmf_find_attr(type, attlist, numattrs);
2061 	if (i == -1)
2062 		return (NULL);
2063 
2064 	return (attlist[i].pValue);
2065 }
2066 
2067 /*
2068  * Find a particular attribute in a list and return
2069  * the value and length values.  Value and length
2070  * may be NULL if the caller doesn't want their values
2071  * to be filled in.
2072  */
2073 KMF_RETURN
2074 kmf_get_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist,
2075 	int numattrs, void *outValue, uint32_t *outlen)
2076 {
2077 	int i;
2078 	uint32_t len = 0;
2079 	uint32_t *lenptr = outlen;
2080 
2081 	if (lenptr == NULL)
2082 		lenptr = &len;
2083 
2084 	i = kmf_find_attr(type, attlist, numattrs);
2085 	if (i == -1)
2086 		return (KMF_ERR_ATTR_NOT_FOUND);
2087 
2088 	/* This assumes that the ptr passed in is pre-allocated space */
2089 	if (attlist[i].pValue != NULL && outValue != NULL) {
2090 		/*
2091 		 * If the caller did not specify a length,
2092 		 * assume "outValue" is big enough.
2093 		 */
2094 		if (outlen != NULL) {
2095 			if (*outlen >= attlist[i].valueLen)
2096 				(void) memcpy(outValue, attlist[i].pValue,
2097 				    attlist[i].valueLen);
2098 			else
2099 				return (KMF_ERR_BUFFER_SIZE);
2100 		} else {
2101 			(void) memcpy(outValue, attlist[i].pValue,
2102 			    attlist[i].valueLen);
2103 		}
2104 	}
2105 
2106 	if (outlen != NULL)
2107 		*outlen = attlist[i].valueLen;
2108 	return (KMF_OK);
2109 }
2110 
2111 /*
2112  * Utility routine to find a string type attribute, allocate it
2113  * and return the value to the caller.  This simplifies the
2114  * operation by doing both "kmf_get_attr" calls and avoids
2115  * duplicating this block of code in lots of places.
2116  */
2117 KMF_RETURN
2118 kmf_get_string_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attrlist,
2119 	int numattrs, char **outstr)
2120 {
2121 	KMF_RETURN rv;
2122 	uint32_t len;
2123 
2124 	if (outstr == NULL)
2125 		return (KMF_ERR_BAD_PARAMETER);
2126 
2127 	if ((rv = kmf_get_attr(type, attrlist, numattrs, NULL, &len)) ==
2128 	    KMF_OK) {
2129 		*outstr = malloc(len + 1);
2130 		if ((*outstr) == NULL)
2131 			return (KMF_ERR_MEMORY);
2132 		(void) memset((*outstr), 0, len + 1);
2133 		rv = kmf_get_attr(type, attrlist, numattrs, (*outstr), &len);
2134 		if (rv != KMF_OK) {
2135 			free(*outstr);
2136 			*outstr = NULL;
2137 		}
2138 	}
2139 
2140 	return (rv);
2141 }
2142 
2143 /*
2144  * This API is used by elfsign. We must keep it in old API form.
2145  */
2146 KMF_RETURN
2147 KMF_ConfigureKeystore(KMF_HANDLE_T handle, KMF_CONFIG_PARAMS *params)
2148 {
2149 
2150 	KMF_ATTRIBUTE attlist[32];
2151 	int i = 0;
2152 
2153 	if (params == NULL)
2154 		return (KMF_ERR_BAD_PARAMETER);
2155 
2156 	kmf_set_attr_at_index(attlist, i,
2157 	    KMF_KEYSTORE_TYPE_ATTR, &params->kstype, sizeof (params->kstype));
2158 	i++;
2159 
2160 	if (params->kstype == KMF_KEYSTORE_NSS) {
2161 		if (params->nssconfig.configdir != NULL) {
2162 			kmf_set_attr_at_index(attlist, i,
2163 			    KMF_DIRPATH_ATTR,
2164 			    params->nssconfig.configdir,
2165 			    strlen(params->nssconfig.configdir));
2166 			i++;
2167 		}
2168 		if (params->nssconfig.certPrefix != NULL) {
2169 			kmf_set_attr_at_index(attlist, i,
2170 			    KMF_CERTPREFIX_ATTR,
2171 			    params->nssconfig.certPrefix,
2172 			    strlen(params->nssconfig.certPrefix));
2173 			i++;
2174 		}
2175 		if (params->nssconfig.keyPrefix != NULL) {
2176 			kmf_set_attr_at_index(attlist, i,
2177 			    KMF_KEYPREFIX_ATTR,
2178 			    params->nssconfig.keyPrefix,
2179 			    strlen(params->nssconfig.keyPrefix));
2180 			i++;
2181 		}
2182 		if (params->nssconfig.secModName != NULL) {
2183 			kmf_set_attr_at_index(attlist, i,
2184 			    KMF_SECMODNAME_ATTR,
2185 			    params->nssconfig.secModName,
2186 			    strlen(params->nssconfig.secModName));
2187 			i++;
2188 		}
2189 	} else if (params->kstype == KMF_KEYSTORE_PK11TOKEN) {
2190 		if (params->pkcs11config.label != NULL) {
2191 			kmf_set_attr_at_index(attlist, i,
2192 			    KMF_TOKEN_LABEL_ATTR,
2193 			    params->pkcs11config.label,
2194 			    strlen(params->pkcs11config.label));
2195 			i++;
2196 		}
2197 		kmf_set_attr_at_index(attlist, i,
2198 		    KMF_READONLY_ATTR,
2199 		    &params->pkcs11config.readonly,
2200 		    sizeof (params->pkcs11config.readonly));
2201 		i++;
2202 	}
2203 
2204 	return (kmf_configure_keystore(handle, i, attlist));
2205 }
2206 
2207 /*
2208  * This API is used by elfsign. We must keep it in old API form.
2209  */
2210 KMF_RETURN
2211 KMF_Initialize(KMF_HANDLE_T *outhandle, char *policyfile, char *policyname)
2212 {
2213 	return (kmf_initialize(outhandle, policyfile, policyname));
2214 }
2215 
2216 /*
2217  * This API is used by elfsign. We must keep it in old API form.
2218  */
2219 KMF_RETURN
2220 KMF_Finalize(KMF_HANDLE_T handle)
2221 {
2222 	return (kmf_finalize(handle));
2223 }
2224 
2225 /*
2226  * This API is used by elfsign. We must keep it in old API form.
2227  */
2228 KMF_RETURN
2229 KMF_GetKMFErrorString(KMF_RETURN errcode, char **errmsg)
2230 {
2231 	return (kmf_get_kmf_error_str(errcode, errmsg));
2232 }
2233 
2234 /*
2235  * This API is used by elfsign. We must keep it in old API form.
2236  */
2237 KMF_RETURN
2238 KMF_ReadInputFile(KMF_HANDLE_T handle, char *filename,  KMF_DATA *pdata)
2239 {
2240 	return (kmf_read_input_file(handle, filename, pdata));
2241 }
2242 
2243 
2244 /*
2245  * This API is used by elfsign. We must keep it in old API form.
2246  */
2247 void
2248 KMF_FreeKMFCert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
2249 {
2250 	kmf_free_kmf_cert(handle, kmf_cert);
2251 }
2252 
2253 /*
2254  * This API is used by elfsign. We must keep it in old API form.
2255  */
2256 void
2257 KMF_FreeData(KMF_DATA *datablock)
2258 {
2259 	kmf_free_data(datablock);
2260 }
2261 
2262 /*
2263  * This API is used by elfsign. We must keep it in old API form.
2264  */
2265 void
2266 KMF_FreeKMFKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key)
2267 {
2268 	kmf_free_kmf_key(handle, key);
2269 }
2270 
2271 /*
2272  * This API is used by elfsign. We must keep it in old API form.
2273  */
2274 void
2275 KMF_FreeSignedCSR(KMF_CSR_DATA *csr)
2276 {
2277 	kmf_free_signed_csr(csr);
2278 }
2279