"Fossies" - the Fresh Open Source Software Archive

Member "src/Common/SecurityToken.cpp" (10 Oct 2018, 21533 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "SecurityToken.cpp" see the Fossies "Dox" file reference documentation.

    1 /*
    2  Derived from source code of TrueCrypt 7.1a, which is
    3  Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
    4  by the TrueCrypt License 3.0.
    5 
    6  Modifications and additions to the original source code (contained in this file)
    7  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
    8  and are governed by the Apache License 2.0 the full text of which is
    9  contained in the file License.txt included in VeraCrypt binary and source
   10  code distribution packages.
   11 */
   12 
   13 #include "Platform/Finally.h"
   14 #include "Platform/ForEach.h"
   15 
   16 #if !defined (TC_WINDOWS) || defined (TC_PROTOTYPE)
   17 #   include "Platform/SerializerFactory.h"
   18 #   include "Platform/StringConverter.h"
   19 #   include "Platform/SystemException.h"
   20 #else
   21 #   include "Dictionary.h"
   22 #   include "Language.h"
   23 #endif
   24 
   25 #ifdef TC_UNIX
   26 #   include <dlfcn.h>
   27 #endif
   28 
   29 #include "SecurityToken.h"
   30 
   31 #ifndef burn
   32 #   define burn Memory::Erase
   33 #endif
   34 
   35 using namespace std;
   36 
   37 namespace VeraCrypt
   38 {
   39     SecurityTokenKeyfile::SecurityTokenKeyfile (const SecurityTokenKeyfilePath &path)
   40     {
   41         wstring pathStr = path;
   42         unsigned long slotId;
   43 
   44         if (swscanf (pathStr.c_str(), TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX TC_SECURITY_TOKEN_KEYFILE_URL_SLOT L"/%lu", &slotId) != 1)
   45             throw InvalidSecurityTokenKeyfilePath();
   46 
   47         SlotId = slotId;
   48 
   49         size_t keyIdPos = pathStr.find (L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/");
   50         if (keyIdPos == wstring::npos)
   51             throw InvalidSecurityTokenKeyfilePath();
   52 
   53         Id = pathStr.substr (keyIdPos + wstring (L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/").size());
   54 
   55         vector <SecurityTokenKeyfile> keyfiles = SecurityToken::GetAvailableKeyfiles (&SlotId, Id);
   56 
   57         if (keyfiles.empty())
   58             throw SecurityTokenKeyfileNotFound();
   59 
   60         *this = keyfiles.front();
   61     }
   62 
   63     SecurityTokenKeyfile::operator SecurityTokenKeyfilePath () const
   64     {
   65         wstringstream path;
   66         path << TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX TC_SECURITY_TOKEN_KEYFILE_URL_SLOT L"/" << SlotId << L"/" TC_SECURITY_TOKEN_KEYFILE_URL_FILE L"/" << Id;
   67         return path.str();
   68     }
   69 
   70     void SecurityToken::CheckLibraryStatus ()
   71     {
   72         if (!Initialized)
   73             throw SecurityTokenLibraryNotInitialized();
   74     }
   75 
   76     void SecurityToken::CloseLibrary ()
   77     {
   78         if (Initialized)
   79         {
   80             CloseAllSessions();
   81             Pkcs11Functions->C_Finalize (NULL_PTR);
   82 
   83 #ifdef TC_WINDOWS
   84             FreeLibrary (Pkcs11LibraryHandle);
   85 #else
   86             dlclose (Pkcs11LibraryHandle);
   87 #endif
   88             Initialized = false;
   89         }
   90     }
   91 
   92     void SecurityToken::CloseAllSessions () throw ()
   93     {
   94         if (!Initialized)
   95             return;
   96 
   97         typedef pair <CK_SLOT_ID, Pkcs11Session> SessionMapPair;
   98 
   99         foreach (SessionMapPair p, Sessions)
  100         {
  101             try
  102             {
  103                 CloseSession (p.first);
  104             }
  105             catch (...) { }
  106         }
  107     }
  108 
  109     void SecurityToken::CloseSession (CK_SLOT_ID slotId)
  110     {
  111         if (Sessions.find (slotId) == Sessions.end())
  112             throw ParameterIncorrect (SRC_POS);
  113 
  114         Pkcs11Functions->C_CloseSession (Sessions[slotId].Handle);
  115         Sessions.erase (Sessions.find (slotId));
  116     }
  117 
  118     void SecurityToken::CreateKeyfile (CK_SLOT_ID slotId, vector <byte> &keyfileData, const string &name)
  119     {
  120         if (name.empty())
  121             throw ParameterIncorrect (SRC_POS);
  122 
  123         LoginUserIfRequired (slotId);
  124 
  125         foreach (const SecurityTokenKeyfile &keyfile, GetAvailableKeyfiles (&slotId))
  126         {
  127             if (keyfile.IdUtf8 == name)
  128                 throw SecurityTokenKeyfileAlreadyExists();
  129         }
  130 
  131         CK_OBJECT_CLASS dataClass = CKO_DATA;
  132         CK_BBOOL trueVal = CK_TRUE;
  133 
  134         CK_ATTRIBUTE keyfileTemplate[] =
  135         {
  136             { CKA_CLASS, &dataClass, sizeof (dataClass) },
  137             { CKA_TOKEN, &trueVal, sizeof (trueVal) },
  138             { CKA_PRIVATE, &trueVal, sizeof (trueVal) },
  139             { CKA_LABEL, (CK_UTF8CHAR *) name.c_str(), (CK_ULONG) name.size() },
  140             { CKA_VALUE, &keyfileData.front(), (CK_ULONG) keyfileData.size() }
  141         };
  142 
  143         CK_OBJECT_HANDLE keyfileHandle;
  144 
  145         CK_RV status = Pkcs11Functions->C_CreateObject (Sessions[slotId].Handle, keyfileTemplate, array_capacity (keyfileTemplate), &keyfileHandle);
  146 
  147         switch (status)
  148         {
  149         case CKR_DATA_LEN_RANGE:
  150             status = CKR_DEVICE_MEMORY;
  151             break;
  152 
  153         case CKR_SESSION_READ_ONLY:
  154             status = CKR_TOKEN_WRITE_PROTECTED;
  155             break;
  156         }
  157 
  158         if (status != CKR_OK)
  159             throw Pkcs11Exception (status);
  160 
  161         // Some tokens report success even if the new object was truncated to fit in the available memory
  162         vector <byte> objectData;
  163 
  164         GetObjectAttribute (slotId, keyfileHandle, CKA_VALUE, objectData);
  165         finally_do_arg (vector <byte> *, &objectData, { if (!finally_arg->empty()) burn (&finally_arg->front(), finally_arg->size()); });
  166 
  167         if (objectData.size() != keyfileData.size())
  168         {
  169             Pkcs11Functions->C_DestroyObject (Sessions[slotId].Handle, keyfileHandle);
  170             throw Pkcs11Exception (CKR_DEVICE_MEMORY);
  171         }
  172     }
  173 
  174     void SecurityToken::DeleteKeyfile (const SecurityTokenKeyfile &keyfile)
  175     {
  176         LoginUserIfRequired (keyfile.SlotId);
  177 
  178         CK_RV status = Pkcs11Functions->C_DestroyObject (Sessions[keyfile.SlotId].Handle, keyfile.Handle);
  179         if (status != CKR_OK)
  180             throw Pkcs11Exception (status);
  181     }
  182 
  183     vector <SecurityTokenKeyfile> SecurityToken::GetAvailableKeyfiles (CK_SLOT_ID *slotIdFilter, const wstring keyfileIdFilter)
  184     {
  185         bool unrecognizedTokenPresent = false;
  186         vector <SecurityTokenKeyfile> keyfiles;
  187 
  188         foreach (const CK_SLOT_ID &slotId, GetTokenSlots())
  189         {
  190             SecurityTokenInfo token;
  191 
  192             if (slotIdFilter && *slotIdFilter != slotId)
  193                 continue;
  194 
  195             try
  196             {
  197                 LoginUserIfRequired (slotId);
  198                 token = GetTokenInfo (slotId);
  199             }
  200             catch (UserAbort &)
  201             {
  202                 continue;
  203             }
  204             catch (Pkcs11Exception &e)
  205             {
  206                 if (e.GetErrorCode() == CKR_TOKEN_NOT_RECOGNIZED)
  207                 {
  208                     unrecognizedTokenPresent = true;
  209                     continue;
  210                 }
  211 
  212                 throw;
  213             }
  214 
  215             foreach (const CK_OBJECT_HANDLE &dataHandle, GetObjects (slotId, CKO_DATA))
  216             {
  217                 SecurityTokenKeyfile keyfile;
  218                 keyfile.Handle = dataHandle;
  219                 keyfile.SlotId = slotId;
  220                 keyfile.Token = token;
  221 
  222                 vector <byte> privateAttrib;
  223                 GetObjectAttribute (slotId, dataHandle, CKA_PRIVATE, privateAttrib);
  224 
  225                 if (privateAttrib.size() == sizeof (CK_BBOOL) && *(CK_BBOOL *) &privateAttrib.front() != CK_TRUE)
  226                     continue;
  227 
  228                 vector <byte> label;
  229                 GetObjectAttribute (slotId, dataHandle, CKA_LABEL, label);
  230                 label.push_back (0);
  231 
  232                 keyfile.IdUtf8 = (char *) &label.front();
  233 
  234 #if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE)
  235                 keyfile.Id = Utf8StringToWide ((const char *) &label.front());
  236 #else
  237                 keyfile.Id = StringConverter::ToWide ((const char *) &label.front());
  238 #endif
  239                 if (keyfile.Id.empty() || (!keyfileIdFilter.empty() && keyfileIdFilter != keyfile.Id))
  240                     continue;
  241 
  242                 keyfiles.push_back (keyfile);
  243 
  244                 if (!keyfileIdFilter.empty())
  245                     break;
  246             }
  247         }
  248 
  249         if (keyfiles.empty() && unrecognizedTokenPresent)
  250             throw Pkcs11Exception (CKR_TOKEN_NOT_RECOGNIZED);
  251 
  252         return keyfiles;
  253     }
  254 
  255     list <SecurityTokenInfo> SecurityToken::GetAvailableTokens ()
  256     {
  257         bool unrecognizedTokenPresent = false;
  258         list <SecurityTokenInfo> tokens;
  259 
  260         foreach (const CK_SLOT_ID &slotId, GetTokenSlots())
  261         {
  262             try
  263             {
  264                 tokens.push_back (GetTokenInfo (slotId));
  265             }
  266             catch (Pkcs11Exception &e)
  267             {
  268                 if (e.GetErrorCode() == CKR_TOKEN_NOT_RECOGNIZED)
  269                 {
  270                     unrecognizedTokenPresent = true;
  271                     continue;
  272                 }
  273 
  274                 throw;
  275             }
  276         }
  277 
  278         if (tokens.empty() && unrecognizedTokenPresent)
  279             throw Pkcs11Exception (CKR_TOKEN_NOT_RECOGNIZED);
  280 
  281         return tokens;
  282     }
  283 
  284     SecurityTokenInfo SecurityToken::GetTokenInfo (CK_SLOT_ID slotId)
  285     {
  286         CK_TOKEN_INFO info;
  287         CK_RV status = Pkcs11Functions->C_GetTokenInfo (slotId, &info);
  288         if (status != CKR_OK)
  289             throw Pkcs11Exception (status);
  290 
  291         SecurityTokenInfo token;
  292         token.SlotId = slotId;
  293         token.Flags = info.flags;
  294 
  295         char label[sizeof (info.label) + 1];
  296         memset (label, 0, sizeof (label));
  297         memcpy (label, info.label, sizeof (info.label));
  298 
  299         token.LabelUtf8 = label;
  300 
  301         size_t lastSpace = token.LabelUtf8.find_last_not_of (' ');
  302         if (lastSpace == string::npos)
  303             token.LabelUtf8.clear();
  304         else
  305             token.LabelUtf8 = token.LabelUtf8.substr (0, lastSpace + 1);
  306 
  307 #if defined (TC_WINDOWS) && !defined (TC_PROTOTYPE)
  308         token.Label = Utf8StringToWide (token.LabelUtf8);
  309 #else
  310         token.Label = StringConverter::ToWide (token.LabelUtf8);
  311 #endif
  312         return token;
  313     }
  314 
  315     void SecurityToken::GetKeyfileData (const SecurityTokenKeyfile &keyfile, vector <byte> &keyfileData)
  316     {
  317         LoginUserIfRequired (keyfile.SlotId);
  318         GetObjectAttribute (keyfile.SlotId, keyfile.Handle, CKA_VALUE, keyfileData);
  319     }
  320 
  321     vector <CK_OBJECT_HANDLE> SecurityToken::GetObjects (CK_SLOT_ID slotId, CK_ATTRIBUTE_TYPE objectClass)
  322     {
  323         if (Sessions.find (slotId) == Sessions.end())
  324             throw ParameterIncorrect (SRC_POS);
  325 
  326         CK_ATTRIBUTE findTemplate;
  327         findTemplate.type = CKA_CLASS;
  328         findTemplate.pValue = &objectClass;
  329         findTemplate.ulValueLen = sizeof (objectClass);
  330 
  331         CK_RV status = Pkcs11Functions->C_FindObjectsInit (Sessions[slotId].Handle, &findTemplate, 1);
  332         if (status != CKR_OK)
  333             throw Pkcs11Exception (status);
  334 
  335         finally_do_arg (CK_SLOT_ID, slotId, { Pkcs11Functions->C_FindObjectsFinal (Sessions[finally_arg].Handle); });
  336 
  337         CK_ULONG objectCount;
  338         vector <CK_OBJECT_HANDLE> objects;
  339 
  340         while (true)
  341         {
  342             CK_OBJECT_HANDLE object;
  343             CK_RV status = Pkcs11Functions->C_FindObjects (Sessions[slotId].Handle, &object, 1, &objectCount);
  344             if (status != CKR_OK)
  345                 throw Pkcs11Exception (status);
  346 
  347             if (objectCount != 1)
  348                 break;
  349 
  350             objects.push_back (object);
  351         }
  352 
  353         return objects;
  354     }
  355 
  356     void SecurityToken::GetObjectAttribute (CK_SLOT_ID slotId, CK_OBJECT_HANDLE tokenObject, CK_ATTRIBUTE_TYPE attributeType, vector <byte> &attributeValue)
  357     {
  358         attributeValue.clear();
  359 
  360         if (Sessions.find (slotId) == Sessions.end())
  361             throw ParameterIncorrect (SRC_POS);
  362 
  363         CK_ATTRIBUTE attribute;
  364         attribute.type = attributeType;
  365         attribute.pValue = NULL_PTR;
  366 
  367         CK_RV status = Pkcs11Functions->C_GetAttributeValue (Sessions[slotId].Handle, tokenObject, &attribute, 1);
  368         if (status != CKR_OK)
  369             throw Pkcs11Exception (status);
  370 
  371         if (attribute.ulValueLen == 0)
  372             return;
  373 
  374         attributeValue = vector <byte> (attribute.ulValueLen);
  375         attribute.pValue = &attributeValue.front();
  376 
  377         status = Pkcs11Functions->C_GetAttributeValue (Sessions[slotId].Handle, tokenObject, &attribute, 1);
  378         if (status != CKR_OK)
  379             throw Pkcs11Exception (status);
  380     }
  381 
  382     list <CK_SLOT_ID> SecurityToken::GetTokenSlots ()
  383     {
  384         CheckLibraryStatus();
  385 
  386         list <CK_SLOT_ID> slots;
  387         CK_ULONG slotCount;
  388 
  389         CK_RV status = Pkcs11Functions->C_GetSlotList (TRUE, NULL_PTR, &slotCount);
  390         if (status != CKR_OK)
  391             throw Pkcs11Exception (status);
  392 
  393         if (slotCount > 0)
  394         {
  395             vector <CK_SLOT_ID> slotArray (slotCount);
  396             status = Pkcs11Functions->C_GetSlotList (TRUE, &slotArray.front(), &slotCount);
  397             if (status != CKR_OK)
  398                 throw Pkcs11Exception (status);
  399 
  400             for (size_t i = 0; i < slotCount; i++)
  401             {
  402                 CK_SLOT_INFO slotInfo;
  403                 status = Pkcs11Functions->C_GetSlotInfo (slotArray[i], &slotInfo);
  404 
  405                 if (status != CKR_OK || !(slotInfo.flags & CKF_TOKEN_PRESENT))
  406                     continue;
  407 
  408                 slots.push_back (slotArray[i]);
  409             }
  410         }
  411 
  412         return slots;
  413     }
  414 
  415     bool SecurityToken::IsKeyfilePathValid (const wstring &securityTokenKeyfilePath)
  416     {
  417         return securityTokenKeyfilePath.find (TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX) == 0;
  418     }
  419 
  420     void SecurityToken::Login (CK_SLOT_ID slotId, const char* pin)
  421     {
  422         if (Sessions.find (slotId) == Sessions.end())
  423             OpenSession (slotId);
  424         else if (Sessions[slotId].UserLoggedIn)
  425             return;
  426 
  427         size_t pinLen = pin? strlen (pin) : 0;
  428         CK_RV status = Pkcs11Functions->C_Login (Sessions[slotId].Handle, CKU_USER, (CK_CHAR_PTR) pin, (CK_ULONG) pinLen);
  429 
  430         if (status != CKR_OK)
  431             throw Pkcs11Exception (status);
  432 
  433         Sessions[slotId].UserLoggedIn = true;
  434     }
  435 
  436     void SecurityToken::LoginUserIfRequired (CK_SLOT_ID slotId)
  437     {
  438         CheckLibraryStatus();
  439         CK_RV status;
  440 
  441         if (Sessions.find (slotId) == Sessions.end())
  442         {
  443             OpenSession (slotId);
  444         }
  445         else
  446         {
  447             CK_SESSION_INFO sessionInfo;
  448             status = Pkcs11Functions->C_GetSessionInfo (Sessions[slotId].Handle, &sessionInfo);
  449 
  450             if (status == CKR_OK)
  451             {
  452                 Sessions[slotId].UserLoggedIn = (sessionInfo.state == CKS_RO_USER_FUNCTIONS || sessionInfo.state == CKS_RW_USER_FUNCTIONS);
  453             }
  454             else
  455             {
  456                 try
  457                 {
  458                     CloseSession (slotId);
  459                 }
  460                 catch (...) { }
  461                 OpenSession (slotId);
  462             }
  463         }
  464 
  465         SecurityTokenInfo tokenInfo = GetTokenInfo (slotId);
  466 
  467         while (!Sessions[slotId].UserLoggedIn && (tokenInfo.Flags & CKF_LOGIN_REQUIRED))
  468         {
  469             try
  470             {
  471                 if (tokenInfo.Flags & CKF_PROTECTED_AUTHENTICATION_PATH)
  472                 {
  473                     status = Pkcs11Functions->C_Login (Sessions[slotId].Handle, CKU_USER, NULL_PTR, 0);
  474                     if (status != CKR_OK)
  475                         throw Pkcs11Exception (status);
  476                 }
  477                 else
  478                 {
  479                     string pin = tokenInfo.LabelUtf8;
  480                     if (tokenInfo.Label.empty())
  481                     {
  482                         stringstream s;
  483                         s << "#" << slotId;
  484                         pin = s.str();
  485                     }
  486 
  487                     finally_do_arg (string*, &pin, { burn ((void *) finally_arg->c_str(), finally_arg->size()); });
  488 
  489                     (*PinCallback) (pin);
  490                     Login (slotId, pin.c_str());
  491                 }
  492 
  493                 Sessions[slotId].UserLoggedIn = true;
  494             }
  495             catch (Pkcs11Exception &e)
  496             {
  497                 CK_RV error = e.GetErrorCode();
  498 
  499                 if (error == CKR_USER_ALREADY_LOGGED_IN)
  500                 {
  501                     break;
  502                 }
  503                 else if (error == CKR_PIN_INCORRECT && !(tokenInfo.Flags & CKF_PROTECTED_AUTHENTICATION_PATH))
  504                 {
  505                     PinCallback->notifyIncorrectPin ();
  506                     (*WarningCallback) (Pkcs11Exception (CKR_PIN_INCORRECT));
  507                     continue;
  508                 }
  509 
  510                 throw;
  511             }
  512         }
  513     }
  514 
  515 #ifdef TC_WINDOWS
  516     void SecurityToken::InitLibrary (const wstring &pkcs11LibraryPath, auto_ptr <GetPinFunctor> pinCallback, auto_ptr <SendExceptionFunctor> warningCallback)
  517 #else
  518     void SecurityToken::InitLibrary (const string &pkcs11LibraryPath, auto_ptr <GetPinFunctor> pinCallback, auto_ptr <SendExceptionFunctor> warningCallback)
  519 #endif
  520     {
  521         if (Initialized)
  522             CloseLibrary();
  523 
  524 #ifdef TC_WINDOWS
  525         Pkcs11LibraryHandle = LoadLibraryW (pkcs11LibraryPath.c_str());
  526         throw_sys_if (!Pkcs11LibraryHandle);
  527 #else
  528         Pkcs11LibraryHandle = dlopen (pkcs11LibraryPath.c_str(), RTLD_NOW | RTLD_LOCAL);
  529         throw_sys_sub_if (!Pkcs11LibraryHandle, dlerror());
  530 #endif
  531 
  532 
  533         typedef CK_RV (*C_GetFunctionList_t) (CK_FUNCTION_LIST_PTR_PTR ppFunctionList);
  534 #ifdef TC_WINDOWS
  535         C_GetFunctionList_t C_GetFunctionList = (C_GetFunctionList_t) GetProcAddress (Pkcs11LibraryHandle, "C_GetFunctionList");
  536 #else
  537         C_GetFunctionList_t C_GetFunctionList = (C_GetFunctionList_t) dlsym (Pkcs11LibraryHandle, "C_GetFunctionList");
  538 #endif
  539 
  540         if (!C_GetFunctionList)
  541             throw SecurityTokenLibraryNotInitialized();
  542 
  543         CK_RV status = C_GetFunctionList (&Pkcs11Functions);
  544         if (status != CKR_OK)
  545             throw Pkcs11Exception (status);
  546 
  547         status = Pkcs11Functions->C_Initialize (NULL_PTR);
  548         if (status != CKR_OK)
  549             throw Pkcs11Exception (status);
  550 
  551         PinCallback = pinCallback;
  552         WarningCallback = warningCallback;
  553 
  554         Initialized = true;
  555     }
  556 
  557     void SecurityToken::OpenSession (CK_SLOT_ID slotId)
  558     {
  559         if (Sessions.find (slotId) != Sessions.end())
  560             return;
  561 
  562         CK_SESSION_HANDLE session;
  563 
  564         CK_FLAGS flags = CKF_SERIAL_SESSION;
  565 
  566         if (!(GetTokenInfo (slotId).Flags & CKF_WRITE_PROTECTED))
  567              flags |= CKF_RW_SESSION;
  568 
  569         CK_RV status = Pkcs11Functions->C_OpenSession (slotId, flags, NULL_PTR, NULL_PTR, &session);
  570         if (status != CKR_OK)
  571             throw Pkcs11Exception (status);
  572 
  573         Sessions[slotId].Handle = session;
  574     }
  575 
  576     Pkcs11Exception::operator string () const
  577     {
  578         if (ErrorCode == CKR_OK)
  579             return string();
  580 
  581         static const struct
  582         {
  583             CK_RV ErrorCode;
  584             const char *ErrorString;
  585         } ErrorStrings[] =
  586         {
  587 #           define TC_TOKEN_ERR(CODE) { CODE, #CODE },
  588 
  589             TC_TOKEN_ERR (CKR_CANCEL)
  590             TC_TOKEN_ERR (CKR_HOST_MEMORY)
  591             TC_TOKEN_ERR (CKR_SLOT_ID_INVALID)
  592             TC_TOKEN_ERR (CKR_GENERAL_ERROR)
  593             TC_TOKEN_ERR (CKR_FUNCTION_FAILED)
  594             TC_TOKEN_ERR (CKR_ARGUMENTS_BAD)
  595             TC_TOKEN_ERR (CKR_NO_EVENT)
  596             TC_TOKEN_ERR (CKR_NEED_TO_CREATE_THREADS)
  597             TC_TOKEN_ERR (CKR_CANT_LOCK)
  598             TC_TOKEN_ERR (CKR_ATTRIBUTE_READ_ONLY)
  599             TC_TOKEN_ERR (CKR_ATTRIBUTE_SENSITIVE)
  600             TC_TOKEN_ERR (CKR_ATTRIBUTE_TYPE_INVALID)
  601             TC_TOKEN_ERR (CKR_ATTRIBUTE_VALUE_INVALID)
  602             TC_TOKEN_ERR (CKR_DATA_INVALID)
  603             TC_TOKEN_ERR (CKR_DATA_LEN_RANGE)
  604             TC_TOKEN_ERR (CKR_DEVICE_ERROR)
  605             TC_TOKEN_ERR (CKR_DEVICE_MEMORY)
  606             TC_TOKEN_ERR (CKR_DEVICE_REMOVED)
  607             TC_TOKEN_ERR (CKR_ENCRYPTED_DATA_INVALID)
  608             TC_TOKEN_ERR (CKR_ENCRYPTED_DATA_LEN_RANGE)
  609             TC_TOKEN_ERR (CKR_FUNCTION_CANCELED)
  610             TC_TOKEN_ERR (CKR_FUNCTION_NOT_PARALLEL)
  611             TC_TOKEN_ERR (CKR_FUNCTION_NOT_SUPPORTED)
  612             TC_TOKEN_ERR (CKR_KEY_HANDLE_INVALID)
  613             TC_TOKEN_ERR (CKR_KEY_SIZE_RANGE)
  614             TC_TOKEN_ERR (CKR_KEY_TYPE_INCONSISTENT)
  615             TC_TOKEN_ERR (CKR_KEY_NOT_NEEDED)
  616             TC_TOKEN_ERR (CKR_KEY_CHANGED)
  617             TC_TOKEN_ERR (CKR_KEY_NEEDED)
  618             TC_TOKEN_ERR (CKR_KEY_INDIGESTIBLE)
  619             TC_TOKEN_ERR (CKR_KEY_FUNCTION_NOT_PERMITTED)
  620             TC_TOKEN_ERR (CKR_KEY_NOT_WRAPPABLE)
  621             TC_TOKEN_ERR (CKR_KEY_UNEXTRACTABLE)
  622             TC_TOKEN_ERR (CKR_MECHANISM_INVALID)
  623             TC_TOKEN_ERR (CKR_MECHANISM_PARAM_INVALID)
  624             TC_TOKEN_ERR (CKR_OBJECT_HANDLE_INVALID)
  625             TC_TOKEN_ERR (CKR_OPERATION_ACTIVE)
  626             TC_TOKEN_ERR (CKR_OPERATION_NOT_INITIALIZED)
  627             TC_TOKEN_ERR (CKR_PIN_INCORRECT)
  628             TC_TOKEN_ERR (CKR_PIN_INVALID)
  629             TC_TOKEN_ERR (CKR_PIN_LEN_RANGE)
  630             TC_TOKEN_ERR (CKR_PIN_EXPIRED)
  631             TC_TOKEN_ERR (CKR_PIN_LOCKED)
  632             TC_TOKEN_ERR (CKR_SESSION_CLOSED)
  633             TC_TOKEN_ERR (CKR_SESSION_COUNT)
  634             TC_TOKEN_ERR (CKR_SESSION_HANDLE_INVALID)
  635             TC_TOKEN_ERR (CKR_SESSION_PARALLEL_NOT_SUPPORTED)
  636             TC_TOKEN_ERR (CKR_SESSION_READ_ONLY)
  637             TC_TOKEN_ERR (CKR_SESSION_EXISTS)
  638             TC_TOKEN_ERR (CKR_SESSION_READ_ONLY_EXISTS)
  639             TC_TOKEN_ERR (CKR_SESSION_READ_WRITE_SO_EXISTS)
  640             TC_TOKEN_ERR (CKR_SIGNATURE_INVALID)
  641             TC_TOKEN_ERR (CKR_SIGNATURE_LEN_RANGE)
  642             TC_TOKEN_ERR (CKR_TEMPLATE_INCOMPLETE)
  643             TC_TOKEN_ERR (CKR_TEMPLATE_INCONSISTENT)
  644             TC_TOKEN_ERR (CKR_TOKEN_NOT_PRESENT)
  645             TC_TOKEN_ERR (CKR_TOKEN_NOT_RECOGNIZED)
  646             TC_TOKEN_ERR (CKR_TOKEN_WRITE_PROTECTED)
  647             TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_HANDLE_INVALID)
  648             TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_SIZE_RANGE)
  649             TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT)
  650             TC_TOKEN_ERR (CKR_USER_ALREADY_LOGGED_IN)
  651             TC_TOKEN_ERR (CKR_USER_NOT_LOGGED_IN)
  652             TC_TOKEN_ERR (CKR_USER_PIN_NOT_INITIALIZED)
  653             TC_TOKEN_ERR (CKR_USER_TYPE_INVALID)
  654             TC_TOKEN_ERR (CKR_USER_ANOTHER_ALREADY_LOGGED_IN)
  655             TC_TOKEN_ERR (CKR_USER_TOO_MANY_TYPES)
  656             TC_TOKEN_ERR (CKR_WRAPPED_KEY_INVALID)
  657             TC_TOKEN_ERR (CKR_WRAPPED_KEY_LEN_RANGE)
  658             TC_TOKEN_ERR (CKR_WRAPPING_KEY_HANDLE_INVALID)
  659             TC_TOKEN_ERR (CKR_WRAPPING_KEY_SIZE_RANGE)
  660             TC_TOKEN_ERR (CKR_WRAPPING_KEY_TYPE_INCONSISTENT)
  661             TC_TOKEN_ERR (CKR_RANDOM_SEED_NOT_SUPPORTED)
  662             TC_TOKEN_ERR (CKR_RANDOM_NO_RNG)
  663             TC_TOKEN_ERR (CKR_DOMAIN_PARAMS_INVALID)
  664             TC_TOKEN_ERR (CKR_BUFFER_TOO_SMALL)
  665             TC_TOKEN_ERR (CKR_SAVED_STATE_INVALID)
  666             TC_TOKEN_ERR (CKR_INFORMATION_SENSITIVE)
  667             TC_TOKEN_ERR (CKR_STATE_UNSAVEABLE)
  668             TC_TOKEN_ERR (CKR_CRYPTOKI_NOT_INITIALIZED)
  669             TC_TOKEN_ERR (CKR_CRYPTOKI_ALREADY_INITIALIZED)
  670             TC_TOKEN_ERR (CKR_MUTEX_BAD)
  671             TC_TOKEN_ERR (CKR_MUTEX_NOT_LOCKED)
  672             TC_TOKEN_ERR (CKR_NEW_PIN_MODE)
  673             TC_TOKEN_ERR (CKR_NEXT_OTP)
  674             TC_TOKEN_ERR (CKR_FUNCTION_REJECTED)
  675 
  676 #undef      TC_TOKEN_ERR
  677         };
  678 
  679 
  680         for (size_t i = 0; i < array_capacity (ErrorStrings); ++i)
  681         {
  682             if (ErrorStrings[i].ErrorCode == ErrorCode)
  683                 return ErrorStrings[i].ErrorString;
  684         }
  685 
  686         stringstream s;
  687         s << "0x" << hex << ErrorCode;
  688         return s.str();
  689 
  690     }
  691 
  692 #ifdef TC_HEADER_Common_Exception
  693     void Pkcs11Exception::Show (HWND parent) const
  694     {
  695         string errorString = string (*this);
  696 
  697         if (!errorString.empty())
  698         {
  699             wstringstream subjectErrorCode;
  700             if (SubjectErrorCodeValid)
  701                 subjectErrorCode << L": " << SubjectErrorCode;
  702 
  703             if (!GetDictionaryValue (errorString.c_str()))
  704             {
  705                 if (errorString.find ("CKR_") == 0)
  706                 {
  707                     errorString = errorString.substr (4);
  708                     for (size_t i = 0; i < errorString.size(); ++i)
  709                     {
  710                         if (errorString[i] == '_')
  711                             errorString[i] = ' ';
  712                     }
  713                 }
  714                 wchar_t err[8192];
  715                 StringCbPrintfW (err, sizeof(err),L"%s:\n\n%hs%s", GetString ("SECURITY_TOKEN_ERROR"), errorString.c_str(), subjectErrorCode.str().c_str());
  716                 ErrorDirect (err, parent);
  717             }
  718             else
  719             {
  720                 wstring err = GetString (errorString.c_str());
  721 
  722                 if (SubjectErrorCodeValid)
  723                     err += L"\n\nError code" + subjectErrorCode.str();
  724 
  725                 ErrorDirect (err.c_str(), parent);
  726             }
  727         }
  728     }
  729 #endif // TC_HEADER_Common_Exception
  730 
  731     auto_ptr <GetPinFunctor> SecurityToken::PinCallback;
  732     auto_ptr <SendExceptionFunctor> SecurityToken::WarningCallback;
  733 
  734     bool SecurityToken::Initialized;
  735     CK_FUNCTION_LIST_PTR SecurityToken::Pkcs11Functions;
  736     map <CK_SLOT_ID, Pkcs11Session> SecurityToken::Sessions;
  737 
  738 #ifdef TC_WINDOWS
  739     HMODULE SecurityToken::Pkcs11LibraryHandle;
  740 #else
  741     void *SecurityToken::Pkcs11LibraryHandle;
  742 #endif
  743 
  744 #ifdef TC_HEADER_Platform_Exception
  745 
  746     void Pkcs11Exception::Deserialize (shared_ptr <Stream> stream)
  747     {
  748         Exception::Deserialize (stream);
  749         Serializer sr (stream);
  750         uint64 code;
  751         sr.Deserialize ("ErrorCode", code);
  752         sr.Deserialize ("SubjectErrorCodeValid", SubjectErrorCodeValid);
  753         sr.Deserialize ("SubjectErrorCode", SubjectErrorCode);
  754         ErrorCode = (CK_RV) code;
  755     }
  756 
  757     void Pkcs11Exception::Serialize (shared_ptr <Stream> stream) const
  758     {
  759         Exception::Serialize (stream);
  760         Serializer sr (stream);
  761         sr.Serialize ("ErrorCode", (uint64) ErrorCode);
  762         sr.Serialize ("SubjectErrorCodeValid", SubjectErrorCodeValid);
  763         sr.Serialize ("SubjectErrorCode", SubjectErrorCode);
  764     }
  765 
  766 #   define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
  767 #   undef TC_EXCEPTION_NODECL
  768 #   define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
  769 
  770     TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (SecurityTokenException);
  771 
  772 #endif
  773 }