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\n", bufSize);
1834 blob = (CRYPT_BIT_BLOB *)buf;
1835 ok(blob->cbData == bits[i].cbDecoded,
1836 "Got unexpected length %d, expected %d\n", blob->cbData,
1838 if (blob->cbData && bits[i].cbDecoded)
1839 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1840 "Unexpected value\n");
1844 /* special case: check that something that's valid in BER but not in DER
1845 * decodes successfully
1847 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1848 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1849 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1852 CRYPT_BIT_BLOB *blob;
1854 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1855 "Got unexpected size %d\n", bufSize);
1856 blob = (CRYPT_BIT_BLOB *)buf;
1857 ok(blob->cbData == sizeof(berDecoded),
1858 "Got unexpected length %d\n", blob->cbData);
1860 ok(*blob->pbData == berDecoded, "Unexpected value\n");
1867 CERT_BASIC_CONSTRAINTS2_INFO info;
1868 const BYTE *encoded;
1871 static const unsigned char bin59[] = { 0x30,0x00 };
1872 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
1873 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
1874 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1875 static const struct Constraints2 constraints2[] = {
1876 /* empty constraints */
1877 { { FALSE, FALSE, 0}, bin59 },
1879 { { TRUE, FALSE, 0}, bin60 },
1880 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1881 * but that's not the case
1883 { { FALSE, TRUE, 0}, bin61 },
1884 /* can be a CA and has path length constraints set */
1885 { { TRUE, TRUE, 1}, bin62 },
1888 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
1889 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
1890 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
1891 0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
1892 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1893 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
1894 0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
1895 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
1896 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
1897 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1899 static void test_encodeBasicConstraints(DWORD dwEncoding)
1901 DWORD i, bufSize = 0;
1902 CERT_BASIC_CONSTRAINTS_INFO info;
1903 CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
1904 (LPBYTE)encodedDomainName };
1908 /* First test with the simpler info2 */
1909 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1911 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1912 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1914 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1917 ok(bufSize == constraints2[i].encoded[1] + 2,
1918 "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
1920 ok(!memcmp(buf, constraints2[i].encoded,
1921 constraints2[i].encoded[1] + 2), "Unexpected value\n");
1925 /* Now test with more complex basic constraints */
1926 info.SubjectType.cbData = 0;
1927 info.fPathLenConstraint = FALSE;
1928 info.cSubtreesConstraint = 0;
1929 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1930 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1931 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1934 ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
1935 ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
1936 "Unexpected value\n");
1939 /* None of the certs I examined had any subtree constraint, but I test one
1940 * anyway just in case.
1942 info.cSubtreesConstraint = 1;
1943 info.rgSubtreesConstraint = &nameBlob;
1944 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1945 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1946 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1949 ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
1950 ok(!memcmp(buf, constraintWithDomainName,
1951 sizeof(constraintWithDomainName)), "Unexpected value\n");
1954 /* FIXME: test encoding with subject type. */
1957 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
1958 static const unsigned char encodedCommonName[] = {
1959 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1961 static void test_decodeBasicConstraints(DWORD dwEncoding)
1963 static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
1965 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
1971 /* First test with simpler info2 */
1972 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1974 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1975 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
1976 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1977 ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
1981 CERT_BASIC_CONSTRAINTS2_INFO *info =
1982 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1984 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
1985 "Unexpected value for item %d\n", i);
1989 /* Check with the order of encoded elements inverted */
1991 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1992 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1994 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1995 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
1996 ok(!buf, "Expected buf to be set to NULL\n");
1997 /* Check with a non-DER bool */
1998 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1999 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2000 (BYTE *)&buf, &bufSize);
2001 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2004 CERT_BASIC_CONSTRAINTS2_INFO *info =
2005 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2007 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2010 /* Check with a non-basic constraints value */
2011 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2012 (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
2013 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2014 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2015 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2016 /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2017 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2018 emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2019 (BYTE *)&buf, &bufSize);
2020 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2023 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2025 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2026 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2027 ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2030 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2031 constraintWithDomainName, sizeof(constraintWithDomainName),
2032 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2033 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2036 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2038 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2039 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2040 ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2041 if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2043 ok(info->rgSubtreesConstraint[0].cbData ==
2044 sizeof(encodedDomainName), "Wrong size %d\n",
2045 info->rgSubtreesConstraint[0].cbData);
2046 ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2047 sizeof(encodedDomainName)), "Unexpected value\n");
2053 /* These are terrible public keys of course, I'm just testing encoding */
2054 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2055 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2056 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2057 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2058 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2059 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2060 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2061 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2063 struct EncodedRSAPubKey
2065 const BYTE *modulus;
2067 const BYTE *encoded;
2068 size_t decodedModulusLen;
2071 struct EncodedRSAPubKey rsaPubKeys[] = {
2072 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2073 { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2074 { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2075 { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2078 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2080 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2081 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2082 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2085 DWORD bufSize = 0, i;
2087 /* Try with a bogus blob type */
2089 hdr->bVersion = CUR_BLOB_VERSION;
2091 hdr->aiKeyAlg = CALG_RSA_KEYX;
2092 rsaPubKey->magic = 0x31415352;
2093 rsaPubKey->bitlen = sizeof(modulus1) * 8;
2094 rsaPubKey->pubexp = 65537;
2095 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2098 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2099 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2101 ok(!ret && GetLastError() == E_INVALIDARG,
2102 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2103 /* Now with a bogus reserved field */
2104 hdr->bType = PUBLICKEYBLOB;
2106 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2107 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2111 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2112 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2113 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2116 /* Now with a bogus blob version */
2119 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2120 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2124 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2125 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2126 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2129 /* And with a bogus alg ID */
2130 hdr->bVersion = CUR_BLOB_VERSION;
2131 hdr->aiKeyAlg = CALG_DES;
2132 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2133 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2137 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2138 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2139 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2142 /* Check a couple of RSA-related OIDs */
2143 hdr->aiKeyAlg = CALG_RSA_KEYX;
2144 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2145 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2146 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2147 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2148 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2149 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2150 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2151 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2152 /* Finally, all valid */
2153 hdr->aiKeyAlg = CALG_RSA_KEYX;
2154 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2156 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2157 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2158 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2159 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2160 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2163 ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2164 "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2166 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2167 "Unexpected value\n");
2173 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2180 /* Try with a bad length */
2181 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2182 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2183 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2184 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2185 "Expected CRYPT_E_ASN1_EOD, got %08x\n", CRYPT_E_ASN1_EOD);
2186 /* Try with a couple of RSA-related OIDs */
2187 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2188 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2189 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2190 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2191 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2192 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2193 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2194 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2195 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2196 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2197 /* Now try success cases */
2198 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2201 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2202 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2203 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2204 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2207 BLOBHEADER *hdr = (BLOBHEADER *)buf;
2208 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2210 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2211 rsaPubKeys[i].decodedModulusLen,
2212 "Wrong size %d\n", bufSize);
2213 ok(hdr->bType == PUBLICKEYBLOB,
2214 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2216 ok(hdr->bVersion == CUR_BLOB_VERSION,
2217 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2218 CUR_BLOB_VERSION, hdr->bVersion);
2219 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2221 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2222 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2223 ok(rsaPubKey->magic == 0x31415352,
2224 "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2225 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2226 "Wrong bit len %d\n", rsaPubKey->bitlen);
2227 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2229 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2230 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2231 "Unexpected modulus\n");
2237 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2238 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2239 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2241 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2242 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2243 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2244 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2246 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2248 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2249 CRYPT_SEQUENCE_OF_ANY seq;
2255 /* Encode a homogenous sequence */
2256 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2258 blobs[i].cbData = ints[i].encoded[1] + 2;
2259 blobs[i].pbData = (BYTE *)ints[i].encoded;
2261 seq.cValue = sizeof(ints) / sizeof(ints[0]);
2262 seq.rgValue = blobs;
2264 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2265 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2266 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2269 ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2270 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2273 /* Change the type of the first element in the sequence, and give it
2276 blobs[0].cbData = times[0].encodedTime[1] + 2;
2277 blobs[0].pbData = (BYTE *)times[0].encodedTime;
2278 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2279 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2280 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2283 ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2284 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2285 "Unexpected value\n");
2290 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2296 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2297 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2298 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2301 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2304 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2305 "Wrong elements %d\n", seq->cValue);
2306 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2308 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2309 "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2310 seq->rgValue[i].cbData);
2311 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2312 ints[i].encoded[1] + 2), "Unexpected value\n");
2316 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2317 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2319 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2322 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2324 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2325 "Wrong elements %d\n", seq->cValue);
2326 /* Just check the first element since it's all that changed */
2327 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2328 "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2329 seq->rgValue[0].cbData);
2330 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2331 times[0].encodedTime[1] + 2), "Unexpected value\n");
2336 struct encodedExtensions
2338 CERT_EXTENSIONS exts;
2339 const BYTE *encoded;
2342 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2343 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2344 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2345 static CERT_EXTENSION criticalExt =
2346 { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2347 static CERT_EXTENSION nonCriticalExt =
2348 { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2350 static const BYTE ext0[] = { 0x30,0x00 };
2351 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2352 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2353 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2354 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2356 static const struct encodedExtensions exts[] = {
2357 { { 0, NULL }, ext0 },
2358 { { 1, &criticalExt }, ext1 },
2359 { { 1, &nonCriticalExt }, ext2 },
2362 static void test_encodeExtensions(DWORD dwEncoding)
2366 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2372 ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2373 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2374 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2377 ok(bufSize == exts[i].encoded[1] + 2,
2378 "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2379 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2380 "Unexpected value\n");
2386 static void test_decodeExtensions(DWORD dwEncoding)
2390 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2396 ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2397 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2398 NULL, (BYTE *)&buf, &bufSize);
2399 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2402 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2405 ok(ext->cExtension == exts[i].exts.cExtension,
2406 "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2408 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2410 ok(!strcmp(ext->rgExtension[j].pszObjId,
2411 exts[i].exts.rgExtension[j].pszObjId),
2412 "Expected OID %s, got %s\n",
2413 exts[i].exts.rgExtension[j].pszObjId,
2414 ext->rgExtension[j].pszObjId);
2415 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2416 exts[i].exts.rgExtension[j].Value.pbData,
2417 exts[i].exts.rgExtension[j].Value.cbData),
2418 "Unexpected value\n");
2425 /* MS encodes public key info with a NULL if the algorithm identifier's
2426 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
2427 * it encodes them by omitting the algorithm parameters. This latter approach
2428 * seems more correct, so accept either form.
2430 struct encodedPublicKey
2432 CERT_PUBLIC_KEY_INFO info;
2433 const BYTE *encoded;
2434 const BYTE *encodedNoNull;
2435 CERT_PUBLIC_KEY_INFO decoded;
2438 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2440 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2442 static const unsigned char bin64[] = {
2443 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2444 static const unsigned char bin65[] = {
2445 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2446 static const unsigned char bin66[] = {
2447 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2448 static const unsigned char bin67[] = {
2449 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2450 static const unsigned char bin68[] = {
2451 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2452 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2453 static const unsigned char bin69[] = {
2454 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2455 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2456 static const unsigned char bin70[] = {
2457 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2458 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2460 static const unsigned char bin71[] = {
2461 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2462 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2464 static unsigned char bin72[] = { 0x05,0x00};
2466 static CHAR oid_bogus[] = "1.2.3",
2467 oid_rsa[] = szOID_RSA;
2469 static const struct encodedPublicKey pubKeys[] = {
2470 /* with a bogus OID */
2471 { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2473 { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2474 /* some normal keys */
2475 { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2477 { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2478 { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2480 { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2481 /* with add'l parameters--note they must be DER-encoded */
2482 { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2483 (BYTE *)aKey, 0 } },
2485 { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2486 (BYTE *)aKey, 0 } } },
2489 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2493 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2499 ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2500 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2502 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2505 ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2506 bufSize == pubKeys[i].encodedNoNull[1] + 2,
2507 "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2508 pubKeys[i].encodedNoNull[1] + 2, bufSize);
2509 if (bufSize == pubKeys[i].encoded[1] + 2)
2510 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2511 "Unexpected value\n");
2512 else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2513 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2514 pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2520 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2521 const CERT_PUBLIC_KEY_INFO *got)
2523 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2524 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2525 got->Algorithm.pszObjId);
2526 ok(expected->Algorithm.Parameters.cbData ==
2527 got->Algorithm.Parameters.cbData,
2528 "Expected parameters of %d bytes, got %d\n",
2529 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2530 if (expected->Algorithm.Parameters.cbData)
2531 ok(!memcmp(expected->Algorithm.Parameters.pbData,
2532 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2533 "Unexpected algorithm parameters\n");
2534 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2535 "Expected public key of %d bytes, got %d\n",
2536 expected->PublicKey.cbData, got->PublicKey.cbData);
2537 if (expected->PublicKey.cbData)
2538 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2539 got->PublicKey.cbData), "Unexpected public key value\n");
2542 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2544 static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2545 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2546 0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2547 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2553 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2555 /* The NULL form decodes to the decoded member */
2556 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2557 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2558 NULL, (BYTE *)&buf, &bufSize);
2559 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2562 comparePublicKeyInfo(&pubKeys[i].decoded,
2563 (CERT_PUBLIC_KEY_INFO *)buf);
2566 /* The non-NULL form decodes to the original */
2567 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2568 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2569 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2570 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2573 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2577 /* Test with bogus (not valid DER) parameters */
2578 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2579 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2580 NULL, (BYTE *)&buf, &bufSize);
2581 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2582 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2585 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2586 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2587 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2588 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2589 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2590 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2591 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2592 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2593 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2594 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2595 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2596 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2597 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2598 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2599 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2600 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2601 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2602 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2603 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2604 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2605 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2606 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2607 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2608 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2609 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2610 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2611 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2612 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2613 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2614 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2615 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2616 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2617 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2618 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2619 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2620 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2621 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2622 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2623 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2625 static const BYTE serialNum[] = { 0x01 };
2627 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2632 CERT_INFO info = { 0 };
2634 /* Test with NULL pvStructInfo */
2635 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2636 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2637 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2638 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2639 /* Test with a V1 cert */
2640 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2641 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2642 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2645 ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2646 v1Cert[1] + 2, size);
2647 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2651 info.dwVersion = CERT_V2;
2652 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2653 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2654 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2657 ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2658 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2662 info.dwVersion = CERT_V3;
2663 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2664 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2665 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2668 ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2669 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2672 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2673 * API doesn't prevent it)
2675 info.dwVersion = CERT_V1;
2676 info.cExtension = 1;
2677 info.rgExtension = &criticalExt;
2678 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2679 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2680 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2683 ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2684 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2687 /* test v1 cert with a serial number */
2688 info.SerialNumber.cbData = sizeof(serialNum);
2689 info.SerialNumber.pbData = (BYTE *)serialNum;
2690 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2691 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2694 ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2695 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2698 /* Test v1 cert with an issuer name, a subject name, and a serial number */
2699 info.Issuer.cbData = sizeof(encodedCommonName);
2700 info.Issuer.pbData = (BYTE *)encodedCommonName;
2701 info.Subject.cbData = sizeof(encodedCommonName);
2702 info.Subject.pbData = (BYTE *)encodedCommonName;
2703 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2704 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2707 ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2708 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2711 /* for now, I let more interesting tests be done for each subcomponent,
2712 * rather than retesting them all here.
2716 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2718 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2719 v1CertWithConstraints, v1CertWithSerial };
2724 /* Test with NULL pbEncoded */
2725 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2726 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2727 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2728 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2729 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2730 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2731 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2732 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2733 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2734 * minimum a cert must have a non-zero serial number, an issuer, and a
2737 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2739 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2740 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2741 (BYTE *)&buf, &size);
2742 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
2743 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2745 /* Now check with serial number, subject and issuer specified */
2746 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2747 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2748 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2751 CERT_INFO *info = (CERT_INFO *)buf;
2753 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2754 ok(info->SerialNumber.cbData == 1,
2755 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2756 ok(*info->SerialNumber.pbData == *serialNum,
2757 "Expected serial number %d, got %d\n", *serialNum,
2758 *info->SerialNumber.pbData);
2759 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2760 "Wrong size %d\n", info->Issuer.cbData);
2761 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2762 "Unexpected issuer\n");
2763 ok(info->Subject.cbData == sizeof(encodedCommonName),
2764 "Wrong size %d\n", info->Subject.cbData);
2765 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2766 info->Subject.cbData), "Unexpected subject\n");
2771 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2774 static const BYTE signedBigCert[] = {
2775 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
2776 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2777 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
2778 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2779 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2780 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
2781 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
2782 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
2783 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
2784 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2785 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
2786 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
2788 static void test_encodeCert(DWORD dwEncoding)
2790 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
2791 * also that bigCert is a NULL-terminated string, so don't count its
2792 * last byte (otherwise the signed cert won't decode.)
2794 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
2795 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
2800 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
2801 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2802 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2805 ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
2806 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
2811 static void test_decodeCert(DWORD dwEncoding)
2817 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
2818 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2819 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2822 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
2824 ok(info->ToBeSigned.cbData == sizeof(bigCert),
2825 "Wrong cert size %d\n", info->ToBeSigned.cbData);
2826 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
2827 "Unexpected cert\n");
2828 ok(info->Signature.cbData == sizeof(hash),
2829 "Wrong signature size %d\n", info->Signature.cbData);
2830 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
2831 "Unexpected signature\n");
2834 /* A signed cert decodes as a CERT_INFO too */
2835 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
2836 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2837 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2840 CERT_INFO *info = (CERT_INFO *)buf;
2842 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2843 ok(info->SerialNumber.cbData == 1,
2844 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2845 ok(*info->SerialNumber.pbData == *serialNum,
2846 "Expected serial number %d, got %d\n", *serialNum,
2847 *info->SerialNumber.pbData);
2848 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2849 "Wrong size %d\n", info->Issuer.cbData);
2850 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2851 "Unexpected issuer\n");
2852 ok(info->Subject.cbData == sizeof(encodedCommonName),
2853 "Wrong size %d\n", info->Subject.cbData);
2854 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2855 info->Subject.cbData), "Unexpected subject\n");
2860 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
2861 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
2862 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
2863 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2864 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
2866 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
2867 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
2868 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2869 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
2870 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
2871 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
2872 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
2873 0x2e, 0x6f, 0x72, 0x67 };
2874 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
2875 CRL_REASON_AFFILIATION_CHANGED;
2877 static void test_encodeCRLDistPoints(DWORD dwEncoding)
2879 CRL_DIST_POINTS_INFO info = { 0 };
2880 CRL_DIST_POINT point = { { 0 } };
2881 CERT_ALT_NAME_ENTRY entry = { 0 };
2886 /* Test with an empty info */
2887 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2888 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2889 ok(!ret && GetLastError() == E_INVALIDARG,
2890 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2891 /* Test with one empty dist point */
2892 info.cDistPoint = 1;
2893 info.rgDistPoint = &point;
2894 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2895 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2898 ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
2899 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
2902 /* A dist point with an invalid name */
2903 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2904 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
2905 U(entry).pwszURL = (LPWSTR)nihongoURL;
2906 U(point.DistPointName).FullName.cAltEntry = 1;
2907 U(point.DistPointName).FullName.rgAltEntry = &entry;
2908 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2909 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2910 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
2911 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
2912 /* The first invalid character is at index 7 */
2913 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
2914 "Expected invalid char at index 7, got %d\n",
2915 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
2916 /* A dist point with (just) a valid name */
2917 U(entry).pwszURL = (LPWSTR)url;
2918 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2919 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2922 ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
2923 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
2926 /* A dist point with (just) reason flags */
2927 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
2928 point.ReasonFlags.cbData = sizeof(crlReason);
2929 point.ReasonFlags.pbData = (LPBYTE)&crlReason;
2930 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2931 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2934 ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
2935 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
2938 /* A dist point with just an issuer */
2939 point.ReasonFlags.cbData = 0;
2940 point.CRLIssuer.cAltEntry = 1;
2941 point.CRLIssuer.rgAltEntry = &entry;
2942 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2943 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2946 ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
2947 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
2950 /* A dist point with both a name and an issuer */
2951 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2952 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2953 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2956 ok(size == sizeof(distPointWithUrlAndIssuer),
2957 "Wrong size %d\n", size);
2958 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
2963 static void test_decodeCRLDistPoints(DWORD dwEncoding)
2968 PCRL_DIST_POINTS_INFO info;
2969 PCRL_DIST_POINT point;
2970 PCERT_ALT_NAME_ENTRY entry;
2972 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2973 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2974 (BYTE *)&buf, &size);
2977 info = (PCRL_DIST_POINTS_INFO)buf;
2978 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2979 "Wrong size %d\n", size);
2980 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
2982 point = info->rgDistPoint;
2983 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
2984 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
2985 point->DistPointName.dwDistPointNameChoice);
2986 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2987 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2990 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2991 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2992 (BYTE *)&buf, &size);
2995 info = (PCRL_DIST_POINTS_INFO)buf;
2996 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2997 "Wrong size %d\n", size);
2998 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3000 point = info->rgDistPoint;
3001 ok(point->DistPointName.dwDistPointNameChoice ==
3002 CRL_DIST_POINT_FULL_NAME,
3003 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3004 point->DistPointName.dwDistPointNameChoice);
3005 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3006 "Expected 1 name entry, got %d\n",
3007 U(point->DistPointName).FullName.cAltEntry);
3008 entry = U(point->DistPointName).FullName.rgAltEntry;
3009 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3010 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3011 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3012 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3013 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3016 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3017 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3018 NULL, (BYTE *)&buf, &size);
3021 info = (PCRL_DIST_POINTS_INFO)buf;
3022 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3023 "Wrong size %d\n", size);
3024 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3026 point = info->rgDistPoint;
3027 ok(point->DistPointName.dwDistPointNameChoice ==
3028 CRL_DIST_POINT_NO_NAME,
3029 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3030 point->DistPointName.dwDistPointNameChoice);
3031 ok(point->ReasonFlags.cbData == sizeof(crlReason),
3032 "Expected reason length\n");
3033 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3034 "Unexpected reason\n");
3035 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3038 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3039 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3040 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3043 info = (PCRL_DIST_POINTS_INFO)buf;
3044 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3045 "Wrong size %d\n", size);
3046 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3048 point = info->rgDistPoint;
3049 ok(point->DistPointName.dwDistPointNameChoice ==
3050 CRL_DIST_POINT_FULL_NAME,
3051 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3052 point->DistPointName.dwDistPointNameChoice);
3053 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3054 "Expected 1 name entry, got %d\n",
3055 U(point->DistPointName).FullName.cAltEntry);
3056 entry = U(point->DistPointName).FullName.rgAltEntry;
3057 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3058 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3059 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3060 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3061 ok(point->CRLIssuer.cAltEntry == 1,
3062 "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3063 entry = point->CRLIssuer.rgAltEntry;
3064 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3065 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3066 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3071 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3072 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3073 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3074 0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3077 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3082 CRL_ISSUING_DIST_POINT point = { { 0 } };
3083 CERT_ALT_NAME_ENTRY entry;
3085 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3086 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3087 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3088 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3089 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3090 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3091 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3094 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3095 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3098 /* nonsensical flags */
3099 point.fOnlyContainsUserCerts = TRUE;
3100 point.fOnlyContainsCACerts = TRUE;
3101 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3102 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3103 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3106 ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3107 ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3110 /* unimplemented name type */
3111 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3112 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3113 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3114 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3115 ok(!ret && GetLastError() == E_INVALIDARG,
3116 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3118 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3119 U(point.DistPointName).FullName.cAltEntry = 0;
3120 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3121 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3122 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3125 ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3126 ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3129 /* name with URL entry */
3130 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3131 U(entry).pwszURL = (LPWSTR)url;
3132 U(point.DistPointName).FullName.cAltEntry = 1;
3133 U(point.DistPointName).FullName.rgAltEntry = &entry;
3134 ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3135 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3136 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3139 ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3140 ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3145 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3146 const CERT_ALT_NAME_ENTRY *got)
3148 ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3149 "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3150 got->dwAltNameChoice);
3151 if (expected->dwAltNameChoice == got->dwAltNameChoice)
3153 switch (got->dwAltNameChoice)
3155 case CERT_ALT_NAME_RFC822_NAME:
3156 case CERT_ALT_NAME_DNS_NAME:
3157 case CERT_ALT_NAME_EDI_PARTY_NAME:
3158 case CERT_ALT_NAME_URL:
3159 case CERT_ALT_NAME_REGISTERED_ID:
3160 ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3161 !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL), "Unexpected name\n");
3163 case CERT_ALT_NAME_X400_ADDRESS:
3164 case CERT_ALT_NAME_DIRECTORY_NAME:
3165 case CERT_ALT_NAME_IP_ADDRESS:
3166 ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3167 "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3168 ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3169 U(*got).IPAddress.cbData), "Unexpected value\n");
3175 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3176 const CERT_ALT_NAME_INFO *got)
3180 ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3181 expected->cAltEntry, got->cAltEntry);
3182 for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3183 compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3186 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3187 const CRL_DIST_POINT_NAME *got)
3189 ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3190 "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3191 if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3192 compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3195 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3196 const CRL_ISSUING_DIST_POINT *got)
3198 compareDistPointName(&expected->DistPointName, &got->DistPointName);
3199 ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3200 "Unexpected fOnlyContainsUserCerts\n");
3201 ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3202 "Unexpected fOnlyContainsCACerts\n");
3203 ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3204 "Unexpected reason flags\n");
3205 ok(got->fIndirectCRL == expected->fIndirectCRL,
3206 "Unexpected fIndirectCRL\n");
3209 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3214 CRL_ISSUING_DIST_POINT point = { { 0 } };
3216 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3217 emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3218 (BYTE *)&buf, &size);
3219 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3222 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3225 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3226 badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3227 (BYTE *)&buf, &size);
3228 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3231 point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3232 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3235 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3236 emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3237 (BYTE *)&buf, &size);
3238 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3241 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3242 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3243 U(point.DistPointName).FullName.cAltEntry = 0;
3244 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3247 ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3248 urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3249 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3252 CERT_ALT_NAME_ENTRY entry;
3254 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3255 U(entry).pwszURL = (LPWSTR)url;
3256 U(point.DistPointName).FullName.cAltEntry = 1;
3257 U(point.DistPointName).FullName.rgAltEntry = &entry;
3258 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3263 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3264 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3266 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3267 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3268 0x30, 0x30, 0x30, 0x30, 0x5a };
3269 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3270 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3271 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3272 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3274 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3275 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3276 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3277 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3278 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3279 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3280 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3281 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3282 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3283 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3284 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3285 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3286 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3287 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3288 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3289 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3290 0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3291 0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3292 0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3293 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3294 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3295 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3296 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3297 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3298 0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3299 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3300 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3301 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3302 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3303 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3304 0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3305 0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3306 0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3307 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3308 0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3309 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3310 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3311 0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3312 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3313 0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3315 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3319 static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3321 CRL_INFO info = { 0 };
3322 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3325 /* Test with a V1 CRL */
3326 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3327 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3328 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3331 ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3332 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3336 info.dwVersion = CRL_V2;
3337 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3338 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3339 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3342 ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3343 v2CRL[1] + 2, size);
3344 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3347 /* v1 CRL with a name */
3348 info.dwVersion = CRL_V1;
3349 info.Issuer.cbData = sizeof(encodedCommonName);
3350 info.Issuer.pbData = (BYTE *)encodedCommonName;
3351 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3352 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3353 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3356 ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3357 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3360 /* v1 CRL with a name and a NULL entry pointer */
3362 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3363 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3364 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3365 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3366 /* now set an empty entry */
3367 info.rgCRLEntry = &entry;
3368 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3369 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3372 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3373 "Wrong size %d\n", size);
3374 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3375 "Got unexpected value\n");
3378 /* an entry with a serial number */
3379 entry.SerialNumber.cbData = sizeof(serialNum);
3380 entry.SerialNumber.pbData = (BYTE *)serialNum;
3381 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3382 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3385 ok(size == sizeof(v1CRLWithIssuerAndEntry),
3386 "Wrong size %d\n", size);
3387 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3388 "Got unexpected value\n");
3391 /* an entry with an extension */
3392 entry.cExtension = 1;
3393 entry.rgExtension = &criticalExt;
3394 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3395 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3396 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3399 ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3400 ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3403 /* a CRL with an extension */
3404 entry.cExtension = 0;
3405 info.cExtension = 1;
3406 info.rgExtension = &criticalExt;
3407 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3408 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3409 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3412 ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3413 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3416 /* a v2 CRL with an extension, this time non-critical */
3417 info.dwVersion = CRL_V2;
3418 info.rgExtension = &nonCriticalExt;
3419 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3420 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3421 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3424 ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3425 ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3428 /* a v2 CRL with an issuing dist point extension */
3429 ext.pszObjId = oid_issuing_dist_point;
3430 ext.fCritical = TRUE;
3431 ext.Value.cbData = sizeof(urlIDP);
3432 ext.Value.pbData = (LPBYTE)urlIDP;
3433 entry.rgExtension = &ext;
3434 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3435 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3436 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3439 ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3440 ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3445 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3446 0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3447 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3448 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3449 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3450 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3451 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3452 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3453 0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3454 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3455 0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3456 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3457 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3458 0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3459 0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3460 0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3461 0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3462 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3463 0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3464 0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3465 0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3466 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3467 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3468 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3469 0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3470 0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3471 0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3472 0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3473 0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3474 0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3475 0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3476 0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3477 0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3478 0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3480 static const BYTE verisignCRLWithLotsOfEntries[] = {
3481 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3482 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3483 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3484 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3485 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3486 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3487 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3488 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3489 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3490 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3491 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3492 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3493 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3494 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3495 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3496 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3497 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3498 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3499 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3500 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3501 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3502 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3503 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3504 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3505 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3506 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3507 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3508 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3509 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3510 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3511 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3512 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3513 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3514 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3515 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3516 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3517 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3518 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3519 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3520 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3521 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3522 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3523 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3524 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3525 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3526 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3527 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3528 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3529 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3530 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3531 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3532 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3533 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3534 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3535 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3536 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3537 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3538 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3539 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3540 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3541 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3542 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3543 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3544 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3545 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3546 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3547 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3548 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3549 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3550 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3551 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3552 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3553 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3554 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3555 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3556 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3557 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3558 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3559 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3560 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3561 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3562 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3563 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3564 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3565 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3566 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3567 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3568 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3569 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3570 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3571 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3572 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3573 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3574 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3575 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3576 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3577 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3578 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3579 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3580 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3581 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3582 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3583 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3584 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3585 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3586 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3587 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3588 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3589 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3590 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3591 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3592 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3593 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3594 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3595 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3596 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3597 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3598 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3599 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3600 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3601 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3602 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3603 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3604 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3605 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3606 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3607 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3608 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3609 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3610 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3611 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3612 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3613 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3614 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3615 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3616 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3617 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3618 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3619 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3620 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3621 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3622 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3623 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3624 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3625 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3626 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3627 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3628 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3629 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3630 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3631 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3632 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3633 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3634 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3635 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3636 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3637 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3638 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3639 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3640 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3641 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3642 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3643 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3644 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3645 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3646 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3647 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3648 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3649 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3650 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3651 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3652 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3653 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3654 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3655 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3656 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3657 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3658 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3659 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3660 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3661 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3662 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3663 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3664 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3665 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3666 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3667 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3668 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
3669 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
3670 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
3671 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
3672 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
3673 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
3674 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
3675 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
3676 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
3677 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
3678 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
3679 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
3680 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
3681 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
3682 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
3683 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
3684 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
3685 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
3686 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
3687 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
3688 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
3689 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
3690 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
3691 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
3692 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
3693 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
3694 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
3695 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
3696 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
3697 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
3698 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
3699 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
3700 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
3701 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
3702 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
3703 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
3704 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
3705 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
3706 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
3707 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
3708 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
3709 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
3710 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
3711 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
3712 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
3713 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
3714 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
3715 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
3716 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
3717 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
3718 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
3719 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
3720 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
3721 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
3722 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
3723 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
3724 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
3725 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
3726 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
3727 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
3728 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
3729 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
3730 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
3731 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
3732 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
3733 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
3734 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
3735 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
3736 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
3737 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
3738 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
3739 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
3740 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
3741 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
3742 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
3743 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
3744 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
3745 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
3746 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
3747 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
3748 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
3749 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
3750 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
3751 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
3752 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
3753 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
3754 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
3755 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
3756 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
3757 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
3758 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
3759 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
3760 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
3761 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
3762 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
3763 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
3764 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
3765 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
3766 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
3767 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
3768 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
3769 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
3770 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
3771 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
3772 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
3773 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
3774 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
3775 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
3776 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
3777 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
3778 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
3779 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
3780 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
3781 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
3782 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
3783 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
3784 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
3785 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
3786 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
3787 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
3788 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
3789 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
3790 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
3791 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
3792 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
3793 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
3794 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
3795 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
3796 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
3797 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
3798 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
3799 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
3800 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
3801 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
3802 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
3803 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
3804 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
3805 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
3806 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
3807 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
3808 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
3809 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
3810 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
3811 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
3812 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
3813 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
3814 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
3815 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
3816 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
3817 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
3818 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
3819 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
3820 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
3821 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
3822 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
3823 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
3824 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
3825 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
3826 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
3827 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
3828 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
3829 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
3830 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
3831 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
3832 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
3833 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
3834 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
3835 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
3836 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
3837 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
3838 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
3839 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
3840 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
3841 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
3842 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
3843 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
3844 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
3845 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
3846 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
3847 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
3848 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
3849 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
3850 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
3851 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
3852 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
3853 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
3854 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
3855 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
3856 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
3857 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
3858 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
3859 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
3860 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
3861 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
3862 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
3863 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
3864 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
3865 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
3866 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
3867 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
3868 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
3869 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
3870 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
3871 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
3872 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
3873 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
3874 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
3875 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
3876 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
3877 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
3878 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
3879 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
3880 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
3881 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
3882 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
3883 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
3884 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
3885 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
3886 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
3887 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
3888 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
3889 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
3890 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
3891 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
3892 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
3893 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
3894 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
3895 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
3896 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
3897 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
3898 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
3899 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
3900 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
3901 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
3902 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
3903 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
3904 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
3905 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
3906 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
3907 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
3908 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
3909 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
3910 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
3911 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
3912 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
3913 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
3914 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
3915 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
3916 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
3917 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
3918 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
3919 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
3920 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
3921 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
3922 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
3923 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
3924 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
3925 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
3926 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
3927 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
3928 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
3929 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
3930 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
3931 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
3932 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
3933 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
3934 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
3935 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
3936 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
3937 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
3938 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
3939 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
3940 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
3941 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
3942 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
3943 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
3944 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
3945 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
3946 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
3947 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
3948 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
3949 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
3950 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
3951 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
3952 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
3953 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
3954 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
3955 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
3956 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
3957 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
3958 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
3959 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
3960 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
3961 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
3962 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
3963 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
3964 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
3965 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
3966 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
3967 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
3968 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
3969 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
3970 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
3971 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
3972 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
3973 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
3974 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
3975 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
3976 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
3977 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
3978 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
3979 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
3980 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
3981 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
3982 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
3983 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
3984 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
3985 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
3986 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
3987 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
3988 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
3990 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
3992 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
3997 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
3999 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4000 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4001 (BYTE *)&buf, &size);
4002 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
4003 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4005 /* at a minimum, a CRL must contain an issuer: */
4006 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4007 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4008 (BYTE *)&buf, &size);
4009 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4012 CRL_INFO *info = (CRL_INFO *)buf;
4014 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4015 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4017 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4018 "Wrong issuer size %d\n", info->Issuer.cbData);
4019 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4020 "Unexpected issuer\n");
4023 /* check decoding with an empty CRL entry */
4024 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4025 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4026 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4027 todo_wine ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
4028 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4029 /* with a real CRL entry */
4030 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4031 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4032 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4033 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4036 CRL_INFO *info = (CRL_INFO *)buf;
4039 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4040 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4042 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4043 entry = info->rgCRLEntry;
4044 ok(entry->SerialNumber.cbData == 1,
4045 "Expected serial number size 1, got %d\n",
4046 entry->SerialNumber.cbData);
4047 ok(*entry->SerialNumber.pbData == *serialNum,
4048 "Expected serial number %d, got %d\n", *serialNum,
4049 *entry->SerialNumber.pbData);
4050 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4051 "Wrong issuer size %d\n", info->Issuer.cbData);
4052 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4053 "Unexpected issuer\n");
4055 /* a real CRL from verisign that has extensions */
4056 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4057 verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4058 NULL, (BYTE *)&buf, &size);
4059 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4062 CRL_INFO *info = (CRL_INFO *)buf;
4065 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4066 ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4068 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4069 entry = info->rgCRLEntry;
4070 ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4074 /* another real CRL from verisign that has lots of entries */
4075 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4076 verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4077 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4078 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4081 CRL_INFO *info = (CRL_INFO *)buf;
4083 ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4084 ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4086 ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4090 /* and finally, with an extension */
4091 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4092 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4093 NULL, (BYTE *)&buf, &size);
4094 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4097 CRL_INFO *info = (CRL_INFO *)buf;
4100 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4101 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4103 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4104 entry = info->rgCRLEntry;
4105 ok(entry->SerialNumber.cbData == 1,
4106 "Expected serial number size 1, got %d\n",
4107 entry->SerialNumber.cbData);
4108 ok(*entry->SerialNumber.pbData == *serialNum,
4109 "Expected serial number %d, got %d\n", *serialNum,
4110 *entry->SerialNumber.pbData);
4111 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4112 "Wrong issuer size %d\n", info->Issuer.cbData);
4113 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4114 "Unexpected issuer\n");
4115 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4118 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4119 v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4120 NULL, (BYTE *)&buf, &size);
4121 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4124 CRL_INFO *info = (CRL_INFO *)buf;
4126 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4130 /* And again, with an issuing dist point */
4131 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4132 v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4133 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4134 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4137 CRL_INFO *info = (CRL_INFO *)buf;
4139 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4145 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4146 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4147 static const BYTE encodedUsage[] = {
4148 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4149 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4150 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4152 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4157 CERT_ENHKEY_USAGE usage;
4159 /* Test with empty usage */
4160 usage.cUsageIdentifier = 0;
4161 ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4162 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4163 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4166 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4167 ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4170 /* Test with a few usages */
4171 usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4172 usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4173 ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4174 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4175 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4178 ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4179 ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4184 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4190 ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4191 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4192 (BYTE *)&buf, &size);
4193 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4196 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4198 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4199 "Wrong size %d\n", size);
4200 ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4201 usage->cUsageIdentifier);
4204 ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4205 encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4206 (BYTE *)&buf, &size);
4207 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4210 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4213 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4214 "Wrong size %d\n", size);
4215 ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4216 "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4217 for (i = 0; i < usage->cUsageIdentifier; i++)
4218 ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4219 "Expected OID %s, got %s\n", keyUsages[i],
4220 usage->rgpszUsageIdentifier[i]);
4225 static const BYTE authorityKeyIdWithId[] = { 0x30,0x03,0x80,0x01,0x01 };
4226 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4227 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4228 0x20,0x4c,0x61,0x6e,0x67,0x00 };
4229 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4231 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4233 CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4238 /* Test with empty id */
4239 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4240 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4241 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4244 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4245 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4248 /* With just a key id */
4249 info.KeyId.cbData = sizeof(serialNum);
4250 info.KeyId.pbData = (BYTE *)serialNum;
4251 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4252 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4253 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4256 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4257 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4260 /* With just an issuer */
4261 info.KeyId.cbData = 0;
4262 info.CertIssuer.cbData = sizeof(encodedCommonName);
4263 info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4264 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4265 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4266 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4269 ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4271 ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4274 /* With just a serial number */
4275 info.CertIssuer.cbData = 0;
4276 info.CertSerialNumber.cbData = sizeof(serialNum);
4277 info.CertSerialNumber.pbData = (BYTE *)serialNum;
4278 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4279 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4280 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4283 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4285 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4290 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4296 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4297 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4298 (BYTE *)&buf, &size);
4299 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4302 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4304 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4306 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4307 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4308 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4311 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4312 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4313 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4314 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4317 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4319 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4321 ok(info->KeyId.cbData == sizeof(serialNum), "Unexpected key id len\n");
4322 ok(!memcmp(info->KeyId.pbData, serialNum, sizeof(serialNum)),
4323 "Unexpected key id\n");
4324 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4325 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4328 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4329 authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4330 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4331 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4334 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4336 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4338 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4339 ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4340 "Unexpected issuer len\n");
4341 ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4342 sizeof(encodedCommonName)), "Unexpected issuer\n");
4343 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4346 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4347 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4348 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4349 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4352 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4354 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4356 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4357 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4358 ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4359 "Unexpected serial number len\n");
4360 ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4361 "Unexpected serial number\n");
4366 /* Free *pInfo with HeapFree */
4367 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
4374 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
4376 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
4377 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4378 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4379 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
4381 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4382 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4383 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
4385 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4386 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4387 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
4388 0, NULL, NULL, &size);
4389 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4390 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4391 /* Test with no key */
4392 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
4393 0, NULL, NULL, &size);
4394 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
4396 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
4397 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
4400 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
4401 NULL, 0, NULL, NULL, &size);
4402 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
4403 *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
4406 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
4407 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
4408 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
4412 /* By default (we passed NULL as the OID) the OID is
4415 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
4416 "Expected %s, got %s\n", szOID_RSA_RSA,
4417 (*pInfo)->Algorithm.pszObjId);
4423 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
4424 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
4425 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
4426 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
4427 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
4428 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
4429 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
4430 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
4431 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
4432 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
4433 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
4434 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
4435 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
4436 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
4437 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
4438 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
4439 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
4440 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
4441 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
4442 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
4443 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
4444 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
4445 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
4446 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
4447 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
4449 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
4453 PCCERT_CONTEXT context;
4456 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
4457 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
4458 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
4459 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
4462 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
4463 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
4464 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
4465 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
4466 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
4467 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
4468 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
4470 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4471 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4472 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
4474 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
4475 CryptDestroyKey(key);
4477 /* Test importing a public key from a certificate context */
4478 context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
4479 sizeof(expiredCert));
4480 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
4484 ok(!strcmp(szOID_RSA_RSA,
4485 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
4486 "Expected %s, got %s\n", szOID_RSA_RSA,
4487 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
4488 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
4489 &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
4490 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
4491 CryptDestroyKey(key);
4492 CertFreeCertificateContext(context);
4496 static const char cspName[] = "WineCryptTemp";
4498 static void testPortPublicKeyInfo(void)
4502 PCERT_PUBLIC_KEY_INFO info = NULL;
4504 /* Just in case a previous run failed, delete this thing */
4505 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
4506 CRYPT_DELETEKEYSET);
4507 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
4510 testExportPublicKey(csp, &info);
4511 testImportPublicKey(csp, info);
4513 HeapFree(GetProcessHeap(), 0, info);
4514 CryptReleaseContext(csp, 0);
4515 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
4516 CRYPT_DELETEKEYSET);
4521 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
4522 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
4525 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
4527 test_encodeInt(encodings[i]);
4528 test_decodeInt(encodings[i]);
4529 test_encodeEnumerated(encodings[i]);
4530 test_decodeEnumerated(encodings[i]);
4531 test_encodeFiletime(encodings[i]);
4532 test_decodeFiletime(encodings[i]);
4533 test_encodeName(encodings[i]);
4534 test_decodeName(encodings[i]);
4535 test_encodeUnicodeName(encodings[i]);
4536 test_decodeUnicodeName(encodings[i]);
4537 test_encodeNameValue(encodings[i]);
4538 test_decodeNameValue(encodings[i]);
4539 test_encodeUnicodeNameValue(encodings[i]);
4540 test_decodeUnicodeNameValue(encodings[i]);
4541 test_encodeAltName(encodings[i]);
4542 test_decodeAltName(encodings[i]);
4543 test_encodeOctets(encodings[i]);
4544 test_decodeOctets(encodings[i]);
4545 test_encodeBits(encodings[i]);
4546 test_decodeBits(encodings[i]);
4547 test_encodeBasicConstraints(encodings[i]);
4548 test_decodeBasicConstraints(encodings[i]);
4549 test_encodeRsaPublicKey(encodings[i]);
4550 test_decodeRsaPublicKey(encodings[i]);
4551 test_encodeSequenceOfAny(encodings[i]);
4552 test_decodeSequenceOfAny(encodings[i]);
4553 test_encodeExtensions(encodings[i]);
4554 test_decodeExtensions(encodings[i]);
4555 test_encodePublicKeyInfo(encodings[i]);
4556 test_decodePublicKeyInfo(encodings[i]);
4557 test_encodeCertToBeSigned(encodings[i]);
4558 test_decodeCertToBeSigned(encodings[i]);
4559 test_encodeCert(encodings[i]);
4560 test_decodeCert(encodings[i]);
4561 test_encodeCRLDistPoints(encodings[i]);
4562 test_decodeCRLDistPoints(encodings[i]);
4563 test_encodeCRLIssuingDistPoint(encodings[i]);
4564 test_decodeCRLIssuingDistPoint(encodings[i]);
4565 test_encodeCRLToBeSigned(encodings[i]);
4566 test_decodeCRLToBeSigned(encodings[i]);
4567 test_encodeEnhancedKeyUsage(encodings[i]);
4568 test_decodeEnhancedKeyUsage(encodings[i]);
4569 test_encodeAuthorityKeyId(encodings[i]);
4570 test_decodeAuthorityKeyId(encodings[i]);
4572 testPortPublicKeyInfo();