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 
144 static void free_extensions(KMF_X509_EXTENSIONS *extns);
145 
146 KMF_RETURN
147 init_pk11()
148 {
149 	(void) mutex_lock(&init_lock);
150 	if (!pkcs11_initialized) {
151 		CK_RV rv = C_Initialize(NULL);
152 		if ((rv != CKR_OK) &&
153 		    (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
154 			(void) mutex_unlock(&init_lock);
155 			return (KMF_ERR_UNINITIALIZED);
156 		} else {
157 			pkcs11_initialized = 1;
158 		}
159 	}
160 	(void) mutex_unlock(&init_lock);
161 	return (KMF_OK);
162 }
163 
164 /*
165  * Private method for searching the plugin list for the correct
166  * Plugin to use.
167  */
168 KMF_PLUGIN *
169 FindPlugin(KMF_HANDLE_T handle, KMF_KEYSTORE_TYPE kstype)
170 {
171 	KMF_PLUGIN_LIST *node;
172 
173 	if (handle == NULL)
174 		return (NULL);
175 
176 	node = handle->plugins;
177 
178 	while (node != NULL && node->plugin->type != kstype)
179 		node = node->next;
180 
181 	/* If it is NULL, that is indication enough of an error */
182 	return (node ? node->plugin : NULL);
183 }
184 
185 static KMF_RETURN
186 InitializePlugin(KMF_KEYSTORE_TYPE kstype, char *path, KMF_PLUGIN **plugin)
187 {
188 	KMF_PLUGIN *p = NULL;
189 	KMF_PLUGIN_FUNCLIST *(*sym)();
190 
191 	if (path == NULL || plugin == NULL)
192 		return (KMF_ERR_BAD_PARAMETER);
193 
194 	*plugin = NULL;
195 
196 	p = (KMF_PLUGIN *)malloc(sizeof (KMF_PLUGIN));
197 	if (p == NULL)
198 		return (KMF_ERR_MEMORY);
199 
200 	p->type = kstype;
201 	p->path = strdup(path);
202 	if (p->path == NULL) {
203 		free(p);
204 		return (KMF_ERR_MEMORY);
205 	}
206 	p->dldesc = dlopen(path, RTLD_NOW | RTLD_GROUP | RTLD_PARENT);
207 	if (p->dldesc == NULL) {
208 		free(p->path);
209 		free(p);
210 		return (KMF_ERR_PLUGIN_INIT);
211 	}
212 
213 	sym = (KMF_PLUGIN_FUNCLIST *(*)())dlsym(p->dldesc,
214 		KMF_PLUGIN_INIT_SYMBOL);
215 	if (sym == NULL) {
216 		(void) dlclose(p->dldesc);
217 		free(p->path);
218 		free(p);
219 		return (KMF_ERR_PLUGIN_INIT);
220 	}
221 
222 	/* Get the function list */
223 	if ((p->funclist = (*sym)()) == NULL) {
224 		(void) dlclose(p->dldesc);
225 		free(p->path);
226 		free(p);
227 		return (KMF_ERR_PLUGIN_INIT);
228 	}
229 
230 	*plugin = p;
231 
232 	return (KMF_OK);
233 }
234 
235 static KMF_RETURN
236 AddPlugin(KMF_HANDLE_T handle, KMF_PLUGIN *plugin)
237 {
238 	KMF_PLUGIN_LIST *n;
239 
240 	if (handle == NULL || plugin == NULL)
241 		return (KMF_ERR_BAD_PARAMETER);
242 
243 	/* If the head is NULL, create it */
244 	if (handle->plugins == NULL) {
245 		handle->plugins = (KMF_PLUGIN_LIST *)malloc(
246 			sizeof (KMF_PLUGIN_LIST));
247 		if (handle->plugins == NULL)
248 			return (KMF_ERR_MEMORY);
249 		handle->plugins->plugin = plugin;
250 		handle->plugins->next = NULL;
251 	} else {
252 		/* walk the list to find the tail */
253 		n = handle->plugins;
254 		while (n->next != NULL)
255 			n = n->next;
256 		n->next = (KMF_PLUGIN_LIST *)malloc(sizeof (KMF_PLUGIN_LIST));
257 		if (n->next == NULL)
258 			return (KMF_ERR_MEMORY);
259 
260 		n->next->plugin = plugin;
261 		n->next->next = NULL;
262 	}
263 	return (0);
264 }
265 
266 static void
267 DestroyPlugin(KMF_PLUGIN *plugin)
268 {
269 	if (plugin) {
270 		if (plugin->path)
271 			free(plugin->path);
272 		free(plugin);
273 	}
274 }
275 
276 static void
277 Cleanup_KMF_Handle(KMF_HANDLE_T handle)
278 {
279 	if (handle != NULL) {
280 		while (handle->plugins != NULL) {
281 			KMF_PLUGIN_LIST *next = handle->plugins->next;
282 
283 			DestroyPlugin(handle->plugins->plugin);
284 
285 			free(handle->plugins);
286 
287 			handle->plugins = next;
288 		}
289 
290 		KMF_FreePolicyRecord(handle->policy);
291 		free(handle->policy);
292 	}
293 	free(handle);
294 }
295 
296 void
297 Cleanup_PK11_Session(KMF_HANDLE_T handle)
298 {
299 	if (handle != NULL) {
300 		/* Close active session on a pkcs11 token */
301 		if (handle->pk11handle != NULL) {
302 			(void) C_CloseSession(handle->pk11handle);
303 			handle->pk11handle = NULL;
304 		}
305 	}
306 }
307 
308 KMF_RETURN
309 KMF_Initialize(KMF_HANDLE_T *outhandle, char *policyfile, char *policyname)
310 {
311 	KMF_RETURN ret = KMF_OK;
312 	KMF_HANDLE *handle = NULL;
313 	KMF_PLUGIN *pluginrec = NULL;
314 
315 	if (outhandle == NULL)
316 		return (KMF_ERR_BAD_PARAMETER);
317 
318 	*outhandle = NULL;
319 	handle = (KMF_HANDLE *)malloc(sizeof (KMF_HANDLE));
320 	if (handle == NULL)
321 		return (KMF_ERR_MEMORY);
322 
323 	(void) memset(handle, 0, sizeof (KMF_HANDLE));
324 	handle->plugins = NULL;
325 
326 
327 	/* Initialize the handle with the policy */
328 	ret = KMF_SetPolicy((void *)handle,
329 	    policyfile == NULL ? KMF_DEFAULT_POLICY_FILE : policyfile,
330 	    policyname == NULL ? KMF_DEFAULT_POLICY_NAME : policyname);
331 	if (ret != KMF_OK)
332 		goto errout;
333 
334 	/* Create a record for the plugin */
335 	if ((ret = InitializePlugin(KMF_KEYSTORE_NSS,
336 		KMF_PLUGIN_PATH "kmf_nss.so.1", &pluginrec)) != KMF_OK)
337 		goto errout;
338 
339 	/* Add it to the handle */
340 	if (pluginrec != NULL) {
341 		if ((ret = AddPlugin(handle, pluginrec)))
342 			goto errout;
343 	}
344 	if ((ret = InitializePlugin(KMF_KEYSTORE_OPENSSL,
345 		KMF_PLUGIN_PATH "kmf_openssl.so.1", &pluginrec)) != KMF_OK)
346 		goto errout;
347 
348 	/* Add it to the handle */
349 	if (pluginrec != NULL)
350 		if ((ret = AddPlugin(handle, pluginrec)))
351 			goto errout;
352 
353 	if ((ret = InitializePlugin(KMF_KEYSTORE_PK11TOKEN,
354 		KMF_PLUGIN_PATH "kmf_pkcs11.so.1", &pluginrec)) != KMF_OK)
355 		goto errout;
356 
357 	/* Add it to the handle */
358 	if (pluginrec != NULL)
359 		if ((ret = AddPlugin(handle, pluginrec)))
360 			goto errout;
361 
362 	CLEAR_ERROR(handle, ret);
363 errout:
364 	if (ret != KMF_OK) {
365 		Cleanup_KMF_Handle(handle);
366 		handle = NULL;
367 	}
368 
369 	*outhandle = (KMF_HANDLE_T)handle;
370 	return (ret);
371 }
372 
373 KMF_RETURN
374 KMF_ConfigureKeystore(KMF_HANDLE_T handle, KMF_CONFIG_PARAMS *params)
375 {
376 	KMF_PLUGIN *plugin;
377 	KMF_RETURN ret;
378 
379 	CLEAR_ERROR(handle, ret);
380 	if (ret != KMF_OK)
381 		return (ret);
382 
383 	if (params == NULL)
384 		return (KMF_ERR_BAD_PARAMETER);
385 
386 	plugin = FindPlugin(handle, params->kstype);
387 	if (plugin == NULL)
388 		return (KMF_ERR_PLUGIN_NOTFOUND);
389 
390 	if (plugin->funclist->ConfigureKeystore != NULL)
391 		return (plugin->funclist->ConfigureKeystore(handle, params));
392 	else
393 		/* return KMF_OK, if the plugin does not have an entry */
394 		return (KMF_OK);
395 }
396 
397 KMF_RETURN
398 KMF_Finalize(KMF_HANDLE_T handle)
399 {
400 	KMF_RETURN ret = KMF_OK;
401 
402 	CLEAR_ERROR(handle, ret);
403 	if (ret != KMF_OK)
404 		return (ret);
405 
406 	if (pkcs11_initialized) {
407 		Cleanup_PK11_Session(handle);
408 	}
409 	Cleanup_KMF_Handle(handle);
410 
411 	return (ret);
412 }
413 
414 KMF_RETURN
415 KMF_GetKMFErrorString(KMF_RETURN errcode, char **errmsg)
416 {
417 	KMF_RETURN ret = KMF_OK;
418 	int i, maxerr;
419 
420 	if (errmsg == NULL)
421 		return (KMF_ERR_BAD_PARAMETER);
422 
423 	*errmsg = NULL;
424 	maxerr = sizeof (kmf_errcodes) / sizeof (kmf_error_map);
425 
426 	for (i = 0; i < maxerr && errcode != kmf_errcodes[i].code; i++);
427 
428 	if (i == maxerr)
429 		return (KMF_ERR_MISSING_ERRCODE);
430 	else {
431 		*errmsg = strdup(kmf_errcodes[i].message);
432 		if ((*errmsg) == NULL)
433 			return (KMF_ERR_MEMORY);
434 	}
435 	return (ret);
436 }
437 
438 KMF_RETURN
439 KMF_GetPluginErrorString(KMF_HANDLE_T handle, char **msgstr)
440 {
441 	KMF_RETURN ret = KMF_OK;
442 	KMF_PLUGIN *plugin;
443 
444 	if (handle == NULL || msgstr == NULL)
445 		return (KMF_ERR_BAD_PARAMETER);
446 
447 	*msgstr = NULL;
448 
449 	if (handle->lasterr.errcode == 0) {
450 		return (KMF_ERR_MISSING_ERRCODE);
451 	}
452 
453 	if (handle->lasterr.kstype == -1) { /* System error */
454 		char *str = strerror(handle->lasterr.errcode);
455 		if (str != NULL) {
456 			*msgstr = strdup(str);
457 			if ((*msgstr) == NULL)
458 				return (KMF_ERR_MEMORY);
459 		}
460 		return (KMF_OK);
461 	}
462 
463 	plugin = FindPlugin(handle, handle->lasterr.kstype);
464 	if (plugin == NULL)
465 		return (KMF_ERR_PLUGIN_NOTFOUND);
466 
467 	if (plugin->funclist->GetErrorString != NULL) {
468 		ret = plugin->funclist->GetErrorString(handle, msgstr);
469 	} else {
470 		return (KMF_ERR_FUNCTION_NOT_FOUND);
471 	}
472 
473 	return (ret);
474 }
475 
476 KMF_RETURN
477 KMF_DNParser(char *string, KMF_X509_NAME *name)
478 {
479 	KMF_RETURN err;
480 
481 	if (string == NULL || name == NULL)
482 		return (KMF_ERR_BAD_PARAMETER);
483 
484 	err = ParseDistinguishedName(string, (int)strlen(string), name);
485 	return (err);
486 }
487 
488 KMF_RETURN
489 KMF_DN2Der(KMF_X509_NAME *dn, KMF_DATA *der)
490 {
491 	KMF_RETURN rv;
492 
493 	if (dn == NULL || der == NULL)
494 		return (KMF_ERR_BAD_PARAMETER);
495 
496 	rv = DerEncodeName(dn, der);
497 	return (rv);
498 }
499 
500 #define	SET_SYS_ERROR(h, c) if (h) {\
501 	h->lasterr.kstype = -1;\
502 	h->lasterr.errcode = c;\
503 }
504 
505 KMF_RETURN
506 KMF_ReadInputFile(KMF_HANDLE_T handle, char *filename,  KMF_DATA *pdata)
507 {
508 	struct stat s;
509 	long nread, total = 0;
510 	int fd;
511 	unsigned char *buf = NULL;
512 	KMF_RETURN ret;
513 
514 	if (handle) {
515 		CLEAR_ERROR(handle, ret);
516 		if (ret != KMF_OK)
517 			return (ret);
518 	}
519 
520 	if (filename == NULL || pdata == NULL) {
521 		return (KMF_ERR_BAD_PARAMETER);
522 	}
523 
524 	if ((fd = open(filename, O_RDONLY)) < 0) {
525 		SET_SYS_ERROR(handle, errno);
526 		return (KMF_ERR_OPEN_FILE);
527 	}
528 
529 	if (fstat(fd, &s) < 0) {
530 		SET_SYS_ERROR(handle, errno);
531 		(void) close(fd);
532 		return (KMF_ERR_OPEN_FILE);
533 	}
534 
535 	if ((buf = (unsigned char *) malloc(s.st_size)) == NULL) {
536 		(void) close(fd);
537 		return (KMF_ERR_MEMORY);
538 	}
539 
540 	do {
541 		nread = read(fd, buf+total, s.st_size-total);
542 		if (nread < 0) {
543 			SET_SYS_ERROR(handle, errno);
544 			(void) close(fd);
545 			free(buf);
546 			return (KMF_ERR_INTERNAL);
547 		}
548 		total += nread;
549 	} while (total < s.st_size);
550 
551 	pdata->Data = buf;
552 	pdata->Length = s.st_size;
553 	(void) close(fd);
554 	return (KMF_OK);
555 }
556 
557 /*
558  *
559  * Name: KMF_Der2Pem
560  *
561  * Description:
562  *   Function for converting DER encoded format to PEM encoded format
563  *
564  * Parameters:
565  *   type(input) - CERTIFICATE or CSR
566  *   data(input) - pointer to the DER encoded data
567  *   len(input)  - length of input data
568  *   out(output) - contains the output buffer address to be returned
569  *   outlen(output) - pointer to the returned output length
570  *
571  * Returns:
572  *   A KMF_RETURN value indicating success or specifying a particular
573  * error condition.
574  *   The value KMF_OK indicates success. All other values represent
575  * an error condition.
576  *
577  */
578 KMF_RETURN
579 KMF_Der2Pem(KMF_OBJECT_TYPE type, unsigned char *data,
580 	int len, unsigned char **out, int *outlen)
581 {
582 
583 	KMF_RETURN err;
584 	if (data == NULL || out == NULL || outlen == NULL)
585 		return (KMF_ERR_BAD_PARAMETER);
586 
587 	err = Der2Pem(type, data, len, out, outlen);
588 	return (err);
589 
590 }
591 
592 /*
593  *
594  * Name: KMF_Pem2Der
595  *
596  * Description:
597  *   Function for converting PEM encoded format to DER encoded format
598  *
599  * Parameters:
600  *   in(input) - pointer to the PEM encoded data
601  *   inlen(input)  - length of input data
602  *   out(output) - contains the output buffer address to be returned
603  *   outlen(output) - pointer to the returned output length
604  *
605  * Returns:
606  *   A KMF_RETURN value indicating success or specifying a particular
607  *   error condition.
608  *   The value KMF_OK indicates success. All other values represent
609  *   an error condition.
610  *
611  */
612 KMF_RETURN
613 KMF_Pem2Der(unsigned char *in, int inlen,
614 	unsigned char **out, int *outlen)
615 {
616 	KMF_RETURN err;
617 	if (in == NULL || out == NULL || outlen == NULL)
618 		return (KMF_ERR_BAD_PARAMETER);
619 
620 	err = Pem2Der(in, inlen, out, outlen);
621 	return (err);
622 }
623 
624 char *
625 KMF_OID2String(KMF_OID *oid)
626 {
627 	char numstr[128];
628 	uint32_t number;
629 	int numshift;
630 	uint32_t i, string_length;
631 	uchar_t *cp;
632 	char *bp;
633 
634 	/* First determine the size of the string */
635 	string_length = 0;
636 	number = 0;
637 	numshift = 0;
638 	cp = (unsigned char *)oid->Data;
639 
640 	number = (uint32_t)cp[0];
641 	(void) sprintf(numstr, "%d ", number/40);
642 
643 	string_length += strlen(numstr);
644 	(void) sprintf(numstr, "%d ", number%40);
645 
646 	string_length += strlen(numstr);
647 
648 	for (i = 1; i < oid->Length; i++) {
649 		if ((uint32_t)(numshift+7) < (sizeof (uint32_t)*8)) {
650 			number = (number << 7) | (cp[i] & 0x7f);
651 			numshift += 7;
652 		} else {
653 			return (NULL);
654 		}
655 
656 		if ((cp[i] & 0x80) == 0) {
657 			(void) sprintf(numstr, "%d ", number);
658 			string_length += strlen(numstr);
659 			number = 0;
660 			numshift = 0;
661 		}
662 	}
663 	/*
664 	 * If we get here, we've calculated the length of "n n n ... n ".  Add 4
665 	 * here for "{ " and "}\0".
666 	 */
667 	string_length += 4;
668 	if ((bp = (char *)malloc(string_length))) {
669 		number = (uint32_t)cp[0];
670 
671 		(void) sprintf(numstr, "%d.", number/40);
672 		(void) strcpy(bp, numstr);
673 
674 		(void) sprintf(numstr, "%d.", number%40);
675 		(void) strcat(bp, numstr);
676 
677 		number = 0;
678 		cp = (unsigned char *) oid->Data;
679 		for (i = 1; i < oid->Length; i++) {
680 			number = (number << 7) | (cp[i] & 0x7f);
681 			if ((cp[i] & 0x80) == 0) {
682 				(void) sprintf(numstr, "%d", number);
683 				(void) strcat(bp, numstr);
684 				number = 0;
685 				if (i+1 < oid->Length)
686 					(void) strcat(bp, ".");
687 			}
688 		}
689 	}
690 	return (bp);
691 }
692 
693 static boolean_t
694 check_for_pem(char *filename)
695 {
696 	KMF_DATA filebuf;
697 	KMF_RETURN rv;
698 	char *p;
699 
700 	rv = KMF_ReadInputFile(NULL, filename, &filebuf);
701 	if (rv != KMF_OK)
702 		return (FALSE);
703 
704 	/* Look for "-----BEGIN" right after a newline */
705 	p = strtok((char *)filebuf.Data, "\n");
706 	while (p != NULL) {
707 		if (strstr(p, "-----BEGIN") != NULL) {
708 			free(filebuf.Data);
709 			return (TRUE);
710 		}
711 		p = strtok(NULL, "\n");
712 	}
713 	free(filebuf.Data);
714 	return (FALSE);
715 }
716 
717 KMF_RETURN
718 KMF_GetFileFormat(char *filename, KMF_ENCODE_FORMAT *fmt)
719 {
720 	int f;
721 	KMF_RETURN ret = KMF_OK;
722 	uchar_t buf[16];
723 
724 	if (filename == NULL || !strlen(filename) || fmt == NULL)
725 		return (KMF_ERR_BAD_PARAMETER);
726 
727 	*fmt = 0;
728 	if ((f = open(filename, O_RDONLY)) == -1) {
729 		return (KMF_ERR_OPEN_FILE);
730 	}
731 
732 	if (read(f, buf, 8) != 8) {
733 		ret = KMF_ERR_OPEN_FILE;
734 		goto end;
735 	}
736 
737 	(void) close(f);
738 	if (buf[0] == 0x30 && (buf[1] & 0x80)) {
739 		if ((buf[1] & 0xFF) == 0x80 &&
740 		    (buf[2] & 0xFF) == 0x02 &&
741 		    (buf[5] & 0xFF) == 0x30) {
742 			*fmt = KMF_FORMAT_PKCS12;
743 		} else if ((buf[1] & 0xFF) == 0x82 &&
744 			(buf[4] & 0xFF) == 0x02 &&
745 			(buf[7] & 0xFF) == 0x30) {
746 			*fmt = KMF_FORMAT_PKCS12;
747 		/* It is most likely a generic ASN.1 encoded file */
748 		} else {
749 			*fmt = KMF_FORMAT_ASN1;
750 		}
751 	} else if (memcmp(buf, "Bag Attr", 8) == 0) {
752 		*fmt = KMF_FORMAT_PEM_KEYPAIR;
753 	} else {
754 		/* Try PEM */
755 		if (check_for_pem(filename) == TRUE) {
756 			*fmt = KMF_FORMAT_PEM;
757 		} else {
758 			/* Cannot determine this file format */
759 			*fmt = 0;
760 			ret = KMF_ERR_ENCODING;
761 		}
762 	}
763 end:
764 	return (ret);
765 }
766 
767 KMF_RETURN
768 KMF_HexString2Bytes(unsigned char *hexstr, unsigned char **bytes,
769 	size_t *outlen)
770 {
771 	KMF_RETURN ret = KMF_OK;
772 	unsigned char *buf = NULL;
773 	int len, stringlen;
774 	int i;
775 	unsigned char ch;
776 
777 	if (hexstr == NULL) {
778 		return (KMF_ERR_BAD_PARAMETER);
779 	}
780 
781 	if (hexstr[0] == '0' &&
782 		((hexstr[1] == 'x') || (hexstr[1] == 'X')))
783 		hexstr += 2;
784 
785 	for (i = 0; i < strlen((char *)hexstr) && isxdigit(hexstr[i]); i++);
786 	/*
787 	 * If all the characters are not legitimate hex chars,
788 	 * return an error.
789 	 */
790 	if (i != strlen((char *)hexstr))
791 		return (KMF_ERR_BAD_HEX_STRING);
792 	stringlen = i;
793 	len = (i / 2) + (i % 2);
794 
795 	buf = malloc(len);
796 	if (buf == NULL) {
797 		return (KMF_ERR_MEMORY);
798 	}
799 	(void) memset(buf, 0, len);
800 
801 	for (i = 0; i < stringlen; i++) {
802 		ch = (unsigned char) *hexstr;
803 		hexstr++;
804 		if ((ch >= '0') && (ch <= '9'))
805 			ch -= '0';
806 		else if ((ch >= 'A') && (ch <= 'F'))
807 			ch = ch - 'A' + 10;
808 		else if ((ch >= 'a') && (ch <= 'f'))
809 			ch = ch - 'a' + 10;
810 		else {
811 			ret = KMF_ERR_BAD_HEX_STRING;
812 			goto out;
813 		}
814 
815 		if (i & 1) {
816 			buf[i/2] |= ch;
817 		} else {
818 			buf[i/2] = (ch << 4);
819 		}
820 	}
821 
822 	*bytes = buf;
823 	*outlen = len;
824 out:
825 	if (buf != NULL && ret != KMF_OK) {
826 		free(buf);
827 	}
828 	return (ret);
829 }
830 
831 void
832 KMF_FreeDN(KMF_X509_NAME *name)
833 {
834 	KMF_X509_RDN 		*newrdn = NULL;
835 	KMF_X509_TYPE_VALUE_PAIR *av = NULL;
836 	int i, j;
837 
838 	if (name && name->numberOfRDNs) {
839 		for (i = 0; i < name->numberOfRDNs; i++) {
840 			newrdn = &name->RelativeDistinguishedName[i];
841 			for (j = 0; j < newrdn->numberOfPairs; j++) {
842 				av = &newrdn->AttributeTypeAndValue[j];
843 				KMF_FreeData(&av->type);
844 				KMF_FreeData(&av->value);
845 			}
846 			free(newrdn->AttributeTypeAndValue);
847 			newrdn->numberOfPairs = 0;
848 			newrdn->AttributeTypeAndValue = NULL;
849 		}
850 		free(name->RelativeDistinguishedName);
851 		name->numberOfRDNs = 0;
852 		name->RelativeDistinguishedName = NULL;
853 	}
854 }
855 
856 void
857 KMF_FreeKMFCert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
858 {
859 	KMF_PLUGIN *plugin;
860 	KMF_RETURN ret;
861 
862 	CLEAR_ERROR(handle, ret);
863 	if (ret != KMF_OK)
864 		return;
865 
866 	if (kmf_cert == NULL)
867 		return;
868 
869 	plugin = FindPlugin(handle, kmf_cert->kmf_private.keystore_type);
870 
871 	if (plugin != NULL && plugin->funclist->FreeKMFCert != NULL) {
872 		plugin->funclist->FreeKMFCert(handle, kmf_cert);
873 	}
874 }
875 
876 void
877 KMF_FreeData(KMF_DATA *datablock)
878 {
879 	if (datablock != NULL && datablock->Data != NULL) {
880 		free(datablock->Data);
881 		datablock->Data = NULL;
882 		datablock->Length = 0;
883 	}
884 }
885 
886 void
887 KMF_FreeAlgOID(KMF_X509_ALGORITHM_IDENTIFIER *algoid)
888 {
889 	if (algoid == NULL)
890 		return;
891 	KMF_FreeData(&algoid->algorithm);
892 	KMF_FreeData(&algoid->parameters);
893 }
894 
895 void
896 KMF_FreeExtension(KMF_X509_EXTENSION *exptr)
897 {
898 	if (exptr == NULL)
899 		return;
900 
901 	KMF_FreeData((KMF_DATA *)&exptr->extnId);
902 	KMF_FreeData(&exptr->BERvalue);
903 
904 	if (exptr->value.tagAndValue) {
905 		KMF_FreeData(&exptr->value.tagAndValue->value);
906 		free(exptr->value.tagAndValue);
907 	}
908 }
909 
910 void
911 KMF_FreeTBSCSR(KMF_TBS_CSR *tbscsr)
912 {
913 	if (tbscsr) {
914 		KMF_FreeData(&tbscsr->version);
915 
916 		KMF_FreeDN(&tbscsr->subject);
917 
918 		KMF_FreeAlgOID(&tbscsr->subjectPublicKeyInfo.algorithm);
919 		KMF_FreeData(&tbscsr->subjectPublicKeyInfo.subjectPublicKey);
920 
921 		free_extensions(&tbscsr->extensions);
922 	}
923 }
924 
925 void
926 KMF_FreeSignedCSR(KMF_CSR_DATA *csr)
927 {
928 	if (csr) {
929 		KMF_FreeTBSCSR(&csr->csr);
930 
931 		KMF_FreeAlgOID(&csr->signature.algorithmIdentifier);
932 		KMF_FreeData(&csr->signature.encrypted);
933 	}
934 }
935 
936 static void
937 free_validity(KMF_X509_VALIDITY *validity)
938 {
939 	if (validity == NULL)
940 		return;
941 	KMF_FreeData(&validity->notBefore.time);
942 	KMF_FreeData(&validity->notAfter.time);
943 }
944 
945 static void
946 free_extensions(KMF_X509_EXTENSIONS *extns)
947 {
948 	int i;
949 	KMF_X509_EXTENSION *exptr;
950 
951 	if (extns && extns->numberOfExtensions > 0) {
952 		for (i = 0; i < extns->numberOfExtensions; i++) {
953 			exptr = &extns->extensions[i];
954 			KMF_FreeExtension(exptr);
955 		}
956 		free(extns->extensions);
957 		extns->numberOfExtensions = 0;
958 		extns->extensions = NULL;
959 	}
960 }
961 
962 void
963 KMF_FreeTBSCert(KMF_X509_TBS_CERT *tbscert)
964 {
965 	if (tbscert) {
966 		KMF_FreeData(&tbscert->version);
967 		KMF_FreeBigint(&tbscert->serialNumber);
968 		KMF_FreeAlgOID(&tbscert->signature);
969 
970 		KMF_FreeDN(&tbscert->issuer);
971 		KMF_FreeDN(&tbscert->subject);
972 
973 		free_validity(&tbscert->validity);
974 
975 		KMF_FreeData(&tbscert->issuerUniqueIdentifier);
976 		KMF_FreeData(&tbscert->subjectUniqueIdentifier);
977 
978 		KMF_FreeAlgOID(&tbscert->subjectPublicKeyInfo.algorithm);
979 		KMF_FreeData(&tbscert->subjectPublicKeyInfo.subjectPublicKey);
980 
981 		free_extensions(&tbscert->extensions);
982 
983 		KMF_FreeData(&tbscert->issuerUniqueIdentifier);
984 		KMF_FreeData(&tbscert->subjectUniqueIdentifier);
985 	}
986 }
987 
988 void
989 KMF_FreeSignedCert(KMF_X509_CERTIFICATE *certptr)
990 {
991 	if (!certptr)
992 		return;
993 
994 	KMF_FreeTBSCert(&certptr->certificate);
995 
996 	KMF_FreeAlgOID(&certptr->signature.algorithmIdentifier);
997 	KMF_FreeData(&certptr->signature.encrypted);
998 }
999 
1000 void
1001 KMF_FreeString(char *pstr)
1002 {
1003 	if (pstr != NULL)
1004 		free(pstr);
1005 }
1006 
1007 void
1008 free_keyidlist(KMF_OID *oidlist, int len)
1009 {
1010 	int i;
1011 	for (i = 0; i < len; i++) {
1012 		KMF_FreeData((KMF_DATA *)&oidlist[i]);
1013 	}
1014 	free(oidlist);
1015 }
1016 
1017 void
1018 KMF_FreeEKU(KMF_X509EXT_EKU *eptr)
1019 {
1020 	if (eptr && eptr->nEKUs > 0 &&
1021 		eptr->keyPurposeIdList != NULL)
1022 		free_keyidlist(eptr->keyPurposeIdList, eptr->nEKUs);
1023 }
1024 
1025 void
1026 KMF_FreeSPKI(KMF_X509_SPKI *spki)
1027 {
1028 	if (spki != NULL) {
1029 		KMF_FreeAlgOID(&spki->algorithm);
1030 		KMF_FreeData(&spki->subjectPublicKey);
1031 	}
1032 }
1033 
1034 void
1035 KMF_FreeKMFKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key)
1036 {
1037 	KMF_PLUGIN *plugin;
1038 	KMF_RETURN ret;
1039 
1040 	CLEAR_ERROR(handle, ret);
1041 	if (ret != KMF_OK)
1042 		return;
1043 
1044 	if (key == NULL)
1045 		return;
1046 
1047 	plugin = FindPlugin(handle, key->kstype);
1048 	if (plugin != NULL && plugin->funclist->DeleteKey != NULL) {
1049 		(void) plugin->funclist->DeleteKey(handle, NULL, key, FALSE);
1050 	}
1051 
1052 	if (key == NULL)
1053 		return;
1054 
1055 	if (key->keylabel)
1056 		free(key->keylabel);
1057 
1058 	if (key->israw) {
1059 		KMF_FreeRawKey(key->keyp);
1060 		free(key->keyp);
1061 	}
1062 
1063 	(void) memset(key, 0, sizeof (KMF_KEY_HANDLE));
1064 }
1065 
1066 void
1067 KMF_FreeBigint(KMF_BIGINT *big)
1068 {
1069 	if (big != NULL && big->val != NULL) {
1070 		/* Clear it out before returning it to the pool */
1071 		(void) memset(big->val, 0x00, big->len);
1072 		free(big->val);
1073 		big->val = NULL;
1074 		big->len = 0;
1075 	}
1076 }
1077 
1078 static void
1079 free_raw_rsa(KMF_RAW_RSA_KEY *key)
1080 {
1081 	if (key == NULL)
1082 		return;
1083 	KMF_FreeBigint(&key->mod);
1084 	KMF_FreeBigint(&key->pubexp);
1085 	KMF_FreeBigint(&key->priexp);
1086 	KMF_FreeBigint(&key->prime1);
1087 	KMF_FreeBigint(&key->prime2);
1088 	KMF_FreeBigint(&key->exp1);
1089 	KMF_FreeBigint(&key->exp2);
1090 	KMF_FreeBigint(&key->coef);
1091 }
1092 
1093 static void
1094 free_raw_dsa(KMF_RAW_DSA_KEY *key)
1095 {
1096 	if (key == NULL)
1097 		return;
1098 	KMF_FreeBigint(&key->prime);
1099 	KMF_FreeBigint(&key->subprime);
1100 	KMF_FreeBigint(&key->base);
1101 	KMF_FreeBigint(&key->value);
1102 }
1103 
1104 static void
1105 free_raw_sym(KMF_RAW_SYM_KEY *key)
1106 {
1107 	if (key == NULL)
1108 		return;
1109 	KMF_FreeBigint(&key->keydata);
1110 }
1111 
1112 void
1113 KMF_FreeRawKey(KMF_RAW_KEY_DATA *key)
1114 {
1115 	if (key == NULL)
1116 		return;
1117 
1118 	switch (key->keytype) {
1119 	case KMF_RSA:
1120 		free_raw_rsa(&key->rawdata.rsa);
1121 		break;
1122 	case KMF_DSA:
1123 		free_raw_dsa(&key->rawdata.dsa);
1124 		break;
1125 	case KMF_AES:
1126 	case KMF_RC4:
1127 	case KMF_DES:
1128 	case KMF_DES3:
1129 		free_raw_sym(&key->rawdata.sym);
1130 		break;
1131 	}
1132 }
1133 
1134 void
1135 KMF_FreeRawSymKey(KMF_RAW_SYM_KEY *key)
1136 {
1137 	if (key == NULL)
1138 		return;
1139 	KMF_FreeBigint(&key->keydata);
1140 	free(key);
1141 }
1142 
1143 /*
1144  * This function frees the space allocated for the name portion of a
1145  * KMF_CRL_DIST_POINT.
1146  */
1147 void
1148 free_dp_name(KMF_CRL_DIST_POINT *dp)
1149 {
1150 	KMF_GENERALNAMES *fullname;
1151 	KMF_DATA *urldata;
1152 	int i;
1153 
1154 	if (dp == NULL)
1155 		return;
1156 
1157 	/* For phase 1, we only need to free the fullname space. */
1158 	fullname = &(dp->name.full_name);
1159 	if (fullname->number == 0)
1160 		return;
1161 
1162 	for (i = 0; i < fullname->number; i++) {
1163 		urldata = &(fullname->namelist[fullname->number - 1].name);
1164 		KMF_FreeData(urldata);
1165 	}
1166 
1167 	free(fullname->namelist);
1168 }
1169 
1170 /*
1171  * This function frees the space allocated for a KMF_CRL_DIST_POINT.
1172  */
1173 void
1174 free_dp(KMF_CRL_DIST_POINT *dp)
1175 {
1176 	if (dp == NULL)
1177 		return;
1178 
1179 	free_dp_name(dp);
1180 	KMF_FreeData(&(dp->reasons));
1181 	/* Need not to free crl_issuer space at phase 1 */
1182 }
1183 
1184 /*
1185  * This function frees space for a KMF_X509EXT_CRLDISTPOINTS internally.
1186  */
1187 void
1188 KMF_FreeCRLDistributionPoints(KMF_X509EXT_CRLDISTPOINTS *crl_dps)
1189 {
1190 	int i;
1191 
1192 	if (crl_dps == NULL)
1193 		return;
1194 
1195 	for (i = 0; i < crl_dps->number; i++)
1196 		free_dp(&(crl_dps->dplist[i]));
1197 
1198 	free(crl_dps->dplist);
1199 }
1200 
1201 KMF_RETURN
1202 KMF_CreateOCSPRequest(KMF_HANDLE_T handle,  KMF_OCSPREQUEST_PARAMS *params,
1203     char *reqfile)
1204 {
1205 	KMF_PLUGIN *plugin;
1206 	KMF_RETURN (*createReqFn)(void *, KMF_OCSPREQUEST_PARAMS *params,
1207 	    char *reqfile);
1208 	KMF_RETURN ret;
1209 
1210 	CLEAR_ERROR(handle, ret);
1211 	if (ret != KMF_OK)
1212 		return (ret);
1213 
1214 
1215 	if (params == NULL ||
1216 		reqfile == NULL)
1217 		return (KMF_ERR_BAD_PARAMETER);
1218 
1219 	/*
1220 	 * This framework function is actually implemented in the openssl
1221 	 * plugin library, so we find the function address and call it.
1222 	 */
1223 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
1224 	if (plugin == NULL || plugin->dldesc == NULL) {
1225 		return (KMF_ERR_PLUGIN_NOTFOUND);
1226 	}
1227 
1228 	createReqFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
1229 	    "OpenSSL_CreateOCSPRequest");
1230 	if (createReqFn == NULL) {
1231 		return (KMF_ERR_FUNCTION_NOT_FOUND);
1232 	}
1233 
1234 	return (createReqFn(handle, params, reqfile));
1235 }
1236 
1237 KMF_RETURN
1238 KMF_GetOCSPStatusForCert(KMF_HANDLE_T handle,
1239     KMF_OCSPRESPONSE_PARAMS_INPUT *params_in,
1240     KMF_OCSPRESPONSE_PARAMS_OUTPUT *params_out)
1241 {
1242 	KMF_PLUGIN *plugin;
1243 	KMF_RETURN (*getCertStatusFn)(void *,
1244 	    KMF_OCSPRESPONSE_PARAMS_INPUT *params_in,
1245 	    KMF_OCSPRESPONSE_PARAMS_OUTPUT *params_out);
1246 	KMF_RETURN ret;
1247 
1248 	CLEAR_ERROR(handle, ret);
1249 	if (ret != KMF_OK)
1250 		return (ret);
1251 
1252 
1253 	if (params_in == NULL ||
1254 		params_out == NULL)
1255 		return (KMF_ERR_BAD_PARAMETER);
1256 
1257 	/*
1258 	 * This framework function is actually implemented in the openssl
1259 	 * plugin library, so we find the function address and call it.
1260 	 */
1261 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
1262 	if (plugin == NULL || plugin->dldesc == NULL) {
1263 		return (KMF_ERR_INTERNAL);
1264 	}
1265 
1266 	getCertStatusFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
1267 	    "OpenSSL_GetOCSPStatusForCert");
1268 	if (getCertStatusFn == NULL) {
1269 		return (KMF_ERR_INTERNAL);
1270 	}
1271 
1272 	return (getCertStatusFn(handle, params_in, params_out));
1273 }
1274 
1275 KMF_RETURN
1276 KMF_String2OID(char *oidstring, KMF_OID *oid)
1277 {
1278 	KMF_RETURN rv = KMF_OK;
1279 	char *cp, *bp, *startp;
1280 	int numbuf;
1281 	int onumbuf;
1282 	int nbytes, index;
1283 	int len;
1284 	unsigned char *op;
1285 
1286 	if (oidstring == NULL || oid == NULL)
1287 		return (KMF_ERR_BAD_PARAMETER);
1288 
1289 	len = strlen(oidstring);
1290 
1291 	bp = oidstring;
1292 	cp = bp;
1293 	/* Skip over leading space */
1294 	while ((bp < &cp[len]) && isspace(*bp))
1295 		bp++;
1296 
1297 	startp = bp;
1298 	nbytes = 0;
1299 
1300 	/*
1301 	 * The first two numbers are chewed up by the first octet.
1302 	 */
1303 	if (sscanf(bp, "%d", &numbuf) != 1)
1304 		return (KMF_ERR_BAD_PARAMETER);
1305 	while ((bp < &cp[len]) && isdigit(*bp))
1306 		bp++;
1307 	while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
1308 		bp++;
1309 	if (sscanf(bp, "%d", &numbuf) != 1)
1310 		return (KMF_ERR_BAD_PARAMETER);
1311 	while ((bp < &cp[len]) && isdigit(*bp))
1312 		bp++;
1313 	while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
1314 		bp++;
1315 	nbytes++;
1316 
1317 	while (isdigit(*bp)) {
1318 		if (sscanf(bp, "%d", &numbuf) != 1)
1319 			return (KMF_ERR_BAD_PARAMETER);
1320 		while (numbuf) {
1321 			nbytes++;
1322 			numbuf >>= 7;
1323 		}
1324 		while ((bp < &cp[len]) && isdigit(*bp))
1325 			bp++;
1326 		while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
1327 			bp++;
1328 	}
1329 
1330 	oid->Length = nbytes;
1331 	oid->Data = malloc(oid->Length);
1332 	if (oid->Data == NULL) {
1333 		return (KMF_ERR_MEMORY);
1334 	}
1335 	(void) memset(oid->Data, 0, oid->Length);
1336 
1337 	op = oid->Data;
1338 
1339 	bp = startp;
1340 	(void) sscanf(bp, "%d", &numbuf);
1341 
1342 	while (isdigit(*bp)) bp++;
1343 	while (isspace(*bp) || *bp == '.') bp++;
1344 
1345 	onumbuf = 40 * numbuf;
1346 	(void) sscanf(bp, "%d", &numbuf);
1347 	onumbuf += numbuf;
1348 	*op = (unsigned char) onumbuf;
1349 	op++;
1350 
1351 	while (isdigit(*bp)) bp++;
1352 	while (isspace(*bp) || *bp == '.') bp++;
1353 	while (isdigit(*bp)) {
1354 		(void) sscanf(bp, "%d", &numbuf);
1355 		nbytes = 0;
1356 		/* Have to fill in the bytes msb-first */
1357 		onumbuf = numbuf;
1358 		while (numbuf) {
1359 			nbytes++;
1360 			numbuf >>= 7;
1361 		}
1362 		numbuf = onumbuf;
1363 		op += nbytes;
1364 		index = -1;
1365 		while (numbuf) {
1366 			op[index] = (unsigned char)numbuf & 0x7f;
1367 			if (index != -1)
1368 				op[index] |= 0x80;
1369 			index--;
1370 			numbuf >>= 7;
1371 		}
1372 		while (isdigit(*bp)) bp++;
1373 		while (isspace(*bp) || *bp == '.') bp++;
1374 	}
1375 
1376 	return (rv);
1377 }
1378 
1379 static KMF_RETURN
1380 encode_rid(char *name, KMF_DATA *derdata)
1381 {
1382 	KMF_RETURN rv = KMF_OK;
1383 
1384 	if (name == NULL || derdata == NULL)
1385 		return (KMF_ERR_BAD_PARAMETER);
1386 
1387 	rv = KMF_String2OID(name, (KMF_OID *)derdata);
1388 
1389 	return (rv);
1390 }
1391 
1392 static KMF_RETURN
1393 encode_ipaddr(char *name, KMF_DATA *derdata)
1394 {
1395 	KMF_RETURN rv = KMF_OK;
1396 	size_t len;
1397 	in_addr_t v4;
1398 	in6_addr_t v6;
1399 	uint8_t *ptr;
1400 
1401 	if (name == NULL || derdata == NULL)
1402 		return (KMF_ERR_BAD_PARAMETER);
1403 
1404 	v4 = inet_addr(name);
1405 	if (v4 == (in_addr_t)-1) {
1406 		ptr = (uint8_t *)&v6;
1407 		if (inet_pton(AF_INET6, name, ptr) != 1)
1408 			return (KMF_ERR_ENCODING);
1409 		len = sizeof (v6);
1410 	} else {
1411 		ptr = (uint8_t *)&v4;
1412 		len = sizeof (v4);
1413 	}
1414 
1415 	derdata->Data = malloc(len);
1416 	if (derdata->Data == NULL)
1417 		return (KMF_ERR_MEMORY);
1418 	(void) memcpy(derdata->Data, ptr, len);
1419 	derdata->Length = len;
1420 
1421 	return (rv);
1422 }
1423 
1424 static KMF_RETURN
1425 verify_uri_format(char *uristring)
1426 {
1427 	KMF_RETURN ret = KMF_OK;
1428 	xmlURIPtr   uriptr = NULL;
1429 
1430 	/* Parse the URI string; get the hostname and port */
1431 	uriptr = xmlParseURI(uristring);
1432 	if (uriptr == NULL) {
1433 		ret = KMF_ERR_BAD_URI;
1434 		goto out;
1435 	}
1436 
1437 	if (uriptr->scheme == NULL || !strlen(uriptr->scheme)) {
1438 		ret = KMF_ERR_BAD_URI;
1439 		goto out;
1440 	}
1441 
1442 	if (uriptr->server == NULL || !strlen(uriptr->server)) {
1443 		ret = KMF_ERR_BAD_URI;
1444 		goto out;
1445 	}
1446 out:
1447 	if (uriptr != NULL)
1448 		xmlFreeURI(uriptr);
1449 	return (ret);
1450 }
1451 
1452 static KMF_RETURN
1453 encode_altname(char *namedata,
1454 	KMF_GENERALNAMECHOICES nametype, KMF_DATA *encodedname)
1455 {
1456 	KMF_RETURN ret = KMF_OK;
1457 	KMF_X509_NAME dnname;
1458 	uchar_t tagval;
1459 	BerElement *asn1 = NULL;
1460 	BerValue *extdata;
1461 
1462 	if (namedata == NULL || encodedname == NULL)
1463 		return (KMF_ERR_BAD_PARAMETER);
1464 
1465 	/*
1466 	 * Encode the namedata according to rules in RFC 3280 for GeneralName.
1467 	 * The input "namedata" is assumed to be an ASCII string representation
1468 	 * of the AltName, we need to convert it to correct ASN.1 here before
1469 	 * adding it to the cert.
1470 	 */
1471 	switch (nametype) {
1472 		case GENNAME_RFC822NAME: /* rfc 822 */
1473 			/* IA5String, no encoding needed */
1474 			encodedname->Data = (uchar_t *)strdup(namedata);
1475 			if (encodedname->Data == NULL)
1476 				return (KMF_ERR_MEMORY);
1477 			encodedname->Length = strlen(namedata);
1478 			tagval = (0x80 | nametype);
1479 			break;
1480 		case GENNAME_DNSNAME: /* rfc 1034 */
1481 			encodedname->Data = (uchar_t *)strdup(namedata);
1482 			if (encodedname->Data == NULL)
1483 				return (KMF_ERR_MEMORY);
1484 			encodedname->Length = strlen(namedata);
1485 			tagval = (0x80 | nametype);
1486 			break;
1487 		case GENNAME_URI: /* rfc 1738 */
1488 			ret = verify_uri_format(namedata);
1489 			if (ret != KMF_OK)
1490 				return (ret);
1491 			/* IA5String, no encoding needed */
1492 			encodedname->Data = (uchar_t *)strdup(namedata);
1493 			if (encodedname->Data == NULL)
1494 				return (KMF_ERR_MEMORY);
1495 			encodedname->Length = strlen(namedata);
1496 			tagval = (0x80 | nametype);
1497 			break;
1498 		case GENNAME_IPADDRESS:
1499 			ret =  encode_ipaddr(namedata, encodedname);
1500 			tagval = (0x80 | nametype);
1501 			break;
1502 		case GENNAME_REGISTEREDID:
1503 			ret = encode_rid(namedata, encodedname);
1504 			tagval = (0x80 | nametype);
1505 			break;
1506 		case GENNAME_DIRECTORYNAME:
1507 			ret = KMF_DNParser(namedata, &dnname);
1508 			if (ret == KMF_OK) {
1509 				ret = KMF_DN2Der(&dnname, encodedname);
1510 			}
1511 			(void) KMF_FreeDN(&dnname);
1512 			tagval = (0xA0 | nametype);
1513 			break;
1514 		default:
1515 			/* unsupported */
1516 			return (KMF_ERR_BAD_PARAMETER);
1517 
1518 	}
1519 	if (ret != KMF_OK) {
1520 		KMF_FreeData(encodedname);
1521 		return (ret);
1522 	}
1523 
1524 	if ((asn1 = kmfder_alloc()) == NULL)
1525 		return (KMF_ERR_MEMORY);
1526 
1527 	if (kmfber_printf(asn1, "Tl",
1528 		tagval, encodedname->Length) == -1)
1529 		goto cleanup;
1530 
1531 	if (kmfber_write(asn1, (char *)encodedname->Data,
1532 		encodedname->Length, 0) == -1) {
1533 		ret = KMF_ERR_ENCODING;
1534 		goto cleanup;
1535 	}
1536 	if (kmfber_flatten(asn1, &extdata) == -1) {
1537 		ret = KMF_ERR_ENCODING;
1538 		goto cleanup;
1539 	}
1540 
1541 	KMF_FreeData(encodedname);
1542 	encodedname->Data = (uchar_t *)extdata->bv_val;
1543 	encodedname->Length = extdata->bv_len;
1544 
1545 	free(extdata);
1546 
1547 cleanup:
1548 	if (asn1)
1549 		kmfber_free(asn1, 1);
1550 
1551 	if (ret != KMF_OK)
1552 		KMF_FreeData(encodedname);
1553 
1554 	return (ret);
1555 }
1556 
1557 KMF_X509_EXTENSION *
1558 FindExtn(KMF_X509_EXTENSIONS *exts, KMF_OID *oid)
1559 {
1560 	KMF_X509_EXTENSION *foundextn = NULL;
1561 	int i;
1562 
1563 	if (exts == NULL || oid == NULL)
1564 		return (NULL);
1565 
1566 	for (i = 0; i < exts->numberOfExtensions; i++) {
1567 		if (IsEqualOid(oid, &exts->extensions[i].extnId))  {
1568 			foundextn = &exts->extensions[i];
1569 			break;
1570 		}
1571 	}
1572 	return (foundextn);
1573 }
1574 
1575 KMF_RETURN
1576 GetSequenceContents(char *data, size_t len,
1577 	char **contents, size_t *outlen)
1578 {
1579 	KMF_RETURN ret = KMF_OK;
1580 	BerElement *exasn1 = NULL;
1581 	BerValue oldextn;
1582 	int tag;
1583 	size_t oldsize;
1584 	char *olddata = NULL;
1585 
1586 	if (data == NULL || contents == NULL || outlen == NULL)
1587 		return (KMF_ERR_BAD_PARAMETER);
1588 
1589 	/*
1590 	 * Decode the sequence of general names
1591 	 */
1592 	oldextn.bv_val = data;
1593 	oldextn.bv_len = len;
1594 
1595 	if ((exasn1 = kmfder_init(&oldextn)) == NULL) {
1596 		ret = KMF_ERR_MEMORY;
1597 		goto out;
1598 	}
1599 
1600 	/*
1601 	 * Unwrap the sequence to find the size of the block
1602 	 * of GeneralName items in the set.
1603 	 *
1604 	 * Peek at the tag and length ("tl"),
1605 	 * then consume them ("{").
1606 	 */
1607 	if (kmfber_scanf(exasn1, "tl{", &tag, &oldsize) == KMFBER_DEFAULT ||
1608 		oldsize == 0) {
1609 		ret = KMF_ERR_ENCODING;
1610 		goto out;
1611 	}
1612 
1613 	olddata = malloc(oldsize);
1614 	if (olddata == NULL) {
1615 		ret = KMF_ERR_MEMORY;
1616 		goto out;
1617 	}
1618 	(void) memset(olddata, 0, oldsize);
1619 	/*
1620 	 * Read the entire blob of GeneralNames, we don't
1621 	 * need to interpret them now.
1622 	 */
1623 	if (kmfber_read(exasn1, olddata, oldsize) != oldsize) {
1624 		ret = KMF_ERR_ENCODING;
1625 		goto out;
1626 	}
1627 out:
1628 	if (exasn1 != NULL)
1629 		kmfber_free(exasn1, 1);
1630 
1631 	if (ret != KMF_OK) {
1632 		*contents = NULL;
1633 		*outlen = 0;
1634 		if (olddata != NULL)
1635 			free(olddata);
1636 	} else {
1637 		*contents = olddata;
1638 		*outlen = oldsize;
1639 	}
1640 	return (ret);
1641 }
1642 
1643 KMF_RETURN
1644 add_an_extension(KMF_X509_EXTENSIONS *exts, KMF_X509_EXTENSION *newextn)
1645 {
1646 	KMF_RETURN ret = KMF_OK;
1647 	KMF_X509_EXTENSION *extlist;
1648 
1649 	if (exts == NULL || newextn == NULL)
1650 		return (KMF_ERR_BAD_PARAMETER);
1651 
1652 	extlist = malloc(sizeof (KMF_X509_EXTENSION) *
1653 			(exts->numberOfExtensions + 1));
1654 	if (extlist == NULL)
1655 		return (KMF_ERR_MEMORY);
1656 
1657 	(void) memcpy(extlist, exts->extensions,
1658 	    exts->numberOfExtensions * sizeof (KMF_X509_EXTENSION));
1659 
1660 	(void) memcpy(&extlist[exts->numberOfExtensions], newextn,
1661 		sizeof (KMF_X509_EXTENSION));
1662 
1663 	free(exts->extensions);
1664 	exts->numberOfExtensions++;
1665 	exts->extensions = extlist;
1666 
1667 	return (ret);
1668 }
1669 
1670 KMF_RETURN
1671 KMF_SetAltName(KMF_X509_EXTENSIONS *extensions,
1672 	KMF_OID *oid,
1673 	int critical,
1674 	KMF_GENERALNAMECHOICES nametype,
1675 	char *namedata)
1676 {
1677 	KMF_RETURN ret = KMF_OK;
1678 	KMF_X509_EXTENSION subjAltName;
1679 	KMF_DATA dername = { NULL, 0 };
1680 	BerElement *asn1 = NULL;
1681 	BerValue *extdata;
1682 	char *olddata = NULL;
1683 	KMF_X509_EXTENSION *foundextn = NULL;
1684 	size_t	oldsize = 0;
1685 
1686 	if (extensions == NULL || oid == NULL || namedata == NULL)
1687 		return (KMF_ERR_BAD_PARAMETER);
1688 
1689 	ret = encode_altname(namedata, nametype, &dername);
1690 
1691 	if (ret != KMF_OK)
1692 		return (ret);
1693 
1694 	(void) memset(&subjAltName, 0, sizeof (subjAltName));
1695 
1696 	ret = copy_data(&subjAltName.extnId, oid);
1697 	if (ret != KMF_OK)
1698 		goto out;
1699 	/*
1700 	 * Check to see if this cert already has a subjectAltName.
1701 	 */
1702 	foundextn = FindExtn(extensions, oid);
1703 
1704 	if (foundextn != NULL) {
1705 		ret = GetSequenceContents(
1706 				(char *)foundextn->BERvalue.Data,
1707 				foundextn->BERvalue.Length,
1708 				&olddata, &oldsize);
1709 		if (ret != KMF_OK)
1710 			goto out;
1711 	}
1712 
1713 	/*
1714 	 * Assume (!!) that the namedata given is already properly encoded.
1715 	 */
1716 	if ((asn1 = kmfder_alloc()) == NULL)
1717 		return (KMF_ERR_MEMORY);
1718 
1719 	if (kmfber_printf(asn1, "{") == -1) {
1720 		ret = KMF_ERR_ENCODING;
1721 		goto out;
1722 	}
1723 
1724 	/* Write the old extension data first */
1725 	if (olddata != NULL && oldsize > 0) {
1726 		if (kmfber_write(asn1, olddata, oldsize, 0) == -1) {
1727 			ret = KMF_ERR_ENCODING;
1728 			goto out;
1729 		}
1730 	}
1731 
1732 	/* Now add the new name to the list */
1733 	if (kmfber_write(asn1, (char *)dername.Data, dername.Length, 0) == -1) {
1734 		ret = KMF_ERR_ENCODING;
1735 		goto out;
1736 	}
1737 
1738 	/* Now close the sequence */
1739 	if (kmfber_printf(asn1, "}") == -1) {
1740 		ret = KMF_ERR_ENCODING;
1741 		goto out;
1742 	}
1743 	if (kmfber_flatten(asn1, &extdata) == -1) {
1744 		ret = KMF_ERR_ENCODING;
1745 		goto out;
1746 	}
1747 
1748 	/*
1749 	 * If we are just adding to an existing list of altNames,
1750 	 * just replace the BER data associated with the found extension.
1751 	 */
1752 	if (foundextn != NULL) {
1753 		free(foundextn->BERvalue.Data);
1754 		foundextn->critical = critical;
1755 		foundextn->BERvalue.Data = (uchar_t *)extdata->bv_val;
1756 		foundextn->BERvalue.Length = extdata->bv_len;
1757 	} else {
1758 		subjAltName.critical = critical;
1759 		subjAltName.format = KMF_X509_DATAFORMAT_ENCODED;
1760 		subjAltName.BERvalue.Data = (uchar_t *)extdata->bv_val;
1761 		subjAltName.BERvalue.Length = extdata->bv_len;
1762 		ret = add_an_extension(extensions, &subjAltName);
1763 		if (ret != KMF_OK)
1764 			free(subjAltName.BERvalue.Data);
1765 	}
1766 
1767 	free(extdata);
1768 out:
1769 	if (olddata != NULL)
1770 		free(olddata);
1771 
1772 	KMF_FreeData(&dername);
1773 	if (ret != KMF_OK)
1774 		KMF_FreeData(&subjAltName.extnId);
1775 	if (asn1 != NULL)
1776 		kmfber_free(asn1, 1);
1777 	return (ret);
1778 }
1779