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