summaryrefslogtreecommitdiff
path: root/src/classlibnative/cryptography/cryptography.h
blob: 0d9a1b6cb0522b8307968575c92d9e85f47e44f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
//

// 


#ifndef _CRYPTOGRAPHY_H_
#define _CRYPTOGRAPHY_H_

#include <wincrypt.h>

#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
#include "fcall.h"

class DSA_CSP_Object : public Object {
public:
    U1ARRAYREF   m_P;            // ubyte[]
    U1ARRAYREF   m_Q;            // ubyte[]
    U1ARRAYREF   m_G;            // ubyte[]
    U1ARRAYREF   m_Y;            // ubyte[] - optional
    U1ARRAYREF   m_J;            // ubyte[] - optional
    U1ARRAYREF   m_X;            // ubyte[] - optional - private key
    U1ARRAYREF   m_seed;         // ubyte[] - optional - paired with counter
    DWORD        m_counter;      // DWORD - optional
};

class RSA_CSP_Object : public Object {
public:
    U1ARRAYREF   m_Exponent;    // ubyte[]
    U1ARRAYREF   m_Modulus;     // ubyte[]
    U1ARRAYREF   m_P;           // ubyte[] - optional
    U1ARRAYREF   m_Q;           // ubyte[] - optional
    U1ARRAYREF   m_dp;          // ubyte[] - optional
    U1ARRAYREF   m_dq;          // ubyte[] - optional
    U1ARRAYREF   m_InverseQ;    // ubyte[] - optional
    U1ARRAYREF   m_d;           // ubyte[] - optional
};

#ifdef USE_CHECKED_OBJECTREFS
typedef REF<DSA_CSP_Object> DSA_CSPREF;
typedef REF<RSA_CSP_Object> RSA_CSPREF;
#else  // !_DEBUG
typedef DSA_CSP_Object * DSA_CSPREF;
typedef RSA_CSP_Object * RSA_CSPREF;
#endif // _DEBUG

#endif // #if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)

#define DSS_MAGIC           0x31535344
#define DSS_PRIVATE_MAGIC   0x32535344
#define DSS_PUB_MAGIC_VER3  0x33535344
#define DSS_PRIV_MAGIC_VER3 0x34535344
#define RSA_PUB_MAGIC       0x31415352
#define RSA_PRIV_MAGIC      0x32415352

#define DSS_Q_LEN 20

// Keep in sync with managed definition in System.Security.Cryptography.Utils
#define CLR_KEYLEN              1
#define CLR_PUBLICKEYONLY       2
#define CLR_EXPORTABLE          3
#define CLR_REMOVABLE           4
#define CLR_HARDWARE            5
#define CLR_ACCESSIBLE          6
#define CLR_PROTECTED           7
#define CLR_UNIQUE_CONTAINER    8
#define CLR_ALGID               9
#define CLR_PP_CLIENT_HWND      10
#define CLR_PP_PIN              11

#define MAX_CACHE_DEFAULT_PROVIDERS 20
// size of a symmetric key block size. 8 is the only supported for now
#define BLOCK_LEN 8
 
// Dependency in managed : System/Security/Cryptography/Crypto.cs
#define CRYPTO_PADDING_NONE         1
#define CRYPTO_PADDING_PKCS5        2
#define CRYPTO_PADDING_Zeros        3
#define CRYPTO_PADDING_ANSI_X_923   4
#define CRYPTO_PADDING_ISO_10126    5

// These flags match those defined for the CspProviderFlags enum in 
// src/bcl/system/security/cryptography/CryptoAPITransform.cs

#define CSP_PROVIDER_FLAGS_USE_MACHINE_KEYSTORE      0x0001
#define CSP_PROVIDER_FLAGS_USE_DEFAULT_KEY_CONTAINER 0x0002
#define CSP_PROVIDER_FLAGS_USE_NON_EXPORTABLE_KEY    0x0004
#define CSP_PROVIDER_FLAGS_USE_EXISTING_KEY          0x0008
#define CSP_PROVIDER_FLAGS_USE_ARCHIVABLE_KEY        0x0010
#define CSP_PROVIDER_FLAGS_USE_USER_PROTECTED_KEY    0x0020
#define CSP_PROVIDER_FLAGS_USE_CRYPT_SILENT          0x0040
#define CSP_PROVIDER_FLAGS_CREATE_EPHEMERAL_KEY      0x0080


