[Openpgpmdrv-commits] r10 - in trunk: OpenPGPminidriver OpenPGPminidriverTest

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Mon Mar 15 19:23:21 CET 2010


Author: vletoux
Date: 2010-03-15 19:23:17 +0100 (Mon, 15 Mar 2010)
New Revision: 10

Modified:
   trunk/OpenPGPminidriver/CardAndContainerProperties.c
   trunk/OpenPGPminidriver/CardCryptographicOperations.c
   trunk/OpenPGPminidriver/Context.h
   trunk/OpenPGPminidriver/ContextManagement.c
   trunk/OpenPGPminidriver/CryptoOperations.c
   trunk/OpenPGPminidriver/CryptoOperations.h
   trunk/OpenPGPminidriver/PinOperations.c
   trunk/OpenPGPminidriver/PublicDataOperations.c
   trunk/OpenPGPminidriverTest/CryptoOperations.cpp
   trunk/OpenPGPminidriverTest/Dialog.h
   trunk/OpenPGPminidriverTest/Dialog.rc
   trunk/OpenPGPminidriverTest/PINOperations.cpp
   trunk/OpenPGPminidriverTest/global.h
   trunk/OpenPGPminidriverTest/main.cpp
Log:
first beta version

Modified: trunk/OpenPGPminidriver/CardAndContainerProperties.c
===================================================================
--- trunk/OpenPGPminidriver/CardAndContainerProperties.c	2010-03-15 09:47:30 UTC (rev 9)
+++ trunk/OpenPGPminidriver/CardAndContainerProperties.c	2010-03-15 18:23:17 UTC (rev 10)
@@ -629,6 +629,7 @@
 )
 {
 	DWORD dwReturn = 0;	
+	POPENPGP_CONTEXT pContext = NULL;
 	Trace(WINEVENT_LEVEL_VERBOSE, L"Enter wszProperty = %s", wszProperty);
 	__try
 	{
@@ -644,6 +645,12 @@
 			dwReturn  = SCARD_E_INVALID_PARAMETER;
 			__leave;
 		}
+		dwReturn = CheckContext(pCardData);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
 		if (wcscmp(wszProperty,CP_CARD_FREE_SPACE) == 0
 			|| wcscmp(wszProperty,CP_CARD_CAPABILITIES) == 0
 			|| wcscmp(wszProperty,CP_CARD_KEYSIZES) == 0
@@ -707,7 +714,21 @@
 				dwReturn  = SCARD_E_INVALID_PARAMETER;
 				__leave;
 			}
-			dwReturn  = SCARD_W_SECURITY_VIOLATION;
+			if ( cbDataLen != sizeof(BOOL) )
+			{
+				Trace(WINEVENT_LEVEL_ERROR, L"cbDataLen == %d", cbDataLen);
+				dwReturn  = SCARD_E_INVALID_PARAMETER ;
+				__leave;
+			}
+			if (pContext->fDoesTheAdminHasBeenAuthenticatedAtLeastOnce)
+			{
+				pContext->fIsReadOnly = *((PBOOL) pbData);
+				dwReturn = 0;
+			}
+			else
+			{
+				dwReturn  = SCARD_W_SECURITY_VIOLATION;
+			}
 		}
 		else  if (wcscmp(wszProperty,CP_PARENT_WINDOW) == 0)
 		{
@@ -729,7 +750,7 @@
 				dwReturn  = SCARD_E_INVALID_PARAMETER ;
 				__leave;
 			}
