CK_RV C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession) { size_t i; INIT_CONTEXT(); st_logf("OpenSession: slot: %d\n", (int)slotID); if (soft_token.open_sessions == MAX_NUM_SESSION) return CKR_SESSION_COUNT; soft_token.application = pApplication; soft_token.notify = Notify; for (i = 0; i < MAX_NUM_SESSION; i++) if (soft_token.state[i].session_handle == CK_INVALID_HANDLE) break; if (i == MAX_NUM_SESSION) abort(); soft_token.open_sessions++; soft_token.state[i].session_handle = (CK_SESSION_HANDLE)(random() & 0xfffff); *phSession = soft_token.state[i].session_handle; return CKR_OK; }
CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { struct session_state *state; CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS }; CK_BBOOL bool_true = CK_TRUE; CK_ATTRIBUTE attr[] = { { CKA_VERIFY, &bool_true, sizeof(bool_true) } }; struct st_object *o; CK_RV ret; INIT_CONTEXT(); st_logf("VerifyInit\n"); VERIFY_SESSION_HANDLE(hSession, &state); ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]), mechs, sizeof(mechs)/sizeof(mechs[0]), pMechanism, hKey, &o); if (ret) return ret; ret = dup_mechanism(&state->verify_mechanism, pMechanism); if (ret == CKR_OK) state->verify_object = OBJECT_ID(o); return ret; }
CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { INIT_CONTEXT(); st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID, has_session()); memset(pInfo, 18, sizeof(*pInfo)); if (slotID != 1) return CKR_ARGUMENTS_BAD; snprintf_fill((char *)pInfo->slotDescription, sizeof(pInfo->slotDescription), ' ', "Heimdal hx509 SoftToken (slot)"); snprintf_fill((char *)pInfo->manufacturerID, sizeof(pInfo->manufacturerID), ' ', "Heimdal hx509 SoftToken (slot)"); pInfo->flags = CKF_TOKEN_PRESENT; if (soft_token.flags.hardware_slot) pInfo->flags |= CKF_HW_SLOT; pInfo->hardwareVersion.major = 1; pInfo->hardwareVersion.minor = 0; pInfo->firmwareVersion.major = 1; pInfo->firmwareVersion.minor = 0; return CKR_OK; }
CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) { INIT_CONTEXT(); *ppFunctionList = &funcs; return CKR_OK; }
CK_RV CK_SPEC C_Initialize(CK_VOID_PTR a) { CK_C_INITIALIZE_ARGS_PTR args = a; CK_RV ret; size_t i; st_logf("Initialize\n"); INIT_CONTEXT(); OpenSSL_add_all_algorithms(); srandom(getpid() ^ (int) time(NULL)); for (i = 0; i < MAX_NUM_SESSION; i++) { soft_token.state[i].session_handle = CK_INVALID_HANDLE; soft_token.state[i].find.attributes = NULL; soft_token.state[i].find.num_attributes = 0; soft_token.state[i].find.next_object = -1; reset_crypto_state(&soft_token.state[i]); } soft_token.flags.hardware_slot = 1; soft_token.flags.app_error_fatal = 0; soft_token.flags.login_done = 0; soft_token.object.objs = NULL; soft_token.object.num_objs = 0; soft_token.logfile = NULL; #if 0 soft_token.logfile = stdout; #endif #if 0 soft_token.logfile = fopen("/tmp/log-pkcs11.txt", "a"); #endif if (a != NULL_PTR) { st_logf("\tCreateMutex:\t%p\n", args->CreateMutex); st_logf("\tDestroyMutext\t%p\n", args->DestroyMutex); st_logf("\tLockMutext\t%p\n", args->LockMutex); st_logf("\tUnlockMutext\t%p\n", args->UnlockMutex); st_logf("\tFlags\t%04x\n", (unsigned int)args->flags); } soft_token.config_file = get_config_file_for_user(); /* * This operations doesn't return CKR_OK if any of the * certificates failes to be unparsed (ie password protected). */ ret = read_conf_file(soft_token.config_file, CKU_USER, NULL); if (ret == CKR_OK) soft_token.flags.login_done = 1; return CKR_OK; }
CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism) { st_logf("DigestInit\n"); INIT_CONTEXT(); VERIFY_SESSION_HANDLE(hSession, NULL); return CKR_FUNCTION_NOT_SUPPORTED; }
CK_RV C_Logout(CK_SESSION_HANDLE hSession) { st_logf("Logout\n"); INIT_CONTEXT(); VERIFY_SESSION_HANDLE(hSession, NULL); return CKR_FUNCTION_NOT_SUPPORTED; }
CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { INIT_CONTEXT(); st_logf("VerifyFinal\n"); VERIFY_SESSION_HANDLE(hSession, NULL); return CKR_FUNCTION_NOT_SUPPORTED; }
CK_RV C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { INIT_CONTEXT(); st_logf("VerifyUpdate\n"); VERIFY_SESSION_HANDLE(hSession, NULL); return CKR_FUNCTION_NOT_SUPPORTED; }
CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR RandomData, CK_ULONG ulRandomLen) { INIT_CONTEXT(); st_logf("GenerateRandom\n"); VERIFY_SESSION_HANDLE(hSession, NULL); return CKR_FUNCTION_NOT_SUPPORTED; }
CK_RV C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel) { INIT_CONTEXT(); st_logf("InitToken: slot %d\n", (int)slotID); return CKR_FUNCTION_NOT_SUPPORTED; }
CK_RV C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize) { st_logf("GetObjectSize\n"); INIT_CONTEXT(); VERIFY_SESSION_HANDLE(hSession, NULL); return CKR_FUNCTION_NOT_SUPPORTED; }
CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession) { struct session_state *state; INIT_CONTEXT(); st_logf("FindObjectsFinal\n"); VERIFY_SESSION_HANDLE(hSession, &state); find_object_final(state); return CKR_OK; }
CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) { INIT_CONTEXT(); st_logf("GetMechanismInfo: slot %d type: %d\n", (int)slotID, (int)type); memset(pInfo, 0, sizeof(*pInfo)); return CKR_OK; }
CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) { INIT_CONTEXT(); st_logf("GetTokenInfo: %s\n", has_session()); memset(pInfo, 19, sizeof(*pInfo)); snprintf_fill((char *)pInfo->label, sizeof(pInfo->label), ' ', "Heimdal hx509 SoftToken (token)"); snprintf_fill((char *)pInfo->manufacturerID, sizeof(pInfo->manufacturerID), ' ', "Heimdal hx509 SoftToken (token)"); snprintf_fill((char *)pInfo->model, sizeof(pInfo->model), ' ', "Heimdal hx509 SoftToken (token)"); snprintf_fill((char *)pInfo->serialNumber, sizeof(pInfo->serialNumber), ' ', "4711"); pInfo->flags = CKF_TOKEN_INITIALIZED | CKF_USER_PIN_INITIALIZED; if (soft_token.flags.login_done == 0) pInfo->flags |= CKF_LOGIN_REQUIRED; /* CFK_RNG | CKF_RESTORE_KEY_NOT_NEEDED | */ pInfo->ulMaxSessionCount = MAX_NUM_SESSION; pInfo->ulSessionCount = soft_token.open_sessions; pInfo->ulMaxRwSessionCount = MAX_NUM_SESSION; pInfo->ulRwSessionCount = soft_token.open_sessions; pInfo->ulMaxPinLen = 1024; pInfo->ulMinPinLen = 0; pInfo->ulTotalPublicMemory = 4711; pInfo->ulFreePublicMemory = 4712; pInfo->ulTotalPrivateMemory = 4713; pInfo->ulFreePrivateMemory = 4714; pInfo->hardwareVersion.major = 2; pInfo->hardwareVersion.minor = 0; pInfo->firmwareVersion.major = 2; pInfo->firmwareVersion.minor = 0; return CKR_OK; }
CK_RV C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) { INIT_CONTEXT(); st_logf("GetSlotList: %s\n", tokenPresent ? "tokenPresent" : "token not Present"); if (pSlotList) pSlotList[0] = 1; *pulCount = 1; return CKR_OK; }
// Destroy a VA/GLX surface VAStatus vaDestroySurfaceGLX( VADisplay dpy, void *gl_surface ) { VADriverContextP ctx; VAStatus status; INIT_CONTEXT(ctx, dpy); INVOKE(ctx, DestroySurface, (ctx, gl_surface)); return status; }
CK_RV C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { struct session_state *state; struct st_object *o; const AlgorithmIdentifier *alg; CK_RV ret; int hret; heim_octet_string data, sig; INIT_CONTEXT(); st_logf("Verify\n"); VERIFY_SESSION_HANDLE(hSession, &state); if (state->verify_object == -1) return CKR_ARGUMENTS_BAD; o = soft_token.object.objs[state->verify_object]; switch(state->verify_mechanism->mechanism) { case CKM_RSA_PKCS: alg = hx509_signature_rsa_pkcs1_x509(); break; default: ret = CKR_FUNCTION_NOT_SUPPORTED; goto out; } sig.data = pData; sig.length = ulDataLen; data.data = pSignature; data.length = ulSignatureLen; hret = _hx509_verify_signature(context, o->cert, alg, &data, &sig); if (hret) { ret = CKR_GENERAL_ERROR; goto out; } ret = CKR_OK; out: return ret; }
CK_RV C_CloseAllSessions(CK_SLOT_ID slotID) { size_t i; INIT_CONTEXT(); st_logf("CloseAllSessions\n"); for (i = 0; i < MAX_NUM_SESSION; i++) if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) close_session(&soft_token.state[i]); return CKR_OK; }
CK_RV C_CloseSession(CK_SESSION_HANDLE hSession) { struct session_state *state; INIT_CONTEXT(); st_logf("CloseSession\n"); if (verify_session_handle(hSession, &state) != CKR_OK) application_error("closed session not open"); else close_session(state); return CKR_OK; }
CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { struct session_state *state; struct st_object *obj; CK_ULONG i; CK_RV ret; int j; INIT_CONTEXT(); st_logf("GetAttributeValue: %lx\n", (unsigned long)HANDLE_OBJECT_ID(hObject)); VERIFY_SESSION_HANDLE(hSession, &state); if ((ret = object_handle_to_object(hObject, &obj)) != CKR_OK) { st_logf("object not found: %lx\n", (unsigned long)HANDLE_OBJECT_ID(hObject)); return ret; } for (i = 0; i < ulCount; i++) { st_logf(" getting 0x%08lx\n", (unsigned long)pTemplate[i].type); for (j = 0; j < obj->num_attributes; j++) { if (obj->attrs[j].secret) { pTemplate[i].ulValueLen = (CK_ULONG)-1; break; } if (pTemplate[i].type == obj->attrs[j].attribute.type) { if (pTemplate[i].pValue != NULL_PTR && obj->attrs[j].secret == 0) { if (pTemplate[i].ulValueLen >= obj->attrs[j].attribute.ulValueLen) memcpy(pTemplate[i].pValue, obj->attrs[j].attribute.pValue, obj->attrs[j].attribute.ulValueLen); } pTemplate[i].ulValueLen = obj->attrs[j].attribute.ulValueLen; break; } } if (j == obj->num_attributes) { st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate[i].type); pTemplate[i].ulValueLen = (CK_ULONG)-1; } } return CKR_OK; }
CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { struct session_state *state; st_logf("FindObjectsInit\n"); INIT_CONTEXT(); VERIFY_SESSION_HANDLE(hSession, &state); if (state->find.next_object != -1) { application_error("application didn't do C_FindObjectsFinal\n"); find_object_final(state); } if (ulCount) { CK_ULONG i; print_attributes(pTemplate, ulCount); state->find.attributes = calloc(1, ulCount * sizeof(state->find.attributes[0])); if (state->find.attributes == NULL) return CKR_DEVICE_MEMORY; for (i = 0; i < ulCount; i++) { state->find.attributes[i].pValue = malloc(pTemplate[i].ulValueLen); if (state->find.attributes[i].pValue == NULL) { find_object_final(state); return CKR_DEVICE_MEMORY; } memcpy(state->find.attributes[i].pValue, pTemplate[i].pValue, pTemplate[i].ulValueLen); state->find.attributes[i].type = pTemplate[i].type; state->find.attributes[i].ulValueLen = pTemplate[i].ulValueLen; } state->find.num_attributes = ulCount; state->find.next_object = 0; } else { st_logf("find all objects\n"); state->find.attributes = NULL; state->find.num_attributes = 0; state->find.next_object = 0; } return CKR_OK; }
CK_RV C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount) { INIT_CONTEXT(); st_logf("GetMechanismList\n"); *pulCount = 1; if (pMechanismList == NULL_PTR) return CKR_OK; pMechanismList[0] = CKM_RSA_PKCS; return CKR_OK; }
// Copy a VA surface to a VA/GLX surface VAStatus vaCopySurfaceGLX( VADisplay dpy, void *gl_surface, VASurfaceID surface, unsigned int flags ) { VADriverContextP ctx; VAStatus status; INIT_CONTEXT(ctx, dpy); INVOKE(ctx, CopySurface, (ctx, gl_surface, surface, flags)); return status; }
// Create a surface used for display to OpenGL VAStatus vaCreateSurfaceGLX( VADisplay dpy, GLenum target, GLuint texture, void **gl_surface ) { VADriverContextP ctx; VAStatus status; /* Make sure it is a valid GL texture object */ if (!glIsTexture(texture)) return VA_STATUS_ERROR_INVALID_PARAMETER; INIT_CONTEXT(ctx, dpy); INVOKE(ctx, CreateSurface, (ctx, target, texture, gl_surface)); return status; }
CK_RV C_Finalize(CK_VOID_PTR args) { size_t i; INIT_CONTEXT(); st_logf("Finalize\n"); for (i = 0; i < MAX_NUM_SESSION; i++) { if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) { application_error("application finalized without " "closing session\n"); close_session(&soft_token.state[i]); } } return CKR_OK; }
CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo) { st_logf("GetSessionInfo\n"); INIT_CONTEXT(); VERIFY_SESSION_HANDLE(hSession, NULL); memset(pInfo, 20, sizeof(*pInfo)); pInfo->slotID = 1; if (soft_token.flags.login_done) pInfo->state = CKS_RO_USER_FUNCTIONS; else pInfo->state = CKS_RO_PUBLIC_SESSION; pInfo->flags = CKF_SERIAL_SESSION; pInfo->ulDeviceError = 0; return CKR_OK; }
CK_RV C_GetInfo(CK_INFO_PTR args) { INIT_CONTEXT(); st_logf("GetInfo\n"); memset(args, 17, sizeof(*args)); args->cryptokiVersion.major = 2; args->cryptokiVersion.minor = 10; snprintf_fill((char *)args->manufacturerID, sizeof(args->manufacturerID), ' ', "Heimdal hx509 SoftToken"); snprintf_fill((char *)args->libraryDescription, sizeof(args->libraryDescription), ' ', "Heimdal hx509 SoftToken"); args->libraryVersion.major = 2; args->libraryVersion.minor = 0; return CKR_OK; }
CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount) { struct session_state *state; int i; INIT_CONTEXT(); st_logf("FindObjects\n"); VERIFY_SESSION_HANDLE(hSession, &state); if (state->find.next_object == -1) { application_error("application didn't do C_FindObjectsInit\n"); return CKR_ARGUMENTS_BAD; } if (ulMaxObjectCount == 0) { application_error("application asked for 0 objects\n"); return CKR_ARGUMENTS_BAD; } *pulObjectCount = 0; for (i = state->find.next_object; i < soft_token.object.num_objs; i++) { st_logf("FindObjects: %d\n", i); state->find.next_object = i + 1; if (attributes_match(soft_token.object.objs[i], state->find.attributes, state->find.num_attributes)) { *phObject++ = soft_token.object.objs[i]->object_handle; ulMaxObjectCount--; (*pulObjectCount)++; if (ulMaxObjectCount == 0) break; } } return CKR_OK; }
CK_RV C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) { char *pin = NULL; CK_RV ret; INIT_CONTEXT(); st_logf("Login\n"); VERIFY_SESSION_HANDLE(hSession, NULL); if (pPin != NULL_PTR) { int aret; aret = asprintf(&pin, "%.*s", (int)ulPinLen, pPin); if (aret != -1 && pin) st_logf("type: %d password: %s\n", (int)userType, pin); else st_logf("memory error: asprintf failed\n"); } /* * Login */ ret = read_conf_file(soft_token.config_file, userType, pin); if (ret == CKR_OK) soft_token.flags.login_done = 1; free(pin); return soft_token.flags.login_done ? CKR_OK : CKR_PIN_INCORRECT; }