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
28 #include "wine/test.h"
30 static void test_msg_open_to_encode(void)
35 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, NULL,
37 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, NULL, NULL,
39 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, NULL, NULL,
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,
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,
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)
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());
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,
98 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
100 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, 0, NULL,
102 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
104 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
106 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
108 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
110 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
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());
117 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
118 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
120 /* or even invalid. */
121 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, 0, NULL,
123 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
125 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 1000, 0, NULL, NULL);
126 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
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,
134 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
138 static void test_msg_get_param(void)
142 DWORD size, i, value;
143 CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
144 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
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 */
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);
166 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, 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++)
177 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
178 ok(!ret, "Parameter %d: expected failure\n", i);
182 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, 0, 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++)
192 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
193 ok(!ret, "Parameter %d: expected failure\n", i);
197 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, 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++)
207 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
208 ok(!ret, "Parameter %d: expected failure\n", i);
212 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, 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++)
222 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
223 ok(!ret, "Parameter %d: expected failure\n", i);
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,
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);
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);
246 static void test_msg_close(void)
251 /* NULL succeeds.. */
252 ret = CryptMsgClose(NULL);
253 ok(ret, "CryptMsgClose failed: %x\n", GetLastError());
254 /* but an arbitrary pointer crashes. */
256 ret = CryptMsgClose((HCRYPTMSG)1);
257 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, 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)
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,
280 ok(!memcmp(buf, expected, size), "%s: unexpected data\n", test);
281 HeapFree(GetProcessHeap(), 0, buf);
284 static void test_data_msg_open(void)
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,
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,
299 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
302 /* An empty stream info is allowed. */
303 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
305 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
308 /* Passing a bogus inner OID succeeds for a non-streamed message.. */
309 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, oid,
311 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
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());
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());
327 static const BYTE msgData[] = { 1, 2, 3, 4 };
329 static BOOL WINAPI nop_stream_output(const void *pvArg, BYTE *pb, DWORD cb,
335 static void test_data_msg_update(void)
339 CMSG_STREAM_INFO streamInfo = { 0 };
341 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, 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());
358 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, 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());
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());
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,
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());
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,
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());
411 static void test_data_msg_get_param(void)
416 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
418 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
421 /* Content and bare content are always gettable when not streaming */
423 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
424 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
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.
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());
445 /* Can't get content or bare content when streaming */
446 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
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());
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,
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 };
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;
481 accum->updates = CryptMemRealloc(accum->updates,
482 (accum->cUpdates + 1) * sizeof(CRYPT_DATA_BLOB));
484 accum->updates = CryptMemAlloc(sizeof(CRYPT_DATA_BLOB));
487 CRYPT_DATA_BLOB *blob = &accum->updates[accum->cUpdates];
489 blob->pbData = CryptMemAlloc(cb);
492 memcpy(blob->pbData, pb, cb);
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[] = {
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[] = {
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[] = {
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)
539 ok(expected->cUpdates == got->cUpdates,
540 "%s: expected %d updates, got %d\n", header, expected->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",
556 /* Frees the updates stored in accum */
557 static void free_updates(struct update_accum *accum)
561 for (i = 0; i < accum->cUpdates; i++)
562 CryptMemFree(accum->updates[i].pbData);
563 CryptMemFree(accum->updates);
564 accum->updates = NULL;
568 static void test_data_msg_encoding(void)
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,
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));
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));
603 /* The inner OID is apparently ignored */
604 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, oid,
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));
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,
623 CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
624 CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
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,
632 CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
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,
640 CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
641 CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
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)
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 };
663 SetLastError(0xdeadbeef);
664 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
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,
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,
677 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
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());
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());
689 static void test_hash_msg_update(void)
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 };
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
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());
721 /* Non-detached messages, in contrast, don't allow non-final updates in
722 * non-streaming mode.
724 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
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());
734 /* And, of course, streaming mode allows non-final updates */
735 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
737 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
738 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
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.)
743 streamInfo.pfnStreamOutput = NULL;
744 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
746 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
747 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
751 static const BYTE emptyHashParam[] = {
752 0xd4,0x1d,0x8c,0xd9,0x8f,0x00,0xb2,0x04,0xe9,0x80,0x09,0x98,0xec,0xf8,0x42,
755 static void test_hash_msg_get_param(void)
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 };
763 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
766 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
768 /* Content and bare content are always gettable for non-streamed messages */
770 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
772 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
774 ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
775 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
777 /* The hash is also available. */
779 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
780 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
781 ok(size == sizeof(buf), "Unexpected size %d\n", size);
782 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, buf, &size);
783 if (size == sizeof(buf))
784 ok(!memcmp(buf, emptyHashParam, size), "Unexpected value\n");
785 /* By getting the hash, further updates are not allowed */
786 SetLastError(0xdeadbeef);
787 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
788 ok(!ret && GetLastError() == NTE_BAD_HASH_STATE,
789 "Expected NTE_BAD_HASH_STATE, got %x\n", GetLastError());
790 /* The version is also available, and should be zero for this message. */
792 ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, NULL, &size);
793 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
794 size = sizeof(value);
795 ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, (LPBYTE)&value, &size);
796 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
797 ok(value == 0, "Expected version 0, got %d\n", value);
798 /* As usual, the type isn't available. */
799 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
801 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
802 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
805 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
807 /* Streamed messages don't allow you to get the content or bare content. */
808 SetLastError(0xdeadbeef);
809 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
811 ok(!ret && GetLastError() == E_INVALIDARG,
812 "Expected E_INVALIDARG, got %x\n", GetLastError());
813 SetLastError(0xdeadbeef);
814 ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
815 ok(!ret && GetLastError() == E_INVALIDARG,
816 "Expected E_INVALIDARG, got %x\n", GetLastError());
818 /* The hash is still available. */
820 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
821 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
822 ok(size == sizeof(buf), "Unexpected size %d\n", size);
823 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, buf, &size);
824 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
825 if (size == sizeof(buf))
826 ok(!memcmp(buf, emptyHashParam, size), "Unexpected value\n");
827 /* After updating the hash, further updates aren't allowed on streamed
830 SetLastError(0xdeadbeef);
831 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
832 ok(!ret && GetLastError() == NTE_BAD_HASH_STATE,
833 "Expected NTE_BAD_HASH_STATE, got %x\n", GetLastError());
837 static const BYTE hashEmptyBareContent[] = {
838 0x30,0x17,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
839 0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x04,0x00 };
840 static const BYTE hashEmptyContent[] = {
841 0x30,0x26,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x19,
842 0x30,0x17,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
843 0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x04,0x00 };
844 static const BYTE hashBareContent[] = {
845 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
846 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
847 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
848 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
849 static const BYTE hashContent[] = {
850 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
851 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
852 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
853 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
854 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
856 static const BYTE detachedHashBareContent[] = {
857 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
858 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
859 0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
860 0x9d,0x2a,0x8f,0x26,0x2f };
861 static const BYTE detachedHashContent[] = {
862 0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
863 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
864 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
865 0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
866 0x9d,0x2a,0x8f,0x26,0x2f };
868 static void test_hash_msg_encoding(void)
871 CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0 };
873 struct update_accum accum = { 0, NULL }, empty_accum = { 0, NULL };
874 CMSG_STREAM_INFO streamInfo = { 0, accumulating_stream_output, &accum };
875 static char oid_rsa_md5[] = szOID_RSA_MD5;
877 hashInfo.HashAlgorithm.pszObjId = oid_rsa_md5;
878 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
881 check_param("hash empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
882 hashEmptyBareContent, sizeof(hashEmptyBareContent));
883 check_param("hash empty content", msg, CMSG_CONTENT_PARAM,
884 hashEmptyContent, sizeof(hashEmptyContent));
886 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
887 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));
895 /* Same test, but with CMSG_BARE_CONTENT_FLAG set */
896 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_BARE_CONTENT_FLAG,
897 CMSG_HASHED, &hashInfo, NULL, NULL);
899 check_param("hash empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
900 hashEmptyBareContent, sizeof(hashEmptyBareContent));
901 check_param("hash empty content", msg, CMSG_CONTENT_PARAM,
902 hashEmptyContent, sizeof(hashEmptyContent));
904 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
905 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
907 check_param("hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
908 hashBareContent, sizeof(hashBareContent));
909 check_param("hash content", msg, CMSG_CONTENT_PARAM,
910 hashContent, sizeof(hashContent));
913 /* Same test, but with CMSG_DETACHED_FLAG set */
914 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
915 CMSG_HASHED, &hashInfo, NULL, NULL);
917 check_param("detached hash empty bare content", msg,
918 CMSG_BARE_CONTENT_PARAM, hashEmptyBareContent,
919 sizeof(hashEmptyBareContent));
920 check_param("detached hash empty content", msg, CMSG_CONTENT_PARAM,
921 hashEmptyContent, sizeof(hashEmptyContent));
923 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
924 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
926 check_param("detached hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
927 detachedHashBareContent, sizeof(detachedHashBareContent));
928 check_param("detached hash content", msg, CMSG_CONTENT_PARAM,
929 detachedHashContent, sizeof(detachedHashContent));
932 /* In what appears to be a bug, streamed updates to hash messages don't
933 * call the output function.
935 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
937 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
938 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
939 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
940 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
942 check_updates("empty hash message", &empty_accum, &accum);
943 free_updates(&accum);
945 streamInfo.cbContent = sizeof(msgData);
946 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
948 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
949 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
951 check_updates("hash message", &empty_accum, &accum);
952 free_updates(&accum);
954 streamInfo.cbContent = sizeof(msgData);
955 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
956 CMSG_HASHED, &hashInfo, NULL, &streamInfo);
957 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
958 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
960 check_updates("detached hash message", &empty_accum, &accum);
961 free_updates(&accum);
964 static void test_hash_msg(void)
966 test_hash_msg_open();
967 test_hash_msg_update();
968 test_hash_msg_get_param();
969 test_hash_msg_encoding();
972 static CRYPT_DATA_BLOB b4 = { 0, NULL };
973 static const struct update_accum a4 = { 1, &b4 };
975 static const BYTE bogusOIDContent[] = {
976 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x07,0xa0,0x02,
979 static void test_decode_msg_update(void)
983 CMSG_STREAM_INFO streamInfo = { 0 };
985 struct update_accum accum = { 0, NULL };
987 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
988 /* Update with a full message in a final update */
989 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
991 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
992 /* Can't update after a final update */
993 SetLastError(0xdeadbeef);
994 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
996 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
997 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1000 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1001 /* Can't send a non-final update without streaming */
1002 SetLastError(0xdeadbeef);
1003 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1006 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1007 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1008 /* A subsequent final update succeeds */
1009 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
1011 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1014 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1015 /* Updating a message that has a NULL stream callback fails */
1016 SetLastError(0xdeadbeef);
1017 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1020 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1021 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
1022 /* Changing the callback pointer after the fact yields the same error (so
1023 * the message must copy the stream info, not just store a pointer to it)
1025 streamInfo.pfnStreamOutput = nop_stream_output;
1026 SetLastError(0xdeadbeef);
1027 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1030 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1031 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
1034 /* Empty non-final updates are allowed when streaming.. */
1035 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1036 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1038 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1039 /* but final updates aren't when not enough data has been received. */
1040 SetLastError(0xdeadbeef);
1041 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1043 ok(!ret && GetLastError() == CRYPT_E_STREAM_INSUFFICIENT_DATA,
1044 "Expected CRYPT_E_STREAM_INSUFFICIENT_DATA, got %x\n", GetLastError());
1047 /* Updating the message byte by byte is legal */
1048 streamInfo.pfnStreamOutput = accumulating_stream_output;
1049 streamInfo.pvArg = &accum;
1050 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1051 for (i = 0, ret = TRUE; ret && i < sizeof(dataEmptyContent); i++)
1052 ret = CryptMsgUpdate(msg, &dataEmptyContent[i], 1, FALSE);
1054 ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
1055 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1056 ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
1060 check_updates("byte-by-byte empty content", &a4, &accum);
1061 free_updates(&accum);
1063 /* Decoding bogus content fails in non-streaming mode.. */
1064 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1065 SetLastError(0xdeadbeef);
1066 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1068 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1069 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1071 /* and as the final update in streaming mode.. */
1072 streamInfo.pfnStreamOutput = nop_stream_output;
1073 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1074 SetLastError(0xdeadbeef);
1075 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1077 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1078 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1080 /* and even as a non-final update in streaming mode. */
1081 streamInfo.pfnStreamOutput = nop_stream_output;
1082 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1083 SetLastError(0xdeadbeef);
1084 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1086 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1087 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1090 /* An empty message can be opened with indetermined type.. */
1091 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1092 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1095 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1096 /* but decoding it as an explicitly typed message fails. */
1097 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
1099 SetLastError(0xdeadbeef);
1100 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1103 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1104 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1106 /* On the other hand, decoding the bare content of an empty message fails
1107 * with unspecified type..
1109 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1110 SetLastError(0xdeadbeef);
1111 ret = CryptMsgUpdate(msg, dataEmptyBareContent,
1112 sizeof(dataEmptyBareContent), TRUE);
1114 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1115 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1117 /* but succeeds with explicit type. */
1118 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
1120 ret = CryptMsgUpdate(msg, dataEmptyBareContent,
1121 sizeof(dataEmptyBareContent), TRUE);
1123 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1126 /* Decoding valid content with an unsupported OID fails */
1127 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1128 SetLastError(0xdeadbeef);
1129 ret = CryptMsgUpdate(msg, bogusOIDContent, sizeof(bogusOIDContent), TRUE);
1131 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1132 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1136 static void test_decode_msg(void)
1138 test_decode_msg_update();
1143 /* Basic parameter checking tests */
1144 test_msg_open_to_encode();
1145 test_msg_open_to_decode();
1146 test_msg_get_param();
1149 /* Message-type specific tests */