#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO) || defined(FEATURE_X509)
class CryptoHelper {
public:
    static void COMPlusThrowCrypto (HRESULT hr);
    static BOOL WszCryptAcquireContext_SO_TOLERANT (HCRYPTPROV *phProv, LPCWSTR pwszContainer, LPCWSTR pwszProvider, DWORD dwProvType, DWORD dwFlags);    
    static WCHAR* STRINGREFToUnicode (STRINGREF s);
    static WCHAR* AnsiToUnicode (__in_z char* pszAnsi);
    static void ByteArrayToU1ARRAYREF (LPBYTE pb, DWORD cb, U1ARRAYREF* u1);
    static BYTE* U1ARRAYREFToByteArray (U1ARRAYREF u1);
    static char* UnicodeToAnsi (__in_z WCHAR* pwszUnicode);
#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
    static WCHAR* GetRandomKeyContainer ();    
    static inline void memrev (LPBYTE pb, DWORD cb);
    static BOOL CryptGenKey_SO_TOLERANT (HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY* phKey);
#endif // FEATURE_CRYPTO    

    static LPCWSTR UpgradeDSS(DWORD dwProvType, __in_z LPCWSTR wszProvider);
    static LPCWSTR UpgradeRSA(DWORD dwProvType, __in_z LPCWSTR wszProvider);

    // Since crytpo classes use safe handles where the handles are really pointers to structures, we
    // need to ensure that they weren't freed and set to NULL if the handle was used in an unsafe
    // multithreaded way. This method unpacks the handle, ensuring it doesn't contain a NULL pointer.
    template<class T>
    static T * DereferenceSafeHandle(const SAFEHANDLE &handle)
    {
        CONTRACT(T *)
        {
            POSTCONDITION(RETVAL != NULL);
            THROWS;
            GC_TRIGGERS;
        }
        CONTRACT_END;

        T * pValue = static_cast<T *>(handle->GetHandle());
        if (!pValue)
        {
            LOG((LF_SECURITY, LL_INFO10000, "Attempt to access a NULL crypto handle, possible unsafe use of a crypto function from multiple threads"));
            COMPlusThrowCrypto(E_POINTER);
        }

        RETURN(pValue);
    }
};
#endif // FEATURE_CRYPTO || FEATURE_X509

#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
typedef struct {
    BLOBHEADER          blob;
    union {
        DSSPRIVKEY_VER3         dss_priv_v3;
        DSSPUBKEY_VER3          dss_pub_v3;
        DSSPUBKEY               dss_v2;
        RSAPUBKEY               rsa;
    };
} KEY_HEADER;

// We need to define this unmanaged memory structure to hold 
// all the information relevant to the CSP in order to guarantee
// critical finalization of the resources
typedef struct CRYPT_PROV_CTX {
private:
    // We implicitely assume this method is not going to do a LoadLibrary
    HRESULT DeleteKeyContainer() {
        CONTRACTL {
            THROWS;
            GC_TRIGGERS;
            MODE_ANY;
        } CONTRACTL_END;

        GCX_PREEMP();

        HCRYPTPROV hProv = NULL;
        if (!CryptoHelper::WszCryptAcquireContext_SO_TOLERANT(&hProv, m_pwszContainer, m_pwszProvider,
                m_dwType, (m_dwFlags & CRYPT_MACHINE_KEYSET) | CRYPT_DELETEKEYSET))
            return HRESULT_FROM_GetLastError();
        return S_OK;
    }

public:
    HCRYPTPROV     m_hProv;
    LPCWSTR        m_pwszContainer;
    LPCWSTR        m_pwszProvider;
    DWORD          m_dwType;
    DWORD          m_dwFlags;
    BOOL           m_fPersistKeyInCsp;
    BOOL           m_fReleaseProvider;
    Volatile<ULONG> m_refCount;

    CRYPT_PROV_CTX() : 
        m_hProv(0), 
        m_pwszContainer(NULL), 
        m_pwszProvider(NULL),
        m_fReleaseProvider(TRUE), 
        m_dwType(0),
        m_dwFlags(0), 
        m_fPersistKeyInCsp(TRUE),
        m_refCount(1) {
        LIMITED_METHOD_CONTRACT;
    }

    // This can be called twice. Also it can be called by multiple threads. The only
    // invariant that needs to be enforced is that when the refCount reaches 0, the 
    // object is not going to be referenced anymore by a CRYPT_KEY_CTX or a CRYPT_HASH_CTX.
    // But this is true in the way we use this in the managed side.
    void Release () {
        CONTRACTL {
            THROWS;
            GC_TRIGGERS;
            MODE_ANY;
        } CONTRACTL_END;

        ULONG cbRef = InterlockedDecrement((LONG*)&m_refCount);
        if (cbRef == 0) {
            // Make sure not to delete a key that we want to keep in the key container or an ephemeral key
            if (m_fPersistKeyInCsp == FALSE && !(m_dwFlags & CRYPT_VERIFYCONTEXT)) {
                // We cannot throw if we fail to delete the key container, since this code runs on the
                // finalizer thread and any exception will tear the process
                DeleteKeyContainer();
            }

            if (m_pwszContainer) {
                delete[] m_pwszContainer;
                m_pwszContainer = NULL;
            }

            // The provider strings are allocated per process, so 
            // we should not free m_pwszProvider unless specified otherwise
            if (m_fReleaseProvider) {
                if (m_pwszProvider) {
                    delete[] m_pwszProvider;
                    m_pwszProvider = NULL;
                }
            }

            // We need to free the CSP handle -- make sure not to throw since this code could be on the
            // finalizer thread.
            if (m_hProv != 0) 
            {
                CryptReleaseContext(m_hProv, 0);
                m_hProv = 0;
            }

            delete this;
        }
    }

} CRYPT_PROV_CTX;

#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
// A key handle needs to be freed before the provider handle
// it was loaded into is freed; so we need to keep a pointer to 
// the CRYPT_PROV_CTX and make the managed SafeKeyHandle contain
// a pointer to the CRYPT_KEY_CTX pointer
typedef struct CRYPT_KEY_CTX {
public:
    CRYPT_PROV_CTX  *m_pProvCtx;
    HCRYPTKEY       m_hKey;
    DWORD           m_dwKeySpec;
    BOOL            m_fPublicOnly;

    CRYPT_KEY_CTX(CRYPT_PROV_CTX * pProvCtx, HCRYPTKEY hKey) : 
        m_pProvCtx(pProvCtx),
        m_hKey(hKey),
        m_dwKeySpec(0),
        m_fPublicOnly(FALSE) {
        CONTRACTL {
            NOTHROW;
            GC_NOTRIGGER;
            MODE_ANY;
            PRECONDITION(hKey != NULL);
            PRECONDITION(CheckPointer(m_pProvCtx));
            PRECONDITION((m_pProvCtx->m_refCount >= 1)); // We can't acquire a dead CRYPT_PROV_CTX
        } CONTRACTL_END;

        InterlockedIncrement((LONG*)&m_pProvCtx->m_refCount);
    }

    void Release () {
        CONTRACTL {
            THROWS;
            GC_TRIGGERS;
            MODE_ANY;
        } CONTRACTL_END;

        // We cannot throw if CryptDestroyKey fails, since this can be executed on the finalizer thread
        if (m_hKey)
            CryptDestroyKey(m_hKey);

        // We need to release the reference to the CSP handle 
        if (m_pProvCtx)
            m_pProvCtx->Release();

        delete this;
    }

} CRYPT_KEY_CTX;

