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