rsaenh.c 168 KB
Newer Older
1 2 3 4
/*
 * Unit tests for rsaenh functions
 *
 * Copyright (c) 2004 Michael Jung
5 6
 * Copyright (c) 2006 Juan Lang
 * Copyright (c) 2007 Vijay Kiran Kamuju
7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 22 23 24 25 26 27 28 29
 */

#include <string.h>
#include <stdio.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wincrypt.h"
30
#include "winreg.h"
31 32

static HCRYPTPROV hProv;
33 34
static const char *szProviders[] = {MS_ENHANCED_PROV_A, MS_DEF_PROV_A, MS_STRONG_PROV_A};
static int iProv;
35
static const char szContainer[] = "winetest";
36 37 38 39 40
static const char *szProvider;

#define ENHANCED_PROV (iProv == 0)
#define BASE_PROV (iProv == 1)
#define STRONG_PROV (iProv == 2)
41

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
typedef struct _ctdatatype {
       unsigned char origstr[32];
       unsigned char decstr[32];
       int strlen;
       int enclen;
       int buflen;
} cryptdata;

static const cryptdata cTestData[4] = {
       {"abcdefghijkl",
       {'a','b','c','d','e','f','g','h',0x2,0x2,'k','l',0},
       12,8,16},
       {"abcdefghij",
       {'a','b','c','d','e','f','g','h',0x2,0x2,0},
       10,8,16},
       {"abcdefgh",
       {'a','b','c','d','e','f','g','h',0},
       8,8,16},
       {"abcdefghijkl",
       {'a','b','c','d','e','f','g','h','i','j','k','l',0},
       12,12,16}
};

65
static int win2k, nt4;
66

67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
/*
 * 1. Take the MD5 Hash of the container name (with an extra null byte)
 * 2. Turn the hash into a 4 DWORD hex value
 * 3. Append a '_'
 * 4. Add the MachineGuid
 *
 */
static void uniquecontainer(char *unique)
{
    /* MD5 hash of "winetest\0" in 4 DWORD hex */
    static const char szContainer_md5[] = "9d20fd8d05ed2b8455d125d0bf6d6a70";
    static const char szCryptography[] = "Software\\Microsoft\\Cryptography";
    static const char szMachineGuid[] = "MachineGuid";
    HKEY hkey;
    char guid[MAX_PATH];
    DWORD size = MAX_PATH;
83
    HRESULT ret;
84 85

    /* Get the MachineGUID */
86 87 88 89 90
    ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, szCryptography, 0, KEY_READ | KEY_WOW64_64KEY, &hkey);
    if (ret == ERROR_ACCESS_DENIED)
    {
        /* Windows 2000 can't handle KEY_WOW64_64KEY */
        RegOpenKeyA(HKEY_LOCAL_MACHINE, szCryptography, &hkey);
91
        win2k++;
92
    }
93 94 95
    RegQueryValueExA(hkey, szMachineGuid, NULL, NULL, (LPBYTE)guid, &size);
    RegCloseKey(hkey);

96
    if (!unique) return;
97 98 99
    lstrcpyA(unique, szContainer_md5);
    lstrcatA(unique, "_");
    lstrcatA(unique, guid);
100 101
}

102
static void printBytes(const char *heading, const BYTE *pb, size_t cb)
103 104 105 106 107 108 109 110
{
    size_t i;
    printf("%s: ",heading);
    for(i=0;i<cb;i++)
        printf("0x%02x,",pb[i]);
    putchar('\n');
}

111 112
static BOOL (WINAPI *pCryptDuplicateHash) (HCRYPTHASH, DWORD*, DWORD, HCRYPTHASH*);

113 114 115 116 117
static void trace_hex(BYTE *pbData, DWORD dwLen) {
    char szTemp[256];
    DWORD i, j;

    for (i = 0; i < dwLen-7; i+=8) {
118 119 120
        trace("0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
              pbData[i], pbData[i+1], pbData[i+2], pbData[i+3], pbData[i+4], pbData[i+5],
              pbData[i+6], pbData[i+7]);
121 122
    }
    for (j=0; i<dwLen; j++,i++) {
123
        sprintf(szTemp+6*j, "0x%02x, ", pbData[i]);
124
    }
125 126
    if (j)
        trace("%s\n", szTemp);
127 128
}

129
static BOOL init_base_environment(const char *provider, DWORD dwKeyFlags)
130 131 132
{
    HCRYPTKEY hKey;
    BOOL result;
133 134

    if (provider) szProvider = provider;
135
        
136 137
    pCryptDuplicateHash = (void *)GetProcAddress(GetModuleHandleA("advapi32.dll"), "CryptDuplicateHash");
        
138 139
    hProv = (HCRYPTPROV)INVALID_HANDLE_VALUE;

140
    result = CryptAcquireContextA(&hProv, szContainer, szProvider, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
141 142 143
    ok(!result && (GetLastError()==NTE_BAD_FLAGS ||
       broken(GetLastError() == NTE_KEYSET_NOT_DEF /* Win9x/NT4 */)),
       "%d, %08x\n", result, GetLastError());
144
    
145
    if (!CryptAcquireContextA(&hProv, szContainer, szProvider, PROV_RSA_FULL, 0))
146
    {
147
        ok(GetLastError()==NTE_BAD_KEYSET ||
148
           broken(GetLastError() == NTE_TEMPORARY_PROFILE /* some Win7 setups */) ||
149 150 151 152 153
           broken(GetLastError() == NTE_KEYSET_NOT_DEF /* Win9x/NT4 */),
           "%08x\n", GetLastError());
        if (GetLastError()!=NTE_BAD_KEYSET)
        {
            win_skip("RSA full provider not available\n");
154
            return FALSE;
155
        }
156
        result = CryptAcquireContextA(&hProv, szContainer, szProvider, PROV_RSA_FULL,
157
                                     CRYPT_NEWKEYSET);
158
        ok(result, "%08x\n", GetLastError());
159 160 161
        if (!result)
        {
            win_skip("Couldn't create crypto provider\n");
162
            return FALSE;
163
        }
164
        result = CryptGenKey(hProv, AT_KEYEXCHANGE, dwKeyFlags, &hKey);
165
        ok(result, "%08x\n", GetLastError());
166
        if (result) CryptDestroyKey(hKey);
167
        result = CryptGenKey(hProv, AT_SIGNATURE, dwKeyFlags, &hKey);
168
        ok(result, "%08x\n", GetLastError());
169 170
        if (result) CryptDestroyKey(hKey);
    }
171
    return TRUE;
172 173
}

174
static void clean_up_base_environment(void)
175
{
176 177
    BOOL result;

178
    SetLastError(0xdeadbeef);
179
    result = CryptReleaseContext(hProv, 1);
180 181
    ok(!result || broken(result) /* Win98 */, "Expected failure\n");
    ok(GetLastError()==NTE_BAD_FLAGS, "Expected NTE_BAD_FLAGS, got %08x\n", GetLastError());
182
        
183 184 185 186 187
    /* Just to prove that Win98 also released the CSP */
    SetLastError(0xdeadbeef);
    result = CryptReleaseContext(hProv, 0);
    ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "%08x\n", GetLastError());

188
    CryptAcquireContextA(&hProv, szContainer, szProvider, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
189 190
}

191
static BOOL init_aes_environment(void)
192 193 194 195 196 197 198 199 200
{
    HCRYPTKEY hKey;
    BOOL result;

    pCryptDuplicateHash = (void *)GetProcAddress(GetModuleHandleA("advapi32.dll"), "CryptDuplicateHash");

    hProv = (HCRYPTPROV)INVALID_HANDLE_VALUE;

    /* we are using NULL as provider name for RSA_AES provider as the provider
201
     * names are different in Windows XP and Vista. This differs from what
202
     * is defined in the SDK on Windows XP.
203 204
     * This provider is available on Windows XP, Windows 2003 and Vista.      */

205
    result = CryptAcquireContextA(&hProv, szContainer, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
206 207
    if (!result && GetLastError() == NTE_PROV_TYPE_NOT_DEF)
    {
208
        win_skip("RSA_AES provider not supported\n");
209
        return FALSE;
210
    }
211 212
    ok(!result && GetLastError()==NTE_BAD_FLAGS, "%d, %08x\n", result, GetLastError());

213
    if (!CryptAcquireContextA(&hProv, szContainer, NULL, PROV_RSA_AES, 0))
214 215
    {
        ok(GetLastError()==NTE_BAD_KEYSET, "%08x\n", GetLastError());
216
        if (GetLastError()!=NTE_BAD_KEYSET) return FALSE;
217
        result = CryptAcquireContextA(&hProv, szContainer, NULL, PROV_RSA_AES,
218 219
                                     CRYPT_NEWKEYSET);
        ok(result, "%08x\n", GetLastError());
220
        if (!result) return FALSE;
221 222 223 224 225 226
        result = CryptGenKey(hProv, AT_KEYEXCHANGE, 0, &hKey);
        ok(result, "%08x\n", GetLastError());
        if (result) CryptDestroyKey(hKey);
        result = CryptGenKey(hProv, AT_SIGNATURE, 0, &hKey);
        ok(result, "%08x\n", GetLastError());
        if (result) CryptDestroyKey(hKey);
227 228 229 230 231 232 233 234 235

        /* CALG_AES is not supported, but CALG_AES_128 is */
        result = CryptGenKey(hProv, CALG_AES, 0, &hKey);
        ok(!result && GetLastError() == NTE_BAD_ALGID, "%d %08x\n", result, GetLastError());
        result = CryptGenKey(hProv, CALG_AES, 128 << 16, &hKey);
        ok(!result && GetLastError() == NTE_BAD_ALGID, "%d %08x\n", result, GetLastError());
        result = CryptGenKey(hProv, CALG_AES_128, 0, &hKey);
        ok(result, "%08x\n", GetLastError());
        if (result) CryptDestroyKey(hKey);
236
    }
237
    return TRUE;
238 239 240 241 242 243 244
}

static void clean_up_aes_environment(void)
{
    BOOL result;

    result = CryptReleaseContext(hProv, 1);
245
    ok(!result && GetLastError()==NTE_BAD_FLAGS, "%08x\n", GetLastError());
246

247
    CryptAcquireContextA(&hProv, szContainer, NULL, PROV_RSA_AES, CRYPT_DELETEKEYSET);
248 249
}

250
static void test_prov(void) 
251 252 253 254 255
{
    BOOL result;
    DWORD dwLen, dwInc;
    
    dwLen = (DWORD)sizeof(DWORD);
256
    SetLastError(0xdeadbeef);
257
    result = CryptGetProvParam(hProv, PP_SIG_KEYSIZE_INC, (BYTE*)&dwInc, &dwLen, 0);
258
    if (!result && GetLastError() == NTE_BAD_TYPE)
259
    {
260
        skip("PP_SIG_KEYSIZE_INC is not supported (win9x or NT)\n");
261 262
        nt4++;
    }
263 264
    else
        ok(result && dwInc==8, "%08x, %d\n", GetLastError(), dwInc);
265 266
    
    dwLen = (DWORD)sizeof(DWORD);
267
    SetLastError(0xdeadbeef);
268
    result = CryptGetProvParam(hProv, PP_KEYX_KEYSIZE_INC, (BYTE*)&dwInc, &dwLen, 0);
269 270 271 272
    if (!result && GetLastError() == NTE_BAD_TYPE)
        skip("PP_KEYX_KEYSIZE_INC is not supported (win9x or NT)\n");
    else
        ok(result && dwInc==8, "%08x, %d\n", GetLastError(), dwInc);
273 274
}

275
static void test_gen_random(void)
276 277 278 279 280 281 282 283 284 285 286 287 288
{
    BOOL result;
    BYTE rnd1[16], rnd2[16];

    memset(rnd1, 0, sizeof(rnd1));
    memset(rnd2, 0, sizeof(rnd2));

    result = CryptGenRandom(hProv, sizeof(rnd1), rnd1);
    if (!result && GetLastError() == NTE_FAIL) {
        /* rsaenh compiled without OpenSSL */
        return;
    }
    
289
    ok(result, "%08x\n", GetLastError());
290 291

    result = CryptGenRandom(hProv, sizeof(rnd2), rnd2);
292
    ok(result, "%08x\n", GetLastError());
293 294 295 296 297 298 299 300 301 302 303

    ok(memcmp(rnd1, rnd2, sizeof(rnd1)), "CryptGenRandom generates non random data\n");
}

static BOOL derive_key(ALG_ID aiAlgid, HCRYPTKEY *phKey, DWORD len) 
{
    HCRYPTHASH hHash;
    BOOL result;
    unsigned char pbData[2000];
    int i;

304
    *phKey = 0;
305 306 307 308
    for (i=0; i<2000; i++) pbData[i] = (unsigned char)i;
    result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
    if (!result) {
        /* rsaenh compiled without OpenSSL */
309
        ok(GetLastError()==NTE_BAD_ALGID, "%08x\n", GetLastError());
310 311
        return FALSE;
    } 
312
    ok(result, "%08x\n", GetLastError());
313
    result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
314
    ok(result, "%08x\n", GetLastError());
315 316
    if (!result) return FALSE;
    result = CryptDeriveKey(hProv, aiAlgid, hHash, (len << 16) | CRYPT_EXPORTABLE, phKey);
317
    ok(result, "%08x\n", GetLastError());
318 319 320
    if (!result) return FALSE;
    len = 2000;
    result = CryptGetHashParam(hHash, HP_HASHVAL, pbData, &len, 0);
321
    ok(result, "%08x\n", GetLastError());
322 323 324 325
    CryptDestroyHash(hHash);
    return TRUE;
}

326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
static BYTE abPlainPrivateKey[596] = {
    0x07, 0x02, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00,
    0x52, 0x53, 0x41, 0x32, 0x00, 0x04, 0x00, 0x00,
    0x01, 0x00, 0x01, 0x00, 0x9b, 0x64, 0xef, 0xce,
    0x31, 0x7c, 0xad, 0x56, 0xe2, 0x1e, 0x9b, 0x96,
    0xb3, 0xf0, 0x29, 0x88, 0x6e, 0xa8, 0xc2, 0x11,
    0x33, 0xd6, 0xcc, 0x8c, 0x69, 0xb2, 0x1a, 0xfd,
    0xfc, 0x23, 0x21, 0x30, 0x4d, 0x29, 0x45, 0xb6,
    0x3a, 0x67, 0x11, 0x80, 0x1a, 0x91, 0xf2, 0x9f,
    0x01, 0xac, 0xc0, 0x11, 0x50, 0x5f, 0xcd, 0xb9,
    0xad, 0x76, 0x9f, 0x6e, 0x91, 0x55, 0x71, 0xda,
    0x97, 0x96, 0x96, 0x22, 0x75, 0xb4, 0x83, 0x44,
    0x89, 0x9e, 0xf8, 0x44, 0x40, 0x7c, 0xd6, 0xcd,
    0x9d, 0x88, 0xd6, 0x88, 0xbc, 0x56, 0xb7, 0x64,
    0xe9, 0x2c, 0x24, 0x2f, 0x0d, 0x78, 0x55, 0x1c,
    0xb2, 0x67, 0xb1, 0x5e, 0xbc, 0x0c, 0xcf, 0x1c,
    0xe9, 0xd3, 0x9e, 0xa2, 0x15, 0x24, 0x73, 0xd6,
    0xdb, 0x6f, 0x83, 0xb2, 0xf8, 0xbc, 0xe7, 0x47,
    0x3b, 0x01, 0xef, 0x49, 0x08, 0x98, 0xd6, 0xa3,
    0xf9, 0x25, 0x57, 0xe9, 0x39, 0x3c, 0x53, 0x30,
    0x1b, 0xf2, 0xc9, 0x62, 0x31, 0x43, 0x5d, 0x84,
    0x24, 0x30, 0x21, 0x9a, 0xad, 0xdb, 0x62, 0x91,
    0xc8, 0x07, 0xd9, 0x2f, 0xd6, 0xb5, 0x37, 0x6f,
    0xfe, 0x7a, 0x12, 0xbc, 0xd9, 0xd2, 0x2b, 0xbf,
    0xd7, 0xb1, 0xfa, 0x7d, 0xc0, 0x48, 0xdd, 0x74,
    0xdd, 0x55, 0x04, 0xa1, 0x8b, 0xc1, 0x0a, 0xc4,
    0xa5, 0x57, 0x62, 0xee, 0x08, 0x8b, 0xf9, 0x19,
    0x6c, 0x52, 0x06, 0xf8, 0x73, 0x0f, 0x24, 0xc9,
    0x71, 0x9f, 0xc5, 0x45, 0x17, 0x3e, 0xae, 0x06,
    0x81, 0xa2, 0x96, 0x40, 0x06, 0xbf, 0xeb, 0x9e,
    0x80, 0x2b, 0x27, 0x20, 0x8f, 0x38, 0xcf, 0xeb,
    0xff, 0x3b, 0x38, 0x41, 0x35, 0x69, 0x66, 0x13,
    0x1d, 0x3c, 0x01, 0x3b, 0xf6, 0x37, 0xca, 0x9c,
    0x61, 0x74, 0x98, 0xcf, 0xc9, 0x6e, 0xe8, 0x90,
    0xc7, 0xb7, 0x33, 0xc0, 0x07, 0x3c, 0xf8, 0xc8,
    0xf6, 0xf2, 0xd7, 0xf0, 0x21, 0x62, 0x58, 0x8a,
    0x55, 0xbf, 0xa1, 0x2d, 0x3d, 0xa6, 0x69, 0xc5,
    0x02, 0x19, 0x31, 0xf0, 0x94, 0x0f, 0x45, 0x5c,
    0x95, 0x1b, 0x53, 0xbc, 0xf5, 0xb0, 0x1a, 0x8f,
    0xbf, 0x40, 0xe0, 0xc7, 0x73, 0xe7, 0x72, 0x6e,
    0xeb, 0xb1, 0x0f, 0x38, 0xc5, 0xf8, 0xee, 0x04,
    0xed, 0x34, 0x1a, 0x10, 0xf9, 0x53, 0x34, 0xf3,
    0x3e, 0xe6, 0x5c, 0xd1, 0x47, 0x65, 0xcd, 0xbd,
    0xf1, 0x06, 0xcb, 0xb4, 0xb1, 0x26, 0x39, 0x9f,
    0x71, 0xfe, 0x3d, 0xf8, 0x62, 0xab, 0x22, 0x8b,
    0x0e, 0xdc, 0xb9, 0xe8, 0x74, 0x06, 0xfc, 0x8c,
    0x25, 0xa1, 0xa9, 0xcf, 0x07, 0xf9, 0xac, 0x21,
    0x01, 0x7b, 0x1c, 0xdc, 0x94, 0xbd, 0x47, 0xe1,
    0xa0, 0x86, 0x59, 0x35, 0x6a, 0x6f, 0xb9, 0x70,
    0x26, 0x7c, 0x3c, 0xfd, 0xbd, 0x81, 0x39, 0x36,
    0x42, 0xc2, 0xbd, 0xbe, 0x84, 0x27, 0x9a, 0x69,
    0x81, 0xda, 0x99, 0x27, 0xc2, 0x4f, 0x62, 0x33,
    0xf4, 0x79, 0x30, 0xc5, 0x63, 0x54, 0x71, 0xf1,
    0x47, 0x22, 0x25, 0x9b, 0x6c, 0x00, 0x2f, 0x1c,
    0xf4, 0x1f, 0x85, 0xbc, 0xf6, 0x67, 0x6a, 0xe3,
    0xf6, 0x55, 0x8a, 0xef, 0xd0, 0x0b, 0xd3, 0xa2,
    0xc5, 0x51, 0x70, 0x15, 0x0a, 0xf0, 0x98, 0x4c,
    0xb7, 0x19, 0x62, 0x0e, 0x2d, 0x2a, 0x4a, 0x7d,
    0x7a, 0x0a, 0xc4, 0x17, 0xe3, 0x5d, 0x20, 0x52,
    0xa9, 0x98, 0xc3, 0xaa, 0x11, 0xf6, 0xbf, 0x4c,
    0x94, 0x99, 0x81, 0x89, 0xf0, 0x7f, 0x66, 0xaa,
    0xc8, 0x88, 0xd7, 0x31, 0x84, 0x71, 0xb6, 0x64,
    0x09, 0x76, 0x0b, 0x7f, 0x1a, 0x1f, 0x2e, 0xfe,
    0xcd, 0x59, 0x2a, 0x54, 0x11, 0x84, 0xd4, 0x6a,
    0x61, 0xdf, 0xaa, 0x76, 0x66, 0x9d, 0x82, 0x11,
    0x56, 0x3d, 0xd2, 0x52, 0xe6, 0x42, 0x5a, 0x77,
    0x92, 0x98, 0x34, 0xf3, 0x56, 0x6c, 0x96, 0x10,
    0x40, 0x59, 0x16, 0xcb, 0x77, 0x61, 0xe3, 0xbf,
    0x4b, 0xd4, 0x39, 0xfb, 0xb1, 0x4e, 0xc1, 0x74,
    0xec, 0x7a, 0xea, 0x3d, 0x68, 0xbb, 0x0b, 0xe6,
    0xc6, 0x06, 0xbf, 0xdd, 0x7f, 0x94, 0x42, 0xc0,
    0x0f, 0xe4, 0x92, 0x33, 0x6c, 0x6e, 0x1b, 0xba,
    0x73, 0xf9, 0x79, 0x84, 0xdf, 0x45, 0x00, 0xe4,
    0x94, 0x88, 0x9d, 0x08, 0x89, 0xcf, 0xf2, 0xa4,
    0xc5, 0x47, 0x45, 0x85, 0x86, 0xa5, 0xcc, 0xa8,
    0xf2, 0x5d, 0x58, 0x07
};

404 405 406 407 408 409 410 411
static void test_hashes(void)
{
    static const unsigned char md2hash[16] = {
        0x12, 0xcb, 0x1b, 0x08, 0xc8, 0x48, 0xa4, 0xa9, 
        0xaa, 0xf3, 0xf1, 0x9f, 0xfc, 0x29, 0x28, 0x68 };
    static const unsigned char md4hash[16] = {
        0x8e, 0x2a, 0x58, 0xbf, 0xf2, 0xf5, 0x26, 0x23, 
        0x79, 0xd2, 0x92, 0x36, 0x1b, 0x23, 0xe3, 0x81 };
412 413 414
    static const unsigned char empty_md5hash[16] = {
        0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
        0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e };
415 416 417 418 419 420
    static const unsigned char md5hash[16] = { 
        0x15, 0x76, 0xa9, 0x4d, 0x6c, 0xb3, 0x34, 0xdd, 
        0x12, 0x6c, 0xb1, 0xc2, 0x7f, 0x19, 0xe0, 0xf2 };    
    static const unsigned char sha1hash[20] = { 
        0xf1, 0x0c, 0xcf, 0xde, 0x60, 0xc1, 0x7d, 0xb2, 0x6e, 0x7d, 
        0x85, 0xd3, 0x56, 0x65, 0xc7, 0x66, 0x1d, 0xbb, 0xeb, 0x2c };
421 422 423 424 425 426 427 428 429 430 431
    static const unsigned char signed_ssl3_shamd5_hash[] = {
        0x4f,0xcc,0x2f,0x33,0x44,0x60,0x76,0x16,0x13,0xc8,0xff,0xd4,0x59,0x19,
        0xde,0x85,0x44,0x72,0x47,0x98,0x01,0xfb,0x67,0x5c,0x5b,0x35,0x15,0x0f,
        0x91,0xda,0xc7,0x7c,0xfb,0xe2,0x18,0xef,0xac,0x31,0x40,0x7b,0xa9,0x83,
        0xdb,0x30,0xcd,0x94,0x4b,0x8e,0x3b,0x6c,0x7a,0x86,0x59,0xf0,0xd1,0xd2,
        0x5e,0xce,0xd4,0x1b,0x7f,0xed,0x24,0xee,0x53,0x5c,0x15,0x97,0x21,0x7c,
        0x5c,0xea,0xab,0xf5,0xd6,0x4b,0xb3,0xbb,0x14,0xf5,0x59,0x9e,0x21,0x90,
        0x21,0x99,0x19,0xad,0xa2,0xa6,0xea,0x61,0xc1,0x41,0xe2,0x70,0x77,0xf7,
        0x15,0x68,0x96,0x1e,0x5c,0x84,0x97,0xe3,0x5c,0xd2,0xd9,0xfb,0x87,0x6f,
        0x11,0x21,0x82,0x43,0x76,0x32,0xa4,0x38,0x7b,0x85,0x22,0x30,0x1e,0x55,
        0x79,0x93 };
432 433 434
    unsigned char pbData[2048];
    BOOL result;
    HCRYPTHASH hHash, hHashClone;
435
    HCRYPTPROV prov;
436
    BYTE pbHashValue[36];
437 438
    BYTE pbSigValue[128];
    HCRYPTKEY hKeyExchangeKey;
439
    DWORD hashlen, len, error, cryptflags;
440 441 442 443 444 445 446 447
    int i;

    for (i=0; i<2048; i++) pbData[i] = (unsigned char)i;

    /* MD2 Hashing */
    result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
    if (!result) {
        /* rsaenh compiled without OpenSSL */
448
        ok(GetLastError() == NTE_BAD_ALGID, "%08x\n", GetLastError());
449
    } else {
450
        result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
451
        ok(result, "%08x\n", GetLastError());
452 453 454

        len = sizeof(DWORD);
        result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
455
           ok(result && (hashlen == 16), "%08x, hashlen: %d\n", GetLastError(), hashlen);
456 457 458

        len = 16;
        result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
459
        ok(result, "%08x\n", GetLastError());
460 461 462 463

        ok(!memcmp(pbHashValue, md2hash, 16), "Wrong MD2 hash!\n");

        result = CryptDestroyHash(hHash);
464
        ok(result, "%08x\n", GetLastError());
465 466 467 468
    } 

    /* MD4 Hashing */
    result = CryptCreateHash(hProv, CALG_MD4, 0, 0, &hHash);
469
    ok(result, "%08x\n", GetLastError());
470

471 472 473
    result = CryptHashData(hHash, pbData, sizeof(pbData), ~0);
    ok(!result && GetLastError() == NTE_BAD_FLAGS, "%08x\n", GetLastError());

474 475
    cryptflags = CRYPT_USERDATA;
    result = CryptHashData(hHash, pbData, sizeof(pbData), cryptflags);
476 477
    if (!result && GetLastError() == NTE_BAD_FLAGS) /* <= NT4 */
    {
478
        cryptflags &= ~CRYPT_USERDATA;
479 480 481
        ok(broken(1), "Failed to support CRYPT_USERDATA flag\n");
        result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
    }
482
    ok(result, "%08x\n", GetLastError());
483 484 485

    len = sizeof(DWORD);
    result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
486
    ok(result && (hashlen == 16), "%08x, hashlen: %d\n", GetLastError(), hashlen);
487 488 489

    len = 16;
    result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
490
    ok(result, "%08x\n", GetLastError());
491 492 493 494

    ok(!memcmp(pbHashValue, md4hash, 16), "Wrong MD4 hash!\n");

    result = CryptDestroyHash(hHash);
495
    ok(result, "%08x\n", GetLastError());
496 497 498

    /* MD5 Hashing */
    result = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
499
    ok(result, "%08x\n", GetLastError());
500 501 502

    len = sizeof(DWORD);
    result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
503
    ok(result && (hashlen == 16), "%08x, hashlen: %d\n", GetLastError(), hashlen);
504

505 506 507
    result = CryptHashData(hHash, pbData, sizeof(pbData), ~0);
    ok(!result && GetLastError() == NTE_BAD_FLAGS, "%08x\n", GetLastError());

508
    result = CryptHashData(hHash, pbData, sizeof(pbData), cryptflags);
509 510
    ok(result, "%08x\n", GetLastError());

511 512
    len = 16;
    result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
513
    ok(result, "%08x\n", GetLastError());
514 515 516 517

    ok(!memcmp(pbHashValue, md5hash, 16), "Wrong MD5 hash!\n");

    result = CryptDestroyHash(hHash);
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
    ok(result, "%08x\n", GetLastError());

    result = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
    ok(result, "%08x\n", GetLastError());

    /* The hash is available even if CryptHashData hasn't been called */
    len = 16;
    result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
    ok(result, "%08x\n", GetLastError());

    ok(!memcmp(pbHashValue, empty_md5hash, 16), "Wrong MD5 hash!\n");

    /* It's also stable:  getting it twice results in the same value */
    result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
    ok(result, "%08x\n", GetLastError());

    ok(!memcmp(pbHashValue, empty_md5hash, 16), "Wrong MD5 hash!\n");

    /* Can't add data after the hash been retrieved */
    SetLastError(0xdeadbeef);
538
    result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
539 540 541 542
    ok(!result, "Expected failure\n");
    ok(GetLastError() == NTE_BAD_HASH_STATE ||
       GetLastError() == NTE_BAD_ALGID, /* Win9x, WinMe, NT4 */
       "Expected NTE_BAD_HASH_STATE or NTE_BAD_ALGID, got %08x\n", GetLastError());
543 544 545 546 547 548 549 550

    /* You can still retrieve the hash, its value just hasn't changed */
    result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
    ok(result, "%08x\n", GetLastError());

    ok(!memcmp(pbHashValue, empty_md5hash, 16), "Wrong MD5 hash!\n");

    result = CryptDestroyHash(hHash);
551
    ok(result, "%08x\n", GetLastError());
552 553 554

    /* SHA1 Hashing */
    result = CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash);
555
    ok(result, "%08x\n", GetLastError());
556

557
    result = CryptHashData(hHash, pbData, 5, cryptflags);
558
    ok(result, "%08x\n", GetLastError());
559

560 561
    if(pCryptDuplicateHash) {
        result = pCryptDuplicateHash(hHash, 0, 0, &hHashClone);
562
        ok(result, "%08x\n", GetLastError());
563

564
        result = CryptHashData(hHashClone, (BYTE*)pbData+5, sizeof(pbData)-5, 0);
565
        ok(result, "%08x\n", GetLastError());
566

567 568
        len = sizeof(DWORD);
        result = CryptGetHashParam(hHashClone, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
569
        ok(result && (hashlen == 20), "%08x, hashlen: %d\n", GetLastError(), hashlen);
570

571 572
        len = 20;
        result = CryptGetHashParam(hHashClone, HP_HASHVAL, pbHashValue, &len, 0);
573
        ok(result, "%08x\n", GetLastError());
574

575 576 577
        ok(!memcmp(pbHashValue, sha1hash, 20), "Wrong SHA1 hash!\n");

        result = CryptDestroyHash(hHashClone);
578
        ok(result, "%08x\n", GetLastError());
579
    }
580 581

    result = CryptDestroyHash(hHash);
582
    ok(result, "%08x\n", GetLastError());
583 584 585 586 587 588 589 590 591 592 593

    /* The SHA-2 variants aren't supported in the RSA full provider */
    result = CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash);
    ok(!result && GetLastError() == NTE_BAD_ALGID,
       "expected NTE_BAD_ALGID, got %08x\n", GetLastError());
    result = CryptCreateHash(hProv, CALG_SHA_384, 0, 0, &hHash);
    ok(!result && GetLastError() == NTE_BAD_ALGID,
       "expected NTE_BAD_ALGID, got %08x\n", GetLastError());
    result = CryptCreateHash(hProv, CALG_SHA_512, 0, 0, &hHash);
    ok(!result && GetLastError() == NTE_BAD_ALGID,
       "expected NTE_BAD_ALGID, got %08x\n", GetLastError());
594

595
    result = CryptAcquireContextA(&prov, NULL, szProvider, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
596
    ok(result, "CryptAcquireContextA failed 0x%08x\n", GetLastError());
597 598 599 600 601 602 603 604 605

    result = CryptCreateHash(prov, CALG_SHA1, 0, 0, &hHash);
    ok(result, "CryptCreateHash failed 0x%08x\n", GetLastError());

    /* release provider before using the hash */
    result = CryptReleaseContext(prov, 0);
    ok(result, "CryptReleaseContext failed 0x%08x\n", GetLastError());

    SetLastError(0xdeadbeef);
606
    result = CryptHashData(hHash, (const BYTE *)"data", sizeof("data"), 0);
607 608 609 610 611 612 613 614 615 616
    error = GetLastError();
    ok(!result, "CryptHashData succeeded\n");
    ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", error);

    SetLastError(0xdeadbeef);
    result = CryptDestroyHash(hHash);
    error = GetLastError();
    ok(!result, "CryptDestroyHash succeeded\n");
    ok(error == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER got %u\n", error);

617 618 619 620 621 622 623
    if (!pCryptDuplicateHash)
    {
        win_skip("CryptDuplicateHash is not available\n");
        return;
    }

    result = CryptAcquireContextA(&prov, NULL, szProvider, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
624
    ok(result, "CryptAcquireContextA failed 0x%08x\n", GetLastError());
625 626 627 628

    result = CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash);
    ok(result, "CryptCreateHash failed 0x%08x\n", GetLastError());

629
    result = CryptHashData(hHash, (const BYTE *)"data", sizeof("data"), 0);
630 631
    ok(result, "CryptHashData failed 0x%08x\n", GetLastError());

632
    result = pCryptDuplicateHash(hHash, NULL, 0, &hHashClone);
633 634 635 636 637 638 639
    ok(result, "CryptDuplicateHash failed 0x%08x\n", GetLastError());

    len = 20;
    result = CryptGetHashParam(hHashClone, HP_HASHVAL, pbHashValue, &len, 0);
    ok(result, "CryptGetHashParam failed 0x%08x\n", GetLastError());

    /* add data after duplicating the hash */
640
    result = CryptHashData(hHash, (const BYTE *)"more data", sizeof("more data"), 0);
641 642 643 644 645 646 647 648 649 650
    ok(result, "CryptHashData failed 0x%08x\n", GetLastError());

    result = CryptDestroyHash(hHash);
    ok(result, "CryptDestroyHash failed 0x%08x\n", GetLastError());

    result = CryptDestroyHash(hHashClone);
    ok(result, "CryptDestroyHash failed 0x%08x\n", GetLastError());

    result = CryptReleaseContext(prov, 0);
    ok(result, "CryptReleaseContext failed 0x%08x\n", GetLastError());
651 652 653

    /* Test CALG_SSL3_SHAMD5 */
    result = CryptAcquireContextA(&prov, NULL, szProvider, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
654
    ok(result, "CryptAcquireContextA failed 0x%08x\n", GetLastError());
655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680

    /* Step 1: create an MD5 hash of the data */
    result = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
    ok(result, "CryptCreateHash failed 0x%08x\n", GetLastError());
    result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
    ok(result, "%08x\n", GetLastError());
    len = 16;
    result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
    ok(result, "CryptGetHashParam failed 0x%08x\n", GetLastError());
    result = CryptDestroyHash(hHash);
    ok(result, "CryptDestroyHash failed 0x%08x\n", GetLastError());
    /* Step 2: create a SHA1 hash of the data */
    result = CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash);
    ok(result, "CryptCreateHash failed 0x%08x\n", GetLastError());
    result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
    ok(result, "%08x\n", GetLastError());
    len = 20;
    result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue + 16, &len, 0);
    ok(result, "CryptGetHashParam failed 0x%08x\n", GetLastError());
    result = CryptDestroyHash(hHash);
    ok(result, "CryptDestroyHash failed 0x%08x\n", GetLastError());
    /* Step 3: create a CALG_SSL3_SHAMD5 hash handle */
    result = CryptCreateHash(hProv, CALG_SSL3_SHAMD5, 0, 0, &hHash);
    ok(result, "CryptCreateHash failed 0x%08x\n", GetLastError());
    /* Test that CryptHashData fails on this hash */
    result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
681 682
    ok(!result && (GetLastError() == NTE_BAD_ALGID || broken(GetLastError() == ERROR_INVALID_HANDLE)) /* Win 8 */,
       "%08x\n", GetLastError());
683 684 685 686 687 688
    result = CryptSetHashParam(hHash, HP_HASHVAL, pbHashValue, 0);
    ok(result, "%08x\n", GetLastError());
    len = (DWORD)sizeof(abPlainPrivateKey);
    result = CryptImportKey(hProv, abPlainPrivateKey, len, 0, 0, &hKeyExchangeKey);
    ok(result, "%08x\n", GetLastError());
    len = 0;
689
    result = CryptSignHashA(hHash, AT_KEYEXCHANGE, NULL, 0, NULL, &len);
690 691
    ok(result, "%08x\n", GetLastError());
    ok(len == 128, "expected len 128, got %d\n", len);
692
    result = CryptSignHashA(hHash, AT_KEYEXCHANGE, NULL, 0, pbSigValue, &len);
693 694 695 696 697 698 699 700
    ok(result, "%08x\n", GetLastError());
    ok(!memcmp(pbSigValue, signed_ssl3_shamd5_hash, len), "unexpected value\n");
    if (len != 128 || memcmp(pbSigValue, signed_ssl3_shamd5_hash, len))
    {
        printBytes("expected", signed_ssl3_shamd5_hash,
                   sizeof(signed_ssl3_shamd5_hash));
        printBytes("got", pbSigValue, len);
    }
701 702
    result = CryptDestroyKey(hKeyExchangeKey);
    ok(result, "CryptDestroyKey failed 0x%08x\n", GetLastError());
703 704 705 706
    result = CryptDestroyHash(hHash);
    ok(result, "CryptDestroyHash failed 0x%08x\n", GetLastError());
    result = CryptReleaseContext(prov, 0);
    ok(result, "CryptReleaseContext failed 0x%08x\n", GetLastError());
707
}
708

709
static void test_block_cipher_modes(void)
710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730
{
    static const BYTE plain[23] = { 
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 
        0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
    static const BYTE ecb[24] = {   
        0xc0, 0x9a, 0xe4, 0x2f, 0x0a, 0x47, 0x67, 0x11, 0xf2, 0xb2, 0x5d, 0x5f, 
        0x08, 0xff, 0x49, 0xa4, 0x45, 0x3a, 0x68, 0x14, 0xca, 0x18, 0xe5, 0xf4 };
    static const BYTE cbc[24] = {   
        0xc0, 0x9a, 0xe4, 0x2f, 0x0a, 0x47, 0x67, 0x11, 0x10, 0xf5, 0xda, 0x61,
        0x4e, 0x3d, 0xab, 0xc0, 0x97, 0x85, 0x01, 0x12, 0x97, 0xa4, 0xf7, 0xd3 };
    static const BYTE cfb[24] = {   
        0x29, 0xb5, 0x67, 0x85, 0x0b, 0x1b, 0xec, 0x07, 0x67, 0x2d, 0xa1, 0xa4,
        0x1a, 0x47, 0x24, 0x6a, 0x54, 0xe1, 0xe0, 0x92, 0xf9, 0x0e, 0xf6, 0xeb };
    HCRYPTKEY hKey;
    BOOL result;
    BYTE abData[24];
    DWORD dwMode, dwLen;

    result = derive_key(CALG_RC2, &hKey, 40);
    if (!result) return;

731
    memcpy(abData, plain, sizeof(plain));
732

733 734 735 736 737 738 739
    /* test default chaining mode */
    dwMode = 0xdeadbeef;
    dwLen = sizeof(dwMode);
    result = CryptGetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, &dwLen, 0);
    ok(result, "%08x\n", GetLastError());
    ok(dwMode == CRYPT_MODE_CBC, "Wrong default chaining mode\n");

740 741
    dwMode = CRYPT_MODE_ECB;
    result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
742
    ok(result, "%08x\n", GetLastError());
743

744 745 746 747
    result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
    ok(result, "%08x\n", GetLastError());
    ok(dwLen == 11 || broken(dwLen == 0 /* Win9x/NT4 */), "unexpected salt length %d\n", dwLen);

748
    dwLen = 23;
749
    result = CryptEncrypt(hKey, 0, TRUE, 0, NULL, &dwLen, 24);
750 751
    ok(result, "CryptEncrypt failed: %08x\n", GetLastError());
    ok(dwLen == 24, "Unexpected length %d\n", dwLen);
752

753 754
    SetLastError(ERROR_SUCCESS);
    dwLen = 23;
755
    result = CryptEncrypt(hKey, 0, TRUE, 0, abData, &dwLen, 24);
756
    ok(result && dwLen == 24 && !memcmp(ecb, abData, sizeof(ecb)), 
757
       "%08x, dwLen: %d\n", GetLastError(), dwLen);
758

759
    result = CryptDecrypt(hKey, 0, TRUE, 0, abData, &dwLen);
760
    ok(result && dwLen == 23 && !memcmp(plain, abData, sizeof(plain)), 
761
       "%08x, dwLen: %d\n", GetLastError(), dwLen);
762 763 764

    dwMode = CRYPT_MODE_CBC;
    result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
765
    ok(result, "%08x\n", GetLastError());
766
    
767
    dwLen = 23;
768
    result = CryptEncrypt(hKey, 0, TRUE, 0, NULL, &dwLen, 24);
769 770
    ok(result, "CryptEncrypt failed: %08x\n", GetLastError());
    ok(dwLen == 24, "Unexpected length %d\n", dwLen);
771

772
    dwLen = 23;
773
    result = CryptEncrypt(hKey, 0, TRUE, 0, abData, &dwLen, 24);
774
    ok(result && dwLen == 24 && !memcmp(cbc, abData, sizeof(cbc)), 
775
       "%08x, dwLen: %d\n", GetLastError(), dwLen);
776

777
    result = CryptDecrypt(hKey, 0, TRUE, 0, abData, &dwLen);
778
    ok(result && dwLen == 23 && !memcmp(plain, abData, sizeof(plain)), 
779
       "%08x, dwLen: %d\n", GetLastError(), dwLen);
780 781 782

    dwMode = CRYPT_MODE_CFB;
    result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
783
    ok(result, "%08x\n", GetLastError());
784 785
    
    dwLen = 16;
786
    result = CryptEncrypt(hKey, 0, FALSE, 0, abData, &dwLen, 24);
787
    ok(result && dwLen == 16, "%08x, dwLen: %d\n", GetLastError(), dwLen);
788 789

    dwLen = 7;
790
    result = CryptEncrypt(hKey, 0, TRUE, 0, abData+16, &dwLen, 8);
791
    ok(result && dwLen == 8 && !memcmp(cfb, abData, sizeof(cfb)), 
792
       "%08x, dwLen: %d\n", GetLastError(), dwLen);
793 794
    
    dwLen = 8;
795
    result = CryptDecrypt(hKey, 0, FALSE, 0, abData, &dwLen);
796
    ok(result && dwLen == 8, "%08x, dwLen: %d\n", GetLastError(), dwLen);
797 798

    dwLen = 16;
799
    result = CryptDecrypt(hKey, 0, TRUE, 0, abData+8, &dwLen);
800
    ok(result && dwLen == 15 && !memcmp(plain, abData, sizeof(plain)), 
801
       "%08x, dwLen: %d\n", GetLastError(), dwLen);
802 803 804

    dwMode = CRYPT_MODE_OFB;
    result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
805 806 807 808 809 810 811 812 813 814 815 816
    if(!result && GetLastError() == ERROR_INTERNAL_ERROR)
    {
        ok(broken(1), "OFB mode not supported\n"); /* Windows 8 */
    }
    else
    {
        ok(result, "%08x\n", GetLastError());

        dwLen = 23;
        result = CryptEncrypt(hKey, 0, TRUE, 0, abData, &dwLen, 24);
        ok(!result && GetLastError() == NTE_BAD_ALGID, "%08x\n", GetLastError());
    }
817 818

    CryptDestroyKey(hKey);
819 820
}

821
static void test_3des112(void)
822 823 824 825
{
    HCRYPTKEY hKey;
    BOOL result;
    DWORD dwLen;
826
    unsigned char pbData[16], enc_data[16], bad_data[16];
827 828 829
    static const BYTE des112[16] = {
        0x8e, 0x0c, 0x3c, 0xa3, 0x05, 0x88, 0x5f, 0x7a,
        0x32, 0xa1, 0x06, 0x52, 0x64, 0xd2, 0x44, 0x1c };
830 831 832 833 834
    int i;

    result = derive_key(CALG_3DES_112, &hKey, 0);
    if (!result) {
        /* rsaenh compiled without OpenSSL */
835
        ok(GetLastError() == NTE_BAD_ALGID, "%08x\n", GetLastError());
836 837 838 839 840 841
        return;
    }

    for (i=0; i<sizeof(pbData); i++) pbData[i] = (unsigned char)i;
    
    dwLen = 13;
842
    result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, 16);
843
    ok(result, "%08x\n", GetLastError());
844
    
845 846
    ok(!memcmp(pbData, des112, sizeof(des112)), "3DES_112 encryption failed!\n");

847
    result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
848
    ok(result, "%08x\n", GetLastError());
849

850 851 852 853 854
    for (i=0; i<4; i++)
    {
      memcpy(pbData,cTestData[i].origstr,cTestData[i].strlen);

      dwLen = cTestData[i].enclen;
855
      result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, cTestData[i].buflen);
856 857
      ok(result, "%08x\n", GetLastError());
      ok(dwLen==cTestData[i].buflen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].buflen);
858
      memcpy(enc_data, pbData, cTestData[i].buflen);
859

860
      result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
861 862 863 864 865 866 867 868 869
      ok(result, "%08x\n", GetLastError());
      ok(dwLen==cTestData[i].enclen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].enclen);
      ok(memcmp(pbData,cTestData[i].decstr,cTestData[1].enclen)==0,"decryption incorrect %d\n",i);
      if((dwLen != cTestData[i].enclen) ||
         memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen))
      {
          printBytes("expected",cTestData[i].decstr,cTestData[i].strlen);
          printBytes("got",pbData,dwLen);
      }
