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 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * General-Purpose Functions
30  * (as defined in PKCS#11 spec section 11.4)
31  */
32 
33 #include <unistd.h>
34 #include <errno.h>
35 #include <string.h>
36 #include "metaGlobal.h"
37 
38 extern meta_session_t *meta_sessionlist_head;
39 
40 struct CK_FUNCTION_LIST metaslot_functionList = {
41 	{ 2, 20 },	/* version */
42 	meta_Initialize,
43 	meta_Finalize,
44 	meta_GetInfo,
45 	meta_GetFunctionList,
46 	meta_GetSlotList,
47 	meta_GetSlotInfo,
48 	meta_GetTokenInfo,
49 	meta_GetMechanismList,
50 	meta_GetMechanismInfo,
51 	meta_InitToken,
52 	meta_InitPIN,
53 	meta_SetPIN,
54 	meta_OpenSession,
55 	meta_CloseSession,
56 	meta_CloseAllSessions,
57 	meta_GetSessionInfo,
58 	meta_GetOperationState,
59 	meta_SetOperationState,
60 	meta_Login,
61 	meta_Logout,
62 	meta_CreateObject,
63 	meta_CopyObject,
64 	meta_DestroyObject,
65 	meta_GetObjectSize,
66 	meta_GetAttributeValue,
67 	meta_SetAttributeValue,
68 	meta_FindObjectsInit,
69 	meta_FindObjects,
70 	meta_FindObjectsFinal,
71 	meta_EncryptInit,
72 	meta_Encrypt,
73 	meta_EncryptUpdate,
74 	meta_EncryptFinal,
75 	meta_DecryptInit,
76 	meta_Decrypt,
77 	meta_DecryptUpdate,
78 	meta_DecryptFinal,
79 	meta_DigestInit,
80 	meta_Digest,
81 	meta_DigestUpdate,
82 	meta_DigestKey,
83 	meta_DigestFinal,
84 	meta_SignInit,
85 	meta_Sign,
86 	meta_SignUpdate,
87 	meta_SignFinal,
88 	meta_SignRecoverInit,
89 	meta_SignRecover,
90 	meta_VerifyInit,
91 	meta_Verify,
92 	meta_VerifyUpdate,
93 	meta_VerifyFinal,
94 	meta_VerifyRecoverInit,
95 	meta_VerifyRecover,
96 	meta_DigestEncryptUpdate,
97 	meta_DecryptDigestUpdate,
98 	meta_SignEncryptUpdate,
99 	meta_DecryptVerifyUpdate,
100 	meta_GenerateKey,
101 	meta_GenerateKeyPair,
102 	meta_WrapKey,
103 	meta_UnwrapKey,
104 	meta_DeriveKey,
105 	meta_SeedRandom,
106 	meta_GenerateRandom,
107 	meta_GetFunctionStatus,
108 	meta_CancelFunction,
109 	meta_WaitForSlotEvent
110 };
111 
112 pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER;
113 
114 int meta_urandom_seed_fd = -1;
115 
116 ses_to_be_freed_list_t ses_delay_freed;
117 object_to_be_freed_list_t obj_delay_freed;
118 
119 /*
120  * meta_Initialize
121  *
122  * This function is never called by the application.  It is only
123  * called by uCF to initialize metaslot.  The pInitArgs argument is ignored.
124  *
125  */
126 /*ARGSUSED*/
127 CK_RV
128 meta_Initialize(CK_VOID_PTR pInitArgs)
129 {
130 	CK_RV rv;
131 
132 	/* Make sure function hasn't been called twice */
133 	(void) pthread_mutex_lock(&initmutex);
134 
135 	rv = meta_slotManager_initialize();
136 	if (rv != CKR_OK) {
137 		(void) pthread_mutex_unlock(&initmutex);
138 		return (rv);
139 	}
140 
141 	rv = meta_mechManager_initialize();
142 	if (rv != CKR_OK) {
143 		(void) meta_slotManager_finalize();
144 		(void) pthread_mutex_unlock(&initmutex);
145 		return (rv);
146 	}
147 
148 	rv = meta_objectManager_initialize();
149 	if (rv != CKR_OK) {
150 		(void) meta_slotManager_finalize();
151 		(void) meta_mechManager_finalize();
152 		(void) pthread_mutex_unlock(&initmutex);
153 		return (rv);
154 	}
155 
156 	rv = meta_sessionManager_initialize();
157 	if (rv != CKR_OK) {
158 		(void) meta_slotManager_finalize();
159 		(void) meta_mechManager_finalize();
160 		(void) meta_objectManager_finalize();
161 		(void) pthread_mutex_unlock(&initmutex);
162 		return (rv);
163 	}
164 
165 	meta_slotManager_find_object_token();
166 
167 	/* Initialize the object_to_be_freed list */
168 	(void) pthread_mutex_init(&obj_delay_freed.obj_to_be_free_mutex, NULL);
169 	obj_delay_freed.count = 0;
170 	obj_delay_freed.first = NULL;
171 	obj_delay_freed.last = NULL;
172 
173 	/* Initialize the session_to_be_freed list */
174 	(void) pthread_mutex_init(&ses_delay_freed.ses_to_be_free_mutex, NULL);
175 	ses_delay_freed.count = 0;
176 	ses_delay_freed.first = NULL;
177 	ses_delay_freed.last = NULL;
178 
179 	(void) pthread_mutex_unlock(&initmutex);
180 
181 	return (CKR_OK);
182 }
183 
184 
185 /*
186  * meta_Finalize
187  *
188  * Called by uCF only, "pReserved" argument is ignored.
189  */
190 /*ARGSUSED*/
191 CK_RV
192 meta_Finalize(CK_VOID_PTR pReserved)
193 {
194 	CK_RV rv = CKR_OK;
195 	meta_object_t *delay_free_obj, *tmpo;
196 	meta_session_t *delay_free_ses, *tmps;
197 
198 	if (pReserved != NULL)
199 		return (CKR_ARGUMENTS_BAD);
200 
201 	(void) pthread_mutex_lock(&initmutex);
202 
203 	if (meta_urandom_seed_fd > 0) {
204 		(void) close(meta_urandom_seed_fd);
205 		meta_urandom_seed_fd = -1;
206 	}
207 
208 	meta_objectManager_finalize();
209 
210 	meta_sessionManager_finalize();
211 
212 	meta_mechManager_finalize();
213 
214 	meta_slotManager_finalize();
215 
216 	/*
217 	 * free all entries in the delay_freed list
218 	 */
219 	delay_free_obj = obj_delay_freed.first;
220 	while (delay_free_obj != NULL) {
221 		tmpo = delay_free_obj->next;
222 		free(delay_free_obj);
223 		delay_free_obj = tmpo;
224 	}
225 	(void) pthread_mutex_destroy(&obj_delay_freed.obj_to_be_free_mutex);
226 
227 	delay_free_ses = ses_delay_freed.first;
228 	while (delay_free_ses != NULL) {
229 		tmps = delay_free_ses->next;
230 		free(delay_free_ses);
231 		delay_free_ses = tmps;
232 	}
233 	(void) pthread_mutex_destroy(&ses_delay_freed.ses_to_be_free_mutex);
234 
235 	(void) pthread_mutex_unlock(&initmutex);
236 
237 	return (rv);
238 }
239 
240 /*
241  * meta_GetInfo
242  *
243  * NOTE: This function will never be called by applications because it's
244  * hidden behind the uCF C_GetInfo. So, it is not implemented.
245  */
246 /*ARGSUSED*/
247 CK_RV
248 meta_GetInfo(CK_INFO_PTR pInfo)
249 {
250 	return (CKR_FUNCTION_NOT_SUPPORTED);
251 }
252 
253 
254 /*
255  * meta_GetFunctionList
256  *
257  * This function is not implemented because metaslot is part of the framework,
258  * so, the framework can just do a static assignment to metaslot's
259  * function list instead of calling this function.
260  */
261 /*ARGSUSED*/
262 CK_RV
263 meta_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
264 {
265 	return (CKR_FUNCTION_NOT_SUPPORTED);
266 }
267 
268 
269 /*
270  * Parallel Function Management Function
271  * (as defined in PKCS#11 spec section 11.16)
272  */
273 
274 /*
275  * This function is no longer supported in this revision of the PKCS#11
276  * standard.  It is maintained for backwards compatibility only.
277  */
278 /* ARGSUSED */
279 CK_RV
280 meta_GetFunctionStatus(CK_SESSION_HANDLE hSession)
281 {
282 	return (CKR_FUNCTION_NOT_PARALLEL);
283 }
284 
285 
286 /*
287  * This function is no longer supported in this revision of the PKCS#11
288  * standard.  It is maintained for backwards compatibility only.
289  */
290 /* ARGSUSED */
291 CK_RV
292 meta_CancelFunction(CK_SESSION_HANDLE hSession)
293 {
294 	return (CKR_FUNCTION_NOT_PARALLEL);
295 }
296 
297 /*
298  * Perform a write that can handle EINTR.
299  */
300 int
301 looping_write(int fd, void *buf, int len)
302 {
303 	char *p = buf;
304 	int cc, len2 = 0;
305 
306 	if (len == 0)
307 		return (0);
308 
309 	do {
310 		cc = write(fd, p, len);
311 		if (cc < 0) {
312 			if (errno == EINTR)
313 				continue;
314 			return (cc);
315 		} else if (cc == 0) {
316 			return (len2);
317 		} else {
318 			p += cc;
319 			len2 += cc;
320 			len -= cc;
321 		}
322 	} while (len > 0);
323 	return (len2);
324 }
325 
326 /*
327  * Perform a read that can handle EINTR.
328  */
329 int
330 looping_read(int fd, void *buf, int len)
331 {
332 	char *p = buf;
333 	int cc, len2 = 0;
334 
335 	do {
336 		cc = read(fd, p, len);
337 		if (cc < 0) {
338 			if (errno == EINTR)
339 				continue;
340 			return (cc);	/* errno is already set */
341 		} else if (cc == 0) {
342 			return (len2);
343 		} else {
344 			p += cc;
345 			len2 += cc;
346 			len -= cc;
347 		}
348 	} while (len > 0);
349 	return (len2);
350 }
351