securitytoken.cpp
来自「外国开源的硬盘加密软件」· C++ 代码 · 共 762 行 · 第 1/2 页
CPP
762 行
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
{
if (ErrorCode == CKR_OK)
return string();
static const struct
{
int ErrorCode;
const char *ErrorString;
} ErrorStrings[] =
{
# define TC_TOKEN_ERR(CODE) { CODE, #CODE },
TC_TOKEN_ERR (CKR_CANCEL)
TC_TOKEN_ERR (CKR_HOST_MEMORY)
TC_TOKEN_ERR (CKR_SLOT_ID_INVALID)
TC_TOKEN_ERR (CKR_GENERAL_ERROR)
TC_TOKEN_ERR (CKR_FUNCTION_FAILED)
TC_TOKEN_ERR (CKR_ARGUMENTS_BAD)
TC_TOKEN_ERR (CKR_NO_EVENT)
TC_TOKEN_ERR (CKR_NEED_TO_CREATE_THREADS)
TC_TOKEN_ERR (CKR_CANT_LOCK)
TC_TOKEN_ERR (CKR_ATTRIBUTE_READ_ONLY)
TC_TOKEN_ERR (CKR_ATTRIBUTE_SENSITIVE)
TC_TOKEN_ERR (CKR_ATTRIBUTE_TYPE_INVALID)
TC_TOKEN_ERR (CKR_ATTRIBUTE_VALUE_INVALID)
TC_TOKEN_ERR (CKR_DATA_INVALID)
TC_TOKEN_ERR (CKR_DATA_LEN_RANGE)
TC_TOKEN_ERR (CKR_DEVICE_ERROR)
TC_TOKEN_ERR (CKR_DEVICE_MEMORY)
TC_TOKEN_ERR (CKR_DEVICE_REMOVED)
TC_TOKEN_ERR (CKR_ENCRYPTED_DATA_INVALID)
TC_TOKEN_ERR (CKR_ENCRYPTED_DATA_LEN_RANGE)
TC_TOKEN_ERR (CKR_FUNCTION_CANCELED)
TC_TOKEN_ERR (CKR_FUNCTION_NOT_PARALLEL)
TC_TOKEN_ERR (CKR_FUNCTION_NOT_SUPPORTED)
TC_TOKEN_ERR (CKR_KEY_HANDLE_INVALID)
TC_TOKEN_ERR (CKR_KEY_SIZE_RANGE)
TC_TOKEN_ERR (CKR_KEY_TYPE_INCONSISTENT)
TC_TOKEN_ERR (CKR_KEY_NOT_NEEDED)
TC_TOKEN_ERR (CKR_KEY_CHANGED)
TC_TOKEN_ERR (CKR_KEY_NEEDED)
TC_TOKEN_ERR (CKR_KEY_INDIGESTIBLE)
TC_TOKEN_ERR (CKR_KEY_FUNCTION_NOT_PERMITTED)
TC_TOKEN_ERR (CKR_KEY_NOT_WRAPPABLE)
TC_TOKEN_ERR (CKR_KEY_UNEXTRACTABLE)
TC_TOKEN_ERR (CKR_MECHANISM_INVALID)
TC_TOKEN_ERR (CKR_MECHANISM_PARAM_INVALID)
TC_TOKEN_ERR (CKR_OBJECT_HANDLE_INVALID)
TC_TOKEN_ERR (CKR_OPERATION_ACTIVE)
TC_TOKEN_ERR (CKR_OPERATION_NOT_INITIALIZED)
TC_TOKEN_ERR (CKR_PIN_INCORRECT)
TC_TOKEN_ERR (CKR_PIN_INVALID)
TC_TOKEN_ERR (CKR_PIN_LEN_RANGE)
TC_TOKEN_ERR (CKR_PIN_EXPIRED)
TC_TOKEN_ERR (CKR_PIN_LOCKED)
TC_TOKEN_ERR (CKR_SESSION_CLOSED)
TC_TOKEN_ERR (CKR_SESSION_COUNT)
TC_TOKEN_ERR (CKR_SESSION_HANDLE_INVALID)
TC_TOKEN_ERR (CKR_SESSION_PARALLEL_NOT_SUPPORTED)
TC_TOKEN_ERR (CKR_SESSION_READ_ONLY)
TC_TOKEN_ERR (CKR_SESSION_EXISTS)
TC_TOKEN_ERR (CKR_SESSION_READ_ONLY_EXISTS)
TC_TOKEN_ERR (CKR_SESSION_READ_WRITE_SO_EXISTS)
TC_TOKEN_ERR (CKR_SIGNATURE_INVALID)
TC_TOKEN_ERR (CKR_SIGNATURE_LEN_RANGE)
TC_TOKEN_ERR (CKR_TEMPLATE_INCOMPLETE)
TC_TOKEN_ERR (CKR_TEMPLATE_INCONSISTENT)
TC_TOKEN_ERR (CKR_TOKEN_NOT_PRESENT)
TC_TOKEN_ERR (CKR_TOKEN_NOT_RECOGNIZED)
TC_TOKEN_ERR (CKR_TOKEN_WRITE_PROTECTED)
TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_HANDLE_INVALID)
TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_SIZE_RANGE)
TC_TOKEN_ERR (CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT)
TC_TOKEN_ERR (CKR_USER_ALREADY_LOGGED_IN)
TC_TOKEN_ERR (CKR_USER_NOT_LOGGED_IN)
TC_TOKEN_ERR (CKR_USER_PIN_NOT_INITIALIZED)
TC_TOKEN_ERR (CKR_USER_TYPE_INVALID)
TC_TOKEN_ERR (CKR_USER_ANOTHER_ALREADY_LOGGED_IN)
TC_TOKEN_ERR (CKR_USER_TOO_MANY_TYPES)
TC_TOKEN_ERR (CKR_WRAPPED_KEY_INVALID)
TC_TOKEN_ERR (CKR_WRAPPED_KEY_LEN_RANGE)
TC_TOKEN_ERR (CKR_WRAPPING_KEY_HANDLE_INVALID)
TC_TOKEN_ERR (CKR_WRAPPING_KEY_SIZE_RANGE)
TC_TOKEN_ERR (CKR_WRAPPING_KEY_TYPE_INCONSISTENT)
TC_TOKEN_ERR (CKR_RANDOM_SEED_NOT_SUPPORTED)
TC_TOKEN_ERR (CKR_RANDOM_NO_RNG)
TC_TOKEN_ERR (CKR_DOMAIN_PARAMS_INVALID)
TC_TOKEN_ERR (CKR_BUFFER_TOO_SMALL)
TC_TOKEN_ERR (CKR_SAVED_STATE_INVALID)
TC_TOKEN_ERR (CKR_INFORMATION_SENSITIVE)
TC_TOKEN_ERR (CKR_STATE_UNSAVEABLE)
TC_TOKEN_ERR (CKR_CRYPTOKI_NOT_INITIALIZED)
TC_TOKEN_ERR (CKR_CRYPTOKI_ALREADY_INITIALIZED)
TC_TOKEN_ERR (CKR_MUTEX_BAD)
TC_TOKEN_ERR (CKR_MUTEX_NOT_LOCKED)
TC_TOKEN_ERR (CKR_NEW_PIN_MODE)
TC_TOKEN_ERR (CKR_NEXT_OTP)
TC_TOKEN_ERR (CKR_FUNCTION_REJECTED)
#undef TC_TOKEN_ERR
};
for (size_t i = 0; i < array_capacity (ErrorStrings); ++i)
{
if (ErrorStrings[i].ErrorCode == ErrorCode)
return ErrorStrings[i].ErrorString;
}
stringstream s;
s << "0x" << hex << ErrorCode;
return s.str();
}
#ifdef TC_HEADER_Common_Exception
void Pkcs11Exception::Show (HWND parent) const
{
string errorString = string (*this);
if (!errorString.empty())
{
wstringstream subjectErrorCode;
if (SubjectErrorCodeValid)
subjectErrorCode << L": " << SubjectErrorCode;
if (!GetDictionaryValue (errorString.c_str()))
{
if (errorString.find ("CKR_") == 0)
{
errorString = errorString.substr (4);
for (size_t i = 0; i < errorString.size(); ++i)
{
if (errorString[i] == '_')
errorString[i] = ' ';
}
}
wchar_t err[8192];
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 + =
减小字号Ctrl + -
显示快捷键?