870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904

      /* Test bad data:
         Decrypting a block of bad data with Final = TRUE should restore the
         initial state of the key as well as decrypting a block of good data.
       */

      /* Changing key state by setting Final = FALSE */
      dwLen = cTestData[i].buflen;
      memcpy(pbData, enc_data, cTestData[i].buflen);
      result = CryptDecrypt(hKey, 0, FALSE, 0, pbData, &dwLen);
      ok(result, "%08x\n", GetLastError());

      /* Restoring key state by decrypting bad_data with Final = TRUE */
      memcpy(bad_data, enc_data, cTestData[i].buflen);
      bad_data[cTestData[i].buflen - 1] = ~bad_data[cTestData[i].buflen - 1];
      SetLastError(0xdeadbeef);
      result = CryptDecrypt(hKey, 0, TRUE, 0, bad_data, &dwLen);
      ok(!result, "CryptDecrypt should failed!\n");
      ok(GetLastError() == NTE_BAD_DATA, "%08x\n", GetLastError());
      ok(dwLen==cTestData[i].buflen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].buflen);
      ok(memcmp(pbData,cTestData[i].decstr,cTestData[1].enclen)==0,"decryption incorrect %d\n",i);

      /* Checking key state */
      dwLen = cTestData[i].buflen;
      memcpy(pbData, enc_data, cTestData[i].buflen);
      result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
      ok(result, "%08x\n", GetLastError());
      ok(dwLen==cTestData[i].enclen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].enclen);
      ok(memcmp(pbData,cTestData[i].decstr,cTestData[1].enclen)==0,"decryption incorrect %d\n",i);
      if((dwLen != cTestData[i].enclen) ||
         memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen))
      {
          printBytes("expected",cTestData[i].decstr,cTestData[i].strlen);
          printBytes("got",pbData,dwLen);
      }
905
    }
906
    result = CryptDestroyKey(hKey);
907
    ok(result, "%08x\n", GetLastError());
908 909
}

910
static void test_des(void) 
911 912 913 914
{
    HCRYPTKEY hKey;
    BOOL result;
    DWORD dwLen, dwMode;
915
    unsigned char pbData[16], enc_data[16], bad_data[16];
916 917 918
    static const BYTE des[16] = {
        0x58, 0x86, 0x42, 0x46, 0x65, 0x4b, 0x92, 0x62,
        0xcf, 0x0f, 0x65, 0x37, 0x43, 0x7a, 0x82, 0xb9 };
919 920 921
    static const BYTE des_old_behavior[16] = {
        0xb0, 0xfd, 0x11, 0x69, 0x76, 0xb1, 0xa1, 0x03,
        0xf7, 0xbc, 0x23, 0xaa, 0xd4, 0xc1, 0xc9, 0x55 };
922 923 924
    static const BYTE des_old_strong[16] = {
        0x9b, 0xc1, 0x2a, 0xec, 0x4a, 0xf9, 0x0f, 0x14,
        0x0a, 0xed, 0xf6, 0xd3, 0xdc, 0xad, 0xf7, 0x0c };
925 926
    int i;

927
    result = derive_key(CALG_DES, &hKey, 0);
928 929
    if (!result) {
        /* rsaenh compiled without OpenSSL */
930
        ok(GetLastError()==NTE_BAD_ALGID, "%08x\n", GetLastError());
931 932 933 934 935
        return;
    }

    dwMode = CRYPT_MODE_ECB;
    result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
936
    ok(result, "%08x\n", GetLastError());
937 938 939
    
    dwLen = sizeof(DWORD);
    result = CryptGetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, &dwLen, 0);
940
    ok(result, "%08x\n", GetLastError());
941
    ok(dwMode == CRYPT_MODE_ECB, "Expected CRYPT_MODE_ECB, got %d\n", dwMode);
942 943 944 945
    
    for (i=0; i<sizeof(pbData); i++) pbData[i] = (unsigned char)i;
    
    dwLen = 13;
946
    result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, 16);
947
    ok(result, "%08x\n", GetLastError());
948
    
949 950
    ok(!memcmp(pbData, des, sizeof(des)), "DES encryption failed!\n");

951
    result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
952
    ok(result, "%08x\n", GetLastError());
953

954 955 956 957 958
    for (i=0; i<4; i++)
    {
      memcpy(pbData,cTestData[i].origstr,cTestData[i].strlen);

      dwLen = cTestData[i].enclen;
959
      result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, cTestData[i].buflen);
960 961
      ok(result, "%08x\n", GetLastError());
      ok(dwLen==cTestData[i].buflen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].buflen);
962
      memcpy(enc_data, pbData, cTestData[i].buflen);
963

964
      result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
965 966 967 968 969 970 971 972 973
      ok(result, "%08x\n", GetLastError());
      ok(dwLen==cTestData[i].enclen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].enclen);
      ok(memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen)==0,"decryption incorrect %d\n",i);
      if((dwLen != cTestData[i].enclen) ||
         memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen))
      {
          printBytes("expected",cTestData[i].decstr,cTestData[i].strlen);
          printBytes("got",pbData,dwLen);
      }
974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008

      /* Test bad data:
         Decrypting a block of bad data with Final = TRUE should restore the
         initial state of the key as well as decrypting a block of good data.
       */

      /* Changing key state by setting Final = FALSE */
      dwLen = cTestData[i].buflen;
      memcpy(pbData, enc_data, cTestData[i].buflen);
      result = CryptDecrypt(hKey, 0, FALSE, 0, pbData, &dwLen);
      ok(result, "%08x\n", GetLastError());

      /* Restoring key state by decrypting bad_data with Final = TRUE */
      memcpy(bad_data, enc_data, cTestData[i].buflen);
      bad_data[cTestData[i].buflen - 1] = ~bad_data[cTestData[i].buflen - 1];
      SetLastError(0xdeadbeef);
      result = CryptDecrypt(hKey, 0, TRUE, 0, bad_data, &dwLen);
      ok(!result, "CryptDecrypt should failed!\n");
      ok(GetLastError() == NTE_BAD_DATA, "%08x\n", GetLastError());
      ok(dwLen==cTestData[i].buflen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].buflen);
      ok(memcmp(pbData,cTestData[i].decstr,cTestData[1].enclen)==0,"decryption incorrect %d\n",i);

      /* Checking key state */
      dwLen = cTestData[i].buflen;
      memcpy(pbData, enc_data, cTestData[i].buflen);
      result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
      ok(result, "%08x\n", GetLastError());
      ok(dwLen==cTestData[i].enclen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].enclen);
      ok(memcmp(pbData,cTestData[i].decstr,cTestData[1].enclen)==0,"decryption incorrect %d\n",i);
      if((dwLen != cTestData[i].enclen) ||
         memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen))
      {
          printBytes("expected",cTestData[i].decstr,cTestData[i].strlen);
          printBytes("got",pbData,dwLen);
      }
1009 1010
    }

1011
    result = CryptDestroyKey(hKey);
1012
    ok(result, "%08x\n", GetLastError());
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025

    /* Windows >= XP changed the way DES keys are derived, this test ensures we don't break that */
    derive_key(CALG_DES, &hKey, 56);

    dwMode = CRYPT_MODE_ECB;
    result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
    ok(result, "%08x\n", GetLastError());

    for (i=0; i<sizeof(pbData); i++) pbData[i] = (unsigned char)i;

    dwLen = 13;
    result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, 16);
    ok(result, "%08x\n", GetLastError());
1026 1027 1028
    ok(!memcmp(pbData, des, sizeof(des)) || broken(
    !memcmp(pbData, des_old_behavior, sizeof(des)) ||
    (STRONG_PROV && !memcmp(pbData, des_old_strong, sizeof(des)))) /* <= 2000 */,
1029 1030 1031 1032
       "DES encryption failed!\n");

    result = CryptDestroyKey(hKey);
    ok(result, "%08x\n", GetLastError());
1033 1034
}

1035
static void test_3des(void)
1036 1037 1038 1039
{
    HCRYPTKEY hKey;
    BOOL result;
    DWORD dwLen;
1040
    unsigned char pbData[16], enc_data[16], bad_data[16];
1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051
    static const BYTE des3[16] = { 
        0x7b, 0xba, 0xdd, 0xa2, 0x39, 0xd3, 0x7b, 0xb3, 
        0xc7, 0x51, 0x81, 0x41, 0x53, 0xe8, 0xcf, 0xeb };
    int i;

    result = derive_key(CALG_3DES, &hKey, 0);
    if (!result) return;

    for (i=0; i<sizeof(pbData); i++) pbData[i] = (unsigned char)i;
    
    dwLen = 13;
1052
    result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, 16);
1053
    ok(result, "%08x\n", GetLastError());
1054

1055
    ok(!memcmp(pbData, des3, sizeof(des3)), "3DES encryption failed!\n");
1056 1057

    result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
1058
    ok(result, "%08x\n", GetLastError());
1059

1060 1061 1062 1063 1064
    for (i=0; i<4; i++)
    {
      memcpy(pbData,cTestData[i].origstr,cTestData[i].strlen);

      dwLen = cTestData[i].enclen;
1065
      result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, cTestData[i].buflen);
1066 1067
      ok(result, "%08x\n", GetLastError());
      ok(dwLen==cTestData[i].buflen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].buflen);
1068
      memcpy(enc_data, pbData, cTestData[i].buflen);
1069

1070
      result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
1071 1072 1073 1074 1075 1076 1077 1078 1079
      ok(result, "%08x\n", GetLastError());
      ok(dwLen==cTestData[i].enclen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].enclen);
      ok(memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen)==0,"decryption incorrect %d\n",i);
      if((dwLen != cTestData[i].enclen) ||
         memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen))
      {
          printBytes("expected",cTestData[i].decstr,cTestData[i].strlen);
          printBytes("got",pbData,dwLen);
      }
1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114

      /* Test bad data:
         Decrypting a block of bad data with Final = TRUE should restore the
         initial state of the key as well as decrypting a block of good data.
       */

      /* Changing key state by setting Final = FALSE */
      dwLen = cTestData[i].buflen;
      memcpy(pbData, enc_data, cTestData[i].buflen);
      result = CryptDecrypt(hKey, 0, FALSE, 0, pbData, &dwLen);
      ok(result, "%08x\n", GetLastError());

      /* Restoring key state by decrypting bad_data with Final = TRUE */
      memcpy(bad_data, enc_data, cTestData[i].buflen);
      bad_data[cTestData[i].buflen - 1] = ~bad_data[cTestData[i].buflen - 1];
      SetLastError(0xdeadbeef);
      result = CryptDecrypt(hKey, 0, TRUE, 0, bad_data, &dwLen);
      ok(!result, "CryptDecrypt should failed!\n");
      ok(GetLastError() == NTE_BAD_DATA, "%08x\n", GetLastError());
      ok(dwLen==cTestData[i].buflen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].buflen);
      ok(memcmp(pbData,cTestData[i].decstr,cTestData[1].enclen)==0,"decryption incorrect %d\n",i);

      /* Checking key state */
      dwLen = cTestData[i].buflen;
      memcpy(pbData, enc_data, cTestData[i].buflen);
      result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
      ok(result, "%08x\n", GetLastError());
      ok(dwLen==cTestData[i].enclen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].enclen);
      ok(memcmp(pbData,cTestData[i].decstr,cTestData[1].enclen)==0,"decryption incorrect %d\n",i);
      if((dwLen != cTestData[i].enclen) ||
         memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen))
      {
          printBytes("expected",cTestData[i].decstr,cTestData[i].strlen);
          printBytes("got",pbData,dwLen);
      }
1115
    }
1116
    result = CryptDestroyKey(hKey);
1117
    ok(result, "%08x\n", GetLastError());
1118 1119
}

