ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

rsaenh.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.