Skip to content

Commit

Permalink
Adapted the KSP to be used in a smart card logon scenario (trick is a…
Browse files Browse the repository at this point in the history
…bout CERT_NCRYPT_KEY_SPEC to force the KSP)
  • Loading branch information
vletoux committed Jul 22, 2018
1 parent acbfc01 commit ae3e9a8
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 73 deletions.
66 changes: 3 additions & 63 deletions OpenPGPCsp/BaseContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,67 +611,7 @@ BOOL ExtractReaderAndContainerFromGeneralNameW(__in PCWSTR szSubmittedContainer,
////////////////////////////////////////////////////////////////////////////


BOOL BaseContainer::GetUserStore(__in PTSTR szProviderName, __out HCERTSTORE* phStore)
{
BOOL fReturn = FALSE;
DWORD dwError = 0;
HCERTSTORE hStore = NULL;
BOOL fEndTransaction = FALSE;
BOOL fAuthenticated = FALSE;
__try
{
if (!m_Card)
{
Trace(TRACE_LEVEL_ERROR, L"defensive programming for user store");
dwError = NTE_NOT_SUPPORTED;
__leave;
}
hStore = CertOpenStore(CERT_STORE_PROV_MEMORY,0,0,0,NULL);
if (!hStore)
{
dwError = GetLastError();
Trace(TRACE_LEVEL_ERROR, L"CertOpenStore failed 0x%08X", dwError);
__leave;
}
if (!StartTransaction())
{
dwError = GetLastError();
Trace(TRACE_LEVEL_ERROR, L"StartTransaction failed 0x%08X", dwError);
__leave;
}
fEndTransaction = TRUE;
DWORD dwMaxContainer = m_Card->GetMaxContainer();
for(DWORD dwI = 0; dwI < dwMaxContainer; dwI++)
{
CHAR szContainer[MAX_CONTAINER_NAME];
BYTE pbBuffer[4096];
DWORD dwSize = sizeof(pbBuffer);
DWORD dwKeySpec = AT_SIGNATURE;
if (m_Card->GetContainerName(dwI, szContainer)
&& m_Card->GetKeySpec(dwI, &dwKeySpec)
&& m_Card->GetCertificate(dwI, pbBuffer, &dwSize))
{
PopulateUserStoreFromContainerName(hStore, szProviderName, szContainer, dwKeySpec, pbBuffer, dwSize);
}
}
*phStore = hStore;
fReturn = TRUE;
}
__finally
{
if (!fReturn)
{
if (hStore)
CertCloseStore(hStore, 0);
}
if (fEndTransaction)
EndTransaction(0, fAuthenticated);
}
SetLastError(dwError);
return fReturn;
}

BOOL BaseContainer::PopulateUserStoreFromContainerName(__in HCERTSTORE hStore, __in PTSTR szProviderName, __in PSTR szContainer, __in DWORD dwKeySpec, __in PBYTE pbData, __in DWORD dwSize)
BOOL BaseContainer::PopulateUserStoreFromContainerName(__in HCERTSTORE hStore, __in PTSTR szProviderName, __in BOOL IsCSP, __in PSTR szContainer, __in DWORD dwKeySpec, __in PBYTE pbData, __in DWORD dwSize)
{
BOOL fReturn = FALSE;
DWORD dwError = 0;
Expand All @@ -691,11 +631,11 @@ BOOL BaseContainer::PopulateUserStoreFromContainerName(__in HCERTSTORE hStore, _
ZeroMemory(&propInfo,sizeof(propInfo));
propInfo.pwszContainerName = szWideContainerName;
propInfo.pwszProvName = szProviderName;
propInfo.dwProvType = PROV_RSA_FULL;
propInfo.dwProvType = (IsCSP ? PROV_RSA_FULL : 0);
propInfo.dwFlags = 0;
propInfo.cProvParam = 0;
propInfo.rgProvParam = 0;
propInfo.dwKeySpec = dwKeySpec;
propInfo.dwKeySpec = (IsCSP ? dwKeySpec : CERT_NCRYPT_KEY_SPEC);
if (!CertSetCertificateContextProperty(pCertContext,CERT_KEY_PROV_INFO_PROP_ID,
0,&propInfo))
{
Expand Down
3 changes: 1 addition & 2 deletions OpenPGPCsp/BaseContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ class BaseContainer {
Card* CreateContext();

// store operations
BOOL GetUserStore(__in PTSTR szProviderName, __out HCERTSTORE* phStore);
BOOL PopulateUserStoreFromContainerName(__in HCERTSTORE hStore, __in PTSTR szProviderName, __in PSTR szContainer, __in DWORD dwKeySpec, __in PBYTE pbData, __in DWORD dwSize);
BOOL PopulateUserStoreFromContainerName(__in HCERTSTORE hStore, __in PTSTR szProviderName, __in BOOL IsCSP, __in PSTR szContainer, __in DWORD dwKeySpec, __in PBYTE pbData, __in DWORD dwSize);
BOOL LoadCertificate(_Out_writes_bytes_to_opt_(*pdwSize, *pdwSize) PBYTE pbData, __inout PDWORD pdwSize);
BOOL SaveCertificate(__in_bcount(dwSize) PBYTE pbData, __in DWORD dwSize, __in DWORD dwKeySpec);

Expand Down
60 changes: 60 additions & 0 deletions OpenPGPCsp/CspContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1190,6 +1190,66 @@ _Success_(return) BOOL CspContainer::GetProvParam(
return fReturn;
}

BOOL CspContainer::GetUserStore(__in PTSTR szProviderName, __out HCERTSTORE* phStore)
{
BOOL fReturn = FALSE;
DWORD dwError = 0;
HCERTSTORE hStore = NULL;
BOOL fEndTransaction = FALSE;
BOOL fAuthenticated = FALSE;
__try
{
if (!m_Card)
{
Trace(TRACE_LEVEL_ERROR, L"defensive programming for user store");
dwError = NTE_NOT_SUPPORTED;
__leave;
}
hStore = CertOpenStore(CERT_STORE_PROV_MEMORY,0,0,0,NULL);
if (!hStore)
{
dwError = GetLastError();
Trace(TRACE_LEVEL_ERROR, L"CertOpenStore failed 0x%08X", dwError);
__leave;
}
if (!StartTransaction())
{
dwError = GetLastError();
Trace(TRACE_LEVEL_ERROR, L"StartTransaction failed 0x%08X", dwError);
__leave;
}
fEndTransaction = TRUE;
DWORD dwMaxContainer = m_Card->GetMaxContainer();
for(DWORD dwI = 0; dwI < dwMaxContainer; dwI++)
{
CHAR szContainer[MAX_CONTAINER_NAME];
BYTE pbBuffer[4096];
DWORD dwSize = sizeof(pbBuffer);
DWORD dwKeySpec = AT_SIGNATURE;
if (m_Card->GetContainerName(dwI, szContainer)
&& m_Card->GetKeySpec(dwI, &dwKeySpec)
&& m_Card->GetCertificate(dwI, pbBuffer, &dwSize))
{
PopulateUserStoreFromContainerName(hStore, szProviderName, TRUE, szContainer, dwKeySpec, pbBuffer, dwSize);
}
}
*phStore = hStore;
fReturn = TRUE;
}
__finally
{
if (!fReturn)
{
if (hStore)
CertCloseStore(hStore, 0);
}
if (fEndTransaction)
EndTransaction(0, fAuthenticated);
}
SetLastError(dwError);
return fReturn;
}

BOOL CspContainer::SetProvParam(
__in DWORD dwParam,
__in CONST BYTE *pbData,
Expand Down
1 change: 1 addition & 0 deletions OpenPGPCsp/CspContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ private :

BOOL AskForSmartCardReader();

BOOL GetUserStore(__in PTSTR szProviderName, __out HCERTSTORE* phStore);
BOOL EnumerateContainer(_Out_writes_bytes_to_opt_(*pdwDataLen, *pdwDataLen) PSTR szContainer, __inout PDWORD pdwDataLen, DWORD dwFlags);

HWND GetParentHwnd();
Expand Down
72 changes: 65 additions & 7 deletions OpenPGPCsp/KspContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ KspContainer::KspContainer()
{
m_hWnd = 0;
m_kspcontainers.push_front(this);
ZeroMemory(&m_LastGUIDSeen, sizeof(GUID));
}

KspContainer::~KspContainer()
Expand Down Expand Up @@ -254,6 +255,10 @@ _Success_(return) BOOL KspContainer::GetProviderProperty(
{
* pcbResult = sizeof(HCERTSTORE);
}
else if(wcscmp(pszProperty, NCRYPT_ROOT_CERTSTORE_PROPERTY) == 0)
{
* pcbResult = sizeof(HCERTSTORE);
}
else if(wcscmp(pszProperty, NCRYPT_IMPL_TYPE_PROPERTY) == 0)
{
* pcbResult = sizeof(DWORD);
Expand All @@ -270,6 +275,10 @@ _Success_(return) BOOL KspContainer::GetProviderProperty(
{
* pcbResult = sizeof(DWORD);
}
else if(wcscmp(pszProperty, NCRYPT_SMARTCARD_GUID_PROPERTY) == 0)
{
* pcbResult = sizeof(GUID);
}
else
{
dwError = NTE_NOT_SUPPORTED;
Expand Down Expand Up @@ -309,6 +318,18 @@ _Success_(return) BOOL KspContainer::GetProviderProperty(
{
}
}
else if(wcscmp(pszProperty, NCRYPT_ROOT_CERTSTORE_PROPERTY) == 0)
{
HCERTSTORE hStore = NULL;
hStore = CertOpenStore(CERT_STORE_PROV_MEMORY,0,0,0,NULL);
if (!hStore)
{
dwError = GetLastError();
Trace(TRACE_LEVEL_ERROR, L"CertOpenStore failed 0x%08X", dwError);
__leave;
}
*(HCERTSTORE *)pbOutput = hStore;
}
else if(wcscmp(pszProperty, NCRYPT_IMPL_TYPE_PROPERTY) == 0)
{
*(DWORD *)pbOutput = NCRYPT_IMPL_HARDWARE_FLAG;
Expand All @@ -325,6 +346,11 @@ _Success_(return) BOOL KspContainer::GetProviderProperty(
{
*(DWORD *)pbOutput =1;
}
else if(wcscmp(pszProperty, NCRYPT_SMARTCARD_GUID_PROPERTY) == 0)
{
//requested by logon ! But on a provider property on not a key one
RtlCopyMemory(pbOutput, &m_LastGUIDSeen, sizeof(GUID));
}
fReturn = TRUE;
}
__finally
Expand Down Expand Up @@ -369,16 +395,19 @@ _Success_(return) BOOL KspContainer::SetProviderProperty(__in LPCWSTR pszProp
if (wcscmp(pszProperty, NCRYPT_WINDOW_HANDLE_PROPERTY) == 0)
{
m_hWnd = *((HWND*)pbInput);
fReturn = TRUE;
}
else if (wcscmp(pszProperty, NCRYPT_USE_CONTEXT_PROPERTY) == 0)
{
fReturn = TRUE;
}
else if (wcscmp(pszProperty, NCRYPT_READER_PROPERTY) == 0)
{
}
else
{
dwError = NTE_NOT_SUPPORTED;
__leave;
}
fReturn = TRUE;
}
__finally
{
Expand Down Expand Up @@ -603,6 +632,7 @@ KspEnumNCryptKeyName* KspContainer::BuildEnumData(__in_opt LPCWSTR pszScope)
returnValue->names[returnValue->dwNumberOfNCryptKeyName].pszName = returnValue->szContainerName[returnValue->dwNumberOfNCryptKeyName];
MultiByteToWideChar(CP_ACP, 0, szContainer, -1, returnValue->szContainerName[returnValue->dwNumberOfNCryptKeyName], (int)(strlen(szContainer) + 1 ) * 2);
returnValue->dwNumberOfNCryptKeyName++;
m_Card->GetCardGUID(&m_LastGUIDSeen);
}
}
delete m_Card;
Expand Down Expand Up @@ -652,7 +682,7 @@ _Success_(return) BOOL KspContainer::EnumKeys(
}
if (!*ppEnumState)
{
*ppEnumState = KspContainer::BuildEnumData(pszScope);
*ppEnumState = BuildEnumData(pszScope);
if (!*ppEnumState )
{
dwError = GetLastError();
Expand Down Expand Up @@ -1067,7 +1097,7 @@ BOOL KspContainer::GetUserStoreWithAllCard(__out HCERTSTORE* phStore)
&& m_Card->GetKeySpec(dwI, &dwKeySpec)
&& m_Card->GetCertificate(dwI, pbBuffer, &dwSize))
{
PopulateUserStoreFromContainerName(hStore, TEXT(KSPNAME), szContainer, dwKeySpec, pbBuffer, dwSize);
PopulateUserStoreFromContainerName(hStore, TEXT(KSPNAME), FALSE, szContainer, dwKeySpec, pbBuffer, dwSize);
}
}
delete m_Card;
Expand Down Expand Up @@ -1259,10 +1289,20 @@ __in DWORD dwFlags)
}
else if (wcscmp(pszProperty, NCRYPT_LENGTHS_PROPERTY) == 0)
{
((NCRYPT_SUPPORTED_LENGTHS*)pbOutput)->dwMinLength = 1024;
((NCRYPT_SUPPORTED_LENGTHS*)pbOutput)->dwDefaultLength = 2048;
((NCRYPT_SUPPORTED_LENGTHS*)pbOutput)->dwMaxLength = 3072;
((NCRYPT_SUPPORTED_LENGTHS*)pbOutput)->dwIncrement = 1024;
if (m_isFinalized)
{
m_Card->GetKeyLength(&((NCRYPT_SUPPORTED_LENGTHS*)pbOutput)->dwDefaultLength,
&((NCRYPT_SUPPORTED_LENGTHS*)pbOutput)->dwMinLength,
&((NCRYPT_SUPPORTED_LENGTHS*)pbOutput)->dwMaxLength);
}
// being called with a fake creation by CNG middleware to get the key length before it is being created
else
{
((NCRYPT_SUPPORTED_LENGTHS*)pbOutput)->dwMinLength = 1024;
((NCRYPT_SUPPORTED_LENGTHS*)pbOutput)->dwDefaultLength = 2048;
((NCRYPT_SUPPORTED_LENGTHS*)pbOutput)->dwMaxLength = 3072;
}
}
else if(wcscmp(pszProperty, NCRYPT_BLOCK_LENGTH_PROPERTY) == 0)
{
Expand Down Expand Up @@ -1315,6 +1355,7 @@ __in DWORD dwFlags)
{
BOOL fReturn = FALSE;
DWORD dwError = 0;
CHAR szAnsiPin[255];
__try
{
if((pszProperty == NULL)||
Expand Down Expand Up @@ -1411,6 +1452,22 @@ __in DWORD dwFlags)
free(m_szPinPROMPT);
m_szPinPROMPT = DuplicateUnicodeString((PWSTR) pbInput);
}
else if (wcscmp(pszProperty, NCRYPT_PIN_PROPERTY) == 0)
{
if (m_Card != NULL)
{
DWORD dwPINType = (m_dwLegacyKeySpec == AT_SIGNATURE ? PP_SIGNATURE_PIN : PP_KEYEXCHANGE_PIN);
Trace(TRACE_LEVEL_VERBOSE, L"set pin %d", dwPINType);
WideCharToMultiByte(CP_ACP, 0, (PWSTR) pbInput, -1, szAnsiPin, sizeof(szAnsiPin), NULL, NULL);
fReturn = SetPin(dwPINType, szAnsiPin);
if (!fReturn)
{
dwError = GetLastError();
Trace(TRACE_LEVEL_ERROR, L"SetPin failed 0x%08X", dwError);
__leave;
}
}
}
else
{
Trace(TRACE_LEVEL_ERROR, L"Invalid property %s", pszProperty);
Expand All @@ -1421,6 +1478,7 @@ __in DWORD dwFlags)
}
__finally
{
SecureZeroMemory(szAnsiPin, sizeof(szAnsiPin));
}
SetLastError(dwError);
return fReturn;
Expand Down
2 changes: 1 addition & 1 deletion OpenPGPCsp/KspContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,5 +159,5 @@ private :
KspKey* LocateKey(__in NCRYPT_KEY_HANDLE hKey);
KspEnumNCryptKeyName* BuildEnumData(__in_opt LPCWSTR pszScope);
BOOL GetUserStoreWithAllCard(__out HCERTSTORE* phStore);

GUID m_LastGUIDSeen;
};

0 comments on commit ae3e9a8

Please sign in to comment.