crypt32: Introduce function to encode an array of items as a set.
[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 void test_signed_msg(void)
1065 {
1066     test_signed_msg_open();
1067 }
1068
1069 static CRYPT_DATA_BLOB b4 = { 0, NULL };
1070 static const struct update_accum a4 = { 1, &b4 };
1071
1072 static const BYTE bogusOIDContent[] = {
1073 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x07,0xa0,0x02,
1074 0x04,0x00 };
1075 static const BYTE bogusHashContent[] = {
1076 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
1077 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1078 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1079 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x00,0xd6,0xc0,
1080 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1081
1082 static void test_decode_msg_update(void)
1083 {
1084     HCRYPTMSG msg;
1085     BOOL ret;
1086     CMSG_STREAM_INFO streamInfo = { 0 };
1087     DWORD i;
1088     struct update_accum accum = { 0, NULL };
1089
1090     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1091     /* Update with a full message in a final update */
1092     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
1093     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1094     /* Can't update after a final update */
1095     SetLastError(0xdeadbeef);
1096     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
1097     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1098      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1099     CryptMsgClose(msg);
1100
1101     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1102     /* Can't send a non-final update without streaming */
1103     SetLastError(0xdeadbeef);
1104     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1105      FALSE);
1106     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1107      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1108     /* A subsequent final update succeeds */
1109     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
1110     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1111     CryptMsgClose(msg);
1112
1113     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1114     /* Updating a message that has a NULL stream callback fails */
1115     SetLastError(0xdeadbeef);
1116     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1117      FALSE);
1118     todo_wine
1119     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1120      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
1121     /* Changing the callback pointer after the fact yields the same error (so
1122      * the message must copy the stream info, not just store a pointer to it)
1123      */
1124     streamInfo.pfnStreamOutput = nop_stream_output;
1125     SetLastError(0xdeadbeef);
1126     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1127      FALSE);
1128     todo_wine
1129     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1130      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
1131     CryptMsgClose(msg);
1132
1133     /* Empty non-final updates are allowed when streaming.. */
1134     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1135     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1136     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1137     /* but final updates aren't when not enough data has been received. */
1138     SetLastError(0xdeadbeef);
1139     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1140     todo_wine
1141     ok(!ret && GetLastError() == CRYPT_E_STREAM_INSUFFICIENT_DATA,
1142      "Expected CRYPT_E_STREAM_INSUFFICIENT_DATA, got %x\n", GetLastError());
1143     CryptMsgClose(msg);
1144
1145     /* Updating the message byte by byte is legal */
1146     streamInfo.pfnStreamOutput = accumulating_stream_output;
1147     streamInfo.pvArg = &accum;
1148     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1149     for (i = 0, ret = TRUE; ret && i < sizeof(dataEmptyContent); i++)
1150         ret = CryptMsgUpdate(msg, &dataEmptyContent[i], 1, FALSE);
1151     ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
1152     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1153     ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
1154     CryptMsgClose(msg);
1155     todo_wine
1156     check_updates("byte-by-byte empty content", &a4, &accum);
1157     free_updates(&accum);
1158
1159     /* Decoding bogus content fails in non-streaming mode.. */
1160     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1161     SetLastError(0xdeadbeef);
1162     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1163     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1164      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1165     CryptMsgClose(msg);
1166     /* and as the final update in streaming mode.. */
1167     streamInfo.pfnStreamOutput = nop_stream_output;
1168     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1169     SetLastError(0xdeadbeef);
1170     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1171     todo_wine
1172     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1173      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1174     CryptMsgClose(msg);
1175     /* and even as a non-final update in streaming mode. */
1176     streamInfo.pfnStreamOutput = nop_stream_output;
1177     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1178     SetLastError(0xdeadbeef);
1179     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1180     todo_wine
1181     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1182      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1183     CryptMsgClose(msg);
1184
1185     /* An empty message can be opened with indetermined type.. */
1186     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1187     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1188      TRUE);
1189     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1190     /* but decoding it as an explicitly typed message fails. */
1191     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
1192      NULL);
1193     SetLastError(0xdeadbeef);
1194     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1195      TRUE);
1196     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1197      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1198     CryptMsgClose(msg);
1199     /* On the other hand, decoding the bare content of an empty message fails
1200      * with unspecified type..
1201      */
1202     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1203     SetLastError(0xdeadbeef);
1204     ret = CryptMsgUpdate(msg, dataEmptyBareContent,
1205      sizeof(dataEmptyBareContent), TRUE);
1206     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1207      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1208     CryptMsgClose(msg);
1209     /* but succeeds with explicit type. */
1210     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
1211      NULL);
1212     ret = CryptMsgUpdate(msg, dataEmptyBareContent,
1213      sizeof(dataEmptyBareContent), TRUE);
1214     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1215     CryptMsgClose(msg);
1216
1217     /* Decoding valid content with an unsupported OID fails */
1218     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1219     SetLastError(0xdeadbeef);
1220     ret = CryptMsgUpdate(msg, bogusOIDContent, sizeof(bogusOIDContent), TRUE);
1221     ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1222      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1223     CryptMsgClose(msg);
1224
1225     /* Similarly, opening an empty hash with unspecified type succeeds.. */
1226     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1227     SetLastError(0xdeadbeef);
1228     ret = CryptMsgUpdate(msg, hashEmptyContent, sizeof(hashEmptyContent), TRUE);
1229     ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1230     CryptMsgClose(msg);
1231     /* while with specified type it fails. */
1232     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1233      NULL);
1234     SetLastError(0xdeadbeef);
1235     ret = CryptMsgUpdate(msg, hashEmptyContent, sizeof(hashEmptyContent), TRUE);
1236     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1237      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1238     CryptMsgClose(msg);
1239     /* On the other hand, decoding the bare content of an empty hash message
1240      * fails with unspecified type..
1241      */
1242     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1243     SetLastError(0xdeadbeef);
1244     ret = CryptMsgUpdate(msg, hashEmptyBareContent,
1245      sizeof(hashEmptyBareContent), TRUE);
1246     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1247      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1248     CryptMsgClose(msg);
1249     /* but succeeds with explicit type. */
1250     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1251      NULL);
1252     ret = CryptMsgUpdate(msg, hashEmptyBareContent,
1253      sizeof(hashEmptyBareContent), TRUE);
1254     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1255     CryptMsgClose(msg);
1256
1257     /* And again, opening a (non-empty) hash message with unspecified type
1258      * succeeds..
1259      */
1260     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1261     SetLastError(0xdeadbeef);
1262     ret = CryptMsgUpdate(msg, hashContent, sizeof(hashContent), TRUE);
1263     ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1264     CryptMsgClose(msg);
1265     /* while with specified type it fails.. */
1266     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1267      NULL);
1268     SetLastError(0xdeadbeef);
1269     ret = CryptMsgUpdate(msg, hashContent, sizeof(hashContent), TRUE);
1270     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1271      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1272     CryptMsgClose(msg);
1273     /* and decoding the bare content of a non-empty hash message fails with
1274      * unspecified type..
1275      */
1276     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1277     SetLastError(0xdeadbeef);
1278     ret = CryptMsgUpdate(msg, hashBareContent, sizeof(hashBareContent), TRUE);
1279     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1280      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1281     CryptMsgClose(msg);
1282     /* but succeeds with explicit type. */
1283     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1284      NULL);
1285     ret = CryptMsgUpdate(msg, hashBareContent, sizeof(hashBareContent), TRUE);
1286     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1287     CryptMsgClose(msg);
1288
1289     /* Opening a (non-empty) hash message with unspecified type and a bogus
1290      * hash value succeeds..
1291      */
1292     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1293     SetLastError(0xdeadbeef);
1294     ret = CryptMsgUpdate(msg, bogusHashContent, sizeof(bogusHashContent), TRUE);
1295     ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1296     CryptMsgClose(msg);
1297 }
1298
1299 static const BYTE hashParam[] = { 0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,
1300  0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1301
1302 static void test_decode_msg_get_param(void)
1303 {
1304     HCRYPTMSG msg;
1305     BOOL ret;
1306     DWORD size = 0, version;
1307
1308     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1309     SetLastError(0xdeadbeef);
1310     ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
1311     ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1312      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1313     ret = CryptMsgUpdate(msg, dataContent, sizeof(dataContent), TRUE);
1314     check_param("data content", msg, CMSG_CONTENT_PARAM, msgData,
1315      sizeof(msgData));
1316     CryptMsgClose(msg);
1317
1318     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1319     ret = CryptMsgUpdate(msg, hashEmptyContent, sizeof(hashEmptyContent), TRUE);
1320     check_param("empty hash content", msg, CMSG_CONTENT_PARAM, NULL, 0);
1321     check_param("empty hash hash data", msg, CMSG_HASH_DATA_PARAM, NULL, 0);
1322     check_param("empty hash computed hash", msg, CMSG_COMPUTED_HASH_PARAM,
1323      emptyHashParam, sizeof(emptyHashParam));
1324     CryptMsgClose(msg);
1325     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1326     ret = CryptMsgUpdate(msg, hashContent, sizeof(hashContent), TRUE);
1327     check_param("hash content", msg, CMSG_CONTENT_PARAM, msgData,
1328      sizeof(msgData));
1329     check_param("hash hash data", msg, CMSG_HASH_DATA_PARAM, hashParam,
1330      sizeof(hashParam));
1331     check_param("hash computed hash", msg, CMSG_COMPUTED_HASH_PARAM,
1332      hashParam, sizeof(hashParam));
1333     size = strlen(szOID_RSA_data) + 1;
1334     check_param("hash inner OID", msg, CMSG_INNER_CONTENT_TYPE_PARAM,
1335      (const BYTE *)szOID_RSA_data, strlen(szOID_RSA_data) + 1);
1336     version = CMSG_HASHED_DATA_V0;
1337     check_param("hash version", msg, CMSG_VERSION_PARAM, (const BYTE *)&version,
1338      sizeof(version));
1339     CryptMsgClose(msg);
1340 }
1341
1342 static void test_decode_msg(void)
1343 {
1344     test_decode_msg_update();
1345     test_decode_msg_get_param();
1346 }
1347
1348 START_TEST(msg)
1349 {
1350     /* Basic parameter checking tests */
1351     test_msg_open_to_encode();
1352     test_msg_open_to_decode();
1353     test_msg_get_param();
1354     test_msg_close();
1355
1356     /* Message-type specific tests */
1357     test_data_msg();
1358     test_hash_msg();
1359     test_signed_msg();
1360     test_decode_msg();
1361 }