crypt32: Add tests for updating signed encoded messages.
[wine] / dlls / crypt32 / tests / msg.c
1 /*
2  * Unit test suite for crypt32.dll's CryptMsg functions
3  *
4  * Copyright 2007 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 void test_msg_open_to_encode(void)
31 {
32     HCRYPTMSG msg;
33
34     /* Crash
35     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, NULL,
36      NULL, NULL);
37     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, NULL, NULL,
38      NULL);
39     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, NULL, NULL,
40      NULL);
41      */
42
43     /* Bad encodings */
44     SetLastError(0xdeadbeef);
45     msg = CryptMsgOpenToEncode(0, 0, 0, NULL, NULL, NULL);
46     ok(!msg && GetLastError() == E_INVALIDARG,
47      "Expected E_INVALIDARG, got %x\n", GetLastError());
48     SetLastError(0xdeadbeef);
49     msg = CryptMsgOpenToEncode(X509_ASN_ENCODING, 0, 0, NULL, NULL, NULL);
50     ok(!msg && GetLastError() == E_INVALIDARG,
51      "Expected E_INVALIDARG, got %x\n", GetLastError());
52
53     /* Bad message types */
54     SetLastError(0xdeadbeef);
55     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, 0, NULL, NULL, NULL);
56     ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
57      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
58     SetLastError(0xdeadbeef);
59     msg = CryptMsgOpenToEncode(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, 0,
60      NULL, NULL, NULL);
61     ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
62      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
63     SetLastError(0xdeadbeef);
64     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0,
65      CMSG_SIGNED_AND_ENVELOPED, NULL, NULL, NULL);
66     ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
67      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
68     SetLastError(0xdeadbeef);
69     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, NULL,
70      NULL, NULL);
71     ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
72      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
73 }
74
75 static void test_msg_open_to_decode(void)
76 {
77     HCRYPTMSG msg;
78     CMSG_STREAM_INFO streamInfo = { 0 };
79
80     SetLastError(0xdeadbeef);
81     msg = CryptMsgOpenToDecode(0, 0, 0, 0, NULL, NULL);
82     ok(!msg && GetLastError() == E_INVALIDARG,
83      "Expected E_INVALIDARG, got %x\n", GetLastError());
84
85     /* Bad encodings */
86     SetLastError(0xdeadbeef);
87     msg = CryptMsgOpenToDecode(X509_ASN_ENCODING, 0, 0, 0, NULL, NULL);
88     ok(!msg && GetLastError() == E_INVALIDARG,
89      "Expected E_INVALIDARG, got %x\n", GetLastError());
90     SetLastError(0xdeadbeef);
91     msg = CryptMsgOpenToDecode(X509_ASN_ENCODING, 0, CMSG_DATA, 0, NULL, NULL);
92     ok(!msg && GetLastError() == E_INVALIDARG,
93      "Expected E_INVALIDARG, got %x\n", GetLastError());
94
95     /* The message type can be explicit... */
96     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
97      NULL);
98     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
99     CryptMsgClose(msg);
100     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, 0, NULL,
101      NULL);
102     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
103     CryptMsgClose(msg);
104     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
105      NULL);
106     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
107     CryptMsgClose(msg);
108     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
109      NULL);
110     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
111     CryptMsgClose(msg);
112     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0,
113      CMSG_SIGNED_AND_ENVELOPED, 0, NULL, NULL);
114     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
115     CryptMsgClose(msg);
116     /* or implicit.. */
117     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
118     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
119     CryptMsgClose(msg);
120     /* or even invalid. */
121     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, 0, NULL,
122      NULL);
123     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
124     CryptMsgClose(msg);
125     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 1000, 0, NULL, NULL);
126     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
127     CryptMsgClose(msg);
128
129     /* And even though the stream info parameter "must be set to NULL" for
130      * CMSG_HASHED, it's still accepted.
131      */
132     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
133      &streamInfo);
134     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
135     CryptMsgClose(msg);
136 }
137
138 static void test_msg_get_param(void)
139 {
140     BOOL ret;
141     HCRYPTMSG msg;
142     DWORD size, i, value;
143     CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
144     CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
145
146     /* Crash
147     ret = CryptMsgGetParam(NULL, 0, 0, NULL, NULL);
148     ret = CryptMsgGetParam(NULL, 0, 0, NULL, &size);
149     ret = CryptMsgGetParam(msg, 0, 0, NULL, NULL);
150      */
151
152     /* Decoded messages */
153     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
154     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
155     /* For decoded messages, the type is always available */
156     size = 0;
157     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
158     ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
159     size = sizeof(value);
160     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
161     ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
162     /* For this (empty) message, the type isn't set */
163     ok(value == 0, "Expected type 0, got %d\n", value);
164     CryptMsgClose(msg);
165
166     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
167      NULL);
168     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
169     /* For explicitly typed messages, the type is known. */
170     size = sizeof(value);
171     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
172     ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
173     ok(value == CMSG_DATA, "Expected CMSG_DATA, got %d\n", value);
174     for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++)
175     {
176         size = 0;
177         ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
178         ok(!ret, "Parameter %d: expected failure\n", i);
179     }
180     CryptMsgClose(msg);
181
182     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, 0, NULL,
183      NULL);
184     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
185     size = sizeof(value);
186     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
187     ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
188     ok(value == CMSG_ENVELOPED, "Expected CMSG_ENVELOPED, got %d\n", value);
189     for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++)
190     {
191         size = 0;
192         ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
193         ok(!ret, "Parameter %d: expected failure\n", i);
194     }
195     CryptMsgClose(msg);
196
197     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
198      NULL);
199     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
200     size = sizeof(value);
201     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
202     ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
203     ok(value == CMSG_HASHED, "Expected CMSG_HASHED, got %d\n", value);
204     for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++)
205     {
206         size = 0;
207         ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
208         ok(!ret, "Parameter %d: expected failure\n", i);
209     }
210     CryptMsgClose(msg);
211
212     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
213      NULL);
214     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
215     size = sizeof(value);
216     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
217     ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
218     ok(value == CMSG_SIGNED, "Expected CMSG_SIGNED, got %d\n", value);
219     for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++)
220     {
221         size = 0;
222         ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
223         ok(!ret, "Parameter %d: expected failure\n", i);
224     }
225     CryptMsgClose(msg);
226
227     /* Explicitly typed messages get their types set, even if they're invalid */
228     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, 0, NULL,
229      NULL);
230     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
231     size = sizeof(value);
232     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
233     ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
234     ok(value == CMSG_ENCRYPTED, "Expected CMSG_ENCRYPTED, got %d\n", value);
235     CryptMsgClose(msg);
236
237     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 1000, 0, NULL, NULL);
238     ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
239     size = sizeof(value);
240     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
241     ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
242     ok(value == 1000, "Expected 1000, got %d\n", value);
243     CryptMsgClose(msg);
244 }
245
246 static void test_msg_close(void)
247 {
248     BOOL ret;
249     HCRYPTMSG msg;
250
251     /* NULL succeeds.. */
252     ret = CryptMsgClose(NULL);
253     ok(ret, "CryptMsgClose failed: %x\n", GetLastError());
254     /* but an arbitrary pointer crashes. */
255     if (0)
256         ret = CryptMsgClose((HCRYPTMSG)1);
257     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
258      NULL);
259     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
260     ret = CryptMsgClose(msg);
261     ok(ret, "CryptMsgClose failed: %x\n", GetLastError());
262 }
263
264 static void check_param(LPCSTR test, HCRYPTMSG msg, DWORD param,
265  const BYTE *expected, DWORD expectedSize)
266 {
267     DWORD size;
268     LPBYTE buf;
269     BOOL ret;
270
271     size = 0xdeadbeef;
272     ret = CryptMsgGetParam(msg, param, 0, NULL, &size);
273     ok(ret, "%s: CryptMsgGetParam failed: %08x\n", test, GetLastError());
274     buf = HeapAlloc(GetProcessHeap(), 0, size);
275     ret = CryptMsgGetParam(msg, param, 0, buf, &size);
276     ok(ret, "%s: CryptMsgGetParam failed: %08x\n", test, GetLastError());
277     ok(size == expectedSize, "%s: expected size %d, got %d\n", test,
278      expectedSize, size);
279     if (size == expectedSize && size)
280         ok(!memcmp(buf, expected, size), "%s: unexpected data\n", test);
281     HeapFree(GetProcessHeap(), 0, buf);
282 }
283
284 static void test_data_msg_open(void)
285 {
286     HCRYPTMSG msg;
287     CMSG_HASHED_ENCODE_INFO hashInfo = { 0 };
288     CMSG_STREAM_INFO streamInfo = { 0 };
289     char oid[] = "1.2.3";
290
291     /* The data message type takes no additional info */
292     SetLastError(0xdeadbeef);
293     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, &hashInfo,
294      NULL, NULL);
295     ok(!msg && GetLastError() == E_INVALIDARG,
296      "Expected E_INVALIDARG, got %x\n", GetLastError());
297     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
298      NULL);
299     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
300     CryptMsgClose(msg);
301
302     /* An empty stream info is allowed. */
303     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
304      &streamInfo);
305     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
306     CryptMsgClose(msg);
307
308     /* Passing a bogus inner OID succeeds for a non-streamed message.. */
309     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, oid,
310      NULL);
311     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
312     CryptMsgClose(msg);
313     /* and still succeeds when CMSG_DETACHED_FLAG is passed.. */
314     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
315      CMSG_DATA, NULL, oid, NULL);
316     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
317     CryptMsgClose(msg);
318     /* and when a stream info is given, even though you're not supposed to be
319      * able to use anything but szOID_RSA_data when streaming is being used.
320      */
321     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
322      CMSG_DATA, NULL, oid, &streamInfo);
323     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
324     CryptMsgClose(msg);
325 }
326
327 static const BYTE msgData[] = { 1, 2, 3, 4 };
328
329 static BOOL WINAPI nop_stream_output(const void *pvArg, BYTE *pb, DWORD cb,
330  BOOL final)
331 {
332     return TRUE;
333 }
334
335 static void test_data_msg_update(void)
336 {
337     HCRYPTMSG msg;
338     BOOL ret;
339     CMSG_STREAM_INFO streamInfo = { 0 };
340
341     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
342      NULL);
343     /* Can't update a message that wasn't opened detached with final = FALSE */
344     SetLastError(0xdeadbeef);
345     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
346     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
347      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
348     /* Updating it with final = TRUE succeeds */
349     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
350     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
351     /* Any subsequent update will fail, as the last was final */
352     SetLastError(0xdeadbeef);
353     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
354     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
355      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
356     CryptMsgClose(msg);
357
358     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
359      NULL);
360     /* Can't update a message with no data */
361     SetLastError(0xdeadbeef);
362     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
363     ok(!ret && GetLastError() == E_INVALIDARG,
364      "Expected E_INVALIDARG, got %x\n", GetLastError());
365     /* Curiously, a valid update will now fail as well, presumably because of
366      * the last (invalid, but final) update.
367      */
368     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
369     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
370      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
371     CryptMsgClose(msg);
372
373     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
374      CMSG_DATA, NULL, NULL, NULL);
375     /* Doesn't appear to be able to update CMSG-DATA with non-final updates */
376     SetLastError(0xdeadbeef);
377     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
378     ok(!ret && GetLastError() == E_INVALIDARG,
379      "Expected E_INVALIDARG, got %x\n", GetLastError());
380     SetLastError(0xdeadbeef);
381     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
382     ok(!ret && GetLastError() == E_INVALIDARG,
383      "Expected E_INVALIDARG, got %x\n", GetLastError());
384     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
385     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
386     CryptMsgClose(msg);
387
388     /* Calling update after opening with an empty stream info (with a bogus
389      * output function) yields an error:
390      */
391     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
392      &streamInfo);
393     SetLastError(0xdeadbeef);
394     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
395     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
396      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
397     CryptMsgClose(msg);
398     /* Calling update with a valid output function succeeds, even if the data
399      * exceeds the size specified in the stream info.
400      */
401     streamInfo.pfnStreamOutput = nop_stream_output;
402     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
403      &streamInfo);
404     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
405     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
406     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
407     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
408     CryptMsgClose(msg);
409 }
410
411 static void test_data_msg_get_param(void)
412 {
413     HCRYPTMSG msg;
414     DWORD size;
415     BOOL ret;
416     CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
417
418     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
419      NULL);
420
421     /* Content and bare content are always gettable when not streaming */
422     size = 0;
423     ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
424     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
425     size = 0;
426     ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
427     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
428     /* But for this type of message, the signer and hash aren't applicable,
429      * and the type isn't available.
430      */
431     size = 0;
432     SetLastError(0xdeadbeef);
433     ret = CryptMsgGetParam(msg, CMSG_ENCODED_SIGNER, 0, NULL, &size);
434     ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
435      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
436     SetLastError(0xdeadbeef);
437     ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
438     ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
439      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
440     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
441     ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
442      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
443     CryptMsgClose(msg);
444
445     /* Can't get content or bare content when streaming */
446     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
447      NULL, &streamInfo);
448     SetLastError(0xdeadbeef);
449     ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
450     ok(!ret && GetLastError() == E_INVALIDARG,
451      "Expected E_INVALIDARG, got %x\n", GetLastError());
452     SetLastError(0xdeadbeef);
453     ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
454     ok(!ret && GetLastError() == E_INVALIDARG,
455      "Expected E_INVALIDARG, got %x\n", GetLastError());
456     CryptMsgClose(msg);
457 }
458
459 static const BYTE dataEmptyBareContent[] = { 0x04,0x00 };
460 static const BYTE dataEmptyContent[] = {
461 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x02,
462 0x04,0x00 };
463 static const BYTE dataBareContent[] = { 0x04,0x04,0x01,0x02,0x03,0x04 };
464 static const BYTE dataContent[] = {
465 0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,
466 0x04,0x04,0x01,0x02,0x03,0x04 };
467
468 struct update_accum
469 {
470     DWORD cUpdates;
471     CRYPT_DATA_BLOB *updates;
472 };
473
474 static BOOL WINAPI accumulating_stream_output(const void *pvArg, BYTE *pb,
475  DWORD cb, BOOL final)
476 {
477     struct update_accum *accum = (struct update_accum *)pvArg;
478     BOOL ret = FALSE;
479
480     if (accum->cUpdates)
481         accum->updates = CryptMemRealloc(accum->updates,
482          (accum->cUpdates + 1) * sizeof(CRYPT_DATA_BLOB));
483     else
484         accum->updates = CryptMemAlloc(sizeof(CRYPT_DATA_BLOB));
485     if (accum->updates)
486     {
487         CRYPT_DATA_BLOB *blob = &accum->updates[accum->cUpdates];
488
489         blob->pbData = CryptMemAlloc(cb);
490         if (blob->pbData)
491         {
492             memcpy(blob->pbData, pb, cb);
493             blob->cbData = cb;
494             ret = TRUE;
495         }
496         accum->cUpdates++;
497     }
498     return ret;
499 }
500
501 /* The updates of a (bogus) definite-length encoded message */
502 static BYTE u1[] = { 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
503  0x07,0x01,0xa0,0x02,0x04,0x00 };
504 static BYTE u2[] = { 0x01,0x02,0x03,0x04 };
505 static CRYPT_DATA_BLOB b1[] = {
506     { sizeof(u1), u1 },
507     { sizeof(u2), u2 },
508     { sizeof(u2), u2 },
509 };
510 static const struct update_accum a1 = { sizeof(b1) / sizeof(b1[0]), b1 };
511 /* The updates of a definite-length encoded message */
512 static BYTE u3[] = { 0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
513  0x07,0x01,0xa0,0x06,0x04,0x04 };
514 static CRYPT_DATA_BLOB b2[] = {
515     { sizeof(u3), u3 },
516     { sizeof(u2), u2 },
517 };
518 static const struct update_accum a2 = { sizeof(b2) / sizeof(b2[0]), b2 };
519 /* The updates of an indefinite-length encoded message */
520 static BYTE u4[] = { 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
521  0x07,0x01,0xa0,0x80,0x24,0x80 };
522 static BYTE u5[] = { 0x04,0x04 };
523 static BYTE u6[] = { 0x00,0x00,0x00,0x00,0x00,0x00 };
524 static CRYPT_DATA_BLOB b3[] = {
525     { sizeof(u4), u4 },
526     { sizeof(u5), u5 },
527     { sizeof(u2), u2 },
528     { sizeof(u5), u5 },
529     { sizeof(u2), u2 },
530     { sizeof(u6), u6 },
531 };
532 static const struct update_accum a3 = { sizeof(b3) / sizeof(b3[0]), b3 };
533
534 static void check_updates(LPCSTR header, const struct update_accum *expected,
535  const struct update_accum *got)
536 {
537     DWORD i;
538
539     ok(expected->cUpdates == got->cUpdates,
540      "%s: expected %d updates, got %d\n", header, expected->cUpdates,
541      got->cUpdates);
542     if (expected->cUpdates == got->cUpdates)
543         for (i = 0; i < min(expected->cUpdates, got->cUpdates); i++)
544         {
545             ok(expected->updates[i].cbData == got->updates[i].cbData,
546              "%s, update %d: expected %d bytes, got %d\n", header, i,
547              expected->updates[i].cbData, got->updates[i].cbData);
548             if (expected->updates[i].cbData && expected->updates[i].cbData ==
549              got->updates[i].cbData)
550                 ok(!memcmp(expected->updates[i].pbData, got->updates[i].pbData,
551                  got->updates[i].cbData), "%s, update %d: unexpected value\n",
552                  header, i);
553         }
554 }
555
556 /* Frees the updates stored in accum */
557 static void free_updates(struct update_accum *accum)
558 {
559     DWORD i;
560
561     for (i = 0; i < accum->cUpdates; i++)
562         CryptMemFree(accum->updates[i].pbData);
563     CryptMemFree(accum->updates);
564     accum->updates = NULL;
565     accum->cUpdates = 0;
566 }
567
568 static void test_data_msg_encoding(void)
569 {
570     HCRYPTMSG msg;
571     BOOL ret;
572     static char oid[] = "1.2.3";
573     struct update_accum accum = { 0, NULL };
574     CMSG_STREAM_INFO streamInfo = { 0, accumulating_stream_output, &accum };
575
576     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
577      NULL);
578     check_param("data empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
579      dataEmptyBareContent, sizeof(dataEmptyBareContent));
580     check_param("data empty content", msg, CMSG_CONTENT_PARAM, dataEmptyContent,
581      sizeof(dataEmptyContent));
582     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
583     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
584     check_param("data bare content", msg, CMSG_BARE_CONTENT_PARAM,
585      dataBareContent, sizeof(dataBareContent));
586     check_param("data content", msg, CMSG_CONTENT_PARAM, dataContent,
587      sizeof(dataContent));
588     CryptMsgClose(msg);
589     /* Same test, but with CMSG_BARE_CONTENT_FLAG set */
590     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_BARE_CONTENT_FLAG,
591      CMSG_DATA, NULL, NULL, NULL);
592     check_param("data empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
593      dataEmptyBareContent, sizeof(dataEmptyBareContent));
594     check_param("data empty content", msg, CMSG_CONTENT_PARAM, dataEmptyContent,
595      sizeof(dataEmptyContent));
596     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
597     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
598     check_param("data bare content", msg, CMSG_BARE_CONTENT_PARAM,
599      dataBareContent, sizeof(dataBareContent));
600     check_param("data content", msg, CMSG_CONTENT_PARAM, dataContent,
601      sizeof(dataContent));
602     CryptMsgClose(msg);
603     /* The inner OID is apparently ignored */
604     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, oid,
605      NULL);
606     check_param("data bogus oid bare content", msg, CMSG_BARE_CONTENT_PARAM,
607      dataEmptyBareContent, sizeof(dataEmptyBareContent));
608     check_param("data bogus oid content", msg, CMSG_CONTENT_PARAM,
609      dataEmptyContent, sizeof(dataEmptyContent));
610     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
611     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
612     check_param("data bare content", msg, CMSG_BARE_CONTENT_PARAM,
613      dataBareContent, sizeof(dataBareContent));
614     check_param("data content", msg, CMSG_CONTENT_PARAM, dataContent,
615      sizeof(dataContent));
616     CryptMsgClose(msg);
617     /* A streaming message is DER encoded if the length is not 0xffffffff, but
618      * curiously, updates aren't validated to make sure they don't exceed the
619      * stated length.  (The resulting output will of course fail to decode.)
620      */
621     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
622      NULL, &streamInfo);
623     CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
624     CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
625     CryptMsgClose(msg);
626     check_updates("bogus data message with definite length", &a1, &accum);
627     free_updates(&accum);
628     /* A valid definite-length encoding: */
629     streamInfo.cbContent = sizeof(msgData);
630     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
631      NULL, &streamInfo);
632     CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
633     CryptMsgClose(msg);
634     check_updates("data message with definite length", &a2, &accum);
635     free_updates(&accum);
636     /* An indefinite-length encoding: */
637     streamInfo.cbContent = 0xffffffff;
638     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
639      NULL, &streamInfo);
640     CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
641     CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
642     CryptMsgClose(msg);
643     todo_wine
644     check_updates("data message with indefinite length", &a3, &accum);
645     free_updates(&accum);
646 }
647
648 static void test_data_msg(void)
649 {
650     test_data_msg_open();
651     test_data_msg_update();
652     test_data_msg_get_param();
653     test_data_msg_encoding();
654 }
655
656 static void test_hash_msg_open(void)
657 {
658     HCRYPTMSG msg;
659     CMSG_HASHED_ENCODE_INFO hashInfo = { 0 };
660     static char oid_rsa_md5[] = szOID_RSA_MD5;
661     CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
662
663     SetLastError(0xdeadbeef);
664     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
665      NULL, NULL);
666     ok(!msg && GetLastError() == E_INVALIDARG,
667      "Expected E_INVALIDARG, got %x\n", GetLastError());
668     hashInfo.cbSize = sizeof(hashInfo);
669     SetLastError(0xdeadbeef);
670     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
671      NULL, NULL);
672     ok(!msg && GetLastError() == CRYPT_E_UNKNOWN_ALGO,
673      "Expected CRYPT_E_UNKNOWN_ALGO, got %x\n", GetLastError());
674     hashInfo.HashAlgorithm.pszObjId = oid_rsa_md5;
675     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
676      NULL, NULL);
677     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
678     CryptMsgClose(msg);
679     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
680      CMSG_HASHED, &hashInfo, NULL, NULL);
681     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
682     CryptMsgClose(msg);
683     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
684      CMSG_HASHED, &hashInfo, NULL, &streamInfo);
685     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
686     CryptMsgClose(msg);
687 }
688
689 static void test_hash_msg_update(void)
690 {
691     HCRYPTMSG msg;
692     BOOL ret;
693     static char oid_rsa_md5[] = szOID_RSA_MD5;
694     CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0,
695      { oid_rsa_md5, { 0, NULL } }, NULL };
696     CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
697
698     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
699      CMSG_HASHED, &hashInfo, NULL, NULL);
700     /* Detached hashed messages opened in non-streaming mode allow non-final
701      * updates..
702      */
703     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
704     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
705     /* including non-final updates with no data.. */
706     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
707     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
708     /* and final updates with no data. */
709     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
710     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
711     /* But no updates are allowed after the final update. */
712     SetLastError(0xdeadbeef);
713     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
714     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
715      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
716     SetLastError(0xdeadbeef);
717     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
718     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
719      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
720     CryptMsgClose(msg);
721     /* Non-detached messages, in contrast, don't allow non-final updates in
722      * non-streaming mode.
723      */
724     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
725      NULL, NULL);
726     SetLastError(0xdeadbeef);
727     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
728     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
729      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
730     /* Final updates (including empty ones) are allowed. */
731     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
732     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
733     CryptMsgClose(msg);
734     /* And, of course, streaming mode allows non-final updates */
735     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
736      NULL, &streamInfo);
737     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
738     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
739     CryptMsgClose(msg);
740     /* Setting pfnStreamOutput to NULL results in no error.  (In what appears
741      * to be a bug, it isn't actually used - see encoding tests.)
742      */
743     streamInfo.pfnStreamOutput = NULL;
744     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
745      NULL, &streamInfo);
746     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
747     ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
748     CryptMsgClose(msg);
749 }
750
751 static const BYTE emptyHashParam[] = {
752 0xd4,0x1d,0x8c,0xd9,0x8f,0x00,0xb2,0x04,0xe9,0x80,0x09,0x98,0xec,0xf8,0x42,
753 0x7e };
754
755 static void test_hash_msg_get_param(void)
756 {
757     HCRYPTMSG msg;
758     BOOL ret;
759     static char oid_rsa_md5[] = szOID_RSA_MD5;
760     CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0,
761      { oid_rsa_md5, { 0, NULL } }, NULL };
762     DWORD size, value;
763     CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
764     BYTE buf[16];
765
766     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
767      NULL, NULL);
768     /* Content and bare content are always gettable for non-streamed messages */
769     size = 0;
770     ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
771     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
772     size = 0;
773     ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
774     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
775     /* The hash is also available. */
776     size = 0;
777     ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
778     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
779     ok(size == sizeof(buf), "Unexpected size %d\n", size);
780     ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, buf, &size);
781     if (size == sizeof(buf))
782         ok(!memcmp(buf, emptyHashParam, size), "Unexpected value\n");
783     /* By getting the hash, further updates are not allowed */
784     SetLastError(0xdeadbeef);
785     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
786     ok(!ret && GetLastError() == NTE_BAD_HASH_STATE,
787      "Expected NTE_BAD_HASH_STATE, got %x\n", GetLastError());
788     /* The version is also available, and should be zero for this message. */
789     size = 0;
790     ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, NULL, &size);
791     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
792     size = sizeof(value);
793     ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, (LPBYTE)&value, &size);
794     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
795     ok(value == 0, "Expected version 0, got %d\n", value);
796     /* As usual, the type isn't available. */
797     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
798     ok(!ret, "Expected failure\n");
799     CryptMsgClose(msg);
800
801     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
802      NULL, &streamInfo);
803     /* Streamed messages don't allow you to get the content or bare content. */
804     SetLastError(0xdeadbeef);
805     ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
806     ok(!ret && GetLastError() == E_INVALIDARG,
807      "Expected E_INVALIDARG, got %x\n", GetLastError());
808     SetLastError(0xdeadbeef);
809     ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
810     ok(!ret && GetLastError() == E_INVALIDARG,
811      "Expected E_INVALIDARG, got %x\n", GetLastError());
812     /* The hash is still available. */
813     size = 0;
814     ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
815     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
816     ok(size == sizeof(buf), "Unexpected size %d\n", size);
817     ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, buf, &size);
818     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
819     if (size == sizeof(buf))
820         ok(!memcmp(buf, emptyHashParam, size), "Unexpected value\n");
821     /* After updating the hash, further updates aren't allowed on streamed
822      * messages either.
823      */
824     SetLastError(0xdeadbeef);
825     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
826     ok(!ret && GetLastError() == NTE_BAD_HASH_STATE,
827      "Expected NTE_BAD_HASH_STATE, got %x\n", GetLastError());
828     CryptMsgClose(msg);
829 }
830
831 static const BYTE hashEmptyBareContent[] = {
832 0x30,0x17,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
833 0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x04,0x00 };
834 static const BYTE hashEmptyContent[] = {
835 0x30,0x26,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x19,
836 0x30,0x17,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
837 0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x04,0x00 };
838 static const BYTE hashBareContent[] = {
839 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
840 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
841 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
842 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
843 static const BYTE hashContent[] = {
844 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
845 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
846 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
847 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
848 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
849
850 static const BYTE detachedHashNonFinalBareContent[] = {
851 0x30,0x20,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
852 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
853 0x07,0x01,0x04,0x00 };
854 static const BYTE detachedHashNonFinalContent[] = {
855 0x30,0x2f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x22,
856 0x30,0x20,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
857 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
858 0x07,0x01,0x04,0x00 };
859 static const BYTE detachedHashBareContent[] = {
860 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
861 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
862 0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
863 0x9d,0x2a,0x8f,0x26,0x2f };
864 static const BYTE detachedHashContent[] = {
865 0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
866 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
867 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
868 0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
869 0x9d,0x2a,0x8f,0x26,0x2f };
870
871 static void test_hash_msg_encoding(void)
872 {
873     HCRYPTMSG msg;
874     CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0 };
875     BOOL ret;
876     struct update_accum accum = { 0, NULL }, empty_accum = { 0, NULL };
877     CMSG_STREAM_INFO streamInfo = { 0, accumulating_stream_output, &accum };
878     static char oid_rsa_md5[] = szOID_RSA_MD5;
879
880     hashInfo.HashAlgorithm.pszObjId = oid_rsa_md5;
881     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
882      NULL, NULL);
883     check_param("hash empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
884      hashEmptyBareContent, sizeof(hashEmptyBareContent));
885     check_param("hash empty content", msg, CMSG_CONTENT_PARAM,
886      hashEmptyContent, sizeof(hashEmptyContent));
887     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
888     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
889     check_param("hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
890      hashBareContent, sizeof(hashBareContent));
891     check_param("hash content", msg, CMSG_CONTENT_PARAM,
892      hashContent, sizeof(hashContent));
893     CryptMsgClose(msg);
894     /* Same test, but with CMSG_BARE_CONTENT_FLAG set */
895     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_BARE_CONTENT_FLAG,
896      CMSG_HASHED, &hashInfo, NULL, NULL);
897     check_param("hash empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
898      hashEmptyBareContent, sizeof(hashEmptyBareContent));
899     check_param("hash empty content", msg, CMSG_CONTENT_PARAM,
900      hashEmptyContent, sizeof(hashEmptyContent));
901     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
902     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
903     check_param("hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
904      hashBareContent, sizeof(hashBareContent));
905     check_param("hash content", msg, CMSG_CONTENT_PARAM,
906      hashContent, sizeof(hashContent));
907     CryptMsgClose(msg);
908     /* Same test, but with CMSG_DETACHED_FLAG set */
909     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
910      CMSG_HASHED, &hashInfo, NULL, NULL);
911     check_param("detached hash empty bare content", msg,
912      CMSG_BARE_CONTENT_PARAM, hashEmptyBareContent,
913      sizeof(hashEmptyBareContent));
914     check_param("detached hash empty content", msg, CMSG_CONTENT_PARAM,
915      hashEmptyContent, sizeof(hashEmptyContent));
916     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
917     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
918     check_param("detached hash not final bare content", msg,
919      CMSG_BARE_CONTENT_PARAM, detachedHashNonFinalBareContent,
920      sizeof(detachedHashNonFinalBareContent));
921     check_param("detached hash not final content", msg, CMSG_CONTENT_PARAM,
922      detachedHashNonFinalContent, sizeof(detachedHashNonFinalContent));
923     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
924     ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
925     check_param("detached hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
926      detachedHashBareContent, sizeof(detachedHashBareContent));
927     check_param("detached hash content", msg, CMSG_CONTENT_PARAM,
928      detachedHashContent, sizeof(detachedHashContent));
929     check_param("detached hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
930      detachedHashBareContent, sizeof(detachedHashBareContent));
931     check_param("detached hash content", msg, CMSG_CONTENT_PARAM,
932      detachedHashContent, sizeof(detachedHashContent));
933     CryptMsgClose(msg);
934     /* In what appears to be a bug, streamed updates to hash messages don't
935      * call the output function.
936      */
937     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
938      NULL, &streamInfo);
939     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
940     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
941     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
942     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
943     CryptMsgClose(msg);
944     check_updates("empty hash message", &empty_accum, &accum);
945     free_updates(&accum);
946
947     streamInfo.cbContent = sizeof(msgData);
948     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
949      NULL, &streamInfo);
950     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
951     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
952     CryptMsgClose(msg);
953     check_updates("hash message", &empty_accum, &accum);
954     free_updates(&accum);
955
956     streamInfo.cbContent = sizeof(msgData);
957     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
958      CMSG_HASHED, &hashInfo, NULL, &streamInfo);
959     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
960     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
961     CryptMsgClose(msg);
962     check_updates("detached hash message", &empty_accum, &accum);
963     free_updates(&accum);
964 }
965
966 static void test_hash_msg(void)
967 {
968     test_hash_msg_open();
969     test_hash_msg_update();
970     test_hash_msg_get_param();
971     test_hash_msg_encoding();
972 }
973
974 static const WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e',
975  'm','p',0 };
976 static BYTE serialNum[] = { 1 };
977 static BYTE encodedCommonName[] = { 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,
978  0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
979
980 static void test_signed_msg_open(void)
981 {
982     HCRYPTMSG msg;
983     BOOL ret;
984     CMSG_SIGNED_ENCODE_INFO signInfo = { 0 };
985     CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
986     CERT_INFO certInfo = { 0 };
987     static char oid_rsa_md5[] = szOID_RSA_MD5;
988
989     SetLastError(0xdeadbeef);
990     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
991      NULL, NULL);
992     ok(!msg && GetLastError() == E_INVALIDARG,
993      "Expected E_INVALIDARG, got %x\n", GetLastError());
994     signInfo.cbSize = sizeof(signInfo);
995     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
996      NULL, NULL);
997     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
998     CryptMsgClose(msg);
999
1000     signInfo.cSigners = 1;
1001     signInfo.rgSigners = &signer;
1002     /* With signer.pCertInfo unset, attempting to open this message this
1003      * crashes.
1004      */
1005     signer.pCertInfo = &certInfo;
1006     /* The cert info must contain a serial number and an issuer. */
1007     SetLastError(0xdeadbeef);
1008     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1009      NULL, NULL);
1010     ok(!msg && GetLastError() == E_INVALIDARG,
1011      "Expected E_INVALIDARG, got %x\n", GetLastError());
1012     certInfo.SerialNumber.cbData = sizeof(serialNum);
1013     certInfo.SerialNumber.pbData = serialNum;
1014     SetLastError(0xdeadbeef);
1015     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1016      NULL, NULL);
1017     ok(!msg && GetLastError() == E_INVALIDARG,
1018      "Expected E_INVALIDARG, got %x\n", GetLastError());
1019     certInfo.Issuer.cbData = sizeof(encodedCommonName);
1020     certInfo.Issuer.pbData = encodedCommonName;
1021     SetLastError(0xdeadbeef);
1022     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1023      NULL, NULL);
1024     ok(!msg && GetLastError() == E_INVALIDARG,
1025      "Expected E_INVALIDARG, got %x\n", GetLastError());
1026
1027     /* The signer's hCryptProv must be set to something.  Whether it's usable
1028      * or not will be checked after the hash algorithm is checked (see next
1029      * test.)
1030      */
1031     signer.hCryptProv = 1;
1032     SetLastError(0xdeadbeef);
1033     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1034      NULL, NULL);
1035     ok(!msg && GetLastError() == CRYPT_E_UNKNOWN_ALGO,
1036      "Expected CRYPT_E_UNKNOWN_ALGO, got %x\n", GetLastError());
1037     /* The signer's hash algorithm must also be set. */
1038     signer.HashAlgorithm.pszObjId = oid_rsa_md5;
1039     SetLastError(0xdeadbeef);
1040     /* Crashes in advapi32 in wine, don't do it */
1041     if (0) {
1042         msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED,
1043          &signInfo, NULL, NULL);
1044         ok(!msg && GetLastError() == ERROR_INVALID_PARAMETER,
1045          "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1046     }
1047     /* The signer's hCryptProv must also be valid. */
1048     ret = CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1049      PROV_RSA_FULL, CRYPT_NEWKEYSET);
1050     if (!ret && GetLastError() == NTE_EXISTS)
1051         ret = CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1052          PROV_RSA_FULL, 0);
1053     ok(ret, "CryptAcquireContextW failed: %x\n", GetLastError());
1054     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1055      NULL, NULL);
1056     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1057     CryptMsgClose(msg);
1058
1059     CryptReleaseContext(signer.hCryptProv, 0);
1060     CryptAcquireContextW(&signer.hCryptProv, cspNameW, MS_DEF_PROV_W,
1061      PROV_RSA_FULL, CRYPT_DELETEKEYSET);
1062 }
1063
1064 static const BYTE privKey[] = {
1065  0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
1066  0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
1067  0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
1068  0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
1069  0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
1070  0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
1071  0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
1072  0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
1073  0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
1074  0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
1075  0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
1076  0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
1077  0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
1078  0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
1079  0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
1080  0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
1081  0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
1082  0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
1083  0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
1084  0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
1085  0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
1086  0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
1087  0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
1088  0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
1089
1090 static void test_signed_msg_update(void)
1091 {
1092     HCRYPTMSG msg;
1093     BOOL ret;
1094     CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
1095     CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
1096     CERT_INFO certInfo = { 0 };
1097     HCRYPTKEY key;
1098     char oid_rsa_md5[] = szOID_RSA_MD5;
1099
1100     certInfo.SerialNumber.cbData = sizeof(serialNum);
1101     certInfo.SerialNumber.pbData = serialNum;
1102     certInfo.Issuer.cbData = sizeof(encodedCommonName);
1103     certInfo.Issuer.pbData = encodedCommonName;
1104     signer.pCertInfo = &certInfo;
1105     signer.HashAlgorithm.pszObjId = oid_rsa_md5;
1106     signInfo.cSigners = 1;
1107     signInfo.rgSigners = &signer;
1108     ret = CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1109      PROV_RSA_FULL, CRYPT_NEWKEYSET);
1110     if (!ret && GetLastError() == NTE_EXISTS)
1111         ret = CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1112          PROV_RSA_FULL, 0);
1113     ok(ret, "CryptAcquireContextW failed: %x\n", GetLastError());
1114     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING,
1115      CMSG_DETACHED_FLAG, CMSG_SIGNED, &signInfo, NULL, NULL);
1116     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1117     /* CMSG_SIGNED allows non-final updates. */
1118     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1119     todo_wine
1120     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1121     /* CMSG_SIGNED also allows non-final updates with no data. */
1122     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1123     todo_wine
1124     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1125     /* The final update requires a private key in the hCryptProv, in order to
1126      * generate the signature.
1127      */
1128     SetLastError(0xdeadbeef);
1129     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1130     todo_wine
1131     ok(!ret && GetLastError() == NTE_BAD_KEYSET,
1132      "Expected NTE_BAD_KEYSET, got %x\n", GetLastError());
1133     ret = CryptImportKey(signer.hCryptProv, (LPBYTE)privKey, sizeof(privKey),
1134      0, 0, &key);
1135     ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
1136     /* The final update should be able to succeed now that a key exists, but
1137      * the previous (invalid) final update prevents it.
1138      */
1139     SetLastError(0xdeadbeef);
1140     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1141     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1142      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1143     CryptMsgClose(msg);
1144
1145     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING,
1146      CMSG_DETACHED_FLAG, CMSG_SIGNED, &signInfo, NULL, NULL);
1147     ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1148     /* CMSG_SIGNED allows non-final updates. */
1149     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1150     todo_wine
1151     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1152     /* CMSG_SIGNED also allows non-final updates with no data. */
1153     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1154     todo_wine
1155     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1156     /* Now that the private key exists, the final update can succeed (even
1157      * with no data.)
1158      */
1159     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1160     todo_wine
1161     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1162     /* But no updates are allowed after the final update. */
1163     SetLastError(0xdeadbeef);
1164     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1165     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1166      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1167     SetLastError(0xdeadbeef);
1168     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1169     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1170      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1171     CryptMsgClose(msg);
1172
1173     CryptDestroyKey(key);
1174     CryptReleaseContext(signer.hCryptProv, 0);
1175     CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL, PROV_RSA_FULL,
1176      CRYPT_DELETEKEYSET);
1177 }
1178
1179 static void test_signed_msg(void)
1180 {
1181     test_signed_msg_open();
1182     test_signed_msg_update();
1183 }
1184
1185 static CRYPT_DATA_BLOB b4 = { 0, NULL };
1186 static const struct update_accum a4 = { 1, &b4 };
1187
1188 static const BYTE bogusOIDContent[] = {
1189 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x07,0xa0,0x02,
1190 0x04,0x00 };
1191 static const BYTE bogusHashContent[] = {
1192 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
1193 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1194 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1195 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x00,0xd6,0xc0,
1196 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1197
1198 static void test_decode_msg_update(void)
1199 {
1200     HCRYPTMSG msg;
1201     BOOL ret;
1202     CMSG_STREAM_INFO streamInfo = { 0 };
1203     DWORD i;
1204     struct update_accum accum = { 0, NULL };
1205
1206     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1207     /* Update with a full message in a final update */
1208     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
1209     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1210     /* Can't update after a final update */
1211     SetLastError(0xdeadbeef);
1212     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
1213     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1214      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1215     CryptMsgClose(msg);
1216
1217     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1218     /* Can't send a non-final update without streaming */
1219     SetLastError(0xdeadbeef);
1220     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1221      FALSE);
1222     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1223      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1224     /* A subsequent final update succeeds */
1225     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
1226     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1227     CryptMsgClose(msg);
1228
1229     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1230     /* Updating a message that has a NULL stream callback fails */
1231     SetLastError(0xdeadbeef);
1232     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1233      FALSE);
1234     todo_wine
1235     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1236      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
1237     /* Changing the callback pointer after the fact yields the same error (so
1238      * the message must copy the stream info, not just store a pointer to it)
1239      */
1240     streamInfo.pfnStreamOutput = nop_stream_output;
1241     SetLastError(0xdeadbeef);
1242     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1243      FALSE);
1244     todo_wine
1245     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1246      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
1247     CryptMsgClose(msg);
1248
1249     /* Empty non-final updates are allowed when streaming.. */
1250     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1251     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1252     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1253     /* but final updates aren't when not enough data has been received. */
1254     SetLastError(0xdeadbeef);
1255     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1256     todo_wine
1257     ok(!ret && GetLastError() == CRYPT_E_STREAM_INSUFFICIENT_DATA,
1258      "Expected CRYPT_E_STREAM_INSUFFICIENT_DATA, got %x\n", GetLastError());
1259     CryptMsgClose(msg);
1260
1261     /* Updating the message byte by byte is legal */
1262     streamInfo.pfnStreamOutput = accumulating_stream_output;
1263     streamInfo.pvArg = &accum;
1264     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1265     for (i = 0, ret = TRUE; ret && i < sizeof(dataEmptyContent); i++)
1266         ret = CryptMsgUpdate(msg, &dataEmptyContent[i], 1, FALSE);
1267     ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
1268     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1269     ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
1270     CryptMsgClose(msg);
1271     todo_wine
1272     check_updates("byte-by-byte empty content", &a4, &accum);
1273     free_updates(&accum);
1274
1275     /* Decoding bogus content fails in non-streaming mode.. */
1276     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1277     SetLastError(0xdeadbeef);
1278     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1279     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1280      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1281     CryptMsgClose(msg);
1282     /* and as the final update in streaming mode.. */
1283     streamInfo.pfnStreamOutput = nop_stream_output;
1284     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1285     SetLastError(0xdeadbeef);
1286     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1287     todo_wine
1288     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1289      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1290     CryptMsgClose(msg);
1291     /* and even as a non-final update in streaming mode. */
1292     streamInfo.pfnStreamOutput = nop_stream_output;
1293     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1294     SetLastError(0xdeadbeef);
1295     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1296     todo_wine
1297     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1298      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1299     CryptMsgClose(msg);
1300
1301     /* An empty message can be opened with indetermined type.. */
1302     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1303     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1304      TRUE);
1305     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1306     /* but decoding it as an explicitly typed message fails. */
1307     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
1308      NULL);
1309     SetLastError(0xdeadbeef);
1310     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1311      TRUE);
1312     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1313      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1314     CryptMsgClose(msg);
1315     /* On the other hand, decoding the bare content of an empty message fails
1316      * with unspecified type..
1317      */
1318     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1319     SetLastError(0xdeadbeef);
1320     ret = CryptMsgUpdate(msg, dataEmptyBareContent,
1321      sizeof(dataEmptyBareContent), TRUE);
1322     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1323      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1324     CryptMsgClose(msg);
1325     /* but succeeds with explicit type. */
1326     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
1327      NULL);
1328     ret = CryptMsgUpdate(msg, dataEmptyBareContent,
1329      sizeof(dataEmptyBareContent), TRUE);
1330     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1331     CryptMsgClose(msg);
1332
1333     /* Decoding valid content with an unsupported OID fails */
1334     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1335     SetLastError(0xdeadbeef);
1336     ret = CryptMsgUpdate(msg, bogusOIDContent, sizeof(bogusOIDContent), TRUE);
1337     ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1338      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1339     CryptMsgClose(msg);
1340
1341     /* Similarly, opening an empty hash with unspecified type succeeds.. */
1342     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1343     SetLastError(0xdeadbeef);
1344     ret = CryptMsgUpdate(msg, hashEmptyContent, sizeof(hashEmptyContent), TRUE);
1345     ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1346     CryptMsgClose(msg);
1347     /* while with specified type it fails. */
1348     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1349      NULL);
1350     SetLastError(0xdeadbeef);
1351     ret = CryptMsgUpdate(msg, hashEmptyContent, sizeof(hashEmptyContent), TRUE);
1352     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1353      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1354     CryptMsgClose(msg);
1355     /* On the other hand, decoding the bare content of an empty hash message
1356      * fails with unspecified type..
1357      */
1358     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1359     SetLastError(0xdeadbeef);
1360     ret = CryptMsgUpdate(msg, hashEmptyBareContent,
1361      sizeof(hashEmptyBareContent), TRUE);
1362     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1363      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1364     CryptMsgClose(msg);
1365     /* but succeeds with explicit type. */
1366     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1367      NULL);
1368     ret = CryptMsgUpdate(msg, hashEmptyBareContent,
1369      sizeof(hashEmptyBareContent), TRUE);
1370     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1371     CryptMsgClose(msg);
1372
1373     /* And again, opening a (non-empty) hash message with unspecified type
1374      * succeeds..
1375      */
1376     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1377     SetLastError(0xdeadbeef);
1378     ret = CryptMsgUpdate(msg, hashContent, sizeof(hashContent), TRUE);
1379     ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1380     CryptMsgClose(msg);
1381     /* while with specified type it fails.. */
1382     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1383      NULL);
1384     SetLastError(0xdeadbeef);
1385     ret = CryptMsgUpdate(msg, hashContent, sizeof(hashContent), TRUE);
1386     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1387      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1388     CryptMsgClose(msg);
1389     /* and decoding the bare content of a non-empty hash message fails with
1390      * unspecified type..
1391      */
1392     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1393     SetLastError(0xdeadbeef);
1394     ret = CryptMsgUpdate(msg, hashBareContent, sizeof(hashBareContent), TRUE);
1395     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1396      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1397     CryptMsgClose(msg);
1398     /* but succeeds with explicit type. */
1399     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1400      NULL);
1401     ret = CryptMsgUpdate(msg, hashBareContent, sizeof(hashBareContent), TRUE);
1402     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1403     CryptMsgClose(msg);
1404
1405     /* Opening a (non-empty) hash message with unspecified type and a bogus
1406      * hash value succeeds..
1407      */
1408     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1409     SetLastError(0xdeadbeef);
1410     ret = CryptMsgUpdate(msg, bogusHashContent, sizeof(bogusHashContent), TRUE);
1411     ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1412     CryptMsgClose(msg);
1413 }
1414
1415 static const BYTE hashParam[] = { 0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,
1416  0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1417
1418 static void test_decode_msg_get_param(void)
1419 {
1420     HCRYPTMSG msg;
1421     BOOL ret;
1422     DWORD size = 0, version;
1423
1424     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1425     SetLastError(0xdeadbeef);
1426     ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
1427     ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1428      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1429     ret = CryptMsgUpdate(msg, dataContent, sizeof(dataContent), TRUE);
1430     check_param("data content", msg, CMSG_CONTENT_PARAM, msgData,
1431      sizeof(msgData));
1432     CryptMsgClose(msg);
1433
1434     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1435     ret = CryptMsgUpdate(msg, hashEmptyContent, sizeof(hashEmptyContent), TRUE);
1436     check_param("empty hash content", msg, CMSG_CONTENT_PARAM, NULL, 0);
1437     check_param("empty hash hash data", msg, CMSG_HASH_DATA_PARAM, NULL, 0);
1438     check_param("empty hash computed hash", msg, CMSG_COMPUTED_HASH_PARAM,
1439      emptyHashParam, sizeof(emptyHashParam));
1440     CryptMsgClose(msg);
1441     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1442     ret = CryptMsgUpdate(msg, hashContent, sizeof(hashContent), TRUE);
1443     check_param("hash content", msg, CMSG_CONTENT_PARAM, msgData,
1444      sizeof(msgData));
1445     check_param("hash hash data", msg, CMSG_HASH_DATA_PARAM, hashParam,
1446      sizeof(hashParam));
1447     check_param("hash computed hash", msg, CMSG_COMPUTED_HASH_PARAM,
1448      hashParam, sizeof(hashParam));
1449     size = strlen(szOID_RSA_data) + 1;
1450     check_param("hash inner OID", msg, CMSG_INNER_CONTENT_TYPE_PARAM,
1451      (const BYTE *)szOID_RSA_data, strlen(szOID_RSA_data) + 1);
1452     version = CMSG_HASHED_DATA_V0;
1453     check_param("hash version", msg, CMSG_VERSION_PARAM, (const BYTE *)&version,
1454      sizeof(version));
1455     CryptMsgClose(msg);
1456 }
1457
1458 static void test_decode_msg(void)
1459 {
1460     test_decode_msg_update();
1461     test_decode_msg_get_param();
1462 }
1463
1464 START_TEST(msg)
1465 {
1466     /* Basic parameter checking tests */
1467     test_msg_open_to_encode();
1468     test_msg_open_to_decode();
1469     test_msg_get_param();
1470     test_msg_close();
1471
1472     /* Message-type specific tests */
1473     test_data_msg();
1474     test_hash_msg();
1475     test_signed_msg();
1476     test_decode_msg();
1477 }