wintrust: Use helper function for setting confidence in SoftpubCheckCert.
[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
30 static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
31 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
32
33 struct encodedInt
34 {
35     int val;
36     const BYTE *encoded;
37 };
38
39 static const BYTE bin1[] = {0x02,0x01,0x01};
40 static const BYTE bin2[] = {0x02,0x01,0x7f};
41 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
42 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
43 static const BYTE bin5[] = {0x02,0x01,0x80};
44 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
45 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
46
47 static const struct encodedInt ints[] = {
48  { 1,          bin1 },
49  { 127,        bin2 },
50  { 128,        bin3 },
51  { 256,        bin4 },
52  { -128,       bin5 },
53  { -129,       bin6 },
54  { 0xbaddf00d, bin7 },
55 };
56
57 struct encodedBigInt
58 {
59     const BYTE *val;
60     const BYTE *encoded;
61     const BYTE *decoded;
62 };
63
64 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
65 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
66 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
67
68 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
69 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
70 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
71
72 static const struct encodedBigInt bigInts[] = {
73  { bin8, bin9, bin10 },
74  { bin11, bin12, bin13 },
75 };
76
77 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
78 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
79 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
80 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
81
82 /* Decoded is the same as original, so don't bother storing a separate copy */
83 static const struct encodedBigInt bigUInts[] = {
84  { bin14, bin15, NULL },
85  { bin16, bin17, NULL },
86 };
87
88 static void test_encodeInt(DWORD dwEncoding)
89 {
90     DWORD bufSize = 0;
91     int i;
92     BOOL ret;
93     CRYPT_INTEGER_BLOB blob;
94     BYTE *buf = NULL;
95
96     /* CryptEncodeObjectEx with NULL bufSize crashes..
97     ret = pCryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
98      NULL);
99      */
100     /* check bogus encoding */
101     ret = pCryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
102      &bufSize);
103     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
104      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
105     if (0)
106     {
107         /* check with NULL integer buffer.  Windows XP incorrectly returns an
108          * NTSTATUS (crashes on win9x).
109          */
110         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
111          &bufSize);
112         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
113          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
114     }
115     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
116     {
117         /* encode as normal integer */
118         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
119          NULL, NULL, &bufSize);
120         ok(ret, "Expected success, got %d\n", GetLastError());
121         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
122          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
123         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
124         if (buf)
125         {
126             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
127              buf[0]);
128             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
129              buf[1], ints[i].encoded[1]);
130             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
131              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
132             LocalFree(buf);
133         }
134         /* encode as multibyte integer */
135         blob.cbData = sizeof(ints[i].val);
136         blob.pbData = (BYTE *)&ints[i].val;
137         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
138          0, NULL, NULL, &bufSize);
139         ok(ret, "Expected success, got %d\n", GetLastError());
140         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
141          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
142         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
143         if (buf)
144         {
145             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
146              buf[0]);
147             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
148              buf[1], ints[i].encoded[1]);
149             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
150              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
151             LocalFree(buf);
152         }
153     }
154     /* encode a couple bigger ints, just to show it's little-endian and leading
155      * sign bytes are dropped
156      */
157     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
158     {
159         blob.cbData = strlen((const char*)bigInts[i].val);
160         blob.pbData = (BYTE *)bigInts[i].val;
161         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
162          0, NULL, NULL, &bufSize);
163         ok(ret, "Expected success, got %d\n", GetLastError());
164         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
165          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
166         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
167         if (buf)
168         {
169             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
170              buf[0]);
171             ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
172              buf[1], bigInts[i].encoded[1]);
173             ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
174              bigInts[i].encoded[1] + 1),
175              "Encoded value didn't match expected\n");
176             LocalFree(buf);
177         }
178     }
179     /* and, encode some uints */
180     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
181     {
182         blob.cbData = strlen((const char*)bigUInts[i].val);
183         blob.pbData = (BYTE*)bigUInts[i].val;
184         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
185          0, NULL, NULL, &bufSize);
186         ok(ret, "Expected success, got %d\n", GetLastError());
187         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
188          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
189         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
190         if (buf)
191         {
192             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
193              buf[0]);
194             ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
195              buf[1], bigUInts[i].encoded[1]);
196             ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
197              bigUInts[i].encoded[1] + 1),
198              "Encoded value didn't match expected\n");
199             LocalFree(buf);
200         }
201     }
202 }
203
204 static void test_decodeInt(DWORD dwEncoding)
205 {
206     static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
207     static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
208     static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
209     static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
210     static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
211     BYTE *buf = NULL;
212     DWORD bufSize = 0;
213     int i;
214     BOOL ret;
215
216     /* CryptDecodeObjectEx with NULL bufSize crashes..
217     ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
218      ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
219      */
220     /* check bogus encoding */
221     ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
222      ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
223     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
224      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
225     /* check with NULL integer buffer */
226     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
227      &bufSize);
228     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
229      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
230     /* check with a valid, but too large, integer */
231     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
232      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
233     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
234      "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
235     /* check with a DER-encoded string */
236     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
237      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
238     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
239      "Expected CRYPT_E_ASN1_BADTAG, got %d\n", GetLastError());
240     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
241     {
242         /* When the output buffer is NULL, this always succeeds */
243         SetLastError(0xdeadbeef);
244         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
245          ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
246          &bufSize);
247         ok(ret && GetLastError() == NOERROR,
248          "Expected success and NOERROR, got %d\n", GetLastError());
249         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
250          ints[i].encoded, ints[i].encoded[1] + 2,
251          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
252         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
253         ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
254         ok(buf != NULL, "Expected allocated buffer\n");
255         if (buf)
256         {
257             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
258              ints[i].val, *(int *)buf);
259             LocalFree(buf);
260         }
261     }
262     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
263     {
264         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
265          bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
266          &bufSize);
267         ok(ret && GetLastError() == NOERROR,
268          "Expected success and NOERROR, got %d\n", GetLastError());
269         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
270          bigInts[i].encoded, bigInts[i].encoded[1] + 2,
271          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
272         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
273         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
274         ok(buf != NULL, "Expected allocated buffer\n");
275         if (buf)
276         {
277             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
278
279             ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
280              "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
281              blob->cbData);
282             ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
283              "Unexpected value\n");
284             LocalFree(buf);
285         }
286     }
287     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
288     {
289         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
290          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
291          &bufSize);
292         ok(ret && GetLastError() == NOERROR,
293          "Expected success and NOERROR, got %d\n", GetLastError());
294         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
295          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
296          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
297         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
298         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
299         ok(buf != NULL, "Expected allocated buffer\n");
300         if (buf)
301         {
302             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
303
304             ok(blob->cbData == strlen((const char*)bigUInts[i].val),
305              "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
306              blob->cbData);
307             ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
308              "Unexpected value\n");
309             LocalFree(buf);
310         }
311     }
312     /* Decode the value 1 with long-form length */
313     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
314      sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
315     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
316     if (buf)
317     {
318         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
319         LocalFree(buf);
320     }
321     /* check with extra bytes at the end */
322     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
323      sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
324     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
325     if (buf)
326     {
327         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
328         LocalFree(buf);
329     }
330     /* Try to decode some bogus large items */
331     /* The buffer size is smaller than the encoded length, so this should fail
332      * with CRYPT_E_ASN1_EOD if it's being decoded.
333      * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
334      * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
335      * So this test unfortunately isn't useful.
336     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
337      0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
338     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
339      "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
340      */
341     /* This will try to decode the buffer and overflow it, check that it's
342      * caught.
343      */
344     if (0)
345     {
346     /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
347     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
348      0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
349     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
350      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
351     }
352 }
353
354 static const BYTE bin18[] = {0x0a,0x01,0x01};
355 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
356
357 /* These are always encoded unsigned, and aren't constrained to be any
358  * particular value
359  */
360 static const struct encodedInt enums[] = {
361  { 1,    bin18 },
362  { -128, bin19 },
363 };
364
365 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
366  * X509_ENUMERATED.
367  */
368 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
369  szOID_CRL_REASON_CODE };
370
371 static void test_encodeEnumerated(DWORD dwEncoding)
372 {
373     DWORD i, j;
374
375     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
376     {
377         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
378         {
379             BOOL ret;
380             BYTE *buf = NULL;
381             DWORD bufSize = 0;
382
383             ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
384              &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
385              &bufSize);
386             ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
387             if (buf)
388             {
389                 ok(buf[0] == 0xa,
390                  "Got unexpected type %d for enumerated (expected 0xa)\n",
391                  buf[0]);
392                 ok(buf[1] == enums[j].encoded[1],
393                  "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
394                 ok(!memcmp(buf + 1, enums[j].encoded + 1,
395                  enums[j].encoded[1] + 1),
396                  "Encoded value of 0x%08x didn't match expected\n",
397                  enums[j].val);
398                 LocalFree(buf);
399             }
400         }
401     }
402 }
403
404 static void test_decodeEnumerated(DWORD dwEncoding)
405 {
406     DWORD i, j;
407
408     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
409     {
410         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
411         {
412             BOOL ret;
413             DWORD bufSize = sizeof(int);
414             int val;
415
416             ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
417              enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
418              (BYTE *)&val, &bufSize);
419             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
420             ok(bufSize == sizeof(int),
421              "Got unexpected size %d for enumerated\n", bufSize);
422             ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
423              val, enums[j].val);
424         }
425     }
426 }
427
428 struct encodedFiletime
429 {
430     SYSTEMTIME sysTime;
431     const BYTE *encodedTime;
432 };
433
434 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
435  const struct encodedFiletime *time)
436 {
437     FILETIME ft = { 0 };
438     BYTE *buf = NULL;
439     DWORD bufSize = 0;
440     BOOL ret;
441
442     ret = SystemTimeToFileTime(&time->sysTime, &ft);
443     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
444     ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft,
445      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
446     /* years other than 1950-2050 are not allowed for encodings other than
447      * X509_CHOICE_OF_TIME.
448      */
449     if (structType == X509_CHOICE_OF_TIME ||
450      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
451     {
452         ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
453          GetLastError());
454         ok(buf != NULL, "Expected an allocated buffer\n");
455         if (buf)
456         {
457             ok(buf[0] == time->encodedTime[0],
458              "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
459              buf[0]);
460             ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
461              time->encodedTime[1], bufSize);
462             ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
463              "Got unexpected value for time encoding\n");
464             LocalFree(buf);
465         }
466     }
467     else
468         ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
469          "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
470 }
471
472 static const char *printSystemTime(const SYSTEMTIME *st)
473 {
474     static char buf[25];
475
476     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
477      st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
478     return buf;
479 }
480
481 static const char *printFileTime(const FILETIME *ft)
482 {
483     static char buf[25];
484     SYSTEMTIME st;
485
486     FileTimeToSystemTime(ft, &st);
487     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
488      st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
489     return buf;
490 }
491
492 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
493 {
494     SYSTEMTIME st;
495
496     FileTimeToSystemTime(got, &st);
497     ok(expected->wYear == st.wYear &&
498      expected->wMonth == st.wMonth &&
499      expected->wDay == st.wDay &&
500      expected->wHour == st.wHour &&
501      expected->wMinute == st.wMinute &&
502      expected->wSecond == st.wSecond &&
503      abs(expected->wMilliseconds - st.wMilliseconds) <= 1,
504      "Got unexpected value for time decoding:\nexpected %s, got %s\n",
505      printSystemTime(expected), printFileTime(got));
506 }
507
508 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
509  const struct encodedFiletime *time)
510 {
511     FILETIME ft = { 0 };
512     DWORD size = sizeof(ft);
513     BOOL ret;
514
515     ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
516      time->encodedTime[1] + 2, 0, NULL, &ft, &size);
517     /* years other than 1950-2050 are not allowed for encodings other than
518      * X509_CHOICE_OF_TIME.
519      */
520     if (structType == X509_CHOICE_OF_TIME ||
521      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
522     {
523         ok(ret, "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
524          GetLastError());
525         compareTime(&time->sysTime, &ft);
526     }
527     else
528         ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
529          "Expected CRYPT_E_ASN1_BADTAG, got 0x%08x\n", GetLastError());
530 }
531
532 static const BYTE bin20[] = {
533     0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
534 static const BYTE bin21[] = {
535     0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
536 static const BYTE bin22[] = {
537     0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
538
539 static const struct encodedFiletime times[] = {
540  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
541  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
542  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
543 };
544
545 static void test_encodeFiletime(DWORD dwEncoding)
546 {
547     DWORD i;
548
549     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
550     {
551         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
552         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
553         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
554     }
555 }
556
557 static const BYTE bin23[] = {
558     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
559 static const BYTE bin24[] = {
560     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
561 static const BYTE bin25[] = {
562     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
563 static const BYTE bin26[] = {
564     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
565 static const BYTE bin27[] = {
566     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
567 static const BYTE bin28[] = {
568     0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
569 static const BYTE bin29[] = {
570     0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
571 static const BYTE bin30[] = {
572     0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
573 static const BYTE bin31[] = {
574     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
575 static const BYTE bin32[] = {
576     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
577 static const BYTE bin33[] = {
578     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
579 static const BYTE bin34[] = {
580     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
581 static const BYTE bin35[] = {
582     0x17,0x08, '4','5','0','6','0','6','1','6'};
583 static const BYTE bin36[] = {
584     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
585 static const BYTE bin37[] = {
586     0x18,0x04, '2','1','4','5'};
587 static const BYTE bin38[] = {
588     0x18,0x08, '2','1','4','5','0','6','0','6'};
589
590 static void test_decodeFiletime(DWORD dwEncoding)
591 {
592     static const struct encodedFiletime otherTimes[] = {
593      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
594      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
595      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
596      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
597      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
598      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
599      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
600      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
601      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
602      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
603      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
604      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
605     };
606     /* An oddball case that succeeds in Windows, but doesn't seem correct
607      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
608      */
609     static const unsigned char *bogusTimes[] = {
610      /* oddly, this succeeds on Windows, with year 2765
611      "\x18" "\x0f" "21r50606161000Z",
612       */
613      bin35,
614      bin36,
615      bin37,
616      bin38,
617     };
618     DWORD i, size;
619     FILETIME ft1 = { 0 }, ft2 = { 0 };
620     BOOL ret;
621
622     /* Check bogus length with non-NULL buffer */
623     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
624     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
625     size = 1;
626     ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
627      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
628     ok(!ret && GetLastError() == ERROR_MORE_DATA,
629      "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
630     /* Normal tests */
631     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
632     {
633         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
634         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
635         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
636     }
637     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
638     {
639         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
640         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
641         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
642     }
643     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
644     {
645         size = sizeof(ft1);
646         ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
647          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
648         ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
649          "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
650     }
651 }
652
653 static const char commonName[] = "Juan Lang";
654 static const char surName[] = "Lang";
655
656 static const BYTE emptySequence[] = { 0x30, 0 };
657 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
658 static const BYTE twoRDNs[] = {
659     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
660     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
661     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
662 static const BYTE encodedTwoRDNs[] = {
663 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
664 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
665 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
666 0x6e,0x67,0x00,
667 };
668
669 static const BYTE us[] = { 0x55, 0x53 };
670 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
671  0x74, 0x61 };
672 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
673  0x6f, 0x6c, 0x69, 0x73 };
674 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
675  0x76, 0x65, 0x72, 0x73 };
676 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
677  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
678 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
679  0x73, 0x74 };
680 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
681  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
682
683 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
684 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
685
686 static CHAR oid_us[]            = "2.5.4.6",
687             oid_minnesota[]     = "2.5.4.8",
688             oid_minneapolis[]   = "2.5.4.7",
689             oid_codeweavers[]   = "2.5.4.10",
690             oid_wine[]          = "2.5.4.11",
691             oid_localhostAttr[] = "2.5.4.3",
692             oid_aric[]          = "1.2.840.113549.1.9.1";
693 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
694                                     { RDNA(minnesota) },
695                                     { RDNA(minneapolis) },
696                                     { RDNA(codeweavers) },
697                                     { RDNA(wine) },
698                                     { RDNA(localhostAttr) },
699                                     { RDNIA5(aric) } };
700 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
701                                            { RDNA(localhostAttr) },
702                                            { RDNA(minnesota) },
703                                            { RDNA(minneapolis) },
704                                            { RDNA(codeweavers) },
705                                            { RDNA(wine) },
706                                            { RDNIA5(aric) } };
707
708 #undef RDNIA5
709 #undef RDNA
710
711 static const BYTE encodedRDNAttrs[] = {
712 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
713 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
714 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
715 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
716 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
717 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
718 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
719 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
720 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
721 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
722 };
723
724 static void test_encodeName(DWORD dwEncoding)
725 {
726     CERT_RDN_ATTR attrs[2];
727     CERT_RDN rdn;
728     CERT_NAME_INFO info;
729     static CHAR oid_common_name[] = szOID_COMMON_NAME,
730                 oid_sur_name[]    = szOID_SUR_NAME;
731     BYTE *buf = NULL;
732     DWORD size = 0;
733     BOOL ret;
734
735     if (0)
736     {
737         /* Test with NULL pvStructInfo (crashes on win9x) */
738         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
739          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
740         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
741          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
742     }
743     /* Test with empty CERT_NAME_INFO */
744     info.cRDN = 0;
745     info.rgRDN = NULL;
746     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
747      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
748     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
749     if (buf)
750     {
751         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
752          "Got unexpected encoding for empty name\n");
753         LocalFree(buf);
754     }
755     if (0)
756     {
757         /* Test with bogus CERT_RDN (crashes on win9x) */
758         info.cRDN = 1;
759         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
760          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
761         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
762          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
763     }
764     /* Test with empty CERT_RDN */
765     rdn.cRDNAttr = 0;
766     rdn.rgRDNAttr = NULL;
767     info.cRDN = 1;
768     info.rgRDN = &rdn;
769     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
770      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
771     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
772     if (buf)
773     {
774         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
775          "Got unexpected encoding for empty RDN array\n");
776         LocalFree(buf);
777     }
778     if (0)
779     {
780         /* Test with bogus attr array (crashes on win9x) */
781         rdn.cRDNAttr = 1;
782         rdn.rgRDNAttr = NULL;
783         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
784          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
785         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
786          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
787     }
788     /* oddly, a bogus OID is accepted by Windows XP; not testing.
789     attrs[0].pszObjId = "bogus";
790     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
791     attrs[0].Value.cbData = sizeof(commonName);
792     attrs[0].Value.pbData = (BYTE *)commonName;
793     rdn.cRDNAttr = 1;
794     rdn.rgRDNAttr = attrs;
795     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
796      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
797     ok(!ret, "Expected failure, got success\n");
798      */
799     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
800      * the encoded attributes to be swapped.
801      */
802     attrs[0].pszObjId = oid_common_name;
803     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
804     attrs[0].Value.cbData = sizeof(commonName);
805     attrs[0].Value.pbData = (BYTE *)commonName;
806     attrs[1].pszObjId = oid_sur_name;
807     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
808     attrs[1].Value.cbData = sizeof(surName);
809     attrs[1].Value.pbData = (BYTE *)surName;
810     rdn.cRDNAttr = 2;
811     rdn.rgRDNAttr = attrs;
812     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
813      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
814     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
815     if (buf)
816     {
817         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
818          "Got unexpected encoding for two RDN array\n");
819         LocalFree(buf);
820     }
821     /* A name can be "encoded" with previously encoded RDN attrs. */
822     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
823     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
824     attrs[0].Value.cbData = sizeof(twoRDNs);
825     rdn.cRDNAttr = 1;
826     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
827      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
828     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
829     if (buf)
830     {
831         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
832         ok(!memcmp(buf, encodedTwoRDNs, size),
833          "Unexpected value for re-endoded two RDN array\n");
834         LocalFree(buf);
835     }
836     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
837     rdn.cRDNAttr = 1;
838     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
839     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
840      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
841     ok(!ret && GetLastError() == E_INVALIDARG,
842      "Expected E_INVALIDARG, got %08x\n", GetLastError());
843     /* Test a more complex name */
844     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
845     rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
846     info.cRDN = 1;
847     info.rgRDN = &rdn;
848     buf = NULL;
849     size = 0;
850     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
851      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
852     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
853     if (ret)
854     {
855         ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
856         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
857         LocalFree(buf);
858     }
859 }
860
861 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
862 static WCHAR surNameW[] = { 'L','a','n','g',0 };
863
864 static const BYTE twoRDNsNoNull[] = {
865  0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
866  0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
867  0x20,0x4c,0x61,0x6e,0x67 };
868 static const BYTE anyType[] = {
869  0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
870  0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
871  0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
872  0x61,0x4c,0x67,0x6e };
873
874 static void test_encodeUnicodeName(DWORD dwEncoding)
875 {
876     CERT_RDN_ATTR attrs[2];
877     CERT_RDN rdn;
878     CERT_NAME_INFO info;
879     static CHAR oid_common_name[] = szOID_COMMON_NAME,
880                 oid_sur_name[]    = szOID_SUR_NAME;
881     BYTE *buf = NULL;
882     DWORD size = 0;
883     BOOL ret;
884
885     if (0)
886     {
887         /* Test with NULL pvStructInfo (crashes on win9x) */
888         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
889          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
890         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
891          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
892     }
893     /* Test with empty CERT_NAME_INFO */
894     info.cRDN = 0;
895     info.rgRDN = NULL;
896     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
897      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
898     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
899     if (buf)
900     {
901         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
902          "Got unexpected encoding for empty name\n");
903         LocalFree(buf);
904     }
905     /* Check with one CERT_RDN_ATTR, that has an invalid character for the
906      * encoding (the NULL).
907      */
908     attrs[0].pszObjId = oid_common_name;
909     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
910     attrs[0].Value.cbData = sizeof(commonNameW);
911     attrs[0].Value.pbData = (BYTE *)commonNameW;
912     rdn.cRDNAttr = 1;
913     rdn.rgRDNAttr = attrs;
914     info.cRDN = 1;
915     info.rgRDN = &rdn;
916     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
917      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
918     ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
919      "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
920     ok(size == 9, "Unexpected error index %08x\n", size);
921     /* Check with two NULL-terminated CERT_RDN_ATTRs.  Note DER encoding
922      * forces the order of the encoded attributes to be swapped.
923      */
924     attrs[0].pszObjId = oid_common_name;
925     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
926     attrs[0].Value.cbData = 0;
927     attrs[0].Value.pbData = (BYTE *)commonNameW;
928     attrs[1].pszObjId = oid_sur_name;
929     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
930     attrs[1].Value.cbData = 0;
931     attrs[1].Value.pbData = (BYTE *)surNameW;
932     rdn.cRDNAttr = 2;
933     rdn.rgRDNAttr = attrs;
934     info.cRDN = 1;
935     info.rgRDN = &rdn;
936     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
937      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
938     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
939     if (buf)
940     {
941         ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
942          "Got unexpected encoding for two RDN array\n");
943         LocalFree(buf);
944     }
945     /* A name can be "encoded" with previously encoded RDN attrs. */
946     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
947     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
948     attrs[0].Value.cbData = sizeof(twoRDNs);
949     rdn.cRDNAttr = 1;
950     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
951      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
952     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
953     if (buf)
954     {
955         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
956         ok(!memcmp(buf, encodedTwoRDNs, size),
957          "Unexpected value for re-endoded two RDN array\n");
958         LocalFree(buf);
959     }
960     /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
961     rdn.cRDNAttr = 1;
962     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
963     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
964      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
965     todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
966     if (buf)
967     {
968         ok(size == sizeof(anyType), "Unexpected size %d\n", size);
969         ok(!memcmp(buf, anyType, size), "Unexpected value\n");
970         LocalFree(buf);
971     }
972 }
973
974 static void compareNameValues(const CERT_NAME_VALUE *expected,
975  const CERT_NAME_VALUE *got)
976 {
977     ok(got->dwValueType == expected->dwValueType,
978      "Expected string type %d, got %d\n", expected->dwValueType,
979      got->dwValueType);
980     ok(got->Value.cbData == expected->Value.cbData,
981      "String type %d: unexpected data size, got %d, expected %d\n",
982      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
983     if (got->Value.cbData && got->Value.pbData)
984         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
985          min(got->Value.cbData, expected->Value.cbData)),
986          "String type %d: unexpected value\n", expected->dwValueType);
987 }
988
989 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
990  const CERT_RDN_ATTR *got)
991 {
992     if (expected->pszObjId && strlen(expected->pszObjId))
993     {
994         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
995          expected->pszObjId);
996         if (got->pszObjId)
997         {
998             ok(!strcmp(got->pszObjId, expected->pszObjId),
999              "Got unexpected OID %s, expected %s\n", got->pszObjId,
1000              expected->pszObjId);
1001         }
1002     }
1003     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1004      (const CERT_NAME_VALUE *)&got->dwValueType);
1005 }
1006
1007 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1008 {
1009     ok(got->cRDNAttr == expected->cRDNAttr,
1010      "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1011     if (got->cRDNAttr)
1012     {
1013         DWORD i;
1014
1015         for (i = 0; i < got->cRDNAttr; i++)
1016             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1017     }
1018 }
1019
1020 static void compareNames(const CERT_NAME_INFO *expected,
1021  const CERT_NAME_INFO *got)
1022 {
1023     ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1024      expected->cRDN, got->cRDN);
1025     if (got->cRDN)
1026     {
1027         DWORD i;
1028
1029         for (i = 0; i < got->cRDN; i++)
1030             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1031     }
1032 }
1033
1034 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1035 static const BYTE twoRDNsExtraBytes[] = {
1036     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1037     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1038     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1039
1040 static void test_decodeName(DWORD dwEncoding)
1041 {
1042     BYTE *buf = NULL;
1043     DWORD bufSize = 0;
1044     BOOL ret;
1045     CERT_RDN rdn;
1046     CERT_NAME_INFO info = { 1, &rdn };
1047
1048     /* test empty name */
1049     bufSize = 0;
1050     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1051      emptySequence[1] + 2,
1052      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1053      (BYTE *)&buf, &bufSize);
1054     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1055     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
1056      * decoder works the same way, so only test the count.
1057      */
1058     if (buf)
1059     {
1060         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1061         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1062          "Expected 0 RDNs in empty info, got %d\n",
1063          ((CERT_NAME_INFO *)buf)->cRDN);
1064         LocalFree(buf);
1065     }
1066     /* test empty name with indefinite-length encoding */
1067     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1068      sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1069      (BYTE *)&buf, &bufSize);
1070     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1071     if (ret)
1072     {
1073         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1074         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1075          "Expected 0 RDNs in empty info, got %d\n",
1076          ((CERT_NAME_INFO *)buf)->cRDN);
1077         LocalFree(buf);
1078     }
1079     /* test empty RDN */
1080     bufSize = 0;
1081     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1082      emptyRDNs[1] + 2,
1083      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1084      (BYTE *)&buf, &bufSize);
1085     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1086     if (buf)
1087     {
1088         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1089
1090         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1091          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1092          "Got unexpected value for empty RDN\n");
1093         LocalFree(buf);
1094     }
1095     /* test two RDN attrs */
1096     bufSize = 0;
1097     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1098      twoRDNs[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         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1105                     oid_common_name[] = szOID_COMMON_NAME;
1106
1107         CERT_RDN_ATTR attrs[] = {
1108          { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1109           (BYTE *)surName } },
1110          { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1111           (BYTE *)commonName } },
1112         };
1113
1114         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1115         rdn.rgRDNAttr = attrs;
1116         compareNames(&info, (CERT_NAME_INFO *)buf);
1117         LocalFree(buf);
1118     }
1119     /* test that two RDN attrs with extra bytes succeeds */
1120     bufSize = 0;
1121     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1122      sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1123     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1124     /* And, a slightly more complicated name */
1125     buf = NULL;
1126     bufSize = 0;
1127     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1128      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1129     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1130     if (ret)
1131     {
1132         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1133         rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
1134         compareNames(&info, (CERT_NAME_INFO *)buf);
1135         LocalFree(buf);
1136     }
1137 }
1138
1139 static void test_decodeUnicodeName(DWORD dwEncoding)
1140 {
1141     BYTE *buf = NULL;
1142     DWORD bufSize = 0;
1143     BOOL ret;
1144     CERT_RDN rdn;
1145     CERT_NAME_INFO info = { 1, &rdn };
1146
1147     /* test empty name */
1148     bufSize = 0;
1149     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1150      emptySequence[1] + 2,
1151      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1152      (BYTE *)&buf, &bufSize);
1153     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1154     if (buf)
1155     {
1156         ok(bufSize == sizeof(CERT_NAME_INFO),
1157          "Got wrong bufSize %d\n", bufSize);
1158         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1159          "Expected 0 RDNs in empty info, got %d\n",
1160          ((CERT_NAME_INFO *)buf)->cRDN);
1161         LocalFree(buf);
1162     }
1163     /* test empty RDN */
1164     bufSize = 0;
1165     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1166      emptyRDNs[1] + 2,
1167      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1168      (BYTE *)&buf, &bufSize);
1169     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1170     if (buf)
1171     {
1172         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1173
1174         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1175          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1176          "Got unexpected value for empty RDN\n");
1177         LocalFree(buf);
1178     }
1179     /* test two RDN attrs */
1180     bufSize = 0;
1181     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1182      sizeof(twoRDNsNoNull),
1183      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1184      (BYTE *)&buf, &bufSize);
1185     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1186     if (buf)
1187     {
1188         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1189                     oid_common_name[] = szOID_COMMON_NAME;
1190
1191         CERT_RDN_ATTR attrs[] = {
1192          { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1193          { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1194          { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1195          { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1196         };
1197
1198         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1199         rdn.rgRDNAttr = attrs;
1200         compareNames(&info, (CERT_NAME_INFO *)buf);
1201         LocalFree(buf);
1202     }
1203 }
1204
1205 struct EncodedNameValue
1206 {
1207     CERT_NAME_VALUE value;
1208     const BYTE *encoded;
1209     DWORD encodedSize;
1210 };
1211
1212 static const char bogusIA5[] = "\x80";
1213 static const char bogusPrintable[] = "~";
1214 static const char bogusNumeric[] = "A";
1215 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1216 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1217 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1218 static BYTE octetCommonNameValue[] = {
1219  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1220 static BYTE numericCommonNameValue[] = {
1221  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1222 static BYTE printableCommonNameValue[] = {
1223  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1224 static BYTE t61CommonNameValue[] = {
1225  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1226 static BYTE videotexCommonNameValue[] = {
1227  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1228 static BYTE ia5CommonNameValue[] = {
1229  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1230 static BYTE graphicCommonNameValue[] = {
1231  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1232 static BYTE visibleCommonNameValue[] = {
1233  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1234 static BYTE generalCommonNameValue[] = {
1235  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1236 static BYTE bmpCommonNameValue[] = {
1237  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1238  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1239 static BYTE utf8CommonNameValue[] = {
1240  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1241
1242 static struct EncodedNameValue nameValues[] = {
1243  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1244      octetCommonNameValue, sizeof(octetCommonNameValue) },
1245  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1246      numericCommonNameValue, sizeof(numericCommonNameValue) },
1247  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1248      printableCommonNameValue, sizeof(printableCommonNameValue) },
1249  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1250      t61CommonNameValue, sizeof(t61CommonNameValue) },
1251  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1252      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1253  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1254      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1255  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1256      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1257  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1258      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1259  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1260      generalCommonNameValue, sizeof(generalCommonNameValue) },
1261  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1262      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1263  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1264      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1265  /* The following tests succeed under Windows, but really should fail,
1266   * they contain characters that are illegal for the encoding.  I'm
1267   * including them to justify my lazy encoding.
1268   */
1269  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1270      sizeof(bin42) },
1271  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1272      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1273  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1274      bin44, sizeof(bin44) },
1275 };
1276
1277 static void test_encodeNameValue(DWORD dwEncoding)
1278 {
1279     BYTE *buf = NULL;
1280     DWORD size = 0, i;
1281     BOOL ret;
1282     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1283
1284     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1285     value.Value.pbData = printableCommonNameValue;
1286     value.Value.cbData = sizeof(printableCommonNameValue);
1287     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1288      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1289     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1290     if (buf)
1291     {
1292         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1293          size);
1294         ok(!memcmp(buf, printableCommonNameValue, size),
1295          "Unexpected encoding\n");
1296         LocalFree(buf);
1297     }
1298     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1299     {
1300         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1301          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1302          &size);
1303         ok(ret, "Type %d: CryptEncodeObjectEx failed: %08x\n",
1304          nameValues[i].value.dwValueType, GetLastError());
1305         if (buf)
1306         {
1307             ok(size == nameValues[i].encodedSize,
1308              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1309             ok(!memcmp(buf, nameValues[i].encoded, size),
1310              "Got unexpected encoding\n");
1311             LocalFree(buf);
1312         }
1313     }
1314 }
1315
1316 static void test_decodeNameValue(DWORD dwEncoding)
1317 {
1318     int i;
1319     BYTE *buf = NULL;
1320     DWORD bufSize = 0;
1321     BOOL ret;
1322
1323     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1324     {
1325         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1326          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1327          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1328          (BYTE *)&buf, &bufSize);
1329         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1330          nameValues[i].value.dwValueType, GetLastError());
1331         if (buf)
1332         {
1333             compareNameValues(&nameValues[i].value,
1334              (const CERT_NAME_VALUE *)buf);
1335             LocalFree(buf);
1336         }
1337     }
1338 }
1339
1340 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1341 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1342 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1343  'h','q','.','o','r','g',0 };
1344 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1345  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1346  0x6f, 0x72, 0x67 };
1347 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1348  0x575b, 0 };
1349 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1350 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1351  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1352 static const BYTE localhost[] = { 127, 0, 0, 1 };
1353 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1354  0x01 };
1355 static const unsigned char encodedCommonName[] = {
1356     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1357 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1358 static const BYTE encodedDirectoryName[] = {
1359 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1360 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1361
1362 static void test_encodeAltName(DWORD dwEncoding)
1363 {
1364     CERT_ALT_NAME_INFO info = { 0 };
1365     CERT_ALT_NAME_ENTRY entry = { 0 };
1366     BYTE *buf = NULL;
1367     DWORD size = 0;
1368     BOOL ret;
1369     char oid[] = "1.2.3";
1370
1371     /* Test with empty info */
1372     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1373      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1374     if (buf)
1375     {
1376         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1377         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1378         LocalFree(buf);
1379     }
1380     /* Test with an empty entry */
1381     info.cAltEntry = 1;
1382     info.rgAltEntry = &entry;
1383     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1384      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1385     ok(!ret && GetLastError() == E_INVALIDARG,
1386      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1387     /* Test with an empty pointer */
1388     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1389     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1390      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1391     if (buf)
1392     {
1393         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1394         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1395         LocalFree(buf);
1396     }
1397     /* Test with a real URL */
1398     U(entry).pwszURL = (LPWSTR)url;
1399     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1400      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1401     if (buf)
1402     {
1403         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1404         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1405         LocalFree(buf);
1406     }
1407     /* Now with the URL containing an invalid IA5 char */
1408     U(entry).pwszURL = (LPWSTR)nihongoURL;
1409     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1410      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1411     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1412      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1413     /* The first invalid character is at index 7 */
1414     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1415      "Expected invalid char at index 7, got %d\n",
1416      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1417     /* Now with the URL missing a scheme */
1418     U(entry).pwszURL = (LPWSTR)dnsName;
1419     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1420      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1421     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1422     if (buf)
1423     {
1424         /* This succeeds, but it shouldn't, so don't worry about conforming */
1425         LocalFree(buf);
1426     }
1427     /* Now with a DNS name */
1428     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1429     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1430      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1431     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1432     if (buf)
1433     {
1434         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1435         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1436         LocalFree(buf);
1437     }
1438     /* Test with an IP address */
1439     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1440     U(entry).IPAddress.cbData = sizeof(localhost);
1441     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1442     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1443      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1444     if (buf)
1445     {
1446         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1447         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1448         LocalFree(buf);
1449     }
1450     /* Test with OID */
1451     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1452     U(entry).pszRegisteredID = oid;
1453     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1454      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1455     if (buf)
1456     {
1457         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1458         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1459         LocalFree(buf);
1460     }
1461     /* Test with directory name */
1462     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1463     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1464     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1465     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1466      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1467     if (buf)
1468     {
1469         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1470         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1471         LocalFree(buf);
1472     }
1473 }
1474
1475 static void test_decodeAltName(DWORD dwEncoding)
1476 {
1477     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1478      0x00, 0x00, 0x01 };
1479     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1480      0x01 };
1481     BOOL ret;
1482     BYTE *buf = NULL;
1483     DWORD bufSize = 0;
1484     CERT_ALT_NAME_INFO *info;
1485
1486     /* Test some bogus ones first */
1487     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1488      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1489      NULL, (BYTE *)&buf, &bufSize);
1490     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1491      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1492     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1493      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1494      &bufSize);
1495     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1496      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
1497     /* Now expected cases */
1498     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1499      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1500      &bufSize);
1501     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1502     if (buf)
1503     {
1504         info = (CERT_ALT_NAME_INFO *)buf;
1505
1506         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1507          info->cAltEntry);
1508         LocalFree(buf);
1509     }
1510     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1511      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1512      &bufSize);
1513     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1514     if (buf)
1515     {
1516         info = (CERT_ALT_NAME_INFO *)buf;
1517
1518         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1519          info->cAltEntry);
1520         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1521          "Expected CERT_ALT_NAME_URL, got %d\n",
1522          info->rgAltEntry[0].dwAltNameChoice);
1523         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1524          "Expected empty URL\n");
1525         LocalFree(buf);
1526     }
1527     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1528      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1529     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1530     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1531      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1532      &bufSize);
1533     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1534     if (buf)
1535     {
1536         info = (CERT_ALT_NAME_INFO *)buf;
1537
1538         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1539          info->cAltEntry);
1540         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1541          "Expected CERT_ALT_NAME_URL, got %d\n",
1542          info->rgAltEntry[0].dwAltNameChoice);
1543         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1544         LocalFree(buf);
1545     }
1546     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1547      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1548      &bufSize);
1549     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1550     if (buf)
1551     {
1552         info = (CERT_ALT_NAME_INFO *)buf;
1553
1554         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1555          info->cAltEntry);
1556         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1557          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1558          info->rgAltEntry[0].dwAltNameChoice);
1559         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1560          "Unexpected DNS name\n");
1561         LocalFree(buf);
1562     }
1563     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1564      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1565      &bufSize);
1566     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1567     if (buf)
1568     {
1569         info = (CERT_ALT_NAME_INFO *)buf;
1570
1571         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1572          info->cAltEntry);
1573         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1574          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1575          info->rgAltEntry[0].dwAltNameChoice);
1576         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1577          "Unexpected IP address length %d\n",
1578           U(info->rgAltEntry[0]).IPAddress.cbData);
1579         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1580          sizeof(localhost)), "Unexpected IP address value\n");
1581         LocalFree(buf);
1582     }
1583     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1584      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1585      &bufSize);
1586     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1587     if (buf)
1588     {
1589         info = (CERT_ALT_NAME_INFO *)buf;
1590
1591         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1592          info->cAltEntry);
1593         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1594          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1595          info->rgAltEntry[0].dwAltNameChoice);
1596         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1597            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1598         LocalFree(buf);
1599     }
1600     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1601      encodedDirectoryName, sizeof(encodedDirectoryName),
1602      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1603     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1604     if (buf)
1605     {
1606         info = (CERT_ALT_NAME_INFO *)buf;
1607
1608         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1609          info->cAltEntry);
1610         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1611          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1612          info->rgAltEntry[0].dwAltNameChoice);
1613         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1614          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1615           U(info->rgAltEntry[0]).DirectoryName.cbData);
1616         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1617          encodedCommonName, sizeof(encodedCommonName)),
1618          "Unexpected directory name value\n");
1619         LocalFree(buf);
1620     }
1621 }
1622
1623 struct UnicodeExpectedError
1624 {
1625     DWORD   valueType;
1626     LPCWSTR str;
1627     DWORD   errorIndex;
1628     DWORD   error;
1629 };
1630
1631 static const WCHAR oneW[] = { '1',0 };
1632 static const WCHAR aW[] = { 'a',0 };
1633 static const WCHAR quoteW[] = { '"', 0 };
1634
1635 static struct UnicodeExpectedError unicodeErrors[] = {
1636  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1637  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1638  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1639  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1640  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1641  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1642 };
1643
1644 struct UnicodeExpectedResult
1645 {
1646     DWORD           valueType;
1647     LPCWSTR         str;
1648     CRYPT_DATA_BLOB encoded;
1649 };
1650
1651 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1652 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1653 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1654 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1655 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1656 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1657 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1658 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1659 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1660 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1661 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1662 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1663  0x5b };
1664 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1665  0x6f,0x5b };
1666 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1667  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1668 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1669  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1670
1671 static struct UnicodeExpectedResult unicodeResults[] = {
1672  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1673  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1674  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1675  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1676  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1677  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1678  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1679  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1680  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1681  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1682  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1683  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1684  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1685 };
1686
1687 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1688  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1689  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1690 };
1691
1692 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1693 {
1694     BYTE *buf = NULL;
1695     DWORD size = 0, i;
1696     BOOL ret;
1697     CERT_NAME_VALUE value;
1698
1699     if (0)
1700     {
1701         /* Crashes on win9x */
1702         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1703          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1704         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1705          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1706     }
1707     /* Have to have a string of some sort */
1708     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1709     value.Value.pbData = NULL;
1710     value.Value.cbData = 0;
1711     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1712      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1713     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1714      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1715     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1716     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1717      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1718     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1719      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1720     value.dwValueType = CERT_RDN_ANY_TYPE;
1721     value.Value.pbData = (LPBYTE)oneW;
1722     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1723      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1724     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1725      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1726     value.Value.cbData = sizeof(oneW);
1727     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1728      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1729     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1730      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1731     /* An encoded string with specified length isn't good enough either */
1732     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1733     value.Value.pbData = oneUniversal;
1734     value.Value.cbData = sizeof(oneUniversal);
1735     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1736      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1737     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1738      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1739     /* More failure checking */
1740     value.Value.cbData = 0;
1741     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1742     {
1743         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1744         value.dwValueType = unicodeErrors[i].valueType;
1745         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1746          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1747         ok(!ret && GetLastError() == unicodeErrors[i].error,
1748          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1749          unicodeErrors[i].error, GetLastError());
1750         ok(size == unicodeErrors[i].errorIndex,
1751          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1752          size);
1753     }
1754     /* cbData can be zero if the string is NULL-terminated */
1755     value.Value.cbData = 0;
1756     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1757     {
1758         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1759         value.dwValueType = unicodeResults[i].valueType;
1760         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1761          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1762         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1763         if (buf)
1764         {
1765             ok(size == unicodeResults[i].encoded.cbData,
1766              "Value type %d: expected size %d, got %d\n",
1767              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1768             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1769              "Value type %d: unexpected value\n", value.dwValueType);
1770             LocalFree(buf);
1771         }
1772     }
1773     /* These "encode," but they do so by truncating each unicode character
1774      * rather than properly encoding it.  Kept separate from the proper results,
1775      * because the encoded forms won't decode to their original strings.
1776      */
1777     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1778     {
1779         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1780         value.dwValueType = unicodeWeirdness[i].valueType;
1781         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1782          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1783         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1784         if (buf)
1785         {
1786             ok(size == unicodeWeirdness[i].encoded.cbData,
1787              "Value type %d: expected size %d, got %d\n",
1788              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1789             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1790              "Value type %d: unexpected value\n", value.dwValueType);
1791             LocalFree(buf);
1792         }
1793     }
1794 }
1795
1796 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1797 {
1798     if (n <= 0) return 0;
1799     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1800     return *str1 - *str2;
1801 }
1802
1803 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1804 {
1805     DWORD i;
1806
1807     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1808     {
1809         BYTE *buf = NULL;
1810         BOOL ret;
1811         DWORD size = 0;
1812
1813         ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1814          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1815          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1816         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1817         if (ret && buf)
1818         {
1819             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1820
1821             ok(value->dwValueType == unicodeResults[i].valueType,
1822              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1823              value->dwValueType);
1824             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1825              value->Value.cbData / sizeof(WCHAR)),
1826              "Unexpected decoded value for index %d (value type %d)\n", i,
1827              unicodeResults[i].valueType);
1828             LocalFree(buf);
1829         }
1830     }
1831 }
1832
1833 struct encodedOctets
1834 {
1835     const BYTE *val;
1836     const BYTE *encoded;
1837 };
1838
1839 static const unsigned char bin46[] = { 'h','i',0 };
1840 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1841 static const unsigned char bin48[] = {
1842      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1843 static const unsigned char bin49[] = {
1844      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1845 static const unsigned char bin50[] = { 0 };
1846 static const unsigned char bin51[] = { 0x04,0x00,0 };
1847
1848 static const struct encodedOctets octets[] = {
1849     { bin46, bin47 },
1850     { bin48, bin49 },
1851     { bin50, bin51 },
1852 };
1853
1854 static void test_encodeOctets(DWORD dwEncoding)
1855 {
1856     CRYPT_DATA_BLOB blob;
1857     DWORD i;
1858
1859     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1860     {
1861         BYTE *buf = NULL;
1862         BOOL ret;
1863         DWORD bufSize = 0;
1864
1865         blob.cbData = strlen((const char*)octets[i].val);
1866         blob.pbData = (BYTE*)octets[i].val;
1867         ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1868          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1869         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1870         if (buf)
1871         {
1872             ok(buf[0] == 4,
1873              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1874             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1875              buf[1], octets[i].encoded[1]);
1876             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1877              octets[i].encoded[1] + 1), "Got unexpected value\n");
1878             LocalFree(buf);
1879         }
1880     }
1881 }
1882
1883 static void test_decodeOctets(DWORD dwEncoding)
1884 {
1885     DWORD i;
1886
1887     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1888     {
1889         BYTE *buf = NULL;
1890         BOOL ret;
1891         DWORD bufSize = 0;
1892
1893         ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1894          (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1895          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1896         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1897         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1898          "Expected size >= %d, got %d\n",
1899            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1900         ok(buf != NULL, "Expected allocated buffer\n");
1901         if (buf)
1902         {
1903             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1904
1905             if (blob->cbData)
1906                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1907                  "Unexpected value\n");
1908             LocalFree(buf);
1909         }
1910     }
1911 }
1912
1913 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1914
1915 struct encodedBits
1916 {
1917     DWORD cUnusedBits;
1918     const BYTE *encoded;
1919     DWORD cbDecoded;
1920     const BYTE *decoded;
1921 };
1922
1923 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1924 static const unsigned char bin53[] = { 0xff,0xff };
1925 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1926 static const unsigned char bin55[] = { 0xff,0xfe };
1927 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1928 static const unsigned char bin57[] = { 0xfe };
1929 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1930
1931 static const struct encodedBits bits[] = {
1932     /* normal test cases */
1933     { 0, bin52, 2, bin53 },
1934     { 1, bin54, 2, bin55 },
1935     /* strange test case, showing cUnusedBits >= 8 is allowed */
1936     { 9, bin56, 1, bin57 },
1937     /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1938     { 17, bin58, 0, NULL },
1939 };
1940
1941 static void test_encodeBits(DWORD dwEncoding)
1942 {
1943     DWORD i;
1944
1945     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1946     {
1947         CRYPT_BIT_BLOB blob;
1948         BOOL ret;
1949         BYTE *buf = NULL;
1950         DWORD bufSize = 0;
1951
1952         blob.cbData = sizeof(bytesToEncode);
1953         blob.pbData = (BYTE *)bytesToEncode;
1954         blob.cUnusedBits = bits[i].cUnusedBits;
1955         ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1956          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1957         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1958         if (buf)
1959         {
1960             ok(bufSize == bits[i].encoded[1] + 2,
1961              "Got unexpected size %d, expected %d\n", bufSize,
1962              bits[i].encoded[1] + 2);
1963             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1964              "Unexpected value\n");
1965             LocalFree(buf);
1966         }
1967     }
1968 }
1969
1970 static void test_decodeBits(DWORD dwEncoding)
1971 {
1972     static const BYTE ber[] = "\x03\x02\x01\xff";
1973     static const BYTE berDecoded = 0xfe;
1974     DWORD i;
1975     BOOL ret;
1976     BYTE *buf = NULL;
1977     DWORD bufSize = 0;
1978
1979     /* normal cases */
1980     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1981     {
1982         ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1983          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1984          &bufSize);
1985         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1986         if (buf)
1987         {
1988             CRYPT_BIT_BLOB *blob;
1989
1990             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1991                "Got unexpected size %d\n", bufSize);
1992             blob = (CRYPT_BIT_BLOB *)buf;
1993             ok(blob->cbData == bits[i].cbDecoded,
1994              "Got unexpected length %d, expected %d\n", blob->cbData,
1995              bits[i].cbDecoded);
1996             if (blob->cbData && bits[i].cbDecoded)
1997                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1998                  "Unexpected value\n");
1999             LocalFree(buf);
2000         }
2001     }
2002     /* special case: check that something that's valid in BER but not in DER
2003      * decodes successfully
2004      */
2005     ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2006      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2007     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2008     if (buf)
2009     {
2010         CRYPT_BIT_BLOB *blob;
2011
2012         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2013            "Got unexpected size %d\n", bufSize);
2014         blob = (CRYPT_BIT_BLOB *)buf;
2015         ok(blob->cbData == sizeof(berDecoded),
2016            "Got unexpected length %d\n", blob->cbData);
2017         if (blob->cbData)
2018             ok(*blob->pbData == berDecoded, "Unexpected value\n");
2019         LocalFree(buf);
2020     }
2021 }
2022
2023 struct Constraints2
2024 {
2025     CERT_BASIC_CONSTRAINTS2_INFO info;
2026     const BYTE *encoded;
2027 };
2028
2029 static const unsigned char bin59[] = { 0x30,0x00 };
2030 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2031 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2032 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2033 static const struct Constraints2 constraints2[] = {
2034  /* empty constraints */
2035  { { FALSE, FALSE, 0}, bin59 },
2036  /* can be a CA */
2037  { { TRUE,  FALSE, 0}, bin60 },
2038  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2039   * but that's not the case
2040   */
2041  { { FALSE, TRUE,  0}, bin61 },
2042  /* can be a CA and has path length constraints set */
2043  { { TRUE,  TRUE,  1}, bin62 },
2044 };
2045
2046 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2047 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2048  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2049  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2050  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2051 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2052  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2053  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2054  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2055  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2056
2057 static void test_encodeBasicConstraints(DWORD dwEncoding)
2058 {
2059     DWORD i, bufSize = 0;
2060     CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2061     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2062      (LPBYTE)encodedDomainName };
2063     BOOL ret;
2064     BYTE *buf = NULL;
2065
2066     /* First test with the simpler info2 */
2067     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2068     {
2069         ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2070          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2071          &bufSize);
2072         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2073         if (buf)
2074         {
2075             ok(bufSize == constraints2[i].encoded[1] + 2,
2076              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2077              bufSize);
2078             ok(!memcmp(buf, constraints2[i].encoded,
2079              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2080             LocalFree(buf);
2081         }
2082     }
2083     /* Now test with more complex basic constraints */
2084     info.SubjectType.cbData = 0;
2085     info.fPathLenConstraint = FALSE;
2086     info.cSubtreesConstraint = 0;
2087     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2088      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2089     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2090     if (buf)
2091     {
2092         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2093         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2094          "Unexpected value\n");
2095         LocalFree(buf);
2096     }
2097     /* None of the certs I examined had any subtree constraint, but I test one
2098      * anyway just in case.
2099      */
2100     info.cSubtreesConstraint = 1;
2101     info.rgSubtreesConstraint = &nameBlob;
2102     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2103      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2104     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2105     if (buf)
2106     {
2107         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2108         ok(!memcmp(buf, constraintWithDomainName,
2109          sizeof(constraintWithDomainName)), "Unexpected value\n");
2110         LocalFree(buf);
2111     }
2112     /* FIXME: test encoding with subject type. */
2113 }
2114
2115 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2116
2117 static void test_decodeBasicConstraints(DWORD dwEncoding)
2118 {
2119     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2120      0xff };
2121     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2122     DWORD i;
2123     BOOL ret;
2124     BYTE *buf = NULL;
2125     DWORD bufSize = 0;
2126
2127     /* First test with simpler info2 */
2128     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2129     {
2130         ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2131          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2132          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2133         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2134          GetLastError());
2135         if (buf)
2136         {
2137             CERT_BASIC_CONSTRAINTS2_INFO *info =
2138              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2139
2140             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2141              "Unexpected value for item %d\n", i);
2142             LocalFree(buf);
2143         }
2144     }
2145     /* Check with the order of encoded elements inverted */
2146     buf = (PBYTE)1;
2147     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2148      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2149      &bufSize);
2150     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2151      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2152     ok(!buf, "Expected buf to be set to NULL\n");
2153     /* Check with a non-DER bool */
2154     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2155      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2156      (BYTE *)&buf, &bufSize);
2157     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2158     if (buf)
2159     {
2160         CERT_BASIC_CONSTRAINTS2_INFO *info =
2161          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2162
2163         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2164         LocalFree(buf);
2165     }
2166     /* Check with a non-basic constraints value */
2167     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2168      (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
2169      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2170     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2171      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2172     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2173     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2174      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2175      (BYTE *)&buf, &bufSize);
2176     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2177     if (buf)
2178     {
2179         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2180
2181         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2182         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2183         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2184         LocalFree(buf);
2185     }
2186     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2187      constraintWithDomainName, sizeof(constraintWithDomainName),
2188      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2189     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2190     if (buf)
2191     {
2192         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2193
2194         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2195         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2196         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2197         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2198         {
2199             ok(info->rgSubtreesConstraint[0].cbData ==
2200              sizeof(encodedDomainName), "Wrong size %d\n",
2201              info->rgSubtreesConstraint[0].cbData);
2202             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2203              sizeof(encodedDomainName)), "Unexpected value\n");
2204         }
2205         LocalFree(buf);
2206     }
2207 }
2208
2209 /* These are terrible public keys of course, I'm just testing encoding */
2210 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2211 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2212 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2213 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2214 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2215 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2216 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2217 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2218
2219 struct EncodedRSAPubKey
2220 {
2221     const BYTE *modulus;
2222     size_t modulusLen;
2223     const BYTE *encoded;
2224     size_t decodedModulusLen;
2225 };
2226
2227 struct EncodedRSAPubKey rsaPubKeys[] = {
2228     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2229     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2230     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2231     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2232 };
2233
2234 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2235 {
2236     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2237     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2238     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2239     BOOL ret;
2240     BYTE *buf = NULL;
2241     DWORD bufSize = 0, i;
2242
2243     /* Try with a bogus blob type */
2244     hdr->bType = 2;
2245     hdr->bVersion = CUR_BLOB_VERSION;
2246     hdr->reserved = 0;
2247     hdr->aiKeyAlg = CALG_RSA_KEYX;
2248     rsaPubKey->magic = 0x31415352;
2249     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2250     rsaPubKey->pubexp = 65537;
2251     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2252      sizeof(modulus1));
2253
2254     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2255      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2256      &bufSize);
2257     ok(!ret && GetLastError() == E_INVALIDARG,
2258      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2259     /* Now with a bogus reserved field */
2260     hdr->bType = PUBLICKEYBLOB;
2261     hdr->reserved = 1;
2262     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2263      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2264      &bufSize);
2265     if (buf)
2266     {
2267         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2268          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2269         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2270         LocalFree(buf);
2271     }
2272     /* Now with a bogus blob version */
2273     hdr->reserved = 0;
2274     hdr->bVersion = 0;
2275     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2276      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2277      &bufSize);
2278     if (buf)
2279     {
2280         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2281          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2282         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2283         LocalFree(buf);
2284     }
2285     /* And with a bogus alg ID */
2286     hdr->bVersion = CUR_BLOB_VERSION;
2287     hdr->aiKeyAlg = CALG_DES;
2288     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2289      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2290      &bufSize);
2291     if (buf)
2292     {
2293         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2294          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2295         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2296         LocalFree(buf);
2297     }
2298     /* Check a couple of RSA-related OIDs */
2299     hdr->aiKeyAlg = CALG_RSA_KEYX;
2300     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2301      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2302     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2303      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2304     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2305      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2306     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2307      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2308     /* Finally, all valid */
2309     hdr->aiKeyAlg = CALG_RSA_KEYX;
2310     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2311     {
2312         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2313          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2314         ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2315          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2316         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2317         if (buf)
2318         {
2319             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2320              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2321              bufSize);
2322             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2323              "Unexpected value\n");
2324             LocalFree(buf);
2325         }
2326     }
2327 }
2328
2329 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2330 {
2331     DWORD i;
2332     LPBYTE buf = NULL;
2333     DWORD bufSize = 0;
2334     BOOL ret;
2335
2336     /* Try with a bad length */
2337     ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2338      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2339      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2340     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2341      "Expected CRYPT_E_ASN1_EOD, got %08x\n", CRYPT_E_ASN1_EOD);
2342     /* Try with a couple of RSA-related OIDs */
2343     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2344      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2345      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2346     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2347      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2348     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2349      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2350      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2351     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2352      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2353     /* Now try success cases */
2354     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2355     {
2356         bufSize = 0;
2357         ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2358          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2359          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2360         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2361         if (buf)
2362         {
2363             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2364             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2365
2366             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2367              rsaPubKeys[i].decodedModulusLen,
2368              "Wrong size %d\n", bufSize);
2369             ok(hdr->bType == PUBLICKEYBLOB,
2370              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2371              hdr->bType);
2372             ok(hdr->bVersion == CUR_BLOB_VERSION,
2373              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2374              CUR_BLOB_VERSION, hdr->bVersion);
2375             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2376              hdr->reserved);
2377             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2378              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2379             ok(rsaPubKey->magic == 0x31415352,
2380              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2381             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2382              "Wrong bit len %d\n", rsaPubKey->bitlen);
2383             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2384              rsaPubKey->pubexp);
2385             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2386              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2387              "Unexpected modulus\n");
2388             LocalFree(buf);
2389         }
2390     }
2391 }
2392
2393 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2394  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2395  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2396
2397 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2398  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2399  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2400  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2401
2402 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2403 {
2404     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2405     CRYPT_SEQUENCE_OF_ANY seq;
2406     DWORD i;
2407     BOOL ret;
2408     BYTE *buf = NULL;
2409     DWORD bufSize = 0;
2410
2411     /* Encode a homogeneous sequence */
2412     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2413     {
2414         blobs[i].cbData = ints[i].encoded[1] + 2;
2415         blobs[i].pbData = (BYTE *)ints[i].encoded;
2416     }
2417     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2418     seq.rgValue = blobs;
2419
2420     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2421      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2422     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2423     if (buf)
2424     {
2425         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2426         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2427         LocalFree(buf);
2428     }
2429     /* Change the type of the first element in the sequence, and give it
2430      * another go
2431      */
2432     blobs[0].cbData = times[0].encodedTime[1] + 2;
2433     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2434     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2435      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2436     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2437     if (buf)
2438     {
2439         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2440         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2441          "Unexpected value\n");
2442         LocalFree(buf);
2443     }
2444 }
2445
2446 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2447 {
2448     BOOL ret;
2449     BYTE *buf = NULL;
2450     DWORD bufSize = 0;
2451
2452     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2453      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2454     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2455     if (buf)
2456     {
2457         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2458         DWORD i;
2459
2460         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2461          "Wrong elements %d\n", seq->cValue);
2462         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2463         {
2464             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2465              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2466              seq->rgValue[i].cbData);
2467             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2468              ints[i].encoded[1] + 2), "Unexpected value\n");
2469         }
2470         LocalFree(buf);
2471     }
2472     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2473      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2474      &bufSize);
2475     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2476     if (buf)
2477     {
2478         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2479
2480         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2481          "Wrong elements %d\n", seq->cValue);
2482         /* Just check the first element since it's all that changed */
2483         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2484          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2485          seq->rgValue[0].cbData);
2486         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2487          times[0].encodedTime[1] + 2), "Unexpected value\n");
2488         LocalFree(buf);
2489     }
2490 }
2491
2492 struct encodedExtensions
2493 {
2494     CERT_EXTENSIONS exts;
2495     const BYTE *encoded;
2496 };
2497
2498 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2499 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2500 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2501 static CERT_EXTENSION criticalExt =
2502  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2503 static CERT_EXTENSION nonCriticalExt =
2504  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2505
2506 static const BYTE ext0[] = { 0x30,0x00 };
2507 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2508                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2509 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2510                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2511
2512 static const struct encodedExtensions exts[] = {
2513  { { 0, NULL }, ext0 },
2514  { { 1, &criticalExt }, ext1 },
2515  { { 1, &nonCriticalExt }, ext2 },
2516 };
2517
2518 static void test_encodeExtensions(DWORD dwEncoding)
2519 {
2520     DWORD i;
2521
2522     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2523     {
2524         BOOL ret;
2525         BYTE *buf = NULL;
2526         DWORD bufSize = 0;
2527
2528         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2529          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2530         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2531         if (buf)
2532         {
2533             ok(bufSize == exts[i].encoded[1] + 2,
2534              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2535             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2536              "Unexpected value\n");
2537             LocalFree(buf);
2538         }
2539     }
2540 }
2541
2542 static void test_decodeExtensions(DWORD dwEncoding)
2543 {
2544     DWORD i;
2545
2546     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2547     {
2548         BOOL ret;
2549         BYTE *buf = NULL;
2550         DWORD bufSize = 0;
2551
2552         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2553          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2554          NULL, (BYTE *)&buf, &bufSize);
2555         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2556         if (buf)
2557         {
2558             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2559             DWORD j;
2560
2561             ok(ext->cExtension == exts[i].exts.cExtension,
2562              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2563              ext->cExtension);
2564             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2565             {
2566                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2567                  exts[i].exts.rgExtension[j].pszObjId),
2568                  "Expected OID %s, got %s\n",
2569                  exts[i].exts.rgExtension[j].pszObjId,
2570                  ext->rgExtension[j].pszObjId);
2571                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2572                  exts[i].exts.rgExtension[j].Value.pbData,
2573                  exts[i].exts.rgExtension[j].Value.cbData),
2574                  "Unexpected value\n");
2575             }
2576             LocalFree(buf);
2577         }
2578     }
2579 }
2580
2581 /* MS encodes public key info with a NULL if the algorithm identifier's
2582  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2583  * it encodes them by omitting the algorithm parameters.  This latter approach
2584  * seems more correct, so accept either form.
2585  */
2586 struct encodedPublicKey
2587 {
2588     CERT_PUBLIC_KEY_INFO info;
2589     const BYTE *encoded;
2590     const BYTE *encodedNoNull;
2591     CERT_PUBLIC_KEY_INFO decoded;
2592 };
2593
2594 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2595  0xe, 0xf };
2596 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2597
2598 static const unsigned char bin64[] = {
2599     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2600 static const unsigned char bin65[] = {
2601     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2602 static const unsigned char bin66[] = {
2603     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2604 static const unsigned char bin67[] = {
2605     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2606 static const unsigned char bin68[] = {
2607     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2608     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2609 static const unsigned char bin69[] = {
2610     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2611     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2612 static const unsigned char bin70[] = {
2613     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2614     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2615     0x0f};
2616 static const unsigned char bin71[] = {
2617     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2618     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2619     0x0f};
2620 static unsigned char bin72[] = { 0x05,0x00};
2621
2622 static CHAR oid_bogus[] = "1.2.3",
2623             oid_rsa[]   = szOID_RSA;
2624
2625 static const struct encodedPublicKey pubKeys[] = {
2626  /* with a bogus OID */
2627  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2628   bin64, bin65,
2629   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2630  /* some normal keys */
2631  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2632   bin66, bin67,
2633   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2634  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2635   bin68, bin69,
2636   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2637  /* with add'l parameters--note they must be DER-encoded */
2638  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2639   (BYTE *)aKey, 0 } },
2640   bin70, bin71,
2641   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2642   (BYTE *)aKey, 0 } } },
2643 };
2644
2645 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2646 {
2647     DWORD i;
2648
2649     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2650     {
2651         BOOL ret;
2652         BYTE *buf = NULL;
2653         DWORD bufSize = 0;
2654
2655         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2656          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2657          &bufSize);
2658         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2659         if (buf)
2660         {
2661             ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2662              bufSize == pubKeys[i].encodedNoNull[1] + 2,
2663              "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2664              pubKeys[i].encodedNoNull[1] + 2, bufSize);
2665             if (bufSize == pubKeys[i].encoded[1] + 2)
2666                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2667                  "Unexpected value\n");
2668             else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2669                 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2670                  pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2671             LocalFree(buf);
2672         }
2673     }
2674 }
2675
2676 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2677  const CERT_PUBLIC_KEY_INFO *got)
2678 {
2679     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2680      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2681      got->Algorithm.pszObjId);
2682     ok(expected->Algorithm.Parameters.cbData ==
2683      got->Algorithm.Parameters.cbData,
2684      "Expected parameters of %d bytes, got %d\n",
2685      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2686     if (expected->Algorithm.Parameters.cbData)
2687         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2688          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2689          "Unexpected algorithm parameters\n");
2690     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2691      "Expected public key of %d bytes, got %d\n",
2692      expected->PublicKey.cbData, got->PublicKey.cbData);
2693     if (expected->PublicKey.cbData)
2694         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2695          got->PublicKey.cbData), "Unexpected public key value\n");
2696 }
2697
2698 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2699 {
2700     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2701      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2702      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2703      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2704     DWORD i;
2705     BOOL ret;
2706     BYTE *buf = NULL;
2707     DWORD bufSize = 0;
2708
2709     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2710     {
2711         /* The NULL form decodes to the decoded member */
2712         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2713          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2714          NULL, (BYTE *)&buf, &bufSize);
2715         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2716         if (buf)
2717         {
2718             comparePublicKeyInfo(&pubKeys[i].decoded,
2719              (CERT_PUBLIC_KEY_INFO *)buf);
2720             LocalFree(buf);
2721         }
2722         /* The non-NULL form decodes to the original */
2723         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2724          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2725          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2726         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2727         if (buf)
2728         {
2729             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2730             LocalFree(buf);
2731         }
2732     }
2733     /* Test with bogus (not valid DER) parameters */
2734     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2735      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2736      NULL, (BYTE *)&buf, &bufSize);
2737     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2738      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2739 }
2740
2741 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2742  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2743  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2744  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2745  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2746 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2747  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2748  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2749  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2750  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2751 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2752  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2753  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2754  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2755  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2756 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2757  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2758  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2759  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2760  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2761  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2762  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2763 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2764  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2765  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2766  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2767  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2768  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2769  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2770 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2771  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2772  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2773  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2774  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2775  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2776  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2777  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2778  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2779  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2780 static const BYTE v1CertWithPubKey[] = {
2781 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2782 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2783 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2784 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2785 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2786 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2787 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2788 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2789 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2790 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2791 0x01,0x01 };
2792 static const BYTE v1CertWithPubKeyNoNull[] = {
2793 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2794 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2795 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2796 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2797 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2798 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2799 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2800 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2801 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2802 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2803 static const BYTE v1CertWithSubjectKeyId[] = {
2804 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2805 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2806 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2807 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2808 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2809 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2810 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2811 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2812 0x4c,0x61,0x6e,0x67,0x00 };
2813
2814 static const BYTE serialNum[] = { 0x01 };
2815
2816 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2817 {
2818     BOOL ret;
2819     BYTE *buf = NULL;
2820     DWORD size = 0;
2821     CERT_INFO info = { 0 };
2822     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2823     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2824     CERT_EXTENSION ext;
2825
2826     if (0)
2827     {
2828         /* Test with NULL pvStructInfo (crashes on win9x) */
2829         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2830          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2831         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2832          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2833     }
2834     /* Test with a V1 cert */
2835     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2836      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2837     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2838     if (buf)
2839     {
2840         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2841          v1Cert[1] + 2, size);
2842         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2843         LocalFree(buf);
2844     }
2845     /* Test v2 cert */
2846     info.dwVersion = CERT_V2;
2847     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2848      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2849     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2850     if (buf)
2851     {
2852         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2853         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2854         LocalFree(buf);
2855     }
2856     /* Test v3 cert */
2857     info.dwVersion = CERT_V3;
2858     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2859      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2860     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2861     if (buf)
2862     {
2863         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2864         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2865         LocalFree(buf);
2866     }
2867     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2868      * API doesn't prevent it)
2869      */
2870     info.dwVersion = CERT_V1;
2871     info.cExtension = 1;
2872     info.rgExtension = &criticalExt;
2873     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2874      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2875     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2876     if (buf)
2877     {
2878         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2879         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2880         LocalFree(buf);
2881     }
2882     /* test v1 cert with a serial number */
2883     info.SerialNumber.cbData = sizeof(serialNum);
2884     info.SerialNumber.pbData = (BYTE *)serialNum;
2885     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2886      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2887     if (buf)
2888     {
2889         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2890         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2891         LocalFree(buf);
2892     }
2893     /* Test v1 cert with an issuer name, a subject name, and a serial number */
2894     info.Issuer.cbData = sizeof(encodedCommonName);
2895     info.Issuer.pbData = (BYTE *)encodedCommonName;
2896     info.Subject.cbData = sizeof(encodedCommonName);
2897     info.Subject.pbData = (BYTE *)encodedCommonName;
2898     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2899      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2900     if (buf)
2901     {
2902         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2903         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2904         LocalFree(buf);
2905     }
2906     /* Add a public key */
2907     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
2908     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
2909     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
2910     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2911      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2912     if (buf)
2913     {
2914         ok(size == sizeof(v1CertWithPubKey) ||
2915          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
2916         if (size == sizeof(v1CertWithPubKey))
2917             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
2918         else if (size == sizeof(v1CertWithPubKeyNoNull))
2919             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
2920              "Got unexpected value\n");
2921         LocalFree(buf);
2922     }
2923     /* Remove the public key, and add a subject key identifier extension */
2924     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
2925     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
2926     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
2927     ext.pszObjId = oid_subject_key_identifier;
2928     ext.fCritical = FALSE;
2929     ext.Value.cbData = sizeof(octetCommonNameValue);
2930     ext.Value.pbData = (BYTE *)octetCommonNameValue;
2931     info.cExtension = 1;
2932     info.rgExtension = &ext;
2933     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2934      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2935     if (buf)
2936     {
2937         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
2938         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
2939         LocalFree(buf);
2940     }
2941 }
2942
2943 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2944 {
2945     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2946      v1CertWithConstraints, v1CertWithSerial };
2947     BOOL ret;
2948     BYTE *buf = NULL;
2949     DWORD size = 0, i;
2950
2951     /* Test with NULL pbEncoded */
2952     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2953      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2954     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2955      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2956     if (0)
2957     {
2958         /* Crashes on win9x */
2959         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2960          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2961         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2962          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2963     }
2964     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2965      * minimum a cert must have a non-zero serial number, an issuer, and a
2966      * subject.
2967      */
2968     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2969     {
2970         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2971          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2972          (BYTE *)&buf, &size);
2973         ok(!ret, "Expected failure\n");
2974     }
2975     /* Now check with serial number, subject and issuer specified */
2976     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2977      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2978     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2979     if (buf)
2980     {
2981         CERT_INFO *info = (CERT_INFO *)buf;
2982
2983         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2984         ok(info->SerialNumber.cbData == 1,
2985          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2986         ok(*info->SerialNumber.pbData == *serialNum,
2987          "Expected serial number %d, got %d\n", *serialNum,
2988          *info->SerialNumber.pbData);
2989         ok(info->Issuer.cbData == sizeof(encodedCommonName),
2990          "Wrong size %d\n", info->Issuer.cbData);
2991         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2992          "Unexpected issuer\n");
2993         ok(info->Subject.cbData == sizeof(encodedCommonName),
2994          "Wrong size %d\n", info->Subject.cbData);
2995         ok(!memcmp(info->Subject.pbData, encodedCommonName,
2996          info->Subject.cbData), "Unexpected subject\n");
2997         LocalFree(buf);
2998     }
2999     /* Check again with pub key specified */
3000     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3001      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3002      (BYTE *)&buf, &size);
3003     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3004     if (buf)
3005     {
3006         CERT_INFO *info = (CERT_INFO *)buf;
3007
3008         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3009         ok(info->SerialNumber.cbData == 1,
3010          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3011         ok(*info->SerialNumber.pbData == *serialNum,
3012          "Expected serial number %d, got %d\n", *serialNum,
3013          *info->SerialNumber.pbData);
3014         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3015          "Wrong size %d\n", info->Issuer.cbData);
3016         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3017          "Unexpected issuer\n");
3018         ok(info->Subject.cbData == sizeof(encodedCommonName),
3019          "Wrong size %d\n", info->Subject.cbData);
3020         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3021          info->Subject.cbData), "Unexpected subject\n");
3022         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3023          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3024          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3025         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3026          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3027         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3028          sizeof(aKey)), "Unexpected public key\n");
3029         LocalFree(buf);
3030     }
3031 }
3032
3033 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3034  0xe, 0xf };
3035
3036 static const BYTE signedBigCert[] = {
3037  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3038  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3039  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3040  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3041  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3042  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3043  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3044  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3045  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3046  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3047  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3048  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3049
3050 static void test_encodeCert(DWORD dwEncoding)
3051 {
3052     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3053      * also that bigCert is a NULL-terminated string, so don't count its
3054      * last byte (otherwise the signed cert won't decode.)
3055      */
3056     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3057      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3058     BOOL ret;
3059     BYTE *buf = NULL;
3060     DWORD bufSize = 0;
3061
3062     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3063      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
3064     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3065     if (buf)
3066     {
3067         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3068         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3069         LocalFree(buf);
3070     }
3071 }
3072
3073 static void test_decodeCert(DWORD dwEncoding)
3074 {
3075     BOOL ret;
3076     BYTE *buf = NULL;
3077     DWORD size = 0;
3078
3079     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3080      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3081     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3082     if (buf)
3083     {
3084         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3085
3086         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3087          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3088         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3089          "Unexpected cert\n");
3090         ok(info->Signature.cbData == sizeof(hash),
3091          "Wrong signature size %d\n", info->Signature.cbData);
3092         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3093          "Unexpected signature\n");
3094         LocalFree(buf);
3095     }
3096     /* A signed cert decodes as a CERT_INFO too */
3097     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3098      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3099     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3100     if (buf)
3101     {
3102         CERT_INFO *info = (CERT_INFO *)buf;
3103
3104         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3105         ok(info->SerialNumber.cbData == 1,
3106          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3107         ok(*info->SerialNumber.pbData == *serialNum,
3108          "Expected serial number %d, got %d\n", *serialNum,
3109          *info->SerialNumber.pbData);
3110         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3111          "Wrong size %d\n", info->Issuer.cbData);
3112         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3113          "Unexpected issuer\n");
3114         ok(info->Subject.cbData == sizeof(encodedCommonName),
3115          "Wrong size %d\n", info->Subject.cbData);
3116         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3117          info->Subject.cbData), "Unexpected subject\n");
3118         LocalFree(buf);
3119     }
3120 }
3121
3122 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3123 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3124  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3125  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3126 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3127  0x00, 0x03 };
3128 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3129  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3130  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3131 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3132  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3133  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3134  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3135  0x2e, 0x6f, 0x72, 0x67 };
3136 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3137  CRL_REASON_AFFILIATION_CHANGED;
3138
3139 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3140 {
3141     CRL_DIST_POINTS_INFO info = { 0 };
3142     CRL_DIST_POINT point = { { 0 } };
3143     CERT_ALT_NAME_ENTRY entry = { 0 };
3144     BOOL ret;
3145     BYTE *buf = NULL;
3146     DWORD size = 0;
3147
3148     /* Test with an empty info */
3149     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3150      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3151     ok(!ret && GetLastError() == E_INVALIDARG,
3152      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3153     /* Test with one empty dist point */
3154     info.cDistPoint = 1;
3155     info.rgDistPoint = &point;
3156     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3157      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3158     if (buf)
3159     {
3160         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3161         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3162         LocalFree(buf);
3163     }
3164     /* A dist point with an invalid name */
3165     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3166     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3167     U(entry).pwszURL = (LPWSTR)nihongoURL;
3168     U(point.DistPointName).FullName.cAltEntry = 1;
3169     U(point.DistPointName).FullName.rgAltEntry = &entry;
3170     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3171      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3172     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3173      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3174     /* The first invalid character is at index 7 */
3175     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3176      "Expected invalid char at index 7, got %d\n",
3177      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3178     /* A dist point with (just) a valid name */
3179     U(entry).pwszURL = (LPWSTR)url;
3180     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3181      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3182     if (buf)
3183     {
3184         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3185         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3186         LocalFree(buf);
3187     }
3188     /* A dist point with (just) reason flags */
3189     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3190     point.ReasonFlags.cbData = sizeof(crlReason);
3191     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3192     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3193      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3194     if (buf)
3195     {
3196         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3197         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3198         LocalFree(buf);
3199     }
3200     /* A dist point with just an issuer */
3201     point.ReasonFlags.cbData = 0;
3202     point.CRLIssuer.cAltEntry = 1;
3203     point.CRLIssuer.rgAltEntry = &entry;
3204     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3205      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3206     if (buf)
3207     {
3208         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3209         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3210         LocalFree(buf);
3211     }
3212     /* A dist point with both a name and an issuer */
3213     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3214     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3215      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3216     if (buf)
3217     {
3218         ok(size == sizeof(distPointWithUrlAndIssuer),
3219          "Wrong size %d\n", size);
3220         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3221         LocalFree(buf);
3222     }
3223 }
3224
3225 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3226 {
3227     BOOL ret;
3228     BYTE *buf = NULL;
3229     DWORD size = 0;
3230     PCRL_DIST_POINTS_INFO info;
3231     PCRL_DIST_POINT point;
3232     PCERT_ALT_NAME_ENTRY entry;
3233
3234     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3235      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3236      (BYTE *)&buf, &size);
3237     if (ret)
3238     {
3239         info = (PCRL_DIST_POINTS_INFO)buf;
3240         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3241          "Wrong size %d\n", size);
3242         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3243          info->cDistPoint);
3244         point = info->rgDistPoint;
3245         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3246          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3247          point->DistPointName.dwDistPointNameChoice);
3248         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3249         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3250         LocalFree(buf);
3251     }
3252     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3253      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3254      (BYTE *)&buf, &size);
3255     if (ret)
3256     {
3257         info = (PCRL_DIST_POINTS_INFO)buf;
3258         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3259          "Wrong size %d\n", size);
3260         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3261          info->cDistPoint);
3262         point = info->rgDistPoint;
3263         ok(point->DistPointName.dwDistPointNameChoice ==
3264          CRL_DIST_POINT_FULL_NAME,
3265          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3266          point->DistPointName.dwDistPointNameChoice);
3267         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3268          "Expected 1 name entry, got %d\n",
3269          U(point->DistPointName).FullName.cAltEntry);
3270         entry = U(point->DistPointName).FullName.rgAltEntry;
3271         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3272          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3273         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3274         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3275         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3276         LocalFree(buf);
3277     }
3278     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3279      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3280      NULL, (BYTE *)&buf, &size);
3281     if (ret)
3282     {
3283         info = (PCRL_DIST_POINTS_INFO)buf;
3284         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3285          "Wrong size %d\n", size);
3286         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3287          info->cDistPoint);
3288         point = info->rgDistPoint;
3289         ok(point->DistPointName.dwDistPointNameChoice ==
3290          CRL_DIST_POINT_NO_NAME,
3291          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3292          point->DistPointName.dwDistPointNameChoice);
3293         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3294          "Expected reason length\n");
3295         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3296          "Unexpected reason\n");
3297         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3298         LocalFree(buf);
3299     }
3300     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3301      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3302      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3303     if (ret)
3304     {
3305         info = (PCRL_DIST_POINTS_INFO)buf;
3306         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3307          "Wrong size %d\n", size);
3308         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3309          info->cDistPoint);
3310         point = info->rgDistPoint;
3311         ok(point->DistPointName.dwDistPointNameChoice ==
3312          CRL_DIST_POINT_FULL_NAME,
3313          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3314          point->DistPointName.dwDistPointNameChoice);
3315         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3316          "Expected 1 name entry, got %d\n",
3317          U(point->DistPointName).FullName.cAltEntry);
3318         entry = U(point->DistPointName).FullName.rgAltEntry;
3319         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3320          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3321         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3322         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3323         ok(point->CRLIssuer.cAltEntry == 1,
3324          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3325         entry = point->CRLIssuer.rgAltEntry;
3326         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3327          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3328         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3329         LocalFree(buf);
3330     }
3331 }
3332
3333 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3334 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3335 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3336  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3337  0x67 };
3338
3339 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3340 {
3341     BOOL ret;
3342     BYTE *buf = NULL;
3343     DWORD size = 0;
3344     CRL_ISSUING_DIST_POINT point = { { 0 } };
3345     CERT_ALT_NAME_ENTRY entry;
3346
3347     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3348      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3349     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3350     {
3351         skip("no X509_ISSUING_DIST_POINT encode support\n");
3352         return;
3353     }
3354     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3355      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3356     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3357      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3358     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3359     if (buf)
3360     {
3361         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3362         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3363         LocalFree(buf);
3364     }
3365     /* nonsensical flags */
3366     point.fOnlyContainsUserCerts = TRUE;
3367     point.fOnlyContainsCACerts = TRUE;
3368     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3369      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3370     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3371     if (buf)
3372     {
3373         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3374         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3375         LocalFree(buf);
3376     }
3377     /* unimplemented name type */
3378     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3379     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3380     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3381      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3382     ok(!ret && GetLastError() == E_INVALIDARG,
3383      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3384     /* empty name */
3385     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3386     U(point.DistPointName).FullName.cAltEntry = 0;
3387     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3388      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3389     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3390     if (buf)
3391     {
3392         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3393         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3394         LocalFree(buf);
3395     }
3396     /* name with URL entry */
3397     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3398     U(entry).pwszURL = (LPWSTR)url;
3399     U(point.DistPointName).FullName.cAltEntry = 1;
3400     U(point.DistPointName).FullName.rgAltEntry = &entry;
3401     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3402      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3403     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3404     if (buf)
3405     {
3406         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3407         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3408         LocalFree(buf);
3409     }
3410 }
3411
3412 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3413  const CERT_ALT_NAME_ENTRY *got)
3414 {
3415     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3416      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3417      got->dwAltNameChoice);
3418     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3419     {
3420         switch (got->dwAltNameChoice)
3421         {
3422         case CERT_ALT_NAME_RFC822_NAME:
3423         case CERT_ALT_NAME_DNS_NAME:
3424         case CERT_ALT_NAME_EDI_PARTY_NAME:
3425         case CERT_ALT_NAME_URL:
3426         case CERT_ALT_NAME_REGISTERED_ID:
3427             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3428              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3429              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3430              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3431              "Unexpected name\n");
3432             break;
3433         case CERT_ALT_NAME_X400_ADDRESS:
3434         case CERT_ALT_NAME_DIRECTORY_NAME:
3435         case CERT_ALT_NAME_IP_ADDRESS:
3436             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3437                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3438             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3439                        U(*got).IPAddress.cbData), "Unexpected value\n");
3440             break;
3441         }
3442     }
3443 }
3444
3445 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3446  const CERT_ALT_NAME_INFO *got)
3447 {
3448     DWORD i;
3449
3450     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3451      expected->cAltEntry, got->cAltEntry);
3452     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3453         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3454 }
3455
3456 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3457  const CRL_DIST_POINT_NAME *got)
3458 {
3459     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3460      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3461     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3462         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3463 }
3464
3465 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3466  const CRL_ISSUING_DIST_POINT *got)
3467 {
3468     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3469     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3470      "Unexpected fOnlyContainsUserCerts\n");
3471     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3472      "Unexpected fOnlyContainsCACerts\n");
3473     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3474      "Unexpected reason flags\n");
3475     ok(got->fIndirectCRL == expected->fIndirectCRL,
3476      "Unexpected fIndirectCRL\n");
3477 }
3478
3479 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3480 {
3481     BOOL ret;
3482     BYTE *buf = NULL;
3483     DWORD size = 0;
3484     CRL_ISSUING_DIST_POINT point = { { 0 } };
3485
3486     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3487      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3488      (BYTE *)&buf, &size);
3489     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3490     {
3491         skip("no X509_ISSUING_DIST_POINT decode support\n");
3492         return;
3493     }
3494     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3495     if (ret)
3496     {
3497         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3498         LocalFree(buf);
3499     }
3500     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3501      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3502      (BYTE *)&buf, &size);
3503     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3504     if (ret)
3505     {
3506         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3507         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3508         LocalFree(buf);
3509     }
3510     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3511      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3512      (BYTE *)&buf, &size);
3513     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3514     if (ret)
3515     {
3516         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3517         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3518         U(point.DistPointName).FullName.cAltEntry = 0;
3519         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3520         LocalFree(buf);
3521     }
3522     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3523      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3524     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3525     if (ret)
3526     {
3527         CERT_ALT_NAME_ENTRY entry;
3528
3529         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3530         U(entry).pwszURL = (LPWSTR)url;
3531         U(point.DistPointName).FullName.cAltEntry = 1;
3532         U(point.DistPointName).FullName.rgAltEntry = &entry;
3533         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3534         LocalFree(buf);
3535     }
3536 }
3537
3538 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3539  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3540  0x30, 0x5a };
3541 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3542  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3543  0x30, 0x30, 0x30, 0x30, 0x5a };
3544 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3545  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3546  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3547  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3548  0x5a };
3549 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3550  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3551  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3552  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3553  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3554  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3555 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3556  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3557  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3558  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3559  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3560  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3561 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3562  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3563  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3564  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3565  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3566  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3567  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3568 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3569  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3570  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3571  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3572  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3573  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3574  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3575 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3576  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3577  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3578  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3579  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3580  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3581  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3582 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3583  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3584  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3585  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3586  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3587  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3588  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3589
3590 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3591 {
3592     BOOL ret;
3593     BYTE *buf = NULL;
3594     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3595     DWORD size = 0;
3596     CRL_INFO info = { 0 };
3597     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3598     CERT_EXTENSION ext;
3599
3600     /* Test with a V1 CRL */
3601     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3602      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3603     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3604     if (buf)
3605     {
3606         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3607         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3608         LocalFree(buf);
3609     }
3610     /* Test v2 CRL */
3611     info.dwVersion = CRL_V2;
3612     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3613      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3614     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3615     if (buf)
3616     {
3617         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3618          v2CRL[1] + 2, size);
3619         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3620         LocalFree(buf);
3621     }
3622     /* v1 CRL with a name */
3623     info.dwVersion = CRL_V1;
3624     info.Issuer.cbData = sizeof(encodedCommonName);
3625     info.Issuer.pbData = (BYTE *)encodedCommonName;
3626     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3627      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3628     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3629     if (buf)
3630     {
3631         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3632         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3633         LocalFree(buf);
3634     }
3635     if (0)
3636     {
3637         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3638         info.cCRLEntry = 1;
3639         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3640          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3641         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3642          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3643     }
3644     /* now set an empty entry */
3645     info.cCRLEntry = 1;
3646     info.rgCRLEntry = &entry;
3647     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3648      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3649     if (buf)
3650     {
3651         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3652          "Wrong size %d\n", size);
3653         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3654          "Got unexpected value\n");
3655         LocalFree(buf);
3656     }
3657     /* an entry with a serial number */
3658     entry.SerialNumber.cbData = sizeof(serialNum);
3659     entry.SerialNumber.pbData = (BYTE *)serialNum;
3660     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3661      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3662     if (buf)
3663     {
3664         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3665          "Wrong size %d\n", size);
3666         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3667          "Got unexpected value\n");
3668         LocalFree(buf);
3669     }
3670     /* an entry with an extension */
3671     entry.cExtension = 1;
3672     entry.rgExtension = &criticalExt;
3673     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3674      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3675     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3676     if (buf)
3677     {
3678         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3679         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3680         LocalFree(buf);
3681     }
3682     /* a CRL with an extension */
3683     entry.cExtension = 0;
3684     info.cExtension = 1;
3685     info.rgExtension = &criticalExt;
3686     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3687      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3688     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3689     if (buf)
3690     {
3691         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3692         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3693         LocalFree(buf);
3694     }
3695     /* a v2 CRL with an extension, this time non-critical */
3696     info.dwVersion = CRL_V2;
3697     info.rgExtension = &nonCriticalExt;
3698     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3699      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3700     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3701     if (buf)
3702     {
3703         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3704         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3705         LocalFree(buf);
3706     }
3707     /* a v2 CRL with an issuing dist point extension */
3708     ext.pszObjId = oid_issuing_dist_point;
3709     ext.fCritical = TRUE;
3710     ext.Value.cbData = sizeof(urlIDP);
3711     ext.Value.pbData = (LPBYTE)urlIDP;
3712     entry.rgExtension = &ext;
3713     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3714      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3715     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3716     if (buf)
3717     {
3718         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3719         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3720         LocalFree(buf);
3721     }
3722 }
3723
3724 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3725  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3726  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3727  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3728  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3729  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3730  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3731  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3732  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3733  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3734  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3735  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3736  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3737  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3738  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3739  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3740  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3741  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3742  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3743  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3744  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3745  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3746  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3747  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3748  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3749  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3750  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3751  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3752  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3753  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3754  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3755  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3756  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3757  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3758  0xcd };
3759 static const BYTE verisignCRLWithLotsOfEntries[] = {
3760 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3761 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3762 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3763 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3764 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3765 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3766 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3767 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3768 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3769 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3770 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3771 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3772 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3773 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3774 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3775 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3776 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3777 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3778 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3779 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3780 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3781 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3782 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3783 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3784 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3785 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3786 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3787 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3788 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3789 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3790 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3791 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3792 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3793 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3794 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3795 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3796 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3797 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3798 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3799 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3800 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3801 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3802 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3803 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3804 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3805 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3806 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3807 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3808 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3809 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3810 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3811 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3812 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3813 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3814 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3815 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3816 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3817 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3818 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3819 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3820 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3821 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3822 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3823 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3824 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3825 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3826 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3827 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3828 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3829 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3830 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3831 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3832 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3833 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3834 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3835 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3836 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3837 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3838 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3839 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3840 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3841 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3842 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3843 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3844 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3845 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3846 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3847 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3848 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3849 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3850 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3851 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3852 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3853 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3854 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3855 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3856 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3857 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3858 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3859 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3860 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3861 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3862 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3863 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3864 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3865 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3866 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3867 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3868 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3869 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3870 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3871 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3872 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3873 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3874 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3875 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3876 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3877 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3878 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3879 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3880 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3881 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3882 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3883 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3884 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3885 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3886 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3887 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3888 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3889 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3890 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3891 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3892 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3893 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3894 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3895 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3896 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3897 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3898 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3899 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3900 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3901 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3902 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3903 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3904 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3905 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3906 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3907 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3908 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3909 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3910 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3911 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3912 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3913 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3914 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3915 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3916 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3917 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3918 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3919 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3920 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3921 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3922 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3923 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3924 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3925 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3926 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3927 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3928 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3929 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3930 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3931 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3932 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3933 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3934 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3935 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3936 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3937 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3938 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3939 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3940 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3941 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3942 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3943 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3944 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3945 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3946 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3947 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
3948 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
3949 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
3950 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
3951 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
3952 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
3953 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
3954 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
3955 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
3956 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
3957 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
3958 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
3959 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
3960 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
3961 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
3962 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
3963 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
3964 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
3965 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
3966 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
3967 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
3968 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
3969 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
3970 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
3971 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
3972 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
3973 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
3974 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
3975 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
3976 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
3977 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
3978 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
3979 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
3980 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
3981 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
3982 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
3983 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
3984 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
3985 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
3986 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
3987 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
3988 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
3989 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
3990 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
3991 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
3992 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
3993 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
3994 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
3995 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
3996 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
3997 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
3998 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
3999 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4000 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4001 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4002 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4003 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4004 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4005 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4006 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4007 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4008 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4009 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4010 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4011 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4012 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4013 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4014 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4015 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4016 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4017 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4018 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4019 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4020 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4021 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4022 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4023 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4024 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4025 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4026 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4027 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4028 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4029 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4030 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4031 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4032 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4033 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4034 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4035 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4036 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4037 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4038 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4039 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4040 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4041 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4042 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4043 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4044 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4045 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4046 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4047 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4048 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4049 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4050 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4051 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4052 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4053 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4054 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4055 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4056 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4057 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4058 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4059 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4060 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4061 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4062 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4063 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4064 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4065 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4066 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4067 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4068 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4069 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4070 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4071 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4072 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4073 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4074 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4075 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4076 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4077 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4078 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4079 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4080 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4081 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4082 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4083 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4084 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4085 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4086 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4087 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4088 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4089 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4090 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4091 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4092 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4093 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4094 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4095 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4096 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4097 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4098 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4099 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4100 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4101 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4102 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4103 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4104 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4105 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4106 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4107 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4108 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4109 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4110 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4111 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4112 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4113 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4114 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4115 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4116 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4117 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4118 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4119 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4120 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4121 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4122 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4123 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4124 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4125 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4126 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4127 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4128 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4129 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4130 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4131 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4132 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4133 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4134 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4135 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4136 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4137 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4138 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4139 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4140 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4141 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4142 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4143 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4144 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4145 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4146 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4147 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4148 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4149 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4150 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4151 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4152 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4153 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4154 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4155 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4156 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4157 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4158 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4159 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4160 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4161 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4162 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4163 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4164 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4165 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4166 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4167 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4168 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4169 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4170 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4171 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4172 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4173 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4174 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4175 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4176 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4177 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4178 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4179 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4180 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4181 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4182 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4183 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4184 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4185 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4186 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4187 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4188 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4189 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4190 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4191 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4192 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4193 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4194 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4195 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4196 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4197 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4198 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4199 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4200 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4201 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4202 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4203 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4204 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4205 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4206 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4207 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4208 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4209 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4210 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4211 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4212 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4213 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4214 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4215 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4216 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4217 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4218 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4219 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4220 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4221 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4222 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4223 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4224 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4225 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4226 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4227 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4228 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4229 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4230 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4231 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4232 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4233 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4234 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4235 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4236 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4237 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4238 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4239 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4240 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4241 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4242 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4243 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4244 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4245 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4246 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4247 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4248 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4249 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4250 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4251 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4252 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4253 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4254 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4255 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4256 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4257 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4258 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4259 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4260 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4261 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4262 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4263 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4264 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4265 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4266 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4267 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4268
4269 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4270 {
4271     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4272     BOOL ret;
4273     BYTE *buf = NULL;
4274     DWORD size = 0, i;
4275
4276     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4277     {
4278         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4279          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4280          (BYTE *)&buf, &size);
4281         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
4282          "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4283     }
4284     /* at a minimum, a CRL must contain an issuer: */
4285     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4286      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4287      (BYTE *)&buf, &size);
4288     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4289     if (buf)
4290     {
4291         CRL_INFO *info = (CRL_INFO *)buf;
4292
4293         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4294         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4295          info->cCRLEntry);
4296         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4297          "Wrong issuer size %d\n", info->Issuer.cbData);
4298         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4299          "Unexpected issuer\n");
4300         LocalFree(buf);
4301     }
4302     /* check decoding with an empty CRL entry */
4303     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4304      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4305      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4306     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
4307      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4308     /* with a real CRL entry */
4309     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4310      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4311      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4312     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4313     if (buf)
4314     {
4315         CRL_INFO *info = (CRL_INFO *)buf;
4316         CRL_ENTRY *entry;
4317
4318         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4319         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4320          info->cCRLEntry);
4321         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4322         entry = info->rgCRLEntry;
4323         ok(entry->SerialNumber.cbData == 1,
4324          "Expected serial number size 1, got %d\n",
4325          entry->SerialNumber.cbData);
4326         ok(*entry->SerialNumber.pbData == *serialNum,
4327          "Expected serial number %d, got %d\n", *serialNum,
4328          *entry->SerialNumber.pbData);
4329         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4330          "Wrong issuer size %d\n", info->Issuer.cbData);
4331         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4332          "Unexpected issuer\n");
4333         LocalFree(buf);
4334     }
4335     /* a real CRL from verisign that has extensions */
4336     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4337      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4338      NULL, (BYTE *)&buf, &size);
4339     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4340     if (buf)
4341     {
4342         CRL_INFO *info = (CRL_INFO *)buf;
4343         CRL_ENTRY *entry;
4344
4345         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4346         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4347          info->cCRLEntry);
4348         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4349         entry = info->rgCRLEntry;
4350         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4351          info->cExtension);
4352         LocalFree(buf);
4353     }
4354     /* another real CRL from verisign that has lots of entries */
4355     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4356      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4357      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4358     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4359     if (buf)
4360     {
4361         CRL_INFO *info = (CRL_INFO *)buf;
4362
4363         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4364         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4365          info->cCRLEntry);
4366         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4367          info->cExtension);
4368         LocalFree(buf);
4369     }
4370     /* and finally, with an extension */
4371     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4372      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4373      NULL, (BYTE *)&buf, &size);
4374     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4375     if (buf)
4376     {
4377         CRL_INFO *info = (CRL_INFO *)buf;
4378         CRL_ENTRY *entry;
4379
4380         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4381         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4382          info->cCRLEntry);
4383         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4384         entry = info->rgCRLEntry;
4385         ok(entry->SerialNumber.cbData == 1,
4386          "Expected serial number size 1, got %d\n",
4387          entry->SerialNumber.cbData);
4388         ok(*entry->SerialNumber.pbData == *serialNum,
4389          "Expected serial number %d, got %d\n", *serialNum,
4390          *entry->SerialNumber.pbData);
4391         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4392          "Wrong issuer size %d\n", info->Issuer.cbData);
4393         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4394          "Unexpected issuer\n");
4395         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4396          info->cExtension);
4397         LocalFree(buf);
4398     }
4399     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4400      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4401      NULL, (BYTE *)&buf, &size);
4402     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4403     if (buf)
4404     {
4405         CRL_INFO *info = (CRL_INFO *)buf;
4406
4407         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4408          info->cExtension);
4409         LocalFree(buf);
4410     }
4411     /* And again, with an issuing dist point */
4412     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4413      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4414      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4415     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4416     if (buf)
4417     {
4418         CRL_INFO *info = (CRL_INFO *)buf;
4419
4420         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4421          info->cExtension);
4422         LocalFree(buf);
4423     }
4424 }
4425
4426 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4427  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4428 static const BYTE encodedUsage[] = {
4429  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4430  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4431  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4432
4433 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4434 {
4435     BOOL ret;
4436     BYTE *buf = NULL;
4437     DWORD size = 0;
4438     CERT_ENHKEY_USAGE usage;
4439
4440     /* Test with empty usage */
4441     usage.cUsageIdentifier = 0;
4442     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4443      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4444     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4445     if (buf)
4446     {
4447         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4448         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4449         LocalFree(buf);
4450     }
4451     /* Test with a few usages */
4452     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4453     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4454     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4455      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4456     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4457     if (buf)
4458     {
4459         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4460         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4461         LocalFree(buf);
4462     }
4463 }
4464
4465 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4466 {
4467     BOOL ret;
4468     LPBYTE buf = NULL;
4469     DWORD size = 0;
4470
4471     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4472      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4473      (BYTE *)&buf, &size);
4474     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4475     if (buf)
4476     {
4477         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4478
4479         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4480          "Wrong size %d\n", size);
4481         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4482          usage->cUsageIdentifier);
4483         LocalFree(buf);
4484     }
4485     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4486      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4487      (BYTE *)&buf, &size);
4488     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4489     if (buf)
4490     {
4491         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4492         DWORD i;
4493
4494         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4495          "Wrong size %d\n", size);
4496         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4497          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4498         for (i = 0; i < usage->cUsageIdentifier; i++)
4499             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4500              "Expected OID %s, got %s\n", keyUsages[i],
4501              usage->rgpszUsageIdentifier[i]);
4502         LocalFree(buf);
4503     }
4504 }
4505
4506 static BYTE keyId[] = { 1,2,3,4 };
4507 static const BYTE authorityKeyIdWithId[] = {
4508  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4509 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4510  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4511  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4512 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4513
4514 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4515 {
4516     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4517     BOOL ret;
4518     BYTE *buf = NULL;
4519     DWORD size = 0;
4520
4521     /* Test with empty id */
4522     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4523      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4524     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4525     if (buf)
4526     {
4527         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4528         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4529         LocalFree(buf);
4530     }
4531     /* With just a key id */
4532     info.KeyId.cbData = sizeof(keyId);
4533     info.KeyId.pbData = keyId;
4534     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4535      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4536     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4537     if (buf)
4538     {
4539         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4540         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4541         LocalFree(buf);
4542     }
4543     /* With just an issuer */
4544     info.KeyId.cbData = 0;
4545     info.CertIssuer.cbData = sizeof(encodedCommonName);
4546     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4547     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4548      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4549     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4550     if (buf)
4551     {
4552         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4553          size);
4554         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4555         LocalFree(buf);
4556     }
4557     /* With just a serial number */
4558     info.CertIssuer.cbData = 0;
4559     info.CertSerialNumber.cbData = sizeof(serialNum);
4560     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4561     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4562      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4563     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4564     if (buf)
4565     {
4566         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4567          size);
4568         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4569         LocalFree(buf);
4570     }
4571 }
4572
4573 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4574 {
4575     BOOL ret;
4576     LPBYTE buf = NULL;
4577     DWORD size = 0;
4578
4579     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4580      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4581      (BYTE *)&buf, &size);
4582     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4583     if (buf)
4584     {
4585         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4586
4587         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4588          size);
4589         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4590         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4591         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4592         LocalFree(buf);
4593     }
4594     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4595      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4596      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4597     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4598     if (buf)
4599     {
4600         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4601
4602         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4603          size);
4604         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4605         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4606          "Unexpected key id\n");
4607         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4608         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4609         LocalFree(buf);
4610     }
4611     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4612      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4613      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4614     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4615     if (buf)
4616     {
4617         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4618
4619         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4620          size);
4621         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4622         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4623          "Unexpected issuer len\n");
4624         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4625          sizeof(encodedCommonName)), "Unexpected issuer\n");
4626         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4627         LocalFree(buf);
4628     }
4629     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4630      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4631      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4632     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4633     if (buf)
4634     {
4635         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4636
4637         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4638          size);
4639         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4640         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4641         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4642          "Unexpected serial number len\n");
4643         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4644          "Unexpected serial number\n");
4645         LocalFree(buf);
4646     }
4647 }
4648
4649 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4650  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4651  0x6f,0x72,0x67 };
4652
4653 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4654 {
4655     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4656     CERT_ALT_NAME_ENTRY entry = { 0 };
4657     BOOL ret;
4658     BYTE *buf = NULL;
4659     DWORD size = 0;
4660
4661     /* Test with empty id */
4662     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4663      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4664     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4665     if (buf)
4666     {
4667         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4668         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4669         LocalFree(buf);
4670     }
4671     /* With just a key id */
4672     info.KeyId.cbData = sizeof(keyId);
4673     info.KeyId.pbData = keyId;
4674     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4675      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4676     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4677     if (buf)
4678     {
4679         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4680          size);
4681         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4682         LocalFree(buf);
4683     }
4684     /* With a bogus issuer name */
4685     info.KeyId.cbData = 0;
4686     info.AuthorityCertIssuer.cAltEntry = 1;
4687     info.AuthorityCertIssuer.rgAltEntry = &entry;
4688     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4689      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4690     ok(!ret && GetLastError() == E_INVALIDARG,
4691      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4692     /* With an issuer name */
4693     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4694     U(entry).pwszURL = (LPWSTR)url;
4695     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4696      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4697     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4698     if (buf)
4699     {
4700         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4701          size);
4702         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4703          "Unexpected value\n");
4704         LocalFree(buf);
4705     }
4706     /* With just a serial number */
4707     info.AuthorityCertIssuer.cAltEntry = 0;
4708     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4709     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4710     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4711      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4712     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4713     if (buf)
4714     {
4715         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4716          size);
4717         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4718         LocalFree(buf);
4719     }
4720 }
4721
4722 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4723 {
4724     BOOL ret;
4725     LPBYTE buf = NULL;
4726     DWORD size = 0;
4727
4728     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4729      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4730      (BYTE *)&buf, &size);
4731     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4732     if (buf)
4733     {
4734         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4735
4736         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4737          size);
4738         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4739         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4740          "Expected no issuer name entries\n");
4741         ok(info->AuthorityCertSerialNumber.cbData == 0,
4742          "Expected no serial number\n");
4743         LocalFree(buf);
4744     }
4745     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4746      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4747      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4748     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4749     if (buf)
4750     {
4751         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4752
4753         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4754          size);
4755         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4756         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4757          "Unexpected key id\n");
4758         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4759          "Expected no issuer name entries\n");
4760         ok(info->AuthorityCertSerialNumber.cbData == 0,
4761          "Expected no serial number\n");
4762         LocalFree(buf);
4763     }
4764     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4765      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4766      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4767     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4768     if (buf)
4769     {
4770         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4771
4772         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4773          size);
4774         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4775         ok(info->AuthorityCertIssuer.cAltEntry == 1,
4776          "Expected 1 issuer entry, got %d\n",
4777          info->AuthorityCertIssuer.cAltEntry);
4778         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4779          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4780          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4781         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4782          url), "Unexpected URL\n");
4783         ok(info->AuthorityCertSerialNumber.cbData == 0,
4784          "Expected no serial number\n");
4785         LocalFree(buf);
4786     }
4787     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4788      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4789      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4790     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4791     if (buf)
4792     {
4793         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4794
4795         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4796          size);
4797         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4798         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4799          "Expected no issuer name entries\n");
4800         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4801          "Unexpected serial number len\n");
4802         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4803          sizeof(serialNum)), "Unexpected serial number\n");
4804         LocalFree(buf);
4805     }
4806 }
4807
4808 static const BYTE authorityInfoAccessWithUrl[] = {
4809 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4810 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
4811 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
4812 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4813 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
4814 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
4815
4816 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
4817 {
4818     static char oid1[] = "1.2.3";
4819     static char oid2[] = "1.5.6";
4820     BOOL ret;
4821     BYTE *buf = NULL;
4822     DWORD size = 0;
4823     CERT_ACCESS_DESCRIPTION accessDescription[2];
4824     CERT_AUTHORITY_INFO_ACCESS aia;
4825
4826     memset(accessDescription, 0, sizeof(accessDescription));
4827     aia.cAccDescr = 0;
4828     aia.rgAccDescr = NULL;
4829     /* Having no access descriptions is allowed */
4830     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4831      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4832     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4833     if (buf)
4834     {
4835         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
4836         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
4837         LocalFree(buf);
4838         buf = NULL;
4839     }
4840     /* It can't have an empty access method */
4841     aia.cAccDescr = 1;
4842     aia.rgAccDescr = accessDescription;
4843     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4844      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4845     ok(!ret && GetLastError() == E_INVALIDARG,
4846      "expected E_INVALIDARG, got %08x\n", GetLastError());
4847     /* It can't have an empty location */
4848     accessDescription[0].pszAccessMethod = oid1;
4849     SetLastError(0xdeadbeef);
4850     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4851      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4852     ok(!ret && GetLastError() == E_INVALIDARG,
4853      "expected E_INVALIDARG, got %08x\n", GetLastError());
4854     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4855     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
4856     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4857      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4858     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4859     if (buf)
4860     {
4861         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
4862          size);
4863         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
4864          "unexpected value\n");
4865         LocalFree(buf);
4866         buf = NULL;
4867     }
4868     accessDescription[1].pszAccessMethod = oid2;
4869     accessDescription[1].AccessLocation.dwAltNameChoice =
4870      CERT_ALT_NAME_IP_ADDRESS;
4871     U(accessDescription[1].AccessLocation).IPAddress.cbData =
4872      sizeof(encodedIPAddr);
4873     U(accessDescription[1].AccessLocation).IPAddress.pbData =
4874      (LPBYTE)encodedIPAddr;
4875     aia.cAccDescr = 2;
4876     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4877      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4878     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4879     if (buf)
4880     {
4881         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
4882          "unexpected size %d\n", size);
4883         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
4884          "unexpected value\n");
4885         LocalFree(buf);
4886         buf = NULL;
4887     }
4888 }
4889
4890 static void compareAuthorityInfoAccess(LPCSTR header,
4891  const CERT_AUTHORITY_INFO_ACCESS *expected,
4892  const CERT_AUTHORITY_INFO_ACCESS *got)
4893 {
4894     DWORD i;
4895
4896     ok(expected->cAccDescr == got->cAccDescr,
4897      "%s: expected %d access descriptions, got %d\n", header,
4898      expected->cAccDescr, got->cAccDescr);
4899     for (i = 0; i < expected->cAccDescr; i++)
4900     {
4901         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
4902          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
4903          header, i, expected->rgAccDescr[i].pszAccessMethod,
4904          got->rgAccDescr[i].pszAccessMethod);
4905         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
4906          &got->rgAccDescr[i].AccessLocation);
4907     }
4908 }
4909
4910 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
4911 {
4912     static char oid1[] = "1.2.3";
4913     static char oid2[] = "1.5.6";
4914     BOOL ret;
4915     LPBYTE buf = NULL;
4916     DWORD size = 0;
4917
4918     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4919      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4920      (BYTE *)&buf, &size);
4921     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4922     if (buf)
4923     {
4924         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
4925
4926         compareAuthorityInfoAccess("empty AIA", &aia,
4927          (CERT_AUTHORITY_INFO_ACCESS *)buf);
4928         LocalFree(buf);
4929         buf = NULL;
4930     }
4931     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4932      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
4933      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4934     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4935     if (buf)
4936     {
4937         CERT_ACCESS_DESCRIPTION accessDescription;
4938         CERT_AUTHORITY_INFO_ACCESS aia;
4939
4940         accessDescription.pszAccessMethod = oid1;
4941         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4942         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
4943         aia.cAccDescr = 1;
4944         aia.rgAccDescr = &accessDescription;
4945         compareAuthorityInfoAccess("AIA with URL", &aia,
4946          (CERT_AUTHORITY_INFO_ACCESS *)buf);
4947         LocalFree(buf);
4948         buf = NULL;
4949     }
4950     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4951      authorityInfoAccessWithUrlAndIPAddr,
4952      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
4953      NULL, (BYTE *)&buf, &size);
4954     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4955     if (buf)
4956     {
4957         CERT_ACCESS_DESCRIPTION accessDescription[2];
4958         CERT_AUTHORITY_INFO_ACCESS aia;
4959
4960         accessDescription[0].pszAccessMethod = oid1;
4961         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4962         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
4963         accessDescription[1].pszAccessMethod = oid2;
4964         accessDescription[1].AccessLocation.dwAltNameChoice =
4965          CERT_ALT_NAME_IP_ADDRESS;
4966         U(accessDescription[1].AccessLocation).IPAddress.cbData =
4967          sizeof(encodedIPAddr);
4968         U(accessDescription[1].AccessLocation).IPAddress.pbData =
4969          (LPBYTE)encodedIPAddr;
4970         aia.cAccDescr = 2;
4971         aia.rgAccDescr = accessDescription;
4972         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
4973          (CERT_AUTHORITY_INFO_ACCESS *)buf);
4974         LocalFree(buf);
4975         buf = NULL;
4976     }
4977 }
4978
4979 static const BYTE emptyCTL[] = {
4980 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
4981 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4982 static const BYTE emptyCTLWithVersion1[] = {
4983 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
4984 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4985 static const BYTE ctlWithUsageIdentifier[] = {
4986 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
4987 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4988 static const BYTE ctlWithListIdentifier[] = {
4989 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
4990 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4991 static const BYTE ctlWithSequenceNumber[] = {
4992 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
4993 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4994 static const BYTE ctlWithThisUpdate[] = {
4995 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
4996 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4997 static const BYTE ctlWithThisAndNextUpdate[] = {
4998 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
4999 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5000 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5001 static const BYTE ctlWithAlgId[] = {
5002 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5003 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5004 static const BYTE ctlWithBogusEntry[] = {
5005 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5006 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5007 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5008 static const BYTE ctlWithOneEntry[] = {
5009 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5010 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5011 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5012 static const BYTE ctlWithTwoEntries[] = {
5013 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5014 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5015 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5016 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5017 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5018
5019 static void test_encodeCTL(DWORD dwEncoding)
5020 {
5021     static char oid1[] = "1.2.3";
5022     static char oid2[] = "1.5.6";
5023     char *pOid1 = oid1;
5024     BOOL ret;
5025     BYTE *buf = NULL;
5026     DWORD size = 0;
5027     CTL_INFO info;
5028     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5029     CTL_ENTRY ctlEntry[2];
5030     CRYPT_ATTRIBUTE attr1, attr2;
5031     CRYPT_ATTR_BLOB value1, value2;
5032
5033     memset(&info, 0, sizeof(info));
5034     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5035      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5036     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5037     if (buf)
5038     {
5039         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5040         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5041         LocalFree(buf);
5042         buf = NULL;
5043     }
5044     info.dwVersion = 1;
5045     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5046      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5047     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5048     if (buf)
5049     {
5050         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5051         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5052         LocalFree(buf);
5053         buf = NULL;
5054     }
5055     info.dwVersion = 0;
5056     info.SubjectUsage.cUsageIdentifier = 1;
5057     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5058     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5059      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5060     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5061     if (buf)
5062     {
5063         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5064          size);
5065         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5066         LocalFree(buf);
5067         buf = NULL;
5068     }
5069     info.SubjectUsage.cUsageIdentifier = 0;
5070     info.ListIdentifier.cbData = sizeof(serialNum);
5071     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5072     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5073      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5074     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5075     if (buf)
5076     {
5077         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5078         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5079         LocalFree(buf);
5080         buf = NULL;
5081     }
5082     info.ListIdentifier.cbData = 0;
5083     info.SequenceNumber.cbData = sizeof(serialNum);
5084     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5085     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5086      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5087     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5088     if (buf)
5089     {
5090         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5091          size);
5092         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5093         LocalFree(buf);
5094         buf = NULL;
5095     }
5096     info.SequenceNumber.cbData = 0;
5097     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5098     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5099      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5100     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5101     if (buf)
5102     {
5103         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5104         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5105         LocalFree(buf);
5106         buf = NULL;
5107     }
5108     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5109     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5110      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5111     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5112     if (buf)
5113     {
5114         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5115          size);
5116         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5117         LocalFree(buf);
5118         buf = NULL;
5119     }
5120     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5121     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5122     info.SubjectAlgorithm.pszObjId = oid2;
5123     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5124      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5125     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5126     if (buf)
5127     {
5128         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5129         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5130         LocalFree(buf);
5131         buf = NULL;
5132     }
5133     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5134      * (see tests below) but it'll encode fine.
5135      */
5136     info.SubjectAlgorithm.pszObjId = NULL;
5137     value1.cbData = sizeof(serialNum);
5138     value1.pbData = (LPBYTE)serialNum;
5139     attr1.pszObjId = oid1;
5140     attr1.cValue = 1;
5141     attr1.rgValue = &value1;
5142     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5143     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5144     ctlEntry[0].cAttribute = 1;
5145     ctlEntry[0].rgAttribute = &attr1;
5146     info.cCTLEntry = 1;
5147     info.rgCTLEntry = ctlEntry;
5148     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5149      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5150     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5151     if (buf)
5152     {
5153         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5154         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5155         LocalFree(buf);
5156         buf = NULL;
5157     }
5158     value1.cbData = sizeof(emptySequence);
5159     value1.pbData = (LPBYTE)emptySequence;
5160     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5161      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5162     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5163     if (buf)
5164     {
5165         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5166         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5167         LocalFree(buf);
5168         buf = NULL;
5169     }
5170     value2.cbData = sizeof(encodedIPAddr);
5171     value2.pbData = (LPBYTE)encodedIPAddr;
5172     attr2.pszObjId = oid2;
5173     attr2.cValue = 1;
5174     attr2.rgValue = &value2;
5175     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5176     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5177     ctlEntry[1].cAttribute = 1;
5178     ctlEntry[1].rgAttribute = &attr2;
5179     info.cCTLEntry = 2;
5180     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5181      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5182     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5183     if (buf)
5184     {
5185         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5186         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5187         LocalFree(buf);
5188         buf = NULL;
5189     }
5190 }
5191
5192 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5193  const CTL_INFO *got)
5194 {
5195     DWORD i, j, k;
5196
5197     ok(expected->dwVersion == got->dwVersion,
5198      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5199      got->dwVersion);
5200     ok(expected->SubjectUsage.cUsageIdentifier ==
5201      got->SubjectUsage.cUsageIdentifier,
5202      "%s: expected %d usage identifiers, got %d\n", header,
5203      expected->SubjectUsage.cUsageIdentifier,
5204      got->SubjectUsage.cUsageIdentifier);
5205     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5206         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5207          got->SubjectUsage.rgpszUsageIdentifier[i]),
5208          "%s[%d]: expected %s, got %s\n", header, i,
5209          expected->SubjectUsage.rgpszUsageIdentifier[i],
5210          got->SubjectUsage.rgpszUsageIdentifier[i]);
5211     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5212      "%s: expected list identifier of %d bytes, got %d\n", header,
5213      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5214     if (expected->ListIdentifier.cbData)
5215         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5216          expected->ListIdentifier.cbData),
5217          "%s: unexpected list identifier value\n", header);
5218     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5219      "%s: expected sequence number of %d bytes, got %d\n", header,
5220      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5221     if (expected->SequenceNumber.cbData)
5222         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5223          expected->SequenceNumber.cbData),
5224          "%s: unexpected sequence number value\n", header);
5225     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5226      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5227      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5228      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5229     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5230      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5231      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5232      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5233     if (expected->SubjectAlgorithm.pszObjId &&
5234      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5235         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5236          expected->SubjectAlgorithm.pszObjId);
5237     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5238         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5239          got->SubjectAlgorithm.pszObjId),
5240          "%s: expected subject algorithm %s, got %s\n", header,
5241          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5242     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5243      got->SubjectAlgorithm.Parameters.cbData,
5244      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5245      expected->SubjectAlgorithm.Parameters.cbData,
5246      got->SubjectAlgorithm.Parameters.cbData);
5247     if (expected->SubjectAlgorithm.Parameters.cbData)
5248         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5249          got->SubjectAlgorithm.Parameters.pbData,
5250          expected->SubjectAlgorithm.Parameters.cbData),
5251          "%s: unexpected subject algorithm parameter value\n", header);
5252     ok(expected->cCTLEntry == got->cCTLEntry,
5253      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5254      got->cCTLEntry);
5255     for (i = 0; i < expected->cCTLEntry; i++)
5256     {
5257         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5258          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5259          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5260          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5261          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5262         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5263             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5264              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5265              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5266              "%s[%d]: unexpected subject identifier value\n",
5267              header, i);
5268         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5269         {
5270             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5271              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5272              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5273              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5274              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5275             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5276             {
5277                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5278                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5279                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5280                  header, i, j, k,
5281                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5282                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5283                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5284                     ok(!memcmp(
5285                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5286                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5287                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5288                      "%s[%d][%d][%d]: unexpected value\n",
5289                      header, i, j, k);
5290             }
5291         }
5292     }
5293     ok(expected->cExtension == got->cExtension,
5294      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5295      got->cExtension);
5296     for (i = 0; i < expected->cExtension; i++)
5297     {
5298         ok(!strcmp(expected->rgExtension[i].pszObjId,
5299          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5300          header, i, expected->rgExtension[i].pszObjId,
5301          got->rgExtension[i].pszObjId);
5302         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5303          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5304          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5305         ok(expected->rgExtension[i].Value.cbData ==
5306          got->rgExtension[i].Value.cbData,
5307          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5308          header, i, expected->rgExtension[i].Value.cbData,
5309          got->rgExtension[i].Value.cbData);
5310         if (expected->rgExtension[i].Value.cbData)
5311             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5312              got->rgExtension[i].Value.pbData,
5313              expected->rgExtension[i].Value.cbData),
5314              "%s[%d]: unexpected extension value\n", header, i);
5315     }
5316 }
5317
5318 static const BYTE signedCTL[] = {
5319 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5320 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5321 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5322 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5323 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5324 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5325 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5326 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5327 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5328 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5329 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5330 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5331 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5332 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5333 static const BYTE signedCTLWithCTLInnerContent[] = {
5334 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5335 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5336 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5337 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5338 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5339 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5340 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5341 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5342 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5343 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5344 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5345 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5346 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5347 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5348 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5349 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5350 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5351 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5352 0x57,0x6c,0x0b,0x47,0xb8 };
5353
5354 static void test_decodeCTL(DWORD dwEncoding)
5355 {
5356     static char oid1[] = "1.2.3";
5357     static char oid2[] = "1.5.6";
5358     static BYTE nullData[] = { 5,0 };
5359     char *pOid1 = oid1;
5360     BOOL ret;
5361     BYTE *buf = NULL;
5362     DWORD size = 0;
5363     CTL_INFO info;
5364     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5365     CTL_ENTRY ctlEntry[2];
5366     CRYPT_ATTRIBUTE attr1, attr2;
5367     CRYPT_ATTR_BLOB value1, value2;
5368
5369     memset(&info, 0, sizeof(info));
5370     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5371      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5372     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5373     if (buf)
5374     {
5375         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5376         LocalFree(buf);
5377         buf = NULL;
5378     }
5379     info.dwVersion = 1;
5380     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5381      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
5382      &size);
5383     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5384     if (buf)
5385     {
5386         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5387         LocalFree(buf);
5388         buf = NULL;
5389     }
5390     info.dwVersion = 0;
5391     info.SubjectUsage.cUsageIdentifier = 1;
5392     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5393     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5394      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5395      (BYTE *)&buf, &size);
5396     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5397     if (buf)
5398     {
5399         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5400         LocalFree(buf);
5401         buf = NULL;
5402     }
5403     info.SubjectUsage.cUsageIdentifier = 0;
5404     info.ListIdentifier.cbData = sizeof(serialNum);
5405     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5406     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5407      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5408      (BYTE *)&buf, &size);
5409     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5410     if (buf)
5411     {
5412         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5413         LocalFree(buf);
5414         buf = NULL;
5415     }
5416     info.ListIdentifier.cbData = 0;
5417     info.SequenceNumber.cbData = sizeof(serialNum);
5418     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5419     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5420      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL,
5421      (BYTE *)&buf, &size);
5422     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5423     if (buf)
5424     {
5425         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5426         LocalFree(buf);
5427         buf = NULL;
5428     }
5429     info.SequenceNumber.cbData = 0;
5430     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5431     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5432      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5433      (BYTE *)&buf, &size);
5434     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5435     if (buf)
5436     {
5437         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5438         LocalFree(buf);
5439         buf = NULL;
5440     }
5441     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5442     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5443      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5444      (BYTE *)&buf, &size);
5445     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5446     if (buf)
5447     {
5448         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5449         LocalFree(buf);
5450         buf = NULL;
5451     }
5452     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5453     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5454     info.SubjectAlgorithm.pszObjId = oid2;
5455     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5456     info.SubjectAlgorithm.Parameters.pbData = nullData;
5457     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5458      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL,
5459      (BYTE *)&buf, &size);
5460     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5461     if (buf)
5462     {
5463         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5464         LocalFree(buf);
5465         buf = NULL;
5466     }
5467     SetLastError(0xdeadbeef);
5468     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5469      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL,
5470      (BYTE *)&buf, &size);
5471     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || CRYPT_E_ASN1_CORRUPT),
5472      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5473      GetLastError());
5474     info.SubjectAlgorithm.Parameters.cbData = 0;
5475     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5476     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5477     info.SubjectAlgorithm.pszObjId = oid2;
5478     info.SubjectAlgorithm.pszObjId = NULL;
5479     value1.cbData = sizeof(emptySequence);
5480     value1.pbData = (LPBYTE)emptySequence;
5481     attr1.pszObjId = oid1;
5482     attr1.cValue = 1;
5483     attr1.rgValue = &value1;
5484     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5485     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5486     ctlEntry[0].cAttribute = 1;
5487     ctlEntry[0].rgAttribute = &attr1;
5488     info.cCTLEntry = 1;
5489     info.rgCTLEntry = ctlEntry;
5490     SetLastError(0xdeadbeef);
5491     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5492      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL,
5493      (BYTE *)&buf, &size);
5494     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5495     if (buf)
5496     {
5497         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5498         LocalFree(buf);
5499         buf = NULL;
5500     }
5501     value2.cbData = sizeof(encodedIPAddr);
5502     value2.pbData = (LPBYTE)encodedIPAddr;
5503     attr2.pszObjId = oid2;
5504     attr2.cValue = 1;
5505     attr2.rgValue = &value2;
5506     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5507     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5508     ctlEntry[1].cAttribute = 1;
5509     ctlEntry[1].rgAttribute = &attr2;
5510     info.cCTLEntry = 2;
5511     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5512      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL,
5513      (BYTE *)&buf, &size);
5514     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5515     if (buf)
5516     {
5517         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5518         LocalFree(buf);
5519         buf = NULL;
5520     }
5521     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5522     SetLastError(0xdeadbeef);
5523     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5524      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5525     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
5526      "expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
5527     SetLastError(0xdeadbeef);
5528     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5529      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5530      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5531     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
5532      "expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
5533 }
5534
5535 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5536 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5537  0x03,0,0,0,0,0,0 };
5538 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5539  0xa0,0x01,0x01 };
5540 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5541  0x03,0x02,0x01,0x01 };
5542 static BYTE bogusDER[] = { 1 };
5543
5544 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5545 {
5546     BOOL ret;
5547     BYTE *buf = NULL;
5548     DWORD size = 0;
5549     CRYPT_CONTENT_INFO info = { 0 };
5550     char oid1[] = "1.2.3";
5551
5552     if (0)
5553     {
5554         /* Crashes on win9x */
5555         SetLastError(0xdeadbeef);
5556         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5557          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5558         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5559          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5560     }
5561     SetLastError(0xdeadbeef);
5562     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5563      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5564     ok(!ret && GetLastError() == E_INVALIDARG,
5565      "Expected E_INVALIDARG, got %x\n", GetLastError());
5566     info.pszObjId = oid1;
5567     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5568      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5569     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5570     if (buf)
5571     {
5572         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5573         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5574         LocalFree(buf);
5575     }
5576     info.Content.pbData = bogusDER;
5577     info.Content.cbData = sizeof(bogusDER);
5578     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5579      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5580     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5581     if (buf)
5582     {
5583         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5584         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5585         LocalFree(buf);
5586     }
5587     info.Content.pbData = (BYTE *)ints[0].encoded;
5588     info.Content.cbData = ints[0].encoded[1] + 2;
5589     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5590      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5591     if (buf)
5592     {
5593         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5594         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5595         LocalFree(buf);
5596     }
5597 }
5598
5599 static const BYTE indefiniteSignedPKCSContent[] = {
5600 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5601 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5602 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5603 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5604 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5605 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5606 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5607 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5608 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5609 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5610 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5611 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5612 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5613 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5614 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5615 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5616 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5617 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5618 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5619 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5620 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5621 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5622 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5623 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5624 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5625 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5626 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5627 0x00,0x00,0x00,0x00,0x00,0x00 };
5628
5629 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5630 {
5631     BOOL ret;
5632     LPBYTE buf = NULL;
5633     DWORD size = 0;
5634     CRYPT_CONTENT_INFO *info;
5635
5636     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5637      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5638      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5639     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5640     if (buf)
5641     {
5642         info = (CRYPT_CONTENT_INFO *)buf;
5643
5644         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5645          info->pszObjId);
5646         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5647          info->Content.cbData);
5648         LocalFree(buf);
5649     }
5650     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5651      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5652      0, NULL, NULL, &size);
5653     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5654     SetLastError(0xdeadbeef);
5655     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5656      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5657      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5658     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5659      * I doubt an app depends on that.
5660      */
5661     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5662      GetLastError() == CRYPT_E_ASN1_CORRUPT),
5663      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5664      GetLastError());
5665     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5666      intPKCSContentInfo, sizeof(intPKCSContentInfo),
5667      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5668     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5669     if (buf)
5670     {
5671         info = (CRYPT_CONTENT_INFO *)buf;
5672
5673         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5674          info->pszObjId);
5675         ok(info->Content.cbData == ints[0].encoded[1] + 2,
5676          "Unexpected size %d\n", info->Content.cbData);
5677         ok(!memcmp(info->Content.pbData, ints[0].encoded,
5678          info->Content.cbData), "Unexpected value\n");
5679         LocalFree(buf);
5680     }
5681     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5682      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5683      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5684     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5685     if (buf)
5686     {
5687         info = (CRYPT_CONTENT_INFO *)buf;
5688
5689         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5690          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5691         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5692          info->Content.cbData);
5693         LocalFree(buf);
5694     }
5695 }
5696
5697 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5698  0x00 };
5699 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5700  0x01 };
5701 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5702  0x02,0x01,0x01 };
5703
5704 static void test_encodePKCSAttribute(DWORD dwEncoding)
5705 {
5706     CRYPT_ATTRIBUTE attr = { 0 };
5707     BOOL ret;
5708     LPBYTE buf = NULL;
5709     DWORD size = 0;
5710     CRYPT_ATTR_BLOB blob;
5711     char oid[] = "1.2.3";
5712
5713     if (0)
5714     {
5715         /* Crashes on win9x */
5716         SetLastError(0xdeadbeef);
5717         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5718          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5719         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5720          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5721     }
5722     SetLastError(0xdeadbeef);
5723     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5724      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5725     ok(!ret && GetLastError() == E_INVALIDARG,
5726      "Expected E_INVALIDARG, got %x\n", GetLastError());
5727     attr.pszObjId = oid;
5728     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5729      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5730     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5731     if (buf)
5732     {
5733         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5734         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5735         LocalFree(buf);
5736     }
5737     blob.cbData = sizeof(bogusDER);
5738     blob.pbData = bogusDER;
5739     attr.cValue = 1;
5740     attr.rgValue = &blob;
5741     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5742      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5743     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5744     if (buf)
5745     {
5746         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5747         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5748         LocalFree(buf);
5749     }
5750     blob.pbData = (BYTE *)ints[0].encoded;
5751     blob.cbData = ints[0].encoded[1] + 2;
5752     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5753      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5754     if (buf)
5755     {
5756         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
5757         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
5758         LocalFree(buf);
5759     }
5760 }
5761
5762 static void test_decodePKCSAttribute(DWORD dwEncoding)
5763 {
5764     BOOL ret;
5765     LPBYTE buf = NULL;
5766     DWORD size = 0;
5767     CRYPT_ATTRIBUTE *attr;
5768
5769     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5770      emptyPKCSAttr, sizeof(emptyPKCSAttr),
5771      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5772     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5773     if (buf)
5774     {
5775         attr = (CRYPT_ATTRIBUTE *)buf;
5776
5777         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5778          attr->pszObjId);
5779         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
5780         LocalFree(buf);
5781     }
5782     SetLastError(0xdeadbeef);
5783     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5784      bogusPKCSAttr, sizeof(bogusPKCSAttr),
5785      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5786     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5787      * I doubt an app depends on that.
5788      */
5789     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5790      GetLastError() == CRYPT_E_ASN1_CORRUPT),
5791      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5792      GetLastError());
5793     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5794      intPKCSAttr, sizeof(intPKCSAttr),
5795      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5796     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5797     if (buf)
5798     {
5799         attr = (CRYPT_ATTRIBUTE *)buf;
5800
5801         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5802          attr->pszObjId);
5803         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
5804         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
5805          "Unexpected size %d\n", attr->rgValue[0].cbData);
5806         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
5807          attr->rgValue[0].cbData), "Unexpected value\n");
5808         LocalFree(buf);
5809     }
5810 }
5811
5812 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
5813 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
5814  0x2a,0x03,0x31,0x00 };
5815 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
5816  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
5817
5818 static void test_encodePKCSAttributes(DWORD dwEncoding)
5819 {
5820     CRYPT_ATTRIBUTES attributes = { 0 };
5821     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
5822     CRYPT_ATTR_BLOB blob;
5823     BOOL ret;
5824     LPBYTE buf = NULL;
5825     DWORD size = 0;
5826     char oid1[] = "1.2.3", oid2[] = "1.5.6";
5827
5828     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5829      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5830     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5831     if (buf)
5832     {
5833         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
5834         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
5835         LocalFree(buf);
5836     }
5837     attributes.cAttr = 1;
5838     attributes.rgAttr = attr;
5839     SetLastError(0xdeadbeef);
5840     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5841      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5842     ok(!ret && GetLastError() == E_INVALIDARG,
5843      "Expected E_INVALIDARG, got %x\n", GetLastError());
5844     attr[0].pszObjId = oid1;
5845     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5846      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5847     if (buf)
5848     {
5849         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
5850         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
5851         LocalFree(buf);
5852     }
5853     attr[1].pszObjId = oid2;
5854     attr[1].cValue = 1;
5855     attr[1].rgValue = &blob;
5856     blob.pbData = (BYTE *)ints[0].encoded;
5857     blob.cbData = ints[0].encoded[1] + 2;
5858     attributes.cAttr = 2;
5859     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5860      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5861     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5862     if (buf)
5863     {
5864         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
5865         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
5866         LocalFree(buf);
5867     }
5868 }
5869
5870 static void test_decodePKCSAttributes(DWORD dwEncoding)
5871 {
5872     BOOL ret;
5873     LPBYTE buf = NULL;
5874     DWORD size = 0;
5875     CRYPT_ATTRIBUTES *attributes;
5876
5877     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5878      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
5879      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5880     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5881     if (buf)
5882     {
5883         attributes = (CRYPT_ATTRIBUTES *)buf;
5884         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
5885          attributes->cAttr);
5886         LocalFree(buf);
5887     }
5888     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5889      singlePKCSAttributes, sizeof(singlePKCSAttributes),
5890      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5891     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5892     if (buf)
5893     {
5894         attributes = (CRYPT_ATTRIBUTES *)buf;
5895         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
5896          attributes->cAttr);
5897         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5898          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5899         ok(attributes->rgAttr[0].cValue == 0,
5900          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5901         LocalFree(buf);
5902     }
5903     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5904      doublePKCSAttributes, sizeof(doublePKCSAttributes),
5905      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5906     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5907     if (buf)
5908     {
5909         attributes = (CRYPT_ATTRIBUTES *)buf;
5910         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
5911          attributes->cAttr);
5912         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5913          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5914         ok(attributes->rgAttr[0].cValue == 0,
5915          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5916         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
5917          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
5918         ok(attributes->rgAttr[1].cValue == 1,
5919          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
5920         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
5921          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
5922         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
5923          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
5924         LocalFree(buf);
5925     }
5926 }
5927
5928 static const BYTE singleCapability[] = {
5929 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
5930 static const BYTE twoCapabilities[] = {
5931 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
5932 static const BYTE singleCapabilitywithNULL[] = {
5933 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5934
5935 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
5936 {
5937     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
5938     BOOL ret;
5939     LPBYTE buf = NULL;
5940     DWORD size = 0;
5941     CRYPT_SMIME_CAPABILITY capability[2];
5942     CRYPT_SMIME_CAPABILITIES capabilities;
5943
5944     /* An empty capabilities is allowed */
5945     capabilities.cCapability = 0;
5946     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5947      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5948     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5949     if (buf)
5950     {
5951         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5952         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5953         LocalFree(buf);
5954     }
5955     /* A non-empty capabilities with an empty capability (lacking an OID) is
5956      * not allowed
5957      */
5958     capability[0].pszObjId = NULL;
5959     capability[0].Parameters.cbData = 0;
5960     capabilities.cCapability = 1;
5961     capabilities.rgCapability = capability;
5962     SetLastError(0xdeadbeef);
5963     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5964      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5965     ok(!ret && GetLastError() == E_INVALIDARG,
5966      "expected E_INVALIDARG, got %08x\n", GetLastError());
5967     capability[0].pszObjId = oid1;
5968     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5969      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5970     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5971     if (buf)
5972     {
5973         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
5974         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
5975         LocalFree(buf);
5976     }
5977     capability[1].pszObjId = oid2;
5978     capability[1].Parameters.cbData = 0;
5979     capabilities.cCapability = 2;
5980     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5981      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5982     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5983     if (buf)
5984     {
5985         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
5986         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
5987         LocalFree(buf);
5988     }
5989 }
5990
5991 static void compareSMimeCapabilities(LPCSTR header,
5992  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
5993 {
5994     DWORD i;
5995
5996     ok(got->cCapability == expected->cCapability,
5997      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
5998      got->cCapability);
5999     for (i = 0; i < expected->cCapability; i++)
6000     {
6001         ok(!strcmp(expected->rgCapability[i].pszObjId,
6002          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6003          header, i, expected->rgCapability[i].pszObjId,
6004          got->rgCapability[i].pszObjId);
6005         ok(expected->rgCapability[i].Parameters.cbData ==
6006          got->rgCapability[i].Parameters.cbData,
6007          "%s[%d]: expected %d bytes, got %d\n", header, i,
6008          expected->rgCapability[i].Parameters.cbData,
6009          got->rgCapability[i].Parameters.cbData);
6010         if (expected->rgCapability[i].Parameters.cbData)
6011             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6012              got->rgCapability[i].Parameters.pbData,
6013              expected->rgCapability[i].Parameters.cbData),
6014              "%s[%d]: unexpected value\n", header, i);
6015     }
6016 }
6017
6018 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6019 {
6020     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6021     BOOL ret;
6022     DWORD size = 0;
6023     CRYPT_SMIME_CAPABILITY capability[2];
6024     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6025
6026     SetLastError(0xdeadbeef);
6027     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6028      emptySequence, sizeof(emptySequence),
6029      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&ptr, &size);
6030     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6031     if (ret)
6032     {
6033         capabilities.cCapability = 0;
6034         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6035         LocalFree(ptr);
6036     }
6037     SetLastError(0xdeadbeef);
6038     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6039      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6040      (BYTE *)&ptr, &size);
6041     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6042     if (ret)
6043     {
6044         capability[0].pszObjId = oid1;
6045         capability[0].Parameters.cbData = 0;
6046         capabilities.cCapability = 1;
6047         capabilities.rgCapability = capability;
6048         compareSMimeCapabilities("single capability", &capabilities, ptr);
6049         LocalFree(ptr);
6050     }
6051     SetLastError(0xdeadbeef);
6052     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6053      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6054      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&ptr, &size);
6055     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6056     if (ret)
6057     {
6058         BYTE NULLparam[] = {0x05, 0x00};
6059         capability[0].pszObjId = oid1;
6060         capability[0].Parameters.cbData = 2;
6061         capability[0].Parameters.pbData = NULLparam;
6062         capabilities.cCapability = 1;
6063         capabilities.rgCapability = capability;
6064         compareSMimeCapabilities("single capability with NULL", &capabilities,
6065          ptr);
6066         LocalFree(ptr);
6067     }
6068     SetLastError(0xdeadbeef);
6069     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6070     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6071     (BYTE *)&ptr, &size);
6072     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6073     if (ret)
6074     {
6075         capability[0].Parameters.cbData = 0;
6076         capability[1].pszObjId = oid2;
6077         capability[1].Parameters.cbData = 0;
6078         capabilities.cCapability = 2;
6079         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6080         LocalFree(ptr);
6081     }
6082 }
6083
6084 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6085  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6086  0x67 };
6087 static const BYTE minimalPKCSSigner[] = {
6088  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6089  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6090  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6091 static const BYTE PKCSSignerWithSerial[] = {
6092  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6093  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6094  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6095  0x00 };
6096 static const BYTE PKCSSignerWithHashAlgo[] = {
6097  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6098  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6099  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6100  0x00,0x04,0x00 };
6101 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6102  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6103  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6104  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6105  0x06,0x05,0x00,0x04,0x00 };
6106 static const BYTE PKCSSignerWithHash[] = {
6107  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6108  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6109  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6110  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6111  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6112 static const BYTE PKCSSignerWithAuthAttr[] = {
6113 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6114 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6115 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6116 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6117 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6118 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6119 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6120
6121 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6122 {
6123     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6124     BOOL ret;
6125     LPBYTE buf = NULL;
6126     DWORD size = 0;
6127     CMSG_SIGNER_INFO info = { 0 };
6128     char oid_common_name[] = szOID_COMMON_NAME;
6129     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6130      (LPBYTE)encodedCommonName };
6131     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6132
6133     SetLastError(0xdeadbeef);
6134     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6135      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6136     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6137     {
6138         skip("no PKCS7_SIGNER_INFO encode support\n");
6139         return;
6140     }
6141     ok(!ret && GetLastError() == E_INVALIDARG,
6142      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6143     /* To be encoded, a signer must have an issuer at least, and the encoding
6144      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6145      * see decoding tests.)
6146      */
6147     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6148     info.Issuer.pbData = encodedCommonNameNoNull;
6149     SetLastError(0xdeadbeef);
6150     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6151      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6152     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6153         ok(!ret && GetLastError() == E_INVALIDARG,
6154          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6155     else
6156     {
6157         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6158         if (buf)
6159         {
6160             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6161             if (size == sizeof(minimalPKCSSigner))
6162                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6163             else
6164                 ok(0, "Unexpected value\n");
6165             LocalFree(buf);
6166         }
6167     }
6168     info.SerialNumber.cbData = sizeof(serialNum);
6169     info.SerialNumber.pbData = (BYTE *)serialNum;
6170     SetLastError(0xdeadbeef);
6171     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6172      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6173     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6174         ok(!ret && GetLastError() == E_INVALIDARG,
6175          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6176     else
6177     {
6178         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6179         if (buf)
6180         {
6181             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6182              size);
6183             if (size == sizeof(PKCSSignerWithSerial))
6184                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6185                  "Unexpected value\n");
6186             else
6187                 ok(0, "Unexpected value\n");
6188             LocalFree(buf);
6189         }
6190     }
6191     info.HashAlgorithm.pszObjId = oid1;
6192     SetLastError(0xdeadbeef);
6193     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6194      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6195     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6196         ok(!ret && GetLastError() == E_INVALIDARG,
6197          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6198     else
6199     {
6200         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6201         if (buf)
6202         {
6203             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6204              size);
6205             if (size == sizeof(PKCSSignerWithHashAlgo))
6206                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6207                  "Unexpected value\n");
6208             else
6209                 ok(0, "Unexpected value\n");
6210             LocalFree(buf);
6211         }
6212     }
6213     info.HashEncryptionAlgorithm.pszObjId = oid2;
6214     SetLastError(0xdeadbeef);
6215     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6216      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6217     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6218         ok(!ret && GetLastError() == E_INVALIDARG,
6219          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6220     else
6221     {
6222         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6223         if (buf)
6224         {
6225             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6226              "Unexpected size %d\n", size);
6227             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6228                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6229                  "Unexpected value\n");
6230             else
6231                 ok(0, "Unexpected value\n");
6232             LocalFree(buf);
6233         }
6234     }
6235     info.EncryptedHash.cbData = sizeof(hash);
6236     info.EncryptedHash.pbData = (BYTE *)hash;
6237     SetLastError(0xdeadbeef);
6238     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6239      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6240     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6241         ok(!ret && GetLastError() == E_INVALIDARG,
6242          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6243     else
6244     {
6245         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6246         if (buf)
6247         {
6248             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6249              size);
6250             if (size == sizeof(PKCSSignerWithHash))
6251                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6252                  "Unexpected value\n");
6253             else
6254                 ok(0, "Unexpected value\n");
6255             LocalFree(buf);
6256         }
6257     }
6258     info.AuthAttrs.cAttr = 1;
6259     info.AuthAttrs.rgAttr = &attr;
6260     SetLastError(0xdeadbeef);
6261     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6262      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6263     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6264         ok(!ret && GetLastError() == E_INVALIDARG,
6265          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6266     else
6267     {
6268         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6269         if (buf)
6270         {
6271             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6272              size);
6273             if (size == sizeof(PKCSSignerWithAuthAttr))
6274                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6275                  "Unexpected value\n");
6276             else
6277                 ok(0, "Unexpected value\n");
6278             LocalFree(buf);
6279         }
6280     }
6281 }
6282
6283 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6284 {
6285     BOOL ret;
6286     LPBYTE buf = NULL;
6287     DWORD size = 0;
6288     CMSG_SIGNER_INFO *info;
6289
6290     /* A PKCS signer can't be decoded without a serial number. */
6291     SetLastError(0xdeadbeef);
6292     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6293      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6294      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6295     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
6296      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6297     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6298      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6299      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6300     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6301     if (buf)
6302     {
6303         info = (CMSG_SIGNER_INFO *)buf;
6304         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6305          info->dwVersion);
6306         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6307          "Unexpected size %d\n", info->Issuer.cbData);
6308         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6309          info->Issuer.cbData), "Unexpected value\n");
6310         ok(info->SerialNumber.cbData == sizeof(serialNum),
6311          "Unexpected size %d\n", info->SerialNumber.cbData);
6312         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6313          "Unexpected value\n");
6314         LocalFree(buf);
6315     }
6316     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6317      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6318      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6319     if (buf)
6320     {
6321         info = (CMSG_SIGNER_INFO *)buf;
6322         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6323          info->dwVersion);
6324         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6325          "Unexpected size %d\n", info->Issuer.cbData);
6326         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6327          info->Issuer.cbData), "Unexpected value\n");
6328         ok(info->SerialNumber.cbData == sizeof(serialNum),
6329          "Unexpected size %d\n", info->SerialNumber.cbData);
6330         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6331          "Unexpected value\n");
6332         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6333          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6334         LocalFree(buf);
6335     }
6336     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6337      PKCSSignerWithHashAndEncryptionAlgo,
6338      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6339      NULL, (BYTE *)&buf, &size);
6340     if (buf)
6341     {
6342         info = (CMSG_SIGNER_INFO *)buf;
6343         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6344          info->dwVersion);
6345         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6346          "Unexpected size %d\n", info->Issuer.cbData);
6347         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6348          info->Issuer.cbData), "Unexpected value\n");
6349         ok(info->SerialNumber.cbData == sizeof(serialNum),
6350          "Unexpected size %d\n", info->SerialNumber.cbData);
6351         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6352          "Unexpected value\n");
6353         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6354          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6355         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6356          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6357         LocalFree(buf);
6358     }
6359     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6360      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6361      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6362     if (buf)
6363     {
6364         info = (CMSG_SIGNER_INFO *)buf;
6365         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6366          info->dwVersion);
6367         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6368          "Unexpected size %d\n", info->Issuer.cbData);
6369         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6370          info->Issuer.cbData), "Unexpected value\n");
6371         ok(info->SerialNumber.cbData == sizeof(serialNum),
6372          "Unexpected size %d\n", info->SerialNumber.cbData);
6373         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6374          "Unexpected value\n");
6375         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6376          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6377         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6378          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6379         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6380          info->EncryptedHash.cbData);
6381         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6382          "Unexpected value\n");
6383         LocalFree(buf);
6384     }
6385     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6386      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6387      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6388     if (buf)
6389     {
6390         info = (CMSG_SIGNER_INFO *)buf;
6391         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6392          info->AuthAttrs.cAttr);
6393         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6394          "Expected %s, got %s\n", szOID_COMMON_NAME,
6395          info->AuthAttrs.rgAttr[0].pszObjId);
6396         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6397          info->AuthAttrs.rgAttr[0].cValue);
6398         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6399          sizeof(encodedCommonName), "Unexpected size %d\n",
6400          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6401         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6402          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6403         LocalFree(buf);
6404     }
6405 }
6406
6407 static const BYTE CMSSignerWithKeyId[] = {
6408 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6409 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6410
6411 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6412 {
6413     BOOL ret;
6414     LPBYTE buf = NULL;
6415     DWORD size = 0;
6416     CMSG_CMS_SIGNER_INFO info = { 0 };
6417     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6418
6419     SetLastError(0xdeadbeef);
6420     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6421      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6422     ok(!ret && GetLastError() == E_INVALIDARG,
6423      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6424     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6425     SetLastError(0xdeadbeef);
6426     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6427      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6428     ok(!ret, "Expected failure, got %d\n", ret);
6429     ok(GetLastError() == E_INVALIDARG,
6430        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6431     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6432      * be a key id or a issuer serial number with at least the issuer set, and
6433      * the encoding must include PKCS_7_ASN_ENCODING.
6434      * (That isn't enough to be decoded, see decoding tests.)
6435      */
6436     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6437      sizeof(encodedCommonNameNoNull);
6438     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6439     SetLastError(0xdeadbeef);
6440     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6441      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6442     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6443         ok(!ret && GetLastError() == E_INVALIDARG,
6444          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6445     else
6446     {
6447         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6448         if (buf)
6449         {
6450             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6451             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6452             LocalFree(buf);
6453         }
6454     }
6455     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6456     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6457     SetLastError(0xdeadbeef);
6458     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6459      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6460     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6461         ok(!ret && GetLastError() == E_INVALIDARG,
6462          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6463     else
6464     {
6465         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6466         if (buf)
6467         {
6468             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6469              size);
6470             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6471             LocalFree(buf);
6472         }
6473     }
6474     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6475     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6476     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6477     SetLastError(0xdeadbeef);
6478     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6479      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6480     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6481         ok(!ret && GetLastError() == E_INVALIDARG,
6482          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6483     else
6484     {
6485         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6486         if (buf)
6487         {
6488             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6489              size);
6490             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6491             LocalFree(buf);
6492         }
6493     }
6494     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6495      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6496      * (see RFC 3852, section 5.3.)
6497      */
6498     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6499     U(info.SignerId).HashId.cbData = sizeof(hash);
6500     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6501     SetLastError(0xdeadbeef);
6502     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6503      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6504     ok(!ret && GetLastError() == E_INVALIDARG,
6505      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6506     /* Now with a hash algo */
6507     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6508     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6509      sizeof(encodedCommonNameNoNull);
6510     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6511     info.HashAlgorithm.pszObjId = oid1;
6512     SetLastError(0xdeadbeef);
6513     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6514      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6515     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6516         ok(!ret && GetLastError() == E_INVALIDARG,
6517          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6518     else
6519     {
6520         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6521         if (buf)
6522         {
6523             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6524              size);
6525             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6526              "Unexpected value\n");
6527             LocalFree(buf);
6528         }
6529     }
6530     info.HashEncryptionAlgorithm.pszObjId = oid2;
6531     SetLastError(0xdeadbeef);
6532     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6533      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6534     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6535         ok(!ret && GetLastError() == E_INVALIDARG,
6536          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6537     else
6538     {
6539         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6540         if (buf)
6541         {
6542             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6543              "Unexpected size %d\n", size);
6544             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6545              "Unexpected value\n");
6546             LocalFree(buf);
6547         }
6548     }
6549     info.EncryptedHash.cbData = sizeof(hash);
6550     info.EncryptedHash.pbData = (BYTE *)hash;
6551     SetLastError(0xdeadbeef);
6552     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6553      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6554     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6555         ok(!ret && GetLastError() == E_INVALIDARG,
6556          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6557     else
6558     {
6559         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6560         if (buf)
6561         {
6562             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6563              size);
6564             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6565             LocalFree(buf);
6566         }
6567     }
6568 }
6569
6570 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6571 {
6572     BOOL ret;
6573     LPBYTE buf = NULL;
6574     DWORD size = 0;
6575     CMSG_CMS_SIGNER_INFO *info;
6576     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6577
6578     /* A CMS signer can't be decoded without a serial number. */
6579     SetLastError(0xdeadbeef);
6580     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6581      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6582      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6583     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
6584      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6585     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6586      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6587      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6588     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6589     if (buf)
6590     {
6591         info = (CMSG_CMS_SIGNER_INFO *)buf;
6592         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6593          info->dwVersion);
6594         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6595          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6596          info->SignerId.dwIdChoice);
6597         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6598          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6599          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6600         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6601          encodedCommonNameNoNull,
6602          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6603          "Unexpected value\n");
6604         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6605          sizeof(serialNum), "Unexpected size %d\n",
6606          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6607         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6608          serialNum, sizeof(serialNum)), "Unexpected value\n");
6609         LocalFree(buf);
6610     }
6611     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6612      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6613      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6614     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6615     if (buf)
6616     {
6617         info = (CMSG_CMS_SIGNER_INFO *)buf;
6618         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6619          info->dwVersion);
6620         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6621          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6622          info->SignerId.dwIdChoice);
6623         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6624          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6625          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6626         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6627          encodedCommonNameNoNull,
6628          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6629          "Unexpected value\n");
6630         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6631          sizeof(serialNum), "Unexpected size %d\n",
6632          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6633         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6634          serialNum, sizeof(serialNum)), "Unexpected value\n");
6635         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6636          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6637         LocalFree(buf);
6638     }
6639     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6640      PKCSSignerWithHashAndEncryptionAlgo,
6641      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6642      NULL, (BYTE *)&buf, &size);
6643     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6644     if (buf)
6645     {
6646         info = (CMSG_CMS_SIGNER_INFO *)buf;
6647         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6648          info->dwVersion);
6649         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6650          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6651          info->SignerId.dwIdChoice);
6652         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6653          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6654          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6655         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6656          encodedCommonNameNoNull,
6657          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6658          "Unexpected value\n");
6659         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6660          sizeof(serialNum), "Unexpected size %d\n",
6661          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6662         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6663          serialNum, sizeof(serialNum)), "Unexpected value\n");
6664         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6665          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6666         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6667          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6668         LocalFree(buf);
6669     }
6670     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6671      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6672      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6673     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6674     if (buf)
6675     {
6676         info = (CMSG_CMS_SIGNER_INFO *)buf;
6677         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6678          info->dwVersion);
6679         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6680          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6681          info->SignerId.dwIdChoice);
6682         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6683          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6684          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6685         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6686          encodedCommonNameNoNull,
6687          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6688          "Unexpected value\n");
6689         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6690          sizeof(serialNum), "Unexpected size %d\n",
6691          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6692         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6693          serialNum, sizeof(serialNum)), "Unexpected value\n");
6694         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6695          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6696         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6697          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6698         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6699          info->EncryptedHash.cbData);
6700         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6701          "Unexpected value\n");
6702         LocalFree(buf);
6703     }
6704     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6705      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6706      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6707     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6708     if (buf)
6709     {
6710         info = (CMSG_CMS_SIGNER_INFO *)buf;
6711         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6712          info->dwVersion);
6713         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6714          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6715          info->SignerId.dwIdChoice);
6716         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6717          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6718         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
6719          "Unexpected value\n");
6720         LocalFree(buf);
6721     }
6722 }
6723
6724 static BYTE emptyDNSPermittedConstraints[] = {
6725 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6726 static BYTE emptyDNSExcludedConstraints[] = {
6727 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
6728 static BYTE DNSExcludedConstraints[] = {
6729 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
6730 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6731 static BYTE permittedAndExcludedConstraints[] = {
6732 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6733 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
6734 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6735 static BYTE permittedAndExcludedWithMinConstraints[] = {
6736 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6737 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
6738 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6739 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
6740 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6741 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
6742 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6743
6744 static void test_encodeNameConstraints(DWORD dwEncoding)
6745 {
6746     BOOL ret;
6747     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
6748     CERT_GENERAL_SUBTREE permitted = { { 0 } };
6749     CERT_GENERAL_SUBTREE excluded = { { 0 } };
6750     LPBYTE buf;
6751     DWORD size;
6752
6753     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6754      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6755     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6756     {
6757         skip("no X509_NAME_CONSTRAINTS encode support\n");
6758         return;
6759     }
6760     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6761     if (ret)
6762     {
6763         ok(size == sizeof(emptySequence), "Unexpected size\n");
6764         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
6765         LocalFree(buf);
6766     }
6767     constraints.cPermittedSubtree = 1;
6768     constraints.rgPermittedSubtree = &permitted;
6769     SetLastError(0xdeadbeef);
6770     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6771      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6772     ok(!ret && GetLastError() == E_INVALIDARG,
6773      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6774     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6775     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6776      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6777     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6778     if (ret)
6779     {
6780         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
6781         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
6782          "Unexpected value\n");
6783         LocalFree(buf);
6784     }
6785     constraints.cPermittedSubtree = 0;
6786     constraints.cExcludedSubtree = 1;
6787     constraints.rgExcludedSubtree = &excluded;
6788     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6789     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6790      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6791     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6792     if (ret)
6793     {
6794         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
6795         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
6796          "Unexpected value\n");
6797         LocalFree(buf);
6798     }
6799     U(excluded.Base).pwszURL = (LPWSTR)url;
6800     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6801      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6802     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6803     if (ret)
6804     {
6805         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
6806         ok(!memcmp(buf, DNSExcludedConstraints, size),
6807          "Unexpected value\n");
6808         LocalFree(buf);
6809     }
6810     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
6811     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6812     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6813     constraints.cPermittedSubtree = 1;
6814     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6815      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6816     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6817     if (ret)
6818     {
6819         ok(size == sizeof(permittedAndExcludedConstraints),
6820          "Unexpected size\n");
6821         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
6822          "Unexpected value\n");
6823         LocalFree(buf);
6824     }
6825     permitted.dwMinimum = 5;
6826     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6827      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6828     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6829     if (ret)
6830     {
6831         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
6832          "Unexpected size\n");
6833         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
6834          "Unexpected value\n");
6835         LocalFree(buf);
6836     }
6837     permitted.fMaximum = TRUE;
6838     permitted.dwMaximum = 3;
6839     SetLastError(0xdeadbeef);
6840     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6841      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6842     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6843     if (ret)
6844     {
6845         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
6846          "Unexpected size\n");
6847         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
6848          "Unexpected value\n");
6849         LocalFree(buf);
6850     }
6851 }
6852
6853 struct EncodedNameConstraints
6854 {
6855     CRYPT_DATA_BLOB            encoded;
6856     CERT_NAME_CONSTRAINTS_INFO constraints;
6857 };
6858
6859 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
6860  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6861 static CERT_GENERAL_SUBTREE DNSSubtree = {
6862  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6863 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
6864  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
6865 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
6866  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
6867 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
6868  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
6869
6870 struct EncodedNameConstraints encodedNameConstraints[] = {
6871  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
6872  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
6873    { 1, &emptyDNSSubtree, 0, NULL } },
6874  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
6875    { 0, NULL, 1, &emptyDNSSubtree } },
6876  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
6877    { 0, NULL, 1, &DNSSubtree } },
6878  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
6879    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
6880  { { sizeof(permittedAndExcludedWithMinConstraints),
6881      permittedAndExcludedWithMinConstraints },
6882    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
6883  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
6884      permittedAndExcludedWithMinMaxConstraints },
6885    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
6886 };
6887
6888 static void test_decodeNameConstraints(DWORD dwEncoding)
6889 {
6890     BOOL ret;
6891     DWORD i;
6892     CERT_NAME_CONSTRAINTS_INFO *constraints;
6893
6894     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
6895     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6896     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6897     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6898     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6899     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6900     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6901     for (i = 0;
6902      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
6903      i++)
6904     {
6905         DWORD size;
6906
6907         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
6908          encodedNameConstraints[i].encoded.pbData,
6909          encodedNameConstraints[i].encoded.cbData,
6910          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
6911         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6912         {
6913             skip("no X509_NAME_CONSTRAINTS decode support\n");
6914             return;
6915         }
6916         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
6917         if (ret)
6918         {
6919             DWORD j;
6920
6921             if (constraints->cPermittedSubtree !=
6922              encodedNameConstraints[i].constraints.cPermittedSubtree)
6923                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
6924                  encodedNameConstraints[i].constraints.cPermittedSubtree,
6925                  constraints->cPermittedSubtree);
6926             if (constraints->cPermittedSubtree ==
6927              encodedNameConstraints[i].constraints.cPermittedSubtree)
6928             {
6929                 for (j = 0; j < constraints->cPermittedSubtree; j++)
6930                 {
6931                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
6932                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
6933                 }
6934             }
6935             if (constraints->cExcludedSubtree !=
6936              encodedNameConstraints[i].constraints.cExcludedSubtree)
6937                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
6938                  encodedNameConstraints[i].constraints.cExcludedSubtree,
6939                  constraints->cExcludedSubtree);
6940             if (constraints->cExcludedSubtree ==
6941              encodedNameConstraints[i].constraints.cExcludedSubtree)
6942             {
6943                 for (j = 0; j < constraints->cExcludedSubtree; j++)
6944                 {
6945                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
6946                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
6947                 }
6948             }
6949             LocalFree(constraints);
6950         }
6951     }
6952 }
6953
6954 /* Free *pInfo with HeapFree */
6955 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
6956 {
6957     BOOL ret;
6958     DWORD size = 0;
6959     HCRYPTKEY key;
6960
6961     /* This crashes
6962     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
6963      */
6964     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
6965     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
6966      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
6967     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
6968      &size);
6969     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
6970      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
6971     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
6972      NULL, &size);
6973     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
6974      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
6975     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
6976      0, NULL, NULL, &size);
6977     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
6978      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
6979     /* Test with no key */
6980     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
6981      0, NULL, NULL, &size);
6982     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
6983      GetLastError());
6984     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
6985     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
6986     if (ret)
6987     {
6988         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
6989          NULL, 0, NULL, NULL, &size);
6990         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
6991         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
6992         if (*pInfo)
6993         {
6994             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
6995              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
6996             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
6997              GetLastError());
6998             if (ret)
6999             {
7000                 /* By default (we passed NULL as the OID) the OID is
7001                  * szOID_RSA_RSA.
7002                  */
7003                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7004                  "Expected %s, got %s\n", szOID_RSA_RSA,
7005                  (*pInfo)->Algorithm.pszObjId);
7006             }
7007         }
7008     }
7009     CryptDestroyKey(key);
7010 }
7011
7012 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7013  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7014  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7015  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7016  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7017  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7018  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7019  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7020  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7021  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7022  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7023  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7024  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7025  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7026  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7027  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7028  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7029  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7030  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7031  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7032  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7033  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7034  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7035  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7036  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7037
7038 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7039 {
7040     BOOL ret;
7041     HCRYPTKEY key;
7042     PCCERT_CONTEXT context;
7043     DWORD dwSize;
7044     ALG_ID ai;
7045
7046     /* These crash
7047     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7048     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7049     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7050     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7051      NULL);
7052      */
7053     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7054     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7055      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7056     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7057     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7058      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7059     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7060      &key);
7061     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7062      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7063
7064     /* Export key with standard algorithm (CALG_RSA_KEYX) */
7065     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7066      &key);
7067     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7068
7069     dwSize = sizeof(ai);
7070     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7071     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7072     if(ret)
7073     {
7074       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7075       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7076     }
7077
7078     CryptDestroyKey(key);
7079
7080     /* Repeat with forced algorithm */
7081     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7082      &key);
7083     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7084
7085     dwSize = sizeof(ai);
7086     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7087     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7088     if(ret)
7089     {
7090       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7091       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7092     }
7093
7094     CryptDestroyKey(key);
7095
7096     /* Test importing a public key from a certificate context */
7097     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7098      sizeof(expiredCert));
7099     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7100      GetLastError());
7101     if (context)
7102     {
7103         ok(!strcmp(szOID_RSA_RSA,
7104          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7105          "Expected %s, got %s\n", szOID_RSA_RSA,
7106          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7107         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7108          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7109         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7110         CryptDestroyKey(key);
7111         CertFreeCertificateContext(context);
7112     }
7113 }
7114
7115 static const char cspName[] = "WineCryptTemp";
7116
7117 static void testPortPublicKeyInfo(void)
7118 {
7119     HCRYPTPROV csp;
7120     BOOL ret;
7121     PCERT_PUBLIC_KEY_INFO info = NULL;
7122
7123     /* Just in case a previous run failed, delete this thing */
7124     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7125      CRYPT_DELETEKEYSET);
7126     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7127      CRYPT_NEWKEYSET);
7128
7129     testExportPublicKey(csp, &info);
7130     testImportPublicKey(csp, info);
7131
7132     HeapFree(GetProcessHeap(), 0, info);
7133     CryptReleaseContext(csp, 0);
7134     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7135      CRYPT_DELETEKEYSET);
7136 }
7137
7138 START_TEST(encode)
7139 {
7140     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7141      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7142     HMODULE hCrypt32;
7143     DWORD i;
7144
7145     hCrypt32 = GetModuleHandleA("crypt32.dll");
7146     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7147     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7148     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7149     {
7150         skip("CryptDecodeObjectEx() is not available\n");
7151         return;
7152     }
7153
7154     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7155     {
7156         test_encodeInt(encodings[i]);
7157         test_decodeInt(encodings[i]);
7158         test_encodeEnumerated(encodings[i]);
7159         test_decodeEnumerated(encodings[i]);
7160         test_encodeFiletime(encodings[i]);
7161         test_decodeFiletime(encodings[i]);
7162         test_encodeName(encodings[i]);
7163         test_decodeName(encodings[i]);
7164         test_encodeUnicodeName(encodings[i]);
7165         test_decodeUnicodeName(encodings[i]);
7166         test_encodeNameValue(encodings[i]);
7167         test_decodeNameValue(encodings[i]);
7168         test_encodeUnicodeNameValue(encodings[i]);
7169         test_decodeUnicodeNameValue(encodings[i]);
7170         test_encodeAltName(encodings[i]);
7171         test_decodeAltName(encodings[i]);
7172         test_encodeOctets(encodings[i]);
7173         test_decodeOctets(encodings[i]);
7174         test_encodeBits(encodings[i]);
7175         test_decodeBits(encodings[i]);
7176         test_encodeBasicConstraints(encodings[i]);
7177         test_decodeBasicConstraints(encodings[i]);
7178         test_encodeRsaPublicKey(encodings[i]);
7179         test_decodeRsaPublicKey(encodings[i]);
7180         test_encodeSequenceOfAny(encodings[i]);
7181         test_decodeSequenceOfAny(encodings[i]);
7182         test_encodeExtensions(encodings[i]);
7183         test_decodeExtensions(encodings[i]);
7184         test_encodePublicKeyInfo(encodings[i]);
7185         test_decodePublicKeyInfo(encodings[i]);
7186         test_encodeCertToBeSigned(encodings[i]);
7187         test_decodeCertToBeSigned(encodings[i]);
7188         test_encodeCert(encodings[i]);
7189         test_decodeCert(encodings[i]);
7190         test_encodeCRLDistPoints(encodings[i]);
7191         test_decodeCRLDistPoints(encodings[i]);
7192         test_encodeCRLIssuingDistPoint(encodings[i]);
7193         test_decodeCRLIssuingDistPoint(encodings[i]);
7194         test_encodeCRLToBeSigned(encodings[i]);
7195         test_decodeCRLToBeSigned(encodings[i]);
7196         test_encodeEnhancedKeyUsage(encodings[i]);
7197         test_decodeEnhancedKeyUsage(encodings[i]);
7198         test_encodeAuthorityKeyId(encodings[i]);
7199         test_decodeAuthorityKeyId(encodings[i]);
7200         test_encodeAuthorityKeyId2(encodings[i]);
7201         test_decodeAuthorityKeyId2(encodings[i]);
7202         test_encodeAuthorityInfoAccess(encodings[i]);
7203         test_decodeAuthorityInfoAccess(encodings[i]);
7204         test_encodeCTL(encodings[i]);
7205         test_decodeCTL(encodings[i]);
7206         test_encodePKCSContentInfo(encodings[i]);
7207         test_decodePKCSContentInfo(encodings[i]);
7208         test_encodePKCSAttribute(encodings[i]);
7209         test_decodePKCSAttribute(encodings[i]);
7210         test_encodePKCSAttributes(encodings[i]);
7211         test_decodePKCSAttributes(encodings[i]);
7212         test_encodePKCSSMimeCapabilities(encodings[i]);
7213         test_decodePKCSSMimeCapabilities(encodings[i]);
7214         test_encodePKCSSignerInfo(encodings[i]);
7215         test_decodePKCSSignerInfo(encodings[i]);
7216         test_encodeCMSSignerInfo(encodings[i]);
7217         test_decodeCMSSignerInfo(encodings[i]);
7218         test_encodeNameConstraints(encodings[i]);
7219         test_decodeNameConstraints(encodings[i]);
7220     }
7221     testPortPublicKeyInfo();
7222 }