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