1120 1121 1122 1123
static void test_aes(int keylen)
{
    HCRYPTKEY hKey;
    BOOL result;
1124
    DWORD dwLen, dwMode;
1125
    unsigned char pbData[48], enc_data[16], bad_data[16];
1126
    int i;
1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142
    static const BYTE aes_plain[32] = {
        "AES Test With 2 Blocks Of Data." };
    static const BYTE aes_cbc_enc[3][48] = {
    /* 128 bit key encrypted text */
    { 0xfe, 0x85, 0x3b, 0xe1, 0xf5, 0xe1, 0x58, 0x75, 0xd5, 0xa9, 0x74, 0xe3, 0x09, 0xea, 0xa5, 0x04,
      0x23, 0x35, 0xa2, 0x3b, 0x5c, 0xf1, 0x6c, 0x6f, 0xb9, 0xcd, 0x64, 0x06, 0x3e, 0x41, 0x83, 0xef,
      0x2a, 0xfe, 0xea, 0xb5, 0x6c, 0x17, 0x20, 0x79, 0x8c, 0x51, 0x3e, 0x56, 0xed, 0xe1, 0x47, 0x68 },
    /* 192 bit key encrypted text */
    { 0x6b, 0xf0, 0xfd, 0x32, 0xee, 0xc6, 0x06, 0x13, 0xa8, 0xe6, 0x3c, 0x81, 0x85, 0xb8, 0x2e, 0xa1,
      0xd4, 0x3b, 0xe8, 0x22, 0xa5, 0x74, 0x4a, 0xbe, 0x9d, 0xcf, 0xcc, 0x37, 0x26, 0x19, 0x5a, 0xd1,
      0x7f, 0x76, 0xbf, 0x94, 0x28, 0xce, 0x27, 0x21, 0x61, 0x87, 0xeb, 0xb9, 0x8b, 0xa8, 0xb4, 0x57 },
    /* 256 bit key encrypted text */
    { 0x20, 0x57, 0x17, 0x0b, 0x17, 0x76, 0xd8, 0x3b, 0x26, 0x90, 0x8b, 0x4c, 0xf2, 0x00, 0x79, 0x33,
      0x29, 0x2b, 0x13, 0x9c, 0xe2, 0x95, 0x09, 0xc1, 0xcd, 0x20, 0x87, 0x22, 0x32, 0x70, 0x9d, 0x75,
      0x9a, 0x94, 0xf5, 0x76, 0x5c, 0xb1, 0x62, 0x2c, 0xe1, 0x76, 0x7c, 0x86, 0x73, 0xe6, 0x7a, 0x23 }
    };
1143 1144 1145 1146
    switch (keylen)
    {
        case 256:
            result = derive_key(CALG_AES_256, &hKey, 0);
1147
            i = 2;
1148 1149 1150
            break;
        case 192:
            result = derive_key(CALG_AES_192, &hKey, 0);
1151
            i = 1;
1152 1153 1154 1155
            break;
        default:
        case 128:
            result = derive_key(CALG_AES_128, &hKey, 0);
1156
            i = 0;
1157 1158 1159 1160
            break;
    }
    if (!result) return;

1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
    dwLen = sizeof(aes_plain);
    memcpy(pbData, aes_plain, dwLen);
    result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, sizeof(pbData));
    ok(result, "Expected OK, got last error %d\n", GetLastError());
    ok(dwLen == 48, "Expected dwLen 48, got %d\n", dwLen);
    ok(!memcmp(aes_cbc_enc[i], pbData, dwLen), "Expected equal data sequences\n");

    result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
    ok(result && dwLen == 32 && !memcmp(aes_plain, pbData, dwLen),
       "%08x, dwLen: %d\n", GetLastError(), dwLen);

1172 1173
    for (i=0; i<sizeof(pbData); i++) pbData[i] = (unsigned char)i;

1174
    /* Does AES provider support salt? */
1175
    result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
1176 1177
    todo_wine ok(result || broken(GetLastError() == NTE_BAD_KEY), /* Vista or older */
       "Expected OK, got last error %d\n", GetLastError());
1178 1179
    if (result)
        ok(!dwLen, "unexpected salt length %d\n", dwLen);
1180

1181 1182 1183 1184 1185 1186 1187
    /* test default chaining mode */
    dwMode = 0xdeadbeef;
    dwLen = sizeof(dwMode);
    result = CryptGetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, &dwLen, 0);
    ok(result, "%08x\n", GetLastError());
    ok(dwMode == CRYPT_MODE_CBC, "Wrong default chaining\n");

1188
    dwLen = 13;
1189
    result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, 16);
1190 1191
    ok(result, "%08x\n", GetLastError());

1192
    result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
1193 1194 1195 1196 1197 1198 1199
    ok(result, "%08x\n", GetLastError());

    for (i=0; i<4; i++)
    {
      memcpy(pbData,cTestData[i].origstr,cTestData[i].strlen);

      dwLen = cTestData[i].enclen;
1200
      result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwLen, cTestData[i].buflen);
1201 1202
      ok(result, "%08x\n", GetLastError());
      ok(dwLen==cTestData[i].buflen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].buflen);
1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235
      memcpy(enc_data, pbData, cTestData[i].buflen);

      result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
      ok(result, "%08x\n", GetLastError());
      ok(dwLen==cTestData[i].enclen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].enclen);
      ok(memcmp(pbData,cTestData[i].decstr,cTestData[1].enclen)==0,"decryption incorrect %d\n",i);
      if((dwLen != cTestData[i].enclen) ||
         memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen))
      {
          printBytes("expected",cTestData[i].decstr,cTestData[i].strlen);
          printBytes("got",pbData,dwLen);
      }

      /* Test bad data:
         Decrypting a block of bad data with Final = TRUE should restore the
         initial state of the key as well as decrypting a block of good data.
       */

      /* Changing key state by setting Final = FALSE */
      dwLen = cTestData[i].buflen;
      memcpy(pbData, enc_data, cTestData[i].buflen);
      result = CryptDecrypt(hKey, 0, FALSE, 0, pbData, &dwLen);
      ok(result, "%08x\n", GetLastError());

      /* Restoring key state by decrypting bad_data with Final = TRUE */
      memcpy(bad_data, enc_data, cTestData[i].buflen);
      bad_data[cTestData[i].buflen - 1] = ~bad_data[cTestData[i].buflen - 1];
      SetLastError(0xdeadbeef);
      result = CryptDecrypt(hKey, 0, TRUE, 0, bad_data, &dwLen);
      ok(!result, "CryptDecrypt should failed!\n");
      ok(GetLastError() == NTE_BAD_DATA, "%08x\n", GetLastError());
      ok(dwLen==cTestData[i].buflen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].buflen);
      ok(memcmp(pbData,cTestData[i].decstr,cTestData[1].enclen)==0,"decryption incorrect %d\n",i);
1236

1237 1238 1239
      /* Checking key state */
      dwLen = cTestData[i].buflen;
      memcpy(pbData, enc_data, cTestData[i].buflen);
1240
      result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwLen);
1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254
      ok(result, "%08x\n", GetLastError());
      ok(dwLen==cTestData[i].enclen,"length incorrect, got %d, expected %d\n",dwLen,cTestData[i].enclen);
      ok(memcmp(pbData,cTestData[i].decstr,cTestData[1].enclen)==0,"decryption incorrect %d\n",i);
      if((dwLen != cTestData[i].enclen) ||
         memcmp(pbData,cTestData[i].decstr,cTestData[i].enclen))
      {
          printBytes("expected",cTestData[i].decstr,cTestData[i].strlen);
          printBytes("got",pbData,dwLen);
      }
    }
    result = CryptDestroyKey(hKey);
    ok(result, "%08x\n", GetLastError());
}

1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288
static void test_sha2(void)
{
    static const unsigned char sha256hash[32] = {
        0x10, 0xfc, 0x3c, 0x51, 0xa1, 0x52, 0xe9, 0x0e, 0x5b, 0x90,
        0x31, 0x9b, 0x60, 0x1d, 0x92, 0xcc, 0xf3, 0x72, 0x90, 0xef,
        0x53, 0xc3, 0x5f, 0xf9, 0x25, 0x07, 0x68, 0x7d, 0x8a, 0x91,
        0x1a, 0x08
    };
    static const unsigned char sha384hash[48] = {
        0x98, 0xd3, 0x3f, 0x89, 0x0b, 0x23, 0x33, 0x44, 0x61, 0x32,
        0x5a, 0x7c, 0xa3, 0x03, 0x89, 0xb5, 0x11, 0xd7, 0x41, 0xc8,
        0x54, 0x6b, 0x12, 0x0c, 0x40, 0x15, 0xb6, 0x2a, 0x03, 0x43,
        0xe5, 0x64, 0x7f, 0x10, 0x1e, 0xae, 0x47, 0xa9, 0x39, 0x05,
        0x6f, 0x40, 0x60, 0x94, 0xd6, 0xad, 0x80, 0x55
    };
    static const unsigned char sha512hash[64] = {
        0x37, 0x86, 0x0e, 0x7d, 0x25, 0xd9, 0xf9, 0x84, 0x3e, 0x3d,
        0xc7, 0x13, 0x95, 0x73, 0x42, 0x04, 0xfd, 0x13, 0xad, 0x23,
        0x39, 0x16, 0x32, 0x5f, 0x99, 0x3e, 0x3c, 0xee, 0x3f, 0x11,
        0x36, 0xf9, 0xc9, 0x66, 0x08, 0x70, 0xcc, 0x49, 0xd8, 0xe0,
        0x7d, 0xa1, 0x57, 0x62, 0x71, 0xa6, 0xc9, 0xa4, 0x24, 0x60,
        0xfc, 0xde, 0x9d, 0xb2, 0xf1, 0xd2, 0xc2, 0xfb, 0x2d, 0xbf,
        0xb7, 0xf4, 0x81, 0xd4
    };
    unsigned char pbData[2048];
    BOOL result;
    HCRYPTHASH hHash;
    BYTE pbHashValue[64];
    DWORD hashlen, len;
    int i;

    for (i=0; i<2048; i++) pbData[i] = (unsigned char)i;

    /* SHA-256 hash */
1289
    SetLastError(0xdeadbeef);
1290
    result = CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash);
1291 1292 1293 1294
    if (!result && GetLastError() == NTE_BAD_ALGID) {
        win_skip("SHA-256/384/512 hashes are not supported before Windows XP SP3\n");
        return;
    }
1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356
    ok(result, "%08x\n", GetLastError());
    if (result) {
        len = sizeof(DWORD);
        result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
        ok(result && (hashlen == 32), "%08x, hashlen: %d\n", GetLastError(), hashlen);

        result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
        ok(result, "%08x\n", GetLastError());

        len = 32;
        result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
        ok(result, "%08x\n", GetLastError());

        ok(!memcmp(pbHashValue, sha256hash, 32), "Wrong SHA-256 hash!\n");

        result = CryptDestroyHash(hHash);
        ok(result, "%08x\n", GetLastError());
    }

    /* SHA-384 hash */
    result = CryptCreateHash(hProv, CALG_SHA_384, 0, 0, &hHash);
    ok(result, "%08x\n", GetLastError());
    if (result) {
        len = sizeof(DWORD);
        result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
        ok(result && (hashlen == 48), "%08x, hashlen: %d\n", GetLastError(), hashlen);

        result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
        ok(result, "%08x\n", GetLastError());

        len = 48;
        result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
        ok(result, "%08x\n", GetLastError());

        ok(!memcmp(pbHashValue, sha384hash, 48), "Wrong SHA-384 hash!\n");

        result = CryptDestroyHash(hHash);
        ok(result, "%08x\n", GetLastError());
    }

    /* SHA-512 hash */
    result = CryptCreateHash(hProv, CALG_SHA_512, 0, 0, &hHash);
    ok(result, "%08x\n", GetLastError());
    if (result) {
        len = sizeof(DWORD);
        result = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashlen, &len, 0);
        ok(result && (hashlen == 64), "%08x, hashlen: %d\n", GetLastError(), hashlen);

        result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
        ok(result, "%08x\n", GetLastError());

        len = 64;
        result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &len, 0);
        ok(result, "%08x\n", GetLastError());

        ok(!memcmp(pbHashValue, sha512hash, 64), "Wrong SHA-512 hash!\n");

        result = CryptDestroyHash(hHash);
        ok(result, "%08x\n", GetLastError());
    }
}

1357
static void test_rc2(void)
1358
{
1359 1360 1361
    static const BYTE rc2_40_encrypted[16] = {
        0xc0, 0x9a, 0xe4, 0x2f, 0x0a, 0x47, 0x67, 0x11,
        0xfb, 0x18, 0x87, 0xce, 0x0c, 0x75, 0x07, 0xb1 };
1362
    static const BYTE rc2_128_encrypted[] = {
1363 1364 1365 1366 1367
        0x82,0x81,0xf7,0xff,0xdd,0xd7,0x88,0x8c,
        0x2a,0x2a,0xc0,0xce,0x4c,0x89,0xb6,0x66 };
    static const BYTE rc2_40def_encrypted[] = {
        0x23,0xc8,0x70,0x13,0x42,0x2e,0xa8,0x98,
        0x5c,0xdf,0x7a,0x9b,0xea,0xdb,0x96,0x1b };
1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379
    static const BYTE rc2_40_salt_enh[24] = {
        0xA3, 0xD7, 0x41, 0x87, 0x7A, 0xD0, 0x18, 0xDB,
        0xD4, 0x6A, 0x4F, 0xEE, 0xF3, 0xCA, 0xCD, 0x34,
        0xB3, 0x15, 0x9A, 0x2A, 0x88, 0x5F, 0x43, 0xA5 };
    static const BYTE rc2_40_salt_base[24] = {
        0x8C, 0x4E, 0xA6, 0x00, 0x9B, 0x15, 0xEF, 0x9E,
        0x88, 0x81, 0xD0, 0x65, 0xD6, 0x53, 0x57, 0x08,
        0x0A, 0x77, 0x80, 0xFA, 0x7E, 0x89, 0x14, 0x55 };
    static const BYTE rc2_40_salt_strong[24] = {
        0xB9, 0x33, 0xB6, 0x7A, 0x35, 0xC3, 0x06, 0x88,
        0xBF, 0xD5, 0xCC, 0xAF, 0x14, 0xAE, 0xE2, 0x31,
        0xC6, 0x9A, 0xAA, 0x3F, 0x05, 0x2F, 0x22, 0xDA };
1380 1381 1382
    HCRYPTHASH hHash;
    HCRYPTKEY hKey;
    BOOL result;
1383
    DWORD dwLen, dwKeyLen, dwDataLen, dwMode, dwModeBits, error;
1384
    unsigned char pbData[2000], pbHashValue[16], pszBuffer[256];
1385 1386 1387 1388 1389 1390 1391
    int i;
    
    for (i=0; i<2000; i++) pbData[i] = (unsigned char)i;

    /* MD2 Hashing */
    result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
    if (!result) {
1392
        ok(GetLastError()==NTE_BAD_ALGID, "%08x\n", GetLastError());
1393
    } else {
1394 1395
        CRYPT_INTEGER_BLOB salt;

1396
        result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
1397
        ok(result, "%08x\n", GetLastError());
1398 1399 1400

        dwLen = 16;
        result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &dwLen, 0);
1401
        ok(result, "%08x\n", GetLastError());
1402

1403
        result = CryptDeriveKey(hProv, CALG_RC2, hHash, 40 << 16, &hKey);
1404
        ok(result, "%08x\n", GetLastError());
1405 1406 1407

        dwLen = sizeof(DWORD);
        result = CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE*)&dwKeyLen, &dwLen, 0);
1408
        ok(result, "%08x\n", GetLastError());
1409

1410 1411 1412 1413 1414 1415 1416
        /* test default chaining mode */
        dwMode = 0xdeadbeef;
        dwLen = sizeof(dwMode);
        result = CryptGetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, &dwLen, 0);
        ok(result, "%08x\n", GetLastError());
        ok(dwMode == CRYPT_MODE_CBC, "Wrong default chaining mode\n");

1417 1418
        dwMode = CRYPT_MODE_CBC;
        result = CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0);
1419
        ok(result, "%08x\n", GetLastError());
1420 1421 1422

        dwLen = sizeof(DWORD);
        result = CryptGetKeyParam(hKey, KP_MODE_BITS, (BYTE*)&dwModeBits, &dwLen, 0);
1423
        ok(result, "%08x\n", GetLastError());
1424

1425 1426 1427 1428 1429
        dwModeBits = 0xdeadbeef;
        dwLen = sizeof(DWORD);
        result = CryptGetKeyParam(hKey, KP_PERMISSIONS, (BYTE*)&dwModeBits, &dwLen, 0);
        ok(result, "%08x\n", GetLastError());
        ok(dwModeBits ==
1430 1431
            (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
            broken(dwModeBits == 0xffffffff), /* Win9x/NT4 */
1432 1433 1434
            "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
            " got %08x\n", dwModeBits);

1435 1436
        dwLen = sizeof(DWORD);
        result = CryptGetKeyParam(hKey, KP_PERMISSIONS, (BYTE*)&dwModeBits, &dwLen, 0);
1437
        ok(result, "%08x\n", GetLastError());
1438 1439 1440

        dwLen = sizeof(DWORD);
        result = CryptGetKeyParam(hKey, KP_BLOCKLEN, (BYTE*)&dwModeBits, &dwLen, 0);
1441
        ok(result, "%08x\n", GetLastError());
1442
        ok(dwLen == 4, "Expected 4, got %d\n", dwLen);
1443

1444
        dwLen = 0;
1445
        result = CryptGetKeyParam(hKey, KP_IV, NULL, &dwLen, 0);
1446
        ok(result, "%08x\n", GetLastError());
1447 1448 1449
        result = CryptGetKeyParam(hKey, KP_IV, pszBuffer, &dwLen, 0);
        ok(result, "%08x\n", GetLastError());
        ok(dwLen == 8, "Expected 8, got %d\n", dwLen);
1450

1451
        dwLen = 0;
1452
        result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
1453
        ok(result, "%08x\n", GetLastError());
1454 1455 1456
        /* The default salt length is always 11... */
        ok(dwLen == 11, "unexpected salt length %d\n", dwLen);
        /* and the default salt is always empty. */
1457 1458
        result = CryptGetKeyParam(hKey, KP_SALT, pszBuffer, &dwLen, 0);
        ok(result, "%08x\n", GetLastError());
1459
        for (i=0; i<dwLen; i++)
1460
            ok(!pszBuffer[i], "unexpected salt value %02x @ %d\n", pszBuffer[i], i);
1461 1462

        dwLen = sizeof(DWORD);
1463 1464 1465
        result = CryptGetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, &dwLen, 0);
        ok(result, "%08x\n", GetLastError());
        ok(dwMode == CRYPT_MODE_CBC, "Expected CRYPT_MODE_CBC, got %d\n", dwMode);
1466 1467

        result = CryptDestroyHash(hHash);
1468
        ok(result, "%08x\n", GetLastError());
1469 1470

        dwDataLen = 13;
1471
        result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen, 24);
1472
        ok(result, "%08x\n", GetLastError());
1473

1474
        ok(!memcmp(pbData, rc2_40_encrypted, 16), "RC2 encryption failed!\n");
1475

1476
        dwLen = 0;
1477
        result = CryptGetKeyParam(hKey, KP_IV, NULL, &dwLen, 0);
1478
        ok(result, "%08x\n", GetLastError());
1479 1480
        result = CryptGetKeyParam(hKey, KP_IV, pszBuffer, &dwLen, 0);
        ok(result, "%08x\n", GetLastError());
1481

1482
        result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen);
1483
        ok(result, "%08x\n", GetLastError());
1484

1485
        /* Setting the salt value will not reset the salt length in base or strong providers */
1486 1487 1488 1489 1490
        result = CryptSetKeyParam(hKey, KP_SALT, pbData, 0);
        ok(result, "setting salt failed: %08x\n", GetLastError());
        dwLen = 0;
        result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
        ok(result, "%08x\n", GetLastError());
1491 1492 1493 1494
        if (BASE_PROV || STRONG_PROV)
            ok(dwLen == 11, "expected salt length 11, got %d\n", dwLen);
        else
            ok(dwLen == 0 || broken(nt4 && dwLen == 11), "expected salt length 0, got %d\n", dwLen);
1495 1496 1497 1498 1499 1500 1501
        /* What sizes salt can I set? */
        salt.pbData = pbData;
        for (i=0; i<24; i++)
        {
            salt.cbData = i;
            result = CryptSetKeyParam(hKey, KP_SALT_EX, (BYTE *)&salt, 0);
            ok(result, "setting salt failed for size %d: %08x\n", i, GetLastError());
1502 1503 1504 1505
            /* The returned salt length is the same as the set salt length */
            result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
            ok(result, "%08x\n", GetLastError());
            ok(dwLen == i, "size %d: unexpected salt length %d\n", i, dwLen);
1506 1507
        }
        salt.cbData = 25;
1508
        SetLastError(0xdeadbeef);
1509
        result = CryptSetKeyParam(hKey, KP_SALT_EX, (BYTE *)&salt, 0);
1510 1511 1512
        ok(!result ||
           broken(result), /* Win9x, WinMe, NT4, W2K */
           "%08x\n", GetLastError());
1513

1514
        result = CryptDestroyKey(hKey);
1515
        ok(result, "%08x\n", GetLastError());
1516
    }
1517 1518 1519 1520 1521 1522 1523 1524

    /* Again, but test setting the effective key len */
    for (i=0; i<2000; i++) pbData[i] = (unsigned char)i;

    result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
    if (!result) {
        ok(GetLastError()==NTE_BAD_ALGID, "%08x\n", GetLastError());
    } else {
1525
        result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544
        ok(result, "%08x\n", GetLastError());

        dwLen = 16;
        result = CryptGetHashParam(hHash, HP_HASHVAL, pbHashValue, &dwLen, 0);
        ok(result, "%08x\n", GetLastError());

        result = CryptDeriveKey(hProv, CALG_RC2, hHash, 56 << 16, &hKey);
        ok(result, "%08x\n", GetLastError());

        SetLastError(0xdeadbeef);
        result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, NULL, 0);
        ok(!result && GetLastError()==ERROR_INVALID_PARAMETER, "%08x\n", GetLastError());
        dwKeyLen = 0;
        SetLastError(0xdeadbeef);
        result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (LPBYTE)&dwKeyLen, 0);
        ok(!result && GetLastError()==NTE_BAD_DATA, "%08x\n", GetLastError());
        dwKeyLen = 1025;
        SetLastError(0xdeadbeef);
        result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (LPBYTE)&dwKeyLen, 0);
1545
        ok(!result, "CryptSetKeyParam failed: %08x\n", GetLastError());
1546 1547

        dwLen = sizeof(dwKeyLen);
1548
        result = CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE *)&dwKeyLen, &dwLen, 0);
1549
        ok(result, "%08x\n", GetLastError());
1550
        ok(dwKeyLen == 56, "%d (%08x)\n", dwKeyLen, GetLastError());
1551
        result = CryptGetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (BYTE *)&dwKeyLen, &dwLen, 0);
1552
        ok(result, "%08x\n", GetLastError());
1553
        ok(dwKeyLen == 56 || broken(dwKeyLen == 40), "%d (%08x)\n", dwKeyLen, GetLastError());
1554 1555

        dwKeyLen = 128;
1556
        SetLastError(0xdeadbeef);
1557
        result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (LPBYTE)&dwKeyLen, 0);
1558
        if (!BASE_PROV)
1559 1560
        {
            dwKeyLen = 12345;
1561
            ok(result, "expected success, got error 0x%08X\n", GetLastError());
1562
            result = CryptGetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (BYTE *)&dwKeyLen, &dwLen, 0);
1563
            ok(result, "%08x\n", GetLastError());
1564 1565
            ok(dwKeyLen == 128, "Expected 128, got %d\n", dwKeyLen);
        }
1566
        else
1567
        {
1568
            ok(!result, "expected error\n");
1569
            ok(GetLastError() == NTE_BAD_DATA, "Expected 0x80009005, got 0x%08X\n", GetLastError());
1570
            result = CryptGetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (BYTE *)&dwKeyLen, &dwLen, 0);
1571
            ok(result, "%08x\n", GetLastError());
1572
            ok(dwKeyLen == 40, "Expected 40, got %d\n", dwKeyLen);
1573
        }
1574 1575

        dwLen = sizeof(dwKeyLen);
1576
        result = CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE *)&dwKeyLen, &dwLen, 0);
1577
        ok(result, "%08x\n", GetLastError());
1578
        ok(dwKeyLen == 56, "%d (%08x)\n", dwKeyLen, GetLastError());
1579
        result = CryptGetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (BYTE *)&dwKeyLen, &dwLen, 0);
1580
        ok(result, "%08x\n", GetLastError());
1581 1582
        ok((!BASE_PROV && dwKeyLen == 128) || (BASE_PROV && dwKeyLen == 40),
           "%d (%08x)\n", dwKeyLen, GetLastError());
1583 1584 1585 1586 1587

        result = CryptDestroyHash(hHash);
        ok(result, "%08x\n", GetLastError());

        dwDataLen = 13;
1588
        result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen, 24);
1589
        ok(result, "%08x\n", GetLastError());
1590 1591
        ok(!memcmp(pbData, !BASE_PROV ? rc2_128_encrypted : rc2_40def_encrypted,
           sizeof(rc2_128_encrypted)), "RC2 encryption failed!\n");
1592 1593 1594 1595 1596 1597 1598 1599

        /* Oddly enough this succeeds, though it should have no effect */
        dwKeyLen = 40;
        result = CryptSetKeyParam(hKey, KP_EFFECTIVE_KEYLEN, (LPBYTE)&dwKeyLen, 0);
        ok(result, "%d\n", GetLastError());

        result = CryptDestroyKey(hKey);
        ok(result, "%08x\n", GetLastError());
1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647

        /* Test a 40 bit key with salt */
        result = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
        ok(result, "%08x\n", GetLastError());

        result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
        ok(result, "%08x\n", GetLastError());

        result = CryptDeriveKey(hProv, CALG_RC2, hHash, (40<<16)|CRYPT_CREATE_SALT, &hKey);
        ok(result, "%08x\n", GetLastError());

        dwDataLen = 16;
        memset(pbData, 0xAF, dwDataLen);
        SetLastError(0xdeadbeef);
        result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen, 24);
        if(result)
        {
            ok((ENHANCED_PROV && !memcmp(pbData, rc2_40_salt_enh, dwDataLen)) ||
               (STRONG_PROV && !memcmp(pbData, rc2_40_salt_strong, dwDataLen)) ||
               (BASE_PROV && !memcmp(pbData, rc2_40_salt_base, dwDataLen)),
               "RC2 encryption failed!\n");
        }
        else /* <= XP */
        {
            error = GetLastError();
            ok(error == NTE_BAD_DATA || broken(error == NTE_DOUBLE_ENCRYPT),
               "Expected 0x80009005, got 0x%08X\n", error);
        }
        dwLen = sizeof(DWORD);
        dwKeyLen = 12345;
        result = CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE*)&dwKeyLen, &dwLen, 0);
        ok(result, "%08x\n", GetLastError());
        ok(dwKeyLen == 40, "Expected 40, got %d\n", dwKeyLen);

        dwLen = sizeof(pszBuffer);
        memset(pszBuffer, 0xAF, dwLen);
        result = CryptGetKeyParam(hKey, KP_SALT, pszBuffer, &dwLen, 0);
        ok(result, "%08x\n", GetLastError());
        if (!ENHANCED_PROV)
            ok(dwLen == 11, "Expected 11, got %d\n", dwLen);
        else
            ok(dwLen == 0, "Expected 0, got %d\n", dwLen);

        result = CryptDestroyKey(hKey);
        ok(result, "%08x\n", GetLastError());

        result = CryptDestroyHash(hHash);
        ok(result, "%08x\n", GetLastError());
1648
    }
1649 1650
}

1651
static void test_rc4(void)
1652 1653 1654 1655
{
    static const BYTE rc4[16] = { 
        0x17, 0x0c, 0x44, 0x8e, 0xae, 0x90, 0xcd, 0xb0, 
        0x7f, 0x87, 0xf5, 0x7a, 0xec, 0xb2, 0x2e, 0x35 };    
1656 1657 1658 1659 1660 1661
    static const BYTE rc4_40_salt[16] = {
        0x41, 0xE6, 0x33, 0xC9, 0x50, 0xA1, 0xBF, 0x88,
        0x12, 0x4D, 0xD3, 0xE3, 0x47, 0x88, 0x6D, 0xA5 };
    static const BYTE rc4_40_salt_base[16] = {
        0x2F, 0xAC, 0xEA, 0xEA, 0xFF, 0x68, 0x7E, 0x77,
        0xF4, 0xB9, 0x48, 0x7C, 0x4E, 0x79, 0xA6, 0xB5 };
1662 1663 1664 1665
    BOOL result;
    HCRYPTHASH hHash;
    HCRYPTKEY hKey;
    DWORD dwDataLen = 5, dwKeyLen, dwLen = sizeof(DWORD), dwMode;
1666
    unsigned char pbData[2000];
1667 1668 1669 1670 1671 1672 1673 1674 1675
    unsigned char pszBuffer[256];
    int i;

    for (i=0; i<2000; i++) pbData[i] = (unsigned char)i;

    /* MD2 Hashing */
    result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
    if (!result) {
        /* rsaenh compiled without OpenSSL */
1676
        ok(GetLastError() == NTE_BAD_ALGID, "%08x\n", GetLastError());
1677
    } else {
1678 1679
        CRYPT_INTEGER_BLOB salt;

1680
        result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
1681
           ok(result, "%08x\n", GetLastError());
1682 1683 1684

        dwLen = 16;
        result = CryptGetHashParam(hHash, HP_HASHVAL, pszBuffer, &dwLen, 0);
1685
        ok(result, "%08x\n", GetLastError());
1686 1687

        result = CryptDeriveKey(hProv, CALG_RC4, hHash, 56 << 16, &hKey);
1688
        ok(result, "%08x\n", GetLastError());
1689 1690 1691

        dwLen = sizeof(DWORD);
        result = CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE*)&dwKeyLen, &dwLen, 0);
1692
        ok(result, "%08x\n", GetLastError());
1693
        ok(dwKeyLen == 56, "Expected 56, got %d\n", dwKeyLen);
1694 1695 1696

        dwLen = sizeof(DWORD);
        result = CryptGetKeyParam(hKey, KP_BLOCKLEN, (BYTE*)&dwKeyLen, &dwLen, 0);
1697
        ok(result, "%08x\n", GetLastError());
1698
        ok(dwKeyLen == 0, "Expected 0, got %d\n", dwKeyLen);
1699

1700
        dwLen = 0;
1701
        result = CryptGetKeyParam(hKey, KP_IV, NULL, &dwLen, 0);
1702
        ok(result, "%08x\n", GetLastError());
1703
        result = CryptGetKeyParam(hKey, KP_IV, pszBuffer, &dwLen, 0);
1704

1705
        dwLen = 0;
1706
        result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
1707
        ok(result, "%08x\n", GetLastError());
1708 1709
        result = CryptGetKeyParam(hKey, KP_SALT, pszBuffer, &dwLen, 0);
        ok(result, "%08x\n", GetLastError());
