push 0f15bbd80d260bbd8adf052e820484a405c49375
[wine/hacks.git] / dlls / rsaenh / rsaenh.c
blob29e072c31c1b709d9b390f191849c6656041fb3e
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"
41 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
43 /******************************************************************************
44 * CRYPTHASH - hash objects
46 #define RSAENH_MAGIC_HASH 0x85938417u
47 #define RSAENH_MAX_HASH_SIZE 104
48 #define RSAENH_HASHSTATE_HASHING 1
49 #define RSAENH_HASHSTATE_FINISHED 2
50 typedef struct _RSAENH_TLS1PRF_PARAMS
52 CRYPT_DATA_BLOB blobLabel;
53 CRYPT_DATA_BLOB blobSeed;
54 } RSAENH_TLS1PRF_PARAMS;
56 typedef struct tagCRYPTHASH
58 OBJECTHDR header;
59 ALG_ID aiAlgid;
60 HCRYPTKEY hKey;
61 HCRYPTPROV hProv;
62 DWORD dwHashSize;
63 DWORD dwState;
64 HASH_CONTEXT context;
65 BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
66 PHMAC_INFO pHMACInfo;
67 RSAENH_TLS1PRF_PARAMS tpPRFParams;
68 } CRYPTHASH;
70 /******************************************************************************
71 * CRYPTKEY - key objects
73 #define RSAENH_MAGIC_KEY 0x73620457u
74 #define RSAENH_MAX_KEY_SIZE 48
75 #define RSAENH_MAX_BLOCK_SIZE 24
76 #define RSAENH_KEYSTATE_IDLE 0
77 #define RSAENH_KEYSTATE_ENCRYPTING 1
78 #define RSAENH_KEYSTATE_DECRYPTING 2
79 #define RSAENH_KEYSTATE_MASTERKEY 3
80 typedef struct _RSAENH_SCHANNEL_INFO
82 SCHANNEL_ALG saEncAlg;
83 SCHANNEL_ALG saMACAlg;
84 CRYPT_DATA_BLOB blobClientRandom;
85 CRYPT_DATA_BLOB blobServerRandom;
86 } RSAENH_SCHANNEL_INFO;
88 typedef struct tagCRYPTKEY
90 OBJECTHDR header;
91 ALG_ID aiAlgid;
92 HCRYPTPROV hProv;
93 DWORD dwMode;
94 DWORD dwModeBits;
95 DWORD dwPermissions;
96 DWORD dwKeyLen;
97 DWORD dwEffectiveKeyLen;
98 DWORD dwSaltLen;
99 DWORD dwBlockLen;
100 DWORD dwState;
101 KEY_CONTEXT context;
102 BYTE abKeyValue[RSAENH_MAX_KEY_SIZE];
103 BYTE abInitVector[RSAENH_MAX_BLOCK_SIZE];
104 BYTE abChainVector[RSAENH_MAX_BLOCK_SIZE];
105 RSAENH_SCHANNEL_INFO siSChannelInfo;
106 } CRYPTKEY;
108 /******************************************************************************
109 * KEYCONTAINER - key containers
111 #define RSAENH_PERSONALITY_BASE 0u
112 #define RSAENH_PERSONALITY_STRONG 1u
113 #define RSAENH_PERSONALITY_ENHANCED 2u
114 #define RSAENH_PERSONALITY_SCHANNEL 3u
115 #define RSAENH_PERSONALITY_AES 4u
117 #define RSAENH_MAGIC_CONTAINER 0x26384993u
118 typedef struct tagKEYCONTAINER
120 OBJECTHDR header;
121 DWORD dwFlags;
122 DWORD dwPersonality;
123 DWORD dwEnumAlgsCtr;
124 DWORD dwEnumContainersCtr;
125 CHAR szName[MAX_PATH];
126 CHAR szProvName[MAX_PATH];
127 HCRYPTKEY hKeyExchangeKeyPair;
128 HCRYPTKEY hSignatureKeyPair;
129 } KEYCONTAINER;
131 /******************************************************************************
132 * Some magic constants
134 #define RSAENH_ENCRYPT 1
135 #define RSAENH_DECRYPT 0
136 #define RSAENH_HMAC_DEF_IPAD_CHAR 0x36
137 #define RSAENH_HMAC_DEF_OPAD_CHAR 0x5c
138 #define RSAENH_HMAC_DEF_PAD_LEN 64
139 #define RSAENH_DES_EFFECTIVE_KEYLEN 56
140 #define RSAENH_DES_STORAGE_KEYLEN 64
141 #define RSAENH_3DES112_EFFECTIVE_KEYLEN 112
142 #define RSAENH_3DES112_STORAGE_KEYLEN 128
143 #define RSAENH_3DES_EFFECTIVE_KEYLEN 168
144 #define RSAENH_3DES_STORAGE_KEYLEN 192
145 #define RSAENH_MAGIC_RSA2 0x32415352
146 #define RSAENH_MAGIC_RSA1 0x31415352
147 #define RSAENH_PKC_BLOCKTYPE 0x02
148 #define RSAENH_SSL3_VERSION_MAJOR 3
149 #define RSAENH_SSL3_VERSION_MINOR 0
150 #define RSAENH_TLS1_VERSION_MAJOR 3
151 #define RSAENH_TLS1_VERSION_MINOR 1
152 #define RSAENH_REGKEY "Software\\Wine\\Crypto\\RSA\\%s"
154 #define RSAENH_MIN(a,b) ((a)<(b)?(a):(b))
155 /******************************************************************************
156 * aProvEnumAlgsEx - Defines the capabilities of the CSP personalities.
158 #define RSAENH_MAX_ENUMALGS 24
159 #define RSAENH_PCT1_SSL2_SSL3_TLS1 (CRYPT_FLAG_PCT1|CRYPT_FLAG_SSL2|CRYPT_FLAG_SSL3|CRYPT_FLAG_TLS1)
160 static const PROV_ENUMALGS_EX aProvEnumAlgsEx[5][RSAENH_MAX_ENUMALGS+1] =
163 {CALG_RC2, 40, 40, 56,0, 4,"RC2", 24,"RSA Data Security's RC2"},
164 {CALG_RC4, 40, 40, 56,0, 4,"RC4", 24,"RSA Data Security's RC4"},
165 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"},
166 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"},
167 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"},
168 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"},
169 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"},
170 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
171 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
172 {CALG_RSA_SIGN, 512,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
173 {CALG_RSA_KEYX, 512,384, 1024,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
174 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
175 {0, 0, 0, 0,0, 1,"", 1,""}
178 {CALG_RC2, 128, 40, 128,0, 4,"RC2", 24,"RSA Data Security's RC2"},
179 {CALG_RC4, 128, 40, 128,0, 4,"RC4", 24,"RSA Data Security's RC4"},
180 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"},
181 {CALG_3DES_112, 112,112, 112,0, 13,"3DES TWO KEY",19,"Two Key Triple DES"},
182 {CALG_3DES, 168,168, 168,0, 5,"3DES", 21,"Three Key Triple DES"},
183 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"},
184 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"},
185 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"},
186 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"},
187 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
188 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
189 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
190 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
191 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
192 {0, 0, 0, 0,0, 1,"", 1,""}
195 {CALG_RC2, 128, 40, 128,0, 4,"RC2", 24,"RSA Data Security's RC2"},
196 {CALG_RC4, 128, 40, 128,0, 4,"RC4", 24,"RSA Data Security's RC4"},
197 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"},
198 {CALG_3DES_112, 112,112, 112,0, 13,"3DES TWO KEY",19,"Two Key Triple DES"},
199 {CALG_3DES, 168,168, 168,0, 5,"3DES", 21,"Three Key Triple DES"},
200 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"},
201 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"},
202 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"},
203 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"},
204 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
205 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
206 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
207 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
208 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
209 {0, 0, 0, 0,0, 1,"", 1,""}
212 {CALG_RC2, 128, 40, 128,RSAENH_PCT1_SSL2_SSL3_TLS1, 4,"RC2", 24,"RSA Data Security's RC2"},
213 {CALG_RC4, 128, 40, 128,RSAENH_PCT1_SSL2_SSL3_TLS1, 4,"RC4", 24,"RSA Data Security's RC4"},
214 {CALG_DES, 56, 56, 56,RSAENH_PCT1_SSL2_SSL3_TLS1, 4,"DES", 31,"Data Encryption Standard (DES)"},
215 {CALG_3DES_112, 112,112, 112,RSAENH_PCT1_SSL2_SSL3_TLS1,13,"3DES TWO KEY",19,"Two Key Triple DES"},
216 {CALG_3DES, 168,168, 168,RSAENH_PCT1_SSL2_SSL3_TLS1, 5,"3DES", 21,"Three Key Triple DES"},
217 {CALG_SHA,160,160,160,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,6,"SHA-1",30,"Secure Hash Algorithm (SHA-1)"},
218 {CALG_MD5,128,128,128,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,4,"MD5",23,"Message Digest 5 (MD5)"},
219 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
220 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
221 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,9,"RSA_SIGN",14,"RSA Signature"},
222 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,9,"RSA_KEYX",17,"RSA Key Exchange"},
223 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
224 {CALG_PCT1_MASTER,128,128,128,CRYPT_FLAG_PCT1, 12,"PCT1 MASTER",12,"PCT1 Master"},
225 {CALG_SSL2_MASTER,40,40, 192,CRYPT_FLAG_SSL2, 12,"SSL2 MASTER",12,"SSL2 Master"},
226 {CALG_SSL3_MASTER,384,384,384,CRYPT_FLAG_SSL3, 12,"SSL3 MASTER",12,"SSL3 Master"},
227 {CALG_TLS1_MASTER,384,384,384,CRYPT_FLAG_TLS1, 12,"TLS1 MASTER",12,"TLS1 Master"},
228 {CALG_SCHANNEL_MASTER_HASH,0,0,-1,0, 16,"SCH MASTER HASH",21,"SChannel Master Hash"},
229 {CALG_SCHANNEL_MAC_KEY,0,0,-1,0, 12,"SCH MAC KEY",17,"SChannel MAC Key"},
230 {CALG_SCHANNEL_ENC_KEY,0,0,-1,0, 12,"SCH ENC KEY",24,"SChannel Encryption Key"},
231 {CALG_TLS1PRF, 0, 0, -1,0, 9,"TLS1 PRF", 28,"TLS1 Pseudo Random Function"},
232 {0, 0, 0, 0,0, 1,"", 1,""}
235 {CALG_RC2, 128, 40, 128,0, 4,"RC2", 24,"RSA Data Security's RC2"},
236 {CALG_RC4, 128, 40, 128,0, 4,"RC4", 24,"RSA Data Security's RC4"},
237 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"},
238 {CALG_3DES_112, 112,112, 112,0, 13,"3DES TWO KEY",19,"Two Key Triple DES"},
239 {CALG_3DES, 168,168, 168,0, 5,"3DES", 21,"Three Key Triple DES"},
240 {CALG_AES, 128,128, 128,0, 4,"AES", 35,"Advanced Encryption Standard (AES)"},
241 {CALG_AES_128, 128,128, 128,0, 8,"AES-128", 39,"Advanced Encryption Standard (AES-128)"},
242 {CALG_AES_192, 192,192, 192,0, 8,"AES-192", 39,"Advanced Encryption Standard (AES-192)"},
243 {CALG_AES_256, 256,256, 256,0, 8,"AES-256", 39,"Advanced Encryption Standard (AES-256)"},
244 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"},
245 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"},
246 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"},
247 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"},
248 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
249 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
250 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
251 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
252 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
253 {0, 0, 0, 0,0, 1,"", 1,""}
257 /******************************************************************************
258 * API forward declarations
260 BOOL WINAPI
261 RSAENH_CPGetKeyParam(
262 HCRYPTPROV hProv,
263 HCRYPTKEY hKey,
264 DWORD dwParam,
265 BYTE *pbData,
266 DWORD *pdwDataLen,
267 DWORD dwFlags
270 BOOL WINAPI
271 RSAENH_CPEncrypt(
272 HCRYPTPROV hProv,
273 HCRYPTKEY hKey,
274 HCRYPTHASH hHash,
275 BOOL Final,
276 DWORD dwFlags,
277 BYTE *pbData,
278 DWORD *pdwDataLen,
279 DWORD dwBufLen
282 BOOL WINAPI
283 RSAENH_CPCreateHash(
284 HCRYPTPROV hProv,
285 ALG_ID Algid,
286 HCRYPTKEY hKey,
287 DWORD dwFlags,
288 HCRYPTHASH *phHash
291 BOOL WINAPI
292 RSAENH_CPSetHashParam(
293 HCRYPTPROV hProv,
294 HCRYPTHASH hHash,
295 DWORD dwParam,
296 BYTE *pbData, DWORD dwFlags
299 BOOL WINAPI
300 RSAENH_CPGetHashParam(
301 HCRYPTPROV hProv,
302 HCRYPTHASH hHash,
303 DWORD dwParam,
304 BYTE *pbData,
305 DWORD *pdwDataLen,
306 DWORD dwFlags
309 BOOL WINAPI
310 RSAENH_CPDestroyHash(
311 HCRYPTPROV hProv,
312 HCRYPTHASH hHash
315 BOOL WINAPI
316 RSAENH_CPExportKey(
317 HCRYPTPROV hProv,
318 HCRYPTKEY hKey,
319 HCRYPTKEY hPubKey,
320 DWORD dwBlobType,
321 DWORD dwFlags,
322 BYTE *pbData,
323 DWORD *pdwDataLen
326 BOOL WINAPI
327 RSAENH_CPImportKey(
328 HCRYPTPROV hProv,
329 CONST BYTE *pbData,
330 DWORD dwDataLen,
331 HCRYPTKEY hPubKey,
332 DWORD dwFlags,
333 HCRYPTKEY *phKey
336 BOOL WINAPI
337 RSAENH_CPHashData(
338 HCRYPTPROV hProv,
339 HCRYPTHASH hHash,
340 CONST BYTE *pbData,
341 DWORD dwDataLen,
342 DWORD dwFlags
345 /******************************************************************************
346 * CSP's handle table (used by all acquired key containers)
348 static HANDLETABLE handle_table;
350 /******************************************************************************
351 * DllMain (RSAENH.@)
353 * Initializes and destroys the handle table for the CSP's handles.
355 int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
357 switch (fdwReason)
359 case DLL_PROCESS_ATTACH:
360 DisableThreadLibraryCalls(hInstance);
361 init_handle_table(&handle_table);
362 break;
364 case DLL_PROCESS_DETACH:
365 destroy_handle_table(&handle_table);
366 break;
368 return 1;
371 /******************************************************************************
372 * copy_param [Internal]
374 * Helper function that supports the standard WINAPI protocol for querying data
375 * of dynamic size.
377 * PARAMS
378 * pbBuffer [O] Buffer where the queried parameter is copied to, if it is large enough.
379 * May be NUL if the required buffer size is to be queried only.
380 * pdwBufferSize [I/O] In: Size of the buffer at pbBuffer
381 * Out: Size of parameter pbParam
382 * pbParam [I] Parameter value.
383 * dwParamSize [I] Size of pbParam
385 * RETURN
386 * Success: TRUE (pbParam was copied into pbBuffer or pbBuffer is NULL)
387 * Failure: FALSE (pbBuffer is not large enough to hold pbParam). Last error: ERROR_MORE_DATA
389 static inline BOOL copy_param(
390 BYTE *pbBuffer, DWORD *pdwBufferSize, CONST BYTE *pbParam, DWORD dwParamSize)
392 if (pbBuffer)
394 if (dwParamSize > *pdwBufferSize)
396 SetLastError(ERROR_MORE_DATA);
397 *pdwBufferSize = dwParamSize;
398 return FALSE;
400 memcpy(pbBuffer, pbParam, dwParamSize);
402 *pdwBufferSize = dwParamSize;
403 return TRUE;
406 /******************************************************************************
407 * get_algid_info [Internal]
409 * Query CSP capabilities for a given crypto algorithm.
411 * PARAMS
412 * hProv [I] Handle to a key container of the CSP whose capabilities are to be queried.
413 * algid [I] Identifier of the crypto algorithm about which information is requested.
415 * RETURNS
416 * Success: Pointer to a PROV_ENUMALGS_EX struct containing information about the crypto algorithm.
417 * Failure: NULL (algid not supported)
419 static inline const PROV_ENUMALGS_EX* get_algid_info(HCRYPTPROV hProv, ALG_ID algid) {
420 const PROV_ENUMALGS_EX *iterator;
421 KEYCONTAINER *pKeyContainer;
423 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER, (OBJECTHDR**)&pKeyContainer)) {
424 SetLastError(NTE_BAD_UID);
425 return NULL;
428 for (iterator = aProvEnumAlgsEx[pKeyContainer->dwPersonality]; iterator->aiAlgid; iterator++) {
429 if (iterator->aiAlgid == algid) return iterator;
432 SetLastError(NTE_BAD_ALGID);
433 return NULL;
436 /******************************************************************************
437 * copy_data_blob [Internal]
439 * deeply copies a DATA_BLOB
441 * PARAMS
442 * dst [O] That's where the blob will be copied to
443 * src [I] Source blob
445 * RETURNS
446 * Success: TRUE
447 * Failure: FALSE (GetLastError() == NTE_NO_MEMORY
449 * NOTES
450 * Use free_data_blob to release resources occupied by copy_data_blob.
452 static inline BOOL copy_data_blob(PCRYPT_DATA_BLOB dst, CONST PCRYPT_DATA_BLOB src) {
453 dst->pbData = HeapAlloc(GetProcessHeap(), 0, src->cbData);
454 if (!dst->pbData) {
455 SetLastError(NTE_NO_MEMORY);
456 return FALSE;
458 dst->cbData = src->cbData;
459 memcpy(dst->pbData, src->pbData, src->cbData);
460 return TRUE;
463 /******************************************************************************
464 * concat_data_blobs [Internal]
466 * Concatenates two blobs
468 * PARAMS
469 * dst [O] The new blob will be copied here
470 * src1 [I] Prefix blob
471 * src2 [I] Appendix blob
473 * RETURNS
474 * Success: TRUE
475 * Failure: FALSE (GetLastError() == NTE_NO_MEMORY)
477 * NOTES
478 * Release resources occupied by concat_data_blobs with free_data_blobs
480 static inline BOOL concat_data_blobs(PCRYPT_DATA_BLOB dst, CONST PCRYPT_DATA_BLOB src1,
481 CONST PCRYPT_DATA_BLOB src2)
483 dst->cbData = src1->cbData + src2->cbData;
484 dst->pbData = HeapAlloc(GetProcessHeap(), 0, dst->cbData);
485 if (!dst->pbData) {
486 SetLastError(NTE_NO_MEMORY);
487 return FALSE;
489 memcpy(dst->pbData, src1->pbData, src1->cbData);
490 memcpy(dst->pbData + src1->cbData, src2->pbData, src2->cbData);
491 return TRUE;
494 /******************************************************************************
495 * free_data_blob [Internal]
497 * releases resource occupied by a dynamically allocated CRYPT_DATA_BLOB
499 * PARAMS
500 * pBlob [I] Heap space occupied by pBlob->pbData is released
502 static inline void free_data_blob(PCRYPT_DATA_BLOB pBlob) {
503 HeapFree(GetProcessHeap(), 0, pBlob->pbData);
506 /******************************************************************************
507 * init_data_blob [Internal]
509 static inline void init_data_blob(PCRYPT_DATA_BLOB pBlob) {
510 pBlob->pbData = NULL;
511 pBlob->cbData = 0;
514 /******************************************************************************
515 * free_hmac_info [Internal]
517 * Deeply free an HMAC_INFO struct.
519 * PARAMS
520 * hmac_info [I] Pointer to the HMAC_INFO struct to be freed.
522 * NOTES
523 * See Internet RFC 2104 for details on the HMAC algorithm.
525 static inline void free_hmac_info(PHMAC_INFO hmac_info) {
526 if (!hmac_info) return;
527 HeapFree(GetProcessHeap(), 0, hmac_info->pbInnerString);
528 HeapFree(GetProcessHeap(), 0, hmac_info->pbOuterString);
529 HeapFree(GetProcessHeap(), 0, hmac_info);
532 /******************************************************************************
533 * copy_hmac_info [Internal]
535 * Deeply copy an HMAC_INFO struct
537 * PARAMS
538 * dst [O] Pointer to a location where the pointer to the HMAC_INFO copy will be stored.
539 * src [I] Pointer to the HMAC_INFO struct to be copied.
541 * RETURNS
542 * Success: TRUE
543 * Failure: FALSE
545 * NOTES
546 * See Internet RFC 2104 for details on the HMAC algorithm.
548 static BOOL copy_hmac_info(PHMAC_INFO *dst, const HMAC_INFO *src) {
549 if (!src) return FALSE;
550 *dst = HeapAlloc(GetProcessHeap(), 0, sizeof(HMAC_INFO));
551 if (!*dst) return FALSE;
552 memcpy(*dst, src, sizeof(HMAC_INFO));
553 (*dst)->pbInnerString = NULL;
554 (*dst)->pbOuterString = NULL;
555 if ((*dst)->cbInnerString == 0) (*dst)->cbInnerString = RSAENH_HMAC_DEF_PAD_LEN;
556 (*dst)->pbInnerString = HeapAlloc(GetProcessHeap(), 0, (*dst)->cbInnerString);
557 if (!(*dst)->pbInnerString) {
558 free_hmac_info(*dst);
559 return FALSE;
561 if (src->cbInnerString)
562 memcpy((*dst)->pbInnerString, src->pbInnerString, src->cbInnerString);
563 else
564 memset((*dst)->pbInnerString, RSAENH_HMAC_DEF_IPAD_CHAR, RSAENH_HMAC_DEF_PAD_LEN);
565 if ((*dst)->cbOuterString == 0) (*dst)->cbOuterString = RSAENH_HMAC_DEF_PAD_LEN;
566 (*dst)->pbOuterString = HeapAlloc(GetProcessHeap(), 0, (*dst)->cbOuterString);
567 if (!(*dst)->pbOuterString) {
568 free_hmac_info(*dst);
569 return FALSE;
571 if (src->cbOuterString)
572 memcpy((*dst)->pbOuterString, src->pbOuterString, src->cbOuterString);
573 else
574 memset((*dst)->pbOuterString, RSAENH_HMAC_DEF_OPAD_CHAR, RSAENH_HMAC_DEF_PAD_LEN);
575 return TRUE;
578 /******************************************************************************
579 * destroy_hash [Internal]
581 * Destructor for hash objects
583 * PARAMS
584 * pCryptHash [I] Pointer to the hash object to be destroyed.
585 * Will be invalid after function returns!
587 static void destroy_hash(OBJECTHDR *pObject)
589 CRYPTHASH *pCryptHash = (CRYPTHASH*)pObject;
591 free_hmac_info(pCryptHash->pHMACInfo);
592 free_data_blob(&pCryptHash->tpPRFParams.blobLabel);
593 free_data_blob(&pCryptHash->tpPRFParams.blobSeed);
594 HeapFree(GetProcessHeap(), 0, pCryptHash);
597 /******************************************************************************
598 * init_hash [Internal]
600 * Initialize (or reset) a hash object
602 * PARAMS
603 * pCryptHash [I] The hash object to be initialized.
605 static inline BOOL init_hash(CRYPTHASH *pCryptHash) {
606 DWORD dwLen;
608 switch (pCryptHash->aiAlgid)
610 case CALG_HMAC:
611 if (pCryptHash->pHMACInfo) {
612 const PROV_ENUMALGS_EX *pAlgInfo;
614 pAlgInfo = get_algid_info(pCryptHash->hProv, pCryptHash->pHMACInfo->HashAlgid);
615 if (!pAlgInfo) return FALSE;
616 pCryptHash->dwHashSize = pAlgInfo->dwDefaultLen >> 3;
617 init_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context);
618 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
619 pCryptHash->pHMACInfo->pbInnerString,
620 pCryptHash->pHMACInfo->cbInnerString);
622 return TRUE;
624 case CALG_MAC:
625 dwLen = sizeof(DWORD);
626 RSAENH_CPGetKeyParam(pCryptHash->hProv, pCryptHash->hKey, KP_BLOCKLEN,
627 (BYTE*)&pCryptHash->dwHashSize, &dwLen, 0);
628 pCryptHash->dwHashSize >>= 3;
629 return TRUE;
631 default:
632 return init_hash_impl(pCryptHash->aiAlgid, &pCryptHash->context);
636 /******************************************************************************
637 * update_hash [Internal]
639 * Hashes the given data and updates the hash object's state accordingly
641 * PARAMS
642 * pCryptHash [I] Hash object to be updated.
643 * pbData [I] Pointer to data stream to be hashed.
644 * dwDataLen [I] Length of data stream.
646 static inline void update_hash(CRYPTHASH *pCryptHash, CONST BYTE *pbData, DWORD dwDataLen) {
647 BYTE *pbTemp;
649 switch (pCryptHash->aiAlgid)
651 case CALG_HMAC:
652 if (pCryptHash->pHMACInfo)
653 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
654 pbData, dwDataLen);
655 break;
657 case CALG_MAC:
658 pbTemp = HeapAlloc(GetProcessHeap(), 0, dwDataLen);
659 if (!pbTemp) return;
660 memcpy(pbTemp, pbData, dwDataLen);
661 RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, (HCRYPTHASH)NULL, FALSE, 0,
662 pbTemp, &dwDataLen, dwDataLen);
663 HeapFree(GetProcessHeap(), 0, pbTemp);
664 break;
666 default:
667 update_hash_impl(pCryptHash->aiAlgid, &pCryptHash->context, pbData, dwDataLen);
671 /******************************************************************************
672 * finalize_hash [Internal]
674 * Finalizes the hash, after all data has been hashed with update_hash.
675 * No additional data can be hashed afterwards until the hash gets initialized again.
677 * PARAMS
678 * pCryptHash [I] Hash object to be finalized.
680 static inline void finalize_hash(CRYPTHASH *pCryptHash) {
681 DWORD dwDataLen;
683 switch (pCryptHash->aiAlgid)
685 case CALG_HMAC:
686 if (pCryptHash->pHMACInfo) {
687 BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
689 finalize_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
690 pCryptHash->abHashValue);
691 memcpy(abHashValue, pCryptHash->abHashValue, pCryptHash->dwHashSize);
692 init_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context);
693 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
694 pCryptHash->pHMACInfo->pbOuterString,
695 pCryptHash->pHMACInfo->cbOuterString);
696 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
697 abHashValue, pCryptHash->dwHashSize);
698 finalize_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
699 pCryptHash->abHashValue);
701 break;
703 case CALG_MAC:
704 dwDataLen = 0;
705 RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, (HCRYPTHASH)NULL, TRUE, 0,
706 pCryptHash->abHashValue, &dwDataLen, pCryptHash->dwHashSize);
707 break;
709 default:
710 finalize_hash_impl(pCryptHash->aiAlgid, &pCryptHash->context, pCryptHash->abHashValue);
714 /******************************************************************************
715 * destroy_key [Internal]
717 * Destructor for key objects
719 * PARAMS
720 * pCryptKey [I] Pointer to the key object to be destroyed.
721 * Will be invalid after function returns!
723 static void destroy_key(OBJECTHDR *pObject)
725 CRYPTKEY *pCryptKey = (CRYPTKEY*)pObject;
727 free_key_impl(pCryptKey->aiAlgid, &pCryptKey->context);
728 free_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom);
729 free_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom);
730 HeapFree(GetProcessHeap(), 0, pCryptKey);
733 /******************************************************************************
734 * setup_key [Internal]
736 * Initialize (or reset) a key object
738 * PARAMS
739 * pCryptKey [I] The key object to be initialized.
741 static inline void setup_key(CRYPTKEY *pCryptKey) {
742 pCryptKey->dwState = RSAENH_KEYSTATE_IDLE;
743 memcpy(pCryptKey->abChainVector, pCryptKey->abInitVector, sizeof(pCryptKey->abChainVector));
744 setup_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen,
745 pCryptKey->dwEffectiveKeyLen, pCryptKey->dwSaltLen,
746 pCryptKey->abKeyValue);
749 /******************************************************************************
750 * new_key [Internal]
752 * Creates a new key object without assigning the actual binary key value.
753 * This is done by CPDeriveKey, CPGenKey or CPImportKey, which call this function.
755 * PARAMS
756 * hProv [I] Handle to the provider to which the created key will belong.
757 * aiAlgid [I] The new key shall use the crypto algorithm idenfied by aiAlgid.
758 * dwFlags [I] Upper 16 bits give the key length.
759 * Lower 16 bits: CRYPT_CREATE_SALT, CRYPT_NO_SALT
760 * ppCryptKey [O] Pointer to the created key
762 * RETURNS
763 * Success: Handle to the created key.
764 * Failure: INVALID_HANDLE_VALUE
766 static HCRYPTKEY new_key(HCRYPTPROV hProv, ALG_ID aiAlgid, DWORD dwFlags, CRYPTKEY **ppCryptKey)
768 HCRYPTKEY hCryptKey;
769 CRYPTKEY *pCryptKey;
770 DWORD dwKeyLen = HIWORD(dwFlags);
771 const PROV_ENUMALGS_EX *peaAlgidInfo;
773 *ppCryptKey = NULL;
776 * Retrieve the CSP's capabilities for the given ALG_ID value
778 peaAlgidInfo = get_algid_info(hProv, aiAlgid);
779 if (!peaAlgidInfo) return (HCRYPTKEY)INVALID_HANDLE_VALUE;
782 * Assume the default key length, if none is specified explicitly
784 if (dwKeyLen == 0) dwKeyLen = peaAlgidInfo->dwDefaultLen;
787 * Check if the requested key length is supported by the current CSP.
788 * Adjust key length's for DES algorithms.
790 switch (aiAlgid) {
791 case CALG_DES:
792 if (dwKeyLen == RSAENH_DES_EFFECTIVE_KEYLEN) {
793 dwKeyLen = RSAENH_DES_STORAGE_KEYLEN;
795 if (dwKeyLen != RSAENH_DES_STORAGE_KEYLEN) {
796 SetLastError(NTE_BAD_FLAGS);
797 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
799 break;
801 case CALG_3DES_112:
802 if (dwKeyLen == RSAENH_3DES112_EFFECTIVE_KEYLEN) {
803 dwKeyLen = RSAENH_3DES112_STORAGE_KEYLEN;
805 if (dwKeyLen != RSAENH_3DES112_STORAGE_KEYLEN) {
806 SetLastError(NTE_BAD_FLAGS);
807 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
809 break;
811 case CALG_3DES:
812 if (dwKeyLen == RSAENH_3DES_EFFECTIVE_KEYLEN) {
813 dwKeyLen = RSAENH_3DES_STORAGE_KEYLEN;
815 if (dwKeyLen != RSAENH_3DES_STORAGE_KEYLEN) {
816 SetLastError(NTE_BAD_FLAGS);
817 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
819 break;
821 default:
822 if (dwKeyLen % 8 ||
823 dwKeyLen > peaAlgidInfo->dwMaxLen ||
824 dwKeyLen < peaAlgidInfo->dwMinLen)
826 SetLastError(NTE_BAD_FLAGS);
827 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
831 hCryptKey = (HCRYPTKEY)new_object(&handle_table, sizeof(CRYPTKEY), RSAENH_MAGIC_KEY,
832 destroy_key, (OBJECTHDR**)&pCryptKey);
833 if (hCryptKey != (HCRYPTKEY)INVALID_HANDLE_VALUE)
835 pCryptKey->aiAlgid = aiAlgid;
836 pCryptKey->hProv = hProv;
837 pCryptKey->dwModeBits = 0;
838 pCryptKey->dwPermissions = CRYPT_ENCRYPT | CRYPT_DECRYPT | CRYPT_READ | CRYPT_WRITE |
839 CRYPT_MAC;
840 pCryptKey->dwKeyLen = dwKeyLen >> 3;
841 pCryptKey->dwEffectiveKeyLen = 0;
842 if ((dwFlags & CRYPT_CREATE_SALT) || (dwKeyLen == 40 && !(dwFlags & CRYPT_NO_SALT)))
843 pCryptKey->dwSaltLen = 16 /*FIXME*/ - pCryptKey->dwKeyLen;
844 else
845 pCryptKey->dwSaltLen = 0;
846 memset(pCryptKey->abKeyValue, 0, sizeof(pCryptKey->abKeyValue));
847 memset(pCryptKey->abInitVector, 0, sizeof(pCryptKey->abInitVector));
848 init_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom);
849 init_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom);
851 switch(aiAlgid)
853 case CALG_PCT1_MASTER:
854 case CALG_SSL2_MASTER:
855 case CALG_SSL3_MASTER:
856 case CALG_TLS1_MASTER:
857 case CALG_RC4:
858 pCryptKey->dwBlockLen = 0;
859 pCryptKey->dwMode = 0;
860 break;
862 case CALG_RC2:
863 case CALG_DES:
864 case CALG_3DES_112:
865 case CALG_3DES:
866 pCryptKey->dwBlockLen = 8;
867 pCryptKey->dwMode = CRYPT_MODE_CBC;
868 break;
870 case CALG_AES:
871 case CALG_AES_128:
872 case CALG_AES_192:
873 case CALG_AES_256:
874 pCryptKey->dwBlockLen = 16;
875 pCryptKey->dwMode = CRYPT_MODE_ECB;
876 break;
878 case CALG_RSA_KEYX:
879 case CALG_RSA_SIGN:
880 pCryptKey->dwBlockLen = dwKeyLen >> 3;
881 pCryptKey->dwMode = 0;
882 break;
885 *ppCryptKey = pCryptKey;
888 return hCryptKey;
891 /******************************************************************************
892 * store_key_pair [Internal]
894 * Stores a key pair to the registry
896 * PARAMS
897 * hCryptKey [I] Handle to the key to be stored
898 * hKey [I] Registry key where the key pair is to be stored
899 * szValueName [I] Registry value where key pair's value is to be stored
900 * dwFlags [I] Flags for protecting the key
902 static void store_key_pair(HCRYPTKEY hCryptKey, HKEY hKey, LPCSTR szValueName, DWORD dwFlags)
904 DATA_BLOB blobIn, blobOut;
905 CRYPTKEY *pKey;
906 DWORD dwLen;
907 BYTE *pbKey;
909 if (lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY,
910 (OBJECTHDR**)&pKey))
912 if (RSAENH_CPExportKey(pKey->hProv, hCryptKey, 0, PRIVATEKEYBLOB, 0, 0,
913 &dwLen))
915 pbKey = HeapAlloc(GetProcessHeap(), 0, dwLen);
916 if (pbKey)
918 if (RSAENH_CPExportKey(pKey->hProv, hCryptKey, 0,
919 PRIVATEKEYBLOB, 0, pbKey, &dwLen))
921 blobIn.pbData = pbKey;
922 blobIn.cbData = dwLen;
924 if (CryptProtectData(&blobIn, NULL, NULL, NULL, NULL,
925 dwFlags, &blobOut))
927 RegSetValueExA(hKey, szValueName, 0, REG_BINARY,
928 blobOut.pbData, blobOut.cbData);
929 LocalFree(blobOut.pbData);
932 HeapFree(GetProcessHeap(), 0, pbKey);
935 release_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY);
939 /******************************************************************************
940 * create_container_key [Internal]
942 * Creates the registry key for a key container's persistent storage.
944 * PARAMS
945 * pKeyContainer [I] Pointer to the key container
946 * sam [I] Desired registry access
947 * phKey [O] Returned key
949 static BOOL create_container_key(KEYCONTAINER *pKeyContainer, REGSAM sam, HKEY *phKey)
951 CHAR szRSABase[MAX_PATH];
952 HKEY hRootKey;
954 sprintf(szRSABase, RSAENH_REGKEY, pKeyContainer->szName);
956 if (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET)
957 hRootKey = HKEY_LOCAL_MACHINE;
958 else
959 hRootKey = HKEY_CURRENT_USER;
961 /* @@ Wine registry key: HKLM\Software\Wine\Crypto\RSA */
962 /* @@ Wine registry key: HKCU\Software\Wine\Crypto\RSA */
963 return RegCreateKeyExA(hRootKey, szRSABase, 0, NULL,
964 REG_OPTION_NON_VOLATILE, sam, NULL, phKey, NULL)
965 == ERROR_SUCCESS;
968 /******************************************************************************
969 * open_container_key [Internal]
971 * Opens a key container's persistent storage for reading.
973 * PARAMS
974 * pszContainerName [I] Name of the container to be opened. May be the empty
975 * string if the parent key of all containers is to be
976 * opened.
977 * dwFlags [I] Flags indicating which keyset to be opened.
978 * phKey [O] Returned key
980 static BOOL open_container_key(LPCSTR pszContainerName, DWORD dwFlags, HKEY *phKey)
982 CHAR szRSABase[MAX_PATH];
983 HKEY hRootKey;
985 sprintf(szRSABase, RSAENH_REGKEY, pszContainerName);
987 if (dwFlags & CRYPT_MACHINE_KEYSET)
988 hRootKey = HKEY_LOCAL_MACHINE;
989 else
990 hRootKey = HKEY_CURRENT_USER;
992 /* @@ Wine registry key: HKLM\Software\Wine\Crypto\RSA */
993 /* @@ Wine registry key: HKCU\Software\Wine\Crypto\RSA */
994 return RegOpenKeyExA(hRootKey, szRSABase, 0, KEY_READ, phKey) ==
995 ERROR_SUCCESS;
998 /******************************************************************************
999 * delete_container_key [Internal]
1001 * Deletes a key container's persistent storage.
1003 * PARAMS
1004 * pszContainerName [I] Name of the container to be opened.
1005 * dwFlags [I] Flags indicating which keyset to be opened.
1007 static BOOL delete_container_key(LPCSTR pszContainerName, DWORD dwFlags)
1009 CHAR szRegKey[MAX_PATH];
1011 if (snprintf(szRegKey, MAX_PATH, RSAENH_REGKEY, pszContainerName) >= MAX_PATH) {
1012 SetLastError(NTE_BAD_KEYSET_PARAM);
1013 return FALSE;
1014 } else {
1015 HKEY hRootKey;
1016 if (dwFlags & CRYPT_MACHINE_KEYSET)
1017 hRootKey = HKEY_LOCAL_MACHINE;
1018 else
1019 hRootKey = HKEY_CURRENT_USER;
1020 if (!RegDeleteKeyA(hRootKey, szRegKey)) {
1021 SetLastError(ERROR_SUCCESS);
1022 return TRUE;
1023 } else {
1024 SetLastError(NTE_BAD_KEYSET);
1025 return FALSE;
1030 /******************************************************************************
1031 * store_key_container_keys [Internal]
1033 * Stores key container's keys in a persistent location.
1035 * PARAMS
1036 * pKeyContainer [I] Pointer to the key container whose keys are to be saved
1038 static void store_key_container_keys(KEYCONTAINER *pKeyContainer)
1040 HKEY hKey;
1041 DWORD dwFlags;
1043 /* On WinXP, persistent keys are stored in a file located at:
1044 * $AppData$\\Microsoft\\Crypto\\RSA\\$SID$\\some_hex_string
1047 if (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET)
1048 dwFlags = CRYPTPROTECT_LOCAL_MACHINE;
1049 else
1050 dwFlags = 0;
1052 if (create_container_key(pKeyContainer, KEY_WRITE, &hKey))
1054 store_key_pair(pKeyContainer->hKeyExchangeKeyPair, hKey,
1055 "KeyExchangeKeyPair", dwFlags);
1056 store_key_pair(pKeyContainer->hSignatureKeyPair, hKey,
1057 "SignatureKeyPair", dwFlags);
1058 RegCloseKey(hKey);
1062 /******************************************************************************
1063 * destroy_key_container [Internal]
1065 * Destructor for key containers.
1067 * PARAMS
1068 * pObjectHdr [I] Pointer to the key container to be destroyed.
1070 static void destroy_key_container(OBJECTHDR *pObjectHdr)
1072 KEYCONTAINER *pKeyContainer = (KEYCONTAINER*)pObjectHdr;
1074 if (!(pKeyContainer->dwFlags & CRYPT_VERIFYCONTEXT))
1075 store_key_container_keys(pKeyContainer);
1076 HeapFree( GetProcessHeap(), 0, pKeyContainer );
1079 /******************************************************************************
1080 * new_key_container [Internal]
1082 * Create a new key container. The personality (RSA Base, Strong or Enhanced CP)
1083 * of the CSP is determined via the pVTable->pszProvName string.
1085 * PARAMS
1086 * pszContainerName [I] Name of the key container.
1087 * pVTable [I] Callback functions and context info provided by the OS
1089 * RETURNS
1090 * Success: Handle to the new key container.
1091 * Failure: INVALID_HANDLE_VALUE
1093 static HCRYPTPROV new_key_container(PCCH pszContainerName, DWORD dwFlags, const VTableProvStruc *pVTable)
1095 KEYCONTAINER *pKeyContainer;
1096 HCRYPTPROV hKeyContainer;
1098 hKeyContainer = (HCRYPTPROV)new_object(&handle_table, sizeof(KEYCONTAINER), RSAENH_MAGIC_CONTAINER,
1099 destroy_key_container, (OBJECTHDR**)&pKeyContainer);
1100 if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE)
1102 lstrcpynA(pKeyContainer->szName, pszContainerName, MAX_PATH);
1103 pKeyContainer->dwFlags = dwFlags;
1104 pKeyContainer->dwEnumAlgsCtr = 0;
1105 pKeyContainer->hKeyExchangeKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE;
1106 pKeyContainer->hSignatureKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE;
1107 if (pVTable && pVTable->pszProvName) {
1108 lstrcpynA(pKeyContainer->szProvName, pVTable->pszProvName, MAX_PATH);
1109 if (!strcmp(pVTable->pszProvName, MS_DEF_PROV_A)) {
1110 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_BASE;
1111 } else if (!strcmp(pVTable->pszProvName, MS_ENHANCED_PROV_A)) {
1112 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_ENHANCED;
1113 } else if (!strcmp(pVTable->pszProvName, MS_DEF_RSA_SCHANNEL_PROV_A)) {
1114 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_SCHANNEL;
1115 } else if (!strcmp(pVTable->pszProvName, MS_ENH_RSA_AES_PROV_A)) {
1116 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_AES;
1117 } else {
1118 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_STRONG;
1122 /* The new key container has to be inserted into the CSP immediately
1123 * after creation to be available for CPGetProvParam's PP_ENUMCONTAINERS. */
1124 if (!(dwFlags & CRYPT_VERIFYCONTEXT)) {
1125 HKEY hKey;
1127 if (create_container_key(pKeyContainer, KEY_WRITE, &hKey))
1128 RegCloseKey(hKey);
1132 return hKeyContainer;
1135 /******************************************************************************
1136 * read_key_value [Internal]
1138 * Reads a key pair value from the registry
1140 * PARAMS
1141 * hKeyContainer [I] Crypt provider to use to import the key
1142 * hKey [I] Registry key from which to read the key pair
1143 * szValueName [I] Registry value from which to read the key pair's value
1144 * dwFlags [I] Flags for unprotecting the key
1145 * phCryptKey [O] Returned key
1147 static BOOL read_key_value(HCRYPTPROV hKeyContainer, HKEY hKey, LPCSTR szValueName, DWORD dwFlags, HCRYPTKEY *phCryptKey)
1149 DWORD dwValueType, dwLen;
1150 BYTE *pbKey;
1151 DATA_BLOB blobIn, blobOut;
1152 BOOL ret = FALSE;
1154 if (RegQueryValueExA(hKey, szValueName, 0, &dwValueType, NULL, &dwLen) ==
1155 ERROR_SUCCESS)
1157 pbKey = HeapAlloc(GetProcessHeap(), 0, dwLen);
1158 if (pbKey)
1160 if (RegQueryValueExA(hKey, szValueName, 0, &dwValueType, pbKey, &dwLen) ==
1161 ERROR_SUCCESS)
1163 blobIn.pbData = pbKey;
1164 blobIn.cbData = dwLen;
1166 if (CryptUnprotectData(&blobIn, NULL, NULL, NULL, NULL,
1167 dwFlags, &blobOut))
1169 ret = RSAENH_CPImportKey(hKeyContainer, blobOut.pbData, blobOut.cbData, 0, 0,
1170 phCryptKey);
1171 LocalFree(blobOut.pbData);
1174 HeapFree(GetProcessHeap(), 0, pbKey);
1177 return ret;
1180 /******************************************************************************
1181 * read_key_container [Internal]
1183 * Tries to read the persistent state of the key container (mainly the signature
1184 * and key exchange private keys) given by pszContainerName.
1186 * PARAMS
1187 * pszContainerName [I] Name of the key container to read from the registry
1188 * pVTable [I] Pointer to context data provided by the operating system
1190 * RETURNS
1191 * Success: Handle to the key container read from the registry
1192 * Failure: INVALID_HANDLE_VALUE
1194 static HCRYPTPROV read_key_container(PCHAR pszContainerName, DWORD dwFlags, const VTableProvStruc *pVTable)
1196 HKEY hKey;
1197 KEYCONTAINER *pKeyContainer;
1198 HCRYPTPROV hKeyContainer;
1199 HCRYPTKEY hCryptKey;
1201 if (!open_container_key(pszContainerName, dwFlags, &hKey))
1203 SetLastError(NTE_BAD_KEYSET);
1204 return (HCRYPTPROV)INVALID_HANDLE_VALUE;
1207 hKeyContainer = new_key_container(pszContainerName, dwFlags, pVTable);
1208 if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE)
1210 DWORD dwProtectFlags = (dwFlags & CRYPT_MACHINE_KEYSET) ?
1211 CRYPTPROTECT_LOCAL_MACHINE : 0;
1213 if (!lookup_handle(&handle_table, hKeyContainer, RSAENH_MAGIC_CONTAINER,
1214 (OBJECTHDR**)&pKeyContainer))
1215 return (HCRYPTPROV)INVALID_HANDLE_VALUE;
1217 if (read_key_value(hKeyContainer, hKey, "KeyExchangeKeyPair",
1218 dwProtectFlags, &hCryptKey))
1219 pKeyContainer->hKeyExchangeKeyPair = hCryptKey;
1220 if (read_key_value(hKeyContainer, hKey, "SignatureKeyPair",
1221 dwProtectFlags, &hCryptKey))
1222 pKeyContainer->hSignatureKeyPair = hCryptKey;
1225 return hKeyContainer;
1228 /******************************************************************************
1229 * build_hash_signature [Internal]
1231 * Builds a padded version of a hash to match the length of the RSA key modulus.
1233 * PARAMS
1234 * pbSignature [O] The padded hash object is stored here.
1235 * dwLen [I] Length of the pbSignature buffer.
1236 * aiAlgid [I] Algorithm identifier of the hash to be padded.
1237 * abHashValue [I] The value of the hash object.
1238 * dwHashLen [I] Length of the hash value.
1239 * dwFlags [I] Selection of padding algorithm.
1241 * RETURNS
1242 * Success: TRUE
1243 * Failure: FALSE (NTE_BAD_ALGID)
1245 static BOOL build_hash_signature(BYTE *pbSignature, DWORD dwLen, ALG_ID aiAlgid,
1246 CONST BYTE *abHashValue, DWORD dwHashLen, DWORD dwFlags)
1248 /* These prefixes are meant to be concatenated with hash values of the
1249 * respective kind to form a PKCS #7 DigestInfo. */
1250 static const struct tagOIDDescriptor {
1251 ALG_ID aiAlgid;
1252 DWORD dwLen;
1253 CONST BYTE abOID[18];
1254 } aOIDDescriptor[5] = {
1255 { CALG_MD2, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
1256 0x86, 0xf7, 0x0d, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10 } },
1257 { CALG_MD4, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
1258 0x86, 0xf7, 0x0d, 0x02, 0x04, 0x05, 0x00, 0x04, 0x10 } },
1259 { CALG_MD5, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
1260 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 } },
1261 { CALG_SHA, 15, { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
1262 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 } },
1263 { 0, 0, {} }
1265 DWORD dwIdxOID, i, j;
1267 for (dwIdxOID = 0; aOIDDescriptor[dwIdxOID].aiAlgid; dwIdxOID++) {
1268 if (aOIDDescriptor[dwIdxOID].aiAlgid == aiAlgid) break;
1271 if (!aOIDDescriptor[dwIdxOID].aiAlgid) {
1272 SetLastError(NTE_BAD_ALGID);
1273 return FALSE;
1276 /* Build the padded signature */
1277 if (dwFlags & CRYPT_X931_FORMAT) {
1278 pbSignature[0] = 0x6b;
1279 for (i=1; i < dwLen - dwHashLen - 3; i++) {
1280 pbSignature[i] = 0xbb;
1282 pbSignature[i++] = 0xba;
1283 for (j=0; j < dwHashLen; j++, i++) {
1284 pbSignature[i] = abHashValue[j];
1286 pbSignature[i++] = 0x33;
1287 pbSignature[i++] = 0xcc;
1288 } else {
1289 pbSignature[0] = 0x00;
1290 pbSignature[1] = 0x01;
1291 if (dwFlags & CRYPT_NOHASHOID) {
1292 for (i=2; i < dwLen - 1 - dwHashLen; i++) {
1293 pbSignature[i] = 0xff;
1295 pbSignature[i++] = 0x00;
1296 } else {
1297 for (i=2; i < dwLen - 1 - aOIDDescriptor[dwIdxOID].dwLen - dwHashLen; i++) {
1298 pbSignature[i] = 0xff;
1300 pbSignature[i++] = 0x00;
1301 for (j=0; j < aOIDDescriptor[dwIdxOID].dwLen; j++) {
1302 pbSignature[i++] = aOIDDescriptor[dwIdxOID].abOID[j];
1305 for (j=0; j < dwHashLen; j++) {
1306 pbSignature[i++] = abHashValue[j];
1310 return TRUE;
1313 /******************************************************************************
1314 * tls1_p [Internal]
1316 * This is an implementation of the 'P_hash' helper function for TLS1's PRF.
1317 * It is used exclusively by tls1_prf. For details see RFC 2246, chapter 5.
1318 * The pseudo random stream generated by this function is exclusive or'ed with
1319 * the data in pbBuffer.
1321 * PARAMS
1322 * hHMAC [I] HMAC object, which will be used in pseudo random generation
1323 * pblobSeed [I] Seed value
1324 * pbBuffer [I/O] Pseudo random stream will be xor'ed to the provided data
1325 * dwBufferLen [I] Number of pseudo random bytes desired
1327 * RETURNS
1328 * Success: TRUE
1329 * Failure: FALSE
1331 static BOOL tls1_p(HCRYPTHASH hHMAC, CONST PCRYPT_DATA_BLOB pblobSeed, PBYTE pbBuffer, DWORD dwBufferLen)
1333 CRYPTHASH *pHMAC;
1334 BYTE abAi[RSAENH_MAX_HASH_SIZE];
1335 DWORD i = 0;
1337 if (!lookup_handle(&handle_table, hHMAC, RSAENH_MAGIC_HASH, (OBJECTHDR**)&pHMAC)) {
1338 SetLastError(NTE_BAD_HASH);
1339 return FALSE;
1342 /* compute A_1 = HMAC(seed) */
1343 init_hash(pHMAC);
1344 update_hash(pHMAC, pblobSeed->pbData, pblobSeed->cbData);
1345 finalize_hash(pHMAC);
1346 memcpy(abAi, pHMAC->abHashValue, pHMAC->dwHashSize);
1348 do {
1349 /* compute HMAC(A_i + seed) */
1350 init_hash(pHMAC);
1351 update_hash(pHMAC, abAi, pHMAC->dwHashSize);
1352 update_hash(pHMAC, pblobSeed->pbData, pblobSeed->cbData);
1353 finalize_hash(pHMAC);
1355 /* pseudo random stream := CONCAT_{i=1..n} ( HMAC(A_i + seed) ) */
1356 do {
1357 if (i >= dwBufferLen) break;
1358 pbBuffer[i] ^= pHMAC->abHashValue[i % pHMAC->dwHashSize];
1359 i++;
1360 } while (i % pHMAC->dwHashSize);
1362 /* compute A_{i+1} = HMAC(A_i) */
1363 init_hash(pHMAC);
1364 update_hash(pHMAC, abAi, pHMAC->dwHashSize);
1365 finalize_hash(pHMAC);
1366 memcpy(abAi, pHMAC->abHashValue, pHMAC->dwHashSize);
1367 } while (i < dwBufferLen);
1369 return TRUE;
1372 /******************************************************************************
1373 * tls1_prf [Internal]
1375 * TLS1 pseudo random function as specified in RFC 2246, chapter 5
1377 * PARAMS
1378 * hProv [I] Key container used to compute the pseudo random stream
1379 * hSecret [I] Key that holds the (pre-)master secret
1380 * pblobLabel [I] Descriptive label
1381 * pblobSeed [I] Seed value
1382 * pbBuffer [O] Pseudo random numbers will be stored here
1383 * dwBufferLen [I] Number of pseudo random bytes desired
1385 * RETURNS
1386 * Success: TRUE
1387 * Failure: FALSE
1389 static BOOL tls1_prf(HCRYPTPROV hProv, HCRYPTPROV hSecret, CONST PCRYPT_DATA_BLOB pblobLabel,
1390 CONST PCRYPT_DATA_BLOB pblobSeed, PBYTE pbBuffer, DWORD dwBufferLen)
1392 HMAC_INFO hmacInfo = { 0, NULL, 0, NULL, 0 };
1393 HCRYPTHASH hHMAC = (HCRYPTHASH)INVALID_HANDLE_VALUE;
1394 HCRYPTKEY hHalfSecret = (HCRYPTKEY)INVALID_HANDLE_VALUE;
1395 CRYPTKEY *pHalfSecret, *pSecret;
1396 DWORD dwHalfSecretLen;
1397 BOOL result = FALSE;
1398 CRYPT_DATA_BLOB blobLabelSeed;
1400 TRACE("(hProv=%08lx, hSecret=%08lx, pblobLabel=%p, pblobSeed=%p, pbBuffer=%p, dwBufferLen=%d)\n",
1401 hProv, hSecret, pblobLabel, pblobSeed, pbBuffer, dwBufferLen);
1403 if (!lookup_handle(&handle_table, hSecret, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pSecret)) {
1404 SetLastError(NTE_FAIL);
1405 return FALSE;
1408 dwHalfSecretLen = (pSecret->dwKeyLen+1)/2;
1410 /* concatenation of the label and the seed */
1411 if (!concat_data_blobs(&blobLabelSeed, pblobLabel, pblobSeed)) goto exit;
1413 /* zero out the buffer, since two random streams will be xor'ed into it. */
1414 memset(pbBuffer, 0, dwBufferLen);
1416 /* build a 'fake' key, to hold the secret. CALG_SSL2_MASTER is used since it provides
1417 * the biggest range of valid key lengths. */
1418 hHalfSecret = new_key(hProv, CALG_SSL2_MASTER, MAKELONG(0,dwHalfSecretLen*8), &pHalfSecret);
1419 if (hHalfSecret == (HCRYPTKEY)INVALID_HANDLE_VALUE) goto exit;
1421 /* Derive an HMAC_MD5 hash and call the helper function. */
1422 memcpy(pHalfSecret->abKeyValue, pSecret->abKeyValue, dwHalfSecretLen);
1423 if (!RSAENH_CPCreateHash(hProv, CALG_HMAC, hHalfSecret, 0, &hHMAC)) goto exit;
1424 hmacInfo.HashAlgid = CALG_MD5;
1425 if (!RSAENH_CPSetHashParam(hProv, hHMAC, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0)) goto exit;
1426 if (!tls1_p(hHMAC, &blobLabelSeed, pbBuffer, dwBufferLen)) goto exit;
1428 /* Reconfigure to HMAC_SHA hash and call helper function again. */
1429 memcpy(pHalfSecret->abKeyValue, pSecret->abKeyValue + (pSecret->dwKeyLen/2), dwHalfSecretLen);
1430 hmacInfo.HashAlgid = CALG_SHA;
1431 if (!RSAENH_CPSetHashParam(hProv, hHMAC, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0)) goto exit;
1432 if (!tls1_p(hHMAC, &blobLabelSeed, pbBuffer, dwBufferLen)) goto exit;
1434 result = TRUE;
1435 exit:
1436 release_handle(&handle_table, hHalfSecret, RSAENH_MAGIC_KEY);
1437 if (hHMAC != (HCRYPTHASH)INVALID_HANDLE_VALUE) RSAENH_CPDestroyHash(hProv, hHMAC);
1438 free_data_blob(&blobLabelSeed);
1439 return result;
1442 /******************************************************************************
1443 * pad_data [Internal]
1445 * Helper function for data padding according to PKCS1 #2
1447 * PARAMS
1448 * abData [I] The data to be padded
1449 * dwDataLen [I] Length of the data
1450 * abBuffer [O] Padded data will be stored here
1451 * dwBufferLen [I] Length of the buffer (also length of padded data)
1452 * dwFlags [I] Padding format (CRYPT_SSL2_FALLBACK)
1454 * RETURN
1455 * Success: TRUE
1456 * Failure: FALSE (NTE_BAD_LEN, too much data to pad)
1458 static BOOL pad_data(CONST BYTE *abData, DWORD dwDataLen, BYTE *abBuffer, DWORD dwBufferLen,
1459 DWORD dwFlags)
1461 DWORD i;
1463 /* Ensure there is enough space for PKCS1 #2 padding */
1464 if (dwDataLen > dwBufferLen-11) {
1465 SetLastError(NTE_BAD_LEN);
1466 return FALSE;
1469 memmove(abBuffer + dwBufferLen - dwDataLen, abData, dwDataLen);
1471 abBuffer[0] = 0x00;
1472 abBuffer[1] = RSAENH_PKC_BLOCKTYPE;
1473 for (i=2; i < dwBufferLen - dwDataLen - 1; i++)
1474 do gen_rand_impl(&abBuffer[i], 1); while (!abBuffer[i]);
1475 if (dwFlags & CRYPT_SSL2_FALLBACK)
1476 for (i-=8; i < dwBufferLen - dwDataLen - 1; i++)
1477 abBuffer[i] = 0x03;
1478 abBuffer[i] = 0x00;
1480 return TRUE;
1483 /******************************************************************************
1484 * unpad_data [Internal]
1486 * Remove the PKCS1 padding from RSA decrypted data
1488 * PARAMS
1489 * abData [I] The padded data
1490 * dwDataLen [I] Length of the padded data
1491 * abBuffer [O] Data without padding will be stored here
1492 * dwBufferLen [I/O] I: Length of the buffer, O: Length of unpadded data
1493 * dwFlags [I] Currently none defined
1495 * RETURNS
1496 * Success: TRUE
1497 * Failure: FALSE, (NTE_BAD_DATA, no valid PKCS1 padding or buffer too small)
1499 static BOOL unpad_data(CONST BYTE *abData, DWORD dwDataLen, BYTE *abBuffer, DWORD *dwBufferLen,
1500 DWORD dwFlags)
1502 DWORD i;
1504 for (i=2; i<dwDataLen; i++)
1505 if (!abData[i])
1506 break;
1508 if ((i == dwDataLen) || (*dwBufferLen < dwDataLen - i - 1) ||
1509 (abData[0] != 0x00) || (abData[1] != RSAENH_PKC_BLOCKTYPE))
1511 SetLastError(NTE_BAD_DATA);
1512 return FALSE;
1515 *dwBufferLen = dwDataLen - i - 1;
1516 memmove(abBuffer, abData + i + 1, *dwBufferLen);
1517 return TRUE;
1520 /******************************************************************************
1521 * CPAcquireContext (RSAENH.@)
1523 * Acquire a handle to the key container specified by pszContainer
1525 * PARAMS
1526 * phProv [O] Pointer to the location the acquired handle will be written to.
1527 * pszContainer [I] Name of the desired key container. See Notes
1528 * dwFlags [I] Flags. See Notes.
1529 * pVTable [I] Pointer to a PVTableProvStruct containing callbacks.
1531 * RETURNS
1532 * Success: TRUE
1533 * Failure: FALSE
1535 * NOTES
1536 * If pszContainer is NULL or points to a zero length string the user's login
1537 * name will be used as the key container name.
1539 * If the CRYPT_NEW_KEYSET flag is set in dwFlags a new keyset will be created.
1540 * If a keyset with the given name already exists, the function fails and sets
1541 * last error to NTE_EXISTS. If CRYPT_NEW_KEYSET is not set and the specified
1542 * key container does not exist, function fails and sets last error to
1543 * NTE_BAD_KEYSET.
1545 BOOL WINAPI RSAENH_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer,
1546 DWORD dwFlags, PVTableProvStruc pVTable)
1548 CHAR szKeyContainerName[MAX_PATH];
1550 TRACE("(phProv=%p, pszContainer=%s, dwFlags=%08x, pVTable=%p)\n", phProv,
1551 debugstr_a(pszContainer), dwFlags, pVTable);
1553 if (pszContainer && *pszContainer)
1555 lstrcpynA(szKeyContainerName, pszContainer, MAX_PATH);
1557 else
1559 DWORD dwLen = sizeof(szKeyContainerName);
1560 if (!GetUserNameA(szKeyContainerName, &dwLen)) return FALSE;
1563 switch (dwFlags & (CRYPT_NEWKEYSET|CRYPT_VERIFYCONTEXT|CRYPT_DELETEKEYSET))
1565 case 0:
1566 *phProv = read_key_container(szKeyContainerName, dwFlags, pVTable);
1567 break;
1569 case CRYPT_DELETEKEYSET:
1570 return delete_container_key(szKeyContainerName, dwFlags);
1572 case CRYPT_NEWKEYSET:
1573 *phProv = read_key_container(szKeyContainerName, dwFlags, pVTable);
1574 if (*phProv != (HCRYPTPROV)INVALID_HANDLE_VALUE)
1576 release_handle(&handle_table, *phProv, RSAENH_MAGIC_CONTAINER);
1577 TRACE("Can't create new keyset, already exists\n");
1578 SetLastError(NTE_EXISTS);
1579 return FALSE;
1581 *phProv = new_key_container(szKeyContainerName, dwFlags, pVTable);
1582 break;
1584 case CRYPT_VERIFYCONTEXT|CRYPT_NEWKEYSET:
1585 case CRYPT_VERIFYCONTEXT:
1586 if (pszContainer && *pszContainer) {
1587 TRACE("pszContainer should be empty\n");
1588 SetLastError(NTE_BAD_FLAGS);
1589 return FALSE;
1591 *phProv = new_key_container("", dwFlags, pVTable);
1592 break;
1594 default:
1595 *phProv = (HCRYPTPROV)INVALID_HANDLE_VALUE;
1596 SetLastError(NTE_BAD_FLAGS);
1597 return FALSE;
1600 if (*phProv != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
1601 SetLastError(ERROR_SUCCESS);
1602 return TRUE;
1603 } else {
1604 return FALSE;
1608 /******************************************************************************
1609 * CPCreateHash (RSAENH.@)
1611 * CPCreateHash creates and initalizes a new hash object.
1613 * PARAMS
1614 * hProv [I] Handle to the key container to which the new hash will belong.
1615 * Algid [I] Identifies the hash algorithm, which will be used for the hash.
1616 * hKey [I] Handle to a session key applied for keyed hashes.
1617 * dwFlags [I] Currently no flags defined. Must be zero.
1618 * phHash [O] Points to the location where a handle to the new hash will be stored.
1620 * RETURNS
1621 * Success: TRUE
1622 * Failure: FALSE
1624 * NOTES
1625 * hKey is a handle to a session key applied in keyed hashes like MAC and HMAC.
1626 * If a normal hash object is to be created (like e.g. MD2 or SHA1) hKey must be zero.
1628 BOOL WINAPI RSAENH_CPCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags,
1629 HCRYPTHASH *phHash)
1631 CRYPTKEY *pCryptKey;
1632 CRYPTHASH *pCryptHash;
1633 const PROV_ENUMALGS_EX *peaAlgidInfo;
1635 TRACE("(hProv=%08lx, Algid=%08x, hKey=%08lx, dwFlags=%08x, phHash=%p)\n", hProv, Algid, hKey,
1636 dwFlags, phHash);
1638 peaAlgidInfo = get_algid_info(hProv, Algid);
1639 if (!peaAlgidInfo) return FALSE;
1641 if (dwFlags)
1643 SetLastError(NTE_BAD_FLAGS);
1644 return FALSE;
1647 if (Algid == CALG_MAC || Algid == CALG_HMAC || Algid == CALG_SCHANNEL_MASTER_HASH ||
1648 Algid == CALG_TLS1PRF)
1650 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey)) {
1651 SetLastError(NTE_BAD_KEY);
1652 return FALSE;
1655 if ((Algid == CALG_MAC) && (GET_ALG_TYPE(pCryptKey->aiAlgid) != ALG_TYPE_BLOCK)) {
1656 SetLastError(NTE_BAD_KEY);
1657 return FALSE;
1660 if ((Algid == CALG_SCHANNEL_MASTER_HASH || Algid == CALG_TLS1PRF) &&
1661 (pCryptKey->aiAlgid != CALG_TLS1_MASTER))
1663 SetLastError(NTE_BAD_KEY);
1664 return FALSE;
1667 if ((Algid == CALG_TLS1PRF) && (pCryptKey->dwState != RSAENH_KEYSTATE_MASTERKEY)) {
1668 SetLastError(NTE_BAD_KEY_STATE);
1669 return FALSE;
1673 *phHash = (HCRYPTHASH)new_object(&handle_table, sizeof(CRYPTHASH), RSAENH_MAGIC_HASH,
1674 destroy_hash, (OBJECTHDR**)&pCryptHash);
1675 if (!pCryptHash) return FALSE;
1677 pCryptHash->aiAlgid = Algid;
1678 pCryptHash->hKey = hKey;
1679 pCryptHash->hProv = hProv;
1680 pCryptHash->dwState = RSAENH_HASHSTATE_HASHING;
1681 pCryptHash->pHMACInfo = (PHMAC_INFO)NULL;
1682 pCryptHash->dwHashSize = peaAlgidInfo->dwDefaultLen >> 3;
1683 init_data_blob(&pCryptHash->tpPRFParams.blobLabel);
1684 init_data_blob(&pCryptHash->tpPRFParams.blobSeed);
1686 if (Algid == CALG_SCHANNEL_MASTER_HASH) {
1687 static const char keyex[] = "key expansion";
1688 BYTE key_expansion[sizeof keyex];
1689 CRYPT_DATA_BLOB blobRandom, blobKeyExpansion = { 13, key_expansion };
1691 memcpy( key_expansion, keyex, sizeof keyex );
1693 if (pCryptKey->dwState != RSAENH_KEYSTATE_MASTERKEY) {
1694 static const char msec[] = "master secret";
1695 BYTE master_secret[sizeof msec];
1696 CRYPT_DATA_BLOB blobLabel = { 13, master_secret };
1697 BYTE abKeyValue[48];
1699 memcpy( master_secret, msec, sizeof msec );
1701 /* See RFC 2246, chapter 8.1 */
1702 if (!concat_data_blobs(&blobRandom,
1703 &pCryptKey->siSChannelInfo.blobClientRandom,
1704 &pCryptKey->siSChannelInfo.blobServerRandom))
1706 return FALSE;
1708 tls1_prf(hProv, hKey, &blobLabel, &blobRandom, abKeyValue, 48);
1709 pCryptKey->dwState = RSAENH_KEYSTATE_MASTERKEY;
1710 memcpy(pCryptKey->abKeyValue, abKeyValue, 48);
1711 free_data_blob(&blobRandom);
1714 /* See RFC 2246, chapter 6.3 */
1715 if (!concat_data_blobs(&blobRandom,
1716 &pCryptKey->siSChannelInfo.blobServerRandom,
1717 &pCryptKey->siSChannelInfo.blobClientRandom))
1719 return FALSE;
1721 tls1_prf(hProv, hKey, &blobKeyExpansion, &blobRandom, pCryptHash->abHashValue,
1722 RSAENH_MAX_HASH_SIZE);
1723 free_data_blob(&blobRandom);
1726 return init_hash(pCryptHash);
1729 /******************************************************************************
1730 * CPDestroyHash (RSAENH.@)
1732 * Releases the handle to a hash object. The object is destroyed if it's reference
1733 * count reaches zero.
1735 * PARAMS
1736 * hProv [I] Handle to the key container to which the hash object belongs.
1737 * hHash [I] Handle to the hash object to be released.
1739 * RETURNS
1740 * Success: TRUE
1741 * Failure: FALSE
1743 BOOL WINAPI RSAENH_CPDestroyHash(HCRYPTPROV hProv, HCRYPTHASH hHash)
1745 TRACE("(hProv=%08lx, hHash=%08lx)\n", hProv, hHash);
1747 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
1749 SetLastError(NTE_BAD_UID);
1750 return FALSE;
1753 if (!release_handle(&handle_table, hHash, RSAENH_MAGIC_HASH))
1755 SetLastError(NTE_BAD_HASH);
1756 return FALSE;
1759 return TRUE;
1762 /******************************************************************************
1763 * CPDestroyKey (RSAENH.@)
1765 * Releases the handle to a key object. The object is destroyed if it's reference
1766 * count reaches zero.
1768 * PARAMS
1769 * hProv [I] Handle to the key container to which the key object belongs.
1770 * hKey [I] Handle to the key object to be released.
1772 * RETURNS
1773 * Success: TRUE
1774 * Failure: FALSE
1776 BOOL WINAPI RSAENH_CPDestroyKey(HCRYPTPROV hProv, HCRYPTKEY hKey)
1778 TRACE("(hProv=%08lx, hKey=%08lx)\n", hProv, hKey);
1780 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
1782 SetLastError(NTE_BAD_UID);
1783 return FALSE;
1786 if (!release_handle(&handle_table, hKey, RSAENH_MAGIC_KEY))
1788 SetLastError(NTE_BAD_KEY);
1789 return FALSE;
1792 return TRUE;
1795 /******************************************************************************
1796 * CPDuplicateHash (RSAENH.@)
1798 * Clones a hash object including it's current state.
1800 * PARAMS
1801 * hUID [I] Handle to the key container the hash belongs to.
1802 * hHash [I] Handle to the hash object to be cloned.
1803 * pdwReserved [I] Reserved. Must be NULL.
1804 * dwFlags [I] No flags are currently defined. Must be 0.
1805 * phHash [O] Handle to the cloned hash object.
1807 * RETURNS
1808 * Success: TRUE.
1809 * Failure: FALSE.
1811 BOOL WINAPI RSAENH_CPDuplicateHash(HCRYPTPROV hUID, HCRYPTHASH hHash, DWORD *pdwReserved,
1812 DWORD dwFlags, HCRYPTHASH *phHash)
1814 CRYPTHASH *pSrcHash, *pDestHash;
1816 TRACE("(hUID=%08lx, hHash=%08lx, pdwReserved=%p, dwFlags=%08x, phHash=%p)\n", hUID, hHash,
1817 pdwReserved, dwFlags, phHash);
1819 if (!is_valid_handle(&handle_table, hUID, RSAENH_MAGIC_CONTAINER))
1821 SetLastError(NTE_BAD_UID);
1822 return FALSE;
1825 if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH, (OBJECTHDR**)&pSrcHash))
1827 SetLastError(NTE_BAD_HASH);
1828 return FALSE;
1831 if (!phHash || pdwReserved || dwFlags)
1833 SetLastError(ERROR_INVALID_PARAMETER);
1834 return FALSE;
1837 *phHash = (HCRYPTHASH)new_object(&handle_table, sizeof(CRYPTHASH), RSAENH_MAGIC_HASH,
1838 destroy_hash, (OBJECTHDR**)&pDestHash);
1839 if (*phHash != (HCRYPTHASH)INVALID_HANDLE_VALUE)
1841 memcpy(pDestHash, pSrcHash, sizeof(CRYPTHASH));
1842 duplicate_hash_impl(pSrcHash->aiAlgid, &pSrcHash->context, &pDestHash->context);
1843 copy_hmac_info(&pDestHash->pHMACInfo, pSrcHash->pHMACInfo);
1844 copy_data_blob(&pDestHash->tpPRFParams.blobLabel, &pSrcHash->tpPRFParams.blobLabel);
1845 copy_data_blob(&pDestHash->tpPRFParams.blobSeed, &pSrcHash->tpPRFParams.blobSeed);
1848 return *phHash != (HCRYPTHASH)INVALID_HANDLE_VALUE;
1851 /******************************************************************************
1852 * CPDuplicateKey (RSAENH.@)
1854 * Clones a key object including it's current state.
1856 * PARAMS
1857 * hUID [I] Handle to the key container the hash belongs to.
1858 * hKey [I] Handle to the key object to be cloned.
1859 * pdwReserved [I] Reserved. Must be NULL.
1860 * dwFlags [I] No flags are currently defined. Must be 0.
1861 * phHash [O] Handle to the cloned key object.
1863 * RETURNS
1864 * Success: TRUE.
1865 * Failure: FALSE.
1867 BOOL WINAPI RSAENH_CPDuplicateKey(HCRYPTPROV hUID, HCRYPTKEY hKey, DWORD *pdwReserved,
1868 DWORD dwFlags, HCRYPTKEY *phKey)
1870 CRYPTKEY *pSrcKey, *pDestKey;
1872 TRACE("(hUID=%08lx, hKey=%08lx, pdwReserved=%p, dwFlags=%08x, phKey=%p)\n", hUID, hKey,
1873 pdwReserved, dwFlags, phKey);
1875 if (!is_valid_handle(&handle_table, hUID, RSAENH_MAGIC_CONTAINER))
1877 SetLastError(NTE_BAD_UID);
1878 return FALSE;
1881 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pSrcKey))
1883 SetLastError(NTE_BAD_KEY);
1884 return FALSE;
1887 if (!phKey || pdwReserved || dwFlags)
1889 SetLastError(ERROR_INVALID_PARAMETER);
1890 return FALSE;
1893 *phKey = (HCRYPTKEY)new_object(&handle_table, sizeof(CRYPTKEY), RSAENH_MAGIC_KEY, destroy_key,
1894 (OBJECTHDR**)&pDestKey);
1895 if (*phKey != (HCRYPTKEY)INVALID_HANDLE_VALUE)
1897 memcpy(pDestKey, pSrcKey, sizeof(CRYPTKEY));
1898 copy_data_blob(&pDestKey->siSChannelInfo.blobServerRandom,
1899 &pSrcKey->siSChannelInfo.blobServerRandom);
1900 copy_data_blob(&pDestKey->siSChannelInfo.blobClientRandom,
1901 &pSrcKey->siSChannelInfo.blobClientRandom);
1902 duplicate_key_impl(pSrcKey->aiAlgid, &pSrcKey->context, &pDestKey->context);
1903 return TRUE;
1905 else
1907 return FALSE;
1911 /******************************************************************************
1912 * CPEncrypt (RSAENH.@)
1914 * Encrypt data.
1916 * PARAMS
1917 * hProv [I] The key container hKey and hHash belong to.
1918 * hKey [I] The key used to encrypt the data.
1919 * hHash [I] An optional hash object for parallel hashing. See notes.
1920 * Final [I] Indicates if this is the last block of data to encrypt.
1921 * dwFlags [I] Currently no flags defined. Must be zero.
1922 * pbData [I/O] Pointer to the data to encrypt. Encrypted data will also be stored there.
1923 * pdwDataLen [I/O] I: Length of data to encrypt, O: Length of encrypted data.
1924 * dwBufLen [I] Size of the buffer at pbData.
1926 * RETURNS
1927 * Success: TRUE.
1928 * Failure: FALSE.
1930 * NOTES
1931 * If a hash object handle is provided in hHash, it will be updated with the plaintext.
1932 * This is useful for message signatures.
1934 * This function uses the standard WINAPI protocol for querying data of dynamic length.
1936 BOOL WINAPI RSAENH_CPEncrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
1937 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
1939 CRYPTKEY *pCryptKey;
1940 BYTE *in, out[RSAENH_MAX_BLOCK_SIZE], o[RSAENH_MAX_BLOCK_SIZE];
1941 DWORD dwEncryptedLen, i, j, k;
1943 TRACE("(hProv=%08lx, hKey=%08lx, hHash=%08lx, Final=%d, dwFlags=%08x, pbData=%p, "
1944 "pdwDataLen=%p, dwBufLen=%d)\n", hProv, hKey, hHash, Final, dwFlags, pbData, pdwDataLen,
1945 dwBufLen);
1947 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
1949 SetLastError(NTE_BAD_UID);
1950 return FALSE;
1953 if (dwFlags)
1955 SetLastError(NTE_BAD_FLAGS);
1956 return FALSE;
1959 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
1961 SetLastError(NTE_BAD_KEY);
1962 return FALSE;
1965 if (pCryptKey->dwState == RSAENH_KEYSTATE_IDLE)
1966 pCryptKey->dwState = RSAENH_KEYSTATE_ENCRYPTING;
1968 if (pCryptKey->dwState != RSAENH_KEYSTATE_ENCRYPTING)
1970 SetLastError(NTE_BAD_DATA);
1971 return FALSE;
1974 if (is_valid_handle(&handle_table, hHash, RSAENH_MAGIC_HASH)) {
1975 if (!RSAENH_CPHashData(hProv, hHash, pbData, *pdwDataLen, 0)) return FALSE;
1978 if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_BLOCK) {
1979 if (!Final && (*pdwDataLen % pCryptKey->dwBlockLen)) {
1980 SetLastError(NTE_BAD_DATA);
1981 return FALSE;
1984 dwEncryptedLen = (*pdwDataLen/pCryptKey->dwBlockLen+(Final?1:0))*pCryptKey->dwBlockLen;
1986 if (pbData == NULL) {
1987 *pdwDataLen = dwEncryptedLen;
1988 return TRUE;
1990 else if (dwEncryptedLen > dwBufLen) {
1991 *pdwDataLen = dwEncryptedLen;
1992 SetLastError(ERROR_MORE_DATA);
1993 return FALSE;
1996 /* Pad final block with length bytes */
1997 for (i=*pdwDataLen; i<dwEncryptedLen; i++) pbData[i] = dwEncryptedLen - *pdwDataLen;
1998 *pdwDataLen = dwEncryptedLen;
2000 for (i=0, in=pbData; i<*pdwDataLen; i+=pCryptKey->dwBlockLen, in+=pCryptKey->dwBlockLen) {
2001 switch (pCryptKey->dwMode) {
2002 case CRYPT_MODE_ECB:
2003 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out,
2004 RSAENH_ENCRYPT);
2005 break;
2007 case CRYPT_MODE_CBC:
2008 for (j=0; j<pCryptKey->dwBlockLen; j++) in[j] ^= pCryptKey->abChainVector[j];
2009 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out,
2010 RSAENH_ENCRYPT);
2011 memcpy(pCryptKey->abChainVector, out, pCryptKey->dwBlockLen);
2012 break;
2014 case CRYPT_MODE_CFB:
2015 for (j=0; j<pCryptKey->dwBlockLen; j++) {
2016 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context,
2017 pCryptKey->abChainVector, o, RSAENH_ENCRYPT);
2018 out[j] = in[j] ^ o[0];
2019 for (k=0; k<pCryptKey->dwBlockLen-1; k++)
2020 pCryptKey->abChainVector[k] = pCryptKey->abChainVector[k+1];
2021 pCryptKey->abChainVector[k] = out[j];
2023 break;
2025 default:
2026 SetLastError(NTE_BAD_ALGID);
2027 return FALSE;
2029 memcpy(in, out, pCryptKey->dwBlockLen);
2031 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_STREAM) {
2032 if (pbData == NULL) {
2033 *pdwDataLen = dwBufLen;
2034 return TRUE;
2036 encrypt_stream_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, *pdwDataLen);
2037 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_RSA) {
2038 if (pCryptKey->aiAlgid == CALG_RSA_SIGN) {
2039 SetLastError(NTE_BAD_KEY);
2040 return FALSE;
2042 if (!pbData) {
2043 *pdwDataLen = pCryptKey->dwBlockLen;
2044 return TRUE;
2046 if (dwBufLen < pCryptKey->dwBlockLen) {
2047 SetLastError(ERROR_MORE_DATA);
2048 return FALSE;
2050 if (!pad_data(pbData, *pdwDataLen, pbData, pCryptKey->dwBlockLen, dwFlags)) return FALSE;
2051 encrypt_block_impl(pCryptKey->aiAlgid, PK_PUBLIC, &pCryptKey->context, pbData, pbData, RSAENH_ENCRYPT);
2052 *pdwDataLen = pCryptKey->dwBlockLen;
2053 Final = TRUE;
2054 } else {
2055 SetLastError(NTE_BAD_TYPE);
2056 return FALSE;
2059 if (Final) setup_key(pCryptKey);
2061 return TRUE;
2064 /******************************************************************************
2065 * CPDecrypt (RSAENH.@)
2067 * Decrypt data.
2069 * PARAMS
2070 * hProv [I] The key container hKey and hHash belong to.
2071 * hKey [I] The key used to decrypt the data.
2072 * hHash [I] An optional hash object for parallel hashing. See notes.
2073 * Final [I] Indicates if this is the last block of data to decrypt.
2074 * dwFlags [I] Currently no flags defined. Must be zero.
2075 * pbData [I/O] Pointer to the data to decrypt. Plaintext will also be stored there.
2076 * pdwDataLen [I/O] I: Length of ciphertext, O: Length of plaintext.
2078 * RETURNS
2079 * Success: TRUE.
2080 * Failure: FALSE.
2082 * NOTES
2083 * If a hash object handle is provided in hHash, it will be updated with the plaintext.
2084 * This is useful for message signatures.
2086 * This function uses the standard WINAPI protocol for querying data of dynamic length.
2088 BOOL WINAPI RSAENH_CPDecrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
2089 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
2091 CRYPTKEY *pCryptKey;
2092 BYTE *in, out[RSAENH_MAX_BLOCK_SIZE], o[RSAENH_MAX_BLOCK_SIZE];
2093 DWORD i, j, k;
2094 DWORD dwMax;
2096 TRACE("(hProv=%08lx, hKey=%08lx, hHash=%08lx, Final=%d, dwFlags=%08x, pbData=%p, "
2097 "pdwDataLen=%p)\n", hProv, hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
2099 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2101 SetLastError(NTE_BAD_UID);
2102 return FALSE;
2105 if (dwFlags)
2107 SetLastError(NTE_BAD_FLAGS);
2108 return FALSE;
2111 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
2113 SetLastError(NTE_BAD_KEY);
2114 return FALSE;
2117 if (pCryptKey->dwState == RSAENH_KEYSTATE_IDLE)
2118 pCryptKey->dwState = RSAENH_KEYSTATE_DECRYPTING;
2120 if (pCryptKey->dwState != RSAENH_KEYSTATE_DECRYPTING)
2122 SetLastError(NTE_BAD_DATA);
2123 return FALSE;
2126 dwMax=*pdwDataLen;
2128 if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_BLOCK) {
2129 for (i=0, in=pbData; i<*pdwDataLen; i+=pCryptKey->dwBlockLen, in+=pCryptKey->dwBlockLen) {
2130 switch (pCryptKey->dwMode) {
2131 case CRYPT_MODE_ECB:
2132 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out,
2133 RSAENH_DECRYPT);
2134 break;
2136 case CRYPT_MODE_CBC:
2137 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out,
2138 RSAENH_DECRYPT);
2139 for (j=0; j<pCryptKey->dwBlockLen; j++) out[j] ^= pCryptKey->abChainVector[j];
2140 memcpy(pCryptKey->abChainVector, in, pCryptKey->dwBlockLen);
2141 break;
2143 case CRYPT_MODE_CFB:
2144 for (j=0; j<pCryptKey->dwBlockLen; j++) {
2145 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context,
2146 pCryptKey->abChainVector, o, RSAENH_ENCRYPT);
2147 out[j] = in[j] ^ o[0];
2148 for (k=0; k<pCryptKey->dwBlockLen-1; k++)
2149 pCryptKey->abChainVector[k] = pCryptKey->abChainVector[k+1];
2150 pCryptKey->abChainVector[k] = in[j];
2152 break;
2154 default:
2155 SetLastError(NTE_BAD_ALGID);
2156 return FALSE;
2158 memcpy(in, out, pCryptKey->dwBlockLen);
2160 if (Final) {
2161 if (pbData[*pdwDataLen-1] &&
2162 pbData[*pdwDataLen-1] <= pCryptKey->dwBlockLen &&
2163 pbData[*pdwDataLen-1] < *pdwDataLen) {
2164 BOOL padOkay = TRUE;
2166 /* check that every bad byte has the same value */
2167 for (i = 1; padOkay && i < pbData[*pdwDataLen-1]; i++)
2168 if (pbData[*pdwDataLen - i - 1] != pbData[*pdwDataLen - 1])
2169 padOkay = FALSE;
2170 if (padOkay)
2171 *pdwDataLen -= pbData[*pdwDataLen-1];
2172 else {
2173 SetLastError(NTE_BAD_DATA);
2174 return FALSE;
2177 else {
2178 SetLastError(NTE_BAD_DATA);
2179 return FALSE;
2183 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_STREAM) {
2184 encrypt_stream_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, *pdwDataLen);
2185 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_RSA) {
2186 if (pCryptKey->aiAlgid == CALG_RSA_SIGN) {
2187 SetLastError(NTE_BAD_KEY);
2188 return FALSE;
2190 encrypt_block_impl(pCryptKey->aiAlgid, PK_PRIVATE, &pCryptKey->context, pbData, pbData, RSAENH_DECRYPT);
2191 if (!unpad_data(pbData, pCryptKey->dwBlockLen, pbData, pdwDataLen, dwFlags)) return FALSE;
2192 Final = TRUE;
2193 } else {
2194 SetLastError(NTE_BAD_TYPE);
2195 return FALSE;
2198 if (Final) setup_key(pCryptKey);
2200 if (is_valid_handle(&handle_table, hHash, RSAENH_MAGIC_HASH)) {
2201 if (*pdwDataLen>dwMax ||
2202 !RSAENH_CPHashData(hProv, hHash, pbData, *pdwDataLen, 0)) return FALSE;
2205 return TRUE;
2208 /******************************************************************************
2209 * CPExportKey (RSAENH.@)
2211 * Export a key into a binary large object (BLOB).
2213 * PARAMS
2214 * hProv [I] Key container from which a key is to be exported.
2215 * hKey [I] Key to be exported.
2216 * hPubKey [I] Key used to encrypt sensitive BLOB data.
2217 * dwBlobType [I] SIMPLEBLOB, PUBLICKEYBLOB or PRIVATEKEYBLOB.
2218 * dwFlags [I] Currently none defined.
2219 * pbData [O] Pointer to a buffer where the BLOB will be written to.
2220 * pdwDataLen [I/O] I: Size of buffer at pbData, O: Size of BLOB
2222 * RETURNS
2223 * Success: TRUE.
2224 * Failure: FALSE.
2226 BOOL WINAPI RSAENH_CPExportKey(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubKey,
2227 DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
2229 CRYPTKEY *pCryptKey, *pPubKey;
2230 BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData;
2231 RSAPUBKEY *pRSAPubKey = (RSAPUBKEY*)(pBlobHeader+1);
2232 ALG_ID *pAlgid = (ALG_ID*)(pBlobHeader+1);
2233 DWORD dwDataLen;
2235 TRACE("(hProv=%08lx, hKey=%08lx, hPubKey=%08lx, dwBlobType=%08x, dwFlags=%08x, pbData=%p,"
2236 "pdwDataLen=%p)\n", hProv, hKey, hPubKey, dwBlobType, dwFlags, pbData, pdwDataLen);
2238 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2240 SetLastError(NTE_BAD_UID);
2241 return FALSE;
2244 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
2246 SetLastError(NTE_BAD_KEY);
2247 return FALSE;
2250 if (dwFlags & CRYPT_SSL2_FALLBACK) {
2251 if (pCryptKey->aiAlgid != CALG_SSL2_MASTER) {
2252 SetLastError(NTE_BAD_KEY);
2253 return FALSE;
2257 switch ((BYTE)dwBlobType)
2259 case SIMPLEBLOB:
2260 if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey)){
2261 SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error_code? */
2262 return FALSE;
2265 if (!(GET_ALG_CLASS(pCryptKey->aiAlgid)&(ALG_CLASS_DATA_ENCRYPT|ALG_CLASS_MSG_ENCRYPT))) {
2266 SetLastError(NTE_BAD_KEY); /* FIXME: error code? */
2267 return FALSE;
2270 dwDataLen = sizeof(BLOBHEADER) + sizeof(ALG_ID) + pPubKey->dwBlockLen;
2271 if (pbData) {
2272 if (*pdwDataLen < dwDataLen) {
2273 SetLastError(ERROR_MORE_DATA);
2274 *pdwDataLen = dwDataLen;
2275 return FALSE;
2278 pBlobHeader->bType = SIMPLEBLOB;
2279 pBlobHeader->bVersion = CUR_BLOB_VERSION;
2280 pBlobHeader->reserved = 0;
2281 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
2283 *pAlgid = pPubKey->aiAlgid;
2285 if (!pad_data(pCryptKey->abKeyValue, pCryptKey->dwKeyLen, (BYTE*)(pAlgid+1),
2286 pPubKey->dwBlockLen, dwFlags))
2288 return FALSE;
2291 encrypt_block_impl(pPubKey->aiAlgid, PK_PUBLIC, &pPubKey->context, (BYTE*)(pAlgid+1),
2292 (BYTE*)(pAlgid+1), RSAENH_ENCRYPT);
2294 *pdwDataLen = dwDataLen;
2295 return TRUE;
2297 case PUBLICKEYBLOB:
2298 if (is_valid_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY)) {
2299 SetLastError(NTE_BAD_KEY); /* FIXME: error code? */
2300 return FALSE;
2303 if ((pCryptKey->aiAlgid != CALG_RSA_KEYX) && (pCryptKey->aiAlgid != CALG_RSA_SIGN)) {
2304 SetLastError(NTE_BAD_KEY);
2305 return FALSE;
2308 dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + pCryptKey->dwKeyLen;
2309 if (pbData) {
2310 if (*pdwDataLen < dwDataLen) {
2311 SetLastError(ERROR_MORE_DATA);
2312 *pdwDataLen = dwDataLen;
2313 return FALSE;
2316 pBlobHeader->bType = PUBLICKEYBLOB;
2317 pBlobHeader->bVersion = CUR_BLOB_VERSION;
2318 pBlobHeader->reserved = 0;
2319 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
2321 pRSAPubKey->magic = RSAENH_MAGIC_RSA1;
2322 pRSAPubKey->bitlen = pCryptKey->dwKeyLen << 3;
2324 export_public_key_impl((BYTE*)(pRSAPubKey+1), &pCryptKey->context,
2325 pCryptKey->dwKeyLen, &pRSAPubKey->pubexp);
2327 *pdwDataLen = dwDataLen;
2328 return TRUE;
2330 case PRIVATEKEYBLOB:
2331 if ((pCryptKey->aiAlgid != CALG_RSA_KEYX) && (pCryptKey->aiAlgid != CALG_RSA_SIGN)) {
2332 SetLastError(NTE_BAD_KEY);
2333 return FALSE;
2336 dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2337 2 * pCryptKey->dwKeyLen + 5 * ((pCryptKey->dwKeyLen + 1) >> 1);
2338 if (pbData) {
2339 if (*pdwDataLen < dwDataLen) {
2340 SetLastError(ERROR_MORE_DATA);
2341 *pdwDataLen = dwDataLen;
2342 return FALSE;
2345 pBlobHeader->bType = PRIVATEKEYBLOB;
2346 pBlobHeader->bVersion = CUR_BLOB_VERSION;
2347 pBlobHeader->reserved = 0;
2348 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
2350 pRSAPubKey->magic = RSAENH_MAGIC_RSA2;
2351 pRSAPubKey->bitlen = pCryptKey->dwKeyLen << 3;
2353 export_private_key_impl((BYTE*)(pRSAPubKey+1), &pCryptKey->context,
2354 pCryptKey->dwKeyLen, &pRSAPubKey->pubexp);
2356 *pdwDataLen = dwDataLen;
2357 return TRUE;
2359 default:
2360 SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */
2361 return FALSE;
2365 /******************************************************************************
2366 * CPImportKey (RSAENH.@)
2368 * Import a BLOB'ed key into a key container.
2370 * PARAMS
2371 * hProv [I] Key container into which the key is to be imported.
2372 * pbData [I] Pointer to a buffer which holds the BLOB.
2373 * dwDataLen [I] Length of data in buffer at pbData.
2374 * hPubKey [I] Key used to decrypt sensitive BLOB data.
2375 * dwFlags [I] Currently none defined.
2376 * phKey [O] Handle to the imported key.
2378 * RETURNS
2379 * Success: TRUE.
2380 * Failure: FALSE.
2382 BOOL WINAPI RSAENH_CPImportKey(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen,
2383 HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
2385 KEYCONTAINER *pKeyContainer;
2386 CRYPTKEY *pCryptKey, *pPubKey;
2387 CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData;
2388 CONST RSAPUBKEY *pRSAPubKey = (CONST RSAPUBKEY*)(pBlobHeader+1);
2389 CONST ALG_ID *pAlgid = (CONST ALG_ID*)(pBlobHeader+1);
2390 CONST BYTE *pbKeyStream = (CONST BYTE*)(pAlgid + 1);
2391 ALG_ID algID;
2392 BYTE *pbDecrypted;
2393 DWORD dwKeyLen;
2394 BOOL ret;
2396 TRACE("(hProv=%08lx, pbData=%p, dwDataLen=%d, hPubKey=%08lx, dwFlags=%08x, phKey=%p)\n",
2397 hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
2399 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
2400 (OBJECTHDR**)&pKeyContainer))
2402 SetLastError(NTE_BAD_UID);
2403 return FALSE;
2406 if (dwDataLen < sizeof(BLOBHEADER) ||
2407 pBlobHeader->bVersion != CUR_BLOB_VERSION ||
2408 pBlobHeader->reserved != 0)
2410 SetLastError(NTE_BAD_DATA);
2411 return FALSE;
2414 switch (pBlobHeader->bType)
2416 case PRIVATEKEYBLOB:
2417 if ((dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY)) ||
2418 (pRSAPubKey->magic != RSAENH_MAGIC_RSA2) ||
2419 (dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2420 (2 * pRSAPubKey->bitlen >> 3) + (5 * ((pRSAPubKey->bitlen+8)>>4))))
2422 SetLastError(NTE_BAD_DATA);
2423 return FALSE;
2426 *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey);
2427 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
2428 setup_key(pCryptKey);
2429 ret = import_private_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context,
2430 pRSAPubKey->bitlen/8, pRSAPubKey->pubexp);
2431 if (ret) {
2432 switch (pBlobHeader->aiKeyAlg)
2434 case AT_SIGNATURE:
2435 case CALG_RSA_SIGN:
2436 TRACE("installing signing key\n");
2437 RSAENH_CPDestroyKey(hProv, pKeyContainer->hSignatureKeyPair);
2438 copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
2439 &pKeyContainer->hSignatureKeyPair);
2440 break;
2441 case AT_KEYEXCHANGE:
2442 case CALG_RSA_KEYX:
2443 TRACE("installing key exchange key\n");
2444 RSAENH_CPDestroyKey(hProv, pKeyContainer->hKeyExchangeKeyPair);
2445 copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
2446 &pKeyContainer->hKeyExchangeKeyPair);
2447 break;
2450 return ret;
2452 case PUBLICKEYBLOB:
2453 if ((dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY)) ||
2454 (pRSAPubKey->magic != RSAENH_MAGIC_RSA1) ||
2455 (dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + (pRSAPubKey->bitlen >> 3)))
2457 SetLastError(NTE_BAD_DATA);
2458 return FALSE;
2461 /* Since this is a public key blob, only the public key is
2462 * available, so only signature verification is possible.
2464 algID = pBlobHeader->aiKeyAlg;
2465 *phKey = new_key(hProv, algID, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey);
2466 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
2467 setup_key(pCryptKey);
2468 ret = import_public_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context,
2469 pRSAPubKey->bitlen >> 3, pRSAPubKey->pubexp);
2470 if (ret) {
2471 switch (pBlobHeader->aiKeyAlg)
2473 case AT_KEYEXCHANGE:
2474 case CALG_RSA_KEYX:
2475 TRACE("installing public key\n");
2476 RSAENH_CPDestroyKey(hProv, pKeyContainer->hKeyExchangeKeyPair);
2477 copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
2478 &pKeyContainer->hKeyExchangeKeyPair);
2479 break;
2482 return ret;
2484 case SIMPLEBLOB:
2485 if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey) ||
2486 pPubKey->aiAlgid != CALG_RSA_KEYX)
2488 SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error code? */
2489 return FALSE;
2492 if (dwDataLen < sizeof(BLOBHEADER)+sizeof(ALG_ID)+pPubKey->dwBlockLen)
2494 SetLastError(NTE_BAD_DATA); /* FIXME: error code */
2495 return FALSE;
2498 pbDecrypted = HeapAlloc(GetProcessHeap(), 0, pPubKey->dwBlockLen);
2499 if (!pbDecrypted) return FALSE;
2500 encrypt_block_impl(pPubKey->aiAlgid, PK_PRIVATE, &pPubKey->context, pbKeyStream, pbDecrypted,
2501 RSAENH_DECRYPT);
2503 dwKeyLen = RSAENH_MAX_KEY_SIZE;
2504 if (!unpad_data(pbDecrypted, pPubKey->dwBlockLen, pbDecrypted, &dwKeyLen, dwFlags)) {
2505 HeapFree(GetProcessHeap(), 0, pbDecrypted);
2506 return FALSE;
2509 *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, dwKeyLen<<19, &pCryptKey);
2510 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE)
2512 HeapFree(GetProcessHeap(), 0, pbDecrypted);
2513 return FALSE;
2515 memcpy(pCryptKey->abKeyValue, pbDecrypted, dwKeyLen);
2516 HeapFree(GetProcessHeap(), 0, pbDecrypted);
2517 setup_key(pCryptKey);
2518 return TRUE;
2520 default:
2521 SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */
2522 return FALSE;
2526 /******************************************************************************
2527 * CPGenKey (RSAENH.@)
2529 * Generate a key in the key container
2531 * PARAMS
2532 * hProv [I] Key container for which a key is to be generated.
2533 * Algid [I] Crypto algorithm identifier for the key to be generated.
2534 * dwFlags [I] Upper 16 bits: Binary length of key. Lower 16 bits: Flags. See Notes
2535 * phKey [O] Handle to the generated key.
2537 * RETURNS
2538 * Success: TRUE.
2539 * Failure: FALSE.
2541 * FIXME
2542 * Flags currently not considered.
2544 * NOTES
2545 * Private key-exchange- and signature-keys can be generated with Algid AT_KEYEXCHANGE
2546 * and AT_SIGNATURE values.
2548 BOOL WINAPI RSAENH_CPGenKey(HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
2550 KEYCONTAINER *pKeyContainer;
2551 CRYPTKEY *pCryptKey;
2553 TRACE("(hProv=%08lx, aiAlgid=%d, dwFlags=%08x, phKey=%p)\n", hProv, Algid, dwFlags, phKey);
2555 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
2556 (OBJECTHDR**)&pKeyContainer))
2558 /* MSDN: hProv not containing valid context handle */
2559 SetLastError(NTE_BAD_UID);
2560 return FALSE;
2563 switch (Algid)
2565 case AT_SIGNATURE:
2566 case CALG_RSA_SIGN:
2567 *phKey = new_key(hProv, CALG_RSA_SIGN, dwFlags, &pCryptKey);
2568 if (pCryptKey) {
2569 new_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen);
2570 setup_key(pCryptKey);
2571 if (Algid == AT_SIGNATURE) {
2572 RSAENH_CPDestroyKey(hProv, pKeyContainer->hSignatureKeyPair);
2573 copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
2574 &pKeyContainer->hSignatureKeyPair);
2577 break;
2579 case AT_KEYEXCHANGE:
2580 case CALG_RSA_KEYX:
2581 *phKey = new_key(hProv, CALG_RSA_KEYX, dwFlags, &pCryptKey);
2582 if (pCryptKey) {
2583 new_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen);
2584 setup_key(pCryptKey);
2585 if (Algid == AT_KEYEXCHANGE) {
2586 RSAENH_CPDestroyKey(hProv, pKeyContainer->hKeyExchangeKeyPair);
2587 copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
2588 &pKeyContainer->hKeyExchangeKeyPair);
2591 break;
2593 case CALG_RC2:
2594 case CALG_RC4:
2595 case CALG_DES:
2596 case CALG_3DES_112:
2597 case CALG_3DES:
2598 case CALG_AES:
2599 case CALG_AES_128:
2600 case CALG_AES_192:
2601 case CALG_AES_256:
2602 case CALG_PCT1_MASTER:
2603 case CALG_SSL2_MASTER:
2604 case CALG_SSL3_MASTER:
2605 case CALG_TLS1_MASTER:
2606 *phKey = new_key(hProv, Algid, dwFlags, &pCryptKey);
2607 if (pCryptKey) {
2608 gen_rand_impl(pCryptKey->abKeyValue, RSAENH_MAX_KEY_SIZE);
2609 switch (Algid) {
2610 case CALG_SSL3_MASTER:
2611 pCryptKey->abKeyValue[0] = RSAENH_SSL3_VERSION_MAJOR;
2612 pCryptKey->abKeyValue[1] = RSAENH_SSL3_VERSION_MINOR;
2613 break;
2615 case CALG_TLS1_MASTER:
2616 pCryptKey->abKeyValue[0] = RSAENH_TLS1_VERSION_MAJOR;
2617 pCryptKey->abKeyValue[1] = RSAENH_TLS1_VERSION_MINOR;
2618 break;
2620 setup_key(pCryptKey);
2622 break;
2624 default:
2625 /* MSDN: Algorithm not supported specified by Algid */
2626 SetLastError(NTE_BAD_ALGID);
2627 return FALSE;
2630 return *phKey != (HCRYPTKEY)INVALID_HANDLE_VALUE;
2633 /******************************************************************************
2634 * CPGenRandom (RSAENH.@)
2636 * Generate a random byte stream.
2638 * PARAMS
2639 * hProv [I] Key container that is used to generate random bytes.
2640 * dwLen [I] Specifies the number of requested random data bytes.
2641 * pbBuffer [O] Random bytes will be stored here.
2643 * RETURNS
2644 * Success: TRUE
2645 * Failure: FALSE
2647 BOOL WINAPI RSAENH_CPGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
2649 TRACE("(hProv=%08lx, dwLen=%d, pbBuffer=%p)\n", hProv, dwLen, pbBuffer);
2651 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2653 /* MSDN: hProv not containing valid context handle */
2654 SetLastError(NTE_BAD_UID);
2655 return FALSE;
2658 return gen_rand_impl(pbBuffer, dwLen);
2661 /******************************************************************************
2662 * CPGetHashParam (RSAENH.@)
2664 * Query parameters of an hash object.
2666 * PARAMS
2667 * hProv [I] The kea container, which the hash belongs to.
2668 * hHash [I] The hash object that is to be queried.
2669 * dwParam [I] Specifies the parameter that is to be queried.
2670 * pbData [I] Pointer to the buffer where the parameter value will be stored.
2671 * pdwDataLen [I/O] I: Buffer length at pbData, O: Length of the parameter value.
2672 * dwFlags [I] None currently defined.
2674 * RETURNS
2675 * Success: TRUE
2676 * Failure: FALSE
2678 * NOTES
2679 * Valid dwParams are: HP_ALGID, HP_HASHSIZE, HP_HASHVALUE. The hash will be
2680 * finalized if HP_HASHVALUE is queried.
2682 BOOL WINAPI RSAENH_CPGetHashParam(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
2683 DWORD *pdwDataLen, DWORD dwFlags)
2685 CRYPTHASH *pCryptHash;
2687 TRACE("(hProv=%08lx, hHash=%08lx, dwParam=%08x, pbData=%p, pdwDataLen=%p, dwFlags=%08x)\n",
2688 hProv, hHash, dwParam, pbData, pdwDataLen, dwFlags);
2690 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2692 SetLastError(NTE_BAD_UID);
2693 return FALSE;
2696 if (dwFlags)
2698 SetLastError(NTE_BAD_FLAGS);
2699 return FALSE;
2702 if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH,
2703 (OBJECTHDR**)&pCryptHash))
2705 SetLastError(NTE_BAD_HASH);
2706 return FALSE;
2709 if (!pdwDataLen)
2711 SetLastError(ERROR_INVALID_PARAMETER);
2712 return FALSE;
2715 switch (dwParam)
2717 case HP_ALGID:
2718 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptHash->aiAlgid,
2719 sizeof(ALG_ID));
2721 case HP_HASHSIZE:
2722 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptHash->dwHashSize,
2723 sizeof(DWORD));
2725 case HP_HASHVAL:
2726 if (pCryptHash->aiAlgid == CALG_TLS1PRF) {
2727 return tls1_prf(hProv, pCryptHash->hKey, &pCryptHash->tpPRFParams.blobLabel,
2728 &pCryptHash->tpPRFParams.blobSeed, pbData, *pdwDataLen);
2731 if ( pbData == NULL ) {
2732 *pdwDataLen = pCryptHash->dwHashSize;
2733 return TRUE;
2736 if (pbData && (pCryptHash->dwState != RSAENH_HASHSTATE_FINISHED))
2738 finalize_hash(pCryptHash);
2739 pCryptHash->dwState = RSAENH_HASHSTATE_FINISHED;
2742 return copy_param(pbData, pdwDataLen, (CONST BYTE*)pCryptHash->abHashValue,
2743 pCryptHash->dwHashSize);
2745 default:
2746 SetLastError(NTE_BAD_TYPE);
2747 return FALSE;
2751 /******************************************************************************
2752 * CPSetKeyParam (RSAENH.@)
2754 * Set a parameter of a key object
2756 * PARAMS
2757 * hProv [I] The key container to which the key belongs.
2758 * hKey [I] The key for which a parameter is to be set.
2759 * dwParam [I] Parameter type. See Notes.
2760 * pbData [I] Pointer to the parameter value.
2761 * dwFlags [I] Currently none defined.
2763 * RETURNS
2764 * Success: TRUE.
2765 * Failure: FALSE.
2767 * NOTES:
2768 * Defined dwParam types are:
2769 * - KP_MODE: Values MODE_CBC, MODE_ECB, MODE_CFB.
2770 * - KP_MODE_BITS: Shift width for cipher feedback mode. (Currently ignored by MS CSP's)
2771 * - KP_PERMISSIONS: Or'ed combination of CRYPT_ENCRYPT, CRYPT_DECRYPT,
2772 * CRYPT_EXPORT, CRYPT_READ, CRYPT_WRITE, CRYPT_MAC
2773 * - KP_IV: Initialization vector
2775 BOOL WINAPI RSAENH_CPSetKeyParam(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
2776 DWORD dwFlags)
2778 CRYPTKEY *pCryptKey;
2780 TRACE("(hProv=%08lx, hKey=%08lx, dwParam=%08x, pbData=%p, dwFlags=%08x)\n", hProv, hKey,
2781 dwParam, pbData, dwFlags);
2783 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2785 SetLastError(NTE_BAD_UID);
2786 return FALSE;
2789 if (dwFlags) {
2790 SetLastError(NTE_BAD_FLAGS);
2791 return FALSE;
2794 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
2796 SetLastError(NTE_BAD_KEY);
2797 return FALSE;
2800 switch (dwParam) {
2801 case KP_PADDING:
2802 /* The MS providers only support PKCS5_PADDING */
2803 if (*(DWORD *)pbData != PKCS5_PADDING) {
2804 SetLastError(NTE_BAD_DATA);
2805 return FALSE;
2807 return TRUE;
2809 case KP_MODE:
2810 pCryptKey->dwMode = *(DWORD*)pbData;
2811 return TRUE;
2813 case KP_MODE_BITS:
2814 pCryptKey->dwModeBits = *(DWORD*)pbData;
2815 return TRUE;
2817 case KP_PERMISSIONS:
2818 pCryptKey->dwPermissions = *(DWORD*)pbData;
2819 return TRUE;
2821 case KP_IV:
2822 memcpy(pCryptKey->abInitVector, pbData, pCryptKey->dwBlockLen);
2823 setup_key(pCryptKey);
2824 return TRUE;
2826 case KP_SALT_EX:
2828 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pbData;
2830 /* salt length can't be greater than 128 bits = 16 bytes */
2831 if (blob->cbData > 16)
2833 SetLastError(ERROR_INVALID_PARAMETER);
2834 return FALSE;
2836 memcpy(pCryptKey->abKeyValue + pCryptKey->dwKeyLen, blob->pbData,
2837 blob->cbData);
2838 pCryptKey->dwSaltLen = blob->cbData;
2839 setup_key(pCryptKey);
2840 return TRUE;
2843 case KP_EFFECTIVE_KEYLEN:
2844 switch (pCryptKey->aiAlgid) {
2845 case CALG_RC2:
2846 if (!pbData)
2848 SetLastError(ERROR_INVALID_PARAMETER);
2849 return FALSE;
2851 else if (!*(DWORD *)pbData || *(DWORD *)pbData > 1024)
2853 SetLastError(NTE_BAD_DATA);
2854 return FALSE;
2856 else
2858 pCryptKey->dwEffectiveKeyLen = *(DWORD *)pbData;
2859 setup_key(pCryptKey);
2861 break;
2862 default:
2863 SetLastError(NTE_BAD_TYPE);
2864 return FALSE;
2866 return TRUE;
2868 case KP_SCHANNEL_ALG:
2869 switch (((PSCHANNEL_ALG)pbData)->dwUse) {
2870 case SCHANNEL_ENC_KEY:
2871 memcpy(&pCryptKey->siSChannelInfo.saEncAlg, pbData, sizeof(SCHANNEL_ALG));
2872 break;
2874 case SCHANNEL_MAC_KEY:
2875 memcpy(&pCryptKey->siSChannelInfo.saMACAlg, pbData, sizeof(SCHANNEL_ALG));
2876 break;
2878 default:
2879 SetLastError(NTE_FAIL); /* FIXME: error code */
2880 return FALSE;
2882 return TRUE;
2884 case KP_CLIENT_RANDOM:
2885 return copy_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom, (PCRYPT_DATA_BLOB)pbData);
2887 case KP_SERVER_RANDOM:
2888 return copy_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom, (PCRYPT_DATA_BLOB)pbData);
2890 default:
2891 SetLastError(NTE_BAD_TYPE);
2892 return FALSE;
2896 /******************************************************************************
2897 * CPGetKeyParam (RSAENH.@)
2899 * Query a key parameter.
2901 * PARAMS
2902 * hProv [I] The key container, which the key belongs to.
2903 * hHash [I] The key object that is to be queried.
2904 * dwParam [I] Specifies the parameter that is to be queried.
2905 * pbData [I] Pointer to the buffer where the parameter value will be stored.
2906 * pdwDataLen [I/O] I: Buffer length at pbData, O: Length of the parameter value.
2907 * dwFlags [I] None currently defined.
2909 * RETURNS
2910 * Success: TRUE
2911 * Failure: FALSE
2913 * NOTES
2914 * Defined dwParam types are:
2915 * - KP_MODE: Values MODE_CBC, MODE_ECB, MODE_CFB.
2916 * - KP_MODE_BITS: Shift width for cipher feedback mode.
2917 * (Currently ignored by MS CSP's - always eight)
2918 * - KP_PERMISSIONS: Or'ed combination of CRYPT_ENCRYPT, CRYPT_DECRYPT,
2919 * CRYPT_EXPORT, CRYPT_READ, CRYPT_WRITE, CRYPT_MAC
2920 * - KP_IV: Initialization vector.
2921 * - KP_KEYLEN: Bitwidth of the key.
2922 * - KP_BLOCKLEN: Size of a block cipher block.
2923 * - KP_SALT: Salt value.
2925 BOOL WINAPI RSAENH_CPGetKeyParam(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
2926 DWORD *pdwDataLen, DWORD dwFlags)
2928 CRYPTKEY *pCryptKey;
2929 DWORD dwValue;
2931 TRACE("(hProv=%08lx, hKey=%08lx, dwParam=%08x, pbData=%p, pdwDataLen=%p dwFlags=%08x)\n",
2932 hProv, hKey, dwParam, pbData, pdwDataLen, dwFlags);
2934 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2936 SetLastError(NTE_BAD_UID);
2937 return FALSE;
2940 if (dwFlags) {
2941 SetLastError(NTE_BAD_FLAGS);
2942 return FALSE;
2945 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
2947 SetLastError(NTE_BAD_KEY);
2948 return FALSE;
2951 switch (dwParam)
2953 case KP_IV:
2954 return copy_param(pbData, pdwDataLen, (CONST BYTE*)pCryptKey->abInitVector,
2955 pCryptKey->dwBlockLen);
2957 case KP_SALT:
2958 return copy_param(pbData, pdwDataLen,
2959 (CONST BYTE*)&pCryptKey->abKeyValue[pCryptKey->dwKeyLen], pCryptKey->dwSaltLen);
2961 case KP_PADDING:
2962 dwValue = PKCS5_PADDING;
2963 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD));
2965 case KP_KEYLEN:
2966 dwValue = pCryptKey->dwKeyLen << 3;
2967 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD));
2969 case KP_EFFECTIVE_KEYLEN:
2970 if (pCryptKey->dwEffectiveKeyLen)
2971 dwValue = pCryptKey->dwEffectiveKeyLen;
2972 else
2973 dwValue = pCryptKey->dwKeyLen << 3;
2974 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD));
2976 case KP_BLOCKLEN:
2977 dwValue = pCryptKey->dwBlockLen << 3;
2978 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD));
2980 case KP_MODE:
2981 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->dwMode, sizeof(DWORD));
2983 case KP_MODE_BITS:
2984 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->dwModeBits,
2985 sizeof(DWORD));
2987 case KP_PERMISSIONS:
2988 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->dwPermissions,
2989 sizeof(DWORD));
2991 case KP_ALGID:
2992 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->aiAlgid, sizeof(DWORD));
2994 default:
2995 SetLastError(NTE_BAD_TYPE);
2996 return FALSE;
3000 /******************************************************************************
3001 * CPGetProvParam (RSAENH.@)
3003 * Query a CSP parameter.
3005 * PARAMS
3006 * hProv [I] The key container that is to be queried.
3007 * dwParam [I] Specifies the parameter that is to be queried.
3008 * pbData [I] Pointer to the buffer where the parameter value will be stored.
3009 * pdwDataLen [I/O] I: Buffer length at pbData, O: Length of the parameter value.
3010 * dwFlags [I] CRYPT_FIRST: Start enumeration (for PP_ENUMALGS{_EX}).
3012 * RETURNS
3013 * Success: TRUE
3014 * Failure: FALSE
3015 * NOTES:
3016 * Defined dwParam types:
3017 * - PP_CONTAINER: Name of the key container.
3018 * - PP_NAME: Name of the cryptographic service provider.
3019 * - PP_SIG_KEYSIZE_INC: RSA signature keywidth granularity in bits.
3020 * - PP_KEYX_KEYSIZE_INC: RSA key-exchange keywidth granularity in bits.
3021 * - PP_ENUMALGS{_EX}: Query provider capabilities.
3023 BOOL WINAPI RSAENH_CPGetProvParam(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
3024 DWORD *pdwDataLen, DWORD dwFlags)
3026 KEYCONTAINER *pKeyContainer;
3027 PROV_ENUMALGS provEnumalgs;
3028 DWORD dwTemp;
3029 HKEY hKey;
3031 /* This is for dwParam 41, which does not seem to be documented
3032 * on MSDN. IE6 SP1 asks for it in the 'About' dialog, however.
3033 * Returning this BLOB seems to satisfy IE. The marked 0x00 seem
3034 * to be 'don't care's. If you know anything more specific about
3035 * provider parameter 41, please report to wine-devel@winehq.org */
3036 static CONST BYTE abWTF[96] = {
3037 0xb0, 0x25, 0x63, 0x86, 0x9c, 0xab, 0xb6, 0x37,
3038 0xe8, 0x82, /**/0x00,/**/ 0x72, 0x06, 0xb2, /**/0x00,/**/ 0x3b,
3039 0x60, 0x35, /**/0x00,/**/ 0x3b, 0x88, 0xce, /**/0x00,/**/ 0x82,
3040 0xbc, 0x7a, /**/0x00,/**/ 0xb7, 0x4f, 0x7e, /**/0x00,/**/ 0xde,
3041 0x92, 0xf1, /**/0x00,/**/ 0x83, 0xea, 0x5e, /**/0x00,/**/ 0xc8,
3042 0x12, 0x1e, 0xd4, 0x06, 0xf7, 0x66, /**/0x00,/**/ 0x01,
3043 0x29, 0xa4, /**/0x00,/**/ 0xf8, 0x24, 0x0c, /**/0x00,/**/ 0x33,
3044 0x06, 0x80, /**/0x00,/**/ 0x02, 0x46, 0x0b, /**/0x00,/**/ 0x6d,
3045 0x5b, 0xca, /**/0x00,/**/ 0x9a, 0x10, 0xf0, /**/0x00,/**/ 0x05,
3046 0x19, 0xd0, /**/0x00,/**/ 0x2c, 0xf6, 0x27, /**/0x00,/**/ 0xaa,
3047 0x7c, 0x6f, /**/0x00,/**/ 0xb9, 0xd8, 0x72, /**/0x00,/**/ 0x03,
3048 0xf3, 0x81, /**/0x00,/**/ 0xfa, 0xe8, 0x26, /**/0x00,/**/ 0xca
3051 TRACE("(hProv=%08lx, dwParam=%08x, pbData=%p, pdwDataLen=%p, dwFlags=%08x)\n",
3052 hProv, dwParam, pbData, pdwDataLen, dwFlags);
3054 if (!pdwDataLen) {
3055 SetLastError(ERROR_INVALID_PARAMETER);
3056 return FALSE;
3059 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
3060 (OBJECTHDR**)&pKeyContainer))
3062 /* MSDN: hProv not containing valid context handle */
3063 SetLastError(NTE_BAD_UID);
3064 return FALSE;
3067 switch (dwParam)
3069 case PP_CONTAINER:
3070 case PP_UNIQUE_CONTAINER:/* MSDN says we can return the same value as PP_CONTAINER */
3071 return copy_param(pbData, pdwDataLen, (CONST BYTE*)pKeyContainer->szName,
3072 strlen(pKeyContainer->szName)+1);
3074 case PP_NAME:
3075 return copy_param(pbData, pdwDataLen, (CONST BYTE*)pKeyContainer->szProvName,
3076 strlen(pKeyContainer->szProvName)+1);
3078 case PP_PROVTYPE:
3079 dwTemp = PROV_RSA_FULL;
3080 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3082 case PP_KEYSPEC:
3083 dwTemp = AT_SIGNATURE | AT_KEYEXCHANGE;
3084 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3086 case PP_KEYSET_TYPE:
3087 dwTemp = pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET;
3088 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3090 case PP_KEYSTORAGE:
3091 dwTemp = CRYPT_SEC_DESCR;
3092 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3094 case PP_SIG_KEYSIZE_INC:
3095 case PP_KEYX_KEYSIZE_INC:
3096 dwTemp = 8;
3097 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3099 case PP_IMPTYPE:
3100 dwTemp = CRYPT_IMPL_SOFTWARE;
3101 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3103 case PP_VERSION:
3104 dwTemp = 0x00000200;
3105 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3107 case PP_ENUMCONTAINERS:
3108 if ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) pKeyContainer->dwEnumContainersCtr = 0;
3110 if (!pbData) {
3111 *pdwDataLen = (DWORD)MAX_PATH + 1;
3112 return TRUE;
3115 if (!open_container_key("", dwFlags, &hKey))
3117 SetLastError(ERROR_NO_MORE_ITEMS);
3118 return FALSE;
3121 dwTemp = *pdwDataLen;
3122 switch (RegEnumKeyExA(hKey, pKeyContainer->dwEnumContainersCtr, (LPSTR)pbData, &dwTemp,
3123 NULL, NULL, NULL, NULL))
3125 case ERROR_MORE_DATA:
3126 *pdwDataLen = (DWORD)MAX_PATH + 1;
3128 case ERROR_SUCCESS:
3129 pKeyContainer->dwEnumContainersCtr++;
3130 RegCloseKey(hKey);
3131 return TRUE;
3133 case ERROR_NO_MORE_ITEMS:
3134 default:
3135 SetLastError(ERROR_NO_MORE_ITEMS);
3136 RegCloseKey(hKey);
3137 return FALSE;
3140 case PP_ENUMALGS:
3141 case PP_ENUMALGS_EX:
3142 if (((pKeyContainer->dwEnumAlgsCtr >= RSAENH_MAX_ENUMALGS-1) ||
3143 (!aProvEnumAlgsEx[pKeyContainer->dwPersonality]
3144 [pKeyContainer->dwEnumAlgsCtr+1].aiAlgid)) &&
3145 ((dwFlags & CRYPT_FIRST) != CRYPT_FIRST))
3147 SetLastError(ERROR_NO_MORE_ITEMS);
3148 return FALSE;
3151 if (dwParam == PP_ENUMALGS) {
3152 if (pbData && (*pdwDataLen >= sizeof(PROV_ENUMALGS)))
3153 pKeyContainer->dwEnumAlgsCtr = ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) ?
3154 0 : pKeyContainer->dwEnumAlgsCtr+1;
3156 provEnumalgs.aiAlgid = aProvEnumAlgsEx
3157 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].aiAlgid;
3158 provEnumalgs.dwBitLen = aProvEnumAlgsEx
3159 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].dwDefaultLen;
3160 provEnumalgs.dwNameLen = aProvEnumAlgsEx
3161 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].dwNameLen;
3162 memcpy(provEnumalgs.szName, aProvEnumAlgsEx
3163 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].szName,
3164 20*sizeof(CHAR));
3166 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&provEnumalgs,
3167 sizeof(PROV_ENUMALGS));
3168 } else {
3169 if (pbData && (*pdwDataLen >= sizeof(PROV_ENUMALGS_EX)))
3170 pKeyContainer->dwEnumAlgsCtr = ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) ?
3171 0 : pKeyContainer->dwEnumAlgsCtr+1;
3173 return copy_param(pbData, pdwDataLen,
3174 (CONST BYTE*)&aProvEnumAlgsEx
3175 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr],
3176 sizeof(PROV_ENUMALGS_EX));
3179 case 41: /* Undocumented. Asked for by IE About dialog */
3180 return copy_param(pbData, pdwDataLen, abWTF, sizeof(abWTF));
3182 default:
3183 /* MSDN: Unknown parameter number in dwParam */
3184 SetLastError(NTE_BAD_TYPE);
3185 return FALSE;
3189 /******************************************************************************
3190 * CPDeriveKey (RSAENH.@)
3192 * Derives a key from a hash value.
3194 * PARAMS
3195 * hProv [I] Key container for which a key is to be generated.
3196 * Algid [I] Crypto algorithm identifier for the key to be generated.
3197 * hBaseData [I] Hash from whose value the key will be derived.
3198 * dwFlags [I] See Notes.
3199 * phKey [O] The generated key.
3201 * RETURNS
3202 * Success: TRUE
3203 * Failure: FALSE
3205 * NOTES
3206 * Defined flags:
3207 * - CRYPT_EXPORTABLE: Key can be exported.
3208 * - CRYPT_NO_SALT: No salt is used for 40 bit keys.
3209 * - CRYPT_CREATE_SALT: Use remaining bits as salt value.
3211 BOOL WINAPI RSAENH_CPDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
3212 DWORD dwFlags, HCRYPTKEY *phKey)
3214 CRYPTKEY *pCryptKey, *pMasterKey;
3215 CRYPTHASH *pCryptHash;
3216 BYTE abHashValue[RSAENH_MAX_HASH_SIZE*2];
3217 DWORD dwLen;
3219 TRACE("(hProv=%08lx, Algid=%d, hBaseData=%08lx, dwFlags=%08x phKey=%p)\n", hProv, Algid,
3220 hBaseData, dwFlags, phKey);
3222 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
3224 SetLastError(NTE_BAD_UID);
3225 return FALSE;
3228 if (!lookup_handle(&handle_table, hBaseData, RSAENH_MAGIC_HASH,
3229 (OBJECTHDR**)&pCryptHash))
3231 SetLastError(NTE_BAD_HASH);
3232 return FALSE;
3235 if (!phKey)
3237 SetLastError(ERROR_INVALID_PARAMETER);
3238 return FALSE;
3241 switch (GET_ALG_CLASS(Algid))
3243 case ALG_CLASS_DATA_ENCRYPT:
3244 *phKey = new_key(hProv, Algid, dwFlags, &pCryptKey);
3245 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
3248 * We derive the key material from the hash.
3249 * If the hash value is not large enough for the claimed key, we have to construct
3250 * a larger binary value based on the hash. This is documented in MSDN: CryptDeriveKey.
3252 dwLen = RSAENH_MAX_HASH_SIZE;
3253 RSAENH_CPGetHashParam(pCryptHash->hProv, hBaseData, HP_HASHVAL, abHashValue, &dwLen, 0);
3255 if (dwLen < pCryptKey->dwKeyLen) {
3256 BYTE pad1[RSAENH_HMAC_DEF_PAD_LEN], pad2[RSAENH_HMAC_DEF_PAD_LEN];
3257 BYTE old_hashval[RSAENH_MAX_HASH_SIZE];
3258 DWORD i;
3260 memcpy(old_hashval, pCryptHash->abHashValue, RSAENH_MAX_HASH_SIZE);
3262 for (i=0; i<RSAENH_HMAC_DEF_PAD_LEN; i++) {
3263 pad1[i] = RSAENH_HMAC_DEF_IPAD_CHAR ^ (i<dwLen ? abHashValue[i] : 0);
3264 pad2[i] = RSAENH_HMAC_DEF_OPAD_CHAR ^ (i<dwLen ? abHashValue[i] : 0);
3267 init_hash(pCryptHash);
3268 update_hash(pCryptHash, pad1, RSAENH_HMAC_DEF_PAD_LEN);
3269 finalize_hash(pCryptHash);
3270 memcpy(abHashValue, pCryptHash->abHashValue, pCryptHash->dwHashSize);
3272 init_hash(pCryptHash);
3273 update_hash(pCryptHash, pad2, RSAENH_HMAC_DEF_PAD_LEN);
3274 finalize_hash(pCryptHash);
3275 memcpy(abHashValue+pCryptHash->dwHashSize, pCryptHash->abHashValue,
3276 pCryptHash->dwHashSize);
3278 memcpy(pCryptHash->abHashValue, old_hashval, RSAENH_MAX_HASH_SIZE);
3281 memcpy(pCryptKey->abKeyValue, abHashValue,
3282 RSAENH_MIN(pCryptKey->dwKeyLen, sizeof(pCryptKey->abKeyValue)));
3283 break;
3285 case ALG_CLASS_MSG_ENCRYPT:
3286 if (!lookup_handle(&handle_table, pCryptHash->hKey, RSAENH_MAGIC_KEY,
3287 (OBJECTHDR**)&pMasterKey))
3289 SetLastError(NTE_FAIL); /* FIXME error code */
3290 return FALSE;
3293 switch (Algid)
3295 /* See RFC 2246, chapter 6.3 Key calculation */
3296 case CALG_SCHANNEL_ENC_KEY:
3297 *phKey = new_key(hProv, pMasterKey->siSChannelInfo.saEncAlg.Algid,
3298 MAKELONG(LOWORD(dwFlags),pMasterKey->siSChannelInfo.saEncAlg.cBits),
3299 &pCryptKey);
3300 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
3301 memcpy(pCryptKey->abKeyValue,
3302 pCryptHash->abHashValue + (
3303 2 * (pMasterKey->siSChannelInfo.saMACAlg.cBits / 8) +
3304 ((dwFlags & CRYPT_SERVER) ?
3305 (pMasterKey->siSChannelInfo.saEncAlg.cBits / 8) : 0)),
3306 pMasterKey->siSChannelInfo.saEncAlg.cBits / 8);
3307 memcpy(pCryptKey->abInitVector,
3308 pCryptHash->abHashValue + (
3309 2 * (pMasterKey->siSChannelInfo.saMACAlg.cBits / 8) +
3310 2 * (pMasterKey->siSChannelInfo.saEncAlg.cBits / 8) +
3311 ((dwFlags & CRYPT_SERVER) ? pCryptKey->dwBlockLen : 0)),
3312 pCryptKey->dwBlockLen);
3313 break;
3315 case CALG_SCHANNEL_MAC_KEY:
3316 *phKey = new_key(hProv, Algid,
3317 MAKELONG(LOWORD(dwFlags),pMasterKey->siSChannelInfo.saMACAlg.cBits),
3318 &pCryptKey);
3319 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
3320 memcpy(pCryptKey->abKeyValue,
3321 pCryptHash->abHashValue + ((dwFlags & CRYPT_SERVER) ?
3322 pMasterKey->siSChannelInfo.saMACAlg.cBits / 8 : 0),
3323 pMasterKey->siSChannelInfo.saMACAlg.cBits / 8);
3324 break;
3326 default:
3327 SetLastError(NTE_BAD_ALGID);
3328 return FALSE;
3330 break;
3332 default:
3333 SetLastError(NTE_BAD_ALGID);
3334 return FALSE;
3337 setup_key(pCryptKey);
3338 return TRUE;
3341 /******************************************************************************
3342 * CPGetUserKey (RSAENH.@)
3344 * Returns a handle to the user's private key-exchange- or signature-key.
3346 * PARAMS
3347 * hProv [I] The key container from which a user key is requested.
3348 * dwKeySpec [I] AT_KEYEXCHANGE or AT_SIGNATURE
3349 * phUserKey [O] Handle to the requested key or INVALID_HANDLE_VALUE in case of failure.
3351 * RETURNS
3352 * Success: TRUE.
3353 * Failure: FALSE.
3355 * NOTE
3356 * A newly created key container does not contain private user key. Create them with CPGenKey.
3358 BOOL WINAPI RSAENH_CPGetUserKey(HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
3360 KEYCONTAINER *pKeyContainer;
3362 TRACE("(hProv=%08lx, dwKeySpec=%08x, phUserKey=%p)\n", hProv, dwKeySpec, phUserKey);
3364 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
3365 (OBJECTHDR**)&pKeyContainer))
3367 /* MSDN: hProv not containing valid context handle */
3368 SetLastError(NTE_BAD_UID);
3369 return FALSE;
3372 switch (dwKeySpec)
3374 case AT_KEYEXCHANGE:
3375 copy_handle(&handle_table, pKeyContainer->hKeyExchangeKeyPair, RSAENH_MAGIC_KEY,
3376 phUserKey);
3377 break;
3379 case AT_SIGNATURE:
3380 copy_handle(&handle_table, pKeyContainer->hSignatureKeyPair, RSAENH_MAGIC_KEY,
3381 phUserKey);
3382 break;
3384 default:
3385 *phUserKey = (HCRYPTKEY)INVALID_HANDLE_VALUE;
3388 if (*phUserKey == (HCRYPTKEY)INVALID_HANDLE_VALUE)
3390 /* MSDN: dwKeySpec parameter specifies nonexistent key */
3391 SetLastError(NTE_NO_KEY);
3392 return FALSE;
3395 return TRUE;
3398 /******************************************************************************
3399 * CPHashData (RSAENH.@)
3401 * Updates a hash object with the given data.
3403 * PARAMS
3404 * hProv [I] Key container to which the hash object belongs.
3405 * hHash [I] Hash object which is to be updated.
3406 * pbData [I] Pointer to data with which the hash object is to be updated.
3407 * dwDataLen [I] Length of the data.
3408 * dwFlags [I] Currently none defined.
3410 * RETURNS
3411 * Success: TRUE.
3412 * Failure: FALSE.
3414 * NOTES
3415 * The actual hash value is queried with CPGetHashParam, which will finalize
3416 * the hash. Updating a finalized hash will fail with a last error NTE_BAD_HASH_STATE.
3418 BOOL WINAPI RSAENH_CPHashData(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST BYTE *pbData,
3419 DWORD dwDataLen, DWORD dwFlags)
3421 CRYPTHASH *pCryptHash;
3423 TRACE("(hProv=%08lx, hHash=%08lx, pbData=%p, dwDataLen=%d, dwFlags=%08x)\n",
3424 hProv, hHash, pbData, dwDataLen, dwFlags);
3426 if (dwFlags)
3428 SetLastError(NTE_BAD_FLAGS);
3429 return FALSE;
3432 if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH,
3433 (OBJECTHDR**)&pCryptHash))
3435 SetLastError(NTE_BAD_HASH);
3436 return FALSE;
3439 if (!get_algid_info(hProv, pCryptHash->aiAlgid) || pCryptHash->aiAlgid == CALG_SSL3_SHAMD5)
3441 SetLastError(NTE_BAD_ALGID);
3442 return FALSE;
3445 if (pCryptHash->dwState != RSAENH_HASHSTATE_HASHING)
3447 SetLastError(NTE_BAD_HASH_STATE);
3448 return FALSE;
3451 update_hash(pCryptHash, pbData, dwDataLen);
3452 return TRUE;
3455 /******************************************************************************
3456 * CPHashSessionKey (RSAENH.@)
3458 * Updates a hash object with the binary representation of a symmetric key.
3460 * PARAMS
3461 * hProv [I] Key container to which the hash object belongs.
3462 * hHash [I] Hash object which is to be updated.
3463 * hKey [I] The symmetric key, whose binary value will be added to the hash.
3464 * dwFlags [I] CRYPT_LITTLE_ENDIAN, if the binary key value shall be interpreted as little endian.
3466 * RETURNS
3467 * Success: TRUE.
3468 * Failure: FALSE.
3470 BOOL WINAPI RSAENH_CPHashSessionKey(HCRYPTPROV hProv, HCRYPTHASH hHash, HCRYPTKEY hKey,
3471 DWORD dwFlags)
3473 BYTE abKeyValue[RSAENH_MAX_KEY_SIZE], bTemp;
3474 CRYPTKEY *pKey;
3475 DWORD i;
3477 TRACE("(hProv=%08lx, hHash=%08lx, hKey=%08lx, dwFlags=%08x)\n", hProv, hHash, hKey, dwFlags);
3479 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pKey) ||
3480 (GET_ALG_CLASS(pKey->aiAlgid) != ALG_CLASS_DATA_ENCRYPT))
3482 SetLastError(NTE_BAD_KEY);
3483 return FALSE;
3486 if (dwFlags & ~CRYPT_LITTLE_ENDIAN) {
3487 SetLastError(NTE_BAD_FLAGS);
3488 return FALSE;
3491 memcpy(abKeyValue, pKey->abKeyValue, pKey->dwKeyLen);
3492 if (!(dwFlags & CRYPT_LITTLE_ENDIAN)) {
3493 for (i=0; i<pKey->dwKeyLen/2; i++) {
3494 bTemp = abKeyValue[i];
3495 abKeyValue[i] = abKeyValue[pKey->dwKeyLen-i-1];
3496 abKeyValue[pKey->dwKeyLen-i-1] = bTemp;
3500 return RSAENH_CPHashData(hProv, hHash, abKeyValue, pKey->dwKeyLen, 0);
3503 /******************************************************************************
3504 * CPReleaseContext (RSAENH.@)
3506 * Release a key container.
3508 * PARAMS
3509 * hProv [I] Key container to be released.
3510 * dwFlags [I] Currently none defined.
3512 * RETURNS
3513 * Success: TRUE
3514 * Failure: FALSE
3516 BOOL WINAPI RSAENH_CPReleaseContext(HCRYPTPROV hProv, DWORD dwFlags)
3518 TRACE("(hProv=%08lx, dwFlags=%08x)\n", hProv, dwFlags);
3520 if (!release_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
3522 /* MSDN: hProv not containing valid context handle */
3523 SetLastError(NTE_BAD_UID);
3524 return FALSE;
3527 if (dwFlags) {
3528 SetLastError(NTE_BAD_FLAGS);
3529 return FALSE;
3532 return TRUE;
3535 /******************************************************************************
3536 * CPSetHashParam (RSAENH.@)
3538 * Set a parameter of a hash object
3540 * PARAMS
3541 * hProv [I] The key container to which the key belongs.
3542 * hHash [I] The hash object for which a parameter is to be set.
3543 * dwParam [I] Parameter type. See Notes.
3544 * pbData [I] Pointer to the parameter value.
3545 * dwFlags [I] Currently none defined.
3547 * RETURNS
3548 * Success: TRUE.
3549 * Failure: FALSE.
3551 * NOTES
3552 * Currently only the HP_HMAC_INFO dwParam type is defined.
3553 * The HMAC_INFO struct will be deep copied into the hash object.
3554 * See Internet RFC 2104 for details on the HMAC algorithm.
3556 BOOL WINAPI RSAENH_CPSetHashParam(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam,
3557 BYTE *pbData, DWORD dwFlags)
3559 CRYPTHASH *pCryptHash;
3560 CRYPTKEY *pCryptKey;
3561 int i;
3563 TRACE("(hProv=%08lx, hHash=%08lx, dwParam=%08x, pbData=%p, dwFlags=%08x)\n",
3564 hProv, hHash, dwParam, pbData, dwFlags);
3566 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
3568 SetLastError(NTE_BAD_UID);
3569 return FALSE;
3572 if (dwFlags) {
3573 SetLastError(NTE_BAD_FLAGS);
3574 return FALSE;
3577 if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH,
3578 (OBJECTHDR**)&pCryptHash))
3580 SetLastError(NTE_BAD_HASH);
3581 return FALSE;
3584 switch (dwParam) {
3585 case HP_HMAC_INFO:
3586 free_hmac_info(pCryptHash->pHMACInfo);
3587 if (!copy_hmac_info(&pCryptHash->pHMACInfo, (PHMAC_INFO)pbData)) return FALSE;
3589 if (!lookup_handle(&handle_table, pCryptHash->hKey, RSAENH_MAGIC_KEY,
3590 (OBJECTHDR**)&pCryptKey))
3592 SetLastError(NTE_FAIL); /* FIXME: correct error code? */
3593 return FALSE;
3596 for (i=0; i<RSAENH_MIN(pCryptKey->dwKeyLen,pCryptHash->pHMACInfo->cbInnerString); i++) {
3597 pCryptHash->pHMACInfo->pbInnerString[i] ^= pCryptKey->abKeyValue[i];
3599 for (i=0; i<RSAENH_MIN(pCryptKey->dwKeyLen,pCryptHash->pHMACInfo->cbOuterString); i++) {
3600 pCryptHash->pHMACInfo->pbOuterString[i] ^= pCryptKey->abKeyValue[i];
3603 init_hash(pCryptHash);
3604 return TRUE;
3606 case HP_HASHVAL:
3607 memcpy(pCryptHash->abHashValue, pbData, pCryptHash->dwHashSize);
3608 pCryptHash->dwState = RSAENH_HASHSTATE_FINISHED;
3609 return TRUE;
3611 case HP_TLS1PRF_SEED:
3612 return copy_data_blob(&pCryptHash->tpPRFParams.blobSeed, (PCRYPT_DATA_BLOB)pbData);
3614 case HP_TLS1PRF_LABEL:
3615 return copy_data_blob(&pCryptHash->tpPRFParams.blobLabel, (PCRYPT_DATA_BLOB)pbData);
3617 default:
3618 SetLastError(NTE_BAD_TYPE);
3619 return FALSE;
3623 /******************************************************************************
3624 * CPSetProvParam (RSAENH.@)
3626 BOOL WINAPI RSAENH_CPSetProvParam(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
3628 FIXME("(stub)\n");
3629 return FALSE;
3632 /******************************************************************************
3633 * CPSignHash (RSAENH.@)
3635 * Sign a hash object
3637 * PARAMS
3638 * hProv [I] The key container, to which the hash object belongs.
3639 * hHash [I] The hash object to be signed.
3640 * dwKeySpec [I] AT_SIGNATURE or AT_KEYEXCHANGE: Key used to generate the signature.
3641 * sDescription [I] Should be NULL for security reasons.
3642 * dwFlags [I] 0, CRYPT_NOHASHOID or CRYPT_X931_FORMAT: Format of the signature.
3643 * pbSignature [O] Buffer, to which the signature will be stored. May be NULL to query SigLen.
3644 * pdwSigLen [I/O] Size of the buffer (in), Length of the signature (out)
3646 * RETURNS
3647 * Success: TRUE
3648 * Failure: FALSE
3650 BOOL WINAPI RSAENH_CPSignHash(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwKeySpec,
3651 LPCWSTR sDescription, DWORD dwFlags, BYTE *pbSignature,
3652 DWORD *pdwSigLen)
3654 HCRYPTKEY hCryptKey;
3655 CRYPTKEY *pCryptKey;
3656 DWORD dwHashLen;
3657 BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
3658 ALG_ID aiAlgid;
3660 TRACE("(hProv=%08lx, hHash=%08lx, dwKeySpec=%08x, sDescription=%s, dwFlags=%08x, "
3661 "pbSignature=%p, pdwSigLen=%p)\n", hProv, hHash, dwKeySpec, debugstr_w(sDescription),
3662 dwFlags, pbSignature, pdwSigLen);
3664 if (dwFlags & ~(CRYPT_NOHASHOID|CRYPT_X931_FORMAT)) {
3665 SetLastError(NTE_BAD_FLAGS);
3666 return FALSE;
3669 if (!RSAENH_CPGetUserKey(hProv, dwKeySpec, &hCryptKey)) return FALSE;
3671 if (!lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY,
3672 (OBJECTHDR**)&pCryptKey))
3674 SetLastError(NTE_NO_KEY);
3675 return FALSE;
3678 if (!pbSignature) {
3679 *pdwSigLen = pCryptKey->dwKeyLen;
3680 return TRUE;
3682 if (pCryptKey->dwKeyLen > *pdwSigLen)
3684 SetLastError(ERROR_MORE_DATA);
3685 *pdwSigLen = pCryptKey->dwKeyLen;
3686 return FALSE;
3688 *pdwSigLen = pCryptKey->dwKeyLen;
3690 if (sDescription) {
3691 if (!RSAENH_CPHashData(hProv, hHash, (CONST BYTE*)sDescription,
3692 (DWORD)lstrlenW(sDescription)*sizeof(WCHAR), 0))
3694 return FALSE;
3698 dwHashLen = sizeof(DWORD);
3699 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_ALGID, (BYTE*)&aiAlgid, &dwHashLen, 0)) return FALSE;
3701 dwHashLen = RSAENH_MAX_HASH_SIZE;
3702 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_HASHVAL, abHashValue, &dwHashLen, 0)) return FALSE;
3705 if (!build_hash_signature(pbSignature, *pdwSigLen, aiAlgid, abHashValue, dwHashLen, dwFlags)) {
3706 return FALSE;
3709 return encrypt_block_impl(pCryptKey->aiAlgid, PK_PRIVATE, &pCryptKey->context, pbSignature, pbSignature, RSAENH_ENCRYPT);
3712 /******************************************************************************
3713 * CPVerifySignature (RSAENH.@)
3715 * Verify the signature of a hash object.
3717 * PARAMS
3718 * hProv [I] The key container, to which the hash belongs.
3719 * hHash [I] The hash for which the signature is verified.
3720 * pbSignature [I] The binary signature.
3721 * dwSigLen [I] Length of the signature BLOB.
3722 * hPubKey [I] Public key used to verify the signature.
3723 * sDescription [I] Should be NULL for security reasons.
3724 * dwFlags [I] 0, CRYPT_NOHASHOID or CRYPT_X931_FORMAT: Format of the signature.
3726 * RETURNS
3727 * Success: TRUE (Signature is valid)
3728 * Failure: FALSE (GetLastError() == NTE_BAD_SIGNATURE, if signature is invalid)
3730 BOOL WINAPI RSAENH_CPVerifySignature(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST BYTE *pbSignature,
3731 DWORD dwSigLen, HCRYPTKEY hPubKey, LPCWSTR sDescription,
3732 DWORD dwFlags)
3734 BYTE *pbConstructed = NULL, *pbDecrypted = NULL;
3735 CRYPTKEY *pCryptKey;
3736 DWORD dwHashLen;
3737 ALG_ID aiAlgid;
3738 BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
3739 BOOL res = FALSE;
3741 TRACE("(hProv=%08lx, hHash=%08lx, pbSignature=%p, dwSigLen=%d, hPubKey=%08lx, sDescription=%s, "
3742 "dwFlags=%08x)\n", hProv, hHash, pbSignature, dwSigLen, hPubKey, debugstr_w(sDescription),
3743 dwFlags);
3745 if (dwFlags & ~(CRYPT_NOHASHOID|CRYPT_X931_FORMAT)) {
3746 SetLastError(NTE_BAD_FLAGS);
3747 return FALSE;
3750 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
3752 SetLastError(NTE_BAD_UID);
3753 return FALSE;
3756 if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY,
3757 (OBJECTHDR**)&pCryptKey))
3759 SetLastError(NTE_BAD_KEY);
3760 return FALSE;
3763 /* in Microsoft implementation, the signature length is checked before
3764 * the signature pointer.
3766 if (dwSigLen != pCryptKey->dwKeyLen)
3768 SetLastError(NTE_BAD_SIGNATURE);
3769 return FALSE;
3772 if (!hHash || !pbSignature)
3774 SetLastError(ERROR_INVALID_PARAMETER);
3775 return FALSE;
3778 if (sDescription) {
3779 if (!RSAENH_CPHashData(hProv, hHash, (CONST BYTE*)sDescription,
3780 (DWORD)lstrlenW(sDescription)*sizeof(WCHAR), 0))
3782 return FALSE;
3786 dwHashLen = sizeof(DWORD);
3787 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_ALGID, (BYTE*)&aiAlgid, &dwHashLen, 0)) return FALSE;
3789 dwHashLen = RSAENH_MAX_HASH_SIZE;
3790 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_HASHVAL, abHashValue, &dwHashLen, 0)) return FALSE;
3792 pbConstructed = HeapAlloc(GetProcessHeap(), 0, dwSigLen);
3793 if (!pbConstructed) {
3794 SetLastError(NTE_NO_MEMORY);
3795 goto cleanup;
3798 pbDecrypted = HeapAlloc(GetProcessHeap(), 0, dwSigLen);
3799 if (!pbDecrypted) {
3800 SetLastError(NTE_NO_MEMORY);
3801 goto cleanup;
3804 if (!encrypt_block_impl(pCryptKey->aiAlgid, PK_PUBLIC, &pCryptKey->context, pbSignature, pbDecrypted,
3805 RSAENH_DECRYPT))
3807 goto cleanup;
3810 if (!build_hash_signature(pbConstructed, dwSigLen, aiAlgid, abHashValue, dwHashLen, dwFlags)) {
3811 goto cleanup;
3814 if (memcmp(pbDecrypted, pbConstructed, dwSigLen)) {
3815 SetLastError(NTE_BAD_SIGNATURE);
3816 goto cleanup;
3819 res = TRUE;
3820 cleanup:
3821 HeapFree(GetProcessHeap(), 0, pbConstructed);
3822 HeapFree(GetProcessHeap(), 0, pbDecrypted);
3823 return res;
3826 static const WCHAR szProviderKeys[5][104] = {
3827 { 'S','o','f','t','w','a','r','e','\\',
3828 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3829 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3830 'i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ','B','a','s',
3831 'e',' ','C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r',
3832 'o','v','i','d','e','r',' ','v','1','.','0',0 },
3833 { 'S','o','f','t','w','a','r','e','\\',
3834 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3835 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3836 'i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ',
3837 'E','n','h','a','n','c','e','d',
3838 ' ','C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r',
3839 'o','v','i','d','e','r',' ','v','1','.','0',0 },
3840 { 'S','o','f','t','w','a','r','e','\\',
3841 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3842 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3843 'i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ','S','t','r','o','n','g',
3844 ' ','C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r',
3845 'o','v','i','d','e','r',0 },
3846 { 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
3847 'C','r','y','p','t','o','g','r','a','p','h','y','\\','D','e','f','a','u','l','t','s','\\',
3848 'P','r','o','v','i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ',
3849 'R','S','A',' ','S','C','h','a','n','n','e','l',' ',
3850 'C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r','o','v','i','d','e','r',0 },
3851 { 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
3852 'C','r','y','p','t','o','g','r','a','p','h','y','\\','D','e','f','a','u','l','t','s','\\',
3853 'P','r','o','v','i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ',
3854 'E','n','h','a','n','c','e','d',' ','R','S','A',' ','a','n','d',' ','A','E','S',' ',
3855 'C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r','o','v','i','d','e','r',0 }
3857 static const WCHAR szDefaultKeys[3][65] = {
3858 { 'S','o','f','t','w','a','r','e','\\',
3859 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3860 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3861 'i','d','e','r',' ','T','y','p','e','s','\\','T','y','p','e',' ','0','0','1',0 },
3862 { 'S','o','f','t','w','a','r','e','\\',
3863 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3864 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3865 'i','d','e','r',' ','T','y','p','e','s','\\','T','y','p','e',' ','0','1','2',0 },
3866 { 'S','o','f','t','w','a','r','e','\\',
3867 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3868 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3869 'i','d','e','r',' ','T','y','p','e','s','\\','T','y','p','e',' ','0','2','4',0 }
3873 /******************************************************************************
3874 * DllRegisterServer (RSAENH.@)
3876 * Dll self registration.
3878 * PARAMS
3880 * RETURNS
3881 * Success: S_OK.
3882 * Failure: != S_OK
3884 * NOTES
3885 * Registers the following keys:
3886 * - HKLM\Software\Microsoft\Cryptography\Defaults\Provider\
3887 * Microsoft Base Cryptographic Provider v1.0
3888 * - HKLM\Software\Microsoft\Cryptography\Defaults\Provider\
3889 * Microsoft Enhanced Cryptographic Provider
3890 * - HKLM\Software\Microsoft\Cryptography\Defaults\Provider\
3891 * Microsoft Strong Cryptographpic Provider
3892 * - HKLM\Software\Microsoft\Cryptography\Defaults\Provider Types\Type 001
3894 HRESULT WINAPI DllRegisterServer(void)
3896 HKEY key;
3897 DWORD dp;
3898 long apiRet;
3899 int i;
3901 for (i=0; i<5; i++) {
3902 apiRet = RegCreateKeyExW(HKEY_LOCAL_MACHINE, szProviderKeys[i], 0, NULL,
3903 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dp);
3905 if (apiRet == ERROR_SUCCESS)
3907 if (dp == REG_CREATED_NEW_KEY)
3909 static const WCHAR szImagePath[] = { 'I','m','a','g','e',' ','P','a','t','h',0 };
3910 static const WCHAR szRSABase[] = { 'r','s','a','e','n','h','.','d','l','l',0 };
3911 static const WCHAR szType[] = { 'T','y','p','e',0 };
3912 static const WCHAR szSignature[] = { 'S','i','g','n','a','t','u','r','e',0 };
3913 DWORD type, sign;
3915 switch(i)
3917 case 3:
3918 type=PROV_RSA_SCHANNEL;
3919 break;
3920 case 4:
3921 type=PROV_RSA_AES;
3922 break;
3923 default:
3924 type=PROV_RSA_FULL;
3925 break;
3927 sign = 0xdeadbeef;
3928 RegSetValueExW(key, szImagePath, 0, REG_SZ, (const BYTE *)szRSABase,
3929 (lstrlenW(szRSABase) + 1) * sizeof(WCHAR));
3930 RegSetValueExW(key, szType, 0, REG_DWORD, (LPBYTE)&type, sizeof(type));
3931 RegSetValueExW(key, szSignature, 0, REG_BINARY, (LPBYTE)&sign, sizeof(sign));
3933 RegCloseKey(key);
3937 for (i=0; i<3; i++) {
3938 apiRet = RegCreateKeyExW(HKEY_LOCAL_MACHINE, szDefaultKeys[i], 0, NULL,
3939 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dp);
3940 if (apiRet == ERROR_SUCCESS)
3942 if (dp == REG_CREATED_NEW_KEY)
3944 static const WCHAR szName[] = { 'N','a','m','e',0 };
3945 static const WCHAR szRSAName[3][54] = {
3946 { 'M','i','c','r','o','s','o','f','t',' ', 'B','a','s','e',' ',
3947 'C','r','y','p','t','o','g','r','a','p','h','i','c',' ',
3948 'P','r','o','v','i','d','e','r',' ','v','1','.','0',0 },
3949 { 'M','i','c','r','o','s','o','f','t',' ','R','S','A',' ',
3950 'S','C','h','a','n','n','e','l',' ',
3951 'C','r','y','p','t','o','g','r','a','p','h','i','c',' ',
3952 'P','r','o','v','i','d','e','r',0 },
3953 { 'M','i','c','r','o','s','o','f','t',' ','E','n','h','a','n','c','e','d',' ',
3954 'R','S','A',' ','a','n','d',' ','A','E','S',' ',
3955 'C','r','y','p','t','o','g','r','a','p','h','i','c',' ',
3956 'P','r','o','v','i','d','e','r',0 } };
3957 static const WCHAR szTypeName[] = { 'T','y','p','e','N','a','m','e',0 };
3958 static const WCHAR szRSATypeName[3][38] = {
3959 { 'R','S','A',' ','F','u','l','l',' ',
3960 '(','S','i','g','n','a','t','u','r','e',' ','a','n','d',' ',
3961 'K','e','y',' ','E','x','c','h','a','n','g','e',')',0 },
3962 { 'R','S','A',' ','S','C','h','a','n','n','e','l',0 },
3963 { 'R','S','A',' ','F','u','l','l',' ','a','n','d',' ','A','E','S',0 } };
3965 RegSetValueExW(key, szName, 0, REG_SZ,
3966 (const BYTE *)szRSAName[i], lstrlenW(szRSAName[i])*sizeof(WCHAR)+sizeof(WCHAR));
3967 RegSetValueExW(key, szTypeName, 0, REG_SZ,
3968 (const BYTE *)szRSATypeName[i], lstrlenW(szRSATypeName[i])*sizeof(WCHAR)+sizeof(WCHAR));
3971 RegCloseKey(key);
3974 return HRESULT_FROM_WIN32(apiRet);
3977 /******************************************************************************
3978 * DllUnregisterServer (RSAENH.@)
3980 * Dll self unregistration.
3982 * PARAMS
3984 * RETURNS
3985 * Success: S_OK
3987 * NOTES
3988 * For the relevant keys see DllRegisterServer.
3990 HRESULT WINAPI DllUnregisterServer(void)
3992 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[0]);
3993 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[1]);
3994 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[2]);
3995 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[3]);
3996 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[4]);
3997 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szDefaultKeys[0]);
3998 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szDefaultKeys[1]);
3999 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szDefaultKeys[2]);
4000 return S_OK;