xref: /titanic_44/usr/src/lib/libkmf/libkmf/common/generalop.c (revision 2a9459bdd821c1cf59590a7a9069ac9c591e8a6b)
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 	if (key->label) {
1229 		free(key->label);
1230 		key->label = NULL;
1231 	}
1232 	kmf_free_data(&key->id);
1233 }
1234 
1235 void
1236 kmf_free_raw_sym_key(KMF_RAW_SYM_KEY *key)
1237 {
1238 	if (key == NULL)
1239 		return;
1240 	kmf_free_bigint(&key->keydata);
1241 	free(key);
1242 }
1243 
1244 /*
1245  * This function frees the space allocated for the name portion of a
1246  * KMF_CRL_DIST_POINT.
1247  */
1248 void
1249 free_dp_name(KMF_CRL_DIST_POINT *dp)
1250 {
1251 	KMF_GENERALNAMES *fullname;
1252 	KMF_DATA *urldata;
1253 	int i;
1254 
1255 	if (dp == NULL)
1256 		return;
1257 
1258 	/* For phase 1, we only need to free the fullname space. */
1259 	fullname = &(dp->name.full_name);
1260 	if (fullname->number == 0)
1261 		return;
1262 
1263 	for (i = 0; i < fullname->number; i++) {
1264 		urldata = &(fullname->namelist[fullname->number - 1].name);
1265 		kmf_free_data(urldata);
1266 	}
1267 
1268 	free(fullname->namelist);
1269 }
1270 
1271 /*
1272  * This function frees the space allocated for a KMF_CRL_DIST_POINT.
1273  */
1274 void
1275 free_dp(KMF_CRL_DIST_POINT *dp)
1276 {
1277 	if (dp == NULL)
1278 		return;
1279 
1280 	free_dp_name(dp);
1281 	kmf_free_data(&(dp->reasons));
1282 	/* Need not to free crl_issuer space at phase 1 */
1283 }
1284 
1285 /*
1286  * This function frees space for a KMF_X509EXT_CRLDISTPOINTS internally.
1287  */
1288 void
1289 kmf_free_crl_dist_pts(KMF_X509EXT_CRLDISTPOINTS *crl_dps)
1290 {
1291 	int i;
1292 
1293 	if (crl_dps == NULL)
1294 		return;
1295 
1296 	for (i = 0; i < crl_dps->number; i++)
1297 		free_dp(&(crl_dps->dplist[i]));
1298 
1299 	free(crl_dps->dplist);
1300 }
1301 
1302 KMF_RETURN
1303 kmf_create_ocsp_request(KMF_HANDLE_T handle,
1304 	int	num_args,
1305 	KMF_ATTRIBUTE	*attrlist)
1306 {
1307 	KMF_RETURN ret = KMF_OK;
1308 	KMF_PLUGIN *plugin;
1309 	KMF_RETURN (*createReqFn)(void *, int num_args,
1310 	    KMF_ATTRIBUTE *attrlist);
1311 
1312 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
1313 		{KMF_OCSP_REQUEST_FILENAME_ATTR, FALSE, 1, 0},
1314 		{KMF_USER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1315 			sizeof (KMF_DATA)},
1316 		{KMF_ISSUER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1317 			sizeof (KMF_DATA)},
1318 	};
1319 
1320 	int num_req_attrs = sizeof (required_attrs) /
1321 	    sizeof (KMF_ATTRIBUTE_TESTER);
1322 
1323 	if (handle == NULL)
1324 		return (KMF_ERR_BAD_PARAMETER);
1325 
1326 	CLEAR_ERROR(handle, ret);
1327 
1328 	ret = test_attributes(num_req_attrs, required_attrs,
1329 	    0, NULL, num_args, attrlist);
1330 
1331 	if (ret != KMF_OK)
1332 		return (ret);
1333 
1334 	/*
1335 	 * This framework function is actually implemented in the openssl
1336 	 * plugin library, so we find the function address and call it.
1337 	 */
1338 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
1339 	if (plugin == NULL || plugin->dldesc == NULL) {
1340 		return (KMF_ERR_PLUGIN_NOTFOUND);
1341 	}
1342 
1343 	createReqFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
1344 	    "OpenSSL_CreateOCSPRequest");
1345 	if (createReqFn == NULL) {
1346 		return (KMF_ERR_FUNCTION_NOT_FOUND);
1347 	}
1348 
1349 	return (createReqFn(handle, num_args, attrlist));
1350 
1351 }
1352 
1353 KMF_RETURN
1354 kmf_get_ocsp_status_for_cert(KMF_HANDLE_T handle,
1355 	int	num_args,
1356 	KMF_ATTRIBUTE	*attrlist)
1357 {
1358 	KMF_RETURN ret = KMF_OK;
1359 	KMF_PLUGIN *plugin;
1360 	KMF_RETURN (*getCertStatusFn)(void *, int num_args,
1361 	    KMF_ATTRIBUTE *attrlist);
1362 
1363 	KMF_ATTRIBUTE_TESTER required_attrs[] = {
1364 		{KMF_USER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1365 			sizeof (KMF_DATA)},
1366 		{KMF_ISSUER_CERT_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1367 			sizeof (KMF_DATA)},
1368 		{KMF_OCSP_RESPONSE_DATA_ATTR, FALSE, sizeof (KMF_DATA),
1369 			sizeof (KMF_DATA)},
1370 		{KMF_OCSP_RESPONSE_STATUS_ATTR, FALSE, sizeof (int),
1371 			sizeof (uint32_t)},
1372 		{KMF_OCSP_RESPONSE_REASON_ATTR, FALSE, sizeof (int),
1373 			sizeof (uint32_t)},
1374 		{KMF_OCSP_RESPONSE_CERT_STATUS_ATTR, FALSE, sizeof (int),
1375 			sizeof (uint32_t)},
1376 	};
1377 
1378 	int num_req_attrs = sizeof (required_attrs) /
1379 	    sizeof (KMF_ATTRIBUTE_TESTER);
1380 
1381 	if (handle == NULL)
1382 		return (KMF_ERR_BAD_PARAMETER);
1383 
1384 	CLEAR_ERROR(handle, ret);
1385 
1386 	ret = test_attributes(num_req_attrs, required_attrs,
1387 	    0, NULL, num_args, attrlist);
1388 
1389 	if (ret != KMF_OK)
1390 		return (ret);
1391 
1392 	/*
1393 	 * This framework function is actually implemented in the openssl
1394 	 * plugin library, so we find the function address and call it.
1395 	 */
1396 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
1397 	if (plugin == NULL || plugin->dldesc == NULL) {
1398 		return (KMF_ERR_INTERNAL);
1399 	}
1400 
1401 	getCertStatusFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
1402 	    "OpenSSL_GetOCSPStatusForCert");
1403 	if (getCertStatusFn == NULL) {
1404 		return (KMF_ERR_INTERNAL);
1405 	}
1406 
1407 	return (getCertStatusFn(handle, num_args, attrlist));
1408 
1409 }
1410 
1411 KMF_RETURN
1412 kmf_string_to_oid(char *oidstring, KMF_OID *oid)
1413 {
1414 	KMF_RETURN rv = KMF_OK;
1415 	char *cp, *bp, *startp;
1416 	int numbuf;
1417 	int onumbuf;
1418 	int nbytes, index;
1419 	int len;
1420 	unsigned char *op;
1421 
1422 	if (oidstring == NULL || oid == NULL)
1423 		return (KMF_ERR_BAD_PARAMETER);
1424 
1425 	len = strlen(oidstring);
1426 
1427 	bp = oidstring;
1428 	cp = bp;
1429 	/* Skip over leading space */
1430 	while ((bp < &cp[len]) && isspace(*bp))
1431 		bp++;
1432 
1433 	startp = bp;
1434 	nbytes = 0;
1435 
1436 	/*
1437 	 * The first two numbers are chewed up by the first octet.
1438 	 */
1439 	if (sscanf(bp, "%d", &numbuf) != 1)
1440 		return (KMF_ERR_BAD_PARAMETER);
1441 	while ((bp < &cp[len]) && isdigit(*bp))
1442 		bp++;
1443 	while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
1444 		bp++;
1445 	if (sscanf(bp, "%d", &numbuf) != 1)
1446 		return (KMF_ERR_BAD_PARAMETER);
1447 	while ((bp < &cp[len]) && isdigit(*bp))
1448 		bp++;
1449 	while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
1450 		bp++;
1451 	nbytes++;
1452 
1453 	while (isdigit(*bp)) {
1454 		if (sscanf(bp, "%d", &numbuf) != 1)
1455 			return (KMF_ERR_BAD_PARAMETER);
1456 		while (numbuf) {
1457 			nbytes++;
1458 			numbuf >>= 7;
1459 		}
1460 		while ((bp < &cp[len]) && isdigit(*bp))
1461 			bp++;
1462 		while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
1463 			bp++;
1464 	}
1465 
1466 	oid->Length = nbytes;
1467 	oid->Data = malloc(oid->Length);
1468 	if (oid->Data == NULL) {
1469 		return (KMF_ERR_MEMORY);
1470 	}
1471 	(void) memset(oid->Data, 0, oid->Length);
1472 
1473 	op = oid->Data;
1474 
1475 	bp = startp;
1476 	(void) sscanf(bp, "%d", &numbuf);
1477 
1478 	while (isdigit(*bp)) bp++;
1479 	while (isspace(*bp) || *bp == '.') bp++;
1480 
1481 	onumbuf = 40 * numbuf;
1482 	(void) sscanf(bp, "%d", &numbuf);
1483 	onumbuf += numbuf;
1484 	*op = (unsigned char) onumbuf;
1485 	op++;
1486 
1487 	while (isdigit(*bp)) bp++;
1488 	while (isspace(*bp) || *bp == '.') bp++;
1489 	while (isdigit(*bp)) {
1490 		(void) sscanf(bp, "%d", &numbuf);
1491 		nbytes = 0;
1492 		/* Have to fill in the bytes msb-first */
1493 		onumbuf = numbuf;
1494 		while (numbuf) {
1495 			nbytes++;
1496 			numbuf >>= 7;
1497 		}
1498 		numbuf = onumbuf;
1499 		op += nbytes;
1500 		index = -1;
1501 		while (numbuf) {
1502 			op[index] = (unsigned char)numbuf & 0x7f;
1503 			if (index != -1)
1504 				op[index] |= 0x80;
1505 			index--;
1506 			numbuf >>= 7;
1507 		}
1508 		while (isdigit(*bp)) bp++;
1509 		while (isspace(*bp) || *bp == '.') bp++;
1510 	}
1511 
1512 	return (rv);
1513 }
1514 
1515 static KMF_RETURN
1516 encode_rid(char *name, KMF_DATA *derdata)
1517 {
1518 	KMF_RETURN rv = KMF_OK;
1519 
1520 	if (name == NULL || derdata == NULL)
1521 		return (KMF_ERR_BAD_PARAMETER);
1522 
1523 	rv = kmf_string_to_oid(name, (KMF_OID *)derdata);
1524 
1525 	return (rv);
1526 }
1527 
1528 static KMF_RETURN
1529 encode_ipaddr(char *name, KMF_DATA *derdata)
1530 {
1531 	KMF_RETURN rv = KMF_OK;
1532 	size_t len;
1533 	in_addr_t v4;
1534 	in6_addr_t v6;
1535 	uint8_t *ptr;
1536 
1537 	if (name == NULL || derdata == NULL)
1538 		return (KMF_ERR_BAD_PARAMETER);
1539 
1540 	v4 = inet_addr(name);
1541 	if (v4 == (in_addr_t)-1) {
1542 		ptr = (uint8_t *)&v6;
1543 		if (inet_pton(AF_INET6, name, ptr) != 1)
1544 			return (KMF_ERR_ENCODING);
1545 		len = sizeof (v6);
1546 	} else {
1547 		ptr = (uint8_t *)&v4;
1548 		len = sizeof (v4);
1549 	}
1550 
1551 	derdata->Data = malloc(len);
1552 	if (derdata->Data == NULL)
1553 		return (KMF_ERR_MEMORY);
1554 	(void) memcpy(derdata->Data, ptr, len);
1555 	derdata->Length = len;
1556 
1557 	return (rv);
1558 }
1559 
1560 static KMF_RETURN
1561 verify_uri_format(char *uristring)
1562 {
1563 	KMF_RETURN ret = KMF_OK;
1564 	xmlURIPtr   uriptr = NULL;
1565 
1566 	/* Parse the URI string; get the hostname and port */
1567 	uriptr = xmlParseURI(uristring);
1568 	if (uriptr == NULL) {
1569 		ret = KMF_ERR_BAD_URI;
1570 		goto out;
1571 	}
1572 
1573 	if (uriptr->scheme == NULL || !strlen(uriptr->scheme)) {
1574 		ret = KMF_ERR_BAD_URI;
1575 		goto out;
1576 	}
1577 
1578 	if (uriptr->server == NULL || !strlen(uriptr->server)) {
1579 		ret = KMF_ERR_BAD_URI;
1580 		goto out;
1581 	}
1582 out:
1583 	if (uriptr != NULL)
1584 		xmlFreeURI(uriptr);
1585 	return (ret);
1586 }
1587 
1588 static KMF_RETURN
1589 encode_altname(char *namedata,
1590 	KMF_GENERALNAMECHOICES nametype, KMF_DATA *encodedname)
1591 {
1592 	KMF_RETURN ret = KMF_OK;
1593 	KMF_X509_NAME dnname;
1594 	uchar_t tagval;
1595 	BerElement *asn1 = NULL;
1596 	BerValue *extdata;
1597 
1598 	if (namedata == NULL || encodedname == NULL)
1599 		return (KMF_ERR_BAD_PARAMETER);
1600 
1601 	/*
1602 	 * Encode the namedata according to rules in RFC 3280 for GeneralName.
1603 	 * The input "namedata" is assumed to be an ASCII string representation
1604 	 * of the AltName, we need to convert it to correct ASN.1 here before
1605 	 * adding it to the cert.
1606 	 */
1607 	switch (nametype) {
1608 		case GENNAME_RFC822NAME: /* rfc 822 */
1609 			/* IA5String, no encoding needed */
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_DNSNAME: /* rfc 1034 */
1617 			encodedname->Data = (uchar_t *)strdup(namedata);
1618 			if (encodedname->Data == NULL)
1619 				return (KMF_ERR_MEMORY);
1620 			encodedname->Length = strlen(namedata);
1621 			tagval = (0x80 | nametype);
1622 			break;
1623 		case GENNAME_URI: /* rfc 1738 */
1624 			ret = verify_uri_format(namedata);
1625 			if (ret != KMF_OK)
1626 				return (ret);
1627 			/* IA5String, no encoding needed */
1628 			encodedname->Data = (uchar_t *)strdup(namedata);
1629 			if (encodedname->Data == NULL)
1630 				return (KMF_ERR_MEMORY);
1631 			encodedname->Length = strlen(namedata);
1632 			tagval = (0x80 | nametype);
1633 			break;
1634 		case GENNAME_IPADDRESS:
1635 			ret =  encode_ipaddr(namedata, encodedname);
1636 			tagval = (0x80 | nametype);
1637 			break;
1638 		case GENNAME_REGISTEREDID:
1639 			ret = encode_rid(namedata, encodedname);
1640 			tagval = (0x80 | nametype);
1641 			break;
1642 		case GENNAME_DIRECTORYNAME:
1643 			ret = kmf_dn_parser(namedata, &dnname);
1644 			if (ret == KMF_OK) {
1645 				ret = DerEncodeName(&dnname, encodedname);
1646 			}
1647 			(void) kmf_free_dn(&dnname);
1648 			tagval = (0xA0 | nametype);
1649 			break;
1650 		default:
1651 			/* unsupported */
1652 			return (KMF_ERR_BAD_PARAMETER);
1653 
1654 	}
1655 	if (ret != KMF_OK) {
1656 		kmf_free_data(encodedname);
1657 		return (ret);
1658 	}
1659 
1660 	if ((asn1 = kmfder_alloc()) == NULL)
1661 		return (KMF_ERR_MEMORY);
1662 
1663 	if (kmfber_printf(asn1, "Tl", tagval, encodedname->Length) == -1)
1664 		goto cleanup;
1665 
1666 	if (kmfber_write(asn1, (char *)encodedname->Data,
1667 	    encodedname->Length, 0) == -1) {
1668 		ret = KMF_ERR_ENCODING;
1669 		goto cleanup;
1670 	}
1671 	if (kmfber_flatten(asn1, &extdata) == -1) {
1672 		ret = KMF_ERR_ENCODING;
1673 		goto cleanup;
1674 	}
1675 
1676 	kmf_free_data(encodedname);
1677 	encodedname->Data = (uchar_t *)extdata->bv_val;
1678 	encodedname->Length = extdata->bv_len;
1679 
1680 	free(extdata);
1681 
1682 cleanup:
1683 	if (asn1)
1684 		kmfber_free(asn1, 1);
1685 
1686 	if (ret != KMF_OK)
1687 		kmf_free_data(encodedname);
1688 
1689 	return (ret);
1690 }
1691 
1692 KMF_X509_EXTENSION *
1693 FindExtn(KMF_X509_EXTENSIONS *exts, KMF_OID *oid)
1694 {
1695 	KMF_X509_EXTENSION *foundextn = NULL;
1696 	int i;
1697 
1698 	if (exts == NULL || oid == NULL)
1699 		return (NULL);
1700 
1701 	for (i = 0; i < exts->numberOfExtensions; i++) {
1702 		if (IsEqualOid(oid, &exts->extensions[i].extnId))  {
1703 			foundextn = &exts->extensions[i];
1704 			break;
1705 		}
1706 	}
1707 	return (foundextn);
1708 }
1709 
1710 KMF_RETURN
1711 GetSequenceContents(char *data, size_t len,
1712 	char **contents, size_t *outlen)
1713 {
1714 	KMF_RETURN ret = KMF_OK;
1715 	BerElement *exasn1 = NULL;
1716 	BerValue oldextn;
1717 	int tag;
1718 	size_t oldsize;
1719 	char *olddata = NULL;
1720 
1721 	if (data == NULL || contents == NULL || outlen == NULL)
1722 		return (KMF_ERR_BAD_PARAMETER);
1723 
1724 	/*
1725 	 * Decode the sequence of general names
1726 	 */
1727 	oldextn.bv_val = data;
1728 	oldextn.bv_len = len;
1729 
1730 	if ((exasn1 = kmfder_init(&oldextn)) == NULL) {
1731 		ret = KMF_ERR_MEMORY;
1732 		goto out;
1733 	}
1734 
1735 	/*
1736 	 * Unwrap the sequence to find the size of the block
1737 	 * of GeneralName items in the set.
1738 	 *
1739 	 * Peek at the tag and length ("tl"),
1740 	 * then consume them ("{").
1741 	 */
1742 	if (kmfber_scanf(exasn1, "tl{", &tag, &oldsize) == KMFBER_DEFAULT ||
1743 	    oldsize == 0) {
1744 		ret = KMF_ERR_ENCODING;
1745 		goto out;
1746 	}
1747 
1748 	olddata = malloc(oldsize);
1749 	if (olddata == NULL) {
1750 		ret = KMF_ERR_MEMORY;
1751 		goto out;
1752 	}
1753 	(void) memset(olddata, 0, oldsize);
1754 	/*
1755 	 * Read the entire blob of GeneralNames, we don't
1756 	 * need to interpret them now.
1757 	 */
1758 	if (kmfber_read(exasn1, olddata, oldsize) != oldsize) {
1759 		ret = KMF_ERR_ENCODING;
1760 		goto out;
1761 	}
1762 out:
1763 	if (exasn1 != NULL)
1764 		kmfber_free(exasn1, 1);
1765 
1766 	if (ret != KMF_OK) {
1767 		*contents = NULL;
1768 		*outlen = 0;
1769 		if (olddata != NULL)
1770 			free(olddata);
1771 	} else {
1772 		*contents = olddata;
1773 		*outlen = oldsize;
1774 	}
1775 	return (ret);
1776 }
1777 
1778 KMF_RETURN
1779 add_an_extension(KMF_X509_EXTENSIONS *exts, KMF_X509_EXTENSION *newextn)
1780 {
1781 	KMF_RETURN ret = KMF_OK;
1782 	KMF_X509_EXTENSION *extlist;
1783 
1784 	if (exts == NULL || newextn == NULL)
1785 		return (KMF_ERR_BAD_PARAMETER);
1786 
1787 	extlist = malloc(sizeof (KMF_X509_EXTENSION) *
1788 	    (exts->numberOfExtensions + 1));
1789 	if (extlist == NULL)
1790 		return (KMF_ERR_MEMORY);
1791 
1792 	(void) memcpy(extlist, exts->extensions,
1793 	    exts->numberOfExtensions * sizeof (KMF_X509_EXTENSION));
1794 
1795 	(void) memcpy(&extlist[exts->numberOfExtensions], newextn,
1796 	    sizeof (KMF_X509_EXTENSION));
1797 
1798 	free(exts->extensions);
1799 	exts->numberOfExtensions++;
1800 	exts->extensions = extlist;
1801 
1802 	return (ret);
1803 }
1804 
1805 KMF_RETURN
1806 kmf_set_altname(KMF_X509_EXTENSIONS *extensions,
1807 	KMF_OID *oid,
1808 	int critical,
1809 	KMF_GENERALNAMECHOICES nametype,
1810 	char *namedata)
1811 {
1812 	KMF_RETURN ret = KMF_OK;
1813 	KMF_X509_EXTENSION subjAltName;
1814 	KMF_DATA dername = { NULL, 0 };
1815 	BerElement *asn1 = NULL;
1816 	BerValue *extdata;
1817 	char *olddata = NULL;
1818 	KMF_X509_EXTENSION *foundextn = NULL;
1819 	size_t	oldsize = 0;
1820 
1821 	if (extensions == NULL || oid == NULL || namedata == NULL)
1822 		return (KMF_ERR_BAD_PARAMETER);
1823 
1824 	ret = encode_altname(namedata, nametype, &dername);
1825 
1826 	if (ret != KMF_OK)
1827 		return (ret);
1828 
1829 	(void) memset(&subjAltName, 0, sizeof (subjAltName));
1830 
1831 	ret = copy_data(&subjAltName.extnId, oid);
1832 	if (ret != KMF_OK)
1833 		goto out;
1834 	/*
1835 	 * Check to see if this cert already has a subjectAltName.
1836 	 */
1837 	foundextn = FindExtn(extensions, oid);
1838 
1839 	if (foundextn != NULL) {
1840 		ret = GetSequenceContents(
1841 		    (char *)foundextn->BERvalue.Data,
1842 		    foundextn->BERvalue.Length,
1843 		    &olddata, &oldsize);
1844 		if (ret != KMF_OK)
1845 			goto out;
1846 	}
1847 
1848 	/*
1849 	 * Assume (!!) that the namedata given is already properly encoded.
1850 	 */
1851 	if ((asn1 = kmfder_alloc()) == NULL)
1852 		return (KMF_ERR_MEMORY);
1853 
1854 	if (kmfber_printf(asn1, "{") == -1) {
1855 		ret = KMF_ERR_ENCODING;
1856 		goto out;
1857 	}
1858 
1859 	/* Write the old extension data first */
1860 	if (olddata != NULL && oldsize > 0) {
1861 		if (kmfber_write(asn1, olddata, oldsize, 0) == -1) {
1862 			ret = KMF_ERR_ENCODING;
1863 			goto out;
1864 		}
1865 	}
1866 
1867 	/* Now add the new name to the list */
1868 	if (kmfber_write(asn1, (char *)dername.Data, dername.Length, 0) == -1) {
1869 		ret = KMF_ERR_ENCODING;
1870 		goto out;
1871 	}
1872 
1873 	/* Now close the sequence */
1874 	if (kmfber_printf(asn1, "}") == -1) {
1875 		ret = KMF_ERR_ENCODING;
1876 		goto out;
1877 	}
1878 	if (kmfber_flatten(asn1, &extdata) == -1) {
1879 		ret = KMF_ERR_ENCODING;
1880 		goto out;
1881 	}
1882 
1883 	/*
1884 	 * If we are just adding to an existing list of altNames,
1885 	 * just replace the BER data associated with the found extension.
1886 	 */
1887 	if (foundextn != NULL) {
1888 		free(foundextn->BERvalue.Data);
1889 		foundextn->critical = critical;
1890 		foundextn->BERvalue.Data = (uchar_t *)extdata->bv_val;
1891 		foundextn->BERvalue.Length = extdata->bv_len;
1892 	} else {
1893 		subjAltName.critical = critical;
1894 		subjAltName.format = KMF_X509_DATAFORMAT_ENCODED;
1895 		subjAltName.BERvalue.Data = (uchar_t *)extdata->bv_val;
1896 		subjAltName.BERvalue.Length = extdata->bv_len;
1897 		ret = add_an_extension(extensions, &subjAltName);
1898 		if (ret != KMF_OK)
1899 			free(subjAltName.BERvalue.Data);
1900 	}
1901 
1902 	free(extdata);
1903 out:
1904 	if (olddata != NULL)
1905 		free(olddata);
1906 
1907 	kmf_free_data(&dername);
1908 	if (ret != KMF_OK)
1909 		kmf_free_data(&subjAltName.extnId);
1910 	if (asn1 != NULL)
1911 		kmfber_free(asn1, 1);
1912 	return (ret);
1913 }
1914 
1915 /*
1916  * Search a list of attributes for one that matches the given type.
1917  * Return a pointer into the attribute list.  This does not
1918  * return a copy of the value, it returns a reference into the
1919  * given list.
1920  */
1921 int
1922 kmf_find_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist, int numattrs)
1923 {
1924 	int i;
1925 	for (i = 0; i < numattrs; i++) {
1926 		if (attlist[i].type == type)
1927 			return (i);
1928 	}
1929 	return (-1);
1930 }
1931 
1932 /*
1933  * Verify that a given attribute is consistent with the
1934  * "test" attribute.
1935  */
1936 static KMF_RETURN
1937 verify_attribute(KMF_ATTRIBUTE *givenattr,
1938 	KMF_ATTRIBUTE_TESTER *testattr)
1939 {
1940 	/* A NULL pValue was found where one is required */
1941 	if (testattr->null_value_ok == FALSE &&
1942 	    givenattr->pValue == NULL)
1943 		return (KMF_ERR_BAD_PARAMETER);
1944 
1945 	/* If the given valueLen is too small, return error */
1946 	if (givenattr->pValue != NULL &&
1947 	    testattr->minlen > 0 &&
1948 	    (givenattr->valueLen < testattr->minlen))
1949 		return (KMF_ERR_BAD_PARAMETER);
1950 
1951 	/* If the given valueLen is too big, return error */
1952 	if (givenattr->pValue != NULL &&
1953 	    testattr->maxlen > 0 &&
1954 	    (givenattr->valueLen > testattr->maxlen))
1955 		return (KMF_ERR_BAD_PARAMETER);
1956 
1957 	return (KMF_OK);
1958 }
1959 
1960 /*
1961  * Given a set of required attribute tests and optional
1962  * attributes, make sure that the actual attributes
1963  * being tested (attrlist below) are allowed and are
1964  * properly specified.
1965  */
1966 KMF_RETURN
1967 test_attributes(int reqnum, KMF_ATTRIBUTE_TESTER *reqattrs,
1968 	int optnum, KMF_ATTRIBUTE_TESTER *optattrs,
1969 	int numattrs, KMF_ATTRIBUTE *attrlist)
1970 {
1971 	KMF_RETURN ret = KMF_OK;
1972 	int i, idx;
1973 
1974 	/*
1975 	 * If the caller didn't supply enough attributes,
1976 	 * return an error.
1977 	 */
1978 	if (numattrs < reqnum || attrlist == NULL)
1979 		return (KMF_ERR_BAD_PARAMETER);
1980 
1981 	/*
1982 	 * Make sure all required attrs are present and
1983 	 * correct.
1984 	 */
1985 	for (i = 0; i < reqnum && ret == KMF_OK; i++) {
1986 		idx = kmf_find_attr(reqattrs[i].type, attrlist, numattrs);
1987 		/* If a required attr is not found, return error */
1988 		if (idx == -1) {
1989 			return (KMF_ERR_BAD_PARAMETER);
1990 		}
1991 
1992 		ret = verify_attribute(&attrlist[idx], &reqattrs[i]);
1993 	}
1994 	/*
1995 	 * Now test the optional parameters.
1996 	 */
1997 	for (i = 0; i < optnum && ret == KMF_OK; i++) {
1998 		idx = kmf_find_attr(optattrs[i].type, attrlist, numattrs);
1999 		/* If a optional attr is not found, continue. */
2000 		if (idx == -1) {
2001 			continue;
2002 		}
2003 
2004 		ret = verify_attribute(&attrlist[idx], &optattrs[i]);
2005 	}
2006 
2007 	return (ret);
2008 }
2009 
2010 /*
2011  * Given an already allocated attribute list, insert
2012  * the given attribute information at a specific index
2013  * in the list.
2014  */
2015 void
2016 kmf_set_attr_at_index(KMF_ATTRIBUTE *attlist, int index,
2017 	KMF_ATTR_TYPE type,  void *pValue, uint32_t len)
2018 {
2019 	if (attlist == NULL)
2020 		return;
2021 
2022 	attlist[index].type = type;
2023 	attlist[index].pValue = pValue;
2024 	attlist[index].valueLen = len;
2025 }
2026 
2027 /*
2028  * Find an attribute matching a particular type and set
2029  * the pValue and length fields to the given values.
2030  */
2031 KMF_RETURN
2032 kmf_set_attr(KMF_ATTRIBUTE *attlist, int numattr,
2033 	KMF_ATTR_TYPE type,  void *pValue, uint32_t len)
2034 {
2035 	int idx;
2036 	if (attlist == NULL)
2037 		return (KMF_ERR_BAD_PARAMETER);
2038 
2039 	idx = kmf_find_attr(type, attlist, numattr);
2040 	if (idx == -1)
2041 		return (KMF_ERR_ATTR_NOT_FOUND);
2042 
2043 	attlist[idx].type = type;
2044 	/* Assumes the attribute pValue can hold the result */
2045 	if (attlist[idx].pValue != NULL) {
2046 		if (attlist[idx].valueLen >= len)
2047 			(void) memcpy(attlist[idx].pValue, pValue, len);
2048 		else
2049 			return (KMF_ERR_BUFFER_SIZE);
2050 	}
2051 	attlist[idx].valueLen = len;
2052 	return (KMF_OK);
2053 }
2054 
2055 /*
2056  * Find a particular attribute in a list and return
2057  * a pointer to its value.
2058  */
2059 void *
2060 kmf_get_attr_ptr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist,
2061 	int numattrs)
2062 {
2063 	int i;
2064 
2065 	i = kmf_find_attr(type, attlist, numattrs);
2066 	if (i == -1)
2067 		return (NULL);
2068 
2069 	return (attlist[i].pValue);
2070 }
2071 
2072 /*
2073  * Find a particular attribute in a list and return
2074  * the value and length values.  Value and length
2075  * may be NULL if the caller doesn't want their values
2076  * to be filled in.
2077  */
2078 KMF_RETURN
2079 kmf_get_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attlist,
2080 	int numattrs, void *outValue, uint32_t *outlen)
2081 {
2082 	int i;
2083 	uint32_t len = 0;
2084 	uint32_t *lenptr = outlen;
2085 
2086 	if (lenptr == NULL)
2087 		lenptr = &len;
2088 
2089 	i = kmf_find_attr(type, attlist, numattrs);
2090 	if (i == -1)
2091 		return (KMF_ERR_ATTR_NOT_FOUND);
2092 
2093 	/* This assumes that the ptr passed in is pre-allocated space */
2094 	if (attlist[i].pValue != NULL && outValue != NULL) {
2095 		/*
2096 		 * If the caller did not specify a length,
2097 		 * assume "outValue" is big enough.
2098 		 */
2099 		if (outlen != NULL) {
2100 			if (*outlen >= attlist[i].valueLen)
2101 				(void) memcpy(outValue, attlist[i].pValue,
2102 				    attlist[i].valueLen);
2103 			else
2104 				return (KMF_ERR_BUFFER_SIZE);
2105 		} else {
2106 			(void) memcpy(outValue, attlist[i].pValue,
2107 			    attlist[i].valueLen);
2108 		}
2109 	}
2110 
2111 	if (outlen != NULL)
2112 		*outlen = attlist[i].valueLen;
2113 	return (KMF_OK);
2114 }
2115 
2116 /*
2117  * Utility routine to find a string type attribute, allocate it
2118  * and return the value to the caller.  This simplifies the
2119  * operation by doing both "kmf_get_attr" calls and avoids
2120  * duplicating this block of code in lots of places.
2121  */
2122 KMF_RETURN
2123 kmf_get_string_attr(KMF_ATTR_TYPE type, KMF_ATTRIBUTE *attrlist,
2124 	int numattrs, char **outstr)
2125 {
2126 	KMF_RETURN rv;
2127 	uint32_t len;
2128 
2129 	if (outstr == NULL)
2130 		return (KMF_ERR_BAD_PARAMETER);
2131 
2132 	if ((rv = kmf_get_attr(type, attrlist, numattrs, NULL, &len)) ==
2133 	    KMF_OK) {
2134 		*outstr = malloc(len + 1);
2135 		if ((*outstr) == NULL)
2136 			return (KMF_ERR_MEMORY);
2137 		(void) memset((*outstr), 0, len + 1);
2138 		rv = kmf_get_attr(type, attrlist, numattrs, (*outstr), &len);
2139 		if (rv != KMF_OK) {
2140 			free(*outstr);
2141 			*outstr = NULL;
2142 		}
2143 	}
2144 
2145 	return (rv);
2146 }
2147 
2148 /*
2149  * This API is used by elfsign. We must keep it in old API form.
2150  */
2151 KMF_RETURN
2152 KMF_ConfigureKeystore(KMF_HANDLE_T handle, KMF_CONFIG_PARAMS *params)
2153 {
2154 
2155 	KMF_ATTRIBUTE attlist[32];
2156 	int i = 0;
2157 
2158 	if (params == NULL)
2159 		return (KMF_ERR_BAD_PARAMETER);
2160 
2161 	kmf_set_attr_at_index(attlist, i,
2162 	    KMF_KEYSTORE_TYPE_ATTR, &params->kstype, sizeof (params->kstype));
2163 	i++;
2164 
2165 	if (params->kstype == KMF_KEYSTORE_NSS) {
2166 		if (params->nssconfig.configdir != NULL) {
2167 			kmf_set_attr_at_index(attlist, i,
2168 			    KMF_DIRPATH_ATTR,
2169 			    params->nssconfig.configdir,
2170 			    strlen(params->nssconfig.configdir));
2171 			i++;
2172 		}
2173 		if (params->nssconfig.certPrefix != NULL) {
2174 			kmf_set_attr_at_index(attlist, i,
2175 			    KMF_CERTPREFIX_ATTR,
2176 			    params->nssconfig.certPrefix,
2177 			    strlen(params->nssconfig.certPrefix));
2178 			i++;
2179 		}
2180 		if (params->nssconfig.keyPrefix != NULL) {
2181 			kmf_set_attr_at_index(attlist, i,
2182 			    KMF_KEYPREFIX_ATTR,
2183 			    params->nssconfig.keyPrefix,
2184 			    strlen(params->nssconfig.keyPrefix));
2185 			i++;
2186 		}
2187 		if (params->nssconfig.secModName != NULL) {
2188 			kmf_set_attr_at_index(attlist, i,
2189 			    KMF_SECMODNAME_ATTR,
2190 			    params->nssconfig.secModName,
2191 			    strlen(params->nssconfig.secModName));
2192 			i++;
2193 		}
2194 	} else if (params->kstype == KMF_KEYSTORE_PK11TOKEN) {
2195 		if (params->pkcs11config.label != NULL) {
2196 			kmf_set_attr_at_index(attlist, i,
2197 			    KMF_TOKEN_LABEL_ATTR,
2198 			    params->pkcs11config.label,
2199 			    strlen(params->pkcs11config.label));
2200 			i++;
2201 		}
2202 		kmf_set_attr_at_index(attlist, i,
2203 		    KMF_READONLY_ATTR,
2204 		    &params->pkcs11config.readonly,
2205 		    sizeof (params->pkcs11config.readonly));
2206 		i++;
2207 	}
2208 
2209 	return (kmf_configure_keystore(handle, i, attlist));
2210 }
2211 
2212 /*
2213  * This API is used by elfsign. We must keep it in old API form.
2214  */
2215 KMF_RETURN
2216 KMF_Initialize(KMF_HANDLE_T *outhandle, char *policyfile, char *policyname)
2217 {
2218 	return (kmf_initialize(outhandle, policyfile, policyname));
2219 }
2220 
2221 /*
2222  * This API is used by elfsign. We must keep it in old API form.
2223  */
2224 KMF_RETURN
2225 KMF_Finalize(KMF_HANDLE_T handle)
2226 {
2227 	return (kmf_finalize(handle));
2228 }
2229 
2230 /*
2231  * This API is used by elfsign. We must keep it in old API form.
2232  */
2233 KMF_RETURN
2234 KMF_GetKMFErrorString(KMF_RETURN errcode, char **errmsg)
2235 {
2236 	return (kmf_get_kmf_error_str(errcode, errmsg));
2237 }
2238 
2239 /*
2240  * This API is used by elfsign. We must keep it in old API form.
2241  */
2242 KMF_RETURN
2243 KMF_ReadInputFile(KMF_HANDLE_T handle, char *filename,  KMF_DATA *pdata)
2244 {
2245 	return (kmf_read_input_file(handle, filename, pdata));
2246 }
2247 
2248 
2249 /*
2250  * This API is used by elfsign. We must keep it in old API form.
2251  */
2252 void
2253 KMF_FreeKMFCert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
2254 {
2255 	kmf_free_kmf_cert(handle, kmf_cert);
2256 }
2257 
2258 /*
2259  * This API is used by elfsign. We must keep it in old API form.
2260  */
2261 void
2262 KMF_FreeData(KMF_DATA *datablock)
2263 {
2264 	kmf_free_data(datablock);
2265 }
2266 
2267 /*
2268  * This API is used by elfsign. We must keep it in old API form.
2269  */
2270 void
2271 KMF_FreeKMFKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key)
2272 {
2273 	kmf_free_kmf_key(handle, key);
2274 }
2275 
2276 /*
2277  * This API is used by elfsign. We must keep it in old API form.
2278  */
2279 void
2280 KMF_FreeSignedCSR(KMF_CSR_DATA *csr)
2281 {
2282 	kmf_free_signed_csr(csr);
2283 }
2284