== RevisiĆ³n de software XCA == XCA options [[Image(xcaOptions.png)]] Add, Remove, Search. '''Options.cpp''' {{{ addLib(QString fname) pkcs11:load_lib(fname, false) class pkcs11 { friend class pk11_attribute; friend class pk11_attr_ulong; friend class pk11_attr_data; private: static pkcs11_lib_list libs; slotid p11slot; CK_SESSION_HANDLE session; CK_OBJECT_HANDLE p11obj; public: pkcs11(); ~pkcs11(); static bool loaded() { return libs.count() != 0; } static pkcs11_lib *load_lib(QString fname, bool silent); static pkcs11_lib *get_lib(QString fname) { return libs.get_lib(fname); } static bool remove_lib(QString fname) { return libs.remove_lib(fname); } static void remove_libs() { while (!libs.isEmpty()) delete libs.takeFirst(); } static void load_libs(QString list, bool silent); static pkcs11_lib_list get_libs() { return libs; } tkInfo tokenInfo(slotid slot); tkInfo tokenInfo() { return tokenInfo(p11slot); } QString driverInfo(slotid slot) { return slot.lib->driverInfo(); } slotidList getSlotList() { return libs.getSlotList(); } bool selectToken(slotid *slot, QWidget *w); void changePin(slotid slot, bool so); void initPin(slotid slot); void initToken(slotid slot, unsigned char *pin, int pinlen, QString label); QList mechanismList(slotid slot); void mechanismInfo(slotid slot, CK_MECHANISM_TYPE m, CK_MECHANISM_INFO *info); void startSession(slotid slot, bool rw = false); /* Session based functions */ void loadAttribute(pk11_attribute &attribute, CK_OBJECT_HANDLE object); void storeAttribute(pk11_attribute &attribute, CK_OBJECT_HANDLE object); QList objectList(pk11_attlist &atts); QString tokenLogin(QString name, bool so, bool force=false); void getRandom(); void logout(); bool needsLogin(bool so); void login(unsigned char *pin, unsigned long pinlen, bool so); void setPin(unsigned char *oldPin, unsigned long oldPinLen, unsigned char *pin, unsigned long pinLen); CK_OBJECT_HANDLE createObject(pk11_attlist &attrs); pk11_attr_data findUniqueID(unsigned long oclass); pk11_attr_data generateKey(QString name, unsigned long ec_rsa_mech, unsigned long bits, int nid); int deleteObjects(QList objects); EVP_PKEY *getPrivateKey(EVP_PKEY *pub, CK_OBJECT_HANDLE obj); int encrypt(int flen, const unsigned char *from, unsigned char *to, int tolen, unsigned long m); int decrypt(int flen, const unsigned char *from, unsigned char *to, int tolen, unsigned long m); }; }}} '''Search''' {{{ bool searchThread::checkLib(QString file) { qint64 siz; int r = -1; QFile qf(file); siz = qf.size(); if (qf.open(QIODevice::ReadOnly)) { uchar *p = qf.map(0, siz); r = QByteArray::fromRawData((char*)p, siz) .indexOf("C_GetFunctionList"); qf.unmap(p); qf.close(); } return r != -1; } }}} '''https://github.com/open-eid/browser-token-signing/blob/master/common/esteid_sign.c''' {{{ 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; CK_RV loginResult = CKR_FUNCTION_CANCELED; char *name; char message[1024]; int remainingTries = -1; int attempt = 0, blocked = FALSE; int isPinPad; unsigned int privateKeyIndex; #ifdef _WIN32 EstEID_PINPromptDataEx pinPromptDataEx; #endif LOG_LOCATION; if (EstEID_CK_failure("C_OpenSession", fl->C_OpenSession(slotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &session))) return FAILURE; name = EstEID_getFullNameWithPersonalCode(cert); privateKeyIndex = (unsigned)atoi(EstEID_mapGet(cert, "privateKeyIndex")); remainingTries = EstEID_getRemainingTries(slotID); for (attempt = 0;; attempt++) { 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, cannot 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; } isPinPad = EstEID_isPinPad(slotID); 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) { 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. */ 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: remainingTries--; 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, privateKeyIndex); } int EstEID_RealSign(CK_SESSION_HANDLE session, char **signature, unsigned int *signatureLength, const char *hash, unsigned int hashLength, char* name, unsigned int privateKeyIndex) { CK_ULONG objectCount; unsigned int hashWithPaddingLength = 0; char *hashWithPadding; CK_MECHANISM mechanism = {CKM_RSA_PKCS, 0, 0}; CK_OBJECT_CLASS objectClass = CKO_PRIVATE_KEY; CK_ATTRIBUTE searchAttribute = {CKA_CLASS, &objectClass, sizeof(objectClass)}; unsigned int max = privateKeyIndex + 1; CK_OBJECT_HANDLE privateKeyHandle[max]; if (EstEID_CK_failure("C_FindObjectsInit", fl->C_FindObjectsInit(session, &searchAttribute, 1))) CLOSE_SESSION_AND_RETURN(FAILURE); if (EstEID_CK_failure("C_FindObjects", fl->C_FindObjects(session, privateKeyHandle, max, &objectCount))) CLOSE_SESSION_AND_RETURN(FAILURE); if (EstEID_CK_failure("C_FindObjectsFinal", fl->C_FindObjectsFinal(session))) CLOSE_SESSION_AND_RETURN(FAILURE); if (objectCount == 0) CLOSE_SESSION_AND_RETURN(FAILURE); // todo ?? set error message EstEID_log("found %i private keys in slot, using key in position %i", objectCount, privateKeyIndex); if (EstEID_CK_failure("C_SignInit", fl->C_SignInit(session, &mechanism, privateKeyHandle[privateKeyIndex]))) CLOSE_SESSION_AND_RETURN(FAILURE); hashWithPadding = EstEID_addPadding(hash, hashLength, &hashWithPaddingLength); if (hashWithPadding) { // This is additional safeguard, as digest length is checked already before calling EstEID_addPadding() 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_RETURN(FAILURE); } *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_RETURN(FAILURE); } *signatureLength = len; free(hashWithPadding); } if (session) { if (EstEID_CK_failure("C_CloseSession", fl->C_CloseSession(session))) { return FAILURE; } } if(name) { free(name); } if (!hashWithPaddingLength) { // This is additional safeguard, as digest length is checked already before calling EstEID_addPadding() EstEID_log("will not sign due to incorrect incoming message digest length"); return FAILURE; } EstEID_log("successfully signed"); return SUCCESS; } }}}