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