cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
ms_capi.c
Go to the documentation of this file.
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 /* Occasionally we need to read things into host memory from a device in a
34  manner that can't be handled by a dynBuf since the data is coming from a
35  device rather than a cryptlib object. The following value defines the
36  maximum size of the on-stack buffer, if the data is larger than this we
37  dynamically allocate the buffer (this almost never occurs) */
38 
39 #define MAX_BUFFER_SIZE 1024
40 
41 #ifdef USE_CRYPTOAPI
42 
43 #if defined( _MSC_VER )
44  #pragma message( " Building with CAPI device interface enabled." )
45 #endif /* Warn with VC++ */
46 
47 /* The following define is needed to enable crypto functions in the include
48  file. This would probably be defined by the compiler since it's not
49  defined in any header file, but it doesn't seem to be enabled by
50  default */
51 
52 #ifndef _WIN32_WINNT
53  #define _WIN32_WINNT 0x0500
54 #endif /* _WIN32_WINNT */
55 
56 /* cryptlib.h includes a trap for inclusion of wincrypt.h before cryptlib.h
57  which results in a compiler error if both files are included. To disable
58  this, we need to undefine the CRYPT_MODE_ECB defined in cryptlib.h */
59 
60 #undef CRYPT_MODE_ECB
61 
62 #include <wincrypt.h>
63 
64 /* CryptoAPI uses the same mode names as cryptlib but different values,
65  fortunately this is done with #defines so we can remove them at this
66  point */
67 
68 #undef CRYPT_MODE_ECB
69 #undef CRYPT_MODE_CBC
70 #undef CRYPT_MODE_CFB
71 #undef CRYPT_MODE_OFB
72 
73 /* Symbolic defines to represent non-initialised values */
74 
75 #define CALG_NONE 0
76 #define HCRYPTPROV_NONE 0
77 
78 /* Some parts of CryptoAPI (inconsistently) require the use of Unicode,
79  winnls.h was already included via the global include of windows.h however
80  it isn't needed for any other part of cryptlib so it was disabled via
81  NONLS. Since winnls.h is now locked out, we have to un-define the guards
82  used earlier to get it included */
83 
84 #undef _WINNLS_
85 #undef NONLS
86 #include <winnls.h>
87 
88 /* Older versions of wincrypt.h don't contain defines and typedefs that we
89  require. Defines can be detected with #ifdef but typedefs can't, to
90  handle this we rely on checking for values that aren't defined in older
91  versions of wincrypt.h, which only go up to KP_PUB_EX_VAL */
92 
93 #ifndef KP_ADMIN_PIN
94  /* Misc values */
95  #define HCERTCHAINENGINE void *
96  #define USAGE_MATCH_TYPE_AND 0
97  #define USAGE_MATCH_TYPE_OR 1
98  #define CERT_COMPARE_KEY_IDENTIFIER 15
99  #define CERT_FIND_KEY_IDENTIFIER ( CERT_COMPARE_KEY_IDENTIFIER << CERT_COMPARE_SHIFT )
100  #define CERT_CHAIN_CACHE_END_CERT 0x00000001
101  #define CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY 0x80000000
102  #define CRYPT_ACQUIRE_CACHE_FLAG 0x00000001
103 
104  /* Certificate chain match information */
105  typedef struct {
106  DWORD dwType;
107  CERT_ENHKEY_USAGE Usage;
108  } CERT_USAGE_MATCH;
109  typedef struct {
110  DWORD cbSize;
111  CERT_USAGE_MATCH RequestedUsage;
112  CERT_USAGE_MATCH RequestedIssuancePolicy;
113  DWORD dwUrlRetrievalTimeout;
114  BOOL fCheckRevocationFreshnessTime;
115  DWORD dwRevocationFreshnessTime;
116  } CERT_CHAIN_PARA, *PCERT_CHAIN_PARA;
117 
118  /* Certificate chain information */
119  typedef struct {
120  DWORD dwErrorStatus;
121  DWORD dwInfoStatus;
122  } CERT_TRUST_STATUS, *PCERT_TRUST_STATUS;
123  typedef struct {
124  DWORD cbSize;
125  PCCERT_CONTEXT pCertContext;
126  CERT_TRUST_STATUS TrustStatus;
127  void *pRevocationInfo; // PCERT_REVOCATION_INFO pRevocationInfo;
128  void *pIssuanceUsage; // PCERT_ENHKEY_USAGE pIssuanceUsage;
129  void *pApplicationUsage; // PCERT_ENHKEY_USAGE pApplicationUsage;
130  LPCWSTR pwszExtendedErrorInfo;
131  } CERT_CHAIN_ELEMENT, *PCERT_CHAIN_ELEMENT;
132  typedef struct {
133  DWORD cbSize;
134  PCTL_ENTRY pCtlEntry;
135  PCCTL_CONTEXT pCtlContext;
136  } CERT_TRUST_LIST_INFO, *PCERT_TRUST_LIST_INFO;
137  typedef struct {
138  DWORD cbSize;
139  CERT_TRUST_STATUS TrustStatus;
140  DWORD cElement;
141  PCERT_CHAIN_ELEMENT *rgpElement;
142  PCERT_TRUST_LIST_INFO pTrustListInfo;
143  BOOL fHasRevocationFreshnessTime;
144  DWORD dwRevocationFreshnessTime;
145  } CERT_SIMPLE_CHAIN, *PCERT_SIMPLE_CHAIN;
146  typedef struct CCC {
147  DWORD cbSize;
148  CERT_TRUST_STATUS TrustStatus;
149  DWORD cChain;
150  PCERT_SIMPLE_CHAIN *rgpChain;
151  DWORD cLowerQualityChainContext;
152  struct CCC **rgpLowerQualityChainContext;
153  BOOL fHasRevocationFreshnessTime;
154  DWORD dwRevocationFreshnessTime;
155  } CERT_CHAIN_CONTEXT;
156  typedef const CERT_CHAIN_CONTEXT *PCCERT_CHAIN_CONTEXT;
157 #endif /* Pre-1999 wincrypt.h */
158 
159 /****************************************************************************
160 * *
161 * Init/Shutdown Routines *
162 * *
163 ****************************************************************************/
164 
165 /* Global function pointers. These are necessary because the functions need
166  to be dynamically linked since not all systems contain the necessary
167  DLL's. Explicitly linking to them will make cryptlib unloadable on some
168  systems */
169 
170 #define NULL_HINSTANCE ( HINSTANCE ) NULL
171 
172 static HINSTANCE hCryptoAPI = NULL_HINSTANCE;
173 static HINSTANCE hAdvAPI32 = NULL_HINSTANCE;
174 
175 typedef BOOL ( WINAPI *CERTADDCERTIFICATETOSTORE )( HCERTSTORE hCertStore,
176  PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition,
177  PCCERT_CONTEXT *ppStoreContext );
178 typedef BOOL ( WINAPI *CERTADDENCODEDCERTIFICATETOSTORE )( HCERTSTORE hCertStore,
179  DWORD dwCertEncodingType, const BYTE *pbCertEncoded,
180  DWORD cbCertEncoded, DWORD dwAddDisposition,
181  PCCERT_CONTEXT *ppCertContext );
182 typedef BOOL ( WINAPI *CERTCLOSESTORE )( HCERTSTORE hCertStore, DWORD dwFlags );
183 typedef PCCERT_CONTEXT ( WINAPI *CERTCREATECERTIFICATECONTEXT )( DWORD dwCertEncodingType,
184  const BYTE *pbCertEncoded, DWORD cbCertEncoded );
185 typedef BOOL ( WINAPI *CERTDELETECERTIFICATEFROMSTORE )( PCCERT_CONTEXT pCertContext );
186 typedef PCCERT_CONTEXT ( WINAPI *CERTFINDCERTIFICATEINSTORE )( HCERTSTORE hCertStore,
187  DWORD dwCertEncodingType, DWORD dwFindFlags,
188  DWORD dwFindType, const void *pvFindPara,
189  PCCERT_CONTEXT pPrevCertContext );
190 typedef VOID ( WINAPI *CERTFREECERTIFICATECHAIN )( PCCERT_CHAIN_CONTEXT pChainContext );
191 typedef BOOL ( WINAPI *CERTFREECERTIFICATECONTEXT )( PCCERT_CONTEXT pCertContext );
192 typedef BOOL ( WINAPI *CERTGETCERTIFICATECHAIN )( HCERTCHAINENGINE hChainEngine,
193  PCCERT_CONTEXT pCertContext, LPFILETIME pTime,
194  HCERTSTORE hAdditionalStore, PCERT_CHAIN_PARA pChainPara,
195  DWORD dwFlags, LPVOID pvReserved,
196  PCCERT_CHAIN_CONTEXT *ppChainContext );
197 typedef BOOL ( WINAPI *CERTGETCERTIFICATECONTEXTPROPERTY )( PCCERT_CONTEXT pCertContext,
198  DWORD dwPropId, void *pvData, DWORD *pcbData );
199 typedef PCCERT_CONTEXT ( WINAPI *CERTGETSUBJECTCERTIFICATEFROMSTORE )( HCERTSTORE hCertStore,
200  DWORD dwCertEncodingType, PCERT_INFO pCertId );
201 typedef BOOL ( WINAPI *CERTSETCERTIFICATEPROPERTY )( PCCERT_CONTEXT pCertContext,
202  DWORD dwPropId, DWORD dwFlags, const void *pvData );
203 typedef HCERTSTORE ( WINAPI *CERTOPENSYSTEMSTORE )( HCRYPTPROV hprov,
204  LPCSTR szSubsystemProtocol );
205 
206 typedef BOOL ( WINAPI *CRYPTACQUIRECERTIFICATEPRIVATEKEY )( PCCERT_CONTEXT pCert,
207  DWORD dwFlags, void *pvReserved, HCRYPTPROV *phCryptProv,
208  DWORD *pdwKeySpec, BOOL *pfCallerFreeProv );
209 typedef BOOL ( WINAPI *CRYPTACQUIRECONTEXTA )( HCRYPTPROV *phProv, LPCSTR pszContainer,
211 typedef BOOL ( WINAPI *CRYPTCREATEHASH )( HCRYPTPROV hProv, ALG_ID Algid,
212  HCRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH* phHash );
213 typedef BOOL ( WINAPI *CRYPTDECRYPT )( HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
214  DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen );
215 typedef BOOL ( WINAPI *CRYPTDESTROYHASH )( HCRYPTHASH hHash );
216 typedef BOOL ( WINAPI *CRYPTDESTROYKEY )( HCRYPTKEY hKey );
217 typedef BOOL ( WINAPI *CRYPTENCRYPT )( HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
218  DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen );
219 typedef BOOL ( WINAPI *CRYPTEXPORTKEY )( HCRYPTKEY hKey, HCRYPTKEY hExpKey,
220  DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen );
221 typedef BOOL ( WINAPI *CRYPTFINDCERTIFICATEKEYPROVINFO )( PCCERT_CONTEXT pCert,
222  DWORD dwFlags, void *pvReserved );
223 typedef BOOL ( WINAPI *CRYPTGENKEY )( HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags,
224  HCRYPTKEY *phKey );
225 typedef BOOL ( WINAPI *CRYPTGENRANDOM )( HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer );
226 typedef BOOL ( WINAPI *CRYPTGETKEYPARAM )( HCRYPTKEY hKey, DWORD dwParam, BYTE* pbData,
227  DWORD* pdwDataLen, DWORD dwFlags );
228 typedef BOOL ( WINAPI *CRYPTGETPROVPARAM )( HCRYPTPROV hProv, DWORD dwParam,
229  BYTE *pbData, DWORD *pdwDataLen, DWORD dwFlags );
230 typedef BOOL ( WINAPI *CRYPTGETUSERKEY )( HCRYPTPROV hProv, DWORD dwKeySpec,
231  HCRYPTKEY* phUserKey );
232 typedef BOOL ( WINAPI *CRYPTHASHDATA )( HCRYPTHASH hHash, BYTE *pbData, DWORD dwDataLen,
233  DWORD dwFlags );
234 typedef BOOL ( WINAPI *CRYPTIMPORTKEY )( HCRYPTPROV hProv, CONST BYTE *pbData,
235  DWORD dwDataLen, HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey );
236 typedef BOOL ( WINAPI *CRYPTRELEASECONTEXT )( HCRYPTPROV hProv, DWORD dwFlags );
237 typedef BOOL ( WINAPI *CRYPTSETHASHPARAM )( HCRYPTHASH hHash, DWORD dwParam,
238  BYTE* pbData, DWORD dwFlags );
239 typedef BOOL ( WINAPI *CRYPTSETKEYPARAM )( HCRYPTKEY hKey, DWORD dwParam,
240  BYTE *pbData, DWORD dwFlags );
241 typedef BOOL ( WINAPI *CRYPTSIGNHASH )( HCRYPTHASH hHash, DWORD dwKeySpec,
242  LPCTSTR sDescription, DWORD dwFlags, BYTE* pbSignature,
243  DWORD* pdwSigLen );
244 
245 static CERTADDCERTIFICATETOSTORE pCertAddCertificateContextToStore = NULL;
246 static CERTADDENCODEDCERTIFICATETOSTORE pCertAddEncodedCertificateToStore = NULL;
247 static CERTCREATECERTIFICATECONTEXT pCertCreateCertificateContext = NULL;
248 static CERTDELETECERTIFICATEFROMSTORE pCertDeleteCertificateFromStore = NULL;
249 static CERTCLOSESTORE pCertCloseStore = NULL;
250 static CERTFINDCERTIFICATEINSTORE pCertFindCertificateInStore = NULL;
251 static CERTFREECERTIFICATECHAIN pCertFreeCertificateChain = NULL;
252 static CERTFREECERTIFICATECONTEXT pCertFreeCertificateContext = NULL;
253 static CERTGETCERTIFICATECHAIN pCertGetCertificateChain = NULL;
254 static CERTGETCERTIFICATECONTEXTPROPERTY pCertGetCertificateContextProperty = NULL;
255 static CERTGETSUBJECTCERTIFICATEFROMSTORE pCertGetSubjectCertificateFromStore = NULL;
256 static CERTSETCERTIFICATEPROPERTY pCertSetCertificateContextProperty = NULL;
257 static CERTOPENSYSTEMSTORE pCertOpenSystemStore = NULL;
258 
259 static CRYPTACQUIRECERTIFICATEPRIVATEKEY pCryptAcquireCertificatePrivateKey = NULL;
260 static CRYPTACQUIRECONTEXTA pCryptAcquireContextA = NULL;
261 static CRYPTCREATEHASH pCryptCreateHash = NULL;
262 static CRYPTDECRYPT pCryptDecrypt = NULL;
263 static CRYPTDESTROYHASH pCryptDestroyHash = NULL;
264 static CRYPTDESTROYKEY pCryptDestroyKey = NULL;
265 static CRYPTENCRYPT pCryptEncrypt = NULL;
266 static CRYPTEXPORTKEY pCryptExportKey = NULL;
267 static CRYPTFINDCERTIFICATEKEYPROVINFO pCryptFindCertificateKeyProvInfo = NULL;
268 static CRYPTGENKEY pCryptGenKey = NULL;
269 static CRYPTGENRANDOM pCryptGenRandom = NULL;
270 static CRYPTGETKEYPARAM pCryptGetKeyParam = NULL;
271 static CRYPTGETPROVPARAM pCryptGetProvParam = NULL;
272 static CRYPTGETUSERKEY pCryptGetUserKey = NULL;
273 static CRYPTHASHDATA pCryptHashData = NULL;
274 static CRYPTIMPORTKEY pCryptImportKey = NULL;
275 static CRYPTRELEASECONTEXT pCryptReleaseContext = NULL;
276 static CRYPTSETHASHPARAM pCryptSetHashParam = NULL;
277 static CRYPTSETKEYPARAM pCryptSetKeyParam = NULL;
278 static CRYPTSIGNHASH pCryptSignHash = NULL;
279 
280 /* Dynamically load and unload any necessary DBMS libraries */
281 
282 int deviceInitCryptoAPI( void )
283  {
284  /* If the CryptoAPI module is already linked in, don't do anything */
285  if( hCryptoAPI != NULL_HINSTANCE )
286  return( CRYPT_OK );
287 
288  /* Obtain handles to the modules containing the CryptoAPI functions */
289  if( ( hAdvAPI32 = GetModuleHandle( "AdvAPI32.DLL" ) ) == NULL )
290  return( CRYPT_ERROR );
291  if( ( hCryptoAPI = DynamicLoad( "Crypt32.dll" ) ) == NULL_HINSTANCE )
292  return( CRYPT_ERROR );
293 
294  /* Get pointers to the crypt functions */
295  pCryptAcquireCertificatePrivateKey = ( CRYPTACQUIRECERTIFICATEPRIVATEKEY ) GetProcAddress( hCryptoAPI, "CryptAcquireCertificatePrivateKey" );
296  pCryptAcquireContextA = ( CRYPTACQUIRECONTEXTA ) GetProcAddress( hAdvAPI32, "CryptAcquireContextA" );
297  pCryptCreateHash = ( CRYPTCREATEHASH ) GetProcAddress( hAdvAPI32, "CryptCreateHash" );
298  pCryptDecrypt = ( CRYPTDECRYPT ) GetProcAddress( hAdvAPI32, "CryptDecrypt" );
299  pCryptDestroyHash = ( CRYPTDESTROYHASH ) GetProcAddress( hAdvAPI32, "CryptDestroyHash" );
300  pCryptDestroyKey = ( CRYPTDESTROYKEY ) GetProcAddress( hAdvAPI32, "CryptDestroyKey" );
301  pCryptEncrypt = ( CRYPTENCRYPT ) GetProcAddress( hAdvAPI32, "CryptEncrypt" );
302  pCryptExportKey = ( CRYPTEXPORTKEY ) GetProcAddress( hAdvAPI32, "CryptExportKey" );
303  pCryptFindCertificateKeyProvInfo = ( CRYPTFINDCERTIFICATEKEYPROVINFO ) GetProcAddress( hCryptoAPI, "CryptFindCertificateKeyProvInfo" );
304  pCryptGenKey = ( CRYPTGENKEY ) GetProcAddress( hAdvAPI32, "CryptGenKey" );
305  pCryptGenRandom = ( CRYPTGENRANDOM ) GetProcAddress( hAdvAPI32, "CryptGenRandom" );
306  pCryptGetKeyParam = ( CRYPTGETKEYPARAM ) GetProcAddress( hAdvAPI32, "CryptGetKeyParam" );
307  pCryptGetProvParam = ( CRYPTGETPROVPARAM ) GetProcAddress( hAdvAPI32, "CryptGetProvParam" );
308  pCryptGetUserKey = ( CRYPTGETUSERKEY ) GetProcAddress( hAdvAPI32, "CryptGetUserKey" );
309  pCryptHashData = ( CRYPTHASHDATA ) GetProcAddress( hAdvAPI32, "CryptHashData" );
310  pCryptImportKey = ( CRYPTIMPORTKEY ) GetProcAddress( hAdvAPI32, "CryptImportKey" );
311  pCryptReleaseContext = ( CRYPTRELEASECONTEXT ) GetProcAddress( hAdvAPI32, "CryptReleaseContext" );
312  pCryptSetHashParam = ( CRYPTSETHASHPARAM ) GetProcAddress( hAdvAPI32, "CryptSetHashParam" );
313  pCryptSetKeyParam = ( CRYPTSETKEYPARAM ) GetProcAddress( hAdvAPI32, "CryptSetKeyParam" );
314  pCryptSignHash = ( CRYPTSIGNHASH ) GetProcAddress( hAdvAPI32, "CryptSignHashA" );
315 
316  /* Get pointers to the certificate functions */
317  pCertAddCertificateContextToStore = ( CERTADDCERTIFICATETOSTORE ) GetProcAddress( hCryptoAPI, "CertAddCertificateContextToStore" );
318  pCertAddEncodedCertificateToStore = ( CERTADDENCODEDCERTIFICATETOSTORE ) GetProcAddress( hCryptoAPI, "CertAddEncodedCertificateToStore" );
319  pCertCreateCertificateContext = ( CERTCREATECERTIFICATECONTEXT ) GetProcAddress( hCryptoAPI, "CertCreateCertificateContext" );
320  pCertDeleteCertificateFromStore = ( CERTDELETECERTIFICATEFROMSTORE ) GetProcAddress( hCryptoAPI, "CertDeleteCertificateFromStore" );
321  pCertCloseStore = ( CERTCLOSESTORE ) GetProcAddress( hCryptoAPI, "CertCloseStore" );
322  pCertFindCertificateInStore = ( CERTFINDCERTIFICATEINSTORE ) GetProcAddress( hCryptoAPI, "CertFindCertificateInStore" );
323  pCertFreeCertificateChain = ( CERTFREECERTIFICATECHAIN ) GetProcAddress( hCryptoAPI, "CertFreeCertificateChain" );
324  pCertFreeCertificateContext = ( CERTFREECERTIFICATECONTEXT ) GetProcAddress( hCryptoAPI, "CertFreeCertificateContext" );
325  pCertGetCertificateChain = ( CERTGETCERTIFICATECHAIN ) GetProcAddress( hCryptoAPI, "CertGetCertificateChain" );
326  pCertGetCertificateContextProperty = ( CERTGETCERTIFICATECONTEXTPROPERTY ) GetProcAddress( hCryptoAPI, "CertGetCertificateContextProperty" );
327  pCertGetSubjectCertificateFromStore = ( CERTGETSUBJECTCERTIFICATEFROMSTORE ) GetProcAddress( hCryptoAPI, "CertGetSubjectCertificateFromStore" );
328  pCertSetCertificateContextProperty = ( CERTSETCERTIFICATEPROPERTY ) GetProcAddress( hCryptoAPI, "CertSetCertificateContextProperty" );
329  pCertOpenSystemStore = ( CERTOPENSYSTEMSTORE ) GetProcAddress( hCryptoAPI, "CertOpenSystemStoreA" );
330 
331  /* Make sure that we got valid pointers for every CryptoAPI function */
332  if( pCertAddCertificateContextToStore == NULL || \
333  pCertAddEncodedCertificateToStore == NULL ||
334  pCertCreateCertificateContext == NULL ||
335  pCertDeleteCertificateFromStore == NULL ||
336  pCertCloseStore == NULL || pCertFindCertificateInStore == NULL ||
337  pCertFreeCertificateChain == NULL ||
338  pCertFreeCertificateContext == NULL ||
339  pCertGetCertificateChain == NULL ||
340  pCertGetCertificateContextProperty == NULL ||
341  pCertGetSubjectCertificateFromStore == NULL ||
342  pCertSetCertificateContextProperty == NULL ||
343  pCertOpenSystemStore == NULL ||
344  pCryptAcquireCertificatePrivateKey == NULL ||
345  pCryptAcquireContextA == NULL || pCryptCreateHash == NULL ||
346  pCryptDecrypt == NULL || pCryptEncrypt == NULL ||
347  pCryptExportKey == NULL || pCryptDestroyHash == NULL ||
348  pCryptDestroyKey == NULL ||
349  pCryptFindCertificateKeyProvInfo == NULL || pCryptGenKey == NULL ||
350  pCryptGenRandom == NULL || pCryptGetKeyParam == NULL ||
351  pCryptGetProvParam == NULL || pCryptGetUserKey == NULL ||
352  pCryptHashData == NULL || pCryptImportKey == NULL ||
353  pCryptReleaseContext == NULL || pCryptSetHashParam == NULL ||
354  pCryptSetKeyParam == NULL || pCryptSignHash == NULL )
355  {
356  /* Free the library reference and reset the handle */
357  DynamicUnload( hCryptoAPI );
358  hCryptoAPI = NULL_HINSTANCE;
359  return( CRYPT_ERROR );
360  }
361 
362  return( CRYPT_OK );
363  }
364 
365 void deviceEndCryptoAPI( void )
366  {
367  if( hCryptoAPI != NULL_HINSTANCE )
368  DynamicUnload( hCryptoAPI );
369  hCryptoAPI = NULL_HINSTANCE;
370  }
371 
372 /****************************************************************************
373 * *
374 * Utility Routines *
375 * *
376 ****************************************************************************/
377 
378 /* Get access to the PKCS #11 device associated with a context */
379 
380 static int getContextDeviceInfo( const CRYPT_HANDLE iCryptContext,
381  CRYPT_DEVICE *iCryptDevice,
382  CRYPTOAPI_INFO **cryptoapiInfoPtrPtr )
383  {
384  CRYPT_DEVICE iLocalDevice;
385  DEVICE_INFO *deviceInfo;
386  int cryptStatus;
387 
388  /* Clear return values */
389  *iCryptDevice = CRYPT_ERROR;
390  *cryptoapiInfoPtrPtr = NULL;
391 
392  /* Get the the device associated with this context */
393  cryptStatus = krnlSendMessage( iCryptContext, IMESSAGE_GETDEPENDENT,
394  &iLocalDevice, OBJECT_TYPE_DEVICE );
395  if( cryptStatusError( cryptStatus ) )
396  return( cryptStatus );
397 
398  /* Get the CryptoAPI information from the device information */
399  cryptStatus = krnlAcquireObject( iLocalDevice, OBJECT_TYPE_DEVICE,
400  ( void ** ) &deviceInfo,
402  if( cryptStatusError( cryptStatus ) )
403  return( cryptStatus );
404  *iCryptDevice = iLocalDevice;
405  *cryptoapiInfoPtrPtr = deviceInfo->deviceCryptoAPI;
406 
407  return( CRYPT_OK );
408  }
409 
410 /* Map a CryptoAPI-specific error to a cryptlib error */
411 
412 static int mapError( CRYPTOAPI_INFO *cryptoapiInfo, const int defaultError )
413  {
414 #ifdef USE_ERRMSGS
415  ERROR_INFO *errorInfo = &cryptoapiInfo->errorInfo;
416  int messageLength;
417 #endif /* USE_ERRMSGS */
418  const DWORD errorCode = GetLastError();
419 
420  /* Get the error message for this error. FormatMessage() adds EOL
421  terminators so we have to strip those before we pass the string back
422  to the caller. There's an incredibly arcane way of telling
423  FormatMessage() to do this via escape codes passed in as part of a
424  va_arg argument list, but aside from being complex to set up this
425  also means that the function will try and insert information such as
426  filenames from the argument list when required (there's no way to
427  tell in advance which arguments are required), so this is more
428  trouble than it's worth */
429 #ifdef USE_ERRMSGS
430  FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorCode, 0,
431  errorInfo->errorString, MAX_ERRMSG_SIZE - 1, NULL );
432  for( messageLength = strlen( errorInfo->errorString );
433  messageLength > 0 && \
434  ( errorInfo->errorString[ messageLength - 1 ] == '\n' || \
435  errorInfo->errorString[ messageLength - 1 ] == '\r' );
436  messageLength-- );
437  errorInfo->errorStringLength = messageLength;
438 #endif /* USE_ERRMSGS */
439 
440  /* Translate the CAPI error code into the cryptlib equivalent */
441  switch( errorCode )
442  {
443  case CRYPT_E_UNKNOWN_ALGO:
444  return( CRYPT_ERROR_NOTAVAIL );
445 
446  case ERROR_BUSY:
447  return( CRYPT_ERROR_TIMEOUT );
448 
449  case ERROR_MORE_DATA:
450  return( CRYPT_ERROR_OVERFLOW );
451 
452  case ERROR_NO_MORE_ITEMS:
453  return( CRYPT_ERROR_COMPLETE );
454 
455  case NTE_BAD_DATA:
456  return( CRYPT_ERROR_BADDATA );
457 
458  case CRYPT_E_EXISTS:
459  case NTE_EXISTS:
460  return( CRYPT_ERROR_DUPLICATE );
461 
462  case ERROR_NOT_ENOUGH_MEMORY:
463  case NTE_NO_MEMORY:
464  return( CRYPT_ERROR_MEMORY );
465 
466  case CRYPT_E_SECURITY_SETTINGS:
467  case NTE_PERM:
468  return( CRYPT_ERROR_PERMISSION );
469 
470  case NTE_BAD_SIGNATURE:
471  return( CRYPT_ERROR_SIGNATURE );
472 
473  case CRYPT_E_NO_MATCH:
474  case CRYPT_E_NOT_FOUND:
475  case NTE_KEYSET_NOT_DEF:
476  case NTE_NOT_FOUND:
477  case NTE_PROV_DLL_NOT_FOUND:
478  case NTE_PROV_TYPE_NO_MATCH:
479  case NTE_PROV_TYPE_NOT_DEF:
480  return( CRYPT_ERROR_NOTFOUND );
481  }
482 
483  return( defaultError );
484  }
485 
486 static int mapDeviceError( CONTEXT_INFO *contextInfoPtr, const int defaultError )
487  {
488  CRYPT_DEVICE iCryptDevice;
489  CRYPTOAPI_INFO *cryptoapiInfo;
490  int status;
491 
492  /* Get the device associated with this context, set the error information
493  in it, and exit */
494  status = getContextDeviceInfo( contextInfoPtr->objectHandle,
495  &iCryptDevice, &cryptoapiInfo );
496  if( cryptStatusError( status ) )
497  return( status );
498  status = mapError( cryptoapiInfo, defaultError );
499  krnlReleaseObject( iCryptDevice );
500  return( status );
501  }
502 
503 /* Map cryptlib to/from CryptoAPI algorithm IDs */
504 
505 static const MAP_TABLE algoMapTbl[] = {
506  /* PKC algorithms */
507  { CRYPT_ALGO_RSA, CALG_RSA_SIGN },
508  { CRYPT_ALGO_RSA, CALG_RSA_KEYX },
509  { CRYPT_ALGO_DSA, CALG_DSS_SIGN },
510 
511  /* Encryption algorithms */
512  { CRYPT_ALGO_DES, CALG_DES },
513  { CRYPT_ALGO_3DES, CALG_3DES },
514  { CRYPT_ALGO_RC2, CALG_RC2 },
515  { CRYPT_ALGO_RC4, CALG_RC4 },
516 
517  /* Hash algorithms */
518  { CRYPT_ALGO_MD5, CALG_MD5 },
519  { CRYPT_ALGO_SHA1, CALG_SHA },
520 
521  { CRYPT_ALGO_NONE, 0 }, { CRYPT_ALGO_NONE, 0 }
522  };
523 
524 static ALG_ID cryptlibToCapiID( const CRYPT_ALGO_TYPE cryptAlgo )
525  {
526  int value, status;
527 
528  status = mapValue( cryptAlgo, &value, algoMapTbl,
529  FAILSAFE_ARRAYSIZE( algoMapTbl, MAP_TABLE ) );
530  ENSURES_EXT( cryptStatusOK( status ), CALG_NONE );
531 
532  return( value );
533  }
534 
535 static CRYPT_ALGO_TYPE capiToCryptlibID( const ALG_ID algID )
536  {
537  int i;
538 
539  for( i = 0; algoMapTbl[ i ].source != CRYPT_ALGO_NONE && \
540  i < FAILSAFE_ARRAYSIZE( algoMapTbl, MAP_TABLE ); i++ )
541  {
542  if( ( ALG_ID ) algoMapTbl[ i ].destination == algID )
543  break;
544  }
545  if( i >= FAILSAFE_ARRAYSIZE( algoMapTbl, MAP_TABLE ) )
547  if( algoMapTbl[ i ].source == CRYPT_ALGO_NONE )
548  return( CRYPT_ALGO_NONE );
549  return( algoMapTbl[ i ].source );
550  }
551 
552 /* Copy an MPI into the little-endian order required by CryptoAPI, returning
553  the end position of the copied MPI */
554 
555 static BYTE *copyMPI( BYTE *dest, const BYTE *src, const int srcLen,
556  const int srcRequiredLen )
557  {
558  int i;
559 
560  dest += srcLen - 1;
561  for( i = 0; i < srcLen; i++ )
562  *dest-- = *src++;
563  dest += srcLen + 1;
564  if( srcLen < srcRequiredLen )
565  {
566  /* CryptoAPI blobs don't contain any length information but
567  implicitly specify all lengths in terms of the size of the
568  main MPI component, so if the actual length is less than the
569  assumed length we pad the remainder out with zeroes */
570  for( i = 0; i < srcRequiredLen - srcLen; i++ )
571  *dest++ = 0;
572  }
573 
574  return( dest );
575  }
576 
577 /* Create the special-case RSA key with e=1 that's needed to allow direct
578  key import and export */
579 
580 static int createExportKey( const HCRYPTPROV hProv, HCRYPTKEY *hPrivateKey,
581  int *privateKeySize )
582  {
583  BLOBHEADER *blobHeaderPtr;
584  RSAPUBKEY *pubKeyPtr;
585  BYTE keyBlob[ 1024 + 8 ], *keyBlobPtr;
586  DWORD keyBlobLen = 1024;
587  BOOL result;
588  int bitLen16;
589 
590  /* Generate a private key and export it as a private key blob:
591 
592  Ofs Value
593 
594  0 BLOBHEADER blobheader {
595  0 BYTE bType;
596  1 BYTE bVersion;
597  2 WORD reserved;
598  4 ALG_ID aiKeyAlg; }
599  8 RSAPUBKEY rsapubkey {
600  8 DWORD magic;
601  12 DWORD bitlen;
602  16 DWORD pubexp; }
603  20 BYTE modulus[ rsapubkey.bitlen / 8 ];
604  BYTE prime1[ rsapubkey.bitlen / 16 ];
605  BYTE prime2[ rsapubkey.bitlen / 16 ];
606  BYTE exponent1[ rsapubkey.bitlen / 16 ];
607  BYTE exponent2[ rsapubkey.bitlen / 16 ];
608  BYTE coefficient[ rsapubkey.bitlen / 16 ];
609  BYTE privateExponent[ rsapubkey.bitlen / 8 ]; */
610  if( !pCryptGenKey( hProv, AT_KEYEXCHANGE, CRYPT_EXPORTABLE, hPrivateKey ) || \
611  !pCryptExportKey( *hPrivateKey, 0, PRIVATEKEYBLOB, 0, keyBlob, &keyBlobLen ) || \
612  !pCryptDestroyKey( *hPrivateKey ) )
613  return( CRYPT_ERROR );
614 
615  /* Perform a general sanity check on the returned data */
616  blobHeaderPtr = ( BLOBHEADER * ) keyBlob;
617  if( blobHeaderPtr->bType != PRIVATEKEYBLOB || \
618  blobHeaderPtr->bVersion != CUR_BLOB_VERSION || \
619  blobHeaderPtr->aiKeyAlg != CALG_RSA_KEYX )
620  {
621  pCryptDestroyKey( *hPrivateKey );
622  return( CRYPT_ERROR );
623  }
624 
625  /* Set the public exponent to 1 (little-endian 32-bit value) and skip to
626  the private exponents */
627  pubKeyPtr = ( RSAPUBKEY * ) ( keyBlob + BLOBHEADER_SIZE );
628  bitLen16 = ( pubKeyPtr->bitlen / 16 );
629  pubKeyPtr->pubexp = 1;
630  keyBlobPtr = keyBlob + 20 + ( pubKeyPtr->bitlen / 8 ) + bitLen16 + bitLen16;
631 
632  /* Set the two exponents to 1 */
633  *keyBlobPtr++ = 1;
634  memset( keyBlobPtr, 0, bitLen16 - 1 );
635  keyBlobPtr += bitLen16 - 1;
636  *keyBlobPtr++ = 1;
637  memset( keyBlobPtr, 0, bitLen16 - 1 );
638  keyBlobPtr += bitLen16 - 1;
639 
640  /* Set the private exponent to 1 */
641  keyBlobPtr += bitLen16; /* Skip coefficient */
642  *keyBlobPtr++ = 1;
643  memset( keyBlobPtr, 0, bitLen16 - 1 );
644  keyBlobPtr += bitLen16 - 1;
645 
646  /* Finally, re-import the hacked key and clean up */
647  result = pCryptImportKey( hProv, keyBlob, keyBlobLen, 0, 0, hPrivateKey );
648  if( result )
649  *privateKeySize = pubKeyPtr->bitlen / 8;
650  else
651  *hPrivateKey = 0;
652  zeroise( keyBlob, keyBlobLen );
653 
654  return( result ? CRYPT_OK : CRYPT_ERROR );
655  }
656 
657 /* Import a raw session key using the exponent-one RSA key */
658 
659 static int importPlainKey( const HCRYPTPROV hProv,
660  const HCRYPTKEY hPrivateKey,
661  const int privateKeySize, HCRYPTKEY *hSessionKey,
662  const CRYPT_ALGO_TYPE cryptAlgo, const BYTE *keyData,
663  const int keyDataSize, void *errorInfoPtr )
664  {
665  BLOBHEADER *blobHeaderPtr;
666  BYTE keyBlob[ 1024 + 8 ], *keyBlobPtr;
667  ALG_ID algID;
668  DWORD *dwPtr;
669  BOOL result;
670  const int blobSize = sizeof( BLOBHEADER ) + sizeof( ALG_ID ) + privateKeySize;
671  int i;
672 
673  /* Set up a SIMPLEBLOB:
674 
675  Ofs Value
676  0 BLOBHEADER blobheader {
677  0 BYTE bType;
678  1 BYTE bVersion;
679  2 WORD reserved;
680  4 ALG_ID aiKeyAlg; }
681  8 ALG_ID algid;
682  12 BYTE encryptedkey[ rsapubkey.bitlen/8 ]; */
683  memset( keyBlob, 0, 1024 );
684  algID = cryptlibToCapiID( cryptAlgo );
685  if( algID == 0 )
686  return( CRYPT_ERROR_NOTAVAIL );
687 
688  /* Set up the BLOBHEADER part of the blob */
689  blobHeaderPtr = ( BLOBHEADER * ) keyBlob;
690  blobHeaderPtr->bType = SIMPLEBLOB;
691  blobHeaderPtr->bVersion = CUR_BLOB_VERSION;
692  blobHeaderPtr->aiKeyAlg = algID;
693 
694  /* Set up the private-key algorithm ID */
695  dwPtr = ( DWORD * )( keyBlob + BLOBHEADER_SIZE );
696  *dwPtr = CALG_RSA_KEYX;
697 
698  /* Store the key as byte-reversed PKCS #1 padded data (or at least close
699  enough to it to work for the import) */
700  keyBlobPtr = keyBlob + 12;
701  for( i = keyDataSize - 1; i >= 0; i-- )
702  *keyBlobPtr++ = keyData[ i ];
703  *keyBlobPtr++ = 0;
704  memset( keyBlobPtr, 2, privateKeySize - ( keyDataSize + 2 ) );
705 
706  /* Import the key from the faked PKCS #1 wrapped form */
707  result = pCryptImportKey( hProv, keyBlob, blobSize, hPrivateKey, 0, hSessionKey );
708  zeroise( keyBlob, blobSize );
709  if( !result )
710  return( mapDeviceError( errorInfoPtr, CRYPT_ERROR_FAILED ) );
711 
712  return( CRYPT_OK );
713  }
714 
715 /* Load a CryptoAPI public key into a cryptlib native context */
716 
717 static int getPubkeyComponents( CRYPTOAPI_INFO *cryptoapiInfo,
718  const HCRYPTKEY hKey, BYTE *n, int *nLen,
719  BYTE *e, int *eLen )
720  {
721  BLOBHEADER *blobHeaderPtr;
722  RSAPUBKEY *pubKeyPtr;
723  BYTE keyBlob[ 1024 + CRYPT_MAX_PKCSIZE + 8 ], *nPtr;
724  BYTE buffer[ 16 + 8 ], *bufPtr = buffer;
725  DWORD keyBlobLen = 1024 + CRYPT_MAX_PKCSIZE;
726  int exponent, length;
727 
728  /* Clear return values */
729  memset( n, 0, 8 );
730  memset( e, 0, 8 );
731  *nLen = *eLen = 0;
732 
733  /* Get the public key components */
734  if( !pCryptExportKey( hKey, 0, PUBLICKEYBLOB, 0, keyBlob, &keyBlobLen ) )
735  return( mapError( cryptoapiInfo, CRYPT_ERROR_FAILED ) );
736 
737  /* Perform a general sanity check on the returned data */
738  blobHeaderPtr = ( BLOBHEADER * ) keyBlob;
739  if( blobHeaderPtr->bType != PUBLICKEYBLOB || \
740  blobHeaderPtr->bVersion != CUR_BLOB_VERSION )
741  return( CRYPT_ERROR_FAILED );
742 
743  /* Extract the public key components */
744  pubKeyPtr = ( RSAPUBKEY * ) ( keyBlob + BLOBHEADER_SIZE );
745  exponent = pubKeyPtr->pubexp;
746  nPtr = keyBlob + 20;
747  length = pubKeyPtr->bitlen / 8;
748  while( length > 0 && nPtr[ length ] == 0 )
749  length--;
750  copyMPI( n, nPtr, length, length );
751  *nLen = length;
752  length = ( exponent <= 0xFF ) ? 1 : \
753  ( exponent <= 0xFFFF ) ? 2 : \
754  ( exponent <= 0xFFFFFFL ) ? 3 : 4;
755  mputLong( bufPtr, exponent );
756  memcpy( e, buffer + ( 4 - length ), length );
757  *eLen = length;
758 
759  return( CRYPT_OK );
760  }
761 
762 static int capiToCryptlibContext( CRYPTOAPI_INFO *cryptoapiInfo,
763  const HCRYPTKEY hKey,
764  CRYPT_CONTEXT *cryptContextPtr )
765  {
766  CRYPT_PKCINFO_RSA rsaKey;
767  MESSAGE_CREATEOBJECT_INFO createInfo;
769  BYTE n[ CRYPT_MAX_PKCSIZE + 8 ], e[ CRYPT_MAX_PKCSIZE + 8 ];
770  int nLen, eLen, status;
771 
772  /* Clear return value */
773  *cryptContextPtr = CRYPT_ERROR;
774 
775  /* Extract the public-key components from the CryptoAPI context */
776  status = getPubkeyComponents( cryptoapiInfo, hKey, n, &nLen, e, &eLen );
777  if( cryptStatusError( status ) )
778  return( status );
779 
780  /* Copy the public-key components into the cryptlib format */
782  cryptSetComponent( ( &rsaKey )->n, n, bytesToBits( nLen ) );
783  cryptSetComponent( ( &rsaKey )->e, e, bytesToBits( eLen ) );
786 
787  /* Create the RSA context */
790  &createInfo, OBJECT_TYPE_CONTEXT );
791  if( cryptStatusError( status ) )
792  {
793  cryptDestroyComponents( &rsaKey );
794  return( status );
795  }
796 
797  /* Load the key into the context */
798  setMessageData( &msgData, "CryptoAPI RSA key", 17 );
800  &msgData, CRYPT_CTXINFO_LABEL );
801  if( cryptStatusOK( status ) )
802  {
803  setMessageData( &msgData, &rsaKey, sizeof( CRYPT_PKCINFO_RSA ) );
804  status = krnlSendMessage( createInfo.cryptHandle,
805  IMESSAGE_SETATTRIBUTE_S, &msgData,
807  }
808  cryptDestroyComponents( &rsaKey );
809  if( cryptStatusError( status ) )
810  {
811  DEBUG_DIAG(( "Failed to load CryptoAPI public key data" ));
812  assert( DEBUG_WARN );
814  return( status );
815  }
816 
817  *cryptContextPtr = createInfo.cryptHandle;
818  return( CRYPT_OK );
819  }
820 
821 /* Compare a CryptoAPI private key with a certificate to check whether the
822  certificate corresponds to the key */
823 
824 static BOOLEAN isCertKey( const CRYPTOAPI_INFO *cryptoapiInfo,
825  const HCRYPTKEY hKey,
827  {
828  return( TRUE );
829  }
830 
831 /* Get a certificate using a key/certificate identifier */
832 
833 static int getCertificate( const CRYPTOAPI_INFO *cryptoapiInfo,
835  const void *keyID, const int keyIDlength,
836  PCCERT_CONTEXT *pCertContextPtr )
837  {
838  PCCERT_CONTEXT pCertContext = NULL;
839 
840  switch( keyIDtype )
841  {
842  case CRYPT_KEYID_NAME:
843  {
844  CERT_RDN certRDN;
845  CERT_RDN_ATTR certRDNAttr;
846 
847  /* Find a certificate by CN */
848  memset( &certRDNAttr, 0, sizeof( CERT_RDN_ATTR ) );
849  certRDNAttr.pszObjId = szOID_COMMON_NAME;
850  certRDNAttr.dwValueType = CERT_RDN_ANY_TYPE;
851  certRDNAttr.Value.pbData = ( void * ) keyID;
852  certRDNAttr.Value.cbData = keyIDlength;
853  memset( &certRDN, 0, sizeof( CERT_RDN ) );
854  certRDN.rgRDNAttr = &certRDNAttr;
855  certRDN.cRDNAttr = 1;
856  pCertContext = \
857  pCertFindCertificateInStore( cryptoapiInfo->hCertStore,
858  X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_ATTR,
859  &certRDN, NULL );
860  break;
861  }
862 
863  case CRYPT_KEYID_URI:
864  {
865  CERT_RDN certRDN;
866  CERT_RDN_ATTR certRDNAttr;
867 
868  /* There doesn't appear to be any way to locate a certificate
869  using the email address in an altName, so we have to restrict
870  ourselves to the most commonly-used OID for certificates in
871  DNs */
872  memset( &certRDNAttr, 0, sizeof( CERT_RDN_ATTR ) );
873  certRDNAttr.pszObjId = szOID_RSA_emailAddr ;
874  certRDNAttr.dwValueType = CERT_RDN_ANY_TYPE;
875  certRDNAttr.Value.pbData = ( void * ) keyID;
876  certRDNAttr.Value.cbData = keyIDlength;
877  memset( &certRDN, 0, sizeof( CERT_RDN ) );
878  certRDN.rgRDNAttr = &certRDNAttr;
879  certRDN.cRDNAttr = 1;
880  pCertContext = \
881  pCertFindCertificateInStore( cryptoapiInfo->hCertStore,
882  X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_ATTR,
883  &certRDN, NULL );
884  break;
885  }
886 
887  case CRYPT_IKEYID_CERTID:
888  {
889  CRYPT_DATA_BLOB cryptDataBlob;
890 
891  memset( &cryptDataBlob, 0, sizeof( CRYPT_DATA_BLOB ) );
892  cryptDataBlob.pbData = ( void * ) keyID;
893  cryptDataBlob.cbData = keyIDlength;
894  pCertContext = \
895  pCertFindCertificateInStore( cryptoapiInfo->hCertStore,
896  X509_ASN_ENCODING, 0, CERT_FIND_SHA1_HASH,
897  &cryptDataBlob, NULL );
898  break;
899  }
900 
901  case CRYPT_IKEYID_KEYID:
902  {
903 #if 0
904  CERT_ID certID;
905 
906  certID.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
907  certID.KeyId.pbData = ( void * ) keyID;
908  certID.KeyId.cbData = keyIDlength;
909  pCertContext = \
910  pCertFindCertificateInStore( cryptoapiInfo->hCertStore,
911  X509_ASN_ENCODING, 0, CERT_FIND_CERT_ID,
912  &certID, NULL );
913 #else
914  CRYPT_HASH_BLOB hashBlob;
915 
916  hashBlob.pbData = ( void * ) keyID;
917  hashBlob.cbData = keyIDlength;
918  pCertContext = \
919  pCertFindCertificateInStore( cryptoapiInfo->hCertStore,
920  X509_ASN_ENCODING, 0, CERT_FIND_KEY_IDENTIFIER,
921  &hashBlob, NULL );
922 #endif /* 0 */
923  break;
924  }
925 
926  case CRYPT_IKEYID_ISSUERANDSERIALNUMBER:
927  {
929  STREAM stream;
930  void *dataPtr = DUMMY_INIT_PTR;
931  int length, status;
932 
933  memset( &certInfo, 0, sizeof( CERT_INFO ) );
934  sMemConnect( &stream, keyID, keyIDlength );
935  readSequence( &stream, NULL );
936  status = getStreamObjectLength( &stream, &length );
937  if( cryptStatusOK( status ) )
938  status = sMemGetDataBlock( &stream, &dataPtr, length );
939  if( cryptStatusError( status ) )
940  {
941  sMemDisconnect( &stream );
942  return( status );
943  }
944  certInfo.Issuer.pbData = dataPtr; /* Issuer DN */
945  certInfo.Issuer.cbData = length;
946  sSkip( &stream, length );
947  status = getStreamObjectLength( &stream, &length );
948  if( cryptStatusOK( status ) )
949  status = sMemGetDataBlock( &stream, &dataPtr, length );
950  if( cryptStatusError( status ) )
951  return( status );
952  certInfo.SerialNumber.pbData = dataPtr; /* Serial number */
953  certInfo.SerialNumber.cbData = length;
954  status = sSkip( &stream, length );
955  assert( sStatusOK( &stream ) );
956  sMemDisconnect( &stream );
957  if( cryptStatusError( status ) )
958  return( status );
959  pCertContext = \
960  pCertGetSubjectCertificateFromStore( cryptoapiInfo->hCertStore,
961  X509_ASN_ENCODING, &certInfo );
962  }
963 
964  default:
965  retIntError();
966  }
967 
968  if( pCertContext == NULL )
969  return( CRYPT_ERROR_NOTFOUND );
970  *pCertContextPtr = pCertContext;
971  return( CRYPT_OK );
972  }
973 
974 /* Get a certificate chain from a leaf certificate */
975 
976 static int getCertificateChain( CRYPTOAPI_INFO *cryptoapiInfo,
977  const PCCERT_CONTEXT pCertContext,
978  PCCERT_CHAIN_CONTEXT *pChainContextPtr )
979  {
980  CERT_CHAIN_PARA chainPara;
981  CERT_USAGE_MATCH certUsage;
982  CERT_ENHKEY_USAGE enhkeyUsage;
983  PCCERT_CHAIN_CONTEXT pChainContext;
984 
985  /* Clear return value */
986  *pChainContextPtr = NULL;
987 
988  /* Get the chain from the supplied certificate up to a root
989  certificate */
990  memset( &enhkeyUsage, 0, sizeof( CERT_ENHKEY_USAGE ) );
991  enhkeyUsage.cUsageIdentifier = 0;
992  enhkeyUsage.rgpszUsageIdentifier = NULL;
993  memset( &certUsage, 0, sizeof( CERT_USAGE_MATCH ) );
994  certUsage.dwType = USAGE_MATCH_TYPE_AND;
995  certUsage.Usage = enhkeyUsage;
996  memset( &chainPara, 0, sizeof( CERT_CHAIN_PARA ) );
997  chainPara.cbSize = sizeof( CERT_CHAIN_PARA );
998  chainPara.RequestedUsage = certUsage;
999  if( !pCertGetCertificateChain( NULL, pCertContext, NULL, NULL, &chainPara,
1000  CERT_CHAIN_CACHE_END_CERT | \
1001  CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY,
1002  NULL, &pChainContext ) )
1003  return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
1004  *pChainContextPtr = pChainContext;
1005  return( CRYPT_OK );
1006  }
1007 
1008 /* Get a certificate from a public/private key and vice versa */
1009 
1010 static int getCertificateFromKey( CRYPTOAPI_INFO *cryptoapiInfo,
1011  const HCRYPTKEY hKey,
1012  const BOOLEAN isSigningKey,
1013  PCCERT_CONTEXT *pCertContextPtr )
1014  {
1015  PCCERT_CONTEXT pCertContext;
1016  CERT_PUBLIC_KEY_INFO pubKeyInfo;
1017  BYTE keyBlob[ 1024 + CRYPT_MAX_PKCSIZE + 8 ];
1018  DWORD keyBlobLen = 1024 + CRYPT_MAX_PKCSIZE;
1019 
1020  /* Clear return value */
1021  *pCertContextPtr = NULL;
1022 
1023  /* Extract the public-key components from the public or private key */
1024  if( !pCryptExportKey( hKey, 0, PUBLICKEYBLOB, 0, keyBlob, &keyBlobLen ) )
1025  {
1026  pCryptDestroyKey( hKey );
1027  return( CRYPT_ERROR_NOTFOUND );
1028  }
1029 
1030  /* Get the certificate for the context's public key */
1031  memset( &pubKeyInfo, 0, sizeof( CERT_PUBLIC_KEY_INFO ) );
1032  pubKeyInfo.Algorithm.pszObjId = isSigningKey ? \
1033  CERT_DEFAULT_OID_PUBLIC_KEY_SIGN : \
1034  CERT_DEFAULT_OID_PUBLIC_KEY_XCHG;
1035  pubKeyInfo.PublicKey.pbData = keyBlob;
1036  pubKeyInfo.PublicKey.cbData = keyBlobLen;
1037  pCertContext = \
1038  pCertFindCertificateInStore( cryptoapiInfo->hCertStore,
1039  X509_ASN_ENCODING, 0, CERT_FIND_PUBLIC_KEY,
1040  &pubKeyInfo, NULL );
1041  if( pCertContext == NULL )
1042  return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
1043  *pCertContextPtr = pCertContext;
1044  return( CRYPT_OK );
1045  }
1046 
1047 #if 0
1048 
1049 static int getPrivKeyFromCertificate( CRYPTOAPI_INFO *cryptoapiInfo,
1050  const PCCERT_CONTEXT pCertContext,
1051  HCRYPTKEY *hKeyPtr )
1052  {
1053  HCRYPTPROV hProv;
1054  HCRYPTKEY hKey;
1055  DWORD dwKeySpec;
1056  BOOL fCallerFreeProv;
1057 
1058  /* Clear return value */
1059  *hKeyPtr = 0;
1060 
1061  /* Get the provider and key-type from the certificate and use that to
1062  get the key */
1063  if( !pCryptAcquireCertificatePrivateKey( pCertContext,
1064  CRYPT_ACQUIRE_CACHE_FLAG, NULL,
1065  &hProv, &dwKeySpec, &fCallerFreeProv ) )
1066  return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
1067  if( !pCryptGetUserKey( hProv, dwKeySpec, &hKey ) )
1068  return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
1069  *hKeyPtr = hKey;
1070  return( CRYPT_OK );
1071  }
1072 #endif /* 0 */
1073 
1074 /* Create a private-key context using a CryptoAPI native key */
1075 
1076 static int createPrivkeyContext( DEVICE_INFO *deviceInfo,
1077  CRYPT_CONTEXT *iCryptContext,
1078  CRYPT_ALGO_TYPE *cryptAlgo,
1079  const HCRYPTKEY hKey,
1080  const char *label )
1081  {
1082  ALG_ID algID;
1083  DWORD dwDataLen = sizeof( ALG_ID );
1084  const CAPABILITY_INFO *capabilityInfoPtr = NULL;
1086  int status;
1087 
1088  /* Clear return values */
1089  *iCryptContext = CRYPT_ERROR;
1090  *cryptAlgo = CRYPT_ALGO_NONE;
1091 
1092  /* Get the algorithm type and look up the corresponding capability
1093  information */
1094  if( !pCryptGetKeyParam( hKey, KP_ALGID, ( BYTE * ) &algID, &dwDataLen,
1095  0 ) || \
1096  ( *cryptAlgo = capiToCryptlibID( algID ) ) == CRYPT_ALGO_NONE )
1097  return( CRYPT_ERROR_NOTAVAIL );
1098  capabilityInfoPtr = findCapabilityInfo( deviceInfo->capabilityInfoList,
1099  *cryptAlgo );
1100  if( capabilityInfoPtr == NULL )
1101  return( CRYPT_ERROR_NOTAVAIL );
1102 
1103  /* Create a dummy context for the key, remember the device it's
1104  contained in, the object's label, and the handle for the device-
1105  internal key, and mark it as initialised (i.e. with a key loaded) */
1106  status = createContextFromCapability( iCryptContext,
1107  deviceInfo->ownerHandle, capabilityInfoPtr,
1110  if( cryptStatusError( status ) )
1111  return( status );
1112  krnlSendMessage( *iCryptContext, IMESSAGE_SETDEPENDENT,
1113  &deviceInfo->objectHandle, SETDEP_OPTION_INCREF );
1114  krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE,
1115  ( MESSAGE_CAST ) &hKey, CRYPT_IATTRIBUTE_DEVICEOBJECT );
1116  setMessageData( &msgData, ( MESSAGE_CAST ) label,
1117  min( strlen( label ), CRYPT_MAX_TEXTSIZE ) );
1118 #if 0
1119  if( cryptAlgo == CRYPT_ALGO_RSA )
1120  /* Send the keying information to the context. This is only
1121  possible for RSA keys since it's not possible to read y from a
1122  DSA private key object (see the comments in the DSA code for more
1123  on this), however the only time this is necessary is when a
1124  certificate is being generated for a key that was pre-generated
1125  in the device by someone else, which is typically done in Europe
1126  where DSA isn't used so this shouldn't be a problem */
1127  // Use getPubkeyComponents()
1128  cryptStatus = rsaSetPublicComponents( deviceInfo, *iCryptContext,
1129  hObject );
1130  else
1131  cryptStatus = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE,
1132  &keySize, CRYPT_IATTRIBUTE_KEYSIZE );
1133 #endif
1134  if( cryptStatusOK( status ) )
1135  status = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE_S,
1136  &msgData, CRYPT_CTXINFO_LABEL );
1137  if( cryptStatusOK( status ) )
1138  status = krnlSendMessage( *iCryptContext, IMESSAGE_SETATTRIBUTE,
1140  CRYPT_IATTRIBUTE_INITIALISED );
1141  if( cryptStatusError( status ) )
1142  {
1143  krnlSendNotifier( *iCryptContext, IMESSAGE_DECREFCOUNT );
1144  return( status );
1145  }
1146 
1147  return( CRYPT_OK );
1148  }
1149 
1150 /****************************************************************************
1151 * *
1152 * Device Init/Shutdown/Device Control Routines *
1153 * *
1154 ****************************************************************************/
1155 
1156 /* Prototypes for functions to get and free device capability information */
1157 
1158 static int getCapabilities( DEVICE_INFO *deviceInfo );
1159 static void freeCapabilities( DEVICE_INFO *deviceInfo );
1160 
1161 /* Close a previously-opened session with the device. We have to have this
1162  before the initialisation function since it may be called by it if the
1163  initialisation process fails */
1164 
1165 static void shutdownFunction( DEVICE_INFO *deviceInfo )
1166  {
1167  CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
1168 
1169  /* Log out and close the session with the device */
1170  if( deviceInfo->flags & DEVICE_LOGGEDIN )
1171  {
1172  if( cryptoapiInfo->hPrivateKey )
1173  pCryptDestroyKey( cryptoapiInfo->hPrivateKey );
1174  pCryptReleaseContext( cryptoapiInfo->hProv, 0 );
1175  }
1176  if( cryptoapiInfo->hCertStore != NULL )
1177  {
1178  pCertCloseStore( cryptoapiInfo->hCertStore, 0 );
1179  cryptoapiInfo->hCertStore = 0;
1180  }
1181  cryptoapiInfo->hProv = HCRYPTPROV_NONE;
1182  deviceInfo->flags &= ~( DEVICE_ACTIVE | DEVICE_LOGGEDIN );
1183 
1184  /* Free the device capability information */
1185  freeCapabilities( deviceInfo );
1186  }
1187 
1188 /* Open a session with the device */
1189 
1190 static int initFunction( DEVICE_INFO *deviceInfo, const char *name,
1191  const int nameLength )
1192  {
1193  CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
1194  HCRYPTPROV hProv;
1195  HCERTSTORE hCertStore;
1196  char providerNameBuffer[ CRYPT_MAX_TEXTSIZE + 1 + 8 ];
1197  char keysetNameBuffer[ CRYPT_MAX_TEXTSIZE + 1 + 8 ];
1198  const char *keysetName = NULL;
1199  DWORD value;
1200  int i, driverNameLength = nameLength, status;
1201 
1202  /* Check whether a keyset name has been specified */
1203  strlcpy_s( keysetNameBuffer, CRYPT_MAX_TEXTSIZE, "MY" );/* Default keyset */
1204  for( i = 1; i < nameLength - 1; i++ )
1205  {
1206  if( name[ i ] == ':' && name[ i + 1 ] == ':' )
1207  {
1208  const int keysetNameLength = nameLength - ( i + 2 );
1209 
1210  if( i > CRYPT_MAX_TEXTSIZE || keysetNameLength <= 0 || \
1211  keysetNameLength > CRYPT_MAX_TEXTSIZE )
1212  return( CRYPT_ARGERROR_STR1 );
1213 
1214  /* We've got a keyset name appended to the provider name, break
1215  out the provider and keyset names */
1216  memcpy( providerNameBuffer, name, i );
1217  providerNameBuffer[ i ] = '\0';
1218  memcpy( keysetNameBuffer, name + i + 2, keysetNameLength );
1219  keysetNameBuffer[ keysetNameLength ] = '\0';
1220  name = providerNameBuffer;
1221  keysetName = keysetNameBuffer;
1222  break;
1223  }
1224  }
1225 
1226  /* If we're auto-detecting the device, try various choices */
1227  if( driverNameLength == 12 && \
1228  !strnicmp( "[Autodetect]", name, driverNameLength ) )
1229  {
1230  if( CryptAcquireContextA( &hProv, keysetName, MS_ENHANCED_PROV,
1231  PROV_RSA_FULL, 0 ) )
1232  cryptoapiInfo->hProv = hProv;
1233  else
1234  {
1235  if( CryptAcquireContextA( &hProv, keysetName, MS_DEF_PROV,
1236  PROV_RSA_FULL, 0 ) )
1237  cryptoapiInfo->hProv = hProv;
1238  else
1239  return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
1240  }
1241  }
1242  else
1243  {
1244  /* Try and find a specific provider */
1245  if( CryptAcquireContextA( &hProv, keysetName, name, PROV_RSA_FULL, 0 ) )
1246  cryptoapiInfo->hProv = hProv;
1247  }
1248 
1249  /* Get information on device-specific capabilities */
1250  value = CRYPT_MAX_TEXTSIZE + 1;
1251  if( !CryptGetProvParam( cryptoapiInfo->hProv, PP_NAME,
1252  cryptoapiInfo->label, &value, 0 ) )
1253  return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
1254  cryptoapiInfo->labelLen = value;
1255  deviceInfo->label = cryptoapiInfo->label;
1256  deviceInfo->labelLen = cryptoapiInfo->labelLen;
1257  deviceInfo->flags |= DEVICE_ACTIVE;
1258 
1259  /* Set up the capability information for this device */
1260  status = getCapabilities( deviceInfo );
1261  if( cryptStatusError( status ) )
1262  {
1263  shutdownFunction( deviceInfo );
1264  return( ( status == CRYPT_ERROR ) ? CRYPT_ERROR_OPEN : status );
1265  }
1266 
1267  /* Create the special-purpose key needed to allow symmetric key loads */
1268  status = createExportKey( cryptoapiInfo->hProv,
1269  &cryptoapiInfo->hPrivateKey,
1270  &cryptoapiInfo->privateKeySize );
1271  if( cryptStatusError( status ) )
1272  {
1273  shutdownFunction( deviceInfo );
1274  return( status );
1275  }
1276 
1277  /* Open the certificate store used to store/retrieve certificates */
1278  hCertStore = pCertOpenSystemStore( cryptoapiInfo->hProv,
1279  keysetNameBuffer );
1280  if( hCertStore == NULL )
1281  {
1282  shutdownFunction( deviceInfo );
1283  return( CRYPT_ERROR_OPEN );
1284  }
1285  cryptoapiInfo->hCertStore = hCertStore;
1286 
1287  return( CRYPT_OK );
1288  }
1289 
1290 /* Handle device control functions */
1291 
1292 static int controlFunction( DEVICE_INFO *deviceInfo,
1293  const CRYPT_ATTRIBUTE_TYPE type,
1294  const void *data, const int dataLength,
1296  {
1297  retIntError();
1298  }
1299 
1300 /****************************************************************************
1301 * *
1302 * Misc.Device Interface Routines *
1303 * *
1304 ****************************************************************************/
1305 
1306 /* Get random data from the device */
1307 
1308 static int getRandomFunction( DEVICE_INFO *deviceInfo, void *buffer,
1309  const int length,
1311  {
1312  CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
1313 
1314  if( pCryptGenRandom( cryptoapiInfo->hProv, length, buffer ) )
1315  return( CRYPT_OK );
1316  return( mapError( cryptoapiInfo, CRYPT_ERROR_FAILED ) );
1317  }
1318 
1319 /* Instantiate an object in a device. This works like the create context
1320  function but instantiates a cryptlib object using data already contained
1321  in the device (for example a stored private key or certificate). If the
1322  value being read is a public key and there's a certificate attached, the
1323  instantiated object is a native cryptlib object rather than a device
1324  object with a native certificate object attached because there doesn't
1325  appear to be any good reason to create the public-key object in the
1326  device.
1327 
1328  CryptoAPI doesn't have any concept of multiple private keys, only a
1329  default encryption + signature key for the provider as a whole, and an
1330  optional additional signature key to complement the encryption (and
1331  signature if necessary) one. In addition the ties between a private key
1332  and its associated certificate(s) are rather tenuous, requiring jumping
1333  through several levels of indirection in order to get from one to the
1334  other. To handle this, we have to use a meet-in-the-middle approach
1335  where we try to go from private key to certificate if the identity of the
1336  private key is obvious (the user has specifically asked for a private
1337  decryption or signature key), or from certificate to private key in all
1338  other cases */
1339 
1340 static int getItemFunction( DEVICE_INFO *deviceInfo,
1341  CRYPT_CONTEXT *iCryptContext,
1342  const KEYMGMT_ITEM_TYPE itemType,
1343  const CRYPT_KEYID_TYPE keyIDtype,
1344  const void *keyID, const int keyIDlength,
1345  void *auxInfo, int *auxInfoLength,
1346  const int flags )
1347  {
1348  CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
1349 // CRYPT_CERTIFICATE iCryptCert;
1350  HCRYPTKEY hKey = 0;
1351  PCCERT_CONTEXT pCertContext = NULL;
1352  PCCERT_CHAIN_CONTEXT pChainContext = NULL;
1353  DWORD dwKeySpec = 0;
1355  CRYPT_ALGO_TYPE cryptAlgo = CRYPT_ALGO_NONE;
1356  const char *label = "Private key";
1357  int status;
1358 
1359  assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
1360  itemType == KEYMGMT_ITEM_PRIVATEKEY );
1361 
1362  /* If we're searching for the key by label and the user has specified
1363  one of the special-case key descriptions, get the appropriate key */
1364  if( keyIDtype == CRYPT_KEYID_NAME )
1365  {
1366  if( keyIDlength == 13 && \
1367  !memcmp( keyID, "Signature key", 13 ) )
1368  dwKeySpec = AT_SIGNATURE;
1369  else
1370  if( keyIDlength == 14 && \
1371  !memcmp( keyID, "Encryption key", 14 ) )
1372  dwKeySpec = AT_KEYEXCHANGE;
1373  }
1374 
1375  /* If we haven't got a key type from the label and we're looking for a
1376  particular usage, get the appropriate key */
1377  if( dwKeySpec == 0 && itemType == KEYMGMT_ITEM_PRIVATEKEY )
1378  {
1379  if( flags & KEYMGMT_FLAG_USAGE_SIGN )
1380  dwKeySpec = AT_SIGNATURE;
1381  else
1382  if( flags & KEYMGMT_FLAG_USAGE_CRYPT )
1383  dwKeySpec = AT_KEYEXCHANGE;
1384  }
1385 
1386  /* If we still haven't got a key type, try and get the certificate for
1387  the given ID */
1388  if( dwKeySpec != 0 )
1389  {
1390  /* Get the required key type */
1391  if( !pCryptGetUserKey( cryptoapiInfo->hProv, dwKeySpec, &hKey ) )
1392  return( CRYPT_ERROR_NOTFOUND );
1393  label = ( dwKeySpec == AT_SIGNATURE ) ? \
1394  "Signature key" : "Encryption key";
1395 
1396  /* If we're only doing a presence check, we don't need the key and
1397  can exit */
1398  if( flags & KEYMGMT_FLAG_CHECK_ONLY )
1399  {
1400  pCryptDestroyKey( hKey );
1401  return( CRYPT_OK );
1402  }
1403 
1404  /* Since CryptoAPI doesn't have any concept of key labels, the best
1405  that we can do is provide a generic description of the intended
1406  key usage as a form of pseudo-label */
1407  if( flags & KEYMGMT_FLAG_LABEL_ONLY )
1408  {
1409  strlcpy_s( auxInfo, *auxInfoLength, label );
1410  *auxInfoLength = strlen( label );
1411  pCryptDestroyKey( hKey );
1412  return( CRYPT_OK );
1413  }
1414 
1415  /* We've got the key, try and get the associated certificate */
1416  status = getCertificateFromKey( cryptoapiInfo, hKey,
1417  ( flags & KEYMGMT_FLAG_USAGE_SIGN ) ? \
1418  TRUE : FALSE, &pCertContext );
1419  if( cryptStatusError( status ) && \
1420  itemType == KEYMGMT_ITEM_PUBLICKEY )
1421  {
1422  /* We couldn't get a certificate for the key, if we're after a
1423  public key return it as a native context */
1424  status = capiToCryptlibContext( cryptoapiInfo, hKey,
1425  iCryptContext );
1426  pCryptDestroyKey( hKey );
1427  return( status );
1428  }
1429  }
1430  else
1431  {
1432  assert( !( flags & KEYMGMT_FLAG_LABEL_ONLY ) );
1433 
1434  /* We don't have a definite private key ID indicator, go via the
1435  certificate instead */
1436  status = getCertificate( cryptoapiInfo, keyIDtype, keyID, keyIDlength,
1437  &pCertContext );
1438  if( cryptStatusError( status ) )
1439  return( status );
1440 
1441  /* If we're only doing a presence check, we don't need the key and
1442  can exit */
1443  if( flags & KEYMGMT_FLAG_CHECK_ONLY )
1444  {
1445  pCertFreeCertificateContext( pCertContext );
1446  return( CRYPT_OK );
1447  }
1448 
1449  /* If we're after a private key, try and find the one corresponding
1450  to the certificate */
1451  if( itemType == KEYMGMT_ITEM_PRIVATEKEY )
1452  {
1453 #if 1
1454  CERT_KEY_CONTEXT certKeyContext;
1455  DWORD certKeyContextSize = sizeof( CERT_KEY_CONTEXT );
1456 
1457  if( !pCertGetCertificateContextProperty( pCertContext,
1458  CERT_KEY_CONTEXT_PROP_ID,
1459  &certKeyContext, &certKeyContextSize ) || \
1460  !pCryptGetUserKey( certKeyContext.hCryptProv,
1461  certKeyContext.dwKeySpec, &hKey ) )
1462  return( mapError( cryptoapiInfo, CRYPT_ERROR_NOTFOUND ) );
1463 
1464 #else /* Need to uncomment gPKFC() above */
1465  status = getPrivKeyFromCertificate( cryptoapiInfo, pCertContext,
1466  &hKey );
1467 #endif
1468  if( cryptStatusError( status ) )
1469  {
1470  pCertFreeCertificateContext( pCertContext );
1471  return( status );
1472  }
1473  }
1474  }
1475 
1476  /* If we've got a priavte key, create a device context for it */
1477  if( hKey != 0 )
1478  {
1479  status = createPrivkeyContext( deviceInfo, iCryptContext,
1480  &cryptAlgo, hKey, label );
1481  if( cryptStatusError( status ) )
1482  {
1483  if( pCertContext != NULL )
1484  pCertFreeCertificateContext( pCertContext );
1485  return( status );
1486  }
1487  }
1488 
1489  /* If there's no certificate available for the key, we're done */
1490  if( pCertContext == NULL )
1491  return( CRYPT_OK );
1492 
1493  /* We've got a key and certificate, try and get the rest of the chain
1494  for the certificate */
1495 {
1497 
1498  status = iCryptImportCertIndirect( &iCryptCert,
1499  deviceInfo->objectHandle, keyIDtype, keyID,
1500  keyIDlength, publicComponentsOnly ? \
1501  KEYMGMT_FLAG_NONE : \
1503 }
1504 
1505  if( cryptStatusOK( status ) )
1506  {
1507  /* If we're getting a public key, the returned information is the
1508  certificate chain */
1509  if( itemType == KEYMGMT_ITEM_PUBLICKEY )
1510  *iCryptContext = iCryptCert;
1511  else
1512  {
1513  /* If we're getting a private key, attach the certificate chain
1514  to the context. The certificate is an internal object used
1515  only by the context so we tell the kernel to mark it as owned
1516  by the context only */
1517  status = krnlSendMessage( *iCryptContext, IMESSAGE_SETDEPENDENT,
1518  &iCryptCert, SETDEP_OPTION_NOINCREF );
1519  }
1520  }
1521 
1522  /* Clean up */
1523  pCertFreeCertificateContext( pCertContext );
1524  pCertFreeCertificateChain( pChainContext );
1525  return( status );
1526 
1527 #if 0
1528  {
1529  const int keyTemplateCount = ( keyID == NULL ) ? 1 : 2;
1530 
1531  /* Try and find the object with the given label/ID, or the first
1532  object of the given class if no ID is given */
1533  keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) \
1534  ( ( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? \
1535  &pubkeyClass : &privkeyClass );
1536  if( keyIDtype != CRYPT_KEYID_NONE )
1537  {
1538  if( keyIDtype == CRYPT_IKEYID_KEYID )
1539  keyTemplate[ 1 ].type = CKA_ID;
1540  keyTemplate[ 1 ].pValue = ( CK_VOID_PTR ) keyID;
1541  keyTemplate[ 1 ].ulValueLen = keyIDlength;
1542  }
1543  cryptStatus = findObject( deviceInfo, &hObject, keyTemplate,
1544  keyTemplateCount );
1545  if( cryptStatus == CRYPT_ERROR_NOTFOUND && \
1546  itemType == KEYMGMT_ITEM_PUBLICKEY )
1547  {
1548  /* Some devices may only contain private key objects with
1549  associated certificates that can't be picked out of the other
1550  cruft that's present without going via the private key, so if
1551  we're looking for a public key and don't find one, we try
1552  again for a private key whose sole function is to point to an
1553  associated certificate */
1554  keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &privkeyClass;
1555  cryptStatus = findObject( deviceInfo, &hObject, keyTemplate,
1556  keyTemplateCount );
1557  if( cryptStatusError( cryptStatus ) )
1558  return( cryptStatus );
1559 
1560  /* Remember that although we've got a private key object, we only
1561  need it to find the associated certificate and not finding an
1562  associated certificate is an error */
1563  certViaPrivateKey = TRUE;
1564  }
1565  }
1566 
1567  /* If we're looking for any kind of private key and we either have an
1568  explicit certificate ID but couldn't find a certificate for it or we
1569  don't have a proper ID to search on and a generic search found more
1570  than one matching object, chances are we're after a generic decrypt
1571  key. The former only occurs in misconfigured or limited-memory
1572  tokens, the latter only in rare tokens that store more than one
1573  private key, typically one for signing and one for verification.
1574 
1575  If either of these cases occur we try again looking specifically for
1576  a decryption key. Even this doesn't always work, there's are some
1577  >1-key tokens that mark a signing key as a decryption key so we still
1578  get a CRYPT_ERROR_DUPLICATE error.
1579 
1580  Finally, if we can't find a decryption key either, we look for an
1581  unwrapping key. This may or may not work, depending on whether we
1582  have a decryption key marked as valid for unwrapping but not
1583  decryption, or a key that's genuinely only valid for unwrapping, but
1584  at this point we're ready to try anything */
1585  if( itemType == KEYMGMT_ITEM_PRIVATEKEY && \
1586  ( keyIDtype == CRYPT_IKEYID_ISSUERANDSERIALNUMBER && \
1587  cryptStatus == CRYPT_ERROR_NOTFOUND ) || \
1588  ( cryptStatus == CRYPT_ERROR_DUPLICATE ) )
1589  {
1590  static const CK_BBOOL bTrue = TRUE;
1591  CK_ATTRIBUTE decryptKeyTemplate[] = {
1592  { CKA_CLASS, ( CK_VOID_PTR ) &privkeyClass, sizeof( CK_OBJECT_CLASS ) },
1593  { CKA_DECRYPT, ( CK_VOID_PTR ) &bTrue, sizeof( CK_BBOOL ) }
1594  };
1595 
1596  cryptStatus = findObject( deviceInfo, &hObject,
1597  decryptKeyTemplate, 2 );
1598  if( cryptStatusError( cryptStatus ) )
1599  {
1600  decryptKeyTemplate[ 1 ].type = CKA_UNWRAP;
1601  cryptStatus = findObject( deviceInfo, &hObject,
1602  decryptKeyTemplate, 2 );
1603  }
1604  }
1605  if( cryptStatusError( cryptStatus ) )
1606  return( cryptStatus );
1607 
1608  /* If we're just checking whether an object exists, return now. If all
1609  we want is the key label, copy it back to the caller and exit */
1610  if( flags & KEYMGMT_FLAG_CHECK_ONLY )
1611  return( CRYPT_OK );
1612  if( flags & KEYMGMT_FLAG_LABEL_ONLY )
1613  return( getObjectLabel( deviceInfo, hObject, auxInfo,
1614  auxInfoLength ) );
1615 
1616  /* We found something, map the key type to a cryptlib algorithm ID,
1617  determine the key size, and find its capabilities */
1618  keyTypeTemplate.pValue = &keyType;
1619  C_GetAttributeValue( cryptoapiInfo->hProv, hObject,
1620  &keyTypeTemplate, 1 );
1621  switch( ( int ) keyType )
1622  {
1623  case CKK_RSA:
1624  cryptAlgo = CRYPT_ALGO_RSA;
1625  keySizeTemplate.type = CKA_MODULUS;
1626  break;
1627  case CKK_DSA:
1628  cryptAlgo = CRYPT_ALGO_DSA;
1629  keySizeTemplate.type = CKA_PRIME;
1630  break;
1631  case CKK_DH:
1632  cryptAlgo = CRYPT_ALGO_DH;
1633  keySizeTemplate.type = CKA_PRIME;
1634  break;
1635  default:
1636  return( CRYPT_ERROR_NOTAVAIL );
1637  }
1638  C_GetAttributeValue( cryptoapiInfo->hProv, hObject,
1639  &keySizeTemplate, 1 );
1640  keySize = keySizeTemplate.ulValueLen;
1641  capabilityInfoPtr = findCapabilityInfo( deviceInfo->capabilityInfo,
1642  cryptAlgo );
1643  if( capabilityInfoPtr == NULL )
1644  return( CRYPT_ERROR_NOTAVAIL );
1645 
1646  /* Try and find a certificate which matches the key. The process is as
1647  follows:
1648 
1649  if certificate object found in issuerAndSerialNumber search
1650  create native data-only certificate object
1651  attach certificate object to key
1652  else
1653  if public key
1654  if certificate
1655  create native certificate (+context) object
1656  else
1657  create device pubkey object, mark as "key loaded"
1658  else
1659  create device privkey object, mark as "key loaded"
1660  if certificate
1661  create native data-only certificate object
1662  attach certificate object to key
1663 
1664  The reason for doing things this way is given in the comments earlier
1665  on in this function */
1666  if( privateKeyViaCert )
1667  {
1668  /* We've already got the certificate object handle, instantiate a
1669  native data-only certificate from it */
1670  cryptStatus = instantiateCert( deviceInfo, hCertificate,
1671  &iCryptCert, FALSE );
1672  if( cryptStatusError( cryptStatus ) )
1673  return( cryptStatus );
1674  certPresent = TRUE;
1675  }
1676  else
1677  {
1678  cryptStatus = findCertFromObject( deviceInfo, hObject, &iCryptCert,
1679  ( itemType == KEYMGMT_ITEM_PUBLICKEY ) ? \
1680  FINDCERT_NORMAL : FINDCERT_DATAONLY );
1681  if( cryptStatusError( cryptStatus ) )
1682  {
1683  /* If we get a CRYPT_ERROR_NOTFOUND this is OK since it means
1684  there's no certificate present, however anything else is an
1685  error. In addition if we've got a private key whose only
1686  function is to point to an associated certificate then not
1687  finding anything is also an error */
1688  if( cryptStatus != CRYPT_ERROR_NOTFOUND || certViaPrivateKey )
1689  return( cryptStatus );
1690  }
1691  else
1692  {
1693  /* We got the certificate, if we're being asked for a public key
1694  then we've created a native object to contain it so we return
1695  that */
1696  certPresent = TRUE;
1697  if( itemType == KEYMGMT_ITEM_PUBLICKEY )
1698  {
1699  *iCryptContext = iCryptCert;
1700  return( CRYPT_OK );
1701  }
1702  }
1703  }
1704 #endif
1705  }
1706 
1707 /* Update a device with a certificate */
1708 
1709 static int setItemFunction( DEVICE_INFO *deviceInfo,
1710  const CRYPT_HANDLE iCryptHandle )
1711  {
1712  CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
1713  HCRYPTKEY hKey;
1714  DWORD dwKeySpec = 0;
1716  BOOLEAN seenNonDuplicate = FALSE;
1717  int iterationCount = 0, status;
1718 
1719  /* Lock the certificate for our exclusive use (in case it's a
1720  certificate chain, we also select the first certificate in the
1721  chain), update the device with the certificate, and unlock it to
1722  allow others access */
1723  krnlSendMessage( iCryptHandle, IMESSAGE_GETDEPENDENT, &iCryptCert,
1725  krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
1728  status = krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
1729  MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_LOCKED );
1730  if( cryptStatusError( status ) )
1731  return( status );
1732 
1733  /* Check whether the leaf certificate matches any of the user's private
1734  keys */
1735  if( pCryptGetUserKey( cryptoapiInfo->hProv, AT_KEYEXCHANGE, &hKey ) )
1736  {
1737  if( isCertKey( cryptoapiInfo, hKey, iCryptCert ) )
1738  dwKeySpec = AT_KEYEXCHANGE;
1739  pCryptDestroyKey( hKey );
1740  }
1741  else
1742  {
1743  if( pCryptGetUserKey( cryptoapiInfo->hProv, AT_SIGNATURE, &hKey ) )
1744  {
1745  if( isCertKey( cryptoapiInfo, hKey, iCryptCert ) )
1746  dwKeySpec = AT_SIGNATURE;
1747  pCryptDestroyKey( hKey );
1748  }
1749  }
1750 
1751  /* Add each certificate in the chain to the store */
1752  do
1753  {
1754  DYNBUF certDB;
1755  BOOL result = FALSE;
1756 
1757  /* Get the certificate data and add it to the store */
1758  status = dynCreate( &certDB, iCryptHandle,
1760  if( cryptStatusError( status ) )
1761  return( status );
1762 
1763  /* If the certificate corresponds to one of the user's private keys
1764  and a binding between the key and a certificate isn't already
1765  established, establish one now */
1766  if( dwKeySpec != 0 )
1767  {
1768  PCCERT_CONTEXT pCertContext;
1769  CERT_KEY_CONTEXT certKeyContext;
1770  DWORD certKeyContextSize = sizeof( CERT_KEY_CONTEXT );
1771 
1772  /* Check whether the certificate is already bound to a key and
1773  if not, bind it to the appropriate private key */
1774  pCertContext = pCertCreateCertificateContext( X509_ASN_ENCODING,
1775  dynData( certDB ), dynLength( certDB ) );
1776  if( pCertContext != NULL && \
1777  !pCertGetCertificateContextProperty( pCertContext,
1778  CERT_KEY_CONTEXT_PROP_ID,
1779  &certKeyContext, &certKeyContextSize ) )
1780  {
1781 #if 1
1782  /* Check the certificate stores synchronising the
1783  certificate's CERT_KEY_PROV_INFO_PROP_ID with any present
1784  private keys if required */
1785  pCryptFindCertificateKeyProvInfo( pCertContext, 0, NULL );
1786 #elif 0
1787  CRYPT_KEY_PROV_INFO keyProvInfo;
1788  BYTE buffer[ 256 + 8 ];
1789  DWORD length = 256;
1790  wchar_t provName[ 256 + 8 ], container[ 256 + 8 ];
1791 
1792  if( pCryptGetProvParam( cryptoapiInfo->hProv, PP_NAME,
1793  buffer, &length, 0 ) )
1794  MultiByteToWideChar( GetACP(), 0, buffer, length + 1,
1795  provName, 256 );
1796  if( pCryptGetProvParam( cryptoapiInfo->hProv, PP_CONTAINER,
1797  buffer, &length, 0 ) )
1798  MultiByteToWideChar( GetACP(), 0, buffer, length + 1,
1799  container, 256 );
1800  memset( &keyProvInfo, 0, sizeof( CRYPT_KEY_PROV_INFO ) );
1801  keyProvInfo.pwszContainerName = container;
1802  keyProvInfo.pwszProvName = provName;
1803  keyProvInfo.dwProvType = PROV_RSA_FULL;
1804  keyProvInfo.cProvParam = 0;
1805  keyProvInfo.dwKeySpec = dwKeySpec;
1806  pCertSetCertificateContextProperty( pCertContext,
1807  CERT_KEY_PROV_HANDLE_PROP_ID, 0,
1808  &keyProvInfo );
1809 #elif 0
1810  memset( &certKeyContext, 0, sizeof( CERT_KEY_CONTEXT ) );
1811  certKeyContext.cbSize = sizeof( CERT_KEY_CONTEXT );
1812  certKeyContext.dwKeySpec = dwKeySpec;
1813  certKeyContext.hCryptProv = cryptoapiInfo->hProv;
1814  pCertSetCertificateContextProperty( pCertContext,
1815  CERT_KEY_CONTEXT_PROP_ID, 0,
1816  &certKeyContext );
1817 #endif
1818  }
1819 
1820  /* Add the certificate to the store */
1821  if( pCertContext != NULL )
1822  {
1823  result = pCertAddCertificateContextToStore( cryptoapiInfo->hCertStore,
1824  pCertContext, CERT_STORE_ADD_NEW, NULL );
1825  pCertFreeCertificateContext( pCertContext );
1826  }
1827 
1828  /* We've now added a bound certificate, don't bind the key to
1829  any more certificates */
1830  dwKeySpec = 0;
1831  }
1832  else
1833  {
1834  /* Add the certificate to the store */
1835  result = pCertAddEncodedCertificateToStore( cryptoapiInfo->hCertStore,
1836  X509_ASN_ENCODING, dynData( certDB ),
1837  dynLength( certDB ), CERT_STORE_ADD_NEW, NULL );
1838  }
1839  dynDestroy( &certDB );
1840  if( result )
1841  seenNonDuplicate = TRUE;
1842  }
1843  while( krnlSendMessage( iCryptCert, IMESSAGE_SETATTRIBUTE,
1846  iterationCount++ < FAILSAFE_ITERATIONS_MED );
1847  if( iterationCount >= FAILSAFE_ITERATIONS_MED )
1848  retIntError();
1849 
1851  CRYPT_IATTRIBUTE_LOCKED );
1852 
1853  return( seenNonDuplicate ? CRYPT_OK : CRYPT_ERROR_DUPLICATE );
1854  }
1855 
1856 /* Delete an object in a device */
1857 
1858 static int deleteItemFunction( DEVICE_INFO *deviceInfo,
1859  const KEYMGMT_ITEM_TYPE itemType,
1860  const CRYPT_KEYID_TYPE keyIDtype,
1861  const void *keyID, const int keyIDlength )
1862  {
1863 #if 0
1864  static const CK_OBJECT_CLASS pubkeyClass = CKO_PUBLIC_KEY;
1865  static const CK_OBJECT_CLASS privkeyClass = CKO_PRIVATE_KEY;
1866  static const CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
1867  static const CK_CERTIFICATE_TYPE certType = CKC_X_509;
1868  CK_ATTRIBUTE certTemplate[] = {
1869  { CKA_CLASS, ( CK_VOID_PTR ) &certClass, sizeof( CK_OBJECT_CLASS ) },
1870  { CKA_CERTIFICATE_TYPE, ( CK_VOID_PTR ) &certType, sizeof( CK_CERTIFICATE_TYPE ) },
1871  { CKA_LABEL, ( CK_VOID_PTR ) keyID, keyIDlength }
1872  };
1873  CK_ATTRIBUTE keyTemplate[] = {
1874  { CKA_CLASS, ( CK_VOID_PTR ) &pubkeyClass, sizeof( CK_OBJECT_CLASS ) },
1875  { CKA_LABEL, ( CK_VOID_PTR ) keyID, keyIDlength }
1876  };
1877  CK_OBJECT_HANDLE hPrivkey = CRYPT_ERROR, hCertificate = CRYPT_ERROR;
1878  CK_OBJECT_HANDLE hPubkey = CRYPT_ERROR;
1879  CK_RV status;
1880  int cryptStatus;
1881 
1882  assert( itemType == KEYMGMT_ITEM_PUBLICKEY || \
1883  itemType == KEYMGMT_ITEM_PRIVATEKEY );
1884  assert( keyIDtype == CRYPT_KEYID_NAME );
1885  assert( keyIDlength > 0 && keyIDlength <= CRYPT_MAX_TEXTSIZE );
1886 
1887  /* Find the object to delete based on the label. Since we can have
1888  multiple related objects (e.g. a key and a certificate) with the same
1889  label, a straight search for all objects with a given label could
1890  return CRYPT_ERROR_DUPLICATE so we search for the objects by type as
1891  well as label. In addition even a search for specific objects can
1892  return CRYPT_ERROR_DUPLICATE so we use the Ex version of findObject()
1893  to make sure we don't get an error if multiple objects exist.
1894  Although cryptlib won't allow more than one object with a given label
1895  to be created, other applications might create duplicate labels. The
1896  correct behaviour in these circumstances is uncertain, what we do for
1897  now is delete the first object we find that matches the label.
1898 
1899  First we try for a certificate and use that to find associated keys */
1900  cryptStatus = findObjectEx( deviceInfo, &hCertificate, certTemplate, 3 );
1901  if( cryptStatusOK( cryptStatus ) )
1902  {
1903  /* We got a certificate, if there are associated keys delete them as
1904  well */
1905  cryptStatus = findObjectFromObject( deviceInfo, hCertificate,
1906  CKO_PUBLIC_KEY, &hPubkey );
1907  if( cryptStatusError( cryptStatus ) )
1908  hPubkey = CRYPT_ERROR;
1909  cryptStatus = findObjectFromObject( deviceInfo, hCertificate,
1910  CKO_PRIVATE_KEY, &hPrivkey );
1911  if( cryptStatusError( cryptStatus ) )
1912  hPrivkey = CRYPT_ERROR;
1913  }
1914  else
1915  {
1916  /* We didn't find a certificate with the given label, try for public
1917  and private keys */
1918  cryptStatus = findObjectEx( deviceInfo, &hPubkey, keyTemplate, 2 );
1919  if( cryptStatusError( cryptStatus ) )
1920  hPubkey = CRYPT_ERROR;
1921  keyTemplate[ 0 ].pValue = ( CK_VOID_PTR ) &privkeyClass;
1922  cryptStatus = findObjectEx( deviceInfo, &hPrivkey, keyTemplate, 2 );
1923  if( cryptStatusError( cryptStatus ) )
1924  hPrivkey = CRYPT_ERROR;
1925 
1926  /* There may be an unlabelled certificate present, try and find it by
1927  looking for a certificate matching the key ID */
1928  if( hPubkey != CRYPT_ERROR || hPrivkey != CRYPT_ERROR )
1929  {
1930  cryptStatus = findObjectFromObject( deviceInfo,
1931  ( hPrivkey != CRYPT_ERROR ) ? hPrivkey : hPubkey,
1932  CKO_CERTIFICATE, &hCertificate );
1933  if( cryptStatusError( cryptStatus ) )
1934  hCertificate = CRYPT_ERROR;
1935  }
1936  }
1937 
1938  /* If we found a public key with a given label but no private key, try
1939  and find a matching private key by ID, and vice versa */
1940  if( hPubkey != CRYPT_ERROR && hPrivkey == CRYPT_ERROR )
1941  {
1942  cryptStatus = findObjectFromObject( deviceInfo, hPubkey,
1943  CKO_PRIVATE_KEY, &hPrivkey );
1944  if( cryptStatusError( cryptStatus ) )
1945  hPrivkey = CRYPT_ERROR;
1946  }
1947  if( hPrivkey != CRYPT_ERROR && hPubkey == CRYPT_ERROR )
1948  {
1949  cryptStatus = findObjectFromObject( deviceInfo, hPrivkey,
1950  CKO_PUBLIC_KEY, &hPubkey );
1951  if( cryptStatusError( cryptStatus ) )
1952  hPubkey = CRYPT_ERROR;
1953  }
1954  if( hPrivkey == CRYPT_ERROR && hPubkey == CRYPT_ERROR )
1955  return( CRYPT_ERROR_NOTFOUND );
1956 
1957  /* Reset the status values, which may contain error values due to not
1958  finding various objects to delete above */
1959  cryptStatus = CRYPT_OK;
1960  status = CKR_OK;
1961 
1962  /* Delete the objects */
1963  if( hCertificate != CRYPT_ERROR )
1964  status = C_DestroyObject( cryptoapiInfo->hProv, hCertificate );
1965  if( hPubkey != CRYPT_ERROR )
1966  {
1967  int status2;
1968 
1969  status2 = C_DestroyObject( cryptoapiInfo->hProv, hPubkey );
1970  if( status2 != CKR_OK && status == CKR_OK )
1971  status = status2;
1972  }
1973  if( hPrivkey != CRYPT_ERROR )
1974  {
1975  int status2;
1976 
1977  status2 = C_DestroyObject( cryptoapiInfo->hProv, hPrivkey );
1978  if( status2 != CKR_OK && status == CKR_OK )
1979  status = status2;
1980  }
1981  if( status != CKR_OK )
1982  cryptStatus = mapError( deviceInfo, status, CRYPT_ERROR_FAILED );
1983  return( cryptStatus );
1984 #endif
1985 
1986  return( CRYPT_ERROR );
1987  }
1988 
1989 /* Get the sequence of certificates in a chain from a device. Unfortunately
1990  we can't really make the certificate chain fetch stateless without re-
1991  doing the read of the entire chain from the CryptoAPI certificate store
1992  for each fetch. To avoid this performance hit we cache the chain in the
1993  device information and pick out each certificate in turn during the
1994  findNext */
1995 
1996 static int getFirstItemFunction( DEVICE_INFO *deviceInfo,
1998  int *stateInfo,
1999  const CRYPT_KEYID_TYPE keyIDtype,
2000  const void *keyID, const int keyIDlength,
2001  const KEYMGMT_ITEM_TYPE itemType,
2002  const int options )
2003  {
2004  CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
2005  PCCERT_CONTEXT pCertContext;
2006  PCCERT_CHAIN_CONTEXT pChainContext;
2007  MESSAGE_CREATEOBJECT_INFO createInfo;
2008  int status;
2009 
2010  assert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
2011  assert( keyIDtype == CRYPT_IKEYID_KEYID );
2012  assert( isReadPtr( keyID, keyIDlength ) );
2013  assert( keyIDlength > 4 && keyIDlength < MAX_INTLENGTH_SHORT );
2014  assert( isWritePtr( stateInfo, sizeof( int ) ) );
2015  assert( itemType == KEYMGMT_ITEM_PUBLICKEY );
2016 
2017  /* Clear return values */
2018  *iCertificate = CRYPT_ERROR;
2019  *stateInfo = CRYPT_ERROR;
2020  cryptoapiInfo->hCertChain = NULL;
2021 
2022  /* Try and find the certificate with the given ID. This should work
2023  because we've just read the ID for the indirect-import that lead to
2024  the getFirst call */
2025  status = getCertificate( cryptoapiInfo, keyIDtype, keyID, keyIDlength,
2026  &pCertContext );
2027  if( cryptStatusError( status ) )
2028  {
2029  DEBUG_DIAG(( "Failed to load CryptoAPI certificate data" ));
2030  assert( DEBUG_WARN );
2031  return( status );
2032  }
2033 
2034  /* Now try and get the chain from the certificate. If this fails, we
2035  just use the standalone certificate */
2036  status = getCertificateChain( cryptoapiInfo, pCertContext,
2037  &pChainContext );
2038  if( cryptStatusOK( status ) )
2039  cryptoapiInfo->hCertChain = pChainContext;
2040 
2041  /* Import the leaf certificate as a cryptlib object */
2042  setMessageCreateObjectIndirectInfo( &createInfo,
2043  pCertContext->pbCertEncoded,
2044  pCertContext->cbCertEncoded,
2046  createInfo.arg1 = CRYPT_CERTTYPE_CERTIFICATE;
2049  &createInfo, OBJECT_TYPE_CERTIFICATE );
2050  pCertFreeCertificateContext( pCertContext );
2051  if( cryptStatusError( status ) )
2052  {
2053  if( cryptoapiInfo->hCertChain != NULL )
2054  pCertFreeCertificateChain( cryptoapiInfo->hCertChain );
2055  return( status );
2056  }
2057 
2058  /* Remember that we've got the leaf certificate in the chain */
2059  assert( pChainContext->cChain == 1 );
2060  *stateInfo = 1;
2061  return( CRYPT_OK );
2062  }
2063 
2064 static int getNextItemFunction( DEVICE_INFO *deviceInfo,
2065  CRYPT_CERTIFICATE *iCertificate,
2066  int *stateInfo, const int options )
2067  {
2068  CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
2069  PCCERT_CHAIN_CONTEXT pChainContext = cryptoapiInfo->hCertChain;
2070  PCERT_SIMPLE_CHAIN pCertSimpleChain;
2071  PCERT_CHAIN_ELEMENT pCertChainElement;
2072  MESSAGE_CREATEOBJECT_INFO createInfo;
2073  int status;
2074 
2075  assert( isWritePtr( iCertificate, sizeof( CRYPT_CERTIFICATE ) ) );
2076  assert( isWritePtr( stateInfo, sizeof( int ) ) );
2077  assert( *stateInfo == CRYPT_ERROR || *stateInfo >= 1 );
2078 
2079  /* Clear return value */
2080  *iCertificate = CRYPT_ERROR;
2081 
2082  /* If the previous certificate was the last one, there's nothing left to
2083  fetch */
2084  if( cryptoapiInfo->hCertChain == NULL )
2085  {
2086  *stateInfo = CRYPT_ERROR;
2087  return( CRYPT_ERROR_NOTFOUND );
2088  }
2089  pCertSimpleChain = pChainContext->rgpChain[ 0 ];
2090  if( *stateInfo < 1 || *stateInfo > pCertSimpleChain->cElement )
2091  {
2092  pCertFreeCertificateChain( cryptoapiInfo->hCertChain );
2093  cryptoapiInfo->hCertChain = NULL;
2094  *stateInfo = CRYPT_ERROR;
2095  return( CRYPT_ERROR_NOTFOUND );
2096  }
2097 
2098  /* Get the next certificate in the chain */
2099  pCertChainElement = pCertSimpleChain->rgpElement[ *stateInfo ];
2100  setMessageCreateObjectIndirectInfo( &createInfo,
2101  pCertChainElement->pCertContext->pbCertEncoded,
2102  pCertChainElement->pCertContext->cbCertEncoded,
2104  createInfo.arg1 = CRYPT_CERTTYPE_CERTIFICATE;
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 
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 
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 ];
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,
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 
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 
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 
2342 static int rsaSign( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )
2343  {
2344  CRYPT_DEVICE iCryptDevice;
2345  CRYPTOAPI_INFO *cryptoapiInfo;
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 
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 
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 
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 = length;
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  {
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,
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, 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 */
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 
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 
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;
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 */
2708  cryptStatus = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
2709  IMESSAGE_DEV_CREATEOBJECT, &createInfo,
2711  if( cryptStatusError( cryptStatus ) )
2712  return( cryptStatus );
2713  setMessageData( &msgData, label, 8 );
2715  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
2717  &msgData, CRYPT_CTXINFO_LABEL );
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  }
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 );
2748  readGenericHole( &stream, &length ); /* q */
2749  publicKeyTemplate[ 4 ].pValue = sMemBufPtr( &stream );
2750  publicKeyTemplate[ 4 ].ulValueLen = length;
2751  sSkip( &stream, length );
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 
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 
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 
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 
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_OFB,
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_OFB == 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  case CRYPT_MODE_OFB:
3003  dwMode = CAPI_CRYPT_MODE_OFB;
3004  break;
3005  default:
3006  retIntError();
3007  }
3008 
3009  /* Set the mode parameter for the CryptoAPI object */
3010  if( !CryptSetKeyParam( contextInfoPtr->deviceObject, KP_MODE,
3011  ( BYTE * ) &dwMode, 0 ) )
3012  return( mapDeviceError( contextInfoPtr, CRYPT_ERROR_NOTAVAIL ) );
3013  if( mode == CRYPT_MODE_CFB || mode == CRYPT_MODE_OFB )
3014  {
3015  const DWORD dwModeBits = contextInfoPtr->capabilityInfo->blockSize * 8;
3016 
3017  /* CryptoAPI defaults to 8-bit feedback for CFB and OFB (!!) so we
3018  have to fix the feedback amount if we're using a stream mode */
3019  if( !CryptSetKeyParam( contextInfoPtr->deviceObject, KP_MODE_BITS,
3020  ( BYTE * ) &dwModeBits, 0 ) )
3021  return( mapDeviceError( contextInfoPtr, CRYPT_ERROR_NOTAVAIL ) );
3022  }
3023 
3024  /* If there's no IV present, we're done */
3025  if( mode == CRYPT_MODE_ECB )
3026  return( CRYPT_OK );
3027 
3028  /* Set the IV parameter for the CryptoAPI object */
3029  if( !CryptSetKeyParam( contextInfoPtr->deviceObject, KP_IV,
3030  contextInfoPtr->ctxConv->currentIV, 0 ) )
3031  return( mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED ) );
3032 
3033  return( CRYPT_OK );
3034  }
3035 
3036 /* En/decrypt/hash data */
3037 
3038 static int cipherEncrypt( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )
3039  {
3040  DWORD resultLength = length;
3041 
3042  /* Finalise the encryption parameters if necessary. We couldn't do this
3043  earlier because the device-level object isn't instantiated until the
3044  key is loaded */
3045  if( !( contextInfoPtr->flags & CONTEXT_FLAG_DUMMY_INITED ) )
3046  {
3047  int status;
3048 
3049  status = initCryptParams( contextInfoPtr );
3050  if( cryptStatusError( status ) )
3051  return( status );
3052  contextInfoPtr->flags |= CONTEXT_FLAG_DUMMY_INITED;
3053  }
3054 
3055  /* Encrypt the data. We always set the bFinal flag to FALSE since
3056  setting it to TRUE tries to apply message padding, resets the IV, and
3057  various other unwanted side-effects */
3058  if( !pCryptEncrypt( contextInfoPtr->deviceObject, 0, FALSE, 0, buffer,
3059  &resultLength, length ) )
3060  return( mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED ) );
3061  return( CRYPT_OK );
3062  }
3063 
3064 static int cipherDecrypt( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )
3065  {
3066  DWORD resultLength = length;
3067 
3068  /* Finalise the encryption parameters if necessary. We couldn't do this
3069  earlier because the device-level object isn't instantiated until the
3070  key is loaded */
3071  if( !( contextInfoPtr->flags & CONTEXT_FLAG_DUMMY_INITED ) )
3072  {
3073  int status;
3074 
3075  status = initCryptParams( contextInfoPtr );
3076  if( cryptStatusError( status ) )
3077  return( status );
3078  contextInfoPtr->flags |= CONTEXT_FLAG_DUMMY_INITED;
3079  }
3080 
3081  /* Decrypt the data. We always set the bFinal flag to FALSE since
3082  setting it to TRUE tries to process message padding, resets the IV,
3083  and various other unwanted side-effects */
3084  if( !pCryptDecrypt( contextInfoPtr->deviceObject, 0, FALSE, 0, buffer,
3085  &resultLength ) )
3086  return( mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED ) );
3087  return( CRYPT_OK );
3088  }
3089 
3090 #if 0 /* Not used, see the comment in the capability information */
3091 
3092 static int hashFunction( CONTEXT_INFO *contextInfoPtr, void *buffer, int length )
3093  {
3094  if( !pCryptHashData( contextInfoPtr->deviceObject, buffer, length, 0 ) )
3095  return( mapDeviceError( contextInfoPtr, CRYPT_ERROR_FAILED ) );
3096  return( CRYPT_OK );
3097  }
3098 #endif /* 0 */
3099 
3100 /****************************************************************************
3101 * *
3102 * Device Capability Routines *
3103 * *
3104 ****************************************************************************/
3105 
3106 /* Templates for the various capabilities. These contain only basic
3107  information, the remaining fields are filled in when the capability is
3108  set up */
3109 
3110 static CAPABILITY_INFO FAR_BSS capabilityTemplates[] = {
3111  /* Encryption capabilities */
3112  { CRYPT_ALGO_DES, bitsToBytes( 64 ), "DES", 3,
3113  bitsToBytes( 40 ), bitsToBytes( 64 ), bitsToBytes( 64 ) },
3114  { CRYPT_ALGO_3DES, bitsToBytes( 64 ), "3DES", 4,
3115  bitsToBytes( 64 + 8 ), bitsToBytes( 128 ), bitsToBytes( 192 ) },
3116  { CRYPT_ALGO_RC2, bitsToBytes( 64 ), "RC2", 3,
3117  bitsToBytes( 40 ), bitsToBytes( 128 ), bitsToBytes( 1024 ) },
3118  { CRYPT_ALGO_RC4, bitsToBytes( 8 ), "RC4", 3,
3119  bitsToBytes( 40 ), bitsToBytes( 128 ), 256 },
3120  { CRYPT_ALGO_RC5, bitsToBytes( 64 ), "RC5", 3,
3121  bitsToBytes( 40 ), bitsToBytes( 128 ), bitsToBytes( 832 ) },
3122  { CRYPT_ALGO_AES, bitsToBytes( 128 ), "AES", 3,
3123  bitsToBytes( 128 ), bitsToBytes( 128 ), bitsToBytes( 256 ) },
3124 
3125  /* Hash capabilities */
3126  { CRYPT_ALGO_MD5, bitsToBytes( 128 ), "MD5", 3,
3127  bitsToBytes( 0 ), bitsToBytes( 0 ), bitsToBytes( 0 ) },
3128  { CRYPT_ALGO_SHA1, bitsToBytes( 160 ), "SHA1", 3,
3129  bitsToBytes( 0 ), bitsToBytes( 0 ), bitsToBytes( 0 ) },
3130  { CRYPT_ALGO_RIPEMD160, bitsToBytes( 160 ), "RIPEMD-160", 10,
3131  bitsToBytes( 0 ), bitsToBytes( 0 ), bitsToBytes( 0 ) },
3132 
3133  /* Public-key capabilities */
3134  { CRYPT_ALGO_RSA, bitsToBytes( 0 ), "RSA", 3,
3135  bitsToBytes( 512 ), bitsToBytes( 1024 ), CRYPT_MAX_PKCSIZE },
3136  { CRYPT_ALGO_DSA, bitsToBytes( 0 ), "DSA", 3,
3137  bitsToBytes( 512 ), bitsToBytes( 1024 ), CRYPT_MAX_PKCSIZE },
3138 
3139  /* Hier ist der Mast zu ende */
3140  { CRYPT_ERROR }, { CRYPT_ERROR }
3141  };
3142 
3143 /* Mapping of CryptoAPI provider capabilities to cryptlib capabilities */
3144 
3145 typedef struct {
3146  /* Mapping information from CryptoAPI to cryptlib algorithms. For some
3147  PKC algorithms CryptoAPI creates two virtual algorithm types (badly,
3148  it's easily confused between the two), one for signing and one for
3149  encryption. The first algorithm type is always the one with
3150  encryption capability, if there's one with signature capability or
3151  it's a signature-only algorithm we specify it as the optional
3152  alternative algorithm type */
3153  const ALG_ID algoID; /* CryptoAPI algorithm type */
3154  const ALG_ID altAlgoID; /* CryptoAPI alt.algorithm type */
3155  const CRYPT_ALGO_TYPE cryptAlgo; /* cryptlib algo and mode */
3156  const CRYPT_MODE_TYPE cryptMode;
3157 
3158  /* Function pointers */
3159  int ( *endFunction )( CONTEXT_INFO *contextInfoPtr );
3160  int ( *initKeyFunction )( CONTEXT_INFO *contextInfoPtr, const void *key, const int keyLength );
3161  int ( *generateKeyFunction )( CONTEXT_INFO *contextInfoPtr, const int keySizeBits );
3162  int ( *encryptFunction )( CONTEXT_INFO *contextInfoPtr, void *buffer, int length );
3163  int ( *decryptFunction )( CONTEXT_INFO *contextInfoPtr, void *buffer, int length );
3164  int ( *signFunction )( CONTEXT_INFO *contextInfoPtr, void *buffer, int length );
3165  int ( *sigCheckFunction )( CONTEXT_INFO *contextInfoPtr, void *buffer, int length );
3166  } MECHANISM_INFO;
3167 
3168 static const MECHANISM_INFO mechanismInfo[] = {
3169  { CALG_RSA_KEYX, CALG_RSA_SIGN, CRYPT_ALGO_RSA, CRYPT_MODE_NONE,
3170  NULL, rsaInitKey, rsaGenerateKey,
3171  rsaEncrypt, rsaDecrypt, rsaSign, rsaVerify },
3172  { CALG_NONE, CALG_DSS_SIGN, CRYPT_ALGO_DSA, CRYPT_MODE_NONE,
3173  NULL, dsaInitKey, dsaGenerateKey,
3174  NULL, NULL, dsaSign, dsaVerify },
3175  { CALG_DES, CALG_NONE, CRYPT_ALGO_DES, CRYPT_MODE_ECB,
3176  genericEndFunction, cipherInitKey, NULL,
3177  cipherEncrypt, cipherDecrypt, NULL, NULL },
3178  { CALG_DES, CALG_NONE, CRYPT_ALGO_DES, CRYPT_MODE_CBC,
3179  genericEndFunction, cipherInitKey, NULL,
3180  cipherEncrypt, cipherDecrypt, NULL, NULL },
3181  { CALG_3DES, CALG_NONE, CRYPT_ALGO_3DES, CRYPT_MODE_ECB,
3182  genericEndFunction, cipherInitKey, NULL,
3183  cipherEncrypt, cipherDecrypt, NULL, NULL },
3184  { CALG_3DES, CALG_NONE, CRYPT_ALGO_3DES, CRYPT_MODE_CBC,
3185  genericEndFunction, cipherInitKey, NULL,
3186  cipherEncrypt, cipherDecrypt, NULL, NULL },
3187  { CALG_RC2, CALG_NONE, CRYPT_ALGO_RC2, CRYPT_MODE_ECB,
3188  genericEndFunction, cipherInitKey, NULL,
3189  cipherEncrypt, cipherDecrypt, NULL, NULL },
3190  { CALG_RC2, CALG_NONE, CRYPT_ALGO_RC2, CRYPT_MODE_CBC,
3191  genericEndFunction, cipherInitKey, NULL,
3192  cipherEncrypt, cipherDecrypt, NULL, NULL },
3193  { CALG_RC4, CALG_NONE, CRYPT_ALGO_RC4, CRYPT_MODE_OFB,
3194  genericEndFunction, cipherInitKey, NULL,
3195  cipherEncrypt, cipherDecrypt, NULL, NULL },
3196 #if 0 /* Although CAPI supports the hash mechanisms, as with PKCS #11
3197  we always use cryptlib native contexts for this */
3198  { CALG_MD5, CALG_NONE, CRYPT_ALGO_MD5, CRYPT_MODE_NONE,
3199  genericEndFunction, NULL, NULL,
3200  hashFunction, hashFunction, NULL, NULL },
3201  { CALG_SHA1, CALG_NONE, CRYPT_ALGO_SHA1, CRYPT_MODE_NONE,
3202  genericEndFunction, NULL, NULL,
3203  hashFunction, hashFunction, NULL, NULL },
3204 #endif /* 0 */
3205  { CALG_NONE, CALG_NONE, CRYPT_ALGO_NONE, CRYPT_MODE_NONE },
3206  { CALG_NONE, CALG_NONE, CRYPT_ALGO_NONE, CRYPT_MODE_NONE }
3207  };
3208 
3209 /* Fill out a capability information based on CryptoAPI algorithm
3210  information */
3211 
3212 static CAPABILITY_INFO *addCapability( const DEVICE_INFO *deviceInfo,
3213  const PROV_ENUMALGS_EX *capiAlgoInfo,
3214  const MECHANISM_INFO *mechanismInfoPtr,
3215  const CAPABILITY_INFO *existingCapabilityInfo )
3216  {
3217  VARIABLE_CAPABILITY_INFO *capabilityInfo = \
3218  ( VARIABLE_CAPABILITY_INFO * ) existingCapabilityInfo;
3219  int i;
3220 
3221  /* If it's a new capability, copy across the template for this
3222  capability */
3223  if( capabilityInfo == NULL )
3224  {
3225  if( ( capabilityInfo = \
3226  clAlloc( "addCapability", sizeof( CAPABILITY_INFO ) ) ) == NULL )
3227  return( NULL );
3228  for( i = 0;
3229  capabilityTemplates[ i ].cryptAlgo != mechanismInfoPtr->cryptAlgo && \
3230  capabilityTemplates[ i ].cryptAlgo != CRYPT_ALGO_NONE && \
3231  i < FAILSAFE_ARRAYSIZE( capabilityTemplates, CAPABILITY_INFO ); \
3232  i++ );
3233  if( i >= FAILSAFE_ARRAYSIZE( capabilityTemplates, CAPABILITY_INFO ) )
3234  retIntError_Null();
3235  assert( i < sizeof( capabilityTemplates ) / sizeof( CAPABILITY_INFO ) && \
3236  capabilityTemplates[ i ].cryptAlgo != CRYPT_ALGO_NONE );
3237  memcpy( capabilityInfo, &capabilityTemplates[ i ],
3238  sizeof( CAPABILITY_INFO ) );
3239  }
3240 
3241  /* Set up the keysize information, limiting the maximum key size to
3242  match the cryptlib native max.key size, both for consistency and
3243  because cryptlib performs buffer allocation based on the maximum
3244  native buffer size. Since CryptoAPI specifies key sizes for unkeyed
3245  hash algorithms, we only set the keysize if there's really a key
3246  present. In addition it indicates the number of bits involved in
3247  keying rather than the nominal key size, so we have to adjust the
3248  reported size to match the conventionally-used value */
3249  if( capabilityInfo->keySize > 0 )
3250  {
3251  int minKeySize = bitsToBytes( capiAlgoInfo->dwMinLen );
3252  int maxKeySize = bitsToBytes( capiAlgoInfo->dwMaxLen );
3253 
3254  if( mechanismInfoPtr->cryptAlgo == CRYPT_ALGO_DES && \
3255  minKeySize == 7 )
3256  {
3257  /* Adjust 56 bits -> 8 bytes */
3258  minKeySize = maxKeySize = 8;
3259  }
3260  if( mechanismInfoPtr->cryptAlgo == CRYPT_ALGO_3DES && \
3261  minKeySize == 21 )
3262  {
3263  /* Adjust 168 bits -> 24 bytes */
3264  minKeySize = maxKeySize = 24;
3265  }
3266  if( minKeySize > capabilityInfo->minKeySize )
3267  capabilityInfo->minKeySize = minKeySize;
3268  if( capabilityInfo->keySize < capabilityInfo->minKeySize )
3269  capabilityInfo->keySize = capabilityInfo->minKeySize;
3270  capabilityInfo->maxKeySize = min( maxKeySize,
3271  capabilityInfo->maxKeySize );
3272  if( capabilityInfo->keySize > capabilityInfo->maxKeySize )
3273  capabilityInfo->keySize = capabilityInfo->maxKeySize;
3274  capabilityInfo->endFunction = genericEndFunction;
3275  }
3276 
3277  /* Set up the device-specific handlers */
3278  capabilityInfo->getInfoFunction = getDefaultInfo;
3279  if( mechanismInfoPtr->cryptAlgo != CRYPT_ALGO_RSA && \
3280  mechanismInfoPtr->cryptAlgo != CRYPT_ALGO_DSA )
3281  capabilityInfo->initParamsFunction = initGenericParams;
3282  capabilityInfo->endFunction = mechanismInfoPtr->endFunction;
3283  capabilityInfo->initKeyFunction = mechanismInfoPtr->initKeyFunction;
3284  capabilityInfo->generateKeyFunction = mechanismInfoPtr->generateKeyFunction;
3285  if( mechanismInfoPtr->algoID == capiAlgoInfo->aiAlgid )
3286  {
3287  if( mechanismInfoPtr->cryptMode == CRYPT_MODE_OFB )
3288  {
3289  /* Stream ciphers have an implicit mode of OFB */
3290  capabilityInfo->encryptOFBFunction = mechanismInfoPtr->encryptFunction;
3291  }
3292  else
3293  capabilityInfo->encryptFunction = mechanismInfoPtr->encryptFunction;
3294  if( mechanismInfoPtr->cryptMode == CRYPT_MODE_OFB )
3295  {
3296  /* Stream ciphers have an implicit mode of OFB */
3297  capabilityInfo->decryptOFBFunction = mechanismInfoPtr->decryptFunction;
3298  }
3299  else
3300  capabilityInfo->decryptFunction = mechanismInfoPtr->decryptFunction;
3301  if( mechanismInfoPtr->cryptMode != CRYPT_MODE_NONE && \
3302  mechanismInfoPtr->cryptMode != CRYPT_MODE_OFB )
3303  {
3304  capabilityInfo->encryptCBCFunction = \
3305  mechanismInfoPtr->encryptFunction;
3306  capabilityInfo->decryptCBCFunction = \
3307  mechanismInfoPtr->decryptFunction;
3308 #if 0 /* CAPI requires the encryption of full blocks even in a stream
3309  cipher mode, which doesn't match the standard cryptlib
3310  behaviour. To avoid this problem, we mark the stream cipher
3311  modes as not available */
3312  capabilityInfo->encryptCFBFunction = \
3313  mechanismInfoPtr->encryptFunction;
3314  capabilityInfo->decryptCFBFunction = \
3315  mechanismInfoPtr->decryptFunction;
3316  capabilityInfo->encryptOFBFunction = \
3317  mechanismInfoPtr->encryptFunction;
3318  capabilityInfo->decryptOFBFunction = \
3319  mechanismInfoPtr->decryptFunction;
3320 #endif /* 0 */
3321  }
3322  }
3323  if( mechanismInfoPtr->altAlgoID == capiAlgoInfo->aiAlgid )
3324  {
3325  capabilityInfo->signFunction = mechanismInfoPtr->signFunction;
3326  capabilityInfo->sigCheckFunction = mechanismInfoPtr->sigCheckFunction;
3327  }
3328 
3329  return( ( CAPABILITY_INFO * ) capabilityInfo );
3330  }
3331 
3332 /* Set the capability information based on device capabilities. Since
3333  CryptoAPI devices can have assorted capabilities, we have to build this
3334  up on the fly rather than using a fixed table like the built-in
3335  capabilities */
3336 
3337 static void freeCapabilities( DEVICE_INFO *deviceInfo )
3338  {
3339  CAPABILITY_INFO_LIST *capabilityInfoListPtr = \
3340  ( CAPABILITY_INFO_LIST * ) deviceInfo->capabilityInfoList;
3341 
3342  /* If the list was empty, return now */
3343  if( capabilityInfoListPtr == NULL )
3344  return;
3345  deviceInfo->capabilityInfoList = NULL;
3346 
3347  while( capabilityInfoListPtr != NULL )
3348  {
3349  CAPABILITY_INFO_LIST *listItemToFree = capabilityInfoListPtr;
3350  CAPABILITY_INFO *itemToFree = ( CAPABILITY_INFO * ) listItemToFree->info;
3351 
3352  capabilityInfoListPtr = capabilityInfoListPtr->next;
3353  zeroise( itemToFree, sizeof( CAPABILITY_INFO ) );
3354  clFree( "freeCapabilities", itemToFree );
3355  zeroise( listItemToFree, sizeof( CAPABILITY_INFO_LIST ) );
3356  clFree( "freeCapabilities", listItemToFree );
3357  }
3358  }
3359 
3360 static int getCapabilities( DEVICE_INFO *deviceInfo )
3361  {
3362  CRYPTOAPI_INFO *cryptoapiInfo = deviceInfo->deviceCryptoAPI;
3363  CAPABILITY_INFO_LIST *capabilityInfoListTail = \
3364  ( CAPABILITY_INFO_LIST * ) deviceInfo->capabilityInfoList;
3365  PROV_ENUMALGS_EX capiAlgoInfo;
3366  DWORD length = sizeof( PROV_ENUMALGS_EX );
3367  int iterationCount = 0;
3368 
3369  assert( sizeof( CAPABILITY_INFO ) == sizeof( VARIABLE_CAPABILITY_INFO ) );
3370 
3371  /* Step through each available CryptoAPI algorithm type adding the
3372  appropriate cryptlib capability for it */
3373  if( !pCryptGetProvParam( cryptoapiInfo->hProv, PP_ENUMALGS_EX,
3374  ( BYTE * ) &capiAlgoInfo, &length, CRYPT_FIRST ) )
3375  return( CRYPT_ERROR );
3376  do
3377  {
3378  CAPABILITY_INFO_LIST *newCapabilityList, *capabilityInfoListPtr;
3379  CAPABILITY_INFO *newCapability;
3381  int i;
3382 
3383  /* Check whether this algorithm type corresponds to a cryptlib
3384  capability */
3385  for( i = 0; mechanismInfo[ i ].cryptAlgo != CRYPT_ALGO_NONE && \
3386  i < FAILSAFE_ARRAYSIZE( mechanismInfo, MECHANISM_INFO );
3387  i++ )
3388  {
3389  if( mechanismInfo[ i ].algoID == capiAlgoInfo.aiAlgid || \
3390  ( mechanismInfo[ i ].altAlgoID != CALG_NONE && \
3391  mechanismInfo[ i ].altAlgoID == capiAlgoInfo.aiAlgid ) )
3392  break;
3393  }
3394  if( i >= FAILSAFE_ARRAYSIZE( mechanismInfo, MECHANISM_INFO ) )
3395  retIntError();
3396  if( mechanismInfo[ i ].cryptAlgo == CRYPT_ALGO_NONE )
3397  continue;
3398  cryptAlgo = mechanismInfo[ i ].cryptAlgo;
3399 
3400  /* Check whether this is a variation of an existing capability */
3401  for( capabilityInfoListPtr = ( CAPABILITY_INFO_LIST * ) \
3402  deviceInfo->capabilityInfoList;
3403  capabilityInfoListPtr != NULL && \
3404  capabilityInfoListPtr->info->cryptAlgo != cryptAlgo;
3405  capabilityInfoListPtr = capabilityInfoListPtr->next );
3406  if( capabilityInfoListPtr != NULL )
3407  {
3408  addCapability( deviceInfo, &capiAlgoInfo, &mechanismInfo[ i ],
3409  capabilityInfoListPtr->info );
3410  continue;
3411  }
3412 
3413  /* Add capabilities for all mechanisms corresponding to the current
3414  CryptoAPI algorithm type. If the assertion below triggers then
3415  the CryptoAPI provider is broken since it's returning
3416  inconsistent information such as illegal key length data,
3417  conflicting algorithm information, etc etc. This assertion is
3418  included here to detect buggy drivers early on rather than
3419  forcing users to step through the CryptoAPI glue code to find out
3420  why an operation is failing.
3421 
3422  Because some providers mapped down to tinkertoy smart cards
3423  support only the bare minimum functionality (e.g.RSA private key
3424  ops and nothing else), we allow asymmetric functionality for
3425  PKCs */
3426  newCapability = addCapability( deviceInfo, &capiAlgoInfo,
3427  &mechanismInfo[ i ], NULL );
3428  if( newCapability == NULL )
3429  break;
3430  REQUIRES( sanityCheckCapability( newCapability,
3431  isPkcAlgo( newCapability->cryptAlgo ) ? \
3432  TRUE : FALSE ) );
3433  if( ( newCapabilityList = \
3434  clAlloc( "getCapabilities", \
3435  sizeof( CAPABILITY_INFO_LIST ) ) ) == NULL )
3436  {
3437  clFree( "getCapabilities", newCapability );
3438  continue;
3439  }
3440  newCapabilityList->info = newCapability;
3441  newCapabilityList->next = NULL;
3442  if( deviceInfo->capabilityInfoList == NULL )
3443  deviceInfo->capabilityInfoList = newCapabilityList;
3444  else
3445  capabilityInfoListTail->next = newCapabilityList;
3446  capabilityInfoListTail = newCapabilityList;
3447  }
3448  while( pCryptGetProvParam( cryptoapiInfo->hProv, PP_ENUMALGS_EX,
3449  ( BYTE * ) &capiAlgoInfo, &length, 0 ) && \
3450  iterationCount++ < FAILSAFE_ITERATIONS_LARGE );
3451  if( iterationCount >= FAILSAFE_ITERATIONS_LARGE )
3452  retIntError();
3453 
3454  return( ( deviceInfo->capabilityInfoList == NULL ) ? CRYPT_ERROR : CRYPT_OK );
3455  }
3456 
3457 /****************************************************************************
3458 * *
3459 * Device Access Routines *
3460 * *
3461 ****************************************************************************/
3462 
3463 /* Mechanisms supported by CryptoAPI devices. These are actually cryptlib
3464  native mechanisms since many aren't supported by CryptoAPI, but not the
3465  full set supported by the system device since functions like private key
3466  export aren't available except in the nonstandard blob format invented
3467  by Microsoft. The list is sorted in order of frequency of use in order
3468  to make lookups a bit faster */
3469 
3470 static const FAR_BSS MECHANISM_FUNCTION_INFO mechanismFunctions[] = {
3471  { MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1, ( MECHANISM_FUNCTION ) exportPKCS1 },
3472  { MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1, ( MECHANISM_FUNCTION ) importPKCS1 },
3473  { MESSAGE_DEV_SIGN, MECHANISM_SIG_PKCS1, ( MECHANISM_FUNCTION ) signPKCS1 },
3474  { MESSAGE_DEV_SIGCHECK, MECHANISM_SIG_PKCS1, ( MECHANISM_FUNCTION ) sigcheckPKCS1 },
3475  { MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1_RAW, ( MECHANISM_FUNCTION ) exportPKCS1 },
3476  { MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1_RAW, ( MECHANISM_FUNCTION ) importPKCS1 },
3477 #ifdef USE_PGP
3478  { MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1_PGP, ( MECHANISM_FUNCTION ) exportPKCS1PGP },
3479  { MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1_PGP, ( MECHANISM_FUNCTION ) importPKCS1PGP },
3480 #endif /* USE_PGP */
3481  { MESSAGE_DEV_EXPORT, MECHANISM_ENC_CMS, ( MECHANISM_FUNCTION ) exportCMS },
3482  { MESSAGE_DEV_IMPORT, MECHANISM_ENC_CMS, ( MECHANISM_FUNCTION ) importCMS },
3483  { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PKCS5, ( MECHANISM_FUNCTION ) derivePKCS5 },
3484 #if defined( USE_PGP ) || defined( USE_PGPKEYS )
3485  { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PGP, ( MECHANISM_FUNCTION ) derivePGP },
3486 #endif /* USE_PGP || USE_PGPKEYS */
3487 #ifdef USE_SSL
3488  { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_SSL, ( MECHANISM_FUNCTION ) deriveSSL },
3489  { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_TLS, ( MECHANISM_FUNCTION ) deriveTLS },
3490  { MESSAGE_DEV_SIGN, MECHANISM_SIG_SSL, ( MECHANISM_FUNCTION ) signSSL },
3491  { MESSAGE_DEV_SIGCHECK, MECHANISM_SIG_SSL, ( MECHANISM_FUNCTION ) sigcheckSSL },
3492 #endif /* USE_SSL */
3493 #ifdef USE_CMP
3494  { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_CMP, ( MECHANISM_FUNCTION ) deriveCMP },
3495 #endif /* USE_CMP */
3496 #ifdef USE_PKCS12
3497  { MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PKCS12, ( MECHANISM_FUNCTION ) derivePKCS12 },
3498 #endif /* USE_PKCS12 */
3500  };
3501 
3502 /* Set up the function pointers to the device methods */
3503 
3504 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
3505 int setDeviceCryptoAPI( INOUT DEVICE_INFO *deviceInfo )
3506  {
3507  /* Make sure that the CryptoAPI driver DLL is loaded */
3508  if( hCryptoAPI == NULL_HINSTANCE )
3509  return( CRYPT_ERROR_OPEN );
3510 
3511  deviceInfo->initFunction = initFunction;
3512  deviceInfo->shutdownFunction = shutdownFunction;
3513  deviceInfo->controlFunction = controlFunction;
3514  deviceInfo->getItemFunction = getItemFunction;
3515  deviceInfo->setItemFunction = setItemFunction;
3516  deviceInfo->deleteItemFunction = deleteItemFunction;
3517  deviceInfo->getFirstItemFunction = getFirstItemFunction;
3518  deviceInfo->getNextItemFunction = getNextItemFunction;
3519  deviceInfo->getRandomFunction = getRandomFunction;
3520  deviceInfo->mechanismFunctions = mechanismFunctions;
3521  deviceInfo->mechanismFunctionCount = \
3522  FAILSAFE_ARRAYSIZE( mechanismFunctions, MECHANISM_FUNCTION_INFO );
3523 
3524  return( CRYPT_OK );
3525  }
3526 #endif /* USE_CRYPTOAPI */