1 /****************************************************************************
2 *																			*
3 *							cryptlib CryptoAPI Routines						*
4 *						Copyright Peter Gutmann 1998-2006					*
5 *																			*
6 ****************************************************************************/
7 
8 /* The following code is purely a test framework used to test the ability to
9    work with CryptoAPI keys.  Much of the code is only present as a rough
10    sketch.  It's not part of cryptlib, and shouldn't be used as a cryptlib
11    component */
12 
13 #if defined( INC_ALL )
14   #include "crypt.h"
15   #include "context.h"
16   #include "device.h"
17   #include "dev_mech.h"
18   #include "asn1.h"
19   #include "asn1_ext.h"
20 #else
21   #include "crypt.h"
22   #include "context/context.h"
23   #include "device/device.h"
24   #include "enc_dec/asn1.h"
25   #include "enc_dec/asn1_ext.h"
26   #include "mechs/dev_mech.h"
27 #endif /* Compiler-specific includes */
28 
29 /* The size of the (packed) header used for key blobs */
30 
31 #define BLOBHEADER_SIZE			8
32 
33 #ifdef USE_CRYPTOAPI
34 
35 #if defined( _MSC_VER )
36   #pragma message( "  Building with CAPI device interface enabled." )
37 #endif /* Warn with VC++ */
38 
39 /* The following define is needed to enable crypto functions in the include
40    file.  This would probably be defined by the compiler since it's not
41    defined in any header file, but it doesn't seem to be enabled by
42    default */
43 
44 #ifndef _WIN32_WINNT
45   #define _WIN32_WINNT	0x0500
46 #endif /* _WIN32_WINNT */
47 
48 /* cryptlib.h includes a trap for inclusion of wincrypt.h before cryptlib.h
49    which results in a compiler error if both files are included.  To disable
50    this, we need to undefine the CRYPT_MODE_ECB defined in cryptlib.h */
51 
52 #undef CRYPT_MODE_ECB
53 
54 #include <wincrypt.h>
55 
56 /* CryptoAPI uses the same mode names as cryptlib but different values,
57    fortunately this is done with #defines so we can remove them at this
58    point */
59 
60 #undef CRYPT_MODE_ECB
61 #undef CRYPT_MODE_CBC
62 #undef CRYPT_MODE_CFB
63 #undef CRYPT_MODE_CTR
64 
65 /* Symbolic defines to represent non-initialised values */
66 
67 #define CALG_NONE			0
68 #define HCRYPTPROV_NONE		0
69 
70 /* Some parts of CryptoAPI (inconsistently) require the use of Unicode,
71    winnls.h was already included via the global include of windows.h however
72    it isn't needed for any other part of cryptlib so it was disabled via
73    NONLS.  Since winnls.h is now locked out, we have to un-define the guards
74    used earlier to get it included */
75 
76 #undef _WINNLS_
77 #undef NONLS
78 #include <winnls.h>
79 
80 /* Older versions of wincrypt.h don't contain defines and typedefs that we
81    require.  Defines can be detected with #ifdef but typedefs can't, to
82    handle this we rely on checking for values that aren't defined in older
83    versions of wincrypt.h, which only go up to KP_PUB_EX_VAL */
84 
85 #ifndef KP_ADMIN_PIN
86   /* Misc values */
87   #define HCERTCHAINENGINE				void *
88   #define USAGE_MATCH_TYPE_AND			0
89   #define USAGE_MATCH_TYPE_OR			1
90   #define CERT_COMPARE_KEY_IDENTIFIER	15
91   #define CERT_FIND_KEY_IDENTIFIER		( CERT_COMPARE_KEY_IDENTIFIER << CERT_COMPARE_SHIFT )
92   #define CERT_CHAIN_CACHE_END_CERT					0x00000001
93   #define CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY	0x80000000
94   #define CRYPT_ACQUIRE_CACHE_FLAG					0x00000001
95 
96   /* Certificate chain match information */
97   typedef struct {
98 	DWORD dwType;
99 	CERT_ENHKEY_USAGE Usage;
100 	} CERT_USAGE_MATCH;
101   typedef struct {
102 	DWORD cbSize;
103 	CERT_USAGE_MATCH RequestedUsage;
104 	CERT_USAGE_MATCH RequestedIssuancePolicy;
105 	DWORD dwUrlRetrievalTimeout;
106 	BOOL fCheckRevocationFreshnessTime;
107 	DWORD dwRevocationFreshnessTime;
108 	} CERT_CHAIN_PARA, *PCERT_CHAIN_PARA;
109 
110   /* Certificate chain information */
111   typedef struct {
112 	DWORD dwErrorStatus;
113 	DWORD dwInfoStatus;
114 	} CERT_TRUST_STATUS, *PCERT_TRUST_STATUS;
115   typedef struct {
116 	DWORD cbSize;
117 	PCCERT_CONTEXT pCertContext;
118 	CERT_TRUST_STATUS TrustStatus;
119 	void *pRevocationInfo;		// PCERT_REVOCATION_INFO pRevocationInfo;
120 	void *pIssuanceUsage;		// PCERT_ENHKEY_USAGE pIssuanceUsage;
121 	void *pApplicationUsage;	// PCERT_ENHKEY_USAGE pApplicationUsage;
122 	LPCWSTR pwszExtendedErrorInfo;
123 	} CERT_CHAIN_ELEMENT, *PCERT_CHAIN_ELEMENT;
124   typedef struct {
125 	DWORD cbSize;
126 	PCTL_ENTRY pCtlEntry;
127 	PCCTL_CONTEXT pCtlContext;
128 	} CERT_TRUST_LIST_INFO, *PCERT_TRUST_LIST_INFO;
129   typedef struct {
130 	DWORD cbSize;
131 	CERT_TRUST_STATUS TrustStatus;
132 	DWORD cElement;
133 	PCERT_CHAIN_ELEMENT *rgpElement;
134 	PCERT_TRUST_LIST_INFO pTrustListInfo;
135 	BOOL fHasRevocationFreshnessTime;
136 	DWORD dwRevocationFreshnessTime;
137 	} CERT_SIMPLE_CHAIN, *PCERT_SIMPLE_CHAIN;
138   typedef struct CCC {
139 	DWORD cbSize;
140 	CERT_TRUST_STATUS TrustStatus;
141 	DWORD cChain;
142 	PCERT_SIMPLE_CHAIN *rgpChain;
143 	DWORD cLowerQualityChainContext;
144 	struct CCC **rgpLowerQualityChainContext;
145 	BOOL fHasRevocationFreshnessTime;
146 	DWORD dwRevocationFreshnessTime;
147 	} CERT_CHAIN_CONTEXT;
148   typedef const CERT_CHAIN_CONTEXT *PCCERT_CHAIN_CONTEXT;
149 #endif /* Pre-1999 wincrypt.h */
150 
151 /****************************************************************************
152 *																			*
153 *						 		Init/Shutdown Routines						*
154 *																			*
155 ****************************************************************************/
156 
157 /* Global function pointers.  These are necessary because the functions need
158    to be dynamically linked since not all systems contain the necessary
159    DLL's.  Explicitly linking to them will make cryptlib unloadable on some
160    systems */
161 
162 #define NULL_HINSTANCE	( HINSTANCE ) NULL
163 
164 static HINSTANCE hCryptoAPI = NULL_HINSTANCE;
165 static HINSTANCE hAdvAPI32 = NULL_HINSTANCE;
166 
167 typedef BOOL ( WINAPI *CERTADDCERTIFICATETOSTORE )( HCERTSTORE hCertStore,
168 					PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition,
169 					PCCERT_CONTEXT *ppStoreContext );
170 typedef BOOL ( WINAPI *CERTADDENCODEDCERTIFICATETOSTORE )( HCERTSTORE hCertStore,
171 					DWORD dwCertEncodingType, const BYTE *pbCertEncoded,
172 					DWORD cbCertEncoded, DWORD dwAddDisposition,
173 					PCCERT_CONTEXT *ppCertContext );
174 typedef BOOL ( WINAPI *CERTCLOSESTORE )( HCERTSTORE hCertStore, DWORD dwFlags );
175 typedef PCCERT_CONTEXT ( WINAPI *CERTCREATECERTIFICATECONTEXT )( DWORD dwCertEncodingType,
176 					const BYTE *pbCertEncoded, DWORD cbCertEncoded );
177 typedef BOOL ( WINAPI *CERTDELETECERTIFICATEFROMSTORE )( PCCERT_CONTEXT pCertContext );
178 typedef PCCERT_CONTEXT ( WINAPI *CERTFINDCERTIFICATEINSTORE )( HCERTSTORE hCertStore,
179 					DWORD dwCertEncodingType, DWORD dwFindFlags,
180 					DWORD dwFindType, const void *pvFindPara,
181 					PCCERT_CONTEXT pPrevCertContext );
182 typedef VOID ( WINAPI *CERTFREECERTIFICATECHAIN )( PCCERT_CHAIN_CONTEXT pChainContext );
183 typedef BOOL ( WINAPI *CERTFREECERTIFICATECONTEXT )( PCCERT_CONTEXT pCertContext );
184 typedef BOOL ( WINAPI *CERTGETCERTIFICATECHAIN )( HCERTCHAINENGINE hChainEngine,
185 					PCCERT_CONTEXT pCertContext, LPFILETIME pTime,
186 					HCERTSTORE hAdditionalStore, PCERT_CHAIN_PARA pChainPara,
187 					DWORD dwFlags, LPVOID pvReserved,
188 					PCCERT_CHAIN_CONTEXT *ppChainContext );
189 typedef BOOL ( WINAPI *CERTGETCERTIFICATECONTEXTPROPERTY )( PCCERT_CONTEXT pCertContext,
190 					DWORD dwPropId, void *pvData, DWORD *pcbData );
191 typedef PCCERT_CONTEXT ( WINAPI *CERTGETSUBJECTCERTIFICATEFROMSTORE )( HCERTSTORE hCertStore,
192 					DWORD dwCertEncodingType, PCERT_INFO pCertId );
193 typedef BOOL ( WINAPI *CERTSETCERTIFICATEPROPERTY )( PCCERT_CONTEXT pCertContext,
194 					DWORD dwPropId, DWORD dwFlags, const void *pvData );
195 typedef HCERTSTORE ( WINAPI *CERTOPENSYSTEMSTORE )( HCRYPTPROV hprov,
196 					LPCSTR szSubsystemProtocol );
197 
198 typedef BOOL ( WINAPI *CRYPTACQUIRECERTIFICATEPRIVATEKEY )( PCCERT_CONTEXT pCert,
199 					DWORD dwFlags, void *pvReserved, HCRYPTPROV *phCryptProv,
200 					DWORD *pdwKeySpec, BOOL *pfCallerFreeProv );
201 typedef BOOL ( WINAPI *CRYPTACQUIRECONTEXTA )( HCRYPTPROV *phProv, LPCSTR pszContainer,
202 					LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags );
203 typedef BOOL ( WINAPI *CRYPTCREATEHASH )( HCRYPTPROV hProv, ALG_ID Algid,
204 					HCRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH* phHash );
205 typedef BOOL ( WINAPI *CRYPTDECRYPT )( HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
206 					DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen );
207 typedef BOOL ( WINAPI *CRYPTDESTROYHASH )( HCRYPTHASH hHash );
208 typedef BOOL ( WINAPI *CRYPTDESTROYKEY )( HCRYPTKEY hKey );
209 typedef BOOL ( WINAPI *CRYPTENCRYPT )( HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
210 					DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen );
211 typedef BOOL ( WINAPI *CRYPTEXPORTKEY )( HCRYPTKEY hKey, HCRYPTKEY hExpKey,
212 					DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen );
213 typedef BOOL ( WINAPI *CRYPTFINDCERTIFICATEKEYPROVINFO )( PCCERT_CONTEXT pCert,
214 					DWORD dwFlags, void *pvReserved );
215 typedef BOOL ( WINAPI *CRYPTGENKEY )( HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags,
216 					HCRYPTKEY *phKey );
217 typedef BOOL ( WINAPI *CRYPTGENRANDOM )( HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer );
218 typedef BOOL ( WINAPI *CRYPTGETKEYPARAM )( HCRYPTKEY hKey, DWORD dwParam, BYTE* pbData,
219 					DWORD* pdwDataLen, DWORD dwFlags );
220 typedef BOOL ( WINAPI *CRYPTGETPROVPARAM )( HCRYPTPROV hProv, DWORD dwParam,
221 					BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags );
222 typedef BOOL ( WINAPI *CRYPTGETUSERKEY )( HCRYPTPROV hProv, DWORD dwKeySpec,
223 					HCRYPTKEY* phUserKey );
224 typedef BOOL ( WINAPI *CRYPTHASHDATA )( HCRYPTHASH hHash, BYTE *pbData, DWORD dwDataLen,
225 					DWORD dwFlags );
226 typedef BOOL ( WINAPI *CRYPTIMPORTKEY )( HCRYPTPROV hProv, CONST BYTE *pbData,
227 					DWORD dwDataLen, HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey );
228 typedef BOOL ( WINAPI *CRYPTRELEASECONTEXT )( HCRYPTPROV hProv, DWORD dwFlags );
229 typedef BOOL ( WINAPI *CRYPTSETHASHPARAM )( HCRYPTHASH hHash, DWORD dwParam,
230 					BYTE* pbData, DWORD dwFlags );
231 typedef BOOL ( WINAPI *CRYPTSETKEYPARAM )( HCRYPTKEY hKey, DWORD dwParam,
232 					BYTE *pbData, DWORD dwFlags );
233 typedef BOOL ( WINAPI *CRYPTSIGNHASH )( HCRYPTHASH hHash, DWORD dwKeySpec,
234 					LPCTSTR sDescription, DWORD dwFlags, BYTE* pbSignature,
235 					DWORD* pdwSigLen );
236 
237 static CERTADDCERTIFICATETOSTORE pCertAddCertificateContextToStore = NULL;
238 static CERTADDENCODEDCERTIFICATETOSTORE pCertAddEncodedCertificateToStore = NULL;
239 static CERTCREATECERTIFICATECONTEXT pCertCreateCertificateContext = NULL;
240 static CERTDELETECERTIFICATEFROMSTORE pCertDeleteCertificateFromStore = NULL;
241 static CERTCLOSESTORE pCertCloseStore = NULL;
242 static CERTFINDCERTIFICATEINSTORE pCertFindCertificateInStore = NULL;
243 static CERTFREECERTIFICATECHAIN pCertFreeCertificateChain = NULL;
244 static CERTFREECERTIFICATECONTEXT pCertFreeCertificateContext = NULL;
245 static CERTGETCERTIFICATECHAIN pCertGetCertificateChain = NULL;
246 static CERTGETCERTIFICATECONTEXTPROPERTY pCertGetCertificateContextProperty = NULL;
247 static CERTGETSUBJECTCERTIFICATEFROMSTORE pCertGetSubjectCertificateFromStore = NULL;
248 static CERTSETCERTIFICATEPROPERTY pCertSetCertificateContextProperty = NULL;
249 static CERTOPENSYSTEMSTORE pCertOpenSystemStore = NULL;
250 
251 static CRYPTACQUIRECERTIFICATEPRIVATEKEY pCryptAcquireCertificatePrivateKey = NULL;
252 static CRYPTACQUIRECONTEXTA pCryptAcquireContextA = NULL;
253 static CRYPTCREATEHASH pCryptCreateHash = NULL;
254 static CRYPTDECRYPT pCryptDecrypt = NULL;
255 static CRYPTDESTROYHASH pCryptDestroyHash = NULL;
256 static CRYPTDESTROYKEY pCryptDestroyKey = NULL;
257 static CRYPTENCRYPT pCryptEncrypt = NULL;
258 static CRYPTEXPORTKEY pCryptExportKey = NULL;
259 static CRYPTFINDCERTIFICATEKEYPROVINFO pCryptFindCertificateKeyProvInfo = NULL;
260 static CRYPTGENKEY pCryptGenKey = NULL;
261 static CRYPTGENRANDOM pCryptGenRandom = NULL;
262 static CRYPTGETKEYPARAM pCryptGetKeyParam = NULL;
263 static CRYPTGETPROVPARAM pCryptGetProvParam = NULL;
264 static CRYPTGETUSERKEY pCryptGetUserKey = NULL;
265 static CRYPTHASHDATA pCryptHashData = NULL;
266 static CRYPTIMPORTKEY pCryptImportKey = NULL;
267 static CRYPTRELEASECONTEXT pCryptReleaseContext = NULL;
268 static CRYPTSETHASHPARAM pCryptSetHashParam = NULL;
269 static CRYPTSETKEYPARAM pCryptSetKeyParam = NULL;
270 static CRYPTSIGNHASH pCryptSignHash = NULL;
271 
272 /* Dynamically load and unload any necessary DBMS libraries */
273 
274 CHECK_RETVAL \
deviceInitCryptoAPI(void)275 int deviceInitCryptoAPI( void )
276 	{
277 	/* If the CryptoAPI module is already linked in, don't do anything */
278 	if( hCryptoAPI != NULL_HINSTANCE )
279 		return( CRYPT_OK );
280 
281 	/* Obtain handles to the modules containing the CryptoAPI functions */
282 	if( ( hAdvAPI32 = GetModuleHandle( "AdvAPI32.DLL" ) ) == NULL )
283 		return( CRYPT_ERROR );
284 	if( ( hCryptoAPI = DynamicLoad( "Crypt32.dll" ) ) == NULL_HINSTANCE )
285 		return( CRYPT_ERROR );
286 
287 	/* Get pointers to the crypt functions */
288 	pCryptAcquireCertificatePrivateKey = ( CRYPTACQUIRECERTIFICATEPRIVATEKEY ) GetProcAddress( hCryptoAPI, "CryptAcquireCertificatePrivateKey" );
289 	pCryptAcquireContextA = ( CRYPTACQUIRECONTEXTA ) GetProcAddress( hAdvAPI32, "CryptAcquireContextA" );
290 	pCryptCreateHash = ( CRYPTCREATEHASH ) GetProcAddress( hAdvAPI32, "CryptCreateHash" );
291 	pCryptDecrypt = ( CRYPTDECRYPT ) GetProcAddress( hAdvAPI32, "CryptDecrypt" );
292 	pCryptDestroyHash = ( CRYPTDESTROYHASH ) GetProcAddress( hAdvAPI32, "CryptDestroyHash" );
293 	pCryptDestroyKey = ( CRYPTDESTROYKEY ) GetProcAddress( hAdvAPI32, "CryptDestroyKey" );
294 	pCryptEncrypt = ( CRYPTENCRYPT ) GetProcAddress( hAdvAPI32, "CryptEncrypt" );
295 	pCryptExportKey = ( CRYPTEXPORTKEY ) GetProcAddress( hAdvAPI32, "CryptExportKey" );
296 	pCryptFindCertificateKeyProvInfo = ( CRYPTFINDCERTIFICATEKEYPROVINFO ) GetProcAddress( hCryptoAPI, "CryptFindCertificateKeyProvInfo" );
297 	pCryptGenKey = ( CRYPTGENKEY ) GetProcAddress( hAdvAPI32, "CryptGenKey" );
298 	pCryptGenRandom = ( CRYPTGENRANDOM ) GetProcAddress( hAdvAPI32, "CryptGenRandom" );
299 	pCryptGetKeyParam = ( CRYPTGETKEYPARAM ) GetProcAddress( hAdvAPI32, "CryptGetKeyParam" );
300 	pCryptGetProvParam = ( CRYPTGETPROVPARAM ) GetProcAddress( hAdvAPI32, "CryptGetProvParam" );
301 	pCryptGetUserKey = ( CRYPTGETUSERKEY ) GetProcAddress( hAdvAPI32, "CryptGetUserKey" );
302 	pCryptHashData = ( CRYPTHASHDATA ) GetProcAddress( hAdvAPI32, "CryptHashData" );
303 	pCryptImportKey = ( CRYPTIMPORTKEY ) GetProcAddress( hAdvAPI32, "CryptImportKey" );
304 	pCryptReleaseContext = ( CRYPTRELEASECONTEXT ) GetProcAddress( hAdvAPI32, "CryptReleaseContext" );
305 	pCryptSetHashParam = ( CRYPTSETHASHPARAM ) GetProcAddress( hAdvAPI32, "CryptSetHashParam" );
306 	pCryptSetKeyParam = ( CRYPTSETKEYPARAM ) GetProcAddress( hAdvAPI32, "CryptSetKeyParam" );
307 	pCryptSignHash = ( CRYPTSIGNHASH ) GetProcAddress( hAdvAPI32, "CryptSignHashA" );
308 
309 	/* Get pointers to the certificate functions */
310 	pCertAddCertificateContextToStore = ( CERTADDCERTIFICATETOSTORE ) GetProcAddress( hCryptoAPI, "CertAddCertificateContextToStore" );
311 	pCertAddEncodedCertificateToStore = ( CERTADDENCODEDCERTIFICATETOSTORE ) GetProcAddress( hCryptoAPI, "CertAddEncodedCertificateToStore" );
312 	pCertCreateCertificateContext = ( CERTCREATECERTIFICATECONTEXT ) GetProcAddress( hCryptoAPI, "CertCreateCertificateContext" );
313 	pCertDeleteCertificateFromStore = ( CERTDELETECERTIFICATEFROMSTORE ) GetProcAddress( hCryptoAPI, "CertDeleteCertificateFromStore" );
314 	pCertCloseStore = ( CERTCLOSESTORE ) GetProcAddress( hCryptoAPI, "CertCloseStore" );
315 	pCertFindCertificateInStore = ( CERTFINDCERTIFICATEINSTORE ) GetProcAddress( hCryptoAPI, "CertFindCertificateInStore" );
316 	pCertFreeCertificateChain = ( CERTFREECERTIFICATECHAIN ) GetProcAddress( hCryptoAPI, "CertFreeCertificateChain" );
317 	pCertFreeCertificateContext = ( CERTFREECERTIFICATECONTEXT )  GetProcAddress( hCryptoAPI, "CertFreeCertificateContext" );
318 	pCertGetCertificateChain = ( CERTGETCERTIFICATECHAIN ) GetProcAddress( hCryptoAPI, "CertGetCertificateChain" );
319 	pCertGetCertificateContextProperty = ( CERTGETCERTIFICATECONTEXTPROPERTY ) GetProcAddress( hCryptoAPI, "CertGetCertificateContextProperty" );
320 	pCertGetSubjectCertificateFromStore = ( CERTGETSUBJECTCERTIFICATEFROMSTORE ) GetProcAddress( hCryptoAPI, "CertGetSubjectCertificateFromStore" );
321 	pCertSetCertificateContextProperty = ( CERTSETCERTIFICATEPROPERTY ) GetProcAddress( hCryptoAPI, "CertSetCertificateContextProperty" );
322 	pCertOpenSystemStore = ( CERTOPENSYSTEMSTORE ) GetProcAddress( hCryptoAPI, "CertOpenSystemStoreA" );
323 
324 	/* Make sure that we got valid pointers for every CryptoAPI function */
325 	if( pCertAddCertificateContextToStore == NULL || \
326 		pCertAddEncodedCertificateToStore == NULL ||
327 		pCertCreateCertificateContext == NULL ||
328 		pCertDeleteCertificateFromStore == NULL ||
329 		pCertCloseStore == NULL || pCertFindCertificateInStore == NULL ||
330 		pCertFreeCertificateChain == NULL ||
331 		pCertFreeCertificateContext == NULL ||
332 		pCertGetCertificateChain == NULL ||
333 		pCertGetCertificateContextProperty  == NULL ||
334 		pCertGetSubjectCertificateFromStore == NULL ||
335 		pCertSetCertificateContextProperty == NULL ||
336 		pCertOpenSystemStore == NULL ||
337 		pCryptAcquireCertificatePrivateKey == NULL ||
338 		pCryptAcquireContextA == NULL || pCryptCreateHash == NULL ||
339 		pCryptDecrypt == NULL || pCryptEncrypt == NULL ||
340 		pCryptExportKey == NULL || pCryptDestroyHash == NULL ||
341 		pCryptDestroyKey == NULL ||
342 		pCryptFindCertificateKeyProvInfo == NULL || pCryptGenKey == NULL ||
343 		pCryptGenRandom == NULL || pCryptGetKeyParam == NULL ||
344 		pCryptGetProvParam == NULL || pCryptGetUserKey == NULL ||
345 		pCryptHashData == NULL || pCryptImportKey == NULL ||
346 		pCryptReleaseContext == NULL || pCryptSetHashParam == NULL ||
347 		pCryptSetKeyParam == NULL || pCryptSignHash == NULL )
348 		{
349 		/* Free the library reference and reset the handle */
350 		DynamicUnload( hCryptoAPI );
351 		hCryptoAPI = NULL_HINSTANCE;
352 		return( CRYPT_ERROR );
353 		}
354 
355 	return( CRYPT_OK );
356 	}
357 
deviceEndCryptoAPI(void)358 void deviceEndCryptoAPI( void )
359 	{
360 	if( hCryptoAPI != NULL_HINSTANCE )
361 		DynamicUnload( hCryptoAPI );
362 	hCryptoAPI = NULL_HINSTANCE;
363 	}
364 
365 /****************************************************************************
366 *																			*
367 *						 		Utility Routines							*
368 *																			*
369 ****************************************************************************/
370 
371 /* Get access to the PKCS #11 device associated with a context */
372 
getContextDeviceInfo(const CRYPT_HANDLE iCryptContext,CRYPT_DEVICE * iCryptDevice,CRYPTOAPI_INFO ** cryptoapiInfoPtrPtr)373 static int getContextDeviceInfo( const CRYPT_HANDLE iCryptContext,
374 								 CRYPT_DEVICE *iCryptDevice,
375 								 CRYPTOAPI_INFO **cryptoapiInfoPtrPtr )
376 	{
377 	CRYPT_DEVICE iLocalDevice;
378 	DEVICE_INFO *deviceInfo;
379 	int cryptStatus;
380 
381 	/* Clear return values */
382 	*iCryptDevice = CRYPT_ERROR;
383 	*cryptoapiInfoPtrPtr = NULL;
384 
385 	/* Get the the device associated with this context */
386 	cryptStatus = krnlSendMessage( iCryptContext, IMESSAGE_GETDEPENDENT,
387 								   &iLocalDevice, OBJECT_TYPE_DEVICE );
388 	if( cryptStatusError( cryptStatus ) )
389 		return( cryptStatus );
390 
391 	/* Get the CryptoAPI information from the device information */
392 	cryptStatus = krnlAcquireObject( iLocalDevice, OBJECT_TYPE_DEVICE,
393 									 ( void ** ) &deviceInfo,
394 									 CRYPT_ERROR_SIGNALLED );
395 	if( cryptStatusError( cryptStatus ) )
396 		return( cryptStatus );
397 	*iCryptDevice = iLocalDevice;
398 	*cryptoapiInfoPtrPtr = deviceInfo->deviceCryptoAPI;
399 
400 	return( CRYPT_OK );
401 	}
402 
403 /* Map a CryptoAPI-specific error to a cryptlib error */
404 
mapError(CRYPTOAPI_INFO * cryptoapiInfo,const int defaultError)405 static int mapError( CRYPTOAPI_INFO *cryptoapiInfo, const int defaultError )
406 	{
407 #ifdef USE_ERRMSGS
408 	ERROR_INFO *errorInfo = &cryptoapiInfo->errorInfo;
409 	int messageLength;
410 #endif /* USE_ERRMSGS */
411 	const DWORD errorCode = GetLastError();
412 
413 	/* Get the error message for this error.  FormatMessage() adds EOL
414 	   terminators so we have to strip those before we pass the string back
415 	   to the caller.  There's an incredibly arcane way of telling
416 	   FormatMessage() to do this via escape codes passed in as part of a
417 	   va_arg argument list, but aside from being complex to set up this
418 	   also means that the function will try and insert information such as
419 	   filenames from the argument list when required (there's no way to
420 	   tell in advance which arguments are required), so this is more
421 	   trouble than it's worth */
422 #ifdef USE_ERRMSGS
423 	FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode, 0,
424 				   errorInfo->errorString, MAX_ERRMSG_SIZE - 1, NULL );
425 	for( messageLength = strlen( errorInfo->errorString );
426 		 messageLength > 0 && \
427 			( errorInfo->errorString[ messageLength - 1 ] == '\n' || \
428 			  errorInfo->errorString[ messageLength - 1 ] == '\r' );
429 		 messageLength-- );
430 	errorInfo->errorStringLength = messageLength;
431 #endif /* USE_ERRMSGS */
432 
433 	/* Translate the CAPI error code into the cryptlib equivalent */
434 	switch( errorCode )
435 		{
436 		case CRYPT_E_UNKNOWN_ALGO:
437 			return( CRYPT_ERROR_NOTAVAIL );
438 
439 		case ERROR_BUSY:
440 			return( CRYPT_ERROR_TIMEOUT );
441 
442 		case ERROR_MORE_DATA:
443 			return( CRYPT_ERROR_OVERFLOW );
444 
445 		case ERROR_NO_MORE_ITEMS:
446 			return( CRYPT_ERROR_COMPLETE );
447 
448 		case NTE_BAD_DATA:
449 			return( CRYPT_ERROR_BADDATA );
450 
451 		case CRYPT_E_EXISTS:
452 		case NTE_EXISTS:
453 			return( CRYPT_ERROR_DUPLICATE );
454 
455 		case ERROR_NOT_ENOUGH_MEMORY:
456 		case NTE_NO_MEMORY:
457 			return( CRYPT_ERROR_MEMORY );
458 
459 		case CRYPT_E_SECURITY_SETTINGS:
460 		case NTE_PERM:
461 			return( CRYPT_ERROR_PERMISSION );
462 
463 		case NTE_BAD_SIGNATURE:
464 			return( CRYPT_ERROR_SIGNATURE );
465 
466 		case CRYPT_E_NO_MATCH:
467 		case CRYPT_E_NOT_FOUND:
468 		case NTE_KEYSET_NOT_DEF:
469 		case NTE_NOT_FOUND:
470 		case NTE_PROV_DLL_NOT_FOUND:
471 		case NTE_PROV_TYPE_NO_MATCH:
472 		case NTE_PROV_TYPE_NOT_DEF:
473 			return( CRYPT_ERROR_NOTFOUND );
474 		}
475 
476 	return( defaultError );
477 	}
478 
mapDeviceError(CONTEXT_INFO * contextInfoPtr,const int defaultError)479 static int mapDeviceError( CONTEXT_INFO *contextInfoPtr, const int defaultError )
480 	{
481 	CRYPT_DEVICE iCryptDevice;
482 	CRYPTOAPI_INFO *cryptoapiInfo;
483 	int status;
484 
485 	/* Get the device associated with this context, set the error information
486 	   in it, and exit */
487 	status = getContextDeviceInfo( contextInfoPtr->objectHandle,
488 								   &iCryptDevice, &cryptoapiInfo );
489 	if( cryptStatusError( status ) )
490 		return( status );
491 	status = mapError( cryptoapiInfo, defaultError );
492 	krnlReleaseObject( iCryptDevice );
493 	return( status );
494 	}
495 
496 /* Map cryptlib to/from CryptoAPI algorithm IDs */
497 
498 static const MAP_TABLE algoMapTbl[] = {
499 	/* PKC algorithms */
500 	{ CRYPT_ALGO_RSA, CALG_RSA_SIGN },
501 	{ CRYPT_ALGO_RSA, CALG_RSA_KEYX },
502 	{ CRYPT_ALGO_DSA, CALG_DSS_SIGN },
503 
504 	/* Encryption algorithms */
505 	{ CRYPT_ALGO_DES, CALG_DES },
506 	{ CRYPT_ALGO_3DES, CALG_3DES },
507 	{ CRYPT_ALGO_RC2, CALG_RC2 },
508 	{ CRYPT_ALGO_RC4, CALG_RC4 },
509 
510 	/* Hash algorithms */
511 	{ CRYPT_ALGO_MD5, CALG_MD5 },
512 	{ CRYPT_ALGO_SHA1, CALG_SHA },
513 
514 	{ CRYPT_ALGO_NONE, 0 }, { CRYPT_ALGO_NONE, 0 }
515 	};
516 
cryptlibToCapiID(const CRYPT_ALGO_TYPE cryptAlgo)517 static ALG_ID cryptlibToCapiID( const CRYPT_ALGO_TYPE cryptAlgo )
518 	{
519 	int value, status;
520 
521 	status = mapValue( cryptAlgo, &value, algoMapTbl,
522 					   FAILSAFE_ARRAYSIZE( algoMapTbl, MAP_TABLE ) );
523 	ENSURES_EXT( cryptStatusOK( status ), CALG_NONE );
524 
525 	return( value );
526 	}
527 
capiToCryptlibID(const ALG_ID algID)528 static CRYPT_ALGO_TYPE capiToCryptlibID( const ALG_ID algID )
529 	{
530 	int i;
531 
532 	for( i = 0; algoMapTbl[ i ].source != CRYPT_ALGO_NONE && \
533 				i < FAILSAFE_ARRAYSIZE( algoMapTbl, MAP_TABLE ); i++ )
534 		{
535 		if( ( ALG_ID ) algoMapTbl[ i ].destination == algID )
536 			break;
537 		}
538 	if( i >= FAILSAFE_ARRAYSIZE( algoMapTbl, MAP_TABLE ) )
539 		retIntError_Ext( CRYPT_ALGO_NONE );
540 	if( algoMapTbl[ i ].source == CRYPT_ALGO_NONE )
541 		return( CRYPT_ALGO_NONE );
542 	return( algoMapTbl[ i ].source );
543 	}
544 
545 /* Copy an MPI into the little-endian order required by CryptoAPI, returning
546    the end position of the copied MPI */
547 
copyMPI(BYTE * dest,const BYTE * src,const int srcLen,const int srcRequiredLen)548 static BYTE *copyMPI( BYTE *dest, const BYTE *src, const int srcLen,
549 					  const int srcRequiredLen )
550 	{
551 	int i;
552 
553 	dest += srcLen - 1;
554 	for( i = 0; i < srcLen; i++ )
555 		*dest-- = *src++;
556 	dest += srcLen + 1;
557 	if( srcLen < srcRequiredLen )
558 		{
559 		/* CryptoAPI blobs don't contain any length information but
560 		   implicitly specify all lengths in terms of the size of the
561 		   main MPI component, so if the actual length is less than the
562 		   assumed length we pad the remainder out with zeroes */
563 		for( i = 0; i < srcRequiredLen - srcLen; i++ )
564 			*dest++ = 0;
565 		}
566 
567 	return( dest );
568 	}
569 
570 /* Create the special-case RSA key with e=1 that's needed to allow direct
571    key import and export */
572 
createExportKey(const HCRYPTPROV hProv,HCRYPTKEY * hPrivateKey,int * privateKeySize)573 static int createExportKey( const HCRYPTPROV hProv, HCRYPTKEY *hPrivateKey,
574 							int *privateKeySize )
575 	{
576 	BLOBHEADER *blobHeaderPtr;
577 	RSAPUBKEY *pubKeyPtr;
578 	BYTE keyBlob[ 1024 + 8 ], *keyBlobPtr;
579 	DWORD keyBlobLen = 1024;
580 	BOOL result;
581 	int bitLen16;
582 
583 	/* Generate a private key and export it as a private key blob:
584 
585 		Ofs	Value
586 
587 		  0	BLOBHEADER blobheader {
588 			  0	BYTE bType;
589 			  1	BYTE bVersion;
590 			  2 WORD reserved;
591 			  4	ALG_ID aiKeyAlg; }
592 		  8	RSAPUBKEY rsapubkey {
593 			  8 DWORD magic;
594 			 12	DWORD bitlen;
595 			 16	DWORD pubexp; }
596 		 20	BYTE modulus[ rsapubkey.bitlen / 8 ];
597 			BYTE prime1[ rsapubkey.bitlen / 16 ];
598 			BYTE prime2[ rsapubkey.bitlen / 16 ];
599 			BYTE exponent1[ rsapubkey.bitlen / 16 ];
600 			BYTE exponent2[ rsapubkey.bitlen / 16 ];
601 			BYTE coefficient[ rsapubkey.bitlen / 16 ];
602 			BYTE privateExponent[ rsapubkey.bitlen / 8 ]; */
603 	if( !pCryptGenKey( hProv, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, hPrivateKey ) || \
604 		!pCryptExportKey( *hPrivateKey, 0, PRIVATEKEYBLOB, 0, keyBlob, &keyBlobLen ) || \
605 		!pCryptDestroyKey( *hPrivateKey ) )
606 		return( CRYPT_ERROR );
607 
608 	/* Perform a general sanity check on the returned data */
609 	blobHeaderPtr = ( BLOBHEADER * ) keyBlob;
610 	if( blobHeaderPtr->bType != PRIVATEKEYBLOB || \
611 		blobHeaderPtr->bVersion != CUR_BLOB_VERSION || \
612 		blobHeaderPtr->aiKeyAlg != CALG_RSA_KEYX )
613 		{
614 		pCryptDestroyKey( *hPrivateKey );
615 		return( CRYPT_ERROR );
616 		}
617 
618 	/* Set the public exponent to 1 (little-endian 32-bit value) and skip to
619 	   the private exponents */
620 	pubKeyPtr = ( RSAPUBKEY * ) ( keyBlob + BLOBHEADER_SIZE );
621 	bitLen16 = ( pubKeyPtr->bitlen / 16 );
622 	pubKeyPtr->pubexp = 1;
623 	keyBlobPtr = keyBlob + 20 + ( pubKeyPtr->bitlen / 8 ) + bitLen16 + bitLen16;
624 
625 	/* Set the two exponents to 1 */
626 	*keyBlobPtr++ = 1;
627 	memset( keyBlobPtr, 0, bitLen16 - 1 );
628 	keyBlobPtr += bitLen16 - 1;
629 	*keyBlobPtr++ = 1;
630 	memset( keyBlobPtr, 0, bitLen16 - 1 );
631 	keyBlobPtr += bitLen16 - 1;
632 
633 	/* Set the private exponent to 1 */
634 	keyBlobPtr += bitLen16;		/* Skip coefficient */
635 	*keyBlobPtr++ = 1;
636 	memset( keyBlobPtr, 0, bitLen16 - 1 );
637 	keyBlobPtr += bitLen16 - 1;
638 
639 	/* Finally, re-import the hacked key and clean up */
640 	result = pCryptImportKey( hProv, keyBlob, keyBlobLen, 0, 0, hPrivateKey );
641 	if( result )
642 		*privateKeySize = pubKeyPtr->bitlen / 8;
643 	else
644 		*hPrivateKey = 0;
645 	zeroise( keyBlob, keyBlobLen );
646 
647 	return( result ? CRYPT_OK : CRYPT_ERROR );
648 	}
649 
650 /* Import a raw session key using the exponent-one RSA key */
651 
importPlainKey(const HCRYPTPROV hProv,const HCRYPTKEY hPrivateKey,const int privateKeySize,HCRYPTKEY * hSessionKey,const CRYPT_ALGO_TYPE cryptAlgo,const BYTE * keyData,const int keyDataSize,void * errorInfoPtr)652 static int importPlainKey( const HCRYPTPROV hProv,
653 						   const HCRYPTKEY hPrivateKey,
654 						   const int privateKeySize, HCRYPTKEY *hSessionKey,
655 						   const CRYPT_ALGO_TYPE cryptAlgo, const BYTE *keyData,
656 						   const int keyDataSize, void *errorInfoPtr )
657 	{
658 	BLOBHEADER *blobHeaderPtr;
659 	BYTE keyBlob[ 1024 + 8 ], *keyBlobPtr;
660 	ALG_ID algID;
661 	DWORD *dwPtr;
662 	BOOL result;
663 	const int blobSize = sizeof( BLOBHEADER ) + sizeof( ALG_ID ) + privateKeySize;
664 	int i;
665 
666 	/* Set up a SIMPLEBLOB:
667 
668 		Ofs	Value
669 		  0	BLOBHEADER blobheader {
670 			  0	BYTE bType;
671 			  1	BYTE bVersion;
672 			  2 WORD reserved;
673 			  4	ALG_ID aiKeyAlg; }
674 		  8	ALG_ID algid;
675 		 12	BYTE encryptedkey[ rsapubkey.bitlen/8 ]; */
676 	memset( keyBlob, 0, 1024 );
677 	algID = cryptlibToCapiID( cryptAlgo );
678 	if( algID == 0 )
679 		return( CRYPT_ERROR_NOTAVAIL );
680 
681 	/* Set up the BLOBHEADER part of the blob */
682 	blobHeaderPtr = ( BLOBHEADER * ) keyBlob;
683     blobHeaderPtr->bType = SIMPLEBLOB;
684 	blobHeaderPtr->bVersion = CUR_BLOB_VERSION;
685 	blobHeaderPtr->aiKeyAlg = algID;
686 
687 	/* Set up the private-key algorithm ID */
688 	dwPtr = ( DWORD * )( keyBlob + BLOBHEADER_SIZE );
689 	*dwPtr = CALG_RSA_KEYX;
690 
691 	/* Store the key as byte-reversed PKCS #1 padded data (or at least close
692 	   enough to it to work for the import) */
693 	keyBlobPtr = keyBlob + 12;
694 	for( i = keyDataSize - 1; i >= 0; i-- )
695 		*keyBlobPtr++ = keyData[ i ];
696 	*keyBlobPtr++ = 0;
697 	memset( keyBlobPtr, 2, privateKeySize - ( keyDataSize + 2 ) );
698 
699 	/* Import the key from the faked PKCS #1 wrapped form */
700 	result = pCryptImportKey( hProv, keyBlob, blobSize, hPrivateKey, 0, hSessionKey );
701 	zeroise( keyBlob, blobSize );
702 	if( !result )
703 		return( mapDeviceError( errorInfoPtr, CRYPT_ERROR_FAILED ) );
704 
705 	return( CRYPT_OK );
706 	}
707 
708 /* Load a CryptoAPI public key into a cryptlib native context */
709 
getPubkeyComponents(CRYPTOAPI_INFO * cryptoapiInfo,const HCRYPTKEY hKey,BYTE * n,int * nLen,BYTE * e,int * eLen)710 static int getPubkeyComponents( CRYPTOAPI_INFO *cryptoapiInfo,
711 								const HCRYPTKEY hKey, BYTE *n, int *nLen,
712 								BYTE *e, int *eLen )
713 	{
714 	BLOBHEADER *blobHeaderPtr;
715 	RSAPUBKEY *pubKeyPtr;
716 	BYTE keyBlob[ 1024 + CRYPT_MAX_PKCSIZE + 8 ], *nPtr;
717 	BYTE buffer[ 16 + 8 ], *bufPtr = buffer;
718 	DWORD keyBlobLen = 1024 + CRYPT_MAX_PKCSIZE;
719 	int exponent, length;
720 
721 	/* Clear return values */
722 	memset( n, 0, 8 );
723 	memset( e, 0, 8 );
724 	*nLen = *eLen = 0;
725 
726 	/* Get the public key components */
727 	if( !pCryptExportKey( hKey, 0, PUBLICKEYBLOB, 0, keyBlob, &keyBlobLen ) )
728 		return( mapError( cryptoapiInfo, CRYPT_ERROR_FAILED ) );
729 
730 	/* Perform a general sanity check on the returned data */
731 	blobHeaderPtr = ( BLOBHEADER * ) keyBlob;
732 	if( blobHeaderPtr->bType != PUBLICKEYBLOB || \
733 		blobHeaderPtr->bVersion != CUR_BLOB_VERSION )
734 		return( CRYPT_ERROR_FAILED );
735 
736 	/* Extract the public key components */
737 	pubKeyPtr = ( RSAPUBKEY * ) ( keyBlob + BLOBHEADER_SIZE );
738 	exponent = pubKeyPtr->pubexp;
739 	nPtr = keyBlob + 20;
740 	length = pubKeyPtr->bitlen / 8;
741 	while( length > 0 && nPtr[ length ] == 0 )
742 		length--;
743 	copyMPI( n, nPtr, length, length );
744 	*nLen = length;
745 	length = ( exponent <= 0xFF ) ? 1 : \
746 			 ( exponent <= 0xFFFF ) ? 2 : \
747 			 ( exponent <= 0xFFFFFFL ) ? 3 : 4;
748 	mputLong( bufPtr, exponent );
749 	memcpy( e, buffer + ( 4 - length ), length );
750 	*eLen = length;
751 
752 	return( CRYPT_OK );
753 	}
754 
capiToCryptlibContext(CRYPTOAPI_INFO * cryptoapiInfo,const HCRYPTKEY hKey,CRYPT_CONTEXT * cryptContextPtr)755 static int capiToCryptlibContext( CRYPTOAPI_INFO *cryptoapiInfo,
756 								  const HCRYPTKEY hKey,
757 								  CRYPT_CONTEXT *cryptContextPtr )
758 	{
759 	CRYPT_PKCINFO_RSA rsaKey;
760 	MESSAGE_CREATEOBJECT_INFO createInfo;
761 	MESSAGE_DATA msgData;
762 	BYTE n[ CRYPT_MAX_PKCSIZE + 8 ], e[ CRYPT_MAX_PKCSIZE + 8 ];
763 	int nLen, eLen, status;
764 
765 	/* Clear return value */
766 	*cryptContextPtr = CRYPT_ERROR;
767 
768 	/* Extract the public-key components from the CryptoAPI context */
769 	status = getPubkeyComponents( cryptoapiInfo, hKey, n, &nLen, e, &eLen );
770 	if( cryptStatusError( status ) )
771 		return( status );
772 
773 	/* Copy the public-key components into the cryptlib format */
774 	cryptInitComponents( &rsaKey, CRYPT_KEYTYPE_PUBLIC );
775 	cryptSetComponent( ( &rsaKey )->n, n, bytesToBits( nLen ) );
776 	cryptSetComponent( ( &rsaKey )->e, e, bytesToBits( eLen ) );
777 	zeroise( n, CRYPT_MAX_PKCSIZE );
778 	zeroise( e, CRYPT_MAX_PKCSIZE );
779 
780 	/* Create the RSA context */
781 	setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_RSA );
782 	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
783 							  &createInfo, OBJECT_TYPE_CONTEXT );
784 	if( cryptStatusError( status ) )
785 		{
786 		cryptDestroyComponents( &rsaKey );
787 		return( status );
788 		}
789 
790 	/* Load the key into the context */
791 	setMessageData( &msgData, "CryptoAPI RSA key", 17 );
792 	status = krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE_S,
793 							  &msgData, CRYPT_CTXINFO_LABEL );
794 	if( cryptStatusOK( status ) )
795 		{
796 		setMessageData( &msgData, &rsaKey, sizeof( CRYPT_PKCINFO_RSA ) );
797 		status = krnlSendMessage( createInfo.cryptHandle,
798 								  IMESSAGE_SETATTRIBUTE_S, &msgData,
799 								  CRYPT_CTXINFO_KEY_COMPONENTS );
800 		}
801 	cryptDestroyComponents( &rsaKey );
802 	if( cryptStatusError( status ) )
803 		{
804 		DEBUG_DIAG(( "Failed to load CryptoAPI public key data" ));
805 		assert( DEBUG_WARN );
806 		krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
807 		return( status );
808 		}
809 
810 	*cryptContextPtr = createInfo.cryptHandle;
811 	return( CRYPT_OK );
812 	}
813 
814 /* Compare a CryptoAPI private key with a certificate to check whether the
815    certificate corresponds to the key */
816 
isCertKey(const CRYPTOAPI_INFO * cryptoapiInfo,const HCRYPTKEY hKey,const CRYPT_CERTIFICATE iCryptCert)817 static BOOLEAN isCertKey( const CRYPTOAPI_INFO *cryptoapiInfo,
818 						  const HCRYPTKEY hKey,
819 						  const CRYPT_CERTIFICATE iCryptCert )
820 	{
821 	return( TRUE );
822 	}
823 
824 /* Get a certificate using a key/certificate identifier */
825 
getCertificate(const CRYPTOAPI_INFO * cryptoapiInfo,const CRYPT_KEYID_TYPE keyIDtype,const void * keyID,const int keyIDlength,PCCERT_CONTEXT * pCertContextPtr)826 static int getCertificate( const CRYPTOAPI_INFO *cryptoapiInfo,
827 						   const CRYPT_KEYID_TYPE keyIDtype,
828 						   const void *keyID, const int keyIDlength,
829 						   PCCERT_CONTEXT *pCertContextPtr )
830 	{
831 	PCCERT_CONTEXT pCertContext = NULL;
832 
833 	switch( keyIDtype )
834 		{
835 		case CRYPT_KEYID_NAME:
836 			{
837 			CERT_RDN certRDN;
838 			CERT_RDN_ATTR certRDNAttr;
839 
840 			/* Find a certificate by CN */
841 			memset( &certRDNAttr, 0, sizeof( CERT_RDN_ATTR ) );
842 			certRDNAttr.pszObjId = szOID_COMMON_NAME;
843 			certRDNAttr.dwValueType = CERT_RDN_ANY_TYPE;
844 			certRDNAttr.Value.pbData = ( void * ) keyID;
845 			certRDNAttr.Value.cbData = keyIDlength;
846 			memset( &certRDN, 0, sizeof( CERT_RDN ) );
847 			certRDN.rgRDNAttr = &certRDNAttr;
848 			certRDN.cRDNAttr = 1;
849 			pCertContext = \
850 				pCertFindCertificateInStore( cryptoapiInfo->hCertStore,
851 							X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_ATTR,
852 							&certRDN, NULL );
853 			break;
854 			}
855 
856 		case CRYPT_KEYID_URI:
857 			{
858 			CERT_RDN certRDN;
859 			CERT_RDN_ATTR certRDNAttr;
860 
861 			/* There doesn't appear to be any way to locate a certificate
862 			   using the email address in an altName, so we have to restrict
863 			   ourselves to the most commonly-used OID for certificates in
864 			   DNs */
865 			memset( &certRDNAttr, 0, sizeof( CERT_RDN_ATTR ) );
866 			certRDNAttr.pszObjId = szOID_RSA_emailAddr ;
867 			certRDNAttr.dwValueType = CERT_RDN_ANY_TYPE;
868 			certRDNAttr.Value.pbData = ( void * ) keyID;
869 			certRDNAttr.Value.cbData = keyIDlength;
870 			memset( &certRDN, 0, sizeof( CERT_RDN ) );
871 			certRDN.rgRDNAttr = &certRDNAttr;
872 			certRDN.cRDNAttr = 1;
873 			pCertContext = \
874 				pCertFindCertificateInStore( cryptoapiInfo->hCertStore,
875 							X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_ATTR,
876 							&certRDN, NULL );
877 			break;
878 			}
879 
880 		case CRYPT_IKEYID_CERTID:
881 			{
882 			CRYPT_DATA_BLOB cryptDataBlob;
883 
884 			memset( &cryptDataBlob, 0, sizeof( CRYPT_DATA_BLOB ) );
885 			cryptDataBlob.pbData = ( void * ) keyID;
886 			cryptDataBlob.cbData = keyIDlength;
887 			pCertContext = \
888 				pCertFindCertificateInStore( cryptoapiInfo->hCertStore,
889 							X509_ASN_ENCODING, 0, CERT_FIND_SHA1_HASH,
890 							&cryptDataBlob, NULL );
891 			break;
892 			}
893 
894 		case CRYPT_IKEYID_KEYID:
895 			{
896 #if 0
897 			CERT_ID certID;
898 
899 			certID.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
900 			certID.KeyId.pbData = ( void * ) keyID;
901 			certID.KeyId.cbData = keyIDlength;
902 			pCertContext = \
903 				pCertFindCertificateInStore( cryptoapiInfo->hCertStore,
904 							X509_ASN_ENCODING, 0, CERT_FIND_CERT_ID,
905 							&certID, NULL );
906 #else
907 			CRYPT_HASH_BLOB hashBlob;
908 
909 			hashBlob.pbData = ( void * ) keyID;
910 			hashBlob.cbData = keyIDlength;
911 			pCertContext = \
912 				pCertFindCertificateInStore( cryptoapiInfo->hCertStore,
913 							X509_ASN_ENCODING, 0, CERT_FIND_KEY_IDENTIFIER,
914 							&hashBlob, NULL );
915 #endif /* 0 */
916 			break;
917 			}
918 
919 		case CRYPT_IKEYID_ISSUERANDSERIALNUMBER:
920 			{
921 			CERT_INFO certInfo;
922 			STREAM stream;
923 			void *dataPtr DUMMY_INIT_PTR;
924 			int length DUMMY_INIT, status;
925 
926 			memset( &certInfo, 0, sizeof( CERT_INFO ) );
927 			sMemConnect( &stream, keyID, keyIDlength );
928 			status = readSequence( &stream, NULL );
929 			if( cryptStatusOK( status ) )
930 				status = getStreamObjectLength( &stream, &length );
931 			if( cryptStatusOK( status ) )
932 				status = sMemGetDataBlock( &stream, &dataPtr, length );
933 			if( cryptStatusError( status ) )
934 				{
935 				sMemDisconnect( &stream );
936 				return( status );
937 				}
938 			certInfo.Issuer.pbData = dataPtr;		/* Issuer DN */
939 			certInfo.Issuer.cbData = length;
940 			status = sSkip( &stream, length, MAX_INTLENGTH_SHORT );
941 			if( cryptStatusOK( status ) )
942 				status = getStreamObjectLength( &stream, &length );
943 			if( cryptStatusOK( status ) )
944 				status = sMemGetDataBlock( &stream, &dataPtr, length );
945 			if( cryptStatusError( status ) )
946 				return( status );
947 			certInfo.SerialNumber.pbData = dataPtr;	/* Serial number */
948 			certInfo.SerialNumber.cbData = length;
949 			status = sSkip( &stream, length, MAX_INTLENGTH_SHORT );
950 			assert( sStatusOK( &stream ) );
951 			sMemDisconnect( &stream );
952 			if( cryptStatusError( status ) )
953 				return( status );
954 			pCertContext = \
955 				pCertGetSubjectCertificateFromStore( cryptoapiInfo->hCertStore,
956 							X509_ASN_ENCODING, &certInfo );
957 			}
958 
959 		default:
960 			retIntError();
961 		}
962 
963 	if( pCertContext == NULL )
964 		return( CRYPT_ERROR_NOTFOUND );
965 	*pCertContextPtr = pCertContext;
966 	return( CRYPT_OK );
967 	}
968 
969 /* Get a certificate chain from a leaf certificate */
970 
getCertificateChain(CRYPTOAPI_INFO * cryptoapiInfo,const PCCERT_CONTEXT pCertContext,PCCERT_CHAIN_CONTEXT * pChainContextPtr)971 static int getCertificateChain( CRYPTOAPI_INFO *cryptoapiInfo,
972 								const PCCERT_CONTEXT pCertContext,
973 								PCCERT_CHAIN_CONTEXT *pChainContextPtr )
974 	{
975 	CERT_CHAIN_PARA chainPara;
976 	CERT_USAGE_MATCH certUsage;
977 	CERT_ENHKEY_USAGE enhkeyUsage;
978 	PCCERT_CHAIN_CONTEXT pChainContext;
979 
980 	/* Clear return value */
981 	*pChainContextPtr = NULL;
982 
983 	/* Get the chain from the supplied certificate up to a root
984 	   certificate */
985 	memset( &enhkeyUsage, 0, sizeof( CERT_ENHKEY_USAGE ) );
986 	enhkeyUsage.cUsageIdentifier = 0;
987 	enhkeyUsage.rgpszUsageIdentifier = NULL;
988 	memset( &certUsage, 0, sizeof( CERT_USAGE_MATCH ) );
989 	certUsage.dwType = USAGE_MATCH_TYPE_AND;
990 	certUsage.Usage = enhkeyUsage;
991 	memset( &chainPara, 0, sizeof( CERT_CHAIN_PARA ) );
992 	chainPara.cbSize = sizeof( CERT_CHAIN_PARA );
993 	chainPara.RequestedUsage = certUsage;
994 	if( !pCertGetCertificateChain( NULL, pCertContext, NULL, NULL, &chainPara,
995 								   CERT_CHAIN_CACHE_END_CERT | \
996 								   CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY,
997 								   NULL, &pChainContext ) )
998 		return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
999 	*pChainContextPtr = pChainContext;
1000 	return( CRYPT_OK );
1001 	}
1002 
1003 /* Get a certificate from a public/private key and vice versa */
1004 
getCertificateFromKey(CRYPTOAPI_INFO * cryptoapiInfo,const HCRYPTKEY hKey,const BOOLEAN isSigningKey,PCCERT_CONTEXT * pCertContextPtr)1005 static int getCertificateFromKey( CRYPTOAPI_INFO *cryptoapiInfo,
1006 								  const HCRYPTKEY hKey,
1007 								  const BOOLEAN isSigningKey,
1008 								  PCCERT_CONTEXT *pCertContextPtr )
1009 	{
1010 	PCCERT_CONTEXT pCertContext;
1011 	CERT_PUBLIC_KEY_INFO pubKeyInfo;
1012 	BYTE keyBlob[ 1024 + CRYPT_MAX_PKCSIZE + 8 ];
1013 	DWORD keyBlobLen = 1024 + CRYPT_MAX_PKCSIZE;
1014 
1015 	/* Clear return value */
1016 	*pCertContextPtr = NULL;
1017 
1018 	/* Extract the public-key components from the public or private key */
1019 	if( !pCryptExportKey( hKey, 0, PUBLICKEYBLOB, 0, keyBlob, &keyBlobLen ) )
1020 		{
1021 		pCryptDestroyKey( hKey );
1022 		return( CRYPT_ERROR_NOTFOUND );
1023 		}
1024 
1025 	/* Get the certificate for the context's public key */
1026 	memset( &pubKeyInfo, 0, sizeof( CERT_PUBLIC_KEY_INFO ) );
1027 	pubKeyInfo.Algorithm.pszObjId = isSigningKey ? \
1028 									CERT_DEFAULT_OID_PUBLIC_KEY_SIGN : \
1029 									CERT_DEFAULT_OID_PUBLIC_KEY_XCHG;
1030 	pubKeyInfo.PublicKey.pbData = keyBlob;
1031 	pubKeyInfo.PublicKey.cbData = keyBlobLen;
1032 	pCertContext = \
1033 		pCertFindCertificateInStore( cryptoapiInfo->hCertStore,
1034 						X509_ASN_ENCODING, 0, CERT_FIND_PUBLIC_KEY,
1035 						&pubKeyInfo, NULL );
1036 	if( pCertContext == NULL )
1037 		return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
1038 	*pCertContextPtr = pCertContext;
1039 	return( CRYPT_OK );
1040 	}
1041 
1042 #if 0
1043 
1044 static int getPrivKeyFromCertificate( CRYPTOAPI_INFO *cryptoapiInfo,
1045 									  const PCCERT_CONTEXT pCertContext,
1046 									  HCRYPTKEY *hKeyPtr )
1047 	{
1048 	HCRYPTPROV hProv;
1049 	HCRYPTKEY hKey;
1050 	DWORD dwKeySpec;
1051 	BOOL fCallerFreeProv;
1052 
1053 	/* Clear return value */
1054 	*hKeyPtr = 0;
1055 
1056 	/* Get the provider and key-type from the certificate and use that to
1057 	   get the key */
1058 	if( !pCryptAcquireCertificatePrivateKey( pCertContext,
1059 									CRYPT_ACQUIRE_CACHE_FLAG, NULL,
1060 									&hProv, &dwKeySpec, &fCallerFreeProv ) )
1061 		return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
1062 	if( !pCryptGetUserKey( hProv, dwKeySpec, &hKey ) )
1063 		return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
1064 	*hKeyPtr = hKey;
1065 	return( CRYPT_OK );
1066 	}
1067 #endif /* 0 */
1068 
1069 /* Create a private-key context using a CryptoAPI native key */
1070 
createPrivkeyContext(DEVICE_INFO * deviceInfo,CRYPT_CONTEXT * iCryptContext,CRYPT_ALGO_TYPE * cryptAlgo,const HCRYPTKEY hKey,const char * label)1071 static int createPrivkeyContext( DEVICE_INFO *deviceInfo,
1072 								 CRYPT_CONTEXT *iCryptContext,
1073 								 CRYPT_ALGO_TYPE *cryptAlgo,
1074 								 const HCRYPTKEY hKey,
1075 								 const char *label )
1076 	{
1077 	ALG_ID algID;
1078 	DWORD dwDataLen = sizeof( ALG_ID );
1079 	const CAPABILITY_INFO *capabilityInfoPtr = NULL;
1080 	MESSAGE_DATA msgData;
1081 	int status;
1082 
1083 	/* Clear return values */
1084 	*iCryptContext = CRYPT_ERROR;
1085 	*cryptAlgo = CRYPT_ALGO_NONE;
1086 
1087 	/* Get the algorithm type and look up the corresponding capability
1088 	   information */
1089 	if( !pCryptGetKeyParam( hKey, KP_ALGID, ( BYTE * ) &algID, &dwDataLen,
1090 							0 ) || \
1091 		( *cryptAlgo = capiToCryptlibID( algID ) ) == CRYPT_ALGO_NONE )
1092 		return( CRYPT_ERROR_NOTAVAIL );
1093 	capabilityInfoPtr = findCapabilityInfo( deviceInfo->capabilityInfoList,
1094 											*cryptAlgo );
1095 	if( capabilityInfoPtr == NULL )
1096 		return( CRYPT_ERROR_NOTAVAIL );
1097 
1098 	/* Create a dummy context for the key, remember the device it's
1099 	   contained in, the object's label, and the handle for the device-
1100 	   internal key, and mark it as initialised (i.e. with a key loaded) */
1101 	status = createContextFromCapability( iCryptContext,
1102 								deviceInfo->ownerHandle, capabilityInfoPtr,
1103 								CREATEOBJECT_FLAG_DUMMY | \
1104 								CREATEOBJECT_FLAG_PERSISTENT );
1105 	if( cryptStatusError( status ) )
1106 		return( status );
1107 	krnlSendMessage( *iCryptContext, IMESSAGE_SETDEPENDENT,
1108 					 &deviceInfo->objectHandle, SETDEP_OPTION_INCREF );
1109 	krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE,
1110 					 ( MESSAGE_CAST ) &hKey, CRYPT_IATTRIBUTE_DEVICEOBJECT );
1111 	setMessageData( &msgData, ( MESSAGE_CAST ) label,
1112 					min( strlen( label ), CRYPT_MAX_TEXTSIZE ) );
1113 #if 0
1114 	if( cryptAlgo == CRYPT_ALGO_RSA )
1115 		/* Send the keying information to the context.  This is only
1116 		   possible for RSA keys since it's not possible to read y from a
1117 		   DSA private key object (see the comments in the DSA code for more
1118 		   on this), however the only time this is necessary is when a
1119 		   certificate is being generated for a key that was pre-generated
1120 		   in the device by someone else, which is typically done in Europe
1121 		   where DSA isn't used so this shouldn't be a problem */
1122 		// Use getPubkeyComponents()
1123 		cryptStatus = rsaSetPublicComponents( deviceInfo, *iCryptContext,
1124 											  hObject );
1125 	else
1126 		cryptStatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE,
1127 									   &keySize, CRYPT_IATTRIBUTE_KEYSIZE );
1128 #endif
1129 	if( cryptStatusOK( status ) )
1130 		status = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE_S,
1131 								  &msgData, CRYPT_CTXINFO_LABEL );
1132 	if( cryptStatusOK( status ) )
1133 		status = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE,
1134 								   MESSAGE_VALUE_UNUSED,
1135 								   CRYPT_IATTRIBUTE_INITIALISED );
1136 	if( cryptStatusError( status ) )
1137 		{
1138 		krnlSendNotifier( *iCryptContext, IMESSAGE_DECREFCOUNT );
1139 		return( status );
1140 		}
1141 
1142 	return( CRYPT_OK );
1143 	}
1144 
1145 /****************************************************************************
1146 *																			*
1147 *					Device Init/Shutdown/Device Control Routines			*
1148 *																			*
1149 ****************************************************************************/
1150 
1151 /* Prototypes for functions to get and free device capability information */
1152 
1153 static int getCapabilities( DEVICE_INFO *deviceInfo );
1154 static void freeCapabilities( DEVICE_INFO *deviceInfo );
1155 
1156 /* Close a previously-opened session with the device.  We have to have this
1157    before the initialisation function since it may be called by it if the
1158    initialisation process fails */
1159 
shutdownFunction(DEVICE_INFO * deviceInfo)1160 static void shutdownFunction( DEVICE_INFO *deviceInfo )
1161 	{
1162 	CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
1163 
1164 	/* Log out and close the session with the device */
1165 	if( deviceInfo->flags & DEVICE_LOGGEDIN )
1166 		{
1167 		if( cryptoapiInfo->hPrivateKey )
1168 			pCryptDestroyKey( cryptoapiInfo->hPrivateKey );
1169 		pCryptReleaseContext( cryptoapiInfo->hProv, 0 );
1170 		}
1171 	if( cryptoapiInfo->hCertStore != NULL )
1172 		{
1173 		pCertCloseStore( cryptoapiInfo->hCertStore, 0 );
1174 		cryptoapiInfo->hCertStore = 0;
1175 		}
1176 	cryptoapiInfo->hProv = HCRYPTPROV_NONE;
1177 	deviceInfo->flags &= ~( DEVICE_ACTIVE | DEVICE_LOGGEDIN );
1178 
1179 	/* Free the device capability information */
1180 	freeCapabilities( deviceInfo );
1181 	}
1182 
1183 /* Open a session with the device */
1184 
initFunction(DEVICE_INFO * deviceInfo,const char * name,const int nameLength)1185 static int initFunction( DEVICE_INFO *deviceInfo, const char *name,
1186 						 const int nameLength )
1187 	{
1188 	CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
1189 	HCRYPTPROV hProv;
1190 	HCERTSTORE hCertStore;
1191 	char providerNameBuffer[ CRYPT_MAX_TEXTSIZE + 1 + 8 ];
1192 	char keysetNameBuffer[ CRYPT_MAX_TEXTSIZE + 1 + 8 ];
1193 	const char *keysetName = NULL;
1194 	DWORD value;
1195 	int i, driverNameLength = nameLength, status;
1196 
1197 	/* Check whether a keyset name has been specified */
1198 	strlcpy_s( keysetNameBuffer, CRYPT_MAX_TEXTSIZE, "MY" );/* Default keyset */
1199 	for( i = 1; i < nameLength - 1; i++ )
1200 		{
1201 		if( name[ i ] == ':' && name[ i + 1 ] == ':' )
1202 			{
1203 			const int keysetNameLength = nameLength - ( i + 2 );
1204 
1205 			if( i > CRYPT_MAX_TEXTSIZE || keysetNameLength <= 0 || \
1206 				keysetNameLength > CRYPT_MAX_TEXTSIZE )
1207 				return( CRYPT_ARGERROR_STR1 );
1208 
1209 			/* We've got a keyset name appended to the provider name, break
1210 			   out the provider and keyset names */
1211 			memcpy( providerNameBuffer, name, i );
1212 			providerNameBuffer[ i ] = '\0';
1213 			memcpy( keysetNameBuffer, name + i + 2, keysetNameLength );
1214 			keysetNameBuffer[ keysetNameLength ] = '\0';
1215 			name = providerNameBuffer;
1216 			keysetName = keysetNameBuffer;
1217 			break;
1218 			}
1219 		}
1220 
1221 	/* If we're auto-detecting the device, try various choices */
1222 	if( driverNameLength == 12 && \
1223 		!strnicmp( "[Autodetect]", name, driverNameLength ) )
1224 		{
1225 		if( CryptAcquireContextA( &hProv, keysetName, MS_ENHANCED_PROV,
1226 								  PROV_RSA_FULL, 0 ) )
1227 			cryptoapiInfo->hProv = hProv;
1228 		else
1229 			{
1230 			if( CryptAcquireContextA( &hProv, keysetName, MS_DEF_PROV,
1231 									  PROV_RSA_FULL, 0 ) )
1232 				cryptoapiInfo->hProv = hProv;
1233 			else
1234 				return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
1235 			}
1236 		}
1237 	else
1238 		{
1239 		/* Try and find a specific provider */
1240 		if( CryptAcquireContextA( &hProv, keysetName, name, PROV_RSA_FULL, 0 ) )
1241 			cryptoapiInfo->hProv = hProv;
1242 		}
1243 
1244 	/* Get information on device-specific capabilities */
1245 	value = CRYPT_MAX_TEXTSIZE + 1;
1246 	if( !CryptGetProvParam( cryptoapiInfo->hProv, PP_NAME,
1247 							cryptoapiInfo->label, &value, 0 ) )
1248 		return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
1249 	cryptoapiInfo->labelLen = value;
1250 	deviceInfo->label = cryptoapiInfo->label;
1251 	deviceInfo->labelLen = cryptoapiInfo->labelLen;
1252 	deviceInfo->flags |= DEVICE_ACTIVE;
1253 
1254 	/* Set up the capability information for this device */
1255 	status = getCapabilities( deviceInfo );
1256 	if( cryptStatusError( status ) )
1257 		{
1258 		shutdownFunction( deviceInfo );
1259 		return( ( status == CRYPT_ERROR ) ? CRYPT_ERROR_OPEN : status );
1260 		}
1261 
1262 	/* Create the special-purpose key needed to allow symmetric key loads */
1263 	status = createExportKey( cryptoapiInfo->hProv,
1264 							  &cryptoapiInfo->hPrivateKey,
1265 							  &cryptoapiInfo->privateKeySize );
1266 	if( cryptStatusError( status ) )
1267 		{
1268 		shutdownFunction( deviceInfo );
1269 		return( status );
1270 		}
1271 
1272 	/* Open the certificate store used to store/retrieve certificates */
1273 	hCertStore = pCertOpenSystemStore( cryptoapiInfo->hProv,
1274 									   keysetNameBuffer );
1275 	if( hCertStore == NULL )
1276 		{
1277 		shutdownFunction( deviceInfo );
1278 		return( CRYPT_ERROR_OPEN );
1279 		}
1280 	cryptoapiInfo->hCertStore = hCertStore;
1281 
1282 	return( CRYPT_OK );
1283 	}
1284 
1285 /* Handle device control functions */
1286 
controlFunction(DEVICE_INFO * deviceInfo,const CRYPT_ATTRIBUTE_TYPE type,const void * data,const int dataLength,MESSAGE_FUNCTION_EXTINFO * messageExtInfo)1287 static int controlFunction( DEVICE_INFO *deviceInfo,
1288 							const CRYPT_ATTRIBUTE_TYPE type,
1289 							const void *data, const int dataLength,
1290 							MESSAGE_FUNCTION_EXTINFO *messageExtInfo )
1291 	{
1292 	retIntError();
1293 	}
1294 
1295 /****************************************************************************
1296 *																			*
1297 *						 	Misc.Device Interface Routines					*
1298 *																			*
1299 ****************************************************************************/
1300 
1301 /* Get random data from the device */
1302 
getRandomFunction(DEVICE_INFO * deviceInfo,void * buffer,const int length,MESSAGE_FUNCTION_EXTINFO * messageExtInfo)1303 static int getRandomFunction( DEVICE_INFO *deviceInfo, void *buffer,
1304 							  const int length,
1305 							  MESSAGE_FUNCTION_EXTINFO *messageExtInfo )
1306 	{
1307 	CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
1308 
1309 	if( pCryptGenRandom( cryptoapiInfo->hProv, length, buffer ) )
1310 		return( CRYPT_OK );
1311 	return( mapError( cryptoapiInfo, CRYPT_ERROR_FAILED ) );
1312 	}
1313 
1314 /* Instantiate an object in a device.  This works like the create context
1315    function but instantiates a cryptlib object using data already contained
1316    in the device (for example a stored private key or certificate).  If the
1317    value being read is a public key and there's a certificate attached, the
1318    instantiated object is a native cryptlib object rather than a device
1319    object with a native certificate object attached because there doesn't
1320    appear to be any good reason to create the public-key object in the
1321    device.
1322 
1323    CryptoAPI doesn't have any concept of multiple private keys, only a
1324    default encryption + signature key for the provider as a whole, and an
1325    optional additional signature key to complement the encryption (and
1326    signature if necessary) one.  In addition the ties between a private key
1327    and its associated certificate(s) are rather tenuous, requiring jumping
1328    through several levels of indirection in order to get from one to the
1329    other.  To handle this, we have to use a meet-in-the-middle approach
1330    where we try to go from private key to certificate if the identity of the
1331    private key is obvious (the user has specifically asked for a private
1332    decryption or signature key), or from certificate to private key in all
1333    other cases */
1334 
getItemFunction(DEVICE_INFO * deviceInfo,CRYPT_CONTEXT * iCryptContext,const KEYMGMT_ITEM_TYPE itemType,const CRYPT_KEYID_TYPE keyIDtype,const void * keyID,const int keyIDlength,void * auxInfo,int * auxInfoLength,const int flags)1335 static int getItemFunction( DEVICE_INFO *deviceInfo,
1336 							CRYPT_CONTEXT *iCryptContext,
1337 							const KEYMGMT_ITEM_TYPE itemType,
1338 							const CRYPT_KEYID_TYPE keyIDtype,
1339 							const void *keyID, const int keyIDlength,
1340 							void *auxInfo, int *auxInfoLength,
1341 							const int flags )
1342 	{
1343 	CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
1344 //	CRYPT_CERTIFICATE iCryptCert;
1345 	HCRYPTKEY hKey = 0;
1346 	PCCERT_CONTEXT pCertContext = NULL;
1347 	PCCERT_CHAIN_CONTEXT pChainContext = NULL;
1348 	DWORD dwKeySpec = 0;
1349 	CRYPT_CERTIFICATE iCryptCert;
1350 	CRYPT_ALGO_TYPE cryptAlgo = CRYPT_ALGO_NONE;
1351 	const char *label = "Private key";
1352 	int status;
1353 
1354 	assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
1355 			itemType == KEYMGMT_ITEM_PRIVATEKEY );
1356 
1357 	/* If we're searching for the key by label and the user has specified
1358 	   one of the special-case key descriptions, get the appropriate key */
1359 	if( keyIDtype == CRYPT_KEYID_NAME )
1360 		{
1361 		if( keyIDlength == 13 && \
1362 			!memcmp( keyID, "Signature key", 13 ) )
1363 			dwKeySpec = AT_SIGNATURE;
1364 		else
1365 			if( keyIDlength == 14 && \
1366 				!memcmp( keyID, "Encryption key", 14 ) )
1367 				dwKeySpec = AT_KEYEXCHANGE;
1368 		}
1369 
1370 	/* If we haven't got a key type from the label and we're looking for a
1371 	   particular usage, get the appropriate key */
1372 	if( dwKeySpec == 0 && itemType == KEYMGMT_ITEM_PRIVATEKEY )
1373 		{
1374 		if( flags & KEYMGMT_FLAG_USAGE_SIGN )
1375 			dwKeySpec = AT_SIGNATURE;
1376 		else
1377 			if( flags & KEYMGMT_FLAG_USAGE_CRYPT )
1378 				dwKeySpec = AT_KEYEXCHANGE;
1379 		}
1380 
1381 	/* If we still haven't got a key type, try and get the certificate for
1382 	   the given ID */
1383 	if( dwKeySpec != 0 )
1384 		{
1385 		/* Get the required key type */
1386 		if( !pCryptGetUserKey( cryptoapiInfo->hProv, dwKeySpec, &hKey ) )
1387 			return( CRYPT_ERROR_NOTFOUND );
1388 		label = ( dwKeySpec == AT_SIGNATURE ) ? \
1389 				"Signature key" : "Encryption key";
1390 
1391 		/* If we're only doing a presence check, we don't need the key and
1392 		   can exit */
1393 		if( flags & KEYMGMT_FLAG_CHECK_ONLY )
1394 			{
1395 			pCryptDestroyKey( hKey );
1396 			return( CRYPT_OK );
1397 			}
1398 
1399 		/* Since CryptoAPI doesn't have any concept of key labels, the best
1400 		   that we can do is provide a generic description of the intended
1401 		   key usage as a form of pseudo-label */
1402 		if( flags & KEYMGMT_FLAG_LABEL_ONLY )
1403 			{
1404 			strlcpy_s( auxInfo, *auxInfoLength, label );
1405 			*auxInfoLength = strlen( label );
1406 			pCryptDestroyKey( hKey );
1407 			return( CRYPT_OK );
1408 			}
1409 
1410 		/* We've got the key, try and get the associated certificate */
1411 		status = getCertificateFromKey( cryptoapiInfo, hKey,
1412 										( flags & KEYMGMT_FLAG_USAGE_SIGN ) ? \
1413 											TRUE : FALSE, &pCertContext );
1414 		if( cryptStatusError( status ) && \
1415 			itemType == KEYMGMT_ITEM_PUBLICKEY )
1416 			{
1417 			/* We couldn't get a certificate for the key, if we're after a
1418 			   public key return it as a native context */
1419 			status = capiToCryptlibContext( cryptoapiInfo, hKey,
1420 											iCryptContext );
1421 			pCryptDestroyKey( hKey );
1422 			return( status );
1423 			}
1424 		}
1425 	else
1426 		{
1427 		assert( !( flags & KEYMGMT_FLAG_LABEL_ONLY ) );
1428 
1429 		/* We don't have a definite private key ID indicator, go via the
1430 		   certificate instead */
1431 		status = getCertificate( cryptoapiInfo, keyIDtype, keyID, keyIDlength,
1432 								 &pCertContext );
1433 		if( cryptStatusError( status ) )
1434 			return( status );
1435 
1436 		/* If we're only doing a presence check, we don't need the key and
1437 		   can exit */
1438 		if( flags & KEYMGMT_FLAG_CHECK_ONLY )
1439 			{
1440 			pCertFreeCertificateContext( pCertContext );
1441 			return( CRYPT_OK );
1442 			}
1443 
1444 		/* If we're after a private key, try and find the one corresponding
1445 		   to the certificate */
1446 		if( itemType == KEYMGMT_ITEM_PRIVATEKEY )
1447 			{
1448 #if 1
1449 			CERT_KEY_CONTEXT certKeyContext;
1450 			DWORD certKeyContextSize = sizeof( CERT_KEY_CONTEXT );
1451 
1452 			if( !pCertGetCertificateContextProperty( pCertContext,
1453 									CERT_KEY_CONTEXT_PROP_ID,
1454 									&certKeyContext, &certKeyContextSize ) || \
1455 				!pCryptGetUserKey( certKeyContext.hCryptProv,
1456 								   certKeyContext.dwKeySpec, &hKey ) )
1457 				return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
1458 
1459 #else		/* Need to uncomment gPKFC() above */
1460 			status = getPrivKeyFromCertificate( cryptoapiInfo, pCertContext,
1461 												&hKey );
1462 #endif
1463 			if( cryptStatusError( status ) )
1464 				{
1465 				pCertFreeCertificateContext( pCertContext );
1466 				return( status );
1467 				}
1468 			}
1469 		}
1470 
1471 	/* If we've got a priavte key, create a device context for it */
1472 	if( hKey != 0 )
1473 		{
1474 		status = createPrivkeyContext( deviceInfo, iCryptContext,
1475 									   &cryptAlgo, hKey, label );
1476 		if( cryptStatusError( status ) )
1477 			{
1478 			if( pCertContext != NULL )
1479 				pCertFreeCertificateContext( pCertContext );
1480 			return( status );
1481 			}
1482 		}
1483 
1484 	/* If there's no certificate available for the key, we're done */
1485 	if( pCertContext == NULL )
1486 		return( CRYPT_OK );
1487 
1488 	/* We've got a key and certificate, try and get the rest of the chain
1489 	   for the certificate */
1490 {
1491 BOOLEAN publicComponentsOnly = FALSE;
1492 
1493 	status = iCryptImportCertIndirect( &iCryptCert,
1494 								deviceInfo->objectHandle, keyIDtype, keyID,
1495 								keyIDlength, publicComponentsOnly ? \
1496 									KEYMGMT_FLAG_NONE : \
1497 									KEYMGMT_FLAG_DATAONLY_CERT );
1498 }
1499 
1500 	if( cryptStatusOK( status ) )
1501 		{
1502 		/* If we're getting a public key, the returned information is the
1503 		   certificate chain */
1504 		if( itemType == KEYMGMT_ITEM_PUBLICKEY )
1505 			*iCryptContext = iCryptCert;
1506 		else
1507 			{
1508 			/* If we're getting a private key, attach the certificate chain
1509 			   to the context.  The certificate is an internal object used
1510 			   only by the context so we tell the kernel to mark it as owned
1511 			   by the context only */
1512 			status = krnlSendMessage( *iCryptContext, IMESSAGE_SETDEPENDENT,
1513 									   &iCryptCert, SETDEP_OPTION_NOINCREF );
1514 			}
1515 		}
1516 
1517 	/* Clean up */
1518 	pCertFreeCertificateContext( pCertContext );
1519 	pCertFreeCertificateChain( pChainContext );
1520 	return( status );
1521 
1522 #if 0
1523 		{
1524 		const int keyTemplateCount = ( keyID == NULL ) ? 1 : 2;
1525 
1526 		/* Try and find the object with the given label/ID, or the first
1527 		   object of the given class if no ID is given */
1528 		keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) \
1529 								  ( ( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? \
1530 								  &pubkeyClass : &privkeyClass );
1531 		if( keyIDtype != CRYPT_KEYID_NONE )
1532 			{
1533 			if( keyIDtype == CRYPT_IKEYID_KEYID )
1534 				keyTemplate[ 1 ].type = CKA_ID;
1535 			keyTemplate[ 1 ].pValue = ( CK_VOID_PTR ) keyID;
1536 			keyTemplate[ 1 ].ulValueLen = keyIDlength;
1537 			}
1538 		cryptStatus = findObject( deviceInfo, &hObject, keyTemplate,
1539 								  keyTemplateCount );
1540 		if( cryptStatus == CRYPT_ERROR_NOTFOUND && \
1541 			itemType == KEYMGMT_ITEM_PUBLICKEY )
1542 			{
1543 			/* Some devices may only contain private key objects with
1544 			   associated certificates that can't be picked out of the other
1545 			   cruft that's present without going via the private key, so if
1546 			   we're looking for a public key and don't find one, we try
1547 			   again for a private key whose sole function is to point to an
1548 			   associated certificate */
1549 			keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &privkeyClass;
1550 			cryptStatus = findObject( deviceInfo, &hObject, keyTemplate,
1551 									  keyTemplateCount );
1552 			if( cryptStatusError( cryptStatus ) )
1553 				return( cryptStatus );
1554 
1555 			/* Remember that although we've got a private key object, we only
1556 			   need it to find the associated certificate and not finding an
1557 			   associated certificate is an error */
1558 			certViaPrivateKey = TRUE;
1559 			}
1560 		}
1561 
1562 	/* If we're looking for any kind of private key and we either have an
1563 	   explicit certificate ID but couldn't find a certificate for it or we
1564 	   don't have a proper ID to search on and a generic search found more
1565 	   than one matching object, chances are we're after a generic decrypt
1566 	   key.  The former only occurs in misconfigured or limited-memory
1567 	   tokens, the latter only in rare tokens that store more than one
1568 	   private key, typically one for signing and one for verification.
1569 
1570 	   If either of these cases occur we try again looking specifically for
1571 	   a decryption key.  Even this doesn't always work, there's are some
1572 	   >1-key tokens that mark a signing key as a decryption key so we still
1573 	   get a CRYPT_ERROR_DUPLICATE error.
1574 
1575 	   Finally, if we can't find a decryption key either, we look for an
1576 	   unwrapping key.  This may or may not work, depending on whether we
1577 	   have a decryption key marked as valid for unwrapping but not
1578 	   decryption, or a key that's genuinely only valid for unwrapping, but
1579 	   at this point we're ready to try anything */
1580 	if( itemType == KEYMGMT_ITEM_PRIVATEKEY && \
1581 		( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER && \
1582 		  cryptStatus == CRYPT_ERROR_NOTFOUND ) || \
1583 		( cryptStatus == CRYPT_ERROR_DUPLICATE ) )
1584 		{
1585 		static const CK_BBOOL bTrue = TRUE;
1586 		CK_ATTRIBUTE decryptKeyTemplate[] = {
1587 			{ CKA_CLASS, ( CK_VOID_PTR ) &privkeyClass, sizeof( CK_OBJECT_CLASS ) },
1588 			{ CKA_DECRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) }
1589 			};
1590 
1591 		cryptStatus = findObject( deviceInfo, &hObject,
1592 								  decryptKeyTemplate, 2 );
1593 		if( cryptStatusError( cryptStatus ) )
1594 			{
1595 			decryptKeyTemplate[ 1 ].type = CKA_UNWRAP;
1596 			cryptStatus = findObject( deviceInfo, &hObject,
1597 									  decryptKeyTemplate, 2 );
1598 			}
1599 		}
1600 	if( cryptStatusError( cryptStatus ) )
1601 		return( cryptStatus );
1602 
1603 	/* If we're just checking whether an object exists, return now.  If all
1604 	   we want is the key label, copy it back to the caller and exit */
1605 	if( flags & KEYMGMT_FLAG_CHECK_ONLY )
1606 		return( CRYPT_OK );
1607 	if( flags & KEYMGMT_FLAG_LABEL_ONLY )
1608 		return( getObjectLabel( deviceInfo, hObject, auxInfo,
1609 								auxInfoLength ) );
1610 
1611 	/* We found something, map the key type to a cryptlib algorithm ID,
1612 	   determine the key size, and find its capabilities */
1613 	keyTypeTemplate.pValue = &keyType;
1614 	C_GetAttributeValue( cryptoapiInfo->hProv, hObject,
1615 						 &keyTypeTemplate, 1 );
1616 	switch( ( int ) keyType )
1617 		{
1618 		case CKK_RSA:
1619 			cryptAlgo = CRYPT_ALGO_RSA;
1620 			keySizeTemplate.type = CKA_MODULUS;
1621 			break;
1622 		case CKK_DSA:
1623 			cryptAlgo = CRYPT_ALGO_DSA;
1624 			keySizeTemplate.type = CKA_PRIME;
1625 			break;
1626 		case CKK_DH:
1627 			cryptAlgo = CRYPT_ALGO_DH;
1628 			keySizeTemplate.type = CKA_PRIME;
1629 			break;
1630 		default:
1631 			return( CRYPT_ERROR_NOTAVAIL );
1632 		}
1633 	C_GetAttributeValue( cryptoapiInfo->hProv, hObject,
1634 						 &keySizeTemplate, 1 );
1635 	keySize = keySizeTemplate.ulValueLen;
1636 	capabilityInfoPtr = findCapabilityInfo( deviceInfo->capabilityInfo,
1637 											cryptAlgo );
1638 	if( capabilityInfoPtr == NULL )
1639 		return( CRYPT_ERROR_NOTAVAIL );
1640 
1641 	/* Try and find a certificate which matches the key.  The process is as
1642 	   follows:
1643 
1644 		if certificate object found in issuerAndSerialNumber search
1645 			create native data-only certificate object
1646 			attach certificate object to key
1647 		else
1648 			if public key
1649 				if certificate
1650 					create native certificate (+context) object
1651 				else
1652 					create device pubkey object, mark as "key loaded"
1653 			else
1654 				create device privkey object, mark as "key loaded"
1655 				if certificate
1656 					create native data-only certificate object
1657 					attach certificate object to key
1658 
1659 	   The reason for doing things this way is given in the comments earlier
1660 	   on in this function */
1661 	if( privateKeyViaCert )
1662 		{
1663 		/* We've already got the certificate object handle, instantiate a
1664 		   native data-only certificate from it */
1665 		cryptStatus = instantiateCert( deviceInfo, hCertificate,
1666 									   &iCryptCert, FALSE );
1667 		if( cryptStatusError( cryptStatus ) )
1668 			return( cryptStatus );
1669 		certPresent = TRUE;
1670 		}
1671 	else
1672 		{
1673 		cryptStatus = findCertFromObject( deviceInfo, hObject, &iCryptCert,
1674 										  ( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? \
1675 										  FINDCERT_NORMAL : FINDCERT_DATAONLY );
1676 		if( cryptStatusError( cryptStatus ) )
1677 			{
1678 			/* If we get a CRYPT_ERROR_NOTFOUND this is OK since it means
1679 			   there's no certificate present, however anything else is an
1680 			   error.  In addition if we've got a private key whose only
1681 			   function is to point to an associated certificate then not
1682 			   finding anything is also an error */
1683 			if( cryptStatus != CRYPT_ERROR_NOTFOUND || certViaPrivateKey )
1684 				return( cryptStatus );
1685 			}
1686 		else
1687 			{
1688 			/* We got the certificate, if we're being asked for a public key
1689 			   then we've created a native object to contain it so we return
1690 			   that */
1691 			certPresent = TRUE;
1692 			if( itemType == KEYMGMT_ITEM_PUBLICKEY )
1693 				{
1694 				*iCryptContext = iCryptCert;
1695 				return( CRYPT_OK );
1696 				}
1697 			}
1698 		}
1699 #endif
1700 	}
1701 
1702 /* Update a device with a certificate */
1703 
setItemFunction(DEVICE_INFO * deviceInfo,const CRYPT_HANDLE iCryptHandle)1704 static int setItemFunction( DEVICE_INFO *deviceInfo,
1705 							const CRYPT_HANDLE iCryptHandle )
1706 	{
1707 	CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
1708 	HCRYPTKEY hKey;
1709 	DWORD dwKeySpec = 0;
1710 	CRYPT_CERTIFICATE iCryptCert;
1711 	BOOLEAN seenNonDuplicate = FALSE;
1712 	int iterationCount = 0, status;
1713 
1714 	/* Lock the certificate for our exclusive use (in case it's a
1715 	   certificate chain, we also select the first certificate in the
1716 	   chain), update the device with the certificate, and unlock it to
1717 	   allow others access */
1718 	status = krnlSendMessage( iCryptHandle, IMESSAGE_GETDEPENDENT, &iCryptCert,
1719 							  OBJECT_TYPE_CERTIFICATE );
1720 	if( cryptStatusOK( status ) )
1721 		{
1722 		status = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
1723 								  MESSAGE_VALUE_CURSORFIRST,
1724 								  CRYPT_CERTINFO_CURRENT_CERTIFICATE );
1725 		}
1726 	if( cryptStatusOK( status ) )
1727 		{
1728 		status = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
1729 								  MESSAGE_VALUE_TRUE,
1730 								  CRYPT_IATTRIBUTE_LOCKED );
1731 		}
1732 	if( cryptStatusError( status ) )
1733 		return( status );
1734 
1735 	/* Check whether the leaf certificate matches any of the user's private
1736 	   keys */
1737 	if( pCryptGetUserKey( cryptoapiInfo->hProv, AT_KEYEXCHANGE, &hKey ) )
1738 		{
1739 		if( isCertKey( cryptoapiInfo, hKey, iCryptCert ) )
1740 			dwKeySpec = AT_KEYEXCHANGE;
1741 		pCryptDestroyKey( hKey );
1742 		}
1743 	else
1744 		{
1745 		if( pCryptGetUserKey( cryptoapiInfo->hProv, AT_SIGNATURE, &hKey ) )
1746 			{
1747 			if( isCertKey( cryptoapiInfo, hKey, iCryptCert ) )
1748 				dwKeySpec = AT_SIGNATURE;
1749 			pCryptDestroyKey( hKey );
1750 			}
1751 		}
1752 
1753 	/* Add each certificate in the chain to the store */
1754 	do
1755 		{
1756 		DYNBUF certDB;
1757 		BOOL result = FALSE;
1758 
1759 		/* Get the certificate data and add it to the store */
1760 		status = dynCreate( &certDB, iCryptHandle,
1761 							CRYPT_CERTFORMAT_CERTIFICATE );
1762 		if( cryptStatusError( status ) )
1763 			return( status );
1764 
1765 		/* If the certificate corresponds to one of the user's private keys
1766 		   and a binding between the key and a certificate isn't already
1767 		   established, establish one now */
1768 		if( dwKeySpec != 0 )
1769 			{
1770 			PCCERT_CONTEXT pCertContext;
1771 			CERT_KEY_CONTEXT certKeyContext;
1772 			DWORD certKeyContextSize = sizeof( CERT_KEY_CONTEXT );
1773 
1774 			/* Check whether the certificate is already bound to a key and
1775 			   if not, bind it to the appropriate private key */
1776 			pCertContext = pCertCreateCertificateContext( X509_ASN_ENCODING,
1777 									dynData( certDB ), dynLength( certDB ) );
1778 			if( pCertContext != NULL && \
1779 				!pCertGetCertificateContextProperty( pCertContext,
1780 									CERT_KEY_CONTEXT_PROP_ID,
1781 									&certKeyContext, &certKeyContextSize ) )
1782 				{
1783 #if 1
1784 				/* Check the certificate stores synchronising the
1785 				   certificate's CERT_KEY_PROV_INFO_PROP_ID with any present
1786 				   private keys if required */
1787 				pCryptFindCertificateKeyProvInfo( pCertContext, 0, NULL );
1788 #elif 0
1789 				CRYPT_KEY_PROV_INFO keyProvInfo;
1790 				BYTE buffer[ 256 + 8 ];
1791 				DWORD length = 256;
1792 				wchar_t provName[ 256 + 8 ], container[ 256 + 8 ];
1793 
1794 				if( pCryptGetProvParam( cryptoapiInfo->hProv, PP_NAME,
1795 										buffer, &length, 0 ) )
1796 					MultiByteToWideChar( GetACP(), 0, buffer, length + 1,
1797 										 provName, 256 );
1798 				if( pCryptGetProvParam( cryptoapiInfo->hProv, PP_CONTAINER,
1799 										buffer, &length, 0 ) )
1800 					MultiByteToWideChar( GetACP(), 0, buffer, length + 1,
1801 										 container, 256 );
1802 				memset( &keyProvInfo, 0, sizeof( CRYPT_KEY_PROV_INFO ) );
1803 				keyProvInfo.pwszContainerName = container;
1804 				keyProvInfo.pwszProvName = provName;
1805 				keyProvInfo.dwProvType = PROV_RSA_FULL;
1806 				keyProvInfo.cProvParam = 0;
1807 				keyProvInfo.dwKeySpec = dwKeySpec;
1808 				pCertSetCertificateContextProperty( pCertContext,
1809 									CERT_KEY_PROV_HANDLE_PROP_ID, 0,
1810 									&keyProvInfo );
1811 #elif 0
1812 				memset( &certKeyContext, 0, sizeof( CERT_KEY_CONTEXT ) );
1813 				certKeyContext.cbSize = sizeof( CERT_KEY_CONTEXT );
1814 				certKeyContext.dwKeySpec = dwKeySpec;
1815 				certKeyContext.hCryptProv = cryptoapiInfo->hProv;
1816 				pCertSetCertificateContextProperty( pCertContext,
1817 									CERT_KEY_CONTEXT_PROP_ID, 0,
1818 									&certKeyContext );
1819 #endif
1820 				}
1821 
1822 			/* Add the certificate to the store */
1823 			if( pCertContext != NULL )
1824 				{
1825 				result = pCertAddCertificateContextToStore( cryptoapiInfo->hCertStore,
1826 								pCertContext, CERT_STORE_ADD_NEW, NULL );
1827 				pCertFreeCertificateContext( pCertContext );
1828 				}
1829 
1830 			/* We've now added a bound certificate, don't bind the key to
1831 			   any more certificates */
1832 			dwKeySpec = 0;
1833 			}
1834 		else
1835 			{
1836 			/* Add the certificate to the store */
1837 			result = pCertAddEncodedCertificateToStore( cryptoapiInfo->hCertStore,
1838 							X509_ASN_ENCODING, dynData( certDB ),
1839 							dynLength( certDB ), CERT_STORE_ADD_NEW, NULL );
1840 			}
1841 		dynDestroy( &certDB );
1842 		if( result )
1843 			seenNonDuplicate = TRUE;
1844 		}
1845 	while( krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
1846 							MESSAGE_VALUE_CURSORNEXT,
1847 							CRYPT_CERTINFO_CURRENT_CERTIFICATE ) == CRYPT_OK && \
1848 		   iterationCount++ < FAILSAFE_ITERATIONS_MED );
1849 	if( iterationCount >= FAILSAFE_ITERATIONS_MED )
1850 		retIntError();
1851 
1852 	krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE, MESSAGE_VALUE_FALSE,
1853 					 CRYPT_IATTRIBUTE_LOCKED );
1854 
1855 	return( seenNonDuplicate ? CRYPT_OK : CRYPT_ERROR_DUPLICATE );
1856 	}
1857 
1858 /* Delete an object in a device */
1859 
deleteItemFunction(DEVICE_INFO * deviceInfo,const KEYMGMT_ITEM_TYPE itemType,const CRYPT_KEYID_TYPE keyIDtype,const void * keyID,const int keyIDlength)1860 static int deleteItemFunction( DEVICE_INFO *deviceInfo,
1861 							   const KEYMGMT_ITEM_TYPE itemType,
1862 							   const CRYPT_KEYID_TYPE keyIDtype,
1863 							   const void *keyID, const int keyIDlength )
1864 	{
1865 #if 0
1866 	static const CK_OBJECT_CLASS pubkeyClass = CKO_PUBLIC_KEY;
1867 	static const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY;
1868 	static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
1869 	static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
1870 	CK_ATTRIBUTE certTemplate[] = {
1871 		{ CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
1872 		{ CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
1873 		{ CKA_LABEL, ( CK_VOID_PTR ) keyID, keyIDlength }
1874 		};
1875 	CK_ATTRIBUTE keyTemplate[] = {
1876 		{ CKA_CLASS, ( CK_VOID_PTR ) &pubkeyClass, sizeof( CK_OBJECT_CLASS ) },
1877 		{ CKA_LABEL, ( CK_VOID_PTR ) keyID, keyIDlength }
1878 		};
1879 	CK_OBJECT_HANDLE hPrivkey = CRYPT_ERROR, hCertificate = CRYPT_ERROR;
1880 	CK_OBJECT_HANDLE hPubkey = CRYPT_ERROR;
1881 	CK_RV status;
1882 	int cryptStatus;
1883 
1884 	assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
1885 			itemType == KEYMGMT_ITEM_PRIVATEKEY );
1886 	assert( keyIDtype == CRYPT_KEYID_NAME );
1887 	assert( keyIDlength > 0 && keyIDlength <= CRYPT_MAX_TEXTSIZE );
1888 
1889 	/* Find the object to delete based on the label.  Since we can have
1890 	   multiple related objects (e.g. a key and a certificate) with the same
1891 	   label, a straight search for all objects with a given label could
1892 	   return CRYPT_ERROR_DUPLICATE so we search for the objects by type as
1893 	   well as label.  In addition even a search for specific objects can
1894 	   return CRYPT_ERROR_DUPLICATE so we use the Ex version of findObject()
1895 	   to make sure we don't get an error if multiple objects exist.
1896 	   Although cryptlib won't allow more than one object with a given label
1897 	   to be created, other applications might create duplicate labels.  The
1898 	   correct behaviour in these circumstances is uncertain, what we do for
1899 	   now is delete the first object we find that matches the label.
1900 
1901 	   First we try for a certificate and use that to find associated keys */
1902 	cryptStatus = findObjectEx( deviceInfo, &hCertificate, certTemplate, 3 );
1903 	if( cryptStatusOK( cryptStatus ) )
1904 		{
1905 		/* We got a certificate, if there are associated keys delete them as
1906 		   well */
1907 		cryptStatus = findObjectFromObject( deviceInfo, hCertificate,
1908 											CKO_PUBLIC_KEY, &hPubkey );
1909 		if( cryptStatusError( cryptStatus ) )
1910 			hPubkey = CRYPT_ERROR;
1911 		cryptStatus = findObjectFromObject( deviceInfo, hCertificate,
1912 											CKO_PRIVATE_KEY, &hPrivkey );
1913 		if( cryptStatusError( cryptStatus ) )
1914 			hPrivkey = CRYPT_ERROR;
1915 		}
1916 	else
1917 		{
1918 		/* We didn't find a certificate with the given label, try for public
1919 		   and private keys */
1920 		cryptStatus = findObjectEx( deviceInfo, &hPubkey, keyTemplate, 2 );
1921 		if( cryptStatusError( cryptStatus ) )
1922 			hPubkey = CRYPT_ERROR;
1923 		keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &privkeyClass;
1924 		cryptStatus = findObjectEx( deviceInfo, &hPrivkey, keyTemplate, 2 );
1925 		if( cryptStatusError( cryptStatus ) )
1926 			hPrivkey = CRYPT_ERROR;
1927 
1928 		/* There may be an unlabelled certificate present, try and find it by
1929 		   looking for a certificate matching the key ID */
1930 		if( hPubkey != CRYPT_ERROR || hPrivkey != CRYPT_ERROR )
1931 			{
1932 			cryptStatus = findObjectFromObject( deviceInfo,
1933 							( hPrivkey != CRYPT_ERROR ) ? hPrivkey : hPubkey,
1934 							CKO_CERTIFICATE, &hCertificate );
1935 			if( cryptStatusError( cryptStatus ) )
1936 				hCertificate = CRYPT_ERROR;
1937 			}
1938 		}
1939 
1940 	/* If we found a public key with a given label but no private key, try
1941 	   and find a matching private key by ID, and vice versa */
1942 	if( hPubkey != CRYPT_ERROR && hPrivkey == CRYPT_ERROR )
1943 		{
1944 		cryptStatus = findObjectFromObject( deviceInfo, hPubkey,
1945 											CKO_PRIVATE_KEY, &hPrivkey );
1946 		if( cryptStatusError( cryptStatus ) )
1947 			hPrivkey = CRYPT_ERROR;
1948 		}
1949 	if( hPrivkey != CRYPT_ERROR && hPubkey == CRYPT_ERROR )
1950 		{
1951 		cryptStatus = findObjectFromObject( deviceInfo, hPrivkey,
1952 											CKO_PUBLIC_KEY, &hPubkey );
1953 		if( cryptStatusError( cryptStatus ) )
1954 			hPubkey = CRYPT_ERROR;
1955 		}
1956 	if( hPrivkey == CRYPT_ERROR && hPubkey == CRYPT_ERROR )
1957 		return( CRYPT_ERROR_NOTFOUND );
1958 
1959 	/* Reset the status values, which may contain error values due to not
1960 	   finding various objects to delete above */
1961 	cryptStatus = CRYPT_OK;
1962 	status = CKR_OK;
1963 
1964 	/* Delete the objects */
1965 	if( hCertificate != CRYPT_ERROR )
1966 		status = C_DestroyObject( cryptoapiInfo->hProv, hCertificate );
1967 	if( hPubkey != CRYPT_ERROR )
1968 		{
1969 		int status2;
1970 
1971 		status2 = C_DestroyObject( cryptoapiInfo->hProv, hPubkey );
1972 		if( status2 != CKR_OK && status == CKR_OK )
1973 			status = status2;
1974 		}
1975 	if( hPrivkey != CRYPT_ERROR )
1976 		{
1977 		int status2;
1978 
1979 		status2 = C_DestroyObject( cryptoapiInfo->hProv, hPrivkey );
1980 		if( status2 != CKR_OK && status == CKR_OK )
1981 			status = status2;
1982 		}
1983 	if( status != CKR_OK )
1984 		cryptStatus = mapError( deviceInfo, status, CRYPT_ERROR_FAILED );
1985 	return( cryptStatus );
1986 #endif
1987 
1988 	return( CRYPT_ERROR );
1989 	}
1990 
1991 /* Get the sequence of certificates in a chain from a device.  Unfortunately
1992    we can't really make the certificate chain fetch stateless without re-
1993    doing the read of the entire chain from the CryptoAPI certificate store
1994    for each fetch.  To avoid this performance hit we cache the chain in the
1995    device information and pick out each certificate in turn during the
1996    findNext */
1997 
getFirstItemFunction(DEVICE_INFO * deviceInfo,CRYPT_CERTIFICATE * iCertificate,int * stateInfo,const CRYPT_KEYID_TYPE keyIDtype,const void * keyID,const int keyIDlength,const KEYMGMT_ITEM_TYPE itemType,const int options)1998 static int getFirstItemFunction( DEVICE_INFO *deviceInfo,
1999 								 CRYPT_CERTIFICATE *iCertificate,
2000 								 int *stateInfo,
2001 								 const CRYPT_KEYID_TYPE keyIDtype,
2002 								 const void *keyID, const int keyIDlength,
2003 								 const KEYMGMT_ITEM_TYPE itemType,
2004 								 const int options )
2005 	{
2006 	CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
2007 	PCCERT_CONTEXT pCertContext;
2008 	PCCERT_CHAIN_CONTEXT pChainContext;
2009 	MESSAGE_CREATEOBJECT_INFO createInfo;
2010 	int status;
2011 
2012 	assert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
2013 	assert( keyIDtype == CRYPT_IKEYID_KEYID );
2014 	assert( isReadPtr( keyID, keyIDlength ) );
2015 	assert( keyIDlength > 4 && keyIDlength < MAX_INTLENGTH_SHORT );
2016 	assert( isWritePtr( stateInfo, sizeof( int ) ) );
2017 	assert( itemType == KEYMGMT_ITEM_PUBLICKEY );
2018 
2019 	/* Clear return values */
2020 	*iCertificate = CRYPT_ERROR;
2021 	*stateInfo = CRYPT_ERROR;
2022 	cryptoapiInfo->hCertChain = NULL;
2023 
2024 	/* Try and find the certificate with the given ID.  This should work
2025 	   because we've just read the ID for the indirect-import that lead to
2026 	   the getFirst call */
2027 	status = getCertificate( cryptoapiInfo, keyIDtype, keyID, keyIDlength,
2028 							 &pCertContext );
2029 	if( cryptStatusError( status ) )
2030 		{
2031 		DEBUG_DIAG(( "Failed to load CryptoAPI certificate data" ));
2032 		assert( DEBUG_WARN );
2033 		return( status );
2034 		}
2035 
2036 	/* Now try and get the chain from the certificate.  If this fails, we
2037 	   just use the standalone certificate */
2038 	status = getCertificateChain( cryptoapiInfo, pCertContext,
2039 								  &pChainContext );
2040 	if( cryptStatusOK( status ) )
2041 		cryptoapiInfo->hCertChain = pChainContext;
2042 
2043 	/* Import the leaf certificate as a cryptlib object */
2044 	setMessageCreateObjectIndirectInfo( &createInfo,
2045 										pCertContext->pbCertEncoded,
2046 										pCertContext->cbCertEncoded,
2047 										CRYPT_CERTTYPE_CERTIFICATE );
2048 	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
2049 							  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
2050 							  &createInfo, OBJECT_TYPE_CERTIFICATE );
2051 	pCertFreeCertificateContext( pCertContext );
2052 	if( cryptStatusError( status ) )
2053 		{
2054 		if( cryptoapiInfo->hCertChain != NULL )
2055 			pCertFreeCertificateChain( cryptoapiInfo->hCertChain );
2056 		return( status );
2057 		}
2058 
2059 	/* Remember that we've got the leaf certificate in the chain */
2060 	assert( pChainContext->cChain == 1 );
2061 	*stateInfo = 1;
2062 	return( CRYPT_OK );
2063 	}
2064 
getNextItemFunction(DEVICE_INFO * deviceInfo,CRYPT_CERTIFICATE * iCertificate,int * stateInfo,const int options)2065 static int getNextItemFunction( DEVICE_INFO *deviceInfo,
2066 								CRYPT_CERTIFICATE *iCertificate,
2067 								int *stateInfo, const int options )
2068 	{
2069 	CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
2070 	PCCERT_CHAIN_CONTEXT pChainContext = cryptoapiInfo->hCertChain;
2071 	PCERT_SIMPLE_CHAIN pCertSimpleChain;
2072 	PCERT_CHAIN_ELEMENT pCertChainElement;
2073 	MESSAGE_CREATEOBJECT_INFO createInfo;
2074 	int status;
2075 
2076 	assert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
2077 	assert( isWritePtr( stateInfo, sizeof( int ) ) );
2078 	assert( *stateInfo == CRYPT_ERROR || *stateInfo >= 1 );
2079 
2080 	/* Clear return value */
2081 	*iCertificate = CRYPT_ERROR;
2082 
2083 	/* If the previous certificate was the last one, there's nothing left to
2084 	   fetch */
2085 	if( cryptoapiInfo->hCertChain == NULL )
2086 		{
2087 		*stateInfo = CRYPT_ERROR;
2088 		return( CRYPT_ERROR_NOTFOUND );
2089 		}
2090 	pCertSimpleChain = pChainContext->rgpChain[ 0 ];
2091 	if( *stateInfo < 1 || *stateInfo > pCertSimpleChain->cElement )
2092 		{
2093 		pCertFreeCertificateChain( cryptoapiInfo->hCertChain );
2094 		cryptoapiInfo->hCertChain = NULL;
2095 		*stateInfo = CRYPT_ERROR;
2096 		return( CRYPT_ERROR_NOTFOUND );
2097 		}
2098 
2099 	/* Get the next certificate in the chain */
2100 	pCertChainElement = pCertSimpleChain->rgpElement[ *stateInfo ];
2101 	setMessageCreateObjectIndirectInfo( &createInfo,
2102 							pCertChainElement->pCertContext->pbCertEncoded,
2103 							pCertChainElement->pCertContext->cbCertEncoded,
2104 							CRYPT_CERTTYPE_CERTIFICATE );
2105 	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
2106 							  IMESSAGE_DEV_CREATEOBJECT_INDIRECT,
2107 							  &createInfo, OBJECT_TYPE_CERTIFICATE );
2108 	if( cryptStatusError( status ) )
2109 		{
2110 		pCertFreeCertificateChain( cryptoapiInfo->hCertChain );
2111 		cryptoapiInfo->hCertChain = NULL;
2112 		*stateInfo = CRYPT_ERROR;
2113 		return( status );
2114 		}
2115 	( *stateInfo )++;
2116 	return( CRYPT_OK );
2117 	}
2118 
2119 /****************************************************************************
2120 *																			*
2121 *						 	Capability Interface Routines					*
2122 *																			*
2123 ****************************************************************************/
2124 
2125 /* Clean up the object associated with a context */
2126 
genericEndFunction(CONTEXT_INFO * contextInfoPtr)2127 static int genericEndFunction( CONTEXT_INFO *contextInfoPtr )
2128 	{
2129 	/* Since the device object that corresponds to the cryptlib object is
2130 	   created on-demand, it may not exist yet if the action that triggers
2131 	   the on-demand creation hasn't been taken yet.  If no device object
2132 	   exists, we're done */
2133 	if( contextInfoPtr->deviceObject == CRYPT_ERROR )
2134 		return( CRYPT_OK );
2135 
2136 	/* Destroy the object */
2137 	if( contextInfoPtr->capabilityInfo->keySize > 0 )
2138 		pCryptDestroyKey( contextInfoPtr->deviceObject );
2139 	else
2140 		pCryptDestroyHash( contextInfoPtr->deviceObject );
2141 	return( CRYPT_OK );
2142 	}
2143 
2144 /* RSA algorithm-specific mapping functions.  Since CryptoAPI adds its own
2145    PKCS #1 padding, we add/remove the cryptlib-added padding to fake out the
2146    presence of a raw RSA mechanism */
2147 
rsaSetKeyInfo(CRYPTOAPI_INFO * cryptoapiInfo,CONTEXT_INFO * contextInfoPtr)2148 static int rsaSetKeyInfo( CRYPTOAPI_INFO *cryptoapiInfo,
2149 						  CONTEXT_INFO *contextInfoPtr )
2150 	{
2151 	BYTE n[ CRYPT_MAX_PKCSIZE + 8 ], e[ CRYPT_MAX_PKCSIZE + 8 ];
2152 	BYTE keyDataBuffer[ ( CRYPT_MAX_PKCSIZE * 2 ) + 8 ];
2153 	MESSAGE_DATA msgData;
2154 	int nLen, eLen, keyDataSize, status;
2155 
2156 	/* Extract the public-key components from the CryptoAPI context */
2157 	status = getPubkeyComponents( cryptoapiInfo,
2158 								  contextInfoPtr->deviceObject,
2159 								  n, &nLen, e, &eLen );
2160 	if( cryptStatusError( status ) )
2161 		return( status );
2162 
2163 	/* Send the public key data to the context.  We send the keying
2164 	   information as CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL rather than
2165 	   CRYPT_IATTRIBUTE_KEY_SPKI since the latter transitions the context
2166 	   into the high state.  We don't want to do this because we're already
2167 	   in the middle of processing a message that does this on completion,
2168 	   all we're doing here is sending in encoded public key data for use by
2169 	   objects such as certificates */
2170 	status = writeFlatPublicKey( keyDataBuffer, CRYPT_MAX_PKCSIZE * 2,
2171 								 &keyDataSize, CRYPT_ALGO_RSA, 0,
2172 								 n, nLen, e, eLen, NULL, 0, NULL, 0 );
2173 	if( cryptStatusOK( status ) )
2174 		{
2175 		setMessageData( &msgData, keyDataBuffer, keyDataSize );
2176 		status = krnlSendMessage( contextInfoPtr->objectHandle,
2177 								  IMESSAGE_SETATTRIBUTE_S, &msgData,
2178 								  CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL );
2179 		}
2180 	return( status );
2181 	}
2182 
rsaInitKey(CONTEXT_INFO * contextInfoPtr,const void * key,const int keyLength)2183 static int rsaInitKey( CONTEXT_INFO *contextInfoPtr, const void *key,
2184 					   const int keyLength )
2185 	{
2186 	CRYPT_DEVICE iCryptDevice;
2187 	CRYPTOAPI_INFO *cryptoapiInfo;
2188 	CRYPT_PKCINFO_RSA *rsaKey = ( CRYPT_PKCINFO_RSA * ) key;
2189 	HCRYPTKEY hKey;
2190 	BLOBHEADER *blobHeaderPtr;
2191 	RSAPUBKEY *pubKeyPtr;
2192 	BYTE keyBlob[ ( CRYPT_MAX_PKCSIZE * 8 ) + 8 ], *keyBlobPtr;
2193 	DWORD exponent = 0L;
2194 	BOOL result;
2195 	const int nLen = bitsToBytes( rsaKey->nLen );
2196 	int i, status;
2197 
2198 	/* CryptoAPI sets some awkward constraints on key formats, only allowing
2199 	   exponents that can be represented as 32-bit ints and requiring that
2200 	   the lengths of all MPIs be explicitly specified by the modulus size,
2201 	   so we have to check whether the key components are in this form
2202 	   before we can try and load the key */
2203 	if( bitsToBytes( rsaKey->eLen ) > sizeof( DWORD ) )
2204 		return( CRYPT_ERROR_BADDATA );
2205 	if( !rsaKey->isPublicKey && \
2206 		( ( bitsToBytes( rsaKey->pLen ) > nLen / 2 ) || \
2207 		  ( bitsToBytes( rsaKey->qLen ) > nLen / 2 ) || \
2208 		  ( bitsToBytes( rsaKey->e1Len ) > nLen / 2 ) || \
2209 		  ( bitsToBytes( rsaKey->e2Len ) > nLen / 2 ) || \
2210 		  ( bitsToBytes( rsaKey->uLen ) > nLen / 2 ) || \
2211 		  ( bitsToBytes( rsaKey->dLen ) > nLen ) ) )
2212 		return( CRYPT_ERROR_BADDATA );
2213 
2214 	/* Get the exponent as a DWORD */
2215 	for( i = 0; i < bitsToBytes( rsaKey->eLen ); i++ )
2216 		exponent = ( exponent << 8 ) | rsaKey->e[ i ];
2217 
2218 	/* Get the information for the device associated with this context */
2219 	status = getContextDeviceInfo( contextInfoPtr->objectHandle,
2220 								   &iCryptDevice, &cryptoapiInfo );
2221 	if( cryptStatusError( status ) )
2222 		return( status );
2223 
2224 	/* Set up the blob header:
2225 
2226 		Ofs	Value
2227 		  0	BLOBHEADER blobheader {
2228 			  0	BYTE bType;
2229 			  1	BYTE bVersion;
2230 			  2 WORD reserved;
2231 			  4	ALG_ID aiKeyAlg; }
2232 		  8	RSAPUBKEY rsapubkey {
2233 			  8 DWORD magic;
2234 			 12	DWORD bitlen;
2235 			 16	DWORD pubexp; }
2236 		 20	BYTE modulus[ rsapubkey.bitlen / 8 ];
2237 			BYTE prime1[ rsapubkey.bitlen / 16 ];
2238 			BYTE prime2[ rsapubkey.bitlen / 16 ];
2239 			BYTE exponent1[ rsapubkey.bitlen / 16 ];
2240 			BYTE exponent2[ rsapubkey.bitlen / 16 ];
2241 			BYTE coefficient[ rsapubkey.bitlen / 16 ];
2242 			BYTE privateExponent[ rsapubkey.bitlen / 8 ]; */
2243 	memset( keyBlob, 0, CRYPT_MAX_PKCSIZE * 8 );
2244 	blobHeaderPtr = ( BLOBHEADER * ) keyBlob;
2245 	blobHeaderPtr->bType = intToByte( ( rsaKey->isPublicKey ) ? \
2246 									  PUBLICKEYBLOB : PRIVATEKEYBLOB );
2247 	blobHeaderPtr->bVersion = CUR_BLOB_VERSION;
2248 	blobHeaderPtr->aiKeyAlg = CALG_RSA_KEYX;
2249 
2250 	/* Set up the public-key components.  CryptoAPI requires that the
2251 	   modulus length be a multiple of 8 bits, so we have to round up the
2252 	   length to the nearest byte boundary */
2253 	pubKeyPtr = ( RSAPUBKEY * ) ( keyBlob + BLOBHEADER_SIZE );
2254 	pubKeyPtr->magic = ( rsaKey->isPublicKey ) ? 0x31415352 : 0x32415352;
2255 	pubKeyPtr->bitlen = roundUp( rsaKey->nLen, 8 );
2256 	pubKeyPtr->pubexp = exponent;
2257 	keyBlobPtr = keyBlob + BLOBHEADER_SIZE + ( 3 * sizeof( DWORD ) );
2258 	keyBlobPtr = copyMPI( keyBlobPtr, rsaKey->n, nLen, nLen );
2259 
2260 	/* Set up the private-key components if necessary */
2261 	if( !rsaKey->isPublicKey )
2262 		{
2263 		keyBlobPtr = copyMPI( keyBlobPtr, rsaKey->p,
2264 							  bitsToBytes( rsaKey->pLen ), nLen / 2 );
2265 		keyBlobPtr = copyMPI( keyBlobPtr, rsaKey->q,
2266 							  bitsToBytes( rsaKey->qLen ), nLen / 2 );
2267 		keyBlobPtr = copyMPI( keyBlobPtr, rsaKey->e1,
2268 							  bitsToBytes( rsaKey->e1Len ), nLen / 2 );
2269 		keyBlobPtr = copyMPI( keyBlobPtr, rsaKey->e2,
2270 							  bitsToBytes( rsaKey->e2Len ), nLen / 2 );
2271 		keyBlobPtr = copyMPI( keyBlobPtr, rsaKey->u,
2272 							  bitsToBytes( rsaKey->uLen ), nLen / 2 );
2273 		keyBlobPtr = copyMPI( keyBlobPtr, rsaKey->d,
2274 							  bitsToBytes( rsaKey->dLen ), nLen );
2275 		}
2276 
2277 	/* Import the key blob and clean up */
2278 	result = pCryptImportKey( cryptoapiInfo->hProv, keyBlob,
2279 							  keyBlobPtr - keyBlob, 0, 0, &hKey );
2280 	if( result )
2281 		{
2282 		/* Note that the following will break under Win64 since the hKey is
2283 		   a 64-bit pointer while the deviceObject is a 32-bit unsigned
2284 		   value, this code is experimental and only enabled for Win32 debug
2285 		   so this isn't a problem at the moment */
2286 		contextInfoPtr->deviceObject = ( long ) hKey;
2287 		}
2288 	else
2289 		status = mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED );
2290 	zeroise( keyBlob, CRYPT_MAX_PKCSIZE * 8 );
2291 
2292 	/* Send the keying information to the context and set up the key ID
2293 	   information */
2294 	if( cryptStatusOK( status ) )
2295 		status = rsaSetKeyInfo( cryptoapiInfo, contextInfoPtr );
2296 
2297 	krnlReleaseObject( iCryptDevice );
2298 	return( status );
2299 	}
2300 
rsaGenerateKey(CONTEXT_INFO * contextInfoPtr,const int keysizeBits)2301 static int rsaGenerateKey( CONTEXT_INFO *contextInfoPtr, const int keysizeBits )
2302 	{
2303 	CRYPT_DEVICE iCryptDevice;
2304 	CRYPTOAPI_INFO *cryptoapiInfo;
2305 	HCRYPTKEY hPrivateKey;
2306 	BOOL result;
2307 	int status;
2308 
2309 	/* Get the information for the device associated with this context */
2310 	status = getContextDeviceInfo( contextInfoPtr->objectHandle,
2311 								   &iCryptDevice, &cryptoapiInfo );
2312 	if( cryptStatusError( status ) )
2313 		return( status );
2314 
2315 	/* Generate the key.  CryptoAPI kludges the key size information by
2316 	   masking it into the high bits of the flags parameter.  We make the
2317 	   key exportable, because the ability to hand out keys in PKCS #12
2318 	   format is the prime (only?) motivation for anyone using CryptoAPI */
2319 	result = pCryptGenKey( cryptoapiInfo->hProv, AT_KEYEXCHANGE,
2320 						   CRYPT_EXPORTABLE | ( keysizeBits << 16 ),
2321 						   &hPrivateKey );
2322 	if( result )
2323 		{
2324 		/* Note that the following will break under Win64 since the hKey is
2325 		   a 64-bit pointer while the deviceObject is a 32-bit unsigned
2326 		   value, this code is experimental and only enabled for Win32 debug
2327 		   so this isn't a problem at the moment */
2328 		contextInfoPtr->deviceObject = ( long ) hPrivateKey;
2329 		}
2330 	else
2331 		status = mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED );
2332 
2333 	/* Send the keying information to the context and set up the key ID
2334 	   information */
2335 	if( cryptStatusOK( status ) )
2336 		status = rsaSetKeyInfo( cryptoapiInfo, contextInfoPtr );
2337 
2338 	krnlReleaseObject( iCryptDevice );
2339 	return( status );
2340 	}
2341 
rsaSign(CONTEXT_INFO * contextInfoPtr,void * buffer,int length)2342 static int rsaSign( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )
2343 	{
2344 	CRYPT_DEVICE iCryptDevice;
2345 	CRYPTOAPI_INFO *cryptoapiInfo;
2346 	CRYPT_ALGO_TYPE cryptAlgo;
2347 	STREAM stream;
2348 	HCRYPTHASH hHash;
2349 	BYTE tempBuffer[ CRYPT_MAX_PKCSIZE + 8 ];
2350 	BYTE hashBuffer[ CRYPT_MAX_HASHSIZE + 8 ], *bufPtr = buffer;
2351 	ALG_ID algID;
2352 	DWORD resultLength = length;
2353 	BOOL result;
2354 	int i, status;
2355 
2356 	/* CryptoAPI adds its own PKCS #1 padding, so we have to reverse-engineer
2357 	   the encoding and padding that's already been added */
2358 	assert( bufPtr[ 0 ] == 0 && bufPtr[ 1 ] == 1 );
2359 	for( i = 2; i < length; i++ )
2360 		{
2361 		if( bufPtr[ i ] == 0 )
2362 			break;
2363 		}
2364 	i++;	/* Skip final 0 byte */
2365 	sMemConnect( &stream, bufPtr + i, length - i );
2366 	status = readMessageDigest( &stream, &cryptAlgo, hashBuffer,
2367 								CRYPT_MAX_HASHSIZE, &i );
2368 	sMemDisconnect( &stream );
2369 	if( cryptStatusError( status ) )
2370 		return( status );
2371 	algID = cryptlibToCapiID( cryptAlgo );
2372 	if( algID == 0 )
2373 		return( CRYPT_ERROR_NOTAVAIL );
2374 
2375 	/* Get the information for the device associated with this context */
2376 	status = getContextDeviceInfo( contextInfoPtr->objectHandle,
2377 								   &iCryptDevice, &cryptoapiInfo );
2378 	if( cryptStatusError( status ) )
2379 		return( status );
2380 
2381 	/* CryptoAPI can only sign hash values inside hash objects, luckily
2382 	   there's a function whose sole purpose is to allow hash values to be
2383 	   loaded directly into hash objects that we can use to create the hash
2384 	   to be signed.
2385 
2386 	   Once we've got the hash though, things get tricky.  CryptSignHash()
2387 	   doesn't let you specify which key you want to use for signing, but it
2388 	   does let you indicate that you want to use the default encryption-only
2389 	   key as your signature key.  This is sort of like building a car where
2390 	   the steering wheel won't turn, but in compensation the fuel tank will
2391 	   explode if you hit the horn */
2392 	result = pCryptCreateHash( cryptoapiInfo->hProv, algID, 0, 0, &hHash );
2393 	if( !result )
2394 		{
2395 		status = mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED );
2396 		krnlReleaseObject( iCryptDevice );
2397 		return( status );
2398 		}
2399 	result = pCryptSetHashParam( hHash, HP_HASHVAL, hashBuffer, 0 );
2400 	if( result )
2401 		result = pCryptSignHash( hHash, AT_KEYEXCHANGE, NULL, 0,
2402 								 tempBuffer, &resultLength );
2403 	pCryptDestroyHash( hHash );
2404 	if( result )
2405 		{
2406 		copyMPI( buffer, tempBuffer, resultLength, resultLength );
2407 		zeroise( tempBuffer, CRYPT_MAX_PKCSIZE + 8 );
2408 
2409 		/* Restore any truncated leading zeroes if necessary */
2410 		if( resultLength < length )
2411 			{
2412 			const int delta = length - resultLength;
2413 
2414 			memmove( ( BYTE * ) buffer + delta, tempBuffer, resultLength );
2415 			memset( buffer, 0, delta );
2416 			}
2417 		}
2418 	if( !result )
2419 		status = mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED );
2420 
2421 	krnlReleaseObject( iCryptDevice );
2422 	return( status );
2423 	}
2424 
rsaVerify(CONTEXT_INFO * contextInfoPtr,void * buffer,int length)2425 static int rsaVerify( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )
2426 	{
2427 	/* This function is present but isn't used as part of any normal
2428 	   operation because cryptlib does the same thing much faster in
2429 	   software and more importanyly because there's no way to get at the
2430 	   hash information that's needed to create the hash object, so that
2431 	   the trick used in rsaSign() won't work */
2432 	retIntError();
2433 	}
2434 
rsaEncrypt(CONTEXT_INFO * contextInfoPtr,void * buffer,int length)2435 static int rsaEncrypt( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )
2436 	{
2437 	BYTE tempBuffer[ CRYPT_MAX_PKCSIZE + 8 ], *tempPtr, *bufPtr = buffer;
2438 	DWORD resultLength;
2439 	int i;
2440 
2441 	/* CryptoAPI adds its own PKCS #1 padding, so we have to undo the
2442 	   padding that's already been added */
2443 	assert( bufPtr[ 0 ] == 0 && bufPtr[ 1 ] == 2 );
2444 	for( i = 2; i < length; i++ )
2445 		{
2446 		if( bufPtr[ i ] == 0 )
2447 			break;
2448 		}
2449 	i++;	/* Skip final 0 byte */
2450 
2451 	/* Change the data into the little-endian order required by CryptoAPI,
2452 	   encrypt it, reverse the order again */
2453 	tempPtr = copyMPI( tempBuffer, bufPtr + i, length - i, length - i );
2454 	resultLength = tempPtr - tempBuffer;
2455 	if( !pCryptEncrypt( contextInfoPtr->deviceObject, 0, TRUE, 0,
2456 						tempBuffer, &resultLength, length ) )
2457 		{
2458 		zeroise( tempBuffer, CRYPT_MAX_PKCSIZE + 8 );
2459 		return( mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED ) );
2460 		}
2461 	copyMPI( buffer, tempBuffer, resultLength, resultLength );
2462 	zeroise( tempBuffer, CRYPT_MAX_PKCSIZE + 8 );
2463 
2464 	/* Restore any truncated leading zeroes if necessary */
2465 	if( resultLength < length )
2466 		{
2467 		const int delta = length - resultLength;
2468 
2469 		memmove( ( BYTE * ) buffer + delta, tempBuffer, resultLength );
2470 		memset( buffer, 0, delta );
2471 		}
2472 	return( CRYPT_OK );
2473 	}
2474 
rsaDecrypt(CONTEXT_INFO * contextInfoPtr,void * buffer,int length)2475 static int rsaDecrypt( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )
2476 	{
2477 	BYTE tempBuffer[ CRYPT_MAX_PKCSIZE + 8 ], *tempPtr, *bufPtr = buffer;
2478 	DWORD resultLength;
2479 	int i;
2480 
2481 	/* Change the data into the little-endian order required by CryptoAPI,
2482 	   decrypt it, and reverse the order again */
2483 	tempPtr = copyMPI( tempBuffer, bufPtr, length, length );
2484 	resultLength = tempPtr - tempBuffer;
2485 	if( !pCryptDecrypt( contextInfoPtr->deviceObject, 0, FALSE, 0,
2486 						tempBuffer, &resultLength ) )
2487 		{
2488 		zeroise( tempBuffer, CRYPT_MAX_PKCSIZE + 8 );
2489 		return( mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED ) );
2490 		}
2491 	copyMPI( buffer, tempBuffer, resultLength, resultLength );
2492 	zeroise( tempBuffer, CRYPT_MAX_PKCSIZE + 8 );
2493 
2494 	/* Redo the PKCS #1 padding that was stripped by CryptoAPI */
2495 	memmove( bufPtr + length - resultLength, bufPtr, resultLength );
2496 	bufPtr[ 0 ] = 0;
2497 	bufPtr[ 1 ] = 2;
2498 	for( i = 2; i < length - resultLength - 1; i++ )
2499 		bufPtr[ i ] = 0xA5;
2500 	bufPtr[ i ] = 0;
2501 	assert( i + 1 + resultLength == length );
2502 	return( CRYPT_OK );
2503 	}
2504 
2505 /* DSA algorithm-specific mapping functions */
2506 
2507 #if 0
2508 
2509 static int dsaSetKeyInfo( DEVICE_INFO *deviceInfo, CONTEXT_INFO *contextInfoPtr,
2510 //						  const CK_OBJECT_HANDLE hPrivateKey,
2511 //						  const CK_OBJECT_HANDLE hPublicKey,
2512 						  const void *p, const int pLen,
2513 						  const void *q, const int qLen,
2514 						  const void *g, const int gLen,
2515 						  const void *y, const int yLen )
2516 	{
2517 	MESSAGE_DATA msgData;
2518 	BYTE keyDataBuffer[ ( CRYPT_MAX_PKCSIZE * 2 ) + 8 ];
2519 	BYTE idBuffer[ KEYID_SIZE + 8 ];
2520 	int keyDataSize, cryptStatus;
2521 
2522 	/* Send the public key data to the context.  We send the keying
2523 	   information as CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL rather than
2524 	   CRYPT_IATTRIBUTE_KEY_SPKI since the latter transitions the context
2525 	   into the high state.  We don't want to do this because we're already
2526 	   in the middle of processing a message that does this on completion,
2527 	   all we're doing here is sending in encoded public key data for use by
2528 	   objects such as certificates */
2529 	cryptStatus = keyDataSize = writeFlatPublicKey( NULL, 0, CRYPT_ALGO_DSA, 0,
2530 													p, pLen, q, qLen,
2531 													g, gLen, y, yLen );
2532 	if( !cryptStatusError( cryptStatus ) )
2533 		cryptStatus = writeFlatPublicKey( keyDataBuffer, CRYPT_MAX_PKCSIZE * 2,
2534 										  CRYPT_ALGO_DSA, 0, p, pLen, q, qLen,
2535 										  g, gLen, y, yLen );
2536 	if( !cryptStatusError( cryptStatus ) )
2537 		{
2538 		setMessageData( &msgData, keyDataBuffer, keyDataSize );
2539 		cryptStatus = krnlSendMessage( contextInfoPtr->objectHandle,
2540 									   IMESSAGE_SETATTRIBUTE_S, &msgData,
2541 									   CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL );
2542 		}
2543 	if( cryptStatusError( cryptStatus ) )
2544 		return( cryptStatus );
2545 
2546 	/* Remember what we've set up */
2547 	krnlSendMessage( contextInfoPtr->objectHandle, IMESSAGE_SETATTRIBUTE,
2548 					 ( MESSAGE_CAST ) &hPrivateKey,
2549 					 CRYPT_IATTRIBUTE_DEVICEOBJECT );
2550 
2551 	/* Get the key ID from the context and use it as the object ID.  Since
2552 	   some objects won't allow after-the-even ID updates, we don't treat a
2553 	   failure to update as an error */
2554 	setMessageData( &msgData, idBuffer, KEYID_SIZE );
2555 	cryptStatus = krnlSendMessage( contextInfoPtr->objectHandle,
2556 								   IMESSAGE_GETATTRIBUTE_S, &msgData,
2557 								   CRYPT_IATTRIBUTE_KEYID );
2558 	if( cryptStatusOK( cryptStatus ) )
2559 		{
2560 		CK_ATTRIBUTE idTemplate = { CKA_ID, msgData.data, msgData.length };
2561 
2562 		if( hPublicKey != CRYPT_UNUSED )
2563 			{
2564 			C_SetAttributeValue( cryptoapiInfo->hProv, hPublicKey,
2565 								 &idTemplate, 1 );
2566 			}
2567 		C_SetAttributeValue( cryptoapiInfo->hProv, hPrivateKey,
2568 							 &idTemplate, 1 );
2569 		}
2570 
2571 	return( cryptStatus );
2572 	return( CRYPT_ERROR );
2573 	}
2574 #endif /* 0 */
2575 
dsaInitKey(CONTEXT_INFO * contextInfoPtr,const void * key,const int keyLength)2576 static int dsaInitKey( CONTEXT_INFO *contextInfoPtr, const void *key,
2577 					   const int keyLength )
2578 	{
2579 	CRYPT_DEVICE iCryptDevice;
2580 	CRYPTOAPI_INFO *cryptoapiInfo;
2581 	CRYPT_PKCINFO_DLP *dlpKey = ( CRYPT_PKCINFO_DLP * ) key;
2582 	HCRYPTKEY hKey;
2583 	BLOBHEADER *blobHeaderPtr;
2584 	DSSPUBKEY *pubKeyPtr;
2585 	BYTE keyBlob[ ( CRYPT_MAX_PKCSIZE * 4 ) + 8 ], *keyBlobPtr;
2586 	BOOL result;
2587 	const int pLen = bitsToBytes( dlpKey->pLen );
2588 	int status;
2589 
2590 	/* CryptoAPI sets some awkward constraints on key formats, only allowing
2591 	   a prime size up to 1024 bits, so we have to check whether the key
2592 	   components are in this form before we can try and load the key */
2593 	if( dlpKey->pLen > 1024 )
2594 		return( CRYPT_ERROR_BADDATA );
2595 
2596 	/* Get the information for the device associated with this context */
2597 	status = getContextDeviceInfo( contextInfoPtr->objectHandle,
2598 								   &iCryptDevice, &cryptoapiInfo );
2599 	if( cryptStatusError( status ) )
2600 		return( status );
2601 
2602 	/* Set up the blob header:
2603 
2604 		Ofs	Value
2605 		  0	BLOBHEADER blobheader {
2606 			  0	BYTE bType;
2607 			  1	BYTE bVersion;
2608 			  2 WORD reserved;
2609 			  4	ALG_ID aiKeyAlg; }
2610 		  8	DSSPUBKEY_VER3 dsspubkey {
2611 			  8 DWORD magic;
2612 			 12	DWORD bitlen; }
2613 		 16	BYTE p[ 128 ];
2614 			BYTE q[ 20 ];
2615 			BYTE g[ 128 ];
2616 			BYTE y[ 128 ]; */
2617 	memset( keyBlob, 0, CRYPT_MAX_PKCSIZE * 4 );
2618 	blobHeaderPtr = ( BLOBHEADER * ) keyBlob;
2619 	blobHeaderPtr->bType = intToByte( ( dlpKey->isPublicKey ) ? \
2620 									  PUBLICKEYBLOB : PRIVATEKEYBLOB );
2621 	blobHeaderPtr->bVersion = CUR_BLOB_VERSION;
2622 	blobHeaderPtr->aiKeyAlg = CALG_DSS_SIGN;
2623 
2624 	/* Set up the public-key components.  CryptoAPI requires that the
2625 	   modulus length be a multiple of 8 bits, so we have to round up the
2626 	   length to the nearest byte boundary */
2627 	pubKeyPtr = ( DSSPUBKEY * ) ( keyBlob + BLOBHEADER_SIZE );
2628 	pubKeyPtr->magic = 0x31535344;
2629 	pubKeyPtr->bitlen = roundUp( dlpKey->pLen, 8 );
2630 	keyBlobPtr = keyBlob + BLOBHEADER_SIZE + ( 2 * sizeof( DWORD ) );
2631 	keyBlobPtr = copyMPI( keyBlobPtr, dlpKey->p, pLen, 128 );
2632 	keyBlobPtr = copyMPI( keyBlobPtr, dlpKey->q,
2633 						  bitsToBytes( dlpKey->qLen ), 20 );
2634 	keyBlobPtr = copyMPI( keyBlobPtr, dlpKey->g,
2635 						  bitsToBytes( dlpKey->gLen ), 128 );
2636 	keyBlobPtr = copyMPI( keyBlobPtr, dlpKey->y,
2637 						  bitsToBytes( dlpKey->yLen ), 128 );
2638 
2639 	/* Set up the private-key components if necessary */
2640 	if( !dlpKey->isPublicKey )
2641 		{
2642 		}
2643 
2644 	/* Import the key blob and clean up */
2645 	result = pCryptImportKey( cryptoapiInfo->hProv, keyBlob,
2646 							  keyBlobPtr - keyBlob, 0, 0, &hKey );
2647 	if( result )
2648 		{
2649 		/* Note that the following will break under Win64 since the hKey is
2650 		   a 64-bit pointer while the deviceObject is a 32-bit unsigned
2651 		   value, this code is experimental and only enabled for Win32 debug
2652 		   so this isn't a problem at the moment */
2653 		contextInfoPtr->deviceObject = ( long ) hKey;
2654 		}
2655 	else
2656 		status = mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED );
2657 	zeroise( keyBlob, CRYPT_MAX_PKCSIZE * 4 );
2658 
2659 	krnlReleaseObject( iCryptDevice );
2660 	return( status );
2661 	}
2662 
dsaGenerateKey(CONTEXT_INFO * contextInfoPtr,const int keysizeBits)2663 static int dsaGenerateKey( CONTEXT_INFO *contextInfoPtr, const int keysizeBits )
2664 	{
2665 #if 0
2666 	static const CK_MECHANISM mechanism = { CKM_DSA_KEY_PAIR_GEN, NULL_PTR, 0 };
2667 	static const CK_BBOOL bTrue = TRUE;
2668 	const CK_ULONG modulusBits = keysizeBits;
2669 	CK_ATTRIBUTE privateKeyTemplate[] = {
2670 		{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
2671 		{ CKA_PRIVATE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
2672 		{ CKA_SENSITIVE, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
2673 		{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },
2674 		{ CKA_SIGN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
2675 		};
2676 	CK_ATTRIBUTE publicKeyTemplate[] = {
2677 		{ CKA_TOKEN, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
2678 		{ CKA_LABEL, contextInfoPtr->label, contextInfoPtr->labelSize },
2679 		{ CKA_VERIFY, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) },
2680 		{ CKA_PRIME, NULL, 0 },
2681 		{ CKA_SUBPRIME, NULL, 0 },
2682 		{ CKA_BASE, NULL, 0 },
2683 		};
2684 	CK_ATTRIBUTE yValueTemplate = { CKA_VALUE, NULL, CRYPT_MAX_PKCSIZE * 2 };
2685 	CK_OBJECT_HANDLE hPublicKey, hPrivateKey;
2686 	MESSAGE_CREATEOBJECT_INFO createInfo;
2687 	MESSAGE_DATA msgData;
2688 	CRYPT_DEVICE iCryptDevice;
2689 	BYTE pubkeyBuffer[ ( CRYPT_MAX_PKCSIZE * 2 ) + 8 ], label[ 8 + 8 ];
2690 	CK_RV status;
2691 	STREAM stream;
2692 	long length;
2693 	int keyLength = bitsToBytes( keysizeBits ), cryptStatus;
2694 
2695 	/* CKM_DSA_KEY_PAIR_GEN is really a Clayton's key generation mechanism
2696 	   since it doesn't actually generate the p, q, or g values (presumably
2697 	   it dates back to the original FIPS 186 shared domain parameters idea).
2698 	   Because of this we'd have to generate half the key ourselves in a
2699 	   native context, then copy portions from the native context over in
2700 	   flat form and complete the keygen via the device.  The easiest way to
2701 	   do this is to create a native DSA context, generate a key, grab the
2702 	   public portions, and destroy the context again (i.e. generate a full
2703 	   key on a superscalar 2GHz RISC CPU, then throw half of it away, and
2704 	   regenerate it on a 5MHz 8-bit tinkertoy).  Since the keygen can take
2705 	   awhile and doesn't require the device, we do it before we grab the
2706 	   device */
2707 	setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_DSA );
2708 	cryptStatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
2709 								   IMESSAGE_DEV_CREATEOBJECT, &createInfo,
2710 								   OBJECT_TYPE_CONTEXT );
2711 	if( cryptStatusError( cryptStatus ) )
2712 		return( cryptStatus );
2713 	setMessageData( &msgData, label, 8 );
2714 	krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S,
2715 					 &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
2716 	krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE_S,
2717 					 &msgData, CRYPT_CTXINFO_LABEL );
2718 	krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,
2719 					 ( int * ) &keyLength, CRYPT_CTXINFO_KEYSIZE );
2720 	cryptStatus = krnlSendMessage( createInfo.cryptHandle,
2721 								   IMESSAGE_CTX_GENKEY, NULL, FALSE );
2722 	if( cryptStatusOK( cryptStatus ) )
2723 		{
2724 		setMessageData( &msgData, pubkeyBuffer, CRYPT_MAX_PKCSIZE * 2 );
2725 		cryptStatus = krnlSendMessage( createInfo.cryptHandle,
2726 									   IMESSAGE_GETATTRIBUTE_S, &msgData,
2727 									   CRYPT_IATTRIBUTE_KEY_SPKI );
2728 		}
2729 	krnlSendNotifier( createInfo.cryptHandle, IMESSAGE_DECREFCOUNT );
2730 	if( cryptStatusError( cryptStatus ) )
2731 		return( cryptStatus );
2732 
2733 	/* Set up the public key information by extracting the flat values from
2734 	   the SubjectPublicKeyInfo.  Note that the data used is represented in
2735 	   DER-canonical form, there may be PKCS #11 implementations that
2736 	   can't handle this (for example they may require q to be zero-padded
2737 	   to make it exactly 20 bytes rather than (say) 19 bytes if the high
2738 	   byte is zero) */
2739 	sMemConnect( &stream, pubkeyBuffer, msgData.length );
2740 	readSequence( &stream, NULL );				/* SEQUENCE */
2741 	readSequence( &stream, NULL );					/* SEQUENCE */
2742 	readUniversal( &stream );							/* OID */
2743 	readSequence( &stream, NULL );						/* SEQUENCE */
2744 	readGenericHole( &stream, &length );					/* p */
2745 	publicKeyTemplate[ 3 ].pValue = sMemBufPtr( &stream );
2746 	publicKeyTemplate[ 3 ].ulValueLen = length;
2747 	sSkip( &stream, length, MAX_INTLENGTH_SHORT );
2748 	readGenericHole( &stream, &length );					/* q */
2749 	publicKeyTemplate[ 4 ].pValue = sMemBufPtr( &stream );
2750 	publicKeyTemplate[ 4 ].ulValueLen = length;
2751 	sSkip( &stream, length, MAX_INTLENGTH_SHORT );
2752 	readGenericHole( &stream, &length );					/* g */
2753 	publicKeyTemplate[ 5 ].pValue = sMemBufPtr( &stream );
2754 	publicKeyTemplate[ 5 ].ulValueLen = length;
2755 	assert( sStatusOK( &stream ) );
2756 	sMemDisconnect( &stream );
2757 
2758 	/* Get the information for the device associated with this context */
2759 	status = getContextDeviceInfo( contextInfoPtr->objectHandle,
2760 								   &iCryptDevice, &cryptoapiInfo );
2761 	if( cryptStatusError( status ) )
2762 		return( status );
2763 
2764 	/* Generate the keys */
2765 	status = C_GenerateKeyPair( cryptoapiInfo->hProv,
2766 								( CK_MECHANISM_PTR ) &mechanism,
2767 								( CK_ATTRIBUTE_PTR ) publicKeyTemplate, 5,
2768 								( CK_ATTRIBUTE_PTR ) privateKeyTemplate, 4,
2769 								&hPublicKey, &hPrivateKey );
2770 	cryptStatus = mapError( deviceInfo, status, CRYPT_ERROR_FAILED );
2771 	if( cryptStatusError( cryptStatus ) )
2772 		{
2773 		krnlReleaseObject( iCryptDevice );
2774 		return( cryptStatus );
2775 		}
2776 
2777 	/* Read back the generated y value, send the public key information to
2778 	   the context, and set up the key ID info.  The odd two-phase y value
2779 	   read is necessary for buggy implementations that fail if the given
2780 	   size isn't exactly the same as the data size */
2781 	status = C_GetAttributeValue( cryptoapiInfo->hProv, hPublicKey,
2782 								  &yValueTemplate, 1 );
2783 	if( status == CKR_OK )
2784 		{
2785 		yValueTemplate.pValue = pubkeyBuffer;
2786 		status = C_GetAttributeValue( cryptoapiInfo->hProv, hPublicKey,
2787 									  &yValueTemplate, 1 );
2788 		}
2789 	cryptStatus = mapError( deviceInfo, status, CRYPT_ERROR_FAILED );
2790 	if( cryptStatusOK( cryptStatus ) )
2791 		cryptStatus = dsaSetKeyInfo( deviceInfo, contextInfoPtr,
2792 			hPrivateKey, hPublicKey,
2793 			publicKeyTemplate[ 3 ].pValue, publicKeyTemplate[ 3 ].ulValueLen,
2794 			publicKeyTemplate[ 4 ].pValue, publicKeyTemplate[ 4 ].ulValueLen,
2795 			publicKeyTemplate[ 5 ].pValue, publicKeyTemplate[ 5 ].ulValueLen,
2796 			yValueTemplate.pValue, yValueTemplate.ulValueLen );
2797 	if( cryptStatusError( cryptStatus ) )
2798 		{
2799 		C_DestroyObject( cryptoapiInfo->hProv, hPublicKey );
2800 		C_DestroyObject( cryptoapiInfo->hProv, hPrivateKey );
2801 		}
2802 
2803 	krnlReleaseObject( iCryptDevice );
2804 	return( cryptStatus );
2805 #endif /* 0 */
2806 	return( CRYPT_ERROR );
2807 	}
2808 
dsaSign(CONTEXT_INFO * contextInfoPtr,void * buffer,int length)2809 static int dsaSign( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )
2810 	{
2811 #if 0
2812 	static const CK_MECHANISM mechanism = { CKM_DSA, NULL_PTR, 0 };
2813 	CRYPT_DEVICE iCryptDevice;
2814 	DLP_PARAMS *dlpParams = ( DLP_PARAMS * ) buffer;
2815 	BIGNUM *r, *s;
2816 	BYTE signature[ 40 + 8 ];
2817 	int cryptStatus;
2818 
2819 	assert( length == sizeof( DLP_PARAMS ) );
2820 	assert( dlpParams->inParam1 != NULL && \
2821 			dlpParams->inLen1 == 20 );
2822 	assert( dlpParams->inParam2 == NULL && dlpParams->inLen2 == 0 );
2823 	assert( dlpParams->outParam != NULL && \
2824 			dlpParams->outLen >= ( 2 + 20 ) * 2 );
2825 
2826 	/* Get the information for the device associated with this context */
2827 	status = getContextDeviceInfo( contextInfoPtr->objectHandle,
2828 								   &iCryptDevice, &cryptoapiInfo );
2829 	if( cryptStatusError( status ) )
2830 		return( status );
2831 	cryptStatus = genericSign( deviceInfo, contextInfoPtr, &mechanism,
2832 							   dlpParams->inParam1, dlpParams->inLen1,
2833 							   signature, 40 );
2834 	krnlReleaseObject( iCryptDevice );
2835 	if( cryptStatusError( cryptStatus ) )
2836 		return( cryptStatus );
2837 
2838 	/* Encode the result as a DL data block.  We have to do this as via
2839 	   bignums, but this isn't a big deal since DSA signing via tokens is
2840 	   almost never used */
2841 	r = BN_new();
2842 	s = BN_new();
2843 	if( r != NULL && s != NULL )
2844 		{
2845 		BN_bin2bn( signature, 20, r );
2846 		BN_bin2bn( signature + 20, 20, s );
2847 		cryptStatus = encodeDLValues( dlpParams->outParam, dlpParams->outLen,
2848 									  r, s, dlpParams->formatType );
2849 		if( !cryptStatusError( cryptStatus ) )
2850 			{
2851 			dlpParams->outLen = cryptStatus;
2852 			cryptStatus = CRYPT_OK;	/* encodeDLValues() returns a byte count */
2853 			}
2854 		BN_clear_free( s );
2855 		BN_clear_free( r );
2856 		}
2857 	return( cryptStatus );
2858 #endif /* 0 */
2859 	return( CRYPT_ERROR );
2860 	}
2861 
dsaVerify(CONTEXT_INFO * contextInfoPtr,void * buffer,int length)2862 static int dsaVerify( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )
2863 	{
2864 #if 0
2865 	static const CK_MECHANISM mechanism = { CKM_DSA, NULL_PTR, 0 };
2866 	CRYPT_DEVICE iCryptDevice;
2867 	DLP_PARAMS *dlpParams = ( DLP_PARAMS * ) buffer;
2868 	BIGNUM *r, *s;
2869 	BYTE signature[ 40 + 8 ];
2870 	int cryptStatus;
2871 
2872 	/* This function is present but isn't used as part of any normal
2873 	   operation because cryptlib does the same thing much faster in
2874 	   software and because some tokens don't support public-key
2875 	   operations */
2876 
2877 	assert( length == sizeof( DLP_PARAMS ) );
2878 	assert( dlpParams->inParam1 != NULL && dlpParams->inLen1 == 20 );
2879 	assert( dlpParams->inParam2 != NULL && \
2880 			( ( dlpParams->formatType == CRYPT_FORMAT_CRYPTLIB && \
2881 				dlpParams->inLen2 >= 46 ) || \
2882 			  ( dlpParams->formatType == CRYPT_FORMAT_PGP && \
2883 				dlpParams->inLen2 == 44 ) || \
2884 				( dlpParams->formatType == CRYPT_IFORMAT_SSH && \
2885 				dlpParams->inLen2 == 40 ) ) );
2886 	assert( dlpParams->outParam == NULL && dlpParams->outLen == 0 );
2887 
2888 	/* Decode the values from a DL data block and make sure r and s are
2889 	   valid */
2890 	cryptStatus = decodeDLValues( dlpParams->inParam2, dlpParams->inLen2,
2891 								  &r, &s, dlpParams->formatType );
2892 	if( cryptStatusError( cryptStatus ) )
2893 		return( cryptStatus );
2894 
2895 	/* This code can never be called, since DSA public-key contexts are
2896 	   always native contexts */
2897 	retIntError();
2898 
2899 	/* Get the information for the device associated with this context */
2900 	status = getContextDeviceInfo( contextInfoPtr->objectHandle,
2901 								   &iCryptDevice, &cryptoapiInfo );
2902 	if( cryptStatusError( status ) )
2903 		return( status );
2904 	cryptStatus = genericVerify( deviceInfo, contextInfoPtr, &mechanism, buffer,
2905 								 20, signature, 40 );
2906 	krnlReleaseObject( iCryptDevice );
2907 	return( cryptStatus );
2908 #endif /* 0 */
2909 	return( CRYPT_ERROR );
2910 	}
2911 
2912 /* Conventional cipher-specific mapping functions */
2913 
cipherInitKey(CONTEXT_INFO * contextInfoPtr,const void * key,const int keyLength)2914 static int cipherInitKey( CONTEXT_INFO *contextInfoPtr, const void *key,
2915 						  const int keyLength )
2916 	{
2917 	CRYPT_DEVICE iCryptDevice;
2918 	CRYPTOAPI_INFO *cryptoapiInfo;
2919 	HCRYPTKEY hSessionKey;
2920 	int keySize = keyLength, status;
2921 
2922 	/* Get the information for the device associated with this context */
2923 	status = getContextDeviceInfo( contextInfoPtr->objectHandle,
2924 								   &iCryptDevice, &cryptoapiInfo );
2925 	if( cryptStatusError( status ) )
2926 		return( status );
2927 
2928 	/* Copy the key to internal storage */
2929 	if( contextInfoPtr->ctxConv->userKey != key )
2930 		memcpy( contextInfoPtr->ctxConv->userKey, key, keyLength );
2931 	contextInfoPtr->ctxConv->userKeyLength = keyLength;
2932 
2933 	/* Special-case handling for 2-key vs.3-key 3DES */
2934 	if( contextInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_3DES )
2935 		{
2936 		/* If the supplied key contains only two DES keys, adjust the key to
2937 		   make it the equivalent of 3-key 3DES.  In addition since the
2938 		   nominal keysize is for 2-key 3DES, we have to make the actual size
2939 		   the maximum size, corresponding to 3-key 3DES */
2940 		if( keyLength <= bitsToBytes( 64 * 2 ) )
2941 			memcpy( contextInfoPtr->ctxConv->userKey + bitsToBytes( 64 * 2 ),
2942 					contextInfoPtr->ctxConv->userKey, bitsToBytes( 64 ) );
2943 		keySize = contextInfoPtr->capabilityInfo->maxKeySize;
2944 		}
2945 
2946 	/* Import the key via the hideous decrypt-with-exponent-one RSA key
2947 	   kludge */
2948 	status = importPlainKey( cryptoapiInfo->hProv,
2949 							 cryptoapiInfo->hPrivateKey,
2950 							 cryptoapiInfo->privateKeySize, &hSessionKey,
2951 							 contextInfoPtr->capabilityInfo->cryptAlgo,
2952 							 key, keySize, contextInfoPtr );
2953 	if( cryptStatusOK( status ) )
2954 		{
2955 		/* Note that the following will break under Win64 since the hKey is
2956 		   a 64-bit pointer while the deviceObject is a 32-bit unsigned
2957 		   value, this code is experimental and only enabled for Win32 debug
2958 		   so this isn't a problem at the moment */
2959 		contextInfoPtr->deviceObject = ( long ) hSessionKey;
2960 		}
2961 
2962 	krnlReleaseObject( iCryptDevice );
2963 	return( status );
2964 	}
2965 
2966 /* Set up algorithm-specific encryption parameters */
2967 
initCryptParams(CONTEXT_INFO * contextInfoPtr)2968 static int initCryptParams( CONTEXT_INFO *contextInfoPtr )
2969 	{
2970 	enum { CAPI_CRYPT_MODE_NONE, CAPI_CRYPT_MODE_CBC,
2971 		   CAPI_CRYPT_MODE_ECB, CAPI_CRYPT_MODE_CTR,
2972 		   CAPI_CRYPT_MODE_CFB };
2973 	const CRYPT_MODE_TYPE mode = contextInfoPtr->ctxConv->mode;
2974 	DWORD dwMode;
2975 
2976 	/* If it's a native stream cipher (rather than a block cipher being run
2977 	   in stream cipher mode), there's nothing to do */
2978 	if( isStreamCipher( contextInfoPtr->capabilityInfo->cryptAlgo ) )
2979 		return( CRYPT_OK );
2980 
2981 	/* Make sure that the values from the CryptoAPI header aren't
2982 	   overriding the cryptlib values */
2983 	assert( CRYPT_MODE_ECB == 1 );
2984 	assert( CRYPT_MODE_CBC == 2 );
2985 	assert( CRYPT_MODE_CFB == 3 );
2986 	assert( CRYPT_MODE_GCM == 4 );
2987 
2988 	/* CryptoAPI uses the same mode names as cryptlib but different values,
2989 	   so we have to override the naming with our own names here and then
2990 	   map the cryptlib values to the CryptoAPI ones */
2991 	switch( mode )
2992 		{
2993 		case CRYPT_MODE_ECB:
2994 			dwMode = CAPI_CRYPT_MODE_ECB;
2995 			break;
2996 		case CRYPT_MODE_CBC:
2997 			dwMode = CAPI_CRYPT_MODE_CBC;
2998 			break;
2999 		case CRYPT_MODE_CFB:
3000 			dwMode = CAPI_CRYPT_MODE_CFB;
3001 			break;
3002 		default:
3003 			retIntError();
3004 		}
3005 
3006 	/* Set the mode parameter for the CryptoAPI object */
3007 	if( !CryptSetKeyParam( contextInfoPtr->deviceObject, KP_MODE,
3008 						   ( BYTE * ) &dwMode, 0 ) )
3009 		return( mapDeviceError( contextInfoPtr, CRYPT_ERROR_NOTAVAIL ) );
3010 	if( mode == CRYPT_MODE_CFB )
3011 		{
3012 		const DWORD dwModeBits = contextInfoPtr->capabilityInfo->blockSize * 8;
3013 
3014 		/* CryptoAPI defaults to 8-bit feedback for CFB and OFB (!!) so we
3015 		   have to fix the feedback amount if we're using a stream mode */
3016 		if( !CryptSetKeyParam( contextInfoPtr->deviceObject, KP_MODE_BITS,
3017 							   ( BYTE * ) &dwModeBits, 0 ) )
3018 			return( mapDeviceError( contextInfoPtr, CRYPT_ERROR_NOTAVAIL ) );
3019 		}
3020 
3021 	/* If there's no IV present, we're done */
3022 	if( mode == CRYPT_MODE_ECB )
3023 		return( CRYPT_OK );
3024 
3025 	/* Set the IV parameter for the CryptoAPI object */
3026 	if( !CryptSetKeyParam( contextInfoPtr->deviceObject, KP_IV,
3027 						   contextInfoPtr->ctxConv->currentIV, 0 ) )
3028 		return( mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED ) );
3029 
3030 	return( CRYPT_OK );
3031 	}
3032 
3033 /* En/decrypt/hash data */
3034 
cipherEncrypt(CONTEXT_INFO * contextInfoPtr,void * buffer,int length)3035 static int cipherEncrypt( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )
3036 	{
3037 	DWORD resultLength = length;
3038 
3039 	/* Finalise the encryption parameters if necessary.  We couldn't do this
3040 	   earlier because the device-level object isn't instantiated until the
3041 	   key is loaded */
3042 	if( !( contextInfoPtr->flags & CONTEXT_FLAG_DUMMY_INITED ) )
3043 		{
3044 		int status;
3045 
3046 		status = initCryptParams( contextInfoPtr );
3047 		if( cryptStatusError( status ) )
3048 			return( status );
3049 		contextInfoPtr->flags |= CONTEXT_FLAG_DUMMY_INITED;
3050 		}
3051 
3052 	/* Encrypt the data.  We always set the bFinal flag to FALSE since
3053 	   setting it to TRUE tries to apply message padding, resets the IV, and
3054 	   various other unwanted side-effects */
3055 	if( !pCryptEncrypt( contextInfoPtr->deviceObject, 0, FALSE, 0, buffer,
3056 						&resultLength, length ) )
3057 		return( mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED ) );
3058 	return( CRYPT_OK );
3059 	}
3060 
cipherDecrypt(CONTEXT_INFO * contextInfoPtr,void * buffer,int length)3061 static int cipherDecrypt( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )
3062 	{
3063 	DWORD resultLength = length;
3064 
3065 	/* Finalise the encryption parameters if necessary.  We couldn't do this
3066 	   earlier because the device-level object isn't instantiated until the
3067 	   key is loaded */
3068 	if( !( contextInfoPtr->flags & CONTEXT_FLAG_DUMMY_INITED ) )
3069 		{
3070 		int status;
3071 
3072 		status = initCryptParams( contextInfoPtr );
3073 		if( cryptStatusError( status ) )
3074 			return( status );
3075 		contextInfoPtr->flags |= CONTEXT_FLAG_DUMMY_INITED;
3076 		}
3077 
3078 	/* Decrypt the data.  We always set the bFinal flag to FALSE since
3079 	   setting it to TRUE tries to process message padding, resets the IV,
3080 	   and various other unwanted side-effects */
3081 	if( !pCryptDecrypt( contextInfoPtr->deviceObject, 0, FALSE, 0, buffer,
3082 						&resultLength ) )
3083 		return( mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED ) );
3084 	return( CRYPT_OK );
3085 	}
3086 
3087 #if 0	/* Not used, see the comment in the capability information */
3088 
3089 static int hashFunction( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )
3090 	{
3091 	if( !pCryptHashData( contextInfoPtr->deviceObject, buffer, length, 0 ) )
3092 		return( mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED ) );
3093 	return( CRYPT_OK );
3094 	}
3095 #endif /* 0 */
3096 
3097 /****************************************************************************
3098 *																			*
3099 *						 	Device Capability Routines						*
3100 *																			*
3101 ****************************************************************************/
3102 
3103 /* Templates for the various capabilities.  These contain only basic
3104    information, the remaining fields are filled in when the capability is
3105    set up */
3106 
3107 static CAPABILITY_INFO FAR_BSS capabilityTemplates[] = {
3108 	/* Encryption capabilities */
3109 	{ CRYPT_ALGO_3DES, bitsToBytes( 64 ), "3DES", 4,
3110 		bitsToBytes( 64 + 8 ), bitsToBytes( 128 ), bitsToBytes( 192 ) },
3111 	{ CRYPT_ALGO_RC2, bitsToBytes( 64 ), "RC2", 3,
3112 		bitsToBytes( 40 ), bitsToBytes( 128 ), bitsToBytes( 1024 ) },
3113 	{ CRYPT_ALGO_RC4, bitsToBytes( 8 ), "RC4", 3,
3114 		bitsToBytes( 40 ), bitsToBytes( 128 ), 256 },
3115 	{ CRYPT_ALGO_AES, bitsToBytes( 128 ), "AES", 3,
3116 		bitsToBytes( 128 ), bitsToBytes( 128 ), bitsToBytes( 256 ) },
3117 
3118 	/* Hash capabilities */
3119 	{ CRYPT_ALGO_MD5, bitsToBytes( 128 ), "MD5", 3,
3120 		bitsToBytes( 0 ), bitsToBytes( 0 ), bitsToBytes( 0 ) },
3121 	{ CRYPT_ALGO_SHA1, bitsToBytes( 160 ), "SHA1", 3,
3122 		bitsToBytes( 0 ), bitsToBytes( 0 ), bitsToBytes( 0 ) },
3123 
3124 	/* Public-key capabilities */
3125 	{ CRYPT_ALGO_RSA, bitsToBytes( 0 ), "RSA", 3,
3126 		bitsToBytes( 512 ), bitsToBytes( 1024 ), CRYPT_MAX_PKCSIZE },
3127 	{ CRYPT_ALGO_DSA, bitsToBytes( 0 ), "DSA", 3,
3128 		bitsToBytes( 512 ), bitsToBytes( 1024 ), CRYPT_MAX_PKCSIZE },
3129 
3130 	/* Hier ist der Mast zu ende */
3131 	{ CRYPT_ERROR }, { CRYPT_ERROR }
3132 	};
3133 
3134 /* Mapping of CryptoAPI provider capabilities to cryptlib capabilities */
3135 
3136 typedef struct {
3137 	/* Mapping information from CryptoAPI to cryptlib algorithms.  For some
3138 	   PKC algorithms CryptoAPI creates two virtual algorithm types (badly,
3139 	   it's easily confused between the two), one for signing and one for
3140 	   encryption.  The first algorithm type is always the one with
3141 	   encryption capability, if there's one with signature capability or
3142 	   it's a signature-only algorithm we specify it as the optional
3143 	   alternative algorithm type */
3144 	const ALG_ID algoID;				/* CryptoAPI algorithm type */
3145 	const ALG_ID altAlgoID;				/* CryptoAPI alt.algorithm type */
3146 	const CRYPT_ALGO_TYPE cryptAlgo;	/* cryptlib algo and mode */
3147 	const CRYPT_MODE_TYPE cryptMode;
3148 
3149 	/* Function pointers */
3150 	int ( *endFunction )( CONTEXT_INFO *contextInfoPtr );
3151 	int ( *initKeyFunction )( CONTEXT_INFO *contextInfoPtr, const void *key, const int keyLength );
3152 	int ( *generateKeyFunction )( CONTEXT_INFO *contextInfoPtr, const int keySizeBits );
3153 	int ( *encryptFunction )( CONTEXT_INFO *contextInfoPtr, void *buffer, int length );
3154 	int ( *decryptFunction )( CONTEXT_INFO *contextInfoPtr, void *buffer, int length );
3155 	int ( *signFunction )( CONTEXT_INFO *contextInfoPtr, void *buffer, int length );
3156 	int ( *sigCheckFunction )( CONTEXT_INFO *contextInfoPtr, void *buffer, int length );
3157 	} MECHANISM_INFO;
3158 
3159 static const MECHANISM_INFO mechanismInfo[] = {
3160 	{ CALG_RSA_KEYX, CALG_RSA_SIGN, CRYPT_ALGO_RSA, CRYPT_MODE_NONE,
3161 	  NULL, rsaInitKey, rsaGenerateKey,
3162 	  rsaEncrypt, rsaDecrypt, rsaSign, rsaVerify },
3163 	{ CALG_NONE, CALG_DSS_SIGN, CRYPT_ALGO_DSA, CRYPT_MODE_NONE,
3164 	  NULL, dsaInitKey, dsaGenerateKey,
3165 	  NULL, NULL, dsaSign, dsaVerify },
3166 	{ CALG_DES, CALG_NONE, CRYPT_ALGO_DES, CRYPT_MODE_ECB,
3167 	  genericEndFunction, cipherInitKey, NULL,
3168 	  cipherEncrypt, cipherDecrypt, NULL, NULL },
3169 	{ CALG_DES, CALG_NONE, CRYPT_ALGO_DES, CRYPT_MODE_CBC,
3170 	  genericEndFunction, cipherInitKey, NULL,
3171 	  cipherEncrypt, cipherDecrypt, NULL, NULL },
3172 	{ CALG_3DES, CALG_NONE, CRYPT_ALGO_3DES, CRYPT_MODE_ECB,
3173 	  genericEndFunction, cipherInitKey, NULL,
3174 	  cipherEncrypt, cipherDecrypt, NULL, NULL },
3175 	{ CALG_3DES, CALG_NONE, CRYPT_ALGO_3DES, CRYPT_MODE_CBC,
3176 	  genericEndFunction, cipherInitKey, NULL,
3177 	  cipherEncrypt, cipherDecrypt, NULL, NULL },
3178 	{ CALG_RC2, CALG_NONE, CRYPT_ALGO_RC2, CRYPT_MODE_ECB,
3179 	  genericEndFunction, cipherInitKey, NULL,
3180 	  cipherEncrypt, cipherDecrypt, NULL, NULL },
3181 	{ CALG_RC2, CALG_NONE, CRYPT_ALGO_RC2, CRYPT_MODE_CBC,
3182 	  genericEndFunction, cipherInitKey, NULL,
3183 	  cipherEncrypt, cipherDecrypt, NULL, NULL },
3184 	{ CALG_RC4, CALG_NONE, CRYPT_ALGO_RC4, CRYPT_MODE_CFB,
3185 	  genericEndFunction, cipherInitKey, NULL,
3186 	  cipherEncrypt, cipherDecrypt, NULL, NULL },
3187 #if 0	/* Although CAPI supports the hash mechanisms, as with PKCS #11
3188 		   we always use cryptlib native contexts for this */
3189 	{ CALG_MD5, CALG_NONE, CRYPT_ALGO_MD5, CRYPT_MODE_NONE,
3190 	  genericEndFunction, NULL, NULL,
3191 	  hashFunction, hashFunction, NULL, NULL },
3192 	{ CALG_SHA1, CALG_NONE, CRYPT_ALGO_SHA1, CRYPT_MODE_NONE,
3193 	  genericEndFunction, NULL, NULL,
3194 	  hashFunction, hashFunction, NULL, NULL },
3195 #endif /* 0 */
3196 	{ CALG_NONE, CALG_NONE, CRYPT_ALGO_NONE, CRYPT_MODE_NONE },
3197 		{ CALG_NONE, CALG_NONE, CRYPT_ALGO_NONE, CRYPT_MODE_NONE }
3198 	};
3199 
3200 /* Fill out a capability information based on CryptoAPI algorithm
3201    information */
3202 
addCapability(const DEVICE_INFO * deviceInfo,const PROV_ENUMALGS_EX * capiAlgoInfo,const MECHANISM_INFO * mechanismInfoPtr,const CAPABILITY_INFO * existingCapabilityInfo)3203 static CAPABILITY_INFO *addCapability( const DEVICE_INFO *deviceInfo,
3204 									   const PROV_ENUMALGS_EX *capiAlgoInfo,
3205 									   const MECHANISM_INFO *mechanismInfoPtr,
3206 									   const CAPABILITY_INFO *existingCapabilityInfo )
3207 	{
3208 	VARIABLE_CAPABILITY_INFO *capabilityInfo = \
3209 					( VARIABLE_CAPABILITY_INFO * ) existingCapabilityInfo;
3210 	int i;
3211 
3212 	/* If it's a new capability, copy across the template for this
3213 	   capability */
3214 	if( capabilityInfo == NULL )
3215 		{
3216 		if( ( capabilityInfo = \
3217 				clAlloc( "addCapability", sizeof( CAPABILITY_INFO ) ) ) == NULL )
3218 			return( NULL );
3219 		for( i = 0;
3220 			 capabilityTemplates[ i ].cryptAlgo != mechanismInfoPtr->cryptAlgo && \
3221 				capabilityTemplates[ i ].cryptAlgo != CRYPT_ALGO_NONE && \
3222 				i < FAILSAFE_ARRAYSIZE( capabilityTemplates, CAPABILITY_INFO ); \
3223 			 i++ );
3224 		if( i >= FAILSAFE_ARRAYSIZE( capabilityTemplates, CAPABILITY_INFO ) )
3225 			retIntError_Null();
3226 		assert( i < sizeof( capabilityTemplates ) / sizeof( CAPABILITY_INFO ) && \
3227 				capabilityTemplates[ i ].cryptAlgo != CRYPT_ALGO_NONE );
3228 		memcpy( capabilityInfo, &capabilityTemplates[ i ],
3229 				sizeof( CAPABILITY_INFO ) );
3230 		}
3231 
3232 	/* Set up the keysize information, limiting the maximum key size to
3233 	   match the cryptlib native max.key size, both for consistency and
3234 	   because cryptlib performs buffer allocation based on the maximum
3235 	   native buffer size.  Since CryptoAPI specifies key sizes for unkeyed
3236 	   hash algorithms, we only set the keysize if there's really a key
3237 	   present.  In addition it indicates the number of bits involved in
3238 	   keying rather than the nominal key size, so we have to adjust the
3239 	   reported size to match the conventionally-used value */
3240 	if( capabilityInfo->keySize > 0 )
3241 		{
3242 		int minKeySize = bitsToBytes( capiAlgoInfo->dwMinLen );
3243 		int maxKeySize = bitsToBytes( capiAlgoInfo->dwMaxLen );
3244 
3245 		if( mechanismInfoPtr->cryptAlgo == CRYPT_ALGO_DES && \
3246 			minKeySize == 7 )
3247 			{
3248 			/* Adjust 56 bits -> 8 bytes */
3249 			minKeySize = maxKeySize = 8;
3250 			}
3251 		if( mechanismInfoPtr->cryptAlgo == CRYPT_ALGO_3DES && \
3252 			minKeySize == 21 )
3253 			{
3254 			/* Adjust 168 bits -> 24 bytes */
3255 			minKeySize = maxKeySize = 24;
3256 			}
3257 		if( minKeySize > capabilityInfo->minKeySize )
3258 			capabilityInfo->minKeySize = minKeySize;
3259 		if( capabilityInfo->keySize < capabilityInfo->minKeySize )
3260 			capabilityInfo->keySize = capabilityInfo->minKeySize;
3261 		capabilityInfo->maxKeySize = min( maxKeySize,
3262 										  capabilityInfo->maxKeySize );
3263 		if( capabilityInfo->keySize > capabilityInfo->maxKeySize )
3264 			capabilityInfo->keySize = capabilityInfo->maxKeySize;
3265 		capabilityInfo->endFunction = genericEndFunction;
3266 		}
3267 
3268 	/* Set up the device-specific handlers */
3269 	capabilityInfo->getInfoFunction = getDefaultInfo;
3270 	if( mechanismInfoPtr->cryptAlgo != CRYPT_ALGO_RSA && \
3271 		mechanismInfoPtr->cryptAlgo != CRYPT_ALGO_DSA )
3272 		capabilityInfo->initParamsFunction = initGenericParams;
3273 	capabilityInfo->endFunction = mechanismInfoPtr->endFunction;
3274 	capabilityInfo->initKeyFunction = mechanismInfoPtr->initKeyFunction;
3275 	capabilityInfo->generateKeyFunction = mechanismInfoPtr->generateKeyFunction;
3276 	if( mechanismInfoPtr->algoID == capiAlgoInfo->aiAlgid )
3277 		{
3278 		if( mechanismInfoPtr->cryptMode == CRYPT_MODE_CFB )
3279 			{
3280 			/* Stream ciphers have an implicit mode of CFB */
3281 			capabilityInfo->encryptCFBFunction = mechanismInfoPtr->encryptFunction;
3282 			}
3283 		else
3284 			capabilityInfo->encryptFunction = mechanismInfoPtr->encryptFunction;
3285 		if( mechanismInfoPtr->cryptMode == CRYPT_MODE_CFB )
3286 			{
3287 			/* Stream ciphers have an implicit mode of CFB */
3288 			capabilityInfo->decryptCFBFunction = mechanismInfoPtr->decryptFunction;
3289 			}
3290 		else
3291 			capabilityInfo->decryptFunction = mechanismInfoPtr->decryptFunction;
3292 		if( mechanismInfoPtr->cryptMode != CRYPT_MODE_NONE )
3293 			{
3294 			capabilityInfo->encryptCBCFunction = \
3295 										mechanismInfoPtr->encryptFunction;
3296 			capabilityInfo->decryptCBCFunction = \
3297 										mechanismInfoPtr->decryptFunction;
3298 #if 0		/* CAPI requires the encryption of full blocks even in a stream
3299 			   cipher mode, which doesn't match the standard cryptlib
3300 			   behaviour.  To avoid this problem, we mark the stream cipher
3301 			   modes as not available */
3302 			capabilityInfo->encryptCFBFunction = \
3303 										mechanismInfoPtr->encryptFunction;
3304 			capabilityInfo->decryptCFBFunction = \
3305 										mechanismInfoPtr->decryptFunction;
3306 			capabilityInfo->encryptCTRFunction = \
3307 										mechanismInfoPtr->encryptFunction;
3308 			capabilityInfo->decryptCTRFunction = \
3309 										mechanismInfoPtr->decryptFunction;
3310 #endif /* 0 */
3311 			}
3312 		}
3313 	if( mechanismInfoPtr->altAlgoID == capiAlgoInfo->aiAlgid )
3314 		{
3315 		capabilityInfo->signFunction = mechanismInfoPtr->signFunction;
3316 		capabilityInfo->sigCheckFunction = mechanismInfoPtr->sigCheckFunction;
3317 		}
3318 
3319 	return( ( CAPABILITY_INFO * ) capabilityInfo );
3320 	}
3321 
3322 /* Set the capability information based on device capabilities.  Since
3323    CryptoAPI devices can have assorted capabilities, we have to build this
3324    up on the fly rather than using a fixed table like the built-in
3325    capabilities */
3326 
freeCapabilities(DEVICE_INFO * deviceInfo)3327 static void freeCapabilities( DEVICE_INFO *deviceInfo )
3328 	{
3329 	CAPABILITY_INFO_LIST *capabilityInfoListPtr = \
3330 				( CAPABILITY_INFO_LIST * ) deviceInfo->capabilityInfoList;
3331 
3332 	/* If the list was empty, return now */
3333 	if( capabilityInfoListPtr == NULL )
3334 		return;
3335 	deviceInfo->capabilityInfoList = NULL;
3336 
3337 	while( capabilityInfoListPtr != NULL )
3338 		{
3339 		CAPABILITY_INFO_LIST *listItemToFree = capabilityInfoListPtr;
3340 		CAPABILITY_INFO *itemToFree = ( CAPABILITY_INFO * ) listItemToFree->info;
3341 
3342 		capabilityInfoListPtr = capabilityInfoListPtr->next;
3343 		zeroise( itemToFree, sizeof( CAPABILITY_INFO ) );
3344 		clFree( "freeCapabilities", itemToFree );
3345 		zeroise( listItemToFree, sizeof( CAPABILITY_INFO_LIST ) );
3346 		clFree( "freeCapabilities", listItemToFree );
3347 		}
3348 	}
3349 
getCapabilities(DEVICE_INFO * deviceInfo)3350 static int getCapabilities( DEVICE_INFO *deviceInfo )
3351 	{
3352 	CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
3353 	CAPABILITY_INFO_LIST *capabilityInfoListTail = \
3354 				( CAPABILITY_INFO_LIST * ) deviceInfo->capabilityInfoList;
3355 	PROV_ENUMALGS_EX capiAlgoInfo;
3356 	DWORD length = sizeof( PROV_ENUMALGS_EX );
3357 	int iterationCount = 0;
3358 
3359 	assert( sizeof( CAPABILITY_INFO ) == sizeof( VARIABLE_CAPABILITY_INFO ) );
3360 
3361 	/* Step through each available CryptoAPI algorithm type adding the
3362 	   appropriate cryptlib capability for it */
3363 	if( !pCryptGetProvParam( cryptoapiInfo->hProv, PP_ENUMALGS_EX,
3364 							 ( BYTE * ) &capiAlgoInfo, &length, CRYPT_FIRST ) )
3365 		return( CRYPT_ERROR );
3366 	do
3367 		{
3368 		CAPABILITY_INFO_LIST *newCapabilityList, *capabilityInfoListPtr;
3369 		CAPABILITY_INFO *newCapability;
3370 		CRYPT_ALGO_TYPE cryptAlgo;
3371 		int i;
3372 
3373 		/* Check whether this algorithm type corresponds to a cryptlib
3374 		   capability */
3375 		for( i = 0; mechanismInfo[ i ].cryptAlgo != CRYPT_ALGO_NONE && \
3376 					i < FAILSAFE_ARRAYSIZE( mechanismInfo, MECHANISM_INFO );
3377 			 i++ )
3378 			{
3379 			if( mechanismInfo[ i ].algoID == capiAlgoInfo.aiAlgid || \
3380 				( mechanismInfo[ i ].altAlgoID != CALG_NONE && \
3381 				  mechanismInfo[ i ].altAlgoID == capiAlgoInfo.aiAlgid ) )
3382 				break;
3383 			}
3384 		if( i >= FAILSAFE_ARRAYSIZE( mechanismInfo, MECHANISM_INFO ) )
3385 			retIntError();
3386 		if( mechanismInfo[ i ].cryptAlgo == CRYPT_ALGO_NONE )
3387 			continue;
3388 		cryptAlgo = mechanismInfo[ i ].cryptAlgo;
3389 
3390 		/* Check whether this is a variation of an existing capability */
3391 		for( capabilityInfoListPtr = ( CAPABILITY_INFO_LIST * ) \
3392 									 deviceInfo->capabilityInfoList;
3393 			 capabilityInfoListPtr != NULL && \
3394 				capabilityInfoListPtr->info->cryptAlgo != cryptAlgo;
3395 			 capabilityInfoListPtr = capabilityInfoListPtr->next );
3396 		if( capabilityInfoListPtr != NULL )
3397 			{
3398 			addCapability( deviceInfo, &capiAlgoInfo, &mechanismInfo[ i ],
3399 						   capabilityInfoListPtr->info );
3400 			continue;
3401 			}
3402 
3403 		/* Add capabilities for all mechanisms corresponding to the current
3404 		   CryptoAPI algorithm type.  If the assertion below triggers then
3405 		   the CryptoAPI provider is broken since it's returning
3406 		   inconsistent information such as illegal key length data,
3407 		   conflicting algorithm information, etc etc.  This assertion is
3408 		   included here to detect buggy drivers early on rather than
3409 		   forcing users to step through the CryptoAPI glue code to find out
3410 		   why an operation is failing.
3411 
3412 		   Because some providers mapped down to tinkertoy smart cards
3413 		   support only the bare minimum functionality (e.g.RSA private key
3414 		   ops and nothing else), we allow asymmetric functionality for
3415 		   PKCs */
3416 		newCapability = addCapability( deviceInfo, &capiAlgoInfo,
3417 									   &mechanismInfo[ i ], NULL );
3418 		if( newCapability == NULL )
3419 			break;
3420 		REQUIRES( sanityCheckCapability( newCapability ) );
3421 		if( ( newCapabilityList = \
3422 						clAlloc( "getCapabilities", \
3423 								 sizeof( CAPABILITY_INFO_LIST ) ) ) == NULL )
3424 			{
3425 			clFree( "getCapabilities", newCapability );
3426 			continue;
3427 			}
3428 		newCapabilityList->info = newCapability;
3429 		newCapabilityList->next = NULL;
3430 		if( deviceInfo->capabilityInfoList == NULL )
3431 			deviceInfo->capabilityInfoList = newCapabilityList;
3432 		else
3433 			capabilityInfoListTail->next = newCapabilityList;
3434 		capabilityInfoListTail = newCapabilityList;
3435 		}
3436 	while( pCryptGetProvParam( cryptoapiInfo->hProv, PP_ENUMALGS_EX,
3437 							   ( BYTE * ) &capiAlgoInfo, &length, 0 ) && \
3438 		   iterationCount++ < FAILSAFE_ITERATIONS_LARGE );
3439 	if( iterationCount >= FAILSAFE_ITERATIONS_LARGE )
3440 		retIntError();
3441 
3442 	return( ( deviceInfo->capabilityInfoList == NULL ) ? CRYPT_ERROR : CRYPT_OK );
3443 	}
3444 
3445 /****************************************************************************
3446 *																			*
3447 *						 	Device Access Routines							*
3448 *																			*
3449 ****************************************************************************/
3450 
3451 /* Mechanisms supported by CryptoAPI devices.  These are actually cryptlib
3452    native mechanisms since many aren't supported by CryptoAPI, but not the
3453    full set supported by the system device since functions like private key
3454    export aren't available except in the nonstandard blob format invented
3455    by Microsoft.  The list is sorted in order of frequency of use in order
3456    to make lookups a bit faster */
3457 
3458 static const FAR_BSS MECHANISM_FUNCTION_INFO mechanismFunctions[] = {
3459 	{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1, ( MECHANISM_FUNCTION ) exportPKCS1 },
3460 	{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1, ( MECHANISM_FUNCTION ) importPKCS1 },
3461 	{ MESSAGE_DEV_SIGN, MECHANISM_SIG_PKCS1, ( MECHANISM_FUNCTION ) signPKCS1 },
3462 	{ MESSAGE_DEV_SIGCHECK, MECHANISM_SIG_PKCS1, ( MECHANISM_FUNCTION ) sigcheckPKCS1 },
3463 	{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1_RAW, ( MECHANISM_FUNCTION ) exportPKCS1 },
3464 	{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1_RAW, ( MECHANISM_FUNCTION ) importPKCS1 },
3465 #ifdef USE_PGP
3466 	{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1_PGP, ( MECHANISM_FUNCTION ) exportPKCS1PGP },
3467 	{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1_PGP, ( MECHANISM_FUNCTION ) importPKCS1PGP },
3468 #endif /* USE_PGP */
3469 	{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_CMS, ( MECHANISM_FUNCTION ) exportCMS },
3470 	{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_CMS, ( MECHANISM_FUNCTION ) importCMS },
3471 	{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PKCS5, ( MECHANISM_FUNCTION ) derivePKCS5 },
3472 #if defined( USE_PGP ) || defined( USE_PGPKEYS )
3473 	{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PGP, ( MECHANISM_FUNCTION ) derivePGP },
3474 #endif /* USE_PGP || USE_PGPKEYS */
3475 #ifdef USE_SSL
3476 	{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_SSL, ( MECHANISM_FUNCTION ) deriveSSL },
3477 	{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_TLS, ( MECHANISM_FUNCTION ) deriveTLS },
3478 	{ MESSAGE_DEV_SIGN, MECHANISM_SIG_SSL, ( MECHANISM_FUNCTION ) signSSL },
3479 	{ MESSAGE_DEV_SIGCHECK, MECHANISM_SIG_SSL, ( MECHANISM_FUNCTION ) sigcheckSSL },
3480 #endif /* USE_SSL */
3481 #ifdef USE_CMP
3482 	{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_CMP, ( MECHANISM_FUNCTION ) deriveCMP },
3483 #endif /* USE_CMP */
3484 #ifdef USE_PKCS12
3485 	{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PKCS12, ( MECHANISM_FUNCTION ) derivePKCS12 },
3486 #endif /* USE_PKCS12 */
3487 	{ MESSAGE_NONE, MECHANISM_NONE, NULL }, { MESSAGE_NONE, MECHANISM_NONE, NULL }
3488 	};
3489 
3490 /* Set up the function pointers to the device methods */
3491 
3492 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
setDeviceCryptoAPI(INOUT DEVICE_INFO * deviceInfo)3493 int setDeviceCryptoAPI( INOUT DEVICE_INFO *deviceInfo )
3494 	{
3495 	/* Make sure that the CryptoAPI driver DLL is loaded */
3496 	if( hCryptoAPI == NULL_HINSTANCE )
3497 		return( CRYPT_ERROR_OPEN );
3498 
3499 	deviceInfo->initFunction = initFunction;
3500 	deviceInfo->shutdownFunction = shutdownFunction;
3501 	deviceInfo->controlFunction = controlFunction;
3502 	deviceInfo->getItemFunction = getItemFunction;
3503 	deviceInfo->setItemFunction = setItemFunction;
3504 	deviceInfo->deleteItemFunction = deleteItemFunction;
3505 	deviceInfo->getFirstItemFunction = getFirstItemFunction;
3506 	deviceInfo->getNextItemFunction = getNextItemFunction;
3507 	deviceInfo->getRandomFunction = getRandomFunction;
3508 	deviceInfo->mechanismFunctions = mechanismFunctions;
3509 	deviceInfo->mechanismFunctionCount = \
3510 		FAILSAFE_ARRAYSIZE( mechanismFunctions, MECHANISM_FUNCTION_INFO );
3511 
3512 	return( CRYPT_OK );
3513 	}
3514 #endif /* USE_CRYPTOAPI */
3515