From ae3e9a808e36b80f37aae47572368cec455fa575 Mon Sep 17 00:00:00 2001 From: vletoux Date: Sun, 22 Jul 2018 18:24:02 +0200 Subject: [PATCH] Adapted the KSP to be used in a smart card logon scenario (trick is about CERT_NCRYPT_KEY_SPEC to force the KSP) --- OpenPGPCsp/BaseContainer.cpp | 66 ++------------------------------- OpenPGPCsp/BaseContainer.h | 3 +- OpenPGPCsp/CspContainer.cpp | 60 ++++++++++++++++++++++++++++++ OpenPGPCsp/CspContainer.h | 1 + OpenPGPCsp/KspContainer.cpp | 72 ++++++++++++++++++++++++++++++++---- OpenPGPCsp/KspContainer.h | 2 +- 6 files changed, 131 insertions(+), 73 deletions(-) diff --git a/OpenPGPCsp/BaseContainer.cpp b/OpenPGPCsp/BaseContainer.cpp index 20516dc..f3f4554 100644 --- a/OpenPGPCsp/BaseContainer.cpp +++ b/OpenPGPCsp/BaseContainer.cpp @@ -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; @@ -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)) { diff --git a/OpenPGPCsp/BaseContainer.h b/OpenPGPCsp/BaseContainer.h index 892fab8..41fa70b 100644 --- a/OpenPGPCsp/BaseContainer.h +++ b/OpenPGPCsp/BaseContainer.h @@ -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); diff --git a/OpenPGPCsp/CspContainer.cpp b/OpenPGPCsp/CspContainer.cpp index 36944cc..8490009 100644 --- a/OpenPGPCsp/CspContainer.cpp +++ b/OpenPGPCsp/CspContainer.cpp @@ -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, diff --git a/OpenPGPCsp/CspContainer.h b/OpenPGPCsp/CspContainer.h index b891999..c9da500 100644 --- a/OpenPGPCsp/CspContainer.h +++ b/OpenPGPCsp/CspContainer.h @@ -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(); diff --git a/OpenPGPCsp/KspContainer.cpp b/OpenPGPCsp/KspContainer.cpp index db1e61b..177f3b7 100644 --- a/OpenPGPCsp/KspContainer.cpp +++ b/OpenPGPCsp/KspContainer.cpp @@ -39,6 +39,7 @@ KspContainer::KspContainer() { m_hWnd = 0; m_kspcontainers.push_front(this); + ZeroMemory(&m_LastGUIDSeen, sizeof(GUID)); } KspContainer::~KspContainer() @@ -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); @@ -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; @@ -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; @@ -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 @@ -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 { @@ -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; @@ -652,7 +682,7 @@ _Success_(return) BOOL KspContainer::EnumKeys( } if (!*ppEnumState) { - *ppEnumState = KspContainer::BuildEnumData(pszScope); + *ppEnumState = BuildEnumData(pszScope); if (!*ppEnumState ) { dwError = GetLastError(); @@ -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; @@ -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) { @@ -1315,6 +1355,7 @@ __in DWORD dwFlags) { BOOL fReturn = FALSE; DWORD dwError = 0; + CHAR szAnsiPin[255]; __try { if((pszProperty == NULL)|| @@ -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); @@ -1421,6 +1478,7 @@ __in DWORD dwFlags) } __finally { + SecureZeroMemory(szAnsiPin, sizeof(szAnsiPin)); } SetLastError(dwError); return fReturn; diff --git a/OpenPGPCsp/KspContainer.h b/OpenPGPCsp/KspContainer.h index 9b9d6fd..1d3a3d1 100644 --- a/OpenPGPCsp/KspContainer.h +++ b/OpenPGPCsp/KspContainer.h @@ -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; }; \ No newline at end of file