Annotation of truecrypt/common/securitytoken.cpp, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.