1710 1711

        dwLen = sizeof(DWORD);
1712 1713 1714 1715
        result = CryptGetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, &dwLen, 0);
        ok(result, "%08x\n", GetLastError());
        ok(dwMode == 0 || broken(dwMode == CRYPT_MODE_CBC) /* <= 2000 */,
           "Expected 0, got %d\n", dwMode);
1716 1717

        result = CryptDestroyHash(hHash);
1718
        ok(result, "%08x\n", GetLastError());
1719

1720
        dwDataLen = 16;
1721
        result = CryptEncrypt(hKey, 0, TRUE, 0, NULL, &dwDataLen, 24);
1722
        ok(result, "%08x\n", GetLastError());
1723
        dwDataLen = 16;
1724
        result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen, 24);
1725
        ok(result, "%08x\n", GetLastError());
1726 1727 1728

        ok(!memcmp(pbData, rc4, dwDataLen), "RC4 encryption failed!\n");

1729
        result = CryptDecrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen);
1730
        ok(result, "%08x\n", GetLastError());
1731

1732
        /* Setting the salt value will not reset the salt length in base or strong providers */
1733 1734 1735 1736 1737
        result = CryptSetKeyParam(hKey, KP_SALT, pbData, 0);
        ok(result, "setting salt failed: %08x\n", GetLastError());
        dwLen = 0;
        result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
        ok(result, "%08x\n", GetLastError());
1738
        if (BASE_PROV || STRONG_PROV)
1739 1740 1741
            ok(dwLen == 11, "expected salt length 11, got %d\n", dwLen);
        else
            ok(dwLen == 0 || broken(nt4 && dwLen == 11), "expected salt length 0, got %d\n", dwLen);
1742 1743 1744 1745 1746 1747 1748
        /* What sizes salt can I set? */
        salt.pbData = pbData;
        for (i=0; i<24; i++)
        {
            salt.cbData = i;
            result = CryptSetKeyParam(hKey, KP_SALT_EX, (BYTE *)&salt, 0);
            ok(result, "setting salt failed for size %d: %08x\n", i, GetLastError());
1749 1750 1751 1752
            /* The returned salt length is the same as the set salt length */
            result = CryptGetKeyParam(hKey, KP_SALT, NULL, &dwLen, 0);
            ok(result, "%08x\n", GetLastError());
            ok(dwLen == i, "size %d: unexpected salt length %d\n", i, dwLen);
1753 1754
        }
        salt.cbData = 25;
1755
        SetLastError(0xdeadbeef);
1756
        result = CryptSetKeyParam(hKey, KP_SALT_EX, (BYTE *)&salt, 0);
1757 1758 1759
        ok(!result ||
           broken(result), /* Win9x, WinMe, NT4, W2K */
           "%08x\n", GetLastError());
1760

1761
        result = CryptDestroyKey(hKey);
1762
        ok(result, "%08x\n", GetLastError());
1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801

        /* Test a 40 bit key with salt */
        result = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
        ok(result, "%08x\n", GetLastError());

        result = CryptHashData(hHash, pbData, sizeof(pbData), 0);
        ok(result, "%08x\n", GetLastError());

        result = CryptDeriveKey(hProv, CALG_RC4, hHash, (40<<16)|CRYPT_CREATE_SALT, &hKey);
        ok(result, "%08x\n", GetLastError());
        dwDataLen = 16;
        memset(pbData, 0xAF, dwDataLen);
        SetLastError(0xdeadbeef);
        result = CryptEncrypt(hKey, 0, TRUE, 0, pbData, &dwDataLen, 24);
        ok(result, "%08x\n", GetLastError());
        ok((ENHANCED_PROV && !memcmp(pbData, rc4_40_salt, dwDataLen)) ||
           (!ENHANCED_PROV && !memcmp(pbData, rc4_40_salt_base, dwDataLen)),
           "RC4 encryption failed!\n");

        dwLen = sizeof(DWORD);
        dwKeyLen = 12345;
        result = CryptGetKeyParam(hKey, KP_KEYLEN, (BYTE*)&dwKeyLen, &dwLen, 0);
        ok(result, "%08x\n", GetLastError());
        ok(dwKeyLen == 40, "Expected 40, got %d\n", dwKeyLen);

        dwLen = sizeof(pszBuffer);
        memset(pszBuffer, 0xAF, dwLen);
        result = CryptGetKeyParam(hKey, KP_SALT, pszBuffer, &dwLen, 0);
        ok(result, "%08x\n", GetLastError());
        if (!ENHANCED_PROV)
            ok(dwLen == 11, "Expected 11, got %d\n", dwLen);
        else
            ok(dwLen == 0, "Expected 0, got %d\n", dwLen);

        result = CryptDestroyKey(hKey);
        ok(result, "%08x\n", GetLastError());

        result = CryptDestroyHash(hHash);
        ok(result, "%08x\n", GetLastError());
1802 1803 1804
    }
}

1805
static void test_hmac(void) {
1806 1807 1808
    HCRYPTKEY hKey;
    HCRYPTHASH hHash;
    BOOL result;
1809 1810
    /* Using CALG_MD2 here fails on Windows 2003, why ? */
    HMAC_INFO hmacInfo = { CALG_MD5, NULL, 0, NULL, 0 };
1811 1812 1813
    DWORD dwLen;
    BYTE abData[256];
    static const BYTE hmac[16] = { 
1814 1815
        0x1a, 0x7d, 0x49, 0xc5, 0x9b, 0x2d, 0x0b, 0x9c, 
        0xcf, 0x10, 0x6b, 0xb6, 0x7d, 0x0f, 0x13, 0x32 };
1816 1817
    int i;

1818
    for (i=0; i < ARRAY_SIZE(abData); i++) abData[i] = (BYTE)i;
1819 1820 1821 1822

    if (!derive_key(CALG_RC2, &hKey, 56)) return;

    result = CryptCreateHash(hProv, CALG_HMAC, hKey, 0, &hHash);
1823
    ok(result, "%08x\n", GetLastError());
1824 1825 1826
    if (!result) return;

    result = CryptSetHashParam(hHash, HP_HMAC_INFO, (BYTE*)&hmacInfo, 0);
1827
    ok(result, "%08x\n", GetLastError());
1828

1829
    result = CryptHashData(hHash, abData, sizeof(abData), 0);
1830
    ok(result, "%08x\n", GetLastError());
1831

1832
    dwLen = ARRAY_SIZE(abData);
1833
    result = CryptGetHashParam(hHash, HP_HASHVAL, abData, &dwLen, 0);
1834
    ok(result, "%08x\n", GetLastError());
1835 1836 1837 1838

    ok(!memcmp(abData, hmac, sizeof(hmac)), "HMAC failed!\n");
    
    result = CryptDestroyHash(hHash);
1839
    ok(result, "%08x\n", GetLastError());
1840 1841
    
    result = CryptDestroyKey(hKey);
1842
    ok(result, "%08x\n", GetLastError());
1843 1844 1845

    /* Provoke errors */
    result = CryptCreateHash(hProv, CALG_HMAC, 0, 0, &hHash);
1846
    ok(!result && GetLastError() == NTE_BAD_KEY, "%08x\n", GetLastError());
1847 1848
}

1849
static void test_mac(void) {
1850 1851 1852 1853 1854
    HCRYPTKEY hKey;
    HCRYPTHASH hHash;
    BOOL result;
    DWORD dwLen;
    BYTE abData[256], abEnc[264];
1855
    static const BYTE mac_40[8] = { 0xb7, 0xa2, 0x46, 0xe9, 0x11, 0x31, 0xe0, 0xad};
1856 1857
    int i;

1858 1859
    for (i=0; i < ARRAY_SIZE(abData); i++) abData[i] = (BYTE)i;
    for (i=0; i < ARRAY_SIZE(abData); i++) abEnc[i] = (BYTE)i;
1860

1861
    if (!derive_key(CALG_RC2, &hKey, 40)) return;
1862 1863

    dwLen = 256;
1864
    result = CryptEncrypt(hKey, 0, TRUE, 0, abEnc, &dwLen, 264);
1865
    ok (result && dwLen == 264, "%08x, dwLen: %d\n", GetLastError(), dwLen);
1866 1867
    
    result = CryptCreateHash(hProv, CALG_MAC, hKey, 0, &hHash);
1868
    ok(result, "%08x\n", GetLastError());
1869 1870
    if (!result) return;

1871
    result = CryptHashData(hHash, abData, sizeof(abData), 0);
1872
    ok(result, "%08x\n", GetLastError());
1873

1874
    dwLen = ARRAY_SIZE(abData);
1875
    result = CryptGetHashParam(hHash, HP_HASHVAL, abData, &dwLen, 0);
1876
    ok(result && dwLen == 8, "%08x, dwLen: %d\n", GetLastError(), dwLen);
1877

1878
    ok(!memcmp(abData, mac_40, sizeof(mac_40)), "MAC failed!\n");
1879 1880
    
    result = CryptDestroyHash(hHash);
1881
    ok(result, "%08x\n", GetLastError());
1882 1883
    
    result = CryptDestroyKey(hKey);
1884
    ok(result, "%08x\n", GetLastError());
1885 1886 1887 1888
    
    /* Provoke errors */
    if (!derive_key(CALG_RC4, &hKey, 56)) return;

1889
    SetLastError(0xdeadbeef);
1890
    result = CryptCreateHash(hProv, CALG_MAC, hKey, 0, &hHash);
1891 1892
    ok((!result && GetLastError() == NTE_BAD_KEY) ||
            broken(result), /* Win9x, WinMe, NT4, W2K */
1893
            "%08x\n", GetLastError());
1894 1895

    result = CryptDestroyKey(hKey);
1896
    ok(result, "%08x\n", GetLastError());
1897 1898
}

1899
static void test_import_private(void) 
1900
{
1901
    DWORD dwLen, dwVal;
1902 1903
    HCRYPTKEY hKeyExchangeKey, hSessionKey;
    BOOL result;
1904
    static BYTE abSessionKey[148] = {
1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923
        0x01, 0x02, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00,
        0x00, 0xa4, 0x00, 0x00, 0xb8, 0xa4, 0xdf, 0x5e,
        0x9e, 0xb1, 0xbf, 0x85, 0x3d, 0x24, 0x2d, 0x1e,
        0x69, 0xb7, 0x67, 0x13, 0x8e, 0x78, 0xf2, 0xdf,
        0xc6, 0x69, 0xce, 0x46, 0x7e, 0xf2, 0xf2, 0x33,
        0x20, 0x6f, 0xa1, 0xa5, 0x59, 0x83, 0x25, 0xcb,
        0x3a, 0xb1, 0x8a, 0x12, 0x63, 0x02, 0x3c, 0xfb,
        0x4a, 0xfa, 0xef, 0x8e, 0xf7, 0x29, 0x57, 0xb1,
        0x9e, 0xa7, 0xf3, 0x02, 0xfd, 0xca, 0xdf, 0x5a,
        0x1f, 0x71, 0xb6, 0x26, 0x09, 0x24, 0x39, 0xda,
        0xc0, 0xde, 0x2a, 0x0e, 0xcd, 0x1f, 0xe5, 0xb6,
        0x4f, 0x82, 0xa0, 0xa9, 0x90, 0xd3, 0xd9, 0x6a,
        0x43, 0x14, 0x2a, 0xf7, 0xac, 0xd5, 0xa0, 0x54,
        0x93, 0xc4, 0xb9, 0xe7, 0x24, 0x84, 0x4d, 0x69,
        0x5e, 0xcc, 0x2a, 0x32, 0xb5, 0xfb, 0xe4, 0xb4,
        0x08, 0xd5, 0x36, 0x58, 0x59, 0x40, 0xfb, 0x29,
        0x7f, 0xa7, 0x17, 0x25, 0xc4, 0x0d, 0x78, 0x37,
        0x04, 0x8c, 0x49, 0x92
    };
1924
    static BYTE abEncryptedMessage[12] = {
1925 1926 1927
        0x40, 0x64, 0x28, 0xe8, 0x8a, 0xe7, 0xa4, 0xd4,
        0x1c, 0xfd, 0xde, 0x71
    };
1928 1929 1930
    BLOBHEADER *blobHeader = (BLOBHEADER *)abPlainPrivateKey;
    RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(blobHeader+1);

1931 1932 1933 1934
    dwLen = (DWORD)sizeof(abPlainPrivateKey);
    result = CryptImportKey(hProv, abPlainPrivateKey, dwLen, 0, 0, &hKeyExchangeKey);
    if (!result) {
        /* rsaenh compiled without OpenSSL */
1935
        ok(GetLastError() == NTE_FAIL, "%08x\n", GetLastError());
1936 1937 1938 1939 1940
        return;
    }

    dwLen = (DWORD)sizeof(abSessionKey);
    result = CryptImportKey(hProv, abSessionKey, dwLen, hKeyExchangeKey, 0, &hSessionKey);
1941
    ok(result, "%08x\n", GetLastError());
1942 1943
    if (!result) return;

1944 1945 1946 1947 1948
    dwVal = 0xdeadbeef;
    dwLen = sizeof(DWORD);
    result = CryptGetKeyParam(hSessionKey, KP_PERMISSIONS, (BYTE*)&dwVal, &dwLen, 0);
    ok(result, "%08x\n", GetLastError());
    ok(dwVal ==
1949 1950
        (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
        broken(dwVal == 0xffffffff), /* Win9x/NT4 */
1951 1952 1953
        "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
        " got %08x\n", dwVal);

1954 1955
    dwLen = (DWORD)sizeof(abEncryptedMessage);
    result = CryptDecrypt(hSessionKey, 0, TRUE, 0, abEncryptedMessage, &dwLen);
1956 1957 1958
    ok(result, "%08x\n", GetLastError());
    ok(dwLen == 12, "expected 12, got %d\n", dwLen);
    ok(!memcmp(abEncryptedMessage, "Wine rocks!", 12), "decrypt failed\n");
1959
    CryptDestroyKey(hSessionKey);
1960 1961 1962 1963 1964
    
    if (!derive_key(CALG_RC4, &hSessionKey, 56)) return;

    dwLen = (DWORD)sizeof(abSessionKey);
    result = CryptExportKey(hSessionKey, hKeyExchangeKey, SIMPLEBLOB, 0, abSessionKey, &dwLen);
1965
    ok(result, "%08x\n", GetLastError());
1966
    CryptDestroyKey(hSessionKey);
1967 1968 1969 1970
    if (!result) return;

    dwLen = (DWORD)sizeof(abSessionKey);
    result = CryptImportKey(hProv, abSessionKey, dwLen, hKeyExchangeKey, 0, &hSessionKey);
1971
    ok(result, "%08x\n", GetLastError());
1972
    if (!result) return;
1973 1974 1975

    CryptDestroyKey(hSessionKey);
    CryptDestroyKey(hKeyExchangeKey);
1976 1977 1978 1979 1980

    /* Test importing a private key with a buffer that's smaller than the
     * actual buffer.  The private exponent can be omitted, its length is
     * inferred from the passed-in length parameter.
     */
1981
    dwLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + rsaPubKey->bitlen / 2;
1982 1983 1984 1985 1986 1987 1988 1989
    for (; dwLen < sizeof(abPlainPrivateKey); dwLen++)
    {
        result = CryptImportKey(hProv, abPlainPrivateKey, dwLen, 0, 0, &hKeyExchangeKey);
        ok(result, "CryptImportKey failed at size %d: %d (%08x)\n", dwLen,
           GetLastError(), GetLastError());
        if (result)
            CryptDestroyKey(hKeyExchangeKey);
    }
1990 1991
}

1992
static void test_verify_signature(void) {
1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171
    HCRYPTHASH hHash;
    HCRYPTKEY hPubSignKey;
    BYTE abData[] = "Wine rocks!";
    BOOL result;
    BYTE abPubKey[148] = {
        0x06, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 
        0x52, 0x53, 0x41, 0x31, 0x00, 0x04, 0x00, 0x00, 
        0x01, 0x00, 0x01, 0x00, 0x71, 0x64, 0x9f, 0x19, 
        0x89, 0x1c, 0x21, 0xcc, 0x36, 0xa3, 0xc9, 0x27, 
        0x08, 0x8a, 0x09, 0xc6, 0xbe, 0xeb, 0xd3, 0xf8, 
        0x19, 0xa9, 0x92, 0x57, 0xe4, 0xb9, 0x5d, 0xda, 
        0x88, 0x93, 0xe4, 0x6b, 0x38, 0x77, 0x14, 0x8a, 
        0x96, 0xc0, 0xb6, 0x4e, 0x42, 0xf5, 0x01, 0xdc, 
        0xf0, 0xeb, 0x3c, 0xc7, 0x7b, 0xc4, 0xfd, 0x7c, 
        0xde, 0x93, 0x34, 0x0a, 0x92, 0xe5, 0x97, 0x9c, 
        0x3e, 0x65, 0xb8, 0x91, 0x2f, 0xe3, 0xf3, 0x89, 
        0xcd, 0x6c, 0x26, 0xa4, 0x6c, 0xc7, 0x6d, 0x0b, 
        0x2c, 0xa2, 0x0b, 0x29, 0xe2, 0xfc, 0x30, 0xfa, 
        0x20, 0xdb, 0x4c, 0xb8, 0x91, 0xb8, 0x69, 0x63, 
        0x96, 0x41, 0xc2, 0xb4, 0x60, 0xeb, 0xcd, 0xff, 
        0x3a, 0x1f, 0x94, 0xb1, 0x23, 0xcf, 0x0f, 0x49, 
        0xad, 0xd5, 0x33, 0x85, 0x71, 0xaf, 0x12, 0x87, 
        0x84, 0xef, 0xa0, 0xea, 0xe1, 0xc1, 0xd4, 0xc7, 
        0xe1, 0x21, 0x50, 0xac
    };
    /* md2 with hash oid */
    BYTE abSignatureMD2[128] = {
        0x4a, 0x4e, 0xb7, 0x5e, 0x32, 0xda, 0xdb, 0x67, 
        0x9f, 0x77, 0x84, 0x32, 0x00, 0xba, 0x5f, 0x6b, 
        0x0d, 0xcf, 0xd9, 0x99, 0xbd, 0x96, 0x31, 0xda, 
        0x23, 0x4c, 0xd9, 0x4a, 0x90, 0x84, 0x20, 0x59, 
        0x51, 0xdc, 0xd4, 0x93, 0x3a, 0xae, 0x0a, 0x0a, 
        0xa1, 0x76, 0xfa, 0xb5, 0x68, 0xee, 0xc7, 0x34, 
        0x41, 0xd3, 0xe7, 0x5a, 0x0e, 0x22, 0x61, 0x40, 
        0xea, 0x24, 0x56, 0xf1, 0x91, 0x5a, 0xf7, 0xa7, 
        0x5b, 0xf4, 0x98, 0x6b, 0xc3, 0xef, 0xad, 0xc0, 
        0x5e, 0x6b, 0x87, 0x76, 0xcb, 0x1f, 0x62, 0x06, 
        0x7c, 0xf6, 0x48, 0x97, 0x81, 0x8d, 0xef, 0x51, 
        0x51, 0xdc, 0x21, 0x91, 0x57, 0x1e, 0x79, 0x6f, 
        0x49, 0xb5, 0xde, 0x31, 0x07, 0x45, 0x99, 0x46, 
        0xc3, 0x4f, 0xca, 0x2d, 0x0e, 0x4c, 0x10, 0x25, 
        0xcb, 0x1a, 0x98, 0x63, 0x41, 0x93, 0x47, 0xc0, 
        0xb2, 0xbc, 0x10, 0x3c, 0xe7, 0xd4, 0x3c, 0x1e
    };
    /* md2 without hash oid */
    BYTE abSignatureMD2NoOID[128] = {
        0x0c, 0x21, 0x3e, 0x60, 0xf9, 0xd0, 0x36, 0x2d, 
        0xe1, 0x10, 0x45, 0x45, 0x85, 0x03, 0x29, 0x19, 
        0xef, 0x19, 0xd9, 0xa6, 0x7e, 0x9c, 0x0d, 0xbd, 
        0x03, 0x0e, 0xb9, 0x51, 0x9e, 0x74, 0x79, 0xc4, 
        0xde, 0x25, 0xf2, 0x35, 0x74, 0x55, 0xbc, 0x65, 
        0x7e, 0x33, 0x28, 0xa8, 0x1e, 0x72, 0xaa, 0x99, 
        0xdd, 0xf5, 0x26, 0x20, 0x29, 0xf8, 0xa6, 0xdf, 
        0x28, 0x4b, 0x1c, 0xdb, 0xa1, 0x41, 0x56, 0xbc, 
        0xf9, 0x9c, 0x66, 0xc0, 0x37, 0x41, 0x55, 0xa0, 
        0xe2, 0xec, 0xbf, 0x71, 0xf0, 0x5d, 0x25, 0x01, 
        0x75, 0x91, 0xe2, 0x81, 0xb2, 0x9f, 0x57, 0xa7, 
        0x5c, 0xd2, 0xfa, 0x66, 0xdb, 0x71, 0x2b, 0x1f, 
        0xad, 0x30, 0xde, 0xea, 0x49, 0x73, 0x30, 0x6a, 
        0x22, 0x54, 0x49, 0x4e, 0xae, 0xf6, 0x88, 0xc9, 
        0xff, 0x71, 0xba, 0xbf, 0x27, 0xc5, 0xfa, 0x06, 
        0xe2, 0x91, 0x71, 0x8a, 0x7e, 0x0c, 0xc2, 0x07
    };
    /* md4 with hash oid */
    BYTE abSignatureMD4[128] = {
        0x1c, 0x78, 0xaa, 0xea, 0x74, 0xf4, 0x83, 0x51, 
        0xae, 0x66, 0xe3, 0xa9, 0x1c, 0x03, 0x39, 0x1b, 
        0xac, 0x7e, 0x4e, 0x85, 0x7e, 0x1c, 0x38, 0xd2, 
        0x82, 0x43, 0xb3, 0x6f, 0x6f, 0x46, 0x45, 0x8e, 
        0x17, 0x74, 0x58, 0x29, 0xca, 0xe1, 0x03, 0x13, 
        0x45, 0x79, 0x34, 0xdf, 0x5c, 0xd6, 0xc3, 0xf9, 
        0x7a, 0x1c, 0x9d, 0xff, 0x6f, 0x03, 0x7d, 0x0f, 
        0x59, 0x1a, 0x2d, 0x0e, 0x94, 0xb4, 0x75, 0x96, 
        0xd1, 0x48, 0x63, 0x6e, 0xb2, 0xc4, 0x5c, 0xd9, 
        0xab, 0x49, 0xb4, 0x90, 0xd9, 0x57, 0x04, 0x6e, 
        0x4c, 0xb6, 0xea, 0x00, 0x94, 0x4a, 0x34, 0xa0, 
        0xd9, 0x63, 0xef, 0x2c, 0xde, 0x5b, 0xb9, 0xbe, 
        0x35, 0xc8, 0xc1, 0x31, 0xb5, 0x31, 0x15, 0x18, 
        0x90, 0x39, 0xf5, 0x2a, 0x34, 0x6d, 0xb4, 0xab, 
        0x09, 0x34, 0x69, 0x54, 0x4d, 0x11, 0x2f, 0xf3, 
        0xa2, 0x36, 0x0e, 0xa8, 0x45, 0xe7, 0x36, 0xac
    };
    /* md4 without hash oid */
    BYTE abSignatureMD4NoOID[128] = {
        0xd3, 0x60, 0xb2, 0xb0, 0x22, 0x0a, 0x99, 0xda, 
        0x04, 0x85, 0x64, 0xc6, 0xc6, 0xdb, 0x11, 0x24, 
        0xe9, 0x68, 0x2d, 0xf7, 0x09, 0xef, 0xb6, 0xa0, 
        0xa2, 0xfe, 0x45, 0xee, 0x85, 0x49, 0xcd, 0x36, 
        0xf7, 0xc7, 0x9d, 0x2b, 0x4c, 0x68, 0xda, 0x85, 
        0x8c, 0x50, 0xcc, 0x4f, 0x4b, 0xe1, 0x82, 0xc3, 
        0xbe, 0xa3, 0xf1, 0x78, 0x6b, 0x60, 0x42, 0x3f, 
        0x67, 0x22, 0x14, 0xe4, 0xe1, 0xa4, 0x6e, 0xa9, 
        0x4e, 0xf1, 0xd4, 0xb0, 0xce, 0x82, 0xac, 0x06, 
        0xba, 0x2c, 0xbc, 0xf7, 0xcb, 0xf6, 0x0c, 0x3f, 
        0xf6, 0x79, 0xfe, 0xb3, 0xd8, 0x5a, 0xbc, 0xdb, 
        0x05, 0x41, 0xa4, 0x07, 0x57, 0x9e, 0xa2, 0x96, 
        0xfc, 0x60, 0x4b, 0xf7, 0x6f, 0x86, 0x26, 0x1f, 
        0xc2, 0x2c, 0x67, 0x08, 0xcd, 0x7f, 0x91, 0xe9, 
        0x16, 0xb5, 0x0e, 0xd9, 0xc4, 0xc4, 0x97, 0xeb, 
        0x91, 0x3f, 0x20, 0x6c, 0xf0, 0x68, 0x86, 0x7f
    }; 
    /* md5 with hash oid */
    BYTE abSignatureMD5[128] = {
        0x4f, 0xe0, 0x8c, 0x9b, 0x43, 0xdd, 0x02, 0xe5, 
        0xf4, 0xa1, 0xdd, 0x88, 0x4c, 0x9c, 0x40, 0x0f, 
        0x6c, 0x43, 0x86, 0x64, 0x00, 0xe6, 0xac, 0xf7, 
        0xd0, 0x92, 0xaa, 0xc4, 0x62, 0x9a, 0x48, 0x98, 
        0x1a, 0x56, 0x6d, 0x75, 0xec, 0x04, 0x89, 0xec, 
        0x69, 0x93, 0xd6, 0x61, 0x37, 0xb2, 0x36, 0xb5, 
        0xb2, 0xba, 0xf2, 0xf5, 0x21, 0x0c, 0xf1, 0x04, 
        0xc8, 0x2d, 0xf5, 0xa0, 0x8d, 0x6d, 0x10, 0x0b, 
        0x68, 0x63, 0xf2, 0x08, 0x68, 0xdc, 0xbd, 0x95, 
        0x25, 0x7d, 0xee, 0x63, 0x5c, 0x3b, 0x98, 0x4c, 
        0xea, 0x41, 0xdc, 0x6a, 0x8b, 0x6c, 0xbb, 0x29, 
        0x2b, 0x1c, 0x5c, 0x8b, 0x7d, 0x94, 0x24, 0xa9, 
        0x7a, 0x62, 0x94, 0xf3, 0x3a, 0x6a, 0xb2, 0x4c, 
        0x33, 0x59, 0x00, 0xcd, 0x7d, 0x37, 0x79, 0x90, 
        0x31, 0xd1, 0xd9, 0x84, 0x12, 0xe5, 0x08, 0x5e, 
        0xb3, 0x60, 0x61, 0x27, 0x78, 0x37, 0x63, 0x01
    };
    /* md5 without hash oid */
    BYTE abSignatureMD5NoOID[128] = {
        0xc6, 0xad, 0x5c, 0x2b, 0x9b, 0xe0, 0x99, 0x2f, 
        0x5e, 0x55, 0x04, 0x32, 0x65, 0xe0, 0xb5, 0x75, 
        0x01, 0x9a, 0x11, 0x4d, 0x0e, 0x9a, 0xe1, 0x9f, 
        0xc7, 0xbf, 0x77, 0x6d, 0xa9, 0xfd, 0xcc, 0x9d, 
        0x8b, 0xd1, 0x31, 0xed, 0x5a, 0xd2, 0xe5, 0x5f, 
        0x42, 0x3b, 0xb5, 0x3c, 0x32, 0x30, 0x88, 0x49, 
        0xcb, 0x67, 0xb8, 0x2e, 0xc9, 0xf5, 0x2b, 0xc8, 
        0x35, 0x71, 0xb5, 0x1b, 0x32, 0x3f, 0x44, 0x4c, 
        0x66, 0x93, 0xcb, 0xe8, 0x48, 0x7c, 0x14, 0x23, 
        0xfb, 0x12, 0xa5, 0xb7, 0x86, 0x94, 0x6b, 0x19, 
        0x17, 0x20, 0xc6, 0xb8, 0x09, 0xe8, 0xbb, 0xdb, 
        0x00, 0x2b, 0x96, 0x4a, 0x93, 0x00, 0x26, 0xd3, 
        0x07, 0xa0, 0x06, 0xce, 0x5a, 0x13, 0x69, 0x6b, 
        0x62, 0x5a, 0x56, 0x61, 0x6a, 0xd8, 0x11, 0x3b, 
        0xd5, 0x67, 0xc7, 0x4d, 0xf6, 0x66, 0x63, 0xc5, 
        0xe3, 0x8f, 0x7c, 0x7c, 0xb1, 0x3e, 0x55, 0x43
    };
    /* sha with hash oid */
    BYTE abSignatureSHA[128] = {
        0x5a, 0x4c, 0x66, 0xc9, 0x30, 0x67, 0xcb, 0x91, 
        0x3c, 0x4d, 0xd5, 0x8d, 0xea, 0x4e, 0x85, 0xcd, 
        0xd9, 0x68, 0x3a, 0xf3, 0x24, 0x3c, 0x99, 0x24, 
        0x25, 0x32, 0x93, 0x3d, 0xd6, 0x2f, 0x86, 0x94, 
        0x23, 0x09, 0xee, 0x02, 0xd4, 0x15, 0xdc, 0x5f, 
        0x0e, 0x44, 0x45, 0x13, 0x5f, 0x18, 0x5d, 0x1a, 
        0xd7, 0x0b, 0xd1, 0x23, 0xd6, 0x35, 0x98, 0x52, 
        0x57, 0x45, 0x74, 0x92, 0xe3, 0x50, 0xb4, 0x20, 
        0x28, 0x2a, 0x11, 0xbf, 0x49, 0xb4, 0x2c, 0xc5, 
        0xd4, 0x1a, 0x27, 0x4e, 0xdf, 0xa0, 0xb5, 0x7a, 
        0xc8, 0x14, 0xdd, 0x9b, 0xb6, 0xca, 0xd6, 0xff, 
        0xb2, 0x6b, 0xd8, 0x98, 0x67, 0x80, 0xab, 0x53, 
        0x52, 0xbb, 0xe1, 0x2a, 0xce, 0x79, 0x2f, 0x00, 
        0x53, 0x26, 0xd8, 0xa7, 0x43, 0xca, 0x72, 0x0e, 
        0x68, 0x97, 0x37, 0x71, 0x87, 0xc2, 0x6a, 0x98, 
        0xbb, 0x6c, 0xa0, 0x01, 0xff, 0x04, 0x9d, 0xa6
    };
    /* sha without hash oid */
    BYTE abSignatureSHANoOID[128] = {
        0x86, 0xa6, 0x2b, 0x9a, 0x04, 0xda, 0x47, 0xc6, 
        0x4f, 0x97, 0x8a, 0x8a, 0xf4, 0xfa, 0x63, 0x1a, 
        0x32, 0x89, 0x56, 0x41, 0x37, 0x91, 0x15, 0x2f, 
        0x2d, 0x1c, 0x8f, 0xdc, 0x88, 0x40, 0xbb, 0x37, 
        0x3e, 0x06, 0x33, 0x1b, 0xde, 0xda, 0x7c, 0x65, 
        0x91, 0x35, 0xca, 0x45, 0x17, 0x0e, 0x24, 0xbe, 
        0x9e, 0xf6, 0x4e, 0x8a, 0xa4, 0x3e, 0xca, 0xe6, 
        0x11, 0x36, 0xb8, 0x3a, 0xf0, 0xde, 0x71, 0xfe, 
        0xdd, 0xb3, 0xcb, 0x6c, 0x39, 0xe0, 0x5f, 0x0c, 
        0x9e, 0xa8, 0x40, 0x26, 0x9c, 0x81, 0xe9, 0xc4, 
        0x15, 0x90, 0xbf, 0x4f, 0xd2, 0xc1, 0xa1, 0x80, 
        0x52, 0xfd, 0xf6, 0x3d, 0x99, 0x1b, 0x9c, 0x8a, 
        0x27, 0x1b, 0x0c, 0x9a, 0xf3, 0xf9, 0xa2, 0x00, 
        0x3e, 0x5b, 0xdf, 0xc2, 0xb4, 0x71, 0xa5, 0xbd, 
        0xf8, 0xae, 0x63, 0xbb, 0x4a, 0xc9, 0xdd, 0x67, 
        0xc1, 0x3e, 0x93, 0xee, 0xf1, 0x1f, 0x24, 0x5b
    }; 
    
    result = CryptImportKey(hProv, abPubKey, 148, 0, 0, &hPubSignKey);
2172
    ok(result, "%08x\n", GetLastError());
2173 2174 2175
    if (!result) return;

    result = CryptCreateHash(hProv, CALG_MD2, 0, 0, &hHash);
2176
    ok(result, "%08x\n", GetLastError());
2177 2178 2179
    if (!result) return;

    result = CryptHashData(hHash, abData, (DWORD)sizeof(abData), 0);
2180
    ok(result, "%08x\n", GetLastError());
2181 2182
    if (!result) return;

2183
    /*check that a NULL pointer signature is correctly handled*/
2184
    result = CryptVerifySignatureA(hHash, NULL, 128, hPubSignKey, NULL, 0);
2185 2186 2187 2188 2189
    ok(!result && ERROR_INVALID_PARAMETER == GetLastError(),
     "Expected ERROR_INVALID_PARAMETER error, got %08x\n", GetLastError());
    if (result) return;

    /* check that we get a bad signature error when the signature is too short*/
2190
    SetLastError(0xdeadbeef);
2191
    result = CryptVerifySignatureA(hHash, abSignatureMD2, 64, hPubSignKey, NULL, 0);
2192 2193 2194
    ok((!result && NTE_BAD_SIGNATURE == GetLastError()) ||
     broken(result), /* Win9x, WinMe, NT4 */
     "Expected NTE_BAD_SIGNATURE, got %08x\n",  GetLastError());
2195

2196
    result = CryptVerifySignatureA(hHash, abSignatureMD2, 128, hPubSignKey, NULL, 0);
2197
    ok(result, "%08x\n", GetLastError());
2198 2199
    if (!result) return;

2200
    /* It seems that CPVerifySignature doesn't care about the OID at all. */
2201
    result = CryptVerifySignatureA(hHash, abSignatureMD2NoOID, 128, hPubSignKey, NULL, 0);
2202
    ok(result, "%08x\n", GetLastError());
2203 2204
    if (!result) return;

2205
    result = CryptVerifySignatureA(hHash, abSignatureMD2NoOID, 128, hPubSignKey, NULL, CRYPT_NOHASHOID);
2206 2207
    ok(result, "%08x\n", GetLastError());
    if (!result) return;
2208

2209 2210
    CryptDestroyHash(hHash);

2211
    result = CryptCreateHash(hProv, CALG_MD4, 0, 0, &hHash);
2212
    ok(result, "%08x\n", GetLastError());
2213 2214 2215
    if (!result) return;

    result = CryptHashData(hHash, abData, (DWORD)sizeof(abData), 0);
2216
    ok(result, "%08x\n", GetLastError());
2217 2218
    if (!result) return;

2219
    result = CryptVerifySignatureA(hHash, abSignatureMD4, 128, hPubSignKey, NULL, 0);
2220
    ok(result, "%08x\n", GetLastError());
2221 2222
    if (!result) return;

2223
    result = CryptVerifySignatureA(hHash, abSignatureMD4NoOID, 128, hPubSignKey, NULL, 0);
2224 2225 2226
    ok(result, "%08x\n", GetLastError());
    if (!result) return;

2227
    result = CryptVerifySignatureA(hHash, abSignatureMD4NoOID, 128, hPubSignKey, NULL, CRYPT_NOHASHOID);
2228
    ok(result, "%08x\n", GetLastError());
2229 2230
    if (!result) return;

2231 2232
    CryptDestroyHash(hHash);

2233
    result = CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
2234
    ok(result, "%08x\n", GetLastError());
2235 2236 2237
    if (!result) return;

    result = CryptHashData(hHash, abData, (DWORD)sizeof(abData), 0);
2238
    ok(result, "%08x\n", GetLastError());
2239 2240
    if (!result) return;

2241
    result = CryptVerifySignatureA(hHash, abSignatureMD5, 128, hPubSignKey, NULL, 0);
2242
    ok(result, "%08x\n", GetLastError());
2243 2244
    if (!result) return;

2245
    result = CryptVerifySignatureA(hHash, abSignatureMD5NoOID, 128, hPubSignKey, NULL, 0);
2246 2247 2248
    ok(result, "%08x\n", GetLastError());
    if (!result) return;

2249
    result = CryptVerifySignatureA(hHash, abSignatureMD5NoOID, 128, hPubSignKey, NULL, CRYPT_NOHASHOID);
2250
    ok(result, "%08x\n", GetLastError());
2251 2252
    if (!result) return;

2253 2254
    CryptDestroyHash(hHash);

2255
    result = CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash);
2256
    ok(result, "%08x\n", GetLastError());
2257 2258 2259
    if (!result) return;

    result = CryptHashData(hHash, abData, (DWORD)sizeof(abData), 0);
2260
    ok(result, "%08x\n", GetLastError());
2261 2262
    if (!result) return;

2263
    result = CryptVerifySignatureA(hHash, abSignatureSHA, 128, hPubSignKey, NULL, 0);
2264
    ok(result, "%08x\n", GetLastError());
2265 2266
    if (!result) return;

2267
    result = CryptVerifySignatureA(hHash, abSignatureSHANoOID, 128, hPubSignKey, NULL, 0);
2268 2269 2270
    ok(result, "%08x\n", GetLastError());
    if (!result) return;

2271
    result = CryptVerifySignatureA(hHash, abSignatureSHANoOID, 128, hPubSignKey, NULL, CRYPT_NOHASHOID);
2272
    ok(result, "%08x\n", GetLastError());
2273
    if (!result) return;
2274 2275 2276

    CryptDestroyHash(hHash);
    CryptDestroyKey(hPubSignKey);
2277 2278
}

