crypt32: Add tests for hash message encoding.
[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 = 0;
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)
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     todo_wine {
772     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
773     size = 0;
774     ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
775     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
776     }
777     /* The hash is also available. */
778     size = 0;
779     ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
780     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
781     ok(size == sizeof(buf), "Unexpected size %d\n", size);
782     ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, buf, &size);
783     if (size == sizeof(buf))
784         ok(!memcmp(buf, emptyHashParam, size), "Unexpected value\n");
785     /* By getting the hash, further updates are not allowed */
786     SetLastError(0xdeadbeef);
787     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
788     ok(!ret && GetLastError() == NTE_BAD_HASH_STATE,
789      "Expected NTE_BAD_HASH_STATE, got %x\n", GetLastError());
790     /* The version is also available, and should be zero for this message. */
791     size = 0;
792     ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, NULL, &size);
793     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
794     size = sizeof(value);
795     ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, (LPBYTE)&value, &size);
796     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
797     ok(value == 0, "Expected version 0, got %d\n", value);
798     /* As usual, the type isn't available. */
799     ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
800     todo_wine
801     ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
802      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
803     CryptMsgClose(msg);
804
805     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
806      NULL, &streamInfo);
807     /* Streamed messages don't allow you to get the content or bare content. */
808     SetLastError(0xdeadbeef);
809     ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
810     todo_wine {
811     ok(!ret && GetLastError() == E_INVALIDARG,
812      "Expected E_INVALIDARG, got %x\n", GetLastError());
813     SetLastError(0xdeadbeef);
814     ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
815     ok(!ret && GetLastError() == E_INVALIDARG,
816      "Expected E_INVALIDARG, got %x\n", GetLastError());
817     }
818     /* The hash is still available. */
819     size = 0;
820     ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
821     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
822     ok(size == sizeof(buf), "Unexpected size %d\n", size);
823     ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, buf, &size);
824     ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
825     if (size == sizeof(buf))
826         ok(!memcmp(buf, emptyHashParam, size), "Unexpected value\n");
827     /* After updating the hash, further updates aren't allowed on streamed
828      * messages either.
829      */
830     SetLastError(0xdeadbeef);
831     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
832     ok(!ret && GetLastError() == NTE_BAD_HASH_STATE,
833      "Expected NTE_BAD_HASH_STATE, got %x\n", GetLastError());
834     CryptMsgClose(msg);
835 }
836
837 static const BYTE hashEmptyBareContent[] = {
838 0x30,0x17,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
839 0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x04,0x00 };
840 static const BYTE hashEmptyContent[] = {
841 0x30,0x26,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x19,
842 0x30,0x17,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
843 0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x04,0x00 };
844 static const BYTE hashBareContent[] = {
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 static const BYTE hashContent[] = {
850 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
851 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
852 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
853 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
854 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
855
856 static const BYTE detachedHashBareContent[] = {
857 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
858 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
859 0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
860 0x9d,0x2a,0x8f,0x26,0x2f };
861 static const BYTE detachedHashContent[] = {
862 0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
863 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
864 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
865 0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
866 0x9d,0x2a,0x8f,0x26,0x2f };
867
868 static void test_hash_msg_encoding(void)
869 {
870     HCRYPTMSG msg;
871     CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0 };
872     BOOL ret;
873     struct update_accum accum = { 0, NULL }, empty_accum = { 0, NULL };
874     CMSG_STREAM_INFO streamInfo = { 0, accumulating_stream_output, &accum };
875     static char oid_rsa_md5[] = szOID_RSA_MD5;
876
877     hashInfo.HashAlgorithm.pszObjId = oid_rsa_md5;
878     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
879      NULL, NULL);
880     todo_wine {
881     check_param("hash empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
882      hashEmptyBareContent, sizeof(hashEmptyBareContent));
883     check_param("hash empty content", msg, CMSG_CONTENT_PARAM,
884      hashEmptyContent, sizeof(hashEmptyContent));
885     }
886     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
887     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
888     todo_wine {
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     }
894     CryptMsgClose(msg);
895     /* Same test, but with CMSG_BARE_CONTENT_FLAG set */
896     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_BARE_CONTENT_FLAG,
897      CMSG_HASHED, &hashInfo, NULL, NULL);
898     todo_wine {
899     check_param("hash empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
900      hashEmptyBareContent, sizeof(hashEmptyBareContent));
901     check_param("hash empty content", msg, CMSG_CONTENT_PARAM,
902      hashEmptyContent, sizeof(hashEmptyContent));
903     }
904     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
905     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
906     todo_wine {
907     check_param("hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
908      hashBareContent, sizeof(hashBareContent));
909     check_param("hash content", msg, CMSG_CONTENT_PARAM,
910      hashContent, sizeof(hashContent));
911     }
912     CryptMsgClose(msg);
913     /* Same test, but with CMSG_DETACHED_FLAG set */
914     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
915      CMSG_HASHED, &hashInfo, NULL, NULL);
916     todo_wine {
917     check_param("detached hash empty bare content", msg,
918      CMSG_BARE_CONTENT_PARAM, hashEmptyBareContent,
919      sizeof(hashEmptyBareContent));
920     check_param("detached hash empty content", msg, CMSG_CONTENT_PARAM,
921      hashEmptyContent, sizeof(hashEmptyContent));
922     }
923     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
924     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
925     todo_wine {
926     check_param("detached hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
927      detachedHashBareContent, sizeof(detachedHashBareContent));
928     check_param("detached hash content", msg, CMSG_CONTENT_PARAM,
929      detachedHashContent, sizeof(detachedHashContent));
930     }
931     CryptMsgClose(msg);
932     /* In what appears to be a bug, streamed updates to hash messages don't
933      * call the output function.
934      */
935     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
936      NULL, &streamInfo);
937     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
938     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
939     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
940     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
941     CryptMsgClose(msg);
942     check_updates("empty hash message", &empty_accum, &accum);
943     free_updates(&accum);
944
945     streamInfo.cbContent = sizeof(msgData);
946     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
947      NULL, &streamInfo);
948     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
949     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
950     CryptMsgClose(msg);
951     check_updates("hash message", &empty_accum, &accum);
952     free_updates(&accum);
953
954     streamInfo.cbContent = sizeof(msgData);
955     msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
956      CMSG_HASHED, &hashInfo, NULL, &streamInfo);
957     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
958     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
959     CryptMsgClose(msg);
960     check_updates("detached hash message", &empty_accum, &accum);
961     free_updates(&accum);
962 }
963
964 static void test_hash_msg(void)
965 {
966     test_hash_msg_open();
967     test_hash_msg_update();
968     test_hash_msg_get_param();
969     test_hash_msg_encoding();
970 }
971
972 static CRYPT_DATA_BLOB b4 = { 0, NULL };
973 static const struct update_accum a4 = { 1, &b4 };
974
975 static const BYTE bogusOIDContent[] = {
976 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x07,0xa0,0x02,
977 0x04,0x00 };
978
979 static void test_decode_msg_update(void)
980 {
981     HCRYPTMSG msg;
982     BOOL ret;
983     CMSG_STREAM_INFO streamInfo = { 0 };
984     DWORD i;
985     struct update_accum accum = { 0, NULL };
986
987     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
988     /* Update with a full message in a final update */
989     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
990     todo_wine
991     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
992     /* Can't update after a final update */
993     SetLastError(0xdeadbeef);
994     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
995     todo_wine
996     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
997      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
998     CryptMsgClose(msg);
999
1000     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1001     /* Can't send a non-final update without streaming */
1002     SetLastError(0xdeadbeef);
1003     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1004      FALSE);
1005     todo_wine
1006     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1007      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1008     /* A subsequent final update succeeds */
1009     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
1010     todo_wine
1011     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1012     CryptMsgClose(msg);
1013
1014     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1015     /* Updating a message that has a NULL stream callback fails */
1016     SetLastError(0xdeadbeef);
1017     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1018      FALSE);
1019     todo_wine
1020     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1021      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
1022     /* Changing the callback pointer after the fact yields the same error (so
1023      * the message must copy the stream info, not just store a pointer to it)
1024      */
1025     streamInfo.pfnStreamOutput = nop_stream_output;
1026     SetLastError(0xdeadbeef);
1027     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1028      FALSE);
1029     todo_wine
1030     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1031      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
1032     CryptMsgClose(msg);
1033
1034     /* Empty non-final updates are allowed when streaming.. */
1035     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1036     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1037     todo_wine
1038     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1039     /* but final updates aren't when not enough data has been received. */
1040     SetLastError(0xdeadbeef);
1041     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1042     todo_wine
1043     ok(!ret && GetLastError() == CRYPT_E_STREAM_INSUFFICIENT_DATA,
1044      "Expected CRYPT_E_STREAM_INSUFFICIENT_DATA, got %x\n", GetLastError());
1045     CryptMsgClose(msg);
1046
1047     /* Updating the message byte by byte is legal */
1048     streamInfo.pfnStreamOutput = accumulating_stream_output;
1049     streamInfo.pvArg = &accum;
1050     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1051     for (i = 0, ret = TRUE; ret && i < sizeof(dataEmptyContent); i++)
1052         ret = CryptMsgUpdate(msg, &dataEmptyContent[i], 1, FALSE);
1053     todo_wine {
1054     ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
1055     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1056     ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
1057     }
1058     CryptMsgClose(msg);
1059     todo_wine
1060     check_updates("byte-by-byte empty content", &a4, &accum);
1061     free_updates(&accum);
1062
1063     /* Decoding bogus content fails in non-streaming mode.. */
1064     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1065     SetLastError(0xdeadbeef);
1066     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1067     todo_wine
1068     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1069      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1070     CryptMsgClose(msg);
1071     /* and as the final update in streaming mode.. */
1072     streamInfo.pfnStreamOutput = nop_stream_output;
1073     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1074     SetLastError(0xdeadbeef);
1075     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1076     todo_wine
1077     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1078      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1079     CryptMsgClose(msg);
1080     /* and even as a non-final update in streaming mode. */
1081     streamInfo.pfnStreamOutput = nop_stream_output;
1082     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1083     SetLastError(0xdeadbeef);
1084     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1085     todo_wine
1086     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1087      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1088     CryptMsgClose(msg);
1089
1090     /* An empty message can be opened with indetermined type.. */
1091     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1092     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1093      TRUE);
1094     todo_wine
1095     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1096     /* but decoding it as an explicitly typed message fails. */
1097     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
1098      NULL);
1099     SetLastError(0xdeadbeef);
1100     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1101      TRUE);
1102     todo_wine
1103     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1104      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1105     CryptMsgClose(msg);
1106     /* On the other hand, decoding the bare content of an empty message fails
1107      * with unspecified type..
1108      */
1109     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1110     SetLastError(0xdeadbeef);
1111     ret = CryptMsgUpdate(msg, dataEmptyBareContent,
1112      sizeof(dataEmptyBareContent), TRUE);
1113     todo_wine
1114     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1115      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1116     CryptMsgClose(msg);
1117     /* but succeeds with explicit type. */
1118     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
1119      NULL);
1120     ret = CryptMsgUpdate(msg, dataEmptyBareContent,
1121      sizeof(dataEmptyBareContent), TRUE);
1122     todo_wine
1123     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1124     CryptMsgClose(msg);
1125
1126     /* Decoding valid content with an unsupported OID fails */
1127     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1128     SetLastError(0xdeadbeef);
1129     ret = CryptMsgUpdate(msg, bogusOIDContent, sizeof(bogusOIDContent), TRUE);
1130     todo_wine
1131     ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1132      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1133     CryptMsgClose(msg);
1134 }
1135
1136 static void test_decode_msg(void)
1137 {
1138     test_decode_msg_update();
1139 }
1140
1141 START_TEST(msg)
1142 {
1143     /* Basic parameter checking tests */
1144     test_msg_open_to_encode();
1145     test_msg_open_to_decode();
1146     test_msg_get_param();
1147     test_msg_close();
1148
1149     /* Message-type specific tests */
1150     test_data_msg();
1151     test_hash_msg();
1152     test_decode_msg();
1153 }