wined3d: Allow SetCursorProperties on existing cursor.
[wine] / dlls / crypt32 / tests / encode.c
1 /*
2  * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
3  *
4  * Copyright 2005 Juan Lang
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
26
27 #include "wine/test.h"
28
29 struct encodedInt
30 {
31     int val;
32     const BYTE *encoded;
33 };
34
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};
42
43 static const struct encodedInt ints[] = {
44  { 1,          bin1 },
45  { 127,        bin2 },
46  { 128,        bin3 },
47  { 256,        bin4 },
48  { -128,       bin5 },
49  { -129,       bin6 },
50  { 0xbaddf00d, bin7 },
51 };
52
53 struct encodedBigInt
54 {
55     const BYTE *val;
56     const BYTE *encoded;
57     const BYTE *decoded;
58 };
59
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};
63
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};
67
68 static const struct encodedBigInt bigInts[] = {
69  { bin8, bin9, bin10 },
70  { bin11, bin12, bin13 },
71 };
72
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};
77
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 },
82 };
83
84 static void test_encodeInt(DWORD dwEncoding)
85 {
86     DWORD bufSize = 0;
87     int i;
88     BOOL ret;
89     CRYPT_INTEGER_BLOB blob;
90     BYTE *buf = NULL;
91
92     /* CryptEncodeObjectEx with NULL bufSize crashes..
93     ret = CryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
94      NULL);
95      */
96     /* check bogus encoding */
97     ret = CryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
98      &bufSize);
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
102      * NTSTATUS.
103      */
104     ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
105      &bufSize);
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++)
109     {
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());
117         if (buf)
118         {
119             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
120              buf[0]);
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);
125             LocalFree(buf);
126         }
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());
136         if (buf)
137         {
138             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
139              buf[0]);
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);
144             LocalFree(buf);
145         }
146     }
147     /* encode a couple bigger ints, just to show it's little-endian and leading
148      * sign bytes are dropped
149      */
150     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
151     {
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());
160         if (buf)
161         {
162             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
163              buf[0]);
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");
169             LocalFree(buf);
170         }
171     }
172     /* and, encode some uints */
173     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
174     {
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());
183         if (buf)
184         {
185             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
186              buf[0]);
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");
192             LocalFree(buf);
193         }
194     }
195 }
196
197 static void test_decodeInt(DWORD dwEncoding)
198 {
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 };
203     BYTE *buf = NULL;
204     DWORD bufSize = 0;
205     int i;
206     BOOL ret;
207
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);
211      */
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,
219      &bufSize);
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++)
233     {
234         /* When the output buffer is NULL, this always succeeds */
235         SetLastError(0xdeadbeef);
236         ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
237          ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
238          &bufSize);
239         ok(ret && GetLastError() == NOERROR,
240          "Expected success and NOERROR, got %d\n", GetLastError());
241         ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
242          ints[i].encoded, ints[i].encoded[1] + 2,
243          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
244         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
245         ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
246         ok(buf != NULL, "Expected allocated buffer\n");
247         if (buf)
248         {
249             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
250              ints[i].val, *(int *)buf);
251             LocalFree(buf);
252         }
253     }
254     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
255     {
256         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
257          bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
258          &bufSize);
259         ok(ret && GetLastError() == NOERROR,
260          "Expected success and NOERROR, got %d\n", GetLastError());
261         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
262          bigInts[i].encoded, bigInts[i].encoded[1] + 2,
263          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
264         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
265         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
266         ok(buf != NULL, "Expected allocated buffer\n");
267         if (buf)
268         {
269             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
270
271             ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
272              "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
273              blob->cbData);
274             ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
275              "Unexpected value\n");
276             LocalFree(buf);
277         }
278     }
279     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
280     {
281         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
282          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
283          &bufSize);
284         ok(ret && GetLastError() == NOERROR,
285          "Expected success and NOERROR, got %d\n", GetLastError());
286         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
287          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
288          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
289         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
290         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
291         ok(buf != NULL, "Expected allocated buffer\n");
292         if (buf)
293         {
294             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
295
296             ok(blob->cbData == strlen((const char*)bigUInts[i].val),
297              "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
298              blob->cbData);
299             ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
300              "Unexpected value\n");
301             LocalFree(buf);
302         }
303     }
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());
308     if (buf)
309     {
310         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
311         LocalFree(buf);
312     }
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());
323      */
324     /* This will try to decode the buffer and overflow it, check that it's
325      * caught.
326      */
327     if (0)
328     {
329     /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
330     ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
331      0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
332     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
333      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
334     }
335 }
336
337 static const BYTE bin18[] = {0x0a,0x01,0x01};
338 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
339
340 /* These are always encoded unsigned, and aren't constrained to be any
341  * particular value
342  */
343 static const struct encodedInt enums[] = {
344  { 1,    bin18 },
345  { -128, bin19 },
346 };
347
348 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
349  * X509_ENUMERATED.
350  */
351 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
352  szOID_CRL_REASON_CODE };
353
354 static void test_encodeEnumerated(DWORD dwEncoding)
355 {
356     DWORD i, j;
357
358     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
359     {
360         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
361         {
362             BOOL ret;
363             BYTE *buf = NULL;
364             DWORD bufSize = 0;
365
366             ret = CryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
367              &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
368              &bufSize);
369             ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
370             if (buf)
371             {
372                 ok(buf[0] == 0xa,
373                  "Got unexpected type %d for enumerated (expected 0xa)\n",
374                  buf[0]);
375                 ok(buf[1] == enums[j].encoded[1],
376                  "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
377                 ok(!memcmp(buf + 1, enums[j].encoded + 1,
378                  enums[j].encoded[1] + 1),
379                  "Encoded value of 0x%08x didn't match expected\n",
380                  enums[j].val);
381                 LocalFree(buf);
382             }
383         }
384     }
385 }
386
387 static void test_decodeEnumerated(DWORD dwEncoding)
388 {
389     DWORD i, j;
390
391     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
392     {
393         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
394         {
395             BOOL ret;
396             DWORD bufSize = sizeof(int);
397             int val;
398
399             ret = CryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
400              enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
401              (BYTE *)&val, &bufSize);
402             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
403             ok(bufSize == sizeof(int),
404              "Got unexpected size %d for enumerated\n", bufSize);
405             ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
406              val, enums[j].val);
407         }
408     }
409 }
410
411 struct encodedFiletime
412 {
413     SYSTEMTIME sysTime;
414     const BYTE *encodedTime;
415 };
416
417 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
418  const struct encodedFiletime *time)
419 {
420     FILETIME ft = { 0 };
421     BYTE *buf = NULL;
422     DWORD bufSize = 0;
423     BOOL ret;
424
425     ret = SystemTimeToFileTime(&time->sysTime, &ft);
426     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
427     ret = CryptEncodeObjectEx(dwEncoding, structType, &ft,
428      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
429     /* years other than 1950-2050 are not allowed for encodings other than
430      * X509_CHOICE_OF_TIME.
431      */
432     if (structType == X509_CHOICE_OF_TIME ||
433      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
434     {
435         ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
436          GetLastError());
437         ok(buf != NULL, "Expected an allocated buffer\n");
438         if (buf)
439         {
440             ok(buf[0] == time->encodedTime[0],
441              "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
442              buf[0]);
443             ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
444              time->encodedTime[1], bufSize);
445             ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
446              "Got unexpected value for time encoding\n");
447             LocalFree(buf);
448         }
449     }
450     else
451         ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
452          "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
453 }
454
455 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
456  const struct encodedFiletime *time)
457 {
458     FILETIME ft1 = { 0 }, ft2 = { 0 };
459     DWORD size = sizeof(ft2);
460     BOOL ret;
461
462     ret = SystemTimeToFileTime(&time->sysTime, &ft1);
463     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
464     ret = CryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
465      time->encodedTime[1] + 2, 0, NULL, &ft2, &size);
466     /* years other than 1950-2050 are not allowed for encodings other than
467      * X509_CHOICE_OF_TIME.
468      */
469     if (structType == X509_CHOICE_OF_TIME ||
470      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
471     {
472         ok(ret, "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
473          GetLastError());
474         ok(!memcmp(&ft1, &ft2, sizeof(ft1)),
475          "Got unexpected value for time decoding\n");
476     }
477     else
478         ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
479          "Expected CRYPT_E_ASN1_BADTAG, got 0x%08x\n", GetLastError());
480 }
481
482 static const BYTE bin20[] = {
483     0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
484 static const BYTE bin21[] = {
485     0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
486 static const BYTE bin22[] = {
487     0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
488
489 static const struct encodedFiletime times[] = {
490  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
491  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
492  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
493 };
494
495 static void test_encodeFiletime(DWORD dwEncoding)
496 {
497     DWORD i;
498
499     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
500     {
501         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
502         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
503         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
504     }
505 }
506
507 static const BYTE bin23[] = {
508     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
509 static const BYTE bin24[] = {
510     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
511 static const BYTE bin25[] = {
512     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
513 static const BYTE bin26[] = {
514     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
515 static const BYTE bin27[] = {
516     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
517 static const BYTE bin28[] = {
518     0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
519 static const BYTE bin29[] = {
520     0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
521 static const BYTE bin30[] = {
522     0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
523 static const BYTE bin31[] = {
524     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
525 static const BYTE bin32[] = {
526     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
527 static const BYTE bin33[] = {
528     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
529 static const BYTE bin34[] = {
530     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
531 static const BYTE bin35[] = {
532     0x17,0x08, '4','5','0','6','0','6','1','6'};
533 static const BYTE bin36[] = {
534     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
535 static const BYTE bin37[] = {
536     0x18,0x04, '2','1','4','5'};
537 static const BYTE bin38[] = {
538     0x18,0x08, '2','1','4','5','0','6','0','6'};
539
540 static void test_decodeFiletime(DWORD dwEncoding)
541 {
542     static const struct encodedFiletime otherTimes[] = {
543      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
544      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
545      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
546      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
547      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
548      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
549      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
550      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
551      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
552      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
553      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
554      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
555     };
556     /* An oddball case that succeeds in Windows, but doesn't seem correct
557      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
558      */
559     static const unsigned char *bogusTimes[] = {
560      /* oddly, this succeeds on Windows, with year 2765
561      "\x18" "\x0f" "21r50606161000Z",
562       */
563      bin35,
564      bin36,
565      bin37,
566      bin38,
567     };
568     DWORD i, size;
569     FILETIME ft1 = { 0 }, ft2 = { 0 };
570     BOOL ret;
571
572     /* Check bogus length with non-NULL buffer */
573     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
574     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
575     size = 1;
576     ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
577      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
578     ok(!ret && GetLastError() == ERROR_MORE_DATA,
579      "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
580     /* Normal tests */
581     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
582     {
583         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
584         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
585         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
586     }
587     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
588     {
589         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
590         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
591         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
592     }
593     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
594     {
595         size = sizeof(ft1);
596         ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
597          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
598         ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
599          "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
600     }
601 }
602
603 static const char commonName[] = "Juan Lang";
604 static const char surName[] = "Lang";
605
606 static const BYTE emptySequence[] = { 0x30, 0 };
607 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
608 static const BYTE twoRDNs[] = {
609     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
610     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
611     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
612 static const BYTE encodedTwoRDNs[] = {
613 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
614 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
615 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
616 0x6e,0x67,0x00,
617 };
618
619 static const BYTE us[] = { 0x55, 0x53 };
620 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
621  0x74, 0x61 };
622 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
623  0x6f, 0x6c, 0x69, 0x73 };
624 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
625  0x76, 0x65, 0x72, 0x73 };
626 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
627  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
628 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
629  0x73, 0x74 };
630 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
631  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
632
633 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
634 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
635
636 static CHAR oid_us[]            = "2.5.4.6",
637             oid_minnesota[]     = "2.5.4.8",
638             oid_minneapolis[]   = "2.5.4.7",
639             oid_codeweavers[]   = "2.5.4.10",
640             oid_wine[]          = "2.5.4.11",
641             oid_localhostAttr[] = "2.5.4.3",
642             oid_aric[]          = "1.2.840.113549.1.9.1";
643 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
644                                     { RDNA(minnesota) },
645                                     { RDNA(minneapolis) },
646                                     { RDNA(codeweavers) },
647                                     { RDNA(wine) },
648                                     { RDNA(localhostAttr) },
649                                     { RDNIA5(aric) } };
650 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
651                                            { RDNA(localhostAttr) },
652                                            { RDNA(minnesota) },
653                                            { RDNA(minneapolis) },
654                                            { RDNA(codeweavers) },
655                                            { RDNA(wine) },
656                                            { RDNIA5(aric) } };
657
658 #undef RDNIA5
659 #undef RDNA
660
661 static const BYTE encodedRDNAttrs[] = {
662 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
663 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
664 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
665 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
666 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
667 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
668 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
669 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
670 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
671 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
672 };
673
674 static void test_encodeName(DWORD dwEncoding)
675 {
676     CERT_RDN_ATTR attrs[2];
677     CERT_RDN rdn;
678     CERT_NAME_INFO info;
679     static CHAR oid_common_name[] = szOID_COMMON_NAME,
680                 oid_sur_name[]    = szOID_SUR_NAME;
681     BYTE *buf = NULL;
682     DWORD size = 0;
683     BOOL ret;
684
685     /* Test with NULL pvStructInfo */
686     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
687      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
688     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
689      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
690     /* Test with empty CERT_NAME_INFO */
691     info.cRDN = 0;
692     info.rgRDN = NULL;
693     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
694      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
695     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
696     if (buf)
697     {
698         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
699          "Got unexpected encoding for empty name\n");
700         LocalFree(buf);
701     }
702     /* Test with bogus CERT_RDN */
703     info.cRDN = 1;
704     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
705      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
706     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
707      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
708     /* Test with empty CERT_RDN */
709     rdn.cRDNAttr = 0;
710     rdn.rgRDNAttr = NULL;
711     info.cRDN = 1;
712     info.rgRDN = &rdn;
713     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
714      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
715     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
716     if (buf)
717     {
718         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
719          "Got unexpected encoding for empty RDN array\n");
720         LocalFree(buf);
721     }
722     /* Test with bogus attr array */
723     rdn.cRDNAttr = 1;
724     rdn.rgRDNAttr = NULL;
725     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
726      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
727     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
728      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
729     /* oddly, a bogus OID is accepted by Windows XP; not testing.
730     attrs[0].pszObjId = "bogus";
731     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
732     attrs[0].Value.cbData = sizeof(commonName);
733     attrs[0].Value.pbData = (BYTE *)commonName;
734     rdn.cRDNAttr = 1;
735     rdn.rgRDNAttr = attrs;
736     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
737      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
738     ok(!ret, "Expected failure, got success\n");
739      */
740     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
741      * the encoded attributes to be swapped.
742      */
743     attrs[0].pszObjId = oid_common_name;
744     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
745     attrs[0].Value.cbData = sizeof(commonName);
746     attrs[0].Value.pbData = (BYTE *)commonName;
747     attrs[1].pszObjId = oid_sur_name;
748     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
749     attrs[1].Value.cbData = sizeof(surName);
750     attrs[1].Value.pbData = (BYTE *)surName;
751     rdn.cRDNAttr = 2;
752     rdn.rgRDNAttr = attrs;
753     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
754      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
755     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
756     if (buf)
757     {
758         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
759          "Got unexpected encoding for two RDN array\n");
760         LocalFree(buf);
761     }
762     /* A name can be "encoded" with previously encoded RDN attrs. */
763     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
764     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
765     attrs[0].Value.cbData = sizeof(twoRDNs);
766     rdn.cRDNAttr = 1;
767     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
768      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
769     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
770     if (buf)
771     {
772         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
773         ok(!memcmp(buf, encodedTwoRDNs, size),
774          "Unexpected value for re-endoded two RDN array\n");
775         LocalFree(buf);
776     }
777     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
778     rdn.cRDNAttr = 1;
779     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
780     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
781      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
782     ok(!ret && GetLastError() == E_INVALIDARG,
783      "Expected E_INVALIDARG, got %08x\n", GetLastError());
784     /* Test a more complex name */
785     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
786     rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
787     info.cRDN = 1;
788     info.rgRDN = &rdn;
789     buf = NULL;
790     size = 0;
791     ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
792      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
793     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
794     if (ret)
795     {
796         ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
797         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
798         LocalFree(buf);
799     }
800 }
801
802 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
803 static WCHAR surNameW[] = { 'L','a','n','g',0 };
804
805 static const BYTE twoRDNsNoNull[] = {
806  0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
807  0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
808  0x20,0x4c,0x61,0x6e,0x67 };
809 static const BYTE anyType[] = {
810  0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
811  0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
812  0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
813  0x61,0x4c,0x67,0x6e };
814
815 static void test_encodeUnicodeName(DWORD dwEncoding)
816 {
817     CERT_RDN_ATTR attrs[2];
818     CERT_RDN rdn;
819     CERT_NAME_INFO info;
820     static CHAR oid_common_name[] = szOID_COMMON_NAME,
821                 oid_sur_name[]    = szOID_SUR_NAME;
822     BYTE *buf = NULL;
823     DWORD size = 0;
824     BOOL ret;
825
826     /* Test with NULL pvStructInfo */
827     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
828      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
829     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
830      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
831     /* Test with empty CERT_NAME_INFO */
832     info.cRDN = 0;
833     info.rgRDN = NULL;
834     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
835      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
836     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
837     if (buf)
838     {
839         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
840          "Got unexpected encoding for empty name\n");
841         LocalFree(buf);
842     }
843     /* Check with one CERT_RDN_ATTR, that has an invalid character for the
844      * encoding (the NULL).
845      */
846     attrs[0].pszObjId = oid_common_name;
847     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
848     attrs[0].Value.cbData = sizeof(commonNameW);
849     attrs[0].Value.pbData = (BYTE *)commonNameW;
850     rdn.cRDNAttr = 1;
851     rdn.rgRDNAttr = attrs;
852     info.cRDN = 1;
853     info.rgRDN = &rdn;
854     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
855      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
856     ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
857      "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
858     ok(size == 9, "Unexpected error index %08x\n", size);
859     /* Check with two NULL-terminated CERT_RDN_ATTRs.  Note DER encoding
860      * forces the order of the encoded attributes to be swapped.
861      */
862     attrs[0].pszObjId = oid_common_name;
863     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
864     attrs[0].Value.cbData = 0;
865     attrs[0].Value.pbData = (BYTE *)commonNameW;
866     attrs[1].pszObjId = oid_sur_name;
867     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
868     attrs[1].Value.cbData = 0;
869     attrs[1].Value.pbData = (BYTE *)surNameW;
870     rdn.cRDNAttr = 2;
871     rdn.rgRDNAttr = attrs;
872     info.cRDN = 1;
873     info.rgRDN = &rdn;
874     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
875      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
876     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
877     if (buf)
878     {
879         ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
880          "Got unexpected encoding for two RDN array\n");
881         LocalFree(buf);
882     }
883     /* A name can be "encoded" with previously encoded RDN attrs. */
884     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
885     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
886     attrs[0].Value.cbData = sizeof(twoRDNs);
887     rdn.cRDNAttr = 1;
888     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
889      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
890     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
891     if (buf)
892     {
893         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
894         ok(!memcmp(buf, encodedTwoRDNs, size),
895          "Unexpected value for re-endoded two RDN array\n");
896         LocalFree(buf);
897     }
898     /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
899     rdn.cRDNAttr = 1;
900     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
901     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
902      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
903     todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
904     if (buf)
905     {
906         ok(size == sizeof(anyType), "Unexpected size %d\n", size);
907         ok(!memcmp(buf, anyType, size), "Unexpected value\n");
908         LocalFree(buf);
909     }
910 }
911
912 static void compareNameValues(const CERT_NAME_VALUE *expected,
913  const CERT_NAME_VALUE *got)
914 {
915     ok(got->dwValueType == expected->dwValueType,
916      "Expected string type %d, got %d\n", expected->dwValueType,
917      got->dwValueType);
918     ok(got->Value.cbData == expected->Value.cbData,
919      "String type %d: unexpected data size, got %d, expected %d\n",
920      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
921     if (got->Value.cbData && got->Value.pbData)
922         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
923          min(got->Value.cbData, expected->Value.cbData)),
924          "String type %d: unexpected value\n", expected->dwValueType);
925 }
926
927 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
928  const CERT_RDN_ATTR *got)
929 {
930     if (expected->pszObjId && strlen(expected->pszObjId))
931     {
932         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
933          expected->pszObjId);
934         if (got->pszObjId)
935         {
936             ok(!strcmp(got->pszObjId, expected->pszObjId),
937              "Got unexpected OID %s, expected %s\n", got->pszObjId,
938              expected->pszObjId);
939         }
940     }
941     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
942      (const CERT_NAME_VALUE *)&got->dwValueType);
943 }
944
945 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
946 {
947     ok(got->cRDNAttr == expected->cRDNAttr,
948      "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
949     if (got->cRDNAttr)
950     {
951         DWORD i;
952
953         for (i = 0; i < got->cRDNAttr; i++)
954             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
955     }
956 }
957
958 static void compareNames(const CERT_NAME_INFO *expected,
959  const CERT_NAME_INFO *got)
960 {
961     ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
962      expected->cRDN, got->cRDN);
963     if (got->cRDN)
964     {
965         DWORD i;
966
967         for (i = 0; i < got->cRDN; i++)
968             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
969     }
970 }
971
972 static void test_decodeName(DWORD dwEncoding)
973 {
974     BYTE *buf = NULL;
975     DWORD bufSize = 0;
976     BOOL ret;
977     CERT_RDN rdn;
978     CERT_NAME_INFO info = { 1, &rdn };
979
980     /* test empty name */
981     bufSize = 0;
982     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
983      emptySequence[1] + 2,
984      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
985      (BYTE *)&buf, &bufSize);
986     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
987     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
988      * decoder works the same way, so only test the count.
989      */
990     if (buf)
991     {
992         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
993         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
994          "Expected 0 RDNs in empty info, got %d\n",
995          ((CERT_NAME_INFO *)buf)->cRDN);
996         LocalFree(buf);
997     }
998     /* test empty RDN */
999     bufSize = 0;
1000     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1001      emptyRDNs[1] + 2,
1002      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1003      (BYTE *)&buf, &bufSize);
1004     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1005     if (buf)
1006     {
1007         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1008
1009         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1010          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1011          "Got unexpected value for empty RDN\n");
1012         LocalFree(buf);
1013     }
1014     /* test two RDN attrs */
1015     bufSize = 0;
1016     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1017      twoRDNs[1] + 2,
1018      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1019      (BYTE *)&buf, &bufSize);
1020     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1021     if (buf)
1022     {
1023         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1024                     oid_common_name[] = szOID_COMMON_NAME;
1025
1026         CERT_RDN_ATTR attrs[] = {
1027          { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1028           (BYTE *)surName } },
1029          { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1030           (BYTE *)commonName } },
1031         };
1032
1033         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1034         rdn.rgRDNAttr = attrs;
1035         compareNames(&info, (CERT_NAME_INFO *)buf);
1036         LocalFree(buf);
1037     }
1038     /* And, a slightly more complicated name */
1039     buf = NULL;
1040     bufSize = 0;
1041     ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1042      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1043     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1044     if (ret)
1045     {
1046         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1047         rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
1048         compareNames(&info, (CERT_NAME_INFO *)buf);
1049         LocalFree(buf);
1050     }
1051 }
1052
1053 static void test_decodeUnicodeName(DWORD dwEncoding)
1054 {
1055     BYTE *buf = NULL;
1056     DWORD bufSize = 0;
1057     BOOL ret;
1058     CERT_RDN rdn;
1059     CERT_NAME_INFO info = { 1, &rdn };
1060
1061     /* test empty name */
1062     bufSize = 0;
1063     ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1064      emptySequence[1] + 2,
1065      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1066      (BYTE *)&buf, &bufSize);
1067     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1068     if (buf)
1069     {
1070         ok(bufSize == sizeof(CERT_NAME_INFO),
1071          "Got wrong bufSize %d\n", bufSize);
1072         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1073          "Expected 0 RDNs in empty info, got %d\n",
1074          ((CERT_NAME_INFO *)buf)->cRDN);
1075         LocalFree(buf);
1076     }
1077     /* test empty RDN */
1078     bufSize = 0;
1079     ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1080      emptyRDNs[1] + 2,
1081      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1082      (BYTE *)&buf, &bufSize);
1083     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1084     if (buf)
1085     {
1086         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1087
1088         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1089          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1090          "Got unexpected value for empty RDN\n");
1091         LocalFree(buf);
1092     }
1093     /* test two RDN attrs */
1094     bufSize = 0;
1095     ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1096      sizeof(twoRDNsNoNull),
1097      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1098      (BYTE *)&buf, &bufSize);
1099     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1100     if (buf)
1101     {
1102         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1103                     oid_common_name[] = szOID_COMMON_NAME;
1104
1105         CERT_RDN_ATTR attrs[] = {
1106          { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1107          { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1108          { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1109          { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1110         };
1111
1112         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1113         rdn.rgRDNAttr = attrs;
1114         compareNames(&info, (CERT_NAME_INFO *)buf);
1115         LocalFree(buf);
1116     }
1117 }
1118
1119 struct EncodedNameValue
1120 {
1121     CERT_NAME_VALUE value;
1122     const BYTE *encoded;
1123     DWORD encodedSize;
1124 };
1125
1126 static const char bogusIA5[] = "\x80";
1127 static const char bogusPrintable[] = "~";
1128 static const char bogusNumeric[] = "A";
1129 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1130 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1131 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1132 static BYTE octetCommonNameValue[] = {
1133  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1134 static BYTE numericCommonNameValue[] = {
1135  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1136 static BYTE printableCommonNameValue[] = {
1137  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1138 static BYTE t61CommonNameValue[] = {
1139  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1140 static BYTE videotexCommonNameValue[] = {
1141  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1142 static BYTE ia5CommonNameValue[] = {
1143  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1144 static BYTE graphicCommonNameValue[] = {
1145  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1146 static BYTE visibleCommonNameValue[] = {
1147  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1148 static BYTE generalCommonNameValue[] = {
1149  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1150 static BYTE bmpCommonNameValue[] = {
1151  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1152  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1153 static BYTE utf8CommonNameValue[] = {
1154  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1155
1156 static struct EncodedNameValue nameValues[] = {
1157  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1158      octetCommonNameValue, sizeof(octetCommonNameValue) },
1159  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1160      numericCommonNameValue, sizeof(numericCommonNameValue) },
1161  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1162      printableCommonNameValue, sizeof(printableCommonNameValue) },
1163  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1164      t61CommonNameValue, sizeof(t61CommonNameValue) },
1165  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1166      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1167  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1168      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1169  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1170      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1171  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1172      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1173  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1174      generalCommonNameValue, sizeof(generalCommonNameValue) },
1175  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1176      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1177  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1178      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1179  /* The following tests succeed under Windows, but really should fail,
1180   * they contain characters that are illegal for the encoding.  I'm
1181   * including them to justify my lazy encoding.
1182   */
1183  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1184      sizeof(bin42) },
1185  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1186      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1187  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1188      bin44, sizeof(bin44) },
1189 };
1190
1191 static void test_encodeNameValue(DWORD dwEncoding)
1192 {
1193     BYTE *buf = NULL;
1194     DWORD size = 0, i;
1195     BOOL ret;
1196     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1197
1198     value.dwValueType = 14;
1199     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1200      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1201     ok(!ret && GetLastError() == CRYPT_E_ASN1_CHOICE,
1202      "Expected CRYPT_E_ASN1_CHOICE, got %08x\n", GetLastError());
1203     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1204     value.Value.pbData = printableCommonNameValue;
1205     value.Value.cbData = sizeof(printableCommonNameValue);
1206     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1207      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1208     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1209     if (buf)
1210     {
1211         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1212          size);
1213         ok(!memcmp(buf, printableCommonNameValue, size),
1214          "Unexpected encoding\n");
1215         LocalFree(buf);
1216     }
1217     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1218     {
1219         ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1220          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1221          &size);
1222         ok(ret, "Type %d: CryptEncodeObjectEx failed: %08x\n",
1223          nameValues[i].value.dwValueType, GetLastError());
1224         if (buf)
1225         {
1226             ok(size == nameValues[i].encodedSize,
1227              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1228             ok(!memcmp(buf, nameValues[i].encoded, size),
1229              "Got unexpected encoding\n");
1230             LocalFree(buf);
1231         }
1232     }
1233 }
1234
1235 static void test_decodeNameValue(DWORD dwEncoding)
1236 {
1237     int i;
1238     BYTE *buf = NULL;
1239     DWORD bufSize = 0;
1240     BOOL ret;
1241
1242     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1243     {
1244         ret = CryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1245          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1246          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1247          (BYTE *)&buf, &bufSize);
1248         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1249          nameValues[i].value.dwValueType, GetLastError());
1250         if (buf)
1251         {
1252             compareNameValues(&nameValues[i].value,
1253              (const CERT_NAME_VALUE *)buf);
1254             LocalFree(buf);
1255         }
1256     }
1257 }
1258
1259 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1260 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1261  'h','q','.','o','r','g',0 };
1262 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1263  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1264  0x6f, 0x72, 0x67 };
1265 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1266  0x575b, 0 };
1267 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1268 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1269  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1270 static const BYTE localhost[] = { 127, 0, 0, 1 };
1271 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1272  0x01 };
1273
1274 static void test_encodeAltName(DWORD dwEncoding)
1275 {
1276     CERT_ALT_NAME_INFO info = { 0 };
1277     CERT_ALT_NAME_ENTRY entry = { 0 };
1278     BYTE *buf = NULL;
1279     DWORD size = 0;
1280     BOOL ret;
1281
1282     /* Test with empty info */
1283     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1284      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1285     if (buf)
1286     {
1287         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1288         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1289         LocalFree(buf);
1290     }
1291     /* Test with an empty entry */
1292     info.cAltEntry = 1;
1293     info.rgAltEntry = &entry;
1294     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1295      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1296     ok(!ret && GetLastError() == E_INVALIDARG,
1297      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1298     /* Test with an empty pointer */
1299     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1300     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1301      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1302     if (buf)
1303     {
1304         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1305         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1306         LocalFree(buf);
1307     }
1308     /* Test with a real URL */
1309     U(entry).pwszURL = (LPWSTR)url;
1310     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1311      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1312     if (buf)
1313     {
1314         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1315         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1316         LocalFree(buf);
1317     }
1318     /* Now with the URL containing an invalid IA5 char */
1319     U(entry).pwszURL = (LPWSTR)nihongoURL;
1320     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1321      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1322     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1323      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1324     /* The first invalid character is at index 7 */
1325     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1326      "Expected invalid char at index 7, got %d\n",
1327      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1328     /* Now with the URL missing a scheme */
1329     U(entry).pwszURL = (LPWSTR)dnsName;
1330     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1331      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1332     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1333     if (buf)
1334     {
1335         /* This succeeds, but it shouldn't, so don't worry about conforming */
1336         LocalFree(buf);
1337     }
1338     /* Now with a DNS name */
1339     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1340     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1341      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1342     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1343     if (buf)
1344     {
1345         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1346         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1347         LocalFree(buf);
1348     }
1349     /* Test with an IP address */
1350     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1351     U(entry).IPAddress.cbData = sizeof(localhost);
1352     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1353     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1354      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1355     if (buf)
1356     {
1357         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1358         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1359         LocalFree(buf);
1360     }
1361 }
1362
1363 static void test_decodeAltName(DWORD dwEncoding)
1364 {
1365     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1366      0x00, 0x00, 0x01 };
1367     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1368      0x01 };
1369     BOOL ret;
1370     BYTE *buf = NULL;
1371     DWORD bufSize = 0;
1372     CERT_ALT_NAME_INFO *info;
1373
1374     /* Test some bogus ones first */
1375     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1376      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1377      NULL, (BYTE *)&buf, &bufSize);
1378     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1379      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1380     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1381      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1382      &bufSize);
1383     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1384      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
1385     /* Now expected cases */
1386     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1387      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1388      &bufSize);
1389     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1390     if (buf)
1391     {
1392         info = (CERT_ALT_NAME_INFO *)buf;
1393
1394         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1395          info->cAltEntry);
1396         LocalFree(buf);
1397     }
1398     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1399      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1400      &bufSize);
1401     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1402     if (buf)
1403     {
1404         info = (CERT_ALT_NAME_INFO *)buf;
1405
1406         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1407          info->cAltEntry);
1408         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1409          "Expected CERT_ALT_NAME_URL, got %d\n",
1410          info->rgAltEntry[0].dwAltNameChoice);
1411         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1412          "Expected empty URL\n");
1413         LocalFree(buf);
1414     }
1415     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1416      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1417      &bufSize);
1418     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1419     if (buf)
1420     {
1421         info = (CERT_ALT_NAME_INFO *)buf;
1422
1423         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1424          info->cAltEntry);
1425         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1426          "Expected CERT_ALT_NAME_URL, got %d\n",
1427          info->rgAltEntry[0].dwAltNameChoice);
1428         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1429         LocalFree(buf);
1430     }
1431     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1432      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1433      &bufSize);
1434     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1435     if (buf)
1436     {
1437         info = (CERT_ALT_NAME_INFO *)buf;
1438
1439         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1440          info->cAltEntry);
1441         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1442          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1443          info->rgAltEntry[0].dwAltNameChoice);
1444         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1445          "Unexpected DNS name\n");
1446         LocalFree(buf);
1447     }
1448     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1449      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1450      &bufSize);
1451     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1452     if (buf)
1453     {
1454         info = (CERT_ALT_NAME_INFO *)buf;
1455
1456         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1457          info->cAltEntry);
1458         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1459          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1460          info->rgAltEntry[0].dwAltNameChoice);
1461         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1462          "Unexpected IP address length %d\n",
1463           U(info->rgAltEntry[0]).IPAddress.cbData);
1464         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1465          sizeof(localhost)), "Unexpected IP address value\n");
1466         LocalFree(buf);
1467     }
1468 }
1469
1470 struct UnicodeExpectedError
1471 {
1472     DWORD   valueType;
1473     LPCWSTR str;
1474     DWORD   errorIndex;
1475     DWORD   error;
1476 };
1477
1478 static const WCHAR oneW[] = { '1',0 };
1479 static const WCHAR aW[] = { 'a',0 };
1480 static const WCHAR quoteW[] = { '"', 0 };
1481
1482 static struct UnicodeExpectedError unicodeErrors[] = {
1483  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1484  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1485  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1486  { 14,                        oneW,       0, CRYPT_E_ASN1_CHOICE },
1487  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1488  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1489  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1490 };
1491
1492 struct UnicodeExpectedResult
1493 {
1494     DWORD           valueType;
1495     LPCWSTR         str;
1496     CRYPT_DATA_BLOB encoded;
1497 };
1498
1499 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1500 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1501 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1502 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1503 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1504 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1505 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1506 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1507 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1508 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1509 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1510 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1511  0x5b };
1512 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1513  0x6f,0x5b };
1514 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1515  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1516 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1517  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1518
1519 static struct UnicodeExpectedResult unicodeResults[] = {
1520  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1521  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1522  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1523  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1524  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1525  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1526  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1527  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1528  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1529  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1530  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1531  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1532  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1533 };
1534
1535 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1536  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1537  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1538 };
1539
1540 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1541 {
1542     BYTE *buf = NULL;
1543     DWORD size = 0, i;
1544     BOOL ret;
1545     CERT_NAME_VALUE value;
1546
1547     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1548      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1549     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1550      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1551     /* Have to have a string of some sort */
1552     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1553     value.Value.pbData = NULL;
1554     value.Value.cbData = 0;
1555     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1556      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1557     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1558      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1559     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1560     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1561      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1562     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1563      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1564     value.dwValueType = CERT_RDN_ANY_TYPE;
1565     value.Value.pbData = (LPBYTE)oneW;
1566     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1567      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1568     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1569      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1570     value.Value.cbData = sizeof(oneW);
1571     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1572      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1573     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1574      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1575     /* An encoded string with specified length isn't good enough either */
1576     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1577     value.Value.pbData = oneUniversal;
1578     value.Value.cbData = sizeof(oneUniversal);
1579     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1580      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1581     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1582      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1583     /* More failure checking */
1584     value.Value.cbData = 0;
1585     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1586     {
1587         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1588         value.dwValueType = unicodeErrors[i].valueType;
1589         ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1590          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1591         ok(!ret && GetLastError() == unicodeErrors[i].error,
1592          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1593          unicodeErrors[i].error, GetLastError());
1594         ok(size == unicodeErrors[i].errorIndex,
1595          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1596          size);
1597     }
1598     /* cbData can be zero if the string is NULL-terminated */
1599     value.Value.cbData = 0;
1600     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1601     {
1602         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1603         value.dwValueType = unicodeResults[i].valueType;
1604         ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1605          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1606         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1607         if (buf)
1608         {
1609             ok(size == unicodeResults[i].encoded.cbData,
1610              "Value type %d: expected size %d, got %d\n",
1611              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1612             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1613              "Value type %d: unexpected value\n", value.dwValueType);
1614             LocalFree(buf);
1615         }
1616     }
1617     /* These "encode," but they do so by truncating each unicode character
1618      * rather than properly encoding it.  Kept separate from the proper results,
1619      * because the encoded forms won't decode to their original strings.
1620      */
1621     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1622     {
1623         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1624         value.dwValueType = unicodeWeirdness[i].valueType;
1625         ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1626          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1627         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1628         if (buf)
1629         {
1630             ok(size == unicodeWeirdness[i].encoded.cbData,
1631              "Value type %d: expected size %d, got %d\n",
1632              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1633             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1634              "Value type %d: unexpected value\n", value.dwValueType);
1635             LocalFree(buf);
1636         }
1637     }
1638 }
1639
1640 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1641 {
1642     if (n <= 0) return 0;
1643     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1644     return *str1 - *str2;
1645 }
1646
1647 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1648 {
1649     DWORD i;
1650
1651     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1652     {
1653         BYTE *buf = NULL;
1654         BOOL ret;
1655         DWORD size = 0;
1656
1657         ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1658          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1659          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1660         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1661         if (ret && buf)
1662         {
1663             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1664
1665             ok(value->dwValueType == unicodeResults[i].valueType,
1666              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1667              value->dwValueType);
1668             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1669              value->Value.cbData / sizeof(WCHAR)),
1670              "Unexpected decoded value for index %d (value type %d)\n", i,
1671              unicodeResults[i].valueType);
1672             LocalFree(buf);
1673         }
1674     }
1675 }
1676
1677 struct encodedOctets
1678 {
1679     const BYTE *val;
1680     const BYTE *encoded;
1681 };
1682
1683 static const unsigned char bin46[] = { 'h','i',0 };
1684 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1685 static const unsigned char bin48[] = {
1686      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1687 static const unsigned char bin49[] = {
1688      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1689 static const unsigned char bin50[] = { 0 };
1690 static const unsigned char bin51[] = { 0x04,0x00,0 };
1691
1692 static const struct encodedOctets octets[] = {
1693     { bin46, bin47 },
1694     { bin48, bin49 },
1695     { bin50, bin51 },
1696 };
1697
1698 static void test_encodeOctets(DWORD dwEncoding)
1699 {
1700     CRYPT_DATA_BLOB blob;
1701     DWORD i;
1702
1703     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1704     {
1705         BYTE *buf = NULL;
1706         BOOL ret;
1707         DWORD bufSize = 0;
1708
1709         blob.cbData = strlen((const char*)octets[i].val);
1710         blob.pbData = (BYTE*)octets[i].val;
1711         ret = CryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1712          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1713         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1714         if (buf)
1715         {
1716             ok(buf[0] == 4,
1717              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1718             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1719              buf[1], octets[i].encoded[1]);
1720             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1721              octets[i].encoded[1] + 1), "Got unexpected value\n");
1722             LocalFree(buf);
1723         }
1724     }
1725 }
1726
1727 static void test_decodeOctets(DWORD dwEncoding)
1728 {
1729     DWORD i;
1730
1731     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1732     {
1733         BYTE *buf = NULL;
1734         BOOL ret;
1735         DWORD bufSize = 0;
1736
1737         ret = CryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1738          (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1739          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1740         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1741         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1742          "Expected size >= %d, got %d\n",
1743            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1744         ok(buf != NULL, "Expected allocated buffer\n");
1745         if (buf)
1746         {
1747             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1748
1749             if (blob->cbData)
1750                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1751                  "Unexpected value\n");
1752             LocalFree(buf);
1753         }
1754     }
1755 }
1756
1757 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1758
1759 struct encodedBits
1760 {
1761     DWORD cUnusedBits;
1762     const BYTE *encoded;
1763     DWORD cbDecoded;
1764     const BYTE *decoded;
1765 };
1766
1767 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1768 static const unsigned char bin53[] = { 0xff,0xff };
1769 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1770 static const unsigned char bin55[] = { 0xff,0xfe };
1771 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1772 static const unsigned char bin57[] = { 0xfe };
1773 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1774
1775 static const struct encodedBits bits[] = {
1776     /* normal test cases */
1777     { 0, bin52, 2, bin53 },
1778     { 1, bin54, 2, bin55 },
1779     /* strange test case, showing cUnusedBits >= 8 is allowed */
1780     { 9, bin56, 1, bin57 },
1781     /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1782     { 17, bin58, 0, NULL },
1783 };
1784
1785 static void test_encodeBits(DWORD dwEncoding)
1786 {
1787     DWORD i;
1788
1789     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1790     {
1791         CRYPT_BIT_BLOB blob;
1792         BOOL ret;
1793         BYTE *buf = NULL;
1794         DWORD bufSize = 0;
1795
1796         blob.cbData = sizeof(bytesToEncode);
1797         blob.pbData = (BYTE *)bytesToEncode;
1798         blob.cUnusedBits = bits[i].cUnusedBits;
1799         ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1800          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1801         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1802         if (buf)
1803         {
1804             ok(bufSize == bits[i].encoded[1] + 2,
1805              "Got unexpected size %d, expected %d\n", bufSize,
1806              bits[i].encoded[1] + 2);
1807             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1808              "Unexpected value\n");
1809             LocalFree(buf);
1810         }
1811     }
1812 }
1813
1814 static void test_decodeBits(DWORD dwEncoding)
1815 {
1816     static const BYTE ber[] = "\x03\x02\x01\xff";
1817     static const BYTE berDecoded = 0xfe;
1818     DWORD i;
1819     BOOL ret;
1820     BYTE *buf = NULL;
1821     DWORD bufSize = 0;
1822
1823     /* normal cases */
1824     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1825     {
1826         ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1827          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1828          &bufSize);
1829         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1830         if (buf)
1831         {
1832             CRYPT_BIT_BLOB *blob;
1833
1834             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1835                "Got unexpected size %d\n", bufSize);
1836             blob = (CRYPT_BIT_BLOB *)buf;
1837             ok(blob->cbData == bits[i].cbDecoded,
1838              "Got unexpected length %d, expected %d\n", blob->cbData,
1839              bits[i].cbDecoded);
1840             if (blob->cbData && bits[i].cbDecoded)
1841                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1842                  "Unexpected value\n");
1843             LocalFree(buf);
1844         }
1845     }
1846     /* special case: check that something that's valid in BER but not in DER
1847      * decodes successfully
1848      */
1849     ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1850      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1851     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1852     if (buf)
1853     {
1854         CRYPT_BIT_BLOB *blob;
1855
1856         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1857            "Got unexpected size %d\n", bufSize);
1858         blob = (CRYPT_BIT_BLOB *)buf;
1859         ok(blob->cbData == sizeof(berDecoded),
1860            "Got unexpected length %d\n", blob->cbData);
1861         if (blob->cbData)
1862             ok(*blob->pbData == berDecoded, "Unexpected value\n");
1863         LocalFree(buf);
1864     }
1865 }
1866
1867 struct Constraints2
1868 {
1869     CERT_BASIC_CONSTRAINTS2_INFO info;
1870     const BYTE *encoded;
1871 };
1872
1873 static const unsigned char bin59[] = { 0x30,0x00 };
1874 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
1875 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
1876 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1877 static const struct Constraints2 constraints2[] = {
1878  /* empty constraints */
1879  { { FALSE, FALSE, 0}, bin59 },
1880  /* can be a CA */
1881  { { TRUE,  FALSE, 0}, bin60 },
1882  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1883   * but that's not the case
1884   */
1885  { { FALSE, TRUE,  0}, bin61 },
1886  /* can be a CA and has path length constraints set */
1887  { { TRUE,  TRUE,  1}, bin62 },
1888 };
1889
1890 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
1891 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
1892  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
1893  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
1894  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1895 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
1896  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
1897  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
1898  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
1899  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1900
1901 static void test_encodeBasicConstraints(DWORD dwEncoding)
1902 {
1903     DWORD i, bufSize = 0;
1904     CERT_BASIC_CONSTRAINTS_INFO info;
1905     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
1906      (LPBYTE)encodedDomainName };
1907     BOOL ret;
1908     BYTE *buf = NULL;
1909
1910     /* First test with the simpler info2 */
1911     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1912     {
1913         ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1914          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1915          &bufSize);
1916         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1917         if (buf)
1918         {
1919             ok(bufSize == constraints2[i].encoded[1] + 2,
1920              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
1921              bufSize);
1922             ok(!memcmp(buf, constraints2[i].encoded,
1923              constraints2[i].encoded[1] + 2), "Unexpected value\n");
1924             LocalFree(buf);
1925         }
1926     }
1927     /* Now test with more complex basic constraints */
1928     info.SubjectType.cbData = 0;
1929     info.fPathLenConstraint = FALSE;
1930     info.cSubtreesConstraint = 0;
1931     ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1932      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1933     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1934     if (buf)
1935     {
1936         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
1937         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
1938          "Unexpected value\n");
1939         LocalFree(buf);
1940     }
1941     /* None of the certs I examined had any subtree constraint, but I test one
1942      * anyway just in case.
1943      */
1944     info.cSubtreesConstraint = 1;
1945     info.rgSubtreesConstraint = &nameBlob;
1946     ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1947      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1948     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1949     if (buf)
1950     {
1951         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
1952         ok(!memcmp(buf, constraintWithDomainName,
1953          sizeof(constraintWithDomainName)), "Unexpected value\n");
1954         LocalFree(buf);
1955     }
1956     /* FIXME: test encoding with subject type. */
1957 }
1958
1959 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
1960 static const unsigned char encodedCommonName[] = {
1961     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1962
1963 static void test_decodeBasicConstraints(DWORD dwEncoding)
1964 {
1965     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
1966      0xff };
1967     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
1968     DWORD i;
1969     BOOL ret;
1970     BYTE *buf = NULL;
1971     DWORD bufSize = 0;
1972
1973     /* First test with simpler info2 */
1974     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1975     {
1976         ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1977          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
1978          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1979         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
1980          GetLastError());
1981         if (buf)
1982         {
1983             CERT_BASIC_CONSTRAINTS2_INFO *info =
1984              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1985
1986             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
1987              "Unexpected value for item %d\n", i);
1988             LocalFree(buf);
1989         }
1990     }
1991     /* Check with the order of encoded elements inverted */
1992     buf = (PBYTE)1;
1993     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1994      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1995      &bufSize);
1996     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1997      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
1998     ok(!buf, "Expected buf to be set to NULL\n");
1999     /* Check with a non-DER bool */
2000     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2001      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2002      (BYTE *)&buf, &bufSize);
2003     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2004     if (buf)
2005     {
2006         CERT_BASIC_CONSTRAINTS2_INFO *info =
2007          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2008
2009         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2010         LocalFree(buf);
2011     }
2012     /* Check with a non-basic constraints value */
2013     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2014      (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
2015      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2016     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2017      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2018     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2019     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2020      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2021      (BYTE *)&buf, &bufSize);
2022     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2023     if (buf)
2024     {
2025         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2026
2027         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2028         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2029         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2030         LocalFree(buf);
2031     }
2032     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2033      constraintWithDomainName, sizeof(constraintWithDomainName),
2034      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2035     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2036     if (buf)
2037     {
2038         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2039
2040         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2041         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2042         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2043         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2044         {
2045             ok(info->rgSubtreesConstraint[0].cbData ==
2046              sizeof(encodedDomainName), "Wrong size %d\n",
2047              info->rgSubtreesConstraint[0].cbData);
2048             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2049              sizeof(encodedDomainName)), "Unexpected value\n");
2050         }
2051         LocalFree(buf);
2052     }
2053 }
2054
2055 /* These are terrible public keys of course, I'm just testing encoding */
2056 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2057 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2058 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2059 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2060 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2061 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2062 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2063 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2064
2065 struct EncodedRSAPubKey
2066 {
2067     const BYTE *modulus;
2068     size_t modulusLen;
2069     const BYTE *encoded;
2070     size_t decodedModulusLen;
2071 };
2072
2073 struct EncodedRSAPubKey rsaPubKeys[] = {
2074     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2075     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2076     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2077     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2078 };
2079
2080 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2081 {
2082     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2083     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2084     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2085     BOOL ret;
2086     BYTE *buf = NULL;
2087     DWORD bufSize = 0, i;
2088
2089     /* Try with a bogus blob type */
2090     hdr->bType = 2;
2091     hdr->bVersion = CUR_BLOB_VERSION;
2092     hdr->reserved = 0;
2093     hdr->aiKeyAlg = CALG_RSA_KEYX;
2094     rsaPubKey->magic = 0x31415352;
2095     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2096     rsaPubKey->pubexp = 65537;
2097     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2098      sizeof(modulus1));
2099
2100     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2101      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2102      &bufSize);
2103     ok(!ret && GetLastError() == E_INVALIDARG,
2104      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2105     /* Now with a bogus reserved field */
2106     hdr->bType = PUBLICKEYBLOB;
2107     hdr->reserved = 1;
2108     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2109      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2110      &bufSize);
2111     if (buf)
2112     {
2113         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2114          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2115         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2116         LocalFree(buf);
2117     }
2118     /* Now with a bogus blob version */
2119     hdr->reserved = 0;
2120     hdr->bVersion = 0;
2121     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2122      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2123      &bufSize);
2124     if (buf)
2125     {
2126         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2127          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2128         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2129         LocalFree(buf);
2130     }
2131     /* And with a bogus alg ID */
2132     hdr->bVersion = CUR_BLOB_VERSION;
2133     hdr->aiKeyAlg = CALG_DES;
2134     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2135      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2136      &bufSize);
2137     if (buf)
2138     {
2139         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2140          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2141         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2142         LocalFree(buf);
2143     }
2144     /* Check a couple of RSA-related OIDs */
2145     hdr->aiKeyAlg = CALG_RSA_KEYX;
2146     ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2147      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2148     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2149      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2150     ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2151      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2152     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2153      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2154     /* Finally, all valid */
2155     hdr->aiKeyAlg = CALG_RSA_KEYX;
2156     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2157     {
2158         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2159          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2160         ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2161          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2162         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2163         if (buf)
2164         {
2165             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2166              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2167              bufSize);
2168             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2169              "Unexpected value\n");
2170             LocalFree(buf);
2171         }
2172     }
2173 }
2174
2175 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2176 {
2177     DWORD i;
2178     LPBYTE buf = NULL;
2179     DWORD bufSize = 0;
2180     BOOL ret;
2181
2182     /* Try with a bad length */
2183     ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2184      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2185      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2186     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2187      "Expected CRYPT_E_ASN1_EOD, got %08x\n", CRYPT_E_ASN1_EOD);
2188     /* Try with a couple of RSA-related OIDs */
2189     ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2190      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2191      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2192     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2193      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2194     ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2195      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2196      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2197     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2198      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2199     /* Now try success cases */
2200     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2201     {
2202         bufSize = 0;
2203         ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2204          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2205          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2206         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2207         if (buf)
2208         {
2209             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2210             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2211
2212             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2213              rsaPubKeys[i].decodedModulusLen,
2214              "Wrong size %d\n", bufSize);
2215             ok(hdr->bType == PUBLICKEYBLOB,
2216              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2217              hdr->bType);
2218             ok(hdr->bVersion == CUR_BLOB_VERSION,
2219              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2220              CUR_BLOB_VERSION, hdr->bVersion);
2221             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2222              hdr->reserved);
2223             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2224              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2225             ok(rsaPubKey->magic == 0x31415352,
2226              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2227             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2228              "Wrong bit len %d\n", rsaPubKey->bitlen);
2229             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2230              rsaPubKey->pubexp);
2231             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2232              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2233              "Unexpected modulus\n");
2234             LocalFree(buf);
2235         }
2236     }
2237 }
2238
2239 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2240  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2241  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2242
2243 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2244  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2245  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2246  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2247
2248 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2249 {
2250     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2251     CRYPT_SEQUENCE_OF_ANY seq;
2252     DWORD i;
2253     BOOL ret;
2254     BYTE *buf = NULL;
2255     DWORD bufSize = 0;
2256
2257     /* Encode a homogenous sequence */
2258     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2259     {
2260         blobs[i].cbData = ints[i].encoded[1] + 2;
2261         blobs[i].pbData = (BYTE *)ints[i].encoded;
2262     }
2263     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2264     seq.rgValue = blobs;
2265
2266     ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2267      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2268     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2269     if (buf)
2270     {
2271         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2272         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2273         LocalFree(buf);
2274     }
2275     /* Change the type of the first element in the sequence, and give it
2276      * another go
2277      */
2278     blobs[0].cbData = times[0].encodedTime[1] + 2;
2279     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2280     ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2281      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2282     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2283     if (buf)
2284     {
2285         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2286         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2287          "Unexpected value\n");
2288         LocalFree(buf);
2289     }
2290 }
2291
2292 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2293 {
2294     BOOL ret;
2295     BYTE *buf = NULL;
2296     DWORD bufSize = 0;
2297
2298     ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2299      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2300     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2301     if (buf)
2302     {
2303         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2304         DWORD i;
2305
2306         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2307          "Wrong elements %d\n", seq->cValue);
2308         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2309         {
2310             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2311              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2312              seq->rgValue[i].cbData);
2313             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2314              ints[i].encoded[1] + 2), "Unexpected value\n");
2315         }
2316         LocalFree(buf);
2317     }
2318     ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2319      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2320      &bufSize);
2321     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2322     if (buf)
2323     {
2324         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2325
2326         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2327          "Wrong elements %d\n", seq->cValue);
2328         /* Just check the first element since it's all that changed */
2329         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2330          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2331          seq->rgValue[0].cbData);
2332         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2333          times[0].encodedTime[1] + 2), "Unexpected value\n");
2334         LocalFree(buf);
2335     }
2336 }
2337
2338 struct encodedExtensions
2339 {
2340     CERT_EXTENSIONS exts;
2341     const BYTE *encoded;
2342 };
2343
2344 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2345 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2346 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2347 static CERT_EXTENSION criticalExt =
2348  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2349 static CERT_EXTENSION nonCriticalExt =
2350  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2351
2352 static const BYTE ext0[] = { 0x30,0x00 };
2353 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2354                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2355 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2356                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2357
2358 static const struct encodedExtensions exts[] = {
2359  { { 0, NULL }, ext0 },
2360  { { 1, &criticalExt }, ext1 },
2361  { { 1, &nonCriticalExt }, ext2 },
2362 };
2363
2364 static void test_encodeExtensions(DWORD dwEncoding)
2365 {
2366     DWORD i;
2367
2368     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2369     {
2370         BOOL ret;
2371         BYTE *buf = NULL;
2372         DWORD bufSize = 0;
2373
2374         ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2375          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2376         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2377         if (buf)
2378         {
2379             ok(bufSize == exts[i].encoded[1] + 2,
2380              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2381             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2382              "Unexpected value\n");
2383             LocalFree(buf);
2384         }
2385     }
2386 }
2387
2388 static void test_decodeExtensions(DWORD dwEncoding)
2389 {
2390     DWORD i;
2391
2392     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2393     {
2394         BOOL ret;
2395         BYTE *buf = NULL;
2396         DWORD bufSize = 0;
2397
2398         ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2399          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2400          NULL, (BYTE *)&buf, &bufSize);
2401         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2402         if (buf)
2403         {
2404             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2405             DWORD j;
2406
2407             ok(ext->cExtension == exts[i].exts.cExtension,
2408              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2409              ext->cExtension);
2410             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2411             {
2412                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2413                  exts[i].exts.rgExtension[j].pszObjId),
2414                  "Expected OID %s, got %s\n",
2415                  exts[i].exts.rgExtension[j].pszObjId,
2416                  ext->rgExtension[j].pszObjId);
2417                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2418                  exts[i].exts.rgExtension[j].Value.pbData,
2419                  exts[i].exts.rgExtension[j].Value.cbData),
2420                  "Unexpected value\n");
2421             }
2422             LocalFree(buf);
2423         }
2424     }
2425 }
2426
2427 /* MS encodes public key info with a NULL if the algorithm identifier's
2428  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2429  * it encodes them by omitting the algorithm parameters.  This latter approach
2430  * seems more correct, so accept either form.
2431  */
2432 struct encodedPublicKey
2433 {
2434     CERT_PUBLIC_KEY_INFO info;
2435     const BYTE *encoded;
2436     const BYTE *encodedNoNull;
2437     CERT_PUBLIC_KEY_INFO decoded;
2438 };
2439
2440 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2441  0xe, 0xf };
2442 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2443
2444 static const unsigned char bin64[] = {
2445     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2446 static const unsigned char bin65[] = {
2447     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2448 static const unsigned char bin66[] = {
2449     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2450 static const unsigned char bin67[] = {
2451     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2452 static const unsigned char bin68[] = {
2453     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2454     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2455 static const unsigned char bin69[] = {
2456     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2457     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2458 static const unsigned char bin70[] = {
2459     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2460     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2461     0x0f};
2462 static const unsigned char bin71[] = {
2463     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2464     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2465     0x0f};
2466 static unsigned char bin72[] = { 0x05,0x00};
2467
2468 static CHAR oid_bogus[] = "1.2.3",
2469             oid_rsa[]   = szOID_RSA;
2470
2471 static const struct encodedPublicKey pubKeys[] = {
2472  /* with a bogus OID */
2473  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2474   bin64, bin65,
2475   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2476  /* some normal keys */
2477  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2478   bin66, bin67,
2479   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2480  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2481   bin68, bin69,
2482   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2483  /* with add'l parameters--note they must be DER-encoded */
2484  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2485   (BYTE *)aKey, 0 } },
2486   bin70, bin71,
2487   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2488   (BYTE *)aKey, 0 } } },
2489 };
2490
2491 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2492 {
2493     DWORD i;
2494
2495     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2496     {
2497         BOOL ret;
2498         BYTE *buf = NULL;
2499         DWORD bufSize = 0;
2500
2501         ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2502          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2503          &bufSize);
2504         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2505         if (buf)
2506         {
2507             ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2508              bufSize == pubKeys[i].encodedNoNull[1] + 2,
2509              "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2510              pubKeys[i].encodedNoNull[1] + 2, bufSize);
2511             if (bufSize == pubKeys[i].encoded[1] + 2)
2512                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2513                  "Unexpected value\n");
2514             else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2515                 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2516                  pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2517             LocalFree(buf);
2518         }
2519     }
2520 }
2521
2522 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2523  const CERT_PUBLIC_KEY_INFO *got)
2524 {
2525     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2526      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2527      got->Algorithm.pszObjId);
2528     ok(expected->Algorithm.Parameters.cbData ==
2529      got->Algorithm.Parameters.cbData,
2530      "Expected parameters of %d bytes, got %d\n",
2531      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2532     if (expected->Algorithm.Parameters.cbData)
2533         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2534          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2535          "Unexpected algorithm parameters\n");
2536     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2537      "Expected public key of %d bytes, got %d\n",
2538      expected->PublicKey.cbData, got->PublicKey.cbData);
2539     if (expected->PublicKey.cbData)
2540         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2541          got->PublicKey.cbData), "Unexpected public key value\n");
2542 }
2543
2544 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2545 {
2546     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2547      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2548      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2549      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2550     DWORD i;
2551     BOOL ret;
2552     BYTE *buf = NULL;
2553     DWORD bufSize = 0;
2554
2555     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2556     {
2557         /* The NULL form decodes to the decoded member */
2558         ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2559          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2560          NULL, (BYTE *)&buf, &bufSize);
2561         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2562         if (buf)
2563         {
2564             comparePublicKeyInfo(&pubKeys[i].decoded,
2565              (CERT_PUBLIC_KEY_INFO *)buf);
2566             LocalFree(buf);
2567         }
2568         /* The non-NULL form decodes to the original */
2569         ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2570          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2571          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2572         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2573         if (buf)
2574         {
2575             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2576             LocalFree(buf);
2577         }
2578     }
2579     /* Test with bogus (not valid DER) parameters */
2580     ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2581      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2582      NULL, (BYTE *)&buf, &bufSize);
2583     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2584      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2585 }
2586
2587 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2588  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2589  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2590  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2591  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2592 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2593  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2594  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2595  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2596  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2597 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2598  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2599  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2600  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2601  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2602 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2603  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2604  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2605  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2606  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2607  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2608  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2609 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2610  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2611  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2612  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2613  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2614  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2615  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2616 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2617  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2618  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2619  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2620  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2621  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2622  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2623  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2624  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2625  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2626
2627 static const BYTE serialNum[] = { 0x01 };
2628
2629 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2630 {
2631     BOOL ret;
2632     BYTE *buf = NULL;
2633     DWORD size = 0;
2634     CERT_INFO info = { 0 };
2635
2636     /* Test with NULL pvStructInfo */
2637     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2638      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2639     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2640      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2641     /* Test with a V1 cert */
2642     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2643      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2644     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2645     if (buf)
2646     {
2647         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2648          v1Cert[1] + 2, size);
2649         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2650         LocalFree(buf);
2651     }
2652     /* Test v2 cert */
2653     info.dwVersion = CERT_V2;
2654     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2655      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2656     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2657     if (buf)
2658     {
2659         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2660         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2661         LocalFree(buf);
2662     }
2663     /* Test v3 cert */
2664     info.dwVersion = CERT_V3;
2665     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2666      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2667     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2668     if (buf)
2669     {
2670         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2671         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2672         LocalFree(buf);
2673     }
2674     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2675      * API doesn't prevent it)
2676      */
2677     info.dwVersion = CERT_V1;
2678     info.cExtension = 1;
2679     info.rgExtension = &criticalExt;
2680     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2681      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2682     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2683     if (buf)
2684     {
2685         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2686         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2687         LocalFree(buf);
2688     }
2689     /* test v1 cert with a serial number */
2690     info.SerialNumber.cbData = sizeof(serialNum);
2691     info.SerialNumber.pbData = (BYTE *)serialNum;
2692     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2693      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2694     if (buf)
2695     {
2696         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2697         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2698         LocalFree(buf);
2699     }
2700     /* Test v1 cert with an issuer name, a subject name, and a serial number */
2701     info.Issuer.cbData = sizeof(encodedCommonName);
2702     info.Issuer.pbData = (BYTE *)encodedCommonName;
2703     info.Subject.cbData = sizeof(encodedCommonName);
2704     info.Subject.pbData = (BYTE *)encodedCommonName;
2705     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2706      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2707     if (buf)
2708     {
2709         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2710         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2711         LocalFree(buf);
2712     }
2713     /* for now, I let more interesting tests be done for each subcomponent,
2714      * rather than retesting them all here.
2715      */
2716 }
2717
2718 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2719 {
2720     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2721      v1CertWithConstraints, v1CertWithSerial };
2722     BOOL ret;
2723     BYTE *buf = NULL;
2724     DWORD size = 0, i;
2725
2726     /* Test with NULL pbEncoded */
2727     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2728      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2729     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2730      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2731     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2732      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2733     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2734      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2735     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2736      * minimum a cert must have a non-zero serial number, an issuer, and a
2737      * subject.
2738      */
2739     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2740     {
2741         ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2742          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2743          (BYTE *)&buf, &size);
2744         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
2745          "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2746     }
2747     /* Now check with serial number, subject and issuer specified */
2748     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2749      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2750     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2751     if (buf)
2752     {
2753         CERT_INFO *info = (CERT_INFO *)buf;
2754
2755         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2756         ok(info->SerialNumber.cbData == 1,
2757          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2758         ok(*info->SerialNumber.pbData == *serialNum,
2759          "Expected serial number %d, got %d\n", *serialNum,
2760          *info->SerialNumber.pbData);
2761         ok(info->Issuer.cbData == sizeof(encodedCommonName),
2762          "Wrong size %d\n", info->Issuer.cbData);
2763         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2764          "Unexpected issuer\n");
2765         ok(info->Subject.cbData == sizeof(encodedCommonName),
2766          "Wrong size %d\n", info->Subject.cbData);
2767         ok(!memcmp(info->Subject.pbData, encodedCommonName,
2768          info->Subject.cbData), "Unexpected subject\n");
2769         LocalFree(buf);
2770     }
2771 }
2772
2773 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2774  0xe, 0xf };
2775
2776 static const BYTE signedBigCert[] = {
2777  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
2778  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2779  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
2780  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2781  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2782  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
2783  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
2784  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
2785  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
2786  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2787  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
2788  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
2789
2790 static void test_encodeCert(DWORD dwEncoding)
2791 {
2792     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
2793      * also that bigCert is a NULL-terminated string, so don't count its
2794      * last byte (otherwise the signed cert won't decode.)
2795      */
2796     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
2797      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
2798     BOOL ret;
2799     BYTE *buf = NULL;
2800     DWORD bufSize = 0;
2801
2802     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
2803      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2804     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2805     if (buf)
2806     {
2807         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
2808         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
2809         LocalFree(buf);
2810     }
2811 }
2812
2813 static void test_decodeCert(DWORD dwEncoding)
2814 {
2815     BOOL ret;
2816     BYTE *buf = NULL;
2817     DWORD size = 0;
2818
2819     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
2820      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2821     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2822     if (buf)
2823     {
2824         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
2825
2826         ok(info->ToBeSigned.cbData == sizeof(bigCert),
2827          "Wrong cert size %d\n", info->ToBeSigned.cbData);
2828         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
2829          "Unexpected cert\n");
2830         ok(info->Signature.cbData == sizeof(hash),
2831          "Wrong signature size %d\n", info->Signature.cbData);
2832         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
2833          "Unexpected signature\n");
2834         LocalFree(buf);
2835     }
2836     /* A signed cert decodes as a CERT_INFO too */
2837     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
2838      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2839     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2840     if (buf)
2841     {
2842         CERT_INFO *info = (CERT_INFO *)buf;
2843
2844         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2845         ok(info->SerialNumber.cbData == 1,
2846          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2847         ok(*info->SerialNumber.pbData == *serialNum,
2848          "Expected serial number %d, got %d\n", *serialNum,
2849          *info->SerialNumber.pbData);
2850         ok(info->Issuer.cbData == sizeof(encodedCommonName),
2851          "Wrong size %d\n", info->Issuer.cbData);
2852         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2853          "Unexpected issuer\n");
2854         ok(info->Subject.cbData == sizeof(encodedCommonName),
2855          "Wrong size %d\n", info->Subject.cbData);
2856         ok(!memcmp(info->Subject.pbData, encodedCommonName,
2857          info->Subject.cbData), "Unexpected subject\n");
2858         LocalFree(buf);
2859     }
2860 }
2861
2862 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
2863 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
2864  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
2865  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2866 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
2867  0x00, 0x03 };
2868 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
2869  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
2870  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2871 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
2872  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
2873  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
2874  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
2875  0x2e, 0x6f, 0x72, 0x67 };
2876 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
2877  CRL_REASON_AFFILIATION_CHANGED;
2878
2879 static void test_encodeCRLDistPoints(DWORD dwEncoding)
2880 {
2881     CRL_DIST_POINTS_INFO info = { 0 };
2882     CRL_DIST_POINT point = { { 0 } };
2883     CERT_ALT_NAME_ENTRY entry = { 0 };
2884     BOOL ret;
2885     BYTE *buf = NULL;
2886     DWORD size = 0;
2887
2888     /* Test with an empty info */
2889     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2890      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2891     ok(!ret && GetLastError() == E_INVALIDARG,
2892      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2893     /* Test with one empty dist point */
2894     info.cDistPoint = 1;
2895     info.rgDistPoint = &point;
2896     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2897      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2898     if (buf)
2899     {
2900         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
2901         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
2902         LocalFree(buf);
2903     }
2904     /* A dist point with an invalid name */
2905     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2906     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
2907     U(entry).pwszURL = (LPWSTR)nihongoURL;
2908     U(point.DistPointName).FullName.cAltEntry = 1;
2909     U(point.DistPointName).FullName.rgAltEntry = &entry;
2910     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2911      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2912     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
2913      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
2914     /* The first invalid character is at index 7 */
2915     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
2916      "Expected invalid char at index 7, got %d\n",
2917      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
2918     /* A dist point with (just) a valid name */
2919     U(entry).pwszURL = (LPWSTR)url;
2920     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2921      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2922     if (buf)
2923     {
2924         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
2925         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
2926         LocalFree(buf);
2927     }
2928     /* A dist point with (just) reason flags */
2929     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
2930     point.ReasonFlags.cbData = sizeof(crlReason);
2931     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
2932     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2933      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2934     if (buf)
2935     {
2936         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
2937         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
2938         LocalFree(buf);
2939     }
2940     /* A dist point with just an issuer */
2941     point.ReasonFlags.cbData = 0;
2942     point.CRLIssuer.cAltEntry = 1;
2943     point.CRLIssuer.rgAltEntry = &entry;
2944     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2945      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2946     if (buf)
2947     {
2948         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
2949         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
2950         LocalFree(buf);
2951     }
2952     /* A dist point with both a name and an issuer */
2953     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2954     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2955      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2956     if (buf)
2957     {
2958         ok(size == sizeof(distPointWithUrlAndIssuer),
2959          "Wrong size %d\n", size);
2960         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
2961         LocalFree(buf);
2962     }
2963 }
2964
2965 static void test_decodeCRLDistPoints(DWORD dwEncoding)
2966 {
2967     BOOL ret;
2968     BYTE *buf = NULL;
2969     DWORD size = 0;
2970     PCRL_DIST_POINTS_INFO info;
2971     PCRL_DIST_POINT point;
2972     PCERT_ALT_NAME_ENTRY entry;
2973
2974     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2975      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2976      (BYTE *)&buf, &size);
2977     if (ret)
2978     {
2979         info = (PCRL_DIST_POINTS_INFO)buf;
2980         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2981          "Wrong size %d\n", size);
2982         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
2983          info->cDistPoint);
2984         point = info->rgDistPoint;
2985         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
2986          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
2987          point->DistPointName.dwDistPointNameChoice);
2988         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2989         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2990         LocalFree(buf);
2991     }
2992     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2993      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2994      (BYTE *)&buf, &size);
2995     if (ret)
2996     {
2997         info = (PCRL_DIST_POINTS_INFO)buf;
2998         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2999          "Wrong size %d\n", size);
3000         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3001          info->cDistPoint);
3002         point = info->rgDistPoint;
3003         ok(point->DistPointName.dwDistPointNameChoice ==
3004          CRL_DIST_POINT_FULL_NAME,
3005          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3006          point->DistPointName.dwDistPointNameChoice);
3007         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3008          "Expected 1 name entry, got %d\n",
3009          U(point->DistPointName).FullName.cAltEntry);
3010         entry = U(point->DistPointName).FullName.rgAltEntry;
3011         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3012          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3013         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3014         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3015         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3016         LocalFree(buf);
3017     }
3018     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3019      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3020      NULL, (BYTE *)&buf, &size);
3021     if (ret)
3022     {
3023         info = (PCRL_DIST_POINTS_INFO)buf;
3024         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3025          "Wrong size %d\n", size);
3026         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3027          info->cDistPoint);
3028         point = info->rgDistPoint;
3029         ok(point->DistPointName.dwDistPointNameChoice ==
3030          CRL_DIST_POINT_NO_NAME,
3031          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3032          point->DistPointName.dwDistPointNameChoice);
3033         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3034          "Expected reason length\n");
3035         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3036          "Unexpected reason\n");
3037         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3038         LocalFree(buf);
3039     }
3040     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3041      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3042      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3043     if (ret)
3044     {
3045         info = (PCRL_DIST_POINTS_INFO)buf;
3046         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3047          "Wrong size %d\n", size);
3048         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3049          info->cDistPoint);
3050         point = info->rgDistPoint;
3051         ok(point->DistPointName.dwDistPointNameChoice ==
3052          CRL_DIST_POINT_FULL_NAME,
3053          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3054          point->DistPointName.dwDistPointNameChoice);
3055         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3056          "Expected 1 name entry, got %d\n",
3057          U(point->DistPointName).FullName.cAltEntry);
3058         entry = U(point->DistPointName).FullName.rgAltEntry;
3059         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3060          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3061         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3062         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3063         ok(point->CRLIssuer.cAltEntry == 1,
3064          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3065         entry = point->CRLIssuer.rgAltEntry;
3066         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3067          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3068         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3069         LocalFree(buf);
3070     }
3071 }
3072
3073 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3074 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3075 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3076  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3077  0x67 };
3078
3079 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3080 {
3081     BOOL ret;
3082     BYTE *buf = NULL;
3083     DWORD size = 0;
3084     CRL_ISSUING_DIST_POINT point = { { 0 } };
3085     CERT_ALT_NAME_ENTRY entry;
3086
3087     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3088      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3089     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3090      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3091     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3092      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3093     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3094     if (buf)
3095     {
3096         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3097         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3098         LocalFree(buf);
3099     }
3100     /* nonsensical flags */
3101     point.fOnlyContainsUserCerts = TRUE;
3102     point.fOnlyContainsCACerts = TRUE;
3103     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3104      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3105     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3106     if (buf)
3107     {
3108         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3109         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3110         LocalFree(buf);
3111     }
3112     /* unimplemented name type */
3113     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3114     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3115     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3116      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3117     ok(!ret && GetLastError() == E_INVALIDARG,
3118      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3119     /* empty name */
3120     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3121     U(point.DistPointName).FullName.cAltEntry = 0;
3122     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3123      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3124     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3125     if (buf)
3126     {
3127         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3128         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3129         LocalFree(buf);
3130     }
3131     /* name with URL entry */
3132     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3133     U(entry).pwszURL = (LPWSTR)url;
3134     U(point.DistPointName).FullName.cAltEntry = 1;
3135     U(point.DistPointName).FullName.rgAltEntry = &entry;
3136     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3137      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3138     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3139     if (buf)
3140     {
3141         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3142         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3143         LocalFree(buf);
3144     }
3145 }
3146
3147 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3148  const CERT_ALT_NAME_ENTRY *got)
3149 {
3150     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3151      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3152      got->dwAltNameChoice);
3153     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3154     {
3155         switch (got->dwAltNameChoice)
3156         {
3157         case CERT_ALT_NAME_RFC822_NAME:
3158         case CERT_ALT_NAME_DNS_NAME:
3159         case CERT_ALT_NAME_EDI_PARTY_NAME:
3160         case CERT_ALT_NAME_URL:
3161         case CERT_ALT_NAME_REGISTERED_ID:
3162             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3163                !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL), "Unexpected name\n");
3164             break;
3165         case CERT_ALT_NAME_X400_ADDRESS:
3166         case CERT_ALT_NAME_DIRECTORY_NAME:
3167         case CERT_ALT_NAME_IP_ADDRESS:
3168             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3169                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3170             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3171                        U(*got).IPAddress.cbData), "Unexpected value\n");
3172             break;
3173         }
3174     }
3175 }
3176
3177 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3178  const CERT_ALT_NAME_INFO *got)
3179 {
3180     DWORD i;
3181
3182     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3183      expected->cAltEntry, got->cAltEntry);
3184     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3185         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3186 }
3187
3188 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3189  const CRL_DIST_POINT_NAME *got)
3190 {
3191     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3192      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3193     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3194         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3195 }
3196
3197 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3198  const CRL_ISSUING_DIST_POINT *got)
3199 {
3200     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3201     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3202      "Unexpected fOnlyContainsUserCerts\n");
3203     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3204      "Unexpected fOnlyContainsCACerts\n");
3205     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3206      "Unexpected reason flags\n");
3207     ok(got->fIndirectCRL == expected->fIndirectCRL,
3208      "Unexpected fIndirectCRL\n");
3209 }
3210
3211 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3212 {
3213     BOOL ret;
3214     BYTE *buf = NULL;
3215     DWORD size = 0;
3216     CRL_ISSUING_DIST_POINT point = { { 0 } };
3217
3218     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3219      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3220      (BYTE *)&buf, &size);
3221     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3222     if (ret)
3223     {
3224         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3225         LocalFree(buf);
3226     }
3227     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3228      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3229      (BYTE *)&buf, &size);
3230     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3231     if (ret)
3232     {
3233         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3234         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3235         LocalFree(buf);
3236     }
3237     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3238      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3239      (BYTE *)&buf, &size);
3240     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3241     if (ret)
3242     {
3243         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3244         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3245         U(point.DistPointName).FullName.cAltEntry = 0;
3246         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3247         LocalFree(buf);
3248     }
3249     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3250      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3251     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3252     if (ret)
3253     {
3254         CERT_ALT_NAME_ENTRY entry;
3255
3256         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3257         U(entry).pwszURL = (LPWSTR)url;
3258         U(point.DistPointName).FullName.cAltEntry = 1;
3259         U(point.DistPointName).FullName.rgAltEntry = &entry;
3260         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3261         LocalFree(buf);
3262     }
3263 }
3264
3265 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3266  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3267  0x30, 0x5a };
3268 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3269  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3270  0x30, 0x30, 0x30, 0x30, 0x5a };
3271 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3272  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3273  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3274  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3275  0x5a };
3276 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3277  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3278  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3279  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3280  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3281  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3282 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3283  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3284  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3285  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3286  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3287  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3288 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3289  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3290  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3291  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3292  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3293  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3294  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3295 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3296  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3297  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3298  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3299  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3300  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3301  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3302 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3303  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3304  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3305  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3306  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3307  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3308  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3309 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3310  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3311  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3312  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3313  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3314  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3315  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3316
3317 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3318 {
3319     BOOL ret;
3320     BYTE *buf = NULL;
3321     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3322     DWORD size = 0;
3323     CRL_INFO info = { 0 };
3324     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3325     CERT_EXTENSION ext;
3326
3327     /* Test with a V1 CRL */
3328     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3329      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3330     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3331     if (buf)
3332     {
3333         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3334         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3335         LocalFree(buf);
3336     }
3337     /* Test v2 CRL */
3338     info.dwVersion = CRL_V2;
3339     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3340      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3341     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3342     if (buf)
3343     {
3344         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3345          v2CRL[1] + 2, size);
3346         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3347         LocalFree(buf);
3348     }
3349     /* v1 CRL with a name */
3350     info.dwVersion = CRL_V1;
3351     info.Issuer.cbData = sizeof(encodedCommonName);
3352     info.Issuer.pbData = (BYTE *)encodedCommonName;
3353     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3354      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3355     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3356     if (buf)
3357     {
3358         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3359         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3360         LocalFree(buf);
3361     }
3362     /* v1 CRL with a name and a NULL entry pointer */
3363     info.cCRLEntry = 1;
3364     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3365      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3366     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3367      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3368     /* now set an empty entry */
3369     info.rgCRLEntry = &entry;
3370     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3371      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3372     if (buf)
3373     {
3374         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3375          "Wrong size %d\n", size);
3376         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3377          "Got unexpected value\n");
3378         LocalFree(buf);
3379     }
3380     /* an entry with a serial number */
3381     entry.SerialNumber.cbData = sizeof(serialNum);
3382     entry.SerialNumber.pbData = (BYTE *)serialNum;
3383     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3384      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3385     if (buf)
3386     {
3387         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3388          "Wrong size %d\n", size);
3389         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3390          "Got unexpected value\n");
3391         LocalFree(buf);
3392     }
3393     /* an entry with an extension */
3394     entry.cExtension = 1;
3395     entry.rgExtension = &criticalExt;
3396     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3397      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3398     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3399     if (buf)
3400     {
3401         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3402         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3403         LocalFree(buf);
3404     }
3405     /* a CRL with an extension */
3406     entry.cExtension = 0;
3407     info.cExtension = 1;
3408     info.rgExtension = &criticalExt;
3409     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3410      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3411     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3412     if (buf)
3413     {
3414         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3415         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3416         LocalFree(buf);
3417     }
3418     /* a v2 CRL with an extension, this time non-critical */
3419     info.dwVersion = CRL_V2;
3420     info.rgExtension = &nonCriticalExt;
3421     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3422      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3423     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3424     if (buf)
3425     {
3426         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3427         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3428         LocalFree(buf);
3429     }
3430     /* a v2 CRL with an issuing dist point extension */
3431     ext.pszObjId = oid_issuing_dist_point;
3432     ext.fCritical = TRUE;
3433     ext.Value.cbData = sizeof(urlIDP);
3434     ext.Value.pbData = (LPBYTE)urlIDP;
3435     entry.rgExtension = &ext;
3436     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3437      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3438     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3439     if (buf)
3440     {
3441         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3442         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3443         LocalFree(buf);
3444     }
3445 }
3446
3447 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3448  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3449  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3450  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3451  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3452  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3453  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3454  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3455  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3456  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3457  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3458  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3459  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3460  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3461  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3462  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3463  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3464  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3465  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3466  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3467  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3468  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3469  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3470  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3471  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3472  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3473  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3474  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3475  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3476  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3477  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3478  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3479  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3480  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3481  0xcd };
3482 static const BYTE verisignCRLWithLotsOfEntries[] = {
3483 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3484 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3485 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3486 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3487 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3488 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3489 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3490 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3491 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3492 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3493 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3494 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3495 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3496 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3497 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3498 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3499 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3500 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3501 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3502 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3503 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3504 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3505 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3506 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3507 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3508 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3509 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3510 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3511 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3512 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3513 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3514 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3515 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3516 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3517 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3518 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3519 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3520 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3521 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3522 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3523 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3524 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3525 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3526 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3527 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3528 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3529 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3530 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3531 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3532 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3533 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3534 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3535 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3536 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3537 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3538 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3539 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3540 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3541 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3542 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3543 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3544 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3545 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3546 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3547 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3548 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3549 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3550 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3551 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3552 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3553 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3554 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3555 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3556 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3557 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3558 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3559 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3560 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3561 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3562 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3563 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3564 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3565 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3566 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3567 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3568 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3569 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3570 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3571 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3572 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3573 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3574 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3575 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3576 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3577 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3578 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3579 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3580 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3581 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3582 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3583 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3584 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3585 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3586 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3587 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3588 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3589 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3590 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3591 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3592 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3593 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3594 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3595 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3596 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3597 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3598 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3599 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3600 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3601 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3602 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3603 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3604 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3605 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3606 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3607 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3608 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3609 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3610 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3611 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3612 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3613 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3614 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3615 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3616 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3617 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3618 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3619 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3620 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3621 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3622 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3623 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3624 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3625 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3626 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3627 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3628 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3629 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3630 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3631 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3632 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3633 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3634 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3635 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3636 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3637 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3638 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3639 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3640 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3641 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3642 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3643 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3644 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3645 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3646 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3647 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3648 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3649 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3650 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3651 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3652 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3653 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3654 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3655 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3656 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3657 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3658 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3659 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3660 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3661 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3662 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3663 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3664 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3665 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3666 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3667 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3668 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3669 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3670 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
3671 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
3672 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
3673 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
3674 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
3675 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
3676 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
3677 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
3678 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
3679 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
3680 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
3681 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
3682 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
3683 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
3684 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
3685 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
3686 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
3687 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
3688 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
3689 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
3690 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
3691 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
3692 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
3693 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
3694 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
3695 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
3696 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
3697 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
3698 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
3699 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
3700 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
3701 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
3702 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
3703 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
3704 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
3705 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
3706 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
3707 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
3708 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
3709 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
3710 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
3711 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
3712 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
3713 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
3714 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
3715 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
3716 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
3717 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
3718 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
3719 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
3720 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
3721 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
3722 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
3723 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
3724 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
3725 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
3726 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
3727 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
3728 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
3729 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
3730 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
3731 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
3732 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
3733 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
3734 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
3735 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
3736 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
3737 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
3738 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
3739 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
3740 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
3741 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
3742 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
3743 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
3744 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
3745 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
3746 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
3747 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
3748 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
3749 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
3750 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
3751 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
3752 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
3753 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
3754 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
3755 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
3756 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
3757 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
3758 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
3759 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
3760 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
3761 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
3762 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
3763 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
3764 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
3765 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
3766 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
3767 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
3768 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
3769 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
3770 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
3771 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
3772 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
3773 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
3774 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
3775 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
3776 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
3777 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
3778 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
3779 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
3780 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
3781 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
3782 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
3783 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
3784 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
3785 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
3786 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
3787 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
3788 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
3789 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
3790 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
3791 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
3792 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
3793 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
3794 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
3795 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
3796 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
3797 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
3798 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
3799 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
3800 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
3801 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
3802 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
3803 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
3804 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
3805 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
3806 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
3807 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
3808 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
3809 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
3810 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
3811 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
3812 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
3813 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
3814 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
3815 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
3816 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
3817 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
3818 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
3819 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
3820 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
3821 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
3822 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
3823 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
3824 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
3825 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
3826 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
3827 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
3828 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
3829 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
3830 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
3831 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
3832 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
3833 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
3834 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
3835 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
3836 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
3837 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
3838 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
3839 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
3840 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
3841 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
3842 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
3843 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
3844 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
3845 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
3846 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
3847 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
3848 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
3849 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
3850 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
3851 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
3852 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
3853 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
3854 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
3855 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
3856 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
3857 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
3858 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
3859 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
3860 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
3861 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
3862 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
3863 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
3864 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
3865 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
3866 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
3867 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
3868 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
3869 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
3870 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
3871 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
3872 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
3873 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
3874 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
3875 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
3876 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
3877 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
3878 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
3879 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
3880 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
3881 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
3882 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
3883 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
3884 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
3885 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
3886 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
3887 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
3888 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
3889 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
3890 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
3891 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
3892 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
3893 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
3894 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
3895 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
3896 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
3897 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
3898 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
3899 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
3900 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
3901 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
3902 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
3903 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
3904 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
3905 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
3906 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
3907 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
3908 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
3909 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
3910 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
3911 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
3912 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
3913 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
3914 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
3915 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
3916 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
3917 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
3918 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
3919 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
3920 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
3921 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
3922 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
3923 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
3924 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
3925 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
3926 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
3927 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
3928 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
3929 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
3930 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
3931 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
3932 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
3933 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
3934 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
3935 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
3936 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
3937 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
3938 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
3939 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
3940 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
3941 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
3942 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
3943 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
3944 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
3945 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
3946 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
3947 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
3948 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
3949 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
3950 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
3951 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
3952 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
3953 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
3954 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
3955 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
3956 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
3957 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
3958 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
3959 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
3960 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
3961 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
3962 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
3963 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
3964 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
3965 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
3966 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
3967 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
3968 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
3969 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
3970 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
3971 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
3972 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
3973 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
3974 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
3975 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
3976 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
3977 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
3978 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
3979 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
3980 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
3981 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
3982 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
3983 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
3984 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
3985 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
3986 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
3987 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
3988 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
3989 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
3990 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
3991
3992 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
3993 {
3994     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
3995     BOOL ret;
3996     BYTE *buf = NULL;
3997     DWORD size = 0, i;
3998
3999     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4000     {
4001         ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4002          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4003          (BYTE *)&buf, &size);
4004         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
4005          "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4006     }
4007     /* at a minimum, a CRL must contain an issuer: */
4008     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4009      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4010      (BYTE *)&buf, &size);
4011     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4012     if (buf)
4013     {
4014         CRL_INFO *info = (CRL_INFO *)buf;
4015
4016         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4017         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4018          info->cCRLEntry);
4019         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4020          "Wrong issuer size %d\n", info->Issuer.cbData);
4021         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4022          "Unexpected issuer\n");
4023         LocalFree(buf);
4024     }
4025     /* check decoding with an empty CRL entry */
4026     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4027      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4028      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4029     todo_wine ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
4030      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4031     /* with a real CRL entry */
4032     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4033      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4034      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4035     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4036     if (buf)
4037     {
4038         CRL_INFO *info = (CRL_INFO *)buf;
4039         CRL_ENTRY *entry;
4040
4041         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4042         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4043          info->cCRLEntry);
4044         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4045         entry = info->rgCRLEntry;
4046         ok(entry->SerialNumber.cbData == 1,
4047          "Expected serial number size 1, got %d\n",
4048          entry->SerialNumber.cbData);
4049         ok(*entry->SerialNumber.pbData == *serialNum,
4050          "Expected serial number %d, got %d\n", *serialNum,
4051          *entry->SerialNumber.pbData);
4052         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4053          "Wrong issuer size %d\n", info->Issuer.cbData);
4054         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4055          "Unexpected issuer\n");
4056     }
4057     /* a real CRL from verisign that has extensions */
4058     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4059      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4060      NULL, (BYTE *)&buf, &size);
4061     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4062     if (buf)
4063     {
4064         CRL_INFO *info = (CRL_INFO *)buf;
4065         CRL_ENTRY *entry;
4066
4067         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4068         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4069          info->cCRLEntry);
4070         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4071         entry = info->rgCRLEntry;
4072         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4073          info->cExtension);
4074         LocalFree(buf);
4075     }
4076     /* another real CRL from verisign that has lots of entries */
4077     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4078      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4079      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4080     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4081     if (buf)
4082     {
4083         CRL_INFO *info = (CRL_INFO *)buf;
4084
4085         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4086         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4087          info->cCRLEntry);
4088         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4089          info->cExtension);
4090         LocalFree(buf);
4091     }
4092     /* and finally, with an extension */
4093     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4094      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4095      NULL, (BYTE *)&buf, &size);
4096     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4097     if (buf)
4098     {
4099         CRL_INFO *info = (CRL_INFO *)buf;
4100         CRL_ENTRY *entry;
4101
4102         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4103         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4104          info->cCRLEntry);
4105         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4106         entry = info->rgCRLEntry;
4107         ok(entry->SerialNumber.cbData == 1,
4108          "Expected serial number size 1, got %d\n",
4109          entry->SerialNumber.cbData);
4110         ok(*entry->SerialNumber.pbData == *serialNum,
4111          "Expected serial number %d, got %d\n", *serialNum,
4112          *entry->SerialNumber.pbData);
4113         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4114          "Wrong issuer size %d\n", info->Issuer.cbData);
4115         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4116          "Unexpected issuer\n");
4117         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4118          info->cExtension);
4119     }
4120     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4121      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4122      NULL, (BYTE *)&buf, &size);
4123     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4124     if (buf)
4125     {
4126         CRL_INFO *info = (CRL_INFO *)buf;
4127
4128         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4129          info->cExtension);
4130         LocalFree(buf);
4131     }
4132     /* And again, with an issuing dist point */
4133     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4134      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4135      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4136     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4137     if (buf)
4138     {
4139         CRL_INFO *info = (CRL_INFO *)buf;
4140
4141         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4142          info->cExtension);
4143         LocalFree(buf);
4144     }
4145 }
4146
4147 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4148  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4149 static const BYTE encodedUsage[] = {
4150  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4151  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4152  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4153
4154 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4155 {
4156     BOOL ret;
4157     BYTE *buf = NULL;
4158     DWORD size = 0;
4159     CERT_ENHKEY_USAGE usage;
4160
4161     /* Test with empty usage */
4162     usage.cUsageIdentifier = 0;
4163     ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4164      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4165     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4166     if (buf)
4167     {
4168         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4169         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4170         LocalFree(buf);
4171     }
4172     /* Test with a few usages */
4173     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4174     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4175     ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4176      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4177     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4178     if (buf)
4179     {
4180         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4181         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4182         LocalFree(buf);
4183     }
4184 }
4185
4186 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4187 {
4188     BOOL ret;
4189     LPBYTE buf = NULL;
4190     DWORD size = 0;
4191
4192     ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4193      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4194      (BYTE *)&buf, &size);
4195     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4196     if (buf)
4197     {
4198         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4199
4200         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4201          "Wrong size %d\n", size);
4202         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4203          usage->cUsageIdentifier);
4204         LocalFree(buf);
4205     }
4206     ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4207      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4208      (BYTE *)&buf, &size);
4209     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4210     if (buf)
4211     {
4212         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4213         DWORD i;
4214
4215         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4216          "Wrong size %d\n", size);
4217         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4218          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4219         for (i = 0; i < usage->cUsageIdentifier; i++)
4220             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4221              "Expected OID %s, got %s\n", keyUsages[i],
4222              usage->rgpszUsageIdentifier[i]);
4223         LocalFree(buf);
4224     }
4225 }
4226
4227 static const BYTE authorityKeyIdWithId[] = { 0x30,0x03,0x80,0x01,0x01 };
4228 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4229  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4230  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4231 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4232
4233 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4234 {
4235     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4236     BOOL ret;
4237     BYTE *buf = NULL;
4238     DWORD size = 0;
4239
4240     /* Test with empty id */
4241     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4242      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4243     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4244     if (buf)
4245     {
4246         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4247         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4248         LocalFree(buf);
4249     }
4250     /* With just a key id */
4251     info.KeyId.cbData = sizeof(serialNum);
4252     info.KeyId.pbData = (BYTE *)serialNum;
4253     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4254      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4255     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4256     if (buf)
4257     {
4258         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4259         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4260         LocalFree(buf);
4261     }
4262     /* With just an issuer */
4263     info.KeyId.cbData = 0;
4264     info.CertIssuer.cbData = sizeof(encodedCommonName);
4265     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4266     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4267      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4268     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4269     if (buf)
4270     {
4271         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4272          size);
4273         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4274         LocalFree(buf);
4275     }
4276     /* With just a serial number */
4277     info.CertIssuer.cbData = 0;
4278     info.CertSerialNumber.cbData = sizeof(serialNum);
4279     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4280     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4281      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4282     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4283     if (buf)
4284     {
4285         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4286          size);
4287         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4288         LocalFree(buf);
4289     }
4290 }
4291
4292 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4293 {
4294     BOOL ret;
4295     LPBYTE buf = NULL;
4296     DWORD size = 0;
4297
4298     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4299      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4300      (BYTE *)&buf, &size);
4301     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4302     if (buf)
4303     {
4304         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4305
4306         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4307          size);
4308         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4309         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4310         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4311         LocalFree(buf);
4312     }
4313     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4314      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4315      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4316     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4317     if (buf)
4318     {
4319         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4320
4321         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4322          size);
4323         ok(info->KeyId.cbData == sizeof(serialNum), "Unexpected key id len\n");
4324         ok(!memcmp(info->KeyId.pbData, serialNum, sizeof(serialNum)),
4325          "Unexpected key id\n");
4326         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4327         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4328         LocalFree(buf);
4329     }
4330     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4331      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4332      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4333     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4334     if (buf)
4335     {
4336         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4337
4338         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4339          size);
4340         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4341         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4342          "Unexpected issuer len\n");
4343         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4344          sizeof(encodedCommonName)), "Unexpected issuer\n");
4345         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4346         LocalFree(buf);
4347     }
4348     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4349      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4350      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4351     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4352     if (buf)
4353     {
4354         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4355
4356         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4357          size);
4358         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4359         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4360         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4361          "Unexpected serial number len\n");
4362         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4363          "Unexpected serial number\n");
4364         LocalFree(buf);
4365     }
4366 }
4367
4368 /* Free *pInfo with HeapFree */
4369 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
4370 {
4371     BOOL ret;
4372     DWORD size = 0;
4373     HCRYPTKEY key;
4374
4375     /* This crashes
4376     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
4377      */
4378     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
4379     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4380      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4381     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
4382      &size);
4383     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4384      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4385     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
4386      NULL, &size);
4387     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4388      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4389     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
4390      0, NULL, NULL, &size);
4391     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4392      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4393     /* Test with no key */
4394     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
4395      0, NULL, NULL, &size);
4396     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
4397      GetLastError());
4398     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
4399     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
4400     if (ret)
4401     {
4402         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
4403          NULL, 0, NULL, NULL, &size);
4404         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
4405         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
4406         if (*pInfo)
4407         {
4408             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
4409              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
4410             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
4411              GetLastError());
4412             if (ret)
4413             {
4414                 /* By default (we passed NULL as the OID) the OID is
4415                  * szOID_RSA_RSA.
4416                  */
4417                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
4418                  "Expected %s, got %s\n", szOID_RSA_RSA,
4419                  (*pInfo)->Algorithm.pszObjId);
4420             }
4421         }
4422     }
4423 }
4424
4425 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
4426  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
4427  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
4428  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
4429  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
4430  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
4431  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
4432  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
4433  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
4434  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
4435  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
4436  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
4437  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
4438  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
4439  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
4440  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
4441  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
4442  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
4443  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
4444  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
4445  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
4446  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
4447  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
4448  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
4449  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
4450
4451 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
4452 {
4453     BOOL ret;
4454     HCRYPTKEY key;
4455     PCCERT_CONTEXT context;
4456
4457     /* These crash
4458     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
4459     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
4460     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
4461     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
4462      NULL);
4463      */
4464     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
4465     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
4466      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
4467     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
4468     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
4469      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
4470     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
4471      &key);
4472     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
4473      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
4474     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
4475      &key);
4476     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
4477     CryptDestroyKey(key);
4478
4479     /* Test importing a public key from a certificate context */
4480     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
4481      sizeof(expiredCert));
4482     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
4483      GetLastError());
4484     if (context)
4485     {
4486         ok(!strcmp(szOID_RSA_RSA,
4487          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
4488          "Expected %s, got %s\n", szOID_RSA_RSA,
4489          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
4490         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
4491          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
4492         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
4493         CryptDestroyKey(key);
4494         CertFreeCertificateContext(context);
4495     }
4496 }
4497
4498 static const char cspName[] = "WineCryptTemp";
4499
4500 static void testPortPublicKeyInfo(void)
4501 {
4502     HCRYPTPROV csp;
4503     BOOL ret;
4504     PCERT_PUBLIC_KEY_INFO info = NULL;
4505
4506     /* Just in case a previous run failed, delete this thing */
4507     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
4508      CRYPT_DELETEKEYSET);
4509     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
4510      CRYPT_NEWKEYSET);
4511
4512     testExportPublicKey(csp, &info);
4513     testImportPublicKey(csp, info);
4514
4515     HeapFree(GetProcessHeap(), 0, info);
4516     CryptReleaseContext(csp, 0);
4517     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
4518      CRYPT_DELETEKEYSET);
4519 }
4520
4521 START_TEST(encode)
4522 {
4523     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
4524      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
4525     DWORD i;
4526
4527     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
4528     {
4529         test_encodeInt(encodings[i]);
4530         test_decodeInt(encodings[i]);
4531         test_encodeEnumerated(encodings[i]);
4532         test_decodeEnumerated(encodings[i]);
4533         test_encodeFiletime(encodings[i]);
4534         test_decodeFiletime(encodings[i]);
4535         test_encodeName(encodings[i]);
4536         test_decodeName(encodings[i]);
4537         test_encodeUnicodeName(encodings[i]);
4538         test_decodeUnicodeName(encodings[i]);
4539         test_encodeNameValue(encodings[i]);
4540         test_decodeNameValue(encodings[i]);
4541         test_encodeUnicodeNameValue(encodings[i]);
4542         test_decodeUnicodeNameValue(encodings[i]);
4543         test_encodeAltName(encodings[i]);
4544         test_decodeAltName(encodings[i]);
4545         test_encodeOctets(encodings[i]);
4546         test_decodeOctets(encodings[i]);
4547         test_encodeBits(encodings[i]);
4548         test_decodeBits(encodings[i]);
4549         test_encodeBasicConstraints(encodings[i]);
4550         test_decodeBasicConstraints(encodings[i]);
4551         test_encodeRsaPublicKey(encodings[i]);
4552         test_decodeRsaPublicKey(encodings[i]);
4553         test_encodeSequenceOfAny(encodings[i]);
4554         test_decodeSequenceOfAny(encodings[i]);
4555         test_encodeExtensions(encodings[i]);
4556         test_decodeExtensions(encodings[i]);
4557         test_encodePublicKeyInfo(encodings[i]);
4558         test_decodePublicKeyInfo(encodings[i]);
4559         test_encodeCertToBeSigned(encodings[i]);
4560         test_decodeCertToBeSigned(encodings[i]);
4561         test_encodeCert(encodings[i]);
4562         test_decodeCert(encodings[i]);
4563         test_encodeCRLDistPoints(encodings[i]);
4564         test_decodeCRLDistPoints(encodings[i]);
4565         test_encodeCRLIssuingDistPoint(encodings[i]);
4566         test_decodeCRLIssuingDistPoint(encodings[i]);
4567         test_encodeCRLToBeSigned(encodings[i]);
4568         test_decodeCRLToBeSigned(encodings[i]);
4569         test_encodeEnhancedKeyUsage(encodings[i]);
4570         test_decodeEnhancedKeyUsage(encodings[i]);
4571         test_encodeAuthorityKeyId(encodings[i]);
4572         test_decodeAuthorityKeyId(encodings[i]);
4573     }
4574     testPortPublicKeyInfo();
4575 }