crypt32: Implement CryptSignMessage.
[wine/multimedia.git] / dlls / crypt32 / tests / message.c
blob8e214e7802db9737e2d67eaa028b022aaca5c332
1 /*
2 * Unit test suite for crypt32.dll's Crypt*Message functions
4 * Copyright 2007-2008 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 const BYTE dataEmptyBareContent[] = { 0x04,0x00 };
31 static const BYTE dataEmptyContent[] = {
32 0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x02,
33 0x04,0x00 };
34 static const BYTE signedEmptyBareContent[] = {
35 0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
36 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02,
37 0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
38 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
39 0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,
40 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
41 static const BYTE signedEmptyContent[] = {
42 0x30,0x5f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x52,
43 0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
44 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02,
45 0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
46 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
47 0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,
48 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
50 static void test_msg_get_signer_count(void)
52 LONG count;
54 SetLastError(0xdeadbeef);
55 count = CryptGetMessageSignerCount(0, NULL, 0);
56 ok(count == -1, "Expected -1, got %d\n", count);
57 ok(GetLastError() == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n",
58 GetLastError());
59 SetLastError(0xdeadbeef);
60 count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, NULL, 0);
61 ok(count == -1, "Expected -1, got %d\n", count);
62 ok(GetLastError() == CRYPT_E_ASN1_EOD ||
63 GetLastError() == OSS_BAD_ARG, /* win9x */
64 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
65 SetLastError(0xdeadbeef);
66 count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
67 dataEmptyBareContent, sizeof(dataEmptyBareContent));
68 ok(count == -1, "Expected -1, got %d\n", count);
69 ok(GetLastError() == CRYPT_E_ASN1_BADTAG ||
70 GetLastError() == OSS_PDU_MISMATCH, /* win9x */
71 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
72 SetLastError(0xdeadbeef);
73 count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
74 dataEmptyContent, sizeof(dataEmptyContent));
75 ok(count == -1, "Expected -1, got %d\n", count);
76 ok(GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
77 "Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
78 SetLastError(0xdeadbeef);
79 count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
80 signedEmptyBareContent, sizeof(signedEmptyBareContent));
81 ok(count == -1, "Expected -1, got %d\n", count);
82 ok(GetLastError() == CRYPT_E_ASN1_BADTAG ||
83 GetLastError() == OSS_DATA_ERROR, /* win9x */
84 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
85 count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
86 signedEmptyContent, sizeof(signedEmptyContent));
87 ok(count == 1 ||
88 broken(count == -1), /* win9x */
89 "Expected 1, got %d\n", count);
92 static BYTE detachedHashContent[] = {
93 0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
94 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
95 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
96 0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
97 0x9d,0x2a,0x8f,0x26,0x2f };
98 static const BYTE msgData[] = { 1, 2, 3, 4 };
100 static void test_verify_detached_message_hash(void)
102 BOOL ret;
103 CRYPT_HASH_MESSAGE_PARA para;
104 DWORD size, hashSize;
105 const BYTE *pMsgData = msgData;
106 BYTE hash[16];
108 if (0)
110 ret = CryptVerifyDetachedMessageHash(NULL, NULL, 0, 0, NULL, NULL, NULL,
111 NULL);
113 memset(&para, 0, sizeof(para));
114 SetLastError(0xdeadbeef);
115 ret = CryptVerifyDetachedMessageHash(&para, NULL, 0, 0, NULL, NULL, NULL,
116 NULL);
117 ok(!ret && GetLastError() == E_INVALIDARG,
118 "expected E_INVALIDARG, got %08x\n", GetLastError());
119 para.cbSize = sizeof(para);
120 SetLastError(0xdeadbeef);
121 ret = CryptVerifyDetachedMessageHash(&para, NULL, 0, 0, NULL, NULL, NULL,
122 NULL);
123 ok(!ret && GetLastError() == E_INVALIDARG,
124 "expected E_INVALIDARG, got %08x\n", GetLastError());
125 para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
126 SetLastError(0xdeadbeef);
127 ret = CryptVerifyDetachedMessageHash(&para, NULL, 0, 0, NULL, NULL, NULL,
128 NULL);
129 ok(!ret &&
130 (GetLastError() == CRYPT_E_ASN1_EOD ||
131 GetLastError() == OSS_BAD_ARG), /* win9x */
132 "expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
133 para.dwMsgEncodingType = X509_ASN_ENCODING;
134 SetLastError(0xdeadbeef);
135 ret = CryptVerifyDetachedMessageHash(&para, NULL, 0, 0, NULL, NULL, NULL,
136 NULL);
137 ok(!ret && GetLastError() == E_INVALIDARG,
138 "expected E_INVALIDARG, got %08x\n", GetLastError());
139 para.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
140 SetLastError(0xdeadbeef);
141 ret = CryptVerifyDetachedMessageHash(&para, NULL, 0, 0, NULL, NULL, NULL,
142 NULL);
143 ok(!ret &&
144 (GetLastError() == CRYPT_E_ASN1_EOD ||
145 GetLastError() == OSS_BAD_ARG), /* win9x */
146 "expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
147 /* Curiously, passing no data to hash succeeds.. */
148 ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
149 sizeof(detachedHashContent), 0, NULL, NULL, NULL, NULL);
150 todo_wine
151 ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
152 /* as does passing the actual content of the message to hash.. */
153 size = sizeof(msgData);
154 pMsgData = msgData;
155 ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
156 sizeof(detachedHashContent), 1, &pMsgData, &size, NULL, NULL);
157 ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
158 /* while passing data to hash that isn't the content of the message fails.
160 size = sizeof(detachedHashContent);
161 pMsgData = detachedHashContent;
162 SetLastError(0xdeadbeef);
163 ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
164 sizeof(detachedHashContent), 1, &pMsgData, &size, NULL, NULL);
165 ok(!ret && GetLastError() == CRYPT_E_HASH_VALUE,
166 "expected CRYPT_E_HASH_VALUE, got %08x\n", GetLastError());
167 /* Getting the size of the hash while passing no hash data causes the
168 * hash to be checked (and fail.)
170 SetLastError(0xdeadbeef);
171 ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
172 sizeof(detachedHashContent), 0, NULL, NULL, NULL, &hashSize);
173 ok(!ret && GetLastError() == CRYPT_E_HASH_VALUE,
174 "expected CRYPT_E_HASH_VALUE, got %08x\n", GetLastError());
175 size = sizeof(msgData);
176 pMsgData = msgData;
177 ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
178 sizeof(detachedHashContent), 1, &pMsgData, &size, NULL, &hashSize);
179 ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
180 ok(hashSize == sizeof(hash), "unexpected size %d\n", hashSize);
181 hashSize = 1;
182 SetLastError(0xdeadbeef);
183 ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
184 sizeof(detachedHashContent), 1, &pMsgData, &size, hash, &hashSize);
185 ok(!ret && GetLastError() == ERROR_MORE_DATA,
186 "expected ERROR_MORE_DATA, got %08x\n", GetLastError());
187 hashSize = sizeof(hash);
188 ret = CryptVerifyDetachedMessageHash(&para, detachedHashContent,
189 sizeof(detachedHashContent), 1, &pMsgData, &size, hash, &hashSize);
190 ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
193 static BYTE hashContent[] = {
194 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
195 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
196 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
197 0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
198 0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
200 static void test_verify_message_hash(void)
202 BOOL ret;
203 CRYPT_HASH_MESSAGE_PARA para;
204 DWORD size;
205 BYTE *buf = NULL;
207 memset(&para, 0, sizeof(para));
208 /* Crash */
209 if (0)
210 ret = CryptVerifyMessageHash(NULL, NULL, 0, NULL, NULL, NULL, NULL);
211 SetLastError(0xdeadbeef);
212 ret = CryptVerifyMessageHash(&para, NULL, 0, NULL, NULL, NULL, NULL);
213 ok(!ret && GetLastError() == E_INVALIDARG,
214 "expected E_INVALIDARG, got %08x\n", GetLastError());
215 para.cbSize = sizeof(para);
216 SetLastError(0xdeadbeef);
217 ret = CryptVerifyMessageHash(&para, NULL, 0, NULL, NULL, NULL, NULL);
218 ok(!ret && GetLastError() == E_INVALIDARG,
219 "expected E_INVALIDARG, got %08x\n", GetLastError());
220 para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
221 SetLastError(0xdeadbeef);
222 ret = CryptVerifyMessageHash(&para, NULL, 0, NULL, NULL, NULL, NULL);
223 ok(!ret, "Expected 0, got %d\n", ret);
224 ok(GetLastError() == CRYPT_E_ASN1_EOD ||
225 GetLastError() == OSS_BAD_ARG, /* win98 */
226 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
227 /* Verifying the hash of a detached message succeeds? */
228 ret = CryptVerifyMessageHash(&para, detachedHashContent,
229 sizeof(detachedHashContent), NULL, NULL, NULL, NULL);
230 todo_wine
231 ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
232 /* As does verifying the hash of a regular message. */
233 ret = CryptVerifyMessageHash(&para, hashContent, sizeof(hashContent),
234 NULL, NULL, NULL, NULL);
235 ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
236 ret = CryptVerifyMessageHash(&para, hashContent, sizeof(hashContent),
237 NULL, &size, NULL, NULL);
238 ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
239 if (ret)
240 buf = CryptMemAlloc(size);
241 if (buf)
243 size = 1;
244 ret = CryptVerifyMessageHash(&para, hashContent, sizeof(hashContent),
245 buf, &size, NULL, NULL);
246 ok(!ret && GetLastError() == ERROR_MORE_DATA,
247 "expected ERROR_MORE_DATA, got %08x\n", GetLastError());
248 ret = CryptVerifyMessageHash(&para, hashContent, sizeof(hashContent),
249 buf, &size, NULL, NULL);
250 ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
251 ok(size == sizeof(msgData), "unexpected size %d\n", size);
252 ok(!memcmp(buf, msgData, size), "unexpected value\n");
253 CryptMemFree(buf);
257 static const BYTE signedWithCertContent[] = {
258 0x30,0x82,0x01,0x32,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
259 0xa0,0x82,0x01,0x23,0x30,0x82,0x01,0x1f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,
260 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,
261 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,
262 0x02,0x03,0x04,0xa0,0x7c,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
263 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
264 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
265 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
266 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
267 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
268 0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
269 0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
270 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,0x77,0x30,0x75,0x02,0x01,
271 0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,
272 0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,
273 0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,
274 0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,
275 0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,
276 0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,
277 0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,
278 0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
279 static const BYTE signedContent[] = {
280 0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
281 0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
282 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
283 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
284 0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,
285 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
286 0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
287 0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,
288 0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,
289 0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,
290 0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,
291 0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,
292 0x0d };
293 static const BYTE detachedSignedContent[] = {
294 0x30,0x81,0xaa,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
295 0x81,0x9c,0x30,0x81,0x99,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
296 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,
297 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,
298 0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
299 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,
300 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,
301 0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,
302 0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,
303 0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,
304 0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,
305 0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
306 static const BYTE v1CertWithValidPubKey[] = {
307 0x30,0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
308 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
309 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
310 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
311 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
312 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
313 0x67,0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
314 0x01,0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,
315 0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,
316 0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,
317 0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,
318 0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,
319 0x79,0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
320 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
322 static PCCERT_CONTEXT WINAPI msg_get_signer_callback(void *pvArg,
323 DWORD certEncodingType, PCERT_INFO signerId, HCERTSTORE store)
325 return CertCreateCertificateContext(X509_ASN_ENCODING,
326 v1CertWithValidPubKey, sizeof(v1CertWithValidPubKey));
329 static void test_verify_detached_message_signature(void)
331 CRYPT_VERIFY_MESSAGE_PARA para;
332 BOOL ret;
333 const BYTE *pContent;
334 DWORD cbContent;
336 memset(&para, 0, sizeof(para));
337 SetLastError(0xdeadbeef);
338 ret = CryptVerifyDetachedMessageSignature(NULL, 0, NULL, 0, 0, NULL,
339 NULL, NULL);
340 ok(!ret && GetLastError() == E_INVALIDARG,
341 "Expected E_INVALIDARG, got %08x\n", GetLastError());
342 SetLastError(0xdeadbeef);
343 ret = CryptVerifyDetachedMessageSignature(&para, 0, NULL, 0, 0, NULL,
344 NULL, NULL);
345 ok(!ret && GetLastError() == E_INVALIDARG,
346 "Expected E_INVALIDARG, got %08x\n", GetLastError());
347 para.cbSize = sizeof(para);
348 SetLastError(0xdeadbeef);
349 ret = CryptVerifyDetachedMessageSignature(&para, 0, NULL, 0, 0, NULL,
350 NULL, NULL);
351 ok(!ret && GetLastError() == E_INVALIDARG,
352 "Expected E_INVALIDARG, got %08x\n", GetLastError());
353 para.dwMsgAndCertEncodingType = X509_ASN_ENCODING;
354 SetLastError(0xdeadbeef);
355 ret = CryptVerifyDetachedMessageSignature(&para, 0, NULL, 0, 0, NULL,
356 NULL, NULL);
357 ok(!ret && GetLastError() == E_INVALIDARG,
358 "Expected E_INVALIDARG, got %08x\n", GetLastError());
359 para.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING;
360 SetLastError(0xdeadbeef);
361 ret = CryptVerifyDetachedMessageSignature(&para, 0, NULL, 0, 0, NULL,
362 NULL, NULL);
363 ok(!ret, "Expected 0, got %d\n", ret);
364 ok(GetLastError() == CRYPT_E_ASN1_EOD ||
365 GetLastError() == OSS_BAD_ARG, /* win98 */
366 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
367 /* None of these messages contains a cert in the message itself, so the
368 * default callback isn't able to verify their signature.
370 SetLastError(0xdeadbeef);
371 ret = CryptVerifyDetachedMessageSignature(&para, 0, signedWithCertContent,
372 sizeof(signedWithCertContent), 0, NULL, NULL, NULL);
373 ok(!ret, "Expected 0, got %d\n", ret);
374 todo_wine
375 ok(GetLastError() == CRYPT_E_NOT_FOUND ||
376 GetLastError() == OSS_DATA_ERROR, /* win98 */
377 "Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
378 SetLastError(0xdeadbeef);
379 ret = CryptVerifyDetachedMessageSignature(&para, 0, signedContent,
380 sizeof(signedContent), 0, NULL, NULL, NULL);
381 ok(!ret, "Expected 0, got %d\n", ret);
382 ok(GetLastError() == CRYPT_E_NOT_FOUND ||
383 GetLastError() == OSS_DATA_ERROR, /* win98 */
384 "Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
385 SetLastError(0xdeadbeef);
386 ret = CryptVerifyDetachedMessageSignature(&para, 0, detachedSignedContent,
387 sizeof(detachedSignedContent), 0, NULL, NULL, NULL);
388 ok(!ret, "Expected 0, got %d\n", ret);
389 ok(GetLastError() == CRYPT_E_NOT_FOUND ||
390 GetLastError() == OSS_DATA_ERROR, /* win98 */
391 "Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
392 SetLastError(0xdeadbeef);
393 pContent = msgData;
394 cbContent = sizeof(msgData);
395 ret = CryptVerifyDetachedMessageSignature(&para, 0, detachedSignedContent,
396 sizeof(detachedSignedContent), 1, &pContent, &cbContent, NULL);
397 ok(!ret, "Expected 0, got %d\n", ret);
398 ok(GetLastError() == CRYPT_E_NOT_FOUND ||
399 GetLastError() == OSS_DATA_ERROR, /* win98 */
400 "Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
401 /* Passing the correct callback results in success */
402 para.pfnGetSignerCertificate = msg_get_signer_callback;
403 ret = CryptVerifyDetachedMessageSignature(&para, 0, detachedSignedContent,
404 sizeof(detachedSignedContent), 1, &pContent, &cbContent, NULL);
405 ok(ret ||
406 broken(!ret), /* win98 */
407 "CryptVerifyDetachedMessageSignature failed: %08x\n",
408 GetLastError());
409 /* Not passing the correct data to be signed results in the signature not
410 * matching.
412 SetLastError(0xdeadbeef);
413 ret = CryptVerifyDetachedMessageSignature(&para, 0, detachedSignedContent,
414 sizeof(detachedSignedContent), 0, NULL, NULL, NULL);
415 ok(!ret, "Expected 0, got %d\n", ret);
416 ok(GetLastError() == NTE_BAD_SIGNATURE ||
417 GetLastError() == OSS_DATA_ERROR, /* win98 */
418 "Expected NTE_BAD_SIGNATURE or OSS_DATA_ERROR, got %08x\n", GetLastError());
421 static const BYTE signedWithCertEmptyContent[] = {
422 0x30,0x81,0xdf,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
423 0x81,0xd1,0x30,0x81,0xce,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
424 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x7c,
425 0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
426 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
427 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
428 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
429 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
430 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
431 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,
432 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
433 0xff,0x02,0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,
434 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
435 0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,
436 0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
437 0x00 };
438 static const BYTE signedWithCertWithPubKeyContent[] = {
439 0x30,0x81,0xfc,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
440 0x81,0xee,0x30,0x81,0xeb,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
441 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x81,
442 0x98,0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,
443 0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,
444 0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
445 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
446 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,
447 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
448 0x6e,0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
449 0x01,0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,
450 0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,
451 0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,
452 0x02,0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
453 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
454 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
455 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
456 static const BYTE signedWithCertWithValidPubKeyContent[] = {
457 0x30,0x82,0x01,0x89,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
458 0xa0,0x82,0x01,0x7a,0x30,0x82,0x01,0x76,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,
459 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,
460 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,
461 0x02,0x03,0x04,0xa0,0x81,0xd2,0x30,0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,
462 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
463 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
464 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
465 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
466 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
467 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,
468 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,
469 0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,
470 0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
471 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,
472 0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,
473 0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,
474 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
475 0x01,0x01,0xff,0x02,0x01,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
476 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
477 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
478 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
479 0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,
480 0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,
481 0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,
482 0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,
483 0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
485 static void test_verify_message_signature(void)
487 BOOL ret;
488 CRYPT_VERIFY_MESSAGE_PARA para = { 0 };
489 PCCERT_CONTEXT cert;
490 DWORD cbDecoded;
491 BYTE decoded[sizeof(msgData)];
493 SetLastError(0xdeadbeef);
494 ret = CryptVerifyMessageSignature(NULL, 0, NULL, 0, NULL, 0, NULL);
495 ok(!ret && GetLastError() == E_INVALIDARG,
496 "Expected E_INVALIDARG, got %08x\n", GetLastError());
497 /* Is cbDecoded set when invalid parameters are passed? */
498 cbDecoded = 0xdeadbeef;
499 ret = CryptVerifyMessageSignature(NULL, 0, NULL, 0, NULL, &cbDecoded,
500 NULL);
501 ok(cbDecoded == 0, "expected 0, got %08x\n", cbDecoded);
502 SetLastError(0xdeadbeef);
503 ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
504 ok(!ret && GetLastError() == E_INVALIDARG,
505 "Expected E_INVALIDARG, got %08x\n", GetLastError());
506 para.cbSize = sizeof(para);
507 SetLastError(0xdeadbeef);
508 ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
509 ok(!ret && GetLastError() == E_INVALIDARG,
510 "Expected E_INVALIDARG, got %08x\n", GetLastError());
511 para.cbSize = 0;
512 para.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING;
513 SetLastError(0xdeadbeef);
514 ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
515 ok(!ret && GetLastError() == E_INVALIDARG,
516 "Expected E_INVALIDARG, got %08x\n", GetLastError());
517 para.cbSize = sizeof(para);
518 SetLastError(0xdeadbeef);
519 ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, NULL);
520 ok(!ret &&
521 (GetLastError() == CRYPT_E_ASN1_EOD ||
522 GetLastError() == OSS_BAD_ARG), /* win9x */
523 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
524 /* Check whether cert is set on error */
525 cert = (PCCERT_CONTEXT)0xdeadbeef;
526 ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, 0, &cert);
527 ok(cert == NULL, "Expected NULL cert\n");
528 /* Check whether cbDecoded is set on error */
529 cbDecoded = 0xdeadbeef;
530 ret = CryptVerifyMessageSignature(&para, 0, NULL, 0, NULL, &cbDecoded,
531 NULL);
532 ok(!cbDecoded, "Expected 0\n");
533 SetLastError(0xdeadbeef);
534 ret = CryptVerifyMessageSignature(&para, 0, dataEmptyBareContent,
535 sizeof(dataEmptyBareContent), NULL, 0, NULL);
536 ok(GetLastError() == CRYPT_E_ASN1_BADTAG ||
537 GetLastError() == OSS_PDU_MISMATCH, /* win9x */
538 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
539 SetLastError(0xdeadbeef);
540 ret = CryptVerifyMessageSignature(&para, 0, dataEmptyContent,
541 sizeof(dataEmptyContent), NULL, 0, NULL);
542 ok(!ret && GetLastError() == CRYPT_E_UNEXPECTED_MSG_TYPE,
543 "Expected CRYPT_E_UNEXPECTED_MSG_TYPE, got %08x\n", GetLastError());
544 SetLastError(0xdeadbeef);
545 ret = CryptVerifyMessageSignature(&para, 0, signedEmptyBareContent,
546 sizeof(signedEmptyBareContent), NULL, 0, NULL);
547 ok(!ret &&
548 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
549 GetLastError() == OSS_DATA_ERROR), /* win9x */
550 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
551 SetLastError(0xdeadbeef);
552 ret = CryptVerifyMessageSignature(&para, 0, signedEmptyContent,
553 sizeof(signedEmptyContent), NULL, 0, NULL);
554 ok(!ret &&
555 (GetLastError() == CRYPT_E_NOT_FOUND ||
556 GetLastError() == OSS_DATA_ERROR), /* win9x */
557 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
558 SetLastError(0xdeadbeef);
559 ret = CryptVerifyMessageSignature(&para, 0, signedContent,
560 sizeof(signedContent), NULL, 0, NULL);
561 ok(!ret &&
562 (GetLastError() == CRYPT_E_NOT_FOUND ||
563 GetLastError() == OSS_DATA_ERROR), /* win9x */
564 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
565 /* FIXME: Windows fails with CRYPT_E_NOT_FOUND for these messages, but
566 * their signer certs have invalid public keys that fail to decode. In
567 * Wine therefore the failure is an ASN error. Need some messages with
568 * valid public keys and invalid signatures to check against.
570 ret = CryptVerifyMessageSignature(&para, 0, signedWithCertEmptyContent,
571 sizeof(signedWithCertEmptyContent), NULL, 0, NULL);
572 ok(!ret, "Expected failure\n");
573 ret = CryptVerifyMessageSignature(&para, 0, signedWithCertContent,
574 sizeof(signedWithCertContent), NULL, 0, NULL);
575 ok(!ret, "Expected failure\n");
576 ret = CryptVerifyMessageSignature(&para, 0, signedWithCertWithPubKeyContent,
577 sizeof(signedWithCertWithPubKeyContent), NULL, 0, NULL);
578 ok(!ret, "Expected failure\n");
579 /* Apparently, an output pcbDecoded parameter is expected. */
580 ret = CryptVerifyMessageSignature(&para, 0,
581 signedWithCertWithValidPubKeyContent,
582 sizeof(signedWithCertWithValidPubKeyContent), NULL, 0, NULL);
583 ok(!ret, "Expected failure\n");
584 /* Finally, a message signed with a valid public key verifies successfully
586 cbDecoded = 0xdeadbeef;
587 ret = CryptVerifyMessageSignature(&para, 0,
588 signedWithCertWithValidPubKeyContent,
589 sizeof(signedWithCertWithValidPubKeyContent), NULL, &cbDecoded, NULL);
590 ok(ret, "CryptVerifyMessageSignature failed: %08x\n", GetLastError());
591 ok(cbDecoded == sizeof(msgData), "expected 4, got %d\n", cbDecoded);
592 cbDecoded = 0;
593 ret = CryptVerifyMessageSignature(&para, 0,
594 signedWithCertWithValidPubKeyContent,
595 sizeof(signedWithCertWithValidPubKeyContent), NULL, &cbDecoded, NULL);
596 /* Setting cbDecoded to 0 succeeds when a NULL buffer is provided */
597 ok(ret, "CryptVerifyMessageSignature failed: %08x\n", GetLastError());
598 ok(cbDecoded == sizeof(msgData), "expected 4, got %d\n", cbDecoded);
599 cbDecoded = 0;
600 ret = CryptVerifyMessageSignature(&para, 0,
601 signedWithCertWithValidPubKeyContent,
602 sizeof(signedWithCertWithValidPubKeyContent), decoded, &cbDecoded, NULL);
603 /* When a non-NULL buffer is provided, cbDecoded must not be too small */
604 ok(!ret && GetLastError() == ERROR_MORE_DATA,
605 "expected ERROR_MORE_DATA, got %d (%08x)\n", GetLastError(),
606 GetLastError());
609 static const BYTE detachedHashBlob[] = {
610 0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
611 0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
612 0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
613 0x07,0x01,0x04,0x10,0x2d,0x1b,0xbc,0x1f,0xc7,0xab,0x36,0x8d,0xdb,0x95,0xe6,
614 0x24,0xb9,0x66,0x7c,0x21 };
615 static const BYTE hashBlob[] = {
616 0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
617 0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
618 0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
619 0x07,0x01,0xa0,0x06,0x04,0x04,0xde,0xad,0xbe,0xef,0x04,0x10,0x2f,0x24,0x92,
620 0x30,0xa8,0xe7,0xc2,0xbf,0x60,0x05,0xcc,0xd2,0x67,0x92,0x59,0xec };
621 static const BYTE hashVal[] = {
622 0x2d,0x1b,0xbc,0x1f,0xc7,0xab,0x36,0x8d,0xdb,0x95,0xe6,0x24,0xb9,0x66,0x7c,
623 0x21 };
625 static void test_hash_message(void)
627 BOOL ret;
628 CRYPT_HASH_MESSAGE_PARA para;
629 static const BYTE blob1[] = { 0xde, 0xad, 0xbe, 0xef };
630 static const BYTE blob2[] = { 0xba, 0xad, 0xf0, 0x0d };
631 const BYTE *toHash[] = { blob1, blob2 };
632 DWORD hashSize[] = { sizeof(blob1), sizeof(blob2) };
633 DWORD hashedBlobSize, computedHashSize;
634 static char oid_rsa_md5[] = szOID_RSA_MD5;
635 LPBYTE hashedBlob, computedHash;
637 /* Crash
638 ret = CryptHashMessage(NULL, FALSE, 0, NULL, 0, NULL, NULL, NULL, NULL);
640 memset(&para, 0, sizeof(para));
641 SetLastError(0xdeadbeef);
642 ret = CryptHashMessage(&para, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
643 ok(!ret && GetLastError() == E_INVALIDARG,
644 "expected E_INVALIDARG, got 0x%08x\n", GetLastError());
645 para.cbSize = sizeof(para);
646 /* Not quite sure what "success" means in this case, but it does succeed */
647 SetLastError(0xdeadbeef);
648 ret = CryptHashMessage(&para, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
649 ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
650 /* With a bogus encoding type it "succeeds" */
651 para.dwMsgEncodingType = 0xdeadbeef;
652 SetLastError(0xdeadbeef);
653 ret = CryptHashMessage(&para, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
654 ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
655 /* According to MSDN, the third parameter (cToBeHashed) must be 1 if the
656 * second parameter (fDetached) is FALSE, but again it "succeeds."
658 SetLastError(0xdeadbeef);
659 ret = CryptHashMessage(&para, FALSE, 2, NULL, NULL, NULL, NULL, NULL, NULL);
660 ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
661 /* Even passing parameters to hash results in "success." */
662 SetLastError(0xdeadbeef);
663 ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL, NULL, NULL,
664 NULL);
665 /* Try again with a valid encoding type */
666 para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
667 SetLastError(0xdeadbeef);
668 ret = CryptHashMessage(&para, FALSE, 2, NULL, NULL, NULL, NULL, NULL, NULL);
669 ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
670 /* And with valid data to hash */
671 SetLastError(0xdeadbeef);
672 ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL, NULL, NULL,
673 NULL);
674 ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
675 /* But requesting the size of the hashed blob and indicating there's data
676 * to hash results in a crash
678 if (0)
680 ret = CryptHashMessage(&para, FALSE, 2, NULL, NULL, NULL,
681 &hashedBlobSize, NULL, NULL);
683 /* Passing a valid pointer for the data to hash fails, as the hash
684 * algorithm is finally checked.
686 SetLastError(0xdeadbeef);
687 ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL,
688 &hashedBlobSize, NULL, NULL);
689 ok(!ret &&
690 (GetLastError() == CRYPT_E_UNKNOWN_ALGO ||
691 GetLastError() == CRYPT_E_OID_FORMAT), /* Vista */
692 "expected CRYPT_E_UNKNOWN_ALGO or CRYPT_E_OID_FORMAT, got 0x%08x (%d)\n",
693 GetLastError(), GetLastError());
694 para.HashAlgorithm.pszObjId = oid_rsa_md5;
695 /* With a valid hash algorithm, this succeeds, even though fDetached is
696 * FALSE.
698 SetLastError(0xdeadbeef);
699 ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, NULL,
700 &hashedBlobSize, NULL, NULL);
701 todo_wine
702 ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
703 if (ret)
705 /* Actually attempting to get the hashed data fails, perhaps because
706 * detached is FALSE.
708 hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
709 SetLastError(0xdeadbeef);
710 ret = CryptHashMessage(&para, FALSE, 2, toHash, hashSize, hashedBlob,
711 &hashedBlobSize, NULL, NULL);
712 ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
713 "expected CRYPT_E_MSG_ERROR, got 0x%08x (%d)\n", GetLastError(),
714 GetLastError());
715 HeapFree(GetProcessHeap(), 0, hashedBlob);
717 /* Repeating tests with fDetached = TRUE results in success */
718 SetLastError(0xdeadbeef);
719 ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, NULL,
720 &hashedBlobSize, NULL, NULL);
721 ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
722 if (ret)
724 hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
725 SetLastError(0xdeadbeef);
726 ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, hashedBlob,
727 &hashedBlobSize, NULL, NULL);
728 ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
729 ok(hashedBlobSize == sizeof(detachedHashBlob),
730 "unexpected size of detached blob %d\n", hashedBlobSize);
731 ok(!memcmp(hashedBlob, detachedHashBlob, hashedBlobSize),
732 "unexpected detached blob value\n");
733 HeapFree(GetProcessHeap(), 0, hashedBlob);
735 /* Hashing a single item with fDetached = FALSE also succeeds */
736 SetLastError(0xdeadbeef);
737 ret = CryptHashMessage(&para, FALSE, 1, toHash, hashSize, NULL,
738 &hashedBlobSize, NULL, NULL);
739 ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
740 if (ret)
742 hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
743 ret = CryptHashMessage(&para, FALSE, 1, toHash, hashSize, hashedBlob,
744 &hashedBlobSize, NULL, NULL);
745 ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
746 ok(hashedBlobSize == sizeof(hashBlob),
747 "unexpected size of detached blob %d\n", hashedBlobSize);
748 ok(!memcmp(hashedBlob, hashBlob, hashedBlobSize),
749 "unexpected detached blob value\n");
750 HeapFree(GetProcessHeap(), 0, hashedBlob);
752 /* Check the computed hash value too. You don't need to get the encoded
753 * blob to get it.
755 computedHashSize = 0xdeadbeef;
756 ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, NULL,
757 &hashedBlobSize, NULL, &computedHashSize);
758 ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
759 ok(computedHashSize == 16, "expected hash size of 16, got %d\n",
760 computedHashSize);
761 if (ret)
763 computedHash = HeapAlloc(GetProcessHeap(), 0, computedHashSize);
764 SetLastError(0xdeadbeef);
765 ret = CryptHashMessage(&para, TRUE, 2, toHash, hashSize, NULL,
766 &hashedBlobSize, computedHash, &computedHashSize);
767 ok(computedHashSize == sizeof(hashVal),
768 "unexpected size of hash value %d\n", computedHashSize);
769 ok(!memcmp(computedHash, hashVal, computedHashSize),
770 "unexpected value\n");
771 HeapFree(GetProcessHeap(), 0, computedHash);
775 static const BYTE publicPrivateKeyPair[] = {
776 0x07,0x02,0x00,0x00,0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x32,0x00,0x02,0x00,
777 0x00,0x01,0x00,0x01,0x00,0x9b,0xd9,0x60,0xd9,0x5b,0x09,0x50,0x9e,0x09,0x94,
778 0x1e,0x6a,0x06,0x1d,0xdd,0x39,0xc5,0x96,0x17,0xe3,0xb9,0x0c,0x71,0x9c,0xf7,
779 0xc1,0x07,0x7b,0xd7,0x4a,0xaa,0x8a,0x3e,0xcd,0x78,0x3c,0x4c,0x95,0x98,0x28,
780 0x29,0x2d,0xe0,0xfc,0xe6,0x4f,0x95,0xca,0x87,0x92,0xdd,0xa3,0x8d,0xf0,0x39,
781 0xf3,0x1b,0x87,0x64,0x82,0x99,0xc0,0xa9,0xe8,0x87,0x86,0x2e,0x72,0x07,0x07,
782 0x8f,0x45,0x54,0x51,0x2f,0x51,0xd0,0x60,0x97,0x48,0x54,0x0e,0x78,0xb5,0x7e,
783 0x2b,0x9d,0xca,0x81,0xa8,0xa8,0x00,0x57,0x69,0xa6,0xf7,0x4d,0x45,0xe0,0xf7,
784 0xfa,0xd2,0xeb,0xaa,0xb8,0x06,0x34,0xce,0xf0,0x9d,0x2b,0x76,0x8a,0x4f,0x70,
785 0x51,0x90,0x33,0x72,0xcb,0x81,0x85,0x7e,0x35,0x2e,0xfb,0x81,0xf0,0xc7,0x85,
786 0xa5,0x75,0xf9,0x2d,0x00,0x71,0x66,0x36,0xfe,0x22,0xd6,0xc9,0x36,0x61,0x9b,
787 0x64,0x92,0xe8,0x25,0x38,0x35,0xeb,0x0c,0x84,0x83,0x76,0x42,0x90,0xf7,0x73,
788 0x91,0xdc,0x43,0x83,0x07,0x77,0xc9,0x1b,0x3f,0x74,0xc0,0xbe,0x18,0x97,0xd6,
789 0x86,0xe5,0xfa,0x28,0x7c,0xf7,0x8d,0x89,0xb1,0x93,0xac,0x48,0x3c,0xa1,0x02,
790 0xfa,0xc6,0x1c,0xa0,0xb5,0xe8,0x4f,0xd7,0xd1,0x33,0x63,0x8b,0x7e,0xf1,0x94,
791 0x56,0x07,0xbc,0x6e,0x0c,0xbd,0xa0,0x15,0xba,0x99,0x5d,0xb7,0x5e,0x09,0xf2,
792 0x1b,0x46,0x85,0x61,0x91,0x6a,0x78,0x31,0xb5,0xf0,0xba,0x20,0xf5,0x7a,0xb4,
793 0x8e,0xd3,0x50,0x87,0xf8,0xf3,0xe4,0xd9,0xab,0x6f,0x0e,0x59,0x42,0xac,0x7d,
794 0xb1,0x8c,0xea,0x33,0x54,0x08,0x38,0xc9,0xcd,0xac,0x10,0x19,0x4a,0xba,0x89,
795 0xdc,0xb6,0x73,0xef,0xec,0x56,0x93,0xd6,0xf2,0x4b,0xba,0x50,0x2d,0x8f,0x15,
796 0xed,0x8b,0xb5,0x67,0xc8,0xfc,0x51,0x5f };
797 static const BYTE certForSigning[] = {
798 0x30,0x81,0xd0,0x30,0x81,0xbe,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x20,0x42,
799 0x68,0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,
800 0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x0c,0x31,0x0a,0x30,
801 0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x30,0x20,0x17,0x0d,0x31,0x30,
802 0x30,0x39,0x31,0x34,0x31,0x33,0x31,0x39,0x30,0x39,0x5a,0x18,0x0f,0x33,0x30,
803 0x31,0x30,0x30,0x39,0x31,0x34,0x31,0x33,0x31,0x39,0x30,0x39,0x5a,0x30,0x0c,
804 0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x30,0x5c,0x30,
805 0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,
806 0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe8,0xa9,0xc0,0x99,0x82,0x64,0x87,0x1b,
807 0xf3,0x39,0xf0,0x8d,0xa3,0xdd,0x92,0x87,0xca,0x95,0x4f,0xe6,0xfc,0xe0,0x2d,
808 0x29,0x28,0x98,0x95,0x4c,0x3c,0x78,0xcd,0x3e,0x8a,0xaa,0x4a,0xd7,0x7b,0x07,
809 0xc1,0xf7,0x9c,0x71,0x0c,0xb9,0xe3,0x17,0x96,0xc5,0x39,0xdd,0x1d,0x06,0x6a,
810 0x1e,0x94,0x09,0x9e,0x50,0x09,0x5b,0xd9,0x60,0xd9,0x9b,0x02,0x03,0x01,0x00,
811 0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x02,0x00,
812 0xc1 };
813 static const BYTE crl[] = {
814 0x30,0x81,0xc2,0x30,0x7e,0x02,0x01,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
815 0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x3c,0x31,0x0b,0x30,0x09,0x06,
816 0x03,0x55,0x04,0x06,0x13,0x02,0x52,0x55,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,
817 0x04,0x08,0x13,0x03,0x53,0x50,0x62,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,0x04,
818 0x07,0x13,0x03,0x53,0x50,0x62,0x31,0x11,0x30,0x0f,0x06,0x03,0x55,0x04,0x0a,
819 0x13,0x08,0x45,0x74,0x65,0x72,0x73,0x6f,0x66,0x74,0x17,0x0d,0x31,0x30,0x30,
820 0x36,0x32,0x38,0x31,0x32,0x35,0x31,0x32,0x37,0x5a,0x17,0x0d,0x31,0x30,0x30,
821 0x37,0x32,0x38,0x31,0x32,0x35,0x31,0x32,0x37,0x5a,0xa0,0x0e,0x30,0x0c,0x30,
822 0x0a,0x06,0x03,0x55,0x1d,0x14,0x04,0x03,0x02,0x01,0x00,0x30,0x0d,0x06,0x09,
823 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x31,0x00,0x83,
824 0x35,0x9c,0xf5,0x35,0x5c,0xc1,0x20,0x81,0x80,0x5c,0x35,0x56,0xaf,0xb3,0x27,
825 0x15,0xc6,0xdd,0x24,0xe1,0xff,0xb9,0xf9,0x19,0x21,0xed,0x5e,0x1b,0xff,0x72,
826 0xc3,0x33,0xf6,0x9f,0xcb,0xde,0x84,0x0b,0x12,0x84,0xad,0x48,0x90,0x9d,0xdd,
827 0x89,0xbb };
828 static const BYTE signedHashForEmptyMessage[] = {
829 0x30,0x81,0xbb,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
830 0x81,0xad,0x30,0x81,0xaa,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
831 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,
832 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x31,0x81,0x87,0x30,0x81,0x84,0x02,0x01,
833 0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,
834 0x01,0x4e,0x02,0x10,0x20,0x42,0x68,0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,
835 0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
836 0x02,0x05,0x05,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
837 0x01,0x01,0x05,0x00,0x04,0x40,0xe1,0xee,0xca,0x98,0x16,0x23,0x5a,0x34,0xfd,
838 0x91,0x69,0x97,0x1e,0x16,0xe4,0x57,0x45,0xad,0xc9,0x5d,0x2e,0xda,0x92,0xbf,
839 0xee,0x2f,0xb1,0xaa,0x32,0xfa,0x07,0x4e,0x63,0xfd,0xe1,0x52,0x17,0xd0,0xa4,
840 0x49,0x30,0x54,0x4d,0x12,0xa0,0x6a,0x1c,0x64,0xea,0xc7,0x50,0x49,0xa5,0xca,
841 0xc3,0x71,0xa4,0xf7,0x8c,0x25,0xe4,0x1a,0xca,0x89 };
842 static const BYTE signedEmptyMessage[] = {
843 0x30,0x81,0xbb,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
844 0x81,0xad,0x30,0x81,0xaa,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
845 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,
846 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x31,0x81,0x87,0x30,0x81,0x84,0x02,0x01,
847 0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,
848 0x01,0x4e,0x02,0x10,0x20,0x42,0x68,0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,
849 0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
850 0x02,0x05,0x05,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
851 0x01,0x01,0x05,0x00,0x04,0x40,0xe1,0xee,0xca,0x98,0x16,0x23,0x5a,0x34,0xfd,
852 0x91,0x69,0x97,0x1e,0x16,0xe4,0x57,0x45,0xad,0xc9,0x5d,0x2e,0xda,0x92,0xbf,
853 0xee,0x2f,0xb1,0xaa,0x32,0xfa,0x07,0x4e,0x63,0xfd,0xe1,0x52,0x17,0xd0,0xa4,
854 0x49,0x30,0x54,0x4d,0x12,0xa0,0x6a,0x1c,0x64,0xea,0xc7,0x50,0x49,0xa5,0xca,
855 0xc3,0x71,0xa4,0xf7,0x8c,0x25,0xe4,0x1a,0xca,0x89 };
856 static const BYTE signedHash[] = {
857 0x30,0x81,0xbb,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
858 0x81,0xad,0x30,0x81,0xaa,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
859 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,
860 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x31,0x81,0x87,0x30,0x81,0x84,0x02,0x01,
861 0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,
862 0x01,0x4e,0x02,0x10,0x20,0x42,0x68,0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,
863 0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
864 0x02,0x05,0x05,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
865 0x01,0x01,0x05,0x00,0x04,0x40,0x1e,0x04,0xa4,0xe3,0x90,0x54,0xed,0xcb,0x94,
866 0xa2,0xbe,0x81,0x73,0x7e,0x05,0xf2,0x82,0xd3,0x3a,0x26,0x96,0x7a,0x53,0xcd,
867 0x05,0xc3,0x09,0x69,0x3d,0x12,0x6c,0xb1,0xb0,0xab,0x0e,0xa1,0xec,0x1b,0xa1,
868 0xff,0x01,0x9c,0x49,0x9f,0x4b,0x69,0x59,0x74,0x20,0x9f,0xb0,0x19,0x95,0xe7,
869 0xed,0x1e,0x84,0xeb,0xe2,0x53,0x2c,0xa6,0x43,0xdf };
870 static const BYTE signedHashWithCert[] = {
871 0x30,0x82,0x01,0x93,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
872 0xa0,0x82,0x01,0x84,0x30,0x82,0x01,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,
873 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,
874 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x81,0xd3,0x30,0x81,
875 0xd0,0x30,0x81,0xbe,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x20,0x42,0x68,0x69,
876 0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,0x09,0x06,
877 0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,
878 0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x30,0x20,0x17,0x0d,0x31,0x30,0x30,0x39,
879 0x31,0x34,0x31,0x33,0x31,0x39,0x30,0x39,0x5a,0x18,0x0f,0x33,0x30,0x31,0x30,
880 0x30,0x39,0x31,0x34,0x31,0x33,0x31,0x39,0x30,0x39,0x5a,0x30,0x0c,0x31,0x0a,
881 0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x30,0x5c,0x30,0x0d,0x06,
882 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x4b,0x00,
883 0x30,0x48,0x02,0x41,0x00,0xe8,0xa9,0xc0,0x99,0x82,0x64,0x87,0x1b,0xf3,0x39,
884 0xf0,0x8d,0xa3,0xdd,0x92,0x87,0xca,0x95,0x4f,0xe6,0xfc,0xe0,0x2d,0x29,0x28,
885 0x98,0x95,0x4c,0x3c,0x78,0xcd,0x3e,0x8a,0xaa,0x4a,0xd7,0x7b,0x07,0xc1,0xf7,
886 0x9c,0x71,0x0c,0xb9,0xe3,0x17,0x96,0xc5,0x39,0xdd,0x1d,0x06,0x6a,0x1e,0x94,
887 0x09,0x9e,0x50,0x09,0x5b,0xd9,0x60,0xd9,0x9b,0x02,0x03,0x01,0x00,0x01,0x30,
888 0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x02,0x00,0xc1,0x31,
889 0x81,0x87,0x30,0x81,0x84,0x02,0x01,0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,0x30,
890 0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x02,0x10,0x20,0x42,0x68,0x69,
891 0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,0x06,
892 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0d,0x06,0x09,
893 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x04,0x40,0x1e,0x04,
894 0xa4,0xe3,0x90,0x54,0xed,0xcb,0x94,0xa2,0xbe,0x81,0x73,0x7e,0x05,0xf2,0x82,
895 0xd3,0x3a,0x26,0x96,0x7a,0x53,0xcd,0x05,0xc3,0x09,0x69,0x3d,0x12,0x6c,0xb1,
896 0xb0,0xab,0x0e,0xa1,0xec,0x1b,0xa1,0xff,0x01,0x9c,0x49,0x9f,0x4b,0x69,0x59,
897 0x74,0x20,0x9f,0xb0,0x19,0x95,0xe7,0xed,0x1e,0x84,0xeb,0xe2,0x53,0x2c,0xa6,
898 0x43,0xdf };
899 static const BYTE signedHashWithCRL[] = {
900 0x30,0x82,0x01,0x85,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
901 0xa0,0x82,0x01,0x76,0x30,0x82,0x01,0x72,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,
902 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,
903 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa1,0x81,0xc5,0x30,0x81,
904 0xc2,0x30,0x7e,0x02,0x01,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
905 0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x3c,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,
906 0x04,0x06,0x13,0x02,0x52,0x55,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,0x04,0x08,
907 0x13,0x03,0x53,0x50,0x62,0x31,0x0c,0x30,0x0a,0x06,0x03,0x55,0x04,0x07,0x13,
908 0x03,0x53,0x50,0x62,0x31,0x11,0x30,0x0f,0x06,0x03,0x55,0x04,0x0a,0x13,0x08,
909 0x45,0x74,0x65,0x72,0x73,0x6f,0x66,0x74,0x17,0x0d,0x31,0x30,0x30,0x36,0x32,
910 0x38,0x31,0x32,0x35,0x31,0x32,0x37,0x5a,0x17,0x0d,0x31,0x30,0x30,0x37,0x32,
911 0x38,0x31,0x32,0x35,0x31,0x32,0x37,0x5a,0xa0,0x0e,0x30,0x0c,0x30,0x0a,0x06,
912 0x03,0x55,0x1d,0x14,0x04,0x03,0x02,0x01,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,
913 0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x31,0x00,0x83,0x35,0x9c,
914 0xf5,0x35,0x5c,0xc1,0x20,0x81,0x80,0x5c,0x35,0x56,0xaf,0xb3,0x27,0x15,0xc6,
915 0xdd,0x24,0xe1,0xff,0xb9,0xf9,0x19,0x21,0xed,0x5e,0x1b,0xff,0x72,0xc3,0x33,
916 0xf6,0x9f,0xcb,0xde,0x84,0x0b,0x12,0x84,0xad,0x48,0x90,0x9d,0xdd,0x89,0xbb,
917 0x31,0x81,0x87,0x30,0x81,0x84,0x02,0x01,0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,
918 0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x02,0x10,0x20,0x42,0x68,
919 0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,
920 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0d,0x06,
921 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x04,0x40,0x1e,
922 0x04,0xa4,0xe3,0x90,0x54,0xed,0xcb,0x94,0xa2,0xbe,0x81,0x73,0x7e,0x05,0xf2,
923 0x82,0xd3,0x3a,0x26,0x96,0x7a,0x53,0xcd,0x05,0xc3,0x09,0x69,0x3d,0x12,0x6c,
924 0xb1,0xb0,0xab,0x0e,0xa1,0xec,0x1b,0xa1,0xff,0x01,0x9c,0x49,0x9f,0x4b,0x69,
925 0x59,0x74,0x20,0x9f,0xb0,0x19,0x95,0xe7,0xed,0x1e,0x84,0xeb,0xe2,0x53,0x2c,
926 0xa6,0x43,0xdf };
927 static const BYTE signedData[] = {
928 0x30,0x81,0xc3,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
929 0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
930 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
931 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
932 0x31,0x81,0x87,0x30,0x81,0x84,0x02,0x01,0x01,0x30,0x20,0x30,0x0c,0x31,0x0a,
933 0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x4e,0x02,0x10,0x20,0x42,0x68,
934 0x69,0xe9,0xea,0x61,0x83,0x11,0xdf,0xc0,0x24,0x2f,0x3b,0xad,0x40,0x30,0x0c,
935 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0d,0x06,
936 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x04,0x40,0xe4,
937 0x69,0xf5,0x62,0xfb,0x3a,0x7d,0x1c,0x7b,0x8b,0xcc,0xfc,0x6e,0x8e,0x91,0x85,
938 0xcf,0x3c,0xb8,0xfd,0x8a,0xac,0x81,0x96,0xa0,0x42,0xac,0x88,0xc4,0x48,0xe8,
939 0x43,0x64,0xd1,0x38,0xd2,0x6c,0xc4,0xd4,0x9b,0x9a,0xd4,0x33,0x02,0xef,0x88,
940 0xef,0x98,0x2d,0xac,0xad,0xc1,0x93,0x60,0xc4,0x3a,0xdc,0xa7,0xd6,0x97,0x70,
941 0x01,0xc1,0x84 };
943 static void test_sign_message(void)
945 BOOL ret;
946 CRYPT_SIGN_MESSAGE_PARA para;
947 static char oid_rsa_md5[] = szOID_RSA_MD5;
948 static const BYTE blob1[] = { 0x01, 0x02, 0x03, 0x04 };
949 static const BYTE blob2[] = { 0x11, 0x12, 0x13, 0x14 };
950 const BYTE *toSign[] = { blob1, blob2 };
951 DWORD signSize[] = { sizeof(blob1), sizeof(blob2) };
952 LPBYTE signedBlob;
953 DWORD signedBlobSize;
954 PCCRL_CONTEXT crlContext;
955 CERT_KEY_CONTEXT keyContext;
956 HCRYPTPROV hCryptProv = 0;
957 HCRYPTKEY hKey = 0;
959 memset(&para, 0, sizeof(para));
960 SetLastError(0xdeadbeef);
961 ret = CryptSignMessage(&para, FALSE, 0, NULL, NULL, NULL, &signedBlobSize);
962 ok(!ret &&
963 (GetLastError() == E_INVALIDARG ||
964 GetLastError() == ERROR_ARITHMETIC_OVERFLOW), /* Win7 */
965 "expected E_INVALIDARG or ERROR_ARITHMETIC_OVERFLOW, got %08x\n",
966 GetLastError());
967 para.cbSize = sizeof(para);
968 para.dwMsgEncodingType = X509_ASN_ENCODING;
969 SetLastError(0xdeadbeef);
970 signedBlobSize = 255;
971 ret = CryptSignMessage(&para, FALSE, 0, NULL, NULL, NULL, &signedBlobSize);
972 ok(!ret && GetLastError() == E_INVALIDARG,
973 "expected E_INVALIDARG, got %08x\n", GetLastError());
974 ok(!signedBlobSize, "unexpected size %d\n", signedBlobSize);
975 para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
976 SetLastError(0xdeadbeef);
977 signedBlobSize = 0;
978 ret = CryptSignMessage(&para, FALSE, 0, NULL, NULL, NULL, &signedBlobSize);
979 ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
980 todo_wine
981 ok(signedBlobSize, "bad size\n");
983 SetLastError(0xdeadbeef);
984 ret = CryptAcquireContextA(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
985 CRYPT_VERIFYCONTEXT);
986 ok(ret, "CryptAcquireContextA failed: %08x\n", GetLastError());
987 SetLastError(0xdeadbeef);
988 ret = CryptImportKey(hCryptProv, publicPrivateKeyPair,
989 sizeof(publicPrivateKeyPair), 0, 0, &hKey);
990 if (!ret && GetLastError() == NTE_PERM) /* Win9x */
992 skip("Failed to import a key\n");
993 if (hCryptProv)
994 CryptReleaseContext(hCryptProv, 0);
995 return;
997 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
999 para.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
1000 SetLastError(0xdeadbeef);
1001 para.pSigningCert = CertCreateCertificateContext(X509_ASN_ENCODING |
1002 PKCS_7_ASN_ENCODING, certForSigning, sizeof(certForSigning));
1003 ok(para.pSigningCert != NULL, "CertCreateCertificateContext failed: %08x\n",
1004 GetLastError());
1005 para.HashAlgorithm.pszObjId = oid_rsa_md5;
1007 memset(&keyContext, 0, sizeof(keyContext));
1008 keyContext.cbSize = sizeof(keyContext);
1009 keyContext.hCryptProv = hCryptProv;
1010 keyContext.dwKeySpec = AT_SIGNATURE;
1011 SetLastError(0xdeadbeef);
1012 ret = CertSetCertificateContextProperty(para.pSigningCert,
1013 CERT_KEY_CONTEXT_PROP_ID, 0, &keyContext);
1014 ok(ret, "CertSetCertificateContextProperty failed: %08x\n", GetLastError());
1016 SetLastError(0xdeadbeef);
1017 signedBlobSize = 0;
1018 ret = CryptSignMessage(&para, TRUE, 0, NULL, NULL, NULL, &signedBlobSize);
1019 ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1020 signedBlob = CryptMemAlloc(signedBlobSize);
1021 if (signedBlob)
1023 SetLastError(0xdeadbeef);
1024 ret = CryptSignMessage(&para, TRUE, 0, NULL, NULL, signedBlob,
1025 &signedBlobSize);
1026 ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1027 todo_wine
1028 ok(signedBlobSize == sizeof(signedHashForEmptyMessage),
1029 "unexpected size %d\n", signedBlobSize);
1030 todo_wine
1031 ok(!memcmp(signedBlob, signedHashForEmptyMessage, signedBlobSize),
1032 "unexpected value\n");
1033 CryptMemFree(signedBlob);
1036 SetLastError(0xdeadbeef);
1037 signedBlobSize = 0;
1038 ret = CryptSignMessage(&para, FALSE, 0, NULL, NULL, NULL, &signedBlobSize);
1039 ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1040 signedBlob = CryptMemAlloc(signedBlobSize);
1041 if (signedBlob)
1043 SetLastError(0xdeadbeef);
1044 ret = CryptSignMessage(&para, FALSE, 0, NULL, NULL, signedBlob,
1045 &signedBlobSize);
1046 ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1047 todo_wine
1048 ok(signedBlobSize == sizeof(signedEmptyMessage), "unexpected size %d\n",
1049 signedBlobSize);
1050 todo_wine
1051 ok(!memcmp(signedBlob, signedEmptyMessage, signedBlobSize),
1052 "unexpected value\n");
1053 CryptMemFree(signedBlob);
1056 SetLastError(0xdeadbeef);
1057 signedBlobSize = 0;
1058 ret = CryptSignMessage(&para, TRUE, 2, toSign, signSize, NULL,
1059 &signedBlobSize);
1060 ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1061 signedBlob = CryptMemAlloc(signedBlobSize);
1062 if (signedBlob)
1064 SetLastError(0xdeadbeef);
1065 ret = CryptSignMessage(&para, TRUE, 2, toSign, signSize, signedBlob,
1066 &signedBlobSize);
1067 ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1068 todo_wine
1069 ok(signedBlobSize == sizeof(signedHash),
1070 "unexpected size of signed blob %d\n", signedBlobSize);
1071 todo_wine
1072 ok(!memcmp(signedBlob, signedHash, signedBlobSize),
1073 "unexpected value\n");
1074 CryptMemFree(signedBlob);
1077 para.cMsgCert = 1;
1078 para.rgpMsgCert = &para.pSigningCert;
1080 SetLastError(0xdeadbeef);
1081 signedBlobSize = 0;
1082 ret = CryptSignMessage(&para, TRUE, 2, toSign, signSize, NULL,
1083 &signedBlobSize);
1084 ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1085 signedBlob = CryptMemAlloc(signedBlobSize);
1086 if (signedBlob)
1088 SetLastError(0xdeadbeef);
1089 ret = CryptSignMessage(&para, TRUE, 2, toSign, signSize, signedBlob,
1090 &signedBlobSize);
1091 ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1092 todo_wine
1093 ok(signedBlobSize == sizeof(signedHashWithCert),
1094 "unexpected size of signed blob %d\n", signedBlobSize);
1095 todo_wine
1096 ok(!memcmp(signedBlob, signedHashWithCert, signedBlobSize),
1097 "unexpected value\n");
1098 CryptMemFree(signedBlob);
1101 para.cMsgCert = 0;
1102 para.rgpMsgCert = NULL;
1103 para.cMsgCrl = 1;
1104 SetLastError(0xdeadbeef);
1105 crlContext = CertCreateCRLContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
1106 crl, sizeof(crl));
1107 ok(crlContext != NULL, "CertCreateCRLContext failed: %08x\n",
1108 GetLastError());
1109 para.rgpMsgCrl = &crlContext;
1111 SetLastError(0xdeadbeef);
1112 signedBlobSize = 0;
1113 ret = CryptSignMessage(&para, TRUE, 2, toSign, signSize, NULL,
1114 &signedBlobSize);
1115 ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1116 signedBlob = CryptMemAlloc(signedBlobSize);
1117 if (signedBlob)
1119 SetLastError(0xdeadbeef);
1120 ret = CryptSignMessage(&para, TRUE, 2, toSign, signSize, signedBlob,
1121 &signedBlobSize);
1122 ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1123 todo_wine
1124 ok(signedBlobSize == sizeof(signedHashWithCRL),
1125 "unexpected size of signed blob %d\n", signedBlobSize);
1126 todo_wine
1127 ok(!memcmp(signedBlob, signedHashWithCRL, signedBlobSize),
1128 "unexpected value\n");
1129 CryptMemFree(signedBlob);
1132 CertFreeCRLContext(crlContext);
1133 para.cMsgCrl = 0;
1134 para.rgpMsgCrl = NULL;
1136 SetLastError(0xdeadbeef);
1137 signedBlobSize = 0;
1138 ret = CryptSignMessage(&para, FALSE, 1, toSign, signSize, NULL,
1139 &signedBlobSize);
1140 ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1141 signedBlob = CryptMemAlloc(signedBlobSize);
1142 if (signedBlob)
1144 SetLastError(0xdeadbeef);
1145 ret = CryptSignMessage(&para, FALSE, 1, toSign, signSize, signedBlob,
1146 &signedBlobSize);
1147 ok(ret, "CryptSignMessage failed: %08x\n", GetLastError());
1148 todo_wine
1149 ok(signedBlobSize == sizeof(signedData),
1150 "unexpected size of signed blob %d\n", signedBlobSize);
1151 todo_wine
1152 ok(!memcmp(signedBlob, signedData, signedBlobSize),
1153 "unexpected value\n");
1154 CryptMemFree(signedBlob);
1157 if (para.pSigningCert)
1158 CertFreeCertificateContext(para.pSigningCert);
1159 if (hKey)
1160 CryptDestroyKey(hKey);
1161 if (hCryptProv)
1162 CryptReleaseContext(hCryptProv, 0);
1165 START_TEST(message)
1167 test_msg_get_signer_count();
1168 test_verify_detached_message_hash();
1169 test_verify_message_hash();
1170 test_verify_detached_message_signature();
1171 test_verify_message_signature();
1172 test_hash_message();
1173 test_sign_message();