Mike McCormack's avatar
Mike McCormack committed
2279
static void test_rsa_encrypt(void)
2280 2281 2282 2283
{
    HCRYPTKEY hRSAKey;
    BYTE abData[2048] = "Wine rocks!";
    BOOL result;
2284
    DWORD dwVal, dwLen;
2285
    DWORD err;
2286 2287 2288

    /* It is allowed to use the key exchange key for encryption/decryption */
    result = CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hRSAKey);
2289
    ok (result, "%08x\n", GetLastError());
2290 2291
    if (!result) return;

2292 2293
    dwLen = 12;
    result = CryptEncrypt(hRSAKey, 0, TRUE, 0, NULL, &dwLen, (DWORD)sizeof(abData));
2294 2295 2296 2297 2298
    if(!ENHANCED_PROV && !result && GetLastError() == NTE_BAD_KEY)
    {
        CryptDestroyKey(hRSAKey);
        return;
    }
2299 2300
    ok(result, "CryptEncrypt failed: %08x\n", GetLastError());
    ok(dwLen == 128, "Unexpected length %d\n", dwLen);
2301
    /* PKCS1 V1.5 */
2302 2303
    dwLen = 12;
    result = CryptEncrypt(hRSAKey, 0, TRUE, 0, abData, &dwLen, (DWORD)sizeof(abData));
2304
    ok (result, "%08x\n", GetLastError());
2305 2306 2307
    if (!result) return;

    result = CryptDecrypt(hRSAKey, 0, TRUE, 0, abData, &dwLen);
2308
    ok (result && dwLen == 12 && !memcmp(abData, "Wine rocks!", 12), "%08x\n", GetLastError());
2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354

    /* OAEP, RFC 8017 PKCS #1 V2.2 */
    /* Test minimal buffer length requirement */
    dwLen = 1;
    SetLastError(0xdeadbeef);
    result = CryptEncrypt(hRSAKey, 0, TRUE, CRYPT_OAEP, abData, &dwLen, 20 * 2 + 2);
    err = GetLastError();
    ok(!result && err == ERROR_MORE_DATA, "%08x\n", err);

    /* Test data length limit */
    dwLen = sizeof(abData) - (20 * 2 + 2) + 1;
    result = CryptEncrypt(hRSAKey, 0, TRUE, CRYPT_OAEP, abData, &dwLen, (DWORD)sizeof(abData));
    err = GetLastError();
    ok(!result && err == NTE_BAD_LEN, "%08x\n", err);

    /* Test malformed data */
    dwLen = 12;
    SetLastError(0xdeadbeef);
    memcpy(abData, "Wine rocks!", dwLen);
    result = CryptDecrypt(hRSAKey, 0, TRUE, CRYPT_OAEP, abData, &dwLen);
    err = GetLastError();
    /* NTE_DOUBLE_ENCRYPT on xp or 2003 */
    ok(!result && (err == NTE_BAD_DATA || broken(err == NTE_DOUBLE_ENCRYPT)), "%08x\n", err);

    /* Test decrypt with insufficient buffer */
    dwLen = 12;
    SetLastError(0xdeadbeef);
    memcpy(abData, "Wine rocks!", 12);
    result = CryptEncrypt(hRSAKey, 0, TRUE, CRYPT_OAEP, abData, &dwLen, (DWORD)sizeof(abData));
    ok(result, "%08x\n", GetLastError());
    dwLen = 11;
    SetLastError(0xdeadbeef);
    result = CryptDecrypt(hRSAKey, 0, TRUE, CRYPT_OAEP, abData, &dwLen);
    err = GetLastError();
    /* broken on xp or 2003 */
    ok((!result && dwLen == 11 && err == NTE_BAD_DATA) || broken(result == TRUE && dwLen == 12 && err == ERROR_NO_TOKEN),
       "%08x %d %08x\n", result, dwLen, err);

    /* Test normal encryption and decryption */
    dwLen = 12;
    memcpy(abData, "Wine rocks!", dwLen);
    result = CryptEncrypt(hRSAKey, 0, TRUE, CRYPT_OAEP, abData, &dwLen, (DWORD)sizeof(abData));
    ok(result, "%08x\n", GetLastError());
    result = CryptDecrypt(hRSAKey, 0, TRUE, CRYPT_OAEP, abData, &dwLen);
    ok(result && dwLen == 12 && !memcmp(abData, "Wine rocks!", 12), "%08x\n", GetLastError());

2355 2356 2357 2358 2359
    dwVal = 0xdeadbeef;
    dwLen = sizeof(DWORD);
    result = CryptGetKeyParam(hRSAKey, KP_PERMISSIONS, (BYTE*)&dwVal, &dwLen, 0);
    ok(result, "%08x\n", GetLastError());
    ok(dwVal ==
2360 2361
        (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
        broken(dwVal == 0xffffffff), /* Win9x/NT4 */
2362 2363 2364
        "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
        " got %08x\n", dwVal);

2365 2366
    /* An RSA key doesn't support salt */
    result = CryptGetKeyParam(hRSAKey, KP_SALT, NULL, &dwLen, 0);
2367 2368
    ok(!result && (GetLastError() == NTE_BAD_KEY || GetLastError() == NTE_NOT_FOUND /* Win7 */),
       "expected NTE_BAD_KEY or NTE_NOT_FOUND, got %08x\n", GetLastError());
2369

2370 2371 2372 2373 2374 2375
    /* The key exchange key's public key may be exported.. */
    result = CryptExportKey(hRSAKey, 0, PUBLICKEYBLOB, 0, NULL, &dwLen);
    ok(result, "%08x\n", GetLastError());
    /* but its private key may not be. */
    SetLastError(0xdeadbeef);
    result = CryptExportKey(hRSAKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwLen);
2376 2377
    ok((!result && GetLastError() == NTE_BAD_KEY_STATE) ||
        broken(result), /* Win9x/NT4 */
2378 2379 2380 2381 2382
        "expected NTE_BAD_KEY_STATE, got %08x\n", GetLastError());
    /* Setting the permissions of the key exchange key isn't allowed, either. */
    dwVal |= CRYPT_EXPORT;
    SetLastError(0xdeadbeef);
    result = CryptSetKeyParam(hRSAKey, KP_PERMISSIONS, (BYTE *)&dwVal, 0);
2383 2384 2385
    ok(!result &&
        (GetLastError() == NTE_BAD_DATA || GetLastError() == NTE_BAD_FLAGS),
        "expected NTE_BAD_DATA or NTE_BAD_FLAGS, got %08x\n", GetLastError());
2386

2387 2388 2389 2390
    CryptDestroyKey(hRSAKey);

    /* It is not allowed to use the signature key for encryption/decryption */
    result = CryptGetUserKey(hProv, AT_SIGNATURE, &hRSAKey);
2391 2392 2393 2394 2395
    if (!result)
    {
        skip("No signature key in provider %s found, error %#x.\n", szProviders[iProv], GetLastError());
        return;
    }
2396

2397 2398 2399 2400 2401
    dwVal = 0xdeadbeef;
    dwLen = sizeof(DWORD);
    result = CryptGetKeyParam(hRSAKey, KP_PERMISSIONS, (BYTE*)&dwVal, &dwLen, 0);
    ok(result, "%08x\n", GetLastError());
    ok(dwVal ==
2402 2403
        (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
        broken(dwVal == 0xffffffff), /* Win9x/NT4 */
2404 2405 2406 2407 2408 2409 2410 2411 2412
        "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
        " got %08x\n", dwVal);

    /* The signature key's public key may also be exported.. */
    result = CryptExportKey(hRSAKey, 0, PUBLICKEYBLOB, 0, NULL, &dwLen);
    ok(result, "%08x\n", GetLastError());
    /* but its private key may not be. */
    SetLastError(0xdeadbeef);
    result = CryptExportKey(hRSAKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwLen);
2413 2414
    ok((!result && GetLastError() == NTE_BAD_KEY_STATE) ||
        broken(result), /* Win9x/NT4 */
2415 2416 2417 2418 2419
        "expected NTE_BAD_KEY_STATE, got %08x\n", GetLastError());
    /* Setting the permissions of the signature key isn't allowed, either. */
    dwVal |= CRYPT_EXPORT;
    SetLastError(0xdeadbeef);
    result = CryptSetKeyParam(hRSAKey, KP_PERMISSIONS, (BYTE *)&dwVal, 0);
2420 2421 2422
    ok(!result &&
        (GetLastError() == NTE_BAD_DATA || GetLastError() == NTE_BAD_FLAGS),
        "expected NTE_BAD_DATA or NTE_BAD_FLAGS, got %08x\n", GetLastError());
2423

2424 2425
    dwLen = 12;
    result = CryptEncrypt(hRSAKey, 0, TRUE, 0, abData, &dwLen, (DWORD)sizeof(abData));
2426
    ok (!result && GetLastError() == NTE_BAD_KEY, "%08x\n", GetLastError());
2427 2428 2429

    CryptDestroyKey(hRSAKey);
}
2430 2431 2432

static void test_import_export(void)
{
2433
    DWORD dwLen, dwDataLen, dwVal;
2434
    HCRYPTKEY hPublicKey, hPrivKey;
2435 2436
    BOOL result;
    ALG_ID algID;
2437
    BYTE emptyKey[2048], *exported_key, *exported_key2;
2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450
    static BYTE abPlainPublicKey[84] = {
        0x06, 0x02, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00,
        0x52, 0x53, 0x41, 0x31, 0x00, 0x02, 0x00, 0x00,
        0x01, 0x00, 0x01, 0x00, 0x11, 0x11, 0x11, 0x11,
        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
        0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
        0x11, 0x11, 0x11, 0x11
    };
2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604
    static BYTE priv_key_with_high_bit[] = {
        0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
        0x52, 0x53, 0x41, 0x32, 0x00, 0x04, 0x00, 0x00,
        0x01, 0x00, 0x01, 0x00, 0xd5, 0xa2, 0x0d, 0x66,
        0xfe, 0x65, 0xb5, 0xf1, 0xc9, 0x6b, 0xf5, 0x58,
        0x04, 0x38, 0x2d, 0xf4, 0xa3, 0x5a, 0xda, 0x9e,
        0x95, 0x81, 0x85, 0x3d, 0x01, 0x07, 0xb2, 0x03,
        0x77, 0x70, 0x79, 0x6e, 0x6c, 0x26, 0x42, 0xa4,
        0x12, 0xfd, 0xaa, 0x29, 0x83, 0x04, 0xce, 0x91,
        0x90, 0x39, 0x5e, 0x49, 0x56, 0xfd, 0x0a, 0xe5,
        0xb1, 0xea, 0x3b, 0xb2, 0x70, 0xb0, 0x20, 0xc1,
        0x1f, 0x22, 0x07, 0x3e, 0x4d, 0xc0, 0x73, 0xfd,
        0x92, 0x8f, 0x87, 0xd8, 0xd1, 0xd1, 0x28, 0xd8,
        0x19, 0xd1, 0x93, 0x83, 0xe0, 0xb8, 0x9f, 0x53,
        0xf4, 0x6a, 0x7c, 0xcb, 0x10, 0x53, 0xd0, 0x37,
        0x02, 0xb4, 0xa5, 0xf7, 0xa2, 0x28, 0x6e, 0x26,
        0xef, 0x5c, 0x14, 0x01, 0x40, 0x1e, 0xa3, 0xe1,
        0xda, 0x76, 0xd0, 0x12, 0x84, 0xb7, 0x48, 0x7d,
        0xc8, 0x67, 0x5c, 0xb2, 0xd5, 0x2e, 0xaf, 0x8e,
        0x7d, 0x32, 0x59, 0x92, 0x01, 0xd6, 0x5b, 0x68,
        0x28, 0x9b, 0xb1, 0x6c, 0x69, 0xeb, 0x61, 0x5b,
        0x4b, 0x13, 0xe2, 0xbd, 0x7d, 0xbe, 0xce, 0xe8,
        0x41, 0x54, 0xca, 0xa8, 0xdd, 0xc7, 0xfe, 0x8b,
        0xdf, 0xf6, 0x55, 0x6c, 0x50, 0x11, 0xc8, 0x15,
        0x13, 0x42, 0x59, 0x9f, 0xbb, 0xea, 0x73, 0x78,
        0x7b, 0x22, 0x8d, 0x96, 0x62, 0xe5, 0xda, 0xa2,
        0x85, 0x5c, 0x20, 0x74, 0x9f, 0x1c, 0x12, 0xf2,
        0x48, 0x06, 0x1a, 0xc6, 0xd5, 0x94, 0xec, 0x31,
        0x6b, 0xb6, 0x7b, 0x54, 0x61, 0x77, 0xec, 0x7c,
        0x6f, 0xb7, 0x55, 0x3d, 0x6b, 0x98, 0x05, 0xd7,
        0x8a, 0x73, 0x25, 0xf2, 0x8f, 0xe4, 0xb8, 0x8d,
        0x27, 0x18, 0x0d, 0x05, 0xba, 0x23, 0x54, 0x37,
        0x10, 0xf0, 0x1c, 0x41, 0xa6, 0xae, 0x4c, 0x2a,
        0x6a, 0x2f, 0x7f, 0x68, 0x43, 0x86, 0xe7, 0x9c,
        0xfd, 0x9e, 0xf1, 0xfe, 0x84, 0xe3, 0xb6, 0x99,
        0x51, 0xfe, 0x1e, 0xbd, 0x01, 0xc6, 0x10, 0xef,
        0x88, 0xa4, 0xd8, 0x53, 0x14, 0x88, 0x15, 0xc9,
        0xe5, 0x86, 0xe2, 0x8d, 0x85, 0x2e, 0x0d, 0xec,
        0x15, 0xa7, 0x48, 0xfa, 0x18, 0xfb, 0x01, 0x8d,
        0x2b, 0x90, 0x70, 0x7f, 0x78, 0xb1, 0x33, 0x7e,
        0xfe, 0x82, 0x40, 0x5f, 0x4a, 0x97, 0xc2, 0x42,
        0x22, 0xd5, 0x5f, 0xbc, 0xbd, 0xab, 0x26, 0x98,
        0xcd, 0xb5, 0xdf, 0x7e, 0xa0, 0x68, 0xa7, 0x12,
        0x9e, 0xa5, 0xa2, 0x90, 0x85, 0xc5, 0xca, 0x73,
        0x4a, 0x59, 0x8a, 0xec, 0xcf, 0xdd, 0x65, 0x5d,
        0xc1, 0xaa, 0x86, 0x53, 0xd5, 0xde, 0xbb, 0x23,
        0x24, 0xb8, 0x9b, 0x74, 0x03, 0x20, 0xb4, 0xf0,
        0xe4, 0xdd, 0xd2, 0x03, 0xfd, 0x67, 0x55, 0x19,
        0x28, 0x1d, 0xc1, 0xb8, 0xa5, 0x89, 0x0e, 0xc0,
        0x80, 0x9d, 0xdd, 0xda, 0x9d, 0x30, 0x5c, 0xc8,
        0xbb, 0xfe, 0x8f, 0xce, 0xd5, 0xf6, 0xdf, 0xfa,
        0x14, 0xaf, 0xe4, 0xba, 0xb0, 0x84, 0x45, 0xd8,
        0x67, 0xa7, 0xd0, 0xce, 0x89, 0x2a, 0x30, 0x8c,
        0xfa, 0xe9, 0x65, 0xa4, 0x21, 0x2d, 0x6b, 0xa2,
        0x9b, 0x8f, 0x92, 0xbd, 0x3a, 0x10, 0x71, 0x12,
        0xc2, 0x02, 0x3d, 0xd5, 0x83, 0x1d, 0xfa, 0x42,
        0xb7, 0x48, 0x1b, 0x31, 0xe3, 0x82, 0x90, 0x2d,
        0x91, 0x59, 0xf9, 0x38, 0x52, 0xe5, 0xdb, 0xc1,
        0x4d, 0x3a, 0xe6, 0x9b, 0x6a, 0xbb, 0xea, 0xa4,
        0x8d, 0x5e, 0xc4, 0x00, 0x01, 0xb8, 0xec, 0x91,
        0xc1, 0xdb, 0x63, 0xbd, 0x57, 0xb6, 0x26, 0x15,
        0xb6, 0x3e, 0xa2, 0xdf, 0x62, 0x8d, 0xa8, 0xbe,
        0xe1, 0xf1, 0x39, 0xbd, 0x18, 0xd2, 0x6f, 0xd7,
        0xda, 0xdc, 0x71, 0x30, 0xf1, 0x21, 0x71, 0xa4,
        0x08, 0x43, 0x46, 0xdf, 0x50, 0xbd, 0x3c, 0x60,
        0x5b, 0x63, 0x35, 0xe3, 0x37, 0x5b, 0x25, 0x17,
        0x54, 0x5e, 0x68, 0x60, 0xb6, 0x49, 0xef, 0x6e,
        0x09, 0xef, 0xda, 0x90, 0x3e, 0xd4, 0x09, 0x33,
        0x36, 0x57, 0x9a, 0x14, 0xbd, 0xf7, 0xb1, 0x98,
        0x30, 0x42, 0x03, 0x84, 0x61, 0xeb, 0x8e, 0x50,
        0xdc, 0x6a, 0x93, 0x1b, 0x32, 0x51, 0xf9, 0xc6,
        0xc2, 0x19, 0xb3, 0x5d, 0xe2, 0xf8, 0xc5, 0x8f,
        0x68, 0xaa, 0x1d, 0xdb, 0xd3, 0x7f, 0x8d, 0x98,
        0x9c, 0x16, 0x8c, 0xc3, 0xcd, 0xd9, 0xdb, 0x08,
        0xe6, 0x36, 0x60, 0xb6, 0x36, 0xdc, 0x1d, 0x59,
        0xb6, 0x5f, 0x01, 0x5e
    };
    static const BYTE expected_exported_priv_key[] = {
        0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
        0x52, 0x53, 0x41, 0x32, 0x00, 0x04, 0x00, 0x00,
        0x01, 0x00, 0x01, 0x00, 0xd5, 0xa2, 0x0d, 0x66,
        0xfe, 0x65, 0xb5, 0xf1, 0xc9, 0x6b, 0xf5, 0x58,
        0x04, 0x38, 0x2d, 0xf4, 0xa3, 0x5a, 0xda, 0x9e,
        0x95, 0x81, 0x85, 0x3d, 0x01, 0x07, 0xb2, 0x03,
        0x77, 0x70, 0x79, 0x6e, 0x6c, 0x26, 0x42, 0xa4,
        0x12, 0xfd, 0xaa, 0x29, 0x83, 0x04, 0xce, 0x91,
        0x90, 0x39, 0x5e, 0x49, 0x56, 0xfd, 0x0a, 0xe5,
        0xb1, 0xea, 0x3b, 0xb2, 0x70, 0xb0, 0x20, 0xc1,
        0x1f, 0x22, 0x07, 0x3e, 0x4d, 0xc0, 0x73, 0xfd,
        0x92, 0x8f, 0x87, 0xd8, 0xd1, 0xd1, 0x28, 0xd8,
        0x19, 0xd1, 0x93, 0x83, 0xe0, 0xb8, 0x9f, 0x53,
        0xf4, 0x6a, 0x7c, 0xcb, 0x10, 0x53, 0xd0, 0x37,
        0x02, 0xb4, 0xa5, 0xf7, 0xa2, 0x28, 0x6e, 0x26,
        0xef, 0x5c, 0x14, 0x01, 0x40, 0x1e, 0xa3, 0xe1,
        0xda, 0x76, 0xd0, 0x12, 0x84, 0xb7, 0x48, 0x7d,
        0xc8, 0x67, 0x5c, 0xb2, 0xd5, 0x2e, 0xaf, 0x8e,
        0x7d, 0x32, 0x59, 0x92, 0x01, 0xd6, 0x5b, 0x68,
        0x28, 0x9b, 0xb1, 0x6c, 0x69, 0xeb, 0x61, 0x5b,
        0x4b, 0x13, 0xe2, 0xbd, 0x7d, 0xbe, 0xce, 0xe8,
        0x41, 0x54, 0xca, 0xa8, 0xdd, 0xc7, 0xfe, 0x8b,
        0xdf, 0xf6, 0x55, 0x6c, 0x50, 0x11, 0xc8, 0x15,
        0x13, 0x42, 0x59, 0x9f, 0xbb, 0xea, 0x73, 0x78,
        0x7b, 0x22, 0x8d, 0x96, 0x62, 0xe5, 0xda, 0xa2,
        0x85, 0x5c, 0x20, 0x74, 0x9f, 0x1c, 0x12, 0xf2,
        0x48, 0x06, 0x1a, 0xc6, 0xd5, 0x94, 0xec, 0x31,
        0x6b, 0xb6, 0x7b, 0x54, 0x61, 0x77, 0xec, 0x7c,
        0x6f, 0xb7, 0x55, 0x3d, 0x6b, 0x98, 0x05, 0xd7,
        0x8a, 0x73, 0x25, 0xf2, 0x8f, 0xe4, 0xb8, 0x8d,
        0x27, 0x18, 0x0d, 0x05, 0xba, 0x23, 0x54, 0x37,
        0x10, 0xf0, 0x1c, 0x41, 0xa6, 0xae, 0x4c, 0x2a,
        0x6a, 0x2f, 0x7f, 0x68, 0x43, 0x86, 0xe7, 0x9c,
        0xfd, 0x9e, 0xf1, 0xfe, 0x84, 0xe3, 0xb6, 0x99,
        0x51, 0xfe, 0x1e, 0xbd, 0x01, 0xc6, 0x10, 0xef,
        0x88, 0xa4, 0xd8, 0x53, 0x14, 0x88, 0x15, 0xc9,
        0xe5, 0x86, 0xe2, 0x8d, 0x85, 0x2e, 0x0d, 0xec,
        0x15, 0xa7, 0x48, 0xfa, 0x18, 0xfb, 0x01, 0x8d,
        0x2b, 0x90, 0x70, 0x7f, 0x78, 0xb1, 0x33, 0x7e,
        0xfe, 0x82, 0x40, 0x5f, 0x4a, 0x97, 0xc2, 0x42,
        0x22, 0xd5, 0x5f, 0xbc, 0xbd, 0xab, 0x26, 0x98,
        0xcd, 0xb5, 0xdf, 0x7e, 0xa0, 0x68, 0xa7, 0x12,
        0x9e, 0xa5, 0xa2, 0x90, 0x85, 0xc5, 0xca, 0x73,
        0x4a, 0x59, 0x8a, 0xec, 0xcf, 0xdd, 0x65, 0x5d,
        0xc1, 0xaa, 0x86, 0x53, 0xd5, 0xde, 0xbb, 0x23,
        0x24, 0xb8, 0x9b, 0x74, 0x03, 0x20, 0xb4, 0xf0,
        0xe4, 0xdd, 0xd2, 0x03, 0xfd, 0x67, 0x55, 0x19,
        0x28, 0x1d, 0xc1, 0xb8, 0xa5, 0x89, 0x0e, 0xc0,
        0x80, 0x9d, 0xdd, 0xda, 0x9d, 0x30, 0x5c, 0xc8,
        0xbb, 0xfe, 0x8f, 0xce, 0xd5, 0xf6, 0xdf, 0xfa,
        0x14, 0xaf, 0xe4, 0xba, 0xb0, 0x84, 0x45, 0xd8,
        0x67, 0xa7, 0xd0, 0xce, 0x89, 0x2a, 0x30, 0x8c,
        0xfa, 0xe9, 0x65, 0xa4, 0x21, 0x2d, 0x6b, 0xa2,
        0x9b, 0x8f, 0x92, 0xbd, 0x3a, 0x10, 0x71, 0x12,
        0xc2, 0x02, 0x3d, 0xd5, 0x83, 0x1d, 0xfa, 0x42,
        0xb7, 0x48, 0x1b, 0x31, 0xe3, 0x82, 0x90, 0x2d,
        0x91, 0x59, 0xf9, 0x38, 0x52, 0xe5, 0xdb, 0xc1,
        0x4d, 0x3a, 0xe6, 0x9b, 0x6a, 0xbb, 0xea, 0xa4,
        0x8d, 0x5e, 0xc4, 0x00, 0x01, 0xb8, 0xec, 0x91,
        0xc1, 0xdb, 0x63, 0xbd, 0x57, 0xb6, 0x26, 0x15,
        0xb6, 0x3e, 0xa2, 0xdf, 0x62, 0x8d, 0xa8, 0xbe,
        0xe1, 0xf1, 0x39, 0xbd, 0x18, 0xd2, 0x6f, 0xd7,
        0xda, 0xdc, 0x71, 0x30, 0xf1, 0x21, 0x71, 0xa4,
        0x08, 0x43, 0x46, 0xdf, 0x50, 0xbd, 0x3c, 0x60,
        0x5b, 0x63, 0x35, 0xe3, 0x37, 0x5b, 0x25, 0x17,
        0x54, 0x5e, 0x68, 0x60, 0xb6, 0x49, 0xef, 0x6e,
        0x09, 0xef, 0xda, 0x90, 0x3e, 0xd4, 0x09, 0x33,
        0x36, 0x57, 0x9a, 0x14, 0xbd, 0xf7, 0xb1, 0x98,
        0x30, 0x42, 0x03, 0x84, 0x61, 0xeb, 0x8e, 0x50,
        0xdc, 0x6a, 0x93, 0x1b, 0x32, 0x51, 0xf9, 0xc6,
        0xc2, 0x19, 0xb3, 0x5d, 0xe2, 0xf8, 0xc5, 0x8f,
        0x68, 0xaa, 0x1d, 0xdb, 0xd3, 0x7f, 0x8d, 0x98,
        0x9c, 0x16, 0x8c, 0xc3, 0xcd, 0xd9, 0xdb, 0x08,
        0xe6, 0x36, 0x60, 0xb6, 0x36, 0xdc, 0x1d, 0x59,
        0xb6, 0x5f, 0x01, 0x5e
    };
2605 2606 2607 2608 2609 2610 2611 2612 2613 2614

    dwLen=84;
    result = CryptImportKey(hProv, abPlainPublicKey, dwLen, 0, 0, &hPublicKey);
    ok(result, "failed to import the public key\n");

    dwDataLen=sizeof(algID);
    result = CryptGetKeyParam(hPublicKey, KP_ALGID, (LPBYTE)&algID, &dwDataLen, 0);
    ok(result, "failed to get the KP_ALGID from the imported public key\n");
    ok(algID == CALG_RSA_KEYX, "Expected CALG_RSA_KEYX, got %x\n", algID);
        
2615 2616 2617 2618 2619
    dwVal = 0xdeadbeef;
    dwDataLen = sizeof(DWORD);
    result = CryptGetKeyParam(hPublicKey, KP_PERMISSIONS, (BYTE*)&dwVal, &dwDataLen, 0);
    ok(result, "%08x\n", GetLastError());
    ok(dwVal ==
2620 2621
        (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
        broken(dwVal == 0xffffffff), /* Win9x/NT4 */
2622 2623
        "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
        " got %08x\n", dwVal);
2624 2625
    result = CryptExportKey(hPublicKey, 0, PUBLICKEYBLOB, 0, emptyKey, &dwLen);
    ok(result, "failed to export the fresh imported public key\n");
2626
    ok(dwLen == 84, "Expected exported key to be 84 bytes long but got %d bytes.\n",dwLen);
2627
    ok(!memcmp(emptyKey, abPlainPublicKey, dwLen), "exported key is different from the imported key\n");
2628 2629

    CryptDestroyKey(hPublicKey);
2630

2631
    /* imports into AT_SIGNATURE key container */
2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650
    result = CryptImportKey(hProv, priv_key_with_high_bit,
        sizeof(priv_key_with_high_bit), 0, CRYPT_EXPORTABLE, &hPrivKey);
    ok(result, "CryptImportKey failed: %08x\n", GetLastError());

    result = CryptExportKey(hPrivKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwDataLen);
    ok(result, "CryptExportKey failed: %08x\n", GetLastError());
    exported_key = HeapAlloc(GetProcessHeap(), 0, dwDataLen);
    result = CryptExportKey(hPrivKey, 0, PRIVATEKEYBLOB, 0, exported_key,
        &dwDataLen);
    ok(result, "CryptExportKey failed: %08x\n", GetLastError());

    ok(dwDataLen == sizeof(expected_exported_priv_key), "unexpected size %d\n",
        dwDataLen);
    ok(!memcmp(exported_key, expected_exported_priv_key, dwDataLen),
        "unexpected value\n");

    HeapFree(GetProcessHeap(), 0, exported_key);

    CryptDestroyKey(hPrivKey);
2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703

    /* imports into AT_KEYEXCHANGE key container */
    result = CryptImportKey(hProv, abPlainPrivateKey,
                            sizeof(abPlainPrivateKey), 0, 0, &hPrivKey);
    ok(result, "CryptImportKey failed: %08x\n", GetLastError());

    result = CryptExportKey(hPrivKey, 0, PUBLICKEYBLOB, 0, NULL, &dwDataLen);
    ok(result, "CryptExportKey failed: %08x\n", GetLastError());
    exported_key = HeapAlloc(GetProcessHeap(), 0, dwDataLen);
    result = CryptExportKey(hPrivKey, 0, PUBLICKEYBLOB, 0, exported_key,
        &dwDataLen);
    ok(result, "CryptExportKey failed: %08x\n", GetLastError());
    CryptDestroyKey(hPrivKey);

    /* getting the public key from AT_KEYEXCHANGE, and compare it */
    result = CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hPrivKey);
    ok(result, "CryptGetUserKey failed: %08x\n", GetLastError());
    result = CryptExportKey(hPrivKey, 0, PUBLICKEYBLOB, 0, NULL, &dwDataLen);
    ok(result, "CryptExportKey failed: %08x\n", GetLastError());
    exported_key2 = HeapAlloc(GetProcessHeap(), 0, dwDataLen);
    result = CryptExportKey(hPrivKey, 0, PUBLICKEYBLOB, 0, exported_key2,
        &dwDataLen);
    ok(result, "CryptExportKey failed: %08x\n", GetLastError());
    CryptDestroyKey(hPrivKey);

    result = !memcmp(exported_key, exported_key2, dwDataLen);
    ok(result, "unexpected value\n");
    if (!result && winetest_debug > 1) {
        trace("Expected public key (%u):\n", dwDataLen);
        trace_hex(exported_key, dwDataLen);
        trace("AT_KEYEXCHANGE public key (%u):\n", dwDataLen);
        trace_hex(exported_key2, dwDataLen);
    }
    HeapFree(GetProcessHeap(), 0, exported_key2);

    /* importing a public key doesn't update key container at all */
    result = CryptImportKey(hProv, abPlainPublicKey,
                            sizeof(abPlainPublicKey), 0, 0, &hPublicKey);
    ok(result, "failed to import the public key\n");
    CryptDestroyKey(hPublicKey);

    /* getting the public key again, and compare it */
    result = CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hPrivKey);
    ok(result, "CryptGetUserKey failed: %08x\n", GetLastError());
    result = CryptExportKey(hPrivKey, 0, PUBLICKEYBLOB, 0, NULL, &dwDataLen);
    ok(result, "CryptExportKey failed: %08x\n", GetLastError());
    exported_key2 = HeapAlloc(GetProcessHeap(), 0, dwDataLen);
    result = CryptExportKey(hPrivKey, 0, PUBLICKEYBLOB, 0, exported_key2,
        &dwDataLen);
    ok(result, "CryptExportKey failed: %08x\n", GetLastError());
    CryptDestroyKey(hPrivKey);

    result = !memcmp(exported_key, exported_key2, dwDataLen);
2704
    ok(result, "unexpected value\n");
2705 2706 2707 2708 2709 2710 2711 2712 2713
    if (!result && winetest_debug > 1) {
        trace("Expected public key (%u):\n", dwDataLen);
        trace_hex(exported_key, dwDataLen);
        trace("AT_KEYEXCHANGE public key (%u):\n", dwDataLen);
        trace_hex(exported_key2, dwDataLen);
    }

    HeapFree(GetProcessHeap(), 0, exported_key);
    HeapFree(GetProcessHeap(), 0, exported_key2);
2714
}
2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777

