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