[CRYPT32_WINETEST] Sync with Wine Staging 2.16. CORE-13762
[reactos.git] / rostests / winetests / crypt32 / encode.c
1 /*
2 * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
3 *
4 * Copyright 2005 Juan Lang
5 *
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.
10 *
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.
15 *
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
19 */
20 #include <stdio.h>
21 //#include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 //#include <winerror.h>
25 #include <wincrypt.h>
26
27 #include <wine/test.h>
28
29
30 static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
31 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
32
33 struct encodedInt
34 {
35 int val;
36 const BYTE *encoded;
37 };
38
39 static const BYTE bin1[] = {0x02,0x01,0x01};
40 static const BYTE bin2[] = {0x02,0x01,0x7f};
41 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
42 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
43 static const BYTE bin5[] = {0x02,0x01,0x80};
44 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
45 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
46
47 static const struct encodedInt ints[] = {
48 { 1, bin1 },
49 { 127, bin2 },
50 { 128, bin3 },
51 { 256, bin4 },
52 { -128, bin5 },
53 { -129, bin6 },
54 { 0xbaddf00d, bin7 },
55 };
56
57 struct encodedBigInt
58 {
59 const BYTE *val;
60 const BYTE *encoded;
61 const BYTE *decoded;
62 };
63
64 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
65 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
66 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
67
68 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
69 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
70 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
71
72 static const struct encodedBigInt bigInts[] = {
73 { bin8, bin9, bin10 },
74 { bin11, bin12, bin13 },
75 };
76
77 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
78 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
79 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
80 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
81
82 /* Decoded is the same as original, so don't bother storing a separate copy */
83 static const struct encodedBigInt bigUInts[] = {
84 { bin14, bin15, NULL },
85 { bin16, bin17, NULL },
86 };
87
88 static void test_encodeInt(DWORD dwEncoding)
89 {
90 DWORD bufSize = 0;
91 int i;
92 BOOL ret;
93 CRYPT_INTEGER_BLOB blob;
94 BYTE *buf = NULL;
95
96 /* CryptEncodeObjectEx with NULL bufSize crashes..
97 ret = pCryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
98 NULL);
99 */
100 /* check bogus encoding */
101 ret = pCryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
102 &bufSize);
103 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
104 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
105 if (0)
106 {
107 /* check with NULL integer buffer. Windows XP incorrectly returns an
108 * NTSTATUS (crashes on win9x).
109 */
110 ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
111 &bufSize);
112 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
113 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
114 }
115 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
116 {
117 /* encode as normal integer */
118 ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
119 NULL, NULL, &bufSize);
120 ok(ret, "Expected success, got %d\n", GetLastError());
121 ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
122 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
123 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
124 if (ret)
125 {
126 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
127 buf[0]);
128 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
129 buf[1], ints[i].encoded[1]);
130 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
131 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
132 LocalFree(buf);
133 }
134 /* encode as multibyte integer */
135 blob.cbData = sizeof(ints[i].val);
136 blob.pbData = (BYTE *)&ints[i].val;
137 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
138 0, NULL, NULL, &bufSize);
139 ok(ret, "Expected success, got %d\n", GetLastError());
140 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
141 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
142 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
143 if (ret)
144 {
145 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
146 buf[0]);
147 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
148 buf[1], ints[i].encoded[1]);
149 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
150 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
151 LocalFree(buf);
152 }
153 }
154 /* encode a couple bigger ints, just to show it's little-endian and leading
155 * sign bytes are dropped
156 */
157 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
158 {
159 blob.cbData = strlen((const char*)bigInts[i].val);
160 blob.pbData = (BYTE *)bigInts[i].val;
161 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
162 0, NULL, NULL, &bufSize);
163 ok(ret, "Expected success, got %d\n", GetLastError());
164 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
165 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
166 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
167 if (ret)
168 {
169 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
170 buf[0]);
171 ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
172 buf[1], bigInts[i].encoded[1]);
173 ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
174 bigInts[i].encoded[1] + 1),
175 "Encoded value didn't match expected\n");
176 LocalFree(buf);
177 }
178 }
179 /* and, encode some uints */
180 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
181 {
182 blob.cbData = strlen((const char*)bigUInts[i].val);
183 blob.pbData = (BYTE*)bigUInts[i].val;
184 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
185 0, NULL, NULL, &bufSize);
186 ok(ret, "Expected success, got %d\n", GetLastError());
187 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
188 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
189 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
190 if (ret)
191 {
192 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
193 buf[0]);
194 ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
195 buf[1], bigUInts[i].encoded[1]);
196 ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
197 bigUInts[i].encoded[1] + 1),
198 "Encoded value didn't match expected\n");
199 LocalFree(buf);
200 }
201 }
202 }
203
204 static void test_decodeInt(DWORD dwEncoding)
205 {
206 static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
207 static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
208 static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
209 static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
210 static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
211 BYTE *buf = NULL;
212 DWORD bufSize = 0;
213 int i;
214 BOOL ret;
215
216 /* CryptDecodeObjectEx with NULL bufSize crashes..
217 ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
218 ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
219 */
220 /* check bogus encoding */
221 ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
222 ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
223 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
224 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
225 /* check with NULL integer buffer */
226 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
227 &bufSize);
228 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
229 GetLastError() == OSS_BAD_ARG /* Win9x */),
230 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
231 /* check with a valid, but too large, integer */
232 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
233 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
234 ok((!ret && GetLastError() == CRYPT_E_ASN1_LARGE) ||
235 broken(ret) /* Win9x */,
236 "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
237 /* check with a DER-encoded string */
238 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
239 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
240 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
241 GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
242 "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
243 GetLastError());
244 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
245 {
246 /* When the output buffer is NULL, this always succeeds */
247 SetLastError(0xdeadbeef);
248 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
249 ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
250 &bufSize);
251 ok(ret && GetLastError() == NOERROR,
252 "Expected success and NOERROR, got %d\n", GetLastError());
253 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
254 ints[i].encoded, ints[i].encoded[1] + 2,
255 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
256 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
257 ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
258 ok(buf != NULL, "Expected allocated buffer\n");
259 if (ret)
260 {
261 ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
262 ints[i].val, *(int *)buf);
263 LocalFree(buf);
264 }
265 }
266 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
267 {
268 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
269 bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
270 &bufSize);
271 ok(ret && GetLastError() == NOERROR,
272 "Expected success and NOERROR, got %d\n", GetLastError());
273 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
274 bigInts[i].encoded, bigInts[i].encoded[1] + 2,
275 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
276 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
277 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
278 ok(buf != NULL, "Expected allocated buffer\n");
279 if (ret)
280 {
281 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
282
283 ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
284 "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
285 blob->cbData);
286 ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
287 "Unexpected value\n");
288 LocalFree(buf);
289 }
290 }
291 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
292 {
293 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
294 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
295 &bufSize);
296 ok(ret && GetLastError() == NOERROR,
297 "Expected success and NOERROR, got %d\n", GetLastError());
298 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
299 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
300 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
301 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
302 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
303 ok(buf != NULL, "Expected allocated buffer\n");
304 if (ret)
305 {
306 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
307
308 ok(blob->cbData == strlen((const char*)bigUInts[i].val),
309 "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
310 blob->cbData);
311 ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
312 "Unexpected value\n");
313 LocalFree(buf);
314 }
315 }
316 /* Decode the value 1 with long-form length */
317 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
318 sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
319 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
320 if (ret)
321 {
322 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
323 LocalFree(buf);
324 }
325 /* check with extra bytes at the end */
326 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
327 sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
328 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
329 if (ret)
330 {
331 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
332 LocalFree(buf);
333 }
334 /* Try to decode some bogus large items */
335 /* The buffer size is smaller than the encoded length, so this should fail
336 * with CRYPT_E_ASN1_EOD if it's being decoded.
337 * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
338 * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
339 * So this test unfortunately isn't useful.
340 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
341 0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
342 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
343 "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
344 */
345 /* This will try to decode the buffer and overflow it, check that it's
346 * caught.
347 */
348 if (0)
349 {
350 /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
351 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
352 0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
353 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
354 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
355 }
356 }
357
358 static const BYTE bin18[] = {0x0a,0x01,0x01};
359 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
360
361 /* These are always encoded unsigned, and aren't constrained to be any
362 * particular value
363 */
364 static const struct encodedInt enums[] = {
365 { 1, bin18 },
366 { -128, bin19 },
367 };
368
369 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
370 * X509_ENUMERATED.
371 */
372 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
373 szOID_CRL_REASON_CODE };
374
375 static void test_encodeEnumerated(DWORD dwEncoding)
376 {
377 DWORD i, j;
378
379 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
380 {
381 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
382 {
383 BOOL ret;
384 BYTE *buf = NULL;
385 DWORD bufSize = 0;
386
387 ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
388 &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
389 &bufSize);
390 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
391 if (ret)
392 {
393 ok(buf[0] == 0xa,
394 "Got unexpected type %d for enumerated (expected 0xa)\n",
395 buf[0]);
396 ok(buf[1] == enums[j].encoded[1],
397 "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
398 ok(!memcmp(buf + 1, enums[j].encoded + 1,
399 enums[j].encoded[1] + 1),
400 "Encoded value of 0x%08x didn't match expected\n",
401 enums[j].val);
402 LocalFree(buf);
403 }
404 }
405 }
406 }
407
408 static void test_decodeEnumerated(DWORD dwEncoding)
409 {
410 DWORD i, j;
411
412 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
413 {
414 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
415 {
416 BOOL ret;
417 DWORD bufSize = sizeof(int);
418 int val;
419
420 ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
421 enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
422 &val, &bufSize);
423 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
424 ok(bufSize == sizeof(int),
425 "Got unexpected size %d for enumerated\n", bufSize);
426 ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
427 val, enums[j].val);
428 }
429 }
430 }
431
432 struct encodedFiletime
433 {
434 SYSTEMTIME sysTime;
435 const BYTE *encodedTime;
436 };
437
438 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
439 const struct encodedFiletime *time)
440 {
441 FILETIME ft = { 0 };
442 BYTE *buf = NULL;
443 DWORD bufSize = 0;
444 BOOL ret;
445
446 ret = SystemTimeToFileTime(&time->sysTime, &ft);
447 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
448 ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft,
449 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
450 /* years other than 1950-2050 are not allowed for encodings other than
451 * X509_CHOICE_OF_TIME.
452 */
453 if (structType == X509_CHOICE_OF_TIME ||
454 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
455 {
456 ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
457 GetLastError());
458 ok(buf != NULL, "Expected an allocated buffer\n");
459 if (ret)
460 {
461 ok(buf[0] == time->encodedTime[0],
462 "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
463 buf[0]);
464 ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
465 time->encodedTime[1], bufSize);
466 ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
467 "Got unexpected value for time encoding\n");
468 LocalFree(buf);
469 }
470 }
471 else
472 ok((!ret && GetLastError() == CRYPT_E_BAD_ENCODE) ||
473 broken(GetLastError() == ERROR_SUCCESS),
474 "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
475 }
476
477 static const char *printSystemTime(const SYSTEMTIME *st)
478 {
479 static char buf[64];
480
481 sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
482 st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
483 return buf;
484 }
485
486 static const char *printFileTime(const FILETIME *ft)
487 {
488 static char buf[64];
489 SYSTEMTIME st;
490
491 FileTimeToSystemTime(ft, &st);
492 sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
493 st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
494 return buf;
495 }
496
497 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
498 {
499 SYSTEMTIME st;
500
501 FileTimeToSystemTime(got, &st);
502 ok((expected->wYear == st.wYear &&
503 expected->wMonth == st.wMonth &&
504 expected->wDay == st.wDay &&
505 expected->wHour == st.wHour &&
506 expected->wMinute == st.wMinute &&
507 expected->wSecond == st.wSecond &&
508 abs(expected->wMilliseconds - st.wMilliseconds) <= 1) ||
509 /* Some Windows systems only seem to be accurate in their time decoding to
510 * within about an hour.
511 */
512 broken(expected->wYear == st.wYear &&
513 expected->wMonth == st.wMonth &&
514 expected->wDay == st.wDay &&
515 abs(expected->wHour - st.wHour) <= 1),
516 "Got unexpected value for time decoding:\nexpected %s, got %s\n",
517 printSystemTime(expected), printFileTime(got));
518 }
519
520 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
521 const struct encodedFiletime *time)
522 {
523 FILETIME ft = { 0 };
524 DWORD size = sizeof(ft);
525 BOOL ret;
526
527 ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
528 time->encodedTime[1] + 2, 0, NULL, &ft, &size);
529 /* years other than 1950-2050 are not allowed for encodings other than
530 * X509_CHOICE_OF_TIME.
531 */
532 if (structType == X509_CHOICE_OF_TIME ||
533 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
534 {
535 ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
536 "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
537 GetLastError());
538 if (ret)
539 compareTime(&time->sysTime, &ft);
540 }
541 else
542 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
543 GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
544 "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
545 GetLastError());
546 }
547
548 static const BYTE bin20[] = {
549 0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
550 static const BYTE bin21[] = {
551 0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
552 static const BYTE bin22[] = {
553 0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
554
555 static const struct encodedFiletime times[] = {
556 { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
557 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
558 { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
559 };
560
561 static void test_encodeFiletime(DWORD dwEncoding)
562 {
563 DWORD i;
564
565 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
566 {
567 testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
568 testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
569 testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
570 }
571 }
572
573 static const BYTE bin23[] = {
574 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
575 static const BYTE bin24[] = {
576 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
577 static const BYTE bin25[] = {
578 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
579 static const BYTE bin26[] = {
580 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
581 static const BYTE bin27[] = {
582 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
583 static const BYTE bin28[] = {
584 0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
585 static const BYTE bin29[] = {
586 0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
587 static const BYTE bin30[] = {
588 0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
589 static const BYTE bin31[] = {
590 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
591 static const BYTE bin32[] = {
592 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
593 static const BYTE bin33[] = {
594 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
595 static const BYTE bin34[] = {
596 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
597 static const BYTE bin35[] = {
598 0x17,0x08, '4','5','0','6','0','6','1','6'};
599 static const BYTE bin36[] = {
600 0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
601 static const BYTE bin37[] = {
602 0x18,0x04, '2','1','4','5'};
603 static const BYTE bin38[] = {
604 0x18,0x08, '2','1','4','5','0','6','0','6'};
605
606 static void test_decodeFiletime(DWORD dwEncoding)
607 {
608 static const struct encodedFiletime otherTimes[] = {
609 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin23 },
610 { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
611 { { 1945, 6, 1, 6, 17, 10, 0, 0 }, bin25 },
612 { { 1945, 6, 1, 6, 15, 10, 0, 0 }, bin26 },
613 { { 1945, 6, 1, 6, 14, 55, 0, 0 }, bin27 },
614 { { 2145, 6, 1, 6, 16, 0, 0, 0 }, bin28 },
615 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin29 },
616 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin30 },
617 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin31 },
618 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin32 },
619 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin33 },
620 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin34 },
621 };
622 /* An oddball case that succeeds in Windows, but doesn't seem correct
623 { { 2145, 6, 1, 2, 11, 31, 0, 0 }, "\x18" "\x13" "21450606161000-9999" },
624 */
625 static const unsigned char *bogusTimes[] = {
626 /* oddly, this succeeds on Windows, with year 2765
627 "\x18" "\x0f" "21r50606161000Z",
628 */
629 bin35,
630 bin36,
631 bin37,
632 bin38,
633 };
634 DWORD i, size;
635 FILETIME ft1 = { 0 }, ft2 = { 0 };
636 BOOL ret;
637
638 /* Check bogus length with non-NULL buffer */
639 ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
640 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
641 size = 1;
642 ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
643 times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
644 ok(!ret && GetLastError() == ERROR_MORE_DATA,
645 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
646 /* Normal tests */
647 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
648 {
649 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
650 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
651 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
652 }
653 for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
654 {
655 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
656 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
657 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
658 }
659 for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
660 {
661 size = sizeof(ft1);
662 ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
663 bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
664 ok((!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
665 GetLastError() == OSS_DATA_ERROR /* Win9x */)) ||
666 broken(ret), /* Win9x and NT4 for bin38 */
667 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
668 GetLastError());
669 }
670 }
671
672 static const char commonName[] = "Juan Lang";
673 static const char surName[] = "Lang";
674
675 static const BYTE emptySequence[] = { 0x30, 0 };
676 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
677 static const BYTE twoRDNs[] = {
678 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
679 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
680 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
681 static const BYTE encodedTwoRDNs[] = {
682 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
683 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
684 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
685 0x6e,0x67,0x00,
686 };
687
688 static const BYTE us[] = { 0x55, 0x53 };
689 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
690 0x74, 0x61 };
691 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
692 0x6f, 0x6c, 0x69, 0x73 };
693 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
694 0x76, 0x65, 0x72, 0x73 };
695 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
696 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
697 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
698 0x73, 0x74 };
699 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
700 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
701
702 #define RDNA(arr) oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
703 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING, { sizeof(arr), (LPBYTE)arr }
704
705 static CHAR oid_us[] = "2.5.4.6",
706 oid_minnesota[] = "2.5.4.8",
707 oid_minneapolis[] = "2.5.4.7",
708 oid_codeweavers[] = "2.5.4.10",
709 oid_wine[] = "2.5.4.11",
710 oid_localhostAttr[] = "2.5.4.3",
711 oid_aric[] = "1.2.840.113549.1.9.1";
712 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
713 { RDNA(minnesota) },
714 { RDNA(minneapolis) },
715 { RDNA(codeweavers) },
716 { RDNA(wine) },
717 { RDNA(localhostAttr) },
718 { RDNIA5(aric) } };
719 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
720 { RDNA(localhostAttr) },
721 { RDNA(minnesota) },
722 { RDNA(minneapolis) },
723 { RDNA(codeweavers) },
724 { RDNA(wine) },
725 { RDNIA5(aric) } };
726
727 #undef RDNIA5
728 #undef RDNA
729
730 static const BYTE encodedRDNAttrs[] = {
731 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
732 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
733 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
734 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
735 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
736 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
737 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
738 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
739 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
740 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
741 };
742
743 static void test_encodeName(DWORD dwEncoding)
744 {
745 CERT_RDN_ATTR attrs[2];
746 CERT_RDN rdn;
747 CERT_NAME_INFO info;
748 static CHAR oid_common_name[] = szOID_COMMON_NAME,
749 oid_sur_name[] = szOID_SUR_NAME;
750 BYTE *buf = NULL;
751 DWORD size = 0;
752 BOOL ret;
753
754 if (0)
755 {
756 /* Test with NULL pvStructInfo (crashes on win9x) */
757 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
758 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
759 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
760 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
761 }
762 /* Test with empty CERT_NAME_INFO */
763 info.cRDN = 0;
764 info.rgRDN = NULL;
765 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
766 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
767 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
768 if (ret)
769 {
770 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
771 "Got unexpected encoding for empty name\n");
772 LocalFree(buf);
773 }
774 if (0)
775 {
776 /* Test with bogus CERT_RDN (crashes on win9x) */
777 info.cRDN = 1;
778 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
779 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
780 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
781 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
782 }
783 /* Test with empty CERT_RDN */
784 rdn.cRDNAttr = 0;
785 rdn.rgRDNAttr = NULL;
786 info.cRDN = 1;
787 info.rgRDN = &rdn;
788 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
789 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
790 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
791 if (ret)
792 {
793 ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
794 "Got unexpected encoding for empty RDN array\n");
795 LocalFree(buf);
796 }
797 if (0)
798 {
799 /* Test with bogus attr array (crashes on win9x) */
800 rdn.cRDNAttr = 1;
801 rdn.rgRDNAttr = NULL;
802 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
803 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
804 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
805 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
806 }
807 /* oddly, a bogus OID is accepted by Windows XP; not testing.
808 attrs[0].pszObjId = "bogus";
809 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
810 attrs[0].Value.cbData = sizeof(commonName);
811 attrs[0].Value.pbData = commonName;
812 rdn.cRDNAttr = 1;
813 rdn.rgRDNAttr = attrs;
814 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
815 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
816 ok(!ret, "Expected failure, got success\n");
817 */
818 /* Check with two CERT_RDN_ATTRs. Note DER encoding forces the order of
819 * the encoded attributes to be swapped.
820 */
821 attrs[0].pszObjId = oid_common_name;
822 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
823 attrs[0].Value.cbData = sizeof(commonName);
824 attrs[0].Value.pbData = (BYTE *)commonName;
825 attrs[1].pszObjId = oid_sur_name;
826 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
827 attrs[1].Value.cbData = sizeof(surName);
828 attrs[1].Value.pbData = (BYTE *)surName;
829 rdn.cRDNAttr = 2;
830 rdn.rgRDNAttr = attrs;
831 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
832 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
833 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
834 if (ret)
835 {
836 ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
837 "Got unexpected encoding for two RDN array\n");
838 LocalFree(buf);
839 }
840 /* A name can be "encoded" with previously encoded RDN attrs. */
841 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
842 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
843 attrs[0].Value.cbData = sizeof(twoRDNs);
844 rdn.cRDNAttr = 1;
845 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
846 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
847 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
848 if (ret)
849 {
850 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
851 ok(!memcmp(buf, encodedTwoRDNs, size),
852 "Unexpected value for re-encoded two RDN array\n");
853 LocalFree(buf);
854 }
855 /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
856 rdn.cRDNAttr = 1;
857 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
858 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
859 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
860 ok(!ret && GetLastError() == E_INVALIDARG,
861 "Expected E_INVALIDARG, got %08x\n", GetLastError());
862 /* Test a more complex name */
863 rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
864 rdn.rgRDNAttr = rdnAttrs;
865 info.cRDN = 1;
866 info.rgRDN = &rdn;
867 buf = NULL;
868 size = 0;
869 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
870 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
871 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
872 if (ret)
873 {
874 ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
875 ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
876 LocalFree(buf);
877 }
878 }
879
880 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
881 static WCHAR surNameW[] = { 'L','a','n','g',0 };
882
883 static const BYTE twoRDNsNoNull[] = {
884 0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
885 0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
886 0x20,0x4c,0x61,0x6e,0x67 };
887 static const BYTE anyType[] = {
888 0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
889 0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
890 0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
891 0x61,0x4c,0x67,0x6e };
892
893 static void test_encodeUnicodeName(DWORD dwEncoding)
894 {
895 CERT_RDN_ATTR attrs[2];
896 CERT_RDN rdn;
897 CERT_NAME_INFO info;
898 static CHAR oid_common_name[] = szOID_COMMON_NAME,
899 oid_sur_name[] = szOID_SUR_NAME;
900 BYTE *buf = NULL;
901 DWORD size = 0;
902 BOOL ret;
903
904 if (0)
905 {
906 /* Test with NULL pvStructInfo (crashes on win9x) */
907 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
908 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
909 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
910 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
911 }
912 /* Test with empty CERT_NAME_INFO */
913 info.cRDN = 0;
914 info.rgRDN = NULL;
915 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
916 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
917 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
918 if (ret)
919 {
920 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
921 "Got unexpected encoding for empty name\n");
922 LocalFree(buf);
923 }
924 /* Check with one CERT_RDN_ATTR, that has an invalid character for the
925 * encoding (the NULL).
926 */
927 attrs[0].pszObjId = oid_common_name;
928 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
929 attrs[0].Value.cbData = sizeof(commonNameW);
930 attrs[0].Value.pbData = (BYTE *)commonNameW;
931 rdn.cRDNAttr = 1;
932 rdn.rgRDNAttr = attrs;
933 info.cRDN = 1;
934 info.rgRDN = &rdn;
935 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
936 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
937 ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
938 "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
939 ok(size == 9, "Unexpected error index %08x\n", size);
940 /* Check with two NULL-terminated CERT_RDN_ATTRs. Note DER encoding
941 * forces the order of the encoded attributes to be swapped.
942 */
943 attrs[0].pszObjId = oid_common_name;
944 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
945 attrs[0].Value.cbData = 0;
946 attrs[0].Value.pbData = (BYTE *)commonNameW;
947 attrs[1].pszObjId = oid_sur_name;
948 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
949 attrs[1].Value.cbData = 0;
950 attrs[1].Value.pbData = (BYTE *)surNameW;
951 rdn.cRDNAttr = 2;
952 rdn.rgRDNAttr = attrs;
953 info.cRDN = 1;
954 info.rgRDN = &rdn;
955 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
956 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
957 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
958 if (ret)
959 {
960 ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
961 "Got unexpected encoding for two RDN array\n");
962 LocalFree(buf);
963 }
964 /* A name can be "encoded" with previously encoded RDN attrs. */
965 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
966 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
967 attrs[0].Value.cbData = sizeof(twoRDNs);
968 rdn.cRDNAttr = 1;
969 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
970 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
971 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
972 if (ret)
973 {
974 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
975 ok(!memcmp(buf, encodedTwoRDNs, size),
976 "Unexpected value for re-encoded two RDN array\n");
977 LocalFree(buf);
978 }
979 /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
980 rdn.cRDNAttr = 1;
981 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
982 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
983 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
984 todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
985 if (ret)
986 {
987 ok(size == sizeof(anyType), "Unexpected size %d\n", size);
988 ok(!memcmp(buf, anyType, size), "Unexpected value\n");
989 LocalFree(buf);
990 }
991 }
992
993 static void compareNameValues(const CERT_NAME_VALUE *expected,
994 const CERT_NAME_VALUE *got)
995 {
996 if (expected->dwValueType == CERT_RDN_UTF8_STRING &&
997 got->dwValueType == CERT_RDN_ENCODED_BLOB)
998 {
999 win_skip("Can't handle CERT_RDN_UTF8_STRING\n");
1000 return;
1001 }
1002
1003 ok(got->dwValueType == expected->dwValueType,
1004 "Expected string type %d, got %d\n", expected->dwValueType,
1005 got->dwValueType);
1006 ok(got->Value.cbData == expected->Value.cbData ||
1007 got->Value.cbData == expected->Value.cbData - sizeof(WCHAR) /* Win8 */,
1008 "String type %d: unexpected data size, got %d, expected %d\n",
1009 expected->dwValueType, got->Value.cbData, expected->Value.cbData);
1010 if (got->Value.cbData && got->Value.pbData)
1011 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1012 min(got->Value.cbData, expected->Value.cbData)),
1013 "String type %d: unexpected value\n", expected->dwValueType);
1014 }
1015
1016 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
1017 const CERT_RDN_ATTR *got)
1018 {
1019 if (expected->pszObjId && strlen(expected->pszObjId))
1020 {
1021 ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
1022 expected->pszObjId);
1023 if (got->pszObjId)
1024 {
1025 ok(!strcmp(got->pszObjId, expected->pszObjId),
1026 "Got unexpected OID %s, expected %s\n", got->pszObjId,
1027 expected->pszObjId);
1028 }
1029 }
1030 compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1031 (const CERT_NAME_VALUE *)&got->dwValueType);
1032 }
1033
1034 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1035 {
1036 ok(got->cRDNAttr == expected->cRDNAttr,
1037 "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1038 if (got->cRDNAttr)
1039 {
1040 DWORD i;
1041
1042 for (i = 0; i < got->cRDNAttr; i++)
1043 compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1044 }
1045 }
1046
1047 static void compareNames(const CERT_NAME_INFO *expected,
1048 const CERT_NAME_INFO *got)
1049 {
1050 ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1051 expected->cRDN, got->cRDN);
1052 if (got->cRDN)
1053 {
1054 DWORD i;
1055
1056 for (i = 0; i < got->cRDN; i++)
1057 compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1058 }
1059 }
1060
1061 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1062 static const BYTE twoRDNsExtraBytes[] = {
1063 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1064 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1065 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1066
1067 static void test_decodeName(DWORD dwEncoding)
1068 {
1069 BYTE *buf = NULL;
1070 DWORD bufSize = 0;
1071 BOOL ret;
1072 CERT_RDN rdn;
1073 CERT_NAME_INFO info = { 1, &rdn };
1074
1075 /* test empty name */
1076 bufSize = 0;
1077 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1078 emptySequence[1] + 2,
1079 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1080 &buf, &bufSize);
1081 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1082 /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL. My
1083 * decoder works the same way, so only test the count.
1084 */
1085 if (ret)
1086 {
1087 ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1088 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1089 "Expected 0 RDNs in empty info, got %d\n",
1090 ((CERT_NAME_INFO *)buf)->cRDN);
1091 LocalFree(buf);
1092 }
1093 /* test empty name with indefinite-length encoding */
1094 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1095 sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1096 &buf, &bufSize);
1097 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1098 if (ret)
1099 {
1100 ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1101 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1102 "Expected 0 RDNs in empty info, got %d\n",
1103 ((CERT_NAME_INFO *)buf)->cRDN);
1104 LocalFree(buf);
1105 }
1106 /* test empty RDN */
1107 bufSize = 0;
1108 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1109 emptyRDNs[1] + 2,
1110 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1111 &buf, &bufSize);
1112 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1113 if (ret)
1114 {
1115 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1116
1117 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1118 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1119 "Got unexpected value for empty RDN\n");
1120 LocalFree(buf);
1121 }
1122 /* test two RDN attrs */
1123 bufSize = 0;
1124 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1125 twoRDNs[1] + 2,
1126 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1127 &buf, &bufSize);
1128 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1129 if (ret)
1130 {
1131 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1132 oid_common_name[] = szOID_COMMON_NAME;
1133
1134 CERT_RDN_ATTR attrs[] = {
1135 { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1136 (BYTE *)surName } },
1137 { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1138 (BYTE *)commonName } },
1139 };
1140
1141 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1142 rdn.rgRDNAttr = attrs;
1143 compareNames(&info, (CERT_NAME_INFO *)buf);
1144 LocalFree(buf);
1145 }
1146 /* test that two RDN attrs with extra bytes succeeds */
1147 bufSize = 0;
1148 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1149 sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1150 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1151 /* And, a slightly more complicated name */
1152 buf = NULL;
1153 bufSize = 0;
1154 ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1155 sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1156 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1157 if (ret)
1158 {
1159 rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1160 rdn.rgRDNAttr = decodedRdnAttrs;
1161 compareNames(&info, (CERT_NAME_INFO *)buf);
1162 LocalFree(buf);
1163 }
1164 }
1165
1166 static void test_decodeUnicodeName(DWORD dwEncoding)
1167 {
1168 BYTE *buf = NULL;
1169 DWORD bufSize = 0;
1170 BOOL ret;
1171 CERT_RDN rdn;
1172 CERT_NAME_INFO info = { 1, &rdn };
1173
1174 /* test empty name */
1175 bufSize = 0;
1176 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1177 emptySequence[1] + 2,
1178 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1179 &buf, &bufSize);
1180 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1181 if (ret)
1182 {
1183 ok(bufSize == sizeof(CERT_NAME_INFO),
1184 "Got wrong bufSize %d\n", bufSize);
1185 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1186 "Expected 0 RDNs in empty info, got %d\n",
1187 ((CERT_NAME_INFO *)buf)->cRDN);
1188 LocalFree(buf);
1189 }
1190 /* test empty RDN */
1191 bufSize = 0;
1192 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1193 emptyRDNs[1] + 2,
1194 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1195 &buf, &bufSize);
1196 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1197 if (ret)
1198 {
1199 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1200
1201 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1202 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1203 "Got unexpected value for empty RDN\n");
1204 LocalFree(buf);
1205 }
1206 /* test two RDN attrs */
1207 bufSize = 0;
1208 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1209 sizeof(twoRDNsNoNull),
1210 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1211 &buf, &bufSize);
1212 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1213 if (ret)
1214 {
1215 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1216 oid_common_name[] = szOID_COMMON_NAME;
1217
1218 CERT_RDN_ATTR attrs[] = {
1219 { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1220 { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1221 { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1222 { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1223 };
1224
1225 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1226 rdn.rgRDNAttr = attrs;
1227 compareNames(&info, (CERT_NAME_INFO *)buf);
1228 LocalFree(buf);
1229 }
1230 }
1231
1232 struct EncodedNameValue
1233 {
1234 CERT_NAME_VALUE value;
1235 const BYTE *encoded;
1236 DWORD encodedSize;
1237 };
1238
1239 static const char bogusIA5[] = "\x80";
1240 static const char bogusPrintable[] = "~";
1241 static const char bogusNumeric[] = "A";
1242 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1243 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1244 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1245 static BYTE octetCommonNameValue[] = {
1246 0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1247 static BYTE numericCommonNameValue[] = {
1248 0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1249 static BYTE printableCommonNameValue[] = {
1250 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1251 static BYTE t61CommonNameValue[] = {
1252 0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1253 static BYTE videotexCommonNameValue[] = {
1254 0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1255 static BYTE ia5CommonNameValue[] = {
1256 0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1257 static BYTE graphicCommonNameValue[] = {
1258 0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1259 static BYTE visibleCommonNameValue[] = {
1260 0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1261 static BYTE generalCommonNameValue[] = {
1262 0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1263 static BYTE bmpCommonNameValue[] = {
1264 0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1265 0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1266 static BYTE utf8CommonNameValue[] = {
1267 0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1268 static char embedded_null[] = "foo\0com";
1269 static BYTE ia5EmbeddedNull[] = {
1270 0x16,0x07,0x66,0x6f,0x6f,0x00,0x63,0x6f,0x6d };
1271
1272 static struct EncodedNameValue nameValues[] = {
1273 { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1274 octetCommonNameValue, sizeof(octetCommonNameValue) },
1275 { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1276 numericCommonNameValue, sizeof(numericCommonNameValue) },
1277 { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1278 printableCommonNameValue, sizeof(printableCommonNameValue) },
1279 { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1280 t61CommonNameValue, sizeof(t61CommonNameValue) },
1281 { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1282 videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1283 { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1284 ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1285 { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1286 graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1287 { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1288 visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1289 { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1290 generalCommonNameValue, sizeof(generalCommonNameValue) },
1291 { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1292 bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1293 { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1294 utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1295 /* The following tests succeed under Windows, but really should fail,
1296 * they contain characters that are illegal for the encoding. I'm
1297 * including them to justify my lazy encoding.
1298 */
1299 { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1300 sizeof(bin42) },
1301 { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1302 (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1303 { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1304 bin44, sizeof(bin44) },
1305 };
1306 /* This is kept separate, because the decoding doesn't return to the original
1307 * value.
1308 */
1309 static struct EncodedNameValue embeddedNullNameValue = {
1310 { CERT_RDN_IA5_STRING, { sizeof(embedded_null) - 1, (BYTE *)embedded_null } },
1311 ia5EmbeddedNull, sizeof(ia5EmbeddedNull) };
1312
1313 static void test_encodeNameValue(DWORD dwEncoding)
1314 {
1315 BYTE *buf = NULL;
1316 DWORD size = 0, i;
1317 BOOL ret;
1318 CERT_NAME_VALUE value = { 0, { 0, NULL } };
1319
1320 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1321 value.Value.pbData = printableCommonNameValue;
1322 value.Value.cbData = sizeof(printableCommonNameValue);
1323 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1324 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1325 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1326 if (ret)
1327 {
1328 ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1329 size);
1330 ok(!memcmp(buf, printableCommonNameValue, size),
1331 "Unexpected encoding\n");
1332 LocalFree(buf);
1333 }
1334 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1335 {
1336 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1337 &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1338 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1339 "Type %d: CryptEncodeObjectEx failed: %08x\n",
1340 nameValues[i].value.dwValueType, GetLastError());
1341 if (ret)
1342 {
1343 ok(size == nameValues[i].encodedSize,
1344 "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1345 ok(!memcmp(buf, nameValues[i].encoded, size),
1346 "Got unexpected encoding\n");
1347 LocalFree(buf);
1348 }
1349 }
1350 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1351 &embeddedNullNameValue.value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1352 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1353 "Type %d: CryptEncodeObjectEx failed: %08x\n",
1354 embeddedNullNameValue.value.dwValueType, GetLastError());
1355 if (ret)
1356 {
1357 ok(size == embeddedNullNameValue.encodedSize,
1358 "Expected size %d, got %d\n", embeddedNullNameValue.encodedSize, size);
1359 ok(!memcmp(buf, embeddedNullNameValue.encoded, size),
1360 "Got unexpected encoding\n");
1361 LocalFree(buf);
1362 }
1363 }
1364
1365 static void test_decodeNameValue(DWORD dwEncoding)
1366 {
1367 int i;
1368 BYTE *buf = NULL;
1369 DWORD bufSize = 0;
1370 BOOL ret;
1371
1372 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1373 {
1374 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1375 nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1376 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1377 &buf, &bufSize);
1378 ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1379 nameValues[i].value.dwValueType, GetLastError());
1380 if (ret)
1381 {
1382 compareNameValues(&nameValues[i].value,
1383 (const CERT_NAME_VALUE *)buf);
1384 LocalFree(buf);
1385 }
1386 }
1387 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1388 embeddedNullNameValue.encoded, embeddedNullNameValue.encodedSize,
1389 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1390 &buf, &bufSize);
1391 /* Some Windows versions disallow name values with embedded NULLs, so
1392 * either success or failure is acceptable.
1393 */
1394 if (ret)
1395 {
1396 CERT_NAME_VALUE rdnEncodedValue = { CERT_RDN_ENCODED_BLOB,
1397 { sizeof(ia5EmbeddedNull), ia5EmbeddedNull } };
1398 CERT_NAME_VALUE embeddedNullValue = { CERT_RDN_IA5_STRING,
1399 { sizeof(embedded_null) - 1, (BYTE *)embedded_null } };
1400 const CERT_NAME_VALUE *got = (const CERT_NAME_VALUE *)buf,
1401 *expected = NULL;
1402
1403 /* Some Windows versions decode name values with embedded NULLs,
1404 * others leave them encoded, even with the same version of crypt32.
1405 * Accept either.
1406 */
1407 ok(got->dwValueType == CERT_RDN_ENCODED_BLOB ||
1408 got->dwValueType == CERT_RDN_IA5_STRING,
1409 "Expected CERT_RDN_ENCODED_BLOB or CERT_RDN_IA5_STRING, got %d\n",
1410 got->dwValueType);
1411 if (got->dwValueType == CERT_RDN_ENCODED_BLOB)
1412 expected = &rdnEncodedValue;
1413 else if (got->dwValueType == CERT_RDN_IA5_STRING)
1414 expected = &embeddedNullValue;
1415 if (expected)
1416 {
1417 ok(got->Value.cbData == expected->Value.cbData,
1418 "String type %d: unexpected data size, got %d, expected %d\n",
1419 got->dwValueType, got->Value.cbData, expected->Value.cbData);
1420 if (got->Value.cbData && got->Value.pbData)
1421 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1422 min(got->Value.cbData, expected->Value.cbData)),
1423 "String type %d: unexpected value\n", expected->dwValueType);
1424 }
1425 LocalFree(buf);
1426 }
1427 }
1428
1429 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1430 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1431 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1432 'h','q','.','o','r','g',0 };
1433 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1434 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1435 0x6f, 0x72, 0x67 };
1436 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1437 0x575b, 0 };
1438 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1439 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1440 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1441 static const BYTE localhost[] = { 127, 0, 0, 1 };
1442 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1443 0x01 };
1444 static const unsigned char encodedCommonName[] = {
1445 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1446 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1447 static const BYTE encodedDirectoryName[] = {
1448 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1449 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1450
1451 static void test_encodeAltName(DWORD dwEncoding)
1452 {
1453 CERT_ALT_NAME_INFO info = { 0 };
1454 CERT_ALT_NAME_ENTRY entry = { 0 };
1455 BYTE *buf = NULL;
1456 DWORD size = 0;
1457 BOOL ret;
1458 char oid[] = "1.2.3";
1459
1460 /* Test with empty info */
1461 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1462 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1463 if (ret)
1464 {
1465 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1466 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1467 LocalFree(buf);
1468 }
1469 /* Test with an empty entry */
1470 info.cAltEntry = 1;
1471 info.rgAltEntry = &entry;
1472 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1473 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1474 ok(!ret && GetLastError() == E_INVALIDARG,
1475 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1476 /* Test with an empty pointer */
1477 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1478 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1479 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1480 if (ret)
1481 {
1482 ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1483 ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1484 LocalFree(buf);
1485 }
1486 /* Test with a real URL */
1487 U(entry).pwszURL = (LPWSTR)url;
1488 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1489 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1490 if (ret)
1491 {
1492 ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1493 ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1494 LocalFree(buf);
1495 }
1496 /* Now with the URL containing an invalid IA5 char */
1497 U(entry).pwszURL = (LPWSTR)nihongoURL;
1498 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1499 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1500 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1501 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1502 /* The first invalid character is at index 7 */
1503 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1504 "Expected invalid char at index 7, got %d\n",
1505 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1506 /* Now with the URL missing a scheme */
1507 U(entry).pwszURL = (LPWSTR)dnsName;
1508 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1509 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1510 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1511 if (ret)
1512 {
1513 /* This succeeds, but it shouldn't, so don't worry about conforming */
1514 LocalFree(buf);
1515 }
1516 /* Now with a DNS name */
1517 entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1518 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1519 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1520 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1521 if (ret)
1522 {
1523 ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1524 ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1525 LocalFree(buf);
1526 }
1527 /* Test with an IP address */
1528 entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1529 U(entry).IPAddress.cbData = sizeof(localhost);
1530 U(entry).IPAddress.pbData = (LPBYTE)localhost;
1531 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1532 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1533 if (ret)
1534 {
1535 ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1536 ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1537 LocalFree(buf);
1538 }
1539 /* Test with OID */
1540 entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1541 U(entry).pszRegisteredID = oid;
1542 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1543 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1544 if (ret)
1545 {
1546 ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1547 ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1548 LocalFree(buf);
1549 }
1550 /* Test with directory name */
1551 entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1552 U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1553 U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1554 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1555 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1556 if (ret)
1557 {
1558 ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1559 ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1560 LocalFree(buf);
1561 }
1562 }
1563
1564 static void test_decodeAltName(DWORD dwEncoding)
1565 {
1566 static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1567 0x00, 0x00, 0x01 };
1568 static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1569 0x01 };
1570 static const BYTE dns_embedded_null[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1571 0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1572 static const BYTE dns_embedded_bell[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1573 0x6f,0x2e,0x63,0x6f,0x6d,0x07,0x62,0x61,0x64,0x64,0x69,0x65 };
1574 static const BYTE url_embedded_null[] = { 0x30,0x10,0x86,0x0e,0x66,0x6f,
1575 0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1576 BOOL ret;
1577 BYTE *buf = NULL;
1578 DWORD bufSize = 0;
1579 CERT_ALT_NAME_INFO *info;
1580
1581 /* Test some bogus ones first */
1582 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1583 unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1584 NULL, &buf, &bufSize);
1585 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1586 GetLastError() == OSS_DATA_ERROR /* Win9x */),
1587 "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1588 GetLastError());
1589 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1590 bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
1591 &bufSize);
1592 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1593 GetLastError() == OSS_DATA_ERROR /* Win9x */),
1594 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1595 GetLastError());
1596 /* Now expected cases */
1597 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1598 emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1599 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1600 if (ret)
1601 {
1602 info = (CERT_ALT_NAME_INFO *)buf;
1603
1604 ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1605 info->cAltEntry);
1606 LocalFree(buf);
1607 }
1608 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1609 emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1610 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1611 if (ret)
1612 {
1613 info = (CERT_ALT_NAME_INFO *)buf;
1614
1615 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1616 info->cAltEntry);
1617 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1618 "Expected CERT_ALT_NAME_URL, got %d\n",
1619 info->rgAltEntry[0].dwAltNameChoice);
1620 ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1621 "Expected empty URL\n");
1622 LocalFree(buf);
1623 }
1624 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1625 emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1626 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1627 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1628 encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1629 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1630 if (ret)
1631 {
1632 info = (CERT_ALT_NAME_INFO *)buf;
1633
1634 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1635 info->cAltEntry);
1636 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1637 "Expected CERT_ALT_NAME_URL, got %d\n",
1638 info->rgAltEntry[0].dwAltNameChoice);
1639 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1640 LocalFree(buf);
1641 }
1642 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1643 encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1644 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1645 if (ret)
1646 {
1647 info = (CERT_ALT_NAME_INFO *)buf;
1648
1649 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1650 info->cAltEntry);
1651 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1652 "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1653 info->rgAltEntry[0].dwAltNameChoice);
1654 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1655 "Unexpected DNS name\n");
1656 LocalFree(buf);
1657 }
1658 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1659 encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1660 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1661 if (ret)
1662 {
1663 info = (CERT_ALT_NAME_INFO *)buf;
1664
1665 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1666 info->cAltEntry);
1667 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1668 "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1669 info->rgAltEntry[0].dwAltNameChoice);
1670 ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1671 "Unexpected IP address length %d\n",
1672 U(info->rgAltEntry[0]).IPAddress.cbData);
1673 ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1674 sizeof(localhost)), "Unexpected IP address value\n");
1675 LocalFree(buf);
1676 }
1677 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1678 sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1679 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1680 if (ret)
1681 {
1682 info = (CERT_ALT_NAME_INFO *)buf;
1683
1684 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1685 info->cAltEntry);
1686 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1687 "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1688 info->rgAltEntry[0].dwAltNameChoice);
1689 ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1690 "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1691 LocalFree(buf);
1692 }
1693 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1694 encodedDirectoryName, sizeof(encodedDirectoryName),
1695 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1696 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1697 if (ret)
1698 {
1699 info = (CERT_ALT_NAME_INFO *)buf;
1700
1701 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1702 info->cAltEntry);
1703 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1704 "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1705 info->rgAltEntry[0].dwAltNameChoice);
1706 ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1707 sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1708 U(info->rgAltEntry[0]).DirectoryName.cbData);
1709 ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1710 encodedCommonName, sizeof(encodedCommonName)),
1711 "Unexpected directory name value\n");
1712 LocalFree(buf);
1713 }
1714 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1715 dns_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1716 NULL, &buf, &bufSize);
1717 /* Fails on WinXP with CRYPT_E_ASN1_RULE. I'm not too concerned about the
1718 * particular failure, just that it doesn't decode.
1719 * It succeeds on (broken) Windows versions that haven't addressed
1720 * embedded NULLs in alternate names.
1721 */
1722 ok(!ret || broken(ret), "expected failure\n");
1723 /* An embedded bell character is allowed, however. */
1724 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1725 dns_embedded_bell, sizeof(dns_embedded_bell), CRYPT_DECODE_ALLOC_FLAG,
1726 NULL, &buf, &bufSize);
1727 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1728 if (ret)
1729 {
1730 info = (CERT_ALT_NAME_INFO *)buf;
1731
1732 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1733 info->cAltEntry);
1734 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1735 "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1736 info->rgAltEntry[0].dwAltNameChoice);
1737 LocalFree(buf);
1738 }
1739 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1740 url_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1741 NULL, &buf, &bufSize);
1742 /* Again, fails on WinXP with CRYPT_E_ASN1_RULE. I'm not too concerned
1743 * about the particular failure, just that it doesn't decode.
1744 * It succeeds on (broken) Windows versions that haven't addressed
1745 * embedded NULLs in alternate names.
1746 */
1747 ok(!ret || broken(ret), "expected failure\n");
1748 }
1749
1750 struct UnicodeExpectedError
1751 {
1752 DWORD valueType;
1753 LPCWSTR str;
1754 DWORD errorIndex;
1755 DWORD error;
1756 };
1757
1758 static const WCHAR oneW[] = { '1',0 };
1759 static const WCHAR aW[] = { 'a',0 };
1760 static const WCHAR quoteW[] = { '"', 0 };
1761
1762 static struct UnicodeExpectedError unicodeErrors[] = {
1763 { CERT_RDN_ANY_TYPE, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1764 { CERT_RDN_ENCODED_BLOB, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1765 { CERT_RDN_OCTET_STRING, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1766 { CERT_RDN_NUMERIC_STRING, aW, 0, CRYPT_E_INVALID_NUMERIC_STRING },
1767 { CERT_RDN_PRINTABLE_STRING, quoteW, 0, CRYPT_E_INVALID_PRINTABLE_STRING },
1768 { CERT_RDN_IA5_STRING, nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1769 };
1770
1771 struct UnicodeExpectedResult
1772 {
1773 DWORD valueType;
1774 LPCWSTR str;
1775 CRYPT_DATA_BLOB encoded;
1776 };
1777
1778 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1779 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1780 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1781 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1782 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1783 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1784 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1785 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1786 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1787 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1788 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1789 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1790 0x5b };
1791 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1792 0x6f,0x5b };
1793 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1794 0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1795 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1796 0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1797
1798 static struct UnicodeExpectedResult unicodeResults[] = {
1799 { CERT_RDN_NUMERIC_STRING, oneW, { sizeof(oneNumeric), oneNumeric } },
1800 { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1801 { CERT_RDN_TELETEX_STRING, oneW, { sizeof(oneTeletex), oneTeletex } },
1802 { CERT_RDN_VIDEOTEX_STRING, oneW, { sizeof(oneVideotex), oneVideotex } },
1803 { CERT_RDN_IA5_STRING, oneW, { sizeof(oneIA5), oneIA5 } },
1804 { CERT_RDN_GRAPHIC_STRING, oneW, { sizeof(oneGraphic), oneGraphic } },
1805 { CERT_RDN_VISIBLE_STRING, oneW, { sizeof(oneVisible), oneVisible } },
1806 { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1807 { CERT_RDN_GENERAL_STRING, oneW, { sizeof(oneGeneral), oneGeneral } },
1808 { CERT_RDN_BMP_STRING, oneW, { sizeof(oneBMP), oneBMP } },
1809 { CERT_RDN_UTF8_STRING, oneW, { sizeof(oneUTF8), oneUTF8 } },
1810 { CERT_RDN_BMP_STRING, nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1811 { CERT_RDN_UTF8_STRING, nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1812 };
1813
1814 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1815 { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1816 { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1817 };
1818
1819 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1820 {
1821 BYTE *buf = NULL;
1822 DWORD size = 0, i;
1823 BOOL ret;
1824 CERT_NAME_VALUE value;
1825
1826 if (0)
1827 {
1828 /* Crashes on win9x */
1829 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1830 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1831 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1832 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1833 }
1834 /* Have to have a string of some sort */
1835 value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1836 value.Value.pbData = NULL;
1837 value.Value.cbData = 0;
1838 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1839 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1840 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1841 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1842 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1843 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1844 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1845 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1846 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1847 value.dwValueType = CERT_RDN_ANY_TYPE;
1848 value.Value.pbData = (LPBYTE)oneW;
1849 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1850 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1851 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1852 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1853 value.Value.cbData = sizeof(oneW);
1854 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1855 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1856 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1857 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1858 /* An encoded string with specified length isn't good enough either */
1859 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1860 value.Value.pbData = oneUniversal;
1861 value.Value.cbData = sizeof(oneUniversal);
1862 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1863 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1864 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1865 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1866 /* More failure checking */
1867 value.Value.cbData = 0;
1868 for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1869 {
1870 value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1871 value.dwValueType = unicodeErrors[i].valueType;
1872 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1873 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1874 ok(!ret && GetLastError() == unicodeErrors[i].error,
1875 "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1876 unicodeErrors[i].error, GetLastError());
1877 ok(size == unicodeErrors[i].errorIndex,
1878 "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1879 size);
1880 }
1881 /* cbData can be zero if the string is NULL-terminated */
1882 value.Value.cbData = 0;
1883 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1884 {
1885 value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1886 value.dwValueType = unicodeResults[i].valueType;
1887 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1888 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1889 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1890 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1891 if (ret)
1892 {
1893 ok(size == unicodeResults[i].encoded.cbData,
1894 "Value type %d: expected size %d, got %d\n",
1895 value.dwValueType, unicodeResults[i].encoded.cbData, size);
1896 ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1897 "Value type %d: unexpected value\n", value.dwValueType);
1898 LocalFree(buf);
1899 }
1900 }
1901 /* These "encode," but they do so by truncating each unicode character
1902 * rather than properly encoding it. Kept separate from the proper results,
1903 * because the encoded forms won't decode to their original strings.
1904 */
1905 for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1906 {
1907 value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1908 value.dwValueType = unicodeWeirdness[i].valueType;
1909 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1910 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1911 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1912 if (ret)
1913 {
1914 ok(size == unicodeWeirdness[i].encoded.cbData,
1915 "Value type %d: expected size %d, got %d\n",
1916 value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1917 ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1918 "Value type %d: unexpected value\n", value.dwValueType);
1919 LocalFree(buf);
1920 }
1921 }
1922 }
1923
1924 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1925 {
1926 if (n <= 0) return 0;
1927 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1928 return *str1 - *str2;
1929 }
1930
1931 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1932 {
1933 DWORD i;
1934
1935 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1936 {
1937 BYTE *buf = NULL;
1938 BOOL ret;
1939 DWORD size = 0;
1940
1941 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1942 unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1943 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
1944 ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1945 "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1946 if (ret && buf)
1947 {
1948 PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1949
1950 ok(value->dwValueType == unicodeResults[i].valueType,
1951 "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1952 value->dwValueType);
1953 ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1954 value->Value.cbData / sizeof(WCHAR)),
1955 "Unexpected decoded value for index %d (value type %d)\n", i,
1956 unicodeResults[i].valueType);
1957 LocalFree(buf);
1958 }
1959 }
1960 }
1961
1962 struct encodedOctets
1963 {
1964 const BYTE *val;
1965 const BYTE *encoded;
1966 };
1967
1968 static const unsigned char bin46[] = { 'h','i',0 };
1969 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1970 static const unsigned char bin48[] = {
1971 's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1972 static const unsigned char bin49[] = {
1973 0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1974 static const unsigned char bin50[] = { 0 };
1975 static const unsigned char bin51[] = { 0x04,0x00,0 };
1976
1977 static const struct encodedOctets octets[] = {
1978 { bin46, bin47 },
1979 { bin48, bin49 },
1980 { bin50, bin51 },
1981 };
1982
1983 static void test_encodeOctets(DWORD dwEncoding)
1984 {
1985 CRYPT_DATA_BLOB blob;
1986 DWORD i;
1987
1988 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1989 {
1990 BYTE *buf = NULL;
1991 BOOL ret;
1992 DWORD bufSize = 0;
1993
1994 blob.cbData = strlen((const char*)octets[i].val);
1995 blob.pbData = (BYTE*)octets[i].val;
1996 ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1997 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1998 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1999 if (ret)
2000 {
2001 ok(buf[0] == 4,
2002 "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
2003 ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
2004 buf[1], octets[i].encoded[1]);
2005 ok(!memcmp(buf + 1, octets[i].encoded + 1,
2006 octets[i].encoded[1] + 1), "Got unexpected value\n");
2007 LocalFree(buf);
2008 }
2009 }
2010 }
2011
2012 static void test_decodeOctets(DWORD dwEncoding)
2013 {
2014 DWORD i;
2015
2016 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
2017 {
2018 BYTE *buf = NULL;
2019 BOOL ret;
2020 DWORD bufSize = 0;
2021
2022 ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
2023 octets[i].encoded, octets[i].encoded[1] + 2,
2024 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2025 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2026 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
2027 "Expected size >= %d, got %d\n",
2028 (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
2029 ok(buf != NULL, "Expected allocated buffer\n");
2030 if (ret)
2031 {
2032 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
2033
2034 if (blob->cbData)
2035 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
2036 "Unexpected value\n");
2037 LocalFree(buf);
2038 }
2039 }
2040 }
2041
2042 static const BYTE bytesToEncode[] = { 0xff, 0xff };
2043
2044 struct encodedBits
2045 {
2046 DWORD cUnusedBits;
2047 const BYTE *encoded;
2048 DWORD cbDecoded;
2049 const BYTE *decoded;
2050 };
2051
2052 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
2053 static const unsigned char bin53[] = { 0xff,0xff };
2054 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
2055 static const unsigned char bin55[] = { 0xff,0xfe };
2056 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
2057 static const unsigned char bin57[] = { 0xfe };
2058
2059 static const struct encodedBits bits[] = {
2060 /* normal test cases */
2061 { 0, bin52, 2, bin53 },
2062 { 1, bin54, 2, bin55 },
2063 /* strange test case, showing cUnusedBits >= 8 is allowed */
2064 { 9, bin56, 1, bin57 },
2065 };
2066
2067 static void test_encodeBits(DWORD dwEncoding)
2068 {
2069 DWORD i;
2070
2071 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2072 {
2073 CRYPT_BIT_BLOB blob;
2074 BOOL ret;
2075 BYTE *buf = NULL;
2076 DWORD bufSize = 0;
2077
2078 blob.cbData = sizeof(bytesToEncode);
2079 blob.pbData = (BYTE *)bytesToEncode;
2080 blob.cUnusedBits = bits[i].cUnusedBits;
2081 ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
2082 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2083 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2084 if (ret)
2085 {
2086 ok(bufSize == bits[i].encoded[1] + 2,
2087 "%d: Got unexpected size %d, expected %d\n", i, bufSize,
2088 bits[i].encoded[1] + 2);
2089 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
2090 "%d: Unexpected value\n", i);
2091 LocalFree(buf);
2092 }
2093 }
2094 }
2095
2096 static void test_decodeBits(DWORD dwEncoding)
2097 {
2098 static const BYTE ber[] = "\x03\x02\x01\xff";
2099 static const BYTE berDecoded = 0xfe;
2100 DWORD i;
2101 BOOL ret;
2102 BYTE *buf = NULL;
2103 DWORD bufSize = 0;
2104
2105 /* normal cases */
2106 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2107 {
2108 ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2109 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2110 &bufSize);
2111 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2112 if (ret)
2113 {
2114 CRYPT_BIT_BLOB *blob;
2115
2116 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2117 "Got unexpected size %d\n", bufSize);
2118 blob = (CRYPT_BIT_BLOB *)buf;
2119 ok(blob->cbData == bits[i].cbDecoded,
2120 "Got unexpected length %d, expected %d\n", blob->cbData,
2121 bits[i].cbDecoded);
2122 if (blob->cbData && bits[i].cbDecoded)
2123 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2124 "Unexpected value\n");
2125 LocalFree(buf);
2126 }
2127 }
2128 /* special case: check that something that's valid in BER but not in DER
2129 * decodes successfully
2130 */
2131 ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2132 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2133 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2134 if (ret)
2135 {
2136 CRYPT_BIT_BLOB *blob;
2137
2138 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2139 "Got unexpected size %d\n", bufSize);
2140 blob = (CRYPT_BIT_BLOB *)buf;
2141 ok(blob->cbData == sizeof(berDecoded),
2142 "Got unexpected length %d\n", blob->cbData);
2143 if (blob->cbData)
2144 ok(*blob->pbData == berDecoded, "Unexpected value\n");
2145 LocalFree(buf);
2146 }
2147 }
2148
2149 struct Constraints2
2150 {
2151 CERT_BASIC_CONSTRAINTS2_INFO info;
2152 const BYTE *encoded;
2153 };
2154
2155 static const unsigned char bin59[] = { 0x30,0x00 };
2156 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2157 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2158 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2159 static const struct Constraints2 constraints2[] = {
2160 /* empty constraints */
2161 { { FALSE, FALSE, 0}, bin59 },
2162 /* can be a CA */
2163 { { TRUE, FALSE, 0}, bin60 },
2164 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2165 * but that's not the case
2166 */
2167 { { FALSE, TRUE, 0}, bin61 },
2168 /* can be a CA and has path length constraints set */
2169 { { TRUE, TRUE, 1}, bin62 },
2170 };
2171
2172 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2173 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2174 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2175 0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2176 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2177 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2178 0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2179 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2180 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2181 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2182
2183 static void test_encodeBasicConstraints(DWORD dwEncoding)
2184 {
2185 DWORD i, bufSize = 0;
2186 CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2187 CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2188 (LPBYTE)encodedDomainName };
2189 BOOL ret;
2190 BYTE *buf = NULL;
2191
2192 /* First test with the simpler info2 */
2193 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2194 {
2195 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2196 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2197 &bufSize);
2198 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2199 if (ret)
2200 {
2201 ok(bufSize == constraints2[i].encoded[1] + 2,
2202 "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2203 bufSize);
2204 ok(!memcmp(buf, constraints2[i].encoded,
2205 constraints2[i].encoded[1] + 2), "Unexpected value\n");
2206 LocalFree(buf);
2207 }
2208 }
2209 /* Now test with more complex basic constraints */
2210 info.SubjectType.cbData = 0;
2211 info.fPathLenConstraint = FALSE;
2212 info.cSubtreesConstraint = 0;
2213 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2214 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2215 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2216 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2217 if (ret)
2218 {
2219 ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2220 ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2221 "Unexpected value\n");
2222 LocalFree(buf);
2223 }
2224 /* None of the certs I examined had any subtree constraint, but I test one
2225 * anyway just in case.
2226 */
2227 info.cSubtreesConstraint = 1;
2228 info.rgSubtreesConstraint = &nameBlob;
2229 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2230 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2231 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2232 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2233 if (ret)
2234 {
2235 ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2236 ok(!memcmp(buf, constraintWithDomainName,
2237 sizeof(constraintWithDomainName)), "Unexpected value\n");
2238 LocalFree(buf);
2239 }
2240 /* FIXME: test encoding with subject type. */
2241 }
2242
2243 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2244
2245 static void test_decodeBasicConstraints(DWORD dwEncoding)
2246 {
2247 static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2248 0xff };
2249 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2250 DWORD i;
2251 BOOL ret;
2252 BYTE *buf = NULL;
2253 DWORD bufSize = 0;
2254
2255 /* First test with simpler info2 */
2256 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2257 {
2258 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2259 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2260 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2261 ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2262 GetLastError());
2263 if (ret)
2264 {
2265 CERT_BASIC_CONSTRAINTS2_INFO *info =
2266 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2267
2268 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2269 "Unexpected value for item %d\n", i);
2270 LocalFree(buf);
2271 }
2272 }
2273 /* Check with the order of encoded elements inverted */
2274 buf = (PBYTE)1;
2275 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2276 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2277 &bufSize);
2278 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2279 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2280 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2281 GetLastError());
2282 ok(!buf, "Expected buf to be set to NULL\n");
2283 /* Check with a non-DER bool */
2284 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2285 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2286 &buf, &bufSize);
2287 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2288 if (ret)
2289 {
2290 CERT_BASIC_CONSTRAINTS2_INFO *info =
2291 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2292
2293 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2294 LocalFree(buf);
2295 }
2296 /* Check with a non-basic constraints value */
2297 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2298 encodedCommonName, encodedCommonName[1] + 2,
2299 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2300 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2301 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2302 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2303 GetLastError());
2304 /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2305 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2306 emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2307 &buf, &bufSize);
2308 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2309 if (ret)
2310 {
2311 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2312
2313 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2314 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2315 ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2316 LocalFree(buf);
2317 }
2318 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2319 constraintWithDomainName, sizeof(constraintWithDomainName),
2320 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2321 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2322 if (ret)
2323 {
2324 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2325
2326 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2327 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2328 ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2329 if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2330 {
2331 ok(info->rgSubtreesConstraint[0].cbData ==
2332 sizeof(encodedDomainName), "Wrong size %d\n",
2333 info->rgSubtreesConstraint[0].cbData);
2334 ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2335 sizeof(encodedDomainName)), "Unexpected value\n");
2336 }
2337 LocalFree(buf);
2338 }
2339 }
2340
2341 /* These are terrible public keys of course, I'm just testing encoding */
2342 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2343 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2344 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2345 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2346 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2347 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2348 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2349 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2350
2351 struct EncodedRSAPubKey
2352 {
2353 const BYTE *modulus;
2354 size_t modulusLen;
2355 const BYTE *encoded;
2356 size_t decodedModulusLen;
2357 };
2358
2359 static const struct EncodedRSAPubKey rsaPubKeys[] = {
2360 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2361 { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2362 { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2363 { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2364 };
2365
2366 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2367 {
2368 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2369 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2370 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2371 BOOL ret;
2372 BYTE *buf = NULL;
2373 DWORD bufSize = 0, i;
2374
2375 /* Try with a bogus blob type */
2376 hdr->bType = 2;
2377 hdr->bVersion = CUR_BLOB_VERSION;
2378 hdr->reserved = 0;
2379 hdr->aiKeyAlg = CALG_RSA_KEYX;
2380 rsaPubKey->magic = 0x31415352;
2381 rsaPubKey->bitlen = sizeof(modulus1) * 8;
2382 rsaPubKey->pubexp = 65537;
2383 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2384 sizeof(modulus1));
2385
2386 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2387 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2388 ok(!ret && GetLastError() == E_INVALIDARG,
2389 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2390 /* Now with a bogus reserved field */
2391 hdr->bType = PUBLICKEYBLOB;
2392 hdr->reserved = 1;
2393 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2394 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2395 if (ret)
2396 {
2397 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2398 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2399 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2400 LocalFree(buf);
2401 }
2402 /* Now with a bogus blob version */
2403 hdr->reserved = 0;
2404 hdr->bVersion = 0;
2405 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2406 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2407 if (ret)
2408 {
2409 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2410 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2411 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2412 LocalFree(buf);
2413 }
2414 /* And with a bogus alg ID */
2415 hdr->bVersion = CUR_BLOB_VERSION;
2416 hdr->aiKeyAlg = CALG_DES;
2417 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2418 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2419 if (ret)
2420 {
2421 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2422 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2423 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2424 LocalFree(buf);
2425 }
2426 /* Check a couple of RSA-related OIDs */
2427 hdr->aiKeyAlg = CALG_RSA_KEYX;
2428 ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2429 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2430 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2431 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2432 ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2433 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2434 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2435 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2436 /* Finally, all valid */
2437 hdr->aiKeyAlg = CALG_RSA_KEYX;
2438 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2439 {
2440 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2441 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2442 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2443 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2444 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2445 if (ret)
2446 {
2447 ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2448 "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2449 bufSize);
2450 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2451 "Unexpected value\n");
2452 LocalFree(buf);
2453 }
2454 }
2455 }
2456
2457 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2458 {
2459 DWORD i;
2460 LPBYTE buf = NULL;
2461 DWORD bufSize = 0;
2462 BOOL ret;
2463
2464 /* Try with a bad length */
2465 ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2466 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2467 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2468 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2469 GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2470 "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2471 GetLastError());
2472 /* Try with a couple of RSA-related OIDs */
2473 ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2474 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2475 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2476 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2477 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2478 ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2479 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2480 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2481 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2482 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2483 /* Now try success cases */
2484 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2485 {
2486 bufSize = 0;
2487 ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2488 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2489 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2490 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2491 if (ret)
2492 {
2493 BLOBHEADER *hdr = (BLOBHEADER *)buf;
2494 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2495
2496 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2497 rsaPubKeys[i].decodedModulusLen,
2498 "Wrong size %d\n", bufSize);
2499 ok(hdr->bType == PUBLICKEYBLOB,
2500 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2501 hdr->bType);
2502 ok(hdr->bVersion == CUR_BLOB_VERSION,
2503 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2504 CUR_BLOB_VERSION, hdr->bVersion);
2505 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2506 hdr->reserved);
2507 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2508 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2509 ok(rsaPubKey->magic == 0x31415352,
2510 "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2511 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2512 "Wrong bit len %d\n", rsaPubKey->bitlen);
2513 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2514 rsaPubKey->pubexp);
2515 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2516 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2517 "Unexpected modulus\n");
2518 LocalFree(buf);
2519 }
2520 }
2521 }
2522
2523 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2524 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2525 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2526
2527 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2528 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2529 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2530 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2531
2532 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2533 {
2534 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2535 CRYPT_SEQUENCE_OF_ANY seq;
2536 DWORD i;
2537 BOOL ret;
2538 BYTE *buf = NULL;
2539 DWORD bufSize = 0;
2540
2541 /* Encode a homogeneous sequence */
2542 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2543 {
2544 blobs[i].cbData = ints[i].encoded[1] + 2;
2545 blobs[i].pbData = (BYTE *)ints[i].encoded;
2546 }
2547 seq.cValue = sizeof(ints) / sizeof(ints[0]);
2548 seq.rgValue = blobs;
2549
2550 ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2551 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2552 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2553 if (ret)
2554 {
2555 ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2556 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2557 LocalFree(buf);
2558 }
2559 /* Change the type of the first element in the sequence, and give it
2560 * another go
2561 */
2562 blobs[0].cbData = times[0].encodedTime[1] + 2;
2563 blobs[0].pbData = (BYTE *)times[0].encodedTime;
2564 ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2565 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2566 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2567 if (ret)
2568 {
2569 ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2570 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2571 "Unexpected value\n");
2572 LocalFree(buf);
2573 }
2574 }
2575
2576 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2577 {
2578 BOOL ret;
2579 BYTE *buf = NULL;
2580 DWORD bufSize = 0;
2581
2582 ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2583 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2584 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2585 if (ret)
2586 {
2587 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2588 DWORD i;
2589
2590 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2591 "Wrong elements %d\n", seq->cValue);
2592 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2593 {
2594 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2595 "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2596 seq->rgValue[i].cbData);
2597 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2598 ints[i].encoded[1] + 2), "Unexpected value\n");
2599 }
2600 LocalFree(buf);
2601 }
2602 ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2603 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2604 &bufSize);
2605 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2606 if (ret)
2607 {
2608 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2609
2610 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2611 "Wrong elements %d\n", seq->cValue);
2612 /* Just check the first element since it's all that changed */
2613 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2614 "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2615 seq->rgValue[0].cbData);
2616 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2617 times[0].encodedTime[1] + 2), "Unexpected value\n");
2618 LocalFree(buf);
2619 }
2620 }
2621
2622 struct encodedExtensions
2623 {
2624 CERT_EXTENSIONS exts;
2625 const BYTE *encoded;
2626 };
2627
2628 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2629 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2630 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2631 static CERT_EXTENSION criticalExt =
2632 { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2633 static CERT_EXTENSION nonCriticalExt =
2634 { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2635 static CHAR oid_short[] = "1.1";
2636 static CERT_EXTENSION extWithShortOid =
2637 { oid_short, FALSE, { 0, NULL } };
2638
2639 static const BYTE ext0[] = { 0x30,0x00 };
2640 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2641 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2642 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2643 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2644 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2645
2646 static const struct encodedExtensions exts[] = {
2647 { { 0, NULL }, ext0 },
2648 { { 1, &criticalExt }, ext1 },
2649 { { 1, &nonCriticalExt }, ext2 },
2650 { { 1, &extWithShortOid }, ext3 }
2651 };
2652
2653 static void test_encodeExtensions(DWORD dwEncoding)
2654 {
2655 DWORD i;
2656
2657 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2658 {
2659 BOOL ret;
2660 BYTE *buf = NULL;
2661 DWORD bufSize = 0;
2662
2663 ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2664 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2665 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2666 if (ret)
2667 {
2668 ok(bufSize == exts[i].encoded[1] + 2,
2669 "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2670 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2671 "Unexpected value\n");
2672 LocalFree(buf);
2673 }
2674 }
2675 }
2676
2677 static void test_decodeExtensions(DWORD dwEncoding)
2678 {
2679 DWORD i;
2680
2681 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2682 {
2683 BOOL ret;
2684 BYTE *buf = NULL;
2685 DWORD bufSize = 0;
2686
2687 ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2688 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2689 NULL, &buf, &bufSize);
2690 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2691 if (ret)
2692 {
2693 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2694 DWORD j;
2695
2696 ok(ext->cExtension == exts[i].exts.cExtension,
2697 "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2698 ext->cExtension);
2699 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2700 {
2701 ok(!strcmp(ext->rgExtension[j].pszObjId,
2702 exts[i].exts.rgExtension[j].pszObjId),
2703 "Expected OID %s, got %s\n",
2704 exts[i].exts.rgExtension[j].pszObjId,
2705 ext->rgExtension[j].pszObjId);
2706 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2707 exts[i].exts.rgExtension[j].Value.pbData,
2708 exts[i].exts.rgExtension[j].Value.cbData),
2709 "Unexpected value\n");
2710 }
2711 LocalFree(buf);
2712 }
2713 ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2714 exts[i].encoded, exts[i].encoded[1] + 2, 0, NULL, NULL, &bufSize);
2715 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2716 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufSize);
2717 if (buf)
2718 {
2719 ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2720 exts[i].encoded, exts[i].encoded[1] + 2, 0, NULL, buf, &bufSize);
2721 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2722 HeapFree(GetProcessHeap(), 0, buf);
2723 }
2724 }
2725 }
2726
2727 /* MS encodes public key info with a NULL if the algorithm identifier's
2728 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
2729 * it encodes them by omitting the algorithm parameters. It accepts either
2730 * form for decoding.
2731 */
2732 struct encodedPublicKey
2733 {
2734 CERT_PUBLIC_KEY_INFO info;
2735 const BYTE *encoded;
2736 const BYTE *encodedNoNull;
2737 CERT_PUBLIC_KEY_INFO decoded;
2738 };
2739
2740 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2741 0xe, 0xf };
2742 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2743
2744 static const unsigned char bin64[] = {
2745 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2746 static const unsigned char bin65[] = {
2747 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2748 static const unsigned char bin66[] = {
2749 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2750 static const unsigned char bin67[] = {
2751 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2752 static const unsigned char bin68[] = {
2753 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2754 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2755 static const unsigned char bin69[] = {
2756 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2757 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2758 static const unsigned char bin70[] = {
2759 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2760 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2761 0x0f};
2762 static const unsigned char bin71[] = {
2763 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2764 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2765 0x0f};
2766 static unsigned char bin72[] = { 0x05,0x00};
2767
2768 static CHAR oid_bogus[] = "1.2.3",
2769 oid_rsa[] = szOID_RSA;
2770
2771 static const struct encodedPublicKey pubKeys[] = {
2772 /* with a bogus OID */
2773 { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2774 bin64, bin65,
2775 { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2776 /* some normal keys */
2777 { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2778 bin66, bin67,
2779 { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2780 { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2781 bin68, bin69,
2782 { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2783 /* with add'l parameters--note they must be DER-encoded */
2784 { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2785 (BYTE *)aKey, 0 } },
2786 bin70, bin71,
2787 { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2788 (BYTE *)aKey, 0 } } },
2789 };
2790
2791 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2792 {
2793 DWORD i;
2794
2795 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2796 {
2797 BOOL ret;
2798 BYTE *buf = NULL;
2799 DWORD bufSize = 0;
2800
2801 ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2802 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2803 &bufSize);
2804 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2805 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2806 if (ret)
2807 {
2808 ok(bufSize == pubKeys[i].encoded[1] + 2,
2809 "Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize);
2810 if (bufSize == pubKeys[i].encoded[1] + 2)
2811 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2812 "Unexpected value\n");
2813 LocalFree(buf);
2814 }
2815 }
2816 }
2817
2818 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2819 const CERT_PUBLIC_KEY_INFO *got)
2820 {
2821 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2822 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2823 got->Algorithm.pszObjId);
2824 ok(expected->Algorithm.Parameters.cbData ==
2825 got->Algorithm.Parameters.cbData,
2826 "Expected parameters of %d bytes, got %d\n",
2827 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2828 if (expected->Algorithm.Parameters.cbData)
2829 ok(!memcmp(expected->Algorithm.Parameters.pbData,
2830 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2831 "Unexpected algorithm parameters\n");
2832 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2833 "Expected public key of %d bytes, got %d\n",
2834 expected->PublicKey.cbData, got->PublicKey.cbData);
2835 if (expected->PublicKey.cbData)
2836 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2837 got->PublicKey.cbData), "Unexpected public key value\n");
2838 }
2839
2840 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2841 {
2842 static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2843 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2844 0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2845 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2846 DWORD i;
2847 BOOL ret;
2848 BYTE *buf = NULL;
2849 DWORD bufSize = 0;
2850
2851 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2852 {
2853 /* The NULL form decodes to the decoded member */
2854 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2855 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2856 NULL, &buf, &bufSize);
2857 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2858 if (ret)
2859 {
2860 comparePublicKeyInfo(&pubKeys[i].decoded,
2861 (CERT_PUBLIC_KEY_INFO *)buf);
2862 LocalFree(buf);
2863 }
2864 /* The non-NULL form decodes to the original */
2865 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2866 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2867 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2868 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2869 if (ret)
2870 {
2871 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2872 LocalFree(buf);
2873 }
2874 }
2875 /* Test with bogus (not valid DER) parameters */
2876 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2877 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2878 NULL, &buf, &bufSize);
2879 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2880 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2881 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2882 GetLastError());
2883 }
2884
2885 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2886 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2887 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2888 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2889 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2890 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2891 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2892 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2893 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2894 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2895 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2896 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2897 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2898 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2899 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2900 static const BYTE v4Cert[] = {
2901 0x30,0x38,0xa0,0x03,0x02,0x01,0x03,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,
2902 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
2903 0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
2904 0x30,0x30,0x30,0x5a,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00 };
2905 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2906 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2907 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2908 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2909 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2910 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2911 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2912 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2913 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2914 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2915 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2916 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2917 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2918 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2919 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2920 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2921 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2922 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2923 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2924 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2925 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2926 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2927 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2928 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2929 static const BYTE v1CertWithPubKey[] = {
2930 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2931 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2932 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2933 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2934 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2935 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2936 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2937 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2938 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2939 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2940 0x01,0x01 };
2941 static const BYTE v1CertWithPubKeyNoNull[] = {
2942 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2943 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2944 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2945 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2946 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2947 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2948 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2949 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2950 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2951 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2952 static const BYTE v1CertWithSubjectKeyId[] = {
2953 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2954 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2955 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2956 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2957 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2958 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2959 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2960 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2961 0x4c,0x61,0x6e,0x67,0x00 };
2962 static const BYTE v1CertWithIssuerUniqueId[] = {
2963 0x30,0x38,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2964 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
2965 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
2966 0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x81,0x02,0x00,0x01 };
2967 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueId[] = {
2968 0x30,0x81,0x99,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2969 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2970 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2971 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2972 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2973 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2974 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2975 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2976 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,
2977 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
2978 0x01,0x01,0xff,0x02,0x01,0x01 };
2979 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull[] = {
2980 0x30,0x81,0x97,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2981 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2982 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2983 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2984 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2985 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2986 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2987 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2988 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,
2989 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
2990 0xff,0x02,0x01,0x01 };
2991
2992 static const BYTE serialNum[] = { 0x01 };
2993
2994 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2995 {
2996 BOOL ret;
2997 BYTE *buf = NULL;
2998 DWORD size = 0;
2999 CERT_INFO info = { 0 };
3000 static char oid_rsa_rsa[] = szOID_RSA_RSA;
3001 static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
3002 CERT_EXTENSION ext;
3003
3004 if (0)
3005 {
3006 /* Test with NULL pvStructInfo (crashes on win9x) */
3007 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
3008 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3009 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3010 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3011 }
3012 /* Test with a V1 cert */
3013 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3014 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3015 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3016 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3017 if (ret)
3018 {
3019 ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
3020 v1Cert[1] + 2, size);
3021 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
3022 LocalFree(buf);
3023 }
3024 /* Test v2 cert */
3025 info.dwVersion = CERT_V2;
3026 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3027 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3028 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3029 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3030 if (ret)
3031 {
3032 ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
3033 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
3034 LocalFree(buf);
3035 }
3036 /* Test v3 cert */
3037 info.dwVersion = CERT_V3;
3038 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3039 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3040 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3041 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3042 if (ret)
3043 {
3044 ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
3045 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
3046 LocalFree(buf);
3047 }
3048 /* A v4 cert? */
3049 info.dwVersion = 3; /* Not a typo, CERT_V3 is 2 */
3050 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3051 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3052 if (ret)
3053 {
3054 ok(size == sizeof(v4Cert), "Wrong size %d\n", size);
3055 ok(!memcmp(buf, v4Cert, size), "Unexpected value\n");
3056 LocalFree(buf);
3057 }
3058 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
3059 * API doesn't prevent it)
3060 */
3061 info.dwVersion = CERT_V1;
3062 info.cExtension = 1;
3063 info.rgExtension = &criticalExt;
3064 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3065 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3066 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3067 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3068 if (ret)
3069 {
3070 ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
3071 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
3072 LocalFree(buf);
3073 }
3074 /* test v1 cert with a serial number */
3075 info.SerialNumber.cbData = sizeof(serialNum);
3076 info.SerialNumber.pbData = (BYTE *)serialNum;
3077 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3078 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3079 if (ret)
3080 {
3081 ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
3082 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
3083 LocalFree(buf);
3084 }
3085 /* Test v1 cert with an issuer name, serial number, and issuer unique id */
3086 info.dwVersion = CERT_V1;
3087 info.cExtension = 0;
3088 info.IssuerUniqueId.cbData = sizeof(serialNum);
3089 info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3090 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3091 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3092 ok(ret || broken(GetLastError() == OSS_BAD_PTR /* Win98 */),
3093 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3094 if (ret)
3095 {
3096 ok(size == sizeof(v1CertWithIssuerUniqueId), "Wrong size %d\n", size);
3097 ok(!memcmp(buf, v1CertWithIssuerUniqueId, size),
3098 "Got unexpected value\n");
3099 LocalFree(buf);
3100 }
3101 /* Test v1 cert with an issuer name, a subject name, and a serial number */
3102 info.IssuerUniqueId.cbData = 0;
3103 info.IssuerUniqueId.pbData = NULL;
3104 info.cExtension = 1;
3105 info.rgExtension = &criticalExt;
3106 info.Issuer.cbData = sizeof(encodedCommonName);
3107 info.Issuer.pbData = (BYTE *)encodedCommonName;
3108 info.Subject.cbData = sizeof(encodedCommonName);
3109 info.Subject.pbData = (BYTE *)encodedCommonName;
3110 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3111 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3112 if (ret)
3113 {
3114 ok(size == sizeof(bigCert), "Wrong size %d\n", size);
3115 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
3116 LocalFree(buf);
3117 }
3118 /* Add a public key */
3119 info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
3120 info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
3121 info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
3122 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3123 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3124 if (ret)
3125 {
3126 ok(size == sizeof(v1CertWithPubKey) ||
3127 size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
3128 if (size == sizeof(v1CertWithPubKey))
3129 ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
3130 else if (size == sizeof(v1CertWithPubKeyNoNull))
3131 ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
3132 "Got unexpected value\n");
3133 LocalFree(buf);
3134 }
3135 /* Again add an issuer unique id */
3136 info.IssuerUniqueId.cbData = sizeof(serialNum);
3137 info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3138 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3139 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3140 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3141 if (ret)
3142 {
3143 ok(size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId) ||
3144 size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull),
3145 "Wrong size %d\n", size);
3146 if (size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId))
3147 ok(!memcmp(buf, v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3148 size), "unexpected value\n");
3149 else if (size ==
3150 sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull))
3151 ok(!memcmp(buf,
3152 v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull, size),
3153 "unexpected value\n");
3154 LocalFree(buf);
3155 }
3156 /* Remove the public key, and add a subject key identifier extension */
3157 info.IssuerUniqueId.cbData = 0;
3158 info.IssuerUniqueId.pbData = NULL;
3159 info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
3160 info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
3161 info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
3162 ext.pszObjId = oid_subject_key_identifier;
3163 ext.fCritical = FALSE;
3164 ext.Value.cbData = sizeof(octetCommonNameValue);
3165 ext.Value.pbData = octetCommonNameValue;
3166 info.cExtension = 1;
3167 info.rgExtension = &ext;
3168 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3169 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3170 if (ret)
3171 {
3172 ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
3173 ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
3174 LocalFree(buf);
3175 }
3176 }
3177
3178 static void test_decodeCertToBeSigned(DWORD dwEncoding)
3179 {
3180 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert, v4Cert,
3181 v1CertWithConstraints, v1CertWithSerial, v1CertWithIssuerUniqueId };
3182 BOOL ret;
3183 BYTE *buf = NULL;
3184 DWORD size = 0, i;
3185
3186 /* Test with NULL pbEncoded */
3187 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
3188 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3189 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
3190 GetLastError() == OSS_BAD_ARG /* Win9x */),
3191 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
3192 if (0)
3193 {
3194 /* Crashes on win9x */
3195 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3196 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3197 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3198 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3199 }
3200 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT or
3201 * CRYPT_E_ASN1_BADTAG, because at a minimum a cert must have a non-zero
3202 * serial number, an issuer, a subject, and a public key.
3203 */
3204 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3205 {
3206 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3207 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3208 &buf, &size);
3209 ok(!ret, "Expected failure\n");
3210 }
3211 /* The following succeeds, even though v1 certs are not allowed to have
3212 * extensions.
3213 */
3214 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3215 v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId),
3216 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3217 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3218 if (ret)
3219 {
3220 CERT_INFO *info = (CERT_INFO *)buf;
3221
3222 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3223 ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3224 info->dwVersion);
3225 ok(info->cExtension == 1, "expected 1 extension, got %d\n",
3226 info->cExtension);
3227 LocalFree(buf);
3228 }
3229 /* The following also succeeds, even though V1 certs are not allowed to
3230 * have issuer unique ids.
3231 */
3232 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3233 v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3234 sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId),
3235 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3236 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3237 if (ret)
3238 {
3239 CERT_INFO *info = (CERT_INFO *)buf;
3240
3241 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3242 ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3243 info->dwVersion);
3244 ok(info->IssuerUniqueId.cbData == sizeof(serialNum),
3245 "unexpected issuer unique id size %d\n", info->IssuerUniqueId.cbData);
3246 ok(!memcmp(info->IssuerUniqueId.pbData, serialNum, sizeof(serialNum)),
3247 "unexpected issuer unique id value\n");
3248 LocalFree(buf);
3249 }
3250 /* Now check with serial number, subject and issuer specified */
3251 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3252 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3253 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3254 if (ret)
3255 {
3256 CERT_INFO *info = (CERT_INFO *)buf;
3257
3258 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3259 ok(info->SerialNumber.cbData == 1,
3260 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3261 ok(*info->SerialNumber.pbData == *serialNum,
3262 "Expected serial number %d, got %d\n", *serialNum,
3263 *info->SerialNumber.pbData);
3264 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3265 "Wrong size %d\n", info->Issuer.cbData);
3266 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3267 "Unexpected issuer\n");
3268 ok(info->Subject.cbData == sizeof(encodedCommonName),
3269 "Wrong size %d\n", info->Subject.cbData);
3270 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3271 info->Subject.cbData), "Unexpected subject\n");
3272 LocalFree(buf);
3273 }
3274 /* Check again with pub key specified */
3275 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3276 v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3277 &buf, &size);
3278 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3279 if (ret)
3280 {
3281 CERT_INFO *info = (CERT_INFO *)buf;
3282
3283 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3284 ok(info->SerialNumber.cbData == 1,
3285 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3286 ok(*info->SerialNumber.pbData == *serialNum,
3287 "Expected serial number %d, got %d\n", *serialNum,
3288 *info->SerialNumber.pbData);
3289 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3290 "Wrong size %d\n", info->Issuer.cbData);
3291 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3292 "Unexpected issuer\n");
3293 ok(info->Subject.cbData == sizeof(encodedCommonName),
3294 "Wrong size %d\n", info->Subject.cbData);
3295 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3296 info->Subject.cbData), "Unexpected subject\n");
3297 ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3298 szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3299 info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3300 ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3301 "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3302 ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3303 sizeof(aKey)), "Unexpected public key\n");
3304 LocalFree(buf);
3305 }
3306 }
3307
3308 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3309 0xe, 0xf };
3310
3311 static const BYTE signedBigCert[] = {
3312 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3313 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3314 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3315 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3316 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3317 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3318 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3319 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3320 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3321 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3322 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3323 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3324
3325 static void test_encodeCert(DWORD dwEncoding)
3326 {
3327 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
3328 * also that bigCert is a NULL-terminated string, so don't count its
3329 * last byte (otherwise the signed cert won't decode.)
3330 */
3331 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3332 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3333 BOOL ret;
3334 BYTE *buf = NULL;
3335 DWORD bufSize = 0;
3336
3337 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3338 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3339 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3340 if (ret)
3341 {
3342 ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3343 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3344 LocalFree(buf);
3345 }
3346 }
3347
3348 static void test_decodeCert(DWORD dwEncoding)
3349 {
3350 BOOL ret;
3351 BYTE *buf = NULL;
3352 DWORD size = 0;
3353
3354 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3355 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3356 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3357 if (ret)
3358 {
3359 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3360
3361 ok(info->ToBeSigned.cbData == sizeof(bigCert),
3362 "Wrong cert size %d\n", info->ToBeSigned.cbData);
3363 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3364 "Unexpected cert\n");
3365 ok(info->Signature.cbData == sizeof(hash),
3366 "Wrong signature size %d\n", info->Signature.cbData);
3367 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3368 "Unexpected signature\n");
3369 LocalFree(buf);
3370 }
3371 /* A signed cert decodes as a CERT_INFO too */
3372 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3373 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3374 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3375 if (ret)
3376 {
3377 CERT_INFO *info = (CERT_INFO *)buf;
3378
3379 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3380 ok(info->SerialNumber.cbData == 1,
3381 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3382 ok(*info->SerialNumber.pbData == *serialNum,
3383 "Expected serial number %d, got %d\n", *serialNum,
3384 *info->SerialNumber.pbData);
3385 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3386 "Wrong size %d\n", info->Issuer.cbData);
3387 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3388 "Unexpected issuer\n");
3389 ok(info->Subject.cbData == sizeof(encodedCommonName),
3390 "Wrong size %d\n", info->Subject.cbData);
3391 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3392 info->Subject.cbData), "Unexpected subject\n");
3393 LocalFree(buf);
3394 }
3395 }
3396
3397 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3398 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3399 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3400 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3401 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3402 0x00, 0x03 };
3403 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3404 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3405 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3406 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3407 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3408 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3409 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3410 0x2e, 0x6f, 0x72, 0x67 };
3411 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3412 CRL_REASON_AFFILIATION_CHANGED;
3413
3414 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3415 {
3416 CRL_DIST_POINTS_INFO info = { 0 };
3417 CRL_DIST_POINT point = { { 0 } };
3418 CERT_ALT_NAME_ENTRY entry = { 0 };
3419 BOOL ret;
3420 BYTE *buf = NULL;
3421 DWORD size = 0;
3422
3423 /* Test with an empty info */
3424 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3425 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3426 ok(!ret && GetLastError() == E_INVALIDARG,
3427 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3428 /* Test with one empty dist point */
3429 info.cDistPoint = 1;
3430 info.rgDistPoint = &point;
3431 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3432 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3433 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3434 if (ret)
3435 {
3436 ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3437 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3438 LocalFree(buf);
3439 }
3440 /* A dist point with an invalid name */
3441 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3442 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3443 U(entry).pwszURL = (LPWSTR)nihongoURL;
3444 U(point.DistPointName).FullName.cAltEntry = 1;
3445 U(point.DistPointName).FullName.rgAltEntry = &entry;
3446 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3447 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3448 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3449 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3450 /* The first invalid character is at index 7 */
3451 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3452 "Expected invalid char at index 7, got %d\n",
3453 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3454 /* A dist point with (just) a valid name */
3455 U(entry).pwszURL = (LPWSTR)url;
3456 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3457 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3458 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3459 if (ret)
3460 {
3461 ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3462 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3463 LocalFree(buf);
3464 }
3465 /* A dist point with (just) reason flags */
3466 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3467 point.ReasonFlags.cbData = sizeof(crlReason);
3468 point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3469 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3470 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3471 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3472 if (ret)
3473 {
3474 ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3475 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3476 LocalFree(buf);
3477 }
3478 /* A dist point with just an issuer */
3479 point.ReasonFlags.cbData = 0;
3480 point.CRLIssuer.cAltEntry = 1;
3481 point.CRLIssuer.rgAltEntry = &entry;
3482 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3483 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3484 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3485 if (ret)
3486 {
3487 ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3488 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3489 LocalFree(buf);
3490 }
3491 /* A dist point with both a name and an issuer */
3492 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3493 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3494 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3495 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3496 if (ret)
3497 {
3498 ok(size == sizeof(distPointWithUrlAndIssuer),
3499 "Wrong size %d\n", size);
3500 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3501 LocalFree(buf);
3502 }
3503 }
3504
3505 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3506 {
3507 BOOL ret;
3508 BYTE *buf = NULL;
3509 DWORD size = 0;
3510 PCRL_DIST_POINTS_INFO info;
3511 PCRL_DIST_POINT point;
3512 PCERT_ALT_NAME_ENTRY entry;
3513
3514 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3515 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3516 &buf, &size);
3517 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3518 if (ret)
3519 {
3520 info = (PCRL_DIST_POINTS_INFO)buf;
3521 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3522 "Wrong size %d\n", size);
3523 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3524 info->cDistPoint);
3525 point = info->rgDistPoint;
3526 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3527 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3528 point->DistPointName.dwDistPointNameChoice);
3529 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3530 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3531 LocalFree(buf);
3532 }
3533 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3534 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3535 &buf, &size);
3536 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3537 if (ret)
3538 {
3539 info = (PCRL_DIST_POINTS_INFO)buf;
3540 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3541 "Wrong size %d\n", size);
3542 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3543 info->cDistPoint);
3544 point = info->rgDistPoint;
3545 ok(point->DistPointName.dwDistPointNameChoice ==
3546 CRL_DIST_POINT_FULL_NAME,
3547 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3548 point->DistPointName.dwDistPointNameChoice);
3549 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3550 "Expected 1 name entry, got %d\n",
3551 U(point->DistPointName).FullName.cAltEntry);
3552 entry = U(point->DistPointName).FullName.rgAltEntry;
3553 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3554 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3555 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3556 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3557 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3558 LocalFree(buf);
3559 }
3560 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3561 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3562 NULL, &buf, &size);
3563 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3564 if (ret)
3565 {
3566 info = (PCRL_DIST_POINTS_INFO)buf;
3567 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3568 "Wrong size %d\n", size);
3569 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3570 info->cDistPoint);
3571 point = info->rgDistPoint;
3572 ok(point->DistPointName.dwDistPointNameChoice ==
3573 CRL_DIST_POINT_NO_NAME,
3574 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3575 point->DistPointName.dwDistPointNameChoice);
3576 ok(point->ReasonFlags.cbData == sizeof(crlReason),
3577 "Expected reason length\n");
3578 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3579 "Unexpected reason\n");
3580 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3581 LocalFree(buf);
3582 }
3583 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3584 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3585 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3586 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3587 if (ret)
3588 {
3589 info = (PCRL_DIST_POINTS_INFO)buf;
3590 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3591 "Wrong size %d\n", size);
3592 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3593 info->cDistPoint);
3594 point = info->rgDistPoint;
3595 ok(point->DistPointName.dwDistPointNameChoice ==
3596 CRL_DIST_POINT_FULL_NAME,
3597 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3598 point->DistPointName.dwDistPointNameChoice);
3599 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3600 "Expected 1 name entry, got %d\n",
3601 U(point->DistPointName).FullName.cAltEntry);
3602 entry = U(point->DistPointName).FullName.rgAltEntry;
3603 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3604 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3605 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3606 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3607 ok(point->CRLIssuer.cAltEntry == 1,
3608 "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3609 entry = point->CRLIssuer.rgAltEntry;
3610 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3611 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3612 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3613 LocalFree(buf);
3614 }
3615 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3616 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2, 0,
3617 NULL, NULL, &size);
3618 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3619 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3620 if (buf)
3621 {
3622 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3623 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2, 0,
3624 NULL, buf, &size);
3625 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3626 HeapFree(GetProcessHeap(), 0, buf);
3627 }
3628 }
3629
3630 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3631 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3632 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3633 0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3634 0x67 };
3635
3636 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3637 {
3638 BOOL ret;
3639 BYTE *buf = NULL;
3640 DWORD size = 0;
3641 CRL_ISSUING_DIST_POINT point = { { 0 } };
3642 CERT_ALT_NAME_ENTRY entry;
3643
3644 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3645 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3646 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3647 {
3648 skip("no X509_ISSUING_DIST_POINT encode support\n");
3649 return;
3650 }
3651 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3652 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3653 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3654 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3655 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3656 if (ret)
3657 {
3658 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3659 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3660 LocalFree(buf);
3661 }
3662 /* nonsensical flags */
3663 point.fOnlyContainsUserCerts = TRUE;
3664 point.fOnlyContainsCACerts = TRUE;
3665 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3666 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3667 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3668 if (ret)
3669 {
3670 ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3671 ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3672 LocalFree(buf);
3673 }
3674 /* unimplemented name type */
3675 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3676 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3677 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3678 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3679 ok(!ret && GetLastError() == E_INVALIDARG,
3680 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3681 /* empty name */
3682 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3683 U(point.DistPointName).FullName.cAltEntry = 0;
3684 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3685 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3686 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3687 if (ret)
3688 {
3689 ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3690 ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3691 LocalFree(buf);
3692 }
3693 /* name with URL entry */
3694 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3695 U(entry).pwszURL = (LPWSTR)url;
3696 U(point.DistPointName).FullName.cAltEntry = 1;
3697 U(point.DistPointName).FullName.rgAltEntry = &entry;
3698 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3699 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3700 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3701 if (ret)
3702 {
3703 ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3704 ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3705 LocalFree(buf);
3706 }
3707 }
3708
3709 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3710 const CERT_ALT_NAME_ENTRY *got)
3711 {
3712 ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3713 "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3714 got->dwAltNameChoice);
3715 if (expected->dwAltNameChoice == got->dwAltNameChoice)
3716 {
3717 switch (got->dwAltNameChoice)
3718 {
3719 case CERT_ALT_NAME_RFC822_NAME:
3720 case CERT_ALT_NAME_DNS_NAME:
3721 case CERT_ALT_NAME_EDI_PARTY_NAME:
3722 case CERT_ALT_NAME_URL:
3723 case CERT_ALT_NAME_REGISTERED_ID:
3724 ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3725 (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3726 (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3727 !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3728 "Unexpected name\n");
3729 break;
3730 case CERT_ALT_NAME_X400_ADDRESS:
3731 case CERT_ALT_NAME_DIRECTORY_NAME:
3732 case CERT_ALT_NAME_IP_ADDRESS:
3733 ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3734 "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3735 ok(!memcmp(U(*got).IPAddress.pbData, U(*expected).IPAddress.pbData,
3736 U(*got).IPAddress.cbData), "Unexpected value\n");
3737 break;
3738 }
3739 }
3740 }
3741
3742 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3743 const CERT_ALT_NAME_INFO *got)
3744 {
3745 DWORD i;
3746
3747 ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3748 expected->cAltEntry, got->cAltEntry);
3749 for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3750 compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3751 }
3752
3753 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3754 const CRL_DIST_POINT_NAME *got)
3755 {
3756 ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3757 "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3758 if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3759 compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3760 }
3761
3762 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3763 const CRL_ISSUING_DIST_POINT *got)
3764 {
3765 compareDistPointName(&expected->DistPointName, &got->DistPointName);
3766 ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3767 "Unexpected fOnlyContainsUserCerts\n");
3768 ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3769 "Unexpected fOnlyContainsCACerts\n");
3770 ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3771 "Unexpected reason flags\n");
3772 ok(got->fIndirectCRL == expected->fIndirectCRL,
3773 "Unexpected fIndirectCRL\n");
3774 }
3775
3776 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3777 {
3778 BOOL ret;
3779 BYTE *buf = NULL;
3780 DWORD size = 0;
3781 CRL_ISSUING_DIST_POINT point = { { 0 } };
3782
3783 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3784 emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3785 &buf, &size);
3786 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3787 {
3788 skip("no X509_ISSUING_DIST_POINT decode support\n");
3789 return;
3790 }
3791 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3792 if (ret)
3793 {
3794 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3795 LocalFree(buf);
3796 }
3797 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3798 badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3799 &buf, &size);
3800 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3801 if (ret)
3802 {
3803 point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3804 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3805 LocalFree(buf);
3806 }
3807 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3808 emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3809 &buf, &size);
3810 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3811 if (ret)
3812 {
3813 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3814 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3815 U(point.DistPointName).FullName.cAltEntry = 0;
3816 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3817 LocalFree(buf);
3818 }
3819 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3820 urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3821 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3822 if (ret)
3823 {
3824 CERT_ALT_NAME_ENTRY entry;
3825
3826 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3827 U(entry).pwszURL = (LPWSTR)url;
3828 U(point.DistPointName).FullName.cAltEntry = 1;
3829 U(point.DistPointName).FullName.rgAltEntry = &entry;
3830 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3831 LocalFree(buf);
3832 }
3833 }
3834
3835 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3836 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3837 0x30, 0x5a };
3838 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3839 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3840 0x30, 0x30, 0x30, 0x30, 0x5a };
3841 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3842 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3843 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3844 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3845 0x5a };
3846 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3847 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3848 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3849 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3850 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3851 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3852 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3853 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3854 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3855 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3856 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3857 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3858 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3859 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3860 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3861 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3862 0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3863 0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3864 0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3865 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3866 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3867 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3868 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3869 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3870 0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3871 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3872 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3873 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3874 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3875 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3876 0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3877 0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3878 0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3879
3880 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3881 {
3882 BOOL ret;
3883 BYTE *buf = NULL;
3884 DWORD size = 0;
3885 CRL_INFO info = { 0 };
3886 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3887
3888 /* Test with a V1 CRL */
3889 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3890 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3891 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3892 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3893 if (ret)
3894 {
3895 ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3896 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3897 LocalFree(buf);
3898 }
3899 /* Test v2 CRL */
3900 info.dwVersion = CRL_V2;
3901 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3902 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3903 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3904 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3905 if (ret)
3906 {
3907 ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3908 v2CRL[1] + 2, size);
3909 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3910 LocalFree(buf);
3911 }
3912 /* v1 CRL with a name */
3913 info.dwVersion = CRL_V1;
3914 info.Issuer.cbData = sizeof(encodedCommonName);
3915 info.Issuer.pbData = (BYTE *)encodedCommonName;
3916 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3917 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3918 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3919 if (ret)
3920 {
3921 ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3922 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3923 LocalFree(buf);
3924 }
3925 if (0)
3926 {
3927 /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3928 info.cCRLEntry = 1;
3929 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3930 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3931 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3932 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3933 }
3934 /* now set an empty entry */
3935 info.cCRLEntry = 1;
3936 info.rgCRLEntry = &entry;
3937 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3938 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3939 if (ret)
3940 {
3941 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3942 "Wrong size %d\n", size);
3943 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3944 "Got unexpected value\n");
3945 LocalFree(buf);
3946 }
3947 /* an entry with a serial number */
3948 entry.SerialNumber.cbData = sizeof(serialNum);
3949 entry.SerialNumber.pbData = (BYTE *)serialNum;
3950 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3951 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3952 if (ret)
3953 {
3954 ok(size == sizeof(v1CRLWithIssuerAndEntry),
3955 "Wrong size %d\n", size);
3956 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3957 "Got unexpected value\n");
3958 LocalFree(buf);
3959 }
3960 /* an entry with an extension */
3961 entry.cExtension = 1;
3962 entry.rgExtension = &criticalExt;
3963 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3964 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3965 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3966 if (ret)
3967 {
3968 ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3969 ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3970 LocalFree(buf);
3971 }
3972 /* a CRL with an extension */
3973 entry.cExtension = 0;
3974 info.cExtension = 1;
3975 info.rgExtension = &criticalExt;
3976 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3977 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3978 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3979 if (ret)
3980 {
3981 ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3982 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3983 LocalFree(buf);
3984 }
3985 /* a v2 CRL with an extension, this time non-critical */
3986 info.dwVersion = CRL_V2;
3987 info.rgExtension = &nonCriticalExt;
3988 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3989 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3990 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3991 if (ret)
3992 {
3993 ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3994 ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3995 LocalFree(buf);
3996 }
3997 }
3998
3999 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
4000 0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
4001 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
4002 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
4003 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
4004 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
4005 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
4006 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
4007 0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
4008 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
4009 0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
4010 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
4011 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
4012 0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
4013 0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
4014 0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
4015 0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
4016 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
4017 0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
4018 0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
4019 0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
4020 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
4021 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
4022 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
4023 0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
4024 0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
4025 0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
4026 0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
4027 0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
4028 0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
4029 0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
4030 0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
4031 0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
4032 0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
4033 0xcd };
4034 static const BYTE verisignCRLWithLotsOfEntries[] = {
4035 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
4036 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
4037 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
4038 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
4039 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
4040 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
4041 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
4042 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
4043 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
4044 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
4045 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
4046 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
4047 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
4048 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
4049 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
4050 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
4051 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4052 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
4053 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
4054 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4055 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
4056 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
4057 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
4058 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
4059 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
4060 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
4061 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
4062 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
4063 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
4064 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
4065 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4066 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
4067 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
4068 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4069 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
4070 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
4071 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
4072 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
4073 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
4074 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
4075 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
4076 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
4077 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
4078 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
4079 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
4080 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
4081 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
4082 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
4083 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
4084 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
4085 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
4086 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
4087 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
4088 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
4089 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4090 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
4091 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
4092 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
4093 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
4094 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
4095 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
4096 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
4097 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
4098 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
4099 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
4100 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
4101 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
4102 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
4103 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
4104 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
4105 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
4106 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
4107 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
4108 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
4109 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
4110 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
4111 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
4112 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
4113 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
4114 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
4115 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
4116 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
4117 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4118 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
4119 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
4120 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
4121 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
4122 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
4123 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
4124 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
4125 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
4126 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
4127 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
4128 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
4129 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
4130 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
4131 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
4132 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
4133 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
4134 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
4135 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
4136 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
4137 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
4138 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
4139 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
4140 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
4141 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
4142 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
4143 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
4144 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
4145 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4146 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
4147 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
4148 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
4149 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
4150 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
4151 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
4152 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
4153 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
4154 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
4155 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
4156 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
4157 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
4158 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
4159 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4160 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
4161 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
4162 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
4163 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
4164 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
4165 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
4166 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
4167 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
4168 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
4169 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
4170 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
4171 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
4172 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
4173 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
4174 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
4175 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
4176 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
4177 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
4178 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
4179 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
4180 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
4181 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
4182 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
4183 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
4184 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
4185 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
4186 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
4187 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
4188 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
4189 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
4190 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
4191 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
4192 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
4193 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
4194 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
4195 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
4196 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
4197 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
4198 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
4199 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
4200 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
4201 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
4202 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
4203 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
4204 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
4205 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
4206 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
4207 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
4208 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
4209 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
4210 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
4211 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
4212 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
4213 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
4214 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
4215 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
4216 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
4217 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
4218 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
4219 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
4220 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
4221 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4222 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4223 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4224 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4225 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4226 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4227 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4228 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4229 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4230 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4231 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4232 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4233 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4234 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4235 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4236 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4237 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4238 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4239 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4240 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4241 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4242 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4243 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4244 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4245 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4246 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4247 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4248 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4249 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4250 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4251 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4252 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4253 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4254 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4255 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4256 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4257 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4258 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4259 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4260 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4261 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4262 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4263 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4264 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4265 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4266 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4267 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4268 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4269 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4270 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4271 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4272 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4273 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4274 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4275 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4276 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4277 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4278 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4279 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4280 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4281 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4282 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4283 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4284 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4285 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4286 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4287 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4288 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4289 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4290 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4291 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4292 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4293 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4294 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4295 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4296 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4297 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4298 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4299 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4300 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4301 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4302 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4303 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4304 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4305 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4306 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4307 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4308 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4309 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4310 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4311 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4312 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4313 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4314 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4315 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4316 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4317 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4318 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4319 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4320 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4321 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4322 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4323 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4324 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4325 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4326 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4327 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4328 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4329 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4330 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4331 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4332 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4333 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4334 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4335 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4336 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4337 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4338 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4339 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4340 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4341 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4342 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4343 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4344 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4345 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4346 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4347 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4348 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4349 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4350 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4351 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4352 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4353 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4354 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4355 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4356 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4357 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4358 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4359 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4360 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4361 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4362 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4363 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4364 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4365 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4366 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4367 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4368 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4369 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4370 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4371 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4372 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4373 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4374 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4375 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4376 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4377 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4378 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4379 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4380 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4381 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4382 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4383 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4384 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4385 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4386 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4387 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4388 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4389 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4390 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4391 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4392 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4393 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4394 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4395 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4396 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4397 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4398 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4399 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4400 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4401 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4402 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4403 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4404 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4405 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4406 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4407 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4408 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4409 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4410 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4411 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4412 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4413 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4414 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4415 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4416 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4417 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4418 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4419 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4420 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4421 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4422 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4423 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4424 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4425 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4426 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4427 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4428 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4429 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4430 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4431 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4432 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4433 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4434 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4435 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4436 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4437 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4438 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4439 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4440 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4441 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4442 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4443 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4444 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4445 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4446 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4447 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4448 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4449 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4450 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4451 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4452 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4453 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4454 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4455 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4456 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4457 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4458 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4459 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4460 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4461 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4462 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4463 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4464 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4465 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4466 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4467 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4468 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4469 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4470 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4471 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4472 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4473 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4474 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4475 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4476 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4477 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4478 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4479 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4480 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4481 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4482 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4483 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4484 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4485 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4486 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4487 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4488 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4489 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4490 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4491 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4492 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4493 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4494 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4495 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4496 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4497 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4498 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4499 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4500 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4501 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4502 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4503 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4504 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4505 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4506 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4507 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4508 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4509 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4510 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4511 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4512 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4513 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4514 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4515 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4516 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4517 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4518 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4519 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4520 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4521 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4522 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4523 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4524 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4525 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4526 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4527 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4528 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4529 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4530 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4531 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4532 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4533 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4534 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4535 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4536 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4537 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4538 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4539 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4540 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4541 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4542 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4543
4544 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4545 {
4546 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4547 BOOL ret;
4548 BYTE *buf = NULL;
4549 DWORD size = 0, i;
4550
4551 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4552 {
4553 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4554 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4555 &buf, &size);
4556 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4557 GetLastError() == OSS_DATA_ERROR /* Win9x */),
4558 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4559 GetLastError());
4560 }
4561 /* at a minimum, a CRL must contain an issuer: */
4562 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4563 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4564 &buf, &size);
4565 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4566 if (ret)
4567 {
4568 CRL_INFO *info = (CRL_INFO *)buf;
4569
4570 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4571 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4572 info->cCRLEntry);
4573 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4574 "Wrong issuer size %d\n", info->Issuer.cbData);
4575 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4576 "Unexpected issuer\n");
4577 LocalFree(buf);
4578 }
4579 /* check decoding with an empty CRL entry */
4580 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4581 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4582 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4583 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4584 GetLastError() == OSS_DATA_ERROR /* Win9x */ ||
4585 GetLastError() == CRYPT_E_BAD_ENCODE /* Win8 */),
4586 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4587 GetLastError());
4588 /* with a real CRL entry */
4589 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4590 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4591 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4592 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4593 if (ret)
4594 {
4595 CRL_INFO *info = (CRL_INFO *)buf;
4596 CRL_ENTRY *entry;
4597
4598 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4599 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4600 info->cCRLEntry);
4601 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4602 entry = info->rgCRLEntry;
4603 ok(entry->SerialNumber.cbData == 1,
4604 "Expected serial number size 1, got %d\n",
4605 entry->SerialNumber.cbData);
4606 ok(*entry->SerialNumber.pbData == *serialNum,
4607 "Expected serial number %d, got %d\n", *serialNum,
4608 *entry->SerialNumber.pbData);
4609 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4610 "Wrong issuer size %d\n", info->Issuer.cbData);
4611 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4612 "Unexpected issuer\n");
4613 LocalFree(buf);
4614 }
4615 /* a real CRL from verisign that has extensions */
4616 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4617 verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4618 NULL, &buf, &size);
4619 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4620 if (ret)
4621 {
4622 CRL_INFO *info = (CRL_INFO *)buf;
4623
4624 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4625 ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4626 info->cCRLEntry);
4627 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4628 ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4629 info->cExtension);
4630 LocalFree(buf);
4631 }
4632 /* another real CRL from verisign that has lots of entries */
4633 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4634 verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4635 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4636 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4637 if (ret)
4638 {
4639 CRL_INFO *info = (CRL_INFO *)buf;
4640
4641 ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4642 ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4643 info->cCRLEntry);
4644 ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4645 info->cExtension);
4646 LocalFree(buf);
4647 }
4648 /* and finally, with an extension */
4649 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4650 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4651 NULL, &buf, &size);
4652 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4653 if (ret)
4654 {
4655 CRL_INFO *info = (CRL_INFO *)buf;
4656 CRL_ENTRY *entry;
4657
4658 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4659 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4660 info->cCRLEntry);
4661 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4662 entry = info->rgCRLEntry;
4663 ok(entry->SerialNumber.cbData == 1,
4664 "Expected serial number size 1, got %d\n",
4665 entry->SerialNumber.cbData);
4666 ok(*entry->SerialNumber.pbData == *serialNum,
4667 "Expected serial number %d, got %d\n", *serialNum,
4668 *entry->SerialNumber.pbData);
4669 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4670 "Wrong issuer size %d\n", info->Issuer.cbData);
4671 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4672 "Unexpected issuer\n");
4673 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4674 info->cExtension);
4675 LocalFree(buf);
4676 }
4677 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4678 v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4679 NULL, &buf, &size);
4680 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4681 if (ret)
4682 {
4683 CRL_INFO *info = (CRL_INFO *)buf;
4684
4685 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4686 info->cExtension);
4687 LocalFree(buf);
4688 }
4689 }
4690
4691 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4692 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4693 static const BYTE encodedUsage[] = {
4694 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4695 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4696 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4697
4698 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4699 {
4700 BOOL ret;
4701 BYTE *buf = NULL;
4702 DWORD size = 0;
4703 CERT_ENHKEY_USAGE usage;
4704
4705 /* Test with empty usage */
4706 usage.cUsageIdentifier = 0;
4707 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4708 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4709 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4710 if (ret)
4711 {
4712 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4713 ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4714 LocalFree(buf);
4715 }
4716 /* Test with a few usages */
4717 usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4718 usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4719 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4720 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4721 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4722 if (ret)
4723 {
4724 ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4725 ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4726 LocalFree(buf);
4727 }
4728 }
4729
4730 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4731 {
4732 BOOL ret;
4733 LPBYTE buf = NULL;
4734 DWORD size = 0;
4735
4736 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4737 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4738 &buf, &size);
4739 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4740 if (ret)
4741 {
4742 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4743
4744 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4745 "Wrong size %d\n", size);
4746 ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4747 usage->cUsageIdentifier);
4748 LocalFree(buf);
4749 }
4750 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4751 encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4752 &buf, &size);
4753 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4754 if (ret)
4755 {
4756 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4757 DWORD i;
4758
4759 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4760 "Wrong size %d\n", size);
4761 ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4762 "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4763 for (i = 0; i < usage->cUsageIdentifier; i++)
4764 ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4765 "Expected OID %s, got %s\n", keyUsages[i],
4766 usage->rgpszUsageIdentifier[i]);
4767 LocalFree(buf);
4768 }
4769 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4770 encodedUsage, sizeof(encodedUsage), 0, NULL, NULL, &size);
4771 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4772 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
4773 if (buf)
4774 {
4775 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4776 encodedUsage, sizeof(encodedUsage), 0, NULL, buf, &size);
4777 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4778 HeapFree(GetProcessHeap(), 0, buf);
4779 }
4780 }
4781
4782 static BYTE keyId[] = { 1,2,3,4 };
4783 static const BYTE authorityKeyIdWithId[] = {
4784 0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4785 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4786 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4787 0x20,0x4c,0x61,0x6e,0x67,0x00 };
4788 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4789
4790 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4791 {
4792 CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4793 BOOL ret;
4794 BYTE *buf = NULL;
4795 DWORD size = 0;
4796
4797 /* Test with empty id */
4798 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4799 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4800 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4801 if (ret)
4802 {
4803 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4804 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4805 LocalFree(buf);
4806 }
4807 /* With just a key id */
4808 info.KeyId.cbData = sizeof(keyId);
4809 info.KeyId.pbData = keyId;
4810 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4811 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4812 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4813 if (ret)
4814 {
4815 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4816 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4817 LocalFree(buf);
4818 }
4819 /* With just an issuer */
4820 info.KeyId.cbData = 0;
4821 info.CertIssuer.cbData = sizeof(encodedCommonName);
4822 info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4823 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4824 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4825 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4826 if (ret)
4827 {
4828 ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4829 size);
4830 ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4831 LocalFree(buf);
4832 }
4833 /* With just a serial number */
4834 info.CertIssuer.cbData = 0;
4835 info.CertSerialNumber.cbData = sizeof(serialNum);
4836 info.CertSerialNumber.pbData = (BYTE *)serialNum;
4837 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4838 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4839 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4840 if (ret)
4841 {
4842 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4843 size);
4844 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4845 LocalFree(buf);
4846 }
4847 }
4848
4849 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4850 {
4851 BOOL ret;
4852 LPBYTE buf = NULL;
4853 DWORD size = 0;
4854
4855 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4856 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4857 &buf, &size);
4858 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4859 if (ret)
4860 {
4861 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4862
4863 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4864 size);
4865 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4866 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4867 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4868 LocalFree(buf);
4869 }
4870 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4871 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4872 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4873 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4874 if (ret)
4875 {
4876 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4877
4878 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4879 size);
4880 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4881 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4882 "Unexpected key id\n");
4883 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4884 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4885 LocalFree(buf);
4886 }
4887 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4888 authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4889 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4890 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4891 if (ret)
4892 {
4893 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4894
4895 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4896 size);
4897 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4898 ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4899 "Unexpected issuer len\n");
4900 ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4901 sizeof(encodedCommonName)), "Unexpected issuer\n");
4902 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4903 LocalFree(buf);
4904 }
4905 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4906 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4907 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4908 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4909 if (ret)
4910 {
4911 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4912
4913 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4914 size);
4915 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4916 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4917 ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4918 "Unexpected serial number len\n");
4919 ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4920 "Unexpected serial number\n");
4921 LocalFree(buf);
4922 }
4923 }
4924
4925 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4926 0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4927 0x6f,0x72,0x67 };
4928
4929 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4930 {
4931 CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4932 CERT_ALT_NAME_ENTRY entry = { 0 };
4933 BOOL ret;
4934 BYTE *buf = NULL;
4935 DWORD size = 0;
4936
4937 /* Test with empty id */
4938 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4939 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4940 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4941 if (ret)
4942 {
4943 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4944 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4945 LocalFree(buf);
4946 }
4947 /* With just a key id */
4948 info.KeyId.cbData = sizeof(keyId);
4949 info.KeyId.pbData = keyId;
4950 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4951 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4952 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4953 if (ret)
4954 {
4955 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4956 size);
4957 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4958 LocalFree(buf);
4959 }
4960 /* With a bogus issuer name */
4961 info.KeyId.cbData = 0;
4962 info.AuthorityCertIssuer.cAltEntry = 1;
4963 info.AuthorityCertIssuer.rgAltEntry = &entry;
4964 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4965 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4966 ok(!ret && GetLastError() == E_INVALIDARG,
4967 "Expected E_INVALIDARG, got %08x\n", GetLastError());
4968 /* With an issuer name */
4969 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4970 U(entry).pwszURL = (LPWSTR)url;
4971 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4972 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4973 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4974 if (ret)
4975 {
4976 ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4977 size);
4978 ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4979 "Unexpected value\n");
4980 LocalFree(buf);
4981 }
4982 /* With just a serial number */
4983 info.AuthorityCertIssuer.cAltEntry = 0;
4984 info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4985 info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4986 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4987 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4988 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4989 if (ret)
4990 {
4991 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4992 size);
4993 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4994 LocalFree(buf);
4995 }
4996 }
4997
4998 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4999 {
5000 BOOL ret;
5001 LPBYTE buf = NULL;
5002 DWORD size = 0;
5003
5004 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5005 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5006 &buf, &size);
5007 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5008 if (ret)
5009 {
5010 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5011
5012 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5013 size);
5014 ok(info->KeyId.cbData == 0, "Expected no key id\n");
5015 ok(info->AuthorityCertIssuer.cAltEntry == 0,
5016 "Expected no issuer name entries\n");
5017 ok(info->AuthorityCertSerialNumber.cbData == 0,
5018 "Expected no serial number\n");
5019 LocalFree(buf);
5020 }
5021 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5022 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
5023 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5024 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5025 if (ret)
5026 {
5027 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5028
5029 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5030 size);
5031 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
5032 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
5033 "Unexpected key id\n");
5034 ok(info->AuthorityCertIssuer.cAltEntry == 0,
5035 "Expected no issuer name entries\n");
5036 ok(info->AuthorityCertSerialNumber.cbData == 0,
5037 "Expected no serial number\n");
5038 LocalFree(buf);
5039 }
5040 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5041 authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
5042 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5043 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5044 if (ret)
5045 {
5046 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5047
5048 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5049 size);
5050 ok(info->KeyId.cbData == 0, "Expected no key id\n");
5051 ok(info->AuthorityCertIssuer.cAltEntry == 1,
5052 "Expected 1 issuer entry, got %d\n",
5053 info->AuthorityCertIssuer.cAltEntry);
5054 ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
5055 CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
5056 info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
5057 ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
5058 url), "Unexpected URL\n");
5059 ok(info->AuthorityCertSerialNumber.cbData == 0,
5060 "Expected no serial number\n");
5061 LocalFree(buf);
5062 }
5063 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5064 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
5065 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5066 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5067 if (ret)
5068 {
5069 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5070
5071 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5072 size);
5073 ok(info->KeyId.cbData == 0, "Expected no key id\n");
5074 ok(info->AuthorityCertIssuer.cAltEntry == 0,
5075 "Expected no issuer name entries\n");
5076 ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
5077 "Unexpected serial number len\n");
5078 ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
5079 sizeof(serialNum)), "Unexpected serial number\n");
5080 LocalFree(buf);
5081 }
5082 }
5083
5084 static const BYTE authorityInfoAccessWithUrl[] = {
5085 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5086 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5087 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
5088 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5089 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
5090 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5091
5092 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
5093 {
5094 static char oid1[] = "1.2.3";
5095 static char oid2[] = "1.5.6";
5096 BOOL ret;
5097 BYTE *buf = NULL;
5098 DWORD size = 0;
5099 CERT_ACCESS_DESCRIPTION accessDescription[2];
5100 CERT_AUTHORITY_INFO_ACCESS aia;
5101
5102 memset(accessDescription, 0, sizeof(accessDescription));
5103 aia.cAccDescr = 0;
5104 aia.rgAccDescr = NULL;
5105 /* Having no access descriptions is allowed */
5106 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5107 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5108 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5109 if (ret)
5110 {
5111 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5112 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5113 LocalFree(buf);
5114 buf = NULL;
5115 }
5116 /* It can't have an empty access method */
5117 aia.cAccDescr = 1;
5118 aia.rgAccDescr = accessDescription;
5119 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5120 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5121 ok(!ret && (GetLastError() == E_INVALIDARG ||
5122 GetLastError() == OSS_LIMITED /* Win9x */),
5123 "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5124 /* It can't have an empty location */
5125 accessDescription[0].pszAccessMethod = oid1;
5126 SetLastError(0xdeadbeef);
5127 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5128 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5129 ok(!ret && GetLastError() == E_INVALIDARG,
5130 "expected E_INVALIDARG, got %08x\n", GetLastError());
5131 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5132 U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5133 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5134 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5135 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5136 if (ret)
5137 {
5138 ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
5139 size);
5140 ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
5141 "unexpected value\n");
5142 LocalFree(buf);
5143 buf = NULL;
5144 }
5145 accessDescription[1].pszAccessMethod = oid2;
5146 accessDescription[1].AccessLocation.dwAltNameChoice =
5147 CERT_ALT_NAME_IP_ADDRESS;
5148 U(accessDescription[1].AccessLocation).IPAddress.cbData =
5149 sizeof(encodedIPAddr);
5150 U(accessDescription[1].AccessLocation).IPAddress.pbData =
5151 (LPBYTE)encodedIPAddr;
5152 aia.cAccDescr = 2;
5153 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5154 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5155 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5156 if (ret)
5157 {
5158 ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
5159 "unexpected size %d\n", size);
5160 ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
5161 "unexpected value\n");
5162 LocalFree(buf);
5163 buf = NULL;
5164 }
5165 }
5166
5167 static void compareAuthorityInfoAccess(LPCSTR header,
5168 const CERT_AUTHORITY_INFO_ACCESS *expected,
5169 const CERT_AUTHORITY_INFO_ACCESS *got)
5170 {
5171 DWORD i;
5172
5173 ok(expected->cAccDescr == got->cAccDescr,
5174 "%s: expected %d access descriptions, got %d\n", header,
5175 expected->cAccDescr, got->cAccDescr);
5176 for (i = 0; i < expected->cAccDescr; i++)
5177 {
5178 ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
5179 got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
5180 header, i, expected->rgAccDescr[i].pszAccessMethod,
5181 got->rgAccDescr[i].pszAccessMethod);
5182 compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
5183 &got->rgAccDescr[i].AccessLocation);
5184 }
5185 }
5186
5187 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
5188 {
5189 static char oid1[] = "1.2.3";
5190 static char oid2[] = "1.5.6";
5191 BOOL ret;
5192 LPBYTE buf = NULL;
5193 DWORD size = 0;
5194
5195 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5196 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5197 &buf, &size);
5198 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5199 if (ret)
5200 {
5201 CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
5202
5203 compareAuthorityInfoAccess("empty AIA", &aia,
5204 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5205 LocalFree(buf);
5206 buf = NULL;
5207 }
5208 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5209 authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
5210 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5211 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5212 if (ret)
5213 {
5214 CERT_ACCESS_DESCRIPTION accessDescription;
5215 CERT_AUTHORITY_INFO_ACCESS aia;
5216
5217 accessDescription.pszAccessMethod = oid1;
5218 accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5219 U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5220 aia.cAccDescr = 1;
5221 aia.rgAccDescr = &accessDescription;
5222 compareAuthorityInfoAccess("AIA with URL", &aia,
5223 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5224 LocalFree(buf);
5225 buf = NULL;
5226 }
5227 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5228 authorityInfoAccessWithUrlAndIPAddr,
5229 sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5230 NULL, &buf, &size);
5231 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5232 if (ret)
5233 {
5234 CERT_ACCESS_DESCRIPTION accessDescription[2];
5235 CERT_AUTHORITY_INFO_ACCESS aia;
5236
5237 accessDescription[0].pszAccessMethod = oid1;
5238 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5239 U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5240 accessDescription[1].pszAccessMethod = oid2;
5241 accessDescription[1].AccessLocation.dwAltNameChoice =
5242 CERT_ALT_NAME_IP_ADDRESS;
5243 U(accessDescription[1].AccessLocation).IPAddress.cbData =
5244 sizeof(encodedIPAddr);
5245 U(accessDescription[1].AccessLocation).IPAddress.pbData =
5246 (LPBYTE)encodedIPAddr;
5247 aia.cAccDescr = 2;
5248 aia.rgAccDescr = accessDescription;
5249 compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5250 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5251 LocalFree(buf);
5252 buf = NULL;
5253 }
5254 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5255 authorityInfoAccessWithUrlAndIPAddr,
5256 sizeof(authorityInfoAccessWithUrlAndIPAddr), 0, NULL, NULL, &size);
5257 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5258 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
5259 if (buf)
5260 {
5261 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5262 authorityInfoAccessWithUrlAndIPAddr,
5263 sizeof(authorityInfoAccessWithUrlAndIPAddr), 0, NULL, buf, &size);
5264 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5265 HeapFree(GetProcessHeap(), 0, buf);
5266 }
5267 }
5268
5269 static const BYTE emptyCTL[] = {
5270 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5271 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5272 static const BYTE emptyCTLWithVersion1[] = {
5273 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5274 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5275 static const BYTE ctlWithUsageIdentifier[] = {
5276 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5277 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5278 static const BYTE ctlWithListIdentifier[] = {
5279 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5280 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5281 static const BYTE ctlWithSequenceNumber[] = {
5282 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5283 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5284 static const BYTE ctlWithThisUpdate[] = {
5285 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5286 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5287 static const BYTE ctlWithThisAndNextUpdate[] = {
5288 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5289 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5290 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5291 static const BYTE ctlWithAlgId[] = {
5292 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5293 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5294 static const BYTE ctlWithBogusEntry[] = {
5295 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5296 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5297 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5298 static const BYTE ctlWithOneEntry[] = {
5299 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5300 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5301 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5302 static const BYTE ctlWithTwoEntries[] = {
5303 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5304 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5305 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5306 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5307 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5308
5309 static void test_encodeCTL(DWORD dwEncoding)
5310 {
5311 static char oid1[] = "1.2.3";
5312 static char oid2[] = "1.5.6";
5313 char *pOid1 = oid1;
5314 BOOL ret;
5315 BYTE *buf = NULL;
5316 DWORD size = 0;
5317 CTL_INFO info;
5318 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5319 CTL_ENTRY ctlEntry[2];
5320 CRYPT_ATTRIBUTE attr1, attr2;
5321 CRYPT_ATTR_BLOB value1, value2;
5322
5323 memset(&info, 0, sizeof(info));
5324 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5325 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5326 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5327 if (ret)
5328 {
5329 ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5330 ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5331 LocalFree(buf);
5332 buf = NULL;
5333 }
5334 info.dwVersion = 1;
5335 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5336 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5337 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5338 if (ret)
5339 {
5340 ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5341 ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5342 LocalFree(buf);
5343 buf = NULL;
5344 }
5345 info.dwVersion = 0;
5346 info.SubjectUsage.cUsageIdentifier = 1;
5347 info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5348 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5349 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5350 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5351 if (ret)
5352 {
5353 ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5354 size);
5355 ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5356 LocalFree(buf);
5357 buf = NULL;
5358 }
5359 info.SubjectUsage.cUsageIdentifier = 0;
5360 info.ListIdentifier.cbData = sizeof(serialNum);
5361 info.ListIdentifier.pbData = (LPBYTE)serialNum;
5362 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5363 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5364 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5365 if (ret)
5366 {
5367 ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5368 ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5369 LocalFree(buf);
5370 buf = NULL;
5371 }
5372 info.ListIdentifier.cbData = 0;
5373 info.SequenceNumber.cbData = sizeof(serialNum);
5374 info.SequenceNumber.pbData = (LPBYTE)serialNum;
5375 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5376 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5377 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5378 if (ret)
5379 {
5380 ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5381 size);
5382 ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5383 LocalFree(buf);
5384 buf = NULL;
5385 }
5386 info.SequenceNumber.cbData = 0;
5387 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5388 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5389 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5390 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5391 if (ret)
5392 {
5393 ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5394 ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5395 LocalFree(buf);
5396 buf = NULL;
5397 }
5398 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5399 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5400 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5401 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5402 if (ret)
5403 {
5404 ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5405 size);
5406 ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5407 LocalFree(buf);
5408 buf = NULL;
5409 }
5410 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5411 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5412 info.SubjectAlgorithm.pszObjId = oid2;
5413 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5414 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5415 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5416 if (ret)
5417 {
5418 ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5419 ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5420 LocalFree(buf);
5421 buf = NULL;
5422 }
5423 /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5424 * (see tests below) but it'll encode fine.
5425 */
5426 info.SubjectAlgorithm.pszObjId = NULL;
5427 value1.cbData = sizeof(serialNum);
5428 value1.pbData = (LPBYTE)serialNum;
5429 attr1.pszObjId = oid1;
5430 attr1.cValue = 1;
5431 attr1.rgValue = &value1;
5432 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5433 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5434 ctlEntry[0].cAttribute = 1;
5435 ctlEntry[0].rgAttribute = &attr1;
5436 info.cCTLEntry = 1;
5437 info.rgCTLEntry = ctlEntry;
5438 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5439 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5440 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5441 if (ret)
5442 {
5443 ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5444 ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5445 LocalFree(buf);
5446 buf = NULL;
5447 }
5448 value1.cbData = sizeof(emptySequence);
5449 value1.pbData = (LPBYTE)emptySequence;
5450 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5451 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5452 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5453 if (ret)
5454 {
5455 ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5456 ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5457 LocalFree(buf);
5458 buf = NULL;
5459 }
5460 value2.cbData = sizeof(encodedIPAddr);
5461 value2.pbData = (LPBYTE)encodedIPAddr;
5462 attr2.pszObjId = oid2;
5463 attr2.cValue = 1;
5464 attr2.rgValue = &value2;
5465 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5466 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5467 ctlEntry[1].cAttribute = 1;
5468 ctlEntry[1].rgAttribute = &attr2;
5469 info.cCTLEntry = 2;
5470 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5471 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5472 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5473 if (ret)
5474 {
5475 ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5476 ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5477 LocalFree(buf);
5478 buf = NULL;
5479 }
5480 }
5481
5482 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5483 const CTL_INFO *got)
5484 {
5485 DWORD i, j, k;
5486
5487 ok(expected->dwVersion == got->dwVersion,
5488 "%s: expected version %d, got %d\n", header, expected->dwVersion,
5489 got->dwVersion);
5490 ok(expected->SubjectUsage.cUsageIdentifier ==
5491 got->SubjectUsage.cUsageIdentifier,
5492 "%s: expected %d usage identifiers, got %d\n", header,
5493 expected->SubjectUsage.cUsageIdentifier,
5494 got->SubjectUsage.cUsageIdentifier);
5495 for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5496 ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5497 got->SubjectUsage.rgpszUsageIdentifier[i]),
5498 "%s[%d]: expected %s, got %s\n", header, i,
5499 expected->SubjectUsage.rgpszUsageIdentifier[i],
5500 got->SubjectUsage.rgpszUsageIdentifier[i]);
5501 ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5502 "%s: expected list identifier of %d bytes, got %d\n", header,
5503 expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5504 if (expected->ListIdentifier.cbData)
5505 ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5506 expected->ListIdentifier.cbData),
5507 "%s: unexpected list identifier value\n", header);
5508 ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5509 "%s: expected sequence number of %d bytes, got %d\n", header,
5510 expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5511 if (expected->SequenceNumber.cbData)
5512 ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5513 expected->SequenceNumber.cbData),
5514 "%s: unexpected sequence number value\n", header);
5515 ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5516 "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5517 expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5518 got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5519 ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5520 "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5521 expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5522 got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5523 if (expected->SubjectAlgorithm.pszObjId &&
5524 *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5525 ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5526 expected->SubjectAlgorithm.pszObjId);
5527 if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5528 ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5529 got->SubjectAlgorithm.pszObjId),
5530 "%s: expected subject algorithm %s, got %s\n", header,
5531 expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5532 ok(expected->SubjectAlgorithm.Parameters.cbData ==
5533 got->SubjectAlgorithm.Parameters.cbData,
5534 "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5535 expected->SubjectAlgorithm.Parameters.cbData,
5536 got->SubjectAlgorithm.Parameters.cbData);
5537 if (expected->SubjectAlgorithm.Parameters.cbData)
5538 ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5539 got->SubjectAlgorithm.Parameters.pbData,
5540 expected->SubjectAlgorithm.Parameters.cbData),
5541 "%s: unexpected subject algorithm parameter value\n", header);
5542 ok(expected->cCTLEntry == got->cCTLEntry,
5543 "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5544 got->cCTLEntry);
5545 for (i = 0; i < expected->cCTLEntry; i++)
5546 {
5547 ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5548 got->rgCTLEntry[i].SubjectIdentifier.cbData,
5549 "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5550 header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5551 got->rgCTLEntry[i].SubjectIdentifier.cbData);
5552 if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5553 ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5554 got->rgCTLEntry[i].SubjectIdentifier.pbData,
5555 expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5556 "%s[%d]: unexpected subject identifier value\n",
5557 header, i);
5558 for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5559 {
5560 ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5561 got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5562 "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5563 expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5564 got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5565 for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5566 {
5567 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5568 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5569 "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5570 header, i, j, k,
5571 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5572 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5573 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5574 ok(!memcmp(
5575 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5576 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5577 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5578 "%s[%d][%d][%d]: unexpected value\n",
5579 header, i, j, k);
5580 }
5581 }
5582 }
5583 ok(expected->cExtension == got->cExtension,
5584 "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5585 got->cExtension);
5586 for (i = 0; i < expected->cExtension; i++)
5587 {
5588 ok(!strcmp(expected->rgExtension[i].pszObjId,
5589 got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5590 header, i, expected->rgExtension[i].pszObjId,
5591 got->rgExtension[i].pszObjId);
5592 ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5593 "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5594 expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5595 ok(expected->rgExtension[i].Value.cbData ==
5596 got->rgExtension[i].Value.cbData,
5597 "%s[%d]: expected extension value to have %d bytes, got %d\n",
5598 header, i, expected->rgExtension[i].Value.cbData,
5599 got->rgExtension[i].Value.cbData);
5600 if (expected->rgExtension[i].Value.cbData)
5601 ok(!memcmp(expected->rgExtension[i].Value.pbData,
5602 got->rgExtension[i].Value.pbData,
5603 expected->rgExtension[i].Value.cbData),
5604 "%s[%d]: unexpected extension value\n", header, i);
5605 }
5606 }
5607
5608 static const BYTE signedCTL[] = {
5609 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5610 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5611 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5612 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5613 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5614 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5615 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5616 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5617 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5618 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5619 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5620 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5621 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5622 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5623 static const BYTE signedCTLWithCTLInnerContent[] = {
5624 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5625 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5626 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5627 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5628 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5629 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5630 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5631 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5632 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5633 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5634 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5635 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5636 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5637 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5638 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5639 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5640 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5641 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5642 0x57,0x6c,0x0b,0x47,0xb8 };
5643
5644 static void test_decodeCTL(DWORD dwEncoding)
5645 {
5646 static char oid1[] = "1.2.3";
5647 static char oid2[] = "1.5.6";
5648 static BYTE nullData[] = { 5,0 };
5649 char *pOid1 = oid1;
5650 BOOL ret;
5651 BYTE *buf = NULL;
5652 DWORD size = 0;
5653 CTL_INFO info;
5654 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5655 CTL_ENTRY ctlEntry[2];
5656 CRYPT_ATTRIBUTE attr1, attr2;
5657 CRYPT_ATTR_BLOB value1, value2;
5658
5659 memset(&info, 0, sizeof(info));
5660 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5661 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5662 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5663 if (ret)
5664 {
5665 compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5666 LocalFree(buf);
5667 buf = NULL;
5668 }
5669 info.dwVersion = 1;
5670 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5671 sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5672 &size);
5673 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5674 if (ret)
5675 {
5676 compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5677 LocalFree(buf);
5678 buf = NULL;
5679 }
5680 info.dwVersion = 0;
5681 info.SubjectUsage.cUsageIdentifier = 1;
5682 info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5683 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5684 sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5685 &buf, &size);
5686 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5687 if (ret)
5688 {
5689 compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5690 LocalFree(buf);
5691 buf = NULL;
5692 }
5693 info.SubjectUsage.cUsageIdentifier = 0;
5694 info.ListIdentifier.cbData = sizeof(serialNum);
5695 info.ListIdentifier.pbData = (LPBYTE)serialNum;
5696 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5697 sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5698 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5699 if (ret)
5700 {
5701 compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5702 LocalFree(buf);
5703 buf = NULL;
5704 }
5705 info.ListIdentifier.cbData = 0;
5706 info.SequenceNumber.cbData = sizeof(serialNum);
5707 info.SequenceNumber.pbData = (LPBYTE)serialNum;
5708 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5709 sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5710 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5711 if (ret)
5712 {
5713 compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5714 LocalFree(buf);
5715 buf = NULL;
5716 }
5717 info.SequenceNumber.cbData = 0;
5718 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5719 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5720 sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5721 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5722 if (ret)
5723 {
5724 compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5725 LocalFree(buf);
5726 buf = NULL;
5727 }
5728 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5729 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5730 sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5731 &buf, &size);
5732 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5733 if (ret)
5734 {
5735 compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5736 LocalFree(buf);
5737 buf = NULL;
5738 }
5739 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5740 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5741 info.SubjectAlgorithm.pszObjId = oid2;
5742 info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5743 info.SubjectAlgorithm.Parameters.pbData = nullData;
5744 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5745 sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5746 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5747 if (ret)
5748 {
5749 compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5750 LocalFree(buf);
5751 buf = NULL;
5752 }
5753 SetLastError(0xdeadbeef);
5754 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5755 sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5756 ok(!ret &&
5757 (GetLastError() == CRYPT_E_ASN1_EOD ||
5758 GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5759 GetLastError() == OSS_MORE_INPUT), /* Win9x */
5760 "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5761 GetLastError());
5762 info.SubjectAlgorithm.Parameters.cbData = 0;
5763 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5764 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5765 info.SubjectAlgorithm.pszObjId = NULL;
5766 value1.cbData = sizeof(emptySequence);
5767 value1.pbData = (LPBYTE)emptySequence;
5768 attr1.pszObjId = oid1;
5769 attr1.cValue = 1;
5770 attr1.rgValue = &value1;
5771 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5772 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5773 ctlEntry[0].cAttribute = 1;
5774 ctlEntry[0].rgAttribute = &attr1;
5775 info.cCTLEntry = 1;
5776 info.rgCTLEntry = ctlEntry;
5777 SetLastError(0xdeadbeef);
5778 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5779 sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5780 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5781 if (ret)
5782 {
5783 compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5784 LocalFree(buf);
5785 buf = NULL;
5786 }
5787 value2.cbData = sizeof(encodedIPAddr);
5788 value2.pbData = (LPBYTE)encodedIPAddr;
5789 attr2.pszObjId = oid2;
5790 attr2.cValue = 1;
5791 attr2.rgValue = &value2;
5792 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5793 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5794 ctlEntry[1].cAttribute = 1;
5795 ctlEntry[1].rgAttribute = &attr2;
5796 info.cCTLEntry = 2;
5797 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5798 sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5799 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5800 if (ret)
5801 {
5802 compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5803 LocalFree(buf);
5804 buf = NULL;
5805 }
5806 /* A signed CTL isn't decodable, even if the inner content is a CTL */
5807 SetLastError(0xdeadbeef);
5808 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5809 sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5810 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5811 GetLastError() == OSS_DATA_ERROR /* Win9x */),
5812 "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5813 GetLastError());
5814 SetLastError(0xdeadbeef);
5815 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5816 signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5817 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5818 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5819 GetLastError() == OSS_DATA_ERROR /* Win9x */),
5820 "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5821 GetLastError());
5822 }
5823
5824 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5825 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5826 0x03,0,0,0,0,0,0 };
5827 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5828 0xa0,0x01,0x01 };
5829 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5830 0x03,0x02,0x01,0x01 };
5831 static BYTE bogusDER[] = { 1 };
5832
5833 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5834 {
5835 BOOL ret;
5836 BYTE *buf = NULL;
5837 DWORD size = 0;
5838 CRYPT_CONTENT_INFO info = { 0 };
5839 char oid1[] = "1.2.3";
5840
5841 if (0)
5842 {
5843 /* Crashes on win9x */
5844 SetLastError(0xdeadbeef);
5845 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5846 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5847 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5848 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5849 }
5850 SetLastError(0xdeadbeef);
5851 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5852 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5853 ok(!ret && (GetLastError() == E_INVALIDARG ||
5854 GetLastError() == OSS_LIMITED /* Win9x */),
5855 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5856 info.pszObjId = oid1;
5857 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5858 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5859 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5860 if (ret)
5861 {
5862 ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5863 ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5864 LocalFree(buf);
5865 }
5866 info.Content.pbData = bogusDER;
5867 info.Content.cbData = sizeof(bogusDER);
5868 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5869 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5870 ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5871 if (ret)
5872 {
5873 ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5874 ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5875 LocalFree(buf);
5876 }
5877 info.Content.pbData = (BYTE *)ints[0].encoded;
5878 info.Content.cbData = ints[0].encoded[1] + 2;
5879 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5880 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5881 if (ret)
5882 {
5883 ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5884 ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5885 LocalFree(buf);
5886 }
5887 }
5888
5889 static const BYTE indefiniteSignedPKCSContent[] = {
5890 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5891 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5892 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5893 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5894 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5895 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5896 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5897 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5898 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5899 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5900 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5901 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5902 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5903 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5904 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5905 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5906 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5907 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5908 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5909 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5910 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5911 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5912 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5913 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5914 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5915 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5916 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5917 0x00,0x00,0x00,0x00,0x00,0x00 };
5918
5919 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5920 {
5921 BOOL ret;
5922 LPBYTE buf = NULL;
5923 DWORD size = 0;
5924 CRYPT_CONTENT_INFO *info;
5925
5926 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5927 emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5928 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5929 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5930 if (ret)
5931 {
5932 info = (CRYPT_CONTENT_INFO *)buf;
5933
5934 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5935 info->pszObjId);
5936 ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5937 info->Content.cbData);
5938 LocalFree(buf);
5939 }
5940 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5941 emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5942 0, NULL, NULL, &size);
5943 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5944 SetLastError(0xdeadbeef);
5945 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5946 bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5947 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5948 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5949 * I doubt an app depends on that.
5950 */
5951 ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5952 GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5953 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5954 GetLastError());
5955 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5956 intPKCSContentInfo, sizeof(intPKCSContentInfo),
5957 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5958 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5959 if (ret)
5960 {
5961 info = (CRYPT_CONTENT_INFO *)buf;
5962
5963 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5964 info->pszObjId);
5965 ok(info->Content.cbData == ints[0].encoded[1] + 2,
5966 "Unexpected size %d\n", info->Content.cbData);
5967 ok(!memcmp(info->Content.pbData, ints[0].encoded,
5968 info->Content.cbData), "Unexpected value\n");
5969 LocalFree(buf);
5970 }
5971 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5972 indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5973 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5974 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5975 if (ret)
5976 {
5977 info = (CRYPT_CONTENT_INFO *)buf;
5978
5979 ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5980 "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5981 ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5982 info->Content.cbData);
5983 LocalFree(buf);
5984 }
5985 }
5986
5987 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5988 0x00 };
5989 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5990 0x01 };
5991 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5992 0x02,0x01,0x01 };
5993
5994 static void test_encodePKCSAttribute(DWORD dwEncoding)
5995 {
5996 CRYPT_ATTRIBUTE attr = { 0 };
5997 BOOL ret;
5998 LPBYTE buf = NULL;
5999 DWORD size = 0;
6000 CRYPT_ATTR_BLOB blob;
6001 char oid[] = "1.2.3";
6002
6003 if (0)
6004 {
6005 /* Crashes on win9x */
6006 SetLastError(0xdeadbeef);
6007 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
6008 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6009 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
6010 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
6011 }
6012 SetLastError(0xdeadbeef);
6013 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6014 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6015 ok(!ret && (GetLastError() == E_INVALIDARG ||
6016 GetLastError() == OSS_LIMITED /* Win9x */),
6017 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
6018 attr.pszObjId = oid;
6019 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6020 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6021 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6022 if (ret)
6023 {
6024 ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
6025 ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
6026 LocalFree(buf);
6027 }
6028 blob.cbData = sizeof(bogusDER);
6029 blob.pbData = bogusDER;
6030 attr.cValue = 1;
6031 attr.rgValue = &blob;
6032 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6033 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6034 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6035 if (ret)
6036 {
6037 ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
6038 ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
6039 LocalFree(buf);
6040 }
6041 blob.pbData = (BYTE *)ints[0].encoded;
6042 blob.cbData = ints[0].encoded[1] + 2;
6043 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6044 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6045 if (ret)
6046 {
6047 ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
6048 ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
6049 LocalFree(buf);
6050 }
6051 }
6052
6053 static void test_decodePKCSAttribute(DWORD dwEncoding)
6054 {
6055 BOOL ret;
6056 LPBYTE buf = NULL;
6057 DWORD size = 0;
6058 CRYPT_ATTRIBUTE *attr;
6059
6060 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6061 emptyPKCSAttr, sizeof(emptyPKCSAttr),
6062 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6063 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6064 if (ret)
6065 {
6066 attr = (CRYPT_ATTRIBUTE *)buf;
6067
6068 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6069 attr->pszObjId);
6070 ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
6071 LocalFree(buf);
6072 }
6073 SetLastError(0xdeadbeef);
6074 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6075 bogusPKCSAttr, sizeof(bogusPKCSAttr),
6076 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6077 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
6078 * I doubt an app depends on that.
6079 */
6080 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
6081 GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6082 GetLastError() == OSS_MORE_INPUT /* Win9x */),
6083 "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
6084 GetLastError());
6085 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6086 intPKCSAttr, sizeof(intPKCSAttr),
6087 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6088 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6089 if (ret)
6090 {
6091 attr = (CRYPT_ATTRIBUTE *)buf;
6092
6093 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6094 attr->pszObjId);
6095 ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
6096 ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
6097 "Unexpected size %d\n", attr->rgValue[0].cbData);
6098 ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
6099 attr->rgValue[0].cbData), "Unexpected value\n");
6100 LocalFree(buf);
6101 }
6102 }
6103
6104 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
6105 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
6106 0x2a,0x03,0x31,0x00 };
6107 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
6108 0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
6109
6110 static void test_encodePKCSAttributes(DWORD dwEncoding)
6111 {
6112 CRYPT_ATTRIBUTES attributes = { 0 };
6113 CRYPT_ATTRIBUTE attr[2] = { { 0 } };
6114 CRYPT_ATTR_BLOB blob;
6115 BOOL ret;
6116 LPBYTE buf = NULL;
6117 DWORD size = 0;
6118 char oid1[] = "1.2.3", oid2[] = "1.5.6";
6119
6120 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6121 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6122 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6123 if (ret)
6124 {
6125 ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
6126 ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
6127 LocalFree(buf);
6128 }
6129 attributes.cAttr = 1;
6130 attributes.rgAttr = attr;
6131 SetLastError(0xdeadbeef);
6132 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6133 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6134 ok(!ret && (GetLastError() == E_INVALIDARG ||
6135 GetLastError() == OSS_LIMITED /* Win9x */),
6136 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6137 attr[0].pszObjId = oid1;
6138 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6139 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6140 if (ret)
6141 {
6142 ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
6143 ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
6144 LocalFree(buf);
6145 }
6146 attr[1].pszObjId = oid2;
6147 attr[1].cValue = 1;
6148 attr[1].rgValue = &blob;
6149 blob.pbData = (BYTE *)ints[0].encoded;
6150 blob.cbData = ints[0].encoded[1] + 2;
6151 attributes.cAttr = 2;
6152 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6153 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6154 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6155 if (ret)
6156 {
6157 ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
6158 ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
6159 LocalFree(buf);
6160 }
6161 }
6162
6163 static void test_decodePKCSAttributes(DWORD dwEncoding)
6164 {
6165 BOOL ret;
6166 LPBYTE buf = NULL;
6167 DWORD size = 0;
6168 CRYPT_ATTRIBUTES *attributes;
6169
6170 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6171 emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
6172 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6173 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6174 if (ret)
6175 {
6176 attributes = (CRYPT_ATTRIBUTES *)buf;
6177 ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
6178 attributes->cAttr);
6179 LocalFree(buf);
6180 }
6181 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6182 singlePKCSAttributes, sizeof(singlePKCSAttributes),
6183 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6184 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6185 if (ret)
6186 {
6187 attributes = (CRYPT_ATTRIBUTES *)buf;
6188 ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
6189 attributes->cAttr);
6190 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6191 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6192 ok(attributes->rgAttr[0].cValue == 0,
6193 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6194 LocalFree(buf);
6195 }
6196 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6197 doublePKCSAttributes, sizeof(doublePKCSAttributes),
6198 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6199 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6200 if (ret)
6201 {
6202 attributes = (CRYPT_ATTRIBUTES *)buf;
6203 ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
6204 attributes->cAttr);
6205 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6206 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6207 ok(attributes->rgAttr[0].cValue == 0,
6208 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6209 ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
6210 "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
6211 ok(attributes->rgAttr[1].cValue == 1,
6212 "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
6213 ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
6214 "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
6215 ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
6216 attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
6217 LocalFree(buf);
6218 }
6219 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6220 doublePKCSAttributes, sizeof(doublePKCSAttributes), 0, NULL, NULL, &size);
6221 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6222 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
6223 if (buf)
6224 {
6225 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6226 doublePKCSAttributes, sizeof(doublePKCSAttributes), 0, NULL, buf, &size);
6227 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6228 HeapFree(GetProcessHeap(), 0, buf);
6229 }
6230 }
6231
6232 static const BYTE singleCapability[] = {
6233 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
6234 static const BYTE twoCapabilities[] = {
6235 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
6236 static const BYTE singleCapabilitywithNULL[] = {
6237 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
6238
6239 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
6240 {
6241 static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6242 BOOL ret;
6243 LPBYTE buf = NULL;
6244 DWORD size = 0;
6245 CRYPT_SMIME_CAPABILITY capability[2];
6246 CRYPT_SMIME_CAPABILITIES capabilities;
6247
6248 /* An empty capabilities is allowed */
6249 capabilities.cCapability = 0;
6250 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6251 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6252 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6253 if (ret)
6254 {
6255 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6256 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6257 LocalFree(buf);
6258 }
6259 /* A non-empty capabilities with an empty capability (lacking an OID) is
6260 * not allowed
6261 */
6262 capability[0].pszObjId = NULL;
6263 capability[0].Parameters.cbData = 0;
6264 capabilities.cCapability = 1;
6265 capabilities.rgCapability = capability;
6266 SetLastError(0xdeadbeef);
6267 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6268 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6269 ok(!ret && (GetLastError() == E_INVALIDARG ||
6270 GetLastError() == OSS_LIMITED /* Win9x */),
6271 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6272 capability[0].pszObjId = oid1;
6273 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6274 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6275 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6276 if (ret)
6277 {
6278 ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6279 ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6280 LocalFree(buf);
6281 }
6282 capability[1].pszObjId = oid2;
6283 capability[1].Parameters.cbData = 0;
6284 capabilities.cCapability = 2;
6285 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6286 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6287 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6288 if (ret)
6289 {
6290 ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6291 ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6292 LocalFree(buf);
6293 }
6294 }
6295
6296 static void compareSMimeCapabilities(LPCSTR header,
6297 const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6298 {
6299 DWORD i;
6300
6301 ok(got->cCapability == expected->cCapability,
6302 "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6303 got->cCapability);
6304 for (i = 0; i < expected->cCapability; i++)
6305 {
6306 ok(!strcmp(expected->rgCapability[i].pszObjId,
6307 got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6308 header, i, expected->rgCapability[i].pszObjId,
6309 got->rgCapability[i].pszObjId);
6310 ok(expected->rgCapability[i].Parameters.cbData ==
6311 got->rgCapability[i].Parameters.cbData,
6312 "%s[%d]: expected %d bytes, got %d\n", header, i,
6313 expected->rgCapability[i].Parameters.cbData,
6314 got->rgCapability[i].Parameters.cbData);
6315 if (expected->rgCapability[i].Parameters.cbData)
6316 ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6317 got->rgCapability[i].Parameters.pbData,
6318 expected->rgCapability[i].Parameters.cbData),
6319 "%s[%d]: unexpected value\n", header, i);
6320 }
6321 }
6322
6323 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6324 {
6325 static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6326 BOOL ret;
6327 DWORD size = 0;
6328 CRYPT_SMIME_CAPABILITY capability[2];
6329 CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6330
6331 SetLastError(0xdeadbeef);
6332 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6333 emptySequence, sizeof(emptySequence),
6334 CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6335 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6336 if (ret)
6337 {
6338 capabilities.cCapability = 0;
6339 compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6340 LocalFree(ptr);
6341 }
6342 SetLastError(0xdeadbeef);
6343 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6344 singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6345 &ptr, &size);
6346 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6347 if (ret)
6348 {
6349 capability[0].pszObjId = oid1;
6350 capability[0].Parameters.cbData = 0;
6351 capabilities.cCapability = 1;
6352 capabilities.rgCapability = capability;
6353 compareSMimeCapabilities("single capability", &capabilities, ptr);
6354 LocalFree(ptr);
6355 }
6356 SetLastError(0xdeadbeef);
6357 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6358 singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6359 CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6360 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6361 if (ret)
6362 {
6363 BYTE NULLparam[] = {0x05, 0x00};
6364 capability[0].pszObjId = oid1;
6365 capability[0].Parameters.cbData = 2;
6366 capability[0].Parameters.pbData = NULLparam;
6367 capabilities.cCapability = 1;
6368 capabilities.rgCapability = capability;
6369 compareSMimeCapabilities("single capability with NULL", &capabilities,
6370 ptr);
6371 LocalFree(ptr);
6372 }
6373 SetLastError(0xdeadbeef);
6374 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6375 twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6376 &ptr, &size);
6377 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6378 if (ret)
6379 {
6380 capability[0].Parameters.cbData = 0;
6381 capability[1].pszObjId = oid2;
6382 capability[1].Parameters.cbData = 0;
6383 capabilities.cCapability = 2;
6384 compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6385 LocalFree(ptr);
6386 }
6387 SetLastError(0xdeadbeef);
6388 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6389 twoCapabilities, sizeof(twoCapabilities), 0, NULL, NULL, &size);
6390 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6391 ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
6392 if (ptr)
6393 {
6394 SetLastError(0xdeadbeef);
6395 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6396 twoCapabilities, sizeof(twoCapabilities), 0, NULL, ptr, &size);
6397 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6398 HeapFree(GetProcessHeap(), 0, ptr);
6399 }
6400 }
6401
6402 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6403 0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6404 0x67 };
6405 static const BYTE minimalPKCSSigner[] = {
6406 0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6407 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6408 0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6409 static const BYTE PKCSSignerWithSerial[] = {
6410 0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6411 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6412 0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6413 0x00 };
6414 static const BYTE PKCSSignerWithHashAlgo[] = {
6415 0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6416 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6417 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6418 0x00,0x04,0x00 };
6419 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6420 0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6421 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6422 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6423 0x06,0x05,0x00,0x04,0x00 };
6424 static const BYTE PKCSSignerWithHash[] = {
6425 0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6426 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6427 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6428 0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6429 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6430 static const BYTE PKCSSignerWithAuthAttr[] = {
6431 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6432 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6433 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6434 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6435 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6436 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6437 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6438
6439 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6440 {
6441 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6442 BOOL ret;
6443 LPBYTE buf = NULL;
6444 DWORD size = 0;
6445 CMSG_SIGNER_INFO info = { 0 };
6446 char oid_common_name[] = szOID_COMMON_NAME;
6447 CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6448 (LPBYTE)encodedCommonName };
6449 CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6450
6451 SetLastError(0xdeadbeef);
6452 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6453 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6454 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6455 {
6456 skip("no PKCS7_SIGNER_INFO encode support\n");
6457 return;
6458 }
6459 ok(!ret && (GetLastError() == E_INVALIDARG ||
6460 GetLastError() == OSS_LIMITED /* Win9x */),
6461 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6462 /* To be encoded, a signer must have an issuer at least, and the encoding
6463 * must include PKCS_7_ASN_ENCODING. (That isn't enough to be decoded,
6464 * see decoding tests.)
6465 */
6466 info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6467 info.Issuer.pbData = encodedCommonNameNoNull;
6468 SetLastError(0xdeadbeef);
6469 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6470 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6471 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6472 ok(!ret && GetLastError() == E_INVALIDARG,
6473 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6474 else
6475 {
6476 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6477 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6478 if (ret)
6479 {
6480 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6481 if (size == sizeof(minimalPKCSSigner))
6482 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6483 else
6484 ok(0, "Unexpected value\n");
6485 LocalFree(buf);
6486 }
6487 }
6488 info.SerialNumber.cbData = sizeof(serialNum);
6489 info.SerialNumber.pbData = (BYTE *)serialNum;
6490 SetLastError(0xdeadbeef);
6491 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6492 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6493 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6494 ok(!ret && GetLastError() == E_INVALIDARG,
6495 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6496 else
6497 {
6498 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6499 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6500 if (ret)
6501 {
6502 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6503 size);
6504 if (size == sizeof(PKCSSignerWithSerial))
6505 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6506 "Unexpected value\n");
6507 else
6508 ok(0, "Unexpected value\n");
6509 LocalFree(buf);
6510 }
6511 }
6512 info.HashAlgorithm.pszObjId = oid1;
6513 SetLastError(0xdeadbeef);
6514 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6515 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6516 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6517 ok(!ret && GetLastError() == E_INVALIDARG,
6518 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6519 else
6520 {
6521 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6522 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6523 if (ret)
6524 {
6525 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6526 size);
6527 if (size == sizeof(PKCSSignerWithHashAlgo))
6528 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6529 "Unexpected value\n");
6530 else
6531 ok(0, "Unexpected value\n");
6532 LocalFree(buf);
6533 }
6534 }
6535 info.HashEncryptionAlgorithm.pszObjId = oid2;
6536 SetLastError(0xdeadbeef);
6537 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6538 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6539 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6540 ok(!ret && GetLastError() == E_INVALIDARG,
6541 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6542 else
6543 {
6544 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6545 if (ret)
6546 {
6547 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6548 "Unexpected size %d\n", size);
6549 if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6550 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6551 "Unexpected value\n");
6552 else
6553 ok(0, "Unexpected value\n");
6554 LocalFree(buf);
6555 }
6556 }
6557 info.EncryptedHash.cbData = sizeof(hash);
6558 info.EncryptedHash.pbData = (BYTE *)hash;
6559 SetLastError(0xdeadbeef);
6560 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6561 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6562 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6563 ok(!ret && GetLastError() == E_INVALIDARG,
6564 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6565 else
6566 {
6567 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6568 if (ret)
6569 {
6570 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6571 size);
6572 if (size == sizeof(PKCSSignerWithHash))
6573 ok(!memcmp(buf, PKCSSignerWithHash, size),
6574 "Unexpected value\n");
6575 else
6576 ok(0, "Unexpected value\n");
6577 LocalFree(buf);
6578 }
6579 }
6580 info.AuthAttrs.cAttr = 1;
6581 info.AuthAttrs.rgAttr = &attr;
6582 SetLastError(0xdeadbeef);
6583 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6584 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6585 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6586 ok(!ret && GetLastError() == E_INVALIDARG,
6587 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6588 else
6589 {
6590 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6591 if (ret)
6592 {
6593 ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6594 size);
6595 if (size == sizeof(PKCSSignerWithAuthAttr))
6596 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6597 "Unexpected value\n");
6598 else
6599 ok(0, "Unexpected value\n");
6600 LocalFree(buf);
6601 }
6602 }
6603 }
6604
6605 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6606 {
6607 BOOL ret;
6608 LPBYTE buf = NULL;
6609 DWORD size = 0;
6610 CMSG_SIGNER_INFO *info;
6611
6612 /* A PKCS signer can't be decoded without a serial number. */
6613 SetLastError(0xdeadbeef);
6614 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6615 minimalPKCSSigner, sizeof(minimalPKCSSigner),
6616 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6617 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6618 GetLastError() == OSS_DATA_ERROR /* Win9x */),
6619 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6620 GetLastError());
6621 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6622 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6623 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6624 ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6625 "CryptDecodeObjectEx failed: %x\n", GetLastError());
6626 if (ret)
6627 {
6628 info = (CMSG_SIGNER_INFO *)buf;
6629 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6630 info->dwVersion);
6631 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6632 "Unexpected size %d\n", info->Issuer.cbData);
6633 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6634 info->Issuer.cbData), "Unexpected value\n");
6635 ok(info->SerialNumber.cbData == sizeof(serialNum),
6636 "Unexpected size %d\n", info->SerialNumber.cbData);
6637 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6638 "Unexpected value\n");
6639 LocalFree(buf);
6640 }
6641 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6642 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6643 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6644 if (ret)
6645 {
6646 info = (CMSG_SIGNER_INFO *)buf;
6647 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6648 info->dwVersion);
6649 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6650 "Unexpected size %d\n", info->Issuer.cbData);
6651 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6652 info->Issuer.cbData), "Unexpected value\n");
6653 ok(info->SerialNumber.cbData == sizeof(serialNum),
6654 "Unexpected size %d\n", info->SerialNumber.cbData);
6655 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6656 "Unexpected value\n");
6657 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6658 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6659 LocalFree(buf);
6660 }
6661 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6662 PKCSSignerWithHashAndEncryptionAlgo,
6663 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6664 NULL, &buf, &size);
6665 if (ret)
6666 {
6667 info = (CMSG_SIGNER_INFO *)buf;
6668 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6669 info->dwVersion);
6670 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6671 "Unexpected size %d\n", info->Issuer.cbData);
6672 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6673 info->Issuer.cbData), "Unexpected value\n");
6674 ok(info->SerialNumber.cbData == sizeof(serialNum),
6675 "Unexpected size %d\n", info->SerialNumber.cbData);
6676 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6677 "Unexpected value\n");
6678 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6679 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6680 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6681 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6682 LocalFree(buf);
6683 }
6684 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6685 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6686 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6687 if (ret)
6688 {
6689 info = (CMSG_SIGNER_INFO *)buf;
6690 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6691 info->dwVersion);
6692 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6693 "Unexpected size %d\n", info->Issuer.cbData);
6694 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6695 info->Issuer.cbData), "Unexpected value\n");
6696 ok(info->SerialNumber.cbData == sizeof(serialNum),
6697 "Unexpected size %d\n", info->SerialNumber.cbData);
6698 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6699 "Unexpected value\n");
6700 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6701 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6702 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6703 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6704 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6705 info->EncryptedHash.cbData);
6706 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6707 "Unexpected value\n");
6708 LocalFree(buf);
6709 }
6710 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6711 PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6712 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6713 if (ret)
6714 {
6715 info = (CMSG_SIGNER_INFO *)buf;
6716 ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6717 info->AuthAttrs.cAttr);
6718 ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6719 "Expected %s, got %s\n", szOID_COMMON_NAME,
6720 info->AuthAttrs.rgAttr[0].pszObjId);
6721 ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6722 info->AuthAttrs.rgAttr[0].cValue);
6723 ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6724 sizeof(encodedCommonName), "Unexpected size %d\n",
6725 info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6726 ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6727 encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6728 LocalFree(buf);
6729 }
6730 }
6731
6732 static const BYTE CMSSignerWithKeyId[] = {
6733 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6734 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6735
6736 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6737 {
6738 BOOL ret;
6739 LPBYTE buf = NULL;
6740 DWORD size = 0;
6741 CMSG_CMS_SIGNER_INFO info = { 0 };
6742 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6743
6744 SetLastError(0xdeadbeef);
6745 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6746 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6747 ok(!ret, "Expected failure, got %d\n", ret);
6748 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6749 {
6750 skip("no CMS_SIGNER_INFO encode support\n");
6751 return;
6752 }
6753 ok(GetLastError() == E_INVALIDARG,
6754 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6755 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6756 SetLastError(0xdeadbeef);
6757 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6758 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6759 ok(!ret, "Expected failure, got %d\n", ret);
6760 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6761 {
6762 skip("no CMS_SIGNER_INFO encode support\n");
6763 return;
6764 }
6765 ok(GetLastError() == E_INVALIDARG,
6766 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6767 /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6768 * be a key id or an issuer serial number with at least the issuer set, and
6769 * the encoding must include PKCS_7_ASN_ENCODING.
6770 * (That isn't enough to be decoded, see decoding tests.)
6771 */
6772 U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6773 sizeof(encodedCommonNameNoNull);
6774 U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6775 SetLastError(0xdeadbeef);
6776 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6777 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6778 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6779 ok(!ret && GetLastError() == E_INVALIDARG,
6780 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6781 else
6782 {
6783 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6784 if (ret)
6785 {
6786 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6787 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6788 LocalFree(buf);
6789 }
6790 }
6791 U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6792 U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6793 SetLastError(0xdeadbeef);
6794 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6795 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6796 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6797 ok(!ret && GetLastError() == E_INVALIDARG,
6798 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6799 else
6800 {
6801 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6802 if (ret)
6803 {
6804 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6805 size);
6806 ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6807 LocalFree(buf);
6808 }
6809 }
6810 info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6811 U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6812 U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6813 SetLastError(0xdeadbeef);
6814 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6815 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6816 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6817 ok(!ret && GetLastError() == E_INVALIDARG,
6818 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6819 else
6820 {
6821 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6822 if (ret)
6823 {
6824 ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6825 size);
6826 ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6827 LocalFree(buf);
6828 }
6829 }
6830 /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6831 * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6832 * (see RFC 3852, section 5.3.)
6833 */
6834 info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6835 U(info.SignerId).HashId.cbData = sizeof(hash);
6836 U(info.SignerId).HashId.pbData = (BYTE *)hash;
6837 SetLastError(0xdeadbeef);
6838 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6839 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6840 ok(!ret && GetLastError() == E_INVALIDARG,
6841 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6842 /* Now with a hash algo */
6843 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6844 U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6845 sizeof(encodedCommonNameNoNull);
6846 U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6847 info.HashAlgorithm.pszObjId = oid1;
6848 SetLastError(0xdeadbeef);
6849 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6850 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6851 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6852 ok(!ret && GetLastError() == E_INVALIDARG,
6853 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6854 else
6855 {
6856 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6857 if (ret)
6858 {
6859 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6860 size);
6861 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6862 "Unexpected value\n");
6863 LocalFree(buf);
6864 }
6865 }
6866 info.HashEncryptionAlgorithm.pszObjId = oid2;
6867 SetLastError(0xdeadbeef);
6868 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6869 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6870 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6871 ok(!ret && GetLastError() == E_INVALIDARG,
6872 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6873 else
6874 {
6875 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6876 if (ret)
6877 {
6878 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6879 "Unexpected size %d\n", size);
6880 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6881 "Unexpected value\n");
6882 LocalFree(buf);
6883 }
6884 }
6885 info.EncryptedHash.cbData = sizeof(hash);
6886 info.EncryptedHash.pbData = (BYTE *)hash;
6887 SetLastError(0xdeadbeef);
6888 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6889 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6890 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6891 ok(!ret && GetLastError() == E_INVALIDARG,
6892 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6893 else
6894 {
6895 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6896 if (ret)
6897 {
6898 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6899 size);
6900 ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6901 LocalFree(buf);
6902 }
6903 }
6904 }
6905
6906 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6907 {
6908 BOOL ret;
6909 LPBYTE buf = NULL;
6910 DWORD size = 0;
6911 CMSG_CMS_SIGNER_INFO *info;
6912 static const char oid1[] = "1.2.3", oid2[] = "1.5.6";
6913
6914 /* A CMS signer can't be decoded without a serial number. */
6915 SetLastError(0xdeadbeef);
6916 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6917 minimalPKCSSigner, sizeof(minimalPKCSSigner),
6918 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6919 ok(!ret, "expected failure\n");
6920 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6921 {
6922 skip("no CMS_SIGNER_INFO decode support\n");
6923 return;
6924 }
6925 ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6926 "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6927 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6928 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6929 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6930 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6931 if (ret)
6932 {
6933 info = (CMSG_CMS_SIGNER_INFO *)buf;
6934 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6935 info->dwVersion);
6936 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6937 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6938 info->SignerId.dwIdChoice);
6939 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6940 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6941 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6942 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6943 encodedCommonNameNoNull,
6944 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6945 "Unexpected value\n");
6946 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6947 sizeof(serialNum), "Unexpected size %d\n",
6948 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6949 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6950 serialNum, sizeof(serialNum)), "Unexpected value\n");
6951 LocalFree(buf);
6952 }
6953 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6954 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6955 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6956 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6957 if (ret)
6958 {
6959 info = (CMSG_CMS_SIGNER_INFO *)buf;
6960 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6961 info->dwVersion);
6962 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6963 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6964 info->SignerId.dwIdChoice);
6965 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6966 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6967 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6968 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6969 encodedCommonNameNoNull,
6970 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6971 "Unexpected value\n");
6972 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6973 sizeof(serialNum), "Unexpected size %d\n",
6974 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6975 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6976 serialNum, sizeof(serialNum)), "Unexpected value\n");
6977 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6978 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6979 LocalFree(buf);
6980 }
6981 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6982 PKCSSignerWithHashAndEncryptionAlgo,
6983 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6984 NULL, &buf, &size);
6985 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6986 if (ret)
6987 {
6988 info = (CMSG_CMS_SIGNER_INFO *)buf;
6989 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6990 info->dwVersion);
6991 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6992 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6993 info->SignerId.dwIdChoice);
6994 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6995 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6996 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6997 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6998 encodedCommonNameNoNull,
6999 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
7000 "Unexpected value\n");
7001 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
7002 sizeof(serialNum), "Unexpected size %d\n",
7003 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
7004 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
7005 serialNum, sizeof(serialNum)), "Unexpected value\n");
7006 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
7007 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
7008 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
7009 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
7010 LocalFree(buf);
7011 }
7012 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7013 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
7014 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7015 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7016 if (ret)
7017 {
7018 info = (CMSG_CMS_SIGNER_INFO *)buf;
7019 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7020 info->dwVersion);
7021 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
7022 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
7023 info->SignerId.dwIdChoice);
7024 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
7025 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
7026 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
7027 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
7028 encodedCommonNameNoNull,
7029 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
7030 "Unexpected value\n");
7031 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
7032 sizeof(serialNum), "Unexpected size %d\n",
7033 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
7034 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
7035 serialNum, sizeof(serialNum)), "Unexpected value\n");
7036 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
7037 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
7038 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
7039 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
7040 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
7041 info->EncryptedHash.cbData);
7042 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
7043 "Unexpected value\n");
7044 LocalFree(buf);
7045 }
7046 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7047 CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
7048 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7049 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7050 if (ret)
7051 {
7052 info = (CMSG_CMS_SIGNER_INFO *)buf;
7053 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7054 info->dwVersion);
7055 ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
7056 "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
7057 info->SignerId.dwIdChoice);
7058 ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
7059 "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
7060 ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
7061 "Unexpected value\n");
7062 LocalFree(buf);
7063 }
7064 }
7065
7066 static BYTE emptyDNSPermittedConstraints[] = {
7067 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
7068 static BYTE emptyDNSExcludedConstraints[] = {
7069 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
7070 static BYTE DNSExcludedConstraints[] = {
7071 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
7072 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7073 static BYTE permittedAndExcludedConstraints[] = {
7074 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7075 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
7076 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7077 static BYTE permittedAndExcludedWithMinConstraints[] = {
7078 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7079 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
7080 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7081 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
7082 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7083 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
7084 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7085
7086 static void test_encodeNameConstraints(DWORD dwEncoding)
7087 {
7088 BOOL ret;
7089 CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
7090 CERT_GENERAL_SUBTREE permitted = { { 0 } };
7091 CERT_GENERAL_SUBTREE excluded = { { 0 } };
7092 LPBYTE buf;
7093 DWORD size;
7094
7095 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7096 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7097 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7098 {
7099 skip("no X509_NAME_CONSTRAINTS encode support\n");
7100 return;
7101 }
7102 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7103 if (ret)
7104 {
7105 ok(size == sizeof(emptySequence), "Unexpected size\n");
7106 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
7107 LocalFree(buf);
7108 }
7109 constraints.cPermittedSubtree = 1;
7110 constraints.rgPermittedSubtree = &permitted;
7111 SetLastError(0xdeadbeef);
7112 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7113 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7114 ok(!ret && GetLastError() == E_INVALIDARG,
7115 "Expected E_INVALIDARG, got %08x\n", GetLastError());
7116 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7117 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7118 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7119 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7120 if (ret)
7121 {
7122 ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
7123 ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
7124 "Unexpected value\n");
7125 LocalFree(buf);
7126 }
7127 constraints.cPermittedSubtree = 0;
7128 constraints.cExcludedSubtree = 1;
7129 constraints.rgExcludedSubtree = &excluded;
7130 excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7131 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7132 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7133 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7134 if (ret)
7135 {
7136 ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
7137 ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
7138 "Unexpected value\n");
7139 LocalFree(buf);
7140 }
7141 U(excluded.Base).pwszURL = (LPWSTR)url;
7142 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7143 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7144 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7145 if (ret)
7146 {
7147 ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
7148 ok(!memcmp(buf, DNSExcludedConstraints, size),
7149 "Unexpected value\n");
7150 LocalFree(buf);
7151 }
7152 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
7153 U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7154 U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7155 constraints.cPermittedSubtree = 1;
7156 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7157 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7158 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7159 if (ret)
7160 {
7161 ok(size == sizeof(permittedAndExcludedConstraints),
7162 "Unexpected size\n");
7163 ok(!memcmp(buf, permittedAndExcludedConstraints, size),
7164 "Unexpected value\n");
7165 LocalFree(buf);
7166 }
7167 permitted.dwMinimum = 5;
7168 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7169 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7170 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7171 if (ret)
7172 {
7173 ok(size == sizeof(permittedAndExcludedWithMinConstraints),
7174 "Unexpected size\n");
7175 ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
7176 "Unexpected value\n");
7177 LocalFree(buf);
7178 }
7179 permitted.fMaximum = TRUE;
7180 permitted.dwMaximum = 3;
7181 SetLastError(0xdeadbeef);
7182 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7183 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7184 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7185 if (ret)
7186 {
7187 ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
7188 "Unexpected size\n");
7189 ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
7190 "Unexpected value\n");
7191 LocalFree(buf);
7192 }
7193 }
7194
7195 struct EncodedNameConstraints
7196 {
7197 CRYPT_DATA_BLOB encoded;
7198 CERT_NAME_CONSTRAINTS_INFO constraints;
7199 };
7200
7201 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
7202 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7203 static CERT_GENERAL_SUBTREE DNSSubtree = {
7204 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7205 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
7206 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
7207 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
7208 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
7209 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
7210 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
7211
7212 static const struct EncodedNameConstraints encodedNameConstraints[] = {
7213 { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
7214 { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
7215 { 1, &emptyDNSSubtree, 0, NULL } },
7216 { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
7217 { 0, NULL, 1, &emptyDNSSubtree } },
7218 { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
7219 { 0, NULL, 1, &DNSSubtree } },
7220 { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
7221 { 1, &IPAddressSubtree, 1, &DNSSubtree } },
7222 { { sizeof(permittedAndExcludedWithMinConstraints),
7223 permittedAndExcludedWithMinConstraints },
7224 { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
7225 { { sizeof(permittedAndExcludedWithMinMaxConstraints),
7226 permittedAndExcludedWithMinMaxConstraints },
7227 { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
7228 };
7229
7230 static void test_decodeNameConstraints(DWORD dwEncoding)
7231 {
7232 BOOL ret;
7233 DWORD i;
7234 CERT_NAME_CONSTRAINTS_INFO *constraints;
7235
7236 U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
7237 U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7238 U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7239 U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7240 U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7241 U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7242 U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7243 for (i = 0;
7244 i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
7245 i++)
7246 {
7247 DWORD size;
7248
7249 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
7250 encodedNameConstraints[i].encoded.pbData,
7251 encodedNameConstraints[i].encoded.cbData,
7252 CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
7253 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7254 {
7255 skip("no X509_NAME_CONSTRAINTS decode support\n");
7256 return;
7257 }
7258 ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7259 if (ret)
7260 {
7261 DWORD j;
7262
7263 if (constraints->cPermittedSubtree !=
7264 encodedNameConstraints[i].constraints.cPermittedSubtree)
7265 fprintf(stderr, "%d: expected %u permitted, got %u\n", i,
7266 encodedNameConstraints[i].constraints.cPermittedSubtree,
7267 constraints->cPermittedSubtree);
7268 if (constraints->cPermittedSubtree ==
7269 encodedNameConstraints[i].constraints.cPermittedSubtree)
7270 {
7271 for (j = 0; j < constraints->cPermittedSubtree; j++)
7272 {
7273 compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7274 &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7275 }
7276 }
7277 if (constraints->cExcludedSubtree !=
7278 encodedNameConstraints[i].constraints.cExcludedSubtree)
7279 fprintf(stderr, "%d: expected %u excluded, got %u\n", i,
7280 encodedNameConstraints[i].constraints.cExcludedSubtree,
7281 constraints->cExcludedSubtree);
7282 if (constraints->cExcludedSubtree ==
7283 encodedNameConstraints[i].constraints.cExcludedSubtree)
7284 {
7285 for (j = 0; j < constraints->cExcludedSubtree; j++)
7286 {
7287 compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7288 &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7289 }
7290 }
7291 LocalFree(constraints);
7292 }
7293 }
7294 }
7295
7296 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7297 'n','o','t','i','c','e',0 };
7298 static const BYTE noticeWithDisplayText[] = {
7299 0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7300 0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7301 0x00,0x69,0x00,0x63,0x00,0x65
7302 };
7303 static char org[] = "Wine";
7304 static int noticeNumbers[] = { 2,3 };
7305 static BYTE noticeWithReference[] = {
7306 0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7307 0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7308 0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7309 0x74,0x00,0x69,0x00,0x63,0x00,0x65
7310 };
7311
7312 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7313 {
7314 BOOL ret;
7315 LPBYTE buf;
7316 DWORD size;
7317 CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7318 CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7319
7320 memset(&notice, 0, sizeof(notice));
7321 ret = pCryptEncodeObjectEx(dwEncoding,
7322 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7323 NULL, &buf, &size);
7324 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7325 {
7326 skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7327 return;
7328 }
7329 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7330 if (ret)
7331 {
7332 ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7333 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7334 LocalFree(buf);
7335 }
7336 notice.pszDisplayText = noticeText;
7337 ret = pCryptEncodeObjectEx(dwEncoding,
7338 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7339 NULL, &buf, &size);
7340 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7341 if (ret)
7342 {
7343 ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7344 ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7345 LocalFree(buf);
7346 }
7347 reference.pszOrganization = org;
7348 reference.cNoticeNumbers = 2;
7349 reference.rgNoticeNumbers = noticeNumbers;
7350 notice.pNoticeReference = &reference;
7351 ret = pCryptEncodeObjectEx(dwEncoding,
7352 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7353 NULL, &buf, &size);
7354 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7355 if (ret)
7356 {
7357 ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7358 ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7359 LocalFree(buf);
7360 }
7361 }
7362
7363 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7364 {
7365 BOOL ret;
7366 CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7367 DWORD size;
7368
7369 ret = pCryptDecodeObjectEx(dwEncoding,
7370 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7371 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7372 &notice, &size);
7373 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7374 {
7375 skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7376 return;
7377 }
7378 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7379 if (ret)
7380 {
7381 ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7382 ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7383 LocalFree(notice);
7384 }
7385 ret = pCryptDecodeObjectEx(dwEncoding,
7386 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7387 noticeWithDisplayText, sizeof(noticeWithDisplayText),
7388 CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7389 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7390 if (ret)
7391 {
7392 ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7393 "unexpected display text\n");
7394 ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7395 LocalFree(notice);
7396 }
7397 ret = pCryptDecodeObjectEx(dwEncoding,
7398 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7399 noticeWithReference, sizeof(noticeWithReference),
7400 CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7401 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7402 if (ret)
7403 {
7404 ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7405 "unexpected display text\n");
7406 ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7407 if (notice->pNoticeReference)
7408 {
7409 ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7410 "unexpected organization %s\n",
7411 notice->pNoticeReference->pszOrganization);
7412 ok(notice->pNoticeReference->cNoticeNumbers == 2,
7413 "expected 2 notice numbers, got %d\n",
7414 notice->pNoticeReference->cNoticeNumbers);
7415 ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7416 "unexpected notice number %d\n",
7417 notice->pNoticeReference->rgNoticeNumbers[0]);
7418 ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7419 "unexpected notice number %d\n",
7420 notice->pNoticeReference->rgNoticeNumbers[1]);
7421 }
7422 LocalFree(notice);
7423 }
7424 }
7425
7426 static char oid_any_policy[] = "2.5.29.32.0";
7427 static const BYTE policiesWithAnyPolicy[] = {
7428 0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7429 };
7430 static char oid1[] = "1.2.3";
7431 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7432 static const BYTE twoPolicies[] = {
7433 0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7434 0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7435 0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7436 0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7437 0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7438 0x74,0x00,0x69,0x00,0x63,0x00,0x65
7439 };
7440
7441 static void test_encodeCertPolicies(DWORD dwEncoding)
7442 {
7443 BOOL ret;
7444 CERT_POLICIES_INFO info;
7445 CERT_POLICY_INFO policy[2];
7446 CERT_POLICY_QUALIFIER_INFO qualifier;
7447 LPBYTE buf;
7448 DWORD size;
7449
7450 memset(&info, 0, sizeof(info));
7451 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7452 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7453 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7454 if (ret)
7455 {
7456 ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7457 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7458 LocalFree(buf);
7459 }
7460 memset(policy, 0, sizeof(policy));
7461 info.cPolicyInfo = 1;
7462 info.rgPolicyInfo = policy;
7463 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7464 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7465 ok(!ret && (GetLastError() == E_INVALIDARG ||
7466 GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7467 "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7468 policy[0].pszPolicyIdentifier = oid_any_policy;
7469 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7470 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7471 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7472 if (ret)
7473 {
7474 ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7475 ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7476 LocalFree(buf);
7477 }
7478 policy[1].pszPolicyIdentifier = oid1;
7479 memset(&qualifier, 0, sizeof(qualifier));
7480 qualifier.pszPolicyQualifierId = oid_user_notice;
7481 qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7482 qualifier.Qualifier.pbData = noticeWithReference;
7483 policy[1].cPolicyQualifier = 1;
7484 policy[1].rgPolicyQualifier = &qualifier;
7485 info.cPolicyInfo = 2;
7486 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7487 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7488 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7489 if (ret)
7490 {
7491 ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7492 ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7493 LocalFree(buf);
7494 }
7495 }
7496
7497 static void test_decodeCertPolicies(DWORD dwEncoding)
7498 {
7499 BOOL ret;
7500 CERT_POLICIES_INFO *info;
7501 DWORD size;
7502
7503 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7504 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7505 &info, &size);
7506 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7507 if (ret)
7508 {
7509 ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7510 info->cPolicyInfo);
7511 LocalFree(info);
7512 }
7513 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7514 policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7515 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7516 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7517 if (ret)
7518 {
7519 ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7520 info->cPolicyInfo);
7521 ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7522 "unexpected policy id %s\n",
7523 info->rgPolicyInfo[0].pszPolicyIdentifier);
7524 ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7525 "unexpected policy qualifier count %d\n",
7526 info->rgPolicyInfo[0].cPolicyQualifier);
7527 LocalFree(info);
7528 }
7529 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7530 twoPolicies, sizeof(twoPolicies),
7531 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7532 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7533 if (ret)
7534 {
7535 ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7536 info->cPolicyInfo);
7537 ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7538 "unexpected policy id %s\n",
7539 info->rgPolicyInfo[0].pszPolicyIdentifier);
7540 ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7541 "unexpected policy qualifier count %d\n",
7542 info->rgPolicyInfo[0].cPolicyQualifier);
7543 ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7544 "unexpected policy id %s\n",
7545 info->rgPolicyInfo[1].pszPolicyIdentifier);
7546 ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7547 "unexpected policy qualifier count %d\n",
7548 info->rgPolicyInfo[1].cPolicyQualifier);
7549 ok(!strcmp(
7550 info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7551 oid_user_notice), "unexpected policy qualifier id %s\n",
7552 info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7553 ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7554 sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7555 info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7556 ok(!memcmp(
7557 info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7558 noticeWithReference, sizeof(noticeWithReference)),
7559 "unexpected qualifier value\n");
7560 LocalFree(info);
7561 }
7562 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7563 twoPolicies, sizeof(twoPolicies), 0, NULL, NULL, &size);
7564 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7565 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7566 if (info)
7567 {
7568 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7569 twoPolicies, sizeof(twoPolicies), 0, NULL, info, &size);
7570 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7571 HeapFree(GetProcessHeap(), 0, info);
7572 }
7573 }
7574
7575 static const BYTE policyMappingWithOneMapping[] = {
7576 0x30,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04 };
7577 static const BYTE policyMappingWithTwoMappings[] = {
7578 0x30,0x14,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04,0x30,0x08,0x06,
7579 0x02,0x2b,0x04,0x06,0x02,0x55,0x06 };
7580 static const LPCSTR mappingOids[] = { X509_POLICY_MAPPINGS,
7581 szOID_POLICY_MAPPINGS, szOID_LEGACY_POLICY_MAPPINGS };
7582
7583 static void test_encodeCertPolicyMappings(DWORD dwEncoding)
7584 {
7585 static char oid2[] = "2.3.4";
7586 static char oid3[] = "1.3.4";
7587 static char oid4[] = "2.5.6";
7588 BOOL ret;
7589 CERT_POLICY_MAPPINGS_INFO info = { 0 };
7590 CERT_POLICY_MAPPING mapping[2];
7591 LPBYTE buf;
7592 DWORD size, i;
7593
7594 /* Each of the mapping OIDs is equivalent, so check with all of them */
7595 for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7596 {
7597 memset(&info, 0, sizeof(info));
7598 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7599 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7600 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7601 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7602 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7603 {
7604 win_skip("no policy mappings support\n");
7605 return;
7606 }
7607 if (ret)
7608 {
7609 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7610 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7611 "unexpected value\n");
7612 LocalFree(buf);
7613 }
7614 mapping[0].pszIssuerDomainPolicy = NULL;
7615 mapping[0].pszSubjectDomainPolicy = NULL;
7616 info.cPolicyMapping = 1;
7617 info.rgPolicyMapping = mapping;
7618 SetLastError(0xdeadbeef);
7619 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7620 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7621 ok(!ret && GetLastError() == E_INVALIDARG,
7622 "expected E_INVALIDARG, got %08x\n", GetLastError());
7623 mapping[0].pszIssuerDomainPolicy = oid1;
7624 mapping[0].pszSubjectDomainPolicy = oid2;
7625 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7626 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7627 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7628 if (ret)
7629 {
7630 ok(size == sizeof(policyMappingWithOneMapping),
7631 "unexpected size %d\n", size);
7632 ok(!memcmp(buf, policyMappingWithOneMapping, size),
7633 "unexpected value\n");
7634 LocalFree(buf);
7635 }
7636 mapping[1].pszIssuerDomainPolicy = oid3;
7637 mapping[1].pszSubjectDomainPolicy = oid4;
7638 info.cPolicyMapping = 2;
7639 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7640 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7641 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7642 if (ret)
7643 {
7644 ok(size == sizeof(policyMappingWithTwoMappings),
7645 "unexpected size %d\n", size);
7646 ok(!memcmp(buf, policyMappingWithTwoMappings, size),
7647 "unexpected value\n");
7648 LocalFree(buf);
7649 }
7650 }
7651 }
7652
7653 static void test_decodeCertPolicyMappings(DWORD dwEncoding)
7654 {
7655 DWORD size, i;
7656 CERT_POLICY_MAPPINGS_INFO *info;
7657 BOOL ret;
7658
7659 /* Each of the mapping OIDs is equivalent, so check with all of them */
7660 for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7661 {
7662 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7663 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7664 &info, &size);
7665 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7666 "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7667 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7668 {
7669 win_skip("no policy mappings support\n");
7670 return;
7671 }
7672 if (ret)
7673 {
7674 ok(info->cPolicyMapping == 0,
7675 "expected 0 policy mappings, got %d\n", info->cPolicyMapping);
7676 LocalFree(info);
7677 }
7678 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7679 policyMappingWithOneMapping, sizeof(policyMappingWithOneMapping),
7680 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7681 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7682 if (ret)
7683 {
7684 ok(info->cPolicyMapping == 1,
7685 "expected 1 policy mappings, got %d\n", info->cPolicyMapping);
7686 ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7687 "unexpected issuer policy %s\n",
7688 info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7689 ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7690 "2.3.4"), "unexpected subject policy %s\n",
7691 info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7692 LocalFree(info);
7693 }
7694 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7695 policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings),
7696 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7697 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7698 if (ret)
7699 {
7700 ok(info->cPolicyMapping == 2,
7701 "expected 2 policy mappings, got %d\n", info->cPolicyMapping);
7702 ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7703 "unexpected issuer policy %s\n",
7704 info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7705 ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7706 "2.3.4"), "unexpected subject policy %s\n",
7707 info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7708 ok(!strcmp(info->rgPolicyMapping[1].pszIssuerDomainPolicy, "1.3.4"),
7709 "unexpected issuer policy %s\n",
7710 info->rgPolicyMapping[1].pszIssuerDomainPolicy);
7711 ok(!strcmp(info->rgPolicyMapping[1].pszSubjectDomainPolicy,
7712 "2.5.6"), "unexpected subject policy %s\n",
7713 info->rgPolicyMapping[1].pszSubjectDomainPolicy);
7714 LocalFree(info);
7715 }
7716 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7717 policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings), 0,
7718 NULL, NULL, &size);
7719 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7720 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7721 if (info)
7722 {
7723 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7724 policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings), 0,
7725 NULL, info, &size);
7726 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7727 HeapFree(GetProcessHeap(), 0, info);
7728 }
7729 }
7730 }
7731
7732 static const BYTE policyConstraintsWithRequireExplicit[] = {
7733 0x30,0x03,0x80,0x01,0x00 };
7734 static const BYTE policyConstraintsWithInhibitMapping[] = {
7735 0x30,0x03,0x81,0x01,0x01 };
7736 static const BYTE policyConstraintsWithBoth[] = {
7737 0x30,0x06,0x80,0x01,0x01,0x81,0x01,0x01 };
7738
7739 static void test_encodeCertPolicyConstraints(DWORD dwEncoding)
7740 {
7741 CERT_POLICY_CONSTRAINTS_INFO info = { 0 };
7742 LPBYTE buf;
7743 DWORD size;
7744 BOOL ret;
7745
7746 /* Even though RFC 5280 explicitly states CAs must not issue empty
7747 * policy constraints (section 4.2.1.11), the API doesn't prevent it.
7748 */
7749 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7750 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7751 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7752 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7753 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7754 {
7755 win_skip("no policy constraints support\n");
7756 return;
7757 }
7758 if (ret)
7759 {
7760 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7761 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7762 "unexpected value\n");
7763 LocalFree(buf);
7764 }
7765 /* If fRequireExplicitPolicy is set but dwRequireExplicitPolicySkipCerts
7766 * is not, then a skip of 0 is encoded.
7767 */
7768 info.fRequireExplicitPolicy = TRUE;
7769 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7770 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7771 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7772 if (ret)
7773 {
7774 ok(size == sizeof(policyConstraintsWithRequireExplicit),
7775 "unexpected size %d\n", size);
7776 ok(!memcmp(buf, policyConstraintsWithRequireExplicit,
7777 sizeof(policyConstraintsWithRequireExplicit)), "unexpected value\n");
7778 LocalFree(buf);
7779 }
7780 /* With inhibit policy mapping */
7781 info.fRequireExplicitPolicy = FALSE;
7782 info.dwRequireExplicitPolicySkipCerts = 0;
7783 info.fInhibitPolicyMapping = TRUE;
7784 info.dwInhibitPolicyMappingSkipCerts = 1;
7785 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7786 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7787 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7788 if (ret)
7789 {
7790 ok(size == sizeof(policyConstraintsWithInhibitMapping),
7791 "unexpected size %d\n", size);
7792 ok(!memcmp(buf, policyConstraintsWithInhibitMapping,
7793 sizeof(policyConstraintsWithInhibitMapping)), "unexpected value\n");
7794 LocalFree(buf);
7795 }
7796 /* And with both */
7797 info.fRequireExplicitPolicy = TRUE;
7798 info.dwRequireExplicitPolicySkipCerts = 1;
7799 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7800 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7801 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7802 if (ret)
7803 {
7804 ok(size == sizeof(policyConstraintsWithBoth), "unexpected size %d\n",
7805 size);
7806 ok(!memcmp(buf, policyConstraintsWithBoth,
7807 sizeof(policyConstraintsWithBoth)), "unexpected value\n");
7808 LocalFree(buf);
7809 }
7810 }
7811
7812 static void test_decodeCertPolicyConstraints(DWORD dwEncoding)
7813 {
7814 CERT_POLICY_CONSTRAINTS_INFO *info;
7815 DWORD size;
7816 BOOL ret;
7817
7818 /* Again, even though CAs must not issue such constraints, they can be
7819 * decoded.
7820 */
7821 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7822 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7823 &info, &size);
7824 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7825 "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7826 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7827 {
7828 win_skip("no policy mappings support\n");
7829 return;
7830 }
7831 if (ret)
7832 {
7833 ok(!info->fRequireExplicitPolicy,
7834 "expected require explicit = FALSE\n");
7835 ok(!info->fInhibitPolicyMapping,
7836 "expected implicit mapping = FALSE\n");
7837 LocalFree(info);
7838 }
7839 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7840 policyConstraintsWithRequireExplicit,
7841 sizeof(policyConstraintsWithRequireExplicit), CRYPT_DECODE_ALLOC_FLAG,
7842 NULL, &info, &size);
7843 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7844 if (ret)
7845 {
7846 ok(info->fRequireExplicitPolicy,
7847 "expected require explicit = TRUE\n");
7848 ok(info->dwRequireExplicitPolicySkipCerts == 0, "expected 0, got %d\n",
7849 info->dwRequireExplicitPolicySkipCerts);
7850 ok(!info->fInhibitPolicyMapping,
7851 "expected implicit mapping = FALSE\n");
7852 LocalFree(info);
7853 }
7854 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7855 policyConstraintsWithInhibitMapping,
7856 sizeof(policyConstraintsWithInhibitMapping), CRYPT_DECODE_ALLOC_FLAG,
7857 NULL, &info, &size);
7858 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7859 if (ret)
7860 {
7861 ok(!info->fRequireExplicitPolicy,
7862 "expected require explicit = FALSE\n");
7863 ok(info->fInhibitPolicyMapping,
7864 "expected implicit mapping = TRUE\n");
7865 ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7866 info->dwInhibitPolicyMappingSkipCerts);
7867 LocalFree(info);
7868 }
7869 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7870 policyConstraintsWithBoth, sizeof(policyConstraintsWithBoth),
7871 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7872 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7873 if (ret)
7874 {
7875 ok(info->fRequireExplicitPolicy,
7876 "expected require explicit = TRUE\n");
7877 ok(info->dwRequireExplicitPolicySkipCerts == 1, "expected 1, got %d\n",
7878 info->dwRequireExplicitPolicySkipCerts);
7879 ok(info->fInhibitPolicyMapping,
7880 "expected implicit mapping = TRUE\n");
7881 ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7882 info->dwInhibitPolicyMappingSkipCerts);
7883 LocalFree(info);
7884 }
7885 }
7886
7887 static const BYTE rsaPrivKeyDer[] = {
7888 0x30,0x82,0x04,0xa5,0x02,0x01,0x00,0x02,0x82,0x01,0x01,0x00,
7889 0xae,0xba,0x3c,0x41,0xeb,0x25,0x41,0xb0,0x1c,0x41,0xd4,0x26,
7890 0xf9,0xf8,0x31,0x64,0x7e,0x97,0x65,0x54,0x9c,0x90,0xdf,0x34,
7891 0x07,0xfb,0xb0,0x69,0x99,0x3b,0x45,0x39,0x06,0xe4,0x3a,0x7a,
7892 0x01,0xe0,0xeb,0x3f,0xe1,0xd5,0x91,0xe0,0x16,0xe0,0xf2,0x35,
7893 0x59,0xdf,0x32,0x2d,0x69,0x3a,0x4a,0xbc,0xd1,0xba,0x1b,0x3b,
7894 0x7a,0x55,0x76,0xba,0x11,0xdd,0x2f,0xc7,0x58,0x66,0xf2,0x6c,
7895 0xd1,0x68,0x27,0x6c,0x85,0x74,0x0b,0xc9,0x7b,0x1a,0xde,0x3c,
7896 0x62,0x73,0xe2,0x9e,0x36,0x3a,0x29,0x3b,0x91,0x85,0x3d,0xd2,
7897 0xe1,0xe5,0x61,0x84,0x1e,0x28,0xfd,0xb7,0x97,0x68,0xc1,0xbb,
7898 0x0f,0x93,0x14,0xc2,0x03,0x60,0x41,0x11,0x7a,0xda,0x76,0x01,
7899 0x65,0x08,0xe6,0x0c,0xf6,0xfc,0x1d,0x64,0x12,0x7b,0x42,0xb0,
7900 0xb8,0xfe,0x61,0xe5,0xe2,0xe5,0x61,0x44,0xcc,0x94,0xe8,0xc0,
7901 0x4f,0x58,0x9a,0xea,0x99,0xaf,0x9c,0xa4,0xf2,0xd7,0x2b,0x31,
7902 0x90,0x3b,0x41,0x2e,0x4a,0x74,0x7c,0x1a,0xfc,0x42,0xa9,0x17,
7903 0xff,0x53,0x20,0x76,0xa7,0xf0,0x2c,0xb9,0xd5,0x1f,0xa9,0x8a,
7904 0x77,0xa8,0x09,0x5c,0x0e,0xd1,0x54,0xc5,0xf2,0x86,0xf1,0x2f,
7905 0x23,0xd6,0x63,0xba,0xe9,0x2b,0x73,0xf9,0xf0,0xdc,0xcb,0xf9,
7906 0xcb,0xe8,0x40,0x62,0x47,0x09,0x85,0xe1,0x9c,0xfd,0xcf,0x75,
7907 0x5a,0x65,0xfd,0x86,0x1c,0x50,0xfa,0x24,0x36,0x0f,0x54,0x5e,
7908 0x81,0xe7,0xf6,0x63,0x2d,0x87,0x0c,0x50,0x03,0x25,0x49,0xe7,
7909 0xc5,0x20,0xaa,0xbc,0x6c,0xf9,0xbe,0x49,0x8f,0x4f,0xb8,0x9a,
7910 0x73,0x9f,0x55,0x43,0x02,0x03,0x01,0x00,0x01,0x02,0x82,0x01,
7911 0x01,0x00,0x99,0x03,0xcd,0x5b,0x69,0x03,0x32,0x98,0x78,0xd6,
7912 0x89,0x65,0x2c,0xc9,0xd6,0xef,0x8c,0x11,0x27,0x93,0x46,0x9d,
7913 0x74,0x6a,0xcb,0x86,0xf6,0x02,0x34,0x47,0xfc,0xa2,0x29,0x4f,
7914 0xdb,0x8a,0x17,0x75,0x12,0x6f,0xda,0x65,0x3f,0x1f,0xc0,0xc9,
7915 0x74,0x33,0x96,0xa5,0xe8,0xfa,0x6d,0xc9,0xb7,0xc3,0xcd,0xe3,
7916 0x2e,0x90,0x12,0xdd,0x1f,0x61,0x69,0xdd,0x8b,0x47,0x07,0x3a,
7917 0xf8,0x98,0xa5,0x76,0x91,0xf7,0xee,0x93,0x26,0xf3,0x66,0x54,
7918 0xac,0x44,0xb3,0x6f,0x8b,0x09,0x44,0xb2,0x00,0x84,0x03,0x37,
7919 0x6d,0x61,0xed,0xa4,0x04,0x97,0x40,0x16,0x63,0xc2,0xd0,0xdc,
7920 0xd3,0xb3,0xee,0xba,0xbe,0x95,0xfd,0x80,0xe0,0xda,0xde,0xfc,
7921 0xcc,0x15,0x02,0x97,0x1d,0x68,0x43,0x2f,0x9c,0xc8,0x20,0x23,
7922 0xeb,0x00,0x4c,0x74,0x3d,0x27,0x20,0x14,0x23,0x95,0xfc,0x8c,
7923 0xb7,0x7e,0x7f,0xb0,0xdb,0xaf,0x8a,0x48,0x1b,0xfe,0x59,0xab,
7924 0x75,0xe2,0xbf,0x69,0xf2,0x73,0xe3,0xb9,0x92,0xa9,0x90,0x03,
7925 0xe5,0xd4,0x2d,0x86,0xff,0x12,0x54,0xb3,0xbb,0xe2,0xce,0x81,
7926 0x58,0x71,0xa4,0xde,0x45,0x05,0xf8,0x2d,0x45,0xf5,0xd8,0x5e,
7927 0x4c,0x5d,0x06,0x69,0x0c,0x86,0x9f,0x66,0x9f,0xb1,0x60,0xfd,
7928 0xf2,0x33,0x85,0x15,0xd5,0x18,0xf7,0xba,0x99,0x65,0x15,0x1d,
7929 0xfa,0xaa,0x76,0xdd,0x25,0xed,0xdf,0x90,0x6e,0xba,0x61,0x96,
7930 0x79,0xde,0xd2,0xda,0x66,0x03,0x74,0x3b,0x13,0x39,0x68,0xbc,
7931 0x94,0x01,0x00,0x2d,0xf8,0xf0,0x8c,0xbd,0x4c,0x9c,0x7e,0x87,
7932 0x9c,0x62,0x9f,0xb6,0x90,0x11,0x02,0x81,0x81,0x00,0xe3,0x5e,
7933 0xfe,0xdd,0xed,0x76,0xb6,0x4e,0xfc,0x5b,0xe0,0x20,0x99,0x7b,
7934 0x48,0x3b,0x1e,0x5f,0x7f,0x9f,0xa4,0x68,0xbe,0xc3,0x7f,0xb8,
7935 0x62,0x98,0xb0,0x95,0x8a,0xfa,0x0d,0xa3,0x79,0x63,0x39,0xf7,
7936 0xdb,0x76,0x3d,0x53,0x4a,0x0a,0x33,0xdf,0xe0,0x47,0x22,0xd5,
7937 0x96,0x80,0xc7,0xcd,0x24,0xef,0xac,0x49,0x46,0x37,0x6c,0x25,
7938 0xcf,0x6c,0x4d,0xe5,0x31,0xf8,0x2f,0xd2,0x59,0x74,0x00,0x38,
7939 0xdb,0xce,0xd1,0x72,0xc3,0xa8,0x30,0x70,0xd8,0x02,0x20,0xe7,
7940 0x56,0xe7,0xca,0xf0,0x3b,0x52,0x5d,0x11,0xbe,0x53,0x4e,0xd0,
7941 0xd9,0x2e,0xa6,0xb8,0xe2,0xd9,0xbf,0xb9,0x77,0xe7,0x3b,0xed,
7942 0x5e,0xd7,0x16,0x4a,0x3a,0xc5,0x86,0xd7,0x74,0x20,0xa7,0x8e,
7943 0xbf,0xb7,0x33,0xdb,0x51,0xe9,0x02,0x81,0x81,0x00,0xc4,0xba,
7944 0x57,0xf0,0x6e,0xcf,0xe8,0xce,0xce,0x9d,0x4a,0xe9,0x0f,0xe1,
7945 0xab,0x91,0x62,0xaa,0x66,0x5d,0x82,0x66,0x1c,0x72,0x18,0x6f,
7946 0x68,0x9c,0x7d,0x5e,0xfc,0xaf,0x4a,0xd6,0x8e,0xc6,0xae,0x40,
7947 0xf2,0x40,0x84,0x93,0xee,0x7c,0x87,0xa9,0xa6,0xcd,0x2b,0xc3,
7948 0xe6,0x29,0x3a,0xe2,0x4a,0xed,0xb0,0x4d,0x9f,0xc0,0xe9,0xd6,
7949 0xa3,0xca,0x97,0xee,0xac,0xab,0xa4,0x32,0x05,0x40,0x4d,0xf2,
7950 0x95,0x99,0xaf,0xa0,0xe1,0xe1,0xe7,0x3a,0x64,0xa4,0x70,0x6b,
7951 0x3d,0x1d,0x7b,0xf1,0x53,0xfa,0xb0,0xe0,0xe2,0x68,0x1a,0x61,
7952 0x2c,0x37,0xa5,0x39,0x7b,0xb2,0xcf,0xe6,0x5f,0x9b,0xc6,0x64,
7953 0xaf,0x48,0x86,0xfb,0xc1,0xf3,0x39,0x97,0x10,0x36,0xf5,0xa9,
7954 0x3d,0x08,0xa5,0x2f,0xe6,0x4b,0x02,0x81,0x81,0x00,0x86,0xe7,
7955 0x02,0x08,0xe2,0xaf,0xa0,0x93,0x54,0x9f,0x9e,0x67,0x39,0x29,
7956 0x30,0x3e,0x03,0x53,0x5e,0x01,0x76,0x26,0xbf,0xa8,0x76,0xcb,
7957 0x0b,0x94,0xd4,0x90,0xa5,0x98,0x9f,0x26,0xf3,0x0a,0xb0,0x86,
7958 0x22,0xac,0x10,0xce,0xae,0x0b,0x47,0xa3,0xf9,0x09,0xbb,0xdd,
7959 0x46,0x22,0xba,0x69,0x39,0x15,0x0a,0xff,0x9e,0xad,0x9b,0x79,
7960 0x03,0x8c,0x9a,0xda,0xf5,0xbe,0xef,0x80,0xba,0x9a,0x5c,0xd7,
7961 0x5f,0x73,0x62,0x49,0xd9,0x54,0x9d,0x09,0x16,0xe0,0x8c,0x6d,
7962 0x35,0xde,0xe9,0x45,0x87,0xac,0xe2,0x93,0x78,0x7d,0x2d,0x32,
7963 0x34,0xe9,0xbc,0xf9,0xcd,0x7e,0xac,0x86,0x7a,0x61,0xb3,0xe8,
7964 0xae,0x70,0xa7,0x44,0xfb,0x81,0xde,0xf3,0x4e,0x6f,0x61,0x7b,
7965 0x0c,0xbc,0xc2,0x03,0xca,0xa1,0x02,0x81,0x80,0x69,0x5b,0x4a,
7966 0xa1,0x4f,0x17,0x35,0x9d,0x1b,0xf6,0x0d,0x1a,0x48,0x11,0x19,
7967 0xab,0x20,0xe6,0x15,0x30,0x5b,0x17,0x88,0x80,0x6a,0x29,0xb0,
7968 0x22,0xae,0xd9,0xe2,0x05,0x96,0xd4,0xd5,0x5d,0xfe,0x10,0x76,
7969 0x2c,0xab,0x53,0xf6,0x52,0xe6,0xec,0xaa,0x92,0x12,0xb0,0x35,
7970 0x61,0x3b,0x51,0xd9,0xc2,0xf5,0xba,0x7c,0xa5,0xfa,0x15,0xa3,
7971 0x5e,0x6a,0x83,0xbe,0x21,0xa6,0x2b,0xcb,0xb8,0x26,0x86,0x96,
7972 0x2b,0xda,0x6d,0x14,0xcb,0xc0,0xe3,0xfa,0xe6,0x3d,0xf6,0x90,
7973 0xa2,0x6b,0xb0,0x50,0xc3,0x5f,0x5a,0xf0,0xa5,0xc4,0x0a,0xea,
7974 0x7d,0x5a,0x95,0x30,0x74,0x10,0xf7,0x55,0x98,0xbd,0x65,0x4a,
7975 0xa2,0x52,0xf8,0x1d,0x64,0xbf,0x20,0xf1,0xe4,0x1d,0x28,0x67,
7976 0xb1,0x6b,0x95,0xfd,0x85,0x02,0x81,0x81,0x00,0xda,0xb4,0x31,
7977 0x34,0xe1,0xec,0x9a,0x1e,0x07,0xd7,0xda,0x20,0x46,0xbf,0x6b,
7978 0xf0,0x45,0xbd,0x50,0xa2,0x0f,0x8a,0x14,0x51,0x52,0x83,0x7c,
7979 0x47,0xc8,0x9c,0x4e,0x68,0x6b,0xae,0x00,0x25,0x63,0xdd,0x13,
7980 0x2a,0x66,0x65,0xb6,0x74,0x91,0x5b,0xb6,0x47,0x3e,0x8e,0x46,
7981 0x62,0xcd,0x9d,0xc1,0xf7,0x14,0x14,0xbc,0x60,0xd6,0x3c,0x7c,
7982 0x3a,0xce,0xff,0x96,0x04,0x84,0xf6,0x44,0x1a,0xf8,0xdb,0x40,
7983 0x1c,0xf2,0xf1,0x4d,0xb2,0x68,0x3e,0xa3,0x0b,0xc6,0xb1,0xd0,
7984 0xa6,0x88,0x18,0x68,0xa1,0x05,0x2a,0xfc,0x2b,0x3a,0xa1,0xe6,
7985 0x31,0x4a,0x46,0x88,0x39,0x1e,0x44,0x11,0x6c,0xc5,0x8b,0xb6,
7986 0x8b,0xce,0x3d,0xd5,0xcb,0xbd,0xf0,0xd4,0xd9,0xfb,0x02,0x35,
7987 0x96,0x39,0x26,0x85,0xf9 };
7988 static const BYTE rsaPrivKeyModulus[] = {
7989 0x43,0x55,0x9f,0x73,0x9a,0xb8,0x4f,0x8f,0x49,0xbe,0xf9,0x6c,
7990 0xbc,0xaa,0x20,0xc5,0xe7,0x49,0x25,0x03,0x50,0x0c,0x87,0x2d,
7991 0x63,0xf6,0xe7,0x81,0x5e,0x54,0x0f,0x36,0x24,0xfa,0x50,0x1c,
7992 0x86,0xfd,0x65,0x5a,0x75,0xcf,0xfd,0x9c,0xe1,0x85,0x09,0x47,
7993 0x62,0x40,0xe8,0xcb,0xf9,0xcb,0xdc,0xf0,0xf9,0x73,0x2b,0xe9,
7994 0xba,0x63,0xd6,0x23,0x2f,0xf1,0x86,0xf2,0xc5,0x54,0xd1,0x0e,
7995 0x5c,0x09,0xa8,0x77,0x8a,0xa9,0x1f,0xd5,0xb9,0x2c,0xf0,0xa7,
7996 0x76,0x20,0x53,0xff,0x17,0xa9,0x42,0xfc,0x1a,0x7c,0x74,0x4a,
7997 0x2e,0x41,0x3b,0x90,0x31,0x2b,0xd7,0xf2,0xa4,0x9c,0xaf,0x99,
7998 0xea,0x9a,0x58,0x4f,0xc0,0xe8,0x94,0xcc,0x44,0x61,0xe5,0xe2,
7999 0xe5,0x61,0xfe,0xb8,0xb0,0x42,0x7b,0x12,0x64,0x1d,0xfc,0xf6,
8000 0x0c,0xe6,0x08,0x65,0x01,0x76,0xda,0x7a,0x11,0x41,0x60,0x03,
8001 0xc2,0x14,0x93,0x0f,0xbb,0xc1,0x68,0x97,0xb7,0xfd,0x28,0x1e,
8002 0x84,0x61,0xe5,0xe1,0xd2,0x3d,0x85,0x91,0x3b,0x29,0x3a,0x36,
8003 0x9e,0xe2,0x73,0x62,0x3c,0xde,0x1a,0x7b,0xc9,0x0b,0x74,0x85,
8004 0x6c,0x27,0x68,0xd1,0x6c,0xf2,0x66,0x58,0xc7,0x2f,0xdd,0x11,
8005 0xba,0x76,0x55,0x7a,0x3b,0x1b,0xba,0xd1,0xbc,0x4a,0x3a,0x69,
8006 0x2d,0x32,0xdf,0x59,0x35,0xf2,0xe0,0x16,0xe0,0x91,0xd5,0xe1,
8007 0x3f,0xeb,0xe0,0x01,0x7a,0x3a,0xe4,0x06,0x39,0x45,0x3b,0x99,
8008 0x69,0xb0,0xfb,0x07,0x34,0xdf,0x90,0x9c,0x54,0x65,0x97,0x7e,
8009 0x64,0x31,0xf8,0xf9,0x26,0xd4,0x41,0x1c,0xb0,0x41,0x25,0xeb,
8010 0x41,0x3c,0xba,0xae };
8011 static const BYTE rsaPrivKeyPrime1[] = {
8012 0xe9,0x51,0xdb,0x33,0xb7,0xbf,0x8e,0xa7,0x20,0x74,0xd7,0x86,
8013 0xc5,0x3a,0x4a,0x16,0xd7,0x5e,0xed,0x3b,0xe7,0x77,0xb9,0xbf,
8014 0xd9,0xe2,0xb8,0xa6,0x2e,0xd9,0xd0,0x4e,0x53,0xbe,0x11,0x5d,
8015 0x52,0x3b,0xf0,0xca,0xe7,0x56,0xe7,0x20,0x02,0xd8,0x70,0x30,
8016 0xa8,0xc3,0x72,0xd1,0xce,0xdb,0x38,0x00,0x74,0x59,0xd2,0x2f,
8017 0xf8,0x31,0xe5,0x4d,0x6c,0xcf,0x25,0x6c,0x37,0x46,0x49,0xac,
8018 0xef,0x24,0xcd,0xc7,0x80,0x96,0xd5,0x22,0x47,0xe0,0xdf,0x33,
8019 0x0a,0x4a,0x53,0x3d,0x76,0xdb,0xf7,0x39,0x63,0x79,0xa3,0x0d,
8020 0xfa,0x8a,0x95,0xb0,0x98,0x62,0xb8,0x7f,0xc3,0xbe,0x68,0xa4,
8021 0x9f,0x7f,0x5f,0x1e,0x3b,0x48,0x7b,0x99,0x20,0xe0,0x5b,0xfc,
8022 0x4e,0xb6,0x76,0xed,0xdd,0xfe,0x5e,0xe3 };
8023 static const BYTE rsaPrivKeyPrime2[] = {
8024 0x4b,0xe6,0x2f,0xa5,0x08,0x3d,0xa9,0xf5,0x36,0x10,0x97,0x39,
8025 0xf3,0xc1,0xfb,0x86,0x48,0xaf,0x64,0xc6,0x9b,0x5f,0xe6,0xcf,
8026 0xb2,0x7b,0x39,0xa5,0x37,0x2c,0x61,0x1a,0x68,0xe2,0xe0,0xb0,
8027 0xfa,0x53,0xf1,0x7b,0x1d,0x3d,0x6b,0x70,0xa4,0x64,0x3a,0xe7,
8028 0xe1,0xe1,0xa0,0xaf,0x99,0x95,0xf2,0x4d,0x40,0x05,0x32,0xa4,
8029 0xab,0xac,0xee,0x97,0xca,0xa3,0xd6,0xe9,0xc0,0x9f,0x4d,0xb0,
8030 0xed,0x4a,0xe2,0x3a,0x29,0xe6,0xc3,0x2b,0xcd,0xa6,0xa9,0x87,
8031 0x7c,0xee,0x93,0x84,0x40,0xf2,0x40,0xae,0xc6,0x8e,0xd6,0x4a,
8032 0xaf,0xfc,0x5e,0x7d,0x9c,0x68,0x6f,0x18,0x72,0x1c,0x66,0x82,
8033 0x5d,0x66,0xaa,0x62,0x91,0xab,0xe1,0x0f,0xe9,0x4a,0x9d,0xce,
8034 0xce,0xe8,0xcf,0x6e,0xf0,0x57,0xba,0xc4 };
8035 static const BYTE rsaPrivKeyExponent1[] = {
8036 0xa1,0xca,0x03,0xc2,0xbc,0x0c,0x7b,0x61,0x6f,0x4e,0xf3,0xde,
8037 0x81,0xfb,0x44,0xa7,0x70,0xae,0xe8,0xb3,0x61,0x7a,0x86,0xac,
8038 0x7e,0xcd,0xf9,0xbc,0xe9,0x34,0x32,0x2d,0x7d,0x78,0x93,0xe2,
8039 0xac,0x87,0x45,0xe9,0xde,0x35,0x6d,0x8c,0xe0,0x16,0x09,0x9d,
8040 0x54,0xd9,0x49,0x62,0x73,0x5f,0xd7,0x5c,0x9a,0xba,0x80,0xef,
8041 0xbe,0xf5,0xda,0x9a,0x8c,0x03,0x79,0x9b,0xad,0x9e,0xff,0x0a,
8042 0x15,0x39,0x69,0xba,0x22,0x46,0xdd,0xbb,0x09,0xf9,0xa3,0x47,
8043 0x0b,0xae,0xce,0x10,0xac,0x22,0x86,0xb0,0x0a,0xf3,0x26,0x9f,
8044 0x98,0xa5,0x90,0xd4,0x94,0x0b,0xcb,0x76,0xa8,0xbf,0x26,0x76,
8045 0x01,0x5e,0x53,0x03,0x3e,0x30,0x29,0x39,0x67,0x9e,0x9f,0x54,
8046 0x93,0xa0,0xaf,0xe2,0x08,0x02,0xe7,0x86 };
8047 static const BYTE rsaPrivKeyExponent2[] = {
8048 0x85,0xfd,0x95,0x6b,0xb1,0x67,0x28,0x1d,0xe4,0xf1,0x20,0xbf,
8049 0x64,0x1d,0xf8,0x52,0xa2,0x4a,0x65,0xbd,0x98,0x55,0xf7,0x10,
8050 0x74,0x30,0x95,0x5a,0x7d,0xea,0x0a,0xc4,0xa5,0xf0,0x5a,0x5f,
8051 0xc3,0x50,0xb0,0x6b,0xa2,0x90,0xf6,0x3d,0xe6,0xfa,0xe3,0xc0,
8052 0xcb,0x14,0x6d,0xda,0x2b,0x96,0x86,0x26,0xb8,0xcb,0x2b,0xa6,
8053 0x21,0xbe,0x83,0x6a,0x5e,0xa3,0x15,0xfa,0xa5,0x7c,0xba,0xf5,
8054 0xc2,0xd9,0x51,0x3b,0x61,0x35,0xb0,0x12,0x92,0xaa,0xec,0xe6,
8055 0x52,0xf6,0x53,0xab,0x2c,0x76,0x10,0xfe,0x5d,0xd5,0xd4,0x96,
8056 0x05,0xe2,0xd9,0xae,0x22,0xb0,0x29,0x6a,0x80,0x88,0x17,0x5b,
8057 0x30,0x15,0xe6,0x20,0xab,0x19,0x11,0x48,0x1a,0x0d,0xf6,0x1b,
8058 0x9d,0x35,0x17,0x4f,0xa1,0x4a,0x5b,0x69 };
8059 static const BYTE rsaPrivKeyCoefficient[] = {
8060 0xf9,0x85,0x26,0x39,0x96,0x35,0x02,0xfb,0xd9,0xd4,0xf0,0xbd,
8061 0xcb,0xd5,0x3d,0xce,0x8b,0xb6,0x8b,0xc5,0x6c,0x11,0x44,0x1e,
8062 0x39,0x88,0x46,0x4a,0x31,0xe6,0xa1,0x3a,0x2b,0xfc,0x2a,0x05,
8063 0xa1,0x68,0x18,0x88,0xa6,0xd0,0xb1,0xc6,0x0b,0xa3,0x3e,0x68,
8064 0xb2,0x4d,0xf1,0xf2,0x1c,0x40,0xdb,0xf8,0x1a,0x44,0xf6,0x84,
8065 0x04,0x96,0xff,0xce,0x3a,0x7c,0x3c,0xd6,0x60,0xbc,0x14,0x14,
8066 0xf7,0xc1,0x9d,0xcd,0x62,0x46,0x8e,0x3e,0x47,0xb6,0x5b,0x91,
8067 0x74,0xb6,0x65,0x66,0x2a,0x13,0xdd,0x63,0x25,0x00,0xae,0x6b,
8068 0x68,0x4e,0x9c,0xc8,0x47,0x7c,0x83,0x52,0x51,0x14,0x8a,0x0f,
8069 0xa2,0x50,0xbd,0x45,0xf0,0x6b,0xbf,0x46,0x20,0xda,0xd7,0x07,
8070 0x1e,0x9a,0xec,0xe1,0x34,0x31,0xb4,0xda };
8071 static const BYTE rsaPrivKeyPrivateExponent[] = {
8072 0x11,0x90,0xb6,0x9f,0x62,0x9c,0x87,0x7e,0x9c,0x4c,0xbd,0x8c,
8073 0xf0,0xf8,0x2d,0x00,0x01,0x94,0xbc,0x68,0x39,0x13,0x3b,0x74,
8074 0x03,0x66,0xda,0xd2,0xde,0x79,0x96,0x61,0xba,0x6e,0x90,0xdf,
8075 0xed,0x25,0xdd,0x76,0xaa,0xfa,0x1d,0x15,0x65,0x99,0xba,0xf7,
8076 0x18,0xd5,0x15,0x85,0x33,0xf2,0xfd,0x60,0xb1,0x9f,0x66,0x9f,
8077 0x86,0x0c,0x69,0x06,0x5d,0x4c,0x5e,0xd8,0xf5,0x45,0x2d,0xf8,
8078 0x05,0x45,0xde,0xa4,0x71,0x58,0x81,0xce,0xe2,0xbb,0xb3,0x54,
8079 0x12,0xff,0x86,0x2d,0xd4,0xe5,0x03,0x90,0xa9,0x92,0xb9,0xe3,
8080 0x73,0xf2,0x69,0xbf,0xe2,0x75,0xab,0x59,0xfe,0x1b,0x48,0x8a,
8081 0xaf,0xdb,0xb0,0x7f,0x7e,0xb7,0x8c,0xfc,0x95,0x23,0x14,0x20,
8082 0x27,0x3d,0x74,0x4c,0x00,0xeb,0x23,0x20,0xc8,0x9c,0x2f,0x43,
8083 0x68,0x1d,0x97,0x02,0x15,0xcc,0xfc,0xde,0xda,0xe0,0x80,0xfd,
8084 0x95,0xbe,0xba,0xee,0xb3,0xd3,0xdc,0xd0,0xc2,0x63,0x16,0x40,
8085 0x97,0x04,0xa4,0xed,0x61,0x6d,0x37,0x03,0x84,0x00,0xb2,0x44,
8086 0x09,0x8b,0x6f,0xb3,0x44,0xac,0x54,0x66,0xf3,0x26,0x93,0xee,
8087 0xf7,0x91,0x76,0xa5,0x98,0xf8,0x3a,0x07,0x47,0x8b,0xdd,0x69,
8088 0x61,0x1f,0xdd,0x12,0x90,0x2e,0xe3,0xcd,0xc3,0xb7,0xc9,0x6d,
8089 0xfa,0xe8,0xa5,0x96,0x33,0x74,0xc9,0xc0,0x1f,0x3f,0x65,0xda,
8090 0x6f,0x12,0x75,0x17,0x8a,0xdb,0x4f,0x29,0xa2,0xfc,0x47,0x34,
8091 0x02,0xf6,0x86,0xcb,0x6a,0x74,0x9d,0x46,0x93,0x27,0x11,0x8c,
8092 0xef,0xd6,0xc9,0x2c,0x65,0x89,0xd6,0x78,0x98,0x32,0x03,0x69,
8093 0x5b,0xcd,0x03,0x99 };
8094
8095 static void test_decodeRsaPrivateKey(DWORD dwEncoding)
8096 {
8097 LPBYTE buf = NULL;
8098 DWORD bufSize = 0;
8099 BOOL ret;
8100
8101 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_RSA_PRIVATE_KEY,
8102 rsaPrivKeyDer, sizeof(rsaPrivKeyDer)-10,
8103 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
8104 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD),
8105 "Expected CRYPT_E_ASN1_EOD, got %08x\n",
8106 GetLastError());
8107
8108 buf = NULL;
8109 bufSize = 0;
8110 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_RSA_PRIVATE_KEY,
8111 rsaPrivKeyDer, sizeof(rsaPrivKeyDer),
8112 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
8113 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
8114
8115 if (ret)
8116 {
8117 BLOBHEADER *hdr = (BLOBHEADER *)buf;
8118 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
8119 static const int bitlen = 2048;
8120 BYTE *modulus = (BYTE*)(rsaPubKey + 1);
8121 BYTE *prime1 = modulus + bitlen/8;
8122 BYTE *prime2 = prime1 + bitlen/16;
8123 BYTE *exponent1 = prime2 + bitlen/16;
8124 BYTE *exponent2 = exponent1 + bitlen/16;
8125 BYTE *coefficient = exponent2 + bitlen/16;
8126 BYTE *privateExponent = coefficient + bitlen/16;
8127
8128 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
8129 (bitlen * 9 / 16),
8130 "Wrong size %d\n", bufSize);
8131
8132 ok(hdr->bType == PRIVATEKEYBLOB,
8133 "Expected type PRIVATEKEYBLOB (%d), got %d\n", PRIVATEKEYBLOB,
8134 hdr->bType);
8135 ok(hdr->bVersion == CUR_BLOB_VERSION,
8136 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
8137 CUR_BLOB_VERSION, hdr->bVersion);
8138 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
8139 hdr->reserved);
8140 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
8141 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
8142
8143 ok(rsaPubKey->magic == 0x32415352,
8144 "Expected magic 0x32415352, got 0x%x\n", rsaPubKey->magic);
8145 ok(rsaPubKey->bitlen == bitlen,
8146 "Expected bitlen %d, got %d\n", bitlen, rsaPubKey->bitlen);
8147 ok(rsaPubKey->pubexp == 65537,
8148 "Expected pubexp 65537, got %d\n", rsaPubKey->pubexp);
8149
8150 ok(!memcmp(modulus, rsaPrivKeyModulus, bitlen/8),
8151 "unexpected modulus\n");
8152 ok(!memcmp(prime1, rsaPrivKeyPrime1, bitlen/16),
8153 "unexpected prime1\n");
8154 ok(!memcmp(prime2, rsaPrivKeyPrime2, bitlen/16),
8155 "unexpected prime2\n");
8156 ok(!memcmp(exponent1, rsaPrivKeyExponent1, bitlen/16),
8157 "unexpected exponent1\n");
8158 ok(!memcmp(exponent2, rsaPrivKeyExponent2, bitlen/16),
8159 "unexpected exponent2\n");
8160 ok(!memcmp(coefficient, rsaPrivKeyCoefficient, bitlen/16),
8161 "unexpected coefficient\n");
8162 ok(!memcmp(privateExponent, rsaPrivKeyPrivateExponent, bitlen/8),
8163 "unexpected privateExponent\n");
8164
8165 LocalFree(buf);
8166 }
8167 }
8168
8169 /* Free *pInfo with HeapFree */
8170 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
8171 {
8172 BOOL ret;
8173 DWORD size = 0;
8174 HCRYPTKEY key;
8175
8176 /* This crashes
8177 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
8178 */
8179 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
8180 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8181 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8182 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
8183 &size);
8184 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8185 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8186 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
8187 NULL, &size);
8188 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8189 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8190 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
8191 0, NULL, NULL, &size);
8192 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8193 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8194 /* Test with no key */
8195 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
8196 0, NULL, NULL, &size);
8197 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
8198 GetLastError());
8199 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
8200 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
8201 if (ret)
8202 {
8203 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
8204 NULL, 0, NULL, NULL, &size);
8205 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
8206 *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
8207 if (*pInfo)
8208 {
8209 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
8210 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
8211 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
8212 GetLastError());
8213 if (ret)
8214 {
8215 /* By default (we passed NULL as the OID) the OID is
8216 * szOID_RSA_RSA.
8217 */
8218 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
8219 "Expected %s, got %s\n", szOID_RSA_RSA,
8220 (*pInfo)->Algorithm.pszObjId);
8221 }
8222 }
8223 }
8224 CryptDestroyKey(key);
8225 }
8226
8227 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
8228 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
8229 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
8230 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
8231 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
8232 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
8233 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
8234 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
8235 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
8236 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
8237 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
8238 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
8239 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
8240 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
8241 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
8242 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
8243 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
8244 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
8245 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
8246 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
8247 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
8248 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
8249 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
8250 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
8251 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
8252
8253 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
8254 {
8255 BOOL ret;
8256 HCRYPTKEY key;
8257 PCCERT_CONTEXT context;
8258 DWORD dwSize;
8259 ALG_ID ai;
8260
8261 /* These crash
8262 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
8263 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
8264 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
8265 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
8266 NULL);
8267 */
8268 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
8269 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
8270 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
8271 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
8272 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
8273 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
8274 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
8275 &key);
8276 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
8277 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
8278
8279 /* Export key with standard algorithm (CALG_RSA_KEYX) */
8280 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
8281 &key);
8282 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8283
8284 dwSize = sizeof(ai);
8285 CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
8286 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
8287 if(ret)
8288 {
8289 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
8290 ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
8291 }
8292
8293 CryptDestroyKey(key);
8294
8295 /* Repeat with forced algorithm */
8296 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
8297 &key);
8298 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8299
8300 dwSize = sizeof(ai);
8301 CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
8302 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
8303 if(ret)
8304 {
8305 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
8306 ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
8307 }
8308
8309 CryptDestroyKey(key);
8310
8311 /* Test importing a public key from a certificate context */
8312 context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
8313 sizeof(expiredCert));
8314 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
8315 GetLastError());
8316 if (context)
8317 {
8318 ok(!strcmp(szOID_RSA_RSA,
8319 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
8320 "Expected %s, got %s\n", szOID_RSA_RSA,
8321 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
8322 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
8323 &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
8324 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8325 CryptDestroyKey(key);
8326 CertFreeCertificateContext(context);
8327 }
8328 }
8329
8330 static const char cspName[] = "WineCryptTemp";
8331
8332 static void testPortPublicKeyInfo(void)
8333 {
8334 HCRYPTPROV csp;
8335 BOOL ret;
8336 PCERT_PUBLIC_KEY_INFO info = NULL;
8337
8338 /* Just in case a previous run failed, delete this thing */
8339 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV_A, PROV_RSA_FULL,
8340 CRYPT_DELETEKEYSET);
8341 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV_A, PROV_RSA_FULL,
8342 CRYPT_NEWKEYSET);
8343 ok(ret,"CryptAcquireContextA failed\n");
8344
8345 testExportPublicKey(csp, &info);
8346 testImportPublicKey(csp, info);
8347
8348 HeapFree(GetProcessHeap(), 0, info);
8349 CryptReleaseContext(csp, 0);
8350 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV_A, PROV_RSA_FULL,
8351 CRYPT_DELETEKEYSET);
8352 ok(ret,"CryptAcquireContextA failed\n");
8353 }
8354
8355 START_TEST(encode)
8356 {
8357 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
8358 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
8359 HMODULE hCrypt32;
8360 DWORD i;
8361
8362 hCrypt32 = GetModuleHandleA("crypt32.dll");
8363 pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
8364 pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
8365 if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
8366 {
8367 win_skip("CryptDecodeObjectEx() is not available\n");
8368 return;
8369 }
8370
8371 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
8372 {
8373 test_encodeInt(encodings[i]);
8374 test_decodeInt(encodings[i]);
8375 test_encodeEnumerated(encodings[i]);
8376 test_decodeEnumerated(encodings[i]);
8377 test_encodeFiletime(encodings[i]);
8378 test_decodeFiletime(encodings[i]);
8379 test_encodeName(encodings[i]);
8380 test_decodeName(encodings[i]);
8381 test_encodeUnicodeName(encodings[i]);
8382 test_decodeUnicodeName(encodings[i]);
8383 test_encodeNameValue(encodings[i]);
8384 test_decodeNameValue(encodings[i]);
8385 test_encodeUnicodeNameValue(encodings[i]);
8386 test_decodeUnicodeNameValue(encodings[i]);
8387 test_encodeAltName(encodings[i]);
8388 test_decodeAltName(encodings[i]);
8389 test_encodeOctets(encodings[i]);
8390 test_decodeOctets(encodings[i]);
8391 test_encodeBits(encodings[i]);
8392 test_decodeBits(encodings[i]);
8393 test_encodeBasicConstraints(encodings[i]);
8394 test_decodeBasicConstraints(encodings[i]);
8395 test_encodeRsaPublicKey(encodings[i]);
8396 test_decodeRsaPublicKey(encodings[i]);
8397 test_encodeSequenceOfAny(encodings[i]);
8398 test_decodeSequenceOfAny(encodings[i]);
8399 test_encodeExtensions(encodings[i]);
8400 test_decodeExtensions(encodings[i]);
8401 test_encodePublicKeyInfo(encodings[i]);
8402 test_decodePublicKeyInfo(encodings[i]);
8403 test_encodeCertToBeSigned(encodings[i]);
8404 test_decodeCertToBeSigned(encodings[i]);
8405 test_encodeCert(encodings[i]);
8406 test_decodeCert(encodings[i]);
8407 test_encodeCRLDistPoints(encodings[i]);
8408 test_decodeCRLDistPoints(encodings[i]);
8409 test_encodeCRLIssuingDistPoint(encodings[i]);
8410 test_decodeCRLIssuingDistPoint(encodings[i]);
8411 test_encodeCRLToBeSigned(encodings[i]);
8412 test_decodeCRLToBeSigned(encodings[i]);
8413 test_encodeEnhancedKeyUsage(encodings[i]);
8414 test_decodeEnhancedKeyUsage(encodings[i]);
8415 test_encodeAuthorityKeyId(encodings[i]);
8416 test_decodeAuthorityKeyId(encodings[i]);
8417 test_encodeAuthorityKeyId2(encodings[i]);
8418 test_decodeAuthorityKeyId2(encodings[i]);
8419 test_encodeAuthorityInfoAccess(encodings[i]);
8420 test_decodeAuthorityInfoAccess(encodings[i]);
8421 test_encodeCTL(encodings[i]);
8422 test_decodeCTL(encodings[i]);
8423 test_encodePKCSContentInfo(encodings[i]);
8424 test_decodePKCSContentInfo(encodings[i]);
8425 test_encodePKCSAttribute(encodings[i]);
8426 test_decodePKCSAttribute(encodings[i]);
8427 test_encodePKCSAttributes(encodings[i]);
8428 test_decodePKCSAttributes(encodings[i]);
8429 test_encodePKCSSMimeCapabilities(encodings[i]);
8430 test_decodePKCSSMimeCapabilities(encodings[i]);
8431 test_encodePKCSSignerInfo(encodings[i]);
8432 test_decodePKCSSignerInfo(encodings[i]);
8433 test_encodeCMSSignerInfo(encodings[i]);
8434 test_decodeCMSSignerInfo(encodings[i]);
8435 test_encodeNameConstraints(encodings[i]);
8436 test_decodeNameConstraints(encodings[i]);
8437 test_encodePolicyQualifierUserNotice(encodings[i]);
8438 test_decodePolicyQualifierUserNotice(encodings[i]);
8439 test_encodeCertPolicies(encodings[i]);
8440 test_decodeCertPolicies(encodings[i]);
8441 test_encodeCertPolicyMappings(encodings[i]);
8442 test_decodeCertPolicyMappings(encodings[i]);
8443 test_encodeCertPolicyConstraints(encodings[i]);
8444 test_decodeCertPolicyConstraints(encodings[i]);
8445 test_decodeRsaPrivateKey(encodings[i]);
8446 }
8447 testPortPublicKeyInfo();
8448 }