static void test_import_hmac(void)
{
    /* Test cases from RFC 2202, section 3 */
    static const struct rfc2202_test_case {
        const char *key;
        DWORD key_len;
        const char *data;
        const DWORD data_len;
        const char *digest;
    } cases[] = {
        { "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
          "\x0b\x0b\x0b\x0b", 20,
          "Hi There", 8,
          "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e"
          "\xf1\x46\xbe\x00" },
        { "Jefe", 4,
          "what do ya want for nothing?", 28,
          "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c"
          "\x25\x9a\x7c\x79" },
        { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
          "\xaa\xaa\xaa\xaa", 20,
          "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
          "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
          "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
          "\xdd\xdd", 50,
          "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f"
          "\x63\xf1\x75\xd3" },
        { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
          "\x11\x12\x13\x14\x15\x16\x17\x18\x19", 25,
          "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
          "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
          "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
          "\xcd\xcd", 50,
          "\x4c\x90\x07\xF4\x02\x62\x50\xc6\xbc\x84\x14\xf9\xbf\x50\xc8\x6c"
          "\x2d\x72\x35\xda" },
        { "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
          "\x0c\x0c\x0c\x0c", 20,
          "Test With Truncation", 20,
          "\x4c\x1a\x03\x42\x4b\x55\xe0\x7f\xe7\xf2\x7b\xe1\xd5\x8b\xb9\x32"
          "\x4a\x9a\x5a\x04" },
        { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
          "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
          "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
          "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
          "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
          80,
          "Test Using Larger Than Block-Size Key - Hash Key First", 54,
          "\xaa\x4a\xe5\xe1\x52\x72\xd0\x0e\x95\x70\x56\x37\xce\x8a\x3b\x55"
          "\xed\x40\x21\x12" },
        { "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
          "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
          "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
          "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
          "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
          80,
          "Test Using Larger Than Block-Size Key and Larger "
          "Than One Block-Size Data", 73,
          "\xe8\xe9\x9D\x0f\x45\x23\x7d\x78\x6d\x6b\xba\xa7\x96\x5c\x78\x08"
          "\xbb\xff\x1a\x91" }
    };
    DWORD i;

2778
    for (i = 0; i < ARRAY_SIZE(cases); i++)
2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815
    {
        const struct rfc2202_test_case *test_case = &cases[i];
        DWORD size = sizeof(BLOBHEADER) + sizeof(DWORD) + test_case->key_len;
        BYTE *blob = HeapAlloc(GetProcessHeap(), 0, size);

        if (blob)
        {
            BLOBHEADER *header = (BLOBHEADER *)blob;
            DWORD *key_len = (DWORD *)(header + 1);
            BYTE *key_bytes = (BYTE *)(key_len + 1);
            BOOL result;
            HCRYPTKEY key;

            header->bType = PLAINTEXTKEYBLOB;
            header->bVersion = CUR_BLOB_VERSION;
            header->reserved = 0;
            header->aiKeyAlg = CALG_RC2;
            *key_len = test_case->key_len;
            memcpy(key_bytes, test_case->key, *key_len);
            result = CryptImportKey(hProv, blob, size, 0, CRYPT_IPSEC_HMAC_KEY, &key);
            ok(result || broken(GetLastError() == NTE_BAD_FLAGS /* Win2k */), "CryptImportKey failed on test case %d: %08x\n", i, GetLastError());
            if (result)
            {
                HCRYPTHASH hash;
                HMAC_INFO hmac_info = { CALG_SHA1, 0 };
                BYTE digest[20];
                DWORD digest_size;

                result = CryptCreateHash(hProv, CALG_HMAC, key, 0, &hash);
                ok(result, "CryptCreateHash failed on test case %d: %08x\n", i, GetLastError());
                result = CryptSetHashParam(hash, HP_HMAC_INFO, (BYTE *)&hmac_info, 0);
                ok(result, "CryptSetHashParam failed on test case %d: %08x\n", i, GetLastError());
                result = CryptHashData(hash, (const BYTE *)test_case->data, test_case->data_len, 0);
                ok(result, "CryptHashData failed on test case %d: %08x\n", i, GetLastError());
                digest_size = sizeof(digest);
                result = CryptGetHashParam(hash, HP_HASHVAL, digest, &digest_size, 0);
                ok(result, "CryptGetHashParam failed on test case %d: %08x\n", i, GetLastError());
2816
                ok(!memcmp(digest, test_case->digest, sizeof(digest)), "Unexpected value on test case %d\n", i);
2817 2818 2819 2820 2821 2822 2823
                CryptDestroyHash(hash);
                CryptDestroyKey(key);
            }
            HeapFree(GetProcessHeap(), 0, blob);
        }
    }
}
2824
        
Mike McCormack's avatar
Mike McCormack committed
2825
static void test_schannel_provider(void)
2826 2827
{
    HCRYPTPROV hProv;
2828 2829
    HCRYPTKEY hRSAKey, hMasterSecret, hServerWriteKey, hServerWriteMACKey;
    HCRYPTHASH hMasterHash, hTLS1PRF, hHMAC;
2830 2831 2832 2833
    BOOL result;
    DWORD dwLen;
    SCHANNEL_ALG saSChannelAlg;
    CRYPT_DATA_BLOB data_blob;
2834
    HMAC_INFO hmacInfo = { CALG_MD5, NULL, 0, NULL, 0 };
2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859
    BYTE abTLS1Master[140] = {
        0x01, 0x02, 0x00, 0x00, 0x06, 0x4c, 0x00, 0x00, 
        0x00, 0xa4, 0x00, 0x00, 0x5b, 0x13, 0xc7, 0x68, 
        0xd8, 0x55, 0x23, 0x5d, 0xbc, 0xa6, 0x9d, 0x97, 
        0x0e, 0xcd, 0x6b, 0xcf, 0xc0, 0xdc, 0xc5, 0x53, 
        0x28, 0xa0, 0xca, 0xc1, 0x63, 0x4e, 0x3a, 0x24, 
        0x22, 0xe5, 0x4d, 0x15, 0xbb, 0xa5, 0x06, 0xc3, 
        0x98, 0x25, 0xdc, 0x35, 0xd3, 0xdb, 0xab, 0xb8, 
        0x44, 0x1b, 0xfe, 0x63, 0x88, 0x7c, 0x2e, 0x6d, 
        0x34, 0xd9, 0x0f, 0x7e, 0x2f, 0xc2, 0xb2, 0x6e, 
        0x56, 0xfa, 0xab, 0xb2, 0x88, 0xf6, 0x15, 0x6e, 
        0xa8, 0xcd, 0x70, 0x16, 0x94, 0x61, 0x07, 0x40, 
        0x9e, 0x25, 0x22, 0xf8, 0x64, 0x9f, 0xcc, 0x0b, 
        0xf1, 0x92, 0x4d, 0xfe, 0xc3, 0x5d, 0x52, 0xdb, 
        0x0f, 0xff, 0x12, 0x0f, 0x49, 0x43, 0x7d, 0xc6, 
        0x52, 0x61, 0xb0, 0x06, 0xc8, 0x1b, 0x90, 0xac, 
        0x09, 0x7e, 0x4b, 0x95, 0x69, 0x3b, 0x0d, 0x41, 
        0x1b, 0x4c, 0x65, 0x75, 0x4d, 0x85, 0x16, 0xc4, 
        0xd3, 0x1e, 0x82, 0xb3
    };
    BYTE abServerSecret[33] = "Super Secret Server Secret 12345";
    BYTE abClientSecret[33] = "Super Secret Client Secret 12345";
    BYTE abHashedHandshakes[37] = "123456789012345678901234567890123456";
    BYTE abClientFinished[16] = "client finished";
    BYTE abData[16] = "Wine rocks!";
2860
    BYTE abMD5Hash[16];
2861 2862 2863 2864 2865 2866 2867 2868
    static const BYTE abEncryptedData[16] = {
        0x13, 0xd2, 0xdd, 0xeb, 0x6c, 0x3f, 0xbe, 0xb2,
        0x04, 0x86, 0xb5, 0xe5, 0x08, 0xe5, 0xf3, 0x0d    
    };
    static const BYTE abPRF[16] = {
        0xa8, 0xb2, 0xa6, 0xef, 0x83, 0x4e, 0x74, 0xb1,
        0xf3, 0xb1, 0x51, 0x5a, 0x1a, 0x2b, 0x11, 0x31
    };
2869 2870 2871 2872 2873
    static const BYTE abMD5[16] = {
        0xe1, 0x65, 0x3f, 0xdb, 0xbb, 0x3d, 0x99, 0x3c,
        0x3d, 0xca, 0x6a, 0x6f, 0xfa, 0x15, 0x4e, 0xaa
    };
    
2874
    result = CryptAcquireContextA(&hProv, NULL, NULL, PROV_RSA_SCHANNEL, CRYPT_VERIFYCONTEXT|CRYPT_NEWKEYSET);
2875 2876 2877 2878 2879
    if (!result)
    {
        win_skip("no PROV_RSA_SCHANNEL support\n");
        return;
    }
2880 2881 2882 2883
    ok (result, "%08x\n", GetLastError());
    if (result)
        CryptReleaseContext(hProv, 0);

2884
    result = CryptAcquireContextA(&hProv, NULL, NULL, PROV_RSA_SCHANNEL, CRYPT_VERIFYCONTEXT);
2885
    ok (result, "%08x\n", GetLastError());
2886 2887 2888 2889 2890 2891 2892
    if (!result) return;
    
    /* To get deterministic results, we import the TLS1 master secret (which
     * is typically generated from a random generator). Therefore, we need
     * an RSA key. */
    dwLen = (DWORD)sizeof(abPlainPrivateKey);
    result = CryptImportKey(hProv, abPlainPrivateKey, dwLen, 0, 0, &hRSAKey);
2893
    ok (result, "%08x\n", GetLastError());
2894 2895 2896 2897
    if (!result) return;

    dwLen = (DWORD)sizeof(abTLS1Master);
    result = CryptImportKey(hProv, abTLS1Master, dwLen, hRSAKey, 0, &hMasterSecret);
2898
    ok (result, "%08x\n", GetLastError());
2899
    if (!result) return;    
2900 2901 2902 2903 2904 2905 2906 2907 2908 2909

    /* Deriving a hash from the master secret. This is due to the CryptoAPI architecture.
     * (Keys can only be derived from hashes, not from other keys.)
     * The hash can't be created yet because the key doesn't have the client
     * random or server random set.
     */
    result = CryptCreateHash(hProv, CALG_SCHANNEL_MASTER_HASH, hMasterSecret, 0, &hMasterHash);
    ok (!result && GetLastError() == ERROR_INVALID_PARAMETER,
        "expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());

2910 2911 2912 2913 2914
    /* Setting the TLS1 client and server random parameters, as well as the 
     * MAC and encryption algorithm parameters. */
    data_blob.cbData = 33;
    data_blob.pbData = abClientSecret;
    result = CryptSetKeyParam(hMasterSecret, KP_CLIENT_RANDOM, (BYTE*)&data_blob, 0);
2915
    ok (result, "%08x\n", GetLastError());
2916 2917 2918 2919 2920
    if (!result) return;

    data_blob.cbData = 33;
    data_blob.pbData = abServerSecret;
    result = CryptSetKeyParam(hMasterSecret, KP_SERVER_RANDOM, (BYTE*)&data_blob, 0);
2921
    ok (result, "%08x\n", GetLastError());
2922
    if (!result) return;
2923 2924

    result = CryptCreateHash(hProv, CALG_SCHANNEL_MASTER_HASH, hMasterSecret, 0, &hMasterHash);
2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936
    ok (result ||
        broken(!result), /* Windows 8 and greater */
        "%08x\n", GetLastError());
    if (!result)
    {
        win_skip("Broken TLS1 hash creation\n");
        CryptDestroyKey(hRSAKey);
        CryptDestroyKey(hMasterSecret);
        CryptReleaseContext(hProv, 0);
        CryptAcquireContextA(&hProv, NULL, NULL, PROV_RSA_SCHANNEL, CRYPT_DELETEKEYSET);
        return;
    }
2937 2938 2939 2940 2941 2942 2943 2944 2945 2946

    /* Deriving the server write encryption key from the master hash can't
     * succeed before the encryption key algorithm is set.
     */
    result = CryptDeriveKey(hProv, CALG_SCHANNEL_ENC_KEY, hMasterHash, CRYPT_SERVER, &hServerWriteKey);
    ok (!result && GetLastError() == NTE_BAD_FLAGS,
        "expected NTE_BAD_FLAGS, got %08x\n", GetLastError());

    CryptDestroyHash(hMasterHash);

2947 2948 2949 2950 2951 2952
    saSChannelAlg.dwUse = SCHANNEL_ENC_KEY;
    saSChannelAlg.Algid = CALG_DES;
    saSChannelAlg.cBits = 64;
    saSChannelAlg.dwFlags = 0;
    saSChannelAlg.dwReserved = 0;
    result = CryptSetKeyParam(hMasterSecret, KP_SCHANNEL_ALG, (PBYTE)&saSChannelAlg, 0);
2953
    ok (result, "%08x\n", GetLastError());
2954 2955 2956 2957 2958 2959 2960 2961
    if (!result) return;

    saSChannelAlg.dwUse = SCHANNEL_MAC_KEY;
    saSChannelAlg.Algid = CALG_MD5;
    saSChannelAlg.cBits = 128;
    saSChannelAlg.dwFlags = 0;
    saSChannelAlg.dwReserved = 0;
    result = CryptSetKeyParam(hMasterSecret, KP_SCHANNEL_ALG, (PBYTE)&saSChannelAlg, 0);
2962
    ok (result, "%08x\n", GetLastError());
2963 2964 2965
    if (!result) return;

    result = CryptCreateHash(hProv, CALG_SCHANNEL_MASTER_HASH, hMasterSecret, 0, &hMasterHash);
2966
    ok (result, "%08x\n", GetLastError());
2967 2968 2969 2970
    if (!result) return;

    /* Deriving the server write encryption key from the master hash */
    result = CryptDeriveKey(hProv, CALG_SCHANNEL_ENC_KEY, hMasterHash, CRYPT_SERVER, &hServerWriteKey);
2971
    ok (result, "%08x\n", GetLastError());
2972 2973 2974 2975 2976
    if (!result) return;

    /* Encrypting some data with the server write encryption key and checking the result. */
    dwLen = 12;
    result = CryptEncrypt(hServerWriteKey, 0, TRUE, 0, abData, &dwLen, 16);
2977
    ok (result && (dwLen == 16) && !memcmp(abData, abEncryptedData, 16), "%08x\n", GetLastError());
2978 2979 2980

    /* Second test case: Test the TLS1 pseudo random number function. */
    result = CryptCreateHash(hProv, CALG_TLS1PRF, hMasterSecret, 0, &hTLS1PRF);
2981
    ok (result, "%08x\n", GetLastError());
2982 2983 2984 2985 2986 2987
    if (!result) return;

    /* Set the label and seed parameters for the random number function */
    data_blob.cbData = 36;
    data_blob.pbData = abHashedHandshakes;
    result = CryptSetHashParam(hTLS1PRF, HP_TLS1PRF_SEED, (BYTE*)&data_blob, 0);
2988
    ok (result, "%08x\n", GetLastError());
2989 2990 2991 2992 2993
    if (!result) return;

    data_blob.cbData = 15;
    data_blob.pbData = abClientFinished;
    result = CryptSetHashParam(hTLS1PRF, HP_TLS1PRF_LABEL, (BYTE*)&data_blob, 0);
2994
    ok (result, "%08x\n", GetLastError());
2995 2996 2997 2998 2999 3000
    if (!result) return;

    /* Generate some pseudo random bytes and check if they are correct. */
    dwLen = (DWORD)sizeof(abData);
    result = CryptGetHashParam(hTLS1PRF, HP_HASHVAL, abData, &dwLen, 0);
    ok (result && (dwLen==(DWORD)sizeof(abData)) && !memcmp(abData, abPRF, sizeof(abData)), 
3001
        "%08x\n", GetLastError());
3002

3003 3004 3005
    /* Third test case. Derive the server write mac key. Derive an HMAC object from this one.
     * Hash some data with the HMAC. Compare results. */
    result = CryptDeriveKey(hProv, CALG_SCHANNEL_MAC_KEY, hMasterHash, CRYPT_SERVER, &hServerWriteMACKey);
3006
    ok (result, "%08x\n", GetLastError());
3007 3008 3009
    if (!result) return;
    
    result = CryptCreateHash(hProv, CALG_HMAC, hServerWriteMACKey, 0, &hHMAC);
3010
    ok (result, "%08x\n", GetLastError());
3011 3012 3013
    if (!result) return;

    result = CryptSetHashParam(hHMAC, HP_HMAC_INFO, (PBYTE)&hmacInfo, 0);
3014
    ok (result, "%08x\n", GetLastError());
3015 3016 3017
    if (!result) return;

    result = CryptHashData(hHMAC, abData, (DWORD)sizeof(abData), 0);
3018
    ok (result, "%08x\n", GetLastError());
3019 3020 3021 3022
    if (!result) return;

    dwLen = (DWORD)sizeof(abMD5Hash);
    result = CryptGetHashParam(hHMAC, HP_HASHVAL, abMD5Hash, &dwLen, 0);
3023
    ok (result && (dwLen == 16) && !memcmp(abMD5Hash, abMD5, 16), "%08x\n", GetLastError());
3024 3025

    CryptDestroyHash(hHMAC);
3026 3027
    CryptDestroyHash(hTLS1PRF);
    CryptDestroyHash(hMasterHash);
3028
    CryptDestroyKey(hServerWriteMACKey);
3029 3030 3031 3032
    CryptDestroyKey(hServerWriteKey);
    CryptDestroyKey(hRSAKey);
    CryptDestroyKey(hMasterSecret);
    CryptReleaseContext(hProv, 0);
3033
    CryptAcquireContextA(&hProv, NULL, NULL, PROV_RSA_SCHANNEL, CRYPT_DELETEKEYSET);
3034 3035
}

3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048
/* Test that a key can be used to encrypt data and exported, and that, when
 * the exported key is imported again, can be used to decrypt the original
 * data again.
 */
static void test_rsa_round_trip(void)
{
    static const char test_string[] = "Well this is a fine how-do-you-do.";
    HCRYPTPROV prov;
    HCRYPTKEY signKey, keyExchangeKey;
    BOOL result;
    BYTE data[256], *exportedKey;
    DWORD dataLen, keyLen;

3049
    CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3050 3051 3052
     CRYPT_DELETEKEYSET);

    /* Generate a new key... */
3053
    result = CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3054
     CRYPT_NEWKEYSET);
