crypt32: Test and correct CryptVerifyCertificateSignature.
[wine] / dlls / crypt32 / tests / message.c
1 /*
2  * Unit test suite for crypt32.dll's Crypt*Message functions
3  *
4  * Copyright 2007-2008 Juan Lang
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <windef.h>
24 #include <winbase.h>
25 #include <winerror.h>
26 #include <wincrypt.h>
27
28 #include "wine/test.h"
29
30 static BOOL (WINAPI * pCryptAcquireContextA)
31                         (HCRYPTPROV *, LPCSTR, LPCSTR, DWORD, DWORD);
32
33 static void init_function_pointers(void)
34 {
35     HMODULE hAdvapi32 = GetModuleHandleA("advapi32.dll");
36
37 #define GET_PROC(dll, func) \
38     p ## func = (void *)GetProcAddress(dll, #func); \
39     if(!p ## func) \
40       trace("GetProcAddress(%s) failed\n", #func);
41
42     GET_PROC(hAdvapi32, CryptAcquireContextA)
43
44 #undef GET_PROC
45 }
46
47 static const BYTE dataEmptyBareContent[] = { 0x04,0x00 };
48 static const BYTE dataEmptyContent[] = {
49 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x02,
50 0x04,0x00 };
51 static const BYTE signedEmptyBareContent[] = {
52 0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
53 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02,
54 0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
55 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
56 0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,
57 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
58 static const BYTE signedEmptyContent[] = {
59 0x30,0x5f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x52,
60 0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
61 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02,
62 0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
63 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
64 0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,
65 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
66
67 static void test_msg_get_signer_count(void)
68 {
69     LONG count;
70
71     SetLastError(0xdeadbeef);
72     count = CryptGetMessageSignerCount(0, NULL, 0);
73     ok(count == -1, "Expected -1, got %d\n", count);
74     ok(GetLastError() == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n",
75      GetLastError());
76     SetLastError(0xdeadbeef);
77     count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, NULL, 0);
78     ok(count == -1, "Expected -1, got %d\n", count);
79     ok(GetLastError() == CRYPT_E_ASN1_EOD ||
80        GetLastError() == OSS_BAD_ARG, /* win9x */
81      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
82     SetLastError(0xdeadbeef);
83     count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
84      dataEmptyBareContent, sizeof(dataEmptyBareContent));
85     ok(count == -1, "Expected -1, got %d\n", count);
86     ok(GetLastError() == CRYPT_E_ASN1_BADTAG ||
87        GetLastError() == OSS_PDU_MISMATCH, /* win9x */
88      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
89     SetLastError(0xdeadbeef);
90     count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
91      dataEmptyContent, sizeof(dataEmptyContent));
92     ok(count == -1, "Expected -1, got %d\n", count);
93     ok(GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
94      "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
95     SetLastError(0xdeadbeef);
96     count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
97      signedEmptyBareContent, sizeof(signedEmptyBareContent));
98     ok(count == -1, "Expected -1, got %d\n", count);
99     ok(GetLastError() == CRYPT_E_ASN1_BADTAG ||
100        GetLastError() == OSS_DATA_ERROR, /* win9x */
101      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
102     count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
103      signedEmptyContent, sizeof(signedEmptyContent));
104     ok(count == 1 ||
105        broken(count == -1), /* win9x */
106        "Expected 1, got %d\n", count);
107 }
108
109 static BYTE detachedHashContent[] = {
110 0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
111 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
112 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
113 0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
114 0x9d,0x2a,0x8f,0x26,0x2f };
115 static const BYTE msgData[] = { 1, 2, 3, 4 };
116
117 static void test_verify_detached_message_hash(void)
118 {
119     BOOL ret;
120     CRYPT_HASH_MESSAGE_PARA para;
121     DWORD size, hashSize;
122     const BYTE *pMsgData = msgData;
123     BYTE hash[16];
124
125     if (0)
126     {
127         CryptVerifyDetachedMessageHash(NULL, NULL, 0, 0, NULL, NULL, NULL,
128          NULL);
129     }
130     memset(&para, 0, sizeof(para));
131     SetLastError(0xdeadbeef);
132     ret = CryptVerifyDetachedMessageHash(&para, NULL, 0, 0, NULL, NULL, NULL,
133      NULL);
134     ok(!ret && GetLastError() == E_INVALIDARG,
135      "expected E_INVALIDARG, got %08x\n", GetLastError());
136     para.cbSize = sizeof(para);
137     SetLastError(0xdeadbeef);
138     ret = CryptVerifyDetachedMessageHash(&para, NULL, 0, 0, NULL, NULL, NULL,
139      NULL);
140     ok(!ret && GetLastError() == E_INVALIDARG,
141      "expected E_INVALIDARG, got %08x\n", GetLastError());
142     para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
143     SetLastError(0xdeadbeef);
144     ret = CryptVerifyDetachedMessageHash(&para, NULL, 0, 0, NULL, NULL, NULL,
145      NULL);
146     ok(!ret &&
147      (GetLastError() == CRYPT_E_ASN1_EOD ||
148       GetLastError() == OSS_BAD_ARG), /* win9x */
149      "expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
150     para.dwMsgEncodingType = X509_ASN_ENCODING;
151     SetLastError(0xdeadbeef);
152     ret = CryptVerifyDetachedMessageHash(&para, NULL, 0, 0, NULL, NULL, NULL,
153      NULL);
154     ok(!ret && GetLastError() == E_INVALIDARG,
155      "expected E_INVALIDARG, got %08x\n", GetLastError());
156     para.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
157     SetLastError(0xdeadbeef);
158     ret = CryptVerifyDetachedMessageHash(&para, NULL, 0, 0, NULL, NULL, NULL,
159      NULL);
160     ok(!ret &&
161      (GetLastError() == CRYPT_E_ASN1_EOD ||
162       GetLastError() == OSS_BAD_ARG), /* win9x */
163      "expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
164     /* Curiously, passing no data to hash succeeds.. */
165     ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
166      sizeof(detachedHashContent), 0, NULL, NULL, NULL, NULL);
167     todo_wine
168     ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
169     /* as does passing the actual content of the message to hash.. */
170     size = sizeof(msgData);
171     pMsgData = msgData;
172     ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
173      sizeof(detachedHashContent), 1, &pMsgData, &size, NULL, NULL);
174     ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
175     /* while passing data to hash that isn't the content of the message fails.
176      */
177     size = sizeof(detachedHashContent);
178     pMsgData = detachedHashContent;
179     SetLastError(0xdeadbeef);
180     ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
181      sizeof(detachedHashContent), 1, &pMsgData, &size, NULL, NULL);
182     ok(!ret && GetLastError() == CRYPT_E_HASH_VALUE,
183      "expected CRYPT_E_HASH_VALUE, got %08x\n", GetLastError());
184     /* Getting the size of the hash while passing no hash data causes the
185      * hash to be checked (and fail.)
186      */
187     SetLastError(0xdeadbeef);
188     ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
189      sizeof(detachedHashContent), 0, NULL, NULL, NULL, &hashSize);
190     ok(!ret && GetLastError() == CRYPT_E_HASH_VALUE,
191      "expected CRYPT_E_HASH_VALUE, got %08x\n", GetLastError());
192     size = sizeof(msgData);
193     pMsgData = msgData;
194     ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
195      sizeof(detachedHashContent), 1, &pMsgData, &size, NULL, &hashSize);
196     ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
197     ok(hashSize == sizeof(hash), "unexpected size %d\n", hashSize);
198     hashSize = 1;
199     SetLastError(0xdeadbeef);
200     ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
201      sizeof(detachedHashContent), 1, &pMsgData, &size, hash, &hashSize);
202     ok(!ret && GetLastError() == ERROR_MORE_DATA,
203      "expected ERROR_MORE_DATA, got %08x\n", GetLastError());
204     hashSize = sizeof(hash);
205     ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
206      sizeof(detachedHashContent), 1, &pMsgData, &size, hash, &hashSize);
207     ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
208 }
209
210 static BYTE hashContent[] = {
211 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
212 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
213 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
214 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
215 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
216
217 static void test_verify_message_hash(void)
218 {
219     BOOL ret;
220     CRYPT_HASH_MESSAGE_PARA para;
221     DWORD size;
222     BYTE *buf = NULL;
223
224     memset(&para, 0, sizeof(para));
225     /* Crash */
226     if (0)
227         ret = CryptVerifyMessageHash(NULL, NULL, 0, NULL, NULL, NULL, NULL);
228     SetLastError(0xdeadbeef);
229     ret = CryptVerifyMessageHash(&para, NULL, 0, NULL, NULL, NULL, NULL);
230     ok(!ret && GetLastError() == E_INVALIDARG,
231      "expected E_INVALIDARG, got %08x\n", GetLastError());
232     para.cbSize = sizeof(para);
233     SetLastError(0xdeadbeef);
234     ret = CryptVerifyMessageHash(&para, NULL, 0, NULL, NULL, NULL, NULL);
235     ok(!ret && GetLastError() == E_INVALIDARG,
236      "expected E_INVALIDARG, got %08x\n", GetLastError());
237     para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
238     SetLastError(0xdeadbeef);
239     ret = CryptVerifyMessageHash(&para, NULL, 0, NULL, NULL, NULL, NULL);
240     ok(!ret, "Expected 0, got %d\n", ret);
241     ok(GetLastError() == CRYPT_E_ASN1_EOD ||
242        GetLastError() == OSS_BAD_ARG, /* win98 */
243      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
244     /* Verifying the hash of a detached message succeeds? */
245     ret = CryptVerifyMessageHash(&para, detachedHashContent,
246      sizeof(detachedHashContent), NULL, NULL, NULL, NULL);
247     todo_wine
248     ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
249     /* As does verifying the hash of a regular message. */
250     ret = CryptVerifyMessageHash(&para, hashContent, sizeof(hashContent),
251      NULL, NULL, NULL, NULL);
252     ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
253     ret = CryptVerifyMessageHash(&para, hashContent, sizeof(hashContent),
254      NULL, &size, NULL, NULL);
255     ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
256     if (ret)
257         buf = CryptMemAlloc(size);
258     if (buf)
259     {
260         size = 1;
261         ret = CryptVerifyMessageHash(&para, hashContent, sizeof(hashContent),
262          buf, &size, NULL, NULL);
263         ok(!ret && GetLastError() == ERROR_MORE_DATA,
264          "expected ERROR_MORE_DATA, got %08x\n", GetLastError());
265         ret = CryptVerifyMessageHash(&para, hashContent, sizeof(hashContent),
266          buf, &size, NULL, NULL);
267         ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
268         ok(size == sizeof(msgData), "unexpected size %d\n", size);
269         ok(!memcmp(buf, msgData, size), "unexpected value\n");
270         CryptMemFree(buf);
271     }
272 }
273
274 static const BYTE signedWithCertContent[] = {
275 0x30,0x82,0x01,0x32,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
276 0xa0,0x82,0x01,0x23,0x30,0x82,0x01,0x1f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,
277 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,
278 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,
279 0x02,0x03,0x04,0xa0,0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
280 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
281 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
282 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
283 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
284 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
285 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
286 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
287 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,0x77,0x30,0x75,0x02,0x01,
288 0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,
289 0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,
290 0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,
291 0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,
292 0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,
293 0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,
294 0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,
295 0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
296 static const BYTE signedContent[] = {
297 0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
298 0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
299 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
300 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
301 0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,
302 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
303 0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
304 0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,
305 0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,
306 0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,
307 0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,
308 0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,
309 0x0d };
310 static const BYTE detachedSignedContent[] = {
311 0x30,0x81,0xaa,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
312 0x81,0x9c,0x30,0x81,0x99,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
313 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,
314 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,
315 0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
316 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,
317 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,
318 0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,
319 0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,
320 0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,
321 0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,
322 0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
323 static const BYTE v1CertWithValidPubKey[] = {
324 0x30,0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
325 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
326 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
327 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
328 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
329 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
330 0x67,0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
331 0x01,0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,
332 0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,
333 0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,
334 0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,
335 0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,
336 0x79,0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
337 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
338
339 static PCCERT_CONTEXT WINAPI msg_get_signer_callback(void *pvArg,
340  DWORD certEncodingType, PCERT_INFO signerId, HCERTSTORE store)
341 {
342     return CertCreateCertificateContext(X509_ASN_ENCODING,
343      v1CertWithValidPubKey, sizeof(v1CertWithValidPubKey));
344 }
345
346 static void test_verify_detached_message_signature(void)
347 {
348     CRYPT_VERIFY_MESSAGE_PARA para;
349     BOOL ret;
350     const BYTE *pContent;
351     DWORD cbContent;
352
353     memset(&para, 0, sizeof(para));
354     SetLastError(0xdeadbeef);
355     ret = CryptVerifyDetachedMessageSignature(NULL, 0, NULL, 0, 0, NULL,
356      NULL, NULL);
357     ok(!ret && GetLastError() == E_INVALIDARG,
358      "Expected E_INVALIDARG, got %08x\n", GetLastError());
359     SetLastError(0xdeadbeef);
360     ret = CryptVerifyDetachedMessageSignature(&para, 0, NULL, 0, 0, NULL,
361      NULL, NULL);
362     ok(!ret && GetLastError() == E_INVALIDARG,
363      "Expected E_INVALIDARG, got %08x\n", GetLastError());
364     para.cbSize = sizeof(para);
365     SetLastError(0xdeadbeef);
366     ret = CryptVerifyDetachedMessageSignature(&para, 0, NULL, 0, 0, NULL,
367      NULL, NULL);
368     ok(!ret && GetLastError() == E_INVALIDARG,
369      "Expected E_INVALIDARG, got %08x\n", GetLastError());
370     para.dwMsgAndCertEncodingType = X509_ASN_ENCODING;
371     SetLastError(0xdeadbeef);
372     ret = CryptVerifyDetachedMessageSignature(&para, 0, NULL, 0, 0, NULL,
373      NULL, NULL);
374     ok(!ret && GetLastError() == E_INVALIDARG,
375      "Expected E_INVALIDARG, got %08x\n", GetLastError());
376     para.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING;
377     SetLastError(0xdeadbeef);
378     ret = CryptVerifyDetachedMessageSignature(&para, 0, NULL, 0, 0, NULL,
379      NULL, NULL);
380     ok(!ret, "Expected 0, got %d\n", ret);
381     ok(GetLastError() == CRYPT_E_ASN1_EOD ||
382      GetLastError() == OSS_BAD_ARG, /* win98 */
383      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
384     /* None of these messages contains a cert in the message itself, so the
385      * default callback isn't able to verify their signature.
386      */
387     SetLastError(0xdeadbeef);
388     ret = CryptVerifyDetachedMessageSignature(&para, 0, signedWithCertContent,
389      sizeof(signedWithCertContent), 0, NULL, NULL, NULL);
390     ok(!ret, "Expected 0, got %d\n", ret);
391     todo_wine
392     ok(GetLastError() == CRYPT_E_NOT_FOUND ||
393      GetLastError() == OSS_DATA_ERROR, /* win98 */
394      "Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
395     SetLastError(0xdeadbeef);
396     ret = CryptVerifyDetachedMessageSignature(&para, 0, signedContent,
397      sizeof(signedContent), 0, NULL, NULL, NULL);
398     ok(!ret, "Expected 0, got %d\n", ret);
399     ok(GetLastError() == CRYPT_E_NOT_FOUND ||
400      GetLastError() == OSS_DATA_ERROR, /* win98 */
401      "Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
402     SetLastError(0xdeadbeef);
403     ret = CryptVerifyDetachedMessageSignature(&para, 0, detachedSignedContent,
404      sizeof(detachedSignedContent), 0, NULL, NULL, NULL);
405     ok(!ret, "Expected 0, got %d\n", ret);
406     ok(GetLastError() == CRYPT_E_NOT_FOUND ||
407      GetLastError() == OSS_DATA_ERROR, /* win98 */
408      "Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
409     SetLastError(0xdeadbeef);
410     pContent = msgData;
411     cbContent = sizeof(msgData);
412     ret = CryptVerifyDetachedMessageSignature(&para, 0, detachedSignedContent,
413      sizeof(detachedSignedContent), 1, &pContent, &cbContent, NULL);
414     ok(!ret, "Expected 0, got %d\n", ret);
415     ok(GetLastError() == CRYPT_E_NOT_FOUND ||
416      GetLastError() == OSS_DATA_ERROR, /* win98 */
417      "Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
418     /* Passing the correct callback results in success */
419     para.pfnGetSignerCertificate = msg_get_signer_callback;
420     ret = CryptVerifyDetachedMessageSignature(&para, 0, detachedSignedContent,
421      sizeof(detachedSignedContent), 1, &pContent, &cbContent, NULL);
422     ok(ret ||
423      broken(!ret), /* win98 */
424      "CryptVerifyDetachedMessageSignature failed: %08x\n",
425      GetLastError());
426     /* Not passing the correct data to be signed results in the signature not
427      * matching.
428      */
429     SetLastError(0xdeadbeef);
430     ret = CryptVerifyDetachedMessageSignature(&para, 0, detachedSignedContent,
431      sizeof(detachedSignedContent), 0, NULL, NULL, NULL);
432     ok(!ret, "Expected 0, got %d\n", ret);
433     ok(GetLastError() == NTE_BAD_SIGNATURE ||
434      GetLastError() == OSS_DATA_ERROR, /* win98 */
435      "Expected NTE_BAD_SIGNATURE or OSS_DATA_ERROR, got %08x\n", GetLastError());
436 }
437
438 static const BYTE signedWithCertEmptyContent[] = {
439 0x30,0x81,0xdf,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
440 0x81,0xd1,0x30,0x81,0xce,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
441 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x7c,
442 0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
443 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
444 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
445 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
446 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
447 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
448 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,
449 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
450 0xff,0x02,0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,
451 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
452 0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,
453 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
454 0x00 };
455 static const BYTE signedWithCertWithPubKeyContent[] = {
456 0x30,0x81,0xfc,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
457 0x81,0xee,0x30,0x81,0xeb,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
458 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x81,
459 0x98,0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,
460 0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,
461 0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
462 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
463 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,
464 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
465 0x6e,0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
466 0x01,0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,
467 0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,
468 0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,
469 0x02,0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
470 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
471 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
472 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
473 static const BYTE signedWithCertWithValidPubKeyContent[] = {
474 0x30,0x82,0x01,0x89,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
475 0xa0,0x82,0x01,0x7a,0x30,0x82,0x01,0x76,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,
476 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,
477 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,
478 0x02,0x03,0x04,0xa0,0x81,0xd2,0x30,0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,
479 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
480 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
481 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
482 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
483 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
484 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,
485 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,
486 0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,
487 0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
488 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,
489 0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,
490 0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,
491 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
492 0x01,0x01,0xff,0x02,0x01,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
493 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
494 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
495 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
496 0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,
497 0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,
498 0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,
499 0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,
500 0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
501
502 static void test_verify_message_signature(void)
503 {
504     BOOL ret;
505     CRYPT_VERIFY_MESSAGE_PARA para = { 0 };
506     PCCERT_CONTEXT cert;
507     DWORD cbDecoded;
508     BYTE decoded[sizeof(msgData)];
509
510     SetLastError(0xdeadbeef);
511     ret = CryptVerifyMessageSignature(NULL, 0, NULL, 0, NULL, 0, NULL);
512     ok(!ret && GetLastError() == E_INVALIDARG,
513      "Expected E_INVALIDARG, got %08x\n", GetLastError());
514     /* Is cbDecoded set when invalid parameters are passed? */
515     cbDecoded = 0xdeadbeef;
516     ret = CryptVerifyMessageSignature(NULL, 0, NULL, 0, NULL, &cbDecoded,
517      NULL);
518     ok(!ret && GetLastError() == E_INVALIDARG,
519      "Expected E_INVALIDARG, got %08x\n", GetLastError());
520     ok(cbDecoded == 0, "expected 0, got %08x\n", cbDecoded);
521     SetLastError(0xdeadbeef);
522     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
523     ok(!ret && GetLastError() == E_INVALIDARG,
524      "Expected E_INVALIDARG, got %08x\n", GetLastError());
525     para.cbSize = sizeof(para);
526     SetLastError(0xdeadbeef);
527     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
528     ok(!ret && GetLastError() == E_INVALIDARG,
529      "Expected E_INVALIDARG, got %08x\n", GetLastError());
530     para.cbSize = 0;
531     para.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING;
532     SetLastError(0xdeadbeef);
533     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
534     ok(!ret && GetLastError() == E_INVALIDARG,
535      "Expected E_INVALIDARG, got %08x\n", GetLastError());
536     para.cbSize = sizeof(para);
537     SetLastError(0xdeadbeef);
538     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
539     ok(!ret &&
540      (GetLastError() == CRYPT_E_ASN1_EOD ||
541       GetLastError() == OSS_BAD_ARG), /* win9x */
542      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
543     /* Check whether cert is set on error */
544     cert = (PCCERT_CONTEXT)0xdeadbeef;
545     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, &cert);
546     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
547     GetLastError() == OSS_BAD_ARG /* NT40 */),
548      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
549     ok(cert == NULL, "Expected NULL cert\n");
550     /* Check whether cbDecoded is set on error */
551     cbDecoded = 0xdeadbeef;
552     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, &cbDecoded,
553      NULL);
554     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
555      GetLastError() == OSS_BAD_ARG /* NT40 */),
556      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
557     ok(!cbDecoded, "Expected 0\n");
558     SetLastError(0xdeadbeef);
559     ret = CryptVerifyMessageSignature(&para, 0, dataEmptyBareContent,
560      sizeof(dataEmptyBareContent), NULL, 0, NULL);
561     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
562      GetLastError() == OSS_PDU_MISMATCH /* NT40 */),
563      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
564     ok(GetLastError() == CRYPT_E_ASN1_BADTAG ||
565      GetLastError() == OSS_PDU_MISMATCH, /* win9x */
566      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
567     SetLastError(0xdeadbeef);
568     ret = CryptVerifyMessageSignature(&para, 0, dataEmptyContent,
569      sizeof(dataEmptyContent), NULL, 0, NULL);
570     ok(!ret && GetLastError() == CRYPT_E_UNEXPECTED_MSG_TYPE,
571      "Expected CRYPT_E_UNEXPECTED_MSG_TYPE, got %08x\n", GetLastError());
572     SetLastError(0xdeadbeef);
573     ret = CryptVerifyMessageSignature(&para, 0, signedEmptyBareContent,
574      sizeof(signedEmptyBareContent), NULL, 0, NULL);
575     ok(!ret &&
576      (GetLastError() == CRYPT_E_ASN1_BADTAG ||
577       GetLastError() == OSS_DATA_ERROR), /* win9x */
578      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
579     SetLastError(0xdeadbeef);
580     ret = CryptVerifyMessageSignature(&para, 0, signedEmptyContent,
581      sizeof(signedEmptyContent), NULL, 0, NULL);
582     ok(!ret &&
583      (GetLastError() == CRYPT_E_NOT_FOUND ||
584       GetLastError() == OSS_DATA_ERROR), /* win9x */
585      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
586     SetLastError(0xdeadbeef);
587     ret = CryptVerifyMessageSignature(&para, 0, signedContent,
588      sizeof(signedContent), NULL, 0, NULL);
589     ok(!ret &&
590      (GetLastError() == CRYPT_E_NOT_FOUND ||
591       GetLastError() == OSS_DATA_ERROR), /* win9x */
592      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
593     /* FIXME: Windows fails with CRYPT_E_NOT_FOUND for these messages, but
594      * their signer certs have invalid public keys that fail to decode.  In
595      * Wine therefore the failure is an ASN error.  Need some messages with
596      * valid public keys and invalid signatures to check against.
597      */
598     ret = CryptVerifyMessageSignature(&para, 0, signedWithCertEmptyContent,
599      sizeof(signedWithCertEmptyContent), NULL, 0, NULL);
600     ok(!ret, "Expected failure\n");
601     ret = CryptVerifyMessageSignature(&para, 0, signedWithCertContent,
602      sizeof(signedWithCertContent), NULL, 0, NULL);
603     ok(!ret, "Expected failure\n");
604     ret = CryptVerifyMessageSignature(&para, 0, signedWithCertWithPubKeyContent,
605      sizeof(signedWithCertWithPubKeyContent), NULL, 0, NULL);
606     ok(!ret, "Expected failure\n");
607     /* Apparently, an output pcbDecoded parameter is expected. */
608     ret = CryptVerifyMessageSignature(&para, 0,
609      signedWithCertWithValidPubKeyContent,
610      sizeof(signedWithCertWithValidPubKeyContent), NULL, 0, NULL);
611     ok(!ret, "Expected failure\n");
612     /* Finally, a message signed with a valid public key verifies successfully
613      */
614     cbDecoded = 0xdeadbeef;
615     ret = CryptVerifyMessageSignature(&para, 0,
616      signedWithCertWithValidPubKeyContent,
617      sizeof(signedWithCertWithValidPubKeyContent), NULL, &cbDecoded, NULL);
618     ok(ret, "CryptVerifyMessageSignature failed: %08x\n", GetLastError());
619     ok(cbDecoded == sizeof(msgData), "expected 4, got %d\n", cbDecoded);
620     cbDecoded = 0;
621     ret = CryptVerifyMessageSignature(&para, 0,
622      signedWithCertWithValidPubKeyContent,
623      sizeof(signedWithCertWithValidPubKeyContent), NULL, &cbDecoded, NULL);
624     /* Setting cbDecoded to 0 succeeds when a NULL buffer is provided */
625     ok(ret, "CryptVerifyMessageSignature failed: %08x\n", GetLastError());
626     ok(cbDecoded == sizeof(msgData), "expected 4, got %d\n", cbDecoded);
627     cbDecoded = 0;
628     ret = CryptVerifyMessageSignature(&para, 0,
629      signedWithCertWithValidPubKeyContent,
630      sizeof(signedWithCertWithValidPubKeyContent), decoded, &cbDecoded, NULL);
631     /* When a non-NULL buffer is provided, cbDecoded must not be too small */
632     ok(!ret && GetLastError() == ERROR_MORE_DATA,
633      "expected ERROR_MORE_DATA, got %d (%08x)\n", GetLastError(),
634      GetLastError());
635 }
636
637 static const BYTE detachedHashBlob[] = {
638 0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
639 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
640 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
641 0x07,0x01,0x04,0x10,0x2d,0x1b,0xbc,0x1f,0xc7,0xab,0x36,0x8d,0xdb,0x95,0xe6,
642 0x24,0xb9,0x66,0x7c,0x21 };
643 static const BYTE hashBlob[] = {
644 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
645 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
646 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
647 0x07,0x01,0xa0,0x06,0x04,0x04,0xde,0xad,0xbe,0xef,0x04,0x10,0x2f,0x24,0x92,
648 0x30,0xa8,0xe7,0xc2,0xbf,0x60,0x05,0xcc,0xd2,0x67,0x92,0x59,0xec };
649 static const BYTE hashVal[] = {
650 0x2d,0x1b,0xbc,0x1f,0xc7,0xab,0x36,0x8d,0xdb,0x95,0xe6,0x24,0xb9,0x66,0x7c,
651 0x21 };
652
653 static void test_hash_message(void)
654 {
655     BOOL ret;
656     CRYPT_HASH_MESSAGE_PARA para;
657     static const BYTE blob1[] = { 0xde, 0xad, 0xbe, 0xef };
658     static const BYTE blob2[] = { 0xba, 0xad, 0xf0, 0x0d };
659     const BYTE *toHash[] = { blob1, blob2 };
660     DWORD hashSize[] = { sizeof(blob1), sizeof(blob2) };
661     DWORD hashedBlobSize, computedHashSize;
662     static char oid_rsa_md5[] = szOID_RSA_MD5;
663     LPBYTE hashedBlob, computedHash;
664
665     /* Crash
666     ret = CryptHashMessage(NULL, FALSE, 0, NULL, 0, NULL, NULL, NULL, NULL);
667      */
668     memset(&para, 0, sizeof(para));
669     SetLastError(0xdeadbeef);
670     ret = CryptHashMessage(&para, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
671     ok(!ret && GetLastError() == E_INVALIDARG,
672      "expected E_INVALIDARG, got 0x%08x\n", GetLastError());
673     para.cbSize = sizeof(para);
674     /* Not quite sure what "success" means in this case, but it does succeed */
675     SetLastError(0xdeadbeef);
676     ret = CryptHashMessage(&para, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
677     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
678     /* With a bogus encoding type it "succeeds" */
679     para.dwMsgEncodingType = 0xdeadbeef;
680     SetLastError(0xdeadbeef);
681     ret = CryptHashMessage(&para, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
682     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
683     /* According to MSDN, the third parameter (cToBeHashed) must be 1 if the
684      * second parameter (fDetached) is FALSE, but again it "succeeds."
685      */
686     SetLastError(0xdeadbeef);
687     ret = CryptHashMessage(&para, FALSE, 2, NULL, NULL, NULL, NULL, NULL, NULL);
688     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
689     /* Even passing parameters to hash results in "success." */
690     SetLastError(0xdeadbeef);
691     ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL, NULL, NULL,
692      NULL);
693     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
694     /* Try again with a valid encoding type */
695     para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
696     SetLastError(0xdeadbeef);
697     ret = CryptHashMessage(&para, FALSE, 2, NULL, NULL, NULL, NULL, NULL, NULL);
698     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
699     /* And with valid data to hash */
700     SetLastError(0xdeadbeef);
701     ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL, NULL, NULL,
702      NULL);
703     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
704     /* But requesting the size of the hashed blob and indicating there's data
705      * to hash results in a crash
706      */
707     if (0)
708     {
709         CryptHashMessage(&para, FALSE, 2, NULL, NULL, NULL,
710          &hashedBlobSize, NULL, NULL);
711     }
712     /* Passing a valid pointer for the data to hash fails, as the hash
713      * algorithm is finally checked.
714      */
715     SetLastError(0xdeadbeef);
716     ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL,
717      &hashedBlobSize, NULL, NULL);
718     ok(!ret &&
719      (GetLastError() == CRYPT_E_UNKNOWN_ALGO ||
720       GetLastError() == CRYPT_E_OID_FORMAT), /* Vista */
721      "expected CRYPT_E_UNKNOWN_ALGO or CRYPT_E_OID_FORMAT, got 0x%08x (%d)\n",
722      GetLastError(), GetLastError());
723     para.HashAlgorithm.pszObjId = oid_rsa_md5;
724     /* With a valid hash algorithm, this succeeds, even though fDetached is
725      * FALSE.
726      */
727     SetLastError(0xdeadbeef);
728     ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL,
729      &hashedBlobSize, NULL, NULL);
730     todo_wine
731     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
732     if (ret)
733     {
734         /* Actually attempting to get the hashed data fails, perhaps because
735          * detached is FALSE.
736          */
737         hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
738         SetLastError(0xdeadbeef);
739         ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, hashedBlob,
740          &hashedBlobSize, NULL, NULL);
741         ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
742          "expected CRYPT_E_MSG_ERROR, got 0x%08x (%d)\n", GetLastError(),
743          GetLastError());
744         HeapFree(GetProcessHeap(), 0, hashedBlob);
745     }
746     /* Repeating tests with fDetached = TRUE results in success */
747     SetLastError(0xdeadbeef);
748     ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, NULL,
749      &hashedBlobSize, NULL, NULL);
750     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
751     if (ret)
752     {
753         hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
754         SetLastError(0xdeadbeef);
755         ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, hashedBlob,
756          &hashedBlobSize, NULL, NULL);
757         ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
758         ok(hashedBlobSize == sizeof(detachedHashBlob),
759          "unexpected size of detached blob %d\n", hashedBlobSize);
760         ok(!memcmp(hashedBlob, detachedHashBlob, hashedBlobSize),
761          "unexpected detached blob value\n");
762         HeapFree(GetProcessHeap(), 0, hashedBlob);
763     }
764     /* Hashing a single item with fDetached = FALSE also succeeds */
765     SetLastError(0xdeadbeef);
766     ret = CryptHashMessage(&para, FALSE, 1, toHash, hashSize, NULL,
767      &hashedBlobSize, NULL, NULL);
768     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
769     if (ret)
770     {
771         hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
772         ret = CryptHashMessage(&para, FALSE, 1, toHash, hashSize, hashedBlob,
773          &hashedBlobSize, NULL, NULL);
774         ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
775         ok(hashedBlobSize == sizeof(hashBlob),
776          "unexpected size of detached blob %d\n", hashedBlobSize);
777         ok(!memcmp(hashedBlob, hashBlob, hashedBlobSize),
778          "unexpected detached blob value\n");
779         HeapFree(GetProcessHeap(), 0, hashedBlob);
780     }
781     /* Check the computed hash value too.  You don't need to get the encoded
782      * blob to get it.
783      */
784     computedHashSize = 0xdeadbeef;
785     ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, NULL,
786      &hashedBlobSize, NULL, &computedHashSize);
787     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
788     ok(computedHashSize == 16, "expected hash size of 16, got %d\n",
789      computedHashSize);
790     if (ret)
791     {
792         computedHash = HeapAlloc(GetProcessHeap(), 0, computedHashSize);
793         SetLastError(0xdeadbeef);
794         ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, NULL,
795          &hashedBlobSize, computedHash, &computedHashSize);
796         ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
797         ok(computedHashSize == sizeof(hashVal),
798          "unexpected size of hash value %d\n", computedHashSize);
799         ok(!memcmp(computedHash, hashVal, computedHashSize),
800          "unexpected value\n");
801         HeapFree(GetProcessHeap(), 0, computedHash);
802     }
803 }
804
805 static const BYTE publicPrivateKeyPair[] = {
806 0x07,0x02,0x00,0x00,0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x32,0x00,0x02,0x00,
807 0x00,0x01,0x00,0x01,0x00,0x9b,0xd9,0x60,0xd9,0x5b,0x09,0x50,0x9e,0x09,0x94,
808 0x1e,0x6a,0x06,0x1d,0xdd,0x39,0xc5,0x96,0x17,0xe3,0xb9,0x0c,0x71,0x9c,0xf7,
809 0xc1,0x07,0x7b,0xd7,0x4a,0xaa,0x8a,0x3e,0xcd,0x78,0x3c,0x4c,0x95,0x98,0x28,
810 0x29,0x2d,0xe0,0xfc,0xe6,0x4f,0x95,0xca,0x87,0x92,0xdd,0xa3,0x8d,0xf0,0x39,
811 0xf3,0x1b,0x87,0x64,0x82,0x99,0xc0,0xa9,0xe8,0x87,0x86,0x2e,0x72,0x07,0x07,
812 0x8f,0x45,0x54,0x51,0x2f,0x51,0xd0,0x60,0x97,0x48,0x54,0x0e,0x78,0xb5,0x7e,
813 0x2b,0x9d,0xca,0x81,0xa8,0xa8,0x00,0x57,0x69,0xa6,0xf7,0x4d,0x45,0xe0,0xf7,
814 0xfa,0xd2,0xeb,0xaa,0xb8,0x06,0x34,0xce,0xf0,0x9d,0x2b,0x76,0x8a,0x4f,0x70,
815 0x51,0x90,0x33,0x72,0xcb,0x81,0x85,0x7e,0x35,0x2e,0xfb,0x81,0xf0,0xc7,0x85,
816 0xa5,0x75,0xf9,0x2d,0x00,0x71,0x66,0x36,0xfe,0x22,0xd6,0xc9,0x36,0x61,0x9b,
817 0x64,0x92,0xe8,0x25,0x38,0x35,0xeb,0x0c,0x84,0x83,0x76,0x42,0x90,0xf7,0x73,
818 0x91,0xdc,0x43,0x83,0x07,0x77,0xc9,0x1b,0x3f,0x74,0xc0,0xbe,0x18,0x97,0xd6,
819 0x86,0xe5,0xfa,0x28,0x7c,0xf7,0x8d,0x89,0xb1,0x93,0xac,0x48,0x3c,0xa1,0x02,
820 0xfa,0xc6,0x1c,0xa0,0xb5,0xe8,0x4f,0xd7,0xd1,0x33,0x63,0x8b,0x7e,0xf1,0x94,
821 0x56,0x07,0xbc,0x6e,0x0c,0xbd,0xa0,0x15,0xba,0x99,0x5d,0xb7,0x5e,0x09,0xf2,
822 0x1b,0x46,0x85,0x61,0x91,0x6a,0x78,0x31,0xb5,0xf0,0xba,0x20,0xf5,0x7a,0xb4,
823 0x8e,0xd3,0x50,0x87,0xf8,0xf3,0xe4,0xd9,0xab,0x6f,0x0e,0x59,0x42,0xac,0x7d,
824 0xb1,0x8c,0xea,0x33,0x54,0x08,0x38,0xc9,0xcd,0xac,0x10,0x19,0x4a,0xba,0x89,
825 0xdc,0xb6,0x73,0xef,0xec,0x56,0x93,0xd6,0xf2,0x4b,0xba,0x50,0x2d,0x8f,0x15,
826 0xed,0x8b,0xb5,0x67,0xc8,0xfc,0x51,0x5f };
827 static const BYTE cert1[] = {
828 0x30,0x81,0xd0,0x30,0x81,0xbe,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x20,0x42,
829 0x68,0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,
830 0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x0c,0x31,0x0a,0x30,
831 0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x30,0x20,0x17,0x0d,0x31,0x30,
832 0x30,0x39,0x31,0x34,0x31,0x33,0x31,0x39,0x30,0x39,0x5a,0x18,0x0f,0x33,0x30,
833 0x31,0x30,0x30,0x39,0x31,0x34,0x31,0x33,0x31,0x39,0x30,0x39,0x5a,0x30,0x0c,
834 0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x30,0x5c,0x30,
835 0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,
836 0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe8,0xa9,0xc0,0x99,0x82,0x64,0x87,0x1b,
837 0xf3,0x39,0xf0,0x8d,0xa3,0xdd,0x92,0x87,0xca,0x95,0x4f,0xe6,0xfc,0xe0,0x2d,
838 0x29,0x28,0x98,0x95,0x4c,0x3c,0x78,0xcd,0x3e,0x8a,0xaa,0x4a,0xd7,0x7b,0x07,
839 0xc1,0xf7,0x9c,0x71,0x0c,0xb9,0xe3,0x17,0x96,0xc5,0x39,0xdd,0x1d,0x06,0x6a,
840 0x1e,0x94,0x09,0x9e,0x50,0x09,0x5b,0xd9,0x60,0xd9,0x9b,0x02,0x03,0x01,0x00,
841 0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x02,0x00,
842 0xc1 };
843 static const BYTE cert2[] = {
844 0x30,0x82,0x01,0x15,0x30,0x82,0x01,0x02,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
845 0x1c,0xf2,0x1f,0xec,0x6b,0xdc,0x36,0xbf,0x4a,0xd7,0xe1,0x6c,0x84,0x85,0xcd,
846 0x2e,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x0c,0x31,
847 0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x58,0x30,0x20,0x17,0x0d,
848 0x31,0x30,0x30,0x37,0x31,0x32,0x31,0x31,0x33,0x37,0x35,0x36,0x5a,0x18,0x0f,
849 0x33,0x30,0x31,0x30,0x30,0x37,0x31,0x32,0x31,0x31,0x33,0x37,0x35,0x36,0x5a,
850 0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x58,0x30,
851 0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,
852 0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xab,0xed,
853 0x6e,0xe0,0x00,0x3c,0xcf,0x2d,0x2b,0xda,0x05,0x88,0x6a,0x7e,0xed,0x60,0x30,
854 0x24,0xef,0x6c,0x6b,0xad,0x28,0x9b,0x14,0x90,0xf6,0xd0,0x96,0x79,0x6d,0xad,
855 0xac,0x46,0x14,0x7b,0x0e,0xfe,0xa9,0x8a,0x05,0x5a,0xc8,0x84,0x38,0x44,0xf9,
856 0xce,0xb2,0xe6,0xde,0x5b,0x80,0x0b,0x15,0xff,0x1b,0x60,0x3f,0xba,0xb2,0xfe,
857 0x6e,0xf5,0xdc,0x54,0x33,0xfc,0xfc,0x79,0x0a,0x10,0xa4,0x23,0x6d,0x67,0xeb,
858 0x16,0xb2,0x92,0xbf,0x63,0x42,0x17,0x0a,0xde,0xe6,0xab,0x8e,0xf7,0x8e,0x41,
859 0x8c,0x04,0xe8,0xe2,0x38,0x73,0xd3,0x82,0xd7,0xd1,0xee,0xd3,0xa6,0x54,0x8c,
860 0xcd,0x0b,0x93,0xda,0x63,0x55,0x0d,0x1f,0x68,0x5c,0x30,0xee,0xad,0x2d,0xd5,
861 0x40,0x56,0xe0,0xd8,0xc7,0xef,0x02,0x03,0x01,0x00,0x01,0x30,0x09,0x06,0x05,
862 0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x02,0x00,0x06 };
863 static const BYTE crl[] = {
864 0x30,0x81,0xc2,0x30,0x7e,0x02,0x01,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
865 0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x3c,0x31,0x0b,0x30,0x09,0x06,
866 0x03,0x55,0x04,0x06,0x13,0x02,0x52,0x55,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,
867 0x04,0x08,0x13,0x03,0x53,0x50,0x62,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,0x04,
868 0x07,0x13,0x03,0x53,0x50,0x62,0x31,0x11,0x30,0x0f,0x06,0x03,0x55,0x04,0x0a,
869 0x13,0x08,0x45,0x74,0x65,0x72,0x73,0x6f,0x66,0x74,0x17,0x0d,0x31,0x30,0x30,
870 0x36,0x32,0x38,0x31,0x32,0x35,0x31,0x32,0x37,0x5a,0x17,0x0d,0x31,0x30,0x30,
871 0x37,0x32,0x38,0x31,0x32,0x35,0x31,0x32,0x37,0x5a,0xa0,0x0e,0x30,0x0c,0x30,
872 0x0a,0x06,0x03,0x55,0x1d,0x14,0x04,0x03,0x02,0x01,0x00,0x30,0x0d,0x06,0x09,
873 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x31,0x00,0x83,
874 0x35,0x9c,0xf5,0x35,0x5c,0xc1,0x20,0x81,0x80,0x5c,0x35,0x56,0xaf,0xb3,0x27,
875 0x15,0xc6,0xdd,0x24,0xe1,0xff,0xb9,0xf9,0x19,0x21,0xed,0x5e,0x1b,0xff,0x72,
876 0xc3,0x33,0xf6,0x9f,0xcb,0xde,0x84,0x0b,0x12,0x84,0xad,0x48,0x90,0x9d,0xdd,
877 0x89,0xbb };
878 static const BYTE signedHashForEmptyMessage[] = {
879 0x30,0x81,0xbb,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
880 0x81,0xad,0x30,0x81,0xaa,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
881 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,
882 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x31,0x81,0x87,0x30,0x81,0x84,0x02,0x01,
883 0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,
884 0x01,0x4e,0x02,0x10,0x20,0x42,0x68,0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,
885 0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
886 0x02,0x05,0x05,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
887 0x01,0x01,0x05,0x00,0x04,0x40,0xe1,0xee,0xca,0x98,0x16,0x23,0x5a,0x34,0xfd,
888 0x91,0x69,0x97,0x1e,0x16,0xe4,0x57,0x45,0xad,0xc9,0x5d,0x2e,0xda,0x92,0xbf,
889 0xee,0x2f,0xb1,0xaa,0x32,0xfa,0x07,0x4e,0x63,0xfd,0xe1,0x52,0x17,0xd0,0xa4,
890 0x49,0x30,0x54,0x4d,0x12,0xa0,0x6a,0x1c,0x64,0xea,0xc7,0x50,0x49,0xa5,0xca,
891 0xc3,0x71,0xa4,0xf7,0x8c,0x25,0xe4,0x1a,0xca,0x89 };
892 static const BYTE signedEmptyMessage[] = {
893 0x30,0x81,0xbb,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
894 0x81,0xad,0x30,0x81,0xaa,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
895 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,
896 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x31,0x81,0x87,0x30,0x81,0x84,0x02,0x01,
897 0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,
898 0x01,0x4e,0x02,0x10,0x20,0x42,0x68,0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,
899 0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
900 0x02,0x05,0x05,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
901 0x01,0x01,0x05,0x00,0x04,0x40,0xe1,0xee,0xca,0x98,0x16,0x23,0x5a,0x34,0xfd,
902 0x91,0x69,0x97,0x1e,0x16,0xe4,0x57,0x45,0xad,0xc9,0x5d,0x2e,0xda,0x92,0xbf,
903 0xee,0x2f,0xb1,0xaa,0x32,0xfa,0x07,0x4e,0x63,0xfd,0xe1,0x52,0x17,0xd0,0xa4,
904 0x49,0x30,0x54,0x4d,0x12,0xa0,0x6a,0x1c,0x64,0xea,0xc7,0x50,0x49,0xa5,0xca,
905 0xc3,0x71,0xa4,0xf7,0x8c,0x25,0xe4,0x1a,0xca,0x89 };
906 static const BYTE signedHash[] = {
907 0x30,0x81,0xbb,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
908 0x81,0xad,0x30,0x81,0xaa,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
909 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,
910 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x31,0x81,0x87,0x30,0x81,0x84,0x02,0x01,
911 0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,
912 0x01,0x4e,0x02,0x10,0x20,0x42,0x68,0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,
913 0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
914 0x02,0x05,0x05,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
915 0x01,0x01,0x05,0x00,0x04,0x40,0x1e,0x04,0xa4,0xe3,0x90,0x54,0xed,0xcb,0x94,
916 0xa2,0xbe,0x81,0x73,0x7e,0x05,0xf2,0x82,0xd3,0x3a,0x26,0x96,0x7a,0x53,0xcd,
917 0x05,0xc3,0x09,0x69,0x3d,0x12,0x6c,0xb1,0xb0,0xab,0x0e,0xa1,0xec,0x1b,0xa1,
918 0xff,0x01,0x9c,0x49,0x9f,0x4b,0x69,0x59,0x74,0x20,0x9f,0xb0,0x19,0x95,0xe7,
919 0xed,0x1e,0x84,0xeb,0xe2,0x53,0x2c,0xa6,0x43,0xdf };
920 static const BYTE signedHashWithCert[] = {
921 0x30,0x82,0x01,0x93,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
922 0xa0,0x82,0x01,0x84,0x30,0x82,0x01,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,
923 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,
924 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x81,0xd3,0x30,0x81,
925 0xd0,0x30,0x81,0xbe,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x20,0x42,0x68,0x69,
926 0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,0x09,0x06,
927 0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,
928 0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x30,0x20,0x17,0x0d,0x31,0x30,0x30,0x39,
929 0x31,0x34,0x31,0x33,0x31,0x39,0x30,0x39,0x5a,0x18,0x0f,0x33,0x30,0x31,0x30,
930 0x30,0x39,0x31,0x34,0x31,0x33,0x31,0x39,0x30,0x39,0x5a,0x30,0x0c,0x31,0x0a,
931 0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x30,0x5c,0x30,0x0d,0x06,
932 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x4b,0x00,
933 0x30,0x48,0x02,0x41,0x00,0xe8,0xa9,0xc0,0x99,0x82,0x64,0x87,0x1b,0xf3,0x39,
934 0xf0,0x8d,0xa3,0xdd,0x92,0x87,0xca,0x95,0x4f,0xe6,0xfc,0xe0,0x2d,0x29,0x28,
935 0x98,0x95,0x4c,0x3c,0x78,0xcd,0x3e,0x8a,0xaa,0x4a,0xd7,0x7b,0x07,0xc1,0xf7,
936 0x9c,0x71,0x0c,0xb9,0xe3,0x17,0x96,0xc5,0x39,0xdd,0x1d,0x06,0x6a,0x1e,0x94,
937 0x09,0x9e,0x50,0x09,0x5b,0xd9,0x60,0xd9,0x9b,0x02,0x03,0x01,0x00,0x01,0x30,
938 0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x02,0x00,0xc1,0x31,
939 0x81,0x87,0x30,0x81,0x84,0x02,0x01,0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,0x30,
940 0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x02,0x10,0x20,0x42,0x68,0x69,
941 0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,0x06,
942 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0d,0x06,0x09,
943 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x04,0x40,0x1e,0x04,
944 0xa4,0xe3,0x90,0x54,0xed,0xcb,0x94,0xa2,0xbe,0x81,0x73,0x7e,0x05,0xf2,0x82,
945 0xd3,0x3a,0x26,0x96,0x7a,0x53,0xcd,0x05,0xc3,0x09,0x69,0x3d,0x12,0x6c,0xb1,
946 0xb0,0xab,0x0e,0xa1,0xec,0x1b,0xa1,0xff,0x01,0x9c,0x49,0x9f,0x4b,0x69,0x59,
947 0x74,0x20,0x9f,0xb0,0x19,0x95,0xe7,0xed,0x1e,0x84,0xeb,0xe2,0x53,0x2c,0xa6,
948 0x43,0xdf };
949 static const BYTE signedHashWithCRL[] = {
950 0x30,0x82,0x01,0x85,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
951 0xa0,0x82,0x01,0x76,0x30,0x82,0x01,0x72,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,
952 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,
953 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa1,0x81,0xc5,0x30,0x81,
954 0xc2,0x30,0x7e,0x02,0x01,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
955 0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x3c,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,
956 0x04,0x06,0x13,0x02,0x52,0x55,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,0x04,0x08,
957 0x13,0x03,0x53,0x50,0x62,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,0x04,0x07,0x13,
958 0x03,0x53,0x50,0x62,0x31,0x11,0x30,0x0f,0x06,0x03,0x55,0x04,0x0a,0x13,0x08,
959 0x45,0x74,0x65,0x72,0x73,0x6f,0x66,0x74,0x17,0x0d,0x31,0x30,0x30,0x36,0x32,
960 0x38,0x31,0x32,0x35,0x31,0x32,0x37,0x5a,0x17,0x0d,0x31,0x30,0x30,0x37,0x32,
961 0x38,0x31,0x32,0x35,0x31,0x32,0x37,0x5a,0xa0,0x0e,0x30,0x0c,0x30,0x0a,0x06,
962 0x03,0x55,0x1d,0x14,0x04,0x03,0x02,0x01,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,
963 0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x31,0x00,0x83,0x35,0x9c,
964 0xf5,0x35,0x5c,0xc1,0x20,0x81,0x80,0x5c,0x35,0x56,0xaf,0xb3,0x27,0x15,0xc6,
965 0xdd,0x24,0xe1,0xff,0xb9,0xf9,0x19,0x21,0xed,0x5e,0x1b,0xff,0x72,0xc3,0x33,
966 0xf6,0x9f,0xcb,0xde,0x84,0x0b,0x12,0x84,0xad,0x48,0x90,0x9d,0xdd,0x89,0xbb,
967 0x31,0x81,0x87,0x30,0x81,0x84,0x02,0x01,0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,
968 0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x02,0x10,0x20,0x42,0x68,
969 0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,
970 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0d,0x06,
971 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x04,0x40,0x1e,
972 0x04,0xa4,0xe3,0x90,0x54,0xed,0xcb,0x94,0xa2,0xbe,0x81,0x73,0x7e,0x05,0xf2,
973 0x82,0xd3,0x3a,0x26,0x96,0x7a,0x53,0xcd,0x05,0xc3,0x09,0x69,0x3d,0x12,0x6c,
974 0xb1,0xb0,0xab,0x0e,0xa1,0xec,0x1b,0xa1,0xff,0x01,0x9c,0x49,0x9f,0x4b,0x69,
975 0x59,0x74,0x20,0x9f,0xb0,0x19,0x95,0xe7,0xed,0x1e,0x84,0xeb,0xe2,0x53,0x2c,
976 0xa6,0x43,0xdf };
977 static const BYTE signedData[] = {
978 0x30,0x81,0xc3,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
979 0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
980 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
981 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
982 0x31,0x81,0x87,0x30,0x81,0x84,0x02,0x01,0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,
983 0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x02,0x10,0x20,0x42,0x68,
984 0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,
985 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0d,0x06,
986 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x04,0x40,0xe4,
987 0x69,0xf5,0x62,0xfb,0x3a,0x7d,0x1c,0x7b,0x8b,0xcc,0xfc,0x6e,0x8e,0x91,0x85,
988 0xcf,0x3c,0xb8,0xfd,0x8a,0xac,0x81,0x96,0xa0,0x42,0xac,0x88,0xc4,0x48,0xe8,
989 0x43,0x64,0xd1,0x38,0xd2,0x6c,0xc4,0xd4,0x9b,0x9a,0xd4,0x33,0x02,0xef,0x88,
990 0xef,0x98,0x2d,0xac,0xad,0xc1,0x93,0x60,0xc4,0x3a,0xdc,0xa7,0xd6,0x97,0x70,
991 0x01,0xc1,0x84 };
992
993 static void test_sign_message(void)
994 {
995     BOOL ret;
996     CRYPT_SIGN_MESSAGE_PARA para;
997     static char oid_rsa_md5[] = szOID_RSA_MD5;
998     static const BYTE blob1[] = { 0x01, 0x02, 0x03, 0x04 };
999     static const BYTE blob2[] = { 0x11, 0x12, 0x13, 0x14 };
1000     const BYTE *toSign[] = { blob1, blob2 };
1001     DWORD signSize[] = { sizeof(blob1), sizeof(blob2) };
1002     LPBYTE signedBlob;
1003     DWORD signedBlobSize;
1004     PCCRL_CONTEXT crlContext;
1005     CERT_KEY_CONTEXT keyContext;
1006     HCRYPTPROV hCryptProv = 0;
1007     HCRYPTKEY hKey = 0;
1008
1009     memset(&para, 0, sizeof(para));
1010     SetLastError(0xdeadbeef);
1011     ret = CryptSignMessage(&para, FALSE, 0, NULL, NULL, NULL, &signedBlobSize);
1012     ok(!ret &&
1013      (GetLastError() == E_INVALIDARG ||
1014       GetLastError() == ERROR_ARITHMETIC_OVERFLOW), /* Win7 */
1015      "expected E_INVALIDARG or ERROR_ARITHMETIC_OVERFLOW, got %08x\n",
1016      GetLastError());
1017     para.cbSize = sizeof(para);
1018     para.dwMsgEncodingType = X509_ASN_ENCODING;
1019     SetLastError(0xdeadbeef);
1020     signedBlobSize = 255;
1021     ret = CryptSignMessage(&para, FALSE, 0, NULL, NULL, NULL, &signedBlobSize);
1022     ok(!ret && GetLastError() == E_INVALIDARG,
1023      "expected E_INVALIDARG, got %08x\n", GetLastError());
1024     ok(!signedBlobSize, "unexpected size %d\n", signedBlobSize);
1025     para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
1026     SetLastError(0xdeadbeef);
1027     signedBlobSize = 0;
1028     ret = CryptSignMessage(&para, FALSE, 0, NULL, NULL, NULL, &signedBlobSize);
1029     ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1030     todo_wine
1031     ok(signedBlobSize, "bad size\n");
1032
1033     SetLastError(0xdeadbeef);
1034     ret = pCryptAcquireContextA(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
1035      CRYPT_VERIFYCONTEXT);
1036     ok(ret, "CryptAcquireContextA failed: %08x\n", GetLastError());
1037     SetLastError(0xdeadbeef);
1038     ret = CryptImportKey(hCryptProv, publicPrivateKeyPair,
1039      sizeof(publicPrivateKeyPair), 0, 0, &hKey);
1040     if (!ret && GetLastError() == NTE_PERM) /* Win9x */
1041     {
1042         skip("Failed to import a key\n");
1043         if (hCryptProv)
1044             CryptReleaseContext(hCryptProv, 0);
1045         return;
1046     }
1047     ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
1048
1049     para.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
1050     SetLastError(0xdeadbeef);
1051     para.pSigningCert = CertCreateCertificateContext(X509_ASN_ENCODING |
1052      PKCS_7_ASN_ENCODING, cert1, sizeof(cert1));
1053     ok(para.pSigningCert != NULL, "CertCreateCertificateContext failed: %08x\n",
1054      GetLastError());
1055     para.HashAlgorithm.pszObjId = oid_rsa_md5;
1056
1057     memset(&keyContext, 0, sizeof(keyContext));
1058     keyContext.cbSize = sizeof(keyContext);
1059     keyContext.hCryptProv = hCryptProv;
1060     keyContext.dwKeySpec = AT_SIGNATURE;
1061     SetLastError(0xdeadbeef);
1062     ret = CertSetCertificateContextProperty(para.pSigningCert,
1063      CERT_KEY_CONTEXT_PROP_ID, 0, &keyContext);
1064     ok(ret, "CertSetCertificateContextProperty failed: %08x\n", GetLastError());
1065
1066     SetLastError(0xdeadbeef);
1067     signedBlobSize = 0;
1068     ret = CryptSignMessage(&para, TRUE, 0, NULL, NULL, NULL, &signedBlobSize);
1069     ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1070     signedBlob = CryptMemAlloc(signedBlobSize);
1071     if (signedBlob)
1072     {
1073         SetLastError(0xdeadbeef);
1074         ret = CryptSignMessage(&para, TRUE, 0, NULL, NULL, signedBlob,
1075          &signedBlobSize);
1076         ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1077         ok(signedBlobSize == sizeof(signedHashForEmptyMessage),
1078          "unexpected size %d\n", signedBlobSize);
1079         ok(!memcmp(signedBlob, signedHashForEmptyMessage, signedBlobSize),
1080          "unexpected value\n");
1081         CryptMemFree(signedBlob);
1082     }
1083
1084     SetLastError(0xdeadbeef);
1085     signedBlobSize = 0;
1086     ret = CryptSignMessage(&para, FALSE, 0, NULL, NULL, NULL, &signedBlobSize);
1087     ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1088     signedBlob = CryptMemAlloc(signedBlobSize);
1089     if (signedBlob)
1090     {
1091         SetLastError(0xdeadbeef);
1092         ret = CryptSignMessage(&para, FALSE, 0, NULL, NULL, signedBlob,
1093          &signedBlobSize);
1094         ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1095         ok(signedBlobSize == sizeof(signedEmptyMessage), "unexpected size %d\n",
1096          signedBlobSize);
1097         ok(!memcmp(signedBlob, signedEmptyMessage, signedBlobSize),
1098          "unexpected value\n");
1099         CryptMemFree(signedBlob);
1100     }
1101
1102     SetLastError(0xdeadbeef);
1103     signedBlobSize = 0;
1104     ret = CryptSignMessage(&para, TRUE, 2, toSign, signSize, NULL,
1105      &signedBlobSize);
1106     ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1107     signedBlob = CryptMemAlloc(signedBlobSize);
1108     if (signedBlob)
1109     {
1110         SetLastError(0xdeadbeef);
1111         ret = CryptSignMessage(&para, TRUE, 2, toSign, signSize, signedBlob,
1112          &signedBlobSize);
1113         ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1114         ok(signedBlobSize == sizeof(signedHash),
1115          "unexpected size of signed blob %d\n", signedBlobSize);
1116         ok(!memcmp(signedBlob, signedHash, signedBlobSize),
1117          "unexpected value\n");
1118         CryptMemFree(signedBlob);
1119     }
1120
1121     para.cMsgCert = 1;
1122     para.rgpMsgCert = &para.pSigningCert;
1123
1124     SetLastError(0xdeadbeef);
1125     signedBlobSize = 0;
1126     ret = CryptSignMessage(&para, TRUE, 2, toSign, signSize, NULL,
1127      &signedBlobSize);
1128     ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1129     signedBlob = CryptMemAlloc(signedBlobSize);
1130     if (signedBlob)
1131     {
1132         SetLastError(0xdeadbeef);
1133         ret = CryptSignMessage(&para, TRUE, 2, toSign, signSize, signedBlob,
1134          &signedBlobSize);
1135         ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1136         ok(signedBlobSize == sizeof(signedHashWithCert),
1137          "unexpected size of signed blob %d\n", signedBlobSize);
1138         ok(!memcmp(signedBlob, signedHashWithCert, signedBlobSize),
1139          "unexpected value\n");
1140         CryptMemFree(signedBlob);
1141     }
1142
1143     para.cMsgCert = 0;
1144     para.rgpMsgCert = NULL;
1145     para.cMsgCrl = 1;
1146     SetLastError(0xdeadbeef);
1147     crlContext = CertCreateCRLContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
1148      crl, sizeof(crl));
1149     ok(crlContext != NULL, "CertCreateCRLContext failed: %08x\n",
1150      GetLastError());
1151     para.rgpMsgCrl = &crlContext;
1152
1153     SetLastError(0xdeadbeef);
1154     signedBlobSize = 0;
1155     ret = CryptSignMessage(&para, TRUE, 2, toSign, signSize, NULL,
1156      &signedBlobSize);
1157     ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1158     signedBlob = CryptMemAlloc(signedBlobSize);
1159     if (signedBlob)
1160     {
1161         SetLastError(0xdeadbeef);
1162         ret = CryptSignMessage(&para, TRUE, 2, toSign, signSize, signedBlob,
1163          &signedBlobSize);
1164         ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1165         ok(signedBlobSize == sizeof(signedHashWithCRL),
1166          "unexpected size of signed blob %d\n", signedBlobSize);
1167         ok(!memcmp(signedBlob, signedHashWithCRL, signedBlobSize),
1168          "unexpected value\n");
1169         CryptMemFree(signedBlob);
1170     }
1171
1172     CertFreeCRLContext(crlContext);
1173     para.cMsgCrl = 0;
1174     para.rgpMsgCrl = NULL;
1175
1176     SetLastError(0xdeadbeef);
1177     signedBlobSize = 0;
1178     ret = CryptSignMessage(&para, FALSE, 1, toSign, signSize, NULL,
1179      &signedBlobSize);
1180     ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1181     signedBlob = CryptMemAlloc(signedBlobSize);
1182     if (signedBlob)
1183     {
1184         SetLastError(0xdeadbeef);
1185         ret = CryptSignMessage(&para, FALSE, 1, toSign, signSize, signedBlob,
1186          &signedBlobSize);
1187         ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1188         ok(signedBlobSize == sizeof(signedData),
1189          "unexpected size of signed blob %d\n", signedBlobSize);
1190         ok(!memcmp(signedBlob, signedData, signedBlobSize),
1191          "unexpected value\n");
1192         CryptMemFree(signedBlob);
1193     }
1194
1195     if (para.pSigningCert)
1196         CertFreeCertificateContext(para.pSigningCert);
1197     if (hKey)
1198         CryptDestroyKey(hKey);
1199     if (hCryptProv)
1200         CryptReleaseContext(hCryptProv, 0);
1201 }
1202
1203 static const BYTE encryptedMessage[] = {
1204 0x30,0x31,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x03,0xa0,0x24,
1205 0x30,0x22,0x02,0x01,0x00,0x31,0x00,0x30,0x1b,0x06,0x09,0x2a,0x86,0x48,0x86,
1206 0xf7,0x0d,0x01,0x07,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1207 0x03,0x04,0x05,0x00,0x80,0x00 };
1208
1209 static void test_encrypt_message(void)
1210 {
1211     BOOL ret;
1212     CRYPT_ENCRYPT_MESSAGE_PARA para;
1213     static char oid_rsa_rc4[] = szOID_RSA_RC4;
1214     static const BYTE blob[] = { 0x01, 0x02, 0x03, 0x04 };
1215     PCCERT_CONTEXT certs[2];
1216     HCRYPTPROV hCryptProv = 0;
1217     LPBYTE encryptedBlob;
1218     DWORD encryptedBlobSize;
1219
1220     SetLastError(0xdeadbeef);
1221     ret = pCryptAcquireContextA(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
1222      CRYPT_VERIFYCONTEXT);
1223     ok(ret, "CryptAcquireContextA failed: %08x\n", GetLastError());
1224
1225     SetLastError(0xdeadbeef);
1226     certs[0] = CertCreateCertificateContext(X509_ASN_ENCODING |
1227      PKCS_7_ASN_ENCODING, cert1, sizeof(cert1));
1228     ok(certs[0] != NULL, "CertCreateCertificateContext failed: %08x\n",
1229      GetLastError());
1230     SetLastError(0xdeadbeef);
1231     certs[1] = CertCreateCertificateContext(X509_ASN_ENCODING |
1232      PKCS_7_ASN_ENCODING, cert2, sizeof(cert2));
1233     ok(certs[1] != NULL, "CertCreateCertificateContext failed: %08x\n",
1234      GetLastError());
1235
1236     memset(&para, 0, sizeof(para));
1237     SetLastError(0xdeadbeef);
1238     encryptedBlobSize = 255;
1239     ret = CryptEncryptMessage(&para, 0, NULL, NULL, 0, NULL,
1240      &encryptedBlobSize);
1241     ok(!ret && GetLastError() == E_INVALIDARG,
1242      "expected E_INVALIDARG, got %08x\n", GetLastError());
1243     ok(!encryptedBlobSize, "unexpected size %d\n", encryptedBlobSize);
1244     para.cbSize = sizeof(para);
1245     para.dwMsgEncodingType = X509_ASN_ENCODING;
1246     SetLastError(0xdeadbeef);
1247     encryptedBlobSize = 255;
1248     ret = CryptEncryptMessage(&para, 0, NULL, NULL, 0, NULL,
1249      &encryptedBlobSize);
1250     ok(!ret && GetLastError() == E_INVALIDARG,
1251      "expected E_INVALIDARG, got %08x\n", GetLastError());
1252     ok(!encryptedBlobSize, "unexpected size %d\n", encryptedBlobSize);
1253     para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
1254     SetLastError(0xdeadbeef);
1255     encryptedBlobSize = 255;
1256     ret = CryptEncryptMessage(&para, 0, NULL, NULL, 0, NULL,
1257      &encryptedBlobSize);
1258     ok(!ret &&
1259      (GetLastError() == CRYPT_E_UNKNOWN_ALGO ||
1260       GetLastError() == E_INVALIDARG), /* Win9x */
1261      "expected CRYPT_E_UNKNOWN_ALGO or E_INVALIDARG, got %08x\n",
1262      GetLastError());
1263     ok(!encryptedBlobSize, "unexpected size %d\n", encryptedBlobSize);
1264
1265     para.hCryptProv = hCryptProv;
1266     para.ContentEncryptionAlgorithm.pszObjId = oid_rsa_rc4;
1267
1268     SetLastError(0xdeadbeef);
1269     encryptedBlobSize = 0;
1270     ret = CryptEncryptMessage(&para, 0, NULL, NULL, 0, NULL,
1271      &encryptedBlobSize);
1272     ok(ret ||
1273      broken(!ret) /* Win9x */,
1274      "CryptEncryptMessage failed: %08x\n", GetLastError());
1275     if (ret)
1276     {
1277         encryptedBlob = CryptMemAlloc(encryptedBlobSize);
1278         if (encryptedBlob)
1279         {
1280             SetLastError(0xdeadbeef);
1281             ret = CryptEncryptMessage(&para, 0, NULL, NULL, 0, encryptedBlob,
1282              &encryptedBlobSize);
1283             ok(ret, "CryptEncryptMessage failed: %08x\n", GetLastError());
1284             ok(encryptedBlobSize == sizeof(encryptedMessage),
1285              "unexpected size of encrypted blob %d\n", encryptedBlobSize);
1286             ok(!memcmp(encryptedBlob, encryptedMessage, encryptedBlobSize),
1287              "unexpected value\n");
1288             CryptMemFree(encryptedBlob);
1289         }
1290     }
1291
1292     SetLastError(0xdeadbeef);
1293     encryptedBlobSize = 0;
1294     ret = CryptEncryptMessage(&para, 2, certs, NULL, 0, NULL,
1295      &encryptedBlobSize);
1296     ok(ret, "CryptEncryptMessage failed: %08x\n", GetLastError());
1297     if (ret)
1298     {
1299         encryptedBlob = CryptMemAlloc(encryptedBlobSize);
1300         if (encryptedBlob)
1301         {
1302             SetLastError(0xdeadbeef);
1303             ret = CryptEncryptMessage(&para, 2, certs, NULL, 0, encryptedBlob,
1304              &encryptedBlobSize);
1305             ok(ret, "CryptEncryptMessage failed: %08x\n", GetLastError());
1306             CryptMemFree(encryptedBlob);
1307         }
1308     }
1309
1310     SetLastError(0xdeadbeef);
1311     encryptedBlobSize = 0;
1312     ret = CryptEncryptMessage(&para, 0, NULL, blob, sizeof(blob), NULL,
1313      &encryptedBlobSize);
1314     ok(ret ||
1315      broken(!ret) /* Win9x */,
1316      "CryptEncryptMessage failed: %08x\n", GetLastError());
1317     if (ret)
1318     {
1319         encryptedBlob = CryptMemAlloc(encryptedBlobSize);
1320         if (encryptedBlob)
1321         {
1322             SetLastError(0xdeadbeef);
1323             ret = CryptEncryptMessage(&para, 0, NULL, blob, sizeof(blob),
1324              encryptedBlob, &encryptedBlobSize);
1325             ok(ret ||
1326              broken(!ret && GetLastError() == NTE_PERM), /* some NT4 */
1327              "CryptEncryptMessage failed: %08x\n", GetLastError());
1328             if (ret)
1329             {
1330                 ok(encryptedBlobSize == 55,
1331                  "unexpected size of encrypted blob %d\n", encryptedBlobSize);
1332             }
1333             CryptMemFree(encryptedBlob);
1334         }
1335     }
1336
1337     SetLastError(0xdeadbeef);
1338     encryptedBlobSize = 0;
1339     ret = CryptEncryptMessage(&para, 2, certs, blob, sizeof(blob), NULL,
1340      &encryptedBlobSize);
1341     ok(ret, "CryptEncryptMessage failed: %08x\n", GetLastError());
1342     if (ret)
1343     {
1344         encryptedBlob = CryptMemAlloc(encryptedBlobSize);
1345         if (encryptedBlob)
1346         {
1347             SetLastError(0xdeadbeef);
1348             ret = CryptEncryptMessage(&para, 2, certs, blob, sizeof(blob),
1349              encryptedBlob, &encryptedBlobSize);
1350             ok(ret ||
1351              broken(!ret), /* some Win95 and some NT4 */
1352              "CryptEncryptMessage failed: %08x\n", GetLastError());
1353             CryptMemFree(encryptedBlob);
1354         }
1355     }
1356
1357     if (certs[0])
1358         CertFreeCertificateContext(certs[0]);
1359     if (certs[1])
1360         CertFreeCertificateContext(certs[1]);
1361     if (hCryptProv)
1362         CryptReleaseContext(hCryptProv, 0);
1363 }
1364
1365 START_TEST(message)
1366 {
1367     init_function_pointers();
1368
1369     test_msg_get_signer_count();
1370     test_verify_detached_message_hash();
1371     test_verify_message_hash();
1372     test_verify_detached_message_signature();
1373     test_verify_message_signature();
1374     test_hash_message();
1375     test_sign_message();
1376     test_encrypt_message();
1377 }