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