📄 securitytoken.cpp
字号:
list <CK_SLOT_ID> SecurityToken::GetTokenSlots ()
{
CheckLibraryStatus();
list <CK_SLOT_ID> slots;
CK_ULONG slotCount;
CK_RV status = Pkcs11Functions->C_GetSlotList (TRUE, NULL_PTR, &slotCount);
if (status != CKR_OK)
throw Pkcs11Exception (status);
if (slotCount > 0)
{
vector <CK_SLOT_ID> slotArray (slotCount);
status = Pkcs11Functions->C_GetSlotList (TRUE, &slotArray.front(), &slotCount);
if (status != CKR_OK)
throw Pkcs11Exception (status);
for (size_t i = 0; i < slotCount; i++)
{
CK_SLOT_INFO slotInfo;
status = Pkcs11Functions->C_GetSlotInfo (slotArray[i], &slotInfo);
if (status != CKR_OK || !(slotInfo.flags & CKF_TOKEN_PRESENT))
continue;
slots.push_back (slotArray[i]);
}
}
return slots;
}
bool SecurityToken::IsKeyfilePathValid (const wstring &securityTokenKeyfilePath)
{
return securityTokenKeyfilePath.find (TC_SECURITY_TOKEN_KEYFILE_URL_PREFIX) == 0;
}
void SecurityToken::Login (CK_SLOT_ID slotId, const string &pin)
{
if (Sessions.find (slotId) == Sessions.end())
OpenSession (slotId);
else if (Sessions[slotId].UserLoggedIn)
return;
CK_RV status = Pkcs11Functions->C_Login (Sessions[slotId].Handle, CKU_USER, (CK_CHAR_PTR) pin.c_str(), pin.size());
if (status != CKR_OK)
throw Pkcs11Exception (status);
Sessions[slotId].UserLoggedIn = true;
}
void SecurityToken::LoginUserIfRequired (CK_SLOT_ID slotId)
{
CheckLibraryStatus();
CK_RV status;
if (Sessions.find (slotId) == Sessions.end())
{
OpenSession (slotId);
}
else
{
CK_SESSION_INFO sessionInfo;
status = Pkcs11Functions->C_GetSessionInfo (Sessions[slotId].Handle, &sessionInfo);
if (status == CKR_OK)
{
Sessions[slotId].UserLoggedIn = (sessionInfo.state == CKS_RO_USER_FUNCTIONS || sessionInfo.state == CKS_RW_USER_FUNCTIONS);
}
else
{
try
{
CloseSession (slotId);
}
catch (...) { }
OpenSession (slotId);
}
}
SecurityTokenInfo tokenInfo = GetTokenInfo (slotId);
while (!Sessions[slotId].UserLoggedIn && (tokenInfo.Flags & CKF_LOGIN_REQUIRED))
{
try
{
if (tokenInfo.Flags & CKF_PROTECTED_AUTHENTICATION_PATH)
{
status = Pkcs11Functions->C_Login (Sessions[slotId].Handle, CKU_USER, NULL_PTR, 0);
if (status != CKR_OK)
throw Pkcs11Exception (status);
}
else
{
string pin = tokenInfo.LabelUtf8;
if (tokenInfo.Label.empty())
{
stringstream s;
s << "#" << slotId;
pin = s.str();
}
finally_do_arg (string*, &pin, { burn ((void *) finally_arg->c_str(), finally_arg->size()); });
(*PinCallback) (pin);
Login (slotId, pin);
}
Sessions[slotId].UserLoggedIn = true;
}
catch (Pkcs11Exception &e)
{
CK_RV error = e.GetErrorCode();
if (error == CKR_USER_ALREADY_LOGGED_IN)
{
break;
}
else if (error == CKR_PIN_INCORRECT && !(tokenInfo.Flags & CKF_PROTECTED_AUTHENTICATION_PATH))
{
(*WarningCallback) (Pkcs11Exception (CKR_PIN_INCORRECT));
continue;
}
throw;
}
}
}
void SecurityToken::InitLibrary (const string &pkcs11LibraryPath, auto_ptr <GetPinFunctor> pinCallback, auto_ptr <SendExceptionFunctor> warningCallback)
{
if (Initialized)
CloseLibrary();
#ifdef TC_WINDOWS
Pkcs11LibraryHandle = LoadLibraryA (pkcs11LibraryPath.c_str());
#else
Pkcs11LibraryHandle = dlopen (pkcs11LibraryPath.c_str(), RTLD_NOW | RTLD_LOCAL);
#endif
throw_sys_if (!Pkcs11LibraryHandle);
typedef CK_RV (*C_GetFunctionList_t) (CK_FUNCTION_LIST_PTR_PTR ppFunctionList);
#ifdef TC_WINDOWS
C_GetFunctionList_t C_GetFunctionList = (C_GetFunctionList_t) GetProcAddress (Pkcs11LibraryHandle, "C_GetFunctionList");
#else
C_GetFunctionList_t C_GetFunctionList = (C_GetFunctionList_t) dlsym (Pkcs11LibraryHandle, "C_GetFunctionList");
#endif
if (!C_GetFunctionList)
throw SecurityTokenLibraryNotInitialized();
CK_RV status = C_GetFunctionList (&Pkcs11Functions);
if (status != CKR_OK)
throw Pkcs11Exception (status);
status = Pkcs11Functions->C_Initialize (NULL_PTR);
if (status != CKR_OK)
throw Pkcs11Exception (status);
PinCallback = pinCallback;
WarningCallback = warningCallback;
Initialized = true;
}
void SecurityToken::OpenSession (CK_SLOT_ID slotId)
{
if (Sessions.find (slotId) != Sessions.end())
return;
CK_SESSION_HANDLE session;
CK_FLAGS flags = CKF_SERIAL_SESSION;
if (!(GetTokenInfo (slotId).Flags & CKF_WRITE_PROTECTED))
flags |= CKF_RW_SESSION;
CK_RV status = Pkcs11Functions->C_OpenSession (slotId, flags, NULL_PTR, NULL_PTR, &session);
if (status != CKR_OK)
throw Pkcs11Exception (status);
Sessions[slotId].Handle = session;
}
Pkcs11Exception::operator string () const
{
#define TC_CASE_STR(CODE) case CODE : return #CODE
switch (ErrorCode)
{
case CKR_OK: return string();
TC_CASE_STR (CKR_CANCEL);
TC_CASE_STR (CKR_HOST_MEMORY);
TC_CASE_STR (CKR_SLOT_ID_INVALID);
TC_CASE_STR (CKR_GENERAL_ERROR);
TC_CASE_STR (CKR_FUNCTION_FAILED);
TC_CASE_STR (CKR_ARGUMENTS_BAD);
TC_CASE_STR (CKR_NO_EVENT);
TC_CASE_STR (CKR_NEED_TO_CREATE_THREADS);
TC_CASE_STR (CKR_CANT_LOCK);
TC_CASE_STR (CKR_ATTRIBUTE_READ_ONLY);
TC_CASE_STR (CKR_ATTRIBUTE_SENSITIVE);
TC_CASE_STR (CKR_ATTRIBUTE_TYPE_INVALID);
TC_CASE_STR (CKR_ATTRIBUTE_VALUE_INVALID);
TC_CASE_STR (CKR_DATA_INVALID);
TC_CASE_STR (CKR_DATA_LEN_RANGE);
TC_CASE_STR (CKR_DEVICE_ERROR);
TC_CASE_STR (CKR_DEVICE_MEMORY);
TC_CASE_STR (CKR_DEVICE_REMOVED);
TC_CASE_STR (CKR_ENCRYPTED_DATA_INVALID);
TC_CASE_STR (CKR_ENCRYPTED_DATA_LEN_RANGE);
TC_CASE_STR (CKR_FUNCTION_CANCELED);
TC_CASE_STR (CKR_FUNCTION_NOT_PARALLEL);
TC_CASE_STR (CKR_FUNCTION_NOT_SUPPORTED);
TC_CASE_STR (CKR_KEY_HANDLE_INVALID);
TC_CASE_STR (CKR_KEY_SIZE_RANGE);
TC_CASE_STR (CKR_KEY_TYPE_INCONSISTENT);
TC_CASE_STR (CKR_KEY_NOT_NEEDED);
TC_CASE_STR (CKR_KEY_CHANGED);
TC_CASE_STR (CKR_KEY_NEEDED);
TC_CASE_STR (CKR_KEY_INDIGESTIBLE);
TC_CASE_STR (CKR_KEY_FUNCTION_NOT_PERMITTED);
TC_CASE_STR (CKR_KEY_NOT_WRAPPABLE);
TC_CASE_STR (CKR_KEY_UNEXTRACTABLE);
TC_CASE_STR (CKR_MECHANISM_INVALID);
TC_CASE_STR (CKR_MECHANISM_PARAM_INVALID);
TC_CASE_STR (CKR_OBJECT_HANDLE_INVALID);
TC_CASE_STR (CKR_OPERATION_ACTIVE);
TC_CASE_STR (CKR_OPERATION_NOT_INITIALIZED);
TC_CASE_STR (CKR_PIN_INCORRECT);
TC_CASE_STR (CKR_PIN_INVALID);
TC_CASE_STR (CKR_PIN_LEN_RANGE);
TC_CASE_STR (CKR_PIN_EXPIRED);
TC_CASE_STR (CKR_PIN_LOCKED);
TC_CASE_STR (CKR_SESSION_CLOSED);
TC_CASE_STR (CKR_SESSION_COUNT);
TC_CASE_STR (CKR_SESSION_HANDLE_INVALID);
TC_CASE_STR (CKR_SESSION_PARALLEL_NOT_SUPPORTED);
TC_CASE_STR (CKR_SESSION_READ_ONLY);
TC_CASE_STR (CKR_SESSION_EXISTS);
TC_CASE_STR (CKR_SESSION_READ_ONLY_EXISTS);
TC_CASE_STR (CKR_SESSION_READ_WRITE_SO_EXISTS);
TC_CASE_STR (CKR_SIGNATURE_INVALID);
TC_CASE_STR (CKR_SIGNATURE_LEN_RANGE);
TC_CASE_STR (CKR_TEMPLATE_INCOMPLETE);
TC_CASE_STR (CKR_TEMPLATE_INCONSISTENT);
TC_CASE_STR (CKR_TOKEN_NOT_PRESENT);
TC_CASE_STR (CKR_TOKEN_NOT_RECOGNIZED);
TC_CASE_STR (CKR_TOKEN_WRITE_PROTECTED);
TC_CASE_STR (CKR_UNWRAPPING_KEY_HANDLE_INVALID);
TC_CASE_STR (CKR_UNWRAPPING_KEY_SIZE_RANGE);
TC_CASE_STR (CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT);
TC_CASE_STR (CKR_USER_ALREADY_LOGGED_IN);
TC_CASE_STR (CKR_USER_NOT_LOGGED_IN);
TC_CASE_STR (CKR_USER_PIN_NOT_INITIALIZED);
TC_CASE_STR (CKR_USER_TYPE_INVALID);
TC_CASE_STR (CKR_USER_ANOTHER_ALREADY_LOGGED_IN);
TC_CASE_STR (CKR_USER_TOO_MANY_TYPES);
TC_CASE_STR (CKR_WRAPPED_KEY_INVALID);
TC_CASE_STR (CKR_WRAPPED_KEY_LEN_RANGE);
TC_CASE_STR (CKR_WRAPPING_KEY_HANDLE_INVALID);
TC_CASE_STR (CKR_WRAPPING_KEY_SIZE_RANGE);
TC_CASE_STR (CKR_WRAPPING_KEY_TYPE_INCONSISTENT);
TC_CASE_STR (CKR_RANDOM_SEED_NOT_SUPPORTED);
TC_CASE_STR (CKR_RANDOM_NO_RNG);
TC_CASE_STR (CKR_DOMAIN_PARAMS_INVALID);
TC_CASE_STR (CKR_BUFFER_TOO_SMALL);
TC_CASE_STR (CKR_SAVED_STATE_INVALID);
TC_CASE_STR (CKR_INFORMATION_SENSITIVE);
TC_CASE_STR (CKR_STATE_UNSAVEABLE);
TC_CASE_STR (CKR_CRYPTOKI_NOT_INITIALIZED);
TC_CASE_STR (CKR_CRYPTOKI_ALREADY_INITIALIZED);
TC_CASE_STR (CKR_MUTEX_BAD);
TC_CASE_STR (CKR_MUTEX_NOT_LOCKED);
TC_CASE_STR (CKR_NEW_PIN_MODE);
TC_CASE_STR (CKR_NEXT_OTP);
TC_CASE_STR (CKR_FUNCTION_REJECTED);
default:
{
stringstream s;
s << "0x" << hex << ErrorCode;
return s.str();
}
};
#undef TC_CASE_STR
}
#ifdef TC_HEADER_Common_Exception
void Pkcs11Exception::Show (HWND parent) const
{
string errorString = string (*this);
if (!errorString.empty())
{
wstringstream subjectErrorCode;
if (SubjectErrorCodeValid)
subjectErrorCode << L": " << SubjectErrorCode;
if (!GetDictionaryValue (errorString.c_str()))
{
if (errorString.find ("CKR_") == 0)
{
errorString = errorString.substr (4);
for (size_t i = 0; i < errorString.size(); ++i)
{
if (errorString[i] == '_')
errorString[i] = ' ';
}
}
wchar_t err[8192];
wsprintfW (err, L"%s:\n\n%hs%s", GetString ("SECURITY_TOKEN_ERROR"), errorString.c_str(), subjectErrorCode.str().c_str());
ErrorDirect (err);
}
else
{
wstring err = GetString (errorString.c_str());
if (SubjectErrorCodeValid)
err += L"\n\nError code" + subjectErrorCode.str();
ErrorDirect (err.c_str());
}
}
}
#endif // TC_HEADER_Common_Exception
auto_ptr <GetPinFunctor> SecurityToken::PinCallback;
auto_ptr <SendExceptionFunctor> SecurityToken::WarningCallback;
bool SecurityToken::Initialized;
CK_FUNCTION_LIST_PTR SecurityToken::Pkcs11Functions;
map <CK_SLOT_ID, Pkcs11Session> SecurityToken::Sessions;
#ifdef TC_WINDOWS
HMODULE SecurityToken::Pkcs11LibraryHandle;
#else
void *SecurityToken::Pkcs11LibraryHandle;
#endif
#ifdef TC_HEADER_Platform_Exception
void Pkcs11Exception::Deserialize (shared_ptr <Stream> stream)
{
Exception::Deserialize (stream);
Serializer sr (stream);
uint64 code;
sr.Deserialize ("ErrorCode", code);
sr.Deserialize ("SubjectErrorCodeValid", SubjectErrorCodeValid);
sr.Deserialize ("SubjectErrorCode", SubjectErrorCode);
ErrorCode = (CK_RV) code;
}
void Pkcs11Exception::Serialize (shared_ptr <Stream> stream) const
{
Exception::Serialize (stream);
Serializer sr (stream);
sr.Serialize ("ErrorCode", (uint64) ErrorCode);
sr.Serialize ("SubjectErrorCodeValid", SubjectErrorCodeValid);
sr.Serialize ("SubjectErrorCode", SubjectErrorCode);
}
# define TC_EXCEPTION(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
# undef TC_EXCEPTION_NODECL
# define TC_EXCEPTION_NODECL(TYPE) TC_SERIALIZER_FACTORY_ADD(TYPE)
TC_SERIALIZER_FACTORY_ADD_EXCEPTION_SET (SecurityTokenException);
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -