d3dcompiler: Use an iface instead of a vtbl pointer in d3dcompiler_blob.
[wine/multimedia.git] / dlls / rsaenh / rsaenh.c
blob46a09200733e1b066e05494905e4b1e455e272a8
1 /*
2 * dlls/rsaenh/rsaenh.c
3 * RSAENH - RSA encryption for Wine
5 * Copyright 2002 TransGaming Technologies (David Hammerton)
6 * Copyright 2004 Mike McCormack for CodeWeavers
7 * Copyright 2004, 2005 Michael Jung
8 * Copyright 2007 Vijay Kiran Kamuju
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "config.h"
26 #include "wine/port.h"
27 #include "wine/library.h"
28 #include "wine/debug.h"
30 #include <stdarg.h>
31 #include <stdio.h>
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winreg.h"
36 #include "wincrypt.h"
37 #include "handle.h"
38 #include "implglue.h"
39 #include "objbase.h"
40 #include "rpcproxy.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
44 static HINSTANCE instance;
46 /******************************************************************************
47 * CRYPTHASH - hash objects
49 #define RSAENH_MAGIC_HASH 0x85938417u
50 #define RSAENH_MAX_HASH_SIZE 104
51 #define RSAENH_HASHSTATE_HASHING 1
52 #define RSAENH_HASHSTATE_FINISHED 2
53 typedef struct _RSAENH_TLS1PRF_PARAMS
55 CRYPT_DATA_BLOB blobLabel;
56 CRYPT_DATA_BLOB blobSeed;
57 } RSAENH_TLS1PRF_PARAMS;
59 typedef struct tagCRYPTHASH
61 OBJECTHDR header;
62 ALG_ID aiAlgid;
63 HCRYPTKEY hKey;
64 HCRYPTPROV hProv;
65 DWORD dwHashSize;
66 DWORD dwState;
67 HASH_CONTEXT context;
68 BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
69 PHMAC_INFO pHMACInfo;
70 RSAENH_TLS1PRF_PARAMS tpPRFParams;
71 } CRYPTHASH;
73 /******************************************************************************
74 * CRYPTKEY - key objects
76 #define RSAENH_MAGIC_KEY 0x73620457u
77 #define RSAENH_MAX_KEY_SIZE 48
78 #define RSAENH_MAX_BLOCK_SIZE 24
79 #define RSAENH_KEYSTATE_IDLE 0
80 #define RSAENH_KEYSTATE_ENCRYPTING 1
81 #define RSAENH_KEYSTATE_MASTERKEY 2
82 typedef struct _RSAENH_SCHANNEL_INFO
84 SCHANNEL_ALG saEncAlg;
85 SCHANNEL_ALG saMACAlg;
86 CRYPT_DATA_BLOB blobClientRandom;
87 CRYPT_DATA_BLOB blobServerRandom;
88 } RSAENH_SCHANNEL_INFO;
90 typedef struct tagCRYPTKEY
92 OBJECTHDR header;
93 ALG_ID aiAlgid;
94 HCRYPTPROV hProv;
95 DWORD dwMode;
96 DWORD dwModeBits;
97 DWORD dwPermissions;
98 DWORD dwKeyLen;
99 DWORD dwEffectiveKeyLen;
100 DWORD dwSaltLen;
101 DWORD dwBlockLen;
102 DWORD dwState;
103 KEY_CONTEXT context;
104 BYTE abKeyValue[RSAENH_MAX_KEY_SIZE];
105 BYTE abInitVector[RSAENH_MAX_BLOCK_SIZE];
106 BYTE abChainVector[RSAENH_MAX_BLOCK_SIZE];
107 RSAENH_SCHANNEL_INFO siSChannelInfo;
108 } CRYPTKEY;
110 /******************************************************************************
111 * KEYCONTAINER - key containers
113 #define RSAENH_PERSONALITY_BASE 0u
114 #define RSAENH_PERSONALITY_STRONG 1u
115 #define RSAENH_PERSONALITY_ENHANCED 2u
116 #define RSAENH_PERSONALITY_SCHANNEL 3u
117 #define RSAENH_PERSONALITY_AES 4u
119 #define RSAENH_MAGIC_CONTAINER 0x26384993u
120 typedef struct tagKEYCONTAINER
122 OBJECTHDR header;
123 DWORD dwFlags;
124 DWORD dwPersonality;
125 DWORD dwEnumAlgsCtr;
126 DWORD dwEnumContainersCtr;
127 CHAR szName[MAX_PATH];
128 CHAR szProvName[MAX_PATH];
129 HCRYPTKEY hKeyExchangeKeyPair;
130 HCRYPTKEY hSignatureKeyPair;
131 } KEYCONTAINER;
133 /******************************************************************************
134 * Some magic constants
136 #define RSAENH_ENCRYPT 1
137 #define RSAENH_DECRYPT 0
138 #define RSAENH_HMAC_DEF_IPAD_CHAR 0x36
139 #define RSAENH_HMAC_DEF_OPAD_CHAR 0x5c
140 #define RSAENH_HMAC_DEF_PAD_LEN 64
141 #define RSAENH_DES_EFFECTIVE_KEYLEN 56
142 #define RSAENH_DES_STORAGE_KEYLEN 64
143 #define RSAENH_3DES112_EFFECTIVE_KEYLEN 112
144 #define RSAENH_3DES112_STORAGE_KEYLEN 128
145 #define RSAENH_3DES_EFFECTIVE_KEYLEN 168
146 #define RSAENH_3DES_STORAGE_KEYLEN 192
147 #define RSAENH_MAGIC_RSA2 0x32415352
148 #define RSAENH_MAGIC_RSA1 0x31415352
149 #define RSAENH_PKC_BLOCKTYPE 0x02
150 #define RSAENH_SSL3_VERSION_MAJOR 3
151 #define RSAENH_SSL3_VERSION_MINOR 0
152 #define RSAENH_TLS1_VERSION_MAJOR 3
153 #define RSAENH_TLS1_VERSION_MINOR 1
154 #define RSAENH_REGKEY "Software\\Wine\\Crypto\\RSA\\%s"
156 #define RSAENH_MIN(a,b) ((a)<(b)?(a):(b))
157 /******************************************************************************
158 * aProvEnumAlgsEx - Defines the capabilities of the CSP personalities.
160 #define RSAENH_MAX_ENUMALGS 24
161 #define RSAENH_PCT1_SSL2_SSL3_TLS1 (CRYPT_FLAG_PCT1|CRYPT_FLAG_SSL2|CRYPT_FLAG_SSL3|CRYPT_FLAG_TLS1)
162 static const PROV_ENUMALGS_EX aProvEnumAlgsEx[5][RSAENH_MAX_ENUMALGS+1] =
165 {CALG_RC2, 40, 40, 56,0, 4,"RC2", 24,"RSA Data Security's RC2"},
166 {CALG_RC4, 40, 40, 56,0, 4,"RC4", 24,"RSA Data Security's RC4"},
167 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"},
168 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"},
169 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"},
170 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"},
171 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"},
172 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
173 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
174 {CALG_RSA_SIGN, 512,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
175 {CALG_RSA_KEYX, 512,384, 1024,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
176 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
177 {0, 0, 0, 0,0, 1,"", 1,""}
180 {CALG_RC2, 128, 40, 128,0, 4,"RC2", 24,"RSA Data Security's RC2"},
181 {CALG_RC4, 128, 40, 128,0, 4,"RC4", 24,"RSA Data Security's RC4"},
182 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"},
183 {CALG_3DES_112, 112,112, 112,0, 13,"3DES TWO KEY",19,"Two Key Triple DES"},
184 {CALG_3DES, 168,168, 168,0, 5,"3DES", 21,"Three Key Triple DES"},
185 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"},
186 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"},
187 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"},
188 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"},
189 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
190 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
191 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
192 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
193 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
194 {0, 0, 0, 0,0, 1,"", 1,""}
197 {CALG_RC2, 128, 40, 128,0, 4,"RC2", 24,"RSA Data Security's RC2"},
198 {CALG_RC4, 128, 40, 128,0, 4,"RC4", 24,"RSA Data Security's RC4"},
199 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"},
200 {CALG_3DES_112, 112,112, 112,0, 13,"3DES TWO KEY",19,"Two Key Triple DES"},
201 {CALG_3DES, 168,168, 168,0, 5,"3DES", 21,"Three Key Triple DES"},
202 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"},
203 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"},
204 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"},
205 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"},
206 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
207 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
208 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
209 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
210 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
211 {0, 0, 0, 0,0, 1,"", 1,""}
214 {CALG_RC2, 128, 40, 128,RSAENH_PCT1_SSL2_SSL3_TLS1, 4,"RC2", 24,"RSA Data Security's RC2"},
215 {CALG_RC4, 128, 40, 128,RSAENH_PCT1_SSL2_SSL3_TLS1, 4,"RC4", 24,"RSA Data Security's RC4"},
216 {CALG_DES, 56, 56, 56,RSAENH_PCT1_SSL2_SSL3_TLS1, 4,"DES", 31,"Data Encryption Standard (DES)"},
217 {CALG_3DES_112, 112,112, 112,RSAENH_PCT1_SSL2_SSL3_TLS1,13,"3DES TWO KEY",19,"Two Key Triple DES"},
218 {CALG_3DES, 168,168, 168,RSAENH_PCT1_SSL2_SSL3_TLS1, 5,"3DES", 21,"Three Key Triple DES"},
219 {CALG_SHA,160,160,160,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,6,"SHA-1",30,"Secure Hash Algorithm (SHA-1)"},
220 {CALG_MD5,128,128,128,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,4,"MD5",23,"Message Digest 5 (MD5)"},
221 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
222 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
223 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,9,"RSA_SIGN",14,"RSA Signature"},
224 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,9,"RSA_KEYX",17,"RSA Key Exchange"},
225 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
226 {CALG_PCT1_MASTER,128,128,128,CRYPT_FLAG_PCT1, 12,"PCT1 MASTER",12,"PCT1 Master"},
227 {CALG_SSL2_MASTER,40,40, 192,CRYPT_FLAG_SSL2, 12,"SSL2 MASTER",12,"SSL2 Master"},
228 {CALG_SSL3_MASTER,384,384,384,CRYPT_FLAG_SSL3, 12,"SSL3 MASTER",12,"SSL3 Master"},
229 {CALG_TLS1_MASTER,384,384,384,CRYPT_FLAG_TLS1, 12,"TLS1 MASTER",12,"TLS1 Master"},
230 {CALG_SCHANNEL_MASTER_HASH,0,0,-1,0, 16,"SCH MASTER HASH",21,"SChannel Master Hash"},
231 {CALG_SCHANNEL_MAC_KEY,0,0,-1,0, 12,"SCH MAC KEY",17,"SChannel MAC Key"},
232 {CALG_SCHANNEL_ENC_KEY,0,0,-1,0, 12,"SCH ENC KEY",24,"SChannel Encryption Key"},
233 {CALG_TLS1PRF, 0, 0, -1,0, 9,"TLS1 PRF", 28,"TLS1 Pseudo Random Function"},
234 {0, 0, 0, 0,0, 1,"", 1,""}
237 {CALG_RC2, 128, 40, 128,0, 4,"RC2", 24,"RSA Data Security's RC2"},
238 {CALG_RC4, 128, 40, 128,0, 4,"RC4", 24,"RSA Data Security's RC4"},
239 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"},
240 {CALG_3DES_112, 112,112, 112,0, 13,"3DES TWO KEY",19,"Two Key Triple DES"},
241 {CALG_3DES, 168,168, 168,0, 5,"3DES", 21,"Three Key Triple DES"},
242 {CALG_AES, 128,128, 128,0, 4,"AES", 35,"Advanced Encryption Standard (AES)"},
243 {CALG_AES_128, 128,128, 128,0, 8,"AES-128", 39,"Advanced Encryption Standard (AES-128)"},
244 {CALG_AES_192, 192,192, 192,0, 8,"AES-192", 39,"Advanced Encryption Standard (AES-192)"},
245 {CALG_AES_256, 256,256, 256,0, 8,"AES-256", 39,"Advanced Encryption Standard (AES-256)"},
246 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"},
247 {CALG_SHA_256, 256,256, 256,CRYPT_FLAG_SIGNING, 6,"SHA-256", 30,"Secure Hash Algorithm (SHA-256)"},
248 {CALG_SHA_384, 384,384, 384,CRYPT_FLAG_SIGNING, 6,"SHA-384", 30,"Secure Hash Algorithm (SHA-284)"},
249 {CALG_SHA_512, 512,512, 512,CRYPT_FLAG_SIGNING, 6,"SHA-512", 30,"Secure Hash Algorithm (SHA-512)"},
250 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"},
251 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"},
252 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"},
253 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
254 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
255 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
256 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
257 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
258 {0, 0, 0, 0,0, 1,"", 1,""}
262 /******************************************************************************
263 * API forward declarations
265 BOOL WINAPI
266 RSAENH_CPGetKeyParam(
267 HCRYPTPROV hProv,
268 HCRYPTKEY hKey,
269 DWORD dwParam,
270 BYTE *pbData,
271 DWORD *pdwDataLen,
272 DWORD dwFlags
275 BOOL WINAPI
276 RSAENH_CPEncrypt(
277 HCRYPTPROV hProv,
278 HCRYPTKEY hKey,
279 HCRYPTHASH hHash,
280 BOOL Final,
281 DWORD dwFlags,
282 BYTE *pbData,
283 DWORD *pdwDataLen,
284 DWORD dwBufLen
287 BOOL WINAPI
288 RSAENH_CPCreateHash(
289 HCRYPTPROV hProv,
290 ALG_ID Algid,
291 HCRYPTKEY hKey,
292 DWORD dwFlags,
293 HCRYPTHASH *phHash
296 BOOL WINAPI
297 RSAENH_CPSetHashParam(
298 HCRYPTPROV hProv,
299 HCRYPTHASH hHash,
300 DWORD dwParam,
301 BYTE *pbData, DWORD dwFlags
304 BOOL WINAPI
305 RSAENH_CPGetHashParam(
306 HCRYPTPROV hProv,
307 HCRYPTHASH hHash,
308 DWORD dwParam,
309 BYTE *pbData,
310 DWORD *pdwDataLen,
311 DWORD dwFlags
314 BOOL WINAPI
315 RSAENH_CPDestroyHash(
316 HCRYPTPROV hProv,
317 HCRYPTHASH hHash
320 static BOOL crypt_export_key(
321 CRYPTKEY *pCryptKey,
322 HCRYPTKEY hPubKey,
323 DWORD dwBlobType,
324 DWORD dwFlags,
325 BOOL force,
326 BYTE *pbData,
327 DWORD *pdwDataLen
330 static BOOL import_key(
331 HCRYPTPROV hProv,
332 CONST BYTE *pbData,
333 DWORD dwDataLen,
334 HCRYPTKEY hPubKey,
335 DWORD dwFlags,
336 BOOL fStoreKey,
337 HCRYPTKEY *phKey
340 BOOL WINAPI
341 RSAENH_CPHashData(
342 HCRYPTPROV hProv,
343 HCRYPTHASH hHash,
344 CONST BYTE *pbData,
345 DWORD dwDataLen,
346 DWORD dwFlags
349 /******************************************************************************
350 * CSP's handle table (used by all acquired key containers)
352 static struct handle_table handle_table;
354 /******************************************************************************
355 * DllMain (RSAENH.@)
357 * Initializes and destroys the handle table for the CSP's handles.
359 int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
361 switch (fdwReason)
363 case DLL_PROCESS_ATTACH:
364 instance = hInstance;
365 DisableThreadLibraryCalls(hInstance);
366 init_handle_table(&handle_table);
367 break;
369 case DLL_PROCESS_DETACH:
370 destroy_handle_table(&handle_table);
371 break;
373 return 1;
376 /******************************************************************************
377 * copy_param [Internal]
379 * Helper function that supports the standard WINAPI protocol for querying data
380 * of dynamic size.
382 * PARAMS
383 * pbBuffer [O] Buffer where the queried parameter is copied to, if it is large enough.
384 * May be NUL if the required buffer size is to be queried only.
385 * pdwBufferSize [I/O] In: Size of the buffer at pbBuffer
386 * Out: Size of parameter pbParam
387 * pbParam [I] Parameter value.
388 * dwParamSize [I] Size of pbParam
390 * RETURN
391 * Success: TRUE (pbParam was copied into pbBuffer or pbBuffer is NULL)
392 * Failure: FALSE (pbBuffer is not large enough to hold pbParam). Last error: ERROR_MORE_DATA
394 static inline BOOL copy_param(
395 BYTE *pbBuffer, DWORD *pdwBufferSize, CONST BYTE *pbParam, DWORD dwParamSize)
397 if (pbBuffer)
399 if (dwParamSize > *pdwBufferSize)
401 SetLastError(ERROR_MORE_DATA);
402 *pdwBufferSize = dwParamSize;
403 return FALSE;
405 memcpy(pbBuffer, pbParam, dwParamSize);
407 *pdwBufferSize = dwParamSize;
408 return TRUE;
411 /******************************************************************************
412 * get_algid_info [Internal]
414 * Query CSP capabilities for a given crypto algorithm.
416 * PARAMS
417 * hProv [I] Handle to a key container of the CSP whose capabilities are to be queried.
418 * algid [I] Identifier of the crypto algorithm about which information is requested.
420 * RETURNS
421 * Success: Pointer to a PROV_ENUMALGS_EX struct containing information about the crypto algorithm.
422 * Failure: NULL (algid not supported)
424 static inline const PROV_ENUMALGS_EX* get_algid_info(HCRYPTPROV hProv, ALG_ID algid) {
425 const PROV_ENUMALGS_EX *iterator;
426 KEYCONTAINER *pKeyContainer;
428 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER, (OBJECTHDR**)&pKeyContainer)) {
429 SetLastError(NTE_BAD_UID);
430 return NULL;
433 for (iterator = aProvEnumAlgsEx[pKeyContainer->dwPersonality]; iterator->aiAlgid; iterator++) {
434 if (iterator->aiAlgid == algid) return iterator;
437 SetLastError(NTE_BAD_ALGID);
438 return NULL;
441 /******************************************************************************
442 * copy_data_blob [Internal]
444 * deeply copies a DATA_BLOB
446 * PARAMS
447 * dst [O] That's where the blob will be copied to
448 * src [I] Source blob
450 * RETURNS
451 * Success: TRUE
452 * Failure: FALSE (GetLastError() == NTE_NO_MEMORY
454 * NOTES
455 * Use free_data_blob to release resources occupied by copy_data_blob.
457 static inline BOOL copy_data_blob(PCRYPT_DATA_BLOB dst, CONST PCRYPT_DATA_BLOB src) {
458 dst->pbData = HeapAlloc(GetProcessHeap(), 0, src->cbData);
459 if (!dst->pbData) {
460 SetLastError(NTE_NO_MEMORY);
461 return FALSE;
463 dst->cbData = src->cbData;
464 memcpy(dst->pbData, src->pbData, src->cbData);
465 return TRUE;
468 /******************************************************************************
469 * concat_data_blobs [Internal]
471 * Concatenates two blobs
473 * PARAMS
474 * dst [O] The new blob will be copied here
475 * src1 [I] Prefix blob
476 * src2 [I] Appendix blob
478 * RETURNS
479 * Success: TRUE
480 * Failure: FALSE (GetLastError() == NTE_NO_MEMORY)
482 * NOTES
483 * Release resources occupied by concat_data_blobs with free_data_blobs
485 static inline BOOL concat_data_blobs(PCRYPT_DATA_BLOB dst, CONST PCRYPT_DATA_BLOB src1,
486 CONST PCRYPT_DATA_BLOB src2)
488 dst->cbData = src1->cbData + src2->cbData;
489 dst->pbData = HeapAlloc(GetProcessHeap(), 0, dst->cbData);
490 if (!dst->pbData) {
491 SetLastError(NTE_NO_MEMORY);
492 return FALSE;
494 memcpy(dst->pbData, src1->pbData, src1->cbData);
495 memcpy(dst->pbData + src1->cbData, src2->pbData, src2->cbData);
496 return TRUE;
499 /******************************************************************************
500 * free_data_blob [Internal]
502 * releases resource occupied by a dynamically allocated CRYPT_DATA_BLOB
504 * PARAMS
505 * pBlob [I] Heap space occupied by pBlob->pbData is released
507 static inline void free_data_blob(PCRYPT_DATA_BLOB pBlob) {
508 HeapFree(GetProcessHeap(), 0, pBlob->pbData);
511 /******************************************************************************
512 * init_data_blob [Internal]
514 static inline void init_data_blob(PCRYPT_DATA_BLOB pBlob) {
515 pBlob->pbData = NULL;
516 pBlob->cbData = 0;
519 /******************************************************************************
520 * free_hmac_info [Internal]
522 * Deeply free an HMAC_INFO struct.
524 * PARAMS
525 * hmac_info [I] Pointer to the HMAC_INFO struct to be freed.
527 * NOTES
528 * See Internet RFC 2104 for details on the HMAC algorithm.
530 static inline void free_hmac_info(PHMAC_INFO hmac_info) {
531 if (!hmac_info) return;
532 HeapFree(GetProcessHeap(), 0, hmac_info->pbInnerString);
533 HeapFree(GetProcessHeap(), 0, hmac_info->pbOuterString);
534 HeapFree(GetProcessHeap(), 0, hmac_info);
537 /******************************************************************************
538 * copy_hmac_info [Internal]
540 * Deeply copy an HMAC_INFO struct
542 * PARAMS
543 * dst [O] Pointer to a location where the pointer to the HMAC_INFO copy will be stored.
544 * src [I] Pointer to the HMAC_INFO struct to be copied.
546 * RETURNS
547 * Success: TRUE
548 * Failure: FALSE
550 * NOTES
551 * See Internet RFC 2104 for details on the HMAC algorithm.
553 static BOOL copy_hmac_info(PHMAC_INFO *dst, const HMAC_INFO *src) {
554 if (!src) return FALSE;
555 *dst = HeapAlloc(GetProcessHeap(), 0, sizeof(HMAC_INFO));
556 if (!*dst) return FALSE;
557 **dst = *src;
558 (*dst)->pbInnerString = NULL;
559 (*dst)->pbOuterString = NULL;
560 if ((*dst)->cbInnerString == 0) (*dst)->cbInnerString = RSAENH_HMAC_DEF_PAD_LEN;
561 (*dst)->pbInnerString = HeapAlloc(GetProcessHeap(), 0, (*dst)->cbInnerString);
562 if (!(*dst)->pbInnerString) {
563 free_hmac_info(*dst);
564 return FALSE;
566 if (src->cbInnerString)
567 memcpy((*dst)->pbInnerString, src->pbInnerString, src->cbInnerString);
568 else
569 memset((*dst)->pbInnerString, RSAENH_HMAC_DEF_IPAD_CHAR, RSAENH_HMAC_DEF_PAD_LEN);
570 if ((*dst)->cbOuterString == 0) (*dst)->cbOuterString = RSAENH_HMAC_DEF_PAD_LEN;
571 (*dst)->pbOuterString = HeapAlloc(GetProcessHeap(), 0, (*dst)->cbOuterString);
572 if (!(*dst)->pbOuterString) {
573 free_hmac_info(*dst);
574 return FALSE;
576 if (src->cbOuterString)
577 memcpy((*dst)->pbOuterString, src->pbOuterString, src->cbOuterString);
578 else
579 memset((*dst)->pbOuterString, RSAENH_HMAC_DEF_OPAD_CHAR, RSAENH_HMAC_DEF_PAD_LEN);
580 return TRUE;
583 /******************************************************************************
584 * destroy_hash [Internal]
586 * Destructor for hash objects
588 * PARAMS
589 * pCryptHash [I] Pointer to the hash object to be destroyed.
590 * Will be invalid after function returns!
592 static void destroy_hash(OBJECTHDR *pObject)
594 CRYPTHASH *pCryptHash = (CRYPTHASH*)pObject;
596 free_hmac_info(pCryptHash->pHMACInfo);
597 free_data_blob(&pCryptHash->tpPRFParams.blobLabel);
598 free_data_blob(&pCryptHash->tpPRFParams.blobSeed);
599 HeapFree(GetProcessHeap(), 0, pCryptHash);
602 /******************************************************************************
603 * init_hash [Internal]
605 * Initialize (or reset) a hash object
607 * PARAMS
608 * pCryptHash [I] The hash object to be initialized.
610 static inline BOOL init_hash(CRYPTHASH *pCryptHash) {
611 DWORD dwLen;
613 switch (pCryptHash->aiAlgid)
615 case CALG_HMAC:
616 if (pCryptHash->pHMACInfo) {
617 const PROV_ENUMALGS_EX *pAlgInfo;
619 pAlgInfo = get_algid_info(pCryptHash->hProv, pCryptHash->pHMACInfo->HashAlgid);
620 if (!pAlgInfo) return FALSE;
621 pCryptHash->dwHashSize = pAlgInfo->dwDefaultLen >> 3;
622 init_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context);
623 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
624 pCryptHash->pHMACInfo->pbInnerString,
625 pCryptHash->pHMACInfo->cbInnerString);
627 return TRUE;
629 case CALG_MAC:
630 dwLen = sizeof(DWORD);
631 RSAENH_CPGetKeyParam(pCryptHash->hProv, pCryptHash->hKey, KP_BLOCKLEN,
632 (BYTE*)&pCryptHash->dwHashSize, &dwLen, 0);
633 pCryptHash->dwHashSize >>= 3;
634 return TRUE;
636 default:
637 return init_hash_impl(pCryptHash->aiAlgid, &pCryptHash->context);
641 /******************************************************************************
642 * update_hash [Internal]
644 * Hashes the given data and updates the hash object's state accordingly
646 * PARAMS
647 * pCryptHash [I] Hash object to be updated.
648 * pbData [I] Pointer to data stream to be hashed.
649 * dwDataLen [I] Length of data stream.
651 static inline void update_hash(CRYPTHASH *pCryptHash, CONST BYTE *pbData, DWORD dwDataLen) {
652 BYTE *pbTemp;
654 switch (pCryptHash->aiAlgid)
656 case CALG_HMAC:
657 if (pCryptHash->pHMACInfo)
658 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
659 pbData, dwDataLen);
660 break;
662 case CALG_MAC:
663 pbTemp = HeapAlloc(GetProcessHeap(), 0, dwDataLen);
664 if (!pbTemp) return;
665 memcpy(pbTemp, pbData, dwDataLen);
666 RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, 0, FALSE, 0,
667 pbTemp, &dwDataLen, dwDataLen);
668 HeapFree(GetProcessHeap(), 0, pbTemp);
669 break;
671 default:
672 update_hash_impl(pCryptHash->aiAlgid, &pCryptHash->context, pbData, dwDataLen);
676 /******************************************************************************
677 * finalize_hash [Internal]
679 * Finalizes the hash, after all data has been hashed with update_hash.
680 * No additional data can be hashed afterwards until the hash gets initialized again.
682 * PARAMS
683 * pCryptHash [I] Hash object to be finalized.
685 static inline void finalize_hash(CRYPTHASH *pCryptHash) {
686 DWORD dwDataLen;
688 switch (pCryptHash->aiAlgid)
690 case CALG_HMAC:
691 if (pCryptHash->pHMACInfo) {
692 BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
694 finalize_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
695 pCryptHash->abHashValue);
696 memcpy(abHashValue, pCryptHash->abHashValue, pCryptHash->dwHashSize);
697 init_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context);
698 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
699 pCryptHash->pHMACInfo->pbOuterString,
700 pCryptHash->pHMACInfo->cbOuterString);
701 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
702 abHashValue, pCryptHash->dwHashSize);
703 finalize_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
704 pCryptHash->abHashValue);
706 break;
708 case CALG_MAC:
709 dwDataLen = 0;
710 RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, 0, TRUE, 0,
711 pCryptHash->abHashValue, &dwDataLen, pCryptHash->dwHashSize);
712 break;
714 default:
715 finalize_hash_impl(pCryptHash->aiAlgid, &pCryptHash->context, pCryptHash->abHashValue);
719 /******************************************************************************
720 * destroy_key [Internal]
722 * Destructor for key objects
724 * PARAMS
725 * pCryptKey [I] Pointer to the key object to be destroyed.
726 * Will be invalid after function returns!
728 static void destroy_key(OBJECTHDR *pObject)
730 CRYPTKEY *pCryptKey = (CRYPTKEY*)pObject;
732 free_key_impl(pCryptKey->aiAlgid, &pCryptKey->context);
733 free_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom);
734 free_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom);
735 HeapFree(GetProcessHeap(), 0, pCryptKey);
738 /******************************************************************************
739 * setup_key [Internal]
741 * Initialize (or reset) a key object
743 * PARAMS
744 * pCryptKey [I] The key object to be initialized.
746 static inline void setup_key(CRYPTKEY *pCryptKey) {
747 pCryptKey->dwState = RSAENH_KEYSTATE_IDLE;
748 memcpy(pCryptKey->abChainVector, pCryptKey->abInitVector, sizeof(pCryptKey->abChainVector));
749 setup_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen,
750 pCryptKey->dwEffectiveKeyLen, pCryptKey->dwSaltLen,
751 pCryptKey->abKeyValue);
754 /******************************************************************************
755 * new_key [Internal]
757 * Creates a new key object without assigning the actual binary key value.
758 * This is done by CPDeriveKey, CPGenKey or CPImportKey, which call this function.
760 * PARAMS
761 * hProv [I] Handle to the provider to which the created key will belong.
762 * aiAlgid [I] The new key shall use the crypto algorithm idenfied by aiAlgid.
763 * dwFlags [I] Upper 16 bits give the key length.
764 * Lower 16 bits: CRYPT_EXPORTABLE, CRYPT_CREATE_SALT,
765 * CRYPT_NO_SALT
766 * ppCryptKey [O] Pointer to the created key
768 * RETURNS
769 * Success: Handle to the created key.
770 * Failure: INVALID_HANDLE_VALUE
772 static HCRYPTKEY new_key(HCRYPTPROV hProv, ALG_ID aiAlgid, DWORD dwFlags, CRYPTKEY **ppCryptKey)
774 HCRYPTKEY hCryptKey;
775 CRYPTKEY *pCryptKey;
776 DWORD dwKeyLen = HIWORD(dwFlags);
777 const PROV_ENUMALGS_EX *peaAlgidInfo;
779 *ppCryptKey = NULL;
782 * Retrieve the CSP's capabilities for the given ALG_ID value
784 peaAlgidInfo = get_algid_info(hProv, aiAlgid);
785 if (!peaAlgidInfo) return (HCRYPTKEY)INVALID_HANDLE_VALUE;
787 TRACE("alg = %s, dwKeyLen = %d\n", debugstr_a(peaAlgidInfo->szName),
788 dwKeyLen);
790 * Assume the default key length, if none is specified explicitly
792 if (dwKeyLen == 0) dwKeyLen = peaAlgidInfo->dwDefaultLen;
795 * Check if the requested key length is supported by the current CSP.
796 * Adjust key length's for DES algorithms.
798 switch (aiAlgid) {
799 case CALG_DES:
800 if (dwKeyLen == RSAENH_DES_EFFECTIVE_KEYLEN) {
801 dwKeyLen = RSAENH_DES_STORAGE_KEYLEN;
803 if (dwKeyLen != RSAENH_DES_STORAGE_KEYLEN) {
804 SetLastError(NTE_BAD_FLAGS);
805 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
807 break;
809 case CALG_3DES_112:
810 if (dwKeyLen == RSAENH_3DES112_EFFECTIVE_KEYLEN) {
811 dwKeyLen = RSAENH_3DES112_STORAGE_KEYLEN;
813 if (dwKeyLen != RSAENH_3DES112_STORAGE_KEYLEN) {
814 SetLastError(NTE_BAD_FLAGS);
815 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
817 break;
819 case CALG_3DES:
820 if (dwKeyLen == RSAENH_3DES_EFFECTIVE_KEYLEN) {
821 dwKeyLen = RSAENH_3DES_STORAGE_KEYLEN;
823 if (dwKeyLen != RSAENH_3DES_STORAGE_KEYLEN) {
824 SetLastError(NTE_BAD_FLAGS);
825 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
827 break;
829 default:
830 if (dwKeyLen % 8 ||
831 dwKeyLen > peaAlgidInfo->dwMaxLen ||
832 dwKeyLen < peaAlgidInfo->dwMinLen)
834 TRACE("key len %d out of bounds (%d, %d)\n", dwKeyLen,
835 peaAlgidInfo->dwMinLen, peaAlgidInfo->dwMaxLen);
836 SetLastError(NTE_BAD_DATA);
837 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
841 hCryptKey = new_object(&handle_table, sizeof(CRYPTKEY), RSAENH_MAGIC_KEY,
842 destroy_key, (OBJECTHDR**)&pCryptKey);
843 if (hCryptKey != (HCRYPTKEY)INVALID_HANDLE_VALUE)
845 pCryptKey->aiAlgid = aiAlgid;
846 pCryptKey->hProv = hProv;
847 pCryptKey->dwModeBits = 0;
848 pCryptKey->dwPermissions = CRYPT_ENCRYPT | CRYPT_DECRYPT | CRYPT_READ | CRYPT_WRITE |
849 CRYPT_MAC;
850 if (dwFlags & CRYPT_EXPORTABLE)
851 pCryptKey->dwPermissions |= CRYPT_EXPORT;
852 pCryptKey->dwKeyLen = dwKeyLen >> 3;
853 pCryptKey->dwEffectiveKeyLen = 0;
854 if ((dwFlags & CRYPT_CREATE_SALT) || (dwKeyLen == 40 && !(dwFlags & CRYPT_NO_SALT)))
855 pCryptKey->dwSaltLen = 16 /*FIXME*/ - pCryptKey->dwKeyLen;
856 else
857 pCryptKey->dwSaltLen = 0;
858 memset(pCryptKey->abKeyValue, 0, sizeof(pCryptKey->abKeyValue));
859 memset(pCryptKey->abInitVector, 0, sizeof(pCryptKey->abInitVector));
860 init_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom);
861 init_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom);
863 switch(aiAlgid)
865 case CALG_PCT1_MASTER:
866 case CALG_SSL2_MASTER:
867 case CALG_SSL3_MASTER:
868 case CALG_TLS1_MASTER:
869 case CALG_RC4:
870 pCryptKey->dwBlockLen = 0;
871 pCryptKey->dwMode = 0;
872 break;
874 case CALG_RC2:
875 case CALG_DES:
876 case CALG_3DES_112:
877 case CALG_3DES:
878 pCryptKey->dwBlockLen = 8;
879 pCryptKey->dwMode = CRYPT_MODE_CBC;
880 break;
882 case CALG_AES:
883 case CALG_AES_128:
884 case CALG_AES_192:
885 case CALG_AES_256:
886 pCryptKey->dwBlockLen = 16;
887 pCryptKey->dwMode = CRYPT_MODE_ECB;
888 break;
890 case CALG_RSA_KEYX:
891 case CALG_RSA_SIGN:
892 pCryptKey->dwBlockLen = dwKeyLen >> 3;
893 pCryptKey->dwMode = 0;
894 break;
897 *ppCryptKey = pCryptKey;
900 return hCryptKey;
903 /******************************************************************************
904 * map_key_spec_to_key_pair_name [Internal]
906 * Returns the name of the registry value associated with a key spec.
908 * PARAMS
909 * dwKeySpec [I] AT_KEYEXCHANGE or AT_SIGNATURE
911 * RETURNS
912 * Success: Name of registry value.
913 * Failure: NULL
915 static LPCSTR map_key_spec_to_key_pair_name(DWORD dwKeySpec)
917 LPCSTR szValueName;
919 switch (dwKeySpec)
921 case AT_KEYEXCHANGE:
922 szValueName = "KeyExchangeKeyPair";
923 break;
924 case AT_SIGNATURE:
925 szValueName = "SignatureKeyPair";
926 break;
927 default:
928 WARN("invalid key spec %d\n", dwKeySpec);
929 szValueName = NULL;
931 return szValueName;
934 /******************************************************************************
935 * store_key_pair [Internal]
937 * Stores a key pair to the registry
939 * PARAMS
940 * hCryptKey [I] Handle to the key to be stored
941 * hKey [I] Registry key where the key pair is to be stored
942 * dwKeySpec [I] AT_KEYEXCHANGE or AT_SIGNATURE
943 * dwFlags [I] Flags for protecting the key
945 static void store_key_pair(HCRYPTKEY hCryptKey, HKEY hKey, DWORD dwKeySpec, DWORD dwFlags)
947 LPCSTR szValueName;
948 DATA_BLOB blobIn, blobOut;
949 CRYPTKEY *pKey;
950 DWORD dwLen;
951 BYTE *pbKey;
953 if (!(szValueName = map_key_spec_to_key_pair_name(dwKeySpec)))
954 return;
955 if (lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY,
956 (OBJECTHDR**)&pKey))
958 if (crypt_export_key(pKey, 0, PRIVATEKEYBLOB, 0, TRUE, 0, &dwLen))
960 pbKey = HeapAlloc(GetProcessHeap(), 0, dwLen);
961 if (pbKey)
963 if (crypt_export_key(pKey, 0, PRIVATEKEYBLOB, 0, TRUE, pbKey,
964 &dwLen))
966 blobIn.pbData = pbKey;
967 blobIn.cbData = dwLen;
969 if (CryptProtectData(&blobIn, NULL, NULL, NULL, NULL,
970 dwFlags, &blobOut))
972 RegSetValueExA(hKey, szValueName, 0, REG_BINARY,
973 blobOut.pbData, blobOut.cbData);
974 LocalFree(blobOut.pbData);
977 HeapFree(GetProcessHeap(), 0, pbKey);
983 /******************************************************************************
984 * map_key_spec_to_permissions_name [Internal]
986 * Returns the name of the registry value associated with the permissions for
987 * a key spec.
989 * PARAMS
990 * dwKeySpec [I] AT_KEYEXCHANGE or AT_SIGNATURE
992 * RETURNS
993 * Success: Name of registry value.
994 * Failure: NULL
996 static LPCSTR map_key_spec_to_permissions_name(DWORD dwKeySpec)
998 LPCSTR szValueName;
1000 switch (dwKeySpec)
1002 case AT_KEYEXCHANGE:
1003 szValueName = "KeyExchangePermissions";
1004 break;
1005 case AT_SIGNATURE:
1006 szValueName = "SignaturePermissions";
1007 break;
1008 default:
1009 WARN("invalid key spec %d\n", dwKeySpec);
1010 szValueName = NULL;
1012 return szValueName;
1015 /******************************************************************************
1016 * store_key_permissions [Internal]
1018 * Stores a key's permissions to the registry
1020 * PARAMS
1021 * hCryptKey [I] Handle to the key whose permissions are to be stored
1022 * hKey [I] Registry key where the key permissions are to be stored
1023 * dwKeySpec [I] AT_KEYEXCHANGE or AT_SIGNATURE
1025 static void store_key_permissions(HCRYPTKEY hCryptKey, HKEY hKey, DWORD dwKeySpec)
1027 LPCSTR szValueName;
1028 CRYPTKEY *pKey;
1030 if (!(szValueName = map_key_spec_to_permissions_name(dwKeySpec)))
1031 return;
1032 if (lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY,
1033 (OBJECTHDR**)&pKey))
1034 RegSetValueExA(hKey, szValueName, 0, REG_DWORD,
1035 (BYTE *)&pKey->dwPermissions,
1036 sizeof(pKey->dwPermissions));
1039 /******************************************************************************
1040 * create_container_key [Internal]
1042 * Creates the registry key for a key container's persistent storage.
1044 * PARAMS
1045 * pKeyContainer [I] Pointer to the key container
1046 * sam [I] Desired registry access
1047 * phKey [O] Returned key
1049 static BOOL create_container_key(KEYCONTAINER *pKeyContainer, REGSAM sam, HKEY *phKey)
1051 CHAR szRSABase[MAX_PATH];
1052 HKEY hRootKey;
1054 sprintf(szRSABase, RSAENH_REGKEY, pKeyContainer->szName);
1056 if (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET)
1057 hRootKey = HKEY_LOCAL_MACHINE;
1058 else
1059 hRootKey = HKEY_CURRENT_USER;
1061 /* @@ Wine registry key: HKLM\Software\Wine\Crypto\RSA */
1062 /* @@ Wine registry key: HKCU\Software\Wine\Crypto\RSA */
1063 return RegCreateKeyExA(hRootKey, szRSABase, 0, NULL,
1064 REG_OPTION_NON_VOLATILE, sam, NULL, phKey, NULL)
1065 == ERROR_SUCCESS;
1068 /******************************************************************************
1069 * open_container_key [Internal]
1071 * Opens a key container's persistent storage for reading.
1073 * PARAMS
1074 * pszContainerName [I] Name of the container to be opened. May be the empty
1075 * string if the parent key of all containers is to be
1076 * opened.
1077 * dwFlags [I] Flags indicating which keyset to be opened.
1078 * phKey [O] Returned key
1080 static BOOL open_container_key(LPCSTR pszContainerName, DWORD dwFlags, HKEY *phKey)
1082 CHAR szRSABase[MAX_PATH];
1083 HKEY hRootKey;
1085 sprintf(szRSABase, RSAENH_REGKEY, pszContainerName);
1087 if (dwFlags & CRYPT_MACHINE_KEYSET)
1088 hRootKey = HKEY_LOCAL_MACHINE;
1089 else
1090 hRootKey = HKEY_CURRENT_USER;
1092 /* @@ Wine registry key: HKLM\Software\Wine\Crypto\RSA */
1093 /* @@ Wine registry key: HKCU\Software\Wine\Crypto\RSA */
1094 return RegOpenKeyExA(hRootKey, szRSABase, 0, KEY_READ, phKey) ==
1095 ERROR_SUCCESS;
1098 /******************************************************************************
1099 * delete_container_key [Internal]
1101 * Deletes a key container's persistent storage.
1103 * PARAMS
1104 * pszContainerName [I] Name of the container to be opened.
1105 * dwFlags [I] Flags indicating which keyset to be opened.
1107 static BOOL delete_container_key(LPCSTR pszContainerName, DWORD dwFlags)
1109 CHAR szRegKey[MAX_PATH];
1111 if (snprintf(szRegKey, MAX_PATH, RSAENH_REGKEY, pszContainerName) >= MAX_PATH) {
1112 SetLastError(NTE_BAD_KEYSET_PARAM);
1113 return FALSE;
1114 } else {
1115 HKEY hRootKey;
1116 if (dwFlags & CRYPT_MACHINE_KEYSET)
1117 hRootKey = HKEY_LOCAL_MACHINE;
1118 else
1119 hRootKey = HKEY_CURRENT_USER;
1120 if (!RegDeleteKeyA(hRootKey, szRegKey)) {
1121 SetLastError(ERROR_SUCCESS);
1122 return TRUE;
1123 } else {
1124 SetLastError(NTE_BAD_KEYSET);
1125 return FALSE;
1130 /******************************************************************************
1131 * store_key_container_keys [Internal]
1133 * Stores key container's keys in a persistent location.
1135 * PARAMS
1136 * pKeyContainer [I] Pointer to the key container whose keys are to be saved
1138 static void store_key_container_keys(KEYCONTAINER *pKeyContainer)
1140 HKEY hKey;
1141 DWORD dwFlags;
1143 /* On WinXP, persistent keys are stored in a file located at:
1144 * $AppData$\\Microsoft\\Crypto\\RSA\\$SID$\\some_hex_string
1147 if (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET)
1148 dwFlags = CRYPTPROTECT_LOCAL_MACHINE;
1149 else
1150 dwFlags = 0;
1152 if (create_container_key(pKeyContainer, KEY_WRITE, &hKey))
1154 store_key_pair(pKeyContainer->hKeyExchangeKeyPair, hKey,
1155 AT_KEYEXCHANGE, dwFlags);
1156 store_key_pair(pKeyContainer->hSignatureKeyPair, hKey,
1157 AT_SIGNATURE, dwFlags);
1158 RegCloseKey(hKey);
1162 /******************************************************************************
1163 * store_key_container_permissions [Internal]
1165 * Stores key container's key permissions in a persistent location.
1167 * PARAMS
1168 * pKeyContainer [I] Pointer to the key container whose key permissions are to
1169 * be saved
1171 static void store_key_container_permissions(KEYCONTAINER *pKeyContainer)
1173 HKEY hKey;
1175 if (create_container_key(pKeyContainer, KEY_WRITE, &hKey))
1177 store_key_permissions(pKeyContainer->hKeyExchangeKeyPair, hKey,
1178 AT_KEYEXCHANGE);
1179 store_key_permissions(pKeyContainer->hSignatureKeyPair, hKey,
1180 AT_SIGNATURE);
1181 RegCloseKey(hKey);
1185 /******************************************************************************
1186 * release_key_container_keys [Internal]
1188 * Releases key container's keys.
1190 * PARAMS
1191 * pKeyContainer [I] Pointer to the key container whose keys are to be released.
1193 static void release_key_container_keys(KEYCONTAINER *pKeyContainer)
1195 release_handle(&handle_table, pKeyContainer->hKeyExchangeKeyPair,
1196 RSAENH_MAGIC_KEY);
1197 release_handle(&handle_table, pKeyContainer->hSignatureKeyPair,
1198 RSAENH_MAGIC_KEY);
1201 /******************************************************************************
1202 * destroy_key_container [Internal]
1204 * Destructor for key containers.
1206 * PARAMS
1207 * pObjectHdr [I] Pointer to the key container to be destroyed.
1209 static void destroy_key_container(OBJECTHDR *pObjectHdr)
1211 KEYCONTAINER *pKeyContainer = (KEYCONTAINER*)pObjectHdr;
1213 if (!(pKeyContainer->dwFlags & CRYPT_VERIFYCONTEXT))
1215 store_key_container_keys(pKeyContainer);
1216 store_key_container_permissions(pKeyContainer);
1217 release_key_container_keys(pKeyContainer);
1219 else
1220 release_key_container_keys(pKeyContainer);
1221 HeapFree( GetProcessHeap(), 0, pKeyContainer );
1224 /******************************************************************************
1225 * new_key_container [Internal]
1227 * Create a new key container. The personality (RSA Base, Strong or Enhanced CP)
1228 * of the CSP is determined via the pVTable->pszProvName string.
1230 * PARAMS
1231 * pszContainerName [I] Name of the key container.
1232 * pVTable [I] Callback functions and context info provided by the OS
1234 * RETURNS
1235 * Success: Handle to the new key container.
1236 * Failure: INVALID_HANDLE_VALUE
1238 static HCRYPTPROV new_key_container(PCCH pszContainerName, DWORD dwFlags, const VTableProvStruc *pVTable)
1240 KEYCONTAINER *pKeyContainer;
1241 HCRYPTPROV hKeyContainer;
1243 hKeyContainer = new_object(&handle_table, sizeof(KEYCONTAINER), RSAENH_MAGIC_CONTAINER,
1244 destroy_key_container, (OBJECTHDR**)&pKeyContainer);
1245 if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE)
1247 lstrcpynA(pKeyContainer->szName, pszContainerName, MAX_PATH);
1248 pKeyContainer->dwFlags = dwFlags;
1249 pKeyContainer->dwEnumAlgsCtr = 0;
1250 pKeyContainer->hKeyExchangeKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE;
1251 pKeyContainer->hSignatureKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE;
1252 if (pVTable && pVTable->pszProvName) {
1253 lstrcpynA(pKeyContainer->szProvName, pVTable->pszProvName, MAX_PATH);
1254 if (!strcmp(pVTable->pszProvName, MS_DEF_PROV_A)) {
1255 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_BASE;
1256 } else if (!strcmp(pVTable->pszProvName, MS_ENHANCED_PROV_A)) {
1257 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_ENHANCED;
1258 } else if (!strcmp(pVTable->pszProvName, MS_DEF_RSA_SCHANNEL_PROV_A)) {
1259 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_SCHANNEL;
1260 } else if (!strcmp(pVTable->pszProvName, MS_ENH_RSA_AES_PROV_A)) {
1261 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_AES;
1262 } else {
1263 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_STRONG;
1267 /* The new key container has to be inserted into the CSP immediately
1268 * after creation to be available for CPGetProvParam's PP_ENUMCONTAINERS. */
1269 if (!(dwFlags & CRYPT_VERIFYCONTEXT)) {
1270 HKEY hKey;
1272 if (create_container_key(pKeyContainer, KEY_WRITE, &hKey))
1273 RegCloseKey(hKey);
1277 return hKeyContainer;
1280 /******************************************************************************
1281 * read_key_value [Internal]
1283 * Reads a key pair value from the registry
1285 * PARAMS
1286 * hKeyContainer [I] Crypt provider to use to import the key
1287 * hKey [I] Registry key from which to read the key pair
1288 * dwKeySpec [I] AT_KEYEXCHANGE or AT_SIGNATURE
1289 * dwFlags [I] Flags for unprotecting the key
1290 * phCryptKey [O] Returned key
1292 static BOOL read_key_value(HCRYPTPROV hKeyContainer, HKEY hKey, DWORD dwKeySpec, DWORD dwFlags, HCRYPTKEY *phCryptKey)
1294 LPCSTR szValueName;
1295 DWORD dwValueType, dwLen;
1296 BYTE *pbKey;
1297 DATA_BLOB blobIn, blobOut;
1298 BOOL ret = FALSE;
1300 if (!(szValueName = map_key_spec_to_key_pair_name(dwKeySpec)))
1301 return FALSE;
1302 if (RegQueryValueExA(hKey, szValueName, 0, &dwValueType, NULL, &dwLen) ==
1303 ERROR_SUCCESS)
1305 pbKey = HeapAlloc(GetProcessHeap(), 0, dwLen);
1306 if (pbKey)
1308 if (RegQueryValueExA(hKey, szValueName, 0, &dwValueType, pbKey, &dwLen) ==
1309 ERROR_SUCCESS)
1311 blobIn.pbData = pbKey;
1312 blobIn.cbData = dwLen;
1314 if (CryptUnprotectData(&blobIn, NULL, NULL, NULL, NULL,
1315 dwFlags, &blobOut))
1317 ret = import_key(hKeyContainer, blobOut.pbData, blobOut.cbData, 0, 0,
1318 FALSE, phCryptKey);
1319 LocalFree(blobOut.pbData);
1322 HeapFree(GetProcessHeap(), 0, pbKey);
1325 if (ret)
1327 CRYPTKEY *pKey;
1329 if (lookup_handle(&handle_table, *phCryptKey, RSAENH_MAGIC_KEY,
1330 (OBJECTHDR**)&pKey))
1332 if ((szValueName = map_key_spec_to_permissions_name(dwKeySpec)))
1334 dwLen = sizeof(pKey->dwPermissions);
1335 RegQueryValueExA(hKey, szValueName, 0, NULL,
1336 (BYTE *)&pKey->dwPermissions, &dwLen);
1340 return ret;
1343 /******************************************************************************
1344 * read_key_container [Internal]
1346 * Tries to read the persistent state of the key container (mainly the signature
1347 * and key exchange private keys) given by pszContainerName.
1349 * PARAMS
1350 * pszContainerName [I] Name of the key container to read from the registry
1351 * pVTable [I] Pointer to context data provided by the operating system
1353 * RETURNS
1354 * Success: Handle to the key container read from the registry
1355 * Failure: INVALID_HANDLE_VALUE
1357 static HCRYPTPROV read_key_container(PCHAR pszContainerName, DWORD dwFlags, const VTableProvStruc *pVTable)
1359 HKEY hKey;
1360 KEYCONTAINER *pKeyContainer;
1361 HCRYPTPROV hKeyContainer;
1362 HCRYPTKEY hCryptKey;
1364 if (!open_container_key(pszContainerName, dwFlags, &hKey))
1366 SetLastError(NTE_BAD_KEYSET);
1367 return (HCRYPTPROV)INVALID_HANDLE_VALUE;
1370 hKeyContainer = new_key_container(pszContainerName, dwFlags, pVTable);
1371 if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE)
1373 DWORD dwProtectFlags = (dwFlags & CRYPT_MACHINE_KEYSET) ?
1374 CRYPTPROTECT_LOCAL_MACHINE : 0;
1376 if (!lookup_handle(&handle_table, hKeyContainer, RSAENH_MAGIC_CONTAINER,
1377 (OBJECTHDR**)&pKeyContainer))
1378 return (HCRYPTPROV)INVALID_HANDLE_VALUE;
1380 /* read_key_value calls import_key, which calls import_private_key,
1381 * which implicitly installs the key value into the appropriate key
1382 * container key. Thus the ref count is incremented twice, once for
1383 * the output key value, and once for the implicit install, and needs
1384 * to be decremented to balance the two.
1386 if (read_key_value(hKeyContainer, hKey, AT_KEYEXCHANGE,
1387 dwProtectFlags, &hCryptKey))
1388 release_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY);
1389 if (read_key_value(hKeyContainer, hKey, AT_SIGNATURE,
1390 dwProtectFlags, &hCryptKey))
1391 release_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY);
1394 return hKeyContainer;
1397 /******************************************************************************
1398 * build_hash_signature [Internal]
1400 * Builds a padded version of a hash to match the length of the RSA key modulus.
1402 * PARAMS
1403 * pbSignature [O] The padded hash object is stored here.
1404 * dwLen [I] Length of the pbSignature buffer.
1405 * aiAlgid [I] Algorithm identifier of the hash to be padded.
1406 * abHashValue [I] The value of the hash object.
1407 * dwHashLen [I] Length of the hash value.
1408 * dwFlags [I] Selection of padding algorithm.
1410 * RETURNS
1411 * Success: TRUE
1412 * Failure: FALSE (NTE_BAD_ALGID)
1414 static BOOL build_hash_signature(BYTE *pbSignature, DWORD dwLen, ALG_ID aiAlgid,
1415 CONST BYTE *abHashValue, DWORD dwHashLen, DWORD dwFlags)
1417 /* These prefixes are meant to be concatenated with hash values of the
1418 * respective kind to form a PKCS #7 DigestInfo. */
1419 static const struct tagOIDDescriptor {
1420 ALG_ID aiAlgid;
1421 DWORD dwLen;
1422 CONST BYTE abOID[19];
1423 } aOIDDescriptor[] = {
1424 { CALG_MD2, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
1425 0x86, 0xf7, 0x0d, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10 } },
1426 { CALG_MD4, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
1427 0x86, 0xf7, 0x0d, 0x02, 0x04, 0x05, 0x00, 0x04, 0x10 } },
1428 { CALG_MD5, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
1429 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 } },
1430 { CALG_SHA, 15, { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
1431 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 } },
1432 { CALG_SHA_256, 19, { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
1433 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
1434 0x05, 0x00, 0x04, 0x20 } },
1435 { CALG_SHA_384, 19, { 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
1436 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
1437 0x05, 0x00, 0x04, 0x30 } },
1438 { CALG_SHA_384, 19, { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
1439 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
1440 0x05, 0x00, 0x04, 0x40 } },
1441 { CALG_SSL3_SHAMD5, 0, { 0 } },
1442 { 0, 0, { 0 } }
1444 DWORD dwIdxOID, i, j;
1446 for (dwIdxOID = 0; aOIDDescriptor[dwIdxOID].aiAlgid; dwIdxOID++) {
1447 if (aOIDDescriptor[dwIdxOID].aiAlgid == aiAlgid) break;
1450 if (!aOIDDescriptor[dwIdxOID].aiAlgid) {
1451 SetLastError(NTE_BAD_ALGID);
1452 return FALSE;
1455 /* Build the padded signature */
1456 if (dwFlags & CRYPT_X931_FORMAT) {
1457 pbSignature[0] = 0x6b;
1458 for (i=1; i < dwLen - dwHashLen - 3; i++) {
1459 pbSignature[i] = 0xbb;
1461 pbSignature[i++] = 0xba;
1462 for (j=0; j < dwHashLen; j++, i++) {
1463 pbSignature[i] = abHashValue[j];
1465 pbSignature[i++] = 0x33;
1466 pbSignature[i++] = 0xcc;
1467 } else {
1468 pbSignature[0] = 0x00;
1469 pbSignature[1] = 0x01;
1470 if (dwFlags & CRYPT_NOHASHOID) {
1471 for (i=2; i < dwLen - 1 - dwHashLen; i++) {
1472 pbSignature[i] = 0xff;
1474 pbSignature[i++] = 0x00;
1475 } else {
1476 for (i=2; i < dwLen - 1 - aOIDDescriptor[dwIdxOID].dwLen - dwHashLen; i++) {
1477 pbSignature[i] = 0xff;
1479 pbSignature[i++] = 0x00;
1480 for (j=0; j < aOIDDescriptor[dwIdxOID].dwLen; j++) {
1481 pbSignature[i++] = aOIDDescriptor[dwIdxOID].abOID[j];
1484 for (j=0; j < dwHashLen; j++) {
1485 pbSignature[i++] = abHashValue[j];
1489 return TRUE;
1492 /******************************************************************************
1493 * tls1_p [Internal]
1495 * This is an implementation of the 'P_hash' helper function for TLS1's PRF.
1496 * It is used exclusively by tls1_prf. For details see RFC 2246, chapter 5.
1497 * The pseudo random stream generated by this function is exclusive or'ed with
1498 * the data in pbBuffer.
1500 * PARAMS
1501 * hHMAC [I] HMAC object, which will be used in pseudo random generation
1502 * pblobSeed [I] Seed value
1503 * pbBuffer [I/O] Pseudo random stream will be xor'ed to the provided data
1504 * dwBufferLen [I] Number of pseudo random bytes desired
1506 * RETURNS
1507 * Success: TRUE
1508 * Failure: FALSE
1510 static BOOL tls1_p(HCRYPTHASH hHMAC, CONST PCRYPT_DATA_BLOB pblobSeed, PBYTE pbBuffer, DWORD dwBufferLen)
1512 CRYPTHASH *pHMAC;
1513 BYTE abAi[RSAENH_MAX_HASH_SIZE];
1514 DWORD i = 0;
1516 if (!lookup_handle(&handle_table, hHMAC, RSAENH_MAGIC_HASH, (OBJECTHDR**)&pHMAC)) {
1517 SetLastError(NTE_BAD_HASH);
1518 return FALSE;
1521 /* compute A_1 = HMAC(seed) */
1522 init_hash(pHMAC);
1523 update_hash(pHMAC, pblobSeed->pbData, pblobSeed->cbData);
1524 finalize_hash(pHMAC);
1525 memcpy(abAi, pHMAC->abHashValue, pHMAC->dwHashSize);
1527 do {
1528 /* compute HMAC(A_i + seed) */
1529 init_hash(pHMAC);
1530 update_hash(pHMAC, abAi, pHMAC->dwHashSize);
1531 update_hash(pHMAC, pblobSeed->pbData, pblobSeed->cbData);
1532 finalize_hash(pHMAC);
1534 /* pseudo random stream := CONCAT_{i=1..n} ( HMAC(A_i + seed) ) */
1535 do {
1536 if (i >= dwBufferLen) break;
1537 pbBuffer[i] ^= pHMAC->abHashValue[i % pHMAC->dwHashSize];
1538 i++;
1539 } while (i % pHMAC->dwHashSize);
1541 /* compute A_{i+1} = HMAC(A_i) */
1542 init_hash(pHMAC);
1543 update_hash(pHMAC, abAi, pHMAC->dwHashSize);
1544 finalize_hash(pHMAC);
1545 memcpy(abAi, pHMAC->abHashValue, pHMAC->dwHashSize);
1546 } while (i < dwBufferLen);
1548 return TRUE;
1551 /******************************************************************************
1552 * tls1_prf [Internal]
1554 * TLS1 pseudo random function as specified in RFC 2246, chapter 5
1556 * PARAMS
1557 * hProv [I] Key container used to compute the pseudo random stream
1558 * hSecret [I] Key that holds the (pre-)master secret
1559 * pblobLabel [I] Descriptive label
1560 * pblobSeed [I] Seed value
1561 * pbBuffer [O] Pseudo random numbers will be stored here
1562 * dwBufferLen [I] Number of pseudo random bytes desired
1564 * RETURNS
1565 * Success: TRUE
1566 * Failure: FALSE
1568 static BOOL tls1_prf(HCRYPTPROV hProv, HCRYPTPROV hSecret, CONST PCRYPT_DATA_BLOB pblobLabel,
1569 CONST PCRYPT_DATA_BLOB pblobSeed, PBYTE pbBuffer, DWORD dwBufferLen)
1571 HMAC_INFO hmacInfo = { 0, NULL, 0, NULL, 0 };
1572 HCRYPTHASH hHMAC = (HCRYPTHASH)INVALID_HANDLE_VALUE;
1573 HCRYPTKEY hHalfSecret = (HCRYPTKEY)INVALID_HANDLE_VALUE;
1574 CRYPTKEY *pHalfSecret, *pSecret;
1575 DWORD dwHalfSecretLen;
1576 BOOL result = FALSE;
1577 CRYPT_DATA_BLOB blobLabelSeed;
1579 TRACE("(hProv=%08lx, hSecret=%08lx, pblobLabel=%p, pblobSeed=%p, pbBuffer=%p, dwBufferLen=%d)\n",
1580 hProv, hSecret, pblobLabel, pblobSeed, pbBuffer, dwBufferLen);
1582 if (!lookup_handle(&handle_table, hSecret, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pSecret)) {
1583 SetLastError(NTE_FAIL);
1584 return FALSE;
1587 dwHalfSecretLen = (pSecret->dwKeyLen+1)/2;
1589 /* concatenation of the label and the seed */
1590 if (!concat_data_blobs(&blobLabelSeed, pblobLabel, pblobSeed)) goto exit;
1592 /* zero out the buffer, since two random streams will be xor'ed into it. */
1593 memset(pbBuffer, 0, dwBufferLen);
1595 /* build a 'fake' key, to hold the secret. CALG_SSL2_MASTER is used since it provides
1596 * the biggest range of valid key lengths. */
1597 hHalfSecret = new_key(hProv, CALG_SSL2_MASTER, MAKELONG(0,dwHalfSecretLen*8), &pHalfSecret);
1598 if (hHalfSecret == (HCRYPTKEY)INVALID_HANDLE_VALUE) goto exit;
1600 /* Derive an HMAC_MD5 hash and call the helper function. */
1601 memcpy(pHalfSecret->abKeyValue, pSecret->abKeyValue, dwHalfSecretLen);
1602 if (!RSAENH_CPCreateHash(hProv, CALG_HMAC, hHalfSecret, 0, &hHMAC)) goto exit;
1603 hmacInfo.HashAlgid = CALG_MD5;
1604 if (!RSAENH_CPSetHashParam(hProv, hHMAC, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0)) goto exit;
1605 if (!tls1_p(hHMAC, &blobLabelSeed, pbBuffer, dwBufferLen)) goto exit;
1607 /* Reconfigure to HMAC_SHA hash and call helper function again. */
1608 memcpy(pHalfSecret->abKeyValue, pSecret->abKeyValue + (pSecret->dwKeyLen/2), dwHalfSecretLen);
1609 hmacInfo.HashAlgid = CALG_SHA;
1610 if (!RSAENH_CPSetHashParam(hProv, hHMAC, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0)) goto exit;
1611 if (!tls1_p(hHMAC, &blobLabelSeed, pbBuffer, dwBufferLen)) goto exit;
1613 result = TRUE;
1614 exit:
1615 release_handle(&handle_table, hHalfSecret, RSAENH_MAGIC_KEY);
1616 if (hHMAC != (HCRYPTHASH)INVALID_HANDLE_VALUE) RSAENH_CPDestroyHash(hProv, hHMAC);
1617 free_data_blob(&blobLabelSeed);
1618 return result;
1621 /******************************************************************************
1622 * pad_data [Internal]
1624 * Helper function for data padding according to PKCS1 #2
1626 * PARAMS
1627 * abData [I] The data to be padded
1628 * dwDataLen [I] Length of the data
1629 * abBuffer [O] Padded data will be stored here
1630 * dwBufferLen [I] Length of the buffer (also length of padded data)
1631 * dwFlags [I] Padding format (CRYPT_SSL2_FALLBACK)
1633 * RETURN
1634 * Success: TRUE
1635 * Failure: FALSE (NTE_BAD_LEN, too much data to pad)
1637 static BOOL pad_data(CONST BYTE *abData, DWORD dwDataLen, BYTE *abBuffer, DWORD dwBufferLen,
1638 DWORD dwFlags)
1640 DWORD i;
1642 /* Ensure there is enough space for PKCS1 #2 padding */
1643 if (dwDataLen > dwBufferLen-11) {
1644 SetLastError(NTE_BAD_LEN);
1645 return FALSE;
1648 memmove(abBuffer + dwBufferLen - dwDataLen, abData, dwDataLen);
1650 abBuffer[0] = 0x00;
1651 abBuffer[1] = RSAENH_PKC_BLOCKTYPE;
1652 for (i=2; i < dwBufferLen - dwDataLen - 1; i++)
1653 do gen_rand_impl(&abBuffer[i], 1); while (!abBuffer[i]);
1654 if (dwFlags & CRYPT_SSL2_FALLBACK)
1655 for (i-=8; i < dwBufferLen - dwDataLen - 1; i++)
1656 abBuffer[i] = 0x03;
1657 abBuffer[i] = 0x00;
1659 return TRUE;
1662 /******************************************************************************
1663 * unpad_data [Internal]
1665 * Remove the PKCS1 padding from RSA decrypted data
1667 * PARAMS
1668 * abData [I] The padded data
1669 * dwDataLen [I] Length of the padded data
1670 * abBuffer [O] Data without padding will be stored here
1671 * dwBufferLen [I/O] I: Length of the buffer, O: Length of unpadded data
1672 * dwFlags [I] Currently none defined
1674 * RETURNS
1675 * Success: TRUE
1676 * Failure: FALSE, (NTE_BAD_DATA, no valid PKCS1 padding or buffer too small)
1678 static BOOL unpad_data(CONST BYTE *abData, DWORD dwDataLen, BYTE *abBuffer, DWORD *dwBufferLen,
1679 DWORD dwFlags)
1681 DWORD i;
1683 for (i=2; i<dwDataLen; i++)
1684 if (!abData[i])
1685 break;
1687 if ((i == dwDataLen) || (*dwBufferLen < dwDataLen - i - 1) ||
1688 (abData[0] != 0x00) || (abData[1] != RSAENH_PKC_BLOCKTYPE))
1690 SetLastError(NTE_BAD_DATA);
1691 return FALSE;
1694 *dwBufferLen = dwDataLen - i - 1;
1695 memmove(abBuffer, abData + i + 1, *dwBufferLen);
1696 return TRUE;
1699 /******************************************************************************
1700 * CPAcquireContext (RSAENH.@)
1702 * Acquire a handle to the key container specified by pszContainer
1704 * PARAMS
1705 * phProv [O] Pointer to the location the acquired handle will be written to.
1706 * pszContainer [I] Name of the desired key container. See Notes
1707 * dwFlags [I] Flags. See Notes.
1708 * pVTable [I] Pointer to a PVTableProvStruct containing callbacks.
1710 * RETURNS
1711 * Success: TRUE
1712 * Failure: FALSE
1714 * NOTES
1715 * If pszContainer is NULL or points to a zero length string the user's login
1716 * name will be used as the key container name.
1718 * If the CRYPT_NEW_KEYSET flag is set in dwFlags a new keyset will be created.
1719 * If a keyset with the given name already exists, the function fails and sets
1720 * last error to NTE_EXISTS. If CRYPT_NEW_KEYSET is not set and the specified
1721 * key container does not exist, function fails and sets last error to
1722 * NTE_BAD_KEYSET.
1724 BOOL WINAPI RSAENH_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer,
1725 DWORD dwFlags, PVTableProvStruc pVTable)
1727 CHAR szKeyContainerName[MAX_PATH];
1729 TRACE("(phProv=%p, pszContainer=%s, dwFlags=%08x, pVTable=%p)\n", phProv,
1730 debugstr_a(pszContainer), dwFlags, pVTable);
1732 if (pszContainer && *pszContainer)
1734 lstrcpynA(szKeyContainerName, pszContainer, MAX_PATH);
1736 else
1738 DWORD dwLen = sizeof(szKeyContainerName);
1739 if (!GetUserNameA(szKeyContainerName, &dwLen)) return FALSE;
1742 switch (dwFlags & (CRYPT_NEWKEYSET|CRYPT_VERIFYCONTEXT|CRYPT_DELETEKEYSET))
1744 case 0:
1745 *phProv = read_key_container(szKeyContainerName, dwFlags, pVTable);
1746 break;
1748 case CRYPT_DELETEKEYSET:
1749 return delete_container_key(szKeyContainerName, dwFlags);
1751 case CRYPT_NEWKEYSET:
1752 *phProv = read_key_container(szKeyContainerName, dwFlags, pVTable);
1753 if (*phProv != (HCRYPTPROV)INVALID_HANDLE_VALUE)
1755 release_handle(&handle_table, *phProv, RSAENH_MAGIC_CONTAINER);
1756 TRACE("Can't create new keyset, already exists\n");
1757 SetLastError(NTE_EXISTS);
1758 return FALSE;
1760 *phProv = new_key_container(szKeyContainerName, dwFlags, pVTable);
1761 break;
1763 case CRYPT_VERIFYCONTEXT|CRYPT_NEWKEYSET:
1764 case CRYPT_VERIFYCONTEXT:
1765 if (pszContainer && *pszContainer) {
1766 TRACE("pszContainer should be empty\n");
1767 SetLastError(NTE_BAD_FLAGS);
1768 return FALSE;
1770 *phProv = new_key_container("", dwFlags, pVTable);
1771 break;
1773 default:
1774 *phProv = (HCRYPTPROV)INVALID_HANDLE_VALUE;
1775 SetLastError(NTE_BAD_FLAGS);
1776 return FALSE;
1779 if (*phProv != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
1780 SetLastError(ERROR_SUCCESS);
1781 return TRUE;
1782 } else {
1783 return FALSE;
1787 /******************************************************************************
1788 * CPCreateHash (RSAENH.@)
1790 * CPCreateHash creates and initalizes a new hash object.
1792 * PARAMS
1793 * hProv [I] Handle to the key container to which the new hash will belong.
1794 * Algid [I] Identifies the hash algorithm, which will be used for the hash.
1795 * hKey [I] Handle to a session key applied for keyed hashes.
1796 * dwFlags [I] Currently no flags defined. Must be zero.
1797 * phHash [O] Points to the location where a handle to the new hash will be stored.
1799 * RETURNS
1800 * Success: TRUE
1801 * Failure: FALSE
1803 * NOTES
1804 * hKey is a handle to a session key applied in keyed hashes like MAC and HMAC.
1805 * If a normal hash object is to be created (like e.g. MD2 or SHA1) hKey must be zero.
1807 BOOL WINAPI RSAENH_CPCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags,
1808 HCRYPTHASH *phHash)
1810 CRYPTKEY *pCryptKey;
1811 CRYPTHASH *pCryptHash;
1812 const PROV_ENUMALGS_EX *peaAlgidInfo;
1814 TRACE("(hProv=%08lx, Algid=%08x, hKey=%08lx, dwFlags=%08x, phHash=%p)\n", hProv, Algid, hKey,
1815 dwFlags, phHash);
1817 peaAlgidInfo = get_algid_info(hProv, Algid);
1818 if (!peaAlgidInfo) return FALSE;
1820 if (dwFlags)
1822 SetLastError(NTE_BAD_FLAGS);
1823 return FALSE;
1826 if (Algid == CALG_MAC || Algid == CALG_HMAC || Algid == CALG_SCHANNEL_MASTER_HASH ||
1827 Algid == CALG_TLS1PRF)
1829 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey)) {
1830 SetLastError(NTE_BAD_KEY);
1831 return FALSE;
1834 if ((Algid == CALG_MAC) && (GET_ALG_TYPE(pCryptKey->aiAlgid) != ALG_TYPE_BLOCK)) {
1835 SetLastError(NTE_BAD_KEY);
1836 return FALSE;
1839 if ((Algid == CALG_SCHANNEL_MASTER_HASH || Algid == CALG_TLS1PRF) &&
1840 (pCryptKey->aiAlgid != CALG_TLS1_MASTER))
1842 SetLastError(NTE_BAD_KEY);
1843 return FALSE;
1846 if ((Algid == CALG_TLS1PRF) && (pCryptKey->dwState != RSAENH_KEYSTATE_MASTERKEY)) {
1847 SetLastError(NTE_BAD_KEY_STATE);
1848 return FALSE;
1852 *phHash = new_object(&handle_table, sizeof(CRYPTHASH), RSAENH_MAGIC_HASH,
1853 destroy_hash, (OBJECTHDR**)&pCryptHash);
1854 if (!pCryptHash) return FALSE;
1856 pCryptHash->aiAlgid = Algid;
1857 pCryptHash->hKey = hKey;
1858 pCryptHash->hProv = hProv;
1859 pCryptHash->dwState = RSAENH_HASHSTATE_HASHING;
1860 pCryptHash->pHMACInfo = NULL;
1861 pCryptHash->dwHashSize = peaAlgidInfo->dwDefaultLen >> 3;
1862 init_data_blob(&pCryptHash->tpPRFParams.blobLabel);
1863 init_data_blob(&pCryptHash->tpPRFParams.blobSeed);
1865 if (Algid == CALG_SCHANNEL_MASTER_HASH) {
1866 static const char keyex[] = "key expansion";
1867 BYTE key_expansion[sizeof keyex];
1868 CRYPT_DATA_BLOB blobRandom, blobKeyExpansion = { 13, key_expansion };
1870 memcpy( key_expansion, keyex, sizeof keyex );
1872 if (pCryptKey->dwState != RSAENH_KEYSTATE_MASTERKEY) {
1873 static const char msec[] = "master secret";
1874 BYTE master_secret[sizeof msec];
1875 CRYPT_DATA_BLOB blobLabel = { 13, master_secret };
1876 BYTE abKeyValue[48];
1878 memcpy( master_secret, msec, sizeof msec );
1880 /* See RFC 2246, chapter 8.1 */
1881 if (!concat_data_blobs(&blobRandom,
1882 &pCryptKey->siSChannelInfo.blobClientRandom,
1883 &pCryptKey->siSChannelInfo.blobServerRandom))
1885 return FALSE;
1887 tls1_prf(hProv, hKey, &blobLabel, &blobRandom, abKeyValue, 48);
1888 pCryptKey->dwState = RSAENH_KEYSTATE_MASTERKEY;
1889 memcpy(pCryptKey->abKeyValue, abKeyValue, 48);
1890 free_data_blob(&blobRandom);
1893 /* See RFC 2246, chapter 6.3 */
1894 if (!concat_data_blobs(&blobRandom,
1895 &pCryptKey->siSChannelInfo.blobServerRandom,
1896 &pCryptKey->siSChannelInfo.blobClientRandom))
1898 return FALSE;
1900 tls1_prf(hProv, hKey, &blobKeyExpansion, &blobRandom, pCryptHash->abHashValue,
1901 RSAENH_MAX_HASH_SIZE);
1902 free_data_blob(&blobRandom);
1905 return init_hash(pCryptHash);
1908 /******************************************************************************
1909 * CPDestroyHash (RSAENH.@)
1911 * Releases the handle to a hash object. The object is destroyed if it's reference
1912 * count reaches zero.
1914 * PARAMS
1915 * hProv [I] Handle to the key container to which the hash object belongs.
1916 * hHash [I] Handle to the hash object to be released.
1918 * RETURNS
1919 * Success: TRUE
1920 * Failure: FALSE
1922 BOOL WINAPI RSAENH_CPDestroyHash(HCRYPTPROV hProv, HCRYPTHASH hHash)
1924 TRACE("(hProv=%08lx, hHash=%08lx)\n", hProv, hHash);
1926 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
1928 SetLastError(NTE_BAD_UID);
1929 return FALSE;
1932 if (!release_handle(&handle_table, hHash, RSAENH_MAGIC_HASH))
1934 SetLastError(NTE_BAD_HASH);
1935 return FALSE;
1938 return TRUE;
1941 /******************************************************************************
1942 * CPDestroyKey (RSAENH.@)
1944 * Releases the handle to a key object. The object is destroyed if it's reference
1945 * count reaches zero.
1947 * PARAMS
1948 * hProv [I] Handle to the key container to which the key object belongs.
1949 * hKey [I] Handle to the key object to be released.
1951 * RETURNS
1952 * Success: TRUE
1953 * Failure: FALSE
1955 BOOL WINAPI RSAENH_CPDestroyKey(HCRYPTPROV hProv, HCRYPTKEY hKey)
1957 TRACE("(hProv=%08lx, hKey=%08lx)\n", hProv, hKey);
1959 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
1961 SetLastError(NTE_BAD_UID);
1962 return FALSE;
1965 if (!release_handle(&handle_table, hKey, RSAENH_MAGIC_KEY))
1967 SetLastError(NTE_BAD_KEY);
1968 return FALSE;
1971 return TRUE;
1974 /******************************************************************************
1975 * CPDuplicateHash (RSAENH.@)
1977 * Clones a hash object including it's current state.
1979 * PARAMS
1980 * hUID [I] Handle to the key container the hash belongs to.
1981 * hHash [I] Handle to the hash object to be cloned.
1982 * pdwReserved [I] Reserved. Must be NULL.
1983 * dwFlags [I] No flags are currently defined. Must be 0.
1984 * phHash [O] Handle to the cloned hash object.
1986 * RETURNS
1987 * Success: TRUE.
1988 * Failure: FALSE.
1990 BOOL WINAPI RSAENH_CPDuplicateHash(HCRYPTPROV hUID, HCRYPTHASH hHash, DWORD *pdwReserved,
1991 DWORD dwFlags, HCRYPTHASH *phHash)
1993 CRYPTHASH *pSrcHash, *pDestHash;
1995 TRACE("(hUID=%08lx, hHash=%08lx, pdwReserved=%p, dwFlags=%08x, phHash=%p)\n", hUID, hHash,
1996 pdwReserved, dwFlags, phHash);
1998 if (!is_valid_handle(&handle_table, hUID, RSAENH_MAGIC_CONTAINER))
2000 SetLastError(NTE_BAD_UID);
2001 return FALSE;
2004 if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH, (OBJECTHDR**)&pSrcHash))
2006 SetLastError(NTE_BAD_HASH);
2007 return FALSE;
2010 if (!phHash || pdwReserved || dwFlags)
2012 SetLastError(ERROR_INVALID_PARAMETER);
2013 return FALSE;
2016 *phHash = new_object(&handle_table, sizeof(CRYPTHASH), RSAENH_MAGIC_HASH,
2017 destroy_hash, (OBJECTHDR**)&pDestHash);
2018 if (*phHash != (HCRYPTHASH)INVALID_HANDLE_VALUE)
2020 *pDestHash = *pSrcHash;
2021 duplicate_hash_impl(pSrcHash->aiAlgid, &pSrcHash->context, &pDestHash->context);
2022 copy_hmac_info(&pDestHash->pHMACInfo, pSrcHash->pHMACInfo);
2023 copy_data_blob(&pDestHash->tpPRFParams.blobLabel, &pSrcHash->tpPRFParams.blobLabel);
2024 copy_data_blob(&pDestHash->tpPRFParams.blobSeed, &pSrcHash->tpPRFParams.blobSeed);
2027 return *phHash != (HCRYPTHASH)INVALID_HANDLE_VALUE;
2030 /******************************************************************************
2031 * CPDuplicateKey (RSAENH.@)
2033 * Clones a key object including it's current state.
2035 * PARAMS
2036 * hUID [I] Handle to the key container the hash belongs to.
2037 * hKey [I] Handle to the key object to be cloned.
2038 * pdwReserved [I] Reserved. Must be NULL.
2039 * dwFlags [I] No flags are currently defined. Must be 0.
2040 * phHash [O] Handle to the cloned key object.
2042 * RETURNS
2043 * Success: TRUE.
2044 * Failure: FALSE.
2046 BOOL WINAPI RSAENH_CPDuplicateKey(HCRYPTPROV hUID, HCRYPTKEY hKey, DWORD *pdwReserved,
2047 DWORD dwFlags, HCRYPTKEY *phKey)
2049 CRYPTKEY *pSrcKey, *pDestKey;
2051 TRACE("(hUID=%08lx, hKey=%08lx, pdwReserved=%p, dwFlags=%08x, phKey=%p)\n", hUID, hKey,
2052 pdwReserved, dwFlags, phKey);
2054 if (!is_valid_handle(&handle_table, hUID, RSAENH_MAGIC_CONTAINER))
2056 SetLastError(NTE_BAD_UID);
2057 return FALSE;
2060 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pSrcKey))
2062 SetLastError(NTE_BAD_KEY);
2063 return FALSE;
2066 if (!phKey || pdwReserved || dwFlags)
2068 SetLastError(ERROR_INVALID_PARAMETER);
2069 return FALSE;
2072 *phKey = new_object(&handle_table, sizeof(CRYPTKEY), RSAENH_MAGIC_KEY, destroy_key,
2073 (OBJECTHDR**)&pDestKey);
2074 if (*phKey != (HCRYPTKEY)INVALID_HANDLE_VALUE)
2076 *pDestKey = *pSrcKey;
2077 copy_data_blob(&pDestKey->siSChannelInfo.blobServerRandom,
2078 &pSrcKey->siSChannelInfo.blobServerRandom);
2079 copy_data_blob(&pDestKey->siSChannelInfo.blobClientRandom,
2080 &pSrcKey->siSChannelInfo.blobClientRandom);
2081 duplicate_key_impl(pSrcKey->aiAlgid, &pSrcKey->context, &pDestKey->context);
2082 return TRUE;
2084 else
2086 return FALSE;
2090 /******************************************************************************
2091 * CPEncrypt (RSAENH.@)
2093 * Encrypt data.
2095 * PARAMS
2096 * hProv [I] The key container hKey and hHash belong to.
2097 * hKey [I] The key used to encrypt the data.
2098 * hHash [I] An optional hash object for parallel hashing. See notes.
2099 * Final [I] Indicates if this is the last block of data to encrypt.
2100 * dwFlags [I] Currently no flags defined. Must be zero.
2101 * pbData [I/O] Pointer to the data to encrypt. Encrypted data will also be stored there.
2102 * pdwDataLen [I/O] I: Length of data to encrypt, O: Length of encrypted data.
2103 * dwBufLen [I] Size of the buffer at pbData.
2105 * RETURNS
2106 * Success: TRUE.
2107 * Failure: FALSE.
2109 * NOTES
2110 * If a hash object handle is provided in hHash, it will be updated with the plaintext.
2111 * This is useful for message signatures.
2113 * This function uses the standard WINAPI protocol for querying data of dynamic length.
2115 BOOL WINAPI RSAENH_CPEncrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
2116 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
2118 CRYPTKEY *pCryptKey;
2119 BYTE *in, out[RSAENH_MAX_BLOCK_SIZE], o[RSAENH_MAX_BLOCK_SIZE];
2120 DWORD dwEncryptedLen, i, j, k;
2122 TRACE("(hProv=%08lx, hKey=%08lx, hHash=%08lx, Final=%d, dwFlags=%08x, pbData=%p, "
2123 "pdwDataLen=%p, dwBufLen=%d)\n", hProv, hKey, hHash, Final, dwFlags, pbData, pdwDataLen,
2124 dwBufLen);
2126 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2128 SetLastError(NTE_BAD_UID);
2129 return FALSE;
2132 if (dwFlags)
2134 SetLastError(NTE_BAD_FLAGS);
2135 return FALSE;
2138 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
2140 SetLastError(NTE_BAD_KEY);
2141 return FALSE;
2144 if (pCryptKey->dwState == RSAENH_KEYSTATE_IDLE)
2145 pCryptKey->dwState = RSAENH_KEYSTATE_ENCRYPTING;
2147 if (pCryptKey->dwState != RSAENH_KEYSTATE_ENCRYPTING)
2149 SetLastError(NTE_BAD_DATA);
2150 return FALSE;
2153 if (is_valid_handle(&handle_table, hHash, RSAENH_MAGIC_HASH)) {
2154 if (!RSAENH_CPHashData(hProv, hHash, pbData, *pdwDataLen, 0)) return FALSE;
2157 if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_BLOCK) {
2158 if (!Final && (*pdwDataLen % pCryptKey->dwBlockLen)) {
2159 SetLastError(NTE_BAD_DATA);
2160 return FALSE;
2163 dwEncryptedLen = (*pdwDataLen/pCryptKey->dwBlockLen+(Final?1:0))*pCryptKey->dwBlockLen;
2165 if (pbData == NULL) {
2166 *pdwDataLen = dwEncryptedLen;
2167 return TRUE;
2169 else if (dwEncryptedLen > dwBufLen) {
2170 *pdwDataLen = dwEncryptedLen;
2171 SetLastError(ERROR_MORE_DATA);
2172 return FALSE;
2175 /* Pad final block with length bytes */
2176 for (i=*pdwDataLen; i<dwEncryptedLen; i++) pbData[i] = dwEncryptedLen - *pdwDataLen;
2177 *pdwDataLen = dwEncryptedLen;
2179 for (i=0, in=pbData; i<*pdwDataLen; i+=pCryptKey->dwBlockLen, in+=pCryptKey->dwBlockLen) {
2180 switch (pCryptKey->dwMode) {
2181 case CRYPT_MODE_ECB:
2182 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out,
2183 RSAENH_ENCRYPT);
2184 break;
2186 case CRYPT_MODE_CBC:
2187 for (j=0; j<pCryptKey->dwBlockLen; j++) in[j] ^= pCryptKey->abChainVector[j];
2188 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out,
2189 RSAENH_ENCRYPT);
2190 memcpy(pCryptKey->abChainVector, out, pCryptKey->dwBlockLen);
2191 break;
2193 case CRYPT_MODE_CFB:
2194 for (j=0; j<pCryptKey->dwBlockLen; j++) {
2195 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context,
2196 pCryptKey->abChainVector, o, RSAENH_ENCRYPT);
2197 out[j] = in[j] ^ o[0];
2198 for (k=0; k<pCryptKey->dwBlockLen-1; k++)
2199 pCryptKey->abChainVector[k] = pCryptKey->abChainVector[k+1];
2200 pCryptKey->abChainVector[k] = out[j];
2202 break;
2204 default:
2205 SetLastError(NTE_BAD_ALGID);
2206 return FALSE;
2208 memcpy(in, out, pCryptKey->dwBlockLen);
2210 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_STREAM) {
2211 if (pbData == NULL) {
2212 *pdwDataLen = dwBufLen;
2213 return TRUE;
2215 encrypt_stream_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, *pdwDataLen);
2216 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_RSA) {
2217 if (pCryptKey->aiAlgid == CALG_RSA_SIGN) {
2218 SetLastError(NTE_BAD_KEY);
2219 return FALSE;
2221 if (!pbData) {
2222 *pdwDataLen = pCryptKey->dwBlockLen;
2223 return TRUE;
2225 if (dwBufLen < pCryptKey->dwBlockLen) {
2226 SetLastError(ERROR_MORE_DATA);
2227 return FALSE;
2229 if (!pad_data(pbData, *pdwDataLen, pbData, pCryptKey->dwBlockLen, dwFlags)) return FALSE;
2230 encrypt_block_impl(pCryptKey->aiAlgid, PK_PUBLIC, &pCryptKey->context, pbData, pbData, RSAENH_ENCRYPT);
2231 *pdwDataLen = pCryptKey->dwBlockLen;
2232 Final = TRUE;
2233 } else {
2234 SetLastError(NTE_BAD_TYPE);
2235 return FALSE;
2238 if (Final) setup_key(pCryptKey);
2240 return TRUE;
2243 /******************************************************************************
2244 * CPDecrypt (RSAENH.@)
2246 * Decrypt data.
2248 * PARAMS
2249 * hProv [I] The key container hKey and hHash belong to.
2250 * hKey [I] The key used to decrypt the data.
2251 * hHash [I] An optional hash object for parallel hashing. See notes.
2252 * Final [I] Indicates if this is the last block of data to decrypt.
2253 * dwFlags [I] Currently no flags defined. Must be zero.
2254 * pbData [I/O] Pointer to the data to decrypt. Plaintext will also be stored there.
2255 * pdwDataLen [I/O] I: Length of ciphertext, O: Length of plaintext.
2257 * RETURNS
2258 * Success: TRUE.
2259 * Failure: FALSE.
2261 * NOTES
2262 * If a hash object handle is provided in hHash, it will be updated with the plaintext.
2263 * This is useful for message signatures.
2265 * This function uses the standard WINAPI protocol for querying data of dynamic length.
2267 BOOL WINAPI RSAENH_CPDecrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
2268 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
2270 CRYPTKEY *pCryptKey;
2271 BYTE *in, out[RSAENH_MAX_BLOCK_SIZE], o[RSAENH_MAX_BLOCK_SIZE];
2272 DWORD i, j, k;
2273 DWORD dwMax;
2275 TRACE("(hProv=%08lx, hKey=%08lx, hHash=%08lx, Final=%d, dwFlags=%08x, pbData=%p, "
2276 "pdwDataLen=%p)\n", hProv, hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
2278 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2280 SetLastError(NTE_BAD_UID);
2281 return FALSE;
2284 if (dwFlags)
2286 SetLastError(NTE_BAD_FLAGS);
2287 return FALSE;
2290 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
2292 SetLastError(NTE_BAD_KEY);
2293 return FALSE;
2296 if (pCryptKey->dwState == RSAENH_KEYSTATE_IDLE)
2297 pCryptKey->dwState = RSAENH_KEYSTATE_ENCRYPTING;
2299 if (pCryptKey->dwState != RSAENH_KEYSTATE_ENCRYPTING)
2301 SetLastError(NTE_BAD_DATA);
2302 return FALSE;
2305 dwMax=*pdwDataLen;
2307 if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_BLOCK) {
2308 for (i=0, in=pbData; i<*pdwDataLen; i+=pCryptKey->dwBlockLen, in+=pCryptKey->dwBlockLen) {
2309 switch (pCryptKey->dwMode) {
2310 case CRYPT_MODE_ECB:
2311 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out,
2312 RSAENH_DECRYPT);
2313 break;
2315 case CRYPT_MODE_CBC:
2316 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out,
2317 RSAENH_DECRYPT);
2318 for (j=0; j<pCryptKey->dwBlockLen; j++) out[j] ^= pCryptKey->abChainVector[j];
2319 memcpy(pCryptKey->abChainVector, in, pCryptKey->dwBlockLen);
2320 break;
2322 case CRYPT_MODE_CFB:
2323 for (j=0; j<pCryptKey->dwBlockLen; j++) {
2324 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context,
2325 pCryptKey->abChainVector, o, RSAENH_ENCRYPT);
2326 out[j] = in[j] ^ o[0];
2327 for (k=0; k<pCryptKey->dwBlockLen-1; k++)
2328 pCryptKey->abChainVector[k] = pCryptKey->abChainVector[k+1];
2329 pCryptKey->abChainVector[k] = in[j];
2331 break;
2333 default:
2334 SetLastError(NTE_BAD_ALGID);
2335 return FALSE;
2337 memcpy(in, out, pCryptKey->dwBlockLen);
2339 if (Final) {
2340 if (pbData[*pdwDataLen-1] &&
2341 pbData[*pdwDataLen-1] <= pCryptKey->dwBlockLen &&
2342 pbData[*pdwDataLen-1] <= *pdwDataLen) {
2343 BOOL padOkay = TRUE;
2345 /* check that every bad byte has the same value */
2346 for (i = 1; padOkay && i < pbData[*pdwDataLen-1]; i++)
2347 if (pbData[*pdwDataLen - i - 1] != pbData[*pdwDataLen - 1])
2348 padOkay = FALSE;
2349 if (padOkay)
2350 *pdwDataLen -= pbData[*pdwDataLen-1];
2351 else {
2352 SetLastError(NTE_BAD_DATA);
2353 return FALSE;
2356 else {
2357 SetLastError(NTE_BAD_DATA);
2358 return FALSE;
2362 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_STREAM) {
2363 encrypt_stream_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, *pdwDataLen);
2364 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_RSA) {
2365 if (pCryptKey->aiAlgid == CALG_RSA_SIGN) {
2366 SetLastError(NTE_BAD_KEY);
2367 return FALSE;
2369 encrypt_block_impl(pCryptKey->aiAlgid, PK_PRIVATE, &pCryptKey->context, pbData, pbData, RSAENH_DECRYPT);
2370 if (!unpad_data(pbData, pCryptKey->dwBlockLen, pbData, pdwDataLen, dwFlags)) return FALSE;
2371 Final = TRUE;
2372 } else {
2373 SetLastError(NTE_BAD_TYPE);
2374 return FALSE;
2377 if (Final) setup_key(pCryptKey);
2379 if (is_valid_handle(&handle_table, hHash, RSAENH_MAGIC_HASH)) {
2380 if (*pdwDataLen>dwMax ||
2381 !RSAENH_CPHashData(hProv, hHash, pbData, *pdwDataLen, 0)) return FALSE;
2384 return TRUE;
2387 static BOOL crypt_export_simple(CRYPTKEY *pCryptKey, CRYPTKEY *pPubKey,
2388 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
2390 BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData;
2391 ALG_ID *pAlgid = (ALG_ID*)(pBlobHeader+1);
2392 DWORD dwDataLen;
2394 if (!(GET_ALG_CLASS(pCryptKey->aiAlgid)&(ALG_CLASS_DATA_ENCRYPT|ALG_CLASS_MSG_ENCRYPT))) {
2395 SetLastError(NTE_BAD_KEY); /* FIXME: error code? */
2396 return FALSE;
2399 dwDataLen = sizeof(BLOBHEADER) + sizeof(ALG_ID) + pPubKey->dwBlockLen;
2400 if (pbData) {
2401 if (*pdwDataLen < dwDataLen) {
2402 SetLastError(ERROR_MORE_DATA);
2403 *pdwDataLen = dwDataLen;
2404 return FALSE;
2407 pBlobHeader->bType = SIMPLEBLOB;
2408 pBlobHeader->bVersion = CUR_BLOB_VERSION;
2409 pBlobHeader->reserved = 0;
2410 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
2412 *pAlgid = pPubKey->aiAlgid;
2414 if (!pad_data(pCryptKey->abKeyValue, pCryptKey->dwKeyLen, (BYTE*)(pAlgid+1),
2415 pPubKey->dwBlockLen, dwFlags))
2417 return FALSE;
2420 encrypt_block_impl(pPubKey->aiAlgid, PK_PUBLIC, &pPubKey->context, (BYTE*)(pAlgid+1),
2421 (BYTE*)(pAlgid+1), RSAENH_ENCRYPT);
2423 *pdwDataLen = dwDataLen;
2424 return TRUE;
2427 static BOOL crypt_export_public_key(CRYPTKEY *pCryptKey, BYTE *pbData,
2428 DWORD *pdwDataLen)
2430 BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData;
2431 RSAPUBKEY *pRSAPubKey = (RSAPUBKEY*)(pBlobHeader+1);
2432 DWORD dwDataLen;
2434 if ((pCryptKey->aiAlgid != CALG_RSA_KEYX) && (pCryptKey->aiAlgid != CALG_RSA_SIGN)) {
2435 SetLastError(NTE_BAD_KEY);
2436 return FALSE;
2439 dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + pCryptKey->dwKeyLen;
2440 if (pbData) {
2441 if (*pdwDataLen < dwDataLen) {
2442 SetLastError(ERROR_MORE_DATA);
2443 *pdwDataLen = dwDataLen;
2444 return FALSE;
2447 pBlobHeader->bType = PUBLICKEYBLOB;
2448 pBlobHeader->bVersion = CUR_BLOB_VERSION;
2449 pBlobHeader->reserved = 0;
2450 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
2452 pRSAPubKey->magic = RSAENH_MAGIC_RSA1;
2453 pRSAPubKey->bitlen = pCryptKey->dwKeyLen << 3;
2455 export_public_key_impl((BYTE*)(pRSAPubKey+1), &pCryptKey->context,
2456 pCryptKey->dwKeyLen, &pRSAPubKey->pubexp);
2458 *pdwDataLen = dwDataLen;
2459 return TRUE;
2462 static BOOL crypt_export_private_key(CRYPTKEY *pCryptKey, BOOL force,
2463 BYTE *pbData, DWORD *pdwDataLen)
2465 BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData;
2466 RSAPUBKEY *pRSAPubKey = (RSAPUBKEY*)(pBlobHeader+1);
2467 DWORD dwDataLen;
2469 if ((pCryptKey->aiAlgid != CALG_RSA_KEYX) && (pCryptKey->aiAlgid != CALG_RSA_SIGN)) {
2470 SetLastError(NTE_BAD_KEY);
2471 return FALSE;
2473 if (!force && !(pCryptKey->dwPermissions & CRYPT_EXPORT))
2475 SetLastError(NTE_BAD_KEY_STATE);
2476 return FALSE;
2479 dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2480 2 * pCryptKey->dwKeyLen + 5 * ((pCryptKey->dwKeyLen + 1) >> 1);
2481 if (pbData) {
2482 if (*pdwDataLen < dwDataLen) {
2483 SetLastError(ERROR_MORE_DATA);
2484 *pdwDataLen = dwDataLen;
2485 return FALSE;
2488 pBlobHeader->bType = PRIVATEKEYBLOB;
2489 pBlobHeader->bVersion = CUR_BLOB_VERSION;
2490 pBlobHeader->reserved = 0;
2491 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
2493 pRSAPubKey->magic = RSAENH_MAGIC_RSA2;
2494 pRSAPubKey->bitlen = pCryptKey->dwKeyLen << 3;
2496 export_private_key_impl((BYTE*)(pRSAPubKey+1), &pCryptKey->context,
2497 pCryptKey->dwKeyLen, &pRSAPubKey->pubexp);
2499 *pdwDataLen = dwDataLen;
2500 return TRUE;
2503 static BOOL crypt_export_plaintext_key(CRYPTKEY *pCryptKey, BYTE *pbData,
2504 DWORD *pdwDataLen)
2506 BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData;
2507 DWORD *pKeyLen = (DWORD*)(pBlobHeader+1);
2508 BYTE *pbKey = (BYTE*)(pKeyLen+1);
2509 DWORD dwDataLen;
2511 dwDataLen = sizeof(BLOBHEADER) + sizeof(DWORD) + pCryptKey->dwKeyLen;
2512 if (pbData) {
2513 if (*pdwDataLen < dwDataLen) {
2514 SetLastError(ERROR_MORE_DATA);
2515 *pdwDataLen = dwDataLen;
2516 return FALSE;
2519 pBlobHeader->bType = PLAINTEXTKEYBLOB;
2520 pBlobHeader->bVersion = CUR_BLOB_VERSION;
2521 pBlobHeader->reserved = 0;
2522 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
2524 *pKeyLen = pCryptKey->dwKeyLen;
2525 memcpy(pbKey, &pCryptKey->abKeyValue, pCryptKey->dwKeyLen);
2527 *pdwDataLen = dwDataLen;
2528 return TRUE;
2530 /******************************************************************************
2531 * crypt_export_key [Internal]
2533 * Export a key into a binary large object (BLOB). Called by CPExportKey and
2534 * by store_key_pair.
2536 * PARAMS
2537 * pCryptKey [I] Key to be exported.
2538 * hPubKey [I] Key used to encrypt sensitive BLOB data.
2539 * dwBlobType [I] SIMPLEBLOB, PUBLICKEYBLOB or PRIVATEKEYBLOB.
2540 * dwFlags [I] Currently none defined.
2541 * force [I] If TRUE, the key is written no matter what the key's
2542 * permissions are. Otherwise the key's permissions are
2543 * checked before exporting.
2544 * pbData [O] Pointer to a buffer where the BLOB will be written to.
2545 * pdwDataLen [I/O] I: Size of buffer at pbData, O: Size of BLOB
2547 * RETURNS
2548 * Success: TRUE.
2549 * Failure: FALSE.
2551 static BOOL crypt_export_key(CRYPTKEY *pCryptKey, HCRYPTKEY hPubKey,
2552 DWORD dwBlobType, DWORD dwFlags, BOOL force,
2553 BYTE *pbData, DWORD *pdwDataLen)
2555 CRYPTKEY *pPubKey;
2557 if (dwFlags & CRYPT_SSL2_FALLBACK) {
2558 if (pCryptKey->aiAlgid != CALG_SSL2_MASTER) {
2559 SetLastError(NTE_BAD_KEY);
2560 return FALSE;
2564 switch ((BYTE)dwBlobType)
2566 case SIMPLEBLOB:
2567 if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey)){
2568 SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error_code? */
2569 return FALSE;
2571 return crypt_export_simple(pCryptKey, pPubKey, dwFlags, pbData,
2572 pdwDataLen);
2574 case PUBLICKEYBLOB:
2575 if (is_valid_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY)) {
2576 SetLastError(NTE_BAD_KEY); /* FIXME: error code? */
2577 return FALSE;
2580 return crypt_export_public_key(pCryptKey, pbData, pdwDataLen);
2582 case PRIVATEKEYBLOB:
2583 return crypt_export_private_key(pCryptKey, force, pbData, pdwDataLen);
2585 case PLAINTEXTKEYBLOB:
2586 return crypt_export_plaintext_key(pCryptKey, pbData, pdwDataLen);
2588 default:
2589 SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */
2590 return FALSE;
2594 /******************************************************************************
2595 * CPExportKey (RSAENH.@)
2597 * Export a key into a binary large object (BLOB).
2599 * PARAMS
2600 * hProv [I] Key container from which a key is to be exported.
2601 * hKey [I] Key to be exported.
2602 * hPubKey [I] Key used to encrypt sensitive BLOB data.
2603 * dwBlobType [I] SIMPLEBLOB, PUBLICKEYBLOB or PRIVATEKEYBLOB.
2604 * dwFlags [I] Currently none defined.
2605 * pbData [O] Pointer to a buffer where the BLOB will be written to.
2606 * pdwDataLen [I/O] I: Size of buffer at pbData, O: Size of BLOB
2608 * RETURNS
2609 * Success: TRUE.
2610 * Failure: FALSE.
2612 BOOL WINAPI RSAENH_CPExportKey(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubKey,
2613 DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
2615 CRYPTKEY *pCryptKey;
2617 TRACE("(hProv=%08lx, hKey=%08lx, hPubKey=%08lx, dwBlobType=%08x, dwFlags=%08x, pbData=%p,"
2618 "pdwDataLen=%p)\n", hProv, hKey, hPubKey, dwBlobType, dwFlags, pbData, pdwDataLen);
2620 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2622 SetLastError(NTE_BAD_UID);
2623 return FALSE;
2626 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
2628 SetLastError(NTE_BAD_KEY);
2629 return FALSE;
2632 return crypt_export_key(pCryptKey, hPubKey, dwBlobType, dwFlags, FALSE,
2633 pbData, pdwDataLen);
2636 /******************************************************************************
2637 * release_and_install_key [Internal]
2639 * Release an existing key, if present, and replaces it with a new one.
2641 * PARAMS
2642 * hProv [I] Key container into which the key is to be imported.
2643 * src [I] Key which will replace *dest
2644 * dest [I] Points to key to be released and replaced with src
2645 * fStoreKey [I] If TRUE, the newly installed key is stored to the registry.
2647 static void release_and_install_key(HCRYPTPROV hProv, HCRYPTKEY src,
2648 HCRYPTKEY *dest, DWORD fStoreKey)
2650 RSAENH_CPDestroyKey(hProv, *dest);
2651 copy_handle(&handle_table, src, RSAENH_MAGIC_KEY, dest);
2652 if (fStoreKey)
2654 KEYCONTAINER *pKeyContainer;
2656 if (lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
2657 (OBJECTHDR**)&pKeyContainer))
2659 store_key_container_keys(pKeyContainer);
2660 store_key_container_permissions(pKeyContainer);
2665 /******************************************************************************
2666 * import_private_key [Internal]
2668 * Import a BLOB'ed private key into a key container.
2670 * PARAMS
2671 * hProv [I] Key container into which the private key is to be imported.
2672 * pbData [I] Pointer to a buffer which holds the private key BLOB.
2673 * dwDataLen [I] Length of data in buffer at pbData.
2674 * dwFlags [I] One of:
2675 * CRYPT_EXPORTABLE: the imported key is marked exportable
2676 * fStoreKey [I] If TRUE, the imported key is stored to the registry.
2677 * phKey [O] Handle to the imported key.
2680 * NOTES
2681 * Assumes the caller has already checked the BLOBHEADER at pbData to ensure
2682 * it's a PRIVATEKEYBLOB.
2684 * RETURNS
2685 * Success: TRUE.
2686 * Failure: FALSE.
2688 static BOOL import_private_key(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen,
2689 DWORD dwFlags, BOOL fStoreKey, HCRYPTKEY *phKey)
2691 KEYCONTAINER *pKeyContainer;
2692 CRYPTKEY *pCryptKey;
2693 CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData;
2694 CONST RSAPUBKEY *pRSAPubKey = (CONST RSAPUBKEY*)(pBlobHeader+1);
2695 BOOL ret;
2697 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
2698 (OBJECTHDR**)&pKeyContainer))
2700 SetLastError(NTE_BAD_UID);
2701 return FALSE;
2704 if ((dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY)) ||
2705 (pRSAPubKey->magic != RSAENH_MAGIC_RSA2) ||
2706 (dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2707 (2 * pRSAPubKey->bitlen >> 3) + (5 * ((pRSAPubKey->bitlen+8)>>4))))
2709 SetLastError(NTE_BAD_DATA);
2710 return FALSE;
2713 *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey);
2714 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
2715 setup_key(pCryptKey);
2716 ret = import_private_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context,
2717 pRSAPubKey->bitlen/8, pRSAPubKey->pubexp);
2718 if (ret) {
2719 if (dwFlags & CRYPT_EXPORTABLE)
2720 pCryptKey->dwPermissions |= CRYPT_EXPORT;
2721 switch (pBlobHeader->aiKeyAlg)
2723 case AT_SIGNATURE:
2724 case CALG_RSA_SIGN:
2725 TRACE("installing signing key\n");
2726 release_and_install_key(hProv, *phKey, &pKeyContainer->hSignatureKeyPair,
2727 fStoreKey);
2728 break;
2729 case AT_KEYEXCHANGE:
2730 case CALG_RSA_KEYX:
2731 TRACE("installing key exchange key\n");
2732 release_and_install_key(hProv, *phKey, &pKeyContainer->hKeyExchangeKeyPair,
2733 fStoreKey);
2734 break;
2737 return ret;
2740 /******************************************************************************
2741 * import_public_key [Internal]
2743 * Import a BLOB'ed public key into a key container.
2745 * PARAMS
2746 * hProv [I] Key container into which the public key is to be imported.
2747 * pbData [I] Pointer to a buffer which holds the public key BLOB.
2748 * dwDataLen [I] Length of data in buffer at pbData.
2749 * dwFlags [I] One of:
2750 * CRYPT_EXPORTABLE: the imported key is marked exportable
2751 * fStoreKey [I] If TRUE, the imported key is stored to the registry.
2752 * phKey [O] Handle to the imported key.
2755 * NOTES
2756 * Assumes the caller has already checked the BLOBHEADER at pbData to ensure
2757 * it's a PUBLICKEYBLOB.
2759 * RETURNS
2760 * Success: TRUE.
2761 * Failure: FALSE.
2763 static BOOL import_public_key(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen,
2764 DWORD dwFlags, BOOL fStoreKey, HCRYPTKEY *phKey)
2766 KEYCONTAINER *pKeyContainer;
2767 CRYPTKEY *pCryptKey;
2768 CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData;
2769 CONST RSAPUBKEY *pRSAPubKey = (CONST RSAPUBKEY*)(pBlobHeader+1);
2770 ALG_ID algID;
2771 BOOL ret;
2773 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
2774 (OBJECTHDR**)&pKeyContainer))
2776 SetLastError(NTE_BAD_UID);
2777 return FALSE;
2780 if ((dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY)) ||
2781 (pRSAPubKey->magic != RSAENH_MAGIC_RSA1) ||
2782 (dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + (pRSAPubKey->bitlen >> 3)))
2784 SetLastError(NTE_BAD_DATA);
2785 return FALSE;
2788 /* Since this is a public key blob, only the public key is
2789 * available, so only signature verification is possible.
2791 algID = pBlobHeader->aiKeyAlg;
2792 *phKey = new_key(hProv, algID, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey);
2793 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
2794 setup_key(pCryptKey);
2795 ret = import_public_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context,
2796 pRSAPubKey->bitlen >> 3, pRSAPubKey->pubexp);
2797 if (ret) {
2798 if (dwFlags & CRYPT_EXPORTABLE)
2799 pCryptKey->dwPermissions |= CRYPT_EXPORT;
2800 switch (pBlobHeader->aiKeyAlg)
2802 case AT_KEYEXCHANGE:
2803 case CALG_RSA_KEYX:
2804 TRACE("installing public key\n");
2805 release_and_install_key(hProv, *phKey, &pKeyContainer->hKeyExchangeKeyPair,
2806 fStoreKey);
2807 break;
2810 return ret;
2813 /******************************************************************************
2814 * import_symmetric_key [Internal]
2816 * Import a BLOB'ed symmetric key into a key container.
2818 * PARAMS
2819 * hProv [I] Key container into which the symmetric key is to be imported.
2820 * pbData [I] Pointer to a buffer which holds the symmetric key BLOB.
2821 * dwDataLen [I] Length of data in buffer at pbData.
2822 * hPubKey [I] Key used to decrypt sensitive BLOB data.
2823 * dwFlags [I] One of:
2824 * CRYPT_EXPORTABLE: the imported key is marked exportable
2825 * phKey [O] Handle to the imported key.
2828 * NOTES
2829 * Assumes the caller has already checked the BLOBHEADER at pbData to ensure
2830 * it's a SIMPLEBLOB.
2832 * RETURNS
2833 * Success: TRUE.
2834 * Failure: FALSE.
2836 static BOOL import_symmetric_key(HCRYPTPROV hProv, CONST BYTE *pbData,
2837 DWORD dwDataLen, HCRYPTKEY hPubKey,
2838 DWORD dwFlags, HCRYPTKEY *phKey)
2840 CRYPTKEY *pCryptKey, *pPubKey;
2841 CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData;
2842 CONST ALG_ID *pAlgid = (CONST ALG_ID*)(pBlobHeader+1);
2843 CONST BYTE *pbKeyStream = (CONST BYTE*)(pAlgid + 1);
2844 BYTE *pbDecrypted;
2845 DWORD dwKeyLen;
2847 if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey) ||
2848 pPubKey->aiAlgid != CALG_RSA_KEYX)
2850 SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error code? */
2851 return FALSE;
2854 if (dwDataLen < sizeof(BLOBHEADER)+sizeof(ALG_ID)+pPubKey->dwBlockLen)
2856 SetLastError(NTE_BAD_DATA); /* FIXME: error code */
2857 return FALSE;
2860 pbDecrypted = HeapAlloc(GetProcessHeap(), 0, pPubKey->dwBlockLen);
2861 if (!pbDecrypted) return FALSE;
2862 encrypt_block_impl(pPubKey->aiAlgid, PK_PRIVATE, &pPubKey->context, pbKeyStream, pbDecrypted,
2863 RSAENH_DECRYPT);
2865 dwKeyLen = RSAENH_MAX_KEY_SIZE;
2866 if (!unpad_data(pbDecrypted, pPubKey->dwBlockLen, pbDecrypted, &dwKeyLen, dwFlags)) {
2867 HeapFree(GetProcessHeap(), 0, pbDecrypted);
2868 return FALSE;
2871 *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, dwKeyLen<<19, &pCryptKey);
2872 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE)
2874 HeapFree(GetProcessHeap(), 0, pbDecrypted);
2875 return FALSE;
2877 memcpy(pCryptKey->abKeyValue, pbDecrypted, dwKeyLen);
2878 HeapFree(GetProcessHeap(), 0, pbDecrypted);
2879 setup_key(pCryptKey);
2880 if (dwFlags & CRYPT_EXPORTABLE)
2881 pCryptKey->dwPermissions |= CRYPT_EXPORT;
2882 return TRUE;
2885 /******************************************************************************
2886 * import_plaintext_key [Internal]
2888 * Import a plaintext key into a key container.
2890 * PARAMS
2891 * hProv [I] Key container into which the symmetric key is to be imported.
2892 * pbData [I] Pointer to a buffer which holds the plaintext key BLOB.
2893 * dwDataLen [I] Length of data in buffer at pbData.
2894 * dwFlags [I] One of:
2895 * CRYPT_EXPORTABLE: the imported key is marked exportable
2896 * phKey [O] Handle to the imported key.
2899 * NOTES
2900 * Assumes the caller has already checked the BLOBHEADER at pbData to ensure
2901 * it's a PLAINTEXTKEYBLOB.
2903 * RETURNS
2904 * Success: TRUE.
2905 * Failure: FALSE.
2907 static BOOL import_plaintext_key(HCRYPTPROV hProv, CONST BYTE *pbData,
2908 DWORD dwDataLen, DWORD dwFlags,
2909 HCRYPTKEY *phKey)
2911 CRYPTKEY *pCryptKey;
2912 CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData;
2913 CONST DWORD *pKeyLen = (CONST DWORD *)(pBlobHeader + 1);
2914 CONST BYTE *pbKeyStream = (CONST BYTE*)(pKeyLen + 1);
2916 if (dwDataLen < sizeof(BLOBHEADER)+sizeof(DWORD)+*pKeyLen)
2918 SetLastError(NTE_BAD_DATA); /* FIXME: error code */
2919 return FALSE;
2922 *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, *pKeyLen<<19, &pCryptKey);
2923 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE)
2924 return FALSE;
2925 memcpy(pCryptKey->abKeyValue, pbKeyStream, *pKeyLen);
2926 setup_key(pCryptKey);
2927 if (dwFlags & CRYPT_EXPORTABLE)
2928 pCryptKey->dwPermissions |= CRYPT_EXPORT;
2929 return TRUE;
2932 /******************************************************************************
2933 * import_key [Internal]
2935 * Import a BLOB'ed key into a key container, optionally storing the key's
2936 * value to the registry.
2938 * PARAMS
2939 * hProv [I] Key container into which the key is to be imported.
2940 * pbData [I] Pointer to a buffer which holds the BLOB.
2941 * dwDataLen [I] Length of data in buffer at pbData.
2942 * hPubKey [I] Key used to decrypt sensitive BLOB data.
2943 * dwFlags [I] One of:
2944 * CRYPT_EXPORTABLE: the imported key is marked exportable
2945 * fStoreKey [I] If TRUE, the imported key is stored to the registry.
2946 * phKey [O] Handle to the imported key.
2948 * RETURNS
2949 * Success: TRUE.
2950 * Failure: FALSE.
2952 static BOOL import_key(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen,
2953 HCRYPTKEY hPubKey, DWORD dwFlags, BOOL fStoreKey,
2954 HCRYPTKEY *phKey)
2956 KEYCONTAINER *pKeyContainer;
2957 CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData;
2959 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
2960 (OBJECTHDR**)&pKeyContainer))
2962 SetLastError(NTE_BAD_UID);
2963 return FALSE;
2966 if (dwDataLen < sizeof(BLOBHEADER) ||
2967 pBlobHeader->bVersion != CUR_BLOB_VERSION ||
2968 pBlobHeader->reserved != 0)
2970 TRACE("bVersion = %d, reserved = %d\n", pBlobHeader->bVersion,
2971 pBlobHeader->reserved);
2972 SetLastError(NTE_BAD_DATA);
2973 return FALSE;
2976 /* If this is a verify-only context, the key is not persisted regardless of
2977 * fStoreKey's original value.
2979 fStoreKey = fStoreKey && !(dwFlags & CRYPT_VERIFYCONTEXT);
2980 TRACE("blob type: %x\n", pBlobHeader->bType);
2981 switch (pBlobHeader->bType)
2983 case PRIVATEKEYBLOB:
2984 return import_private_key(hProv, pbData, dwDataLen, dwFlags,
2985 fStoreKey, phKey);
2987 case PUBLICKEYBLOB:
2988 return import_public_key(hProv, pbData, dwDataLen, dwFlags,
2989 fStoreKey, phKey);
2991 case SIMPLEBLOB:
2992 return import_symmetric_key(hProv, pbData, dwDataLen, hPubKey,
2993 dwFlags, phKey);
2995 case PLAINTEXTKEYBLOB:
2996 return import_plaintext_key(hProv, pbData, dwDataLen, dwFlags,
2997 phKey);
2999 default:
3000 SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */
3001 return FALSE;
3005 /******************************************************************************
3006 * CPImportKey (RSAENH.@)
3008 * Import a BLOB'ed key into a key container.
3010 * PARAMS
3011 * hProv [I] Key container into which the key is to be imported.
3012 * pbData [I] Pointer to a buffer which holds the BLOB.
3013 * dwDataLen [I] Length of data in buffer at pbData.
3014 * hPubKey [I] Key used to decrypt sensitive BLOB data.
3015 * dwFlags [I] One of:
3016 * CRYPT_EXPORTABLE: the imported key is marked exportable
3017 * phKey [O] Handle to the imported key.
3019 * RETURNS
3020 * Success: TRUE.
3021 * Failure: FALSE.
3023 BOOL WINAPI RSAENH_CPImportKey(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen,
3024 HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
3026 TRACE("(hProv=%08lx, pbData=%p, dwDataLen=%d, hPubKey=%08lx, dwFlags=%08x, phKey=%p)\n",
3027 hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
3029 if (dwFlags & CRYPT_IPSEC_HMAC_KEY)
3031 FIXME("unimplemented for CRYPT_IPSEC_HMAC_KEY\n");
3032 SetLastError(NTE_BAD_FLAGS);
3033 return FALSE;
3035 return import_key(hProv, pbData, dwDataLen, hPubKey, dwFlags, TRUE, phKey);
3038 /******************************************************************************
3039 * CPGenKey (RSAENH.@)
3041 * Generate a key in the key container
3043 * PARAMS
3044 * hProv [I] Key container for which a key is to be generated.
3045 * Algid [I] Crypto algorithm identifier for the key to be generated.
3046 * dwFlags [I] Upper 16 bits: Binary length of key. Lower 16 bits: Flags. See Notes
3047 * phKey [O] Handle to the generated key.
3049 * RETURNS
3050 * Success: TRUE.
3051 * Failure: FALSE.
3053 * FIXME
3054 * Flags currently not considered.
3056 * NOTES
3057 * Private key-exchange- and signature-keys can be generated with Algid AT_KEYEXCHANGE
3058 * and AT_SIGNATURE values.
3060 BOOL WINAPI RSAENH_CPGenKey(HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
3062 KEYCONTAINER *pKeyContainer;
3063 CRYPTKEY *pCryptKey;
3065 TRACE("(hProv=%08lx, aiAlgid=%d, dwFlags=%08x, phKey=%p)\n", hProv, Algid, dwFlags, phKey);
3067 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
3068 (OBJECTHDR**)&pKeyContainer))
3070 /* MSDN: hProv not containing valid context handle */
3071 SetLastError(NTE_BAD_UID);
3072 return FALSE;
3075 switch (Algid)
3077 case AT_SIGNATURE:
3078 case CALG_RSA_SIGN:
3079 *phKey = new_key(hProv, CALG_RSA_SIGN, dwFlags, &pCryptKey);
3080 if (pCryptKey) {
3081 new_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen);
3082 setup_key(pCryptKey);
3083 release_and_install_key(hProv, *phKey,
3084 &pKeyContainer->hSignatureKeyPair,
3085 FALSE);
3087 break;
3089 case AT_KEYEXCHANGE:
3090 case CALG_RSA_KEYX:
3091 *phKey = new_key(hProv, CALG_RSA_KEYX, dwFlags, &pCryptKey);
3092 if (pCryptKey) {
3093 new_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen);
3094 setup_key(pCryptKey);
3095 release_and_install_key(hProv, *phKey,
3096 &pKeyContainer->hKeyExchangeKeyPair,
3097 FALSE);
3099 break;
3101 case CALG_RC2:
3102 case CALG_RC4:
3103 case CALG_DES:
3104 case CALG_3DES_112:
3105 case CALG_3DES:
3106 case CALG_AES:
3107 case CALG_AES_128:
3108 case CALG_AES_192:
3109 case CALG_AES_256:
3110 case CALG_PCT1_MASTER:
3111 case CALG_SSL2_MASTER:
3112 case CALG_SSL3_MASTER:
3113 case CALG_TLS1_MASTER:
3114 *phKey = new_key(hProv, Algid, dwFlags, &pCryptKey);
3115 if (pCryptKey) {
3116 gen_rand_impl(pCryptKey->abKeyValue, RSAENH_MAX_KEY_SIZE);
3117 switch (Algid) {
3118 case CALG_SSL3_MASTER:
3119 pCryptKey->abKeyValue[0] = RSAENH_SSL3_VERSION_MAJOR;
3120 pCryptKey->abKeyValue[1] = RSAENH_SSL3_VERSION_MINOR;
3121 break;
3123 case CALG_TLS1_MASTER:
3124 pCryptKey->abKeyValue[0] = RSAENH_TLS1_VERSION_MAJOR;
3125 pCryptKey->abKeyValue[1] = RSAENH_TLS1_VERSION_MINOR;
3126 break;
3128 setup_key(pCryptKey);
3130 break;
3132 default:
3133 /* MSDN: Algorithm not supported specified by Algid */
3134 SetLastError(NTE_BAD_ALGID);
3135 return FALSE;
3138 return *phKey != (HCRYPTKEY)INVALID_HANDLE_VALUE;
3141 /******************************************************************************
3142 * CPGenRandom (RSAENH.@)
3144 * Generate a random byte stream.
3146 * PARAMS
3147 * hProv [I] Key container that is used to generate random bytes.
3148 * dwLen [I] Specifies the number of requested random data bytes.
3149 * pbBuffer [O] Random bytes will be stored here.
3151 * RETURNS
3152 * Success: TRUE
3153 * Failure: FALSE
3155 BOOL WINAPI RSAENH_CPGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
3157 TRACE("(hProv=%08lx, dwLen=%d, pbBuffer=%p)\n", hProv, dwLen, pbBuffer);
3159 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
3161 /* MSDN: hProv not containing valid context handle */
3162 SetLastError(NTE_BAD_UID);
3163 return FALSE;
3166 return gen_rand_impl(pbBuffer, dwLen);
3169 /******************************************************************************
3170 * CPGetHashParam (RSAENH.@)
3172 * Query parameters of an hash object.
3174 * PARAMS
3175 * hProv [I] The kea container, which the hash belongs to.
3176 * hHash [I] The hash object that is to be queried.
3177 * dwParam [I] Specifies the parameter that is to be queried.
3178 * pbData [I] Pointer to the buffer where the parameter value will be stored.
3179 * pdwDataLen [I/O] I: Buffer length at pbData, O: Length of the parameter value.
3180 * dwFlags [I] None currently defined.
3182 * RETURNS
3183 * Success: TRUE
3184 * Failure: FALSE
3186 * NOTES
3187 * Valid dwParams are: HP_ALGID, HP_HASHSIZE, HP_HASHVALUE. The hash will be
3188 * finalized if HP_HASHVALUE is queried.
3190 BOOL WINAPI RSAENH_CPGetHashParam(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
3191 DWORD *pdwDataLen, DWORD dwFlags)
3193 CRYPTHASH *pCryptHash;
3195 TRACE("(hProv=%08lx, hHash=%08lx, dwParam=%08x, pbData=%p, pdwDataLen=%p, dwFlags=%08x)\n",
3196 hProv, hHash, dwParam, pbData, pdwDataLen, dwFlags);
3198 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
3200 SetLastError(NTE_BAD_UID);
3201 return FALSE;
3204 if (dwFlags)
3206 SetLastError(NTE_BAD_FLAGS);
3207 return FALSE;
3210 if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH,
3211 (OBJECTHDR**)&pCryptHash))
3213 SetLastError(NTE_BAD_HASH);
3214 return FALSE;
3217 if (!pdwDataLen)
3219 SetLastError(ERROR_INVALID_PARAMETER);
3220 return FALSE;
3223 switch (dwParam)
3225 case HP_ALGID:
3226 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptHash->aiAlgid,
3227 sizeof(ALG_ID));
3229 case HP_HASHSIZE:
3230 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptHash->dwHashSize,
3231 sizeof(DWORD));
3233 case HP_HASHVAL:
3234 if (pCryptHash->aiAlgid == CALG_TLS1PRF) {
3235 return tls1_prf(hProv, pCryptHash->hKey, &pCryptHash->tpPRFParams.blobLabel,
3236 &pCryptHash->tpPRFParams.blobSeed, pbData, *pdwDataLen);
3239 if ( pbData == NULL ) {
3240 *pdwDataLen = pCryptHash->dwHashSize;
3241 return TRUE;
3244 if (pbData && (pCryptHash->dwState != RSAENH_HASHSTATE_FINISHED))
3246 finalize_hash(pCryptHash);
3247 pCryptHash->dwState = RSAENH_HASHSTATE_FINISHED;
3250 return copy_param(pbData, pdwDataLen, pCryptHash->abHashValue,
3251 pCryptHash->dwHashSize);
3253 default:
3254 SetLastError(NTE_BAD_TYPE);
3255 return FALSE;
3259 /******************************************************************************
3260 * CPSetKeyParam (RSAENH.@)
3262 * Set a parameter of a key object
3264 * PARAMS
3265 * hProv [I] The key container to which the key belongs.
3266 * hKey [I] The key for which a parameter is to be set.
3267 * dwParam [I] Parameter type. See Notes.
3268 * pbData [I] Pointer to the parameter value.
3269 * dwFlags [I] Currently none defined.
3271 * RETURNS
3272 * Success: TRUE.
3273 * Failure: FALSE.
3275 * NOTES:
3276 * Defined dwParam types are:
3277 * - KP_MODE: Values MODE_CBC, MODE_ECB, MODE_CFB.
3278 * - KP_MODE_BITS: Shift width for cipher feedback mode. (Currently ignored by MS CSP's)
3279 * - KP_PERMISSIONS: Or'ed combination of CRYPT_ENCRYPT, CRYPT_DECRYPT,
3280 * CRYPT_EXPORT, CRYPT_READ, CRYPT_WRITE, CRYPT_MAC
3281 * - KP_IV: Initialization vector
3283 BOOL WINAPI RSAENH_CPSetKeyParam(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
3284 DWORD dwFlags)
3286 CRYPTKEY *pCryptKey;
3288 TRACE("(hProv=%08lx, hKey=%08lx, dwParam=%08x, pbData=%p, dwFlags=%08x)\n", hProv, hKey,
3289 dwParam, pbData, dwFlags);
3291 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
3293 SetLastError(NTE_BAD_UID);
3294 return FALSE;
3297 if (dwFlags) {
3298 SetLastError(NTE_BAD_FLAGS);
3299 return FALSE;
3302 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
3304 SetLastError(NTE_BAD_KEY);
3305 return FALSE;
3308 switch (dwParam) {
3309 case KP_PADDING:
3310 /* The MS providers only support PKCS5_PADDING */
3311 if (*(DWORD *)pbData != PKCS5_PADDING) {
3312 SetLastError(NTE_BAD_DATA);
3313 return FALSE;
3315 return TRUE;
3317 case KP_MODE:
3318 pCryptKey->dwMode = *(DWORD*)pbData;
3319 return TRUE;
3321 case KP_MODE_BITS:
3322 pCryptKey->dwModeBits = *(DWORD*)pbData;
3323 return TRUE;
3325 case KP_PERMISSIONS:
3327 DWORD perms = *(DWORD *)pbData;
3329 if ((perms & CRYPT_EXPORT) &&
3330 !(pCryptKey->dwPermissions & CRYPT_EXPORT))
3332 SetLastError(NTE_BAD_DATA);
3333 return FALSE;
3335 else if (!(perms & CRYPT_EXPORT) &&
3336 (pCryptKey->dwPermissions & CRYPT_EXPORT))
3338 /* Clearing the export permission appears to be ignored,
3339 * see tests.
3341 perms |= CRYPT_EXPORT;
3343 pCryptKey->dwPermissions = perms;
3344 return TRUE;
3347 case KP_IV:
3348 memcpy(pCryptKey->abInitVector, pbData, pCryptKey->dwBlockLen);
3349 setup_key(pCryptKey);
3350 return TRUE;
3352 case KP_SALT:
3353 switch (pCryptKey->aiAlgid) {
3354 case CALG_RC2:
3355 case CALG_RC4:
3356 if (!pbData)
3358 SetLastError(ERROR_INVALID_PARAMETER);
3359 return FALSE;
3361 /* MSDN: the base provider always sets eleven bytes of
3362 * salt value.
3364 memcpy(pCryptKey->abKeyValue + pCryptKey->dwKeyLen,
3365 pbData, 11);
3366 pCryptKey->dwSaltLen = 11;
3367 setup_key(pCryptKey);
3368 /* Strange but true: salt length reset to 0 after setting
3369 * it via KP_SALT.
3371 pCryptKey->dwSaltLen = 0;
3372 break;
3373 default:
3374 SetLastError(NTE_BAD_KEY);
3375 return FALSE;
3377 return TRUE;
3379 case KP_SALT_EX:
3381 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pbData;
3383 /* salt length can't be greater than 184 bits = 24 bytes */
3384 if (blob->cbData > 24)
3386 SetLastError(NTE_BAD_DATA);
3387 return FALSE;
3389 memcpy(pCryptKey->abKeyValue + pCryptKey->dwKeyLen, blob->pbData,
3390 blob->cbData);
3391 pCryptKey->dwSaltLen = blob->cbData;
3392 setup_key(pCryptKey);
3393 return TRUE;
3396 case KP_EFFECTIVE_KEYLEN:
3397 switch (pCryptKey->aiAlgid) {
3398 case CALG_RC2:
3399 if (!pbData)
3401 SetLastError(ERROR_INVALID_PARAMETER);
3402 return FALSE;
3404 else if (!*(DWORD *)pbData || *(DWORD *)pbData > 1024)
3406 SetLastError(NTE_BAD_DATA);
3407 return FALSE;
3409 else
3411 pCryptKey->dwEffectiveKeyLen = *(DWORD *)pbData;
3412 setup_key(pCryptKey);
3414 break;
3415 default:
3416 SetLastError(NTE_BAD_TYPE);
3417 return FALSE;
3419 return TRUE;
3421 case KP_SCHANNEL_ALG:
3422 switch (((PSCHANNEL_ALG)pbData)->dwUse) {
3423 case SCHANNEL_ENC_KEY:
3424 memcpy(&pCryptKey->siSChannelInfo.saEncAlg, pbData, sizeof(SCHANNEL_ALG));
3425 break;
3427 case SCHANNEL_MAC_KEY:
3428 memcpy(&pCryptKey->siSChannelInfo.saMACAlg, pbData, sizeof(SCHANNEL_ALG));
3429 break;
3431 default:
3432 SetLastError(NTE_FAIL); /* FIXME: error code */
3433 return FALSE;
3435 return TRUE;
3437 case KP_CLIENT_RANDOM:
3438 return copy_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom, (PCRYPT_DATA_BLOB)pbData);
3440 case KP_SERVER_RANDOM:
3441 return copy_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom, (PCRYPT_DATA_BLOB)pbData);
3443 default:
3444 SetLastError(NTE_BAD_TYPE);
3445 return FALSE;
3449 /******************************************************************************
3450 * CPGetKeyParam (RSAENH.@)
3452 * Query a key parameter.
3454 * PARAMS
3455 * hProv [I] The key container, which the key belongs to.
3456 * hHash [I] The key object that is to be queried.
3457 * dwParam [I] Specifies the parameter that is to be queried.
3458 * pbData [I] Pointer to the buffer where the parameter value will be stored.
3459 * pdwDataLen [I/O] I: Buffer length at pbData, O: Length of the parameter value.
3460 * dwFlags [I] None currently defined.
3462 * RETURNS
3463 * Success: TRUE
3464 * Failure: FALSE
3466 * NOTES
3467 * Defined dwParam types are:
3468 * - KP_MODE: Values MODE_CBC, MODE_ECB, MODE_CFB.
3469 * - KP_MODE_BITS: Shift width for cipher feedback mode.
3470 * (Currently ignored by MS CSP's - always eight)
3471 * - KP_PERMISSIONS: Or'ed combination of CRYPT_ENCRYPT, CRYPT_DECRYPT,
3472 * CRYPT_EXPORT, CRYPT_READ, CRYPT_WRITE, CRYPT_MAC
3473 * - KP_IV: Initialization vector.
3474 * - KP_KEYLEN: Bitwidth of the key.
3475 * - KP_BLOCKLEN: Size of a block cipher block.
3476 * - KP_SALT: Salt value.
3478 BOOL WINAPI RSAENH_CPGetKeyParam(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
3479 DWORD *pdwDataLen, DWORD dwFlags)
3481 CRYPTKEY *pCryptKey;
3482 DWORD dwValue;
3484 TRACE("(hProv=%08lx, hKey=%08lx, dwParam=%08x, pbData=%p, pdwDataLen=%p dwFlags=%08x)\n",
3485 hProv, hKey, dwParam, pbData, pdwDataLen, dwFlags);
3487 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
3489 SetLastError(NTE_BAD_UID);
3490 return FALSE;
3493 if (dwFlags) {
3494 SetLastError(NTE_BAD_FLAGS);
3495 return FALSE;
3498 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
3500 SetLastError(NTE_BAD_KEY);
3501 return FALSE;
3504 switch (dwParam)
3506 case KP_IV:
3507 return copy_param(pbData, pdwDataLen, pCryptKey->abInitVector,
3508 pCryptKey->dwBlockLen);
3510 case KP_SALT:
3511 switch (pCryptKey->aiAlgid) {
3512 case CALG_RC2:
3513 case CALG_RC4:
3514 return copy_param(pbData, pdwDataLen,
3515 &pCryptKey->abKeyValue[pCryptKey->dwKeyLen],
3516 pCryptKey->dwSaltLen);
3517 default:
3518 SetLastError(NTE_BAD_KEY);
3519 return FALSE;
3522 case KP_PADDING:
3523 dwValue = PKCS5_PADDING;
3524 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD));
3526 case KP_KEYLEN:
3527 dwValue = pCryptKey->dwKeyLen << 3;
3528 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD));
3530 case KP_EFFECTIVE_KEYLEN:
3531 if (pCryptKey->dwEffectiveKeyLen)
3532 dwValue = pCryptKey->dwEffectiveKeyLen;
3533 else
3534 dwValue = pCryptKey->dwKeyLen << 3;
3535 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD));
3537 case KP_BLOCKLEN:
3538 dwValue = pCryptKey->dwBlockLen << 3;
3539 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD));
3541 case KP_MODE:
3542 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->dwMode, sizeof(DWORD));
3544 case KP_MODE_BITS:
3545 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->dwModeBits,
3546 sizeof(DWORD));
3548 case KP_PERMISSIONS:
3549 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->dwPermissions,
3550 sizeof(DWORD));
3552 case KP_ALGID:
3553 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->aiAlgid, sizeof(DWORD));
3555 default:
3556 SetLastError(NTE_BAD_TYPE);
3557 return FALSE;
3561 /******************************************************************************
3562 * CPGetProvParam (RSAENH.@)
3564 * Query a CSP parameter.
3566 * PARAMS
3567 * hProv [I] The key container that is to be queried.
3568 * dwParam [I] Specifies the parameter that is to be queried.
3569 * pbData [I] Pointer to the buffer where the parameter value will be stored.
3570 * pdwDataLen [I/O] I: Buffer length at pbData, O: Length of the parameter value.
3571 * dwFlags [I] CRYPT_FIRST: Start enumeration (for PP_ENUMALGS{_EX}).
3573 * RETURNS
3574 * Success: TRUE
3575 * Failure: FALSE
3576 * NOTES:
3577 * Defined dwParam types:
3578 * - PP_CONTAINER: Name of the key container.
3579 * - PP_NAME: Name of the cryptographic service provider.
3580 * - PP_SIG_KEYSIZE_INC: RSA signature keywidth granularity in bits.
3581 * - PP_KEYX_KEYSIZE_INC: RSA key-exchange keywidth granularity in bits.
3582 * - PP_ENUMALGS{_EX}: Query provider capabilities.
3584 BOOL WINAPI RSAENH_CPGetProvParam(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
3585 DWORD *pdwDataLen, DWORD dwFlags)
3587 KEYCONTAINER *pKeyContainer;
3588 PROV_ENUMALGS provEnumalgs;
3589 DWORD dwTemp;
3590 HKEY hKey;
3592 /* This is for dwParam PP_CRYPT_COUNT_KEY_USE.
3593 * IE6 SP1 asks for it in the 'About' dialog.
3594 * Returning this BLOB seems to satisfy IE. The marked 0x00 seem
3595 * to be 'don't care's. If you know anything more specific about
3596 * this provider parameter, please report to wine-devel@winehq.org */
3597 static CONST BYTE abWTF[96] = {
3598 0xb0, 0x25, 0x63, 0x86, 0x9c, 0xab, 0xb6, 0x37,
3599 0xe8, 0x82, /**/0x00,/**/ 0x72, 0x06, 0xb2, /**/0x00,/**/ 0x3b,
3600 0x60, 0x35, /**/0x00,/**/ 0x3b, 0x88, 0xce, /**/0x00,/**/ 0x82,
3601 0xbc, 0x7a, /**/0x00,/**/ 0xb7, 0x4f, 0x7e, /**/0x00,/**/ 0xde,
3602 0x92, 0xf1, /**/0x00,/**/ 0x83, 0xea, 0x5e, /**/0x00,/**/ 0xc8,
3603 0x12, 0x1e, 0xd4, 0x06, 0xf7, 0x66, /**/0x00,/**/ 0x01,
3604 0x29, 0xa4, /**/0x00,/**/ 0xf8, 0x24, 0x0c, /**/0x00,/**/ 0x33,
3605 0x06, 0x80, /**/0x00,/**/ 0x02, 0x46, 0x0b, /**/0x00,/**/ 0x6d,
3606 0x5b, 0xca, /**/0x00,/**/ 0x9a, 0x10, 0xf0, /**/0x00,/**/ 0x05,
3607 0x19, 0xd0, /**/0x00,/**/ 0x2c, 0xf6, 0x27, /**/0x00,/**/ 0xaa,
3608 0x7c, 0x6f, /**/0x00,/**/ 0xb9, 0xd8, 0x72, /**/0x00,/**/ 0x03,
3609 0xf3, 0x81, /**/0x00,/**/ 0xfa, 0xe8, 0x26, /**/0x00,/**/ 0xca
3612 TRACE("(hProv=%08lx, dwParam=%08x, pbData=%p, pdwDataLen=%p, dwFlags=%08x)\n",
3613 hProv, dwParam, pbData, pdwDataLen, dwFlags);
3615 if (!pdwDataLen) {
3616 SetLastError(ERROR_INVALID_PARAMETER);
3617 return FALSE;
3620 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
3621 (OBJECTHDR**)&pKeyContainer))
3623 /* MSDN: hProv not containing valid context handle */
3624 SetLastError(NTE_BAD_UID);
3625 return FALSE;
3628 switch (dwParam)
3630 case PP_CONTAINER:
3631 case PP_UNIQUE_CONTAINER:/* MSDN says we can return the same value as PP_CONTAINER */
3632 return copy_param(pbData, pdwDataLen, (CONST BYTE*)pKeyContainer->szName,
3633 strlen(pKeyContainer->szName)+1);
3635 case PP_NAME:
3636 return copy_param(pbData, pdwDataLen, (CONST BYTE*)pKeyContainer->szProvName,
3637 strlen(pKeyContainer->szProvName)+1);
3639 case PP_PROVTYPE:
3640 dwTemp = PROV_RSA_FULL;
3641 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3643 case PP_KEYSPEC:
3644 dwTemp = AT_SIGNATURE | AT_KEYEXCHANGE;
3645 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3647 case PP_KEYSET_TYPE:
3648 dwTemp = pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET;
3649 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3651 case PP_KEYSTORAGE:
3652 dwTemp = CRYPT_SEC_DESCR;
3653 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3655 case PP_SIG_KEYSIZE_INC:
3656 case PP_KEYX_KEYSIZE_INC:
3657 dwTemp = 8;
3658 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3660 case PP_IMPTYPE:
3661 dwTemp = CRYPT_IMPL_SOFTWARE;
3662 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3664 case PP_VERSION:
3665 dwTemp = 0x00000200;
3666 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3668 case PP_ENUMCONTAINERS:
3669 if ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) pKeyContainer->dwEnumContainersCtr = 0;
3671 if (!pbData) {
3672 *pdwDataLen = (DWORD)MAX_PATH + 1;
3673 return TRUE;
3676 if (!open_container_key("", dwFlags, &hKey))
3678 SetLastError(ERROR_NO_MORE_ITEMS);
3679 return FALSE;
3682 dwTemp = *pdwDataLen;
3683 switch (RegEnumKeyExA(hKey, pKeyContainer->dwEnumContainersCtr, (LPSTR)pbData, &dwTemp,
3684 NULL, NULL, NULL, NULL))
3686 case ERROR_MORE_DATA:
3687 *pdwDataLen = (DWORD)MAX_PATH + 1;
3689 case ERROR_SUCCESS:
3690 pKeyContainer->dwEnumContainersCtr++;
3691 RegCloseKey(hKey);
3692 return TRUE;
3694 case ERROR_NO_MORE_ITEMS:
3695 default:
3696 SetLastError(ERROR_NO_MORE_ITEMS);
3697 RegCloseKey(hKey);
3698 return FALSE;
3701 case PP_ENUMALGS:
3702 case PP_ENUMALGS_EX:
3703 if (((pKeyContainer->dwEnumAlgsCtr >= RSAENH_MAX_ENUMALGS-1) ||
3704 (!aProvEnumAlgsEx[pKeyContainer->dwPersonality]
3705 [pKeyContainer->dwEnumAlgsCtr+1].aiAlgid)) &&
3706 ((dwFlags & CRYPT_FIRST) != CRYPT_FIRST))
3708 SetLastError(ERROR_NO_MORE_ITEMS);
3709 return FALSE;
3712 if (dwParam == PP_ENUMALGS) {
3713 if (pbData && (*pdwDataLen >= sizeof(PROV_ENUMALGS)))
3714 pKeyContainer->dwEnumAlgsCtr = ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) ?
3715 0 : pKeyContainer->dwEnumAlgsCtr+1;
3717 provEnumalgs.aiAlgid = aProvEnumAlgsEx
3718 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].aiAlgid;
3719 provEnumalgs.dwBitLen = aProvEnumAlgsEx
3720 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].dwDefaultLen;
3721 provEnumalgs.dwNameLen = aProvEnumAlgsEx
3722 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].dwNameLen;
3723 memcpy(provEnumalgs.szName, aProvEnumAlgsEx
3724 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].szName,
3725 20*sizeof(CHAR));
3727 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&provEnumalgs,
3728 sizeof(PROV_ENUMALGS));
3729 } else {
3730 if (pbData && (*pdwDataLen >= sizeof(PROV_ENUMALGS_EX)))
3731 pKeyContainer->dwEnumAlgsCtr = ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) ?
3732 0 : pKeyContainer->dwEnumAlgsCtr+1;
3734 return copy_param(pbData, pdwDataLen,
3735 (CONST BYTE*)&aProvEnumAlgsEx
3736 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr],
3737 sizeof(PROV_ENUMALGS_EX));
3740 case PP_CRYPT_COUNT_KEY_USE: /* Asked for by IE About dialog */
3741 return copy_param(pbData, pdwDataLen, abWTF, sizeof(abWTF));
3743 default:
3744 /* MSDN: Unknown parameter number in dwParam */
3745 SetLastError(NTE_BAD_TYPE);
3746 return FALSE;
3750 /******************************************************************************
3751 * CPDeriveKey (RSAENH.@)
3753 * Derives a key from a hash value.
3755 * PARAMS
3756 * hProv [I] Key container for which a key is to be generated.
3757 * Algid [I] Crypto algorithm identifier for the key to be generated.
3758 * hBaseData [I] Hash from whose value the key will be derived.
3759 * dwFlags [I] See Notes.
3760 * phKey [O] The generated key.
3762 * RETURNS
3763 * Success: TRUE
3764 * Failure: FALSE
3766 * NOTES
3767 * Defined flags:
3768 * - CRYPT_EXPORTABLE: Key can be exported.
3769 * - CRYPT_NO_SALT: No salt is used for 40 bit keys.
3770 * - CRYPT_CREATE_SALT: Use remaining bits as salt value.
3772 BOOL WINAPI RSAENH_CPDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
3773 DWORD dwFlags, HCRYPTKEY *phKey)
3775 CRYPTKEY *pCryptKey, *pMasterKey;
3776 CRYPTHASH *pCryptHash;
3777 BYTE abHashValue[RSAENH_MAX_HASH_SIZE*2];
3778 DWORD dwLen;
3780 TRACE("(hProv=%08lx, Algid=%d, hBaseData=%08lx, dwFlags=%08x phKey=%p)\n", hProv, Algid,
3781 hBaseData, dwFlags, phKey);
3783 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
3785 SetLastError(NTE_BAD_UID);
3786 return FALSE;
3789 if (!lookup_handle(&handle_table, hBaseData, RSAENH_MAGIC_HASH,
3790 (OBJECTHDR**)&pCryptHash))
3792 SetLastError(NTE_BAD_HASH);
3793 return FALSE;
3796 if (!phKey)
3798 SetLastError(ERROR_INVALID_PARAMETER);
3799 return FALSE;
3802 switch (GET_ALG_CLASS(Algid))
3804 case ALG_CLASS_DATA_ENCRYPT:
3805 *phKey = new_key(hProv, Algid, dwFlags, &pCryptKey);
3806 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
3809 * We derive the key material from the hash.
3810 * If the hash value is not large enough for the claimed key, we have to construct
3811 * a larger binary value based on the hash. This is documented in MSDN: CryptDeriveKey.
3813 dwLen = RSAENH_MAX_HASH_SIZE;
3814 RSAENH_CPGetHashParam(pCryptHash->hProv, hBaseData, HP_HASHVAL, abHashValue, &dwLen, 0);
3816 if (dwLen < pCryptKey->dwKeyLen) {
3817 BYTE pad1[RSAENH_HMAC_DEF_PAD_LEN], pad2[RSAENH_HMAC_DEF_PAD_LEN];
3818 BYTE old_hashval[RSAENH_MAX_HASH_SIZE];
3819 DWORD i;
3821 memcpy(old_hashval, pCryptHash->abHashValue, RSAENH_MAX_HASH_SIZE);
3823 for (i=0; i<RSAENH_HMAC_DEF_PAD_LEN; i++) {
3824 pad1[i] = RSAENH_HMAC_DEF_IPAD_CHAR ^ (i<dwLen ? abHashValue[i] : 0);
3825 pad2[i] = RSAENH_HMAC_DEF_OPAD_CHAR ^ (i<dwLen ? abHashValue[i] : 0);
3828 init_hash(pCryptHash);
3829 update_hash(pCryptHash, pad1, RSAENH_HMAC_DEF_PAD_LEN);
3830 finalize_hash(pCryptHash);
3831 memcpy(abHashValue, pCryptHash->abHashValue, pCryptHash->dwHashSize);
3833 init_hash(pCryptHash);
3834 update_hash(pCryptHash, pad2, RSAENH_HMAC_DEF_PAD_LEN);
3835 finalize_hash(pCryptHash);
3836 memcpy(abHashValue+pCryptHash->dwHashSize, pCryptHash->abHashValue,
3837 pCryptHash->dwHashSize);
3839 memcpy(pCryptHash->abHashValue, old_hashval, RSAENH_MAX_HASH_SIZE);
3842 memcpy(pCryptKey->abKeyValue, abHashValue,
3843 RSAENH_MIN(pCryptKey->dwKeyLen, sizeof(pCryptKey->abKeyValue)));
3844 break;
3846 case ALG_CLASS_MSG_ENCRYPT:
3847 if (!lookup_handle(&handle_table, pCryptHash->hKey, RSAENH_MAGIC_KEY,
3848 (OBJECTHDR**)&pMasterKey))
3850 SetLastError(NTE_FAIL); /* FIXME error code */
3851 return FALSE;
3854 switch (Algid)
3856 /* See RFC 2246, chapter 6.3 Key calculation */
3857 case CALG_SCHANNEL_ENC_KEY:
3858 *phKey = new_key(hProv, pMasterKey->siSChannelInfo.saEncAlg.Algid,
3859 MAKELONG(LOWORD(dwFlags),pMasterKey->siSChannelInfo.saEncAlg.cBits),
3860 &pCryptKey);
3861 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
3862 memcpy(pCryptKey->abKeyValue,
3863 pCryptHash->abHashValue + (
3864 2 * (pMasterKey->siSChannelInfo.saMACAlg.cBits / 8) +
3865 ((dwFlags & CRYPT_SERVER) ?
3866 (pMasterKey->siSChannelInfo.saEncAlg.cBits / 8) : 0)),
3867 pMasterKey->siSChannelInfo.saEncAlg.cBits / 8);
3868 memcpy(pCryptKey->abInitVector,
3869 pCryptHash->abHashValue + (
3870 2 * (pMasterKey->siSChannelInfo.saMACAlg.cBits / 8) +
3871 2 * (pMasterKey->siSChannelInfo.saEncAlg.cBits / 8) +
3872 ((dwFlags & CRYPT_SERVER) ? pCryptKey->dwBlockLen : 0)),
3873 pCryptKey->dwBlockLen);
3874 break;
3876 case CALG_SCHANNEL_MAC_KEY:
3877 *phKey = new_key(hProv, Algid,
3878 MAKELONG(LOWORD(dwFlags),pMasterKey->siSChannelInfo.saMACAlg.cBits),
3879 &pCryptKey);
3880 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
3881 memcpy(pCryptKey->abKeyValue,
3882 pCryptHash->abHashValue + ((dwFlags & CRYPT_SERVER) ?
3883 pMasterKey->siSChannelInfo.saMACAlg.cBits / 8 : 0),
3884 pMasterKey->siSChannelInfo.saMACAlg.cBits / 8);
3885 break;
3887 default:
3888 SetLastError(NTE_BAD_ALGID);
3889 return FALSE;
3891 break;
3893 default:
3894 SetLastError(NTE_BAD_ALGID);
3895 return FALSE;
3898 setup_key(pCryptKey);
3899 return TRUE;
3902 /******************************************************************************
3903 * CPGetUserKey (RSAENH.@)
3905 * Returns a handle to the user's private key-exchange- or signature-key.
3907 * PARAMS
3908 * hProv [I] The key container from which a user key is requested.
3909 * dwKeySpec [I] AT_KEYEXCHANGE or AT_SIGNATURE
3910 * phUserKey [O] Handle to the requested key or INVALID_HANDLE_VALUE in case of failure.
3912 * RETURNS
3913 * Success: TRUE.
3914 * Failure: FALSE.
3916 * NOTE
3917 * A newly created key container does not contain private user key. Create them with CPGenKey.
3919 BOOL WINAPI RSAENH_CPGetUserKey(HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
3921 KEYCONTAINER *pKeyContainer;
3923 TRACE("(hProv=%08lx, dwKeySpec=%08x, phUserKey=%p)\n", hProv, dwKeySpec, phUserKey);
3925 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
3926 (OBJECTHDR**)&pKeyContainer))
3928 /* MSDN: hProv not containing valid context handle */
3929 SetLastError(NTE_BAD_UID);
3930 return FALSE;
3933 switch (dwKeySpec)
3935 case AT_KEYEXCHANGE:
3936 copy_handle(&handle_table, pKeyContainer->hKeyExchangeKeyPair, RSAENH_MAGIC_KEY,
3937 phUserKey);
3938 break;
3940 case AT_SIGNATURE:
3941 copy_handle(&handle_table, pKeyContainer->hSignatureKeyPair, RSAENH_MAGIC_KEY,
3942 phUserKey);
3943 break;
3945 default:
3946 *phUserKey = (HCRYPTKEY)INVALID_HANDLE_VALUE;
3949 if (*phUserKey == (HCRYPTKEY)INVALID_HANDLE_VALUE)
3951 /* MSDN: dwKeySpec parameter specifies nonexistent key */
3952 SetLastError(NTE_NO_KEY);
3953 return FALSE;
3956 return TRUE;
3959 /******************************************************************************
3960 * CPHashData (RSAENH.@)
3962 * Updates a hash object with the given data.
3964 * PARAMS
3965 * hProv [I] Key container to which the hash object belongs.
3966 * hHash [I] Hash object which is to be updated.
3967 * pbData [I] Pointer to data with which the hash object is to be updated.
3968 * dwDataLen [I] Length of the data.
3969 * dwFlags [I] Currently none defined.
3971 * RETURNS
3972 * Success: TRUE.
3973 * Failure: FALSE.
3975 * NOTES
3976 * The actual hash value is queried with CPGetHashParam, which will finalize
3977 * the hash. Updating a finalized hash will fail with a last error NTE_BAD_HASH_STATE.
3979 BOOL WINAPI RSAENH_CPHashData(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST BYTE *pbData,
3980 DWORD dwDataLen, DWORD dwFlags)
3982 CRYPTHASH *pCryptHash;
3984 TRACE("(hProv=%08lx, hHash=%08lx, pbData=%p, dwDataLen=%d, dwFlags=%08x)\n",
3985 hProv, hHash, pbData, dwDataLen, dwFlags);
3987 if (dwFlags)
3989 SetLastError(NTE_BAD_FLAGS);
3990 return FALSE;
3993 if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH,
3994 (OBJECTHDR**)&pCryptHash))
3996 SetLastError(NTE_BAD_HASH);
3997 return FALSE;
4000 if (!get_algid_info(hProv, pCryptHash->aiAlgid) || pCryptHash->aiAlgid == CALG_SSL3_SHAMD5)
4002 SetLastError(NTE_BAD_ALGID);
4003 return FALSE;
4006 if (pCryptHash->dwState != RSAENH_HASHSTATE_HASHING)
4008 SetLastError(NTE_BAD_HASH_STATE);
4009 return FALSE;
4012 update_hash(pCryptHash, pbData, dwDataLen);
4013 return TRUE;
4016 /******************************************************************************
4017 * CPHashSessionKey (RSAENH.@)
4019 * Updates a hash object with the binary representation of a symmetric key.
4021 * PARAMS
4022 * hProv [I] Key container to which the hash object belongs.
4023 * hHash [I] Hash object which is to be updated.
4024 * hKey [I] The symmetric key, whose binary value will be added to the hash.
4025 * dwFlags [I] CRYPT_LITTLE_ENDIAN, if the binary key value shall be interpreted as little endian.
4027 * RETURNS
4028 * Success: TRUE.
4029 * Failure: FALSE.
4031 BOOL WINAPI RSAENH_CPHashSessionKey(HCRYPTPROV hProv, HCRYPTHASH hHash, HCRYPTKEY hKey,
4032 DWORD dwFlags)
4034 BYTE abKeyValue[RSAENH_MAX_KEY_SIZE], bTemp;
4035 CRYPTKEY *pKey;
4036 DWORD i;
4038 TRACE("(hProv=%08lx, hHash=%08lx, hKey=%08lx, dwFlags=%08x)\n", hProv, hHash, hKey, dwFlags);
4040 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pKey) ||
4041 (GET_ALG_CLASS(pKey->aiAlgid) != ALG_CLASS_DATA_ENCRYPT))
4043 SetLastError(NTE_BAD_KEY);
4044 return FALSE;
4047 if (dwFlags & ~CRYPT_LITTLE_ENDIAN) {
4048 SetLastError(NTE_BAD_FLAGS);
4049 return FALSE;
4052 memcpy(abKeyValue, pKey->abKeyValue, pKey->dwKeyLen);
4053 if (!(dwFlags & CRYPT_LITTLE_ENDIAN)) {
4054 for (i=0; i<pKey->dwKeyLen/2; i++) {
4055 bTemp = abKeyValue[i];
4056 abKeyValue[i] = abKeyValue[pKey->dwKeyLen-i-1];
4057 abKeyValue[pKey->dwKeyLen-i-1] = bTemp;
4061 return RSAENH_CPHashData(hProv, hHash, abKeyValue, pKey->dwKeyLen, 0);
4064 /******************************************************************************
4065 * CPReleaseContext (RSAENH.@)
4067 * Release a key container.
4069 * PARAMS
4070 * hProv [I] Key container to be released.
4071 * dwFlags [I] Currently none defined.
4073 * RETURNS
4074 * Success: TRUE
4075 * Failure: FALSE
4077 BOOL WINAPI RSAENH_CPReleaseContext(HCRYPTPROV hProv, DWORD dwFlags)
4079 TRACE("(hProv=%08lx, dwFlags=%08x)\n", hProv, dwFlags);
4081 if (!release_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
4083 /* MSDN: hProv not containing valid context handle */
4084 SetLastError(NTE_BAD_UID);
4085 return FALSE;
4088 if (dwFlags) {
4089 SetLastError(NTE_BAD_FLAGS);
4090 return FALSE;
4093 return TRUE;
4096 /******************************************************************************
4097 * CPSetHashParam (RSAENH.@)
4099 * Set a parameter of a hash object
4101 * PARAMS
4102 * hProv [I] The key container to which the key belongs.
4103 * hHash [I] The hash object for which a parameter is to be set.
4104 * dwParam [I] Parameter type. See Notes.
4105 * pbData [I] Pointer to the parameter value.
4106 * dwFlags [I] Currently none defined.
4108 * RETURNS
4109 * Success: TRUE.
4110 * Failure: FALSE.
4112 * NOTES
4113 * Currently only the HP_HMAC_INFO dwParam type is defined.
4114 * The HMAC_INFO struct will be deep copied into the hash object.
4115 * See Internet RFC 2104 for details on the HMAC algorithm.
4117 BOOL WINAPI RSAENH_CPSetHashParam(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam,
4118 BYTE *pbData, DWORD dwFlags)
4120 CRYPTHASH *pCryptHash;
4121 CRYPTKEY *pCryptKey;
4122 DWORD i;
4124 TRACE("(hProv=%08lx, hHash=%08lx, dwParam=%08x, pbData=%p, dwFlags=%08x)\n",
4125 hProv, hHash, dwParam, pbData, dwFlags);
4127 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
4129 SetLastError(NTE_BAD_UID);
4130 return FALSE;
4133 if (dwFlags) {
4134 SetLastError(NTE_BAD_FLAGS);
4135 return FALSE;
4138 if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH,
4139 (OBJECTHDR**)&pCryptHash))
4141 SetLastError(NTE_BAD_HASH);
4142 return FALSE;
4145 switch (dwParam) {
4146 case HP_HMAC_INFO:
4147 free_hmac_info(pCryptHash->pHMACInfo);
4148 if (!copy_hmac_info(&pCryptHash->pHMACInfo, (PHMAC_INFO)pbData)) return FALSE;
4150 if (!lookup_handle(&handle_table, pCryptHash->hKey, RSAENH_MAGIC_KEY,
4151 (OBJECTHDR**)&pCryptKey))
4153 SetLastError(NTE_FAIL); /* FIXME: correct error code? */
4154 return FALSE;
4157 for (i=0; i<RSAENH_MIN(pCryptKey->dwKeyLen,pCryptHash->pHMACInfo->cbInnerString); i++) {
4158 pCryptHash->pHMACInfo->pbInnerString[i] ^= pCryptKey->abKeyValue[i];
4160 for (i=0; i<RSAENH_MIN(pCryptKey->dwKeyLen,pCryptHash->pHMACInfo->cbOuterString); i++) {
4161 pCryptHash->pHMACInfo->pbOuterString[i] ^= pCryptKey->abKeyValue[i];
4164 init_hash(pCryptHash);
4165 return TRUE;
4167 case HP_HASHVAL:
4168 memcpy(pCryptHash->abHashValue, pbData, pCryptHash->dwHashSize);
4169 pCryptHash->dwState = RSAENH_HASHSTATE_FINISHED;
4170 return TRUE;
4172 case HP_TLS1PRF_SEED:
4173 return copy_data_blob(&pCryptHash->tpPRFParams.blobSeed, (PCRYPT_DATA_BLOB)pbData);
4175 case HP_TLS1PRF_LABEL:
4176 return copy_data_blob(&pCryptHash->tpPRFParams.blobLabel, (PCRYPT_DATA_BLOB)pbData);
4178 default:
4179 SetLastError(NTE_BAD_TYPE);
4180 return FALSE;
4184 /******************************************************************************
4185 * CPSetProvParam (RSAENH.@)
4187 BOOL WINAPI RSAENH_CPSetProvParam(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
4189 FIXME("(stub)\n");
4190 return FALSE;
4193 /******************************************************************************
4194 * CPSignHash (RSAENH.@)
4196 * Sign a hash object
4198 * PARAMS
4199 * hProv [I] The key container, to which the hash object belongs.
4200 * hHash [I] The hash object to be signed.
4201 * dwKeySpec [I] AT_SIGNATURE or AT_KEYEXCHANGE: Key used to generate the signature.
4202 * sDescription [I] Should be NULL for security reasons.
4203 * dwFlags [I] 0, CRYPT_NOHASHOID or CRYPT_X931_FORMAT: Format of the signature.
4204 * pbSignature [O] Buffer, to which the signature will be stored. May be NULL to query SigLen.
4205 * pdwSigLen [I/O] Size of the buffer (in), Length of the signature (out)
4207 * RETURNS
4208 * Success: TRUE
4209 * Failure: FALSE
4211 BOOL WINAPI RSAENH_CPSignHash(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwKeySpec,
4212 LPCWSTR sDescription, DWORD dwFlags, BYTE *pbSignature,
4213 DWORD *pdwSigLen)
4215 HCRYPTKEY hCryptKey = (HCRYPTKEY)INVALID_HANDLE_VALUE;
4216 CRYPTKEY *pCryptKey;
4217 DWORD dwHashLen;
4218 BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
4219 ALG_ID aiAlgid;
4220 BOOL ret = FALSE;
4222 TRACE("(hProv=%08lx, hHash=%08lx, dwKeySpec=%08x, sDescription=%s, dwFlags=%08x, "
4223 "pbSignature=%p, pdwSigLen=%p)\n", hProv, hHash, dwKeySpec, debugstr_w(sDescription),
4224 dwFlags, pbSignature, pdwSigLen);
4226 if (dwFlags & ~(CRYPT_NOHASHOID|CRYPT_X931_FORMAT)) {
4227 SetLastError(NTE_BAD_FLAGS);
4228 return FALSE;
4231 if (!RSAENH_CPGetUserKey(hProv, dwKeySpec, &hCryptKey)) return FALSE;
4233 if (!lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY,
4234 (OBJECTHDR**)&pCryptKey))
4236 SetLastError(NTE_NO_KEY);
4237 goto out;
4240 if (!pbSignature) {
4241 *pdwSigLen = pCryptKey->dwKeyLen;
4242 ret = TRUE;
4243 goto out;
4245 if (pCryptKey->dwKeyLen > *pdwSigLen)
4247 SetLastError(ERROR_MORE_DATA);
4248 *pdwSigLen = pCryptKey->dwKeyLen;
4249 goto out;
4251 *pdwSigLen = pCryptKey->dwKeyLen;
4253 if (sDescription) {
4254 if (!RSAENH_CPHashData(hProv, hHash, (CONST BYTE*)sDescription,
4255 (DWORD)lstrlenW(sDescription)*sizeof(WCHAR), 0))
4257 goto out;
4261 dwHashLen = sizeof(DWORD);
4262 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_ALGID, (BYTE*)&aiAlgid, &dwHashLen, 0)) goto out;
4264 dwHashLen = RSAENH_MAX_HASH_SIZE;
4265 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_HASHVAL, abHashValue, &dwHashLen, 0)) goto out;
4268 if (!build_hash_signature(pbSignature, *pdwSigLen, aiAlgid, abHashValue, dwHashLen, dwFlags)) {
4269 goto out;
4272 ret = encrypt_block_impl(pCryptKey->aiAlgid, PK_PRIVATE, &pCryptKey->context, pbSignature, pbSignature, RSAENH_ENCRYPT);
4273 out:
4274 RSAENH_CPDestroyKey(hProv, hCryptKey);
4275 return ret;
4278 /******************************************************************************
4279 * CPVerifySignature (RSAENH.@)
4281 * Verify the signature of a hash object.
4283 * PARAMS
4284 * hProv [I] The key container, to which the hash belongs.
4285 * hHash [I] The hash for which the signature is verified.
4286 * pbSignature [I] The binary signature.
4287 * dwSigLen [I] Length of the signature BLOB.
4288 * hPubKey [I] Public key used to verify the signature.
4289 * sDescription [I] Should be NULL for security reasons.
4290 * dwFlags [I] 0, CRYPT_NOHASHOID or CRYPT_X931_FORMAT: Format of the signature.
4292 * RETURNS
4293 * Success: TRUE (Signature is valid)
4294 * Failure: FALSE (GetLastError() == NTE_BAD_SIGNATURE, if signature is invalid)
4296 BOOL WINAPI RSAENH_CPVerifySignature(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST BYTE *pbSignature,
4297 DWORD dwSigLen, HCRYPTKEY hPubKey, LPCWSTR sDescription,
4298 DWORD dwFlags)
4300 BYTE *pbConstructed = NULL, *pbDecrypted = NULL;
4301 CRYPTKEY *pCryptKey;
4302 DWORD dwHashLen;
4303 ALG_ID aiAlgid;
4304 BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
4305 BOOL res = FALSE;
4307 TRACE("(hProv=%08lx, hHash=%08lx, pbSignature=%p, dwSigLen=%d, hPubKey=%08lx, sDescription=%s, "
4308 "dwFlags=%08x)\n", hProv, hHash, pbSignature, dwSigLen, hPubKey, debugstr_w(sDescription),
4309 dwFlags);
4311 if (dwFlags & ~(CRYPT_NOHASHOID|CRYPT_X931_FORMAT)) {
4312 SetLastError(NTE_BAD_FLAGS);
4313 return FALSE;
4316 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
4318 SetLastError(NTE_BAD_UID);
4319 return FALSE;
4322 if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY,
4323 (OBJECTHDR**)&pCryptKey))
4325 SetLastError(NTE_BAD_KEY);
4326 return FALSE;
4329 /* in Microsoft implementation, the signature length is checked before
4330 * the signature pointer.
4332 if (dwSigLen != pCryptKey->dwKeyLen)
4334 SetLastError(NTE_BAD_SIGNATURE);
4335 return FALSE;
4338 if (!hHash || !pbSignature)
4340 SetLastError(ERROR_INVALID_PARAMETER);
4341 return FALSE;
4344 if (sDescription) {
4345 if (!RSAENH_CPHashData(hProv, hHash, (CONST BYTE*)sDescription,
4346 (DWORD)lstrlenW(sDescription)*sizeof(WCHAR), 0))
4348 return FALSE;
4352 dwHashLen = sizeof(DWORD);
4353 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_ALGID, (BYTE*)&aiAlgid, &dwHashLen, 0)) return FALSE;
4355 dwHashLen = RSAENH_MAX_HASH_SIZE;
4356 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_HASHVAL, abHashValue, &dwHashLen, 0)) return FALSE;
4358 pbConstructed = HeapAlloc(GetProcessHeap(), 0, dwSigLen);
4359 if (!pbConstructed) {
4360 SetLastError(NTE_NO_MEMORY);
4361 goto cleanup;
4364 pbDecrypted = HeapAlloc(GetProcessHeap(), 0, dwSigLen);
4365 if (!pbDecrypted) {
4366 SetLastError(NTE_NO_MEMORY);
4367 goto cleanup;
4370 if (!encrypt_block_impl(pCryptKey->aiAlgid, PK_PUBLIC, &pCryptKey->context, pbSignature, pbDecrypted,
4371 RSAENH_DECRYPT))
4373 goto cleanup;
4376 if (!build_hash_signature(pbConstructed, dwSigLen, aiAlgid, abHashValue, dwHashLen, dwFlags)) {
4377 goto cleanup;
4380 if (memcmp(pbDecrypted, pbConstructed, dwSigLen)) {
4381 SetLastError(NTE_BAD_SIGNATURE);
4382 goto cleanup;
4385 res = TRUE;
4386 cleanup:
4387 HeapFree(GetProcessHeap(), 0, pbConstructed);
4388 HeapFree(GetProcessHeap(), 0, pbDecrypted);
4389 return res;
4392 static const WCHAR szProviderKeys[6][116] = {
4393 { 'S','o','f','t','w','a','r','e','\\',
4394 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
4395 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
4396 'i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ','B','a','s',
4397 'e',' ','C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r',
4398 'o','v','i','d','e','r',' ','v','1','.','0',0 },
4399 { 'S','o','f','t','w','a','r','e','\\',
4400 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
4401 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
4402 'i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ',
4403 'E','n','h','a','n','c','e','d',
4404 ' ','C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r',
4405 'o','v','i','d','e','r',' ','v','1','.','0',0 },
4406 { 'S','o','f','t','w','a','r','e','\\',
4407 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
4408 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
4409 'i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ','S','t','r','o','n','g',
4410 ' ','C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r',
4411 'o','v','i','d','e','r',0 },
4412 { 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
4413 'C','r','y','p','t','o','g','r','a','p','h','y','\\','D','e','f','a','u','l','t','s','\\',
4414 'P','r','o','v','i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ',
4415 'R','S','A',' ','S','C','h','a','n','n','e','l',' ',
4416 'C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r','o','v','i','d','e','r',0 },
4417 { 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
4418 'C','r','y','p','t','o','g','r','a','p','h','y','\\','D','e','f','a','u','l','t','s','\\',
4419 'P','r','o','v','i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ',
4420 'E','n','h','a','n','c','e','d',' ','R','S','A',' ','a','n','d',' ','A','E','S',' ',
4421 'C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r','o','v','i','d','e','r',0 },
4422 { 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
4423 'C','r','y','p','t','o','g','r','a','p','h','y','\\','D','e','f','a','u','l','t','s','\\',
4424 'P','r','o','v','i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ',
4425 'E','n','h','a','n','c','e','d',' ','R','S','A',' ','a','n','d',' ','A','E','S',' ',
4426 'C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r','o','v','i','d','e','r',
4427 ' ','(','P','r','o','t','o','t','y','p','e',')',0 }
4429 static const WCHAR szDefaultKeys[3][65] = {
4430 { 'S','o','f','t','w','a','r','e','\\',
4431 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
4432 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
4433 'i','d','e','r',' ','T','y','p','e','s','\\','T','y','p','e',' ','0','0','1',0 },
4434 { 'S','o','f','t','w','a','r','e','\\',
4435 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
4436 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
4437 'i','d','e','r',' ','T','y','p','e','s','\\','T','y','p','e',' ','0','1','2',0 },
4438 { 'S','o','f','t','w','a','r','e','\\',
4439 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
4440 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
4441 'i','d','e','r',' ','T','y','p','e','s','\\','T','y','p','e',' ','0','2','4',0 }
4445 /******************************************************************************
4446 * DllRegisterServer (RSAENH.@)
4448 HRESULT WINAPI DllRegisterServer(void)
4450 return __wine_register_resources( instance, NULL );
4453 /******************************************************************************
4454 * DllUnregisterServer (RSAENH.@)
4456 HRESULT WINAPI DllUnregisterServer(void)
4458 return __wine_unregister_resources( instance, NULL );