CK_RV pkcs11_login_session(CK_FUNCTION_LIST_PTR funcs, FILE *out, CK_SLOT_ID slot, CK_SESSION_HANDLE_PTR session, CK_BBOOL readwrite, CK_USER_TYPE user, CK_UTF8CHAR_PTR pin, CK_ULONG pinLen) { CK_SESSION_HANDLE h_session; CK_FLAGS flags = CKF_SERIAL_SESSION | (readwrite ? CKF_RW_SESSION : 0); CK_RV rc; rc = funcs->C_OpenSession(slot, flags, NULL, NULL, &h_session); if (rc != CKR_OK) { if(out) { show_error(stdout, "C_OpenSession", rc); } return rc; } if(pin) { rc = funcs->C_Login(h_session, user, pin, pinLen); if (rc != CKR_OK) { if(out) { show_error(out, "C_Login", rc); } goto end; } } else if(readwrite || pinLen > 0) { CK_TOKEN_INFO info; rc = funcs->C_GetTokenInfo(slot, &info); if (rc != CKR_OK) { if(out) { show_error(out, "C_GetTokenInfo", rc); } goto end; } if(info.flags & CKF_PROTECTED_AUTHENTICATION_PATH) { rc = funcs->C_Login(h_session, user, NULL, 0); if (rc != CKR_OK) { if(out) { show_error(out, "C_Login", rc); } goto end; } } } end: if (rc != CKR_OK) { /* We want to keep the original error code */ CK_RV r = funcs->C_CloseSession(h_session); if ((r != CKR_OK) && out) { show_error(out, "C_CloseSession", r); } } else if(session) { *session = h_session; } return rc; }
int EstEID_sighHashWindows(char **signature, unsigned int *signatureLength, CK_SLOT_ID slotID, EstEID_Map cert, const char *hash, unsigned int hashLength, EstEID_PINPromptData pinPromptData) { CK_SESSION_HANDLE session = 0L; char message[1024]; int remainingTries = 0; CK_RV loginResult = CKR_FUNCTION_CANCELED; LOG_LOCATION; if (EstEID_CK_failure("C_OpenSession", fl->C_OpenSession(slotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session))) return FAILURE; remainingTries = EstEID_getRemainingTries(slotID); EstEID_log("EstEID_getRemainingTries(slotID) = %i", remainingTries); if (remainingTries == -1) CLOSE_SESSION_AND_RETURN(FAILURE); if (!remainingTries) { sprintf_s(EstEID_error, ESTEID_ERROR_SIZE, "C_Login error: %s (%li)", pkcs11_error_message(CKR_PIN_LOCKED), CKR_PIN_LOCKED); CLOSE_SESSION_AND_RETURN(FAILURE); } if (remainingTries < 3) { sprintf_s(message, 1024, "%s %i", l10n("Tries left:"), remainingTries); } else { message[0] = 0; } loginResult = fl->C_Login(session, CKU_USER, (unsigned char *)pinPromptData.pin2, strlen(pinPromptData.pin2)); if(loginResult != CKR_OK) { EstEID_log("loginResult = %s", pkcs11_error_message(loginResult)); sprintf_s(EstEID_error, 1024, "C_Login error: %s (%li)", pkcs11_error_message(loginResult), loginResult); CLOSE_SESSION_AND_RETURN(loginResult); } return EstEID_RealSign(session, signature, signatureLength, hash, hashLength, NULL); }
THREAD_RETURN_TYPE EstEID_pinPadLogin(void* threadData) { #ifndef _WIN32 LOG_LOCATION; pthread_mutex_lock(&pinpad_thread_mutex); CK_SESSION_HANDLE session = ((EstEID_PINPadThreadData*)threadData)->session; CK_RV loginResult = fl->C_Login(session, CKU_USER, NULL, 0); ((EstEID_PINPadThreadData*)threadData)->result = loginResult; closePinPadModalSheet(); EstEID_log("modal sheet/dialog destroyed"); pinpad_thread_completed = TRUE; pthread_cond_broadcast(&pinpad_thread_condition); pthread_mutex_unlock(&pinpad_thread_mutex); pthread_exit(NULL); #else EstEID_PINPromptDataEx* pinPromptDataEx; LOG_LOCATION; WaitForSingleObject(pinpad_thread_mutex, INFINITE); pinPromptDataEx = (EstEID_PINPromptDataEx*)threadData; pinPromptDataEx->pinPromptData.promptFunction(NULL, pinPromptDataEx->name, pinPromptDataEx->message, 0, TRUE); ReleaseMutex(pinpad_thread_mutex); return TRUE; #endif }
static void test_login() { CK_SESSION_HANDLE session; CK_SESSION_INFO info; asrt(funcs->C_Initialize(NULL), CKR_OK, "INITIALIZE"); asrt(funcs->C_OpenSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &session), CKR_OK, "OpenSession1"); asrt(funcs->C_Login(session, CKU_USER, "123456", 6), CKR_OK, "Login USER"); asrt(funcs->C_Logout(session), CKR_OK, "Logout USER"); asrt(funcs->C_Login(session, CKU_SO, "010203040506070801020304050607080102030405060708", 48), CKR_OK, "Login SO"); asrt(funcs->C_Logout(session), CKR_OK, "Logout SO"); asrt(funcs->C_CloseSession(session), CKR_OK, "CloseSession"); asrt(funcs->C_Finalize(NULL), CKR_OK, "FINALIZE"); }
CK_RV login(CK_FUNCTION_LIST_PTR p11p, CK_SESSION_HANDLE hSession, int admin, CK_UTF8CHAR *password, CK_ULONG passwordLen) { CK_UTF8CHAR pin[64]; CK_ULONG pinLen = sizeof(pin) - 1; CK_RV rv; if (passwordLen > 0 && password != NULL && passwordLen <= pinLen) { memcpy(pin, password, passwordLen); pinLen = passwordLen; } else { printf("Enter %sPIN: ", (admin == 1) ? "admin " : ""); rv = getPassword(pin, &pinLen); if (rv!= 0) return(-1); } if (admin == 1) rv = p11p->C_Login(hSession, CKU_SO, pin, pinLen); else rv = p11p->C_Login(hSession, CKU_USER, pin, pinLen); memset(pin, 0, sizeof(pin)); return(rv); }
/* * Log in to the keystore in the child if we were logged in in the parent. There * are similarities in the code with pk11_token_login() but still it is quite * different so we need a separate function for this. * * Note that this function is called under the locked session mutex when fork is * detected. That means that C_Login() will be called from the child just once. * * Returns: * 1 on success * 0 on failure */ int pk11_token_relogin(CK_SESSION_HANDLE session) { CK_RV rv; /* * We are in the child so check if we should login to the token again. * Note that it is enough to log in to the token through one session * only, all already open and all future sessions can access the token * then. */ if (passphrasedialog != NULL) { char *pin = NULL; /* If we cached the PIN then use it. */ if (token_pin != NULL) pin = token_pin; else if (pk11_get_pin(passphrasedialog, &pin) == 0) goto err; (void) pthread_mutex_lock(uri_lock); if ((rv = pFuncList->C_Login(session, CKU_USER, (CK_UTF8CHAR_PTR)pin, strlen(pin))) != CKR_OK) { PK11err_add_data(PK11_F_TOKEN_RELOGIN, PK11_R_TOKEN_LOGIN_FAILED, rv); (void) pthread_mutex_unlock(uri_lock); goto err; } (void) pthread_mutex_unlock(uri_lock); /* Forget the PIN now if we did not cache it before. */ if (pin != token_pin) { memset(pin, 0, strlen(pin)); OPENSSL_free(pin); } } return (1); err: return (0); }
// Connect and login to the token int openP11(CK_SLOT_ID slotID, char* userPIN, CK_SESSION_HANDLE* hSession) { char user_pin_copy[MAX_PIN_LEN+1]; CK_RV rv; rv = p11->C_OpenSession(slotID, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL_PTR, NULL_PTR, hSession); if (rv != CKR_OK) { if (rv == CKR_SLOT_ID_INVALID) { fprintf(stderr, "ERROR: The given slot does not exist.\n"); } else { fprintf(stderr, "ERROR: Could not open a session on the given slot.\n"); } return 1; } // Get the password if (getPW(userPIN, user_pin_copy, CKU_USER) != 0) { fprintf(stderr, "ERROR: Could not get user PIN\n"); return 1; } rv = p11->C_Login(*hSession, CKU_USER, (CK_UTF8CHAR_PTR)user_pin_copy, strlen(user_pin_copy)); if (rv != CKR_OK) { if (rv == CKR_PIN_INCORRECT) { fprintf(stderr, "ERROR: The given user PIN does not match the one in the token.\n"); } else { fprintf(stderr, "ERROR: Could not log in on the token.\n"); } return 1; } return 0; }
static CK_RV hacky_perform_initialize_pin (GP11Slot *slot) { CK_FUNCTION_LIST_PTR funcs; CK_SESSION_HANDLE session; CK_SLOT_ID slot_id; CK_RV rv; /* * This hack only works when: * * - Module is protected authentication path * - No other sessions are open. * * Thankfully this is the case with mate-keyring-daemon and * the mate-keyring tool. */ funcs = gp11_module_get_functions (gp11_slot_get_module (slot)); g_return_val_if_fail (funcs, CKR_GENERAL_ERROR); slot_id = gp11_slot_get_handle (slot); rv = funcs->C_OpenSession (slot_id, CKF_RW_SESSION | CKF_SERIAL_SESSION, NULL, NULL, &session); if (rv != CKR_OK) return rv; rv = funcs->C_Login (session, CKU_SO, NULL, 0); if (rv == CKR_OK) { rv = funcs->C_InitPIN (session, NULL, 0); funcs->C_Logout (session); } funcs->C_CloseSession (session); return rv; }
int EstEID_signHash(char **signature, unsigned int *signatureLength, CK_SLOT_ID slotID, EstEID_Map cert, const char *hash, unsigned int hashLength, EstEID_PINPromptData pinPromptData) { CK_SESSION_HANDLE session = 0L; LOG_LOCATION; if (EstEID_CK_failure("C_OpenSession", fl->C_OpenSession(slotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session))) return FAILURE; char *name = EstEID_getFullNameWithPersonalCode(cert); for (int attempt = 0, blocked = FALSE;; attempt++) { char message[1024]; int remainingTries = EstEID_getRemainingTries(slotID); if (remainingTries == -1) CLOSE_SESSION_AND_RETURN(FAILURE); if (!remainingTries || blocked) { sprintf(EstEID_error, "C_Login error: %s (%li)", pkcs11_error_message(CKR_PIN_LOCKED), CKR_PIN_LOCKED); pinPromptData.alertFunction(pinPromptData.nativeWindowHandle, l10n("PIN2 blocked, can not sign!")); CLOSE_SESSION_AND_RETURN(FAILURE); } if (remainingTries < 3 || attempt) { sprintf(message, "%s%s %i", (attempt ? l10n("Incorrect PIN2! ") : ""), l10n("Tries left:"), remainingTries); } else { message[0] = 0; } int isPinPad = EstEID_isPinPad(slotID); CK_RV loginResult = CKR_FUNCTION_CANCELED; if(!isPinPad) { // Simple card reader char *pin = pinPromptData.promptFunction(pinPromptData.nativeWindowHandle, name, message, (unsigned)atoi(EstEID_mapGet(cert, "minPinLen")), isPinPad); if (!pin || strlen(pin) == 0) { if (pin) free(pin); setUserCancelErrorCodeAndMessage(); CLOSE_SESSION_AND_RETURN(FAILURE); } loginResult = fl->C_Login(session, CKU_USER, (unsigned char *)pin, strlen(pin)); free(pin); } else { // PIN pad #ifdef _WIN32 EstEID_log("creating pinpad dialog UI thread"); pinpad_thread_result = -1; FAIL_IF_THREAD_ERROR("CreateMutex", (pinpad_thread_mutex = CreateMutex(NULL, FALSE, NULL))); #else EstEID_log("creating pinpad worker thread"); pinpad_thread_result = -1; FAIL_IF_PTHREAD_ERROR("pthread_mutex_init", pthread_mutex_init(&pinpad_thread_mutex, NULL)); FAIL_IF_PTHREAD_ERROR("pthread_cond_init", pthread_cond_init(&pinpad_thread_condition, NULL)); pthread_t pinpad_thread; EstEID_PINPadThreadData threadData; threadData.session = session; threadData.result = CKR_OK; #endif EstEID_log("thread launched"); #ifdef _WIN32 /* NB! Due to Firefox for Windows specific behaviour C_Login() is launched from main thread and UI code is running in separate thread if running on Windows. */ EstEID_PINPromptDataEx pinPromptDataEx; pinPromptDataEx.pinPromptData = pinPromptData; pinPromptDataEx.message = message; pinPromptDataEx.name = name; CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&EstEID_pinPadLogin, (LPVOID)&pinPromptDataEx, 0, NULL); loginResult = fl->C_Login(session, CKU_USER, NULL, 0); closePinPadModalSheet(); #else FAIL_IF_PTHREAD_ERROR("pthread_create", pthread_create(&pinpad_thread, NULL, EstEID_pinPadLogin, (void*)&threadData)); pinPromptData.promptFunction(pinPromptData.nativeWindowHandle, name, message, 0, isPinPad); loginResult = threadData.result; #endif EstEID_log("pinpad sheet/dialog closed"); if (loginResult == CKR_FUNCTION_CANCELED) { setUserCancelErrorCodeAndMessage(); CLOSE_SESSION_AND_RETURN(FAILURE); } } EstEID_log("loginResult = %s", pkcs11_error_message(loginResult)); switch (loginResult) { case CKR_PIN_LOCKED: blocked = TRUE; case CKR_PIN_INCORRECT: case CKR_PIN_INVALID: case CKR_PIN_LEN_RANGE: EstEID_log("this was attempt %i, loginResult causes to run next round", attempt); continue; default: if (EstEID_CK_failure("C_Login", loginResult)) CLOSE_SESSION_AND_RETURN(FAILURE); } break; // Login successful - correct PIN supplied } return EstEID_RealSign(session, signature, signatureLength, hash, hashLength, name); }
void processRequest(int client) { DataMarshalling *d = NULL; while (1) { d = new DataMarshalling(client); d->recvData(); if (!strcmp(d->getMsgType(), "C_Initialize")) { int p = 0; printf("Processing: C_Initialize\n"); p = d->unpackInt(); if (p == 0) pFunctionList->C_Initialize(NULL); else { printf("ERROR: C_Initialize shouldn't be called with not NULL\n"); } } else if (!strcmp(d->getMsgType(), "C_Finalize")) { int p = 0; CK_RV ret = 0; printf("Processing: C_Finalize\n"); p = d->unpackInt(); if (p == NULL) { ret = pFunctionList->C_Finalize(NULL); } else { printf("ERROR: C_Finalize shouldn't be called with not NULL\n"); ret = CKR_CANCEL; } { CK_ULONG count = 0; DataMarshalling *d2 = new DataMarshalling(client); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->sendData(); delete d2; } break; } else if (!strcmp(d->getMsgType(), "C_GetSlotList")) { int p = 0; printf("Processing: C_GetSlotList\n"); p = d->unpackInt(); if (p == 0) { CK_ULONG count = 0; CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); /* * Retrieving Slots size */ ret = pFunctionList->C_GetSlotList(TRUE, NULL, &count); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->packInt((char *)&count); d2->sendData(); delete d2; } else { CK_ULONG count = 0; CK_SLOT_ID_PTR slot = NULL; CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); /* * Retrieving Slots size */ pFunctionList->C_GetSlotList(TRUE, NULL, &count); slot = new(CK_SLOT_ID[count]); ret = pFunctionList->C_GetSlotList(TRUE, slot, &count); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->packInt((char *)&count); for (int i = 0; i < count; i ++) d2->packInt((char *)&slot[i]); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_OpenSession")) { unsigned int slotId = 0, flags = 0; CK_SESSION_HANDLE sessionId = 0; printf("Processing: C_OpenSession\n"); slotId = d->unpackInt(); flags = d->unpackInt(); { CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); /* * Opening session */ ret = pFunctionList->C_OpenSession(slotId, flags, NULL, NULL, &sessionId); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->packInt((char *)&sessionId); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_CloseSession")) { CK_SESSION_HANDLE sessionId = 0; printf("Processing: C_CloseSession\n"); sessionId = d->unpackInt(); { CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); /* * Opening session */ ret = pFunctionList->C_CloseSession(sessionId); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_GetInfo")) { unsigned int slotId = 0, flags = 0; CK_SESSION_HANDLE sessionId = 0; CK_INFO info; printf("Processing: C_GetInfo\n"); slotId = d->unpackInt(); { CK_RV ret = 0; CK_TOKEN_INFO token; DataMarshalling *d2 = new DataMarshalling(client); /* * Opening session */ ret = pFunctionList->C_GetInfo(&info); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->packChar(info.cryptokiVersion.major); d2->packChar(info.cryptokiVersion.minor); d2->packMem((char *)info.manufacturerID, 32); d2->packInt((char *)&info.flags); d2->packMem((char *)info.libraryDescription, 32); d2->packChar(info.libraryVersion.major); d2->packChar(info.libraryVersion.minor); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_GetSlotInfo")) { unsigned int slotId = 0, flags = 0; CK_SESSION_HANDLE sessionId = 0; printf("Processing: C_GetSlotInfo\n"); slotId = d->unpackInt(); { CK_RV ret = 0; CK_SLOT_INFO slot; DataMarshalling *d2 = new DataMarshalling(client); /* * Opening session */ ret = pFunctionList->C_GetSlotInfo(slotId, &slot); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->packMem((char *)slot.slotDescription, 64); d2->packMem((char *)slot.manufacturerID, 32); d2->packInt((char *)&slot.flags); d2->packChar(slot.hardwareVersion.major); d2->packChar(slot.hardwareVersion.minor); d2->packChar(slot.firmwareVersion.major); d2->packChar(slot.firmwareVersion.minor); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_GetTokenInfo")) { unsigned int slotId = 0, flags = 0; CK_SESSION_HANDLE sessionId = 0; printf("Processing: C_GetTokenInfo\n"); slotId = d->unpackInt(); { CK_RV ret = 0; CK_TOKEN_INFO token; DataMarshalling *d2 = new DataMarshalling(client); /* * Opening session */ ret = pFunctionList->C_GetTokenInfo(slotId, &token); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->packMem((char *)token.label, 32); d2->packMem((char *)token.manufacturerID, 32); d2->packMem((char *)token.model, 16); d2->packMem((char *)token.serialNumber, 16); d2->packInt((char *)&token.flags); d2->packInt((char *)&token.ulMaxSessionCount); d2->packInt((char *)&token.ulSessionCount); d2->packInt((char *)&token.ulMaxRwSessionCount); d2->packInt((char *)&token.ulRwSessionCount); d2->packInt((char *)&token.ulMaxPinLen); d2->packInt((char *)&token.ulMinPinLen); d2->packInt((char *)&token.ulTotalPublicMemory); d2->packInt((char *)&token.ulFreePublicMemory); d2->packInt((char *)&token.ulTotalPrivateMemory); d2->packInt((char *)&token.ulFreePrivateMemory); d2->packChar(token.hardwareVersion.major); d2->packChar(token.hardwareVersion.minor); d2->packChar(token.firmwareVersion.major); d2->packChar(token.firmwareVersion.minor); d2->packMem((char *)token.utcTime, 16); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_GetMechanismList")) { unsigned int slotId = 0; CK_MECHANISM_TYPE_PTR pMechanismList = NULL; printf("Processing: C_GetMechanismList\n"); slotId = d->unpackInt(); pMechanismList = (CK_MECHANISM_TYPE_PTR)d->unpackInt(); if (pMechanismList == NULL) { CK_ULONG count = 0; CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); /* * Retrieving Slots size */ ret = pFunctionList->C_GetMechanismList(slotId, pMechanismList, &count); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->packInt((char *)&count); printf("C_GetMechanismList count: %d\n", count); d2->sendData(); delete d2; } else { CK_ULONG count = 0; CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); /* * Retrieving Slots size */ pFunctionList->C_GetMechanismList(TRUE, NULL, &count); pMechanismList = new(CK_MECHANISM_TYPE[count]); ret = pFunctionList->C_GetMechanismList(slotId, pMechanismList, &count); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->packInt((char *)&count); printf("C_GetMechanismList count: %d\n", count); for (int i = 0; i < count; i ++) d2->packInt((char *)&pMechanismList[i]); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_GetMechanismInfo")) { unsigned int slotId = 0, mechanismType = 0; printf("Processing: C_GetMechanismInfo\n"); slotId = d->unpackInt(); mechanismType = d->unpackInt(); { CK_RV ret = 0; CK_MECHANISM_INFO mechanism; DataMarshalling *d2 = new DataMarshalling(client); ret = pFunctionList->C_GetMechanismInfo(slotId, mechanismType, &mechanism); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->packInt((char *)&mechanism.ulMinKeySize); d2->packInt((char *)&mechanism.ulMaxKeySize); d2->packInt((char *)&mechanism.flags); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_Login")) { CK_SESSION_HANDLE sessionId = 0; unsigned int user = 0, len = 0; CK_CHAR_PTR pin = NULL; printf("Processing: C_Login\n"); sessionId = d->unpackInt(); user = d->unpackInt(); len = d->unpackInt(); pin = (CK_CHAR_PTR) calloc(1, len + 1); if (!pin) { printf("ERROR: NO MEMORY\n"); break; } d->unpackMem((char *)pin, len); { CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); /* * Opening session */ ret = pFunctionList->C_Login(sessionId, user, pin, len); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_Logout")) { CK_SESSION_HANDLE sessionId = 0; printf("Processing: C_Logout\n"); sessionId = d->unpackInt(); { CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); /* * Opening session */ ret = pFunctionList->C_Logout(sessionId); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_FindObjectsInit")) { CK_SESSION_HANDLE sessionId = 0; unsigned int len = 0; CK_ATTRIBUTE_PTR attr = NULL; printf("Processing: C_FindObjectsInit\n"); sessionId = d->unpackInt(); len = d->unpackInt(); attr = (CK_ATTRIBUTE_PTR) calloc(len, sizeof(CK_ATTRIBUTE)); if (!attr) { printf("ERROR: NO MEMORY\n"); break; } for (int i = 0; i < len; i ++) { attr[i].type = d->unpackInt(); attr[i].ulValueLen = d->unpackInt(); attr[i].pValue = (char *)calloc(1, attr[i].ulValueLen); d->unpackMem((char *)attr[i].pValue, attr[i].ulValueLen); } { CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); /* * Opening session */ ret = pFunctionList->C_FindObjectsInit(sessionId, attr, len); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_FindObjects")) { CK_SESSION_HANDLE sessionId = 0; CK_OBJECT_HANDLE_PTR phObject = NULL; CK_ULONG len = 0, maxlen = 0; printf("Processing: C_FindObjects\n"); sessionId = d->unpackInt(); maxlen = d->unpackInt(); if (maxlen > 0) { phObject = new(CK_OBJECT_HANDLE[maxlen]); } { CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); /* * Opening session */ ret = pFunctionList->C_FindObjects(sessionId, phObject, maxlen, &len); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->packInt((char *)&len); for (int i = 0; i < len && i < maxlen; i ++) d2->packInt((char *)&phObject[i]); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_GetAttributeValue")) { CK_SESSION_HANDLE sessionId = 0; CK_OBJECT_HANDLE hObject = 0; CK_ULONG len = 0; CK_ATTRIBUTE_PTR attr = NULL; printf("Processing: C_GetAttributeValue\n"); sessionId = d->unpackInt(); hObject = d->unpackInt(); len = d->unpackInt(); attr = (CK_ATTRIBUTE_PTR) calloc(len, sizeof(CK_ATTRIBUTE)); if (!attr) { printf("ERROR: NO MEM C_GetAttributeValue\n"); break; } for (int i = 0; i < len; i ++) { attr[i].type = d->unpackInt(); attr[i].ulValueLen = d->unpackInt(); attr[i].pValue = (char *)d->unpackInt(); if (attr[i].pValue != NULL) { attr[i].pValue = (char *)calloc(1, attr[i].ulValueLen); if (!attr[i].pValue) { printf("ERROR: NO MEM\n"); exit(-1); } //d->unpackMem((char *)attr[i].pValue, attr[i].ulValueLen); } } { CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); ret = pFunctionList->C_GetAttributeValue(sessionId, hObject, attr, len); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); for (int i = 0; i < len; i ++) { d2->packInt((char *)&attr[i].type); d2->packInt((char *)&attr[i].ulValueLen); d2->packInt((char *)&attr[i].pValue); if (attr[i].pValue != NULL) { d2->packMem((char *)attr[i].pValue, attr[i].ulValueLen); #ifdef FUNC_DEBUG_ if (i == 2) { PCCERT_CONTEXT pCertContext; pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING,((BYTE *)attr[i].pValue),attr[i].ulValueLen); printf("data len: %d\n", attr[i].ulValueLen); printf("issuer len: %d\n", pCertContext->pCertInfo->Issuer.cbData); std::wcout << byte2str(pCertContext->pCertInfo->Issuer.pbData, pCertContext->pCertInfo->Issuer.cbData); CertFreeCertificateContext(pCertContext); } #endif } } d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_FindObjectsFinal")) { CK_SESSION_HANDLE sessionId = 0; printf("Processing: C_FindObjectsFinal\n"); sessionId = d->unpackInt(); { CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); /* * Opening session */ ret = pFunctionList->C_FindObjectsFinal(sessionId); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_SignInit")) { CK_SESSION_HANDLE sessionId = 0; CK_MECHANISM mechanism; CK_OBJECT_HANDLE hKey; printf("Processing: C_SignInit\n"); sessionId = d->unpackInt(); hKey = d->unpackInt(); mechanism.mechanism = d->unpackInt(); mechanism.ulParameterLen = d->unpackInt(); mechanism.pParameter = NULL; { CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); /* * Opening session */ ret = pFunctionList->C_SignInit(sessionId, &mechanism, hKey); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_Sign")) { CK_SESSION_HANDLE sessionId = 0; char *data = NULL, *signature = NULL; CK_ULONG dataLen = 0, signatureLen = 0; printf("Processing: C_Sign\n"); sessionId = d->unpackInt(); dataLen = d->unpackInt(); data = (char *)d->unpackInt(); if (data != NULL) { data = (char *)calloc(1, dataLen); if (!data) { printf("ERROR: NO MEM C_Sign\n"); break; } d->unpackMem((char *)data, dataLen); } signatureLen = d->unpackInt(); signature = (char *)d->unpackInt(); if (signature != NULL) { signature = (char *)calloc(1, signatureLen); if (!signature) { printf("ERROR: NO MEM C_Sign\n"); break; } d->unpackMem((char *)signature, signatureLen); } { CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); /* * Opening session */ ret = pFunctionList->C_Sign(sessionId, (CK_BYTE_PTR)data, dataLen, (CK_BYTE_PTR)signature, &signatureLen); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->packInt((char *)&signatureLen); if (signature != NULL) d2->packMem((char *)signature, signatureLen); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_VerifyInit")) { CK_SESSION_HANDLE sessionId = 0; CK_MECHANISM mechanism; CK_OBJECT_HANDLE hKey; printf("Processing: C_VerifyInit\n"); sessionId = d->unpackInt(); hKey = d->unpackInt(); mechanism.mechanism = d->unpackInt(); mechanism.ulParameterLen = d->unpackInt(); mechanism.pParameter = NULL; { CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); /* * Opening session */ ret = pFunctionList->C_VerifyInit(sessionId, &mechanism, hKey); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_Verify")) { CK_SESSION_HANDLE sessionId = 0; char *data = NULL, *signature = NULL; CK_ULONG dataLen = 0, signatureLen = 0; printf("Processing: C_Verify\n"); sessionId = d->unpackInt(); dataLen = d->unpackInt(); data = (char *)d->unpackInt(); if (data != NULL) { data = (char *)calloc(1, dataLen); if (!data) { printf("ERROR: NO MEM C_Verify\n"); break; } d->unpackMem((char *)data, dataLen); } signatureLen = d->unpackInt(); signature = (char *)d->unpackInt(); if (signature != NULL) { signature = (char *)calloc(1, signatureLen); if (!signature) { printf("ERROR: NO MEM C_Verify\n"); break; } d->unpackMem((char *)signature, signatureLen); } { CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); /* * Opening session */ ret = pFunctionList->C_Verify(sessionId, (CK_BYTE_PTR)data, dataLen, (CK_BYTE_PTR)signature, signatureLen); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_GenerateRandom")) { CK_SESSION_HANDLE sessionId = 0; char *data = NULL; CK_ULONG dataLen = 0; printf("Processing: C_GenerateRandom\n"); sessionId = d->unpackInt(); dataLen = d->unpackInt(); data = (char *)d->unpackInt(); if (data != NULL) { data = (char *)calloc(1, dataLen); if (!data) { printf("ERROR: NO MEM C_GenerateRandom\n"); break; } //d->unpackMem((char *)data, dataLen); } { CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); /* * Opening session */ ret = pFunctionList->C_GenerateRandom(sessionId, (CK_BYTE_PTR)data, dataLen); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); if (data != NULL) d2->packMem((char *)data, dataLen); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_SeedRandom")) { CK_SESSION_HANDLE sessionId = 0; char *data = NULL; CK_ULONG dataLen = 0; printf("Processing: C_SeedRandom\n"); sessionId = d->unpackInt(); dataLen = d->unpackInt(); data = (char *)d->unpackInt(); if (data != NULL) { data = (char *)calloc(1, dataLen); if (!data) { printf("ERROR: NO MEM C_SeedRandom\n"); break; } d->unpackMem((char *)data, dataLen); } { CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); /* * Opening session */ ret = pFunctionList->C_SeedRandom(sessionId, (CK_BYTE_PTR)data, dataLen); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_GetSessionInfo")) { CK_SESSION_HANDLE sessionId = 0; printf("Processing: C_GetSessionInfo\n"); sessionId = d->unpackInt(); { CK_RV ret = 0; CK_SESSION_INFO info; DataMarshalling *d2 = new DataMarshalling(client); /* * Opening session */ ret = pFunctionList->C_GetSessionInfo(sessionId, &info); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->packInt((char *)&info.slotID); d2->packInt((char *)&info.state); d2->packInt((char *)&info.flags); d2->packInt((char *)&info.ulDeviceError); d2->sendData(); delete d2; } } else if (!strcmp(d->getMsgType(), "C_CloseAllSessions")) { CK_SLOT_ID slotID = 0; printf("Processing: C_Logout\n"); slotID = d->unpackInt(); { CK_RV ret = 0; DataMarshalling *d2 = new DataMarshalling(client); /* * Opening session */ ret = pFunctionList->C_CloseAllSessions(slotID); d2->setMsgType(d->getMsgType()); d2->packInt((char *)&ret); d2->sendData(); delete d2; } } else { pFunctionList->C_Finalize(NULL); } delete d; } }
/* * Log in to the keystore if we are supposed to do that at all. Take care of * reading and caching the PIN etc. Log in only once even when called from * multiple threads. * * Returns: * 1 on success * 0 on failure */ int pk11_token_login(CK_SESSION_HANDLE session, CK_BBOOL *login_done, pkcs11_uri *uri_struct, CK_BBOOL is_private) { CK_RV rv; if ((pubkey_token_flags & CKF_TOKEN_INITIALIZED) == 0) { PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_NOT_INITIALIZED); goto err; } /* * If login is required or needed but the PIN has not been even * initialized we can bail out right now. Note that we are supposed to * always log in if we are going to access private keys. However, we may * need to log in even for accessing public keys in case that the * CKF_LOGIN_REQUIRED flag is set. */ if ((pubkey_token_flags & CKF_LOGIN_REQUIRED || is_private == CK_TRUE) && ~pubkey_token_flags & CKF_USER_PIN_INITIALIZED) { PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_SET); goto err; } /* * Note on locking: it is possible that more than one thread gets into * pk11_get_pin() so we must deal with that. We cannot avoid it since we * cannot guard fork() in there with a lock because we could end up in * a dead lock in the child. Why? Remember we are in a multithreaded * environment so we must lock all mutexes in the prefork function to * avoid a situation in which a thread that did not call fork() held a * lock, making future unlocking impossible. We lock right before * C_Login(). */ if (pubkey_token_flags & CKF_LOGIN_REQUIRED || is_private == CK_TRUE) { if (*login_done == CK_FALSE && uri_struct->askpass == NULL) { PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_PROVIDED); goto err; } if (*login_done == CK_FALSE && uri_struct->askpass != NULL) { if (pk11_get_pin(uri_struct->askpass, &uri_struct->pin) == 0) { PK11err(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_PIN_NOT_PROVIDED); goto err; } } /* * Note that what we are logging into is the keystore from * pubkey_SLOTID because we work with OP_RSA session type here. * That also means that we can work with only one keystore in * the engine. * * We must make sure we do not try to login more than once. * Also, see the comment above on locking strategy. */ (void) pthread_mutex_lock(uri_lock); if (*login_done == CK_FALSE) { if ((rv = pFuncList->C_Login(session, CKU_USER, (CK_UTF8CHAR*)uri_struct->pin, strlen(uri_struct->pin))) != CKR_OK) { PK11err_add_data(PK11_F_TOKEN_LOGIN, PK11_R_TOKEN_LOGIN_FAILED, rv); goto err_locked; } *login_done = CK_TRUE; /* * Cache the passphrasedialog for possible child (which * would need to relogin). */ if (passphrasedialog == NULL && uri_struct->askpass != NULL) { passphrasedialog = strdup(uri_struct->askpass); if (passphrasedialog == NULL) { PK11err_add_data(PK11_F_TOKEN_LOGIN, PK11_R_MALLOC_FAILURE, rv); goto err_locked; } } /* * Check the PIN caching policy. Note that user might * have provided a PIN even when no PIN was required - * in that case we always remove the PIN from memory. */ if (pk11_get_pin_caching_policy() == POLICY_WRONG_VALUE) { PK11err(PK11_F_TOKEN_LOGIN, PK11_R_PIN_CACHING_POLICY_INVALID); goto err_locked; } if (pk11_get_pin_caching_policy() != POLICY_NONE) if (pk11_cache_pin(uri_struct->pin) == 0) goto err_locked; } (void) pthread_mutex_unlock(uri_lock); } else { /* * If token does not require login we take it as the * login was done. */ *login_done = CK_TRUE; } /* * If we raced at pk11_get_pin() we must make sure that all threads that * called pk11_get_pin() will erase the PIN from memory, not just the * one that called C_Login(). Note that if we were supposed to cache the * PIN it was already cached by now so filling "uri_struct.pin" with * zero bytes is always OK since pk11_cache_pin() makes a copy of it. */ if (uri_struct->pin != NULL) memset(uri_struct->pin, 0, strlen(uri_struct->pin)); return (1); err_locked: (void) pthread_mutex_unlock(uri_lock); err: /* Always get rid of the PIN. */ if (uri_struct->pin != NULL) memset(uri_struct->pin, 0, strlen(uri_struct->pin)); return (0); }
int EstEID_signHash(char **signature, unsigned int *signatureLength, CK_SLOT_ID slotID, EstEID_Map cert, const char *hash, unsigned int hashLength, EstEID_PINPromptData pinPromptData) { CK_SESSION_HANDLE session = 0L; if (EstEID_CK_failure("C_OpenSession", fl->C_OpenSession(slotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session))) return FAILURE; const char *givenName = EstEID_mapGet(cert, "givenName"); if (!givenName) givenName = ""; const char *surname = EstEID_mapGet(cert, "surname"); if (!surname) surname = ""; const char *personalID = EstEID_mapGet(cert, "serialNumber"); if (!personalID) personalID = ""; char *name = (char *)malloc(strlen(givenName) + strlen(surname) + strlen(personalID) + 4); sprintf(name, "%s %s", givenName, surname); if(strlen(personalID)) { strcat(name, ", "); strcat(name, personalID); } for (int attempt = 0, blocked = FALSE;; attempt++) { char message[1024]; int remainingTries = EstEID_getRemainingTries(slotID); if (remainingTries == -1) CLOSE_SESSION_AND_FAIL; if (!remainingTries || blocked) { sprintf(EstEID_error, "C_Login error: %s (%li)", pkcs11_error_message(CKR_PIN_LOCKED), CKR_PIN_LOCKED); pinPromptData.alertFunction(pinPromptData.nativeWindowHandle, l10n("PIN2 blocked, cannot sign!")); CLOSE_SESSION_AND_FAIL; } if (remainingTries < 3 || attempt) { sprintf(message, "%s%s %i", (attempt ? l10n("Incorrect PIN2! ") : ""), l10n("Tries left:"), remainingTries); } else { message[0] = 0; } int isPinPad = EstEID_isPinPad(slotID); CK_RV loginResult = CKR_FUNCTION_CANCELED; if(!isPinPad) { // Simple card reader char *pin = pinPromptData.promptFunction(pinPromptData.nativeWindowHandle, name, message, (unsigned)atoi(EstEID_mapGet(cert, "minPinLen")), isPinPad); if (!pin || strlen(pin) == 0) { if (pin) free(pin); setUserCancelErrorCodeAndMessage(); CLOSE_SESSION_AND_FAIL; } loginResult = fl->C_Login(session, CKU_USER, (unsigned char *)pin, strlen(pin)); free(pin); } else { // PIN pad #ifdef _WIN32 EstEID_log("creating pinpad dialog UI thread"); pinpad_thread_result = -1; FAIL_IF_THREAD_ERROR("CreateMutex", (pinpad_thread_mutex = CreateMutex(NULL, FALSE, NULL))); #else EstEID_log("creating pinpad worker thread"); pinpad_thread_result = -1; FAIL_IF_PTHREAD_ERROR("pthread_mutex_init", pthread_mutex_init(&pinpad_thread_mutex, NULL)); FAIL_IF_PTHREAD_ERROR("pthread_cond_init", pthread_cond_init(&pinpad_thread_condition, NULL)); pthread_t pinpad_thread; EstEID_PINPadThreadData threadData; threadData.session = session; threadData.result = CKR_OK; #endif EstEID_log("thread launched"); #ifdef _WIN32 /* NB! Due to Firefox for Windows specific behaviour C_Login() is launched from main thread and UI code is running in separate thread if running on Windows. */ EstEID_PINPromptDataEx pinPromptDataEx; pinPromptDataEx.pinPromptData = pinPromptData; pinPromptDataEx.message = message; pinPromptDataEx.name = name; CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&EstEID_pinPadLogin, (LPVOID)&pinPromptDataEx, 0, NULL); loginResult = fl->C_Login(session, CKU_USER, NULL, 0); closePinPadModalSheet(); #else FAIL_IF_PTHREAD_ERROR("pthread_create", pthread_create(&pinpad_thread, NULL, EstEID_pinPadLogin, (void*)&threadData)); pinPromptData.promptFunction(pinPromptData.nativeWindowHandle, name, message, 0, isPinPad); loginResult = threadData.result; #endif EstEID_log("pinpad sheet/dialog closed"); if (loginResult == CKR_FUNCTION_CANCELED) { setUserCancelErrorCodeAndMessage(); CLOSE_SESSION_AND_FAIL; } } EstEID_log("loginResult = %s", pkcs11_error_message(loginResult)); switch (loginResult) { case CKR_PIN_LOCKED: blocked = TRUE; case CKR_PIN_INCORRECT: case CKR_PIN_INVALID: case CKR_PIN_LEN_RANGE: EstEID_log("this was attempt %i, loginResult causes to run next round", attempt); continue; default: if (EstEID_CK_failure("C_Login", loginResult)) CLOSE_SESSION_AND_FAIL; } break; // Login successful - correct PIN supplied } if (name){ free(name); name = NULL; } CK_OBJECT_CLASS objectClass = CKO_PRIVATE_KEY; CK_ATTRIBUTE searchAttribute = {CKA_CLASS, &objectClass, sizeof(objectClass)}; if (EstEID_CK_failure("C_FindObjectsInit", fl->C_FindObjectsInit(session, &searchAttribute, 1))) CLOSE_SESSION_AND_FAIL; CK_OBJECT_HANDLE privateKeyHandle; CK_ULONG objectCount; if (EstEID_CK_failure("C_FindObjects", fl->C_FindObjects(session, &privateKeyHandle, 1, &objectCount))) CLOSE_SESSION_AND_FAIL; if (EstEID_CK_failure("C_FindObjectsFinal", fl->C_FindObjectsFinal(session))) CLOSE_SESSION_AND_FAIL; if (objectCount == 0) CLOSE_SESSION_AND_FAIL; // todo ?? set error message CK_MECHANISM mechanism = {CKM_RSA_PKCS, 0, 0}; if (EstEID_CK_failure("C_SignInit", fl->C_SignInit(session, &mechanism, privateKeyHandle))) CLOSE_SESSION_AND_FAIL; unsigned int hashWithPaddingLength; char *hashWithPadding = EstEID_addPadding(hash, hashLength, &hashWithPaddingLength); CK_ULONG len; if (EstEID_CK_failure("C_Sign", fl->C_Sign(session, (CK_BYTE_PTR)hashWithPadding, hashWithPaddingLength, NULL, &len))) { free(hashWithPadding); CLOSE_SESSION_AND_FAIL; } *signature = (char *)malloc(len); if (EstEID_CK_failure("C_Sign", fl->C_Sign(session, (CK_BYTE_PTR)hashWithPadding, hashWithPaddingLength, (CK_BYTE_PTR) * signature, &len))) { free(hashWithPadding); CLOSE_SESSION_AND_FAIL; } *signatureLength = len; free(hashWithPadding); if (session) { if (EstEID_CK_failure("C_CloseSession", fl->C_CloseSession(session))) { return FAILURE; } } EstEID_log("successfully signed"); return SUCCESS; }
// Import a newly generated RSA1024 pvt key and a certificate // to every slot and use the key to sign some data static void test_import_and_sign_all_10_RSA() { EVP_PKEY *evp; RSA *rsak; X509 *cert; ASN1_TIME *tm; CK_BYTE i, j; CK_BYTE some_data[32]; CK_BYTE e[] = {0x01, 0x00, 0x01}; CK_BYTE p[64]; CK_BYTE q[64]; CK_BYTE dp[64]; CK_BYTE dq[64]; CK_BYTE qinv[64]; BIGNUM *e_bn; CK_ULONG class_k = CKO_PRIVATE_KEY; CK_ULONG class_c = CKO_CERTIFICATE; CK_ULONG kt = CKK_RSA; CK_BYTE id = 0; CK_BYTE sig[64]; CK_ULONG recv_len; CK_BYTE value_c[3100]; CK_ULONG cert_len; CK_BYTE der_encoded[80]; CK_BYTE_PTR der_ptr; CK_BYTE_PTR r_ptr; CK_BYTE_PTR s_ptr; CK_ULONG r_len; CK_ULONG s_len; unsigned char *px; CK_ATTRIBUTE privateKeyTemplate[] = { {CKA_CLASS, &class_k, sizeof(class_k)}, {CKA_KEY_TYPE, &kt, sizeof(kt)}, {CKA_ID, &id, sizeof(id)}, {CKA_PUBLIC_EXPONENT, e, sizeof(e)}, {CKA_PRIME_1, p, sizeof(p)}, {CKA_PRIME_2, q, sizeof(q)}, {CKA_EXPONENT_1, dp, sizeof(dp)}, {CKA_EXPONENT_2, dq, sizeof(dq)}, {CKA_COEFFICIENT, qinv, sizeof(qinv)} }; CK_ATTRIBUTE publicKeyTemplate[] = { {CKA_CLASS, &class_c, sizeof(class_c)}, {CKA_ID, &id, sizeof(id)}, {CKA_VALUE, value_c, sizeof(value_c)} }; CK_OBJECT_HANDLE obj[24]; CK_SESSION_HANDLE session; CK_MECHANISM mech = {CKM_RSA_PKCS, NULL}; evp = EVP_PKEY_new(); if (evp == NULL) exit(EXIT_FAILURE); rsak = RSA_new(); if (rsak == NULL) exit(EXIT_FAILURE); e_bn = BN_bin2bn(e, 3, NULL); if (e_bn == NULL) exit(EXIT_FAILURE); asrt(RSA_generate_key_ex(rsak, 1024, e_bn, NULL), 1, "GENERATE RSAK"); asrt(BN_bn2bin(rsak->p, p), 64, "GET P"); asrt(BN_bn2bin(rsak->q, q), 64, "GET Q"); asrt(BN_bn2bin(rsak->dmp1, dp), 64, "GET DP"); asrt(BN_bn2bin(rsak->dmq1, dp), 64, "GET DQ"); asrt(BN_bn2bin(rsak->iqmp, qinv), 64, "GET QINV"); if (EVP_PKEY_set1_RSA(evp, rsak) == 0) exit(EXIT_FAILURE); cert = X509_new(); if (cert == NULL) exit(EXIT_FAILURE); if (X509_set_pubkey(cert, evp) == 0) exit(EXIT_FAILURE); tm = ASN1_TIME_new(); if (tm == NULL) exit(EXIT_FAILURE); ASN1_TIME_set_string(tm, "000001010000Z"); X509_set_notBefore(cert, tm); X509_set_notAfter(cert, tm); cert->sig_alg->algorithm = OBJ_nid2obj(8); cert->cert_info->signature->algorithm = OBJ_nid2obj(8); ASN1_BIT_STRING_set_bit(cert->signature, 8, 1); ASN1_BIT_STRING_set(cert->signature, "\x00", 1); px = value_c; if ((cert_len = (CK_ULONG) i2d_X509(cert, &px)) == 0 || cert_len > sizeof(value_c)) exit(EXIT_FAILURE); publicKeyTemplate[2].ulValueLen = cert_len; asrt(funcs->C_Initialize(NULL), CKR_OK, "INITIALIZE"); asrt(funcs->C_OpenSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &session), CKR_OK, "OpenSession1"); asrt(funcs->C_Login(session, CKU_SO, "010203040506070801020304050607080102030405060708", 48), CKR_OK, "Login SO"); for (i = 0; i < 24; i++) { id = i; asrt(funcs->C_CreateObject(session, publicKeyTemplate, 3, obj + i), CKR_OK, "IMPORT CERT"); asrt(funcs->C_CreateObject(session, privateKeyTemplate, 9, obj + i), CKR_OK, "IMPORT KEY"); } asrt(funcs->C_Logout(session), CKR_OK, "Logout SO"); for (i = 0; i < 24; i++) { for (j = 0; j < 10; j++) { if(RAND_pseudo_bytes(some_data, sizeof(some_data)) == -1) exit(EXIT_FAILURE); asrt(funcs->C_Login(session, CKU_USER, "123456", 6), CKR_OK, "Login USER"); asrt(funcs->C_SignInit(session, &mech, obj[i]), CKR_OK, "SignInit"); recv_len = sizeof(sig); asrt(funcs->C_Sign(session, some_data, sizeof(some_data), sig, &recv_len), CKR_OK, "Sign"); /* r_len = 32; */ /* s_len = 32; */ /* der_ptr = der_encoded; */ /* *der_ptr++ = 0x30; */ /* *der_ptr++ = 0xff; // placeholder, fix below */ /* r_ptr = sig; */ /* *der_ptr++ = 0x02; */ /* *der_ptr++ = r_len; */ /* if (*r_ptr >= 0x80) { */ /* *(der_ptr - 1) = *(der_ptr - 1) + 1; */ /* *der_ptr++ = 0x00; */ /* } */ /* else if (*r_ptr == 0x00 && *(r_ptr + 1) < 0x80) { */ /* r_len--; */ /* *(der_ptr - 1) = *(der_ptr - 1) - 1; */ /* r_ptr++; */ /* } */ /* memcpy(der_ptr, r_ptr, r_len); */ /* der_ptr+= r_len; */ /* s_ptr = sig + 32; */ /* *der_ptr++ = 0x02; */ /* *der_ptr++ = s_len; */ /* if (*s_ptr >= 0x80) { */ /* *(der_ptr - 1) = *(der_ptr - 1) + 1; */ /* *der_ptr++ = 0x00; */ /* } */ /* else if (*s_ptr == 0x00 && *(s_ptr + 1) < 0x80) { */ /* s_len--; */ /* *(der_ptr - 1) = *(der_ptr - 1) - 1; */ /* s_ptr++; */ /* } */ /* memcpy(der_ptr, s_ptr, s_len); */ /* der_ptr+= s_len; */ /* der_encoded[1] = der_ptr - der_encoded - 2; */ /* dump_hex(der_encoded, der_encoded[1] + 2, stderr, 1); */ /* asrt(ECDSA_verify(0, some_data, sizeof(some_data), der_encoded, der_encoded[1] + 2, eck), 1, "ECDSA VERIFICATION"); */ } } asrt(funcs->C_Logout(session), CKR_OK, "Logout USER"); asrt(funcs->C_CloseSession(session), CKR_OK, "CloseSession"); asrt(funcs->C_Finalize(NULL), CKR_OK, "FINALIZE"); }
// Import a newly generated P256 pvt key and a certificate // to every slot and use the key to sign some data static void test_import_and_sign_all_10() { EVP_PKEY *evp; EC_KEY *eck; const EC_POINT *ecp; const BIGNUM *bn; char pvt[32]; X509 *cert; ASN1_TIME *tm; CK_BYTE i, j; CK_BYTE some_data[32]; CK_ULONG class_k = CKO_PRIVATE_KEY; CK_ULONG class_c = CKO_CERTIFICATE; CK_ULONG kt = CKK_ECDSA; CK_BYTE id = 0; CK_BYTE params[] = {0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07}; CK_BYTE sig[64]; CK_ULONG recv_len; CK_BYTE value_c[3100]; CK_ULONG cert_len; CK_BYTE der_encoded[80]; CK_BYTE_PTR der_ptr; CK_BYTE_PTR r_ptr; CK_BYTE_PTR s_ptr; CK_ULONG r_len; CK_ULONG s_len; unsigned char *p; CK_ATTRIBUTE privateKeyTemplate[] = { {CKA_CLASS, &class_k, sizeof(class_k)}, {CKA_KEY_TYPE, &kt, sizeof(kt)}, {CKA_ID, &id, sizeof(id)}, {CKA_EC_PARAMS, ¶ms, sizeof(params)}, {CKA_VALUE, pvt, sizeof(pvt)} }; CK_ATTRIBUTE publicKeyTemplate[] = { {CKA_CLASS, &class_c, sizeof(class_c)}, {CKA_ID, &id, sizeof(id)}, {CKA_VALUE, value_c, sizeof(value_c)} }; CK_OBJECT_HANDLE obj[24]; CK_SESSION_HANDLE session; CK_MECHANISM mech = {CKM_ECDSA, NULL}; evp = EVP_PKEY_new(); if (evp == NULL) exit(EXIT_FAILURE); eck = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); if (eck == NULL) exit(EXIT_FAILURE); asrt(EC_KEY_generate_key(eck), 1, "GENERATE ECK"); bn = EC_KEY_get0_private_key(eck); asrt(BN_bn2bin(bn, pvt), 32, "EXTRACT PVT"); if (EVP_PKEY_set1_EC_KEY(evp, eck) == 0) exit(EXIT_FAILURE); cert = X509_new(); if (cert == NULL) exit(EXIT_FAILURE); if (X509_set_pubkey(cert, evp) == 0) exit(EXIT_FAILURE); tm = ASN1_TIME_new(); if (tm == NULL) exit(EXIT_FAILURE); ASN1_TIME_set_string(tm, "000001010000Z"); X509_set_notBefore(cert, tm); X509_set_notAfter(cert, tm); cert->sig_alg->algorithm = OBJ_nid2obj(8); cert->cert_info->signature->algorithm = OBJ_nid2obj(8); ASN1_BIT_STRING_set_bit(cert->signature, 8, 1); ASN1_BIT_STRING_set(cert->signature, "\x00", 1); p = value_c; if ((cert_len = (CK_ULONG) i2d_X509(cert, &p)) == 0 || cert_len > sizeof(value_c)) exit(EXIT_FAILURE); publicKeyTemplate[2].ulValueLen = cert_len; asrt(funcs->C_Initialize(NULL), CKR_OK, "INITIALIZE"); asrt(funcs->C_OpenSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &session), CKR_OK, "OpenSession1"); asrt(funcs->C_Login(session, CKU_SO, "010203040506070801020304050607080102030405060708", 48), CKR_OK, "Login SO"); for (i = 0; i < 24; i++) { id = i; asrt(funcs->C_CreateObject(session, publicKeyTemplate, 3, obj + i), CKR_OK, "IMPORT CERT"); asrt(funcs->C_CreateObject(session, privateKeyTemplate, 5, obj + i), CKR_OK, "IMPORT KEY"); } asrt(funcs->C_Logout(session), CKR_OK, "Logout SO"); for (i = 0; i < 24; i++) { for (j = 0; j < 10; j++) { if(RAND_pseudo_bytes(some_data, sizeof(some_data)) == -1) exit(EXIT_FAILURE); asrt(funcs->C_Login(session, CKU_USER, "123456", 6), CKR_OK, "Login USER"); asrt(funcs->C_SignInit(session, &mech, obj[i]), CKR_OK, "SignInit"); recv_len = sizeof(sig); asrt(funcs->C_Sign(session, some_data, sizeof(some_data), sig, &recv_len), CKR_OK, "Sign"); r_len = 32; s_len = 32; der_ptr = der_encoded; *der_ptr++ = 0x30; *der_ptr++ = 0xff; // placeholder, fix below r_ptr = sig; *der_ptr++ = 0x02; *der_ptr++ = r_len; if (*r_ptr >= 0x80) { *(der_ptr - 1) = *(der_ptr - 1) + 1; *der_ptr++ = 0x00; } else if (*r_ptr == 0x00 && *(r_ptr + 1) < 0x80) { r_len--; *(der_ptr - 1) = *(der_ptr - 1) - 1; r_ptr++; } memcpy(der_ptr, r_ptr, r_len); der_ptr+= r_len; s_ptr = sig + 32; *der_ptr++ = 0x02; *der_ptr++ = s_len; if (*s_ptr >= 0x80) { *(der_ptr - 1) = *(der_ptr - 1) + 1; *der_ptr++ = 0x00; } else if (*s_ptr == 0x00 && *(s_ptr + 1) < 0x80) { s_len--; *(der_ptr - 1) = *(der_ptr - 1) - 1; s_ptr++; } memcpy(der_ptr, s_ptr, s_len); der_ptr+= s_len; der_encoded[1] = der_ptr - der_encoded - 2; dump_hex(der_encoded, der_encoded[1] + 2, stderr, 1); asrt(ECDSA_verify(0, some_data, sizeof(some_data), der_encoded, der_encoded[1] + 2, eck), 1, "ECDSA VERIFICATION"); } } asrt(funcs->C_Logout(session), CKR_OK, "Logout USER"); asrt(funcs->C_CloseSession(session), CKR_OK, "CloseSession"); asrt(funcs->C_Finalize(NULL), CKR_OK, "FINALIZE"); }