3055
    ok(result, "CryptAcquireContextA failed: %08x\n", GetLastError());
3056 3057 3058 3059 3060 3061 3062 3063 3064
    result = CryptGenKey(prov, CALG_RSA_KEYX, CRYPT_EXPORTABLE, &signKey);
    ok(result, "CryptGenKey with CALG_RSA_KEYX failed with error %08x\n", GetLastError());
    result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &keyExchangeKey);
    ok(result, "CryptGetUserKey failed: %08x\n", GetLastError());
    /* encrypt some data with it... */
    memcpy(data, test_string, strlen(test_string) + 1);
    dataLen = strlen(test_string) + 1;
    result = CryptEncrypt(keyExchangeKey, 0, TRUE, 0, data, &dataLen,
                          sizeof(data));
3065 3066
    ok(result || broken(GetLastError() == NTE_BAD_KEY /* Win9x/2000 */) ||
       broken(GetLastError() == NTE_PERM /* NT4 */),
3067
       "CryptEncrypt failed: %08x\n", GetLastError());
3068 3069 3070 3071 3072 3073 3074
    /* export the key... */
    result = CryptExportKey(keyExchangeKey, 0, PRIVATEKEYBLOB, 0, NULL,
                            &keyLen);
    ok(result, "CryptExportKey failed: %08x\n", GetLastError());
    exportedKey = HeapAlloc(GetProcessHeap(), 0, keyLen);
    result = CryptExportKey(keyExchangeKey, 0, PRIVATEKEYBLOB, 0, exportedKey,
                            &keyLen);
3075
    ok(result, "CryptExportKey failed: %08x\n", GetLastError());
3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086
    /* destroy the key... */
    CryptDestroyKey(keyExchangeKey);
    CryptDestroyKey(signKey);
    /* import the key again... */
    result = CryptImportKey(prov, exportedKey, keyLen, 0, 0, &keyExchangeKey);
    ok(result, "CryptImportKey failed: %08x\n", GetLastError());
    HeapFree(GetProcessHeap(), 0, exportedKey);
    /* and decrypt the data encrypted with the original key with the imported
     * key.
     */
    result = CryptDecrypt(keyExchangeKey, 0, TRUE, 0, data, &dataLen);
3087 3088
    ok(result || broken(GetLastError() == NTE_BAD_KEY /* Win9x/2000 */) ||
       broken(GetLastError() == NTE_PERM /* NT4 */),
3089
       "CryptDecrypt failed: %08x\n", GetLastError());
3090 3091 3092
    if (result)
    {
        ok(dataLen == sizeof(test_string), "unexpected size %d\n", dataLen);
3093
        ok(!memcmp(data, test_string, sizeof(test_string)), "unexpected value\n");
3094
    }
3095
    CryptDestroyKey(keyExchangeKey);
3096 3097
    CryptReleaseContext(prov, 0);

3098
    CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3099 3100 3101
     CRYPT_DELETEKEYSET);
}

Mike McCormack's avatar
Mike McCormack committed
3102
static void test_enum_container(void)
3103
{
3104
    BYTE abContainerName[MAX_PATH + 2]; /* Larger than maximum name len */
3105 3106 3107 3108 3109
    DWORD dwBufferLen;
    BOOL result, fFound = FALSE;

    /* If PP_ENUMCONTAINERS is queried with CRYPT_FIRST and abData == NULL, it returns
     * the maximum legal length of container names (which is MAX_PATH + 1 == 261) */
3110
    SetLastError(0xdeadbeef);
3111
    result = CryptGetProvParam(hProv, PP_ENUMCONTAINERS, NULL, &dwBufferLen, CRYPT_FIRST);
3112 3113
    ok (result, "%08x\n", GetLastError());
    ok (dwBufferLen == MAX_PATH + 1 ||
3114
        broken(dwBufferLen != MAX_PATH + 1), /* Win9x, WinMe, NT4 */
3115
        "Expected dwBufferLen to be (MAX_PATH + 1), it was : %d\n", dwBufferLen);
3116 3117 3118 3119

    /* If the result fits into abContainerName dwBufferLen is left untouched */
    dwBufferLen = (DWORD)sizeof(abContainerName);
    result = CryptGetProvParam(hProv, PP_ENUMCONTAINERS, abContainerName, &dwBufferLen, CRYPT_FIRST);
3120
    ok (result && dwBufferLen == (DWORD)sizeof(abContainerName), "%08x\n", GetLastError());
3121 3122 3123
    
    /* We only check, if the currently open 'winetest' container is among the enumerated. */
    do {
Mike McCormack's avatar
Mike McCormack committed
3124
        if (!strcmp((const char*)abContainerName, "winetest")) fFound = TRUE;
3125 3126 3127
        dwBufferLen = (DWORD)sizeof(abContainerName);
    } while (CryptGetProvParam(hProv, PP_ENUMCONTAINERS, abContainerName, &dwBufferLen, 0));
        
3128
    ok (fFound && GetLastError() == ERROR_NO_MORE_ITEMS, "%d, %08x\n", fFound, GetLastError());
3129 3130
}

3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157
static BYTE signBlob[] = {
0x07,0x02,0x00,0x00,0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x32,0x00,0x02,0x00,0x00,
0x01,0x00,0x01,0x00,0xf1,0x82,0x9e,0x84,0xb5,0x79,0x9a,0xbe,0x4d,0x06,0x20,0x21,
0xb1,0x89,0x0c,0xca,0xb0,0x35,0x72,0x18,0xc6,0x92,0xa8,0xe2,0xb1,0xe1,0xf6,0x56,
0x53,0x99,0x47,0x10,0x6e,0x1c,0x81,0xaf,0xb8,0xf9,0x5f,0xfe,0x76,0x7f,0x2c,0x93,
0xec,0x54,0x7e,0x5e,0xc2,0x25,0x3c,0x50,0x56,0x10,0x20,0x72,0x4a,0x93,0x03,0x12,
0x29,0x98,0xcc,0xc9,0x47,0xbf,0xbf,0x93,0xcc,0xb0,0xe5,0x53,0x14,0xc8,0x7e,0x1f,
0xa4,0x03,0x2d,0x8e,0x84,0x7a,0xd2,0xeb,0xf7,0x92,0x5e,0xa2,0xc7,0x6b,0x35,0x7d,
0xcb,0x60,0xae,0xfb,0x07,0x78,0x11,0x73,0xb5,0x79,0xe5,0x7e,0x96,0xe3,0x50,0x95,
0x80,0x0e,0x1c,0xf6,0x56,0xc6,0xe9,0x0a,0xaf,0x03,0xc6,0xdc,0x9a,0x81,0xcf,0x7a,
0x63,0x16,0x43,0xcd,0xab,0x74,0xa1,0x7d,0xe7,0xe0,0x75,0x6d,0xbd,0x19,0xae,0x0b,
0xa3,0x7f,0x6a,0x7b,0x05,0x4e,0xbc,0xec,0x18,0xfc,0x19,0xc2,0x00,0xf0,0x6a,0x2e,
0xc4,0x31,0x73,0xba,0x07,0xcc,0x9d,0x57,0xeb,0xc7,0x7c,0x00,0x7d,0x5d,0x11,0x16,
0x42,0x4b,0xe5,0x3a,0xf5,0xc7,0xf8,0xee,0xc3,0x2c,0x0d,0x86,0x03,0xe2,0xaf,0xb2,
0xd2,0x91,0xdb,0x71,0xcd,0xdf,0x81,0x5f,0x06,0xfc,0x48,0x0d,0xb6,0x88,0x9f,0xc1,
0x5e,0x24,0xa2,0x05,0x4f,0x30,0x2e,0x8f,0x8b,0x0d,0x76,0xa1,0x84,0xda,0x7b,0x44,
0x70,0x85,0xf1,0x50,0xb1,0x21,0x3d,0xe2,0x57,0x3d,0xd0,0x01,0x93,0x49,0x8e,0xc5,
0x0b,0x8b,0x0d,0x7b,0x08,0xe9,0x14,0xec,0x20,0x0d,0xea,0x02,0x00,0x63,0xe8,0x0a,
0x52,0xe8,0xfb,0x21,0xbd,0x37,0xde,0x4c,0x4d,0xc2,0xf6,0xb9,0x0d,0x2a,0xc3,0xe2,
0xc9,0xdf,0x48,0x3e,0x55,0x3d,0xe3,0xc0,0x22,0x37,0xf9,0x52,0xc0,0xd7,0x61,0x22,
0xb6,0x85,0x86,0x07 };

static void test_null_provider(void)
{
    HCRYPTPROV prov;
    HCRYPTKEY key;
    BOOL result;
3158 3159
    DWORD keySpec, dataLen,dwParam;
    char szName[MAX_PATH];
3160

3161
    result = CryptAcquireContextA(NULL, szContainer, NULL, 0, 0);
3162
    ok(!result && GetLastError() == NTE_BAD_PROV_TYPE,
3163
     "Expected NTE_BAD_PROV_TYPE, got %08x\n", GetLastError());
3164
    result = CryptAcquireContextA(NULL, szContainer, NULL, PROV_RSA_FULL, 0);
3165 3166
    ok(!result && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == NTE_BAD_KEYSET),
     "Expected ERROR_INVALID_PARAMETER or NTE_BAD_KEYSET, got %08x\n", GetLastError());
3167
    result = CryptAcquireContextA(NULL, szContainer, NULL, PROV_RSA_FULL,
3168
     CRYPT_DELETEKEYSET);
3169 3170
    ok(!result && ( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == NTE_BAD_KEYSET),
     "Expected ERROR_INVALID_PARAMETER or NTE_BAD_KEYSET, got %08x\n", GetLastError());
3171
    result = CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3172 3173
     CRYPT_DELETEKEYSET);
    ok(!result && GetLastError() == NTE_BAD_KEYSET,
3174
     "Expected NTE_BAD_KEYSET, got %08x\n", GetLastError());
3175
    result = CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL, 0);
3176
    ok(!result && GetLastError() == NTE_BAD_KEYSET,
3177
     "Expected NTE_BAD_KEYSET, got %08x\n", GetLastError());
3178 3179

    /* Delete the default container. */
3180
    CryptAcquireContextA(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
3181 3182 3183
    /* Once you've deleted the default container you can't open it as if it
     * already exists.
     */
3184
    result = CryptAcquireContextA(&prov, NULL, NULL, PROV_RSA_FULL, 0);
3185
    ok(!result && GetLastError() == NTE_BAD_KEYSET,
3186
     "Expected NTE_BAD_KEYSET, got %08x\n", GetLastError());
3187
    /* But you can always open the default container for CRYPT_VERIFYCONTEXT. */
3188
    result = CryptAcquireContextA(&prov, NULL, NULL, PROV_RSA_FULL,
3189
     CRYPT_VERIFYCONTEXT);
3190
    ok(result, "CryptAcquireContextA failed: %08x\n", GetLastError());
3191 3192 3193 3194 3195
    if (!result) return;
    dataLen = sizeof(keySpec);
    result = CryptGetProvParam(prov, PP_KEYSPEC, (LPBYTE)&keySpec, &dataLen, 0);
    if (result)
        ok(keySpec == (AT_KEYEXCHANGE | AT_SIGNATURE),
3196
         "Expected AT_KEYEXCHANGE | AT_SIGNATURE, got %08x\n", keySpec);
3197 3198 3199 3200 3201
    /* Even though PP_KEYSPEC says both AT_KEYEXCHANGE and AT_SIGNATURE are
     * supported, you can't get the keys from this container.
     */
    result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
    ok(!result && GetLastError() == NTE_NO_KEY,
3202
     "Expected NTE_NO_KEY, got %08x\n", GetLastError());
3203 3204
    result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
    ok(!result && GetLastError() == NTE_NO_KEY,
3205
     "Expected NTE_NO_KEY, got %08x\n", GetLastError());
3206
    result = CryptReleaseContext(prov, 0);
3207
    ok(result, "CryptReleaseContext failed: %08x\n", GetLastError());
3208
    /* You can create a new default container. */
3209
    result = CryptAcquireContextA(&prov, NULL, NULL, PROV_RSA_FULL,
3210
     CRYPT_NEWKEYSET);
3211
    ok(result, "CryptAcquireContextA failed: %08x\n", GetLastError());
3212 3213 3214
    /* But you still can't get the keys (until one's been generated.) */
    result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
    ok(!result && GetLastError() == NTE_NO_KEY,
3215
     "Expected NTE_NO_KEY, got %08x\n", GetLastError());
3216 3217
    result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
    ok(!result && GetLastError() == NTE_NO_KEY,
3218
     "Expected NTE_NO_KEY, got %08x\n", GetLastError());
3219
    CryptReleaseContext(prov, 0);
3220
    CryptAcquireContextA(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
3221

3222
    CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3223
     CRYPT_DELETEKEYSET);
3224
    result = CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL, 0);
3225
    ok(!result && GetLastError() == NTE_BAD_KEYSET,
3226
     "Expected NTE_BAD_KEYSET, got %08x\n", GetLastError());
3227
    result = CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3228 3229
     CRYPT_VERIFYCONTEXT);
    ok(!result && GetLastError() == NTE_BAD_FLAGS,
3230
     "Expected NTE_BAD_FLAGS, got %08x\n", GetLastError());
3231
    result = CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3232
     CRYPT_NEWKEYSET);
3233
    ok(result, "CryptAcquireContextA failed: %08x\n", GetLastError());
3234
    if (!result) return;
3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247
    /* Test provider parameters getter */
    dataLen = sizeof(dwParam);
    result = CryptGetProvParam(prov, PP_PROVTYPE, (LPBYTE)&dwParam, &dataLen, 0);
    ok(result && dataLen == sizeof(dwParam) && dwParam == PROV_RSA_FULL,
        "Expected PROV_RSA_FULL, got 0x%08X\n",dwParam);
    dataLen = sizeof(dwParam);
    result = CryptGetProvParam(prov, PP_KEYSET_TYPE, (LPBYTE)&dwParam, &dataLen, 0);
    ok(result && dataLen == sizeof(dwParam) && dwParam == 0,
        "Expected 0, got 0x%08X\n",dwParam);
    dataLen = sizeof(dwParam);
    result = CryptGetProvParam(prov, PP_KEYSTORAGE, (LPBYTE)&dwParam, &dataLen, 0);
    ok(result && dataLen == sizeof(dwParam) && (dwParam & CRYPT_SEC_DESCR),
        "Expected CRYPT_SEC_DESCR to be set, got 0x%08X\n",dwParam);
3248
    dataLen = sizeof(keySpec);
3249
    SetLastError(0xdeadbeef);
3250
    result = CryptGetProvParam(prov, PP_KEYSPEC, (LPBYTE)&keySpec, &dataLen, 0);
3251 3252 3253 3254 3255
    if (!result && GetLastError() == NTE_BAD_TYPE)
        skip("PP_KEYSPEC is not supported (win9x or NT)\n");
    else
        ok(result && keySpec == (AT_KEYEXCHANGE | AT_SIGNATURE),
            "Expected AT_KEYEXCHANGE | AT_SIGNATURE, got %08x\n", keySpec);
3256 3257 3258 3259 3260 3261 3262 3263
    /* PP_CONTAINER parameter */
    dataLen = sizeof(szName);
    result = CryptGetProvParam(prov, PP_CONTAINER, (LPBYTE)szName, &dataLen, 0);
    ok(result && dataLen == strlen(szContainer)+1 && strcmp(szContainer,szName) == 0,
        "failed getting PP_CONTAINER. result = %s. Error 0x%08X. returned length = %d\n",
        (result)? "TRUE":"FALSE",GetLastError(),dataLen);
    /* PP_UNIQUE_CONTAINER parameter */
    dataLen = sizeof(szName);
3264
    SetLastError(0xdeadbeef);
3265
    result = CryptGetProvParam(prov, PP_UNIQUE_CONTAINER, (LPBYTE)szName, &dataLen, 0);
3266
    if (!result && GetLastError() == NTE_BAD_TYPE)
3267
    {
3268
        skip("PP_UNIQUE_CONTAINER is not supported (win9x or NT)\n");
3269
    }
3270
    else
3271 3272 3273 3274 3275 3276 3277
    {
        char container[MAX_PATH];

        ok(result, "failed getting PP_UNIQUE_CONTAINER : 0x%08X\n", GetLastError());
        uniquecontainer(container);
        todo_wine
        {
3278 3279 3280 3281 3282 3283
            ok(dataLen == strlen(container)+1 ||
               broken(dataLen == strlen(szContainer)+1) /* WinME */,
               "Expected a param length of 70, got %d\n", dataLen);
            ok(!strcmp(container, szName) ||
               broken(!strcmp(szName, szContainer)) /* WinME */,
               "Wrong container name : %s\n", szName);
3284 3285
        }
    }
3286 3287
    result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
    ok(!result && GetLastError() == NTE_NO_KEY,
3288
     "Expected NTE_NO_KEY, got %08x\n", GetLastError());
3289 3290
    result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
    ok(!result && GetLastError() == NTE_NO_KEY,
3291
     "Expected NTE_NO_KEY, got %08x\n", GetLastError());
3292 3293 3294 3295

    /* Importing a key exchange blob.. */
    result = CryptImportKey(prov, abPlainPrivateKey, sizeof(abPlainPrivateKey),
     0, 0, &key);
3296
    ok(result, "CryptImportKey failed: %08x\n", GetLastError());
3297 3298 3299
    CryptDestroyKey(key);
    /* allows access to the key exchange key.. */
    result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
3300
    ok(result, "CryptGetUserKey failed: %08x\n", GetLastError());
3301 3302 3303 3304
    CryptDestroyKey(key);
    /* but not to the private key. */
    result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
    ok(!result && GetLastError() == NTE_NO_KEY,
3305
     "Expected NTE_NO_KEY, got %08x\n", GetLastError());
3306
    CryptReleaseContext(prov, 0);
3307
    CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3308 3309 3310
     CRYPT_DELETEKEYSET);

    /* Whereas importing a sign blob.. */
3311
    result = CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3312
     CRYPT_NEWKEYSET);
3313
    ok(result, "CryptAcquireContextA failed: %08x\n", GetLastError());
3314 3315
    if (!result) return;
    result = CryptImportKey(prov, signBlob, sizeof(signBlob), 0, 0, &key);
3316
    ok(result, "CryptImportKey failed: %08x\n", GetLastError());
3317
    CryptDestroyKey(key);
3318 3319 3320
    /* doesn't allow access to the key exchange key.. */
    result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
    ok(!result && GetLastError() == NTE_NO_KEY,
3321
     "Expected NTE_NO_KEY, got %08x\n", GetLastError());
3322 3323
    /* but does to the private key. */
    result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
3324
    ok(result, "CryptGetUserKey failed: %08x\n", GetLastError());
3325
    CryptDestroyKey(key);
3326
    CryptReleaseContext(prov, 0);
3327

3328
    CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3329
     CRYPT_DELETEKEYSET);
3330

3331
    /* Test for being able to get a key generated with CALG_RSA_SIGN. */
3332
    result = CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3333
     CRYPT_NEWKEYSET);
3334
    ok(result, "CryptAcquireContextA failed: %08x\n", GetLastError());
3335 3336
    result = CryptGenKey(prov, CALG_RSA_SIGN, 0, &key);
    ok(result, "CryptGenKey with CALG_RSA_SIGN failed with error %08x\n", GetLastError());
3337
    CryptDestroyKey(key);
3338 3339 3340 3341 3342 3343 3344
    result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
    ok(!result, "expected CryptGetUserKey to fail\n");
    result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
    ok(result, "CryptGetUserKey with AT_SIGNATURE failed: %08x\n", GetLastError());
    CryptDestroyKey(key);
    CryptReleaseContext(prov, 0);

3345
    CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3346 3347 3348
     CRYPT_DELETEKEYSET);

    /* Test for being able to get a key generated with CALG_RSA_KEYX. */
3349
    result = CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3350
     CRYPT_NEWKEYSET);
3351
    ok(result, "CryptAcquireContextA failed: %08x\n", GetLastError());
3352 3353
    result = CryptGenKey(prov, CALG_RSA_KEYX, 0, &key);
    ok(result, "CryptGenKey with CALG_RSA_KEYX failed with error %08x\n", GetLastError());
3354
    CryptDestroyKey(key);
3355 3356
    result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
    ok(result, "CryptGetUserKey with AT_KEYEXCHANGE failed: %08x\n", GetLastError());
3357
    CryptDestroyKey(key);
3358 3359 3360 3361
    result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
    ok(!result, "expected CryptGetUserKey to fail\n");
    CryptReleaseContext(prov, 0);

3362
    CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3363
     CRYPT_DELETEKEYSET);
3364 3365 3366

    /* test for the bug in accessing the user key in a container
     */
3367
    result = CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3368
     CRYPT_NEWKEYSET);
3369
    ok(result, "CryptAcquireContextA failed: %08x\n", GetLastError());
3370 3371 3372 3373
    result = CryptGenKey(prov, AT_KEYEXCHANGE, 0, &key);
    ok(result, "CryptGenKey with AT_KEYEXCHANGE failed with error %08x\n", GetLastError());
    CryptDestroyKey(key);
    CryptReleaseContext(prov,0);
3374 3375
    result = CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,0);
    ok(result, "CryptAcquireContextA failed: 0x%08x\n", GetLastError());
3376 3377 3378
    result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
    ok (result, "CryptGetUserKey failed with error %08x\n", GetLastError());
    CryptDestroyKey(key);
3379
    CryptReleaseContext(prov, 0);
3380

3381
    CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3382 3383
     CRYPT_DELETEKEYSET);

3384
    /* test the machine key set */
3385
    CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3386
     CRYPT_DELETEKEYSET|CRYPT_MACHINE_KEYSET);
3387
    result = CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3388
     CRYPT_NEWKEYSET|CRYPT_MACHINE_KEYSET);
3389
    ok(result, "CryptAcquireContextA with CRYPT_MACHINE_KEYSET failed: %08x\n", GetLastError());
3390
    CryptReleaseContext(prov, 0);
3391
    result = CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3392
     CRYPT_MACHINE_KEYSET);
3393
    ok(result, "CryptAcquireContextA with CRYPT_MACHINE_KEYSET failed: %08x\n", GetLastError());
3394
    CryptReleaseContext(prov,0);
3395
    result = CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3396
       CRYPT_DELETEKEYSET|CRYPT_MACHINE_KEYSET);
3397
    ok(result, "CryptAcquireContextA with CRYPT_DELETEKEYSET|CRYPT_MACHINE_KEYSET failed: %08x\n",
3398
		GetLastError());
3399
    result = CryptAcquireContextA(&prov, szContainer, NULL, PROV_RSA_FULL,
3400 3401 3402 3403
     CRYPT_MACHINE_KEYSET);
    ok(!result && GetLastError() == NTE_BAD_KEYSET ,
	"Expected NTE_BAD_KEYSET, got %08x\n", GetLastError());

3404 3405
}

3406 3407 3408 3409 3410 3411 3412
static void test_key_permissions(void)
{
    HCRYPTKEY hKey1, hKey2;
    DWORD dwVal, dwLen;
    BOOL result;

    /* Create keys that are exportable */
3413
    if (!init_base_environment(NULL, CRYPT_EXPORTABLE))
3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424
        return;

    result = CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hKey1);
    ok (result, "%08x\n", GetLastError());
    if (!result) return;

    dwVal = 0xdeadbeef;
    dwLen = sizeof(DWORD);
    result = CryptGetKeyParam(hKey1, KP_PERMISSIONS, (BYTE*)&dwVal, &dwLen, 0);
    ok(result, "%08x\n", GetLastError());
    ok(dwVal ==
3425 3426
        (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_EXPORT|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
        broken(dwVal == 0xffffffff), /* Win9x/NT4 */
3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438
        "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_EXPORT|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
        " got %08x\n", dwVal);

    /* The key exchange key's public key may be exported.. */
    result = CryptExportKey(hKey1, 0, PUBLICKEYBLOB, 0, NULL, &dwLen);
    ok(result, "%08x\n", GetLastError());
    /* and its private key may be too. */
    result = CryptExportKey(hKey1, 0, PRIVATEKEYBLOB, 0, NULL, &dwLen);
    ok(result, "%08x\n", GetLastError());
    /* Turning off the key's export permissions is "allowed".. */
    dwVal &= ~CRYPT_EXPORT;
    result = CryptSetKeyParam(hKey1, KP_PERMISSIONS, (BYTE *)&dwVal, 0);
3439 3440 3441 3442
    ok(result ||
        broken(!result && GetLastError() == NTE_BAD_DATA) || /* W2K */
        broken(!result && GetLastError() == NTE_BAD_FLAGS), /* Win9x/WinME/NT4 */
        "%08x\n", GetLastError());
3443 3444 3445 3446 3447 3448
    /* but it has no effect. */
    dwVal = 0xdeadbeef;
    dwLen = sizeof(DWORD);
    result = CryptGetKeyParam(hKey1, KP_PERMISSIONS, (BYTE*)&dwVal, &dwLen, 0);
    ok(result, "%08x\n", GetLastError());
    ok(dwVal ==
3449 3450
        (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_EXPORT|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
        broken(dwVal == 0xffffffff), /* Win9x/NT4 */
3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469
        "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_EXPORT|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
        " got %08x\n", dwVal);
    /* Thus, changing the export flag of the key doesn't affect whether the key
     * may be exported.
     */
    result = CryptExportKey(hKey1, 0, PRIVATEKEYBLOB, 0, NULL, &dwLen);
    ok(result, "%08x\n", GetLastError());

    result = CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hKey2);
    ok (result, "%08x\n", GetLastError());

    /* A subsequent get of the same key, into a different handle, also doesn't
     * show that the permissions have been changed.
     */
    dwVal = 0xdeadbeef;
    dwLen = sizeof(DWORD);
    result = CryptGetKeyParam(hKey2, KP_PERMISSIONS, (BYTE*)&dwVal, &dwLen, 0);
    ok(result, "%08x\n", GetLastError());
    ok(dwVal ==
3470 3471
        (CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_EXPORT|CRYPT_DECRYPT|CRYPT_ENCRYPT) ||
        broken(dwVal == 0xffffffff), /* Win9x/NT4 */
3472 3473 3474 3475 3476 3477 3478 3479 3480
        "expected CRYPT_MAC|CRYPT_WRITE|CRYPT_READ|CRYPT_EXPORT|CRYPT_DECRYPT|CRYPT_ENCRYPT,"
        " got %08x\n", dwVal);

    CryptDestroyKey(hKey2);
    CryptDestroyKey(hKey1);

    clean_up_base_environment();
}

3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510
static void test_key_initialization(void)
{
    DWORD dwLen;
    HCRYPTPROV prov1, prov2;
    HCRYPTKEY hKeyExchangeKey, hSessionKey, hKey;
    BOOL result;
    static BYTE abSessionKey[148] = {
        0x01, 0x02, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00,
        0x00, 0xa4, 0x00, 0x00, 0xb8, 0xa4, 0xdf, 0x5e,
        0x9e, 0xb1, 0xbf, 0x85, 0x3d, 0x24, 0x2d, 0x1e,
        0x69, 0xb7, 0x67, 0x13, 0x8e, 0x78, 0xf2, 0xdf,
        0xc6, 0x69, 0xce, 0x46, 0x7e, 0xf2, 0xf2, 0x33,
        0x20, 0x6f, 0xa1, 0xa5, 0x59, 0x83, 0x25, 0xcb,
        0x3a, 0xb1, 0x8a, 0x12, 0x63, 0x02, 0x3c, 0xfb,
        0x4a, 0xfa, 0xef, 0x8e, 0xf7, 0x29, 0x57, 0xb1,
        0x9e, 0xa7, 0xf3, 0x02, 0xfd, 0xca, 0xdf, 0x5a,
        0x1f, 0x71, 0xb6, 0x26, 0x09, 0x24, 0x39, 0xda,
        0xc0, 0xde, 0x2a, 0x0e, 0xcd, 0x1f, 0xe5, 0xb6,
        0x4f, 0x82, 0xa0, 0xa9, 0x90, 0xd3, 0xd9, 0x6a,
        0x43, 0x14, 0x2a, 0xf7, 0xac, 0xd5, 0xa0, 0x54,
        0x93, 0xc4, 0xb9, 0xe7, 0x24, 0x84, 0x4d, 0x69,
        0x5e, 0xcc, 0x2a, 0x32, 0xb5, 0xfb, 0xe4, 0xb4,
        0x08, 0xd5, 0x36, 0x58, 0x59, 0x40, 0xfb, 0x29,
        0x7f, 0xa7, 0x17, 0x25, 0xc4, 0x0d, 0x78, 0x37,
        0x04, 0x8c, 0x49, 0x92
    };

    /* Like init_base_environment, but doesn't generate new keys, as they'll
     * be imported instead.
     */
3511
    if (!CryptAcquireContextA(&prov1, szContainer, szProvider, PROV_RSA_FULL, 0))
3512
    {
3513
        result = CryptAcquireContextA(&prov1, szContainer, szProvider, PROV_RSA_FULL,
3514
                                     CRYPT_NEWKEYSET);
3515
        ok(result, "CryptAcquireContextA failed: %08x\n", GetLastError());
3516 3517 3518
    }
    dwLen = (DWORD)sizeof(abPlainPrivateKey);
    result = CryptImportKey(prov1, abPlainPrivateKey, dwLen, 0, 0, &hKeyExchangeKey);
3519
    ok(result, "CryptImportKey failed: %08x\n", GetLastError());
3520 3521 3522

    dwLen = (DWORD)sizeof(abSessionKey);
    result = CryptImportKey(prov1, abSessionKey, dwLen, hKeyExchangeKey, 0, &hSessionKey);
3523
    ok(result, "CryptImportKey failed: %08x\n", GetLastError());
3524 3525 3526 3527

    /* Once the key has been imported, subsequently acquiring a context with
     * the same name will allow retrieving the key.
     */
3528 3529
    result = CryptAcquireContextA(&prov2, szContainer, szProvider, PROV_RSA_FULL, 0);
    ok(result, "CryptAcquireContextA failed: %08x\n", GetLastError());
3530
    result = CryptGetUserKey(prov2, AT_KEYEXCHANGE, &hKey);
3531
    ok(result, "CryptGetUserKey failed: %08x\n", GetLastError());
3532 3533 3534 3535 3536 3537
    if (result) CryptDestroyKey(hKey);
    CryptReleaseContext(prov2, 0);

    CryptDestroyKey(hSessionKey);
    CryptDestroyKey(hKeyExchangeKey);
    CryptReleaseContext(prov1, 0);
3538
    CryptAcquireContextA(&prov1, szContainer, NULL, PROV_RSA_FULL,
3539 3540 3541
     CRYPT_DELETEKEYSET);
}

