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