// A hash handle needs to be freed before the provider handle
// it was loaded into is freed; so we need to keep a pointer to 
// the CRYPT_PROV_CTX and make the managed SafeHashHandle contain
// a pointer to the CRYPT_HASH_CTX pointer
typedef struct CRYPT_HASH_CTX {
public:
    CRYPT_PROV_CTX  *m_pProvCtx;
    HCRYPTHASH      m_hHash;

    CRYPT_HASH_CTX(CRYPT_PROV_CTX * pProvCtx, HCRYPTHASH hHash) : 
        m_pProvCtx(pProvCtx),
        m_hHash(hHash) {
        CONTRACTL {
            NOTHROW;
            GC_NOTRIGGER;
            MODE_ANY;
            PRECONDITION(hHash != NULL);
            PRECONDITION(CheckPointer(m_pProvCtx));
            PRECONDITION((m_pProvCtx->m_refCount >= 1)); // We can't acquire a dead CRYPT_PROV_CTX
        } CONTRACTL_END;

        InterlockedIncrement((LONG*)&m_pProvCtx->m_refCount);
    }

    void Release () {
        CONTRACTL {
            THROWS;
            GC_TRIGGERS;
            MODE_ANY;
        } CONTRACTL_END;

        // We cannot throw if CryptDestroyHash fails since this code could run on the finalizer thread
        if (m_hHash)
            CryptDestroyHash(m_hHash);

        // We need to release the reference to the CSP handle 
        if (m_pProvCtx)
            m_pProvCtx->Release();

        delete this;
    }

} CRYPT_HASH_CTX;
#endif // FEATURE_CRYPTO

class COMCryptography
{
public:

#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
    //
    // QCalls from RSACryptoServiceProvider
    //

    // Decrypt a symmetric key using the private key in pKeyContext
    static
    void QCALLTYPE DecryptKey(__in CRYPT_KEY_CTX *pKeyContext,
                              __in_bcount(cbEncryptedKey) BYTE *pbEncryptedKey,
                              DWORD cbEncryptedKey,
                              BOOL fOAEP,
                              QCall::ObjectHandleOnStack ohRetDecryptedKey);

    // Encrypt a symmetric key using the public key in pKeyContext
    static
    void QCALLTYPE EncryptKey(__in CRYPT_KEY_CTX *pKeyContext,
                              __in_bcount(cbKey) BYTE *pbKey,
                              DWORD cbKey,
                              BOOL fOAEP,
                              QCall::ObjectHandleOnStack ohRetEncryptedKey);

    //
    // SafeHandle release QCALLS
    //
#endif // FEATURE_CRYPTO
    // Release our handle to a CSP, potentially deleting the referenced key.
    static
    void QCALLTYPE FreeCsp(__in_opt CRYPT_PROV_CTX *pProviderContext);

#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
    // Release our handle to a hash, potentially also releasing the provider
    static
    void QCALLTYPE FreeHash(__in_opt CRYPT_HASH_CTX *pHashContext);

    // Release our handle to a key, potentially also releasing the provider
    static
    void QCALLTYPE FreeKey(__in_opt CRYPT_KEY_CTX *pKeyContext);

    //
    // Util QCALLS
    //

    static
    CRYPT_HASH_CTX * CreateHash(CRYPT_PROV_CTX * pProvCtx, DWORD dwHashType);

    static
    void QCALLTYPE DeriveKey(CRYPT_PROV_CTX * pProvCtx, DWORD dwCalgKey, DWORD dwCalgHash, 
                             LPCBYTE pbPwd, DWORD cbPwd, DWORD dwFlags, LPBYTE pbIVIn, DWORD cbIVIn,
                             QCall::ObjectHandleOnStack retKey);

    static
    void QCALLTYPE EndHash(CRYPT_HASH_CTX * pHashCtx, QCall::ObjectHandleOnStack retHash);

    static
    void QCALLTYPE ExportCspBlob(CRYPT_KEY_CTX * pKeyCtx, DWORD dwBlobType, QCall::ObjectHandleOnStack retBlob);
#endif // FEATURE_CRYPTO

    static
    void QCALLTYPE GetBytes(CRYPT_PROV_CTX * pProvCtx, BYTE * pbOut, INT32 cb);

    static
    void QCALLTYPE GetNonZeroBytes(CRYPT_PROV_CTX * pProvCtx, BYTE * pbOut, INT32 cb);

#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
    static
    BOOL QCALLTYPE GetPersistKeyInCsp(CRYPT_PROV_CTX * pProvCtx);

    static
    void QCALLTYPE HashData(CRYPT_HASH_CTX * pHashCtx, LPCBYTE pData, DWORD cbData, DWORD dwStart, DWORD dwSize);