3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799
static void test_key_derivation(const char *prov)
{
    HCRYPTKEY hKey;
    HCRYPTHASH hHash;
    BOOL result;
    unsigned char pbData[128], dvData[512];
    DWORD i, j, len, mode;
    struct _test
    {
        ALG_ID crypt_algo, hash_algo;
        int blocklen, hashlen, chain_mode;
        DWORD errorkey;
        const char *expected_hash, *expected_enc;
    } tests[] = {
        /* ================================================================== */
        { CALG_DES, CALG_MD2, 8, 16, CRYPT_MODE_CBC, 0,
          "\xBA\xBF\x93\xAE\xBC\x77\x45\xAA\x7E\x45\x69\xE5\x90\xE6\x04\x7F",
          "\x5D\xDA\x25\xA6\xB5\xC4\x43\xFB",
          /* 0 */
        },
        { CALG_3DES_112, CALG_MD2, 8, 16, CRYPT_MODE_CBC, 0,
          "\xDA\x4A\x9F\x5D\x2E\x7A\x3A\x4B\xBF\xDE\x47\x5B\x06\x84\x48\xA7",
          "\x6B\x18\x3B\xA1\x89\x27\xBF\xD4",
          /* 1 */
        },
        { CALG_3DES, CALG_MD2, 8, 16, CRYPT_MODE_CBC, 0,
          "\x38\xE5\x2E\x95\xA4\xA3\x73\x88\xF8\x1F\x87\xB7\x74\xB1\xA1\x56",
          "\x91\xAB\x17\xE5\xDA\x27\x11\x7D",
          /* 2 */
        },
        { CALG_RC2, CALG_MD2, 8, 16, CRYPT_MODE_CBC, 0,
          "\x7D\xA4\xB1\x10\x43\x26\x76\xB1\x0D\xB6\xE6\x9C\xA5\x8B\xCB\xE6",
          "\x7D\x45\x3D\x56\x00\xD7\xD1\x54",
          /* 3 */
        },
        { CALG_RC4, CALG_MD2, 4, 16, 0, 0,
          "\xFF\x32\xF1\x69\x62\xDE\xEB\x53\x8C\xFF\xA6\x92\x58\xA8\x22\xEA",
          "\xA9\x83\x73\xA9",
          /* 4 */
        },
        { CALG_RC5, CALG_MD2, 0, 16, 0, NTE_BAD_ALGID,
          "\x8A\xF2\xA3\xDA\xA5\x9A\x8B\x42\x4C\xE0\x2E\x00\xE5\x1E\x98\xE4",
          NULL,
          /* 5 */
        },
        { CALG_RSA_SIGN, CALG_MD2, 0, 16, 0, NTE_BAD_ALGID,
          "\xAE\xFE\xD6\xA5\x3E\x4B\xAC\xFA\x0E\x92\xC4\xC0\x06\xC9\x2B\xFD",
          NULL,
          /* 6 */
        },
        { CALG_RSA_KEYX, CALG_MD2, 0, 16, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\x30\xF4\xBC\x33\x93\xF3\x58\x19\xD1\x2B\x73\x4A\x92\xC7\xFC\xD7",
          NULL,
          /* 7 */
        },
        { CALG_AES, CALG_MD2, 0, 16, 0, NTE_BAD_ALGID,
          "\x07\x3B\x12\xE9\x96\x93\x85\xD7\xEC\xF4\xB1\xAC\x89\x2D\xC6\x9A",
          NULL,
          /* 8 */
        },
        { CALG_AES_128, CALG_MD2, 16, 16, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\xD2\x37\xE2\x49\xEB\x99\x23\xDA\x3E\x88\x55\x7E\x04\x5E\x15\x5D",
          "\xA1\x64\x3F\xFE\x99\x7F\x24\x13\x0C\xA9\x03\xEF\x9B\xC8\x1F\x2A",
          /* 9 */
        },
        { CALG_AES_192, CALG_MD2, 16, 16, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\x3E\x74\xED\xBF\x23\xAB\x03\x09\xBB\xD3\xE3\xAB\xCA\x12\x72\x7F",
          "\x5D\xEC\xF8\x72\xB2\xA6\x4D\x5C\xEA\x38\x9E\xF0\x86\xB6\x79\x34",
          /* 10 */
        },
        { CALG_AES_256, CALG_MD2, 16, 16, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\xBE\x9A\xE8\xF6\xCE\x79\x86\x5C\x1B\x01\x96\x4E\x5A\x8D\x09\x33",
          "\xD9\x4B\xC2\xE3\xCA\x89\x8B\x94\x0D\x87\xBB\xA2\xE8\x3D\x5C\x62",
          /* 11 */
        },
        /* ================================================================== */
        { CALG_DES, CALG_MD4, 8, 16, CRYPT_MODE_CBC, 0,
          "\xE8\x2F\x96\xC4\x6C\xC1\x91\xB4\x78\x40\x56\xD8\xA0\x25\xF5\x71",
          "\x21\x5A\xBD\x26\xB4\x3E\x86\x04",
          /* 12 */
        },
        { CALG_3DES_112, CALG_MD4, 8, 16, CRYPT_MODE_CBC, 0,
          "\x23\xBB\x6F\xE4\xB0\xF6\x35\xB6\x89\x2F\xEC\xDC\x06\xA9\xDF\x35",
          "\x9B\xE5\xD1\xEB\x8F\x13\x0B\xB3",
          /* 13 */
        },
        { CALG_3DES, CALG_MD4, 8, 16, CRYPT_MODE_CBC, 0,
          "\xE4\x72\x48\xC6\x6E\x38\x2F\x00\xC9\x2D\x01\x12\xB7\x8B\x64\x09",
          "\x7D\x5E\xAA\xEA\x10\xA4\xA4\x44",
          /* 14 */
        },
        { CALG_RC2, CALG_MD4, 8, 16, CRYPT_MODE_CBC, 0,
          "\xBF\x54\xDA\x3A\x56\x72\x0D\x9F\x30\x7D\x2F\x54\x13\xB2\xD7\xC6",
          "\x77\x42\x0E\xD2\x60\x29\x6F\x68",
          /* 15 */
        },
        { CALG_RC4, CALG_MD4, 4, 16, 0, 0,
          "\x9B\x74\x6D\x22\x11\x16\x05\x50\xA3\x75\x6B\xB2\x38\x8C\x2B\xC6",
          "\x5C\x7E\x99\x84",
          /* 16 */
        },
        { CALG_RC5, CALG_MD4, 0, 16, 0, NTE_BAD_ALGID,
          "\x51\xA8\x29\x8D\xE0\x36\xC1\xD3\x5E\x6A\x51\x4F\xE1\x65\xEE\xF1",
          NULL,
          /* 17 */
        },
        { CALG_RSA_SIGN, CALG_MD4, 0, 16, 0, NTE_BAD_ALGID,
          "\xA6\x83\x13\x4C\xB1\xAA\x06\x16\xE6\x4E\x7F\x0B\x8D\x19\xF5\x45",
          NULL,
          /* 18 */
        },
        { CALG_RSA_KEYX, CALG_MD4, 0, 16, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\x04\x24\xC8\x64\x98\x84\xE3\x3A\x7B\x9C\x50\x3E\xE7\xC4\x89\x82",
          NULL,
          /* 19 */
        },
        { CALG_AES, CALG_MD4, 0, 16, 0, NTE_BAD_ALGID,
          "\xF6\xEF\x81\xF8\xF2\xA3\xF6\x11\xFE\xA4\x7D\xC1\xD2\xF7\x7C\xDC",
          NULL,
          /* 20 */
        },
        { CALG_AES_128, CALG_MD4, 16, 16, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\xFF\xE9\x69\xFF\xC1\xDB\x08\xD4\x5B\xC8\x51\x71\x38\xEF\x8A\x5B",
          "\x8A\x24\xD0\x7A\x03\xE7\xA7\x02\xF2\x17\x4C\x01\xD5\x0E\x7F\x12",
          /* 21 */
        },
        { CALG_AES_192, CALG_MD4, 16, 16, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\x12\x01\xDD\x25\xBA\x8F\x1B\xCB\x7B\xAD\x3F\xDF\xB2\x68\x4F\x6A",
          "\xA9\x56\xBC\xA7\x97\x4E\x28\xAA\x4B\xE1\xA0\x6C\xE2\x43\x2C\x61",
          /* 22 */
        },
        { CALG_AES_256, CALG_MD4, 16, 16, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\x69\x08\x9F\x76\xD7\x9A\x93\x6F\xC7\x51\xA4\x00\xCF\x5A\xBB\x3D",
          "\x04\x07\xEA\xD9\x89\x0A\xD2\x65\x12\x13\x68\x9A\xD0\x86\x15\xED",
          /* 23 */
        },
        /* ================================================================== */
        { CALG_DES, CALG_MD5, 8, 16, CRYPT_MODE_CBC, 0,
          "\xEA\x01\x47\xA0\x7F\x96\x44\x6B\x0D\x95\x2C\x97\x4B\x28\x1C\x86",
          "\xF3\x75\xCC\x7C\x6C\x0B\xCF\x93",
          /* 24 */
        },
        { CALG_3DES_112, CALG_MD5, 8, 16, CRYPT_MODE_CBC, 0,
          "\xD2\xA2\xD7\x87\x32\x29\xF9\xE0\x45\x0D\xEC\x8D\xB5\xBC\x8A\xD9",
          "\x51\x70\xE0\xB7\x00\x0D\x3E\x21",
          /* 25 */
        },
        { CALG_3DES, CALG_MD5, 8, 16, CRYPT_MODE_CBC, 0,
          "\x2B\x36\xA2\x85\x85\xC0\xEC\xBE\x04\x56\x1D\x97\x8E\x82\xDB\xD8",
          "\x58\x23\x75\x25\x3F\x88\x25\xEB",
          /* 26 */
        },
        { CALG_RC2, CALG_MD5, 8, 16, CRYPT_MODE_CBC, 0,
          "\x3B\x89\x72\x3B\x8A\xD1\x2E\x13\x44\xD6\xD0\x97\xE6\xB8\x46\xCD",
          "\x90\x1C\x77\x45\x87\xDD\x1C\x2E",
          /* 27 */
        },
        { CALG_RC4, CALG_MD5, 4, 16, 0, 0,
          "\x00\x6D\xEF\xB1\xC8\xC6\x25\x5E\x45\x4F\x4E\x3D\xAF\x9C\x53\xD2",
          "\xC4\x4C\xD2\xF1",
          /* 28 */
        },
        { CALG_RC5, CALG_MD5, 0, 16, 0, NTE_BAD_ALGID,
          "\x56\x49\xDC\xBA\x32\xC6\x0D\x84\xE9\x2D\x42\x8C\xD6\x7C\x4A\x7A",
          NULL,
          /* 29 */
        },
        { CALG_RSA_SIGN, CALG_MD5, 0, 16, 0, NTE_BAD_ALGID,
          "\xDF\xD6\x3A\xE6\x3E\x8D\xB4\x17\x9F\x29\xF0\xFD\x6D\x98\x98\xAD",
          NULL,
          /* 30 */
        },
        { CALG_RSA_KEYX, CALG_MD5, 0, 16, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\xD4\x4D\x60\x9A\x39\x27\x88\xB7\xD7\xB4\x34\x2F\x92\x61\x3C\xA8",
          NULL,
          /* 31 */
        },
        { CALG_AES, CALG_MD5, 0, 16, 0, NTE_BAD_ALGID,
          "\xF4\x83\x2E\x02\xDE\xAE\x46\x1F\xE1\x31\x65\x03\x08\x58\xE0\x7D",
          NULL,
          /* 32 */
        },
        { CALG_AES_128, CALG_MD5, 16, 16, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\x0E\xA0\x40\x72\x55\xE5\x4C\xEB\x79\xCB\x48\xC3\xD1\xB1\xD0\xF4",
          "\x97\x66\x92\x02\x6D\xEC\x33\xF8\x4E\x82\x11\x20\xC7\xE2\xE6\xE8",
          /* 33 */
        },
        { CALG_AES_192, CALG_MD5, 16, 16, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\x3F\x91\x5E\x09\x19\x11\x14\x27\xCA\x6A\x20\x24\x3E\xF0\x02\x3E",
          "\x9B\xDA\x73\xF4\xF3\x06\x93\x07\xC9\x32\xF1\xD8\xD4\x96\xD1\x7D",
          /* 34 */
        },
        { CALG_AES_256, CALG_MD5, 16, 16, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\x27\x51\xD8\xB3\xC7\x14\x66\xE1\x99\xC3\x5C\x9C\x90\xF5\xE5\x94",
          "\x2A\x0F\xE9\xA9\x6F\x53\x7C\x9E\x07\xE6\xC3\xC9\x15\x99\x7C\xA8",
          /* 35 */
        },
        /* ================================================================== */
        { CALG_DES, CALG_SHA1, 8, 20, CRYPT_MODE_CBC, 0,
          "\xC1\x91\xF6\x5A\x81\x87\xAC\x6D\x48\x7C\x78\xF7\xEC\x37\xE2\x0C\xEC\xF7\xC0\xB8",
          "\xD4\xD8\xAA\x44\xAC\x5E\x0B\x8D",
          /* 36 */
        },
        { CALG_3DES_112, CALG_SHA1, 8, 20, CRYPT_MODE_CBC, 0,
          "\x5D\x9B\xC3\x99\xC4\x73\x90\x78\xCB\x51\x6B\x61\x8A\xBE\x1A\xF3\x7A\x90\xF3\x34",
          "\xD8\x1C\xBC\x6C\x92\xD3\x09\xBF",
          /* 37 */
        },
        { CALG_3DES, CALG_SHA1, 8, 20, CRYPT_MODE_CBC, 0,
          "\x90\xB8\x01\x89\xEC\x9A\x6C\xAD\x1E\xAC\xB3\x17\x0A\x44\xA2\x4D\x80\xA5\x25\x97",
          "\xBD\x58\x5A\x88\x98\xF8\x69\x9A",
          /* 38 */
        },
        { CALG_RC2, CALG_SHA1, 8, 20, CRYPT_MODE_CBC, 0,
          "\x42\xBD\xB8\xF2\xB5\xC2\x28\x64\x85\x98\x8E\x49\xE6\xDC\x92\x80\xCD\xC1\x63\x00",
          "\xCC\xFB\x1A\x4D\x29\xAD\x3E\x65",
          /* 39 */
        },
        { CALG_RC4, CALG_SHA1, 4, 20, 0, 0,
          "\x67\x36\xE9\x57\x5E\xCD\x56\x5E\x8B\x25\x35\x23\x74\xBA\x20\x46\xD0\x21\xDE\x0A",
          "\x7A\x34\x3D\x3C",
          /* 40 */
        },
        { CALG_RC5, CALG_SHA1, 0, 20, 0, NTE_BAD_ALGID,
          "\x5F\x29\xA5\xA4\x10\x08\x56\x15\x92\xF9\x55\x3B\x4B\xF5\xAB\xBD\xE7\x4D\x47\x28",
          NULL,
          /* 41 */
        },
        { CALG_RSA_SIGN, CALG_SHA1, 0, 20, 0, NTE_BAD_ALGID,
          "\xD3\xB7\xF8\xB9\xBE\x67\xD1\xFE\x10\x51\x23\x3B\x7D\xB7\x61\xF5\xA7\x1A\x02\x5E",
          NULL,
          /* 42 */
        },
        { CALG_RSA_KEYX, CALG_SHA1, 0, 20, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\x09\x68\x97\x23\x11\x2B\x6A\x71\xBA\x33\x60\x43\xEE\xC9\x9B\xB7\x8F\x8A\x2E\x33",
          NULL,
          /* 43 */
        },
        { CALG_AES, CALG_SHA1, 0, 20, 0, NTE_BAD_ALGID,
          "\xCF\x28\x23\x83\x62\x87\x43\xF6\x50\x57\xED\x54\xEC\x93\x5E\xEC\x0E\xD3\x23\x9A",
          NULL,
          /* 44 */
        },
        { CALG_AES_128, CALG_SHA1, 16, 20, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\x81\xC1\x7E\x42\xC3\x07\x1F\x5E\xF8\x75\xA3\x5A\xFC\x0B\x61\xBA\x0B\xD8\x53\x0D",
          "\x39\xCB\xAF\xD7\x8B\x75\x4A\x3B\xD2\x0E\x0D\xB1\x64\x57\x88\x58",
          /* 45 */
        },
        { CALG_AES_192, CALG_SHA1, 16, 20, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\x93\xA7\xE8\x9E\x96\xB5\x97\x23\xD0\x58\x44\x8C\x4D\xBB\xAB\xB6\x3E\x1F\x2C\x1D",
          "\xA9\x13\x83\xCA\x21\xA2\xF0\xBE\x13\xBC\x55\x04\x38\x08\xA9\xC4",
          /* 46 */
        },
        { CALG_AES_256, CALG_SHA1, 16, 20, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\x15\x6A\xB2\xDF\x32\x57\x14\x69\x09\x07\xAD\x24\x83\xA1\x74\x47\x41\x72\x69\xBC",
          "\xE1\x6C\xA8\x54\x0E\x24\x67\x6D\xCA\xA2\xFE\x84\xF0\x9B\x78\x66",
          /* 47 */
        },
3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872
        /* ================================================================== */
        { CALG_DES, CALG_SHA_256, 8, 32, CRYPT_MODE_CBC, 0,
          "\x20\x34\xf7\xbb\x7a\x3a\x79\xf0\xb9\x65\x18\x11\xaa\xfd\x26\x6b"
          "\x60\x5c\x6d\x4c\x81\x7c\x3f\xc4\xce\x94\xe3\x67\xdf\xf2\x16\xd8",
          "\x86\x0d\x8c\xf4\xc0\x22\x4a\xdd",
          /* 48 */
        },
        { CALG_3DES_112, CALG_SHA_256, 8, 32, CRYPT_MODE_CBC, 0,
          "\x09\x6e\x7f\xd5\xf2\x72\x4e\x18\x70\x09\xc1\x35\xf4\xd1\x3a\xe8"
          "\xe6\x1f\x91\xae\x2f\xfd\xa8\x8c\xce\x47\x0f\x7a\xf5\xef\xfd\xbe",
          "\x2d\xe7\x63\xf6\x58\x4d\x9a\xa6",
          /* 49 */
        },
        { CALG_3DES, CALG_SHA_256, 8, 32, CRYPT_MODE_CBC, 0,
          "\x54\x7f\x84\x7f\xfe\x83\xc6\x50\xbc\xd9\x92\x78\x32\x67\x50\x7d"
          "\xdf\x44\x55\x7d\x87\x74\xd2\x56\xff\xd9\x74\x44\xd5\x07\x9e\xdc",
          "\x20\xaa\x66\xd0\xac\x83\x9d\x99",
          /* 50 */
        },
        { CALG_RC2, CALG_SHA_256, 8, 32, CRYPT_MODE_CBC, 0,
          "\xc6\x22\x46\x15\xa1\x27\x38\x23\x91\xf2\x29\xda\x15\xc9\x5d\x92"
          "\x7c\x34\x4a\x1f\xb0\x8a\x81\xd6\x17\x09\xda\x52\x1f\xb9\x64\x60",
          "\x8c\x01\x19\x47\x7e\xd2\x10\x2c",
          /* 51 */
        },
        { CALG_RC4, CALG_SHA_256, 4, 32, 0, 0,
          "\xcd\x53\x95\xa6\xb6\x6e\x25\x92\x78\xac\xe6\x7e\xfc\xd3\x8d\xaa"
          "\xc3\x15\x83\xb5\xe6\xaf\xf9\x32\x4c\x17\xb8\x82\xdf\xc0\x45\x9e",
          "\xfa\x54\x13\x9c",
          /* 52 */
        },
        { CALG_RC5, CALG_SHA_256, 0, 32, 0, NTE_BAD_ALGID,
          "\x2a\x3b\x08\xe1\xec\xa7\x04\xf9\xc9\x42\x74\x9a\x82\xad\x99\xd2"
          "\x10\x51\xe3\x51\x6c\x67\xa4\xf2\xca\x99\x21\x43\xdf\xa0\xfc\xa1",
          NULL,
          /* 53 */
        },
        { CALG_RSA_SIGN, CALG_SHA_256, 0, 32, 0, NTE_BAD_ALGID,
          "\x10\x1d\x36\xc7\x38\x73\xc3\x80\xf0\x7a\x4e\x25\x52\x8a\x5c\x3f"
          "\xfc\x41\xa7\xe5\x20\xed\xd5\x1d\x00\x6e\x77\xf4\xa7\x71\x81\x6b",
          NULL,
          /* 54 */
        },
        { CALG_RSA_KEYX, CALG_SHA_256, 0, 32, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\x0a\x74\xde\x4f\x07\xce\x73\xd6\xd9\xa3\xba\xbb\x7c\x98\xe1\x94"
          "\x13\x93\xb1\xfd\x26\x31\x4b\xfc\x61\x27\xef\x4d\xd0\x48\x76\x67",
          NULL,
          /* 55 */
        },
        { CALG_AES, CALG_SHA_256, 0, 32, 0, NTE_BAD_ALGID,
          "\xf0\x13\xbc\x25\x2a\x2f\xba\xf1\x39\xe5\x7d\xb8\x5f\xaa\xd0\x19"
          "\xbd\x1c\xd8\x7b\x39\x5a\xb3\x85\x84\x80\xbd\xe0\x4a\x65\x03\xdd",
          NULL,
          /* 56 */
        },
        { CALG_AES_128, CALG_SHA_256, 16, 32, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\xc8\xc2\x6f\xe2\xbe\xa7\x38\x87\x04\xc7\x39\xcb\x9f\x57\xfc\xde"
          "\x14\x81\x46\xa4\xbb\xa7\x0f\x01\x1d\xc2\x6d\x7a\x43\x5f\x38\xc3",
          "\xf8\x75\xc6\x71\x8b\xb6\x54\xd3\xdc\xff\x0e\x84\x8a\x3f\x19\x46",
          /* 57 */
        },
        { CALG_AES_192, CALG_SHA_256, 16, 32, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\xb7\x3a\x43\x0f\xea\x90\x4f\x0f\xb9\x82\xf6\x1e\x07\xc4\x25\x4e"
          "\xdb\xe7\xf7\x1d\x7c\xd0\xe5\x51\xd8\x1b\x97\xc8\xc2\x46\xb9\xfe",
          "\x35\xf2\x20\xc7\x6c\xb2\x8e\x51\x3e\xc7\x6b\x3e\x64\xa5\x05\xdf",
          /* 58 */
        },
        { CALG_AES_256, CALG_SHA_256, 16, 32, CRYPT_MODE_CBC, NTE_BAD_ALGID,
          "\xbd\xcc\x0c\x59\x99\x29\xa7\x24\xf3\xdc\x20\x40\x4e\xe8\xe5\x48"
          "\xdd\x27\x0e\xdf\x7e\x50\x65\x17\x34\x50\x47\x78\x9a\x23\x1b\x40",
          "\x8c\xeb\x1f\xd3\x78\x77\xf5\xbf\x7a\xde\x8d\x2c\xa5\x16\xcc\xe9",
          /* 59 */
        },
3873 3874
    };
    /* Due to differences between encryption from <= 2000 and >= XP some tests need to be skipped */
3875
    int old_broken[ARRAY_SIZE(tests)];
3876 3877 3878 3879 3880
    memset(old_broken, 0, sizeof(old_broken));
    old_broken[3] = old_broken[4] = old_broken[15] = old_broken[16] = 1;
    old_broken[27] = old_broken[28] = old_broken[39] = old_broken[40] = 1;
    uniquecontainer(NULL);

3881
    for (i=0; i < ARRAY_SIZE(tests); i++)
3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936
    {
        if (win2k && old_broken[i]) continue;

        for (j=0; j<sizeof(dvData); j++) dvData[j] = (unsigned char)j+i;
        SetLastError(0xdeadbeef);
        result = CryptCreateHash(hProv, tests[i].hash_algo, 0, 0, &hHash);
        if (!result)
        {
            /* rsaenh compiled without OpenSSL or not supported by provider */
            ok(GetLastError() == NTE_BAD_ALGID, "Test [%s %d]: Expected NTE_BAD_ALGID, got 0x%08x\n",
               prov, i, GetLastError());
            continue;
        }
        ok(result, "Test [%s %d]: CryptCreateHash failed with error 0x%08x\n", prov, i, GetLastError());
        result = CryptHashData(hHash, dvData, sizeof(dvData), 0);
        ok(result, "Test [%s %d]: CryptHashData failed with error 0x%08x\n", prov, i, GetLastError());

        len = sizeof(pbData);
        result = CryptGetHashParam(hHash, HP_HASHVAL, pbData, &len, 0);
        ok(result, "Test [%s %d]: CryptGetHashParam failed with error 0x%08x\n", prov, i, GetLastError());
        ok(len == tests[i].hashlen, "Test [%s %d]: Expected hash len %d, got %d\n",
           prov, i, tests[i].hashlen, len);
        ok(!tests[i].hashlen || !memcmp(pbData, tests[i].expected_hash, tests[i].hashlen),
           "Test [%s %d]: Hash comparison failed\n", prov, i);

        SetLastError(0xdeadbeef);
        result = CryptDeriveKey(hProv, tests[i].crypt_algo, hHash, 0, &hKey);
        /* the provider may not support the algorithm */
        if(!result && (GetLastError() == tests[i].errorkey
           || GetLastError() == ERROR_INVALID_PARAMETER /* <= NT4*/))
            goto err;
        ok(result, "Test [%s %d]: CryptDeriveKey failed with error 0x%08x\n", prov, i, GetLastError());

        len = sizeof(mode);
        mode = 0xdeadbeef;
        result = CryptGetKeyParam(hKey, KP_MODE, (BYTE*)&mode, &len, 0);
        ok(result, "Test [%s %d]: CryptGetKeyParam failed with error %08x\n", prov, i, GetLastError());
        ok(mode == tests[i].chain_mode, "Test [%s %d]: Expected chaining mode %d, got %d\n",
           prov, i, tests[i].chain_mode, mode);

        SetLastError(0xdeadbeef);
        len = 4;
        result = CryptEncrypt(hKey, 0, TRUE, 0, dvData, &len, sizeof(dvData));
        ok(result, "Test [%s %d]: CryptEncrypt failed with error 0x%08x\n", prov, i, GetLastError());
        ok(len == tests[i].blocklen, "Test [%s %d]: Expected block len %d, got %d\n",
           prov, i, tests[i].blocklen, len);
        ok(!memcmp(dvData, tests[i].expected_enc, tests[i].blocklen),
           "Test [%s %d]: Encrypted data comparison failed\n", prov, i);

        CryptDestroyKey(hKey);
err:
        CryptDestroyHash(hHash);
    }
}

3937 3938
START_TEST(rsaenh)
{
3939
    for (iProv = 0; iProv < ARRAY_SIZE(szProviders); iProv++)
3940 3941
    {
        if (!init_base_environment(szProviders[iProv], 0))
3942
            continue;
3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969
        trace("Testing '%s'\n", szProviders[iProv]);
        test_prov();
        test_gen_random();
        test_hashes();
        test_rc4();
        test_rc2();
        test_des();
        if(!BASE_PROV)
        {
            test_3des112();
            test_3des();
        }
        if(ENHANCED_PROV)
        {
            test_import_private();
        }
        test_hmac();
        test_mac();
        test_block_cipher_modes();
        test_verify_signature();
        test_rsa_encrypt();
        test_import_export();
        test_import_hmac();
        test_enum_container();
        if(!BASE_PROV) test_key_derivation(STRONG_PROV ? "STRONG" : "ENH");
        clean_up_base_environment();
    }
3970

3971
    test_key_permissions();
3972
    test_key_initialization();
3973
    test_schannel_provider();
3974
    test_null_provider();
3975
    test_rsa_round_trip();
3976 3977 3978 3979 3980
    if (!init_aes_environment())
        return;
    test_aes(128);
    test_aes(192);
    test_aes(256);
3981
    test_sha2();
3982
    test_key_derivation("AES");
3983
    clean_up_aes_environment();
3984
}