2 * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
4 * Copyright 2005 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/test.h"
35 static const BYTE bin1[] = {0x02,0x01,0x01};
36 static const BYTE bin2[] = {0x02,0x01,0x7f};
37 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
38 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
39 static const BYTE bin5[] = {0x02,0x01,0x80};
40 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
41 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
43 static const struct encodedInt ints[] = {
60 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
61 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
62 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
64 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
65 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
66 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
68 static const struct encodedBigInt bigInts[] = {
69 { bin8, bin9, bin10 },
70 { bin11, bin12, bin13 },
73 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
74 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
75 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
76 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
78 /* Decoded is the same as original, so don't bother storing a separate copy */
79 static const struct encodedBigInt bigUInts[] = {
80 { bin14, bin15, NULL },
81 { bin16, bin17, NULL },
84 static void test_encodeInt(DWORD dwEncoding)
89 CRYPT_INTEGER_BLOB blob;
92 /* CryptEncodeObjectEx with NULL bufSize crashes..
93 ret = CryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
96 /* check bogus encoding */
97 ret = CryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
99 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
100 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
101 /* check with NULL integer buffer. Windows XP incorrectly returns an
104 ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
106 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
107 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
108 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
110 /* encode as normal integer */
111 ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
112 NULL, NULL, &bufSize);
113 ok(ret, "Expected success, got %d\n", GetLastError());
114 ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
115 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
116 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
119 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
121 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
122 buf[1], ints[i].encoded[1]);
123 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
124 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
127 /* encode as multibyte integer */
128 blob.cbData = sizeof(ints[i].val);
129 blob.pbData = (BYTE *)&ints[i].val;
130 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
131 0, NULL, NULL, &bufSize);
132 ok(ret, "Expected success, got %d\n", GetLastError());
133 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
134 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
135 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
138 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
140 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
141 buf[1], ints[i].encoded[1]);
142 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
143 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
147 /* encode a couple bigger ints, just to show it's little-endian and leading
148 * sign bytes are dropped
150 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
152 blob.cbData = strlen((const char*)bigInts[i].val);
153 blob.pbData = (BYTE *)bigInts[i].val;
154 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
155 0, NULL, NULL, &bufSize);
156 ok(ret, "Expected success, got %d\n", GetLastError());
157 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
158 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
159 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
162 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
164 ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
165 buf[1], bigInts[i].encoded[1]);
166 ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
167 bigInts[i].encoded[1] + 1),
168 "Encoded value didn't match expected\n");
172 /* and, encode some uints */
173 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
175 blob.cbData = strlen((const char*)bigUInts[i].val);
176 blob.pbData = (BYTE*)bigUInts[i].val;
177 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
178 0, NULL, NULL, &bufSize);
179 ok(ret, "Expected success, got %d\n", GetLastError());
180 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
181 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
182 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
185 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
187 ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
188 buf[1], bigUInts[i].encoded[1]);
189 ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
190 bigUInts[i].encoded[1] + 1),
191 "Encoded value didn't match expected\n");
197 static void test_decodeInt(DWORD dwEncoding)
199 static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
200 static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
201 static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
202 static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
208 /* CryptDecodeObjectEx with NULL bufSize crashes..
209 ret = CryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
210 ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
212 /* check bogus encoding */
213 ret = CryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
214 ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
215 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
216 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
217 /* check with NULL integer buffer */
218 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
220 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
221 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
222 /* check with a valid, but too large, integer */
223 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
224 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
225 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
226 "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
227 /* check with a DER-encoded string */
228 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
229 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
230 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
231 "Expected CRYPT_E_ASN1_BADTAG, got %d\n", GetLastError());
232 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
234 /* When the output buffer is NULL, this always succeeds */
235 SetLastError(0xdeadbeef);
236 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
237 ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
239 ok(ret && GetLastError() == NOERROR,
240 "Expected success and NOERROR, got %d\n", GetLastError());
241 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
242 ints[i].encoded, ints[i].encoded[1] + 2,
243 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
244 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
245 ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
246 ok(buf != NULL, "Expected allocated buffer\n");
249 ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
250 ints[i].val, *(int *)buf);
254 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
256 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
257 bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
259 ok(ret && GetLastError() == NOERROR,
260 "Expected success and NOERROR, got %d\n", GetLastError());
261 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
262 bigInts[i].encoded, bigInts[i].encoded[1] + 2,
263 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
264 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
265 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
266 ok(buf != NULL, "Expected allocated buffer\n");
269 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
271 ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
272 "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
274 ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
275 "Unexpected value\n");
279 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
281 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
282 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
284 ok(ret && GetLastError() == NOERROR,
285 "Expected success and NOERROR, got %d\n", GetLastError());
286 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
287 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
288 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
289 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
290 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
291 ok(buf != NULL, "Expected allocated buffer\n");
294 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
296 ok(blob->cbData == strlen((const char*)bigUInts[i].val),
297 "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
299 ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
300 "Unexpected value\n");
304 /* Decode the value 1 with long-form length */
305 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
306 sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
307 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
310 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
313 /* Try to decode some bogus large items */
314 /* The buffer size is smaller than the encoded length, so this should fail
315 * with CRYPT_E_ASN1_EOD if it's being decoded.
316 * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
317 * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
318 * So this test unfortunately isn't useful.
319 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
320 0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
321 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
322 "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
324 /* This will try to decode the buffer and overflow it, check that it's
329 /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
330 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
331 0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
332 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
333 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
337 static const BYTE bin18[] = {0x0a,0x01,0x01};
338 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
340 /* These are always encoded unsigned, and aren't constrained to be any
343 static const struct encodedInt enums[] = {
348 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
351 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
352 szOID_CRL_REASON_CODE };
354 static void test_encodeEnumerated(DWORD dwEncoding)
358 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
360 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
366 ret = CryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
367 &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
369 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
373 "Got unexpected type %d for enumerated (expected 0xa)\n",
375 ok(buf[1] == enums[j].encoded[1],
376 "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
377 ok(!memcmp(buf + 1, enums[j].encoded + 1,
378 enums[j].encoded[1] + 1),
379 "Encoded value of 0x%08x didn't match expected\n",
387 static void test_decodeEnumerated(DWORD dwEncoding)
391 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
393 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
396 DWORD bufSize = sizeof(int);
399 ret = CryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
400 enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
401 (BYTE *)&val, &bufSize);
402 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
403 ok(bufSize == sizeof(int),
404 "Got unexpected size %d for enumerated\n", bufSize);
405 ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
411 struct encodedFiletime
414 const BYTE *encodedTime;
417 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
418 const struct encodedFiletime *time)
425 ret = SystemTimeToFileTime(&time->sysTime, &ft);
426 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
427 ret = CryptEncodeObjectEx(dwEncoding, structType, &ft,
428 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
429 /* years other than 1950-2050 are not allowed for encodings other than
430 * X509_CHOICE_OF_TIME.
432 if (structType == X509_CHOICE_OF_TIME ||
433 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
435 ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
437 ok(buf != NULL, "Expected an allocated buffer\n");
440 ok(buf[0] == time->encodedTime[0],
441 "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
443 ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
444 time->encodedTime[1], bufSize);
445 ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
446 "Got unexpected value for time encoding\n");
451 ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
452 "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
455 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
456 const struct encodedFiletime *time)
458 FILETIME ft1 = { 0 }, ft2 = { 0 };
459 DWORD size = sizeof(ft2);
462 ret = SystemTimeToFileTime(&time->sysTime, &ft1);
463 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
464 ret = CryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
465 time->encodedTime[1] + 2, 0, NULL, &ft2, &size);
466 /* years other than 1950-2050 are not allowed for encodings other than
467 * X509_CHOICE_OF_TIME.
469 if (structType == X509_CHOICE_OF_TIME ||
470 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
472 ok(ret, "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
474 ok(!memcmp(&ft1, &ft2, sizeof(ft1)),
475 "Got unexpected value for time decoding\n");
478 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
479 "Expected CRYPT_E_ASN1_BADTAG, got 0x%08x\n", GetLastError());
482 static const BYTE bin20[] = {
483 0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
484 static const BYTE bin21[] = {
485 0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
486 static const BYTE bin22[] = {
487 0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
489 static const struct encodedFiletime times[] = {
490 { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
491 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
492 { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
495 static void test_encodeFiletime(DWORD dwEncoding)
499 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
501 testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, ×[i]);
502 testTimeEncoding(dwEncoding, PKCS_UTC_TIME, ×[i]);
503 testTimeEncoding(dwEncoding, szOID_RSA_signingTime, ×[i]);
507 static const BYTE bin23[] = {
508 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
509 static const BYTE bin24[] = {
510 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
511 static const BYTE bin25[] = {
512 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
513 static const BYTE bin26[] = {
514 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
515 static const BYTE bin27[] = {
516 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
517 static const BYTE bin28[] = {
518 0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
519 static const BYTE bin29[] = {
520 0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
521 static const BYTE bin30[] = {
522 0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
523 static const BYTE bin31[] = {
524 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
525 static const BYTE bin32[] = {
526 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
527 static const BYTE bin33[] = {
528 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
529 static const BYTE bin34[] = {
530 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
531 static const BYTE bin35[] = {
532 0x17,0x08, '4','5','0','6','0','6','1','6'};
533 static const BYTE bin36[] = {
534 0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
535 static const BYTE bin37[] = {
536 0x18,0x04, '2','1','4','5'};
537 static const BYTE bin38[] = {
538 0x18,0x08, '2','1','4','5','0','6','0','6'};
540 static void test_decodeFiletime(DWORD dwEncoding)
542 static const struct encodedFiletime otherTimes[] = {
543 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin23 },
544 { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
545 { { 1945, 6, 1, 6, 17, 10, 0, 0 }, bin25 },
546 { { 1945, 6, 1, 6, 15, 10, 0, 0 }, bin26 },
547 { { 1945, 6, 1, 6, 14, 55, 0, 0 }, bin27 },
548 { { 2145, 6, 1, 6, 16, 0, 0, 0 }, bin28 },
549 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin29 },
550 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin30 },
551 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin31 },
552 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin32 },
553 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin33 },
554 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin34 },
556 /* An oddball case that succeeds in Windows, but doesn't seem correct
557 { { 2145, 6, 1, 2, 11, 31, 0, 0 }, "\x18" "\x13" "21450606161000-9999" },
559 static const unsigned char *bogusTimes[] = {
560 /* oddly, this succeeds on Windows, with year 2765
561 "\x18" "\x0f" "21r50606161000Z",
569 FILETIME ft1 = { 0 }, ft2 = { 0 };
572 /* Check bogus length with non-NULL buffer */
573 ret = SystemTimeToFileTime(×[0].sysTime, &ft1);
574 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
576 ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
577 times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
578 ok(!ret && GetLastError() == ERROR_MORE_DATA,
579 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
581 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
583 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, ×[i]);
584 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, ×[i]);
585 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, ×[i]);
587 for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
589 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
590 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
591 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
593 for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
596 ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
597 bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
598 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
599 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
603 static const char commonName[] = "Juan Lang";
604 static const char surName[] = "Lang";
606 static const BYTE emptySequence[] = { 0x30, 0 };
607 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
608 static const BYTE twoRDNs[] = {
609 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
610 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
611 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
612 static const BYTE encodedTwoRDNs[] = {
613 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
614 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
615 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
619 static const BYTE us[] = { 0x55, 0x53 };
620 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
622 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
623 0x6f, 0x6c, 0x69, 0x73 };
624 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
625 0x76, 0x65, 0x72, 0x73 };
626 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
627 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
628 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
630 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
631 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
633 #define RDNA(arr) oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
634 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING, { sizeof(arr), (LPBYTE)arr }
636 static CHAR oid_us[] = "2.5.4.6",
637 oid_minnesota[] = "2.5.4.8",
638 oid_minneapolis[] = "2.5.4.7",
639 oid_codeweavers[] = "2.5.4.10",
640 oid_wine[] = "2.5.4.11",
641 oid_localhostAttr[] = "2.5.4.3",
642 oid_aric[] = "1.2.840.113549.1.9.1";
643 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
645 { RDNA(minneapolis) },
646 { RDNA(codeweavers) },
648 { RDNA(localhostAttr) },
650 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
651 { RDNA(localhostAttr) },
653 { RDNA(minneapolis) },
654 { RDNA(codeweavers) },
661 static const BYTE encodedRDNAttrs[] = {
662 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
663 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
664 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
665 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
666 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
667 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
668 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
669 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
670 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
671 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
674 static void test_encodeName(DWORD dwEncoding)
676 CERT_RDN_ATTR attrs[2];
679 static CHAR oid_common_name[] = szOID_COMMON_NAME,
680 oid_sur_name[] = szOID_SUR_NAME;
685 /* Test with NULL pvStructInfo */
686 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
687 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
688 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
689 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
690 /* Test with empty CERT_NAME_INFO */
693 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
694 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
695 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
698 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
699 "Got unexpected encoding for empty name\n");
702 /* Test with bogus CERT_RDN */
704 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
705 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
706 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
707 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
708 /* Test with empty CERT_RDN */
710 rdn.rgRDNAttr = NULL;
713 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
714 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
715 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
718 ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
719 "Got unexpected encoding for empty RDN array\n");
722 /* Test with bogus attr array */
724 rdn.rgRDNAttr = NULL;
725 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
726 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
727 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
728 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
729 /* oddly, a bogus OID is accepted by Windows XP; not testing.
730 attrs[0].pszObjId = "bogus";
731 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
732 attrs[0].Value.cbData = sizeof(commonName);
733 attrs[0].Value.pbData = (BYTE *)commonName;
735 rdn.rgRDNAttr = attrs;
736 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
737 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
738 ok(!ret, "Expected failure, got success\n");
740 /* Check with two CERT_RDN_ATTRs. Note DER encoding forces the order of
741 * the encoded attributes to be swapped.
743 attrs[0].pszObjId = oid_common_name;
744 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
745 attrs[0].Value.cbData = sizeof(commonName);
746 attrs[0].Value.pbData = (BYTE *)commonName;
747 attrs[1].pszObjId = oid_sur_name;
748 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
749 attrs[1].Value.cbData = sizeof(surName);
750 attrs[1].Value.pbData = (BYTE *)surName;
752 rdn.rgRDNAttr = attrs;
753 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
754 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
755 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
758 ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
759 "Got unexpected encoding for two RDN array\n");
762 /* A name can be "encoded" with previously encoded RDN attrs. */
763 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
764 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
765 attrs[0].Value.cbData = sizeof(twoRDNs);
767 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
768 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
769 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
772 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
773 ok(!memcmp(buf, encodedTwoRDNs, size),
774 "Unexpected value for re-endoded two RDN array\n");
777 /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
779 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
780 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
781 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
782 ok(!ret && GetLastError() == E_INVALIDARG,
783 "Expected E_INVALIDARG, got %08x\n", GetLastError());
784 /* Test a more complex name */
785 rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
786 rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
791 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
792 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
793 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
796 ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
797 ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
802 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
803 static WCHAR surNameW[] = { 'L','a','n','g',0 };
805 static const BYTE twoRDNsNoNull[] = {
806 0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
807 0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
808 0x20,0x4c,0x61,0x6e,0x67 };
809 static const BYTE anyType[] = {
810 0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
811 0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
812 0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
813 0x61,0x4c,0x67,0x6e };
815 static void test_encodeUnicodeName(DWORD dwEncoding)
817 CERT_RDN_ATTR attrs[2];
820 static CHAR oid_common_name[] = szOID_COMMON_NAME,
821 oid_sur_name[] = szOID_SUR_NAME;
826 /* Test with NULL pvStructInfo */
827 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
828 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
829 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
830 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
831 /* Test with empty CERT_NAME_INFO */
834 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
835 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
836 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
839 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
840 "Got unexpected encoding for empty name\n");
843 /* Check with one CERT_RDN_ATTR, that has an invalid character for the
844 * encoding (the NULL).
846 attrs[0].pszObjId = oid_common_name;
847 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
848 attrs[0].Value.cbData = sizeof(commonNameW);
849 attrs[0].Value.pbData = (BYTE *)commonNameW;
851 rdn.rgRDNAttr = attrs;
854 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
855 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
856 ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
857 "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
858 ok(size == 9, "Unexpected error index %08x\n", size);
859 /* Check with two NULL-terminated CERT_RDN_ATTRs. Note DER encoding
860 * forces the order of the encoded attributes to be swapped.
862 attrs[0].pszObjId = oid_common_name;
863 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
864 attrs[0].Value.cbData = 0;
865 attrs[0].Value.pbData = (BYTE *)commonNameW;
866 attrs[1].pszObjId = oid_sur_name;
867 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
868 attrs[1].Value.cbData = 0;
869 attrs[1].Value.pbData = (BYTE *)surNameW;
871 rdn.rgRDNAttr = attrs;
874 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
875 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
876 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
879 ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
880 "Got unexpected encoding for two RDN array\n");
883 /* A name can be "encoded" with previously encoded RDN attrs. */
884 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
885 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
886 attrs[0].Value.cbData = sizeof(twoRDNs);
888 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
889 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
890 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
893 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
894 ok(!memcmp(buf, encodedTwoRDNs, size),
895 "Unexpected value for re-endoded two RDN array\n");
898 /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
900 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
901 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
902 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
903 todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
906 ok(size == sizeof(anyType), "Unexpected size %d\n", size);
907 ok(!memcmp(buf, anyType, size), "Unexpected value\n");
912 static void compareNameValues(const CERT_NAME_VALUE *expected,
913 const CERT_NAME_VALUE *got)
915 ok(got->dwValueType == expected->dwValueType,
916 "Expected string type %d, got %d\n", expected->dwValueType,
918 ok(got->Value.cbData == expected->Value.cbData,
919 "String type %d: unexpected data size, got %d, expected %d\n",
920 expected->dwValueType, got->Value.cbData, expected->Value.cbData);
921 if (got->Value.cbData && got->Value.pbData)
922 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
923 min(got->Value.cbData, expected->Value.cbData)),
924 "String type %d: unexpected value\n", expected->dwValueType);
927 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
928 const CERT_RDN_ATTR *got)
930 if (expected->pszObjId && strlen(expected->pszObjId))
932 ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
936 ok(!strcmp(got->pszObjId, expected->pszObjId),
937 "Got unexpected OID %s, expected %s\n", got->pszObjId,
941 compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
942 (const CERT_NAME_VALUE *)&got->dwValueType);
945 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
947 ok(got->cRDNAttr == expected->cRDNAttr,
948 "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
953 for (i = 0; i < got->cRDNAttr; i++)
954 compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
958 static void compareNames(const CERT_NAME_INFO *expected,
959 const CERT_NAME_INFO *got)
961 ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
962 expected->cRDN, got->cRDN);
967 for (i = 0; i < got->cRDN; i++)
968 compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
972 static void test_decodeName(DWORD dwEncoding)
978 CERT_NAME_INFO info = { 1, &rdn };
980 /* test empty name */
982 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
983 emptySequence[1] + 2,
984 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
985 (BYTE *)&buf, &bufSize);
986 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
987 /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL. My
988 * decoder works the same way, so only test the count.
992 ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
993 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
994 "Expected 0 RDNs in empty info, got %d\n",
995 ((CERT_NAME_INFO *)buf)->cRDN);
1000 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1002 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1003 (BYTE *)&buf, &bufSize);
1004 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1007 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1009 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1010 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1011 "Got unexpected value for empty RDN\n");
1014 /* test two RDN attrs */
1016 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1018 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1019 (BYTE *)&buf, &bufSize);
1020 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1023 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1024 oid_common_name[] = szOID_COMMON_NAME;
1026 CERT_RDN_ATTR attrs[] = {
1027 { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1028 (BYTE *)surName } },
1029 { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1030 (BYTE *)commonName } },
1033 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1034 rdn.rgRDNAttr = attrs;
1035 compareNames(&info, (CERT_NAME_INFO *)buf);
1038 /* And, a slightly more complicated name */
1041 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1042 sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1043 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1046 rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1047 rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
1048 compareNames(&info, (CERT_NAME_INFO *)buf);
1053 static void test_decodeUnicodeName(DWORD dwEncoding)
1059 CERT_NAME_INFO info = { 1, &rdn };
1061 /* test empty name */
1063 ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1064 emptySequence[1] + 2,
1065 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1066 (BYTE *)&buf, &bufSize);
1067 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1070 ok(bufSize == sizeof(CERT_NAME_INFO),
1071 "Got wrong bufSize %d\n", bufSize);
1072 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1073 "Expected 0 RDNs in empty info, got %d\n",
1074 ((CERT_NAME_INFO *)buf)->cRDN);
1077 /* test empty RDN */
1079 ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1081 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1082 (BYTE *)&buf, &bufSize);
1083 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1086 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1088 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1089 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1090 "Got unexpected value for empty RDN\n");
1093 /* test two RDN attrs */
1095 ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1096 sizeof(twoRDNsNoNull),
1097 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1098 (BYTE *)&buf, &bufSize);
1099 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1102 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1103 oid_common_name[] = szOID_COMMON_NAME;
1105 CERT_RDN_ATTR attrs[] = {
1106 { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1107 { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1108 { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1109 { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1112 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1113 rdn.rgRDNAttr = attrs;
1114 compareNames(&info, (CERT_NAME_INFO *)buf);
1119 struct EncodedNameValue
1121 CERT_NAME_VALUE value;
1122 const BYTE *encoded;
1126 static const char bogusIA5[] = "\x80";
1127 static const char bogusPrintable[] = "~";
1128 static const char bogusNumeric[] = "A";
1129 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1130 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1131 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1132 static BYTE octetCommonNameValue[] = {
1133 0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1134 static BYTE numericCommonNameValue[] = {
1135 0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1136 static BYTE printableCommonNameValue[] = {
1137 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1138 static BYTE t61CommonNameValue[] = {
1139 0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1140 static BYTE videotexCommonNameValue[] = {
1141 0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1142 static BYTE ia5CommonNameValue[] = {
1143 0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1144 static BYTE graphicCommonNameValue[] = {
1145 0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1146 static BYTE visibleCommonNameValue[] = {
1147 0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1148 static BYTE generalCommonNameValue[] = {
1149 0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1150 static BYTE bmpCommonNameValue[] = {
1151 0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1152 0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1153 static BYTE utf8CommonNameValue[] = {
1154 0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1156 static struct EncodedNameValue nameValues[] = {
1157 { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1158 octetCommonNameValue, sizeof(octetCommonNameValue) },
1159 { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1160 numericCommonNameValue, sizeof(numericCommonNameValue) },
1161 { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1162 printableCommonNameValue, sizeof(printableCommonNameValue) },
1163 { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1164 t61CommonNameValue, sizeof(t61CommonNameValue) },
1165 { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1166 videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1167 { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1168 ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1169 { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1170 graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1171 { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1172 visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1173 { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1174 generalCommonNameValue, sizeof(generalCommonNameValue) },
1175 { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1176 bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1177 { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1178 utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1179 /* The following tests succeed under Windows, but really should fail,
1180 * they contain characters that are illegal for the encoding. I'm
1181 * including them to justify my lazy encoding.
1183 { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1185 { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1186 (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1187 { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1188 bin44, sizeof(bin44) },
1191 static void test_encodeNameValue(DWORD dwEncoding)
1196 CERT_NAME_VALUE value = { 0, { 0, NULL } };
1198 value.dwValueType = 14;
1199 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1200 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1201 ok(!ret && GetLastError() == CRYPT_E_ASN1_CHOICE,
1202 "Expected CRYPT_E_ASN1_CHOICE, got %08x\n", GetLastError());
1203 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1204 value.Value.pbData = printableCommonNameValue;
1205 value.Value.cbData = sizeof(printableCommonNameValue);
1206 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1207 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1208 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1211 ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1213 ok(!memcmp(buf, printableCommonNameValue, size),
1214 "Unexpected encoding\n");
1217 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1219 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1220 &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1222 ok(ret, "Type %d: CryptEncodeObjectEx failed: %08x\n",
1223 nameValues[i].value.dwValueType, GetLastError());
1226 ok(size == nameValues[i].encodedSize,
1227 "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1228 ok(!memcmp(buf, nameValues[i].encoded, size),
1229 "Got unexpected encoding\n");
1235 static void test_decodeNameValue(DWORD dwEncoding)
1242 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1244 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1245 nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1246 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1247 (BYTE *)&buf, &bufSize);
1248 ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1249 nameValues[i].value.dwValueType, GetLastError());
1252 compareNameValues(&nameValues[i].value,
1253 (const CERT_NAME_VALUE *)buf);
1259 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1260 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1261 'h','q','.','o','r','g',0 };
1262 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1263 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1265 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1267 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1268 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1269 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1270 static const BYTE localhost[] = { 127, 0, 0, 1 };
1271 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1274 static void test_encodeAltName(DWORD dwEncoding)
1276 CERT_ALT_NAME_INFO info = { 0 };
1277 CERT_ALT_NAME_ENTRY entry = { 0 };
1282 /* Test with empty info */
1283 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1284 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1287 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1288 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1291 /* Test with an empty entry */
1293 info.rgAltEntry = &entry;
1294 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1295 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1296 ok(!ret && GetLastError() == E_INVALIDARG,
1297 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1298 /* Test with an empty pointer */
1299 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1300 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1301 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1304 ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1305 ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1308 /* Test with a real URL */
1309 U(entry).pwszURL = (LPWSTR)url;
1310 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1311 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1314 ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1315 ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1318 /* Now with the URL containing an invalid IA5 char */
1319 U(entry).pwszURL = (LPWSTR)nihongoURL;
1320 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1321 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1322 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1323 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1324 /* The first invalid character is at index 7 */
1325 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1326 "Expected invalid char at index 7, got %d\n",
1327 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1328 /* Now with the URL missing a scheme */
1329 U(entry).pwszURL = (LPWSTR)dnsName;
1330 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1331 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1332 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1335 /* This succeeds, but it shouldn't, so don't worry about conforming */
1338 /* Now with a DNS name */
1339 entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1340 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1341 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1342 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1345 ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1346 ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1349 /* Test with an IP address */
1350 entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1351 U(entry).IPAddress.cbData = sizeof(localhost);
1352 U(entry).IPAddress.pbData = (LPBYTE)localhost;
1353 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1354 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1357 ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1358 ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1363 static void test_decodeAltName(DWORD dwEncoding)
1365 static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1367 static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1372 CERT_ALT_NAME_INFO *info;
1374 /* Test some bogus ones first */
1375 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1376 unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1377 NULL, (BYTE *)&buf, &bufSize);
1378 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1379 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1380 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1381 bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1383 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1384 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
1385 /* Now expected cases */
1386 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1387 emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1389 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1392 info = (CERT_ALT_NAME_INFO *)buf;
1394 ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1398 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1399 emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1401 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1404 info = (CERT_ALT_NAME_INFO *)buf;
1406 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1408 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1409 "Expected CERT_ALT_NAME_URL, got %d\n",
1410 info->rgAltEntry[0].dwAltNameChoice);
1411 ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1412 "Expected empty URL\n");
1415 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1416 encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1418 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1421 info = (CERT_ALT_NAME_INFO *)buf;
1423 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1425 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1426 "Expected CERT_ALT_NAME_URL, got %d\n",
1427 info->rgAltEntry[0].dwAltNameChoice);
1428 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1431 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1432 encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1434 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1437 info = (CERT_ALT_NAME_INFO *)buf;
1439 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1441 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1442 "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1443 info->rgAltEntry[0].dwAltNameChoice);
1444 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1445 "Unexpected DNS name\n");
1448 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1449 encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1451 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1454 info = (CERT_ALT_NAME_INFO *)buf;
1456 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1458 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1459 "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1460 info->rgAltEntry[0].dwAltNameChoice);
1461 ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1462 "Unexpected IP address length %d\n",
1463 U(info->rgAltEntry[0]).IPAddress.cbData);
1464 ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1465 sizeof(localhost)), "Unexpected IP address value\n");
1470 struct UnicodeExpectedError
1478 static const WCHAR oneW[] = { '1',0 };
1479 static const WCHAR aW[] = { 'a',0 };
1480 static const WCHAR quoteW[] = { '"', 0 };
1482 static struct UnicodeExpectedError unicodeErrors[] = {
1483 { CERT_RDN_ANY_TYPE, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1484 { CERT_RDN_ENCODED_BLOB, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1485 { CERT_RDN_OCTET_STRING, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1486 { 14, oneW, 0, CRYPT_E_ASN1_CHOICE },
1487 { CERT_RDN_NUMERIC_STRING, aW, 0, CRYPT_E_INVALID_NUMERIC_STRING },
1488 { CERT_RDN_PRINTABLE_STRING, quoteW, 0, CRYPT_E_INVALID_PRINTABLE_STRING },
1489 { CERT_RDN_IA5_STRING, nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1492 struct UnicodeExpectedResult
1496 CRYPT_DATA_BLOB encoded;
1499 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1500 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1501 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1502 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1503 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1504 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1505 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1506 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1507 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1508 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1509 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1510 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1512 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1514 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1515 0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1516 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1517 0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1519 static struct UnicodeExpectedResult unicodeResults[] = {
1520 { CERT_RDN_NUMERIC_STRING, oneW, { sizeof(oneNumeric), oneNumeric } },
1521 { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1522 { CERT_RDN_TELETEX_STRING, oneW, { sizeof(oneTeletex), oneTeletex } },
1523 { CERT_RDN_VIDEOTEX_STRING, oneW, { sizeof(oneVideotex), oneVideotex } },
1524 { CERT_RDN_IA5_STRING, oneW, { sizeof(oneIA5), oneIA5 } },
1525 { CERT_RDN_GRAPHIC_STRING, oneW, { sizeof(oneGraphic), oneGraphic } },
1526 { CERT_RDN_VISIBLE_STRING, oneW, { sizeof(oneVisible), oneVisible } },
1527 { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1528 { CERT_RDN_GENERAL_STRING, oneW, { sizeof(oneGeneral), oneGeneral } },
1529 { CERT_RDN_BMP_STRING, oneW, { sizeof(oneBMP), oneBMP } },
1530 { CERT_RDN_UTF8_STRING, oneW, { sizeof(oneUTF8), oneUTF8 } },
1531 { CERT_RDN_BMP_STRING, nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1532 { CERT_RDN_UTF8_STRING, nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1535 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1536 { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1537 { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1540 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1545 CERT_NAME_VALUE value;
1547 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1548 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1549 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1550 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1551 /* Have to have a string of some sort */
1552 value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1553 value.Value.pbData = NULL;
1554 value.Value.cbData = 0;
1555 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1556 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1557 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1558 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1559 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1560 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1561 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1562 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1563 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1564 value.dwValueType = CERT_RDN_ANY_TYPE;
1565 value.Value.pbData = (LPBYTE)oneW;
1566 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1567 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1568 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1569 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1570 value.Value.cbData = sizeof(oneW);
1571 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1572 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1573 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1574 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1575 /* An encoded string with specified length isn't good enough either */
1576 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1577 value.Value.pbData = oneUniversal;
1578 value.Value.cbData = sizeof(oneUniversal);
1579 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1580 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1581 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1582 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1583 /* More failure checking */
1584 value.Value.cbData = 0;
1585 for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1587 value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1588 value.dwValueType = unicodeErrors[i].valueType;
1589 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1590 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1591 ok(!ret && GetLastError() == unicodeErrors[i].error,
1592 "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1593 unicodeErrors[i].error, GetLastError());
1594 ok(size == unicodeErrors[i].errorIndex,
1595 "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1598 /* cbData can be zero if the string is NULL-terminated */
1599 value.Value.cbData = 0;
1600 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1602 value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1603 value.dwValueType = unicodeResults[i].valueType;
1604 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1605 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1606 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1609 ok(size == unicodeResults[i].encoded.cbData,
1610 "Value type %d: expected size %d, got %d\n",
1611 value.dwValueType, unicodeResults[i].encoded.cbData, size);
1612 ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1613 "Value type %d: unexpected value\n", value.dwValueType);
1617 /* These "encode," but they do so by truncating each unicode character
1618 * rather than properly encoding it. Kept separate from the proper results,
1619 * because the encoded forms won't decode to their original strings.
1621 for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1623 value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1624 value.dwValueType = unicodeWeirdness[i].valueType;
1625 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1626 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1627 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1630 ok(size == unicodeWeirdness[i].encoded.cbData,
1631 "Value type %d: expected size %d, got %d\n",
1632 value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1633 ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1634 "Value type %d: unexpected value\n", value.dwValueType);
1640 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1642 if (n <= 0) return 0;
1643 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1644 return *str1 - *str2;
1647 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1651 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1657 ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1658 unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1659 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1660 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1663 PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1665 ok(value->dwValueType == unicodeResults[i].valueType,
1666 "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1667 value->dwValueType);
1668 ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1669 value->Value.cbData / sizeof(WCHAR)),
1670 "Unexpected decoded value for index %d (value type %d)\n", i,
1671 unicodeResults[i].valueType);
1677 struct encodedOctets
1680 const BYTE *encoded;
1683 static const unsigned char bin46[] = { 'h','i',0 };
1684 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1685 static const unsigned char bin48[] = {
1686 's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1687 static const unsigned char bin49[] = {
1688 0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1689 static const unsigned char bin50[] = { 0 };
1690 static const unsigned char bin51[] = { 0x04,0x00,0 };
1692 static const struct encodedOctets octets[] = {
1698 static void test_encodeOctets(DWORD dwEncoding)
1700 CRYPT_DATA_BLOB blob;
1703 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1709 blob.cbData = strlen((const char*)octets[i].val);
1710 blob.pbData = (BYTE*)octets[i].val;
1711 ret = CryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1712 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1713 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1717 "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1718 ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1719 buf[1], octets[i].encoded[1]);
1720 ok(!memcmp(buf + 1, octets[i].encoded + 1,
1721 octets[i].encoded[1] + 1), "Got unexpected value\n");
1727 static void test_decodeOctets(DWORD dwEncoding)
1731 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1737 ret = CryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1738 (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1739 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1740 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1741 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1742 "Expected size >= %d, got %d\n",
1743 (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1744 ok(buf != NULL, "Expected allocated buffer\n");
1747 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1750 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1751 "Unexpected value\n");
1757 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1762 const BYTE *encoded;
1764 const BYTE *decoded;
1767 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1768 static const unsigned char bin53[] = { 0xff,0xff };
1769 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1770 static const unsigned char bin55[] = { 0xff,0xfe };
1771 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1772 static const unsigned char bin57[] = { 0xfe };
1773 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1775 static const struct encodedBits bits[] = {
1776 /* normal test cases */
1777 { 0, bin52, 2, bin53 },
1778 { 1, bin54, 2, bin55 },
1779 /* strange test case, showing cUnusedBits >= 8 is allowed */
1780 { 9, bin56, 1, bin57 },
1781 /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1782 { 17, bin58, 0, NULL },
1785 static void test_encodeBits(DWORD dwEncoding)
1789 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1791 CRYPT_BIT_BLOB blob;
1796 blob.cbData = sizeof(bytesToEncode);
1797 blob.pbData = (BYTE *)bytesToEncode;
1798 blob.cUnusedBits = bits[i].cUnusedBits;
1799 ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1800 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1801 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1804 ok(bufSize == bits[i].encoded[1] + 2,
1805 "Got unexpected size %d, expected %d\n", bufSize,
1806 bits[i].encoded[1] + 2);
1807 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1808 "Unexpected value\n");
1814 static void test_decodeBits(DWORD dwEncoding)
1816 static const BYTE ber[] = "\x03\x02\x01\xff";
1817 static const BYTE berDecoded = 0xfe;
1824 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1826 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1827 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1829 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1832 CRYPT_BIT_BLOB *blob;
1834 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1835 "Got unexpected size %d\n", bufSize);
1836 blob = (CRYPT_BIT_BLOB *)buf;
1837 ok(blob->cbData == bits[i].cbDecoded,
1838 "Got unexpected length %d, expected %d\n", blob->cbData,
1840 if (blob->cbData && bits[i].cbDecoded)
1841 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1842 "Unexpected value\n");
1846 /* special case: check that something that's valid in BER but not in DER
1847 * decodes successfully
1849 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1850 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1851 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1854 CRYPT_BIT_BLOB *blob;
1856 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1857 "Got unexpected size %d\n", bufSize);
1858 blob = (CRYPT_BIT_BLOB *)buf;
1859 ok(blob->cbData == sizeof(berDecoded),
1860 "Got unexpected length %d\n", blob->cbData);
1862 ok(*blob->pbData == berDecoded, "Unexpected value\n");
1869 CERT_BASIC_CONSTRAINTS2_INFO info;
1870 const BYTE *encoded;
1873 static const unsigned char bin59[] = { 0x30,0x00 };
1874 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
1875 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
1876 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1877 static const struct Constraints2 constraints2[] = {
1878 /* empty constraints */
1879 { { FALSE, FALSE, 0}, bin59 },
1881 { { TRUE, FALSE, 0}, bin60 },
1882 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1883 * but that's not the case
1885 { { FALSE, TRUE, 0}, bin61 },
1886 /* can be a CA and has path length constraints set */
1887 { { TRUE, TRUE, 1}, bin62 },
1890 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
1891 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
1892 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
1893 0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
1894 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1895 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
1896 0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
1897 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
1898 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
1899 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1901 static void test_encodeBasicConstraints(DWORD dwEncoding)
1903 DWORD i, bufSize = 0;
1904 CERT_BASIC_CONSTRAINTS_INFO info;
1905 CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
1906 (LPBYTE)encodedDomainName };
1910 /* First test with the simpler info2 */
1911 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1913 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1914 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1916 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1919 ok(bufSize == constraints2[i].encoded[1] + 2,
1920 "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
1922 ok(!memcmp(buf, constraints2[i].encoded,
1923 constraints2[i].encoded[1] + 2), "Unexpected value\n");
1927 /* Now test with more complex basic constraints */
1928 info.SubjectType.cbData = 0;
1929 info.fPathLenConstraint = FALSE;
1930 info.cSubtreesConstraint = 0;
1931 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1932 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1933 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1936 ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
1937 ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
1938 "Unexpected value\n");
1941 /* None of the certs I examined had any subtree constraint, but I test one
1942 * anyway just in case.
1944 info.cSubtreesConstraint = 1;
1945 info.rgSubtreesConstraint = &nameBlob;
1946 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1947 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1948 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1951 ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
1952 ok(!memcmp(buf, constraintWithDomainName,
1953 sizeof(constraintWithDomainName)), "Unexpected value\n");
1956 /* FIXME: test encoding with subject type. */
1959 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
1960 static const unsigned char encodedCommonName[] = {
1961 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1963 static void test_decodeBasicConstraints(DWORD dwEncoding)
1965 static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
1967 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
1973 /* First test with simpler info2 */
1974 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1976 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1977 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
1978 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1979 ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
1983 CERT_BASIC_CONSTRAINTS2_INFO *info =
1984 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1986 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
1987 "Unexpected value for item %d\n", i);
1991 /* Check with the order of encoded elements inverted */
1993 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1994 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1996 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1997 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
1998 ok(!buf, "Expected buf to be set to NULL\n");
1999 /* Check with a non-DER bool */
2000 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2001 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2002 (BYTE *)&buf, &bufSize);
2003 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2006 CERT_BASIC_CONSTRAINTS2_INFO *info =
2007 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2009 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2012 /* Check with a non-basic constraints value */
2013 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2014 (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
2015 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2016 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2017 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2018 /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2019 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2020 emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2021 (BYTE *)&buf, &bufSize);
2022 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2025 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2027 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2028 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2029 ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2032 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2033 constraintWithDomainName, sizeof(constraintWithDomainName),
2034 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2035 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2038 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2040 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2041 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2042 ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2043 if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2045 ok(info->rgSubtreesConstraint[0].cbData ==
2046 sizeof(encodedDomainName), "Wrong size %d\n",
2047 info->rgSubtreesConstraint[0].cbData);
2048 ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2049 sizeof(encodedDomainName)), "Unexpected value\n");
2055 /* These are terrible public keys of course, I'm just testing encoding */
2056 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2057 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2058 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2059 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2060 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2061 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2062 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2063 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2065 struct EncodedRSAPubKey
2067 const BYTE *modulus;
2069 const BYTE *encoded;
2070 size_t decodedModulusLen;
2073 struct EncodedRSAPubKey rsaPubKeys[] = {
2074 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2075 { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2076 { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2077 { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2080 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2082 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2083 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2084 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2087 DWORD bufSize = 0, i;
2089 /* Try with a bogus blob type */
2091 hdr->bVersion = CUR_BLOB_VERSION;
2093 hdr->aiKeyAlg = CALG_RSA_KEYX;
2094 rsaPubKey->magic = 0x31415352;
2095 rsaPubKey->bitlen = sizeof(modulus1) * 8;
2096 rsaPubKey->pubexp = 65537;
2097 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2100 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2101 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2103 ok(!ret && GetLastError() == E_INVALIDARG,
2104 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2105 /* Now with a bogus reserved field */
2106 hdr->bType = PUBLICKEYBLOB;
2108 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2109 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2113 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2114 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2115 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2118 /* Now with a bogus blob version */
2121 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2122 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2126 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2127 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2128 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2131 /* And with a bogus alg ID */
2132 hdr->bVersion = CUR_BLOB_VERSION;
2133 hdr->aiKeyAlg = CALG_DES;
2134 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2135 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2139 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2140 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2141 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2144 /* Check a couple of RSA-related OIDs */
2145 hdr->aiKeyAlg = CALG_RSA_KEYX;
2146 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2147 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2148 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2149 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2150 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2151 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2152 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2153 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2154 /* Finally, all valid */
2155 hdr->aiKeyAlg = CALG_RSA_KEYX;
2156 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2158 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2159 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2160 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2161 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2162 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2165 ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2166 "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2168 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2169 "Unexpected value\n");
2175 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2182 /* Try with a bad length */
2183 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2184 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2185 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2186 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2187 "Expected CRYPT_E_ASN1_EOD, got %08x\n", CRYPT_E_ASN1_EOD);
2188 /* Try with a couple of RSA-related OIDs */
2189 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2190 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2191 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2192 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2193 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2194 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2195 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2196 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2197 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2198 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2199 /* Now try success cases */
2200 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2203 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2204 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2205 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2206 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2209 BLOBHEADER *hdr = (BLOBHEADER *)buf;
2210 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2212 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2213 rsaPubKeys[i].decodedModulusLen,
2214 "Wrong size %d\n", bufSize);
2215 ok(hdr->bType == PUBLICKEYBLOB,
2216 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2218 ok(hdr->bVersion == CUR_BLOB_VERSION,
2219 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2220 CUR_BLOB_VERSION, hdr->bVersion);
2221 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2223 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2224 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2225 ok(rsaPubKey->magic == 0x31415352,
2226 "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2227 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2228 "Wrong bit len %d\n", rsaPubKey->bitlen);
2229 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2231 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2232 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2233 "Unexpected modulus\n");
2239 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2240 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2241 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2243 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2244 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2245 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2246 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2248 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2250 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2251 CRYPT_SEQUENCE_OF_ANY seq;
2257 /* Encode a homogenous sequence */
2258 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2260 blobs[i].cbData = ints[i].encoded[1] + 2;
2261 blobs[i].pbData = (BYTE *)ints[i].encoded;
2263 seq.cValue = sizeof(ints) / sizeof(ints[0]);
2264 seq.rgValue = blobs;
2266 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2267 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2268 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2271 ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2272 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2275 /* Change the type of the first element in the sequence, and give it
2278 blobs[0].cbData = times[0].encodedTime[1] + 2;
2279 blobs[0].pbData = (BYTE *)times[0].encodedTime;
2280 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2281 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2282 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2285 ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2286 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2287 "Unexpected value\n");
2292 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2298 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2299 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2300 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2303 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2306 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2307 "Wrong elements %d\n", seq->cValue);
2308 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2310 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2311 "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2312 seq->rgValue[i].cbData);
2313 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2314 ints[i].encoded[1] + 2), "Unexpected value\n");
2318 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2319 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2321 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2324 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2326 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2327 "Wrong elements %d\n", seq->cValue);
2328 /* Just check the first element since it's all that changed */
2329 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2330 "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2331 seq->rgValue[0].cbData);
2332 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2333 times[0].encodedTime[1] + 2), "Unexpected value\n");
2338 struct encodedExtensions
2340 CERT_EXTENSIONS exts;
2341 const BYTE *encoded;
2344 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2345 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2346 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2347 static CERT_EXTENSION criticalExt =
2348 { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2349 static CERT_EXTENSION nonCriticalExt =
2350 { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2352 static const BYTE ext0[] = { 0x30,0x00 };
2353 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2354 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2355 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2356 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2358 static const struct encodedExtensions exts[] = {
2359 { { 0, NULL }, ext0 },
2360 { { 1, &criticalExt }, ext1 },
2361 { { 1, &nonCriticalExt }, ext2 },
2364 static void test_encodeExtensions(DWORD dwEncoding)
2368 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2374 ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2375 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2376 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2379 ok(bufSize == exts[i].encoded[1] + 2,
2380 "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2381 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2382 "Unexpected value\n");
2388 static void test_decodeExtensions(DWORD dwEncoding)
2392 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2398 ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2399 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2400 NULL, (BYTE *)&buf, &bufSize);
2401 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2404 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2407 ok(ext->cExtension == exts[i].exts.cExtension,
2408 "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2410 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2412 ok(!strcmp(ext->rgExtension[j].pszObjId,
2413 exts[i].exts.rgExtension[j].pszObjId),
2414 "Expected OID %s, got %s\n",
2415 exts[i].exts.rgExtension[j].pszObjId,
2416 ext->rgExtension[j].pszObjId);
2417 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2418 exts[i].exts.rgExtension[j].Value.pbData,
2419 exts[i].exts.rgExtension[j].Value.cbData),
2420 "Unexpected value\n");
2427 /* MS encodes public key info with a NULL if the algorithm identifier's
2428 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
2429 * it encodes them by omitting the algorithm parameters. This latter approach
2430 * seems more correct, so accept either form.
2432 struct encodedPublicKey
2434 CERT_PUBLIC_KEY_INFO info;
2435 const BYTE *encoded;
2436 const BYTE *encodedNoNull;
2437 CERT_PUBLIC_KEY_INFO decoded;
2440 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2442 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2444 static const unsigned char bin64[] = {
2445 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2446 static const unsigned char bin65[] = {
2447 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2448 static const unsigned char bin66[] = {
2449 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2450 static const unsigned char bin67[] = {
2451 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2452 static const unsigned char bin68[] = {
2453 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2454 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2455 static const unsigned char bin69[] = {
2456 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2457 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2458 static const unsigned char bin70[] = {
2459 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2460 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2462 static const unsigned char bin71[] = {
2463 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2464 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2466 static unsigned char bin72[] = { 0x05,0x00};
2468 static CHAR oid_bogus[] = "1.2.3",
2469 oid_rsa[] = szOID_RSA;
2471 static const struct encodedPublicKey pubKeys[] = {
2472 /* with a bogus OID */
2473 { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2475 { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2476 /* some normal keys */
2477 { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2479 { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2480 { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2482 { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2483 /* with add'l parameters--note they must be DER-encoded */
2484 { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2485 (BYTE *)aKey, 0 } },
2487 { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2488 (BYTE *)aKey, 0 } } },
2491 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2495 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2501 ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2502 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2504 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2507 ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2508 bufSize == pubKeys[i].encodedNoNull[1] + 2,
2509 "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2510 pubKeys[i].encodedNoNull[1] + 2, bufSize);
2511 if (bufSize == pubKeys[i].encoded[1] + 2)
2512 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2513 "Unexpected value\n");
2514 else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2515 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2516 pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2522 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2523 const CERT_PUBLIC_KEY_INFO *got)
2525 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2526 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2527 got->Algorithm.pszObjId);
2528 ok(expected->Algorithm.Parameters.cbData ==
2529 got->Algorithm.Parameters.cbData,
2530 "Expected parameters of %d bytes, got %d\n",
2531 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2532 if (expected->Algorithm.Parameters.cbData)
2533 ok(!memcmp(expected->Algorithm.Parameters.pbData,
2534 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2535 "Unexpected algorithm parameters\n");
2536 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2537 "Expected public key of %d bytes, got %d\n",
2538 expected->PublicKey.cbData, got->PublicKey.cbData);
2539 if (expected->PublicKey.cbData)
2540 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2541 got->PublicKey.cbData), "Unexpected public key value\n");
2544 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2546 static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2547 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2548 0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2549 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2555 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2557 /* The NULL form decodes to the decoded member */
2558 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2559 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2560 NULL, (BYTE *)&buf, &bufSize);
2561 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2564 comparePublicKeyInfo(&pubKeys[i].decoded,
2565 (CERT_PUBLIC_KEY_INFO *)buf);
2568 /* The non-NULL form decodes to the original */
2569 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2570 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2571 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2572 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2575 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2579 /* Test with bogus (not valid DER) parameters */
2580 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2581 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2582 NULL, (BYTE *)&buf, &bufSize);
2583 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2584 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2587 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2588 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2589 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2590 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2591 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2592 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2593 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2594 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2595 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2596 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2597 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2598 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2599 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2600 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2601 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2602 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2603 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2604 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2605 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2606 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2607 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2608 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2609 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2610 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2611 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2612 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2613 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2614 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2615 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2616 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2617 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2618 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2619 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2620 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2621 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2622 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2623 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2624 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2625 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2627 static const BYTE serialNum[] = { 0x01 };
2629 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2634 CERT_INFO info = { 0 };
2636 /* Test with NULL pvStructInfo */
2637 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2638 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2639 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2640 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2641 /* Test with a V1 cert */
2642 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2643 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2644 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2647 ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2648 v1Cert[1] + 2, size);
2649 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2653 info.dwVersion = CERT_V2;
2654 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2655 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2656 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2659 ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2660 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2664 info.dwVersion = CERT_V3;
2665 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2666 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2667 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2670 ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2671 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2674 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2675 * API doesn't prevent it)
2677 info.dwVersion = CERT_V1;
2678 info.cExtension = 1;
2679 info.rgExtension = &criticalExt;
2680 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2681 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2682 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2685 ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2686 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2689 /* test v1 cert with a serial number */
2690 info.SerialNumber.cbData = sizeof(serialNum);
2691 info.SerialNumber.pbData = (BYTE *)serialNum;
2692 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2693 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2696 ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2697 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2700 /* Test v1 cert with an issuer name, a subject name, and a serial number */
2701 info.Issuer.cbData = sizeof(encodedCommonName);
2702 info.Issuer.pbData = (BYTE *)encodedCommonName;
2703 info.Subject.cbData = sizeof(encodedCommonName);
2704 info.Subject.pbData = (BYTE *)encodedCommonName;
2705 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2706 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2709 ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2710 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2713 /* for now, I let more interesting tests be done for each subcomponent,
2714 * rather than retesting them all here.
2718 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2720 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2721 v1CertWithConstraints, v1CertWithSerial };
2726 /* Test with NULL pbEncoded */
2727 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2728 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2729 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2730 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2731 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2732 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2733 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2734 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2735 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2736 * minimum a cert must have a non-zero serial number, an issuer, and a
2739 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2741 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2742 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2743 (BYTE *)&buf, &size);
2744 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
2745 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2747 /* Now check with serial number, subject and issuer specified */
2748 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2749 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2750 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2753 CERT_INFO *info = (CERT_INFO *)buf;
2755 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2756 ok(info->SerialNumber.cbData == 1,
2757 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2758 ok(*info->SerialNumber.pbData == *serialNum,
2759 "Expected serial number %d, got %d\n", *serialNum,
2760 *info->SerialNumber.pbData);
2761 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2762 "Wrong size %d\n", info->Issuer.cbData);
2763 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2764 "Unexpected issuer\n");
2765 ok(info->Subject.cbData == sizeof(encodedCommonName),
2766 "Wrong size %d\n", info->Subject.cbData);
2767 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2768 info->Subject.cbData), "Unexpected subject\n");
2773 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2776 static const BYTE signedBigCert[] = {
2777 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
2778 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2779 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
2780 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2781 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2782 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
2783 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
2784 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
2785 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
2786 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2787 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
2788 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
2790 static void test_encodeCert(DWORD dwEncoding)
2792 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
2793 * also that bigCert is a NULL-terminated string, so don't count its
2794 * last byte (otherwise the signed cert won't decode.)
2796 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
2797 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
2802 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
2803 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2804 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2807 ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
2808 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
2813 static void test_decodeCert(DWORD dwEncoding)
2819 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
2820 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2821 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2824 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
2826 ok(info->ToBeSigned.cbData == sizeof(bigCert),
2827 "Wrong cert size %d\n", info->ToBeSigned.cbData);
2828 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
2829 "Unexpected cert\n");
2830 ok(info->Signature.cbData == sizeof(hash),
2831 "Wrong signature size %d\n", info->Signature.cbData);
2832 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
2833 "Unexpected signature\n");
2836 /* A signed cert decodes as a CERT_INFO too */
2837 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
2838 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2839 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2842 CERT_INFO *info = (CERT_INFO *)buf;
2844 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2845 ok(info->SerialNumber.cbData == 1,
2846 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2847 ok(*info->SerialNumber.pbData == *serialNum,
2848 "Expected serial number %d, got %d\n", *serialNum,
2849 *info->SerialNumber.pbData);
2850 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2851 "Wrong size %d\n", info->Issuer.cbData);
2852 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2853 "Unexpected issuer\n");
2854 ok(info->Subject.cbData == sizeof(encodedCommonName),
2855 "Wrong size %d\n", info->Subject.cbData);
2856 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2857 info->Subject.cbData), "Unexpected subject\n");
2862 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
2863 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
2864 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
2865 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2866 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
2868 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
2869 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
2870 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2871 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
2872 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
2873 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
2874 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
2875 0x2e, 0x6f, 0x72, 0x67 };
2876 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
2877 CRL_REASON_AFFILIATION_CHANGED;
2879 static void test_encodeCRLDistPoints(DWORD dwEncoding)
2881 CRL_DIST_POINTS_INFO info = { 0 };
2882 CRL_DIST_POINT point = { { 0 } };
2883 CERT_ALT_NAME_ENTRY entry = { 0 };
2888 /* Test with an empty info */
2889 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2890 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2891 ok(!ret && GetLastError() == E_INVALIDARG,
2892 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2893 /* Test with one empty dist point */
2894 info.cDistPoint = 1;
2895 info.rgDistPoint = &point;
2896 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2897 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2900 ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
2901 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
2904 /* A dist point with an invalid name */
2905 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2906 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
2907 U(entry).pwszURL = (LPWSTR)nihongoURL;
2908 U(point.DistPointName).FullName.cAltEntry = 1;
2909 U(point.DistPointName).FullName.rgAltEntry = &entry;
2910 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2911 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2912 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
2913 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
2914 /* The first invalid character is at index 7 */
2915 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
2916 "Expected invalid char at index 7, got %d\n",
2917 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
2918 /* A dist point with (just) a valid name */
2919 U(entry).pwszURL = (LPWSTR)url;
2920 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2921 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2924 ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
2925 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
2928 /* A dist point with (just) reason flags */
2929 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
2930 point.ReasonFlags.cbData = sizeof(crlReason);
2931 point.ReasonFlags.pbData = (LPBYTE)&crlReason;
2932 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2933 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2936 ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
2937 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
2940 /* A dist point with just an issuer */
2941 point.ReasonFlags.cbData = 0;
2942 point.CRLIssuer.cAltEntry = 1;
2943 point.CRLIssuer.rgAltEntry = &entry;
2944 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2945 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2948 ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
2949 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
2952 /* A dist point with both a name and an issuer */
2953 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2954 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2955 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2958 ok(size == sizeof(distPointWithUrlAndIssuer),
2959 "Wrong size %d\n", size);
2960 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
2965 static void test_decodeCRLDistPoints(DWORD dwEncoding)
2970 PCRL_DIST_POINTS_INFO info;
2971 PCRL_DIST_POINT point;
2972 PCERT_ALT_NAME_ENTRY entry;
2974 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2975 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2976 (BYTE *)&buf, &size);
2979 info = (PCRL_DIST_POINTS_INFO)buf;
2980 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2981 "Wrong size %d\n", size);
2982 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
2984 point = info->rgDistPoint;
2985 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
2986 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
2987 point->DistPointName.dwDistPointNameChoice);
2988 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2989 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2992 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2993 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2994 (BYTE *)&buf, &size);
2997 info = (PCRL_DIST_POINTS_INFO)buf;
2998 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2999 "Wrong size %d\n", size);
3000 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3002 point = info->rgDistPoint;
3003 ok(point->DistPointName.dwDistPointNameChoice ==
3004 CRL_DIST_POINT_FULL_NAME,
3005 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3006 point->DistPointName.dwDistPointNameChoice);
3007 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3008 "Expected 1 name entry, got %d\n",
3009 U(point->DistPointName).FullName.cAltEntry);
3010 entry = U(point->DistPointName).FullName.rgAltEntry;
3011 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3012 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3013 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3014 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3015 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3018 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3019 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3020 NULL, (BYTE *)&buf, &size);
3023 info = (PCRL_DIST_POINTS_INFO)buf;
3024 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3025 "Wrong size %d\n", size);
3026 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3028 point = info->rgDistPoint;
3029 ok(point->DistPointName.dwDistPointNameChoice ==
3030 CRL_DIST_POINT_NO_NAME,
3031 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3032 point->DistPointName.dwDistPointNameChoice);
3033 ok(point->ReasonFlags.cbData == sizeof(crlReason),
3034 "Expected reason length\n");
3035 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3036 "Unexpected reason\n");
3037 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3040 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3041 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3042 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3045 info = (PCRL_DIST_POINTS_INFO)buf;
3046 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3047 "Wrong size %d\n", size);
3048 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3050 point = info->rgDistPoint;
3051 ok(point->DistPointName.dwDistPointNameChoice ==
3052 CRL_DIST_POINT_FULL_NAME,
3053 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3054 point->DistPointName.dwDistPointNameChoice);
3055 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3056 "Expected 1 name entry, got %d\n",
3057 U(point->DistPointName).FullName.cAltEntry);
3058 entry = U(point->DistPointName).FullName.rgAltEntry;
3059 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3060 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3061 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3062 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3063 ok(point->CRLIssuer.cAltEntry == 1,
3064 "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3065 entry = point->CRLIssuer.rgAltEntry;
3066 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3067 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3068 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3073 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3074 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3075 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3076 0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3079 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3084 CRL_ISSUING_DIST_POINT point = { { 0 } };
3085 CERT_ALT_NAME_ENTRY entry;
3087 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3088 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3089 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3090 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3091 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3092 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3093 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3096 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3097 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3100 /* nonsensical flags */
3101 point.fOnlyContainsUserCerts = TRUE;
3102 point.fOnlyContainsCACerts = TRUE;
3103 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3104 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3105 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3108 ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3109 ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3112 /* unimplemented name type */
3113 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3114 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3115 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3116 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3117 ok(!ret && GetLastError() == E_INVALIDARG,
3118 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3120 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3121 U(point.DistPointName).FullName.cAltEntry = 0;
3122 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3123 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3124 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3127 ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3128 ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3131 /* name with URL entry */
3132 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3133 U(entry).pwszURL = (LPWSTR)url;
3134 U(point.DistPointName).FullName.cAltEntry = 1;
3135 U(point.DistPointName).FullName.rgAltEntry = &entry;
3136 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3137 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3138 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3141 ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3142 ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3147 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3148 const CERT_ALT_NAME_ENTRY *got)
3150 ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3151 "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3152 got->dwAltNameChoice);
3153 if (expected->dwAltNameChoice == got->dwAltNameChoice)
3155 switch (got->dwAltNameChoice)
3157 case CERT_ALT_NAME_RFC822_NAME:
3158 case CERT_ALT_NAME_DNS_NAME:
3159 case CERT_ALT_NAME_EDI_PARTY_NAME:
3160 case CERT_ALT_NAME_URL:
3161 case CERT_ALT_NAME_REGISTERED_ID:
3162 ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3163 !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL), "Unexpected name\n");
3165 case CERT_ALT_NAME_X400_ADDRESS:
3166 case CERT_ALT_NAME_DIRECTORY_NAME:
3167 case CERT_ALT_NAME_IP_ADDRESS:
3168 ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3169 "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3170 ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3171 U(*got).IPAddress.cbData), "Unexpected value\n");
3177 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3178 const CERT_ALT_NAME_INFO *got)
3182 ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3183 expected->cAltEntry, got->cAltEntry);
3184 for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3185 compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3188 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3189 const CRL_DIST_POINT_NAME *got)
3191 ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3192 "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3193 if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3194 compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3197 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3198 const CRL_ISSUING_DIST_POINT *got)
3200 compareDistPointName(&expected->DistPointName, &got->DistPointName);
3201 ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3202 "Unexpected fOnlyContainsUserCerts\n");
3203 ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3204 "Unexpected fOnlyContainsCACerts\n");
3205 ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3206 "Unexpected reason flags\n");
3207 ok(got->fIndirectCRL == expected->fIndirectCRL,
3208 "Unexpected fIndirectCRL\n");
3211 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3216 CRL_ISSUING_DIST_POINT point = { { 0 } };
3218 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3219 emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3220 (BYTE *)&buf, &size);
3221 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3224 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3227 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3228 badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3229 (BYTE *)&buf, &size);
3230 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3233 point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3234 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3237 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3238 emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3239 (BYTE *)&buf, &size);
3240 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3243 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3244 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3245 U(point.DistPointName).FullName.cAltEntry = 0;
3246 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3249 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3250 urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3251 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3254 CERT_ALT_NAME_ENTRY entry;
3256 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3257 U(entry).pwszURL = (LPWSTR)url;
3258 U(point.DistPointName).FullName.cAltEntry = 1;
3259 U(point.DistPointName).FullName.rgAltEntry = &entry;
3260 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3265 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3266 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3268 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3269 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3270 0x30, 0x30, 0x30, 0x30, 0x5a };
3271 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3272 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3273 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3274 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3276 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3277 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3278 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3279 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3280 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3281 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3282 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3283 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3284 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3285 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3286 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3287 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3288 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3289 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3290 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3291 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3292 0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3293 0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3294 0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3295 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3296 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3297 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3298 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3299 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3300 0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3301 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3302 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3303 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3304 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3305 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3306 0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3307 0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3308 0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3309 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3310 0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3311 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3312 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3313 0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3314 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3315 0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3317 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3321 static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3323 CRL_INFO info = { 0 };
3324 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3327 /* Test with a V1 CRL */
3328 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3329 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3330 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3333 ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3334 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3338 info.dwVersion = CRL_V2;
3339 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3340 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3341 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3344 ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3345 v2CRL[1] + 2, size);
3346 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3349 /* v1 CRL with a name */
3350 info.dwVersion = CRL_V1;
3351 info.Issuer.cbData = sizeof(encodedCommonName);
3352 info.Issuer.pbData = (BYTE *)encodedCommonName;
3353 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3354 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3355 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3358 ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3359 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3362 /* v1 CRL with a name and a NULL entry pointer */
3364 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3365 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3366 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3367 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3368 /* now set an empty entry */
3369 info.rgCRLEntry = &entry;
3370 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3371 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3374 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3375 "Wrong size %d\n", size);
3376 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3377 "Got unexpected value\n");
3380 /* an entry with a serial number */
3381 entry.SerialNumber.cbData = sizeof(serialNum);
3382 entry.SerialNumber.pbData = (BYTE *)serialNum;
3383 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3384 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3387 ok(size == sizeof(v1CRLWithIssuerAndEntry),
3388 "Wrong size %d\n", size);
3389 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3390 "Got unexpected value\n");
3393 /* an entry with an extension */
3394 entry.cExtension = 1;
3395 entry.rgExtension = &criticalExt;
3396 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3397 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3398 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3401 ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3402 ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3405 /* a CRL with an extension */
3406 entry.cExtension = 0;
3407 info.cExtension = 1;
3408 info.rgExtension = &criticalExt;
3409 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3410 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3411 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3414 ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3415 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3418 /* a v2 CRL with an extension, this time non-critical */
3419 info.dwVersion = CRL_V2;
3420 info.rgExtension = &nonCriticalExt;
3421 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3422 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3423 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3426 ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3427 ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3430 /* a v2 CRL with an issuing dist point extension */
3431 ext.pszObjId = oid_issuing_dist_point;
3432 ext.fCritical = TRUE;
3433 ext.Value.cbData = sizeof(urlIDP);
3434 ext.Value.pbData = (LPBYTE)urlIDP;
3435 entry.rgExtension = &ext;
3436 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3437 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3438 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3441 ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3442 ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3447 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3448 0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3449 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3450 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3451 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3452 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3453 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3454 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3455 0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3456 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3457 0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3458 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3459 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3460 0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3461 0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3462 0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3463 0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3464 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3465 0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3466 0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3467 0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3468 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3469 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3470 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3471 0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3472 0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3473 0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3474 0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3475 0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3476 0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3477 0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3478 0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3479 0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3480 0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3482 static const BYTE verisignCRLWithLotsOfEntries[] = {
3483 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3484 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3485 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3486 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3487 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3488 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3489 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3490 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3491 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3492 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3493 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3494 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3495 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3496 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3497 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3498 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3499 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3500 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3501 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3502 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3503 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3504 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3505 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3506 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3507 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3508 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3509 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3510 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3511 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3512 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3513 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3514 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3515 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3516 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3517 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3518 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3519 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3520 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3521 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3522 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3523 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3524 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3525 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3526 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3527 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3528 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3529 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3530 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3531 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3532 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3533 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3534 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3535 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3536 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3537 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3538 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3539 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3540 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3541 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3542 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3543 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3544 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3545 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3546 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3547 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3548 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3549 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3550 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3551 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3552 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3553 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3554 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3555 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3556 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3557 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3558 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3559 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3560 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3561 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3562 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3563 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3564 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3565 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3566 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3567 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3568 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3569 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3570 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3571 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3572 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3573 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3574 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3575 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3576 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3577 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3578 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3579 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3580 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3581 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3582 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3583 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3584 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3585 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3586 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3587 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3588 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3589 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3590 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3591 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3592 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3593 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3594 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3595 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3596 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3597 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3598 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3599 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3600 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3601 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3602 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3603 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3604 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3605 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3606 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3607 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3608 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3609 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3610 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3611 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3612 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3613 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3614 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3615 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3616 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3617 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3618 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3619 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3620 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3621 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3622 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3623 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3624 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3625 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3626 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3627 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3628 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3629 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3630 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3631 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3632 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3633 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3634 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3635 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3636 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3637 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3638 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3639 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3640 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3641 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3642 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3643 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3644 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3645 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3646 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3647 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3648 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3649 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3650 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3651 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3652 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3653 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3654 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3655 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3656 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3657 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3658 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3659 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3660 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3661 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3662 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3663 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3664 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3665 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3666 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3667 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3668 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3669 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3670 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
3671 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
3672 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
3673 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
3674 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
3675 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
3676 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
3677 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
3678 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
3679 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
3680 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
3681 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
3682 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
3683 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
3684 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
3685 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
3686 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
3687 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
3688 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
3689 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
3690 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
3691 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
3692 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
3693 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
3694 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
3695 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
3696 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
3697 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
3698 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
3699 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
3700 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
3701 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
3702 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
3703 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
3704 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
3705 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
3706 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
3707 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
3708 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
3709 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
3710 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
3711 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
3712 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
3713 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
3714 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
3715 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
3716 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
3717 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
3718 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
3719 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
3720 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
3721 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
3722 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
3723 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
3724 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
3725 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
3726 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
3727 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
3728 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
3729 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
3730 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
3731 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
3732 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
3733 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
3734 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
3735 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
3736 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
3737 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
3738 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
3739 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
3740 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
3741 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
3742 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
3743 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
3744 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
3745 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
3746 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
3747 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
3748 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
3749 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
3750 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
3751 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
3752 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
3753 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
3754 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
3755 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
3756 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
3757 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
3758 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
3759 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
3760 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
3761 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
3762 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
3763 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
3764 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
3765 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
3766 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
3767 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
3768 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
3769 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
3770 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
3771 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
3772 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
3773 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
3774 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
3775 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
3776 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
3777 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
3778 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
3779 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
3780 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
3781 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
3782 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
3783 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
3784 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
3785 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
3786 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
3787 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
3788 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
3789 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
3790 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
3791 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
3792 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
3793 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
3794 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
3795 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
3796 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
3797 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
3798 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
3799 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
3800 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
3801 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
3802 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
3803 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
3804 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
3805 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
3806 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
3807 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
3808 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
3809 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
3810 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
3811 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
3812 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
3813 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
3814 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
3815 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
3816 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
3817 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
3818 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
3819 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
3820 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
3821 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
3822 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
3823 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
3824 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
3825 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
3826 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
3827 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
3828 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
3829 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
3830 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
3831 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
3832 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
3833 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
3834 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
3835 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
3836 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
3837 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
3838 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
3839 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
3840 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
3841 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
3842 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
3843 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
3844 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
3845 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
3846 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
3847 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
3848 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
3849 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
3850 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
3851 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
3852 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
3853 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
3854 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
3855 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
3856 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
3857 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
3858 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
3859 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
3860 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
3861 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
3862 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
3863 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
3864 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
3865 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
3866 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
3867 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
3868 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
3869 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
3870 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
3871 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
3872 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
3873 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
3874 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
3875 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
3876 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
3877 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
3878 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
3879 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
3880 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
3881 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
3882 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
3883 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
3884 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
3885 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
3886 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
3887 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
3888 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
3889 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
3890 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
3891 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
3892 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
3893 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
3894 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
3895 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
3896 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
3897 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
3898 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
3899 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
3900 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
3901 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
3902 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
3903 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
3904 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
3905 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
3906 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
3907 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
3908 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
3909 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
3910 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
3911 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
3912 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
3913 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
3914 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
3915 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
3916 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
3917 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
3918 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
3919 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
3920 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
3921 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
3922 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
3923 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
3924 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
3925 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
3926 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
3927 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
3928 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
3929 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
3930 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
3931 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
3932 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
3933 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
3934 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
3935 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
3936 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
3937 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
3938 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
3939 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
3940 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
3941 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
3942 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
3943 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
3944 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
3945 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
3946 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
3947 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
3948 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
3949 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
3950 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
3951 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
3952 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
3953 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
3954 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
3955 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
3956 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
3957 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
3958 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
3959 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
3960 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
3961 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
3962 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
3963 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
3964 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
3965 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
3966 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
3967 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
3968 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
3969 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
3970 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
3971 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
3972 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
3973 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
3974 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
3975 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
3976 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
3977 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
3978 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
3979 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
3980 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
3981 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
3982 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
3983 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
3984 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
3985 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
3986 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
3987 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
3988 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
3989 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
3990 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
3992 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
3994 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
3999 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4001 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4002 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4003 (BYTE *)&buf, &size);
4004 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
4005 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4007 /* at a minimum, a CRL must contain an issuer: */
4008 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4009 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4010 (BYTE *)&buf, &size);
4011 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4014 CRL_INFO *info = (CRL_INFO *)buf;
4016 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4017 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4019 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4020 "Wrong issuer size %d\n", info->Issuer.cbData);
4021 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4022 "Unexpected issuer\n");
4025 /* check decoding with an empty CRL entry */
4026 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4027 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4028 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4029 todo_wine ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
4030 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4031 /* with a real CRL entry */
4032 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4033 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4034 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4035 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4038 CRL_INFO *info = (CRL_INFO *)buf;
4041 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4042 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4044 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4045 entry = info->rgCRLEntry;
4046 ok(entry->SerialNumber.cbData == 1,
4047 "Expected serial number size 1, got %d\n",
4048 entry->SerialNumber.cbData);
4049 ok(*entry->SerialNumber.pbData == *serialNum,
4050 "Expected serial number %d, got %d\n", *serialNum,
4051 *entry->SerialNumber.pbData);
4052 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4053 "Wrong issuer size %d\n", info->Issuer.cbData);
4054 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4055 "Unexpected issuer\n");
4057 /* a real CRL from verisign that has extensions */
4058 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4059 verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4060 NULL, (BYTE *)&buf, &size);
4061 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4064 CRL_INFO *info = (CRL_INFO *)buf;
4067 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4068 ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4070 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4071 entry = info->rgCRLEntry;
4072 ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4076 /* another real CRL from verisign that has lots of entries */
4077 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4078 verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4079 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4080 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4083 CRL_INFO *info = (CRL_INFO *)buf;
4085 ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4086 ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4088 ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4092 /* and finally, with an extension */
4093 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4094 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4095 NULL, (BYTE *)&buf, &size);
4096 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4099 CRL_INFO *info = (CRL_INFO *)buf;
4102 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4103 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4105 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4106 entry = info->rgCRLEntry;
4107 ok(entry->SerialNumber.cbData == 1,
4108 "Expected serial number size 1, got %d\n",
4109 entry->SerialNumber.cbData);
4110 ok(*entry->SerialNumber.pbData == *serialNum,
4111 "Expected serial number %d, got %d\n", *serialNum,
4112 *entry->SerialNumber.pbData);
4113 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4114 "Wrong issuer size %d\n", info->Issuer.cbData);
4115 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4116 "Unexpected issuer\n");
4117 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4120 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4121 v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4122 NULL, (BYTE *)&buf, &size);
4123 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4126 CRL_INFO *info = (CRL_INFO *)buf;
4128 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4132 /* And again, with an issuing dist point */
4133 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4134 v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4135 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4136 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4139 CRL_INFO *info = (CRL_INFO *)buf;
4141 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4147 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4148 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4149 static const BYTE encodedUsage[] = {
4150 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4151 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4152 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4154 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4159 CERT_ENHKEY_USAGE usage;
4161 /* Test with empty usage */
4162 usage.cUsageIdentifier = 0;
4163 ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4164 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4165 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4168 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4169 ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4172 /* Test with a few usages */
4173 usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4174 usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4175 ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4176 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4177 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4180 ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4181 ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4186 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4192 ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4193 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4194 (BYTE *)&buf, &size);
4195 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4198 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4200 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4201 "Wrong size %d\n", size);
4202 ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4203 usage->cUsageIdentifier);
4206 ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4207 encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4208 (BYTE *)&buf, &size);
4209 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4212 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4215 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4216 "Wrong size %d\n", size);
4217 ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4218 "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4219 for (i = 0; i < usage->cUsageIdentifier; i++)
4220 ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4221 "Expected OID %s, got %s\n", keyUsages[i],
4222 usage->rgpszUsageIdentifier[i]);
4227 static const BYTE authorityKeyIdWithId[] = { 0x30,0x03,0x80,0x01,0x01 };
4228 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4229 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4230 0x20,0x4c,0x61,0x6e,0x67,0x00 };
4231 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4233 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4235 CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4240 /* Test with empty id */
4241 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4242 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4243 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4246 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4247 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4250 /* With just a key id */
4251 info.KeyId.cbData = sizeof(serialNum);
4252 info.KeyId.pbData = (BYTE *)serialNum;
4253 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4254 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4255 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4258 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4259 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4262 /* With just an issuer */
4263 info.KeyId.cbData = 0;
4264 info.CertIssuer.cbData = sizeof(encodedCommonName);
4265 info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4266 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4267 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4268 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4271 ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4273 ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4276 /* With just a serial number */
4277 info.CertIssuer.cbData = 0;
4278 info.CertSerialNumber.cbData = sizeof(serialNum);
4279 info.CertSerialNumber.pbData = (BYTE *)serialNum;
4280 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4281 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4282 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4285 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4287 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4292 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4298 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4299 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4300 (BYTE *)&buf, &size);
4301 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4304 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4306 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4308 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4309 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4310 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4313 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4314 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4315 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4316 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4319 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4321 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4323 ok(info->KeyId.cbData == sizeof(serialNum), "Unexpected key id len\n");
4324 ok(!memcmp(info->KeyId.pbData, serialNum, sizeof(serialNum)),
4325 "Unexpected key id\n");
4326 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4327 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4330 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4331 authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4332 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4333 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4336 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4338 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4340 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4341 ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4342 "Unexpected issuer len\n");
4343 ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4344 sizeof(encodedCommonName)), "Unexpected issuer\n");
4345 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4348 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4349 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4350 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4351 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4354 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4356 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4358 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4359 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4360 ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4361 "Unexpected serial number len\n");
4362 ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4363 "Unexpected serial number\n");
4368 /* Free *pInfo with HeapFree */
4369 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
4376 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
4378 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
4379 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4380 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4381 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
4383 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4384 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4385 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
4387 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4388 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4389 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
4390 0, NULL, NULL, &size);
4391 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4392 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4393 /* Test with no key */
4394 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
4395 0, NULL, NULL, &size);
4396 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
4398 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
4399 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
4402 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
4403 NULL, 0, NULL, NULL, &size);
4404 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
4405 *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
4408 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
4409 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
4410 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
4414 /* By default (we passed NULL as the OID) the OID is
4417 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
4418 "Expected %s, got %s\n", szOID_RSA_RSA,
4419 (*pInfo)->Algorithm.pszObjId);
4425 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
4426 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
4427 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
4428 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
4429 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
4430 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
4431 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
4432 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
4433 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
4434 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
4435 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
4436 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
4437 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
4438 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
4439 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
4440 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
4441 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
4442 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
4443 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
4444 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
4445 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
4446 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
4447 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
4448 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
4449 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
4451 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
4455 PCCERT_CONTEXT context;
4458 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
4459 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
4460 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
4461 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
4464 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
4465 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
4466 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
4467 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
4468 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
4469 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
4470 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
4472 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4473 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4474 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
4476 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
4477 CryptDestroyKey(key);
4479 /* Test importing a public key from a certificate context */
4480 context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
4481 sizeof(expiredCert));
4482 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
4486 ok(!strcmp(szOID_RSA_RSA,
4487 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
4488 "Expected %s, got %s\n", szOID_RSA_RSA,
4489 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
4490 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
4491 &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
4492 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
4493 CryptDestroyKey(key);
4494 CertFreeCertificateContext(context);
4498 static const char cspName[] = "WineCryptTemp";
4500 static void testPortPublicKeyInfo(void)
4504 PCERT_PUBLIC_KEY_INFO info = NULL;
4506 /* Just in case a previous run failed, delete this thing */
4507 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
4508 CRYPT_DELETEKEYSET);
4509 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
4512 testExportPublicKey(csp, &info);
4513 testImportPublicKey(csp, info);
4515 HeapFree(GetProcessHeap(), 0, info);
4516 CryptReleaseContext(csp, 0);
4517 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
4518 CRYPT_DELETEKEYSET);
4523 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
4524 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
4527 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
4529 test_encodeInt(encodings[i]);
4530 test_decodeInt(encodings[i]);
4531 test_encodeEnumerated(encodings[i]);
4532 test_decodeEnumerated(encodings[i]);
4533 test_encodeFiletime(encodings[i]);
4534 test_decodeFiletime(encodings[i]);
4535 test_encodeName(encodings[i]);
4536 test_decodeName(encodings[i]);
4537 test_encodeUnicodeName(encodings[i]);
4538 test_decodeUnicodeName(encodings[i]);
4539 test_encodeNameValue(encodings[i]);
4540 test_decodeNameValue(encodings[i]);
4541 test_encodeUnicodeNameValue(encodings[i]);
4542 test_decodeUnicodeNameValue(encodings[i]);
4543 test_encodeAltName(encodings[i]);
4544 test_decodeAltName(encodings[i]);
4545 test_encodeOctets(encodings[i]);
4546 test_decodeOctets(encodings[i]);
4547 test_encodeBits(encodings[i]);
4548 test_decodeBits(encodings[i]);
4549 test_encodeBasicConstraints(encodings[i]);
4550 test_decodeBasicConstraints(encodings[i]);
4551 test_encodeRsaPublicKey(encodings[i]);
4552 test_decodeRsaPublicKey(encodings[i]);
4553 test_encodeSequenceOfAny(encodings[i]);
4554 test_decodeSequenceOfAny(encodings[i]);
4555 test_encodeExtensions(encodings[i]);
4556 test_decodeExtensions(encodings[i]);
4557 test_encodePublicKeyInfo(encodings[i]);
4558 test_decodePublicKeyInfo(encodings[i]);
4559 test_encodeCertToBeSigned(encodings[i]);
4560 test_decodeCertToBeSigned(encodings[i]);
4561 test_encodeCert(encodings[i]);
4562 test_decodeCert(encodings[i]);
4563 test_encodeCRLDistPoints(encodings[i]);
4564 test_decodeCRLDistPoints(encodings[i]);
4565 test_encodeCRLIssuingDistPoint(encodings[i]);
4566 test_decodeCRLIssuingDistPoint(encodings[i]);
4567 test_encodeCRLToBeSigned(encodings[i]);
4568 test_decodeCRLToBeSigned(encodings[i]);
4569 test_encodeEnhancedKeyUsage(encodings[i]);
4570 test_decodeEnhancedKeyUsage(encodings[i]);
4571 test_encodeAuthorityKeyId(encodings[i]);
4572 test_decodeAuthorityKeyId(encodings[i]);
4574 testPortPublicKeyInfo();