source: trunk/src/rsaenh/rsaenh.c@ 21363

Last change on this file since 21363 was 21363, checked in by vladest, 16 years ago
  • Added RSA security interface
File size: 144.2 KB
Line 
1/*
2 * dlls/rsaenh/rsaenh.c
3 * RSAENH - RSA encryption for Wine
4 *
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
9 *
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.
14 *
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.
19 *
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
23 */
24
25#include "config.h"
26#include "wine/port.h"
27#include "wine/library.h"
28#include "wine/debug.h"
29
30#include <stdarg.h>
31#include <stdio.h>
32
33#include "windef.h"
34#include "winbase.h"
35#include "winreg.h"
36#include "wincrypt.h"
37#include "handle.h"
38#include "implglue.h"
39#include "objbase.h"
40#include <winerror.h>
41
42WINE_DEFAULT_DEBUG_CHANNEL(crypt);
43#include <heapstring.h>
44#define snprintf wsnprintfA
45
46/******************************************************************************
47 * CRYPTHASH - hash objects
48 */
49#define RSAENH_MAGIC_HASH 0x85938417u
50#define RSAENH_MAX_HASH_SIZE 104
51#define RSAENH_HASHSTATE_HASHING 1
52#define RSAENH_HASHSTATE_FINISHED 2
53typedef struct _RSAENH_TLS1PRF_PARAMS
54{
55 CRYPT_DATA_BLOB blobLabel;
56 CRYPT_DATA_BLOB blobSeed;
57} RSAENH_TLS1PRF_PARAMS;
58
59typedef struct tagCRYPTHASH
60{
61 OBJECTHDR header;
62 ALG_ID aiAlgid;
63 HCRYPTKEY hKey;
64 HCRYPTPROV hProv;
65 DWORD dwHashSize;
66 DWORD dwState;
67 HASH_CONTEXT context;
68 BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
69 PHMAC_INFO pHMACInfo;
70 RSAENH_TLS1PRF_PARAMS tpPRFParams;
71} CRYPTHASH;
72
73/******************************************************************************
74 * CRYPTKEY - key objects
75 */
76#define RSAENH_MAGIC_KEY 0x73620457u
77#define RSAENH_MAX_KEY_SIZE 48
78#define RSAENH_MAX_BLOCK_SIZE 24
79#define RSAENH_KEYSTATE_IDLE 0
80#define RSAENH_KEYSTATE_ENCRYPTING 1
81#define RSAENH_KEYSTATE_MASTERKEY 2
82typedef struct _RSAENH_SCHANNEL_INFO
83{
84 SCHANNEL_ALG saEncAlg;
85 SCHANNEL_ALG saMACAlg;
86 CRYPT_DATA_BLOB blobClientRandom;
87 CRYPT_DATA_BLOB blobServerRandom;
88} RSAENH_SCHANNEL_INFO;
89
90typedef struct tagCRYPTKEY
91{
92 OBJECTHDR header;
93 ALG_ID aiAlgid;
94 HCRYPTPROV hProv;
95 DWORD dwMode;
96 DWORD dwModeBits;
97 DWORD dwPermissions;
98 DWORD dwKeyLen;
99 DWORD dwEffectiveKeyLen;
100 DWORD dwSaltLen;
101 DWORD dwBlockLen;
102 DWORD dwState;
103 KEY_CONTEXT context;
104 BYTE abKeyValue[RSAENH_MAX_KEY_SIZE];
105 BYTE abInitVector[RSAENH_MAX_BLOCK_SIZE];
106 BYTE abChainVector[RSAENH_MAX_BLOCK_SIZE];
107 RSAENH_SCHANNEL_INFO siSChannelInfo;
108} CRYPTKEY;
109
110/******************************************************************************
111 * KEYCONTAINER - key containers
112 */
113#define RSAENH_PERSONALITY_BASE 0u
114#define RSAENH_PERSONALITY_STRONG 1u
115#define RSAENH_PERSONALITY_ENHANCED 2u
116#define RSAENH_PERSONALITY_SCHANNEL 3u
117#define RSAENH_PERSONALITY_AES 4u
118
119#define RSAENH_MAGIC_CONTAINER 0x26384993u
120typedef struct tagKEYCONTAINER
121{
122 OBJECTHDR header;
123 DWORD dwFlags;
124 DWORD dwPersonality;
125 DWORD dwEnumAlgsCtr;
126 DWORD dwEnumContainersCtr;
127 CHAR szName[MAX_PATH];
128 CHAR szProvName[MAX_PATH];
129 HCRYPTKEY hKeyExchangeKeyPair;
130 HCRYPTKEY hSignatureKeyPair;
131} KEYCONTAINER;
132
133/******************************************************************************
134 * Some magic constants
135 */
136#define RSAENH_ENCRYPT 1
137#define RSAENH_DECRYPT 0
138#define RSAENH_HMAC_DEF_IPAD_CHAR 0x36
139#define RSAENH_HMAC_DEF_OPAD_CHAR 0x5c
140#define RSAENH_HMAC_DEF_PAD_LEN 64
141#define RSAENH_DES_EFFECTIVE_KEYLEN 56
142#define RSAENH_DES_STORAGE_KEYLEN 64
143#define RSAENH_3DES112_EFFECTIVE_KEYLEN 112
144#define RSAENH_3DES112_STORAGE_KEYLEN 128
145#define RSAENH_3DES_EFFECTIVE_KEYLEN 168
146#define RSAENH_3DES_STORAGE_KEYLEN 192
147#define RSAENH_MAGIC_RSA2 0x32415352
148#define RSAENH_MAGIC_RSA1 0x31415352
149#define RSAENH_PKC_BLOCKTYPE 0x02
150#define RSAENH_SSL3_VERSION_MAJOR 3
151#define RSAENH_SSL3_VERSION_MINOR 0
152#define RSAENH_TLS1_VERSION_MAJOR 3
153#define RSAENH_TLS1_VERSION_MINOR 1
154#define RSAENH_REGKEY "Software\\Wine\\Crypto\\RSA\\%s"
155
156#define RSAENH_MIN(a,b) ((a)<(b)?(a):(b))
157/******************************************************************************
158 * aProvEnumAlgsEx - Defines the capabilities of the CSP personalities.
159 */
160#define RSAENH_MAX_ENUMALGS 24
161#define RSAENH_PCT1_SSL2_SSL3_TLS1 (CRYPT_FLAG_PCT1|CRYPT_FLAG_SSL2|CRYPT_FLAG_SSL3|CRYPT_FLAG_TLS1)
162static const PROV_ENUMALGS_EX aProvEnumAlgsEx[5][RSAENH_MAX_ENUMALGS+1] =
163{
164 {
165 {CALG_RC2, 40, 40, 56,0, 4,"RC2", 24,"RSA Data Security's RC2"},
166 {CALG_RC4, 40, 40, 56,0, 4,"RC4", 24,"RSA Data Security's RC4"},
167 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"},
168 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"},
169 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"},
170 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"},
171 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"},
172 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
173 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
174 {CALG_RSA_SIGN, 512,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
175 {CALG_RSA_KEYX, 512,384, 1024,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
176 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
177 {0, 0, 0, 0,0, 1,"", 1,""}
178 },
179 {
180 {CALG_RC2, 128, 40, 128,0, 4,"RC2", 24,"RSA Data Security's RC2"},
181 {CALG_RC4, 128, 40, 128,0, 4,"RC4", 24,"RSA Data Security's RC4"},
182 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"},
183 {CALG_3DES_112, 112,112, 112,0, 13,"3DES TWO KEY",19,"Two Key Triple DES"},
184 {CALG_3DES, 168,168, 168,0, 5,"3DES", 21,"Three Key Triple DES"},
185 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"},
186 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"},
187 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"},
188 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"},
189 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
190 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
191 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
192 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
193 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
194 {0, 0, 0, 0,0, 1,"", 1,""}
195 },
196 {
197 {CALG_RC2, 128, 40, 128,0, 4,"RC2", 24,"RSA Data Security's RC2"},
198 {CALG_RC4, 128, 40, 128,0, 4,"RC4", 24,"RSA Data Security's RC4"},
199 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"},
200 {CALG_3DES_112, 112,112, 112,0, 13,"3DES TWO KEY",19,"Two Key Triple DES"},
201 {CALG_3DES, 168,168, 168,0, 5,"3DES", 21,"Three Key Triple DES"},
202 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"},
203 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"},
204 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"},
205 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"},
206 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
207 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
208 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
209 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
210 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
211 {0, 0, 0, 0,0, 1,"", 1,""}
212 },
213 {
214 {CALG_RC2, 128, 40, 128,RSAENH_PCT1_SSL2_SSL3_TLS1, 4,"RC2", 24,"RSA Data Security's RC2"},
215 {CALG_RC4, 128, 40, 128,RSAENH_PCT1_SSL2_SSL3_TLS1, 4,"RC4", 24,"RSA Data Security's RC4"},
216 {CALG_DES, 56, 56, 56,RSAENH_PCT1_SSL2_SSL3_TLS1, 4,"DES", 31,"Data Encryption Standard (DES)"},
217 {CALG_3DES_112, 112,112, 112,RSAENH_PCT1_SSL2_SSL3_TLS1,13,"3DES TWO KEY",19,"Two Key Triple DES"},
218 {CALG_3DES, 168,168, 168,RSAENH_PCT1_SSL2_SSL3_TLS1, 5,"3DES", 21,"Three Key Triple DES"},
219 {CALG_SHA,160,160,160,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,6,"SHA-1",30,"Secure Hash Algorithm (SHA-1)"},
220 {CALG_MD5,128,128,128,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,4,"MD5",23,"Message Digest 5 (MD5)"},
221 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
222 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
223 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,9,"RSA_SIGN",14,"RSA Signature"},
224 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,9,"RSA_KEYX",17,"RSA Key Exchange"},
225 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
226 {CALG_PCT1_MASTER,128,128,128,CRYPT_FLAG_PCT1, 12,"PCT1 MASTER",12,"PCT1 Master"},
227 {CALG_SSL2_MASTER,40,40, 192,CRYPT_FLAG_SSL2, 12,"SSL2 MASTER",12,"SSL2 Master"},
228 {CALG_SSL3_MASTER,384,384,384,CRYPT_FLAG_SSL3, 12,"SSL3 MASTER",12,"SSL3 Master"},
229 {CALG_TLS1_MASTER,384,384,384,CRYPT_FLAG_TLS1, 12,"TLS1 MASTER",12,"TLS1 Master"},
230 {CALG_SCHANNEL_MASTER_HASH,0,0,-1,0, 16,"SCH MASTER HASH",21,"SChannel Master Hash"},
231 {CALG_SCHANNEL_MAC_KEY,0,0,-1,0, 12,"SCH MAC KEY",17,"SChannel MAC Key"},
232 {CALG_SCHANNEL_ENC_KEY,0,0,-1,0, 12,"SCH ENC KEY",24,"SChannel Encryption Key"},
233 {CALG_TLS1PRF, 0, 0, -1,0, 9,"TLS1 PRF", 28,"TLS1 Pseudo Random Function"},
234 {0, 0, 0, 0,0, 1,"", 1,""}
235 },
236 {
237 {CALG_RC2, 128, 40, 128,0, 4,"RC2", 24,"RSA Data Security's RC2"},
238 {CALG_RC4, 128, 40, 128,0, 4,"RC4", 24,"RSA Data Security's RC4"},
239 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"},
240 {CALG_3DES_112, 112,112, 112,0, 13,"3DES TWO KEY",19,"Two Key Triple DES"},
241 {CALG_3DES, 168,168, 168,0, 5,"3DES", 21,"Three Key Triple DES"},
242 {CALG_AES, 128,128, 128,0, 4,"AES", 35,"Advanced Encryption Standard (AES)"},
243 {CALG_AES_128, 128,128, 128,0, 8,"AES-128", 39,"Advanced Encryption Standard (AES-128)"},
244 {CALG_AES_192, 192,192, 192,0, 8,"AES-192", 39,"Advanced Encryption Standard (AES-192)"},
245 {CALG_AES_256, 256,256, 256,0, 8,"AES-256", 39,"Advanced Encryption Standard (AES-256)"},
246 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"},
247 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"},
248 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"},
249 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"},
250 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
251 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
252 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
253 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
254 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
255 {0, 0, 0, 0,0, 1,"", 1,""}
256 }
257};
258
259/******************************************************************************
260 * API forward declarations
261 */
262BOOL WINAPI
263RSAENH_CPGetKeyParam(
264 HCRYPTPROV hProv,
265 HCRYPTKEY hKey,
266 DWORD dwParam,
267 BYTE *pbData,
268 DWORD *pdwDataLen,
269 DWORD dwFlags
270);
271
272BOOL WINAPI
273RSAENH_CPEncrypt(
274 HCRYPTPROV hProv,
275 HCRYPTKEY hKey,
276 HCRYPTHASH hHash,
277 BOOL Final,
278 DWORD dwFlags,
279 BYTE *pbData,
280 DWORD *pdwDataLen,
281 DWORD dwBufLen
282);
283
284BOOL WINAPI
285RSAENH_CPCreateHash(
286 HCRYPTPROV hProv,
287 ALG_ID Algid,
288 HCRYPTKEY hKey,
289 DWORD dwFlags,
290 HCRYPTHASH *phHash
291);
292
293BOOL WINAPI
294RSAENH_CPSetHashParam(
295 HCRYPTPROV hProv,
296 HCRYPTHASH hHash,
297 DWORD dwParam,
298 BYTE *pbData, DWORD dwFlags
299);
300
301BOOL WINAPI
302RSAENH_CPGetHashParam(
303 HCRYPTPROV hProv,
304 HCRYPTHASH hHash,
305 DWORD dwParam,
306 BYTE *pbData,
307 DWORD *pdwDataLen,
308 DWORD dwFlags
309);
310
311BOOL WINAPI
312RSAENH_CPDestroyHash(
313 HCRYPTPROV hProv,
314 HCRYPTHASH hHash
315);
316
317BOOL WINAPI
318RSAENH_CPExportKey(
319 HCRYPTPROV hProv,
320 HCRYPTKEY hKey,
321 HCRYPTKEY hPubKey,
322 DWORD dwBlobType,
323 DWORD dwFlags,
324 BYTE *pbData,
325 DWORD *pdwDataLen
326);
327
328BOOL WINAPI
329RSAENH_CPImportKey(
330 HCRYPTPROV hProv,
331 CONST BYTE *pbData,
332 DWORD dwDataLen,
333 HCRYPTKEY hPubKey,
334 DWORD dwFlags,
335 HCRYPTKEY *phKey
336);
337
338BOOL WINAPI
339RSAENH_CPHashData(
340 HCRYPTPROV hProv,
341 HCRYPTHASH hHash,
342 CONST BYTE *pbData,
343 DWORD dwDataLen,
344 DWORD dwFlags
345);
346
347/******************************************************************************
348 * CSP's handle table (used by all acquired key containers)
349 */
350static HANDLETABLE handle_table;
351
352/******************************************************************************
353 * DllMain (RSAENH.@)
354 *
355 * Initializes and destroys the handle table for the CSP's handles.
356 */
357int WINAPI RsaenhDllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
358{
359 switch (fdwReason)
360 {
361 case DLL_PROCESS_ATTACH:
362 DisableThreadLibraryCalls(hInstance);
363 init_handle_table(&handle_table);
364 break;
365
366 case DLL_PROCESS_DETACH:
367 destroy_handle_table(&handle_table);
368 break;
369 }
370 return 1;
371}
372
373/******************************************************************************
374 * copy_param [Internal]
375 *
376 * Helper function that supports the standard WINAPI protocol for querying data
377 * of dynamic size.
378 *
379 * PARAMS
380 * pbBuffer [O] Buffer where the queried parameter is copied to, if it is large enough.
381 * May be NUL if the required buffer size is to be queried only.
382 * pdwBufferSize [I/O] In: Size of the buffer at pbBuffer
383 * Out: Size of parameter pbParam
384 * pbParam [I] Parameter value.
385 * dwParamSize [I] Size of pbParam
386 *
387 * RETURN
388 * Success: TRUE (pbParam was copied into pbBuffer or pbBuffer is NULL)
389 * Failure: FALSE (pbBuffer is not large enough to hold pbParam). Last error: ERROR_MORE_DATA
390 */
391static inline BOOL copy_param(
392 BYTE *pbBuffer, DWORD *pdwBufferSize, CONST BYTE *pbParam, DWORD dwParamSize)
393{
394 if (pbBuffer)
395 {
396 if (dwParamSize > *pdwBufferSize)
397 {
398 SetLastError(ERROR_MORE_DATA);
399 *pdwBufferSize = dwParamSize;
400 return FALSE;
401 }
402 memcpy(pbBuffer, pbParam, dwParamSize);
403 }
404 *pdwBufferSize = dwParamSize;
405 return TRUE;
406}
407
408/******************************************************************************
409 * get_algid_info [Internal]
410 *
411 * Query CSP capabilities for a given crypto algorithm.
412 *
413 * PARAMS
414 * hProv [I] Handle to a key container of the CSP whose capabilities are to be queried.
415 * algid [I] Identifier of the crypto algorithm about which information is requested.
416 *
417 * RETURNS
418 * Success: Pointer to a PROV_ENUMALGS_EX struct containing information about the crypto algorithm.
419 * Failure: NULL (algid not supported)
420 */
421static inline const PROV_ENUMALGS_EX* get_algid_info(HCRYPTPROV hProv, ALG_ID algid) {
422 const PROV_ENUMALGS_EX *iterator;
423 KEYCONTAINER *pKeyContainer;
424
425 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER, (OBJECTHDR**)&pKeyContainer)) {
426 SetLastError(NTE_BAD_UID);
427 return NULL;
428 }
429
430 for (iterator = aProvEnumAlgsEx[pKeyContainer->dwPersonality]; iterator->aiAlgid; iterator++) {
431 if (iterator->aiAlgid == algid) return iterator;
432 }
433
434 SetLastError(NTE_BAD_ALGID);
435 return NULL;
436}
437
438/******************************************************************************
439 * copy_data_blob [Internal]
440 *
441 * deeply copies a DATA_BLOB
442 *
443 * PARAMS
444 * dst [O] That's where the blob will be copied to
445 * src [I] Source blob
446 *
447 * RETURNS
448 * Success: TRUE
449 * Failure: FALSE (GetLastError() == NTE_NO_MEMORY
450 *
451 * NOTES
452 * Use free_data_blob to release resources occupied by copy_data_blob.
453 */
454static inline BOOL copy_data_blob(PCRYPT_DATA_BLOB dst, CONST PCRYPT_DATA_BLOB src) {
455 dst->pbData = HeapAlloc(GetProcessHeap(), 0, src->cbData);
456 if (!dst->pbData) {
457 SetLastError(NTE_NO_MEMORY);
458 return FALSE;
459 }
460 dst->cbData = src->cbData;
461 memcpy(dst->pbData, src->pbData, src->cbData);
462 return TRUE;
463}
464
465/******************************************************************************
466 * concat_data_blobs [Internal]
467 *
468 * Concatenates two blobs
469 *
470 * PARAMS
471 * dst [O] The new blob will be copied here
472 * src1 [I] Prefix blob
473 * src2 [I] Appendix blob
474 *
475 * RETURNS
476 * Success: TRUE
477 * Failure: FALSE (GetLastError() == NTE_NO_MEMORY)
478 *
479 * NOTES
480 * Release resources occupied by concat_data_blobs with free_data_blobs
481 */
482static inline BOOL concat_data_blobs(PCRYPT_DATA_BLOB dst, CONST PCRYPT_DATA_BLOB src1,
483 CONST PCRYPT_DATA_BLOB src2)
484{
485 dst->cbData = src1->cbData + src2->cbData;
486 dst->pbData = HeapAlloc(GetProcessHeap(), 0, dst->cbData);
487 if (!dst->pbData) {
488 SetLastError(NTE_NO_MEMORY);
489 return FALSE;
490 }
491 memcpy(dst->pbData, src1->pbData, src1->cbData);
492 memcpy(dst->pbData + src1->cbData, src2->pbData, src2->cbData);
493 return TRUE;
494}
495
496/******************************************************************************
497 * free_data_blob [Internal]
498 *
499 * releases resource occupied by a dynamically allocated CRYPT_DATA_BLOB
500 *
501 * PARAMS
502 * pBlob [I] Heap space occupied by pBlob->pbData is released
503 */
504static inline void free_data_blob(PCRYPT_DATA_BLOB pBlob) {
505 HeapFree(GetProcessHeap(), 0, pBlob->pbData);
506}
507
508/******************************************************************************
509 * init_data_blob [Internal]
510 */
511static inline void init_data_blob(PCRYPT_DATA_BLOB pBlob) {
512 pBlob->pbData = NULL;
513 pBlob->cbData = 0;
514}
515
516/******************************************************************************
517 * free_hmac_info [Internal]
518 *
519 * Deeply free an HMAC_INFO struct.
520 *
521 * PARAMS
522 * hmac_info [I] Pointer to the HMAC_INFO struct to be freed.
523 *
524 * NOTES
525 * See Internet RFC 2104 for details on the HMAC algorithm.
526 */
527static inline void free_hmac_info(PHMAC_INFO hmac_info) {
528 if (!hmac_info) return;
529 HeapFree(GetProcessHeap(), 0, hmac_info->pbInnerString);
530 HeapFree(GetProcessHeap(), 0, hmac_info->pbOuterString);
531 HeapFree(GetProcessHeap(), 0, hmac_info);
532}
533
534/******************************************************************************
535 * copy_hmac_info [Internal]
536 *
537 * Deeply copy an HMAC_INFO struct
538 *
539 * PARAMS
540 * dst [O] Pointer to a location where the pointer to the HMAC_INFO copy will be stored.
541 * src [I] Pointer to the HMAC_INFO struct to be copied.
542 *
543 * RETURNS
544 * Success: TRUE
545 * Failure: FALSE
546 *
547 * NOTES
548 * See Internet RFC 2104 for details on the HMAC algorithm.
549 */
550static BOOL copy_hmac_info(PHMAC_INFO *dst, const HMAC_INFO *src) {
551 if (!src) return FALSE;
552 *dst = HeapAlloc(GetProcessHeap(), 0, sizeof(HMAC_INFO));
553 if (!*dst) return FALSE;
554 **dst = *src;
555 (*dst)->pbInnerString = NULL;
556 (*dst)->pbOuterString = NULL;
557 if ((*dst)->cbInnerString == 0) (*dst)->cbInnerString = RSAENH_HMAC_DEF_PAD_LEN;
558 (*dst)->pbInnerString = HeapAlloc(GetProcessHeap(), 0, (*dst)->cbInnerString);
559 if (!(*dst)->pbInnerString) {
560 free_hmac_info(*dst);
561 return FALSE;
562 }
563 if (src->cbInnerString)
564 memcpy((*dst)->pbInnerString, src->pbInnerString, src->cbInnerString);
565 else
566 memset((*dst)->pbInnerString, RSAENH_HMAC_DEF_IPAD_CHAR, RSAENH_HMAC_DEF_PAD_LEN);
567 if ((*dst)->cbOuterString == 0) (*dst)->cbOuterString = RSAENH_HMAC_DEF_PAD_LEN;
568 (*dst)->pbOuterString = HeapAlloc(GetProcessHeap(), 0, (*dst)->cbOuterString);
569 if (!(*dst)->pbOuterString) {
570 free_hmac_info(*dst);
571 return FALSE;
572 }
573 if (src->cbOuterString)
574 memcpy((*dst)->pbOuterString, src->pbOuterString, src->cbOuterString);
575 else
576 memset((*dst)->pbOuterString, RSAENH_HMAC_DEF_OPAD_CHAR, RSAENH_HMAC_DEF_PAD_LEN);
577 return TRUE;
578}
579
580/******************************************************************************
581 * destroy_hash [Internal]
582 *
583 * Destructor for hash objects
584 *
585 * PARAMS
586 * pCryptHash [I] Pointer to the hash object to be destroyed.
587 * Will be invalid after function returns!
588 */
589static void destroy_hash(OBJECTHDR *pObject)
590{
591 CRYPTHASH *pCryptHash = (CRYPTHASH*)pObject;
592
593 free_hmac_info(pCryptHash->pHMACInfo);
594 free_data_blob(&pCryptHash->tpPRFParams.blobLabel);
595 free_data_blob(&pCryptHash->tpPRFParams.blobSeed);
596 HeapFree(GetProcessHeap(), 0, pCryptHash);
597}
598
599/******************************************************************************
600 * init_hash [Internal]
601 *
602 * Initialize (or reset) a hash object
603 *
604 * PARAMS
605 * pCryptHash [I] The hash object to be initialized.
606 */
607static inline BOOL init_hash(CRYPTHASH *pCryptHash) {
608 DWORD dwLen;
609
610 switch (pCryptHash->aiAlgid)
611 {
612 case CALG_HMAC:
613 if (pCryptHash->pHMACInfo) {
614 const PROV_ENUMALGS_EX *pAlgInfo;
615
616 pAlgInfo = get_algid_info(pCryptHash->hProv, pCryptHash->pHMACInfo->HashAlgid);
617 if (!pAlgInfo) return FALSE;
618 pCryptHash->dwHashSize = pAlgInfo->dwDefaultLen >> 3;
619 init_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context);
620 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
621 pCryptHash->pHMACInfo->pbInnerString,
622 pCryptHash->pHMACInfo->cbInnerString);
623 }
624 return TRUE;
625
626 case CALG_MAC:
627 dwLen = sizeof(DWORD);
628 RSAENH_CPGetKeyParam(pCryptHash->hProv, pCryptHash->hKey, KP_BLOCKLEN,
629 (BYTE*)&pCryptHash->dwHashSize, &dwLen, 0);
630 pCryptHash->dwHashSize >>= 3;
631 return TRUE;
632
633 default:
634 return init_hash_impl(pCryptHash->aiAlgid, &pCryptHash->context);
635 }
636}
637
638/******************************************************************************
639 * update_hash [Internal]
640 *
641 * Hashes the given data and updates the hash object's state accordingly
642 *
643 * PARAMS
644 * pCryptHash [I] Hash object to be updated.
645 * pbData [I] Pointer to data stream to be hashed.
646 * dwDataLen [I] Length of data stream.
647 */
648static inline void update_hash(CRYPTHASH *pCryptHash, CONST BYTE *pbData, DWORD dwDataLen) {
649 BYTE *pbTemp;
650
651 switch (pCryptHash->aiAlgid)
652 {
653 case CALG_HMAC:
654 if (pCryptHash->pHMACInfo)
655 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
656 pbData, dwDataLen);
657 break;
658
659 case CALG_MAC:
660 pbTemp = HeapAlloc(GetProcessHeap(), 0, dwDataLen);
661 if (!pbTemp) return;
662 memcpy(pbTemp, pbData, dwDataLen);
663 RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, 0, FALSE, 0,
664 pbTemp, &dwDataLen, dwDataLen);
665 HeapFree(GetProcessHeap(), 0, pbTemp);
666 break;
667
668 default:
669 update_hash_impl(pCryptHash->aiAlgid, &pCryptHash->context, pbData, dwDataLen);
670 }
671}
672
673/******************************************************************************
674 * finalize_hash [Internal]
675 *
676 * Finalizes the hash, after all data has been hashed with update_hash.
677 * No additional data can be hashed afterwards until the hash gets initialized again.
678 *
679 * PARAMS
680 * pCryptHash [I] Hash object to be finalized.
681 */
682static inline void finalize_hash(CRYPTHASH *pCryptHash) {
683 DWORD dwDataLen;
684
685 switch (pCryptHash->aiAlgid)
686 {
687 case CALG_HMAC:
688 if (pCryptHash->pHMACInfo) {
689 BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
690
691 finalize_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
692 pCryptHash->abHashValue);
693 memcpy(abHashValue, pCryptHash->abHashValue, pCryptHash->dwHashSize);
694 init_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context);
695 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
696 pCryptHash->pHMACInfo->pbOuterString,
697 pCryptHash->pHMACInfo->cbOuterString);
698 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
699 abHashValue, pCryptHash->dwHashSize);
700 finalize_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
701 pCryptHash->abHashValue);
702 }
703 break;
704
705 case CALG_MAC:
706 dwDataLen = 0;
707 RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, 0, TRUE, 0,
708 pCryptHash->abHashValue, &dwDataLen, pCryptHash->dwHashSize);
709 break;
710
711 default:
712 finalize_hash_impl(pCryptHash->aiAlgid, &pCryptHash->context, pCryptHash->abHashValue);
713 }
714}
715
716/******************************************************************************
717 * destroy_key [Internal]
718 *
719 * Destructor for key objects
720 *
721 * PARAMS
722 * pCryptKey [I] Pointer to the key object to be destroyed.
723 * Will be invalid after function returns!
724 */
725static void destroy_key(OBJECTHDR *pObject)
726{
727 CRYPTKEY *pCryptKey = (CRYPTKEY*)pObject;
728
729 free_key_impl(pCryptKey->aiAlgid, &pCryptKey->context);
730 free_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom);
731 free_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom);
732 HeapFree(GetProcessHeap(), 0, pCryptKey);
733}
734
735/******************************************************************************
736 * setup_key [Internal]
737 *
738 * Initialize (or reset) a key object
739 *
740 * PARAMS
741 * pCryptKey [I] The key object to be initialized.
742 */
743static inline void setup_key(CRYPTKEY *pCryptKey) {
744 pCryptKey->dwState = RSAENH_KEYSTATE_IDLE;
745 memcpy(pCryptKey->abChainVector, pCryptKey->abInitVector, sizeof(pCryptKey->abChainVector));
746 setup_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen,
747 pCryptKey->dwEffectiveKeyLen, pCryptKey->dwSaltLen,
748 pCryptKey->abKeyValue);
749}
750
751/******************************************************************************
752 * new_key [Internal]
753 *
754 * Creates a new key object without assigning the actual binary key value.
755 * This is done by CPDeriveKey, CPGenKey or CPImportKey, which call this function.
756 *
757 * PARAMS
758 * hProv [I] Handle to the provider to which the created key will belong.
759 * aiAlgid [I] The new key shall use the crypto algorithm idenfied by aiAlgid.
760 * dwFlags [I] Upper 16 bits give the key length.
761 * Lower 16 bits: CRYPT_CREATE_SALT, CRYPT_NO_SALT
762 * ppCryptKey [O] Pointer to the created key
763 *
764 * RETURNS
765 * Success: Handle to the created key.
766 * Failure: INVALID_HANDLE_VALUE
767 */
768static HCRYPTKEY new_key(HCRYPTPROV hProv, ALG_ID aiAlgid, DWORD dwFlags, CRYPTKEY **ppCryptKey)
769{
770 HCRYPTKEY hCryptKey;
771 CRYPTKEY *pCryptKey;
772 DWORD dwKeyLen = HIWORD(dwFlags);
773 const PROV_ENUMALGS_EX *peaAlgidInfo;
774
775 *ppCryptKey = NULL;
776
777 /*
778 * Retrieve the CSP's capabilities for the given ALG_ID value
779 */
780 peaAlgidInfo = get_algid_info(hProv, aiAlgid);
781 if (!peaAlgidInfo) return (HCRYPTKEY)INVALID_HANDLE_VALUE;
782
783 /*
784 * Assume the default key length, if none is specified explicitly
785 */
786 if (dwKeyLen == 0) dwKeyLen = peaAlgidInfo->dwDefaultLen;
787
788 /*
789 * Check if the requested key length is supported by the current CSP.
790 * Adjust key length's for DES algorithms.
791 */
792 switch (aiAlgid) {
793 case CALG_DES:
794 if (dwKeyLen == RSAENH_DES_EFFECTIVE_KEYLEN) {
795 dwKeyLen = RSAENH_DES_STORAGE_KEYLEN;
796 }
797 if (dwKeyLen != RSAENH_DES_STORAGE_KEYLEN) {
798 SetLastError(NTE_BAD_FLAGS);
799 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
800 }
801 break;
802
803 case CALG_3DES_112:
804 if (dwKeyLen == RSAENH_3DES112_EFFECTIVE_KEYLEN) {
805 dwKeyLen = RSAENH_3DES112_STORAGE_KEYLEN;
806 }
807 if (dwKeyLen != RSAENH_3DES112_STORAGE_KEYLEN) {
808 SetLastError(NTE_BAD_FLAGS);
809 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
810 }
811 break;
812
813 case CALG_3DES:
814 if (dwKeyLen == RSAENH_3DES_EFFECTIVE_KEYLEN) {
815 dwKeyLen = RSAENH_3DES_STORAGE_KEYLEN;
816 }
817 if (dwKeyLen != RSAENH_3DES_STORAGE_KEYLEN) {
818 SetLastError(NTE_BAD_FLAGS);
819 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
820 }
821 break;
822
823 default:
824 if (dwKeyLen % 8 ||
825 dwKeyLen > peaAlgidInfo->dwMaxLen ||
826 dwKeyLen < peaAlgidInfo->dwMinLen)
827 {
828 SetLastError(NTE_BAD_FLAGS);
829 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
830 }
831 }
832
833 hCryptKey = new_object(&handle_table, sizeof(CRYPTKEY), RSAENH_MAGIC_KEY,
834 destroy_key, (OBJECTHDR**)&pCryptKey);
835 if (hCryptKey != (HCRYPTKEY)INVALID_HANDLE_VALUE)
836 {
837 pCryptKey->aiAlgid = aiAlgid;
838 pCryptKey->hProv = hProv;
839 pCryptKey->dwModeBits = 0;
840 pCryptKey->dwPermissions = CRYPT_ENCRYPT | CRYPT_DECRYPT | CRYPT_READ | CRYPT_WRITE |
841 CRYPT_MAC;
842 pCryptKey->dwKeyLen = dwKeyLen >> 3;
843 pCryptKey->dwEffectiveKeyLen = 0;
844 if ((dwFlags & CRYPT_CREATE_SALT) || (dwKeyLen == 40 && !(dwFlags & CRYPT_NO_SALT)))
845 pCryptKey->dwSaltLen = 16 /*FIXME*/ - pCryptKey->dwKeyLen;
846 else
847 pCryptKey->dwSaltLen = 0;
848 memset(pCryptKey->abKeyValue, 0, sizeof(pCryptKey->abKeyValue));
849 memset(pCryptKey->abInitVector, 0, sizeof(pCryptKey->abInitVector));
850 init_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom);
851 init_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom);
852
853 switch(aiAlgid)
854 {
855 case CALG_PCT1_MASTER:
856 case CALG_SSL2_MASTER:
857 case CALG_SSL3_MASTER:
858 case CALG_TLS1_MASTER:
859 case CALG_RC4:
860 pCryptKey->dwBlockLen = 0;
861 pCryptKey->dwMode = 0;
862 break;
863
864 case CALG_RC2:
865 case CALG_DES:
866 case CALG_3DES_112:
867 case CALG_3DES:
868 pCryptKey->dwBlockLen = 8;
869 pCryptKey->dwMode = CRYPT_MODE_CBC;
870 break;
871
872 case CALG_AES:
873 case CALG_AES_128:
874 case CALG_AES_192:
875 case CALG_AES_256:
876 pCryptKey->dwBlockLen = 16;
877 pCryptKey->dwMode = CRYPT_MODE_ECB;
878 break;
879
880 case CALG_RSA_KEYX:
881 case CALG_RSA_SIGN:
882 pCryptKey->dwBlockLen = dwKeyLen >> 3;
883 pCryptKey->dwMode = 0;
884 break;
885 }
886
887 *ppCryptKey = pCryptKey;
888 }
889
890 return hCryptKey;
891}
892
893/******************************************************************************
894 * store_key_pair [Internal]
895 *
896 * Stores a key pair to the registry
897 *
898 * PARAMS
899 * hCryptKey [I] Handle to the key to be stored
900 * hKey [I] Registry key where the key pair is to be stored
901 * szValueName [I] Registry value where key pair's value is to be stored
902 * dwFlags [I] Flags for protecting the key
903 */
904static void store_key_pair(HCRYPTKEY hCryptKey, HKEY hKey, LPCSTR szValueName, DWORD dwFlags)
905{
906 DATA_BLOB blobIn, blobOut;
907 CRYPTKEY *pKey;
908 DWORD dwLen;
909 BYTE *pbKey;
910
911 if (lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY,
912 (OBJECTHDR**)&pKey))
913 {
914 if (RSAENH_CPExportKey(pKey->hProv, hCryptKey, 0, PRIVATEKEYBLOB, 0, 0,
915 &dwLen))
916 {
917 pbKey = HeapAlloc(GetProcessHeap(), 0, dwLen);
918 if (pbKey)
919 {
920 if (RSAENH_CPExportKey(pKey->hProv, hCryptKey, 0,
921 PRIVATEKEYBLOB, 0, pbKey, &dwLen))
922 {
923 blobIn.pbData = pbKey;
924 blobIn.cbData = dwLen;
925
926 if (CryptProtectData(&blobIn, NULL, NULL, NULL, NULL,
927 dwFlags, &blobOut))
928 {
929 RegSetValueExA(hKey, szValueName, 0, REG_BINARY,
930 blobOut.pbData, blobOut.cbData);
931 LocalFree(blobOut.pbData);
932 }
933 }
934 HeapFree(GetProcessHeap(), 0, pbKey);
935 }
936 }
937 release_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY);
938 }
939}
940
941/******************************************************************************
942 * create_container_key [Internal]
943 *
944 * Creates the registry key for a key container's persistent storage.
945 *
946 * PARAMS
947 * pKeyContainer [I] Pointer to the key container
948 * sam [I] Desired registry access
949 * phKey [O] Returned key
950 */
951static BOOL create_container_key(KEYCONTAINER *pKeyContainer, REGSAM sam, HKEY *phKey)
952{
953 CHAR szRSABase[MAX_PATH];
954 HKEY hRootKey;
955
956 sprintf(szRSABase, RSAENH_REGKEY, pKeyContainer->szName);
957
958 if (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET)
959 hRootKey = HKEY_LOCAL_MACHINE;
960 else
961 hRootKey = HKEY_CURRENT_USER;
962
963 /* @@ Wine registry key: HKLM\Software\Wine\Crypto\RSA */
964 /* @@ Wine registry key: HKCU\Software\Wine\Crypto\RSA */
965 return RegCreateKeyExA(hRootKey, szRSABase, 0, NULL,
966 REG_OPTION_NON_VOLATILE, sam, NULL, phKey, NULL)
967 == ERROR_SUCCESS;
968}
969
970/******************************************************************************
971 * open_container_key [Internal]
972 *
973 * Opens a key container's persistent storage for reading.
974 *
975 * PARAMS
976 * pszContainerName [I] Name of the container to be opened. May be the empty
977 * string if the parent key of all containers is to be
978 * opened.
979 * dwFlags [I] Flags indicating which keyset to be opened.
980 * phKey [O] Returned key
981 */
982static BOOL open_container_key(LPCSTR pszContainerName, DWORD dwFlags, HKEY *phKey)
983{
984 CHAR szRSABase[MAX_PATH];
985 HKEY hRootKey;
986
987 sprintf(szRSABase, RSAENH_REGKEY, pszContainerName);
988
989 if (dwFlags & CRYPT_MACHINE_KEYSET)
990 hRootKey = HKEY_LOCAL_MACHINE;
991 else
992 hRootKey = HKEY_CURRENT_USER;
993
994 /* @@ Wine registry key: HKLM\Software\Wine\Crypto\RSA */
995 /* @@ Wine registry key: HKCU\Software\Wine\Crypto\RSA */
996 return RegOpenKeyExA(hRootKey, szRSABase, 0, KEY_READ, phKey) ==
997 ERROR_SUCCESS;
998}
999
1000/******************************************************************************
1001 * delete_container_key [Internal]
1002 *
1003 * Deletes a key container's persistent storage.
1004 *
1005 * PARAMS
1006 * pszContainerName [I] Name of the container to be opened.
1007 * dwFlags [I] Flags indicating which keyset to be opened.
1008 */
1009static BOOL delete_container_key(LPCSTR pszContainerName, DWORD dwFlags)
1010{
1011 CHAR szRegKey[MAX_PATH];
1012
1013 if (snprintf(szRegKey, MAX_PATH, RSAENH_REGKEY, pszContainerName) >= MAX_PATH) {
1014 SetLastError(NTE_BAD_KEYSET_PARAM);
1015 return FALSE;
1016 } else {
1017 HKEY hRootKey;
1018 if (dwFlags & CRYPT_MACHINE_KEYSET)
1019 hRootKey = HKEY_LOCAL_MACHINE;
1020 else
1021 hRootKey = HKEY_CURRENT_USER;
1022 if (!RegDeleteKeyA(hRootKey, szRegKey)) {
1023 SetLastError(ERROR_SUCCESS);
1024 return TRUE;
1025 } else {
1026 SetLastError(NTE_BAD_KEYSET);
1027 return FALSE;
1028 }
1029 }
1030}
1031
1032/******************************************************************************
1033 * store_key_container_keys [Internal]
1034 *
1035 * Stores key container's keys in a persistent location.
1036 *
1037 * PARAMS
1038 * pKeyContainer [I] Pointer to the key container whose keys are to be saved
1039 */
1040static void store_key_container_keys(KEYCONTAINER *pKeyContainer)
1041{
1042 HKEY hKey;
1043 DWORD dwFlags;
1044
1045 /* On WinXP, persistent keys are stored in a file located at:
1046 * $AppData$\\Microsoft\\Crypto\\RSA\\$SID$\\some_hex_string
1047 */
1048
1049 if (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET)
1050 dwFlags = CRYPTPROTECT_LOCAL_MACHINE;
1051 else
1052 dwFlags = 0;
1053
1054 if (create_container_key(pKeyContainer, KEY_WRITE, &hKey))
1055 {
1056 store_key_pair(pKeyContainer->hKeyExchangeKeyPair, hKey,
1057 "KeyExchangeKeyPair", dwFlags);
1058 store_key_pair(pKeyContainer->hSignatureKeyPair, hKey,
1059 "SignatureKeyPair", dwFlags);
1060 RegCloseKey(hKey);
1061 }
1062}
1063
1064/******************************************************************************
1065 * destroy_key_container [Internal]
1066 *
1067 * Destructor for key containers.
1068 *
1069 * PARAMS
1070 * pObjectHdr [I] Pointer to the key container to be destroyed.
1071 */
1072static void destroy_key_container(OBJECTHDR *pObjectHdr)
1073{
1074 KEYCONTAINER *pKeyContainer = (KEYCONTAINER*)pObjectHdr;
1075
1076 if (!(pKeyContainer->dwFlags & CRYPT_VERIFYCONTEXT))
1077 store_key_container_keys(pKeyContainer);
1078 HeapFree( GetProcessHeap(), 0, pKeyContainer );
1079}
1080
1081/******************************************************************************
1082 * new_key_container [Internal]
1083 *
1084 * Create a new key container. The personality (RSA Base, Strong or Enhanced CP)
1085 * of the CSP is determined via the pVTable->pszProvName string.
1086 *
1087 * PARAMS
1088 * pszContainerName [I] Name of the key container.
1089 * pVTable [I] Callback functions and context info provided by the OS
1090 *
1091 * RETURNS
1092 * Success: Handle to the new key container.
1093 * Failure: INVALID_HANDLE_VALUE
1094 */
1095static HCRYPTPROV new_key_container(PCCH pszContainerName, DWORD dwFlags, const VTableProvStruc *pVTable)
1096{
1097 KEYCONTAINER *pKeyContainer;
1098 HCRYPTPROV hKeyContainer;
1099
1100 hKeyContainer = new_object(&handle_table, sizeof(KEYCONTAINER), RSAENH_MAGIC_CONTAINER,
1101 destroy_key_container, (OBJECTHDR**)&pKeyContainer);
1102 if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE)
1103 {
1104 lstrcpynA(pKeyContainer->szName, pszContainerName, MAX_PATH);
1105 pKeyContainer->dwFlags = dwFlags;
1106 pKeyContainer->dwEnumAlgsCtr = 0;
1107 pKeyContainer->hKeyExchangeKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE;
1108 pKeyContainer->hSignatureKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE;
1109 if (pVTable && pVTable->pszProvName) {
1110 lstrcpynA(pKeyContainer->szProvName, pVTable->pszProvName, MAX_PATH);
1111 if (!strcmp(pVTable->pszProvName, MS_DEF_PROV_A)) {
1112 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_BASE;
1113 } else if (!strcmp(pVTable->pszProvName, MS_ENHANCED_PROV_A)) {
1114 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_ENHANCED;
1115 } else if (!strcmp(pVTable->pszProvName, MS_DEF_RSA_SCHANNEL_PROV_A)) {
1116 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_SCHANNEL;
1117 } else if (!strcmp(pVTable->pszProvName, MS_ENH_RSA_AES_PROV_A)) {
1118 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_AES;
1119 } else {
1120 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_STRONG;
1121 }
1122 }
1123
1124 /* The new key container has to be inserted into the CSP immediately
1125 * after creation to be available for CPGetProvParam's PP_ENUMCONTAINERS. */
1126 if (!(dwFlags & CRYPT_VERIFYCONTEXT)) {
1127 HKEY hKey;
1128
1129 if (create_container_key(pKeyContainer, KEY_WRITE, &hKey))
1130 RegCloseKey(hKey);
1131 }
1132 }
1133
1134 return hKeyContainer;
1135}
1136
1137/******************************************************************************
1138 * read_key_value [Internal]
1139 *
1140 * Reads a key pair value from the registry
1141 *
1142 * PARAMS
1143 * hKeyContainer [I] Crypt provider to use to import the key
1144 * hKey [I] Registry key from which to read the key pair
1145 * szValueName [I] Registry value from which to read the key pair's value
1146 * dwFlags [I] Flags for unprotecting the key
1147 * phCryptKey [O] Returned key
1148 */
1149static BOOL read_key_value(HCRYPTPROV hKeyContainer, HKEY hKey, LPCSTR szValueName, DWORD dwFlags, HCRYPTKEY *phCryptKey)
1150{
1151 DWORD dwValueType, dwLen;
1152 BYTE *pbKey;
1153 DATA_BLOB blobIn, blobOut;
1154 BOOL ret = FALSE;
1155
1156 if (RegQueryValueExA(hKey, szValueName, 0, &dwValueType, NULL, &dwLen) ==
1157 ERROR_SUCCESS)
1158 {
1159 pbKey = HeapAlloc(GetProcessHeap(), 0, dwLen);
1160 if (pbKey)
1161 {
1162 if (RegQueryValueExA(hKey, szValueName, 0, &dwValueType, pbKey, &dwLen) ==
1163 ERROR_SUCCESS)
1164 {
1165 blobIn.pbData = pbKey;
1166 blobIn.cbData = dwLen;
1167
1168 if (CryptUnprotectData(&blobIn, NULL, NULL, NULL, NULL,
1169 dwFlags, &blobOut))
1170 {
1171 ret = RSAENH_CPImportKey(hKeyContainer, blobOut.pbData, blobOut.cbData, 0, 0,
1172 phCryptKey);
1173 LocalFree(blobOut.pbData);
1174 }
1175 }
1176 HeapFree(GetProcessHeap(), 0, pbKey);
1177 }
1178 }
1179 return ret;
1180}
1181
1182/******************************************************************************
1183 * read_key_container [Internal]
1184 *
1185 * Tries to read the persistent state of the key container (mainly the signature
1186 * and key exchange private keys) given by pszContainerName.
1187 *
1188 * PARAMS
1189 * pszContainerName [I] Name of the key container to read from the registry
1190 * pVTable [I] Pointer to context data provided by the operating system
1191 *
1192 * RETURNS
1193 * Success: Handle to the key container read from the registry
1194 * Failure: INVALID_HANDLE_VALUE
1195 */
1196static HCRYPTPROV read_key_container(PCHAR pszContainerName, DWORD dwFlags, const VTableProvStruc *pVTable)
1197{
1198 HKEY hKey;
1199 KEYCONTAINER *pKeyContainer;
1200 HCRYPTPROV hKeyContainer;
1201 HCRYPTKEY hCryptKey;
1202
1203 if (!open_container_key(pszContainerName, dwFlags, &hKey))
1204 {
1205 SetLastError(NTE_BAD_KEYSET);
1206 return (HCRYPTPROV)INVALID_HANDLE_VALUE;
1207 }
1208
1209 hKeyContainer = new_key_container(pszContainerName, dwFlags, pVTable);
1210 if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE)
1211 {
1212 DWORD dwProtectFlags = (dwFlags & CRYPT_MACHINE_KEYSET) ?
1213 CRYPTPROTECT_LOCAL_MACHINE : 0;
1214
1215 if (!lookup_handle(&handle_table, hKeyContainer, RSAENH_MAGIC_CONTAINER,
1216 (OBJECTHDR**)&pKeyContainer))
1217 return (HCRYPTPROV)INVALID_HANDLE_VALUE;
1218
1219 if (read_key_value(hKeyContainer, hKey, "KeyExchangeKeyPair",
1220 dwProtectFlags, &hCryptKey))
1221 pKeyContainer->hKeyExchangeKeyPair = hCryptKey;
1222 if (read_key_value(hKeyContainer, hKey, "SignatureKeyPair",
1223 dwProtectFlags, &hCryptKey))
1224 pKeyContainer->hSignatureKeyPair = hCryptKey;
1225 }
1226
1227 return hKeyContainer;
1228}
1229
1230/******************************************************************************
1231 * build_hash_signature [Internal]
1232 *
1233 * Builds a padded version of a hash to match the length of the RSA key modulus.
1234 *
1235 * PARAMS
1236 * pbSignature [O] The padded hash object is stored here.
1237 * dwLen [I] Length of the pbSignature buffer.
1238 * aiAlgid [I] Algorithm identifier of the hash to be padded.
1239 * abHashValue [I] The value of the hash object.
1240 * dwHashLen [I] Length of the hash value.
1241 * dwFlags [I] Selection of padding algorithm.
1242 *
1243 * RETURNS
1244 * Success: TRUE
1245 * Failure: FALSE (NTE_BAD_ALGID)
1246 */
1247static BOOL build_hash_signature(BYTE *pbSignature, DWORD dwLen, ALG_ID aiAlgid,
1248 CONST BYTE *abHashValue, DWORD dwHashLen, DWORD dwFlags)
1249{
1250 /* These prefixes are meant to be concatenated with hash values of the
1251 * respective kind to form a PKCS #7 DigestInfo. */
1252 static const struct tagOIDDescriptor {
1253 ALG_ID aiAlgid;
1254 DWORD dwLen;
1255 CONST BYTE abOID[18];
1256 } aOIDDescriptor[5] = {
1257 { CALG_MD2, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
1258 0x86, 0xf7, 0x0d, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10 } },
1259 { CALG_MD4, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
1260 0x86, 0xf7, 0x0d, 0x02, 0x04, 0x05, 0x00, 0x04, 0x10 } },
1261 { CALG_MD5, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
1262 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 } },
1263 { CALG_SHA, 15, { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
1264 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 } },
1265 { 0, 0, { 0 } }
1266 };
1267 DWORD dwIdxOID, i, j;
1268
1269 for (dwIdxOID = 0; aOIDDescriptor[dwIdxOID].aiAlgid; dwIdxOID++) {
1270 if (aOIDDescriptor[dwIdxOID].aiAlgid == aiAlgid) break;
1271 }
1272
1273 if (!aOIDDescriptor[dwIdxOID].aiAlgid) {
1274 SetLastError(NTE_BAD_ALGID);
1275 return FALSE;
1276 }
1277
1278 /* Build the padded signature */
1279 if (dwFlags & CRYPT_X931_FORMAT) {
1280 pbSignature[0] = 0x6b;
1281 for (i=1; i < dwLen - dwHashLen - 3; i++) {
1282 pbSignature[i] = 0xbb;
1283 }
1284 pbSignature[i++] = 0xba;
1285 for (j=0; j < dwHashLen; j++, i++) {
1286 pbSignature[i] = abHashValue[j];
1287 }
1288 pbSignature[i++] = 0x33;
1289 pbSignature[i++] = 0xcc;
1290 } else {
1291 pbSignature[0] = 0x00;
1292 pbSignature[1] = 0x01;
1293 if (dwFlags & CRYPT_NOHASHOID) {
1294 for (i=2; i < dwLen - 1 - dwHashLen; i++) {
1295 pbSignature[i] = 0xff;
1296 }
1297 pbSignature[i++] = 0x00;
1298 } else {
1299 for (i=2; i < dwLen - 1 - aOIDDescriptor[dwIdxOID].dwLen - dwHashLen; i++) {
1300 pbSignature[i] = 0xff;
1301 }
1302 pbSignature[i++] = 0x00;
1303 for (j=0; j < aOIDDescriptor[dwIdxOID].dwLen; j++) {
1304 pbSignature[i++] = aOIDDescriptor[dwIdxOID].abOID[j];
1305 }
1306 }
1307 for (j=0; j < dwHashLen; j++) {
1308 pbSignature[i++] = abHashValue[j];
1309 }
1310 }
1311
1312 return TRUE;
1313}
1314
1315/******************************************************************************
1316 * tls1_p [Internal]
1317 *
1318 * This is an implementation of the 'P_hash' helper function for TLS1's PRF.
1319 * It is used exclusively by tls1_prf. For details see RFC 2246, chapter 5.
1320 * The pseudo random stream generated by this function is exclusive or'ed with
1321 * the data in pbBuffer.
1322 *
1323 * PARAMS
1324 * hHMAC [I] HMAC object, which will be used in pseudo random generation
1325 * pblobSeed [I] Seed value
1326 * pbBuffer [I/O] Pseudo random stream will be xor'ed to the provided data
1327 * dwBufferLen [I] Number of pseudo random bytes desired
1328 *
1329 * RETURNS
1330 * Success: TRUE
1331 * Failure: FALSE
1332 */
1333static BOOL tls1_p(HCRYPTHASH hHMAC, CONST PCRYPT_DATA_BLOB pblobSeed, PBYTE pbBuffer, DWORD dwBufferLen)
1334{
1335 CRYPTHASH *pHMAC;
1336 BYTE abAi[RSAENH_MAX_HASH_SIZE];
1337 DWORD i = 0;
1338
1339 if (!lookup_handle(&handle_table, hHMAC, RSAENH_MAGIC_HASH, (OBJECTHDR**)&pHMAC)) {
1340 SetLastError(NTE_BAD_HASH);
1341 return FALSE;
1342 }
1343
1344 /* compute A_1 = HMAC(seed) */
1345 init_hash(pHMAC);
1346 update_hash(pHMAC, pblobSeed->pbData, pblobSeed->cbData);
1347 finalize_hash(pHMAC);
1348 memcpy(abAi, pHMAC->abHashValue, pHMAC->dwHashSize);
1349
1350 do {
1351 /* compute HMAC(A_i + seed) */
1352 init_hash(pHMAC);
1353 update_hash(pHMAC, abAi, pHMAC->dwHashSize);
1354 update_hash(pHMAC, pblobSeed->pbData, pblobSeed->cbData);
1355 finalize_hash(pHMAC);
1356
1357 /* pseudo random stream := CONCAT_{i=1..n} ( HMAC(A_i + seed) ) */
1358 do {
1359 if (i >= dwBufferLen) break;
1360 pbBuffer[i] ^= pHMAC->abHashValue[i % pHMAC->dwHashSize];
1361 i++;
1362 } while (i % pHMAC->dwHashSize);
1363
1364 /* compute A_{i+1} = HMAC(A_i) */
1365 init_hash(pHMAC);
1366 update_hash(pHMAC, abAi, pHMAC->dwHashSize);
1367 finalize_hash(pHMAC);
1368 memcpy(abAi, pHMAC->abHashValue, pHMAC->dwHashSize);
1369 } while (i < dwBufferLen);
1370
1371 return TRUE;
1372}
1373
1374/******************************************************************************
1375 * tls1_prf [Internal]
1376 *
1377 * TLS1 pseudo random function as specified in RFC 2246, chapter 5
1378 *
1379 * PARAMS
1380 * hProv [I] Key container used to compute the pseudo random stream
1381 * hSecret [I] Key that holds the (pre-)master secret
1382 * pblobLabel [I] Descriptive label
1383 * pblobSeed [I] Seed value
1384 * pbBuffer [O] Pseudo random numbers will be stored here
1385 * dwBufferLen [I] Number of pseudo random bytes desired
1386 *
1387 * RETURNS
1388 * Success: TRUE
1389 * Failure: FALSE
1390 */
1391static BOOL tls1_prf(HCRYPTPROV hProv, HCRYPTPROV hSecret, CONST PCRYPT_DATA_BLOB pblobLabel,
1392 CONST PCRYPT_DATA_BLOB pblobSeed, PBYTE pbBuffer, DWORD dwBufferLen)
1393{
1394 HMAC_INFO hmacInfo = { 0, NULL, 0, NULL, 0 };
1395 HCRYPTHASH hHMAC = (HCRYPTHASH)INVALID_HANDLE_VALUE;
1396 HCRYPTKEY hHalfSecret = (HCRYPTKEY)INVALID_HANDLE_VALUE;
1397 CRYPTKEY *pHalfSecret, *pSecret;
1398 DWORD dwHalfSecretLen;
1399 BOOL result = FALSE;
1400 CRYPT_DATA_BLOB blobLabelSeed;
1401
1402 TRACE("(hProv=%08lx, hSecret=%08lx, pblobLabel=%p, pblobSeed=%p, pbBuffer=%p, dwBufferLen=%d)\n",
1403 hProv, hSecret, pblobLabel, pblobSeed, pbBuffer, dwBufferLen);
1404
1405 if (!lookup_handle(&handle_table, hSecret, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pSecret)) {
1406 SetLastError(NTE_FAIL);
1407 return FALSE;
1408 }
1409
1410 dwHalfSecretLen = (pSecret->dwKeyLen+1)/2;
1411
1412 /* concatenation of the label and the seed */
1413 if (!concat_data_blobs(&blobLabelSeed, pblobLabel, pblobSeed)) goto exit;
1414
1415 /* zero out the buffer, since two random streams will be xor'ed into it. */
1416 memset(pbBuffer, 0, dwBufferLen);
1417
1418 /* build a 'fake' key, to hold the secret. CALG_SSL2_MASTER is used since it provides
1419 * the biggest range of valid key lengths. */
1420 hHalfSecret = new_key(hProv, CALG_SSL2_MASTER, MAKELONG(0,dwHalfSecretLen*8), &pHalfSecret);
1421 if (hHalfSecret == (HCRYPTKEY)INVALID_HANDLE_VALUE) goto exit;
1422
1423 /* Derive an HMAC_MD5 hash and call the helper function. */
1424 memcpy(pHalfSecret->abKeyValue, pSecret->abKeyValue, dwHalfSecretLen);
1425 if (!RSAENH_CPCreateHash(hProv, CALG_HMAC, hHalfSecret, 0, &hHMAC)) goto exit;
1426 hmacInfo.HashAlgid = CALG_MD5;
1427 if (!RSAENH_CPSetHashParam(hProv, hHMAC, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0)) goto exit;
1428 if (!tls1_p(hHMAC, &blobLabelSeed, pbBuffer, dwBufferLen)) goto exit;
1429
1430 /* Reconfigure to HMAC_SHA hash and call helper function again. */
1431 memcpy(pHalfSecret->abKeyValue, pSecret->abKeyValue + (pSecret->dwKeyLen/2), dwHalfSecretLen);
1432 hmacInfo.HashAlgid = CALG_SHA;
1433 if (!RSAENH_CPSetHashParam(hProv, hHMAC, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0)) goto exit;
1434 if (!tls1_p(hHMAC, &blobLabelSeed, pbBuffer, dwBufferLen)) goto exit;
1435
1436 result = TRUE;
1437exit:
1438 release_handle(&handle_table, hHalfSecret, RSAENH_MAGIC_KEY);
1439 if (hHMAC != (HCRYPTHASH)INVALID_HANDLE_VALUE) RSAENH_CPDestroyHash(hProv, hHMAC);
1440 free_data_blob(&blobLabelSeed);
1441 return result;
1442}
1443
1444/******************************************************************************
1445 * pad_data [Internal]
1446 *
1447 * Helper function for data padding according to PKCS1 #2
1448 *
1449 * PARAMS
1450 * abData [I] The data to be padded
1451 * dwDataLen [I] Length of the data
1452 * abBuffer [O] Padded data will be stored here
1453 * dwBufferLen [I] Length of the buffer (also length of padded data)
1454 * dwFlags [I] Padding format (CRYPT_SSL2_FALLBACK)
1455 *
1456 * RETURN
1457 * Success: TRUE
1458 * Failure: FALSE (NTE_BAD_LEN, too much data to pad)
1459 */
1460static BOOL pad_data(CONST BYTE *abData, DWORD dwDataLen, BYTE *abBuffer, DWORD dwBufferLen,
1461 DWORD dwFlags)
1462{
1463 DWORD i;
1464
1465 /* Ensure there is enough space for PKCS1 #2 padding */
1466 if (dwDataLen > dwBufferLen-11) {
1467 SetLastError(NTE_BAD_LEN);
1468 return FALSE;
1469 }
1470
1471 memmove(abBuffer + dwBufferLen - dwDataLen, abData, dwDataLen);
1472
1473 abBuffer[0] = 0x00;
1474 abBuffer[1] = RSAENH_PKC_BLOCKTYPE;
1475 for (i=2; i < dwBufferLen - dwDataLen - 1; i++)
1476 do gen_rand_impl(&abBuffer[i], 1); while (!abBuffer[i]);
1477 if (dwFlags & CRYPT_SSL2_FALLBACK)
1478 for (i-=8; i < dwBufferLen - dwDataLen - 1; i++)
1479 abBuffer[i] = 0x03;
1480 abBuffer[i] = 0x00;
1481
1482 return TRUE;
1483}
1484
1485/******************************************************************************
1486 * unpad_data [Internal]
1487 *
1488 * Remove the PKCS1 padding from RSA decrypted data
1489 *
1490 * PARAMS
1491 * abData [I] The padded data
1492 * dwDataLen [I] Length of the padded data
1493 * abBuffer [O] Data without padding will be stored here
1494 * dwBufferLen [I/O] I: Length of the buffer, O: Length of unpadded data
1495 * dwFlags [I] Currently none defined
1496 *
1497 * RETURNS
1498 * Success: TRUE
1499 * Failure: FALSE, (NTE_BAD_DATA, no valid PKCS1 padding or buffer too small)
1500 */
1501static BOOL unpad_data(CONST BYTE *abData, DWORD dwDataLen, BYTE *abBuffer, DWORD *dwBufferLen,
1502 DWORD dwFlags)
1503{
1504 DWORD i;
1505
1506 for (i=2; i<dwDataLen; i++)
1507 if (!abData[i])
1508 break;
1509
1510 if ((i == dwDataLen) || (*dwBufferLen < dwDataLen - i - 1) ||
1511 (abData[0] != 0x00) || (abData[1] != RSAENH_PKC_BLOCKTYPE))
1512 {
1513 SetLastError(NTE_BAD_DATA);
1514 return FALSE;
1515 }
1516
1517 *dwBufferLen = dwDataLen - i - 1;
1518 memmove(abBuffer, abData + i + 1, *dwBufferLen);
1519 return TRUE;
1520}
1521
1522/******************************************************************************
1523 * CPAcquireContext (RSAENH.@)
1524 *
1525 * Acquire a handle to the key container specified by pszContainer
1526 *
1527 * PARAMS
1528 * phProv [O] Pointer to the location the acquired handle will be written to.
1529 * pszContainer [I] Name of the desired key container. See Notes
1530 * dwFlags [I] Flags. See Notes.
1531 * pVTable [I] Pointer to a PVTableProvStruct containing callbacks.
1532 *
1533 * RETURNS
1534 * Success: TRUE
1535 * Failure: FALSE
1536 *
1537 * NOTES
1538 * If pszContainer is NULL or points to a zero length string the user's login
1539 * name will be used as the key container name.
1540 *
1541 * If the CRYPT_NEW_KEYSET flag is set in dwFlags a new keyset will be created.
1542 * If a keyset with the given name already exists, the function fails and sets
1543 * last error to NTE_EXISTS. If CRYPT_NEW_KEYSET is not set and the specified
1544 * key container does not exist, function fails and sets last error to
1545 * NTE_BAD_KEYSET.
1546 */
1547BOOL WINAPI RSAENH_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer,
1548 DWORD dwFlags, PVTableProvStruc pVTable)
1549{
1550 CHAR szKeyContainerName[MAX_PATH];
1551
1552 TRACE("(phProv=%p, pszContainer=%s, dwFlags=%08x, pVTable=%p)\n", phProv,
1553 debugstr_a(pszContainer), dwFlags, pVTable);
1554
1555 if (pszContainer && *pszContainer)
1556 {
1557 lstrcpynA(szKeyContainerName, pszContainer, MAX_PATH);
1558 }
1559 else
1560 {
1561 DWORD dwLen = sizeof(szKeyContainerName);
1562 if (!GetUserNameA(szKeyContainerName, &dwLen)) return FALSE;
1563 }
1564
1565 switch (dwFlags & (CRYPT_NEWKEYSET|CRYPT_VERIFYCONTEXT|CRYPT_DELETEKEYSET))
1566 {
1567 case 0:
1568 *phProv = read_key_container(szKeyContainerName, dwFlags, pVTable);
1569 break;
1570
1571 case CRYPT_DELETEKEYSET:
1572 return delete_container_key(szKeyContainerName, dwFlags);
1573
1574 case CRYPT_NEWKEYSET:
1575 *phProv = read_key_container(szKeyContainerName, dwFlags, pVTable);
1576 if (*phProv != (HCRYPTPROV)INVALID_HANDLE_VALUE)
1577 {
1578 release_handle(&handle_table, *phProv, RSAENH_MAGIC_CONTAINER);
1579 TRACE("Can't create new keyset, already exists\n");
1580 SetLastError(NTE_EXISTS);
1581 return FALSE;
1582 }
1583 *phProv = new_key_container(szKeyContainerName, dwFlags, pVTable);
1584 break;
1585
1586 case CRYPT_VERIFYCONTEXT|CRYPT_NEWKEYSET:
1587 case CRYPT_VERIFYCONTEXT:
1588 if (pszContainer && *pszContainer) {
1589 TRACE("pszContainer should be empty\n");
1590 SetLastError(NTE_BAD_FLAGS);
1591 return FALSE;
1592 }
1593 *phProv = new_key_container("", dwFlags, pVTable);
1594 break;
1595
1596 default:
1597 *phProv = (HCRYPTPROV)INVALID_HANDLE_VALUE;
1598 SetLastError(NTE_BAD_FLAGS);
1599 return FALSE;
1600 }
1601
1602 if (*phProv != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
1603 SetLastError(ERROR_SUCCESS);
1604 return TRUE;
1605 } else {
1606 return FALSE;
1607 }
1608}
1609
1610/******************************************************************************
1611 * CPCreateHash (RSAENH.@)
1612 *
1613 * CPCreateHash creates and initalizes a new hash object.
1614 *
1615 * PARAMS
1616 * hProv [I] Handle to the key container to which the new hash will belong.
1617 * Algid [I] Identifies the hash algorithm, which will be used for the hash.
1618 * hKey [I] Handle to a session key applied for keyed hashes.
1619 * dwFlags [I] Currently no flags defined. Must be zero.
1620 * phHash [O] Points to the location where a handle to the new hash will be stored.
1621 *
1622 * RETURNS
1623 * Success: TRUE
1624 * Failure: FALSE
1625 *
1626 * NOTES
1627 * hKey is a handle to a session key applied in keyed hashes like MAC and HMAC.
1628 * If a normal hash object is to be created (like e.g. MD2 or SHA1) hKey must be zero.
1629 */
1630BOOL WINAPI RSAENH_CPCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags,
1631 HCRYPTHASH *phHash)
1632{
1633 CRYPTKEY *pCryptKey;
1634 CRYPTHASH *pCryptHash;
1635 const PROV_ENUMALGS_EX *peaAlgidInfo;
1636
1637 TRACE("(hProv=%08lx, Algid=%08x, hKey=%08lx, dwFlags=%08x, phHash=%p)\n", hProv, Algid, hKey,
1638 dwFlags, phHash);
1639
1640 peaAlgidInfo = get_algid_info(hProv, Algid);
1641 if (!peaAlgidInfo) return FALSE;
1642
1643 if (dwFlags)
1644 {
1645 SetLastError(NTE_BAD_FLAGS);
1646 return FALSE;
1647 }
1648
1649 if (Algid == CALG_MAC || Algid == CALG_HMAC || Algid == CALG_SCHANNEL_MASTER_HASH ||
1650 Algid == CALG_TLS1PRF)
1651 {
1652 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey)) {
1653 SetLastError(NTE_BAD_KEY);
1654 return FALSE;
1655 }
1656
1657 if ((Algid == CALG_MAC) && (GET_ALG_TYPE(pCryptKey->aiAlgid) != ALG_TYPE_BLOCK)) {
1658 SetLastError(NTE_BAD_KEY);
1659 return FALSE;
1660 }
1661
1662 if ((Algid == CALG_SCHANNEL_MASTER_HASH || Algid == CALG_TLS1PRF) &&
1663 (pCryptKey->aiAlgid != CALG_TLS1_MASTER))
1664 {
1665 SetLastError(NTE_BAD_KEY);
1666 return FALSE;
1667 }
1668
1669 if ((Algid == CALG_TLS1PRF) && (pCryptKey->dwState != RSAENH_KEYSTATE_MASTERKEY)) {
1670 SetLastError(NTE_BAD_KEY_STATE);
1671 return FALSE;
1672 }
1673 }
1674
1675 *phHash = new_object(&handle_table, sizeof(CRYPTHASH), RSAENH_MAGIC_HASH,
1676 destroy_hash, (OBJECTHDR**)&pCryptHash);
1677 if (!pCryptHash) return FALSE;
1678
1679 pCryptHash->aiAlgid = Algid;
1680 pCryptHash->hKey = hKey;
1681 pCryptHash->hProv = hProv;
1682 pCryptHash->dwState = RSAENH_HASHSTATE_HASHING;
1683 pCryptHash->pHMACInfo = NULL;
1684 pCryptHash->dwHashSize = peaAlgidInfo->dwDefaultLen >> 3;
1685 init_data_blob(&pCryptHash->tpPRFParams.blobLabel);
1686 init_data_blob(&pCryptHash->tpPRFParams.blobSeed);
1687
1688 if (Algid == CALG_SCHANNEL_MASTER_HASH) {
1689 static const char keyex[] = "key expansion";
1690 BYTE key_expansion[sizeof keyex];
1691 CRYPT_DATA_BLOB blobRandom, blobKeyExpansion = { 13, key_expansion };
1692
1693 memcpy( key_expansion, keyex, sizeof keyex );
1694
1695 if (pCryptKey->dwState != RSAENH_KEYSTATE_MASTERKEY) {
1696 static const char msec[] = "master secret";
1697 BYTE master_secret[sizeof msec];
1698 CRYPT_DATA_BLOB blobLabel = { 13, master_secret };
1699 BYTE abKeyValue[48];
1700
1701 memcpy( master_secret, msec, sizeof msec );
1702
1703 /* See RFC 2246, chapter 8.1 */
1704 if (!concat_data_blobs(&blobRandom,
1705 &pCryptKey->siSChannelInfo.blobClientRandom,
1706 &pCryptKey->siSChannelInfo.blobServerRandom))
1707 {
1708 return FALSE;
1709 }
1710 tls1_prf(hProv, hKey, &blobLabel, &blobRandom, abKeyValue, 48);
1711 pCryptKey->dwState = RSAENH_KEYSTATE_MASTERKEY;
1712 memcpy(pCryptKey->abKeyValue, abKeyValue, 48);
1713 free_data_blob(&blobRandom);
1714 }
1715
1716 /* See RFC 2246, chapter 6.3 */
1717 if (!concat_data_blobs(&blobRandom,
1718 &pCryptKey->siSChannelInfo.blobServerRandom,
1719 &pCryptKey->siSChannelInfo.blobClientRandom))
1720 {
1721 return FALSE;
1722 }
1723 tls1_prf(hProv, hKey, &blobKeyExpansion, &blobRandom, pCryptHash->abHashValue,
1724 RSAENH_MAX_HASH_SIZE);
1725 free_data_blob(&blobRandom);
1726 }
1727
1728 return init_hash(pCryptHash);
1729}
1730
1731/******************************************************************************
1732 * CPDestroyHash (RSAENH.@)
1733 *
1734 * Releases the handle to a hash object. The object is destroyed if it's reference
1735 * count reaches zero.
1736 *
1737 * PARAMS
1738 * hProv [I] Handle to the key container to which the hash object belongs.
1739 * hHash [I] Handle to the hash object to be released.
1740 *
1741 * RETURNS
1742 * Success: TRUE
1743 * Failure: FALSE
1744 */
1745BOOL WINAPI RSAENH_CPDestroyHash(HCRYPTPROV hProv, HCRYPTHASH hHash)
1746{
1747 TRACE("(hProv=%08lx, hHash=%08lx)\n", hProv, hHash);
1748
1749 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
1750 {
1751 SetLastError(NTE_BAD_UID);
1752 return FALSE;
1753 }
1754
1755 if (!release_handle(&handle_table, hHash, RSAENH_MAGIC_HASH))
1756 {
1757 SetLastError(NTE_BAD_HASH);
1758 return FALSE;
1759 }
1760
1761 return TRUE;
1762}
1763
1764/******************************************************************************
1765 * CPDestroyKey (RSAENH.@)
1766 *
1767 * Releases the handle to a key object. The object is destroyed if it's reference
1768 * count reaches zero.
1769 *
1770 * PARAMS
1771 * hProv [I] Handle to the key container to which the key object belongs.
1772 * hKey [I] Handle to the key object to be released.
1773 *
1774 * RETURNS
1775 * Success: TRUE
1776 * Failure: FALSE
1777 */
1778BOOL WINAPI RSAENH_CPDestroyKey(HCRYPTPROV hProv, HCRYPTKEY hKey)
1779{
1780 TRACE("(hProv=%08lx, hKey=%08lx)\n", hProv, hKey);
1781
1782 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
1783 {
1784 SetLastError(NTE_BAD_UID);
1785 return FALSE;
1786 }
1787
1788 if (!release_handle(&handle_table, hKey, RSAENH_MAGIC_KEY))
1789 {
1790 SetLastError(NTE_BAD_KEY);
1791 return FALSE;
1792 }
1793
1794 return TRUE;
1795}
1796
1797/******************************************************************************
1798 * CPDuplicateHash (RSAENH.@)
1799 *
1800 * Clones a hash object including it's current state.
1801 *
1802 * PARAMS
1803 * hUID [I] Handle to the key container the hash belongs to.
1804 * hHash [I] Handle to the hash object to be cloned.
1805 * pdwReserved [I] Reserved. Must be NULL.
1806 * dwFlags [I] No flags are currently defined. Must be 0.
1807 * phHash [O] Handle to the cloned hash object.
1808 *
1809 * RETURNS
1810 * Success: TRUE.
1811 * Failure: FALSE.
1812 */
1813BOOL WINAPI RSAENH_CPDuplicateHash(HCRYPTPROV hUID, HCRYPTHASH hHash, DWORD *pdwReserved,
1814 DWORD dwFlags, HCRYPTHASH *phHash)
1815{
1816 CRYPTHASH *pSrcHash, *pDestHash;
1817
1818 TRACE("(hUID=%08lx, hHash=%08lx, pdwReserved=%p, dwFlags=%08x, phHash=%p)\n", hUID, hHash,
1819 pdwReserved, dwFlags, phHash);
1820
1821 if (!is_valid_handle(&handle_table, hUID, RSAENH_MAGIC_CONTAINER))
1822 {
1823 SetLastError(NTE_BAD_UID);
1824 return FALSE;
1825 }
1826
1827 if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH, (OBJECTHDR**)&pSrcHash))
1828 {
1829 SetLastError(NTE_BAD_HASH);
1830 return FALSE;
1831 }
1832
1833 if (!phHash || pdwReserved || dwFlags)
1834 {
1835 SetLastError(ERROR_INVALID_PARAMETER);
1836 return FALSE;
1837 }
1838
1839 *phHash = new_object(&handle_table, sizeof(CRYPTHASH), RSAENH_MAGIC_HASH,
1840 destroy_hash, (OBJECTHDR**)&pDestHash);
1841 if (*phHash != (HCRYPTHASH)INVALID_HANDLE_VALUE)
1842 {
1843 *pDestHash = *pSrcHash;
1844 duplicate_hash_impl(pSrcHash->aiAlgid, &pSrcHash->context, &pDestHash->context);
1845 copy_hmac_info(&pDestHash->pHMACInfo, pSrcHash->pHMACInfo);
1846 copy_data_blob(&pDestHash->tpPRFParams.blobLabel, &pSrcHash->tpPRFParams.blobLabel);
1847 copy_data_blob(&pDestHash->tpPRFParams.blobSeed, &pSrcHash->tpPRFParams.blobSeed);
1848 }
1849
1850 return *phHash != (HCRYPTHASH)INVALID_HANDLE_VALUE;
1851}
1852
1853/******************************************************************************
1854 * CPDuplicateKey (RSAENH.@)
1855 *
1856 * Clones a key object including it's current state.
1857 *
1858 * PARAMS
1859 * hUID [I] Handle to the key container the hash belongs to.
1860 * hKey [I] Handle to the key object to be cloned.
1861 * pdwReserved [I] Reserved. Must be NULL.
1862 * dwFlags [I] No flags are currently defined. Must be 0.
1863 * phHash [O] Handle to the cloned key object.
1864 *
1865 * RETURNS
1866 * Success: TRUE.
1867 * Failure: FALSE.
1868 */
1869BOOL WINAPI RSAENH_CPDuplicateKey(HCRYPTPROV hUID, HCRYPTKEY hKey, DWORD *pdwReserved,
1870 DWORD dwFlags, HCRYPTKEY *phKey)
1871{
1872 CRYPTKEY *pSrcKey, *pDestKey;
1873
1874 TRACE("(hUID=%08lx, hKey=%08lx, pdwReserved=%p, dwFlags=%08x, phKey=%p)\n", hUID, hKey,
1875 pdwReserved, dwFlags, phKey);
1876
1877 if (!is_valid_handle(&handle_table, hUID, RSAENH_MAGIC_CONTAINER))
1878 {
1879 SetLastError(NTE_BAD_UID);
1880 return FALSE;
1881 }
1882
1883 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pSrcKey))
1884 {
1885 SetLastError(NTE_BAD_KEY);
1886 return FALSE;
1887 }
1888
1889 if (!phKey || pdwReserved || dwFlags)
1890 {
1891 SetLastError(ERROR_INVALID_PARAMETER);
1892 return FALSE;
1893 }
1894
1895 *phKey = new_object(&handle_table, sizeof(CRYPTKEY), RSAENH_MAGIC_KEY, destroy_key,
1896 (OBJECTHDR**)&pDestKey);
1897 if (*phKey != (HCRYPTKEY)INVALID_HANDLE_VALUE)
1898 {
1899 *pDestKey = *pSrcKey;
1900 copy_data_blob(&pDestKey->siSChannelInfo.blobServerRandom,
1901 &pSrcKey->siSChannelInfo.blobServerRandom);
1902 copy_data_blob(&pDestKey->siSChannelInfo.blobClientRandom,
1903 &pSrcKey->siSChannelInfo.blobClientRandom);
1904 duplicate_key_impl(pSrcKey->aiAlgid, &pSrcKey->context, &pDestKey->context);
1905 return TRUE;
1906 }
1907 else
1908 {
1909 return FALSE;
1910 }
1911}
1912
1913/******************************************************************************
1914 * CPEncrypt (RSAENH.@)
1915 *
1916 * Encrypt data.
1917 *
1918 * PARAMS
1919 * hProv [I] The key container hKey and hHash belong to.
1920 * hKey [I] The key used to encrypt the data.
1921 * hHash [I] An optional hash object for parallel hashing. See notes.
1922 * Final [I] Indicates if this is the last block of data to encrypt.
1923 * dwFlags [I] Currently no flags defined. Must be zero.
1924 * pbData [I/O] Pointer to the data to encrypt. Encrypted data will also be stored there.
1925 * pdwDataLen [I/O] I: Length of data to encrypt, O: Length of encrypted data.
1926 * dwBufLen [I] Size of the buffer at pbData.
1927 *
1928 * RETURNS
1929 * Success: TRUE.
1930 * Failure: FALSE.
1931 *
1932 * NOTES
1933 * If a hash object handle is provided in hHash, it will be updated with the plaintext.
1934 * This is useful for message signatures.
1935 *
1936 * This function uses the standard WINAPI protocol for querying data of dynamic length.
1937 */
1938BOOL WINAPI RSAENH_CPEncrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
1939 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
1940{
1941 CRYPTKEY *pCryptKey;
1942 BYTE *in, out[RSAENH_MAX_BLOCK_SIZE], o[RSAENH_MAX_BLOCK_SIZE];
1943 DWORD dwEncryptedLen, i, j, k;
1944
1945 TRACE("(hProv=%08lx, hKey=%08lx, hHash=%08lx, Final=%d, dwFlags=%08x, pbData=%p, "
1946 "pdwDataLen=%p, dwBufLen=%d)\n", hProv, hKey, hHash, Final, dwFlags, pbData, pdwDataLen,
1947 dwBufLen);
1948
1949 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
1950 {
1951 SetLastError(NTE_BAD_UID);
1952 return FALSE;
1953 }
1954
1955 if (dwFlags)
1956 {
1957 SetLastError(NTE_BAD_FLAGS);
1958 return FALSE;
1959 }
1960
1961 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
1962 {
1963 SetLastError(NTE_BAD_KEY);
1964 return FALSE;
1965 }
1966
1967 if (pCryptKey->dwState == RSAENH_KEYSTATE_IDLE)
1968 pCryptKey->dwState = RSAENH_KEYSTATE_ENCRYPTING;
1969
1970 if (pCryptKey->dwState != RSAENH_KEYSTATE_ENCRYPTING)
1971 {
1972 SetLastError(NTE_BAD_DATA);
1973 return FALSE;
1974 }
1975
1976 if (is_valid_handle(&handle_table, hHash, RSAENH_MAGIC_HASH)) {
1977 if (!RSAENH_CPHashData(hProv, hHash, pbData, *pdwDataLen, 0)) return FALSE;
1978 }
1979
1980 if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_BLOCK) {
1981 if (!Final && (*pdwDataLen % pCryptKey->dwBlockLen)) {
1982 SetLastError(NTE_BAD_DATA);
1983 return FALSE;
1984 }
1985
1986 dwEncryptedLen = (*pdwDataLen/pCryptKey->dwBlockLen+(Final?1:0))*pCryptKey->dwBlockLen;
1987
1988 if (pbData == NULL) {
1989 *pdwDataLen = dwEncryptedLen;
1990 return TRUE;
1991 }
1992 else if (dwEncryptedLen > dwBufLen) {
1993 *pdwDataLen = dwEncryptedLen;
1994 SetLastError(ERROR_MORE_DATA);
1995 return FALSE;
1996 }
1997
1998 /* Pad final block with length bytes */
1999 for (i=*pdwDataLen; i<dwEncryptedLen; i++) pbData[i] = dwEncryptedLen - *pdwDataLen;
2000 *pdwDataLen = dwEncryptedLen;
2001
2002 for (i=0, in=pbData; i<*pdwDataLen; i+=pCryptKey->dwBlockLen, in+=pCryptKey->dwBlockLen) {
2003 switch (pCryptKey->dwMode) {
2004 case CRYPT_MODE_ECB:
2005 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out,
2006 RSAENH_ENCRYPT);
2007 break;
2008
2009 case CRYPT_MODE_CBC:
2010 for (j=0; j<pCryptKey->dwBlockLen; j++) in[j] ^= pCryptKey->abChainVector[j];
2011 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out,
2012 RSAENH_ENCRYPT);
2013 memcpy(pCryptKey->abChainVector, out, pCryptKey->dwBlockLen);
2014 break;
2015
2016 case CRYPT_MODE_CFB:
2017 for (j=0; j<pCryptKey->dwBlockLen; j++) {
2018 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context,
2019 pCryptKey->abChainVector, o, RSAENH_ENCRYPT);
2020 out[j] = in[j] ^ o[0];
2021 for (k=0; k<pCryptKey->dwBlockLen-1; k++)
2022 pCryptKey->abChainVector[k] = pCryptKey->abChainVector[k+1];
2023 pCryptKey->abChainVector[k] = out[j];
2024 }
2025 break;
2026
2027 default:
2028 SetLastError(NTE_BAD_ALGID);
2029 return FALSE;
2030 }
2031 memcpy(in, out, pCryptKey->dwBlockLen);
2032 }
2033 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_STREAM) {
2034 if (pbData == NULL) {
2035 *pdwDataLen = dwBufLen;
2036 return TRUE;
2037 }
2038 encrypt_stream_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, *pdwDataLen);
2039 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_RSA) {
2040 if (pCryptKey->aiAlgid == CALG_RSA_SIGN) {
2041 SetLastError(NTE_BAD_KEY);
2042 return FALSE;
2043 }
2044 if (!pbData) {
2045 *pdwDataLen = pCryptKey->dwBlockLen;
2046 return TRUE;
2047 }
2048 if (dwBufLen < pCryptKey->dwBlockLen) {
2049 SetLastError(ERROR_MORE_DATA);
2050 return FALSE;
2051 }
2052 if (!pad_data(pbData, *pdwDataLen, pbData, pCryptKey->dwBlockLen, dwFlags)) return FALSE;
2053 encrypt_block_impl(pCryptKey->aiAlgid, PK_PUBLIC, &pCryptKey->context, pbData, pbData, RSAENH_ENCRYPT);
2054 *pdwDataLen = pCryptKey->dwBlockLen;
2055 Final = TRUE;
2056 } else {
2057 SetLastError(NTE_BAD_TYPE);
2058 return FALSE;
2059 }
2060
2061 if (Final) setup_key(pCryptKey);
2062
2063 return TRUE;
2064}
2065
2066/******************************************************************************
2067 * CPDecrypt (RSAENH.@)
2068 *
2069 * Decrypt data.
2070 *
2071 * PARAMS
2072 * hProv [I] The key container hKey and hHash belong to.
2073 * hKey [I] The key used to decrypt the data.
2074 * hHash [I] An optional hash object for parallel hashing. See notes.
2075 * Final [I] Indicates if this is the last block of data to decrypt.
2076 * dwFlags [I] Currently no flags defined. Must be zero.
2077 * pbData [I/O] Pointer to the data to decrypt. Plaintext will also be stored there.
2078 * pdwDataLen [I/O] I: Length of ciphertext, O: Length of plaintext.
2079 *
2080 * RETURNS
2081 * Success: TRUE.
2082 * Failure: FALSE.
2083 *
2084 * NOTES
2085 * If a hash object handle is provided in hHash, it will be updated with the plaintext.
2086 * This is useful for message signatures.
2087 *
2088 * This function uses the standard WINAPI protocol for querying data of dynamic length.
2089 */
2090BOOL WINAPI RSAENH_CPDecrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
2091 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
2092{
2093 CRYPTKEY *pCryptKey;
2094 BYTE *in, out[RSAENH_MAX_BLOCK_SIZE], o[RSAENH_MAX_BLOCK_SIZE];
2095 DWORD i, j, k;
2096 DWORD dwMax;
2097
2098 TRACE("(hProv=%08lx, hKey=%08lx, hHash=%08lx, Final=%d, dwFlags=%08x, pbData=%p, "
2099 "pdwDataLen=%p)\n", hProv, hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
2100
2101 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2102 {
2103 SetLastError(NTE_BAD_UID);
2104 return FALSE;
2105 }
2106
2107 if (dwFlags)
2108 {
2109 SetLastError(NTE_BAD_FLAGS);
2110 return FALSE;
2111 }
2112
2113 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
2114 {
2115 SetLastError(NTE_BAD_KEY);
2116 return FALSE;
2117 }
2118
2119 if (pCryptKey->dwState == RSAENH_KEYSTATE_IDLE)
2120 pCryptKey->dwState = RSAENH_KEYSTATE_ENCRYPTING;
2121
2122 if (pCryptKey->dwState != RSAENH_KEYSTATE_ENCRYPTING)
2123 {
2124 SetLastError(NTE_BAD_DATA);
2125 return FALSE;
2126 }
2127
2128 dwMax=*pdwDataLen;
2129
2130 if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_BLOCK) {
2131 for (i=0, in=pbData; i<*pdwDataLen; i+=pCryptKey->dwBlockLen, in+=pCryptKey->dwBlockLen) {
2132 switch (pCryptKey->dwMode) {
2133 case CRYPT_MODE_ECB:
2134 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out,
2135 RSAENH_DECRYPT);
2136 break;
2137
2138 case CRYPT_MODE_CBC:
2139 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out,
2140 RSAENH_DECRYPT);
2141 for (j=0; j<pCryptKey->dwBlockLen; j++) out[j] ^= pCryptKey->abChainVector[j];
2142 memcpy(pCryptKey->abChainVector, in, pCryptKey->dwBlockLen);
2143 break;
2144
2145 case CRYPT_MODE_CFB:
2146 for (j=0; j<pCryptKey->dwBlockLen; j++) {
2147 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context,
2148 pCryptKey->abChainVector, o, RSAENH_ENCRYPT);
2149 out[j] = in[j] ^ o[0];
2150 for (k=0; k<pCryptKey->dwBlockLen-1; k++)
2151 pCryptKey->abChainVector[k] = pCryptKey->abChainVector[k+1];
2152 pCryptKey->abChainVector[k] = in[j];
2153 }
2154 break;
2155
2156 default:
2157 SetLastError(NTE_BAD_ALGID);
2158 return FALSE;
2159 }
2160 memcpy(in, out, pCryptKey->dwBlockLen);
2161 }
2162 if (Final) {
2163 if (pbData[*pdwDataLen-1] &&
2164 pbData[*pdwDataLen-1] <= pCryptKey->dwBlockLen &&
2165 pbData[*pdwDataLen-1] < *pdwDataLen) {
2166 BOOL padOkay = TRUE;
2167
2168 /* check that every bad byte has the same value */
2169 for (i = 1; padOkay && i < pbData[*pdwDataLen-1]; i++)
2170 if (pbData[*pdwDataLen - i - 1] != pbData[*pdwDataLen - 1])
2171 padOkay = FALSE;
2172 if (padOkay)
2173 *pdwDataLen -= pbData[*pdwDataLen-1];
2174 else {
2175 SetLastError(NTE_BAD_DATA);
2176 return FALSE;
2177 }
2178 }
2179 else {
2180 SetLastError(NTE_BAD_DATA);
2181 return FALSE;
2182 }
2183 }
2184
2185 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_STREAM) {
2186 encrypt_stream_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, *pdwDataLen);
2187 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_RSA) {
2188 if (pCryptKey->aiAlgid == CALG_RSA_SIGN) {
2189 SetLastError(NTE_BAD_KEY);
2190 return FALSE;
2191 }
2192 encrypt_block_impl(pCryptKey->aiAlgid, PK_PRIVATE, &pCryptKey->context, pbData, pbData, RSAENH_DECRYPT);
2193 if (!unpad_data(pbData, pCryptKey->dwBlockLen, pbData, pdwDataLen, dwFlags)) return FALSE;
2194 Final = TRUE;
2195 } else {
2196 SetLastError(NTE_BAD_TYPE);
2197 return FALSE;
2198 }
2199
2200 if (Final) setup_key(pCryptKey);
2201
2202 if (is_valid_handle(&handle_table, hHash, RSAENH_MAGIC_HASH)) {
2203 if (*pdwDataLen>dwMax ||
2204 !RSAENH_CPHashData(hProv, hHash, pbData, *pdwDataLen, 0)) return FALSE;
2205 }
2206
2207 return TRUE;
2208}
2209
2210/******************************************************************************
2211 * CPExportKey (RSAENH.@)
2212 *
2213 * Export a key into a binary large object (BLOB).
2214 *
2215 * PARAMS
2216 * hProv [I] Key container from which a key is to be exported.
2217 * hKey [I] Key to be exported.
2218 * hPubKey [I] Key used to encrypt sensitive BLOB data.
2219 * dwBlobType [I] SIMPLEBLOB, PUBLICKEYBLOB or PRIVATEKEYBLOB.
2220 * dwFlags [I] Currently none defined.
2221 * pbData [O] Pointer to a buffer where the BLOB will be written to.
2222 * pdwDataLen [I/O] I: Size of buffer at pbData, O: Size of BLOB
2223 *
2224 * RETURNS
2225 * Success: TRUE.
2226 * Failure: FALSE.
2227 */
2228BOOL WINAPI RSAENH_CPExportKey(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubKey,
2229 DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
2230{
2231 CRYPTKEY *pCryptKey, *pPubKey;
2232 BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData;
2233 RSAPUBKEY *pRSAPubKey = (RSAPUBKEY*)(pBlobHeader+1);
2234 ALG_ID *pAlgid = (ALG_ID*)(pBlobHeader+1);
2235 DWORD dwDataLen;
2236
2237 TRACE("(hProv=%08lx, hKey=%08lx, hPubKey=%08lx, dwBlobType=%08x, dwFlags=%08x, pbData=%p,"
2238 "pdwDataLen=%p)\n", hProv, hKey, hPubKey, dwBlobType, dwFlags, pbData, pdwDataLen);
2239
2240 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2241 {
2242 SetLastError(NTE_BAD_UID);
2243 return FALSE;
2244 }
2245
2246 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
2247 {
2248 SetLastError(NTE_BAD_KEY);
2249 return FALSE;
2250 }
2251
2252 if (dwFlags & CRYPT_SSL2_FALLBACK) {
2253 if (pCryptKey->aiAlgid != CALG_SSL2_MASTER) {
2254 SetLastError(NTE_BAD_KEY);
2255 return FALSE;
2256 }
2257 }
2258
2259 switch ((BYTE)dwBlobType)
2260 {
2261 case SIMPLEBLOB:
2262 if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey)){
2263 SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error_code? */
2264 return FALSE;
2265 }
2266
2267 if (!(GET_ALG_CLASS(pCryptKey->aiAlgid)&(ALG_CLASS_DATA_ENCRYPT|ALG_CLASS_MSG_ENCRYPT))) {
2268 SetLastError(NTE_BAD_KEY); /* FIXME: error code? */
2269 return FALSE;
2270 }
2271
2272 dwDataLen = sizeof(BLOBHEADER) + sizeof(ALG_ID) + pPubKey->dwBlockLen;
2273 if (pbData) {
2274 if (*pdwDataLen < dwDataLen) {
2275 SetLastError(ERROR_MORE_DATA);
2276 *pdwDataLen = dwDataLen;
2277 return FALSE;
2278 }
2279
2280 pBlobHeader->bType = SIMPLEBLOB;
2281 pBlobHeader->bVersion = CUR_BLOB_VERSION;
2282 pBlobHeader->reserved = 0;
2283 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
2284
2285 *pAlgid = pPubKey->aiAlgid;
2286
2287 if (!pad_data(pCryptKey->abKeyValue, pCryptKey->dwKeyLen, (BYTE*)(pAlgid+1),
2288 pPubKey->dwBlockLen, dwFlags))
2289 {
2290 return FALSE;
2291 }
2292
2293 encrypt_block_impl(pPubKey->aiAlgid, PK_PUBLIC, &pPubKey->context, (BYTE*)(pAlgid+1),
2294 (BYTE*)(pAlgid+1), RSAENH_ENCRYPT);
2295 }
2296 *pdwDataLen = dwDataLen;
2297 return TRUE;
2298
2299 case PUBLICKEYBLOB:
2300 if (is_valid_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY)) {
2301 SetLastError(NTE_BAD_KEY); /* FIXME: error code? */
2302 return FALSE;
2303 }
2304
2305 if ((pCryptKey->aiAlgid != CALG_RSA_KEYX) && (pCryptKey->aiAlgid != CALG_RSA_SIGN)) {
2306 SetLastError(NTE_BAD_KEY);
2307 return FALSE;
2308 }
2309
2310 dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + pCryptKey->dwKeyLen;
2311 if (pbData) {
2312 if (*pdwDataLen < dwDataLen) {
2313 SetLastError(ERROR_MORE_DATA);
2314 *pdwDataLen = dwDataLen;
2315 return FALSE;
2316 }
2317
2318 pBlobHeader->bType = PUBLICKEYBLOB;
2319 pBlobHeader->bVersion = CUR_BLOB_VERSION;
2320 pBlobHeader->reserved = 0;
2321 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
2322
2323 pRSAPubKey->magic = RSAENH_MAGIC_RSA1;
2324 pRSAPubKey->bitlen = pCryptKey->dwKeyLen << 3;
2325
2326 export_public_key_impl((BYTE*)(pRSAPubKey+1), &pCryptKey->context,
2327 pCryptKey->dwKeyLen, &pRSAPubKey->pubexp);
2328 }
2329 *pdwDataLen = dwDataLen;
2330 return TRUE;
2331
2332 case PRIVATEKEYBLOB:
2333 if ((pCryptKey->aiAlgid != CALG_RSA_KEYX) && (pCryptKey->aiAlgid != CALG_RSA_SIGN)) {
2334 SetLastError(NTE_BAD_KEY);
2335 return FALSE;
2336 }
2337
2338 dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2339 2 * pCryptKey->dwKeyLen + 5 * ((pCryptKey->dwKeyLen + 1) >> 1);
2340 if (pbData) {
2341 if (*pdwDataLen < dwDataLen) {
2342 SetLastError(ERROR_MORE_DATA);
2343 *pdwDataLen = dwDataLen;
2344 return FALSE;
2345 }
2346
2347 pBlobHeader->bType = PRIVATEKEYBLOB;
2348 pBlobHeader->bVersion = CUR_BLOB_VERSION;
2349 pBlobHeader->reserved = 0;
2350 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
2351
2352 pRSAPubKey->magic = RSAENH_MAGIC_RSA2;
2353 pRSAPubKey->bitlen = pCryptKey->dwKeyLen << 3;
2354
2355 export_private_key_impl((BYTE*)(pRSAPubKey+1), &pCryptKey->context,
2356 pCryptKey->dwKeyLen, &pRSAPubKey->pubexp);
2357 }
2358 *pdwDataLen = dwDataLen;
2359 return TRUE;
2360
2361 default:
2362 SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */
2363 return FALSE;
2364 }
2365}
2366
2367/******************************************************************************
2368 * CPImportKey (RSAENH.@)
2369 *
2370 * Import a BLOB'ed key into a key container.
2371 *
2372 * PARAMS
2373 * hProv [I] Key container into which the key is to be imported.
2374 * pbData [I] Pointer to a buffer which holds the BLOB.
2375 * dwDataLen [I] Length of data in buffer at pbData.
2376 * hPubKey [I] Key used to decrypt sensitive BLOB data.
2377 * dwFlags [I] Currently none defined.
2378 * phKey [O] Handle to the imported key.
2379 *
2380 * RETURNS
2381 * Success: TRUE.
2382 * Failure: FALSE.
2383 */
2384BOOL WINAPI RSAENH_CPImportKey(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen,
2385 HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
2386{
2387 KEYCONTAINER *pKeyContainer;
2388 CRYPTKEY *pCryptKey, *pPubKey;
2389 CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData;
2390 CONST RSAPUBKEY *pRSAPubKey = (CONST RSAPUBKEY*)(pBlobHeader+1);
2391 CONST ALG_ID *pAlgid = (CONST ALG_ID*)(pBlobHeader+1);
2392 CONST BYTE *pbKeyStream = (CONST BYTE*)(pAlgid + 1);
2393 ALG_ID algID;
2394 BYTE *pbDecrypted;
2395 DWORD dwKeyLen;
2396 BOOL ret;
2397
2398 TRACE("(hProv=%08lx, pbData=%p, dwDataLen=%d, hPubKey=%08lx, dwFlags=%08x, phKey=%p)\n",
2399 hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
2400
2401 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
2402 (OBJECTHDR**)&pKeyContainer))
2403 {
2404 SetLastError(NTE_BAD_UID);
2405 return FALSE;
2406 }
2407
2408 if (dwDataLen < sizeof(BLOBHEADER) ||
2409 pBlobHeader->bVersion != CUR_BLOB_VERSION ||
2410 pBlobHeader->reserved != 0)
2411 {
2412 SetLastError(NTE_BAD_DATA);
2413 return FALSE;
2414 }
2415
2416 switch (pBlobHeader->bType)
2417 {
2418 case PRIVATEKEYBLOB:
2419 if ((dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY)) ||
2420 (pRSAPubKey->magic != RSAENH_MAGIC_RSA2) ||
2421 (dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2422 (2 * pRSAPubKey->bitlen >> 3) + (5 * ((pRSAPubKey->bitlen+8)>>4))))
2423 {
2424 SetLastError(NTE_BAD_DATA);
2425 return FALSE;
2426 }
2427
2428 *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey);
2429 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
2430 setup_key(pCryptKey);
2431 ret = import_private_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context,
2432 pRSAPubKey->bitlen/8, pRSAPubKey->pubexp);
2433 if (ret) {
2434 switch (pBlobHeader->aiKeyAlg)
2435 {
2436 case AT_SIGNATURE:
2437 case CALG_RSA_SIGN:
2438 TRACE("installing signing key\n");
2439 RSAENH_CPDestroyKey(hProv, pKeyContainer->hSignatureKeyPair);
2440 copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
2441 &pKeyContainer->hSignatureKeyPair);
2442 break;
2443 case AT_KEYEXCHANGE:
2444 case CALG_RSA_KEYX:
2445 TRACE("installing key exchange key\n");
2446 RSAENH_CPDestroyKey(hProv, pKeyContainer->hKeyExchangeKeyPair);
2447 copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
2448 &pKeyContainer->hKeyExchangeKeyPair);
2449 break;
2450 }
2451 }
2452 return ret;
2453
2454 case PUBLICKEYBLOB:
2455 if ((dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY)) ||
2456 (pRSAPubKey->magic != RSAENH_MAGIC_RSA1) ||
2457 (dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + (pRSAPubKey->bitlen >> 3)))
2458 {
2459 SetLastError(NTE_BAD_DATA);
2460 return FALSE;
2461 }
2462
2463 /* Since this is a public key blob, only the public key is
2464 * available, so only signature verification is possible.
2465 */
2466 algID = pBlobHeader->aiKeyAlg;
2467 *phKey = new_key(hProv, algID, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey);
2468 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
2469 setup_key(pCryptKey);
2470 ret = import_public_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context,
2471 pRSAPubKey->bitlen >> 3, pRSAPubKey->pubexp);
2472 if (ret) {
2473 switch (pBlobHeader->aiKeyAlg)
2474 {
2475 case AT_KEYEXCHANGE:
2476 case CALG_RSA_KEYX:
2477 TRACE("installing public key\n");
2478 RSAENH_CPDestroyKey(hProv, pKeyContainer->hKeyExchangeKeyPair);
2479 copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
2480 &pKeyContainer->hKeyExchangeKeyPair);
2481 break;
2482 }
2483 }
2484 return ret;
2485
2486 case SIMPLEBLOB:
2487 if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey) ||
2488 pPubKey->aiAlgid != CALG_RSA_KEYX)
2489 {
2490 SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error code? */
2491 return FALSE;
2492 }
2493
2494 if (dwDataLen < sizeof(BLOBHEADER)+sizeof(ALG_ID)+pPubKey->dwBlockLen)
2495 {
2496 SetLastError(NTE_BAD_DATA); /* FIXME: error code */
2497 return FALSE;
2498 }
2499
2500 pbDecrypted = HeapAlloc(GetProcessHeap(), 0, pPubKey->dwBlockLen);
2501 if (!pbDecrypted) return FALSE;
2502 encrypt_block_impl(pPubKey->aiAlgid, PK_PRIVATE, &pPubKey->context, pbKeyStream, pbDecrypted,
2503 RSAENH_DECRYPT);
2504
2505 dwKeyLen = RSAENH_MAX_KEY_SIZE;
2506 if (!unpad_data(pbDecrypted, pPubKey->dwBlockLen, pbDecrypted, &dwKeyLen, dwFlags)) {
2507 HeapFree(GetProcessHeap(), 0, pbDecrypted);
2508 return FALSE;
2509 }
2510
2511 *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, dwKeyLen<<19, &pCryptKey);
2512 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE)
2513 {
2514 HeapFree(GetProcessHeap(), 0, pbDecrypted);
2515 return FALSE;
2516 }
2517 memcpy(pCryptKey->abKeyValue, pbDecrypted, dwKeyLen);
2518 HeapFree(GetProcessHeap(), 0, pbDecrypted);
2519 setup_key(pCryptKey);
2520 return TRUE;
2521
2522 default:
2523 SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */
2524 return FALSE;
2525 }
2526}
2527
2528/******************************************************************************
2529 * CPGenKey (RSAENH.@)
2530 *
2531 * Generate a key in the key container
2532 *
2533 * PARAMS
2534 * hProv [I] Key container for which a key is to be generated.
2535 * Algid [I] Crypto algorithm identifier for the key to be generated.
2536 * dwFlags [I] Upper 16 bits: Binary length of key. Lower 16 bits: Flags. See Notes
2537 * phKey [O] Handle to the generated key.
2538 *
2539 * RETURNS
2540 * Success: TRUE.
2541 * Failure: FALSE.
2542 *
2543 * FIXME
2544 * Flags currently not considered.
2545 *
2546 * NOTES
2547 * Private key-exchange- and signature-keys can be generated with Algid AT_KEYEXCHANGE
2548 * and AT_SIGNATURE values.
2549 */
2550BOOL WINAPI RSAENH_CPGenKey(HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
2551{
2552 KEYCONTAINER *pKeyContainer;
2553 CRYPTKEY *pCryptKey;
2554
2555 TRACE("(hProv=%08lx, aiAlgid=%d, dwFlags=%08x, phKey=%p)\n", hProv, Algid, dwFlags, phKey);
2556
2557 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
2558 (OBJECTHDR**)&pKeyContainer))
2559 {
2560 /* MSDN: hProv not containing valid context handle */
2561 SetLastError(NTE_BAD_UID);
2562 return FALSE;
2563 }
2564
2565 switch (Algid)
2566 {
2567 case AT_SIGNATURE:
2568 case CALG_RSA_SIGN:
2569 *phKey = new_key(hProv, CALG_RSA_SIGN, dwFlags, &pCryptKey);
2570 if (pCryptKey) {
2571 new_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen);
2572 setup_key(pCryptKey);
2573 if (Algid == AT_SIGNATURE) {
2574 RSAENH_CPDestroyKey(hProv, pKeyContainer->hSignatureKeyPair);
2575 copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
2576 &pKeyContainer->hSignatureKeyPair);
2577 }
2578 }
2579 break;
2580
2581 case AT_KEYEXCHANGE:
2582 case CALG_RSA_KEYX:
2583 *phKey = new_key(hProv, CALG_RSA_KEYX, dwFlags, &pCryptKey);
2584 if (pCryptKey) {
2585 new_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen);
2586 setup_key(pCryptKey);
2587 if (Algid == AT_KEYEXCHANGE) {
2588 RSAENH_CPDestroyKey(hProv, pKeyContainer->hKeyExchangeKeyPair);
2589 copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
2590 &pKeyContainer->hKeyExchangeKeyPair);
2591 }
2592 }
2593 break;
2594
2595 case CALG_RC2:
2596 case CALG_RC4:
2597 case CALG_DES:
2598 case CALG_3DES_112:
2599 case CALG_3DES:
2600 case CALG_AES:
2601 case CALG_AES_128:
2602 case CALG_AES_192:
2603 case CALG_AES_256:
2604 case CALG_PCT1_MASTER:
2605 case CALG_SSL2_MASTER:
2606 case CALG_SSL3_MASTER:
2607 case CALG_TLS1_MASTER:
2608 *phKey = new_key(hProv, Algid, dwFlags, &pCryptKey);
2609 if (pCryptKey) {
2610 gen_rand_impl(pCryptKey->abKeyValue, RSAENH_MAX_KEY_SIZE);
2611 switch (Algid) {
2612 case CALG_SSL3_MASTER:
2613 pCryptKey->abKeyValue[0] = RSAENH_SSL3_VERSION_MAJOR;
2614 pCryptKey->abKeyValue[1] = RSAENH_SSL3_VERSION_MINOR;
2615 break;
2616
2617 case CALG_TLS1_MASTER:
2618 pCryptKey->abKeyValue[0] = RSAENH_TLS1_VERSION_MAJOR;
2619 pCryptKey->abKeyValue[1] = RSAENH_TLS1_VERSION_MINOR;
2620 break;
2621 }
2622 setup_key(pCryptKey);
2623 }
2624 break;
2625
2626 default:
2627 /* MSDN: Algorithm not supported specified by Algid */
2628 SetLastError(NTE_BAD_ALGID);
2629 return FALSE;
2630 }
2631
2632 return *phKey != (HCRYPTKEY)INVALID_HANDLE_VALUE;
2633}
2634
2635/******************************************************************************
2636 * CPGenRandom (RSAENH.@)
2637 *
2638 * Generate a random byte stream.
2639 *
2640 * PARAMS
2641 * hProv [I] Key container that is used to generate random bytes.
2642 * dwLen [I] Specifies the number of requested random data bytes.
2643 * pbBuffer [O] Random bytes will be stored here.
2644 *
2645 * RETURNS
2646 * Success: TRUE
2647 * Failure: FALSE
2648 */
2649BOOL WINAPI RSAENH_CPGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
2650{
2651 TRACE("(hProv=%08lx, dwLen=%d, pbBuffer=%p)\n", hProv, dwLen, pbBuffer);
2652
2653 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2654 {
2655 /* MSDN: hProv not containing valid context handle */
2656 SetLastError(NTE_BAD_UID);
2657 return FALSE;
2658 }
2659
2660 return gen_rand_impl(pbBuffer, dwLen);
2661}
2662
2663/******************************************************************************
2664 * CPGetHashParam (RSAENH.@)
2665 *
2666 * Query parameters of an hash object.
2667 *
2668 * PARAMS
2669 * hProv [I] The kea container, which the hash belongs to.
2670 * hHash [I] The hash object that is to be queried.
2671 * dwParam [I] Specifies the parameter that is to be queried.
2672 * pbData [I] Pointer to the buffer where the parameter value will be stored.
2673 * pdwDataLen [I/O] I: Buffer length at pbData, O: Length of the parameter value.
2674 * dwFlags [I] None currently defined.
2675 *
2676 * RETURNS
2677 * Success: TRUE
2678 * Failure: FALSE
2679 *
2680 * NOTES
2681 * Valid dwParams are: HP_ALGID, HP_HASHSIZE, HP_HASHVALUE. The hash will be
2682 * finalized if HP_HASHVALUE is queried.
2683 */
2684BOOL WINAPI RSAENH_CPGetHashParam(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
2685 DWORD *pdwDataLen, DWORD dwFlags)
2686{
2687 CRYPTHASH *pCryptHash;
2688
2689 TRACE("(hProv=%08lx, hHash=%08lx, dwParam=%08x, pbData=%p, pdwDataLen=%p, dwFlags=%08x)\n",
2690 hProv, hHash, dwParam, pbData, pdwDataLen, dwFlags);
2691
2692 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2693 {
2694 SetLastError(NTE_BAD_UID);
2695 return FALSE;
2696 }
2697
2698 if (dwFlags)
2699 {
2700 SetLastError(NTE_BAD_FLAGS);
2701 return FALSE;
2702 }
2703
2704 if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH,
2705 (OBJECTHDR**)&pCryptHash))
2706 {
2707 SetLastError(NTE_BAD_HASH);
2708 return FALSE;
2709 }
2710
2711 if (!pdwDataLen)
2712 {
2713 SetLastError(ERROR_INVALID_PARAMETER);
2714 return FALSE;
2715 }
2716
2717 switch (dwParam)
2718 {
2719 case HP_ALGID:
2720 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptHash->aiAlgid,
2721 sizeof(ALG_ID));
2722
2723 case HP_HASHSIZE:
2724 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptHash->dwHashSize,
2725 sizeof(DWORD));
2726
2727 case HP_HASHVAL:
2728 if (pCryptHash->aiAlgid == CALG_TLS1PRF) {
2729 return tls1_prf(hProv, pCryptHash->hKey, &pCryptHash->tpPRFParams.blobLabel,
2730 &pCryptHash->tpPRFParams.blobSeed, pbData, *pdwDataLen);
2731 }
2732
2733 if ( pbData == NULL ) {
2734 *pdwDataLen = pCryptHash->dwHashSize;
2735 return TRUE;
2736 }
2737
2738 if (pbData && (pCryptHash->dwState != RSAENH_HASHSTATE_FINISHED))
2739 {
2740 finalize_hash(pCryptHash);
2741 pCryptHash->dwState = RSAENH_HASHSTATE_FINISHED;
2742 }
2743
2744 return copy_param(pbData, pdwDataLen, (CONST BYTE*)pCryptHash->abHashValue,
2745 pCryptHash->dwHashSize);
2746
2747 default:
2748 SetLastError(NTE_BAD_TYPE);
2749 return FALSE;
2750 }
2751}
2752
2753/******************************************************************************
2754 * CPSetKeyParam (RSAENH.@)
2755 *
2756 * Set a parameter of a key object
2757 *
2758 * PARAMS
2759 * hProv [I] The key container to which the key belongs.
2760 * hKey [I] The key for which a parameter is to be set.
2761 * dwParam [I] Parameter type. See Notes.
2762 * pbData [I] Pointer to the parameter value.
2763 * dwFlags [I] Currently none defined.
2764 *
2765 * RETURNS
2766 * Success: TRUE.
2767 * Failure: FALSE.
2768 *
2769 * NOTES:
2770 * Defined dwParam types are:
2771 * - KP_MODE: Values MODE_CBC, MODE_ECB, MODE_CFB.
2772 * - KP_MODE_BITS: Shift width for cipher feedback mode. (Currently ignored by MS CSP's)
2773 * - KP_PERMISSIONS: Or'ed combination of CRYPT_ENCRYPT, CRYPT_DECRYPT,
2774 * CRYPT_EXPORT, CRYPT_READ, CRYPT_WRITE, CRYPT_MAC
2775 * - KP_IV: Initialization vector
2776 */
2777BOOL WINAPI RSAENH_CPSetKeyParam(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
2778 DWORD dwFlags)
2779{
2780 CRYPTKEY *pCryptKey;
2781
2782 TRACE("(hProv=%08lx, hKey=%08lx, dwParam=%08x, pbData=%p, dwFlags=%08x)\n", hProv, hKey,
2783 dwParam, pbData, dwFlags);
2784
2785 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2786 {
2787 SetLastError(NTE_BAD_UID);
2788 return FALSE;
2789 }
2790
2791 if (dwFlags) {
2792 SetLastError(NTE_BAD_FLAGS);
2793 return FALSE;
2794 }
2795
2796 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
2797 {
2798 SetLastError(NTE_BAD_KEY);
2799 return FALSE;
2800 }
2801
2802 switch (dwParam) {
2803 case KP_PADDING:
2804 /* The MS providers only support PKCS5_PADDING */
2805 if (*(DWORD *)pbData != PKCS5_PADDING) {
2806 SetLastError(NTE_BAD_DATA);
2807 return FALSE;
2808 }
2809 return TRUE;
2810
2811 case KP_MODE:
2812 pCryptKey->dwMode = *(DWORD*)pbData;
2813 return TRUE;
2814
2815 case KP_MODE_BITS:
2816 pCryptKey->dwModeBits = *(DWORD*)pbData;
2817 return TRUE;
2818
2819 case KP_PERMISSIONS:
2820 pCryptKey->dwPermissions = *(DWORD*)pbData;
2821 return TRUE;
2822
2823 case KP_IV:
2824 memcpy(pCryptKey->abInitVector, pbData, pCryptKey->dwBlockLen);
2825 setup_key(pCryptKey);
2826 return TRUE;
2827
2828 case KP_SALT_EX:
2829 {
2830 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pbData;
2831
2832 /* salt length can't be greater than 184 bits = 24 bytes */
2833 if (blob->cbData > 24)
2834 {
2835 SetLastError(NTE_BAD_DATA);
2836 return FALSE;
2837 }
2838 memcpy(pCryptKey->abKeyValue + pCryptKey->dwKeyLen, blob->pbData,
2839 blob->cbData);
2840 pCryptKey->dwSaltLen = blob->cbData;
2841 setup_key(pCryptKey);
2842 return TRUE;
2843 }
2844
2845 case KP_EFFECTIVE_KEYLEN:
2846 switch (pCryptKey->aiAlgid) {
2847 case CALG_RC2:
2848 if (!pbData)
2849 {
2850 SetLastError(ERROR_INVALID_PARAMETER);
2851 return FALSE;
2852 }
2853 else if (!*(DWORD *)pbData || *(DWORD *)pbData > 1024)
2854 {
2855 SetLastError(NTE_BAD_DATA);
2856 return FALSE;
2857 }
2858 else
2859 {
2860 pCryptKey->dwEffectiveKeyLen = *(DWORD *)pbData;
2861 setup_key(pCryptKey);
2862 }
2863 break;
2864 default:
2865 SetLastError(NTE_BAD_TYPE);
2866 return FALSE;
2867 }
2868 return TRUE;
2869
2870 case KP_SCHANNEL_ALG:
2871 switch (((PSCHANNEL_ALG)pbData)->dwUse) {
2872 case SCHANNEL_ENC_KEY:
2873 memcpy(&pCryptKey->siSChannelInfo.saEncAlg, pbData, sizeof(SCHANNEL_ALG));
2874 break;
2875
2876 case SCHANNEL_MAC_KEY:
2877 memcpy(&pCryptKey->siSChannelInfo.saMACAlg, pbData, sizeof(SCHANNEL_ALG));
2878 break;
2879
2880 default:
2881 SetLastError(NTE_FAIL); /* FIXME: error code */
2882 return FALSE;
2883 }
2884 return TRUE;
2885
2886 case KP_CLIENT_RANDOM:
2887 return copy_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom, (PCRYPT_DATA_BLOB)pbData);
2888
2889 case KP_SERVER_RANDOM:
2890 return copy_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom, (PCRYPT_DATA_BLOB)pbData);
2891
2892 default:
2893 SetLastError(NTE_BAD_TYPE);
2894 return FALSE;
2895 }
2896}
2897
2898/******************************************************************************
2899 * CPGetKeyParam (RSAENH.@)
2900 *
2901 * Query a key parameter.
2902 *
2903 * PARAMS
2904 * hProv [I] The key container, which the key belongs to.
2905 * hHash [I] The key object that is to be queried.
2906 * dwParam [I] Specifies the parameter that is to be queried.
2907 * pbData [I] Pointer to the buffer where the parameter value will be stored.
2908 * pdwDataLen [I/O] I: Buffer length at pbData, O: Length of the parameter value.
2909 * dwFlags [I] None currently defined.
2910 *
2911 * RETURNS
2912 * Success: TRUE
2913 * Failure: FALSE
2914 *
2915 * NOTES
2916 * Defined dwParam types are:
2917 * - KP_MODE: Values MODE_CBC, MODE_ECB, MODE_CFB.
2918 * - KP_MODE_BITS: Shift width for cipher feedback mode.
2919 * (Currently ignored by MS CSP's - always eight)
2920 * - KP_PERMISSIONS: Or'ed combination of CRYPT_ENCRYPT, CRYPT_DECRYPT,
2921 * CRYPT_EXPORT, CRYPT_READ, CRYPT_WRITE, CRYPT_MAC
2922 * - KP_IV: Initialization vector.
2923 * - KP_KEYLEN: Bitwidth of the key.
2924 * - KP_BLOCKLEN: Size of a block cipher block.
2925 * - KP_SALT: Salt value.
2926 */
2927BOOL WINAPI RSAENH_CPGetKeyParam(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
2928 DWORD *pdwDataLen, DWORD dwFlags)
2929{
2930 CRYPTKEY *pCryptKey;
2931 DWORD dwValue;
2932
2933 TRACE("(hProv=%08lx, hKey=%08lx, dwParam=%08x, pbData=%p, pdwDataLen=%p dwFlags=%08x)\n",
2934 hProv, hKey, dwParam, pbData, pdwDataLen, dwFlags);
2935
2936 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2937 {
2938 SetLastError(NTE_BAD_UID);
2939 return FALSE;
2940 }
2941
2942 if (dwFlags) {
2943 SetLastError(NTE_BAD_FLAGS);
2944 return FALSE;
2945 }
2946
2947 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
2948 {
2949 SetLastError(NTE_BAD_KEY);
2950 return FALSE;
2951 }
2952
2953 switch (dwParam)
2954 {
2955 case KP_IV:
2956 return copy_param(pbData, pdwDataLen, (CONST BYTE*)pCryptKey->abInitVector,
2957 pCryptKey->dwBlockLen);
2958
2959 case KP_SALT:
2960 return copy_param(pbData, pdwDataLen,
2961 (CONST BYTE*)&pCryptKey->abKeyValue[pCryptKey->dwKeyLen], pCryptKey->dwSaltLen);
2962
2963 case KP_PADDING:
2964 dwValue = PKCS5_PADDING;
2965 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD));
2966
2967 case KP_KEYLEN:
2968 dwValue = pCryptKey->dwKeyLen << 3;
2969 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD));
2970
2971 case KP_EFFECTIVE_KEYLEN:
2972 if (pCryptKey->dwEffectiveKeyLen)
2973 dwValue = pCryptKey->dwEffectiveKeyLen;
2974 else
2975 dwValue = pCryptKey->dwKeyLen << 3;
2976 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD));
2977
2978 case KP_BLOCKLEN:
2979 dwValue = pCryptKey->dwBlockLen << 3;
2980 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD));
2981
2982 case KP_MODE:
2983 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->dwMode, sizeof(DWORD));
2984
2985 case KP_MODE_BITS:
2986 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->dwModeBits,
2987 sizeof(DWORD));
2988
2989 case KP_PERMISSIONS:
2990 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->dwPermissions,
2991 sizeof(DWORD));
2992
2993 case KP_ALGID:
2994 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->aiAlgid, sizeof(DWORD));
2995
2996 default:
2997 SetLastError(NTE_BAD_TYPE);
2998 return FALSE;
2999 }
3000}
3001
3002/******************************************************************************
3003 * CPGetProvParam (RSAENH.@)
3004 *
3005 * Query a CSP parameter.
3006 *
3007 * PARAMS
3008 * hProv [I] The key container that is to be queried.
3009 * dwParam [I] Specifies the parameter that is to be queried.
3010 * pbData [I] Pointer to the buffer where the parameter value will be stored.
3011 * pdwDataLen [I/O] I: Buffer length at pbData, O: Length of the parameter value.
3012 * dwFlags [I] CRYPT_FIRST: Start enumeration (for PP_ENUMALGS{_EX}).
3013 *
3014 * RETURNS
3015 * Success: TRUE
3016 * Failure: FALSE
3017 * NOTES:
3018 * Defined dwParam types:
3019 * - PP_CONTAINER: Name of the key container.
3020 * - PP_NAME: Name of the cryptographic service provider.
3021 * - PP_SIG_KEYSIZE_INC: RSA signature keywidth granularity in bits.
3022 * - PP_KEYX_KEYSIZE_INC: RSA key-exchange keywidth granularity in bits.
3023 * - PP_ENUMALGS{_EX}: Query provider capabilities.
3024 */
3025BOOL WINAPI RSAENH_CPGetProvParam(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
3026 DWORD *pdwDataLen, DWORD dwFlags)
3027{
3028 KEYCONTAINER *pKeyContainer;
3029 PROV_ENUMALGS provEnumalgs;
3030 DWORD dwTemp;
3031 HKEY hKey;
3032
3033 /* This is for dwParam PP_CRYPT_COUNT_KEY_USE.
3034 * IE6 SP1 asks for it in the 'About' dialog.
3035 * Returning this BLOB seems to satisfy IE. The marked 0x00 seem
3036 * to be 'don't care's. If you know anything more specific about
3037 * this provider parameter, please report to wine-devel@winehq.org */
3038 static CONST BYTE abWTF[96] = {
3039 0xb0, 0x25, 0x63, 0x86, 0x9c, 0xab, 0xb6, 0x37,
3040 0xe8, 0x82, /**/0x00,/**/ 0x72, 0x06, 0xb2, /**/0x00,/**/ 0x3b,
3041 0x60, 0x35, /**/0x00,/**/ 0x3b, 0x88, 0xce, /**/0x00,/**/ 0x82,
3042 0xbc, 0x7a, /**/0x00,/**/ 0xb7, 0x4f, 0x7e, /**/0x00,/**/ 0xde,
3043 0x92, 0xf1, /**/0x00,/**/ 0x83, 0xea, 0x5e, /**/0x00,/**/ 0xc8,
3044 0x12, 0x1e, 0xd4, 0x06, 0xf7, 0x66, /**/0x00,/**/ 0x01,
3045 0x29, 0xa4, /**/0x00,/**/ 0xf8, 0x24, 0x0c, /**/0x00,/**/ 0x33,
3046 0x06, 0x80, /**/0x00,/**/ 0x02, 0x46, 0x0b, /**/0x00,/**/ 0x6d,
3047 0x5b, 0xca, /**/0x00,/**/ 0x9a, 0x10, 0xf0, /**/0x00,/**/ 0x05,
3048 0x19, 0xd0, /**/0x00,/**/ 0x2c, 0xf6, 0x27, /**/0x00,/**/ 0xaa,
3049 0x7c, 0x6f, /**/0x00,/**/ 0xb9, 0xd8, 0x72, /**/0x00,/**/ 0x03,
3050 0xf3, 0x81, /**/0x00,/**/ 0xfa, 0xe8, 0x26, /**/0x00,/**/ 0xca
3051 };
3052
3053 TRACE("(hProv=%08lx, dwParam=%08x, pbData=%p, pdwDataLen=%p, dwFlags=%08x)\n",
3054 hProv, dwParam, pbData, pdwDataLen, dwFlags);
3055
3056 if (!pdwDataLen) {
3057 SetLastError(ERROR_INVALID_PARAMETER);
3058 return FALSE;
3059 }
3060
3061 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
3062 (OBJECTHDR**)&pKeyContainer))
3063 {
3064 /* MSDN: hProv not containing valid context handle */
3065 SetLastError(NTE_BAD_UID);
3066 return FALSE;
3067 }
3068
3069 switch (dwParam)
3070 {
3071 case PP_CONTAINER:
3072 case PP_UNIQUE_CONTAINER:/* MSDN says we can return the same value as PP_CONTAINER */
3073 return copy_param(pbData, pdwDataLen, (CONST BYTE*)pKeyContainer->szName,
3074 strlen(pKeyContainer->szName)+1);
3075
3076 case PP_NAME:
3077 return copy_param(pbData, pdwDataLen, (CONST BYTE*)pKeyContainer->szProvName,
3078 strlen(pKeyContainer->szProvName)+1);
3079
3080 case PP_PROVTYPE:
3081 dwTemp = PROV_RSA_FULL;
3082 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3083
3084 case PP_KEYSPEC:
3085 dwTemp = AT_SIGNATURE | AT_KEYEXCHANGE;
3086 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3087
3088 case PP_KEYSET_TYPE:
3089 dwTemp = pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET;
3090 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3091
3092 case PP_KEYSTORAGE:
3093 dwTemp = CRYPT_SEC_DESCR;
3094 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3095
3096 case PP_SIG_KEYSIZE_INC:
3097 case PP_KEYX_KEYSIZE_INC:
3098 dwTemp = 8;
3099 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3100
3101 case PP_IMPTYPE:
3102 dwTemp = CRYPT_IMPL_SOFTWARE;
3103 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3104
3105 case PP_VERSION:
3106 dwTemp = 0x00000200;
3107 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
3108
3109 case PP_ENUMCONTAINERS:
3110 if ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) pKeyContainer->dwEnumContainersCtr = 0;
3111
3112 if (!pbData) {
3113 *pdwDataLen = (DWORD)MAX_PATH + 1;
3114 return TRUE;
3115 }
3116
3117 if (!open_container_key("", dwFlags, &hKey))
3118 {
3119 SetLastError(ERROR_NO_MORE_ITEMS);
3120 return FALSE;
3121 }
3122
3123 dwTemp = *pdwDataLen;
3124 switch (RegEnumKeyExA(hKey, pKeyContainer->dwEnumContainersCtr, (LPSTR)pbData, &dwTemp,
3125 NULL, NULL, NULL, NULL))
3126 {
3127 case ERROR_MORE_DATA:
3128 *pdwDataLen = (DWORD)MAX_PATH + 1;
3129
3130 case ERROR_SUCCESS:
3131 pKeyContainer->dwEnumContainersCtr++;
3132 RegCloseKey(hKey);
3133 return TRUE;
3134
3135 case ERROR_NO_MORE_ITEMS:
3136 default:
3137 SetLastError(ERROR_NO_MORE_ITEMS);
3138 RegCloseKey(hKey);
3139 return FALSE;
3140 }
3141
3142 case PP_ENUMALGS:
3143 case PP_ENUMALGS_EX:
3144 if (((pKeyContainer->dwEnumAlgsCtr >= RSAENH_MAX_ENUMALGS-1) ||
3145 (!aProvEnumAlgsEx[pKeyContainer->dwPersonality]
3146 [pKeyContainer->dwEnumAlgsCtr+1].aiAlgid)) &&
3147 ((dwFlags & CRYPT_FIRST) != CRYPT_FIRST))
3148 {
3149 SetLastError(ERROR_NO_MORE_ITEMS);
3150 return FALSE;
3151 }
3152
3153 if (dwParam == PP_ENUMALGS) {
3154 if (pbData && (*pdwDataLen >= sizeof(PROV_ENUMALGS)))
3155 pKeyContainer->dwEnumAlgsCtr = ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) ?
3156 0 : pKeyContainer->dwEnumAlgsCtr+1;
3157
3158 provEnumalgs.aiAlgid = aProvEnumAlgsEx
3159 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].aiAlgid;
3160 provEnumalgs.dwBitLen = aProvEnumAlgsEx
3161 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].dwDefaultLen;
3162 provEnumalgs.dwNameLen = aProvEnumAlgsEx
3163 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].dwNameLen;
3164 memcpy(provEnumalgs.szName, aProvEnumAlgsEx
3165 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].szName,
3166 20*sizeof(CHAR));
3167
3168 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&provEnumalgs,
3169 sizeof(PROV_ENUMALGS));
3170 } else {
3171 if (pbData && (*pdwDataLen >= sizeof(PROV_ENUMALGS_EX)))
3172 pKeyContainer->dwEnumAlgsCtr = ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) ?
3173 0 : pKeyContainer->dwEnumAlgsCtr+1;
3174
3175 return copy_param(pbData, pdwDataLen,
3176 (CONST BYTE*)&aProvEnumAlgsEx
3177 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr],
3178 sizeof(PROV_ENUMALGS_EX));
3179 }
3180
3181 case PP_CRYPT_COUNT_KEY_USE: /* Asked for by IE About dialog */
3182 return copy_param(pbData, pdwDataLen, abWTF, sizeof(abWTF));
3183
3184 default:
3185 /* MSDN: Unknown parameter number in dwParam */
3186 SetLastError(NTE_BAD_TYPE);
3187 return FALSE;
3188 }
3189}
3190
3191/******************************************************************************
3192 * CPDeriveKey (RSAENH.@)
3193 *
3194 * Derives a key from a hash value.
3195 *
3196 * PARAMS
3197 * hProv [I] Key container for which a key is to be generated.
3198 * Algid [I] Crypto algorithm identifier for the key to be generated.
3199 * hBaseData [I] Hash from whose value the key will be derived.
3200 * dwFlags [I] See Notes.
3201 * phKey [O] The generated key.
3202 *
3203 * RETURNS
3204 * Success: TRUE
3205 * Failure: FALSE
3206 *
3207 * NOTES
3208 * Defined flags:
3209 * - CRYPT_EXPORTABLE: Key can be exported.
3210 * - CRYPT_NO_SALT: No salt is used for 40 bit keys.
3211 * - CRYPT_CREATE_SALT: Use remaining bits as salt value.
3212 */
3213BOOL WINAPI RSAENH_CPDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
3214 DWORD dwFlags, HCRYPTKEY *phKey)
3215{
3216 CRYPTKEY *pCryptKey, *pMasterKey;
3217 CRYPTHASH *pCryptHash;
3218 BYTE abHashValue[RSAENH_MAX_HASH_SIZE*2];
3219 DWORD dwLen;
3220
3221 TRACE("(hProv=%08lx, Algid=%d, hBaseData=%08lx, dwFlags=%08x phKey=%p)\n", hProv, Algid,
3222 hBaseData, dwFlags, phKey);
3223
3224 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
3225 {
3226 SetLastError(NTE_BAD_UID);
3227 return FALSE;
3228 }
3229
3230 if (!lookup_handle(&handle_table, hBaseData, RSAENH_MAGIC_HASH,
3231 (OBJECTHDR**)&pCryptHash))
3232 {
3233 SetLastError(NTE_BAD_HASH);
3234 return FALSE;
3235 }
3236
3237 if (!phKey)
3238 {
3239 SetLastError(ERROR_INVALID_PARAMETER);
3240 return FALSE;
3241 }
3242
3243 switch (GET_ALG_CLASS(Algid))
3244 {
3245 case ALG_CLASS_DATA_ENCRYPT:
3246 *phKey = new_key(hProv, Algid, dwFlags, &pCryptKey);
3247 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
3248
3249 /*
3250 * We derive the key material from the hash.
3251 * If the hash value is not large enough for the claimed key, we have to construct
3252 * a larger binary value based on the hash. This is documented in MSDN: CryptDeriveKey.
3253 */
3254 dwLen = RSAENH_MAX_HASH_SIZE;
3255 RSAENH_CPGetHashParam(pCryptHash->hProv, hBaseData, HP_HASHVAL, abHashValue, &dwLen, 0);
3256
3257 if (dwLen < pCryptKey->dwKeyLen) {
3258 BYTE pad1[RSAENH_HMAC_DEF_PAD_LEN], pad2[RSAENH_HMAC_DEF_PAD_LEN];
3259 BYTE old_hashval[RSAENH_MAX_HASH_SIZE];
3260 DWORD i;
3261
3262 memcpy(old_hashval, pCryptHash->abHashValue, RSAENH_MAX_HASH_SIZE);
3263
3264 for (i=0; i<RSAENH_HMAC_DEF_PAD_LEN; i++) {
3265 pad1[i] = RSAENH_HMAC_DEF_IPAD_CHAR ^ (i<dwLen ? abHashValue[i] : 0);
3266 pad2[i] = RSAENH_HMAC_DEF_OPAD_CHAR ^ (i<dwLen ? abHashValue[i] : 0);
3267 }
3268
3269 init_hash(pCryptHash);
3270 update_hash(pCryptHash, pad1, RSAENH_HMAC_DEF_PAD_LEN);
3271 finalize_hash(pCryptHash);
3272 memcpy(abHashValue, pCryptHash->abHashValue, pCryptHash->dwHashSize);
3273
3274 init_hash(pCryptHash);
3275 update_hash(pCryptHash, pad2, RSAENH_HMAC_DEF_PAD_LEN);
3276 finalize_hash(pCryptHash);
3277 memcpy(abHashValue+pCryptHash->dwHashSize, pCryptHash->abHashValue,
3278 pCryptHash->dwHashSize);
3279
3280 memcpy(pCryptHash->abHashValue, old_hashval, RSAENH_MAX_HASH_SIZE);
3281 }
3282
3283 memcpy(pCryptKey->abKeyValue, abHashValue,
3284 RSAENH_MIN(pCryptKey->dwKeyLen, sizeof(pCryptKey->abKeyValue)));
3285 break;
3286
3287 case ALG_CLASS_MSG_ENCRYPT:
3288 if (!lookup_handle(&handle_table, pCryptHash->hKey, RSAENH_MAGIC_KEY,
3289 (OBJECTHDR**)&pMasterKey))
3290 {
3291 SetLastError(NTE_FAIL); /* FIXME error code */
3292 return FALSE;
3293 }
3294
3295 switch (Algid)
3296 {
3297 /* See RFC 2246, chapter 6.3 Key calculation */
3298 case CALG_SCHANNEL_ENC_KEY:
3299 *phKey = new_key(hProv, pMasterKey->siSChannelInfo.saEncAlg.Algid,
3300 MAKELONG(LOWORD(dwFlags),pMasterKey->siSChannelInfo.saEncAlg.cBits),
3301 &pCryptKey);
3302 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
3303 memcpy(pCryptKey->abKeyValue,
3304 pCryptHash->abHashValue + (
3305 2 * (pMasterKey->siSChannelInfo.saMACAlg.cBits / 8) +
3306 ((dwFlags & CRYPT_SERVER) ?
3307 (pMasterKey->siSChannelInfo.saEncAlg.cBits / 8) : 0)),
3308 pMasterKey->siSChannelInfo.saEncAlg.cBits / 8);
3309 memcpy(pCryptKey->abInitVector,
3310 pCryptHash->abHashValue + (
3311 2 * (pMasterKey->siSChannelInfo.saMACAlg.cBits / 8) +
3312 2 * (pMasterKey->siSChannelInfo.saEncAlg.cBits / 8) +
3313 ((dwFlags & CRYPT_SERVER) ? pCryptKey->dwBlockLen : 0)),
3314 pCryptKey->dwBlockLen);
3315 break;
3316
3317 case CALG_SCHANNEL_MAC_KEY:
3318 *phKey = new_key(hProv, Algid,
3319 MAKELONG(LOWORD(dwFlags),pMasterKey->siSChannelInfo.saMACAlg.cBits),
3320 &pCryptKey);
3321 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
3322 memcpy(pCryptKey->abKeyValue,
3323 pCryptHash->abHashValue + ((dwFlags & CRYPT_SERVER) ?
3324 pMasterKey->siSChannelInfo.saMACAlg.cBits / 8 : 0),
3325 pMasterKey->siSChannelInfo.saMACAlg.cBits / 8);
3326 break;
3327
3328 default:
3329 SetLastError(NTE_BAD_ALGID);
3330 return FALSE;
3331 }
3332 break;
3333
3334 default:
3335 SetLastError(NTE_BAD_ALGID);
3336 return FALSE;
3337 }
3338
3339 setup_key(pCryptKey);
3340 return TRUE;
3341}
3342
3343/******************************************************************************
3344 * CPGetUserKey (RSAENH.@)
3345 *
3346 * Returns a handle to the user's private key-exchange- or signature-key.
3347 *
3348 * PARAMS
3349 * hProv [I] The key container from which a user key is requested.
3350 * dwKeySpec [I] AT_KEYEXCHANGE or AT_SIGNATURE
3351 * phUserKey [O] Handle to the requested key or INVALID_HANDLE_VALUE in case of failure.
3352 *
3353 * RETURNS
3354 * Success: TRUE.
3355 * Failure: FALSE.
3356 *
3357 * NOTE
3358 * A newly created key container does not contain private user key. Create them with CPGenKey.
3359 */
3360BOOL WINAPI RSAENH_CPGetUserKey(HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
3361{
3362 KEYCONTAINER *pKeyContainer;
3363
3364 TRACE("(hProv=%08lx, dwKeySpec=%08x, phUserKey=%p)\n", hProv, dwKeySpec, phUserKey);
3365
3366 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
3367 (OBJECTHDR**)&pKeyContainer))
3368 {
3369 /* MSDN: hProv not containing valid context handle */
3370 SetLastError(NTE_BAD_UID);
3371 return FALSE;
3372 }
3373
3374 switch (dwKeySpec)
3375 {
3376 case AT_KEYEXCHANGE:
3377 copy_handle(&handle_table, pKeyContainer->hKeyExchangeKeyPair, RSAENH_MAGIC_KEY,
3378 phUserKey);
3379 break;
3380
3381 case AT_SIGNATURE:
3382 copy_handle(&handle_table, pKeyContainer->hSignatureKeyPair, RSAENH_MAGIC_KEY,
3383 phUserKey);
3384 break;
3385
3386 default:
3387 *phUserKey = (HCRYPTKEY)INVALID_HANDLE_VALUE;
3388 }
3389
3390 if (*phUserKey == (HCRYPTKEY)INVALID_HANDLE_VALUE)
3391 {
3392 /* MSDN: dwKeySpec parameter specifies nonexistent key */
3393 SetLastError(NTE_NO_KEY);
3394 return FALSE;
3395 }
3396
3397 return TRUE;
3398}
3399
3400/******************************************************************************
3401 * CPHashData (RSAENH.@)
3402 *
3403 * Updates a hash object with the given data.
3404 *
3405 * PARAMS
3406 * hProv [I] Key container to which the hash object belongs.
3407 * hHash [I] Hash object which is to be updated.
3408 * pbData [I] Pointer to data with which the hash object is to be updated.
3409 * dwDataLen [I] Length of the data.
3410 * dwFlags [I] Currently none defined.
3411 *
3412 * RETURNS
3413 * Success: TRUE.
3414 * Failure: FALSE.
3415 *
3416 * NOTES
3417 * The actual hash value is queried with CPGetHashParam, which will finalize
3418 * the hash. Updating a finalized hash will fail with a last error NTE_BAD_HASH_STATE.
3419 */
3420BOOL WINAPI RSAENH_CPHashData(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST BYTE *pbData,
3421 DWORD dwDataLen, DWORD dwFlags)
3422{
3423 CRYPTHASH *pCryptHash;
3424
3425 TRACE("(hProv=%08lx, hHash=%08lx, pbData=%p, dwDataLen=%d, dwFlags=%08x)\n",
3426 hProv, hHash, pbData, dwDataLen, dwFlags);
3427
3428 if (dwFlags)
3429 {
3430 SetLastError(NTE_BAD_FLAGS);
3431 return FALSE;
3432 }
3433
3434 if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH,
3435 (OBJECTHDR**)&pCryptHash))
3436 {
3437 SetLastError(NTE_BAD_HASH);
3438 return FALSE;
3439 }
3440
3441 if (!get_algid_info(hProv, pCryptHash->aiAlgid) || pCryptHash->aiAlgid == CALG_SSL3_SHAMD5)
3442 {
3443 SetLastError(NTE_BAD_ALGID);
3444 return FALSE;
3445 }
3446
3447 if (pCryptHash->dwState != RSAENH_HASHSTATE_HASHING)
3448 {
3449 SetLastError(NTE_BAD_HASH_STATE);
3450 return FALSE;
3451 }
3452
3453 update_hash(pCryptHash, pbData, dwDataLen);
3454 return TRUE;
3455}
3456
3457/******************************************************************************
3458 * CPHashSessionKey (RSAENH.@)
3459 *
3460 * Updates a hash object with the binary representation of a symmetric key.
3461 *
3462 * PARAMS
3463 * hProv [I] Key container to which the hash object belongs.
3464 * hHash [I] Hash object which is to be updated.
3465 * hKey [I] The symmetric key, whose binary value will be added to the hash.
3466 * dwFlags [I] CRYPT_LITTLE_ENDIAN, if the binary key value shall be interpreted as little endian.
3467 *
3468 * RETURNS
3469 * Success: TRUE.
3470 * Failure: FALSE.
3471 */
3472BOOL WINAPI RSAENH_CPHashSessionKey(HCRYPTPROV hProv, HCRYPTHASH hHash, HCRYPTKEY hKey,
3473 DWORD dwFlags)
3474{
3475 BYTE abKeyValue[RSAENH_MAX_KEY_SIZE], bTemp;
3476 CRYPTKEY *pKey;
3477 DWORD i;
3478
3479 TRACE("(hProv=%08lx, hHash=%08lx, hKey=%08lx, dwFlags=%08x)\n", hProv, hHash, hKey, dwFlags);
3480
3481 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pKey) ||
3482 (GET_ALG_CLASS(pKey->aiAlgid) != ALG_CLASS_DATA_ENCRYPT))
3483 {
3484 SetLastError(NTE_BAD_KEY);
3485 return FALSE;
3486 }
3487
3488 if (dwFlags & ~CRYPT_LITTLE_ENDIAN) {
3489 SetLastError(NTE_BAD_FLAGS);
3490 return FALSE;
3491 }
3492
3493 memcpy(abKeyValue, pKey->abKeyValue, pKey->dwKeyLen);
3494 if (!(dwFlags & CRYPT_LITTLE_ENDIAN)) {
3495 for (i=0; i<pKey->dwKeyLen/2; i++) {
3496 bTemp = abKeyValue[i];
3497 abKeyValue[i] = abKeyValue[pKey->dwKeyLen-i-1];
3498 abKeyValue[pKey->dwKeyLen-i-1] = bTemp;
3499 }
3500 }
3501
3502 return RSAENH_CPHashData(hProv, hHash, abKeyValue, pKey->dwKeyLen, 0);
3503}
3504
3505/******************************************************************************
3506 * CPReleaseContext (RSAENH.@)
3507 *
3508 * Release a key container.
3509 *
3510 * PARAMS
3511 * hProv [I] Key container to be released.
3512 * dwFlags [I] Currently none defined.
3513 *
3514 * RETURNS
3515 * Success: TRUE
3516 * Failure: FALSE
3517 */
3518BOOL WINAPI RSAENH_CPReleaseContext(HCRYPTPROV hProv, DWORD dwFlags)
3519{
3520 TRACE("(hProv=%08lx, dwFlags=%08x)\n", hProv, dwFlags);
3521
3522 if (!release_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
3523 {
3524 /* MSDN: hProv not containing valid context handle */
3525 SetLastError(NTE_BAD_UID);
3526 return FALSE;
3527 }
3528
3529 if (dwFlags) {
3530 SetLastError(NTE_BAD_FLAGS);
3531 return FALSE;
3532 }
3533
3534 return TRUE;
3535}
3536
3537/******************************************************************************
3538 * CPSetHashParam (RSAENH.@)
3539 *
3540 * Set a parameter of a hash object
3541 *
3542 * PARAMS
3543 * hProv [I] The key container to which the key belongs.
3544 * hHash [I] The hash object for which a parameter is to be set.
3545 * dwParam [I] Parameter type. See Notes.
3546 * pbData [I] Pointer to the parameter value.
3547 * dwFlags [I] Currently none defined.
3548 *
3549 * RETURNS
3550 * Success: TRUE.
3551 * Failure: FALSE.
3552 *
3553 * NOTES
3554 * Currently only the HP_HMAC_INFO dwParam type is defined.
3555 * The HMAC_INFO struct will be deep copied into the hash object.
3556 * See Internet RFC 2104 for details on the HMAC algorithm.
3557 */
3558BOOL WINAPI RSAENH_CPSetHashParam(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam,
3559 BYTE *pbData, DWORD dwFlags)
3560{
3561 CRYPTHASH *pCryptHash;
3562 CRYPTKEY *pCryptKey;
3563 DWORD i;
3564
3565 TRACE("(hProv=%08lx, hHash=%08lx, dwParam=%08x, pbData=%p, dwFlags=%08x)\n",
3566 hProv, hHash, dwParam, pbData, dwFlags);
3567
3568 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
3569 {
3570 SetLastError(NTE_BAD_UID);
3571 return FALSE;
3572 }
3573
3574 if (dwFlags) {
3575 SetLastError(NTE_BAD_FLAGS);
3576 return FALSE;
3577 }
3578
3579 if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH,
3580 (OBJECTHDR**)&pCryptHash))
3581 {
3582 SetLastError(NTE_BAD_HASH);
3583 return FALSE;
3584 }
3585
3586 switch (dwParam) {
3587 case HP_HMAC_INFO:
3588 free_hmac_info(pCryptHash->pHMACInfo);
3589 if (!copy_hmac_info(&pCryptHash->pHMACInfo, (PHMAC_INFO)pbData)) return FALSE;
3590
3591 if (!lookup_handle(&handle_table, pCryptHash->hKey, RSAENH_MAGIC_KEY,
3592 (OBJECTHDR**)&pCryptKey))
3593 {
3594 SetLastError(NTE_FAIL); /* FIXME: correct error code? */
3595 return FALSE;
3596 }
3597
3598 for (i=0; i<RSAENH_MIN(pCryptKey->dwKeyLen,pCryptHash->pHMACInfo->cbInnerString); i++) {
3599 pCryptHash->pHMACInfo->pbInnerString[i] ^= pCryptKey->abKeyValue[i];
3600 }
3601 for (i=0; i<RSAENH_MIN(pCryptKey->dwKeyLen,pCryptHash->pHMACInfo->cbOuterString); i++) {
3602 pCryptHash->pHMACInfo->pbOuterString[i] ^= pCryptKey->abKeyValue[i];
3603 }
3604
3605 init_hash(pCryptHash);
3606 return TRUE;
3607
3608 case HP_HASHVAL:
3609 memcpy(pCryptHash->abHashValue, pbData, pCryptHash->dwHashSize);
3610 pCryptHash->dwState = RSAENH_HASHSTATE_FINISHED;
3611 return TRUE;
3612
3613 case HP_TLS1PRF_SEED:
3614 return copy_data_blob(&pCryptHash->tpPRFParams.blobSeed, (PCRYPT_DATA_BLOB)pbData);
3615
3616 case HP_TLS1PRF_LABEL:
3617 return copy_data_blob(&pCryptHash->tpPRFParams.blobLabel, (PCRYPT_DATA_BLOB)pbData);
3618
3619 default:
3620 SetLastError(NTE_BAD_TYPE);
3621 return FALSE;
3622 }
3623}
3624
3625/******************************************************************************
3626 * CPSetProvParam (RSAENH.@)
3627 */
3628BOOL WINAPI RSAENH_CPSetProvParam(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
3629{
3630 FIXME("(stub)\n");
3631 return FALSE;
3632}
3633
3634/******************************************************************************
3635 * CPSignHash (RSAENH.@)
3636 *
3637 * Sign a hash object
3638 *
3639 * PARAMS
3640 * hProv [I] The key container, to which the hash object belongs.
3641 * hHash [I] The hash object to be signed.
3642 * dwKeySpec [I] AT_SIGNATURE or AT_KEYEXCHANGE: Key used to generate the signature.
3643 * sDescription [I] Should be NULL for security reasons.
3644 * dwFlags [I] 0, CRYPT_NOHASHOID or CRYPT_X931_FORMAT: Format of the signature.
3645 * pbSignature [O] Buffer, to which the signature will be stored. May be NULL to query SigLen.
3646 * pdwSigLen [I/O] Size of the buffer (in), Length of the signature (out)
3647 *
3648 * RETURNS
3649 * Success: TRUE
3650 * Failure: FALSE
3651 */
3652BOOL WINAPI RSAENH_CPSignHash(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwKeySpec,
3653 LPCWSTR sDescription, DWORD dwFlags, BYTE *pbSignature,
3654 DWORD *pdwSigLen)
3655{
3656 HCRYPTKEY hCryptKey;
3657 CRYPTKEY *pCryptKey;
3658 DWORD dwHashLen;
3659 BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
3660 ALG_ID aiAlgid;
3661
3662 TRACE("(hProv=%08lx, hHash=%08lx, dwKeySpec=%08x, sDescription=%s, dwFlags=%08x, "
3663 "pbSignature=%p, pdwSigLen=%p)\n", hProv, hHash, dwKeySpec, debugstr_w(sDescription),
3664 dwFlags, pbSignature, pdwSigLen);
3665
3666 if (dwFlags & ~(CRYPT_NOHASHOID|CRYPT_X931_FORMAT)) {
3667 SetLastError(NTE_BAD_FLAGS);
3668 return FALSE;
3669 }
3670
3671 if (!RSAENH_CPGetUserKey(hProv, dwKeySpec, &hCryptKey)) return FALSE;
3672
3673 if (!lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY,
3674 (OBJECTHDR**)&pCryptKey))
3675 {
3676 SetLastError(NTE_NO_KEY);
3677 return FALSE;
3678 }
3679
3680 if (!pbSignature) {
3681 *pdwSigLen = pCryptKey->dwKeyLen;
3682 return TRUE;
3683 }
3684 if (pCryptKey->dwKeyLen > *pdwSigLen)
3685 {
3686 SetLastError(ERROR_MORE_DATA);
3687 *pdwSigLen = pCryptKey->dwKeyLen;
3688 return FALSE;
3689 }
3690 *pdwSigLen = pCryptKey->dwKeyLen;
3691
3692 if (sDescription) {
3693 if (!RSAENH_CPHashData(hProv, hHash, (CONST BYTE*)sDescription,
3694 (DWORD)lstrlenW(sDescription)*sizeof(WCHAR), 0))
3695 {
3696 return FALSE;
3697 }
3698 }
3699
3700 dwHashLen = sizeof(DWORD);
3701 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_ALGID, (BYTE*)&aiAlgid, &dwHashLen, 0)) return FALSE;
3702
3703 dwHashLen = RSAENH_MAX_HASH_SIZE;
3704 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_HASHVAL, abHashValue, &dwHashLen, 0)) return FALSE;
3705
3706
3707 if (!build_hash_signature(pbSignature, *pdwSigLen, aiAlgid, abHashValue, dwHashLen, dwFlags)) {
3708 return FALSE;
3709 }
3710
3711 return encrypt_block_impl(pCryptKey->aiAlgid, PK_PRIVATE, &pCryptKey->context, pbSignature, pbSignature, RSAENH_ENCRYPT);
3712}
3713
3714/******************************************************************************
3715 * CPVerifySignature (RSAENH.@)
3716 *
3717 * Verify the signature of a hash object.
3718 *
3719 * PARAMS
3720 * hProv [I] The key container, to which the hash belongs.
3721 * hHash [I] The hash for which the signature is verified.
3722 * pbSignature [I] The binary signature.
3723 * dwSigLen [I] Length of the signature BLOB.
3724 * hPubKey [I] Public key used to verify the signature.
3725 * sDescription [I] Should be NULL for security reasons.
3726 * dwFlags [I] 0, CRYPT_NOHASHOID or CRYPT_X931_FORMAT: Format of the signature.
3727 *
3728 * RETURNS
3729 * Success: TRUE (Signature is valid)
3730 * Failure: FALSE (GetLastError() == NTE_BAD_SIGNATURE, if signature is invalid)
3731 */
3732BOOL WINAPI RSAENH_CPVerifySignature(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST BYTE *pbSignature,
3733 DWORD dwSigLen, HCRYPTKEY hPubKey, LPCWSTR sDescription,
3734 DWORD dwFlags)
3735{
3736 BYTE *pbConstructed = NULL, *pbDecrypted = NULL;
3737 CRYPTKEY *pCryptKey;
3738 DWORD dwHashLen;
3739 ALG_ID aiAlgid;
3740 BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
3741 BOOL res = FALSE;
3742
3743 TRACE("(hProv=%08lx, hHash=%08lx, pbSignature=%p, dwSigLen=%d, hPubKey=%08lx, sDescription=%s, "
3744 "dwFlags=%08x)\n", hProv, hHash, pbSignature, dwSigLen, hPubKey, debugstr_w(sDescription),
3745 dwFlags);
3746
3747 if (dwFlags & ~(CRYPT_NOHASHOID|CRYPT_X931_FORMAT)) {
3748 SetLastError(NTE_BAD_FLAGS);
3749 return FALSE;
3750 }
3751
3752 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
3753 {
3754 SetLastError(NTE_BAD_UID);
3755 return FALSE;
3756 }
3757
3758 if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY,
3759 (OBJECTHDR**)&pCryptKey))
3760 {
3761 SetLastError(NTE_BAD_KEY);
3762 return FALSE;
3763 }
3764
3765 /* in Microsoft implementation, the signature length is checked before
3766 * the signature pointer.
3767 */
3768 if (dwSigLen != pCryptKey->dwKeyLen)
3769 {
3770 SetLastError(NTE_BAD_SIGNATURE);
3771 return FALSE;
3772 }
3773
3774 if (!hHash || !pbSignature)
3775 {
3776 SetLastError(ERROR_INVALID_PARAMETER);
3777 return FALSE;
3778 }
3779
3780 if (sDescription) {
3781 if (!RSAENH_CPHashData(hProv, hHash, (CONST BYTE*)sDescription,
3782 (DWORD)lstrlenW(sDescription)*sizeof(WCHAR), 0))
3783 {
3784 return FALSE;
3785 }
3786 }
3787
3788 dwHashLen = sizeof(DWORD);
3789 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_ALGID, (BYTE*)&aiAlgid, &dwHashLen, 0)) return FALSE;
3790
3791 dwHashLen = RSAENH_MAX_HASH_SIZE;
3792 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_HASHVAL, abHashValue, &dwHashLen, 0)) return FALSE;
3793
3794 pbConstructed = HeapAlloc(GetProcessHeap(), 0, dwSigLen);
3795 if (!pbConstructed) {
3796 SetLastError(NTE_NO_MEMORY);
3797 goto cleanup;
3798 }
3799
3800 pbDecrypted = HeapAlloc(GetProcessHeap(), 0, dwSigLen);
3801 if (!pbDecrypted) {
3802 SetLastError(NTE_NO_MEMORY);
3803 goto cleanup;
3804 }
3805
3806 if (!encrypt_block_impl(pCryptKey->aiAlgid, PK_PUBLIC, &pCryptKey->context, pbSignature, pbDecrypted,
3807 RSAENH_DECRYPT))
3808 {
3809 goto cleanup;
3810 }
3811
3812 if (!build_hash_signature(pbConstructed, dwSigLen, aiAlgid, abHashValue, dwHashLen, dwFlags)) {
3813 goto cleanup;
3814 }
3815
3816 if (memcmp(pbDecrypted, pbConstructed, dwSigLen)) {
3817 SetLastError(NTE_BAD_SIGNATURE);
3818 goto cleanup;
3819 }
3820
3821 res = TRUE;
3822cleanup:
3823 HeapFree(GetProcessHeap(), 0, pbConstructed);
3824 HeapFree(GetProcessHeap(), 0, pbDecrypted);
3825 return res;
3826}
3827
3828static const WCHAR szProviderKeys[6][116] = {
3829 { 'S','o','f','t','w','a','r','e','\\',
3830 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3831 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3832 'i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ','B','a','s',
3833 'e',' ','C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r',
3834 'o','v','i','d','e','r',' ','v','1','.','0',0 },
3835 { 'S','o','f','t','w','a','r','e','\\',
3836 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3837 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3838 'i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ',
3839 'E','n','h','a','n','c','e','d',
3840 ' ','C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r',
3841 'o','v','i','d','e','r',' ','v','1','.','0',0 },
3842 { 'S','o','f','t','w','a','r','e','\\',
3843 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3844 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3845 'i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ','S','t','r','o','n','g',
3846 ' ','C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r',
3847 'o','v','i','d','e','r',0 },
3848 { 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
3849 'C','r','y','p','t','o','g','r','a','p','h','y','\\','D','e','f','a','u','l','t','s','\\',
3850 'P','r','o','v','i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ',
3851 'R','S','A',' ','S','C','h','a','n','n','e','l',' ',
3852 'C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r','o','v','i','d','e','r',0 },
3853 { 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
3854 'C','r','y','p','t','o','g','r','a','p','h','y','\\','D','e','f','a','u','l','t','s','\\',
3855 'P','r','o','v','i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ',
3856 'E','n','h','a','n','c','e','d',' ','R','S','A',' ','a','n','d',' ','A','E','S',' ',
3857 'C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r','o','v','i','d','e','r',0 },
3858 { 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
3859 'C','r','y','p','t','o','g','r','a','p','h','y','\\','D','e','f','a','u','l','t','s','\\',
3860 'P','r','o','v','i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ',
3861 'E','n','h','a','n','c','e','d',' ','R','S','A',' ','a','n','d',' ','A','E','S',' ',
3862 'C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r','o','v','i','d','e','r',
3863 ' ','(','P','r','o','t','o','t','y','p','e',')',0 }
3864};
3865static const WCHAR szDefaultKeys[3][65] = {
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','0','1',0 },
3870 { 'S','o','f','t','w','a','r','e','\\',
3871 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3872 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3873 'i','d','e','r',' ','T','y','p','e','s','\\','T','y','p','e',' ','0','1','2',0 },
3874 { 'S','o','f','t','w','a','r','e','\\',
3875 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3876 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3877 'i','d','e','r',' ','T','y','p','e','s','\\','T','y','p','e',' ','0','2','4',0 }
3878};
3879
3880
3881/******************************************************************************
3882 * DllRegisterServer (RSAENH.@)
3883 *
3884 * Dll self registration.
3885 *
3886 * PARAMS
3887 *
3888 * RETURNS
3889 * Success: S_OK.
3890 * Failure: != S_OK
3891 *
3892 * NOTES
3893 * Registers the following keys:
3894 * - HKLM\Software\Microsoft\Cryptography\Defaults\Provider\
3895 * Microsoft Base Cryptographic Provider v1.0
3896 * - HKLM\Software\Microsoft\Cryptography\Defaults\Provider\
3897 * Microsoft Enhanced Cryptographic Provider
3898 * - HKLM\Software\Microsoft\Cryptography\Defaults\Provider\
3899 * Microsoft Strong Cryptographpic Provider
3900 * - HKLM\Software\Microsoft\Cryptography\Defaults\Provider Types\Type 001
3901 */
3902HRESULT WINAPI DllRegisterServer(void)
3903{
3904 HKEY key;
3905 DWORD dp;
3906 long apiRet;
3907 int i;
3908
3909 for (i=0; i<6; i++) {
3910 apiRet = RegCreateKeyExW(HKEY_LOCAL_MACHINE, szProviderKeys[i], 0, NULL,
3911 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dp);
3912
3913 if (apiRet == ERROR_SUCCESS)
3914 {
3915 if (dp == REG_CREATED_NEW_KEY)
3916 {
3917 static const WCHAR szImagePath[] = { 'I','m','a','g','e',' ','P','a','t','h',0 };
3918 static const WCHAR szRSABase[] = { 'r','s','a','e','n','h','.','d','l','l',0 };
3919 static const WCHAR szType[] = { 'T','y','p','e',0 };
3920 static const WCHAR szSignature[] = { 'S','i','g','n','a','t','u','r','e',0 };
3921 DWORD type, sign;
3922
3923 switch(i)
3924 {
3925 case 3:
3926 type=PROV_RSA_SCHANNEL;
3927 break;
3928 case 4:
3929 case 5:
3930 type=PROV_RSA_AES;
3931 break;
3932 default:
3933 type=PROV_RSA_FULL;
3934 break;
3935 }
3936 sign = 0xdeadbeef;
3937 RegSetValueExW(key, szImagePath, 0, REG_SZ, (const BYTE *)szRSABase,
3938 (lstrlenW(szRSABase) + 1) * sizeof(WCHAR));
3939 RegSetValueExW(key, szType, 0, REG_DWORD, (LPBYTE)&type, sizeof(type));
3940 RegSetValueExW(key, szSignature, 0, REG_BINARY, (LPBYTE)&sign, sizeof(sign));
3941 }
3942 RegCloseKey(key);
3943 }
3944 }
3945
3946 for (i=0; i<3; i++) {
3947 apiRet = RegCreateKeyExW(HKEY_LOCAL_MACHINE, szDefaultKeys[i], 0, NULL,
3948 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dp);
3949 if (apiRet == ERROR_SUCCESS)
3950 {
3951 if (dp == REG_CREATED_NEW_KEY)
3952 {
3953 static const WCHAR szName[] = { 'N','a','m','e',0 };
3954 static const WCHAR szRSAName[3][54] = {
3955 { 'M','i','c','r','o','s','o','f','t',' ', 'B','a','s','e',' ',
3956 'C','r','y','p','t','o','g','r','a','p','h','i','c',' ',
3957 'P','r','o','v','i','d','e','r',' ','v','1','.','0',0 },
3958 { 'M','i','c','r','o','s','o','f','t',' ','R','S','A',' ',
3959 'S','C','h','a','n','n','e','l',' ',
3960 'C','r','y','p','t','o','g','r','a','p','h','i','c',' ',
3961 'P','r','o','v','i','d','e','r',0 },
3962 { 'M','i','c','r','o','s','o','f','t',' ','E','n','h','a','n','c','e','d',' ',
3963 'R','S','A',' ','a','n','d',' ','A','E','S',' ',
3964 'C','r','y','p','t','o','g','r','a','p','h','i','c',' ',
3965 'P','r','o','v','i','d','e','r',0 } };
3966 static const WCHAR szTypeName[] = { 'T','y','p','e','N','a','m','e',0 };
3967 static const WCHAR szRSATypeName[3][38] = {
3968 { 'R','S','A',' ','F','u','l','l',' ',
3969 '(','S','i','g','n','a','t','u','r','e',' ','a','n','d',' ',
3970 'K','e','y',' ','E','x','c','h','a','n','g','e',')',0 },
3971 { 'R','S','A',' ','S','C','h','a','n','n','e','l',0 },
3972 { 'R','S','A',' ','F','u','l','l',' ','a','n','d',' ','A','E','S',0 } };
3973
3974 RegSetValueExW(key, szName, 0, REG_SZ,
3975 (const BYTE *)szRSAName[i], lstrlenW(szRSAName[i])*sizeof(WCHAR)+sizeof(WCHAR));
3976 RegSetValueExW(key, szTypeName, 0, REG_SZ,
3977 (const BYTE *)szRSATypeName[i], lstrlenW(szRSATypeName[i])*sizeof(WCHAR)+sizeof(WCHAR));
3978 }
3979 }
3980 RegCloseKey(key);
3981 }
3982
3983 return HRESULT_FROM_WIN32(apiRet);
3984}
3985
3986/******************************************************************************
3987 * DllUnregisterServer (RSAENH.@)
3988 *
3989 * Dll self unregistration.
3990 *
3991 * PARAMS
3992 *
3993 * RETURNS
3994 * Success: S_OK
3995 *
3996 * NOTES
3997 * For the relevant keys see DllRegisterServer.
3998 */
3999HRESULT WINAPI DllUnregisterServer(void)
4000{
4001 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[0]);
4002 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[1]);
4003 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[2]);
4004 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[3]);
4005 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[4]);
4006 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[5]);
4007 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szDefaultKeys[0]);
4008 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szDefaultKeys[1]);
4009 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szDefaultKeys[2]);
4010 return S_OK;
4011}
Note: See TracBrowser for help on using the repository browser.