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 (BYTE *)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 (BYTE *)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 (BYTE *)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 (BYTE *)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 (BYTE *)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 (BYTE *)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
327 #if 0 /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
328 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
329 0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
330 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
331 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
335 static const BYTE bin18[] = {0x0a,0x01,0x01};
336 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
338 /* These are always encoded unsigned, and aren't constrained to be any
341 static const struct encodedInt enums[] = {
346 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
349 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
350 szOID_CRL_REASON_CODE };
352 static void test_encodeEnumerated(DWORD dwEncoding)
356 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
358 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
364 ret = CryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
365 &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
367 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
371 "Got unexpected type %d for enumerated (expected 0xa)\n",
373 ok(buf[1] == enums[j].encoded[1],
374 "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
375 ok(!memcmp(buf + 1, enums[j].encoded + 1,
376 enums[j].encoded[1] + 1),
377 "Encoded value of 0x%08x didn't match expected\n",
385 static void test_decodeEnumerated(DWORD dwEncoding)
389 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
391 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
394 DWORD bufSize = sizeof(int);
397 ret = CryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
398 enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
399 (BYTE *)&val, &bufSize);
400 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
401 ok(bufSize == sizeof(int),
402 "Got unexpected size %d for enumerated\n", bufSize);
403 ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
409 struct encodedFiletime
412 const BYTE *encodedTime;
415 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
416 const struct encodedFiletime *time)
423 ret = SystemTimeToFileTime(&time->sysTime, &ft);
424 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
425 ret = CryptEncodeObjectEx(dwEncoding, structType, &ft,
426 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
427 /* years other than 1950-2050 are not allowed for encodings other than
428 * X509_CHOICE_OF_TIME.
430 if (structType == X509_CHOICE_OF_TIME ||
431 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
433 ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
435 ok(buf != NULL, "Expected an allocated buffer\n");
438 ok(buf[0] == time->encodedTime[0],
439 "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
441 ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
442 time->encodedTime[1], bufSize);
443 ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
444 "Got unexpected value for time encoding\n");
449 ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
450 "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
453 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
454 const struct encodedFiletime *time)
456 FILETIME ft1 = { 0 }, ft2 = { 0 };
457 DWORD size = sizeof(ft2);
460 ret = SystemTimeToFileTime(&time->sysTime, &ft1);
461 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
462 ret = CryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
463 time->encodedTime[1] + 2, 0, NULL, &ft2, &size);
464 /* years other than 1950-2050 are not allowed for encodings other than
465 * X509_CHOICE_OF_TIME.
467 if (structType == X509_CHOICE_OF_TIME ||
468 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
470 ok(ret, "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
472 ok(!memcmp(&ft1, &ft2, sizeof(ft1)),
473 "Got unexpected value for time decoding\n");
476 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
477 "Expected CRYPT_E_ASN1_BADTAG, got 0x%08x\n", GetLastError());
480 static const BYTE bin20[] = {
481 0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
482 static const BYTE bin21[] = {
483 0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
484 static const BYTE bin22[] = {
485 0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
487 static const struct encodedFiletime times[] = {
488 { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
489 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
490 { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
493 static void test_encodeFiletime(DWORD dwEncoding)
497 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
499 testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, ×[i]);
500 testTimeEncoding(dwEncoding, PKCS_UTC_TIME, ×[i]);
501 testTimeEncoding(dwEncoding, szOID_RSA_signingTime, ×[i]);
505 static const BYTE bin23[] = {
506 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
507 static const BYTE bin24[] = {
508 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
509 static const BYTE bin25[] = {
510 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
511 static const BYTE bin26[] = {
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 bin27[] = {
514 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
515 static const BYTE bin28[] = {
516 0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
517 static const BYTE bin29[] = {
518 0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
519 static const BYTE bin30[] = {
520 0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
521 static const BYTE bin31[] = {
522 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
523 static const BYTE bin32[] = {
524 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
525 static const BYTE bin33[] = {
526 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
527 static const BYTE bin34[] = {
528 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
529 static const BYTE bin35[] = {
530 0x17,0x08, '4','5','0','6','0','6','1','6'};
531 static const BYTE bin36[] = {
532 0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
533 static const BYTE bin37[] = {
534 0x18,0x04, '2','1','4','5'};
535 static const BYTE bin38[] = {
536 0x18,0x08, '2','1','4','5','0','6','0','6'};
538 static void test_decodeFiletime(DWORD dwEncoding)
540 static const struct encodedFiletime otherTimes[] = {
541 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin23 },
542 { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
543 { { 1945, 6, 1, 6, 17, 10, 0, 0 }, bin25 },
544 { { 1945, 6, 1, 6, 15, 10, 0, 0 }, bin26 },
545 { { 1945, 6, 1, 6, 14, 55, 0, 0 }, bin27 },
546 { { 2145, 6, 1, 6, 16, 0, 0, 0 }, bin28 },
547 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin29 },
548 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin30 },
549 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin31 },
550 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin32 },
551 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin33 },
552 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin34 },
554 /* An oddball case that succeeds in Windows, but doesn't seem correct
555 { { 2145, 6, 1, 2, 11, 31, 0, 0 }, "\x18" "\x13" "21450606161000-9999" },
557 static const unsigned char *bogusTimes[] = {
558 /* oddly, this succeeds on Windows, with year 2765
559 "\x18" "\x0f" "21r50606161000Z",
567 FILETIME ft1 = { 0 }, ft2 = { 0 };
570 /* Check bogus length with non-NULL buffer */
571 ret = SystemTimeToFileTime(×[0].sysTime, &ft1);
572 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
574 ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
575 times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
576 ok(!ret && GetLastError() == ERROR_MORE_DATA,
577 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
579 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
581 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, ×[i]);
582 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, ×[i]);
583 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, ×[i]);
585 for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
587 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
588 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
589 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
591 for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
594 ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
595 bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
596 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
597 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
601 static const char commonName[] = "Juan Lang";
602 static const char surName[] = "Lang";
604 static const BYTE emptySequence[] = { 0x30, 0 };
605 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
606 static const BYTE twoRDNs[] = {
607 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
608 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
609 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
610 static const BYTE encodedTwoRDNs[] = {
611 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
612 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
613 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
617 static const BYTE us[] = { 0x55, 0x53 };
618 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
620 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
621 0x6f, 0x6c, 0x69, 0x73 };
622 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
623 0x76, 0x65, 0x72, 0x73 };
624 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
625 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
626 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
628 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
629 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
631 #define RDNA(arr) oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
632 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING, { sizeof(arr), (LPBYTE)arr }
634 static CHAR oid_us[] = "2.5.4.6",
635 oid_minnesota[] = "2.5.4.8",
636 oid_minneapolis[] = "2.5.4.7",
637 oid_codeweavers[] = "2.5.4.10",
638 oid_wine[] = "2.5.4.11",
639 oid_localhostAttr[] = "2.5.4.3",
640 oid_aric[] = "1.2.840.113549.1.9.1";
641 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
643 { RDNA(minneapolis) },
644 { RDNA(codeweavers) },
646 { RDNA(localhostAttr) },
648 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
649 { RDNA(localhostAttr) },
651 { RDNA(minneapolis) },
652 { RDNA(codeweavers) },
659 static const BYTE encodedRDNAttrs[] = {
660 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
661 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
662 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
663 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
664 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
665 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
666 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
667 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
668 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
669 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
672 static void test_encodeName(DWORD dwEncoding)
674 CERT_RDN_ATTR attrs[2];
677 static CHAR oid_common_name[] = szOID_COMMON_NAME,
678 oid_sur_name[] = szOID_SUR_NAME;
683 /* Test with NULL pvStructInfo */
684 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
685 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
686 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
687 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
688 /* Test with empty CERT_NAME_INFO */
691 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
692 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
693 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
696 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
697 "Got unexpected encoding for empty name\n");
700 /* Test with bogus CERT_RDN */
702 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
703 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
704 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
705 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
706 /* Test with empty CERT_RDN */
708 rdn.rgRDNAttr = NULL;
711 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
712 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
713 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
716 ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
717 "Got unexpected encoding for empty RDN array\n");
720 /* Test with bogus attr array */
722 rdn.rgRDNAttr = NULL;
723 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
724 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
725 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
726 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
727 /* oddly, a bogus OID is accepted by Windows XP; not testing.
728 attrs[0].pszObjId = "bogus";
729 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
730 attrs[0].Value.cbData = sizeof(commonName);
731 attrs[0].Value.pbData = (BYTE *)commonName;
733 rdn.rgRDNAttr = attrs;
734 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
735 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
736 ok(!ret, "Expected failure, got success\n");
738 /* Check with two CERT_RDN_ATTRs. Note DER encoding forces the order of
739 * the encoded attributes to be swapped.
741 attrs[0].pszObjId = oid_common_name;
742 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
743 attrs[0].Value.cbData = sizeof(commonName);
744 attrs[0].Value.pbData = (BYTE *)commonName;
745 attrs[1].pszObjId = oid_sur_name;
746 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
747 attrs[1].Value.cbData = sizeof(surName);
748 attrs[1].Value.pbData = (BYTE *)surName;
750 rdn.rgRDNAttr = attrs;
751 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
752 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
753 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
756 ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
757 "Got unexpected encoding for two RDN array\n");
760 /* A name can be "encoded" with previously encoded RDN attrs. */
761 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
762 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
763 attrs[0].Value.cbData = sizeof(twoRDNs);
765 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
766 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
767 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
770 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
771 ok(!memcmp(buf, encodedTwoRDNs, size),
772 "Unexpected value for re-endoded two RDN array\n");
775 /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
777 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
778 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
779 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
780 ok(!ret && GetLastError() == E_INVALIDARG,
781 "Expected E_INVALIDARG, got %08x\n", GetLastError());
782 /* Test a more complex name */
783 rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
784 rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
789 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
790 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
791 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
794 ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
795 ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
800 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
801 static WCHAR surNameW[] = { 'L','a','n','g',0 };
803 static const BYTE twoRDNsNoNull[] = {
804 0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
805 0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
806 0x20,0x4c,0x61,0x6e,0x67 };
807 static const BYTE anyType[] = {
808 0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
809 0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
810 0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
811 0x61,0x4c,0x67,0x6e };
813 static void test_encodeUnicodeName(DWORD dwEncoding)
815 CERT_RDN_ATTR attrs[2];
818 static CHAR oid_common_name[] = szOID_COMMON_NAME,
819 oid_sur_name[] = szOID_SUR_NAME;
824 /* Test with NULL pvStructInfo */
825 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
826 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
827 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
828 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
829 /* Test with empty CERT_NAME_INFO */
832 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
833 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
834 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
837 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
838 "Got unexpected encoding for empty name\n");
841 /* Check with one CERT_RDN_ATTR, that has an invalid character for the
842 * encoding (the NULL).
844 attrs[0].pszObjId = oid_common_name;
845 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
846 attrs[0].Value.cbData = sizeof(commonNameW);
847 attrs[0].Value.pbData = (BYTE *)commonNameW;
849 rdn.rgRDNAttr = attrs;
852 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
853 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
854 ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
855 "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
856 ok(size == 9, "Unexpected error index %08x\n", size);
857 /* Check with two NULL-terminated CERT_RDN_ATTRs. Note DER encoding
858 * forces the order of the encoded attributes to be swapped.
860 attrs[0].pszObjId = oid_common_name;
861 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
862 attrs[0].Value.cbData = 0;
863 attrs[0].Value.pbData = (BYTE *)commonNameW;
864 attrs[1].pszObjId = oid_sur_name;
865 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
866 attrs[1].Value.cbData = 0;
867 attrs[1].Value.pbData = (BYTE *)surNameW;
869 rdn.rgRDNAttr = attrs;
872 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
873 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
874 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
877 ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
878 "Got unexpected encoding for two RDN array\n");
881 /* A name can be "encoded" with previously encoded RDN attrs. */
882 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
883 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
884 attrs[0].Value.cbData = sizeof(twoRDNs);
886 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
887 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
888 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
891 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
892 ok(!memcmp(buf, encodedTwoRDNs, size),
893 "Unexpected value for re-endoded two RDN array\n");
896 /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
898 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
899 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
900 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
901 todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
904 ok(size == sizeof(anyType), "Unexpected size %d\n", size);
905 ok(!memcmp(buf, anyType, size), "Unexpected value\n");
910 static void compareNameValues(const CERT_NAME_VALUE *expected,
911 const CERT_NAME_VALUE *got)
913 ok(got->dwValueType == expected->dwValueType,
914 "Expected string type %d, got %d\n", expected->dwValueType,
916 ok(got->Value.cbData == expected->Value.cbData,
917 "String type %d: unexpected data size, got %d, expected %d\n",
918 expected->dwValueType, got->Value.cbData, expected->Value.cbData);
919 if (got->Value.cbData && got->Value.pbData)
920 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
921 min(got->Value.cbData, expected->Value.cbData)),
922 "String type %d: unexpected value\n", expected->dwValueType);
925 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
926 const CERT_RDN_ATTR *got)
928 if (expected->pszObjId && strlen(expected->pszObjId))
930 ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
934 ok(!strcmp(got->pszObjId, expected->pszObjId),
935 "Got unexpected OID %s, expected %s\n", got->pszObjId,
939 compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
940 (const CERT_NAME_VALUE *)&got->dwValueType);
943 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
945 ok(got->cRDNAttr == expected->cRDNAttr,
946 "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
951 for (i = 0; i < got->cRDNAttr; i++)
952 compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
956 static void compareNames(const CERT_NAME_INFO *expected,
957 const CERT_NAME_INFO *got)
959 ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
960 expected->cRDN, got->cRDN);
965 for (i = 0; i < got->cRDN; i++)
966 compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
970 static void test_decodeName(DWORD dwEncoding)
976 CERT_NAME_INFO info = { 1, &rdn };
978 /* test empty name */
980 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
981 emptySequence[1] + 2,
982 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
983 (BYTE *)&buf, &bufSize);
984 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
985 /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL. My
986 * decoder works the same way, so only test the count.
990 ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
991 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
992 "Expected 0 RDNs in empty info, got %d\n",
993 ((CERT_NAME_INFO *)buf)->cRDN);
998 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1000 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1001 (BYTE *)&buf, &bufSize);
1002 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1005 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1007 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1008 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1009 "Got unexpected value for empty RDN\n");
1012 /* test two RDN attrs */
1014 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1016 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1017 (BYTE *)&buf, &bufSize);
1018 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1021 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1022 oid_common_name[] = szOID_COMMON_NAME;
1024 CERT_RDN_ATTR attrs[] = {
1025 { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1026 (BYTE *)surName } },
1027 { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1028 (BYTE *)commonName } },
1031 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1032 rdn.rgRDNAttr = attrs;
1033 compareNames(&info, (CERT_NAME_INFO *)buf);
1036 /* And, a slightly more complicated name */
1039 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1040 sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1041 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1044 rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1045 rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
1046 compareNames(&info, (CERT_NAME_INFO *)buf);
1051 static void test_decodeUnicodeName(DWORD dwEncoding)
1057 CERT_NAME_INFO info = { 1, &rdn };
1059 /* test empty name */
1061 ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1062 emptySequence[1] + 2,
1063 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1064 (BYTE *)&buf, &bufSize);
1065 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1068 ok(bufSize == sizeof(CERT_NAME_INFO),
1069 "Got wrong bufSize %d\n", bufSize);
1070 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1071 "Expected 0 RDNs in empty info, got %d\n",
1072 ((CERT_NAME_INFO *)buf)->cRDN);
1075 /* test empty RDN */
1077 ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1079 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1080 (BYTE *)&buf, &bufSize);
1081 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1084 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1086 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1087 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1088 "Got unexpected value for empty RDN\n");
1091 /* test two RDN attrs */
1093 ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1094 sizeof(twoRDNsNoNull),
1095 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1096 (BYTE *)&buf, &bufSize);
1097 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1100 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1101 oid_common_name[] = szOID_COMMON_NAME;
1103 CERT_RDN_ATTR attrs[] = {
1104 { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1105 { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1106 { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1107 { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1110 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1111 rdn.rgRDNAttr = attrs;
1112 compareNames(&info, (CERT_NAME_INFO *)buf);
1117 struct EncodedNameValue
1119 CERT_NAME_VALUE value;
1120 const BYTE *encoded;
1124 static const char bogusIA5[] = "\x80";
1125 static const char bogusPrintable[] = "~";
1126 static const char bogusNumeric[] = "A";
1127 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1128 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1129 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1130 static BYTE octetCommonNameValue[] = {
1131 0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1132 static BYTE numericCommonNameValue[] = {
1133 0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1134 static BYTE printableCommonNameValue[] = {
1135 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1136 static BYTE t61CommonNameValue[] = {
1137 0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1138 static BYTE videotexCommonNameValue[] = {
1139 0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1140 static BYTE ia5CommonNameValue[] = {
1141 0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1142 static BYTE graphicCommonNameValue[] = {
1143 0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1144 static BYTE visibleCommonNameValue[] = {
1145 0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1146 static BYTE generalCommonNameValue[] = {
1147 0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1148 static BYTE bmpCommonNameValue[] = {
1149 0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1150 0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1151 static BYTE utf8CommonNameValue[] = {
1152 0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1154 static struct EncodedNameValue nameValues[] = {
1155 { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1156 octetCommonNameValue, sizeof(octetCommonNameValue) },
1157 { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1158 numericCommonNameValue, sizeof(numericCommonNameValue) },
1159 { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1160 printableCommonNameValue, sizeof(printableCommonNameValue) },
1161 { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1162 t61CommonNameValue, sizeof(t61CommonNameValue) },
1163 { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1164 videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1165 { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1166 ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1167 { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1168 graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1169 { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1170 visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1171 { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1172 generalCommonNameValue, sizeof(generalCommonNameValue) },
1173 { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1174 bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1175 { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1176 utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1177 /* The following tests succeed under Windows, but really should fail,
1178 * they contain characters that are illegal for the encoding. I'm
1179 * including them to justify my lazy encoding.
1181 { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1183 { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1184 (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1185 { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1186 bin44, sizeof(bin44) },
1189 static void test_encodeNameValue(DWORD dwEncoding)
1194 CERT_NAME_VALUE value = { 0, { 0, NULL } };
1196 value.dwValueType = 14;
1197 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1198 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1199 ok(!ret && GetLastError() == CRYPT_E_ASN1_CHOICE,
1200 "Expected CRYPT_E_ASN1_CHOICE, got %08x\n", GetLastError());
1201 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1202 value.Value.pbData = printableCommonNameValue;
1203 value.Value.cbData = sizeof(printableCommonNameValue);
1204 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1205 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1206 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1209 ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1211 ok(!memcmp(buf, printableCommonNameValue, size),
1212 "Unexpected encoding\n");
1215 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1217 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1218 &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1220 ok(ret, "Type %d: CryptEncodeObjectEx failed: %08x\n",
1221 nameValues[i].value.dwValueType, GetLastError());
1224 ok(size == nameValues[i].encodedSize,
1225 "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1226 ok(!memcmp(buf, nameValues[i].encoded, size),
1227 "Got unexpected encoding\n");
1233 static void test_decodeNameValue(DWORD dwEncoding)
1240 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1242 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1243 nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1244 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1245 (BYTE *)&buf, &bufSize);
1246 ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1247 nameValues[i].value.dwValueType, GetLastError());
1250 compareNameValues(&nameValues[i].value,
1251 (const CERT_NAME_VALUE *)buf);
1257 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1258 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1259 'h','q','.','o','r','g',0 };
1260 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1261 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1263 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1265 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1266 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1267 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1268 static const BYTE localhost[] = { 127, 0, 0, 1 };
1269 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1272 static void test_encodeAltName(DWORD dwEncoding)
1274 CERT_ALT_NAME_INFO info = { 0 };
1275 CERT_ALT_NAME_ENTRY entry = { 0 };
1280 /* Test with empty info */
1281 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1282 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1285 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1286 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1289 /* Test with an empty entry */
1291 info.rgAltEntry = &entry;
1292 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1293 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1294 ok(!ret && GetLastError() == E_INVALIDARG,
1295 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1296 /* Test with an empty pointer */
1297 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1298 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1299 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1302 ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1303 ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1306 /* Test with a real URL */
1307 U(entry).pwszURL = (LPWSTR)url;
1308 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1309 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1312 ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1313 ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1316 /* Now with the URL containing an invalid IA5 char */
1317 U(entry).pwszURL = (LPWSTR)nihongoURL;
1318 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1319 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1320 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1321 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1322 /* The first invalid character is at index 7 */
1323 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1324 "Expected invalid char at index 7, got %d\n",
1325 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1326 /* Now with the URL missing a scheme */
1327 U(entry).pwszURL = (LPWSTR)dnsName;
1328 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1329 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1330 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1333 /* This succeeds, but it shouldn't, so don't worry about conforming */
1336 /* Now with a DNS name */
1337 entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1338 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1339 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1340 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1343 ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1344 ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1347 /* Test with an IP address */
1348 entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1349 U(entry).IPAddress.cbData = sizeof(localhost);
1350 U(entry).IPAddress.pbData = (LPBYTE)localhost;
1351 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1352 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1355 ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1356 ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1361 static void test_decodeAltName(DWORD dwEncoding)
1363 static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1365 static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1370 CERT_ALT_NAME_INFO *info;
1372 /* Test some bogus ones first */
1373 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1374 unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1375 NULL, (BYTE *)&buf, &bufSize);
1376 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1377 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1378 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1379 bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1381 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1382 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
1383 /* Now expected cases */
1384 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1385 emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1387 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1390 info = (CERT_ALT_NAME_INFO *)buf;
1392 ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1396 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1397 emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1399 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1402 info = (CERT_ALT_NAME_INFO *)buf;
1404 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1406 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1407 "Expected CERT_ALT_NAME_URL, got %d\n",
1408 info->rgAltEntry[0].dwAltNameChoice);
1409 ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1410 "Expected empty URL\n");
1413 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1414 encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1416 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1419 info = (CERT_ALT_NAME_INFO *)buf;
1421 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1423 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1424 "Expected CERT_ALT_NAME_URL, got %d\n",
1425 info->rgAltEntry[0].dwAltNameChoice);
1426 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1429 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1430 encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1432 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1435 info = (CERT_ALT_NAME_INFO *)buf;
1437 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1439 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1440 "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1441 info->rgAltEntry[0].dwAltNameChoice);
1442 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1443 "Unexpected DNS name\n");
1446 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1447 encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1449 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1452 info = (CERT_ALT_NAME_INFO *)buf;
1454 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1456 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1457 "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1458 info->rgAltEntry[0].dwAltNameChoice);
1459 ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1460 "Unexpected IP address length %d\n",
1461 U(info->rgAltEntry[0]).IPAddress.cbData);
1462 ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1463 sizeof(localhost)), "Unexpected IP address value\n");
1468 struct UnicodeExpectedError
1476 static const WCHAR oneW[] = { '1',0 };
1477 static const WCHAR aW[] = { 'a',0 };
1478 static const WCHAR quoteW[] = { '"', 0 };
1480 static struct UnicodeExpectedError unicodeErrors[] = {
1481 { CERT_RDN_ANY_TYPE, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1482 { CERT_RDN_ENCODED_BLOB, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1483 { CERT_RDN_OCTET_STRING, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1484 { 14, oneW, 0, CRYPT_E_ASN1_CHOICE },
1485 { CERT_RDN_NUMERIC_STRING, aW, 0, CRYPT_E_INVALID_NUMERIC_STRING },
1486 { CERT_RDN_PRINTABLE_STRING, quoteW, 0, CRYPT_E_INVALID_PRINTABLE_STRING },
1487 { CERT_RDN_IA5_STRING, nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1490 struct UnicodeExpectedResult
1494 CRYPT_DATA_BLOB encoded;
1497 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1498 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1499 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1500 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1501 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1502 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1503 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1504 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1505 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1506 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1507 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1508 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1510 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1512 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1513 0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1514 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1515 0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1517 static struct UnicodeExpectedResult unicodeResults[] = {
1518 { CERT_RDN_NUMERIC_STRING, oneW, { sizeof(oneNumeric), oneNumeric } },
1519 { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1520 { CERT_RDN_TELETEX_STRING, oneW, { sizeof(oneTeletex), oneTeletex } },
1521 { CERT_RDN_VIDEOTEX_STRING, oneW, { sizeof(oneVideotex), oneVideotex } },
1522 { CERT_RDN_IA5_STRING, oneW, { sizeof(oneIA5), oneIA5 } },
1523 { CERT_RDN_GRAPHIC_STRING, oneW, { sizeof(oneGraphic), oneGraphic } },
1524 { CERT_RDN_VISIBLE_STRING, oneW, { sizeof(oneVisible), oneVisible } },
1525 { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1526 { CERT_RDN_GENERAL_STRING, oneW, { sizeof(oneGeneral), oneGeneral } },
1527 { CERT_RDN_BMP_STRING, oneW, { sizeof(oneBMP), oneBMP } },
1528 { CERT_RDN_UTF8_STRING, oneW, { sizeof(oneUTF8), oneUTF8 } },
1529 { CERT_RDN_BMP_STRING, nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1530 { CERT_RDN_UTF8_STRING, nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1533 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1534 { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1535 { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1538 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1543 CERT_NAME_VALUE value;
1545 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1546 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1547 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1548 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1549 /* Have to have a string of some sort */
1550 value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1551 value.Value.pbData = NULL;
1552 value.Value.cbData = 0;
1553 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1554 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1555 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1556 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1557 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1558 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1559 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1560 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1561 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1562 value.dwValueType = CERT_RDN_ANY_TYPE;
1563 value.Value.pbData = (LPBYTE)oneW;
1564 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1565 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1566 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1567 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1568 value.Value.cbData = sizeof(oneW);
1569 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1570 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1571 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1572 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1573 /* An encoded string with specified length isn't good enough either */
1574 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1575 value.Value.pbData = oneUniversal;
1576 value.Value.cbData = sizeof(oneUniversal);
1577 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1578 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1579 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1580 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1581 /* More failure checking */
1582 value.Value.cbData = 0;
1583 for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1585 value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1586 value.dwValueType = unicodeErrors[i].valueType;
1587 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1588 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1589 ok(!ret && GetLastError() == unicodeErrors[i].error,
1590 "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1591 unicodeErrors[i].error, GetLastError());
1592 ok(size == unicodeErrors[i].errorIndex,
1593 "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1596 /* cbData can be zero if the string is NULL-terminated */
1597 value.Value.cbData = 0;
1598 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1600 value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1601 value.dwValueType = unicodeResults[i].valueType;
1602 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1603 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1604 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1607 ok(size == unicodeResults[i].encoded.cbData,
1608 "Value type %d: expected size %d, got %d\n",
1609 value.dwValueType, unicodeResults[i].encoded.cbData, size);
1610 ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1611 "Value type %d: unexpected value\n", value.dwValueType);
1615 /* These "encode," but they do so by truncating each unicode character
1616 * rather than properly encoding it. Kept separate from the proper results,
1617 * because the encoded forms won't decode to their original strings.
1619 for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1621 value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1622 value.dwValueType = unicodeWeirdness[i].valueType;
1623 ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1624 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1625 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1628 ok(size == unicodeWeirdness[i].encoded.cbData,
1629 "Value type %d: expected size %d, got %d\n",
1630 value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1631 ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1632 "Value type %d: unexpected value\n", value.dwValueType);
1638 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1640 if (n <= 0) return 0;
1641 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1642 return *str1 - *str2;
1645 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1649 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1655 ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1656 unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1657 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1658 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1661 PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1663 ok(value->dwValueType == unicodeResults[i].valueType,
1664 "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1665 value->dwValueType);
1666 ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1667 value->Value.cbData / sizeof(WCHAR)),
1668 "Unexpected decoded value for index %d (value type %d)\n", i,
1669 unicodeResults[i].valueType);
1675 struct encodedOctets
1678 const BYTE *encoded;
1681 static const unsigned char bin46[] = { 'h','i',0 };
1682 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1683 static const unsigned char bin48[] = {
1684 's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1685 static const unsigned char bin49[] = {
1686 0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1687 static const unsigned char bin50[] = { 0 };
1688 static const unsigned char bin51[] = { 0x04,0x00,0 };
1690 static const struct encodedOctets octets[] = {
1696 static void test_encodeOctets(DWORD dwEncoding)
1698 CRYPT_DATA_BLOB blob;
1701 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1707 blob.cbData = strlen((const char*)octets[i].val);
1708 blob.pbData = (BYTE*)octets[i].val;
1709 ret = CryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1710 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1711 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1715 "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1716 ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1717 buf[1], octets[i].encoded[1]);
1718 ok(!memcmp(buf + 1, octets[i].encoded + 1,
1719 octets[i].encoded[1] + 1), "Got unexpected value\n");
1725 static void test_decodeOctets(DWORD dwEncoding)
1729 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1735 ret = CryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1736 (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1737 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1738 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1739 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1740 "Expected size >= %d, got %d\n",
1741 (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1742 ok(buf != NULL, "Expected allocated buffer\n");
1745 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1748 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1749 "Unexpected value\n");
1755 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1760 const BYTE *encoded;
1762 const BYTE *decoded;
1765 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1766 static const unsigned char bin53[] = { 0xff,0xff };
1767 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1768 static const unsigned char bin55[] = { 0xff,0xfe };
1769 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1770 static const unsigned char bin57[] = { 0xfe };
1771 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1773 static const struct encodedBits bits[] = {
1774 /* normal test cases */
1775 { 0, bin52, 2, bin53 },
1776 { 1, bin54, 2, bin55 },
1777 /* strange test case, showing cUnusedBits >= 8 is allowed */
1778 { 9, bin56, 1, bin57 },
1779 /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1780 { 17, bin58, 0, NULL },
1783 static void test_encodeBits(DWORD dwEncoding)
1787 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1789 CRYPT_BIT_BLOB blob;
1794 blob.cbData = sizeof(bytesToEncode);
1795 blob.pbData = (BYTE *)bytesToEncode;
1796 blob.cUnusedBits = bits[i].cUnusedBits;
1797 ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1798 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1799 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1802 ok(bufSize == bits[i].encoded[1] + 2,
1803 "Got unexpected size %d, expected %d\n", bufSize,
1804 bits[i].encoded[1] + 2);
1805 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1806 "Unexpected value\n");
1812 static void test_decodeBits(DWORD dwEncoding)
1814 static const BYTE ber[] = "\x03\x02\x01\xff";
1815 static const BYTE berDecoded = 0xfe;
1822 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1824 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1825 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1827 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1830 CRYPT_BIT_BLOB *blob;
1832 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1833 "Got unexpected size %d, expected >= %d\n", bufSize,
1834 sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded);
1835 blob = (CRYPT_BIT_BLOB *)buf;
1836 ok(blob->cbData == bits[i].cbDecoded,
1837 "Got unexpected length %d, expected %d\n", blob->cbData,
1839 if (blob->cbData && bits[i].cbDecoded)
1840 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1841 "Unexpected value\n");
1845 /* special case: check that something that's valid in BER but not in DER
1846 * decodes successfully
1848 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1849 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1850 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1853 CRYPT_BIT_BLOB *blob;
1855 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1856 "Got unexpected size %d\n", bufSize);
1857 blob = (CRYPT_BIT_BLOB *)buf;
1858 ok(blob->cbData == sizeof(berDecoded),
1859 "Got unexpected length %d\n", blob->cbData);
1861 ok(*blob->pbData == berDecoded, "Unexpected value\n");
1868 CERT_BASIC_CONSTRAINTS2_INFO info;
1869 const BYTE *encoded;
1872 static const unsigned char bin59[] = { 0x30,0x00 };
1873 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
1874 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
1875 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1876 static const struct Constraints2 constraints2[] = {
1877 /* empty constraints */
1878 { { FALSE, FALSE, 0}, bin59 },
1880 { { TRUE, FALSE, 0}, bin60 },
1881 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1882 * but that's not the case
1884 { { FALSE, TRUE, 0}, bin61 },
1885 /* can be a CA and has path length constraints set */
1886 { { TRUE, TRUE, 1}, bin62 },
1889 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
1890 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
1891 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
1892 0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
1893 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1894 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
1895 0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
1896 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
1897 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
1898 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1900 static void test_encodeBasicConstraints(DWORD dwEncoding)
1902 DWORD i, bufSize = 0;
1903 CERT_BASIC_CONSTRAINTS_INFO info;
1904 CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
1905 (LPBYTE)encodedDomainName };
1909 /* First test with the simpler info2 */
1910 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1912 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1913 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1915 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1918 ok(bufSize == constraints2[i].encoded[1] + 2,
1919 "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
1921 ok(!memcmp(buf, constraints2[i].encoded,
1922 constraints2[i].encoded[1] + 2), "Unexpected value\n");
1926 /* Now test with more complex basic constraints */
1927 info.SubjectType.cbData = 0;
1928 info.fPathLenConstraint = FALSE;
1929 info.cSubtreesConstraint = 0;
1930 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1931 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1932 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1935 ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
1936 ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
1937 "Unexpected value\n");
1940 /* None of the certs I examined had any subtree constraint, but I test one
1941 * anyway just in case.
1943 info.cSubtreesConstraint = 1;
1944 info.rgSubtreesConstraint = &nameBlob;
1945 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1946 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1947 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1950 ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
1951 ok(!memcmp(buf, constraintWithDomainName,
1952 sizeof(constraintWithDomainName)), "Unexpected value\n");
1955 /* FIXME: test encoding with subject type. */
1958 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
1959 static const unsigned char encodedCommonName[] = {
1960 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1962 static void test_decodeBasicConstraints(DWORD dwEncoding)
1964 static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
1966 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
1972 /* First test with simpler info2 */
1973 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1975 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1976 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
1977 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1978 ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
1982 CERT_BASIC_CONSTRAINTS2_INFO *info =
1983 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1985 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
1986 "Unexpected value for item %d\n", i);
1990 /* Check with the order of encoded elements inverted */
1992 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1993 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1995 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1996 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
1997 ok(!buf, "Expected buf to be set to NULL\n");
1998 /* Check with a non-DER bool */
1999 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2000 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2001 (BYTE *)&buf, &bufSize);
2002 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2005 CERT_BASIC_CONSTRAINTS2_INFO *info =
2006 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2008 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2011 /* Check with a non-basic constraints value */
2012 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2013 (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
2014 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2015 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2016 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2017 /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2018 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2019 emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2020 (BYTE *)&buf, &bufSize);
2021 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2024 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2026 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2027 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2028 ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2031 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2032 constraintWithDomainName, sizeof(constraintWithDomainName),
2033 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2034 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2037 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2039 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2040 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2041 ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2042 if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2044 ok(info->rgSubtreesConstraint[0].cbData ==
2045 sizeof(encodedDomainName), "Wrong size %d\n",
2046 info->rgSubtreesConstraint[0].cbData);
2047 ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2048 sizeof(encodedDomainName)), "Unexpected value\n");
2054 /* These are terrible public keys of course, I'm just testing encoding */
2055 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2056 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2057 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2058 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2059 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2060 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2061 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2062 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2064 struct EncodedRSAPubKey
2066 const BYTE *modulus;
2068 const BYTE *encoded;
2069 size_t decodedModulusLen;
2072 struct EncodedRSAPubKey rsaPubKeys[] = {
2073 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2074 { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2075 { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2076 { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2079 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2081 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2082 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2083 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2086 DWORD bufSize = 0, i;
2088 /* Try with a bogus blob type */
2090 hdr->bVersion = CUR_BLOB_VERSION;
2092 hdr->aiKeyAlg = CALG_RSA_KEYX;
2093 rsaPubKey->magic = 0x31415352;
2094 rsaPubKey->bitlen = sizeof(modulus1) * 8;
2095 rsaPubKey->pubexp = 65537;
2096 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2099 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2100 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2102 ok(!ret && GetLastError() == E_INVALIDARG,
2103 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2104 /* Now with a bogus reserved field */
2105 hdr->bType = PUBLICKEYBLOB;
2107 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2108 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2112 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2113 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2114 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2117 /* Now with a bogus blob version */
2120 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2121 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2125 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2126 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2127 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2130 /* And with a bogus alg ID */
2131 hdr->bVersion = CUR_BLOB_VERSION;
2132 hdr->aiKeyAlg = CALG_DES;
2133 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2134 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2138 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2139 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2140 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2143 /* Check a couple of RSA-related OIDs */
2144 hdr->aiKeyAlg = CALG_RSA_KEYX;
2145 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2146 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2147 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2148 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2149 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2150 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2151 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2152 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2153 /* Finally, all valid */
2154 hdr->aiKeyAlg = CALG_RSA_KEYX;
2155 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2157 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2158 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2159 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2160 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2161 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2164 ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2165 "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2167 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2168 "Unexpected value\n");
2174 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2181 /* Try with a bad length */
2182 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2183 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2184 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2185 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2186 "Expected CRYPT_E_ASN1_EOD, got %08x\n", CRYPT_E_ASN1_EOD);
2187 /* Try with a couple of RSA-related OIDs */
2188 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2189 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2190 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2191 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2192 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2193 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2194 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2195 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2196 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2197 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2198 /* Now try success cases */
2199 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2202 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2203 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2204 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2205 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2208 BLOBHEADER *hdr = (BLOBHEADER *)buf;
2209 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2211 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2212 rsaPubKeys[i].decodedModulusLen,
2213 "Wrong size %d\n", bufSize);
2214 ok(hdr->bType == PUBLICKEYBLOB,
2215 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2217 ok(hdr->bVersion == CUR_BLOB_VERSION,
2218 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2219 CUR_BLOB_VERSION, hdr->bVersion);
2220 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2222 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2223 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2224 ok(rsaPubKey->magic == 0x31415352,
2225 "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2226 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2227 "Wrong bit len %d\n", rsaPubKey->bitlen);
2228 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2230 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2231 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2232 "Unexpected modulus\n");
2238 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2239 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2240 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2242 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2243 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2244 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2245 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2247 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2249 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2250 CRYPT_SEQUENCE_OF_ANY seq;
2256 /* Encode a homogenous sequence */
2257 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2259 blobs[i].cbData = ints[i].encoded[1] + 2;
2260 blobs[i].pbData = (BYTE *)ints[i].encoded;
2262 seq.cValue = sizeof(ints) / sizeof(ints[0]);
2263 seq.rgValue = blobs;
2265 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2266 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2267 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2270 ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2271 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2274 /* Change the type of the first element in the sequence, and give it
2277 blobs[0].cbData = times[0].encodedTime[1] + 2;
2278 blobs[0].pbData = (BYTE *)times[0].encodedTime;
2279 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2280 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2281 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2284 ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2285 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2286 "Unexpected value\n");
2291 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2297 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2298 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2299 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2302 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2305 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2306 "Wrong elements %d\n", seq->cValue);
2307 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2309 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2310 "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2311 seq->rgValue[i].cbData);
2312 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2313 ints[i].encoded[1] + 2), "Unexpected value\n");
2317 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2318 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2320 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2323 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2325 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2326 "Wrong elements %d\n", seq->cValue);
2327 /* Just check the first element since it's all that changed */
2328 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2329 "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2330 seq->rgValue[0].cbData);
2331 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2332 times[0].encodedTime[1] + 2), "Unexpected value\n");
2337 struct encodedExtensions
2339 CERT_EXTENSIONS exts;
2340 const BYTE *encoded;
2343 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2344 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2345 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2346 static CERT_EXTENSION criticalExt =
2347 { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2348 static CERT_EXTENSION nonCriticalExt =
2349 { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2351 static const BYTE ext0[] = { 0x30,0x00 };
2352 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2353 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2354 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2355 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2357 static const struct encodedExtensions exts[] = {
2358 { { 0, NULL }, ext0 },
2359 { { 1, &criticalExt }, ext1 },
2360 { { 1, &nonCriticalExt }, ext2 },
2363 static void test_encodeExtensions(DWORD dwEncoding)
2367 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2373 ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2374 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2375 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2378 ok(bufSize == exts[i].encoded[1] + 2,
2379 "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2380 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2381 "Unexpected value\n");
2387 static void test_decodeExtensions(DWORD dwEncoding)
2391 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2397 ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2398 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2399 NULL, (BYTE *)&buf, &bufSize);
2400 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2403 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2406 ok(ext->cExtension == exts[i].exts.cExtension,
2407 "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2409 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2411 ok(!strcmp(ext->rgExtension[j].pszObjId,
2412 exts[i].exts.rgExtension[j].pszObjId),
2413 "Expected OID %s, got %s\n",
2414 exts[i].exts.rgExtension[j].pszObjId,
2415 ext->rgExtension[j].pszObjId);
2416 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2417 exts[i].exts.rgExtension[j].Value.pbData,
2418 exts[i].exts.rgExtension[j].Value.cbData),
2419 "Unexpected value\n");
2426 /* MS encodes public key info with a NULL if the algorithm identifier's
2427 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
2428 * it encodes them by omitting the algorithm parameters. This latter approach
2429 * seems more correct, so accept either form.
2431 struct encodedPublicKey
2433 CERT_PUBLIC_KEY_INFO info;
2434 const BYTE *encoded;
2435 const BYTE *encodedNoNull;
2436 CERT_PUBLIC_KEY_INFO decoded;
2439 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2441 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2443 static const unsigned char bin64[] = {
2444 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2445 static const unsigned char bin65[] = {
2446 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2447 static const unsigned char bin66[] = {
2448 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2449 static const unsigned char bin67[] = {
2450 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2451 static const unsigned char bin68[] = {
2452 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2453 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2454 static const unsigned char bin69[] = {
2455 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2456 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2457 static const unsigned char bin70[] = {
2458 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2459 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2461 static const unsigned char bin71[] = {
2462 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2463 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2465 static unsigned char bin72[] = { 0x05,0x00};
2467 static CHAR oid_bogus[] = "1.2.3",
2468 oid_rsa[] = szOID_RSA;
2470 static const struct encodedPublicKey pubKeys[] = {
2471 /* with a bogus OID */
2472 { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2474 { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2475 /* some normal keys */
2476 { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2478 { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2479 { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2481 { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2482 /* with add'l parameters--note they must be DER-encoded */
2483 { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2484 (BYTE *)aKey, 0 } },
2486 { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2487 (BYTE *)aKey, 0 } } },
2490 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2494 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2500 ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2501 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2503 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2506 ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2507 bufSize == pubKeys[i].encodedNoNull[1] + 2,
2508 "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2509 pubKeys[i].encodedNoNull[1] + 2, bufSize);
2510 if (bufSize == pubKeys[i].encoded[1] + 2)
2511 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2512 "Unexpected value\n");
2513 else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2514 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2515 pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2521 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2522 const CERT_PUBLIC_KEY_INFO *got)
2524 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2525 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2526 got->Algorithm.pszObjId);
2527 ok(expected->Algorithm.Parameters.cbData ==
2528 got->Algorithm.Parameters.cbData,
2529 "Expected parameters of %d bytes, got %d\n",
2530 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2531 if (expected->Algorithm.Parameters.cbData)
2532 ok(!memcmp(expected->Algorithm.Parameters.pbData,
2533 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2534 "Unexpected algorithm parameters\n");
2535 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2536 "Expected public key of %d bytes, got %d\n",
2537 expected->PublicKey.cbData, got->PublicKey.cbData);
2538 if (expected->PublicKey.cbData)
2539 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2540 got->PublicKey.cbData), "Unexpected public key value\n");
2543 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2545 static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2546 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2547 0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2548 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2554 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2556 /* The NULL form decodes to the decoded member */
2557 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2558 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2559 NULL, (BYTE *)&buf, &bufSize);
2560 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2563 comparePublicKeyInfo(&pubKeys[i].decoded,
2564 (CERT_PUBLIC_KEY_INFO *)buf);
2567 /* The non-NULL form decodes to the original */
2568 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2569 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2570 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2571 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2574 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2578 /* Test with bogus (not valid DER) parameters */
2579 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2580 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2581 NULL, (BYTE *)&buf, &bufSize);
2582 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2583 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2586 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2587 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2588 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2589 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2590 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2591 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2592 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2593 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2594 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2595 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2596 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2597 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2598 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2599 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2600 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2601 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2602 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2603 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2604 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2605 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2606 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2607 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2608 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2609 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2610 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2611 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2612 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2613 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2614 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2615 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2616 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2617 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2618 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2619 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2620 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2621 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2622 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2623 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2624 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2626 static const BYTE serialNum[] = { 0x01 };
2628 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2633 CERT_INFO info = { 0 };
2635 /* Test with NULL pvStructInfo */
2636 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2637 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2638 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2639 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2640 /* Test with a V1 cert */
2641 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2642 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2643 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2646 ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2647 v1Cert[1] + 2, size);
2648 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2652 info.dwVersion = CERT_V2;
2653 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2654 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2655 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2658 ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2659 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2663 info.dwVersion = CERT_V3;
2664 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2665 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2666 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2669 ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2670 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2673 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2674 * API doesn't prevent it)
2676 info.dwVersion = CERT_V1;
2677 info.cExtension = 1;
2678 info.rgExtension = &criticalExt;
2679 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2680 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2681 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2684 ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2685 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2688 /* test v1 cert with a serial number */
2689 info.SerialNumber.cbData = sizeof(serialNum);
2690 info.SerialNumber.pbData = (BYTE *)serialNum;
2691 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2692 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2695 ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2696 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2699 /* Test v1 cert with an issuer name, a subject name, and a serial number */
2700 info.Issuer.cbData = sizeof(encodedCommonName);
2701 info.Issuer.pbData = (BYTE *)encodedCommonName;
2702 info.Subject.cbData = sizeof(encodedCommonName);
2703 info.Subject.pbData = (BYTE *)encodedCommonName;
2704 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2705 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2708 ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2709 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2712 /* for now, I let more interesting tests be done for each subcomponent,
2713 * rather than retesting them all here.
2717 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2719 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2720 v1CertWithConstraints, v1CertWithSerial };
2725 /* Test with NULL pbEncoded */
2726 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2727 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2728 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2729 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2730 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2731 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2732 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2733 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2734 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2735 * minimum a cert must have a non-zero serial number, an issuer, and a
2738 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2740 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2741 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2742 (BYTE *)&buf, &size);
2743 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
2744 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2746 /* Now check with serial number, subject and issuer specified */
2747 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2748 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2749 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2752 CERT_INFO *info = (CERT_INFO *)buf;
2754 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2755 ok(info->SerialNumber.cbData == 1,
2756 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2757 ok(*info->SerialNumber.pbData == *serialNum,
2758 "Expected serial number %d, got %d\n", *serialNum,
2759 *info->SerialNumber.pbData);
2760 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2761 "Wrong size %d\n", info->Issuer.cbData);
2762 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2763 "Unexpected issuer\n");
2764 ok(info->Subject.cbData == sizeof(encodedCommonName),
2765 "Wrong size %d\n", info->Subject.cbData);
2766 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2767 info->Subject.cbData), "Unexpected subject\n");
2772 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2775 static const BYTE signedBigCert[] = {
2776 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
2777 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2778 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
2779 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2780 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2781 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
2782 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
2783 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
2784 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
2785 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2786 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
2787 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
2789 static void test_encodeCert(DWORD dwEncoding)
2791 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
2792 * also that bigCert is a NULL-terminated string, so don't count its
2793 * last byte (otherwise the signed cert won't decode.)
2795 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
2796 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
2801 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
2802 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2803 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2806 ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
2807 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
2812 static void test_decodeCert(DWORD dwEncoding)
2818 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
2819 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2820 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2823 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
2825 ok(info->ToBeSigned.cbData == sizeof(bigCert),
2826 "Wrong cert size %d\n", info->ToBeSigned.cbData);
2827 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
2828 "Unexpected cert\n");
2829 ok(info->Signature.cbData == sizeof(hash),
2830 "Wrong signature size %d\n", info->Signature.cbData);
2831 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
2832 "Unexpected signature\n");
2835 /* A signed cert decodes as a CERT_INFO too */
2836 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
2837 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2838 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2841 CERT_INFO *info = (CERT_INFO *)buf;
2843 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2844 ok(info->SerialNumber.cbData == 1,
2845 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2846 ok(*info->SerialNumber.pbData == *serialNum,
2847 "Expected serial number %d, got %d\n", *serialNum,
2848 *info->SerialNumber.pbData);
2849 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2850 "Wrong size %d\n", info->Issuer.cbData);
2851 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2852 "Unexpected issuer\n");
2853 ok(info->Subject.cbData == sizeof(encodedCommonName),
2854 "Wrong size %d\n", info->Subject.cbData);
2855 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2856 info->Subject.cbData), "Unexpected subject\n");
2861 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
2862 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
2863 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
2864 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2865 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
2867 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
2868 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
2869 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2870 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
2871 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
2872 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
2873 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
2874 0x2e, 0x6f, 0x72, 0x67 };
2875 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
2876 CRL_REASON_AFFILIATION_CHANGED;
2878 static void test_encodeCRLDistPoints(DWORD dwEncoding)
2880 CRL_DIST_POINTS_INFO info = { 0 };
2881 CRL_DIST_POINT point = { { 0 } };
2882 CERT_ALT_NAME_ENTRY entry = { 0 };
2887 /* Test with an empty info */
2888 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2889 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2890 ok(!ret && GetLastError() == E_INVALIDARG,
2891 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2892 /* Test with one empty dist point */
2893 info.cDistPoint = 1;
2894 info.rgDistPoint = &point;
2895 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2896 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2899 ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
2900 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
2903 /* A dist point with an invalid name */
2904 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2905 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
2906 U(entry).pwszURL = (LPWSTR)nihongoURL;
2907 U(point.DistPointName).FullName.cAltEntry = 1;
2908 U(point.DistPointName).FullName.rgAltEntry = &entry;
2909 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2910 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2911 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
2912 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
2913 /* The first invalid character is at index 7 */
2914 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
2915 "Expected invalid char at index 7, got %d\n",
2916 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
2917 /* A dist point with (just) a valid name */
2918 U(entry).pwszURL = (LPWSTR)url;
2919 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2920 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2923 ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
2924 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
2927 /* A dist point with (just) reason flags */
2928 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
2929 point.ReasonFlags.cbData = sizeof(crlReason);
2930 point.ReasonFlags.pbData = (LPBYTE)&crlReason;
2931 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2932 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2935 ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
2936 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
2939 /* A dist point with just an issuer */
2940 point.ReasonFlags.cbData = 0;
2941 point.CRLIssuer.cAltEntry = 1;
2942 point.CRLIssuer.rgAltEntry = &entry;
2943 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2944 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2947 ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
2948 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
2951 /* A dist point with both a name and an issuer */
2952 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2953 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2954 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2957 ok(size == sizeof(distPointWithUrlAndIssuer),
2958 "Wrong size %d\n", size);
2959 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
2964 static void test_decodeCRLDistPoints(DWORD dwEncoding)
2969 PCRL_DIST_POINTS_INFO info;
2970 PCRL_DIST_POINT point;
2971 PCERT_ALT_NAME_ENTRY entry;
2973 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2974 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2975 (BYTE *)&buf, &size);
2978 info = (PCRL_DIST_POINTS_INFO)buf;
2979 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2980 "Wrong size %d\n", size);
2981 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
2983 point = info->rgDistPoint;
2984 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
2985 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
2986 point->DistPointName.dwDistPointNameChoice);
2987 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2988 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2991 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2992 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2993 (BYTE *)&buf, &size);
2996 info = (PCRL_DIST_POINTS_INFO)buf;
2997 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2998 "Wrong size %d\n", size);
2999 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3001 point = info->rgDistPoint;
3002 ok(point->DistPointName.dwDistPointNameChoice ==
3003 CRL_DIST_POINT_FULL_NAME,
3004 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3005 point->DistPointName.dwDistPointNameChoice);
3006 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3007 "Expected 1 name entry, got %d\n",
3008 U(point->DistPointName).FullName.cAltEntry);
3009 entry = U(point->DistPointName).FullName.rgAltEntry;
3010 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3011 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3012 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3013 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3014 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3017 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3018 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3019 NULL, (BYTE *)&buf, &size);
3022 info = (PCRL_DIST_POINTS_INFO)buf;
3023 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3024 "Wrong size %d\n", size);
3025 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3027 point = info->rgDistPoint;
3028 ok(point->DistPointName.dwDistPointNameChoice ==
3029 CRL_DIST_POINT_NO_NAME,
3030 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3031 point->DistPointName.dwDistPointNameChoice);
3032 ok(point->ReasonFlags.cbData == sizeof(crlReason),
3033 "Expected reason length\n");
3034 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3035 "Unexpected reason\n");
3036 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3039 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3040 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3041 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3044 info = (PCRL_DIST_POINTS_INFO)buf;
3045 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3046 "Wrong size %d\n", size);
3047 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3049 point = info->rgDistPoint;
3050 ok(point->DistPointName.dwDistPointNameChoice ==
3051 CRL_DIST_POINT_FULL_NAME,
3052 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3053 point->DistPointName.dwDistPointNameChoice);
3054 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3055 "Expected 1 name entry, got %d\n",
3056 U(point->DistPointName).FullName.cAltEntry);
3057 entry = U(point->DistPointName).FullName.rgAltEntry;
3058 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3059 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3060 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3061 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3062 ok(point->CRLIssuer.cAltEntry == 1,
3063 "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3064 entry = point->CRLIssuer.rgAltEntry;
3065 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3066 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3067 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3072 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3073 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3074 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3075 0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3078 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3083 CRL_ISSUING_DIST_POINT point = { { 0 } };
3084 CERT_ALT_NAME_ENTRY entry;
3086 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3087 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3088 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3089 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3090 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3091 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3092 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3095 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3096 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3099 /* nonsensical flags */
3100 point.fOnlyContainsUserCerts = TRUE;
3101 point.fOnlyContainsCACerts = TRUE;
3102 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3103 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3104 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3107 ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3108 ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3111 /* unimplemented name type */
3112 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3113 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3114 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3115 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3116 ok(!ret && GetLastError() == E_INVALIDARG,
3117 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3119 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3120 U(point.DistPointName).FullName.cAltEntry = 0;
3121 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3122 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3123 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3126 ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3127 ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3130 /* name with URL entry */
3131 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3132 U(entry).pwszURL = (LPWSTR)url;
3133 U(point.DistPointName).FullName.cAltEntry = 1;
3134 U(point.DistPointName).FullName.rgAltEntry = &entry;
3135 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3136 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3137 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3140 ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3141 ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3146 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3147 const CERT_ALT_NAME_ENTRY *got)
3149 ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3150 "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3151 got->dwAltNameChoice);
3152 if (expected->dwAltNameChoice == got->dwAltNameChoice)
3154 switch (got->dwAltNameChoice)
3156 case CERT_ALT_NAME_RFC822_NAME:
3157 case CERT_ALT_NAME_DNS_NAME:
3158 case CERT_ALT_NAME_EDI_PARTY_NAME:
3159 case CERT_ALT_NAME_URL:
3160 case CERT_ALT_NAME_REGISTERED_ID:
3161 ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3162 !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL), "Unexpected name\n");
3164 case CERT_ALT_NAME_X400_ADDRESS:
3165 case CERT_ALT_NAME_DIRECTORY_NAME:
3166 case CERT_ALT_NAME_IP_ADDRESS:
3167 ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3168 "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3169 ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3170 U(*got).IPAddress.cbData), "Unexpected value\n");
3176 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3177 const CERT_ALT_NAME_INFO *got)
3181 ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3182 expected->cAltEntry, got->cAltEntry);
3183 for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3184 compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3187 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3188 const CRL_DIST_POINT_NAME *got)
3190 ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3191 "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3192 if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3193 compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3196 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3197 const CRL_ISSUING_DIST_POINT *got)
3199 compareDistPointName(&expected->DistPointName, &got->DistPointName);
3200 ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3201 "Unexpected fOnlyContainsUserCerts\n");
3202 ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3203 "Unexpected fOnlyContainsCACerts\n");
3204 ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3205 "Unexpected reason flags\n");
3206 ok(got->fIndirectCRL == expected->fIndirectCRL,
3207 "Unexpected fIndirectCRL\n");
3210 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3215 CRL_ISSUING_DIST_POINT point = { { 0 } };
3217 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3218 emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3219 (BYTE *)&buf, &size);
3220 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3223 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3226 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3227 badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3228 (BYTE *)&buf, &size);
3229 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3232 point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3233 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3236 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3237 emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3238 (BYTE *)&buf, &size);
3239 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3242 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3243 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3244 U(point.DistPointName).FullName.cAltEntry = 0;
3245 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3248 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3249 urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3250 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3253 CERT_ALT_NAME_ENTRY entry;
3255 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3256 U(entry).pwszURL = (LPWSTR)url;
3257 U(point.DistPointName).FullName.cAltEntry = 1;
3258 U(point.DistPointName).FullName.rgAltEntry = &entry;
3259 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3264 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3265 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3267 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3268 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3269 0x30, 0x30, 0x30, 0x30, 0x5a };
3270 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3271 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3272 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3273 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3275 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3276 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3277 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3278 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3279 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3280 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3281 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3282 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3283 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3284 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3285 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3286 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3287 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3288 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3289 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3290 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3291 0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3292 0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3293 0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3294 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3295 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3296 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3297 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3298 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3299 0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3300 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3301 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3302 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3303 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3304 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3305 0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3306 0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3307 0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3308 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3309 0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3310 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3311 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3312 0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3313 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3314 0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3316 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3320 static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3322 CRL_INFO info = { 0 };
3323 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3326 /* Test with a V1 CRL */
3327 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3328 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3329 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3332 ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3333 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3337 info.dwVersion = CRL_V2;
3338 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3339 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3340 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3343 ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3344 v2CRL[1] + 2, size);
3345 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3348 /* v1 CRL with a name */
3349 info.dwVersion = CRL_V1;
3350 info.Issuer.cbData = sizeof(encodedCommonName);
3351 info.Issuer.pbData = (BYTE *)encodedCommonName;
3352 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3353 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3354 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3357 ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3358 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3361 /* v1 CRL with a name and a NULL entry pointer */
3363 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3364 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3365 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3366 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3367 /* now set an empty entry */
3368 info.rgCRLEntry = &entry;
3369 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3370 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3373 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3374 "Wrong size %d\n", size);
3375 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3376 "Got unexpected value\n");
3379 /* an entry with a serial number */
3380 entry.SerialNumber.cbData = sizeof(serialNum);
3381 entry.SerialNumber.pbData = (BYTE *)serialNum;
3382 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3383 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3386 ok(size == sizeof(v1CRLWithIssuerAndEntry),
3387 "Wrong size %d\n", size);
3388 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3389 "Got unexpected value\n");
3392 /* an entry with an extension */
3393 entry.cExtension = 1;
3394 entry.rgExtension = &criticalExt;
3395 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3396 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3397 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3400 ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3401 ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3404 /* a CRL with an extension */
3405 entry.cExtension = 0;
3406 info.cExtension = 1;
3407 info.rgExtension = &criticalExt;
3408 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3409 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3410 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3413 ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3414 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3417 /* a v2 CRL with an extension, this time non-critical */
3418 info.dwVersion = CRL_V2;
3419 info.rgExtension = &nonCriticalExt;
3420 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3421 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3422 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3425 ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3426 ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3429 /* a v2 CRL with an issuing dist point extension */
3430 ext.pszObjId = oid_issuing_dist_point;
3431 ext.fCritical = TRUE;
3432 ext.Value.cbData = sizeof(urlIDP);
3433 ext.Value.pbData = (LPBYTE)urlIDP;
3434 entry.rgExtension = &ext;
3435 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3436 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3437 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3440 ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3441 ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3446 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3447 0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3448 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3449 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3450 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3451 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3452 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3453 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3454 0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3455 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3456 0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3457 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3458 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3459 0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3460 0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3461 0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3462 0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3463 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3464 0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3465 0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3466 0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3467 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3468 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3469 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3470 0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3471 0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3472 0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3473 0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3474 0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3475 0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3476 0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3477 0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3478 0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3479 0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3481 static const BYTE verisignCRLWithLotsOfEntries[] = {
3482 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3483 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3484 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3485 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3486 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3487 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3488 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3489 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3490 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3491 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3492 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3493 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3494 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3495 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3496 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3497 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3498 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3499 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3500 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3501 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3502 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3503 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3504 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3505 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3506 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3507 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3508 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3509 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3510 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3511 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3512 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3513 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3514 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3515 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3516 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3517 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3518 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3519 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3520 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3521 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3522 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3523 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3524 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3525 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3526 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3527 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3528 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3529 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3530 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3531 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3532 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3533 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3534 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3535 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3536 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3537 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3538 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3539 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3540 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3541 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3542 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3543 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3544 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3545 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3546 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3547 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3548 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3549 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3550 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3551 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3552 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3553 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3554 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3555 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3556 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3557 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3558 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3559 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3560 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3561 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3562 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3563 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3564 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3565 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3566 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3567 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3568 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3569 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3570 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3571 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3572 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3573 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3574 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3575 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3576 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3577 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3578 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3579 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3580 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3581 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3582 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3583 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3584 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3585 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3586 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3587 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3588 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3589 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3590 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3591 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3592 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3593 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3594 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3595 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3596 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3597 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3598 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3599 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3600 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3601 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3602 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3603 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3604 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3605 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3606 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3607 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3608 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3609 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3610 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3611 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3612 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3613 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3614 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3615 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3616 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3617 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3618 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3619 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3620 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3621 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3622 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3623 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3624 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3625 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3626 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3627 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3628 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3629 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3630 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3631 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3632 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3633 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3634 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3635 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3636 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3637 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3638 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3639 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3640 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3641 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3642 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3643 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3644 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3645 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3646 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3647 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3648 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3649 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3650 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3651 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3652 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3653 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3654 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3655 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3656 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3657 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3658 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3659 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3660 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3661 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3662 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3663 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3664 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3665 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3666 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3667 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3668 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3669 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
3670 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
3671 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
3672 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
3673 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
3674 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
3675 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
3676 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
3677 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
3678 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
3679 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
3680 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
3681 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
3682 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
3683 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
3684 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
3685 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
3686 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
3687 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
3688 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
3689 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
3690 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
3691 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
3692 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
3693 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
3694 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
3695 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
3696 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
3697 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
3698 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
3699 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
3700 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
3701 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
3702 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
3703 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
3704 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
3705 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
3706 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
3707 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
3708 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
3709 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
3710 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
3711 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
3712 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
3713 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
3714 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
3715 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
3716 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
3717 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
3718 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
3719 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
3720 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
3721 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
3722 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
3723 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
3724 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
3725 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
3726 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
3727 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
3728 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
3729 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
3730 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
3731 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
3732 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
3733 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
3734 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
3735 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
3736 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
3737 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
3738 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
3739 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
3740 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
3741 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
3742 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
3743 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
3744 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
3745 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
3746 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
3747 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
3748 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
3749 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
3750 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
3751 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
3752 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
3753 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
3754 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
3755 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
3756 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
3757 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
3758 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
3759 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
3760 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
3761 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
3762 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
3763 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
3764 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
3765 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
3766 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
3767 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
3768 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
3769 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
3770 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
3771 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
3772 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
3773 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
3774 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
3775 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
3776 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
3777 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
3778 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
3779 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
3780 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
3781 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
3782 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
3783 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
3784 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
3785 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
3786 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
3787 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
3788 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
3789 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
3790 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
3791 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
3792 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
3793 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
3794 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
3795 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
3796 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
3797 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
3798 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
3799 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
3800 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
3801 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
3802 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
3803 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
3804 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
3805 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
3806 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
3807 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
3808 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
3809 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
3810 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
3811 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
3812 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
3813 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
3814 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
3815 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
3816 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
3817 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
3818 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
3819 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
3820 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
3821 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
3822 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
3823 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
3824 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
3825 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
3826 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
3827 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
3828 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
3829 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
3830 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
3831 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
3832 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
3833 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
3834 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
3835 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
3836 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
3837 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
3838 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
3839 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
3840 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
3841 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
3842 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
3843 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
3844 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
3845 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
3846 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
3847 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
3848 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
3849 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
3850 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
3851 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
3852 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
3853 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
3854 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
3855 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
3856 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
3857 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
3858 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
3859 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
3860 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
3861 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
3862 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
3863 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
3864 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
3865 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
3866 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
3867 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
3868 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
3869 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
3870 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
3871 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
3872 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
3873 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
3874 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
3875 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
3876 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
3877 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
3878 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
3879 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
3880 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
3881 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
3882 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
3883 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
3884 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
3885 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
3886 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
3887 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
3888 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
3889 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
3890 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
3891 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
3892 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
3893 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
3894 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
3895 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
3896 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
3897 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
3898 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
3899 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
3900 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
3901 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
3902 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
3903 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
3904 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
3905 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
3906 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
3907 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
3908 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
3909 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
3910 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
3911 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
3912 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
3913 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
3914 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
3915 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
3916 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
3917 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
3918 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
3919 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
3920 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
3921 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
3922 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
3923 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
3924 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
3925 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
3926 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
3927 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
3928 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
3929 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
3930 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
3931 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
3932 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
3933 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
3934 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
3935 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
3936 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
3937 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
3938 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
3939 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
3940 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
3941 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
3942 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
3943 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
3944 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
3945 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
3946 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
3947 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
3948 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
3949 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
3950 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
3951 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
3952 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
3953 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
3954 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
3955 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
3956 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
3957 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
3958 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
3959 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
3960 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
3961 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
3962 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
3963 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
3964 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
3965 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
3966 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
3967 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
3968 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
3969 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
3970 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
3971 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
3972 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
3973 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
3974 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
3975 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
3976 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
3977 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
3978 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
3979 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
3980 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
3981 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
3982 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
3983 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
3984 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
3985 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
3986 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
3987 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
3988 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
3989 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
3991 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
3993 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
3998 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4000 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4001 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4002 (BYTE *)&buf, &size);
4003 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
4004 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4006 /* at a minimum, a CRL must contain an issuer: */
4007 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4008 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4009 (BYTE *)&buf, &size);
4010 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4013 CRL_INFO *info = (CRL_INFO *)buf;
4015 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4016 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4018 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4019 "Wrong issuer size %d\n", info->Issuer.cbData);
4020 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4021 "Unexpected issuer\n");
4024 /* check decoding with an empty CRL entry */
4025 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4026 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4027 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4028 todo_wine ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
4029 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4030 /* with a real CRL entry */
4031 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4032 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4033 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4034 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4037 CRL_INFO *info = (CRL_INFO *)buf;
4040 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4041 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4043 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4044 entry = info->rgCRLEntry;
4045 ok(entry->SerialNumber.cbData == 1,
4046 "Expected serial number size 1, got %d\n",
4047 entry->SerialNumber.cbData);
4048 ok(*entry->SerialNumber.pbData == *serialNum,
4049 "Expected serial number %d, got %d\n", *serialNum,
4050 *entry->SerialNumber.pbData);
4051 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4052 "Wrong issuer size %d\n", info->Issuer.cbData);
4053 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4054 "Unexpected issuer\n");
4056 /* a real CRL from verisign that has extensions */
4057 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4058 verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4059 NULL, (BYTE *)&buf, &size);
4060 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4063 CRL_INFO *info = (CRL_INFO *)buf;
4066 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4067 ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4069 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4070 entry = info->rgCRLEntry;
4071 ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4075 /* another real CRL from verisign that has lots of entries */
4076 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4077 verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4078 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4079 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4082 CRL_INFO *info = (CRL_INFO *)buf;
4084 ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %d\n",
4085 sizeof(CRL_INFO), 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();