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