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