    static
    BOOL QCALLTYPE SearchForAlgorithm(CRYPT_PROV_CTX * pProvCtx, DWORD dwAlgID, DWORD dwKeyLength);

    static
    void QCALLTYPE SetKeyParamDw(CRYPT_KEY_CTX * pKeyCtx, DWORD dwParam, DWORD dwValue);

    static
    void QCALLTYPE SetKeyParamRgb(CRYPT_KEY_CTX * pKeyCtx, DWORD dwParam, LPCBYTE pValue, DWORD cbValue);

    static
    DWORD QCALLTYPE SetKeySetSecurityInfo(CRYPT_PROV_CTX * pProvCtx, DWORD dwSecurityInformation, LPCBYTE pSecurityDescriptor);

    static
    void QCALLTYPE SetPersistKeyInCsp(CRYPT_PROV_CTX * pProvCtx, BOOL fPersistKeyInCsp);

    static
    void QCALLTYPE SetProviderParameter(CRYPT_PROV_CTX * pProvCtx, DWORD dwKeySpec, DWORD dwProvParam, INT_PTR pbData);

    static
    void QCALLTYPE SignValue(CRYPT_KEY_CTX * pKeyCtx, DWORD dwKeySpec, DWORD dwCalgKey, DWORD dwCalgHash, 
                             LPCBYTE pbHash, DWORD cbHash, QCall::ObjectHandleOnStack retSignature);

    static 
    BOOL QCALLTYPE VerifySign(CRYPT_KEY_CTX * pKeyCtx, DWORD dwCalgKey, DWORD dwCalgHash, 
                              LPCBYTE pbHash, DWORD cbHash, LPCBYTE pbSignature, DWORD cbSignature);

#endif // FEATURE_CRYPTO

public:
    //
    // FCalls from System.Security.Cryptography.Utils
    //

