Index: build/chrome/Makefile ================================================================== --- build/chrome/Makefile +++ build/chrome/Makefile @@ -35,12 +35,12 @@ cackey.zip: $(CACKEY_EXECUTABLES) cackey.nmf manifest.json cackey.js google-pcsc.js pin.html pin.js pin-icon.png icon.png rm -f cackey.zip zip cackey.zip.new $^ mv cackey.zip.new cackey.zip -cackey.bc: cackey-chrome.o cackey-chrome-init.o lib/libcackey.a lib/libpcsc.a lib/libz.a - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o cackey.bc.new cackey-chrome.o cackey-chrome-init.o $(LIBS) +cackey.bc: cackey-chrome-pkcs11.o cackey-chrome-plugin.o lib/libcackey.a lib/libpcsc.a lib/libz.a + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o cackey.bc.new cackey-chrome-pkcs11.o cackey-chrome-plugin.o $(LIBS) mv cackey.bc.new cackey.bc cackey.pexe: cackey.bc cp cackey.bc cackey.pexe.new $(FINALIZE) cackey.pexe.new @@ -82,18 +82,18 @@ rm -f include/PCSC/pcsc-nacl.h.new include/PCSC/pcsc-nacl.h cd include/PCSC && ln -s ../../workdir-*.inst/include/PCSC/pcsc-nacl.h pcsc-nacl.h.new touch include/PCSC/pcsc-nacl.h.new mv include/PCSC/pcsc-nacl.h.new include/PCSC/pcsc-nacl.h -test: cackey-chrome.c cackey-chrome-test.c ../../cackey.c Makefile - gcc -g3 -ggdb3 -Wall -I. -I../../pkcs11 -I/opt/appfs/core.appfs.rkeene.org/zlib/platform/latest/include -I/opt/appfs/rkeene.org/pcsc-lite/platform/latest/include/PCSC -DHAVE_WINTYPES_H=1 -DHAVE_PCSCLITE_H=1 -DHAVE_WINSCARD_H=1 -DHAVE_STDINT_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDLIB_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRING_H=1 -DHAVE_PTHREAD_H=1 -DHAVE_LIMITS_H=1 -DHAVE_STDIO_H=1 -DHAVE_ZLIB_H -DHAVE_LIBZ -DCACKEY_DEBUG=1 -o test cackey-chrome.c cackey-chrome-test.c ../../cackey.c -L/opt/appfs/core.appfs.rkeene.org/zlib/platform/latest/lib -lz -L/opt/appfs/rkeene.org/pcsc-lite/platform/latest/lib -lpcsclite -L/opt/appfs/core.appfs.rkeene.org/glibc/platform/latest/lib -lc -lpthread -Wl,-R,/opt/appfs/core.appfs.rkeene.org/zlib/platform/latest/lib -Wl,-R,/opt/appfs/rkeene.org/pcsc-lite/platform/latest/lib -Wl,-R,/opt/appfs/core.appfs.rkeene.org/glibc/platform/latest/lib -Wl,-dynamic-linker,/opt/appfs/core.appfs.rkeene.org/glibc/platform/latest/lib/ld-linux-x86-64.so.2 +test: cackey-chrome-pkcs11.c cackey-chrome-test.c ../../cackey.c Makefile + gcc -g3 -ggdb3 -Wall -I. -I../../pkcs11 -I/opt/appfs/core.appfs.rkeene.org/zlib/platform/latest/include -I/opt/appfs/rkeene.org/pcsc-lite/platform/latest/include/PCSC -DHAVE_WINTYPES_H=1 -DHAVE_PCSCLITE_H=1 -DHAVE_WINSCARD_H=1 -DHAVE_STDINT_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDLIB_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRING_H=1 -DHAVE_PTHREAD_H=1 -DHAVE_LIMITS_H=1 -DHAVE_STDIO_H=1 -DHAVE_ZLIB_H -DHAVE_LIBZ -DCACKEY_DEBUG=1 -o test cackey-chrome-pkcs11.c cackey-chrome-test.c ../../cackey.c -L/opt/appfs/core.appfs.rkeene.org/zlib/platform/latest/lib -lz -L/opt/appfs/rkeene.org/pcsc-lite/platform/latest/lib -lpcsclite -L/opt/appfs/core.appfs.rkeene.org/glibc/platform/latest/lib -lc -lpthread -Wl,-R,/opt/appfs/core.appfs.rkeene.org/zlib/platform/latest/lib -Wl,-R,/opt/appfs/rkeene.org/pcsc-lite/platform/latest/lib -Wl,-R,/opt/appfs/core.appfs.rkeene.org/glibc/platform/latest/lib -Wl,-dynamic-linker,/opt/appfs/core.appfs.rkeene.org/glibc/platform/latest/lib/ld-linux-x86-64.so.2 -cackey-chrome.o: cackey-chrome.c cackey-chrome.h -cackey-chrome-init.o: cackey-chrome-init.cc cackey-chrome.h include/PCSC/pcsc-nacl.h +cackey-chrome-pkcs11.o: cackey-chrome-pkcs11.c cackey-chrome.h +cackey-chrome-plugin.o: cackey-chrome-plugin.cc cackey-chrome.h include/PCSC/pcsc-nacl.h clean: - rm -f cackey-chrome.o cackey-chrome-init.o + rm -f cackey-chrome-pkcs11.o cackey-chrome-plugin.o rm -f cackey.pexe cackey.bc rm -f cackey.zip cackey.nmf rm -f test distclean: clean DELETED build/chrome/cackey-chrome-init.cc Index: build/chrome/cackey-chrome-init.cc ================================================================== --- build/chrome/cackey-chrome-init.cc +++ build/chrome/cackey-chrome-init.cc @@ -1,264 +0,0 @@ -/* - * Google's PCSC library requires us to write our module in C++ to initialize - * it. This component handles the initialization of our module and handles - * incoming messages, passing them either to our library (cackey-chrome) or - * to the PCSC-NaCl library from Google as appropriate. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "pcsc-nacl.h" -#include "cackey-chrome.h" - -class CACKeyInstance : public pp::Instance { - private: - pp::Core *corePointer; - public: - explicit CACKeyInstance(PP_Instance instance, pp::Core *core) : pp::Instance(instance) { - corePointer = core; - } - - virtual ~CACKeyInstance() {} - - virtual void HandleMessageThread(pp::VarDictionary *message, pp::Var *messagePlain) { - cackey_chrome_returnType signRet; - char *pinPrompt = NULL; - const char *pin; - const char *smartcardManagerAppId = NULL; - unsigned char buffer[8192]; - struct cackey_certificate *certificates, incomingCertificateCACKey; - pp::VarDictionary *reply; - pp::VarArray certificatesPPArray; - pp::VarArrayBuffer *certificateContents, *incomingCertificateContents, *incomingData, *outgoingData; - pp::Var command; - int numCertificates, i; - unsigned long outgoingDataLength; - - /* - * Extract the command - */ - command = message->Get("command"); - - /* - * Do the thing we are being asked to do - */ - reply = new pp::VarDictionary(); - - if (command.AsString() == "init") { - if (message->HasKey("smartcardManagerAppId")) { - smartcardManagerAppId = strdup(message->Get("smartcardManagerAppId").AsString().c_str()); - } - - pcscNaClInit(this, corePointer, smartcardManagerAppId, "CACKey"); - - if (smartcardManagerAppId) { - free((void *) smartcardManagerAppId); - } - - reply->Set("status", "success"); - } else if (command.AsString() == "listcertificates") { - numCertificates = cackey_chrome_listCertificates(&certificates); - - certificatesPPArray.SetLength(numCertificates); - - for (i = 0; i < numCertificates; i++) { - certificateContents = new pp::VarArrayBuffer(certificates[i].certificate_len); - - memcpy(certificateContents->Map(), certificates[i].certificate, certificates[i].certificate_len); - - certificateContents->Unmap(); - - certificatesPPArray.Set(i, *certificateContents); - - delete certificateContents; - } - - cackey_chrome_freeCertificates(certificates, numCertificates); - - reply->Set("status", "success"); - reply->Set("certificates", certificatesPPArray); - } else if (command.AsString() == "sign") { - if (!message->HasKey("certificate")) { - reply->Set("status", "error"); - reply->Set("error", "Certificate not supplied"); - } else if (!message->HasKey("data")) { - reply->Set("status", "error"); - reply->Set("error", "Data not supplied"); - } else { - incomingCertificateContents = new pp::VarArrayBuffer(message->Get("certificate")); - incomingData = new pp::VarArrayBuffer(message->Get("data")); - - if (message->HasKey("pin")) { - pin = message->Get("pin").AsString().c_str(); - } else { - pin = NULL; - } - - incomingCertificateCACKey.certificate = incomingCertificateContents->Map(); - incomingCertificateCACKey.certificate_len = incomingCertificateContents->ByteLength(); - - outgoingDataLength = sizeof(buffer); - - signRet = cackey_chrome_signMessage(&incomingCertificateCACKey, - incomingData->Map(), incomingData->ByteLength(), - buffer, &outgoingDataLength, - &pinPrompt, pin - ); - - incomingCertificateContents->Unmap(); - incomingData->Unmap(); - - delete incomingCertificateContents; - delete incomingData; - - switch (signRet) { - case CACKEY_CHROME_OK: - outgoingData = new pp::VarArrayBuffer(outgoingDataLength); - - memcpy(outgoingData->Map(), buffer, outgoingDataLength); - - outgoingData->Unmap(); - - reply->Set("status", "success"); - reply->Set("signedData", *outgoingData); - - delete outgoingData; - - break; - case CACKEY_CHROME_ERROR: - reply->Set("status", "error"); - reply->Set("error", "Unable to sign data"); - break; - case CACKEY_CHROME_NEEDLOGIN: - case CACKEY_CHROME_NEEDPROTECTEDLOGIN: - reply->Set("status", "retry"); - reply->Set("originalrequest", *messagePlain); - reply->Set("pinprompt", pinPrompt); - - break; - } - - if (pinPrompt != NULL) { - free(pinPrompt); - } - } - } else { - reply->Set("status", "error"); - reply->Set("error", "Invalid command"); - } - - /* - * If a message ID was sent in the request, include it in the reply - */ - if (message->HasKey("id")) { - reply->Set("id", message->Get("id")); - } - - /* - * Indicate who our message is for - */ - reply->Set("target", "cackey"); - reply->Set("command", command); - - /* - * Send the reply back to the requestor, hopefully they are waiting for this message - */ - PostMessage(*reply); - - delete reply; - - delete message; - - delete messagePlain; - - return; - } - - virtual void HandleMessage(const pp::Var& messagePlain) { - pp::VarDictionary *message; - pp::Var *messagePlainCopy; - pp::Var target; - - /* - * The incoming message must be a dictionary - */ - if (!messagePlain.is_dictionary()) { - pcscNaClHandleMessage(messagePlain); - - return; - } - - /* - * Process the appropriate command from the incoming message - */ - message = new pp::VarDictionary(messagePlain); - - /* - * Verify that this message is destined for us - */ - if (!message->HasKey("target")) { - delete message; - - /* We don't handle this message, see if PCSC-NaCl does */ - pcscNaClHandleMessage(messagePlain); - - return; - } - - target = message->Get("target"); - if (target.AsString() != "cackey") { - delete message; - - /* We don't handle this message, see if PCSC-NaCl does */ - pcscNaClHandleMessage(messagePlain); - - return; - } - - /* - * Determine what we are being asked to do - */ - if (!message->HasKey("command")) { - delete message; - - /* We don't handle this message, see if PCSC-NaCl does */ - pcscNaClHandleMessage(messagePlain); - - return; - } - - /* - * Process the request in another thread - */ - messagePlainCopy = new pp::Var(messagePlain); - std::thread(&CACKeyInstance::HandleMessageThread, this, message, messagePlainCopy).detach(); - - return; - } -}; - -class CACKeyModule : public pp::Module { - public: - CACKeyModule() : pp::Module() {} - virtual ~CACKeyModule() {} - - virtual pp::Instance *CreateInstance(PP_Instance instance) { - return(new CACKeyInstance(instance, core())); - } -}; - -namespace pp { - Module *CreateModule() { - return(new CACKeyModule()); - } -} ADDED build/chrome/cackey-chrome-pkcs11.c Index: build/chrome/cackey-chrome-pkcs11.c ================================================================== --- build/chrome/cackey-chrome-pkcs11.c +++ build/chrome/cackey-chrome-pkcs11.c @@ -0,0 +1,576 @@ +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#include "mypkcs11.h" +#include "cackey-chrome.h" + +struct cackey_chrome_id { + void *id; + size_t idLen; + int initialized; +}; + +static CK_FUNCTION_LIST_PTR moduleFunctionList = NULL; + +static CK_RV cackey_chrome_init(void) { + CK_C_INITIALIZE_ARGS initargs; + CK_RV chk_rv; + + if (moduleFunctionList != NULL) { + return(CKR_OK); + } + + chk_rv = C_GetFunctionList(&moduleFunctionList); + if (chk_rv != CKR_OK) { + return(chk_rv); + } + + initargs.CreateMutex = NULL; + initargs.DestroyMutex = NULL; + initargs.LockMutex = NULL; + initargs.UnlockMutex = NULL; + initargs.flags = CKF_OS_LOCKING_OK; + initargs.pReserved = NULL; + + chk_rv = moduleFunctionList->C_Initialize(&initargs); + if (chk_rv != CKR_OK) { + return(chk_rv); + } + + return(CKR_OK); +} + +void cackey_chrome_terminate(void) { + if (!moduleFunctionList) { + return; + } + + moduleFunctionList->C_Finalize(NULL); + + free(moduleFunctionList); + + moduleFunctionList = NULL; + + return; +} + +static CK_RV cackey_chrome_GetAttributesFromTemplate(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE *attrTemplate, CK_ULONG attrTemplateCount) { + CK_RV chk_rv; + CK_ATTRIBUTE *currAttr; + CK_ULONG currAttrIndex; + + for (currAttrIndex = 0; currAttrIndex < attrTemplateCount; currAttrIndex++) { + currAttr = &attrTemplate[currAttrIndex]; + + currAttr->pValue = NULL; + currAttr->ulValueLen = 0; + } + + chk_rv = moduleFunctionList->C_GetAttributeValue(hSession, hObject, attrTemplate, attrTemplateCount); + if (chk_rv == CKR_ATTRIBUTE_TYPE_INVALID || chk_rv == CKR_ATTRIBUTE_SENSITIVE || chk_rv == CKR_BUFFER_TOO_SMALL) { + chk_rv = CKR_OK; + } + + if (chk_rv != CKR_OK) { + return(chk_rv); + } + + for (currAttrIndex = 0; currAttrIndex < attrTemplateCount; currAttrIndex++) { + currAttr = &attrTemplate[currAttrIndex]; + + if (currAttr->ulValueLen == 0) { + continue; + } + + if (((CK_LONG) currAttr->ulValueLen) == ((CK_LONG) -1)) { + continue; + } + + currAttr->pValue = malloc(currAttr->ulValueLen); + } + + chk_rv = moduleFunctionList->C_GetAttributeValue(hSession, hObject, attrTemplate, attrTemplateCount); + if (chk_rv != CKR_OK) { + free(currAttr->pValue); + + return(chk_rv); + } + + return(CKR_OK); +} + +int cackey_chrome_listCertificates(struct cackey_certificate **certificates) { + CK_RV chk_rv; + CK_ULONG numSlots, currSlot; + CK_SLOT_ID_PTR slots; + CK_SLOT_INFO slotInfo; + CK_SESSION_HANDLE hSession; + CK_OBJECT_HANDLE hObject; + CK_ULONG ulObjectCount; + CK_ATTRIBUTE searchTemplatePrivateKeys[] = { + {CKA_CLASS, NULL, sizeof(CK_OBJECT_CLASS)} + }; + CK_ATTRIBUTE searchTemplateCertificates[] = { + {CKA_CLASS, NULL, sizeof(CK_OBJECT_CLASS)}, + {CKA_ID, NULL, 0} + }; + CK_ATTRIBUTE attrTemplatePrivateKey[] = { + {CKA_ID, NULL, 0} + }; + CK_ATTRIBUTE attrTemplateCertificate[] = { + {CKA_VALUE, NULL, 0} + }; + CK_OBJECT_CLASS objectClassPrivateKey = CKO_PRIVATE_KEY; + CK_OBJECT_CLASS objectClassCertificate = CKO_CERTIFICATE; + struct cackey_chrome_id *ids; + int idsCount, currId; + int foundCertificates, certificatesCount; + + *certificates = NULL; + + chk_rv = cackey_chrome_init(); + if (chk_rv != CKR_OK) { + return(0); + } + + chk_rv = moduleFunctionList->C_GetSlotList(FALSE, NULL, &numSlots); + if (chk_rv != CKR_OK) { + return(0); + } + + slots = malloc(sizeof(*slots) * numSlots); + + chk_rv = moduleFunctionList->C_GetSlotList(FALSE, slots, &numSlots); + if (chk_rv != CKR_OK) { + free(slots); + + return(0); + } + + searchTemplatePrivateKeys[0].pValue = &objectClassPrivateKey; + searchTemplateCertificates[0].pValue = &objectClassCertificate; + + foundCertificates = 0; + certificatesCount = 10; + *certificates = malloc(sizeof(**certificates) * certificatesCount); + + idsCount = 10; + ids = malloc(sizeof(*ids) * idsCount); + + for (currId = 0; currId < idsCount; currId++) { + ids[currId].initialized = 0; + } + + for (currSlot = 0; currSlot < numSlots; currSlot++) { + chk_rv = moduleFunctionList->C_GetSlotInfo(slots[currSlot], &slotInfo); + if (chk_rv != CKR_OK) { + continue; + } + + if ((slotInfo.flags & CKF_TOKEN_PRESENT) != CKF_TOKEN_PRESENT) { + continue; + } + + chk_rv = moduleFunctionList->C_OpenSession(slots[currSlot], CKF_SERIAL_SESSION, NULL, NULL, &hSession); + if (chk_rv != CKR_OK) { + continue; + } + + chk_rv = moduleFunctionList->C_FindObjectsInit(hSession, searchTemplatePrivateKeys, sizeof(searchTemplatePrivateKeys) / sizeof(searchTemplatePrivateKeys[0])); + if (chk_rv != CKR_OK) { + moduleFunctionList->C_CloseSession(hSession); + + continue; + } + + for (currId = 0; currId < idsCount; currId++) { + if (!ids[currId].initialized) { + continue; + } + + free(ids[currId].id); + + ids[currId].initialized = 0; + } + + currId = 0; + + while (1) { + chk_rv = moduleFunctionList->C_FindObjects(hSession, &hObject, 1, &ulObjectCount); + if (chk_rv != CKR_OK) { + break; + } + + if (ulObjectCount == 0) { + break; + } + + if (ulObjectCount != 1) { + break; + } + + chk_rv = cackey_chrome_GetAttributesFromTemplate(hSession, hObject, attrTemplatePrivateKey, sizeof(attrTemplatePrivateKey) / sizeof(attrTemplatePrivateKey[0])); + if (chk_rv != CKR_OK) { + continue; + } + + if (currId >= idsCount) { + idsCount *= 2; + + ids = realloc(ids, sizeof(*ids) * idsCount); + } + + ids[currId].idLen = attrTemplatePrivateKey[0].ulValueLen; + ids[currId].id = attrTemplatePrivateKey[0].pValue; + ids[currId].initialized = 1; + currId++; + } + + moduleFunctionList->C_FindObjectsFinal(hSession); + + for (currId = 0; currId < idsCount; currId++) { + if (!ids[currId].initialized) { + continue; + } + + searchTemplateCertificates[1].pValue = ids[currId].id; + searchTemplateCertificates[1].ulValueLen = ids[currId].idLen; + + chk_rv = moduleFunctionList->C_FindObjectsInit(hSession, searchTemplateCertificates, sizeof(searchTemplateCertificates) / sizeof(searchTemplateCertificates[0])); + if (chk_rv != CKR_OK) { + free(ids[currId].id); + + ids[currId].initialized = 0; + + continue; + } + + while (1) { + chk_rv = moduleFunctionList->C_FindObjects(hSession, &hObject, 1, &ulObjectCount); + if (chk_rv != CKR_OK) { + break; + } + + if (ulObjectCount == 0) { + break; + } + + if (ulObjectCount != 1) { + break; + } + + chk_rv = cackey_chrome_GetAttributesFromTemplate(hSession, hObject, attrTemplateCertificate, sizeof(attrTemplateCertificate) / sizeof(attrTemplateCertificate[0])); + if (chk_rv != CKR_OK) { + continue; + } + + if (foundCertificates >= certificatesCount) { + certificatesCount *= 2; + *certificates = realloc(*certificates, sizeof(**certificates) * certificatesCount); + } + + (*certificates)[foundCertificates].certificate = malloc(attrTemplateCertificate[0].ulValueLen); + memcpy((*certificates)[foundCertificates].certificate, attrTemplateCertificate[0].pValue, attrTemplateCertificate[0].ulValueLen); + (*certificates)[foundCertificates].certificate_len = attrTemplateCertificate[0].ulValueLen; + + free(attrTemplateCertificate[0].pValue); + + foundCertificates++; + } + + moduleFunctionList->C_FindObjectsFinal(hSession); + + free(ids[currId].id); + + ids[currId].initialized = 0; + } + + moduleFunctionList->C_CloseSession(hSession); + } + + for (currId = 0; currId < idsCount; currId++) { + if (!ids[currId].initialized) { + continue; + } + + free(ids[currId].id); + + ids[currId].initialized = 0; + } + + free(ids); + + free(slots); + + return(foundCertificates); +} + +void cackey_chrome_freeCertificates(struct cackey_certificate *certificates, int certificatesCount) { + int idx; + + if (certificates == NULL) { + return; + } + + for (idx = 0; idx < certificatesCount; idx++) { + if (certificates[idx].certificate) { + free(certificates[idx].certificate); + } + } + + free(certificates); + + return; +} + +cackey_chrome_returnType cackey_chrome_signMessage(struct cackey_certificate *certificate, void *data, unsigned long dataLength, void *destination, unsigned long *destinationLength, char **pinPrompt, const char *pin) { + CK_RV chk_rv; + CK_ULONG numSlots, currSlot; + CK_SLOT_ID_PTR slots; + CK_SLOT_INFO slotInfo; + CK_SESSION_HANDLE hSession; + CK_OBJECT_HANDLE hObject, hKey; + CK_ULONG ulObjectCount; + CK_ATTRIBUTE searchTemplateCertificates[] = { + {CKA_CLASS, NULL, sizeof(CK_OBJECT_CLASS)}, + {CKA_VALUE, NULL, 0} + }; + CK_ATTRIBUTE searchTemplatePrivateKeys[] = { + {CKA_CLASS, NULL, sizeof(CK_OBJECT_CLASS)}, + {CKA_ID, NULL, 0} + }; + CK_ATTRIBUTE attrTemplateCertificate[] = { + {CKA_ID, NULL, 0}, + {CKA_LABEL, NULL, 0} + }; + CK_MECHANISM signMechanism = {CKM_RSA_PKCS, NULL, 0}; + CK_OBJECT_CLASS objectClassPrivateKey = CKO_PRIVATE_KEY; + CK_OBJECT_CLASS objectClassCertificate = CKO_CERTIFICATE; + CK_TOKEN_INFO tokenInfo; + CK_ULONG tmpDestinationLength; + char *certificateLabel; + int foundPrivateKeyObject; + cackey_chrome_returnType retval; + + *pinPrompt = NULL; + + retval = CACKEY_CHROME_ERROR; + + chk_rv = cackey_chrome_init(); + if (chk_rv != CKR_OK) { + return(retval); + } + + chk_rv = moduleFunctionList->C_GetSlotList(FALSE, NULL, &numSlots); + if (chk_rv != CKR_OK) { + return(retval); + } + + slots = malloc(sizeof(*slots) * numSlots); + + chk_rv = moduleFunctionList->C_GetSlotList(FALSE, slots, &numSlots); + if (chk_rv != CKR_OK) { + free(slots); + + return(retval); + } + + searchTemplateCertificates[0].pValue = &objectClassCertificate; + searchTemplatePrivateKeys[0].pValue = &objectClassPrivateKey; + + searchTemplateCertificates[1].pValue = certificate->certificate; + searchTemplateCertificates[1].ulValueLen = certificate->certificate_len; + + foundPrivateKeyObject = 0; + + certificateLabel = NULL; + + for (currSlot = 0; currSlot < numSlots; currSlot++) { + chk_rv = moduleFunctionList->C_GetSlotInfo(slots[currSlot], &slotInfo); + if (chk_rv != CKR_OK) { + continue; + } + + if ((slotInfo.flags & CKF_TOKEN_PRESENT) != CKF_TOKEN_PRESENT) { + continue; + } + + chk_rv = moduleFunctionList->C_OpenSession(slots[currSlot], CKF_SERIAL_SESSION, NULL, NULL, &hSession); + if (chk_rv != CKR_OK) { + continue; + } + + chk_rv = moduleFunctionList->C_FindObjectsInit(hSession, searchTemplateCertificates, sizeof(searchTemplateCertificates) / sizeof(searchTemplateCertificates[0])); + if (chk_rv != CKR_OK) { + moduleFunctionList->C_CloseSession(hSession); + + continue; + } + + while (1) { + chk_rv = moduleFunctionList->C_FindObjects(hSession, &hObject, 1, &ulObjectCount); + if (chk_rv != CKR_OK) { + break; + } + + if (ulObjectCount == 0) { + break; + } + + if (ulObjectCount != 1) { + break; + } + + chk_rv = cackey_chrome_GetAttributesFromTemplate(hSession, hObject, attrTemplateCertificate, sizeof(attrTemplateCertificate) / sizeof(attrTemplateCertificate[0])); + if (chk_rv != CKR_OK) { + continue; + } + + searchTemplatePrivateKeys[1].pValue = attrTemplateCertificate[0].pValue; + searchTemplatePrivateKeys[1].ulValueLen = attrTemplateCertificate[0].ulValueLen; + + if (attrTemplateCertificate[1].ulValueLen > 0 && attrTemplateCertificate[1].pValue != NULL) { + certificateLabel = malloc(attrTemplateCertificate[1].ulValueLen + 1); + memcpy(certificateLabel, attrTemplateCertificate[1].pValue, attrTemplateCertificate[1].ulValueLen); + certificateLabel[attrTemplateCertificate[1].ulValueLen] = '\0'; + } + + break; + } + + moduleFunctionList->C_FindObjectsFinal(hSession); + + if (searchTemplatePrivateKeys[1].pValue != NULL) { + chk_rv = moduleFunctionList->C_FindObjectsInit(hSession, searchTemplateCertificates, sizeof(searchTemplateCertificates) / sizeof(searchTemplateCertificates[0])); + if (chk_rv == CKR_OK) { + while (1) { + chk_rv = moduleFunctionList->C_FindObjects(hSession, &hObject, 1, &ulObjectCount); + if (chk_rv != CKR_OK) { + break; + } + + if (ulObjectCount == 0) { + break; + } + + if (ulObjectCount != 1) { + break; + } + + hKey = hObject; + + foundPrivateKeyObject = 1; + + break; + } + + moduleFunctionList->C_FindObjectsFinal(hSession); + } + + free(searchTemplatePrivateKeys[1].pValue); + + } + + if (foundPrivateKeyObject) { + chk_rv = moduleFunctionList->C_SignInit(hSession, &signMechanism, hKey); + if (chk_rv != CKR_OK) { + break; + } + + tmpDestinationLength = *destinationLength; + chk_rv = moduleFunctionList->C_Sign(hSession, data, dataLength, destination, &tmpDestinationLength); + switch (chk_rv) { + case CKR_OK: + *destinationLength = tmpDestinationLength; + retval = CACKEY_CHROME_OK; + break; + case CKR_USER_NOT_LOGGED_IN: + chk_rv = moduleFunctionList->C_GetTokenInfo(slots[currSlot], &tokenInfo); + if (chk_rv == CKR_OK) { + if ((tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == CKF_PROTECTED_AUTHENTICATION_PATH) { + retval = CACKEY_CHROME_NEEDPROTECTEDLOGIN; + } else { + retval = CACKEY_CHROME_NEEDLOGIN; + + *pinPrompt = malloc(1024); + if (certificateLabel) { + snprintf(*pinPrompt, 1024, "Please enter the PIN for %s:%s", tokenInfo.label, certificateLabel); + } else { + snprintf(*pinPrompt, 1024, "Please enter the PIN for %s", tokenInfo.label); + } + } + } else { + retval = CACKEY_CHROME_NEEDLOGIN; + + *pinPrompt = strdup("Please enter your Smartcard PIN"); + } + + if (retval == CACKEY_CHROME_NEEDPROTECTEDLOGIN) { + retval = CACKEY_CHROME_ERROR; + + chk_rv = moduleFunctionList->C_Login(hSession, CKU_USER, NULL, 0); + } else { + if (pin) { + retval = CACKEY_CHROME_ERROR; + + free(*pinPrompt); + *pinPrompt = NULL; + + chk_rv = moduleFunctionList->C_Login(hSession, CKU_USER, (CK_UTF8CHAR_PTR) pin, strlen(pin)); + } else { + chk_rv = CKR_GENERAL_ERROR; + } + } + + if (chk_rv == CKR_OK && retval == CACKEY_CHROME_ERROR) { + chk_rv = moduleFunctionList->C_SignInit(hSession, &signMechanism, hKey); + if (chk_rv != CKR_OK) { + break; + } + + tmpDestinationLength = *destinationLength; + chk_rv = moduleFunctionList->C_Sign(hSession, data, dataLength, destination, &tmpDestinationLength); + switch (chk_rv) { + case CKR_OK: + *destinationLength = tmpDestinationLength; + retval = CACKEY_CHROME_OK; + break; + case CKR_USER_NOT_LOGGED_IN: + retval = CACKEY_CHROME_NEEDLOGIN; + break; + default: + retval = CACKEY_CHROME_ERROR; + break; + } + } + + break; + default: + retval = CACKEY_CHROME_ERROR; + break; + } + + break; + } + + moduleFunctionList->C_CloseSession(hSession); + } + + free(slots); + + if (certificateLabel) { + free(certificateLabel); + } + + return(retval); +} + +#ifdef __cplusplus +} +#endif ADDED build/chrome/cackey-chrome-plugin.cc Index: build/chrome/cackey-chrome-plugin.cc ================================================================== --- build/chrome/cackey-chrome-plugin.cc +++ build/chrome/cackey-chrome-plugin.cc @@ -0,0 +1,264 @@ +/* + * Google's PCSC library requires us to write our module in C++ to initialize + * it. This component handles the initialization of our module and handles + * incoming messages, passing them either to our library (cackey-chrome) or + * to the PCSC-NaCl library from Google as appropriate. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pcsc-nacl.h" +#include "cackey-chrome.h" + +class CACKeyInstance : public pp::Instance { + private: + pp::Core *corePointer; + public: + explicit CACKeyInstance(PP_Instance instance, pp::Core *core) : pp::Instance(instance) { + corePointer = core; + } + + virtual ~CACKeyInstance() {} + + virtual void HandleMessageThread(pp::VarDictionary *message, pp::Var *messagePlain) { + cackey_chrome_returnType signRet; + char *pinPrompt = NULL; + const char *pin; + const char *smartcardManagerAppId = NULL; + unsigned char buffer[8192]; + struct cackey_certificate *certificates, incomingCertificateCACKey; + pp::VarDictionary *reply; + pp::VarArray certificatesPPArray; + pp::VarArrayBuffer *certificateContents, *incomingCertificateContents, *incomingData, *outgoingData; + pp::Var command; + int numCertificates, i; + unsigned long outgoingDataLength; + + /* + * Extract the command + */ + command = message->Get("command"); + + /* + * Do the thing we are being asked to do + */ + reply = new pp::VarDictionary(); + + if (command.AsString() == "init") { + if (message->HasKey("smartcardManagerAppId")) { + smartcardManagerAppId = strdup(message->Get("smartcardManagerAppId").AsString().c_str()); + } + + pcscNaClInit(this, corePointer, smartcardManagerAppId, "CACKey"); + + if (smartcardManagerAppId) { + free((void *) smartcardManagerAppId); + } + + reply->Set("status", "success"); + } else if (command.AsString() == "listcertificates") { + numCertificates = cackey_chrome_listCertificates(&certificates); + + certificatesPPArray.SetLength(numCertificates); + + for (i = 0; i < numCertificates; i++) { + certificateContents = new pp::VarArrayBuffer(certificates[i].certificate_len); + + memcpy(certificateContents->Map(), certificates[i].certificate, certificates[i].certificate_len); + + certificateContents->Unmap(); + + certificatesPPArray.Set(i, *certificateContents); + + delete certificateContents; + } + + cackey_chrome_freeCertificates(certificates, numCertificates); + + reply->Set("status", "success"); + reply->Set("certificates", certificatesPPArray); + } else if (command.AsString() == "sign") { + if (!message->HasKey("certificate")) { + reply->Set("status", "error"); + reply->Set("error", "Certificate not supplied"); + } else if (!message->HasKey("data")) { + reply->Set("status", "error"); + reply->Set("error", "Data not supplied"); + } else { + incomingCertificateContents = new pp::VarArrayBuffer(message->Get("certificate")); + incomingData = new pp::VarArrayBuffer(message->Get("data")); + + if (message->HasKey("pin")) { + pin = message->Get("pin").AsString().c_str(); + } else { + pin = NULL; + } + + incomingCertificateCACKey.certificate = incomingCertificateContents->Map(); + incomingCertificateCACKey.certificate_len = incomingCertificateContents->ByteLength(); + + outgoingDataLength = sizeof(buffer); + + signRet = cackey_chrome_signMessage(&incomingCertificateCACKey, + incomingData->Map(), incomingData->ByteLength(), + buffer, &outgoingDataLength, + &pinPrompt, pin + ); + + incomingCertificateContents->Unmap(); + incomingData->Unmap(); + + delete incomingCertificateContents; + delete incomingData; + + switch (signRet) { + case CACKEY_CHROME_OK: + outgoingData = new pp::VarArrayBuffer(outgoingDataLength); + + memcpy(outgoingData->Map(), buffer, outgoingDataLength); + + outgoingData->Unmap(); + + reply->Set("status", "success"); + reply->Set("signedData", *outgoingData); + + delete outgoingData; + + break; + case CACKEY_CHROME_ERROR: + reply->Set("status", "error"); + reply->Set("error", "Unable to sign data"); + break; + case CACKEY_CHROME_NEEDLOGIN: + case CACKEY_CHROME_NEEDPROTECTEDLOGIN: + reply->Set("status", "retry"); + reply->Set("originalrequest", *messagePlain); + reply->Set("pinprompt", pinPrompt); + + break; + } + + if (pinPrompt != NULL) { + free(pinPrompt); + } + } + } else { + reply->Set("status", "error"); + reply->Set("error", "Invalid command"); + } + + /* + * If a message ID was sent in the request, include it in the reply + */ + if (message->HasKey("id")) { + reply->Set("id", message->Get("id")); + } + + /* + * Indicate who our message is for + */ + reply->Set("target", "cackey"); + reply->Set("command", command); + + /* + * Send the reply back to the requestor, hopefully they are waiting for this message + */ + PostMessage(*reply); + + delete reply; + + delete message; + + delete messagePlain; + + return; + } + + virtual void HandleMessage(const pp::Var& messagePlain) { + pp::VarDictionary *message; + pp::Var *messagePlainCopy; + pp::Var target; + + /* + * The incoming message must be a dictionary + */ + if (!messagePlain.is_dictionary()) { + pcscNaClHandleMessage(messagePlain); + + return; + } + + /* + * Process the appropriate command from the incoming message + */ + message = new pp::VarDictionary(messagePlain); + + /* + * Verify that this message is destined for us + */ + if (!message->HasKey("target")) { + delete message; + + /* We don't handle this message, see if PCSC-NaCl does */ + pcscNaClHandleMessage(messagePlain); + + return; + } + + target = message->Get("target"); + if (target.AsString() != "cackey") { + delete message; + + /* We don't handle this message, see if PCSC-NaCl does */ + pcscNaClHandleMessage(messagePlain); + + return; + } + + /* + * Determine what we are being asked to do + */ + if (!message->HasKey("command")) { + delete message; + + /* We don't handle this message, see if PCSC-NaCl does */ + pcscNaClHandleMessage(messagePlain); + + return; + } + + /* + * Process the request in another thread + */ + messagePlainCopy = new pp::Var(messagePlain); + std::thread(&CACKeyInstance::HandleMessageThread, this, message, messagePlainCopy).detach(); + + return; + } +}; + +class CACKeyModule : public pp::Module { + public: + CACKeyModule() : pp::Module() {} + virtual ~CACKeyModule() {} + + virtual pp::Instance *CreateInstance(PP_Instance instance) { + return(new CACKeyInstance(instance, core())); + } +}; + +namespace pp { + Module *CreateModule() { + return(new CACKeyModule()); + } +} DELETED build/chrome/cackey-chrome.c Index: build/chrome/cackey-chrome.c ================================================================== --- build/chrome/cackey-chrome.c +++ build/chrome/cackey-chrome.c @@ -1,576 +0,0 @@ -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#include "mypkcs11.h" -#include "cackey-chrome.h" - -struct cackey_chrome_id { - void *id; - size_t idLen; - int initialized; -}; - -static CK_FUNCTION_LIST_PTR moduleFunctionList = NULL; - -static CK_RV cackey_chrome_init(void) { - CK_C_INITIALIZE_ARGS initargs; - CK_RV chk_rv; - - if (moduleFunctionList != NULL) { - return(CKR_OK); - } - - chk_rv = C_GetFunctionList(&moduleFunctionList); - if (chk_rv != CKR_OK) { - return(chk_rv); - } - - initargs.CreateMutex = NULL; - initargs.DestroyMutex = NULL; - initargs.LockMutex = NULL; - initargs.UnlockMutex = NULL; - initargs.flags = CKF_OS_LOCKING_OK; - initargs.pReserved = NULL; - - chk_rv = moduleFunctionList->C_Initialize(&initargs); - if (chk_rv != CKR_OK) { - return(chk_rv); - } - - return(CKR_OK); -} - -void cackey_chrome_terminate(void) { - if (!moduleFunctionList) { - return; - } - - moduleFunctionList->C_Finalize(NULL); - - free(moduleFunctionList); - - moduleFunctionList = NULL; - - return; -} - -static CK_RV cackey_chrome_GetAttributesFromTemplate(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE *attrTemplate, CK_ULONG attrTemplateCount) { - CK_RV chk_rv; - CK_ATTRIBUTE *currAttr; - CK_ULONG currAttrIndex; - - for (currAttrIndex = 0; currAttrIndex < attrTemplateCount; currAttrIndex++) { - currAttr = &attrTemplate[currAttrIndex]; - - currAttr->pValue = NULL; - currAttr->ulValueLen = 0; - } - - chk_rv = moduleFunctionList->C_GetAttributeValue(hSession, hObject, attrTemplate, attrTemplateCount); - if (chk_rv == CKR_ATTRIBUTE_TYPE_INVALID || chk_rv == CKR_ATTRIBUTE_SENSITIVE || chk_rv == CKR_BUFFER_TOO_SMALL) { - chk_rv = CKR_OK; - } - - if (chk_rv != CKR_OK) { - return(chk_rv); - } - - for (currAttrIndex = 0; currAttrIndex < attrTemplateCount; currAttrIndex++) { - currAttr = &attrTemplate[currAttrIndex]; - - if (currAttr->ulValueLen == 0) { - continue; - } - - if (((CK_LONG) currAttr->ulValueLen) == ((CK_LONG) -1)) { - continue; - } - - currAttr->pValue = malloc(currAttr->ulValueLen); - } - - chk_rv = moduleFunctionList->C_GetAttributeValue(hSession, hObject, attrTemplate, attrTemplateCount); - if (chk_rv != CKR_OK) { - free(currAttr->pValue); - - return(chk_rv); - } - - return(CKR_OK); -} - -int cackey_chrome_listCertificates(struct cackey_certificate **certificates) { - CK_RV chk_rv; - CK_ULONG numSlots, currSlot; - CK_SLOT_ID_PTR slots; - CK_SLOT_INFO slotInfo; - CK_SESSION_HANDLE hSession; - CK_OBJECT_HANDLE hObject; - CK_ULONG ulObjectCount; - CK_ATTRIBUTE searchTemplatePrivateKeys[] = { - {CKA_CLASS, NULL, sizeof(CK_OBJECT_CLASS)} - }; - CK_ATTRIBUTE searchTemplateCertificates[] = { - {CKA_CLASS, NULL, sizeof(CK_OBJECT_CLASS)}, - {CKA_ID, NULL, 0} - }; - CK_ATTRIBUTE attrTemplatePrivateKey[] = { - {CKA_ID, NULL, 0} - }; - CK_ATTRIBUTE attrTemplateCertificate[] = { - {CKA_VALUE, NULL, 0} - }; - CK_OBJECT_CLASS objectClassPrivateKey = CKO_PRIVATE_KEY; - CK_OBJECT_CLASS objectClassCertificate = CKO_CERTIFICATE; - struct cackey_chrome_id *ids; - int idsCount, currId; - int foundCertificates, certificatesCount; - - *certificates = NULL; - - chk_rv = cackey_chrome_init(); - if (chk_rv != CKR_OK) { - return(0); - } - - chk_rv = moduleFunctionList->C_GetSlotList(FALSE, NULL, &numSlots); - if (chk_rv != CKR_OK) { - return(0); - } - - slots = malloc(sizeof(*slots) * numSlots); - - chk_rv = moduleFunctionList->C_GetSlotList(FALSE, slots, &numSlots); - if (chk_rv != CKR_OK) { - free(slots); - - return(0); - } - - searchTemplatePrivateKeys[0].pValue = &objectClassPrivateKey; - searchTemplateCertificates[0].pValue = &objectClassCertificate; - - foundCertificates = 0; - certificatesCount = 10; - *certificates = malloc(sizeof(**certificates) * certificatesCount); - - idsCount = 10; - ids = malloc(sizeof(*ids) * idsCount); - - for (currId = 0; currId < idsCount; currId++) { - ids[currId].initialized = 0; - } - - for (currSlot = 0; currSlot < numSlots; currSlot++) { - chk_rv = moduleFunctionList->C_GetSlotInfo(slots[currSlot], &slotInfo); - if (chk_rv != CKR_OK) { - continue; - } - - if ((slotInfo.flags & CKF_TOKEN_PRESENT) != CKF_TOKEN_PRESENT) { - continue; - } - - chk_rv = moduleFunctionList->C_OpenSession(slots[currSlot], CKF_SERIAL_SESSION, NULL, NULL, &hSession); - if (chk_rv != CKR_OK) { - continue; - } - - chk_rv = moduleFunctionList->C_FindObjectsInit(hSession, searchTemplatePrivateKeys, sizeof(searchTemplatePrivateKeys) / sizeof(searchTemplatePrivateKeys[0])); - if (chk_rv != CKR_OK) { - moduleFunctionList->C_CloseSession(hSession); - - continue; - } - - for (currId = 0; currId < idsCount; currId++) { - if (!ids[currId].initialized) { - continue; - } - - free(ids[currId].id); - - ids[currId].initialized = 0; - } - - currId = 0; - - while (1) { - chk_rv = moduleFunctionList->C_FindObjects(hSession, &hObject, 1, &ulObjectCount); - if (chk_rv != CKR_OK) { - break; - } - - if (ulObjectCount == 0) { - break; - } - - if (ulObjectCount != 1) { - break; - } - - chk_rv = cackey_chrome_GetAttributesFromTemplate(hSession, hObject, attrTemplatePrivateKey, sizeof(attrTemplatePrivateKey) / sizeof(attrTemplatePrivateKey[0])); - if (chk_rv != CKR_OK) { - continue; - } - - if (currId >= idsCount) { - idsCount *= 2; - - ids = realloc(ids, sizeof(*ids) * idsCount); - } - - ids[currId].idLen = attrTemplatePrivateKey[0].ulValueLen; - ids[currId].id = attrTemplatePrivateKey[0].pValue; - ids[currId].initialized = 1; - currId++; - } - - moduleFunctionList->C_FindObjectsFinal(hSession); - - for (currId = 0; currId < idsCount; currId++) { - if (!ids[currId].initialized) { - continue; - } - - searchTemplateCertificates[1].pValue = ids[currId].id; - searchTemplateCertificates[1].ulValueLen = ids[currId].idLen; - - chk_rv = moduleFunctionList->C_FindObjectsInit(hSession, searchTemplateCertificates, sizeof(searchTemplateCertificates) / sizeof(searchTemplateCertificates[0])); - if (chk_rv != CKR_OK) { - free(ids[currId].id); - - ids[currId].initialized = 0; - - continue; - } - - while (1) { - chk_rv = moduleFunctionList->C_FindObjects(hSession, &hObject, 1, &ulObjectCount); - if (chk_rv != CKR_OK) { - break; - } - - if (ulObjectCount == 0) { - break; - } - - if (ulObjectCount != 1) { - break; - } - - chk_rv = cackey_chrome_GetAttributesFromTemplate(hSession, hObject, attrTemplateCertificate, sizeof(attrTemplateCertificate) / sizeof(attrTemplateCertificate[0])); - if (chk_rv != CKR_OK) { - continue; - } - - if (foundCertificates >= certificatesCount) { - certificatesCount *= 2; - *certificates = realloc(*certificates, sizeof(**certificates) * certificatesCount); - } - - (*certificates)[foundCertificates].certificate = malloc(attrTemplateCertificate[0].ulValueLen); - memcpy((*certificates)[foundCertificates].certificate, attrTemplateCertificate[0].pValue, attrTemplateCertificate[0].ulValueLen); - (*certificates)[foundCertificates].certificate_len = attrTemplateCertificate[0].ulValueLen; - - free(attrTemplateCertificate[0].pValue); - - foundCertificates++; - } - - moduleFunctionList->C_FindObjectsFinal(hSession); - - free(ids[currId].id); - - ids[currId].initialized = 0; - } - - moduleFunctionList->C_CloseSession(hSession); - } - - for (currId = 0; currId < idsCount; currId++) { - if (!ids[currId].initialized) { - continue; - } - - free(ids[currId].id); - - ids[currId].initialized = 0; - } - - free(ids); - - free(slots); - - return(foundCertificates); -} - -void cackey_chrome_freeCertificates(struct cackey_certificate *certificates, int certificatesCount) { - int idx; - - if (certificates == NULL) { - return; - } - - for (idx = 0; idx < certificatesCount; idx++) { - if (certificates[idx].certificate) { - free(certificates[idx].certificate); - } - } - - free(certificates); - - return; -} - -cackey_chrome_returnType cackey_chrome_signMessage(struct cackey_certificate *certificate, void *data, unsigned long dataLength, void *destination, unsigned long *destinationLength, char **pinPrompt, const char *pin) { - CK_RV chk_rv; - CK_ULONG numSlots, currSlot; - CK_SLOT_ID_PTR slots; - CK_SLOT_INFO slotInfo; - CK_SESSION_HANDLE hSession; - CK_OBJECT_HANDLE hObject, hKey; - CK_ULONG ulObjectCount; - CK_ATTRIBUTE searchTemplateCertificates[] = { - {CKA_CLASS, NULL, sizeof(CK_OBJECT_CLASS)}, - {CKA_VALUE, NULL, 0} - }; - CK_ATTRIBUTE searchTemplatePrivateKeys[] = { - {CKA_CLASS, NULL, sizeof(CK_OBJECT_CLASS)}, - {CKA_ID, NULL, 0} - }; - CK_ATTRIBUTE attrTemplateCertificate[] = { - {CKA_ID, NULL, 0}, - {CKA_LABEL, NULL, 0} - }; - CK_MECHANISM signMechanism = {CKM_RSA_PKCS, NULL, 0}; - CK_OBJECT_CLASS objectClassPrivateKey = CKO_PRIVATE_KEY; - CK_OBJECT_CLASS objectClassCertificate = CKO_CERTIFICATE; - CK_TOKEN_INFO tokenInfo; - CK_ULONG tmpDestinationLength; - char *certificateLabel; - int foundPrivateKeyObject; - cackey_chrome_returnType retval; - - *pinPrompt = NULL; - - retval = CACKEY_CHROME_ERROR; - - chk_rv = cackey_chrome_init(); - if (chk_rv != CKR_OK) { - return(retval); - } - - chk_rv = moduleFunctionList->C_GetSlotList(FALSE, NULL, &numSlots); - if (chk_rv != CKR_OK) { - return(retval); - } - - slots = malloc(sizeof(*slots) * numSlots); - - chk_rv = moduleFunctionList->C_GetSlotList(FALSE, slots, &numSlots); - if (chk_rv != CKR_OK) { - free(slots); - - return(retval); - } - - searchTemplateCertificates[0].pValue = &objectClassCertificate; - searchTemplatePrivateKeys[0].pValue = &objectClassPrivateKey; - - searchTemplateCertificates[1].pValue = certificate->certificate; - searchTemplateCertificates[1].ulValueLen = certificate->certificate_len; - - foundPrivateKeyObject = 0; - - certificateLabel = NULL; - - for (currSlot = 0; currSlot < numSlots; currSlot++) { - chk_rv = moduleFunctionList->C_GetSlotInfo(slots[currSlot], &slotInfo); - if (chk_rv != CKR_OK) { - continue; - } - - if ((slotInfo.flags & CKF_TOKEN_PRESENT) != CKF_TOKEN_PRESENT) { - continue; - } - - chk_rv = moduleFunctionList->C_OpenSession(slots[currSlot], CKF_SERIAL_SESSION, NULL, NULL, &hSession); - if (chk_rv != CKR_OK) { - continue; - } - - chk_rv = moduleFunctionList->C_FindObjectsInit(hSession, searchTemplateCertificates, sizeof(searchTemplateCertificates) / sizeof(searchTemplateCertificates[0])); - if (chk_rv != CKR_OK) { - moduleFunctionList->C_CloseSession(hSession); - - continue; - } - - while (1) { - chk_rv = moduleFunctionList->C_FindObjects(hSession, &hObject, 1, &ulObjectCount); - if (chk_rv != CKR_OK) { - break; - } - - if (ulObjectCount == 0) { - break; - } - - if (ulObjectCount != 1) { - break; - } - - chk_rv = cackey_chrome_GetAttributesFromTemplate(hSession, hObject, attrTemplateCertificate, sizeof(attrTemplateCertificate) / sizeof(attrTemplateCertificate[0])); - if (chk_rv != CKR_OK) { - continue; - } - - searchTemplatePrivateKeys[1].pValue = attrTemplateCertificate[0].pValue; - searchTemplatePrivateKeys[1].ulValueLen = attrTemplateCertificate[0].ulValueLen; - - if (attrTemplateCertificate[1].ulValueLen > 0 && attrTemplateCertificate[1].pValue != NULL) { - certificateLabel = malloc(attrTemplateCertificate[1].ulValueLen + 1); - memcpy(certificateLabel, attrTemplateCertificate[1].pValue, attrTemplateCertificate[1].ulValueLen); - certificateLabel[attrTemplateCertificate[1].ulValueLen] = '\0'; - } - - break; - } - - moduleFunctionList->C_FindObjectsFinal(hSession); - - if (searchTemplatePrivateKeys[1].pValue != NULL) { - chk_rv = moduleFunctionList->C_FindObjectsInit(hSession, searchTemplateCertificates, sizeof(searchTemplateCertificates) / sizeof(searchTemplateCertificates[0])); - if (chk_rv == CKR_OK) { - while (1) { - chk_rv = moduleFunctionList->C_FindObjects(hSession, &hObject, 1, &ulObjectCount); - if (chk_rv != CKR_OK) { - break; - } - - if (ulObjectCount == 0) { - break; - } - - if (ulObjectCount != 1) { - break; - } - - hKey = hObject; - - foundPrivateKeyObject = 1; - - break; - } - - moduleFunctionList->C_FindObjectsFinal(hSession); - } - - free(searchTemplatePrivateKeys[1].pValue); - - } - - if (foundPrivateKeyObject) { - chk_rv = moduleFunctionList->C_SignInit(hSession, &signMechanism, hKey); - if (chk_rv != CKR_OK) { - break; - } - - tmpDestinationLength = *destinationLength; - chk_rv = moduleFunctionList->C_Sign(hSession, data, dataLength, destination, &tmpDestinationLength); - switch (chk_rv) { - case CKR_OK: - *destinationLength = tmpDestinationLength; - retval = CACKEY_CHROME_OK; - break; - case CKR_USER_NOT_LOGGED_IN: - chk_rv = moduleFunctionList->C_GetTokenInfo(slots[currSlot], &tokenInfo); - if (chk_rv == CKR_OK) { - if ((tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == CKF_PROTECTED_AUTHENTICATION_PATH) { - retval = CACKEY_CHROME_NEEDPROTECTEDLOGIN; - } else { - retval = CACKEY_CHROME_NEEDLOGIN; - - *pinPrompt = malloc(1024); - if (certificateLabel) { - snprintf(*pinPrompt, 1024, "Please enter the PIN for %s:%s", tokenInfo.label, certificateLabel); - } else { - snprintf(*pinPrompt, 1024, "Please enter the PIN for %s", tokenInfo.label); - } - } - } else { - retval = CACKEY_CHROME_NEEDLOGIN; - - *pinPrompt = strdup("Please enter your Smartcard PIN"); - } - - if (retval == CACKEY_CHROME_NEEDPROTECTEDLOGIN) { - retval = CACKEY_CHROME_ERROR; - - chk_rv = moduleFunctionList->C_Login(hSession, CKU_USER, NULL, 0); - } else { - if (pin) { - retval = CACKEY_CHROME_ERROR; - - free(*pinPrompt); - *pinPrompt = NULL; - - chk_rv = moduleFunctionList->C_Login(hSession, CKU_USER, (CK_UTF8CHAR_PTR) pin, strlen(pin)); - } else { - chk_rv = CKR_GENERAL_ERROR; - } - } - - if (chk_rv == CKR_OK && retval == CACKEY_CHROME_ERROR) { - chk_rv = moduleFunctionList->C_SignInit(hSession, &signMechanism, hKey); - if (chk_rv != CKR_OK) { - break; - } - - tmpDestinationLength = *destinationLength; - chk_rv = moduleFunctionList->C_Sign(hSession, data, dataLength, destination, &tmpDestinationLength); - switch (chk_rv) { - case CKR_OK: - *destinationLength = tmpDestinationLength; - retval = CACKEY_CHROME_OK; - break; - case CKR_USER_NOT_LOGGED_IN: - retval = CACKEY_CHROME_NEEDLOGIN; - break; - default: - retval = CACKEY_CHROME_ERROR; - break; - } - } - - break; - default: - retval = CACKEY_CHROME_ERROR; - break; - } - - break; - } - - moduleFunctionList->C_CloseSession(hSession); - } - - free(slots); - - if (certificateLabel) { - free(certificateLabel); - } - - return(retval); -} - -#ifdef __cplusplus -} -#endif