sane.ds: Add suport for CAP_AUTOFEED, make batch scans the default.
[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 const BYTE dataEmptyBareContent[] = { 0x04,0x00 };
31 static const BYTE dataEmptyContent[] = {
32 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x02,
33 0x04,0x00 };
34 static const BYTE signedEmptyBareContent[] = {
35 0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
36 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02,
37 0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
38 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
39 0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,
40 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
41 static const BYTE signedEmptyContent[] = {
42 0x30,0x5f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x52,
43 0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
44 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02,
45 0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
46 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
47 0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,
48 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
49
50 static void test_msg_get_signer_count(void)
51 {
52     LONG count;
53
54     SetLastError(0xdeadbeef);
55     count = CryptGetMessageSignerCount(0, NULL, 0);
56     ok(count == -1, "Expected -1, got %d\n", count);
57     ok(GetLastError() == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n",
58      GetLastError());
59     SetLastError(0xdeadbeef);
60     count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, NULL, 0);
61     ok(count == -1, "Expected -1, got %d\n", count);
62     ok(GetLastError() == CRYPT_E_ASN1_EOD ||
63        GetLastError() == OSS_BAD_ARG, /* win9x */
64      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
65     SetLastError(0xdeadbeef);
66     count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
67      dataEmptyBareContent, sizeof(dataEmptyBareContent));
68     ok(count == -1, "Expected -1, got %d\n", count);
69     ok(GetLastError() == CRYPT_E_ASN1_BADTAG ||
70        GetLastError() == OSS_PDU_MISMATCH, /* win9x */
71      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
72     SetLastError(0xdeadbeef);
73     count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
74      dataEmptyContent, sizeof(dataEmptyContent));
75     ok(count == -1, "Expected -1, got %d\n", count);
76     ok(GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
77      "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
78     SetLastError(0xdeadbeef);
79     count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
80      signedEmptyBareContent, sizeof(signedEmptyBareContent));
81     ok(count == -1, "Expected -1, got %d\n", count);
82     ok(GetLastError() == CRYPT_E_ASN1_BADTAG ||
83        GetLastError() == OSS_DATA_ERROR, /* win9x */
84      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
85     count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
86      signedEmptyContent, sizeof(signedEmptyContent));
87     ok(count == 1 ||
88        broken(count == -1), /* win9x */
89        "Expected 1, got %d\n", count);
90 }
91
92 static BYTE detachedHashContent[] = {
93 0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
94 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
95 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
96 0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
97 0x9d,0x2a,0x8f,0x26,0x2f };
98 static const BYTE msgData[] = { 1, 2, 3, 4 };
99
100 static void test_verify_detached_message_hash(void)
101 {
102     BOOL ret;
103     CRYPT_HASH_MESSAGE_PARA para;
104     DWORD size, hashSize;
105     const BYTE *pMsgData = msgData;
106     BYTE hash[16];
107
108     if (0)
109     {
110         ret = CryptVerifyDetachedMessageHash(NULL, NULL, 0, 0, NULL, NULL, NULL,
111          NULL);
112     }
113     memset(&para, 0, sizeof(para));
114     SetLastError(0xdeadbeef);
115     ret = CryptVerifyDetachedMessageHash(&para, NULL, 0, 0, NULL, NULL, NULL,
116      NULL);
117     ok(!ret && GetLastError() == E_INVALIDARG,
118      "expected E_INVALIDARG, got %08x\n", GetLastError());
119     para.cbSize = sizeof(para);
120     SetLastError(0xdeadbeef);
121     ret = CryptVerifyDetachedMessageHash(&para, NULL, 0, 0, NULL, NULL, NULL,
122      NULL);
123     ok(!ret && GetLastError() == E_INVALIDARG,
124      "expected E_INVALIDARG, got %08x\n", GetLastError());
125     para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
126     SetLastError(0xdeadbeef);
127     ret = CryptVerifyDetachedMessageHash(&para, NULL, 0, 0, NULL, NULL, NULL,
128      NULL);
129     ok(!ret &&
130      (GetLastError() == CRYPT_E_ASN1_EOD ||
131       GetLastError() == OSS_BAD_ARG), /* win9x */
132      "expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
133     para.dwMsgEncodingType = X509_ASN_ENCODING;
134     SetLastError(0xdeadbeef);
135     ret = CryptVerifyDetachedMessageHash(&para, NULL, 0, 0, NULL, NULL, NULL,
136      NULL);
137     ok(!ret && GetLastError() == E_INVALIDARG,
138      "expected E_INVALIDARG, got %08x\n", GetLastError());
139     para.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
140     SetLastError(0xdeadbeef);
141     ret = CryptVerifyDetachedMessageHash(&para, NULL, 0, 0, NULL, NULL, NULL,
142      NULL);
143     ok(!ret &&
144      (GetLastError() == CRYPT_E_ASN1_EOD ||
145       GetLastError() == OSS_BAD_ARG), /* win9x */
146      "expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
147     /* Curiously, passing no data to hash succeeds.. */
148     ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
149      sizeof(detachedHashContent), 0, NULL, NULL, NULL, NULL);
150     todo_wine
151     ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
152     /* as does passing the actual content of the message to hash.. */
153     size = sizeof(msgData);
154     pMsgData = msgData;
155     ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
156      sizeof(detachedHashContent), 1, &pMsgData, &size, NULL, NULL);
157     ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
158     /* while passing data to hash that isn't the content of the message fails.
159      */
160     size = sizeof(detachedHashContent);
161     pMsgData = detachedHashContent;
162     SetLastError(0xdeadbeef);
163     ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
164      sizeof(detachedHashContent), 1, &pMsgData, &size, NULL, NULL);
165     ok(!ret && GetLastError() == CRYPT_E_HASH_VALUE,
166      "expected CRYPT_E_HASH_VALUE, got %08x\n", GetLastError());
167     /* Getting the size of the hash while passing no hash data causes the
168      * hash to be checked (and fail.)
169      */
170     SetLastError(0xdeadbeef);
171     ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
172      sizeof(detachedHashContent), 0, NULL, NULL, NULL, &hashSize);
173     ok(!ret && GetLastError() == CRYPT_E_HASH_VALUE,
174      "expected CRYPT_E_HASH_VALUE, got %08x\n", GetLastError());
175     size = sizeof(msgData);
176     pMsgData = msgData;
177     ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
178      sizeof(detachedHashContent), 1, &pMsgData, &size, NULL, &hashSize);
179     ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
180     ok(hashSize == sizeof(hash), "unexpected size %d\n", hashSize);
181     hashSize = 1;
182     SetLastError(0xdeadbeef);
183     ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
184      sizeof(detachedHashContent), 1, &pMsgData, &size, hash, &hashSize);
185     ok(!ret && GetLastError() == ERROR_MORE_DATA,
186      "expected ERROR_MORE_DATA, got %08x\n", GetLastError());
187     hashSize = sizeof(hash);
188     ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
189      sizeof(detachedHashContent), 1, &pMsgData, &size, hash, &hashSize);
190     ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
191 }
192
193 static BYTE hashContent[] = {
194 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
195 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
196 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
197 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
198 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
199
200 static void test_verify_message_hash(void)
201 {
202     BOOL ret;
203     CRYPT_HASH_MESSAGE_PARA para;
204     DWORD size;
205     BYTE *buf = NULL;
206
207     memset(&para, 0, sizeof(para));
208     /* Crash */
209     if (0)
210         ret = CryptVerifyMessageHash(NULL, NULL, 0, NULL, NULL, NULL, NULL);
211     SetLastError(0xdeadbeef);
212     ret = CryptVerifyMessageHash(&para, NULL, 0, NULL, NULL, NULL, NULL);
213     ok(!ret && GetLastError() == E_INVALIDARG,
214      "expected E_INVALIDARG, got %08x\n", GetLastError());
215     para.cbSize = sizeof(para);
216     SetLastError(0xdeadbeef);
217     ret = CryptVerifyMessageHash(&para, NULL, 0, NULL, NULL, NULL, NULL);
218     ok(!ret && GetLastError() == E_INVALIDARG,
219      "expected E_INVALIDARG, got %08x\n", GetLastError());
220     para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
221     SetLastError(0xdeadbeef);
222     ret = CryptVerifyMessageHash(&para, NULL, 0, NULL, NULL, NULL, NULL);
223     ok(!ret, "Expected 0, got %d\n", ret);
224     ok(GetLastError() == CRYPT_E_ASN1_EOD ||
225        GetLastError() == OSS_BAD_ARG, /* win98 */
226      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
227     /* Verifying the hash of a detached message succeeds? */
228     ret = CryptVerifyMessageHash(&para, detachedHashContent,
229      sizeof(detachedHashContent), NULL, NULL, NULL, NULL);
230     todo_wine
231     ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
232     /* As does verifying the hash of a regular message. */
233     ret = CryptVerifyMessageHash(&para, hashContent, sizeof(hashContent),
234      NULL, NULL, NULL, NULL);
235     ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
236     ret = CryptVerifyMessageHash(&para, hashContent, sizeof(hashContent),
237      NULL, &size, NULL, NULL);
238     ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
239     if (ret)
240         buf = CryptMemAlloc(size);
241     if (buf)
242     {
243         size = 1;
244         ret = CryptVerifyMessageHash(&para, hashContent, sizeof(hashContent),
245          buf, &size, NULL, NULL);
246         ok(!ret && GetLastError() == ERROR_MORE_DATA,
247          "expected ERROR_MORE_DATA, got %08x\n", GetLastError());
248         ret = CryptVerifyMessageHash(&para, hashContent, sizeof(hashContent),
249          buf, &size, NULL, NULL);
250         ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
251         ok(size == sizeof(msgData), "unexpected size %d\n", size);
252         ok(!memcmp(buf, msgData, size), "unexpected value\n");
253         CryptMemFree(buf);
254     }
255 }
256
257 static const BYTE signedWithCertContent[] = {
258 0x30,0x82,0x01,0x32,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
259 0xa0,0x82,0x01,0x23,0x30,0x82,0x01,0x1f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,
260 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,
261 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,
262 0x02,0x03,0x04,0xa0,0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
263 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
264 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
265 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
266 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
267 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
268 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
269 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
270 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,0x77,0x30,0x75,0x02,0x01,
271 0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,
272 0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,
273 0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,
274 0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,
275 0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,
276 0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,
277 0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,
278 0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
279 static const BYTE signedContent[] = {
280 0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
281 0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
282 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
283 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
284 0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,
285 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
286 0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
287 0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,
288 0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,
289 0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,
290 0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,
291 0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,
292 0x0d };
293 static const BYTE detachedSignedContent[] = {
294 0x30,0x81,0xaa,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
295 0x81,0x9c,0x30,0x81,0x99,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
296 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,
297 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,
298 0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
299 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,
300 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,
301 0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,
302 0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,
303 0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,
304 0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,
305 0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
306 static const BYTE v1CertWithValidPubKey[] = {
307 0x30,0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
308 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
309 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
310 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
311 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
312 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
313 0x67,0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
314 0x01,0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,
315 0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,
316 0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,
317 0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,
318 0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,
319 0x79,0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
320 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
321
322 static PCCERT_CONTEXT WINAPI msg_get_signer_callback(void *pvArg,
323  DWORD certEncodingType, PCERT_INFO signerId, HCERTSTORE store)
324 {
325     return CertCreateCertificateContext(X509_ASN_ENCODING,
326      v1CertWithValidPubKey, sizeof(v1CertWithValidPubKey));
327 }
328
329 static void test_verify_detached_message_signature(void)
330 {
331     CRYPT_VERIFY_MESSAGE_PARA para;
332     BOOL ret;
333     const BYTE *pContent;
334     DWORD cbContent;
335
336     memset(&para, 0, sizeof(para));
337     SetLastError(0xdeadbeef);
338     ret = CryptVerifyDetachedMessageSignature(NULL, 0, NULL, 0, 0, NULL,
339      NULL, NULL);
340     ok(!ret && GetLastError() == E_INVALIDARG,
341      "Expected E_INVALIDARG, got %08x\n", GetLastError());
342     SetLastError(0xdeadbeef);
343     ret = CryptVerifyDetachedMessageSignature(&para, 0, NULL, 0, 0, NULL,
344      NULL, NULL);
345     ok(!ret && GetLastError() == E_INVALIDARG,
346      "Expected E_INVALIDARG, got %08x\n", GetLastError());
347     para.cbSize = sizeof(para);
348     SetLastError(0xdeadbeef);
349     ret = CryptVerifyDetachedMessageSignature(&para, 0, NULL, 0, 0, NULL,
350      NULL, NULL);
351     ok(!ret && GetLastError() == E_INVALIDARG,
352      "Expected E_INVALIDARG, got %08x\n", GetLastError());
353     para.dwMsgAndCertEncodingType = X509_ASN_ENCODING;
354     SetLastError(0xdeadbeef);
355     ret = CryptVerifyDetachedMessageSignature(&para, 0, NULL, 0, 0, NULL,
356      NULL, NULL);
357     ok(!ret && GetLastError() == E_INVALIDARG,
358      "Expected E_INVALIDARG, got %08x\n", GetLastError());
359     para.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING;
360     SetLastError(0xdeadbeef);
361     ret = CryptVerifyDetachedMessageSignature(&para, 0, NULL, 0, 0, NULL,
362      NULL, NULL);
363     ok(!ret, "Expected 0, got %d\n", ret);
364     ok(GetLastError() == CRYPT_E_ASN1_EOD ||
365      GetLastError() == OSS_BAD_ARG, /* win98 */
366      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
367     /* None of these messages contains a cert in the message itself, so the
368      * default callback isn't able to verify their signature.
369      */
370     SetLastError(0xdeadbeef);
371     ret = CryptVerifyDetachedMessageSignature(&para, 0, signedWithCertContent,
372      sizeof(signedWithCertContent), 0, NULL, NULL, NULL);
373     ok(!ret, "Expected 0, got %d\n", ret);
374     todo_wine
375     ok(GetLastError() == CRYPT_E_NOT_FOUND ||
376      GetLastError() == OSS_DATA_ERROR, /* win98 */
377      "Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
378     SetLastError(0xdeadbeef);
379     ret = CryptVerifyDetachedMessageSignature(&para, 0, signedContent,
380      sizeof(signedContent), 0, NULL, NULL, NULL);
381     ok(!ret, "Expected 0, got %d\n", ret);
382     ok(GetLastError() == CRYPT_E_NOT_FOUND ||
383      GetLastError() == OSS_DATA_ERROR, /* win98 */
384      "Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
385     SetLastError(0xdeadbeef);
386     ret = CryptVerifyDetachedMessageSignature(&para, 0, detachedSignedContent,
387      sizeof(detachedSignedContent), 0, NULL, NULL, NULL);
388     ok(!ret, "Expected 0, got %d\n", ret);
389     ok(GetLastError() == CRYPT_E_NOT_FOUND ||
390      GetLastError() == OSS_DATA_ERROR, /* win98 */
391      "Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
392     SetLastError(0xdeadbeef);
393     pContent = msgData;
394     cbContent = sizeof(msgData);
395     ret = CryptVerifyDetachedMessageSignature(&para, 0, detachedSignedContent,
396      sizeof(detachedSignedContent), 1, &pContent, &cbContent, NULL);
397     ok(!ret, "Expected 0, got %d\n", ret);
398     ok(GetLastError() == CRYPT_E_NOT_FOUND ||
399      GetLastError() == OSS_DATA_ERROR, /* win98 */
400      "Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
401     /* Passing the correct callback results in success */
402     para.pfnGetSignerCertificate = msg_get_signer_callback;
403     ret = CryptVerifyDetachedMessageSignature(&para, 0, detachedSignedContent,
404      sizeof(detachedSignedContent), 1, &pContent, &cbContent, NULL);
405     ok(ret ||
406      broken(!ret), /* win98 */
407      "CryptVerifyDetachedMessageSignature failed: %08x\n",
408      GetLastError());
409     /* Not passing the correct data to be signed results in the signature not
410      * matching.
411      */
412     SetLastError(0xdeadbeef);
413     ret = CryptVerifyDetachedMessageSignature(&para, 0, detachedSignedContent,
414      sizeof(detachedSignedContent), 0, NULL, NULL, NULL);
415     ok(!ret, "Expected 0, got %d\n", ret);
416     ok(GetLastError() == NTE_BAD_SIGNATURE ||
417      GetLastError() == OSS_DATA_ERROR, /* win98 */
418      "Expected NTE_BAD_SIGNATURE or OSS_DATA_ERROR, got %08x\n", GetLastError());
419 }
420
421 static const BYTE signedWithCertEmptyContent[] = {
422 0x30,0x81,0xdf,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
423 0x81,0xd1,0x30,0x81,0xce,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
424 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x7c,
425 0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
426 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
427 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
428 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
429 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
430 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
431 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,
432 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
433 0xff,0x02,0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,
434 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
435 0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,
436 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
437 0x00 };
438 static const BYTE signedWithCertWithPubKeyContent[] = {
439 0x30,0x81,0xfc,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
440 0x81,0xee,0x30,0x81,0xeb,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,0x81,
442 0x98,0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,
443 0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,
444 0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
445 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
446 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,
447 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
448 0x6e,0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
449 0x01,0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,
450 0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,
451 0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,
452 0x02,0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
453 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
454 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
455 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
456
457 static void test_verify_message_signature(void)
458 {
459     BOOL ret;
460     CRYPT_VERIFY_MESSAGE_PARA para = { 0 };
461     PCCERT_CONTEXT cert;
462     DWORD cbDecoded;
463
464     SetLastError(0xdeadbeef);
465     ret = CryptVerifyMessageSignature(NULL, 0, NULL, 0, NULL, 0, NULL);
466     ok(!ret && GetLastError() == E_INVALIDARG,
467      "Expected E_INVALIDARG, got %08x\n", GetLastError());
468     SetLastError(0xdeadbeef);
469     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
470     ok(!ret && GetLastError() == E_INVALIDARG,
471      "Expected E_INVALIDARG, got %08x\n", GetLastError());
472     para.cbSize = sizeof(para);
473     SetLastError(0xdeadbeef);
474     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
475     ok(!ret && GetLastError() == E_INVALIDARG,
476      "Expected E_INVALIDARG, got %08x\n", GetLastError());
477     para.cbSize = 0;
478     para.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING;
479     SetLastError(0xdeadbeef);
480     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
481     ok(!ret && GetLastError() == E_INVALIDARG,
482      "Expected E_INVALIDARG, got %08x\n", GetLastError());
483     para.cbSize = sizeof(para);
484     SetLastError(0xdeadbeef);
485     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
486     ok(!ret &&
487      (GetLastError() == CRYPT_E_ASN1_EOD ||
488       GetLastError() == OSS_BAD_ARG), /* win9x */
489      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
490     /* Check whether cert is set on error */
491     cert = (PCCERT_CONTEXT)0xdeadbeef;
492     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, &cert);
493     ok(cert == NULL, "Expected NULL cert\n");
494     /* Check whether cbDecoded is set on error */
495     cbDecoded = 0xdeadbeef;
496     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, &cbDecoded,
497      NULL);
498     ok(!cbDecoded, "Expected 0\n");
499     SetLastError(0xdeadbeef);
500     ret = CryptVerifyMessageSignature(&para, 0, dataEmptyBareContent,
501      sizeof(dataEmptyBareContent), NULL, 0, NULL);
502     ok(GetLastError() == CRYPT_E_ASN1_BADTAG ||
503      GetLastError() == OSS_PDU_MISMATCH, /* win9x */
504      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
505     SetLastError(0xdeadbeef);
506     ret = CryptVerifyMessageSignature(&para, 0, dataEmptyContent,
507      sizeof(dataEmptyContent), NULL, 0, NULL);
508     ok(!ret && GetLastError() == CRYPT_E_UNEXPECTED_MSG_TYPE,
509      "Expected CRYPT_E_UNEXPECTED_MSG_TYPE, got %08x\n", GetLastError());
510     SetLastError(0xdeadbeef);
511     ret = CryptVerifyMessageSignature(&para, 0, signedEmptyBareContent,
512      sizeof(signedEmptyBareContent), NULL, 0, NULL);
513     ok(!ret &&
514      (GetLastError() == CRYPT_E_ASN1_BADTAG ||
515       GetLastError() == OSS_DATA_ERROR), /* win9x */
516      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
517     SetLastError(0xdeadbeef);
518     ret = CryptVerifyMessageSignature(&para, 0, signedEmptyContent,
519      sizeof(signedEmptyContent), NULL, 0, NULL);
520     ok(!ret &&
521      (GetLastError() == CRYPT_E_NOT_FOUND ||
522       GetLastError() == OSS_DATA_ERROR), /* win9x */
523      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
524     SetLastError(0xdeadbeef);
525     ret = CryptVerifyMessageSignature(&para, 0, signedContent,
526      sizeof(signedContent), NULL, 0, NULL);
527     ok(!ret &&
528      (GetLastError() == CRYPT_E_NOT_FOUND ||
529       GetLastError() == OSS_DATA_ERROR), /* win9x */
530      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
531     /* FIXME: Windows fails with CRYPT_E_NOT_FOUND for these messages, but
532      * their signer certs have invalid public keys that fail to decode.  In
533      * Wine therefore the failure is an ASN error.  Need some messages with
534      * valid public keys and invalid signatures to check against.
535      */
536     ret = CryptVerifyMessageSignature(&para, 0, signedWithCertEmptyContent,
537      sizeof(signedWithCertEmptyContent), NULL, 0, NULL);
538     ok(!ret, "Expected failure\n");
539     ret = CryptVerifyMessageSignature(&para, 0, signedWithCertContent,
540      sizeof(signedWithCertContent), NULL, 0, NULL);
541     ok(!ret, "Expected failure\n");
542     ret = CryptVerifyMessageSignature(&para, 0, signedWithCertWithPubKeyContent,
543      sizeof(signedWithCertWithPubKeyContent), NULL, 0, NULL);
544     ok(!ret, "Expected failure\n");
545 }
546
547 static const BYTE detachedHashBlob[] = {
548 0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
549 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
550 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
551 0x07,0x01,0x04,0x10,0x2d,0x1b,0xbc,0x1f,0xc7,0xab,0x36,0x8d,0xdb,0x95,0xe6,
552 0x24,0xb9,0x66,0x7c,0x21 };
553 static const BYTE hashBlob[] = {
554 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
555 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
556 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
557 0x07,0x01,0xa0,0x06,0x04,0x04,0xde,0xad,0xbe,0xef,0x04,0x10,0x2f,0x24,0x92,
558 0x30,0xa8,0xe7,0xc2,0xbf,0x60,0x05,0xcc,0xd2,0x67,0x92,0x59,0xec };
559 static const BYTE hashVal[] = {
560 0x2d,0x1b,0xbc,0x1f,0xc7,0xab,0x36,0x8d,0xdb,0x95,0xe6,0x24,0xb9,0x66,0x7c,
561 0x21 };
562
563 static void test_hash_message(void)
564 {
565     BOOL ret;
566     CRYPT_HASH_MESSAGE_PARA para;
567     static const BYTE blob1[] = { 0xde, 0xad, 0xbe, 0xef };
568     static const BYTE blob2[] = { 0xba, 0xad, 0xf0, 0x0d };
569     const BYTE *toHash[] = { blob1, blob2 };
570     DWORD hashSize[] = { sizeof(blob1), sizeof(blob2) };
571     DWORD hashedBlobSize, computedHashSize;
572     static char oid_rsa_md5[] = szOID_RSA_MD5;
573     LPBYTE hashedBlob, computedHash;
574
575     /* Crash
576     ret = CryptHashMessage(NULL, FALSE, 0, NULL, 0, NULL, NULL, NULL, NULL);
577      */
578     memset(&para, 0, sizeof(para));
579     SetLastError(0xdeadbeef);
580     ret = CryptHashMessage(&para, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
581     ok(!ret && GetLastError() == E_INVALIDARG,
582      "expected E_INVALIDARG, got 0x%08x\n", GetLastError());
583     para.cbSize = sizeof(para);
584     /* Not quite sure what "success" means in this case, but it does succeed */
585     SetLastError(0xdeadbeef);
586     ret = CryptHashMessage(&para, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
587     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
588     /* With a bogus encoding type it "succeeds" */
589     para.dwMsgEncodingType = 0xdeadbeef;
590     SetLastError(0xdeadbeef);
591     ret = CryptHashMessage(&para, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
592     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
593     /* According to MSDN, the third parameter (cToBeHashed) must be 1 if the
594      * second parameter (fDetached) is FALSE, but again it "succeeds."
595      */
596     SetLastError(0xdeadbeef);
597     ret = CryptHashMessage(&para, FALSE, 2, NULL, NULL, NULL, NULL, NULL, NULL);
598     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
599     /* Even passing parameters to hash results in "success." */
600     SetLastError(0xdeadbeef);
601     ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL, NULL, NULL,
602      NULL);
603     /* Try again with a valid encoding type */
604     para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
605     SetLastError(0xdeadbeef);
606     ret = CryptHashMessage(&para, FALSE, 2, NULL, NULL, NULL, NULL, NULL, NULL);
607     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
608     /* And with valid data to hash */
609     SetLastError(0xdeadbeef);
610     ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL, NULL, NULL,
611      NULL);
612     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
613     /* But requesting the size of the hashed blob and indicating there's data
614      * to hash results in a crash
615      */
616     if (0)
617     {
618         ret = CryptHashMessage(&para, FALSE, 2, NULL, NULL, NULL,
619          &hashedBlobSize, NULL, NULL);
620     }
621     /* Passing a valid pointer for the data to hash fails, as the hash
622      * algorithm is finally checked.
623      */
624     SetLastError(0xdeadbeef);
625     ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL,
626      &hashedBlobSize, NULL, NULL);
627     ok(!ret &&
628      (GetLastError() == CRYPT_E_UNKNOWN_ALGO ||
629       GetLastError() == CRYPT_E_OID_FORMAT), /* Vista */
630      "expected CRYPT_E_UNKNOWN_ALGO or CRYPT_E_OID_FORMAT, got 0x%08x (%d)\n",
631      GetLastError(), GetLastError());
632     para.HashAlgorithm.pszObjId = oid_rsa_md5;
633     /* With a valid hash algorithm, this succeeds, even though fDetached is
634      * FALSE.
635      */
636     SetLastError(0xdeadbeef);
637     ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL,
638      &hashedBlobSize, NULL, NULL);
639     todo_wine
640     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
641     if (ret)
642     {
643         /* Actually attempting to get the hashed data fails, perhaps because
644          * detached is FALSE.
645          */
646         hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
647         SetLastError(0xdeadbeef);
648         ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, hashedBlob,
649          &hashedBlobSize, NULL, NULL);
650         ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
651          "expected CRYPT_E_MSG_ERROR, got 0x%08x (%d)\n", GetLastError(),
652          GetLastError());
653         HeapFree(GetProcessHeap(), 0, hashedBlob);
654     }
655     /* Repeating tests with fDetached = TRUE results in success */
656     SetLastError(0xdeadbeef);
657     ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, NULL,
658      &hashedBlobSize, NULL, NULL);
659     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
660     if (ret)
661     {
662         hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
663         SetLastError(0xdeadbeef);
664         ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, hashedBlob,
665          &hashedBlobSize, NULL, NULL);
666         ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
667         ok(hashedBlobSize == sizeof(detachedHashBlob),
668          "unexpected size of detached blob %d\n", hashedBlobSize);
669         ok(!memcmp(hashedBlob, detachedHashBlob, hashedBlobSize),
670          "unexpected detached blob value\n");
671         HeapFree(GetProcessHeap(), 0, hashedBlob);
672     }
673     /* Hashing a single item with fDetached = FALSE also succeeds */
674     SetLastError(0xdeadbeef);
675     ret = CryptHashMessage(&para, FALSE, 1, toHash, hashSize, NULL,
676      &hashedBlobSize, NULL, NULL);
677     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
678     if (ret)
679     {
680         hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
681         ret = CryptHashMessage(&para, FALSE, 1, toHash, hashSize, hashedBlob,
682          &hashedBlobSize, NULL, NULL);
683         ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
684         ok(hashedBlobSize == sizeof(hashBlob),
685          "unexpected size of detached blob %d\n", hashedBlobSize);
686         ok(!memcmp(hashedBlob, hashBlob, hashedBlobSize),
687          "unexpected detached blob value\n");
688         HeapFree(GetProcessHeap(), 0, hashedBlob);
689     }
690     /* Check the computed hash value too.  You don't need to get the encoded
691      * blob to get it.
692      */
693     computedHashSize = 0xdeadbeef;
694     ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, NULL,
695      &hashedBlobSize, NULL, &computedHashSize);
696     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
697     ok(computedHashSize == 16, "expected hash size of 16, got %d\n",
698      computedHashSize);
699     if (ret)
700     {
701         computedHash = HeapAlloc(GetProcessHeap(), 0, computedHashSize);
702         SetLastError(0xdeadbeef);
703         ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, NULL,
704          &hashedBlobSize, computedHash, &computedHashSize);
705         ok(computedHashSize == sizeof(hashVal),
706          "unexpected size of hash value %d\n", computedHashSize);
707         ok(!memcmp(computedHash, hashVal, computedHashSize),
708          "unexpected value\n");
709         HeapFree(GetProcessHeap(), 0, computedHash);
710     }
711 }
712
713 START_TEST(message)
714 {
715     test_msg_get_signer_count();
716     test_verify_detached_message_hash();
717     test_verify_message_hash();
718     test_verify_detached_message_signature();
719     test_verify_message_signature();
720     test_hash_message();
721 }