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