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