3 * RSAENH - RSA encryption for Wine
5 * Copyright 2002 TransGaming Technologies (David Hammerton)
6 * Copyright 2004 Mike McCormack for CodeWeavers
7 * Copyright 2004, 2005 Michael Jung
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wine/port.h"
26 #include "wine/library.h"
27 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
42 /******************************************************************************
43 * CRYPTHASH - hash objects
45 #define RSAENH_MAGIC_HASH 0x85938417u
46 #define RSAENH_MAX_HASH_SIZE 104
47 #define RSAENH_HASHSTATE_IDLE 0
48 #define RSAENH_HASHSTATE_HASHING 1
49 #define RSAENH_HASHSTATE_FINISHED 2
50 typedef struct _RSAENH_TLS1PRF_PARAMS
52 CRYPT_DATA_BLOB blobLabel;
53 CRYPT_DATA_BLOB blobSeed;
54 } RSAENH_TLS1PRF_PARAMS;
56 typedef struct tagCRYPTHASH
65 BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
67 RSAENH_TLS1PRF_PARAMS tpPRFParams;
70 /******************************************************************************
71 * CRYPTKEY - key objects
73 #define RSAENH_MAGIC_KEY 0x73620457u
74 #define RSAENH_MAX_KEY_SIZE 48
75 #define RSAENH_MAX_BLOCK_SIZE 24
76 #define RSAENH_KEYSTATE_IDLE 0
77 #define RSAENH_KEYSTATE_ENCRYPTING 1
78 #define RSAENH_KEYSTATE_DECRYPTING 2
79 #define RSAENH_KEYSTATE_MASTERKEY 3
80 typedef struct _RSAENH_SCHANNEL_INFO
82 SCHANNEL_ALG saEncAlg;
83 SCHANNEL_ALG saMACAlg;
84 CRYPT_DATA_BLOB blobClientRandom;
85 CRYPT_DATA_BLOB blobServerRandom;
86 } RSAENH_SCHANNEL_INFO;
88 typedef struct tagCRYPTKEY
101 BYTE abKeyValue[RSAENH_MAX_KEY_SIZE];
102 BYTE abInitVector[RSAENH_MAX_BLOCK_SIZE];
103 BYTE abChainVector[RSAENH_MAX_BLOCK_SIZE];
104 RSAENH_SCHANNEL_INFO siSChannelInfo;
107 /******************************************************************************
108 * KEYCONTAINER - key containers
110 #define RSAENH_PERSONALITY_BASE 0u
111 #define RSAENH_PERSONALITY_STRONG 1u
112 #define RSAENH_PERSONALITY_ENHANCED 2u
113 #define RSAENH_PERSONALITY_SCHANNEL 3u
115 #define RSAENH_MAGIC_CONTAINER 0x26384993u
116 typedef struct tagKEYCONTAINER
122 CHAR szName[MAX_PATH];
123 CHAR szProvName[MAX_PATH];
124 HCRYPTKEY hKeyExchangeKeyPair;
125 HCRYPTKEY hSignatureKeyPair;
128 /******************************************************************************
129 * Some magic constants
131 #define RSAENH_ENCRYPT 1
132 #define RSAENH_DECRYPT 0
133 #define RSAENH_HMAC_DEF_IPAD_CHAR 0x36
134 #define RSAENH_HMAC_DEF_OPAD_CHAR 0x5c
135 #define RSAENH_HMAC_DEF_PAD_LEN 64
136 #define RSAENH_DES_EFFECTIVE_KEYLEN 56
137 #define RSAENH_DES_STORAGE_KEYLEN 64
138 #define RSAENH_3DES112_EFFECTIVE_KEYLEN 112
139 #define RSAENH_3DES112_STORAGE_KEYLEN 128
140 #define RSAENH_3DES_EFFECTIVE_KEYLEN 168
141 #define RSAENH_3DES_STORAGE_KEYLEN 192
142 #define RSAENH_MAGIC_RSA2 0x32415352
143 #define RSAENH_MAGIC_RSA1 0x31415352
144 #define RSAENH_PKC_BLOCKTYPE 0x02
145 #define RSAENH_SSL3_VERSION_MAJOR 3
146 #define RSAENH_SSL3_VERSION_MINOR 0
147 #define RSAENH_TLS1_VERSION_MAJOR 3
148 #define RSAENH_TLS1_VERSION_MINOR 1
149 #define RSAENH_REGKEY "Software\\Wine\\Crypto\\RSA\\%s"
151 #define RSAENH_MIN(a,b) ((a)<(b)?(a):(b))
152 /******************************************************************************
153 * aProvEnumAlgsEx - Defines the capabilities of the CSP personalities.
155 #define RSAENH_MAX_ENUMALGS 20
156 #define RSAENH_PCT1_SSL2_SSL3_TLS1 (CRYPT_FLAG_PCT1|CRYPT_FLAG_SSL2|CRYPT_FLAG_SSL3|CRYPT_FLAG_TLS1)
157 PROV_ENUMALGS_EX aProvEnumAlgsEx[4][RSAENH_MAX_ENUMALGS+1] =
160 {CALG_RC2, 40, 40, 56,0, 4,"RC2", 24,"RSA Data Security's RC2"},
161 {CALG_RC4, 40, 40, 56,0, 4,"RC4", 24,"RSA Data Security's RC4"},
162 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"},
163 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"},
164 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"},
165 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"},
166 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"},
167 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
168 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
169 {CALG_RSA_SIGN, 512,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
170 {CALG_RSA_KEYX, 512,384, 1024,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
171 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
172 {0, 0, 0, 0,0, 1,"", 1,""}
175 {CALG_RC2, 128, 40, 128,0, 4,"RC2", 24,"RSA Data Security's RC2"},
176 {CALG_RC4, 128, 40, 128,0, 4,"RC4", 24,"RSA Data Security's RC4"},
177 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"},
178 {CALG_3DES_112, 112,112, 112,0, 13,"3DES TWO KEY",19,"Two Key Triple DES"},
179 {CALG_3DES, 168,168, 168,0, 5,"3DES", 21,"Three Key Triple DES"},
180 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"},
181 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"},
182 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"},
183 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"},
184 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
185 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
186 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
187 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
188 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
189 {0, 0, 0, 0,0, 1,"", 1,""}
192 {CALG_RC2, 128, 40, 128,0, 4,"RC2", 24,"RSA Data Security's RC2"},
193 {CALG_RC4, 128, 40, 128,0, 4,"RC4", 24,"RSA Data Security's RC4"},
194 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"},
195 {CALG_3DES_112, 112,112, 112,0, 13,"3DES TWO KEY",19,"Two Key Triple DES"},
196 {CALG_3DES, 168,168, 168,0, 5,"3DES", 21,"Three Key Triple DES"},
197 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"},
198 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"},
199 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"},
200 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"},
201 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
202 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
203 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"},
204 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"},
205 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
206 {0, 0, 0, 0,0, 1,"", 1,""}
209 {CALG_RC2, 128, 40, 128,RSAENH_PCT1_SSL2_SSL3_TLS1, 4,"RC2", 24,"RSA Data Security's RC2"},
210 {CALG_RC4, 128, 40, 128,RSAENH_PCT1_SSL2_SSL3_TLS1, 4,"RC4", 24,"RSA Data Security's RC4"},
211 {CALG_DES, 56, 56, 56,RSAENH_PCT1_SSL2_SSL3_TLS1, 4,"DES", 31,"Data Encryption Standard (DES)"},
212 {CALG_3DES_112, 112,112, 112,RSAENH_PCT1_SSL2_SSL3_TLS1,13,"3DES TWO KEY",19,"Two Key Triple DES"},
213 {CALG_3DES, 168,168, 168,RSAENH_PCT1_SSL2_SSL3_TLS1, 5,"3DES", 21,"Three Key Triple DES"},
214 {CALG_SHA,160,160,160,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,6,"SHA-1",30,"Secure Hash Algorithm (SHA-1)"},
215 {CALG_MD5,128,128,128,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,4,"MD5",23,"Message Digest 5 (MD5)"},
216 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"},
217 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"},
218 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,9,"RSA_SIGN",14,"RSA Signature"},
219 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,9,"RSA_KEYX",17,"RSA Key Exchange"},
220 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"},
221 {CALG_PCT1_MASTER,128,128,128,CRYPT_FLAG_PCT1, 12,"PCT1 MASTER",12,"PCT1 Master"},
222 {CALG_SSL2_MASTER,40,40, 192,CRYPT_FLAG_SSL2, 12,"SSL2 MASTER",12,"SSL2 Master"},
223 {CALG_SSL3_MASTER,384,384,384,CRYPT_FLAG_SSL3, 12,"SSL3 MASTER",12,"SSL3 Master"},
224 {CALG_TLS1_MASTER,384,384,384,CRYPT_FLAG_TLS1, 12,"TLS1 MASTER",12,"TLS1 Master"},
225 {CALG_SCHANNEL_MASTER_HASH,0,0,-1,0, 16,"SCH MASTER HASH",21,"SChannel Master Hash"},
226 {CALG_SCHANNEL_MAC_KEY,0,0,-1,0, 12,"SCH MAC KEY",17,"SChannel MAC Key"},
227 {CALG_SCHANNEL_ENC_KEY,0,0,-1,0, 12,"SCH ENC KEY",24,"SChannel Encryption Key"},
228 {CALG_TLS1PRF, 0, 0, -1,0, 9,"TLS1 PRF", 28,"TLS1 Pseudo Random Function"},
229 {0, 0, 0, 0,0, 1,"", 1,""}
233 /******************************************************************************
234 * API forward declarations
237 RSAENH_CPGetKeyParam(
268 RSAENH_CPSetHashParam(
272 BYTE *pbData, DWORD dwFlags
276 RSAENH_CPGetHashParam(
286 RSAENH_CPDestroyHash(
321 /******************************************************************************
322 * CSP's handle table (used by all acquired key containers)
324 static HANDLETABLE handle_table;
326 /******************************************************************************
329 * Initializes and destroys the handle table for the CSP's handles.
331 int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
335 case DLL_PROCESS_ATTACH:
336 init_handle_table(&handle_table);
339 case DLL_PROCESS_DETACH:
340 destroy_handle_table(&handle_table);
346 /******************************************************************************
347 * copy_param [Internal]
349 * Helper function that supports the standard WINAPI protocol for querying data
353 * pbBuffer [O] Buffer where the queried parameter is copied to, if it is large enough.
354 * May be NUL if the required buffer size is to be queried only.
355 * pdwBufferSize [I/O] In: Size of the buffer at pbBuffer
356 * Out: Size of parameter pbParam
357 * pbParam [I] Parameter value.
358 * dwParamSize [I] Size of pbParam
361 * Success: TRUE (pbParam was copied into pbBuffer or pbBuffer is NULL)
362 * Failure: FALSE (pbBuffer is not large enough to hold pbParam). Last error: ERROR_MORE_DATA
364 static inline BOOL copy_param(
365 BYTE *pbBuffer, DWORD *pdwBufferSize, CONST BYTE *pbParam, DWORD dwParamSize)
369 if (dwParamSize > *pdwBufferSize)
371 SetLastError(ERROR_MORE_DATA);
372 *pdwBufferSize = dwParamSize;
375 memcpy(pbBuffer, pbParam, dwParamSize);
377 *pdwBufferSize = dwParamSize;
381 /******************************************************************************
382 * get_algid_info [Internal]
384 * Query CSP capabilities for a given crypto algorithm.
387 * hProv [I] Handle to a key container of the CSP whose capabilities are to be queried.
388 * algid [I] Identifier of the crypto algorithm about which information is requested.
391 * Success: Pointer to a PROV_ENUMALGS_EX struct containing information about the crypto algorithm.
392 * Failure: NULL (algid not supported)
394 static inline const PROV_ENUMALGS_EX* get_algid_info(HCRYPTPROV hProv, ALG_ID algid) {
395 PROV_ENUMALGS_EX *iterator;
396 KEYCONTAINER *pKeyContainer;
398 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER, (OBJECTHDR**)&pKeyContainer)) {
399 SetLastError(NTE_BAD_UID);
403 for (iterator = aProvEnumAlgsEx[pKeyContainer->dwPersonality]; iterator->aiAlgid; iterator++) {
404 if (iterator->aiAlgid == algid) return iterator;
407 SetLastError(NTE_BAD_ALGID);
411 /******************************************************************************
412 * copy_data_blob [Internal]
414 * deeply copies a DATA_BLOB
417 * dst [O] That's where the blob will be copied to
418 * src [I] Source blob
422 * Failure: FALSE (GetLastError() == NTE_NO_MEMORY
425 * Use free_data_blob to release resources occupied by copy_data_blob.
427 static inline BOOL copy_data_blob(PCRYPT_DATA_BLOB dst, CONST PCRYPT_DATA_BLOB src) {
428 dst->pbData = (BYTE*)HeapAlloc(GetProcessHeap(), 0, src->cbData);
430 SetLastError(NTE_NO_MEMORY);
433 dst->cbData = src->cbData;
434 memcpy(dst->pbData, src->pbData, src->cbData);
438 /******************************************************************************
439 * concat_data_blobs [Internal]
441 * Concatenates two blobs
444 * dst [O] The new blob will be copied here
445 * src1 [I] Prefix blob
446 * src2 [I] Appendix blob
450 * Failure: FALSE (GetLastError() == NTE_NO_MEMORY)
453 * Release resources occupied by concat_data_blobs with free_data_blobs
455 static inline BOOL concat_data_blobs(PCRYPT_DATA_BLOB dst, CONST PCRYPT_DATA_BLOB src1,
456 CONST PCRYPT_DATA_BLOB src2)
458 dst->cbData = src1->cbData + src2->cbData;
459 dst->pbData = (BYTE*)HeapAlloc(GetProcessHeap(), 0, dst->cbData);
461 SetLastError(NTE_NO_MEMORY);
464 memcpy(dst->pbData, src1->pbData, src1->cbData);
465 memcpy(dst->pbData + src1->cbData, src2->pbData, src2->cbData);
469 /******************************************************************************
470 * free_data_blob [Internal]
472 * releases resource occupied by a dynamically allocated CRYPT_DATA_BLOB
475 * pBlob [I] Heap space occupied by pBlob->pbData is released
477 static inline void free_data_blob(PCRYPT_DATA_BLOB pBlob) {
478 HeapFree(GetProcessHeap(), 0, pBlob->pbData);
481 /******************************************************************************
482 * init_data_blob [Internal]
484 static inline void init_data_blob(PCRYPT_DATA_BLOB pBlob) {
485 pBlob->pbData = NULL;
489 /******************************************************************************
490 * free_hmac_info [Internal]
492 * Deeply free an HMAC_INFO struct.
495 * hmac_info [I] Pointer to the HMAC_INFO struct to be freed.
498 * See Internet RFC 2104 for details on the HMAC algorithm.
500 static inline void free_hmac_info(PHMAC_INFO hmac_info) {
501 if (!hmac_info) return;
502 HeapFree(GetProcessHeap(), 0, hmac_info->pbInnerString);
503 HeapFree(GetProcessHeap(), 0, hmac_info->pbOuterString);
504 HeapFree(GetProcessHeap(), 0, hmac_info);
507 /******************************************************************************
508 * copy_hmac_info [Internal]
510 * Deeply copy an HMAC_INFO struct
513 * dst [O] Pointer to a location where the pointer to the HMAC_INFO copy will be stored.
514 * src [I] Pointer to the HMAC_INFO struct to be copied.
521 * See Internet RFC 2104 for details on the HMAC algorithm.
523 static BOOL copy_hmac_info(PHMAC_INFO *dst, PHMAC_INFO src) {
524 if (!src) return FALSE;
525 *dst = (PHMAC_INFO)HeapAlloc(GetProcessHeap(), 0, sizeof(HMAC_INFO));
526 if (!*dst) return FALSE;
527 memcpy(*dst, src, sizeof(HMAC_INFO));
528 (*dst)->pbInnerString = NULL;
529 (*dst)->pbOuterString = NULL;
530 if ((*dst)->cbInnerString == 0) (*dst)->cbInnerString = RSAENH_HMAC_DEF_PAD_LEN;
531 (*dst)->pbInnerString = (BYTE*)HeapAlloc(GetProcessHeap(), 0, (*dst)->cbInnerString);
532 if (!(*dst)->pbInnerString) {
533 free_hmac_info(*dst);
536 if (src->cbInnerString)
537 memcpy((*dst)->pbInnerString, src->pbInnerString, src->cbInnerString);
539 memset((*dst)->pbInnerString, RSAENH_HMAC_DEF_IPAD_CHAR, RSAENH_HMAC_DEF_PAD_LEN);
540 if ((*dst)->cbOuterString == 0) (*dst)->cbOuterString = RSAENH_HMAC_DEF_PAD_LEN;
541 (*dst)->pbOuterString = (BYTE*)HeapAlloc(GetProcessHeap(), 0, (*dst)->cbOuterString);
542 if (!(*dst)->pbOuterString) {
543 free_hmac_info(*dst);
546 if (src->cbOuterString)
547 memcpy((*dst)->pbOuterString, src->pbOuterString, src->cbOuterString);
549 memset((*dst)->pbOuterString, RSAENH_HMAC_DEF_OPAD_CHAR, RSAENH_HMAC_DEF_PAD_LEN);
553 /******************************************************************************
554 * destroy_hash [Internal]
556 * Destructor for hash objects
559 * pCryptHash [I] Pointer to the hash object to be destroyed.
560 * Will be invalid after function returns!
562 static void destroy_hash(OBJECTHDR *pObject)
564 CRYPTHASH *pCryptHash = (CRYPTHASH*)pObject;
566 free_hmac_info(pCryptHash->pHMACInfo);
567 free_data_blob(&pCryptHash->tpPRFParams.blobLabel);
568 free_data_blob(&pCryptHash->tpPRFParams.blobSeed);
569 HeapFree(GetProcessHeap(), 0, pCryptHash);
572 /******************************************************************************
573 * init_hash [Internal]
575 * Initialize (or reset) a hash object
578 * pCryptHash [I] The hash object to be initialized.
580 static inline BOOL init_hash(CRYPTHASH *pCryptHash) {
583 switch (pCryptHash->aiAlgid)
586 if (pCryptHash->pHMACInfo) {
587 const PROV_ENUMALGS_EX *pAlgInfo;
589 pAlgInfo = get_algid_info(pCryptHash->hProv, pCryptHash->pHMACInfo->HashAlgid);
590 if (!pAlgInfo) return FALSE;
591 pCryptHash->dwHashSize = pAlgInfo->dwDefaultLen >> 3;
592 init_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context);
593 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
594 pCryptHash->pHMACInfo->pbInnerString,
595 pCryptHash->pHMACInfo->cbInnerString);
600 dwLen = sizeof(DWORD);
601 RSAENH_CPGetKeyParam(pCryptHash->hProv, pCryptHash->hKey, KP_BLOCKLEN,
602 (BYTE*)&pCryptHash->dwHashSize, &dwLen, 0);
603 pCryptHash->dwHashSize >>= 3;
607 return init_hash_impl(pCryptHash->aiAlgid, &pCryptHash->context);
611 /******************************************************************************
612 * update_hash [Internal]
614 * Hashes the given data and updates the hash object's state accordingly
617 * pCryptHash [I] Hash object to be updated.
618 * pbData [I] Pointer to data stream to be hashed.
619 * dwDataLen [I] Length of data stream.
621 static inline void update_hash(CRYPTHASH *pCryptHash, CONST BYTE *pbData, DWORD dwDataLen) {
624 switch (pCryptHash->aiAlgid)
627 if (pCryptHash->pHMACInfo)
628 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
633 pbTemp = (BYTE*)HeapAlloc(GetProcessHeap(), 0, dwDataLen);
635 memcpy(pbTemp, pbData, dwDataLen);
636 RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, (HCRYPTHASH)NULL, FALSE, 0,
637 pbTemp, &dwDataLen, dwDataLen);
638 HeapFree(GetProcessHeap(), 0, pbTemp);
642 update_hash_impl(pCryptHash->aiAlgid, &pCryptHash->context, pbData, dwDataLen);
646 /******************************************************************************
647 * finalize_hash [Internal]
649 * Finalizes the hash, after all data has been hashed with update_hash.
650 * No additional data can be hashed afterwards until the hash gets initialized again.
653 * pCryptHash [I] Hash object to be finalized.
655 static inline void finalize_hash(CRYPTHASH *pCryptHash) {
658 switch (pCryptHash->aiAlgid)
661 if (pCryptHash->pHMACInfo) {
662 BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
664 finalize_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
665 pCryptHash->abHashValue);
666 memcpy(abHashValue, pCryptHash->abHashValue, pCryptHash->dwHashSize);
667 init_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context);
668 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
669 pCryptHash->pHMACInfo->pbOuterString,
670 pCryptHash->pHMACInfo->cbOuterString);
671 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
672 abHashValue, pCryptHash->dwHashSize);
673 finalize_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context,
674 pCryptHash->abHashValue);
680 RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, (HCRYPTHASH)NULL, TRUE, 0,
681 pCryptHash->abHashValue, &dwDataLen, pCryptHash->dwHashSize);
685 finalize_hash_impl(pCryptHash->aiAlgid, &pCryptHash->context, pCryptHash->abHashValue);
689 /******************************************************************************
690 * destroy_key [Internal]
692 * Destructor for key objects
695 * pCryptKey [I] Pointer to the key object to be destroyed.
696 * Will be invalid after function returns!
698 static void destroy_key(OBJECTHDR *pObject)
700 CRYPTKEY *pCryptKey = (CRYPTKEY*)pObject;
702 free_key_impl(pCryptKey->aiAlgid, &pCryptKey->context);
703 free_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom);
704 free_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom);
705 HeapFree(GetProcessHeap(), 0, pCryptKey);
708 /******************************************************************************
709 * setup_key [Internal]
711 * Initialize (or reset) a key object
714 * pCryptKey [I] The key object to be initialized.
716 static inline void setup_key(CRYPTKEY *pCryptKey) {
717 pCryptKey->dwState = RSAENH_KEYSTATE_IDLE;
718 memcpy(pCryptKey->abChainVector, pCryptKey->abInitVector, sizeof(pCryptKey->abChainVector));
719 setup_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen,
720 pCryptKey->dwSaltLen, pCryptKey->abKeyValue);
723 /******************************************************************************
726 * Creates a new key object without assigning the actual binary key value.
727 * This is done by CPDeriveKey, CPGenKey or CPImportKey, which call this function.
730 * hProv [I] Handle to the provider to which the created key will belong.
731 * aiAlgid [I] The new key shall use the crypto algorithm idenfied by aiAlgid.
732 * dwFlags [I] Upper 16 bits give the key length.
733 * Lower 16 bits: CRYPT_CREATE_SALT, CRYPT_NO_SALT
734 * ppCryptKey [O] Pointer to the created key
737 * Success: Handle to the created key.
738 * Failure: INVALID_HANDLE_VALUE
740 static HCRYPTKEY new_key(HCRYPTPROV hProv, ALG_ID aiAlgid, DWORD dwFlags, CRYPTKEY **ppCryptKey)
744 DWORD dwKeyLen = HIWORD(dwFlags);
745 const PROV_ENUMALGS_EX *peaAlgidInfo;
750 * Retrieve the CSP's capabilities for the given ALG_ID value
752 peaAlgidInfo = get_algid_info(hProv, aiAlgid);
753 if (!peaAlgidInfo) return (HCRYPTKEY)INVALID_HANDLE_VALUE;
756 * Assume the default key length, if none is specified explicitly
758 if (dwKeyLen == 0) dwKeyLen = peaAlgidInfo->dwDefaultLen;
761 * Check if the requested key length is supported by the current CSP.
762 * Adjust key length's for DES algorithms.
766 if (dwKeyLen == RSAENH_DES_EFFECTIVE_KEYLEN) {
767 dwKeyLen = RSAENH_DES_STORAGE_KEYLEN;
769 if (dwKeyLen != RSAENH_DES_STORAGE_KEYLEN) {
770 SetLastError(NTE_BAD_FLAGS);
771 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
776 if (dwKeyLen == RSAENH_3DES112_EFFECTIVE_KEYLEN) {
777 dwKeyLen = RSAENH_3DES112_STORAGE_KEYLEN;
779 if (dwKeyLen != RSAENH_3DES112_STORAGE_KEYLEN) {
780 SetLastError(NTE_BAD_FLAGS);
781 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
786 if (dwKeyLen == RSAENH_3DES_EFFECTIVE_KEYLEN) {
787 dwKeyLen = RSAENH_3DES_STORAGE_KEYLEN;
789 if (dwKeyLen != RSAENH_3DES_STORAGE_KEYLEN) {
790 SetLastError(NTE_BAD_FLAGS);
791 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
797 dwKeyLen > peaAlgidInfo->dwMaxLen ||
798 dwKeyLen < peaAlgidInfo->dwMinLen)
800 SetLastError(NTE_BAD_FLAGS);
801 return (HCRYPTKEY)INVALID_HANDLE_VALUE;
805 hCryptKey = (HCRYPTKEY)new_object(&handle_table, sizeof(CRYPTKEY), RSAENH_MAGIC_KEY,
806 destroy_key, (OBJECTHDR**)&pCryptKey);
807 if (hCryptKey != (HCRYPTKEY)INVALID_HANDLE_VALUE)
809 pCryptKey->aiAlgid = aiAlgid;
810 pCryptKey->hProv = hProv;
811 pCryptKey->dwModeBits = 0;
812 pCryptKey->dwPermissions = CRYPT_ENCRYPT | CRYPT_DECRYPT | CRYPT_READ | CRYPT_WRITE |
814 pCryptKey->dwKeyLen = dwKeyLen >> 3;
815 if ((dwFlags & CRYPT_CREATE_SALT) || (dwKeyLen == 40 && !(dwFlags & CRYPT_NO_SALT)))
816 pCryptKey->dwSaltLen = 16 /*FIXME*/ - pCryptKey->dwKeyLen;
818 pCryptKey->dwSaltLen = 0;
819 memset(pCryptKey->abKeyValue, 0, sizeof(pCryptKey->abKeyValue));
820 memset(pCryptKey->abInitVector, 0, sizeof(pCryptKey->abInitVector));
821 init_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom);
822 init_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom);
826 case CALG_PCT1_MASTER:
827 case CALG_SSL2_MASTER:
828 case CALG_SSL3_MASTER:
829 case CALG_TLS1_MASTER:
831 pCryptKey->dwBlockLen = 0;
832 pCryptKey->dwMode = 0;
839 pCryptKey->dwBlockLen = 8;
840 pCryptKey->dwMode = CRYPT_MODE_CBC;
845 pCryptKey->dwBlockLen = dwKeyLen >> 3;
846 pCryptKey->dwMode = 0;
850 *ppCryptKey = pCryptKey;
856 /******************************************************************************
857 * destroy_key_container [Internal]
859 * Destructor for key containers. The user's signature and key exchange private
860 * keys are stored in the registry _IN_PLAINTEXT_.
863 * pObjectHdr [I] Pointer to the key container to be destroyed.
865 static void destroy_key_container(OBJECTHDR *pObjectHdr)
867 KEYCONTAINER *pKeyContainer = (KEYCONTAINER*)pObjectHdr;
869 CHAR szRSABase[MAX_PATH];
874 if (!(pKeyContainer->dwFlags & CRYPT_VERIFYCONTEXT)) {
875 /* On WinXP, persistent keys are stored in a file located at:
876 * $AppData$\\Microsoft\\Crypto\\RSA\\$SID$\\some_hex_string
878 sprintf(szRSABase, RSAENH_REGKEY, pKeyContainer->szName);
880 if (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET) {
881 hRootKey = HKEY_LOCAL_MACHINE;
883 hRootKey = HKEY_CURRENT_USER;
886 if (RegCreateKeyExA(hRootKey, szRSABase, 0, NULL, REG_OPTION_NON_VOLATILE,
887 KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS)
889 if (lookup_handle(&handle_table, pKeyContainer->hKeyExchangeKeyPair, RSAENH_MAGIC_KEY,
892 if (RSAENH_CPExportKey(pKey->hProv, pKeyContainer->hKeyExchangeKeyPair, 0,
893 PRIVATEKEYBLOB, 0, 0, &dwLen))
895 pbKey = (BYTE*)HeapAlloc(GetProcessHeap(), 0, dwLen);
898 if (RSAENH_CPExportKey(pKey->hProv, pKeyContainer->hKeyExchangeKeyPair, 0,
899 PRIVATEKEYBLOB, 0, pbKey, &dwLen))
901 RegSetValueExA(hKey, "KeyExchangeKeyPair", 0, REG_BINARY, pbKey, dwLen);
903 HeapFree(GetProcessHeap(), 0, pbKey);
906 release_handle(&handle_table, (unsigned int)pKeyContainer->hKeyExchangeKeyPair,
910 if (lookup_handle(&handle_table, pKeyContainer->hSignatureKeyPair, RSAENH_MAGIC_KEY,
913 if (RSAENH_CPExportKey(pKey->hProv, pKeyContainer->hSignatureKeyPair, 0,
914 PRIVATEKEYBLOB, 0, 0, &dwLen))
916 pbKey = (BYTE*)HeapAlloc(GetProcessHeap(), 0, dwLen);
919 if (RSAENH_CPExportKey(pKey->hProv, pKeyContainer->hSignatureKeyPair, 0,
920 PRIVATEKEYBLOB, 0, pbKey, &dwLen))
922 RegSetValueExA(hKey, "SignatureKeyPair", 0, REG_BINARY, pbKey, dwLen);
924 HeapFree(GetProcessHeap(), 0, pbKey);
927 release_handle(&handle_table, (unsigned int)pKeyContainer->hSignatureKeyPair,
935 HeapFree( GetProcessHeap(), 0, pKeyContainer );
938 /******************************************************************************
939 * new_key_container [Internal]
941 * Create a new key container. The personality (RSA Base, Strong or Enhanced CP)
942 * of the CSP is determined via the pVTable->pszProvName string.
945 * pszContainerName [I] Name of the key container.
946 * pVTable [I] Callback functions and context info provided by the OS
949 * Success: Handle to the new key container.
950 * Failure: INVALID_HANDLE_VALUE
952 static HCRYPTPROV new_key_container(PCHAR pszContainerName, DWORD dwFlags, PVTableProvStruc pVTable)
954 KEYCONTAINER *pKeyContainer;
955 HCRYPTPROV hKeyContainer;
957 hKeyContainer = (HCRYPTPROV)new_object(&handle_table, sizeof(KEYCONTAINER), RSAENH_MAGIC_CONTAINER,
958 destroy_key_container, (OBJECTHDR**)&pKeyContainer);
959 if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE)
961 strncpy(pKeyContainer->szName, pszContainerName, MAX_PATH);
962 pKeyContainer->szName[MAX_PATH-1] = '\0';
963 pKeyContainer->dwFlags = dwFlags;
964 pKeyContainer->dwEnumAlgsCtr = 0;
965 pKeyContainer->hKeyExchangeKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE;
966 pKeyContainer->hSignatureKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE;
967 if (pVTable && pVTable->pszProvName) {
968 strncpy(pKeyContainer->szProvName, pVTable->pszProvName, MAX_PATH);
969 pKeyContainer->szProvName[MAX_PATH-1] = '\0';
970 if (!strcmp(pVTable->pszProvName, MS_DEF_PROV_A)) {
971 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_BASE;
972 } else if (!strcmp(pVTable->pszProvName, MS_ENHANCED_PROV_A)) {
973 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_ENHANCED;
974 } else if (!strcmp(pVTable->pszProvName, MS_DEF_RSA_SCHANNEL_PROV_A)) {
975 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_SCHANNEL;
977 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_STRONG;
982 return hKeyContainer;
985 /******************************************************************************
986 * read_key_container [Internal]
988 * Tries to read the persistent state of the key container (mainly the signature
989 * and key exchange private keys) given by pszContainerName.
992 * pszContainerName [I] Name of the key container to read from the registry
993 * pVTable [I] Pointer to context data provided by the operating system
996 * Success: Handle to the key container read from the registry
997 * Failure: INVALID_HANDLE_VALUE
999 static HCRYPTPROV read_key_container(PCHAR pszContainerName, DWORD dwFlags, PVTableProvStruc pVTable)
1001 CHAR szRSABase[MAX_PATH];
1003 HKEY hKey, hRootKey;
1004 DWORD dwValueType, dwLen;
1005 KEYCONTAINER *pKeyContainer;
1006 HCRYPTPROV hKeyContainer;
1008 sprintf(szRSABase, RSAENH_REGKEY, pszContainerName);
1010 if (dwFlags & CRYPT_MACHINE_KEYSET) {
1011 hRootKey = HKEY_LOCAL_MACHINE;
1013 hRootKey = HKEY_CURRENT_USER;
1016 if (RegOpenKeyExA(hRootKey, szRSABase, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
1018 SetLastError(NTE_BAD_KEYSET);
1019 return (HCRYPTPROV)INVALID_HANDLE_VALUE;
1022 hKeyContainer = new_key_container(pszContainerName, dwFlags, pVTable);
1023 if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE)
1025 if (!lookup_handle(&handle_table, hKeyContainer, RSAENH_MAGIC_CONTAINER,
1026 (OBJECTHDR**)&pKeyContainer))
1027 return (HCRYPTPROV)INVALID_HANDLE_VALUE;
1029 if (RegQueryValueExA(hKey, "KeyExchangeKeyPair", 0, &dwValueType, NULL, &dwLen) ==
1032 pbKey = (BYTE*)HeapAlloc(GetProcessHeap(), 0, dwLen);
1035 if (RegQueryValueExA(hKey, "KeyExchangeKeyPair", 0, &dwValueType, pbKey, &dwLen) ==
1038 RSAENH_CPImportKey(hKeyContainer, pbKey, dwLen, 0, 0,
1039 &pKeyContainer->hKeyExchangeKeyPair);
1041 HeapFree(GetProcessHeap(), 0, pbKey);
1045 if (RegQueryValueExA(hKey, "SignatureKeyPair", 0, &dwValueType, NULL, &dwLen) ==
1048 pbKey = (BYTE*)HeapAlloc(GetProcessHeap(), 0, dwLen);
1051 if (RegQueryValueExA(hKey, "SignatureKeyPair", 0, &dwValueType, pbKey, &dwLen) ==
1054 RSAENH_CPImportKey(hKeyContainer, pbKey, dwLen, 0, 0,
1055 &pKeyContainer->hSignatureKeyPair);
1057 HeapFree(GetProcessHeap(), 0, pbKey);
1062 return hKeyContainer;
1065 /******************************************************************************
1066 * build_hash_signature [Internal]
1068 * Builds a padded version of a hash to match the length of the RSA key modulus.
1071 * pbSignature [O] The padded hash object is stored here.
1072 * dwLen [I] Length of the pbSignature buffer.
1073 * aiAlgid [I] Algorithm identifier of the hash to be padded.
1074 * abHashValue [I] The value of the hash object.
1075 * dwHashLen [I] Length of the hash value.
1076 * dwFlags [I] Selection of padding algorithm.
1080 * Failure: FALSE (NTE_BAD_ALGID)
1082 static BOOL build_hash_signature(BYTE *pbSignature, DWORD dwLen, ALG_ID aiAlgid,
1083 CONST BYTE *abHashValue, DWORD dwHashLen, DWORD dwFlags)
1085 /* These prefixes are meant to be concatenated with hash values of the
1086 * respective kind to form a PKCS #7 DigestInfo. */
1087 static const struct tagOIDDescriptor {
1090 CONST BYTE abOID[18];
1091 } aOIDDescriptor[5] = {
1092 { CALG_MD2, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
1093 0x86, 0xf7, 0x0d, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10 } },
1094 { CALG_MD4, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
1095 0x86, 0xf7, 0x0d, 0x02, 0x04, 0x05, 0x00, 0x04, 0x10 } },
1096 { CALG_MD5, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48,
1097 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 } },
1098 { CALG_SHA, 15, { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
1099 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 } },
1102 DWORD dwIdxOID, i, j;
1104 for (dwIdxOID = 0; aOIDDescriptor[dwIdxOID].aiAlgid; dwIdxOID++) {
1105 if (aOIDDescriptor[dwIdxOID].aiAlgid == aiAlgid) break;
1108 if (!aOIDDescriptor[dwIdxOID].aiAlgid) {
1109 SetLastError(NTE_BAD_ALGID);
1113 /* Build the padded signature */
1114 if (dwFlags & CRYPT_X931_FORMAT) {
1115 pbSignature[0] = 0x6b;
1116 for (i=1; i < dwLen - dwHashLen - 3; i++) {
1117 pbSignature[i] = 0xbb;
1119 pbSignature[i++] = 0xba;
1120 for (j=0; j < dwHashLen; j++, i++) {
1121 pbSignature[i] = abHashValue[j];
1123 pbSignature[i++] = 0x33;
1124 pbSignature[i++] = 0xcc;
1126 pbSignature[0] = 0x00;
1127 pbSignature[1] = 0x01;
1128 if (dwFlags & CRYPT_NOHASHOID) {
1129 for (i=2; i < dwLen - 1 - dwHashLen; i++) {
1130 pbSignature[i] = 0xff;
1132 pbSignature[i++] = 0x00;
1134 for (i=2; i < dwLen - 1 - aOIDDescriptor[dwIdxOID].dwLen - dwHashLen; i++) {
1135 pbSignature[i] = 0xff;
1137 pbSignature[i++] = 0x00;
1138 for (j=0; j < aOIDDescriptor[dwIdxOID].dwLen; j++) {
1139 pbSignature[i++] = aOIDDescriptor[dwIdxOID].abOID[j];
1142 for (j=0; j < dwHashLen; j++) {
1143 pbSignature[i++] = abHashValue[j];
1150 /******************************************************************************
1153 * This is an implementation of the 'P_hash' helper function for TLS1's PRF.
1154 * It is used exclusively by tls1_prf. For details see RFC 2246, chapter 5.
1155 * The pseudo random stream generated by this function is exclusive or'ed with
1156 * the data in pbBuffer.
1159 * hHMAC [I] HMAC object, which will be used in pseudo random generation
1160 * pblobSeed [I] Seed value
1161 * pbBuffer [I/O] Pseudo random stream will be xor'ed to the provided data
1162 * dwBufferLen [I] Number of pseudo random bytes desired
1168 static BOOL tls1_p(HCRYPTHASH hHMAC, CONST PCRYPT_DATA_BLOB pblobSeed, PBYTE pbBuffer, DWORD dwBufferLen)
1171 BYTE abAi[RSAENH_MAX_HASH_SIZE];
1174 if (!lookup_handle(&handle_table, hHMAC, RSAENH_MAGIC_HASH, (OBJECTHDR**)&pHMAC)) {
1175 SetLastError(NTE_BAD_HASH);
1179 /* compute A_1 = HMAC(seed) */
1181 update_hash(pHMAC, pblobSeed->pbData, pblobSeed->cbData);
1182 finalize_hash(pHMAC);
1183 memcpy(abAi, pHMAC->abHashValue, pHMAC->dwHashSize);
1186 /* compute HMAC(A_i + seed) */
1188 update_hash(pHMAC, abAi, pHMAC->dwHashSize);
1189 update_hash(pHMAC, pblobSeed->pbData, pblobSeed->cbData);
1190 finalize_hash(pHMAC);
1192 /* pseudo random stream := CONCAT_{i=1..n} ( HMAC(A_i + seed) ) */
1194 if (i >= dwBufferLen) break;
1195 pbBuffer[i] ^= pHMAC->abHashValue[i % pHMAC->dwHashSize];
1197 } while (i % pHMAC->dwHashSize);
1199 /* compute A_{i+1} = HMAC(A_i) */
1201 update_hash(pHMAC, abAi, pHMAC->dwHashSize);
1202 finalize_hash(pHMAC);
1203 memcpy(abAi, pHMAC->abHashValue, pHMAC->dwHashSize);
1204 } while (i < dwBufferLen);
1209 /******************************************************************************
1210 * tls1_prf [Internal]
1212 * TLS1 pseudo random function as specified in RFC 2246, chapter 5
1215 * hProv [I] Key container used to compute the pseudo random stream
1216 * hSecret [I] Key that holds the (pre-)master secret
1217 * pblobLabel [I] Descriptive label
1218 * pblobSeed [I] Seed value
1219 * pbBuffer [O] Pseudo random numbers will be stored here
1220 * dwBufferLen [I] Number of pseudo random bytes desired
1226 static BOOL tls1_prf(HCRYPTPROV hProv, HCRYPTPROV hSecret, CONST PCRYPT_DATA_BLOB pblobLabel,
1227 CONST PCRYPT_DATA_BLOB pblobSeed, PBYTE pbBuffer, DWORD dwBufferLen)
1229 HMAC_INFO hmacInfo = { 0, NULL, 0, NULL, 0 };
1230 HCRYPTHASH hHMAC = (HCRYPTHASH)INVALID_HANDLE_VALUE;
1231 HCRYPTKEY hHalfSecret = (HCRYPTKEY)INVALID_HANDLE_VALUE;
1232 CRYPTKEY *pHalfSecret, *pSecret;
1233 DWORD dwHalfSecretLen;
1234 BOOL result = FALSE;
1235 CRYPT_DATA_BLOB blobLabelSeed;
1237 TRACE("(hProv=%08lx, hSecret=%08lx, pblobLabel=%p, pblobSeed=%p, pbBuffer=%p, dwBufferLen=%ld)\n",
1238 hProv, hSecret, pblobLabel, pblobSeed, pbBuffer, dwBufferLen);
1240 if (!lookup_handle(&handle_table, hSecret, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pSecret)) {
1241 SetLastError(NTE_FAIL);
1245 dwHalfSecretLen = (pSecret->dwKeyLen+1)/2;
1247 /* concatenation of the label and the seed */
1248 if (!concat_data_blobs(&blobLabelSeed, pblobLabel, pblobSeed)) goto exit;
1250 /* zero out the buffer, since two random streams will be xor'ed into it. */
1251 memset(pbBuffer, 0, dwBufferLen);
1253 /* build a 'fake' key, to hold the secret. CALG_SSL2_MASTER is used since it provides
1254 * the biggest range of valid key lengths. */
1255 hHalfSecret = new_key(hProv, CALG_SSL2_MASTER, MAKELONG(0,dwHalfSecretLen*8), &pHalfSecret);
1256 if (hHalfSecret == (HCRYPTKEY)INVALID_HANDLE_VALUE) goto exit;
1258 /* Derive an HMAC_MD5 hash and call the helper function. */
1259 memcpy(pHalfSecret->abKeyValue, pSecret->abKeyValue, dwHalfSecretLen);
1260 if (!RSAENH_CPCreateHash(hProv, CALG_HMAC, hHalfSecret, 0, &hHMAC)) goto exit;
1261 hmacInfo.HashAlgid = CALG_MD5;
1262 if (!RSAENH_CPSetHashParam(hProv, hHMAC, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0)) goto exit;
1263 if (!tls1_p(hHMAC, &blobLabelSeed, pbBuffer, dwBufferLen)) goto exit;
1265 /* Reconfigure to HMAC_SHA hash and call helper function again. */
1266 memcpy(pHalfSecret->abKeyValue, pSecret->abKeyValue + (pSecret->dwKeyLen/2), dwHalfSecretLen);
1267 hmacInfo.HashAlgid = CALG_SHA;
1268 if (!RSAENH_CPSetHashParam(hProv, hHMAC, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0)) goto exit;
1269 if (!tls1_p(hHMAC, &blobLabelSeed, pbBuffer, dwBufferLen)) goto exit;
1273 release_handle(&handle_table, hHalfSecret, RSAENH_MAGIC_KEY);
1274 if (hHMAC != (HCRYPTHASH)INVALID_HANDLE_VALUE) RSAENH_CPDestroyHash(hProv, hHMAC);
1275 free_data_blob(&blobLabelSeed);
1279 /******************************************************************************
1280 * pad_data [Internal]
1282 * Helper function for data padding according to PKCS1 #2
1285 * abData [I] The data to be padded
1286 * dwDataLen [I] Length of the data
1287 * abBuffer [O] Padded data will be stored here
1288 * dwBufferLen [I] Length of the buffer (also length of padded data)
1289 * dwFlags [I] Padding format (CRYPT_SSL2_FALLBACK)
1293 * Failure: FALSE (NTE_BAD_LEN, too much data to pad)
1295 static BOOL pad_data(CONST BYTE *abData, DWORD dwDataLen, BYTE *abBuffer, DWORD dwBufferLen,
1300 /* Ensure there is enough space for PKCS1 #2 padding */
1301 if (dwDataLen > dwBufferLen-11) {
1302 SetLastError(NTE_BAD_LEN);
1306 memmove(abBuffer + dwBufferLen - dwDataLen, abData, dwDataLen);
1309 abBuffer[1] = RSAENH_PKC_BLOCKTYPE;
1310 for (i=2; i < dwBufferLen - dwDataLen - 1; i++)
1311 do gen_rand_impl(&abBuffer[i], 1); while (!abBuffer[i]);
1312 if (dwFlags & CRYPT_SSL2_FALLBACK)
1313 for (i-=8; i < dwBufferLen - dwDataLen - 1; i++)
1320 /******************************************************************************
1321 * unpad_data [Internal]
1323 * Remove the PKCS1 padding from RSA decrypted data
1326 * abData [I] The padded data
1327 * dwDataLen [I] Length of the padded data
1328 * abBuffer [O] Data without padding will be stored here
1329 * dwBufferLen [I/O] I: Length of the buffer, O: Length of unpadded data
1330 * dwFlags [I] Currently none defined
1334 * Failure: FALSE, (NTE_BAD_DATA, no valid PKCS1 padding or buffer too small)
1336 static BOOL unpad_data(CONST BYTE *abData, DWORD dwDataLen, BYTE *abBuffer, DWORD *dwBufferLen,
1341 for (i=2; i<dwDataLen; i++)
1345 if ((i == dwDataLen) || (*dwBufferLen < dwDataLen - i - 1) ||
1346 (abData[0] != 0x00) || (abData[1] != RSAENH_PKC_BLOCKTYPE))
1348 SetLastError(NTE_BAD_DATA);
1352 *dwBufferLen = dwDataLen - i - 1;
1353 memmove(abBuffer, abData + i + 1, *dwBufferLen);
1357 /******************************************************************************
1358 * CPAcquireContext (RSAENH.@)
1360 * Acquire a handle to the key container specified by pszContainer
1363 * phProv [O] Pointer to the location the acquired handle will be written to.
1364 * pszContainer [I] Name of the desired key container. See Notes
1365 * dwFlags [I] Flags. See Notes.
1366 * pVTable [I] Pointer to a PVTableProvStruct containing callbacks.
1373 * If pszContainer is NULL or points to a zero length string the user's login
1374 * name will be used as the key container name.
1376 * If the CRYPT_NEW_KEYSET flag is set in dwFlags a new keyset will be created.
1377 * If a keyset with the given name already exists, the function fails and sets
1378 * last error to NTE_EXISTS. If CRYPT_NEW_KEYSET is not set and the specified
1379 * key container does not exist, function fails and sets last error to
1382 BOOL WINAPI RSAENH_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer,
1383 DWORD dwFlags, PVTableProvStruc pVTable)
1386 CHAR szKeyContainerName[MAX_PATH] = "";
1387 CHAR szRegKey[MAX_PATH];
1389 TRACE("(phProv=%p, pszContainer=%s, dwFlags=%08lx, pVTable=%p)\n", phProv,
1390 debugstr_a(pszContainer), dwFlags, pVTable);
1392 if (pszContainer ? strlen(pszContainer) : 0)
1394 strncpy(szKeyContainerName, pszContainer, MAX_PATH);
1395 szKeyContainerName[MAX_PATH-1] = '\0';
1400 if (!GetUserNameA(szKeyContainerName, &dwLen)) return FALSE;
1403 switch (dwFlags & (CRYPT_NEWKEYSET|CRYPT_VERIFYCONTEXT|CRYPT_DELETEKEYSET))
1406 *phProv = read_key_container(szKeyContainerName, dwFlags, pVTable);
1409 case CRYPT_DELETEKEYSET:
1410 if (snprintf(szRegKey, MAX_PATH, RSAENH_REGKEY, pszContainer) >= MAX_PATH) {
1411 SetLastError(NTE_BAD_KEYSET_PARAM);
1414 RegDeleteKeyA(HKEY_CURRENT_USER, szRegKey);
1415 SetLastError(ERROR_SUCCESS);
1420 case CRYPT_NEWKEYSET:
1421 *phProv = read_key_container(szKeyContainerName, dwFlags, pVTable);
1422 if (*phProv != (HCRYPTPROV)INVALID_HANDLE_VALUE)
1424 release_handle(&handle_table, (unsigned int)*phProv, RSAENH_MAGIC_CONTAINER);
1425 SetLastError(NTE_EXISTS);
1428 *phProv = new_key_container(szKeyContainerName, dwFlags, pVTable);
1431 case CRYPT_VERIFYCONTEXT:
1433 SetLastError(NTE_BAD_FLAGS);
1436 *phProv = new_key_container("", dwFlags, pVTable);
1440 *phProv = (unsigned int)INVALID_HANDLE_VALUE;
1441 SetLastError(NTE_BAD_FLAGS);
1445 if (*phProv != (unsigned int)INVALID_HANDLE_VALUE) {
1446 SetLastError(ERROR_SUCCESS);
1453 /******************************************************************************
1454 * CPCreateHash (RSAENH.@)
1456 * CPCreateHash creates and initalizes a new hash object.
1459 * hProv [I] Handle to the key container to which the new hash will belong.
1460 * Algid [I] Identifies the hash algorithm, which will be used for the hash.
1461 * hKey [I] Handle to a session key applied for keyed hashes.
1462 * dwFlags [I] Currently no flags defined. Must be zero.
1463 * phHash [O] Points to the location where a handle to the new hash will be stored.
1470 * hKey is a handle to a session key applied in keyed hashes like MAC and HMAC.
1471 * If a normal hash object is to be created (like e.g. MD2 or SHA1) hKey must be zero.
1473 BOOL WINAPI RSAENH_CPCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags,
1476 CRYPTKEY *pCryptKey;
1477 CRYPTHASH *pCryptHash;
1478 const PROV_ENUMALGS_EX *peaAlgidInfo;
1480 TRACE("(hProv=%08lx, Algid=%08x, hKey=%08lx, dwFlags=%08lx, phHash=%p)\n", hProv, Algid, hKey,
1483 peaAlgidInfo = get_algid_info(hProv, Algid);
1484 if (!peaAlgidInfo) return FALSE;
1488 SetLastError(NTE_BAD_FLAGS);
1492 if (Algid == CALG_MAC || Algid == CALG_HMAC || Algid == CALG_SCHANNEL_MASTER_HASH ||
1493 Algid == CALG_TLS1PRF)
1495 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey)) {
1496 SetLastError(NTE_BAD_KEY);
1500 if ((Algid == CALG_MAC) && (GET_ALG_TYPE(pCryptKey->aiAlgid) != ALG_TYPE_BLOCK)) {
1501 SetLastError(NTE_BAD_KEY);
1505 if ((Algid == CALG_SCHANNEL_MASTER_HASH || Algid == CALG_TLS1PRF) &&
1506 (pCryptKey->aiAlgid != CALG_TLS1_MASTER))
1508 SetLastError(NTE_BAD_KEY);
1512 if ((Algid == CALG_TLS1PRF) && (pCryptKey->dwState != RSAENH_KEYSTATE_MASTERKEY)) {
1513 SetLastError(NTE_BAD_KEY_STATE);
1518 *phHash = (HCRYPTHASH)new_object(&handle_table, sizeof(CRYPTHASH), RSAENH_MAGIC_HASH,
1519 destroy_hash, (OBJECTHDR**)&pCryptHash);
1520 if (!pCryptHash) return FALSE;
1522 pCryptHash->aiAlgid = Algid;
1523 pCryptHash->hKey = hKey;
1524 pCryptHash->hProv = hProv;
1525 pCryptHash->dwState = RSAENH_HASHSTATE_IDLE;
1526 pCryptHash->pHMACInfo = (PHMAC_INFO)NULL;
1527 pCryptHash->dwHashSize = peaAlgidInfo->dwDefaultLen >> 3;
1528 init_data_blob(&pCryptHash->tpPRFParams.blobLabel);
1529 init_data_blob(&pCryptHash->tpPRFParams.blobSeed);
1531 if (Algid == CALG_SCHANNEL_MASTER_HASH) {
1532 CRYPT_DATA_BLOB blobRandom, blobKeyExpansion = { 13, "key expansion" };
1534 if (pCryptKey->dwState != RSAENH_KEYSTATE_MASTERKEY) {
1535 CRYPT_DATA_BLOB blobLabel = { 13, "master secret" };
1536 BYTE abKeyValue[48];
1538 /* See RFC 2246, chapter 8.1 */
1539 if (!concat_data_blobs(&blobRandom,
1540 &pCryptKey->siSChannelInfo.blobClientRandom,
1541 &pCryptKey->siSChannelInfo.blobServerRandom))
1545 tls1_prf(hProv, hKey, &blobLabel, &blobRandom, abKeyValue, 48);
1546 pCryptKey->dwState = RSAENH_KEYSTATE_MASTERKEY;
1547 memcpy(pCryptKey->abKeyValue, abKeyValue, 48);
1548 free_data_blob(&blobRandom);
1551 /* See RFC 2246, chapter 6.3 */
1552 if (!concat_data_blobs(&blobRandom,
1553 &pCryptKey->siSChannelInfo.blobServerRandom,
1554 &pCryptKey->siSChannelInfo.blobClientRandom))
1558 tls1_prf(hProv, hKey, &blobKeyExpansion, &blobRandom, pCryptHash->abHashValue,
1559 RSAENH_MAX_HASH_SIZE);
1560 free_data_blob(&blobRandom);
1563 return init_hash(pCryptHash);
1566 /******************************************************************************
1567 * CPDestroyHash (RSAENH.@)
1569 * Releases the handle to a hash object. The object is destroyed if it's reference
1570 * count reaches zero.
1573 * hProv [I] Handle to the key container to which the hash object belongs.
1574 * hHash [I] Handle to the hash object to be released.
1580 BOOL WINAPI RSAENH_CPDestroyHash(HCRYPTPROV hProv, HCRYPTHASH hHash)
1582 TRACE("(hProv=%08lx, hHash=%08lx)\n", hProv, hHash);
1584 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
1586 SetLastError(NTE_BAD_UID);
1590 if (!release_handle(&handle_table, hHash, RSAENH_MAGIC_HASH))
1592 SetLastError(NTE_BAD_HASH);
1599 /******************************************************************************
1600 * CPDestroyKey (RSAENH.@)
1602 * Releases the handle to a key object. The object is destroyed if it's reference
1603 * count reaches zero.
1606 * hProv [I] Handle to the key container to which the key object belongs.
1607 * hKey [I] Handle to the key object to be released.
1613 BOOL WINAPI RSAENH_CPDestroyKey(HCRYPTPROV hProv, HCRYPTKEY hKey)
1615 TRACE("(hProv=%08lx, hKey=%08lx)\n", hProv, hKey);
1617 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
1619 SetLastError(NTE_BAD_UID);
1623 if (!release_handle(&handle_table, hKey, RSAENH_MAGIC_KEY))
1625 SetLastError(NTE_BAD_KEY);
1632 /******************************************************************************
1633 * CPDuplicateHash (RSAENH.@)
1635 * Clones a hash object including it's current state.
1638 * hUID [I] Handle to the key container the hash belongs to.
1639 * hHash [I] Handle to the hash object to be cloned.
1640 * pdwReserved [I] Reserved. Must be NULL.
1641 * dwFlags [I] No flags are currently defined. Must be 0.
1642 * phHash [O] Handle to the cloned hash object.
1648 BOOL WINAPI RSAENH_CPDuplicateHash(HCRYPTPROV hUID, HCRYPTHASH hHash, DWORD *pdwReserved,
1649 DWORD dwFlags, HCRYPTHASH *phHash)
1651 CRYPTHASH *pSrcHash, *pDestHash;
1653 TRACE("(hUID=%08lx, hHash=%08lx, pdwReserved=%p, dwFlags=%08lx, phHash=%p)\n", hUID, hHash,
1654 pdwReserved, dwFlags, phHash);
1656 if (!is_valid_handle(&handle_table, hUID, RSAENH_MAGIC_CONTAINER))
1658 SetLastError(NTE_BAD_UID);
1662 if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH, (OBJECTHDR**)&pSrcHash))
1664 SetLastError(NTE_BAD_HASH);
1668 if (!phHash || pdwReserved || dwFlags)
1670 SetLastError(ERROR_INVALID_PARAMETER);
1674 *phHash = (HCRYPTHASH)new_object(&handle_table, sizeof(CRYPTHASH), RSAENH_MAGIC_HASH,
1675 destroy_hash, (OBJECTHDR**)&pDestHash);
1676 if (*phHash != (HCRYPTHASH)INVALID_HANDLE_VALUE)
1678 memcpy(pDestHash, pSrcHash, sizeof(CRYPTHASH));
1679 duplicate_hash_impl(pSrcHash->aiAlgid, &pSrcHash->context, &pDestHash->context);
1680 copy_hmac_info(&pDestHash->pHMACInfo, pSrcHash->pHMACInfo);
1681 copy_data_blob(&pDestHash->tpPRFParams.blobLabel, &pSrcHash->tpPRFParams.blobLabel);
1682 copy_data_blob(&pDestHash->tpPRFParams.blobSeed, &pSrcHash->tpPRFParams.blobSeed);
1685 return *phHash != (HCRYPTHASH)INVALID_HANDLE_VALUE;
1688 /******************************************************************************
1689 * CPDuplicateKey (RSAENH.@)
1691 * Clones a key object including it's current state.
1694 * hUID [I] Handle to the key container the hash belongs to.
1695 * hKey [I] Handle to the key object to be cloned.
1696 * pdwReserved [I] Reserved. Must be NULL.
1697 * dwFlags [I] No flags are currently defined. Must be 0.
1698 * phHash [O] Handle to the cloned key object.
1704 BOOL WINAPI RSAENH_CPDuplicateKey(HCRYPTPROV hUID, HCRYPTKEY hKey, DWORD *pdwReserved,
1705 DWORD dwFlags, HCRYPTKEY *phKey)
1707 CRYPTKEY *pSrcKey, *pDestKey;
1709 TRACE("(hUID=%08lx, hKey=%08lx, pdwReserved=%p, dwFlags=%08lx, phKey=%p)\n", hUID, hKey,
1710 pdwReserved, dwFlags, phKey);
1712 if (!is_valid_handle(&handle_table, hUID, RSAENH_MAGIC_CONTAINER))
1714 SetLastError(NTE_BAD_UID);
1718 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pSrcKey))
1720 SetLastError(NTE_BAD_KEY);
1724 if (!phKey || pdwReserved || dwFlags)
1726 SetLastError(ERROR_INVALID_PARAMETER);
1730 *phKey = (HCRYPTKEY)new_object(&handle_table, sizeof(CRYPTKEY), RSAENH_MAGIC_KEY, destroy_key,
1731 (OBJECTHDR**)&pDestKey);
1732 if (*phKey != (HCRYPTKEY)INVALID_HANDLE_VALUE)
1734 memcpy(pDestKey, pSrcKey, sizeof(CRYPTKEY));
1735 copy_data_blob(&pDestKey->siSChannelInfo.blobServerRandom,
1736 &pSrcKey->siSChannelInfo.blobServerRandom);
1737 copy_data_blob(&pDestKey->siSChannelInfo.blobClientRandom,
1738 &pSrcKey->siSChannelInfo.blobClientRandom);
1739 duplicate_key_impl(pSrcKey->aiAlgid, &pSrcKey->context, &pDestKey->context);
1748 /******************************************************************************
1749 * CPEncrypt (RSAENH.@)
1754 * hProv [I] The key container hKey and hHash belong to.
1755 * hKey [I] The key used to encrypt the data.
1756 * hHash [I] An optional hash object for parallel hashing. See notes.
1757 * Final [I] Indicates if this is the last block of data to encrypt.
1758 * dwFlags [I] Currently no flags defined. Must be zero.
1759 * pbData [I/O] Pointer to the data to encrypt. Encrypted data will also be stored there.
1760 * pdwDataLen [I/O] I: Length of data to encrypt, O: Length of encrypted data.
1761 * dwBufLen [I] Size of the buffer at pbData.
1768 * If a hash object handle is provided in hHash, it will be updated with the plaintext.
1769 * This is useful for message signatures.
1771 * This function uses the standard WINAPI protocol for querying data of dynamic length.
1773 BOOL WINAPI RSAENH_CPEncrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
1774 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen)
1776 CRYPTKEY *pCryptKey;
1777 BYTE *in, out[RSAENH_MAX_BLOCK_SIZE], o[RSAENH_MAX_BLOCK_SIZE];
1778 DWORD dwEncryptedLen, i, j, k;
1780 TRACE("(hProv=%08lx, hKey=%08lx, hHash=%08lx, Final=%d, dwFlags=%08lx, pbData=%p, "
1781 "pdwDataLen=%p, dwBufLen=%ld)\n", hProv, hKey, hHash, Final, dwFlags, pbData, pdwDataLen,
1784 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
1786 SetLastError(NTE_BAD_UID);
1792 SetLastError(NTE_BAD_FLAGS);
1796 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
1798 SetLastError(NTE_BAD_KEY);
1802 if (pCryptKey->dwState == RSAENH_KEYSTATE_IDLE)
1803 pCryptKey->dwState = RSAENH_KEYSTATE_ENCRYPTING;
1805 if (pCryptKey->dwState != RSAENH_KEYSTATE_ENCRYPTING)
1807 SetLastError(NTE_BAD_DATA);
1811 if (is_valid_handle(&handle_table, hHash, RSAENH_MAGIC_HASH)) {
1812 if (!RSAENH_CPHashData(hProv, hHash, pbData, *pdwDataLen, 0)) return FALSE;
1815 if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_BLOCK) {
1816 if (!Final && (*pdwDataLen % pCryptKey->dwBlockLen)) {
1817 SetLastError(NTE_BAD_DATA);
1821 dwEncryptedLen = (*pdwDataLen/pCryptKey->dwBlockLen+(Final?1:0))*pCryptKey->dwBlockLen;
1822 for (i=*pdwDataLen; i<dwEncryptedLen; i++) pbData[i] = dwEncryptedLen - *pdwDataLen;
1823 *pdwDataLen = dwEncryptedLen;
1825 if (*pdwDataLen > dwBufLen)
1827 SetLastError(ERROR_MORE_DATA);
1831 for (i=0, in=pbData; i<*pdwDataLen; i+=pCryptKey->dwBlockLen, in+=pCryptKey->dwBlockLen) {
1832 switch (pCryptKey->dwMode) {
1833 case CRYPT_MODE_ECB:
1834 encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, in, out,
1838 case CRYPT_MODE_CBC:
1839 for (j=0; j<pCryptKey->dwBlockLen; j++) in[j] ^= pCryptKey->abChainVector[j];
1840 encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, in, out,
1842 memcpy(pCryptKey->abChainVector, out, pCryptKey->dwBlockLen);
1845 case CRYPT_MODE_CFB:
1846 for (j=0; j<pCryptKey->dwBlockLen; j++) {
1847 encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context,
1848 pCryptKey->abChainVector, o, RSAENH_ENCRYPT);
1849 out[j] = in[j] ^ o[0];
1850 for (k=0; k<pCryptKey->dwBlockLen-1; k++)
1851 pCryptKey->abChainVector[k] = pCryptKey->abChainVector[k+1];
1852 pCryptKey->abChainVector[k] = out[j];
1857 SetLastError(NTE_BAD_ALGID);
1860 memcpy(in, out, pCryptKey->dwBlockLen);
1862 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_STREAM) {
1863 encrypt_stream_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, *pdwDataLen);
1864 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_RSA) {
1865 if (pCryptKey->aiAlgid == CALG_RSA_SIGN) {
1866 SetLastError(NTE_BAD_KEY);
1869 if (dwBufLen < pCryptKey->dwBlockLen) {
1870 SetLastError(ERROR_MORE_DATA);
1873 if (!pad_data(pbData, *pdwDataLen, pbData, pCryptKey->dwBlockLen, dwFlags)) return FALSE;
1874 encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, pbData, RSAENH_ENCRYPT);
1875 *pdwDataLen = pCryptKey->dwBlockLen;
1878 SetLastError(NTE_BAD_TYPE);
1882 if (Final) setup_key(pCryptKey);
1887 /******************************************************************************
1888 * CPDecrypt (RSAENH.@)
1893 * hProv [I] The key container hKey and hHash belong to.
1894 * hKey [I] The key used to decrypt the data.
1895 * hHash [I] An optional hash object for parallel hashing. See notes.
1896 * Final [I] Indicates if this is the last block of data to decrypt.
1897 * dwFlags [I] Currently no flags defined. Must be zero.
1898 * pbData [I/O] Pointer to the data to decrypt. Plaintext will also be stored there.
1899 * pdwDataLen [I/O] I: Length of ciphertext, O: Length of plaintext.
1906 * If a hash object handle is provided in hHash, it will be updated with the plaintext.
1907 * This is useful for message signatures.
1909 * This function uses the standard WINAPI protocol for querying data of dynamic length.
1911 BOOL WINAPI RSAENH_CPDecrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final,
1912 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
1914 CRYPTKEY *pCryptKey;
1915 BYTE *in, out[RSAENH_MAX_BLOCK_SIZE], o[RSAENH_MAX_BLOCK_SIZE];
1918 TRACE("(hProv=%08lx, hKey=%08lx, hHash=%08lx, Final=%d, dwFlags=%08lx, pbData=%p, "
1919 "pdwDataLen=%p)\n", hProv, hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
1921 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
1923 SetLastError(NTE_BAD_UID);
1929 SetLastError(NTE_BAD_FLAGS);
1933 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
1935 SetLastError(NTE_BAD_KEY);
1939 if (pCryptKey->dwState == RSAENH_KEYSTATE_IDLE)
1940 pCryptKey->dwState = RSAENH_KEYSTATE_DECRYPTING;
1942 if (pCryptKey->dwState != RSAENH_KEYSTATE_DECRYPTING)
1944 SetLastError(NTE_BAD_DATA);
1948 if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_BLOCK) {
1949 for (i=0, in=pbData; i<*pdwDataLen; i+=pCryptKey->dwBlockLen, in+=pCryptKey->dwBlockLen) {
1950 switch (pCryptKey->dwMode) {
1951 case CRYPT_MODE_ECB:
1952 encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, in, out,
1956 case CRYPT_MODE_CBC:
1957 encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, in, out,
1959 for (j=0; j<pCryptKey->dwBlockLen; j++) out[j] ^= pCryptKey->abChainVector[j];
1960 memcpy(pCryptKey->abChainVector, in, pCryptKey->dwBlockLen);
1963 case CRYPT_MODE_CFB:
1964 for (j=0; j<pCryptKey->dwBlockLen; j++) {
1965 encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context,
1966 pCryptKey->abChainVector, o, RSAENH_ENCRYPT);
1967 out[j] = in[j] ^ o[0];
1968 for (k=0; k<pCryptKey->dwBlockLen-1; k++)
1969 pCryptKey->abChainVector[k] = pCryptKey->abChainVector[k+1];
1970 pCryptKey->abChainVector[k] = in[j];
1975 SetLastError(NTE_BAD_ALGID);
1978 memcpy(in, out, pCryptKey->dwBlockLen);
1980 if (Final) *pdwDataLen -= pbData[*pdwDataLen-1];
1982 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_STREAM) {
1983 encrypt_stream_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, *pdwDataLen);
1984 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_RSA) {
1985 if (pCryptKey->aiAlgid == CALG_RSA_SIGN) {
1986 SetLastError(NTE_BAD_KEY);
1989 encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, pbData, RSAENH_DECRYPT);
1990 if (!unpad_data(pbData, pCryptKey->dwBlockLen, pbData, pdwDataLen, dwFlags)) return FALSE;
1993 SetLastError(NTE_BAD_TYPE);
1997 if (Final) setup_key(pCryptKey);
1999 if (is_valid_handle(&handle_table, hHash, RSAENH_MAGIC_HASH)) {
2000 if (!RSAENH_CPHashData(hProv, hHash, pbData, *pdwDataLen, 0)) return FALSE;
2006 /******************************************************************************
2007 * CPExportKey (RSAENH.@)
2009 * Export a key into a binary large object (BLOB).
2012 * hProv [I] Key container from which a key is to be exported.
2013 * hKey [I] Key to be exported.
2014 * hPubKey [I] Key used to encrypt sensitive BLOB data.
2015 * dwBlobType [I] SIMPLEBLOB, PUBLICKEYBLOB or PRIVATEKEYBLOB.
2016 * dwFlags [I] Currently none defined.
2017 * pbData [O] Pointer to a buffer where the BLOB will be written to.
2018 * pdwDataLen [I/O] I: Size of buffer at pbData, O: Size of BLOB
2024 BOOL WINAPI RSAENH_CPExportKey(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubKey,
2025 DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
2027 CRYPTKEY *pCryptKey, *pPubKey;
2028 BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData;
2029 RSAPUBKEY *pRSAPubKey = (RSAPUBKEY*)(pBlobHeader+1);
2030 ALG_ID *pAlgid = (ALG_ID*)(pBlobHeader+1);
2033 TRACE("(hProv=%08lx, hKey=%08lx, hPubKey=%08lx, dwBlobType=%08lx, dwFlags=%08lx, pbData=%p,"
2034 "pdwDataLen=%p)\n", hProv, hKey, hPubKey, dwBlobType, dwFlags, pbData, pdwDataLen);
2036 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2038 SetLastError(NTE_BAD_UID);
2042 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
2044 SetLastError(NTE_BAD_KEY);
2048 if (dwFlags & CRYPT_SSL2_FALLBACK) {
2049 if (pCryptKey->aiAlgid != CALG_SSL2_MASTER) {
2050 SetLastError(NTE_BAD_KEY);
2055 switch ((BYTE)dwBlobType)
2058 if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey)){
2059 SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error_code? */
2063 if (!(GET_ALG_CLASS(pCryptKey->aiAlgid)&(ALG_CLASS_DATA_ENCRYPT|ALG_CLASS_MSG_ENCRYPT))) {
2064 SetLastError(NTE_BAD_KEY); /* FIXME: error code? */
2068 dwDataLen = sizeof(BLOBHEADER) + sizeof(ALG_ID) + pPubKey->dwBlockLen;
2070 if (*pdwDataLen < dwDataLen) {
2071 SetLastError(ERROR_MORE_DATA);
2072 *pdwDataLen = dwDataLen;
2076 pBlobHeader->bType = SIMPLEBLOB;
2077 pBlobHeader->bVersion = CUR_BLOB_VERSION;
2078 pBlobHeader->reserved = 0;
2079 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
2081 *pAlgid = pPubKey->aiAlgid;
2083 if (!pad_data(pCryptKey->abKeyValue, pCryptKey->dwKeyLen, (BYTE*)(pAlgid+1),
2084 pPubKey->dwBlockLen, dwFlags))
2089 encrypt_block_impl(pPubKey->aiAlgid, &pPubKey->context, (BYTE*)(pAlgid+1),
2090 (BYTE*)(pAlgid+1), RSAENH_ENCRYPT);
2092 *pdwDataLen = dwDataLen;
2096 if (is_valid_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY)) {
2097 SetLastError(NTE_BAD_KEY); /* FIXME: error code? */
2101 if ((pCryptKey->aiAlgid != CALG_RSA_KEYX) && (pCryptKey->aiAlgid != CALG_RSA_SIGN)) {
2102 SetLastError(NTE_BAD_KEY);
2106 dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + pCryptKey->dwKeyLen;
2108 if (*pdwDataLen < dwDataLen) {
2109 SetLastError(ERROR_MORE_DATA);
2110 *pdwDataLen = dwDataLen;
2114 pBlobHeader->bType = PUBLICKEYBLOB;
2115 pBlobHeader->bVersion = CUR_BLOB_VERSION;
2116 pBlobHeader->reserved = 0;
2117 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
2119 pRSAPubKey->magic = RSAENH_MAGIC_RSA1;
2120 pRSAPubKey->bitlen = pCryptKey->dwKeyLen << 3;
2122 export_public_key_impl((BYTE*)(pRSAPubKey+1), &pCryptKey->context,
2123 pCryptKey->dwKeyLen, &pRSAPubKey->pubexp);
2125 *pdwDataLen = dwDataLen;
2128 case PRIVATEKEYBLOB:
2129 if ((pCryptKey->aiAlgid != CALG_RSA_KEYX) && (pCryptKey->aiAlgid != CALG_RSA_SIGN)) {
2130 SetLastError(NTE_BAD_KEY);
2134 dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2135 2 * pCryptKey->dwKeyLen + 5 * ((pCryptKey->dwKeyLen + 1) >> 1);
2137 if (*pdwDataLen < dwDataLen) {
2138 SetLastError(ERROR_MORE_DATA);
2139 *pdwDataLen = dwDataLen;
2143 pBlobHeader->bType = PRIVATEKEYBLOB;
2144 pBlobHeader->bVersion = CUR_BLOB_VERSION;
2145 pBlobHeader->reserved = 0;
2146 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
2148 pRSAPubKey->magic = RSAENH_MAGIC_RSA2;
2149 pRSAPubKey->bitlen = pCryptKey->dwKeyLen << 3;
2151 export_private_key_impl((BYTE*)(pRSAPubKey+1), &pCryptKey->context,
2152 pCryptKey->dwKeyLen, &pRSAPubKey->pubexp);
2154 *pdwDataLen = dwDataLen;
2158 SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */
2163 /******************************************************************************
2164 * CPImportKey (RSAENH.@)
2166 * Import a BLOB'ed key into a key container.
2169 * hProv [I] Key container into which the key is to be imported.
2170 * pbData [I] Pointer to a buffer which holds the BLOB.
2171 * dwDataLen [I] Length of data in buffer at pbData.
2172 * hPubKey [I] Key used to decrypt sensitive BLOB data.
2173 * dwFlags [I] Currently none defined.
2174 * phKey [O] Handle to the imported key.
2180 BOOL WINAPI RSAENH_CPImportKey(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen,
2181 HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
2183 CRYPTKEY *pCryptKey, *pPubKey;
2184 CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData;
2185 CONST RSAPUBKEY *pRSAPubKey = (CONST RSAPUBKEY*)(pBlobHeader+1);
2186 CONST ALG_ID *pAlgid = (CONST ALG_ID*)(pBlobHeader+1);
2187 CONST BYTE *pbKeyStream = (CONST BYTE*)(pAlgid + 1);
2191 TRACE("(hProv=%08lx, pbData=%p, dwDataLen=%ld, hPubKey=%08lx, dwFlags=%08lx, phKey=%p)\n",
2192 hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
2194 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
2196 SetLastError(NTE_BAD_UID);
2200 if (dwDataLen < sizeof(BLOBHEADER) ||
2201 pBlobHeader->bVersion != CUR_BLOB_VERSION ||
2202 pBlobHeader->reserved != 0)
2204 SetLastError(NTE_BAD_DATA);
2208 switch (pBlobHeader->bType)
2210 case PRIVATEKEYBLOB:
2211 if ((dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY)) ||
2212 (pRSAPubKey->magic != RSAENH_MAGIC_RSA2) ||
2213 (dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2214 (2 * pRSAPubKey->bitlen >> 3) + (5 * ((pRSAPubKey->bitlen+8)>>4))))
2216 SetLastError(NTE_BAD_DATA);
2220 *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey);
2221 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
2222 setup_key(pCryptKey);
2223 return import_private_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context,
2224 pRSAPubKey->bitlen/8, pRSAPubKey->pubexp);
2227 if ((dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY)) ||
2228 (pRSAPubKey->magic != RSAENH_MAGIC_RSA1) ||
2229 (dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + (pRSAPubKey->bitlen >> 3)))
2231 SetLastError(NTE_BAD_DATA);
2235 *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey);
2236 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
2237 setup_key(pCryptKey);
2238 return import_public_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context,
2239 pRSAPubKey->bitlen >> 3, pRSAPubKey->pubexp);
2242 if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey) ||
2243 pPubKey->aiAlgid != CALG_RSA_KEYX)
2245 SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error code? */
2249 if (dwDataLen < sizeof(BLOBHEADER)+sizeof(ALG_ID)+pPubKey->dwBlockLen)
2251 SetLastError(NTE_BAD_DATA); /* FIXME: error code */
2255 pbDecrypted = (BYTE*)HeapAlloc(GetProcessHeap(), 0, pPubKey->dwBlockLen);
2256 if (!pbDecrypted) return FALSE;
2257 encrypt_block_impl(pPubKey->aiAlgid, &pPubKey->context, pbKeyStream, pbDecrypted,
2260 dwKeyLen = RSAENH_MAX_KEY_SIZE;
2261 if (!unpad_data(pbDecrypted, pPubKey->dwBlockLen, pbDecrypted, &dwKeyLen, dwFlags)) {
2262 HeapFree(GetProcessHeap(), 0, pbDecrypted);
2266 *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, dwKeyLen<<19, &pCryptKey);
2267 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE)
2269 HeapFree(GetProcessHeap(), 0, pbDecrypted);
2272 memcpy(pCryptKey->abKeyValue, pbDecrypted, dwKeyLen);
2273 HeapFree(GetProcessHeap(), 0, pbDecrypted);
2274 setup_key(pCryptKey);
2278 SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */
2283 /******************************************************************************
2284 * CPGenKey (RSAENH.@)
2286 * Generate a key in the key container
2289 * hProv [I] Key container for which a key is to be generated.
2290 * Algid [I] Crypto algorithm identifier for the key to be generated.
2291 * dwFlags [I] Upper 16 bits: Binary length of key. Lower 16 bits: Flags. See Notes
2292 * phKey [O] Handle to the generated key.
2299 * Flags currently not considered.
2302 * Private key-exchange- and signature-keys can be generated with Algid AT_KEYEXCHANGE
2303 * and AT_SIGNATURE values.
2305 BOOL WINAPI RSAENH_CPGenKey(HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey)
2307 KEYCONTAINER *pKeyContainer;
2308 CRYPTKEY *pCryptKey;
2310 TRACE("(hProv=%08lx, aiAlgid=%d, dwFlags=%08lx, phKey=%p)\n", hProv, Algid, dwFlags, phKey);
2312 if (!lookup_handle(&handle_table, (unsigned int)hProv, RSAENH_MAGIC_CONTAINER,
2313 (OBJECTHDR**)&pKeyContainer))
2315 /* MSDN: hProv not containing valid context handle */
2316 SetLastError(NTE_BAD_UID);
2324 *phKey = new_key(hProv, CALG_RSA_SIGN, dwFlags, &pCryptKey);
2326 new_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen);
2327 setup_key(pCryptKey);
2328 if (Algid == AT_SIGNATURE) {
2329 RSAENH_CPDestroyKey(hProv, pKeyContainer->hSignatureKeyPair);
2330 copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
2331 (unsigned int*)&pKeyContainer->hSignatureKeyPair);
2336 case AT_KEYEXCHANGE:
2338 *phKey = new_key(hProv, CALG_RSA_KEYX, dwFlags, &pCryptKey);
2340 new_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen);
2341 setup_key(pCryptKey);
2342 if (Algid == AT_KEYEXCHANGE) {
2343 RSAENH_CPDestroyKey(hProv, pKeyContainer->hKeyExchangeKeyPair);
2344 copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
2345 (unsigned int*)&pKeyContainer->hKeyExchangeKeyPair);
2355 case CALG_PCT1_MASTER:
2356 case CALG_SSL2_MASTER:
2357 case CALG_SSL3_MASTER:
2358 case CALG_TLS1_MASTER:
2359 *phKey = new_key(hProv, Algid, dwFlags, &pCryptKey);
2361 gen_rand_impl(pCryptKey->abKeyValue, RSAENH_MAX_KEY_SIZE);
2363 case CALG_SSL3_MASTER:
2364 pCryptKey->abKeyValue[0] = RSAENH_SSL3_VERSION_MAJOR;
2365 pCryptKey->abKeyValue[1] = RSAENH_SSL3_VERSION_MINOR;
2368 case CALG_TLS1_MASTER:
2369 pCryptKey->abKeyValue[0] = RSAENH_TLS1_VERSION_MAJOR;
2370 pCryptKey->abKeyValue[1] = RSAENH_TLS1_VERSION_MINOR;
2373 setup_key(pCryptKey);
2378 /* MSDN: Algorithm not supported specified by Algid */
2379 SetLastError(NTE_BAD_ALGID);
2383 return *phKey != (unsigned int)INVALID_HANDLE_VALUE;
2386 /******************************************************************************
2387 * CPGenRandom (RSAENH.@)
2389 * Generate a random byte stream.
2392 * hProv [I] Key container that is used to generate random bytes.
2393 * dwLen [I] Specifies the number of requested random data bytes.
2394 * pbBuffer [O] Random bytes will be stored here.
2400 BOOL WINAPI RSAENH_CPGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer)
2402 TRACE("(hProv=%08lx, dwLen=%ld, pbBuffer=%p)\n", hProv, dwLen, pbBuffer);
2404 if (!is_valid_handle(&handle_table, (unsigned int)hProv, RSAENH_MAGIC_CONTAINER))
2406 /* MSDN: hProv not containing valid context handle */
2407 SetLastError(NTE_BAD_UID);
2411 return gen_rand_impl(pbBuffer, dwLen);
2414 /******************************************************************************
2415 * CPGetHashParam (RSAENH.@)
2417 * Query parameters of an hash object.
2420 * hProv [I] The kea container, which the hash belongs to.
2421 * hHash [I] The hash object that is to be queried.
2422 * dwParam [I] Specifies the parameter that is to be queried.
2423 * pbData [I] Pointer to the buffer where the parameter value will be stored.
2424 * pdwDataLen [I/O] I: Buffer length at pbData, O: Length of the parameter value.
2425 * dwFlags [I] None currently defined.
2432 * Valid dwParams are: HP_ALGID, HP_HASHSIZE, HP_HASHVALUE. The hash will be
2433 * finalized if HP_HASHVALUE is queried.
2435 BOOL WINAPI RSAENH_CPGetHashParam(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData,
2436 DWORD *pdwDataLen, DWORD dwFlags)
2438 CRYPTHASH *pCryptHash;
2440 TRACE("(hProv=%08lx, hHash=%08lx, dwParam=%08lx, pbData=%p, pdwDataLen=%p, dwFlags=%08lx)\n",
2441 hProv, hHash, dwParam, pbData, pdwDataLen, dwFlags);
2443 if (!is_valid_handle(&handle_table, (unsigned int)hProv, RSAENH_MAGIC_CONTAINER))
2445 SetLastError(NTE_BAD_UID);
2451 SetLastError(NTE_BAD_FLAGS);
2455 if (!lookup_handle(&handle_table, (unsigned int)hHash, RSAENH_MAGIC_HASH,
2456 (OBJECTHDR**)&pCryptHash))
2458 SetLastError(NTE_BAD_HASH);
2464 SetLastError(ERROR_INVALID_PARAMETER);
2471 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptHash->aiAlgid,
2475 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptHash->dwHashSize,
2479 if (pCryptHash->aiAlgid == CALG_TLS1PRF) {
2480 return tls1_prf(hProv, pCryptHash->hKey, &pCryptHash->tpPRFParams.blobLabel,
2481 &pCryptHash->tpPRFParams.blobSeed, pbData, *pdwDataLen);
2484 if (pCryptHash->dwState == RSAENH_HASHSTATE_IDLE) {
2485 SetLastError(NTE_BAD_HASH_STATE);
2489 if (pbData && (pCryptHash->dwState != RSAENH_HASHSTATE_FINISHED))
2491 finalize_hash(pCryptHash);
2492 pCryptHash->dwState = RSAENH_HASHSTATE_FINISHED;
2495 return copy_param(pbData, pdwDataLen, (CONST BYTE*)pCryptHash->abHashValue,
2496 pCryptHash->dwHashSize);
2499 SetLastError(NTE_BAD_TYPE);
2504 /******************************************************************************
2505 * CPSetKeyParam (RSAENH.@)
2507 * Set a parameter of a key object
2510 * hProv [I] The key container to which the key belongs.
2511 * hKey [I] The key for which a parameter is to be set.
2512 * dwParam [I] Parameter type. See Notes.
2513 * pbData [I] Pointer to the parameter value.
2514 * dwFlags [I] Currently none defined.
2521 * Defined dwParam types are:
2522 * - KP_MODE: Values MODE_CBC, MODE_ECB, MODE_CFB.
2523 * - KP_MODE_BITS: Shift width for cipher feedback mode. (Currently ignored by MS CSP's)
2524 * - KP_PERMISSIONS: Or'ed combination of CRYPT_ENCRYPT, CRYPT_DECRYPT,
2525 * CRYPT_EXPORT, CRYPT_READ, CRYPT_WRITE, CRYPT_MAC
2526 * - KP_IV: Initialization vector
2528 BOOL WINAPI RSAENH_CPSetKeyParam(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
2531 CRYPTKEY *pCryptKey;
2533 TRACE("(hProv=%08lx, hKey=%08lx, dwParam=%08lx, pbData=%p, dwFlags=%08lx)\n", hProv, hKey,
2534 dwParam, pbData, dwFlags);
2536 if (!is_valid_handle(&handle_table, (unsigned int)hProv, RSAENH_MAGIC_CONTAINER))
2538 SetLastError(NTE_BAD_UID);
2543 SetLastError(NTE_BAD_FLAGS);
2547 if (!lookup_handle(&handle_table, (unsigned int)hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
2549 SetLastError(NTE_BAD_KEY);
2555 pCryptKey->dwMode = *(DWORD*)pbData;
2559 pCryptKey->dwModeBits = *(DWORD*)pbData;
2562 case KP_PERMISSIONS:
2563 pCryptKey->dwPermissions = *(DWORD*)pbData;
2567 memcpy(pCryptKey->abInitVector, pbData, pCryptKey->dwBlockLen);
2570 case KP_SCHANNEL_ALG:
2571 switch (((PSCHANNEL_ALG)pbData)->dwUse) {
2572 case SCHANNEL_ENC_KEY:
2573 memcpy(&pCryptKey->siSChannelInfo.saEncAlg, pbData, sizeof(SCHANNEL_ALG));
2576 case SCHANNEL_MAC_KEY:
2577 memcpy(&pCryptKey->siSChannelInfo.saMACAlg, pbData, sizeof(SCHANNEL_ALG));
2581 SetLastError(NTE_FAIL); /* FIXME: error code */
2586 case KP_CLIENT_RANDOM:
2587 return copy_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom, (PCRYPT_DATA_BLOB)pbData);
2589 case KP_SERVER_RANDOM:
2590 return copy_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom, (PCRYPT_DATA_BLOB)pbData);
2593 SetLastError(NTE_BAD_TYPE);
2598 /******************************************************************************
2599 * CPGetKeyParam (RSAENH.@)
2601 * Query a key parameter.
2604 * hProv [I] The key container, which the key belongs to.
2605 * hHash [I] The key object that is to be queried.
2606 * dwParam [I] Specifies the parameter that is to be queried.
2607 * pbData [I] Pointer to the buffer where the parameter value will be stored.
2608 * pdwDataLen [I/O] I: Buffer length at pbData, O: Length of the parameter value.
2609 * dwFlags [I] None currently defined.
2616 * Defined dwParam types are:
2617 * - KP_MODE: Values MODE_CBC, MODE_ECB, MODE_CFB.
2618 * - KP_MODE_BITS: Shift width for cipher feedback mode.
2619 * (Currently ignored by MS CSP's - always eight)
2620 * - KP_PERMISSIONS: Or'ed combination of CRYPT_ENCRYPT, CRYPT_DECRYPT,
2621 * CRYPT_EXPORT, CRYPT_READ, CRYPT_WRITE, CRYPT_MAC
2622 * - KP_IV: Initialization vector.
2623 * - KP_KEYLEN: Bitwidth of the key.
2624 * - KP_BLOCKLEN: Size of a block cipher block.
2625 * - KP_SALT: Salt value.
2627 BOOL WINAPI RSAENH_CPGetKeyParam(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData,
2628 DWORD *pdwDataLen, DWORD dwFlags)
2630 CRYPTKEY *pCryptKey;
2633 TRACE("(hProv=%08lx, hKey=%08lx, dwParam=%08lx, pbData=%p, pdwDataLen=%p dwFlags=%08lx)\n",
2634 hProv, hKey, dwParam, pbData, pdwDataLen, dwFlags);
2636 if (!is_valid_handle(&handle_table, (unsigned int)hProv, RSAENH_MAGIC_CONTAINER))
2638 SetLastError(NTE_BAD_UID);
2643 SetLastError(NTE_BAD_FLAGS);
2647 if (!lookup_handle(&handle_table, (unsigned int)hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey))
2649 SetLastError(NTE_BAD_KEY);
2656 return copy_param(pbData, pdwDataLen, (CONST BYTE*)pCryptKey->abInitVector,
2657 pCryptKey->dwBlockLen);
2660 return copy_param(pbData, pdwDataLen,
2661 (CONST BYTE*)&pCryptKey->abKeyValue[pCryptKey->dwKeyLen], pCryptKey->dwSaltLen);
2664 dwBitLen = pCryptKey->dwKeyLen << 3;
2665 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwBitLen, sizeof(DWORD));
2668 dwBitLen = pCryptKey->dwBlockLen << 3;
2669 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwBitLen, sizeof(DWORD));
2672 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->dwMode, sizeof(DWORD));
2675 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->dwModeBits,
2678 case KP_PERMISSIONS:
2679 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->dwPermissions,
2683 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->aiAlgid, sizeof(DWORD));
2686 SetLastError(NTE_BAD_TYPE);
2691 /******************************************************************************
2692 * CPGetProvParam (RSAENH.@)
2694 * Query a CSP parameter.
2697 * hProv [I] The key container that is to be queried.
2698 * dwParam [I] Specifies the parameter that is to be queried.
2699 * pbData [I] Pointer to the buffer where the parameter value will be stored.
2700 * pdwDataLen [I/O] I: Buffer length at pbData, O: Length of the parameter value.
2701 * dwFlags [I] CRYPT_FIRST: Start enumeration (for PP_ENUMALGS{_EX}).
2707 * Defined dwParam types:
2708 * - PP_CONTAINER: Name of the key container.
2709 * - PP_NAME: Name of the cryptographic service provider.
2710 * - PP_SIG_KEYSIZE_INC: RSA signature keywidth granularity in bits.
2711 * - PP_KEYX_KEYSIZE_INC: RSA key-exchange keywidth granularity in bits.
2712 * - PP_ENUMALGS{_EX}: Query provider capabilities.
2714 BOOL WINAPI RSAENH_CPGetProvParam(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData,
2715 DWORD *pdwDataLen, DWORD dwFlags)
2717 KEYCONTAINER *pKeyContainer;
2718 PROV_ENUMALGS provEnumalgs;
2721 /* This is for dwParam 41, which does not seem to be documented
2722 * on MSDN. IE6 SP1 asks for it in the 'About' dialog, however.
2723 * Returning this BLOB seems to satisfy IE. The marked 0x00 seem
2724 * to be 'don't care's. If you know anything more specific about
2725 * provider parameter 41, please report to wine-devel@winehq.org */
2726 static CONST BYTE abWTF[96] = {
2727 0xb0, 0x25, 0x63, 0x86, 0x9c, 0xab, 0xb6, 0x37,
2728 0xe8, 0x82, /**/0x00,/**/ 0x72, 0x06, 0xb2, /**/0x00,/**/ 0x3b,
2729 0x60, 0x35, /**/0x00,/**/ 0x3b, 0x88, 0xce, /**/0x00,/**/ 0x82,
2730 0xbc, 0x7a, /**/0x00,/**/ 0xb7, 0x4f, 0x7e, /**/0x00,/**/ 0xde,
2731 0x92, 0xf1, /**/0x00,/**/ 0x83, 0xea, 0x5e, /**/0x00,/**/ 0xc8,
2732 0x12, 0x1e, 0xd4, 0x06, 0xf7, 0x66, /**/0x00,/**/ 0x01,
2733 0x29, 0xa4, /**/0x00,/**/ 0xf8, 0x24, 0x0c, /**/0x00,/**/ 0x33,
2734 0x06, 0x80, /**/0x00,/**/ 0x02, 0x46, 0x0b, /**/0x00,/**/ 0x6d,
2735 0x5b, 0xca, /**/0x00,/**/ 0x9a, 0x10, 0xf0, /**/0x00,/**/ 0x05,
2736 0x19, 0xd0, /**/0x00,/**/ 0x2c, 0xf6, 0x27, /**/0x00,/**/ 0xaa,
2737 0x7c, 0x6f, /**/0x00,/**/ 0xb9, 0xd8, 0x72, /**/0x00,/**/ 0x03,
2738 0xf3, 0x81, /**/0x00,/**/ 0xfa, 0xe8, 0x26, /**/0x00,/**/ 0xca
2741 TRACE("(hProv=%08lx, dwParam=%08lx, pbData=%p, pdwDataLen=%p, dwFlags=%08lx)\n",
2742 hProv, dwParam, pbData, pdwDataLen, dwFlags);
2744 if (!lookup_handle(&handle_table, (unsigned int)hProv, RSAENH_MAGIC_CONTAINER,
2745 (OBJECTHDR**)&pKeyContainer))
2747 /* MSDN: hProv not containing valid context handle */
2748 SetLastError(NTE_BAD_UID);
2755 return copy_param(pbData, pdwDataLen, (CONST BYTE*)pKeyContainer->szName,
2756 strlen(pKeyContainer->szName)+1);
2759 return copy_param(pbData, pdwDataLen, (CONST BYTE*)pKeyContainer->szProvName,
2760 strlen(pKeyContainer->szProvName)+1);
2762 case PP_SIG_KEYSIZE_INC:
2763 case PP_KEYX_KEYSIZE_INC:
2765 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp));
2768 case PP_ENUMALGS_EX:
2769 if (((pKeyContainer->dwEnumAlgsCtr >= RSAENH_MAX_ENUMALGS-1) ||
2770 (!aProvEnumAlgsEx[pKeyContainer->dwPersonality]
2771 [pKeyContainer->dwEnumAlgsCtr+1].aiAlgid)) &&
2772 ((dwFlags & CRYPT_FIRST) != CRYPT_FIRST))
2774 SetLastError(ERROR_NO_MORE_ITEMS);
2778 if (dwParam == PP_ENUMALGS) {
2779 if (pbData && (*pdwDataLen >= sizeof(PROV_ENUMALGS)))
2780 pKeyContainer->dwEnumAlgsCtr = ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) ?
2781 0 : pKeyContainer->dwEnumAlgsCtr+1;
2783 provEnumalgs.aiAlgid = aProvEnumAlgsEx
2784 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].aiAlgid;
2785 provEnumalgs.dwBitLen = aProvEnumAlgsEx
2786 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].dwDefaultLen;
2787 provEnumalgs.dwNameLen = aProvEnumAlgsEx
2788 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].dwNameLen;
2789 memcpy(provEnumalgs.szName, aProvEnumAlgsEx
2790 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].szName,
2793 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&provEnumalgs,
2794 sizeof(PROV_ENUMALGS));
2796 if (pbData && (*pdwDataLen >= sizeof(PROV_ENUMALGS_EX)))
2797 pKeyContainer->dwEnumAlgsCtr = ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) ?
2798 0 : pKeyContainer->dwEnumAlgsCtr+1;
2800 return copy_param(pbData, pdwDataLen,
2801 (CONST BYTE*)&aProvEnumAlgsEx
2802 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr],
2803 sizeof(PROV_ENUMALGS_EX));
2806 case 41: /* Undocumented. Asked for by IE About dialog */
2807 return copy_param(pbData, pdwDataLen, abWTF, sizeof(abWTF));
2810 /* MSDN: Unknown parameter number in dwParam */
2811 SetLastError(NTE_BAD_TYPE);
2816 /******************************************************************************
2817 * CPDeriveKey (RSAENH.@)
2819 * Derives a key from a hash value.
2822 * hProv [I] Key container for which a key is to be generated.
2823 * Algid [I] Crypto algorithm identifier for the key to be generated.
2824 * hBaseData [I] Hash from whose value the key will be derived.
2825 * dwFlags [I] See Notes.
2826 * phKey [O] The generated key.
2834 * - CRYPT_EXPORTABLE: Key can be exported.
2835 * - CRYPT_NO_SALT: No salt is used for 40 bit keys.
2836 * - CRYPT_CREATE_SALT: Use remaining bits as salt value.
2838 BOOL WINAPI RSAENH_CPDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData,
2839 DWORD dwFlags, HCRYPTKEY *phKey)
2841 CRYPTKEY *pCryptKey, *pMasterKey;
2842 CRYPTHASH *pCryptHash;
2843 BYTE abHashValue[RSAENH_MAX_HASH_SIZE*2];
2846 TRACE("(hProv=%08lx, Algid=%d, hBaseData=%08lx, dwFlags=%08lx phKey=%p)\n", hProv, Algid,
2847 hBaseData, dwFlags, phKey);
2849 if (!is_valid_handle(&handle_table, (unsigned int)hProv, RSAENH_MAGIC_CONTAINER))
2851 SetLastError(NTE_BAD_UID);
2855 if (!lookup_handle(&handle_table, (unsigned int)hBaseData, RSAENH_MAGIC_HASH,
2856 (OBJECTHDR**)&pCryptHash))
2858 SetLastError(NTE_BAD_HASH);
2864 SetLastError(ERROR_INVALID_PARAMETER);
2868 switch (GET_ALG_CLASS(Algid))
2870 case ALG_CLASS_DATA_ENCRYPT:
2871 *phKey = new_key(hProv, Algid, dwFlags, &pCryptKey);
2872 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
2875 * We derive the key material from the hash.
2876 * If the hash value is not large enough for the claimed key, we have to construct
2877 * a larger binary value based on the hash. This is documented in MSDN: CryptDeriveKey.
2879 dwLen = RSAENH_MAX_HASH_SIZE;
2880 RSAENH_CPGetHashParam(pCryptHash->hProv, hBaseData, HP_HASHVAL, abHashValue, &dwLen, 0);
2882 if (dwLen < pCryptKey->dwKeyLen) {
2883 BYTE pad1[RSAENH_HMAC_DEF_PAD_LEN], pad2[RSAENH_HMAC_DEF_PAD_LEN];
2884 BYTE old_hashval[RSAENH_MAX_HASH_SIZE];
2887 memcpy(old_hashval, pCryptHash->abHashValue, RSAENH_MAX_HASH_SIZE);
2889 for (i=0; i<RSAENH_HMAC_DEF_PAD_LEN; i++) {
2890 pad1[i] = RSAENH_HMAC_DEF_IPAD_CHAR ^ (i<dwLen ? abHashValue[i] : 0);
2891 pad2[i] = RSAENH_HMAC_DEF_OPAD_CHAR ^ (i<dwLen ? abHashValue[i] : 0);
2894 init_hash(pCryptHash);
2895 update_hash(pCryptHash, pad1, RSAENH_HMAC_DEF_PAD_LEN);
2896 finalize_hash(pCryptHash);
2897 memcpy(abHashValue, pCryptHash->abHashValue, pCryptHash->dwHashSize);
2899 init_hash(pCryptHash);
2900 update_hash(pCryptHash, pad2, RSAENH_HMAC_DEF_PAD_LEN);
2901 finalize_hash(pCryptHash);
2902 memcpy(abHashValue+pCryptHash->dwHashSize, pCryptHash->abHashValue,
2903 pCryptHash->dwHashSize);
2905 memcpy(pCryptHash->abHashValue, old_hashval, RSAENH_MAX_HASH_SIZE);
2908 memcpy(pCryptKey->abKeyValue, abHashValue,
2909 RSAENH_MIN(pCryptKey->dwKeyLen, sizeof(pCryptKey->abKeyValue)));
2912 case ALG_CLASS_MSG_ENCRYPT:
2913 if (!lookup_handle(&handle_table, pCryptHash->hKey, RSAENH_MAGIC_KEY,
2914 (OBJECTHDR**)&pMasterKey))
2916 SetLastError(NTE_FAIL); /* FIXME error code */
2922 /* See RFC 2246, chapter 6.3 Key calculation */
2923 case CALG_SCHANNEL_ENC_KEY:
2924 *phKey = new_key(hProv, pMasterKey->siSChannelInfo.saEncAlg.Algid,
2925 MAKELONG(LOWORD(dwFlags),pMasterKey->siSChannelInfo.saEncAlg.cBits),
2927 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
2928 memcpy(pCryptKey->abKeyValue,
2929 pCryptHash->abHashValue + (
2930 2 * (pMasterKey->siSChannelInfo.saMACAlg.cBits / 8) +
2931 ((dwFlags & CRYPT_SERVER) ?
2932 (pMasterKey->siSChannelInfo.saEncAlg.cBits / 8) : 0)),
2933 pMasterKey->siSChannelInfo.saEncAlg.cBits / 8);
2934 memcpy(pCryptKey->abInitVector,
2935 pCryptHash->abHashValue + (
2936 2 * (pMasterKey->siSChannelInfo.saMACAlg.cBits / 8) +
2937 2 * (pMasterKey->siSChannelInfo.saEncAlg.cBits / 8) +
2938 ((dwFlags & CRYPT_SERVER) ? pCryptKey->dwBlockLen : 0)),
2939 pCryptKey->dwBlockLen);
2942 case CALG_SCHANNEL_MAC_KEY:
2943 *phKey = new_key(hProv, Algid,
2944 MAKELONG(LOWORD(dwFlags),pMasterKey->siSChannelInfo.saMACAlg.cBits),
2946 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
2947 memcpy(pCryptKey->abKeyValue,
2948 pCryptHash->abHashValue + ((dwFlags & CRYPT_SERVER) ?
2949 pMasterKey->siSChannelInfo.saMACAlg.cBits / 8 : 0),
2950 pMasterKey->siSChannelInfo.saMACAlg.cBits / 8);
2954 SetLastError(NTE_BAD_ALGID);
2960 SetLastError(NTE_BAD_ALGID);
2964 setup_key(pCryptKey);
2968 /******************************************************************************
2969 * CPGetUserKey (RSAENH.@)
2971 * Returns a handle to the user's private key-exchange- or signature-key.
2974 * hProv [I] The key container from which a user key is requested.
2975 * dwKeySpec [I] AT_KEYEXCHANGE or AT_SIGNATURE
2976 * phUserKey [O] Handle to the requested key or INVALID_HANDLE_VALUE in case of failure.
2983 * A newly created key container does not contain private user key. Create them with CPGenKey.
2985 BOOL WINAPI RSAENH_CPGetUserKey(HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey)
2987 KEYCONTAINER *pKeyContainer;
2989 TRACE("(hProv=%08lx, dwKeySpec=%08lx, phUserKey=%p)\n", hProv, dwKeySpec, phUserKey);
2991 if (!lookup_handle(&handle_table, (unsigned int)hProv, RSAENH_MAGIC_CONTAINER,
2992 (OBJECTHDR**)&pKeyContainer))
2994 /* MSDN: hProv not containing valid context handle */
2995 SetLastError(NTE_BAD_UID);
3001 case AT_KEYEXCHANGE:
3002 copy_handle(&handle_table, pKeyContainer->hKeyExchangeKeyPair, RSAENH_MAGIC_KEY,
3003 (unsigned int*)phUserKey);
3007 copy_handle(&handle_table, pKeyContainer->hSignatureKeyPair, RSAENH_MAGIC_KEY,
3008 (unsigned int*)phUserKey);
3012 *phUserKey = (HCRYPTKEY)INVALID_HANDLE_VALUE;
3015 if (*phUserKey == (HCRYPTKEY)INVALID_HANDLE_VALUE)
3017 /* MSDN: dwKeySpec parameter specifies non existent key */
3018 SetLastError(NTE_NO_KEY);
3025 /******************************************************************************
3026 * CPHashData (RSAENH.@)
3028 * Updates a hash object with the given data.
3031 * hProv [I] Key container to which the hash object belongs.
3032 * hHash [I] Hash object which is to be updated.
3033 * pbData [I] Pointer to data with which the hash object is to be updated.
3034 * dwDataLen [I] Length of the data.
3035 * dwFlags [I] Currently none defined.
3042 * The actual hash value is queried with CPGetHashParam, which will finalize
3043 * the hash. Updating a finalized hash will fail with a last error NTE_BAD_HASH_STATE.
3045 BOOL WINAPI RSAENH_CPHashData(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST BYTE *pbData,
3046 DWORD dwDataLen, DWORD dwFlags)
3048 CRYPTHASH *pCryptHash;
3050 TRACE("(hProv=%08lx, hHash=%08lx, pbData=%p, dwDataLen=%ld, dwFlags=%08lx)\n",
3051 hProv, hHash, pbData, dwDataLen, dwFlags);
3055 SetLastError(NTE_BAD_FLAGS);
3059 if (!lookup_handle(&handle_table, (unsigned int)hHash, RSAENH_MAGIC_HASH,
3060 (OBJECTHDR**)&pCryptHash))
3062 SetLastError(NTE_BAD_HASH);
3066 if (!get_algid_info(hProv, pCryptHash->aiAlgid) || pCryptHash->aiAlgid == CALG_SSL3_SHAMD5)
3068 SetLastError(NTE_BAD_ALGID);
3072 if (pCryptHash->dwState == RSAENH_HASHSTATE_IDLE)
3073 pCryptHash->dwState = RSAENH_HASHSTATE_HASHING;
3075 if (pCryptHash->dwState != RSAENH_HASHSTATE_HASHING)
3077 SetLastError(NTE_BAD_HASH_STATE);
3081 update_hash(pCryptHash, pbData, dwDataLen);
3085 /******************************************************************************
3086 * CPHashSessionKey (RSAENH.@)
3088 * Updates a hash object with the binary representation of a symmetric key.
3091 * hProv [I] Key container to which the hash object belongs.
3092 * hHash [I] Hash object which is to be updated.
3093 * hKey [I] The symmetric key, whose binary value will be added to the hash.
3094 * dwFlags [I] CRYPT_LITTLE_ENDIAN, if the binary key value shall be interpreted as little endian.
3100 BOOL WINAPI RSAENH_CPHashSessionKey(HCRYPTPROV hProv, HCRYPTHASH hHash, HCRYPTKEY hKey,
3103 BYTE abKeyValue[RSAENH_MAX_KEY_SIZE], bTemp;
3107 TRACE("(hProv=%08lx, hHash=%08lx, hKey=%08lx, dwFlags=%08lx)\n", hProv, hHash, hKey, dwFlags);
3109 if (!lookup_handle(&handle_table, (unsigned int)hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pKey) ||
3110 (GET_ALG_CLASS(pKey->aiAlgid) != ALG_CLASS_DATA_ENCRYPT))
3112 SetLastError(NTE_BAD_KEY);
3116 if (dwFlags & ~CRYPT_LITTLE_ENDIAN) {
3117 SetLastError(NTE_BAD_FLAGS);
3121 memcpy(abKeyValue, pKey->abKeyValue, pKey->dwKeyLen);
3122 if (!(dwFlags & CRYPT_LITTLE_ENDIAN)) {
3123 for (i=0; i<pKey->dwKeyLen/2; i++) {
3124 bTemp = abKeyValue[i];
3125 abKeyValue[i] = abKeyValue[pKey->dwKeyLen-i-1];
3126 abKeyValue[pKey->dwKeyLen-i-1] = bTemp;
3130 return RSAENH_CPHashData(hProv, hHash, abKeyValue, pKey->dwKeyLen, 0);
3133 /******************************************************************************
3134 * CPReleaseContext (RSAENH.@)
3136 * Release a key container.
3139 * hProv [I] Key container to be released.
3140 * dwFlags [I] Currently none defined.
3146 BOOL WINAPI RSAENH_CPReleaseContext(HCRYPTPROV hProv, DWORD dwFlags)
3148 TRACE("(hProv=%08lx, dwFlags=%08lx)\n", hProv, dwFlags);
3150 if (!release_handle(&handle_table, (unsigned int)hProv, RSAENH_MAGIC_CONTAINER))
3152 /* MSDN: hProv not containing valid context handle */
3153 SetLastError(NTE_BAD_UID);
3158 SetLastError(NTE_BAD_FLAGS);
3165 /******************************************************************************
3166 * CPSetHashParam (RSAENH.@)
3168 * Set a parameter of a hash object
3171 * hProv [I] The key container to which the key belongs.
3172 * hHash [I] The hash object for which a parameter is to be set.
3173 * dwParam [I] Parameter type. See Notes.
3174 * pbData [I] Pointer to the parameter value.
3175 * dwFlags [I] Currently none defined.
3182 * Currently only the HP_HMAC_INFO dwParam type is defined.
3183 * The HMAC_INFO struct will be deep copied into the hash object.
3184 * See Internet RFC 2104 for details on the HMAC algorithm.
3186 BOOL WINAPI RSAENH_CPSetHashParam(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam,
3187 BYTE *pbData, DWORD dwFlags)
3189 CRYPTHASH *pCryptHash;
3190 CRYPTKEY *pCryptKey;
3193 TRACE("(hProv=%08lx, hHash=%08lx, dwParam=%08lx, pbData=%p, dwFlags=%08lx)\n",
3194 hProv, hHash, dwParam, pbData, dwFlags);
3196 if (!is_valid_handle(&handle_table, (unsigned int)hProv, RSAENH_MAGIC_CONTAINER))
3198 SetLastError(NTE_BAD_UID);
3203 SetLastError(NTE_BAD_FLAGS);
3207 if (!lookup_handle(&handle_table, (unsigned int)hHash, RSAENH_MAGIC_HASH,
3208 (OBJECTHDR**)&pCryptHash))
3210 SetLastError(NTE_BAD_HASH);
3216 free_hmac_info(pCryptHash->pHMACInfo);
3217 if (!copy_hmac_info(&pCryptHash->pHMACInfo, (PHMAC_INFO)pbData)) return FALSE;
3219 if (!lookup_handle(&handle_table, pCryptHash->hKey, RSAENH_MAGIC_KEY,
3220 (OBJECTHDR**)&pCryptKey))
3222 SetLastError(NTE_FAIL); /* FIXME: correct error code? */
3226 for (i=0; i<RSAENH_MIN(pCryptKey->dwKeyLen,pCryptHash->pHMACInfo->cbInnerString); i++) {
3227 pCryptHash->pHMACInfo->pbInnerString[i] ^= pCryptKey->abKeyValue[i];
3229 for (i=0; i<RSAENH_MIN(pCryptKey->dwKeyLen,pCryptHash->pHMACInfo->cbOuterString); i++) {
3230 pCryptHash->pHMACInfo->pbOuterString[i] ^= pCryptKey->abKeyValue[i];
3233 init_hash(pCryptHash);
3237 memcpy(pCryptHash->abHashValue, pbData, pCryptHash->dwHashSize);
3238 pCryptHash->dwState = RSAENH_HASHSTATE_FINISHED;
3241 case HP_TLS1PRF_SEED:
3242 return copy_data_blob(&pCryptHash->tpPRFParams.blobSeed, (PCRYPT_DATA_BLOB)pbData);
3244 case HP_TLS1PRF_LABEL:
3245 return copy_data_blob(&pCryptHash->tpPRFParams.blobLabel, (PCRYPT_DATA_BLOB)pbData);
3248 SetLastError(NTE_BAD_TYPE);
3253 /******************************************************************************
3254 * CPSetProvParam (RSAENH.@)
3256 BOOL WINAPI RSAENH_CPSetProvParam(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags)
3262 /******************************************************************************
3263 * CPSignHash (RSAENH.@)
3265 * Sign a hash object
3268 * hProv [I] The key container, to which the hash object belongs.
3269 * hHash [I] The hash object to be signed.
3270 * dwKeySpec [I] AT_SIGNATURE or AT_KEYEXCHANGE: Key used to generate the signature.
3271 * sDescription [I] Should be NULL for security reasons.
3272 * dwFlags [I] 0, CRYPT_NOHASHOID or CRYPT_X931_FORMAT: Format of the signature.
3273 * pbSignature [O] Buffer, to which the signature will be stored. May be NULL to query SigLen.
3274 * pdwSigLen [I/O] Size of the buffer (in), Length of the signature (out)
3280 BOOL WINAPI RSAENH_CPSignHash(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwKeySpec,
3281 LPCWSTR sDescription, DWORD dwFlags, BYTE *pbSignature,
3284 HCRYPTKEY hCryptKey;
3285 CRYPTKEY *pCryptKey;
3287 BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
3290 TRACE("(hProv=%08lx, hHash=%08lx, dwKeySpec=%08lx, sDescription=%s, dwFlags=%08lx, "
3291 "pbSignature=%p, pdwSigLen=%p)\n", hProv, hHash, dwKeySpec, debugstr_w(sDescription),
3292 dwFlags, pbSignature, pdwSigLen);
3294 if (dwFlags & ~(CRYPT_NOHASHOID|CRYPT_X931_FORMAT)) {
3295 SetLastError(NTE_BAD_FLAGS);
3299 if (!RSAENH_CPGetUserKey(hProv, dwKeySpec, &hCryptKey)) return FALSE;
3301 if (!lookup_handle(&handle_table, (unsigned int)hCryptKey, RSAENH_MAGIC_KEY,
3302 (OBJECTHDR**)&pCryptKey))
3304 SetLastError(NTE_NO_KEY);
3309 *pdwSigLen = pCryptKey->dwKeyLen;
3312 if (pCryptKey->dwKeyLen > *pdwSigLen)
3314 SetLastError(ERROR_MORE_DATA);
3315 *pdwSigLen = pCryptKey->dwKeyLen;
3318 *pdwSigLen = pCryptKey->dwKeyLen;
3321 if (!RSAENH_CPHashData(hProv, hHash, (CONST BYTE*)sDescription,
3322 (DWORD)lstrlenW(sDescription)*sizeof(WCHAR), 0))
3328 dwHashLen = sizeof(DWORD);
3329 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_ALGID, (BYTE*)&aiAlgid, &dwHashLen, 0)) return FALSE;
3331 dwHashLen = RSAENH_MAX_HASH_SIZE;
3332 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_HASHVAL, abHashValue, &dwHashLen, 0)) return FALSE;
3335 if (!build_hash_signature(pbSignature, *pdwSigLen, aiAlgid, abHashValue, dwHashLen, dwFlags)) {
3339 return encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbSignature, pbSignature, RSAENH_ENCRYPT);
3342 /******************************************************************************
3343 * CPVerifySignature (RSAENH.@)
3345 * Verify the signature of a hash object.
3348 * hProv [I] The key container, to which the hash belongs.
3349 * hHash [I] The hash for which the signature is verified.
3350 * pbSignature [I] The binary signature.
3351 * dwSigLen [I] Length of the signature BLOB.
3352 * hPubKey [I] Public key used to verify the signature.
3353 * sDescription [I] Should be NULL for security reasons.
3354 * dwFlags [I] 0, CRYPT_NOHASHOID or CRYPT_X931_FORMAT: Format of the signature.
3357 * Success: TRUE (Signature is valid)
3358 * Failure: FALSE (GetLastError() == NTE_BAD_SIGNATURE, if signature is invalid)
3360 BOOL WINAPI RSAENH_CPVerifySignature(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST BYTE *pbSignature,
3361 DWORD dwSigLen, HCRYPTKEY hPubKey, LPCWSTR sDescription,
3364 BYTE *pbConstructed = NULL, *pbDecrypted = NULL;
3365 CRYPTKEY *pCryptKey;
3368 BYTE abHashValue[RSAENH_MAX_HASH_SIZE];
3371 TRACE("(hProv=%08lx, hHash=%08lx, pbSignature=%p, dwSigLen=%ld, hPubKey=%08lx, sDescription=%s, "
3372 "dwFlags=%08lx)\n", hProv, hHash, pbSignature, dwSigLen, hPubKey, debugstr_w(sDescription),
3375 if (dwFlags & ~(CRYPT_NOHASHOID|CRYPT_X931_FORMAT)) {
3376 SetLastError(NTE_BAD_FLAGS);
3380 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
3382 SetLastError(NTE_BAD_UID);
3386 if (!lookup_handle(&handle_table, (unsigned int)hPubKey, RSAENH_MAGIC_KEY,
3387 (OBJECTHDR**)&pCryptKey))
3389 SetLastError(NTE_BAD_KEY);
3394 if (!RSAENH_CPHashData(hProv, hHash, (CONST BYTE*)sDescription,
3395 (DWORD)lstrlenW(sDescription)*sizeof(WCHAR), 0))
3401 dwHashLen = sizeof(DWORD);
3402 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_ALGID, (BYTE*)&aiAlgid, &dwHashLen, 0)) return FALSE;
3404 dwHashLen = RSAENH_MAX_HASH_SIZE;
3405 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_HASHVAL, abHashValue, &dwHashLen, 0)) return FALSE;
3407 pbConstructed = HeapAlloc(GetProcessHeap(), 0, dwSigLen);
3408 if (!pbConstructed) {
3409 SetLastError(NTE_NO_MEMORY);
3413 pbDecrypted = HeapAlloc(GetProcessHeap(), 0, dwSigLen);
3415 SetLastError(NTE_NO_MEMORY);
3419 if (!encrypt_block_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbSignature, pbDecrypted,
3425 if (!build_hash_signature(pbConstructed, dwSigLen, aiAlgid, abHashValue, dwHashLen, dwFlags)) {
3429 if (memcmp(pbDecrypted, pbConstructed, dwSigLen)) {
3430 SetLastError(NTE_BAD_SIGNATURE);
3436 HeapFree(GetProcessHeap(), 0, pbConstructed);
3437 HeapFree(GetProcessHeap(), 0, pbDecrypted);
3441 static const WCHAR szProviderKeys[4][97] = {
3442 { 'S','o','f','t','w','a','r','e','\\',
3443 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3444 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3445 'i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ','B','a','s',
3446 'e',' ','C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r',
3447 'o','v','i','d','e','r',' ','v','1','.','0',0 },
3448 { 'S','o','f','t','w','a','r','e','\\',
3449 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3450 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3451 'i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ',
3452 'E','n','h','a','n','c','e','d',
3453 ' ','C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r',
3454 'o','v','i','d','e','r',' ','v','1','.','0',0 },
3455 { 'S','o','f','t','w','a','r','e','\\',
3456 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3457 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3458 'i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ','S','t','r','o','n','g',
3459 ' ','C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r',
3460 'o','v','i','d','e','r',0 },
3461 { 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
3462 'C','r','y','p','t','o','g','r','a','p','h','y','\\','D','e','f','a','u','l','t','s','\\',
3463 'P','r','o','v','i','d','e','r','\\','M','i','c','r','o','s','o','f','t',' ',
3464 'R','S','A',' ','S','C','h','a','n','n','e','l',' ',
3465 'C','r','y','p','t','o','g','r','a','p','h','i','c',' ','P','r','o','v','i','d','e','r',0 }
3467 static const WCHAR szDefaultKeys[2][65] = {
3468 { 'S','o','f','t','w','a','r','e','\\',
3469 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3470 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3471 'i','d','e','r',' ','T','y','p','e','s','\\','T','y','p','e',' ','0','0','1',0 },
3472 { 'S','o','f','t','w','a','r','e','\\',
3473 'M','i','c','r','o','s','o','f','t','\\','C','r','y','p','t','o','g','r',
3474 'a','p','h','y','\\','D','e','f','a','u','l','t','s','\\','P','r','o','v',
3475 'i','d','e','r',' ','T','y','p','e','s','\\','T','y','p','e',' ','0','1','2',0 }
3479 /******************************************************************************
3480 * DllRegisterServer (RSAENH.@)
3482 * Dll self registration.
3491 * Registers the following keys:
3492 * - HKLM\Software\Microsoft\Cryptography\Defaults\Provider\
3493 * Microsoft Base Cryptographic Provider v1.0
3494 * - HKLM\Software\Microsoft\Cryptography\Defaults\Provider\
3495 * Microsoft Enhanced Cryptographic Provider
3496 * - HKLM\Software\Microsoft\Cryptography\Defaults\Provider\
3497 * Microsoft Strong Cryptographpic Provider
3498 * - HKLM\Software\Microsoft\Cryptography\Defaults\Provider Types\Type 001
3500 HRESULT WINAPI RSAENH_DllRegisterServer()
3507 for (i=0; i<4; i++) {
3508 apiRet = RegCreateKeyExW(HKEY_LOCAL_MACHINE, szProviderKeys[i], 0, NULL,
3509 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dp);
3511 if (apiRet == ERROR_SUCCESS)
3513 if (dp == REG_CREATED_NEW_KEY)
3515 static const WCHAR szImagePath[] = { 'I','m','a','g','e',' ','P','a','t','h',0 };
3516 static const WCHAR szRSABase[] = { 'r','s','a','e','n','h','.','d','l','l',0 };
3517 static const WCHAR szType[] = { 'T','y','p','e',0 };
3518 static const WCHAR szSignature[] = { 'S','i','g','n','a','t','u','r','e',0 };
3519 DWORD type = (i == 3) ? PROV_RSA_SCHANNEL : PROV_RSA_FULL;
3520 DWORD sign = 0xdeadbeef;
3521 RegSetValueExW(key, szImagePath, 0, REG_SZ, (LPBYTE)szRSABase,
3522 (lstrlenW(szRSABase) + 1) * sizeof(WCHAR));
3523 RegSetValueExW(key, szType, 0, REG_DWORD, (LPBYTE)&type, sizeof(type));
3524 RegSetValueExW(key, szSignature, 0, REG_BINARY, (LPBYTE)&sign, sizeof(sign));
3530 for (i=0; i<2; i++) {
3531 apiRet = RegCreateKeyExW(HKEY_LOCAL_MACHINE, szDefaultKeys[i], 0, NULL,
3532 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &dp);
3533 if (apiRet == ERROR_SUCCESS)
3535 if (dp == REG_CREATED_NEW_KEY)
3537 static const WCHAR szName[] = { 'N','a','m','e',0 };
3538 static const WCHAR szRSAName[2][46] = {
3539 { 'M','i','c','r','o','s','o','f','t',' ', 'B','a','s','e',' ',
3540 'C','r','y','p','t','o','g','r','a','p','h','i','c',' ',
3541 'P','r','o','v','i','d','e','r',' ','v','1','.','0',0 },
3542 { 'M','i','c','r','o','s','o','f','t',' ','R','S','A',' ',
3543 'S','C','h','a','n','n','e','l',' ',
3544 'C','r','y','p','t','o','g','r','a','p','h','i','c',' ',
3545 'P','r','o','v','i','d','e','r',0 } };
3546 static const WCHAR szTypeName[] = { 'T','y','p','e','N','a','m','e',0 };
3547 static const WCHAR szRSATypeName[2][38] = {
3548 { 'R','S','A',' ','F','u','l','l',' ',
3549 '(','S','i','g','n','a','t','u','r','e',' ','a','n','d',' ',
3550 'K','e','y',' ','E','x','c','h','a','n','g','e',')',0 },
3551 { 'R','S','A',' ','S','C','h','a','n','n','e','l',0 } };
3553 RegSetValueExW(key, szName, 0, REG_SZ, (LPBYTE)szRSAName[i], sizeof(szRSAName));
3554 RegSetValueExW(key, szTypeName, 0, REG_SZ,
3555 (LPBYTE)szRSATypeName[i],sizeof(szRSATypeName));
3561 return HRESULT_FROM_WIN32(apiRet);
3564 /******************************************************************************
3565 * DllUnregisterServer (RSAENH.@)
3567 * Dll self unregistration.
3575 * For the relevant keys see DllRegisterServer.
3577 HRESULT WINAPI RSAENH_DllUnregisterServer()
3579 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[0]);
3580 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[1]);
3581 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[2]);
3582 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szProviderKeys[3]);
3583 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szDefaultKeys[0]);
3584 RegDeleteKeyW(HKEY_LOCAL_MACHINE, szDefaultKeys[1]);