crypt32/tests: Fix another test failure on Win98.
[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 static const BYTE signedWithCertWithValidPubKeyContent[] = {
457 0x30,0x82,0x01,0x89,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
458 0xa0,0x82,0x01,0x7a,0x30,0x82,0x01,0x76,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,
459 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,
460 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,
461 0x02,0x03,0x04,0xa0,0x81,0xd2,0x30,0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,
462 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
463 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
464 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
465 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
466 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
467 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,
468 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,
469 0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,
470 0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
471 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,
472 0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,
473 0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,
474 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
475 0x01,0x01,0xff,0x02,0x01,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
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,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
478 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
479 0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,
480 0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,
481 0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,
482 0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,
483 0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
484
485 static void test_verify_message_signature(void)
486 {
487     BOOL ret;
488     CRYPT_VERIFY_MESSAGE_PARA para = { 0 };
489     PCCERT_CONTEXT cert;
490     DWORD cbDecoded;
491     BYTE decoded[sizeof(msgData)];
492
493     SetLastError(0xdeadbeef);
494     ret = CryptVerifyMessageSignature(NULL, 0, NULL, 0, NULL, 0, NULL);
495     ok(!ret && GetLastError() == E_INVALIDARG,
496      "Expected E_INVALIDARG, got %08x\n", GetLastError());
497     /* Is cbDecoded set when invalid parameters are passed? */
498     cbDecoded = 0xdeadbeef;
499     ret = CryptVerifyMessageSignature(NULL, 0, NULL, 0, NULL, &cbDecoded,
500      NULL);
501     ok(cbDecoded == 0, "expected 0, got %08x\n", cbDecoded);
502     SetLastError(0xdeadbeef);
503     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
504     ok(!ret && GetLastError() == E_INVALIDARG,
505      "Expected E_INVALIDARG, got %08x\n", GetLastError());
506     para.cbSize = sizeof(para);
507     SetLastError(0xdeadbeef);
508     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
509     ok(!ret && GetLastError() == E_INVALIDARG,
510      "Expected E_INVALIDARG, got %08x\n", GetLastError());
511     para.cbSize = 0;
512     para.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING;
513     SetLastError(0xdeadbeef);
514     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
515     ok(!ret && GetLastError() == E_INVALIDARG,
516      "Expected E_INVALIDARG, got %08x\n", GetLastError());
517     para.cbSize = sizeof(para);
518     SetLastError(0xdeadbeef);
519     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
520     ok(!ret &&
521      (GetLastError() == CRYPT_E_ASN1_EOD ||
522       GetLastError() == OSS_BAD_ARG), /* win9x */
523      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
524     /* Check whether cert is set on error */
525     cert = (PCCERT_CONTEXT)0xdeadbeef;
526     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, &cert);
527     ok(cert == NULL, "Expected NULL cert\n");
528     /* Check whether cbDecoded is set on error */
529     cbDecoded = 0xdeadbeef;
530     ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, &cbDecoded,
531      NULL);
532     ok(!cbDecoded, "Expected 0\n");
533     SetLastError(0xdeadbeef);
534     ret = CryptVerifyMessageSignature(&para, 0, dataEmptyBareContent,
535      sizeof(dataEmptyBareContent), NULL, 0, NULL);
536     ok(GetLastError() == CRYPT_E_ASN1_BADTAG ||
537      GetLastError() == OSS_PDU_MISMATCH, /* win9x */
538      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
539     SetLastError(0xdeadbeef);
540     ret = CryptVerifyMessageSignature(&para, 0, dataEmptyContent,
541      sizeof(dataEmptyContent), NULL, 0, NULL);
542     ok(!ret && GetLastError() == CRYPT_E_UNEXPECTED_MSG_TYPE,
543      "Expected CRYPT_E_UNEXPECTED_MSG_TYPE, got %08x\n", GetLastError());
544     SetLastError(0xdeadbeef);
545     ret = CryptVerifyMessageSignature(&para, 0, signedEmptyBareContent,
546      sizeof(signedEmptyBareContent), NULL, 0, NULL);
547     ok(!ret &&
548      (GetLastError() == CRYPT_E_ASN1_BADTAG ||
549       GetLastError() == OSS_DATA_ERROR), /* win9x */
550      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
551     SetLastError(0xdeadbeef);
552     ret = CryptVerifyMessageSignature(&para, 0, signedEmptyContent,
553      sizeof(signedEmptyContent), NULL, 0, NULL);
554     ok(!ret &&
555      (GetLastError() == CRYPT_E_NOT_FOUND ||
556       GetLastError() == OSS_DATA_ERROR), /* win9x */
557      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
558     SetLastError(0xdeadbeef);
559     ret = CryptVerifyMessageSignature(&para, 0, signedContent,
560      sizeof(signedContent), NULL, 0, NULL);
561     ok(!ret &&
562      (GetLastError() == CRYPT_E_NOT_FOUND ||
563       GetLastError() == OSS_DATA_ERROR), /* win9x */
564      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
565     /* FIXME: Windows fails with CRYPT_E_NOT_FOUND for these messages, but
566      * their signer certs have invalid public keys that fail to decode.  In
567      * Wine therefore the failure is an ASN error.  Need some messages with
568      * valid public keys and invalid signatures to check against.
569      */
570     ret = CryptVerifyMessageSignature(&para, 0, signedWithCertEmptyContent,
571      sizeof(signedWithCertEmptyContent), NULL, 0, NULL);
572     ok(!ret, "Expected failure\n");
573     ret = CryptVerifyMessageSignature(&para, 0, signedWithCertContent,
574      sizeof(signedWithCertContent), NULL, 0, NULL);
575     ok(!ret, "Expected failure\n");
576     ret = CryptVerifyMessageSignature(&para, 0, signedWithCertWithPubKeyContent,
577      sizeof(signedWithCertWithPubKeyContent), NULL, 0, NULL);
578     ok(!ret, "Expected failure\n");
579     /* Apparently, an output pcbDecoded parameter is expected. */
580     ret = CryptVerifyMessageSignature(&para, 0,
581      signedWithCertWithValidPubKeyContent,
582      sizeof(signedWithCertWithValidPubKeyContent), NULL, 0, NULL);
583     ok(!ret, "Expected failure\n");
584     /* Finally, a message signed with a valid public key verifies successfully
585      */
586     cbDecoded = 0xdeadbeef;
587     ret = CryptVerifyMessageSignature(&para, 0,
588      signedWithCertWithValidPubKeyContent,
589      sizeof(signedWithCertWithValidPubKeyContent), NULL, &cbDecoded, NULL);
590     ok(ret, "CryptVerifyMessageSignature failed: %08x\n", GetLastError());
591     ok(cbDecoded == sizeof(msgData), "expected 4, got %d\n", cbDecoded);
592     cbDecoded = 0;
593     ret = CryptVerifyMessageSignature(&para, 0,
594      signedWithCertWithValidPubKeyContent,
595      sizeof(signedWithCertWithValidPubKeyContent), NULL, &cbDecoded, NULL);
596     /* Setting cbDecoded to 0 succeeds when a NULL buffer is provided */
597     ok(ret, "CryptVerifyMessageSignature failed: %08x\n", GetLastError());
598     ok(cbDecoded == sizeof(msgData), "expected 4, got %d\n", cbDecoded);
599     cbDecoded = 0;
600     ret = CryptVerifyMessageSignature(&para, 0,
601      signedWithCertWithValidPubKeyContent,
602      sizeof(signedWithCertWithValidPubKeyContent), decoded, &cbDecoded, NULL);
603     /* When a non-NULL buffer is provided, cbDecoded must not be too small */
604     ok(!ret && GetLastError() == ERROR_MORE_DATA,
605      "expected ERROR_MORE_DATA, got %d (%08x)\n", GetLastError(),
606      GetLastError());
607 }
608
609 static const BYTE detachedHashBlob[] = {
610 0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
611 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
612 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
613 0x07,0x01,0x04,0x10,0x2d,0x1b,0xbc,0x1f,0xc7,0xab,0x36,0x8d,0xdb,0x95,0xe6,
614 0x24,0xb9,0x66,0x7c,0x21 };
615 static const BYTE hashBlob[] = {
616 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
617 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
618 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
619 0x07,0x01,0xa0,0x06,0x04,0x04,0xde,0xad,0xbe,0xef,0x04,0x10,0x2f,0x24,0x92,
620 0x30,0xa8,0xe7,0xc2,0xbf,0x60,0x05,0xcc,0xd2,0x67,0x92,0x59,0xec };
621 static const BYTE hashVal[] = {
622 0x2d,0x1b,0xbc,0x1f,0xc7,0xab,0x36,0x8d,0xdb,0x95,0xe6,0x24,0xb9,0x66,0x7c,
623 0x21 };
624
625 static void test_hash_message(void)
626 {
627     BOOL ret;
628     CRYPT_HASH_MESSAGE_PARA para;
629     static const BYTE blob1[] = { 0xde, 0xad, 0xbe, 0xef };
630     static const BYTE blob2[] = { 0xba, 0xad, 0xf0, 0x0d };
631     const BYTE *toHash[] = { blob1, blob2 };
632     DWORD hashSize[] = { sizeof(blob1), sizeof(blob2) };
633     DWORD hashedBlobSize, computedHashSize;
634     static char oid_rsa_md5[] = szOID_RSA_MD5;
635     LPBYTE hashedBlob, computedHash;
636
637     /* Crash
638     ret = CryptHashMessage(NULL, FALSE, 0, NULL, 0, NULL, NULL, NULL, NULL);
639      */
640     memset(&para, 0, sizeof(para));
641     SetLastError(0xdeadbeef);
642     ret = CryptHashMessage(&para, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
643     ok(!ret && GetLastError() == E_INVALIDARG,
644      "expected E_INVALIDARG, got 0x%08x\n", GetLastError());
645     para.cbSize = sizeof(para);
646     /* Not quite sure what "success" means in this case, but it does succeed */
647     SetLastError(0xdeadbeef);
648     ret = CryptHashMessage(&para, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
649     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
650     /* With a bogus encoding type it "succeeds" */
651     para.dwMsgEncodingType = 0xdeadbeef;
652     SetLastError(0xdeadbeef);
653     ret = CryptHashMessage(&para, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
654     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
655     /* According to MSDN, the third parameter (cToBeHashed) must be 1 if the
656      * second parameter (fDetached) is FALSE, but again it "succeeds."
657      */
658     SetLastError(0xdeadbeef);
659     ret = CryptHashMessage(&para, FALSE, 2, NULL, NULL, NULL, NULL, NULL, NULL);
660     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
661     /* Even passing parameters to hash results in "success." */
662     SetLastError(0xdeadbeef);
663     ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL, NULL, NULL,
664      NULL);
665     /* Try again with a valid encoding type */
666     para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
667     SetLastError(0xdeadbeef);
668     ret = CryptHashMessage(&para, FALSE, 2, NULL, NULL, NULL, NULL, NULL, NULL);
669     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
670     /* And with valid data to hash */
671     SetLastError(0xdeadbeef);
672     ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL, NULL, NULL,
673      NULL);
674     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
675     /* But requesting the size of the hashed blob and indicating there's data
676      * to hash results in a crash
677      */
678     if (0)
679     {
680         ret = CryptHashMessage(&para, FALSE, 2, NULL, NULL, NULL,
681          &hashedBlobSize, NULL, NULL);
682     }
683     /* Passing a valid pointer for the data to hash fails, as the hash
684      * algorithm is finally checked.
685      */
686     SetLastError(0xdeadbeef);
687     ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL,
688      &hashedBlobSize, NULL, NULL);
689     ok(!ret &&
690      (GetLastError() == CRYPT_E_UNKNOWN_ALGO ||
691       GetLastError() == CRYPT_E_OID_FORMAT), /* Vista */
692      "expected CRYPT_E_UNKNOWN_ALGO or CRYPT_E_OID_FORMAT, got 0x%08x (%d)\n",
693      GetLastError(), GetLastError());
694     para.HashAlgorithm.pszObjId = oid_rsa_md5;
695     /* With a valid hash algorithm, this succeeds, even though fDetached is
696      * FALSE.
697      */
698     SetLastError(0xdeadbeef);
699     ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL,
700      &hashedBlobSize, NULL, NULL);
701     todo_wine
702     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
703     if (ret)
704     {
705         /* Actually attempting to get the hashed data fails, perhaps because
706          * detached is FALSE.
707          */
708         hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
709         SetLastError(0xdeadbeef);
710         ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, hashedBlob,
711          &hashedBlobSize, NULL, NULL);
712         ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
713          "expected CRYPT_E_MSG_ERROR, got 0x%08x (%d)\n", GetLastError(),
714          GetLastError());
715         HeapFree(GetProcessHeap(), 0, hashedBlob);
716     }
717     /* Repeating tests with fDetached = TRUE results in success */
718     SetLastError(0xdeadbeef);
719     ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, NULL,
720      &hashedBlobSize, NULL, NULL);
721     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
722     if (ret)
723     {
724         hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
725         SetLastError(0xdeadbeef);
726         ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, hashedBlob,
727          &hashedBlobSize, NULL, NULL);
728         ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
729         ok(hashedBlobSize == sizeof(detachedHashBlob),
730          "unexpected size of detached blob %d\n", hashedBlobSize);
731         ok(!memcmp(hashedBlob, detachedHashBlob, hashedBlobSize),
732          "unexpected detached blob value\n");
733         HeapFree(GetProcessHeap(), 0, hashedBlob);
734     }
735     /* Hashing a single item with fDetached = FALSE also succeeds */
736     SetLastError(0xdeadbeef);
737     ret = CryptHashMessage(&para, FALSE, 1, toHash, hashSize, NULL,
738      &hashedBlobSize, NULL, NULL);
739     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
740     if (ret)
741     {
742         hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
743         ret = CryptHashMessage(&para, FALSE, 1, toHash, hashSize, hashedBlob,
744          &hashedBlobSize, NULL, NULL);
745         ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
746         ok(hashedBlobSize == sizeof(hashBlob),
747          "unexpected size of detached blob %d\n", hashedBlobSize);
748         ok(!memcmp(hashedBlob, hashBlob, hashedBlobSize),
749          "unexpected detached blob value\n");
750         HeapFree(GetProcessHeap(), 0, hashedBlob);
751     }
752     /* Check the computed hash value too.  You don't need to get the encoded
753      * blob to get it.
754      */
755     computedHashSize = 0xdeadbeef;
756     ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, NULL,
757      &hashedBlobSize, NULL, &computedHashSize);
758     ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
759     ok(computedHashSize == 16, "expected hash size of 16, got %d\n",
760      computedHashSize);
761     if (ret)
762     {
763         computedHash = HeapAlloc(GetProcessHeap(), 0, computedHashSize);
764         SetLastError(0xdeadbeef);
765         ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, NULL,
766          &hashedBlobSize, computedHash, &computedHashSize);
767         ok(computedHashSize == sizeof(hashVal),
768          "unexpected size of hash value %d\n", computedHashSize);
769         ok(!memcmp(computedHash, hashVal, computedHashSize),
770          "unexpected value\n");
771         HeapFree(GetProcessHeap(), 0, computedHash);
772     }
773 }
774
775 static const BYTE publicPrivateKeyPair[] = {
776 0x07,0x02,0x00,0x00,0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x32,0x00,0x02,0x00,
777 0x00,0x01,0x00,0x01,0x00,0x9b,0xd9,0x60,0xd9,0x5b,0x09,0x50,0x9e,0x09,0x94,
778 0x1e,0x6a,0x06,0x1d,0xdd,0x39,0xc5,0x96,0x17,0xe3,0xb9,0x0c,0x71,0x9c,0xf7,
779 0xc1,0x07,0x7b,0xd7,0x4a,0xaa,0x8a,0x3e,0xcd,0x78,0x3c,0x4c,0x95,0x98,0x28,
780 0x29,0x2d,0xe0,0xfc,0xe6,0x4f,0x95,0xca,0x87,0x92,0xdd,0xa3,0x8d,0xf0,0x39,
781 0xf3,0x1b,0x87,0x64,0x82,0x99,0xc0,0xa9,0xe8,0x87,0x86,0x2e,0x72,0x07,0x07,
782 0x8f,0x45,0x54,0x51,0x2f,0x51,0xd0,0x60,0x97,0x48,0x54,0x0e,0x78,0xb5,0x7e,
783 0x2b,0x9d,0xca,0x81,0xa8,0xa8,0x00,0x57,0x69,0xa6,0xf7,0x4d,0x45,0xe0,0xf7,
784 0xfa,0xd2,0xeb,0xaa,0xb8,0x06,0x34,0xce,0xf0,0x9d,0x2b,0x76,0x8a,0x4f,0x70,
785 0x51,0x90,0x33,0x72,0xcb,0x81,0x85,0x7e,0x35,0x2e,0xfb,0x81,0xf0,0xc7,0x85,
786 0xa5,0x75,0xf9,0x2d,0x00,0x71,0x66,0x36,0xfe,0x22,0xd6,0xc9,0x36,0x61,0x9b,
787 0x64,0x92,0xe8,0x25,0x38,0x35,0xeb,0x0c,0x84,0x83,0x76,0x42,0x90,0xf7,0x73,
788 0x91,0xdc,0x43,0x83,0x07,0x77,0xc9,0x1b,0x3f,0x74,0xc0,0xbe,0x18,0x97,0xd6,
789 0x86,0xe5,0xfa,0x28,0x7c,0xf7,0x8d,0x89,0xb1,0x93,0xac,0x48,0x3c,0xa1,0x02,
790 0xfa,0xc6,0x1c,0xa0,0xb5,0xe8,0x4f,0xd7,0xd1,0x33,0x63,0x8b,0x7e,0xf1,0x94,
791 0x56,0x07,0xbc,0x6e,0x0c,0xbd,0xa0,0x15,0xba,0x99,0x5d,0xb7,0x5e,0x09,0xf2,
792 0x1b,0x46,0x85,0x61,0x91,0x6a,0x78,0x31,0xb5,0xf0,0xba,0x20,0xf5,0x7a,0xb4,
793 0x8e,0xd3,0x50,0x87,0xf8,0xf3,0xe4,0xd9,0xab,0x6f,0x0e,0x59,0x42,0xac,0x7d,
794 0xb1,0x8c,0xea,0x33,0x54,0x08,0x38,0xc9,0xcd,0xac,0x10,0x19,0x4a,0xba,0x89,
795 0xdc,0xb6,0x73,0xef,0xec,0x56,0x93,0xd6,0xf2,0x4b,0xba,0x50,0x2d,0x8f,0x15,
796 0xed,0x8b,0xb5,0x67,0xc8,0xfc,0x51,0x5f };
797 static const BYTE cert1[] = {
798 0x30,0x81,0xd0,0x30,0x81,0xbe,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x20,0x42,
799 0x68,0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,
800 0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x0c,0x31,0x0a,0x30,
801 0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x30,0x20,0x17,0x0d,0x31,0x30,
802 0x30,0x39,0x31,0x34,0x31,0x33,0x31,0x39,0x30,0x39,0x5a,0x18,0x0f,0x33,0x30,
803 0x31,0x30,0x30,0x39,0x31,0x34,0x31,0x33,0x31,0x39,0x30,0x39,0x5a,0x30,0x0c,
804 0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x30,0x5c,0x30,
805 0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,
806 0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe8,0xa9,0xc0,0x99,0x82,0x64,0x87,0x1b,
807 0xf3,0x39,0xf0,0x8d,0xa3,0xdd,0x92,0x87,0xca,0x95,0x4f,0xe6,0xfc,0xe0,0x2d,
808 0x29,0x28,0x98,0x95,0x4c,0x3c,0x78,0xcd,0x3e,0x8a,0xaa,0x4a,0xd7,0x7b,0x07,
809 0xc1,0xf7,0x9c,0x71,0x0c,0xb9,0xe3,0x17,0x96,0xc5,0x39,0xdd,0x1d,0x06,0x6a,
810 0x1e,0x94,0x09,0x9e,0x50,0x09,0x5b,0xd9,0x60,0xd9,0x9b,0x02,0x03,0x01,0x00,
811 0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x02,0x00,
812 0xc1 };
813 static const BYTE cert2[] = {
814 0x30,0x82,0x01,0x15,0x30,0x82,0x01,0x02,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
815 0x1c,0xf2,0x1f,0xec,0x6b,0xdc,0x36,0xbf,0x4a,0xd7,0xe1,0x6c,0x84,0x85,0xcd,
816 0x2e,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x0c,0x31,
817 0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x58,0x30,0x20,0x17,0x0d,
818 0x31,0x30,0x30,0x37,0x31,0x32,0x31,0x31,0x33,0x37,0x35,0x36,0x5a,0x18,0x0f,
819 0x33,0x30,0x31,0x30,0x30,0x37,0x31,0x32,0x31,0x31,0x33,0x37,0x35,0x36,0x5a,
820 0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x58,0x30,
821 0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,
822 0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xab,0xed,
823 0x6e,0xe0,0x00,0x3c,0xcf,0x2d,0x2b,0xda,0x05,0x88,0x6a,0x7e,0xed,0x60,0x30,
824 0x24,0xef,0x6c,0x6b,0xad,0x28,0x9b,0x14,0x90,0xf6,0xd0,0x96,0x79,0x6d,0xad,
825 0xac,0x46,0x14,0x7b,0x0e,0xfe,0xa9,0x8a,0x05,0x5a,0xc8,0x84,0x38,0x44,0xf9,
826 0xce,0xb2,0xe6,0xde,0x5b,0x80,0x0b,0x15,0xff,0x1b,0x60,0x3f,0xba,0xb2,0xfe,
827 0x6e,0xf5,0xdc,0x54,0x33,0xfc,0xfc,0x79,0x0a,0x10,0xa4,0x23,0x6d,0x67,0xeb,
828 0x16,0xb2,0x92,0xbf,0x63,0x42,0x17,0x0a,0xde,0xe6,0xab,0x8e,0xf7,0x8e,0x41,
829 0x8c,0x04,0xe8,0xe2,0x38,0x73,0xd3,0x82,0xd7,0xd1,0xee,0xd3,0xa6,0x54,0x8c,
830 0xcd,0x0b,0x93,0xda,0x63,0x55,0x0d,0x1f,0x68,0x5c,0x30,0xee,0xad,0x2d,0xd5,
831 0x40,0x56,0xe0,0xd8,0xc7,0xef,0x02,0x03,0x01,0x00,0x01,0x30,0x09,0x06,0x05,
832 0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x02,0x00,0x06 };
833 static const BYTE crl[] = {
834 0x30,0x81,0xc2,0x30,0x7e,0x02,0x01,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
835 0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x3c,0x31,0x0b,0x30,0x09,0x06,
836 0x03,0x55,0x04,0x06,0x13,0x02,0x52,0x55,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,
837 0x04,0x08,0x13,0x03,0x53,0x50,0x62,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,0x04,
838 0x07,0x13,0x03,0x53,0x50,0x62,0x31,0x11,0x30,0x0f,0x06,0x03,0x55,0x04,0x0a,
839 0x13,0x08,0x45,0x74,0x65,0x72,0x73,0x6f,0x66,0x74,0x17,0x0d,0x31,0x30,0x30,
840 0x36,0x32,0x38,0x31,0x32,0x35,0x31,0x32,0x37,0x5a,0x17,0x0d,0x31,0x30,0x30,
841 0x37,0x32,0x38,0x31,0x32,0x35,0x31,0x32,0x37,0x5a,0xa0,0x0e,0x30,0x0c,0x30,
842 0x0a,0x06,0x03,0x55,0x1d,0x14,0x04,0x03,0x02,0x01,0x00,0x30,0x0d,0x06,0x09,
843 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x31,0x00,0x83,
844 0x35,0x9c,0xf5,0x35,0x5c,0xc1,0x20,0x81,0x80,0x5c,0x35,0x56,0xaf,0xb3,0x27,
845 0x15,0xc6,0xdd,0x24,0xe1,0xff,0xb9,0xf9,0x19,0x21,0xed,0x5e,0x1b,0xff,0x72,
846 0xc3,0x33,0xf6,0x9f,0xcb,0xde,0x84,0x0b,0x12,0x84,0xad,0x48,0x90,0x9d,0xdd,
847 0x89,0xbb };
848 static const BYTE signedHashForEmptyMessage[] = {
849 0x30,0x81,0xbb,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
850 0x81,0xad,0x30,0x81,0xaa,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
851 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,
852 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x31,0x81,0x87,0x30,0x81,0x84,0x02,0x01,
853 0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,
854 0x01,0x4e,0x02,0x10,0x20,0x42,0x68,0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,
855 0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
856 0x02,0x05,0x05,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
857 0x01,0x01,0x05,0x00,0x04,0x40,0xe1,0xee,0xca,0x98,0x16,0x23,0x5a,0x34,0xfd,
858 0x91,0x69,0x97,0x1e,0x16,0xe4,0x57,0x45,0xad,0xc9,0x5d,0x2e,0xda,0x92,0xbf,
859 0xee,0x2f,0xb1,0xaa,0x32,0xfa,0x07,0x4e,0x63,0xfd,0xe1,0x52,0x17,0xd0,0xa4,
860 0x49,0x30,0x54,0x4d,0x12,0xa0,0x6a,0x1c,0x64,0xea,0xc7,0x50,0x49,0xa5,0xca,
861 0xc3,0x71,0xa4,0xf7,0x8c,0x25,0xe4,0x1a,0xca,0x89 };
862 static const BYTE signedEmptyMessage[] = {
863 0x30,0x81,0xbb,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
864 0x81,0xad,0x30,0x81,0xaa,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
865 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,
866 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x31,0x81,0x87,0x30,0x81,0x84,0x02,0x01,
867 0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,
868 0x01,0x4e,0x02,0x10,0x20,0x42,0x68,0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,
869 0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
870 0x02,0x05,0x05,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
871 0x01,0x01,0x05,0x00,0x04,0x40,0xe1,0xee,0xca,0x98,0x16,0x23,0x5a,0x34,0xfd,
872 0x91,0x69,0x97,0x1e,0x16,0xe4,0x57,0x45,0xad,0xc9,0x5d,0x2e,0xda,0x92,0xbf,
873 0xee,0x2f,0xb1,0xaa,0x32,0xfa,0x07,0x4e,0x63,0xfd,0xe1,0x52,0x17,0xd0,0xa4,
874 0x49,0x30,0x54,0x4d,0x12,0xa0,0x6a,0x1c,0x64,0xea,0xc7,0x50,0x49,0xa5,0xca,
875 0xc3,0x71,0xa4,0xf7,0x8c,0x25,0xe4,0x1a,0xca,0x89 };
876 static const BYTE signedHash[] = {
877 0x30,0x81,0xbb,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
878 0x81,0xad,0x30,0x81,0xaa,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
879 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,
880 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x31,0x81,0x87,0x30,0x81,0x84,0x02,0x01,
881 0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,
882 0x01,0x4e,0x02,0x10,0x20,0x42,0x68,0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,
883 0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
884 0x02,0x05,0x05,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
885 0x01,0x01,0x05,0x00,0x04,0x40,0x1e,0x04,0xa4,0xe3,0x90,0x54,0xed,0xcb,0x94,
886 0xa2,0xbe,0x81,0x73,0x7e,0x05,0xf2,0x82,0xd3,0x3a,0x26,0x96,0x7a,0x53,0xcd,
887 0x05,0xc3,0x09,0x69,0x3d,0x12,0x6c,0xb1,0xb0,0xab,0x0e,0xa1,0xec,0x1b,0xa1,
888 0xff,0x01,0x9c,0x49,0x9f,0x4b,0x69,0x59,0x74,0x20,0x9f,0xb0,0x19,0x95,0xe7,
889 0xed,0x1e,0x84,0xeb,0xe2,0x53,0x2c,0xa6,0x43,0xdf };
890 static const BYTE signedHashWithCert[] = {
891 0x30,0x82,0x01,0x93,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
892 0xa0,0x82,0x01,0x84,0x30,0x82,0x01,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,
893 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,
894 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x81,0xd3,0x30,0x81,
895 0xd0,0x30,0x81,0xbe,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x20,0x42,0x68,0x69,
896 0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,0x09,0x06,
897 0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,
898 0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x30,0x20,0x17,0x0d,0x31,0x30,0x30,0x39,
899 0x31,0x34,0x31,0x33,0x31,0x39,0x30,0x39,0x5a,0x18,0x0f,0x33,0x30,0x31,0x30,
900 0x30,0x39,0x31,0x34,0x31,0x33,0x31,0x39,0x30,0x39,0x5a,0x30,0x0c,0x31,0x0a,
901 0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x30,0x5c,0x30,0x0d,0x06,
902 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x4b,0x00,
903 0x30,0x48,0x02,0x41,0x00,0xe8,0xa9,0xc0,0x99,0x82,0x64,0x87,0x1b,0xf3,0x39,
904 0xf0,0x8d,0xa3,0xdd,0x92,0x87,0xca,0x95,0x4f,0xe6,0xfc,0xe0,0x2d,0x29,0x28,
905 0x98,0x95,0x4c,0x3c,0x78,0xcd,0x3e,0x8a,0xaa,0x4a,0xd7,0x7b,0x07,0xc1,0xf7,
906 0x9c,0x71,0x0c,0xb9,0xe3,0x17,0x96,0xc5,0x39,0xdd,0x1d,0x06,0x6a,0x1e,0x94,
907 0x09,0x9e,0x50,0x09,0x5b,0xd9,0x60,0xd9,0x9b,0x02,0x03,0x01,0x00,0x01,0x30,
908 0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x02,0x00,0xc1,0x31,
909 0x81,0x87,0x30,0x81,0x84,0x02,0x01,0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,0x30,
910 0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x02,0x10,0x20,0x42,0x68,0x69,
911 0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,0x06,
912 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0d,0x06,0x09,
913 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x04,0x40,0x1e,0x04,
914 0xa4,0xe3,0x90,0x54,0xed,0xcb,0x94,0xa2,0xbe,0x81,0x73,0x7e,0x05,0xf2,0x82,
915 0xd3,0x3a,0x26,0x96,0x7a,0x53,0xcd,0x05,0xc3,0x09,0x69,0x3d,0x12,0x6c,0xb1,
916 0xb0,0xab,0x0e,0xa1,0xec,0x1b,0xa1,0xff,0x01,0x9c,0x49,0x9f,0x4b,0x69,0x59,
917 0x74,0x20,0x9f,0xb0,0x19,0x95,0xe7,0xed,0x1e,0x84,0xeb,0xe2,0x53,0x2c,0xa6,
918 0x43,0xdf };
919 static const BYTE signedHashWithCRL[] = {
920 0x30,0x82,0x01,0x85,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
921 0xa0,0x82,0x01,0x76,0x30,0x82,0x01,0x72,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,
922 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,
923 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa1,0x81,0xc5,0x30,0x81,
924 0xc2,0x30,0x7e,0x02,0x01,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
925 0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x3c,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,
926 0x04,0x06,0x13,0x02,0x52,0x55,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,0x04,0x08,
927 0x13,0x03,0x53,0x50,0x62,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,0x04,0x07,0x13,
928 0x03,0x53,0x50,0x62,0x31,0x11,0x30,0x0f,0x06,0x03,0x55,0x04,0x0a,0x13,0x08,
929 0x45,0x74,0x65,0x72,0x73,0x6f,0x66,0x74,0x17,0x0d,0x31,0x30,0x30,0x36,0x32,
930 0x38,0x31,0x32,0x35,0x31,0x32,0x37,0x5a,0x17,0x0d,0x31,0x30,0x30,0x37,0x32,
931 0x38,0x31,0x32,0x35,0x31,0x32,0x37,0x5a,0xa0,0x0e,0x30,0x0c,0x30,0x0a,0x06,
932 0x03,0x55,0x1d,0x14,0x04,0x03,0x02,0x01,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,
933 0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x31,0x00,0x83,0x35,0x9c,
934 0xf5,0x35,0x5c,0xc1,0x20,0x81,0x80,0x5c,0x35,0x56,0xaf,0xb3,0x27,0x15,0xc6,
935 0xdd,0x24,0xe1,0xff,0xb9,0xf9,0x19,0x21,0xed,0x5e,0x1b,0xff,0x72,0xc3,0x33,
936 0xf6,0x9f,0xcb,0xde,0x84,0x0b,0x12,0x84,0xad,0x48,0x90,0x9d,0xdd,0x89,0xbb,
937 0x31,0x81,0x87,0x30,0x81,0x84,0x02,0x01,0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,
938 0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x02,0x10,0x20,0x42,0x68,
939 0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,
940 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0d,0x06,
941 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x04,0x40,0x1e,
942 0x04,0xa4,0xe3,0x90,0x54,0xed,0xcb,0x94,0xa2,0xbe,0x81,0x73,0x7e,0x05,0xf2,
943 0x82,0xd3,0x3a,0x26,0x96,0x7a,0x53,0xcd,0x05,0xc3,0x09,0x69,0x3d,0x12,0x6c,
944 0xb1,0xb0,0xab,0x0e,0xa1,0xec,0x1b,0xa1,0xff,0x01,0x9c,0x49,0x9f,0x4b,0x69,
945 0x59,0x74,0x20,0x9f,0xb0,0x19,0x95,0xe7,0xed,0x1e,0x84,0xeb,0xe2,0x53,0x2c,
946 0xa6,0x43,0xdf };
947 static const BYTE signedData[] = {
948 0x30,0x81,0xc3,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
949 0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
950 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
951 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
952 0x31,0x81,0x87,0x30,0x81,0x84,0x02,0x01,0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,
953 0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x02,0x10,0x20,0x42,0x68,
954 0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,
955 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0d,0x06,
956 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x04,0x40,0xe4,
957 0x69,0xf5,0x62,0xfb,0x3a,0x7d,0x1c,0x7b,0x8b,0xcc,0xfc,0x6e,0x8e,0x91,0x85,
958 0xcf,0x3c,0xb8,0xfd,0x8a,0xac,0x81,0x96,0xa0,0x42,0xac,0x88,0xc4,0x48,0xe8,
959 0x43,0x64,0xd1,0x38,0xd2,0x6c,0xc4,0xd4,0x9b,0x9a,0xd4,0x33,0x02,0xef,0x88,
960 0xef,0x98,0x2d,0xac,0xad,0xc1,0x93,0x60,0xc4,0x3a,0xdc,0xa7,0xd6,0x97,0x70,
961 0x01,0xc1,0x84 };
962
963 static void test_sign_message(void)
964 {
965     BOOL ret;
966     CRYPT_SIGN_MESSAGE_PARA para;
967     static char oid_rsa_md5[] = szOID_RSA_MD5;
968     static const BYTE blob1[] = { 0x01, 0x02, 0x03, 0x04 };
969     static const BYTE blob2[] = { 0x11, 0x12, 0x13, 0x14 };
970     const BYTE *toSign[] = { blob1, blob2 };
971     DWORD signSize[] = { sizeof(blob1), sizeof(blob2) };
972     LPBYTE signedBlob;
973     DWORD signedBlobSize;
974     PCCRL_CONTEXT crlContext;
975     CERT_KEY_CONTEXT keyContext;
976     HCRYPTPROV hCryptProv = 0;
977     HCRYPTKEY hKey = 0;
978
979     memset(&para, 0, sizeof(para));
980     SetLastError(0xdeadbeef);
981     ret = CryptSignMessage(&para, FALSE, 0, NULL, NULL, NULL, &signedBlobSize);
982     ok(!ret &&
983      (GetLastError() == E_INVALIDARG ||
984       GetLastError() == ERROR_ARITHMETIC_OVERFLOW), /* Win7 */
985      "expected E_INVALIDARG or ERROR_ARITHMETIC_OVERFLOW, got %08x\n",
986      GetLastError());
987     para.cbSize = sizeof(para);
988     para.dwMsgEncodingType = X509_ASN_ENCODING;
989     SetLastError(0xdeadbeef);
990     signedBlobSize = 255;
991     ret = CryptSignMessage(&para, FALSE, 0, NULL, NULL, NULL, &signedBlobSize);
992     ok(!ret && GetLastError() == E_INVALIDARG,
993      "expected E_INVALIDARG, got %08x\n", GetLastError());
994     ok(!signedBlobSize, "unexpected size %d\n", signedBlobSize);
995     para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
996     SetLastError(0xdeadbeef);
997     signedBlobSize = 0;
998     ret = CryptSignMessage(&para, FALSE, 0, NULL, NULL, NULL, &signedBlobSize);
999     ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1000     todo_wine
1001     ok(signedBlobSize, "bad size\n");
1002
1003     SetLastError(0xdeadbeef);
1004     ret = CryptAcquireContextA(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
1005      CRYPT_VERIFYCONTEXT);
1006     ok(ret, "CryptAcquireContextA failed: %08x\n", GetLastError());
1007     SetLastError(0xdeadbeef);
1008     ret = CryptImportKey(hCryptProv, publicPrivateKeyPair,
1009      sizeof(publicPrivateKeyPair), 0, 0, &hKey);
1010     if (!ret && GetLastError() == NTE_PERM) /* Win9x */
1011     {
1012         skip("Failed to import a key\n");
1013         if (hCryptProv)
1014             CryptReleaseContext(hCryptProv, 0);
1015         return;
1016     }
1017     ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
1018
1019     para.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
1020     SetLastError(0xdeadbeef);
1021     para.pSigningCert = CertCreateCertificateContext(X509_ASN_ENCODING |
1022      PKCS_7_ASN_ENCODING, cert1, sizeof(cert1));
1023     ok(para.pSigningCert != NULL, "CertCreateCertificateContext failed: %08x\n",
1024      GetLastError());
1025     para.HashAlgorithm.pszObjId = oid_rsa_md5;
1026
1027     memset(&keyContext, 0, sizeof(keyContext));
1028     keyContext.cbSize = sizeof(keyContext);
1029     keyContext.hCryptProv = hCryptProv;
1030     keyContext.dwKeySpec = AT_SIGNATURE;
1031     SetLastError(0xdeadbeef);
1032     ret = CertSetCertificateContextProperty(para.pSigningCert,
1033      CERT_KEY_CONTEXT_PROP_ID, 0, &keyContext);
1034     ok(ret, "CertSetCertificateContextProperty failed: %08x\n", GetLastError());
1035
1036     SetLastError(0xdeadbeef);
1037     signedBlobSize = 0;
1038     ret = CryptSignMessage(&para, TRUE, 0, NULL, NULL, NULL, &signedBlobSize);
1039     ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1040     signedBlob = CryptMemAlloc(signedBlobSize);
1041     if (signedBlob)
1042     {
1043         SetLastError(0xdeadbeef);
1044         ret = CryptSignMessage(&para, TRUE, 0, NULL, NULL, signedBlob,
1045          &signedBlobSize);
1046         ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1047         ok(signedBlobSize == sizeof(signedHashForEmptyMessage),
1048          "unexpected size %d\n", signedBlobSize);
1049         ok(!memcmp(signedBlob, signedHashForEmptyMessage, signedBlobSize),
1050          "unexpected value\n");
1051         CryptMemFree(signedBlob);
1052     }
1053
1054     SetLastError(0xdeadbeef);
1055     signedBlobSize = 0;
1056     ret = CryptSignMessage(&para, FALSE, 0, NULL, NULL, NULL, &signedBlobSize);
1057     ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1058     signedBlob = CryptMemAlloc(signedBlobSize);
1059     if (signedBlob)
1060     {
1061         SetLastError(0xdeadbeef);
1062         ret = CryptSignMessage(&para, FALSE, 0, NULL, NULL, signedBlob,
1063          &signedBlobSize);
1064         ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1065         ok(signedBlobSize == sizeof(signedEmptyMessage), "unexpected size %d\n",
1066          signedBlobSize);
1067         ok(!memcmp(signedBlob, signedEmptyMessage, signedBlobSize),
1068          "unexpected value\n");
1069         CryptMemFree(signedBlob);
1070     }
1071
1072     SetLastError(0xdeadbeef);
1073     signedBlobSize = 0;
1074     ret = CryptSignMessage(&para, TRUE, 2, toSign, signSize, NULL,
1075      &signedBlobSize);
1076     ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1077     signedBlob = CryptMemAlloc(signedBlobSize);
1078     if (signedBlob)
1079     {
1080         SetLastError(0xdeadbeef);
1081         ret = CryptSignMessage(&para, TRUE, 2, toSign, signSize, signedBlob,
1082          &signedBlobSize);
1083         ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1084         ok(signedBlobSize == sizeof(signedHash),
1085          "unexpected size of signed blob %d\n", signedBlobSize);
1086         ok(!memcmp(signedBlob, signedHash, signedBlobSize),
1087          "unexpected value\n");
1088         CryptMemFree(signedBlob);
1089     }
1090
1091     para.cMsgCert = 1;
1092     para.rgpMsgCert = &para.pSigningCert;
1093
1094     SetLastError(0xdeadbeef);
1095     signedBlobSize = 0;
1096     ret = CryptSignMessage(&para, TRUE, 2, toSign, signSize, NULL,
1097      &signedBlobSize);
1098     ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1099     signedBlob = CryptMemAlloc(signedBlobSize);
1100     if (signedBlob)
1101     {
1102         SetLastError(0xdeadbeef);
1103         ret = CryptSignMessage(&para, TRUE, 2, toSign, signSize, signedBlob,
1104          &signedBlobSize);
1105         ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1106         ok(signedBlobSize == sizeof(signedHashWithCert),
1107          "unexpected size of signed blob %d\n", signedBlobSize);
1108         ok(!memcmp(signedBlob, signedHashWithCert, signedBlobSize),
1109          "unexpected value\n");
1110         CryptMemFree(signedBlob);
1111     }
1112
1113     para.cMsgCert = 0;
1114     para.rgpMsgCert = NULL;
1115     para.cMsgCrl = 1;
1116     SetLastError(0xdeadbeef);
1117     crlContext = CertCreateCRLContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
1118      crl, sizeof(crl));
1119     ok(crlContext != NULL, "CertCreateCRLContext failed: %08x\n",
1120      GetLastError());
1121     para.rgpMsgCrl = &crlContext;
1122
1123     SetLastError(0xdeadbeef);
1124     signedBlobSize = 0;
1125     ret = CryptSignMessage(&para, TRUE, 2, toSign, signSize, NULL,
1126      &signedBlobSize);
1127     ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1128     signedBlob = CryptMemAlloc(signedBlobSize);
1129     if (signedBlob)
1130     {
1131         SetLastError(0xdeadbeef);
1132         ret = CryptSignMessage(&para, TRUE, 2, toSign, signSize, signedBlob,
1133          &signedBlobSize);
1134         ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1135         ok(signedBlobSize == sizeof(signedHashWithCRL),
1136          "unexpected size of signed blob %d\n", signedBlobSize);
1137         ok(!memcmp(signedBlob, signedHashWithCRL, signedBlobSize),
1138          "unexpected value\n");
1139         CryptMemFree(signedBlob);
1140     }
1141
1142     CertFreeCRLContext(crlContext);
1143     para.cMsgCrl = 0;
1144     para.rgpMsgCrl = NULL;
1145
1146     SetLastError(0xdeadbeef);
1147     signedBlobSize = 0;
1148     ret = CryptSignMessage(&para, FALSE, 1, toSign, signSize, NULL,
1149      &signedBlobSize);
1150     ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1151     signedBlob = CryptMemAlloc(signedBlobSize);
1152     if (signedBlob)
1153     {
1154         SetLastError(0xdeadbeef);
1155         ret = CryptSignMessage(&para, FALSE, 1, toSign, signSize, signedBlob,
1156          &signedBlobSize);
1157         ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1158         ok(signedBlobSize == sizeof(signedData),
1159          "unexpected size of signed blob %d\n", signedBlobSize);
1160         ok(!memcmp(signedBlob, signedData, signedBlobSize),
1161          "unexpected value\n");
1162         CryptMemFree(signedBlob);
1163     }
1164
1165     if (para.pSigningCert)
1166         CertFreeCertificateContext(para.pSigningCert);
1167     if (hKey)
1168         CryptDestroyKey(hKey);
1169     if (hCryptProv)
1170         CryptReleaseContext(hCryptProv, 0);
1171 }
1172
1173 static const BYTE encryptedMessage[] = {
1174 0x30,0x31,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x03,0xa0,0x24,
1175 0x30,0x22,0x02,0x01,0x00,0x31,0x00,0x30,0x1b,0x06,0x09,0x2a,0x86,0x48,0x86,
1176 0xf7,0x0d,0x01,0x07,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1177 0x03,0x04,0x05,0x00,0x80,0x00 };
1178
1179 static void test_encrypt_message(void)
1180 {
1181     BOOL ret;
1182     CRYPT_ENCRYPT_MESSAGE_PARA para;
1183     static char oid_rsa_rc4[] = szOID_RSA_RC4;
1184     static const BYTE blob[] = { 0x01, 0x02, 0x03, 0x04 };
1185     PCCERT_CONTEXT certs[2];
1186     HCRYPTPROV hCryptProv = 0;
1187     LPBYTE encryptedBlob;
1188     DWORD encryptedBlobSize;
1189
1190     SetLastError(0xdeadbeef);
1191     ret = CryptAcquireContextA(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
1192      CRYPT_VERIFYCONTEXT);
1193     ok(ret, "CryptAcquireContextA failed: %08x\n", GetLastError());
1194
1195     SetLastError(0xdeadbeef);
1196     certs[0] = CertCreateCertificateContext(X509_ASN_ENCODING |
1197      PKCS_7_ASN_ENCODING, cert1, sizeof(cert1));
1198     ok(certs[0] != NULL, "CertCreateCertificateContext failed: %08x\n",
1199      GetLastError());
1200     SetLastError(0xdeadbeef);
1201     certs[1] = CertCreateCertificateContext(X509_ASN_ENCODING |
1202      PKCS_7_ASN_ENCODING, cert2, sizeof(cert2));
1203     ok(certs[1] != NULL, "CertCreateCertificateContext failed: %08x\n",
1204      GetLastError());
1205
1206     memset(&para, 0, sizeof(para));
1207     SetLastError(0xdeadbeef);
1208     encryptedBlobSize = 255;
1209     ret = CryptEncryptMessage(&para, 0, NULL, NULL, 0, NULL,
1210      &encryptedBlobSize);
1211     todo_wine
1212     ok(!ret && GetLastError() == E_INVALIDARG,
1213      "expected E_INVALIDARG, got %08x\n", GetLastError());
1214     todo_wine
1215     ok(!encryptedBlobSize, "unexpected size %d\n", encryptedBlobSize);
1216     para.cbSize = sizeof(para);
1217     para.dwMsgEncodingType = X509_ASN_ENCODING;
1218     SetLastError(0xdeadbeef);
1219     encryptedBlobSize = 255;
1220     ret = CryptEncryptMessage(&para, 0, NULL, NULL, 0, NULL,
1221      &encryptedBlobSize);
1222     todo_wine
1223     ok(!ret && GetLastError() == E_INVALIDARG,
1224      "expected E_INVALIDARG, got %08x\n", GetLastError());
1225     todo_wine
1226     ok(!encryptedBlobSize, "unexpected size %d\n", encryptedBlobSize);
1227     para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
1228     SetLastError(0xdeadbeef);
1229     encryptedBlobSize = 255;
1230     ret = CryptEncryptMessage(&para, 0, NULL, NULL, 0, NULL,
1231      &encryptedBlobSize);
1232     todo_wine
1233     ok(!ret &&
1234      (GetLastError() == CRYPT_E_UNKNOWN_ALGO ||
1235       GetLastError() == E_INVALIDARG), /* Win9x */
1236      "expected CRYPT_E_UNKNOWN_ALGO or E_INVALIDARG, got %08x\n",
1237      GetLastError());
1238     todo_wine
1239     ok(!encryptedBlobSize, "unexpected size %d\n", encryptedBlobSize);
1240
1241     para.hCryptProv = hCryptProv;
1242     para.ContentEncryptionAlgorithm.pszObjId = oid_rsa_rc4;
1243
1244     SetLastError(0xdeadbeef);
1245     encryptedBlobSize = 0;
1246     ret = CryptEncryptMessage(&para, 0, NULL, NULL, 0, NULL,
1247      &encryptedBlobSize);
1248     todo_wine
1249     ok(ret ||
1250      broken(!ret) /* Win9x */,
1251      "CryptEncryptMessage failed: %08x\n", GetLastError());
1252     if (ret)
1253     {
1254         encryptedBlob = CryptMemAlloc(encryptedBlobSize);
1255         if (encryptedBlob)
1256         {
1257             SetLastError(0xdeadbeef);
1258             ret = CryptEncryptMessage(&para, 0, NULL, NULL, 0, encryptedBlob,
1259              &encryptedBlobSize);
1260             todo_wine
1261             ok(ret, "CryptEncryptMessage failed: %08x\n", GetLastError());
1262             todo_wine
1263             ok(encryptedBlobSize == sizeof(encryptedMessage),
1264              "unexpected size of encrypted blob %d\n", encryptedBlobSize);
1265             ok(!memcmp(encryptedBlob, encryptedMessage, encryptedBlobSize),
1266              "unexpected value\n");
1267             CryptMemFree(encryptedBlob);
1268         }
1269     }
1270
1271     SetLastError(0xdeadbeef);
1272     encryptedBlobSize = 0;
1273     ret = CryptEncryptMessage(&para, 2, certs, NULL, 0, NULL,
1274      &encryptedBlobSize);
1275     todo_wine
1276     ok(ret, "CryptEncryptMessage failed: %08x\n", GetLastError());
1277     if (ret)
1278     {
1279         encryptedBlob = CryptMemAlloc(encryptedBlobSize);
1280         if (encryptedBlob)
1281         {
1282             SetLastError(0xdeadbeef);
1283             ret = CryptEncryptMessage(&para, 2, certs, NULL, 0, encryptedBlob,
1284              &encryptedBlobSize);
1285             todo_wine
1286             ok(ret, "CryptEncryptMessage failed: %08x\n", GetLastError());
1287             CryptMemFree(encryptedBlob);
1288         }
1289     }
1290
1291     SetLastError(0xdeadbeef);
1292     encryptedBlobSize = 0;
1293     ret = CryptEncryptMessage(&para, 0, NULL, blob, sizeof(blob), NULL,
1294      &encryptedBlobSize);
1295     todo_wine
1296     ok(ret ||
1297      broken(!ret) /* Win9x */,
1298      "CryptEncryptMessage failed: %08x\n", GetLastError());
1299     if (ret)
1300     {
1301         encryptedBlob = CryptMemAlloc(encryptedBlobSize);
1302         if (encryptedBlob)
1303         {
1304             SetLastError(0xdeadbeef);
1305             ret = CryptEncryptMessage(&para, 0, NULL, blob, sizeof(blob),
1306              encryptedBlob, &encryptedBlobSize);
1307             todo_wine
1308             ok(ret, "CryptEncryptMessage failed: %08x\n", GetLastError());
1309             todo_wine
1310             ok(encryptedBlobSize == 55,
1311              "unexpected size of encrypted blob %d\n", encryptedBlobSize);
1312             CryptMemFree(encryptedBlob);
1313         }
1314     }
1315
1316     SetLastError(0xdeadbeef);
1317     encryptedBlobSize = 0;
1318     ret = CryptEncryptMessage(&para, 2, certs, blob, sizeof(blob), NULL,
1319      &encryptedBlobSize);
1320     todo_wine
1321     ok(ret, "CryptEncryptMessage failed: %08x\n", GetLastError());
1322     if (ret)
1323     {
1324         encryptedBlob = CryptMemAlloc(encryptedBlobSize);
1325         if (encryptedBlob)
1326         {
1327             SetLastError(0xdeadbeef);
1328             ret = CryptEncryptMessage(&para, 2, certs, blob, sizeof(blob),
1329              encryptedBlob, &encryptedBlobSize);
1330             todo_wine
1331             ok(ret, "CryptEncryptMessage failed: %08x\n", GetLastError());
1332             CryptMemFree(encryptedBlob);
1333         }
1334     }
1335
1336     if (certs[0])
1337         CertFreeCertificateContext(certs[0]);
1338     if (certs[1])
1339         CertFreeCertificateContext(certs[1]);
1340     if (hCryptProv)
1341         CryptReleaseContext(hCryptProv, 0);
1342 }
1343
1344 START_TEST(message)
1345 {
1346     test_msg_get_signer_count();
1347     test_verify_detached_message_hash();
1348     test_verify_message_hash();
1349     test_verify_detached_message_signature();
1350     test_verify_message_signature();
1351     test_hash_message();
1352     test_sign_message();
1353     test_encrypt_message();
1354 }