crypt32: Test getting the hash from a hash message with an invalid index.
[wine.git] / dlls / crypt32 / tests / msg.c
blobf65c7f8f2b3fc4fcb351b0e053f3e2172b9231d4
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 char oid_rsa_md5[] = szOID_RSA_MD5;
32 static void test_msg_open_to_encode(void)
34 HCRYPTMSG msg;
36 /* Crash
37 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, NULL,
38 NULL, NULL);
39 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, NULL, NULL,
40 NULL);
41 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, NULL, NULL,
42 NULL);
45 /* Bad encodings */
46 SetLastError(0xdeadbeef);
47 msg = CryptMsgOpenToEncode(0, 0, 0, NULL, NULL, NULL);
48 ok(!msg && GetLastError() == E_INVALIDARG,
49 "Expected E_INVALIDARG, got %x\n", GetLastError());
50 SetLastError(0xdeadbeef);
51 msg = CryptMsgOpenToEncode(X509_ASN_ENCODING, 0, 0, NULL, NULL, NULL);
52 ok(!msg && GetLastError() == E_INVALIDARG,
53 "Expected E_INVALIDARG, got %x\n", GetLastError());
55 /* Bad message types */
56 SetLastError(0xdeadbeef);
57 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, 0, NULL, NULL, NULL);
58 ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
59 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
60 SetLastError(0xdeadbeef);
61 msg = CryptMsgOpenToEncode(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, 0,
62 NULL, NULL, NULL);
63 ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
64 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
65 SetLastError(0xdeadbeef);
66 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0,
67 CMSG_SIGNED_AND_ENVELOPED, NULL, NULL, NULL);
68 ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
69 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
70 SetLastError(0xdeadbeef);
71 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, NULL,
72 NULL, NULL);
73 ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
74 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
77 static void test_msg_open_to_decode(void)
79 HCRYPTMSG msg;
80 CMSG_STREAM_INFO streamInfo = { 0 };
82 SetLastError(0xdeadbeef);
83 msg = CryptMsgOpenToDecode(0, 0, 0, 0, NULL, NULL);
84 ok(!msg && GetLastError() == E_INVALIDARG,
85 "Expected E_INVALIDARG, got %x\n", GetLastError());
87 /* Bad encodings */
88 SetLastError(0xdeadbeef);
89 msg = CryptMsgOpenToDecode(X509_ASN_ENCODING, 0, 0, 0, NULL, NULL);
90 ok(!msg && GetLastError() == E_INVALIDARG,
91 "Expected E_INVALIDARG, got %x\n", GetLastError());
92 SetLastError(0xdeadbeef);
93 msg = CryptMsgOpenToDecode(X509_ASN_ENCODING, 0, CMSG_DATA, 0, NULL, NULL);
94 ok(!msg && GetLastError() == E_INVALIDARG,
95 "Expected E_INVALIDARG, got %x\n", GetLastError());
97 /* The message type can be explicit... */
98 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
99 NULL);
100 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
101 CryptMsgClose(msg);
102 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, 0, NULL,
103 NULL);
104 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
105 CryptMsgClose(msg);
106 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
107 NULL);
108 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
109 CryptMsgClose(msg);
110 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
111 NULL);
112 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
113 CryptMsgClose(msg);
114 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0,
115 CMSG_SIGNED_AND_ENVELOPED, 0, NULL, NULL);
116 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
117 CryptMsgClose(msg);
118 /* or implicit.. */
119 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
120 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
121 CryptMsgClose(msg);
122 /* or even invalid. */
123 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, 0, NULL,
124 NULL);
125 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
126 CryptMsgClose(msg);
127 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 1000, 0, NULL, NULL);
128 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
129 CryptMsgClose(msg);
131 /* And even though the stream info parameter "must be set to NULL" for
132 * CMSG_HASHED, it's still accepted.
134 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
135 &streamInfo);
136 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
137 CryptMsgClose(msg);
140 static void test_msg_get_param(void)
142 BOOL ret;
143 HCRYPTMSG msg;
144 DWORD size, i, value;
145 CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
146 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
148 /* Crash
149 ret = CryptMsgGetParam(NULL, 0, 0, NULL, NULL);
150 ret = CryptMsgGetParam(NULL, 0, 0, NULL, &size);
151 ret = CryptMsgGetParam(msg, 0, 0, NULL, NULL);
154 /* Decoded messages */
155 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
156 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
157 /* For decoded messages, the type is always available */
158 size = 0;
159 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
160 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
161 size = sizeof(value);
162 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
163 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
164 /* For this (empty) message, the type isn't set */
165 ok(value == 0, "Expected type 0, got %d\n", value);
166 CryptMsgClose(msg);
168 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
169 NULL);
170 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
171 /* For explicitly typed messages, the type is known. */
172 size = sizeof(value);
173 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
174 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
175 ok(value == CMSG_DATA, "Expected CMSG_DATA, got %d\n", value);
176 for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++)
178 size = 0;
179 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
180 ok(!ret, "Parameter %d: expected failure\n", i);
182 CryptMsgClose(msg);
184 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, 0, NULL,
185 NULL);
186 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
187 size = sizeof(value);
188 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
189 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
190 ok(value == CMSG_ENVELOPED, "Expected CMSG_ENVELOPED, got %d\n", value);
191 for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++)
193 size = 0;
194 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
195 ok(!ret, "Parameter %d: expected failure\n", i);
197 CryptMsgClose(msg);
199 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
200 NULL);
201 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
202 size = sizeof(value);
203 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
204 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
205 ok(value == CMSG_HASHED, "Expected CMSG_HASHED, got %d\n", value);
206 for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++)
208 size = 0;
209 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
210 ok(!ret, "Parameter %d: expected failure\n", i);
212 CryptMsgClose(msg);
214 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
215 NULL);
216 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
217 size = sizeof(value);
218 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
219 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
220 ok(value == CMSG_SIGNED, "Expected CMSG_SIGNED, got %d\n", value);
221 for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++)
223 size = 0;
224 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
225 ok(!ret, "Parameter %d: expected failure\n", i);
227 CryptMsgClose(msg);
229 /* Explicitly typed messages get their types set, even if they're invalid */
230 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, 0, NULL,
231 NULL);
232 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
233 size = sizeof(value);
234 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
235 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
236 ok(value == CMSG_ENCRYPTED, "Expected CMSG_ENCRYPTED, got %d\n", value);
237 CryptMsgClose(msg);
239 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 1000, 0, NULL, NULL);
240 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
241 size = sizeof(value);
242 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
243 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
244 ok(value == 1000, "Expected 1000, got %d\n", value);
245 CryptMsgClose(msg);
248 static void test_msg_close(void)
250 BOOL ret;
251 HCRYPTMSG msg;
253 /* NULL succeeds.. */
254 ret = CryptMsgClose(NULL);
255 ok(ret, "CryptMsgClose failed: %x\n", GetLastError());
256 /* but an arbitrary pointer crashes. */
257 if (0)
258 ret = CryptMsgClose((HCRYPTMSG)1);
259 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
260 NULL);
261 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
262 ret = CryptMsgClose(msg);
263 ok(ret, "CryptMsgClose failed: %x\n", GetLastError());
266 static void check_param(LPCSTR test, HCRYPTMSG msg, DWORD param,
267 const BYTE *expected, DWORD expectedSize)
269 DWORD size;
270 LPBYTE buf;
271 BOOL ret;
273 size = 0xdeadbeef;
274 ret = CryptMsgGetParam(msg, param, 0, NULL, &size);
275 ok(ret, "%s: CryptMsgGetParam failed: %08x\n", test, GetLastError());
276 buf = HeapAlloc(GetProcessHeap(), 0, size);
277 ret = CryptMsgGetParam(msg, param, 0, buf, &size);
278 ok(ret, "%s: CryptMsgGetParam failed: %08x\n", test, GetLastError());
279 ok(size == expectedSize, "%s: expected size %d, got %d\n", test,
280 expectedSize, size);
281 if (size == expectedSize && size)
282 ok(!memcmp(buf, expected, size), "%s: unexpected data\n", test);
283 HeapFree(GetProcessHeap(), 0, buf);
286 static void test_data_msg_open(void)
288 HCRYPTMSG msg;
289 CMSG_HASHED_ENCODE_INFO hashInfo = { 0 };
290 CMSG_STREAM_INFO streamInfo = { 0 };
291 char oid[] = "1.2.3";
293 /* The data message type takes no additional info */
294 SetLastError(0xdeadbeef);
295 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, &hashInfo,
296 NULL, NULL);
297 ok(!msg && GetLastError() == E_INVALIDARG,
298 "Expected E_INVALIDARG, got %x\n", GetLastError());
299 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
300 NULL);
301 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
302 CryptMsgClose(msg);
304 /* An empty stream info is allowed. */
305 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
306 &streamInfo);
307 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
308 CryptMsgClose(msg);
310 /* Passing a bogus inner OID succeeds for a non-streamed message.. */
311 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, oid,
312 NULL);
313 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
314 CryptMsgClose(msg);
315 /* and still succeeds when CMSG_DETACHED_FLAG is passed.. */
316 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
317 CMSG_DATA, NULL, oid, NULL);
318 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
319 CryptMsgClose(msg);
320 /* and when a stream info is given, even though you're not supposed to be
321 * able to use anything but szOID_RSA_data when streaming is being used.
323 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
324 CMSG_DATA, NULL, oid, &streamInfo);
325 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
326 CryptMsgClose(msg);
329 static const BYTE msgData[] = { 1, 2, 3, 4 };
331 static BOOL WINAPI nop_stream_output(const void *pvArg, BYTE *pb, DWORD cb,
332 BOOL final)
334 return TRUE;
337 static void test_data_msg_update(void)
339 HCRYPTMSG msg;
340 BOOL ret;
341 CMSG_STREAM_INFO streamInfo = { 0 };
343 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
344 NULL);
345 /* Can't update a message that wasn't opened detached with final = FALSE */
346 SetLastError(0xdeadbeef);
347 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
348 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
349 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
350 /* Updating it with final = TRUE succeeds */
351 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
352 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
353 /* Any subsequent update will fail, as the last was final */
354 SetLastError(0xdeadbeef);
355 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
356 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
357 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
358 CryptMsgClose(msg);
360 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
361 NULL);
362 /* Can't update a message with no data */
363 SetLastError(0xdeadbeef);
364 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
365 ok(!ret && GetLastError() == E_INVALIDARG,
366 "Expected E_INVALIDARG, got %x\n", GetLastError());
367 /* Curiously, a valid update will now fail as well, presumably because of
368 * the last (invalid, but final) update.
370 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
371 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
372 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
373 CryptMsgClose(msg);
375 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
376 CMSG_DATA, NULL, NULL, NULL);
377 /* Doesn't appear to be able to update CMSG-DATA with non-final updates */
378 SetLastError(0xdeadbeef);
379 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
380 ok(!ret && GetLastError() == E_INVALIDARG,
381 "Expected E_INVALIDARG, got %x\n", GetLastError());
382 SetLastError(0xdeadbeef);
383 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
384 ok(!ret && GetLastError() == E_INVALIDARG,
385 "Expected E_INVALIDARG, got %x\n", GetLastError());
386 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
387 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
388 CryptMsgClose(msg);
390 /* Calling update after opening with an empty stream info (with a bogus
391 * output function) yields an error:
393 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
394 &streamInfo);
395 SetLastError(0xdeadbeef);
396 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
397 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
398 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
399 CryptMsgClose(msg);
400 /* Calling update with a valid output function succeeds, even if the data
401 * exceeds the size specified in the stream info.
403 streamInfo.pfnStreamOutput = nop_stream_output;
404 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
405 &streamInfo);
406 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
407 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
408 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
409 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
410 CryptMsgClose(msg);
413 static void test_data_msg_get_param(void)
415 HCRYPTMSG msg;
416 DWORD size;
417 BOOL ret;
418 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
420 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
421 NULL);
423 /* Content and bare content are always gettable when not streaming */
424 size = 0;
425 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
426 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
427 size = 0;
428 ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
429 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
430 /* But for this type of message, the signer and hash aren't applicable,
431 * and the type isn't available.
433 size = 0;
434 SetLastError(0xdeadbeef);
435 ret = CryptMsgGetParam(msg, CMSG_ENCODED_SIGNER, 0, NULL, &size);
436 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
437 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
438 SetLastError(0xdeadbeef);
439 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
440 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
441 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
442 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
443 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
444 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
445 CryptMsgClose(msg);
447 /* Can't get content or bare content when streaming */
448 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
449 NULL, &streamInfo);
450 SetLastError(0xdeadbeef);
451 ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
452 ok(!ret && GetLastError() == E_INVALIDARG,
453 "Expected E_INVALIDARG, got %x\n", GetLastError());
454 SetLastError(0xdeadbeef);
455 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
456 ok(!ret && GetLastError() == E_INVALIDARG,
457 "Expected E_INVALIDARG, got %x\n", GetLastError());
458 CryptMsgClose(msg);
461 static const BYTE dataEmptyBareContent[] = { 0x04,0x00 };
462 static const BYTE dataEmptyContent[] = {
463 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x02,
464 0x04,0x00 };
465 static const BYTE dataBareContent[] = { 0x04,0x04,0x01,0x02,0x03,0x04 };
466 static const BYTE dataContent[] = {
467 0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,
468 0x04,0x04,0x01,0x02,0x03,0x04 };
470 struct update_accum
472 DWORD cUpdates;
473 CRYPT_DATA_BLOB *updates;
476 static BOOL WINAPI accumulating_stream_output(const void *pvArg, BYTE *pb,
477 DWORD cb, BOOL final)
479 struct update_accum *accum = (struct update_accum *)pvArg;
480 BOOL ret = FALSE;
482 if (accum->cUpdates)
483 accum->updates = CryptMemRealloc(accum->updates,
484 (accum->cUpdates + 1) * sizeof(CRYPT_DATA_BLOB));
485 else
486 accum->updates = CryptMemAlloc(sizeof(CRYPT_DATA_BLOB));
487 if (accum->updates)
489 CRYPT_DATA_BLOB *blob = &accum->updates[accum->cUpdates];
491 blob->pbData = CryptMemAlloc(cb);
492 if (blob->pbData)
494 memcpy(blob->pbData, pb, cb);
495 blob->cbData = cb;
496 ret = TRUE;
498 accum->cUpdates++;
500 return ret;
503 /* The updates of a (bogus) definite-length encoded message */
504 static BYTE u1[] = { 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
505 0x07,0x01,0xa0,0x02,0x04,0x00 };
506 static BYTE u2[] = { 0x01,0x02,0x03,0x04 };
507 static CRYPT_DATA_BLOB b1[] = {
508 { sizeof(u1), u1 },
509 { sizeof(u2), u2 },
510 { sizeof(u2), u2 },
512 static const struct update_accum a1 = { sizeof(b1) / sizeof(b1[0]), b1 };
513 /* The updates of a definite-length encoded message */
514 static BYTE u3[] = { 0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
515 0x07,0x01,0xa0,0x06,0x04,0x04 };
516 static CRYPT_DATA_BLOB b2[] = {
517 { sizeof(u3), u3 },
518 { sizeof(u2), u2 },
520 static const struct update_accum a2 = { sizeof(b2) / sizeof(b2[0]), b2 };
521 /* The updates of an indefinite-length encoded message */
522 static BYTE u4[] = { 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
523 0x07,0x01,0xa0,0x80,0x24,0x80 };
524 static BYTE u5[] = { 0x04,0x04 };
525 static BYTE u6[] = { 0x00,0x00,0x00,0x00,0x00,0x00 };
526 static CRYPT_DATA_BLOB b3[] = {
527 { sizeof(u4), u4 },
528 { sizeof(u5), u5 },
529 { sizeof(u2), u2 },
530 { sizeof(u5), u5 },
531 { sizeof(u2), u2 },
532 { sizeof(u6), u6 },
534 static const struct update_accum a3 = { sizeof(b3) / sizeof(b3[0]), b3 };
536 static void check_updates(LPCSTR header, const struct update_accum *expected,
537 const struct update_accum *got)
539 DWORD i;
541 ok(expected->cUpdates == got->cUpdates,
542 "%s: expected %d updates, got %d\n", header, expected->cUpdates,
543 got->cUpdates);
544 if (expected->cUpdates == got->cUpdates)
545 for (i = 0; i < min(expected->cUpdates, got->cUpdates); i++)
547 ok(expected->updates[i].cbData == got->updates[i].cbData,
548 "%s, update %d: expected %d bytes, got %d\n", header, i,
549 expected->updates[i].cbData, got->updates[i].cbData);
550 if (expected->updates[i].cbData && expected->updates[i].cbData ==
551 got->updates[i].cbData)
552 ok(!memcmp(expected->updates[i].pbData, got->updates[i].pbData,
553 got->updates[i].cbData), "%s, update %d: unexpected value\n",
554 header, i);
558 /* Frees the updates stored in accum */
559 static void free_updates(struct update_accum *accum)
561 DWORD i;
563 for (i = 0; i < accum->cUpdates; i++)
564 CryptMemFree(accum->updates[i].pbData);
565 CryptMemFree(accum->updates);
566 accum->updates = NULL;
567 accum->cUpdates = 0;
570 static void test_data_msg_encoding(void)
572 HCRYPTMSG msg;
573 BOOL ret;
574 static char oid[] = "1.2.3";
575 struct update_accum accum = { 0, NULL };
576 CMSG_STREAM_INFO streamInfo = { 0, accumulating_stream_output, &accum };
578 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
579 NULL);
580 check_param("data empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
581 dataEmptyBareContent, sizeof(dataEmptyBareContent));
582 check_param("data empty content", msg, CMSG_CONTENT_PARAM, dataEmptyContent,
583 sizeof(dataEmptyContent));
584 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
585 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
586 check_param("data bare content", msg, CMSG_BARE_CONTENT_PARAM,
587 dataBareContent, sizeof(dataBareContent));
588 check_param("data content", msg, CMSG_CONTENT_PARAM, dataContent,
589 sizeof(dataContent));
590 CryptMsgClose(msg);
591 /* Same test, but with CMSG_BARE_CONTENT_FLAG set */
592 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_BARE_CONTENT_FLAG,
593 CMSG_DATA, NULL, NULL, NULL);
594 check_param("data empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
595 dataEmptyBareContent, sizeof(dataEmptyBareContent));
596 check_param("data empty content", msg, CMSG_CONTENT_PARAM, dataEmptyContent,
597 sizeof(dataEmptyContent));
598 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
599 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
600 check_param("data bare content", msg, CMSG_BARE_CONTENT_PARAM,
601 dataBareContent, sizeof(dataBareContent));
602 check_param("data content", msg, CMSG_CONTENT_PARAM, dataContent,
603 sizeof(dataContent));
604 CryptMsgClose(msg);
605 /* The inner OID is apparently ignored */
606 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, oid,
607 NULL);
608 check_param("data bogus oid bare content", msg, CMSG_BARE_CONTENT_PARAM,
609 dataEmptyBareContent, sizeof(dataEmptyBareContent));
610 check_param("data bogus oid content", msg, CMSG_CONTENT_PARAM,
611 dataEmptyContent, sizeof(dataEmptyContent));
612 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
613 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
614 check_param("data bare content", msg, CMSG_BARE_CONTENT_PARAM,
615 dataBareContent, sizeof(dataBareContent));
616 check_param("data content", msg, CMSG_CONTENT_PARAM, dataContent,
617 sizeof(dataContent));
618 CryptMsgClose(msg);
619 /* A streaming message is DER encoded if the length is not 0xffffffff, but
620 * curiously, updates aren't validated to make sure they don't exceed the
621 * stated length. (The resulting output will of course fail to decode.)
623 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
624 NULL, &streamInfo);
625 CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
626 CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
627 CryptMsgClose(msg);
628 check_updates("bogus data message with definite length", &a1, &accum);
629 free_updates(&accum);
630 /* A valid definite-length encoding: */
631 streamInfo.cbContent = sizeof(msgData);
632 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
633 NULL, &streamInfo);
634 CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
635 CryptMsgClose(msg);
636 check_updates("data message with definite length", &a2, &accum);
637 free_updates(&accum);
638 /* An indefinite-length encoding: */
639 streamInfo.cbContent = 0xffffffff;
640 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
641 NULL, &streamInfo);
642 CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
643 CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
644 CryptMsgClose(msg);
645 todo_wine
646 check_updates("data message with indefinite length", &a3, &accum);
647 free_updates(&accum);
650 static void test_data_msg(void)
652 test_data_msg_open();
653 test_data_msg_update();
654 test_data_msg_get_param();
655 test_data_msg_encoding();
658 static void test_hash_msg_open(void)
660 HCRYPTMSG msg;
661 CMSG_HASHED_ENCODE_INFO hashInfo = { 0 };
662 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
664 SetLastError(0xdeadbeef);
665 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
666 NULL, NULL);
667 ok(!msg && GetLastError() == E_INVALIDARG,
668 "Expected E_INVALIDARG, got %x\n", GetLastError());
669 hashInfo.cbSize = sizeof(hashInfo);
670 SetLastError(0xdeadbeef);
671 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
672 NULL, NULL);
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 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
679 CryptMsgClose(msg);
680 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
681 CMSG_HASHED, &hashInfo, NULL, NULL);
682 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
683 CryptMsgClose(msg);
684 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
685 CMSG_HASHED, &hashInfo, NULL, &streamInfo);
686 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
687 CryptMsgClose(msg);
690 static void test_hash_msg_update(void)
692 HCRYPTMSG msg;
693 BOOL ret;
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
701 * updates..
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.
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.)
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);
751 static const BYTE emptyHashParam[] = {
752 0xd4,0x1d,0x8c,0xd9,0x8f,0x00,0xb2,0x04,0xe9,0x80,0x09,0x98,0xec,0xf8,0x42,
753 0x7e };
755 static void test_hash_msg_get_param(void)
757 HCRYPTMSG msg;
758 BOOL ret;
759 CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0,
760 { oid_rsa_md5, { 0, NULL } }, NULL };
761 DWORD size, value;
762 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
763 BYTE buf[16];
765 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
766 NULL, NULL);
767 /* Content and bare content are always gettable for non-streamed messages */
768 size = 0;
769 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
770 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
771 size = 0;
772 ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
773 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
774 /* The hash is also available. */
775 size = 0;
776 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
777 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
778 ok(size == sizeof(buf), "Unexpected size %d\n", size);
779 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, buf, &size);
780 if (size == sizeof(buf))
781 ok(!memcmp(buf, emptyHashParam, size), "Unexpected value\n");
782 /* By getting the hash, further updates are not allowed */
783 SetLastError(0xdeadbeef);
784 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
785 ok(!ret && GetLastError() == NTE_BAD_HASH_STATE,
786 "Expected NTE_BAD_HASH_STATE, got %x\n", GetLastError());
787 /* The version is also available, and should be zero for this message. */
788 size = 0;
789 ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, NULL, &size);
790 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
791 size = sizeof(value);
792 ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, (LPBYTE)&value, &size);
793 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
794 ok(value == 0, "Expected version 0, got %d\n", value);
795 /* As usual, the type isn't available. */
796 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
797 ok(!ret, "Expected failure\n");
798 CryptMsgClose(msg);
800 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
801 NULL, &streamInfo);
802 /* Streamed messages don't allow you to get the content or bare content. */
803 SetLastError(0xdeadbeef);
804 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
805 ok(!ret && GetLastError() == E_INVALIDARG,
806 "Expected E_INVALIDARG, got %x\n", GetLastError());
807 SetLastError(0xdeadbeef);
808 ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
809 ok(!ret && GetLastError() == E_INVALIDARG,
810 "Expected E_INVALIDARG, got %x\n", GetLastError());
811 /* The hash is still available. */
812 size = 0;
813 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
814 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
815 ok(size == sizeof(buf), "Unexpected size %d\n", size);
816 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, buf, &size);
817 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
818 if (size == sizeof(buf))
819 ok(!memcmp(buf, emptyHashParam, size), "Unexpected value\n");
820 /* After updating the hash, further updates aren't allowed on streamed
821 * messages either.
823 SetLastError(0xdeadbeef);
824 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
825 ok(!ret && GetLastError() == NTE_BAD_HASH_STATE,
826 "Expected NTE_BAD_HASH_STATE, got %x\n", GetLastError());
827 CryptMsgClose(msg);
830 static const BYTE hashEmptyBareContent[] = {
831 0x30,0x17,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
832 0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x04,0x00 };
833 static const BYTE hashEmptyContent[] = {
834 0x30,0x26,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x19,
835 0x30,0x17,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
836 0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x04,0x00 };
837 static const BYTE hashBareContent[] = {
838 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
839 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
840 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
841 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
842 static const BYTE hashContent[] = {
843 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
844 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
845 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
846 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
847 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
849 static const BYTE detachedHashNonFinalBareContent[] = {
850 0x30,0x20,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
851 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
852 0x07,0x01,0x04,0x00 };
853 static const BYTE detachedHashNonFinalContent[] = {
854 0x30,0x2f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x22,
855 0x30,0x20,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
856 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
857 0x07,0x01,0x04,0x00 };
858 static const BYTE detachedHashBareContent[] = {
859 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
860 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
861 0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
862 0x9d,0x2a,0x8f,0x26,0x2f };
863 static const BYTE detachedHashContent[] = {
864 0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
865 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
866 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
867 0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
868 0x9d,0x2a,0x8f,0x26,0x2f };
870 static void test_hash_msg_encoding(void)
872 HCRYPTMSG msg;
873 CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0 };
874 BOOL ret;
875 struct update_accum accum = { 0, NULL }, empty_accum = { 0, NULL };
876 CMSG_STREAM_INFO streamInfo = { 0, accumulating_stream_output, &accum };
878 hashInfo.HashAlgorithm.pszObjId = oid_rsa_md5;
879 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
880 NULL, NULL);
881 check_param("hash empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
882 hashEmptyBareContent, sizeof(hashEmptyBareContent));
883 check_param("hash empty content", msg, CMSG_CONTENT_PARAM,
884 hashEmptyContent, sizeof(hashEmptyContent));
885 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
886 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
887 check_param("hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
888 hashBareContent, sizeof(hashBareContent));
889 check_param("hash content", msg, CMSG_CONTENT_PARAM,
890 hashContent, sizeof(hashContent));
891 CryptMsgClose(msg);
892 /* Same test, but with CMSG_BARE_CONTENT_FLAG set */
893 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_BARE_CONTENT_FLAG,
894 CMSG_HASHED, &hashInfo, NULL, NULL);
895 check_param("hash empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
896 hashEmptyBareContent, sizeof(hashEmptyBareContent));
897 check_param("hash empty content", msg, CMSG_CONTENT_PARAM,
898 hashEmptyContent, sizeof(hashEmptyContent));
899 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
900 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
901 check_param("hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
902 hashBareContent, sizeof(hashBareContent));
903 check_param("hash content", msg, CMSG_CONTENT_PARAM,
904 hashContent, sizeof(hashContent));
905 CryptMsgClose(msg);
906 /* Same test, but with CMSG_DETACHED_FLAG set */
907 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
908 CMSG_HASHED, &hashInfo, NULL, NULL);
909 check_param("detached hash empty bare content", msg,
910 CMSG_BARE_CONTENT_PARAM, hashEmptyBareContent,
911 sizeof(hashEmptyBareContent));
912 check_param("detached hash empty content", msg, CMSG_CONTENT_PARAM,
913 hashEmptyContent, sizeof(hashEmptyContent));
914 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
915 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
916 check_param("detached hash not final bare content", msg,
917 CMSG_BARE_CONTENT_PARAM, detachedHashNonFinalBareContent,
918 sizeof(detachedHashNonFinalBareContent));
919 check_param("detached hash not final content", msg, CMSG_CONTENT_PARAM,
920 detachedHashNonFinalContent, sizeof(detachedHashNonFinalContent));
921 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
922 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
923 check_param("detached hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
924 detachedHashBareContent, sizeof(detachedHashBareContent));
925 check_param("detached hash content", msg, CMSG_CONTENT_PARAM,
926 detachedHashContent, sizeof(detachedHashContent));
927 check_param("detached hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
928 detachedHashBareContent, sizeof(detachedHashBareContent));
929 check_param("detached hash content", msg, CMSG_CONTENT_PARAM,
930 detachedHashContent, sizeof(detachedHashContent));
931 CryptMsgClose(msg);
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,
936 NULL, &streamInfo);
937 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
938 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
939 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
940 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
941 CryptMsgClose(msg);
942 check_updates("empty hash message", &empty_accum, &accum);
943 free_updates(&accum);
945 streamInfo.cbContent = sizeof(msgData);
946 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
947 NULL, &streamInfo);
948 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
949 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
950 CryptMsgClose(msg);
951 check_updates("hash message", &empty_accum, &accum);
952 free_updates(&accum);
954 streamInfo.cbContent = sizeof(msgData);
955 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
956 CMSG_HASHED, &hashInfo, NULL, &streamInfo);
957 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
958 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
959 CryptMsgClose(msg);
960 check_updates("detached hash message", &empty_accum, &accum);
961 free_updates(&accum);
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 const WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e',
973 'm','p',0 };
974 static BYTE serialNum[] = { 1 };
975 static BYTE encodedCommonName[] = { 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,
976 0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
978 static void test_signed_msg_open(void)
980 HCRYPTMSG msg;
981 BOOL ret;
982 CMSG_SIGNED_ENCODE_INFO signInfo = { 0 };
983 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
984 CERT_INFO certInfo = { 0 };
986 SetLastError(0xdeadbeef);
987 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
988 NULL, NULL);
989 ok(!msg && GetLastError() == E_INVALIDARG,
990 "Expected E_INVALIDARG, got %x\n", GetLastError());
991 signInfo.cbSize = sizeof(signInfo);
992 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
993 NULL, NULL);
994 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
995 CryptMsgClose(msg);
997 signInfo.cSigners = 1;
998 signInfo.rgSigners = &signer;
999 /* With signer.pCertInfo unset, attempting to open this message this
1000 * crashes.
1002 signer.pCertInfo = &certInfo;
1003 /* The cert info must contain a serial number and an issuer. */
1004 SetLastError(0xdeadbeef);
1005 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1006 NULL, NULL);
1007 ok(!msg && GetLastError() == E_INVALIDARG,
1008 "Expected E_INVALIDARG, got %x\n", GetLastError());
1009 certInfo.SerialNumber.cbData = sizeof(serialNum);
1010 certInfo.SerialNumber.pbData = serialNum;
1011 SetLastError(0xdeadbeef);
1012 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1013 NULL, NULL);
1014 ok(!msg && GetLastError() == E_INVALIDARG,
1015 "Expected E_INVALIDARG, got %x\n", GetLastError());
1016 certInfo.Issuer.cbData = sizeof(encodedCommonName);
1017 certInfo.Issuer.pbData = encodedCommonName;
1018 SetLastError(0xdeadbeef);
1019 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1020 NULL, NULL);
1021 ok(!msg && GetLastError() == E_INVALIDARG,
1022 "Expected E_INVALIDARG, got %x\n", GetLastError());
1024 /* The signer's hCryptProv must be set to something. Whether it's usable
1025 * or not will be checked after the hash algorithm is checked (see next
1026 * test.)
1028 signer.hCryptProv = 1;
1029 SetLastError(0xdeadbeef);
1030 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1031 NULL, NULL);
1032 ok(!msg && GetLastError() == CRYPT_E_UNKNOWN_ALGO,
1033 "Expected CRYPT_E_UNKNOWN_ALGO, got %x\n", GetLastError());
1034 /* The signer's hash algorithm must also be set. */
1035 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
1036 SetLastError(0xdeadbeef);
1037 /* Crashes in advapi32 in wine, don't do it */
1038 if (0) {
1039 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED,
1040 &signInfo, NULL, NULL);
1041 ok(!msg && GetLastError() == ERROR_INVALID_PARAMETER,
1042 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1044 /* The signer's hCryptProv must also be valid. */
1045 ret = CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1046 PROV_RSA_FULL, CRYPT_NEWKEYSET);
1047 if (!ret && GetLastError() == NTE_EXISTS)
1048 ret = CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1049 PROV_RSA_FULL, 0);
1050 ok(ret, "CryptAcquireContextW failed: %x\n", GetLastError());
1051 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1052 NULL, NULL);
1053 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1054 CryptMsgClose(msg);
1056 CryptReleaseContext(signer.hCryptProv, 0);
1057 CryptAcquireContextW(&signer.hCryptProv, cspNameW, MS_DEF_PROV_W,
1058 PROV_RSA_FULL, CRYPT_DELETEKEYSET);
1061 static const BYTE privKey[] = {
1062 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
1063 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
1064 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
1065 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
1066 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
1067 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
1068 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
1069 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
1070 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
1071 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
1072 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
1073 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
1074 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
1075 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
1076 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
1077 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
1078 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
1079 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
1080 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
1081 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
1082 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
1083 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
1084 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
1085 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
1087 static void test_signed_msg_update(void)
1089 HCRYPTMSG msg;
1090 BOOL ret;
1091 CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
1092 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
1093 CERT_INFO certInfo = { 0 };
1094 HCRYPTKEY key;
1096 certInfo.SerialNumber.cbData = sizeof(serialNum);
1097 certInfo.SerialNumber.pbData = serialNum;
1098 certInfo.Issuer.cbData = sizeof(encodedCommonName);
1099 certInfo.Issuer.pbData = encodedCommonName;
1100 signer.pCertInfo = &certInfo;
1101 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
1102 signInfo.cSigners = 1;
1103 signInfo.rgSigners = &signer;
1104 ret = CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1105 PROV_RSA_FULL, CRYPT_NEWKEYSET);
1106 if (!ret && GetLastError() == NTE_EXISTS)
1107 ret = CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1108 PROV_RSA_FULL, 0);
1109 ok(ret, "CryptAcquireContextW failed: %x\n", GetLastError());
1110 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING,
1111 CMSG_DETACHED_FLAG, CMSG_SIGNED, &signInfo, NULL, NULL);
1112 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1113 /* Detached CMSG_SIGNED allows non-final updates. */
1114 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1115 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1116 /* Detached CMSG_SIGNED also allows non-final updates with no data. */
1117 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1118 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1119 /* The final update requires a private key in the hCryptProv, in order to
1120 * generate the signature.
1122 SetLastError(0xdeadbeef);
1123 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1124 ok(!ret && (GetLastError() == NTE_BAD_KEYSET ||
1125 GetLastError() == NTE_NO_KEY),
1126 "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %x\n", GetLastError());
1127 ret = CryptImportKey(signer.hCryptProv, (LPBYTE)privKey, sizeof(privKey),
1128 0, 0, &key);
1129 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
1130 /* The final update should be able to succeed now that a key exists, but
1131 * the previous (invalid) final update prevents it.
1133 SetLastError(0xdeadbeef);
1134 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1135 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1136 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1137 CryptMsgClose(msg);
1139 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING,
1140 CMSG_DETACHED_FLAG, CMSG_SIGNED, &signInfo, NULL, NULL);
1141 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1142 /* Detached CMSG_SIGNED allows non-final updates. */
1143 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1144 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1145 /* Detached CMSG_SIGNED also allows non-final updates with no data. */
1146 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1147 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1148 /* Now that the private key exists, the final update can succeed (even
1149 * with no data.)
1151 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1152 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1153 /* But no updates are allowed after the final update. */
1154 SetLastError(0xdeadbeef);
1155 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1156 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1157 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1158 SetLastError(0xdeadbeef);
1159 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1160 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1161 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1162 CryptMsgClose(msg);
1164 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1165 NULL, NULL);
1166 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1167 /* Non-detached messages don't allow non-final updates.. */
1168 SetLastError(0xdeadbeef);
1169 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1170 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1171 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1172 /* but they do allow final ones. */
1173 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1174 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1175 CryptMsgClose(msg);
1176 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1177 NULL, NULL);
1178 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1179 /* They also allow final updates with no data. */
1180 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1181 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1182 CryptMsgClose(msg);
1184 CryptDestroyKey(key);
1185 CryptReleaseContext(signer.hCryptProv, 0);
1186 CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL, PROV_RSA_FULL,
1187 CRYPT_DELETEKEYSET);
1190 static const BYTE signedEmptyBareContent[] = {
1191 0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
1192 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02,
1193 0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1194 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
1195 0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,
1196 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
1197 static const BYTE signedEmptyContent[] = {
1198 0x30,0x5f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x52,
1199 0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
1200 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02,
1201 0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1202 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
1203 0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,
1204 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
1205 static const BYTE detachedSignedBareContent[] = {
1206 0x30,0x81,0x99,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1207 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,
1208 0xf7,0x0d,0x01,0x07,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,
1209 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1210 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,
1211 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,
1212 0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,
1213 0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,
1214 0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,
1215 0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,
1216 0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1217 static const BYTE detachedSignedContent[] = {
1218 0x30,0x81,0xaa,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
1219 0x81,0x9c,0x30,0x81,0x99,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
1220 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,
1221 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,
1222 0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
1223 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,
1224 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,
1225 0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,
1226 0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,
1227 0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,
1228 0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,
1229 0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1230 static const BYTE signedBareContent[] = {
1231 0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1232 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,
1233 0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x31,0x77,
1234 0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,
1235 0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
1236 0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,
1237 0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,
1238 0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,
1239 0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,
1240 0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,
1241 0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1242 static const BYTE signedContent[] = {
1243 0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
1244 0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
1245 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
1246 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
1247 0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,
1248 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1249 0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1250 0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,
1251 0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,
1252 0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,
1253 0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,
1254 0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,
1255 0x0d };
1256 static const BYTE signedHash[] = {
1257 0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,
1258 0x2f };
1259 static const BYTE signedEncodedSigner[] = {
1260 0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,
1261 0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
1262 0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,
1263 0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,
1264 0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,
1265 0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,
1266 0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,
1267 0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1268 static BYTE cert[] = {
1269 0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
1270 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1271 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
1272 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
1273 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
1274 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
1275 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,
1276 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
1277 0xff,0x02,0x01,0x01 };
1278 static const BYTE signedWithCertEmptyBareContent[] = {
1279 0x30,0x81,0xce,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1280 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x7c,0x30,0x7a,
1281 0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,
1282 0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
1283 0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
1284 0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
1285 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
1286 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
1287 0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
1288 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
1289 0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,
1290 0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,
1291 0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
1292 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
1293 static const BYTE signedWithCertBareContent[] = {
1294 0x30,0x82,0x01,0x1f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,
1295 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,
1296 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa0,
1297 0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1298 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1299 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
1300 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1301 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
1302 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1303 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,
1304 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
1305 0x01,0xff,0x02,0x01,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,
1306 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1307 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,
1308 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,
1309 0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,
1310 0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,
1311 0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,
1312 0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,
1313 0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1314 static BYTE crl[] = { 0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1315 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1316 0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
1317 0x30,0x30,0x30,0x30,0x5a };
1318 static const BYTE signedWithCrlEmptyBareContent[] = {
1319 0x30,0x81,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1320 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa1,0x2e,0x30,0x2c,
1321 0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1322 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
1323 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x31,
1324 0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
1325 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
1326 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
1327 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
1328 static const BYTE signedWithCrlBareContent[] = {
1329 0x30,0x81,0xd1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1330 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,
1331 0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa1,0x2e,
1332 0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
1333 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,
1334 0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,
1335 0x5a,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,
1336 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1337 0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1338 0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,
1339 0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,
1340 0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,
1341 0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,
1342 0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,
1343 0xa8,0x0d };
1344 static const BYTE signedWithCertAndCrlEmptyBareContent[] = {
1345 0x30,0x81,0xfe,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1346 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x7c,0x30,0x7a,
1347 0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,
1348 0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
1349 0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
1350 0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
1351 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
1352 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
1353 0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
1354 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
1355 0x01,0x01,0xa1,0x2e,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1356 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1357 0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
1358 0x30,0x30,0x30,0x30,0x5a,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,
1359 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1360 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,
1361 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,
1362 0x04,0x00 };
1363 static const BYTE signedWithCertAndCrlBareContent[] = {
1364 0x30,0x82,0x01,0x4f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,
1365 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,
1366 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa0,
1367 0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1368 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1369 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
1370 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1371 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
1372 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1373 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,
1374 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
1375 0x01,0xff,0x02,0x01,0x01,0xa1,0x2e,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,
1376 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1377 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
1378 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x31,0x77,0x30,0x75,0x02,0x01,0x01,
1379 0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,
1380 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,
1381 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,
1382 0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,
1383 0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,
1384 0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,
1385 0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,
1386 0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1388 static void test_signed_msg_encoding(void)
1390 HCRYPTMSG msg;
1391 CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
1392 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
1393 CERT_INFO certInfo = { 0 };
1394 CERT_BLOB encodedCert = { sizeof(cert), cert };
1395 CRL_BLOB encodedCrl = { sizeof(crl), crl };
1396 BOOL ret;
1397 HCRYPTKEY key;
1398 DWORD size;
1400 certInfo.SerialNumber.cbData = sizeof(serialNum);
1401 certInfo.SerialNumber.pbData = serialNum;
1402 certInfo.Issuer.cbData = sizeof(encodedCommonName);
1403 certInfo.Issuer.pbData = encodedCommonName;
1404 signer.pCertInfo = &certInfo;
1405 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
1406 signInfo.cSigners = 1;
1407 signInfo.rgSigners = &signer;
1408 ret = CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1409 PROV_RSA_FULL, CRYPT_NEWKEYSET);
1410 if (!ret && GetLastError() == NTE_EXISTS)
1411 ret = CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1412 PROV_RSA_FULL, 0);
1413 ok(ret, "CryptAcquireContextW failed: %x\n", GetLastError());
1414 ret = CryptImportKey(signer.hCryptProv, (LPBYTE)privKey, sizeof(privKey),
1415 0, 0, &key);
1416 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
1418 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING,
1419 CMSG_DETACHED_FLAG, CMSG_SIGNED, &signInfo, NULL, NULL);
1420 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1422 check_param("detached signed empty bare content", msg,
1423 CMSG_BARE_CONTENT_PARAM, signedEmptyBareContent,
1424 sizeof(signedEmptyBareContent));
1425 check_param("detached signed empty content", msg, CMSG_CONTENT_PARAM,
1426 signedEmptyContent, sizeof(signedEmptyContent));
1427 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1428 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1429 check_param("detached signed hash", msg, CMSG_COMPUTED_HASH_PARAM,
1430 signedHash, sizeof(signedHash));
1431 check_param("detached signed bare content", msg, CMSG_BARE_CONTENT_PARAM,
1432 detachedSignedBareContent, sizeof(detachedSignedBareContent));
1433 check_param("detached signed content", msg, CMSG_CONTENT_PARAM,
1434 detachedSignedContent, sizeof(detachedSignedContent));
1435 SetLastError(0xdeadbeef);
1436 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 1, NULL, &size);
1437 ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
1438 "Expected CRYPT_E_INVALID_INDEX, got %x\n", GetLastError());
1439 check_param("detached signed encoded signer", msg, CMSG_ENCODED_SIGNER,
1440 signedEncodedSigner, sizeof(signedEncodedSigner));
1442 CryptMsgClose(msg);
1444 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1445 NULL, NULL);
1446 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1448 check_param("signed empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
1449 signedEmptyBareContent, sizeof(signedEmptyBareContent));
1450 check_param("signed empty content", msg, CMSG_CONTENT_PARAM,
1451 signedEmptyContent, sizeof(signedEmptyContent));
1452 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1453 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1454 check_param("signed bare content", msg, CMSG_BARE_CONTENT_PARAM,
1455 signedBareContent, sizeof(signedBareContent));
1456 check_param("signed content", msg, CMSG_CONTENT_PARAM,
1457 signedContent, sizeof(signedContent));
1459 CryptMsgClose(msg);
1461 signInfo.rgCertEncoded = &encodedCert;
1462 signInfo.cCertEncoded = 1;
1463 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1464 NULL, NULL);
1465 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1467 check_param("signed with cert empty bare content", msg,
1468 CMSG_BARE_CONTENT_PARAM, signedWithCertEmptyBareContent,
1469 sizeof(signedWithCertEmptyBareContent));
1470 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1471 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1472 check_param("signed with cert bare content", msg, CMSG_BARE_CONTENT_PARAM,
1473 signedWithCertBareContent, sizeof(signedWithCertBareContent));
1475 CryptMsgClose(msg);
1477 signInfo.cCertEncoded = 0;
1478 signInfo.rgCrlEncoded = &encodedCrl;
1479 signInfo.cCrlEncoded = 1;
1480 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1481 NULL, NULL);
1482 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1484 check_param("signed with crl empty bare content", msg,
1485 CMSG_BARE_CONTENT_PARAM, signedWithCrlEmptyBareContent,
1486 sizeof(signedWithCrlEmptyBareContent));
1487 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1488 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1489 check_param("signed with crl bare content", msg, CMSG_BARE_CONTENT_PARAM,
1490 signedWithCrlBareContent, sizeof(signedWithCrlBareContent));
1492 CryptMsgClose(msg);
1494 signInfo.cCertEncoded = 1;
1495 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1496 NULL, NULL);
1497 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1499 check_param("signed with cert and crl empty bare content", msg,
1500 CMSG_BARE_CONTENT_PARAM, signedWithCertAndCrlEmptyBareContent,
1501 sizeof(signedWithCertAndCrlEmptyBareContent));
1502 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1503 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1504 check_param("signed with cert and crl bare content", msg,
1505 CMSG_BARE_CONTENT_PARAM, signedWithCertAndCrlBareContent,
1506 sizeof(signedWithCertAndCrlBareContent));
1508 CryptMsgClose(msg);
1510 CryptDestroyKey(key);
1511 CryptReleaseContext(signer.hCryptProv, 0);
1512 CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL, PROV_RSA_FULL,
1513 CRYPT_DELETEKEYSET);
1516 static void test_signed_msg_get_param(void)
1518 BOOL ret;
1519 HCRYPTMSG msg;
1520 DWORD size, value = 0;
1521 CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
1522 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
1523 CERT_INFO certInfo = { 0 };
1525 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1526 NULL, NULL);
1527 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1529 /* Content and bare content are always gettable */
1530 size = 0;
1531 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
1532 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1533 size = 0;
1534 ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
1535 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1536 /* For "signed" messages, so is the version. */
1537 size = 0;
1538 ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, NULL, &size);
1539 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1540 size = sizeof(value);
1541 ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, (LPBYTE)&value, &size);
1542 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1543 ok(value == CMSG_SIGNED_DATA_V1, "Expected version 1, got %d\n", value);
1544 /* But for this message, with no signers, the hash and signer aren't
1545 * available.
1547 size = 0;
1548 SetLastError(0xdeadbeef);
1549 ret = CryptMsgGetParam(msg, CMSG_ENCODED_SIGNER, 0, NULL, &size);
1550 ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
1551 "Expected CRYPT_E_INVALID_INDEX, got %x\n", GetLastError());
1552 SetLastError(0xdeadbeef);
1553 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
1554 ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
1555 "Expected CRYPT_E_INVALID_INDEX, got %x\n", GetLastError());
1556 /* As usual, the type isn't available. */
1557 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
1558 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1559 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1561 CryptMsgClose(msg);
1563 certInfo.SerialNumber.cbData = sizeof(serialNum);
1564 certInfo.SerialNumber.pbData = serialNum;
1565 certInfo.Issuer.cbData = sizeof(encodedCommonName);
1566 certInfo.Issuer.pbData = encodedCommonName;
1567 signer.pCertInfo = &certInfo;
1568 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
1569 signInfo.cSigners = 1;
1570 signInfo.rgSigners = &signer;
1571 ret = CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1572 PROV_RSA_FULL, CRYPT_NEWKEYSET);
1573 if (!ret && GetLastError() == NTE_EXISTS)
1574 ret = CryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1575 PROV_RSA_FULL, 0);
1576 ok(ret, "CryptAcquireContextW failed: %x\n", GetLastError());
1577 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1578 NULL, NULL);
1579 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1581 /* This message, with one signer, has the hash and signer for index 0
1582 * available, but not for other indexes.
1584 size = 0;
1585 ret = CryptMsgGetParam(msg, CMSG_ENCODED_SIGNER, 0, NULL, &size);
1586 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
1587 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
1588 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
1589 size = 0;
1590 SetLastError(0xdeadbeef);
1591 ret = CryptMsgGetParam(msg, CMSG_ENCODED_SIGNER, 1, NULL, &size);
1592 ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
1593 "Expected CRYPT_E_INVALID_INDEX, got %x\n", GetLastError());
1594 SetLastError(0xdeadbeef);
1595 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 1, NULL, &size);
1596 ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
1597 "Expected CRYPT_E_INVALID_INDEX, got %x\n", GetLastError());
1598 /* As usual, the type isn't available. */
1599 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
1600 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1601 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1603 CryptMsgClose(msg);
1605 CryptReleaseContext(signer.hCryptProv, 0);
1606 CryptAcquireContextW(&signer.hCryptProv, cspNameW, MS_DEF_PROV_W,
1607 PROV_RSA_FULL, CRYPT_DELETEKEYSET);
1610 static void test_signed_msg(void)
1612 test_signed_msg_open();
1613 test_signed_msg_update();
1614 test_signed_msg_encoding();
1615 test_signed_msg_get_param();
1618 static CRYPT_DATA_BLOB b4 = { 0, NULL };
1619 static const struct update_accum a4 = { 1, &b4 };
1621 static const BYTE bogusOIDContent[] = {
1622 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x07,0xa0,0x02,
1623 0x04,0x00 };
1624 static const BYTE bogusHashContent[] = {
1625 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
1626 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1627 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1628 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x00,0xd6,0xc0,
1629 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1631 static void test_decode_msg_update(void)
1633 HCRYPTMSG msg;
1634 BOOL ret;
1635 CMSG_STREAM_INFO streamInfo = { 0 };
1636 DWORD i;
1637 struct update_accum accum = { 0, NULL };
1639 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1640 /* Update with a full message in a final update */
1641 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
1642 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1643 /* Can't update after a final update */
1644 SetLastError(0xdeadbeef);
1645 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
1646 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1647 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1648 CryptMsgClose(msg);
1650 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1651 /* Can't send a non-final update without streaming */
1652 SetLastError(0xdeadbeef);
1653 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1654 FALSE);
1655 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1656 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1657 /* A subsequent final update succeeds */
1658 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
1659 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1660 CryptMsgClose(msg);
1662 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1663 /* Updating a message that has a NULL stream callback fails */
1664 SetLastError(0xdeadbeef);
1665 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1666 FALSE);
1667 todo_wine
1668 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1669 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
1670 /* Changing the callback pointer after the fact yields the same error (so
1671 * the message must copy the stream info, not just store a pointer to it)
1673 streamInfo.pfnStreamOutput = nop_stream_output;
1674 SetLastError(0xdeadbeef);
1675 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1676 FALSE);
1677 todo_wine
1678 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1679 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
1680 CryptMsgClose(msg);
1682 /* Empty non-final updates are allowed when streaming.. */
1683 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1684 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1685 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1686 /* but final updates aren't when not enough data has been received. */
1687 SetLastError(0xdeadbeef);
1688 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1689 todo_wine
1690 ok(!ret && GetLastError() == CRYPT_E_STREAM_INSUFFICIENT_DATA,
1691 "Expected CRYPT_E_STREAM_INSUFFICIENT_DATA, got %x\n", GetLastError());
1692 CryptMsgClose(msg);
1694 /* Updating the message byte by byte is legal */
1695 streamInfo.pfnStreamOutput = accumulating_stream_output;
1696 streamInfo.pvArg = &accum;
1697 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1698 for (i = 0, ret = TRUE; ret && i < sizeof(dataEmptyContent); i++)
1699 ret = CryptMsgUpdate(msg, &dataEmptyContent[i], 1, FALSE);
1700 ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
1701 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1702 ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
1703 CryptMsgClose(msg);
1704 todo_wine
1705 check_updates("byte-by-byte empty content", &a4, &accum);
1706 free_updates(&accum);
1708 /* Decoding bogus content fails in non-streaming mode.. */
1709 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1710 SetLastError(0xdeadbeef);
1711 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1712 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1713 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1714 CryptMsgClose(msg);
1715 /* and as the final update in streaming mode.. */
1716 streamInfo.pfnStreamOutput = nop_stream_output;
1717 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1718 SetLastError(0xdeadbeef);
1719 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1720 todo_wine
1721 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1722 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1723 CryptMsgClose(msg);
1724 /* and even as a non-final update in streaming mode. */
1725 streamInfo.pfnStreamOutput = nop_stream_output;
1726 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1727 SetLastError(0xdeadbeef);
1728 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1729 todo_wine
1730 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1731 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1732 CryptMsgClose(msg);
1734 /* An empty message can be opened with indetermined type.. */
1735 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1736 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1737 TRUE);
1738 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1739 /* but decoding it as an explicitly typed message fails. */
1740 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
1741 NULL);
1742 SetLastError(0xdeadbeef);
1743 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1744 TRUE);
1745 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1746 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1747 CryptMsgClose(msg);
1748 /* On the other hand, decoding the bare content of an empty message fails
1749 * with unspecified type..
1751 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1752 SetLastError(0xdeadbeef);
1753 ret = CryptMsgUpdate(msg, dataEmptyBareContent,
1754 sizeof(dataEmptyBareContent), TRUE);
1755 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1756 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1757 CryptMsgClose(msg);
1758 /* but succeeds with explicit type. */
1759 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
1760 NULL);
1761 ret = CryptMsgUpdate(msg, dataEmptyBareContent,
1762 sizeof(dataEmptyBareContent), TRUE);
1763 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1764 CryptMsgClose(msg);
1766 /* Decoding valid content with an unsupported OID fails */
1767 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1768 SetLastError(0xdeadbeef);
1769 ret = CryptMsgUpdate(msg, bogusOIDContent, sizeof(bogusOIDContent), TRUE);
1770 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1771 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1772 CryptMsgClose(msg);
1774 /* Similarly, opening an empty hash with unspecified type succeeds.. */
1775 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1776 SetLastError(0xdeadbeef);
1777 ret = CryptMsgUpdate(msg, hashEmptyContent, sizeof(hashEmptyContent), TRUE);
1778 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1779 CryptMsgClose(msg);
1780 /* while with specified type it fails. */
1781 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1782 NULL);
1783 SetLastError(0xdeadbeef);
1784 ret = CryptMsgUpdate(msg, hashEmptyContent, sizeof(hashEmptyContent), TRUE);
1785 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1786 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1787 CryptMsgClose(msg);
1788 /* On the other hand, decoding the bare content of an empty hash message
1789 * fails with unspecified type..
1791 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1792 SetLastError(0xdeadbeef);
1793 ret = CryptMsgUpdate(msg, hashEmptyBareContent,
1794 sizeof(hashEmptyBareContent), TRUE);
1795 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1796 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1797 CryptMsgClose(msg);
1798 /* but succeeds with explicit type. */
1799 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1800 NULL);
1801 ret = CryptMsgUpdate(msg, hashEmptyBareContent,
1802 sizeof(hashEmptyBareContent), TRUE);
1803 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1804 CryptMsgClose(msg);
1806 /* And again, opening a (non-empty) hash message with unspecified type
1807 * succeeds..
1809 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1810 SetLastError(0xdeadbeef);
1811 ret = CryptMsgUpdate(msg, hashContent, sizeof(hashContent), TRUE);
1812 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1813 CryptMsgClose(msg);
1814 /* while with specified type it fails.. */
1815 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1816 NULL);
1817 SetLastError(0xdeadbeef);
1818 ret = CryptMsgUpdate(msg, hashContent, sizeof(hashContent), TRUE);
1819 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1820 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1821 CryptMsgClose(msg);
1822 /* and decoding the bare content of a non-empty hash message fails with
1823 * unspecified type..
1825 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1826 SetLastError(0xdeadbeef);
1827 ret = CryptMsgUpdate(msg, hashBareContent, sizeof(hashBareContent), TRUE);
1828 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1829 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1830 CryptMsgClose(msg);
1831 /* but succeeds with explicit type. */
1832 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1833 NULL);
1834 ret = CryptMsgUpdate(msg, hashBareContent, sizeof(hashBareContent), TRUE);
1835 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1836 CryptMsgClose(msg);
1838 /* Opening a (non-empty) hash message with unspecified type and a bogus
1839 * hash value succeeds..
1841 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1842 SetLastError(0xdeadbeef);
1843 ret = CryptMsgUpdate(msg, bogusHashContent, sizeof(bogusHashContent), TRUE);
1844 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1845 CryptMsgClose(msg);
1848 static const BYTE hashParam[] = { 0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,
1849 0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1851 static void test_decode_msg_get_param(void)
1853 HCRYPTMSG msg;
1854 BOOL ret;
1855 DWORD size = 0, version;
1856 LPBYTE buf;
1858 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1859 SetLastError(0xdeadbeef);
1860 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
1861 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1862 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1863 ret = CryptMsgUpdate(msg, dataContent, sizeof(dataContent), TRUE);
1864 check_param("data content", msg, CMSG_CONTENT_PARAM, msgData,
1865 sizeof(msgData));
1866 CryptMsgClose(msg);
1868 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1869 ret = CryptMsgUpdate(msg, hashEmptyContent, sizeof(hashEmptyContent), TRUE);
1870 check_param("empty hash content", msg, CMSG_CONTENT_PARAM, NULL, 0);
1871 check_param("empty hash hash data", msg, CMSG_HASH_DATA_PARAM, NULL, 0);
1872 check_param("empty hash computed hash", msg, CMSG_COMPUTED_HASH_PARAM,
1873 emptyHashParam, sizeof(emptyHashParam));
1874 CryptMsgClose(msg);
1875 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1876 ret = CryptMsgUpdate(msg, hashContent, sizeof(hashContent), TRUE);
1877 check_param("hash content", msg, CMSG_CONTENT_PARAM, msgData,
1878 sizeof(msgData));
1879 check_param("hash hash data", msg, CMSG_HASH_DATA_PARAM, hashParam,
1880 sizeof(hashParam));
1881 check_param("hash computed hash", msg, CMSG_COMPUTED_HASH_PARAM,
1882 hashParam, sizeof(hashParam));
1883 /* Curiously, getting the hash of index 1 succeeds, even though there's
1884 * only one hash.
1886 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 1, NULL, &size);
1887 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1888 buf = CryptMemAlloc(size);
1889 if (buf)
1891 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 1, buf, &size);
1892 ok(size == sizeof(hashParam), "Unexpected size %d\n", size);
1893 ok(!memcmp(buf, hashParam, size), "Unexpected value\n");
1894 CryptMemFree(buf);
1896 check_param("hash inner OID", msg, CMSG_INNER_CONTENT_TYPE_PARAM,
1897 (const BYTE *)szOID_RSA_data, strlen(szOID_RSA_data) + 1);
1898 version = CMSG_HASHED_DATA_V0;
1899 check_param("hash version", msg, CMSG_VERSION_PARAM, (const BYTE *)&version,
1900 sizeof(version));
1901 CryptMsgClose(msg);
1904 static void test_decode_msg(void)
1906 test_decode_msg_update();
1907 test_decode_msg_get_param();
1910 START_TEST(msg)
1912 /* Basic parameter checking tests */
1913 test_msg_open_to_encode();
1914 test_msg_open_to_decode();
1915 test_msg_get_param();
1916 test_msg_close();
1918 /* Message-type specific tests */
1919 test_data_msg();
1920 test_hash_msg();
1921 test_signed_msg();
1922 test_decode_msg();