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