crypt32: Add tests for updating hash messages opened to encode.
[wine.git] / dlls / crypt32 / tests / msg.c
blobf5b2fc578fb711d81b6a0494614d61d023aaa365
1 /*
2 * Unit test suite for crypt32.dll's CryptMsg functions
4 * Copyright 2007 Juan Lang
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.
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.
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
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <windef.h>
24 #include <winbase.h>
25 #include <winerror.h>
26 #include <wincrypt.h>
28 #include "wine/test.h"
30 static void test_msg_open_to_encode(void)
32 HCRYPTMSG msg;
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);
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());
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());
75 static void test_msg_open_to_decode(void)
77 HCRYPTMSG msg;
78 CMSG_STREAM_INFO streamInfo = { 0 };
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());
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());
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);
129 /* And even though the stream info parameter "must be set to NULL" for
130 * CMSG_HASHED, it's still accepted.
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);
138 static void test_msg_get_param(void)
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 };
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);
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);
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++)
176 size = 0;
177 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
178 ok(!ret, "Parameter %d: expected failure\n", i);
180 CryptMsgClose(msg);
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++)
191 size = 0;
192 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
193 ok(!ret, "Parameter %d: expected failure\n", i);
195 CryptMsgClose(msg);
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++)
206 size = 0;
207 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
208 ok(!ret, "Parameter %d: expected failure\n", i);
210 CryptMsgClose(msg);
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++)
221 size = 0;
222 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
223 ok(!ret, "Parameter %d: expected failure\n", i);
225 CryptMsgClose(msg);
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);
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);
246 static void test_msg_close(void)
248 BOOL ret;
249 HCRYPTMSG msg;
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());
264 static void check_param(LPCSTR test, HCRYPTMSG msg, DWORD param,
265 const BYTE *expected, DWORD expectedSize)
267 DWORD size;
268 LPBYTE buf;
269 BOOL ret;
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);
284 static void test_data_msg_open(void)
286 HCRYPTMSG msg;
287 CMSG_HASHED_ENCODE_INFO hashInfo = { 0 };
288 CMSG_STREAM_INFO streamInfo = { 0 };
289 char oid[] = "1.2.3";
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);
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);
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.
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);
327 static const BYTE msgData[] = { 1, 2, 3, 4 };
329 static BOOL WINAPI nop_stream_output(const void *pvArg, BYTE *pb, DWORD cb,
330 BOOL final)
332 return TRUE;
335 static void test_data_msg_update(void)
337 HCRYPTMSG msg;
338 BOOL ret;
339 CMSG_STREAM_INFO streamInfo = { 0 };
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);
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.
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);
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);
388 /* Calling update after opening with an empty stream info (with a bogus
389 * output function) yields an error:
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.
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);
411 static void test_data_msg_get_param(void)
413 HCRYPTMSG msg;
414 DWORD size;
415 BOOL ret;
416 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
418 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
419 NULL);
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.
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);
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);
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 };
468 struct update_accum
470 DWORD cUpdates;
471 CRYPT_DATA_BLOB *updates;
474 static BOOL WINAPI accumulating_stream_output(const void *pvArg, BYTE *pb,
475 DWORD cb, BOOL final)
477 struct update_accum *accum = (struct update_accum *)pvArg;
478 BOOL ret = FALSE;
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)
487 CRYPT_DATA_BLOB *blob = &accum->updates[accum->cUpdates];
489 blob->pbData = CryptMemAlloc(cb);
490 if (blob->pbData)
492 memcpy(blob->pbData, pb, cb);
493 blob->cbData = cb;
494 ret = TRUE;
496 accum->cUpdates++;
498 return ret;
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 },
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 },
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 },
532 static const struct update_accum a3 = { sizeof(b3) / sizeof(b3[0]), b3 };
534 static void check_updates(LPCSTR header, const struct update_accum *expected,
535 const struct update_accum *got)
537 DWORD i;
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++)
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);
556 /* Frees the updates stored in accum */
557 static void free_updates(struct update_accum *accum)
559 DWORD i;
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;
568 static void test_data_msg_encoding(void)
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 };
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.)
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);
648 static void test_data_msg(void)
650 test_data_msg_open();
651 test_data_msg_update();
652 test_data_msg_get_param();
653 test_data_msg_encoding();
656 static void test_hash_msg_open(void)
658 HCRYPTMSG msg;
659 CMSG_HASHED_ENCODE_INFO hashInfo = { 0 };
660 static char oid_rsa_md5[] = szOID_RSA_MD5;
662 SetLastError(0xdeadbeef);
663 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
664 NULL, NULL);
665 todo_wine
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 todo_wine
673 ok(!msg && GetLastError() == CRYPT_E_UNKNOWN_ALGO,
674 "Expected CRYPT_E_UNKNOWN_ALGO, got %x\n", GetLastError());
675 hashInfo.HashAlgorithm.pszObjId = oid_rsa_md5;
676 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
677 NULL, NULL);
678 todo_wine
679 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
680 CryptMsgClose(msg);
683 static void test_hash_msg_update(void)
685 HCRYPTMSG msg;
686 BOOL ret;
687 static char oid_rsa_md5[] = szOID_RSA_MD5;
688 CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0,
689 { oid_rsa_md5, { 0, NULL } }, NULL };
690 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
692 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
693 CMSG_HASHED, &hashInfo, NULL, NULL);
694 /* Detached hashed messages opened in non-streaming mode allow non-final
695 * updates..
697 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
698 todo_wine
699 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
700 /* including non-final updates with no data.. */
701 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
702 todo_wine
703 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
704 /* and final updates with no data. */
705 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
706 todo_wine
707 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
708 /* But no updates are allowed after the final update. */
709 SetLastError(0xdeadbeef);
710 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
711 todo_wine
712 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
713 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
714 SetLastError(0xdeadbeef);
715 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
716 todo_wine
717 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
718 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
719 CryptMsgClose(msg);
720 /* Non-detached messages, in contrast, don't allow non-final updates in
721 * non-streaming mode.
723 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
724 NULL, NULL);
725 SetLastError(0xdeadbeef);
726 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
727 todo_wine
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 todo_wine
733 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
734 CryptMsgClose(msg);
735 /* And, of course, streaming mode allows non-final updates */
736 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
737 NULL, &streamInfo);
738 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
739 todo_wine
740 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
741 CryptMsgClose(msg);
744 static void test_hash_msg(void)
746 test_hash_msg_open();
747 test_hash_msg_update();
750 static CRYPT_DATA_BLOB b4 = { 0, NULL };
751 static const struct update_accum a4 = { 1, &b4 };
753 static const BYTE bogusOIDContent[] = {
754 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x07,0xa0,0x02,
755 0x04,0x00 };
757 static void test_decode_msg_update(void)
759 HCRYPTMSG msg;
760 BOOL ret;
761 CMSG_STREAM_INFO streamInfo = { 0 };
762 DWORD i;
763 struct update_accum accum = { 0, NULL };
765 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
766 /* Update with a full message in a final update */
767 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
768 todo_wine
769 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
770 /* Can't update after a final update */
771 SetLastError(0xdeadbeef);
772 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
773 todo_wine
774 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
775 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
776 CryptMsgClose(msg);
778 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
779 /* Can't send a non-final update without streaming */
780 SetLastError(0xdeadbeef);
781 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
782 FALSE);
783 todo_wine
784 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
785 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
786 /* A subsequent final update succeeds */
787 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
788 todo_wine
789 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
790 CryptMsgClose(msg);
792 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
793 /* Updating a message that has a NULL stream callback fails */
794 SetLastError(0xdeadbeef);
795 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
796 FALSE);
797 todo_wine
798 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
799 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
800 /* Changing the callback pointer after the fact yields the same error (so
801 * the message must copy the stream info, not just store a pointer to it)
803 streamInfo.pfnStreamOutput = nop_stream_output;
804 SetLastError(0xdeadbeef);
805 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
806 FALSE);
807 todo_wine
808 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
809 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
810 CryptMsgClose(msg);
812 /* Empty non-final updates are allowed when streaming.. */
813 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
814 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
815 todo_wine
816 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
817 /* but final updates aren't when not enough data has been received. */
818 SetLastError(0xdeadbeef);
819 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
820 todo_wine
821 ok(!ret && GetLastError() == CRYPT_E_STREAM_INSUFFICIENT_DATA,
822 "Expected CRYPT_E_STREAM_INSUFFICIENT_DATA, got %x\n", GetLastError());
823 CryptMsgClose(msg);
825 /* Updating the message byte by byte is legal */
826 streamInfo.pfnStreamOutput = accumulating_stream_output;
827 streamInfo.pvArg = &accum;
828 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
829 for (i = 0, ret = TRUE; ret && i < sizeof(dataEmptyContent); i++)
830 ret = CryptMsgUpdate(msg, &dataEmptyContent[i], 1, FALSE);
831 todo_wine {
832 ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
833 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
834 ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
836 CryptMsgClose(msg);
837 todo_wine
838 check_updates("byte-by-byte empty content", &a4, &accum);
839 free_updates(&accum);
841 /* Decoding bogus content fails in non-streaming mode.. */
842 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
843 SetLastError(0xdeadbeef);
844 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
845 todo_wine
846 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
847 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
848 CryptMsgClose(msg);
849 /* and as the final update in streaming mode.. */
850 streamInfo.pfnStreamOutput = nop_stream_output;
851 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
852 SetLastError(0xdeadbeef);
853 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
854 todo_wine
855 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
856 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
857 CryptMsgClose(msg);
858 /* and even as a non-final update in streaming mode. */
859 streamInfo.pfnStreamOutput = nop_stream_output;
860 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
861 SetLastError(0xdeadbeef);
862 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
863 todo_wine
864 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
865 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
866 CryptMsgClose(msg);
868 /* An empty message can be opened with indetermined type.. */
869 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
870 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
871 TRUE);
872 todo_wine
873 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
874 /* but decoding it as an explicitly typed message fails. */
875 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
876 NULL);
877 SetLastError(0xdeadbeef);
878 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
879 TRUE);
880 todo_wine
881 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
882 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
883 CryptMsgClose(msg);
884 /* On the other hand, decoding the bare content of an empty message fails
885 * with unspecified type..
887 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
888 SetLastError(0xdeadbeef);
889 ret = CryptMsgUpdate(msg, dataEmptyBareContent,
890 sizeof(dataEmptyBareContent), TRUE);
891 todo_wine
892 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
893 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
894 CryptMsgClose(msg);
895 /* but succeeds with explicit type. */
896 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
897 NULL);
898 ret = CryptMsgUpdate(msg, dataEmptyBareContent,
899 sizeof(dataEmptyBareContent), TRUE);
900 todo_wine
901 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
902 CryptMsgClose(msg);
904 /* Decoding valid content with an unsupported OID fails */
905 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
906 SetLastError(0xdeadbeef);
907 ret = CryptMsgUpdate(msg, bogusOIDContent, sizeof(bogusOIDContent), TRUE);
908 todo_wine
909 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
910 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
911 CryptMsgClose(msg);
914 static void test_decode_msg(void)
916 test_decode_msg_update();
919 START_TEST(msg)
921 /* Basic parameter checking tests */
922 test_msg_open_to_encode();
923 test_msg_open_to_decode();
924 test_msg_get_param();
925 test_msg_close();
927 /* Message-type specific tests */
928 test_data_msg();
929 test_hash_msg();
930 test_decode_msg();