From fc37cc4a02ed13d1a73b941a9f80975600fd1b99 Mon Sep 17 00:00:00 2001 From: David Foerster Date: Tue, 10 May 2016 20:20:14 +0200 Subject: Normalize all line terminators --- src/Common/SecurityToken.cpp | 1570 +++++++++++++++++++++--------------------- 1 file changed, 785 insertions(+), 785 deletions(-) (limited to 'src/Common/SecurityToken.cpp') diff --git a/src/Common/SecurityToken.cpp b/src/Common/SecurityToken.cpp index db80ff0d..8909059d 100644 --- a/src/Common/SecurityToken.cpp +++ b/src/Common/SecurityToken.cpp @@ -1,787 +1,787 @@ -/* - Derived from source code of TrueCrypt 7.1a, which is - Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed - by the TrueCrypt License 3.0. - - Modifications and additions to the original source code (contained in this file) - and all other portions of this file are Copyright (c) 2013-2016 IDRIX - and are governed by the Apache License 2.0 the full text of which is - contained in the file License.txt included in VeraCrypt binary and source - code distribution packages. -*/ - -#include "Platform/Finally.h" -#include "Platform/ForEach.h" - -#if !defined (TC_WINDOWS) || defined (TC_PROTOTYPE) -# include "Platform/SerializerFactory.h" -# include "Platform/StringConverter.h" -# include "Platform/SystemException.h" -#else -# include "Dictionary.h" -# include "Language.h" -#endif - -#ifdef TC_UNIX -# include -#endif - -#include "SecurityToken.h" - -#ifndef burn -# define burn Memory::Erase -#endif - -using namespace std; - -namespace VeraCrypt -{ - SecurityTokenKeyfile::SecurityTokenKeyfile (const SecurityTokenKeyfilePath &path, char* pin) - { - wstring pathStr = path; - unsigned long slotId; - - if (swscanf (pathStr.c_str(), TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX TC_SECURITY_TOKEN_KEYFILE_URL_SLOT L"/%lu", &slotId) != 1) - throw InvalidSecurityTokenKeyfilePath(); - - SlotId = slotId; - - size_t keyIdPos = pathStr.find (L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/"); - if (keyIdPos == wstring::npos) - throw InvalidSecurityTokenKeyfilePath(); - - Id = pathStr.substr (keyIdPos + wstring (L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/").size()); - - vector keyfiles = SecurityToken::GetAvailableKeyfiles (&SlotId, Id, pin); - - if (keyfiles.empty()) - throw SecurityTokenKeyfileNotFound(); - - *this = keyfiles.front(); - } - - SecurityTokenKeyfile::operator SecurityTokenKeyfilePath () const - { - wstringstream path; - path << TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX TC_SECURITY_TOKEN_KEYFILE_URL_SLOT L"/" << SlotId << L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/" << Id; - return path.str(); - } - - void SecurityToken::CheckLibraryStatus () - { - if (!Initialized) - throw SecurityTokenLibraryNotInitialized(); - } - - void SecurityToken::CloseLibrary () - { - if (Initialized) - { - CloseAllSessions(); - Pkcs11Functions->C_Finalize (NULL_PTR); - -#ifdef TC_WINDOWS - FreeLibrary (Pkcs11LibraryHandle); -#else - dlclose (Pkcs11LibraryHandle); -#endif - Initialized = false; - } - } - - void SecurityToken::CloseAllSessions () throw () - { - if (!Initialized) - return; - - typedef pair SessionMapPair; - - foreach (SessionMapPair p, Sessions) - { - try - { - CloseSession (p.first); - } - catch (...) { } - } - } - - void SecurityToken::CloseSession (CK_SLOT_ID slotId) - { - if (Sessions.find (slotId) == Sessions.end()) - throw ParameterIncorrect (SRC_POS); - - Pkcs11Functions->C_CloseSession (Sessions[slotId].Handle); - Sessions.erase (Sessions.find (slotId)); - } - - void SecurityToken::CreateKeyfile (CK_SLOT_ID slotId, vector &keyfileData, const string &name) - { - if (name.empty()) - throw ParameterIncorrect (SRC_POS); - - LoginUserIfRequired (slotId); - - foreach (const SecurityTokenKeyfile &keyfile, GetAvailableKeyfiles (&slotId)) - { - if (keyfile.IdUtf8 == name) - throw SecurityTokenKeyfileAlreadyExists(); - } - - CK_OBJECT_CLASS dataClass = CKO_DATA; - CK_BBOOL trueVal = CK_TRUE; - - CK_ATTRIBUTE keyfileTemplate[] = - { - { CKA_CLASS, &dataClass, sizeof (dataClass) }, - { CKA_TOKEN, &trueVal, sizeof (trueVal) }, - { CKA_PRIVATE, &trueVal, sizeof (trueVal) }, - { CKA_LABEL, (CK_UTF8CHAR *) name.c_str(), (CK_ULONG) name.size() }, - { CKA_VALUE, &keyfileData.front(), (CK_ULONG) keyfileData.size() } - }; - - CK_OBJECT_HANDLE keyfileHandle; - - CK_RV status = Pkcs11Functions->C_CreateObject (Sessions[slotId].Handle, keyfileTemplate, array_capacity (keyfileTemplate), &keyfileHandle); - - switch (status) - { - case CKR_DATA_LEN_RANGE: - status = CKR_DEVICE_MEMORY; - break; - - case CKR_SESSION_READ_ONLY: - status = CKR_TOKEN_WRITE_PROTECTED; - break; - } - - if (status != CKR_OK) - throw Pkcs11Exception (status); - - // Some tokens report success even if the new object was truncated to fit in the available memory - vector objectData; - - GetObjectAttribute (slotId, keyfileHandle, CKA_VALUE, objectData); - finally_do_arg (vector *, &objectData, { if (!finally_arg->empty()) burn (&finally_arg->front(), finally_arg->size()); }); - - if (objectData.size() != keyfileData.size()) - { - Pkcs11Functions->C_DestroyObject (Sessions[slotId].Handle, keyfileHandle); - throw Pkcs11Exception (CKR_DEVICE_MEMORY); - } - } - - void SecurityToken::DeleteKeyfile (const SecurityTokenKeyfile &keyfile) - { - LoginUserIfRequired (keyfile.SlotId); - - CK_RV status = Pkcs11Functions->C_DestroyObject (Sessions[keyfile.SlotId].Handle, keyfile.Handle); - if (status != CKR_OK) - throw Pkcs11Exception (status); - } - - vector SecurityToken::GetAvailableKeyfiles (CK_SLOT_ID *slotIdFilter, const wstring keyfileIdFilter, char* pin) - { - bool unrecognizedTokenPresent = false; - vector keyfiles; - - foreach (const CK_SLOT_ID &slotId, GetTokenSlots()) - { - SecurityTokenInfo token; - - if (slotIdFilter && *slotIdFilter != slotId) - continue; - - try - { - LoginUserIfRequired (slotId, pin); - token = GetTokenInfo (slotId); - } - catch (UserAbort &) - { - continue; - } - catch (Pkcs11Exception &e) - { - if (e.GetErrorCode() == CKR_TOKEN_NOT_RECOGNIZED) - { - unrecognizedTokenPresent = true; - continue; - } - - throw; - } - - foreach (const CK_OBJECT_HANDLE &dataHandle, GetObjects (slotId, CKO_DATA)) - { - SecurityTokenKeyfile keyfile; - keyfile.Handle = dataHandle; - keyfile.SlotId = slotId; - keyfile.Token = token; - - vector privateAttrib; - GetObjectAttribute (slotId, dataHandle, CKA_PRIVATE, privateAttrib); - - if (privateAttrib.size() == sizeof (CK_BBOOL) && *(CK_BBOOL *) &privateAttrib.front() != CK_TRUE) - continue; - - vector label; - GetObjectAttribute (slotId, dataHandle, CKA_LABEL, label); - label.push_back (0); - - keyfile.IdUtf8 = (char *) &label.front(); - -#if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE) - keyfile.Id = Utf8StringToWide ((const char *) &label.front()); -#else - keyfile.Id = StringConverter::ToWide ((const char *) &label.front()); -#endif - if (keyfile.Id.empty() || (!keyfileIdFilter.empty() && keyfileIdFilter != keyfile.Id)) - continue; - - keyfiles.push_back (keyfile); - - if (!keyfileIdFilter.empty()) - break; - } - } - - if (keyfiles.empty() && unrecognizedTokenPresent) - throw Pkcs11Exception (CKR_TOKEN_NOT_RECOGNIZED); - - return keyfiles; - } - - list SecurityToken::GetAvailableTokens () - { - bool unrecognizedTokenPresent = false; - list tokens; - - foreach (const CK_SLOT_ID &slotId, GetTokenSlots()) - { - try - { - tokens.push_back (GetTokenInfo (slotId)); - } - catch (Pkcs11Exception &e) - { - if (e.GetErrorCode() == CKR_TOKEN_NOT_RECOGNIZED) - { - unrecognizedTokenPresent = true; - continue; - } - - throw; - } - } - - if (tokens.empty() && unrecognizedTokenPresent) - throw Pkcs11Exception (CKR_TOKEN_NOT_RECOGNIZED); - - return tokens; - } - - SecurityTokenInfo SecurityToken::GetTokenInfo (CK_SLOT_ID slotId) - { - CK_TOKEN_INFO info; - CK_RV status = Pkcs11Functions->C_GetTokenInfo (slotId, &info); - if (status != CKR_OK) - throw Pkcs11Exception (status); - - SecurityTokenInfo token; - token.SlotId = slotId; - token.Flags = info.flags; - - char label[sizeof (info.label) + 1]; - memset (label, 0, sizeof (label)); - memcpy (label, info.label, sizeof (info.label)); - - token.LabelUtf8 = label; - - size_t lastSpace = token.LabelUtf8.find_last_not_of (' '); - if (lastSpace == string::npos) - token.LabelUtf8.clear(); - else - token.LabelUtf8 = token.LabelUtf8.substr (0, lastSpace + 1); - -#if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE) - token.Label = Utf8StringToWide (token.LabelUtf8); -#else - token.Label = StringConverter::ToWide (token.LabelUtf8); -#endif - return token; - } - - void SecurityToken::GetKeyfileData (const SecurityTokenKeyfile &keyfile, vector &keyfileData) - { - GetKeyfileData (keyfile, nullptr, keyfileData); - } - - void SecurityToken::GetKeyfileData (const SecurityTokenKeyfile &keyfile, char* pin, vector &keyfileData) - { - LoginUserIfRequired (keyfile.SlotId, pin); - GetObjectAttribute (keyfile.SlotId, keyfile.Handle, CKA_VALUE, keyfileData); - } - - vector SecurityToken::GetObjects (CK_SLOT_ID slotId, CK_ATTRIBUTE_TYPE objectClass) - { - if (Sessions.find (slotId) == Sessions.end()) - throw ParameterIncorrect (SRC_POS); - - CK_ATTRIBUTE findTemplate; - findTemplate.type = CKA_CLASS; - findTemplate.pValue = &objectClass; - findTemplate.ulValueLen = sizeof (objectClass); - - CK_RV status = Pkcs11Functions->C_FindObjectsInit (Sessions[slotId].Handle, &findTemplate, 1); - if (status != CKR_OK) - throw Pkcs11Exception (status); - - finally_do_arg (CK_SLOT_ID, slotId, { Pkcs11Functions->C_FindObjectsFinal (Sessions[finally_arg].Handle); }); - - CK_ULONG objectCount; - vector objects; - - while (true) - { - CK_OBJECT_HANDLE object; - CK_RV status = Pkcs11Functions->C_FindObjects (Sessions[slotId].Handle, &object, 1, &objectCount); - if (status != CKR_OK) - throw Pkcs11Exception (status); - - if (objectCount != 1) - break; - - objects.push_back (object); - } - - return objects; - } - - void SecurityToken::GetObjectAttribute (CK_SLOT_ID slotId, CK_OBJECT_HANDLE tokenObject, CK_ATTRIBUTE_TYPE attributeType, vector &attributeValue) - { - attributeValue.clear(); - - if (Sessions.find (slotId) == Sessions.end()) - throw ParameterIncorrect (SRC_POS); - - CK_ATTRIBUTE attribute; - attribute.type = attributeType; - attribute.pValue = NULL_PTR; - - CK_RV status = Pkcs11Functions->C_GetAttributeValue (Sessions[slotId].Handle, tokenObject, &attribute, 1); - if (status != CKR_OK) - throw Pkcs11Exception (status); - - if (attribute.ulValueLen == 0) - return; - - attributeValue = vector (attribute.ulValueLen); - attribute.pValue = &attributeValue.front(); - - status = Pkcs11Functions->C_GetAttributeValue (Sessions[slotId].Handle, tokenObject, &attribute, 1); - if (status != CKR_OK) - throw Pkcs11Exception (status); - } - - list SecurityToken::GetTokenSlots () - { - CheckLibraryStatus(); - - list slots; - CK_ULONG slotCount; - - CK_RV status = Pkcs11Functions->C_GetSlotList (TRUE, NULL_PTR, &slotCount); - if (status != CKR_OK) - throw Pkcs11Exception (status); - - if (slotCount > 0) - { - vector slotArray (slotCount); - status = Pkcs11Functions->C_GetSlotList (TRUE, &slotArray.front(), &slotCount); - if (status != CKR_OK) - throw Pkcs11Exception (status); - - for (size_t i = 0; i < slotCount; i++) - { - CK_SLOT_INFO slotInfo; - status = Pkcs11Functions->C_GetSlotInfo (slotArray[i], &slotInfo); - - if (status != CKR_OK || !(slotInfo.flags & CKF_TOKEN_PRESENT)) - continue; - - slots.push_back (slotArray[i]); - } - } - - return slots; - } - - bool SecurityToken::IsKeyfilePathValid (const wstring &securityTokenKeyfilePath) - { - return securityTokenKeyfilePath.find (TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX) == 0; - } - - void SecurityToken::Login (CK_SLOT_ID slotId, const char* pin) - { - if (Sessions.find (slotId) == Sessions.end()) - OpenSession (slotId); - else if (Sessions[slotId].UserLoggedIn) - return; - - size_t pinLen = pin? strlen (pin) : 0; - CK_RV status = Pkcs11Functions->C_Login (Sessions[slotId].Handle, CKU_USER, (CK_CHAR_PTR) pin, (CK_ULONG) pinLen); - - if (status != CKR_OK) - throw Pkcs11Exception (status); - - Sessions[slotId].UserLoggedIn = true; - } - - void SecurityToken::LoginUserIfRequired (CK_SLOT_ID slotId, char* cmdPin) - { - CheckLibraryStatus(); - CK_RV status; - - if (Sessions.find (slotId) == Sessions.end()) - { - OpenSession (slotId); - } - else - { - CK_SESSION_INFO sessionInfo; - status = Pkcs11Functions->C_GetSessionInfo (Sessions[slotId].Handle, &sessionInfo); - - if (status == CKR_OK) - { - Sessions[slotId].UserLoggedIn = (sessionInfo.state == CKS_RO_USER_FUNCTIONS || sessionInfo.state == CKS_RW_USER_FUNCTIONS); - } - else - { - try - { - CloseSession (slotId); - } - catch (...) { } - OpenSession (slotId); - } - } - - SecurityTokenInfo tokenInfo = GetTokenInfo (slotId); - - while (!Sessions[slotId].UserLoggedIn && (tokenInfo.Flags & CKF_LOGIN_REQUIRED)) - { - try - { - if (tokenInfo.Flags & CKF_PROTECTED_AUTHENTICATION_PATH) - { - status = Pkcs11Functions->C_Login (Sessions[slotId].Handle, CKU_USER, NULL_PTR, 0); - if (status != CKR_OK) - throw Pkcs11Exception (status); - } - else if (cmdPin && cmdPin [0]) - { - Login (slotId, cmdPin); - } - else - { - string pin = tokenInfo.LabelUtf8; - if (tokenInfo.Label.empty()) - { - stringstream s; - s << "#" << slotId; - pin = s.str(); - } - - finally_do_arg (string*, &pin, { burn ((void *) finally_arg->c_str(), finally_arg->size()); }); - - (*PinCallback) (pin); - Login (slotId, pin.c_str()); - } - - Sessions[slotId].UserLoggedIn = true; - } - catch (Pkcs11Exception &e) - { - CK_RV error = e.GetErrorCode(); - - if (error == CKR_USER_ALREADY_LOGGED_IN) - { - break; - } - else if (error == CKR_PIN_INCORRECT && !(tokenInfo.Flags & CKF_PROTECTED_AUTHENTICATION_PATH)) - { - if (cmdPin && cmdPin [0]) - { - // clear wrong PIN - size_t cmdPinLen = strlen (cmdPin); - burn (cmdPin, cmdPinLen); - } - (*WarningCallback) (Pkcs11Exception (CKR_PIN_INCORRECT)); - continue; - } - - throw; - } - } - } - -#ifdef TC_WINDOWS - void SecurityToken::InitLibrary (const wstring &pkcs11LibraryPath, auto_ptr pinCallback, auto_ptr warningCallback) -#else - void SecurityToken::InitLibrary (const string &pkcs11LibraryPath, auto_ptr pinCallback, auto_ptr warningCallback) -#endif - { - if (Initialized) - CloseLibrary(); - -#ifdef TC_WINDOWS +/* + Derived from source code of TrueCrypt 7.1a, which is + Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed + by the TrueCrypt License 3.0. + + Modifications and additions to the original source code (contained in this file) + and all other portions of this file are Copyright (c) 2013-2016 IDRIX + and are governed by the Apache License 2.0 the full text of which is + contained in the file License.txt included in VeraCrypt binary and source + code distribution packages. +*/ + +#include "Platform/Finally.h" +#include "Platform/ForEach.h" + +#if !defined (TC_WINDOWS) || defined (TC_PROTOTYPE) +# include "Platform/SerializerFactory.h" +# include "Platform/StringConverter.h" +# include "Platform/SystemException.h" +#else +# include "Dictionary.h" +# include "Language.h" +#endif + +#ifdef TC_UNIX +# include +#endif + +#include "SecurityToken.h" + +#ifndef burn +# define burn Memory::Erase +#endif + +using namespace std; + +namespace VeraCrypt +{ + SecurityTokenKeyfile::SecurityTokenKeyfile (const SecurityTokenKeyfilePath &path, char* pin) + { + wstring pathStr = path; + unsigned long slotId; + + if (swscanf (pathStr.c_str(), TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX TC_SECURITY_TOKEN_KEYFILE_URL_SLOT L"/%lu", &slotId) != 1) + throw InvalidSecurityTokenKeyfilePath(); + + SlotId = slotId; + + size_t keyIdPos = pathStr.find (L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/"); + if (keyIdPos == wstring::npos) + throw InvalidSecurityTokenKeyfilePath(); + + Id = pathStr.substr (keyIdPos + wstring (L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/").size()); + + vector keyfiles = SecurityToken::GetAvailableKeyfiles (&SlotId, Id, pin); + + if (keyfiles.empty()) + throw SecurityTokenKeyfileNotFound(); + + *this = keyfiles.front(); + } + + SecurityTokenKeyfile::operator SecurityTokenKeyfilePath () const + { + wstringstream path; + path << TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX TC_SECURITY_TOKEN_KEYFILE_URL_SLOT L"/" << SlotId << L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/" << Id; + return path.str(); + } + + void SecurityToken::CheckLibraryStatus () + { + if (!Initialized) + throw SecurityTokenLibraryNotInitialized(); + } + + void SecurityToken::CloseLibrary () + { + if (Initialized) + { + CloseAllSessions(); + Pkcs11Functions->C_Finalize (NULL_PTR); + +#ifdef TC_WINDOWS + FreeLibrary (Pkcs11LibraryHandle); +#else + dlclose (Pkcs11LibraryHandle); +#endif + Initialized = false; + } + } + + void SecurityToken::CloseAllSessions () throw () + { + if (!Initialized) + return; + + typedef pair SessionMapPair; + + foreach (SessionMapPair p, Sessions) + { + try + { + CloseSession (p.first); + } + catch (...) { } + } + } + + void SecurityToken::CloseSession (CK_SLOT_ID slotId) + { + if (Sessions.find (slotId) == Sessions.end()) + throw ParameterIncorrect (SRC_POS); + + Pkcs11Functions->C_CloseSession (Sessions[slotId].Handle); + Sessions.erase (Sessions.find (slotId)); + } + + void SecurityToken::CreateKeyfile (CK_SLOT_ID slotId, vector &keyfileData, const string &name) + { + if (name.empty()) + throw ParameterIncorrect (SRC_POS); + + LoginUserIfRequired (slotId); + + foreach (const SecurityTokenKeyfile &keyfile, GetAvailableKeyfiles (&slotId)) + { + if (keyfile.IdUtf8 == name) + throw SecurityTokenKeyfileAlreadyExists(); + } + + CK_OBJECT_CLASS dataClass = CKO_DATA; + CK_BBOOL trueVal = CK_TRUE; + + CK_ATTRIBUTE keyfileTemplate[] = + { + { CKA_CLASS, &dataClass, sizeof (dataClass) }, + { CKA_TOKEN, &trueVal, sizeof (trueVal) }, + { CKA_PRIVATE, &trueVal, sizeof (trueVal) }, + { CKA_LABEL, (CK_UTF8CHAR *) name.c_str(), (CK_ULONG) name.size() }, + { CKA_VALUE, &keyfileData.front(), (CK_ULONG) keyfileData.size() } + }; + + CK_OBJECT_HANDLE keyfileHandle; + + CK_RV status = Pkcs11Functions->C_CreateObject (Sessions[slotId].Handle, keyfileTemplate, array_capacity (keyfileTemplate), &keyfileHandle); + + switch (status) + { + case CKR_DATA_LEN_RANGE: + status = CKR_DEVICE_MEMORY; + break; + + case CKR_SESSION_READ_ONLY: + status = CKR_TOKEN_WRITE_PROTECTED; + break; + } + + if (status != CKR_OK) + throw Pkcs11Exception (status); + + // Some tokens report success even if the new object was truncated to fit in the available memory + vector objectData; + + GetObjectAttribute (slotId, keyfileHandle, CKA_VALUE, objectData); + finally_do_arg (vector *, &objectData, { if (!finally_arg->empty()) burn (&finally_arg->front(), finally_arg->size()); }); + + if (objectData.size() != keyfileData.size()) + { + Pkcs11Functions->C_DestroyObject (Sessions[slotId].Handle, keyfileHandle); + throw Pkcs11Exception (CKR_DEVICE_MEMORY); + } + } + + void SecurityToken::DeleteKeyfile (const SecurityTokenKeyfile &keyfile) + { + LoginUserIfRequired (keyfile.SlotId); + + CK_RV status = Pkcs11Functions->C_DestroyObject (Sessions[keyfile.SlotId].Handle, keyfile.Handle); + if (status != CKR_OK) + throw Pkcs11Exception (status); + } + + vector SecurityToken::GetAvailableKeyfiles (CK_SLOT_ID *slotIdFilter, const wstring keyfileIdFilter, char* pin) + { + bool unrecognizedTokenPresent = false; + vector keyfiles; + + foreach (const CK_SLOT_ID &slotId, GetTokenSlots()) + { + SecurityTokenInfo token; + + if (slotIdFilter && *slotIdFilter != slotId) + continue; + + try + { + LoginUserIfRequired (slotId, pin); + token = GetTokenInfo (slotId); + } + catch (UserAbort &) + { + continue; + } + catch (Pkcs11Exception &e) + { + if (e.GetErrorCode() == CKR_TOKEN_NOT_RECOGNIZED) + { + unrecognizedTokenPresent = true; + continue; + } + + throw; + } + + foreach (const CK_OBJECT_HANDLE &dataHandle, GetObjects (slotId, CKO_DATA)) + { + SecurityTokenKeyfile keyfile; + keyfile.Handle = dataHandle; + keyfile.SlotId = slotId; + keyfile.Token = token; + + vector privateAttrib; + GetObjectAttribute (slotId, dataHandle, CKA_PRIVATE, privateAttrib); + + if (privateAttrib.size() == sizeof (CK_BBOOL) && *(CK_BBOOL *) &privateAttrib.front() != CK_TRUE) + continue; + + vector label; + GetObjectAttribute (slotId, dataHandle, CKA_LABEL, label); + label.push_back (0); + + keyfile.IdUtf8 = (char *) &label.front(); + +#if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE) + keyfile.Id = Utf8StringToWide ((const char *) &label.front()); +#else + keyfile.Id = StringConverter::ToWide ((const char *) &label.front()); +#endif + if (keyfile.Id.empty() || (!keyfileIdFilter.empty() && keyfileIdFilter != keyfile.Id)) + continue; + + keyfiles.push_back (keyfile); + + if (!keyfileIdFilter.empty()) + break; + } + } + + if (keyfiles.empty() && unrecognizedTokenPresent) + throw Pkcs11Exception (CKR_TOKEN_NOT_RECOGNIZED); + + return keyfiles; + } + + list SecurityToken::GetAvailableTokens () + { + bool unrecognizedTokenPresent = false; + list tokens; + + foreach (const CK_SLOT_ID &slotId, GetTokenSlots()) + { + try + { + tokens.push_back (GetTokenInfo (slotId)); + } + catch (Pkcs11Exception &e) + { + if (e.GetErrorCode() == CKR_TOKEN_NOT_RECOGNIZED) + { + unrecognizedTokenPresent = true; + continue; + } + + throw; + } + } + + if (tokens.empty() && unrecognizedTokenPresent) + throw Pkcs11Exception (CKR_TOKEN_NOT_RECOGNIZED); + + return tokens; + } + + SecurityTokenInfo SecurityToken::GetTokenInfo (CK_SLOT_ID slotId) + { + CK_TOKEN_INFO info; + CK_RV status = Pkcs11Functions->C_GetTokenInfo (slotId, &info); + if (status != CKR_OK) + throw Pkcs11Exception (status); + + SecurityTokenInfo token; + token.SlotId = slotId; + token.Flags = info.flags; + + char label[sizeof (info.label) + 1]; + memset (label, 0, sizeof (label)); + memcpy (label, info.label, sizeof (info.label)); + + token.LabelUtf8 = label; + + size_t lastSpace = token.LabelUtf8.find_last_not_of (' '); + if (lastSpace == string::npos) + token.LabelUtf8.clear(); + else + token.LabelUtf8 = token.LabelUtf8.substr (0, lastSpace + 1); + +#if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE) + token.Label = Utf8StringToWide (token.LabelUtf8); +#else + token.Label = StringConverter::ToWide (token.LabelUtf8); +#endif + return token; + } + + void SecurityToken::GetKeyfileData (const SecurityTokenKeyfile &keyfile, vector &keyfileData) + { + GetKeyfileData (keyfile, nullptr, keyfileData); + } + + void SecurityToken::GetKeyfileData (const SecurityTokenKeyfile &keyfile, char* pin, vector &keyfileData) + { + LoginUserIfRequired (keyfile.SlotId, pin); + GetObjectAttribute (keyfile.SlotId, keyfile.Handle, CKA_VALUE, keyfileData); + } + + vector SecurityToken::GetObjects (CK_SLOT_ID slotId, CK_ATTRIBUTE_TYPE objectClass) + { + if (Sessions.find (slotId) == Sessions.end()) + throw ParameterIncorrect (SRC_POS); + + CK_ATTRIBUTE findTemplate; + findTemplate.type = CKA_CLASS; + findTemplate.pValue = &objectClass; + findTemplate.ulValueLen = sizeof (objectClass); + + CK_RV status = Pkcs11Functions->C_FindObjectsInit (Sessions[slotId].Handle, &findTemplate, 1); + if (status != CKR_OK) + throw Pkcs11Exception (status); + + finally_do_arg (CK_SLOT_ID, slotId, { Pkcs11Functions->C_FindObjectsFinal (Sessions[finally_arg].Handle); }); + + CK_ULONG objectCount; + vector objects; + + while (true) + { + CK_OBJECT_HANDLE object; + CK_RV status = Pkcs11Functions->C_FindObjects (Sessions[slotId].Handle, &object, 1, &objectCount); + if (status != CKR_OK) + throw Pkcs11Exception (status); + + if (objectCount != 1) + break; + + objects.push_back (object); + } + + return objects; + } + + void SecurityToken::GetObjectAttribute (CK_SLOT_ID slotId, CK_OBJECT_HANDLE tokenObject, CK_ATTRIBUTE_TYPE attributeType, vector &attributeValue) + { + attributeValue.clear(); + + if (Sessions.find (slotId) == Sessions.end()) + throw ParameterIncorrect (SRC_POS); + + CK_ATTRIBUTE attribute; + attribute.type = attributeType; + attribute.pValue = NULL_PTR; + + CK_RV status = Pkcs11Functions->C_GetAttributeValue (Sessions[slotId].Handle, tokenObject, &attribute, 1); + if (status != CKR_OK) + throw Pkcs11Exception (status); + + if (attribute.ulValueLen == 0) + return; + + attributeValue = vector (attribute.ulValueLen); + attribute.pValue = &attributeValue.front(); + + status = Pkcs11Functions->C_GetAttributeValue (Sessions[slotId].Handle, tokenObject, &attribute, 1); + if (status != CKR_OK) + throw Pkcs11Exception (status); + } + + list SecurityToken::GetTokenSlots () + { + CheckLibraryStatus(); + + list slots; + CK_ULONG slotCount; + + CK_RV status = Pkcs11Functions->C_GetSlotList (TRUE, NULL_PTR, &slotCount); + if (status != CKR_OK) + throw Pkcs11Exception (status); + + if (slotCount > 0) + { + vector slotArray (slotCount); + status = Pkcs11Functions->C_GetSlotList (TRUE, &slotArray.front(), &slotCount); + if (status != CKR_OK) + throw Pkcs11Exception (status); + + for (size_t i = 0; i < slotCount; i++) + { + CK_SLOT_INFO slotInfo; + status = Pkcs11Functions->C_GetSlotInfo (slotArray[i], &slotInfo); + + if (status != CKR_OK || !(slotInfo.flags & CKF_TOKEN_PRESENT)) + continue; + + slots.push_back (slotArray[i]); + } + } + + return slots; + } + + bool SecurityToken::IsKeyfilePathValid (const wstring &securityTokenKeyfilePath) + { + return securityTokenKeyfilePath.find (TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX) == 0; + } + + void SecurityToken::Login (CK_SLOT_ID slotId, const char* pin) + { + if (Sessions.find (slotId) == Sessions.end()) + OpenSession (slotId); + else if (Sessions[slotId].UserLoggedIn) + return; + + size_t pinLen = pin? strlen (pin) : 0; + CK_RV status = Pkcs11Functions->C_Login (Sessions[slotId].Handle, CKU_USER, (CK_CHAR_PTR) pin, (CK_ULONG) pinLen); + + if (status != CKR_OK) + throw Pkcs11Exception (status); + + Sessions[slotId].UserLoggedIn = true; + } + + void SecurityToken::LoginUserIfRequired (CK_SLOT_ID slotId, char* cmdPin) + { + CheckLibraryStatus(); + CK_RV status; + + if (Sessions.find (slotId) == Sessions.end()) + { + OpenSession (slotId); + } + else + { + CK_SESSION_INFO sessionInfo; + status = Pkcs11Functions->C_GetSessionInfo (Sessions[slotId].Handle, &sessionInfo); + + if (status == CKR_OK) + { + Sessions[slotId].UserLoggedIn = (sessionInfo.state == CKS_RO_USER_FUNCTIONS || sessionInfo.state == CKS_RW_USER_FUNCTIONS); + } + else + { + try + { + CloseSession (slotId); + } + catch (...) { } + OpenSession (slotId); + } + } + + SecurityTokenInfo tokenInfo = GetTokenInfo (slotId); + + while (!Sessions[slotId].UserLoggedIn && (tokenInfo.Flags & CKF_LOGIN_REQUIRED)) + { + try + { + if (tokenInfo.Flags & CKF_PROTECTED_AUTHENTICATION_PATH) + { + status = Pkcs11Functions->C_Login (Sessions[slotId].Handle, CKU_USER, NULL_PTR, 0); + if (status != CKR_OK) + throw Pkcs11Exception (status); + } + else if (cmdPin && cmdPin [0]) + { + Login (slotId, cmdPin); + } + else + { + string pin = tokenInfo.LabelUtf8; + if (tokenInfo.Label.empty()) + { + stringstream s; + s << "#" << slotId; + pin = s.str(); + } + + finally_do_arg (string*, &pin, { burn ((void *) finally_arg->c_str(), finally_arg->size()); }); + + (*PinCallback) (pin); + Login (slotId, pin.c_str()); + } + + Sessions[slotId].UserLoggedIn = true; + } + catch (Pkcs11Exception &e) + { + CK_RV error = e.GetErrorCode(); + + if (error == CKR_USER_ALREADY_LOGGED_IN) + { + break; + } + else if (error == CKR_PIN_INCORRECT && !(tokenInfo.Flags & CKF_PROTECTED_AUTHENTICATION_PATH)) + { + if (cmdPin && cmdPin [0]) + { + // clear wrong PIN + size_t cmdPinLen = strlen (cmdPin); + burn (cmdPin, cmdPinLen); + } + (*WarningCallback) (Pkcs11Exception (CKR_PIN_INCORRECT)); + continue; + } + + throw; + } + } + } + +#ifdef TC_WINDOWS + void SecurityToken::InitLibrary (const wstring &pkcs11LibraryPath, auto_ptr pinCallback, auto_ptr warningCallback) +#else + void SecurityToken::InitLibrary (const string &pkcs11LibraryPath, auto_ptr pinCallback, auto_ptr warningCallback) +#endif + { + if (Initialized) + CloseLibrary(); + +#ifdef TC_WINDOWS Pkcs11LibraryHandle = LoadLibraryW (pkcs11LibraryPath.c_str()); - throw_sys_if (!Pkcs11LibraryHandle); -#else + throw_sys_if (!Pkcs11LibraryHandle); +#else Pkcs11LibraryHandle = dlopen (pkcs11LibraryPath.c_str(), RTLD_NOW | RTLD_LOCAL); - throw_sys_sub_if (!Pkcs11LibraryHandle, dlerror()); -#endif - - - typedef CK_RV (*C_GetFunctionList_t) (CK_FUNCTION_LIST_PTR_PTR ppFunctionList); -#ifdef TC_WINDOWS - C_GetFunctionList_t C_GetFunctionList = (C_GetFunctionList_t) GetProcAddress (Pkcs11LibraryHandle, "C_GetFunctionList"); -#else - C_GetFunctionList_t C_GetFunctionList = (C_GetFunctionList_t) dlsym (Pkcs11LibraryHandle, "C_GetFunctionList"); -#endif - - if (!C_GetFunctionList) - throw SecurityTokenLibraryNotInitialized(); - - CK_RV status = C_GetFunctionList (&Pkcs11Functions); - if (status != CKR_OK) - throw Pkcs11Exception (status); - - status = Pkcs11Functions->C_Initialize (NULL_PTR); - if (status != CKR_OK) - throw Pkcs11Exception (status); - - PinCallback = pinCallback; - WarningCallback = warningCallback; - - Initialized = true; - } - - void SecurityToken::OpenSession (CK_SLOT_ID slotId) - { - if (Sessions.find (slotId) != Sessions.end()) - return; - - CK_SESSION_HANDLE session; - - CK_FLAGS flags = CKF_SERIAL_SESSION; - - if (!(GetTokenInfo (slotId).Flags & CKF_WRITE_PROTECTED)) - flags |= CKF_RW_SESSION; - - CK_RV status = Pkcs11Functions->C_OpenSession (slotId, flags, NULL_PTR, NULL_PTR, &session); - if (status != CKR_OK) - throw Pkcs11Exception (status); - - Sessions[slotId].Handle = session; - } - - Pkcs11Exception::operator string () const - { - if (ErrorCode == CKR_OK) - return string(); - - static const struct - { - CK_RV ErrorCode; - const char *ErrorString; - } ErrorStrings[] = - { -# define TC_TOKEN_ERR(CODE) { CODE, #CODE }, - - TC_TOKEN_ERR (CKR_CANCEL) - TC_TOKEN_ERR (CKR_HOST_MEMORY) - TC_TOKEN_ERR (CKR_SLOT_ID_INVALID) - TC_TOKEN_ERR (CKR_GENERAL_ERROR) - TC_TOKEN_ERR (CKR_FUNCTION_FAILED) - TC_TOKEN_ERR (CKR_ARGUMENTS_BAD) - TC_TOKEN_ERR (CKR_NO_EVENT) - TC_TOKEN_ERR (CKR_NEED_TO_CREATE_THREADS) - TC_TOKEN_ERR (CKR_CANT_LOCK) - TC_TOKEN_ERR (CKR_ATTRIBUTE_READ_ONLY) - TC_TOKEN_ERR (CKR_ATTRIBUTE_SENSITIVE) - TC_TOKEN_ERR (CKR_ATTRIBUTE_TYPE_INVALID) - TC_TOKEN_ERR (CKR_ATTRIBUTE_VALUE_INVALID) - TC_TOKEN_ERR (CKR_DATA_INVALID) - TC_TOKEN_ERR (CKR_DATA_LEN_RANGE) - TC_TOKEN_ERR (CKR_DEVICE_ERROR) - TC_TOKEN_ERR (CKR_DEVICE_MEMORY) - TC_TOKEN_ERR (CKR_DEVICE_REMOVED) - TC_TOKEN_ERR (CKR_ENCRYPTED_DATA_INVALID) - TC_TOKEN_ERR (CKR_ENCRYPTED_DATA_LEN_RANGE) - TC_TOKEN_ERR (CKR_FUNCTION_CANCELED) - TC_TOKEN_ERR (CKR_FUNCTION_NOT_PARALLEL) - TC_TOKEN_ERR (CKR_FUNCTION_NOT_SUPPORTED) - TC_TOKEN_ERR (CKR_KEY_HANDLE_INVALID) - TC_TOKEN_ERR (CKR_KEY_SIZE_RANGE) - TC_TOKEN_ERR (CKR_KEY_TYPE_INCONSISTENT) - TC_TOKEN_ERR (CKR_KEY_NOT_NEEDED) - TC_TOKEN_ERR (CKR_KEY_CHANGED) - TC_TOKEN_ERR (CKR_KEY_NEEDED) - TC_TOKEN_ERR (CKR_KEY_INDIGESTIBLE) - TC_TOKEN_ERR (CKR_KEY_FUNCTION_NOT_PERMITTED) - TC_TOKEN_ERR (CKR_KEY_NOT_WRAPPABLE) - TC_TOKEN_ERR (CKR_KEY_UNEXTRACTABLE) - TC_TOKEN_ERR (CKR_MECHANISM_INVALID) - TC_TOKEN_ERR (CKR_MECHANISM_PARAM_INVALID) - TC_TOKEN_ERR (CKR_OBJECT_HANDLE_INVALID) - TC_TOKEN_ERR (CKR_OPERATION_ACTIVE) - TC_TOKEN_ERR (CKR_OPERATION_NOT_INITIALIZED) - TC_TOKEN_ERR (CKR_PIN_INCORRECT) - TC_TOKEN_ERR (CKR_PIN_INVALID) - TC_TOKEN_ERR (CKR_PIN_LEN_RANGE) - TC_TOKEN_ERR (CKR_PIN_EXPIRED) - TC_TOKEN_ERR (CKR_PIN_LOCKED) - TC_TOKEN_ERR (CKR_SESSION_CLOSED) - TC_TOKEN_ERR (CKR_SESSION_COUNT) - TC_TOKEN_ERR (CKR_SESSION_HANDLE_INVALID) - TC_TOKEN_ERR (CKR_SESSION_PARALLEL_NOT_SUPPORTED) - TC_TOKEN_ERR (CKR_SESSION_READ_ONLY) - TC_TOKEN_ERR (CKR_SESSION_EXISTS) - TC_TOKEN_ERR (CKR_SESSION_READ_ONLY_EXISTS) - TC_TOKEN_ERR (CKR_SESSION_READ_WRITE_SO_EXISTS) - TC_TOKEN_ERR (CKR_SIGNATURE_INVALID) - TC_TOKEN_ERR (CKR_SIGNATURE_LEN_RANGE) - TC_TOKEN_ERR (CKR_TEMPLATE_INCOMPLETE) - TC_TOKEN_ERR (CKR_TEMPLATE_INCONSISTENT) - TC_TOKEN_ERR (CKR_TOKEN_NOT_PRESENT) - TC_TOKEN_ERR (CKR_TOKEN_NOT_RECOGNIZED) - TC_TOKEN_ERR (CKR_TOKEN_WRITE_PROTECTED) - TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_HANDLE_INVALID) - TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_SIZE_RANGE) - TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT) - TC_TOKEN_ERR (CKR_USER_ALREADY_LOGGED_IN) - TC_TOKEN_ERR (CKR_USER_NOT_LOGGED_IN) - TC_TOKEN_ERR (CKR_USER_PIN_NOT_INITIALIZED) - TC_TOKEN_ERR (CKR_USER_TYPE_INVALID) - TC_TOKEN_ERR (CKR_USER_ANOTHER_ALREADY_LOGGED_IN) - TC_TOKEN_ERR (CKR_USER_TOO_MANY_TYPES) - TC_TOKEN_ERR (CKR_WRAPPED_KEY_INVALID) - TC_TOKEN_ERR (CKR_WRAPPED_KEY_LEN_RANGE) - TC_TOKEN_ERR (CKR_WRAPPING_KEY_HANDLE_INVALID) - TC_TOKEN_ERR (CKR_WRAPPING_KEY_SIZE_RANGE) - TC_TOKEN_ERR (CKR_WRAPPING_KEY_TYPE_INCONSISTENT) - TC_TOKEN_ERR (CKR_RANDOM_SEED_NOT_SUPPORTED) - TC_TOKEN_ERR (CKR_RANDOM_NO_RNG) - TC_TOKEN_ERR (CKR_DOMAIN_PARAMS_INVALID) - TC_TOKEN_ERR (CKR_BUFFER_TOO_SMALL) - TC_TOKEN_ERR (CKR_SAVED_STATE_INVALID) - TC_TOKEN_ERR (CKR_INFORMATION_SENSITIVE) - TC_TOKEN_ERR (CKR_STATE_UNSAVEABLE) - TC_TOKEN_ERR (CKR_CRYPTOKI_NOT_INITIALIZED) - TC_TOKEN_ERR (CKR_CRYPTOKI_ALREADY_INITIALIZED) - TC_TOKEN_ERR (CKR_MUTEX_BAD) - TC_TOKEN_ERR (CKR_MUTEX_NOT_LOCKED) - TC_TOKEN_ERR (CKR_NEW_PIN_MODE) - TC_TOKEN_ERR (CKR_NEXT_OTP) - TC_TOKEN_ERR (CKR_FUNCTION_REJECTED) - -#undef TC_TOKEN_ERR - }; - - - for (size_t i = 0; i < array_capacity (ErrorStrings); ++i) - { - if (ErrorStrings[i].ErrorCode == ErrorCode) - return ErrorStrings[i].ErrorString; - } - - stringstream s; - s << "0x" << hex << ErrorCode; - return s.str(); - - } - -#ifdef TC_HEADER_Common_Exception - void Pkcs11Exception::Show (HWND parent) const - { - string errorString = string (*this); - - if (!errorString.empty()) - { - wstringstream subjectErrorCode; - if (SubjectErrorCodeValid) - subjectErrorCode << L": " << SubjectErrorCode; - - if (!GetDictionaryValue (errorString.c_str())) - { - if (errorString.find ("CKR_") == 0) - { - errorString = errorString.substr (4); - for (size_t i = 0; i < errorString.size(); ++i) - { - if (errorString[i] == '_') - errorString[i] = ' '; - } - } - wchar_t err[8192]; - StringCbPrintfW (err, sizeof(err),L"%s:\n\n%hs%s", GetString ("SECURITY_TOKEN_ERROR"), errorString.c_str(), subjectErrorCode.str().c_str()); - ErrorDirect (err, parent); - } - else - { - wstring err = GetString (errorString.c_str()); - - if (SubjectErrorCodeValid) - err += L"\n\nError code" + subjectErrorCode.str(); - - ErrorDirect (err.c_str(), parent); - } - } - } -#endif // TC_HEADER_Common_Exception - - auto_ptr SecurityToken::PinCallback; - auto_ptr SecurityToken::WarningCallback; - - bool SecurityToken::Initialized; - CK_FUNCTION_LIST_PTR SecurityToken::Pkcs11Functions; - map SecurityToken::Sessions; - -#ifdef TC_WINDOWS - HMODULE SecurityToken::Pkcs11LibraryHandle; -#else - void *SecurityToken::Pkcs11LibraryHandle; -#endif - -#ifdef TC_HEADER_Platform_Exception - - void Pkcs11Exception::Deserialize (shared_ptr stream) - { - Exception::Deserialize (stream); - Serializer sr (stream); - uint64 code; - sr.Deserialize ("ErrorCode", code); - sr.Deserialize ("SubjectErrorCodeValid", SubjectErrorCodeValid); - sr.Deserialize ("SubjectErrorCode", SubjectErrorCode); - ErrorCode = (CK_RV) code; - } - - void Pkcs11Exception::Serialize (shared_ptr stream) const - { - Exception::Serialize (stream); - Serializer sr (stream); - sr.Serialize ("ErrorCode", (uint64) ErrorCode); - sr.Serialize ("SubjectErrorCodeValid", SubjectErrorCodeValid); - sr.Serialize ("SubjectErrorCode", SubjectErrorCode); - } - -# define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) -# undef TC_EXCEPTION_NODECL -# define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) - - TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (SecurityTokenException); - -#endif -} + throw_sys_sub_if (!Pkcs11LibraryHandle, dlerror()); +#endif + + + typedef CK_RV (*C_GetFunctionList_t) (CK_FUNCTION_LIST_PTR_PTR ppFunctionList); +#ifdef TC_WINDOWS + C_GetFunctionList_t C_GetFunctionList = (C_GetFunctionList_t) GetProcAddress (Pkcs11LibraryHandle, "C_GetFunctionList"); +#else + C_GetFunctionList_t C_GetFunctionList = (C_GetFunctionList_t) dlsym (Pkcs11LibraryHandle, "C_GetFunctionList"); +#endif + + if (!C_GetFunctionList) + throw SecurityTokenLibraryNotInitialized(); + + CK_RV status = C_GetFunctionList (&Pkcs11Functions); + if (status != CKR_OK) + throw Pkcs11Exception (status); + + status = Pkcs11Functions->C_Initialize (NULL_PTR); + if (status != CKR_OK) + throw Pkcs11Exception (status); + + PinCallback = pinCallback; + WarningCallback = warningCallback; + + Initialized = true; + } + + void SecurityToken::OpenSession (CK_SLOT_ID slotId) + { + if (Sessions.find (slotId) != Sessions.end()) + return; + + CK_SESSION_HANDLE session; + + CK_FLAGS flags = CKF_SERIAL_SESSION; + + if (!(GetTokenInfo (slotId).Flags & CKF_WRITE_PROTECTED)) + flags |= CKF_RW_SESSION; + + CK_RV status = Pkcs11Functions->C_OpenSession (slotId, flags, NULL_PTR, NULL_PTR, &session); + if (status != CKR_OK) + throw Pkcs11Exception (status); + + Sessions[slotId].Handle = session; + } + + Pkcs11Exception::operator string () const + { + if (ErrorCode == CKR_OK) + return string(); + + static const struct + { + CK_RV ErrorCode; + const char *ErrorString; + } ErrorStrings[] = + { +# define TC_TOKEN_ERR(CODE) { CODE, #CODE }, + + TC_TOKEN_ERR (CKR_CANCEL) + TC_TOKEN_ERR (CKR_HOST_MEMORY) + TC_TOKEN_ERR (CKR_SLOT_ID_INVALID) + TC_TOKEN_ERR (CKR_GENERAL_ERROR) + TC_TOKEN_ERR (CKR_FUNCTION_FAILED) + TC_TOKEN_ERR (CKR_ARGUMENTS_BAD) + TC_TOKEN_ERR (CKR_NO_EVENT) + TC_TOKEN_ERR (CKR_NEED_TO_CREATE_THREADS) + TC_TOKEN_ERR (CKR_CANT_LOCK) + TC_TOKEN_ERR (CKR_ATTRIBUTE_READ_ONLY) + TC_TOKEN_ERR (CKR_ATTRIBUTE_SENSITIVE) + TC_TOKEN_ERR (CKR_ATTRIBUTE_TYPE_INVALID) + TC_TOKEN_ERR (CKR_ATTRIBUTE_VALUE_INVALID) + TC_TOKEN_ERR (CKR_DATA_INVALID) + TC_TOKEN_ERR (CKR_DATA_LEN_RANGE) + TC_TOKEN_ERR (CKR_DEVICE_ERROR) + TC_TOKEN_ERR (CKR_DEVICE_MEMORY) + TC_TOKEN_ERR (CKR_DEVICE_REMOVED) + TC_TOKEN_ERR (CKR_ENCRYPTED_DATA_INVALID) + TC_TOKEN_ERR (CKR_ENCRYPTED_DATA_LEN_RANGE) + TC_TOKEN_ERR (CKR_FUNCTION_CANCELED) + TC_TOKEN_ERR (CKR_FUNCTION_NOT_PARALLEL) + TC_TOKEN_ERR (CKR_FUNCTION_NOT_SUPPORTED) + TC_TOKEN_ERR (CKR_KEY_HANDLE_INVALID) + TC_TOKEN_ERR (CKR_KEY_SIZE_RANGE) + TC_TOKEN_ERR (CKR_KEY_TYPE_INCONSISTENT) + TC_TOKEN_ERR (CKR_KEY_NOT_NEEDED) + TC_TOKEN_ERR (CKR_KEY_CHANGED) + TC_TOKEN_ERR (CKR_KEY_NEEDED) + TC_TOKEN_ERR (CKR_KEY_INDIGESTIBLE) + TC_TOKEN_ERR (CKR_KEY_FUNCTION_NOT_PERMITTED) + TC_TOKEN_ERR (CKR_KEY_NOT_WRAPPABLE) + TC_TOKEN_ERR (CKR_KEY_UNEXTRACTABLE) + TC_TOKEN_ERR (CKR_MECHANISM_INVALID) + TC_TOKEN_ERR (CKR_MECHANISM_PARAM_INVALID) + TC_TOKEN_ERR (CKR_OBJECT_HANDLE_INVALID) + TC_TOKEN_ERR (CKR_OPERATION_ACTIVE) + TC_TOKEN_ERR (CKR_OPERATION_NOT_INITIALIZED) + TC_TOKEN_ERR (CKR_PIN_INCORRECT) + TC_TOKEN_ERR (CKR_PIN_INVALID) + TC_TOKEN_ERR (CKR_PIN_LEN_RANGE) + TC_TOKEN_ERR (CKR_PIN_EXPIRED) + TC_TOKEN_ERR (CKR_PIN_LOCKED) + TC_TOKEN_ERR (CKR_SESSION_CLOSED) + TC_TOKEN_ERR (CKR_SESSION_COUNT) + TC_TOKEN_ERR (CKR_SESSION_HANDLE_INVALID) + TC_TOKEN_ERR (CKR_SESSION_PARALLEL_NOT_SUPPORTED) + TC_TOKEN_ERR (CKR_SESSION_READ_ONLY) + TC_TOKEN_ERR (CKR_SESSION_EXISTS) + TC_TOKEN_ERR (CKR_SESSION_READ_ONLY_EXISTS) + TC_TOKEN_ERR (CKR_SESSION_READ_WRITE_SO_EXISTS) + TC_TOKEN_ERR (CKR_SIGNATURE_INVALID) + TC_TOKEN_ERR (CKR_SIGNATURE_LEN_RANGE) + TC_TOKEN_ERR (CKR_TEMPLATE_INCOMPLETE) + TC_TOKEN_ERR (CKR_TEMPLATE_INCONSISTENT) + TC_TOKEN_ERR (CKR_TOKEN_NOT_PRESENT) + TC_TOKEN_ERR (CKR_TOKEN_NOT_RECOGNIZED) + TC_TOKEN_ERR (CKR_TOKEN_WRITE_PROTECTED) + TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_HANDLE_INVALID) + TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_SIZE_RANGE) + TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT) + TC_TOKEN_ERR (CKR_USER_ALREADY_LOGGED_IN) + TC_TOKEN_ERR (CKR_USER_NOT_LOGGED_IN) + TC_TOKEN_ERR (CKR_USER_PIN_NOT_INITIALIZED) + TC_TOKEN_ERR (CKR_USER_TYPE_INVALID) + TC_TOKEN_ERR (CKR_USER_ANOTHER_ALREADY_LOGGED_IN) + TC_TOKEN_ERR (CKR_USER_TOO_MANY_TYPES) + TC_TOKEN_ERR (CKR_WRAPPED_KEY_INVALID) + TC_TOKEN_ERR (CKR_WRAPPED_KEY_LEN_RANGE) + TC_TOKEN_ERR (CKR_WRAPPING_KEY_HANDLE_INVALID) + TC_TOKEN_ERR (CKR_WRAPPING_KEY_SIZE_RANGE) + TC_TOKEN_ERR (CKR_WRAPPING_KEY_TYPE_INCONSISTENT) + TC_TOKEN_ERR (CKR_RANDOM_SEED_NOT_SUPPORTED) + TC_TOKEN_ERR (CKR_RANDOM_NO_RNG) + TC_TOKEN_ERR (CKR_DOMAIN_PARAMS_INVALID) + TC_TOKEN_ERR (CKR_BUFFER_TOO_SMALL) + TC_TOKEN_ERR (CKR_SAVED_STATE_INVALID) + TC_TOKEN_ERR (CKR_INFORMATION_SENSITIVE) + TC_TOKEN_ERR (CKR_STATE_UNSAVEABLE) + TC_TOKEN_ERR (CKR_CRYPTOKI_NOT_INITIALIZED) + TC_TOKEN_ERR (CKR_CRYPTOKI_ALREADY_INITIALIZED) + TC_TOKEN_ERR (CKR_MUTEX_BAD) + TC_TOKEN_ERR (CKR_MUTEX_NOT_LOCKED) + TC_TOKEN_ERR (CKR_NEW_PIN_MODE) + TC_TOKEN_ERR (CKR_NEXT_OTP) + TC_TOKEN_ERR (CKR_FUNCTION_REJECTED) + +#undef TC_TOKEN_ERR + }; + + + for (size_t i = 0; i < array_capacity (ErrorStrings); ++i) + { + if (ErrorStrings[i].ErrorCode == ErrorCode) + return ErrorStrings[i].ErrorString; + } + + stringstream s; + s << "0x" << hex << ErrorCode; + return s.str(); + + } + +#ifdef TC_HEADER_Common_Exception + void Pkcs11Exception::Show (HWND parent) const + { + string errorString = string (*this); + + if (!errorString.empty()) + { + wstringstream subjectErrorCode; + if (SubjectErrorCodeValid) + subjectErrorCode << L": " << SubjectErrorCode; + + if (!GetDictionaryValue (errorString.c_str())) + { + if (errorString.find ("CKR_") == 0) + { + errorString = errorString.substr (4); + for (size_t i = 0; i < errorString.size(); ++i) + { + if (errorString[i] == '_') + errorString[i] = ' '; + } + } + wchar_t err[8192]; + StringCbPrintfW (err, sizeof(err),L"%s:\n\n%hs%s", GetString ("SECURITY_TOKEN_ERROR"), errorString.c_str(), subjectErrorCode.str().c_str()); + ErrorDirect (err, parent); + } + else + { + wstring err = GetString (errorString.c_str()); + + if (SubjectErrorCodeValid) + err += L"\n\nError code" + subjectErrorCode.str(); + + ErrorDirect (err.c_str(), parent); + } + } + } +#endif // TC_HEADER_Common_Exception + + auto_ptr SecurityToken::PinCallback; + auto_ptr SecurityToken::WarningCallback; + + bool SecurityToken::Initialized; + CK_FUNCTION_LIST_PTR SecurityToken::Pkcs11Functions; + map SecurityToken::Sessions; + +#ifdef TC_WINDOWS + HMODULE SecurityToken::Pkcs11LibraryHandle; +#else + void *SecurityToken::Pkcs11LibraryHandle; +#endif + +#ifdef TC_HEADER_Platform_Exception + + void Pkcs11Exception::Deserialize (shared_ptr stream) + { + Exception::Deserialize (stream); + Serializer sr (stream); + uint64 code; + sr.Deserialize ("ErrorCode", code); + sr.Deserialize ("SubjectErrorCodeValid", SubjectErrorCodeValid); + sr.Deserialize ("SubjectErrorCode", SubjectErrorCode); + ErrorCode = (CK_RV) code; + } + + void Pkcs11Exception::Serialize (shared_ptr stream) const + { + Exception::Serialize (stream); + Serializer sr (stream); + sr.Serialize ("ErrorCode", (uint64) ErrorCode); + sr.Serialize ("SubjectErrorCodeValid", SubjectErrorCodeValid); + sr.Serialize ("SubjectErrorCode", SubjectErrorCode); + } + +# define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) +# undef TC_EXCEPTION_NODECL +# define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE) + + TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (SecurityTokenException); + +#endif +} -- cgit v1.2.3