-			if ( *pbData != 0)
+			if ( *((HWND*)pbData) != 0)
 			{
 				if (IsWindow( *((HWND*)pbData)) == 0)
 				{

Modified: trunk/OpenPGPminidriver/CardCryptographicOperations.c
===================================================================
--- trunk/OpenPGPminidriver/CardCryptographicOperations.c	2010-03-15 09:47:30 UTC (rev 9)
+++ trunk/OpenPGPminidriver/CardCryptographicOperations.c	2010-03-15 18:23:17 UTC (rev 10)
@@ -136,14 +136,8 @@
 			dwReturn  = SCARD_E_INVALID_PARAMETER;
 			__leave;
 		}
-		if (pInfo->dwKeySpec == AT_KEYEXCHANGE)
+		if (pInfo->dwKeySpec != AT_SIGNATURE && pInfo->dwKeySpec != AT_KEYEXCHANGE)
 		{
-			Trace(WINEVENT_LEVEL_ERROR, L"AT_KEYEXCHANGE %d", pInfo->dwKeySpec);
-			dwReturn  = SCARD_E_NO_KEY_CONTAINER ;
-			__leave;
-		}
-		if (pInfo->dwKeySpec != AT_SIGNATURE)
-		{
 			Trace(WINEVENT_LEVEL_ERROR, L"AT_SIGNATURE %d", pInfo->dwKeySpec);
 			dwReturn  = SCARD_E_INVALID_PARAMETER ;
 			__leave;
@@ -156,6 +150,7 @@
 		switch(pInfo->bContainerIndex)
 		{
 		case ContainerAuthentication:
+		case ContainerConfidentiality:
 			dwReturn = OCardAuthenticate(pCardData, pInfo);
 			break;
 		case ContainerSignature:

Modified: trunk/OpenPGPminidriver/Context.h
===================================================================
--- trunk/OpenPGPminidriver/Context.h	2010-03-15 09:47:30 UTC (rev 9)
+++ trunk/OpenPGPminidriver/Context.h	2010-03-15 18:23:17 UTC (rev 10)
@@ -65,8 +65,11 @@
 	BOOL					fHasKey[KEYMAX];
 	BOOL					fIsReadOnly;
 	BYTE					bFingerPrint[60];
-	PBYTE					pbKeyCache[KEYMAX];
-	DWORD					dwKeyCacheSize[KEYMAX];
+	PBYTE					pbModulusInLittleEndian[KEYMAX];
+	WORD					dwModulusSizeInBytes[KEYMAX];
+	DWORD					dwExponent[KEYMAX];
+	LARGE_INTEGER			LastCacheCheck[KEYMAX];
+	BOOL					fDoesTheAdminHasBeenAuthenticatedAtLeastOnce;
 } OPENPGP_CONTEXT, *POPENPGP_CONTEXT ;
 
 DWORD CreateContext(__in PCARD_DATA pCardData, __in DWORD dwFlags);

Modified: trunk/OpenPGPminidriver/ContextManagement.c
===================================================================
--- trunk/OpenPGPminidriver/ContextManagement.c	2010-03-15 09:47:30 UTC (rev 9)
+++ trunk/OpenPGPminidriver/ContextManagement.c	2010-03-15 18:23:17 UTC (rev 10)
@@ -197,13 +197,22 @@
 
 DWORD CleanContext(__in PCARD_DATA pCardData)
 {
-	DWORD dwReturn = 0;
+	DWORD dwReturn = 0, dwI;
 	__try
 	{
 		if (pCardData)
 		{
 			if ( pCardData->pvVendorSpecific)
 			{
+				POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
+				for(dwI = 0; dwI < KeyMax; dwI++)
+				{
+					if (pContext->pbModulusInLittleEndian[dwI] != NULL)
+					{
+						pCardData->pfnCspFree(pContext->pbModulusInLittleEndian[dwI]);
+						pContext->pbModulusInLittleEndian[dwI] = NULL;
+					}
+				}
 				pCardData->pfnCspFree( pCardData->pvVendorSpecific);
 				pCardData->pvVendorSpecific = NULL;
 			}
@@ -362,11 +371,11 @@
 				}
 			}
 		}
-		dwReturn = CCIDgetFeatures(pCardData);
+		/*dwReturn = CCIDgetFeatures(pCardData);
 		if (dwReturn)
 		{
 			__leave;
-		}
+		}*/
 		dwReturn = 0;
 	}
 	__finally

Modified: trunk/OpenPGPminidriver/CryptoOperations.c
===================================================================
--- trunk/OpenPGPminidriver/CryptoOperations.c	2010-03-15 09:47:30 UTC (rev 9)
+++ trunk/OpenPGPminidriver/CryptoOperations.c	2010-03-15 18:23:17 UTC (rev 10)
@@ -29,15 +29,15 @@
 OPENPGP_KEY_INFO Keys[] = 
 {
 	{0xB6, 0xCE, 0xC7, CALG_RSA_SIGN}, // signature
- 	{0xA4, 0xD0, 0xC9, CALG_RSA_SIGN}, // authentication
-	{0xB8, 0xCF, 0xC8, CALG_RSA_KEYX}  // confidentiality
+ 	{0xB8, 0xCF, 0xC8, CALG_RSA_KEYX}, // confidentiality
+	{0xA4, 0xD0, 0xC9, CALG_RSA_SIGN}  // authentication
 };
 
 OPENPGP_CONTAINER_INFO Containers[] = 
 {
 	{ROLE_SIGNATURE, AT_SIGNATURE},
-	{ROLE_AUTHENTICATION, AT_SIGNATURE},
-	{ROLE_CONFIDENTIALITY, AT_KEYEXCHANGE}
+	{ROLE_CONFIDENTIALITY, AT_KEYEXCHANGE},
+	{ROLE_AUTHENTICATION, AT_SIGNATURE}
 };
 typedef struct _OPENPGP_SUPPORTED_SIGNATURE_ALGORITHM
 {
@@ -57,6 +57,7 @@
 BYTE dwSHA512EncodedOid[] = {0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
 			0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
 
+#define OPENPGP_NO_OID 0xFFFFFFFF
 OPENPGP_SUPPORTED_SIGNATURE_ALGORITHM SignatureAlgorithm[] = 
 {
 	{CALG_SHA1,20, 
@@ -103,10 +104,10 @@
 			szAlgorithmAttributes = szOpenPGPAlgoAttributesSignature;
 			break;
 		case KeyAuthentication:
-			szAlgorithmAttributes = szOpenPGPAlgoAttributesDecryption;
+			szAlgorithmAttributes = szOpenPGPAlgoAttributesAuthentication;
 			break;
 		case KeyConfidentiality:
-			szAlgorithmAttributes = szOpenPGPAlgoAttributesAuthentication;
+			szAlgorithmAttributes = szOpenPGPAlgoAttributesDecryption;
 			break;
 		default:
 			dwReturn = SCARD_E_NO_KEY_CONTAINER;
@@ -159,10 +160,10 @@
 			szAlgorithmAttributes = szOpenPGPAlgoAttributesSignature;
 			break;
 		case KeyAuthentication:
-			szAlgorithmAttributes = szOpenPGPAlgoAttributesDecryption;
+			szAlgorithmAttributes = szOpenPGPAlgoAttributesAuthentication;
 			break;
 		case KeyConfidentiality:
-			szAlgorithmAttributes = szOpenPGPAlgoAttributesAuthentication;
+			szAlgorithmAttributes = szOpenPGPAlgoAttributesDecryption;
 			break;
 		default:
 			dwReturn = SCARD_E_NO_KEY_CONTAINER;
@@ -185,7 +186,7 @@
 	__finally
 	{
 	}
-	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X for key = %d",dwReturn, dwKey);
 	return dwReturn;
 }
 
@@ -370,56 +371,63 @@
 	__finally
 	{
 	}
-	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X for key = %d", dwReturn, dwKey);
 	return dwReturn;
 }
 
-DWORD UpdateGenerationDateTime(__in PCARD_DATA pCardData, __in OPENPGP_KEY dwKey,
+DWORD CreateGenerationDateTime(__in PCARD_DATA pCardData,
 							   __out PDWORD pdwSecondsSince1970)
 {
-	DWORD dwReturn = 0;
 	LARGE_INTEGER UnixZeroTime = {0}, WindowsTime;
 	SYSTEMTIME WindowsSystemTime;
 	FILETIME WindowsFileTime;
+	UnixZeroTime.QuadPart = 116444736000000000I64; // january 1st 1970
+	GetSystemTime(&WindowsSystemTime);
+	SystemTimeToFileTime(&WindowsSystemTime, &WindowsFileTime);
+	/* It is not recommended that you add and subtract values from the FILETIME
+	structure to obtain relative times. Instead, you should copy the low- and high-order
+	parts of the file time to a ULARGE_INTEGER  structure, perform 64-bit arithmetic
+	on the QuadPart member, and copy the LowPart and HighPart  members into the 
+	FILETIME structure.
+
+	Do not cast a pointer to a FILETIME structure to either a ULARGE_INTEGER* 
+	or __int64* value because it can cause alignment faults on 64-bit Windows.
+	*/
+	WindowsTime.HighPart = WindowsFileTime.dwHighDateTime;
+	WindowsTime.LowPart = WindowsFileTime.dwLowDateTime;
+	*pdwSecondsSince1970 = (DWORD)((WindowsTime.QuadPart - UnixZeroTime.QuadPart) / 10000000);
+	return 0;
+}
+
+
+DWORD UpdateGenerationDateTime(__in PCARD_DATA pCardData, __in OPENPGP_KEY dwKey,
+							   __out DWORD dwSecondsSince1970)
+{
+	DWORD dwReturn = 0;
+	
 	BYTE pbCommand[] = {0x00, 0xDA, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00};
 	DWORD dwCommandSize = ARRAYSIZE(pbCommand);
 	__try
 	{
-		UnixZeroTime.QuadPart = 116444736000000000I64; // january 1st 1970
-		GetSystemTime(&WindowsSystemTime);
-		SystemTimeToFileTime(&WindowsSystemTime, &WindowsFileTime);
-		/* It is not recommended that you add and subtract values from the FILETIME
-		structure to obtain relative times. Instead, you should copy the low- and high-order
-		parts of the file time to a ULARGE_INTEGER  structure, perform 64-bit arithmetic
-		on the QuadPart member, and copy the LowPart and HighPart  members into the 
-		FILETIME structure.
-
-		Do not cast a pointer to a FILETIME structure to either a ULARGE_INTEGER* 
-		or __int64* value because it can cause alignment faults on 64-bit Windows.
-		*/
-		WindowsTime.HighPart = WindowsFileTime.dwHighDateTime;
-		WindowsTime.LowPart = WindowsFileTime.dwLowDateTime;
-		*pdwSecondsSince1970 = (DWORD)((WindowsTime.QuadPart - UnixZeroTime.QuadPart) / 10000000);
 		
+		
 		pbCommand[3] = Keys[dwKey].bDateTimeTag;
-		pbCommand[5] = (BYTE) (*pdwSecondsSince1970 / 0x1000000);
-		pbCommand[6] = (BYTE) ((*pdwSecondsSince1970 % 0x1000000) / 0x10000);
-		pbCommand[7] = (BYTE) ((*pdwSecondsSince1970 % 0x10000) / 0x100);
-		pbCommand[8] = (BYTE) ((*pdwSecondsSince1970 % 0x100) / 0x1);
+		pbCommand[5] = (BYTE) (dwSecondsSince1970 / 0x1000000);
+		pbCommand[6] = (BYTE) ((dwSecondsSince1970 % 0x1000000) / 0x10000);
+		pbCommand[7] = (BYTE) ((dwSecondsSince1970 % 0x10000) / 0x100);
+		pbCommand[8] = (BYTE) ((dwSecondsSince1970 % 0x100) / 0x1);
 		dwReturn = OCardSendCommand(pCardData, pbCommand, dwCommandSize);
 	}
 	__finally
 	{
 	}
-	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X for key = %d",dwReturn,dwKey);
 	return dwReturn;
 }
 
-DWORD UpdateFingerPrint(__in PCARD_DATA pCardData, __in OPENPGP_KEY dwKey, 
+DWORD CreateFingerPrint(__in PCARD_DATA pCardData, __in OPENPGP_KEY dwKey, 
 						__in DWORD dwSecondsSince1970,
-						__in PBYTE pbModulus, __in DWORD dwModulusSizeInBit,
-						__in BOOL fIsModulusInBigEndian,
-						__in DWORD dwExponent)
+						__inout BYTE pbFingerPrint[20])
 {
 	// modulus in input are in big endian
 	// rfc4880 12.2
@@ -429,12 +437,15 @@
 	DWORD dwOffset = 0;
 	HCRYPTPROV hProv = 0;
 	HCRYPTHASH hHash = 0;
-	BYTE pbCommand[25] = {0x00, 0xDA, 0x00, 0x00, 0x14};
-	DWORD dwCommandSize = ARRAYSIZE(pbCommand);
-	DWORD dwHashLen = 0x14;
+	POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
+	DWORD dwHashLen = 0x14, dwModulusSizeInBytes, dwModulusSizeInBit, dwExponent;
+	DWORD dwI;
 	__try
 	{
-		dwBufferSize = dwModulusSizeInBit / 8 + sizeof(DWORD) + 10  + 3;
+		dwModulusSizeInBytes = pContext->dwModulusSizeInBytes[dwKey];
+		dwModulusSizeInBit = dwModulusSizeInBytes * 8;
+		dwExponent = pContext->dwExponent[dwKey];
+		dwBufferSize = dwModulusSizeInBytes + sizeof(DWORD) + 10  + 3;
 		pbBuffer = (PBYTE) pCardData->pfnCspAlloc(dwBufferSize);
 		if (!pbBuffer)
 		{
@@ -442,6 +453,7 @@
 			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
 			__leave;
 		}
+		
 		pbBuffer[dwOffset++] = 0x99;
 		// -3 because of the header size
 		pbBuffer[dwOffset++] = (BYTE) ((dwBufferSize-3) / 0x100);
@@ -459,18 +471,11 @@
 		// size of modulus
 		pbBuffer[dwOffset++] = (BYTE) ((dwModulusSizeInBit % 0x10000) / 0x100);
 		pbBuffer[dwOffset++] = (BYTE) ((dwModulusSizeInBit % 0x100) / 0x1);
-		if (fIsModulusInBigEndian)
+		// little endian => big endian
+		for(dwI = 0; dwI < dwModulusSizeInBytes; dwI++)
 		{
-			memcpy(pbBuffer + dwOffset, pbModulus, dwModulusSizeInBit / 8);
+			pbBuffer[dwOffset + dwI] = pContext->pbModulusInLittleEndian[dwKey][dwModulusSizeInBytes - 1 - dwI];
 		}
-		else
-		{
-			DWORD dwI;
-			for(dwI = 0; dwI < dwModulusSizeInBit / 8; dwI++)
-			{
-				pbBuffer[dwOffset + dwI] = pbModulus[dwModulusSizeInBit / 8 - 1 - dwI];
-			}
-		}
 		// size of exponent
 		pbBuffer[dwOffset++] = 0;
 		pbBuffer[dwOffset++] = sizeof(DWORD);
@@ -499,13 +504,12 @@
 			Trace(WINEVENT_LEVEL_ERROR, L"CryptHashData 0x%08X", dwReturn);
 			__leave;
 		}
-		if(!CryptGetHashParam(hHash, HP_HASHVAL, pbCommand + 5, &dwHashLen, 0)) {
+		if(!CryptGetHashParam(hHash, HP_HASHVAL, pbFingerPrint, &dwHashLen, 0)) {
 			dwReturn = GetLastError();
 			Trace(WINEVENT_LEVEL_ERROR, L"CryptGetHashParam 0x%08X", dwReturn);
 			__leave;
 		}
-		pbCommand[3] = Keys[dwKey].bSignatureTag;
-		dwReturn = OCardSendCommand(pCardData, pbCommand, dwCommandSize);
+		
 
 	}
 	__finally
@@ -518,16 +522,32 @@
 			CryptReleaseContext(hProv,0);
 
 	}
-	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X for key = %d",dwReturn, dwKey);
 	return dwReturn;
 
 }
 
-DWORD OCardReadPublicKey(PCARD_DATA pCardData, OPENPGP_KEY dwKey, PBYTE *pbPublicKey, PDWORD pdwPublicKeySize)
+DWORD UpdateFingerPrint(__in PCARD_DATA pCardData, __in OPENPGP_KEY dwKey, 
+						__inout BYTE pbFingerPrint[20])
 {
-	DWORD dwReturn;
+	BYTE pbCommand[25] = {0x00, 0xDA, 0x00, 0x00, 0x14};
+	DWORD dwCommandSize = ARRAYSIZE(pbCommand), dwReturn;
+	__try
+	{
+		pbCommand[3] = Keys[dwKey].bSignatureTag;
+		memcpy(pbCommand + 5, pbFingerPrint, 20);
+		dwReturn = OCardSendCommand(pCardData, pbCommand, dwCommandSize);
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X for key = %d",dwReturn,dwKey);
+	return dwReturn;
+}
+DWORD OCardUpdateCachedPublicKey(__in PCARD_DATA pCardData, __in OPENPGP_KEY dwKey)
+{
 	PBYTE pbData = NULL;
-	DWORD dwResponseSize = 0;
+	DWORD dwResponseSize = 0, dwReturn;
 	BYTE pbCmd[] = {0x00, 
 				    0x47,
 					0x81,
@@ -541,12 +561,12 @@
 					0x00
 					};
 	DWORD dwCmdSize;
-	POPENPGP_CONTEXT pContext;
+	DWORD dwTotalTlvSize, dwOffset;
+	DWORD dwModulusSizeInBytes;
 	PBYTE pbModulus;
-	DWORD dwModulusSize, dwI;
+	DWORD dwI;
 	PBYTE pbExponent;
-	PRSAPUBLICKEYBLOB pbBlob = NULL;
-	DWORD dwTotalTlvSize, dwOffset;
+	POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
 	__try
 	{
 		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwKey=%d",dwKey);
@@ -556,7 +576,11 @@
 			Trace(WINEVENT_LEVEL_INFO, L"SCARD_E_NO_KEY_CONTAINER %d", dwKey);
 			__leave;
 		}
-		pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
+		if (pContext->pbModulusInLittleEndian[dwKey] != NULL)
+		{
+			pCardData->pfnCspFree(pContext->pbModulusInLittleEndian[dwKey]);
+			pContext->pbModulusInLittleEndian[dwKey] = NULL;
+		}
 		pbCmd[7] = Keys[dwKey].bKeyTag;
 		dwCmdSize = 9;
 		if (pContext->fExtentedLeLcFields)
@@ -576,7 +600,7 @@
 		}
 		dwOffset = 2;
 		dwTotalTlvSize = getTlvSize(pbData + 2,&dwOffset) + 2;
-		if (!find_tlv(pbData + dwOffset,0x81,dwTotalTlvSize,&pbModulus,&dwModulusSize))
+		if (!find_tlv(pbData + dwOffset,0x81,dwTotalTlvSize,&pbModulus,&dwModulusSizeInBytes))
 		{
 			dwReturn = SCARD_E_UNEXPECTED;
 			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_UNEXPECTED 0x81");
@@ -588,8 +612,167 @@
 			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_UNEXPECTED 0x81");
 			__leave;
 		}
-		Trace(WINEVENT_LEVEL_INFO, L"dwModulusSize %d bits", dwModulusSize * 8);
-		*pdwPublicKeySize = sizeof(RSAPUBLICKEYBLOB) + dwModulusSize - sizeof(DWORD);
+		Trace(WINEVENT_LEVEL_INFO, L"dwModulusSize %d bits", dwModulusSizeInBytes * 8);
+		
+		pContext->dwExponent[dwKey] = pbExponent[0] * 0x1000000  + pbExponent[1] * 0x10000  + pbExponent[2] * 0x100 + pbExponent[3];
+		pContext->pbModulusInLittleEndian[dwKey] = pCardData->pfnCspAlloc(dwModulusSizeInBytes);
+		if (!pContext->pbModulusInLittleEndian[dwKey])
+		{
+			dwReturn = SCARD_E_NO_MEMORY;
+			Trace(WINEVENT_LEVEL_INFO, L"SCARD_E_NO_MEMORY");
+			__leave;
+		}
+		// convert big endian into little endian
+		for (dwI = 0; dwI < dwModulusSizeInBytes; dwI++)
+		{
+			pContext->pbModulusInLittleEndian[dwKey][dwI] = pbModulus[dwModulusSizeInBytes - 1 - dwI];
+		}
+		pContext->dwModulusSizeInBytes[dwKey] = (WORD) dwModulusSizeInBytes;
+		dwReturn = 0;
+	}
+	__finally
+	{
+		if (pbData)
+			pCardData->pfnCspFree(pbData);
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+DWORD OCardUpdateCachedPublicKeyIfNeeded(__in PCARD_DATA pCardData, __in OPENPGP_KEY dwKey)
+{
+	PBYTE pbFingerPrint = NULL;
+	DWORD dwFingerPrintSize, dwReturn;
+	BOOL fHasToUpdateTheCache;
+	POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
+	LARGE_INTEGER Now;
+	SYSTEMTIME WindowsSystemTime;
+	FILETIME WindowsFileTime;
+	__try
+	{
+		GetSystemTime(&WindowsSystemTime);
+		SystemTimeToFileTime(&WindowsSystemTime, &WindowsFileTime);
+		Now.HighPart = WindowsFileTime.dwHighDateTime;
+		Now.LowPart = WindowsFileTime.dwLowDateTime;
+		// last read less than 0,2 s
+		if ((Now.QuadPart - pContext->LastCacheCheck[dwKey].QuadPart) < 2000000)
+		{
+			Trace(WINEVENT_LEVEL_INFO, L"Cache up to date");
+			pContext->LastCacheCheck[dwKey] = Now;
+			dwReturn = 0;
+			__leave;
+		}
+		Trace(WINEVENT_LEVEL_INFO, L"Updating cache");
+		// try to use the cache
+		dwReturn = OCardReadFile(pCardData, szOpenPGPDir, szOpenPGPFingerprint, &pbFingerPrint, &dwFingerPrintSize);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		if (dwFingerPrintSize != 60)
+		{
+			Trace(WINEVENT_LEVEL_ERROR, L"dwFingerPrintSize = %02X", dwFingerPrintSize);
+			dwReturn = SCARD_E_UNEXPECTED;
+			__leave;
+		}
+		// determine if we have to retrieve the modulus from the card
+		if (memcmp(pbFingerPrint + dwKey * 20, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) == 0)
+		{
+			// no public key => why want to read it ?
+			Trace(WINEVENT_LEVEL_ERROR, L"pbFingerPrint null for key %d", dwKey);
+			dwReturn = SCARD_E_NO_KEY_CONTAINER;
+			if (pContext->pbModulusInLittleEndian[dwKey])
+			{
+				pCardData->pfnCspFree(pContext->pbModulusInLittleEndian[dwKey]);
+				pContext->pbModulusInLittleEndian[dwKey] = NULL;
+			}
+			pContext->fHasKey[dwKey] = FALSE;
+			__leave;
+		}
+		if (memcmp(pbFingerPrint + dwKey * 20, pContext->bFingerPrint + dwKey * 20, 20) == 0)
+		{
+			if (pContext->pbModulusInLittleEndian[dwKey])
+			{
+				fHasToUpdateTheCache = FALSE;
+			}
+			else
+			{
+				fHasToUpdateTheCache = TRUE;
+			}
+		}
+		else
+		{
+			fHasToUpdateTheCache = TRUE;
+		}
+		if (fHasToUpdateTheCache)
+		{
+			dwReturn = OCardUpdateCachedPublicKey(pCardData, dwKey);
+			if (dwReturn)
+			{
+				__leave;
+			}
+		}
+		pContext->LastCacheCheck[dwKey] = Now;
+	}
+	__finally
+	{
+		if (pbFingerPrint)
+			pCardData->pfnCspFree(pbFingerPrint);
+	}
+	return dwReturn;
+}
+
+DWORD OCardGetKeyLengthInBytes(__in PCARD_DATA pCardData, __in OPENPGP_KEY dwKey, __out PDWORD pdwLengthInBytes)
+{
+	DWORD dwReturn;
+	POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
+	__try
+	{
+		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwKey=%d",dwKey);
+		if (dwKey >= KeyMax)
+		{
+			dwReturn = SCARD_E_NO_KEY_CONTAINER;
+			Trace(WINEVENT_LEVEL_INFO, L"SCARD_E_NO_KEY_CONTAINER %d", dwKey);
+			__leave;
+		}
+		dwReturn = OCardUpdateCachedPublicKeyIfNeeded(pCardData, dwKey);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		*pdwLengthInBytes = pContext->dwModulusSizeInBytes[dwKey];
+		Trace(WINEVENT_LEVEL_VERBOSE, L"modulus size in bits= %d",*pdwLengthInBytes*8);
+	}
+	__finally
+	{
+	}
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	return dwReturn;
+}
+
+DWORD OCardReadPublicKey(PCARD_DATA pCardData, OPENPGP_KEY dwKey, PBYTE *pbPublicKey, PDWORD pdwPublicKeySize)
+{
+	DWORD dwReturn;
+	POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
+	PRSAPUBLICKEYBLOB pbBlob = NULL;
+	DWORD dwModulusSizeInBytes;
+	__try
+	{
+		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwKey=%d",dwKey);
+		if (dwKey >= KeyMax)
+		{
+			dwReturn = SCARD_E_NO_KEY_CONTAINER;
+			Trace(WINEVENT_LEVEL_INFO, L"SCARD_E_NO_KEY_CONTAINER %d", dwKey);
+			__leave;
+		}
+		dwReturn = OCardUpdateCachedPublicKeyIfNeeded(pCardData, dwKey);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		dwModulusSizeInBytes = pContext->dwModulusSizeInBytes[dwKey];
+		Trace(WINEVENT_LEVEL_INFO, L"dwModulusSize %d bits", dwModulusSizeInBytes * 8);
+		*pdwPublicKeySize = sizeof(RSAPUBLICKEYBLOB) + dwModulusSizeInBytes - sizeof(DWORD);
 		*pbPublicKey = pCardData->pfnCspAlloc(*pdwPublicKeySize);
 		if (!*pbPublicKey)
 		{
@@ -604,21 +787,13 @@
 		pbBlob->blobheader.reserved = 0;
 		pbBlob->blobheader.aiKeyAlg = Keys[dwKey].aiKeyAlg;
 		pbBlob->rsapubkey.magic = 0x31415352; //'RSA1';
-		pbBlob->rsapubkey.bitlen = dwModulusSize*8;
-		pbBlob->rsapubkey.pubexp = pbExponent[0] * 0x1000000  + pbExponent[1] * 0x10000  + pbExponent[2] * 0x100 + pbExponent[3];
-		// convert big endian into little endian
-		//memcpy(pbBlob->modulus, pbModulus, dwModulusSize);
-		for (dwI = 0; dwI < dwModulusSize; dwI++)
-		{
-			pbBlob->modulus[dwI] = pbModulus[dwModulusSize - 1 - dwI];
-		}
-		
+		pbBlob->rsapubkey.bitlen = dwModulusSizeInBytes*8;
+		pbBlob->rsapubkey.pubexp = pContext->dwExponent[dwKey];
+		memcpy(pbBlob->modulus, pContext->pbModulusInLittleEndian[dwKey], dwModulusSizeInBytes);
 		dwReturn = 0;
 	}
 	__finally
 	{
-		if (pbData)
-			pCardData->pfnCspFree(pbData);
 	}
 	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
 	return dwReturn;
@@ -630,10 +805,10 @@
 	PBYTE pbData = NULL;
 	DWORD dwResponseSize = 0, dwCmdSize;
 	OPENPGP_ALGORITHM_ATTRIBUTE Attributes;
-	POPENPGP_CONTEXT pContext;
+	POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
 	DWORD dwSecondsSince1970;
 	PBYTE pbModulus, pbExponent;
-	DWORD dwModulusSize, dwExponent;
+	DWORD dwModulusSizeInBytes, dwExponent, dwI;
 	BYTE pbCmd[] = {0x00, 
 				    0x47,
 					0x80,
@@ -647,6 +822,7 @@
 					0x00
 					};
 	DWORD dwTotalTlvSize, dwOffset;
+	BYTE pbFingerPrint[20];
 	__try
 	{
 		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwKey=%d",dwKey);
@@ -657,19 +833,16 @@
 			__leave;
 		}
 		// key len
-		dwReturn = OCardGetKeyAlgorithmAttributes(pCardData, dwKey, &Attributes);
-		if (dwReturn)
-		{
-			__leave;
-		}
-		Attributes.wModulusLengthInBit = (WORD) dwBitLen;
+		Attributes.wModulusLengthInBit = (unsigned short)dwBitLen * 8;
+		Attributes.wExponentLengthInBit = 4 * 8;
+		Attributes.bAlgoId = 1;
+		Attributes.bFormat = 0;
 		dwReturn = OCardSetKeyAlgorithmAttributes(pCardData, dwKey, &Attributes);
 		if (dwReturn)
 		{
 			__leave;
 		}
 
-		pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
 		pbCmd[7] = Keys[dwKey].bKeyTag;
 		dwCmdSize = 9;
 		if (pContext->fExtentedLeLcFields)
@@ -689,7 +862,7 @@
 		}
 		dwOffset = 2;
 		dwTotalTlvSize = getTlvSize(pbData + 2,&dwOffset) + 2;
-		if (!find_tlv(pbData + dwOffset,0x81,dwTotalTlvSize, &pbModulus,&dwModulusSize))
+		if (!find_tlv(pbData + dwOffset,0x81,dwTotalTlvSize, &pbModulus,&dwModulusSizeInBytes))
 		{
 			dwReturn = SCARD_E_UNEXPECTED;
 			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_UNEXPECTED 0x81");
@@ -698,26 +871,62 @@
 		if (!find_tlv(pbData + dwOffset,0x82,dwTotalTlvSize, (PBYTE*)&pbExponent,NULL))
 		{
 			dwReturn = SCARD_E_UNEXPECTED;
-			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_UNEXPECTED 0x81");
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_UNEXPECTED 0x82");
 			__leave;
 		}
 		dwExponent = pbExponent[0] * 0x1000000  + pbExponent[1] * 0x10000  + pbExponent[2] * 0x100 + pbExponent[3];
-		dwReturn = UpdateGenerationDateTime(pCardData, dwKey, &dwSecondsSince1970);
+		// save in the cache
+		pContext->fHasKey[dwKey] = TRUE;
+		pContext->dwExponent[dwKey] = dwExponent;
+		pContext->dwModulusSizeInBytes[dwKey] = (WORD) dwModulusSizeInBytes;
+		if (pContext->pbModulusInLittleEndian[dwKey])
+		{
+			pCardData->pfnCspFree(pContext->pbModulusInLittleEndian[dwKey]);
+		}
+		pContext->pbModulusInLittleEndian[dwKey] = pCardData->pfnCspAlloc(dwModulusSizeInBytes);
+		if (!pContext->pbModulusInLittleEndian[dwKey])
+		{
+			dwReturn = SCARD_E_NO_MEMORY;
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
+			__leave;
+		}
+		for (dwI = 0; dwI < dwModulusSizeInBytes; dwI++)
+		{
+			pContext->pbModulusInLittleEndian[dwKey][dwI] = pbModulus[dwModulusSizeInBytes - 1 - dwI];
+		}
+		dwReturn = CreateGenerationDateTime(pCardData, &dwSecondsSince1970);
 		if (dwReturn)
 		{
 			__leave;
 		}
-		dwReturn = UpdateFingerPrint(pCardData, dwKey, dwSecondsSince1970, 
-										pbModulus,
-										dwModulusSize * 8,
-										TRUE,
-										dwExponent
-										);
+		dwReturn = CreateFingerPrint(pCardData, dwKey, dwSecondsSince1970, pbFingerPrint);
 		if (dwReturn)
 		{
 			__leave;
 		}
-		pContext->fHasKey[dwKey] = TRUE;
+		// avoid two key having the same fingerprint if generated too fast
+		while (memcmp(pbFingerPrint, pContext->bFingerPrint, 20) == 0
+			|| memcmp(pbFingerPrint, pContext->bFingerPrint + 20, 20) == 0
+			|| memcmp(pbFingerPrint, pContext->bFingerPrint + 40, 20) == 0)
+		{
+			dwSecondsSince1970++;
+			dwReturn = CreateFingerPrint(pCardData, dwKey, dwSecondsSince1970, pbFingerPrint);
+			if (dwReturn)
+			{
+				__leave;
+			}
+		}
+		dwReturn = UpdateGenerationDateTime(pCardData, dwKey, dwSecondsSince1970);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		dwReturn = UpdateFingerPrint(pCardData, dwKey, pbFingerPrint);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		memcpy(pContext->bFingerPrint + 20 * dwKey, pbFingerPrint, 20);
 	}
 	__finally
 	{
@@ -744,6 +953,7 @@
 	BYTE bCommand[] = {0x00,0xDB,0x3F,0xFF};
 	DWORD dwSecondsSince1970;
 	POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
+	BYTE pbFingerPrint[20];
 	__try
 	{
 		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",dwKey);
@@ -768,12 +978,10 @@
 			__leave;
 		}
 		
-		dwReturn = OCardGetKeyAlgorithmAttributes(pCardData, dwKey, &Attributes);
-		if (dwReturn)
-		{
-			__leave;
-		}
 		Attributes.wModulusLengthInBit = (WORD) pbPublicKeyBlob->rsapubkey.bitlen;
+		Attributes.wExponentLengthInBit = 4 * 8;
+		Attributes.bAlgoId = 1;
+		Attributes.bFormat = 0;
 		dwReturn = OCardSetKeyAlgorithmAttributes(pCardData, dwKey, &Attributes);
 		if (dwReturn)
 		{
@@ -818,22 +1026,55 @@
 		{
 			__leave;
 		}
-		dwReturn = UpdateGenerationDateTime(pCardData, dwKey, &dwSecondsSince1970);
+		// save in the cache
+		pContext->fHasKey[dwKey] = TRUE;
+		pContext->dwExponent[dwKey] = pbPublicKeyBlob->rsapubkey.pubexp;
+		pContext->dwModulusSizeInBytes[dwKey] = (WORD) pbPublicKeyBlob->rsapubkey.bitlen / 8;
+		if (pContext->pbModulusInLittleEndian[dwKey])
+		{
+			pCardData->pfnCspFree(pContext->pbModulusInLittleEndian[dwKey]);
+		}
+		pContext->pbModulusInLittleEndian[dwKey] = pCardData->pfnCspAlloc(pContext->dwModulusSizeInBytes[dwKey]);
+		if (!pContext->pbModulusInLittleEndian[dwKey])
+		{
+			dwReturn = SCARD_E_NO_MEMORY;
+			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY");
+			__leave;
+		}
+		memcpy(pContext->pbModulusInLittleEndian[dwKey],&(pbPublicKeyBlob->modulus),pContext->dwModulusSizeInBytes[dwKey]);
+		dwReturn = CreateGenerationDateTime(pCardData, &dwSecondsSince1970);
 		if (dwReturn)
 		{
 			__leave;
 		}
-		dwReturn = UpdateFingerPrint(pCardData, dwKey, dwSecondsSince1970, 
-										pbPublicKeyBlob->modulus,
-										pbPublicKeyBlob->rsapubkey.bitlen,
-										FALSE,
-										pbPublicKeyBlob->rsapubkey.pubexp
-										);
+		dwReturn = CreateFingerPrint(pCardData, dwKey, dwSecondsSince1970, pbFingerPrint);
 		if (dwReturn)
 		{
 			__leave;
 		}
-		pContext->fHasKey[dwKey] = TRUE;
+		// avoid two key having the same fingerprint if generated too fast
+		while (memcmp(pbFingerPrint, pContext->bFingerPrint, 20) == 0
+			|| memcmp(pbFingerPrint, pContext->bFingerPrint + 20, 20) == 0
+			|| memcmp(pbFingerPrint, pContext->bFingerPrint + 40, 20) == 0)
+		{
+			dwSecondsSince1970++;
+			dwReturn = CreateFingerPrint(pCardData, dwKey, dwSecondsSince1970, pbFingerPrint);
+			if (dwReturn)
+			{
+				__leave;
+			}
+		}
+		dwReturn = UpdateGenerationDateTime(pCardData, dwKey, dwSecondsSince1970);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		dwReturn = UpdateFingerPrint(pCardData, dwKey, pbFingerPrint);
+		if (dwReturn)
+		{
+			__leave;
+		}
+		memcpy(pContext->bFingerPrint + 20 * dwKey, pbFingerPrint, 20);
 	}
 	__finally
 	{
@@ -848,11 +1089,11 @@
 			pCardData->pfnCspFree(pbTlv);
 		}
 	}
-	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
+	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X for key = %d",dwReturn, dwKey);
 	return dwReturn;
 }
 
-DWORD OCardCheckSigningInfo(__in PCARD_SIGNING_INFO  pInfo, __out PDWORD pdwIndex)
+DWORD OCardCheckSigningInfo(__in PCARD_SIGNING_INFO  pInfo, __in BOOL fAllowNoOid, __out PDWORD pdwIndex)
 {
 	DWORD dwReturn, dwI;
 	__try
@@ -868,6 +1109,21 @@
 			if ( pInfo->dwPaddingType == CARD_PADDING_PKCS1)
 			{
 				BCRYPT_PKCS1_PADDING_INFO* padding = (BCRYPT_PKCS1_PADDING_INFO*) pInfo->pPaddingInfo;
+				if (padding->pszAlgId == NULL)
+				{
+					if (fAllowNoOid)
+					{
+						*pdwIndex = OPENPGP_NO_OID;
+						dwReturn = 0;
+						__leave;
+					}
+					else
+					{
+						Trace(WINEVENT_LEVEL_ERROR, L"alg not found %s", padding->pszAlgId);
+						dwReturn = SCARD_E_UNSUPPORTED_FEATURE;
+						__leave;
+					}
+				}
 				for(dwI = 0 ; dwI < dwSignatureAlgorithmCount ; dwI++)
 				{
 					if (wcscmp(SignatureAlgorithm[dwI].szAlgId,padding->pszAlgId) == 0)
@@ -940,8 +1196,7 @@
 	DWORD dwReturn;
 	PBYTE pbData = NULL;
 	DWORD dwCmdSize = 0, dwIndex, dwI;
-	POPENPGP_CONTEXT pContext;
-	OPENPGP_ALGORITHM_ATTRIBUTE Attributes;
+	POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
 	BYTE pbCmd[6 + 256 + 256] = {0x00, 
 				    0x2A,
 					0x9E,
@@ -952,33 +1207,25 @@
 	__try
 	{
 		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",pInfo->bContainerIndex);
-		dwReturn = OCardCheckSigningInfo(pInfo, &dwIndex);
-		if (dwReturn)
-		{
-			__leave;
-		}
 		if (pInfo->bContainerIndex != ContainerSignature)
 		{
 			dwReturn = SCARD_E_NO_KEY_CONTAINER;
 			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
 			__leave;
 		}
+		dwReturn = OCardCheckSigningInfo(pInfo, FALSE, &dwIndex);
+		if (dwReturn)
+		{
+			__leave;
+		}
 		if (pInfo->dwSigningFlags & CARD_BUFFER_SIZE_ONLY)
 		{
 			// optimisation :
 			// return the buffer size only
-			dwReturn = OCardGetKeyAlgorithmAttributes(pCardData, KeySignature, &Attributes);
-			if (dwReturn)
-			{
-				__leave;
-			}
-			pInfo->cbSignedData = Attributes.wModulusLengthInBit/8;
-			dwReturn = 0;
+			dwReturn = OCardGetKeyLengthInBytes(pCardData, pInfo->bContainerIndex, &pInfo->cbSignedData);
 			__leave;
 		}
 
-		pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
-
 		dwCmdSize = 5;
 		if (pContext->fExtentedLeLcFields)
 		{
@@ -1033,15 +1280,56 @@
 	Trace(WINEVENT_LEVEL_VERBOSE, L"dwReturn = 0x%08X",dwReturn);
 	return dwReturn;
 }
-
+DWORD OCardIsConfidentialityKeyTheSameThanAuthentication(__in PCARD_DATA pCardData)
+{
+	DWORD dwReturn;
+	POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
+	__try
+	{
+	// see if the confidentiality key is the same than the authentication key
+			// if yes, confidentiality key can sign
+			// else ... we don't follow ms guidelines which requiers every container
+			// to be able to sign data
+			dwReturn = OCardUpdateCachedPublicKeyIfNeeded(pCardData, ContainerAuthentication);
+			if (dwReturn)
+			{
+				__leave;
+			}
+			dwReturn = OCardUpdateCachedPublicKeyIfNeeded(pCardData, ContainerConfidentiality);
+			if (dwReturn)
+			{
+				__leave;
+			}
+			if (pContext->dwModulusSizeInBytes[ContainerAuthentication]
+							!= pContext->dwModulusSizeInBytes[ContainerConfidentiality])
+			{
+				dwReturn = SCARD_E_NO_KEY_CONTAINER;
+				Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER");
+				__leave;
+			}
+			if (memcmp(pContext->pbModulusInLittleEndian[ContainerAuthentication],
+				pContext->pbModulusInLittleEndian[ContainerConfidentiality],
+				pContext->dwModulusSizeInBytes[ContainerConfidentiality]) != 0)
+			{
+				dwReturn = SCARD_E_NO_KEY_CONTAINER;
+				Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER");
+				__leave;
+			}
+			// if we are here, then the confidentiality key can sign using the authentication key
+			dwReturn = 0;
+	}
+	__finally
+	{
+	}
+	return dwReturn;
+}
 DWORD OCardAuthenticate(PCARD_DATA pCardData,
 				PCARD_SIGNING_INFO  pInfo)
 {
 	DWORD dwReturn;
 	PBYTE pbData = NULL;
 	DWORD dwCmdSize = 0, dwIndex, dwI;
-	POPENPGP_CONTEXT pContext;
-	OPENPGP_ALGORITHM_ATTRIBUTE Attributes;
+	POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
 	BYTE pbCmd[6 + 256 + 256] = {0x00, 
 				    0x88,
 					0x00,
@@ -1052,48 +1340,51 @@
 	__try
 	{
 		Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",pInfo->bContainerIndex);
-		dwReturn = OCardCheckSigningInfo(pInfo, &dwIndex);
-		if (dwReturn)
+		
+		if (pInfo->bContainerIndex != ContainerAuthentication && pInfo->bContainerIndex != ContainerConfidentiality)
 		{
-			__leave;
-		}
-		if (pInfo->bContainerIndex != ContainerAuthentication)
-		{
 			dwReturn = SCARD_E_NO_KEY_CONTAINER;
 			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_KEY_CONTAINER %d", pInfo->bContainerIndex);
 			__leave;
 		}
-		if (pInfo->dwSigningFlags & CARD_BUFFER_SIZE_ONLY)
+		if (pInfo->bContainerIndex == ContainerConfidentiality)
 		{
-			// optimisation :
-			// return the buffer size only
-			dwReturn = OCardGetKeyAlgorithmAttributes(pCardData, KeyAuthentication, &Attributes);
+			dwReturn = OCardIsConfidentialityKeyTheSameThanAuthentication(pCardData);
 			if (dwReturn)
 			{
 				__leave;
 			}
-			pInfo->cbSignedData = Attributes.wModulusLengthInBit/8;
-			dwReturn = 0;
+		}
+		dwReturn = OCardCheckSigningInfo(pInfo, TRUE, &dwIndex);
+		if (dwReturn)
+		{
 			__leave;
 		}
+		if (pInfo->dwSigningFlags & CARD_BUFFER_SIZE_ONLY)
+		{
+			// optimisation :
+			// return the buffer size only
+			dwReturn = OCardGetKeyLengthInBytes(pCardData, pInfo->bContainerIndex, &pInfo->cbSignedData);
+			__leave;
+		}
 
-		pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
-
 		dwCmdSize = 5;
 		if (pContext->fExtentedLeLcFields)
 		{
 			dwCmdSize++;
 		}
-		pbCmd[dwCmdSize++] = (BYTE) (SignatureAlgorithm[dwIndex].dwEncodedOidSize + pInfo->cbData);
-		memcpy(pbCmd + dwCmdSize , SignatureAlgorithm[dwIndex].pbEncodedOid,SignatureAlgorithm[dwIndex].dwEncodedOidSize);
-		dwCmdSize += SignatureAlgorithm[dwIndex].dwEncodedOidSize;
-		/*for(dwI = 0 ; dwI < pInfo->cbData ; dwI++)
+		if (dwIndex == OPENPGP_NO_OID)
 		{
-			pbCmd[dwCmdSize + dwI] = pInfo->pbData[pInfo->cbData - dwI -1];
-		}*/
+			pbCmd[dwCmdSize++] = (BYTE) (pInfo->cbData);
+		}
+		else
+		{
+			pbCmd[dwCmdSize++] = (BYTE) (SignatureAlgorithm[dwIndex].dwEncodedOidSize + pInfo->cbData);
+			memcpy(pbCmd + dwCmdSize , SignatureAlgorithm[dwIndex].pbEncodedOid,SignatureAlgorithm[dwIndex].dwEncodedOidSize);
+			dwCmdSize += SignatureAlgorithm[dwIndex].dwEncodedOidSize;
+		}
 		memcpy(pbCmd + dwCmdSize, pInfo->pbData,pInfo->cbData);
 		dwCmdSize += pInfo->cbData;
-
 		
 		if (pContext->fExtentedLeLcFields)
 		{
@@ -1146,7 +1437,7 @@
 					0x86,
 					0x00,
 					};
-	POPENPGP_CONTEXT pContext;
+	POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
 	DWORD dwI;
 	OPENPGP_ALGORITHM_ATTRIBUTE Attributes;
 	__try
@@ -1176,7 +1467,6 @@
 			Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_INSUFFICIENT_BUFFER %d", pInfo->cbData);
 			__leave;
 		}
-		pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
 		dwCmdSize = 5;
 		if (pContext->fExtentedLeLcFields)
 		{
@@ -1250,7 +1540,7 @@
 {
 	DWORD dwReturn = 0;
 	POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
-	OPENPGP_ALGORITHM_ATTRIBUTE Attributes;
+	DWORD dwSizeInBits;
 	__try
 	{
 		PCONTAINER_MAP_RECORD pContainer = NULL;
@@ -1266,12 +1556,12 @@
 		pContainer = (PCONTAINER_MAP_RECORD) *ppbResponse;
 		memset(pContainer,0,sizeof(CONTAINER_MAP_RECORD) * ContainerMax);
 		
-		dwReturn = OCardGetKeyAlgorithmAttributes(pCardData, KeyAuthentication, &Attributes);
+		dwReturn = OCardGetKeyLengthInBytes(pCardData, KeyAuthentication, &dwSizeInBits);
 		if (dwReturn)
 		{
 			__leave;
 		}
-		pContainer[ContainerAuthentication].wSigKeySizeBits = Attributes.wModulusLengthInBit;
+		pContainer[ContainerAuthentication].wSigKeySizeBits = (WORD)dwSizeInBits * 8;
 		swprintf_s(pContainer[ContainerAuthentication].wszGuid,MAX_CONTAINER_NAME_LEN + 1,
 			L"OPENPGP_%02X%02X_%02X%02X_%02X%02X%02X%02X_Authenticate",
 			pContext->Aid.AidVersion[0],pContext->Aid.AidVersion[1],
@@ -1284,12 +1574,12 @@
 			fIsDefaultContainerSet = TRUE;
 		}
 
-		dwReturn = OCardGetKeyAlgorithmAttributes(pCardData, KeyConfidentiality, &Attributes);
+		dwReturn = OCardGetKeyLengthInBytes(pCardData, KeyConfidentiality, &dwSizeInBits);
 		if (dwReturn)
 		{
 			__leave;
 		}
-		pContainer[ContainerConfidentiality].wKeyExchangeKeySizeBits = Attributes.wModulusLengthInBit;
+		pContainer[ContainerConfidentiality].wKeyExchangeKeySizeBits = (WORD)dwSizeInBits * 8;
 		swprintf_s(pContainer[ContainerConfidentiality].wszGuid,MAX_CONTAINER_NAME_LEN + 1,
 			L"OPENPGP_%02X%02X_%02X%02X_%02X%02X%02X%02X_Confidential",
 			pContext->Aid.AidVersion[0],pContext->Aid.AidVersion[1],
@@ -1306,12 +1596,12 @@
 			}
 		}
 
-		dwReturn = OCardGetKeyAlgorithmAttributes(pCardData, KeySignature, &Attributes);
+		dwReturn = OCardGetKeyLengthInBytes(pCardData, KeySignature, &dwSizeInBits);
 		if (dwReturn)
 		{
 			__leave;
 		}
-		pContainer[ContainerSignature].wSigKeySizeBits = Attributes.wModulusLengthInBit;
+		pContainer[ContainerSignature].wSigKeySizeBits = (WORD)dwSizeInBits * 8;
 		swprintf_s(pContainer[ContainerSignature].wszGuid,MAX_CONTAINER_NAME_LEN + 1,
 			L"OPENPGP_%02X%02X_%02X%02X_%02X%02X%02X%02X_Signature",
 			pContext->Aid.AidVersion[0],pContext->Aid.AidVersion[1],

Modified: trunk/OpenPGPminidriver/CryptoOperations.h
===================================================================
--- trunk/OpenPGPminidriver/CryptoOperations.h	2010-03-15 09:47:30 UTC (rev 9)
+++ trunk/OpenPGPminidriver/CryptoOperations.h	2010-03-15 18:23:17 UTC (rev 10)
@@ -18,16 +18,16 @@
 typedef enum _OPENPGP_CONTAINER
 {
 	ContainerSignature,
+	ContainerConfidentiality,
 	ContainerAuthentication,
-	ContainerConfidentiality,
 	ContainerMax
 } OPENPGP_CONTAINER;
 
 typedef enum _OPENPGP_KEY
 {
 	KeySignature,
+	KeyConfidentiality,
 	KeyAuthentication,
-	KeyConfidentiality,
 	KeyMax
 } OPENPGP_KEY;
 
@@ -83,4 +83,9 @@
 				PCARD_RSA_DECRYPT_INFO  pInfo);
 
 DWORD OCardReadContainerMapFile(__in PCARD_DATA  pCardData, 
-					__in PBYTE* ppbResponse, __in PDWORD pdwResponseSize);
\ No newline at end of file
+					__in PBYTE* ppbResponse, __in PDWORD pdwResponseSize);
+
+DWORD OCardGetKeyLengthInBytes(__in PCARD_DATA pCardData, __in OPENPGP_KEY dwKey,
+							   __out PDWORD pdwLengthInBytes);
+
+DWORD OCardIsConfidentialityKeyTheSameThanAuthentication(__in PCARD_DATA pCardData);
\ No newline at end of file

Modified: trunk/OpenPGPminidriver/PinOperations.c
===================================================================
--- trunk/OpenPGPminidriver/PinOperations.c	2010-03-15 09:47:30 UTC (rev 9)
+++ trunk/OpenPGPminidriver/PinOperations.c	2010-03-15 18:23:17 UTC (rev 10)
@@ -133,6 +133,7 @@
 				__in_bcount(cbPin) PBYTE  pbPin, __in DWORD  cbPin)
 {
 	DWORD dwReturn;
+	POPENPGP_CONTEXT pContext = (POPENPGP_CONTEXT) pCardData->pvVendorSpecific;
 	// 256 because the size of the PIN must fit in a Byte
 	BYTE pbCmd[256 + 5] = {0x00, 
 				    0x20,
@@ -171,7 +172,10 @@
 			__leave;
 		}
 		Trace(WINEVENT_LEVEL_VERBOSE, L"Authentication successfull");
-			
+		if (PinId == ROLE_ADMIN)
+		{
+			pContext->fDoesTheAdminHasBeenAuthenticatedAtLeastOnce = TRUE;
+		}
 	}
 	__finally
 	{

Modified: trunk/OpenPGPminidriver/PublicDataOperations.c
===================================================================
--- trunk/OpenPGPminidriver/PublicDataOperations.c	2010-03-15 09:47:30 UTC (rev 9)
+++ trunk/OpenPGPminidriver/PublicDataOperations.c	2010-03-15 18:23:17 UTC (rev 10)
@@ -34,6 +34,7 @@
 #define OPENPGP_FILE_OPTIONAL 1
 #define OPENPGP_FILE_WRITE_ONLY 2
 #define OPENPGP_FILE_NULL_LENGHT_EQUALS_MISSING 4
+#define OPENPGP_FILE_CONF_IS_AUTH 8
 
 typedef struct _OPENPGP_FILE
 {
@@ -70,7 +71,8 @@
 	{NULL, szCARD_APPLICATION_FILE, Virtual, 0, 0, EveryoneReadAdminWriteAc},
 	{NULL, szCACHE_FILE, Virtual, 0, 0, EveryoneReadUserWriteAc},
 	{szBASE_CSP_DIR, szCONTAINER_MAP_FILE, Virtual, 0, 0, EveryoneReadUserWriteAc},
-	{szBASE_CSP_DIR, "ksc1", StoredOnSmartCard, 0x7F21, 0, EveryoneReadAdminWriteAc, OPENPGP_FILE_NULL_LENGHT_EQUALS_MISSING},
+	{szBASE_CSP_DIR, "ksc1", StoredOnSmartCard, 0x7F21, 0, EveryoneReadAdminWriteAc, OPENPGP_FILE_NULL_LENGHT_EQUALS_MISSING | OPENPGP_FILE_CONF_IS_AUTH},
+	{szBASE_CSP_DIR, "ksc2", StoredOnSmartCard, 0x7F21, 0, EveryoneReadAdminWriteAc, OPENPGP_FILE_NULL_LENGHT_EQUALS_MISSING},
 
 };
 
@@ -237,7 +239,7 @@
 					__in_opt PSTR szDirectory,
 					__in PBYTE* pbResponse, __in PDWORD pdwResponseSize)
 {
-	DWORD dwReturn = 0, dwReadFileReturn;
+	DWORD dwReturn = 0, dwTempReturn;
 	DWORD dwI, dwSize;
 	BOOL fDirectoryFound = FALSE;
 	BOOL fAddToOuput;
@@ -296,8 +298,8 @@
 					DWORD dwSize;
 					fAddToOuput = FALSE;
 					// check if the file exists and be read
-					dwReadFileReturn = OCardReadFile(pCardData, szDirectory, Files[dwI].szFile, &pbData, &dwSize);
-					if (!dwReadFileReturn)
+					dwTempReturn = OCardReadFile(pCardData, szDirectory, Files[dwI].szFile, &pbData, &dwSize);
+					if (!dwTempReturn)
 					{
 						pCardData->pfnCspFree(pbData);
 						if (dwSize > 0)
@@ -306,6 +308,14 @@
 						}
 					}
 				}
+				if (fAddToOuput && (Files[dwI].dwFlag & OPENPGP_FILE_CONF_IS_AUTH))
+				{
+					dwTempReturn = OCardIsConfidentialityKeyTheSameThanAuthentication(pCardData);
+					if (dwReturn)
+					{
+						fAddToOuput = FALSE;
+					}
+				}
 				if (fAddToOuput)
 				{
 					dwSize = (DWORD) strlen( Files[dwI].szFile) + 1;

Modified: trunk/OpenPGPminidriverTest/CryptoOperations.cpp
===================================================================
--- trunk/OpenPGPminidriverTest/CryptoOperations.cpp	2010-03-15 09:47:30 UTC (rev 9)
+++ trunk/OpenPGPminidriverTest/CryptoOperations.cpp	2010-03-15 18:23:17 UTC (rev 10)
@@ -37,11 +37,11 @@
 			dwKeySpec = AT_SIGNATURE;
 			PinId = ROLE_USER;
 			break;
-		case 1: //Authentication,
+		case 2: //Authentication,
 			dwKeySpec = AT_SIGNATURE;
 			PinId = 3;
 			break;
-		case 2: // Confidentiality,
+		case 1: // Confidentiality,
 			dwKeySpec = AT_KEYEXCHANGE;
 			PinId = 4;
 			break;
@@ -97,11 +97,11 @@
 			dwKeySpec = AT_SIGNATURE;
 			PinId = ROLE_USER;
 			break;
-		case 1: //Authentication,
+		case 2: //Authentication,
 			dwKeySpec = AT_SIGNATURE;
 			PinId = 3;
 			break;
-		case 2: // Confidentiality,
+		case 1: // Confidentiality,
 			dwKeySpec = AT_KEYEXCHANGE;
 			PinId = 4;
 			break;
@@ -251,11 +251,11 @@
 				dwKeySpec = AT_SIGNATURE;
 				PinId = ROLE_USER;
 				break;
-			case 1: //Authentication,
+			case 2: //Authentication,
 				dwKeySpec = AT_SIGNATURE;
 				PinId = 3;
 				break;
-			case 2: // Confidentiality,
+			case 1: // Confidentiality,
 				dwKeySpec = AT_KEYEXCHANGE;
 				PinId = 4;
 				break;
@@ -315,4 +315,21 @@
 			CryptReleaseContext(hProv,0);
 	}
 	return dwReturn;
+}
+DWORD SetReadOnly(BOOL fSet)
+{
+	DWORD dwReturn;
+	__try
+	{
+		if (!pCardData)
+		{
+			dwReturn = SCARD_E_COMM_DATA_LOST;
+			__leave;
+		}
+		dwReturn = pCardData->pfnCardSetProperty(pCardData, CP_CARD_READ_ONLY, (PBYTE) &fSet, sizeof(BOOL),0);
+	}
+	__finally
+	{
+	}
+	return dwReturn;
 }
\ No newline at end of file

Modified: trunk/OpenPGPminidriverTest/Dialog.h
===================================================================
--- trunk/OpenPGPminidriverTest/Dialog.h	2010-03-15 09:47:30 UTC (rev 9)
+++ trunk/OpenPGPminidriverTest/Dialog.h	2010-03-15 18:23:17 UTC (rev 10)
@@ -8,18 +8,20 @@
 #define IDD_PIN 1200
 #define IDC_PINUSER 1201
 #define IDC_PINADMIN 1202
+#define IDC_PUK 1208
 #define IDC_CHECKPIN 1203
 #define IDC_TXTPIN 1204
 #define IDC_TXTPIN2 1205
 #define IDC_CHANGEPIN 1206
 #define IDC_UNBLOCKPIN 1207
-#define IDC_PUK 1208
 #define IDC_BTN1 1209
 #define IDD_CRYPTO 1300
 #define IDC_SAMEKEY 1301
 #define IDC_IMPORTKEY 1302
 #define IDC_NEWKEY 1303
 #define IDC_CONTAINERINDEX 1304
+#define IDC_SETREADONLY 1305
+#define IDC_UNSETREADONLY 1306
 #define IDD_FILE 1400
 #define IDC_LISTFILES 1401
 #define IDC_STC2 1402

Modified: trunk/OpenPGPminidriverTest/Dialog.rc
===================================================================
--- trunk/OpenPGPminidriverTest/Dialog.rc	2010-03-15 09:47:30 UTC (rev 9)
+++ trunk/OpenPGPminidriverTest/Dialog.rc	2010-03-15 18:23:17 UTC (rev 10)
@@ -36,15 +36,17 @@
   CONTROL "Set Puk",IDC_BTN1,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,267,66,54,21
 END
 
-IDD_CRYPTO DIALOGEX 10,10,400,300
+IDD_CRYPTO DIALOGEX 0,0,400,300
 CAPTION "IDD_MAIN"
 FONT 8,"MS Sans Serif",0,0,0
 STYLE NOT WS_VISIBLE|WS_CHILDWINDOW
 BEGIN
-  CONTROL "Set same key",IDC_SAMEKEY,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,123,39,72,21
+  CONTROL "Set same key for all containers",IDC_SAMEKEY,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,150,18,105,36
   CONTROL "Import key",IDC_IMPORTKEY,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,42,63,72,21
   CONTROL "Generate new key",IDC_NEWKEY,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,42,39,72,21
   CONTROL "",IDC_CONTAINERINDEX,"ComboBox",WS_CHILD|WS_VISIBLE|WS_TABSTOP|CBS_DROPDOWNLIST,39,18,90,15
+  CONTROL "Set readonly",IDC_SETREADONLY,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,174,117,57,24
+  CONTROL "Unset readonly",IDC_UNSETREADONLY,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,174,147,57,24
 END
 
 IDD_FILE DIALOGEX 10,10,400,300

Modified: trunk/OpenPGPminidriverTest/PINOperations.cpp
===================================================================
--- trunk/OpenPGPminidriverTest/PINOperations.cpp	2010-03-15 09:47:30 UTC (rev 9)
+++ trunk/OpenPGPminidriverTest/PINOperations.cpp	2010-03-15 18:23:17 UTC (rev 10)
@@ -36,7 +36,7 @@
             pCardData,
             wszUserId,
             (PBYTE) szPin,
-            cbPin - 1,
+            cbPin,
             pcAttemptsRemaining);
     }
     __finally

Modified: trunk/OpenPGPminidriverTest/global.h
===================================================================
--- trunk/OpenPGPminidriverTest/global.h	2010-03-15 09:47:30 UTC (rev 9)
+++ trunk/OpenPGPminidriverTest/global.h	2010-03-15 18:23:17 UTC (rev 10)
@@ -30,4 +30,5 @@
 DWORD GenerateNewKey(DWORD dwIndex);
 DWORD ImportKey(DWORD dwIndex);
 DWORD SetTheSameKeyForAllContainers();
+DWORD SetReadOnly(BOOL fSet);
 #define OPENPGP_TEST_CONTAINER TEXT("Test_OPENPGPG")
\ No newline at end of file

Modified: trunk/OpenPGPminidriverTest/main.cpp
===================================================================
--- trunk/OpenPGPminidriverTest/main.cpp	2010-03-15 09:47:30 UTC (rev 9)
+++ trunk/OpenPGPminidriverTest/main.cpp	2010-03-15 18:23:17 UTC (rev 10)
@@ -315,8 +315,8 @@
 	{
 	case WM_INITDIALOG:
 		SendDlgItemMessage(hWnd,IDC_CONTAINERINDEX,CB_ADDSTRING,0,(LPARAM)TEXT("Signature"));
+		SendDlgItemMessage(hWnd,IDC_CONTAINERINDEX,CB_ADDSTRING,0,(LPARAM)TEXT("Confidentiality"));
 		SendDlgItemMessage(hWnd,IDC_CONTAINERINDEX,CB_ADDSTRING,0,(LPARAM)TEXT("Authentication"));
-		SendDlgItemMessage(hWnd,IDC_CONTAINERINDEX,CB_ADDSTRING,0,(LPARAM)TEXT("Confidentiality"));
 		SendDlgItemMessage(hWnd,IDC_CONTAINERINDEX, CB_SETCURSEL, 0, 0);
 		break;
 	case WM_COMMAND:
@@ -337,6 +337,14 @@
 				dwReturn = SetTheSameKeyForAllContainers();
 				MessageBoxWin32(dwReturn);
 				break;
+			case IDC_SETREADONLY:
+				dwReturn = SetReadOnly(TRUE);
+				MessageBoxWin32(dwReturn);
+				break;
+			case IDC_UNSETREADONLY:
+				dwReturn = SetReadOnly(FALSE);
+				MessageBoxWin32(dwReturn);
+				break;
 		}
 		break;
 	}



More information about the Openpgpmdrv-commits mailing list