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