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

1.1       root        1: /*
1.1.1.6 ! root        2:  Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
1.1       root        3: 
1.1.1.6 ! root        4:  Governed by the TrueCrypt License 3.0 the full text of which is contained in
1.1.1.5   root        5:  the file License.txt included in TrueCrypt binary and source code distribution
                      6:  packages.
1.1       root        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);
1.1.1.6 ! root      161:                finally_do_arg (vector <byte> *, &objectData, { if (!finally_arg->empty()) burn (&finally_arg->front(), finally_arg->size()); });
1.1       root      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:        {
1.1.1.2   root      566:                if (ErrorCode == CKR_OK)
                    567:                        return string();
                    568: 
                    569:                static const struct
1.1       root      570:                {
1.1.1.4   root      571:                        CK_RV ErrorCode;
1.1.1.2   root      572:                        const char *ErrorString;
                    573:                } ErrorStrings[] =
                    574:                {
                    575: #                      define TC_TOKEN_ERR(CODE) { CODE, #CODE },
                    576: 
                    577:                        TC_TOKEN_ERR (CKR_CANCEL)
                    578:                        TC_TOKEN_ERR (CKR_HOST_MEMORY)
                    579:                        TC_TOKEN_ERR (CKR_SLOT_ID_INVALID)
                    580:                        TC_TOKEN_ERR (CKR_GENERAL_ERROR)
                    581:                        TC_TOKEN_ERR (CKR_FUNCTION_FAILED)
                    582:                        TC_TOKEN_ERR (CKR_ARGUMENTS_BAD)
                    583:                        TC_TOKEN_ERR (CKR_NO_EVENT)
                    584:                        TC_TOKEN_ERR (CKR_NEED_TO_CREATE_THREADS)
                    585:                        TC_TOKEN_ERR (CKR_CANT_LOCK)
                    586:                        TC_TOKEN_ERR (CKR_ATTRIBUTE_READ_ONLY)
                    587:                        TC_TOKEN_ERR (CKR_ATTRIBUTE_SENSITIVE)
                    588:                        TC_TOKEN_ERR (CKR_ATTRIBUTE_TYPE_INVALID)
                    589:                        TC_TOKEN_ERR (CKR_ATTRIBUTE_VALUE_INVALID)
                    590:                        TC_TOKEN_ERR (CKR_DATA_INVALID)
                    591:                        TC_TOKEN_ERR (CKR_DATA_LEN_RANGE)
                    592:                        TC_TOKEN_ERR (CKR_DEVICE_ERROR)
                    593:                        TC_TOKEN_ERR (CKR_DEVICE_MEMORY)
                    594:                        TC_TOKEN_ERR (CKR_DEVICE_REMOVED)
                    595:                        TC_TOKEN_ERR (CKR_ENCRYPTED_DATA_INVALID)
                    596:                        TC_TOKEN_ERR (CKR_ENCRYPTED_DATA_LEN_RANGE)
                    597:                        TC_TOKEN_ERR (CKR_FUNCTION_CANCELED)
                    598:                        TC_TOKEN_ERR (CKR_FUNCTION_NOT_PARALLEL)
                    599:                        TC_TOKEN_ERR (CKR_FUNCTION_NOT_SUPPORTED)
                    600:                        TC_TOKEN_ERR (CKR_KEY_HANDLE_INVALID)
                    601:                        TC_TOKEN_ERR (CKR_KEY_SIZE_RANGE)
                    602:                        TC_TOKEN_ERR (CKR_KEY_TYPE_INCONSISTENT)
                    603:                        TC_TOKEN_ERR (CKR_KEY_NOT_NEEDED)
                    604:                        TC_TOKEN_ERR (CKR_KEY_CHANGED)
                    605:                        TC_TOKEN_ERR (CKR_KEY_NEEDED)
                    606:                        TC_TOKEN_ERR (CKR_KEY_INDIGESTIBLE)
                    607:                        TC_TOKEN_ERR (CKR_KEY_FUNCTION_NOT_PERMITTED)
                    608:                        TC_TOKEN_ERR (CKR_KEY_NOT_WRAPPABLE)
                    609:                        TC_TOKEN_ERR (CKR_KEY_UNEXTRACTABLE)
                    610:                        TC_TOKEN_ERR (CKR_MECHANISM_INVALID)
                    611:                        TC_TOKEN_ERR (CKR_MECHANISM_PARAM_INVALID)
                    612:                        TC_TOKEN_ERR (CKR_OBJECT_HANDLE_INVALID)
                    613:                        TC_TOKEN_ERR (CKR_OPERATION_ACTIVE)
                    614:                        TC_TOKEN_ERR (CKR_OPERATION_NOT_INITIALIZED)
                    615:                        TC_TOKEN_ERR (CKR_PIN_INCORRECT)
                    616:                        TC_TOKEN_ERR (CKR_PIN_INVALID)
                    617:                        TC_TOKEN_ERR (CKR_PIN_LEN_RANGE)
                    618:                        TC_TOKEN_ERR (CKR_PIN_EXPIRED)
                    619:                        TC_TOKEN_ERR (CKR_PIN_LOCKED)
                    620:                        TC_TOKEN_ERR (CKR_SESSION_CLOSED)
                    621:                        TC_TOKEN_ERR (CKR_SESSION_COUNT)
                    622:                        TC_TOKEN_ERR (CKR_SESSION_HANDLE_INVALID)
                    623:                        TC_TOKEN_ERR (CKR_SESSION_PARALLEL_NOT_SUPPORTED)
                    624:                        TC_TOKEN_ERR (CKR_SESSION_READ_ONLY)
                    625:                        TC_TOKEN_ERR (CKR_SESSION_EXISTS)
                    626:                        TC_TOKEN_ERR (CKR_SESSION_READ_ONLY_EXISTS)
                    627:                        TC_TOKEN_ERR (CKR_SESSION_READ_WRITE_SO_EXISTS)
                    628:                        TC_TOKEN_ERR (CKR_SIGNATURE_INVALID)
                    629:                        TC_TOKEN_ERR (CKR_SIGNATURE_LEN_RANGE)
                    630:                        TC_TOKEN_ERR (CKR_TEMPLATE_INCOMPLETE)
                    631:                        TC_TOKEN_ERR (CKR_TEMPLATE_INCONSISTENT)
                    632:                        TC_TOKEN_ERR (CKR_TOKEN_NOT_PRESENT)
                    633:                        TC_TOKEN_ERR (CKR_TOKEN_NOT_RECOGNIZED)
                    634:                        TC_TOKEN_ERR (CKR_TOKEN_WRITE_PROTECTED)
                    635:                        TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_HANDLE_INVALID)
                    636:                        TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_SIZE_RANGE)
                    637:                        TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT)
                    638:                        TC_TOKEN_ERR (CKR_USER_ALREADY_LOGGED_IN)
                    639:                        TC_TOKEN_ERR (CKR_USER_NOT_LOGGED_IN)
                    640:                        TC_TOKEN_ERR (CKR_USER_PIN_NOT_INITIALIZED)
                    641:                        TC_TOKEN_ERR (CKR_USER_TYPE_INVALID)
                    642:                        TC_TOKEN_ERR (CKR_USER_ANOTHER_ALREADY_LOGGED_IN)
                    643:                        TC_TOKEN_ERR (CKR_USER_TOO_MANY_TYPES)
                    644:                        TC_TOKEN_ERR (CKR_WRAPPED_KEY_INVALID)
                    645:                        TC_TOKEN_ERR (CKR_WRAPPED_KEY_LEN_RANGE)
                    646:                        TC_TOKEN_ERR (CKR_WRAPPING_KEY_HANDLE_INVALID)
                    647:                        TC_TOKEN_ERR (CKR_WRAPPING_KEY_SIZE_RANGE)
                    648:                        TC_TOKEN_ERR (CKR_WRAPPING_KEY_TYPE_INCONSISTENT)
                    649:                        TC_TOKEN_ERR (CKR_RANDOM_SEED_NOT_SUPPORTED)
                    650:                        TC_TOKEN_ERR (CKR_RANDOM_NO_RNG)
                    651:                        TC_TOKEN_ERR (CKR_DOMAIN_PARAMS_INVALID)
                    652:                        TC_TOKEN_ERR (CKR_BUFFER_TOO_SMALL)
                    653:                        TC_TOKEN_ERR (CKR_SAVED_STATE_INVALID)
                    654:                        TC_TOKEN_ERR (CKR_INFORMATION_SENSITIVE)
                    655:                        TC_TOKEN_ERR (CKR_STATE_UNSAVEABLE)
                    656:                        TC_TOKEN_ERR (CKR_CRYPTOKI_NOT_INITIALIZED)
                    657:                        TC_TOKEN_ERR (CKR_CRYPTOKI_ALREADY_INITIALIZED)
                    658:                        TC_TOKEN_ERR (CKR_MUTEX_BAD)
                    659:                        TC_TOKEN_ERR (CKR_MUTEX_NOT_LOCKED)
                    660:                        TC_TOKEN_ERR (CKR_NEW_PIN_MODE)
                    661:                        TC_TOKEN_ERR (CKR_NEXT_OTP)
                    662:                        TC_TOKEN_ERR (CKR_FUNCTION_REJECTED)
1.1       root      663: 
1.1.1.2   root      664: #undef         TC_TOKEN_ERR
1.1       root      665:                };
                    666: 
1.1.1.2   root      667: 
                    668:                for (size_t i = 0; i < array_capacity (ErrorStrings); ++i)
                    669:                {
                    670:                        if (ErrorStrings[i].ErrorCode == ErrorCode)
                    671:                                return ErrorStrings[i].ErrorString;
                    672:                }
                    673: 
                    674:                stringstream s;
                    675:                s << "0x" << hex << ErrorCode;
                    676:                return s.str();
                    677: 
1.1       root      678:        }
                    679: 
                    680: #ifdef TC_HEADER_Common_Exception
                    681:        void Pkcs11Exception::Show (HWND parent) const
                    682:        {
                    683:                string errorString = string (*this);
                    684: 
                    685:                if (!errorString.empty())
                    686:                {
                    687:                        wstringstream subjectErrorCode;
                    688:                        if (SubjectErrorCodeValid)
                    689:                                subjectErrorCode << L": " << SubjectErrorCode;
                    690: 
                    691:                        if (!GetDictionaryValue (errorString.c_str()))
                    692:                        {
                    693:                                if (errorString.find ("CKR_") == 0)
                    694:                                {
                    695:                                        errorString = errorString.substr (4);
                    696:                                        for (size_t i = 0; i < errorString.size(); ++i)
                    697:                                        {
                    698:                                                if (errorString[i] == '_')
                    699:                                                        errorString[i] = ' ';
                    700:                                        }
                    701:                                }
                    702:                                wchar_t err[8192];
                    703:                                wsprintfW (err, L"%s:\n\n%hs%s", GetString ("SECURITY_TOKEN_ERROR"), errorString.c_str(), subjectErrorCode.str().c_str());
                    704:                                ErrorDirect (err);
                    705:                        }
                    706:                        else
                    707:                        {
                    708:                                wstring err = GetString (errorString.c_str());
                    709: 
                    710:                                if (SubjectErrorCodeValid)
                    711:                                        err += L"\n\nError code" + subjectErrorCode.str();
                    712: 
                    713:                                ErrorDirect (err.c_str());
                    714:                        }
                    715:                }
                    716:        }
                    717: #endif // TC_HEADER_Common_Exception
                    718: 
                    719:        auto_ptr <GetPinFunctor> SecurityToken::PinCallback;
                    720:        auto_ptr <SendExceptionFunctor> SecurityToken::WarningCallback;
                    721: 
                    722:        bool SecurityToken::Initialized;
                    723:        CK_FUNCTION_LIST_PTR SecurityToken::Pkcs11Functions;
                    724:        map <CK_SLOT_ID, Pkcs11Session> SecurityToken::Sessions;
                    725: 
                    726: #ifdef TC_WINDOWS
                    727:        HMODULE SecurityToken::Pkcs11LibraryHandle;
                    728: #else
                    729:        void *SecurityToken::Pkcs11LibraryHandle;
                    730: #endif
                    731: 
                    732: #ifdef TC_HEADER_Platform_Exception
                    733: 
                    734:        void Pkcs11Exception::Deserialize (shared_ptr <Stream> stream)
                    735:        {
                    736:                Exception::Deserialize (stream);
                    737:                Serializer sr (stream);
                    738:                uint64 code;
                    739:                sr.Deserialize ("ErrorCode", code);
                    740:                sr.Deserialize ("SubjectErrorCodeValid", SubjectErrorCodeValid);
                    741:                sr.Deserialize ("SubjectErrorCode", SubjectErrorCode);
                    742:                ErrorCode = (CK_RV) code;
                    743:        }
                    744: 
                    745:        void Pkcs11Exception::Serialize (shared_ptr <Stream> stream) const
                    746:        {
                    747:                Exception::Serialize (stream);
                    748:                Serializer sr (stream);
                    749:                sr.Serialize ("ErrorCode", (uint64) ErrorCode);
                    750:                sr.Serialize ("SubjectErrorCodeValid", SubjectErrorCodeValid);
                    751:                sr.Serialize ("SubjectErrorCode", SubjectErrorCode);
                    752:        }
                    753: 
                    754: #      define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
                    755: #      undef TC_EXCEPTION_NODECL
                    756: #      define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
                    757: 
                    758:        TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (SecurityTokenException);
                    759: 
                    760: #endif
                    761: }

unix.superglobalmegacorp.com

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