push 4d5485f9b89f417d46b39b93e8d940437007f325
[wine/hacks.git] / dlls / crypt32 / tests / msg.c
blob15f6baa67ffb9e5927759fca1f8177acb91a027b
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 BOOL (WINAPI * pCryptAcquireContextW)
33 (HCRYPTPROV *, LPCWSTR, LPCWSTR, DWORD, DWORD);
35 static void init_function_pointers(void)
37 HMODULE hAdvapi32 = GetModuleHandleA("advapi32.dll");
39 #define GET_PROC(dll, func) \
40 p ## func = (void *)GetProcAddress(dll, #func); \
41 if(!p ## func) \
42 trace("GetProcAddress(%s) failed\n", #func);
44 GET_PROC(hAdvapi32, CryptAcquireContextW)
46 #undef GET_PROC
49 static void test_msg_open_to_encode(void)
51 HCRYPTMSG msg;
53 /* Crash
54 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, NULL,
55 NULL, NULL);
56 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, NULL, NULL,
57 NULL);
58 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, NULL, NULL,
59 NULL);
62 /* Bad encodings */
63 SetLastError(0xdeadbeef);
64 msg = CryptMsgOpenToEncode(0, 0, 0, NULL, NULL, NULL);
65 ok(!msg && GetLastError() == E_INVALIDARG,
66 "Expected E_INVALIDARG, got %x\n", GetLastError());
67 SetLastError(0xdeadbeef);
68 msg = CryptMsgOpenToEncode(X509_ASN_ENCODING, 0, 0, NULL, NULL, NULL);
69 ok(!msg && GetLastError() == E_INVALIDARG,
70 "Expected E_INVALIDARG, got %x\n", GetLastError());
72 /* Bad message types */
73 SetLastError(0xdeadbeef);
74 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, 0, NULL, NULL, NULL);
75 ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
76 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
77 SetLastError(0xdeadbeef);
78 msg = CryptMsgOpenToEncode(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, 0,
79 NULL, NULL, NULL);
80 ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
81 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
82 SetLastError(0xdeadbeef);
83 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0,
84 CMSG_SIGNED_AND_ENVELOPED, NULL, NULL, NULL);
85 ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
86 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
87 SetLastError(0xdeadbeef);
88 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, NULL,
89 NULL, NULL);
90 ok(!msg && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
91 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
94 static void test_msg_open_to_decode(void)
96 HCRYPTMSG msg;
97 CMSG_STREAM_INFO streamInfo = { 0 };
99 SetLastError(0xdeadbeef);
100 msg = CryptMsgOpenToDecode(0, 0, 0, 0, NULL, NULL);
101 ok(!msg && GetLastError() == E_INVALIDARG,
102 "Expected E_INVALIDARG, got %x\n", GetLastError());
104 /* Bad encodings */
105 SetLastError(0xdeadbeef);
106 msg = CryptMsgOpenToDecode(X509_ASN_ENCODING, 0, 0, 0, NULL, NULL);
107 ok(!msg && GetLastError() == E_INVALIDARG,
108 "Expected E_INVALIDARG, got %x\n", GetLastError());
109 SetLastError(0xdeadbeef);
110 msg = CryptMsgOpenToDecode(X509_ASN_ENCODING, 0, CMSG_DATA, 0, NULL, NULL);
111 ok(!msg && GetLastError() == E_INVALIDARG,
112 "Expected E_INVALIDARG, got %x\n", GetLastError());
114 /* The message type can be explicit... */
115 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
116 NULL);
117 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
118 CryptMsgClose(msg);
119 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, 0, NULL,
120 NULL);
121 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
122 CryptMsgClose(msg);
123 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
124 NULL);
125 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
126 CryptMsgClose(msg);
127 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
128 NULL);
129 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
130 CryptMsgClose(msg);
131 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0,
132 CMSG_SIGNED_AND_ENVELOPED, 0, NULL, NULL);
133 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
134 CryptMsgClose(msg);
135 /* or implicit.. */
136 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
137 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
138 CryptMsgClose(msg);
139 /* or even invalid. */
140 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, 0, NULL,
141 NULL);
142 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
143 CryptMsgClose(msg);
144 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 1000, 0, NULL, NULL);
145 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
146 CryptMsgClose(msg);
148 /* And even though the stream info parameter "must be set to NULL" for
149 * CMSG_HASHED, it's still accepted.
151 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
152 &streamInfo);
153 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
154 CryptMsgClose(msg);
157 static void test_msg_get_param(void)
159 BOOL ret;
160 HCRYPTMSG msg;
161 DWORD size, i, value;
162 CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
163 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
165 /* Crash
166 ret = CryptMsgGetParam(NULL, 0, 0, NULL, NULL);
167 ret = CryptMsgGetParam(NULL, 0, 0, NULL, &size);
168 ret = CryptMsgGetParam(msg, 0, 0, NULL, NULL);
171 /* Decoded messages */
172 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
173 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
174 /* For decoded messages, the type is always available */
175 size = 0;
176 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
177 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
178 size = sizeof(value);
179 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
180 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
181 /* For this (empty) message, the type isn't set */
182 ok(value == 0, "Expected type 0, got %d\n", value);
183 CryptMsgClose(msg);
185 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
186 NULL);
187 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
188 /* For explicitly typed messages, the type is known. */
189 size = sizeof(value);
190 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
191 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
192 ok(value == CMSG_DATA, "Expected CMSG_DATA, got %d\n", value);
193 for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++)
195 size = 0;
196 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
197 ok(!ret, "Parameter %d: expected failure\n", i);
199 CryptMsgClose(msg);
201 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENVELOPED, 0, NULL,
202 NULL);
203 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
204 size = sizeof(value);
205 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
206 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
207 ok(value == CMSG_ENVELOPED, "Expected CMSG_ENVELOPED, got %d\n", value);
208 for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++)
210 size = 0;
211 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
212 ok(!ret, "Parameter %d: expected failure\n", i);
214 CryptMsgClose(msg);
216 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
217 NULL);
218 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
219 size = sizeof(value);
220 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
221 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
222 ok(value == CMSG_HASHED, "Expected CMSG_HASHED, got %d\n", value);
223 for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++)
225 size = 0;
226 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
227 ok(!ret, "Parameter %d: expected failure\n", i);
229 CryptMsgClose(msg);
231 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
232 NULL);
233 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
234 size = sizeof(value);
235 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
236 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
237 ok(value == CMSG_SIGNED, "Expected CMSG_SIGNED, got %d\n", value);
238 for (i = CMSG_CONTENT_PARAM; i <= CMSG_CMS_SIGNER_INFO_PARAM; i++)
240 size = 0;
241 ret = CryptMsgGetParam(msg, i, 0, NULL, &size);
242 ok(!ret, "Parameter %d: expected failure\n", i);
244 CryptMsgClose(msg);
246 /* Explicitly typed messages get their types set, even if they're invalid */
247 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_ENCRYPTED, 0, NULL,
248 NULL);
249 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
250 size = sizeof(value);
251 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
252 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
253 ok(value == CMSG_ENCRYPTED, "Expected CMSG_ENCRYPTED, got %d\n", value);
254 CryptMsgClose(msg);
256 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 1000, 0, NULL, NULL);
257 ok(msg != NULL, "CryptMsgOpenToDecode failed: %x\n", GetLastError());
258 size = sizeof(value);
259 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, (LPBYTE)&value, &size);
260 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
261 ok(value == 1000, "Expected 1000, got %d\n", value);
262 CryptMsgClose(msg);
265 static void test_msg_close(void)
267 BOOL ret;
268 HCRYPTMSG msg;
270 /* NULL succeeds.. */
271 ret = CryptMsgClose(NULL);
272 ok(ret, "CryptMsgClose failed: %x\n", GetLastError());
273 /* but an arbitrary pointer crashes. */
274 if (0)
275 ret = CryptMsgClose((HCRYPTMSG)1);
276 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
277 NULL);
278 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
279 ret = CryptMsgClose(msg);
280 ok(ret, "CryptMsgClose failed: %x\n", GetLastError());
283 static void check_param(LPCSTR test, HCRYPTMSG msg, DWORD param,
284 const BYTE *expected, DWORD expectedSize)
286 DWORD size;
287 LPBYTE buf;
288 BOOL ret;
290 size = 0xdeadbeef;
291 ret = CryptMsgGetParam(msg, param, 0, NULL, &size);
292 ok(ret, "%s: CryptMsgGetParam failed: %08x\n", test, GetLastError());
293 buf = HeapAlloc(GetProcessHeap(), 0, size);
294 ret = CryptMsgGetParam(msg, param, 0, buf, &size);
295 ok(ret, "%s: CryptMsgGetParam failed: %08x\n", test, GetLastError());
296 ok(size == expectedSize, "%s: expected size %d, got %d\n", test,
297 expectedSize, size);
298 if (size == expectedSize && size)
299 ok(!memcmp(buf, expected, size), "%s: unexpected data\n", test);
300 HeapFree(GetProcessHeap(), 0, buf);
303 static void test_data_msg_open(void)
305 HCRYPTMSG msg;
306 CMSG_HASHED_ENCODE_INFO hashInfo = { 0 };
307 CMSG_STREAM_INFO streamInfo = { 0 };
308 char oid[] = "1.2.3";
310 /* The data message type takes no additional info */
311 SetLastError(0xdeadbeef);
312 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, &hashInfo,
313 NULL, NULL);
314 ok(!msg && GetLastError() == E_INVALIDARG,
315 "Expected E_INVALIDARG, got %x\n", GetLastError());
316 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
317 NULL);
318 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
319 CryptMsgClose(msg);
321 /* An empty stream info is allowed. */
322 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
323 &streamInfo);
324 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
325 CryptMsgClose(msg);
327 /* Passing a bogus inner OID succeeds for a non-streamed message.. */
328 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, oid,
329 NULL);
330 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
331 CryptMsgClose(msg);
332 /* and still succeeds when CMSG_DETACHED_FLAG is passed.. */
333 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
334 CMSG_DATA, NULL, oid, NULL);
335 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
336 CryptMsgClose(msg);
337 /* and when a stream info is given, even though you're not supposed to be
338 * able to use anything but szOID_RSA_data when streaming is being used.
340 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
341 CMSG_DATA, NULL, oid, &streamInfo);
342 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
343 CryptMsgClose(msg);
346 static const BYTE msgData[] = { 1, 2, 3, 4 };
348 static BOOL WINAPI nop_stream_output(const void *pvArg, BYTE *pb, DWORD cb,
349 BOOL final)
351 return TRUE;
354 static void test_data_msg_update(void)
356 HCRYPTMSG msg;
357 BOOL ret;
358 CMSG_STREAM_INFO streamInfo = { 0 };
360 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
361 NULL);
362 /* Can't update a message that wasn't opened detached with final = FALSE */
363 SetLastError(0xdeadbeef);
364 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
365 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
366 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
367 /* Updating it with final = TRUE succeeds */
368 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
369 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
370 /* Any subsequent update will fail, as the last was final */
371 SetLastError(0xdeadbeef);
372 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
373 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
374 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
375 CryptMsgClose(msg);
377 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
378 NULL);
379 /* Can't update a message with no data */
380 SetLastError(0xdeadbeef);
381 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
382 ok(!ret && GetLastError() == E_INVALIDARG,
383 "Expected E_INVALIDARG, got %x\n", GetLastError());
384 /* Curiously, a valid update will now fail as well, presumably because of
385 * the last (invalid, but final) update.
387 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
388 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
389 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
390 CryptMsgClose(msg);
392 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
393 CMSG_DATA, NULL, NULL, NULL);
394 /* Doesn't appear to be able to update CMSG-DATA with non-final updates */
395 SetLastError(0xdeadbeef);
396 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
397 ok(!ret && GetLastError() == E_INVALIDARG,
398 "Expected E_INVALIDARG, got %x\n", GetLastError());
399 SetLastError(0xdeadbeef);
400 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
401 ok(!ret && GetLastError() == E_INVALIDARG,
402 "Expected E_INVALIDARG, got %x\n", GetLastError());
403 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
404 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
405 CryptMsgClose(msg);
407 /* Calling update after opening with an empty stream info (with a bogus
408 * output function) yields an error:
410 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
411 &streamInfo);
412 SetLastError(0xdeadbeef);
413 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
414 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
415 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
416 CryptMsgClose(msg);
417 /* Calling update with a valid output function succeeds, even if the data
418 * exceeds the size specified in the stream info.
420 streamInfo.pfnStreamOutput = nop_stream_output;
421 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
422 &streamInfo);
423 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
424 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
425 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
426 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
427 CryptMsgClose(msg);
430 static void test_data_msg_get_param(void)
432 HCRYPTMSG msg;
433 DWORD size;
434 BOOL ret;
435 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
437 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
438 NULL);
440 /* Content and bare content are always gettable when not streaming */
441 size = 0;
442 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
443 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
444 size = 0;
445 ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
446 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
447 /* But for this type of message, the signer and hash aren't applicable,
448 * and the type isn't available.
450 size = 0;
451 SetLastError(0xdeadbeef);
452 ret = CryptMsgGetParam(msg, CMSG_ENCODED_SIGNER, 0, NULL, &size);
453 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
454 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
455 SetLastError(0xdeadbeef);
456 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
457 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
458 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
459 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
460 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
461 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
462 CryptMsgClose(msg);
464 /* Can't get content or bare content when streaming */
465 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
466 NULL, &streamInfo);
467 SetLastError(0xdeadbeef);
468 ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
469 ok(!ret && GetLastError() == E_INVALIDARG,
470 "Expected E_INVALIDARG, got %x\n", GetLastError());
471 SetLastError(0xdeadbeef);
472 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
473 ok(!ret && GetLastError() == E_INVALIDARG,
474 "Expected E_INVALIDARG, got %x\n", GetLastError());
475 CryptMsgClose(msg);
478 static const BYTE dataEmptyBareContent[] = { 0x04,0x00 };
479 static const BYTE dataEmptyContent[] = {
480 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x02,
481 0x04,0x00 };
482 static const BYTE dataBareContent[] = { 0x04,0x04,0x01,0x02,0x03,0x04 };
483 static const BYTE dataContent[] = {
484 0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,
485 0x04,0x04,0x01,0x02,0x03,0x04 };
487 struct update_accum
489 DWORD cUpdates;
490 CRYPT_DATA_BLOB *updates;
493 static BOOL WINAPI accumulating_stream_output(const void *pvArg, BYTE *pb,
494 DWORD cb, BOOL final)
496 struct update_accum *accum = (struct update_accum *)pvArg;
497 BOOL ret = FALSE;
499 if (accum->cUpdates)
500 accum->updates = CryptMemRealloc(accum->updates,
501 (accum->cUpdates + 1) * sizeof(CRYPT_DATA_BLOB));
502 else
503 accum->updates = CryptMemAlloc(sizeof(CRYPT_DATA_BLOB));
504 if (accum->updates)
506 CRYPT_DATA_BLOB *blob = &accum->updates[accum->cUpdates];
508 blob->pbData = CryptMemAlloc(cb);
509 if (blob->pbData)
511 memcpy(blob->pbData, pb, cb);
512 blob->cbData = cb;
513 ret = TRUE;
515 accum->cUpdates++;
517 return ret;
520 /* The updates of a (bogus) definite-length encoded message */
521 static BYTE u1[] = { 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
522 0x07,0x01,0xa0,0x02,0x04,0x00 };
523 static BYTE u2[] = { 0x01,0x02,0x03,0x04 };
524 static CRYPT_DATA_BLOB b1[] = {
525 { sizeof(u1), u1 },
526 { sizeof(u2), u2 },
527 { sizeof(u2), u2 },
529 static const struct update_accum a1 = { sizeof(b1) / sizeof(b1[0]), b1 };
530 /* The updates of a definite-length encoded message */
531 static BYTE u3[] = { 0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
532 0x07,0x01,0xa0,0x06,0x04,0x04 };
533 static CRYPT_DATA_BLOB b2[] = {
534 { sizeof(u3), u3 },
535 { sizeof(u2), u2 },
537 static const struct update_accum a2 = { sizeof(b2) / sizeof(b2[0]), b2 };
538 /* The updates of an indefinite-length encoded message */
539 static BYTE u4[] = { 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
540 0x07,0x01,0xa0,0x80,0x24,0x80 };
541 static BYTE u5[] = { 0x04,0x04 };
542 static BYTE u6[] = { 0x00,0x00,0x00,0x00,0x00,0x00 };
543 static CRYPT_DATA_BLOB b3[] = {
544 { sizeof(u4), u4 },
545 { sizeof(u5), u5 },
546 { sizeof(u2), u2 },
547 { sizeof(u5), u5 },
548 { sizeof(u2), u2 },
549 { sizeof(u6), u6 },
551 static const struct update_accum a3 = { sizeof(b3) / sizeof(b3[0]), b3 };
553 static void check_updates(LPCSTR header, const struct update_accum *expected,
554 const struct update_accum *got)
556 DWORD i;
558 ok(expected->cUpdates == got->cUpdates,
559 "%s: expected %d updates, got %d\n", header, expected->cUpdates,
560 got->cUpdates);
561 if (expected->cUpdates == got->cUpdates)
562 for (i = 0; i < min(expected->cUpdates, got->cUpdates); i++)
564 ok(expected->updates[i].cbData == got->updates[i].cbData,
565 "%s, update %d: expected %d bytes, got %d\n", header, i,
566 expected->updates[i].cbData, got->updates[i].cbData);
567 if (expected->updates[i].cbData && expected->updates[i].cbData ==
568 got->updates[i].cbData)
569 ok(!memcmp(expected->updates[i].pbData, got->updates[i].pbData,
570 got->updates[i].cbData), "%s, update %d: unexpected value\n",
571 header, i);
575 /* Frees the updates stored in accum */
576 static void free_updates(struct update_accum *accum)
578 DWORD i;
580 for (i = 0; i < accum->cUpdates; i++)
581 CryptMemFree(accum->updates[i].pbData);
582 CryptMemFree(accum->updates);
583 accum->updates = NULL;
584 accum->cUpdates = 0;
587 static void test_data_msg_encoding(void)
589 HCRYPTMSG msg;
590 BOOL ret;
591 static char oid[] = "1.2.3";
592 struct update_accum accum = { 0, NULL };
593 CMSG_STREAM_INFO streamInfo = { 0, accumulating_stream_output, &accum };
595 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, NULL,
596 NULL);
597 check_param("data empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
598 dataEmptyBareContent, sizeof(dataEmptyBareContent));
599 check_param("data empty content", msg, CMSG_CONTENT_PARAM, dataEmptyContent,
600 sizeof(dataEmptyContent));
601 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
602 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
603 check_param("data bare content", msg, CMSG_BARE_CONTENT_PARAM,
604 dataBareContent, sizeof(dataBareContent));
605 check_param("data content", msg, CMSG_CONTENT_PARAM, dataContent,
606 sizeof(dataContent));
607 CryptMsgClose(msg);
608 /* Same test, but with CMSG_BARE_CONTENT_FLAG set */
609 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_BARE_CONTENT_FLAG,
610 CMSG_DATA, NULL, NULL, NULL);
611 check_param("data empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
612 dataEmptyBareContent, sizeof(dataEmptyBareContent));
613 check_param("data empty content", msg, CMSG_CONTENT_PARAM, dataEmptyContent,
614 sizeof(dataEmptyContent));
615 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
616 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
617 check_param("data bare content", msg, CMSG_BARE_CONTENT_PARAM,
618 dataBareContent, sizeof(dataBareContent));
619 check_param("data content", msg, CMSG_CONTENT_PARAM, dataContent,
620 sizeof(dataContent));
621 CryptMsgClose(msg);
622 /* The inner OID is apparently ignored */
623 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL, oid,
624 NULL);
625 check_param("data bogus oid bare content", msg, CMSG_BARE_CONTENT_PARAM,
626 dataEmptyBareContent, sizeof(dataEmptyBareContent));
627 check_param("data bogus oid content", msg, CMSG_CONTENT_PARAM,
628 dataEmptyContent, sizeof(dataEmptyContent));
629 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
630 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
631 check_param("data bare content", msg, CMSG_BARE_CONTENT_PARAM,
632 dataBareContent, sizeof(dataBareContent));
633 check_param("data content", msg, CMSG_CONTENT_PARAM, dataContent,
634 sizeof(dataContent));
635 CryptMsgClose(msg);
636 /* A streaming message is DER encoded if the length is not 0xffffffff, but
637 * curiously, updates aren't validated to make sure they don't exceed the
638 * stated length. (The resulting output will of course fail to decode.)
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 check_updates("bogus data message with definite length", &a1, &accum);
646 free_updates(&accum);
647 /* A valid definite-length encoding: */
648 streamInfo.cbContent = sizeof(msgData);
649 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
650 NULL, &streamInfo);
651 CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
652 CryptMsgClose(msg);
653 check_updates("data message with definite length", &a2, &accum);
654 free_updates(&accum);
655 /* An indefinite-length encoding: */
656 streamInfo.cbContent = 0xffffffff;
657 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, NULL,
658 NULL, &streamInfo);
659 CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
660 CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
661 CryptMsgClose(msg);
662 todo_wine
663 check_updates("data message with indefinite length", &a3, &accum);
664 free_updates(&accum);
667 static void test_data_msg(void)
669 test_data_msg_open();
670 test_data_msg_update();
671 test_data_msg_get_param();
672 test_data_msg_encoding();
675 static void test_hash_msg_open(void)
677 HCRYPTMSG msg;
678 CMSG_HASHED_ENCODE_INFO hashInfo = { 0 };
679 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
681 SetLastError(0xdeadbeef);
682 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
683 NULL, NULL);
684 ok(!msg && GetLastError() == E_INVALIDARG,
685 "Expected E_INVALIDARG, got %x\n", GetLastError());
686 hashInfo.cbSize = sizeof(hashInfo);
687 SetLastError(0xdeadbeef);
688 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
689 NULL, NULL);
690 ok(!msg && GetLastError() == CRYPT_E_UNKNOWN_ALGO,
691 "Expected CRYPT_E_UNKNOWN_ALGO, got %x\n", GetLastError());
692 hashInfo.HashAlgorithm.pszObjId = oid_rsa_md5;
693 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
694 NULL, NULL);
695 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
696 CryptMsgClose(msg);
697 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
698 CMSG_HASHED, &hashInfo, NULL, NULL);
699 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
700 CryptMsgClose(msg);
701 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
702 CMSG_HASHED, &hashInfo, NULL, &streamInfo);
703 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
704 CryptMsgClose(msg);
707 static void test_hash_msg_update(void)
709 HCRYPTMSG msg;
710 BOOL ret;
711 CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0,
712 { oid_rsa_md5, { 0, NULL } }, NULL };
713 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
715 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
716 CMSG_HASHED, &hashInfo, NULL, NULL);
717 /* Detached hashed messages opened in non-streaming mode allow non-final
718 * updates..
720 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
721 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
722 /* including non-final updates with no data.. */
723 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
724 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
725 /* and final updates with no data. */
726 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
727 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
728 /* But no updates are allowed after the final update. */
729 SetLastError(0xdeadbeef);
730 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
731 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
732 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
733 SetLastError(0xdeadbeef);
734 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
735 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
736 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
737 CryptMsgClose(msg);
738 /* Non-detached messages, in contrast, don't allow non-final updates in
739 * non-streaming mode.
741 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
742 NULL, NULL);
743 SetLastError(0xdeadbeef);
744 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
745 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
746 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
747 /* Final updates (including empty ones) are allowed. */
748 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
749 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
750 CryptMsgClose(msg);
751 /* And, of course, streaming mode allows non-final updates */
752 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
753 NULL, &streamInfo);
754 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
755 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
756 CryptMsgClose(msg);
757 /* Setting pfnStreamOutput to NULL results in no error. (In what appears
758 * to be a bug, it isn't actually used - see encoding tests.)
760 streamInfo.pfnStreamOutput = NULL;
761 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
762 NULL, &streamInfo);
763 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
764 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
765 CryptMsgClose(msg);
768 static const BYTE emptyHashParam[] = {
769 0xd4,0x1d,0x8c,0xd9,0x8f,0x00,0xb2,0x04,0xe9,0x80,0x09,0x98,0xec,0xf8,0x42,
770 0x7e };
772 static void test_hash_msg_get_param(void)
774 HCRYPTMSG msg;
775 BOOL ret;
776 CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0,
777 { oid_rsa_md5, { 0, NULL } }, NULL };
778 DWORD size, value;
779 CMSG_STREAM_INFO streamInfo = { 0, nop_stream_output, NULL };
780 BYTE buf[16];
782 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
783 NULL, NULL);
784 /* Content and bare content are always gettable for non-streamed messages */
785 size = 0;
786 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
787 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
788 size = 0;
789 ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
790 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
791 /* The hash is also available. */
792 size = 0;
793 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
794 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
795 ok(size == sizeof(buf), "Unexpected size %d\n", size);
796 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, buf, &size);
797 if (size == sizeof(buf))
798 ok(!memcmp(buf, emptyHashParam, size), "Unexpected value\n");
799 /* By getting the hash, further updates are not allowed */
800 SetLastError(0xdeadbeef);
801 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
802 ok(!ret && GetLastError() == NTE_BAD_HASH_STATE,
803 "Expected NTE_BAD_HASH_STATE, got %x\n", GetLastError());
804 /* The version is also available, and should be zero for this message. */
805 size = 0;
806 ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, NULL, &size);
807 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
808 size = sizeof(value);
809 ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, (LPBYTE)&value, &size);
810 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
811 ok(value == 0, "Expected version 0, got %d\n", value);
812 /* As usual, the type isn't available. */
813 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
814 ok(!ret, "Expected failure\n");
815 CryptMsgClose(msg);
817 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
818 NULL, &streamInfo);
819 /* Streamed messages don't allow you to get the content or bare content. */
820 SetLastError(0xdeadbeef);
821 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
822 ok(!ret && GetLastError() == E_INVALIDARG,
823 "Expected E_INVALIDARG, got %x\n", GetLastError());
824 SetLastError(0xdeadbeef);
825 ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
826 ok(!ret && GetLastError() == E_INVALIDARG,
827 "Expected E_INVALIDARG, got %x\n", GetLastError());
828 /* The hash is still available. */
829 size = 0;
830 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
831 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
832 ok(size == sizeof(buf), "Unexpected size %d\n", size);
833 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, buf, &size);
834 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
835 if (size == sizeof(buf))
836 ok(!memcmp(buf, emptyHashParam, size), "Unexpected value\n");
837 /* After updating the hash, further updates aren't allowed on streamed
838 * messages either.
840 SetLastError(0xdeadbeef);
841 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
842 ok(!ret && GetLastError() == NTE_BAD_HASH_STATE,
843 "Expected NTE_BAD_HASH_STATE, got %x\n", GetLastError());
844 CryptMsgClose(msg);
847 static const BYTE hashEmptyBareContent[] = {
848 0x30,0x17,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
849 0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x04,0x00 };
850 static const BYTE hashEmptyContent[] = {
851 0x30,0x26,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x19,
852 0x30,0x17,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
853 0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x04,0x00 };
854 static const BYTE hashBareContent[] = {
855 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
856 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
857 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
858 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
859 static const BYTE hashContent[] = {
860 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
861 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
862 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
863 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
864 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
866 static const BYTE detachedHashNonFinalBareContent[] = {
867 0x30,0x20,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
868 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
869 0x07,0x01,0x04,0x00 };
870 static const BYTE detachedHashNonFinalContent[] = {
871 0x30,0x2f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x22,
872 0x30,0x20,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
873 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
874 0x07,0x01,0x04,0x00 };
875 static const BYTE detachedHashBareContent[] = {
876 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
877 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
878 0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
879 0x9d,0x2a,0x8f,0x26,0x2f };
880 static const BYTE detachedHashContent[] = {
881 0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
882 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
883 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
884 0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
885 0x9d,0x2a,0x8f,0x26,0x2f };
887 static void test_hash_msg_encoding(void)
889 HCRYPTMSG msg;
890 CMSG_HASHED_ENCODE_INFO hashInfo = { sizeof(hashInfo), 0 };
891 BOOL ret;
892 struct update_accum accum = { 0, NULL }, empty_accum = { 0, NULL };
893 CMSG_STREAM_INFO streamInfo = { 0, accumulating_stream_output, &accum };
895 hashInfo.HashAlgorithm.pszObjId = oid_rsa_md5;
896 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
897 NULL, NULL);
898 check_param("hash empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
899 hashEmptyBareContent, sizeof(hashEmptyBareContent));
900 check_param("hash empty content", msg, CMSG_CONTENT_PARAM,
901 hashEmptyContent, sizeof(hashEmptyContent));
902 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
903 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
904 check_param("hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
905 hashBareContent, sizeof(hashBareContent));
906 check_param("hash content", msg, CMSG_CONTENT_PARAM,
907 hashContent, sizeof(hashContent));
908 CryptMsgClose(msg);
909 /* Same test, but with CMSG_BARE_CONTENT_FLAG set */
910 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_BARE_CONTENT_FLAG,
911 CMSG_HASHED, &hashInfo, NULL, NULL);
912 check_param("hash empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
913 hashEmptyBareContent, sizeof(hashEmptyBareContent));
914 check_param("hash empty content", msg, CMSG_CONTENT_PARAM,
915 hashEmptyContent, sizeof(hashEmptyContent));
916 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
917 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
918 check_param("hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
919 hashBareContent, sizeof(hashBareContent));
920 check_param("hash content", msg, CMSG_CONTENT_PARAM,
921 hashContent, sizeof(hashContent));
922 CryptMsgClose(msg);
923 /* Same test, but with CMSG_DETACHED_FLAG set */
924 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
925 CMSG_HASHED, &hashInfo, NULL, NULL);
926 check_param("detached hash empty bare content", msg,
927 CMSG_BARE_CONTENT_PARAM, hashEmptyBareContent,
928 sizeof(hashEmptyBareContent));
929 check_param("detached hash empty content", msg, CMSG_CONTENT_PARAM,
930 hashEmptyContent, sizeof(hashEmptyContent));
931 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
932 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
933 check_param("detached hash not final bare content", msg,
934 CMSG_BARE_CONTENT_PARAM, detachedHashNonFinalBareContent,
935 sizeof(detachedHashNonFinalBareContent));
936 check_param("detached hash not final content", msg, CMSG_CONTENT_PARAM,
937 detachedHashNonFinalContent, sizeof(detachedHashNonFinalContent));
938 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
939 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
940 check_param("detached hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
941 detachedHashBareContent, sizeof(detachedHashBareContent));
942 check_param("detached hash content", msg, CMSG_CONTENT_PARAM,
943 detachedHashContent, sizeof(detachedHashContent));
944 check_param("detached hash bare content", msg, CMSG_BARE_CONTENT_PARAM,
945 detachedHashBareContent, sizeof(detachedHashBareContent));
946 check_param("detached hash content", msg, CMSG_CONTENT_PARAM,
947 detachedHashContent, sizeof(detachedHashContent));
948 CryptMsgClose(msg);
949 /* In what appears to be a bug, streamed updates to hash messages don't
950 * call the output function.
952 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
953 NULL, &streamInfo);
954 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
955 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
956 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
957 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
958 CryptMsgClose(msg);
959 check_updates("empty hash message", &empty_accum, &accum);
960 free_updates(&accum);
962 streamInfo.cbContent = sizeof(msgData);
963 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, &hashInfo,
964 NULL, &streamInfo);
965 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
966 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
967 CryptMsgClose(msg);
968 check_updates("hash message", &empty_accum, &accum);
969 free_updates(&accum);
971 streamInfo.cbContent = sizeof(msgData);
972 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, CMSG_DETACHED_FLAG,
973 CMSG_HASHED, &hashInfo, NULL, &streamInfo);
974 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
975 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
976 CryptMsgClose(msg);
977 check_updates("detached hash message", &empty_accum, &accum);
978 free_updates(&accum);
981 static void test_hash_msg(void)
983 test_hash_msg_open();
984 test_hash_msg_update();
985 test_hash_msg_get_param();
986 test_hash_msg_encoding();
989 static const WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e',
990 'm','p',0 };
991 static BYTE serialNum[] = { 1 };
992 static BYTE encodedCommonName[] = { 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,
993 0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
995 static void test_signed_msg_open(void)
997 HCRYPTMSG msg;
998 BOOL ret;
999 CMSG_SIGNED_ENCODE_INFO signInfo = { 0 };
1000 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
1001 CERT_INFO certInfo = { 0 };
1003 SetLastError(0xdeadbeef);
1004 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1005 NULL, NULL);
1006 ok(!msg && GetLastError() == E_INVALIDARG,
1007 "Expected E_INVALIDARG, got %x\n", GetLastError());
1008 signInfo.cbSize = sizeof(signInfo);
1009 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1010 NULL, NULL);
1011 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1012 CryptMsgClose(msg);
1014 signInfo.cSigners = 1;
1015 signInfo.rgSigners = &signer;
1016 /* With signer.pCertInfo unset, attempting to open this message this
1017 * crashes.
1019 signer.pCertInfo = &certInfo;
1020 /* The cert info must contain a serial number and an issuer. */
1021 SetLastError(0xdeadbeef);
1022 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1023 NULL, NULL);
1024 ok(!msg && GetLastError() == E_INVALIDARG,
1025 "Expected E_INVALIDARG, got %x\n", GetLastError());
1026 certInfo.SerialNumber.cbData = sizeof(serialNum);
1027 certInfo.SerialNumber.pbData = serialNum;
1028 SetLastError(0xdeadbeef);
1029 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1030 NULL, NULL);
1031 ok(!msg && GetLastError() == E_INVALIDARG,
1032 "Expected E_INVALIDARG, got %x\n", GetLastError());
1033 certInfo.Issuer.cbData = sizeof(encodedCommonName);
1034 certInfo.Issuer.pbData = encodedCommonName;
1035 SetLastError(0xdeadbeef);
1036 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1037 NULL, NULL);
1038 ok(!msg && GetLastError() == E_INVALIDARG,
1039 "Expected E_INVALIDARG, got %x\n", GetLastError());
1041 /* The signer's hCryptProv must be set to something. Whether it's usable
1042 * or not will be checked after the hash algorithm is checked (see next
1043 * test.)
1045 signer.hCryptProv = 1;
1046 SetLastError(0xdeadbeef);
1047 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1048 NULL, NULL);
1049 ok(!msg && GetLastError() == CRYPT_E_UNKNOWN_ALGO,
1050 "Expected CRYPT_E_UNKNOWN_ALGO, got %x\n", GetLastError());
1051 /* The signer's hash algorithm must also be set. */
1052 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
1053 SetLastError(0xdeadbeef);
1054 /* Crashes in advapi32 in wine, don't do it */
1055 if (0) {
1056 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED,
1057 &signInfo, NULL, NULL);
1058 ok(!msg && GetLastError() == ERROR_INVALID_PARAMETER,
1059 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1061 /* The signer's hCryptProv must also be valid. */
1062 ret = pCryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1063 PROV_RSA_FULL, CRYPT_NEWKEYSET);
1064 if (!ret && GetLastError() == NTE_EXISTS)
1065 ret = pCryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1066 PROV_RSA_FULL, 0);
1067 ok(ret, "CryptAcquireContextW failed: %x\n", GetLastError());
1068 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1069 NULL, NULL);
1070 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1071 CryptMsgClose(msg);
1073 CryptReleaseContext(signer.hCryptProv, 0);
1074 pCryptAcquireContextW(&signer.hCryptProv, cspNameW, MS_DEF_PROV_W,
1075 PROV_RSA_FULL, CRYPT_DELETEKEYSET);
1078 static const BYTE privKey[] = {
1079 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
1080 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
1081 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
1082 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
1083 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
1084 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
1085 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
1086 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
1087 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
1088 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
1089 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
1090 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
1091 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
1092 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
1093 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
1094 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
1095 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
1096 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
1097 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
1098 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
1099 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
1100 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
1101 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
1102 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
1104 static void test_signed_msg_update(void)
1106 HCRYPTMSG msg;
1107 BOOL ret;
1108 CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
1109 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
1110 CERT_INFO certInfo = { 0 };
1111 HCRYPTKEY key;
1113 certInfo.SerialNumber.cbData = sizeof(serialNum);
1114 certInfo.SerialNumber.pbData = serialNum;
1115 certInfo.Issuer.cbData = sizeof(encodedCommonName);
1116 certInfo.Issuer.pbData = encodedCommonName;
1117 signer.pCertInfo = &certInfo;
1118 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
1119 signInfo.cSigners = 1;
1120 signInfo.rgSigners = &signer;
1121 ret = pCryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1122 PROV_RSA_FULL, CRYPT_NEWKEYSET);
1123 if (!ret && GetLastError() == NTE_EXISTS)
1124 ret = pCryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1125 PROV_RSA_FULL, 0);
1126 ok(ret, "CryptAcquireContextW failed: %x\n", GetLastError());
1127 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING,
1128 CMSG_DETACHED_FLAG, CMSG_SIGNED, &signInfo, NULL, NULL);
1129 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1130 /* Detached CMSG_SIGNED allows non-final updates. */
1131 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1132 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1133 /* Detached CMSG_SIGNED also allows non-final updates with no data. */
1134 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1135 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1136 /* The final update requires a private key in the hCryptProv, in order to
1137 * generate the signature.
1139 SetLastError(0xdeadbeef);
1140 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1141 ok(!ret && (GetLastError() == NTE_BAD_KEYSET ||
1142 GetLastError() == NTE_NO_KEY),
1143 "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %x\n", GetLastError());
1144 ret = CryptImportKey(signer.hCryptProv, (LPBYTE)privKey, sizeof(privKey),
1145 0, 0, &key);
1146 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
1147 /* The final update should be able to succeed now that a key exists, but
1148 * the previous (invalid) final update prevents it.
1150 SetLastError(0xdeadbeef);
1151 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1152 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1153 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1154 CryptMsgClose(msg);
1156 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING,
1157 CMSG_DETACHED_FLAG, CMSG_SIGNED, &signInfo, NULL, NULL);
1158 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1159 /* Detached CMSG_SIGNED allows non-final updates. */
1160 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1161 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1162 /* Detached CMSG_SIGNED also allows non-final updates with no data. */
1163 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1164 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1165 /* Now that the private key exists, the final update can succeed (even
1166 * with no data.)
1168 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1169 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1170 /* But no updates are allowed after the final update. */
1171 SetLastError(0xdeadbeef);
1172 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1173 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1174 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1175 SetLastError(0xdeadbeef);
1176 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1177 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1178 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1179 CryptMsgClose(msg);
1181 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1182 NULL, NULL);
1183 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1184 /* Non-detached messages don't allow non-final updates.. */
1185 SetLastError(0xdeadbeef);
1186 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1187 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1188 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1189 /* but they do allow final ones. */
1190 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1191 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1192 CryptMsgClose(msg);
1193 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1194 NULL, NULL);
1195 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1196 /* They also allow final updates with no data. */
1197 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1198 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1199 CryptMsgClose(msg);
1201 CryptDestroyKey(key);
1202 CryptReleaseContext(signer.hCryptProv, 0);
1203 pCryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL, PROV_RSA_FULL,
1204 CRYPT_DELETEKEYSET);
1207 static const BYTE signedEmptyBareContent[] = {
1208 0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
1209 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02,
1210 0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1211 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
1212 0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,
1213 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
1214 static const BYTE signedEmptyContent[] = {
1215 0x30,0x5f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x52,
1216 0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
1217 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02,
1218 0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1219 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
1220 0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,
1221 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
1222 static const BYTE detachedSignedBareContent[] = {
1223 0x30,0x81,0x99,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1224 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,
1225 0xf7,0x0d,0x01,0x07,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,
1226 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1227 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,
1228 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,
1229 0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,
1230 0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,
1231 0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,
1232 0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,
1233 0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1234 static const BYTE detachedSignedContent[] = {
1235 0x30,0x81,0xaa,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
1236 0x81,0x9c,0x30,0x81,0x99,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
1237 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,
1238 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,
1239 0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
1240 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,
1241 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,
1242 0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,
1243 0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,
1244 0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,
1245 0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,
1246 0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1247 static const BYTE signedBareContent[] = {
1248 0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1249 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,
1250 0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x31,0x77,
1251 0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,
1252 0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
1253 0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,
1254 0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,
1255 0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,
1256 0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,
1257 0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,
1258 0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1259 static const BYTE signedContent[] = {
1260 0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
1261 0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
1262 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
1263 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
1264 0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,
1265 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1266 0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1267 0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,
1268 0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,
1269 0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,
1270 0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,
1271 0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,
1272 0x0d };
1273 static const BYTE signedHash[] = {
1274 0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,
1275 0x2f };
1276 static const BYTE signedEncodedSigner[] = {
1277 0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,
1278 0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
1279 0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,
1280 0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,
1281 0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,
1282 0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,
1283 0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,
1284 0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1285 static const BYTE signedWithAuthAttrsBareContent[] = {
1286 0x30,0x82,0x01,0x00,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,
1287 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,
1288 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x31,
1289 0x81,0xd5,0x30,0x81,0xd2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,
1290 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1291 0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1292 0x0d,0x02,0x05,0x05,0x00,0xa0,0x5b,0x30,0x18,0x06,0x09,0x2a,0x86,0x48,0x86,
1293 0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1294 0x01,0x07,0x01,0x30,0x1e,0x06,0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,
1295 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
1296 0x4c,0x61,0x6e,0x67,0x00,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1297 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,
1298 0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
1299 0x40,0xbf,0x65,0xde,0x7a,0x3e,0xa2,0x19,0x59,0xc3,0xc7,0x02,0x53,0xc9,0x72,
1300 0xcd,0x74,0x96,0x70,0x0b,0x3b,0xcf,0x8b,0xd9,0x17,0x5c,0xc5,0xd1,0x83,0x41,
1301 0x32,0x93,0xa6,0xf3,0x52,0x83,0x94,0xa9,0x6b,0x0a,0x92,0xcf,0xaf,0x12,0xfa,
1302 0x40,0x53,0x12,0x84,0x03,0xab,0x10,0xa2,0x3d,0xe6,0x9f,0x5a,0xbf,0xc5,0xb8,
1303 0xff,0xc6,0x33,0x63,0x34 };
1304 static BYTE cert[] = {
1305 0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
1306 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1307 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
1308 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
1309 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
1310 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
1311 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,
1312 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
1313 0xff,0x02,0x01,0x01 };
1314 static const BYTE signedWithCertEmptyBareContent[] = {
1315 0x30,0x81,0xce,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1316 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x7c,0x30,0x7a,
1317 0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,
1318 0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
1319 0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
1320 0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
1321 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
1322 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
1323 0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
1324 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
1325 0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,
1326 0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,
1327 0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
1328 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
1329 static const BYTE signedWithCertBareContent[] = {
1330 0x30,0x82,0x01,0x1f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,
1331 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,
1332 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa0,
1333 0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1334 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1335 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
1336 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1337 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
1338 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1339 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,
1340 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
1341 0x01,0xff,0x02,0x01,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,
1342 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1343 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,
1344 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,
1345 0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,
1346 0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,
1347 0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,
1348 0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,
1349 0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1350 static BYTE crl[] = { 0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1351 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1352 0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
1353 0x30,0x30,0x30,0x30,0x5a };
1354 static const BYTE signedWithCrlEmptyBareContent[] = {
1355 0x30,0x81,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1356 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa1,0x2e,0x30,0x2c,
1357 0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1358 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
1359 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x31,
1360 0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
1361 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
1362 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
1363 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
1364 static const BYTE signedWithCrlBareContent[] = {
1365 0x30,0x81,0xd1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1366 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,
1367 0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa1,0x2e,
1368 0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
1369 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,
1370 0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,
1371 0x5a,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,
1372 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1373 0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1374 0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,
1375 0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,
1376 0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,
1377 0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,
1378 0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,
1379 0xa8,0x0d };
1380 static const BYTE signedWithCertAndCrlEmptyBareContent[] = {
1381 0x30,0x81,0xfe,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
1382 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x7c,0x30,0x7a,
1383 0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,
1384 0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,
1385 0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
1386 0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
1387 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
1388 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
1389 0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
1390 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
1391 0x01,0x01,0xa1,0x2e,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1392 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1393 0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
1394 0x30,0x30,0x30,0x30,0x5a,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,
1395 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
1396 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,
1397 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,
1398 0x04,0x00 };
1399 static const BYTE signedWithCertAndCrlBareContent[] = {
1400 0x30,0x82,0x01,0x4f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,
1401 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,
1402 0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0xa0,
1403 0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
1404 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
1405 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
1406 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
1407 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
1408 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
1409 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,
1410 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
1411 0x01,0xff,0x02,0x01,0x01,0xa1,0x2e,0x30,0x2c,0x30,0x02,0x06,0x00,0x30,0x15,
1412 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
1413 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
1414 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x31,0x77,0x30,0x75,0x02,0x01,0x01,
1415 0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,
1416 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,
1417 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,
1418 0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,
1419 0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,
1420 0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,
1421 0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,
1422 0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
1424 static void test_signed_msg_encoding(void)
1426 HCRYPTMSG msg;
1427 CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
1428 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
1429 CERT_INFO certInfo = { 0 };
1430 CERT_BLOB encodedCert = { sizeof(cert), cert };
1431 CRL_BLOB encodedCrl = { sizeof(crl), crl };
1432 char oid_common_name[] = szOID_COMMON_NAME;
1433 CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
1434 encodedCommonName };
1435 CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
1436 BOOL ret;
1437 HCRYPTKEY key;
1438 DWORD size;
1440 certInfo.SerialNumber.cbData = sizeof(serialNum);
1441 certInfo.SerialNumber.pbData = serialNum;
1442 certInfo.Issuer.cbData = sizeof(encodedCommonName);
1443 certInfo.Issuer.pbData = encodedCommonName;
1444 signer.pCertInfo = &certInfo;
1445 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
1446 signInfo.cSigners = 1;
1447 signInfo.rgSigners = &signer;
1448 ret = pCryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1449 PROV_RSA_FULL, CRYPT_NEWKEYSET);
1450 if (!ret && GetLastError() == NTE_EXISTS)
1451 ret = pCryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1452 PROV_RSA_FULL, 0);
1453 ok(ret, "CryptAcquireContextW failed: %x\n", GetLastError());
1454 ret = CryptImportKey(signer.hCryptProv, (LPBYTE)privKey, sizeof(privKey),
1455 0, 0, &key);
1456 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
1458 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING,
1459 CMSG_DETACHED_FLAG, CMSG_SIGNED, &signInfo, NULL, NULL);
1460 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1462 check_param("detached signed empty bare content", msg,
1463 CMSG_BARE_CONTENT_PARAM, signedEmptyBareContent,
1464 sizeof(signedEmptyBareContent));
1465 check_param("detached signed empty content", msg, CMSG_CONTENT_PARAM,
1466 signedEmptyContent, sizeof(signedEmptyContent));
1467 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1468 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1469 check_param("detached signed hash", msg, CMSG_COMPUTED_HASH_PARAM,
1470 signedHash, sizeof(signedHash));
1471 check_param("detached signed bare content", msg, CMSG_BARE_CONTENT_PARAM,
1472 detachedSignedBareContent, sizeof(detachedSignedBareContent));
1473 check_param("detached signed content", msg, CMSG_CONTENT_PARAM,
1474 detachedSignedContent, sizeof(detachedSignedContent));
1475 SetLastError(0xdeadbeef);
1476 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 1, NULL, &size);
1477 ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
1478 "Expected CRYPT_E_INVALID_INDEX, got %x\n", GetLastError());
1479 check_param("detached signed encoded signer", msg, CMSG_ENCODED_SIGNER,
1480 signedEncodedSigner, sizeof(signedEncodedSigner));
1482 CryptMsgClose(msg);
1484 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1485 NULL, NULL);
1486 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1488 check_param("signed empty bare content", msg, CMSG_BARE_CONTENT_PARAM,
1489 signedEmptyBareContent, sizeof(signedEmptyBareContent));
1490 check_param("signed empty content", msg, CMSG_CONTENT_PARAM,
1491 signedEmptyContent, sizeof(signedEmptyContent));
1492 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1493 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1494 check_param("signed bare content", msg, CMSG_BARE_CONTENT_PARAM,
1495 signedBareContent, sizeof(signedBareContent));
1496 check_param("signed content", msg, CMSG_CONTENT_PARAM,
1497 signedContent, sizeof(signedContent));
1499 CryptMsgClose(msg);
1501 signer.cAuthAttr = 1;
1502 signer.rgAuthAttr = &attr;
1503 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1504 NULL, NULL);
1505 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1507 CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1508 check_param("signed with auth attrs bare content", msg,
1509 CMSG_BARE_CONTENT_PARAM, signedWithAuthAttrsBareContent,
1510 sizeof(signedWithAuthAttrsBareContent));
1512 CryptMsgClose(msg);
1514 signer.cAuthAttr = 0;
1515 signInfo.rgCertEncoded = &encodedCert;
1516 signInfo.cCertEncoded = 1;
1517 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1518 NULL, NULL);
1519 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1521 check_param("signed with cert empty bare content", msg,
1522 CMSG_BARE_CONTENT_PARAM, signedWithCertEmptyBareContent,
1523 sizeof(signedWithCertEmptyBareContent));
1524 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1525 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1526 check_param("signed with cert bare content", msg, CMSG_BARE_CONTENT_PARAM,
1527 signedWithCertBareContent, sizeof(signedWithCertBareContent));
1529 CryptMsgClose(msg);
1531 signInfo.cCertEncoded = 0;
1532 signInfo.rgCrlEncoded = &encodedCrl;
1533 signInfo.cCrlEncoded = 1;
1534 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1535 NULL, NULL);
1536 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1538 check_param("signed with crl empty bare content", msg,
1539 CMSG_BARE_CONTENT_PARAM, signedWithCrlEmptyBareContent,
1540 sizeof(signedWithCrlEmptyBareContent));
1541 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1542 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1543 check_param("signed with crl bare content", msg, CMSG_BARE_CONTENT_PARAM,
1544 signedWithCrlBareContent, sizeof(signedWithCrlBareContent));
1546 CryptMsgClose(msg);
1548 signInfo.cCertEncoded = 1;
1549 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1550 NULL, NULL);
1551 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1553 check_param("signed with cert and crl empty bare content", msg,
1554 CMSG_BARE_CONTENT_PARAM, signedWithCertAndCrlEmptyBareContent,
1555 sizeof(signedWithCertAndCrlEmptyBareContent));
1556 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1557 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1558 check_param("signed with cert and crl bare content", msg,
1559 CMSG_BARE_CONTENT_PARAM, signedWithCertAndCrlBareContent,
1560 sizeof(signedWithCertAndCrlBareContent));
1562 CryptMsgClose(msg);
1564 CryptDestroyKey(key);
1565 CryptReleaseContext(signer.hCryptProv, 0);
1566 pCryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL, PROV_RSA_FULL,
1567 CRYPT_DELETEKEYSET);
1570 static void test_signed_msg_get_param(void)
1572 BOOL ret;
1573 HCRYPTMSG msg;
1574 DWORD size, value = 0;
1575 CMSG_SIGNED_ENCODE_INFO signInfo = { sizeof(signInfo), 0 };
1576 CMSG_SIGNER_ENCODE_INFO signer = { sizeof(signer), 0 };
1577 CERT_INFO certInfo = { 0 };
1579 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1580 NULL, NULL);
1581 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1583 /* Content and bare content are always gettable */
1584 size = 0;
1585 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
1586 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1587 size = 0;
1588 ret = CryptMsgGetParam(msg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &size);
1589 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1590 /* For "signed" messages, so is the version. */
1591 size = 0;
1592 ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, NULL, &size);
1593 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1594 size = sizeof(value);
1595 ret = CryptMsgGetParam(msg, CMSG_VERSION_PARAM, 0, (LPBYTE)&value, &size);
1596 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1597 ok(value == CMSG_SIGNED_DATA_V1, "Expected version 1, got %d\n", value);
1598 /* But for this message, with no signers, the hash and signer aren't
1599 * available.
1601 size = 0;
1602 SetLastError(0xdeadbeef);
1603 ret = CryptMsgGetParam(msg, CMSG_ENCODED_SIGNER, 0, NULL, &size);
1604 ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
1605 "Expected CRYPT_E_INVALID_INDEX, got %x\n", GetLastError());
1606 SetLastError(0xdeadbeef);
1607 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
1608 ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
1609 "Expected CRYPT_E_INVALID_INDEX, got %x\n", GetLastError());
1610 /* As usual, the type isn't available. */
1611 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
1612 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1613 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1615 CryptMsgClose(msg);
1617 certInfo.SerialNumber.cbData = sizeof(serialNum);
1618 certInfo.SerialNumber.pbData = serialNum;
1619 certInfo.Issuer.cbData = sizeof(encodedCommonName);
1620 certInfo.Issuer.pbData = encodedCommonName;
1621 signer.pCertInfo = &certInfo;
1622 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
1623 signInfo.cSigners = 1;
1624 signInfo.rgSigners = &signer;
1625 ret = pCryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1626 PROV_RSA_FULL, CRYPT_NEWKEYSET);
1627 if (!ret && GetLastError() == NTE_EXISTS)
1628 ret = pCryptAcquireContextW(&signer.hCryptProv, cspNameW, NULL,
1629 PROV_RSA_FULL, 0);
1630 ok(ret, "CryptAcquireContextW failed: %x\n", GetLastError());
1631 msg = CryptMsgOpenToEncode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, &signInfo,
1632 NULL, NULL);
1633 ok(msg != NULL, "CryptMsgOpenToEncode failed: %x\n", GetLastError());
1635 /* This message, with one signer, has the hash and signer for index 0
1636 * available, but not for other indexes.
1638 size = 0;
1639 ret = CryptMsgGetParam(msg, CMSG_ENCODED_SIGNER, 0, NULL, &size);
1640 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
1641 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 0, NULL, &size);
1642 ok(ret, "CryptMsgGetParam failed: %x\n", GetLastError());
1643 size = 0;
1644 SetLastError(0xdeadbeef);
1645 ret = CryptMsgGetParam(msg, CMSG_ENCODED_SIGNER, 1, NULL, &size);
1646 ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
1647 "Expected CRYPT_E_INVALID_INDEX, got %x\n", GetLastError());
1648 SetLastError(0xdeadbeef);
1649 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 1, NULL, &size);
1650 ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
1651 "Expected CRYPT_E_INVALID_INDEX, got %x\n", GetLastError());
1652 /* As usual, the type isn't available. */
1653 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, NULL, &size);
1654 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1655 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1657 CryptMsgClose(msg);
1659 CryptReleaseContext(signer.hCryptProv, 0);
1660 pCryptAcquireContextW(&signer.hCryptProv, cspNameW, MS_DEF_PROV_W,
1661 PROV_RSA_FULL, CRYPT_DELETEKEYSET);
1664 static void test_signed_msg(void)
1666 test_signed_msg_open();
1667 test_signed_msg_update();
1668 test_signed_msg_encoding();
1669 test_signed_msg_get_param();
1672 static CRYPT_DATA_BLOB b4 = { 0, NULL };
1673 static const struct update_accum a4 = { 1, &b4 };
1675 static const BYTE bogusOIDContent[] = {
1676 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x07,0xa0,0x02,
1677 0x04,0x00 };
1678 static const BYTE bogusHashContent[] = {
1679 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
1680 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1681 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
1682 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x00,0xd6,0xc0,
1683 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1685 static void test_decode_msg_update(void)
1687 HCRYPTMSG msg;
1688 BOOL ret;
1689 CMSG_STREAM_INFO streamInfo = { 0 };
1690 DWORD i;
1691 struct update_accum accum = { 0, NULL };
1693 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1694 /* Update with a full message in a final update */
1695 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
1696 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1697 /* Can't update after a final update */
1698 SetLastError(0xdeadbeef);
1699 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
1700 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1701 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1702 CryptMsgClose(msg);
1704 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1705 /* Can't send a non-final update without streaming */
1706 SetLastError(0xdeadbeef);
1707 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1708 FALSE);
1709 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
1710 "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
1711 /* A subsequent final update succeeds */
1712 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
1713 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1714 CryptMsgClose(msg);
1716 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1717 /* Updating a message that has a NULL stream callback fails */
1718 SetLastError(0xdeadbeef);
1719 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1720 FALSE);
1721 todo_wine
1722 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1723 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
1724 /* Changing the callback pointer after the fact yields the same error (so
1725 * the message must copy the stream info, not just store a pointer to it)
1727 streamInfo.pfnStreamOutput = nop_stream_output;
1728 SetLastError(0xdeadbeef);
1729 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1730 FALSE);
1731 todo_wine
1732 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1733 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
1734 CryptMsgClose(msg);
1736 /* Empty non-final updates are allowed when streaming.. */
1737 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1738 ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
1739 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1740 /* but final updates aren't when not enough data has been received. */
1741 SetLastError(0xdeadbeef);
1742 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1743 todo_wine
1744 ok(!ret && GetLastError() == CRYPT_E_STREAM_INSUFFICIENT_DATA,
1745 "Expected CRYPT_E_STREAM_INSUFFICIENT_DATA, got %x\n", GetLastError());
1746 CryptMsgClose(msg);
1748 /* Updating the message byte by byte is legal */
1749 streamInfo.pfnStreamOutput = accumulating_stream_output;
1750 streamInfo.pvArg = &accum;
1751 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1752 for (i = 0, ret = TRUE; ret && i < sizeof(dataEmptyContent); i++)
1753 ret = CryptMsgUpdate(msg, &dataEmptyContent[i], 1, FALSE);
1754 ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
1755 ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
1756 ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
1757 CryptMsgClose(msg);
1758 todo_wine
1759 check_updates("byte-by-byte empty content", &a4, &accum);
1760 free_updates(&accum);
1762 /* Decoding bogus content fails in non-streaming mode.. */
1763 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1764 SetLastError(0xdeadbeef);
1765 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1766 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1767 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1768 CryptMsgClose(msg);
1769 /* and as the final update in streaming mode.. */
1770 streamInfo.pfnStreamOutput = nop_stream_output;
1771 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1772 SetLastError(0xdeadbeef);
1773 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
1774 todo_wine
1775 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1776 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1777 CryptMsgClose(msg);
1778 /* and even as a non-final update in streaming mode. */
1779 streamInfo.pfnStreamOutput = nop_stream_output;
1780 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
1781 SetLastError(0xdeadbeef);
1782 ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), FALSE);
1783 todo_wine
1784 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1785 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1786 CryptMsgClose(msg);
1788 /* An empty message can be opened with indetermined type.. */
1789 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1790 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1791 TRUE);
1792 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1793 /* but decoding it as an explicitly typed message fails. */
1794 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
1795 NULL);
1796 SetLastError(0xdeadbeef);
1797 ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
1798 TRUE);
1799 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1800 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1801 CryptMsgClose(msg);
1802 /* On the other hand, decoding the bare content of an empty message fails
1803 * with unspecified type..
1805 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1806 SetLastError(0xdeadbeef);
1807 ret = CryptMsgUpdate(msg, dataEmptyBareContent,
1808 sizeof(dataEmptyBareContent), TRUE);
1809 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1810 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1811 CryptMsgClose(msg);
1812 /* but succeeds with explicit type. */
1813 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
1814 NULL);
1815 ret = CryptMsgUpdate(msg, dataEmptyBareContent,
1816 sizeof(dataEmptyBareContent), TRUE);
1817 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1818 CryptMsgClose(msg);
1820 /* Decoding valid content with an unsupported OID fails */
1821 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1822 SetLastError(0xdeadbeef);
1823 ret = CryptMsgUpdate(msg, bogusOIDContent, sizeof(bogusOIDContent), TRUE);
1824 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1825 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1826 CryptMsgClose(msg);
1828 /* Similarly, opening an empty hash with unspecified type succeeds.. */
1829 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1830 SetLastError(0xdeadbeef);
1831 ret = CryptMsgUpdate(msg, hashEmptyContent, sizeof(hashEmptyContent), TRUE);
1832 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1833 CryptMsgClose(msg);
1834 /* while with specified type it fails. */
1835 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1836 NULL);
1837 SetLastError(0xdeadbeef);
1838 ret = CryptMsgUpdate(msg, hashEmptyContent, sizeof(hashEmptyContent), TRUE);
1839 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1840 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1841 CryptMsgClose(msg);
1842 /* On the other hand, decoding the bare content of an empty hash message
1843 * fails with unspecified type..
1845 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1846 SetLastError(0xdeadbeef);
1847 ret = CryptMsgUpdate(msg, hashEmptyBareContent,
1848 sizeof(hashEmptyBareContent), TRUE);
1849 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1850 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1851 CryptMsgClose(msg);
1852 /* but succeeds with explicit type. */
1853 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1854 NULL);
1855 ret = CryptMsgUpdate(msg, hashEmptyBareContent,
1856 sizeof(hashEmptyBareContent), TRUE);
1857 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1858 CryptMsgClose(msg);
1860 /* And again, opening a (non-empty) hash message with unspecified type
1861 * succeeds..
1863 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1864 SetLastError(0xdeadbeef);
1865 ret = CryptMsgUpdate(msg, hashContent, sizeof(hashContent), TRUE);
1866 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1867 CryptMsgClose(msg);
1868 /* while with specified type it fails.. */
1869 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1870 NULL);
1871 SetLastError(0xdeadbeef);
1872 ret = CryptMsgUpdate(msg, hashContent, sizeof(hashContent), TRUE);
1873 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1874 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1875 CryptMsgClose(msg);
1876 /* and decoding the bare content of a non-empty hash message fails with
1877 * unspecified type..
1879 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1880 SetLastError(0xdeadbeef);
1881 ret = CryptMsgUpdate(msg, hashBareContent, sizeof(hashBareContent), TRUE);
1882 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1883 "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
1884 CryptMsgClose(msg);
1885 /* but succeeds with explicit type. */
1886 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_HASHED, 0, NULL,
1887 NULL);
1888 ret = CryptMsgUpdate(msg, hashBareContent, sizeof(hashBareContent), TRUE);
1889 ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
1890 CryptMsgClose(msg);
1892 /* Opening a (non-empty) hash message with unspecified type and a bogus
1893 * hash value succeeds..
1895 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1896 SetLastError(0xdeadbeef);
1897 ret = CryptMsgUpdate(msg, bogusHashContent, sizeof(bogusHashContent), TRUE);
1898 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1899 CryptMsgClose(msg);
1901 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1902 ret = CryptMsgUpdate(msg, signedContent, sizeof(signedContent), TRUE);
1903 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1904 CryptMsgClose(msg);
1905 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1906 SetLastError(0xdeadbeef);
1907 ret = CryptMsgUpdate(msg, signedWithCertAndCrlBareContent,
1908 sizeof(signedWithCertAndCrlBareContent), TRUE);
1909 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1910 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1911 CryptMsgClose(msg);
1912 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
1913 NULL);
1914 ret = CryptMsgUpdate(msg, signedWithCertAndCrlBareContent,
1915 sizeof(signedWithCertAndCrlBareContent), TRUE);
1916 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1917 CryptMsgClose(msg);
1920 static const BYTE hashParam[] = { 0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,
1921 0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
1923 static void compare_signer_info(const CMSG_SIGNER_INFO *got,
1924 const CMSG_SIGNER_INFO *expected)
1926 ok(got->dwVersion == expected->dwVersion, "Expected version %d, got %d\n",
1927 expected->dwVersion, got->dwVersion);
1928 ok(got->Issuer.cbData == expected->Issuer.cbData,
1929 "Expected issuer size %d, got %d\n", expected->Issuer.cbData,
1930 got->Issuer.cbData);
1931 ok(!memcmp(got->Issuer.pbData, got->Issuer.pbData, got->Issuer.cbData),
1932 "Unexpected issuer\n");
1933 ok(got->SerialNumber.cbData == expected->SerialNumber.cbData,
1934 "Expected serial number size %d, got %d\n", expected->SerialNumber.cbData,
1935 got->SerialNumber.cbData);
1936 ok(!memcmp(got->SerialNumber.pbData, got->SerialNumber.pbData,
1937 got->SerialNumber.cbData), "Unexpected serial number\n");
1938 /* FIXME: check more things */
1941 static void test_decode_msg_get_param(void)
1943 HCRYPTMSG msg;
1944 BOOL ret;
1945 DWORD size = 0, value;
1946 LPBYTE buf;
1948 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1949 SetLastError(0xdeadbeef);
1950 ret = CryptMsgGetParam(msg, CMSG_CONTENT_PARAM, 0, NULL, &size);
1951 ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
1952 "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
1953 ret = CryptMsgUpdate(msg, dataContent, sizeof(dataContent), TRUE);
1954 check_param("data content", msg, CMSG_CONTENT_PARAM, msgData,
1955 sizeof(msgData));
1956 CryptMsgClose(msg);
1958 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1959 ret = CryptMsgUpdate(msg, hashEmptyContent, sizeof(hashEmptyContent), TRUE);
1960 check_param("empty hash content", msg, CMSG_CONTENT_PARAM, NULL, 0);
1961 check_param("empty hash hash data", msg, CMSG_HASH_DATA_PARAM, NULL, 0);
1962 check_param("empty hash computed hash", msg, CMSG_COMPUTED_HASH_PARAM,
1963 emptyHashParam, sizeof(emptyHashParam));
1964 CryptMsgClose(msg);
1965 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1966 ret = CryptMsgUpdate(msg, hashContent, sizeof(hashContent), TRUE);
1967 check_param("hash content", msg, CMSG_CONTENT_PARAM, msgData,
1968 sizeof(msgData));
1969 check_param("hash hash data", msg, CMSG_HASH_DATA_PARAM, hashParam,
1970 sizeof(hashParam));
1971 check_param("hash computed hash", msg, CMSG_COMPUTED_HASH_PARAM,
1972 hashParam, sizeof(hashParam));
1973 /* Curiously, getting the hash of index 1 succeeds, even though there's
1974 * only one hash.
1976 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 1, NULL, &size);
1977 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
1978 buf = CryptMemAlloc(size);
1979 if (buf)
1981 ret = CryptMsgGetParam(msg, CMSG_COMPUTED_HASH_PARAM, 1, buf, &size);
1982 ok(size == sizeof(hashParam), "Unexpected size %d\n", size);
1983 ok(!memcmp(buf, hashParam, size), "Unexpected value\n");
1984 CryptMemFree(buf);
1986 check_param("hash inner OID", msg, CMSG_INNER_CONTENT_TYPE_PARAM,
1987 (const BYTE *)szOID_RSA_data, strlen(szOID_RSA_data) + 1);
1988 value = CMSG_HASHED_DATA_V0;
1989 check_param("hash version", msg, CMSG_VERSION_PARAM, (const BYTE *)&value,
1990 sizeof(value));
1991 CryptMsgClose(msg);
1993 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
1994 ret = CryptMsgUpdate(msg, signedContent, sizeof(signedContent), TRUE);
1995 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
1996 check_param("signed content", msg, CMSG_CONTENT_PARAM, msgData,
1997 sizeof(msgData));
1998 check_param("inner content", msg, CMSG_INNER_CONTENT_TYPE_PARAM,
1999 (const BYTE *)szOID_RSA_data, strlen(szOID_RSA_data) + 1);
2000 size = sizeof(value);
2001 value = 2112;
2002 ret = CryptMsgGetParam(msg, CMSG_SIGNER_COUNT_PARAM, 0, &value, &size);
2003 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2004 ok(value == 1, "Expected 1 signer, got %d\n", value);
2005 size = 0;
2006 ret = CryptMsgGetParam(msg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &size);
2007 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2008 if (ret)
2009 buf = CryptMemAlloc(size);
2010 else
2011 buf = NULL;
2012 if (buf)
2014 CMSG_SIGNER_INFO signer = { 0 };
2016 signer.dwVersion = 1;
2017 signer.Issuer.cbData = sizeof(encodedCommonName);
2018 signer.Issuer.pbData = encodedCommonName;
2019 signer.SerialNumber.cbData = sizeof(serialNum);
2020 signer.SerialNumber.pbData = serialNum;
2021 signer.HashAlgorithm.pszObjId = oid_rsa_md5;
2022 CryptMsgGetParam(msg, CMSG_SIGNER_INFO_PARAM, 0, buf, &size);
2023 compare_signer_info((CMSG_SIGNER_INFO *)buf, &signer);
2024 CryptMemFree(buf);
2026 /* index is ignored when getting signer count */
2027 size = sizeof(value);
2028 ret = CryptMsgGetParam(msg, CMSG_SIGNER_COUNT_PARAM, 1, &value, &size);
2029 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2030 ok(value == 1, "Expected 1 signer, got %d\n", value);
2031 ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &value, &size);
2032 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2033 ok(value == 0, "Expected 0 certs, got %d\n", value);
2034 ret = CryptMsgGetParam(msg, CMSG_CRL_COUNT_PARAM, 0, &value, &size);
2035 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2036 ok(value == 0, "Expected 0 CRLs, got %d\n", value);
2037 CryptMsgClose(msg);
2038 msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_SIGNED, 0, NULL,
2039 NULL);
2040 ret = CryptMsgUpdate(msg, signedWithCertAndCrlBareContent,
2041 sizeof(signedWithCertAndCrlBareContent), TRUE);
2042 ok(ret, "CryptMsgUpdate failed: %08x\n", GetLastError());
2043 ret = CryptMsgGetParam(msg, CMSG_CERT_COUNT_PARAM, 0, &value, &size);
2044 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2045 ok(value == 1, "Expected 1 cert, got %d\n", value);
2046 check_param("cert", msg, CMSG_CERT_PARAM, cert, sizeof(cert));
2047 ret = CryptMsgGetParam(msg, CMSG_CRL_COUNT_PARAM, 0, &value, &size);
2048 ok(ret, "CryptMsgGetParam failed: %08x\n", GetLastError());
2049 ok(value == 1, "Expected 1 CRL, got %d\n", value);
2050 check_param("crl", msg, CMSG_CRL_PARAM, crl, sizeof(crl));
2051 CryptMsgClose(msg);
2054 static void test_decode_msg(void)
2056 test_decode_msg_update();
2057 test_decode_msg_get_param();
2060 START_TEST(msg)
2062 init_function_pointers();
2064 /* Basic parameter checking tests */
2065 test_msg_open_to_encode();
2066 test_msg_open_to_decode();
2067 test_msg_get_param();
2068 test_msg_close();
2070 /* Message-type specific tests */
2071 test_data_msg();
2072 test_hash_msg();
2073 test_signed_msg();
2074 test_decode_msg();