    static FCDECL2(void, _AcquireCSP, Object* cspParametersUNSAFE, SafeHandle** hProvUNSAFE);
    static FCDECL3(HRESULT, _OpenCSP, Object* cspParametersUNSAFE, DWORD dwFlags, SafeHandle** hProvUNSAFE);
    static FCDECL0(StringObject*, _GetRandomKeyContainer);
    static LPCWSTR GetDefaultProvider(DWORD dwType);    

#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
    static FCDECL3(void, _CreateCSP, Object* cspParametersUNSAFE, CLR_BOOL randomKeyContainer, SafeHandle** hProvUNSAFE);
    static FCDECL8(DWORD, _DecryptData, SafeHandle* hKeyUNSAFE, U1Array* dataUNSAFE, INT32 dwOffset, INT32 dwCount, U1Array** outputUNSAFE, INT32 dwOutputOffset, DWORD dwPaddingMode, CLR_BOOL fLast);
    static FCDECL8(DWORD, _EncryptData, SafeHandle* hKeyUNSAFE, U1Array* dataUNSAFE, INT32 dwOffset, INT32 dwCount, U1Array** outputUNSAFE, INT32 dwOutputOffset, DWORD dwPaddingMode, CLR_BOOL fLast);
    static FCDECL3(void, _ExportKey, SafeHandle* hKeyUNSAFE, DWORD dwBlobType, Object* theKeyUNSAFE);
    static FCDECL5(void, _GenerateKey, SafeHandle* hProvUNSAFE, DWORD dwCalg, DWORD dwFlags, DWORD dwKeySize, SafeHandle** hKeyUNSAFE);
    static FCDECL0(FC_BOOL_RET, _GetEnforceFipsPolicySetting);
    static FCDECL2(U1Array*, _GetKeyParameter, SafeHandle* hKeyUNSAFE, DWORD dwKeyParam);
    static FCDECL3(U1Array*, _GetKeySetSecurityInfo, SafeHandle* hProvUNSAFE, DWORD dwSecurityInformation, DWORD* pdwErrorCode);
    static FCDECL3(Object*, _GetProviderParameter, SafeHandle* hKeyUNSAFE, DWORD dwKeySpec, DWORD dwKeyParam);
    static FCDECL3(HRESULT, _GetUserKey, SafeHandle* hProvUNSAFE, DWORD dwKeySpec, SafeHandle** hKeyUNSAFE);
    static FCDECL5(void, _ImportBulkKey, SafeHandle* hProvUNSAFE, DWORD dwCalg, CLR_BOOL useSalt, U1Array* rgbKeyUNSAFE, SafeHandle** hKeyUNSAFE);
    static FCDECL4(DWORD, _ImportCspBlob, U1Array* rawDataUNSAFE, SafeHandle* hProvUNSAFE, DWORD dwFlags, SafeHandle** hKeyUNSAFE);
    static FCDECL5(void, _ImportKey, SafeHandle* hProvUNSAFE, DWORD dwCalg, DWORD dwFlags, Object* refKeyUNSAFE, SafeHandle** hKeyUNSAFE);
    static FCDECL0(FC_BOOL_RET, _ProduceLegacyHMACValues);
#endif // FEATURE_CRYPTO

private:
    static HRESULT OpenCSP(OBJECTREF * pSafeThis, DWORD dwFlags, CRYPT_PROV_CTX * pProvCtxStruct);
    static DWORD MapCspProviderFlags (DWORD dwFlags);

#if defined(FEATURE_CRYPTO) || defined(FEATURE_LEGACYNETCFCRYPTO)
    static HRESULT MSProviderCryptImportKey(HCRYPTPROV hProv, LPBYTE rgbSymKey, DWORD cbSymKey, DWORD dwFlags, HCRYPTKEY * phkey);
    static HRESULT ExponentOfOneImport(HCRYPTPROV hProv, LPBYTE rgbKeyMaterial, DWORD cbKeyMaterial, DWORD dwKeyAlg, DWORD dwFlags, HCRYPTKEY * phkey);
    static HRESULT PlainTextKeyBlobImport(HCRYPTPROV hProv, LPBYTE rgbKeyMaterial, DWORD cbKeyMaterial, DWORD dwKeyAlg, DWORD dwFlags, HCRYPTKEY * phkey);
    static HRESULT LoadKey(LPBYTE rgbKeyMaterial, DWORD cbKeyMaterial, HCRYPTPROV hprov, DWORD dwCalg, DWORD dwFlags, HCRYPTKEY * phkey);
    static HRESULT UnloadKey(HCRYPTPROV hprov, HCRYPTKEY hkey, LPBYTE * ppb, DWORD * pcb);
    static inline DWORD ConvertByteArrayToDWORD (LPBYTE pb, DWORD cb);
    static inline void ConvertIntToByteArray(DWORD dwInput, LPBYTE * ppb, DWORD * pcb);
    static DWORD MapCspKeyFlags (DWORD dwFlags);
#endif //FEATURE_CRYPTO    

}; // class COMCryptography

// @telesto - with talk of registry access, sounds like this should be #ifdef out from Telesto?
//---------------------------------------------------------------------------------------
//
// Cache of CSP data we've already looked up in the registry
//
// Notes:
//    This cache is thread safe. If a CSP is not stored in the cache, it will
//    return NULL rather than throwing. Attempting to store multiple CSPs with
//    the same type will result in only the first CSP being stored.
//

class ProviderCache
{
public:
    // Associate a name with a CSP type
    static void CacheProvider(DWORD dwType, __in_z LPWSTR pwzProvider);

    // Get the name that's associated with the given type, NULL if there is no association setup
    static LPCWSTR GetProvider(DWORD dwType);

private:
    // The largest type of CSP that Windows defines. This should be updated as new CSP types are defined
    static const DWORD  MaxWindowsProviderType = PROV_RSA_AES;

    static ProviderCache    *s_pCache;      // singleton cache instance

    EEIntHashTable          m_htCache;      // Mapping between cached provider types and CSP names
    Crst                    m_crstCache;    // Lock guarding access to m_htCache

    ProviderCache();

    void InternalCacheProvider(DWORD dwType, __in_z LPWSTR pwzProvider);
    LPCWSTR InternalGetProvider(DWORD dwType);
};
#endif // FEATURE_CRYPTO -- review flags

#endif // !_CRYPTOGRPAPHY_H_