Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenrsaenh.c
Go to the documentation of this file.
00001 /* 00002 * dlls/rsaenh/rsaenh.c 00003 * RSAENH - RSA encryption for Wine 00004 * 00005 * Copyright 2002 TransGaming Technologies (David Hammerton) 00006 * Copyright 2004 Mike McCormack for CodeWeavers 00007 * Copyright 2004, 2005 Michael Jung 00008 * Copyright 2007 Vijay Kiran Kamuju 00009 * 00010 * This library is free software; you can redistribute it and/or 00011 * modify it under the terms of the GNU Lesser General Public 00012 * License as published by the Free Software Foundation; either 00013 * version 2.1 of the License, or (at your option) any later version. 00014 * 00015 * This library is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 * Lesser General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU Lesser General Public 00021 * License along with this library; if not, write to the Free Software 00022 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00023 */ 00024 00025 #include "config.h" 00026 #include "wine/port.h" 00027 #include "wine/library.h" 00028 #include "wine/debug.h" 00029 00030 #include <stdarg.h> 00031 #include <stdio.h> 00032 00033 #include "windef.h" 00034 #include "winbase.h" 00035 #include "winreg.h" 00036 #include "wincrypt.h" 00037 #include "handle.h" 00038 #include "implglue.h" 00039 #include "objbase.h" 00040 #include "rpcproxy.h" 00041 00042 WINE_DEFAULT_DEBUG_CHANNEL(crypt); 00043 00044 static HINSTANCE instance; 00045 00046 /****************************************************************************** 00047 * CRYPTHASH - hash objects 00048 */ 00049 #define RSAENH_MAGIC_HASH 0x85938417u 00050 #define RSAENH_MAX_HASH_SIZE 104 00051 #define RSAENH_HASHSTATE_HASHING 1 00052 #define RSAENH_HASHSTATE_FINISHED 2 00053 typedef struct _RSAENH_TLS1PRF_PARAMS 00054 { 00055 CRYPT_DATA_BLOB blobLabel; 00056 CRYPT_DATA_BLOB blobSeed; 00057 } RSAENH_TLS1PRF_PARAMS; 00058 00059 typedef struct tagCRYPTHASH 00060 { 00061 OBJECTHDR header; 00062 ALG_ID aiAlgid; 00063 HCRYPTKEY hKey; 00064 HCRYPTPROV hProv; 00065 DWORD dwHashSize; 00066 DWORD dwState; 00067 HASH_CONTEXT context; 00068 BYTE abHashValue[RSAENH_MAX_HASH_SIZE]; 00069 PHMAC_INFO pHMACInfo; 00070 RSAENH_TLS1PRF_PARAMS tpPRFParams; 00071 } CRYPTHASH; 00072 00073 /****************************************************************************** 00074 * CRYPTKEY - key objects 00075 */ 00076 #define RSAENH_MAGIC_KEY 0x73620457u 00077 #define RSAENH_MAX_KEY_SIZE 64 00078 #define RSAENH_MAX_BLOCK_SIZE 24 00079 #define RSAENH_KEYSTATE_IDLE 0 00080 #define RSAENH_KEYSTATE_ENCRYPTING 1 00081 #define RSAENH_KEYSTATE_MASTERKEY 2 00082 typedef struct _RSAENH_SCHANNEL_INFO 00083 { 00084 SCHANNEL_ALG saEncAlg; 00085 SCHANNEL_ALG saMACAlg; 00086 CRYPT_DATA_BLOB blobClientRandom; 00087 CRYPT_DATA_BLOB blobServerRandom; 00088 } RSAENH_SCHANNEL_INFO; 00089 00090 typedef struct tagCRYPTKEY 00091 { 00092 OBJECTHDR header; 00093 ALG_ID aiAlgid; 00094 HCRYPTPROV hProv; 00095 DWORD dwMode; 00096 DWORD dwModeBits; 00097 DWORD dwPermissions; 00098 DWORD dwKeyLen; 00099 DWORD dwEffectiveKeyLen; 00100 DWORD dwSaltLen; 00101 DWORD dwBlockLen; 00102 DWORD dwState; 00103 KEY_CONTEXT context; 00104 BYTE abKeyValue[RSAENH_MAX_KEY_SIZE]; 00105 BYTE abInitVector[RSAENH_MAX_BLOCK_SIZE]; 00106 BYTE abChainVector[RSAENH_MAX_BLOCK_SIZE]; 00107 RSAENH_SCHANNEL_INFO siSChannelInfo; 00108 CRYPT_DATA_BLOB blobHmacKey; 00109 } CRYPTKEY; 00110 00111 /****************************************************************************** 00112 * KEYCONTAINER - key containers 00113 */ 00114 #define RSAENH_PERSONALITY_BASE 0u 00115 #define RSAENH_PERSONALITY_STRONG 1u 00116 #define RSAENH_PERSONALITY_ENHANCED 2u 00117 #define RSAENH_PERSONALITY_SCHANNEL 3u 00118 #define RSAENH_PERSONALITY_AES 4u 00119 00120 #define RSAENH_MAGIC_CONTAINER 0x26384993u 00121 typedef struct tagKEYCONTAINER 00122 { 00123 OBJECTHDR header; 00124 DWORD dwFlags; 00125 DWORD dwPersonality; 00126 DWORD dwEnumAlgsCtr; 00127 DWORD dwEnumContainersCtr; 00128 CHAR szName[MAX_PATH]; 00129 CHAR szProvName[MAX_PATH]; 00130 HCRYPTKEY hKeyExchangeKeyPair; 00131 HCRYPTKEY hSignatureKeyPair; 00132 } KEYCONTAINER; 00133 00134 /****************************************************************************** 00135 * Some magic constants 00136 */ 00137 #define RSAENH_ENCRYPT 1 00138 #define RSAENH_DECRYPT 0 00139 #define RSAENH_HMAC_DEF_IPAD_CHAR 0x36 00140 #define RSAENH_HMAC_DEF_OPAD_CHAR 0x5c 00141 #define RSAENH_HMAC_DEF_PAD_LEN 64 00142 #define RSAENH_HMAC_BLOCK_LEN 64 00143 #define RSAENH_DES_EFFECTIVE_KEYLEN 56 00144 #define RSAENH_DES_STORAGE_KEYLEN 64 00145 #define RSAENH_3DES112_EFFECTIVE_KEYLEN 112 00146 #define RSAENH_3DES112_STORAGE_KEYLEN 128 00147 #define RSAENH_3DES_EFFECTIVE_KEYLEN 168 00148 #define RSAENH_3DES_STORAGE_KEYLEN 192 00149 #define RSAENH_MAGIC_RSA2 0x32415352 00150 #define RSAENH_MAGIC_RSA1 0x31415352 00151 #define RSAENH_PKC_BLOCKTYPE 0x02 00152 #define RSAENH_SSL3_VERSION_MAJOR 3 00153 #define RSAENH_SSL3_VERSION_MINOR 0 00154 #define RSAENH_TLS1_VERSION_MAJOR 3 00155 #define RSAENH_TLS1_VERSION_MINOR 1 00156 #define RSAENH_REGKEY "Software\\Wine\\Crypto\\RSA\\%s" 00157 00158 #define RSAENH_MIN(a,b) ((a)<(b)?(a):(b)) 00159 /****************************************************************************** 00160 * aProvEnumAlgsEx - Defines the capabilities of the CSP personalities. 00161 */ 00162 #define RSAENH_MAX_ENUMALGS 24 00163 #define RSAENH_PCT1_SSL2_SSL3_TLS1 (CRYPT_FLAG_PCT1|CRYPT_FLAG_SSL2|CRYPT_FLAG_SSL3|CRYPT_FLAG_TLS1) 00164 static const PROV_ENUMALGS_EX aProvEnumAlgsEx[5][RSAENH_MAX_ENUMALGS+1] = 00165 { 00166 { 00167 {CALG_RC2, 40, 40, 56,0, 4,"RC2", 24,"RSA Data Security's RC2"}, 00168 {CALG_RC4, 40, 40, 56,0, 4,"RC4", 24,"RSA Data Security's RC4"}, 00169 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"}, 00170 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"}, 00171 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"}, 00172 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"}, 00173 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"}, 00174 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"}, 00175 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"}, 00176 {CALG_RSA_SIGN, 512,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"}, 00177 {CALG_RSA_KEYX, 512,384, 1024,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"}, 00178 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"}, 00179 {0, 0, 0, 0,0, 1,"", 1,""} 00180 }, 00181 { 00182 {CALG_RC2, 128, 40, 128,0, 4,"RC2", 24,"RSA Data Security's RC2"}, 00183 {CALG_RC4, 128, 40, 128,0, 4,"RC4", 24,"RSA Data Security's RC4"}, 00184 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"}, 00185 {CALG_3DES_112, 112,112, 112,0, 13,"3DES TWO KEY",19,"Two Key Triple DES"}, 00186 {CALG_3DES, 168,168, 168,0, 5,"3DES", 21,"Three Key Triple DES"}, 00187 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"}, 00188 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"}, 00189 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"}, 00190 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"}, 00191 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"}, 00192 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"}, 00193 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"}, 00194 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"}, 00195 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"}, 00196 {0, 0, 0, 0,0, 1,"", 1,""} 00197 }, 00198 { 00199 {CALG_RC2, 128, 40, 128,0, 4,"RC2", 24,"RSA Data Security's RC2"}, 00200 {CALG_RC4, 128, 40, 128,0, 4,"RC4", 24,"RSA Data Security's RC4"}, 00201 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"}, 00202 {CALG_3DES_112, 112,112, 112,0, 13,"3DES TWO KEY",19,"Two Key Triple DES"}, 00203 {CALG_3DES, 168,168, 168,0, 5,"3DES", 21,"Three Key Triple DES"}, 00204 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"}, 00205 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"}, 00206 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"}, 00207 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"}, 00208 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"}, 00209 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"}, 00210 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"}, 00211 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"}, 00212 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"}, 00213 {0, 0, 0, 0,0, 1,"", 1,""} 00214 }, 00215 { 00216 {CALG_RC2, 128, 40, 128,RSAENH_PCT1_SSL2_SSL3_TLS1, 4,"RC2", 24,"RSA Data Security's RC2"}, 00217 {CALG_RC4, 128, 40, 128,RSAENH_PCT1_SSL2_SSL3_TLS1, 4,"RC4", 24,"RSA Data Security's RC4"}, 00218 {CALG_DES, 56, 56, 56,RSAENH_PCT1_SSL2_SSL3_TLS1, 4,"DES", 31,"Data Encryption Standard (DES)"}, 00219 {CALG_3DES_112, 112,112, 112,RSAENH_PCT1_SSL2_SSL3_TLS1,13,"3DES TWO KEY",19,"Two Key Triple DES"}, 00220 {CALG_3DES, 168,168, 168,RSAENH_PCT1_SSL2_SSL3_TLS1, 5,"3DES", 21,"Three Key Triple DES"}, 00221 {CALG_SHA,160,160,160,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,6,"SHA-1",30,"Secure Hash Algorithm (SHA-1)"}, 00222 {CALG_MD5,128,128,128,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,4,"MD5",23,"Message Digest 5 (MD5)"}, 00223 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"}, 00224 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"}, 00225 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,9,"RSA_SIGN",14,"RSA Signature"}, 00226 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|RSAENH_PCT1_SSL2_SSL3_TLS1,9,"RSA_KEYX",17,"RSA Key Exchange"}, 00227 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"}, 00228 {CALG_PCT1_MASTER,128,128,128,CRYPT_FLAG_PCT1, 12,"PCT1 MASTER",12,"PCT1 Master"}, 00229 {CALG_SSL2_MASTER,40,40, 192,CRYPT_FLAG_SSL2, 12,"SSL2 MASTER",12,"SSL2 Master"}, 00230 {CALG_SSL3_MASTER,384,384,384,CRYPT_FLAG_SSL3, 12,"SSL3 MASTER",12,"SSL3 Master"}, 00231 {CALG_TLS1_MASTER,384,384,384,CRYPT_FLAG_TLS1, 12,"TLS1 MASTER",12,"TLS1 Master"}, 00232 {CALG_SCHANNEL_MASTER_HASH,0,0,-1,0, 16,"SCH MASTER HASH",21,"SChannel Master Hash"}, 00233 {CALG_SCHANNEL_MAC_KEY,0,0,-1,0, 12,"SCH MAC KEY",17,"SChannel MAC Key"}, 00234 {CALG_SCHANNEL_ENC_KEY,0,0,-1,0, 12,"SCH ENC KEY",24,"SChannel Encryption Key"}, 00235 {CALG_TLS1PRF, 0, 0, -1,0, 9,"TLS1 PRF", 28,"TLS1 Pseudo Random Function"}, 00236 {0, 0, 0, 0,0, 1,"", 1,""} 00237 }, 00238 { 00239 {CALG_RC2, 128, 40, 128,0, 4,"RC2", 24,"RSA Data Security's RC2"}, 00240 {CALG_RC4, 128, 40, 128,0, 4,"RC4", 24,"RSA Data Security's RC4"}, 00241 {CALG_DES, 56, 56, 56,0, 4,"DES", 31,"Data Encryption Standard (DES)"}, 00242 {CALG_3DES_112, 112,112, 112,0, 13,"3DES TWO KEY",19,"Two Key Triple DES"}, 00243 {CALG_3DES, 168,168, 168,0, 5,"3DES", 21,"Three Key Triple DES"}, 00244 {CALG_AES, 128,128, 128,0, 4,"AES", 35,"Advanced Encryption Standard (AES)"}, 00245 {CALG_AES_128, 128,128, 128,0, 8,"AES-128", 39,"Advanced Encryption Standard (AES-128)"}, 00246 {CALG_AES_192, 192,192, 192,0, 8,"AES-192", 39,"Advanced Encryption Standard (AES-192)"}, 00247 {CALG_AES_256, 256,256, 256,0, 8,"AES-256", 39,"Advanced Encryption Standard (AES-256)"}, 00248 {CALG_SHA, 160,160, 160,CRYPT_FLAG_SIGNING, 6,"SHA-1", 30,"Secure Hash Algorithm (SHA-1)"}, 00249 {CALG_SHA_256, 256,256, 256,CRYPT_FLAG_SIGNING, 6,"SHA-256", 30,"Secure Hash Algorithm (SHA-256)"}, 00250 {CALG_SHA_384, 384,384, 384,CRYPT_FLAG_SIGNING, 6,"SHA-384", 30,"Secure Hash Algorithm (SHA-284)"}, 00251 {CALG_SHA_512, 512,512, 512,CRYPT_FLAG_SIGNING, 6,"SHA-512", 30,"Secure Hash Algorithm (SHA-512)"}, 00252 {CALG_MD2, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD2", 23,"Message Digest 2 (MD2)"}, 00253 {CALG_MD4, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD4", 23,"Message Digest 4 (MD4)"}, 00254 {CALG_MD5, 128,128, 128,CRYPT_FLAG_SIGNING, 4,"MD5", 23,"Message Digest 5 (MD5)"}, 00255 {CALG_SSL3_SHAMD5,288,288,288,0, 12,"SSL3 SHAMD5",12,"SSL3 SHAMD5"}, 00256 {CALG_MAC, 0, 0, 0,0, 4,"MAC", 28,"Message Authentication Code"}, 00257 {CALG_RSA_SIGN,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_SIGN",14,"RSA Signature"}, 00258 {CALG_RSA_KEYX,1024,384,16384,CRYPT_FLAG_SIGNING|CRYPT_FLAG_IPSEC,9,"RSA_KEYX",17,"RSA Key Exchange"}, 00259 {CALG_HMAC, 0, 0, 0,0, 5,"HMAC", 18,"Hugo's MAC (HMAC)"}, 00260 {0, 0, 0, 0,0, 1,"", 1,""} 00261 } 00262 }; 00263 00264 /****************************************************************************** 00265 * API forward declarations 00266 */ 00267 BOOL WINAPI 00268 RSAENH_CPGetKeyParam( 00269 HCRYPTPROV hProv, 00270 HCRYPTKEY hKey, 00271 DWORD dwParam, 00272 BYTE *pbData, 00273 DWORD *pdwDataLen, 00274 DWORD dwFlags 00275 ); 00276 00277 BOOL WINAPI 00278 RSAENH_CPEncrypt( 00279 HCRYPTPROV hProv, 00280 HCRYPTKEY hKey, 00281 HCRYPTHASH hHash, 00282 BOOL Final, 00283 DWORD dwFlags, 00284 BYTE *pbData, 00285 DWORD *pdwDataLen, 00286 DWORD dwBufLen 00287 ); 00288 00289 BOOL WINAPI 00290 RSAENH_CPCreateHash( 00291 HCRYPTPROV hProv, 00292 ALG_ID Algid, 00293 HCRYPTKEY hKey, 00294 DWORD dwFlags, 00295 HCRYPTHASH *phHash 00296 ); 00297 00298 BOOL WINAPI 00299 RSAENH_CPSetHashParam( 00300 HCRYPTPROV hProv, 00301 HCRYPTHASH hHash, 00302 DWORD dwParam, 00303 BYTE *pbData, DWORD dwFlags 00304 ); 00305 00306 BOOL WINAPI 00307 RSAENH_CPGetHashParam( 00308 HCRYPTPROV hProv, 00309 HCRYPTHASH hHash, 00310 DWORD dwParam, 00311 BYTE *pbData, 00312 DWORD *pdwDataLen, 00313 DWORD dwFlags 00314 ); 00315 00316 BOOL WINAPI 00317 RSAENH_CPDestroyHash( 00318 HCRYPTPROV hProv, 00319 HCRYPTHASH hHash 00320 ); 00321 00322 static BOOL crypt_export_key( 00323 CRYPTKEY *pCryptKey, 00324 HCRYPTKEY hPubKey, 00325 DWORD dwBlobType, 00326 DWORD dwFlags, 00327 BOOL force, 00328 BYTE *pbData, 00329 DWORD *pdwDataLen 00330 ); 00331 00332 static BOOL import_key( 00333 HCRYPTPROV hProv, 00334 CONST BYTE *pbData, 00335 DWORD dwDataLen, 00336 HCRYPTKEY hPubKey, 00337 DWORD dwFlags, 00338 BOOL fStoreKey, 00339 HCRYPTKEY *phKey 00340 ); 00341 00342 BOOL WINAPI 00343 RSAENH_CPHashData( 00344 HCRYPTPROV hProv, 00345 HCRYPTHASH hHash, 00346 CONST BYTE *pbData, 00347 DWORD dwDataLen, 00348 DWORD dwFlags 00349 ); 00350 00351 /****************************************************************************** 00352 * CSP's handle table (used by all acquired key containers) 00353 */ 00354 static struct handle_table handle_table; 00355 00356 /****************************************************************************** 00357 * DllMain (RSAENH.@) 00358 * 00359 * Initializes and destroys the handle table for the CSP's handles. 00360 */ 00361 int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) 00362 { 00363 switch (fdwReason) 00364 { 00365 case DLL_PROCESS_ATTACH: 00366 instance = hInstance; 00367 DisableThreadLibraryCalls(hInstance); 00368 init_handle_table(&handle_table); 00369 break; 00370 00371 case DLL_PROCESS_DETACH: 00372 destroy_handle_table(&handle_table); 00373 break; 00374 } 00375 return 1; 00376 } 00377 00378 /****************************************************************************** 00379 * copy_param [Internal] 00380 * 00381 * Helper function that supports the standard WINAPI protocol for querying data 00382 * of dynamic size. 00383 * 00384 * PARAMS 00385 * pbBuffer [O] Buffer where the queried parameter is copied to, if it is large enough. 00386 * May be NUL if the required buffer size is to be queried only. 00387 * pdwBufferSize [I/O] In: Size of the buffer at pbBuffer 00388 * Out: Size of parameter pbParam 00389 * pbParam [I] Parameter value. 00390 * dwParamSize [I] Size of pbParam 00391 * 00392 * RETURN 00393 * Success: TRUE (pbParam was copied into pbBuffer or pbBuffer is NULL) 00394 * Failure: FALSE (pbBuffer is not large enough to hold pbParam). Last error: ERROR_MORE_DATA 00395 */ 00396 static inline BOOL copy_param( 00397 BYTE *pbBuffer, DWORD *pdwBufferSize, CONST BYTE *pbParam, DWORD dwParamSize) 00398 { 00399 if (pbBuffer) 00400 { 00401 if (dwParamSize > *pdwBufferSize) 00402 { 00403 SetLastError(ERROR_MORE_DATA); 00404 *pdwBufferSize = dwParamSize; 00405 return FALSE; 00406 } 00407 memcpy(pbBuffer, pbParam, dwParamSize); 00408 } 00409 *pdwBufferSize = dwParamSize; 00410 return TRUE; 00411 } 00412 00413 /****************************************************************************** 00414 * get_algid_info [Internal] 00415 * 00416 * Query CSP capabilities for a given crypto algorithm. 00417 * 00418 * PARAMS 00419 * hProv [I] Handle to a key container of the CSP whose capabilities are to be queried. 00420 * algid [I] Identifier of the crypto algorithm about which information is requested. 00421 * 00422 * RETURNS 00423 * Success: Pointer to a PROV_ENUMALGS_EX struct containing information about the crypto algorithm. 00424 * Failure: NULL (algid not supported) 00425 */ 00426 static inline const PROV_ENUMALGS_EX* get_algid_info(HCRYPTPROV hProv, ALG_ID algid) { 00427 const PROV_ENUMALGS_EX *iterator; 00428 KEYCONTAINER *pKeyContainer; 00429 00430 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER, (OBJECTHDR**)&pKeyContainer)) { 00431 SetLastError(NTE_BAD_UID); 00432 return NULL; 00433 } 00434 00435 for (iterator = aProvEnumAlgsEx[pKeyContainer->dwPersonality]; iterator->aiAlgid; iterator++) { 00436 if (iterator->aiAlgid == algid) return iterator; 00437 } 00438 00439 SetLastError(NTE_BAD_ALGID); 00440 return NULL; 00441 } 00442 00443 /****************************************************************************** 00444 * copy_data_blob [Internal] 00445 * 00446 * deeply copies a DATA_BLOB 00447 * 00448 * PARAMS 00449 * dst [O] That's where the blob will be copied to 00450 * src [I] Source blob 00451 * 00452 * RETURNS 00453 * Success: TRUE 00454 * Failure: FALSE (GetLastError() == NTE_NO_MEMORY 00455 * 00456 * NOTES 00457 * Use free_data_blob to release resources occupied by copy_data_blob. 00458 */ 00459 static inline BOOL copy_data_blob(PCRYPT_DATA_BLOB dst, CONST PCRYPT_DATA_BLOB src) { 00460 dst->pbData = HeapAlloc(GetProcessHeap(), 0, src->cbData); 00461 if (!dst->pbData) { 00462 SetLastError(NTE_NO_MEMORY); 00463 return FALSE; 00464 } 00465 dst->cbData = src->cbData; 00466 memcpy(dst->pbData, src->pbData, src->cbData); 00467 return TRUE; 00468 } 00469 00470 /****************************************************************************** 00471 * concat_data_blobs [Internal] 00472 * 00473 * Concatenates two blobs 00474 * 00475 * PARAMS 00476 * dst [O] The new blob will be copied here 00477 * src1 [I] Prefix blob 00478 * src2 [I] Appendix blob 00479 * 00480 * RETURNS 00481 * Success: TRUE 00482 * Failure: FALSE (GetLastError() == NTE_NO_MEMORY) 00483 * 00484 * NOTES 00485 * Release resources occupied by concat_data_blobs with free_data_blobs 00486 */ 00487 static inline BOOL concat_data_blobs(PCRYPT_DATA_BLOB dst, CONST PCRYPT_DATA_BLOB src1, 00488 CONST PCRYPT_DATA_BLOB src2) 00489 { 00490 dst->cbData = src1->cbData + src2->cbData; 00491 dst->pbData = HeapAlloc(GetProcessHeap(), 0, dst->cbData); 00492 if (!dst->pbData) { 00493 SetLastError(NTE_NO_MEMORY); 00494 return FALSE; 00495 } 00496 memcpy(dst->pbData, src1->pbData, src1->cbData); 00497 memcpy(dst->pbData + src1->cbData, src2->pbData, src2->cbData); 00498 return TRUE; 00499 } 00500 00501 /****************************************************************************** 00502 * free_data_blob [Internal] 00503 * 00504 * releases resource occupied by a dynamically allocated CRYPT_DATA_BLOB 00505 * 00506 * PARAMS 00507 * pBlob [I] Heap space occupied by pBlob->pbData is released 00508 */ 00509 static inline void free_data_blob(PCRYPT_DATA_BLOB pBlob) { 00510 HeapFree(GetProcessHeap(), 0, pBlob->pbData); 00511 } 00512 00513 /****************************************************************************** 00514 * init_data_blob [Internal] 00515 */ 00516 static inline void init_data_blob(PCRYPT_DATA_BLOB pBlob) { 00517 pBlob->pbData = NULL; 00518 pBlob->cbData = 0; 00519 } 00520 00521 /****************************************************************************** 00522 * free_hmac_info [Internal] 00523 * 00524 * Deeply free an HMAC_INFO struct. 00525 * 00526 * PARAMS 00527 * hmac_info [I] Pointer to the HMAC_INFO struct to be freed. 00528 * 00529 * NOTES 00530 * See Internet RFC 2104 for details on the HMAC algorithm. 00531 */ 00532 static inline void free_hmac_info(PHMAC_INFO hmac_info) { 00533 if (!hmac_info) return; 00534 HeapFree(GetProcessHeap(), 0, hmac_info->pbInnerString); 00535 HeapFree(GetProcessHeap(), 0, hmac_info->pbOuterString); 00536 HeapFree(GetProcessHeap(), 0, hmac_info); 00537 } 00538 00539 /****************************************************************************** 00540 * copy_hmac_info [Internal] 00541 * 00542 * Deeply copy an HMAC_INFO struct 00543 * 00544 * PARAMS 00545 * dst [O] Pointer to a location where the pointer to the HMAC_INFO copy will be stored. 00546 * src [I] Pointer to the HMAC_INFO struct to be copied. 00547 * 00548 * RETURNS 00549 * Success: TRUE 00550 * Failure: FALSE 00551 * 00552 * NOTES 00553 * See Internet RFC 2104 for details on the HMAC algorithm. 00554 */ 00555 static BOOL copy_hmac_info(PHMAC_INFO *dst, const HMAC_INFO *src) { 00556 if (!src) return FALSE; 00557 *dst = HeapAlloc(GetProcessHeap(), 0, sizeof(HMAC_INFO)); 00558 if (!*dst) return FALSE; 00559 **dst = *src; 00560 (*dst)->pbInnerString = NULL; 00561 (*dst)->pbOuterString = NULL; 00562 if ((*dst)->cbInnerString == 0) (*dst)->cbInnerString = RSAENH_HMAC_DEF_PAD_LEN; 00563 (*dst)->pbInnerString = HeapAlloc(GetProcessHeap(), 0, (*dst)->cbInnerString); 00564 if (!(*dst)->pbInnerString) { 00565 free_hmac_info(*dst); 00566 return FALSE; 00567 } 00568 if (src->cbInnerString) 00569 memcpy((*dst)->pbInnerString, src->pbInnerString, src->cbInnerString); 00570 else 00571 memset((*dst)->pbInnerString, RSAENH_HMAC_DEF_IPAD_CHAR, RSAENH_HMAC_DEF_PAD_LEN); 00572 if ((*dst)->cbOuterString == 0) (*dst)->cbOuterString = RSAENH_HMAC_DEF_PAD_LEN; 00573 (*dst)->pbOuterString = HeapAlloc(GetProcessHeap(), 0, (*dst)->cbOuterString); 00574 if (!(*dst)->pbOuterString) { 00575 free_hmac_info(*dst); 00576 return FALSE; 00577 } 00578 if (src->cbOuterString) 00579 memcpy((*dst)->pbOuterString, src->pbOuterString, src->cbOuterString); 00580 else 00581 memset((*dst)->pbOuterString, RSAENH_HMAC_DEF_OPAD_CHAR, RSAENH_HMAC_DEF_PAD_LEN); 00582 return TRUE; 00583 } 00584 00585 /****************************************************************************** 00586 * destroy_hash [Internal] 00587 * 00588 * Destructor for hash objects 00589 * 00590 * PARAMS 00591 * pCryptHash [I] Pointer to the hash object to be destroyed. 00592 * Will be invalid after function returns! 00593 */ 00594 static void destroy_hash(OBJECTHDR *pObject) 00595 { 00596 CRYPTHASH *pCryptHash = (CRYPTHASH*)pObject; 00597 00598 free_hmac_info(pCryptHash->pHMACInfo); 00599 free_data_blob(&pCryptHash->tpPRFParams.blobLabel); 00600 free_data_blob(&pCryptHash->tpPRFParams.blobSeed); 00601 HeapFree(GetProcessHeap(), 0, pCryptHash); 00602 } 00603 00604 /****************************************************************************** 00605 * init_hash [Internal] 00606 * 00607 * Initialize (or reset) a hash object 00608 * 00609 * PARAMS 00610 * pCryptHash [I] The hash object to be initialized. 00611 */ 00612 static inline BOOL init_hash(CRYPTHASH *pCryptHash) { 00613 DWORD dwLen; 00614 00615 switch (pCryptHash->aiAlgid) 00616 { 00617 case CALG_HMAC: 00618 if (pCryptHash->pHMACInfo) { 00619 const PROV_ENUMALGS_EX *pAlgInfo; 00620 00621 pAlgInfo = get_algid_info(pCryptHash->hProv, pCryptHash->pHMACInfo->HashAlgid); 00622 if (!pAlgInfo) return FALSE; 00623 pCryptHash->dwHashSize = pAlgInfo->dwDefaultLen >> 3; 00624 init_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context); 00625 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context, 00626 pCryptHash->pHMACInfo->pbInnerString, 00627 pCryptHash->pHMACInfo->cbInnerString); 00628 } 00629 return TRUE; 00630 00631 case CALG_MAC: 00632 dwLen = sizeof(DWORD); 00633 RSAENH_CPGetKeyParam(pCryptHash->hProv, pCryptHash->hKey, KP_BLOCKLEN, 00634 (BYTE*)&pCryptHash->dwHashSize, &dwLen, 0); 00635 pCryptHash->dwHashSize >>= 3; 00636 return TRUE; 00637 00638 default: 00639 return init_hash_impl(pCryptHash->aiAlgid, &pCryptHash->context); 00640 } 00641 } 00642 00643 /****************************************************************************** 00644 * update_hash [Internal] 00645 * 00646 * Hashes the given data and updates the hash object's state accordingly 00647 * 00648 * PARAMS 00649 * pCryptHash [I] Hash object to be updated. 00650 * pbData [I] Pointer to data stream to be hashed. 00651 * dwDataLen [I] Length of data stream. 00652 */ 00653 static inline void update_hash(CRYPTHASH *pCryptHash, CONST BYTE *pbData, DWORD dwDataLen) { 00654 BYTE *pbTemp; 00655 00656 switch (pCryptHash->aiAlgid) 00657 { 00658 case CALG_HMAC: 00659 if (pCryptHash->pHMACInfo) 00660 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context, 00661 pbData, dwDataLen); 00662 break; 00663 00664 case CALG_MAC: 00665 pbTemp = HeapAlloc(GetProcessHeap(), 0, dwDataLen); 00666 if (!pbTemp) return; 00667 memcpy(pbTemp, pbData, dwDataLen); 00668 RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, 0, FALSE, 0, 00669 pbTemp, &dwDataLen, dwDataLen); 00670 HeapFree(GetProcessHeap(), 0, pbTemp); 00671 break; 00672 00673 default: 00674 update_hash_impl(pCryptHash->aiAlgid, &pCryptHash->context, pbData, dwDataLen); 00675 } 00676 } 00677 00678 /****************************************************************************** 00679 * finalize_hash [Internal] 00680 * 00681 * Finalizes the hash, after all data has been hashed with update_hash. 00682 * No additional data can be hashed afterwards until the hash gets initialized again. 00683 * 00684 * PARAMS 00685 * pCryptHash [I] Hash object to be finalized. 00686 */ 00687 static inline void finalize_hash(CRYPTHASH *pCryptHash) { 00688 DWORD dwDataLen; 00689 00690 switch (pCryptHash->aiAlgid) 00691 { 00692 case CALG_HMAC: 00693 if (pCryptHash->pHMACInfo) { 00694 BYTE abHashValue[RSAENH_MAX_HASH_SIZE]; 00695 00696 finalize_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context, 00697 pCryptHash->abHashValue); 00698 memcpy(abHashValue, pCryptHash->abHashValue, pCryptHash->dwHashSize); 00699 init_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context); 00700 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context, 00701 pCryptHash->pHMACInfo->pbOuterString, 00702 pCryptHash->pHMACInfo->cbOuterString); 00703 update_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context, 00704 abHashValue, pCryptHash->dwHashSize); 00705 finalize_hash_impl(pCryptHash->pHMACInfo->HashAlgid, &pCryptHash->context, 00706 pCryptHash->abHashValue); 00707 } 00708 break; 00709 00710 case CALG_MAC: 00711 dwDataLen = 0; 00712 RSAENH_CPEncrypt(pCryptHash->hProv, pCryptHash->hKey, 0, TRUE, 0, 00713 pCryptHash->abHashValue, &dwDataLen, pCryptHash->dwHashSize); 00714 break; 00715 00716 default: 00717 finalize_hash_impl(pCryptHash->aiAlgid, &pCryptHash->context, pCryptHash->abHashValue); 00718 } 00719 } 00720 00721 /****************************************************************************** 00722 * destroy_key [Internal] 00723 * 00724 * Destructor for key objects 00725 * 00726 * PARAMS 00727 * pCryptKey [I] Pointer to the key object to be destroyed. 00728 * Will be invalid after function returns! 00729 */ 00730 static void destroy_key(OBJECTHDR *pObject) 00731 { 00732 CRYPTKEY *pCryptKey = (CRYPTKEY*)pObject; 00733 00734 free_key_impl(pCryptKey->aiAlgid, &pCryptKey->context); 00735 free_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom); 00736 free_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom); 00737 free_data_blob(&pCryptKey->blobHmacKey); 00738 HeapFree(GetProcessHeap(), 0, pCryptKey); 00739 } 00740 00741 /****************************************************************************** 00742 * setup_key [Internal] 00743 * 00744 * Initialize (or reset) a key object 00745 * 00746 * PARAMS 00747 * pCryptKey [I] The key object to be initialized. 00748 */ 00749 static inline void setup_key(CRYPTKEY *pCryptKey) { 00750 pCryptKey->dwState = RSAENH_KEYSTATE_IDLE; 00751 memcpy(pCryptKey->abChainVector, pCryptKey->abInitVector, sizeof(pCryptKey->abChainVector)); 00752 setup_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen, 00753 pCryptKey->dwEffectiveKeyLen, pCryptKey->dwSaltLen, 00754 pCryptKey->abKeyValue); 00755 } 00756 00757 /****************************************************************************** 00758 * new_key [Internal] 00759 * 00760 * Creates a new key object without assigning the actual binary key value. 00761 * This is done by CPDeriveKey, CPGenKey or CPImportKey, which call this function. 00762 * 00763 * PARAMS 00764 * hProv [I] Handle to the provider to which the created key will belong. 00765 * aiAlgid [I] The new key shall use the crypto algorithm identified by aiAlgid. 00766 * dwFlags [I] Upper 16 bits give the key length. 00767 * Lower 16 bits: CRYPT_EXPORTABLE, CRYPT_CREATE_SALT, 00768 * CRYPT_NO_SALT 00769 * ppCryptKey [O] Pointer to the created key 00770 * 00771 * RETURNS 00772 * Success: Handle to the created key. 00773 * Failure: INVALID_HANDLE_VALUE 00774 */ 00775 static HCRYPTKEY new_key(HCRYPTPROV hProv, ALG_ID aiAlgid, DWORD dwFlags, CRYPTKEY **ppCryptKey) 00776 { 00777 HCRYPTKEY hCryptKey; 00778 CRYPTKEY *pCryptKey; 00779 DWORD dwKeyLen = HIWORD(dwFlags); 00780 const PROV_ENUMALGS_EX *peaAlgidInfo; 00781 00782 *ppCryptKey = NULL; 00783 00784 /* 00785 * Retrieve the CSP's capabilities for the given ALG_ID value 00786 */ 00787 peaAlgidInfo = get_algid_info(hProv, aiAlgid); 00788 if (!peaAlgidInfo) return (HCRYPTKEY)INVALID_HANDLE_VALUE; 00789 00790 TRACE("alg = %s, dwKeyLen = %d\n", debugstr_a(peaAlgidInfo->szName), 00791 dwKeyLen); 00792 /* 00793 * Assume the default key length, if none is specified explicitly 00794 */ 00795 if (dwKeyLen == 0) dwKeyLen = peaAlgidInfo->dwDefaultLen; 00796 00797 /* 00798 * Check if the requested key length is supported by the current CSP. 00799 * Adjust key length's for DES algorithms. 00800 */ 00801 switch (aiAlgid) { 00802 case CALG_DES: 00803 if (dwKeyLen == RSAENH_DES_EFFECTIVE_KEYLEN) { 00804 dwKeyLen = RSAENH_DES_STORAGE_KEYLEN; 00805 } 00806 if (dwKeyLen != RSAENH_DES_STORAGE_KEYLEN) { 00807 SetLastError(NTE_BAD_FLAGS); 00808 return (HCRYPTKEY)INVALID_HANDLE_VALUE; 00809 } 00810 break; 00811 00812 case CALG_3DES_112: 00813 if (dwKeyLen == RSAENH_3DES112_EFFECTIVE_KEYLEN) { 00814 dwKeyLen = RSAENH_3DES112_STORAGE_KEYLEN; 00815 } 00816 if (dwKeyLen != RSAENH_3DES112_STORAGE_KEYLEN) { 00817 SetLastError(NTE_BAD_FLAGS); 00818 return (HCRYPTKEY)INVALID_HANDLE_VALUE; 00819 } 00820 break; 00821 00822 case CALG_3DES: 00823 if (dwKeyLen == RSAENH_3DES_EFFECTIVE_KEYLEN) { 00824 dwKeyLen = RSAENH_3DES_STORAGE_KEYLEN; 00825 } 00826 if (dwKeyLen != RSAENH_3DES_STORAGE_KEYLEN) { 00827 SetLastError(NTE_BAD_FLAGS); 00828 return (HCRYPTKEY)INVALID_HANDLE_VALUE; 00829 } 00830 break; 00831 00832 case CALG_HMAC: 00833 /* Avoid the key length check for HMAC keys, which have unlimited 00834 * length. 00835 */ 00836 break; 00837 00838 default: 00839 if (dwKeyLen % 8 || 00840 dwKeyLen > peaAlgidInfo->dwMaxLen || 00841 dwKeyLen < peaAlgidInfo->dwMinLen) 00842 { 00843 TRACE("key len %d out of bounds (%d, %d)\n", dwKeyLen, 00844 peaAlgidInfo->dwMinLen, peaAlgidInfo->dwMaxLen); 00845 SetLastError(NTE_BAD_DATA); 00846 return (HCRYPTKEY)INVALID_HANDLE_VALUE; 00847 } 00848 } 00849 00850 hCryptKey = new_object(&handle_table, sizeof(CRYPTKEY), RSAENH_MAGIC_KEY, 00851 destroy_key, (OBJECTHDR**)&pCryptKey); 00852 if (hCryptKey != (HCRYPTKEY)INVALID_HANDLE_VALUE) 00853 { 00854 pCryptKey->aiAlgid = aiAlgid; 00855 pCryptKey->hProv = hProv; 00856 pCryptKey->dwModeBits = 0; 00857 pCryptKey->dwPermissions = CRYPT_ENCRYPT | CRYPT_DECRYPT | CRYPT_READ | CRYPT_WRITE | 00858 CRYPT_MAC; 00859 if (dwFlags & CRYPT_EXPORTABLE) 00860 pCryptKey->dwPermissions |= CRYPT_EXPORT; 00861 pCryptKey->dwKeyLen = dwKeyLen >> 3; 00862 pCryptKey->dwEffectiveKeyLen = 0; 00863 if ((dwFlags & CRYPT_CREATE_SALT) || (dwKeyLen == 40 && !(dwFlags & CRYPT_NO_SALT))) 00864 pCryptKey->dwSaltLen = 16 /*FIXME*/ - pCryptKey->dwKeyLen; 00865 else 00866 pCryptKey->dwSaltLen = 0; 00867 memset(pCryptKey->abKeyValue, 0, sizeof(pCryptKey->abKeyValue)); 00868 memset(pCryptKey->abInitVector, 0, sizeof(pCryptKey->abInitVector)); 00869 memset(&pCryptKey->siSChannelInfo.saEncAlg, 0, sizeof(pCryptKey->siSChannelInfo.saEncAlg)); 00870 memset(&pCryptKey->siSChannelInfo.saMACAlg, 0, sizeof(pCryptKey->siSChannelInfo.saMACAlg)); 00871 init_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom); 00872 init_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom); 00873 init_data_blob(&pCryptKey->blobHmacKey); 00874 00875 switch(aiAlgid) 00876 { 00877 case CALG_PCT1_MASTER: 00878 case CALG_SSL2_MASTER: 00879 case CALG_SSL3_MASTER: 00880 case CALG_TLS1_MASTER: 00881 case CALG_RC4: 00882 pCryptKey->dwBlockLen = 0; 00883 pCryptKey->dwMode = 0; 00884 break; 00885 00886 case CALG_RC2: 00887 case CALG_DES: 00888 case CALG_3DES_112: 00889 case CALG_3DES: 00890 pCryptKey->dwBlockLen = 8; 00891 pCryptKey->dwMode = CRYPT_MODE_CBC; 00892 break; 00893 00894 case CALG_AES: 00895 case CALG_AES_128: 00896 case CALG_AES_192: 00897 case CALG_AES_256: 00898 pCryptKey->dwBlockLen = 16; 00899 pCryptKey->dwMode = CRYPT_MODE_ECB; 00900 break; 00901 00902 case CALG_RSA_KEYX: 00903 case CALG_RSA_SIGN: 00904 pCryptKey->dwBlockLen = dwKeyLen >> 3; 00905 pCryptKey->dwMode = 0; 00906 break; 00907 00908 case CALG_HMAC: 00909 pCryptKey->dwBlockLen = 0; 00910 pCryptKey->dwMode = 0; 00911 break; 00912 } 00913 00914 *ppCryptKey = pCryptKey; 00915 } 00916 00917 return hCryptKey; 00918 } 00919 00920 /****************************************************************************** 00921 * map_key_spec_to_key_pair_name [Internal] 00922 * 00923 * Returns the name of the registry value associated with a key spec. 00924 * 00925 * PARAMS 00926 * dwKeySpec [I] AT_KEYEXCHANGE or AT_SIGNATURE 00927 * 00928 * RETURNS 00929 * Success: Name of registry value. 00930 * Failure: NULL 00931 */ 00932 static LPCSTR map_key_spec_to_key_pair_name(DWORD dwKeySpec) 00933 { 00934 LPCSTR szValueName; 00935 00936 switch (dwKeySpec) 00937 { 00938 case AT_KEYEXCHANGE: 00939 szValueName = "KeyExchangeKeyPair"; 00940 break; 00941 case AT_SIGNATURE: 00942 szValueName = "SignatureKeyPair"; 00943 break; 00944 default: 00945 WARN("invalid key spec %d\n", dwKeySpec); 00946 szValueName = NULL; 00947 } 00948 return szValueName; 00949 } 00950 00951 /****************************************************************************** 00952 * store_key_pair [Internal] 00953 * 00954 * Stores a key pair to the registry 00955 * 00956 * PARAMS 00957 * hCryptKey [I] Handle to the key to be stored 00958 * hKey [I] Registry key where the key pair is to be stored 00959 * dwKeySpec [I] AT_KEYEXCHANGE or AT_SIGNATURE 00960 * dwFlags [I] Flags for protecting the key 00961 */ 00962 static void store_key_pair(HCRYPTKEY hCryptKey, HKEY hKey, DWORD dwKeySpec, DWORD dwFlags) 00963 { 00964 LPCSTR szValueName; 00965 DATA_BLOB blobIn, blobOut; 00966 CRYPTKEY *pKey; 00967 DWORD dwLen; 00968 BYTE *pbKey; 00969 00970 if (!(szValueName = map_key_spec_to_key_pair_name(dwKeySpec))) 00971 return; 00972 if (lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY, 00973 (OBJECTHDR**)&pKey)) 00974 { 00975 if (crypt_export_key(pKey, 0, PRIVATEKEYBLOB, 0, TRUE, 0, &dwLen)) 00976 { 00977 pbKey = HeapAlloc(GetProcessHeap(), 0, dwLen); 00978 if (pbKey) 00979 { 00980 if (crypt_export_key(pKey, 0, PRIVATEKEYBLOB, 0, TRUE, pbKey, 00981 &dwLen)) 00982 { 00983 blobIn.pbData = pbKey; 00984 blobIn.cbData = dwLen; 00985 00986 if (CryptProtectData(&blobIn, NULL, NULL, NULL, NULL, 00987 dwFlags, &blobOut)) 00988 { 00989 RegSetValueExA(hKey, szValueName, 0, REG_BINARY, 00990 blobOut.pbData, blobOut.cbData); 00991 LocalFree(blobOut.pbData); 00992 } 00993 } 00994 HeapFree(GetProcessHeap(), 0, pbKey); 00995 } 00996 } 00997 } 00998 } 00999 01000 /****************************************************************************** 01001 * map_key_spec_to_permissions_name [Internal] 01002 * 01003 * Returns the name of the registry value associated with the permissions for 01004 * a key spec. 01005 * 01006 * PARAMS 01007 * dwKeySpec [I] AT_KEYEXCHANGE or AT_SIGNATURE 01008 * 01009 * RETURNS 01010 * Success: Name of registry value. 01011 * Failure: NULL 01012 */ 01013 static LPCSTR map_key_spec_to_permissions_name(DWORD dwKeySpec) 01014 { 01015 LPCSTR szValueName; 01016 01017 switch (dwKeySpec) 01018 { 01019 case AT_KEYEXCHANGE: 01020 szValueName = "KeyExchangePermissions"; 01021 break; 01022 case AT_SIGNATURE: 01023 szValueName = "SignaturePermissions"; 01024 break; 01025 default: 01026 WARN("invalid key spec %d\n", dwKeySpec); 01027 szValueName = NULL; 01028 } 01029 return szValueName; 01030 } 01031 01032 /****************************************************************************** 01033 * store_key_permissions [Internal] 01034 * 01035 * Stores a key's permissions to the registry 01036 * 01037 * PARAMS 01038 * hCryptKey [I] Handle to the key whose permissions are to be stored 01039 * hKey [I] Registry key where the key permissions are to be stored 01040 * dwKeySpec [I] AT_KEYEXCHANGE or AT_SIGNATURE 01041 */ 01042 static void store_key_permissions(HCRYPTKEY hCryptKey, HKEY hKey, DWORD dwKeySpec) 01043 { 01044 LPCSTR szValueName; 01045 CRYPTKEY *pKey; 01046 01047 if (!(szValueName = map_key_spec_to_permissions_name(dwKeySpec))) 01048 return; 01049 if (lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY, 01050 (OBJECTHDR**)&pKey)) 01051 RegSetValueExA(hKey, szValueName, 0, REG_DWORD, 01052 (BYTE *)&pKey->dwPermissions, 01053 sizeof(pKey->dwPermissions)); 01054 } 01055 01056 /****************************************************************************** 01057 * create_container_key [Internal] 01058 * 01059 * Creates the registry key for a key container's persistent storage. 01060 * 01061 * PARAMS 01062 * pKeyContainer [I] Pointer to the key container 01063 * sam [I] Desired registry access 01064 * phKey [O] Returned key 01065 */ 01066 static BOOL create_container_key(KEYCONTAINER *pKeyContainer, REGSAM sam, HKEY *phKey) 01067 { 01068 CHAR szRSABase[MAX_PATH]; 01069 HKEY hRootKey; 01070 01071 sprintf(szRSABase, RSAENH_REGKEY, pKeyContainer->szName); 01072 01073 if (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET) 01074 hRootKey = HKEY_LOCAL_MACHINE; 01075 else 01076 hRootKey = HKEY_CURRENT_USER; 01077 01078 /* @@ Wine registry key: HKLM\Software\Wine\Crypto\RSA */ 01079 /* @@ Wine registry key: HKCU\Software\Wine\Crypto\RSA */ 01080 return RegCreateKeyExA(hRootKey, szRSABase, 0, NULL, 01081 REG_OPTION_NON_VOLATILE, sam, NULL, phKey, NULL) 01082 == ERROR_SUCCESS; 01083 } 01084 01085 /****************************************************************************** 01086 * open_container_key [Internal] 01087 * 01088 * Opens a key container's persistent storage for reading. 01089 * 01090 * PARAMS 01091 * pszContainerName [I] Name of the container to be opened. May be the empty 01092 * string if the parent key of all containers is to be 01093 * opened. 01094 * dwFlags [I] Flags indicating which keyset to be opened. 01095 * phKey [O] Returned key 01096 */ 01097 static BOOL open_container_key(LPCSTR pszContainerName, DWORD dwFlags, HKEY *phKey) 01098 { 01099 CHAR szRSABase[MAX_PATH]; 01100 HKEY hRootKey; 01101 01102 sprintf(szRSABase, RSAENH_REGKEY, pszContainerName); 01103 01104 if (dwFlags & CRYPT_MACHINE_KEYSET) 01105 hRootKey = HKEY_LOCAL_MACHINE; 01106 else 01107 hRootKey = HKEY_CURRENT_USER; 01108 01109 /* @@ Wine registry key: HKLM\Software\Wine\Crypto\RSA */ 01110 /* @@ Wine registry key: HKCU\Software\Wine\Crypto\RSA */ 01111 return RegOpenKeyExA(hRootKey, szRSABase, 0, KEY_READ, phKey) == 01112 ERROR_SUCCESS; 01113 } 01114 01115 /****************************************************************************** 01116 * delete_container_key [Internal] 01117 * 01118 * Deletes a key container's persistent storage. 01119 * 01120 * PARAMS 01121 * pszContainerName [I] Name of the container to be opened. 01122 * dwFlags [I] Flags indicating which keyset to be opened. 01123 */ 01124 static BOOL delete_container_key(LPCSTR pszContainerName, DWORD dwFlags) 01125 { 01126 CHAR szRegKey[MAX_PATH]; 01127 01128 if (snprintf(szRegKey, MAX_PATH, RSAENH_REGKEY, pszContainerName) >= MAX_PATH) { 01129 SetLastError(NTE_BAD_KEYSET_PARAM); 01130 return FALSE; 01131 } else { 01132 HKEY hRootKey; 01133 if (dwFlags & CRYPT_MACHINE_KEYSET) 01134 hRootKey = HKEY_LOCAL_MACHINE; 01135 else 01136 hRootKey = HKEY_CURRENT_USER; 01137 if (!RegDeleteKeyA(hRootKey, szRegKey)) { 01138 SetLastError(ERROR_SUCCESS); 01139 return TRUE; 01140 } else { 01141 SetLastError(NTE_BAD_KEYSET); 01142 return FALSE; 01143 } 01144 } 01145 } 01146 01147 /****************************************************************************** 01148 * store_key_container_keys [Internal] 01149 * 01150 * Stores key container's keys in a persistent location. 01151 * 01152 * PARAMS 01153 * pKeyContainer [I] Pointer to the key container whose keys are to be saved 01154 */ 01155 static void store_key_container_keys(KEYCONTAINER *pKeyContainer) 01156 { 01157 HKEY hKey; 01158 DWORD dwFlags; 01159 01160 /* On WinXP, persistent keys are stored in a file located at: 01161 * $AppData$\\Microsoft\\Crypto\\RSA\\$SID$\\some_hex_string 01162 */ 01163 01164 if (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET) 01165 dwFlags = CRYPTPROTECT_LOCAL_MACHINE; 01166 else 01167 dwFlags = 0; 01168 01169 if (create_container_key(pKeyContainer, KEY_WRITE, &hKey)) 01170 { 01171 store_key_pair(pKeyContainer->hKeyExchangeKeyPair, hKey, 01172 AT_KEYEXCHANGE, dwFlags); 01173 store_key_pair(pKeyContainer->hSignatureKeyPair, hKey, 01174 AT_SIGNATURE, dwFlags); 01175 RegCloseKey(hKey); 01176 } 01177 } 01178 01179 /****************************************************************************** 01180 * store_key_container_permissions [Internal] 01181 * 01182 * Stores key container's key permissions in a persistent location. 01183 * 01184 * PARAMS 01185 * pKeyContainer [I] Pointer to the key container whose key permissions are to 01186 * be saved 01187 */ 01188 static void store_key_container_permissions(KEYCONTAINER *pKeyContainer) 01189 { 01190 HKEY hKey; 01191 01192 if (create_container_key(pKeyContainer, KEY_WRITE, &hKey)) 01193 { 01194 store_key_permissions(pKeyContainer->hKeyExchangeKeyPair, hKey, 01195 AT_KEYEXCHANGE); 01196 store_key_permissions(pKeyContainer->hSignatureKeyPair, hKey, 01197 AT_SIGNATURE); 01198 RegCloseKey(hKey); 01199 } 01200 } 01201 01202 /****************************************************************************** 01203 * release_key_container_keys [Internal] 01204 * 01205 * Releases key container's keys. 01206 * 01207 * PARAMS 01208 * pKeyContainer [I] Pointer to the key container whose keys are to be released. 01209 */ 01210 static void release_key_container_keys(KEYCONTAINER *pKeyContainer) 01211 { 01212 release_handle(&handle_table, pKeyContainer->hKeyExchangeKeyPair, 01213 RSAENH_MAGIC_KEY); 01214 release_handle(&handle_table, pKeyContainer->hSignatureKeyPair, 01215 RSAENH_MAGIC_KEY); 01216 } 01217 01218 /****************************************************************************** 01219 * destroy_key_container [Internal] 01220 * 01221 * Destructor for key containers. 01222 * 01223 * PARAMS 01224 * pObjectHdr [I] Pointer to the key container to be destroyed. 01225 */ 01226 static void destroy_key_container(OBJECTHDR *pObjectHdr) 01227 { 01228 KEYCONTAINER *pKeyContainer = (KEYCONTAINER*)pObjectHdr; 01229 01230 if (!(pKeyContainer->dwFlags & CRYPT_VERIFYCONTEXT)) 01231 { 01232 store_key_container_keys(pKeyContainer); 01233 store_key_container_permissions(pKeyContainer); 01234 release_key_container_keys(pKeyContainer); 01235 } 01236 else 01237 release_key_container_keys(pKeyContainer); 01238 HeapFree( GetProcessHeap(), 0, pKeyContainer ); 01239 } 01240 01241 /****************************************************************************** 01242 * new_key_container [Internal] 01243 * 01244 * Create a new key container. The personality (RSA Base, Strong or Enhanced CP) 01245 * of the CSP is determined via the pVTable->pszProvName string. 01246 * 01247 * PARAMS 01248 * pszContainerName [I] Name of the key container. 01249 * pVTable [I] Callback functions and context info provided by the OS 01250 * 01251 * RETURNS 01252 * Success: Handle to the new key container. 01253 * Failure: INVALID_HANDLE_VALUE 01254 */ 01255 static HCRYPTPROV new_key_container(PCCH pszContainerName, DWORD dwFlags, const VTableProvStruc *pVTable) 01256 { 01257 KEYCONTAINER *pKeyContainer; 01258 HCRYPTPROV hKeyContainer; 01259 01260 hKeyContainer = new_object(&handle_table, sizeof(KEYCONTAINER), RSAENH_MAGIC_CONTAINER, 01261 destroy_key_container, (OBJECTHDR**)&pKeyContainer); 01262 if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE) 01263 { 01264 lstrcpynA(pKeyContainer->szName, pszContainerName, MAX_PATH); 01265 pKeyContainer->dwFlags = dwFlags; 01266 pKeyContainer->dwEnumAlgsCtr = 0; 01267 pKeyContainer->hKeyExchangeKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE; 01268 pKeyContainer->hSignatureKeyPair = (HCRYPTKEY)INVALID_HANDLE_VALUE; 01269 if (pVTable && pVTable->pszProvName) { 01270 lstrcpynA(pKeyContainer->szProvName, pVTable->pszProvName, MAX_PATH); 01271 if (!strcmp(pVTable->pszProvName, MS_DEF_PROV_A)) { 01272 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_BASE; 01273 } else if (!strcmp(pVTable->pszProvName, MS_ENHANCED_PROV_A)) { 01274 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_ENHANCED; 01275 } else if (!strcmp(pVTable->pszProvName, MS_DEF_RSA_SCHANNEL_PROV_A)) { 01276 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_SCHANNEL; 01277 } else if (!strcmp(pVTable->pszProvName, MS_ENH_RSA_AES_PROV_A)) { 01278 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_AES; 01279 } else { 01280 pKeyContainer->dwPersonality = RSAENH_PERSONALITY_STRONG; 01281 } 01282 } 01283 01284 /* The new key container has to be inserted into the CSP immediately 01285 * after creation to be available for CPGetProvParam's PP_ENUMCONTAINERS. */ 01286 if (!(dwFlags & CRYPT_VERIFYCONTEXT)) { 01287 HKEY hKey; 01288 01289 if (create_container_key(pKeyContainer, KEY_WRITE, &hKey)) 01290 RegCloseKey(hKey); 01291 } 01292 } 01293 01294 return hKeyContainer; 01295 } 01296 01297 /****************************************************************************** 01298 * read_key_value [Internal] 01299 * 01300 * Reads a key pair value from the registry 01301 * 01302 * PARAMS 01303 * hKeyContainer [I] Crypt provider to use to import the key 01304 * hKey [I] Registry key from which to read the key pair 01305 * dwKeySpec [I] AT_KEYEXCHANGE or AT_SIGNATURE 01306 * dwFlags [I] Flags for unprotecting the key 01307 * phCryptKey [O] Returned key 01308 */ 01309 static BOOL read_key_value(HCRYPTPROV hKeyContainer, HKEY hKey, DWORD dwKeySpec, DWORD dwFlags, HCRYPTKEY *phCryptKey) 01310 { 01311 LPCSTR szValueName; 01312 DWORD dwValueType, dwLen; 01313 BYTE *pbKey; 01314 DATA_BLOB blobIn, blobOut; 01315 BOOL ret = FALSE; 01316 01317 if (!(szValueName = map_key_spec_to_key_pair_name(dwKeySpec))) 01318 return FALSE; 01319 if (RegQueryValueExA(hKey, szValueName, 0, &dwValueType, NULL, &dwLen) == 01320 ERROR_SUCCESS) 01321 { 01322 pbKey = HeapAlloc(GetProcessHeap(), 0, dwLen); 01323 if (pbKey) 01324 { 01325 if (RegQueryValueExA(hKey, szValueName, 0, &dwValueType, pbKey, &dwLen) == 01326 ERROR_SUCCESS) 01327 { 01328 blobIn.pbData = pbKey; 01329 blobIn.cbData = dwLen; 01330 01331 if (CryptUnprotectData(&blobIn, NULL, NULL, NULL, NULL, 01332 dwFlags, &blobOut)) 01333 { 01334 ret = import_key(hKeyContainer, blobOut.pbData, blobOut.cbData, 0, 0, 01335 FALSE, phCryptKey); 01336 LocalFree(blobOut.pbData); 01337 } 01338 } 01339 HeapFree(GetProcessHeap(), 0, pbKey); 01340 } 01341 } 01342 if (ret) 01343 { 01344 CRYPTKEY *pKey; 01345 01346 if (lookup_handle(&handle_table, *phCryptKey, RSAENH_MAGIC_KEY, 01347 (OBJECTHDR**)&pKey)) 01348 { 01349 if ((szValueName = map_key_spec_to_permissions_name(dwKeySpec))) 01350 { 01351 dwLen = sizeof(pKey->dwPermissions); 01352 RegQueryValueExA(hKey, szValueName, 0, NULL, 01353 (BYTE *)&pKey->dwPermissions, &dwLen); 01354 } 01355 } 01356 } 01357 return ret; 01358 } 01359 01360 /****************************************************************************** 01361 * read_key_container [Internal] 01362 * 01363 * Tries to read the persistent state of the key container (mainly the signature 01364 * and key exchange private keys) given by pszContainerName. 01365 * 01366 * PARAMS 01367 * pszContainerName [I] Name of the key container to read from the registry 01368 * pVTable [I] Pointer to context data provided by the operating system 01369 * 01370 * RETURNS 01371 * Success: Handle to the key container read from the registry 01372 * Failure: INVALID_HANDLE_VALUE 01373 */ 01374 static HCRYPTPROV read_key_container(PCHAR pszContainerName, DWORD dwFlags, const VTableProvStruc *pVTable) 01375 { 01376 HKEY hKey; 01377 KEYCONTAINER *pKeyContainer; 01378 HCRYPTPROV hKeyContainer; 01379 HCRYPTKEY hCryptKey; 01380 01381 if (!open_container_key(pszContainerName, dwFlags, &hKey)) 01382 { 01383 SetLastError(NTE_BAD_KEYSET); 01384 return (HCRYPTPROV)INVALID_HANDLE_VALUE; 01385 } 01386 01387 hKeyContainer = new_key_container(pszContainerName, dwFlags, pVTable); 01388 if (hKeyContainer != (HCRYPTPROV)INVALID_HANDLE_VALUE) 01389 { 01390 DWORD dwProtectFlags = (dwFlags & CRYPT_MACHINE_KEYSET) ? 01391 CRYPTPROTECT_LOCAL_MACHINE : 0; 01392 01393 if (!lookup_handle(&handle_table, hKeyContainer, RSAENH_MAGIC_CONTAINER, 01394 (OBJECTHDR**)&pKeyContainer)) 01395 return (HCRYPTPROV)INVALID_HANDLE_VALUE; 01396 01397 /* read_key_value calls import_key, which calls import_private_key, 01398 * which implicitly installs the key value into the appropriate key 01399 * container key. Thus the ref count is incremented twice, once for 01400 * the output key value, and once for the implicit install, and needs 01401 * to be decremented to balance the two. 01402 */ 01403 if (read_key_value(hKeyContainer, hKey, AT_KEYEXCHANGE, 01404 dwProtectFlags, &hCryptKey)) 01405 release_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY); 01406 if (read_key_value(hKeyContainer, hKey, AT_SIGNATURE, 01407 dwProtectFlags, &hCryptKey)) 01408 release_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY); 01409 } 01410 01411 return hKeyContainer; 01412 } 01413 01414 /****************************************************************************** 01415 * build_hash_signature [Internal] 01416 * 01417 * Builds a padded version of a hash to match the length of the RSA key modulus. 01418 * 01419 * PARAMS 01420 * pbSignature [O] The padded hash object is stored here. 01421 * dwLen [I] Length of the pbSignature buffer. 01422 * aiAlgid [I] Algorithm identifier of the hash to be padded. 01423 * abHashValue [I] The value of the hash object. 01424 * dwHashLen [I] Length of the hash value. 01425 * dwFlags [I] Selection of padding algorithm. 01426 * 01427 * RETURNS 01428 * Success: TRUE 01429 * Failure: FALSE (NTE_BAD_ALGID) 01430 */ 01431 static BOOL build_hash_signature(BYTE *pbSignature, DWORD dwLen, ALG_ID aiAlgid, 01432 CONST BYTE *abHashValue, DWORD dwHashLen, DWORD dwFlags) 01433 { 01434 /* These prefixes are meant to be concatenated with hash values of the 01435 * respective kind to form a PKCS #7 DigestInfo. */ 01436 static const struct tagOIDDescriptor { 01437 ALG_ID aiAlgid; 01438 DWORD dwLen; 01439 CONST BYTE abOID[19]; 01440 } aOIDDescriptor[] = { 01441 { CALG_MD2, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 01442 0x86, 0xf7, 0x0d, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10 } }, 01443 { CALG_MD4, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 01444 0x86, 0xf7, 0x0d, 0x02, 0x04, 0x05, 0x00, 0x04, 0x10 } }, 01445 { CALG_MD5, 18, { 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 01446 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 } }, 01447 { CALG_SHA, 15, { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 01448 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 } }, 01449 { CALG_SHA_256, 19, { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 01450 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 01451 0x05, 0x00, 0x04, 0x20 } }, 01452 { CALG_SHA_384, 19, { 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 01453 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 01454 0x05, 0x00, 0x04, 0x30 } }, 01455 { CALG_SHA_384, 19, { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 01456 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 01457 0x05, 0x00, 0x04, 0x40 } }, 01458 { CALG_SSL3_SHAMD5, 0, { 0 } }, 01459 { 0, 0, { 0 } } 01460 }; 01461 DWORD dwIdxOID, i, j; 01462 01463 for (dwIdxOID = 0; aOIDDescriptor[dwIdxOID].aiAlgid; dwIdxOID++) { 01464 if (aOIDDescriptor[dwIdxOID].aiAlgid == aiAlgid) break; 01465 } 01466 01467 if (!aOIDDescriptor[dwIdxOID].aiAlgid) { 01468 SetLastError(NTE_BAD_ALGID); 01469 return FALSE; 01470 } 01471 01472 /* Build the padded signature */ 01473 if (dwFlags & CRYPT_X931_FORMAT) { 01474 pbSignature[0] = 0x6b; 01475 for (i=1; i < dwLen - dwHashLen - 3; i++) { 01476 pbSignature[i] = 0xbb; 01477 } 01478 pbSignature[i++] = 0xba; 01479 for (j=0; j < dwHashLen; j++, i++) { 01480 pbSignature[i] = abHashValue[j]; 01481 } 01482 pbSignature[i++] = 0x33; 01483 pbSignature[i++] = 0xcc; 01484 } else { 01485 pbSignature[0] = 0x00; 01486 pbSignature[1] = 0x01; 01487 if (dwFlags & CRYPT_NOHASHOID) { 01488 for (i=2; i < dwLen - 1 - dwHashLen; i++) { 01489 pbSignature[i] = 0xff; 01490 } 01491 pbSignature[i++] = 0x00; 01492 } else { 01493 for (i=2; i < dwLen - 1 - aOIDDescriptor[dwIdxOID].dwLen - dwHashLen; i++) { 01494 pbSignature[i] = 0xff; 01495 } 01496 pbSignature[i++] = 0x00; 01497 for (j=0; j < aOIDDescriptor[dwIdxOID].dwLen; j++) { 01498 pbSignature[i++] = aOIDDescriptor[dwIdxOID].abOID[j]; 01499 } 01500 } 01501 for (j=0; j < dwHashLen; j++) { 01502 pbSignature[i++] = abHashValue[j]; 01503 } 01504 } 01505 01506 return TRUE; 01507 } 01508 01509 /****************************************************************************** 01510 * tls1_p [Internal] 01511 * 01512 * This is an implementation of the 'P_hash' helper function for TLS1's PRF. 01513 * It is used exclusively by tls1_prf. For details see RFC 2246, chapter 5. 01514 * The pseudo random stream generated by this function is exclusive or'ed with 01515 * the data in pbBuffer. 01516 * 01517 * PARAMS 01518 * hHMAC [I] HMAC object, which will be used in pseudo random generation 01519 * pblobSeed [I] Seed value 01520 * pbBuffer [I/O] Pseudo random stream will be xor'ed to the provided data 01521 * dwBufferLen [I] Number of pseudo random bytes desired 01522 * 01523 * RETURNS 01524 * Success: TRUE 01525 * Failure: FALSE 01526 */ 01527 static BOOL tls1_p(HCRYPTHASH hHMAC, CONST PCRYPT_DATA_BLOB pblobSeed, PBYTE pbBuffer, DWORD dwBufferLen) 01528 { 01529 CRYPTHASH *pHMAC; 01530 BYTE abAi[RSAENH_MAX_HASH_SIZE]; 01531 DWORD i = 0; 01532 01533 if (!lookup_handle(&handle_table, hHMAC, RSAENH_MAGIC_HASH, (OBJECTHDR**)&pHMAC)) { 01534 SetLastError(NTE_BAD_HASH); 01535 return FALSE; 01536 } 01537 01538 /* compute A_1 = HMAC(seed) */ 01539 init_hash(pHMAC); 01540 update_hash(pHMAC, pblobSeed->pbData, pblobSeed->cbData); 01541 finalize_hash(pHMAC); 01542 memcpy(abAi, pHMAC->abHashValue, pHMAC->dwHashSize); 01543 01544 do { 01545 /* compute HMAC(A_i + seed) */ 01546 init_hash(pHMAC); 01547 update_hash(pHMAC, abAi, pHMAC->dwHashSize); 01548 update_hash(pHMAC, pblobSeed->pbData, pblobSeed->cbData); 01549 finalize_hash(pHMAC); 01550 01551 /* pseudo random stream := CONCAT_{i=1..n} ( HMAC(A_i + seed) ) */ 01552 do { 01553 if (i >= dwBufferLen) break; 01554 pbBuffer[i] ^= pHMAC->abHashValue[i % pHMAC->dwHashSize]; 01555 i++; 01556 } while (i % pHMAC->dwHashSize); 01557 01558 /* compute A_{i+1} = HMAC(A_i) */ 01559 init_hash(pHMAC); 01560 update_hash(pHMAC, abAi, pHMAC->dwHashSize); 01561 finalize_hash(pHMAC); 01562 memcpy(abAi, pHMAC->abHashValue, pHMAC->dwHashSize); 01563 } while (i < dwBufferLen); 01564 01565 return TRUE; 01566 } 01567 01568 /****************************************************************************** 01569 * tls1_prf [Internal] 01570 * 01571 * TLS1 pseudo random function as specified in RFC 2246, chapter 5 01572 * 01573 * PARAMS 01574 * hProv [I] Key container used to compute the pseudo random stream 01575 * hSecret [I] Key that holds the (pre-)master secret 01576 * pblobLabel [I] Descriptive label 01577 * pblobSeed [I] Seed value 01578 * pbBuffer [O] Pseudo random numbers will be stored here 01579 * dwBufferLen [I] Number of pseudo random bytes desired 01580 * 01581 * RETURNS 01582 * Success: TRUE 01583 * Failure: FALSE 01584 */ 01585 static BOOL tls1_prf(HCRYPTPROV hProv, HCRYPTPROV hSecret, CONST PCRYPT_DATA_BLOB pblobLabel, 01586 CONST PCRYPT_DATA_BLOB pblobSeed, PBYTE pbBuffer, DWORD dwBufferLen) 01587 { 01588 HMAC_INFO hmacInfo = { 0, NULL, 0, NULL, 0 }; 01589 HCRYPTHASH hHMAC = (HCRYPTHASH)INVALID_HANDLE_VALUE; 01590 HCRYPTKEY hHalfSecret = (HCRYPTKEY)INVALID_HANDLE_VALUE; 01591 CRYPTKEY *pHalfSecret, *pSecret; 01592 DWORD dwHalfSecretLen; 01593 BOOL result = FALSE; 01594 CRYPT_DATA_BLOB blobLabelSeed; 01595 01596 TRACE("(hProv=%08lx, hSecret=%08lx, pblobLabel=%p, pblobSeed=%p, pbBuffer=%p, dwBufferLen=%d)\n", 01597 hProv, hSecret, pblobLabel, pblobSeed, pbBuffer, dwBufferLen); 01598 01599 if (!lookup_handle(&handle_table, hSecret, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pSecret)) { 01600 SetLastError(NTE_FAIL); 01601 return FALSE; 01602 } 01603 01604 dwHalfSecretLen = (pSecret->dwKeyLen+1)/2; 01605 01606 /* concatenation of the label and the seed */ 01607 if (!concat_data_blobs(&blobLabelSeed, pblobLabel, pblobSeed)) goto exit; 01608 01609 /* zero out the buffer, since two random streams will be xor'ed into it. */ 01610 memset(pbBuffer, 0, dwBufferLen); 01611 01612 /* build a 'fake' key, to hold the secret. CALG_SSL2_MASTER is used since it provides 01613 * the biggest range of valid key lengths. */ 01614 hHalfSecret = new_key(hProv, CALG_SSL2_MASTER, MAKELONG(0,dwHalfSecretLen*8), &pHalfSecret); 01615 if (hHalfSecret == (HCRYPTKEY)INVALID_HANDLE_VALUE) goto exit; 01616 01617 /* Derive an HMAC_MD5 hash and call the helper function. */ 01618 memcpy(pHalfSecret->abKeyValue, pSecret->abKeyValue, dwHalfSecretLen); 01619 if (!RSAENH_CPCreateHash(hProv, CALG_HMAC, hHalfSecret, 0, &hHMAC)) goto exit; 01620 hmacInfo.HashAlgid = CALG_MD5; 01621 if (!RSAENH_CPSetHashParam(hProv, hHMAC, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0)) goto exit; 01622 if (!tls1_p(hHMAC, &blobLabelSeed, pbBuffer, dwBufferLen)) goto exit; 01623 01624 /* Reconfigure to HMAC_SHA hash and call helper function again. */ 01625 memcpy(pHalfSecret->abKeyValue, pSecret->abKeyValue + (pSecret->dwKeyLen/2), dwHalfSecretLen); 01626 hmacInfo.HashAlgid = CALG_SHA; 01627 if (!RSAENH_CPSetHashParam(hProv, hHMAC, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0)) goto exit; 01628 if (!tls1_p(hHMAC, &blobLabelSeed, pbBuffer, dwBufferLen)) goto exit; 01629 01630 result = TRUE; 01631 exit: 01632 release_handle(&handle_table, hHalfSecret, RSAENH_MAGIC_KEY); 01633 if (hHMAC != (HCRYPTHASH)INVALID_HANDLE_VALUE) RSAENH_CPDestroyHash(hProv, hHMAC); 01634 free_data_blob(&blobLabelSeed); 01635 return result; 01636 } 01637 01638 /****************************************************************************** 01639 * pad_data [Internal] 01640 * 01641 * Helper function for data padding according to PKCS1 #2 01642 * 01643 * PARAMS 01644 * abData [I] The data to be padded 01645 * dwDataLen [I] Length of the data 01646 * abBuffer [O] Padded data will be stored here 01647 * dwBufferLen [I] Length of the buffer (also length of padded data) 01648 * dwFlags [I] Padding format (CRYPT_SSL2_FALLBACK) 01649 * 01650 * RETURN 01651 * Success: TRUE 01652 * Failure: FALSE (NTE_BAD_LEN, too much data to pad) 01653 */ 01654 static BOOL pad_data(CONST BYTE *abData, DWORD dwDataLen, BYTE *abBuffer, DWORD dwBufferLen, 01655 DWORD dwFlags) 01656 { 01657 DWORD i; 01658 01659 /* Ensure there is enough space for PKCS1 #2 padding */ 01660 if (dwDataLen > dwBufferLen-11) { 01661 SetLastError(NTE_BAD_LEN); 01662 return FALSE; 01663 } 01664 01665 memmove(abBuffer + dwBufferLen - dwDataLen, abData, dwDataLen); 01666 01667 abBuffer[0] = 0x00; 01668 abBuffer[1] = RSAENH_PKC_BLOCKTYPE; 01669 for (i=2; i < dwBufferLen - dwDataLen - 1; i++) 01670 do gen_rand_impl(&abBuffer[i], 1); while (!abBuffer[i]); 01671 if (dwFlags & CRYPT_SSL2_FALLBACK) 01672 for (i-=8; i < dwBufferLen - dwDataLen - 1; i++) 01673 abBuffer[i] = 0x03; 01674 abBuffer[i] = 0x00; 01675 01676 return TRUE; 01677 } 01678 01679 /****************************************************************************** 01680 * unpad_data [Internal] 01681 * 01682 * Remove the PKCS1 padding from RSA decrypted data 01683 * 01684 * PARAMS 01685 * abData [I] The padded data 01686 * dwDataLen [I] Length of the padded data 01687 * abBuffer [O] Data without padding will be stored here 01688 * dwBufferLen [I/O] I: Length of the buffer, O: Length of unpadded data 01689 * dwFlags [I] Currently none defined 01690 * 01691 * RETURNS 01692 * Success: TRUE 01693 * Failure: FALSE, (NTE_BAD_DATA, no valid PKCS1 padding or buffer too small) 01694 */ 01695 static BOOL unpad_data(CONST BYTE *abData, DWORD dwDataLen, BYTE *abBuffer, DWORD *dwBufferLen, 01696 DWORD dwFlags) 01697 { 01698 DWORD i; 01699 01700 for (i=2; i<dwDataLen; i++) 01701 if (!abData[i]) 01702 break; 01703 01704 if ((i == dwDataLen) || (*dwBufferLen < dwDataLen - i - 1) || 01705 (abData[0] != 0x00) || (abData[1] != RSAENH_PKC_BLOCKTYPE)) 01706 { 01707 SetLastError(NTE_BAD_DATA); 01708 return FALSE; 01709 } 01710 01711 *dwBufferLen = dwDataLen - i - 1; 01712 memmove(abBuffer, abData + i + 1, *dwBufferLen); 01713 return TRUE; 01714 } 01715 01716 /****************************************************************************** 01717 * CPAcquireContext (RSAENH.@) 01718 * 01719 * Acquire a handle to the key container specified by pszContainer 01720 * 01721 * PARAMS 01722 * phProv [O] Pointer to the location the acquired handle will be written to. 01723 * pszContainer [I] Name of the desired key container. See Notes 01724 * dwFlags [I] Flags. See Notes. 01725 * pVTable [I] Pointer to a PVTableProvStruct containing callbacks. 01726 * 01727 * RETURNS 01728 * Success: TRUE 01729 * Failure: FALSE 01730 * 01731 * NOTES 01732 * If pszContainer is NULL or points to a zero length string the user's login 01733 * name will be used as the key container name. 01734 * 01735 * If the CRYPT_NEW_KEYSET flag is set in dwFlags a new keyset will be created. 01736 * If a keyset with the given name already exists, the function fails and sets 01737 * last error to NTE_EXISTS. If CRYPT_NEW_KEYSET is not set and the specified 01738 * key container does not exist, function fails and sets last error to 01739 * NTE_BAD_KEYSET. 01740 */ 01741 BOOL WINAPI RSAENH_CPAcquireContext(HCRYPTPROV *phProv, LPSTR pszContainer, 01742 DWORD dwFlags, PVTableProvStruc pVTable) 01743 { 01744 CHAR szKeyContainerName[MAX_PATH]; 01745 01746 TRACE("(phProv=%p, pszContainer=%s, dwFlags=%08x, pVTable=%p)\n", phProv, 01747 debugstr_a(pszContainer), dwFlags, pVTable); 01748 01749 if (pszContainer && *pszContainer) 01750 { 01751 lstrcpynA(szKeyContainerName, pszContainer, MAX_PATH); 01752 } 01753 else 01754 { 01755 DWORD dwLen = sizeof(szKeyContainerName); 01756 if (!GetUserNameA(szKeyContainerName, &dwLen)) return FALSE; 01757 } 01758 01759 switch (dwFlags & (CRYPT_NEWKEYSET|CRYPT_VERIFYCONTEXT|CRYPT_DELETEKEYSET)) 01760 { 01761 case 0: 01762 *phProv = read_key_container(szKeyContainerName, dwFlags, pVTable); 01763 break; 01764 01765 case CRYPT_DELETEKEYSET: 01766 return delete_container_key(szKeyContainerName, dwFlags); 01767 01768 case CRYPT_NEWKEYSET: 01769 *phProv = read_key_container(szKeyContainerName, dwFlags, pVTable); 01770 if (*phProv != (HCRYPTPROV)INVALID_HANDLE_VALUE) 01771 { 01772 release_handle(&handle_table, *phProv, RSAENH_MAGIC_CONTAINER); 01773 TRACE("Can't create new keyset, already exists\n"); 01774 SetLastError(NTE_EXISTS); 01775 return FALSE; 01776 } 01777 *phProv = new_key_container(szKeyContainerName, dwFlags, pVTable); 01778 break; 01779 01780 case CRYPT_VERIFYCONTEXT|CRYPT_NEWKEYSET: 01781 case CRYPT_VERIFYCONTEXT: 01782 if (pszContainer && *pszContainer) { 01783 TRACE("pszContainer should be empty\n"); 01784 SetLastError(NTE_BAD_FLAGS); 01785 return FALSE; 01786 } 01787 *phProv = new_key_container("", dwFlags, pVTable); 01788 break; 01789 01790 default: 01791 *phProv = (HCRYPTPROV)INVALID_HANDLE_VALUE; 01792 SetLastError(NTE_BAD_FLAGS); 01793 return FALSE; 01794 } 01795 01796 if (*phProv != (HCRYPTPROV)INVALID_HANDLE_VALUE) { 01797 SetLastError(ERROR_SUCCESS); 01798 return TRUE; 01799 } else { 01800 return FALSE; 01801 } 01802 } 01803 01804 /****************************************************************************** 01805 * CPCreateHash (RSAENH.@) 01806 * 01807 * CPCreateHash creates and initializes a new hash object. 01808 * 01809 * PARAMS 01810 * hProv [I] Handle to the key container to which the new hash will belong. 01811 * Algid [I] Identifies the hash algorithm, which will be used for the hash. 01812 * hKey [I] Handle to a session key applied for keyed hashes. 01813 * dwFlags [I] Currently no flags defined. Must be zero. 01814 * phHash [O] Points to the location where a handle to the new hash will be stored. 01815 * 01816 * RETURNS 01817 * Success: TRUE 01818 * Failure: FALSE 01819 * 01820 * NOTES 01821 * hKey is a handle to a session key applied in keyed hashes like MAC and HMAC. 01822 * If a normal hash object is to be created (like e.g. MD2 or SHA1) hKey must be zero. 01823 */ 01824 BOOL WINAPI RSAENH_CPCreateHash(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags, 01825 HCRYPTHASH *phHash) 01826 { 01827 CRYPTKEY *pCryptKey; 01828 CRYPTHASH *pCryptHash; 01829 const PROV_ENUMALGS_EX *peaAlgidInfo; 01830 01831 TRACE("(hProv=%08lx, Algid=%08x, hKey=%08lx, dwFlags=%08x, phHash=%p)\n", hProv, Algid, hKey, 01832 dwFlags, phHash); 01833 01834 peaAlgidInfo = get_algid_info(hProv, Algid); 01835 if (!peaAlgidInfo) return FALSE; 01836 01837 if (dwFlags) 01838 { 01839 SetLastError(NTE_BAD_FLAGS); 01840 return FALSE; 01841 } 01842 01843 if (Algid == CALG_MAC || Algid == CALG_HMAC || Algid == CALG_SCHANNEL_MASTER_HASH || 01844 Algid == CALG_TLS1PRF) 01845 { 01846 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey)) { 01847 SetLastError(NTE_BAD_KEY); 01848 return FALSE; 01849 } 01850 01851 if ((Algid == CALG_MAC) && (GET_ALG_TYPE(pCryptKey->aiAlgid) != ALG_TYPE_BLOCK)) { 01852 SetLastError(NTE_BAD_KEY); 01853 return FALSE; 01854 } 01855 01856 if ((Algid == CALG_SCHANNEL_MASTER_HASH || Algid == CALG_TLS1PRF) && 01857 (pCryptKey->aiAlgid != CALG_TLS1_MASTER)) 01858 { 01859 SetLastError(NTE_BAD_KEY); 01860 return FALSE; 01861 } 01862 if (Algid == CALG_SCHANNEL_MASTER_HASH && 01863 ((!pCryptKey->siSChannelInfo.blobClientRandom.cbData) || 01864 (!pCryptKey->siSChannelInfo.blobServerRandom.cbData))) 01865 { 01866 SetLastError(ERROR_INVALID_PARAMETER); 01867 return FALSE; 01868 } 01869 01870 if ((Algid == CALG_TLS1PRF) && (pCryptKey->dwState != RSAENH_KEYSTATE_MASTERKEY)) { 01871 SetLastError(NTE_BAD_KEY_STATE); 01872 return FALSE; 01873 } 01874 } 01875 01876 *phHash = new_object(&handle_table, sizeof(CRYPTHASH), RSAENH_MAGIC_HASH, 01877 destroy_hash, (OBJECTHDR**)&pCryptHash); 01878 if (!pCryptHash) return FALSE; 01879 01880 pCryptHash->aiAlgid = Algid; 01881 pCryptHash->hKey = hKey; 01882 pCryptHash->hProv = hProv; 01883 pCryptHash->dwState = RSAENH_HASHSTATE_HASHING; 01884 pCryptHash->pHMACInfo = NULL; 01885 pCryptHash->dwHashSize = peaAlgidInfo->dwDefaultLen >> 3; 01886 init_data_blob(&pCryptHash->tpPRFParams.blobLabel); 01887 init_data_blob(&pCryptHash->tpPRFParams.blobSeed); 01888 01889 if (Algid == CALG_SCHANNEL_MASTER_HASH) { 01890 static const char keyex[] = "key expansion"; 01891 BYTE key_expansion[sizeof keyex]; 01892 CRYPT_DATA_BLOB blobRandom, blobKeyExpansion = { 13, key_expansion }; 01893 01894 memcpy( key_expansion, keyex, sizeof keyex ); 01895 01896 if (pCryptKey->dwState != RSAENH_KEYSTATE_MASTERKEY) { 01897 static const char msec[] = "master secret"; 01898 BYTE master_secret[sizeof msec]; 01899 CRYPT_DATA_BLOB blobLabel = { 13, master_secret }; 01900 BYTE abKeyValue[48]; 01901 01902 memcpy( master_secret, msec, sizeof msec ); 01903 01904 /* See RFC 2246, chapter 8.1 */ 01905 if (!concat_data_blobs(&blobRandom, 01906 &pCryptKey->siSChannelInfo.blobClientRandom, 01907 &pCryptKey->siSChannelInfo.blobServerRandom)) 01908 { 01909 return FALSE; 01910 } 01911 tls1_prf(hProv, hKey, &blobLabel, &blobRandom, abKeyValue, 48); 01912 pCryptKey->dwState = RSAENH_KEYSTATE_MASTERKEY; 01913 memcpy(pCryptKey->abKeyValue, abKeyValue, 48); 01914 free_data_blob(&blobRandom); 01915 } 01916 01917 /* See RFC 2246, chapter 6.3 */ 01918 if (!concat_data_blobs(&blobRandom, 01919 &pCryptKey->siSChannelInfo.blobServerRandom, 01920 &pCryptKey->siSChannelInfo.blobClientRandom)) 01921 { 01922 return FALSE; 01923 } 01924 tls1_prf(hProv, hKey, &blobKeyExpansion, &blobRandom, pCryptHash->abHashValue, 01925 RSAENH_MAX_HASH_SIZE); 01926 free_data_blob(&blobRandom); 01927 } 01928 01929 return init_hash(pCryptHash); 01930 } 01931 01932 /****************************************************************************** 01933 * CPDestroyHash (RSAENH.@) 01934 * 01935 * Releases the handle to a hash object. The object is destroyed if its reference 01936 * count reaches zero. 01937 * 01938 * PARAMS 01939 * hProv [I] Handle to the key container to which the hash object belongs. 01940 * hHash [I] Handle to the hash object to be released. 01941 * 01942 * RETURNS 01943 * Success: TRUE 01944 * Failure: FALSE 01945 */ 01946 BOOL WINAPI RSAENH_CPDestroyHash(HCRYPTPROV hProv, HCRYPTHASH hHash) 01947 { 01948 TRACE("(hProv=%08lx, hHash=%08lx)\n", hProv, hHash); 01949 01950 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER)) 01951 { 01952 SetLastError(NTE_BAD_UID); 01953 return FALSE; 01954 } 01955 01956 if (!release_handle(&handle_table, hHash, RSAENH_MAGIC_HASH)) 01957 { 01958 SetLastError(NTE_BAD_HASH); 01959 return FALSE; 01960 } 01961 01962 return TRUE; 01963 } 01964 01965 /****************************************************************************** 01966 * CPDestroyKey (RSAENH.@) 01967 * 01968 * Releases the handle to a key object. The object is destroyed if its reference 01969 * count reaches zero. 01970 * 01971 * PARAMS 01972 * hProv [I] Handle to the key container to which the key object belongs. 01973 * hKey [I] Handle to the key object to be released. 01974 * 01975 * RETURNS 01976 * Success: TRUE 01977 * Failure: FALSE 01978 */ 01979 BOOL WINAPI RSAENH_CPDestroyKey(HCRYPTPROV hProv, HCRYPTKEY hKey) 01980 { 01981 TRACE("(hProv=%08lx, hKey=%08lx)\n", hProv, hKey); 01982 01983 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER)) 01984 { 01985 SetLastError(NTE_BAD_UID); 01986 return FALSE; 01987 } 01988 01989 if (!release_handle(&handle_table, hKey, RSAENH_MAGIC_KEY)) 01990 { 01991 SetLastError(NTE_BAD_KEY); 01992 return FALSE; 01993 } 01994 01995 return TRUE; 01996 } 01997 01998 /****************************************************************************** 01999 * CPDuplicateHash (RSAENH.@) 02000 * 02001 * Clones a hash object including its current state. 02002 * 02003 * PARAMS 02004 * hUID [I] Handle to the key container the hash belongs to. 02005 * hHash [I] Handle to the hash object to be cloned. 02006 * pdwReserved [I] Reserved. Must be NULL. 02007 * dwFlags [I] No flags are currently defined. Must be 0. 02008 * phHash [O] Handle to the cloned hash object. 02009 * 02010 * RETURNS 02011 * Success: TRUE. 02012 * Failure: FALSE. 02013 */ 02014 BOOL WINAPI RSAENH_CPDuplicateHash(HCRYPTPROV hUID, HCRYPTHASH hHash, DWORD *pdwReserved, 02015 DWORD dwFlags, HCRYPTHASH *phHash) 02016 { 02017 CRYPTHASH *pSrcHash, *pDestHash; 02018 02019 TRACE("(hUID=%08lx, hHash=%08lx, pdwReserved=%p, dwFlags=%08x, phHash=%p)\n", hUID, hHash, 02020 pdwReserved, dwFlags, phHash); 02021 02022 if (!is_valid_handle(&handle_table, hUID, RSAENH_MAGIC_CONTAINER)) 02023 { 02024 SetLastError(NTE_BAD_UID); 02025 return FALSE; 02026 } 02027 02028 if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH, (OBJECTHDR**)&pSrcHash)) 02029 { 02030 SetLastError(NTE_BAD_HASH); 02031 return FALSE; 02032 } 02033 02034 if (!phHash || pdwReserved || dwFlags) 02035 { 02036 SetLastError(ERROR_INVALID_PARAMETER); 02037 return FALSE; 02038 } 02039 02040 *phHash = new_object(&handle_table, sizeof(CRYPTHASH), RSAENH_MAGIC_HASH, 02041 destroy_hash, (OBJECTHDR**)&pDestHash); 02042 if (*phHash != (HCRYPTHASH)INVALID_HANDLE_VALUE) 02043 { 02044 *pDestHash = *pSrcHash; 02045 duplicate_hash_impl(pSrcHash->aiAlgid, &pSrcHash->context, &pDestHash->context); 02046 copy_hmac_info(&pDestHash->pHMACInfo, pSrcHash->pHMACInfo); 02047 copy_data_blob(&pDestHash->tpPRFParams.blobLabel, &pSrcHash->tpPRFParams.blobLabel); 02048 copy_data_blob(&pDestHash->tpPRFParams.blobSeed, &pSrcHash->tpPRFParams.blobSeed); 02049 } 02050 02051 return *phHash != (HCRYPTHASH)INVALID_HANDLE_VALUE; 02052 } 02053 02054 /****************************************************************************** 02055 * CPDuplicateKey (RSAENH.@) 02056 * 02057 * Clones a key object including its current state. 02058 * 02059 * PARAMS 02060 * hUID [I] Handle to the key container the hash belongs to. 02061 * hKey [I] Handle to the key object to be cloned. 02062 * pdwReserved [I] Reserved. Must be NULL. 02063 * dwFlags [I] No flags are currently defined. Must be 0. 02064 * phHash [O] Handle to the cloned key object. 02065 * 02066 * RETURNS 02067 * Success: TRUE. 02068 * Failure: FALSE. 02069 */ 02070 BOOL WINAPI RSAENH_CPDuplicateKey(HCRYPTPROV hUID, HCRYPTKEY hKey, DWORD *pdwReserved, 02071 DWORD dwFlags, HCRYPTKEY *phKey) 02072 { 02073 CRYPTKEY *pSrcKey, *pDestKey; 02074 02075 TRACE("(hUID=%08lx, hKey=%08lx, pdwReserved=%p, dwFlags=%08x, phKey=%p)\n", hUID, hKey, 02076 pdwReserved, dwFlags, phKey); 02077 02078 if (!is_valid_handle(&handle_table, hUID, RSAENH_MAGIC_CONTAINER)) 02079 { 02080 SetLastError(NTE_BAD_UID); 02081 return FALSE; 02082 } 02083 02084 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pSrcKey)) 02085 { 02086 SetLastError(NTE_BAD_KEY); 02087 return FALSE; 02088 } 02089 02090 if (!phKey || pdwReserved || dwFlags) 02091 { 02092 SetLastError(ERROR_INVALID_PARAMETER); 02093 return FALSE; 02094 } 02095 02096 *phKey = new_object(&handle_table, sizeof(CRYPTKEY), RSAENH_MAGIC_KEY, destroy_key, 02097 (OBJECTHDR**)&pDestKey); 02098 if (*phKey != (HCRYPTKEY)INVALID_HANDLE_VALUE) 02099 { 02100 *pDestKey = *pSrcKey; 02101 copy_data_blob(&pDestKey->siSChannelInfo.blobServerRandom, 02102 &pSrcKey->siSChannelInfo.blobServerRandom); 02103 copy_data_blob(&pDestKey->siSChannelInfo.blobClientRandom, 02104 &pSrcKey->siSChannelInfo.blobClientRandom); 02105 duplicate_key_impl(pSrcKey->aiAlgid, &pSrcKey->context, &pDestKey->context); 02106 return TRUE; 02107 } 02108 else 02109 { 02110 return FALSE; 02111 } 02112 } 02113 02114 /****************************************************************************** 02115 * CPEncrypt (RSAENH.@) 02116 * 02117 * Encrypt data. 02118 * 02119 * PARAMS 02120 * hProv [I] The key container hKey and hHash belong to. 02121 * hKey [I] The key used to encrypt the data. 02122 * hHash [I] An optional hash object for parallel hashing. See notes. 02123 * Final [I] Indicates if this is the last block of data to encrypt. 02124 * dwFlags [I] Currently no flags defined. Must be zero. 02125 * pbData [I/O] Pointer to the data to encrypt. Encrypted data will also be stored there. 02126 * pdwDataLen [I/O] I: Length of data to encrypt, O: Length of encrypted data. 02127 * dwBufLen [I] Size of the buffer at pbData. 02128 * 02129 * RETURNS 02130 * Success: TRUE. 02131 * Failure: FALSE. 02132 * 02133 * NOTES 02134 * If a hash object handle is provided in hHash, it will be updated with the plaintext. 02135 * This is useful for message signatures. 02136 * 02137 * This function uses the standard WINAPI protocol for querying data of dynamic length. 02138 */ 02139 BOOL WINAPI RSAENH_CPEncrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, 02140 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen, DWORD dwBufLen) 02141 { 02142 CRYPTKEY *pCryptKey; 02143 BYTE *in, out[RSAENH_MAX_BLOCK_SIZE], o[RSAENH_MAX_BLOCK_SIZE]; 02144 DWORD dwEncryptedLen, i, j, k; 02145 02146 TRACE("(hProv=%08lx, hKey=%08lx, hHash=%08lx, Final=%d, dwFlags=%08x, pbData=%p, " 02147 "pdwDataLen=%p, dwBufLen=%d)\n", hProv, hKey, hHash, Final, dwFlags, pbData, pdwDataLen, 02148 dwBufLen); 02149 02150 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER)) 02151 { 02152 SetLastError(NTE_BAD_UID); 02153 return FALSE; 02154 } 02155 02156 if (dwFlags) 02157 { 02158 SetLastError(NTE_BAD_FLAGS); 02159 return FALSE; 02160 } 02161 02162 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey)) 02163 { 02164 SetLastError(NTE_BAD_KEY); 02165 return FALSE; 02166 } 02167 02168 if (pCryptKey->dwState == RSAENH_KEYSTATE_IDLE) 02169 pCryptKey->dwState = RSAENH_KEYSTATE_ENCRYPTING; 02170 02171 if (pCryptKey->dwState != RSAENH_KEYSTATE_ENCRYPTING) 02172 { 02173 SetLastError(NTE_BAD_DATA); 02174 return FALSE; 02175 } 02176 02177 if (is_valid_handle(&handle_table, hHash, RSAENH_MAGIC_HASH)) { 02178 if (!RSAENH_CPHashData(hProv, hHash, pbData, *pdwDataLen, 0)) return FALSE; 02179 } 02180 02181 if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_BLOCK) { 02182 if (!Final && (*pdwDataLen % pCryptKey->dwBlockLen)) { 02183 SetLastError(NTE_BAD_DATA); 02184 return FALSE; 02185 } 02186 02187 dwEncryptedLen = (*pdwDataLen/pCryptKey->dwBlockLen+(Final?1:0))*pCryptKey->dwBlockLen; 02188 02189 if (pbData == NULL) { 02190 *pdwDataLen = dwEncryptedLen; 02191 return TRUE; 02192 } 02193 else if (dwEncryptedLen > dwBufLen) { 02194 *pdwDataLen = dwEncryptedLen; 02195 SetLastError(ERROR_MORE_DATA); 02196 return FALSE; 02197 } 02198 02199 /* Pad final block with length bytes */ 02200 for (i=*pdwDataLen; i<dwEncryptedLen; i++) pbData[i] = dwEncryptedLen - *pdwDataLen; 02201 *pdwDataLen = dwEncryptedLen; 02202 02203 for (i=0, in=pbData; i<*pdwDataLen; i+=pCryptKey->dwBlockLen, in+=pCryptKey->dwBlockLen) { 02204 switch (pCryptKey->dwMode) { 02205 case CRYPT_MODE_ECB: 02206 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out, 02207 RSAENH_ENCRYPT); 02208 break; 02209 02210 case CRYPT_MODE_CBC: 02211 for (j=0; j<pCryptKey->dwBlockLen; j++) in[j] ^= pCryptKey->abChainVector[j]; 02212 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out, 02213 RSAENH_ENCRYPT); 02214 memcpy(pCryptKey->abChainVector, out, pCryptKey->dwBlockLen); 02215 break; 02216 02217 case CRYPT_MODE_CFB: 02218 for (j=0; j<pCryptKey->dwBlockLen; j++) { 02219 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, 02220 pCryptKey->abChainVector, o, RSAENH_ENCRYPT); 02221 out[j] = in[j] ^ o[0]; 02222 for (k=0; k<pCryptKey->dwBlockLen-1; k++) 02223 pCryptKey->abChainVector[k] = pCryptKey->abChainVector[k+1]; 02224 pCryptKey->abChainVector[k] = out[j]; 02225 } 02226 break; 02227 02228 default: 02229 SetLastError(NTE_BAD_ALGID); 02230 return FALSE; 02231 } 02232 memcpy(in, out, pCryptKey->dwBlockLen); 02233 } 02234 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_STREAM) { 02235 if (pbData == NULL) { 02236 *pdwDataLen = dwBufLen; 02237 return TRUE; 02238 } 02239 encrypt_stream_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, *pdwDataLen); 02240 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_RSA) { 02241 if (pCryptKey->aiAlgid == CALG_RSA_SIGN) { 02242 SetLastError(NTE_BAD_KEY); 02243 return FALSE; 02244 } 02245 if (!pbData) { 02246 *pdwDataLen = pCryptKey->dwBlockLen; 02247 return TRUE; 02248 } 02249 if (dwBufLen < pCryptKey->dwBlockLen) { 02250 SetLastError(ERROR_MORE_DATA); 02251 return FALSE; 02252 } 02253 if (!pad_data(pbData, *pdwDataLen, pbData, pCryptKey->dwBlockLen, dwFlags)) return FALSE; 02254 encrypt_block_impl(pCryptKey->aiAlgid, PK_PUBLIC, &pCryptKey->context, pbData, pbData, RSAENH_ENCRYPT); 02255 *pdwDataLen = pCryptKey->dwBlockLen; 02256 Final = TRUE; 02257 } else { 02258 SetLastError(NTE_BAD_TYPE); 02259 return FALSE; 02260 } 02261 02262 if (Final) setup_key(pCryptKey); 02263 02264 return TRUE; 02265 } 02266 02267 /****************************************************************************** 02268 * CPDecrypt (RSAENH.@) 02269 * 02270 * Decrypt data. 02271 * 02272 * PARAMS 02273 * hProv [I] The key container hKey and hHash belong to. 02274 * hKey [I] The key used to decrypt the data. 02275 * hHash [I] An optional hash object for parallel hashing. See notes. 02276 * Final [I] Indicates if this is the last block of data to decrypt. 02277 * dwFlags [I] Currently no flags defined. Must be zero. 02278 * pbData [I/O] Pointer to the data to decrypt. Plaintext will also be stored there. 02279 * pdwDataLen [I/O] I: Length of ciphertext, O: Length of plaintext. 02280 * 02281 * RETURNS 02282 * Success: TRUE. 02283 * Failure: FALSE. 02284 * 02285 * NOTES 02286 * If a hash object handle is provided in hHash, it will be updated with the plaintext. 02287 * This is useful for message signatures. 02288 * 02289 * This function uses the standard WINAPI protocol for querying data of dynamic length. 02290 */ 02291 BOOL WINAPI RSAENH_CPDecrypt(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, 02292 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen) 02293 { 02294 CRYPTKEY *pCryptKey; 02295 BYTE *in, out[RSAENH_MAX_BLOCK_SIZE], o[RSAENH_MAX_BLOCK_SIZE]; 02296 DWORD i, j, k; 02297 DWORD dwMax; 02298 02299 TRACE("(hProv=%08lx, hKey=%08lx, hHash=%08lx, Final=%d, dwFlags=%08x, pbData=%p, " 02300 "pdwDataLen=%p)\n", hProv, hKey, hHash, Final, dwFlags, pbData, pdwDataLen); 02301 02302 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER)) 02303 { 02304 SetLastError(NTE_BAD_UID); 02305 return FALSE; 02306 } 02307 02308 if (dwFlags) 02309 { 02310 SetLastError(NTE_BAD_FLAGS); 02311 return FALSE; 02312 } 02313 02314 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey)) 02315 { 02316 SetLastError(NTE_BAD_KEY); 02317 return FALSE; 02318 } 02319 02320 if (pCryptKey->dwState == RSAENH_KEYSTATE_IDLE) 02321 pCryptKey->dwState = RSAENH_KEYSTATE_ENCRYPTING; 02322 02323 if (pCryptKey->dwState != RSAENH_KEYSTATE_ENCRYPTING) 02324 { 02325 SetLastError(NTE_BAD_DATA); 02326 return FALSE; 02327 } 02328 02329 dwMax=*pdwDataLen; 02330 02331 if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_BLOCK) { 02332 for (i=0, in=pbData; i<*pdwDataLen; i+=pCryptKey->dwBlockLen, in+=pCryptKey->dwBlockLen) { 02333 switch (pCryptKey->dwMode) { 02334 case CRYPT_MODE_ECB: 02335 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out, 02336 RSAENH_DECRYPT); 02337 break; 02338 02339 case CRYPT_MODE_CBC: 02340 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, in, out, 02341 RSAENH_DECRYPT); 02342 for (j=0; j<pCryptKey->dwBlockLen; j++) out[j] ^= pCryptKey->abChainVector[j]; 02343 memcpy(pCryptKey->abChainVector, in, pCryptKey->dwBlockLen); 02344 break; 02345 02346 case CRYPT_MODE_CFB: 02347 for (j=0; j<pCryptKey->dwBlockLen; j++) { 02348 encrypt_block_impl(pCryptKey->aiAlgid, 0, &pCryptKey->context, 02349 pCryptKey->abChainVector, o, RSAENH_ENCRYPT); 02350 out[j] = in[j] ^ o[0]; 02351 for (k=0; k<pCryptKey->dwBlockLen-1; k++) 02352 pCryptKey->abChainVector[k] = pCryptKey->abChainVector[k+1]; 02353 pCryptKey->abChainVector[k] = in[j]; 02354 } 02355 break; 02356 02357 default: 02358 SetLastError(NTE_BAD_ALGID); 02359 return FALSE; 02360 } 02361 memcpy(in, out, pCryptKey->dwBlockLen); 02362 } 02363 if (Final) { 02364 if (pbData[*pdwDataLen-1] && 02365 pbData[*pdwDataLen-1] <= pCryptKey->dwBlockLen && 02366 pbData[*pdwDataLen-1] <= *pdwDataLen) { 02367 BOOL padOkay = TRUE; 02368 02369 /* check that every bad byte has the same value */ 02370 for (i = 1; padOkay && i < pbData[*pdwDataLen-1]; i++) 02371 if (pbData[*pdwDataLen - i - 1] != pbData[*pdwDataLen - 1]) 02372 padOkay = FALSE; 02373 if (padOkay) 02374 *pdwDataLen -= pbData[*pdwDataLen-1]; 02375 else { 02376 SetLastError(NTE_BAD_DATA); 02377 return FALSE; 02378 } 02379 } 02380 else { 02381 SetLastError(NTE_BAD_DATA); 02382 return FALSE; 02383 } 02384 } 02385 02386 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_STREAM) { 02387 encrypt_stream_impl(pCryptKey->aiAlgid, &pCryptKey->context, pbData, *pdwDataLen); 02388 } else if (GET_ALG_TYPE(pCryptKey->aiAlgid) == ALG_TYPE_RSA) { 02389 if (pCryptKey->aiAlgid == CALG_RSA_SIGN) { 02390 SetLastError(NTE_BAD_KEY); 02391 return FALSE; 02392 } 02393 encrypt_block_impl(pCryptKey->aiAlgid, PK_PRIVATE, &pCryptKey->context, pbData, pbData, RSAENH_DECRYPT); 02394 if (!unpad_data(pbData, pCryptKey->dwBlockLen, pbData, pdwDataLen, dwFlags)) return FALSE; 02395 Final = TRUE; 02396 } else { 02397 SetLastError(NTE_BAD_TYPE); 02398 return FALSE; 02399 } 02400 02401 if (Final) setup_key(pCryptKey); 02402 02403 if (is_valid_handle(&handle_table, hHash, RSAENH_MAGIC_HASH)) { 02404 if (*pdwDataLen>dwMax || 02405 !RSAENH_CPHashData(hProv, hHash, pbData, *pdwDataLen, 0)) return FALSE; 02406 } 02407 02408 return TRUE; 02409 } 02410 02411 static BOOL crypt_export_simple(CRYPTKEY *pCryptKey, CRYPTKEY *pPubKey, 02412 DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen) 02413 { 02414 BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData; 02415 ALG_ID *pAlgid = (ALG_ID*)(pBlobHeader+1); 02416 DWORD dwDataLen; 02417 02418 if (!(GET_ALG_CLASS(pCryptKey->aiAlgid)&(ALG_CLASS_DATA_ENCRYPT|ALG_CLASS_MSG_ENCRYPT))) { 02419 SetLastError(NTE_BAD_KEY); /* FIXME: error code? */ 02420 return FALSE; 02421 } 02422 02423 dwDataLen = sizeof(BLOBHEADER) + sizeof(ALG_ID) + pPubKey->dwBlockLen; 02424 if (pbData) { 02425 if (*pdwDataLen < dwDataLen) { 02426 SetLastError(ERROR_MORE_DATA); 02427 *pdwDataLen = dwDataLen; 02428 return FALSE; 02429 } 02430 02431 pBlobHeader->bType = SIMPLEBLOB; 02432 pBlobHeader->bVersion = CUR_BLOB_VERSION; 02433 pBlobHeader->reserved = 0; 02434 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid; 02435 02436 *pAlgid = pPubKey->aiAlgid; 02437 02438 if (!pad_data(pCryptKey->abKeyValue, pCryptKey->dwKeyLen, (BYTE*)(pAlgid+1), 02439 pPubKey->dwBlockLen, dwFlags)) 02440 { 02441 return FALSE; 02442 } 02443 02444 encrypt_block_impl(pPubKey->aiAlgid, PK_PUBLIC, &pPubKey->context, (BYTE*)(pAlgid+1), 02445 (BYTE*)(pAlgid+1), RSAENH_ENCRYPT); 02446 } 02447 *pdwDataLen = dwDataLen; 02448 return TRUE; 02449 } 02450 02451 static BOOL crypt_export_public_key(CRYPTKEY *pCryptKey, BYTE *pbData, 02452 DWORD *pdwDataLen) 02453 { 02454 BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData; 02455 RSAPUBKEY *pRSAPubKey = (RSAPUBKEY*)(pBlobHeader+1); 02456 DWORD dwDataLen; 02457 02458 if ((pCryptKey->aiAlgid != CALG_RSA_KEYX) && (pCryptKey->aiAlgid != CALG_RSA_SIGN)) { 02459 SetLastError(NTE_BAD_KEY); 02460 return FALSE; 02461 } 02462 02463 dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + pCryptKey->dwKeyLen; 02464 if (pbData) { 02465 if (*pdwDataLen < dwDataLen) { 02466 SetLastError(ERROR_MORE_DATA); 02467 *pdwDataLen = dwDataLen; 02468 return FALSE; 02469 } 02470 02471 pBlobHeader->bType = PUBLICKEYBLOB; 02472 pBlobHeader->bVersion = CUR_BLOB_VERSION; 02473 pBlobHeader->reserved = 0; 02474 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid; 02475 02476 pRSAPubKey->magic = RSAENH_MAGIC_RSA1; 02477 pRSAPubKey->bitlen = pCryptKey->dwKeyLen << 3; 02478 02479 export_public_key_impl((BYTE*)(pRSAPubKey+1), &pCryptKey->context, 02480 pCryptKey->dwKeyLen, &pRSAPubKey->pubexp); 02481 } 02482 *pdwDataLen = dwDataLen; 02483 return TRUE; 02484 } 02485 02486 static BOOL crypt_export_private_key(CRYPTKEY *pCryptKey, BOOL force, 02487 BYTE *pbData, DWORD *pdwDataLen) 02488 { 02489 BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData; 02490 RSAPUBKEY *pRSAPubKey = (RSAPUBKEY*)(pBlobHeader+1); 02491 DWORD dwDataLen; 02492 02493 if ((pCryptKey->aiAlgid != CALG_RSA_KEYX) && (pCryptKey->aiAlgid != CALG_RSA_SIGN)) { 02494 SetLastError(NTE_BAD_KEY); 02495 return FALSE; 02496 } 02497 if (!force && !(pCryptKey->dwPermissions & CRYPT_EXPORT)) 02498 { 02499 SetLastError(NTE_BAD_KEY_STATE); 02500 return FALSE; 02501 } 02502 02503 dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + 02504 2 * pCryptKey->dwKeyLen + 5 * ((pCryptKey->dwKeyLen + 1) >> 1); 02505 if (pbData) { 02506 if (*pdwDataLen < dwDataLen) { 02507 SetLastError(ERROR_MORE_DATA); 02508 *pdwDataLen = dwDataLen; 02509 return FALSE; 02510 } 02511 02512 pBlobHeader->bType = PRIVATEKEYBLOB; 02513 pBlobHeader->bVersion = CUR_BLOB_VERSION; 02514 pBlobHeader->reserved = 0; 02515 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid; 02516 02517 pRSAPubKey->magic = RSAENH_MAGIC_RSA2; 02518 pRSAPubKey->bitlen = pCryptKey->dwKeyLen << 3; 02519 02520 export_private_key_impl((BYTE*)(pRSAPubKey+1), &pCryptKey->context, 02521 pCryptKey->dwKeyLen, &pRSAPubKey->pubexp); 02522 } 02523 *pdwDataLen = dwDataLen; 02524 return TRUE; 02525 } 02526 02527 static BOOL crypt_export_plaintext_key(CRYPTKEY *pCryptKey, BYTE *pbData, 02528 DWORD *pdwDataLen) 02529 { 02530 BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData; 02531 DWORD *pKeyLen = (DWORD*)(pBlobHeader+1); 02532 BYTE *pbKey = (BYTE*)(pKeyLen+1); 02533 DWORD dwDataLen; 02534 02535 dwDataLen = sizeof(BLOBHEADER) + sizeof(DWORD) + pCryptKey->dwKeyLen; 02536 if (pbData) { 02537 if (*pdwDataLen < dwDataLen) { 02538 SetLastError(ERROR_MORE_DATA); 02539 *pdwDataLen = dwDataLen; 02540 return FALSE; 02541 } 02542 02543 pBlobHeader->bType = PLAINTEXTKEYBLOB; 02544 pBlobHeader->bVersion = CUR_BLOB_VERSION; 02545 pBlobHeader->reserved = 0; 02546 pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid; 02547 02548 *pKeyLen = pCryptKey->dwKeyLen; 02549 memcpy(pbKey, pCryptKey->abKeyValue, pCryptKey->dwKeyLen); 02550 } 02551 *pdwDataLen = dwDataLen; 02552 return TRUE; 02553 } 02554 /****************************************************************************** 02555 * crypt_export_key [Internal] 02556 * 02557 * Export a key into a binary large object (BLOB). Called by CPExportKey and 02558 * by store_key_pair. 02559 * 02560 * PARAMS 02561 * pCryptKey [I] Key to be exported. 02562 * hPubKey [I] Key used to encrypt sensitive BLOB data. 02563 * dwBlobType [I] SIMPLEBLOB, PUBLICKEYBLOB or PRIVATEKEYBLOB. 02564 * dwFlags [I] Currently none defined. 02565 * force [I] If TRUE, the key is written no matter what the key's 02566 * permissions are. Otherwise the key's permissions are 02567 * checked before exporting. 02568 * pbData [O] Pointer to a buffer where the BLOB will be written to. 02569 * pdwDataLen [I/O] I: Size of buffer at pbData, O: Size of BLOB 02570 * 02571 * RETURNS 02572 * Success: TRUE. 02573 * Failure: FALSE. 02574 */ 02575 static BOOL crypt_export_key(CRYPTKEY *pCryptKey, HCRYPTKEY hPubKey, 02576 DWORD dwBlobType, DWORD dwFlags, BOOL force, 02577 BYTE *pbData, DWORD *pdwDataLen) 02578 { 02579 CRYPTKEY *pPubKey; 02580 02581 if (dwFlags & CRYPT_SSL2_FALLBACK) { 02582 if (pCryptKey->aiAlgid != CALG_SSL2_MASTER) { 02583 SetLastError(NTE_BAD_KEY); 02584 return FALSE; 02585 } 02586 } 02587 02588 switch ((BYTE)dwBlobType) 02589 { 02590 case SIMPLEBLOB: 02591 if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey)){ 02592 SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error_code? */ 02593 return FALSE; 02594 } 02595 return crypt_export_simple(pCryptKey, pPubKey, dwFlags, pbData, 02596 pdwDataLen); 02597 02598 case PUBLICKEYBLOB: 02599 if (is_valid_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY)) { 02600 SetLastError(NTE_BAD_KEY); /* FIXME: error code? */ 02601 return FALSE; 02602 } 02603 02604 return crypt_export_public_key(pCryptKey, pbData, pdwDataLen); 02605 02606 case PRIVATEKEYBLOB: 02607 return crypt_export_private_key(pCryptKey, force, pbData, pdwDataLen); 02608 02609 case PLAINTEXTKEYBLOB: 02610 return crypt_export_plaintext_key(pCryptKey, pbData, pdwDataLen); 02611 02612 default: 02613 SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */ 02614 return FALSE; 02615 } 02616 } 02617 02618 /****************************************************************************** 02619 * CPExportKey (RSAENH.@) 02620 * 02621 * Export a key into a binary large object (BLOB). 02622 * 02623 * PARAMS 02624 * hProv [I] Key container from which a key is to be exported. 02625 * hKey [I] Key to be exported. 02626 * hPubKey [I] Key used to encrypt sensitive BLOB data. 02627 * dwBlobType [I] SIMPLEBLOB, PUBLICKEYBLOB or PRIVATEKEYBLOB. 02628 * dwFlags [I] Currently none defined. 02629 * pbData [O] Pointer to a buffer where the BLOB will be written to. 02630 * pdwDataLen [I/O] I: Size of buffer at pbData, O: Size of BLOB 02631 * 02632 * RETURNS 02633 * Success: TRUE. 02634 * Failure: FALSE. 02635 */ 02636 BOOL WINAPI RSAENH_CPExportKey(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubKey, 02637 DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen) 02638 { 02639 CRYPTKEY *pCryptKey; 02640 02641 TRACE("(hProv=%08lx, hKey=%08lx, hPubKey=%08lx, dwBlobType=%08x, dwFlags=%08x, pbData=%p," 02642 "pdwDataLen=%p)\n", hProv, hKey, hPubKey, dwBlobType, dwFlags, pbData, pdwDataLen); 02643 02644 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER)) 02645 { 02646 SetLastError(NTE_BAD_UID); 02647 return FALSE; 02648 } 02649 02650 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey)) 02651 { 02652 SetLastError(NTE_BAD_KEY); 02653 return FALSE; 02654 } 02655 02656 return crypt_export_key(pCryptKey, hPubKey, dwBlobType, dwFlags, FALSE, 02657 pbData, pdwDataLen); 02658 } 02659 02660 /****************************************************************************** 02661 * release_and_install_key [Internal] 02662 * 02663 * Release an existing key, if present, and replaces it with a new one. 02664 * 02665 * PARAMS 02666 * hProv [I] Key container into which the key is to be imported. 02667 * src [I] Key which will replace *dest 02668 * dest [I] Points to key to be released and replaced with src 02669 * fStoreKey [I] If TRUE, the newly installed key is stored to the registry. 02670 */ 02671 static void release_and_install_key(HCRYPTPROV hProv, HCRYPTKEY src, 02672 HCRYPTKEY *dest, DWORD fStoreKey) 02673 { 02674 RSAENH_CPDestroyKey(hProv, *dest); 02675 copy_handle(&handle_table, src, RSAENH_MAGIC_KEY, dest); 02676 if (fStoreKey) 02677 { 02678 KEYCONTAINER *pKeyContainer; 02679 02680 if (lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER, 02681 (OBJECTHDR**)&pKeyContainer)) 02682 { 02683 store_key_container_keys(pKeyContainer); 02684 store_key_container_permissions(pKeyContainer); 02685 } 02686 } 02687 } 02688 02689 /****************************************************************************** 02690 * import_private_key [Internal] 02691 * 02692 * Import a BLOB'ed private key into a key container. 02693 * 02694 * PARAMS 02695 * hProv [I] Key container into which the private key is to be imported. 02696 * pbData [I] Pointer to a buffer which holds the private key BLOB. 02697 * dwDataLen [I] Length of data in buffer at pbData. 02698 * dwFlags [I] One of: 02699 * CRYPT_EXPORTABLE: the imported key is marked exportable 02700 * fStoreKey [I] If TRUE, the imported key is stored to the registry. 02701 * phKey [O] Handle to the imported key. 02702 * 02703 * 02704 * NOTES 02705 * Assumes the caller has already checked the BLOBHEADER at pbData to ensure 02706 * it's a PRIVATEKEYBLOB. 02707 * 02708 * RETURNS 02709 * Success: TRUE. 02710 * Failure: FALSE. 02711 */ 02712 static BOOL import_private_key(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen, 02713 DWORD dwFlags, BOOL fStoreKey, HCRYPTKEY *phKey) 02714 { 02715 KEYCONTAINER *pKeyContainer; 02716 CRYPTKEY *pCryptKey; 02717 CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData; 02718 CONST RSAPUBKEY *pRSAPubKey = (CONST RSAPUBKEY*)(pBlobHeader+1); 02719 BOOL ret; 02720 02721 if (dwFlags & CRYPT_IPSEC_HMAC_KEY) 02722 { 02723 FIXME("unimplemented for CRYPT_IPSEC_HMAC_KEY\n"); 02724 SetLastError(NTE_BAD_FLAGS); 02725 return FALSE; 02726 } 02727 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER, 02728 (OBJECTHDR**)&pKeyContainer)) 02729 { 02730 SetLastError(NTE_BAD_UID); 02731 return FALSE; 02732 } 02733 02734 if ((dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY))) 02735 { 02736 ERR("datalen %d not long enough for a BLOBHEADER + RSAPUBKEY\n", 02737 dwDataLen); 02738 SetLastError(NTE_BAD_DATA); 02739 return FALSE; 02740 } 02741 if (pRSAPubKey->magic != RSAENH_MAGIC_RSA2) 02742 { 02743 ERR("unexpected magic %08x\n", pRSAPubKey->magic); 02744 SetLastError(NTE_BAD_DATA); 02745 return FALSE; 02746 } 02747 if ((dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + 02748 (pRSAPubKey->bitlen >> 3) + (5 * ((pRSAPubKey->bitlen+8)>>4)))) 02749 { 02750 DWORD expectedLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + 02751 (pRSAPubKey->bitlen >> 3) + (5 * ((pRSAPubKey->bitlen+8)>>4)); 02752 02753 ERR("blob too short for pub key: expect %d, got %d\n", 02754 expectedLen, dwDataLen); 02755 SetLastError(NTE_BAD_DATA); 02756 return FALSE; 02757 } 02758 02759 *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey); 02760 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE; 02761 setup_key(pCryptKey); 02762 ret = import_private_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context, 02763 pRSAPubKey->bitlen/8, dwDataLen, pRSAPubKey->pubexp); 02764 if (ret) { 02765 if (dwFlags & CRYPT_EXPORTABLE) 02766 pCryptKey->dwPermissions |= CRYPT_EXPORT; 02767 switch (pBlobHeader->aiKeyAlg) 02768 { 02769 case AT_SIGNATURE: 02770 case CALG_RSA_SIGN: 02771 TRACE("installing signing key\n"); 02772 release_and_install_key(hProv, *phKey, &pKeyContainer->hSignatureKeyPair, 02773 fStoreKey); 02774 break; 02775 case AT_KEYEXCHANGE: 02776 case CALG_RSA_KEYX: 02777 TRACE("installing key exchange key\n"); 02778 release_and_install_key(hProv, *phKey, &pKeyContainer->hKeyExchangeKeyPair, 02779 fStoreKey); 02780 break; 02781 } 02782 } 02783 return ret; 02784 } 02785 02786 /****************************************************************************** 02787 * import_public_key [Internal] 02788 * 02789 * Import a BLOB'ed public key into a key container. 02790 * 02791 * PARAMS 02792 * hProv [I] Key container into which the public key is to be imported. 02793 * pbData [I] Pointer to a buffer which holds the public key BLOB. 02794 * dwDataLen [I] Length of data in buffer at pbData. 02795 * dwFlags [I] One of: 02796 * CRYPT_EXPORTABLE: the imported key is marked exportable 02797 * fStoreKey [I] If TRUE, the imported key is stored to the registry. 02798 * phKey [O] Handle to the imported key. 02799 * 02800 * 02801 * NOTES 02802 * Assumes the caller has already checked the BLOBHEADER at pbData to ensure 02803 * it's a PUBLICKEYBLOB. 02804 * 02805 * RETURNS 02806 * Success: TRUE. 02807 * Failure: FALSE. 02808 */ 02809 static BOOL import_public_key(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen, 02810 DWORD dwFlags, BOOL fStoreKey, HCRYPTKEY *phKey) 02811 { 02812 KEYCONTAINER *pKeyContainer; 02813 CRYPTKEY *pCryptKey; 02814 CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData; 02815 CONST RSAPUBKEY *pRSAPubKey = (CONST RSAPUBKEY*)(pBlobHeader+1); 02816 ALG_ID algID; 02817 BOOL ret; 02818 02819 if (dwFlags & CRYPT_IPSEC_HMAC_KEY) 02820 { 02821 FIXME("unimplemented for CRYPT_IPSEC_HMAC_KEY\n"); 02822 SetLastError(NTE_BAD_FLAGS); 02823 return FALSE; 02824 } 02825 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER, 02826 (OBJECTHDR**)&pKeyContainer)) 02827 { 02828 SetLastError(NTE_BAD_UID); 02829 return FALSE; 02830 } 02831 02832 if ((dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY)) || 02833 (pRSAPubKey->magic != RSAENH_MAGIC_RSA1) || 02834 (dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + (pRSAPubKey->bitlen >> 3))) 02835 { 02836 SetLastError(NTE_BAD_DATA); 02837 return FALSE; 02838 } 02839 02840 /* Since this is a public key blob, only the public key is 02841 * available, so only signature verification is possible. 02842 */ 02843 algID = pBlobHeader->aiKeyAlg; 02844 *phKey = new_key(hProv, algID, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey); 02845 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE; 02846 setup_key(pCryptKey); 02847 ret = import_public_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context, 02848 pRSAPubKey->bitlen >> 3, pRSAPubKey->pubexp); 02849 if (ret) { 02850 if (dwFlags & CRYPT_EXPORTABLE) 02851 pCryptKey->dwPermissions |= CRYPT_EXPORT; 02852 switch (pBlobHeader->aiKeyAlg) 02853 { 02854 case AT_KEYEXCHANGE: 02855 case CALG_RSA_KEYX: 02856 TRACE("installing public key\n"); 02857 release_and_install_key(hProv, *phKey, &pKeyContainer->hKeyExchangeKeyPair, 02858 fStoreKey); 02859 break; 02860 } 02861 } 02862 return ret; 02863 } 02864 02865 /****************************************************************************** 02866 * import_symmetric_key [Internal] 02867 * 02868 * Import a BLOB'ed symmetric key into a key container. 02869 * 02870 * PARAMS 02871 * hProv [I] Key container into which the symmetric key is to be imported. 02872 * pbData [I] Pointer to a buffer which holds the symmetric key BLOB. 02873 * dwDataLen [I] Length of data in buffer at pbData. 02874 * hPubKey [I] Key used to decrypt sensitive BLOB data. 02875 * dwFlags [I] One of: 02876 * CRYPT_EXPORTABLE: the imported key is marked exportable 02877 * phKey [O] Handle to the imported key. 02878 * 02879 * 02880 * NOTES 02881 * Assumes the caller has already checked the BLOBHEADER at pbData to ensure 02882 * it's a SIMPLEBLOB. 02883 * 02884 * RETURNS 02885 * Success: TRUE. 02886 * Failure: FALSE. 02887 */ 02888 static BOOL import_symmetric_key(HCRYPTPROV hProv, CONST BYTE *pbData, 02889 DWORD dwDataLen, HCRYPTKEY hPubKey, 02890 DWORD dwFlags, HCRYPTKEY *phKey) 02891 { 02892 CRYPTKEY *pCryptKey, *pPubKey; 02893 CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData; 02894 CONST ALG_ID *pAlgid = (CONST ALG_ID*)(pBlobHeader+1); 02895 CONST BYTE *pbKeyStream = (CONST BYTE*)(pAlgid + 1); 02896 BYTE *pbDecrypted; 02897 DWORD dwKeyLen; 02898 02899 if (dwFlags & CRYPT_IPSEC_HMAC_KEY) 02900 { 02901 FIXME("unimplemented for CRYPT_IPSEC_HMAC_KEY\n"); 02902 SetLastError(NTE_BAD_FLAGS); 02903 return FALSE; 02904 } 02905 if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey) || 02906 pPubKey->aiAlgid != CALG_RSA_KEYX) 02907 { 02908 SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error code? */ 02909 return FALSE; 02910 } 02911 02912 if (dwDataLen < sizeof(BLOBHEADER)+sizeof(ALG_ID)+pPubKey->dwBlockLen) 02913 { 02914 SetLastError(NTE_BAD_DATA); /* FIXME: error code */ 02915 return FALSE; 02916 } 02917 02918 pbDecrypted = HeapAlloc(GetProcessHeap(), 0, pPubKey->dwBlockLen); 02919 if (!pbDecrypted) return FALSE; 02920 encrypt_block_impl(pPubKey->aiAlgid, PK_PRIVATE, &pPubKey->context, pbKeyStream, pbDecrypted, 02921 RSAENH_DECRYPT); 02922 02923 dwKeyLen = RSAENH_MAX_KEY_SIZE; 02924 if (!unpad_data(pbDecrypted, pPubKey->dwBlockLen, pbDecrypted, &dwKeyLen, dwFlags)) { 02925 HeapFree(GetProcessHeap(), 0, pbDecrypted); 02926 return FALSE; 02927 } 02928 02929 *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, dwKeyLen<<19, &pCryptKey); 02930 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) 02931 { 02932 HeapFree(GetProcessHeap(), 0, pbDecrypted); 02933 return FALSE; 02934 } 02935 memcpy(pCryptKey->abKeyValue, pbDecrypted, dwKeyLen); 02936 HeapFree(GetProcessHeap(), 0, pbDecrypted); 02937 setup_key(pCryptKey); 02938 if (dwFlags & CRYPT_EXPORTABLE) 02939 pCryptKey->dwPermissions |= CRYPT_EXPORT; 02940 return TRUE; 02941 } 02942 02943 /****************************************************************************** 02944 * import_plaintext_key [Internal] 02945 * 02946 * Import a plaintext key into a key container. 02947 * 02948 * PARAMS 02949 * hProv [I] Key container into which the symmetric key is to be imported. 02950 * pbData [I] Pointer to a buffer which holds the plaintext key BLOB. 02951 * dwDataLen [I] Length of data in buffer at pbData. 02952 * dwFlags [I] One of: 02953 * CRYPT_EXPORTABLE: the imported key is marked exportable 02954 * phKey [O] Handle to the imported key. 02955 * 02956 * 02957 * NOTES 02958 * Assumes the caller has already checked the BLOBHEADER at pbData to ensure 02959 * it's a PLAINTEXTKEYBLOB. 02960 * 02961 * RETURNS 02962 * Success: TRUE. 02963 * Failure: FALSE. 02964 */ 02965 static BOOL import_plaintext_key(HCRYPTPROV hProv, CONST BYTE *pbData, 02966 DWORD dwDataLen, DWORD dwFlags, 02967 HCRYPTKEY *phKey) 02968 { 02969 CRYPTKEY *pCryptKey; 02970 CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData; 02971 CONST DWORD *pKeyLen = (CONST DWORD *)(pBlobHeader + 1); 02972 CONST BYTE *pbKeyStream = (CONST BYTE*)(pKeyLen + 1); 02973 02974 if (dwDataLen < sizeof(BLOBHEADER)+sizeof(DWORD)+*pKeyLen) 02975 { 02976 SetLastError(NTE_BAD_DATA); /* FIXME: error code */ 02977 return FALSE; 02978 } 02979 02980 if (dwFlags & CRYPT_IPSEC_HMAC_KEY) 02981 { 02982 *phKey = new_key(hProv, CALG_HMAC, 0, &pCryptKey); 02983 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) 02984 return FALSE; 02985 if (*pKeyLen <= RSAENH_MIN(sizeof(pCryptKey->abKeyValue), RSAENH_HMAC_BLOCK_LEN)) 02986 { 02987 memcpy(pCryptKey->abKeyValue, pbKeyStream, *pKeyLen); 02988 pCryptKey->dwKeyLen = *pKeyLen; 02989 } 02990 else 02991 { 02992 CRYPT_DATA_BLOB blobHmacKey = { *pKeyLen, (BYTE *)pbKeyStream }; 02993 02994 /* In order to initialize an HMAC key, the key material is hashed, 02995 * and the output of the hash function is used as the key material. 02996 * Unfortunately, the way the Crypto API is designed, we don't know 02997 * the hash algorithm yet, so we have to copy the entire key 02998 * material. 02999 */ 03000 if (!copy_data_blob(&pCryptKey->blobHmacKey, &blobHmacKey)) 03001 { 03002 release_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY); 03003 *phKey = (HCRYPTKEY)INVALID_HANDLE_VALUE; 03004 return FALSE; 03005 } 03006 } 03007 setup_key(pCryptKey); 03008 if (dwFlags & CRYPT_EXPORTABLE) 03009 pCryptKey->dwPermissions |= CRYPT_EXPORT; 03010 } 03011 else 03012 { 03013 *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, *pKeyLen<<19, &pCryptKey); 03014 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) 03015 return FALSE; 03016 memcpy(pCryptKey->abKeyValue, pbKeyStream, *pKeyLen); 03017 setup_key(pCryptKey); 03018 if (dwFlags & CRYPT_EXPORTABLE) 03019 pCryptKey->dwPermissions |= CRYPT_EXPORT; 03020 } 03021 return TRUE; 03022 } 03023 03024 /****************************************************************************** 03025 * import_key [Internal] 03026 * 03027 * Import a BLOB'ed key into a key container, optionally storing the key's 03028 * value to the registry. 03029 * 03030 * PARAMS 03031 * hProv [I] Key container into which the key is to be imported. 03032 * pbData [I] Pointer to a buffer which holds the BLOB. 03033 * dwDataLen [I] Length of data in buffer at pbData. 03034 * hPubKey [I] Key used to decrypt sensitive BLOB data. 03035 * dwFlags [I] One of: 03036 * CRYPT_EXPORTABLE: the imported key is marked exportable 03037 * fStoreKey [I] If TRUE, the imported key is stored to the registry. 03038 * phKey [O] Handle to the imported key. 03039 * 03040 * RETURNS 03041 * Success: TRUE. 03042 * Failure: FALSE. 03043 */ 03044 static BOOL import_key(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen, 03045 HCRYPTKEY hPubKey, DWORD dwFlags, BOOL fStoreKey, 03046 HCRYPTKEY *phKey) 03047 { 03048 KEYCONTAINER *pKeyContainer; 03049 CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData; 03050 03051 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER, 03052 (OBJECTHDR**)&pKeyContainer)) 03053 { 03054 SetLastError(NTE_BAD_UID); 03055 return FALSE; 03056 } 03057 03058 if (dwDataLen < sizeof(BLOBHEADER) || 03059 pBlobHeader->bVersion != CUR_BLOB_VERSION || 03060 pBlobHeader->reserved != 0) 03061 { 03062 TRACE("bVersion = %d, reserved = %d\n", pBlobHeader->bVersion, 03063 pBlobHeader->reserved); 03064 SetLastError(NTE_BAD_DATA); 03065 return FALSE; 03066 } 03067 03068 /* If this is a verify-only context, the key is not persisted regardless of 03069 * fStoreKey's original value. 03070 */ 03071 fStoreKey = fStoreKey && !(dwFlags & CRYPT_VERIFYCONTEXT); 03072 TRACE("blob type: %x\n", pBlobHeader->bType); 03073 switch (pBlobHeader->bType) 03074 { 03075 case PRIVATEKEYBLOB: 03076 return import_private_key(hProv, pbData, dwDataLen, dwFlags, 03077 fStoreKey, phKey); 03078 03079 case PUBLICKEYBLOB: 03080 return import_public_key(hProv, pbData, dwDataLen, dwFlags, 03081 fStoreKey, phKey); 03082 03083 case SIMPLEBLOB: 03084 return import_symmetric_key(hProv, pbData, dwDataLen, hPubKey, 03085 dwFlags, phKey); 03086 03087 case PLAINTEXTKEYBLOB: 03088 return import_plaintext_key(hProv, pbData, dwDataLen, dwFlags, 03089 phKey); 03090 03091 default: 03092 SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */ 03093 return FALSE; 03094 } 03095 } 03096 03097 /****************************************************************************** 03098 * CPImportKey (RSAENH.@) 03099 * 03100 * Import a BLOB'ed key into a key container. 03101 * 03102 * PARAMS 03103 * hProv [I] Key container into which the key is to be imported. 03104 * pbData [I] Pointer to a buffer which holds the BLOB. 03105 * dwDataLen [I] Length of data in buffer at pbData. 03106 * hPubKey [I] Key used to decrypt sensitive BLOB data. 03107 * dwFlags [I] One of: 03108 * CRYPT_EXPORTABLE: the imported key is marked exportable 03109 * phKey [O] Handle to the imported key. 03110 * 03111 * RETURNS 03112 * Success: TRUE. 03113 * Failure: FALSE. 03114 */ 03115 BOOL WINAPI RSAENH_CPImportKey(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen, 03116 HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey) 03117 { 03118 TRACE("(hProv=%08lx, pbData=%p, dwDataLen=%d, hPubKey=%08lx, dwFlags=%08x, phKey=%p)\n", 03119 hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey); 03120 03121 return import_key(hProv, pbData, dwDataLen, hPubKey, dwFlags, TRUE, phKey); 03122 } 03123 03124 /****************************************************************************** 03125 * CPGenKey (RSAENH.@) 03126 * 03127 * Generate a key in the key container 03128 * 03129 * PARAMS 03130 * hProv [I] Key container for which a key is to be generated. 03131 * Algid [I] Crypto algorithm identifier for the key to be generated. 03132 * dwFlags [I] Upper 16 bits: Binary length of key. Lower 16 bits: Flags. See Notes 03133 * phKey [O] Handle to the generated key. 03134 * 03135 * RETURNS 03136 * Success: TRUE. 03137 * Failure: FALSE. 03138 * 03139 * FIXME 03140 * Flags currently not considered. 03141 * 03142 * NOTES 03143 * Private key-exchange- and signature-keys can be generated with Algid AT_KEYEXCHANGE 03144 * and AT_SIGNATURE values. 03145 */ 03146 BOOL WINAPI RSAENH_CPGenKey(HCRYPTPROV hProv, ALG_ID Algid, DWORD dwFlags, HCRYPTKEY *phKey) 03147 { 03148 KEYCONTAINER *pKeyContainer; 03149 CRYPTKEY *pCryptKey; 03150 03151 TRACE("(hProv=%08lx, aiAlgid=%d, dwFlags=%08x, phKey=%p)\n", hProv, Algid, dwFlags, phKey); 03152 03153 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER, 03154 (OBJECTHDR**)&pKeyContainer)) 03155 { 03156 /* MSDN: hProv not containing valid context handle */ 03157 SetLastError(NTE_BAD_UID); 03158 return FALSE; 03159 } 03160 03161 switch (Algid) 03162 { 03163 case AT_SIGNATURE: 03164 case CALG_RSA_SIGN: 03165 *phKey = new_key(hProv, CALG_RSA_SIGN, dwFlags, &pCryptKey); 03166 if (pCryptKey) { 03167 new_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen); 03168 setup_key(pCryptKey); 03169 release_and_install_key(hProv, *phKey, 03170 &pKeyContainer->hSignatureKeyPair, 03171 FALSE); 03172 } 03173 break; 03174 03175 case AT_KEYEXCHANGE: 03176 case CALG_RSA_KEYX: 03177 *phKey = new_key(hProv, CALG_RSA_KEYX, dwFlags, &pCryptKey); 03178 if (pCryptKey) { 03179 new_key_impl(pCryptKey->aiAlgid, &pCryptKey->context, pCryptKey->dwKeyLen); 03180 setup_key(pCryptKey); 03181 release_and_install_key(hProv, *phKey, 03182 &pKeyContainer->hKeyExchangeKeyPair, 03183 FALSE); 03184 } 03185 break; 03186 03187 case CALG_RC2: 03188 case CALG_RC4: 03189 case CALG_DES: 03190 case CALG_3DES_112: 03191 case CALG_3DES: 03192 case CALG_AES: 03193 case CALG_AES_128: 03194 case CALG_AES_192: 03195 case CALG_AES_256: 03196 case CALG_PCT1_MASTER: 03197 case CALG_SSL2_MASTER: 03198 case CALG_SSL3_MASTER: 03199 case CALG_TLS1_MASTER: 03200 *phKey = new_key(hProv, Algid, dwFlags, &pCryptKey); 03201 if (pCryptKey) { 03202 gen_rand_impl(pCryptKey->abKeyValue, RSAENH_MAX_KEY_SIZE); 03203 switch (Algid) { 03204 case CALG_SSL3_MASTER: 03205 pCryptKey->abKeyValue[0] = RSAENH_SSL3_VERSION_MAJOR; 03206 pCryptKey->abKeyValue[1] = RSAENH_SSL3_VERSION_MINOR; 03207 break; 03208 03209 case CALG_TLS1_MASTER: 03210 pCryptKey->abKeyValue[0] = RSAENH_TLS1_VERSION_MAJOR; 03211 pCryptKey->abKeyValue[1] = RSAENH_TLS1_VERSION_MINOR; 03212 break; 03213 } 03214 setup_key(pCryptKey); 03215 } 03216 break; 03217 03218 default: 03219 /* MSDN: Algorithm not supported specified by Algid */ 03220 SetLastError(NTE_BAD_ALGID); 03221 return FALSE; 03222 } 03223 03224 return *phKey != (HCRYPTKEY)INVALID_HANDLE_VALUE; 03225 } 03226 03227 /****************************************************************************** 03228 * CPGenRandom (RSAENH.@) 03229 * 03230 * Generate a random byte stream. 03231 * 03232 * PARAMS 03233 * hProv [I] Key container that is used to generate random bytes. 03234 * dwLen [I] Specifies the number of requested random data bytes. 03235 * pbBuffer [O] Random bytes will be stored here. 03236 * 03237 * RETURNS 03238 * Success: TRUE 03239 * Failure: FALSE 03240 */ 03241 BOOL WINAPI RSAENH_CPGenRandom(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer) 03242 { 03243 TRACE("(hProv=%08lx, dwLen=%d, pbBuffer=%p)\n", hProv, dwLen, pbBuffer); 03244 03245 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER)) 03246 { 03247 /* MSDN: hProv not containing valid context handle */ 03248 SetLastError(NTE_BAD_UID); 03249 return FALSE; 03250 } 03251 03252 return gen_rand_impl(pbBuffer, dwLen); 03253 } 03254 03255 /****************************************************************************** 03256 * CPGetHashParam (RSAENH.@) 03257 * 03258 * Query parameters of an hash object. 03259 * 03260 * PARAMS 03261 * hProv [I] The kea container, which the hash belongs to. 03262 * hHash [I] The hash object that is to be queried. 03263 * dwParam [I] Specifies the parameter that is to be queried. 03264 * pbData [I] Pointer to the buffer where the parameter value will be stored. 03265 * pdwDataLen [I/O] I: Buffer length at pbData, O: Length of the parameter value. 03266 * dwFlags [I] None currently defined. 03267 * 03268 * RETURNS 03269 * Success: TRUE 03270 * Failure: FALSE 03271 * 03272 * NOTES 03273 * Valid dwParams are: HP_ALGID, HP_HASHSIZE, HP_HASHVALUE. The hash will be 03274 * finalized if HP_HASHVALUE is queried. 03275 */ 03276 BOOL WINAPI RSAENH_CPGetHashParam(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam, BYTE *pbData, 03277 DWORD *pdwDataLen, DWORD dwFlags) 03278 { 03279 CRYPTHASH *pCryptHash; 03280 03281 TRACE("(hProv=%08lx, hHash=%08lx, dwParam=%08x, pbData=%p, pdwDataLen=%p, dwFlags=%08x)\n", 03282 hProv, hHash, dwParam, pbData, pdwDataLen, dwFlags); 03283 03284 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER)) 03285 { 03286 SetLastError(NTE_BAD_UID); 03287 return FALSE; 03288 } 03289 03290 if (dwFlags) 03291 { 03292 SetLastError(NTE_BAD_FLAGS); 03293 return FALSE; 03294 } 03295 03296 if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH, 03297 (OBJECTHDR**)&pCryptHash)) 03298 { 03299 SetLastError(NTE_BAD_HASH); 03300 return FALSE; 03301 } 03302 03303 if (!pdwDataLen) 03304 { 03305 SetLastError(ERROR_INVALID_PARAMETER); 03306 return FALSE; 03307 } 03308 03309 switch (dwParam) 03310 { 03311 case HP_ALGID: 03312 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptHash->aiAlgid, 03313 sizeof(ALG_ID)); 03314 03315 case HP_HASHSIZE: 03316 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptHash->dwHashSize, 03317 sizeof(DWORD)); 03318 03319 case HP_HASHVAL: 03320 if (pCryptHash->aiAlgid == CALG_TLS1PRF) { 03321 return tls1_prf(hProv, pCryptHash->hKey, &pCryptHash->tpPRFParams.blobLabel, 03322 &pCryptHash->tpPRFParams.blobSeed, pbData, *pdwDataLen); 03323 } 03324 03325 if ( pbData == NULL ) { 03326 *pdwDataLen = pCryptHash->dwHashSize; 03327 return TRUE; 03328 } 03329 03330 if (pbData && (pCryptHash->dwState != RSAENH_HASHSTATE_FINISHED)) 03331 { 03332 finalize_hash(pCryptHash); 03333 pCryptHash->dwState = RSAENH_HASHSTATE_FINISHED; 03334 } 03335 03336 return copy_param(pbData, pdwDataLen, pCryptHash->abHashValue, 03337 pCryptHash->dwHashSize); 03338 03339 default: 03340 SetLastError(NTE_BAD_TYPE); 03341 return FALSE; 03342 } 03343 } 03344 03345 /****************************************************************************** 03346 * CPSetKeyParam (RSAENH.@) 03347 * 03348 * Set a parameter of a key object 03349 * 03350 * PARAMS 03351 * hProv [I] The key container to which the key belongs. 03352 * hKey [I] The key for which a parameter is to be set. 03353 * dwParam [I] Parameter type. See Notes. 03354 * pbData [I] Pointer to the parameter value. 03355 * dwFlags [I] Currently none defined. 03356 * 03357 * RETURNS 03358 * Success: TRUE. 03359 * Failure: FALSE. 03360 * 03361 * NOTES: 03362 * Defined dwParam types are: 03363 * - KP_MODE: Values MODE_CBC, MODE_ECB, MODE_CFB. 03364 * - KP_MODE_BITS: Shift width for cipher feedback mode. (Currently ignored by MS CSP's) 03365 * - KP_PERMISSIONS: Or'ed combination of CRYPT_ENCRYPT, CRYPT_DECRYPT, 03366 * CRYPT_EXPORT, CRYPT_READ, CRYPT_WRITE, CRYPT_MAC 03367 * - KP_IV: Initialization vector 03368 */ 03369 BOOL WINAPI RSAENH_CPSetKeyParam(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, 03370 DWORD dwFlags) 03371 { 03372 CRYPTKEY *pCryptKey; 03373 03374 TRACE("(hProv=%08lx, hKey=%08lx, dwParam=%08x, pbData=%p, dwFlags=%08x)\n", hProv, hKey, 03375 dwParam, pbData, dwFlags); 03376 03377 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER)) 03378 { 03379 SetLastError(NTE_BAD_UID); 03380 return FALSE; 03381 } 03382 03383 if (dwFlags) { 03384 SetLastError(NTE_BAD_FLAGS); 03385 return FALSE; 03386 } 03387 03388 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey)) 03389 { 03390 SetLastError(NTE_BAD_KEY); 03391 return FALSE; 03392 } 03393 03394 switch (dwParam) { 03395 case KP_PADDING: 03396 /* The MS providers only support PKCS5_PADDING */ 03397 if (*(DWORD *)pbData != PKCS5_PADDING) { 03398 SetLastError(NTE_BAD_DATA); 03399 return FALSE; 03400 } 03401 return TRUE; 03402 03403 case KP_MODE: 03404 pCryptKey->dwMode = *(DWORD*)pbData; 03405 return TRUE; 03406 03407 case KP_MODE_BITS: 03408 pCryptKey->dwModeBits = *(DWORD*)pbData; 03409 return TRUE; 03410 03411 case KP_PERMISSIONS: 03412 { 03413 DWORD perms = *(DWORD *)pbData; 03414 03415 if ((perms & CRYPT_EXPORT) && 03416 !(pCryptKey->dwPermissions & CRYPT_EXPORT)) 03417 { 03418 SetLastError(NTE_BAD_DATA); 03419 return FALSE; 03420 } 03421 else if (!(perms & CRYPT_EXPORT) && 03422 (pCryptKey->dwPermissions & CRYPT_EXPORT)) 03423 { 03424 /* Clearing the export permission appears to be ignored, 03425 * see tests. 03426 */ 03427 perms |= CRYPT_EXPORT; 03428 } 03429 pCryptKey->dwPermissions = perms; 03430 return TRUE; 03431 } 03432 03433 case KP_IV: 03434 memcpy(pCryptKey->abInitVector, pbData, pCryptKey->dwBlockLen); 03435 setup_key(pCryptKey); 03436 return TRUE; 03437 03438 case KP_SALT: 03439 switch (pCryptKey->aiAlgid) { 03440 case CALG_RC2: 03441 case CALG_RC4: 03442 if (!pbData) 03443 { 03444 SetLastError(ERROR_INVALID_PARAMETER); 03445 return FALSE; 03446 } 03447 /* MSDN: the base provider always sets eleven bytes of 03448 * salt value. 03449 */ 03450 memcpy(pCryptKey->abKeyValue + pCryptKey->dwKeyLen, 03451 pbData, 11); 03452 pCryptKey->dwSaltLen = 11; 03453 setup_key(pCryptKey); 03454 /* Strange but true: salt length reset to 0 after setting 03455 * it via KP_SALT. 03456 */ 03457 pCryptKey->dwSaltLen = 0; 03458 break; 03459 default: 03460 SetLastError(NTE_BAD_KEY); 03461 return FALSE; 03462 } 03463 return TRUE; 03464 03465 case KP_SALT_EX: 03466 { 03467 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pbData; 03468 03469 /* salt length can't be greater than 184 bits = 24 bytes */ 03470 if (blob->cbData > 24) 03471 { 03472 SetLastError(NTE_BAD_DATA); 03473 return FALSE; 03474 } 03475 memcpy(pCryptKey->abKeyValue + pCryptKey->dwKeyLen, blob->pbData, 03476 blob->cbData); 03477 pCryptKey->dwSaltLen = blob->cbData; 03478 setup_key(pCryptKey); 03479 return TRUE; 03480 } 03481 03482 case KP_EFFECTIVE_KEYLEN: 03483 switch (pCryptKey->aiAlgid) { 03484 case CALG_RC2: 03485 if (!pbData) 03486 { 03487 SetLastError(ERROR_INVALID_PARAMETER); 03488 return FALSE; 03489 } 03490 else if (!*(DWORD *)pbData || *(DWORD *)pbData > 1024) 03491 { 03492 SetLastError(NTE_BAD_DATA); 03493 return FALSE; 03494 } 03495 else 03496 { 03497 pCryptKey->dwEffectiveKeyLen = *(DWORD *)pbData; 03498 setup_key(pCryptKey); 03499 } 03500 break; 03501 default: 03502 SetLastError(NTE_BAD_TYPE); 03503 return FALSE; 03504 } 03505 return TRUE; 03506 03507 case KP_SCHANNEL_ALG: 03508 switch (((PSCHANNEL_ALG)pbData)->dwUse) { 03509 case SCHANNEL_ENC_KEY: 03510 memcpy(&pCryptKey->siSChannelInfo.saEncAlg, pbData, sizeof(SCHANNEL_ALG)); 03511 break; 03512 03513 case SCHANNEL_MAC_KEY: 03514 memcpy(&pCryptKey->siSChannelInfo.saMACAlg, pbData, sizeof(SCHANNEL_ALG)); 03515 break; 03516 03517 default: 03518 SetLastError(NTE_FAIL); /* FIXME: error code */ 03519 return FALSE; 03520 } 03521 return TRUE; 03522 03523 case KP_CLIENT_RANDOM: 03524 return copy_data_blob(&pCryptKey->siSChannelInfo.blobClientRandom, (PCRYPT_DATA_BLOB)pbData); 03525 03526 case KP_SERVER_RANDOM: 03527 return copy_data_blob(&pCryptKey->siSChannelInfo.blobServerRandom, (PCRYPT_DATA_BLOB)pbData); 03528 03529 default: 03530 SetLastError(NTE_BAD_TYPE); 03531 return FALSE; 03532 } 03533 } 03534 03535 /****************************************************************************** 03536 * CPGetKeyParam (RSAENH.@) 03537 * 03538 * Query a key parameter. 03539 * 03540 * PARAMS 03541 * hProv [I] The key container, which the key belongs to. 03542 * hHash [I] The key object that is to be queried. 03543 * dwParam [I] Specifies the parameter that is to be queried. 03544 * pbData [I] Pointer to the buffer where the parameter value will be stored. 03545 * pdwDataLen [I/O] I: Buffer length at pbData, O: Length of the parameter value. 03546 * dwFlags [I] None currently defined. 03547 * 03548 * RETURNS 03549 * Success: TRUE 03550 * Failure: FALSE 03551 * 03552 * NOTES 03553 * Defined dwParam types are: 03554 * - KP_MODE: Values MODE_CBC, MODE_ECB, MODE_CFB. 03555 * - KP_MODE_BITS: Shift width for cipher feedback mode. 03556 * (Currently ignored by MS CSP's - always eight) 03557 * - KP_PERMISSIONS: Or'ed combination of CRYPT_ENCRYPT, CRYPT_DECRYPT, 03558 * CRYPT_EXPORT, CRYPT_READ, CRYPT_WRITE, CRYPT_MAC 03559 * - KP_IV: Initialization vector. 03560 * - KP_KEYLEN: Bitwidth of the key. 03561 * - KP_BLOCKLEN: Size of a block cipher block. 03562 * - KP_SALT: Salt value. 03563 */ 03564 BOOL WINAPI RSAENH_CPGetKeyParam(HCRYPTPROV hProv, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, 03565 DWORD *pdwDataLen, DWORD dwFlags) 03566 { 03567 CRYPTKEY *pCryptKey; 03568 DWORD dwValue; 03569 03570 TRACE("(hProv=%08lx, hKey=%08lx, dwParam=%08x, pbData=%p, pdwDataLen=%p dwFlags=%08x)\n", 03571 hProv, hKey, dwParam, pbData, pdwDataLen, dwFlags); 03572 03573 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER)) 03574 { 03575 SetLastError(NTE_BAD_UID); 03576 return FALSE; 03577 } 03578 03579 if (dwFlags) { 03580 SetLastError(NTE_BAD_FLAGS); 03581 return FALSE; 03582 } 03583 03584 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pCryptKey)) 03585 { 03586 SetLastError(NTE_BAD_KEY); 03587 return FALSE; 03588 } 03589 03590 switch (dwParam) 03591 { 03592 case KP_IV: 03593 return copy_param(pbData, pdwDataLen, pCryptKey->abInitVector, 03594 pCryptKey->dwBlockLen); 03595 03596 case KP_SALT: 03597 switch (pCryptKey->aiAlgid) { 03598 case CALG_RC2: 03599 case CALG_RC4: 03600 return copy_param(pbData, pdwDataLen, 03601 &pCryptKey->abKeyValue[pCryptKey->dwKeyLen], 03602 pCryptKey->dwSaltLen); 03603 default: 03604 SetLastError(NTE_BAD_KEY); 03605 return FALSE; 03606 } 03607 03608 case KP_PADDING: 03609 dwValue = PKCS5_PADDING; 03610 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD)); 03611 03612 case KP_KEYLEN: 03613 dwValue = pCryptKey->dwKeyLen << 3; 03614 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD)); 03615 03616 case KP_EFFECTIVE_KEYLEN: 03617 if (pCryptKey->dwEffectiveKeyLen) 03618 dwValue = pCryptKey->dwEffectiveKeyLen; 03619 else 03620 dwValue = pCryptKey->dwKeyLen << 3; 03621 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD)); 03622 03623 case KP_BLOCKLEN: 03624 dwValue = pCryptKey->dwBlockLen << 3; 03625 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD)); 03626 03627 case KP_MODE: 03628 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->dwMode, sizeof(DWORD)); 03629 03630 case KP_MODE_BITS: 03631 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->dwModeBits, 03632 sizeof(DWORD)); 03633 03634 case KP_PERMISSIONS: 03635 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->dwPermissions, 03636 sizeof(DWORD)); 03637 03638 case KP_ALGID: 03639 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&pCryptKey->aiAlgid, sizeof(DWORD)); 03640 03641 default: 03642 SetLastError(NTE_BAD_TYPE); 03643 return FALSE; 03644 } 03645 } 03646 03647 /****************************************************************************** 03648 * CPGetProvParam (RSAENH.@) 03649 * 03650 * Query a CSP parameter. 03651 * 03652 * PARAMS 03653 * hProv [I] The key container that is to be queried. 03654 * dwParam [I] Specifies the parameter that is to be queried. 03655 * pbData [I] Pointer to the buffer where the parameter value will be stored. 03656 * pdwDataLen [I/O] I: Buffer length at pbData, O: Length of the parameter value. 03657 * dwFlags [I] CRYPT_FIRST: Start enumeration (for PP_ENUMALGS{_EX}). 03658 * 03659 * RETURNS 03660 * Success: TRUE 03661 * Failure: FALSE 03662 * NOTES: 03663 * Defined dwParam types: 03664 * - PP_CONTAINER: Name of the key container. 03665 * - PP_NAME: Name of the cryptographic service provider. 03666 * - PP_SIG_KEYSIZE_INC: RSA signature keywidth granularity in bits. 03667 * - PP_KEYX_KEYSIZE_INC: RSA key-exchange keywidth granularity in bits. 03668 * - PP_ENUMALGS{_EX}: Query provider capabilities. 03669 */ 03670 BOOL WINAPI RSAENH_CPGetProvParam(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, 03671 DWORD *pdwDataLen, DWORD dwFlags) 03672 { 03673 KEYCONTAINER *pKeyContainer; 03674 PROV_ENUMALGS provEnumalgs; 03675 DWORD dwTemp; 03676 HKEY hKey; 03677 03678 /* This is for dwParam PP_CRYPT_COUNT_KEY_USE. 03679 * IE6 SP1 asks for it in the 'About' dialog. 03680 * Returning this BLOB seems to satisfy IE. The marked 0x00 seem 03681 * to be 'don't care's. If you know anything more specific about 03682 * this provider parameter, please report to wine-devel@winehq.org */ 03683 static CONST BYTE abWTF[96] = { 03684 0xb0, 0x25, 0x63, 0x86, 0x9c, 0xab, 0xb6, 0x37, 03685 0xe8, 0x82, 0x00, 0x72, 0x06, 0xb2, 0x00, 0x3b, 03686 0x60, 0x35, 0x00, 0x3b, 0x88, 0xce, 0x00, 0x82, 03687 0xbc, 0x7a, 0x00, 0xb7, 0x4f, 0x7e, 0x00, 0xde, 03688 0x92, 0xf1, 0x00, 0x83, 0xea, 0x5e, 0x00, 0xc8, 03689 0x12, 0x1e, 0xd4, 0x06, 0xf7, 0x66, 0x00, 0x01, 03690 0x29, 0xa4, 0x00, 0xf8, 0x24, 0x0c, 0x00, 0x33, 03691 0x06, 0x80, 0x00, 0x02, 0x46, 0x0b, 0x00, 0x6d, 03692 0x5b, 0xca, 0x00, 0x9a, 0x10, 0xf0, 0x00, 0x05, 03693 0x19, 0xd0, 0x00, 0x2c, 0xf6, 0x27, 0x00, 0xaa, 03694 0x7c, 0x6f, 0x00, 0xb9, 0xd8, 0x72, 0x00, 0x03, 03695 0xf3, 0x81, 0x00, 0xfa, 0xe8, 0x26, 0x00, 0xca 03696 }; 03697 03698 TRACE("(hProv=%08lx, dwParam=%08x, pbData=%p, pdwDataLen=%p, dwFlags=%08x)\n", 03699 hProv, dwParam, pbData, pdwDataLen, dwFlags); 03700 03701 if (!pdwDataLen) { 03702 SetLastError(ERROR_INVALID_PARAMETER); 03703 return FALSE; 03704 } 03705 03706 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER, 03707 (OBJECTHDR**)&pKeyContainer)) 03708 { 03709 /* MSDN: hProv not containing valid context handle */ 03710 SetLastError(NTE_BAD_UID); 03711 return FALSE; 03712 } 03713 03714 switch (dwParam) 03715 { 03716 case PP_CONTAINER: 03717 case PP_UNIQUE_CONTAINER:/* MSDN says we can return the same value as PP_CONTAINER */ 03718 return copy_param(pbData, pdwDataLen, (CONST BYTE*)pKeyContainer->szName, 03719 strlen(pKeyContainer->szName)+1); 03720 03721 case PP_NAME: 03722 return copy_param(pbData, pdwDataLen, (CONST BYTE*)pKeyContainer->szProvName, 03723 strlen(pKeyContainer->szProvName)+1); 03724 03725 case PP_PROVTYPE: 03726 dwTemp = PROV_RSA_FULL; 03727 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp)); 03728 03729 case PP_KEYSPEC: 03730 dwTemp = AT_SIGNATURE | AT_KEYEXCHANGE; 03731 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp)); 03732 03733 case PP_KEYSET_TYPE: 03734 dwTemp = pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET; 03735 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp)); 03736 03737 case PP_KEYSTORAGE: 03738 dwTemp = CRYPT_SEC_DESCR; 03739 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp)); 03740 03741 case PP_SIG_KEYSIZE_INC: 03742 case PP_KEYX_KEYSIZE_INC: 03743 dwTemp = 8; 03744 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp)); 03745 03746 case PP_IMPTYPE: 03747 dwTemp = CRYPT_IMPL_SOFTWARE; 03748 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp)); 03749 03750 case PP_VERSION: 03751 dwTemp = 0x00000200; 03752 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwTemp, sizeof(dwTemp)); 03753 03754 case PP_ENUMCONTAINERS: 03755 if ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) pKeyContainer->dwEnumContainersCtr = 0; 03756 03757 if (!pbData) { 03758 *pdwDataLen = (DWORD)MAX_PATH + 1; 03759 return TRUE; 03760 } 03761 03762 if (!open_container_key("", dwFlags, &hKey)) 03763 { 03764 SetLastError(ERROR_NO_MORE_ITEMS); 03765 return FALSE; 03766 } 03767 03768 dwTemp = *pdwDataLen; 03769 switch (RegEnumKeyExA(hKey, pKeyContainer->dwEnumContainersCtr, (LPSTR)pbData, &dwTemp, 03770 NULL, NULL, NULL, NULL)) 03771 { 03772 case ERROR_MORE_DATA: 03773 *pdwDataLen = (DWORD)MAX_PATH + 1; 03774 03775 case ERROR_SUCCESS: 03776 pKeyContainer->dwEnumContainersCtr++; 03777 RegCloseKey(hKey); 03778 return TRUE; 03779 03780 case ERROR_NO_MORE_ITEMS: 03781 default: 03782 SetLastError(ERROR_NO_MORE_ITEMS); 03783 RegCloseKey(hKey); 03784 return FALSE; 03785 } 03786 03787 case PP_ENUMALGS: 03788 case PP_ENUMALGS_EX: 03789 if (((pKeyContainer->dwEnumAlgsCtr >= RSAENH_MAX_ENUMALGS-1) || 03790 (!aProvEnumAlgsEx[pKeyContainer->dwPersonality] 03791 [pKeyContainer->dwEnumAlgsCtr+1].aiAlgid)) && 03792 ((dwFlags & CRYPT_FIRST) != CRYPT_FIRST)) 03793 { 03794 SetLastError(ERROR_NO_MORE_ITEMS); 03795 return FALSE; 03796 } 03797 03798 if (dwParam == PP_ENUMALGS) { 03799 if (pbData && (*pdwDataLen >= sizeof(PROV_ENUMALGS))) 03800 pKeyContainer->dwEnumAlgsCtr = ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) ? 03801 0 : pKeyContainer->dwEnumAlgsCtr+1; 03802 03803 provEnumalgs.aiAlgid = aProvEnumAlgsEx 03804 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].aiAlgid; 03805 provEnumalgs.dwBitLen = aProvEnumAlgsEx 03806 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].dwDefaultLen; 03807 provEnumalgs.dwNameLen = aProvEnumAlgsEx 03808 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].dwNameLen; 03809 memcpy(provEnumalgs.szName, aProvEnumAlgsEx 03810 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr].szName, 03811 20*sizeof(CHAR)); 03812 03813 return copy_param(pbData, pdwDataLen, (CONST BYTE*)&provEnumalgs, 03814 sizeof(PROV_ENUMALGS)); 03815 } else { 03816 if (pbData && (*pdwDataLen >= sizeof(PROV_ENUMALGS_EX))) 03817 pKeyContainer->dwEnumAlgsCtr = ((dwFlags & CRYPT_FIRST) == CRYPT_FIRST) ? 03818 0 : pKeyContainer->dwEnumAlgsCtr+1; 03819 03820 return copy_param(pbData, pdwDataLen, 03821 (CONST BYTE*)&aProvEnumAlgsEx 03822 [pKeyContainer->dwPersonality][pKeyContainer->dwEnumAlgsCtr], 03823 sizeof(PROV_ENUMALGS_EX)); 03824 } 03825 03826 case PP_CRYPT_COUNT_KEY_USE: /* Asked for by IE About dialog */ 03827 return copy_param(pbData, pdwDataLen, abWTF, sizeof(abWTF)); 03828 03829 default: 03830 /* MSDN: Unknown parameter number in dwParam */ 03831 SetLastError(NTE_BAD_TYPE); 03832 return FALSE; 03833 } 03834 } 03835 03836 /****************************************************************************** 03837 * CPDeriveKey (RSAENH.@) 03838 * 03839 * Derives a key from a hash value. 03840 * 03841 * PARAMS 03842 * hProv [I] Key container for which a key is to be generated. 03843 * Algid [I] Crypto algorithm identifier for the key to be generated. 03844 * hBaseData [I] Hash from whose value the key will be derived. 03845 * dwFlags [I] See Notes. 03846 * phKey [O] The generated key. 03847 * 03848 * RETURNS 03849 * Success: TRUE 03850 * Failure: FALSE 03851 * 03852 * NOTES 03853 * Defined flags: 03854 * - CRYPT_EXPORTABLE: Key can be exported. 03855 * - CRYPT_NO_SALT: No salt is used for 40 bit keys. 03856 * - CRYPT_CREATE_SALT: Use remaining bits as salt value. 03857 */ 03858 BOOL WINAPI RSAENH_CPDeriveKey(HCRYPTPROV hProv, ALG_ID Algid, HCRYPTHASH hBaseData, 03859 DWORD dwFlags, HCRYPTKEY *phKey) 03860 { 03861 CRYPTKEY *pCryptKey, *pMasterKey; 03862 CRYPTHASH *pCryptHash; 03863 BYTE abHashValue[RSAENH_MAX_HASH_SIZE*2]; 03864 DWORD dwLen; 03865 03866 TRACE("(hProv=%08lx, Algid=%d, hBaseData=%08lx, dwFlags=%08x phKey=%p)\n", hProv, Algid, 03867 hBaseData, dwFlags, phKey); 03868 03869 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER)) 03870 { 03871 SetLastError(NTE_BAD_UID); 03872 return FALSE; 03873 } 03874 03875 if (!lookup_handle(&handle_table, hBaseData, RSAENH_MAGIC_HASH, 03876 (OBJECTHDR**)&pCryptHash)) 03877 { 03878 SetLastError(NTE_BAD_HASH); 03879 return FALSE; 03880 } 03881 03882 if (!phKey) 03883 { 03884 SetLastError(ERROR_INVALID_PARAMETER); 03885 return FALSE; 03886 } 03887 03888 switch (GET_ALG_CLASS(Algid)) 03889 { 03890 case ALG_CLASS_DATA_ENCRYPT: 03891 *phKey = new_key(hProv, Algid, dwFlags, &pCryptKey); 03892 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE; 03893 03894 /* 03895 * We derive the key material from the hash. 03896 * If the hash value is not large enough for the claimed key, we have to construct 03897 * a larger binary value based on the hash. This is documented in MSDN: CryptDeriveKey. 03898 */ 03899 dwLen = RSAENH_MAX_HASH_SIZE; 03900 RSAENH_CPGetHashParam(pCryptHash->hProv, hBaseData, HP_HASHVAL, abHashValue, &dwLen, 0); 03901 03902 if (dwLen < pCryptKey->dwKeyLen) { 03903 BYTE pad1[RSAENH_HMAC_DEF_PAD_LEN], pad2[RSAENH_HMAC_DEF_PAD_LEN]; 03904 BYTE old_hashval[RSAENH_MAX_HASH_SIZE]; 03905 DWORD i; 03906 03907 memcpy(old_hashval, pCryptHash->abHashValue, RSAENH_MAX_HASH_SIZE); 03908 03909 for (i=0; i<RSAENH_HMAC_DEF_PAD_LEN; i++) { 03910 pad1[i] = RSAENH_HMAC_DEF_IPAD_CHAR ^ (i<dwLen ? abHashValue[i] : 0); 03911 pad2[i] = RSAENH_HMAC_DEF_OPAD_CHAR ^ (i<dwLen ? abHashValue[i] : 0); 03912 } 03913 03914 init_hash(pCryptHash); 03915 update_hash(pCryptHash, pad1, RSAENH_HMAC_DEF_PAD_LEN); 03916 finalize_hash(pCryptHash); 03917 memcpy(abHashValue, pCryptHash->abHashValue, pCryptHash->dwHashSize); 03918 03919 init_hash(pCryptHash); 03920 update_hash(pCryptHash, pad2, RSAENH_HMAC_DEF_PAD_LEN); 03921 finalize_hash(pCryptHash); 03922 memcpy(abHashValue+pCryptHash->dwHashSize, pCryptHash->abHashValue, 03923 pCryptHash->dwHashSize); 03924 03925 memcpy(pCryptHash->abHashValue, old_hashval, RSAENH_MAX_HASH_SIZE); 03926 } 03927 03928 memcpy(pCryptKey->abKeyValue, abHashValue, 03929 RSAENH_MIN(pCryptKey->dwKeyLen, sizeof(pCryptKey->abKeyValue))); 03930 break; 03931 03932 case ALG_CLASS_MSG_ENCRYPT: 03933 if (!lookup_handle(&handle_table, pCryptHash->hKey, RSAENH_MAGIC_KEY, 03934 (OBJECTHDR**)&pMasterKey)) 03935 { 03936 SetLastError(NTE_FAIL); /* FIXME error code */ 03937 return FALSE; 03938 } 03939 03940 switch (Algid) 03941 { 03942 /* See RFC 2246, chapter 6.3 Key calculation */ 03943 case CALG_SCHANNEL_ENC_KEY: 03944 if (!pMasterKey->siSChannelInfo.saEncAlg.Algid || 03945 !pMasterKey->siSChannelInfo.saEncAlg.cBits) 03946 { 03947 SetLastError(NTE_BAD_FLAGS); 03948 return FALSE; 03949 } 03950 *phKey = new_key(hProv, pMasterKey->siSChannelInfo.saEncAlg.Algid, 03951 MAKELONG(LOWORD(dwFlags),pMasterKey->siSChannelInfo.saEncAlg.cBits), 03952 &pCryptKey); 03953 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE; 03954 memcpy(pCryptKey->abKeyValue, 03955 pCryptHash->abHashValue + ( 03956 2 * (pMasterKey->siSChannelInfo.saMACAlg.cBits / 8) + 03957 ((dwFlags & CRYPT_SERVER) ? 03958 (pMasterKey->siSChannelInfo.saEncAlg.cBits / 8) : 0)), 03959 pMasterKey->siSChannelInfo.saEncAlg.cBits / 8); 03960 memcpy(pCryptKey->abInitVector, 03961 pCryptHash->abHashValue + ( 03962 2 * (pMasterKey->siSChannelInfo.saMACAlg.cBits / 8) + 03963 2 * (pMasterKey->siSChannelInfo.saEncAlg.cBits / 8) + 03964 ((dwFlags & CRYPT_SERVER) ? pCryptKey->dwBlockLen : 0)), 03965 pCryptKey->dwBlockLen); 03966 break; 03967 03968 case CALG_SCHANNEL_MAC_KEY: 03969 *phKey = new_key(hProv, Algid, 03970 MAKELONG(LOWORD(dwFlags),pMasterKey->siSChannelInfo.saMACAlg.cBits), 03971 &pCryptKey); 03972 if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE; 03973 memcpy(pCryptKey->abKeyValue, 03974 pCryptHash->abHashValue + ((dwFlags & CRYPT_SERVER) ? 03975 pMasterKey->siSChannelInfo.saMACAlg.cBits / 8 : 0), 03976 pMasterKey->siSChannelInfo.saMACAlg.cBits / 8); 03977 break; 03978 03979 default: 03980 SetLastError(NTE_BAD_ALGID); 03981 return FALSE; 03982 } 03983 break; 03984 03985 default: 03986 SetLastError(NTE_BAD_ALGID); 03987 return FALSE; 03988 } 03989 03990 setup_key(pCryptKey); 03991 return TRUE; 03992 } 03993 03994 /****************************************************************************** 03995 * CPGetUserKey (RSAENH.@) 03996 * 03997 * Returns a handle to the user's private key-exchange- or signature-key. 03998 * 03999 * PARAMS 04000 * hProv [I] The key container from which a user key is requested. 04001 * dwKeySpec [I] AT_KEYEXCHANGE or AT_SIGNATURE 04002 * phUserKey [O] Handle to the requested key or INVALID_HANDLE_VALUE in case of failure. 04003 * 04004 * RETURNS 04005 * Success: TRUE. 04006 * Failure: FALSE. 04007 * 04008 * NOTE 04009 * A newly created key container does not contain private user key. Create them with CPGenKey. 04010 */ 04011 BOOL WINAPI RSAENH_CPGetUserKey(HCRYPTPROV hProv, DWORD dwKeySpec, HCRYPTKEY *phUserKey) 04012 { 04013 KEYCONTAINER *pKeyContainer; 04014 04015 TRACE("(hProv=%08lx, dwKeySpec=%08x, phUserKey=%p)\n", hProv, dwKeySpec, phUserKey); 04016 04017 if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER, 04018 (OBJECTHDR**)&pKeyContainer)) 04019 { 04020 /* MSDN: hProv not containing valid context handle */ 04021 SetLastError(NTE_BAD_UID); 04022 return FALSE; 04023 } 04024 04025 switch (dwKeySpec) 04026 { 04027 case AT_KEYEXCHANGE: 04028 copy_handle(&handle_table, pKeyContainer->hKeyExchangeKeyPair, RSAENH_MAGIC_KEY, 04029 phUserKey); 04030 break; 04031 04032 case AT_SIGNATURE: 04033 copy_handle(&handle_table, pKeyContainer->hSignatureKeyPair, RSAENH_MAGIC_KEY, 04034 phUserKey); 04035 break; 04036 04037 default: 04038 *phUserKey = (HCRYPTKEY)INVALID_HANDLE_VALUE; 04039 } 04040 04041 if (*phUserKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) 04042 { 04043 /* MSDN: dwKeySpec parameter specifies nonexistent key */ 04044 SetLastError(NTE_NO_KEY); 04045 return FALSE; 04046 } 04047 04048 return TRUE; 04049 } 04050 04051 /****************************************************************************** 04052 * CPHashData (RSAENH.@) 04053 * 04054 * Updates a hash object with the given data. 04055 * 04056 * PARAMS 04057 * hProv [I] Key container to which the hash object belongs. 04058 * hHash [I] Hash object which is to be updated. 04059 * pbData [I] Pointer to data with which the hash object is to be updated. 04060 * dwDataLen [I] Length of the data. 04061 * dwFlags [I] Currently none defined. 04062 * 04063 * RETURNS 04064 * Success: TRUE. 04065 * Failure: FALSE. 04066 * 04067 * NOTES 04068 * The actual hash value is queried with CPGetHashParam, which will finalize 04069 * the hash. Updating a finalized hash will fail with a last error NTE_BAD_HASH_STATE. 04070 */ 04071 BOOL WINAPI RSAENH_CPHashData(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST BYTE *pbData, 04072 DWORD dwDataLen, DWORD dwFlags) 04073 { 04074 CRYPTHASH *pCryptHash; 04075 04076 TRACE("(hProv=%08lx, hHash=%08lx, pbData=%p, dwDataLen=%d, dwFlags=%08x)\n", 04077 hProv, hHash, pbData, dwDataLen, dwFlags); 04078 04079 if (dwFlags) 04080 { 04081 SetLastError(NTE_BAD_FLAGS); 04082 return FALSE; 04083 } 04084 04085 if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH, 04086 (OBJECTHDR**)&pCryptHash)) 04087 { 04088 SetLastError(NTE_BAD_HASH); 04089 return FALSE; 04090 } 04091 04092 if (!get_algid_info(hProv, pCryptHash->aiAlgid) || pCryptHash->aiAlgid == CALG_SSL3_SHAMD5) 04093 { 04094 SetLastError(NTE_BAD_ALGID); 04095 return FALSE; 04096 } 04097 04098 if (pCryptHash->dwState != RSAENH_HASHSTATE_HASHING) 04099 { 04100 SetLastError(NTE_BAD_HASH_STATE); 04101 return FALSE; 04102 } 04103 04104 update_hash(pCryptHash, pbData, dwDataLen); 04105 return TRUE; 04106 } 04107 04108 /****************************************************************************** 04109 * CPHashSessionKey (RSAENH.@) 04110 * 04111 * Updates a hash object with the binary representation of a symmetric key. 04112 * 04113 * PARAMS 04114 * hProv [I] Key container to which the hash object belongs. 04115 * hHash [I] Hash object which is to be updated. 04116 * hKey [I] The symmetric key, whose binary value will be added to the hash. 04117 * dwFlags [I] CRYPT_LITTLE_ENDIAN, if the binary key value shall be interpreted as little endian. 04118 * 04119 * RETURNS 04120 * Success: TRUE. 04121 * Failure: FALSE. 04122 */ 04123 BOOL WINAPI RSAENH_CPHashSessionKey(HCRYPTPROV hProv, HCRYPTHASH hHash, HCRYPTKEY hKey, 04124 DWORD dwFlags) 04125 { 04126 BYTE abKeyValue[RSAENH_MAX_KEY_SIZE], bTemp; 04127 CRYPTKEY *pKey; 04128 DWORD i; 04129 04130 TRACE("(hProv=%08lx, hHash=%08lx, hKey=%08lx, dwFlags=%08x)\n", hProv, hHash, hKey, dwFlags); 04131 04132 if (!lookup_handle(&handle_table, hKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pKey) || 04133 (GET_ALG_CLASS(pKey->aiAlgid) != ALG_CLASS_DATA_ENCRYPT)) 04134 { 04135 SetLastError(NTE_BAD_KEY); 04136 return FALSE; 04137 } 04138 04139 if (dwFlags & ~CRYPT_LITTLE_ENDIAN) { 04140 SetLastError(NTE_BAD_FLAGS); 04141 return FALSE; 04142 } 04143 04144 memcpy(abKeyValue, pKey->abKeyValue, pKey->dwKeyLen); 04145 if (!(dwFlags & CRYPT_LITTLE_ENDIAN)) { 04146 for (i=0; i<pKey->dwKeyLen/2; i++) { 04147 bTemp = abKeyValue[i]; 04148 abKeyValue[i] = abKeyValue[pKey->dwKeyLen-i-1]; 04149 abKeyValue[pKey->dwKeyLen-i-1] = bTemp; 04150 } 04151 } 04152 04153 return RSAENH_CPHashData(hProv, hHash, abKeyValue, pKey->dwKeyLen, 0); 04154 } 04155 04156 /****************************************************************************** 04157 * CPReleaseContext (RSAENH.@) 04158 * 04159 * Release a key container. 04160 * 04161 * PARAMS 04162 * hProv [I] Key container to be released. 04163 * dwFlags [I] Currently none defined. 04164 * 04165 * RETURNS 04166 * Success: TRUE 04167 * Failure: FALSE 04168 */ 04169 BOOL WINAPI RSAENH_CPReleaseContext(HCRYPTPROV hProv, DWORD dwFlags) 04170 { 04171 TRACE("(hProv=%08lx, dwFlags=%08x)\n", hProv, dwFlags); 04172 04173 if (!release_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER)) 04174 { 04175 /* MSDN: hProv not containing valid context handle */ 04176 SetLastError(NTE_BAD_UID); 04177 return FALSE; 04178 } 04179 04180 if (dwFlags) { 04181 SetLastError(NTE_BAD_FLAGS); 04182 return FALSE; 04183 } 04184 04185 return TRUE; 04186 } 04187 04188 /****************************************************************************** 04189 * CPSetHashParam (RSAENH.@) 04190 * 04191 * Set a parameter of a hash object 04192 * 04193 * PARAMS 04194 * hProv [I] The key container to which the key belongs. 04195 * hHash [I] The hash object for which a parameter is to be set. 04196 * dwParam [I] Parameter type. See Notes. 04197 * pbData [I] Pointer to the parameter value. 04198 * dwFlags [I] Currently none defined. 04199 * 04200 * RETURNS 04201 * Success: TRUE. 04202 * Failure: FALSE. 04203 * 04204 * NOTES 04205 * Currently only the HP_HMAC_INFO dwParam type is defined. 04206 * The HMAC_INFO struct will be deep copied into the hash object. 04207 * See Internet RFC 2104 for details on the HMAC algorithm. 04208 */ 04209 BOOL WINAPI RSAENH_CPSetHashParam(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwParam, 04210 BYTE *pbData, DWORD dwFlags) 04211 { 04212 CRYPTHASH *pCryptHash; 04213 CRYPTKEY *pCryptKey; 04214 DWORD i; 04215 04216 TRACE("(hProv=%08lx, hHash=%08lx, dwParam=%08x, pbData=%p, dwFlags=%08x)\n", 04217 hProv, hHash, dwParam, pbData, dwFlags); 04218 04219 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER)) 04220 { 04221 SetLastError(NTE_BAD_UID); 04222 return FALSE; 04223 } 04224 04225 if (dwFlags) { 04226 SetLastError(NTE_BAD_FLAGS); 04227 return FALSE; 04228 } 04229 04230 if (!lookup_handle(&handle_table, hHash, RSAENH_MAGIC_HASH, 04231 (OBJECTHDR**)&pCryptHash)) 04232 { 04233 SetLastError(NTE_BAD_HASH); 04234 return FALSE; 04235 } 04236 04237 switch (dwParam) { 04238 case HP_HMAC_INFO: 04239 free_hmac_info(pCryptHash->pHMACInfo); 04240 if (!copy_hmac_info(&pCryptHash->pHMACInfo, (PHMAC_INFO)pbData)) return FALSE; 04241 04242 if (!lookup_handle(&handle_table, pCryptHash->hKey, RSAENH_MAGIC_KEY, 04243 (OBJECTHDR**)&pCryptKey)) 04244 { 04245 SetLastError(NTE_FAIL); /* FIXME: correct error code? */ 04246 return FALSE; 04247 } 04248 04249 if (pCryptKey->aiAlgid == CALG_HMAC && !pCryptKey->dwKeyLen) { 04250 HCRYPTHASH hKeyHash; 04251 DWORD keyLen; 04252 04253 if (!RSAENH_CPCreateHash(hProv, ((PHMAC_INFO)pbData)->HashAlgid, 0, 0, 04254 &hKeyHash)) 04255 return FALSE; 04256 if (!RSAENH_CPHashData(hProv, hKeyHash, pCryptKey->blobHmacKey.pbData, 04257 pCryptKey->blobHmacKey.cbData, 0)) 04258 { 04259 RSAENH_CPDestroyHash(hProv, hKeyHash); 04260 return FALSE; 04261 } 04262 keyLen = sizeof(pCryptKey->abKeyValue); 04263 if (!RSAENH_CPGetHashParam(hProv, hKeyHash, HP_HASHVAL, pCryptKey->abKeyValue, 04264 &keyLen, 0)) 04265 { 04266 RSAENH_CPDestroyHash(hProv, hKeyHash); 04267 return FALSE; 04268 } 04269 pCryptKey->dwKeyLen = keyLen; 04270 RSAENH_CPDestroyHash(hProv, hKeyHash); 04271 } 04272 for (i=0; i<RSAENH_MIN(pCryptKey->dwKeyLen,pCryptHash->pHMACInfo->cbInnerString); i++) { 04273 pCryptHash->pHMACInfo->pbInnerString[i] ^= pCryptKey->abKeyValue[i]; 04274 } 04275 for (i=0; i<RSAENH_MIN(pCryptKey->dwKeyLen,pCryptHash->pHMACInfo->cbOuterString); i++) { 04276 pCryptHash->pHMACInfo->pbOuterString[i] ^= pCryptKey->abKeyValue[i]; 04277 } 04278 04279 init_hash(pCryptHash); 04280 return TRUE; 04281 04282 case HP_HASHVAL: 04283 memcpy(pCryptHash->abHashValue, pbData, pCryptHash->dwHashSize); 04284 pCryptHash->dwState = RSAENH_HASHSTATE_FINISHED; 04285 return TRUE; 04286 04287 case HP_TLS1PRF_SEED: 04288 return copy_data_blob(&pCryptHash->tpPRFParams.blobSeed, (PCRYPT_DATA_BLOB)pbData); 04289 04290 case HP_TLS1PRF_LABEL: 04291 return copy_data_blob(&pCryptHash->tpPRFParams.blobLabel, (PCRYPT_DATA_BLOB)pbData); 04292 04293 default: 04294 SetLastError(NTE_BAD_TYPE); 04295 return FALSE; 04296 } 04297 } 04298 04299 /****************************************************************************** 04300 * CPSetProvParam (RSAENH.@) 04301 */ 04302 BOOL WINAPI RSAENH_CPSetProvParam(HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags) 04303 { 04304 FIXME("(stub)\n"); 04305 return FALSE; 04306 } 04307 04308 /****************************************************************************** 04309 * CPSignHash (RSAENH.@) 04310 * 04311 * Sign a hash object 04312 * 04313 * PARAMS 04314 * hProv [I] The key container, to which the hash object belongs. 04315 * hHash [I] The hash object to be signed. 04316 * dwKeySpec [I] AT_SIGNATURE or AT_KEYEXCHANGE: Key used to generate the signature. 04317 * sDescription [I] Should be NULL for security reasons. 04318 * dwFlags [I] 0, CRYPT_NOHASHOID or CRYPT_X931_FORMAT: Format of the signature. 04319 * pbSignature [O] Buffer, to which the signature will be stored. May be NULL to query SigLen. 04320 * pdwSigLen [I/O] Size of the buffer (in), Length of the signature (out) 04321 * 04322 * RETURNS 04323 * Success: TRUE 04324 * Failure: FALSE 04325 */ 04326 BOOL WINAPI RSAENH_CPSignHash(HCRYPTPROV hProv, HCRYPTHASH hHash, DWORD dwKeySpec, 04327 LPCWSTR sDescription, DWORD dwFlags, BYTE *pbSignature, 04328 DWORD *pdwSigLen) 04329 { 04330 HCRYPTKEY hCryptKey = (HCRYPTKEY)INVALID_HANDLE_VALUE; 04331 CRYPTKEY *pCryptKey; 04332 DWORD dwHashLen; 04333 BYTE abHashValue[RSAENH_MAX_HASH_SIZE]; 04334 ALG_ID aiAlgid; 04335 BOOL ret = FALSE; 04336 04337 TRACE("(hProv=%08lx, hHash=%08lx, dwKeySpec=%08x, sDescription=%s, dwFlags=%08x, " 04338 "pbSignature=%p, pdwSigLen=%p)\n", hProv, hHash, dwKeySpec, debugstr_w(sDescription), 04339 dwFlags, pbSignature, pdwSigLen); 04340 04341 if (dwFlags & ~(CRYPT_NOHASHOID|CRYPT_X931_FORMAT)) { 04342 SetLastError(NTE_BAD_FLAGS); 04343 return FALSE; 04344 } 04345 04346 if (!RSAENH_CPGetUserKey(hProv, dwKeySpec, &hCryptKey)) return FALSE; 04347 04348 if (!lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY, 04349 (OBJECTHDR**)&pCryptKey)) 04350 { 04351 SetLastError(NTE_NO_KEY); 04352 goto out; 04353 } 04354 04355 if (!pbSignature) { 04356 *pdwSigLen = pCryptKey->dwKeyLen; 04357 ret = TRUE; 04358 goto out; 04359 } 04360 if (pCryptKey->dwKeyLen > *pdwSigLen) 04361 { 04362 SetLastError(ERROR_MORE_DATA); 04363 *pdwSigLen = pCryptKey->dwKeyLen; 04364 goto out; 04365 } 04366 *pdwSigLen = pCryptKey->dwKeyLen; 04367 04368 if (sDescription) { 04369 if (!RSAENH_CPHashData(hProv, hHash, (CONST BYTE*)sDescription, 04370 (DWORD)lstrlenW(sDescription)*sizeof(WCHAR), 0)) 04371 { 04372 goto out; 04373 } 04374 } 04375 04376 dwHashLen = sizeof(DWORD); 04377 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_ALGID, (BYTE*)&aiAlgid, &dwHashLen, 0)) goto out; 04378 04379 dwHashLen = RSAENH_MAX_HASH_SIZE; 04380 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_HASHVAL, abHashValue, &dwHashLen, 0)) goto out; 04381 04382 04383 if (!build_hash_signature(pbSignature, *pdwSigLen, aiAlgid, abHashValue, dwHashLen, dwFlags)) { 04384 goto out; 04385 } 04386 04387 ret = encrypt_block_impl(pCryptKey->aiAlgid, PK_PRIVATE, &pCryptKey->context, pbSignature, pbSignature, RSAENH_ENCRYPT); 04388 out: 04389 RSAENH_CPDestroyKey(hProv, hCryptKey); 04390 return ret; 04391 } 04392 04393 /****************************************************************************** 04394 * CPVerifySignature (RSAENH.@) 04395 * 04396 * Verify the signature of a hash object. 04397 * 04398 * PARAMS 04399 * hProv [I] The key container, to which the hash belongs. 04400 * hHash [I] The hash for which the signature is verified. 04401 * pbSignature [I] The binary signature. 04402 * dwSigLen [I] Length of the signature BLOB. 04403 * hPubKey [I] Public key used to verify the signature. 04404 * sDescription [I] Should be NULL for security reasons. 04405 * dwFlags [I] 0, CRYPT_NOHASHOID or CRYPT_X931_FORMAT: Format of the signature. 04406 * 04407 * RETURNS 04408 * Success: TRUE (Signature is valid) 04409 * Failure: FALSE (GetLastError() == NTE_BAD_SIGNATURE, if signature is invalid) 04410 */ 04411 BOOL WINAPI RSAENH_CPVerifySignature(HCRYPTPROV hProv, HCRYPTHASH hHash, CONST BYTE *pbSignature, 04412 DWORD dwSigLen, HCRYPTKEY hPubKey, LPCWSTR sDescription, 04413 DWORD dwFlags) 04414 { 04415 BYTE *pbConstructed = NULL, *pbDecrypted = NULL; 04416 CRYPTKEY *pCryptKey; 04417 DWORD dwHashLen; 04418 ALG_ID aiAlgid; 04419 BYTE abHashValue[RSAENH_MAX_HASH_SIZE]; 04420 BOOL res = FALSE; 04421 04422 TRACE("(hProv=%08lx, hHash=%08lx, pbSignature=%p, dwSigLen=%d, hPubKey=%08lx, sDescription=%s, " 04423 "dwFlags=%08x)\n", hProv, hHash, pbSignature, dwSigLen, hPubKey, debugstr_w(sDescription), 04424 dwFlags); 04425 04426 if (dwFlags & ~(CRYPT_NOHASHOID|CRYPT_X931_FORMAT)) { 04427 SetLastError(NTE_BAD_FLAGS); 04428 return FALSE; 04429 } 04430 04431 if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER)) 04432 { 04433 SetLastError(NTE_BAD_UID); 04434 return FALSE; 04435 } 04436 04437 if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, 04438 (OBJECTHDR**)&pCryptKey)) 04439 { 04440 SetLastError(NTE_BAD_KEY); 04441 return FALSE; 04442 } 04443 04444 /* in Microsoft implementation, the signature length is checked before 04445 * the signature pointer. 04446 */ 04447 if (dwSigLen != pCryptKey->dwKeyLen) 04448 { 04449 SetLastError(NTE_BAD_SIGNATURE); 04450 return FALSE; 04451 } 04452 04453 if (!hHash || !pbSignature) 04454 { 04455 SetLastError(ERROR_INVALID_PARAMETER); 04456 return FALSE; 04457 } 04458 04459 if (sDescription) { 04460 if (!RSAENH_CPHashData(hProv, hHash, (CONST BYTE*)sDescription, 04461 (DWORD)lstrlenW(sDescription)*sizeof(WCHAR), 0)) 04462 { 04463 return FALSE; 04464 } 04465 } 04466 04467 dwHashLen = sizeof(DWORD); 04468 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_ALGID, (BYTE*)&aiAlgid, &dwHashLen, 0)) return FALSE; 04469 04470 dwHashLen = RSAENH_MAX_HASH_SIZE; 04471 if (!RSAENH_CPGetHashParam(hProv, hHash, HP_HASHVAL, abHashValue, &dwHashLen, 0)) return FALSE; 04472 04473 pbConstructed = HeapAlloc(GetProcessHeap(), 0, dwSigLen); 04474 if (!pbConstructed) { 04475 SetLastError(NTE_NO_MEMORY); 04476 goto cleanup; 04477 } 04478 04479 pbDecrypted = HeapAlloc(GetProcessHeap(), 0, dwSigLen); 04480 if (!pbDecrypted) { 04481 SetLastError(NTE_NO_MEMORY); 04482 goto cleanup; 04483 } 04484 04485 if (!encrypt_block_impl(pCryptKey->aiAlgid, PK_PUBLIC, &pCryptKey->context, pbSignature, pbDecrypted, 04486 RSAENH_DECRYPT)) 04487 { 04488 goto cleanup; 04489 } 04490 04491 if (build_hash_signature(pbConstructed, dwSigLen, aiAlgid, abHashValue, dwHashLen, dwFlags) && 04492 !memcmp(pbDecrypted, pbConstructed, dwSigLen)) { 04493 res = TRUE; 04494 goto cleanup; 04495 } 04496 04497 if (!(dwFlags & CRYPT_NOHASHOID) && 04498 build_hash_signature(pbConstructed, dwSigLen, aiAlgid, abHashValue, dwHashLen, dwFlags|CRYPT_NOHASHOID) && 04499 !memcmp(pbDecrypted, pbConstructed, dwSigLen)) { 04500 res = TRUE; 04501 goto cleanup; 04502 } 04503 04504 SetLastError(NTE_BAD_SIGNATURE); 04505 04506 cleanup: 04507 HeapFree(GetProcessHeap(), 0, pbConstructed); 04508 HeapFree(GetProcessHeap(), 0, pbDecrypted); 04509 return res; 04510 } 04511 04512 /****************************************************************************** 04513 * DllRegisterServer (RSAENH.@) 04514 */ 04515 HRESULT WINAPI DllRegisterServer(void) 04516 { 04517 return __wine_register_resources( instance ); 04518 } 04519 04520 /****************************************************************************** 04521 * DllUnregisterServer (RSAENH.@) 04522 */ 04523 HRESULT WINAPI DllUnregisterServer(void) 04524 { 04525 return __wine_unregister_resources( instance ); 04526 } Generated on Sat May 26 2012 04:24:46 for ReactOS by
1.7.6.1
|