xref: /titanic_44/usr/src/lib/libkmf/libkmf/common/generalop.c (revision e1c679fa4b0ab8c4bcaa6263974ca0c46e5b027f)
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 KMF_RETURN
691 KMF_GetFileFormat(char *filename, KMF_ENCODE_FORMAT *fmt)
692 {
693 	int f;
694 	KMF_RETURN ret = KMF_OK;
695 	uchar_t buf[16];
696 
697 	if (filename == NULL || !strlen(filename) || fmt == NULL)
698 		return (KMF_ERR_BAD_PARAMETER);
699 
700 	*fmt = 0;
701 	if ((f = open(filename, O_RDONLY)) == -1) {
702 		return (KMF_ERR_OPEN_FILE);
703 	}
704 
705 	if (read(f, buf, 8) != 8) {
706 		ret = KMF_ERR_OPEN_FILE;
707 		goto end;
708 	}
709 
710 	if (memcmp(buf, "-----BEG", 8) == 0) {
711 		*fmt = KMF_FORMAT_PEM;
712 	} else if (buf[0] == 0x30 && (buf[1] & 0x80)) {
713 		if ((buf[1] & 0xFF) == 0x80 &&
714 		    (buf[2] & 0xFF) == 0x02 &&
715 		    (buf[5] & 0xFF) == 0x30) {
716 			*fmt = KMF_FORMAT_PKCS12;
717 		} else if ((buf[1] & 0xFF) == 0x82 &&
718 			(buf[4] & 0xFF) == 0x02 &&
719 			(buf[7] & 0xFF) == 0x30) {
720 			*fmt = KMF_FORMAT_PKCS12;
721 		/* It is most likely a generic ASN.1 encoded file */
722 		} else {
723 			*fmt = KMF_FORMAT_ASN1;
724 		}
725 	} else if (memcmp(buf, "Bag Attr", 8) == 0) {
726 		*fmt = KMF_FORMAT_PEM_KEYPAIR;
727 	} else {
728 		/* Cannot determine this file format */
729 		*fmt = 0;
730 		ret = KMF_ERR_ENCODING;
731 	}
732 end:
733 	(void) close(f);
734 	return (ret);
735 }
736 
737 KMF_RETURN
738 KMF_HexString2Bytes(unsigned char *hexstr, unsigned char **bytes,
739 	size_t *outlen)
740 {
741 	KMF_RETURN ret = KMF_OK;
742 	unsigned char *buf = NULL;
743 	int len, stringlen;
744 	int i;
745 	unsigned char ch;
746 
747 	if (hexstr == NULL) {
748 		return (KMF_ERR_BAD_PARAMETER);
749 	}
750 
751 	if (hexstr[0] == '0' &&
752 		((hexstr[1] == 'x') || (hexstr[1] == 'X')))
753 		hexstr += 2;
754 
755 	for (i = 0; i < strlen((char *)hexstr) && isxdigit(hexstr[i]); i++);
756 	/*
757 	 * If all the characters are not legitimate hex chars,
758 	 * return an error.
759 	 */
760 	if (i != strlen((char *)hexstr))
761 		return (KMF_ERR_BAD_HEX_STRING);
762 	stringlen = i;
763 	len = (i / 2) + (i % 2);
764 
765 	buf = malloc(len);
766 	if (buf == NULL) {
767 		return (KMF_ERR_MEMORY);
768 	}
769 	(void) memset(buf, 0, len);
770 
771 	for (i = 0; i < stringlen; i++) {
772 		ch = (unsigned char) *hexstr;
773 		hexstr++;
774 		if ((ch >= '0') && (ch <= '9'))
775 			ch -= '0';
776 		else if ((ch >= 'A') && (ch <= 'F'))
777 			ch = ch - 'A' + 10;
778 		else if ((ch >= 'a') && (ch <= 'f'))
779 			ch = ch - 'a' + 10;
780 		else {
781 			ret = KMF_ERR_BAD_HEX_STRING;
782 			goto out;
783 		}
784 
785 		if (i & 1) {
786 			buf[i/2] |= ch;
787 		} else {
788 			buf[i/2] = (ch << 4);
789 		}
790 	}
791 
792 	*bytes = buf;
793 	*outlen = len;
794 out:
795 	if (buf != NULL && ret != KMF_OK) {
796 		free(buf);
797 	}
798 	return (ret);
799 }
800 
801 void
802 KMF_FreeDN(KMF_X509_NAME *name)
803 {
804 	KMF_X509_RDN 		*newrdn = NULL;
805 	KMF_X509_TYPE_VALUE_PAIR *av = NULL;
806 	int i, j;
807 
808 	if (name && name->numberOfRDNs) {
809 		for (i = 0; i < name->numberOfRDNs; i++) {
810 			newrdn = &name->RelativeDistinguishedName[i];
811 			for (j = 0; j < newrdn->numberOfPairs; j++) {
812 				av = &newrdn->AttributeTypeAndValue[j];
813 				KMF_FreeData(&av->type);
814 				KMF_FreeData(&av->value);
815 			}
816 			free(newrdn->AttributeTypeAndValue);
817 			newrdn->numberOfPairs = 0;
818 			newrdn->AttributeTypeAndValue = NULL;
819 		}
820 		free(name->RelativeDistinguishedName);
821 		name->numberOfRDNs = 0;
822 		name->RelativeDistinguishedName = NULL;
823 	}
824 }
825 
826 void
827 KMF_FreeKMFCert(KMF_HANDLE_T handle, KMF_X509_DER_CERT *kmf_cert)
828 {
829 	KMF_PLUGIN *plugin;
830 	KMF_RETURN ret;
831 
832 	CLEAR_ERROR(handle, ret);
833 	if (ret != KMF_OK)
834 		return;
835 
836 	if (kmf_cert == NULL)
837 		return;
838 
839 	plugin = FindPlugin(handle, kmf_cert->kmf_private.keystore_type);
840 
841 	if (plugin != NULL && plugin->funclist->FreeKMFCert != NULL) {
842 		plugin->funclist->FreeKMFCert(handle, kmf_cert);
843 	}
844 }
845 
846 void
847 KMF_FreeData(KMF_DATA *datablock)
848 {
849 	if (datablock != NULL && datablock->Data != NULL) {
850 		free(datablock->Data);
851 		datablock->Data = NULL;
852 		datablock->Length = 0;
853 	}
854 }
855 
856 void
857 KMF_FreeAlgOID(KMF_X509_ALGORITHM_IDENTIFIER *algoid)
858 {
859 	if (algoid == NULL)
860 		return;
861 	KMF_FreeData(&algoid->algorithm);
862 	KMF_FreeData(&algoid->parameters);
863 }
864 
865 void
866 KMF_FreeExtension(KMF_X509_EXTENSION *exptr)
867 {
868 	if (exptr == NULL)
869 		return;
870 
871 	KMF_FreeData((KMF_DATA *)&exptr->extnId);
872 	KMF_FreeData(&exptr->BERvalue);
873 
874 	if (exptr->value.tagAndValue) {
875 		KMF_FreeData(&exptr->value.tagAndValue->value);
876 		free(exptr->value.tagAndValue);
877 	}
878 }
879 
880 void
881 KMF_FreeTBSCSR(KMF_TBS_CSR *tbscsr)
882 {
883 	if (tbscsr) {
884 		KMF_FreeData(&tbscsr->version);
885 
886 		KMF_FreeDN(&tbscsr->subject);
887 
888 		KMF_FreeAlgOID(&tbscsr->subjectPublicKeyInfo.algorithm);
889 		KMF_FreeData(&tbscsr->subjectPublicKeyInfo.subjectPublicKey);
890 
891 		free_extensions(&tbscsr->extensions);
892 	}
893 }
894 
895 void
896 KMF_FreeSignedCSR(KMF_CSR_DATA *csr)
897 {
898 	if (csr) {
899 		KMF_FreeTBSCSR(&csr->csr);
900 
901 		KMF_FreeAlgOID(&csr->signature.algorithmIdentifier);
902 		KMF_FreeData(&csr->signature.encrypted);
903 	}
904 }
905 
906 static void
907 free_validity(KMF_X509_VALIDITY *validity)
908 {
909 	if (validity == NULL)
910 		return;
911 	KMF_FreeData(&validity->notBefore.time);
912 	KMF_FreeData(&validity->notAfter.time);
913 }
914 
915 static void
916 free_extensions(KMF_X509_EXTENSIONS *extns)
917 {
918 	int i;
919 	KMF_X509_EXTENSION *exptr;
920 
921 	if (extns && extns->numberOfExtensions > 0) {
922 		for (i = 0; i < extns->numberOfExtensions; i++) {
923 			exptr = &extns->extensions[i];
924 			KMF_FreeExtension(exptr);
925 		}
926 		free(extns->extensions);
927 		extns->numberOfExtensions = 0;
928 		extns->extensions = NULL;
929 	}
930 }
931 
932 void
933 KMF_FreeTBSCert(KMF_X509_TBS_CERT *tbscert)
934 {
935 	if (tbscert) {
936 		KMF_FreeData(&tbscert->version);
937 		KMF_FreeBigint(&tbscert->serialNumber);
938 		KMF_FreeAlgOID(&tbscert->signature);
939 
940 		KMF_FreeDN(&tbscert->issuer);
941 		KMF_FreeDN(&tbscert->subject);
942 
943 		free_validity(&tbscert->validity);
944 
945 		KMF_FreeData(&tbscert->issuerUniqueIdentifier);
946 		KMF_FreeData(&tbscert->subjectUniqueIdentifier);
947 
948 		KMF_FreeAlgOID(&tbscert->subjectPublicKeyInfo.algorithm);
949 		KMF_FreeData(&tbscert->subjectPublicKeyInfo.subjectPublicKey);
950 
951 		free_extensions(&tbscert->extensions);
952 
953 		KMF_FreeData(&tbscert->issuerUniqueIdentifier);
954 		KMF_FreeData(&tbscert->subjectUniqueIdentifier);
955 	}
956 }
957 
958 void
959 KMF_FreeSignedCert(KMF_X509_CERTIFICATE *certptr)
960 {
961 	if (!certptr)
962 		return;
963 
964 	KMF_FreeTBSCert(&certptr->certificate);
965 
966 	KMF_FreeAlgOID(&certptr->signature.algorithmIdentifier);
967 	KMF_FreeData(&certptr->signature.encrypted);
968 }
969 
970 void
971 KMF_FreeString(char *pstr)
972 {
973 	if (pstr != NULL)
974 		free(pstr);
975 }
976 
977 void
978 free_keyidlist(KMF_OID *oidlist, int len)
979 {
980 	int i;
981 	for (i = 0; i < len; i++) {
982 		KMF_FreeData((KMF_DATA *)&oidlist[i]);
983 	}
984 	free(oidlist);
985 }
986 
987 void
988 KMF_FreeEKU(KMF_X509EXT_EKU *eptr)
989 {
990 	if (eptr && eptr->nEKUs > 0 &&
991 		eptr->keyPurposeIdList != NULL)
992 		free_keyidlist(eptr->keyPurposeIdList, eptr->nEKUs);
993 }
994 
995 void
996 KMF_FreeSPKI(KMF_X509_SPKI *spki)
997 {
998 	if (spki != NULL) {
999 		KMF_FreeAlgOID(&spki->algorithm);
1000 		KMF_FreeData(&spki->subjectPublicKey);
1001 	}
1002 }
1003 
1004 void
1005 KMF_FreeKMFKey(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key)
1006 {
1007 	KMF_PLUGIN *plugin;
1008 	KMF_RETURN ret;
1009 
1010 	CLEAR_ERROR(handle, ret);
1011 	if (ret != KMF_OK)
1012 		return;
1013 
1014 	if (key == NULL)
1015 		return;
1016 
1017 	plugin = FindPlugin(handle, key->kstype);
1018 	if (plugin != NULL && plugin->funclist->DeleteKey != NULL) {
1019 		(void) plugin->funclist->DeleteKey(handle, NULL, key, FALSE);
1020 	}
1021 
1022 	if (key == NULL)
1023 		return;
1024 
1025 	if (key->keylabel)
1026 		free(key->keylabel);
1027 
1028 	if (key->israw) {
1029 		KMF_FreeRawKey(key->keyp);
1030 		free(key->keyp);
1031 	}
1032 
1033 	(void) memset(key, 0, sizeof (KMF_KEY_HANDLE));
1034 }
1035 
1036 void
1037 KMF_FreeBigint(KMF_BIGINT *big)
1038 {
1039 	if (big != NULL && big->val != NULL) {
1040 		free(big->val);
1041 		big->val = NULL;
1042 		big->len = 0;
1043 	}
1044 }
1045 
1046 static void
1047 free_raw_rsa(KMF_RAW_RSA_KEY *key)
1048 {
1049 	if (key == NULL)
1050 		return;
1051 	KMF_FreeBigint(&key->mod);
1052 	KMF_FreeBigint(&key->pubexp);
1053 	KMF_FreeBigint(&key->priexp);
1054 	KMF_FreeBigint(&key->prime1);
1055 	KMF_FreeBigint(&key->prime2);
1056 	KMF_FreeBigint(&key->exp1);
1057 	KMF_FreeBigint(&key->exp2);
1058 	KMF_FreeBigint(&key->coef);
1059 }
1060 
1061 static void
1062 free_raw_dsa(KMF_RAW_DSA_KEY *key)
1063 {
1064 	if (key == NULL)
1065 		return;
1066 	KMF_FreeBigint(&key->prime);
1067 	KMF_FreeBigint(&key->subprime);
1068 	KMF_FreeBigint(&key->base);
1069 	KMF_FreeBigint(&key->value);
1070 }
1071 
1072 static void
1073 free_raw_sym(KMF_RAW_SYM_KEY *key)
1074 {
1075 	if (key == NULL)
1076 		return;
1077 	KMF_FreeBigint(&key->keydata);
1078 }
1079 
1080 void
1081 KMF_FreeRawKey(KMF_RAW_KEY_DATA *key)
1082 {
1083 	if (key == NULL)
1084 		return;
1085 
1086 	switch (key->keytype) {
1087 	case KMF_RSA:
1088 		free_raw_rsa(&key->rawdata.rsa);
1089 		break;
1090 	case KMF_DSA:
1091 		free_raw_dsa(&key->rawdata.dsa);
1092 		break;
1093 	case KMF_AES:
1094 	case KMF_RC4:
1095 	case KMF_DES:
1096 	case KMF_DES3:
1097 		free_raw_sym(&key->rawdata.sym);
1098 		break;
1099 	}
1100 }
1101 
1102 void
1103 KMF_FreeRawSymKey(KMF_RAW_SYM_KEY *key)
1104 {
1105 	if (key == NULL)
1106 		return;
1107 	KMF_FreeBigint(&key->keydata);
1108 	free(key);
1109 }
1110 
1111 /*
1112  * This function frees the space allocated for the name portion of a
1113  * KMF_CRL_DIST_POINT.
1114  */
1115 void
1116 free_dp_name(KMF_CRL_DIST_POINT *dp)
1117 {
1118 	KMF_GENERALNAMES *fullname;
1119 	KMF_DATA *urldata;
1120 	int i;
1121 
1122 	if (dp == NULL)
1123 		return;
1124 
1125 	/* For phase 1, we only need to free the fullname space. */
1126 	fullname = &(dp->name.full_name);
1127 	if (fullname->number == 0)
1128 		return;
1129 
1130 	for (i = 0; i < fullname->number; i++) {
1131 		urldata = &(fullname->namelist[fullname->number - 1].name);
1132 		KMF_FreeData(urldata);
1133 	}
1134 
1135 	free(fullname->namelist);
1136 }
1137 
1138 /*
1139  * This function frees the space allocated for a KMF_CRL_DIST_POINT.
1140  */
1141 void
1142 free_dp(KMF_CRL_DIST_POINT *dp)
1143 {
1144 	if (dp == NULL)
1145 		return;
1146 
1147 	free_dp_name(dp);
1148 	KMF_FreeData(&(dp->reasons));
1149 	/* Need not to free crl_issuer space at phase 1 */
1150 }
1151 
1152 /*
1153  * This function frees space for a KMF_X509EXT_CRLDISTPOINTS internally.
1154  */
1155 void
1156 KMF_FreeCRLDistributionPoints(KMF_X509EXT_CRLDISTPOINTS *crl_dps)
1157 {
1158 	int i;
1159 
1160 	if (crl_dps == NULL)
1161 		return;
1162 
1163 	for (i = 0; i < crl_dps->number; i++)
1164 		free_dp(&(crl_dps->dplist[i]));
1165 
1166 	free(crl_dps->dplist);
1167 }
1168 
1169 KMF_RETURN
1170 KMF_CreateOCSPRequest(KMF_HANDLE_T handle,  KMF_OCSPREQUEST_PARAMS *params,
1171     char *reqfile)
1172 {
1173 	KMF_PLUGIN *plugin;
1174 	KMF_RETURN (*createReqFn)(void *, KMF_OCSPREQUEST_PARAMS *params,
1175 	    char *reqfile);
1176 	KMF_RETURN ret;
1177 
1178 	CLEAR_ERROR(handle, ret);
1179 	if (ret != KMF_OK)
1180 		return (ret);
1181 
1182 
1183 	if (params == NULL ||
1184 		reqfile == NULL)
1185 		return (KMF_ERR_BAD_PARAMETER);
1186 
1187 	/*
1188 	 * This framework function is actually implemented in the openssl
1189 	 * plugin library, so we find the function address and call it.
1190 	 */
1191 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
1192 	if (plugin == NULL || plugin->dldesc == NULL) {
1193 		return (KMF_ERR_PLUGIN_NOTFOUND);
1194 	}
1195 
1196 	createReqFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
1197 	    "OpenSSL_CreateOCSPRequest");
1198 	if (createReqFn == NULL) {
1199 		return (KMF_ERR_FUNCTION_NOT_FOUND);
1200 	}
1201 
1202 	return (createReqFn(handle, params, reqfile));
1203 }
1204 
1205 KMF_RETURN
1206 KMF_GetOCSPStatusForCert(KMF_HANDLE_T handle,
1207     KMF_OCSPRESPONSE_PARAMS_INPUT *params_in,
1208     KMF_OCSPRESPONSE_PARAMS_OUTPUT *params_out)
1209 {
1210 	KMF_PLUGIN *plugin;
1211 	KMF_RETURN (*getCertStatusFn)(void *,
1212 	    KMF_OCSPRESPONSE_PARAMS_INPUT *params_in,
1213 	    KMF_OCSPRESPONSE_PARAMS_OUTPUT *params_out);
1214 	KMF_RETURN ret;
1215 
1216 	CLEAR_ERROR(handle, ret);
1217 	if (ret != KMF_OK)
1218 		return (ret);
1219 
1220 
1221 	if (params_in == NULL ||
1222 		params_out == NULL)
1223 		return (KMF_ERR_BAD_PARAMETER);
1224 
1225 	/*
1226 	 * This framework function is actually implemented in the openssl
1227 	 * plugin library, so we find the function address and call it.
1228 	 */
1229 	plugin = FindPlugin(handle, KMF_KEYSTORE_OPENSSL);
1230 	if (plugin == NULL || plugin->dldesc == NULL) {
1231 		return (KMF_ERR_INTERNAL);
1232 	}
1233 
1234 	getCertStatusFn = (KMF_RETURN(*)())dlsym(plugin->dldesc,
1235 	    "OpenSSL_GetOCSPStatusForCert");
1236 	if (getCertStatusFn == NULL) {
1237 		return (KMF_ERR_INTERNAL);
1238 	}
1239 
1240 	return (getCertStatusFn(handle, params_in, params_out));
1241 }
1242 
1243 KMF_RETURN
1244 KMF_String2OID(char *oidstring, KMF_OID *oid)
1245 {
1246 	KMF_RETURN rv = KMF_OK;
1247 	char *cp, *bp, *startp;
1248 	int numbuf;
1249 	int onumbuf;
1250 	int nbytes, index;
1251 	int len;
1252 	unsigned char *op;
1253 
1254 	if (oidstring == NULL || oid == NULL)
1255 		return (KMF_ERR_BAD_PARAMETER);
1256 
1257 	len = strlen(oidstring);
1258 
1259 	bp = oidstring;
1260 	cp = bp;
1261 	/* Skip over leading space */
1262 	while ((bp < &cp[len]) && isspace(*bp))
1263 		bp++;
1264 
1265 	startp = bp;
1266 	nbytes = 0;
1267 
1268 	/*
1269 	 * The first two numbers are chewed up by the first octet.
1270 	 */
1271 	if (sscanf(bp, "%d", &numbuf) != 1)
1272 		return (KMF_ERR_BAD_PARAMETER);
1273 	while ((bp < &cp[len]) && isdigit(*bp))
1274 		bp++;
1275 	while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
1276 		bp++;
1277 	if (sscanf(bp, "%d", &numbuf) != 1)
1278 		return (KMF_ERR_BAD_PARAMETER);
1279 	while ((bp < &cp[len]) && isdigit(*bp))
1280 		bp++;
1281 	while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
1282 		bp++;
1283 	nbytes++;
1284 
1285 	while (isdigit(*bp)) {
1286 		if (sscanf(bp, "%d", &numbuf) != 1)
1287 			return (KMF_ERR_BAD_PARAMETER);
1288 		while (numbuf) {
1289 			nbytes++;
1290 			numbuf >>= 7;
1291 		}
1292 		while ((bp < &cp[len]) && isdigit(*bp))
1293 			bp++;
1294 		while ((bp < &cp[len]) && (isspace(*bp) || *bp == '.'))
1295 			bp++;
1296 	}
1297 
1298 	oid->Length = nbytes;
1299 	oid->Data = malloc(oid->Length);
1300 	if (oid->Data == NULL) {
1301 		return (KMF_ERR_MEMORY);
1302 	}
1303 	(void) memset(oid->Data, 0, oid->Length);
1304 
1305 	op = oid->Data;
1306 
1307 	bp = startp;
1308 	(void) sscanf(bp, "%d", &numbuf);
1309 
1310 	while (isdigit(*bp)) bp++;
1311 	while (isspace(*bp) || *bp == '.') bp++;
1312 
1313 	onumbuf = 40 * numbuf;
1314 	(void) sscanf(bp, "%d", &numbuf);
1315 	onumbuf += numbuf;
1316 	*op = (unsigned char) onumbuf;
1317 	op++;
1318 
1319 	while (isdigit(*bp)) bp++;
1320 	while (isspace(*bp) || *bp == '.') bp++;
1321 	while (isdigit(*bp)) {
1322 		(void) sscanf(bp, "%d", &numbuf);
1323 		nbytes = 0;
1324 		/* Have to fill in the bytes msb-first */
1325 		onumbuf = numbuf;
1326 		while (numbuf) {
1327 			nbytes++;
1328 			numbuf >>= 7;
1329 		}
1330 		numbuf = onumbuf;
1331 		op += nbytes;
1332 		index = -1;
1333 		while (numbuf) {
1334 			op[index] = (unsigned char)numbuf & 0x7f;
1335 			if (index != -1)
1336 				op[index] |= 0x80;
1337 			index--;
1338 			numbuf >>= 7;
1339 		}
1340 		while (isdigit(*bp)) bp++;
1341 		while (isspace(*bp) || *bp == '.') bp++;
1342 	}
1343 
1344 	return (rv);
1345 }
1346 
1347 static KMF_RETURN
1348 encode_rid(char *name, KMF_DATA *derdata)
1349 {
1350 	KMF_RETURN rv = KMF_OK;
1351 
1352 	if (name == NULL || derdata == NULL)
1353 		return (KMF_ERR_BAD_PARAMETER);
1354 
1355 	rv = KMF_String2OID(name, (KMF_OID *)derdata);
1356 
1357 	return (rv);
1358 }
1359 
1360 static KMF_RETURN
1361 encode_ipaddr(char *name, KMF_DATA *derdata)
1362 {
1363 	KMF_RETURN rv = KMF_OK;
1364 	size_t len;
1365 	in_addr_t v4;
1366 	in6_addr_t v6;
1367 	uint8_t *ptr;
1368 
1369 	if (name == NULL || derdata == NULL)
1370 		return (KMF_ERR_BAD_PARAMETER);
1371 
1372 	v4 = inet_addr(name);
1373 	if (v4 == (in_addr_t)-1) {
1374 		ptr = (uint8_t *)&v6;
1375 		if (inet_pton(AF_INET6, name, ptr) != 1)
1376 			return (KMF_ERR_ENCODING);
1377 		len = sizeof (v6);
1378 	} else {
1379 		ptr = (uint8_t *)&v4;
1380 		len = sizeof (v4);
1381 	}
1382 
1383 	derdata->Data = malloc(len);
1384 	if (derdata->Data == NULL)
1385 		return (KMF_ERR_MEMORY);
1386 	(void) memcpy(derdata->Data, ptr, len);
1387 	derdata->Length = len;
1388 
1389 	return (rv);
1390 }
1391 
1392 static KMF_RETURN
1393 verify_uri_format(char *uristring)
1394 {
1395 	KMF_RETURN ret = KMF_OK;
1396 	xmlURIPtr   uriptr = NULL;
1397 
1398 	/* Parse the URI string; get the hostname and port */
1399 	uriptr = xmlParseURI(uristring);
1400 	if (uriptr == NULL) {
1401 		ret = KMF_ERR_BAD_URI;
1402 		goto out;
1403 	}
1404 
1405 	if (uriptr->scheme == NULL || !strlen(uriptr->scheme)) {
1406 		ret = KMF_ERR_BAD_URI;
1407 		goto out;
1408 	}
1409 
1410 	if (uriptr->server == NULL || !strlen(uriptr->server)) {
1411 		ret = KMF_ERR_BAD_URI;
1412 		goto out;
1413 	}
1414 out:
1415 	if (uriptr != NULL)
1416 		xmlFreeURI(uriptr);
1417 	return (ret);
1418 }
1419 
1420 static KMF_RETURN
1421 encode_altname(char *namedata,
1422 	KMF_GENERALNAMECHOICES nametype, KMF_DATA *encodedname)
1423 {
1424 	KMF_RETURN ret = KMF_OK;
1425 	KMF_X509_NAME dnname;
1426 	uchar_t tagval;
1427 	BerElement *asn1 = NULL;
1428 	BerValue *extdata;
1429 
1430 	if (namedata == NULL || encodedname == NULL)
1431 		return (KMF_ERR_BAD_PARAMETER);
1432 
1433 	/*
1434 	 * Encode the namedata according to rules in RFC 3280 for GeneralName.
1435 	 * The input "namedata" is assumed to be an ASCII string representation
1436 	 * of the AltName, we need to convert it to correct ASN.1 here before
1437 	 * adding it to the cert.
1438 	 */
1439 	switch (nametype) {
1440 		case GENNAME_RFC822NAME: /* rfc 822 */
1441 			/* IA5String, no encoding needed */
1442 			encodedname->Data = (uchar_t *)strdup(namedata);
1443 			if (encodedname->Data == NULL)
1444 				return (KMF_ERR_MEMORY);
1445 			encodedname->Length = strlen(namedata);
1446 			tagval = (0x80 | nametype);
1447 			break;
1448 		case GENNAME_DNSNAME: /* rfc 1034 */
1449 			encodedname->Data = (uchar_t *)strdup(namedata);
1450 			if (encodedname->Data == NULL)
1451 				return (KMF_ERR_MEMORY);
1452 			encodedname->Length = strlen(namedata);
1453 			tagval = (0x80 | nametype);
1454 			break;
1455 		case GENNAME_URI: /* rfc 1738 */
1456 			ret = verify_uri_format(namedata);
1457 			if (ret != KMF_OK)
1458 				return (ret);
1459 			/* IA5String, no encoding needed */
1460 			encodedname->Data = (uchar_t *)strdup(namedata);
1461 			if (encodedname->Data == NULL)
1462 				return (KMF_ERR_MEMORY);
1463 			encodedname->Length = strlen(namedata);
1464 			tagval = (0x80 | nametype);
1465 			break;
1466 		case GENNAME_IPADDRESS:
1467 			ret =  encode_ipaddr(namedata, encodedname);
1468 			tagval = (0x80 | nametype);
1469 			break;
1470 		case GENNAME_REGISTEREDID:
1471 			ret = encode_rid(namedata, encodedname);
1472 			tagval = (0x80 | nametype);
1473 			break;
1474 		case GENNAME_DIRECTORYNAME:
1475 			ret = KMF_DNParser(namedata, &dnname);
1476 			if (ret == KMF_OK) {
1477 				ret = KMF_DN2Der(&dnname, encodedname);
1478 			}
1479 			(void) KMF_FreeDN(&dnname);
1480 			tagval = (0xA0 | nametype);
1481 			break;
1482 		default:
1483 			/* unsupported */
1484 			return (KMF_ERR_BAD_PARAMETER);
1485 
1486 	}
1487 	if (ret != KMF_OK) {
1488 		KMF_FreeData(encodedname);
1489 		return (ret);
1490 	}
1491 
1492 	if ((asn1 = kmfder_alloc()) == NULL)
1493 		return (KMF_ERR_MEMORY);
1494 
1495 	if (kmfber_printf(asn1, "Tl",
1496 		tagval, encodedname->Length) == -1)
1497 		goto cleanup;
1498 
1499 	if (kmfber_write(asn1, (char *)encodedname->Data,
1500 		encodedname->Length, 0) == -1) {
1501 		ret = KMF_ERR_ENCODING;
1502 		goto cleanup;
1503 	}
1504 	if (kmfber_flatten(asn1, &extdata) == -1) {
1505 		ret = KMF_ERR_ENCODING;
1506 		goto cleanup;
1507 	}
1508 
1509 	KMF_FreeData(encodedname);
1510 	encodedname->Data = (uchar_t *)extdata->bv_val;
1511 	encodedname->Length = extdata->bv_len;
1512 
1513 	free(extdata);
1514 
1515 cleanup:
1516 	if (asn1)
1517 		kmfber_free(asn1, 1);
1518 
1519 	if (ret != KMF_OK)
1520 		KMF_FreeData(encodedname);
1521 
1522 	return (ret);
1523 }
1524 
1525 KMF_X509_EXTENSION *
1526 FindExtn(KMF_X509_EXTENSIONS *exts, KMF_OID *oid)
1527 {
1528 	KMF_X509_EXTENSION *foundextn = NULL;
1529 	int i;
1530 
1531 	if (exts == NULL || oid == NULL)
1532 		return (NULL);
1533 
1534 	for (i = 0; i < exts->numberOfExtensions; i++) {
1535 		if (IsEqualOid(oid, &exts->extensions[i].extnId))  {
1536 			foundextn = &exts->extensions[i];
1537 			break;
1538 		}
1539 	}
1540 	return (foundextn);
1541 }
1542 
1543 KMF_RETURN
1544 GetSequenceContents(char *data, size_t len,
1545 	char **contents, size_t *outlen)
1546 {
1547 	KMF_RETURN ret = KMF_OK;
1548 	BerElement *exasn1 = NULL;
1549 	BerValue oldextn;
1550 	int tag;
1551 	size_t oldsize;
1552 	char *olddata = NULL;
1553 
1554 	if (data == NULL || contents == NULL || outlen == NULL)
1555 		return (KMF_ERR_BAD_PARAMETER);
1556 
1557 	/*
1558 	 * Decode the sequence of general names
1559 	 */
1560 	oldextn.bv_val = data;
1561 	oldextn.bv_len = len;
1562 
1563 	if ((exasn1 = kmfder_init(&oldextn)) == NULL) {
1564 		ret = KMF_ERR_MEMORY;
1565 		goto out;
1566 	}
1567 
1568 	/*
1569 	 * Unwrap the sequence to find the size of the block
1570 	 * of GeneralName items in the set.
1571 	 *
1572 	 * Peek at the tag and length ("tl"),
1573 	 * then consume them ("{").
1574 	 */
1575 	if (kmfber_scanf(exasn1, "tl{", &tag, &oldsize) == KMFBER_DEFAULT ||
1576 		oldsize == 0) {
1577 		ret = KMF_ERR_ENCODING;
1578 		goto out;
1579 	}
1580 
1581 	olddata = malloc(oldsize);
1582 	if (olddata == NULL) {
1583 		ret = KMF_ERR_MEMORY;
1584 		goto out;
1585 	}
1586 	(void) memset(olddata, 0, oldsize);
1587 	/*
1588 	 * Read the entire blob of GeneralNames, we don't
1589 	 * need to interpret them now.
1590 	 */
1591 	if (kmfber_read(exasn1, olddata, oldsize) != oldsize) {
1592 		ret = KMF_ERR_ENCODING;
1593 		goto out;
1594 	}
1595 out:
1596 	if (exasn1 != NULL)
1597 		kmfber_free(exasn1, 1);
1598 
1599 	if (ret != KMF_OK) {
1600 		*contents = NULL;
1601 		*outlen = 0;
1602 		if (olddata != NULL)
1603 			free(olddata);
1604 	} else {
1605 		*contents = olddata;
1606 		*outlen = oldsize;
1607 	}
1608 	return (ret);
1609 }
1610 
1611 KMF_RETURN
1612 add_an_extension(KMF_X509_EXTENSIONS *exts, KMF_X509_EXTENSION *newextn)
1613 {
1614 	KMF_RETURN ret = KMF_OK;
1615 	KMF_X509_EXTENSION *extlist;
1616 
1617 	if (exts == NULL || newextn == NULL)
1618 		return (KMF_ERR_BAD_PARAMETER);
1619 
1620 	extlist = malloc(sizeof (KMF_X509_EXTENSION) *
1621 			(exts->numberOfExtensions + 1));
1622 	if (extlist == NULL)
1623 		return (KMF_ERR_MEMORY);
1624 
1625 	(void) memcpy(extlist, exts->extensions,
1626 	    exts->numberOfExtensions * sizeof (KMF_X509_EXTENSION));
1627 
1628 	(void) memcpy(&extlist[exts->numberOfExtensions], newextn,
1629 		sizeof (KMF_X509_EXTENSION));
1630 
1631 	free(exts->extensions);
1632 	exts->numberOfExtensions++;
1633 	exts->extensions = extlist;
1634 
1635 	return (ret);
1636 }
1637 
1638 KMF_RETURN
1639 KMF_SetAltName(KMF_X509_EXTENSIONS *extensions,
1640 	KMF_OID *oid,
1641 	int critical,
1642 	KMF_GENERALNAMECHOICES nametype,
1643 	char *namedata)
1644 {
1645 	KMF_RETURN ret = KMF_OK;
1646 	KMF_X509_EXTENSION subjAltName;
1647 	KMF_DATA dername = { NULL, 0 };
1648 	BerElement *asn1 = NULL;
1649 	BerValue *extdata;
1650 	char *olddata = NULL;
1651 	KMF_X509_EXTENSION *foundextn = NULL;
1652 	size_t	oldsize = 0;
1653 
1654 	if (extensions == NULL || oid == NULL || namedata == NULL)
1655 		return (KMF_ERR_BAD_PARAMETER);
1656 
1657 	ret = encode_altname(namedata, nametype, &dername);
1658 
1659 	if (ret != KMF_OK)
1660 		return (ret);
1661 
1662 	(void) memset(&subjAltName, 0, sizeof (subjAltName));
1663 
1664 	ret = copy_data(&subjAltName.extnId, oid);
1665 	if (ret != KMF_OK)
1666 		goto out;
1667 	/*
1668 	 * Check to see if this cert already has a subjectAltName.
1669 	 */
1670 	foundextn = FindExtn(extensions, oid);
1671 
1672 	if (foundextn != NULL) {
1673 		ret = GetSequenceContents(
1674 				(char *)foundextn->BERvalue.Data,
1675 				foundextn->BERvalue.Length,
1676 				&olddata, &oldsize);
1677 		if (ret != KMF_OK)
1678 			goto out;
1679 	}
1680 
1681 	/*
1682 	 * Assume (!!) that the namedata given is already properly encoded.
1683 	 */
1684 	if ((asn1 = kmfder_alloc()) == NULL)
1685 		return (KMF_ERR_MEMORY);
1686 
1687 	if (kmfber_printf(asn1, "{") == -1) {
1688 		ret = KMF_ERR_ENCODING;
1689 		goto out;
1690 	}
1691 
1692 	/* Write the old extension data first */
1693 	if (olddata != NULL && oldsize > 0) {
1694 		if (kmfber_write(asn1, olddata, oldsize, 0) == -1) {
1695 			ret = KMF_ERR_ENCODING;
1696 			goto out;
1697 		}
1698 	}
1699 
1700 	/* Now add the new name to the list */
1701 	if (kmfber_write(asn1, (char *)dername.Data, dername.Length, 0) == -1) {
1702 		ret = KMF_ERR_ENCODING;
1703 		goto out;
1704 	}
1705 
1706 	/* Now close the sequence */
1707 	if (kmfber_printf(asn1, "}") == -1) {
1708 		ret = KMF_ERR_ENCODING;
1709 		goto out;
1710 	}
1711 	if (kmfber_flatten(asn1, &extdata) == -1) {
1712 		ret = KMF_ERR_ENCODING;
1713 		goto out;
1714 	}
1715 
1716 	/*
1717 	 * If we are just adding to an existing list of altNames,
1718 	 * just replace the BER data associated with the found extension.
1719 	 */
1720 	if (foundextn != NULL) {
1721 		free(foundextn->BERvalue.Data);
1722 		foundextn->critical = critical;
1723 		foundextn->BERvalue.Data = (uchar_t *)extdata->bv_val;
1724 		foundextn->BERvalue.Length = extdata->bv_len;
1725 	} else {
1726 		subjAltName.critical = critical;
1727 		subjAltName.format = KMF_X509_DATAFORMAT_ENCODED;
1728 		subjAltName.BERvalue.Data = (uchar_t *)extdata->bv_val;
1729 		subjAltName.BERvalue.Length = extdata->bv_len;
1730 		ret = add_an_extension(extensions, &subjAltName);
1731 		if (ret != KMF_OK)
1732 			free(subjAltName.BERvalue.Data);
1733 	}
1734 
1735 	free(extdata);
1736 out:
1737 	if (olddata != NULL)
1738 		free(olddata);
1739 
1740 	KMF_FreeData(&dername);
1741 	if (ret != KMF_OK)
1742 		KMF_FreeData(&subjAltName.extnId);
1743 	if (asn1 != NULL)
1744 		kmfber_free(asn1, 1);
1745 	return (ret);
1746 }
1747