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