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